@@ -131,7 +131,10 @@ 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 */
+ mq->queue->limits.max_discard_sectors =
+ mmc_set_discard_limit(card);
+
if (card->erased_byte == 0)
mq->queue->limits.discard_zeroes_data = 1;
if (!mmc_can_trim(card) && is_power_of_2(card->erase_size)) {
@@ -1469,6 +1469,39 @@ 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 erase capability.
+ * @card: card need to be erased
+ *
+ * Return value:
+ * positive value: one erase block size
+ * UINT_MAX: unlimitied value which means no limitation for
+ * max_discard_sectors
+ */
+int mmc_set_discard_limit(struct mmc_card *card)
+{
+ struct mmc_host *host;
+ unsigned int nr = UINT_MAX;
+ 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 erasing, here let limitation
+ * to be one erase block size.
+ * 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;
@@ -1875,6 +1875,10 @@ int sdhci_add_host(struct sdhci_host *host)
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;
/*
* A controller may support 8-bit width, but the board itself
@@ -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);
@@ -169,6 +169,8 @@ struct mmc_host {
#define MMC_CAP_1_2V_DDR (1 << 12) /* can support */
/* DDR mode at 1.2V */
#define MMC_CAP_POWER_OFF_CARD (1 << 13) /* Can power off after boot */
+#define MMC_CAP_ERASE_SINGLE (1 << 14)
+ /* 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 */