Commit 2be2a988 authored by Sumit.Saxena@avagotech.com's avatar Sumit.Saxena@avagotech.com Committed by James Bottomley

megaraid_sas : Modify return value of megasas_issue_blocked_cmd() and...

megaraid_sas : Modify return value of megasas_issue_blocked_cmd() and wait_and_poll() to consider command status returned by firmware

This patch is rebased on top of recently sent 18 patches(submitted by me) for
megaraid_sas driver.

Change the return value of wait_and_poll() and megsas_issue_blocked_cmd()
based on MFI_STAT returned by firmware for that command. Earlier driver always
send return type based on command completion (but never check MFI_STAT_OK for
that command), so even if command is failed by firmware still driver will
return SUCCESS status from these functions wait_and_poll() and
megsas_issue_blocked_cmd() and if caller of these functions does not check
command status (MFI_STAT), then it may endup using invalid data returned in
DMA buffers(one of the example is megasas_ld_list_query DCMD). Best thing to
avoid this type of issue is do error handling and set proper return type from
caller function wait_and_poll() and megsas_issue_blocked_cmd().

The change proposed in this patch will fix the regression introduced in patch-
"90dc9d98 megaraid_sas : MFI MPT linked list corruption fix" inside function
megasas_ld_list_query().  Prior to this MFI MPT linked list corruption fix
patch, megasas_ld_list_query() function used to check DCMD status(returned by
firmware) but with this linked list corruption fix patch, DCMD status will not
be checked inside function megasas_ld_list_query() and introduced this issue
of wrong data being used by function megasas_ld_list_query().

Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarKashyap Desai <kashyap.desai@avagotech.com>
Signed-off-by: default avatarSumit Saxena <sumit.saxena@avagotech.com>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent b84b1d52
...@@ -1894,7 +1894,7 @@ struct megasas_cmd { ...@@ -1894,7 +1894,7 @@ struct megasas_cmd {
u32 index; u32 index;
u8 sync_cmd; u8 sync_cmd;
u8 cmd_status; u8 cmd_status_drv;
u8 abort_aen; u8 abort_aen;
u8 retry_for_fw_reset; u8 retry_for_fw_reset;
......
...@@ -898,7 +898,7 @@ extern struct megasas_instance_template megasas_instance_template_fusion; ...@@ -898,7 +898,7 @@ extern struct megasas_instance_template megasas_instance_template_fusion;
* @instance: Adapter soft state * @instance: Adapter soft state
* @cmd: Command packet to be issued * @cmd: Command packet to be issued
* *
* For polling, MFI requires the cmd_status to be set to 0xFF before posting. * For polling, MFI requires the cmd_status to be set to MFI_STAT_INVALID_STATUS before posting.
*/ */
int int
megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd)
...@@ -940,19 +940,20 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, ...@@ -940,19 +940,20 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance,
struct megasas_cmd *cmd, int timeout) struct megasas_cmd *cmd, int timeout)
{ {
int ret = 0; int ret = 0;
cmd->cmd_status = ENODATA; cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
instance->instancet->issue_dcmd(instance, cmd); instance->instancet->issue_dcmd(instance, cmd);
if (timeout) { if (timeout) {
ret = wait_event_timeout(instance->int_cmd_wait_q, ret = wait_event_timeout(instance->int_cmd_wait_q,
cmd->cmd_status != ENODATA, timeout * HZ); cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ);
if (!ret) if (!ret)
return 1; return 1;
} else } else
wait_event(instance->int_cmd_wait_q, wait_event(instance->int_cmd_wait_q,
cmd->cmd_status != ENODATA); cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS);
return 0; return (cmd->cmd_status_drv == MFI_STAT_OK) ?
0 : 1;
} }
/** /**
...@@ -985,7 +986,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, ...@@ -985,7 +986,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
* Prepare and issue the abort frame * Prepare and issue the abort frame
*/ */
abort_fr->cmd = MFI_CMD_ABORT; abort_fr->cmd = MFI_CMD_ABORT;
abort_fr->cmd_status = 0xFF; abort_fr->cmd_status = MFI_STAT_INVALID_STATUS;
abort_fr->flags = cpu_to_le16(0); abort_fr->flags = cpu_to_le16(0);
abort_fr->abort_context = cpu_to_le32(cmd_to_abort->index); abort_fr->abort_context = cpu_to_le32(cmd_to_abort->index);
abort_fr->abort_mfi_phys_addr_lo = abort_fr->abort_mfi_phys_addr_lo =
...@@ -994,13 +995,13 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, ...@@ -994,13 +995,13 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr)); cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr));
cmd->sync_cmd = 1; cmd->sync_cmd = 1;
cmd->cmd_status = ENODATA; cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
instance->instancet->issue_dcmd(instance, cmd); instance->instancet->issue_dcmd(instance, cmd);
if (timeout) { if (timeout) {
ret = wait_event_timeout(instance->abort_cmd_wait_q, ret = wait_event_timeout(instance->abort_cmd_wait_q,
cmd->cmd_status != ENODATA, timeout * HZ); cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ);
if (!ret) { if (!ret) {
dev_err(&instance->pdev->dev, "Command timedout" dev_err(&instance->pdev->dev, "Command timedout"
"from %s\n", __func__); "from %s\n", __func__);
...@@ -1008,7 +1009,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, ...@@ -1008,7 +1009,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
} }
} else } else
wait_event(instance->abort_cmd_wait_q, wait_event(instance->abort_cmd_wait_q,
cmd->cmd_status != ENODATA); cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS);
cmd->sync_cmd = 0; cmd->sync_cmd = 0;
...@@ -1909,7 +1910,7 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance, ...@@ -1909,7 +1910,7 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance,
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd = MFI_CMD_DCMD;
dcmd->cmd_status = 0xFF; dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
dcmd->sge_count = 1; dcmd->sge_count = 1;
dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_BOTH); dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_BOTH);
dcmd->timeout = 0; dcmd->timeout = 0;
...@@ -2022,7 +2023,7 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance, ...@@ -2022,7 +2023,7 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance,
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd = MFI_CMD_DCMD;
dcmd->cmd_status = 0xFF; dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
dcmd->sge_count = 1; dcmd->sge_count = 1;
dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_BOTH); dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_BOTH);
dcmd->timeout = 0; dcmd->timeout = 0;
...@@ -2189,7 +2190,7 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance, ...@@ -2189,7 +2190,7 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
dcmd->mbox.s[0] = cpu_to_le16(sizeof(struct MR_CTRL_HB_HOST_MEM)); dcmd->mbox.s[0] = cpu_to_le16(sizeof(struct MR_CTRL_HB_HOST_MEM));
dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd = MFI_CMD_DCMD;
dcmd->cmd_status = 0xFF; dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
dcmd->sge_count = 1; dcmd->sge_count = 1;
dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_BOTH); dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_BOTH);
dcmd->timeout = 0; dcmd->timeout = 0;
...@@ -2209,21 +2210,11 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance, ...@@ -2209,21 +2210,11 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
retval = megasas_issue_polled(instance, cmd); retval = megasas_issue_polled(instance, cmd);
if (retval) { if (retval) {
printk(KERN_WARNING "megasas: SR-IOV: MR_DCMD_CTRL_SHARED_HOST" dev_warn(&instance->pdev->dev, "SR-IOV: MR_DCMD_CTRL_SHARED_HOST"
"_MEM_ALLOC DCMD timed out for scsi%d\n", "_MEM_ALLOC DCMD %s for scsi%d\n",
instance->host->host_no); (dcmd->cmd_status == MFI_STAT_INVALID_STATUS) ?
retval = 1; "timed out" : "failed", instance->host->host_no);
goto out;
}
if (dcmd->cmd_status) {
printk(KERN_WARNING "megasas: SR-IOV: MR_DCMD_CTRL_SHARED_HOST"
"_MEM_ALLOC DCMD failed with status 0x%x for scsi%d\n",
dcmd->cmd_status,
instance->host->host_no);
retval = 1; retval = 1;
goto out;
} }
out: out:
...@@ -2319,7 +2310,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) ...@@ -2319,7 +2310,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
"reset queue\n", "reset queue\n",
reset_cmd); reset_cmd);
reset_cmd->cmd_status = ENODATA; reset_cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
instance->instancet->fire_cmd(instance, instance->instancet->fire_cmd(instance,
reset_cmd->frame_phys_addr, reset_cmd->frame_phys_addr,
0, instance->reg_set); 0, instance->reg_set);
...@@ -2798,11 +2789,7 @@ static void ...@@ -2798,11 +2789,7 @@ static void
megasas_complete_int_cmd(struct megasas_instance *instance, megasas_complete_int_cmd(struct megasas_instance *instance,
struct megasas_cmd *cmd) struct megasas_cmd *cmd)
{ {
cmd->cmd_status = cmd->frame->io.cmd_status; cmd->cmd_status_drv = cmd->frame->io.cmd_status;
if (cmd->cmd_status == ENODATA) {
cmd->cmd_status = 0;
}
wake_up(&instance->int_cmd_wait_q); wake_up(&instance->int_cmd_wait_q);
} }
...@@ -2821,7 +2808,7 @@ megasas_complete_abort(struct megasas_instance *instance, ...@@ -2821,7 +2808,7 @@ megasas_complete_abort(struct megasas_instance *instance,
{ {
if (cmd->sync_cmd) { if (cmd->sync_cmd) {
cmd->sync_cmd = 0; cmd->sync_cmd = 0;
cmd->cmd_status = 0; cmd->cmd_status_drv = 0;
wake_up(&instance->abort_cmd_wait_q); wake_up(&instance->abort_cmd_wait_q);
} }
...@@ -3067,7 +3054,7 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance) ...@@ -3067,7 +3054,7 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance)
printk(KERN_NOTICE "megasas: %p synchronous cmd" printk(KERN_NOTICE "megasas: %p synchronous cmd"
"on the internal reset queue," "on the internal reset queue,"
"issue it again.\n", cmd); "issue it again.\n", cmd);
cmd->cmd_status = ENODATA; cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
instance->instancet->fire_cmd(instance, instance->instancet->fire_cmd(instance,
cmd->frame_phys_addr , cmd->frame_phys_addr ,
0, instance->reg_set); 0, instance->reg_set);
...@@ -3807,7 +3794,7 @@ megasas_get_pd_list(struct megasas_instance *instance) ...@@ -3807,7 +3794,7 @@ megasas_get_pd_list(struct megasas_instance *instance)
dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST; dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
dcmd->mbox.b[1] = 0; dcmd->mbox.b[1] = 0;
dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd = MFI_CMD_DCMD;
dcmd->cmd_status = 0xFF; dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
dcmd->sge_count = 1; dcmd->sge_count = 1;
dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
dcmd->timeout = 0; dcmd->timeout = 0;
...@@ -3903,7 +3890,7 @@ megasas_get_ld_list(struct megasas_instance *instance) ...@@ -3903,7 +3890,7 @@ megasas_get_ld_list(struct megasas_instance *instance)
if (instance->supportmax256vd) if (instance->supportmax256vd)
dcmd->mbox.b[0] = 1; dcmd->mbox.b[0] = 1;
dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd = MFI_CMD_DCMD;
dcmd->cmd_status = 0xFF; dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
dcmd->sge_count = 1; dcmd->sge_count = 1;
dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
dcmd->timeout = 0; dcmd->timeout = 0;
...@@ -3992,7 +3979,7 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type) ...@@ -3992,7 +3979,7 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
dcmd->mbox.b[2] = 1; dcmd->mbox.b[2] = 1;
dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd = MFI_CMD_DCMD;
dcmd->cmd_status = 0xFF; dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
dcmd->sge_count = 1; dcmd->sge_count = 1;
dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
dcmd->timeout = 0; dcmd->timeout = 0;
...@@ -4125,7 +4112,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance) ...@@ -4125,7 +4112,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance)
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd = MFI_CMD_DCMD;
dcmd->cmd_status = 0xFF; dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
dcmd->sge_count = 1; dcmd->sge_count = 1;
dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ); dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
dcmd->timeout = 0; dcmd->timeout = 0;
...@@ -4197,7 +4184,7 @@ int megasas_set_crash_dump_params(struct megasas_instance *instance, ...@@ -4197,7 +4184,7 @@ int megasas_set_crash_dump_params(struct megasas_instance *instance,
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
dcmd->mbox.b[0] = crash_buf_state; dcmd->mbox.b[0] = crash_buf_state;
dcmd->cmd = MFI_CMD_DCMD; dcmd->cmd = MFI_CMD_DCMD;
dcmd->cmd_status = 0xFF; dcmd->cmd_status = MFI_STAT_INVALID_STATUS;
dcmd->sge_count = 1; dcmd->sge_count = 1;
dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_NONE); dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_NONE);
dcmd->timeout = 0; dcmd->timeout = 0;
...@@ -4264,7 +4251,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance) ...@@ -4264,7 +4251,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
initq_info->consumer_index_phys_addr_lo = cpu_to_le32(instance->consumer_h); initq_info->consumer_index_phys_addr_lo = cpu_to_le32(instance->consumer_h);
init_frame->cmd = MFI_CMD_INIT; init_frame->cmd = MFI_CMD_INIT;
init_frame->cmd_status = 0xFF; init_frame->cmd_status = MFI_STAT_INVALID_STATUS;
init_frame->queue_info_new_phys_addr_lo = init_frame->queue_info_new_phys_addr_lo =
cpu_to_le32(lower_32_bits(initq_info_h)); cpu_to_le32(lower_32_bits(initq_info_h));
init_frame->queue_info_new_phys_addr_hi = init_frame->queue_info_new_phys_addr_hi =
......
...@@ -584,7 +584,8 @@ wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, ...@@ -584,7 +584,8 @@ wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
if (frame_hdr->cmd_status == 0xff) if (frame_hdr->cmd_status == 0xff)
return -ETIME; return -ETIME;
return 0; return (frame_hdr->cmd_status == MFI_STAT_OK) ?
0 : 1;
} }
/** /**
......
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