]> git.hungrycats.org Git - linux/commitdiff
Fix locking problems in scsi_report_bus_reset() causing aic7xxx to hang
authorJames Bottomley <jejb@raven.il.steeleye.com>
Mon, 24 Nov 2003 04:02:15 +0000 (22:02 -0600)
committerJames Bottomley <jejb@mulgrave.(none)>
Mon, 24 Nov 2003 04:02:15 +0000 (22:02 -0600)
All the users of this function in the SCSI tree call it with the host
lock held.  With the new list traversal code, it was trying to take
the lock again to traverse the list.

Fix it to use the unlocked version of list traversal and modify the
header comments to make it clear that the lock is expected to be held
on calling it.

drivers/scsi/scsi_error.c

index c33e6bcfa554e213a5bc3a15cb5a52e38891c23e..9458bb42cfe0e3d4ce80721dc819eb32b0fef5cc 100644 (file)
@@ -911,7 +911,9 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
 
        if (rtn == SUCCESS) {
                scsi_sleep(BUS_RESET_SETTLE_TIME);
+               spin_lock_irqsave(scmd->device->host->host_lock, flags);
                scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
+               spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
        }
 
        return rtn;
@@ -940,7 +942,9 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
 
        if (rtn == SUCCESS) {
                scsi_sleep(HOST_RESET_SETTLE_TIME);
+               spin_lock_irqsave(scmd->device->host->host_lock, flags);
                scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
+               spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
        }
 
        return rtn;
@@ -1608,7 +1612,7 @@ int scsi_error_handler(void *data)
  *
  * Returns:     Nothing
  *
- * Lock status: No locks are assumed held.
+ * Lock status: Host lock must be held.
  *
  * Notes:       This only needs to be called if the reset is one which
  *             originates from an unknown location.  Resets originated
@@ -1622,7 +1626,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
 {
        struct scsi_device *sdev;
 
-       shost_for_each_device(sdev, shost) {
+       __shost_for_each_device(sdev, shost) {
                if (channel == sdev->channel) {
                        sdev->was_reset = 1;
                        sdev->expecting_cc_ua = 1;
@@ -1642,7 +1646,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
  *
  * Returns:     Nothing
  *
- * Lock status: No locks are assumed held.
+ * Lock status: Host lock must be held
  *
  * Notes:       This only needs to be called if the reset is one which
  *             originates from an unknown location.  Resets originated
@@ -1656,7 +1660,7 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
 {
        struct scsi_device *sdev;
 
-       shost_for_each_device(sdev, shost) {
+       __shost_for_each_device(sdev, shost) {
                if (channel == sdev->channel &&
                    target == sdev->id) {
                        sdev->was_reset = 1;