On 11/22/2021 3:48 PM, Bart Van Assche wrote:
On 11/22/21 3:02 PM, Asutosh Das (asd) wrote:
Current code waits for the already issued requests to complete. It
doesn't issue the yet-to-be issued requests. Wouldn't freezing the
queue issue the requests in the context of scaling_{up/down}?
If yes, I don't think the current code is doing that.
Hi Asutosh,
How about the patch below that preserves most of the existing code for
preparing for clock scaling?
Thanks,
Bart.
Hi Bart,
This looks good to me. Please push a change and I can test it out.
-asd
Subject: [PATCH] scsi: ufs: Optimize the command queueing code
Remove the clock scaling lock from ufshcd_queuecommand() since it is a
performance bottleneck. Instead, use synchronize_rcu_expedited() to wait
for ongoing ufshcd_queuecommand() calls.
Signed-off-by: Bart Van Assche <bvanassche@xxxxxxx>
---
drivers/scsi/ufs/ufshcd.c | 12 +++++++-----
drivers/scsi/ufs/ufshcd.h | 1 +
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d214456bf82..1d929c28efaf 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1196,6 +1196,13 @@ static int ufshcd_clock_scaling_prepare(struct
ufs_hba *hba)
/* let's not get into low power until clock scaling is completed */
ufshcd_hold(hba, false);
+ /*
+ * Wait for ongoing ufshcd_queuecommand() calls. Calling
+ * synchronize_rcu_expedited() instead of synchronize_rcu() reduces
the
+ * waiting time from milliseconds to microseconds.
+ */
+ synchronize_rcu_expedited();
+
out:
return ret;
}
@@ -2699,9 +2706,6 @@ static int ufshcd_queuecommand(struct Scsi_Host
*host, struct scsi_cmnd *cmd)
WARN_ONCE(tag < 0, "Invalid tag %d\n", tag);
- if (!down_read_trylock(&hba->clk_scaling_lock))
- return SCSI_MLQUEUE_HOST_BUSY;
-
/*
* Allows the UFS error handler to wait for prior
ufshcd_queuecommand()
* calls.
@@ -2790,8 +2794,6 @@ static int ufshcd_queuecommand(struct Scsi_Host
*host, struct scsi_cmnd *cmd)
out:
rcu_read_unlock();
- up_read(&hba->clk_scaling_lock);
-
if (ufs_trigger_eh()) {
unsigned long flags;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index c13ae56fbff8..695bede14dac 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -777,6 +777,7 @@ struct ufs_hba_monitor {
* @clk_list_head: UFS host controller clocks list node head
* @pwr_info: holds current power mode
* @max_pwr_info: keeps the device max valid pwm
+ * @clk_scaling_lock: used to serialize device commands and clock scaling
* @desc_size: descriptor sizes reported by device
* @urgent_bkops_lvl: keeps track of urgent bkops level for device
* @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level
for
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
Linux Foundation Collaborative Project