Micron MTFC4GACAJCN eMMC supports cache but requires that flush cache
operation be allowed only after a write has occurred. Otherwise, the
cache flush command or subsequent commands will time out.
Signed-off-by: Bean Huo <beanhuo@micron.com>
Signed-off-by: Rafael Beims <rafael.beims@toradex.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20231030224809.59245-1-beanhuo@iokpp.de
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
 
                        }
                        ret = mmc_blk_cqe_issue_flush(mq, req);
                        break;
-               case REQ_OP_READ:
                case REQ_OP_WRITE:
+                       card->written_flag = true;
+                       fallthrough;
+               case REQ_OP_READ:
                        if (host->cqe_enabled)
                                ret = mmc_blk_cqe_issue_rw_rq(mq, req);
                        else
 
        return c->quirks & MMC_QUIRK_BROKEN_SD_CACHE;
 }
 
+static inline int mmc_card_broken_cache_flush(const struct mmc_card *c)
+{
+       return c->quirks & MMC_QUIRK_BROKEN_CACHE_FLUSH;
+}
 #endif
 
 {
        int err = 0;
 
+       if (mmc_card_broken_cache_flush(host->card) && !host->card->written_flag)
+               return 0;
+
        if (_mmc_cache_enabled(host)) {
                err = mmc_switch(host->card, EXT_CSD_CMD_SET_NORMAL,
                                 EXT_CSD_FLUSH_CACHE, 1,
                                 CACHE_FLUSH_TIMEOUT_MS);
                if (err)
-                       pr_err("%s: cache flush error %d\n",
-                              mmc_hostname(host), err);
+                       pr_err("%s: cache flush error %d\n", mmc_hostname(host), err);
+               else
+                       host->card->written_flag = false;
        }
 
        return err;
 
                  MMC_QUIRK_TRIM_BROKEN),
 
        /*
-        * Micron MTFC4GACAJCN-1M advertises TRIM but it does not seems to
-        * support being used to offload WRITE_ZEROES.
+        * Micron MTFC4GACAJCN-1M supports TRIM but does not appear to support
+        * WRITE_ZEROES offloading. It also supports caching, but the cache can
+        * only be flushed after a write has occurred.
         */
        MMC_FIXUP("Q2J54A", CID_MANFID_MICRON, 0x014e, add_quirk_mmc,
-                 MMC_QUIRK_TRIM_BROKEN),
+                 MMC_QUIRK_TRIM_BROKEN | MMC_QUIRK_BROKEN_CACHE_FLUSH),
 
        /*
         * Kingston EMMC04G-M627 advertises TRIM but it does not seems to
 
 #define MMC_QUIRK_BROKEN_HPI   (1<<13)         /* Disable broken HPI support */
 #define MMC_QUIRK_BROKEN_SD_DISCARD    (1<<14) /* Disable broken SD discard support */
 #define MMC_QUIRK_BROKEN_SD_CACHE      (1<<15) /* Disable broken SD cache support */
+#define MMC_QUIRK_BROKEN_CACHE_FLUSH   (1<<16) /* Don't flush cache until the write has occurred */
 
+       bool                    written_flag;   /* Indicates eMMC has been written since power on */
        bool                    reenable_cmdq;  /* Re-enable Command Queue */
 
        unsigned int            erase_size;     /* erase size in sectors */