static void
 megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                     u8 alt_status);
+static irqreturn_t megasas_isr(int irq, void *devp);
+static u32
+megasas_init_adapter_mfi(struct megasas_instance *instance);
+u32
+megasas_build_and_issue_cmd(struct megasas_instance *instance,
+                           struct scsi_cmnd *scmd);
+static void megasas_complete_cmd_dpc(unsigned long instance_addr);
+
+void
+megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
+{
+       instance->instancet->fire_cmd(instance,
+               cmd->frame_phys_addr, 0, instance->reg_set);
+}
 
 /**
  * megasas_get_cmd -   Get a command from the free pool
        .read_fw_status_reg = megasas_read_fw_status_reg_xscale,
        .adp_reset = megasas_adp_reset_xscale,
        .check_reset = megasas_check_reset_xscale,
+       .service_isr = megasas_isr,
+       .tasklet = megasas_complete_cmd_dpc,
+       .init_adapter = megasas_init_adapter_mfi,
+       .build_and_issue_cmd = megasas_build_and_issue_cmd,
+       .issue_dcmd = megasas_issue_dcmd,
 };
 
 /**
        .read_fw_status_reg = megasas_read_fw_status_reg_ppc,
        .adp_reset = megasas_adp_reset_ppc,
        .check_reset = megasas_check_reset_ppc,
+       .service_isr = megasas_isr,
+       .tasklet = megasas_complete_cmd_dpc,
+       .init_adapter = megasas_init_adapter_mfi,
+       .build_and_issue_cmd = megasas_build_and_issue_cmd,
+       .issue_dcmd = megasas_issue_dcmd,
 };
 
 /**
        .read_fw_status_reg = megasas_read_fw_status_reg_skinny,
        .adp_reset = megasas_adp_reset_skinny,
        .check_reset = megasas_check_reset_skinny,
+       .service_isr = megasas_isr,
+       .tasklet = megasas_complete_cmd_dpc,
+       .init_adapter = megasas_init_adapter_mfi,
+       .build_and_issue_cmd = megasas_build_and_issue_cmd,
+       .issue_dcmd = megasas_issue_dcmd,
 };
 
 
        .read_fw_status_reg = megasas_read_fw_status_reg_gen2,
        .adp_reset = megasas_adp_reset_gen2,
        .check_reset = megasas_check_reset_gen2,
+       .service_isr = megasas_isr,
+       .tasklet = megasas_complete_cmd_dpc,
+       .init_adapter = megasas_init_adapter_mfi,
+       .build_and_issue_cmd = megasas_build_and_issue_cmd,
+       .issue_dcmd = megasas_issue_dcmd,
 };
 
 /**
        printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
 }
 
+u32
+megasas_build_and_issue_cmd(struct megasas_instance *instance,
+                           struct scsi_cmnd *scmd)
+{
+       struct megasas_cmd *cmd;
+       u32 frame_count;
+
+       cmd = megasas_get_cmd(instance);
+       if (!cmd)
+               return SCSI_MLQUEUE_HOST_BUSY;
+
+       /*
+        * Logical drive command
+        */
+       if (megasas_is_ldio(scmd))
+               frame_count = megasas_build_ldio(instance, scmd, cmd);
+       else
+               frame_count = megasas_build_dcdb(instance, scmd, cmd);
+
+       if (!frame_count)
+               goto out_return_cmd;
+
+       cmd->scmd = scmd;
+       scmd->SCp.ptr = (char *)cmd;
+
+       /*
+        * Issue the command to the FW
+        */
+       atomic_inc(&instance->fw_outstanding);
+
+       instance->instancet->fire_cmd(instance, 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;
+out_return_cmd:
+       megasas_return_cmd(instance, cmd);
+       return 1;
+}
+
+
 /**
  * megasas_queue_command -     Queue entry point
  * @scmd:                      SCSI command to be queued
 static int
 megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 {
-       u32 frame_count;
-       struct megasas_cmd *cmd;
        struct megasas_instance *instance;
        unsigned long flags;
 
                break;
        }
 
-       cmd = megasas_get_cmd(instance);
-       if (!cmd)
+       if (instance->instancet->build_and_issue_cmd(instance, scmd)) {
+               printk(KERN_ERR "megasas: Err returned from build_and_issue_cmd\n");
                return SCSI_MLQUEUE_HOST_BUSY;
-
-       /*
-        * Logical drive command
-        */
-       if (megasas_is_ldio(scmd))
-               frame_count = megasas_build_ldio(instance, scmd, cmd);
-       else
-               frame_count = megasas_build_dcdb(instance, scmd, cmd);
-
-       if (!frame_count)
-               goto out_return_cmd;
-
-       cmd->scmd = scmd;
-       scmd->SCp.ptr = (char *)cmd;
-
-       /*
-        * Issue the command to the FW
-        */
-       atomic_inc(&instance->fw_outstanding);
-
-       instance->instancet->fire_cmd(instance, 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;
 
- out_return_cmd:
-       megasas_return_cmd(instance, cmd);
  out_done:
        done(scmd);
        return 0;
                        jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
 }
 
