* [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