summaryrefslogtreecommitdiff
path: root/drivers/scsi/megaraid
diff options
context:
space:
mode:
authorShivasharan S <shivasharan.srikanteshwara@broadcom.com>2017-02-10 00:59:17 -0800
committerMartin K. Petersen <martin.petersen@oracle.com>2017-02-13 07:26:22 -0500
commit5fc499b612c5401a7ae0674086befcdf8b148516 (patch)
treec2e4b571415353ed30bfdb6ce89fc5bbaba25e8f /drivers/scsi/megaraid
parentb4a42213a7eb8ec8556f27e6750bbc5c9193e86e (diff)
scsi: megaraid_sas: reduce size of fusion_context and use vmalloc if kmalloc fails
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>
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c15
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c3
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c71
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h3
5 files changed, 76 insertions, 18 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 93da6dc196ad..0a20fff04192 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -2488,4 +2488,6 @@ 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);
u32 mega_mod64(u64 dividend, u32 divisor);
+int megasas_alloc_fusion_context(struct megasas_instance *instance);
+void megasas_free_fusion_context(struct megasas_instance *instance);
#endif /*LSI_MEGARAID_SAS_H */
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index c8fa480f9686..b2da25764261 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -6029,18 +6029,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;
@@ -6683,8 +6677,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),
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index c3ef82ddcc0f..d9b0f28cce8a 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -489,7 +489,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);
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 1252a3c08e1a..9019b82b467f 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -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>
@@ -2397,8 +2398,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],
@@ -4270,9 +4272,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);
@@ -4426,6 +4429,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,
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index c606ca000596..f25a26252790 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -1287,7 +1287,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;