summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ibmvscsi
diff options
context:
space:
mode:
authorDave C Boutcher <sleddog@us.ibm.com>2005-08-15 16:52:58 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2005-08-28 11:14:08 -0500
commitbe042f240a8528b8f6b741a484cdbbf515698388 (patch)
tree2015cb8448cdfb0350cfd582c660535e4242fed0 /drivers/scsi/ibmvscsi
parent3b2946cc96bfafa90a555c70b2e876cbbd0fae98 (diff)
downloadlinux-be042f240a8528b8f6b741a484cdbbf515698388.tar.gz
linux-be042f240a8528b8f6b741a484cdbbf515698388.tar.bz2
linux-be042f240a8528b8f6b741a484cdbbf515698388.zip
[SCSI] ibmvscsi eh locking
With the removal of the spinlocking around eh calls, we need to add a little more locking back in, otherwise we do some naked list manipulation. Signed-off-by: Dave Boutcher <boutcher@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/ibmvscsi')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index fe09d145542a..1ae800ae93d7 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -826,11 +826,13 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
struct srp_event_struct *tmp_evt, *found_evt;
union viosrp_iu srp_rsp;
int rsp_rc;
+ unsigned long flags;
u16 lun = lun_from_dev(cmd->device);
/* First, find this command in our sent list so we can figure
* out the correct tag
*/
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
found_evt = NULL;
list_for_each_entry(tmp_evt, &hostdata->sent, list) {
if (tmp_evt->cmnd == cmd) {
@@ -839,11 +841,14 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
}
- if (!found_evt)
+ if (!found_evt) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
return FAILED;
+ }
evt = get_event_struct(&hostdata->pool);
if (evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
return FAILED;
}
@@ -867,7 +872,9 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
- if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+ rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ if (rsp_rc != 0) {
printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
return FAILED;
}
@@ -901,6 +908,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
* The event is no longer in our list. Make sure it didn't
* complete while we were aborting
*/
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
found_evt = NULL;
list_for_each_entry(tmp_evt, &hostdata->sent, list) {
if (tmp_evt->cmnd == cmd) {
@@ -910,6 +918,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
if (found_evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_INFO
"ibmvscsi: aborted task tag 0x%lx completed\n",
tsk_mgmt->managed_task_tag);
@@ -924,6 +933,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
list_del(&found_evt->list);
unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
free_event_struct(&found_evt->hostdata->pool, found_evt);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
atomic_inc(&hostdata->request_limit);
return SUCCESS;
}
@@ -943,10 +953,13 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
struct srp_event_struct *tmp_evt, *pos;
union viosrp_iu srp_rsp;
int rsp_rc;
+ unsigned long flags;
u16 lun = lun_from_dev(cmd->device);
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
evt = get_event_struct(&hostdata->pool);
if (evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
return FAILED;
}
@@ -969,7 +982,9 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
- if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+ rsp_rc = ibmvscsi_send_srp_event(evt, hostdata);
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ if (rsp_rc != 0) {
printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
return FAILED;
}
@@ -1002,6 +1017,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
/* We need to find all commands for this LUN that have not yet been
* responded to, and fail them with DID_RESET
*/
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) {
if (tmp_evt->cmnd)
@@ -1017,6 +1033,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
tmp_evt->done(tmp_evt);
}
}
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
return SUCCESS;
}