linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy
@ 2021-07-02 13:42 Ulf Hansson
  2021-07-02 13:42 ` [PATCH 1/3] mmc: core: Avoid hogging the CPU while polling for busy in the I/O err path Ulf Hansson
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Ulf Hansson @ 2021-07-02 13:42 UTC (permalink / raw)
  To: linux-mmc, Ulf Hansson
  Cc: Adrian Hunter, Linus Walleij, Wolfram Sang, Shawn Lin,
	Christian Lohle, linux-kernel

Step by step, code that have been dealing sending CMD13 to poll the card for
busy, have been moved to use the common mmc_poll_for_busy() loop. This helps to
avoid hogging the CPU, for example, as it inserts a small delay in between each
polling attempt. Additionally, it avoids open coding.

This series takes the next and final step, by moving the mmc block device layer
from its own busy polling loop, into using the common code.

Please test and review!

Kind regards
Uffe

Ulf Hansson (3):
  mmc: core: Avoid hogging the CPU while polling for busy in the I/O err
    path
  mmc: core: Avoid hogging the CPU while polling for busy for mmc ioctls
  mmc: core: Avoid hogging the CPU while polling for busy after I/O
    writes

 drivers/mmc/core/block.c   | 74 +++++++++++++++++---------------------
 drivers/mmc/core/mmc_ops.c |  5 ++-
 drivers/mmc/core/mmc_ops.h |  1 +
 3 files changed, 37 insertions(+), 43 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] mmc: core: Avoid hogging the CPU while polling for busy in the I/O err path
  2021-07-02 13:42 [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy Ulf Hansson
@ 2021-07-02 13:42 ` Ulf Hansson
  2021-07-02 13:42 ` [PATCH 2/3] mmc: core: Avoid hogging the CPU while polling for busy for mmc ioctls Ulf Hansson
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Ulf Hansson @ 2021-07-02 13:42 UTC (permalink / raw)
  To: linux-mmc, Ulf Hansson
  Cc: Adrian Hunter, Linus Walleij, Wolfram Sang, Shawn Lin,
	Christian Lohle, linux-kernel

When mmc_blk_fix_state() sends a CMD12 to try to move the card into the
transfer state, it calls card_busy_detect() to poll for the card's state
with CMD13. This is done without any delays in between the commands being
sent.

Rather than fixing card_busy_detect() in this regards, let's instead
convert into using the common mmc_poll_for_busy(), which also helps us to
avoid open-coding.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/mmc/core/block.c   | 2 +-
 drivers/mmc/core/mmc_ops.c | 4 +++-
 drivers/mmc/core/mmc_ops.h | 1 +
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 88f4c215caa6..1b5576048cdb 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -1630,7 +1630,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req)
 
 	mmc_blk_send_stop(card, timeout);
 
-	err = card_busy_detect(card, timeout, NULL);
+	err = mmc_poll_for_busy(card, timeout, false, MMC_BUSY_IO);
 
 	mmc_retune_release(card->host);
 
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 973756ed4016..e2c431c0ce5d 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -435,7 +435,7 @@ static int mmc_busy_cb(void *cb_data, bool *busy)
 	u32 status = 0;
 	int err;
 
-	if (host->ops->card_busy) {
+	if (data->busy_cmd != MMC_BUSY_IO && host->ops->card_busy) {
 		*busy = host->ops->card_busy(host);
 		return 0;
 	}
@@ -457,6 +457,7 @@ static int mmc_busy_cb(void *cb_data, bool *busy)
 		break;
 	case MMC_BUSY_HPI:
 	case MMC_BUSY_EXTR_SINGLE:
+	case MMC_BUSY_IO:
 		break;
 	default:
 		err = -EINVAL;
@@ -521,6 +522,7 @@ int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
 
 	return __mmc_poll_for_busy(card, timeout_ms, &mmc_busy_cb, &cb_data);
 }
+EXPORT_SYMBOL_GPL(mmc_poll_for_busy);
 
 bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd,
 			  unsigned int timeout_ms)
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 41ab4f573a31..ae25ffc2e870 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -15,6 +15,7 @@ enum mmc_busy_cmd {
 	MMC_BUSY_ERASE,
 	MMC_BUSY_HPI,
 	MMC_BUSY_EXTR_SINGLE,
+	MMC_BUSY_IO,
 };
 
 struct mmc_host;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] mmc: core: Avoid hogging the CPU while polling for busy for mmc ioctls
  2021-07-02 13:42 [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy Ulf Hansson
  2021-07-02 13:42 ` [PATCH 1/3] mmc: core: Avoid hogging the CPU while polling for busy in the I/O err path Ulf Hansson
@ 2021-07-02 13:42 ` Ulf Hansson
  2021-07-02 13:42 ` [PATCH 3/3] mmc: core: Avoid hogging the CPU while polling for busy after I/O writes Ulf Hansson
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Ulf Hansson @ 2021-07-02 13:42 UTC (permalink / raw)
  To: linux-mmc, Ulf Hansson
  Cc: Adrian Hunter, Linus Walleij, Wolfram Sang, Shawn Lin,
	Christian Lohle, linux-kernel

