mmc: core: keep consistent with upstream
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / core / core.c
index 1e2e1a8f8872e26c7b84d2b4db9dd542a2d843fe..5afb319bb40e2fcc2dd57357c8619c6304eb2308 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/mmc.h>
+
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include "sd_ops.h"
 #include "sdio_ops.h"
 
+EXPORT_TRACEPOINT_SYMBOL_GPL(mmc_blk_erase_start);
+EXPORT_TRACEPOINT_SYMBOL_GPL(mmc_blk_erase_end);
+EXPORT_TRACEPOINT_SYMBOL_GPL(mmc_blk_rw_start);
+EXPORT_TRACEPOINT_SYMBOL_GPL(mmc_blk_rw_end);
+
 /* If the device is not responding */
 #define MMC_CORE_TIMEOUT_MS    (10 * 60 * 1000) /* 10 minute timeout */
 
@@ -55,7 +63,6 @@
  */
 #define MMC_BKOPS_MAX_TIMEOUT  (4 * 60 * 1000) /* max time to wait in ms */
 
-static struct workqueue_struct *workqueue;
 static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
 
 /*
@@ -66,21 +73,16 @@ static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
 bool use_spi_crc = 1;
 module_param(use_spi_crc, bool, 0);
 
-/*
- * Internal function. Schedule delayed work in the MMC work queue.
- */
 static int mmc_schedule_delayed_work(struct delayed_work *work,
                                     unsigned long delay)
 {
-       return queue_delayed_work(workqueue, work, delay);
-}
-
-/*
- * Internal function. Flush all scheduled work from the MMC work queue.
- */
-static void mmc_flush_scheduled_work(void)
-{
-       flush_workqueue(workqueue);
+       /*
+        * We use the system_freezable_wq, because of two reasons.
+        * First, it allows several works (not the same work item) to be
+        * executed simultaneously. Second, the queue becomes frozen when
+        * userspace becomes frozen during system PM.
+        */
+       return queue_delayed_work(system_freezable_wq, work, delay);
 }
 
 #ifdef CONFIG_FAIL_MMC_REQUEST
@@ -175,6 +177,7 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
                        pr_debug("%s:     %d bytes transferred: %d\n",
                                mmc_hostname(host),
                                mrq->data->bytes_xfered, mrq->data->error);
+                       trace_mmc_blk_rw_end(cmd->opcode, cmd->arg, mrq->data);
                }
 
                if (mrq->stop) {
@@ -617,8 +620,12 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
                }
        }
 
-       if (!err && areq)
+       if (!err && areq) {
+               trace_mmc_blk_rw_start(areq->mrq->cmd->opcode,
+                                      areq->mrq->cmd->arg,
+                                      areq->mrq->data);
                start_err = __mmc_start_data_req(host, areq->mrq);
+       }
 
        if (host->areq)
                mmc_post_req(host, host->areq->mrq, 0);
@@ -1125,6 +1132,11 @@ void mmc_set_initial_state(struct mmc_host *host)
        host->ios.bus_width = MMC_BUS_WIDTH_1;
        host->ios.timing = MMC_TIMING_LEGACY;
        host->ios.drv_type = 0;
+       host->ios.enhanced_strobe = false;
+
+       if ((host->caps2 & MMC_CAP2_HS400_ES) &&
+               host->ops->hs400_enhanced_strobe)
+               host->ops->hs400_enhanced_strobe(host, &host->ios);
 
        mmc_set_ios(host);
 }
@@ -2055,8 +2067,13 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
        struct mmc_command cmd = {0};
        unsigned int qty = 0;
        unsigned long timeout;
+       unsigned int fr, nr;
        int err;
 
+       fr = from;
+       nr = to - from + 1;
+       trace_mmc_blk_erase_start(arg, fr, nr);
+
        mmc_retune_hold(card->host);
 
        /*
@@ -2163,6 +2180,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
                 (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG));
 out:
        mmc_retune_release(card->host);
+       trace_mmc_blk_erase_end(arg, fr, nr);
        return err;
 }
 
@@ -2477,6 +2495,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
         * if the card is being re-initialized, just send it.  CMD52
         * should be ignored by SD/eMMC cards.
         */
+#ifdef MMC_STANDARD_PROBE
        sdio_reset(host);
        mmc_go_idle(host);
 
@@ -2489,7 +2508,26 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
                return 0;
        if (!mmc_attach_mmc(host))
                return 0;
+#else
+       if (host->restrict_caps & RESTRICT_CARD_TYPE_SDIO)
+               sdio_reset(host);
+
+       mmc_go_idle(host);
 
+       if (host->restrict_caps &
+           (RESTRICT_CARD_TYPE_SDIO | RESTRICT_CARD_TYPE_SD))
+               mmc_send_if_cond(host, host->ocr_avail);
+       /* Order's important: probe SDIO, then SD, then MMC */
+       if ((host->restrict_caps & RESTRICT_CARD_TYPE_SDIO) &&
+           !mmc_attach_sdio(host))
+               return 0;
+       if ((host->restrict_caps & RESTRICT_CARD_TYPE_SD) &&
+            !mmc_attach_sd(host))
+               return 0;
+       if ((host->restrict_caps & RESTRICT_CARD_TYPE_EMMC) &&
+            !mmc_attach_mmc(host))
+               return 0;
+#endif
        mmc_power_off(host);
        return -EIO;
 }
@@ -2663,7 +2701,6 @@ void mmc_stop_host(struct mmc_host *host)
 
        host->rescan_disable = 1;
        cancel_delayed_work_sync(&host->detect);
-       mmc_flush_scheduled_work();
 
        /* clear pm flags now and let card drivers set them as needed */
        host->pm_flags = 0;
@@ -2852,13 +2889,9 @@ static int __init mmc_init(void)
 {
        int ret;
 
-       workqueue = alloc_ordered_workqueue("kmmcd", 0);
-       if (!workqueue)
-               return -ENOMEM;
-
        ret = mmc_register_bus();
        if (ret)
-               goto destroy_workqueue;
+               return ret;
 
        ret = mmc_register_host_class();
        if (ret)
@@ -2874,9 +2907,6 @@ unregister_host_class:
        mmc_unregister_host_class();
 unregister_bus:
        mmc_unregister_bus();
-destroy_workqueue:
-       destroy_workqueue(workqueue);
-
        return ret;
 }
 
@@ -2885,7 +2915,6 @@ static void __exit mmc_exit(void)
        sdio_unregister_bus();
        mmc_unregister_host_class();
        mmc_unregister_bus();
-       destroy_workqueue(workqueue);
 }
 
 subsys_initcall(mmc_init);