Merge tag 'fixes-for-v3.8-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi...
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / be2iscsi / be_main.c
index 9e669cec3424194577df793ce8f189e9b32baae5..48d37dded8f16fbd64290aa599b187d54b9baef3 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2011 Emulex
+ * Copyright (C) 2005 - 2012 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -152,9 +152,11 @@ BEISCSI_RW_ATTR(log_enable, 0x00,
                "\t\t\t\tConfiguration Path     : 0x20\n");
 
 DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL);
+DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL);
 struct device_attribute *beiscsi_attrs[] = {
        &dev_attr_beiscsi_log_enable,
        &dev_attr_beiscsi_drvr_ver,
+       &dev_attr_beiscsi_adapter_family,
        NULL,
 };
 
@@ -265,11 +267,9 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
                                    nonemb_cmd.va, nonemb_cmd.dma);
 
                return FAILED;
-       } else {
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
-               free_mcc_tag(&phba->ctrl, tag);
        }
+
+       beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
        pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                            nonemb_cmd.va, nonemb_cmd.dma);
        return iscsi_eh_abort(sc);
@@ -340,11 +340,9 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
                pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                                    nonemb_cmd.va, nonemb_cmd.dma);
                return FAILED;
-       } else {
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
-               free_mcc_tag(&phba->ctrl, tag);
        }
+
+       beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
        pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                            nonemb_cmd.va, nonemb_cmd.dma);
        return iscsi_eh_device_reset(sc);
@@ -1248,7 +1246,8 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
 
 static void
 be_complete_io(struct beiscsi_conn *beiscsi_conn,
-              struct iscsi_task *task, struct sol_cqe *psol)
+               struct iscsi_task *task,
+               struct common_sol_cqe *csol_cqe)
 {
        struct beiscsi_io_task *io_task = task->dd_data;
        struct be_status_bhs *sts_bhs =
@@ -1258,20 +1257,14 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
        u32 resid = 0, exp_cmdsn, max_cmdsn;
        u8 rsp, status, flags;
 
-       exp_cmdsn = (psol->
-                       dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-                       & SOL_EXP_CMD_SN_MASK);
-       max_cmdsn = ((psol->
-                       dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-                       & SOL_EXP_CMD_SN_MASK) +
-                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-                               / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
-       rsp = ((psol->dw[offsetof(struct amap_sol_cqe, i_resp) / 32]
-                                               & SOL_RESP_MASK) >> 16);
-       status = ((psol->dw[offsetof(struct amap_sol_cqe, i_sts) / 32]
-                                               & SOL_STS_MASK) >> 8);
-       flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-                                       & SOL_FLAGS_MASK) >> 24) | 0x80;
+       exp_cmdsn = csol_cqe->exp_cmdsn;
+       max_cmdsn = (csol_cqe->exp_cmdsn +
+                    csol_cqe->cmd_wnd - 1);
+       rsp = csol_cqe->i_resp;
+       status = csol_cqe->i_sts;
+       flags = csol_cqe->i_flags;
+       resid = csol_cqe->res_cnt;
+
        if (!task->sc) {
                if (io_task->scsi_cmnd)
                        scsi_dma_unmap(io_task->scsi_cmnd);
@@ -1286,9 +1279,6 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
 
        /* bidi not initially supported */
        if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) {
-               resid = (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) /
-                               32] & SOL_RES_CNT_MASK);
-
                if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW))
                        task->sc->result = DID_ERROR << 16;
 
@@ -1310,13 +1300,8 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
                       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)
-                        conn->rxdata_octets += (psol->
-                            dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
-                            & SOL_RES_CNT_MASK);
-       }
+       if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ)
+               conn->rxdata_octets += resid;
 unmap:
        scsi_dma_unmap(io_task->scsi_cmnd);
        iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn);
@@ -1324,7 +1309,8 @@ unmap:
 
 static void
 be_complete_logout(struct beiscsi_conn *beiscsi_conn,
-                  struct iscsi_task *task, struct sol_cqe *psol)
+                   struct iscsi_task *task,
+                   struct common_sol_cqe *csol_cqe)
 {
        struct iscsi_logout_rsp *hdr;
        struct beiscsi_io_task *io_task = task->dd_data;
@@ -1334,18 +1320,11 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
        hdr->opcode = ISCSI_OP_LOGOUT_RSP;
        hdr->t2wait = 5;
        hdr->t2retain = 0;
-       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) /
-                                       32] & SOL_RESP_MASK);
-       hdr->exp_cmdsn = cpu_to_be32(psol->
-                       dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-                                       & SOL_EXP_CMD_SN_MASK);
-       hdr->max_cmdsn = be32_to_cpu((psol->
-                        dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
-                                       & SOL_EXP_CMD_SN_MASK) +
-                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-                                       / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       hdr->flags = csol_cqe->i_flags;
+       hdr->response = csol_cqe->i_resp;
+       hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
+       hdr->max_cmdsn = (csol_cqe->exp_cmdsn + csol_cqe->cmd_wnd - 1);
+
        hdr->dlength[0] = 0;
        hdr->dlength[1] = 0;
        hdr->dlength[2] = 0;
@@ -1356,7 +1335,8 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
 
 static void
 be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
-               struct iscsi_task *task, struct sol_cqe *psol)
+                struct iscsi_task *task,
+                struct common_sol_cqe *csol_cqe)
 {
        struct iscsi_tm_rsp *hdr;
        struct iscsi_conn *conn = beiscsi_conn->conn;
@@ -1364,16 +1344,12 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
 
        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) /
