* [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY
@ 2014-01-29 22:37 Ulf Hansson
2014-01-29 22:37 ` [PATCH 01/13] mmc: core: Rename max_discard_to to max_busy_timeout Ulf Hansson
` (13 more replies)
0 siblings, 14 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:37 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
This patchset improves the handling around busy detection in the mmc core layer
while operating on host supporting MMC_CAP_WAIT_WHILE_BUSY.
A R1B response is for an mmc command, specified as and R1 but with an optional
busy assertion on the DAT0 line. Hosts supporting MMC_CAP_WAIT_WHILE_BUSY,
normally has a busy detection mechanism build in it's controller HW.
Using such a feature decreases the need for polling of the card's status using
CMD13, which is the fallback method used by the mmc core for hosts that don't
support MMC_CAP_WAIT_WHILE_BUSY.
Typcial commands that expects R1B responses are CMD6 (SWITCH), CMD12 (STOP),
CMD38 (ERASE) and CMD5 (SLEEP). This patchset adresses CMD6, CMD5 and improves
some parts where CMD12 are used. If the implemented approach becomes accepted,
a future patchset for CMD38 can be based on top if this patchset.
Do note, the final two patches implements support for busy detection for the
mmci host driver, since some of it's HW variants do supports busy detection.
Future suggested improvements related to this patchset: (Please, feel free to
implement any of them :-) ).
a) For CMD38, select a fixed number maximum blocks to accept for
erase/discard/trim operations. Compute the needed timeout depending on each
card's erase information provided through it's CSD/EXT_CSD registers. Then
follow the same principle as for sending a CMD6.
b) At least for CMD38, but likely for other commands as well, we could benefit
from doing a _periodic_ CMD13 polling to handle the busy completion. This will
also be useful for hosts supporting MMC_CAP_WAIT_WHILE_BUSY, in particular for
cases where the host are unable to support the needed busy timeout.
c) Handle timeouts while polling for card's status with CMD13 in cases where
a CMD12 has been used to finalize a data DATA_WRITE transfer.
Ulf Hansson (13):
mmc: core: Rename max_discard_to to max_busy_timeout
mmc: core: Rename cmd_timeout_ms to busy_timeout
mmc: core: Add ignore_crc flag to __mmc_switch
mmc: core: Minor simplifications to __mmc_switch
mmc: core: Fixup busy detection for mmc switch operations
mmc: core: Use generic CMD6 time while switching to eMMC HS200 mode
mmc: core: Respect host's max_busy_timeout when sending sleep cmd
mmc: block: Use R1 responses for stop cmds for read requests
mmc: block: Implement card_busy_detect() for busy detection
mmc: block: Respect hw busy detection in card_busy_detect()
mmc: block: Fixup busy detection while invoking stop cmd at recovery
mmc: mmci: Handle CMD irq before DATA irq
mmc: mmci: Enable support for busy detection for ux500 variant
drivers/mmc/card/block.c | 178 ++++++++++++++++++++++++++++----------------
drivers/mmc/core/core.c | 11 +--
drivers/mmc/core/mmc.c | 34 ++++++---
drivers/mmc/core/mmc_ops.c | 64 ++++++++++------
drivers/mmc/host/mmci.c | 54 +++++++++++---
drivers/mmc/host/mmci.h | 2 +
drivers/mmc/host/sdhci.c | 10 +--
include/linux/mmc/core.h | 4 +-
include/linux/mmc/host.h | 2 +-
9 files changed, 241 insertions(+), 118 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/13] mmc: core: Rename max_discard_to to max_busy_timeout
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
@ 2014-01-29 22:37 ` Ulf Hansson
2014-01-29 22:37 ` [PATCH 02/13] mmc: core: Rename cmd_timeout_ms to busy_timeout Ulf Hansson
` (12 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:37 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
Rename host->max_discard_to to host->max_busy_timeout, to reflect that
it tells the mmc core layer about the maximum supported busy detection
timeout by the host.
This timeout is at the moment only applicable to erase/trim/discard
commands. By the renaming we provide the option of make use of it for
other commands that cares about busy detection. In other words, those
commands that wants an R1B response, like for example the mmc switch
command.
Do note that the max_busy_timeout is supposed to be specified only by
hosts supporting MMC_CAP_WAIT_WHILE_BUSY.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/core/core.c | 6 +++---
drivers/mmc/host/sdhci.c | 2 +-
include/linux/mmc/host.h | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 098374b..a81d754 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2137,7 +2137,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card,
y = 0;
for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) {
timeout = mmc_erase_timeout(card, arg, qty + x);
- if (timeout > host->max_discard_to)
+ if (timeout > host->max_busy_timeout)
break;
if (timeout < last_timeout)
break;
@@ -2169,7 +2169,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
struct mmc_host *host = card->host;
unsigned int max_discard, max_trim;
- if (!host->max_discard_to)
+ if (!host->max_busy_timeout)
return UINT_MAX;
/*
@@ -2189,7 +2189,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
max_discard = 0;
}
pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n",
- mmc_hostname(host), max_discard, host->max_discard_to);
+ mmc_hostname(host), max_discard, host->max_busy_timeout);
return max_discard;
}
EXPORT_SYMBOL(mmc_calc_max_discard);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 9ddef47..ec57c6c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2941,7 +2941,7 @@ int sdhci_add_host(struct sdhci_host *host)
if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
host->timeout_clk = mmc->f_max / 1000;
- mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+ mmc->max_busy_timeout = (1 << 27) / host->timeout_clk;
mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 99f5709..9805522 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -304,7 +304,7 @@ struct mmc_host {
unsigned int max_req_size; /* maximum number of bytes in one req */
unsigned int max_blk_size; /* maximum size of one mmc block */
unsigned int max_blk_count; /* maximum number of blocks in one req */
- unsigned int max_discard_to; /* max. discard timeout in ms */
+ unsigned int max_busy_timeout; /* max busy timeout in ms */
/* private data */
spinlock_t lock; /* lock for claim and bus ops */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 02/13] mmc: core: Rename cmd_timeout_ms to busy_timeout
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
2014-01-29 22:37 ` [PATCH 01/13] mmc: core: Rename max_discard_to to max_busy_timeout Ulf Hansson
@ 2014-01-29 22:37 ` Ulf Hansson
2014-01-29 22:37 ` [PATCH 03/13] mmc: core: Add ignore_crc flag to __mmc_switch Ulf Hansson
` (11 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:37 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
To better reflect that the cmd_timeout_ms is directly related to the
busy detection timeout, let's rename it.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/core/core.c | 2 +-
drivers/mmc/core/mmc_ops.c | 2 +-
drivers/mmc/host/sdhci.c | 8 ++++----
include/linux/mmc/core.h | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index a81d754..90de094 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1950,7 +1950,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
cmd.opcode = MMC_ERASE;
cmd.arg = arg;
cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
- cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty);
+ cmd.busy_timeout = mmc_erase_timeout(card, arg, qty);
err = mmc_wait_for_cmd(card->host, &cmd, 0);
if (err) {
pr_err("mmc_erase: erase error %d, status %#x\n",
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index e5b5eeb..3377bbf 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -432,7 +432,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
- cmd.cmd_timeout_ms = timeout_ms;
+ cmd.busy_timeout = timeout_ms;
if (index == EXT_CSD_SANITIZE_START)
cmd.sanitize_busy = true;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index ec57c6c..1853255 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -675,12 +675,12 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
return 0xE;
/* Unspecified timeout, assume max */
- if (!data && !cmd->cmd_timeout_ms)
+ if (!data && !cmd->busy_timeout)
return 0xE;
/* timeout in us */
if (!data)
- target_timeout = cmd->cmd_timeout_ms * 1000;
+ target_timeout = cmd->busy_timeout * 1000;
else {
target_timeout = data->timeout_ns / 1000;
if (host->clock)
@@ -1019,8 +1019,8 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
}
timeout = jiffies;
- if (!cmd->data && cmd->cmd_timeout_ms > 9000)
- timeout += DIV_ROUND_UP(cmd->cmd_timeout_ms, 1000) * HZ + HZ;
+ if (!cmd->data && cmd->busy_timeout > 9000)
+ timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
else
timeout += 10 * HZ;
mod_timer(&host->timer, timeout);
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 87079fc..b276996 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -95,7 +95,7 @@ struct mmc_command {
* actively failing requests
*/
- unsigned int cmd_timeout_ms; /* in milliseconds */
+ unsigned int busy_timeout; /* busy detect timeout in ms */
/* Set this flag only for blocking sanitize request */
bool sanitize_busy;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 03/13] mmc: core: Add ignore_crc flag to __mmc_switch
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
2014-01-29 22:37 ` [PATCH 01/13] mmc: core: Rename max_discard_to to max_busy_timeout Ulf Hansson
2014-01-29 22:37 ` [PATCH 02/13] mmc: core: Rename cmd_timeout_ms to busy_timeout Ulf Hansson
@ 2014-01-29 22:37 ` Ulf Hansson
2014-01-29 22:37 ` [PATCH 04/13] mmc: core: Minor simplifications " Ulf Hansson
` (10 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:37 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
Instead of handle specific adaptations, releated to certain switch
operations, inside __mmc_switch, push this to be handled by the caller
instead.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/core/core.c | 3 ++-
drivers/mmc/core/mmc.c | 13 +++++++------
drivers/mmc/core/mmc_ops.c | 19 ++++++++++---------
include/linux/mmc/core.h | 2 +-
4 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 90de094..75ce01d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -302,7 +302,8 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
}
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal, true);
+ EXT_CSD_BKOPS_START, 1, timeout,
+ use_busy_signal, true, false);
if (err) {
pr_warn("%s: Error %d starting bkops\n",
mmc_hostname(card->host), err);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 98e9eb0..ae3489a 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -856,8 +856,8 @@ static int mmc_select_hs200(struct mmc_card *card)
/* switch to HS200 mode if bus width set successfully */
if (!err)
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 2, 0);
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, 2, 0, true, true, true);
err:
return err;
}
@@ -1074,9 +1074,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
host->caps2 & MMC_CAP2_HS200)
err = mmc_select_hs200(card);
else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 1,
- card->ext_csd.generic_cmd6_time);
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, 1,
+ card->ext_csd.generic_cmd6_time,
+ true, true, true);
if (err && err != -EBADMSG)
goto free_card;
@@ -1404,7 +1405,7 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_POWER_OFF_NOTIFICATION,
- notify_type, timeout, true, false);
+ notify_type, timeout, true, false, false);
if (err)
pr_err("%s: Power Off Notification timed out, %u\n",
mmc_hostname(card->host), timeout);
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 3377bbf..5e1a2cb 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -405,17 +405,18 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
* timeout of zero implies maximum possible timeout
* @use_busy_signal: use the busy signal as response type
* @send_status: send status cmd to poll for busy
+ * @ignore_crc: ignore CRC errors when sending status cmd to poll for busy
*
* Modifies the EXT_CSD register for selected card.
*/
int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
- unsigned int timeout_ms, bool use_busy_signal, bool send_status)
+ unsigned int timeout_ms, bool use_busy_signal, bool send_status,
+ bool ignore_crc)
{
int err;
struct mmc_command cmd = {0};
unsigned long timeout;
u32 status = 0;
- bool ignore_crc = false;
BUG_ON(!card);
BUG_ON(!card->host);
@@ -445,14 +446,13 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
return 0;
/*
- * Must check status to be sure of no errors
- * If CMD13 is to check the busy completion of the timing change,
- * disable the check of CRC error.
+ * CRC errors shall only be ignored in cases were CMD13 is used to poll
+ * to detect busy completion.
*/
- if (index == EXT_CSD_HS_TIMING &&
- !(card->host->caps & MMC_CAP_WAIT_WHILE_BUSY))
- ignore_crc = true;
+ if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ ignore_crc = false;
+ /* Must check status to be sure of no errors. */
timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
do {
if (send_status) {
@@ -501,7 +501,8 @@ EXPORT_SYMBOL_GPL(__mmc_switch);
int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms)
{
- return __mmc_switch(card, set, index, value, timeout_ms, true, true);
+ return __mmc_switch(card, set, index, value, timeout_ms, true, true,
+ false);
}
EXPORT_SYMBOL_GPL(mmc_switch);
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index b276996..f206e29 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -152,7 +152,7 @@ extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
struct mmc_command *, int);
extern void mmc_start_bkops(struct mmc_card *card, bool from_exception);
extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool,
- bool);
+ bool, bool);
extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 04/13] mmc: core: Minor simplifications to __mmc_switch
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (2 preceding siblings ...)
2014-01-29 22:37 ` [PATCH 03/13] mmc: core: Add ignore_crc flag to __mmc_switch Ulf Hansson
@ 2014-01-29 22:37 ` Ulf Hansson
2014-01-29 22:37 ` [PATCH 05/13] mmc: core: Fixup busy detection for mmc switch operations Ulf Hansson
` (9 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:37 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
Instead of using several references to card->host, let's use a local
variable. That means we can remove the BUG_ON verifications for the
same pointers.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/core/mmc_ops.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 5e1a2cb..04ecdb9 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -413,14 +413,12 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms, bool use_busy_signal, bool send_status,
bool ignore_crc)
{
+ struct mmc_host *host = card->host;
int err;
struct mmc_command cmd = {0};
unsigned long timeout;
u32 status = 0;
- BUG_ON(!card);
- BUG_ON(!card->host);
-
cmd.opcode = MMC_SWITCH;
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
(index << 16) |
@@ -437,7 +435,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
if (index == EXT_CSD_SANITIZE_START)
cmd.sanitize_busy = true;
- err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+ err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
if (err)
return err;
@@ -449,7 +447,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
* CRC errors shall only be ignored in cases were CMD13 is used to poll
* to detect busy completion.
*/
- if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
ignore_crc = false;
/* Must check status to be sure of no errors. */
@@ -460,9 +458,9 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
if (err)
return err;
}
- if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
break;
- if (mmc_host_is_spi(card->host))
+ if (mmc_host_is_spi(host))
break;
/*
@@ -478,18 +476,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
/* Timeout if the device never leaves the program state. */
if (time_after(jiffies, timeout)) {
pr_err("%s: Card stuck in programming state! %s\n",
- mmc_hostname(card->host), __func__);
+ mmc_hostname(host), __func__);
return -ETIMEDOUT;
}
} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
- if (mmc_host_is_spi(card->host)) {
+ if (mmc_host_is_spi(host)) {
if (status & R1_SPI_ILLEGAL_COMMAND)
return -EBADMSG;
} else {
if (status & 0xFDFFA000)
- pr_warning("%s: unexpected status %#x after "
- "switch", mmc_hostname(card->host), status);
+ pr_warn("%s: unexpected status %#x after switch\n",
+ mmc_hostname(host), status);
if (status & R1_SWITCH_ERROR)
return -EBADMSG;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 05/13] mmc: core: Fixup busy detection for mmc switch operations
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (3 preceding siblings ...)
2014-01-29 22:37 ` [PATCH 04/13] mmc: core: Minor simplifications " Ulf Hansson
@ 2014-01-29 22:37 ` Ulf Hansson
2014-01-29 22:37 ` [PATCH 06/13] mmc: core: Use generic CMD6 time while switching to eMMC HS200 mode Ulf Hansson
` (8 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:37 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
If the host controller supports busy detection in HW, we expect the
MMC_CAP_WAIT_WHILE_BUSY to be set. Likewise the corresponding
host->max_busy_timeout should reflect the maximum busy detection
timeout supported by the host.
Previously we expected a host that supported MMC_CAP_WAIT_WHILE_BUSY to
cope with any timeout, which just isn't feasible due to HW limitations.
For most switch operations, R1B responses are expected and thus we need
to check for busy detection completion. To cope with cases where the
requested busy detection timeout is greater than what the host are able
to support, we fallback to use a R1 response instead. This will prevent
the host from doing HW busy detection.
In those cases, busy detection completion is handled by polling the for
the card's status using CMD13. This is the same mechanism used when the
host doesn't support MMC_CAP_WAIT_WHILE_BUSY.
Do note, a host->max_busy_timeout set to zero, is interpreted by the
mmc core as it don't know what the host supports. It will then provide
the host with whatever timeout the mmc core finds suitable.
For some cases the mmc core has unfurtunate no clue of what timeout to
use. In these cases we provide the host with a timeout value of zero,
which the host may interpret as use whatever timeout it finds suitable.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/core/mmc_ops.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 04ecdb9..f51b5ba 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -418,6 +418,17 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
struct mmc_command cmd = {0};
unsigned long timeout;
u32 status = 0;
+ bool use_r1b_resp = use_busy_signal;
+
+ /*
+ * If the cmd timeout and the max_busy_timeout of the host are both
+ * specified, let's validate them. A failure means we need to prevent
+ * the host from doing hw busy detection, which is done by converting
+ * to a R1 response instead of a R1B.
+ */
+ if (timeout_ms && host->max_busy_timeout &&
+ (timeout_ms > host->max_busy_timeout))
+ use_r1b_resp = false;
cmd.opcode = MMC_SWITCH;
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
@@ -425,13 +436,17 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
(value << 8) |
set;
cmd.flags = MMC_CMD_AC;
- if (use_busy_signal)
+ if (use_r1b_resp) {
cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
- else
+ /*
+ * A busy_timeout of zero means the host can decide to use
+ * whatever value it finds suitable.
+ */
+ cmd.busy_timeout = timeout_ms;
+ } else {
cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
+ }
-
- cmd.busy_timeout = timeout_ms;
if (index == EXT_CSD_SANITIZE_START)
cmd.sanitize_busy = true;
@@ -447,18 +462,22 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
* CRC errors shall only be ignored in cases were CMD13 is used to poll
* to detect busy completion.
*/
- if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
ignore_crc = false;
+ /* We have an unspecified cmd timeout, use the fallback value. */
+ if (!timeout_ms)
+ timeout_ms = MMC_OPS_TIMEOUT_MS;
+
/* Must check status to be sure of no errors. */
- timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
+ timeout = jiffies + msecs_to_jiffies(timeout_ms);
do {
if (send_status) {
err = __mmc_send_status(card, &status, ignore_crc);
if (err)
return err;
}
- if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+ if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
break;
if (mmc_host_is_spi(host))
break;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 06/13] mmc: core: Use generic CMD6 time while switching to eMMC HS200 mode
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (4 preceding siblings ...)
2014-01-29 22:37 ` [PATCH 05/13] mmc: core: Fixup busy detection for mmc switch operations Ulf Hansson
@ 2014-01-29 22:37 ` Ulf Hansson
2014-01-29 22:37 ` [PATCH 07/13] mmc: core: Respect host's max_busy_timeout when sending sleep cmd Ulf Hansson
` (7 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:37 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
Conform to the eMMC spec and use the CMD6 generic timeout from the
EXT_CSD register, when switching to HS200 mode.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/core/mmc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index ae3489a..897fdd1 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -857,7 +857,9 @@ static int mmc_select_hs200(struct mmc_card *card)
/* switch to HS200 mode if bus width set successfully */
if (!err)
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 2, 0, true, true, true);
+ EXT_CSD_HS_TIMING, 2,
+ card->ext_csd.generic_cmd6_time,
+ true, true, true);
err:
return err;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 07/13] mmc: core: Respect host's max_busy_timeout when sending sleep cmd
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (5 preceding siblings ...)
2014-01-29 22:37 ` [PATCH 06/13] mmc: core: Use generic CMD6 time while switching to eMMC HS200 mode Ulf Hansson
@ 2014-01-29 22:37 ` Ulf Hansson
2014-01-29 22:38 ` [PATCH 08/13] mmc: block: Use R1 responses for stop cmds for read requests Ulf Hansson
` (6 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:37 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
When sending the sleep command for host drivers supporting
MMC_CAP_WAIT_WHILE_BUSY, we need to confirm that max_busy_timeout is
big enough comparing to the sleep timeout specified from card's
EXT_CSD. If this isn't case, we use a R1 response instead of R1B and
fallback to use a delay instead.
Do note that a max_busy_timeout set to zero by the host, is interpreted
as it can cope with whatever timeout the mmc core provides it with.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/core/mmc.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 897fdd1..d641590 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1359,6 +1359,7 @@ static int mmc_sleep(struct mmc_host *host)
{
struct mmc_command cmd = {0};
struct mmc_card *card = host->card;
+ unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000);
int err;
if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
@@ -1372,7 +1373,19 @@ static int mmc_sleep(struct mmc_host *host)
cmd.arg = card->rca << 16;
cmd.arg |= 1 << 15;
- cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+ /*
+ * If the max_busy_timeout of the host is specified, validate it against
+ * the sleep cmd timeout. A failure means we need to prevent the host
+ * from doing hw busy detection, which is done by converting to a R1
+ * response instead of a R1B.
+ */
+ if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) {
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+ } else {
+ cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+ cmd.busy_timeout = timeout_ms;
+ }
+
err = mmc_wait_for_cmd(host, &cmd, 0);
if (err)
return err;
@@ -1383,8 +1396,8 @@ static int mmc_sleep(struct mmc_host *host)
* SEND_STATUS command to poll the status because that command (and most
* others) is invalid while the card sleeps.
*/
- if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
- mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
+ if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
+ mmc_delay(timeout_ms);
return err;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 08/13] mmc: block: Use R1 responses for stop cmds for read requests
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (6 preceding siblings ...)
2014-01-29 22:37 ` [PATCH 07/13] mmc: core: Respect host's max_busy_timeout when sending sleep cmd Ulf Hansson
@ 2014-01-29 22:38 ` Ulf Hansson
2014-01-29 22:38 ` [PATCH 09/13] mmc: block: Implement card_busy_detect() for busy detection Ulf Hansson
` (5 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:38 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
While using open ended transmission and thus ending the transfer by
sending a stop command, we shall use R1B only for writes and R1 shall
be used for reads. Previously R1B were used in both cases.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/card/block.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 7b5424f..87cd2b0 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1335,7 +1335,6 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
brq->data.blksz = 512;
brq->stop.opcode = MMC_STOP_TRANSMISSION;
brq->stop.arg = 0;
- brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
brq->data.blocks = blk_rq_sectors(req);
/*
@@ -1378,9 +1377,15 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
if (rq_data_dir(req) == READ) {
brq->cmd.opcode = readcmd;
brq->data.flags |= MMC_DATA_READ;
+ if (brq->mrq.stop)
+ brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 |
+ MMC_CMD_AC;
} else {
brq->cmd.opcode = writecmd;
brq->data.flags |= MMC_DATA_WRITE;
+ if (brq->mrq.stop)
+ brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B |
+ MMC_CMD_AC;
}
if (do_rel_wr)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 09/13] mmc: block: Implement card_busy_detect() for busy detection
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (7 preceding siblings ...)
2014-01-29 22:38 ` [PATCH 08/13] mmc: block: Use R1 responses for stop cmds for read requests Ulf Hansson
@ 2014-01-29 22:38 ` Ulf Hansson
2014-01-29 22:38 ` [PATCH 10/13] mmc: block: Respect hw busy detection in card_busy_detect() Ulf Hansson
` (4 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:38 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
To complete a data write request we poll for the card's status register
by sending CMD13. The are other scenarios when this polling method are
needed, which is why we here moves this code to it's own function. No
functional change.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/card/block.c | 82 ++++++++++++++++++++++++++--------------------
1 file changed, 47 insertions(+), 35 deletions(-)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 87cd2b0..9568999 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -750,6 +750,49 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries)
return err;
}
+static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
+ struct request *req, int *gen_err)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+ int err = 0;
+ u32 status;
+
+ do {
+ err = get_card_status(card, &status, 5);
+ if (err) {
+ pr_err("%s: error %d requesting status\n",
+ req->rq_disk->disk_name, err);
+ return err;
+ }
+
+ if (status & R1_ERROR) {
+ pr_err("%s: %s: error sending status cmd, status %#x\n",
+ req->rq_disk->disk_name, __func__, status);
+ *gen_err = 1;
+ }
+
+ /*
+ * Timeout if the device never becomes ready for data and never
+ * leaves the program state.
+ */
+ if (time_after(jiffies, timeout)) {
+ pr_err("%s: Card stuck in programming state! %s %s\n",
+ mmc_hostname(card->host),
+ req->rq_disk->disk_name, __func__);
+ return -ETIMEDOUT;
+ }
+
+ /*
+ * Some cards mishandle the status bits,
+ * so make sure to check both the busy
+ * indication and the card state.
+ */
+ } while (!(status & R1_READY_FOR_DATA) ||
+ (R1_CURRENT_STATE(status) == R1_STATE_PRG));
+
+ return err;
+}
+
#define ERR_NOMEDIUM 3
#define ERR_RETRY 2
#define ERR_ABORT 1
@@ -1157,8 +1200,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
* program mode, which we have to wait for it to complete.
*/
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
- u32 status;
- unsigned long timeout;
+ int err;
/* Check stop command response */
if (brq->stop.resp[0] & R1_ERROR) {
@@ -1168,39 +1210,9 @@ static int mmc_blk_err_check(struct mmc_card *card,
gen_err = 1;
}
- timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
- do {
- int err = get_card_status(card, &status, 5);
- if (err) {
- pr_err("%s: error %d requesting status\n",
- req->rq_disk->disk_name, err);
- return MMC_BLK_CMD_ERR;
- }
-
- if (status & R1_ERROR) {
- pr_err("%s: %s: general error sending status command, card status %#x\n",
- req->rq_disk->disk_name, __func__,
- status);
- gen_err = 1;
- }
-
- /* Timeout if the device never becomes ready for data
- * and never leaves the program state.
- */
- if (time_after(jiffies, timeout)) {
- pr_err("%s: Card stuck in programming state!"\
- " %s %s\n", mmc_hostname(card->host),
- req->rq_disk->disk_name, __func__);
-
- return MMC_BLK_CMD_ERR;
- }
- /*
- * Some cards mishandle the status bits,
- * so make sure to check both the busy
- * indication and the card state.
- */
- } while (!(status & R1_READY_FOR_DATA) ||
- (R1_CURRENT_STATE(status) == R1_STATE_PRG));
+ err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &gen_err);
+ if (err)
+ return MMC_BLK_CMD_ERR;
}
/* if general error occurs, retry the write operation. */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 10/13] mmc: block: Respect hw busy detection in card_busy_detect()
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (8 preceding siblings ...)
2014-01-29 22:38 ` [PATCH 09/13] mmc: block: Implement card_busy_detect() for busy detection Ulf Hansson
@ 2014-01-29 22:38 ` Ulf Hansson
2014-01-29 22:38 ` [PATCH 11/13] mmc: block: Fixup busy detection while invoking stop cmd at recovery Ulf Hansson
` (3 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:38 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
Currently for write request we don't trust the hw busy detection to be
fully handled by host, thus we also poll the card's status until we see
it's gets out of the busy state.
Still there are scenarios where it will a benefit to trust the hw busy
detection done by the host, since no additional polling is needed.
Let's prepare card_busy_detect() to be able to handle this.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/card/block.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 9568999..fec5e98 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -751,7 +751,7 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries)
}
static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
- struct request *req, int *gen_err)
+ bool hw_busy_detect, struct request *req, int *gen_err)
{
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
int err = 0;
@@ -771,6 +771,11 @@ static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
*gen_err = 1;
}
+ /* We may rely on the host hw to handle busy detection.*/
+ if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) &&
+ hw_busy_detect)
+ break;
+
/*
* Timeout if the device never becomes ready for data and never
* leaves the program state.
@@ -1210,7 +1215,8 @@ static int mmc_blk_err_check(struct mmc_card *card,
gen_err = 1;
}
- err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &gen_err);
+ err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req,
+ &gen_err);
if (err)
return MMC_BLK_CMD_ERR;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 11/13] mmc: block: Fixup busy detection while invoking stop cmd at recovery
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (9 preceding siblings ...)
2014-01-29 22:38 ` [PATCH 10/13] mmc: block: Respect hw busy detection in card_busy_detect() Ulf Hansson
@ 2014-01-29 22:38 ` Ulf Hansson
2014-01-29 22:38 ` [PATCH 12/13] mmc: mmci: Handle CMD irq before DATA irq Ulf Hansson
` (2 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:38 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson
When sending a stop command at the recovery path, use a R1B response
when the failing data request are a WRITE. Thus we also care about the
busy detection completion in this case.
For a failing READ request, we use a R1 response for the stop command,
since we don't need to care about busy detection in this case.
To align behavior between hosts supporting MMC_CAP_WAIT_WHILE_BUSY and
those who are not, we add a CMD13 polling method for the card's status.
We also respect whether the host has specified the max_busy_timeout,
which means we may fallback to CMD13 polling if the timeout is greater
than what the host are able to support.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/card/block.c | 83 ++++++++++++++++++++++++++++++----------------
1 file changed, 55 insertions(+), 28 deletions(-)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index fec5e98..17cd0fc 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -722,19 +722,6 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
return result;
}
-static int send_stop(struct mmc_card *card, u32 *status)
-{
- struct mmc_command cmd = {0};
- int err;
-
- cmd.opcode = MMC_STOP_TRANSMISSION;
- cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
- err = mmc_wait_for_cmd(card->host, &cmd, 5);
- if (err == 0)
- *status = cmd.resp[0];
- return err;
-}
-
static int get_card_status(struct mmc_card *card, u32 *status, int retries)
{
struct mmc_command cmd = {0};
@@ -798,6 +785,51 @@ static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
return err;
}
+static int send_stop(struct mmc_card *card, unsigned int timeout_ms,
+ struct request *req, int *gen_err, u32 *stop_status)
+{
+ struct mmc_host *host = card->host;
+ struct mmc_command cmd = {0};
+ int err;
+ bool use_r1b_resp = rq_data_dir(req) == WRITE;
+
+ /*
+ * Normally we use R1B responses for WRITE, but in cases where the host
+ * has specified a max_busy_timeout we need to validate it. A failure
+ * means we need to prevent the host from doing hw busy detection, which
+ * is done by converting to a R1 response instead.
+ */
+ if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))
+ use_r1b_resp = false;
+
+ cmd.opcode = MMC_STOP_TRANSMISSION;
+ if (use_r1b_resp) {
+ cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+ cmd.busy_timeout = timeout_ms;
+ } else {
+ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+ }
+
+ err = mmc_wait_for_cmd(host, &cmd, 5);
+ if (err)
+ return err;
+
+ *stop_status = cmd.resp[0];
+
+ /* No need to check card status in case of READ. */
+ if (rq_data_dir(req) == READ)
+ return 0;
+
+ if (!mmc_host_is_spi(host) &&
+ (*stop_status & R1_ERROR)) {
+ pr_err("%s: %s: general error sending stop command, resp %#x\n",
+ req->rq_disk->disk_name, __func__, *stop_status);
+ *gen_err = 1;
+ }
+
+ return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err);
+}
+
#define ERR_NOMEDIUM 3
#define ERR_RETRY 2
#define ERR_ABORT 1
@@ -914,26 +946,21 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
*/
if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
R1_CURRENT_STATE(status) == R1_STATE_RCV) {
- err = send_stop(card, &stop_status);
- if (err)
+ err = send_stop(card,
+ DIV_ROUND_UP(brq->data.timeout_ns, 1000000),
+ req, gen_err, &stop_status);
+ if (err) {
pr_err("%s: error %d sending stop command\n",
req->rq_disk->disk_name, err);
-
- /*
- * If the stop cmd also timed out, the card is probably
- * not present, so abort. Other errors are bad news too.
- */
- if (err)
+ /*
+ * If the stop cmd also timed out, the card is probably
+ * not present, so abort. Other errors are bad news too.
+ */
return ERR_ABORT;
+ }
+
if (stop_status & R1_CARD_ECC_FAILED)
*ecc_err = 1;
- if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
- if (stop_status & R1_ERROR) {
- pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
- req->rq_disk->disk_name, __func__,
- stop_status);
- *gen_err = 1;
- }
}
/* Check for set block count errors */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 12/13] mmc: mmci: Handle CMD irq before DATA irq
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (10 preceding siblings ...)
2014-01-29 22:38 ` [PATCH 11/13] mmc: block: Fixup busy detection while invoking stop cmd at recovery Ulf Hansson
@ 2014-01-29 22:38 ` Ulf Hansson
2014-02-12 13:17 ` Ulf Hansson
2014-01-29 22:38 ` [PATCH 13/13] mmc: mmci: Enable support for busy detection for ux500 variant Ulf Hansson
2014-09-03 6:51 ` [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Dong Aisheng
13 siblings, 1 reply; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:38 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson, Russell King, Johan Rudholm
In case of a read operation both MCI_CMDRESPEND and MCI_DATAEND can be
set in the status register when entering the interrupt handler. This is
due to that the card start sending data before the host has
acknowledged the command response.
To resolve the issue for this scenario, we must start by handling the
CMD irq instead of the DATA irq. The reason is beacuse the completion
of the DATA irq will not respect the current command and then causing
it to be garbled.
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Johan Rudholm <jrudholm@gmail.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/host/mmci.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index f320579..1a4b153 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1144,16 +1144,17 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
+ cmd = host->cmd;
+ if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|
+ MCI_CMDRESPEND) && cmd)
+ mmci_cmd_irq(host, cmd, status);
+
data = host->data;
if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND|
MCI_DATABLOCKEND) && data)
mmci_data_irq(host, data, status);
- cmd = host->cmd;
- if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
- mmci_cmd_irq(host, cmd, status);
-
ret = 1;
} while (status);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 13/13] mmc: mmci: Enable support for busy detection for ux500 variant
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (11 preceding siblings ...)
2014-01-29 22:38 ` [PATCH 12/13] mmc: mmci: Handle CMD irq before DATA irq Ulf Hansson
@ 2014-01-29 22:38 ` Ulf Hansson
2014-02-12 13:20 ` Ulf Hansson
2014-09-03 6:51 ` [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Dong Aisheng
13 siblings, 1 reply; 21+ messages in thread
From: Ulf Hansson @ 2014-01-29 22:38 UTC (permalink / raw)
To: linux-mmc, Chris Ball
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson, Russell King, Johan Rudholm
The ux500 variants have HW busy detection support, which is indicated
by the busy_detect flag. For these variants let's enable the
MMC_CAP_WAIT_WHILE_BUSY flag and add the support for it.
The mmc core will provide the RSP_BUSY command flag for those requests
we should care about busy detection. Regarding the max_busy_timeout,
the HW don't support busy detection timeouts so at this initial step
let's make it simple and set it to zero to indicate we are able to
support any timeout.
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Johan Rudholm <jrudholm@gmail.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/host/mmci.c | 51 +++++++++++++++++++++++++++++++++++++++--------
drivers/mmc/host/mmci.h | 2 ++
2 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 1a4b153..9976a90 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -921,6 +921,29 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
{
void __iomem *base = host->base;
bool sbc = (cmd == host->mrq->sbc);
+ bool busy_resp = host->variant->busy_detect &&
+ (cmd->flags & MMC_RSP_BUSY);
+
+ /* Check if we need to wait for busy completion. */
+ if (host->busy_status && (status & MCI_ST_CARDBUSY))
+ return;
+
+ /* Enable busy completion if needed and supported. */
+ if (!host->busy_status && busy_resp &&
+ !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
+ (readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) {
+ writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND,
+ base + MMCIMASK0);
+ host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND);
+ return;
+ }
+
+ /* At busy completion, mask the IRQ and complete the request. */
+ if (host->busy_status) {
+ writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND,
+ base + MMCIMASK0);
+ host->busy_status = 0;
+ }
host->cmd = NULL;
@@ -1139,14 +1162,19 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
status &= ~MCI_IRQ1MASK;
}
+ /*
+ * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's
+ * enabled) since the HW seems to be triggering the IRQ on both
+ * edges while monitoring DAT0 for busy completion.
+ */
status &= readl(host->base + MMCIMASK0);
writel(status, host->base + MMCICLEAR);
dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
cmd = host->cmd;
- if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|
- MCI_CMDRESPEND) && cmd)
+ if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
+ MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
mmci_cmd_irq(host, cmd, status);
data = host->data;
@@ -1155,6 +1183,10 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
MCI_DATABLOCKEND) && data)
mmci_data_irq(host, data, status);
+ /* Don't poll for busy completion in irq context. */
+ if (host->busy_status)
+ status &= ~MCI_ST_CARDBUSY;
+
ret = 1;
} while (status);
@@ -1504,12 +1536,6 @@ static int mmci_probe(struct amba_device *dev,
goto clk_disable;
}
- if (variant->busy_detect) {
- mmci_ops.card_busy = mmci_card_busy;
- mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
- }
-
- mmc->ops = &mmci_ops;
/*
* The ARM and ST versions of the block have slightly different
* clock divider equations which means that the minimum divider
@@ -1543,6 +1569,15 @@ static int mmci_probe(struct amba_device *dev,
mmc->caps = plat->capabilities;
mmc->caps2 = plat->capabilities2;
+ if (variant->busy_detect) {
+ mmci_ops.card_busy = mmci_card_busy;
+ mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
+ mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
+ mmc->max_busy_timeout = 0;
+ }
+
+ mmc->ops = &mmci_ops;
+
/* We support these PM capabilities. */
mmc->pm_caps = MMC_PM_KEEP_POWER;
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 168bc72..b008ace 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -139,6 +139,7 @@
/* Extended status bits for the ST Micro variants */
#define MCI_ST_SDIOITMASK (1 << 22)
#define MCI_ST_CEATAENDMASK (1 << 23)
+#define MCI_ST_BUSYEND (1 << 24)
#define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x048
@@ -186,6 +187,7 @@ struct mmci_host {
u32 pwr_reg;
u32 clk_reg;
u32 datactrl_reg;
+ u32 busy_status;
bool vqmmc_enabled;
struct mmci_platform_data *plat;
struct variant_data *variant;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 12/13] mmc: mmci: Handle CMD irq before DATA irq
2014-01-29 22:38 ` [PATCH 12/13] mmc: mmci: Handle CMD irq before DATA irq Ulf Hansson
@ 2014-02-12 13:17 ` Ulf Hansson
0 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-02-12 13:17 UTC (permalink / raw)
To: Russell King
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson, Johan Rudholm, Chris Ball, linux-mmc
On 29 January 2014 23:38, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> In case of a read operation both MCI_CMDRESPEND and MCI_DATAEND can be
> set in the status register when entering the interrupt handler. This is
> due to that the card start sending data before the host has
> acknowledged the command response.
>
> To resolve the issue for this scenario, we must start by handling the
> CMD irq instead of the DATA irq. The reason is beacuse the completion
> of the DATA irq will not respect the current command and then causing
> it to be garbled.
>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Johan Rudholm <jrudholm@gmail.com>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Hi Russell,
Just wanted to know if you were happy with this patch.
I would prefer if we could let Chris carry this patch, since there are
a dependency. Are you fine with that?
Kind regards
Ulf Hansson
> ---
> drivers/mmc/host/mmci.c | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
> index f320579..1a4b153 100644
> --- a/drivers/mmc/host/mmci.c
> +++ b/drivers/mmc/host/mmci.c
> @@ -1144,16 +1144,17 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
>
> dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
>
> + cmd = host->cmd;
> + if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|
> + MCI_CMDRESPEND) && cmd)
> + mmci_cmd_irq(host, cmd, status);
> +
> data = host->data;
> if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
> MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND|
> MCI_DATABLOCKEND) && data)
> mmci_data_irq(host, data, status);
>
> - cmd = host->cmd;
> - if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
> - mmci_cmd_irq(host, cmd, status);
> -
> ret = 1;
> } while (status);
>
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 13/13] mmc: mmci: Enable support for busy detection for ux500 variant
2014-01-29 22:38 ` [PATCH 13/13] mmc: mmci: Enable support for busy detection for ux500 variant Ulf Hansson
@ 2014-02-12 13:20 ` Ulf Hansson
0 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-02-12 13:20 UTC (permalink / raw)
To: Russell King
Cc: Dong Aisheng, Stephen Warren, Vladimir Zapolskiy, Adrian Hunter,
Ulf Hansson, Johan Rudholm, Chris Ball, linux-mmc
On 29 January 2014 23:38, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> The ux500 variants have HW busy detection support, which is indicated
> by the busy_detect flag. For these variants let's enable the
> MMC_CAP_WAIT_WHILE_BUSY flag and add the support for it.
>
> The mmc core will provide the RSP_BUSY command flag for those requests
> we should care about busy detection. Regarding the max_busy_timeout,
> the HW don't support busy detection timeouts so at this initial step
> let's make it simple and set it to zero to indicate we are able to
> support any timeout.
>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Johan Rudholm <jrudholm@gmail.com>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Hi Russell,
Just wanted to know if you were happy with this patch.
I would prefer if we could let Chris carry this patch, since there are
a dependency. Are you fine with that?
Kind regards
Ulf Hansson
> ---
> drivers/mmc/host/mmci.c | 51 +++++++++++++++++++++++++++++++++++++++--------
> drivers/mmc/host/mmci.h | 2 ++
> 2 files changed, 45 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
> index 1a4b153..9976a90 100644
> --- a/drivers/mmc/host/mmci.c
> +++ b/drivers/mmc/host/mmci.c
> @@ -921,6 +921,29 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
> {
> void __iomem *base = host->base;
> bool sbc = (cmd == host->mrq->sbc);
> + bool busy_resp = host->variant->busy_detect &&
> + (cmd->flags & MMC_RSP_BUSY);
> +
> + /* Check if we need to wait for busy completion. */
> + if (host->busy_status && (status & MCI_ST_CARDBUSY))
> + return;
> +
> + /* Enable busy completion if needed and supported. */
> + if (!host->busy_status && busy_resp &&
> + !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
> + (readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) {
> + writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND,
> + base + MMCIMASK0);
> + host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND);
> + return;
> + }
> +
> + /* At busy completion, mask the IRQ and complete the request. */
> + if (host->busy_status) {
> + writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND,
> + base + MMCIMASK0);
> + host->busy_status = 0;
> + }
>
> host->cmd = NULL;
>
> @@ -1139,14 +1162,19 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
> status &= ~MCI_IRQ1MASK;
> }
>
> + /*
> + * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's
> + * enabled) since the HW seems to be triggering the IRQ on both
> + * edges while monitoring DAT0 for busy completion.
> + */
> status &= readl(host->base + MMCIMASK0);
> writel(status, host->base + MMCICLEAR);
>
> dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
>
> cmd = host->cmd;
> - if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|
> - MCI_CMDRESPEND) && cmd)
> + if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
> + MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
> mmci_cmd_irq(host, cmd, status);
>
> data = host->data;
> @@ -1155,6 +1183,10 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
> MCI_DATABLOCKEND) && data)
> mmci_data_irq(host, data, status);
>
> + /* Don't poll for busy completion in irq context. */
> + if (host->busy_status)
> + status &= ~MCI_ST_CARDBUSY;
> +
> ret = 1;
> } while (status);
>
> @@ -1504,12 +1536,6 @@ static int mmci_probe(struct amba_device *dev,
> goto clk_disable;
> }
>
> - if (variant->busy_detect) {
> - mmci_ops.card_busy = mmci_card_busy;
> - mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
> - }
> -
> - mmc->ops = &mmci_ops;
> /*
> * The ARM and ST versions of the block have slightly different
> * clock divider equations which means that the minimum divider
> @@ -1543,6 +1569,15 @@ static int mmci_probe(struct amba_device *dev,
> mmc->caps = plat->capabilities;
> mmc->caps2 = plat->capabilities2;
>
> + if (variant->busy_detect) {
> + mmci_ops.card_busy = mmci_card_busy;
> + mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
> + mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
> + mmc->max_busy_timeout = 0;
> + }
> +
> + mmc->ops = &mmci_ops;
> +
> /* We support these PM capabilities. */
> mmc->pm_caps = MMC_PM_KEEP_POWER;
>
> diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
> index 168bc72..b008ace 100644
> --- a/drivers/mmc/host/mmci.h
> +++ b/drivers/mmc/host/mmci.h
> @@ -139,6 +139,7 @@
> /* Extended status bits for the ST Micro variants */
> #define MCI_ST_SDIOITMASK (1 << 22)
> #define MCI_ST_CEATAENDMASK (1 << 23)
> +#define MCI_ST_BUSYEND (1 << 24)
>
> #define MMCIMASK1 0x040
> #define MMCIFIFOCNT 0x048
> @@ -186,6 +187,7 @@ struct mmci_host {
> u32 pwr_reg;
> u32 clk_reg;
> u32 datactrl_reg;
> + u32 busy_status;
> bool vqmmc_enabled;
> struct mmci_platform_data *plat;
> struct variant_data *variant;
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
` (12 preceding siblings ...)
2014-01-29 22:38 ` [PATCH 13/13] mmc: mmci: Enable support for busy detection for ux500 variant Ulf Hansson
@ 2014-09-03 6:51 ` Dong Aisheng
2014-09-03 7:32 ` Ulf Hansson
13 siblings, 1 reply; 21+ messages in thread
From: Dong Aisheng @ 2014-09-03 6:51 UTC (permalink / raw)
To: Ulf Hansson
Cc: linux-mmc@vger.kernel.org, Chris Ball, Dong Aisheng,
Stephen Warren, Vladimir Zapolskiy, Adrian Hunter
Hi Ulf,
On Thu, Jan 30, 2014 at 6:37 AM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> This patchset improves the handling around busy detection in the mmc core layer
> while operating on host supporting MMC_CAP_WAIT_WHILE_BUSY.
>
> A R1B response is for an mmc command, specified as and R1 but with an optional
> busy assertion on the DAT0 line. Hosts supporting MMC_CAP_WAIT_WHILE_BUSY,
> normally has a busy detection mechanism build in it's controller HW.
>
> Using such a feature decreases the need for polling of the card's status using
> CMD13, which is the fallback method used by the mmc core for hosts that don't
> support MMC_CAP_WAIT_WHILE_BUSY.
>
> Typcial commands that expects R1B responses are CMD6 (SWITCH), CMD12 (STOP),
> CMD38 (ERASE) and CMD5 (SLEEP). This patchset adresses CMD6, CMD5 and improves
> some parts where CMD12 are used. If the implemented approach becomes accepted,
> a future patchset for CMD38 can be based on top if this patchset.
>
> Do note, the final two patches implements support for busy detection for the
> mmci host driver, since some of it's HW variants do supports busy detection.
>
> Future suggested improvements related to this patchset: (Please, feel free to
> implement any of them :-) ).
>
> a) For CMD38, select a fixed number maximum blocks to accept for
> erase/discard/trim operations. Compute the needed timeout depending on each
> card's erase information provided through it's CSD/EXT_CSD registers. Then
> follow the same principle as for sending a CMD6.
>
> b) At least for CMD38, but likely for other commands as well, we could benefit
> from doing a _periodic_ CMD13 polling to handle the busy completion. This will
> also be useful for hosts supporting MMC_CAP_WAIT_WHILE_BUSY, in particular for
> cases where the host are unable to support the needed busy timeout.
>
Do you have the plan to implement above two items?
Since currently the max_discard_sectors is still calculated based on
max_busy_timeout of host,
it is possible that for some eMMC chips, the max_discard_sectors is 1,
which then cause the erase operation terribly slow.
Regards
Dong Aisheng
> c) Handle timeouts while polling for card's status with CMD13 in cases where
> a CMD12 has been used to finalize a data DATA_WRITE transfer.
>
>
> Ulf Hansson (13):
> mmc: core: Rename max_discard_to to max_busy_timeout
> mmc: core: Rename cmd_timeout_ms to busy_timeout
> mmc: core: Add ignore_crc flag to __mmc_switch
> mmc: core: Minor simplifications to __mmc_switch
> mmc: core: Fixup busy detection for mmc switch operations
> mmc: core: Use generic CMD6 time while switching to eMMC HS200 mode
> mmc: core: Respect host's max_busy_timeout when sending sleep cmd
> mmc: block: Use R1 responses for stop cmds for read requests
> mmc: block: Implement card_busy_detect() for busy detection
> mmc: block: Respect hw busy detection in card_busy_detect()
> mmc: block: Fixup busy detection while invoking stop cmd at recovery
> mmc: mmci: Handle CMD irq before DATA irq
> mmc: mmci: Enable support for busy detection for ux500 variant
>
> drivers/mmc/card/block.c | 178 ++++++++++++++++++++++++++++----------------
> drivers/mmc/core/core.c | 11 +--
> drivers/mmc/core/mmc.c | 34 ++++++---
> drivers/mmc/core/mmc_ops.c | 64 ++++++++++------
> drivers/mmc/host/mmci.c | 54 +++++++++++---
> drivers/mmc/host/mmci.h | 2 +
> drivers/mmc/host/sdhci.c | 10 +--
> include/linux/mmc/core.h | 4 +-
> include/linux/mmc/host.h | 2 +-
> 9 files changed, 241 insertions(+), 118 deletions(-)
>
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY
2014-09-03 7:32 ` Ulf Hansson
@ 2014-09-03 7:24 ` Dong Aisheng
2014-09-05 9:29 ` Jaehoon Chung
1 sibling, 0 replies; 21+ messages in thread
From: Dong Aisheng @ 2014-09-03 7:24 UTC (permalink / raw)
To: Ulf Hansson
Cc: Dong Aisheng, linux-mmc@vger.kernel.org, Chris Ball,
Stephen Warren, Vladimir Zapolskiy, Adrian Hunter, b51421
On Wed, Sep 03, 2014 at 09:32:35AM +0200, Ulf Hansson wrote:
> On 3 September 2014 08:51, Dong Aisheng <dongas86@gmail.com> wrote:
> > Hi Ulf,
> >
> > On Thu, Jan 30, 2014 at 6:37 AM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> >> This patchset improves the handling around busy detection in the mmc core layer
> >> while operating on host supporting MMC_CAP_WAIT_WHILE_BUSY.
> >>
> >> A R1B response is for an mmc command, specified as and R1 but with an optional
> >> busy assertion on the DAT0 line. Hosts supporting MMC_CAP_WAIT_WHILE_BUSY,
> >> normally has a busy detection mechanism build in it's controller HW.
> >>
> >> Using such a feature decreases the need for polling of the card's status using
> >> CMD13, which is the fallback method used by the mmc core for hosts that don't
> >> support MMC_CAP_WAIT_WHILE_BUSY.
> >>
> >> Typcial commands that expects R1B responses are CMD6 (SWITCH), CMD12 (STOP),
> >> CMD38 (ERASE) and CMD5 (SLEEP). This patchset adresses CMD6, CMD5 and improves
> >> some parts where CMD12 are used. If the implemented approach becomes accepted,
> >> a future patchset for CMD38 can be based on top if this patchset.
> >>
> >> Do note, the final two patches implements support for busy detection for the
> >> mmci host driver, since some of it's HW variants do supports busy detection.
> >>
> >> Future suggested improvements related to this patchset: (Please, feel free to
> >> implement any of them :-) ).
> >>
> >> a) For CMD38, select a fixed number maximum blocks to accept for
> >> erase/discard/trim operations. Compute the needed timeout depending on each
> >> card's erase information provided through it's CSD/EXT_CSD registers. Then
> >> follow the same principle as for sending a CMD6.
> >>
> >> b) At least for CMD38, but likely for other commands as well, we could benefit
> >> from doing a _periodic_ CMD13 polling to handle the busy completion. This will
> >> also be useful for hosts supporting MMC_CAP_WAIT_WHILE_BUSY, in particular for
> >> cases where the host are unable to support the needed busy timeout.
> >>
> >
> > Do you have the plan to implement above two items?
>
> Yes, it's on top of my TODO list for MMC. I really need to get this
> done asap. Thanks for pinging me about this.
>
Great!
> > Since currently the max_discard_sectors is still calculated based on
> > max_busy_timeout of host,
> > it is possible that for some eMMC chips, the max_discard_sectors is 1,
> > which then cause the erase operation terribly slow.
>
> Yes!
>
> Another issue to fix is get MMC_CAP_ERASE removed - and that should be
> possible once the above described problem has been solved.
>
Yes, seems MMC_CAP_ERASE is not needed anymore.
Regards
Dong Aisheng
> Kind regards
> Uffe
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY
2014-09-03 6:51 ` [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Dong Aisheng
@ 2014-09-03 7:32 ` Ulf Hansson
2014-09-03 7:24 ` Dong Aisheng
2014-09-05 9:29 ` Jaehoon Chung
0 siblings, 2 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-09-03 7:32 UTC (permalink / raw)
To: Dong Aisheng
Cc: linux-mmc@vger.kernel.org, Chris Ball, Dong Aisheng,
Stephen Warren, Vladimir Zapolskiy, Adrian Hunter
On 3 September 2014 08:51, Dong Aisheng <dongas86@gmail.com> wrote:
> Hi Ulf,
>
> On Thu, Jan 30, 2014 at 6:37 AM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>> This patchset improves the handling around busy detection in the mmc core layer
>> while operating on host supporting MMC_CAP_WAIT_WHILE_BUSY.
>>
>> A R1B response is for an mmc command, specified as and R1 but with an optional
>> busy assertion on the DAT0 line. Hosts supporting MMC_CAP_WAIT_WHILE_BUSY,
>> normally has a busy detection mechanism build in it's controller HW.
>>
>> Using such a feature decreases the need for polling of the card's status using
>> CMD13, which is the fallback method used by the mmc core for hosts that don't
>> support MMC_CAP_WAIT_WHILE_BUSY.
>>
>> Typcial commands that expects R1B responses are CMD6 (SWITCH), CMD12 (STOP),
>> CMD38 (ERASE) and CMD5 (SLEEP). This patchset adresses CMD6, CMD5 and improves
>> some parts where CMD12 are used. If the implemented approach becomes accepted,
>> a future patchset for CMD38 can be based on top if this patchset.
>>
>> Do note, the final two patches implements support for busy detection for the
>> mmci host driver, since some of it's HW variants do supports busy detection.
>>
>> Future suggested improvements related to this patchset: (Please, feel free to
>> implement any of them :-) ).
>>
>> a) For CMD38, select a fixed number maximum blocks to accept for
>> erase/discard/trim operations. Compute the needed timeout depending on each
>> card's erase information provided through it's CSD/EXT_CSD registers. Then
>> follow the same principle as for sending a CMD6.
>>
>> b) At least for CMD38, but likely for other commands as well, we could benefit
>> from doing a _periodic_ CMD13 polling to handle the busy completion. This will
>> also be useful for hosts supporting MMC_CAP_WAIT_WHILE_BUSY, in particular for
>> cases where the host are unable to support the needed busy timeout.
>>
>
> Do you have the plan to implement above two items?
Yes, it's on top of my TODO list for MMC. I really need to get this
done asap. Thanks for pinging me about this.
> Since currently the max_discard_sectors is still calculated based on
> max_busy_timeout of host,
> it is possible that for some eMMC chips, the max_discard_sectors is 1,
> which then cause the erase operation terribly slow.
Yes!
Another issue to fix is get MMC_CAP_ERASE removed - and that should be
possible once the above described problem has been solved.
Kind regards
Uffe
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY
2014-09-03 7:32 ` Ulf Hansson
2014-09-03 7:24 ` Dong Aisheng
@ 2014-09-05 9:29 ` Jaehoon Chung
2014-09-05 11:02 ` Ulf Hansson
1 sibling, 1 reply; 21+ messages in thread
From: Jaehoon Chung @ 2014-09-05 9:29 UTC (permalink / raw)
To: Ulf Hansson, Dong Aisheng
Cc: linux-mmc@vger.kernel.org, Chris Ball, Dong Aisheng,
Stephen Warren, Vladimir Zapolskiy, Adrian Hunter
Hi, Ulf.
On 09/03/2014 04:32 PM, Ulf Hansson wrote:
> On 3 September 2014 08:51, Dong Aisheng <dongas86@gmail.com> wrote:
>> Hi Ulf,
>>
>> On Thu, Jan 30, 2014 at 6:37 AM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>>> This patchset improves the handling around busy detection in the mmc core layer
>>> while operating on host supporting MMC_CAP_WAIT_WHILE_BUSY.
>>>
>>> A R1B response is for an mmc command, specified as and R1 but with an optional
>>> busy assertion on the DAT0 line. Hosts supporting MMC_CAP_WAIT_WHILE_BUSY,
>>> normally has a busy detection mechanism build in it's controller HW.
>>>
>>> Using such a feature decreases the need for polling of the card's status using
>>> CMD13, which is the fallback method used by the mmc core for hosts that don't
>>> support MMC_CAP_WAIT_WHILE_BUSY.
>>>
>>> Typcial commands that expects R1B responses are CMD6 (SWITCH), CMD12 (STOP),
>>> CMD38 (ERASE) and CMD5 (SLEEP). This patchset adresses CMD6, CMD5 and improves
>>> some parts where CMD12 are used. If the implemented approach becomes accepted,
>>> a future patchset for CMD38 can be based on top if this patchset.
>>>
>>> Do note, the final two patches implements support for busy detection for the
>>> mmci host driver, since some of it's HW variants do supports busy detection.
>>>
>>> Future suggested improvements related to this patchset: (Please, feel free to
>>> implement any of them :-) ).
>>>
>>> a) For CMD38, select a fixed number maximum blocks to accept for
>>> erase/discard/trim operations. Compute the needed timeout depending on each
>>> card's erase information provided through it's CSD/EXT_CSD registers. Then
>>> follow the same principle as for sending a CMD6.
>>>
>>> b) At least for CMD38, but likely for other commands as well, we could benefit
>>> from doing a _periodic_ CMD13 polling to handle the busy completion. This will
>>> also be useful for hosts supporting MMC_CAP_WAIT_WHILE_BUSY, in particular for
>>> cases where the host are unable to support the needed busy timeout.
>>>
>>
>> Do you have the plan to implement above two items?
>
> Yes, it's on top of my TODO list for MMC. I really need to get this
> done asap. Thanks for pinging me about this.
>
>> Since currently the max_discard_sectors is still calculated based on
>> max_busy_timeout of host,
>> it is possible that for some eMMC chips, the max_discard_sectors is 1,
>> which then cause the erase operation terribly slow.
>
> Yes!
>
> Another issue to fix is get MMC_CAP_ERASE removed - and that should be
> possible once the above described problem has been solved.
Did you send the patch V2 for this patch-set?
Best Regards,
Jaehoon Chung
>
> Kind regards
> Uffe
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY
2014-09-05 9:29 ` Jaehoon Chung
@ 2014-09-05 11:02 ` Ulf Hansson
0 siblings, 0 replies; 21+ messages in thread
From: Ulf Hansson @ 2014-09-05 11:02 UTC (permalink / raw)
To: Jaehoon Chung
Cc: Dong Aisheng, linux-mmc@vger.kernel.org, Chris Ball, Dong Aisheng,
Stephen Warren, Vladimir Zapolskiy, Adrian Hunter
On 5 September 2014 11:29, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> Hi, Ulf.
>
> On 09/03/2014 04:32 PM, Ulf Hansson wrote:
>> On 3 September 2014 08:51, Dong Aisheng <dongas86@gmail.com> wrote:
>>> Hi Ulf,
>>>
>>> On Thu, Jan 30, 2014 at 6:37 AM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>>>> This patchset improves the handling around busy detection in the mmc core layer
>>>> while operating on host supporting MMC_CAP_WAIT_WHILE_BUSY.
>>>>
>>>> A R1B response is for an mmc command, specified as and R1 but with an optional
>>>> busy assertion on the DAT0 line. Hosts supporting MMC_CAP_WAIT_WHILE_BUSY,
>>>> normally has a busy detection mechanism build in it's controller HW.
>>>>
>>>> Using such a feature decreases the need for polling of the card's status using
>>>> CMD13, which is the fallback method used by the mmc core for hosts that don't
>>>> support MMC_CAP_WAIT_WHILE_BUSY.
>>>>
>>>> Typcial commands that expects R1B responses are CMD6 (SWITCH), CMD12 (STOP),
>>>> CMD38 (ERASE) and CMD5 (SLEEP). This patchset adresses CMD6, CMD5 and improves
>>>> some parts where CMD12 are used. If the implemented approach becomes accepted,
>>>> a future patchset for CMD38 can be based on top if this patchset.
>>>>
>>>> Do note, the final two patches implements support for busy detection for the
>>>> mmci host driver, since some of it's HW variants do supports busy detection.
>>>>
>>>> Future suggested improvements related to this patchset: (Please, feel free to
>>>> implement any of them :-) ).
>>>>
>>>> a) For CMD38, select a fixed number maximum blocks to accept for
>>>> erase/discard/trim operations. Compute the needed timeout depending on each
>>>> card's erase information provided through it's CSD/EXT_CSD registers. Then
>>>> follow the same principle as for sending a CMD6.
>>>>
>>>> b) At least for CMD38, but likely for other commands as well, we could benefit
>>>> from doing a _periodic_ CMD13 polling to handle the busy completion. This will
>>>> also be useful for hosts supporting MMC_CAP_WAIT_WHILE_BUSY, in particular for
>>>> cases where the host are unable to support the needed busy timeout.
>>>>
>>>
>>> Do you have the plan to implement above two items?
>>
>> Yes, it's on top of my TODO list for MMC. I really need to get this
>> done asap. Thanks for pinging me about this.
>>
>>> Since currently the max_discard_sectors is still calculated based on
>>> max_busy_timeout of host,
>>> it is possible that for some eMMC chips, the max_discard_sectors is 1,
>>> which then cause the erase operation terribly slow.
>>
>> Yes!
>>
>> Another issue to fix is get MMC_CAP_ERASE removed - and that should be
>> possible once the above described problem has been solved.
>
> Did you send the patch V2 for this patch-set?
I assume you refer to:
[PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY
All those patches has been merged, but can't remember how many
iterations of them we required though. :-)
Kind regards
Uffe
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2014-09-05 11:02 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-29 22:37 [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Ulf Hansson
2014-01-29 22:37 ` [PATCH 01/13] mmc: core: Rename max_discard_to to max_busy_timeout Ulf Hansson
2014-01-29 22:37 ` [PATCH 02/13] mmc: core: Rename cmd_timeout_ms to busy_timeout Ulf Hansson
2014-01-29 22:37 ` [PATCH 03/13] mmc: core: Add ignore_crc flag to __mmc_switch Ulf Hansson
2014-01-29 22:37 ` [PATCH 04/13] mmc: core: Minor simplifications " Ulf Hansson
2014-01-29 22:37 ` [PATCH 05/13] mmc: core: Fixup busy detection for mmc switch operations Ulf Hansson
2014-01-29 22:37 ` [PATCH 06/13] mmc: core: Use generic CMD6 time while switching to eMMC HS200 mode Ulf Hansson
2014-01-29 22:37 ` [PATCH 07/13] mmc: core: Respect host's max_busy_timeout when sending sleep cmd Ulf Hansson
2014-01-29 22:38 ` [PATCH 08/13] mmc: block: Use R1 responses for stop cmds for read requests Ulf Hansson
2014-01-29 22:38 ` [PATCH 09/13] mmc: block: Implement card_busy_detect() for busy detection Ulf Hansson
2014-01-29 22:38 ` [PATCH 10/13] mmc: block: Respect hw busy detection in card_busy_detect() Ulf Hansson
2014-01-29 22:38 ` [PATCH 11/13] mmc: block: Fixup busy detection while invoking stop cmd at recovery Ulf Hansson
2014-01-29 22:38 ` [PATCH 12/13] mmc: mmci: Handle CMD irq before DATA irq Ulf Hansson
2014-02-12 13:17 ` Ulf Hansson
2014-01-29 22:38 ` [PATCH 13/13] mmc: mmci: Enable support for busy detection for ux500 variant Ulf Hansson
2014-02-12 13:20 ` Ulf Hansson
2014-09-03 6:51 ` [PATCH 00/13] mmc: Improve busy detection for MMC_CAP_WAIT_WHILE_BUSY Dong Aisheng
2014-09-03 7:32 ` Ulf Hansson
2014-09-03 7:24 ` Dong Aisheng
2014-09-05 9:29 ` Jaehoon Chung
2014-09-05 11:02 ` 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).