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: Sumit Saxena <sumit.saxena@avagotech.com> Signed-off-by: Kashyap Desai <kashyap.desai@avagotech.com> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
e399065be0
commit
d009b5760f
@ -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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
"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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
"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)
|
|||||||
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 {
|
|||||||
|
|
||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user