Skip to content

Commit 0fef6bb

Browse files
Stanley Chumartinkpetersen
authored andcommitted
scsi: ufs: core: mcq: Fix the incorrect OCS value for the device command
In MCQ mode, when a device command uses a hardware queue shared with other commands, a race condition may occur in the following scenario: 1. A device command is completed in CQx with CQE entry "e". 2. The interrupt handler copies the "cqe" pointer to "hba->dev_cmd.cqe" and completes "hba->dev_cmd.complete". 3. The "ufshcd_wait_for_dev_cmd()" function is awakened and retrieves the OCS value from "hba->dev_cmd.cqe". However, there is a possibility that the CQE entry "e" will be overwritten by newly completed commands in CQx, resulting in an incorrect OCS value being received by "ufshcd_wait_for_dev_cmd()". To avoid this race condition, the OCS value should be immediately copied to the struct "lrb" of the device command. Then "ufshcd_wait_for_dev_cmd()" can retrieve the OCS value from the struct "lrb". Fixes: 57b1c0e ("scsi: ufs: core: mcq: Add support to allocate multiple queues") Suggested-by: Can Guo <[email protected]> Signed-off-by: Stanley Chu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Tested-by: Po-Wen Kao <[email protected]> Reviewed-by: Bart Van Assche <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent e246514 commit 0fef6bb

File tree

2 files changed

+7
-4
lines changed

2 files changed

+7
-4
lines changed

drivers/ufs/core/ufshcd.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,7 +3086,7 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
30863086
* not trigger any race conditions.
30873087
*/
30883088
hba->dev_cmd.complete = NULL;
3089-
err = ufshcd_get_tr_ocs(lrbp, hba->dev_cmd.cqe);
3089+
err = ufshcd_get_tr_ocs(lrbp, NULL);
30903090
if (!err)
30913091
err = ufshcd_dev_cmd_completion(hba, lrbp);
30923092
} else {
@@ -3182,7 +3182,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
31823182
goto out;
31833183

31843184
hba->dev_cmd.complete = &wait;
3185-
hba->dev_cmd.cqe = NULL;
31863185

31873186
ufshcd_add_query_upiu_trace(hba, UFS_QUERY_SEND, lrbp->ucd_req_ptr);
31883187

@@ -5431,6 +5430,7 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
54315430
{
54325431
struct ufshcd_lrb *lrbp;
54335432
struct scsi_cmnd *cmd;
5433+
enum utp_ocs ocs;
54345434

54355435
lrbp = &hba->lrb[task_tag];
54365436
lrbp->compl_time_stamp = ktime_get();
@@ -5446,7 +5446,11 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
54465446
} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE ||
54475447
lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) {
54485448
if (hba->dev_cmd.complete) {
5449-
hba->dev_cmd.cqe = cqe;
5449+
if (cqe) {
5450+
ocs = le32_to_cpu(cqe->status) & MASK_OCS;
5451+
lrbp->utr_descriptor_ptr->header.dword_2 =
5452+
cpu_to_le32(ocs);
5453+
}
54505454
complete(hba->dev_cmd.complete);
54515455
ufshcd_clk_scaling_update_busy(hba);
54525456
}

include/ufs/ufshcd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ struct ufs_dev_cmd {
225225
struct mutex lock;
226226
struct completion *complete;
227227
struct ufs_query query;
228-
struct cq_entry *cqe;
229228
};
230229

231230
/**

0 commit comments

Comments
 (0)