[SCSI] megaraid_sas: Add struct megasas_instance_template changes
authoradam radford <aradford@gmail.com>
Tue, 21 Dec 2010 18:23:23 +0000 (10:23 -0800)
committerJames Bottomley <James.Bottomley@suse.de>
Thu, 23 Dec 2010 05:26:52 +0000 (23:26 -0600)
The following patch adds struct megasas_instance_template changes to
the megaraid_sas driver, and changes all code to use the new instance
entries:

   irqreturn_t (*service_isr )(int irq, void *devp);
   void (*tasklet)(unsigned long);
   u32 (*init_adapter)(struct megasas_instance *);
   u32 (*build_and_issue_cmd) (struct megasas_instance *, struct scsi_cmnd *);
   void (*issue_dcmd) (struct megasas_instance *instance,
                              struct megasas_cmd *cmd);

Signed-off-by: Adam Radford <aradford@gmail.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c

index 0e09a0f..a0b8ee1 100644 (file)
@@ -1364,6 +1364,13 @@ struct megasas_instance_template {
                struct megasas_register_set __iomem *);
        int (*check_reset)(struct megasas_instance *, \
                struct megasas_register_set __iomem *);
+       irqreturn_t (*service_isr)(int irq, void *devp);
+       void (*tasklet)(unsigned long);
+       u32 (*init_adapter)(struct megasas_instance *);
+       u32 (*build_and_issue_cmd) (struct megasas_instance *,
+                                   struct scsi_cmnd *);
+       void (*issue_dcmd) (struct megasas_instance *instance,
+                           struct megasas_cmd *cmd);
 };
 
 #define MEGASAS_IS_LOGICAL(scp)                                                \
index 6e7bb7c..5938267 100644 (file)
@@ -131,6 +131,20 @@ spinlock_t poll_aen_lock;
 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
@@ -334,6 +348,11 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
        .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,
 };
 
 /**
@@ -460,6 +479,11 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
        .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,
 };
 
 /**
@@ -581,6 +605,11 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
        .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,
 };
 
 
@@ -755,6 +784,11 @@ static struct megasas_instance_template megasas_instance_template_gen2 = {
        .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,
 };
 
 /**
@@ -1339,6 +1373,51 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
        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
@@ -1347,8 +1426,6 @@ megasas_dump_pending_frames(struct megasas_instance *instance)
 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;
 
@@ -1387,42 +1464,13 @@ megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd
                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;
@@ -3221,69 +3269,15 @@ megasas_io_completion_timer(unsigned long instance_addr)
                        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
         */
@@ -3337,6 +3331,87 @@ static int megasas_init_mfi(struct megasas_instance *instance)
        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.
        */
@@ -3392,15 +3467,7 @@ static int megasas_init_mfi(struct megasas_instance *instance)
                                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:
@@ -3855,7 +3922,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        /*
         * Initialize MFI Firmware
         */
-       if (megasas_init_mfi(instance))
+       if (megasas_init_fw(instance))
                goto fail_init_mfi;
 
        /* Try to enable MSI-X */
@@ -3870,7 +3937,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
         * 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;
@@ -3920,7 +3987,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                 instance->pdev->irq, instance);
        if (instance->msi_flag)
                pci_disable_msix(instance->pdev);
-       megasas_release_mfi(instance);
 
       fail_irq:
       fail_init_mfi:
@@ -3930,9 +3996,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                                    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);
@@ -4134,7 +4202,7 @@ megasas_resume(struct pci_dev *pdev)
         * 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;