diff options
author | Ulf Hansson <ulf.hansson@linaro.org> | 2020-02-04 09:54:47 +0100 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2020-03-24 14:35:40 +0100 |
commit | 490ff95f8e2c89d7541f187bae78d340b20d0ef0 (patch) | |
tree | a967edb18f3d0aab43101892b8f71dd887064d69 /drivers | |
parent | 9f94d04752ad6bf6a704637c61590fe55c4c0d82 (diff) |
mmc: core: Convert to mmc_poll_for_busy() for HPI commands
Rather than open coding the polling loop in mmc_interrupt_hpi(), let's
convert to use mmc_poll_for_busy().
Note that, moving to mmc_poll_for_busy() for HPI also improves the
behaviour according to below.
- Adds support for polling via the optional ->card_busy() host ops.
- Require R1_READY_FOR_DATA to be set in the CMD13 response before exiting
the polling loop.
- Adds a throttling mechanism to avoid CPU hogging when polling.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Baolin Wang <baolin.wang7@gmail.com>
Tested-by: Ludovic Barre <ludovic.barre@st.com>
Reviewed-by: Ludovic Barre <ludovic.barre@st.com>
Link: https://lore.kernel.org/r/20200204085449.32585-11-ulf.hansson@linaro.org
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 20 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.h | 1 |
2 files changed, 6 insertions, 15 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 7d150e68be08..0099f39a60a3 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -471,6 +471,8 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, case MMC_BUSY_ERASE: err = R1_STATUS(status) ? -EIO : 0; break; + case MMC_BUSY_HPI: + break; default: err = -EINVAL; } @@ -831,6 +833,7 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width) static int mmc_send_hpi_cmd(struct mmc_card *card) { + unsigned int busy_timeout_ms = card->ext_csd.out_of_int_time; struct mmc_command cmd = {}; unsigned int opcode; int err; @@ -852,7 +855,8 @@ static int mmc_send_hpi_cmd(struct mmc_card *card) return err; } - return 0; + /* Let's poll to find out when the HPI request completes. */ + return mmc_poll_for_busy(card, busy_timeout_ms, MMC_BUSY_HPI); } /** @@ -866,7 +870,6 @@ int mmc_interrupt_hpi(struct mmc_card *card) { int err; u32 status; - unsigned long prg_wait; if (!card->ext_csd.hpi_en) { pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host)); @@ -900,19 +903,6 @@ int mmc_interrupt_hpi(struct mmc_card *card) } err = mmc_send_hpi_cmd(card); - if (err) - goto out; - - prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time); - do { - err = mmc_send_status(card, &status); - - if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN) - break; - if (time_after(jiffies, prg_wait)) - err = -ETIMEDOUT; - } while (!err); - out: return err; } diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 8cd05fb583da..38dcfeeaf6d5 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -13,6 +13,7 @@ enum mmc_busy_cmd { MMC_BUSY_CMD6, MMC_BUSY_ERASE, + MMC_BUSY_HPI, }; struct mmc_host; |