OSDN Git Service

Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[uclinux-h8/linux.git] / drivers / scsi / megaraid / megaraid_sas_base.c
index 4c3fc0e..71b884d 100644 (file)
@@ -94,8 +94,8 @@ MODULE_PARM_DESC(smp_affinity_enable, "SMP affinity feature enable/disbale Defau
 
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEGASAS_VERSION);
-MODULE_AUTHOR("megaraidlinux@lsi.com");
-MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
+MODULE_AUTHOR("megaraidlinux.pdl@avagotech.com");
+MODULE_DESCRIPTION("Avago MegaRAID SAS Driver");
 
 int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
 static int megasas_get_pd_list(struct megasas_instance *instance);
@@ -215,7 +215,6 @@ struct megasas_cmd *megasas_get_cmd(struct megasas_instance
                cmd = list_entry((&instance->cmd_pool)->next,
                                 struct megasas_cmd, list);
                list_del_init(&cmd->list);
-               atomic_set(&cmd->mfi_mpt_pthr, MFI_MPT_DETACHED);
        } else {
                printk(KERN_ERR "megasas: Command pool empty!\n");
        }
@@ -225,52 +224,41 @@ struct megasas_cmd *megasas_get_cmd(struct megasas_instance
 }
 
 /**
- * __megasas_return_cmd -      Return a cmd to free command pool
+ * megasas_return_cmd -        Return a cmd to free command pool
  * @instance:          Adapter soft state
  * @cmd:               Command packet to be returned to free command pool
  */
 inline void
-__megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
 {
-       /*
-        * Don't go ahead and free the MFI frame, if corresponding
-        * MPT frame is not freed(valid for only fusion adapters).
-        * In case of MFI adapters, anyways for any allocated MFI
-        * frame will have cmd->mfi_mpt_mpthr set to MFI_MPT_DETACHED
+       unsigned long flags;
+       u32 blk_tags;
+       struct megasas_cmd_fusion *cmd_fusion;
+       struct fusion_context *fusion = instance->ctrl_context;
+
+       /* This flag is used only for fusion adapter.
+        * Wait for Interrupt for Polled mode DCMD
         */
-       if (atomic_read(&cmd->mfi_mpt_pthr) != MFI_MPT_DETACHED)
+       if (cmd->flags & DRV_DCMD_POLLED_MODE)
                return;
 
+       spin_lock_irqsave(&instance->mfi_pool_lock, flags);
+
+       if (fusion) {
+               blk_tags = instance->max_scsi_cmds + cmd->index;
+               cmd_fusion = fusion->cmd_list[blk_tags];
+               megasas_return_cmd_fusion(instance, cmd_fusion);
+       }
        cmd->scmd = NULL;
        cmd->frame_count = 0;
-       cmd->is_wait_event = 0;
-       cmd->mpt_pthr_cmd_blocked = NULL;
-
-       if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
-           (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
-           (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) &&
-           (reset_devices))
+       cmd->flags = 0;
+       if (!fusion && reset_devices)
                cmd->frame->hdr.cmd = MFI_CMD_INVALID;
-
-       atomic_set(&cmd->mfi_mpt_pthr, MFI_LIST_ADDED);
        list_add(&cmd->list, (&instance->cmd_pool)->next);
-}
-
-/**
- * megasas_return_cmd -        Return a cmd to free command pool
- * @instance:          Adapter soft state
- * @cmd:               Command packet to be returned to free command pool
- */
-inline void
-megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
-{
-       unsigned long flags;
 
-       spin_lock_irqsave(&instance->mfi_pool_lock, flags);
-       __megasas_return_cmd(instance, cmd);
        spin_unlock_irqrestore(&instance->mfi_pool_lock, flags);
-}
 
+}
 
 /**
 *      The following functions are defined for xscale
@@ -814,8 +802,8 @@ megasas_adp_reset_gen2(struct megasas_instance *instance,
 {
        u32                     retry = 0 ;
        u32                     HostDiag;
-       u32                     *seq_offset = &reg_set->seq_offset;
-       u32                     *hostdiag_offset = &reg_set->host_diag;
+       u32 __iomem             *seq_offset = &reg_set->seq_offset;
+       u32 __iomem             *hostdiag_offset = &reg_set->host_diag;
 
        if (instance->instancet == &megasas_instance_template_skinny) {
                seq_offset = &reg_set->fusion_seq_offset;
@@ -910,7 +898,7 @@ extern struct megasas_instance_template megasas_instance_template_fusion;
  * @instance:                  Adapter soft state
  * @cmd:                       Command packet to be issued
  *
- * For polling, MFI requires the cmd_status to be set to 0xFF before posting.
+ * For polling, MFI requires the cmd_status to be set to MFI_STAT_INVALID_STATUS before posting.
  */
 int
 megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
@@ -952,20 +940,20 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance,
                          struct megasas_cmd *cmd, int timeout)
 {
        int ret = 0;
-       cmd->cmd_status = ENODATA;
+       cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
 
-       cmd->is_wait_event = 1;
        instance->instancet->issue_dcmd(instance, cmd);
        if (timeout) {
                ret = wait_event_timeout(instance->int_cmd_wait_q,
-                               cmd->cmd_status != ENODATA, timeout * HZ);
+                               cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ);
                if (!ret)
                        return 1;
        } else
                wait_event(instance->int_cmd_wait_q,
-                               cmd->cmd_status != ENODATA);
+                               cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS);
 
-       return 0;
+       return (cmd->cmd_status_drv == MFI_STAT_OK) ?
+               0 : 1;
 }
 
 /**
@@ -998,7 +986,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
         * Prepare and issue the abort frame
         */
        abort_fr->cmd = MFI_CMD_ABORT;
-       abort_fr->cmd_status = 0xFF;
+       abort_fr->cmd_status = MFI_STAT_INVALID_STATUS;
        abort_fr->flags = cpu_to_le16(0);
        abort_fr->abort_context = cpu_to_le32(cmd_to_abort->index);
        abort_fr->abort_mfi_phys_addr_lo =
@@ -1007,13 +995,13 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
                cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr));
 
        cmd->sync_cmd = 1;
-       cmd->cmd_status = ENODATA;
+       cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
 
        instance->instancet->issue_dcmd(instance, cmd);
 
        if (timeout) {
                ret = wait_event_timeout(instance->abort_cmd_wait_q,
-                               cmd->cmd_status != ENODATA, timeout * HZ);
+                               cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ);
                if (!ret) {
                        dev_err(&instance->pdev->dev, "Command timedout"
                                "from %s\n", __func__);
@@ -1021,7 +1009,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
                }
        } else
                wait_event(instance->abort_cmd_wait_q,
-                               cmd->cmd_status != ENODATA);
+                               cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS);
 
        cmd->sync_cmd = 0;
 
