]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/scsi/qla2xxx/qla_mbx.c
[SCSI] qla2xxx: Pass first 64 bytes of MBX information when vendor commands fail.
[mirror_ubuntu-bionic-kernel.git] / drivers / scsi / qla2xxx / qla_mbx.c
index f3650d0434cadf7b1d00bb63694f48fefaa7f26f..d0413d56887c7a4016ebf6a330c24e6fe859160e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2008 QLogic Corporation
+ * Copyright (c)  2003-2010 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -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);
 
@@ -866,8 +900,8 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag)
 
        l = l;
        vha = fcport->vha;
-       req = vha->hw->req_q_map[tag];
-       rsp = vha->hw->rsp_q_map[tag];
+       req = vha->hw->req_q_map[0];
+       rsp = req->rsp;
        mcp->mb[0] = MBC_ABORT_TARGET;
        mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
        if (HAS_EXTENDED_IDS(vha->hw)) {
@@ -915,8 +949,8 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
        DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
 
        vha = fcport->vha;
-       req = vha->hw->req_q_map[tag];
-       rsp = vha->hw->rsp_q_map[tag];
+       req = vha->hw->req_q_map[0];
+       rsp = req->rsp;
        mcp->mb[0] = MBC_LUN_RESET;
        mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
        if (HAS_EXTENDED_IDS(vha->hw))
@@ -3791,8 +3825,6 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
 
        /* Copy mailbox information */
        memcpy( mresp, mcp->mb, 64);
-       mresp[3] = mcp->mb[18];
-       mresp[4] = mcp->mb[19];
        return rval;
 }
 
@@ -3853,9 +3885,10 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
        }
 
        /* Copy mailbox information */
-       memcpy( mresp, mcp->mb, 32);
+       memcpy(mresp, mcp->mb, 64);
        return rval;
 }
+
 int
 qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic)
 {
@@ -3949,6 +3982,72 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
        return rval;
 }
 
+int
+qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+       struct qla_hw_data *ha = vha->hw;
+
+       DEBUG11(printk(KERN_INFO
+           "%s(%ld): entered.\n", __func__, vha->host_no));
+
+       if (!IS_QLA81XX(ha))
+               return QLA_FUNCTION_FAILED;
+       mcp->mb[0] = MBC_GET_PORT_CONFIG;
+       mcp->out_mb = MBX_0;
+       mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+
+       rval = qla2x00_mailbox_command(vha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk(KERN_WARNING
+                   "%s(%ld): failed=%x (%x).\n", __func__,
+                   vha->host_no, rval, mcp->mb[0]));
+       } else {
+               /* Copy all bits to preserve original value */
+               memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4);
+
+               DEBUG11(printk(KERN_INFO
+                   "%s(%ld): done.\n", __func__, vha->host_no));
+       }
+       return rval;
+}
+
+int
+qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       DEBUG11(printk(KERN_INFO
+           "%s(%ld): entered.\n", __func__, vha->host_no));
+
+       mcp->mb[0] = MBC_SET_PORT_CONFIG;
+       /* Copy all bits to preserve original setting */
+       memcpy(&mcp->mb[1], mb, sizeof(uint16_t) * 4);
+       mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(vha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk(KERN_WARNING
+                   "%s(%ld): failed=%x (%x).\n", __func__,
+                   vha->host_no, rval, mcp->mb[0]));
+       } else
+               DEBUG11(printk(KERN_INFO
+                   "%s(%ld): done.\n", __func__, vha->host_no));
+
+       return rval;
+}
+
+
 int
 qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
                uint16_t *mb)
@@ -4011,7 +4110,7 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
                "%s(%ld): entered.\n", __func__, vha->host_no));
 
        memset(mcp, 0, sizeof(mbx_cmd_t));
-       mcp->mb[0] = MBC_TOGGLE_INTR;
+       mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
        mcp->mb[1] = 1;
 
        mcp->out_mb = MBX_1|MBX_0;
@@ -4047,7 +4146,7 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha)
                "%s(%ld): entered.\n", __func__, vha->host_no));
 
        memset(mcp, 0, sizeof(mbx_cmd_t));
-       mcp->mb[0] = MBC_TOGGLE_INTR;
+       mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
        mcp->mb[1] = 0;
 
        mcp->out_mb = MBX_1|MBX_0;