Commit 383d0b65 authored by James Bottomley's avatar James Bottomley Committed by James Bottomley

Fix locking problems in scsi_report_bus_reset() causing aic7xxx to hang

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.
parent 9b22a8fb
...@@ -911,7 +911,9 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd) ...@@ -911,7 +911,9 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
if (rtn == SUCCESS) { if (rtn == SUCCESS) {
scsi_sleep(BUS_RESET_SETTLE_TIME); 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); scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
} }
return rtn; return rtn;
...@@ -940,7 +942,9 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd) ...@@ -940,7 +942,9 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
if (rtn == SUCCESS) { if (rtn == SUCCESS) {
scsi_sleep(HOST_RESET_SETTLE_TIME); 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); scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
} }
return rtn; return rtn;
...@@ -1608,7 +1612,7 @@ int scsi_error_handler(void *data) ...@@ -1608,7 +1612,7 @@ int scsi_error_handler(void *data)
* *
* Returns: Nothing * 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 * Notes: This only needs to be called if the reset is one which
* originates from an unknown location. Resets originated * originates from an unknown location. Resets originated
...@@ -1622,7 +1626,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) ...@@ -1622,7 +1626,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
shost_for_each_device(sdev, shost) { __shost_for_each_device(sdev, shost) {
if (channel == sdev->channel) { if (channel == sdev->channel) {
sdev->was_reset = 1; sdev->was_reset = 1;
sdev->expecting_cc_ua = 1; sdev->expecting_cc_ua = 1;
...@@ -1642,7 +1646,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) ...@@ -1642,7 +1646,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
* *
* Returns: Nothing * 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 * Notes: This only needs to be called if the reset is one which
* originates from an unknown location. Resets originated * originates from an unknown location. Resets originated
...@@ -1656,7 +1660,7 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target) ...@@ -1656,7 +1660,7 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
shost_for_each_device(sdev, shost) { __shost_for_each_device(sdev, shost) {
if (channel == sdev->channel && if (channel == sdev->channel &&
target == sdev->id) { target == sdev->id) {
sdev->was_reset = 1; sdev->was_reset = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment