diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2005-05-27 18:04:47 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-06-03 10:37:53 -0400 |
commit | 18e144d32cd3dae6953c385e4b376ef9688b61b0 (patch) | |
tree | 8b8376da9f809cca19894792b53aecb7a40ba5bf | |
parent | cdbbde14cb55dd10771ce79154f787322d88411b (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.c | 24 |
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); |