mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
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>
This commit is contained in:
parent
b4a42213a7
commit
5fc499b612
5 changed files with 76 additions and 18 deletions
|
@ -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_task_abort_fusion(struct scsi_cmnd *scmd);
|
||||||
int megasas_reset_target_fusion(struct scsi_cmnd *scmd);
|
int megasas_reset_target_fusion(struct scsi_cmnd *scmd);
|
||||||
u32 mega_mod64(u64 dividend, u32 divisor);
|
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 */
|
#endif /*LSI_MEGARAID_SAS_H */
|
||||||
|
|
|
@ -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_52:
|
||||||
case PCI_DEVICE_ID_LSI_CUTLASS_53:
|
case PCI_DEVICE_ID_LSI_CUTLASS_53:
|
||||||
{
|
{
|
||||||
instance->ctrl_context_pages =
|
if (megasas_alloc_fusion_context(instance)) {
|
||||||
get_order(sizeof(struct fusion_context));
|
megasas_free_fusion_context(instance);
|
||||||
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");
|
|
||||||
goto fail_alloc_dma_buf;
|
goto fail_alloc_dma_buf;
|
||||||
}
|
}
|
||||||
fusion = instance->ctrl_context;
|
fusion = instance->ctrl_context;
|
||||||
memset(fusion, 0,
|
|
||||||
((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
|
|
||||||
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
|
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
|
||||||
(instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA))
|
(instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA))
|
||||||
fusion->adapter_type = THUNDERBOLT_SERIES;
|
fusion->adapter_type = THUNDERBOLT_SERIES;
|
||||||
|
@ -6683,8 +6677,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
|
||||||
fusion->pd_seq_sync[i],
|
fusion->pd_seq_sync[i],
|
||||||
fusion->pd_seq_phys[i]);
|
fusion->pd_seq_phys[i]);
|
||||||
}
|
}
|
||||||
free_pages((ulong)instance->ctrl_context,
|
megasas_free_fusion_context(instance);
|
||||||
instance->ctrl_context_pages);
|
|
||||||
} else {
|
} else {
|
||||||
megasas_release_mfi(instance);
|
megasas_release_mfi(instance);
|
||||||
pci_free_consistent(pdev, sizeof(u32),
|
pci_free_consistent(pdev, sizeof(u32),
|
||||||
|
|
|
@ -489,7 +489,8 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
|
||||||
if (instance->UnevenSpanSupport)
|
if (instance->UnevenSpanSupport)
|
||||||
mr_update_span_set(drv_map, ldSpanInfo);
|
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);
|
num_lds = le16_to_cpu(drv_map->raidMap.ldCount);
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
|
||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
#include <scsi/scsi_cmnd.h>
|
#include <scsi/scsi_cmnd.h>
|
||||||
|
@ -2397,8 +2398,9 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
|
||||||
io_request->IoFlags |=
|
io_request->IoFlags |=
|
||||||
cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
|
cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
|
||||||
}
|
}
|
||||||
if ((fusion->load_balance_info[device_id].loadBalanceFlag) &&
|
if (fusion->load_balance_info &&
|
||||||
(io_info.isRead)) {
|
(fusion->load_balance_info[device_id].loadBalanceFlag) &&
|
||||||
|
(io_info.isRead)) {
|
||||||
io_info.devHandle =
|
io_info.devHandle =
|
||||||
get_updated_dev_handle(instance,
|
get_updated_dev_handle(instance,
|
||||||
&fusion->load_balance_info[device_id],
|
&fusion->load_balance_info[device_id],
|
||||||
|
@ -4270,9 +4272,10 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
|
||||||
retval = FAILED;
|
retval = FAILED;
|
||||||
}
|
}
|
||||||
/* Reset load balance info */
|
/* Reset load balance info */
|
||||||
memset(fusion->load_balance_info, 0,
|
if (fusion->load_balance_info)
|
||||||
sizeof(struct LD_LOAD_BALANCE_INFO)
|
memset(fusion->load_balance_info, 0,
|
||||||
*MAX_LOGICAL_DRIVES_EXT);
|
(sizeof(struct LD_LOAD_BALANCE_INFO) *
|
||||||
|
MAX_LOGICAL_DRIVES_EXT));
|
||||||
|
|
||||||
if (!megasas_get_map_info(instance))
|
if (!megasas_get_map_info(instance))
|
||||||
megasas_sync_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);
|
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 = {
|
struct megasas_instance_template megasas_instance_template_fusion = {
|
||||||
.enable_intr = megasas_enable_intr_fusion,
|
.enable_intr = megasas_enable_intr_fusion,
|
||||||
.disable_intr = megasas_disable_intr_fusion,
|
.disable_intr = megasas_disable_intr_fusion,
|
||||||
|
|
|
@ -1287,7 +1287,8 @@ struct fusion_context {
|
||||||
struct MR_PD_CFG_SEQ_NUM_SYNC *pd_seq_sync[JBOD_MAPS_COUNT];
|
struct MR_PD_CFG_SEQ_NUM_SYNC *pd_seq_sync[JBOD_MAPS_COUNT];
|
||||||
dma_addr_t pd_seq_phys[JBOD_MAPS_COUNT];
|
dma_addr_t pd_seq_phys[JBOD_MAPS_COUNT];
|
||||||
u8 fast_path_io;
|
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];
|
LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT];
|
||||||
u8 adapter_type;
|
u8 adapter_type;
|
||||||
struct LD_STREAM_DETECT **stream_detect_by_ld;
|
struct LD_STREAM_DETECT **stream_detect_by_ld;
|
||||||
|
|
Loading…
Reference in a new issue