Merge branch 'timers/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / scsi / megaraid / megaraid_sas.c
index 77a62a1..fc7ac15 100644 (file)
@@ -10,7 +10,7 @@
  *        2 of the License, or (at your option) any later version.
  *
  * FILE                : megaraid_sas.c
- * Version     : v00.00.03.16-rc1
+ * Version     : v00.00.03.20-rc1
  *
  * Authors:
  *     (email-id : megaraidlinux@lsi.com)
@@ -33,6 +33,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <asm/uaccess.h>
 #include <linux/fs.h>
@@ -68,6 +69,8 @@ static struct pci_device_id megasas_pci_table[] = {
        /* xscale IOP */
        {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
        /* ppc IOP */
+       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
+       /* ppc IOP */
        {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
        /* xscale IOP, vega */
        {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
@@ -488,12 +491,13 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
 
  /**
  * megasas_get_frame_count - Computes the number of frames
+ * @frame_type         : type of frame- io or pthru frame
  * @sge_count          : number of sg elements
  *
  * Returns the number of frames required for numnber of sge's (sge_count)
  */
 
-static u32 megasas_get_frame_count(u8 sge_count)
+static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
 {
        int num_cnt;
        int sge_bytes;
@@ -504,13 +508,22 @@ static u32 megasas_get_frame_count(u8 sge_count)
            sizeof(struct megasas_sge32);
 
        /*
-       * Main frame can contain 2 SGEs for 64-bit SGLs and
-       * 3 SGEs for 32-bit SGLs
-       */
-       if (IS_DMA64)
-               num_cnt = sge_count - 2;
-       else
-               num_cnt = sge_count - 3;
+        * Main frame can contain 2 SGEs for 64-bit SGLs and
+        * 3 SGEs for 32-bit SGLs for ldio &
+        * 1 SGEs for 64-bit SGLs and
+        * 2 SGEs for 32-bit SGLs for pthru frame
+        */
+       if (unlikely(frame_type == PTHRU_FRAME)) {
+               if (IS_DMA64)
+                       num_cnt = sge_count - 1;
+               else
+                       num_cnt = sge_count - 2;
+       } else {
+               if (IS_DMA64)
+                       num_cnt = sge_count - 2;
+               else
+                       num_cnt = sge_count - 3;
+       }
 
        if(num_cnt>0){
                sge_bytes = sge_sz * num_cnt;
@@ -592,7 +605,8 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
         * Compute the total number of frames this command consumes. FW uses
         * this number to pull sufficient number of frames from host memory.
         */
-       cmd->frame_count = megasas_get_frame_count(pthru->sge_count);
+       cmd->frame_count = megasas_get_frame_count(pthru->sge_count,
+                                                       PTHRU_FRAME);
 
        return cmd->frame_count;
 }
@@ -709,7 +723,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
         * Compute the total number of frames this command consumes. FW uses
         * this number to pull sufficient number of frames from host memory.
         */
-       cmd->frame_count = megasas_get_frame_count(ldio->sge_count);
+       cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME);
 
        return cmd->frame_count;
 }
@@ -1460,7 +1474,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
                        instance->instancet->disable_intr(instance->reg_set);
                        writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
 
-                       max_wait = 10;
+                       max_wait = 60;
                        cur_state = MFI_STATE_OPERATIONAL;
                        break;
 
@@ -1980,7 +1994,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 
        switch(instance->pdev->device)
        {
-               case PCI_DEVICE_ID_LSI_SAS1078R:        
+               case PCI_DEVICE_ID_LSI_SAS1078R:
+               case PCI_DEVICE_ID_LSI_SAS1078DE:
                        instance->instancet = &megasas_instance_template_ppc;
                        break;
                case PCI_DEVICE_ID_LSI_SAS1064R:
@@ -2636,12 +2651,13 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
        return;
 }
 
+#ifdef CONFIG_PM
 /**
  * megasas_suspend -   driver suspend entry point
  * @pdev:              PCI device structure
  * @state:             PCI power state to suspend routine
  */
-static int __devinit
+static int
 megasas_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct Scsi_Host *host;
@@ -2673,7 +2689,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
  * megasas_resume-      driver resume entry point
  * @pdev:               PCI device structure
  */
-static int __devinit
+static int
 megasas_resume(struct pci_dev *pdev)
 {
        int rval;
@@ -2768,12 +2784,16 @@ fail_ready_state:
 
        return -ENODEV;
 }
+#else
+#define megasas_suspend        NULL
+#define megasas_resume NULL
+#endif
 
 /**
  * megasas_detach_one -        PCI hot"un"plug entry point
  * @pdev:              PCI device structure
  */
-static void megasas_detach_one(struct pci_dev *pdev)
+static void __devexit megasas_detach_one(struct pci_dev *pdev)
 {
        int i;
        struct Scsi_Host *host;
@@ -2844,6 +2864,7 @@ static void megasas_shutdown(struct pci_dev *pdev)
  */
 static int megasas_mgmt_open(struct inode *inode, struct file *filep)
 {
+       cycle_kernel_lock();
        /*
         * Allow only those users with admin rights
         */
@@ -2909,7 +2930,6 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        void *sense = NULL;
        dma_addr_t sense_handle;
        u32 *sense_ptr;
-       unsigned long *sense_buff;
 
        memset(kbuff_arr, 0, sizeof(kbuff_arr));
 
@@ -3014,14 +3034,14 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
         */
        if (ioc->sense_len) {
                /*
-                * sense_buff points to the location that has the user
+                * sense_ptr points to the location that has the user
                 * sense buffer address
                 */
-               sense_buff = (unsigned long *) ((unsigned long)ioc->frame.raw +
-                                                               ioc->sense_off);
+               sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
+                                    ioc->sense_off);
 
-               if (copy_to_user((void __user *)(unsigned long)(*sense_buff),
-                               sense, ioc->sense_len)) {
+               if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
+                                sense, ioc->sense_len)) {
                        printk(KERN_ERR "megasas: Failed to copy out to user "
                                        "sense data\n");
                        error = -EFAULT;