scsi: megaraid_sas: Limit the number of retries for the IOCTLs causing firmware fault

IOCTLs causing firmware fault may end up in failed controller resets and
finally killing the adapter.

This patch fixes this problem as stated below:

In OCR sequence, driver will attempt refiring pended IOCTLs upto two times.
If first two attempts fail, then in third attempt driver will return pended
IOCTLs with EBUSY status to application. These changes are done to ensure
if any of pended IOCTLs is causing firmware fault and resulting into OCR
failure, then in last attempt of OCR driver will refrain firing it to
firmware and saving adapter from being killed due to faulty IOCTL.

Link: https://lore.kernel.org/r/1579000882-20246-10-git-send-email-anand.lodnoor@broadcom.com
Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
Signed-off-by: Chandrakanth Patil <chandrakanth.patil@broadcom.com>
Signed-off-by: Anand Lodnoor <anand.lodnoor@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Anand Lodnoor 2020-01-14 16:51:20 +05:30 committed by Martin K. Petersen
parent 6d7537270e
commit 56ee0c5856

View file

@ -4223,7 +4223,8 @@ void megasas_reset_reply_desc(struct megasas_instance *instance)
* megasas_refire_mgmt_cmd : Re-fire management commands
* @instance: Controller's soft instance
*/
static void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
void megasas_refire_mgmt_cmd(struct megasas_instance *instance,
bool return_ioctl)
{
int j;
struct megasas_cmd_fusion *cmd_fusion;
@ -4287,6 +4288,16 @@ static void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
break;
}
if (return_ioctl && cmd_mfi->sync_cmd &&
cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT) {
dev_err(&instance->pdev->dev,
"return -EBUSY from %s %d cmd 0x%x opcode 0x%x\n",
__func__, __LINE__, cmd_mfi->frame->hdr.cmd,
le32_to_cpu(cmd_mfi->frame->dcmd.opcode));
cmd_mfi->cmd_status_drv = DCMD_BUSY;
result = COMPLETE_CMD;
}
switch (result) {
case REFIRE_CMD:
megasas_fire_cmd_fusion(instance, req_desc);
@ -4301,6 +4312,37 @@ static void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
}
}
/*
* megasas_return_polled_cmds: Return polled mode commands back to the pool
* before initiating an OCR.
* @instance: Controller's soft instance
*/
static void
megasas_return_polled_cmds(struct megasas_instance *instance)
{
int i;
struct megasas_cmd_fusion *cmd_fusion;
struct fusion_context *fusion;
struct megasas_cmd *cmd_mfi;
fusion = instance->ctrl_context;
for (i = instance->max_scsi_cmds; i < instance->max_fw_cmds; i++) {
cmd_fusion = fusion->cmd_list[i];
cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
if (cmd_mfi->flags & DRV_DCMD_POLLED_MODE) {
if (megasas_dbg_lvl & OCR_DEBUG)
dev_info(&instance->pdev->dev,
"%s %d return cmd 0x%x opcode 0x%x\n",
__func__, __LINE__, cmd_mfi->frame->hdr.cmd,
le32_to_cpu(cmd_mfi->frame->dcmd.opcode));
cmd_mfi->flags &= ~DRV_DCMD_POLLED_MODE;
megasas_return_cmd(instance, cmd_mfi);
}
}
}
/*
* megasas_track_scsiio : Track SCSI IOs outstanding to a SCSI device
* @instance: per adapter struct
@ -4956,7 +4998,9 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
goto kill_hba;
}
megasas_refire_mgmt_cmd(instance);
megasas_refire_mgmt_cmd(instance,
(i == (MEGASAS_FUSION_MAX_RESET_TRIES - 1)
? 1 : 0));
/* Reset load balance info */
if (fusion->load_balance_info)
@ -4964,8 +5008,16 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
(sizeof(struct LD_LOAD_BALANCE_INFO) *
MAX_LOGICAL_DRIVES_EXT));
if (!megasas_get_map_info(instance))
if (!megasas_get_map_info(instance)) {
megasas_sync_map_info(instance);
} else {
/*
* Return pending polled mode cmds before
* retrying OCR
*/
megasas_return_polled_cmds(instance);
continue;
}
megasas_setup_jbod_map(instance);