summaryrefslogtreecommitdiff
path: root/drivers/scsi/scsi_sysfs.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-02 11:14:30 -0600
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-02 13:08:00 -0600
commit751bf4d7865e4ced406be93b04c7436d866d3684 (patch)
treebb5d45ec9af0dc3cf22d3a21364c13f6ae2e5358 /drivers/scsi/scsi_sysfs.c
parentdc512814b5f8b7b80c74d6170b93a606ae4f36c5 (diff)
downloadkernel-common-751bf4d7865e4ced406be93b04c7436d866d3684.tar.gz
kernel-common-751bf4d7865e4ced406be93b04c7436d866d3684.tar.bz2
kernel-common-751bf4d7865e4ced406be93b04c7436d866d3684.zip
[SCSI] scsi_sysfs: restore prep_fn when ULD is removed
A recent bug report: http://bugzilla.kernel.org/show_bug.cgi?id=9674 Was caused because the ULDs now set their own prep functions, but don't necessarily reset the prep function back to the SCSI default when they are removed. This leads to panics if commands are sent to the device after the module is removed because the prep_fn is still pointing to the old module code. The fix for this is to implement a bus remove method that resets the prep_fn pointer correctly before calling the ULD specific driver remove method. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/scsi_sysfs.c')
-rw-r--r--drivers/scsi/scsi_sysfs.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index f374fdcb6815..00b386677392 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -373,12 +373,29 @@ static int scsi_bus_resume(struct device * dev)
return err;
}
+static int scsi_bus_remove(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+ struct scsi_device *sdev = to_scsi_device(dev);
+ int err = 0;
+
+ /* reset the prep_fn back to the default since the
+ * driver may have altered it and it's being removed */
+ blk_queue_prep_rq(sdev->request_queue, scsi_prep_fn);
+
+ if (drv && drv->remove)
+ err = drv->remove(dev);
+
+ return 0;
+}
+
struct bus_type scsi_bus_type = {
.name = "scsi",
.match = scsi_bus_match,
.uevent = scsi_bus_uevent,
.suspend = scsi_bus_suspend,
.resume = scsi_bus_resume,
+ .remove = scsi_bus_remove,
};
int scsi_sysfs_register(void)