-/**
- * megasas_init_mfi -  Initializes the FW
- * @instance:          Adapter soft state
- *
- * This is the main function for initializing MFI firmware.
- */
-static int megasas_init_mfi(struct megasas_instance *instance)
+static u32
+megasas_init_adapter_mfi(struct megasas_instance *instance)
 {
+       struct megasas_register_set __iomem *reg_set;
        u32 context_sz;
        u32 reply_q_sz;
-       u32 max_sectors_1;
-       u32 max_sectors_2;
-       u32 tmp_sectors;
-       struct megasas_register_set __iomem *reg_set;
-       struct megasas_ctrl_info *ctrl_info;
-       unsigned long bar_list;
-
-       /* Find first memory bar */
-       bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
-       instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
-       instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
-       if (pci_request_selected_regions(instance->pdev, instance->bar,
-                                        "megasas: LSI")) {
-               printk(KERN_DEBUG "megasas: IO memory region busy!\n");
-               return -EBUSY;
-       }
-
-       instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
-
-       if (!instance->reg_set) {
-               printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
-               goto fail_ioremap;
-       }
 
        reg_set = instance->reg_set;
 
-       switch(instance->pdev->device)
-       {
-               case PCI_DEVICE_ID_LSI_SAS1078R:
-               case PCI_DEVICE_ID_LSI_SAS1078DE:
-                       instance->instancet = &megasas_instance_template_ppc;
-                       break;
-               case PCI_DEVICE_ID_LSI_SAS1078GEN2:
-               case PCI_DEVICE_ID_LSI_SAS0079GEN2:
-                       instance->instancet = &megasas_instance_template_gen2;
-                       break;
-               case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
-               case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
-                       instance->instancet = &megasas_instance_template_skinny;
-                       break;
-               case PCI_DEVICE_ID_LSI_SAS1064R:
-               case PCI_DEVICE_ID_DELL_PERC5:
-               default:
-                       instance->instancet = &megasas_instance_template_xscale;
-                       break;
-       }
-
-       /*
-        * We expect the FW state to be READY
-        */
-       if (megasas_transition_to_ready(instance))
-               goto fail_ready_state;
-
        /*
         * Get various operational parameters from status register
         */
        if (instance->fw_support_ieee)
                instance->flag_ieee = 1;
 
+       return 0;
+
+fail_fw_init:
+
+       pci_free_consistent(instance->pdev, reply_q_sz,
+                           instance->reply_queue, instance->reply_queue_h);
+fail_reply_queue:
+       megasas_free_cmds(instance);
+
+fail_alloc_cmds:
+       iounmap(instance->reg_set);
+       return 1;
+}
+
+/**
+ * megasas_init_fw -   Initializes the FW
+ * @instance:          Adapter soft state
+ *
+ * This is the main function for initializing firmware
+ */
+
+static int megasas_init_fw(struct megasas_instance *instance)
+{
+       u32 max_sectors_1;
+       u32 max_sectors_2;
+       u32 tmp_sectors;
+       struct megasas_register_set __iomem *reg_set;
+       struct megasas_ctrl_info *ctrl_info;
+       unsigned long bar_list;
+
+       /* Find first memory bar */
+       bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
+       instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
+       instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
+       if (pci_request_selected_regions(instance->pdev, instance->bar,
+                                        "megasas: LSI")) {
+               printk(KERN_DEBUG "megasas: IO memory region busy!\n");
+               return -EBUSY;
+       }
+
+       instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
+
+       if (!instance->reg_set) {
+               printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
+               goto fail_ioremap;
+       }
+
+       reg_set = instance->reg_set;
+
+       switch (instance->pdev->device) {
+       case PCI_DEVICE_ID_LSI_SAS1078R:
+       case PCI_DEVICE_ID_LSI_SAS1078DE:
+               instance->instancet = &megasas_instance_template_ppc;
+               break;
+       case PCI_DEVICE_ID_LSI_SAS1078GEN2:
+       case PCI_DEVICE_ID_LSI_SAS0079GEN2:
+               instance->instancet = &megasas_instance_template_gen2;
+               break;
+       case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
+       case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
+               instance->instancet = &megasas_instance_template_skinny;
+               break;
+       case PCI_DEVICE_ID_LSI_SAS1064R:
+       case PCI_DEVICE_ID_DELL_PERC5:
+       default:
+               instance->instancet = &megasas_instance_template_xscale;
+               break;
+       }
+
+       /*
+        * We expect the FW state to be READY
+        */
+       if (megasas_transition_to_ready(instance))
+               goto fail_ready_state;
+
+       /* Get operational params, sge flags, send init cmd to controller */
+       if (instance->instancet->init_adapter(instance))
+               return -ENODEV;
+
+       printk(KERN_ERR "megasas: INIT adapter done\n");
+
        /** for passthrough
        * the following function will get the PD LIST.
        */
                                MEGASAS_COMPLETION_TIMER_INTERVAL);
        return 0;
 