When __mmc_blk_ioctl_cmd() calls card_busy_detect() to verify that the
card's states moves back into transfer state, the polling with CMD13 is
done without any delays in between the commands being sent.

Rather than fixing card_busy_detect() in this regards, let's instead
convert into using the common mmc_poll_for_busy(), which also helps us to
avoid open-coding.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/mmc/core/block.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 1b5576048cdb..0f9044cf3aab 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -599,7 +599,8 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
 		 * Ensure RPMB/R1B command has completed by polling CMD13
 		 * "Send Status".
 		 */
-		err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
+		err = mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, false,
+					MMC_BUSY_IO);
 	}
 
 	return err;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] mmc: core: Avoid hogging the CPU while polling for busy after I/O writes
  2021-07-02 13:42 [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy Ulf Hansson
  2021-07-02 13:42 ` [PATCH 1/3] mmc: core: Avoid hogging the CPU while polling for busy in the I/O err path Ulf Hansson
  2021-07-02 13:42 ` [PATCH 2/3] mmc: core: Avoid hogging the CPU while polling for busy for mmc ioctls Ulf Hansson
@ 2021-07-02 13:42 ` Ulf Hansson
  2021-07-06  7:05 ` [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy Shawn Lin
  2021-08-04 11:34 ` Ulf Hansson
  4 siblings, 0 replies; 6+ messages in thread
From: Ulf Hansson @ 2021-07-02 13:42 UTC (permalink / raw)
  To: linux-mmc, Ulf Hansson
  Cc: Adrian Hunter, Linus Walleij, Wolfram Sang, Shawn Lin,
	Christian Lohle, linux-kernel

When mmc_blk_card_busy() calls card_busy_detect() to poll for the card's
state with CMD13, this is done without any delays in between the commands
being sent.

Rather than fixing card_busy_detect() in this regards, let's instead
convert into using the common __mmc_poll_for_busy(), which also helps us to
avoid open-coding.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/mmc/core/block.c   | 69 ++++++++++++++++----------------------
 drivers/mmc/core/mmc_ops.c |  1 +
 2 files changed, 30 insertions(+), 40 deletions(-)

diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 0f9044cf3aab..c692f2af77f2 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -97,6 +97,11 @@ static int max_devices;
 static DEFINE_IDA(mmc_blk_ida);
 static DEFINE_IDA(mmc_rpmb_ida);
 
+struct mmc_blk_busy_data {
+	struct mmc_card *card;
+	u32 status;
+};
+
 /*
  * There is one mmc_blk_data per slot.
  */
@@ -411,42 +416,6 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
 	return 0;
 }
 
-static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
-			    u32 *resp_errs)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
-	int err = 0;
-	u32 status;
-
-	do {
-		bool done = time_after(jiffies, timeout);
-
-		err = __mmc_send_status(card, &status, 5);
-		if (err) {
-			dev_err(mmc_dev(card->host),
-				"error %d requesting status\n", err);
-			return err;
-		}
-
-		/* Accumulate any response error bits seen */
-		if (resp_errs)
-			*resp_errs |= status;
-
-		/*
-		 * Timeout if the device never becomes ready for data and never
-		 * leaves the program state.
-		 */
-		if (done) {
-			dev_err(mmc_dev(card->host),
-				"Card stuck in wrong state! %s status: %#x\n",
-				 __func__, status);
-			return -ETIMEDOUT;
-		}
-	} while (!mmc_ready_for_data(status));
-
-	return err;
-}
-
 static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
 			       struct mmc_blk_ioc_data *idata)
 {
@@ -1846,28 +1815,48 @@ static inline bool mmc_blk_rq_error(struct mmc_blk_request *brq)
 	       brq->data.error || brq->cmd.resp[0] & CMD_ERRORS;
 }
 
+static int mmc_blk_busy_cb(void *cb_data, bool *busy)
+{
+	struct mmc_blk_busy_data *data = cb_data;
+	u32 status = 0;
+	int err;
+
+	err = mmc_send_status(data->card, &status);
+	if (err)
+		return err;
+
+	/* Accumulate response error bits. */
+	data->status |= status;
+
+	*busy = !mmc_ready_for_data(status);
+	return 0;
+}
+
 static int mmc_blk_card_busy(struct mmc_card *card, struct request *req)
 {
 	struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
-	u32 status = 0;
+	struct mmc_blk_busy_data cb_data;
 	int err;
 
 	if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
 		return 0;
 
-	err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status);
+	cb_data.card = card;
+	cb_data.status = 0;
+	err = __mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, &mmc_blk_busy_cb,
+				  &cb_data);
 
 	/*
 	 * Do not assume data transferred correctly if there are any error bits
 	 * set.
 	 */
-	if (status & mmc_blk_stop_err_bits(&mqrq->brq)) {
+	if (cb_data.status & mmc_blk_stop_err_bits(&mqrq->brq)) {
 		mqrq->brq.data.bytes_xfered = 0;
 		err = err ? err : -EIO;
 	}
 
 	/* Copy the exception bit so it will be seen later on */
-	if (mmc_card_mmc(card) && status & R1_EXCEPTION_EVENT)
+	if (mmc_card_mmc(card) && cb_data.status & R1_EXCEPTION_EVENT)
 		mqrq->brq.cmd.resp[0] |= R1_EXCEPTION_EVENT;
 
 	return err;
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index e2c431c0ce5d..90d213a2203f 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -510,6 +510,7 @@ int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(__mmc_poll_for_busy);
 
 int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
 		      bool retry_crc_err, enum mmc_busy_cmd busy_cmd)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy
  2021-07-02 13:42 [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy Ulf Hansson
                   ` (2 preceding siblings ...)
  2021-07-02 13:42 ` [PATCH 3/3] mmc: core: Avoid hogging the CPU while polling for busy after I/O writes Ulf Hansson
@ 2021-07-06  7:05 ` Shawn Lin
  2021-08-04 11:34 ` Ulf Hansson
  4 siblings, 0 replies; 6+ messages in thread
From: Shawn Lin @ 2021-07-06  7:05 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: shawn.lin, Adrian Hunter, Linus Walleij, Wolfram Sang,
	Christian Lohle, linux-kernel, linux-mmc

On 2021/7/2 21:42, Ulf Hansson wrote:
> Step by step, code that have been dealing sending CMD13 to poll the card for
> busy, have been moved to use the common mmc_poll_for_busy() loop. This helps to
> avoid hogging the CPU, for example, as it inserts a small delay in between each
> polling attempt. Additionally, it avoids open coding.
> 
> This series takes the next and final step, by moving the mmc block device layer
> from its own busy polling loop, into using the common code.
> 
> Please test and review!

Hi Ulf,

This patch-set looks good,

Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>

> 
> Kind regards
> Uffe
> 
> Ulf Hansson (3):
>    mmc: core: Avoid hogging the CPU while polling for busy in the I/O err
>      path
>    mmc: core: Avoid hogging the CPU while polling for busy for mmc ioctls
>    mmc: core: Avoid hogging the CPU while polling for busy after I/O
>      writes
> 
>   drivers/mmc/core/block.c   | 74 +++++++++++++++++---------------------
>   drivers/mmc/core/mmc_ops.c |  5 ++-
>   drivers/mmc/core/mmc_ops.h |  1 +
>   3 files changed, 37 insertions(+), 43 deletions(-)
> 



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy
  2021-07-02 13:42 [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy Ulf Hansson
                   ` (3 preceding siblings ...)
  2021-07-06  7:05 ` [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy Shawn Lin
@ 2021-08-04 11:34 ` Ulf Hansson
  4 siblings, 0 replies; 6+ messages in thread
From: Ulf Hansson @ 2021-08-04 11:34 UTC (permalink / raw)
  To: linux-mmc, Ulf Hansson
  Cc: Adrian Hunter, Linus Walleij, Wolfram Sang, Shawn Lin,
	Christian Lohle, Linux Kernel Mailing List

On Fri, 2 Jul 2021 at 15:42, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> Step by step, code that have been dealing sending CMD13 to poll the card for
> busy, have been moved to use the common mmc_poll_for_busy() loop. This helps to
> avoid hogging the CPU, for example, as it inserts a small delay in between each
> polling attempt. Additionally, it avoids open coding.
>
> This series takes the next and final step, by moving the mmc block device layer
> from its own busy polling loop, into using the common code.
>
> Please test and review!
>
> Kind regards
> Uffe
>
> Ulf Hansson (3):
>   mmc: core: Avoid hogging the CPU while polling for busy in the I/O err
>     path
>   mmc: core: Avoid hogging the CPU while polling for busy for mmc ioctls
>   mmc: core: Avoid hogging the CPU while polling for busy after I/O
>     writes
>
>  drivers/mmc/core/block.c   | 74 +++++++++++++++++---------------------
>  drivers/mmc/core/mmc_ops.c |  5 ++-
>  drivers/mmc/core/mmc_ops.h |  1 +
>  3 files changed, 37 insertions(+), 43 deletions(-)
>

This series has been applied for next. If you encounter any
regressions (performance related as well), please report them!

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-08-04 11:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-02 13:42 [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy Ulf Hansson
2021-07-02 13:42 ` [PATCH 1/3] mmc: core: Avoid hogging the CPU while polling for busy in the I/O err path Ulf Hansson
2021-07-02 13:42 ` [PATCH 2/3] mmc: core: Avoid hogging the CPU while polling for busy for mmc ioctls Ulf Hansson
2021-07-02 13:42 ` [PATCH 3/3] mmc: core: Avoid hogging the CPU while polling for busy after I/O writes Ulf Hansson
2021-07-06  7:05 ` [PATCH 0/3] mmc: core: Avoid hogging the CPU while polling for busy Shawn Lin
2021-08-04 11:34 ` Ulf Hansson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).