]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/qla2xxx/qla_mbx.c
Merge branch 'for-linus' of git://git.o-hand.com/linux-mfd
[linux-2.6-omap-h63xx.git] / drivers / scsi / qla2xxx / qla_mbx.c
index bbe7181fb3d576f0bf9937f84bac8050a65ef307..f94ffbb98e95f2a53918888ed76ebf235b3aa5cc 100644 (file)
@@ -58,14 +58,11 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
         * seconds. This is to serialize actual issuing of mailbox cmds during
         * non ISP abort time.
         */
-       if (!abort_active) {
-               if (!wait_for_completion_timeout(&ha->mbx_cmd_comp,
-                   mcp->tov * HZ)) {
-                       /* Timeout occurred. Return error. */
-                       DEBUG2_3_11(printk("%s(%ld): cmd access timeout. "
-                           "Exiting.\n", __func__, base_vha->host_no));
-                       return QLA_FUNCTION_TIMEOUT;
-               }
+       if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) {
+               /* Timeout occurred. Return error. */
+               DEBUG2_3_11(printk("%s(%ld): cmd access timeout. "
+                   "Exiting.\n", __func__, base_vha->host_no));
+               return QLA_FUNCTION_TIMEOUT;
        }
 
        ha->flags.mbox_busy = 1;
@@ -123,8 +120,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 
        /* Wait for mbx cmd completion until timeout */
 
-       if (!abort_active && io_lock_on) {
-
+       if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
                set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
 
                if (IS_FWI2_CAPABLE(ha))
@@ -153,7 +149,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                                break;
 
                        /* Check for pending interrupts. */
-                       qla2x00_poll(ha->rsp);
+                       qla2x00_poll(ha->rsp_q_map[0]);
 
                        if (command != MBC_LOAD_RISC_RAM_EXTENDED &&
                            !ha->flags.mbox_int)
@@ -218,12 +214,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        /* Clean up */
        ha->mcp = NULL;
 
-       if (abort_active || !io_lock_on) {
+       if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) {
                DEBUG11(printk("%s(%ld): checking for additional resp "
                    "interrupt.\n", __func__, base_vha->host_no));
 
                /* polling mode for non isp_abort commands. */
-               qla2x00_poll(ha->rsp);
+               qla2x00_poll(ha->rsp_q_map[0]);
        }
 
        if (rval == QLA_FUNCTION_TIMEOUT &&
@@ -266,8 +262,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        }
 
        /* Allow next mbx cmd to come in. */
-       if (!abort_active)
-               complete(&ha->mbx_cmd_comp);
+       complete(&ha->mbx_cmd_comp);
 
        if (rval) {
                DEBUG2_3_11(printk("%s(%ld): **** FAILED. mbx0=%x, mbx1=%x, "
@@ -412,7 +407,8 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
  */
 void
 qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
-    uint16_t *subminor, uint16_t *attributes, uint32_t *memory)
+    uint16_t *subminor, uint16_t *attributes, uint32_t *memory, uint8_t *mpi,
+    uint32_t *mpi_caps)
 {
        int             rval;
        mbx_cmd_t       mc;
@@ -423,6 +419,8 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
        mcp->mb[0] = MBC_GET_FIRMWARE_VERSION;
        mcp->out_mb = MBX_0;
        mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+       if (IS_QLA81XX(vha->hw))
+               mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
        mcp->flags = 0;
        mcp->tov = MBX_TOV_SECONDS;
        rval = qla2x00_mailbox_command(vha, mcp);
@@ -436,6 +434,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
                *memory = 0x1FFFF;                      /* Defaults to 128KB. */
        else
                *memory = (mcp->mb[5] << 16) | mcp->mb[4];
+       if (IS_QLA81XX(vha->hw)) {
+               mpi[0] = mcp->mb[10] >> 8;
+               mpi[1] = mcp->mb[10] & 0xff;
+               mpi[2] = mcp->mb[11] >> 8;
+               mpi[3] = mcp->mb[11] & 0xff;
+               *mpi_caps = (mcp->mb[12] << 16) | mcp->mb[13];
+       }
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
@@ -568,7 +573,6 @@ int
 qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
 {
        int rval;
-       struct qla_hw_data *ha = vha->hw;
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
@@ -595,14 +599,6 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
                if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
                    mcp->mb[7] != 0x2525)
                        rval = QLA_FUNCTION_FAILED;
-               if (rval == QLA_FUNCTION_FAILED) {
-                       struct device_reg_24xx __iomem *reg =
-                           &ha->iobase->isp24;
-
-                       qla2xxx_hw_event_log(vha, HW_EVENT_ISP_ERR, 0,
-                           LSW(RD_REG_DWORD(&reg->hccr)),
-                           LSW(RD_REG_DWORD(&reg->istatus)));
-               }
        }
 
        if (rval != QLA_SUCCESS) {
@@ -713,8 +709,6 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer,
                /*EMPTY*/
                DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n",
                    vha->host_no, rval));
-               DEBUG2(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n",
-                   vha->host_no, rval));
        } else {
                sts_entry_t *sts_entry = (sts_entry_t *) buffer;
 
@@ -749,16 +743,15 @@ qla2x00_issue_iocb(scsi_qla_host_t *vha, void *buffer, dma_addr_t phys_addr,
  *     Kernel context.
  */
 int
-qla2x00_abort_command(scsi_qla_host_t *vha, srb_t *sp)
+qla2x00_abort_command(scsi_qla_host_t *vha, srb_t *sp, struct req_que *req)
 {
        unsigned long   flags = 0;
        fc_port_t       *fcport;
        int             rval;
-       uint32_t        handle;
+       uint32_t        handle = 0;
        mbx_cmd_t       mc;
        mbx_cmd_t       *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
-       struct req_que *req = ha->req;
 
        DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", vha->host_no));
 
@@ -808,11 +801,15 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l)
        mbx_cmd_t  mc;
        mbx_cmd_t  *mcp = &mc;
        scsi_qla_host_t *vha;
+       struct req_que *req;
+       struct rsp_que *rsp;
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
 
        l = l;
        vha = fcport->vha;
+       req = vha->hw->req_q_map[0];
+       rsp = vha->hw->rsp_q_map[0];
        mcp->mb[0] = MBC_ABORT_TARGET;
        mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
        if (HAS_EXTENDED_IDS(vha->hw)) {
@@ -835,7 +832,8 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l)
        }
 
        /* Issue marker IOCB. */
-       rval2 = qla2x00_marker(vha, fcport->loop_id, 0, MK_SYNC_ID);
+       rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, 0,
+                                                       MK_SYNC_ID);
        if (rval2 != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
                    "(%x).\n", __func__, vha->host_no, rval2));
@@ -853,10 +851,14 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l)
        mbx_cmd_t  mc;
        mbx_cmd_t  *mcp = &mc;
        scsi_qla_host_t *vha;
+       struct req_que *req;
+       struct rsp_que *rsp;
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
 
        vha = fcport->vha;
+       req = vha->hw->req_q_map[0];
+       rsp = vha->hw->rsp_q_map[0];
        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))
@@ -877,7 +879,8 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l)
        }
 
        /* Issue marker IOCB. */
-       rval2 = qla2x00_marker(vha, fcport->loop_id, l, MK_SYNC_ID_LUN);
+       rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
+                                                               MK_SYNC_ID_LUN);
        if (rval2 != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
                    "(%x).\n", __func__, vha->host_no, rval2));
@@ -1356,7 +1359,13 @@ qla2x00_lip_reset(scsi_qla_host_t *vha)
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
 
-       if (IS_FWI2_CAPABLE(vha->hw)) {
+       if (IS_QLA81XX(vha->hw)) {
+               /* Logout across all FCFs. */
+               mcp->mb[0] = MBC_LIP_FULL_LOGIN;
+               mcp->mb[1] = BIT_1;
+               mcp->mb[2] = 0;
+               mcp->out_mb = MBX_2|MBX_1|MBX_0;
+       } else if (IS_FWI2_CAPABLE(vha->hw)) {
                mcp->mb[0] = MBC_LIP_FULL_LOGIN;
                mcp->mb[1] = BIT_6;
                mcp->mb[2] = 0;
@@ -1743,6 +1752,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
        lg->port_id[1] = area;
        lg->port_id[2] = domain;
        lg->vp_index = vha->vp_idx;
+
        rval = qla2x00_issue_iocb(vha, lg, lg_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
@@ -1753,9 +1763,9 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
                    lg->entry_status));
                rval = QLA_FUNCTION_FAILED;
        } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) {
-               DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+               DEBUG2_3_11(printk("%s(%ld %d): failed to complete IOCB "
                    "-- completion status (%x)  ioparam=%x/%x.\n", __func__,
-                   vha->host_no, le16_to_cpu(lg->comp_status),
+                   vha->host_no, vha->vp_idx, le16_to_cpu(lg->comp_status),
                    le32_to_cpu(lg->io_parameter[0]),
                    le32_to_cpu(lg->io_parameter[1])));
        } else {
@@ -1845,6 +1855,9 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha)
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
+       if (IS_QLA81XX(vha->hw))
+           return QLA_SUCCESS;
+
        DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n",
            vha->host_no));
 
@@ -2173,7 +2186,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
 }
 
 int
-qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp)
+qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp, struct req_que *req)
 {
        int             rval;
        fc_port_t       *fcport;
@@ -2183,7 +2196,6 @@ qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp)
        dma_addr_t      abt_dma;
        uint32_t        handle;
        struct qla_hw_data *ha = vha->hw;
-       struct req_que *req = ha->req;
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
 
