Skip to content

Commit d1a7644

Browse files
bvanasschemartinkpetersen
authored andcommitted
scsi: ufs: Support clearing multiple commands at once
Modify ufshcd_clear_cmd() such that it supports clearing multiple commands at once instead of one command at a time. This change will be used in a later patch to reduce the time spent in the reset handler. Link: https://lore.kernel.org/r/20220613214442.212466-3-bvanassche@acm.org Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> Reviewed-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent da8badd commit d1a7644

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

drivers/ufs/core/ufshcd.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -748,17 +748,28 @@ static enum utp_ocs ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp)
748748
}
749749

750750
/**
751-
* ufshcd_utrl_clear - Clear a bit in UTRLCLR register
751+
* ufshcd_utrl_clear() - Clear requests from the controller request list.
752752
* @hba: per adapter instance
753-
* @pos: position of the bit to be cleared
753+
* @mask: mask with one bit set for each request to be cleared
754754
*/
755-
static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
755+
static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 mask)
756756
{
757757
if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR)
758-
ufshcd_writel(hba, (1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
759-
else
760-
ufshcd_writel(hba, ~(1 << pos),
761-
REG_UTP_TRANSFER_REQ_LIST_CLEAR);
758+
mask = ~mask;
759+
/*
760+
* From the UFSHCI specification: "UTP Transfer Request List CLear
761+
* Register (UTRLCLR): This field is bit significant. Each bit
762+
* corresponds to a slot in the UTP Transfer Request List, where bit 0
763+
* corresponds to request slot 0. A bit in this field is set to ‘0’
764+
* by host software to indicate to the host controller that a transfer
765+
* request slot is cleared. The host controller
766+
* shall free up any resources associated to the request slot
767+
* immediately, and shall set the associated bit in UTRLDBR to ‘0’. The
768+
* host software indicates no change to request slots by setting the
769+
* associated bits in this field to ‘1’. Bits in this field shall only
770+
* be set ‘1’ or ‘0’ by host software when UTRLRSR is set to ‘1’."
771+
*/
772+
ufshcd_writel(hba, ~mask, REG_UTP_TRANSFER_REQ_LIST_CLEAR);
762773
}
763774

764775
/**
@@ -2863,15 +2874,18 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
28632874
return ufshcd_compose_devman_upiu(hba, lrbp);
28642875
}
28652876

2866-
static int
2867-
ufshcd_clear_cmd(struct ufs_hba *hba, int tag)
2877+
/*
2878+
* Clear all the requests from the controller for which a bit has been set in
2879+
* @mask and wait until the controller confirms that these requests have been
2880+
* cleared.
2881+
*/
2882+
static int ufshcd_clear_cmds(struct ufs_hba *hba, u32 mask)
28682883
{
28692884
unsigned long flags;
2870-
u32 mask = 1 << tag;
28712885

28722886
/* clear outstanding transaction before retry */
28732887
spin_lock_irqsave(hba->host->host_lock, flags);
2874-
ufshcd_utrl_clear(hba, tag);
2888+
ufshcd_utrl_clear(hba, mask);
28752889
spin_unlock_irqrestore(hba->host->host_lock, flags);
28762890

28772891
/*
@@ -2959,7 +2973,7 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
29592973
err = -ETIMEDOUT;
29602974
dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
29612975
__func__, lrbp->task_tag);
2962-
if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
2976+
if (!ufshcd_clear_cmds(hba, 1U << lrbp->task_tag))
29632977
/* successfully cleared the command, retry if needed */
29642978
err = -EAGAIN;
29652979
/*
@@ -6982,7 +6996,7 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
69826996
/* clear the commands that were pending for corresponding LUN */
69836997
for_each_set_bit(pos, &hba->outstanding_reqs, hba->nutrs) {
69846998
if (hba->lrb[pos].lun == lun) {
6985-
err = ufshcd_clear_cmd(hba, pos);
6999+
err = ufshcd_clear_cmds(hba, 1U << pos);
69867000
if (err)
69877001
break;
69887002
__ufshcd_transfer_req_compl(hba, 1U << pos);
@@ -7084,7 +7098,7 @@ static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
70847098
goto out;
70857099
}
70867100

7087-
err = ufshcd_clear_cmd(hba, tag);
7101+
err = ufshcd_clear_cmds(hba, 1U << tag);
70887102
if (err)
70897103
dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n",
70907104
__func__, tag, err);

0 commit comments

Comments
 (0)