Commit def3e8df authored by Shivasharan S's avatar Shivasharan S Committed by Martin K. Petersen

scsi: megaraid_sas: use vmalloc for crash dump buffers and driver's local RAID map

Driver's local RAID map is accessed frequently. We will first try to get
memory from __get_free_pages. If this fails, fall back to using vmalloc.
For crash dump buffers always prefer vmalloc.
Signed-off-by: default avatarKashyap Desai <kashyap.desai@broadcom.com>
Signed-off-by: default avatarShivasharan S <shivasharan.srikanteshwara@broadcom.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 28661c88
...@@ -2115,7 +2115,6 @@ struct megasas_instance { ...@@ -2115,7 +2115,6 @@ struct megasas_instance {
u32 *crash_dump_buf; u32 *crash_dump_buf;
dma_addr_t crash_dump_h; dma_addr_t crash_dump_h;
void *crash_buf[MAX_CRASH_DUMP_SIZE]; void *crash_buf[MAX_CRASH_DUMP_SIZE];
u32 crash_buf_pages;
unsigned int fw_crash_buffer_size; unsigned int fw_crash_buffer_size;
unsigned int fw_crash_state; unsigned int fw_crash_state;
unsigned int fw_crash_buffer_offset; unsigned int fw_crash_buffer_offset;
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,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>
...@@ -6671,9 +6672,14 @@ static void megasas_detach_one(struct pci_dev *pdev) ...@@ -6671,9 +6672,14 @@ static void megasas_detach_one(struct pci_dev *pdev)
fusion->max_map_sz, fusion->max_map_sz,
fusion->ld_map[i], fusion->ld_map[i],
fusion->ld_map_phys[i]); fusion->ld_map_phys[i]);
if (fusion->ld_drv_map[i]) if (fusion->ld_drv_map[i]) {
free_pages((ulong)fusion->ld_drv_map[i], if (is_vmalloc_addr(fusion->ld_drv_map[i]))
fusion->drv_map_pages); vfree(fusion->ld_drv_map[i]);
else
free_pages((ulong)fusion->ld_drv_map[i],
fusion->drv_map_pages);
}
if (fusion->pd_seq_sync[i]) if (fusion->pd_seq_sync[i])
dma_free_coherent(&instance->pdev->dev, dma_free_coherent(&instance->pdev->dev,
pd_seq_map_sz, pd_seq_map_sz,
......
...@@ -1262,6 +1262,80 @@ megasas_display_intel_branding(struct megasas_instance *instance) ...@@ -1262,6 +1262,80 @@ megasas_display_intel_branding(struct megasas_instance *instance)
} }
} }
/**
* megasas_allocate_raid_maps - Allocate memory for RAID maps
* @instance: Adapter soft state
*
* return: if success: return 0
* failed: return -ENOMEM
*/
static inline int megasas_allocate_raid_maps(struct megasas_instance *instance)
{
struct fusion_context *fusion;
int i = 0;
fusion = instance->ctrl_context;
fusion->drv_map_pages = get_order(fusion->drv_map_sz);
for (i = 0; i < 2; i++) {
fusion->ld_map[i] = NULL;
fusion->ld_drv_map[i] = (void *)
__get_free_pages(__GFP_ZERO | GFP_KERNEL,
fusion->drv_map_pages);
if (!fusion->ld_drv_map[i]) {
fusion->ld_drv_map[i] = vzalloc(fusion->drv_map_sz);
if (!fusion->ld_drv_map[i]) {
dev_err(&instance->pdev->dev,
"Could not allocate memory for local map"
" size requested: %d\n",
fusion->drv_map_sz);
goto ld_drv_map_alloc_fail;
}
}
}
for (i = 0; i < 2; i++) {
fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
fusion->max_map_sz,
&fusion->ld_map_phys[i],
GFP_KERNEL);
if (!fusion->ld_map[i]) {
dev_err(&instance->pdev->dev,
"Could not allocate memory for map info %s:%d\n",
__func__, __LINE__);
goto ld_map_alloc_fail;
}
}
return 0;
ld_map_alloc_fail:
for (i = 0; i < 2; i++) {
if (fusion->ld_map[i])
dma_free_coherent(&instance->pdev->dev,
fusion->max_map_sz,
fusion->ld_map[i],
fusion->ld_map_phys[i]);
}
ld_drv_map_alloc_fail:
for (i = 0; i < 2; i++) {
if (fusion->ld_drv_map[i]) {
if (is_vmalloc_addr(fusion->ld_drv_map[i]))
vfree(fusion->ld_drv_map[i]);
else
free_pages((ulong)fusion->ld_drv_map[i],
fusion->drv_map_pages);
}
}
return -ENOMEM;
}
/** /**
* megasas_init_adapter_fusion - Initializes the FW * megasas_init_adapter_fusion - Initializes the FW
* @instance: Adapter soft state * @instance: Adapter soft state
...@@ -1381,45 +1455,14 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) ...@@ -1381,45 +1455,14 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
instance->r1_ldio_hint_default = MR_R1_LDIO_PIGGYBACK_DEFAULT; instance->r1_ldio_hint_default = MR_R1_LDIO_PIGGYBACK_DEFAULT;
fusion->fast_path_io = 0; fusion->fast_path_io = 0;
fusion->drv_map_pages = get_order(fusion->drv_map_sz); if (megasas_allocate_raid_maps(instance))
for (i = 0; i < 2; i++) { goto fail_ioc_init;
fusion->ld_map[i] = NULL;
fusion->ld_drv_map[i] = (void *)__get_free_pages(GFP_KERNEL,
fusion->drv_map_pages);
if (!fusion->ld_drv_map[i]) {
dev_err(&instance->pdev->dev, "Could not allocate "
"memory for local map info for %d pages\n",
fusion->drv_map_pages);
if (i == 1)
free_pages((ulong)fusion->ld_drv_map[0],
fusion->drv_map_pages);
goto fail_ioc_init;
}
memset(fusion->ld_drv_map[i], 0,
((1 << PAGE_SHIFT) << fusion->drv_map_pages));
}
for (i = 0; i < 2; i++) {
fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
fusion->max_map_sz,
&fusion->ld_map_phys[i],
GFP_KERNEL);
if (!fusion->ld_map[i]) {
dev_err(&instance->pdev->dev, "Could not allocate memory "
"for map info\n");
goto fail_map_info;
}
}
if (!megasas_get_map_info(instance)) if (!megasas_get_map_info(instance))
megasas_sync_map_info(instance); megasas_sync_map_info(instance);
return 0; return 0;
fail_map_info:
if (i == 1)
dma_free_coherent(&instance->pdev->dev, fusion->max_map_sz,
fusion->ld_map[0], fusion->ld_map_phys[0]);
fail_ioc_init: fail_ioc_init:
megasas_free_cmds_fusion(instance); megasas_free_cmds_fusion(instance);
fail_alloc_cmds: fail_alloc_cmds:
...@@ -3371,17 +3414,13 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance) ...@@ -3371,17 +3414,13 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
{ {
unsigned int i; unsigned int i;
instance->crash_buf_pages = get_order(CRASH_DMA_BUF_SIZE);
for (i = 0; i < MAX_CRASH_DUMP_SIZE; i++) { for (i = 0; i < MAX_CRASH_DUMP_SIZE; i++) {
instance->crash_buf[i] = (void *)__get_free_pages(GFP_KERNEL, instance->crash_buf[i] = vzalloc(CRASH_DMA_BUF_SIZE);
instance->crash_buf_pages);
if (!instance->crash_buf[i]) { if (!instance->crash_buf[i]) {
dev_info(&instance->pdev->dev, "Firmware crash dump " dev_info(&instance->pdev->dev, "Firmware crash dump "
"memory allocation failed at index %d\n", i); "memory allocation failed at index %d\n", i);
break; break;
} }
memset(instance->crash_buf[i], 0,
((1 << PAGE_SHIFT) << instance->crash_buf_pages));
} }
instance->drv_buf_alloc = i; instance->drv_buf_alloc = i;
} }
...@@ -3393,12 +3432,10 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance) ...@@ -3393,12 +3432,10 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
void void
megasas_free_host_crash_buffer(struct megasas_instance *instance) megasas_free_host_crash_buffer(struct megasas_instance *instance)
{ {
unsigned int i unsigned int i;
;
for (i = 0; i < instance->drv_buf_alloc; i++) { for (i = 0; i < instance->drv_buf_alloc; i++) {
if (instance->crash_buf[i]) if (instance->crash_buf[i])
free_pages((ulong)instance->crash_buf[i], vfree(instance->crash_buf[i]);
instance->crash_buf_pages);
} }
instance->drv_buf_index = 0; instance->drv_buf_index = 0;
instance->drv_buf_alloc = 0; instance->drv_buf_alloc = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment