From 2220eedfd7aea69008173a224975e10284fbe854 Mon Sep 17 00:00:00 2001 From: Konstantin Dorfman Date: Mon, 14 Jan 2013 14:28:17 -0500 Subject: mmc: fix async request mechanism for sequential read scenarios When current request is running on the bus and if next request fetched by mmcqd is NULL, mmc context (mmcqd thread) gets blocked until the current request completes. This means that if new request comes in while the mmcqd thread is blocked, this new request can not be prepared in parallel to current ongoing request. This may result in delaying the new request execution and increase it's latency. This change allows to wake up the MMC thread on new request arrival. Now once the MMC thread is woken up, a new request can be fetched and prepared in parallel to the current running request which means this new request can be started immediately after the current running request completes. With this change read throughput is improved by 16%. Signed-off-by: Konstantin Dorfman Reviewed-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/core/core.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mmc/core/core.h') diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 3bdafbca354f..0272b3284b5e 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -76,5 +76,6 @@ void mmc_remove_host_debugfs(struct mmc_host *host); void mmc_add_card_debugfs(struct mmc_card *card); void mmc_remove_card_debugfs(struct mmc_card *card); +void mmc_init_context_info(struct mmc_host *host); #endif -- cgit v1.2.3 From 276e090f9217b69e46d8255132d2667ac5eec51b Mon Sep 17 00:00:00 2001 From: Johan Rudholm Date: Mon, 28 Jan 2013 15:08:25 +0100 Subject: mmc: core: Add mmc_power_cycle Add mmc_power_cycle which can be used to power cycle for instance SD-cards. Signed-off-by: Johan Rudholm Acked-by: Ulf Hansson Tested-by: Wei WANG Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 8 ++++++++ drivers/mmc/core/core.h | 1 + 2 files changed, 9 insertions(+) (limited to 'drivers/mmc/core/core.h') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 39f28af34cb6..789056fbfc93 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1470,6 +1470,14 @@ void mmc_power_off(struct mmc_host *host) mmc_host_clk_release(host); } +void mmc_power_cycle(struct mmc_host *host) +{ + mmc_power_off(host); + /* Wait at least 1 ms according to SD spec */ + mmc_delay(1); + mmc_power_up(host); +} + /* * Cleanup when the last reference to the bus operator is dropped. */ diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 0272b3284b5e..9007de74d8a9 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -45,6 +45,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, void mmc_set_timing(struct mmc_host *host, unsigned int timing); void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); void mmc_power_off(struct mmc_host *host); +void mmc_power_cycle(struct mmc_host *host); static inline void mmc_delay(unsigned int ms) { -- cgit v1.2.3 From 567c89032cfdda8047562abe450947ac01f2d3c7 Mon Sep 17 00:00:00 2001 From: Johan Rudholm Date: Mon, 28 Jan 2013 15:08:27 +0100 Subject: mmc: core: Break out start_signal_voltage_switch Allow callers to access the start_signal_voltage_switch host_ops member without going through any cmd11 logic. This is mostly a preparation for the following signal voltage switch patch. Also, reset ios.signal_voltage to its original value if start_signal_voltage_switch fails. Signed-off-by: Johan Rudholm Acked-by: Ulf Hansson Tested-by: Wei WANG Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 35 +++++++++++++++++++++++------------ drivers/mmc/core/core.h | 4 ++-- drivers/mmc/core/mmc.c | 8 ++++---- drivers/mmc/core/sd.c | 2 +- drivers/mmc/core/sdio.c | 3 +-- 5 files changed, 31 insertions(+), 21 deletions(-) (limited to 'drivers/mmc/core/core.h') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 789056fbfc93..bb794c784597 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1317,7 +1317,26 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) return ocr; } -int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11) +int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) +{ + int err = 0; + int old_signal_voltage = host->ios.signal_voltage; + + host->ios.signal_voltage = signal_voltage; + if (host->ops->start_signal_voltage_switch) { + mmc_host_clk_hold(host); + err = host->ops->start_signal_voltage_switch(host, &host->ios); + mmc_host_clk_release(host); + } + + if (err) + host->ios.signal_voltage = old_signal_voltage; + + return err; + +} + +int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) { struct mmc_command cmd = {0}; int err = 0; @@ -1328,7 +1347,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11 * Send CMD11 only if the request is to switch the card to * 1.8V signalling. */ - if ((signal_voltage != MMC_SIGNAL_VOLTAGE_330) && cmd11) { + if (signal_voltage != MMC_SIGNAL_VOLTAGE_330) { cmd.opcode = SD_SWITCH_VOLTAGE; cmd.arg = 0; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; @@ -1341,15 +1360,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11 return -EIO; } - host->ios.signal_voltage = signal_voltage; - - if (host->ops->start_signal_voltage_switch) { - mmc_host_clk_hold(host); - err = host->ops->start_signal_voltage_switch(host, &host->ios); - mmc_host_clk_release(host); - } - - return err; + return __mmc_set_signal_voltage(host, signal_voltage); } /* @@ -1412,7 +1423,7 @@ static void mmc_power_up(struct mmc_host *host) mmc_set_ios(host); /* Set signal voltage to 3.3V */ - mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, false); + __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); /* * This delay should be sufficient to allow the power supply diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 9007de74d8a9..b9f18a2a8874 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -40,8 +40,8 @@ void mmc_set_ungated(struct mmc_host *host); void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); -int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, - bool cmd11); +int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); +int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); void mmc_set_timing(struct mmc_host *host, unsigned int timing); void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); void mmc_power_off(struct mmc_host *host); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 0d7a9795a6da..8a3ad602a877 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -769,11 +769,11 @@ static int mmc_select_hs200(struct mmc_card *card) if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V && host->caps2 & MMC_CAP2_HS200_1_2V_SDR) - err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120, 0); + err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V && host->caps2 & MMC_CAP2_HS200_1_8V_SDR) - err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, 0); + err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); /* If fails try again during next card power cycle */ if (err) @@ -1221,8 +1221,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * WARNING: eMMC rules are NOT the same as SD DDR */ if (ddr == MMC_1_2V_DDR_MODE) { - err = mmc_set_signal_voltage(host, - MMC_SIGNAL_VOLTAGE_120, 0); + err = __mmc_set_signal_voltage(host, + MMC_SIGNAL_VOLTAGE_120); if (err) goto err; } diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 937363948079..9a59fcd55a75 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -757,7 +757,7 @@ try_again: */ if (!mmc_host_is_spi(host) && rocr && ((*rocr & 0x41000000) == 0x41000000)) { - err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, true); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); if (err) { ocr &= ~SD_OCR_S18R; goto try_again; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 3a64933466b8..1a726aef211d 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -647,8 +647,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, * it. */ if ((ocr & R4_18V_PRESENT) && mmc_host_uhs(host)) { - err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, - true); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); if (err) { ocr &= ~R4_18V_PRESENT; host->ocr &= ~R4_18V_PRESENT; -- cgit v1.2.3