summaryrefslogtreecommitdiff
path: root/drivers/mmc/core
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2020-02-04 11:54:47 +0300
committerUlf Hansson <ulf.hansson@linaro.org>2020-03-24 16:35:40 +0300
commit490ff95f8e2c89d7541f187bae78d340b20d0ef0 (patch)
treea967edb18f3d0aab43101892b8f71dd887064d69 /drivers/mmc/core
parent9f94d04752ad6bf6a704637c61590fe55c4c0d82 (diff)
downloadlinux-490ff95f8e2c89d7541f187bae78d340b20d0ef0.tar.xz
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/mmc/core')
-rw-r--r--drivers/mmc/core/mmc_ops.c20
-rw-r--r--drivers/mmc/core/mmc_ops.h1
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;