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

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
...@@ -1931,8 +1931,7 @@ u16 get_updated_dev_handle(struct megasas_instance *instance, ...@@ -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); 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, void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
struct LD_LOAD_BALANCE_INFO *lbInfo); struct LD_LOAD_BALANCE_INFO *lbInfo);
int megasas_get_ctrl_info(struct megasas_instance *instance, 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, 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_free_host_crash_buffer(struct megasas_instance *instance);
......
...@@ -4026,25 +4026,83 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) ...@@ -4026,25 +4026,83 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
return ret; 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 * megasas_get_controller_info - Returns FW's controller structure
* @instance: Adapter soft state * @instance: Adapter soft state
* @ctrl_info: Controller information structure
* *
* Issues an internal command (DCMD) to get the FW's controller 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 * This information is mainly used to find out the maximum IO transfer per
* command supported by the FW. * command supported by the FW.
*/ */
int int
megasas_get_ctrl_info(struct megasas_instance *instance, megasas_get_ctrl_info(struct megasas_instance *instance)
struct megasas_ctrl_info *ctrl_info)
{ {
int ret = 0; int ret = 0;
struct megasas_cmd *cmd; struct megasas_cmd *cmd;
struct megasas_dcmd_frame *dcmd; struct megasas_dcmd_frame *dcmd;
struct megasas_ctrl_info *ci; struct megasas_ctrl_info *ci;
struct megasas_ctrl_info *ctrl_info;
dma_addr_t ci_h = 0; dma_addr_t ci_h = 0;
ctrl_info = instance->ctrl_info;
cmd = megasas_get_cmd(instance); cmd = megasas_get_cmd(instance);
if (!cmd) { if (!cmd) {
...@@ -4084,8 +4142,13 @@ megasas_get_ctrl_info(struct megasas_instance *instance, ...@@ -4084,8 +4142,13 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
else else
ret = megasas_issue_polled(instance, cmd); ret = megasas_issue_polled(instance, cmd);
if (!ret) if (!ret) {
memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info)); 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), pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
ci, ci_h); ci, ci_h);
...@@ -4287,7 +4350,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance) ...@@ -4287,7 +4350,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance)
if (megasas_issue_init_mfi(instance)) if (megasas_issue_init_mfi(instance))
goto fail_fw_init; 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 " dev_err(&instance->pdev->dev, "(%d): Could get controller info "
"Fail from %s %d\n", instance->unique_id, "Fail from %s %d\n", instance->unique_id,
__func__, __LINE__); __func__, __LINE__);
...@@ -4525,12 +4588,8 @@ static int megasas_init_fw(struct megasas_instance *instance) ...@@ -4525,12 +4588,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
dev_info(&instance->pdev->dev, dev_info(&instance->pdev->dev,
"Controller type: iMR\n"); "Controller type: iMR\n");
} }
/* OnOffProperties are converted into CPU arch*/
le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
instance->disableOnlineCtrlReset = instance->disableOnlineCtrlReset =
ctrl_info->properties.OnOffProperties.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->mpio = ctrl_info->adapterOperations2.mpio;
instance->UnevenSpanSupport = instance->UnevenSpanSupport =
ctrl_info->adapterOperations2.supportUnevenSpans; ctrl_info->adapterOperations2.supportUnevenSpans;
...@@ -4560,7 +4619,6 @@ static int megasas_init_fw(struct megasas_instance *instance) ...@@ -4560,7 +4619,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
"requestorId %d\n", instance->requestorId); "requestorId %d\n", instance->requestorId);
} }
le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
instance->crash_dump_fw_support = instance->crash_dump_fw_support =
ctrl_info->adapterOperations3.supportCrashDump; ctrl_info->adapterOperations3.supportCrashDump;
instance->crash_dump_drv_support = instance->crash_dump_drv_support =
...@@ -4585,8 +4643,6 @@ static int megasas_init_fw(struct megasas_instance *instance) ...@@ -4585,8 +4643,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors)) if (tmp_sectors && (instance->max_sectors_per_req > 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 */ /* Check for valid throttlequeuedepth module parameter */
if (instance->is_imr) { if (instance->is_imr) {
if (throttlequeuedepth > (instance->max_fw_cmds - if (throttlequeuedepth > (instance->max_fw_cmds -
...@@ -5081,6 +5137,8 @@ static int megasas_probe_one(struct pci_dev *pdev, ...@@ -5081,6 +5137,8 @@ static int megasas_probe_one(struct pci_dev *pdev,
goto fail_alloc_dma_buf; goto fail_alloc_dma_buf;
} }
fusion = instance->ctrl_context; fusion = instance->ctrl_context;
memset(fusion, 0,
((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
INIT_LIST_HEAD(&fusion->cmd_pool); INIT_LIST_HEAD(&fusion->cmd_pool);
spin_lock_init(&fusion->mpt_pool_lock); spin_lock_init(&fusion->mpt_pool_lock);
memset(fusion->load_balance_info, 0, memset(fusion->load_balance_info, 0,
......
...@@ -1067,48 +1067,16 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) ...@@ -1067,48 +1067,16 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
goto fail_ioc_init; goto fail_ioc_init;
megasas_display_intel_branding(instance); 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, dev_err(&instance->pdev->dev,
"Could not get controller info. Fail from %s %d\n", "Could not get controller info. Fail from %s %d\n",
__func__, __LINE__); __func__, __LINE__);
goto fail_ioc_init; 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; instance->flag_ieee = 1;
fusion->fast_path_io = 0; 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); fusion->drv_map_pages = get_order(fusion->drv_map_sz);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
fusion->ld_map[i] = NULL; fusion->ld_map[i] = NULL;
...@@ -1123,16 +1091,10 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) ...@@ -1123,16 +1091,10 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
fusion->drv_map_pages); fusion->drv_map_pages);
goto fail_ioc_init; 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++) { for (i = 0; i < 2; i++) {
fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev, fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
fusion->max_map_sz, fusion->max_map_sz,
...@@ -2387,6 +2349,8 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance) ...@@ -2387,6 +2349,8 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
"memory allocation failed at index %d\n", i); "memory allocation failed at index %d\n", i);
break; break;
} }
memset(instance->crash_buf[i], 0,
((1 << PAGE_SHIFT) << instance->crash_buf_pages));
} }
instance->drv_buf_alloc = i; instance->drv_buf_alloc = i;
} }
...@@ -2844,6 +2808,15 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout) ...@@ -2844,6 +2808,15 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
instance->instancet->enable_intr(instance); instance->instancet->enable_intr(instance);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL; 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 */ /* Reset load balance info */
memset(fusion->load_balance_info, 0, memset(fusion->load_balance_info, 0,
sizeof(struct LD_LOAD_BALANCE_INFO) sizeof(struct LD_LOAD_BALANCE_INFO)
......
...@@ -836,8 +836,6 @@ struct fusion_context { ...@@ -836,8 +836,6 @@ struct fusion_context {
u32 max_map_sz; u32 max_map_sz;
u32 current_map_sz; u32 current_map_sz;
u32 old_map_sz;
u32 new_map_sz;
u32 drv_map_sz; u32 drv_map_sz;
u32 drv_map_pages; u32 drv_map_pages;
u8 fast_path_io; u8 fast_path_io;
......
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