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

Commit d009b576 authored by Sumit.Saxena@avagotech.com's avatar Sumit.Saxena@avagotech.com Committed by Christoph Hellwig
Browse files

megaraid_sas: online Firmware upgrade support for Extended VD feature



In OCR (Online Controller Reset) path, driver sets adapter state to
MEGASAS_HBA_OPERATIONAL before getting new RAID map.  There will be a small
window where IO will come from OS with old RAID map.  This patch will
update adapter state to MEGASAS_HBA_OPERATIONAL, only after driver has new
RAID map to avoid any IOs getting build using old RAID map.

Signed-off-by: default avatarSumit Saxena <sumit.saxena@avagotech.com>
Signed-off-by: default avatarKashyap Desai <kashyap.desai@avagotech.com>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent e399065b
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -1931,8 +1931,7 @@ u16 get_updated_dev_handle(struct megasas_instance *instance,
	struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *in_info);
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_get_ctrl_info(struct megasas_instance *instance);
int megasas_set_crash_dump_params(struct megasas_instance *instance,
	u8 crash_buf_state);
void megasas_free_host_crash_buffer(struct megasas_instance *instance);
+70 −12
Original line number Diff line number Diff line
@@ -4026,25 +4026,83 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
	return ret;
}

/*
 * megasas_update_ext_vd_details : Update details w.r.t Extended VD
 * instance			 : Controller's instance
*/
static void megasas_update_ext_vd_details(struct megasas_instance *instance)
{
	struct fusion_context *fusion;
	u32 old_map_sz;
	u32 new_map_sz;

	fusion = instance->ctrl_context;
	/* For MFI based controllers return dummy success */
	if (!fusion)
		return;

	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 VD %d PD\n",
		instance->fw_supported_vd_count,
		instance->fw_supported_pd_count);
	dev_info(&instance->pdev->dev, "Driver supports %d VD  %d PD\n",
		instance->drv_supported_vd_count,
		instance->drv_supported_pd_count);

	old_map_sz =  sizeof(struct MR_FW_RAID_MAP) +
				(sizeof(struct MR_LD_SPAN_MAP) *
				(instance->fw_supported_vd_count - 1));
	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->max_map_sz = max(old_map_sz, new_map_sz);


	if (instance->supportmax256vd)
		fusion->current_map_sz = new_map_sz;
	else
		fusion->current_map_sz = old_map_sz;

}

/**
 * megasas_get_controller_info -	Returns FW's controller structure
 * @instance:				Adapter soft state
 * @ctrl_info:				Controller information structure
 *
 * Issues an internal command (DCMD) to get the FW's controller structure.
 * This information is mainly used to find out the maximum IO transfer per
 * command supported by the FW.
 */
int
megasas_get_ctrl_info(struct megasas_instance *instance,
		      struct megasas_ctrl_info *ctrl_info)
megasas_get_ctrl_info(struct megasas_instance *instance)
{
	int ret = 0;
	struct megasas_cmd *cmd;
	struct megasas_dcmd_frame *dcmd;
	struct megasas_ctrl_info *ci;
	struct megasas_ctrl_info *ctrl_info;
	dma_addr_t ci_h = 0;

	ctrl_info = instance->ctrl_info;

	cmd = megasas_get_cmd(instance);

	if (!cmd) {
@@ -4084,8 +4142,13 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
	else
		ret = megasas_issue_polled(instance, cmd);

	if (!ret)
	if (!ret) {
		memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
		le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
		le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
		le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
		megasas_update_ext_vd_details(instance);
	}

	pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
			    ci, ci_h);
@@ -4287,7 +4350,7 @@ 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)) {
	if (megasas_get_ctrl_info(instance)) {
		dev_err(&instance->pdev->dev, "(%d): Could get controller info "
			"Fail from %s %d\n", instance->unique_id,
			__func__, __LINE__);
@@ -4525,12 +4588,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
		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;
@@ -4560,7 +4619,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
		       "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 =
@@ -4585,8 +4643,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
	if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
		instance->max_sectors_per_req = tmp_sectors;

	kfree(ctrl_info);

	/* Check for valid throttlequeuedepth module parameter */
	if (instance->is_imr) {
		if (throttlequeuedepth > (instance->max_fw_cmds -
@@ -5081,6 +5137,8 @@ static int megasas_probe_one(struct pci_dev *pdev,
			goto fail_alloc_dma_buf;
		}
		fusion = instance->ctrl_context;
		memset(fusion, 0,
			((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
		INIT_LIST_HEAD(&fusion->cmd_pool);
		spin_lock_init(&fusion->mpt_pool_lock);
		memset(fusion->load_balance_info, 0,
+14 −41
Original line number Diff line number Diff line
@@ -1067,48 +1067,16 @@ 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)) {
	if (megasas_get_ctrl_info(instance)) {
		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->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;
@@ -1123,16 +1091,10 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
					fusion->drv_map_pages);
			goto fail_ioc_init;
		}
		memset(fusion->ld_drv_map[i], 0,
			((1 << PAGE_SHIFT) << fusion->drv_map_pages));
	}

	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;


	for (i = 0; i < 2; i++) {
		fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
						       fusion->max_map_sz,
@@ -2387,6 +2349,8 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
				"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;
}
@@ -2844,6 +2808,15 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
			instance->instancet->enable_intr(instance);
			instance->adprecovery = MEGASAS_HBA_OPERATIONAL;

			if (megasas_get_ctrl_info(instance)) {
				dev_info(&instance->pdev->dev,
					"Failed from %s %d\n",
					__func__, __LINE__);
				instance->adprecovery =
					MEGASAS_HW_CRITICAL_ERROR;
				megaraid_sas_kill_hba(instance);
				retval = FAILED;
			}
			/* Reset load balance info */
			memset(fusion->load_balance_info, 0,
			       sizeof(struct LD_LOAD_BALANCE_INFO)
+0 −2
Original line number Diff line number Diff line
@@ -836,8 +836,6 @@ struct fusion_context {

	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;