diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-13 08:34:11 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-13 08:34:11 -0800 |
| commit | 5233c331cfb41433bc167fc7c70ea67c1133ffec (patch) | |
| tree | 1ab0da40a3069c54e41a2aed8a0ada8ddb325e46 /drivers/mmc/core | |
| parent | Merge tag 'regulator-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
| parent | mmc: sdhci-cadence: add Cadence SD4HC support (diff) | |
| download | linux-5233c331cfb41433bc167fc7c70ea67c1133ffec.tar.gz linux-5233c331cfb41433bc167fc7c70ea67c1133ffec.zip | |
Merge tag 'mmc-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"It's been an busy period for mmc. Quite some changes in the mmc core,
two new mmc host drivers, some existing drivers being extended to
support new IP versions and lots of other updates.
MMC core:
- Delete eMMC packed command support
- Introduce mmc_abort_tuning() to enable eMMC tuning to fail
gracefully
- Introduce mmc_can_retune() to see if a host can be retuned
- Re-work and improve the sequence when sending a CMD6 for mmc
- Enable CDM13 polling when switching to HS and HS DDR mode for mmc
- Relax checking for CMD6 errors after switch to HS200
- Re-factoring the code dealing with the mmc block queue
- Recognize whether the eMMC card supports CMDQ
- Fix 4K native sector check
- Don't power off the card when starting the host
- Increase MMC_IOC_MAX_BYTES to support bigger firmware binaries
- Improve error handling and drop meaningless BUG_ONs()
- Lots of clean-ups and changes to improve the quality of the code
MMC host:
- sdhci: Fix tuning sequence and clean-up the related code
- sdhci: Add support to via DT override broken SDHCI cap register
bits
- sdhci-cadence: Add new driver for Cadence SD4HC SDHCI variant
- sdhci-msm: Update clock management
- sdhci-msm: Add support for eMMC HS400 mode
- sdhci-msm: Deploy runtime/system PM support
- sdhci-iproc: Extend driver support to newer IP versions
- sdhci-pci: Add support for Intel GLK
- sdhci-pci: Add support for Intel NI byt sdio
- sdhci-acpi: Add support for 80860F14 UID 2 SDIO bus
- sdhci: Lots of various small improvements and clean-ups
- tmio: Add support for tuning
- sh_mobile_sdhi: Add support for tuning
- sh_mobile_sdhi: Extend driver to support SDHI IP on R7S72100 SoC
- sh_mobile_sdhi: remove support for sh7372
- davinci: Use mmc_of_parse() to enable generic mmc DT bindings
- meson: Add new driver to support GX platforms
- dw_mmc: Deploy generic runtime/system PM support
- dw_mmc: Lots of various small improvements
As a part of the mmc changes this time, I have also pulled in an
immutable branch/tag (soc-device-match-tag1) hosted by Geert
Uytterhoeven, to share the implementation of the new
soc_device_match() interface. This is needed by these mmc related
changes:
- mmc: sdhci-of-esdhc: Get correct IP version for T4240-R1.0-R2.0
- soc: fsl: add GUTS driver for QorIQ platforms"
* tag 'mmc-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (136 commits)
mmc: sdhci-cadence: add Cadence SD4HC support
mmc: sdhci: export sdhci_execute_tuning()
mmc: sdhci: Tidy tuning loop
mmc: sdhci: Simplify tuning block size logic
mmc: sdhci: Factor out tuning helper functions
mmc: sdhci: Use mmc_abort_tuning()
mmc: mmc: Introduce mmc_abort_tuning()
mmc: sdhci: Always allow tuning to fall back to fixed sampling
mmc: sdhci: Fix tuning reset after exhausting the maximum number of loops
mmc: sdhci: Fix recovery from tuning timeout
Revert "mmc: sdhci: Reset cmd and data circuits after tuning failure"
mmc: mmc: Relax checking for switch errors after HS200 switch
mmc: sdhci-acpi: support 80860F14 UID 2 SDIO bus
mmc: sdhci-of-at91: remove bogus MMC_SDHCI_IO_ACCESSORS select
mmc: sdhci-pci: Use ACPI to get max frequency for Intel NI byt sdio
mmc: sdhci-pci: Add PCI ID for Intel NI byt sdio
mmc: sdhci-s3c: add spin_unlock_irq() before calling clk_round_rate
mmc: dw_mmc: display the clock message only one time when card is polling
mmc: dw_mmc: add the debug message for polling and non-removable
mmc: dw_mmc: check the "present" variable before checking flags
...
Diffstat (limited to 'drivers/mmc/core')
| -rw-r--r-- | drivers/mmc/core/core.c | 97 | ||||
| -rw-r--r-- | drivers/mmc/core/debugfs.c | 6 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc.c | 113 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc_ops.c | 220 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc_ops.h | 7 | ||||
| -rw-r--r-- | drivers/mmc/core/sd.c | 14 | ||||
| -rw-r--r-- | drivers/mmc/core/sd_ops.c | 27 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio.c | 17 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio_cis.c | 3 | ||||
| -rw-r--r-- | drivers/mmc/core/sdio_irq.c | 12 | ||||
| -rw-r--r-- | drivers/mmc/core/slot-gpio.c | 8 |
11 files changed, 257 insertions, 267 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 2553d903a82b..543eadd230e5 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -306,16 +306,16 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mrq->sbc->mrq = mrq; } if (mrq->data) { - BUG_ON(mrq->data->blksz > host->max_blk_size); - BUG_ON(mrq->data->blocks > host->max_blk_count); - BUG_ON(mrq->data->blocks * mrq->data->blksz > - host->max_req_size); - + if (mrq->data->blksz > host->max_blk_size || + mrq->data->blocks > host->max_blk_count || + mrq->data->blocks * mrq->data->blksz > host->max_req_size) + return -EINVAL; #ifdef CONFIG_MMC_DEBUG sz = 0; for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i) sz += sg->length; - BUG_ON(sz != mrq->data->blocks * mrq->data->blksz); + if (sz != mrq->data->blocks * mrq->data->blksz) + return -EINVAL; #endif mrq->cmd->data = mrq->data; @@ -349,8 +349,6 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) int timeout; bool use_busy_signal; - BUG_ON(!card); - if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card)) return; @@ -380,7 +378,7 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) mmc_retune_hold(card->host); err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BKOPS_START, 1, timeout, + EXT_CSD_BKOPS_START, 1, timeout, 0, use_busy_signal, true, false); if (err) { pr_warn("%s: Error %d starting bkops\n", @@ -497,32 +495,28 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) * * Returns enum mmc_blk_status after checking errors. */ -static int mmc_wait_for_data_req_done(struct mmc_host *host, +static enum mmc_blk_status mmc_wait_for_data_req_done(struct mmc_host *host, struct mmc_request *mrq, struct mmc_async_req *next_req) { struct mmc_command *cmd; struct mmc_context_info *context_info = &host->context_info; - int err; - unsigned long flags; + enum mmc_blk_status status; while (1) { wait_event_interruptible(context_info->wait, (context_info->is_done_rcv || context_info->is_new_req)); - spin_lock_irqsave(&context_info->lock, flags); context_info->is_waiting_last_req = false; - spin_unlock_irqrestore(&context_info->lock, flags); if (context_info->is_done_rcv) { context_info->is_done_rcv = false; - context_info->is_new_req = false; cmd = mrq->cmd; if (!cmd->error || !cmd->retries || mmc_card_removed(host->card)) { - err = host->areq->err_check(host->card, - host->areq); - break; /* return err */ + status = host->areq->err_check(host->card, + host->areq); + break; /* return status */ } else { mmc_retune_recheck(host); pr_info("%s: req failed (CMD%u): %d, retrying...\n", @@ -534,13 +528,12 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, continue; /* wait for done/new event again */ } } else if (context_info->is_new_req) { - context_info->is_new_req = false; if (!next_req) return MMC_BLK_NEW_REQUEST; } } mmc_retune_release(host); - return err; + return status; } void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) @@ -611,18 +604,15 @@ EXPORT_SYMBOL(mmc_is_req_done); * mmc_pre_req - Prepare for a new request * @host: MMC host to prepare command * @mrq: MMC request to prepare for - * @is_first_req: true if there is no previous started request - * that may run in parellel to this call, otherwise false * * mmc_pre_req() is called in prior to mmc_start_req() to let * host prepare for the new request. Preparation of a request may be * performed while another request is running on the host. */ -static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, - bool is_first_req) +static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq) { if (host->ops->pre_req) - host->ops->pre_req(host, mrq, is_first_req); + host->ops->pre_req(host, mrq); } /** @@ -658,21 +648,22 @@ static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, * 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, int *error) + struct mmc_async_req *areq, + enum mmc_blk_status *ret_stat) { - int err = 0; + enum mmc_blk_status status = MMC_BLK_SUCCESS; int start_err = 0; struct mmc_async_req *data = host->areq; /* Prepare a new request */ if (areq) - mmc_pre_req(host, areq->mrq, !host->areq); + mmc_pre_req(host, areq->mrq); if (host->areq) { - err = mmc_wait_for_data_req_done(host, host->areq->mrq, areq); - if (err == MMC_BLK_NEW_REQUEST) { - if (error) - *error = err; + status = mmc_wait_for_data_req_done(host, host->areq->mrq, areq); + if (status == MMC_BLK_NEW_REQUEST) { + if (ret_stat) + *ret_stat = status; /* * The previous request was not completed, * nothing to return @@ -695,27 +686,27 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, /* prepare the request again */ if (areq) - mmc_pre_req(host, areq->mrq, !host->areq); + mmc_pre_req(host, areq->mrq); } } - if (!err && areq) + if (status == MMC_BLK_SUCCESS && areq) start_err = __mmc_start_data_req(host, areq->mrq); if (host->areq) mmc_post_req(host, host->areq->mrq, 0); /* Cancel a prepared request if it was not started. */ - if ((err || start_err) && areq) + if ((status != MMC_BLK_SUCCESS || start_err) && areq) mmc_post_req(host, areq->mrq, -EINVAL); - if (err) + if (status != MMC_BLK_SUCCESS) host->areq = NULL; else host->areq = areq; - if (error) - *error = err; + if (ret_stat) + *ret_stat = status; return data; } EXPORT_SYMBOL(mmc_start_req); @@ -754,8 +745,6 @@ int mmc_interrupt_hpi(struct mmc_card *card) u32 status; unsigned long prg_wait; - BUG_ON(!card); - if (!card->ext_csd.hpi_en) { pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host)); return 1; @@ -850,7 +839,6 @@ int mmc_stop_bkops(struct mmc_card *card) { int err = 0; - BUG_ON(!card); err = mmc_interrupt_hpi(card); /* @@ -1666,8 +1654,6 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) int err = 0; u32 clock; - BUG_ON(!host); - /* * Send CMD11 only if the request is to switch the card to * 1.8V signalling. @@ -1884,9 +1870,7 @@ void mmc_power_cycle(struct mmc_host *host, u32 ocr) */ static void __mmc_release_bus(struct mmc_host *host) { - BUG_ON(!host); - BUG_ON(host->bus_refs); - BUG_ON(!host->bus_dead); + WARN_ON(!host->bus_dead); host->bus_ops = NULL; } @@ -1926,15 +1910,12 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) { unsigned long flags; - BUG_ON(!host); - BUG_ON(!ops); - WARN_ON(!host->claimed); spin_lock_irqsave(&host->lock, flags); - BUG_ON(host->bus_ops); - BUG_ON(host->bus_refs); + WARN_ON(host->bus_ops); + WARN_ON(host->bus_refs); host->bus_ops = ops; host->bus_refs = 1; @@ -1950,8 +1931,6 @@ void mmc_detach_bus(struct mmc_host *host) { unsigned long flags; - BUG_ON(!host); - WARN_ON(!host->claimed); WARN_ON(!host->bus_ops); @@ -2824,12 +2803,11 @@ void mmc_start_host(struct mmc_host *host) host->rescan_disable = 0; host->ios.power_mode = MMC_POWER_UNDEFINED; - mmc_claim_host(host); - if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP) - mmc_power_off(host); - else + if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) { + mmc_claim_host(host); mmc_power_up(host, host->ocr_avail); - mmc_release_host(host); + mmc_release_host(host); + } mmc_gpiod_request_cd_irq(host); _mmc_detect_change(host, 0, false); @@ -2865,8 +2843,6 @@ void mmc_stop_host(struct mmc_host *host) } mmc_bus_put(host); - BUG_ON(host->card); - mmc_claim_host(host); mmc_power_off(host); mmc_release_host(host); @@ -3019,7 +2995,6 @@ void mmc_unregister_pm_notifier(struct mmc_host *host) */ void mmc_init_context_info(struct mmc_host *host) { - spin_lock_init(&host->context_info.lock); host->context_info.is_new_req = false; host->context_info.is_done_rcv = false; host->context_info.is_waiting_last_req = false; diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index c8451ce557ae..30623b8b86a4 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -321,7 +321,11 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp) for (i = 0; i < 512; i++) n += sprintf(buf + n, "%02x", ext_csd[i]); n += sprintf(buf + n, "\n"); - BUG_ON(n != EXT_CSD_STR_LEN); + + if (n != EXT_CSD_STR_LEN) { + err = -EINVAL; + goto out_free; + } filp->private_data = buf; kfree(ext_csd); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index df19777068a6..b61b52f9da3d 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -618,6 +618,24 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) (ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) && !(ext_csd[EXT_CSD_FW_CONFIG] & 0x1); } + + /* eMMC v5.1 or later */ + if (card->ext_csd.rev >= 8) { + card->ext_csd.cmdq_support = ext_csd[EXT_CSD_CMDQ_SUPPORT] & + EXT_CSD_CMDQ_SUPPORTED; + card->ext_csd.cmdq_depth = (ext_csd[EXT_CSD_CMDQ_DEPTH] & + EXT_CSD_CMDQ_DEPTH_MASK) + 1; + /* Exclude inefficiently small queue depths */ + if (card->ext_csd.cmdq_depth <= 2) { + card->ext_csd.cmdq_support = false; + card->ext_csd.cmdq_depth = 0; + } + if (card->ext_csd.cmdq_support) { + pr_debug("%s: Command Queue supported depth %u\n", + mmc_hostname(card->host), + card->ext_csd.cmdq_depth); + } + } out: return err; } @@ -1003,19 +1021,6 @@ static int mmc_select_bus_width(struct mmc_card *card) return err; } -/* Caller must hold re-tuning */ -static int mmc_switch_status(struct mmc_card *card) -{ - u32 status; - int err; - - err = mmc_send_status(card, &status); - if (err) - return err; - - return mmc_switch_status_error(card->host, status); -} - /* * Switch to the high-speed mode */ @@ -1025,13 +1030,8 @@ static int mmc_select_hs(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, - card->ext_csd.generic_cmd6_time, - true, false, true); - if (!err) { - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); - err = mmc_switch_status(card); - } - + card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_HS, + true, true, true); if (err) pr_warn("%s: switch to high-speed failed, err:%d\n", mmc_hostname(card->host), err); @@ -1058,10 +1058,12 @@ static int mmc_select_hs_ddr(struct mmc_card *card) ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4; - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, - ext_csd_bits, - card->ext_csd.generic_cmd6_time); + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BUS_WIDTH, + ext_csd_bits, + card->ext_csd.generic_cmd6_time, + MMC_TIMING_MMC_DDR52, + true, true, true); if (err) { pr_err("%s: switch to bus width %d ddr failed\n", mmc_hostname(host), 1 << bus_width); @@ -1104,9 +1106,6 @@ static int mmc_select_hs_ddr(struct mmc_card *card) if (err) err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); - if (!err) - mmc_set_timing(host, MMC_TIMING_MMC_DDR52); - return err; } @@ -1128,7 +1127,7 @@ static int mmc_select_hs400(struct mmc_card *card) val = EXT_CSD_TIMING_HS; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, - card->ext_csd.generic_cmd6_time, + card->ext_csd.generic_cmd6_time, 0, true, false, true); if (err) { pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", @@ -1163,7 +1162,7 @@ static int mmc_select_hs400(struct mmc_card *card) card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, - card->ext_csd.generic_cmd6_time, + card->ext_csd.generic_cmd6_time, 0, true, false, true); if (err) { pr_err("%s: switch to hs400 failed, err:%d\n", @@ -1206,7 +1205,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card) /* Switch HS400 to HS DDR */ val = EXT_CSD_TIMING_HS; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, - val, card->ext_csd.generic_cmd6_time, + val, card->ext_csd.generic_cmd6_time, 0, true, false, true); if (err) goto out_err; @@ -1220,7 +1219,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card) /* Switch HS DDR to HS */ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time, - true, false, true); + 0, true, false, true); if (err) goto out_err; @@ -1234,14 +1233,19 @@ int mmc_hs400_to_hs200(struct mmc_card *card) val = EXT_CSD_TIMING_HS200 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, - val, card->ext_csd.generic_cmd6_time, + val, card->ext_csd.generic_cmd6_time, 0, true, false, true); if (err) goto out_err; mmc_set_timing(host, MMC_TIMING_MMC_HS200); - err = mmc_switch_status(card); + /* + * For HS200, CRC errors are not a reliable way to know the switch + * failed. If there really is a problem, we would expect tuning will + * fail and the result ends up the same. + */ + err = __mmc_switch_status(card, false); if (err) goto out_err; @@ -1281,16 +1285,23 @@ static int mmc_select_hs400es(struct mmc_card *card) goto out_err; /* Switch card to HS mode */ - err = mmc_select_hs(card); - if (err) + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, + card->ext_csd.generic_cmd6_time, 0, + true, false, true); + if (err) { + pr_err("%s: switch to hs for hs400es failed, err:%d\n", + mmc_hostname(host), err); goto out_err; + } - mmc_set_clock(host, card->ext_csd.hs_max_dtr); - + mmc_set_timing(host, MMC_TIMING_MMC_HS); err = mmc_switch_status(card); if (err) goto out_err; + mmc_set_clock(host, card->ext_csd.hs_max_dtr); + /* Switch card to DDR with strobe bit */ val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE; err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, @@ -1308,7 +1319,7 @@ static int mmc_select_hs400es(struct mmc_card *card) card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, - card->ext_csd.generic_cmd6_time, + card->ext_csd.generic_cmd6_time, 0, true, false, true); if (err) { pr_err("%s: switch to hs400es failed, err:%d\n", @@ -1390,14 +1401,20 @@ static int mmc_select_hs200(struct mmc_card *card) card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, - card->ext_csd.generic_cmd6_time, + card->ext_csd.generic_cmd6_time, 0, true, false, true); if (err) goto err; old_timing = host->ios.timing; mmc_set_timing(host, MMC_TIMING_MMC_HS200); - err = mmc_switch_status(card); + /* + * For HS200, CRC errors are not a reliable way to know the + * switch failed. If there really is a problem, we would expect + * tuning will fail and the result ends up the same. + */ + err = __mmc_switch_status(card, false); + /* * mmc_select_timing() assumes timing has not changed if * it is a switch error. @@ -1480,7 +1497,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, u32 cid[4]; u32 rocr; - BUG_ON(!host); WARN_ON(!host->claimed); /* Set correct bus mode for MMC before attempting init */ @@ -1854,7 +1870,7 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_POWER_OFF_NOTIFICATION, - notify_type, timeout, true, false, false); + notify_type, timeout, 0, true, false, false); if (err) pr_err("%s: Power Off Notification timed out, %u\n", mmc_hostname(card->host), timeout); @@ -1870,9 +1886,6 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) */ static void mmc_remove(struct mmc_host *host) { - BUG_ON(!host); - BUG_ON(!host->card); - mmc_remove_card(host->card); host->card = NULL; } @@ -1892,9 +1905,6 @@ static void mmc_detect(struct mmc_host *host) { int err; - BUG_ON(!host); - BUG_ON(!host->card); - mmc_get_card(host->card); /* @@ -1920,9 +1930,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT : EXT_CSD_POWER_OFF_LONG; - BUG_ON(!host); - BUG_ON(!host->card); - mmc_claim_host(host); if (mmc_card_suspended(host->card)) @@ -1979,9 +1986,6 @@ static int _mmc_resume(struct mmc_host *host) { int err = 0; - BUG_ON(!host); - BUG_ON(!host->card); - mmc_claim_host(host); if (!mmc_card_suspended(host->card)) @@ -2114,7 +2118,6 @@ int mmc_attach_mmc(struct mmc_host *host) int err; u32 ocr, rocr; - BUG_ON(!host); WARN_ON(!host->claimed); /* Set correct bus mode for MMC before attempting attach */ diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index ad6e9798e949..b11c3455b040 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -54,21 +54,15 @@ static const u8 tuning_blk_pattern_8bit[] = { 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, }; -static inline int __mmc_send_status(struct mmc_card *card, u32 *status, - bool ignore_crc) +int mmc_send_status(struct mmc_card *card, u32 *status) { int err; struct mmc_command cmd = {0}; - BUG_ON(!card); - BUG_ON(!card->host); - cmd.opcode = MMC_SEND_STATUS; if (!mmc_host_is_spi(card->host)) cmd.arg = card->rca << 16; cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; - if (ignore_crc) - cmd.flags &= ~MMC_RSP_CRC; err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); if (err) @@ -83,17 +77,10 @@ static inline int __mmc_send_status(struct mmc_card *card, u32 *status, return 0; } -int mmc_send_status(struct mmc_card *card, u32 *status) -{ - return __mmc_send_status(card, status, false); -} - static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) { struct mmc_command cmd = {0}; - BUG_ON(!host); - cmd.opcode = MMC_SELECT_CARD; if (card) { @@ -109,7 +96,6 @@ static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) int mmc_select_card(struct mmc_card *card) { - BUG_ON(!card); return _mmc_select_card(card->host, card); } @@ -181,8 +167,6 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) struct mmc_command cmd = {0}; int i, err = 0; - BUG_ON(!host); - cmd.opcode = MMC_SEND_OP_COND; cmd.arg = mmc_host_is_spi(host) ? 0 : ocr; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; @@ -221,9 +205,6 @@ int mmc_all_send_cid(struct mmc_host *host, u32 *cid) int err; struct mmc_command cmd = {0}; - BUG_ON(!host); - BUG_ON(!cid); - cmd.opcode = MMC_ALL_SEND_CID; cmd.arg = 0; cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; @@ -241,9 +222,6 @@ int mmc_set_relative_addr(struct mmc_card *card) { struct mmc_command cmd = {0}; - BUG_ON(!card); - BUG_ON(!card->host); - cmd.opcode = MMC_SET_RELATIVE_ADDR; cmd.arg = card->rca << 16; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; @@ -257,9 +235,6 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) int err; struct mmc_command cmd = {0}; - BUG_ON(!host); - BUG_ON(!cxd); - cmd.opcode = opcode; cmd.arg = arg; cmd.flags = MMC_RSP_R2 | MMC_CMD_AC; @@ -440,7 +415,7 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc) return err; } -int mmc_switch_status_error(struct mmc_host *host, u32 status) +static int mmc_switch_status_error(struct mmc_host *host, u32 status) { if (mmc_host_is_spi(host)) { if (status & R1_SPI_ILLEGAL_COMMAND) @@ -455,6 +430,88 @@ int mmc_switch_status_error(struct mmc_host *host, u32 status) return 0; } +/* Caller must hold re-tuning */ +int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) +{ + u32 status; + int err; + + err = mmc_send_status(card, &status); + if (!crc_err_fatal && err == -EILSEQ) + return 0; + if (err) + return err; + + return mmc_switch_status_error(card->host, status); +} + +int mmc_switch_status(struct mmc_card *card) +{ + return __mmc_switch_status(card, true); +} + +static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + bool send_status, bool retry_crc_err) +{ + struct mmc_host *host = card->host; + int err; + unsigned long timeout; + u32 status = 0; + bool expired = false; + bool busy = false; + + /* We have an unspecified cmd timeout, use the fallback value. */ + if (!timeout_ms) + timeout_ms = MMC_OPS_TIMEOUT_MS; + + /* + * In cases when not allowed to poll by using CMD13 or because we aren't + * capable of polling by using ->card_busy(), then rely on waiting the + * stated timeout to be sufficient. + */ + if (!send_status && !host->ops->card_busy) { + mmc_delay(timeout_ms); + return 0; + } + + timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1; + do { + /* + * Due to the possibility of being preempted while polling, + * check the expiration time first. + */ + expired = time_after(jiffies, timeout); + + if (host->ops->card_busy) { + busy = host->ops->card_busy(host); + } else { + err = mmc_send_status(card, &status); + if (retry_crc_err && err == -EILSEQ) { + busy = true; + } else if (err) { + return err; + } else { + err = mmc_switch_status_error(host, status); + if (err) + return err; + busy = R1_CURRENT_STATE(status) == R1_STATE_PRG; + } + } + + /* Timeout if the device still remains busy. */ + if (expired && busy) { + pr_err("%s: Card stuck being busy! %s\n", + mmc_hostname(host), __func__); + return -ETIMEDOUT; + } + } while (busy); + + if (host->ops->card_busy && send_status) + return mmc_switch_status(card); + + return 0; +} + /** * __mmc_switch - modify EXT_CSD register * @card: the MMC card associated with the data transfer @@ -463,24 +520,22 @@ int mmc_switch_status_error(struct mmc_host *host, u32 status) * @value: value to program into EXT_CSD register * @timeout_ms: timeout (ms) for operation performed by register write, * timeout of zero implies maximum possible timeout + * @timing: new timing to change to * @use_busy_signal: use the busy signal as response type * @send_status: send status cmd to poll for busy - * @ignore_crc: ignore CRC errors when sending status cmd to poll for busy + * @retry_crc_err: retry when CRC errors when polling with CMD13 for busy * * Modifies the EXT_CSD register for selected card. */ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, - unsigned int timeout_ms, bool use_busy_signal, bool send_status, - bool ignore_crc) + unsigned int timeout_ms, unsigned char timing, + bool use_busy_signal, bool send_status, bool retry_crc_err) { struct mmc_host *host = card->host; int err; struct mmc_command cmd = {0}; - unsigned long timeout; - u32 status = 0; bool use_r1b_resp = use_busy_signal; - bool expired = false; - bool busy = false; + unsigned char old_timing = host->ios.timing; mmc_retune_hold(host); @@ -522,62 +577,24 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, if (!use_busy_signal) goto out; - /* - * CRC errors shall only be ignored in cases were CMD13 is used to poll - * to detect busy completion. - */ - if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) - ignore_crc = false; - - /* We have an unspecified cmd timeout, use the fallback value. */ - if (!timeout_ms) - timeout_ms = MMC_OPS_TIMEOUT_MS; - - /* Must check status to be sure of no errors. */ - timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1; - do { - /* - * Due to the possibility of being preempted after - * sending the status command, check the expiration - * time first. - */ - expired = time_after(jiffies, timeout); - if (send_status) { - err = __mmc_send_status(card, &status, ignore_crc); - if (err) - goto out; - } - if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) - break; - if (host->ops->card_busy) { - if (!host->ops->card_busy(host)) - break; - busy = true; - } - if (mmc_host_is_spi(host)) - break; + /* Switch to new timing before poll and check switch status. */ + if (timing) + mmc_set_timing(host, timing); - /* - * We are not allowed to issue a status command and the host - * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only - * rely on waiting for the stated timeout to be sufficient. - */ - if (!send_status && !host->ops->card_busy) { - mmc_delay(timeout_ms); - goto out; - } + /*If SPI or used HW busy detection above, then we don't need to poll. */ + if (((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) || + mmc_host_is_spi(host)) { + if (send_status) + err = mmc_switch_status(card); + goto out_tim; + } - /* Timeout if the device never leaves the program state. */ - if (expired && - (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy)) { - pr_err("%s: Card stuck in programming state! %s\n", - mmc_hostname(host), __func__); - err = -ETIMEDOUT; - goto out; - } - } while (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy); + /* Let's try to poll to find out when the command is completed. */ + err = mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err); - err = mmc_switch_status_error(host, status); +out_tim: + if (err && timing) + mmc_set_timing(host, old_timing); out: mmc_retune_release(host); @@ -587,8 +604,8 @@ out: int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms) { - return __mmc_switch(card, set, index, value, timeout_ms, true, true, - false); + return __mmc_switch(card, set, index, value, timeout_ms, 0, + true, true, false); } EXPORT_SYMBOL_GPL(mmc_switch); @@ -661,6 +678,31 @@ out: } EXPORT_SYMBOL_GPL(mmc_send_tuning); +int mmc_abort_tuning(struct mmc_host *host, u32 opcode) +{ + struct mmc_command cmd = {0}; + + /* + * eMMC specification specifies that CMD12 can be used to stop a tuning + * command, but SD specification does not, so do nothing unless it is + * eMMC. + */ + if (opcode != MMC_SEND_TUNING_BLOCK_HS200) + return 0; + + cmd.opcode = MMC_STOP_TRANSMISSION; + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + + /* + * For drivers that override R1 to R1b, set an arbitrary timeout based + * on the tuning timeout i.e. 150ms. + */ + cmd.busy_timeout = 150; + + return mmc_wait_for_cmd(host, &cmd, 0); +} +EXPORT_SYMBOL_GPL(mmc_abort_tuning); + static int mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, u8 len) diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index f1b8e81aaa28..abd525ed74be 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -27,10 +27,11 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc); int mmc_bus_test(struct mmc_card *card, u8 bus_width); int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); int mmc_can_ext_csd(struct mmc_card *card); -int mmc_switch_status_error(struct mmc_host *host, u32 status); +int mmc_switch_status(struct mmc_card *card); +int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, - unsigned int timeout_ms, bool use_busy_signal, bool send_status, - bool ignore_crc); + unsigned int timeout_ms, unsigned char timing, + bool use_busy_signal, bool send_status, bool retry_crc_err); #endif diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 73c762a28dfe..deb90c2ff6b4 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -927,7 +927,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, u32 cid[4]; u32 rocr = 0; - BUG_ON(!host); WARN_ON(!host->claimed); err = mmc_sd_get_cid(host, ocr, cid, &rocr); @@ -1043,9 +1042,6 @@ free_card: */ static void mmc_sd_remove(struct mmc_host *host) { - BUG_ON(!host); - BUG_ON(!host->card); - mmc_remove_card(host->card); host->card = NULL; } @@ -1065,9 +1061,6 @@ static void mmc_sd_detect(struct mmc_host *host) { int err; - BUG_ON(!host); - BUG_ON(!host->card); - mmc_get_card(host->card); /* @@ -1091,9 +1084,6 @@ static int _mmc_sd_suspend(struct mmc_host *host) { int err = 0; - BUG_ON(!host); - BUG_ON(!host->card); - mmc_claim_host(host); if (mmc_card_suspended(host->card)) @@ -1136,9 +1126,6 @@ static int _mmc_sd_resume(struct mmc_host *host) { int err = 0; - BUG_ON(!host); - BUG_ON(!host->card); - mmc_claim_host(host); if (!mmc_card_suspended(host->card)) @@ -1221,7 +1208,6 @@ int mmc_attach_sd(struct mmc_host *host) int err; u32 ocr, rocr; - BUG_ON(!host); WARN_ON(!host->claimed); err = mmc_send_app_op_cond(host, 0, &ocr); diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 16b774c18e75..de125a41aa7a 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -27,8 +27,8 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) int err; struct mmc_command cmd = {0}; - BUG_ON(!host); - BUG_ON(card && (card->host != host)); + if (WARN_ON(card && card->host != host)) + return -EINVAL; cmd.opcode = MMC_APP_CMD; @@ -72,8 +72,8 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, int i, err; - BUG_ON(!cmd); - BUG_ON(retries < 0); + if (retries < 0) + retries = MMC_CMD_RETRIES; err = -EIO; @@ -122,9 +122,6 @@ int mmc_app_set_bus_width(struct mmc_card *card, int width) { struct mmc_command cmd = {0}; - BUG_ON(!card); - BUG_ON(!card->host); - cmd.opcode = SD_APP_SET_BUS_WIDTH; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; @@ -147,8 +144,6 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) struct mmc_command cmd = {0}; int i, err = 0; - BUG_ON(!host); - cmd.opcode = SD_APP_OP_COND; if (mmc_host_is_spi(host)) cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */ @@ -224,9 +219,6 @@ int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca) int err; struct mmc_command cmd = {0}; - BUG_ON(!host); - BUG_ON(!rca); - cmd.opcode = SD_SEND_RELATIVE_ADDR; cmd.arg = 0; cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; @@ -249,10 +241,6 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr) struct scatterlist sg; void *data_buf; - BUG_ON(!card); - BUG_ON(!card->host); - BUG_ON(!scr); - /* NOTE: caller guarantees scr is heap-allocated */ err = mmc_app_cmd(card->host, card); @@ -307,9 +295,6 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, struct mmc_data data = {0}; struct scatterlist sg; - BUG_ON(!card); - BUG_ON(!card->host); - /* NOTE: caller guarantees resp is heap-allocated */ mode = !!mode; @@ -352,10 +337,6 @@ int mmc_app_sd_status(struct mmc_card *card, void *ssr) struct mmc_data data = {0}; struct scatterlist sg; - BUG_ON(!card); - BUG_ON(!card->host); - BUG_ON(!ssr); - /* NOTE: caller guarantees ssr is heap-allocated */ err = mmc_app_cmd(card->host, card); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index bd44ba8116d1..ecbc52981ba5 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -63,7 +63,8 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn) int ret; struct sdio_func *func; - BUG_ON(fn > SDIO_MAX_FUNCS); + if (WARN_ON(fn > SDIO_MAX_FUNCS)) + return -EINVAL; func = sdio_alloc_func(card); if (IS_ERR(func)) @@ -555,7 +556,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, u32 rocr = 0; u32 ocr_card = ocr; - BUG_ON(!host); WARN_ON(!host->claimed); /* to query card if 1.8V signalling is supported */ @@ -791,9 +791,6 @@ static void mmc_sdio_remove(struct mmc_host *host) { int i; - BUG_ON(!host); - BUG_ON(!host->card); - for (i = 0;i < host->card->sdio_funcs;i++) { if (host->card->sdio_func[i]) { sdio_remove_func(host->card->sdio_func[i]); @@ -820,9 +817,6 @@ static void mmc_sdio_detect(struct mmc_host *host) { int err; - BUG_ON(!host); - BUG_ON(!host->card); - /* Make sure card is powered before detecting it */ if (host->caps & MMC_CAP_POWER_OFF_CARD) { err = pm_runtime_get_sync(&host->card->dev); @@ -916,9 +910,6 @@ static int mmc_sdio_resume(struct mmc_host *host) { int err = 0; - BUG_ON(!host); - BUG_ON(!host->card); - /* Basic card reinitialization. */ mmc_claim_host(host); @@ -970,9 +961,6 @@ static int mmc_sdio_power_restore(struct mmc_host *host) { int ret; - BUG_ON(!host); - BUG_ON(!host->card); - mmc_claim_host(host); /* @@ -1063,7 +1051,6 @@ int mmc_attach_sdio(struct mmc_host *host) u32 ocr, rocr; struct mmc_card *card; - BUG_ON(!host); WARN_ON(!host->claimed); err = mmc_send_io_op_cond(host, 0, &ocr); diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index dcb3dee59fa5..f8c372839d24 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -262,7 +262,8 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) else prev = &card->tuples; - BUG_ON(*prev); + if (*prev) + return -EINVAL; do { unsigned char tpl_code, tpl_link; diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 91bbbfb29f3f..f1faf9acc007 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -214,7 +214,9 @@ static int sdio_card_irq_put(struct mmc_card *card) struct mmc_host *host = card->host; WARN_ON(!host->claimed); - BUG_ON(host->sdio_irqs < 1); + + if (host->sdio_irqs < 1) + return -EINVAL; if (!--host->sdio_irqs) { if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) { @@ -261,8 +263,8 @@ int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler) int ret; unsigned char reg; - BUG_ON(!func); - BUG_ON(!func->card); + if (!func) + return -EINVAL; pr_debug("SDIO: Enabling IRQ for %s...\n", sdio_func_id(func)); @@ -304,8 +306,8 @@ int sdio_release_irq(struct sdio_func *func) int ret; unsigned char reg; - BUG_ON(!func); - BUG_ON(!func->card); + if (!func) + return -EINVAL; pr_debug("SDIO: Disabling IRQ for %s...\n", sdio_func_id(func)); diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 27117ba47073..babe591aea96 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -258,6 +258,14 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, } EXPORT_SYMBOL(mmc_gpiod_request_cd); +bool mmc_can_gpio_cd(struct mmc_host *host) +{ + struct mmc_gpio *ctx = host->slot.handler_priv; + + return ctx->cd_gpio ? true : false; +} +EXPORT_SYMBOL(mmc_can_gpio_cd); + /** * mmc_gpiod_request_ro - request a gpio descriptor for write protection * @host: mmc host |
