]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
scsi: megaraid_sas: reduce size of fusion_context and use vmalloc if kmalloc fails
authorShivasharan S <shivasharan.srikanteshwara@broadcom.com>
Fri, 10 Feb 2017 08:59:17 +0000 (00:59 -0800)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 1 Jun 2017 21:06:03 +0000 (14:06 -0700)
Orabug: 26096381

Currently fusion context has fixed array load_balance_info. Use dynamic
allocation.  In few places, driver do not want physically contigious
memory.  Attempt to use vmalloc if physical contiguous memory is not
available.

Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
(cherry picked from commit 5fc499b612c5401a7ae0674086befcdf8b148516)
Signed-off-by: Somasundaram Krishnasamy <somasundaram.krishnasamy@oracle.com>
Signed-off-by: Kirtikar Kashyap <kirtikar.kashyap@oracle.com>
Reviewed-by: Dhaval Giani <dhaval.giani@oracle.com>
Conflicts:
drivers/scsi/megaraid/megaraid_sas.h

drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fp.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/megaraid/megaraid_sas_fusion.h

index 4519452d1b0b5f399ba771838935792ed31f1025..899a5beef9379e37275a3f7e46ce24d2346bbc77 100644 (file)
@@ -2458,4 +2458,6 @@ void megasas_update_sdev_properties(struct scsi_device *sdev);
 int megasas_reset_fusion(struct Scsi_Host *shost, int reason);
 int megasas_task_abort_fusion(struct scsi_cmnd *scmd);
 int megasas_reset_target_fusion(struct scsi_cmnd *scmd);
+int megasas_alloc_fusion_context(struct megasas_instance *instance);
+void megasas_free_fusion_context(struct megasas_instance *instance);
 #endif                         /*LSI_MEGARAID_SAS_H */
