Merge git://git.kernel.org/pub/scm/linux/kernel/git/bunk/trivial
[sfrench/cifs-2.6.git] / drivers / scsi / megaraid / megaraid_sas.c
index a487f414960e5e9a6553c7c1b7dc7fe2042253c2..39729460b00e243b8be2b9257d9f71e11b769895 100644 (file)
@@ -10,7 +10,7 @@
  *        2 of the License, or (at your option) any later version.
  *
  * FILE                : megaraid_sas.c
- * Version     : v00.00.02.02
+ * Version     : v00.00.02.04
  *
  * Authors:
  *     Sreenivas Bagalkote     <Sreenivas.Bagalkote@lsil.com>
@@ -59,6 +59,12 @@ static struct pci_device_id megasas_pci_table[] = {
         PCI_ANY_ID,
         PCI_ANY_ID,
         },
+       {
+        PCI_VENDOR_ID_LSI_LOGIC,
+        PCI_DEVICE_ID_LSI_SAS1078R, // ppc IOP
+        PCI_ANY_ID,
+        PCI_ANY_ID,
+       },
        {
         PCI_VENDOR_ID_DELL,
         PCI_DEVICE_ID_DELL_PERC5, // xscale IOP
@@ -198,6 +204,86 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
 *      to xscale (deviceid : 1064R, PERC5) controllers
 */
 
+/**
+*      The following functions are defined for ppc (deviceid : 0x60) 
+*      controllers
+*/
+
+/**
+ * megasas_enable_intr_ppc -   Enables interrupts
+ * @regs:                      MFI register set
+ */
+static inline void
+megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+       writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
+    
+       writel(~0x80000004, &(regs)->outbound_intr_mask);
+
+       /* Dummy readl to force pci flush */
+       readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_ppc - returns the current FW status value
+ * @regs:                      MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs)
+{
+       return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_clear_interrupt_ppc -       Check & clear interrupt
+ * @regs:                              MFI register set
+ */
+static int 
+megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
+{
+       u32 status;
+       /*
+        * Check if it is our interrupt
+        */
+       status = readl(&regs->outbound_intr_status);
+
+       if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
+               return 1;
+       }
+
+       /*
+        * Clear the interrupt by writing back the same value
+        */
+       writel(status, &regs->outbound_doorbell_clear);
+
+       return 0;
+}
+/**
+ * megasas_fire_cmd_ppc -      Sends command to the FW
+ * @frame_phys_addr :          Physical address of cmd
+ * @frame_count :              Number of frames for the command
+ * @regs :                     MFI register set
+ */
+static inline void 
+megasas_fire_cmd_ppc(dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs)
+{
+       writel((frame_phys_addr | (frame_count<<1))|1, 
+                       &(regs)->inbound_queue_port);
+}
+
+static struct megasas_instance_template megasas_instance_template_ppc = {
+       
+       .fire_cmd = megasas_fire_cmd_ppc,
+       .enable_intr = megasas_enable_intr_ppc,
+       .clear_intr = megasas_clear_intr_ppc,
+       .read_fw_status_reg = megasas_read_fw_status_reg_ppc,
+};
+
+/**
+*      This is the end of set of functions & definitions
+*      specific to ppc (deviceid : 0x60) controllers
+*/
+
 /**
  * megasas_disable_intr -      Disables interrupts
  * @regs:                      MFI register set
@@ -686,8 +772,6 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
                goto out_return_cmd;
 
        cmd->scmd = scmd;
-       scmd->SCp.ptr = (char *)cmd;
-       scmd->SCp.sent_command = jiffies;
 
        /*
         * Issue the command to the FW
@@ -707,6 +791,26 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
        return 0;
 }
 
+static int megasas_slave_configure(struct scsi_device *sdev)
+{
+       /*
+        * Don't export physical disk devices to the disk driver.
+        *
+        * FIXME: Currently we don't export them to the midlayer at all.
+        *        That will be fixed once LSI engineers have audited the
+        *        firmware for possible issues.
+        */
+       if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
+               return -ENXIO;
+
+       /*
+        * The RAID firmware may require extended timeouts.
+        */
+       if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
+               sdev->timeout = 90 * HZ;
+       return 0;
+}
+
 /**
  * megasas_wait_for_outstanding -      Wait for all outstanding cmds
  * @instance:                          Adapter soft state
@@ -775,23 +879,6 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
        return ret_val;
 }
 
-static enum scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
-{
-       unsigned long seconds;
-
-       if (scmd->SCp.ptr) {
-               seconds = (jiffies - scmd->SCp.sent_command) / HZ;
-
-               if (seconds < 90) {
-                       return EH_RESET_TIMER;
-               } else {
-                       return EH_NOT_HANDLED;
-               }
-       }
-
-       return EH_HANDLED;
-}
-
 /**
  * megasas_reset_device -      Device reset handler entry point
  */
@@ -815,7 +902,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
        int ret;
 
        /*
-        * Frist wait for all commands to complete
+        * First wait for all commands to complete
         */
        ret = megasas_generic_reset(scmd);
 
@@ -857,11 +944,11 @@ static struct scsi_host_template megasas_template = {
        .module = THIS_MODULE,
        .name = "LSI Logic SAS based MegaRAID driver",
        .proc_name = "megaraid_sas",
+       .slave_configure = megasas_slave_configure,
        .queuecommand = megasas_queue_command,
        .eh_device_reset_handler = megasas_reset_device,
        .eh_bus_reset_handler = megasas_reset_bus_host,
        .eh_host_reset_handler = megasas_reset_bus_host,
-       .eh_timed_out = megasas_reset_timer,
        .use_clustering = ENABLE_CLUSTERING,
 };
 
@@ -985,20 +1072,6 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                        break;
                }
 
-               /*
-                * Don't export physical disk devices to mid-layer.
-                */
-               if (!MEGASAS_IS_LOGICAL(cmd->scmd) &&
-                   (hdr->cmd_status == MFI_STAT_OK) &&
-                   (cmd->scmd->cmnd[0] == INQUIRY)) {
-
-                       if (((*(u8 *) cmd->scmd->request_buffer) & 0x1F) ==
-                           TYPE_DISK) {
-                               cmd->scmd->result = DID_BAD_TARGET << 16;
-                               exception = 1;
-                       }
-               }
-
        case MFI_CMD_LD_READ:
        case MFI_CMD_LD_WRITE:
 
@@ -1607,7 +1680,17 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 
        reg_set = instance->reg_set;
 
-       instance->instancet = &megasas_instance_template_xscale;
+       switch(instance->pdev->device)
+       {
+               case PCI_DEVICE_ID_LSI_SAS1078R:        
+                       instance->instancet = &megasas_instance_template_ppc;
+                       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
@@ -1983,6 +2066,7 @@ static int megasas_io_attach(struct megasas_instance *instance)
        host->max_channel = MEGASAS_MAX_CHANNELS - 1;
        host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
        host->max_lun = MEGASAS_MAX_LUN;
+       host->max_cmd_len = 16;
 
        /*
         * Notify the mid-layer about the new controller