struct ib_update_work *work = (struct ib_update_work *)Context;
UNREFERENCED_PARAMETER(DeviceObject);
ib_cache_task(Context);
+ shutter_loose( &work->device->cache.x.work_thread );
IoFreeWorkItem(work->work_item);
kfree(Context);
}
event->event == IB_EVENT_PKEY_CHANGE ||
event->event == IB_EVENT_SM_CHANGE ||
event->event == IB_EVENT_CLIENT_REREGISTER) {
+
work = kmalloc(sizeof *work, GFP_ATOMIC);
if (work) {
- work->device = event->device;
- work->port_num = event->element.port_num;
+ PDEVICE_OBJECT pdo = to_mdev(handler->device)->dev->pdev->p_self_do;
+
+ // allocate work item
+ work->work_item = IoAllocateWorkItem(pdo);
+ if (work->work_item == NULL) {
+ //TODO: at least - print error. Need to return code, but the function is void
+ kfree( work );
+ return;
+ }
- { // schedule a work item to work
- // get PDO
- PDEVICE_OBJECT pdo = to_mdev(handler->device)->dev->pdev->p_self_do;
-
- // allocate work item
- work->work_item = IoAllocateWorkItem(pdo);
- if (work->work_item == NULL) {
- //TODO: at least - print error. Need to return code, but the function is void
- }
- else { // schedule the work
- IoQueueWorkItem(
- work->work_item,
- ib_work_item,
- DelayedWorkQueue,
- work
- );
- }
+ // check whether we are in shutdown
+ if (shutter_use( &event->device->cache.x.work_thread ) <= 0) {
+ kfree( work );
+ return;
}
+
+ // schedule the work
+ work->device = event->device;
+ work->port_num = event->element.port_num;
+ IoQueueWorkItem( work->work_item, ib_work_item, DelayedWorkQueue, work );
}
}
}
goto err;
}
+ shutter_init( &device->cache.x.work_thread );
+
for (p = 0; p <= end_port(device) - start_port(device); ++p) {
device->cache.pkey_cache[p] = NULL;
device->cache.gid_cache [p] = NULL;
kfree(device->cache.lmc_cache);
}
+// calling sequence:
+// EvtReleaseHardware ==> mlx4_ib_cleanup ==> mlx4_unregister_interface ==>
+// ==> mlx4_remove_device ==> mlx4_ib_remove ==> ib_unregister_device ==>
+// ==> ib_cache_cleanup
static void ib_cache_cleanup_one(struct ib_device *device)
{
int p;
ib_unregister_event_handler(&device->cache.event_handler);
- // TODO: how to do that ?
- // LINUX: flush_scheduled_work();
+ // instead of Linux flush_scheduled_work(): wait for them to quit
+ shutter_shut( &device->cache.x.work_thread );
for (p = 0; p <= end_port(device) - start_port(device); ++p) {
kfree(device->cache.pkey_cache[p]);
--- /dev/null
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: shutter.h 1611 2006-08-20 14:48:55Z sleybo $\r
+ */\r
+\r
+\r
+#pragma once\r
+\r
+\r
+// Define the max numbers of operations that can be simultaniously done\r
+#define MAX_OPERATIONS 0x10000000\r
+\r
+typedef struct _shutter_t {\r
+ long cnt;\r
+ KEVENT event;\r
+\r
+} shutter_t;\r
+\r
+static inline void shutter_init(shutter_t* p_shutter)\r
+{\r
+ p_shutter->cnt = 0;\r
+ KeInitializeEvent( &p_shutter->event, SynchronizationEvent, FALSE );\r
+}\r
+\r
+// if RC > 0, one can proceed\r
+static inline int shutter_use(shutter_t * p_shutter)\r
+{\r
+ long res = InterlockedIncrement( &p_shutter->cnt ); \r
+ ASSERT(res <= MAX_OPERATIONS);\r
+ if (res <= 0 ) \r
+ InterlockedDecrement( &p_shutter->cnt ); // The object is in shutdown\r
+ return res;\r
+}\r
+\r
+static inline void shutter_loose(shutter_t * p_shutter)\r
+{\r
+ long res = InterlockedDecrement( &p_shutter->cnt );\r
+ if (res == -MAX_OPERATIONS)\r
+ KeSetEvent( &p_shutter->event, 0, FALSE );\r
+}\r
+\r
+static inline void shutter_shut(shutter_t * p_shutter)\r
+{\r
+ long res;\r
+ // Mark the counter as locked\r
+ res = InterlockedExchangeAdd(&p_shutter->cnt, -MAX_OPERATIONS);\r
+ ASSERT(res >= 0);\r
+ if (res) \r
+ // We are now waiting for the object to reach -MAX_OPERATIONS\r
+ KeWaitForSingleObject( &p_shutter->event, Executive, KernelMode, FALSE, NULL );\r
+}\r
+\r