forked from mirrors/linux
		
	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: Kashyap Desai <kashyap.desai@broadcom.com> Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com> Cc: stable@vger.kernel.org Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									b99fc20281
								
							
						
					
					
						commit
						b9637d14dc
					
				
					 2 changed files with 58 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -780,13 +780,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
 | 
			
		|||
	ioc_init_handle = fusion->ioc_init_request_phys;
 | 
			
		||||
	IOCInitMessage = fusion->ioc_init_request;
 | 
			
		||||
 | 
			
		||||
	cmd = megasas_get_cmd(instance);
 | 
			
		||||
 | 
			
		||||
	if (!cmd) {
 | 
			
		||||
		dev_err(&instance->pdev->dev, "Could not allocate cmd for INIT Frame\n");
 | 
			
		||||
		ret = 1;
 | 
			
		||||
		goto fail_get_cmd;
 | 
			
		||||
	}
 | 
			
		||||
	cmd = fusion->ioc_init_cmd;
 | 
			
		||||
 | 
			
		||||
	scratch_pad_2 = readl
 | 
			
		||||
		(&instance->reg_set->outbound_scratch_pad_2);
 | 
			
		||||
| 
						 | 
				
			
			@ -918,8 +912,6 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
 | 
			
		|||
	ret = 0;
 | 
			
		||||
 | 
			
		||||
fail_fw_init:
 | 
			
		||||
	megasas_return_cmd(instance, cmd);
 | 
			
		||||
fail_get_cmd:
 | 
			
		||||
	dev_err(&instance->pdev->dev,
 | 
			
		||||
		"Init cmd return status %s for SCSI host %d\n",
 | 
			
		||||
		ret ? "FAILED" : "SUCCESS", instance->host->host_no);
 | 
			
		||||
| 
						 | 
				
			
			@ -1333,6 +1325,56 @@ static inline int megasas_allocate_raid_maps(struct megasas_instance *instance)
 | 
			
		|||
	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
 | 
			
		||||
 * @instance:		Adapter soft state
 | 
			
		||||
| 
						 | 
				
			
			@ -1428,6 +1470,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
 | 
			
		|||
				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
 | 
			
		||||
	 * Create a pool of commands
 | 
			
		||||
| 
						 | 
				
			
			@ -1465,6 +1510,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
 | 
			
		|||
fail_alloc_cmds:
 | 
			
		||||
	megasas_free_cmds(instance);
 | 
			
		||||
fail_alloc_mfi_cmds:
 | 
			
		||||
	megasas_free_ioc_init_cmd(instance);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3383,6 +3429,7 @@ megasas_issue_dcmd_fusion(struct megasas_instance *instance,
 | 
			
		|||
void
 | 
			
		||||
megasas_release_fusion(struct megasas_instance *instance)
 | 
			
		||||
{
 | 
			
		||||
	megasas_free_ioc_init_cmd(instance);
 | 
			
		||||
	megasas_free_cmds(instance);
 | 
			
		||||
	megasas_free_cmds_fusion(instance);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,6 +103,7 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
 | 
			
		|||
#define THRESHOLD_REPLY_COUNT 50
 | 
			
		||||
#define RAID_1_PEER_CMDS 2
 | 
			
		||||
#define JBOD_MAPS_COUNT	2
 | 
			
		||||
#define IOC_INIT_FRAME_SIZE 4096
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Raid Context structure which describes MegaRAID specific IO Parameters
 | 
			
		||||
| 
						 | 
				
			
			@ -1317,6 +1318,7 @@ struct fusion_context {
 | 
			
		|||
	struct LD_STREAM_DETECT **stream_detect_by_ld;
 | 
			
		||||
	dma_addr_t ioc_init_request_phys;
 | 
			
		||||
	struct MPI2_IOC_INIT_REQUEST *ioc_init_request;
 | 
			
		||||
	struct megasas_cmd *ioc_init_cmd;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue