diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-21 12:04:54 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-21 12:04:54 -0800 |
commit | e67bd12d6036ae3de9eeb0ba52e43691264ec850 (patch) | |
tree | 0232867e68e2b56fd601f7c31b0d5f87d7ec3792 /drivers/mmc/core/core.c | |
parent | cdc194705d26fdd7fc5446b5d830f2bbe2b22c30 (diff) | |
parent | 8c7cdbf9272c300dc093da3c62fa3b4bc6dc960e (diff) | |
download | linux-e67bd12d6036ae3de9eeb0ba52e43691264ec850.tar.bz2 |
Merge tag 'mmc-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"MMC core:
- Add support for Marvell SD8787 Wifi/BT chip
- Improve UHS support for SDIO
- Invent MMC_CAP_3_3V_DDR and a DT binding for eMMC DDR 3.3V mode
- Detect Auto BKOPS enable bit
- Export eMMC device lifetime information through sysfs
- First take to slim down the public mmc headers to avoid abuse
- Re-factoring of the mmc block device driver to prepare for blkmq
- Cleanup code for the mmc block device driver
- Clarify and cleanup code dealing with data requests
- Cleanup some code by converting to ida_simple_ functions
- Cleanup code dealing with card quirks
- Cleanup private and public mmc header files
MMC host:
- Don't rely on public mmc headers to include non-mmc related headers
- meson: Add support for eMMC HS400 mode
- meson: Various cleanups and improvements
- omap_hsmmc: Use the proper provided busy timeout from the core
- sunxi: Enable new timings for the A64 MMC controllers
- sunxi: Improvements for clock management
- tmio: Improvements for SDIO interrupts
- mxs-mmc: Add CMD23 support
- sdhci-msm: Enable HS400 enhanced strobe mode support
- sdhci-msm: Correct HS400 tuning sequence
- sdhci-acpi: Support deferred probe
- sdhci-pci: Add support for eMMC HS200 tuning mode on AMD
- mediatek: Correct the implementation of card busy detection
- dw_mmc: Initial support for ZX mmc controller
- sh_mobile_sdhi: Enable support for eMMC HS200 mode
- sh_mmcif: Various cleanups and improvements"
* tag 'mmc-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (145 commits)
mmc: core: add mmc prefix for blk_fixups
mmc: core: move all quirks together into quirks.h
mmc: core: improve the quirks for sdio devices
mmc: core: move some sdio IDs out of quirks file
mmc: core: change quirks.c to be a header file
mmc: sdhci-cadence: fix bit shift of read data from PHY port
mmc: Adding AUTO_BKOPS_EN bit set for Auto BKOPS support
mmc: MAN_BKOPS_EN inverse debug message logic
mmc: meson-gx: add support for HS400 mode
mmc: meson-gx: remove unneeded checks in remove
mmc: meson-gx: reduce bounce buffer size
mmc: meson-gx: set max block count and request size
mmc: meson-gx: improve interrupt handling
mmc: meson-gx: improve meson_mmc_irq_thread
mmc: meson-gx: improve meson_mmc_clk_set
mmc: meson-gx: minor improvements in meson_mmc_set_ios
mmc: meson: Assign the minimum clk rate as close to 400KHz as possible
mmc: core: start to break apart mmc_start_areq()
mmc: block: respect bool returned from blk_end_request()
mmc: block: return errorcode from mmc_sd_num_wr_blocks()
...
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r-- | drivers/mmc/core/core.c | 116 |
1 files changed, 61 insertions, 55 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 1076b9d89df3..926e0fde07d7 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -40,6 +40,7 @@ #include <trace/events/mmc.h> #include "core.h" +#include "card.h" #include "bus.h" #include "host.h" #include "sdio_bus.h" @@ -630,10 +631,41 @@ static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, } /** - * mmc_start_req - start a non-blocking request + * mmc_finalize_areq() - finalize an asynchronous request + * @host: MMC host to finalize any ongoing request on + * + * Returns the status of the ongoing asynchronous request, but + * MMC_BLK_SUCCESS if no request was going on. + */ +static enum mmc_blk_status mmc_finalize_areq(struct mmc_host *host) +{ + enum mmc_blk_status status; + + if (!host->areq) + return MMC_BLK_SUCCESS; + + status = mmc_wait_for_data_req_done(host, host->areq->mrq); + if (status == MMC_BLK_NEW_REQUEST) + return status; + + /* + * Check BKOPS urgency for each R1 response + */ + if (host->card && mmc_card_mmc(host->card) && + ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) || + (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) && + (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) { + mmc_start_bkops(host->card, true); + } + + return status; +} + +/** + * mmc_start_areq - start an asynchronous request * @host: MMC host to start command - * @areq: async request to start - * @error: out parameter returns 0 for success, otherwise non zero + * @areq: asynchronous request to start + * @ret_stat: out parameter for status * * Start a new MMC custom command request for a host. * If there is on ongoing async request wait for completion @@ -645,11 +677,11 @@ static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, * return the completed request. If there is no ongoing request, NULL * is returned without waiting. NULL is not an error condition. */ -struct mmc_async_req *mmc_start_req(struct mmc_host *host, - struct mmc_async_req *areq, - enum mmc_blk_status *ret_stat) +struct mmc_async_req *mmc_start_areq(struct mmc_host *host, + struct mmc_async_req *areq, + enum mmc_blk_status *ret_stat) { - enum mmc_blk_status status = MMC_BLK_SUCCESS; + enum mmc_blk_status status; int start_err = 0; struct mmc_async_req *data = host->areq; @@ -657,44 +689,25 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, if (areq) mmc_pre_req(host, areq->mrq); - if (host->areq) { - status = mmc_wait_for_data_req_done(host, host->areq->mrq); - if (status == MMC_BLK_NEW_REQUEST) { - if (ret_stat) - *ret_stat = status; - /* - * The previous request was not completed, - * nothing to return - */ - return NULL; - } - /* - * Check BKOPS urgency for each R1 response - */ - if (host->card && mmc_card_mmc(host->card) && - ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) || - (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) && - (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) { - - /* Cancel the prepared request */ - if (areq) - mmc_post_req(host, areq->mrq, -EINVAL); - - mmc_start_bkops(host->card, true); + /* Finalize previous request */ + status = mmc_finalize_areq(host); - /* prepare the request again */ - if (areq) - mmc_pre_req(host, areq->mrq); - } + /* The previous request is still going on... */ + if (status == MMC_BLK_NEW_REQUEST) { + if (ret_stat) + *ret_stat = status; + return NULL; } + /* Fine so far, start the new request! */ if (status == MMC_BLK_SUCCESS && areq) start_err = __mmc_start_data_req(host, areq->mrq); + /* Postprocess the old request at this point */ if (host->areq) mmc_post_req(host, host->areq->mrq, 0); - /* Cancel a prepared request if it was not started. */ + /* Cancel a prepared request if it was not started. */ if ((status != MMC_BLK_SUCCESS || start_err) && areq) mmc_post_req(host, areq->mrq, -EINVAL); @@ -707,7 +720,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, *ret_stat = status; return data; } -EXPORT_SYMBOL(mmc_start_req); +EXPORT_SYMBOL(mmc_start_areq); /** * mmc_wait_for_req - start a request and wait for completion @@ -807,7 +820,7 @@ EXPORT_SYMBOL(mmc_interrupt_hpi); */ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries) { - struct mmc_request mrq = {NULL}; + struct mmc_request mrq = {}; WARN_ON(!host->claimed); @@ -1630,7 +1643,7 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) return ocr; } -int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) +int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) { int err = 0; int old_signal_voltage = host->ios.signal_voltage; @@ -1646,20 +1659,13 @@ int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) } -int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) +int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) { - struct mmc_command cmd = {0}; + struct mmc_command cmd = {}; int err = 0; u32 clock; /* - * Send CMD11 only if the request is to switch the card to - * 1.8V signalling. - */ - if (signal_voltage == MMC_SIGNAL_VOLTAGE_330) - return __mmc_set_signal_voltage(host, signal_voltage); - - /* * If we cannot switch voltages, return failure so the caller * can continue without UHS mode */ @@ -1697,7 +1703,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) host->ios.clock = 0; mmc_set_ios(host); - if (__mmc_set_signal_voltage(host, signal_voltage)) { + if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) { /* * Voltages may not have been switched, but we've already * sent CMD11, so a power cycle is required anyway @@ -1806,11 +1812,11 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) mmc_set_initial_state(host); /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ - if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0) + if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330)) dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n"); - else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180) == 0) + else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n"); - else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120) == 0) + else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120)) dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n"); /* @@ -2129,7 +2135,7 @@ static unsigned int mmc_erase_timeout(struct mmc_card *card, static int mmc_do_erase(struct mmc_card *card, unsigned int from, unsigned int to, unsigned int arg) { - struct mmc_command cmd = {0}; + struct mmc_command cmd = {}; unsigned int qty = 0, busy_timeout = 0; bool use_r1b_resp = false; unsigned long timeout; @@ -2551,7 +2557,7 @@ EXPORT_SYMBOL(mmc_calc_max_discard); int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) { - struct mmc_command cmd = {0}; + struct mmc_command cmd = {}; if (mmc_card_blockaddr(card) || mmc_card_ddr52(card) || mmc_card_hs400(card) || mmc_card_hs400es(card)) @@ -2567,7 +2573,7 @@ EXPORT_SYMBOL(mmc_set_blocklen); int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount, bool is_rel_write) { - struct mmc_command cmd = {0}; + struct mmc_command cmd = {}; cmd.opcode = MMC_SET_BLOCK_COUNT; cmd.arg = blockcount & 0x0000FFFF; |