[SCSI] iscsi class: sysfs group is_visible callout for session attrs
[linux-2.6.git] / drivers / scsi / be2iscsi / be_main.c
index 4f1aca3..93a3c70 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2009 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -7,24 +7,26 @@
  * as published by the Free Software Foundation.  The full GNU General
  * Public License is included in this distribution in the file called COPYING.
  *
- * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
+ * Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)
  *
  * Contact Information:
- * linux-drivers@serverengines.com
- *
- *  ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * linux-drivers@emulex.com
  *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
+
 #include <linux/reboot.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/semaphore.h>
+#include <linux/iscsi_boot_sysfs.h>
 
 #include <scsi/libiscsi.h>
 #include <scsi/scsi_transport_iscsi.h>
@@ -39,7 +41,9 @@
 
 static unsigned int be_iopoll_budget = 10;
 static unsigned int be_max_phys_size = 64;
-static unsigned int enable_msix;
+static unsigned int enable_msix = 1;
+static unsigned int gcrashmode = 0;
+static unsigned int num_hba = 0;
 
 MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
 MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
@@ -58,17 +62,346 @@ static int beiscsi_slave_configure(struct scsi_device *sdev)
        return 0;
 }
 
+static int beiscsi_eh_abort(struct scsi_cmnd *sc)
+{
+       struct iscsi_cls_session *cls_session;
+       struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr;
+       struct beiscsi_io_task *aborted_io_task;
+       struct iscsi_conn *conn;
+       struct beiscsi_conn *beiscsi_conn;
+       struct beiscsi_hba *phba;
+       struct iscsi_session *session;
+       struct invalidate_command_table *inv_tbl;
+       struct be_dma_mem nonemb_cmd;
+       unsigned int cid, tag, num_invalidate;
+
+       cls_session = starget_to_session(scsi_target(sc->device));
+       session = cls_session->dd_data;
+
+       spin_lock_bh(&session->lock);
+       if (!aborted_task || !aborted_task->sc) {
+               /* we raced */
+               spin_unlock_bh(&session->lock);
+               return SUCCESS;
+       }
+
+       aborted_io_task = aborted_task->dd_data;
+       if (!aborted_io_task->scsi_cmnd) {
+               /* raced or invalid command */
+               spin_unlock_bh(&session->lock);
+               return SUCCESS;
+       }
+       spin_unlock_bh(&session->lock);
+       conn = aborted_task->conn;
+       beiscsi_conn = conn->dd_data;
+       phba = beiscsi_conn->phba;
+
+       /* invalidate iocb */
+       cid = beiscsi_conn->beiscsi_conn_cid;
+       inv_tbl = phba->inv_tbl;
+       memset(inv_tbl, 0x0, sizeof(*inv_tbl));
+       inv_tbl->cid = cid;
+       inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index;
+       num_invalidate = 1;
+       nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
+                               sizeof(struct invalidate_commands_params_in),
+                               &nonemb_cmd.dma);
+       if (nonemb_cmd.va == NULL) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Failed to allocate memory for"
+                        "mgmt_invalidate_icds\n");
+               return FAILED;
+       }
+       nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
+
+       tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,
+                                  cid, &nonemb_cmd);
+       if (!tag) {
+               shost_printk(KERN_WARNING, phba->shost,
+                            "mgmt_invalidate_icds could not be"
+                            " submitted\n");
+               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);
+       }
+       pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
+                           nonemb_cmd.va, nonemb_cmd.dma);
+       return iscsi_eh_abort(sc);
+}
+
+static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
+{
+       struct iscsi_task *abrt_task;
+       struct beiscsi_io_task *abrt_io_task;
+       struct iscsi_conn *conn;
+       struct beiscsi_conn *beiscsi_conn;
+       struct beiscsi_hba *phba;
+       struct iscsi_session *session;
+       struct iscsi_cls_session *cls_session;
+       struct invalidate_command_table *inv_tbl;
+       struct be_dma_mem nonemb_cmd;
+       unsigned int cid, tag, i, num_invalidate;
+       int rc = FAILED;
+
+       /* invalidate iocbs */
+       cls_session = starget_to_session(scsi_target(sc->device));
+       session = cls_session->dd_data;
+       spin_lock_bh(&session->lock);
+       if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN)
+               goto unlock;
+
+       conn = session->leadconn;
+       beiscsi_conn = conn->dd_data;
+       phba = beiscsi_conn->phba;
+       cid = beiscsi_conn->beiscsi_conn_cid;
+       inv_tbl = phba->inv_tbl;
+       memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN);
+       num_invalidate = 0;
+       for (i = 0; i < conn->session->cmds_max; i++) {
+               abrt_task = conn->session->cmds[i];
+               abrt_io_task = abrt_task->dd_data;
+               if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE)
+                       continue;
+
+               if (abrt_task->sc->device->lun != abrt_task->sc->device->lun)
+                       continue;
+
+               inv_tbl->cid = cid;
+               inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index;
+               num_invalidate++;
+               inv_tbl++;
+       }
+       spin_unlock_bh(&session->lock);
+       inv_tbl = phba->inv_tbl;
+
+       nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
+                               sizeof(struct invalidate_commands_params_in),
+                               &nonemb_cmd.dma);
+       if (nonemb_cmd.va == NULL) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Failed to allocate memory for"
+                        "mgmt_invalidate_icds\n");
+               return FAILED;
+       }
+       nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
+       memset(nonemb_cmd.va, 0, nonemb_cmd.size);
+       tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,
+                                  cid, &nonemb_cmd);
+       if (!tag) {
+               shost_printk(KERN_WARNING, phba->shost,
+                            "mgmt_invalidate_icds could not be"
+                            " submitted\n");
+               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);
+       }
+       pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
+                           nonemb_cmd.va, nonemb_cmd.dma);
+       return iscsi_eh_device_reset(sc);
+unlock:
+       spin_unlock_bh(&session->lock);
+       return rc;
+}
+
+static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
+{
+       struct beiscsi_hba *phba = data;
+       struct mgmt_session_info *boot_sess = &phba->boot_sess;
+       struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0];
+       char *str = buf;
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_TGT_NAME:
+               rc = sprintf(buf, "%.*s\n",
+                           (int)strlen(boot_sess->target_name),
+                           (char *)&boot_sess->target_name);
+               break;
+       case ISCSI_BOOT_TGT_IP_ADDR:
+               if (boot_conn->dest_ipaddr.ip_type == 0x1)
+                       rc = sprintf(buf, "%pI4\n",
+                               (char *)&boot_conn->dest_ipaddr.ip_address);
+               else
+                       rc = sprintf(str, "%pI6\n",
+                               (char *)&boot_conn->dest_ipaddr.ip_address);
+               break;
+       case ISCSI_BOOT_TGT_PORT:
+               rc = sprintf(str, "%d\n", boot_conn->dest_port);
+               break;
+
+       case ISCSI_BOOT_TGT_CHAP_NAME:
+               rc = sprintf(str,  "%.*s\n",
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            target_chap_name_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.target_chap_name);
+               break;
+       case ISCSI_BOOT_TGT_CHAP_SECRET:
+               rc = sprintf(str,  "%.*s\n",
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            target_secret_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.target_secret);
+               break;
+       case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+               rc = sprintf(str,  "%.*s\n",
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            intr_chap_name_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.intr_chap_name);
+               break;
+       case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+               rc = sprintf(str,  "%.*s\n",
+                            boot_conn->negotiated_login_options.auth_data.chap.
+                            intr_secret_length,
+                            (char *)&boot_conn->negotiated_login_options.
+                            auth_data.chap.intr_secret);
+               break;
+       case ISCSI_BOOT_TGT_FLAGS:
+               rc = sprintf(str, "2\n");
+               break;
+       case ISCSI_BOOT_TGT_NIC_ASSOC:
+               rc = sprintf(str, "0\n");
+               break;
+       default:
+               rc = -ENOSYS;
+               break;
+       }
+       return rc;
+}
+
+static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf)
+{
+       struct beiscsi_hba *phba = data;
+       char *str = buf;
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_INI_INITIATOR_NAME:
+               rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname);
+               break;
+       default:
+               rc = -ENOSYS;
+               break;
+       }
+       return rc;
+}
+
+static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
+{
+       struct beiscsi_hba *phba = data;
+       char *str = buf;
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_ETH_FLAGS:
+               rc = sprintf(str, "2\n");
+               break;
+       case ISCSI_BOOT_ETH_INDEX:
+               rc = sprintf(str, "0\n");
+               break;
+       case ISCSI_BOOT_ETH_MAC:
+               rc  = beiscsi_get_macaddr(buf, phba);
+               if (rc < 0) {
+                       SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n");
+                       return rc;
+               }
+       break;
+       default:
+               rc = -ENOSYS;
+               break;
+       }
+       return rc;
+}
+
+
+static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type)
+{
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_TGT_NAME:
+       case ISCSI_BOOT_TGT_IP_ADDR:
+       case ISCSI_BOOT_TGT_PORT:
+       case ISCSI_BOOT_TGT_CHAP_NAME:
+       case ISCSI_BOOT_TGT_CHAP_SECRET:
+       case ISCSI_BOOT_TGT_REV_CHAP_NAME:
+       case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
+       case ISCSI_BOOT_TGT_NIC_ASSOC:
+       case ISCSI_BOOT_TGT_FLAGS:
+               rc = S_IRUGO;
+               break;
+       default:
+               rc = 0;
+               break;
+       }
+       return rc;
+}
+
+static mode_t beiscsi_ini_get_attr_visibility(void *data, int type)
+{
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_INI_INITIATOR_NAME:
+               rc = S_IRUGO;
+               break;
+       default:
+               rc = 0;
+               break;
+       }
+       return rc;
+}
+
+
+static mode_t beiscsi_eth_get_attr_visibility(void *data, int type)
+{
+       int rc;
+
+       switch (type) {
+       case ISCSI_BOOT_ETH_FLAGS:
+       case ISCSI_BOOT_ETH_MAC:
+       case ISCSI_BOOT_ETH_INDEX:
+               rc = S_IRUGO;
+               break;
+       default:
+               rc = 0;
+               break;
+       }
+       return rc;
+}
+
+/*------------------- PCI Driver operations and data ----------------- */
+static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
+       { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
+       { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
+       { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
+       { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
+       { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) },
+       { 0 }
+};
+MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
+
 static struct scsi_host_template beiscsi_sht = {
        .module = THIS_MODULE,
        .name = "ServerEngines 10Gbe open-iscsi Initiator Driver",
        .proc_name = DRV_NAME,
        .queuecommand = iscsi_queuecommand,
-       .eh_abort_handler = iscsi_eh_abort,
        .change_queue_depth = iscsi_change_queue_depth,
        .slave_configure = beiscsi_slave_configure,
        .target_alloc = iscsi_target_alloc,
-       .eh_device_reset_handler = iscsi_eh_device_reset,
-       .eh_target_reset_handler = iscsi_eh_target_reset,
+       .eh_abort_handler = beiscsi_eh_abort,
+       .eh_device_reset_handler = beiscsi_eh_device_reset,
+       .eh_target_reset_handler = iscsi_eh_session_reset,
        .sg_tablesize = BEISCSI_SGLIST_ELEMENTS,
        .can_queue = BE2_IO_DEPTH,
        .this_id = -1,
@@ -76,16 +409,8 @@ static struct scsi_host_template beiscsi_sht = {
        .cmd_per_lun = BEISCSI_CMD_PER_LUN,
        .use_clustering = ENABLE_CLUSTERING,
 };
-static struct scsi_transport_template *beiscsi_scsi_transport;
 
-/*------------------- PCI Driver operations and data ----------------- */
-static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
-       { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
-       { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
-       { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
-       { 0 }
-};
-MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
+static struct scsi_transport_template *beiscsi_scsi_transport;
 
 static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
 {
@@ -95,7 +420,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
        shost = iscsi_host_alloc(&beiscsi_sht, sizeof(*phba), 0);
        if (!shost) {
                dev_err(&pcidev->dev, "beiscsi_hba_alloc -"
-                       "iscsi_host_alloc failed \n");
+                       "iscsi_host_alloc failed\n");
                return NULL;
        }
        shost->dma_boundary = pcidev->dma_mask;
@@ -104,14 +429,15 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
        shost->max_cmd_len = BEISCSI_MAX_CMD_LEN;
        shost->max_lun = BEISCSI_NUM_MAX_LUN;
        shost->transportt = beiscsi_scsi_transport;
-
        phba = iscsi_host_priv(shost);
        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;
+
        return phba;
 
 free_devices:
@@ -140,6 +466,7 @@ static int beiscsi_map_pci_bars(struct beiscsi_hba *phba,
                                struct pci_dev *pcidev)
 {
        u8 __iomem *addr;
+       int pcicfg_reg;
 
        addr = ioremap_nocache(pci_resource_start(pcidev, 2),
                               pci_resource_len(pcidev, 2));
@@ -156,13 +483,19 @@ static int beiscsi_map_pci_bars(struct beiscsi_hba *phba,
        phba->db_va = addr;
        phba->db_pa.u.a64.address =  pci_resource_start(pcidev, 4);
 
-       addr = ioremap_nocache(pci_resource_start(pcidev, 1),
-                              pci_resource_len(pcidev, 1));
+       if (phba->generation == BE_GEN2)
+               pcicfg_reg = 1;
+       else
+               pcicfg_reg = 0;
+
+       addr = ioremap_nocache(pci_resource_start(pcidev, pcicfg_reg),
+                              pci_resource_len(pcidev, pcicfg_reg));
+
        if (addr == NULL)
                goto pci_map_err;
        phba->ctrl.pcicfg = addr;
        phba->pci_va = addr;
-       phba->pci_pa.u.a64.address = pci_resource_start(pcidev, 1);
+       phba->pci_pa.u.a64.address = pci_resource_start(pcidev, pcicfg_reg);
        return 0;
 
 pci_map_err:
@@ -181,6 +514,7 @@ static int beiscsi_enable_pci(struct pci_dev *pcidev)
                return ret;
        }
 
+       pci_set_master(pcidev);
        if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) {
                ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
                if (ret) {
@@ -203,7 +537,6 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)
        status = beiscsi_map_pci_bars(phba, pdev);
        if (status)
                return status;
-
        mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
        mbox_mem_alloc->va = pci_alloc_consistent(pdev,
                                                  mbox_mem_alloc->size,
@@ -219,34 +552,35 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)
        mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
        memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
        spin_lock_init(&ctrl->mbox_lock);
+       spin_lock_init(&phba->ctrl.mcc_lock);
+       spin_lock_init(&phba->ctrl.mcc_cq_lock);
+
        return status;
 }
 
 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 * 2;
+       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);
+       SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d\n",
+                            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;
 }
 
@@ -268,6 +602,113 @@ static void hwi_ring_eq_db(struct beiscsi_hba *phba,
 }
 
 /**
+ * be_isr_mcc - The isr routine of the driver.
+ * @irq: Not used
+ * @dev_id: Pointer to host adapter structure
+ */
+static irqreturn_t be_isr_mcc(int irq, void *dev_id)
+{
+       struct beiscsi_hba *phba;
+       struct be_eq_entry *eqe = NULL;
+       struct be_queue_info *eq;
+       struct be_queue_info *mcc;
+       unsigned int num_eq_processed;
+       struct be_eq_obj *pbe_eq;
+       unsigned long flags;
+
+       pbe_eq = dev_id;
+       eq = &pbe_eq->q;
+       phba =  pbe_eq->phba;
+       mcc = &phba->ctrl.mcc_obj.cq;
+       eqe = queue_tail_node(eq);
+       if (!eqe)
+               SE_DEBUG(DBG_LVL_1, "eqe is NULL\n");
+
+       num_eq_processed = 0;
+
+       while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
+                               & EQE_VALID_MASK) {
+               if (((eqe->dw[offsetof(struct amap_eq_entry,
+                    resource_id) / 32] &
+                    EQE_RESID_MASK) >> 16) == mcc->id) {
+                       spin_lock_irqsave(&phba->isr_lock, flags);
+                       phba->todo_mcc_cq = 1;
+                       spin_unlock_irqrestore(&phba->isr_lock, flags);
+               }
+               AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
+               queue_tail_inc(eq);
+               eqe = queue_tail_node(eq);
+               num_eq_processed++;
+       }
+       if (phba->todo_mcc_cq)
+               queue_work(phba->wq, &phba->work_cqs);
+       if (num_eq_processed)
+               hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * be_isr_msix - The isr routine of the driver.
+ * @irq: Not used
+ * @dev_id: Pointer to host adapter structure
+ */
+static irqreturn_t be_isr_msix(int irq, void *dev_id)
+{
+       struct beiscsi_hba *phba;
+       struct be_eq_entry *eqe = NULL;
+       struct be_queue_info *eq;
+       struct be_queue_info *cq;
+       unsigned int num_eq_processed;
+       struct be_eq_obj *pbe_eq;
+       unsigned long flags;
+
+       pbe_eq = dev_id;
+       eq = &pbe_eq->q;
+       cq = pbe_eq->cq;
+       eqe = queue_tail_node(eq);
+       if (!eqe)
+               SE_DEBUG(DBG_LVL_1, "eqe is NULL\n");
+
+       phba = pbe_eq->phba;
+       num_eq_processed = 0;
+       if (blk_iopoll_enabled) {
+               while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
+                                       & EQE_VALID_MASK) {
+                       if (!blk_iopoll_sched_prep(&pbe_eq->iopoll))
+                               blk_iopoll_sched(&pbe_eq->iopoll);
+
+                       AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
+                       queue_tail_inc(eq);
+                       eqe = queue_tail_node(eq);
+                       num_eq_processed++;
+               }
+               if (num_eq_processed)
+                       hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1);
+
+               return IRQ_HANDLED;
+       } else {
+               while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
+                                               & EQE_VALID_MASK) {
+                       spin_lock_irqsave(&phba->isr_lock, flags);
+                       phba->todo_cq = 1;
+                       spin_unlock_irqrestore(&phba->isr_lock, flags);
+                       AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
+                       queue_tail_inc(eq);
+                       eqe = queue_tail_node(eq);
+                       num_eq_processed++;
+               }
+               if (phba->todo_cq)
+                       queue_work(phba->wq, &phba->work_cqs);
+
+               if (num_eq_processed)
+                       hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1);
+
+               return IRQ_HANDLED;
+       }
+}
+
+/**
  * be_isr - The isr routine of the driver.
  * @irq: Not used
  * @dev_id: Pointer to host adapter structure
@@ -280,48 +721,70 @@ static irqreturn_t be_isr(int irq, void *dev_id)
        struct be_eq_entry *eqe = NULL;
        struct be_queue_info *eq;
        struct be_queue_info *cq;
+       struct be_queue_info *mcc;
        unsigned long flags, index;
-       unsigned int num_eq_processed;
+       unsigned int num_mcceq_processed, num_ioeq_processed;
        struct be_ctrl_info *ctrl;
+       struct be_eq_obj *pbe_eq;
        int isr;
 
        phba = dev_id;
-       if (!enable_msix) {
-               ctrl = &phba->ctrl;;
-               isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
-                              (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE));
-               if (!isr)
-                       return IRQ_NONE;
-       }
+       ctrl = &phba->ctrl;
+       isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
+                      (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE));
+       if (!isr)
+               return IRQ_NONE;
 
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
-       eq = &phwi_context->be_eq.q;
-       cq = &phwi_context->be_cq;
+       pbe_eq = &phwi_context->be_eq[0];
+
+       eq = &phwi_context->be_eq[0].q;
+       mcc = &phba->ctrl.mcc_obj.cq;
        index = 0;
        eqe = queue_tail_node(eq);
        if (!eqe)
                SE_DEBUG(DBG_LVL_1, "eqe is NULL\n");
 
-       num_eq_processed = 0;
+       num_ioeq_processed = 0;
+       num_mcceq_processed = 0;
        if (blk_iopoll_enabled) {
                while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
                                        & EQE_VALID_MASK) {
-                       if (!blk_iopoll_sched_prep(&phba->iopoll))
-                               blk_iopoll_sched(&phba->iopoll);
-
+                       if (((eqe->dw[offsetof(struct amap_eq_entry,
+                            resource_id) / 32] &
+                            EQE_RESID_MASK) >> 16) == mcc->id) {
+                               spin_lock_irqsave(&phba->isr_lock, flags);
+                               phba->todo_mcc_cq = 1;
+                               spin_unlock_irqrestore(&phba->isr_lock, flags);
+                               num_mcceq_processed++;
+                       } else {
+                               if (!blk_iopoll_sched_prep(&pbe_eq->iopoll))
+                                       blk_iopoll_sched(&pbe_eq->iopoll);
+                               num_ioeq_processed++;
+                       }
                        AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
                        queue_tail_inc(eq);
                        eqe = queue_tail_node(eq);
-                       num_eq_processed++;
-                       SE_DEBUG(DBG_LVL_8, "Valid EQE\n");
                }
-               if (num_eq_processed) {
-                       hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 0, 1);
+               if (num_ioeq_processed || num_mcceq_processed) {
+                       if (phba->todo_mcc_cq)
+                               queue_work(phba->wq, &phba->work_cqs);
+
+                       if ((num_mcceq_processed) && (!num_ioeq_processed))
+                               hwi_ring_eq_db(phba, eq->id, 0,
+                                             (num_ioeq_processed +
+                                              num_mcceq_processed) , 1, 1);
+                       else
+                               hwi_ring_eq_db(phba, eq->id, 0,
+                                              (num_ioeq_processed +
+                                               num_mcceq_processed), 0, 1);
+
                        return IRQ_HANDLED;
                } else
                        return IRQ_NONE;
        } else {
+               cq = &phwi_context->be_cq[0];
                while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
                                                & EQE_VALID_MASK) {
 
@@ -339,13 +802,14 @@ static irqreturn_t be_isr(int irq, void *dev_id)
                        AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
                        queue_tail_inc(eq);
                        eqe = queue_tail_node(eq);
-                       num_eq_processed++;
+                       num_ioeq_processed++;
                }
                if (phba->todo_cq || phba->todo_mcc_cq)
                        queue_work(phba->wq, &phba->work_cqs);
 
-               if (num_eq_processed) {
-                       hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 1, 1);
+               if (num_ioeq_processed) {
+                       hwi_ring_eq_db(phba, eq->id, 0,
+                                      num_ioeq_processed, 1, 1);
                        return IRQ_HANDLED;
                } else
                        return IRQ_NONE;
@@ -355,15 +819,53 @@ static irqreturn_t be_isr(int irq, void *dev_id)
 static int beiscsi_init_irqs(struct beiscsi_hba *phba)
 {
        struct pci_dev *pcidev = phba->pcidev;
-       int ret;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       int ret, msix_vec, i, j;
+       char desc[32];
 
-       ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED, "beiscsi", phba);
-       if (ret) {
-               shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-"
-                            "Failed to register irq\\n");
-               return ret;
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+
+       if (phba->msix_enabled) {
+               for (i = 0; i < phba->num_cpus; i++) {
+                       sprintf(desc, "beiscsi_msix_%04x", i);
+                       msix_vec = phba->msix_entries[i].vector;
+                       ret = request_irq(msix_vec, be_isr_msix, 0, desc,
+                                         &phwi_context->be_eq[i]);
+                       if (ret) {
+                               shost_printk(KERN_ERR, phba->shost,
+                                            "beiscsi_init_irqs-Failed to"
+                                            "register msix for i = %d\n", i);
+                               if (!i)
+                                       return ret;
+                               goto free_msix_irqs;
+                       }
+               }
+               msix_vec = phba->msix_entries[i].vector;
+               ret = request_irq(msix_vec, be_isr_mcc, 0, "beiscsi_msix_mcc",
+                                 &phwi_context->be_eq[i]);
+               if (ret) {
+                       shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-"
+                                    "Failed to register beiscsi_msix_mcc\n");
+                       i++;
+                       goto free_msix_irqs;
+               }
+
+       } else {
+               ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED,
+                                 "beiscsi", phba);
+               if (ret) {
+                       shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-"
+                                    "Failed to register irq\\n");
+                       return ret;
+               }
        }
        return 0;
+free_msix_irqs:
+       for (j = i - 1; j == 0; j++)
+               free_irq(msix_vec, &phwi_context->be_eq[j]);
+       return ret;
 }
 
 static void hwi_ring_cq_db(struct beiscsi_hba *phba,
@@ -378,15 +880,6 @@ static void hwi_ring_cq_db(struct beiscsi_hba *phba,
        iowrite32(val, phba->db_va + DB_CQ_OFFSET);
 }
 
-/*
- * async pdus include
- * a. unsolicited NOP-In (target initiated NOP-In)
- * b. Async Messages
- * c. Reject PDU
- * d. Login response
- * These headers arrive unprocessed by the EP firmware and iSCSI layer
- * process them
- */
 static unsigned int
 beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,
                          struct beiscsi_hba *phba,
@@ -397,6 +890,9 @@ beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,
 {
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct iscsi_session *session = conn->session;
+       struct iscsi_task *task;
+       struct beiscsi_io_task *io_task;
+       struct iscsi_hdr *login_hdr;
 
        switch (ppdu->dw[offsetof(struct amap_pdu_base, opcode) / 32] &
                                                PDUBASE_OPCODE_MASK) {
@@ -412,10 +908,15 @@ 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;
+               login_hdr->itt = io_task->libiscsi_itt;
                break;
        default:
                shost_printk(KERN_WARNING, phba->shost,
-                            "Unrecognized opcode 0x%x in async msg \n",
+                            "Unrecognized opcode 0x%x in async msg\n",
                             (ppdu->
                             dw[offsetof(struct amap_pdu_base, opcode) / 32]
                                                & PDUBASE_OPCODE_MASK));
@@ -434,13 +935,14 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)
 
        if (phba->io_sgl_hndl_avbl) {
                SE_DEBUG(DBG_LVL_8,
-                        "In alloc_io_sgl_handle,io_sgl_alloc_index=%d \n",
+                        "In alloc_io_sgl_handle,io_sgl_alloc_index=%d\n",
                         phba->io_sgl_alloc_index);
                psgl_handle = phba->io_sgl_hndl_base[phba->
                                                io_sgl_alloc_index];
                phba->io_sgl_hndl_base[phba->io_sgl_alloc_index] = NULL;
                phba->io_sgl_hndl_avbl--;
-               if (phba->io_sgl_alloc_index == (phba->params.ios_per_ctrl - 1))
+               if (phba->io_sgl_alloc_index == (phba->params.
+                                                ios_per_ctrl - 1))
                        phba->io_sgl_alloc_index = 0;
                else
                        phba->io_sgl_alloc_index++;
@@ -452,7 +954,7 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)
 static void
 free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
 {
-       SE_DEBUG(DBG_LVL_8, "In free_,io_sgl_free_index=%d \n",
+       SE_DEBUG(DBG_LVL_8, "In free_,io_sgl_free_index=%d\n",
                 phba->io_sgl_free_index);
        if (phba->io_sgl_hndl_base[phba->io_sgl_free_index]) {
                /*
@@ -461,7 +963,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
                 */
                 SE_DEBUG(DBG_LVL_8,
                         "Double Free in IO SGL io_sgl_free_index=%d,"
-                        "value there=%p \n", phba->io_sgl_free_index,
+                        "value there=%p\n", phba->io_sgl_free_index,
                         phba->io_sgl_hndl_base[phba->io_sgl_free_index]);
                return;
        }
@@ -477,22 +979,31 @@ 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];
-       pwrb_handle = pwrb_context->pwrb_handle_base[index];
-       pwrb_handle->wrb_index = index;
-       pwrb_handle->nxt_wrb_index = index;
+       if (pwrb_context->wrb_handles_available >= 2) {
+               pwrb_handle = pwrb_context->pwrb_handle_base[
+                                           pwrb_context->alloc_index];
+               pwrb_context->wrb_handles_available--;
+               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;
 }
 
@@ -508,11 +1019,18 @@ static void
 free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context,
                struct wrb_handle *pwrb_handle)
 {
+       pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle;
+       pwrb_context->wrb_handles_available++;
+       if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1))
+               pwrb_context->free_index = 0;
+       else
+               pwrb_context->free_index++;
+
        SE_DEBUG(DBG_LVL_8,
-                "FREE WRB: pwrb_handle=%p free_index=%d=0x%x"
-                "wrb_handles_available=%d \n",
+                "FREE WRB: pwrb_handle=%p free_index=0x%x"
+                "wrb_handles_available=%d\n",
                 pwrb_handle, pwrb_context->free_index,
-                pwrb_context->free_index, pwrb_context->wrb_handles_available);
+                pwrb_context->wrb_handles_available);
 }
 
 static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)
@@ -522,7 +1040,7 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)
        if (phba->eh_sgl_hndl_avbl) {
                psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index];
                phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL;
-               SE_DEBUG(DBG_LVL_8, "mgmt_sgl_alloc_index=%d=0x%x \n",
+               SE_DEBUG(DBG_LVL_8, "mgmt_sgl_alloc_index=%d=0x%x\n",
                         phba->eh_sgl_alloc_index, phba->eh_sgl_alloc_index);
                phba->eh_sgl_hndl_avbl--;
                if (phba->eh_sgl_alloc_index ==
@@ -540,13 +1058,15 @@ void
 free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
 {
 
+       SE_DEBUG(DBG_LVL_8, "In  free_mgmt_sgl_handle,eh_sgl_free_index=%d\n",
+                            phba->eh_sgl_free_index);
        if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) {
                /*
                 * this can happen if clean_task is called on a task that
                 * failed in xmit_task or alloc_pdu.
                 */
                SE_DEBUG(DBG_LVL_8,
-                        "Double Free in eh SGL ,eh_sgl_free_index=%d \n",
+                        "Double Free in eh SGL ,eh_sgl_free_index=%d\n",
                         phba->eh_sgl_free_index);
                return;
        }
@@ -572,10 +1092,10 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
        u32 resid = 0, exp_cmdsn, max_cmdsn;
        u8 rsp, status, flags;
 
-       exp_cmdsn = be32_to_cpu(psol->
+       exp_cmdsn = (psol->
                        dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
                        & SOL_EXP_CMD_SN_MASK);
-       max_cmdsn = be32_to_cpu((psol->
+       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)
@@ -610,18 +1130,19 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,
        }
 
        if (status == SAM_STAT_CHECK_CONDITION) {
+               unsigned short *slen = (unsigned short *)sts_bhs->sense_info;
                sense = sts_bhs->sense_info + sizeof(unsigned short);
-               sense_len =
-                   cpu_to_be16((unsigned short)(sts_bhs->sense_info[0]));
+               sense_len =  cpu_to_be16(*slen);
                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)
                         conn->rxdata_octets += (psol->
-                             dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
-                                                       & SOL_RES_CNT_MASK);
+                            dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
+                            & SOL_RES_CNT_MASK);
        }
 unmap:
        scsi_dma_unmap(io_task->scsi_cmnd);
@@ -633,9 +1154,11 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
                   struct iscsi_task *task, struct sol_cqe *psol)
 {
        struct iscsi_logout_rsp *hdr;
+       struct beiscsi_io_task *io_task = task->dd_data;
        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]
@@ -650,8 +1173,11 @@ 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);
 }
 
@@ -661,18 +1187,21 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
 {
        struct iscsi_tm_rsp *hdr;
        struct iscsi_conn *conn = beiscsi_conn->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) /
                                        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);
+                                   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->itt = io_task->libiscsi_itt;
        __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
 }
 
@@ -681,18 +1210,27 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
                       struct beiscsi_hba *phba, struct sol_cqe *psol)
 {
        struct hwi_wrb_context *pwrb_context;
-       struct wrb_handle *pwrb_handle;
+       struct wrb_handle *pwrb_handle = NULL;
        struct hwi_controller *phwi_ctrlr;
+       struct iscsi_task *task;
+       struct beiscsi_io_task *io_task;
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct iscsi_session *session = conn->session;
 
        phwi_ctrlr = phba->phwi_ctrlr;
        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)];
+       task = pwrb_handle->pio_handle;
+
+       io_task = task->dd_data;
+       spin_lock(&phba->mgmt_sgl_lock);
+       free_mgmt_sgl_handle(phba, io_task->psgl_handle);
+       spin_unlock(&phba->mgmt_sgl_lock);
        spin_lock_bh(&session->lock);
        free_wrb_handle(phba, pwrb_context, pwrb_handle);
        spin_unlock_bh(&session->lock);
@@ -704,6 +1242,7 @@ be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
 {
        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]
@@ -715,6 +1254,7 @@ be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
                        ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
                        / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
        hdr->opcode = ISCSI_OP_NOOP_IN;
+       hdr->itt = io_task->libiscsi_itt;
        __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
 }
 
@@ -726,46 +1266,46 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
        struct iscsi_wrb *pwrb = NULL;
        struct hwi_controller *phwi_ctrlr;
        struct iscsi_task *task;
-       struct beiscsi_io_task *io_task;
+       unsigned int type;
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct iscsi_session *session = conn->session;
 
        phwi_ctrlr = phba->phwi_ctrlr;
-
-       pwrb_context = &phwi_ctrlr->
-               wrb_context[((psol->dw[offsetof(struct amap_sol_cqe, cid) / 32]
-               & SOL_CID_MASK) >> 6)];
+       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)];
-
        task = pwrb_handle->pio_handle;
-       io_task = task->dd_data;
-       spin_lock_bh(&session->lock);
        pwrb = pwrb_handle->pwrb;
-       switch ((pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] &
-                WRB_TYPE_MASK) >> 28) {
+       type = (pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] &
+                                WRB_TYPE_MASK) >> 28;
+
+       spin_lock_bh(&session->lock);
+       switch (type) {
        case HWH_TYPE_IO:
        case HWH_TYPE_IO_RD:
                if ((task->hdr->opcode & ISCSI_OPCODE_MASK) ==
-                   ISCSI_OP_NOOP_OUT) {
+                    ISCSI_OP_NOOP_OUT)
                        be_complete_nopin_resp(beiscsi_conn, task, psol);
-               } else
+               else
                        be_complete_io(beiscsi_conn, task, psol);
                break;
 
        case HWH_TYPE_LOGOUT:
-               be_complete_logout(beiscsi_conn, task, psol);
+               if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
+                       be_complete_logout(beiscsi_conn, task, psol);
+               else
+                       be_complete_tmf(beiscsi_conn, task, psol);
+
                break;
 
        case HWH_TYPE_LOGIN:
                SE_DEBUG(DBG_LVL_1,
                         "\t\t No HWH_TYPE_LOGIN Expected in hwi_complete_cmd"
-                        "- Solicited path \n");
-               break;
-
-       case HWH_TYPE_TMF:
-               be_complete_tmf(beiscsi_conn, task, psol);
+                        "- Solicited path\n");
                break;
 
        case HWH_TYPE_NOP:
@@ -774,11 +1314,12 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
 
        default:
                shost_printk(KERN_WARNING, phba->shost,
-                           "wrb_index 0x%x CID 0x%x\n",
-                           ((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));
+                               "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));
                break;
        }
 
@@ -847,7 +1388,7 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
        default:
                pbusy_list = NULL;
                shost_printk(KERN_WARNING, phba->shost,
-                       "Unexpected code=%d \n",
+                       "Unexpected code=%d\n",
                         pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
                                        code) / 32] & PDUCQE_CODE_MASK);
                return NULL;
@@ -863,7 +1404,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]
@@ -1113,9 +1655,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);
@@ -1208,40 +1751,79 @@ static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn,
        hwi_post_async_buffers(phba, pasync_handle->is_header);
 }
 
-static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba)
+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)
 {
-       struct hwi_controller *phwi_ctrlr;
-       struct hwi_context_memory *phwi_context;
        struct be_queue_info *cq;
        struct sol_cqe *sol;
        struct dmsg_cqe *dmsg;
        unsigned int num_processed = 0;
        unsigned int tot_nump = 0;
        struct beiscsi_conn *beiscsi_conn;
+       struct beiscsi_endpoint *beiscsi_ep;
+       struct iscsi_endpoint *ep;
+       struct beiscsi_hba *phba;
 
-       phwi_ctrlr = phba->phwi_ctrlr;
-       phwi_context = phwi_ctrlr->phwi_ctxt;
-       cq = &phwi_context->be_cq;
+       cq = pbe_eq->cq;
        sol = queue_tail_node(cq);
+       phba = pbe_eq->phba;
 
        while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] &
               CQE_VALID_MASK) {
                be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));
 
-               beiscsi_conn = phba->conn_table[(u32) (sol->
-                                dw[offsetof(struct amap_sol_cqe, cid) / 32] &
-                                SOL_CID_MASK) >> 6];
+               ep = phba->ep_array[(u32) ((sol->
+                                  dw[offsetof(struct amap_sol_cqe, cid) / 32] &
+                                  SOL_CID_MASK) >> 6) -
+                                  phba->fw_config.iscsi_cid_start];
 
