[SCSI] qla2xxx: Correct several PCI-EEH issues.
authorSeokmann Ju <seokmann.ju@qlogic.com>
Tue, 24 Mar 2009 16:08:18 +0000 (09:08 -0700)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Fri, 3 Apr 2009 14:22:53 +0000 (09:22 -0500)
In addition to checking for potentially unnecessary iomem
readX()/writeX() operations, a pci_channel_io_perm_failure should
not trigger a full internal removal.  Found during additional
testing with pSeries blade systems.

Signed-off-by: Seokmann Ju <seokmann.ju@qlogic.com>
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c

index 15573f6dc36bbfcc774ef7f9bb25486859825a5c..b09993a06576cfbf37ead3608b53d5256bf084f4 100644 (file)
@@ -1282,7 +1282,10 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
        if (!fcport)
                return;
 
-       qla2x00_abort_fcport_cmds(fcport);
+       if (unlikely(pci_channel_offline(fcport->vha->hw->pdev)))
+               qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
+       else
+               qla2x00_abort_fcport_cmds(fcport);
 
        /*
         * Transport has effectively 'deleted' the rport, clear
@@ -1302,6 +1305,10 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
        if (!fcport)
                return;
 
+       if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
+               qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
+               return;
+       }
        /*
         * At this point all fcport's software-states are cleared.  Perform any
         * final cleanup of firmware resources (PCBs and XCBs).
index 951537e3029406eeabcb669d7ee4b75da7299ee9..e67c1660bf4671aacf54c43e35dca5182b81fc33 100644 (file)
@@ -45,6 +45,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        struct qla_hw_data *ha = vha->hw;
        scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
 
+       if (ha->pdev->error_state > pci_channel_io_frozen)
+               return QLA_FUNCTION_TIMEOUT;
+
        reg = ha->iobase;
        io_lock_on = base_vha->flags.init_done;
 
index 7e038e4107a5d28597b0e30fcb30591f9b6413bb..efe29924e058669bafe576ef711aa557ad2fb190 100644 (file)
@@ -407,7 +407,10 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
        int rval;
 
        if (unlikely(pci_channel_offline(ha->pdev))) {
-               cmd->result = DID_REQUEUE << 16;
+               if (ha->pdev->error_state == pci_channel_io_frozen)
+                       cmd->result = DID_REQUEUE << 16;
+               else
+                       cmd->result = DID_NO_CONNECT << 16;
                goto qc24_fail_command;
        }
 
@@ -2990,6 +2993,8 @@ qla2x00_release_firmware(void)
 static pci_ers_result_t
 qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
+       scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
+
        switch (state) {
        case pci_channel_io_normal:
                return PCI_ERS_RESULT_CAN_RECOVER;
@@ -2997,7 +3002,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
                pci_disable_device(pdev);
                return PCI_ERS_RESULT_NEED_RESET;
        case pci_channel_io_perm_failure:
-               qla2x00_remove_one(pdev);
+               qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
                return PCI_ERS_RESULT_DISCONNECT;
        }
        return PCI_ERS_RESULT_NEED_RESET;