Commit 56ee0c58 authored by Anand Lodnoor's avatar Anand Lodnoor Committed by Martin K. Petersen

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.comSigned-off-by: default avatarSumit Saxena <sumit.saxena@broadcom.com>
Signed-off-by: default avatarShivasharan S <shivasharan.srikanteshwara@broadcom.com>
Signed-off-by: default avatarChandrakanth Patil <chandrakanth.patil@broadcom.com>
Signed-off-by: default avatarAnand Lodnoor <anand.lodnoor@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 6d753727
...@@ -4223,7 +4223,8 @@ void megasas_reset_reply_desc(struct megasas_instance *instance) ...@@ -4223,7 +4223,8 @@ void megasas_reset_reply_desc(struct megasas_instance *instance)
* megasas_refire_mgmt_cmd : Re-fire management commands * megasas_refire_mgmt_cmd : Re-fire management commands
* @instance: Controller's soft instance * @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; int j;
struct megasas_cmd_fusion *cmd_fusion; struct megasas_cmd_fusion *cmd_fusion;
...@@ -4287,6 +4288,16 @@ static void megasas_refire_mgmt_cmd(struct megasas_instance *instance) ...@@ -4287,6 +4288,16 @@ static void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
break; 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) { switch (result) {
case REFIRE_CMD: case REFIRE_CMD:
megasas_fire_cmd_fusion(instance, req_desc); megasas_fire_cmd_fusion(instance, req_desc);
...@@ -4301,6 +4312,37 @@ static void megasas_refire_mgmt_cmd(struct megasas_instance *instance) ...@@ -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 * megasas_track_scsiio : Track SCSI IOs outstanding to a SCSI device
* @instance: per adapter struct * @instance: per adapter struct
...@@ -4956,7 +4998,9 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) ...@@ -4956,7 +4998,9 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
goto kill_hba; 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 */ /* Reset load balance info */
if (fusion->load_balance_info) if (fusion->load_balance_info)
...@@ -4964,8 +5008,16 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) ...@@ -4964,8 +5008,16 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
(sizeof(struct LD_LOAD_BALANCE_INFO) * (sizeof(struct LD_LOAD_BALANCE_INFO) *
MAX_LOGICAL_DRIVES_EXT)); MAX_LOGICAL_DRIVES_EXT));
if (!megasas_get_map_info(instance)) if (!megasas_get_map_info(instance)) {
megasas_sync_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); megasas_setup_jbod_map(instance);
......
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