From: Hannes Reinecke <hare@suse.de>
Date: Wed, 16 Mar 2016 10:47:25 +0100
Subject: megaraid_sas: Fallback to older scanning if no disks are found
References: bnc#870440
Patch-Mainline: submitted linux-scsi 2017/08/13
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@suse.de>
Cc: Sumit Saxena <sumit.saxena@broadcom.com>
Cc: Kashyap Desai <kashyap.desai@broadcom.com>
Cc: megaraidlinux.pdl@broadcom.com
---
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 360e24f..8269953 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -4502,7 +4502,6 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
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 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
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;
/*
@@ -7440,8 +7450,12 @@ megasas_aen_polling(struct work_struct *work)
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;
@@ -7457,8 +7471,11 @@ megasas_aen_polling(struct work_struct *work)
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