All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bart Van Assche <bvanassche@acm.org>
To: "Martin K . Petersen" <martin.petersen@oracle.com>
Cc: Jaegeuk Kim <jaegeuk@kernel.org>,
	Adrian Hunter <adrian.hunter@intel.com>,
	linux-scsi@vger.kernel.org, Bart Van Assche <bvanassche@acm.org>,
	"James E.J. Bottomley" <jejb@linux.ibm.com>,
	Bean Huo <beanhuo@micron.com>, Can Guo <cang@codeaurora.org>,
	Avri Altman <avri.altman@wdc.com>,
	Stanley Chu <stanley.chu@mediatek.com>,
	Asutosh Das <asutoshd@codeaurora.org>,
	Keoseong Park <keosung.park@samsung.com>
Subject: [PATCH v2 18/20] scsi: ufs: Optimize the command queueing code
Date: Fri, 19 Nov 2021 11:57:41 -0800	[thread overview]
Message-ID: <20211119195743.2817-19-bvanassche@acm.org> (raw)
In-Reply-To: <20211119195743.2817-1-bvanassche@acm.org>

Remove the clock scaling lock from ufshcd_queuecommand() since it is a
performance bottleneck. Freeze request queues instead of polling the
doorbell registers to wait until pending commands have completed.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 drivers/scsi/ufs/ufshcd.c | 124 +++++++++++++-------------------------
 drivers/scsi/ufs/ufshcd.h |   1 +
 2 files changed, 44 insertions(+), 81 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a6d3f71c6b00..9cf4a22f1950 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1070,65 +1070,6 @@ static bool ufshcd_is_devfreq_scaling_required(struct ufs_hba *hba,
 	return false;
 }
 
-static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba,
-					u64 wait_timeout_us)
-{
-	unsigned long flags;
-	int ret = 0;
-	u32 tm_doorbell;
-	u32 tr_doorbell;
-	bool timeout = false, do_last_check = false;
-	ktime_t start;
-
-	ufshcd_hold(hba, false);
-	spin_lock_irqsave(hba->host->host_lock, flags);
-	/*
-	 * Wait for all the outstanding tasks/transfer requests.
-	 * Verify by checking the doorbell registers are clear.
-	 */
-	start = ktime_get();
-	do {
-		if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) {
-			ret = -EBUSY;
-			goto out;
-		}
-
-		tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
-		tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
-		if (!tm_doorbell && !tr_doorbell) {
-			timeout = false;
-			break;
-		} else if (do_last_check) {
-			break;
-		}
-
-		spin_unlock_irqrestore(hba->host->host_lock, flags);
-		schedule();
-		if (ktime_to_us(ktime_sub(ktime_get(), start)) >
-		    wait_timeout_us) {
-			timeout = true;
-			/*
-			 * We might have scheduled out for long time so make
-			 * sure to check if doorbells are cleared by this time
-			 * or not.
-			 */
-			do_last_check = true;
-		}
-		spin_lock_irqsave(hba->host->host_lock, flags);
-	} while (tm_doorbell || tr_doorbell);
-
-	if (timeout) {
-		dev_err(hba->dev,
-			"%s: timedout waiting for doorbell to clear (tm=0x%x, tr=0x%x)\n",
-			__func__, tm_doorbell, tr_doorbell);
-		ret = -EBUSY;
-	}
-out:
-	spin_unlock_irqrestore(hba->host->host_lock, flags);
-	ufshcd_release(hba);
-	return ret;
-}
-
 /**
  * ufshcd_scale_gear - scale up/down UFS gear
  * @hba: per adapter instance
@@ -1176,37 +1117,63 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up)
 
 static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
 {
-	#define DOORBELL_CLR_TOUT_US		(1000 * 1000) /* 1 sec */
-	int ret = 0;
+	struct scsi_device *sdev;
+
 	/*
-	 * make sure that there are no outstanding requests when
-	 * clock scaling is in progress
+	 * Make sure that no commands are in progress while the clock frequency
+	 * is being modified.
+	 *
+	 * Since ufshcd_exec_dev_cmd() and ufshcd_issue_devman_upiu_cmd() lock
+	 * the clk_scaling_lock before calling blk_get_request(), lock
+	 * clk_scaling_lock before freezing the request queues to prevent lock
+	 * inversion.
 	 */
