Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier...
[sfrench/cifs-2.6.git] / drivers / scsi / qla2xxx / qla_mbx.c
index 42eb7ffd5942ed2e9a4243a01ece11e85bceeb0f..f3650d0434cadf7b1d00bb63694f48fefaa7f26f 100644 (file)
@@ -49,6 +49,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        if (ha->pdev->error_state > pci_channel_io_frozen)
                return QLA_FUNCTION_TIMEOUT;
 
+       if (vha->device_flags & DFLG_DEV_FAILED) {
+               DEBUG2_3_11(qla_printk(KERN_WARNING, ha,
+                       "%s(%ld): Device in failed state, "
+                       "timeout MBX Exiting.\n",
+                       __func__, base_vha->host_no));
+               return QLA_FUNCTION_TIMEOUT;
+       }
+
        reg = ha->iobase;
        io_lock_on = base_vha->flags.init_done;
 
@@ -85,7 +93,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
        /* Load mailbox registers. */
-       if (IS_FWI2_CAPABLE(ha))
+       if (IS_QLA82XX(ha))
+               optr = (uint16_t __iomem *)&reg->isp82.mailbox_in[0];
+       else if (IS_FWI2_CAPABLE(ha) && !IS_QLA82XX(ha))
                optr = (uint16_t __iomem *)&reg->isp24.mailbox0;
        else
                optr = (uint16_t __iomem *)MAILBOX_REG(ha, &reg->isp, 0);
@@ -133,7 +143,18 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
                set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
 
-               if (IS_FWI2_CAPABLE(ha))
+               if (IS_QLA82XX(ha)) {
+                       if (RD_REG_DWORD(&reg->isp82.hint) &
+                               HINT_MBX_INT_PENDING) {
+                               spin_unlock_irqrestore(&ha->hardware_lock,
+                                       flags);
+                               DEBUG2_3_11(printk(KERN_INFO
+                                   "%s(%ld): Pending Mailbox timeout. "
+                                   "Exiting.\n", __func__, base_vha->host_no));
+                               return QLA_FUNCTION_TIMEOUT;
+                       }
+                       WRT_REG_DWORD(&reg->isp82.hint, HINT_MBX_INT_PENDING);
+               } else if (IS_FWI2_CAPABLE(ha))
                        WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
                else
                        WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
@@ -147,7 +168,18 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__,
                    base_vha->host_no, command));
 
-               if (IS_FWI2_CAPABLE(ha))
+               if (IS_QLA82XX(ha)) {
+                       if (RD_REG_DWORD(&reg->isp82.hint) &
+                               HINT_MBX_INT_PENDING) {
+                               spin_unlock_irqrestore(&ha->hardware_lock,
+                                       flags);
+                               DEBUG2_3_11(printk(KERN_INFO
+                                   "%s(%ld): Pending Mailbox timeout. "
+                                   "Exiting.\n", __func__, base_vha->host_no));
+                               return QLA_FUNCTION_TIMEOUT;
+                       }
+                       WRT_REG_DWORD(&reg->isp82.hint, HINT_MBX_INT_PENDING);
+               } else if (IS_FWI2_CAPABLE(ha))
                        WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
                else
                        WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
@@ -264,7 +296,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 
                        set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
                        clear_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
-                       if (qla2x00_abort_isp(base_vha)) {
+                       if (ha->isp_ops->abort_isp(base_vha)) {
                                /* Failed. retry later. */
                                set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
                        }
@@ -711,7 +743,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr)
  * Context:
  *     Kernel context.
  */
