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

scsi: megaraid_sas: Resize MFA frame used for IOC INIT to 4k

Older firmware version unconditionally pulls 4k frame for IOC INIT MFA
frame.  But driver allocates 1k or 4k max_chain_frame_sz based on FW
capability.  During boot time, this results in DMA read errors.
Workaround fix in driver by allocating separate ioc_init frame of 4k
size to support older firmware.
Signed-off-by: default avatarKashyap Desai <kashyap.desai@broadcom.com>
Signed-off-by: default avatarShivasharan S <shivasharan.srikanteshwara@broadcom.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent b99fc202
...@@ -780,13 +780,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) ...@@ -780,13 +780,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
ioc_init_handle = fusion->ioc_init_request_phys; ioc_init_handle = fusion->ioc_init_request_phys;
IOCInitMessage = fusion->ioc_init_request; IOCInitMessage = fusion->ioc_init_request;
cmd = megasas_get_cmd(instance); cmd = fusion->ioc_init_cmd;
if (!cmd) {
dev_err(&instance->pdev->dev, "Could not allocate cmd for INIT Frame\n");
ret = 1;
goto fail_get_cmd;
}
scratch_pad_2 = readl scratch_pad_2 = readl
(&instance->reg_set->outbound_scratch_pad_2); (&instance->reg_set->outbound_scratch_pad_2);
...@@ -918,8 +912,6 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) ...@@ -918,8 +912,6 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
ret = 0; ret = 0;
fail_fw_init: fail_fw_init:
megasas_return_cmd(instance, cmd);
fail_get_cmd:
dev_err(&instance->pdev->dev, dev_err(&instance->pdev->dev,
"Init cmd return status %s for SCSI host %d\n", "Init cmd return status %s for SCSI host %d\n",
ret ? "FAILED" : "SUCCESS", instance->host->host_no); ret ? "FAILED" : "SUCCESS", instance->host->host_no);
...@@ -1333,6 +1325,56 @@ static inline int megasas_allocate_raid_maps(struct megasas_instance *instance) ...@@ -1333,6 +1325,56 @@ static inline int megasas_allocate_raid_maps(struct megasas_instance *instance)
return -ENOMEM; return -ENOMEM;
} }
static int megasas_alloc_ioc_init_frame(struct megasas_instance *instance)
{
struct fusion_context *fusion;
struct megasas_cmd *cmd;
fusion = instance->ctrl_context;
cmd = kmalloc(sizeof(struct megasas_cmd), GFP_KERNEL);
if (!cmd) {
dev_err(&instance->pdev->dev, "Failed from func: %s line: %d\n",
__func__, __LINE__);
return -ENOMEM;
}
cmd->frame = dma_alloc_coherent(&instance->pdev->dev,
IOC_INIT_FRAME_SIZE,
&cmd->frame_phys_addr, GFP_KERNEL);
if (!cmd->frame) {
dev_err(&instance->pdev->dev, "Failed from func: %s line: %d\n",
__func__, __LINE__);
kfree(cmd);
return -ENOMEM;
}
fusion->ioc_init_cmd = cmd;
return 0;
}
/**
* megasas_free_ioc_init_cmd - Free IOC INIT command frame
* @instance: Adapter soft state
*/
static inline void megasas_free_ioc_init_cmd(struct megasas_instance *instance)
{
struct fusion_context *fusion;
fusion = instance->ctrl_context;
if (fusion->ioc_init_cmd && fusion->ioc_init_cmd->frame)
dma_free_coherent(&instance->pdev->dev,
IOC_INIT_FRAME_SIZE,
fusion->ioc_init_cmd->frame,
fusion->ioc_init_cmd->frame_phys_addr);
if (fusion->ioc_init_cmd)
kfree(fusion->ioc_init_cmd);
}
/** /**
* megasas_init_adapter_fusion - Initializes the FW * megasas_init_adapter_fusion - Initializes the FW
* @instance: Adapter soft state * @instance: Adapter soft state
...@@ -1428,6 +1470,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) ...@@ -1428,6 +1470,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
MEGASAS_FUSION_IOCTL_CMDS); MEGASAS_FUSION_IOCTL_CMDS);
sema_init(&instance->ioctl_sem, MEGASAS_FUSION_IOCTL_CMDS); sema_init(&instance->ioctl_sem, MEGASAS_FUSION_IOCTL_CMDS);
if (megasas_alloc_ioc_init_frame(instance))
return 1;
/* /*
* Allocate memory for descriptors * Allocate memory for descriptors
* Create a pool of commands * Create a pool of commands
...@@ -1465,6 +1510,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) ...@@ -1465,6 +1510,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
fail_alloc_cmds: fail_alloc_cmds:
megasas_free_cmds(instance); megasas_free_cmds(instance);
fail_alloc_mfi_cmds: fail_alloc_mfi_cmds:
megasas_free_ioc_init_cmd(instance);
return 1; return 1;
} }
...@@ -3383,6 +3429,7 @@ megasas_issue_dcmd_fusion(struct megasas_instance *instance, ...@@ -3383,6 +3429,7 @@ megasas_issue_dcmd_fusion(struct megasas_instance *instance,
void void
megasas_release_fusion(struct megasas_instance *instance) megasas_release_fusion(struct megasas_instance *instance)
{ {
megasas_free_ioc_init_cmd(instance);
megasas_free_cmds(instance); megasas_free_cmds(instance);
megasas_free_cmds_fusion(instance); megasas_free_cmds_fusion(instance);
......
...@@ -103,6 +103,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE { ...@@ -103,6 +103,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
#define THRESHOLD_REPLY_COUNT 50 #define THRESHOLD_REPLY_COUNT 50
#define RAID_1_PEER_CMDS 2 #define RAID_1_PEER_CMDS 2
#define JBOD_MAPS_COUNT 2 #define JBOD_MAPS_COUNT 2
#define IOC_INIT_FRAME_SIZE 4096
/* /*
* Raid Context structure which describes MegaRAID specific IO Parameters * Raid Context structure which describes MegaRAID specific IO Parameters
...@@ -1317,6 +1318,7 @@ struct fusion_context { ...@@ -1317,6 +1318,7 @@ struct fusion_context {
struct LD_STREAM_DETECT **stream_detect_by_ld; struct LD_STREAM_DETECT **stream_detect_by_ld;
dma_addr_t ioc_init_request_phys; dma_addr_t ioc_init_request_phys;
struct MPI2_IOC_INIT_REQUEST *ioc_init_request; struct MPI2_IOC_INIT_REQUEST *ioc_init_request;
struct megasas_cmd *ioc_init_cmd;
}; };
......
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