@@ -1196,7 +1184,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
        struct megasas_pthru_frame *pthru;
 
        is_logical = MEGASAS_IS_LOGICAL(scp);
-       device_id = MEGASAS_DEV_INDEX(instance, scp);
+       device_id = MEGASAS_DEV_INDEX(scp);
        pthru = (struct megasas_pthru_frame *)cmd->frame;
 
        if (scp->sc_data_direction == PCI_DMA_TODEVICE)
@@ -1232,7 +1220,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
        */
        if (scp->device->type == TYPE_TAPE) {
                if ((scp->request->timeout / HZ) > 0xFFFF)
-                       pthru->timeout = 0xFFFF;
+                       pthru->timeout = cpu_to_le16(0xFFFF);
                else
                        pthru->timeout = cpu_to_le16(scp->request->timeout / HZ);
        }
@@ -1294,7 +1282,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
        u16 flags = 0;
        struct megasas_io_frame *ldio;
 
-       device_id = MEGASAS_DEV_INDEX(instance, scp);
+       device_id = MEGASAS_DEV_INDEX(scp);
        ldio = (struct megasas_io_frame *)cmd->frame;
 
        if (scp->sc_data_direction == PCI_DMA_TODEVICE)
@@ -1698,7 +1686,7 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
 * @instance:                           Adapter soft state
 *
 */
-void megasas_complete_outstanding_ioctls(struct megasas_instance *instance)
+static void megasas_complete_outstanding_ioctls(struct megasas_instance *instance)
 {
        int i;
        struct megasas_cmd *cmd_mfi;
@@ -1922,22 +1910,24 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance,
        memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
 
        dcmd->cmd = MFI_CMD_DCMD;
-       dcmd->cmd_status = 0xFF;
+       dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
        dcmd->sge_count = 1;
-       dcmd->flags = MFI_FRAME_DIR_BOTH;
+       dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_BOTH);
        dcmd->timeout = 0;
        dcmd->pad_0 = 0;
-       dcmd->data_xfer_len = sizeof(struct MR_LD_VF_AFFILIATION_111);
-       dcmd->opcode = MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111;
+       dcmd->data_xfer_len =
+               cpu_to_le32(sizeof(struct MR_LD_VF_AFFILIATION_111));
+       dcmd->opcode = cpu_to_le32(MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111);
 
        if (initial)
                dcmd->sgl.sge32[0].phys_addr =
-                       instance->vf_affiliation_111_h;
+                       cpu_to_le32(instance->vf_affiliation_111_h);
        else
-               dcmd->sgl.sge32[0].phys_addr = new_affiliation_111_h;
+               dcmd->sgl.sge32[0].phys_addr =
+                       cpu_to_le32(new_affiliation_111_h);
 
-       dcmd->sgl.sge32[0].length =
-               sizeof(struct MR_LD_VF_AFFILIATION_111);
+       dcmd->sgl.sge32[0].length = cpu_to_le32(
+               sizeof(struct MR_LD_VF_AFFILIATION_111));
 
        printk(KERN_WARNING "megasas: SR-IOV: Getting LD/VF affiliation for "
               "scsi%d\n", instance->host->host_no);
@@ -1976,11 +1966,7 @@ out:
                                    new_affiliation_111_h);
        }
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
 
        return retval;
 }
@@ -2037,22 +2023,24 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance,
        memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
 
        dcmd->cmd = MFI_CMD_DCMD;
-       dcmd->cmd_status = 0xFF;
+       dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
        dcmd->sge_count = 1;
-       dcmd->flags = MFI_FRAME_DIR_BOTH;
+       dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_BOTH);
        dcmd->timeout = 0;
        dcmd->pad_0 = 0;
-       dcmd->data_xfer_len = (MAX_LOGICAL_DRIVES + 1) *
-               sizeof(struct MR_LD_VF_AFFILIATION);
-       dcmd->opcode = MR_DCMD_LD_VF_MAP_GET_ALL_LDS;
+       dcmd->data_xfer_len = cpu_to_le32((MAX_LOGICAL_DRIVES + 1) *
+               sizeof(struct MR_LD_VF_AFFILIATION));
+       dcmd->opcode = cpu_to_le32(MR_DCMD_LD_VF_MAP_GET_ALL_LDS);
 
        if (initial)
-               dcmd->sgl.sge32[0].phys_addr = instance->vf_affiliation_h;
+               dcmd->sgl.sge32[0].phys_addr =
+                       cpu_to_le32(instance->vf_affiliation_h);
        else
-               dcmd->sgl.sge32[0].phys_addr = new_affiliation_h;
+               dcmd->sgl.sge32[0].phys_addr =
+                       cpu_to_le32(new_affiliation_h);
 
-       dcmd->sgl.sge32[0].length = (MAX_LOGICAL_DRIVES + 1) *
-               sizeof(struct MR_LD_VF_AFFILIATION);
+       dcmd->sgl.sge32[0].length = cpu_to_le32((MAX_LOGICAL_DRIVES + 1) *
+               sizeof(struct MR_LD_VF_AFFILIATION));
 
        printk(KERN_WARNING "megasas: SR-IOV: Getting LD/VF affiliation for "
               "scsi%d\n", instance->host->host_no);
@@ -2147,11 +2135,7 @@ out:
                                    (MAX_LOGICAL_DRIVES + 1) *
                                    sizeof(struct MR_LD_VF_AFFILIATION),
                                    new_affiliation, new_affiliation_h);
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
 
        return retval;
 }
@@ -2204,39 +2188,33 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
 
        memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
 
-       dcmd->mbox.s[0] = sizeof(struct MR_CTRL_HB_HOST_MEM);
+       dcmd->mbox.s[0] = cpu_to_le16(sizeof(struct MR_CTRL_HB_HOST_MEM));
        dcmd->cmd = MFI_CMD_DCMD;
-       dcmd->cmd_status = 0xFF;
+       dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
        dcmd->sge_count = 1;
-       dcmd->flags = MFI_FRAME_DIR_BOTH;
+       dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_BOTH);
        dcmd->timeout = 0;
        dcmd->pad_0 = 0;