-      fail_fw_init:
-
-       pci_free_consistent(instance->pdev, reply_q_sz,
-                           instance->reply_queue, instance->reply_queue_h);
-      fail_reply_queue:
-       megasas_free_cmds(instance);
-
-      fail_alloc_cmds:
-      fail_ready_state:
+fail_ready_state:
        iounmap(instance->reg_set);
 
       fail_ioremap:
        /*
         * Initialize MFI Firmware
         */
-       if (megasas_init_mfi(instance))
+       if (megasas_init_fw(instance))
                goto fail_init_mfi;
 
        /* Try to enable MSI-X */
         * Register IRQ
         */
        if (request_irq(instance->msi_flag ? instance->msixentry.vector :
-                       pdev->irq, megasas_isr,
+                       pdev->irq, instance->instancet->service_isr,
                        IRQF_SHARED, "megasas", instance)) {
                printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
                goto fail_irq;
                 instance->pdev->irq, instance);
        if (instance->msi_flag)
                pci_disable_msix(instance->pdev);
-       megasas_release_mfi(instance);
 
       fail_irq:
       fail_init_mfi:
                                    instance->evt_detail,
                                    instance->evt_detail_h);
 
-       if (instance->producer)
+       if (instance->producer) {
                pci_free_consistent(pdev, sizeof(u32), instance->producer,
                                    instance->producer_h);
+               megasas_release_mfi(instance);
+       }
        if (instance->consumer)
                pci_free_consistent(pdev, sizeof(u32), instance->consumer,
                                    instance->consumer_h);
         * Register IRQ
         */
        if (request_irq(instance->msi_flag ? instance->msixentry.vector :
-                       pdev->irq, megasas_isr,
+                       pdev->irq, instance->instancet->service_isr,
                        IRQF_SHARED, "megasas", instance)) {
                printk(KERN_ERR "megasas: Failed to register IRQ\n");
                goto fail_irq;