[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: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Родитель
cdbbde14cb
Коммит
18e144d32c
|
@ -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)
|
||||||
|
|
||||||
/* 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)
|
||||||
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)
|
||||||
"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)
|
||||||
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)
|
||||||
* 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} 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)
|
||||||
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)
|
||||||
* 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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче