Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 22a2d56

Browse files
Asutosh Dasmartinkpetersen
authored andcommitted
scsi: ufs: core: Prepare ufshcd_send_command() for MCQ
Add support to send commands using multiple submission queues in MCQ mode. Modify the functions that use ufshcd_send_command(). Co-developed-by: Can Guo <[email protected]> Signed-off-by: Can Guo <[email protected]> Signed-off-by: Asutosh Das <[email protected]> Reviewed-by: Bart Van Assche <[email protected]> Reviewed-by: Manivannan Sadhasivam <[email protected]> Reviewed-by: Stanley Chu <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 0d33728 commit 22a2d56

File tree

4 files changed

+43
-11
lines changed

4 files changed

+43
-11
lines changed

drivers/ufs/core/ufs-mcq.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ int ufshcd_mcq_init(struct ufs_hba *hba)
309309
for (i = 0; i < hba->nr_hw_queues; i++) {
310310
hwq = &hba->uhq[i];
311311
hwq->max_entries = hba->nutrs;
312+
spin_lock_init(&hwq->sq_lock);
312313
}
313314

314315
/* The very first HW queue serves device commands */

drivers/ufs/core/ufshcd-priv.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,14 @@ static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info, u8
335335
return lun == UFS_UPIU_RPMB_WLUN || (lun < dev_info->max_lu_supported);
336336
}
337337

338+
static inline void ufshcd_inc_sq_tail(struct ufs_hw_queue *q)
339+
{
340+
u32 mask = q->max_entries - 1;
341+
u32 val;
342+
343+
q->sq_tail_slot = (q->sq_tail_slot + 1) & mask;
344+
val = q->sq_tail_slot * sizeof(struct utp_transfer_req_desc);
345+
writel(val, q->mcq_sq_tail);
346+
}
347+
338348
#endif /* _UFSHCD_PRIV_H_ */

drivers/ufs/core/ufshcd.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,9 +2185,11 @@ static void ufshcd_update_monitor(struct ufs_hba *hba, const struct ufshcd_lrb *
21852185
* ufshcd_send_command - Send SCSI or device management commands
21862186
* @hba: per adapter instance
21872187
* @task_tag: Task tag of the command
2188+
* @hwq: pointer to hardware queue instance
21882189
*/
21892190
static inline
2190-
void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
2191+
void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag,
2192+
struct ufs_hw_queue *hwq)
21912193
{
21922194
struct ufshcd_lrb *lrbp = &hba->lrb[task_tag];
21932195
unsigned long flags;
@@ -2201,12 +2203,24 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
22012203
if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
22022204
ufshcd_start_monitor(hba, lrbp);
22032205

2204-
spin_lock_irqsave(&hba->outstanding_lock, flags);
2205-
if (hba->vops && hba->vops->setup_xfer_req)
2206-
hba->vops->setup_xfer_req(hba, task_tag, !!lrbp->cmd);
2207-
__set_bit(task_tag, &hba->outstanding_reqs);
2208-
ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
2209-
spin_unlock_irqrestore(&hba->outstanding_lock, flags);
2206+
if (is_mcq_enabled(hba)) {
2207+
int utrd_size = sizeof(struct utp_transfer_req_desc);
2208+
2209+
spin_lock(&hwq->sq_lock);
2210+
memcpy(hwq->sqe_base_addr + (hwq->sq_tail_slot * utrd_size),
2211+
lrbp->utr_descriptor_ptr, utrd_size);
2212+
ufshcd_inc_sq_tail(hwq);
2213+
spin_unlock(&hwq->sq_lock);
2214+
} else {
2215+
spin_lock_irqsave(&hba->outstanding_lock, flags);
2216+
if (hba->vops && hba->vops->setup_xfer_req)
2217+
hba->vops->setup_xfer_req(hba, lrbp->task_tag,
2218+
!!lrbp->cmd);
2219+
__set_bit(lrbp->task_tag, &hba->outstanding_reqs);
2220+
ufshcd_writel(hba, 1 << lrbp->task_tag,
2221+
REG_UTP_TRANSFER_REQ_DOOR_BELL);
2222+
spin_unlock_irqrestore(&hba->outstanding_lock, flags);
2223+
}
22102224
}
22112225

22122226
/**
@@ -2836,6 +2850,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
28362850
int tag = scsi_cmd_to_rq(cmd)->tag;
28372851
struct ufshcd_lrb *lrbp;
28382852
int err = 0;
2853+
struct ufs_hw_queue *hwq = NULL;
28392854

28402855
WARN_ONCE(tag < 0 || tag >= hba->nutrs, "Invalid tag %d\n", tag);
28412856

@@ -2920,7 +2935,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
29202935
goto out;
29212936
}
29222937

2923-
ufshcd_send_command(hba, tag);
2938+
ufshcd_send_command(hba, tag, hwq);
29242939

29252940
out:
29262941
rcu_read_unlock();
@@ -3121,10 +3136,11 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
31213136
goto out;
31223137

31233138
hba->dev_cmd.complete = &wait;
3139+
hba->dev_cmd.cqe = NULL;
31243140

31253141
ufshcd_add_query_upiu_trace(hba, UFS_QUERY_SEND, lrbp->ucd_req_ptr);
31263142

3127-
ufshcd_send_command(hba, tag);
3143+
ufshcd_send_command(hba, tag, hba->dev_cmd_queue);
31283144
err = ufshcd_wait_for_dev_cmd(hba, lrbp, timeout);
31293145
ufshcd_add_query_upiu_trace(hba, err ? UFS_QUERY_ERR : UFS_QUERY_COMP,
31303146
(struct utp_upiu_req *)lrbp->ucd_rsp_ptr);
@@ -6938,7 +6954,7 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
69386954

69396955
ufshcd_add_query_upiu_trace(hba, UFS_QUERY_SEND, lrbp->ucd_req_ptr);
69406956

6941-
ufshcd_send_command(hba, tag);
6957+
ufshcd_send_command(hba, tag, hba->dev_cmd_queue);
69426958
/*
69436959
* ignore the returning value here - ufshcd_check_query_response is
69446960
* bound to fail since dev_cmd.query and dev_cmd.type were left empty.
@@ -7104,7 +7120,7 @@ int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *r
71047120

71057121
hba->dev_cmd.complete = &wait;
71067122

7107-
ufshcd_send_command(hba, tag);
7123+
ufshcd_send_command(hba, tag, hba->dev_cmd_queue);
71087124

71097125
err = ufshcd_wait_for_dev_cmd(hba, lrbp, ADVANCED_RPMB_REQ_TIMEOUT);
71107126

include/ufs/ufshcd.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ struct ufs_dev_cmd {
224224
struct mutex lock;
225225
struct completion *complete;
226226
struct ufs_query query;
227+
struct cq_entry *cqe;
227228
};
228229

229230
/**
@@ -1078,6 +1079,8 @@ struct ufs_hba {
10781079
* @cqe_dma_addr: completion queue dma address
10791080
* @max_entries: max number of slots in this hardware queue
10801081
* @id: hardware queue ID
1082+
* @sq_tp_slot: current slot to which SQ tail pointer is pointing
1083+
* @sq_lock: serialize submission queue access
10811084
*/
10821085
struct ufs_hw_queue {
10831086
void __iomem *mcq_sq_head;
@@ -1091,6 +1094,8 @@ struct ufs_hw_queue {
10911094
dma_addr_t cqe_dma_addr;
10921095
u32 max_entries;
10931096
u32 id;
1097+
u32 sq_tail_slot;
1098+
spinlock_t sq_lock;
10941099
};
10951100

10961101
static inline bool is_mcq_enabled(struct ufs_hba *hba)

0 commit comments

Comments
 (0)