#include <scsi/scsi_host.h>
 #include "megaraid_sas.h"
 
+/*
+ * poll_mode_io:1- schedule complete completion from q cmd
+ */
+static unsigned int poll_mode_io;
+module_param_named(poll_mode_io, poll_mode_io, int, 0);
+MODULE_PARM_DESC(poll_mode_io,
+       "Complete cmds from IO path, (default=0)");
+
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEGASAS_VERSION);
 MODULE_AUTHOR("megaraidlinux@lsi.com");
        atomic_inc(&instance->fw_outstanding);
 
        instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
+       /*
+        * Check if we have pend cmds to be completed
+        */
+       if (poll_mode_io && atomic_read(&instance->fw_outstanding))
+               tasklet_schedule(&instance->isr_tasklet);
+
 
        return 0;
 
        return -EINVAL;
 }
 
+/**
+ * megasas_start_timer - Initializes a timer object
+ * @instance:          Adapter soft state
+ * @timer:             timer object to be initialized
+ * @fn:                        timer function
+ * @interval:          time interval between timer function call
+ */
+static inline void
+megasas_start_timer(struct megasas_instance *instance,
+                       struct timer_list *timer,
+                       void *fn, unsigned long interval)
+{
+       init_timer(timer);
+       timer->expires = jiffies + interval;
+       timer->data = (unsigned long)instance;
+       timer->function = fn;
+       add_timer(timer);
+}
+
+/**
+ * megasas_io_completion_timer - Timer fn
+ * @instance_addr:     Address of adapter soft state
+ *
+ * Schedules tasklet for cmd completion
+ * if poll_mode_io is set
+ */
+static void
+megasas_io_completion_timer(unsigned long instance_addr)
+{
+       struct megasas_instance *instance =
+                       (struct megasas_instance *)instance_addr;
+
+       if (atomic_read(&instance->fw_outstanding))
+               tasklet_schedule(&instance->isr_tasklet);
+
+       /* Restart timer */
+       if (poll_mode_io)
+               mod_timer(&instance->io_completion_timer,
+                       jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
+}
+
 /**
  * megasas_init_mfi -  Initializes the FW
  * @instance:          Adapter soft state
        * Setup tasklet for cmd completion
        */
 
-        tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
-                        (unsigned long)instance);
+       tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
+               (unsigned long)instance);
+
+       /* Initialize the cmd completion timer */
+       if (poll_mode_io)
+               megasas_start_timer(instance, &instance->io_completion_timer,
+                               megasas_io_completion_timer,
+                               MEGASAS_COMPLETION_TIMER_INTERVAL);
        return 0;
 
       fail_fw_init:
 }
 
 /**
- * megasas_suspend -    driver suspend entry point
- * @pdev:               PCI device structure
+ * megasas_suspend -   driver suspend entry point
+ * @pdev:              PCI device structure
  * @state:             PCI power state to suspend routine
  */
 static int __devinit
        instance = pci_get_drvdata(pdev);
        host = instance->host;
 
+       if (poll_mode_io)
+               del_timer_sync(&instance->io_completion_timer);
+
        megasas_flush_cache(instance);
        megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
        tasklet_kill(&instance->isr_tasklet);
        if (megasas_start_aen(instance))
                printk(KERN_ERR "megasas: Start AEN failed\n");
 
+       /* Initialize the cmd completion timer */
+       if (poll_mode_io)
+               megasas_start_timer(instance, &instance->io_completion_timer,
+                               megasas_io_completion_timer,
+                               MEGASAS_COMPLETION_TIMER_INTERVAL);
        return 0;
 
 fail_irq:
        instance = pci_get_drvdata(pdev);
        host = instance->host;
 
+       if (poll_mode_io)
+               del_timer_sync(&instance->io_completion_timer);
+
        scsi_remove_host(instance->host);
        megasas_flush_cache(instance);
        megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
 static ssize_t
 megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
 {
-       return sprintf(buf,"%u",megasas_dbg_lvl);
+       return sprintf(buf, "%u\n", megasas_dbg_lvl);
 }
 
 static ssize_t
 }
 
 static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl,
-                  megasas_sysfs_set_dbg_lvl);
+               megasas_sysfs_set_dbg_lvl);
+
+static ssize_t
+megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
+{
+       return sprintf(buf, "%u\n", poll_mode_io);
+}
+
+static ssize_t
+megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
+                               const char *buf, size_t count)
+{
+       int retval = count;
+       int tmp = poll_mode_io;
+       int i;
+       struct megasas_instance *instance;
+
+       if (sscanf(buf, "%u", &poll_mode_io) < 1) {
+               printk(KERN_ERR "megasas: could not set poll_mode_io\n");
+               retval = -EINVAL;
+       }
+
+       /*
+        * Check if poll_mode_io is already set or is same as previous value
+        */
+       if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
+               goto out;
+
+       if (poll_mode_io) {
+               /*
+                * Start timers for all adapters
+                */
+               for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+                       instance = megasas_mgmt_info.instance[i];
+                       if (instance) {
+                               megasas_start_timer(instance,
+                                       &instance->io_completion_timer,
+                                       megasas_io_completion_timer,
+                                       MEGASAS_COMPLETION_TIMER_INTERVAL);
+                       }
+               }
+       } else {
+               /*
+                * Delete timers for all adapters
+                */
+               for (i = 0; i < megasas_mgmt_info.max_index; i++) {
+                       instance = megasas_mgmt_info.instance[i];
+                       if (instance)
+                               del_timer_sync(&instance->io_completion_timer);
+               }
+       }
+
+out:
+       return retval;
+}
+
+static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO,
+               megasas_sysfs_show_poll_mode_io,
+               megasas_sysfs_set_poll_mode_io);
 
 /**
  * megasas_init - Driver load entry point
                                  &driver_attr_dbg_lvl);
        if (rval)
                goto err_dcf_dbg_lvl;
+       rval = driver_create_file(&megasas_pci_driver.driver,
+                                 &driver_attr_poll_mode_io);
+       if (rval)
+               goto err_dcf_poll_mode_io;
 
        return rval;
+
+err_dcf_poll_mode_io:
+       driver_remove_file(&megasas_pci_driver.driver,
+                          &driver_attr_dbg_lvl);
 err_dcf_dbg_lvl:
        driver_remove_file(&megasas_pci_driver.driver,
                           &driver_attr_release_date);
  */
 static void __exit megasas_exit(void)
 {
+       driver_remove_file(&megasas_pci_driver.driver,
+                          &driver_attr_poll_mode_io);
        driver_remove_file(&megasas_pci_driver.driver,
                           &driver_attr_dbg_lvl);
        driver_remove_file(&megasas_pci_driver.driver,