@@ -131,7 +131,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
if (mmc_can_erase(card)) {
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue);
- mq->queue->limits.max_discard_sectors = UINT_MAX;
+ /* get a suitable max_discard_sectors limitation */
+ ret = mmc_set_discard_limit(card);
+ if (ret > 0)
+ mq->queue->limits.max_discard_sectors = ret;
+ else
+ mq->queue->limits.max_discard_sectors = UINT_MAX;
+
if (card->erased_byte == 0)
mq->queue->limits.discard_zeroes_data = 1;
if (!mmc_can_trim(card) && is_power_of_2(card->erase_size)) {
@@ -1454,6 +1454,33 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
}
EXPORT_SYMBOL(mmc_erase_group_aligned);
+/*
+ * mmc_set_discard_limit: set the max_discard_sectors according
+ * to host controller timeout capability.
+ */
+int mmc_set_discard_limit(struct mmc_card *card)
+{
+ struct mmc_host *host;
+ unsigned int nr = 0;
+ host = card->host;
+ if (host->caps & MMC_CAP_ERASE_SINGLE) {
+ /*
+ * Have to set a small limitation for request queue
+ * to ensure that host controller won't generate a
+ * timeout interrupt during waiting, here let limitation
+ * to be 1 erase block. And this will let TRIM/ERASE
+ * performance lower.
+ */
+ nr = 1;
+ if (card->erase_shift)
+ nr <<= card->erase_shift;
+ else
+ nr *= card->erase_size;
+ }
+ return nr;
+}
+EXPORT_SYMBOL(mmc_set_discard_limit);
+
int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
{
struct mmc_command cmd;
@@ -1857,6 +1857,10 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
mmc->f_max = host->max_clk;
mmc->caps |= MMC_CAP_SDIO_IRQ;
+ mmc->caps |= MMC_CAP_ERASE;
+
+ if (host->quirks & SDHCI_QUIRK_FORCE_ERASE_SINGLE)
+ mmc->caps |= MMC_CAP_ERASE_SINGLE;
if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
@@ -152,6 +152,7 @@ extern int mmc_can_trim(struct mmc_card *card);
extern int mmc_can_secure_erase_trim(struct mmc_card *card);
extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
unsigned int nr);
+extern int mmc_set_discard_limit(struct mmc_card *card);
extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
@@ -168,6 +168,8 @@ struct mmc_host {
/* DDR mode at 1.8V */
#define MMC_CAP_1_2V_DDR (1 << 12) /* can support */
/* DDR mode at 1.2V */
+#define MMC_CAP_ERASE_SINGLE (1 << 13)
+ /* Erase signle erase block each time */
mmc_pm_flag_t pm_caps; /* supported pm features */
@@ -83,6 +83,8 @@ struct sdhci_host {
#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1<<28)
/* Controller doesn't have HISPD bit field in HI-SPEED SD card */
#define SDHCI_QUIRK_NO_HISPD_BIT (1<<29)
+/* Controller has an issue with erase/trim the whole device at one time */
+#define SDHCI_QUIRK_FORCE_ERASE_SINGLE (1<<30)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */