]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/scsi/be2iscsi/be_main.c
[SCSI] be2iscsi: Enable async mode for mcc rings
[karo-tx-linux.git] / drivers / scsi / be2iscsi / be_main.c
index 1a557fa778887700b42c99c4fe55fb1328039ab7..a6a2c6469677a41733e615f4da45eee8a574b0d7 100644 (file)
@@ -112,6 +112,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
        memset(phba, 0, sizeof(*phba));
        phba->shost = shost;
        phba->pcidev = pci_dev_get(pcidev);
+       pci_set_drvdata(pcidev, phba);
 
        if (iscsi_host_add(shost, &phba->pcidev->dev))
                goto free_devices;
@@ -230,29 +231,27 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)
 
 static void beiscsi_get_params(struct beiscsi_hba *phba)
 {
-       phba->params.ios_per_ctrl = BE2_IO_DEPTH;
-       phba->params.cxns_per_ctrl = BE2_MAX_SESSIONS;
-       phba->params.asyncpdus_per_ctrl = BE2_ASYNCPDUS;
-       phba->params.icds_per_ctrl = BE2_MAX_ICDS / 2;
+       phba->params.ios_per_ctrl = (phba->fw_config.iscsi_icd_count
+                                   - (phba->fw_config.iscsi_cid_count
+                                   + BE2_TMFS
+                                   + BE2_NOPOUT_REQ));
+       phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count;
+       phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count;;
+       phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;;
        phba->params.num_sge_per_io = BE2_SGE;
        phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
        phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ;
        phba->params.eq_timer = 64;
        phba->params.num_eq_entries =
-           (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) /
-                                                               512) + 1) * 512;
+           (((BE2_CMDS_PER_CXN * 2 + phba->fw_config.iscsi_cid_count * 2
+                                   + BE2_TMFS) / 512) + 1) * 512;
        phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024)
                                ? 1024 : phba->params.num_eq_entries;
        SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d \n",
-                phba->params.num_eq_entries);
+                            phba->params.num_eq_entries);
        phba->params.num_cq_entries =
-           (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) /
-                                                               512) + 1) * 512;
-       SE_DEBUG(DBG_LVL_8,
-               "phba->params.num_cq_entries=%d BE2_CMDS_PER_CXN=%d"
-               "BE2_LOGOUTS=%d BE2_TMFS=%d BE2_ASYNCPDUS=%d \n",
-               phba->params.num_cq_entries, BE2_CMDS_PER_CXN,
-               BE2_LOGOUTS, BE2_TMFS, BE2_ASYNCPDUS);
+           (((BE2_CMDS_PER_CXN * 2 +  phba->fw_config.iscsi_cid_count * 2
+                                   + BE2_TMFS) / 512) + 1) * 512;
        phba->params.wrbs_per_cxn = 256;
 }
 
@@ -443,7 +442,7 @@ static irqreturn_t be_isr(int irq, void *dev_id)
                        if (phba->todo_mcc_cq)
                                queue_work(phba->wq, &phba->work_cqs);
 
-               if ((num_mcceq_processed) && (!num_ioeq_processed))
+                       if ((num_mcceq_processed) && (!num_ioeq_processed))
                                hwi_ring_eq_db(phba, eq->id, 0,
                                              (num_ioeq_processed +
                                               num_mcceq_processed) , 1, 1);
@@ -561,6 +560,7 @@ beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,
                SE_DEBUG(DBG_LVL_1, "In ISCSI_OP_REJECT\n");
                break;
        case ISCSI_OP_LOGIN_RSP:
+       case ISCSI_OP_TEXT_RSP:
                task = conn->login_task;
                io_task = task->dd_data;
                login_hdr = (struct iscsi_hdr *)ppdu;
@@ -631,29 +631,29 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
  * alloc_wrb_handle - To allocate a wrb handle
  * @phba: The hba pointer
  * @cid: The cid to use for allocation
- * @index: index allocation and wrb index
  *
  * This happens under session_lock until submission to chip
  */
-struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
-                                   int index)
+struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
 {
        struct hwi_wrb_context *pwrb_context;
        struct hwi_controller *phwi_ctrlr;
-       struct wrb_handle *pwrb_handle;
+       struct wrb_handle *pwrb_handle, *pwrb_handle_tmp;
 
        phwi_ctrlr = phba->phwi_ctrlr;
        pwrb_context = &phwi_ctrlr->wrb_context[cid];
-       if (pwrb_context->wrb_handles_available) {
+       if (pwrb_context->wrb_handles_available >= 2) {
                pwrb_handle = pwrb_context->pwrb_handle_base[
                                            pwrb_context->alloc_index];
                pwrb_context->wrb_handles_available--;
-               pwrb_handle->nxt_wrb_index = pwrb_handle->wrb_index;
                if (pwrb_context->alloc_index ==
                                                (phba->params.wrbs_per_cxn - 1))
                        pwrb_context->alloc_index = 0;
                else
                        pwrb_context->alloc_index++;
+               pwrb_handle_tmp = pwrb_context->pwrb_handle_base[
+                                               pwrb_context->alloc_index];
+               pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index;
        } else
                pwrb_handle = NULL;
        return pwrb_handle;
@@ -790,6 +790,7 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
                memcpy(task->sc->sense_buffer, sense,
                       min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE));
        }
+
        if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) {
                if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
                                                        & SOL_RES_CNT_MASK)
@@ -811,6 +812,7 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
        struct iscsi_conn *conn = beiscsi_conn->conn;
 
        hdr = (struct iscsi_logout_rsp *)task->hdr;
+       hdr->opcode = ISCSI_OP_LOGOUT_RSP;
        hdr->t2wait = 5;
        hdr->t2retain = 0;
        hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
@@ -825,6 +827,9 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
                                        & SOL_EXP_CMD_SN_MASK) +
                        ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
                                        / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       hdr->dlength[0] = 0;
+       hdr->dlength[1] = 0;
+       hdr->dlength[2] = 0;
        hdr->hlength = 0;
        hdr->itt = io_task->libiscsi_itt;
        __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
@@ -839,6 +844,7 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
        struct beiscsi_io_task *io_task = task->dd_data;
 
        hdr = (struct iscsi_tm_rsp *)task->hdr;
+       hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP;
        hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
                                        & SOL_FLAGS_MASK) >> 24) | 0x80;
        hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
@@ -877,7 +883,8 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
        } else {
                pwrb_context = &phwi_ctrlr->wrb_context[((psol->
                                dw[offsetof(struct amap_sol_cqe, cid) / 32] &
-                               SOL_CID_MASK) >> 6)];
+                               SOL_CID_MASK) >> 6) -
+                               phba->fw_config.iscsi_cid_start];
                pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
                                dw[offsetof(struct amap_sol_cqe, wrb_index) /
                                32] & SOL_WRB_INDEX_MASK) >> 16)];
@@ -939,7 +946,8 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
                pwrb_context = &phwi_ctrlr->
                                wrb_context[((psol->dw[offsetof
                                (struct amap_sol_cqe, cid) / 32]
-                               & SOL_CID_MASK) >> 6)];
+                               & SOL_CID_MASK) >> 6) -
+                               phba->fw_config.iscsi_cid_start];
                pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
                                dw[offsetof(struct amap_sol_cqe, wrb_index) /
                                32] & SOL_WRB_INDEX_MASK) >> 16)];
@@ -1077,7 +1085,8 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
 
        WARN_ON(!pasync_handle);
 
-       pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid;
+       pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid -
+                                            phba->fw_config.iscsi_cid_start;
        pasync_handle->is_header = is_header;
        pasync_handle->buffer_len = ((pdpdu_cqe->
                        dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
@@ -1327,9 +1336,10 @@ hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn,
        }
 
        status = beiscsi_process_async_pdu(beiscsi_conn, phba,
-                                          beiscsi_conn->beiscsi_conn_cid,
-                                          phdr, hdr_len, pfirst_buffer,
-                                          buf_len);
+                                          (beiscsi_conn->beiscsi_conn_cid -
+                                           phba->fw_config.iscsi_cid_start),
+                                           phdr, hdr_len, pfirst_buffer,
+                                           buf_len);
 
        if (status == 0)
                hwi_free_async_msg(phba, cri);
@@ -1422,6 +1432,48 @@ static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn,
        hwi_post_async_buffers(phba, pasync_handle->is_header);
 }
 
+static void  beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
+{
+       struct be_queue_info *mcc_cq;
+       struct  be_mcc_compl *mcc_compl;
+       unsigned int num_processed = 0;
+
+       mcc_cq = &phba->ctrl.mcc_obj.cq;
+       mcc_compl = queue_tail_node(mcc_cq);
+       mcc_compl->flags = le32_to_cpu(mcc_compl->flags);
+       while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) {
+
+               if (num_processed >= 32) {
+                       hwi_ring_cq_db(phba, mcc_cq->id,
+                                       num_processed, 0, 0);
+                       num_processed = 0;
+               }
+               if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) {
+                       /* Interpret flags as an async trailer */
+                       if (is_link_state_evt(mcc_compl->flags))
+                               /* Interpret compl as a async link evt */
+                               beiscsi_async_link_state_process(phba,
+                               (struct be_async_event_link_state *) mcc_compl);
+                       else
+                               SE_DEBUG(DBG_LVL_1,
+                                       " Unsupported Async Event, flags"
+                                       " = 0x%08x \n", mcc_compl->flags);
+               } else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) {
+                       be_mcc_compl_process_isr(&phba->ctrl, mcc_compl);
+                       atomic_dec(&phba->ctrl.mcc_obj.q.used);
+               }
+
+               mcc_compl->flags = 0;
+               queue_tail_inc(mcc_cq);
+               mcc_compl = queue_tail_node(mcc_cq);
+               mcc_compl->flags = le32_to_cpu(mcc_compl->flags);
+               num_processed++;
+       }
+
+       if (num_processed > 0)
+               hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0);
+
+}
 
 static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
 {
@@ -1432,6 +1484,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
        unsigned int tot_nump = 0;
        struct beiscsi_conn *beiscsi_conn;
        struct sgl_handle *psgl_handle = NULL;
+       struct beiscsi_endpoint *beiscsi_ep;
+       struct iscsi_endpoint *ep;
        struct beiscsi_hba *phba;
 
        cq = pbe_eq->cq;
@@ -1447,27 +1501,15 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                                      dw[offsetof(struct amap_sol_cqe_ring,
                                      icd_index) / 32] & SOL_ICD_INDEX_MASK)
                                      >> 6)];
-                       beiscsi_conn = phba->conn_table[psgl_handle->cid];
-                       if (!beiscsi_conn || !beiscsi_conn->ep) {
-                               shost_printk(KERN_WARNING, phba->shost,
-                                    "Connection table empty for cid = %d\n",
-                                     psgl_handle->cid);
-                               return 0;
-                       }
-
+                       ep = phba->ep_array[psgl_handle->cid];
                } else {
-                       beiscsi_conn = phba->conn_table[(u32) (sol->
-                                dw[offsetof(struct amap_sol_cqe, cid) / 32] &
-                                SOL_CID_MASK) >> 6];
-
-                       if (!beiscsi_conn || !beiscsi_conn->ep) {
-                               shost_printk(KERN_WARNING, phba->shost,
-                                    "Connection table empty for cid = %d\n",
-                                    (u32)(sol->dw[offsetof(struct amap_sol_cqe,
-                                    cid) / 32] & SOL_CID_MASK) >> 6);
-                               return 0;
-                       }
+                       ep = phba->ep_array[(u32) ((sol->
+                                  dw[offsetof(struct amap_sol_cqe, cid) / 32] &
+                                  SOL_CID_MASK) >> 6) -
+                                  phba->fw_config.iscsi_cid_start];
                }
+               beiscsi_ep = ep->dd_data;
+               beiscsi_conn = beiscsi_ep->conn;
 
                if (num_processed >= 32) {
                        hwi_ring_cq_db(phba, cq->id,
@@ -1557,8 +1599,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                                 "0x%x...\n",
                                 sol->dw[offsetof(struct amap_sol_cqe, code) /
                                 32] & CQE_CODE_MASK,
-                                sol->dw[offsetof(struct amap_sol_cqe, cid) /
-                                32] & CQE_CID_MASK);
+                                (sol->dw[offsetof(struct amap_sol_cqe, cid) /
+                                32] & CQE_CID_MASK));
                        }
                        iscsi_conn_failure(beiscsi_conn->conn,
                                           ISCSI_ERR_CONN_FAILED);