-static int
+int
 qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer,
     dma_addr_t phys_addr, size_t size, uint32_t tov)
 {
@@ -952,7 +984,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
        mcp->mb[9] = vha->vp_idx;
        mcp->out_mb = MBX_9|MBX_0;
        mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
-       if (IS_QLA81XX(vha->hw))
+       if (IS_QLA8XXX_TYPE(vha->hw))
                mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
        mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
@@ -978,7 +1010,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
                DEBUG11(printk("qla2x00_get_adapter_id(%ld): done.\n",
                    vha->host_no));
 
-               if (IS_QLA81XX(vha->hw)) {
+               if (IS_QLA8XXX_TYPE(vha->hw)) {
                        vha->fcoe_vlan_id = mcp->mb[9] & 0xfff;
                        vha->fcoe_fcf_idx = mcp->mb[10];
                        vha->fcoe_vn_port_mac[5] = mcp->mb[11] >> 8;
@@ -1076,6 +1108,10 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
        DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n",
            vha->host_no));
 
+       if (IS_QLA82XX(ha) && ql2xdbwr)
+               qla82xx_wr_32(ha, ha->nxdb_wr_ptr,
+                       (0x04 | (ha->portnum << 5) | (0 << 8) | (0 << 16)));
+
        if (ha->flags.npiv_supported)
                mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE;
        else
@@ -1408,7 +1444,7 @@ qla2x00_lip_reset(scsi_qla_host_t *vha)
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
 
-       if (IS_QLA81XX(vha->hw)) {
+       if (IS_QLA8XXX_TYPE(vha->hw)) {
                /* Logout across all FCFs. */
                mcp->mb[0] = MBC_LIP_FULL_LOGIN;
                mcp->mb[1] = BIT_1;
@@ -2428,12 +2464,22 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
 int
 qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag)
 {
+       struct qla_hw_data *ha = fcport->vha->hw;
+
+       if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
+               return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag);
+
        return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l, tag);
 }
 
 int
 qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag)
 {
+       struct qla_hw_data *ha = fcport->vha->hw;
+
+       if ((ql2xasynctmfenable) && IS_FWI2_CAPABLE(ha))
+               return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag);
+
        return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l, tag);
 }
 
@@ -2739,6 +2785,48 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint16_t addr,
        return rval;
 }
 
+int
+qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
+       uint16_t *port_speed, uint16_t *mb)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       if (!IS_IIDMA_CAPABLE(vha->hw))
+               return QLA_FUNCTION_FAILED;
+
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+       mcp->mb[0] = MBC_PORT_PARAMS;
+       mcp->mb[1] = loop_id;
+       mcp->mb[2] = mcp->mb[3] = 0;
+       mcp->mb[9] = vha->vp_idx;
+       mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_3|MBX_1|MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(vha, mcp);
+
+       /* Return mailbox statuses. */
+       if (mb != NULL) {
+               mb[0] = mcp->mb[0];
+               mb[1] = mcp->mb[1];
+               mb[3] = mcp->mb[3];
+       }
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+                   vha->host_no, rval));
+       } else {
+               DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+               if (port_speed)
+                       *port_speed = mcp->mb[3];
+       }
+
+       return rval;
+}
+
 int
 qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
     uint16_t port_speed, uint16_t *mb)
@@ -2755,7 +2843,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
        mcp->mb[0] = MBC_PORT_PARAMS;
        mcp->mb[1] = loop_id;
        mcp->mb[2] = BIT_0;
-       if (IS_QLA81XX(vha->hw))
+       if (IS_QLA8XXX_TYPE(vha->hw))
                mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0);
        else
                mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0);
@@ -3544,7 +3632,7 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       if (!IS_QLA81XX(vha->hw))
+       if (!IS_QLA8XXX_TYPE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
@@ -3582,7 +3670,7 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       if (!IS_QLA81XX(vha->hw))
+       if (!IS_QLA8XXX_TYPE(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
@@ -3643,7 +3731,8 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data)
 }
 
 int
-qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mresp)
+qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
+       uint16_t *mresp)
 {
        int rval;
        mbx_cmd_t mc;
@@ -3678,7 +3767,7 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *
 
        mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
            MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
-       if (IS_QLA81XX(vha->hw))
+       if (IS_QLA8XXX_TYPE(vha->hw))
                mcp->out_mb |= MBX_2;
        mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
 
@@ -3690,9 +3779,11 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *
 
        if (rval != QLA_SUCCESS) {
                DEBUG2(printk(KERN_WARNING
-                   "(%ld): failed=%x mb[0]=0x%x "
-                       "mb[1]=0x%x mb[2]=0x%x mb[3]=0x%x mb[18]=0x%x mb[19]=0x%x. \n", vha->host_no, rval,
-                       mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[18], mcp->mb[19]));
+                       "(%ld): failed=%x mb[0]=0x%x "
+                       "mb[1]=0x%x mb[2]=0x%x mb[3]=0x%x mb[18]=0x%x "
+                       "mb[19]=0x%x.\n",
+                       vha->host_no, rval, mcp->mb[0], mcp->mb[1], mcp->mb[2],
+                       mcp->mb[3], mcp->mb[18], mcp->mb[19]));
        } else {
                DEBUG2(printk(KERN_WARNING
                    "scsi(%ld): done.\n", vha->host_no));
@@ -3706,7 +3797,8 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *
 }
 
 int
-qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mresp)
+qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
+       uint16_t *mresp)
 {
        int rval;
        mbx_cmd_t mc;
@@ -3718,9 +3810,10 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mres
        memset(mcp->mb, 0 , sizeof(mcp->mb));
        mcp->mb[0] = MBC_DIAGNOSTIC_ECHO;
        mcp->mb[1] = mreq->options | BIT_6;     /* BIT_6 specifies 64bit address */
-       if (IS_QLA81XX(ha))
+       if (IS_QLA8XXX_TYPE(ha)) {
                mcp->mb[1] |= BIT_15;
-       mcp->mb[2] = IS_QLA81XX(ha) ? vha->fcoe_fcf_idx : 0;
+               mcp->mb[2] = vha->fcoe_fcf_idx;
+       }
        mcp->mb[16] = LSW(mreq->rcv_dma);
        mcp->mb[17] = MSW(mreq->rcv_dma);
        mcp->mb[6] = LSW(MSD(mreq->rcv_dma));
@@ -3735,13 +3828,13 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mres
 
        mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|
            MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
-       if (IS_QLA81XX(ha))
+       if (IS_QLA8XXX_TYPE(ha))
                mcp->out_mb |= MBX_2;
 
        mcp->in_mb = MBX_0;
-       if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha))
+       if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA8XXX_TYPE(ha))
                mcp->in_mb |= MBX_1;
-       if (IS_QLA81XX(ha))
+       if (IS_QLA8XXX_TYPE(ha))
                mcp->in_mb |= MBX_3;
 
        mcp->tov = MBX_TOV_SECONDS;
@@ -3764,8 +3857,7 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mres
        return rval;
 }
 int
-qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic,
-    uint16_t *cmd_status)
+qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic)
 {
        int rval;
        mbx_cmd_t mc;
@@ -3782,8 +3874,6 @@ qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic,
        mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD;
        rval = qla2x00_mailbox_command(ha, mcp);
 
-       /* Return mailbox statuses. */
-       *cmd_status = mcp->mb[0];
        if (rval != QLA_SUCCESS)
                DEBUG16(printk("%s(%ld): failed=%x.\n", __func__, ha->host_no,
                        rval));
@@ -3801,7 +3891,7 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
        mbx_cmd_t *mcp = &mc;
 
        if (!IS_FWI2_CAPABLE(vha->hw))
-                return QLA_FUNCTION_FAILED;
+               return QLA_FUNCTION_FAILED;
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
 
@@ -3836,7 +3926,8 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
        if (!IS_FWI2_CAPABLE(ha))
                return QLA_FUNCTION_FAILED;
 
-       DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, vha->host_no));
+       DEBUG11(qla_printk(KERN_INFO, ha,
+               "%s(%ld): entered.\n", __func__, vha->host_no));
 
        mcp->mb[0] = MBC_DATA_RATE;
        mcp->mb[1] = 0;
@@ -3857,3 +3948,122 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
 
        return rval;
 }
+
+int
+qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority,
+               uint16_t *mb)
+{
+       int rval;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
+               return QLA_FUNCTION_FAILED;
+
+       DEBUG11(printk(KERN_INFO
+           "%s(%ld): entered.\n", __func__, ha->host_no));
+
+       mcp->mb[0] = MBC_PORT_PARAMS;
+       mcp->mb[1] = loop_id;
+       if (ha->flags.fcp_prio_enabled)
+               mcp->mb[2] = BIT_1;
+       else
+               mcp->mb[2] = BIT_2;
+       mcp->mb[4] = priority & 0xf;
+       mcp->mb[9] = vha->vp_idx;
+       mcp->out_mb = MBX_9|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0;
+       mcp->tov = 30;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(vha, mcp);
+       if (mb != NULL) {
+               mb[0] = mcp->mb[0];
+               mb[1] = mcp->mb[1];
+               mb[3] = mcp->mb[3];
+               mb[4] = mcp->mb[4];
+       }
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk(KERN_WARNING
+                   "%s(%ld): failed=%x.\n", __func__,
+                   vha->host_no, rval));
+       } else {
+               DEBUG11(printk(KERN_INFO
+                   "%s(%ld): done.\n", __func__, vha->host_no));
+       }
+
+       return rval;
+}
+
+int
+qla82xx_mbx_intr_enable(scsi_qla_host_t *vha)
+{
+       int rval;
+       struct qla_hw_data *ha = vha->hw;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       if (!IS_FWI2_CAPABLE(ha))
+               return QLA_FUNCTION_FAILED;
+
+       DEBUG11(qla_printk(KERN_INFO, ha,
+               "%s(%ld): entered.\n", __func__, vha->host_no));
+
+       memset(mcp, 0, sizeof(mbx_cmd_t));
+       mcp->mb[0] = MBC_TOGGLE_INTR;
+       mcp->mb[1] = 1;
+
+       mcp->out_mb = MBX_1|MBX_0;
+       mcp->in_mb = MBX_0;
+       mcp->tov = 30;
+       mcp->flags = 0;
+
+       rval = qla2x00_mailbox_command(vha, mcp);
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(qla_printk(KERN_WARNING, ha,
+                       "%s(%ld): failed=%x mb[0]=%x.\n", __func__,
+                       vha->host_no, rval, mcp->mb[0]));
+       } else {
+               DEBUG11(qla_printk(KERN_INFO, ha,
+                       "%s(%ld): done.\n", __func__, vha->host_no));
+       }
+
+       return rval;
+}
+
+int
+qla82xx_mbx_intr_disable(scsi_qla_host_t *vha)
+{
+       int rval;
+       struct qla_hw_data *ha = vha->hw;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+
+       if (!IS_QLA82XX(ha))
+               return QLA_FUNCTION_FAILED;
+
+       DEBUG11(qla_printk(KERN_INFO, ha,
+               "%s(%ld): entered.\n", __func__, vha->host_no));
+
+       memset(mcp, 0, sizeof(mbx_cmd_t));
+       mcp->mb[0] = MBC_TOGGLE_INTR;
+       mcp->mb[1] = 0;
+
+       mcp->out_mb = MBX_1|MBX_0;
+       mcp->in_mb = MBX_0;
+       mcp->tov = 30;
+       mcp->flags = 0;
+
+       rval = qla2x00_mailbox_command(vha, mcp);
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(qla_printk(KERN_WARNING, ha,
+                       "%s(%ld): failed=%x mb[0]=%x.\n", __func__,
+                       vha->host_no, rval, mcp->mb[0]));
+       } else {
+               DEBUG11(qla_printk(KERN_INFO, ha,
+                       "%s(%ld): done.\n", __func__, vha->host_no));
+       }
+
+       return rval;
+}