Commit 18e144d3 authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley

[SCSI] qla2xxx: fix bad locking during eh_abort


Correct incorrect locking order in qla2xxx_eh_abort() handler which
would case a hang during certain code-paths.

With extra pieces to fix the irq state in the locks.
Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent cdbbde14
...@@ -507,6 +507,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) ...@@ -507,6 +507,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
int ret, i; int ret, i;
unsigned int id, lun; unsigned int id, lun;
unsigned long serial; unsigned long serial;
unsigned long flags;
if (!CMD_SP(cmd)) if (!CMD_SP(cmd))
return FAILED; return FAILED;
...@@ -519,7 +520,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) ...@@ -519,7 +520,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
/* Check active list for command command. */ /* Check active list for command command. */
spin_unlock_irq(ha->host->host_lock); spin_unlock_irq(ha->host->host_lock);
spin_lock(&ha->hardware_lock); spin_lock_irqsave(&ha->hardware_lock, flags);
for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
sp = ha->outstanding_cmds[i]; sp = ha->outstanding_cmds[i];
...@@ -534,7 +535,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) ...@@ -534,7 +535,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
sp->state)); sp->state));
DEBUG3(qla2x00_print_scsi_cmd(cmd);) DEBUG3(qla2x00_print_scsi_cmd(cmd);)
spin_unlock(&ha->hardware_lock); spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (qla2x00_abort_command(ha, sp)) { if (qla2x00_abort_command(ha, sp)) {
DEBUG2(printk("%s(%ld): abort_command " DEBUG2(printk("%s(%ld): abort_command "
"mbx failed.\n", __func__, ha->host_no)); "mbx failed.\n", __func__, ha->host_no));
...@@ -543,20 +544,19 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) ...@@ -543,20 +544,19 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
"mbx success.\n", __func__, ha->host_no)); "mbx success.\n", __func__, ha->host_no));
ret = SUCCESS; ret = SUCCESS;
} }
spin_lock(&ha->hardware_lock); spin_lock_irqsave(&ha->hardware_lock, flags);
break; break;
} }
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Wait for the command to be returned. */ /* Wait for the command to be returned. */
if (ret == SUCCESS) { if (ret == SUCCESS) {
spin_unlock(&ha->hardware_lock);
if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) { if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
qla_printk(KERN_ERR, ha, qla_printk(KERN_ERR, ha,
"scsi(%ld:%d:%d): Abort handler timed out -- %lx " "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
"%x.\n", ha->host_no, id, lun, serial, ret); "%x.\n", ha->host_no, id, lun, serial, ret);
} }
spin_lock(&ha->hardware_lock);
} }
spin_lock_irq(ha->host->host_lock); spin_lock_irq(ha->host->host_lock);
...@@ -588,6 +588,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) ...@@ -588,6 +588,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
int status; int status;
srb_t *sp; srb_t *sp;
struct scsi_cmnd *cmd; struct scsi_cmnd *cmd;
unsigned long flags;
status = 0; status = 0;
...@@ -596,11 +597,11 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) ...@@ -596,11 +597,11 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
* array * array
*/ */
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
spin_lock(&ha->hardware_lock); spin_lock_irqsave(&ha->hardware_lock, flags);
sp = ha->outstanding_cmds[cnt]; sp = ha->outstanding_cmds[cnt];
if (sp) { if (sp) {
cmd = sp->cmd; cmd = sp->cmd;
spin_unlock(&ha->hardware_lock); spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (cmd->device->id == t) { if (cmd->device->id == t) {
if (!qla2x00_eh_wait_on_command(ha, cmd)) { if (!qla2x00_eh_wait_on_command(ha, cmd)) {
status = 1; status = 1;
...@@ -608,7 +609,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) ...@@ -608,7 +609,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
} }
} }
} else { } else {
spin_unlock(&ha->hardware_lock); spin_unlock_irqrestore(&ha->hardware_lock, flags);
} }
} }
return (status); return (status);
...@@ -740,6 +741,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) ...@@ -740,6 +741,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
int status; int status;
srb_t *sp; srb_t *sp;
struct scsi_cmnd *cmd; struct scsi_cmnd *cmd;
unsigned long flags;
status = 1; status = 1;
...@@ -748,17 +750,17 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) ...@@ -748,17 +750,17 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
* array * array
*/ */
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
spin_lock(&ha->hardware_lock); spin_lock_irqsave(&ha->hardware_lock, flags);
sp = ha->outstanding_cmds[cnt]; sp = ha->outstanding_cmds[cnt];
if (sp) { if (sp) {
cmd = sp->cmd; cmd = sp->cmd;
spin_unlock(&ha->hardware_lock); spin_unlock_irqrestore(&ha->hardware_lock, flags);
status = qla2x00_eh_wait_on_command(ha, cmd); status = qla2x00_eh_wait_on_command(ha, cmd);
if (status == 0) if (status == 0)
break; break;
} }
else { else {
spin_unlock(&ha->hardware_lock); spin_unlock_irqrestore(&ha->hardware_lock, flags);
} }
} }
return (status); return (status);
......
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