@@ -1575,8 +1617,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                                "received/sent on CID 0x%x...\n",
                                 sol->dw[offsetof(struct amap_sol_cqe, code) /
                                 32] & CQE_CODE_MASK,
-                                sol->dw[offsetof(struct amap_sol_cqe, cid) /
-                                32] & CQE_CID_MASK);
+                                (sol->dw[offsetof(struct amap_sol_cqe, cid) /
+                                32] & CQE_CID_MASK));
                        }
                        iscsi_conn_failure(beiscsi_conn->conn,
                                           ISCSI_ERR_CONN_FAILED);
@@ -1586,8 +1628,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                                 "received on CID 0x%x...\n",
                                 sol->dw[offsetof(struct amap_sol_cqe, code) /
                                 32] & CQE_CODE_MASK,
-                                sol->dw[offsetof(struct amap_sol_cqe, cid) /
-                                32] & CQE_CID_MASK);
+                                (sol->dw[offsetof(struct amap_sol_cqe, cid) /
+                                32] & CQE_CID_MASK));
                        break;
                }
 
@@ -1604,7 +1646,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
        return tot_nump;
 }
 
-static void beiscsi_process_all_cqs(struct work_struct *work)
+void beiscsi_process_all_cqs(struct work_struct *work)
 {
        unsigned long flags;
        struct hwi_controller *phwi_ctrlr;
@@ -1624,6 +1666,7 @@ static void beiscsi_process_all_cqs(struct work_struct *work)
                spin_lock_irqsave(&phba->isr_lock, flags);
                phba->todo_mcc_cq = 0;
                spin_unlock_irqrestore(&phba->isr_lock, flags);
+               beiscsi_process_mcc_isr(phba);
        }
 
        if (phba->todo_cq) {
@@ -2383,7 +2426,7 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba,
                                                     &paddr);
                if (!cq_vaddress)
                        goto create_cq_error;
-               ret = be_fill_queue(cq, phba->params.icds_per_ctrl / 2,
+               ret = be_fill_queue(cq, phba->params.num_cq_entries,
                                    sizeof(struct sol_cqe), cq_vaddress);
                if (ret) {
                        shost_printk(KERN_ERR, phba->shost,
@@ -2634,7 +2677,8 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
                                     "wrbq create failed.");
                        return status;
                }
-               phwi_ctrlr->wrb_context[i].cid = phwi_context->be_wrbq[i].id;
+               phwi_ctrlr->wrb_context[i * 2].cid = phwi_context->be_wrbq[i].
+                                                                  id;
        }
        kfree(pwrb_arr);
        return 0;
@@ -2807,12 +2851,6 @@ static int hwi_init_port(struct beiscsi_hba *phba)
                ring_mode = 1;
        else
                ring_mode = 0;
-       status = mgmt_get_fw_config(ctrl, phba);
-       if (status != 0) {
-               shost_printk(KERN_ERR, phba->shost,
-                            "Error getting fw config\n");
-               goto error;
-       }
 
        status = beiscsi_create_cqs(phba, phwi_context);
        if (status != 0) {
@@ -3032,7 +3070,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
                        AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0);
                        pfrag += phba->params.num_sge_per_io;
                        psgl_handle->sgl_index =
-                               phba->fw_config.iscsi_cid_start + arr_index++;
+                               phba->fw_config.iscsi_icd_start + arr_index++;
                }
                idx++;
        }
@@ -3047,7 +3085,7 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
 {
        int i, new_cid;
 
-       phba->cid_array = kmalloc(sizeof(void *) * phba->params.cxns_per_ctrl,
+       phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl,
                                  GFP_KERNEL);
        if (!phba->cid_array) {
                shost_printk(KERN_ERR, phba->shost,
@@ -3055,7 +3093,7 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
                             "hba_setup_cid_tbls\n");
                return -ENOMEM;
        }
-       phba->ep_array = kmalloc(sizeof(struct iscsi_endpoint *) *
+       phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) *
                                 phba->params.cxns_per_ctrl * 2, GFP_KERNEL);
        if (!phba->ep_array) {
                shost_printk(KERN_ERR, phba->shost,
@@ -3064,7 +3102,7 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
                kfree(phba->cid_array);
                return -ENOMEM;
        }
-       new_cid = phba->fw_config.iscsi_icd_start;
+       new_cid = phba->fw_config.iscsi_cid_start;
        for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
                phba->cid_array[i] = new_cid;
                new_cid += 2;
@@ -3166,6 +3204,7 @@ static void hwi_purge_eq(struct beiscsi_hba *phba)
        struct be_queue_info *eq;
        struct be_eq_entry *eqe = NULL;
        int i, eq_msix;
+       unsigned int num_processed;
 
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -3177,13 +3216,17 @@ static void hwi_purge_eq(struct beiscsi_hba *phba)
        for (i = 0; i < (phba->num_cpus + eq_msix); i++) {
                eq = &phwi_context->be_eq[i].q;
                eqe = queue_tail_node(eq);
-
+               num_processed = 0;
                while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
                                        & EQE_VALID_MASK) {
                        AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
                        queue_tail_inc(eq);
                        eqe = queue_tail_node(eq);
+                       num_processed++;
                }
+
+               if (num_processed)
+                       hwi_ring_eq_db(phba, eq->id, 1, num_processed, 1, 1);
        }
 }
 
@@ -3195,8 +3238,9 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba)
        if (mgmt_status)
                shost_printk(KERN_WARNING, phba->shost,
                             "mgmt_epfw_cleanup FAILED \n");
-       hwi_cleanup(phba);
+
        hwi_purge_eq(phba);
+       hwi_cleanup(phba);
        if (ring_mode)
                kfree(phba->sgl_hndl_array);
        kfree(phba->io_sgl_hndl_base);
@@ -3219,7 +3263,8 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
         * We can always use 0 here because it is reserved by libiscsi for
         * login/startup related tasks.
         */
-       pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid, 0);
+       pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid -
+                                      phba->fw_config.iscsi_cid_start));
        pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb;
        memset(pwrb, 0, sizeof(*pwrb));
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
@@ -3328,8 +3373,9 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
        io_task->bhs_pa.u.a64.address = paddr;
        io_task->libiscsi_itt = (itt_t)task->itt;
        io_task->pwrb_handle = alloc_wrb_handle(phba,
-                                               beiscsi_conn->beiscsi_conn_cid,
-                                               task->itt);
+                                               beiscsi_conn->beiscsi_conn_cid -
+                                               phba->fw_config.iscsi_cid_start
+                                               );
        io_task->conn = beiscsi_conn;
 
        task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr;
@@ -3343,7 +3389,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                        goto free_hndls;
        } else {
                io_task->scsi_cmnd = NULL;
-               if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
+               if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
                        if (!beiscsi_conn->login_in_progress) {
                                spin_lock(&phba->mgmt_sgl_lock);
                                io_task->psgl_handle = (struct sgl_handle *)
@@ -3372,10 +3418,11 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                                (io_task->psgl_handle->sgl_index));
        if (ring_mode) {
                phba->sgl_hndl_array[io_task->psgl_handle->sgl_index -
-                                    phba->fw_config.iscsi_cid_start] =
+                                    phba->fw_config.iscsi_icd_start] =
                                     io_task->psgl_handle;
                io_task->psgl_handle->task = task;
-               io_task->psgl_handle->cid = beiscsi_conn->beiscsi_conn_cid;
+               io_task->psgl_handle->cid = beiscsi_conn->beiscsi_conn_cid  -
+                                           phba->fw_config.iscsi_cid_start;
        } else
                io_task->pwrb_handle->pio_handle = task;
 
@@ -3384,7 +3431,9 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
 
 free_hndls:
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid];
+       pwrb_context = &phwi_ctrlr->wrb_context[
+                       beiscsi_conn->beiscsi_conn_cid -
+                       phba->fw_config.iscsi_cid_start];
        free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
        io_task->pwrb_handle = NULL;
        pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
@@ -3404,7 +3453,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
        struct hwi_controller *phwi_ctrlr;
 
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid];
+       pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid
+                       - phba->fw_config.iscsi_cid_start];
        if (io_task->pwrb_handle) {
                free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
                io_task->pwrb_handle = NULL;
@@ -3519,6 +3569,7 @@ static int beiscsi_mtask(struct iscsi_task *task)
        unsigned int doorbell = 0;
        unsigned int i, cid;
        struct iscsi_task *aborted_task;
+       unsigned int tag;
 
        cid = beiscsi_conn->beiscsi_conn_cid;
        pwrb = io_task->pwrb_handle->pwrb;
@@ -3546,6 +3597,10 @@ static int beiscsi_mtask(struct iscsi_task *task)
                else
                        AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
                                      INI_RD_CMD);