-	ufshcd_scsi_block_requests(hba);
 	down_write(&hba->clk_scaling_lock);
-
-	if (!hba->clk_scaling.is_allowed ||
-	    ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) {
-		ret = -EBUSY;
-		up_write(&hba->clk_scaling_lock);
-		ufshcd_scsi_unblock_requests(hba);
-		goto out;
-	}
-
+	if (!hba->clk_scaling.is_allowed)
+		goto busy;
+	blk_freeze_queue_start(hba->tmf_queue);
+	blk_freeze_queue_start(hba->cmd_queue);
+	shost_for_each_device(sdev, hba->host)
+		blk_freeze_queue_start(sdev->request_queue);
+	/*
+	 * Calling synchronize_rcu_expedited() reduces the time required to
+	 * freeze request queues from milliseconds to microseconds.
+	 */
+	synchronize_rcu_expedited();
+	shost_for_each_device(sdev, hba->host)
+		if (blk_mq_freeze_queue_wait_timeout(sdev->request_queue, HZ)
+		    <= 0)
+			goto unfreeze;
+	if (blk_mq_freeze_queue_wait_timeout(hba->cmd_queue, HZ) <= 0 ||
+	    blk_mq_freeze_queue_wait_timeout(hba->tmf_queue, HZ / 10) <= 0)
+		goto unfreeze;
 	/* let's not get into low power until clock scaling is completed */
 	ufshcd_hold(hba, false);
+	return 0;
 
-out:
-	return ret;
+unfreeze:
+	shost_for_each_device(sdev, hba->host)
+		blk_mq_unfreeze_queue(sdev->request_queue);
+	blk_mq_unfreeze_queue(hba->cmd_queue);
+	blk_mq_unfreeze_queue(hba->tmf_queue);
+
+busy:
+	up_write(&hba->clk_scaling_lock);
+	return -EBUSY;
 }
 
 static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, bool writelock)
 {
+	struct scsi_device *sdev;
+
+	shost_for_each_device(sdev, hba->host)
+		blk_mq_unfreeze_queue(sdev->request_queue);
+	blk_mq_unfreeze_queue(hba->cmd_queue);
+	blk_mq_unfreeze_queue(hba->tmf_queue);
 	if (writelock)
 		up_write(&hba->clk_scaling_lock);
 	else
 		up_read(&hba->clk_scaling_lock);
-	ufshcd_scsi_unblock_requests(hba);
 	ufshcd_release(hba);
 }
 
@@ -2699,9 +2666,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 +2754,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 e9bc07c69a80..7ec463c97d64 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -778,6 +778,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

  parent reply	other threads:[~2021-11-19 19:58 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-19 19:57 [PATCH v2 00/20] UFS patches for kernel v5.17 Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 01/20] block: Add a flag for internal commands Bart Van Assche
2021-11-22  8:46   ` John Garry
2021-11-22 17:38     ` Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 02/20] scsi: core: Unexport scsi_track_queue_full() Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 03/20] scsi: core: Fix scsi_device_max_queue_depth() Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 04/20] scsi: core: Fix a race between scsi_done() and scsi_times_out() Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 05/20] scsi: core: Add support for internal commands Bart Van Assche
2021-11-22  8:58   ` John Garry
2021-11-22 17:46     ` Bart Van Assche
2021-11-22 18:08       ` John Garry
2021-11-22 19:04       ` Bart Van Assche
2021-11-23  8:13       ` Hannes Reinecke
2021-11-23 17:46         ` Bart Van Assche
2021-11-23 19:18           ` Bart Van Assche
2021-11-24  6:33             ` Hannes Reinecke
2021-11-19 19:57 ` [PATCH v2 06/20] scsi: core: Add support for reserved tags Bart Van Assche
2021-11-22  8:15   ` John Garry
2021-11-22 17:25     ` Bart Van Assche
2021-11-22 18:13       ` John Garry
2021-11-19 19:57 ` [PATCH v2 07/20] scsi: ufs: Rename a function argument Bart Van Assche
2021-11-22 20:25   ` Bean Huo
2021-11-19 19:57 ` [PATCH v2 08/20] scsi: ufs: Remove is_rpmb_wlun() Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 09/20] scsi: ufs: Remove the sdev_rpmb member Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 10/20] scsi: ufs: Remove dead code Bart Van Assche
2021-11-24 11:11   ` Adrian Hunter
2021-11-29 19:12     ` Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 11/20] scsi: ufs: Switch to scsi_(get|put)_internal_cmd() Bart Van Assche
2021-11-23 12:20   ` Bean Huo
2021-11-23 17:54     ` Bart Van Assche
2021-11-23 19:41     ` Bart Van Assche
2021-11-24 18:18       ` Bean Huo
2021-11-24 11:02   ` Adrian Hunter
2021-11-24 11:15     ` Adrian Hunter
2021-11-29 19:32     ` Bart Van Assche
2021-11-30  6:41       ` Adrian Hunter
2021-11-30 17:51         ` Bart Van Assche
2021-11-30 19:15           ` Adrian Hunter
2021-11-30 19:21             ` Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 12/20] scsi: ufs: Rework ufshcd_change_queue_depth() Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 13/20] scsi: ufs: Fix a deadlock in the error handler Bart Van Assche
2021-11-30  8:54   ` Bean Huo
2021-11-30 17:52     ` Bart Van Assche
2021-11-30 19:32     ` Bart Van Assche
2021-12-01 13:44       ` Bean Huo
2021-12-01 18:31         ` Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 14/20] scsi: ufs: Introduce ufshcd_release_scsi_cmd() Bart Van Assche
2021-11-24 12:03   ` Adrian Hunter
2021-11-30 18:00     ` Bart Van Assche
2021-11-30 19:02       ` Adrian Hunter
2021-11-30 19:16         ` Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 15/20] scsi: ufs: Improve SCSI abort handling Bart Van Assche
2021-11-24 12:28   ` Adrian Hunter
2021-11-30  4:13     ` Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 16/20] scsi: ufs: Fix a kernel crash during shutdown Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 17/20] scsi: ufs: Stop using the clock scaling lock in the error handler Bart Van Assche
2021-11-19 19:57 ` Bart Van Assche [this message]
2021-11-22 17:46   ` [PATCH v2 18/20] scsi: ufs: Optimize the command queueing code Asutosh Das (asd)
2021-11-22 18:13     ` Bart Van Assche
2021-11-22 23:02       ` Asutosh Das (asd)
2021-11-22 23:48         ` Bart Van Assche
2021-11-23 18:24           ` Asutosh Das (asd)
2021-12-01 18:33             ` Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 19/20] scsi: ufs: Implement polling support Bart Van Assche
2021-11-30  8:43   ` Bean Huo
2021-11-30  8:57     ` Avri Altman
2021-11-30  9:15       ` Bean Huo
2021-11-30 14:26     ` Bart Van Assche
2021-11-30 15:40       ` Bean Huo
2021-11-30 17:34         ` Bart Van Assche
2021-11-30 17:37     ` Bart Van Assche
2021-11-19 19:57 ` [PATCH v2 20/20] scsi: ufs: Fix race conditions related to driver data Bart Van Assche

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211119195743.2817-19-bvanassche@acm.org \
    --to=bvanassche@acm.org \
    --cc=adrian.hunter@intel.com \
    --cc=asutoshd@codeaurora.org \
    --cc=avri.altman@wdc.com \
    --cc=beanhuo@micron.com \
    --cc=cang@codeaurora.org \
    --cc=jaegeuk@kernel.org \
    --cc=jejb@linux.ibm.com \
    --cc=keosung.park@samsung.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    --cc=stanley.chu@mediatek.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.