-       dcmd->data_xfer_len = sizeof(struct MR_CTRL_HB_HOST_MEM);
-       dcmd->opcode = MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC;
-       dcmd->sgl.sge32[0].phys_addr = instance->hb_host_mem_h;
-       dcmd->sgl.sge32[0].length = sizeof(struct MR_CTRL_HB_HOST_MEM);
+       dcmd->data_xfer_len = cpu_to_le32(sizeof(struct MR_CTRL_HB_HOST_MEM));
+       dcmd->opcode = cpu_to_le32(MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC);
+       dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(instance->hb_host_mem_h);
+       dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct MR_CTRL_HB_HOST_MEM));
 
        printk(KERN_WARNING "megasas: SR-IOV: Starting heartbeat for scsi%d\n",
               instance->host->host_no);
 
-       if (!megasas_issue_polled(instance, cmd)) {
-               retval = 0;
-       } else {
-               printk(KERN_WARNING "megasas: SR-IOV: MR_DCMD_CTRL_SHARED_HOST"
-                      "_MEM_ALLOC DCMD timed out for scsi%d\n",
-                      instance->host->host_no);
-               retval = 1;
-               goto out;
-       }
-
+       if (instance->ctrl_context && !instance->mask_interrupts)
+               retval = megasas_issue_blocked_cmd(instance, cmd,
+                       MEGASAS_ROUTINE_WAIT_TIME_VF);
+       else
+               retval = megasas_issue_polled(instance, cmd);
 
-       if (dcmd->cmd_status) {
-               printk(KERN_WARNING "megasas: SR-IOV: MR_DCMD_CTRL_SHARED_HOST"
-                      "_MEM_ALLOC DCMD failed with status 0x%x for scsi%d\n",
-                      dcmd->cmd_status,
-                      instance->host->host_no);
+       if (retval) {
+               dev_warn(&instance->pdev->dev, "SR-IOV: MR_DCMD_CTRL_SHARED_HOST"
+                       "_MEM_ALLOC DCMD %s for scsi%d\n",
+                       (dcmd->cmd_status == MFI_STAT_INVALID_STATUS) ?
+                       "timed out" : "failed", instance->host->host_no);
                retval = 1;
-               goto out;
        }
 
 out:
@@ -2332,7 +2310,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
                                                "reset queue\n",
                                                reset_cmd);
 
-                               reset_cmd->cmd_status = ENODATA;
+                               reset_cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
                                instance->instancet->fire_cmd(instance,
                                                reset_cmd->frame_phys_addr,
                                                0, instance->reg_set);
@@ -2612,11 +2590,7 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
 
        instance->aen_cmd = NULL;
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
 
        if ((instance->unload == 0) &&
                ((instance->issuepend_done == 1))) {
@@ -2786,7 +2760,7 @@ struct device_attribute *megaraid_host_attrs[] = {
 static struct scsi_host_template megasas_template = {
 
        .module = THIS_MODULE,
-       .name = "LSI SAS based MegaRAID driver",
+       .name = "Avago SAS based MegaRAID driver",
        .proc_name = "megaraid_sas",
        .slave_configure = megasas_slave_configure,
        .slave_alloc = megasas_slave_alloc,
@@ -2815,11 +2789,7 @@ static void
 megasas_complete_int_cmd(struct megasas_instance *instance,
                         struct megasas_cmd *cmd)
 {
-       cmd->cmd_status = cmd->frame->io.cmd_status;
-
-       if (cmd->cmd_status == ENODATA) {
-               cmd->cmd_status = 0;
-       }
+       cmd->cmd_status_drv = cmd->frame->io.cmd_status;
        wake_up(&instance->int_cmd_wait_q);
 }
 
@@ -2838,7 +2808,7 @@ megasas_complete_abort(struct megasas_instance *instance,
 {
        if (cmd->sync_cmd) {
                cmd->sync_cmd = 0;
-               cmd->cmd_status = 0;
+               cmd->cmd_status_drv = 0;
                wake_up(&instance->abort_cmd_wait_q);
        }
 
@@ -2978,8 +2948,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                                               "failed, status = 0x%x.\n",
                                               cmd->frame->hdr.cmd_status);
                                else {
-                                       megasas_return_mfi_mpt_pthr(instance,
-                                               cmd, cmd->mpt_pthr_cmd_blocked);
+                                       megasas_return_cmd(instance, cmd);
                                        spin_unlock_irqrestore(
                                                instance->host->host_lock,
                                                flags);
@@ -2987,8 +2956,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                                }
                        } else
                                instance->map_id++;
-                       megasas_return_mfi_mpt_pthr(instance, cmd,
-                               cmd->mpt_pthr_cmd_blocked);
+                       megasas_return_cmd(instance, cmd);
 
                        /*
                         * Set fast path IO to ZERO.
@@ -3086,7 +3054,7 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance)
                        printk(KERN_NOTICE "megasas: %p synchronous cmd"
                                                "on the internal reset queue,"
                                                "issue it again.\n", cmd);
-                       cmd->cmd_status = ENODATA;
+                       cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
                        instance->instancet->fire_cmd(instance,
                                                        cmd->frame_phys_addr ,
                                                        0, instance->reg_set);
@@ -3766,7 +3734,6 @@ int megasas_alloc_cmds(struct megasas_instance *instance)
                cmd = instance->cmd_list[i];
                memset(cmd, 0, sizeof(struct megasas_cmd));
                cmd->index = i;
-               atomic_set(&cmd->mfi_mpt_pthr, MFI_LIST_ADDED);
                cmd->scmd = NULL;
                cmd->instance = instance;
 
@@ -3827,7 +3794,7 @@ megasas_get_pd_list(struct megasas_instance *instance)
        dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
        dcmd->mbox.b[1] = 0;
        dcmd->cmd = MFI_CMD_DCMD;
-       dcmd->cmd_status = 0xFF;
+       dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
        dcmd->sge_count = 1;
        dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
        dcmd->timeout = 0;
@@ -3874,11 +3841,7 @@ megasas_get_pd_list(struct megasas_instance *instance)
                                MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
                                ci, ci_h);
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
 
        return ret;
 }
@@ -3927,7 +3890,7 @@ megasas_get_ld_list(struct megasas_instance *instance)
        if (instance->supportmax256vd)
                dcmd->mbox.b[0] = 1;
        dcmd->cmd = MFI_CMD_DCMD;
-       dcmd->cmd_status = 0xFF;
+       dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
        dcmd->sge_count = 1;
        dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
        dcmd->timeout = 0;
@@ -3965,11 +3928,7 @@ megasas_get_ld_list(struct megasas_instance *instance)
                                ci,
                                ci_h);
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
        return ret;
 }
 
@@ -4020,7 +3979,7 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
                dcmd->mbox.b[2] = 1;
 
        dcmd->cmd = MFI_CMD_DCMD;
-       dcmd->cmd_status = 0xFF;
+       dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
        dcmd->sge_count = 1;
        dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
        dcmd->timeout = 0;
@@ -4050,11 +4009,7 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
        pci_free_consistent(instance->pdev, sizeof(struct MR_LD_TARGETID_LIST),
                            ci, ci_h);
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
 
        return ret;
 }
@@ -4091,12 +4046,11 @@ static void megasas_update_ext_vd_details(struct megasas_instance *instance)
                instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
                instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
        }
-       dev_info(&instance->pdev->dev, "Firmware supports %d VD %d PD\n",
-               instance->fw_supported_vd_count,
-               instance->fw_supported_pd_count);
-       dev_info(&instance->pdev->dev, "Driver supports %d VD  %d PD\n",
-               instance->drv_supported_vd_count,
-               instance->drv_supported_pd_count);
+
+       dev_info(&instance->pdev->dev,
+               "firmware type\t: %s\n",
+               instance->supportmax256vd ? "Extended VD(240 VD)firmware" :
+               "Legacy(64 VD) firmware");
 
        old_map_sz =  sizeof(struct MR_FW_RAID_MAP) +
                                (sizeof(struct MR_LD_SPAN_MAP) *
@@ -4158,7 +4112,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance)
        memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
 
        dcmd->cmd = MFI_CMD_DCMD;
-       dcmd->cmd_status = 0xFF;
+       dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
        dcmd->sge_count = 1;
        dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
        dcmd->timeout = 0;
@@ -4181,16 +4135,17 @@ megasas_get_ctrl_info(struct megasas_instance *instance)
                le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
                le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
                megasas_update_ext_vd_details(instance);
+               instance->is_imr = (ctrl_info->memory_size ? 0 : 1);
+               dev_info(&instance->pdev->dev,
+                               "controller type\t: %s(%dMB)\n",
+                               instance->is_imr ? "iMR" : "MR",
+                               le16_to_cpu(ctrl_info->memory_size));
        }
 
        pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
                            ci, ci_h);
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
        return ret;
 }
 
@@ -4229,7 +4184,7 @@ int megasas_set_crash_dump_params(struct megasas_instance *instance,
        memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
        dcmd->mbox.b[0] = crash_buf_state;
        dcmd->cmd = MFI_CMD_DCMD;
-       dcmd->cmd_status = 0xFF;
+       dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
        dcmd->sge_count = 1;
        dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_NONE);
        dcmd->timeout = 0;
@@ -4245,11 +4200,7 @@ int megasas_set_crash_dump_params(struct megasas_instance *instance,
        else
                ret = megasas_issue_polled(instance, cmd);
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
        return ret;
 }
 
@@ -4262,7 +4213,7 @@ int megasas_set_crash_dump_params(struct megasas_instance *instance,
 static int
 megasas_issue_init_mfi(struct megasas_instance *instance)
 {
-       u32 context;
+       __le32 context;
 
        struct megasas_cmd *cmd;
 
@@ -4300,7 +4251,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
        initq_info->consumer_index_phys_addr_lo = cpu_to_le32(instance->consumer_h);
 
        init_frame->cmd = MFI_CMD_INIT;
-       init_frame->cmd_status = 0xFF;
+       init_frame->cmd_status = MFI_STAT_INVALID_STATUS;
        init_frame->queue_info_new_phys_addr_lo =
                cpu_to_le32(lower_32_bits(initq_info_h));
        init_frame->queue_info_new_phys_addr_hi =
@@ -4354,6 +4305,21 @@ megasas_init_adapter_mfi(struct megasas_instance *instance)
        instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >>
                                        0x10;
        /*
+        * For MFI skinny adapters, MEGASAS_SKINNY_INT_CMDS commands
+        * are reserved for IOCTL + driver's internal DCMDs.
+        */
+       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+               instance->max_scsi_cmds = (instance->max_fw_cmds -
+                       MEGASAS_SKINNY_INT_CMDS);
+               sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
+       } else {
+               instance->max_scsi_cmds = (instance->max_fw_cmds -
+                       MEGASAS_INT_CMDS);
+               sema_init(&instance->ioctl_sem, (MEGASAS_MFI_IOCTL_CMDS));
+       }
+
+       /*
         * Create a pool of commands
         */
        if (megasas_alloc_cmds(instance))
@@ -4414,6 +4380,107 @@ fail_alloc_cmds:
        return 1;
 }
 
+/*
+ * megasas_setup_irqs_msix -           register legacy interrupts.
+ * @instance:                          Adapter soft state
+ *
+ * Do not enable interrupt, only setup ISRs.
+ *
+ * Return 0 on success.
+ */
+static int
+megasas_setup_irqs_ioapic(struct megasas_instance *instance)
+{
+       struct pci_dev *pdev;
+
+       pdev = instance->pdev;
+       instance->irq_context[0].instance = instance;
+       instance->irq_context[0].MSIxIndex = 0;
+       if (request_irq(pdev->irq, instance->instancet->service_isr,
+               IRQF_SHARED, "megasas", &instance->irq_context[0])) {
+               dev_err(&instance->pdev->dev,
+                               "Failed to register IRQ from %s %d\n",
+                               __func__, __LINE__);
+               return -1;
+       }
+       return 0;
+}
+
+/**
+ * megasas_setup_irqs_msix -           register MSI-x interrupts.
+ * @instance:                          Adapter soft state
+ * @is_probe:                          Driver probe check
+ *
+ * Do not enable interrupt, only setup ISRs.
+ *
+ * Return 0 on success.
+ */
+static int
+megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe)
+{
+       int i, j, cpu;
+       struct pci_dev *pdev;
+
+       pdev = instance->pdev;
+
+       /* Try MSI-x */
+       cpu = cpumask_first(cpu_online_mask);
+       for (i = 0; i < instance->msix_vectors; i++) {
+               instance->irq_context[i].instance = instance;
+               instance->irq_context[i].MSIxIndex = i;
+               if (request_irq(instance->msixentry[i].vector,
+                       instance->instancet->service_isr, 0, "megasas",
+                       &instance->irq_context[i])) {
+                       dev_err(&instance->pdev->dev,
+                               "Failed to register IRQ for vector %d.\n", i);
+                       for (j = 0; j < i; j++) {
+                               if (smp_affinity_enable)
+                                       irq_set_affinity_hint(
+                                               instance->msixentry[j].vector, NULL);
+                               free_irq(instance->msixentry[j].vector,
+                                       &instance->irq_context[j]);
+                       }
+                       /* Retry irq register for IO_APIC*/
+                       instance->msix_vectors = 0;
+                       if (is_probe)
+                               return megasas_setup_irqs_ioapic(instance);
+                       else
+                               return -1;
+               }
+               if (smp_affinity_enable) {
+                       if (irq_set_affinity_hint(instance->msixentry[i].vector,
+                               get_cpu_mask(cpu)))
+                               dev_err(&instance->pdev->dev,
+                                       "Failed to set affinity hint"
+                                       " for cpu %d\n", cpu);
+                       cpu = cpumask_next(cpu, cpu_online_mask);
+               }
+       }
+       return 0;
+}
+
+/*
+ * megasas_destroy_irqs-               unregister interrupts.
+ * @instance:                          Adapter soft state
+ * return:                             void
+ */
+static void
+megasas_destroy_irqs(struct megasas_instance *instance) {
+
+       int i;
+
+       if (instance->msix_vectors)
+               for (i = 0; i < instance->msix_vectors; i++) {
+                       if (smp_affinity_enable)
+                               irq_set_affinity_hint(
+                                       instance->msixentry[i].vector, NULL);
+                       free_irq(instance->msixentry[i].vector,
+                                &instance->irq_context[i]);
+               }
+       else
+               free_irq(instance->pdev->irq, &instance->irq_context[0]);
+}
+
 /**
  * megasas_init_fw -   Initializes the FW
  * @instance:          Adapter soft state
@@ -4499,7 +4566,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
         * It is used for all MPT based Adapters.
         */
        instance->reply_post_host_index_addr[0] =
-               (u32 *)((u8 *)instance->reg_set +
+               (u32 __iomem *)((u8 __iomem *)instance->reg_set +
                MPI2_REPLY_POST_HOST_INDEX_OFFSET);
 
        /* Check if MSI-X is supported while in ready state */
@@ -4531,7 +4598,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
                         */
                        for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) {
                                instance->reply_post_host_index_addr[loop] =
-                                       (u32 *)((u8 *)instance->reg_set +
+                                       (u32 __iomem *)
+                                       ((u8 __iomem *)instance->reg_set +
                                        MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET
                                        + (loop * 0x10));
                        }
@@ -4551,14 +4619,19 @@ static int megasas_init_fw(struct megasas_instance *instance)
                        instance->msix_vectors = i;
                else
                        instance->msix_vectors = 0;
-
-               dev_info(&instance->pdev->dev, "[scsi%d]: FW supports"
-                       "<%d> MSIX vector,Online CPUs: <%d>,"
-                       "Current MSIX <%d>\n", instance->host->host_no,
-                       fw_msix_count, (unsigned int)num_online_cpus(),
-                       instance->msix_vectors);
        }
 
+       dev_info(&instance->pdev->dev,
+               "firmware supports msix\t: (%d)", fw_msix_count);
+       dev_info(&instance->pdev->dev,
+               "current msix/online cpus\t: (%d/%d)\n",
+               instance->msix_vectors, (unsigned int)num_online_cpus());
+
+       if (instance->msix_vectors ?
+               megasas_setup_irqs_msix(instance, 1) :
+               megasas_setup_irqs_ioapic(instance))
+               goto fail_setup_irqs;
+
        instance->ctrl_info = kzalloc(sizeof(struct megasas_ctrl_info),
                                GFP_KERNEL);
        if (instance->ctrl_info == NULL)
@@ -4574,6 +4647,11 @@ static int megasas_init_fw(struct megasas_instance *instance)
        if (instance->instancet->init_adapter(instance))
                goto fail_init_adapter;
 
+       tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
+               (unsigned long)instance);
+
+       instance->instancet->enable_intr(instance);
+
        printk(KERN_ERR "megasas: INIT adapter done\n");
 
        /** for passthrough
@@ -4584,7 +4662,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
                (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
        if (megasas_get_pd_list(instance) < 0) {
                printk(KERN_ERR "megasas: failed to get PD list\n");
-               goto fail_init_adapter;
+               goto fail_get_pd_list;
        }
 
        memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
@@ -4610,17 +4688,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
 
        tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
 
-       /*Check whether controller is iMR or MR */
-       if (ctrl_info->memory_size) {
-               instance->is_imr = 0;
-               dev_info(&instance->pdev->dev, "Controller type: MR,"
-                       "Memory size is: %dMB\n",
-                       le16_to_cpu(ctrl_info->memory_size));
-       } else {
-               instance->is_imr = 1;
-               dev_info(&instance->pdev->dev,
-                       "Controller type: iMR\n");
-       }
        instance->disableOnlineCtrlReset =
        ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
        instance->mpio = ctrl_info->adapterOperations2.mpio;
@@ -4628,9 +4695,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
                ctrl_info->adapterOperations2.supportUnevenSpans;
        if (instance->UnevenSpanSupport) {
                struct fusion_context *fusion = instance->ctrl_context;
-
-               dev_info(&instance->pdev->dev, "FW supports: "
-               "UnevenSpanSupport=%x\n", instance->UnevenSpanSupport);
                if (MR_ValidateMapInfo(instance))
                        fusion->fast_path_io = 1;
                else
@@ -4657,13 +4721,11 @@ static int megasas_init_fw(struct megasas_instance *instance)
        instance->crash_dump_drv_support =
                (instance->crash_dump_fw_support &&
                instance->crash_dump_buf);
-       if (instance->crash_dump_drv_support) {
-               dev_info(&instance->pdev->dev, "Firmware Crash dump "
-                       "feature is supported\n");
+       if (instance->crash_dump_drv_support)
                megasas_set_crash_dump_params(instance,
                        MR_CRASH_BUF_TURN_OFF);
 
-       else {
+       else {
                if (instance->crash_dump_buf)
                        pci_free_consistent(instance->pdev,
                                CRASH_DMA_BUF_SIZE,
@@ -4674,37 +4736,28 @@ static int megasas_init_fw(struct megasas_instance *instance)
 
        instance->secure_jbod_support =
                ctrl_info->adapterOperations3.supportSecurityonJBOD;
-       if (instance->secure_jbod_support)
-               dev_info(&instance->pdev->dev, "Firmware supports Secure JBOD\n");
+
+       dev_info(&instance->pdev->dev,
+               "pci id\t\t: (0x%04x)/(0x%04x)/(0x%04x)/(0x%04x)\n",
+               le16_to_cpu(ctrl_info->pci.vendor_id),
+               le16_to_cpu(ctrl_info->pci.device_id),
+               le16_to_cpu(ctrl_info->pci.sub_vendor_id),
+               le16_to_cpu(ctrl_info->pci.sub_device_id));
+       dev_info(&instance->pdev->dev, "unevenspan support      : %s\n",
+               instance->UnevenSpanSupport ? "yes" : "no");
+       dev_info(&instance->pdev->dev, "disable ocr             : %s\n",
+               instance->disableOnlineCtrlReset ? "yes" : "no");
+       dev_info(&instance->pdev->dev, "firmware crash dump     : %s\n",
+               instance->crash_dump_drv_support ? "yes" : "no");
+       dev_info(&instance->pdev->dev, "secure jbod             : %s\n",
+               instance->secure_jbod_support ? "yes" : "no");
+
+
        instance->max_sectors_per_req = instance->max_num_sge *
                                                PAGE_SIZE / 512;
        if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
                instance->max_sectors_per_req = tmp_sectors;
 
-       /*
-        * 1. For fusion adapters, 3 commands for IOCTL and 5 commands
-        *    for driver's internal DCMDs.
-        * 2. For MFI skinny adapters, 5 commands for IOCTL + driver's
-        *    internal DCMDs.
-        * 3. For rest of MFI adapters, 27 commands reserved for IOCTLs
-        *    and 5 commands for drivers's internal DCMD.
-        */
-       if (instance->ctrl_context) {
-               instance->max_scsi_cmds = instance->max_fw_cmds -
-                                       (MEGASAS_FUSION_INTERNAL_CMDS +
-                                       MEGASAS_FUSION_IOCTL_CMDS);
-               sema_init(&instance->ioctl_sem, MEGASAS_FUSION_IOCTL_CMDS);
-       } else if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
-               instance->max_scsi_cmds = instance->max_fw_cmds -
-                                               MEGASAS_SKINNY_INT_CMDS;
-               sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
-       } else {
-               instance->max_scsi_cmds = instance->max_fw_cmds -
-                                               MEGASAS_INT_CMDS;
-               sema_init(&instance->ioctl_sem, (MEGASAS_INT_CMDS - 5));
-       }
-
        /* Check for valid throttlequeuedepth module parameter */
        if (throttlequeuedepth &&
                        throttlequeuedepth <= instance->max_scsi_cmds)
@@ -4713,12 +4766,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
                instance->throttlequeuedepth =
                                MEGASAS_THROTTLE_QUEUE_DEPTH;
 
-        /*
-       * Setup tasklet for cmd completion
-       */
-
-       tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
-               (unsigned long)instance);
 
        /* Launch SR-IOV heartbeat timer */
        if (instance->requestorId) {
@@ -4733,7 +4780,14 @@ static int megasas_init_fw(struct megasas_instance *instance)
 
        return 0;
 
+fail_get_pd_list:
+       instance->instancet->disable_intr(instance);
 fail_init_adapter:
+       megasas_destroy_irqs(instance);
+fail_setup_irqs:
+       if (instance->msix_vectors)
+               pci_disable_msix(instance->pdev);
+       instance->msix_vectors = 0;
 fail_ready_state:
        kfree(instance->ctrl_info);
        instance->ctrl_info = NULL;
@@ -4822,21 +4876,17 @@ megasas_get_seq_num(struct megasas_instance *instance,
                /*
                 * Copy the data back into callers buffer
                 */
-               eli->newest_seq_num = le32_to_cpu(el_info->newest_seq_num);
-               eli->oldest_seq_num = le32_to_cpu(el_info->oldest_seq_num);
-               eli->clear_seq_num = le32_to_cpu(el_info->clear_seq_num);
-               eli->shutdown_seq_num = le32_to_cpu(el_info->shutdown_seq_num);
-               eli->boot_seq_num = le32_to_cpu(el_info->boot_seq_num);
+               eli->newest_seq_num = el_info->newest_seq_num;
+               eli->oldest_seq_num = el_info->oldest_seq_num;
+               eli->clear_seq_num = el_info->clear_seq_num;
+               eli->shutdown_seq_num = el_info->shutdown_seq_num;
+               eli->boot_seq_num = el_info->boot_seq_num;
        }
 
        pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info),
                            el_info, el_info_h);
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
 
        return 0;
 }
@@ -4877,8 +4927,8 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
 
        if (instance->aen_cmd) {
 
-               prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1];
-               prev_aen.members.locale = le16_to_cpu(prev_aen.members.locale);
+               prev_aen.word =
+                       le32_to_cpu(instance->aen_cmd->frame->dcmd.mbox.w[1]);
 
                /*
                 * A class whose enum value is smaller is inclusive of all
@@ -4990,7 +5040,7 @@ static int megasas_start_aen(struct megasas_instance *instance)
        class_locale.members.class = MR_EVT_CLASS_DEBUG;
 
        return megasas_register_aen(instance,
-                       eli.newest_seq_num + 1,
+                       le32_to_cpu(eli.newest_seq_num) + 1,
                        class_locale.word);
 }
 
@@ -5001,6 +5051,7 @@ static int megasas_start_aen(struct megasas_instance *instance)
 static int megasas_io_attach(struct megasas_instance *instance)
 {
        struct Scsi_Host *host = instance->host;
+       u32             error;
 
        /*
         * Export parameters required by SCSI mid-layer
@@ -5050,12 +5101,21 @@ static int megasas_io_attach(struct megasas_instance *instance)
                host->hostt->eh_device_reset_handler = NULL;
                host->hostt->eh_bus_reset_handler = NULL;
        }
+       error = scsi_init_shared_tag_map(host, host->can_queue);
+       if (error) {
+               dev_err(&instance->pdev->dev,
+                       "Failed to shared tag from %s %d\n",
+                       __func__, __LINE__);
+               return -ENODEV;
+       }
 
        /*
         * Notify the mid-layer about the new controller
         */
        if (scsi_add_host(host, &instance->pdev->dev)) {
-               printk(KERN_DEBUG "megasas: scsi_add_host failed\n");
+               dev_err(&instance->pdev->dev,
+                       "Failed to add host from %s %d\n",
+                       __func__, __LINE__);
                return -ENODEV;
        }
 
@@ -5106,7 +5166,7 @@ fail_set_dma_mask:
 static int megasas_probe_one(struct pci_dev *pdev,
                             const struct pci_device_id *id)
 {
-       int rval, pos, i, j, cpu;
+       int rval, pos;
        struct Scsi_Host *host;
        struct megasas_instance *instance;
        u16 control = 0;
@@ -5129,16 +5189,6 @@ static int megasas_probe_one(struct pci_dev *pdev,
        }
 
        /*
-        * Announce PCI information
-        */
-       printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
-              pdev->vendor, pdev->device, pdev->subsystem_vendor,
-              pdev->subsystem_device);
-
-       printk("bus %d:slot %d:func %d\n",
-              pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
-
-       /*
         * PCI prepping: enable device set bus mastering and dma mask
         */
        rval = pci_enable_device_mem(pdev);
@@ -5183,8 +5233,6 @@ static int megasas_probe_one(struct pci_dev *pdev,
                fusion = instance->ctrl_context;
                memset(fusion, 0,
                        ((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
-               INIT_LIST_HEAD(&fusion->cmd_pool);
-               spin_lock_init(&fusion->mpt_pool_lock);
        }
        break;
        default: /* For all other supported controllers */
@@ -5207,6 +5255,13 @@ static int megasas_probe_one(struct pci_dev *pdev,
                break;
        }
 
+       instance->system_info_buf = pci_zalloc_consistent(pdev,
+                                       sizeof(struct MR_DRV_SYSTEM_INFO),
+                                       &instance->system_info_h);
+
+       if (!instance->system_info_buf)
+               dev_info(&instance->pdev->dev, "Can't allocate system info buffer\n");
+
        /* Crash dump feature related initialisation*/
        instance->drv_buf_index = 0;
        instance->drv_buf_alloc = 0;
@@ -5315,55 +5370,6 @@ static int megasas_probe_one(struct pci_dev *pdev,
                }
        }
 
-retry_irq_register:
-       /*
-        * Register IRQ
-        */
-       if (instance->msix_vectors) {
-               cpu = cpumask_first(cpu_online_mask);
-               for (i = 0; i < instance->msix_vectors; i++) {
-                       instance->irq_context[i].instance = instance;
-                       instance->irq_context[i].MSIxIndex = i;
-                       if (request_irq(instance->msixentry[i].vector,
-                                       instance->instancet->service_isr, 0,
-                                       "megasas",
-                                       &instance->irq_context[i])) {
-                               printk(KERN_DEBUG "megasas: Failed to "
-                                      "register IRQ for vector %d.\n", i);
-                               for (j = 0; j < i; j++) {
-                                       if (smp_affinity_enable)
-                                               irq_set_affinity_hint(
-                                                       instance->msixentry[j].vector, NULL);
-                                       free_irq(
-                                               instance->msixentry[j].vector,
-                                               &instance->irq_context[j]);
-                               }
-                               /* Retry irq register for IO_APIC */
-                               instance->msix_vectors = 0;
-                               goto retry_irq_register;
-                       }
-                       if (smp_affinity_enable) {
-                               if (irq_set_affinity_hint(instance->msixentry[i].vector,
-                                       get_cpu_mask(cpu)))
-                                       dev_err(&instance->pdev->dev,
-                                               "Error setting affinity hint "
-                                               "for cpu %d\n", cpu);
-                               cpu = cpumask_next(cpu, cpu_online_mask);
-                       }
-               }
-       } else {
-               instance->irq_context[0].instance = instance;
-               instance->irq_context[0].MSIxIndex = 0;
-               if (request_irq(pdev->irq, instance->instancet->service_isr,
-                               IRQF_SHARED, "megasas",
-                               &instance->irq_context[0])) {
-                       printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
-                       goto fail_irq;
-               }
-       }
-
-       instance->instancet->enable_intr(instance);
-
        /*
         * Store instance in PCI softstate
         */
@@ -5410,17 +5416,8 @@ retry_irq_register:
        megasas_mgmt_info.max_index--;
 
        instance->instancet->disable_intr(instance);
-       if (instance->msix_vectors)
-               for (i = 0; i < instance->msix_vectors; i++) {
-                       if (smp_affinity_enable)
-                               irq_set_affinity_hint(
-                                       instance->msixentry[i].vector, NULL);
-                       free_irq(instance->msixentry[i].vector,
-                                &instance->irq_context[i]);
-               }
-       else
-               free_irq(instance->pdev->irq, &instance->irq_context[0]);
-fail_irq:
+       megasas_destroy_irqs(instance);
+
        if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
            (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
            (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
@@ -5428,9 +5425,9 @@ fail_irq:
                megasas_release_fusion(instance);
        else
                megasas_release_mfi(instance);
-      fail_init_mfi:
        if (instance->msix_vectors)
                pci_disable_msix(instance->pdev);
+fail_init_mfi:
       fail_alloc_dma_buf:
        if (instance->evt_detail)
                pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
@@ -5487,11 +5484,7 @@ static void megasas_flush_cache(struct megasas_instance *instance)
                dev_err(&instance->pdev->dev, "Command timedout"
                        " from %s\n", __func__);
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
 
        return;
 }
@@ -5538,11 +5531,7 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
                dev_err(&instance->pdev->dev, "Command timedout"
                        "from %s\n", __func__);
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
 
        return;
 }
@@ -5558,7 +5547,6 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct Scsi_Host *host;
        struct megasas_instance *instance;
-       int i;
 
        instance = pci_get_drvdata(pdev);
        host = instance->host;
@@ -5583,16 +5571,8 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
        pci_set_drvdata(instance->pdev, instance);
        instance->instancet->disable_intr(instance);
 
-       if (instance->msix_vectors)
-               for (i = 0; i < instance->msix_vectors; i++) {
-                       if (smp_affinity_enable)
-                               irq_set_affinity_hint(
-                                       instance->msixentry[i].vector, NULL);
-                       free_irq(instance->msixentry[i].vector,
-                                &instance->irq_context[i]);
-               }
-       else
-               free_irq(instance->pdev->irq, &instance->irq_context[0]);
+       megasas_destroy_irqs(instance);
+
        if (instance->msix_vectors)
                pci_disable_msix(instance->pdev);
 
@@ -5611,7 +5591,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
 static int
 megasas_resume(struct pci_dev *pdev)
 {
-       int rval, i, j, cpu;
+       int rval;
        struct Scsi_Host *host;
        struct megasas_instance *instance;
 
@@ -5681,50 +5661,10 @@ megasas_resume(struct pci_dev *pdev)
        tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
                     (unsigned long)instance);
 
-       /*
-        * Register IRQ
-        */
-       if (instance->msix_vectors) {
-               cpu = cpumask_first(cpu_online_mask);
-               for (i = 0 ; i < instance->msix_vectors; i++) {
-                       instance->irq_context[i].instance = instance;
-                       instance->irq_context[i].MSIxIndex = i;
-                       if (request_irq(instance->msixentry[i].vector,
-                                       instance->instancet->service_isr, 0,
-                                       "megasas",
-                                       &instance->irq_context[i])) {
-                               printk(KERN_DEBUG "megasas: Failed to "
-                                      "register IRQ for vector %d.\n", i);
-                               for (j = 0; j < i; j++) {
-                                       if (smp_affinity_enable)
-                                               irq_set_affinity_hint(
-                                                       instance->msixentry[j].vector, NULL);
-                                       free_irq(
-                                               instance->msixentry[j].vector,
-                                               &instance->irq_context[j]);
-                               }
-                               goto fail_irq;
-                       }
-
-                       if (smp_affinity_enable) {
-                               if (irq_set_affinity_hint(instance->msixentry[i].vector,
-                                       get_cpu_mask(cpu)))
-                                       dev_err(&instance->pdev->dev, "Error "
-                                               "setting affinity hint for cpu "
-                                               "%d\n", cpu);
-                               cpu = cpumask_next(cpu, cpu_online_mask);
-                       }
-               }
-       } else {
-               instance->irq_context[0].instance = instance;
-               instance->irq_context[0].MSIxIndex = 0;
-               if (request_irq(pdev->irq, instance->instancet->service_isr,
-                               IRQF_SHARED, "megasas",
-                               &instance->irq_context[0])) {
-                       printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
-                       goto fail_irq;
-               }
-       }
+       if (instance->msix_vectors ?
+                       megasas_setup_irqs_msix(instance, 0) :
+                       megasas_setup_irqs_ioapic(instance))
+               goto fail_init_mfi;
 
        /* Re-launch SR-IOV heartbeat timer */
        if (instance->requestorId) {
@@ -5733,8 +5673,10 @@ megasas_resume(struct pci_dev *pdev)
                                            &instance->sriov_heartbeat_timer,
                                            megasas_sriov_heartbeat_handler,
                                            MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF);
-               else
+               else {
                        instance->skip_heartbeat_timer_del = 1;
+                       goto fail_init_mfi;
+               }
        }
 
        instance->instancet->enable_intr(instance);
@@ -5748,7 +5690,6 @@ megasas_resume(struct pci_dev *pdev)
 
        return 0;
 
-fail_irq:
 fail_init_mfi:
        if (instance->evt_detail)
                pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
@@ -5829,16 +5770,8 @@ static void megasas_detach_one(struct pci_dev *pdev)
 
        instance->instancet->disable_intr(instance);
 
-       if (instance->msix_vectors)
-               for (i = 0; i < instance->msix_vectors; i++) {
-                       if (smp_affinity_enable)
-                               irq_set_affinity_hint(
-                                       instance->msixentry[i].vector, NULL);
-                       free_irq(instance->msixentry[i].vector,
-                                &instance->irq_context[i]);
-               }
-       else
-               free_irq(instance->pdev->irq, &instance->irq_context[0]);
+       megasas_destroy_irqs(instance);
+
        if (instance->msix_vectors)
                pci_disable_msix(instance->pdev);
 
@@ -5899,6 +5832,10 @@ static void megasas_detach_one(struct pci_dev *pdev)
                pci_free_consistent(pdev, CRASH_DMA_BUF_SIZE,
                            instance->crash_dump_buf, instance->crash_dump_h);
 
+       if (instance->system_info_buf)
+               pci_free_consistent(pdev, sizeof(struct MR_DRV_SYSTEM_INFO),
+                                   instance->system_info_buf, instance->system_info_h);
+
        scsi_host_put(host);
 
        pci_disable_device(pdev);
@@ -5912,23 +5849,14 @@ static void megasas_detach_one(struct pci_dev *pdev)
  */
 static void megasas_shutdown(struct pci_dev *pdev)
 {
-       int i;
        struct megasas_instance *instance = pci_get_drvdata(pdev);
 
        instance->unload = 1;
        megasas_flush_cache(instance);
        megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
        instance->instancet->disable_intr(instance);
-       if (instance->msix_vectors)
-               for (i = 0; i < instance->msix_vectors; i++) {
-                       if (smp_affinity_enable)
-                               irq_set_affinity_hint(
-                                       instance->msixentry[i].vector, NULL);
-                       free_irq(instance->msixentry[i].vector,
-                                &instance->irq_context[i]);
-               }
-       else
-               free_irq(instance->pdev->irq, &instance->irq_context[0]);
+       megasas_destroy_irqs(instance);
+
        if (instance->msix_vectors)
                pci_disable_msix(instance->pdev);
 }
@@ -6211,11 +6139,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
                        kbuff_arr[i] = NULL;
        }
 
-       if (instance->ctrl_context && cmd->mpt_pthr_cmd_blocked)
-               megasas_return_mfi_mpt_pthr(instance, cmd,
-                       cmd->mpt_pthr_cmd_blocked);
-       else
-               megasas_return_cmd(instance, cmd);
+       megasas_return_cmd(instance, cmd);
        return error;
 }
 
@@ -6502,6 +6426,15 @@ static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
 static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
 
 static ssize_t
+megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
+{
+       return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
+               MEGASAS_RELDATE);
+}
+
+static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, NULL);
+
+static ssize_t
 megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
 {
        return sprintf(buf, "%u\n", support_poll_for_event);
@@ -6841,6 +6774,11 @@ static int __init megasas_init(void)
                goto err_dcf_attr_ver;
 
        rval = driver_create_file(&megasas_pci_driver.driver,
+                                 &driver_attr_release_date);
+       if (rval)
+               goto err_dcf_rel_date;
+
+       rval = driver_create_file(&megasas_pci_driver.driver,
                                &driver_attr_support_poll_for_event);
        if (rval)
                goto err_dcf_support_poll_for_event;
@@ -6863,6 +6801,9 @@ err_dcf_dbg_lvl:
        driver_remove_file(&megasas_pci_driver.driver,
                        &driver_attr_support_poll_for_event);
 err_dcf_support_poll_for_event:
+       driver_remove_file(&megasas_pci_driver.driver,
+                          &driver_attr_release_date);
+err_dcf_rel_date:
        driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 err_dcf_attr_ver:
        pci_unregister_driver(&megasas_pci_driver);
@@ -6882,6 +6823,8 @@ static void __exit megasas_exit(void)
                        &driver_attr_support_poll_for_event);
        driver_remove_file(&megasas_pci_driver.driver,
                        &driver_attr_support_device_change);
+       driver_remove_file(&megasas_pci_driver.driver,
+                          &driver_attr_release_date);
        driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 
        pci_unregister_driver(&megasas_pci_driver);