+               if (task->hdr->ttt == ISCSI_RESERVED_TAG)
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+               else
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_TEXT:
@@ -3554,6 +3609,7 @@ static int beiscsi_mtask(struct iscsi_task *task)
                else
                        AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
                                      INI_WR_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
                AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
                hwi_write_buffer(pwrb, task);
                break;
@@ -3561,7 +3617,8 @@ static int beiscsi_mtask(struct iscsi_task *task)
                session = conn->session;
                i = ((struct iscsi_tm *)task->hdr)->rtt;
                phwi_ctrlr = phba->phwi_ctrlr;
-               pwrb_context = &phwi_ctrlr->wrb_context[cid];
+               pwrb_context = &phwi_ctrlr->wrb_context[cid -
+                                           phba->fw_config.iscsi_cid_start];
                pwrb_handle = pwrb_context->pwrb_handle_basestd[be32_to_cpu(i)
                                                                >> 16];
                aborted_task = pwrb_handle->pio_handle;
@@ -3572,9 +3629,18 @@ static int beiscsi_mtask(struct iscsi_task *task)
                if (!aborted_io_task->scsi_cmnd)
                        return 0;
 
-               mgmt_invalidate_icds(phba,
+               tag = mgmt_invalidate_icds(phba,
                                     aborted_io_task->psgl_handle->sgl_index,
                                     cid);
+               if (!tag) {
+                       shost_printk(KERN_WARNING, phba->shost,
+                                    "mgmt_invalidate_icds could not be"
+                                    " submitted\n");
+               } else {
+                       wait_event_interruptible(phba->ctrl.mcc_wait[tag],
+                                                phba->ctrl.mcc_numtag[tag]);
+                       free_mcc_tag(&phba->ctrl, tag);
+               }
                if (ring_mode)
                        io_task->psgl_handle->type = INI_TMF_CMD;
                else
@@ -3600,7 +3666,7 @@ static int beiscsi_mtask(struct iscsi_task *task)
        }
 
        AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
-                     be32_to_cpu(task->data_count));
+                     task->data_count);
        AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
                      io_task->pwrb_handle->nxt_wrb_index);
        be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
@@ -3649,7 +3715,6 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
        return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
 }
 
-
 static void beiscsi_remove(struct pci_dev *pcidev)
 {
        struct beiscsi_hba *phba = NULL;
@@ -3734,7 +3799,6 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
        }
        SE_DEBUG(DBG_LVL_8, " phba = %p \n", phba);
 
-       pci_set_drvdata(pcidev, phba);
        if (enable_msix)
                num_cpus = find_num_cpus();
        else
@@ -3754,6 +3818,14 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
        spin_lock_init(&phba->io_sgl_lock);
        spin_lock_init(&phba->mgmt_sgl_lock);
        spin_lock_init(&phba->isr_lock);
+       ret = mgmt_get_fw_config(&phba->ctrl, phba);
+       if (ret != 0) {
+               shost_printk(KERN_ERR, phba->shost,
+                            "Error getting fw config\n");
+               goto free_port;
+       }
+       phba->shost->max_id = phba->fw_config.iscsi_cid_count;
+       phba->shost->can_queue = phba->params.ios_per_ctrl;
        beiscsi_get_params(phba);
        ret = beiscsi_init_port(phba);
        if (ret < 0) {
@@ -3762,6 +3834,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                goto free_port;
        }
 
+       for (i = 0; i < MAX_MCC_CMD ; i++) {
+               init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]);
+               phba->ctrl.mcc_tag[i] = i + 1;
+               phba->ctrl.mcc_numtag[i + 1] = 0;
+               phba->ctrl.mcc_tag_available++;
+       }
+
+       phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0;
+
        snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
                 phba->shost->host_no);
        phba->wq = create_workqueue(phba->wq_name);
@@ -3859,7 +3940,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
                ISCSI_USERNAME | ISCSI_PASSWORD |
                ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
                ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
-               ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+               ISCSI_LU_RESET_TMO |
                ISCSI_PING_TMO | ISCSI_RECV_TMO |
                ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
        .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |