aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2005-05-27 18:04:47 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-06-03 10:37:53 -0400
commit18e144d32cd3dae6953c385e4b376ef9688b61b0 (patch)
tree8b8376da9f809cca19894792b53aecb7a40ba5bf
parentcdbbde14cb55dd10771ce79154f787322d88411b (diff)
[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>
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 579448222d69..3c97aa45772d 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -507,6 +507,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
507 int ret, i; 507 int ret, i;
508 unsigned int id, lun; 508 unsigned int id, lun;
509 unsigned long serial; 509 unsigned long serial;
510 unsigned long flags;
510 511
511 if (!CMD_SP(cmd)) 512 if (!CMD_SP(cmd))
512 return FAILED; 513 return FAILED;
@@ -519,7 +520,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
519 520
520 /* Check active list for command command. */ 521 /* Check active list for command command. */
521 spin_unlock_irq(ha->host->host_lock); 522 spin_unlock_irq(ha->host->host_lock);
522 spin_lock(&ha->hardware_lock); 523 spin_lock_irqsave(&ha->hardware_lock, flags);
523 for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { 524 for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
524 sp = ha->outstanding_cmds[i]; 525 sp = ha->outstanding_cmds[i];
525 526
@@ -534,7 +535,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
534 sp->state)); 535 sp->state));
535 DEBUG3(qla2x00_print_scsi_cmd(cmd);) 536 DEBUG3(qla2x00_print_scsi_cmd(cmd);)
536 537
537 spin_unlock(&ha->hardware_lock); 538 spin_unlock_irqrestore(&ha->hardware_lock, flags);
538 if (qla2x00_abort_command(ha, sp)) { 539 if (qla2x00_abort_command(ha, sp)) {
539 DEBUG2(printk("%s(%ld): abort_command " 540 DEBUG2(printk("%s(%ld): abort_command "
540 "mbx failed.\n", __func__, ha->host_no)); 541 "mbx failed.\n", __func__, ha->host_no));
@@ -543,20 +544,19 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
543 "mbx success.\n", __func__, ha->host_no)); 544 "mbx success.\n", __func__, ha->host_no));
544 ret = SUCCESS; 545 ret = SUCCESS;
545 } 546 }
546 spin_lock(&ha->hardware_lock); 547 spin_lock_irqsave(&ha->hardware_lock, flags);
547 548
548 break; 549 break;
549 } 550 }
551 spin_unlock_irqrestore(&ha->hardware_lock, flags);
550 552
551 /* Wait for the command to be returned. */ 553 /* Wait for the command to be returned. */
552 if (ret == SUCCESS) { 554 if (ret == SUCCESS) {
553 spin_unlock(&ha->hardware_lock);
554 if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) { 555 if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
555 qla_printk(KERN_ERR, ha, 556 qla_printk(KERN_ERR, ha,
556 "scsi(%ld:%d:%d): Abort handler timed out -- %lx " 557 "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
557 "%x.\n", ha->host_no, id, lun, serial, ret); 558 "%x.\n", ha->host_no, id, lun, serial, ret);
558 } 559 }
559 spin_lock(&ha->hardware_lock);
560 } 560 }
561 spin_lock_irq(ha->host->host_lock); 561 spin_lock_irq(ha->host->host_lock);
562 562
@@ -588,6 +588,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
588 int status; 588 int status;
589 srb_t *sp; 589 srb_t *sp;
590 struct scsi_cmnd *cmd; 590 struct scsi_cmnd *cmd;
591 unsigned long flags;
591 592
592 status = 0; 593 status = 0;
593 594
@@ -596,11 +597,11 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
596 * array 597 * array
597 */ 598 */
598 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { 599 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
599 spin_lock(&ha->hardware_lock); 600 spin_lock_irqsave(&ha->hardware_lock, flags);
600 sp = ha->outstanding_cmds[cnt]; 601 sp = ha->outstanding_cmds[cnt];
601 if (sp) { 602 if (sp) {
602 cmd = sp->cmd; 603 cmd = sp->cmd;
603 spin_unlock(&ha->hardware_lock); 604 spin_unlock_irqrestore(&ha->hardware_lock, flags);
604 if (cmd->device->id == t) { 605 if (cmd->device->id == t) {
605 if (!qla2x00_eh_wait_on_command(ha, cmd)) { 606 if (!qla2x00_eh_wait_on_command(ha, cmd)) {
606 status = 1; 607 status = 1;
@@ -608,7 +609,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
608 } 609 }
609 } 610 }
610 } else { 611 } else {
611 spin_unlock(&ha->hardware_lock); 612 spin_unlock_irqrestore(&ha->hardware_lock, flags);
612 } 613 }
613 } 614 }
614 return (status); 615 return (status);
@@ -740,6 +741,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
740 int status; 741 int status;
741 srb_t *sp; 742 srb_t *sp;
742 struct scsi_cmnd *cmd; 743 struct scsi_cmnd *cmd;
744 unsigned long flags;
743 745
744 status = 1; 746 status = 1;
745 747
@@ -748,17 +750,17 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
748 * array 750 * array
749 */ 751 */
750 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { 752 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
751 spin_lock(&ha->hardware_lock); 753 spin_lock_irqsave(&ha->hardware_lock, flags);
752 sp = ha->outstanding_cmds[cnt]; 754 sp = ha->outstanding_cmds[cnt];
753 if (sp) { 755 if (sp) {
754 cmd = sp->cmd; 756 cmd = sp->cmd;
755 spin_unlock(&ha->hardware_lock); 757 spin_unlock_irqrestore(&ha->hardware_lock, flags);
756 status = qla2x00_eh_wait_on_command(ha, cmd); 758 status = qla2x00_eh_wait_on_command(ha, cmd);
757 if (status == 0) 759 if (status == 0)
758 break; 760 break;
759 } 761 }
760 else { 762 else {
761 spin_unlock(&ha->hardware_lock); 763 spin_unlock_irqrestore(&ha->hardware_lock, flags);
762 } 764 }
763 } 765 }
764 return (status); 766 return (status);