* @regs:                      MFI register set
  */
 static inline void
-megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
+megasas_enable_intr_xscale(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *regs;
+       regs = instance->reg_set;
        writel(0, &(regs)->outbound_intr_mask);
 
        /* Dummy readl to force pci flush */
  * @regs:                      MFI register set
  */
 static inline void
-megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs)
+megasas_disable_intr_xscale(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *regs;
        u32 mask = 0x1f;
+       regs = instance->reg_set;
        writel(mask, ®s->outbound_intr_mask);
        /* Dummy readl to force pci flush */
        readl(®s->outbound_intr_mask);
  * @regs:                      MFI register set
  */
 static inline void
-megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
+megasas_enable_intr_ppc(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *regs;
+       regs = instance->reg_set;
        writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
 
        writel(~0x80000000, &(regs)->outbound_intr_mask);
  * @regs:                      MFI register set
  */
 static inline void
-megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs)
+megasas_disable_intr_ppc(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *regs;
        u32 mask = 0xFFFFFFFF;
+       regs = instance->reg_set;
        writel(mask, ®s->outbound_intr_mask);
        /* Dummy readl to force pci flush */
        readl(®s->outbound_intr_mask);
  * @regs:                      MFI register set
  */
 static inline void
-megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
+megasas_enable_intr_skinny(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *regs;
+       regs = instance->reg_set;
        writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
 
        writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
  * @regs:                      MFI register set
  */
 static inline void
-megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs)
+megasas_disable_intr_skinny(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *regs;
        u32 mask = 0xFFFFFFFF;
+       regs = instance->reg_set;
        writel(mask, ®s->outbound_intr_mask);
        /* Dummy readl to force pci flush */
        readl(®s->outbound_intr_mask);
  * @regs:                      MFI register set
  */
 static inline void
-megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
+megasas_enable_intr_gen2(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *regs;
+       regs = instance->reg_set;
        writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
 
        /* write ~0x00000005 (4 & 1) to the intr mask*/
  * @regs:                      MFI register set
  */
 static inline void
-megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
+megasas_disable_intr_gen2(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *regs;
        u32 mask = 0xFFFFFFFF;
+       regs = instance->reg_set;
        writel(mask, ®s->outbound_intr_mask);
        /* Dummy readl to force pci flush */
        readl(®s->outbound_intr_mask);
        (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
                *instance->consumer     = MEGASAS_ADPRESET_INPROG_SIGN;
        }
-       instance->instancet->disable_intr(instance->reg_set);
+       instance->instancet->disable_intr(instance);
        instance->adprecovery   = MEGASAS_ADPRESET_SM_INFAULT;
        instance->issuepend_done = 0;
 
                printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault"
                                        "state, restarting it...\n");
 
-               instance->instancet->disable_intr(instance->reg_set);
+               instance->instancet->disable_intr(instance);
                atomic_set(&instance->fw_outstanding, 0);
 
                atomic_set(&instance->fw_reset_no_pci_access, 1);
                spin_lock_irqsave(&instance->hba_lock, flags);
                instance->adprecovery   = MEGASAS_HBA_OPERATIONAL;
                spin_unlock_irqrestore(&instance->hba_lock, flags);
-               instance->instancet->enable_intr(instance->reg_set);
+               instance->instancet->enable_intr(instance);
 
                megasas_issue_pending_cmds_again(instance);
                instance->issuepend_done = 1;
                        }
 
 
-                       instance->instancet->disable_intr(instance->reg_set);
+                       instance->instancet->disable_intr(instance);
                        instance->adprecovery   = MEGASAS_ADPRESET_SM_INFAULT;
                        instance->issuepend_done = 0;
 
                        /*
                         * Bring it to READY state; assuming max wait 10 secs
                         */
-                       instance->instancet->disable_intr(instance->reg_set);
+                       instance->instancet->disable_intr(instance);
                        if ((instance->pdev->device ==
                                PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
                                (instance->pdev->device ==
        /*
         * disable the intr before firing the init frame to FW
         */
-       instance->instancet->disable_intr(instance->reg_set);
+       instance->instancet->disable_intr(instance);
 
        /*
         * Issue the init frame in polled mode
 {
        u32 max_sectors_1;
        u32 max_sectors_2;
-       u32 tmp_sectors, msix_enable;
+       u32 tmp_sectors, msix_enable, scratch_pad_2;
        struct megasas_register_set __iomem *reg_set;
        struct megasas_ctrl_info *ctrl_info;
        unsigned long bar_list;
-       int i;
+       int i, loop, fw_msix_count = 0;
 
        /* Find first memory bar */
        bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
        if (megasas_transition_to_ready(instance, 0))
                goto fail_ready_state;
 
+       /*
+        * MSI-X host index 0 is common for all adapter.
+        * It is used for all MPT based Adapters.
+        */
+       instance->reply_post_host_index_addr[0] =
+               (u32 *)((u8 *)instance->reg_set +
+               MPI2_REPLY_POST_HOST_INDEX_OFFSET);
+
        /* Check if MSI-X is supported while in ready state */
        msix_enable = (instance->instancet->read_fw_status_reg(reg_set) &
                       0x4000000) >> 0x1a;
        if (msix_enable && !msix_disable) {
+               scratch_pad_2 = readl
+                       (&instance->reg_set->outbound_scratch_pad_2);
                /* Check max MSI-X vectors */
-               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)) {
-                       instance->msix_vectors = (readl(&instance->reg_set->
-                                                       outbound_scratch_pad_2
-                                                         ) & 0x1F) + 1;
+               if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) {
+                       instance->msix_vectors = (scratch_pad_2
+                               & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
+                       fw_msix_count = instance->msix_vectors;
                        if (msix_vectors)
                                instance->msix_vectors =
                                        min(msix_vectors,
                                            instance->msix_vectors);
+               } else if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)
+                       || (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+                       /* Invader/Fury supports more than 8 MSI-X */
+                       instance->msix_vectors = ((scratch_pad_2
+                               & MR_MAX_REPLY_QUEUES_EXT_OFFSET)
+                               >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
+                       fw_msix_count = instance->msix_vectors;
+                       /* Save 1-15 reply post index address to local memory
+                        * Index 0 is already saved from reg offset
+                        * MPI2_REPLY_POST_HOST_INDEX_OFFSET
+                        */
+                       for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) {
+                               instance->reply_post_host_index_addr[loop] =
+                                       (u32 *)((u8 *)instance->reg_set +
+                                       MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET
+                                       + (loop * 0x10));
+                       }
+                       if (msix_vectors)
+                               instance->msix_vectors = min(msix_vectors,
+                                       instance->msix_vectors);
                } else
                        instance->msix_vectors = 1;
                /* Don't bother allocating more MSI-X vectors than cpus */
                        }
                } 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);
        }
 
        /* Get operational params, sge flags, send init cmd to controller */
        if (megasas_init_fw(instance))
                goto fail_init_mfi;
 
+retry_irq_register:
        /*
         * Register IRQ
         */
                                        free_irq(
                                                instance->msixentry[j].vector,
                                                &instance->irq_context[j]);
-                               goto fail_irq;
+                               /* Retry irq register for IO_APIC */
+                               instance->msix_vectors = 0;
+                               goto retry_irq_register;
                        }
                }
        } else {
                }
        }
 
