summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_sysfs.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2006-02-14 17:48:46 +0100
committer <jejb@mulgrave.il.steeleye.com>2006-02-14 18:15:11 +0100
commit65110b2168950a19cc78b5027ed18cb811fbdae8 (patch)
tree8cdf4fc26b707e0e6ba988fd56da118d3206dceb /drivers/scsi/scsi_sysfs.c
parent[PATCH] add scsi_execute_in_process_context() API (diff)
downloadlinux-65110b2168950a19cc78b5027ed18cb811fbdae8.tar.xz
linux-65110b2168950a19cc78b5027ed18cb811fbdae8.zip
[SCSI] fix wrong context bugs in SCSI
There's a bug in releasing scsi_device where the release function actually frees the block queue. However, the block queue release calls flush_work(), which requires process context (the scsi_device structure may release from irq context). Update the release function to invoke via the execute_in_process_context() API. Also clean up the scsi_target structure releasing via this API. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_sysfs.c')
-rw-r--r--drivers/scsi/scsi_sysfs.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index a77b32deaf8f..902a5def8e62 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -217,8 +217,9 @@ static void scsi_device_cls_release(struct class_device *class_dev)
put_device(&sdev->sdev_gendev);
}
-static void scsi_device_dev_release(struct device *dev)
+static void scsi_device_dev_release_usercontext(void *data)
{
+ struct device *dev = data;
struct scsi_device *sdev;
struct device *parent;
struct scsi_target *starget;
@@ -237,6 +238,7 @@ static void scsi_device_dev_release(struct device *dev)
if (sdev->request_queue) {
sdev->request_queue->queuedata = NULL;
+ /* user context needed to free queue */
scsi_free_queue(sdev->request_queue);
/* temporary expedient, try to catch use of queue lock
* after free of sdev */
@@ -252,6 +254,11 @@ static void scsi_device_dev_release(struct device *dev)
put_device(parent);
}
+static void scsi_device_dev_release(struct device *dev)
+{
+ scsi_execute_in_process_context(scsi_device_dev_release_usercontext, dev);
+}
+
static struct class sdev_class = {
.name = "scsi_device",
.release = scsi_device_cls_release,