-               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;
-               }
+               beiscsi_ep = ep->dd_data;
+               beiscsi_conn = beiscsi_ep->conn;
 
                if (num_processed >= 32) {
-                       hwi_ring_cq_db(phba, phwi_context->be_cq.id,
+                       hwi_ring_cq_db(phba, cq->id,
                                        num_processed, 0, 0);
                        tot_nump += num_processed;
                        num_processed = 0;
@@ -1253,13 +1835,17 @@ static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba)
                        hwi_complete_cmd(beiscsi_conn, phba, sol);
                        break;
                case DRIVERMSG_NOTIFY:
-                       SE_DEBUG(DBG_LVL_8, "Received DRIVERMSG_NOTIFY \n");
+                       SE_DEBUG(DBG_LVL_8, "Received DRIVERMSG_NOTIFY\n");
                        dmsg = (struct dmsg_cqe *)sol;
                        hwi_complete_drvr_msgs(beiscsi_conn, phba, sol);
                        break;
                case UNSOL_HDR_NOTIFY:
+                       SE_DEBUG(DBG_LVL_8, "Received UNSOL_HDR_ NOTIFY\n");
+                       hwi_process_default_pdu_ring(beiscsi_conn, phba,
+                                            (struct i_t_dpdu_cqe *)sol);
+                       break;
                case UNSOL_DATA_NOTIFY:
-                       SE_DEBUG(DBG_LVL_8, "Received UNSOL_HDR/DATA_NOTIFY\n");
+                       SE_DEBUG(DBG_LVL_8, "Received UNSOL_DATA_NOTIFY\n");
                        hwi_process_default_pdu_ring(beiscsi_conn, phba,
                                             (struct i_t_dpdu_cqe *)sol);
                        break;
@@ -1306,23 +1892,23 @@ static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba)
                case CXN_KILLED_OVER_RUN_RESIDUAL:
                case CXN_KILLED_UNDER_RUN_RESIDUAL:
                case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN:
-                       SE_DEBUG(DBG_LVL_1, "CQ Error %d, resetting CID "
+                       SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset 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);
                        break;
                case CXN_KILLED_RST_SENT:
                case CXN_KILLED_RST_RCVD:
-                       SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset received/sent "
-                                "on CID 0x%x...\n",
+                       SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset"
+                               "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);
                        break;
@@ -1331,8 +1917,8 @@ static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba)
                                 "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;
                }
 
@@ -1344,30 +1930,39 @@ static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba)
 
        if (num_processed > 0) {
                tot_nump += num_processed;
-               hwi_ring_cq_db(phba, phwi_context->be_cq.id, num_processed,
-                              1, 0);
+               hwi_ring_cq_db(phba, cq->id, num_processed, 1, 0);
        }
        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;
+       struct hwi_context_memory *phwi_context;
+       struct be_eq_obj *pbe_eq;
        struct beiscsi_hba *phba =
            container_of(work, struct beiscsi_hba, work_cqs);
 
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
+       if (phba->msix_enabled)
+               pbe_eq = &phwi_context->be_eq[phba->num_cpus];
+       else
+               pbe_eq = &phwi_context->be_eq[0];
+
        if (phba->todo_mcc_cq) {
                spin_lock_irqsave(&phba->isr_lock, flags);
                phba->todo_mcc_cq = 0;
                spin_unlock_irqrestore(&phba->isr_lock, flags);
-               SE_DEBUG(DBG_LVL_1, "MCC Interrupt Not expected \n");
+               beiscsi_process_mcc_isr(phba);
        }
 
        if (phba->todo_cq) {
                spin_lock_irqsave(&phba->isr_lock, flags);
                phba->todo_cq = 0;
                spin_unlock_irqrestore(&phba->isr_lock, flags);
-               beiscsi_process_cq(phba);
+               beiscsi_process_cq(pbe_eq);
        }
 }
 
@@ -1375,19 +1970,15 @@ static int be_iopoll(struct blk_iopoll *iop, int budget)
 {
        static unsigned int ret;
        struct beiscsi_hba *phba;
+       struct be_eq_obj *pbe_eq;
 
-       phba = container_of(iop, struct beiscsi_hba, iopoll);
-
-       ret = beiscsi_process_cq(phba);
+       pbe_eq = container_of(iop, struct be_eq_obj, iopoll);
+       ret = beiscsi_process_cq(pbe_eq);
        if (ret < budget) {
-               struct hwi_controller *phwi_ctrlr;
-               struct hwi_context_memory *phwi_context;
-
-               phwi_ctrlr = phba->phwi_ctrlr;
-               phwi_context = phwi_ctrlr->phwi_ctxt;
+               phba = pbe_eq->phba;
                blk_iopoll_complete(iop);
-               hwi_ring_eq_db(phba, phwi_context->be_eq.q.id, 0,
-                                                       0, 1, 1);
+               SE_DEBUG(DBG_LVL_8, "rearm pbe_eq->q.id =%d\n", pbe_eq->q.id);
+               hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1);
        }
        return ret;
 }
@@ -1397,7 +1988,7 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
              unsigned int num_sg, struct beiscsi_io_task *io_task)
 {
        struct iscsi_sge *psgl;
-       unsigned short sg_len, index;
+       unsigned int sg_len, index;
        unsigned int sge_len = 0;
        unsigned long long addr;
        struct scatterlist *l_sg;
@@ -1409,30 +2000,27 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
                                      io_task->bhs_pa.u.a32.address_hi);
 
        l_sg = sg;
-       for (index = 0; (index < num_sg) && (index < 2); index++, sg_next(sg)) {
+       for (index = 0; (index < num_sg) && (index < 2); index++,
+                                                        sg = sg_next(sg)) {
                if (index == 0) {
                        sg_len = sg_dma_len(sg);
                        addr = (u64) sg_dma_address(sg);
                        AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
-                                                       (addr & 0xFFFFFFFF));
+                                               ((u32)(addr & 0xFFFFFFFF)));
                        AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
-                                                       (addr >> 32));
+                                                       ((u32)(addr >> 32)));
                        AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
                                                        sg_len);
                        sge_len = sg_len;
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
-                                                       1);
                } else {
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
-                                                       0);
                        AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_r2t_offset,
                                                        pwrb, sge_len);
                        sg_len = sg_dma_len(sg);
                        addr = (u64) sg_dma_address(sg);
                        AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_lo, pwrb,
-                                                       (addr & 0xFFFFFFFF));
+                                               ((u32)(addr & 0xFFFFFFFF)));
                        AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_hi, pwrb,
-                                                       (addr >> 32));
+                                                       ((u32)(addr >> 32)));
                        AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_len, pwrb,
                                                        sg_len);
                }
@@ -1447,13 +2035,27 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
        AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
                        io_task->bhs_pa.u.a32.address_lo);
 
-       if (num_sg == 2)
-               AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, 1);
+       if (num_sg == 1) {
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
+                                                               1);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb,
+                                                               0);
+       } else if (num_sg == 2) {
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
+                                                               0);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb,
+                                                               1);
+       } else {
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
+                                                               0);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb,
+                                                               0);
+       }
        sg = l_sg;
        psgl++;
        psgl++;
        offset = 0;
-       for (index = 0; index < num_sg; index++, sg_next(sg), psgl++) {
+       for (index = 0; index < num_sg; index++, sg = sg_next(sg), psgl++) {
                sg_len = sg_dma_len(sg);
                addr = (u64) sg_dma_address(sg);
                AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
@@ -1494,9 +2096,9 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
                        addr = 0;
                }
                AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
-                                               (addr & 0xFFFFFFFF));
+                                               ((u32)(addr & 0xFFFFFFFF)));
                AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
-                                               (addr >> 32));
+                                               ((u32)(addr >> 32)));
                AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
                                                task->data_count);
 
@@ -1526,9 +2128,9 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
                psgl++;
                if (task->data) {
                        AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
-                                               (addr & 0xFFFFFFFF));
+                                               ((u32)(addr & 0xFFFFFFFF)));
                        AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
-                                               (addr >> 32));
+                                               ((u32)(addr >> 32)));
                }
                AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106);
        }
@@ -1537,14 +2139,12 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
 
 static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
 {
-       unsigned int num_cq_pages, num_eq_pages, num_async_pdu_buf_pages;
+       unsigned int num_cq_pages, num_async_pdu_buf_pages;
        unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn;
        unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages;
 
        num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \
                                      sizeof(struct sol_cqe));
-       num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \
-                                     sizeof(struct be_eq_entry));
        num_async_pdu_buf_pages =
                        PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
                                       phba->params.defpdu_hdr_sz);
@@ -1565,8 +2165,6 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
        phba->mem_req[HWI_MEM_ADDN_CONTEXT] =
                                            sizeof(struct hwi_context_memory);
 
-       phba->mem_req[HWI_MEM_CQ] = num_cq_pages * PAGE_SIZE;
-       phba->mem_req[HWI_MEM_EQ] = num_eq_pages * PAGE_SIZE;
 
        phba->mem_req[HWI_MEM_WRB] = sizeof(struct iscsi_wrb)
            * (phba->params.wrbs_per_cxn)
@@ -1680,7 +2278,8 @@ free_mem:
                                            mem_descr->mem_array[j - 1].size,
                                            mem_descr->mem_array[j - 1].
                                            virtual_address,
-                                           mem_descr->mem_array[j - 1].
+                                           (unsigned long)mem_descr->
+                                           mem_array[j - 1].
                                            bus_address.u.a64.address);
                }
                if (i) {
@@ -1751,8 +2350,6 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
 
        for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
                pwrb_context = &phwi_ctrlr->wrb_context[index];
-               SE_DEBUG(DBG_LVL_8, "cid=%d pwrb_context=%p \n", index,
-                                               pwrb_context);
                pwrb_context->pwrb_handle_base =
                                kzalloc(sizeof(struct wrb_handle *) *
                                        phba->params.wrbs_per_cxn, GFP_KERNEL);
@@ -1767,6 +2364,7 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
                                pwrb_context->pwrb_handle_basestd[j] =
                                                                pwrb_handle;
                                pwrb_context->wrb_handles_available++;
+                               pwrb_handle->wrb_index = j;
                                pwrb_handle++;
                        }
                        pwrb_context->free_index = 0;
@@ -1785,6 +2383,7 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
                                pwrb_context->pwrb_handle_basestd[j] =
                                    pwrb_handle;
                                pwrb_context->wrb_handles_available++;
+                               pwrb_handle->wrb_index = j;
                                pwrb_handle++;
                        }
                        pwrb_context->free_index = 0;
@@ -1793,11 +2392,10 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
        }
        idx = 0;
        pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
-       num_cxn_wrb =
-           ((mem_descr_wrb->mem_array[idx].size) / (sizeof(struct iscsi_wrb)) *
-            phba->params.wrbs_per_cxn);
-
-       for (index = 0; index < phba->params.cxns_per_ctrl; index += 2) {
+       num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) /
+                     ((sizeof(struct iscsi_wrb) *
+                       phba->params.wrbs_per_cxn));
+       for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
                pwrb_context = &phwi_ctrlr->wrb_context[index];
                if (num_cxn_wrb) {
                        for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
@@ -1809,9 +2407,9 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
                } else {
                        idx++;
                        pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
-                       num_cxn_wrb = ((mem_descr_wrb->mem_array[idx].size) /
-                                       (sizeof(struct iscsi_wrb)) *
-                                       phba->params.wrbs_per_cxn);
+                       num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) /
+                                     ((sizeof(struct iscsi_wrb) *
+                                       phba->params.wrbs_per_cxn));
                        for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
                                pwrb_handle = pwrb_context->pwrb_handle_base[j];
                                pwrb_handle->pwrb = pwrb;
@@ -1850,10 +2448,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
        if (mem_descr->mem_array[0].virtual_address) {
                SE_DEBUG(DBG_LVL_8,
                         "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_BUF"
-                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+                        "va=%p\n", mem_descr->mem_array[0].virtual_address);
        } else
                shost_printk(KERN_WARNING, phba->shost,
-                            "No Virtual address \n");
+                            "No Virtual address\n");
 
        pasync_ctx->async_header.va_base =
                        mem_descr->mem_array[0].virtual_address;
@@ -1866,10 +2464,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
        if (mem_descr->mem_array[0].virtual_address) {
                SE_DEBUG(DBG_LVL_8,
                         "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_RING"
-                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+                        "va=%p\n", mem_descr->mem_array[0].virtual_address);
        } else
                shost_printk(KERN_WARNING, phba->shost,
-                           "No Virtual address \n");
+                           "No Virtual address\n");
        pasync_ctx->async_header.ring_base =
                        mem_descr->mem_array[0].virtual_address;
 
@@ -1878,10 +2476,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
        if (mem_descr->mem_array[0].virtual_address) {
                SE_DEBUG(DBG_LVL_8,
                         "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_HANDLE"
-                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+                        "va=%p\n", mem_descr->mem_array[0].virtual_address);
        } else
                shost_printk(KERN_WARNING, phba->shost,
-                           "No Virtual address \n");
+                           "No Virtual address\n");
 
        pasync_ctx->async_header.handle_base =
                        mem_descr->mem_array[0].virtual_address;
@@ -1893,10 +2491,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
        if (mem_descr->mem_array[0].virtual_address) {
                SE_DEBUG(DBG_LVL_8,
                         "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_BUF"
-                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+                        "va=%p\n", mem_descr->mem_array[0].virtual_address);
        } else
                shost_printk(KERN_WARNING, phba->shost,
-                           "No Virtual address \n");
+                           "No Virtual address\n");
        pasync_ctx->async_data.va_base =
                        mem_descr->mem_array[0].virtual_address;
        pasync_ctx->async_data.pa_base.u.a64.address =
@@ -1907,10 +2505,10 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
        if (mem_descr->mem_array[0].virtual_address) {
                SE_DEBUG(DBG_LVL_8,
                         "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_RING"
-                        "va=%p \n", mem_descr->mem_array[0].virtual_address);
+                        "va=%p\n", mem_descr->mem_array[0].virtual_address);
        } else
                shost_printk(KERN_WARNING, phba->shost,
-                            "No Virtual address \n");
+                            "No Virtual address\n");
 
        pasync_ctx->async_data.ring_base =
                        mem_descr->mem_array[0].virtual_address;
@@ -1919,7 +2517,7 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
        mem_descr += HWI_MEM_ASYNC_DATA_HANDLE;
        if (!mem_descr->mem_array[0].virtual_address)
                shost_printk(KERN_WARNING, phba->shost,
-                           "No Virtual address \n");
+                           "No Virtual address\n");
 
        pasync_ctx->async_data.handle_base =
                        mem_descr->mem_array[0].virtual_address;
@@ -1991,7 +2589,7 @@ be_sgl_create_contiguous(void *virtual_address,
        WARN_ON(!sgl);
 
        sgl->va = virtual_address;
-       sgl->dma = physical_address;
+       sgl->dma = (unsigned long)physical_address;
        sgl->size = length;
 
        return 0;
@@ -2042,79 +2640,126 @@ static int be_fill_queue(struct be_queue_info *q,
        return 0;
 }
 
-static int beiscsi_create_eq(struct beiscsi_hba *phba,
+static int beiscsi_create_eqs(struct beiscsi_hba *phba,
                             struct hwi_context_memory *phwi_context)
 {
-       unsigned int idx;
-       int ret;
+       unsigned int i, num_eq_pages;
+       int ret, eq_for_mcc;
        struct be_queue_info *eq;
        struct be_dma_mem *mem;
-       struct be_mem_descriptor *mem_descr;
        void *eq_vaddress;
+       dma_addr_t paddr;
 
-       idx = 0;
-       eq = &phwi_context->be_eq.q;
-       mem = &eq->dma_mem;
-       mem_descr = phba->init_mem;
-       mem_descr += HWI_MEM_EQ;
-       eq_vaddress = mem_descr->mem_array[idx].virtual_address;
-
-       ret = be_fill_queue(eq, phba->params.num_eq_entries,
-                           sizeof(struct be_eq_entry), eq_vaddress);
-       if (ret) {
-               shost_printk(KERN_ERR, phba->shost,
-                            "be_fill_queue Failed for EQ \n");
-               return ret;
-       }
+       num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \
+                                     sizeof(struct be_eq_entry));
 
-       mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
+       if (phba->msix_enabled)
+               eq_for_mcc = 1;
+       else
+               eq_for_mcc = 0;
+       for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) {
+               eq = &phwi_context->be_eq[i].q;
+               mem = &eq->dma_mem;
+               phwi_context->be_eq[i].phba = phba;
+               eq_vaddress = pci_alloc_consistent(phba->pcidev,
+                                                    num_eq_pages * PAGE_SIZE,
+                                                    &paddr);
+               if (!eq_vaddress)
+                       goto create_eq_error;
+
+               mem->va = eq_vaddress;
+               ret = be_fill_queue(eq, phba->params.num_eq_entries,
+                                   sizeof(struct be_eq_entry), eq_vaddress);
+               if (ret) {
+                       shost_printk(KERN_ERR, phba->shost,
+                                    "be_fill_queue Failed for EQ\n");
+                       goto create_eq_error;
+               }
 
-       ret = beiscsi_cmd_eq_create(&phba->ctrl, eq,
-                                   phwi_context->be_eq.cur_eqd);
-       if (ret) {
-               shost_printk(KERN_ERR, phba->shost, "beiscsi_cmd_eq_create"
-                            "Failedfor EQ \n");
-               return ret;
+               mem->dma = paddr;
+               ret = beiscsi_cmd_eq_create(&phba->ctrl, eq,
+                                           phwi_context->cur_eqd);
+               if (ret) {
+                       shost_printk(KERN_ERR, phba->shost,
+                                    "beiscsi_cmd_eq_create"
+                                    "Failedfor EQ\n");
+                       goto create_eq_error;
+               }
+               SE_DEBUG(DBG_LVL_8, "eqid = %d\n", phwi_context->be_eq[i].q.id);
        }
-       SE_DEBUG(DBG_LVL_8, "eq id is %d\n", phwi_context->be_eq.q.id);
        return 0;
+create_eq_error:
+       for (i = 0; i < (phba->num_cpus + 1); i++) {
+               eq = &phwi_context->be_eq[i].q;
+               mem = &eq->dma_mem;
+               if (mem->va)
+                       pci_free_consistent(phba->pcidev, num_eq_pages
+                                           * PAGE_SIZE,
+                                           mem->va, mem->dma);
+       }
+       return ret;
 }
 
-static int beiscsi_create_cq(struct beiscsi_hba *phba,
+static int beiscsi_create_cqs(struct beiscsi_hba *phba,
                             struct hwi_context_memory *phwi_context)
 {
-       unsigned int idx;
+       unsigned int i, num_cq_pages;
        int ret;
        struct be_queue_info *cq, *eq;
        struct be_dma_mem *mem;
-       struct be_mem_descriptor *mem_descr;
+       struct be_eq_obj *pbe_eq;
        void *cq_vaddress;
+       dma_addr_t paddr;
 
-       idx = 0;
-       cq = &phwi_context->be_cq;
-       eq = &phwi_context->be_eq.q;
-       mem = &cq->dma_mem;
-       mem_descr = phba->init_mem;
-       mem_descr += HWI_MEM_CQ;
-       cq_vaddress = mem_descr->mem_array[idx].virtual_address;
-       ret = be_fill_queue(cq, phba->params.icds_per_ctrl / 2,
-                           sizeof(struct sol_cqe), cq_vaddress);
-       if (ret) {
-               shost_printk(KERN_ERR, phba->shost,
-                            "be_fill_queue Failed for ISCSI CQ \n");
-               return ret;
-       }
+       num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \
+                                     sizeof(struct sol_cqe));
 
-       mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
-       ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false, false, 0);
-       if (ret) {
-               shost_printk(KERN_ERR, phba->shost,
-                            "beiscsi_cmd_eq_create Failed for ISCSI CQ \n");
-               return ret;
+       for (i = 0; i < phba->num_cpus; i++) {
+               cq = &phwi_context->be_cq[i];
+               eq = &phwi_context->be_eq[i].q;
+               pbe_eq = &phwi_context->be_eq[i];
+               pbe_eq->cq = cq;
+               pbe_eq->phba = phba;
+               mem = &cq->dma_mem;
+               cq_vaddress = pci_alloc_consistent(phba->pcidev,
+                                                    num_cq_pages * PAGE_SIZE,
+                                                    &paddr);
+               if (!cq_vaddress)
+                       goto create_cq_error;
+               ret = be_fill_queue(cq, phba->params.num_cq_entries,
+                                   sizeof(struct sol_cqe), cq_vaddress);
+               if (ret) {
+                       shost_printk(KERN_ERR, phba->shost,
+                                    "be_fill_queue Failed for ISCSI CQ\n");
+                       goto create_cq_error;
+               }
+
+               mem->dma = paddr;
+               ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false,
+                                           false, 0);
+               if (ret) {
+                       shost_printk(KERN_ERR, phba->shost,
+                                    "beiscsi_cmd_eq_create"
+                                    "Failed for ISCSI CQ\n");
+                       goto create_cq_error;
+               }
+               SE_DEBUG(DBG_LVL_8, "iscsi cq_id is %d for eq_id %d\n",
+                                                cq->id, eq->id);
+               SE_DEBUG(DBG_LVL_8, "ISCSI CQ CREATED\n");
        }
-       SE_DEBUG(DBG_LVL_8, "iscsi cq id is %d\n", phwi_context->be_cq.id);
-       SE_DEBUG(DBG_LVL_8, "ISCSI CQ CREATED\n");
        return 0;
+
+create_cq_error:
+       for (i = 0; i < phba->num_cpus; i++) {
+               cq = &phwi_context->be_cq[i];
+               mem = &cq->dma_mem;
+               if (mem->va)
+                       pci_free_consistent(phba->pcidev, num_cq_pages
+                                           * PAGE_SIZE,
+                                           mem->va, mem->dma);
+       }
+       return ret;
+
 }
 
 static int
@@ -2132,7 +2777,7 @@ beiscsi_create_def_hdr(struct beiscsi_hba *phba,
 
        idx = 0;
        dq = &phwi_context->be_def_hdrq;
-       cq = &phwi_context->be_cq;
+       cq = &phwi_context->be_cq[0];
        mem = &dq->dma_mem;
        mem_descr = phba->init_mem;
        mem_descr += HWI_MEM_ASYNC_HEADER_RING;
@@ -2145,7 +2790,8 @@ beiscsi_create_def_hdr(struct beiscsi_hba *phba,
                             "be_fill_queue Failed for DEF PDU HDR\n");
                return ret;
        }
-       mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
+       mem->dma = (unsigned long)mem_descr->mem_array[idx].
+                                 bus_address.u.a64.address;
        ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq,
                                              def_pdu_ring_sz,
                                              phba->params.defpdu_hdr_sz);
@@ -2176,7 +2822,7 @@ beiscsi_create_def_data(struct beiscsi_hba *phba,
 
        idx = 0;
        dataq = &phwi_context->be_def_dataq;
-       cq = &phwi_context->be_cq;
+       cq = &phwi_context->be_cq[0];
        mem = &dataq->dma_mem;
        mem_descr = phba->init_mem;
        mem_descr += HWI_MEM_ASYNC_DATA_RING;
@@ -2189,7 +2835,8 @@ beiscsi_create_def_data(struct beiscsi_hba *phba,
                             "be_fill_queue Failed for DEF PDU DATA\n");
                return ret;
        }
-       mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
+       mem->dma = (unsigned long)mem_descr->mem_array[idx].
+                                 bus_address.u.a64.address;
        ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq,
                                              def_pdu_ring_sz,
                                              phba->params.defpdu_data_sz);
@@ -2203,7 +2850,7 @@ beiscsi_create_def_data(struct beiscsi_hba *phba,
        SE_DEBUG(DBG_LVL_8, "iscsi def data id is %d\n",
                 phwi_context->be_def_dataq.id);
        hwi_post_async_buffers(phba, 0);
-       SE_DEBUG(DBG_LVL_8, "DEFAULT PDU DATA RING CREATED \n");
+       SE_DEBUG(DBG_LVL_8, "DEFAULT PDU DATA RING CREATED\n");
        return 0;
 }
 
@@ -2235,7 +2882,31 @@ beiscsi_post_pages(struct beiscsi_hba *phba)
                }
                pm_arr++;
        }
-       SE_DEBUG(DBG_LVL_8, "POSTED PAGES \n");
+       SE_DEBUG(DBG_LVL_8, "POSTED PAGES\n");
+       return 0;
+}
+
+static void be_queue_free(struct beiscsi_hba *phba, struct be_queue_info *q)
+{
+       struct be_dma_mem *mem = &q->dma_mem;
+       if (mem->va)
+               pci_free_consistent(phba->pcidev, mem->size,
+                       mem->va, mem->dma);
+}
+
+static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q,
+               u16 len, u16 entry_size)
+{
+       struct be_dma_mem *mem = &q->dma_mem;
+
+       memset(q, 0, sizeof(*q));
+       q->len = len;
+       q->entry_size = entry_size;
+       mem->size = len * entry_size;
+       mem->va = pci_alloc_consistent(phba->pcidev, mem->size, &mem->dma);
+       if (!mem->va)
+               return -ENOMEM;
+       memset(mem->va, 0, mem->size);
        return 0;
 }
 
@@ -2306,9 +2977,11 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
                if (status != 0) {
                        shost_printk(KERN_ERR, phba->shost,
                                     "wrbq create failed.");
+                       kfree(pwrb_arr);
                        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;
@@ -2328,13 +3001,29 @@ static void free_wrb_handles(struct beiscsi_hba *phba)
        }
 }
 
+static void be_mcc_queues_destroy(struct beiscsi_hba *phba)
+{
+       struct be_queue_info *q;
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+
+       q = &phba->ctrl.mcc_obj.q;
+       if (q->created)
+               beiscsi_cmd_q_destroy(ctrl, q, QTYPE_MCCQ);
+       be_queue_free(phba, q);
+
+       q = &phba->ctrl.mcc_obj.cq;
+       if (q->created)
+               beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);
+       be_queue_free(phba, q);
+}
+
 static void hwi_cleanup(struct beiscsi_hba *phba)
 {
        struct be_queue_info *q;
        struct be_ctrl_info *ctrl = &phba->ctrl;
        struct hwi_controller *phwi_ctrlr;
        struct hwi_context_memory *phwi_context;
-       int i;
+       int i, eq_num;
 
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -2343,7 +3032,6 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
                if (q->created)
                        beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ);
        }
-
        free_wrb_handles(phba);
 
        q = &phwi_context->be_def_hdrq;
@@ -2356,13 +3044,76 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
 
        beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
 
-       q = &phwi_context->be_cq;
-       if (q->created)
-               beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);
+       for (i = 0; i < (phba->num_cpus); i++) {
+               q = &phwi_context->be_cq[i];
+               if (q->created)
+                       beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);
+       }
+       if (phba->msix_enabled)
+               eq_num = 1;
+       else
+               eq_num = 0;
+       for (i = 0; i < (phba->num_cpus + eq_num); i++) {
+               q = &phwi_context->be_eq[i].q;
+               if (q->created)
+                       beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
+       }
+       be_mcc_queues_destroy(phba);
+}
 
-       q = &phwi_context->be_eq.q;
-       if (q->created)
-               beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
+static int be_mcc_queues_create(struct beiscsi_hba *phba,
+                               struct hwi_context_memory *phwi_context)
+{
+       struct be_queue_info *q, *cq;
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+
+       /* Alloc MCC compl queue */
+       cq = &phba->ctrl.mcc_obj.cq;
+       if (be_queue_alloc(phba, cq, MCC_CQ_LEN,
+                       sizeof(struct be_mcc_compl)))
+               goto err;
+       /* Ask BE to create MCC compl queue; */
+       if (phba->msix_enabled) {
+               if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq
+                                        [phba->num_cpus].q, false, true, 0))
+               goto mcc_cq_free;
+       } else {
+               if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq[0].q,
+                                         false, true, 0))
+               goto mcc_cq_free;
+       }
+
+       /* Alloc MCC queue */
+       q = &phba->ctrl.mcc_obj.q;
+       if (be_queue_alloc(phba, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb)))
+               goto mcc_cq_destroy;
+
+       /* Ask BE to create MCC queue */
+       if (beiscsi_cmd_mccq_create(phba, q, cq))
+               goto mcc_q_free;
+
+       return 0;
+
+mcc_q_free:
+       be_queue_free(phba, q);
+mcc_cq_destroy:
+       beiscsi_cmd_q_destroy(ctrl, cq, QTYPE_CQ);
+mcc_cq_free:
+       be_queue_free(phba, cq);
+err:
+       return -ENOMEM;
+}
+
+static int find_num_cpus(void)
+{
+       int  num_cpus = 0;
+
+       num_cpus = num_online_cpus();
+       if (num_cpus >= MAX_CPUS)
+               num_cpus = MAX_CPUS - 1;
+
+       SE_DEBUG(DBG_LVL_8, "num_cpus = %d\n", num_cpus);
+       return num_cpus;
 }
 
 static int hwi_init_port(struct beiscsi_hba *phba)
@@ -2376,34 +3127,30 @@ static int hwi_init_port(struct beiscsi_hba *phba)
        def_pdu_ring_sz =
                phba->params.asyncpdus_per_ctrl * sizeof(struct phys_addr);
        phwi_ctrlr = phba->phwi_ctrlr;
-
        phwi_context = phwi_ctrlr->phwi_ctxt;
-       phwi_context->be_eq.max_eqd = 0;
-       phwi_context->be_eq.min_eqd = 0;
-       phwi_context->be_eq.cur_eqd = 64;
-       phwi_context->be_eq.enable_aic = false;
+       phwi_context->max_eqd = 0;
+       phwi_context->min_eqd = 0;
+       phwi_context->cur_eqd = 64;
        be_cmd_fw_initialize(&phba->ctrl);
-       status = beiscsi_create_eq(phba, phwi_context);
+
+       status = beiscsi_create_eqs(phba, phwi_context);
        if (status != 0) {
-               shost_printk(KERN_ERR, phba->shost, "EQ not created \n");
+               shost_printk(KERN_ERR, phba->shost, "EQ not created\n");
                goto error;
        }
 
-       status = mgmt_check_supported_fw(ctrl);
-       if (status != 0) {
-               shost_printk(KERN_ERR, phba->shost,
-                            "Unsupported fw version \n");
+       status = be_mcc_queues_create(phba, phwi_context);
+       if (status != 0)
                goto error;
-       }
 
-       status = mgmt_get_fw_config(ctrl, phba);
+       status = mgmt_check_supported_fw(ctrl, phba);
        if (status != 0) {
                shost_printk(KERN_ERR, phba->shost,
-                            "Error getting fw config\n");
+                            "Unsupported fw version\n");
                goto error;
        }
 
-       status = beiscsi_create_cq(phba, phwi_context);
+       status = beiscsi_create_cqs(phba, phwi_context);
        if (status != 0) {
                shost_printk(KERN_ERR, phba->shost, "CQ not created\n");
                goto error;
@@ -2447,7 +3194,6 @@ error:
        return -ENOMEM;
 }
 
-
 static int hwi_init_controller(struct beiscsi_hba *phba)
 {
        struct hwi_controller *phwi_ctrlr;
@@ -2456,7 +3202,7 @@ static int hwi_init_controller(struct beiscsi_hba *phba)
        if (1 == phba->init_mem[HWI_MEM_ADDN_CONTEXT].num_elements) {
                phwi_ctrlr->phwi_ctxt = (struct hwi_context_memory *)phba->
                    init_mem[HWI_MEM_ADDN_CONTEXT].mem_array[0].virtual_address;
-               SE_DEBUG(DBG_LVL_8, " phwi_ctrlr->phwi_ctxt=%p \n",
+               SE_DEBUG(DBG_LVL_8, " phwi_ctrlr->phwi_ctxt=%p\n",
                         phwi_ctrlr->phwi_ctxt);
        } else {
                shost_printk(KERN_ERR, phba->shost,
@@ -2489,8 +3235,8 @@ static void beiscsi_free_mem(struct beiscsi_hba *phba)
                        pci_free_consistent(phba->pcidev,
                          mem_descr->mem_array[j - 1].size,
                          mem_descr->mem_array[j - 1].virtual_address,
-                         mem_descr->mem_array[j - 1].bus_address.
-                               u.a64.address);
+                         (unsigned long)mem_descr->mem_array[j - 1].
+                         bus_address.u.a64.address);
                }
                kfree(mem_descr->mem_array);
                mem_descr++;
@@ -2506,7 +3252,7 @@ static int beiscsi_init_controller(struct beiscsi_hba *phba)
        ret = beiscsi_get_memory(phba);
        if (ret < 0) {
                shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe -"
-                            "Failed in beiscsi_alloc_memory \n");
+                            "Failed in beiscsi_alloc_memory\n");
                return ret;
        }
 
@@ -2530,6 +3276,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
 
        phba->io_sgl_hndl_avbl = 0;
        phba->eh_sgl_hndl_avbl = 0;
+
        mem_descr_sglh = phba->init_mem;
        mem_descr_sglh += HWI_MEM_SGLH;
        if (1 == mem_descr_sglh->num_elements) {
@@ -2582,12 +3329,12 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
        }
        SE_DEBUG(DBG_LVL_8,
                 "phba->io_sgl_hndl_avbl=%d"
-                "phba->eh_sgl_hndl_avbl=%d \n",
+                "phba->eh_sgl_hndl_avbl=%d\n",
                 phba->io_sgl_hndl_avbl,
                 phba->eh_sgl_hndl_avbl);
        mem_descr_sg = phba->init_mem;
        mem_descr_sg += HWI_MEM_SGE;
-       SE_DEBUG(DBG_LVL_8, "\n mem_descr_sg->num_elements=%d \n",
+       SE_DEBUG(DBG_LVL_8, "\n mem_descr_sg->num_elements=%d\n",
                 mem_descr_sg->num_elements);
        arr_index = 0;
        idx = 0;
@@ -2608,7 +3355,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++;
        }
@@ -2623,7 +3370,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,
@@ -2631,16 +3378,16 @@ 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,
                             "Failed to allocate memory in "
-                            "hba_setup_cid_tbls \n");
+                            "hba_setup_cid_tbls\n");
                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;
@@ -2649,37 +3396,41 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
        return 0;
 }
 
-static unsigned char hwi_enable_intr(struct beiscsi_hba *phba)
+static void hwi_enable_intr(struct beiscsi_hba *phba)
 {
        struct be_ctrl_info *ctrl = &phba->ctrl;
        struct hwi_controller *phwi_ctrlr;
        struct hwi_context_memory *phwi_context;
        struct be_queue_info *eq;
        u8 __iomem *addr;
-       u32 reg;
+       u32 reg, i;
        u32 enabled;
 
        phwi_ctrlr = phba->phwi_ctrlr;
        phwi_context = phwi_ctrlr->phwi_ctxt;
 
-       eq = &phwi_context->be_eq.q;
        addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg +
                        PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
        reg = ioread32(addr);
-       SE_DEBUG(DBG_LVL_8, "reg =x%08x \n", reg);
 
        enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
        if (!enabled) {
                reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
-               SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr);
+               SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p\n", reg, addr);
                iowrite32(reg, addr);
-               SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id);
+       }
 
+       if (!phba->msix_enabled) {
+               eq = &phwi_context->be_eq[0].q;
+               SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id);
                hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
-       } else
-               shost_printk(KERN_WARNING, phba->shost,
-                            "In hwi_enable_intr, Not Enabled \n");
-       return true;
+       } else {
+               for (i = 0; i <= phba->num_cpus; i++) {
+                       eq = &phwi_context->be_eq[i].q;
+                       SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id);
+                       hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
+               }
+       }
 }
 
 static void hwi_disable_intr(struct beiscsi_hba *phba)
@@ -2695,7 +3446,146 @@ static void hwi_disable_intr(struct beiscsi_hba *phba)
                iowrite32(reg, addr);
        } else
                shost_printk(KERN_WARNING, phba->shost,
-                            "In hwi_disable_intr, Already Disabled \n");
+                            "In hwi_disable_intr, Already Disabled\n");
+}
+
+static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
+{
+       struct be_cmd_resp_get_boot_target *boot_resp;
+       struct be_cmd_resp_get_session *session_resp;
+       struct be_mcc_wrb *wrb;
+       struct be_dma_mem nonemb_cmd;
+       unsigned int tag, wrb_num;
+       unsigned short status, extd_status;
+       struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
+       int ret = -ENOMEM;
+
+       tag = beiscsi_get_boot_target(phba);
+       if (!tag) {
+               SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
+               return -EAGAIN;
+       } 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) {
+               SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
+                                   " status = %d extd_status = %d\n",
+                                   status, extd_status);
+               free_mcc_tag(&phba->ctrl, tag);
+               return -EBUSY;
+       }
+       wrb = queue_get_wrb(mccq, wrb_num);
+       free_mcc_tag(&phba->ctrl, tag);
+       boot_resp = embedded_payload(wrb);
+
+       if (boot_resp->boot_session_handle < 0) {
+               shost_printk(KERN_INFO, phba->shost, "No Boot Session.\n");
+               return -ENXIO;
+       }
+
+       nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
+                               sizeof(*session_resp),
+                               &nonemb_cmd.dma);
+       if (nonemb_cmd.va == NULL) {
+               SE_DEBUG(DBG_LVL_1,
+                        "Failed to allocate memory for"
+                        "beiscsi_get_session_info\n");
+               return -ENOMEM;
+       }
+
+       memset(nonemb_cmd.va, 0, sizeof(*session_resp));
+       tag = beiscsi_get_session_info(phba,
+               boot_resp->boot_session_handle, &nonemb_cmd);
+       if (!tag) {
+               SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info"
+                       " 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) {
+               SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info Failed"
+                                   " status = %d extd_status = %d\n",
+                                   status, extd_status);
+               free_mcc_tag(&phba->ctrl, tag);
+               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,
+              sizeof(struct mgmt_session_info));
+       ret = 0;
+
+boot_freemem:
+       pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
+                   nonemb_cmd.va, nonemb_cmd.dma);
+       return ret;
+}
+
+static void beiscsi_boot_release(void *data)
+{
+       struct beiscsi_hba *phba = data;
+
+       scsi_host_put(phba->shost);
+}
+
+static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
+{
+       struct iscsi_boot_kobj *boot_kobj;
+
+       /* get boot info using mgmt cmd */
+       if (beiscsi_get_boot_info(phba))
+               /* Try to see if we can carry on without this */
+               return 0;
+
+       phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
+       if (!phba->boot_kset)
+               return -ENOMEM;
+
+       /* get a ref because the show function will ref the phba */
+       if (!scsi_host_get(phba->shost))
+               goto free_kset;
+       boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
+                                            beiscsi_show_boot_tgt_info,
+                                            beiscsi_tgt_get_attr_visibility,
+                                            beiscsi_boot_release);
+       if (!boot_kobj)
+               goto put_shost;
+
+       if (!scsi_host_get(phba->shost))
+               goto free_kset;
+       boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
+                                               beiscsi_show_boot_ini_info,
+                                               beiscsi_ini_get_attr_visibility,
+                                               beiscsi_boot_release);
+       if (!boot_kobj)
+               goto put_shost;
+
+       if (!scsi_host_get(phba->shost))
+               goto free_kset;
+       boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
+                                              beiscsi_show_boot_eth_info,
+                                              beiscsi_eth_get_attr_visibility,
+                                              beiscsi_boot_release);
+       if (!boot_kobj)
+               goto put_shost;
+       return 0;
+
+put_shost:
+       scsi_host_put(phba->shost);
+free_kset:
+       iscsi_boot_destroy_kset(phba->boot_kset);
+       return -ENOMEM;
 }
 
 static int beiscsi_init_port(struct beiscsi_hba *phba)
@@ -2706,14 +3596,14 @@ static int beiscsi_init_port(struct beiscsi_hba *phba)
        if (ret < 0) {
                shost_printk(KERN_ERR, phba->shost,
                             "beiscsi_dev_probe - Failed in"
-                            "beiscsi_init_controller \n");
+                            "beiscsi_init_controller\n");
                return ret;
        }
        ret = beiscsi_init_sgl_handle(phba);
        if (ret < 0) {
                shost_printk(KERN_ERR, phba->shost,
                             "beiscsi_dev_probe - Failed in"
-                            "beiscsi_init_sgl_handle \n");
+                            "beiscsi_init_sgl_handle\n");
                goto do_cleanup_ctrlr;
        }
 
@@ -2738,30 +3628,44 @@ static void hwi_purge_eq(struct beiscsi_hba *phba)
        struct hwi_context_memory *phwi_context;
        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;
-       eq = &phwi_context->be_eq.q;
-       eqe = queue_tail_node(eq);
+       if (phba->msix_enabled)
+               eq_msix = 1;
+       else
+               eq_msix = 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);
+       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);
        }
 }
 
 static void beiscsi_clean_port(struct beiscsi_hba *phba)
 {
-       unsigned char mgmt_status;
+       int mgmt_status;
 
        mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0);
        if (mgmt_status)
                shost_printk(KERN_WARNING, phba->shost,
-                            "mgmt_epfw_cleanup FAILED \n");
-       hwi_cleanup(phba);
+                            "mgmt_epfw_cleanup FAILED\n");
+
        hwi_purge_eq(phba);
+       hwi_cleanup(phba);
        kfree(phba->io_sgl_hndl_base);
        kfree(phba->eh_sgl_hndl_base);
        kfree(phba->cid_array);
@@ -2782,7 +3686,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,
@@ -2846,8 +3751,8 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
        be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb));
 
        doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
-       doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) <<
-                                       DB_DEF_PDU_WRB_INDEX_SHIFT;
+       doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK)
+                            << DB_DEF_PDU_WRB_INDEX_SHIFT;
        doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
 
        iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
@@ -2856,7 +3761,7 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
 static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt,
                              int *index, int *age)
 {
-       *index = be32_to_cpu(itt) >> 16;
+       *index = (int)itt;
        if (age)
                *age = conn->session->age;
 }
@@ -2884,20 +3789,17 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
        dma_addr_t paddr;
 
        io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool,
-                                         GFP_KERNEL, &paddr);
-
+                                         GFP_ATOMIC, &paddr);
        if (!io_task->cmd_bhs)
                return -ENOMEM;
-
        io_task->bhs_pa.u.a64.address = paddr;
-       io_task->pwrb_handle = alloc_wrb_handle(phba,
-                                               beiscsi_conn->beiscsi_conn_cid,
-                                               task->itt);
-       io_task->pwrb_handle->pio_handle = task;
+       io_task->libiscsi_itt = (itt_t)task->itt;
        io_task->conn = beiscsi_conn;
 
        task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr;
        task->hdr_max = sizeof(struct be_cmd_bhs);
+       io_task->psgl_handle = NULL;
+       io_task->psgl_handle = NULL;
 
        if (task->sc) {
                spin_lock(&phba->io_sgl_lock);
@@ -2905,10 +3807,14 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                spin_unlock(&phba->io_sgl_lock);
                if (!io_task->psgl_handle)
                        goto free_hndls;
-
+               io_task->pwrb_handle = alloc_wrb_handle(phba,
+                                       beiscsi_conn->beiscsi_conn_cid -
+                                       phba->fw_config.iscsi_cid_start);
+               if (!io_task->pwrb_handle)
+                       goto free_io_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 *)
@@ -2920,9 +3826,20 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                                beiscsi_conn->login_in_progress = 1;
                                beiscsi_conn->plogin_sgl_handle =
                                                        io_task->psgl_handle;
+                               io_task->pwrb_handle =
+                                       alloc_wrb_handle(phba,
+                                       beiscsi_conn->beiscsi_conn_cid -
+                                       phba->fw_config.iscsi_cid_start);
+                               if (!io_task->pwrb_handle)
+                                       goto free_io_hndls;
+                               beiscsi_conn->plogin_wrb_handle =
+                                                       io_task->pwrb_handle;
+
                        } else {
                                io_task->psgl_handle =
                                                beiscsi_conn->plogin_sgl_handle;
+                               io_task->pwrb_handle =
+                                               beiscsi_conn->plogin_wrb_handle;
                        }
                } else {
                        spin_lock(&phba->mgmt_sgl_lock);
@@ -2930,21 +3847,43 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                        spin_unlock(&phba->mgmt_sgl_lock);
                        if (!io_task->psgl_handle)
                                goto free_hndls;
+                       io_task->pwrb_handle =
+                                       alloc_wrb_handle(phba,
+                                       beiscsi_conn->beiscsi_conn_cid -
+                                       phba->fw_config.iscsi_cid_start);
+                       if (!io_task->pwrb_handle)
+                               goto free_mgmt_hndls;
+
                }
        }
-       itt = (itt_t) cpu_to_be32(((unsigned int)task->itt << 16) |
-                       (unsigned int)(io_task->psgl_handle->sgl_index));
+       itt = (itt_t) cpu_to_be32(((unsigned int)io_task->pwrb_handle->
+                                wrb_index << 16) | (unsigned int)
+                               (io_task->psgl_handle->sgl_index));
+       io_task->pwrb_handle->pio_handle = task;
+
        io_task->cmd_bhs->iscsi_hdr.itt = itt;
        return 0;
 
+free_io_hndls:
+       spin_lock(&phba->io_sgl_lock);
+       free_io_sgl_handle(phba, io_task->psgl_handle);
+       spin_unlock(&phba->io_sgl_lock);
+       goto free_hndls;
+free_mgmt_hndls:
+       spin_lock(&phba->mgmt_sgl_lock);
+       free_mgmt_sgl_handle(phba, io_task->psgl_handle);
+       spin_unlock(&phba->mgmt_sgl_lock);
 free_hndls:
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid];
-       free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
+       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;
        pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
                      io_task->bhs_pa.u.a64.address);
-       SE_DEBUG(DBG_LVL_1, "Alloc of SGL_ICD Failed \n");
+       SE_DEBUG(DBG_LVL_1, "Alloc of SGL_ICD Failed\n");
        return -ENOMEM;
 }
 
@@ -2959,7 +3898,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;
@@ -2978,7 +3918,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
                        io_task->psgl_handle = NULL;
                }
        } else {
-               if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN)
+               if (task->hdr &&
+                  ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN))
                        return;
                if (io_task->psgl_handle) {
                        spin_lock(&phba->mgmt_sgl_lock);
@@ -3006,7 +3947,6 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
        io_task->bhs_len = sizeof(struct be_cmd_bhs);
 
        if (writedir) {
-               SE_DEBUG(DBG_LVL_4, " WRITE Command \t");
                memset(&io_task->cmd_bhs->iscsi_data_pdu, 0, 48);
                AMAP_SET_BITS(struct amap_pdu_data_out, itt,
                              &io_task->cmd_bhs->iscsi_data_pdu,
@@ -3016,20 +3956,20 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
                              ISCSI_OPCODE_SCSI_DATA_OUT);
                AMAP_SET_BITS(struct amap_pdu_data_out, final_bit,
                              &io_task->cmd_bhs->iscsi_data_pdu, 1);
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
+                             INI_WR_CMD);
                AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
        } else {
-               SE_DEBUG(DBG_LVL_4, "READ Command \t");
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_RD_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
+                             INI_RD_CMD);
                AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
        }
        memcpy(&io_task->cmd_bhs->iscsi_data_pdu.
               dw[offsetof(struct amap_pdu_data_out, lun) / 32],
-              io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
+              &io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
 
        AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
-                     cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr.
-                                 lun[0]));
+                     cpu_to_be16(*(unsigned short *)&io_task->cmd_bhs->iscsi_hdr.lun));
        AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
        AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
                      io_task->pwrb_handle->wrb_index);
@@ -3055,15 +3995,17 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
 
 static int beiscsi_mtask(struct iscsi_task *task)
 {
-       struct beiscsi_io_task *aborted_io_task, *io_task = task->dd_data;
+       struct beiscsi_io_task *io_task = task->dd_data;
        struct iscsi_conn *conn = task->conn;
        struct beiscsi_conn *beiscsi_conn = conn->dd_data;
        struct beiscsi_hba *phba = beiscsi_conn->phba;
        struct iscsi_wrb *pwrb = NULL;
        unsigned int doorbell = 0;
-       struct iscsi_task *aborted_task;
+       unsigned int cid;
 
+       cid = beiscsi_conn->beiscsi_conn_cid;
        pwrb = io_task->pwrb_handle->pwrb;
+       memset(pwrb, 0, sizeof(*pwrb));
        AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
                      be32_to_cpu(task->cmdsn));
        AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
@@ -3073,56 +4015,58 @@ static int beiscsi_mtask(struct iscsi_task *task)
 
        switch (task->hdr->opcode & ISCSI_OPCODE_MASK) {
        case ISCSI_OP_LOGIN:
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, TGT_DM_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
+                             TGT_DM_CMD);
                AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
                AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1);
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_NOOP_OUT:
-               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, type, pwrb,
+                                     TGT_DM_CMD);
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt,
+                                     pwrb, 0);
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
+               } else {
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
+                                     INI_RD_CMD);
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
+               }
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_TEXT:
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD);
-               AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
+                             TGT_DM_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_SCSI_TMFUNC:
-               aborted_task = iscsi_itt_to_task(conn,
-                                       ((struct iscsi_tm *)task->hdr)->rtt);
-                if (!aborted_task)
-                       return 0;
-               aborted_io_task = aborted_task->dd_data;
-               if (!aborted_io_task->scsi_cmnd)
-                       return 0;
-
-               mgmt_invalidate_icds(phba,
-                                    aborted_io_task->psgl_handle->sgl_index,
-                                    beiscsi_conn->beiscsi_conn_cid);
-               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_TMF_CMD);
+               AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
+                             INI_TMF_CMD);
                AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
                hwi_write_buffer(pwrb, task);
                break;
        case ISCSI_OP_LOGOUT:
                AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
                AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
-                               HWH_TYPE_LOGOUT);
+                             HWH_TYPE_LOGOUT);
                hwi_write_buffer(pwrb, task);
                break;
 
        default:
-               SE_DEBUG(DBG_LVL_1, "opcode =%d Not supported \n",
+               SE_DEBUG(DBG_LVL_1, "opcode =%d Not supported\n",
                         task->hdr->opcode & ISCSI_OPCODE_MASK);
                return -EINVAL;
        }
 
        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));
 
-       doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
+       doorbell |= cid & DB_WRB_POST_CID_MASK;
        doorbell |= (io_task->pwrb_handle->wrb_index &
                     DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT;
        doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
@@ -3132,17 +4076,12 @@ static int beiscsi_mtask(struct iscsi_task *task)
 
 static int beiscsi_task_xmit(struct iscsi_task *task)
 {
-       struct iscsi_conn *conn = task->conn;
        struct beiscsi_io_task *io_task = task->dd_data;
        struct scsi_cmnd *sc = task->sc;
-       struct beiscsi_conn *beiscsi_conn = conn->dd_data;
        struct scatterlist *sg;
        int num_sg;
        unsigned int  writedir = 0, xferlen = 0;
 
-       SE_DEBUG(DBG_LVL_4, "\n cid=%d In beiscsi_task_xmit task=%p conn=%p \t"
-                "beiscsi_conn=%p \n", beiscsi_conn->beiscsi_conn_cid,
-                task, conn, beiscsi_conn);
        if (!sc)
                return beiscsi_mtask(task);
 
@@ -3152,13 +4091,11 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
                SE_DEBUG(DBG_LVL_1, " scsi_dma_map Failed\n")
                return num_sg;
        }
-       SE_DEBUG(DBG_LVL_4, "xferlen=0x%08x scmd=%p num_sg=%d sernum=%lu\n",
-                 (scsi_bufflen(sc)), sc, num_sg, sc->serial_number);
        xferlen = scsi_bufflen(sc);
        sg = scsi_sglist(sc);
        if (sc->sc_data_direction == DMA_TO_DEVICE) {
                writedir = 1;
-               SE_DEBUG(DBG_LVL_4, "task->imm_count=0x%08x \n",
+               SE_DEBUG(DBG_LVL_4, "task->imm_count=0x%08x\n",
                         task->imm_count);
        } else
                writedir = 0;
@@ -3168,53 +4105,122 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
 static void beiscsi_remove(struct pci_dev *pcidev)
 {
        struct beiscsi_hba *phba = NULL;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       struct be_eq_obj *pbe_eq;
+       unsigned int i, msix_vec;
+       u8 *real_offset = 0;
+       u32 value = 0;
 
        phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
        if (!phba) {
-               dev_err(&pcidev->dev, "beiscsi_remove called with no phba \n");
+               dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n");
                return;
        }
 
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
        hwi_disable_intr(phba);
-       if (phba->pcidev->irq)
-               free_irq(phba->pcidev->irq, phba);
+       if (phba->msix_enabled) {
+               for (i = 0; i <= phba->num_cpus; i++) {
+                       msix_vec = phba->msix_entries[i].vector;
+                       free_irq(msix_vec, &phwi_context->be_eq[i]);
+               }
+       } else
+               if (phba->pcidev->irq)
+                       free_irq(phba->pcidev->irq, phba);
+       pci_disable_msix(phba->pcidev);
        destroy_workqueue(phba->wq);
        if (blk_iopoll_enabled)
-               blk_iopoll_disable(&phba->iopoll);
+               for (i = 0; i < phba->num_cpus; i++) {
+                       pbe_eq = &phwi_context->be_eq[i];
+                       blk_iopoll_disable(&pbe_eq->iopoll);
+               }
 
        beiscsi_clean_port(phba);
        beiscsi_free_mem(phba);
+       real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
+
+       value = readl((void *)real_offset);
+
+       if (value & 0x00010000) {
+               value &= 0xfffeffff;
+               writel(value, (void *)real_offset);
+       }
        beiscsi_unmap_pci_function(phba);
        pci_free_consistent(phba->pcidev,
                            phba->ctrl.mbox_mem_alloced.size,
                            phba->ctrl.mbox_mem_alloced.va,
                            phba->ctrl.mbox_mem_alloced.dma);
+       iscsi_boot_destroy_kset(phba->boot_kset);
        iscsi_host_remove(phba->shost);
        pci_dev_put(phba->pcidev);
        iscsi_host_free(phba->shost);
 }
 
+static void beiscsi_msix_enable(struct beiscsi_hba *phba)
+{
+       int i, status;
+
+       for (i = 0; i <= phba->num_cpus; i++)
+               phba->msix_entries[i].entry = i;
+
+       status = pci_enable_msix(phba->pcidev, phba->msix_entries,
+                                (phba->num_cpus + 1));
+       if (!status)
+               phba->msix_enabled = true;
+
+       return;
+}
+
 static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                                const struct pci_device_id *id)
 {
        struct beiscsi_hba *phba = NULL;
-       int ret;
+       struct hwi_controller *phwi_ctrlr;
+       struct hwi_context_memory *phwi_context;
+       struct be_eq_obj *pbe_eq;
+       int ret, num_cpus, i;
+       u8 *real_offset = 0;
+       u32 value = 0;
 
        ret = beiscsi_enable_pci(pcidev);
        if (ret < 0) {
-               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
-                            "Failed to enable pci device \n");
+               dev_err(&pcidev->dev, "beiscsi_dev_probe-"
+                       " Failed to enable pci device\n");
                return ret;
        }
 
        phba = beiscsi_hba_alloc(pcidev);
        if (!phba) {
                dev_err(&pcidev->dev, "beiscsi_dev_probe-"
-                       " Failed in beiscsi_hba_alloc \n");
+                       " Failed in beiscsi_hba_alloc\n");
                goto disable_pci;
        }
 
-       pci_set_drvdata(pcidev, phba);
+       switch (pcidev->device) {
+       case BE_DEVICE_ID1:
+       case OC_DEVICE_ID1:
+       case OC_DEVICE_ID2:
+               phba->generation = BE_GEN2;
+               break;
+       case BE_DEVICE_ID2:
+       case OC_DEVICE_ID3:
+               phba->generation = BE_GEN3;
+               break;
+       default:
+               phba->generation = 0;
+       }
+
+       if (enable_msix)
+               num_cpus = find_num_cpus();
+       else
+               num_cpus = 1;
+       phba->num_cpus = num_cpus;
+       SE_DEBUG(DBG_LVL_8, "num_cpus = %d\n", phba->num_cpus);
+
+       if (enable_msix)
+               beiscsi_msix_enable(phba);
        ret = be_ctrl_init(phba, pcidev);
        if (ret) {
                shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
@@ -3222,10 +4228,45 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                goto hba_free;
        }
 
+       if (!num_hba) {
+               real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
+               value = readl((void *)real_offset);
+               if (value & 0x00010000) {
+                       gcrashmode++;
+                       shost_printk(KERN_ERR, phba->shost,
+                               "Loading Driver in crashdump mode\n");
+                       ret = beiscsi_pci_soft_reset(phba);
+                       if (ret) {
+                               shost_printk(KERN_ERR, phba->shost,
+                                       "Reset Failed. Aborting Crashdump\n");
+                               goto hba_free;
+                       }
+                       ret = be_chk_reset_complete(phba);
+                       if (ret) {
+                               shost_printk(KERN_ERR, phba->shost,
+                                       "Failed to get out of reset."
+                                       "Aborting Crashdump\n");
+                               goto hba_free;
+                       }
+               } else {
+                       value |= 0x00010000;
+                       writel(value, (void *)real_offset);
+                       num_hba++;
+               }
+       }
+
        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;
        beiscsi_get_params(phba);
+       phba->shost->can_queue = phba->params.ios_per_ctrl;
        ret = beiscsi_init_port(phba);
        if (ret < 0) {
                shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
@@ -3233,9 +4274,18 @@ 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_singlethread_workqueue(phba->wq_name);
+       phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1);
        if (!phba->wq) {
                shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
                                "Failed to allocate work queue\n");
@@ -3244,44 +4294,63 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 
        INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs);
 
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_context = phwi_ctrlr->phwi_ctxt;
        if (blk_iopoll_enabled) {
-               blk_iopoll_init(&phba->iopoll, be_iopoll_budget, be_iopoll);
-               blk_iopoll_enable(&phba->iopoll);
+               for (i = 0; i < phba->num_cpus; i++) {
+                       pbe_eq = &phwi_context->be_eq[i];
+                       blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget,
+                                       be_iopoll);
+                       blk_iopoll_enable(&pbe_eq->iopoll);
+               }
        }
-
        ret = beiscsi_init_irqs(phba);
        if (ret < 0) {
                shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
                             "Failed to beiscsi_init_irqs\n");
                goto free_blkenbld;
        }
-       ret = hwi_enable_intr(phba);
-       if (ret < 0) {
-               shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
-                            "Failed to hwi_enable_intr\n");
-               goto free_ctrlr;
-       }
+       hwi_enable_intr(phba);
 
-       SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED \n\n\n");
+       if (beiscsi_setup_boot_info(phba))
+               /*
+                * log error but continue, because we may not be using
+                * iscsi boot.
+                */
+               shost_printk(KERN_ERR, phba->shost, "Could not set up "
+                            "iSCSI boot info.");
+
+       SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
        return 0;
 
-free_ctrlr:
-       if (phba->pcidev->irq)
-               free_irq(phba->pcidev->irq, phba);
 free_blkenbld:
        destroy_workqueue(phba->wq);
        if (blk_iopoll_enabled)
-               blk_iopoll_disable(&phba->iopoll);
+               for (i = 0; i < phba->num_cpus; i++) {
+                       pbe_eq = &phwi_context->be_eq[i];
+                       blk_iopoll_disable(&pbe_eq->iopoll);
+               }
 free_twq:
        beiscsi_clean_port(phba);
        beiscsi_free_mem(phba);
 free_port:
+       real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
+
+       value = readl((void *)real_offset);
+
+       if (value & 0x00010000) {
+               value &= 0xfffeffff;
+               writel(value, (void *)real_offset);
+       }
+
        pci_free_consistent(phba->pcidev,
                            phba->ctrl.mbox_mem_alloced.size,
                            phba->ctrl.mbox_mem_alloced.va,
                           phba->ctrl.mbox_mem_alloced.dma);
        beiscsi_unmap_pci_function(phba);
 hba_free:
+       if (phba->msix_enabled)
+               pci_disable_msix(phba->pcidev);
        iscsi_host_remove(phba->shost);
        pci_dev_put(phba->pcidev);
        iscsi_host_free(phba->shost);
@@ -3293,32 +4362,8 @@ disable_pci:
 struct iscsi_transport beiscsi_iscsi_transport = {
        .owner = THIS_MODULE,
        .name = DRV_NAME,
-       .caps = CAP_RECOVERY_L0 | CAP_HDRDGST |
+       .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO |
                CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
-       .param_mask = ISCSI_MAX_RECV_DLENGTH |
-               ISCSI_MAX_XMIT_DLENGTH |
-               ISCSI_HDRDGST_EN |
-               ISCSI_DATADGST_EN |
-               ISCSI_INITIAL_R2T_EN |
-               ISCSI_MAX_R2T |
-               ISCSI_IMM_DATA_EN |
-               ISCSI_FIRST_BURST |
-               ISCSI_MAX_BURST |
-               ISCSI_PDU_INORDER_EN |
-               ISCSI_DATASEQ_INORDER_EN |
-               ISCSI_ERL |
-               ISCSI_CONN_PORT |
-               ISCSI_CONN_ADDRESS |
-               ISCSI_EXP_STATSN |
-               ISCSI_PERSISTENT_PORT |
-               ISCSI_PERSISTENT_ADDRESS |
-               ISCSI_TARGET_NAME | ISCSI_TPGT |
-               ISCSI_USERNAME | ISCSI_PASSWORD |
-               ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
-               ISCSI_FAST_ABORT | ISCSI_ABORT_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 |
                                ISCSI_HOST_INITIATOR_NAME,
        .create_session = beiscsi_session_create,
@@ -3326,18 +4371,20 @@ struct iscsi_transport beiscsi_iscsi_transport = {
        .create_conn = beiscsi_conn_create,
        .bind_conn = beiscsi_conn_bind,
        .destroy_conn = iscsi_conn_teardown,
+       .attr_is_visible = be2iscsi_attr_is_visible,
        .set_param = beiscsi_set_param,
-       .get_conn_param = beiscsi_conn_get_param,
+       .get_conn_param = iscsi_conn_get_param,
        .get_session_param = iscsi_session_get_param,
        .get_host_param = beiscsi_get_host_param,
        .start_conn = beiscsi_conn_start,
-       .stop_conn = beiscsi_conn_stop,
+       .stop_conn = iscsi_conn_stop,
        .send_pdu = iscsi_conn_send_pdu,
        .xmit_task = beiscsi_task_xmit,
        .cleanup_task = beiscsi_cleanup_task,
        .alloc_pdu = beiscsi_alloc_pdu,
        .parse_pdu_itt = beiscsi_parse_pdu,
        .get_stats = beiscsi_conn_get_stats,
+       .get_ep_param = beiscsi_ep_get_param,
        .ep_connect = beiscsi_ep_connect,
        .ep_poll = beiscsi_ep_poll,
        .ep_disconnect = beiscsi_ep_disconnect,
@@ -3351,6 +4398,7 @@ static struct pci_driver beiscsi_pci_driver = {
        .id_table = beiscsi_pci_id_table
 };
 
+
 static int __init beiscsi_module_init(void)
 {
        int ret;
@@ -3361,9 +4409,9 @@ static int __init beiscsi_module_init(void)
                SE_DEBUG(DBG_LVL_1,
                         "beiscsi_module_init - Unable to  register beiscsi"
                         "transport.\n");
-               ret = -ENOMEM;
+               return -ENOMEM;
        }
-       SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p \n",
+       SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p\n",
                 &beiscsi_iscsi_transport);
 
        ret = pci_register_driver(&beiscsi_pci_driver);