Re: [PATCH 05/11] megaraid_sas : Extended VD support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 09/06/2014 03:25 PM, Sumit.Saxena@xxxxxxxxxxxxx wrote:
> Current MegaRAID firmware and hence the driver only supported 64VDs.
> E.g: If the user wants to create more than 64VD on a controller,
>     it is not possible on current firmware/driver.
>  
> New feature and requirement to support upto 256VD, firmware/driver/apps need changes. 
> In addition to that there must be a backward compatibility of the new driver with the 
> older firmware and vice versa.
>  
> RAID map is the interface between Driver and FW to fetch all required
> fields(attributes) for each Virtual Drives.
> In the earlier design driver was using the FW copy of RAID map where as
> in the new design the Driver will keep the RAID map copy of its own; on which
> it will operate for any raid map access in fast path.
>
> Local driver raid map copy will provide ease of access through out the code
> and provide generic interface for future FW raid map changes.
>  
> For the backward compatibility driver will notify FW that it supports 256VD
> to the FW in driver capability field.
> Based on the controller properly returned by the FW, the Driver will know
> whether it supports 256VD or not and will copy the RAID map accordingly.
>
> At any given time, driver will always have old or new Raid map.
> So with this changes, driver can also work in host lock less mode. Please 
> see next patch which enable host lock less mode for megaraid_sas driver.
>
> Signed-off-by: Sumit Saxena <sumit.saxena@xxxxxxxxxxxxx>
> Signed-off-by: Kashyap Desai <kashyap.desai@xxxxxxxxxxxxx>
> ---
>  drivers/scsi/megaraid/megaraid_sas.h        |  73 +++++++---
>  drivers/scsi/megaraid/megaraid_sas_base.c   | 205 ++++++++++++++++------------
>  drivers/scsi/megaraid/megaraid_sas_fp.c     | 195 ++++++++++++++++++--------
>  drivers/scsi/megaraid/megaraid_sas_fusion.c | 118 ++++++++++++----
>  drivers/scsi/megaraid/megaraid_sas_fusion.h |  95 ++++++++++++-
>  5 files changed, 502 insertions(+), 184 deletions(-)
>
> diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
> index e0f03e2..5dedf09 100644
> --- a/drivers/scsi/megaraid/megaraid_sas.h
> +++ b/drivers/scsi/megaraid/megaraid_sas.h
> @@ -390,7 +390,6 @@ enum MR_LD_QUERY_TYPE {
>  #define MR_EVT_FOREIGN_CFG_IMPORTED                     0x00db
>  #define MR_EVT_LD_OFFLINE                               0x00fc
>  #define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED             0x0152
> -#define MAX_LOGICAL_DRIVES				64
>  
>  enum MR_PD_STATE {
>  	MR_PD_STATE_UNCONFIGURED_GOOD   = 0x00,
> @@ -468,14 +467,14 @@ struct MR_LD_LIST {
>  		u8          state;
>  		u8          reserved[3];
>  		u64         size;
> -	} ldList[MAX_LOGICAL_DRIVES];
> +	} ldList[MAX_LOGICAL_DRIVES_EXT];
>  } __packed;
>  
>  struct MR_LD_TARGETID_LIST {
>  	u32	size;
>  	u32	count;
>  	u8	pad[3];
> -	u8	targetId[MAX_LOGICAL_DRIVES];
> +	u8	targetId[MAX_LOGICAL_DRIVES_EXT];
>  };
>  
>  
> @@ -941,6 +940,15 @@ struct megasas_ctrl_info {
>  	* HA cluster information
>  	*/
>  	struct {
> +#if defined(__BIG_ENDIAN_BITFIELD)
> +		u32     reserved:26;
> +		u32     premiumFeatureMismatch:1;
> +		u32     ctrlPropIncompatible:1;
> +		u32     fwVersionMismatch:1;
> +		u32     hwIncompatible:1;
> +		u32     peerIsIncompatible:1;
> +		u32     peerIsPresent:1;
> +#else
>  		u32     peerIsPresent:1;
>  		u32     peerIsIncompatible:1;
>  		u32     hwIncompatible:1;
> @@ -948,6 +956,7 @@ struct megasas_ctrl_info {
>  		u32     ctrlPropIncompatible:1;
>  		u32     premiumFeatureMismatch:1;
>  		u32     reserved:26;
> +#endif
>  	} cluster;
>  
>  	char clusterId[16];                     /*7D4h */
> @@ -962,9 +971,17 @@ struct megasas_ctrl_info {
>  #if defined(__BIG_ENDIAN_BITFIELD)
>  		u32     reserved:25;
>  		u32     supportCrashDump:1;
> -		u32     reserved1:6;
> +		u32     supportMaxExtLDs:1;
> +		u32     supportT10RebuildAssist:1;
> +		u32     supportDisableImmediateIO:1;
> +		u32     supportThermalPollInterval:1;
> +		u32     supportPersonalityChange:2;
>  #else
> -		u32     reserved1:6;
> +		u32     supportPersonalityChange:2;
> +		u32     supportThermalPollInterval:1;
> +		u32     supportDisableImmediateIO:1;
> +		u32     supportT10RebuildAssist:1;
> +		u32     supportMaxExtLDs:1;
>  		u32     supportCrashDump:1;
>  		u32     reserved:25;
>  #endif
> @@ -979,13 +996,12 @@ struct megasas_ctrl_info {
>   * ===============================
>   */
>  #define MEGASAS_MAX_PD_CHANNELS			2
> -#define MEGASAS_MAX_LD_CHANNELS			1
> +#define MEGASAS_MAX_LD_CHANNELS			2
>  #define MEGASAS_MAX_CHANNELS			(MEGASAS_MAX_PD_CHANNELS + \
>  						MEGASAS_MAX_LD_CHANNELS)
>  #define MEGASAS_MAX_DEV_PER_CHANNEL		128
>  #define MEGASAS_DEFAULT_INIT_ID			-1
>  #define MEGASAS_MAX_LUN				8
> -#define MEGASAS_MAX_LD				64
>  #define MEGASAS_DEFAULT_CMD_PER_LUN		256
>  #define MEGASAS_MAX_PD                          (MEGASAS_MAX_PD_CHANNELS * \
>  						MEGASAS_MAX_DEV_PER_CHANNEL)
> @@ -998,6 +1014,8 @@ struct megasas_ctrl_info {
>  
>  #define MEGASAS_FW_BUSY				1
>  
> +#define VD_EXT_DEBUG 0
> +
>  /* Frame Type */
>  #define IO_FRAME				0
>  #define PTHRU_FRAME				1
> @@ -1170,13 +1188,17 @@ union megasas_sgl_frame {
>  typedef union _MFI_CAPABILITIES {
>  	struct {
>  #if   defined(__BIG_ENDIAN_BITFIELD)
> -		u32     reserved:30;
> +		u32     reserved:28;
> +		u32	support_max_255lds:1;
> +		u32	reserved1:1;
>  		u32     support_additional_msix:1;
>  		u32     support_fp_remote_lun:1;
>  #else
>  		u32     support_fp_remote_lun:1;
>  		u32     support_additional_msix:1;
> -		u32     reserved:30;
> +		u32	reserved1:1;
> +		u32	support_max_255lds:1;
> +		u32     reserved:28;
>  #endif
>  	} mfi_capabilities;
>  	u32     reg;
> @@ -1665,6 +1687,14 @@ struct megasas_instance {
>  	u8 issuepend_done;
>  	u8 disableOnlineCtrlReset;
>  	u8 UnevenSpanSupport;
> +
> +	u8 supportmax256vd;
> +	u16 fw_supported_vd_count;
> +	u16 fw_supported_pd_count;
> +
> +	u16 drv_supported_vd_count;
> +	u16 drv_supported_pd_count;
> +
>  	u8 adprecovery;
>  	unsigned long last_time;
>  	u32 mfiStatus;
> @@ -1674,6 +1704,8 @@ struct megasas_instance {
>  
>  	/* Ptr to hba specific information */
>  	void *ctrl_context;
> +	u32 ctrl_context_pages;
> +	struct megasas_ctrl_info *ctrl_info;
>  	unsigned int msix_vectors;
>  	struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES];
>  	struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES];
> @@ -1874,16 +1906,21 @@ u8
>  MR_BuildRaidContext(struct megasas_instance *instance,
>  		    struct IO_REQUEST_INFO *io_info,
>  		    struct RAID_CONTEXT *pRAID_Context,
> -		    struct MR_FW_RAID_MAP_ALL *map, u8 **raidLUN);
> -u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
> -struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
> -u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map);
> -u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map);
> -u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map);
> -u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
> -
> +		    struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN);
> +u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map);
> +struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map);
> +u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map);
> +u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map);
> +u16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map);
> +u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map);
> +
> +void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
> +	struct LD_LOAD_BALANCE_INFO *lbInfo);
> +int megasas_get_ctrl_info(struct megasas_instance *instance,
> +	struct megasas_ctrl_info *ctrl_info);
>  int megasas_set_crash_dump_params(struct megasas_instance *instance,
> -		u8 crash_buf_state);
> +	u8 crash_buf_state);
>  void megasas_free_host_crash_buffer(struct megasas_instance *instance);
>  void megasas_fusion_crash_dump_wq(struct work_struct *work);
> +
>  #endif				/*LSI_MEGARAID_SAS_H */
> diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
> index 5b58e39d..9dbbd9d 100644
> --- a/drivers/scsi/megaraid/megaraid_sas_base.c
> +++ b/drivers/scsi/megaraid/megaraid_sas_base.c
> @@ -1581,7 +1581,8 @@ megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd
>  	scmd->result = 0;
>  
>  	if (MEGASAS_IS_LOGICAL(scmd) &&
> -	    (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) {
> +	    (scmd->device->id >= instance->fw_supported_vd_count ||
> +		scmd->device->lun)) {
>  		scmd->result = DID_BAD_TARGET << 16;
>  		goto out_done;
>  	}
> @@ -3846,6 +3847,8 @@ megasas_get_ld_list(struct megasas_instance *instance)
>  	memset(ci, 0, sizeof(*ci));
>  	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
>  
> +	if (instance->supportmax256vd)
> +		dcmd->mbox.b[0] = 1;
>  	dcmd->cmd = MFI_CMD_DCMD;
>  	dcmd->cmd_status = 0xFF;
>  	dcmd->sge_count = 1;
> @@ -3867,8 +3870,8 @@ megasas_get_ld_list(struct megasas_instance *instance)
>  
>  	/* the following function will get the instance PD LIST */
>  
> -	if ((ret == 0) && (ld_count <= MAX_LOGICAL_DRIVES)) {
> -		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
> +	if ((ret == 0) && (ld_count <= instance->fw_supported_vd_count)) {
> +		memset(instance->ld_ids, 0xff, MAX_LOGICAL_DRIVES_EXT);
>  
>  		for (ld_index = 0; ld_index < ld_count; ld_index++) {
>  			if (ci->ldList[ld_index].state != 0) {
> @@ -3931,6 +3934,8 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
>  	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
>  
>  	dcmd->mbox.b[0] = query_type;
> +	if (instance->supportmax256vd)
> +		dcmd->mbox.b[2] = 1;
>  
>  	dcmd->cmd = MFI_CMD_DCMD;
>  	dcmd->cmd_status = 0xFF;
> @@ -3952,7 +3957,7 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
>  
>  	tgtid_count = le32_to_cpu(ci->count);
>  
> -	if ((ret == 0) && (tgtid_count <= (MAX_LOGICAL_DRIVES))) {
> +	if ((ret == 0) && (tgtid_count <= (instance->fw_supported_vd_count))) {
>  		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
>  		for (ld_index = 0; ld_index < tgtid_count; ld_index++) {
>  			ids = ci->targetId[ld_index];
> @@ -3978,7 +3983,7 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
>   * This information is mainly used to find out the maximum IO transfer per
>   * command supported by the FW.
>   */
> -static int
> +int
>  megasas_get_ctrl_info(struct megasas_instance *instance,
>  		      struct megasas_ctrl_info *ctrl_info)
>  {
> @@ -4019,6 +4024,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
>  	dcmd->opcode = cpu_to_le32(MR_DCMD_CTRL_GET_INFO);
>  	dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(ci_h);
>  	dcmd->sgl.sge32[0].length = cpu_to_le32(sizeof(struct megasas_ctrl_info));
> +	dcmd->mbox.b[0] = 1;
>  
>  	if (!megasas_issue_polled(instance, cmd)) {
>  		ret = 0;
> @@ -4217,6 +4223,13 @@ megasas_init_adapter_mfi(struct megasas_instance *instance)
>  	if (megasas_issue_init_mfi(instance))
>  		goto fail_fw_init;
>  
> +	if (megasas_get_ctrl_info(instance, instance->ctrl_info)) {
> +		dev_err(&instance->pdev->dev, "(%d): Could get controller info "
> +			"Fail from %s %d\n", instance->unique_id,
> +			__func__, __LINE__);
> +		goto fail_fw_init;
> +	}
> +
>  	instance->fw_support_ieee = 0;
>  	instance->fw_support_ieee =
>  		(instance->instancet->read_fw_status_reg(reg_set) &
> @@ -4255,7 +4268,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
>  	u32 tmp_sectors, msix_enable, scratch_pad_2;
>  	resource_size_t base_addr;
>  	struct megasas_register_set __iomem *reg_set;
> -	struct megasas_ctrl_info *ctrl_info;
> +	struct megasas_ctrl_info *ctrl_info = NULL;
>  	unsigned long bar_list;
>  	int i, loop, fw_msix_count = 0;
>  	struct IOV_111 *iovPtr;
> @@ -4386,6 +4399,17 @@ static int megasas_init_fw(struct megasas_instance *instance)
>  			instance->msix_vectors);
>  	}
>  
> +	instance->ctrl_info = kzalloc(sizeof(struct megasas_ctrl_info),
> +				GFP_KERNEL);
> +	if (instance->ctrl_info == NULL)
> +		goto fail_init_adapter;
> +
> +	/*
> +	 * Below are default value for legacy Firmware.
> +	 * non-fusion based controllers
> +	 */
> +	instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
> +	instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
>  	/* Get operational params, sge flags, send init cmd to controller */
>  	if (instance->instancet->init_adapter(instance))
>  		goto fail_init_adapter;
> @@ -4408,8 +4432,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
>  				  MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
>  		megasas_get_ld_list(instance);
>  
> -	ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
> -
>  	/*
>  	 * Compute the max allowed sectors per IO: The controller info has two
>  	 * limits on max sectors. Driver should use the minimum of these two.
> @@ -4420,79 +4442,79 @@ static int megasas_init_fw(struct megasas_instance *instance)
>  	 * to calculate max_sectors_1. So the number ended up as zero always.
>  	 */
>  	tmp_sectors = 0;
> -	if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) {
> -
> -		max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
> -			le16_to_cpu(ctrl_info->max_strips_per_io);
> -		max_sectors_2 = le32_to_cpu(ctrl_info->max_request_size);
> +	ctrl_info = instance->ctrl_info;
>  
> -		tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
> +	max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
> +		le16_to_cpu(ctrl_info->max_strips_per_io);
> +	max_sectors_2 = le32_to_cpu(ctrl_info->max_request_size);
>  
> -		/*Check whether controller is iMR or MR */
> -		if (ctrl_info->memory_size) {
> -			instance->is_imr = 0;
> -			dev_info(&instance->pdev->dev, "Controller type: MR,"
> -				"Memory size is: %dMB\n",
> -				le16_to_cpu(ctrl_info->memory_size));
> -		} else {
> -			instance->is_imr = 1;
> -			dev_info(&instance->pdev->dev,
> -				"Controller type: iMR\n");
> -		}
> -		/* OnOffProperties are converted into CPU arch*/
> -		le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
> -		instance->disableOnlineCtrlReset =
> -		ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
> -		/* adapterOperations2 are converted into CPU arch*/
> -		le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
> -		instance->mpio = ctrl_info->adapterOperations2.mpio;
> -		instance->UnevenSpanSupport =
> -			ctrl_info->adapterOperations2.supportUnevenSpans;
> -		if (instance->UnevenSpanSupport) {
> -			struct fusion_context *fusion = instance->ctrl_context;
> -			dev_info(&instance->pdev->dev, "FW supports: "
> -			"UnevenSpanSupport=%x\n", instance->UnevenSpanSupport);
> -			if (MR_ValidateMapInfo(instance))
> -				fusion->fast_path_io = 1;
> -			else
> -				fusion->fast_path_io = 0;
> +	tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
>  
> -		}
> -		if (ctrl_info->host_interface.SRIOV) {
> -			if (!ctrl_info->adapterOperations2.activePassive)
> -				instance->PlasmaFW111 = 1;
> -
> -			if (!instance->PlasmaFW111)
> -				instance->requestorId =
> -					ctrl_info->iov.requestorId;
> -			else {
> -				iovPtr = (struct IOV_111 *)((unsigned char *)ctrl_info + IOV_111_OFFSET);
> -				instance->requestorId = iovPtr->requestorId;
> -			}
> -			printk(KERN_WARNING "megaraid_sas: I am VF "
> -			       "requestorId %d\n", instance->requestorId);
> -		}
> +	/*Check whether controller is iMR or MR */
> +	if (ctrl_info->memory_size) {
> +		instance->is_imr = 0;
> +		dev_info(&instance->pdev->dev, "Controller type: MR,"
> +			"Memory size is: %dMB\n",
> +			le16_to_cpu(ctrl_info->memory_size));
> +	} else {
> +		instance->is_imr = 1;
> +		dev_info(&instance->pdev->dev,
> +			"Controller type: iMR\n");
> +	}
> +	/* OnOffProperties are converted into CPU arch*/
> +	le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
> +	instance->disableOnlineCtrlReset =
> +	ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
> +	/* adapterOperations2 are converted into CPU arch*/
> +	le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
> +	instance->mpio = ctrl_info->adapterOperations2.mpio;
> +	instance->UnevenSpanSupport =
> +		ctrl_info->adapterOperations2.supportUnevenSpans;
> +	if (instance->UnevenSpanSupport) {
> +		struct fusion_context *fusion = instance->ctrl_context;
> +
> +		dev_info(&instance->pdev->dev, "FW supports: "
> +		"UnevenSpanSupport=%x\n", instance->UnevenSpanSupport);
> +		if (MR_ValidateMapInfo(instance))
> +			fusion->fast_path_io = 1;
> +		else
> +			fusion->fast_path_io = 0;
>  
> -		le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
> -		instance->crash_dump_fw_support =
> -			ctrl_info->adapterOperations3.supportCrashDump;
> -		instance->crash_dump_drv_support =
> -			(instance->crash_dump_fw_support &&
> -			instance->crash_dump_buf);
> -		if (instance->crash_dump_drv_support) {
> -			dev_info(&instance->pdev->dev, "Firmware Crash dump "
> -				"feature is supported\n");
> -			megasas_set_crash_dump_params(instance,
> -				MR_CRASH_BUF_TURN_OFF);
> +	}
> +	if (ctrl_info->host_interface.SRIOV) {
> +		if (!ctrl_info->adapterOperations2.activePassive)
> +			instance->PlasmaFW111 = 1;
>  
> -		} else {
> -			if (instance->crash_dump_buf)
> -				pci_free_consistent(instance->pdev,
> -					CRASH_DMA_BUF_SIZE,
> -					instance->crash_dump_buf,
> -					instance->crash_dump_h);
> -			instance->crash_dump_buf = NULL;
> +		if (!instance->PlasmaFW111)
> +			instance->requestorId =
> +				ctrl_info->iov.requestorId;
> +		else {
> +			iovPtr = (struct IOV_111 *)((unsigned char *)ctrl_info + IOV_111_OFFSET);
> +			instance->requestorId = iovPtr->requestorId;
>  		}
> +		dev_warn(&instance->pdev->dev, "I am VF "
> +		       "requestorId %d\n", instance->requestorId);
> +	}
> +
> +	le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
> +	instance->crash_dump_fw_support =
> +		ctrl_info->adapterOperations3.supportCrashDump;
> +	instance->crash_dump_drv_support =
> +		(instance->crash_dump_fw_support &&
> +		instance->crash_dump_buf);
> +	if (instance->crash_dump_drv_support) {
> +		dev_info(&instance->pdev->dev, "Firmware Crash dump "
> +			"feature is supported\n");
> +		megasas_set_crash_dump_params(instance,
> +			MR_CRASH_BUF_TURN_OFF);
> +
> +	} else {
> +		if (instance->crash_dump_buf)
> +			pci_free_consistent(instance->pdev,
> +				CRASH_DMA_BUF_SIZE,
> +				instance->crash_dump_buf,
> +				instance->crash_dump_h);
> +		instance->crash_dump_buf = NULL;
>  	}
>  	instance->max_sectors_per_req = instance->max_num_sge *
>  						PAGE_SIZE / 512;
> @@ -4540,6 +4562,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
>  
>  fail_init_adapter:
>  fail_ready_state:
> +	kfree(instance->ctrl_info);
> +	instance->ctrl_info = NULL;
>  	iounmap(instance->reg_set);
>  
>        fail_ioremap:
> @@ -4918,6 +4942,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
>  	struct Scsi_Host *host;
>  	struct megasas_instance *instance;
>  	u16 control = 0;
> +	struct fusion_context *fusion = NULL;
>  
>  	/* Reset MSI-X in the kdump kernel */
>  	if (reset_devices) {
> @@ -4978,10 +5003,10 @@ static int megasas_probe_one(struct pci_dev *pdev,
>  	case PCI_DEVICE_ID_LSI_INVADER:
>  	case PCI_DEVICE_ID_LSI_FURY:
>  	{
> -		struct fusion_context *fusion;
> -
> -		instance->ctrl_context =
> -			kzalloc(sizeof(struct fusion_context), GFP_KERNEL);
> +		instance->ctrl_context_pages =
> +			get_order(sizeof(struct fusion_context));
> +		instance->ctrl_context = (void *)__get_free_pages(GFP_KERNEL,
> +				instance->ctrl_context_pages);
>  		if (!instance->ctrl_context) {
>  			printk(KERN_DEBUG "megasas: Failed to allocate "
>  			       "memory for Fusion context info\n");
> @@ -4990,6 +5015,8 @@ static int megasas_probe_one(struct pci_dev *pdev,
>  		fusion = instance->ctrl_context;
>  		INIT_LIST_HEAD(&fusion->cmd_pool);
>  		spin_lock_init(&fusion->cmd_pool_lock);
> +		memset(fusion->load_balance_info, 0,
> +			sizeof(struct LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES_EXT);
>  	}
>  	break;
>  	default: /* For all other supported controllers */
> @@ -5033,7 +5060,6 @@ static int megasas_probe_one(struct pci_dev *pdev,
>  	instance->issuepend_done = 1;
>  	instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
>  	instance->is_imr = 0;
> -	megasas_poll_wait_aen = 0;
>  
>  	instance->evt_detail = pci_alloc_consistent(pdev,
>  						    sizeof(struct
> @@ -5070,6 +5096,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
>  	instance->host = host;
>  	instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
>  	instance->init_id = MEGASAS_DEFAULT_INIT_ID;
> +	instance->ctrl_info = NULL;
>  
>  	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
>  		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
> @@ -5630,14 +5657,18 @@ static void megasas_detach_one(struct pci_dev *pdev)
>  	case PCI_DEVICE_ID_LSI_INVADER:
>  	case PCI_DEVICE_ID_LSI_FURY:
>  		megasas_release_fusion(instance);
> -		for (i = 0; i < 2 ; i++)
> +		for (i = 0; i < 2 ; i++) {
>  			if (fusion->ld_map[i])
>  				dma_free_coherent(&instance->pdev->dev,
> -						  fusion->map_sz,
> +						  fusion->max_map_sz,
>  						  fusion->ld_map[i],
> -						  fusion->
> -						  ld_map_phys[i]);
> -		kfree(instance->ctrl_context);
> +						  fusion->ld_map_phys[i]);
> +			if (fusion->ld_drv_map[i])
> +				free_pages((ulong)fusion->ld_drv_map[i],
> +					fusion->drv_map_pages);
> +		}
> +		free_pages((ulong)instance->ctrl_context,
> +			instance->ctrl_context_pages);
>  		break;
>  	default:
>  		megasas_release_mfi(instance);
> @@ -5650,6 +5681,8 @@ static void megasas_detach_one(struct pci_dev *pdev)
>  		break;
>  	}
>  
> +	kfree(instance->ctrl_info);
> +
>  	if (instance->evt_detail)
>  		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
>  				instance->evt_detail, instance->evt_detail_h);
> @@ -5760,8 +5793,10 @@ static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
>  	spin_lock_irqsave(&poll_aen_lock, flags);
>  	if (megasas_poll_wait_aen)
>  		mask =   (POLLIN | POLLRDNORM);
> +
>  	else
>  		mask = 0;
> +	megasas_poll_wait_aen = 0;
>  	spin_unlock_irqrestore(&poll_aen_lock, flags);
>  	return mask;
>  }
> diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
> index 081bfff..c2eaf6e 100644
> --- a/drivers/scsi/megaraid/megaraid_sas_fp.c
> +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
> @@ -66,16 +66,13 @@
>  #define SPAN_INVALID  0xff
>  
>  /* Prototypes */
> -void mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
> -	struct LD_LOAD_BALANCE_INFO *lbInfo);
> -
> -static void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map,
> +static void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map,
>  	PLD_SPAN_INFO ldSpanInfo);
>  static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
>  	u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info,
> -	struct RAID_CONTEXT *pRAID_Context, struct MR_FW_RAID_MAP_ALL *map);
> +	struct RAID_CONTEXT *pRAID_Context, struct MR_DRV_RAID_MAP_ALL *map);
>  static u64 get_row_from_strip(struct megasas_instance *instance, u32 ld,
> -	u64 strip, struct MR_FW_RAID_MAP_ALL *map);
> +	u64 strip, struct MR_DRV_RAID_MAP_ALL *map);
>  
>  u32 mega_mod64(u64 dividend, u32 divisor)
>  {
> @@ -109,94 +106,183 @@ u64 mega_div64_32(uint64_t dividend, uint32_t divisor)
>  	return d;
>  }
>  
> -struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map)
> +struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	return &map->raidMap.ldSpanMap[ld].ldRaid;
>  }
>  
>  static struct MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u32 ld,
> -						   struct MR_FW_RAID_MAP_ALL
> +						   struct MR_DRV_RAID_MAP_ALL
>  						   *map)
>  {
>  	return &map->raidMap.ldSpanMap[ld].spanBlock[0];
>  }
>  
> -static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_FW_RAID_MAP_ALL *map)
> +static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx];
>  }
>  
> -u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map)
> +u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	return le16_to_cpu(map->raidMap.arMapInfo[ar].pd[arm]);
>  }
>  
> -u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map)
> +u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	return le16_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef);
>  }
>  
> -u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map)
> +u16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	return map->raidMap.devHndlInfo[pd].curDevHdl;
>  }
>  
> -u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map)
> +u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	return le16_to_cpu(map->raidMap.ldSpanMap[ld].ldRaid.targetId);
>  }
>  
> -u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map)
> +u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	return map->raidMap.ldTgtIdToLd[ldTgtId];
>  }
>  
>  static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span,
> -					  struct MR_FW_RAID_MAP_ALL *map)
> +					  struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	return &map->raidMap.ldSpanMap[ld].spanBlock[span].span;
>  }
>  
>  /*
> + * This function will Populate Driver Map using firmware raid map
> + */
> +void MR_PopulateDrvRaidMap(struct megasas_instance *instance)
> +{
> +	struct fusion_context *fusion = instance->ctrl_context;
> +	struct MR_FW_RAID_MAP_ALL     *fw_map_old    = NULL;
> +	struct MR_FW_RAID_MAP         *pFwRaidMap    = NULL;
> +	int i;
> +
> +
> +	struct MR_DRV_RAID_MAP_ALL *drv_map =
> +			fusion->ld_drv_map[(instance->map_id & 1)];
> +	struct MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap;
> +
> +	if (instance->supportmax256vd) {
> +		memcpy(fusion->ld_drv_map[instance->map_id & 1],
> +			fusion->ld_map[instance->map_id & 1],
> +			fusion->current_map_sz);
> +		/* New Raid map will not set totalSize, so keep expected value
> +		 * for legacy code in ValidateMapInfo
> +		 */
> +		pDrvRaidMap->totalSize = sizeof(struct MR_FW_RAID_MAP_EXT);
> +	} else {
> +		fw_map_old = (struct MR_FW_RAID_MAP_ALL *)
> +			fusion->ld_map[(instance->map_id & 1)];
> +		pFwRaidMap = &fw_map_old->raidMap;
> +
> +#if VD_EXT_DEBUG
> +		for (i = 0; i < pFwRaidMap->ldCount; i++) {
> +			dev_dbg(&instance->pdev->dev, "(%d) :Index 0x%x "
> +				"Target Id 0x%x Seq Num 0x%x Size 0/%llx\n",
> +				instance->unique_id, i,
> +				fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId,
> +				fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum,
> +				fw_map_old->raidMap.ldSpanMap[i].ldRaid.size);
> +		}
> +#endif
> +
> +		memset(drv_map, 0, fusion->drv_map_sz);
> +		pDrvRaidMap->totalSize = pFwRaidMap->totalSize;
> +		pDrvRaidMap->ldCount = pFwRaidMap->ldCount;
> +		pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec;
> +		for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++)
> +			pDrvRaidMap->ldTgtIdToLd[i] =
> +				(u8)pFwRaidMap->ldTgtIdToLd[i];
> +		for (i = 0; i < pDrvRaidMap->ldCount; i++) {
> +			pDrvRaidMap->ldSpanMap[i] = pFwRaidMap->ldSpanMap[i];
> +#if VD_EXT_DEBUG
> +			dev_dbg(&instance->pdev->dev,
> +				"pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x "
> +				"pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x "
> +				"size 0x%x\n", i, i,
> +				pFwRaidMap->ldSpanMap[i].ldRaid.targetId,
> +				pFwRaidMap->ldSpanMap[i].ldRaid.seqNum,
> +				(u32)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize);
> +			dev_dbg(&instance->pdev->dev,
> +				"pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x "
> +				"pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x "
> +				"size 0x%x\n", i, i,
> +				pDrvRaidMap->ldSpanMap[i].ldRaid.targetId,
> +				pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum,
> +				(u32)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize);
> +			dev_dbg(&instance->pdev->dev, "Driver raid map all %p "
> +				"raid map %p LD RAID MAP %p/%p\n", drv_map,
> +				pDrvRaidMap, &pFwRaidMap->ldSpanMap[i].ldRaid,
> +				&pDrvRaidMap->ldSpanMap[i].ldRaid);
> +#endif
> +		}
> +		memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo,
> +			sizeof(struct MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS);
> +		memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo,
> +			sizeof(struct MR_DEV_HANDLE_INFO) *
> +			MAX_RAIDMAP_PHYSICAL_DEVICES);
> +	}
> +}
> +
> +/*
>   * This function will validate Map info data provided by FW
>   */
>  u8 MR_ValidateMapInfo(struct megasas_instance *instance)
>  {
> -	struct fusion_context *fusion = instance->ctrl_context;
> -	struct MR_FW_RAID_MAP_ALL *map = fusion->ld_map[(instance->map_id & 1)];
> -	struct LD_LOAD_BALANCE_INFO *lbInfo = fusion->load_balance_info;
> -	PLD_SPAN_INFO ldSpanInfo = fusion->log_to_span;
> -	struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap;
> +	struct fusion_context *fusion;
> +	struct MR_DRV_RAID_MAP_ALL *drv_map;
> +	struct MR_DRV_RAID_MAP *pDrvRaidMap;
> +	struct LD_LOAD_BALANCE_INFO *lbInfo;
> +	PLD_SPAN_INFO ldSpanInfo;
>  	struct MR_LD_RAID         *raid;
>  	int ldCount, num_lds;
>  	u16 ld;
> +	u32 expected_size;
>  
>  
> -	if (le32_to_cpu(pFwRaidMap->totalSize) !=
> -	    (sizeof(struct MR_FW_RAID_MAP) -sizeof(struct MR_LD_SPAN_MAP) +
> -	     (sizeof(struct MR_LD_SPAN_MAP) * le32_to_cpu(pFwRaidMap->ldCount)))) {
> -		printk(KERN_ERR "megasas: map info structure size 0x%x is not matching with ld count\n",
> -		       (unsigned int)((sizeof(struct MR_FW_RAID_MAP) -
> -				       sizeof(struct MR_LD_SPAN_MAP)) +
> -				      (sizeof(struct MR_LD_SPAN_MAP) *
> -					le32_to_cpu(pFwRaidMap->ldCount))));
> -		printk(KERN_ERR "megasas: span map %x, pFwRaidMap->totalSize "
> -		       ": %x\n", (unsigned int)sizeof(struct MR_LD_SPAN_MAP),
> -			le32_to_cpu(pFwRaidMap->totalSize));
> +	MR_PopulateDrvRaidMap(instance);
> +
> +	fusion = instance->ctrl_context;
> +	drv_map = fusion->ld_drv_map[(instance->map_id & 1)];
> +	pDrvRaidMap = &drv_map->raidMap;
> +
> +	lbInfo = fusion->load_balance_info;
> +	ldSpanInfo = fusion->log_to_span;
> +
> +	if (instance->supportmax256vd)
> +		expected_size = sizeof(struct MR_FW_RAID_MAP_EXT);
> +	else
> +		expected_size =
> +			(sizeof(struct MR_FW_RAID_MAP) - sizeof(struct MR_LD_SPAN_MAP) +
> +			(sizeof(struct MR_LD_SPAN_MAP) * le32_to_cpu(pDrvRaidMap->ldCount)));
> +
> +	if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) {
> +		dev_err(&instance->pdev->dev, "map info structure size 0x%x is not matching with ld count\n",
> +		       (unsigned int) expected_size);
> +		dev_err(&instance->pdev->dev, "megasas: span map %x, pDrvRaidMap->totalSize : %x\n",
> +			(unsigned int)sizeof(struct MR_LD_SPAN_MAP),
> +			le32_to_cpu(pDrvRaidMap->totalSize));
>  		return 0;
>  	}
>  
>  	if (instance->UnevenSpanSupport)
> -		mr_update_span_set(map, ldSpanInfo);
> +		mr_update_span_set(drv_map, ldSpanInfo);
>  
> -	mr_update_load_balance_params(map, lbInfo);
> +	mr_update_load_balance_params(drv_map, lbInfo);
>  
> -	num_lds = le32_to_cpu(map->raidMap.ldCount);
> +	num_lds = le32_to_cpu(drv_map->raidMap.ldCount);
>  
>  	/*Convert Raid capability values to CPU arch */
>  	for (ldCount = 0; ldCount < num_lds; ldCount++) {
> -		ld = MR_TargetIdToLdGet(ldCount, map);
> -		raid = MR_LdRaidGet(ld, map);
> +		ld = MR_TargetIdToLdGet(ldCount, drv_map);
> +		raid = MR_LdRaidGet(ld, drv_map);
>  		le32_to_cpus((u32 *)&raid->capability);
>  	}
>  
> @@ -204,7 +290,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
>  }
>  
>  u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
> -		    struct MR_FW_RAID_MAP_ALL *map)
> +		    struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map);
>  	struct MR_QUAD_ELEMENT    *quad;
> @@ -246,7 +332,8 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
>  * ldSpanInfo - ldSpanInfo per HBA instance
>  */
>  #if SPAN_DEBUG
> -static int getSpanInfo(struct MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo)
> +static int getSpanInfo(struct MR_DRV_RAID_MAP_ALL *map,
> +	PLD_SPAN_INFO ldSpanInfo)
>  {
>  
>  	u8   span;
> @@ -257,9 +344,9 @@ static int getSpanInfo(struct MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo)
>  	int ldCount;
>  	u16 ld;
>  
> -	for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
> +	for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) {
>  		ld = MR_TargetIdToLdGet(ldCount, map);
> -			if (ld >= MAX_LOGICAL_DRIVES)
> +			if (ld >= MAX_LOGICAL_DRIVES_EXT)
>  				continue;
>  		raid = MR_LdRaidGet(ld, map);
>  		dev_dbg(&instance->pdev->dev, "LD %x: span_depth=%x\n",
> @@ -339,7 +426,7 @@ static int getSpanInfo(struct MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo)
>  */
>  
>  u32 mr_spanset_get_span_block(struct megasas_instance *instance,
> -		u32 ld, u64 row, u64 *span_blk, struct MR_FW_RAID_MAP_ALL *map)
> +		u32 ld, u64 row, u64 *span_blk, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	struct fusion_context *fusion = instance->ctrl_context;
>  	struct MR_LD_RAID         *raid = MR_LdRaidGet(ld, map);
> @@ -402,7 +489,7 @@ u32 mr_spanset_get_span_block(struct megasas_instance *instance,
>  */
>  
>  static u64  get_row_from_strip(struct megasas_instance *instance,
> -	u32 ld, u64 strip, struct MR_FW_RAID_MAP_ALL *map)
> +	u32 ld, u64 strip, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	struct fusion_context *fusion = instance->ctrl_context;
>  	struct MR_LD_RAID	*raid = MR_LdRaidGet(ld, map);
> @@ -471,7 +558,7 @@ static u64  get_row_from_strip(struct megasas_instance *instance,
>  */
>  
>  static u64 get_strip_from_row(struct megasas_instance *instance,
> -		u32 ld, u64 row, struct MR_FW_RAID_MAP_ALL *map)
> +		u32 ld, u64 row, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	struct fusion_context *fusion = instance->ctrl_context;
>  	struct MR_LD_RAID         *raid = MR_LdRaidGet(ld, map);
> @@ -532,7 +619,7 @@ static u64 get_strip_from_row(struct megasas_instance *instance,
>  */
>  
>  static u32 get_arm_from_strip(struct megasas_instance *instance,
> -	u32 ld, u64 strip, struct MR_FW_RAID_MAP_ALL *map)
> +	u32 ld, u64 strip, struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	struct fusion_context *fusion = instance->ctrl_context;
>  	struct MR_LD_RAID         *raid = MR_LdRaidGet(ld, map);
> @@ -580,7 +667,7 @@ static u32 get_arm_from_strip(struct megasas_instance *instance,
>  
>  /* This Function will return Phys arm */
>  u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe,
> -		struct MR_FW_RAID_MAP_ALL *map)
> +		struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	struct MR_LD_RAID  *raid = MR_LdRaidGet(ld, map);
>  	/* Need to check correct default value */
> @@ -624,7 +711,7 @@ u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe,
>  static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
>  		u64 stripRow, u16 stripRef, struct IO_REQUEST_INFO *io_info,
>  		struct RAID_CONTEXT *pRAID_Context,
> -		struct MR_FW_RAID_MAP_ALL *map)
> +		struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	struct MR_LD_RAID  *raid = MR_LdRaidGet(ld, map);
>  	u32     pd, arRef;
> @@ -705,7 +792,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
>  u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
>  		u16 stripRef, struct IO_REQUEST_INFO *io_info,
>  		struct RAID_CONTEXT *pRAID_Context,
> -		struct MR_FW_RAID_MAP_ALL *map)
> +		struct MR_DRV_RAID_MAP_ALL *map)
>  {
>  	struct MR_LD_RAID  *raid = MR_LdRaidGet(ld, map);
>  	u32         pd, arRef;
> @@ -794,7 +881,7 @@ u8
>  MR_BuildRaidContext(struct megasas_instance *instance,
>  		    struct IO_REQUEST_INFO *io_info,
>  		    struct RAID_CONTEXT *pRAID_Context,
> -		    struct MR_FW_RAID_MAP_ALL *map, u8 **raidLUN)
> +		    struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN)
>  {
>  	struct MR_LD_RAID  *raid;
>  	u32         ld, stripSize, stripe_mask;
> @@ -1043,7 +1130,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
>  * ldSpanInfo - ldSpanInfo per HBA instance
>  *
>  */
> -void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map,
> +void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map,
>  			PLD_SPAN_INFO ldSpanInfo)
>  {
>  	u8   span, count;
> @@ -1056,9 +1143,9 @@ void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map,
>  	u16 ld;
>  
>  
> -	for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
> +	for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) {
>  		ld = MR_TargetIdToLdGet(ldCount, map);
> -		if (ld >= MAX_LOGICAL_DRIVES)
> +		if (ld >= MAX_LOGICAL_DRIVES_EXT)
>  			continue;
>  		raid = MR_LdRaidGet(ld, map);
>  		for (element = 0; element < MAX_QUAD_DEPTH; element++) {
> @@ -1153,16 +1240,16 @@ void mr_update_span_set(struct MR_FW_RAID_MAP_ALL *map,
>  }
>  
>  void
> -mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map,
> +mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
>  			      struct LD_LOAD_BALANCE_INFO *lbInfo)
>  {
>  	int ldCount;
>  	u16 ld;
>  	struct MR_LD_RAID *raid;
>  
> -	for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
> +	for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) {
>  		ld = MR_TargetIdToLdGet(ldCount, map);
> -		if (ld >= MAX_LOGICAL_DRIVES) {
> +		if (ld >= MAX_LOGICAL_DRIVES_EXT) {
>  			lbInfo[ldCount].loadBalanceFlag = 0;
>  			continue;
>  		}
> diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
> index aaba2a7..65f617e 100644
> --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
> +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
> @@ -652,6 +652,8 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
>  	/* driver supports HA / Remote LUN over Fast Path interface */
>  	init_frame->driver_operations.mfi_capabilities.support_fp_remote_lun
>  		= 1;
> +	init_frame->driver_operations.mfi_capabilities.support_max_255lds
> +		= 1;
>  	/* Convert capability to LE32 */
>  	cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities);
>  
> @@ -711,6 +713,13 @@ fail_get_cmd:
>   * Issues an internal command (DCMD) to get the FW's controller PD
>   * list structure.  This information is mainly used to find out SYSTEM
>   * supported by the FW.
> + * dcmd.mbox value setting for MR_DCMD_LD_MAP_GET_INFO
> + * dcmd.mbox.b[0]	- number of LDs being sync'd
> + * dcmd.mbox.b[1]	- 0 - complete command immediately.
> + *			- 1 - pend till config change
> + * dcmd.mbox.b[2]	- 0 - supports max 64 lds and uses legacy MR_FW_RAID_MAP
> + *			- 1 - supports max MAX_LOGICAL_DRIVES_EXT lds and
> + *				uses extended struct MR_FW_RAID_MAP_EXT
>   */
>  static int
>  megasas_get_ld_map_info(struct megasas_instance *instance)
> @@ -718,7 +727,7 @@ megasas_get_ld_map_info(struct megasas_instance *instance)
>  	int ret = 0;
>  	struct megasas_cmd *cmd;
>  	struct megasas_dcmd_frame *dcmd;
> -	struct MR_FW_RAID_MAP_ALL *ci;
> +	void *ci;
>  	dma_addr_t ci_h = 0;
>  	u32 size_map_info;
>  	struct fusion_context *fusion;
> @@ -739,10 +748,9 @@ megasas_get_ld_map_info(struct megasas_instance *instance)
>  
>  	dcmd = &cmd->frame->dcmd;
>  
> -	size_map_info = sizeof(struct MR_FW_RAID_MAP) +
> -		(sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
> +	size_map_info = fusion->current_map_sz;
>  
> -	ci = fusion->ld_map[(instance->map_id & 1)];
> +	ci = (void *) fusion->ld_map[(instance->map_id & 1)];
>  	ci_h = fusion->ld_map_phys[(instance->map_id & 1)];
>  
>  	if (!ci) {
> @@ -751,9 +759,13 @@ megasas_get_ld_map_info(struct megasas_instance *instance)
>  		return -ENOMEM;
>  	}
>  
> -	memset(ci, 0, sizeof(*ci));
> +	memset(ci, 0, fusion->max_map_sz);
>  	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
> -
> +#if VD_EXT_DEBUG
> +	dev_dbg(&instance->pdev->dev,
> +		"%s sending MR_DCMD_LD_MAP_GET_INFO with size %d\n",
> +		__func__, cpu_to_le32(size_map_info));
> +#endif
>  	dcmd->cmd = MFI_CMD_DCMD;
>  	dcmd->cmd_status = 0xFF;
>  	dcmd->sge_count = 1;
> @@ -809,7 +821,7 @@ megasas_sync_map_info(struct megasas_instance *instance)
>  	u32 size_sync_info, num_lds;
>  	struct fusion_context *fusion;
>  	struct MR_LD_TARGET_SYNC *ci = NULL;
> -	struct MR_FW_RAID_MAP_ALL *map;
> +	struct MR_DRV_RAID_MAP_ALL *map;
>  	struct MR_LD_RAID  *raid;
>  	struct MR_LD_TARGET_SYNC *ld_sync;
>  	dma_addr_t ci_h = 0;
> @@ -830,7 +842,7 @@ megasas_sync_map_info(struct megasas_instance *instance)
>  		return 1;
>  	}
>  
> -	map = fusion->ld_map[instance->map_id & 1];
> +	map = fusion->ld_drv_map[instance->map_id & 1];
>  
>  	num_lds = le32_to_cpu(map->raidMap.ldCount);
>  
> @@ -842,7 +854,7 @@ megasas_sync_map_info(struct megasas_instance *instance)
>  
>  	ci = (struct MR_LD_TARGET_SYNC *)
>  	  fusion->ld_map[(instance->map_id - 1) & 1];
> -	memset(ci, 0, sizeof(struct MR_FW_RAID_MAP_ALL));
> +	memset(ci, 0, fusion->max_map_sz);
>  
>  	ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1];
>  
> @@ -854,8 +866,7 @@ megasas_sync_map_info(struct megasas_instance *instance)
>  		ld_sync->seqNum = raid->seqNum;
>  	}
>  
> -	size_map_info = sizeof(struct MR_FW_RAID_MAP) +
> -		(sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
> +	size_map_info = fusion->current_map_sz;
>  
>  	dcmd->cmd = MFI_CMD_DCMD;
>  	dcmd->cmd_status = 0xFF;
> @@ -1018,17 +1029,75 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
>  		goto fail_ioc_init;
>  
>  	megasas_display_intel_branding(instance);
> +	if (megasas_get_ctrl_info(instance, instance->ctrl_info)) {
> +		dev_err(&instance->pdev->dev,
> +			"Could not get controller info. Fail from %s %d\n",
> +			__func__, __LINE__);
> +		goto fail_ioc_init;
> +	}
> +
> +	instance->supportmax256vd =
> +		instance->ctrl_info->adapterOperations3.supportMaxExtLDs;
> +	/* Below is additional check to address future FW enhancement */
> +	if (instance->ctrl_info->max_lds > 64)
> +		instance->supportmax256vd = 1;
> +	instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS
> +					* MEGASAS_MAX_DEV_PER_CHANNEL;
> +	instance->drv_supported_pd_count = MEGASAS_MAX_PD_CHANNELS
> +					* MEGASAS_MAX_DEV_PER_CHANNEL;
> +	if (instance->supportmax256vd) {
> +		instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT;
> +		instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
> +	} else {
> +		instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
> +		instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
> +	}
> +	dev_info(&instance->pdev->dev, "Firmware supports %d VDs %d PDs\n"
> +		"Driver supports %d VDs  %d PDs\n",
> +		instance->fw_supported_vd_count,
> +		instance->fw_supported_pd_count,
> +		instance->drv_supported_vd_count,
> +		instance->drv_supported_pd_count);
>  
>  	instance->flag_ieee = 1;
> +	fusion->fast_path_io = 0;
>  
> -	fusion->map_sz =  sizeof(struct MR_FW_RAID_MAP) +
> -	  (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1));
> +	fusion->old_map_sz =
> +		sizeof(struct MR_FW_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) *
> +		(instance->fw_supported_vd_count - 1));
> +	fusion->new_map_sz =
> +		sizeof(struct MR_FW_RAID_MAP_EXT);
> +	fusion->drv_map_sz =
> +		sizeof(struct MR_DRV_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) *
> +		(instance->drv_supported_vd_count - 1));
> +
> +	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);
> +			goto fail_ioc_init;
> +		}
> +	}
> +
> +	fusion->max_map_sz = max(fusion->old_map_sz, fusion->new_map_sz);
> +
> +	if (instance->supportmax256vd)
> +		fusion->current_map_sz = fusion->new_map_sz;
> +	else
> +		fusion->current_map_sz = fusion->old_map_sz;
>  
> -	fusion->fast_path_io = 0;
>  
>  	for (i = 0; i < 2; i++) {
>  		fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
> -						       fusion->map_sz,
> +						       fusion->max_map_sz,
>  						       &fusion->ld_map_phys[i],
>  						       GFP_KERNEL);
>  		if (!fusion->ld_map[i]) {
> @@ -1045,7 +1114,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
>  
>  fail_map_info:
>  	if (i == 1)
> -		dma_free_coherent(&instance->pdev->dev, fusion->map_sz,
> +		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);
> @@ -1234,7 +1303,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
>  void
>  megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
>  		   struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp,
> -		   struct MR_FW_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
> +		   struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
>  {
>  	struct MR_LD_RAID *raid;
>  	u32 ld;
> @@ -1419,7 +1488,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
>  	union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
>  	struct IO_REQUEST_INFO io_info;
>  	struct fusion_context *fusion;
> -	struct MR_FW_RAID_MAP_ALL *local_map_ptr;
> +	struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
>  	u8 *raidLUN;
>  
>  	device_id = MEGASAS_DEV_INDEX(instance, scp);
> @@ -1496,10 +1565,10 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
>  	if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
>  		io_info.isRead = 1;
>  
> -	local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
> +	local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
>  
>  	if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >=
> -	     MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io)) {
> +		instance->fw_supported_vd_count) || (!fusion->fast_path_io)) {
>  		io_request->RaidContext.regLockFlags  = 0;
>  		fp_possible = 0;
>  	} else {
> @@ -1589,7 +1658,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
>  	u32 device_id;
>  	struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
>  	u16 pd_index = 0;
> -	struct MR_FW_RAID_MAP_ALL *local_map_ptr;
> +	struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
>  	struct fusion_context *fusion = instance->ctrl_context;
>  	u8                          span, physArm;
>  	u16                         devHandle;
> @@ -1601,7 +1670,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
>  	device_id = MEGASAS_DEV_INDEX(instance, scmd);
>  	pd_index = (scmd->device->channel * MEGASAS_MAX_DEV_PER_CHANNEL)
>  		+scmd->device->id;
> -	local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
> +	local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
>  
>  	io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
>  
> @@ -1649,7 +1718,8 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
>  			goto NonFastPath;
>  
>  		ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
> -		if ((ld >= MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io))
> +		if ((ld >= instance->fw_supported_vd_count) ||
> +			(!fusion->fast_path_io))
>  			goto NonFastPath;
>  
>  		raid = MR_LdRaidGet(ld, local_map_ptr);
> @@ -2724,7 +2794,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
>  			/* Reset load balance info */
>  			memset(fusion->load_balance_info, 0,
>  			       sizeof(struct LD_LOAD_BALANCE_INFO)
> -			       *MAX_LOGICAL_DRIVES);
> +			       *MAX_LOGICAL_DRIVES_EXT);
>  
>  			if (!megasas_get_map_info(instance))
>  				megasas_sync_map_info(instance);
> diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
> index d660c4d..0a6a430 100644
> --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
> +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
> @@ -479,10 +479,13 @@ struct MPI2_IOC_INIT_REQUEST {
>  #define MAX_ROW_SIZE 32
>  #define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
>  #define MAX_LOGICAL_DRIVES 64
> +#define MAX_LOGICAL_DRIVES_EXT 256
>  #define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES)
>  #define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES)
>  #define MAX_ARRAYS 128
>  #define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS)
> +#define MAX_ARRAYS_EXT	256
> +#define MAX_API_ARRAYS_EXT (MAX_ARRAYS_EXT)
>  #define MAX_PHYSICAL_DEVICES 256
>  #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
>  #define MR_DCMD_LD_MAP_GET_INFO             0x0300e101
> @@ -714,6 +717,83 @@ struct MR_FW_RAID_MAP_ALL {
>  	struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1];
>  } __attribute__ ((packed));
>  
> +struct MR_DRV_RAID_MAP {
> +	/* total size of this structure, including this field.
> +	 * This feild will be manupulated by driver for ext raid map,
> +	 * else pick the value from firmware raid map.
> +	 */
> +	u32                 totalSize;
> +
> +	union {
> +	struct {
> +		u32         maxLd;
> +		u32         maxSpanDepth;
> +		u32         maxRowSize;
> +		u32         maxPdCount;
> +		u32         maxArrays;
> +	} validationInfo;
> +	u32             version[5];
> +	u32             reserved1[5];

What is this 'reserved1' used for? In a union it does not
reserve  additional space, ther already is 'version' with the same size.

> +	};
> +
> +	/* timeout value used by driver in FP IOs*/
> +	u8                  fpPdIoTimeoutSec;
> +	u8                  reserved2[7];
> +
> +	u16                 ldCount;
> +	u16                 arCount;
> +	u16                 spanCount;
> +	u16                 reserve3;
> +
> +	struct MR_DEV_HANDLE_INFO  devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES];
> +	u8                  ldTgtIdToLd[MAX_LOGICAL_DRIVES_EXT];
> +	struct MR_ARRAY_INFO       arMapInfo[MAX_API_ARRAYS_EXT];
> +	struct MR_LD_SPAN_MAP      ldSpanMap[1];
> +
> +};
> +
> +/* Driver raid map size is same as raid map ext
> + * MR_DRV_RAID_MAP_ALL is created to sync with old raid.
> + * And it is mainly for code re-use purpose.
> + */
> +struct MR_DRV_RAID_MAP_ALL {
> +
> +	struct MR_DRV_RAID_MAP raidMap;
> +	struct MR_LD_SPAN_MAP      ldSpanMap[MAX_LOGICAL_DRIVES_EXT - 1];
> +} __packed;
> +
> +
> +
> +struct MR_FW_RAID_MAP_EXT {
> +	/* Not usred in new map */
> +	u32                 reserved;
> +
> +	union {
> +	struct {
> +		u32         maxLd;
> +		u32         maxSpanDepth;
> +		u32         maxRowSize;
> +		u32         maxPdCount;
> +		u32         maxArrays;
> +	} validationInfo;
> +	u32             version[5];
> +	u32             reserved1[5];
> +	};
> +
> +	u8                  fpPdIoTimeoutSec;
> +	u8                  reserved2[7];
> +
> +	u16                 ldCount;
> +	u16                 arCount;
> +	u16                 spanCount;
> +	u16                 reserve3;
> +
> +	struct MR_DEV_HANDLE_INFO  devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES];
> +	u8                  ldTgtIdToLd[MAX_LOGICAL_DRIVES_EXT];
> +	struct MR_ARRAY_INFO       arMapInfo[MAX_API_ARRAYS_EXT];
> +	struct MR_LD_SPAN_MAP      ldSpanMap[MAX_LOGICAL_DRIVES_EXT];
> +};
> +
>  struct fusion_context {
>  	struct megasas_cmd_fusion **cmd_list;
>  	struct list_head cmd_pool;
> @@ -750,10 +830,18 @@ struct fusion_context {
>  	struct MR_FW_RAID_MAP_ALL *ld_map[2];
>  	dma_addr_t ld_map_phys[2];
>  
> -	u32 map_sz;
> +	/*Non dma-able memory. Driver local copy.*/
> +	struct MR_DRV_RAID_MAP_ALL *ld_drv_map[2];
> +
> +	u32 max_map_sz;
> +	u32 current_map_sz;
> +	u32 old_map_sz;
> +	u32 new_map_sz;
> +	u32 drv_map_sz;
> +	u32 drv_map_pages;
>  	u8 fast_path_io;
> -	struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES];
> -	LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES];
> +	struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT];
> +	LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT];
>  };
>  
>  union desc_value {
> @@ -764,4 +852,5 @@ union desc_value {
>  	} u;
>  };
>  
> +
>  #endif /* _MEGARAID_SAS_FUSION_H_ */

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux