#include <linux/mutex.h>
 #include <linux/poll.h>
 #include <linux/vmalloc.h>
+#include <linux/irq_poll.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
        return 1;
 }
 
+static
+void megasas_setup_irq_poll(struct megasas_instance *instance)
+{
+       struct megasas_irq_context *irq_ctx;
+       u32 count, i;
+
+       count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
+
+       /* Initialize IRQ poll */
+       for (i = 0; i < count; i++) {
+               irq_ctx = &instance->irq_context[i];
+               irq_ctx->os_irq = pci_irq_vector(instance->pdev, i);
+               irq_ctx->irq_poll_scheduled = false;
+               irq_poll_init(&irq_ctx->irqpoll,
+                             instance->threshold_reply_count,
+                             megasas_irqpoll);
+       }
+}
+
 /*
  * megasas_setup_irqs_ioapic -         register legacy interrupts.
  * @instance:                          Adapter soft state
 megasas_destroy_irqs(struct megasas_instance *instance) {
 
        int i;
+       int count;
+       struct megasas_irq_context *irq_ctx;
+
+       count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
+       if (instance->adapter_type != MFI_SERIES) {
+               for (i = 0; i < count; i++) {
+                       irq_ctx = &instance->irq_context[i];
+                       irq_poll_disable(&irq_ctx->irqpoll);
+               }
+       }
 
        if (instance->msix_vectors)
                for (i = 0; i < instance->msix_vectors; i++) {
                megasas_setup_irqs_ioapic(instance))
                goto fail_init_adapter;
 
+       if (instance->adapter_type != MFI_SERIES)
+               megasas_setup_irq_poll(instance);
+
        instance->instancet->enable_intr(instance);
 
        dev_info(&instance->pdev->dev, "INIT adapter done\n");
                        megasas_setup_irqs_ioapic(instance))
                goto fail_init_mfi;
 
+       if (instance->adapter_type != MFI_SERIES)
+               megasas_setup_irq_poll(instance);
+
        /* Re-launch SR-IOV heartbeat timer */
        if (instance->requestorId) {
                if (!megasas_sriov_start_heartbeat(instance, 0))
 
 #include <linux/poll.h>
 #include <linux/vmalloc.h>
 #include <linux/workqueue.h>
+#include <linux/irq_poll.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
        instance->flag_ieee = 1;
        instance->r1_ldio_hint_default =  MR_R1_LDIO_PIGGYBACK_DEFAULT;
+       instance->threshold_reply_count = instance->max_fw_cmds / 4;
        fusion->fast_path_io = 0;
 
        if (megasas_allocate_raid_maps(instance))
  * Completes all commands that is in reply descriptor queue
  */
 int
-complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
+complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex,
+                   struct megasas_irq_context *irq_context)
 {
        union MPI2_REPLY_DESCRIPTORS_UNION *desc;
        struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
                 * number of reply counts and still there are more replies in reply queue
                 * pending to be completed
                 */
-               if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
+               if (threshold_reply_count >= instance->threshold_reply_count) {
                        if (instance->msix_combined)
                                writel(((MSIxIndex & 0x7) << 24) |
                                        fusion->last_reply_idx[MSIxIndex],
                                        fusion->last_reply_idx[MSIxIndex],
                                        instance->reply_post_host_index_addr[0]);
                        threshold_reply_count = 0;
+                       if (irq_context) {
+                               if (!irq_context->irq_poll_scheduled) {
+                                       irq_context->irq_poll_scheduled = true;
+                                       disable_irq_nosync(irq_context->os_irq);
+                                       irq_poll_sched(&irq_context->irqpoll);
+                               }
+                               return num_completed;
+                       }
                }
        }
 
-       if (!num_completed)
-               return IRQ_NONE;
+       if (num_completed) {
+               wmb();
+               if (instance->msix_combined)
+                       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 num_completed;
+}
 
-       wmb();
-       if (instance->msix_combined)
-               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;
+/**
+ * megasas_enable_irq_poll() - enable irqpoll
+ */
+static void megasas_enable_irq_poll(struct megasas_instance *instance)
+{
+       u32 count, i;
+       struct megasas_irq_context *irq_ctx;
+
+       count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
+
+       for (i = 0; i < count; i++) {
+               irq_ctx = &instance->irq_context[i];
+               irq_poll_enable(&irq_ctx->irqpoll);
+       }
 }
 
 /**
        u32 count, i;
        struct megasas_instance *instance =
                (struct megasas_instance *)instance_addr;
+       struct megasas_irq_context *irq_ctx;
 
        count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
 
-       for (i = 0; i < count; i++)
+       for (i = 0; i < count; i++) {
                synchronize_irq(pci_irq_vector(instance->pdev, i));
+               irq_ctx = &instance->irq_context[i];
+               irq_poll_disable(&irq_ctx->irqpoll);
+               if (irq_ctx->irq_poll_scheduled) {
+                       irq_ctx->irq_poll_scheduled = false;
+                       enable_irq(irq_ctx->os_irq);
+               }
+       }
+}
+
+/**
+ * megasas_irqpoll() - process a queue for completed reply descriptors
+ * @irqpoll:   IRQ poll structure associated with queue to poll.
+ * @budget:    Threshold of reply descriptors to process per poll.
+ *
+ * Return: The number of entries processed.
+ */
+
+int megasas_irqpoll(struct irq_poll *irqpoll, int budget)
+{
+       struct megasas_irq_context *irq_ctx;
+       struct megasas_instance *instance;
+       int num_entries;
+
+       irq_ctx = container_of(irqpoll, struct megasas_irq_context, irqpoll);
+       instance = irq_ctx->instance;
+
+       num_entries = complete_cmd_fusion(instance, irq_ctx->MSIxIndex, irq_ctx);
+       if (num_entries < budget) {
+               irq_poll_complete(irqpoll);
+               irq_ctx->irq_poll_scheduled = false;
+               enable_irq(irq_ctx->os_irq);
+       }
+
+       return num_entries;
 }
 
 /**
                return;
 
        for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
-               complete_cmd_fusion(instance, MSIxIndex);
+               complete_cmd_fusion(instance, MSIxIndex, NULL);
 }
 
 /**
                return IRQ_HANDLED;
        }
 
-       return complete_cmd_fusion(instance, irq_context->MSIxIndex);
+       return complete_cmd_fusion(instance, irq_context->MSIxIndex, irq_context)
+                       ? IRQ_HANDLED : IRQ_NONE;
 }
 
 /**
                        instance->instancet->disable_intr(instance);
                        megasas_sync_irqs((unsigned long)instance);
                        instance->instancet->enable_intr(instance);
+                       megasas_enable_irq_poll(instance);
                        if (scsi_lookup->scmd == NULL)
                                break;
                }
                megasas_sync_irqs((unsigned long)instance);
                rc = megasas_track_scsiio(instance, id, channel);
                instance->instancet->enable_intr(instance);
+               megasas_enable_irq_poll(instance);
 
                break;
        case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
                        dev_warn(&instance->pdev->dev, "Reset not supported"
                               ", killing adapter scsi%d.\n",
                                instance->host->host_no);
-                       megaraid_sas_kill_hba(instance);
-                       instance->skip_heartbeat_timer_del = 1;
-                       retval = FAILED;
-                       goto out;
+                       goto kill_hba;
                }
 
                /* Let SR-IOV VF & PF sync up if there was a HB failure */
                                dev_info(&instance->pdev->dev,
                                        "Failed from %s %d\n",
                                        __func__, __LINE__);
-                               megaraid_sas_kill_hba(instance);
-                               retval = FAILED;
-                               goto out;
+                               goto kill_hba;
                        }
 
                        megasas_refire_mgmt_cmd(instance);
                        clear_bit(MEGASAS_FUSION_IN_RESET,
                                  &instance->reset_flags);
                        instance->instancet->enable_intr(instance);
-
+                       megasas_enable_irq_poll(instance);
                        shost_for_each_device(sdev, shost) {
                                if ((instance->tgt_prop) &&
                                    (instance->nvme_page_size))
                /* Reset failed, kill the adapter */
                dev_warn(&instance->pdev->dev, "Reset failed, killing "
                       "adapter scsi%d.\n", instance->host->host_no);
-               megaraid_sas_kill_hba(instance);
-               instance->skip_heartbeat_timer_del = 1;
-               retval = FAILED;
+               goto kill_hba;
        } else {
                /* For VF: Restart HB timer if we didn't OCR */
                if (instance->requestorId) {
                }
                clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
                instance->instancet->enable_intr(instance);
+               megasas_enable_irq_poll(instance);
                atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL);
+               goto out;
        }
+kill_hba:
+       megaraid_sas_kill_hba(instance);
+       megasas_enable_irq_poll(instance);
+       instance->skip_heartbeat_timer_del = 1;
+       retval = FAILED;
 out:
        clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
        mutex_unlock(&instance->reset_mutex);