IB/cm: Flush workqueue when removing device
authorSean Hefty <sean.hefty@intel.com>
Fri, 22 Feb 2008 18:40:45 +0000 (10:40 -0800)
committerRoland Dreier <rolandd@cisco.com>
Fri, 29 Feb 2008 21:27:52 +0000 (13:27 -0800)
When a CM MAD is received, it is queued to a CM workqueue for
processing.  The queued work item references the port and device on
which the MAD was received.  If that device is removed from the system
before the work item can execute, the work item will reference freed
memory.

To fix this, flush the workqueue after unregistering to receive MAD,
and before the device is be freed.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/core/cm.c

index b10ade92efedfedbc6b0519c82ea9c3858f94fd8..4df405157086f458aae293a837a83d0983556210 100644 (file)
@@ -3759,6 +3759,7 @@ static void cm_remove_one(struct ib_device *device)
                port = cm_dev->port[i-1];
                ib_modify_port(device, port->port_num, 0, &port_modify);
                ib_unregister_mad_agent(port->mad_agent);
+               flush_workqueue(cm.wq);
                cm_remove_port_fs(port);
        }
        kobject_put(&cm_dev->dev_obj);
@@ -3813,6 +3814,7 @@ static void __exit ib_cm_cleanup(void)
                cancel_delayed_work(&timewait_info->work.work);
        spin_unlock_irq(&cm.lock);
 
+       ib_unregister_client(&cm_client);
        destroy_workqueue(cm.wq);
 
        list_for_each_entry_safe(timewait_info, tmp, &cm.timewait_list, list) {
@@ -3820,7 +3822,6 @@ static void __exit ib_cm_cleanup(void)
                kfree(timewait_info);
        }
 
-       ib_unregister_client(&cm_client);
        class_unregister(&cm_class);
        idr_destroy(&cm.local_id_table);
 }