X-Git-Url: http://plrg.eecs.uci.edu/git/?p=firefly-linux-kernel-4.4.55.git;a=blobdiff_plain;f=drivers%2Fmmc%2Fcore%2Fcore.c;h=5afb319bb40e2fcc2dd57357c8619c6304eb2308;hp=5ae89e48fd85b575cf743363b3a298b49872b7db;hb=64f9234b9b05d1df85baeba2a072b69ef435b4dc;hpb=3bea6a4c7895fc94965a219a8da9bcf753667901 diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5ae89e48fd85..5afb319bb40e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -30,6 +30,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include + #include #include #include @@ -46,6 +49,11 @@ #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; @@ -2832,17 +2869,29 @@ void mmc_init_context_info(struct mmc_host *host) init_waitqueue_head(&host->context_info.wait); } +#ifdef CONFIG_MMC_EMBEDDED_SDIO +void mmc_set_embedded_sdio_data(struct mmc_host *host, + struct sdio_cis *cis, + struct sdio_cccr *cccr, + struct sdio_embedded_func *funcs, + int num_funcs) +{ + host->embedded_sdio_data.cis = cis; + host->embedded_sdio_data.cccr = cccr; + host->embedded_sdio_data.funcs = funcs; + host->embedded_sdio_data.num_funcs = num_funcs; +} + +EXPORT_SYMBOL(mmc_set_embedded_sdio_data); +#endif + 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) @@ -2858,9 +2907,6 @@ unregister_host_class: mmc_unregister_host_class(); unregister_bus: mmc_unregister_bus(); -destroy_workqueue: - destroy_workqueue(workqueue); - return ret; } @@ -2869,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);