index bf1a42e8531b4eced7de61658f2dbf75dfb5e999..b0ad619cce5a93170a4dd0f4cd412c98ffda2fb5 100644 (file)
@@ -5873,18 +5873,12 @@ static int megasas_probe_one(struct pci_dev *pdev,
        case PCI_DEVICE_ID_LSI_CUTLASS_52:
        case PCI_DEVICE_ID_LSI_CUTLASS_53:
        {
-               instance->ctrl_context_pages =
-                       get_order(sizeof(struct fusion_context));
-               instance->ctrl_context = (void *)__get_free_pages(GFP_KERNEL,
-                               instance->ctrl_context_pages);
-               if (!instance->ctrl_context) {
-                       dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate "
-                              "memory for Fusion context info\n");
+               if (megasas_alloc_fusion_context(instance)) {
+                       megasas_free_fusion_context(instance);
                        goto fail_alloc_dma_buf;
                }
                fusion = instance->ctrl_context;
-               memset(fusion, 0,
-                       ((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
+
                if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
                        (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA))
                        fusion->adapter_type = THUNDERBOLT_SERIES;
@@ -6504,8 +6498,7 @@ skip_firing_dcmds:
                                        fusion->pd_seq_sync[i],
                                        fusion->pd_seq_phys[i]);
                }
-               free_pages((ulong)instance->ctrl_context,
-                       instance->ctrl_context_pages);
+               megasas_free_fusion_context(instance);
        } else {
                megasas_release_mfi(instance);
                pci_free_consistent(pdev, sizeof(u32),
index 24258afb207f4f81ede8867029155c49a3e62a2a..bd3c41b2044d9992f629fd047875830c872d7e61 100644 (file)
@@ -484,7 +484,8 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
        if (instance->UnevenSpanSupport)
                mr_update_span_set(drv_map, ldSpanInfo);
 
-       mr_update_load_balance_params(drv_map, lbInfo);
+       if (lbInfo)
+               mr_update_load_balance_params(drv_map, lbInfo);
 
        num_lds = le16_to_cpu(drv_map->raidMap.ldCount);
 
index 81babcf8d741166857cd2212d4f8bf1c5c082b88..c665d2b4e242c6e442efc1b301416c3c68c2ddc0 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
 #include <linux/poll.h>
+#include <linux/vmalloc.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -2124,8 +2125,9 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
                        io_request->IoFlags |=
                        cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
                }
-               if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
-                   (io_info.isRead)) {
+               if (fusion->load_balance_info &&
+                       (fusion->load_balance_info[device_id].loadBalanceFlag) &&
+                       (io_info.isRead)) {
                        io_info.devHandle =
                                get_updated_dev_handle(instance,
                                        &fusion->load_balance_info[device_id],
@@ -3996,9 +3998,10 @@ transition_to_ready:
                                retval = FAILED;
                        }
                        /* Reset load balance info */
-                       memset(fusion->load_balance_info, 0,
-                              sizeof(struct LD_LOAD_BALANCE_INFO)
-                              *MAX_LOGICAL_DRIVES_EXT);
+                       if (fusion->load_balance_info)
+                               memset(fusion->load_balance_info, 0,
+                                      (sizeof(struct LD_LOAD_BALANCE_INFO) *
+                                      MAX_LOGICAL_DRIVES_EXT));
 
                        if (!megasas_get_map_info(instance))
                                megasas_sync_map_info(instance);
@@ -4152,6 +4155,64 @@ void megasas_fusion_ocr_wq(struct work_struct *work)
        megasas_reset_fusion(instance->host, 0);
 }
 
+/* Allocate fusion context */
+int
+megasas_alloc_fusion_context(struct megasas_instance *instance)
+{
+       struct fusion_context *fusion;
+
+       instance->ctrl_context_pages = get_order(sizeof(struct fusion_context));
+       instance->ctrl_context = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+               instance->ctrl_context_pages);
+       if (!instance->ctrl_context) {
+               /* fall back to using vmalloc for fusion_context */
+               instance->ctrl_context = vzalloc(sizeof(struct fusion_context));
+               if (!instance->ctrl_context) {
+                       dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__);
+                       return -ENOMEM;
+               }
+       }
+
+       fusion = instance->ctrl_context;
+
+       fusion->load_balance_info_pages = get_order(MAX_LOGICAL_DRIVES_EXT *
+               sizeof(struct LD_LOAD_BALANCE_INFO));
+       fusion->load_balance_info =
+               (struct LD_LOAD_BALANCE_INFO *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+               fusion->load_balance_info_pages);
+       if (!fusion->load_balance_info) {
+               fusion->load_balance_info = vzalloc(MAX_LOGICAL_DRIVES_EXT *
+                       sizeof(struct LD_LOAD_BALANCE_INFO));
+               if (!fusion->load_balance_info)
+                       dev_err(&instance->pdev->dev, "Failed to allocate load_balance_info, "
+                               "continuing without Load Balance support\n");
+       }
+
+       return 0;
+}
+
+void
+megasas_free_fusion_context(struct megasas_instance *instance)
+{
+       struct fusion_context *fusion = instance->ctrl_context;
+
+       if (fusion) {
+               if (fusion->load_balance_info) {
+                       if (is_vmalloc_addr(fusion->load_balance_info))
+                               vfree(fusion->load_balance_info);
+                       else
+                               free_pages((ulong)fusion->load_balance_info,
+                                       fusion->load_balance_info_pages);
+               }
+
+               if (is_vmalloc_addr(fusion))
+                       vfree(fusion);
+               else
+                       free_pages((ulong)fusion,
+                               instance->ctrl_context_pages);
+       }
+}
+
 struct megasas_instance_template megasas_instance_template_fusion = {
        .enable_intr = megasas_enable_intr_fusion,
        .disable_intr = megasas_disable_intr_fusion,
index 9d9658ea4e6e40936d0fc28d9e4919a9822d9154..0b21786df4e63f5944b359809cbc59043076c895 100644 (file)
@@ -1274,7 +1274,8 @@ struct fusion_context {
        struct MR_PD_CFG_SEQ_NUM_SYNC   *pd_seq_sync[JBOD_MAPS_COUNT];
        dma_addr_t pd_seq_phys[JBOD_MAPS_COUNT];
        u8 fast_path_io;
-       struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT];
+       struct LD_LOAD_BALANCE_INFO *load_balance_info;
+       u32 load_balance_info_pages;
        LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT];
        u8 adapter_type;
        struct LD_STREAM_DETECT **stream_detect_by_ld;