-                                       32] & SOL_RESP_MASK);
-       hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
-                                   i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
-       hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
-                       i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
-                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-                       / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       hdr->flags = csol_cqe->i_flags;
+       hdr->response = csol_cqe->i_resp;
+       hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
+       hdr->max_cmdsn = (csol_cqe->exp_cmdsn +
+                         csol_cqe->cmd_wnd - 1);
+
        hdr->itt = io_task->libiscsi_itt;
        __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
 }
@@ -1389,15 +1365,24 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
        struct beiscsi_io_task *io_task;
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct iscsi_session *session = conn->session;
+       uint16_t wrb_index, cid;
 
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[((psol->
-                               dw[offsetof(struct amap_sol_cqe, cid) / 32] &
-                               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)];
+       if (chip_skh_r(phba->pcidev)) {
+               wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+                                         wrb_idx, psol);
+               cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+                                   cid, psol);
+       } else {
+               wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+                                         wrb_idx, psol);
+               cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+                                   cid, psol);
+       }
+
+       pwrb_context = &phwi_ctrlr->wrb_context[
+                       cid - phba->fw_config.iscsi_cid_start];
+       pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index];
        task = pwrb_handle->pio_handle;
 
        io_task = task->dd_data;
@@ -1411,26 +1396,78 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
 
 static void
 be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
-                      struct iscsi_task *task, struct sol_cqe *psol)
+                       struct iscsi_task *task,
+                       struct common_sol_cqe *csol_cqe)
 {
        struct iscsi_nopin *hdr;
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct beiscsi_io_task *io_task = task->dd_data;
 
        hdr = (struct iscsi_nopin *)task->hdr;
-       hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
-                       & SOL_FLAGS_MASK) >> 24) | 0x80;
-       hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
-                                    i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
-       hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
-                       i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
-                       ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
-                       / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
+       hdr->flags = csol_cqe->i_flags;
+       hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn);
+       hdr->max_cmdsn = be32_to_cpu(hdr->exp_cmdsn +
+                        csol_cqe->cmd_wnd - 1);
+
        hdr->opcode = ISCSI_OP_NOOP_IN;
        hdr->itt = io_task->libiscsi_itt;
        __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
 }
 
+static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
+               struct sol_cqe *psol,
+               struct common_sol_cqe *csol_cqe)
+{
+       if (chip_skh_r(phba->pcidev)) {
+               csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                   i_exp_cmd_sn, psol);
+               csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                 i_res_cnt, psol);
+               csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                   wrb_index, psol);
+               csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                             cid, psol);
+               csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                hw_sts, psol);
+               csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_cmd_wnd, psol);
+               if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                 cmd_cmpl, psol))
+                       csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                       i_sts, psol);
+               else
+                       csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                        i_sts, psol);
+               if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                 u, psol))
+                       csol_cqe->i_flags = ISCSI_FLAG_CMD_UNDERFLOW;
+
+               if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                 o, psol))
+                       csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW;
+       } else {
+               csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                   i_exp_cmd_sn, psol);
+               csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_res_cnt, psol);
+               csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_cmd_wnd, psol);
+               csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                   wrb_index, psol);
+               csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe,
+                                             cid, psol);
+               csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                hw_sts, psol);
+               csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                i_resp, psol);
+               csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+                                               i_sts, psol);
+               csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_flags, psol);
+       }
+}
+
+
 static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
                             struct beiscsi_hba *phba, struct sol_cqe *psol)
 {
@@ -1442,19 +1479,22 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
        unsigned int type;
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct iscsi_session *session = conn->session;
+       struct common_sol_cqe csol_cqe = {0};
 
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[((psol->dw[offsetof
-                               (struct amap_sol_cqe, cid) / 32]
-                               & 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)];
+
+       /* Copy the elements to a common structure */
+       adapter_get_sol_cqe(phba, psol, &csol_cqe);
+
+       pwrb_context = &phwi_ctrlr->wrb_context[
+                       csol_cqe.cid - phba->fw_config.iscsi_cid_start];
+
+       pwrb_handle = pwrb_context->pwrb_handle_basestd[
+                     csol_cqe.wrb_index];
+
        task = pwrb_handle->pio_handle;
        pwrb = pwrb_handle->pwrb;
-       type = (pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] &
-                                WRB_TYPE_MASK) >> 28;
+       type = ((struct beiscsi_io_task *)task->dd_data)->wrb_type;
 
        spin_lock_bh(&session->lock);
        switch (type) {
@@ -1462,17 +1502,16 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
        case HWH_TYPE_IO_RD:
                if ((task->hdr->opcode & ISCSI_OPCODE_MASK) ==
                     ISCSI_OP_NOOP_OUT)
-                       be_complete_nopin_resp(beiscsi_conn, task, psol);
+                       be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe);
                else
-                       be_complete_io(beiscsi_conn, task, psol);
+                       be_complete_io(beiscsi_conn, task, &csol_cqe);
                break;
 
        case HWH_TYPE_LOGOUT:
                if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
-                       be_complete_logout(beiscsi_conn, task, psol);
+                       be_complete_logout(beiscsi_conn, task, &csol_cqe);
                else
-                       be_complete_tmf(beiscsi_conn, task, psol);
-
+                       be_complete_tmf(beiscsi_conn, task, &csol_cqe);
                break;
 
        case HWH_TYPE_LOGIN:
@@ -1483,7 +1522,7 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
                break;
 
        case HWH_TYPE_NOP:
-               be_complete_nopin_resp(beiscsi_conn, task, psol);
+               be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe);
                break;
 
        default:
@@ -1491,10 +1530,8 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
                            "BM_%d : In hwi_complete_cmd, unknown type = %d"
                            "wrb_index 0x%x CID 0x%x\n", type,
-                           ((psol->dw[offsetof(struct amap_iscsi_wrb,
-                           type) / 32] & SOL_WRB_INDEX_MASK) >> 16),
-                           ((psol->dw[offsetof(struct amap_sol_cqe,
-                           cid) / 32] & SOL_CID_MASK) >> 6));
+                           csol_cqe.wrb_index,
+                           csol_cqe.cid);
                break;
        }
 
@@ -1522,13 +1559,26 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
        struct list_head *pbusy_list;
        struct async_pdu_handle *pasync_handle = NULL;
        unsigned char is_header = 0;
+       unsigned int index, dpl;
+
+       if (chip_skh_r(phba->pcidev)) {
+               dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+                                   dpl, pdpdu_cqe);
+               index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+                                     index, pdpdu_cqe);
+       } else {
+               dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+                                   dpl, pdpdu_cqe);
+               index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+                                     index, pdpdu_cqe);
+       }
 
        phys_addr.u.a32.address_lo =
-           pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_lo) / 32] -
-           ((pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
-                                               & PDUCQE_DPL_MASK) >> 16);
+               (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
+                                       db_addr_lo) / 32] - dpl);
        phys_addr.u.a32.address_hi =
-           pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_hi) / 32];
+               pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
+                                      db_addr_hi) / 32];
 
        phys_addr.u.a64.address =
                        *((unsigned long long *)(&phys_addr.u.a64.address));
@@ -1538,14 +1588,12 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
        case UNSOL_HDR_NOTIFY:
                is_header = 1;
 
-               pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1,
-                       (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
-                       index) / 32] & PDUCQE_INDEX_MASK));
+                pbusy_list = hwi_get_async_busy_list(pasync_ctx,
+                                                     is_header, index);
                break;
        case UNSOL_DATA_NOTIFY:
-               pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe->
-                                       dw[offsetof(struct amap_i_t_dpdu_cqe,
-                                       index) / 32] & PDUCQE_INDEX_MASK));
+                pbusy_list = hwi_get_async_busy_list(pasync_ctx,
+                                                     is_header, index);
                break;
        default:
                pbusy_list = NULL;
@@ -1568,12 +1616,9 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
        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]
-                       & PDUCQE_DPL_MASK) >> 16);
+       pasync_handle->buffer_len = dpl;
+       *pcq_index = index;
 
-       *pcq_index = (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
-                       index) / 32] & PDUCQE_INDEX_MASK);
        return pasync_handle;
 }
 
@@ -1979,12 +2024,24 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
               CQE_VALID_MASK) {
                be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));
 
-               cid = ((sol->dw[offsetof(struct amap_sol_cqe, cid)/32] &
-                     CQE_CID_MASK) >> 6);
-               code = (sol->dw[offsetof(struct amap_sol_cqe, code)/32] &
-                      CQE_CODE_MASK);
-               ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];
+                code = (sol->dw[offsetof(struct amap_sol_cqe, code) /
+                        32] & CQE_CODE_MASK);
+
+                /* Get the CID */
+               if (chip_skh_r(phba->pcidev)) {
+                       if ((code == DRIVERMSG_NOTIFY) ||
+                           (code == UNSOL_HDR_NOTIFY) ||
+                           (code == UNSOL_DATA_NOTIFY))
+                               cid = AMAP_GET_BITS(
+                                                   struct amap_i_t_dpdu_cqe_v2,
+                                                   cid, sol);
+                        else
+                                cid = AMAP_GET_BITS(struct amap_sol_cqe_v2,
+                                                    cid, sol);
+                  } else
+                        cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol);
 
+               ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];
                beiscsi_ep = ep->dd_data;
                beiscsi_conn = beiscsi_ep->conn;
 
@@ -3810,12 +3867,9 @@ static void hwi_disable_intr(struct beiscsi_hba *phba)
 static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
 {
        struct be_cmd_get_session_resp *session_resp;
-       struct be_mcc_wrb *wrb;
        struct be_dma_mem nonemb_cmd;
-       unsigned int tag, wrb_num;
-       unsigned short status, extd_status;
+       unsigned int tag;
        unsigned int s_handle;
-       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
        int ret = -ENOMEM;
 
        /* Get the session handle of the boot target */
@@ -3848,25 +3902,16 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
                            " Failed\n");
 
                goto boot_freemem;
-       } else
-               wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                        phba->ctrl.mcc_numtag[tag]);
+       }
 
-       wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
-       extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
-       status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
-       if (status || extd_status) {
+       ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
+       if (ret) {
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
-                           "BM_%d : beiscsi_get_session_info Failed"
-                           " status = %d extd_status = %d\n",
-                           status, extd_status);
-
-               free_mcc_tag(&phba->ctrl, tag);
+                           "BM_%d : beiscsi_get_session_info Failed");
                goto boot_freemem;
        }
-       wrb = queue_get_wrb(mccq, wrb_num);
-       free_mcc_tag(&phba->ctrl, tag);
+
        session_resp = nonemb_cmd.va ;
 
        memcpy(&phba->boot_sess, &session_resp->session_info,
@@ -4582,9 +4627,13 @@ static int beiscsi_bsg_request(struct bsg_job *job)
                        pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                                            nonemb_cmd.va, nonemb_cmd.dma);
                        return -EAGAIN;
-               } else
-                       wait_event_interruptible(phba->ctrl.mcc_wait[tag],
-                                                phba->ctrl.mcc_numtag[tag]);
+               }
+
+               rc = wait_event_interruptible_timeout(
+                                       phba->ctrl.mcc_wait[tag],
+                                       phba->ctrl.mcc_numtag[tag],
+                                       msecs_to_jiffies(
+                                       BEISCSI_HOST_MBX_TIMEOUT));
                extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
                status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
                free_mcc_tag(&phba->ctrl, tag);
@@ -4668,6 +4717,8 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba)
                            phba->ctrl.mbox_mem_alloced.size,
                            phba->ctrl.mbox_mem_alloced.va,
                            phba->ctrl.mbox_mem_alloced.dma);
+
+       cancel_delayed_work_sync(&phba->beiscsi_hw_check_task);
 }
 
 static void beiscsi_remove(struct pci_dev *pcidev)
@@ -4720,6 +4771,25 @@ static void beiscsi_msix_enable(struct beiscsi_hba *phba)
        return;
 }
 
+/*
+ * beiscsi_hw_health_check()- Check adapter health
+ * @work: work item to check HW health
+ *
+ * Check if adapter in an unrecoverable state or not.
+ **/
+static void
+beiscsi_hw_health_check(struct work_struct *work)
+{
+       struct beiscsi_hba *phba =
+               container_of(work, struct beiscsi_hba,
+                            beiscsi_hw_check_task.work);
+
+       beiscsi_ue_detect(phba);
+
+       schedule_delayed_work(&phba->beiscsi_hw_check_task,
+                             msecs_to_jiffies(1000));
+}
+
 static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                                const struct pci_device_id *id)
 {
@@ -4746,6 +4816,9 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
        /* Initialize Driver configuration Paramters */
        beiscsi_hba_attrs_init(phba);
 
+       phba->fw_timeout = false;
+
+
        switch (pcidev->device) {
        case BE_DEVICE_ID1:
        case OC_DEVICE_ID1:
@@ -4840,6 +4913,8 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                goto free_twq;
        }
 
+       INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task,
+                         beiscsi_hw_health_check);
 
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -4889,6 +4964,9 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                            "iSCSI boot info.\n");
 
        beiscsi_create_def_ifaces(phba);
+       schedule_delayed_work(&phba->beiscsi_hw_check_task,
+                             msecs_to_jiffies(1000));
+
        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
                    "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n");
        return 0;