-       instance->instancet->enable_intr(instance->reg_set);
+       instance->instancet->enable_intr(instance);
 
        /*
         * Store instance in PCI softstate
        megasas_mgmt_info.max_index--;
 
        pci_set_drvdata(pdev, NULL);
-       instance->instancet->disable_intr(instance->reg_set);
+       instance->instancet->disable_intr(instance);
        if (instance->msix_vectors)
                for (i = 0 ; i < instance->msix_vectors; i++)
                        free_irq(instance->msixentry[i].vector,
        tasklet_kill(&instance->isr_tasklet);
 
        pci_set_drvdata(instance->pdev, instance);
-       instance->instancet->disable_intr(instance->reg_set);
+       instance->instancet->disable_intr(instance);
 
        if (instance->msix_vectors)
                for (i = 0 ; i < instance->msix_vectors; i++)
                }
        }
 
-       instance->instancet->enable_intr(instance->reg_set);
+       instance->instancet->enable_intr(instance);
        instance->unload = 0;
 
        /*
 
        pci_set_drvdata(instance->pdev, NULL);
 
-       instance->instancet->disable_intr(instance->reg_set);
+       instance->instancet->disable_intr(instance);
 
        if (instance->msix_vectors)
                for (i = 0 ; i < instance->msix_vectors; i++)
        instance->unload = 1;
        megasas_flush_cache(instance);
        megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
-       instance->instancet->disable_intr(instance->reg_set);
+       instance->instancet->disable_intr(instance);
        if (instance->msix_vectors)
                for (i = 0 ; i < instance->msix_vectors; i++)
                        free_irq(instance->msixentry[i].vector,
 
  * @regs:                      MFI register set
  */
 void
-megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
+megasas_enable_intr_fusion(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *regs;
+       regs = instance->reg_set;
        /* For Thunderbolt/Invader also clear intr on enable */
        writel(~0, ®s->outbound_intr_status);
        readl(®s->outbound_intr_status);
 
        /* Dummy readl to force pci flush */
        readl(®s->outbound_intr_mask);
+       instance->mask_interrupts = 0;
 }
 
 /**
  * @regs:                       MFI register set
  */
 void
-megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs)
+megasas_disable_intr_fusion(struct megasas_instance *instance)
 {
        u32 mask = 0xFFFFFFFF;
        u32 status;
+       struct megasas_register_set __iomem *regs;
+       regs = instance->reg_set;
+       instance->mask_interrupts = 1;
 
        writel(mask, ®s->outbound_intr_mask);
        /* Dummy readl to force pci flush */
        init_frame->cmd = MFI_CMD_INIT;
        init_frame->cmd_status = 0xFF;
 
+       /* driver support Extended MSIX */
+       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+               init_frame->driver_operations.
+                       mfi_capabilities.support_additional_msix = 1;
+
        init_frame->queue_info_new_phys_addr_lo = ioc_init_handle;
        init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
 
        /*
         * disable the intr before firing the init frame
         */
-       instance->instancet->disable_intr(instance->reg_set);
+       instance->instancet->disable_intr(instance);
 
        for (i = 0; i < (10 * 1000); i += 20) {
                if (readl(&instance->reg_set->doorbell) & 1)
                return IRQ_NONE;
 
        wmb();
-       writel((MSIxIndex << 24) | fusion->last_reply_idx[MSIxIndex],
-              &instance->reg_set->reply_post_host_index);
+       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
+               (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+               writel(((MSIxIndex & 0x7) << 24) |
+                       fusion->last_reply_idx[MSIxIndex],
+                       instance->reply_post_host_index_addr[MSIxIndex/8]);
+       else
+               writel((MSIxIndex << 24) |
+                       fusion->last_reply_idx[MSIxIndex],
+                       instance->reply_post_host_index_addr[0]);
        megasas_check_and_restore_queue_depth(instance);
        return IRQ_HANDLED;
 }
        struct megasas_instance *instance = irq_context->instance;
        u32 mfiStatus, fw_state;
 
+       if (instance->mask_interrupts)
+               return IRQ_NONE;
+
        if (!instance->msix_vectors) {
                mfiStatus = instance->instancet->clear_intr(instance->reg_set);
                if (!mfiStatus)
        mutex_lock(&instance->reset_mutex);
        set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
        instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
-       instance->instancet->disable_intr(instance->reg_set);
+       instance->instancet->disable_intr(instance);
        msleep(1000);
 
        /* First try waiting for commands to complete */
 
                        clear_bit(MEGASAS_FUSION_IN_RESET,
                                  &instance->reset_flags);
-                       instance->instancet->enable_intr(instance->reg_set);
+                       instance->instancet->enable_intr(instance);
                        instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
 
                        /* Re-fire management commands */
                retval = FAILED;
        } else {
                clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
-               instance->instancet->enable_intr(instance->reg_set);
+               instance->instancet->enable_intr(instance);
                instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
        }
 out: