Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -2115,7 +2115,6 @@ struct megasas_instance {
	u32 *crash_dump_buf;
	dma_addr_t crash_dump_h;
	void *crash_buf[MAX_CRASH_DUMP_SIZE];
	u32 crash_buf_pages;
	unsigned int    fw_crash_buffer_size;
	unsigned int    fw_crash_state;
	unsigned int    fw_crash_buffer_offset;
+9 −3
Original line number Diff line number Diff line
@@ -49,6 +49,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>
@@ -6671,9 +6672,14 @@ static void megasas_detach_one(struct pci_dev *pdev)
						  fusion->max_map_sz,
						  fusion->ld_map[i],
						  fusion->ld_map_phys[i]);
			if (fusion->ld_drv_map[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);
			}

			if (fusion->pd_seq_sync[i])
				dma_free_coherent(&instance->pdev->dev,
					pd_seq_map_sz,
+79 −42
Original line number Diff line number Diff line
@@ -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
 * @instance:		Adapter soft state
@@ -1381,45 +1455,14 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
	instance->r1_ldio_hint_default =  MR_R1_LDIO_PIGGYBACK_DEFAULT;
	fusion->fast_path_io = 0;

	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_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);
	if (megasas_allocate_raid_maps(instance))
		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))
		megasas_sync_map_info(instance);

	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:
	megasas_free_cmds_fusion(instance);
fail_alloc_cmds:
@@ -3371,17 +3414,13 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
{
	unsigned int i;

	instance->crash_buf_pages = get_order(CRASH_DMA_BUF_SIZE);
	for (i = 0; i < MAX_CRASH_DUMP_SIZE; i++) {
		instance->crash_buf[i] = (void	*)__get_free_pages(GFP_KERNEL,
				instance->crash_buf_pages);
		instance->crash_buf[i] = vzalloc(CRASH_DMA_BUF_SIZE);
		if (!instance->crash_buf[i]) {
			dev_info(&instance->pdev->dev, "Firmware crash dump "
				"memory allocation failed at index %d\n", i);
			break;
		}
		memset(instance->crash_buf[i], 0,
			((1 << PAGE_SHIFT) << instance->crash_buf_pages));
	}
	instance->drv_buf_alloc = i;
}
@@ -3393,12 +3432,10 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
void
megasas_free_host_crash_buffer(struct megasas_instance *instance)
{
	unsigned int i
;
	unsigned int i;
	for (i = 0; i < instance->drv_buf_alloc; i++) {
		if (instance->crash_buf[i])
			free_pages((ulong)instance->crash_buf[i],
					instance->crash_buf_pages);
			vfree(instance->crash_buf[i]);
	}
	instance->drv_buf_index = 0;
	instance->drv_buf_alloc = 0;