commit 21c9e160a51383d4cb0b882398534b0c95c0cc3b implemented a new driver lookup using the MR_DCMD_LD_LIST_QUERY firmware command. However, this command might not work properly on older firmware, causing the command to return no drives instead of an error. This causes a regression on older firmware as the driver will no longer detect any drives. This patch checks if MR_DCMD_LD_LIST_QUERY return no drives, and falls back to the original method if so. Signed-off-by: Hannes Reinecke <hare@xxxxxxx> --- drivers/scsi/megaraid/megaraid_sas_base.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 39b08fc..a1cf2c3 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4502,7 +4502,6 @@ int megasas_alloc_cmds(struct megasas_instance *instance) dev_info(&instance->pdev->dev, "DCMD not supported by firmware - %s %d\n", __func__, __LINE__); - ret = megasas_get_ld_list(instance); break; case DCMD_TIMEOUT: switch (dcmd_timeout_ocr_possible(instance)) { @@ -4530,6 +4529,14 @@ int megasas_alloc_cmds(struct megasas_instance *instance) break; case DCMD_SUCCESS: tgtid_count = le32_to_cpu(ci->count); + /* + * Some older firmware return '0' if the LD LIST QUERY + * command is not supported. + */ + if (tgtid_count == 0) { + ret = DCMD_FAILED; + break; + } if ((tgtid_count > (instance->fw_supported_vd_count))) break; @@ -5146,7 +5153,7 @@ static int megasas_init_fw(struct megasas_instance *instance) struct megasas_register_set __iomem *reg_set; struct megasas_ctrl_info *ctrl_info = NULL; unsigned long bar_list; - int i, j, loop, fw_msix_count = 0; + int i, j, loop, fw_msix_count = 0, ret; struct IOV_111 *iovPtr; struct fusion_context *fusion; @@ -5384,8 +5391,11 @@ static int megasas_init_fw(struct megasas_instance *instance) } } - if (megasas_ld_list_query(instance, - MR_LD_QUERY_TYPE_EXPOSED_TO_HOST)) + ret = megasas_ld_list_query(instance, + MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); + if (ret == DCMD_FAILED) + ret = megasas_get_ld_list(instance); + if (ret) goto fail_get_ld_pd_list; /* @@ -7426,8 +7436,12 @@ static inline void megasas_remove_scsi_device(struct scsi_device *sdev) case MR_EVT_LD_DELETED: case MR_EVT_LD_CREATED: if (!instance->requestorId || - (instance->requestorId && megasas_get_ld_vf_affiliation(instance, 0))) + (instance->requestorId && + megasas_get_ld_vf_affiliation(instance, 0))) { dcmd_ret = megasas_ld_list_query(instance, MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); + if (dcmd_ret == DCMD_FAILED) + dcmd_ret = megasas_get_ld_list(instance); + } if (dcmd_ret == DCMD_SUCCESS) doscan = SCAN_VD_CHANNEL; @@ -7443,8 +7457,11 @@ static inline void megasas_remove_scsi_device(struct scsi_device *sdev) break; if (!instance->requestorId || - (instance->requestorId && megasas_get_ld_vf_affiliation(instance, 0))) + (instance->requestorId && megasas_get_ld_vf_affiliation(instance, 0))) { dcmd_ret = megasas_ld_list_query(instance, MR_LD_QUERY_TYPE_EXPOSED_TO_HOST); + if (dcmd_ret == DCMD_FAILED) + dcmd_ret = megasas_get_ld_list(instance); + } if (dcmd_ret != DCMD_SUCCESS) break; -- 1.8.5.6