]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/scsi/qla2xxx/qla_mbx.c
[SCSI] qla2xxx: Handle outstanding mbx cmds on hung f/w scenarios.
[mv-sheeva.git] / drivers / scsi / qla2xxx / qla_mbx.c
index 10f4815aec77099b3a3b9ac4d85a97841afa692a..2f39e309393992525a8b3da790ad6443ea10bab0 100644 (file)
@@ -37,7 +37,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        device_reg_t __iomem *reg;
        uint8_t         abort_active;
        uint8_t         io_lock_on;
-       uint16_t        command;
+       uint16_t        command = 0;
        uint16_t        *iptr;
        uint16_t __iomem *optr;
        uint32_t        cnt;
@@ -83,6 +83,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                return QLA_FUNCTION_TIMEOUT;
        }
 
+       if (IS_QLA82XX(ha) && ha->flags.fw_hung) {
+               /* Setting Link-Down error */
+               mcp->mb[0] = MBS_LINK_DOWN_ERROR;
+               rval = QLA_FUNCTION_FAILED;
+               goto premature_exit;
+       }
+
        ha->flags.mbox_busy = 1;
        /* Save mailbox command for debug */
        ha->mcp = mcp;
@@ -151,7 +158,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                                DEBUG2_3_11(printk(KERN_INFO
                                    "%s(%ld): Pending Mailbox timeout. "
                                    "Exiting.\n", __func__, base_vha->host_no));
-                               return QLA_FUNCTION_TIMEOUT;
+                               rval = QLA_FUNCTION_TIMEOUT;
+                               goto premature_exit;
                        }
                        WRT_REG_DWORD(&reg->isp82.hint, HINT_MBX_INT_PENDING);
                } else if (IS_FWI2_CAPABLE(ha))
@@ -176,7 +184,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                                DEBUG2_3_11(printk(KERN_INFO
                                    "%s(%ld): Pending Mailbox timeout. "
                                    "Exiting.\n", __func__, base_vha->host_no));
-                               return QLA_FUNCTION_TIMEOUT;
+                               rval = QLA_FUNCTION_TIMEOUT;
+                               goto premature_exit;
                        }
                        WRT_REG_DWORD(&reg->isp82.hint, HINT_MBX_INT_PENDING);
                } else if (IS_FWI2_CAPABLE(ha))
@@ -214,6 +223,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                ha->flags.mbox_int = 0;
                clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 
+               if (IS_QLA82XX(ha) && ha->flags.fw_hung) {
+                       ha->flags.mbox_busy = 0;
+                       /* Setting Link-Down error */
+                       mcp->mb[0] = MBS_LINK_DOWN_ERROR;
+                       ha->mcp = NULL;
+                       rval = QLA_FUNCTION_FAILED;
+                       goto premature_exit;
+               }
+
                if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE)
                        rval = QLA_FUNCTION_FAILED;
 
@@ -279,35 +297,51 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                        DEBUG2_3_11(printk("%s(%ld): timeout schedule "
                        "isp_abort_needed.\n", __func__,
                        base_vha->host_no));
-                       qla_printk(KERN_WARNING, ha,
-                           "Mailbox command timeout occurred. Scheduling ISP "
-                           "abort. eeh_busy: 0x%x\n", ha->flags.eeh_busy);
-                       set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
-                       qla2xxx_wake_dpc(vha);
+
+                       if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
+                           !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
+                           !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+
+                               qla_printk(KERN_WARNING, ha,
+                                   "Mailbox command timeout occured. "
+                                   "Scheduling ISP " "abort. eeh_busy: 0x%x\n",
+                                   ha->flags.eeh_busy);
+                               set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+                               qla2xxx_wake_dpc(vha);
+                       }
                } else if (!abort_active) {
                        /* call abort directly since we are in the DPC thread */
                        DEBUG(printk("%s(%ld): timeout calling abort_isp\n",
                            __func__, base_vha->host_no));
                        DEBUG2_3_11(printk("%s(%ld): timeout calling "
                            "abort_isp\n", __func__, base_vha->host_no));
-                       qla_printk(KERN_WARNING, ha,
-                           "Mailbox command timeout occurred. Issuing ISP "
-                           "abort.\n");
-
-                       set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
-                       clear_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
-                       if (ha->isp_ops->abort_isp(base_vha)) {
-                               /* Failed. retry later. */
-                               set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
+
+                       if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) &&
+                           !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
+                           !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+
+                               qla_printk(KERN_WARNING, ha,
+                                   "Mailbox command timeout occured. "
+                                   "Issuing ISP abort.\n");
+
+                               set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
+                               clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+                               if (ha->isp_ops->abort_isp(vha)) {
+                                       /* Failed. retry later. */
+                                       set_bit(ISP_ABORT_NEEDED,
+                                           &vha->dpc_flags);
+                               }
+                               clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
+                               DEBUG(printk("%s(%ld): finished abort_isp\n",
+                                   __func__, vha->host_no));
+                               DEBUG2_3_11(printk(
+                                   "%s(%ld): finished abort_isp\n",
+                                   __func__, vha->host_no));
                        }
-                       clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
-                       DEBUG(printk("%s(%ld): finished abort_isp\n", __func__,
-                           base_vha->host_no));
-                       DEBUG2_3_11(printk("%s(%ld): finished abort_isp\n",
-                           __func__, base_vha->host_no));
                }
        }
 
+premature_exit:
        /* Allow next mbx cmd to come in. */
        complete(&ha->mbx_cmd_comp);