Merge tag '4.4-scsi-mkp' into misc
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / megaraid / megaraid_sas_base.c
index d61e35380b0e162186fcac30a4d851618dc8c02e..97a1c1c33b05dd2ba7e2dfe4feb3469dce3b6199 100644 (file)
@@ -1725,8 +1725,56 @@ static struct megasas_instance *megasas_lookup_instance(u16 host_no)
        return NULL;
 }
 
+/*
+* megasas_set_dma_alignment - Set DMA alignment for PI enabled VD
+*
+* @sdev: OS provided scsi device
+*
+* Returns void
+*/
+static void megasas_set_dma_alignment(struct scsi_device *sdev)
+{
+       u32 device_id, ld;
+       struct megasas_instance *instance;
+       struct fusion_context *fusion;
+       struct MR_LD_RAID *raid;
+       struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
+
+       instance = megasas_lookup_instance(sdev->host->host_no);
+       fusion = instance->ctrl_context;
+
+       if (!fusion)
+               return;
+
+       if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS) {
+               device_id = ((sdev->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL)
+                                       + sdev->id;
+               local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
+               ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
+               raid = MR_LdRaidGet(ld, local_map_ptr);
+
+               if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER)
+                       blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
+       }
+}
+
 static int megasas_slave_configure(struct scsi_device *sdev)
 {
+       u16 pd_index = 0;
+       struct megasas_instance *instance;
+
+       instance = megasas_lookup_instance(sdev->host->host_no);
+       if (instance->allow_fw_scan) {
+               if (sdev->channel < MEGASAS_MAX_PD_CHANNELS &&
+                       sdev->type == TYPE_DISK) {
+                       pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
+                               sdev->id;
+                       if (instance->pd_list[pd_index].driveState !=
+                               MR_PD_STATE_SYSTEM)
+                               return -ENXIO;
+               }
+       }
+       megasas_set_dma_alignment(sdev);
        /*
         * The RAID firmware may require extended timeouts.
         */
@@ -1749,9 +1797,8 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
                pd_index =
                        (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
                        sdev->id;
-               if ((instance->pd_list[pd_index].driveState ==
-                       MR_PD_STATE_SYSTEM) ||
-                       (instance->pd_list[pd_index].driveType != TYPE_DISK)) {
+               if ((instance->allow_fw_scan || instance->pd_list[pd_index].driveState ==
+                       MR_PD_STATE_SYSTEM)) {
                        return 0;
                }
                return -ENXIO;
@@ -4665,6 +4712,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
        case PCI_DEVICE_ID_DELL_PERC5:
        default:
                instance->instancet = &megasas_instance_template_xscale;
+               instance->allow_fw_scan = 1;
                break;
        }
 
@@ -4745,6 +4793,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
                "current msix/online cpus\t: (%d/%d)\n",
                instance->msix_vectors, (unsigned int)num_online_cpus());
 
+       tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
+               (unsigned long)instance);
+
        if (instance->msix_vectors ?
                megasas_setup_irqs_msix(instance, 1) :
                megasas_setup_irqs_ioapic(instance))
@@ -4765,8 +4816,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
        if (instance->instancet->init_adapter(instance))
                goto fail_init_adapter;
 
-       tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
-               (unsigned long)instance);
 
        instance->instancet->enable_intr(instance);
 
@@ -5168,7 +5217,6 @@ static int megasas_start_aen(struct megasas_instance *instance)
 static int megasas_io_attach(struct megasas_instance *instance)
 {
        struct Scsi_Host *host = instance->host;
-       u32 error;
 
        /*
         * Export parameters required by SCSI mid-layer
@@ -5215,13 +5263,6 @@ static int megasas_io_attach(struct megasas_instance *instance)
                host->hostt->eh_device_reset_handler = NULL;
                host->hostt->eh_bus_reset_handler = NULL;
        }
-       error = scsi_init_shared_tag_map(host, host->can_queue);
-       if (error) {
-               dev_err(&instance->pdev->dev,
-                       "Failed to shared tag from %s %d\n",
-                       __func__, __LINE__);
-               return -ENODEV;
-       }
 
        /*
         * Notify the mid-layer about the new controller
@@ -6435,6 +6476,9 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
        int i;
        int error = 0;
        compat_uptr_t ptr;
+       unsigned long local_raw_ptr;
+       u32 local_sense_off;
+       u32 local_sense_len;
 
        if (clear_user(ioc, sizeof(*ioc)))
                return -EFAULT;
@@ -6452,9 +6496,15 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
         * sense_len is not null, so prepare the 64bit value under
         * the same condition.
         */
-       if (ioc->sense_len) {
+       if (get_user(local_raw_ptr, ioc->frame.raw) ||
+               get_user(local_sense_off, &ioc->sense_off) ||
+               get_user(local_sense_len, &ioc->sense_len))
+               return -EFAULT;
+
+
+       if (local_sense_len) {
                void __user **sense_ioc_ptr =
-                       (void __user **)(ioc->frame.raw + ioc->sense_off);
+                       (void __user **)((u8*)local_raw_ptr + local_sense_off);
                compat_uptr_t *sense_cioc_ptr =
                        (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
                if (get_user(ptr, sense_cioc_ptr) ||