@@ -2216,6 +2228,9 @@ qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp)
        abt->port_id[1] = fcport->d_id.b.area;
        abt->port_id[2] = fcport->d_id.b.domain;
        abt->vp_index = fcport->vp_idx;
+
+       abt->req_que_no = cpu_to_le16(req->id);
+
        rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0);
        if (rval != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n",
@@ -2255,11 +2270,15 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
        dma_addr_t      tsk_dma;
        scsi_qla_host_t *vha;
        struct qla_hw_data *ha;
+       struct req_que *req;
+       struct rsp_que *rsp;
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no));
 
        vha = fcport->vha;
        ha = vha->hw;
+       req = ha->req_q_map[0];
+       rsp = ha->rsp_q_map[0];
        tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
        if (tsk == NULL) {
                DEBUG2_3(printk("%s(%ld): failed to allocate Task Management "
@@ -2301,7 +2320,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
        }
 
        /* Issue marker IOCB. */
-       rval2 = qla2x00_marker(vha, fcport->loop_id, l,
+       rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
            type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID);
        if (rval2 != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
@@ -2498,7 +2517,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
 
-       if (!IS_QLA25XX(vha->hw))
+       if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw))
                return QLA_FUNCTION_FAILED;
 
        DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
@@ -3069,3 +3088,108 @@ verify_done:
 
        return rval;
 }
+
+int
+qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
+       uint8_t options)
+{
+       int rval;
+       unsigned long flags;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+       struct device_reg_25xxmq __iomem *reg;
+       struct qla_hw_data *ha = vha->hw;
+
+       mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
+       mcp->mb[1] = options;
+       mcp->mb[2] = MSW(LSD(req->dma));
+       mcp->mb[3] = LSW(LSD(req->dma));
+       mcp->mb[6] = MSW(MSD(req->dma));
+       mcp->mb[7] = LSW(MSD(req->dma));
+       mcp->mb[5] = req->length;
+       if (req->rsp)
+               mcp->mb[10] = req->rsp->id;
+       mcp->mb[12] = req->qos;
+       mcp->mb[11] = req->vp_idx;
+       mcp->mb[13] = req->rid;
+
+       reg = (struct device_reg_25xxmq *)((void *)(ha->mqiobase) +
+               QLA_QUE_PAGE * req->id);
+
+       mcp->mb[4] = req->id;
+       /* que in ptr index */
+       mcp->mb[8] = 0;
+       /* que out ptr index */
+       mcp->mb[9] = 0;
+       mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7|
+                       MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_0;
+       mcp->flags = MBX_DMA_OUT;
+       mcp->tov = 60;
+
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       if (!(options & BIT_0)) {
+               WRT_REG_DWORD(&reg->req_q_in, 0);
+               WRT_REG_DWORD(&reg->req_q_out, 0);
+       }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+       rval = qla2x00_mailbox_command(vha, mcp);
+       if (rval != QLA_SUCCESS)
+               DEBUG2_3_11(printk(KERN_WARNING "%s(%ld): failed=%x mb0=%x.\n",
+                       __func__, vha->host_no, rval, mcp->mb[0]));
+       return rval;
+}
+
+int
+qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
+       uint8_t options)
+{
+       int rval;
+       unsigned long flags;
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+       struct device_reg_25xxmq __iomem *reg;
+       struct qla_hw_data *ha = vha->hw;
+
+       mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
+       mcp->mb[1] = options;
+       mcp->mb[2] = MSW(LSD(rsp->dma));
+       mcp->mb[3] = LSW(LSD(rsp->dma));
+       mcp->mb[6] = MSW(MSD(rsp->dma));
+       mcp->mb[7] = LSW(MSD(rsp->dma));
+       mcp->mb[5] = rsp->length;
+       mcp->mb[11] = rsp->vp_idx;
+       mcp->mb[14] = rsp->msix->entry;
+       mcp->mb[13] = rsp->rid;
+
+       reg = (struct device_reg_25xxmq *)((void *)(ha->mqiobase) +
+               QLA_QUE_PAGE * rsp->id);
+
+       mcp->mb[4] = rsp->id;
+       /* que in ptr index */
+       mcp->mb[8] = 0;
+       /* que out ptr index */
+       mcp->mb[9] = 0;
+       mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7
+                       |MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_0;
+       mcp->flags = MBX_DMA_OUT;
+       mcp->tov = 60;
+
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       if (!(options & BIT_0)) {
+               WRT_REG_DWORD(&reg->rsp_q_out, 0);
+               WRT_REG_DWORD(&reg->rsp_q_in, 0);
+       }
+
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+       rval = qla2x00_mailbox_command(vha, mcp);
+       if (rval != QLA_SUCCESS)
+               DEBUG2_3_11(printk(KERN_WARNING "%s(%ld): failed=%x "
+                       "mb0=%x.\n", __func__,
+                       vha->host_no, rval, mcp->mb[0]));
+       return rval;
+}
+