SD spec v5.1 adds discard support. The flows and commands matches those
in eMMC, Which leaves to set the appropriate discard arg in CMD38 if
DISCARD_SUPPORT (b313) is set in the SD_STATUS register.
We set this arg on card init: not in mmc_init_erase as one might expect
but arbitrarily once the card indicated its discard support. This is
because unlike erase, it doesn't really involve any logic, and we want
to avoid the unnecessary complication.
V2->v3:
The first 2 patches in the series got accepted.
Elaborate the changelog of some of the differences between discard and
erase. Clean some inconsistency in arg checking in mmc_erase().
Add a patch to set the timeout for sd discard.
V1->v2:
In the first patch, assign the discard arg for SD cards as well to keep
the code consistent. Rename "discard_arg" to "erase_arg", and elaborate
the change log.
Avri Altman (2):
mmc: core: Add discard support to sd
mmc: core: Add sd discard timeout
drivers/mmc/core/core.c | 15 +++++++++++----
drivers/mmc/core/sd.c | 10 +++++++++-
include/linux/mmc/sd.h | 1 +
3 files changed, 21 insertions(+), 5 deletions(-)
--
1.9.1
SD spec v5.1 adds discard support. The flows and commands are similar to
mmc, so just set the discard arg in CMD38.
A host which supports DISCARD shall check if the DISCARD_SUPPORT (b313)
is set in the SD_STATUS register. If the card does not support discard,
the host shall not issue DISCARD command, but ERASE command instead.
Post the DISCARD operation, the card may de-allocate the discarded
blocks partially or completely. So the host mustn't make any assumptions
concerning the content of the discarded region. This is unlike ERASE
command, in which the region is guaranteed to contain either '0's or
'1's, depends on the content of DATA_STAT_AFTER_ERASE (b55) in the scr
register.
One more important difference compared to ERASE is the busy timeout
which we will address on the next patch.
Signed-off-by: Avri Altman <[email protected]>
---
drivers/mmc/core/core.c | 8 ++++----
drivers/mmc/core/sd.c | 10 +++++++++-
include/linux/mmc/sd.h | 1 +
3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 0950edf..b7367ac 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1847,7 +1847,7 @@ static unsigned int mmc_align_erase_size(struct mmc_card *card,
* @card: card to erase
* @from: first sector to erase
* @nr: number of sectors to erase
- * @arg: erase command argument (SD supports only %SD_ERASE_ARG)
+ * @arg: erase command argument
*
* Caller must claim host before calling this function.
*/
@@ -1864,14 +1864,14 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
if (!card->erase_size)
return -EOPNOTSUPP;
- if (mmc_card_sd(card) && arg != SD_ERASE_ARG)
+ if (mmc_card_sd(card) && arg != SD_ERASE_ARG && arg != SD_DISCARD_ARG)
return -EOPNOTSUPP;
- if ((arg & MMC_SECURE_ARGS) &&
+ if (mmc_card_mmc(card) && (arg & MMC_SECURE_ARGS) &&
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN))
return -EOPNOTSUPP;
- if ((arg & MMC_TRIM_ARGS) &&
+ if (mmc_card_mmc(card) && (arg & MMC_TRIM_ARGS) &&
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN))
return -EOPNOTSUPP;
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index c2db94d..2b4fc22 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -231,6 +231,8 @@ static int mmc_read_ssr(struct mmc_card *card)
{
unsigned int au, es, et, eo;
__be32 *raw_ssr;
+ u32 resp[4] = {};
+ u8 discard_support;
int i;
if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
@@ -276,7 +278,13 @@ static int mmc_read_ssr(struct mmc_card *card)
}
}
- card->erase_arg = SD_ERASE_ARG;
+ /*
+ * starting SD5.1 discard is supported if DISCARD_SUPPORT (b313) is set
+ */
+ resp[3] = card->raw_ssr[6];
+ discard_support = UNSTUFF_BITS(resp, 313 - 288, 1);
+ card->erase_arg = (card->scr.sda_specx && discard_support) ?
+ SD_DISCARD_ARG : SD_ERASE_ARG;
return 0;
}
diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
index 1a6d10f..ec94a5a 100644
--- a/include/linux/mmc/sd.h
+++ b/include/linux/mmc/sd.h
@@ -95,5 +95,6 @@
* Erase/discard
*/
#define SD_ERASE_ARG 0x00000000
+#define SD_DISCARD_ARG 0x00000001
#endif /* LINUX_MMC_SD_H */
--
1.9.1
The busy timeout is 250msec per discard command.
Signed-off-by: Avri Altman <[email protected]>
---
drivers/mmc/core/core.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b7367ac..4979d4e 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -51,6 +51,7 @@
/* The max erase timeout, used when host->max_busy_timeout isn't specified */
#define MMC_ERASE_TIMEOUT_MS (60 * 1000) /* 60 s */
+#define SD_DISCARD_TIMEOUT_MS (250)
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
@@ -1619,6 +1620,12 @@ static unsigned int mmc_sd_erase_timeout(struct mmc_card *card,
{
unsigned int erase_timeout;
+ /* for DISCARD none of the below calculation applies.
+ * the busy timeout is 250msec per discard command.
+ */
+ if (arg == SD_DISCARD_ARG)
+ return SD_DISCARD_TIMEOUT_MS;
+
if (card->ssr.erase_timeout) {
/* Erase timeout specified in SD Status Register (SSR) */
erase_timeout = card->ssr.erase_timeout * qty +
--
1.9.1
On Tue, 26 Feb 2019 at 16:10, Avri Altman <[email protected]> wrote:
>
> SD spec v5.1 adds discard support. The flows and commands matches those
> in eMMC, Which leaves to set the appropriate discard arg in CMD38 if
> DISCARD_SUPPORT (b313) is set in the SD_STATUS register.
>
> We set this arg on card init: not in mmc_init_erase as one might expect
> but arbitrarily once the card indicated its discard support. This is
> because unlike erase, it doesn't really involve any logic, and we want
> to avoid the unnecessary complication.
>
> V2->v3:
> The first 2 patches in the series got accepted.
> Elaborate the changelog of some of the differences between discard and
> erase. Clean some inconsistency in arg checking in mmc_erase().
> Add a patch to set the timeout for sd discard.
>
> V1->v2:
> In the first patch, assign the discard arg for SD cards as well to keep
> the code consistent. Rename "discard_arg" to "erase_arg", and elaborate
> the change log.
>
>
> Avri Altman (2):
> mmc: core: Add discard support to sd
> mmc: core: Add sd discard timeout
>
> drivers/mmc/core/core.c | 15 +++++++++++----
> drivers/mmc/core/sd.c | 10 +++++++++-
> include/linux/mmc/sd.h | 1 +
> 3 files changed, 21 insertions(+), 5 deletions(-)
>
> --
> 1.9.1
>
Looks good, applied for next, thanks!
Kind regards
Uffe