From 68249abd7ae8de55e59844436bcd3c8f51bdd252 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 24 Jun 2021 17:16:15 +0200 Subject: mmc: host: add kdoc for mmc_retune_{en|dis}able I wanted to use it in a wrong way, so document the intended way. Signed-off-by: Wolfram Sang Acked-by: Adrian Hunter Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210624151616.38770-3-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/host.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 0475d96047c4..913fd62c01cd 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -96,6 +96,10 @@ void mmc_unregister_host_class(void) class_unregister(&mmc_host_class); } +/** + * mmc_retune_enable() - enter a transfer mode that requires retuning + * @host: host which should retune now + */ void mmc_retune_enable(struct mmc_host *host) { host->can_retune = 1; @@ -127,6 +131,12 @@ void mmc_retune_unpause(struct mmc_host *host) } EXPORT_SYMBOL(mmc_retune_unpause); +/** + * mmc_retune_disable() - exit a transfer mode that requires retuning + * @host: host which should not retune anymore + * + * It is not meant for temporarily preventing retuning! + */ void mmc_retune_disable(struct mmc_host *host) { mmc_retune_unpause(host); -- cgit v1.2.3 From 8ffb2611a752e1067c18fba39968080469394206 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 24 Jun 2021 17:16:16 +0200 Subject: mmc: host: factor out clearing the retune state We have this in two places, so let's have a dedicated function. It is also more readable. Signed-off-by: Wolfram Sang Acked-by: Adrian Hunter Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210624151616.38770-4-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/core.c | 3 +-- drivers/mmc/core/host.c | 3 +-- drivers/mmc/core/host.h | 6 ++++++ 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 95fedcf56e4a..84f39a59a28e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -941,8 +941,7 @@ int mmc_execute_tuning(struct mmc_card *card) pr_err("%s: tuning execution failed: %d\n", mmc_hostname(host), err); } else { - host->retune_now = 0; - host->need_retune = 0; + mmc_retune_clear(host); mmc_retune_enable(host); } diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 913fd62c01cd..d4683b1d263f 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -142,8 +142,7 @@ void mmc_retune_disable(struct mmc_host *host) mmc_retune_unpause(host); host->can_retune = 0; del_timer_sync(&host->retune_timer); - host->retune_now = 0; - host->need_retune = 0; + mmc_retune_clear(host); } void mmc_retune_timer_stop(struct mmc_host *host) diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h index ba407617ed23..48c4952512a5 100644 --- a/drivers/mmc/core/host.h +++ b/drivers/mmc/core/host.h @@ -21,6 +21,12 @@ int mmc_retune(struct mmc_host *host); void mmc_retune_pause(struct mmc_host *host); void mmc_retune_unpause(struct mmc_host *host); +static inline void mmc_retune_clear(struct mmc_host *host) +{ + host->retune_now = 0; + host->need_retune = 0; +} + static inline void mmc_retune_hold_now(struct mmc_host *host) { host->retune_now = 0; -- cgit v1.2.3 From 972d5084831dc9ae30f1a4b66cb4a19fb7ba6f09 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 2 Jul 2021 15:42:27 +0200 Subject: mmc: core: Avoid hogging the CPU while polling for busy in the I/O err path When mmc_blk_fix_state() sends a CMD12 to try to move the card into the transfer state, it calls card_busy_detect() to poll for the card's state with CMD13. This is done without any delays in between the commands being sent. Rather than fixing card_busy_detect() in this regards, let's instead convert into using the common mmc_poll_for_busy(), which also helps us to avoid open-coding. Signed-off-by: Ulf Hansson Reviewed-by: Shawn Lin Link: https://lore.kernel.org/r/20210702134229.357717-2-ulf.hansson@linaro.org --- drivers/mmc/core/block.c | 2 +- drivers/mmc/core/mmc_ops.c | 4 +++- drivers/mmc/core/mmc_ops.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index ce8aed562929..170343411f53 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1636,7 +1636,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req) mmc_blk_send_stop(card, timeout); - err = card_busy_detect(card, timeout, NULL); + err = mmc_poll_for_busy(card, timeout, false, MMC_BUSY_IO); mmc_retune_release(card->host); diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 973756ed4016..e2c431c0ce5d 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -435,7 +435,7 @@ static int mmc_busy_cb(void *cb_data, bool *busy) u32 status = 0; int err; - if (host->ops->card_busy) { + if (data->busy_cmd != MMC_BUSY_IO && host->ops->card_busy) { *busy = host->ops->card_busy(host); return 0; } @@ -457,6 +457,7 @@ static int mmc_busy_cb(void *cb_data, bool *busy) break; case MMC_BUSY_HPI: case MMC_BUSY_EXTR_SINGLE: + case MMC_BUSY_IO: break; default: err = -EINVAL; @@ -521,6 +522,7 @@ int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, return __mmc_poll_for_busy(card, timeout_ms, &mmc_busy_cb, &cb_data); } +EXPORT_SYMBOL_GPL(mmc_poll_for_busy); bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, unsigned int timeout_ms) diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 41ab4f573a31..ae25ffc2e870 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -15,6 +15,7 @@ enum mmc_busy_cmd { MMC_BUSY_ERASE, MMC_BUSY_HPI, MMC_BUSY_EXTR_SINGLE, + MMC_BUSY_IO, }; struct mmc_host; -- cgit v1.2.3 From 468108155b0f89cc08189cc33f9bacfe9da8a125 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 2 Jul 2021 15:42:28 +0200 Subject: mmc: core: Avoid hogging the CPU while polling for busy for mmc ioctls When __mmc_blk_ioctl_cmd() calls card_busy_detect() to verify that the card's states moves back into transfer state, the polling with CMD13 is done without any delays in between the commands being sent. Rather than fixing card_busy_detect() in this regards, let's instead convert into using the common mmc_poll_for_busy(), which also helps us to avoid open-coding. Signed-off-by: Ulf Hansson Reviewed-by: Shawn Lin Link: https://lore.kernel.org/r/20210702134229.357717-3-ulf.hansson@linaro.org --- drivers/mmc/core/block.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 170343411f53..c30d0ab15539 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -605,7 +605,8 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, * Ensure RPMB/R1B command has completed by polling CMD13 * "Send Status". */ - err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL); + err = mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, false, + MMC_BUSY_IO); } return err; -- cgit v1.2.3 From 6966e6094c6d594044ef1b740dd827e05881331c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 2 Jul 2021 15:42:29 +0200 Subject: mmc: core: Avoid hogging the CPU while polling for busy after I/O writes When mmc_blk_card_busy() calls card_busy_detect() to poll for the card's state with CMD13, this is done without any delays in between the commands being sent. Rather than fixing card_busy_detect() in this regards, let's instead convert into using the common __mmc_poll_for_busy(), which also helps us to avoid open-coding. Signed-off-by: Ulf Hansson Reviewed-by: Shawn Lin Link: https://lore.kernel.org/r/20210702134229.357717-4-ulf.hansson@linaro.org --- drivers/mmc/core/block.c | 69 +++++++++++++++++++--------------------------- drivers/mmc/core/mmc_ops.c | 1 + 2 files changed, 30 insertions(+), 40 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index c30d0ab15539..a9ad9f5fa949 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -98,6 +98,11 @@ static int max_devices; static DEFINE_IDA(mmc_blk_ida); static DEFINE_IDA(mmc_rpmb_ida); +struct mmc_blk_busy_data { + struct mmc_card *card; + u32 status; +}; + /* * There is one mmc_blk_data per slot. */ @@ -417,42 +422,6 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr, return 0; } -static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, - u32 *resp_errs) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); - int err = 0; - u32 status; - - do { - bool done = time_after(jiffies, timeout); - - err = __mmc_send_status(card, &status, 5); - if (err) { - dev_err(mmc_dev(card->host), - "error %d requesting status\n", err); - return err; - } - - /* Accumulate any response error bits seen */ - if (resp_errs) - *resp_errs |= status; - - /* - * Timeout if the device never becomes ready for data and never - * leaves the program state. - */ - if (done) { - dev_err(mmc_dev(card->host), - "Card stuck in wrong state! %s status: %#x\n", - __func__, status); - return -ETIMEDOUT; - } - } while (!mmc_ready_for_data(status)); - - return err; -} - static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, struct mmc_blk_ioc_data *idata) { @@ -1852,28 +1821,48 @@ static inline bool mmc_blk_rq_error(struct mmc_blk_request *brq) brq->data.error || brq->cmd.resp[0] & CMD_ERRORS; } +static int mmc_blk_busy_cb(void *cb_data, bool *busy) +{ + struct mmc_blk_busy_data *data = cb_data; + u32 status = 0; + int err; + + err = mmc_send_status(data->card, &status); + if (err) + return err; + + /* Accumulate response error bits. */ + data->status |= status; + + *busy = !mmc_ready_for_data(status); + return 0; +} + static int mmc_blk_card_busy(struct mmc_card *card, struct request *req) { struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); - u32 status = 0; + struct mmc_blk_busy_data cb_data; int err; if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ) return 0; - err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status); + cb_data.card = card; + cb_data.status = 0; + err = __mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, &mmc_blk_busy_cb, + &cb_data); /* * Do not assume data transferred correctly if there are any error bits * set. */ - if (status & mmc_blk_stop_err_bits(&mqrq->brq)) { + if (cb_data.status & mmc_blk_stop_err_bits(&mqrq->brq)) { mqrq->brq.data.bytes_xfered = 0; err = err ? err : -EIO; } /* Copy the exception bit so it will be seen later on */ - if (mmc_card_mmc(card) && status & R1_EXCEPTION_EVENT) + if (mmc_card_mmc(card) && cb_data.status & R1_EXCEPTION_EVENT) mqrq->brq.cmd.resp[0] |= R1_EXCEPTION_EVENT; return err; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index e2c431c0ce5d..90d213a2203f 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -510,6 +510,7 @@ int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, return 0; } +EXPORT_SYMBOL_GPL(__mmc_poll_for_busy); int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, bool retry_crc_err, enum mmc_busy_cmd busy_cmd) -- cgit v1.2.3 From 86c639ce08266ed521974038f0592739fec1c11a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 21 Jul 2021 08:47:38 -0700 Subject: mmc: core: Store pointer to bio_crypt_ctx in mmc_request Make 'struct mmc_request' contain a pointer to the request's 'struct bio_crypt_ctx' directly, instead of extracting a 32-bit DUN from it which is a cqhci-crypto specific detail. This keeps the cqhci crypto specific details in the cqhci module, and it makes mmc_core and mmc_block ready for MMC crypto hardware that accepts the DUN and/or key in a way that is more flexible than that which will be specified by the eMMC v5.2 standard. Exynos SoCs are an example of such hardware, as their inline encryption hardware takes keys directly (it has no concept of keyslots) and supports 128-bit DUNs. Note that the 32-bit DUN length specified by the standard is very restrictive, so it is likely that more hardware will support longer DUNs despite it not following the standard. Thus, limiting the scope of the 32-bit DUN assumption to the place that actually needs it is warranted. Signed-off-by: Eric Biggers Link: https://lore.kernel.org/r/20210721154738.3966463-1-ebiggers@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/crypto.c | 15 ++++----------- drivers/mmc/host/cqhci-crypto.h | 7 +++++-- include/linux/mmc/core.h | 3 +-- 3 files changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/crypto.c b/drivers/mmc/core/crypto.c index 419a368f8402..67557808cada 100644 --- a/drivers/mmc/core/crypto.c +++ b/drivers/mmc/core/crypto.c @@ -31,18 +31,11 @@ void mmc_crypto_prepare_req(struct mmc_queue_req *mqrq) struct request *req = mmc_queue_req_to_req(mqrq); struct mmc_request *mrq = &mqrq->brq.mrq; - if (!req->crypt_keyslot) + if (!req->crypt_ctx) return; - mrq->crypto_enabled = true; - mrq->crypto_key_slot = blk_ksm_get_slot_idx(req->crypt_keyslot); - - /* - * For now we assume that all MMC drivers set max_dun_bytes_supported=4, - * which is the limit for CQHCI crypto. So all DUNs should be 32-bit. - */ - WARN_ON_ONCE(req->crypt_ctx->bc_dun[0] > U32_MAX); - - mrq->data_unit_num = req->crypt_ctx->bc_dun[0]; + mrq->crypto_ctx = req->crypt_ctx; + if (req->crypt_keyslot) + mrq->crypto_key_slot = blk_ksm_get_slot_idx(req->crypt_keyslot); } EXPORT_SYMBOL_GPL(mmc_crypto_prepare_req); diff --git a/drivers/mmc/host/cqhci-crypto.h b/drivers/mmc/host/cqhci-crypto.h index 60b58ee0e625..d7fb084f563b 100644 --- a/drivers/mmc/host/cqhci-crypto.h +++ b/drivers/mmc/host/cqhci-crypto.h @@ -22,12 +22,15 @@ int cqhci_crypto_init(struct cqhci_host *host); */ static inline u64 cqhci_crypto_prep_task_desc(struct mmc_request *mrq) { - if (!mrq->crypto_enabled) + if (!mrq->crypto_ctx) return 0; + /* We set max_dun_bytes_supported=4, so all DUNs should be 32-bit. */ + WARN_ON_ONCE(mrq->crypto_ctx->bc_dun[0] > U32_MAX); + return CQHCI_CRYPTO_ENABLE_BIT | CQHCI_CRYPTO_KEYSLOT(mrq->crypto_key_slot) | - mrq->data_unit_num; + mrq->crypto_ctx->bc_dun[0]; } #else /* CONFIG_MMC_CRYPTO */ diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index ab19245e9945..71101d1ec825 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -164,9 +164,8 @@ struct mmc_request { int tag; #ifdef CONFIG_MMC_CRYPTO - bool crypto_enabled; + const struct bio_crypt_ctx *crypto_ctx; int crypto_key_slot; - u32 data_unit_num; #endif }; -- cgit v1.2.3 From 8335928849729f8e5f10c1497c67260742f7a8cb Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 30 Jun 2021 06:16:58 +0200 Subject: mmc: core: Only print retune error when we don't check for card removal Skip printing a retune error when we scan for a removed card because we then expect a failed command. Signed-off-by: Wolfram Sang Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20210630041658.7574-1-wsa+renesas@sang-engineering.com [Ulf: Rebased patch] Signed-off-by: Ulf Hansson --- drivers/mmc/core/core.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 84f39a59a28e..6249c83d616f 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -936,15 +936,17 @@ int mmc_execute_tuning(struct mmc_card *card) opcode = MMC_SEND_TUNING_BLOCK; err = host->ops->execute_tuning(host, opcode); - - if (err) { - pr_err("%s: tuning execution failed: %d\n", - mmc_hostname(host), err); - } else { + if (!err) { mmc_retune_clear(host); mmc_retune_enable(host); + return 0; } + /* Only print error when we don't check for card removal */ + if (!host->detect_change) + pr_err("%s: tuning execution failed: %d\n", + mmc_hostname(host), err); + return err; } -- cgit v1.2.3 From 4b5e37b8fd6491b4a782cbbb8a98e5031b0bc981 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Mon, 26 Jul 2021 12:36:52 -0400 Subject: mmc: sdio: Don't warn about vendor CIS tuples CIS tuples in the range 0x80-0x8F are reserved for vendors. Some devices have tuples in this range which get warned about every boot. Since this is normal behavior, don't print these tuples unless debug is enabled. Unfortunately, we cannot use a variable for the format string since it gets pasted by pr_*_ratelimited. Signed-off-by: Sean Anderson Link: https://lore.kernel.org/r/20210726163654.1110969-1-sean.anderson@seco.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio_cis.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index b23773583179..7518b27bcef2 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -330,13 +330,23 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) prev = &this->next; if (ret == -ENOENT) { + if (time_after(jiffies, timeout)) break; - /* warn about unknown tuples */ - pr_warn_ratelimited("%s: queuing unknown" - " CIS tuple 0x%02x (%u bytes)\n", - mmc_hostname(card->host), - tpl_code, tpl_link); + +#define FMT(type) "%s: queuing " type " CIS tuple 0x%02x (%u bytes)\n" + /* + * Tuples in this range are reserved for + * vendors, so don't warn about them + */ + if (tpl_code >= 0x80 && tpl_code <= 0x8f) + pr_debug_ratelimited(FMT("vendor"), + mmc_hostname(card->host), + tpl_code, tpl_link); + else + pr_warn_ratelimited(FMT("unknown"), + mmc_hostname(card->host), + tpl_code, tpl_link); } /* keep on analyzing tuples */ -- cgit v1.2.3 From e285b3e064647c6b4b822ade9acb0f3ffd6b1317 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Mon, 26 Jul 2021 12:36:53 -0400 Subject: mmc: sdio: Print contents of unknown CIS tuples Print out the contents of the offending tuples when we do print them. This can make it easier to debug, since these tuples are not exposed to userspace anywhere else. We are limited to 64 bytes, so keep printing out the full length in case the tuple is truncated. Signed-off-by: Sean Anderson Link: https://lore.kernel.org/r/20210726163654.1110969-2-sean.anderson@seco.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio_cis.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index 7518b27bcef2..a705ba6eff5b 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -334,7 +334,7 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) if (time_after(jiffies, timeout)) break; -#define FMT(type) "%s: queuing " type " CIS tuple 0x%02x (%u bytes)\n" +#define FMT(type) "%s: queuing " type " CIS tuple 0x%02x [%*ph] (%u bytes)\n" /* * Tuples in this range are reserved for * vendors, so don't warn about them @@ -342,11 +342,13 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) if (tpl_code >= 0x80 && tpl_code <= 0x8f) pr_debug_ratelimited(FMT("vendor"), mmc_hostname(card->host), - tpl_code, tpl_link); + tpl_code, tpl_link, this->data, + tpl_link); else pr_warn_ratelimited(FMT("unknown"), mmc_hostname(card->host), - tpl_code, tpl_link); + tpl_code, tpl_link, this->data, + tpl_link); } /* keep on analyzing tuples */ -- cgit v1.2.3 From b2832b96fcf50270d69dae3f95bf14949ff638e4 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 20 Aug 2021 12:28:01 +0300 Subject: mmc: pwrseq: sd8787: add support for wilc1000 Add new compatible for wilc1000 devices and specify the delay in .data member of struct of_device_id. WILC1000, WILC3000 devices needs a minimum of 5ms delay b/w reset and power lines. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20210820092803.78523-3-claudiu.beznea@microchip.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/pwrseq_sd8787.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/pwrseq_sd8787.c b/drivers/mmc/core/pwrseq_sd8787.c index 68a826f1c0a1..264e48067af2 100644 --- a/drivers/mmc/core/pwrseq_sd8787.c +++ b/drivers/mmc/core/pwrseq_sd8787.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ struct mmc_pwrseq_sd8787 { struct mmc_pwrseq pwrseq; struct gpio_desc *reset_gpio; struct gpio_desc *pwrdn_gpio; + u32 reset_pwrdwn_delay_ms; }; #define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787, pwrseq) @@ -37,7 +39,7 @@ static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host) gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); - msleep(300); + msleep(pwrseq->reset_pwrdwn_delay_ms); gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1); } @@ -55,7 +57,8 @@ static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = { }; static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = { - { .compatible = "mmc-pwrseq-sd8787",}, + { .compatible = "mmc-pwrseq-sd8787", .data = (void *)300 }, + { .compatible = "mmc-pwrseq-wilc1000", .data = (void *)5 }, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match); @@ -64,11 +67,15 @@ static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev) { struct mmc_pwrseq_sd8787 *pwrseq; struct device *dev = &pdev->dev; + const struct of_device_id *match; pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); if (!pwrseq) return -ENOMEM; + match = of_match_node(mmc_pwrseq_sd8787_of_match, pdev->dev.of_node); + pwrseq->reset_pwrdwn_delay_ms = (u32)match->data; + pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW); if (IS_ERR(pwrseq->pwrdn_gpio)) return PTR_ERR(pwrseq->pwrdn_gpio); -- cgit v1.2.3 From 09cedbd8dbc057c07885cfacdcdb09ef4880c5cb Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 20 Aug 2021 12:28:02 +0300 Subject: mmc: pwrseq: add wilc1000_sdio dependency for pwrseq_sd8787 pwseq_sd8787 could also be used with wilc1000_sdio driver. Add a dependency for this. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20210820092803.78523-4-claudiu.beznea@microchip.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index ae8b69aee619..6f25c34e4fec 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig @@ -15,7 +15,7 @@ config PWRSEQ_EMMC config PWRSEQ_SD8787 tristate "HW reset support for SD8787 BT + Wifi module" - depends on OF && (MWIFIEX || BT_MRVL_SDIO || LIBERTAS_SDIO) + depends on OF && (MWIFIEX || BT_MRVL_SDIO || LIBERTAS_SDIO || WILC1000_SDIO) help This selects hardware reset support for the SD8787 BT + Wifi module. By default this option is set to n. -- cgit v1.2.3 From f6f607070aa6f0c730c5ca38e888c88f34bea7d6 Mon Sep 17 00:00:00 2001 From: ChanWoo Lee Date: Tue, 24 Aug 2021 16:39:34 +0900 Subject: mmc: queue: Match the data type of max_segments Each function has a different data type for max_segments, Modify to match unsigned short(host->max_segs). * unsigned short max_segs; /* see blk_queue_max_segments */ 1) Return type : unsigned int static unsigned int mmc_get_max_segments(struct mmc_host *host) { return host->can_dma_map_merge ? MMC_DMA_MAP_MERGE_SEGMENTS : host->max_segs; } 2) Parameter type : int mmc_alloc_sg(mmc_get_max_segments(host), gfp); -> static struct scatterlist *mmc_alloc_sg(int sg_len, gfp_t gfp) 3) Parameter type : unsigned short blk_queue_max_segments(mq->queue, mmc_get_max_segments(host)); -> void blk_queue_max_segments(struct request_queue *q, unsigned short max_segments) Signed-off-by: ChanWoo Lee Acked-by: Coly Li Link: https://lore.kernel.org/r/20210824073934.19727-1-cw9316.lee@samsung.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/queue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index cc3261777637..48304bcf963c 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -163,7 +163,7 @@ static void mmc_mq_recovery_handler(struct work_struct *work) blk_mq_run_hw_queues(q, true); } -static struct scatterlist *mmc_alloc_sg(int sg_len, gfp_t gfp) +static struct scatterlist *mmc_alloc_sg(unsigned short sg_len, gfp_t gfp) { struct scatterlist *sg; @@ -193,7 +193,7 @@ static void mmc_queue_setup_discard(struct request_queue *q, blk_queue_flag_set(QUEUE_FLAG_SECERASE, q); } -static unsigned int mmc_get_max_segments(struct mmc_host *host) +static unsigned short mmc_get_max_segments(struct mmc_host *host) { return host->can_dma_map_merge ? MMC_DMA_MAP_MERGE_SEGMENTS : host->max_segs; -- cgit v1.2.3 From fe72d08a961f9e09a7b04c15904a98f7c8cd537e Mon Sep 17 00:00:00 2001 From: Bean Huo Date: Wed, 18 Aug 2021 00:42:07 +0200 Subject: mmc: core: Issue HPI in case the BKOPS timed out If the BKOPS timed out, the card is probably still busy in the R1_STATE_PRG. Rather than continue as nothing has happened and hitting and error for the next command being sent, let's try to abort the running BKOPS by sending a HPI command to get back into R1_STATE_TRAN. Signed-off-by: Bean Huo Link: https://lore.kernel.org/r/20210817224208.153652-2-huobean@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc_ops.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 90d213a2203f..0c54858e89c0 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -959,8 +959,15 @@ void mmc_run_bkops(struct mmc_card *card) */ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_START, 1, MMC_BKOPS_TIMEOUT_MS); - if (err) - pr_warn("%s: Error %d starting bkops\n", + /* + * If the BKOPS timed out, the card is probably still busy in the + * R1_STATE_PRG. Rather than continue to wait, let's try to abort + * it with a HPI command to get back into R1_STATE_TRAN. + */ + if (err == -ETIMEDOUT && !mmc_interrupt_hpi(card)) + pr_warn("%s: BKOPS aborted\n", mmc_hostname(card->host)); + else if (err) + pr_warn("%s: Error %d running bkops\n", mmc_hostname(card->host), err); mmc_retune_release(card->host); -- cgit v1.2.3 From e72a55f2e5ddcfb3dce0701caf925ce435b87682 Mon Sep 17 00:00:00 2001 From: Nishad Kamdar Date: Wed, 25 Aug 2021 00:47:26 +0530 Subject: mmc: core: Return correct emmc response in case of ioctl error When a read/write command is sent via ioctl to the kernel, and the command fails, the actual error response of the emmc is not sent to the user. IOCTL read/write tests are carried out using commands 17 (Single BLock Read), 24 (Single Block Write), 18 (Multi Block Read), 25 (Multi Block Write) The tests are carried out on a 64Gb emmc device. All of these tests try to access an "out of range" sector address (0x09B2FFFF). It is seen that without the patch the response received by the user is not OUT_OF_RANGE error (R1 response 31st bit is not set) as per JEDEC specification. After applying the patch proper response is seen. This is because the function returns without copying the response to the user in case of failure. This patch fixes the issue. Hence, this memcpy is required whether we get an error response or not. Therefor it is moved up from the current position up to immediately after we have called mmc_wait_for_req(). The test code and the output of only the CMD17 is included in the commit to limit the message length. CMD17 (Test Code Snippet): ========================== printf("Forming CMD%d\n", opt_idx); /* single block read */ cmd.blksz = 512; cmd.blocks = 1; cmd.write_flag = 0; cmd.opcode = 17; //cmd.arg = atoi(argv[3]); cmd.arg = 0x09B2FFFF; /* Expecting response R1B */ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; memset(data, 0, sizeof(__u8) * 512); mmc_ioc_cmd_set_data(cmd, data); printf("Sending CMD%d: ARG[0x%08x]\n", opt_idx, cmd.arg); if(ioctl(fd, MMC_IOC_CMD, &cmd)) perror("Error"); printf("\nResponse: %08x\n", cmd.response[0]); CMD17 (Output without patch): ============================= test@test-LIVA-Z:~$ sudo ./mmc cmd_test /dev/mmcblk0 17 Entering the do_mmc_commands:Device: /dev/mmcblk0 nargs:4 Entering the do_mmc_commands:Device: /dev/mmcblk0 options[17, 0x09B2FFF] Forming CMD17 Sending CMD17: ARG[0x09b2ffff] Error: Connection timed out Response: 00000000 (Incorrect response) CMD17 (Output with patch): ========================== test@test-LIVA-Z:~$ sudo ./mmc cmd_test /dev/mmcblk0 17 [sudo] password for test: Entering the do_mmc_commands:Device: /dev/mmcblk0 nargs:4 Entering the do_mmc_commands:Device: /dev/mmcblk0 options[17, 09B2FFFF] Forming CMD17 Sending CMD17: ARG[0x09b2ffff] Error: Connection timed out Response: 80000900 (Correct OUT_OF_ERROR response as per JEDEC specification) Signed-off-by: Nishad Kamdar Reviewed-by: Avri Altman Link: https://lore.kernel.org/r/20210824191726.8296-1-nishadkamdar@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index a9ad9f5fa949..c3ecec3f6ddc 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -518,6 +518,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, return mmc_sanitize(card, idata->ic.cmd_timeout_ms); mmc_wait_for_req(card->host, &mrq); + memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp)); if (cmd.error) { dev_err(mmc_dev(card->host), "%s: cmd error %d\n", @@ -567,8 +568,6 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, if (idata->ic.postsleep_min_us) usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us); - memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp)); - if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) { /* * Ensure RPMB/R1B command has completed by polling CMD13 -- cgit v1.2.3 From dba914b248845492080162c0b604a5e25e52dc7b Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 25 Aug 2021 11:19:31 +0300 Subject: mmc: pwrseq: sd8787: fix compilation warning Fixed compilation warning "cast from pointer to integer of different size [-Wpointer-to-int-cast]" Fixes: b2832b96fcf5 ("mmc: pwrseq: sd8787: add support for wilc1000") Reported-by: kernel test robot Reported-by: Stephen Rothwell Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20210825081931.598934-1-claudiu.beznea@microchip.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/pwrseq_sd8787.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/pwrseq_sd8787.c b/drivers/mmc/core/pwrseq_sd8787.c index 264e48067af2..2e120ad83020 100644 --- a/drivers/mmc/core/pwrseq_sd8787.c +++ b/drivers/mmc/core/pwrseq_sd8787.c @@ -56,9 +56,12 @@ static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = { .power_off = mmc_pwrseq_sd8787_power_off, }; +static const u32 sd8787_delay_ms = 300; +static const u32 wilc1000_delay_ms = 5; + static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = { - { .compatible = "mmc-pwrseq-sd8787", .data = (void *)300 }, - { .compatible = "mmc-pwrseq-wilc1000", .data = (void *)5 }, + { .compatible = "mmc-pwrseq-sd8787", .data = &sd8787_delay_ms }, + { .compatible = "mmc-pwrseq-wilc1000", .data = &wilc1000_delay_ms }, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match); @@ -74,7 +77,7 @@ static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev) return -ENOMEM; match = of_match_node(mmc_pwrseq_sd8787_of_match, pdev->dev.of_node); - pwrseq->reset_pwrdwn_delay_ms = (u32)match->data; + pwrseq->reset_pwrdwn_delay_ms = *(u32 *)match->data; pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW); if (IS_ERR(pwrseq->pwrdn_gpio)) -- cgit v1.2.3 From f80c8e6864eb14b71f58c1a159654e4f379673a6 Mon Sep 17 00:00:00 2001 From: ChanWoo Lee Date: Wed, 25 Aug 2021 16:46:01 +0900 Subject: mmc: queue: Remove unused parameters(request_queue) In function mmc_exit_request, the request_queue structure(*q) is not used. I remove the unnecessary code related to the request_queue structure. Signed-off-by: ChanWoo Lee Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20210825074601.8881-1-cw9316.lee@samsung.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/queue.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 48304bcf963c..b15c034b42fb 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -199,27 +199,23 @@ static unsigned short mmc_get_max_segments(struct mmc_host *host) host->max_segs; } -/** - * mmc_init_request() - initialize the MMC-specific per-request data - * @mq: the request queue - * @req: the request - * @gfp: memory allocation policy - */ -static int __mmc_init_request(struct mmc_queue *mq, struct request *req, - gfp_t gfp) +static int mmc_mq_init_request(struct blk_mq_tag_set *set, struct request *req, + unsigned int hctx_idx, unsigned int numa_node) { struct mmc_queue_req *mq_rq = req_to_mmc_queue_req(req); + struct mmc_queue *mq = set->driver_data; struct mmc_card *card = mq->card; struct mmc_host *host = card->host; - mq_rq->sg = mmc_alloc_sg(mmc_get_max_segments(host), gfp); + mq_rq->sg = mmc_alloc_sg(mmc_get_max_segments(host), GFP_KERNEL); if (!mq_rq->sg) return -ENOMEM; return 0; } -static void mmc_exit_request(struct request_queue *q, struct request *req) +static void mmc_mq_exit_request(struct blk_mq_tag_set *set, struct request *req, + unsigned int hctx_idx) { struct mmc_queue_req *mq_rq = req_to_mmc_queue_req(req); @@ -227,20 +223,6 @@ static void mmc_exit_request(struct request_queue *q, struct request *req) mq_rq->sg = NULL; } -static int mmc_mq_init_request(struct blk_mq_tag_set *set, struct request *req, - unsigned int hctx_idx, unsigned int numa_node) -{ - return __mmc_init_request(set->driver_data, req, GFP_KERNEL); -} - -static void mmc_mq_exit_request(struct blk_mq_tag_set *set, struct request *req, - unsigned int hctx_idx) -{ - struct mmc_queue *mq = set->driver_data; - - mmc_exit_request(mq->queue, req); -} - static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) { -- cgit v1.2.3