diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-28 16:52:18 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-28 16:52:18 -0800 |
commit | 00d59fde8532b2d42e80909d2e58678755e04da9 (patch) | |
tree | 5383ad260f0d0abc2fb624f8cd528e46a950317c /drivers/mmc/core | |
parent | 75f95da078b2891cd186f074ffc15a8e7c3f082d (diff) | |
parent | 5215b2e952f3f94d74cac1a59494eb8ac647e216 (diff) | |
download | linux-00d59fde8532b2d42e80909d2e58678755e04da9.tar.bz2 |
Merge tag 'mmc-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"This time, this pull request contains changes crossing subsystems and
archs/platforms, which is mainly because of a bigger modernization of
moving from legacy GPIO to GPIO descriptors for MMC (by Linus
Walleij).
Additionally, once again, I am funneling changes to
drivers/misc/cardreader/* and drivers/memstick/* through my MMC tree,
mostly due to that we lack a maintainer for these.
Summary:
MMC core:
- Cleanup BKOPS support
- Introduce MMC_CAP_SYNC_RUNTIME_PM
- slot-gpio: Delete legacy slot GPIO handling
MMC host:
- alcor: Add new mmc host driver for Alcor Micro PCI based cardreader
- bcm2835: Several improvements to better recover from errors
- jz4740: Rework and fixup pre|post_req support
- mediatek: Add support for SDIO IRQs
- meson-gx: Improve clock phase management
- meson-gx: Stop descriptor on errors
- mmci: Complete the sbc error path by sending a stop command
- renesas_sdhi/tmio: Fixup reset/resume operations
- renesas_sdhi: Add support for r8a774c0 and R7S9210
- renesas_sdhi: Whitelist R8A77990 SDHI
- renesas_sdhi: Fixup eMMC HS400 compatibility issues for H3 and M3-W
- rtsx_usb_sdmmc: Re-work card detection/removal support
- rtsx_usb_sdmmc: Re-work runtime PM support
- sdhci: Fix timeout loops for some variant drivers
- sdhci: Improve support for error handling due to failing commands
- sdhci-acpi/pci: Disable LED control for Intel BYT-based controllers
- sdhci_am654: Add new SDHCI variant driver to support TI's AM654 SOCs
- sdhci-of-esdhc: Add support for eMMC HS400 mode
- sdhci-omap: Fixup reset support
- sdhci-omap: Workaround errata regarding SDR104/HS200 tuning failures
- sdhci-msm: Fixup sporadic write transfers issues for SDR104/HS200
- sdhci-msm: Fixup dynamical clock gating issues
- various: Complete converting all hosts into using slot GPIO descriptors
Other:
- Move GPIO mmc platform data for mips/sh/arm to GPIO descriptors
- Add new Alcor Micro cardreader PCI driver
- Support runtime power management for memstick rtsx_usb_ms driver
- Use USB remote wakeups for card detection for rtsx_usb misc driver"
* tag 'mmc-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (99 commits)
mmc: mediatek: Add MMC_CAP_SDIO_IRQ support
mmc: renesas_sdhi_internal_dmac: Whitelist r8a774c0
dt-bindings: mmc: renesas_sdhi: Add r8a774c0 support
mmc: core: Cleanup BKOPS support
mmc: core: Drop redundant check in mmc_send_hpi_cmd()
mmc: sdhci-omap: Workaround errata regarding SDR104/HS200 tuning failures (i929)
dt-bindings: sdhci-omap: Add note for cpu_thermal
mmc: sdhci-acpi: Disable LED control for Intel BYT-based controllers
mmc: sdhci-pci: Disable LED control for Intel BYT-based controllers
mmc: sdhci: Add quirk to disable LED control
mmc: mmci: add variant property to set command stop bit
misc: alcor_pci: fix spelling mistake "invailid" -> "invalid"
mmc: meson-gx: add signal resampling
mmc: meson-gx: align default phase on soc vendor tree
mmc: meson-gx: remove useless lock
mmc: meson-gx: make sure the descriptor is stopped on errors
mmc: sdhci_am654: Add Initial Support for AM654 SDHCI driver
dt-bindings: mmc: sdhci-of-arasan: Add deprecated message for AM65
dt-bindings: mmc: sdhci-am654: Document bindings for the host controllers on TI's AM654 SOCs
mmc: sdhci-msm: avoid unused function warning
...
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/block.c | 2 | ||||
-rw-r--r-- | drivers/mmc/core/card.h | 6 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 19 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 2 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 9 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 93 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.h | 3 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_test.c | 14 | ||||
-rw-r--r-- | drivers/mmc/core/slot-gpio.c | 97 |
9 files changed, 41 insertions, 204 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 62e7619d5a4d..aef1185f383d 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1960,7 +1960,7 @@ static void mmc_blk_urgent_bkops(struct mmc_queue *mq, struct mmc_queue_req *mqrq) { if (mmc_blk_urgent_bkops_needed(mq, mqrq)) - mmc_start_bkops(mq->card, true); + mmc_run_bkops(mq->card); } void mmc_blk_mq_complete(struct request *req) diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index 1170feb8f969..eef301452406 100644 --- a/drivers/mmc/core/card.h +++ b/drivers/mmc/core/card.h @@ -23,15 +23,13 @@ #define MMC_STATE_BLOCKADDR (1<<2) /* card uses block-addressing */ #define MMC_CARD_SDXC (1<<3) /* card is SDXC */ #define MMC_CARD_REMOVED (1<<4) /* card has been removed */ -#define MMC_STATE_DOING_BKOPS (1<<5) /* card is doing BKOPS */ -#define MMC_STATE_SUSPENDED (1<<6) /* card is suspended */ +#define MMC_STATE_SUSPENDED (1<<5) /* card is suspended */ #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT) #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) -#define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) #define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) @@ -39,8 +37,6 @@ #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) -#define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS) -#define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS) #define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED) #define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 50a5c340307b..5bd58b95d318 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -887,7 +887,10 @@ void mmc_release_host(struct mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); wake_up(&host->wq); pm_runtime_mark_last_busy(mmc_dev(host)); - pm_runtime_put_autosuspend(mmc_dev(host)); + if (host->caps & MMC_CAP_SYNC_RUNTIME_PM) + pm_runtime_put_sync_suspend(mmc_dev(host)); + else + pm_runtime_put_autosuspend(mmc_dev(host)); } } EXPORT_SYMBOL(mmc_release_host); @@ -2413,20 +2416,6 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) } EXPORT_SYMBOL(mmc_set_blocklen); -int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount, - bool is_rel_write) -{ - struct mmc_command cmd = {}; - - cmd.opcode = MMC_SET_BLOCK_COUNT; - cmd.arg = blockcount & 0x0000FFFF; - if (is_rel_write) - cmd.arg |= 1 << 31; - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; - return mmc_wait_for_cmd(card->host, &cmd, 5); -} -EXPORT_SYMBOL(mmc_set_blockcount); - static void mmc_hw_reset_for_init(struct mmc_host *host) { mmc_pwrseq_reset(host); diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 087ba68b2920..8fb6bc37f808 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -118,8 +118,6 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, unsigned int mmc_calc_max_discard(struct mmc_card *card); int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen); -int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount, - bool is_rel_write); int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx, atomic_t *abort); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 55997cf84b39..da892a599524 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1181,6 +1181,9 @@ static int mmc_select_hs400(struct mmc_card *card) if (err) goto out_err; + if (host->ops->hs400_prepare_ddr) + host->ops->hs400_prepare_ddr(host); + /* Switch card to DDR */ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, @@ -2011,12 +2014,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_card_suspended(host->card)) goto out; - if (mmc_card_doing_bkops(host->card)) { - err = mmc_stop_bkops(host->card); - if (err) - goto out; - } - err = mmc_flush_cache(host->card); if (err) goto out; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 873b2aa0c155..9054329fe903 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -802,12 +802,6 @@ static int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) unsigned int opcode; int err; - if (!card->ext_csd.hpi) { - pr_warn("%s: Card didn't support HPI command\n", - mmc_hostname(card->host)); - return -EINVAL; - } - opcode = card->ext_csd.hpi_cmd; if (opcode == MMC_STOP_TRANSMISSION) cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; @@ -897,34 +891,6 @@ int mmc_can_ext_csd(struct mmc_card *card) return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3); } -/** - * mmc_stop_bkops - stop ongoing BKOPS - * @card: MMC card to check BKOPS - * - * Send HPI command to stop ongoing background operations to - * allow rapid servicing of foreground operations, e.g. read/ - * writes. Wait until the card comes out of the programming state - * to avoid errors in servicing read/write requests. - */ -int mmc_stop_bkops(struct mmc_card *card) -{ - int err = 0; - - err = mmc_interrupt_hpi(card); - - /* - * If err is EINVAL, we can't issue an HPI. - * It should complete the BKOPS. - */ - if (!err || (err == -EINVAL)) { - mmc_card_clr_doing_bkops(card); - mmc_retune_release(card->host); - err = 0; - } - - return err; -} - static int mmc_read_bkops_status(struct mmc_card *card) { int err; @@ -941,22 +907,17 @@ static int mmc_read_bkops_status(struct mmc_card *card) } /** - * mmc_start_bkops - start BKOPS for supported cards - * @card: MMC card to start BKOPS - * @from_exception: A flag to indicate if this function was - * called due to an exception raised by the card + * mmc_run_bkops - Run BKOPS for supported cards + * @card: MMC card to run BKOPS for * - * Start background operations whenever requested. - * When the urgent BKOPS bit is set in a R1 command response - * then background operations should be started immediately. + * Run background operations synchronously for cards having manual BKOPS + * enabled and in case it reports urgent BKOPS level. */ -void mmc_start_bkops(struct mmc_card *card, bool from_exception) +void mmc_run_bkops(struct mmc_card *card) { int err; - int timeout; - bool use_busy_signal; - if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card)) + if (!card->ext_csd.man_bkops_en) return; err = mmc_read_bkops_status(card); @@ -966,44 +927,26 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) return; } - if (!card->ext_csd.raw_bkops_status) - return; - - if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 && - from_exception) + if (!card->ext_csd.raw_bkops_status || + card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2) return; - if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) { - timeout = MMC_OPS_TIMEOUT_MS; - use_busy_signal = true; - } else { - timeout = 0; - use_busy_signal = false; - } - mmc_retune_hold(card->host); - err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BKOPS_START, 1, timeout, 0, - use_busy_signal, true, false); - if (err) { + /* + * For urgent BKOPS status, LEVEL_2 and higher, let's execute + * synchronously. Future wise, we may consider to start BKOPS, for less + * urgent levels by using an asynchronous background task, when idle. + */ + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BKOPS_START, 1, MMC_OPS_TIMEOUT_MS); + if (err) pr_warn("%s: Error %d starting bkops\n", mmc_hostname(card->host), err); - mmc_retune_release(card->host); - return; - } - /* - * For urgent bkops status (LEVEL_2 and more) - * bkops executed synchronously, otherwise - * the operation is in progress - */ - if (!use_busy_signal) - mmc_card_set_doing_bkops(card); - else - mmc_retune_release(card->host); + mmc_retune_release(card->host); } -EXPORT_SYMBOL(mmc_start_bkops); +EXPORT_SYMBOL(mmc_run_bkops); /* * Flush the cache to the non-volatile storage. diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index a1390d486381..018a5e3f66d6 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -40,8 +40,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, bool use_busy_signal, bool send_status, bool retry_crc_err); int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms); -int mmc_stop_bkops(struct mmc_card *card); -void mmc_start_bkops(struct mmc_card *card, bool from_exception); +void mmc_run_bkops(struct mmc_card *card); int mmc_flush_cache(struct mmc_card *card); int mmc_cmdq_enable(struct mmc_card *card); int mmc_cmdq_disable(struct mmc_card *card); diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c index ef18daeaa4cc..eabb1cab1765 100644 --- a/drivers/mmc/core/mmc_test.c +++ b/drivers/mmc/core/mmc_test.c @@ -3145,17 +3145,7 @@ static int mtf_testlist_show(struct seq_file *sf, void *data) return 0; } -static int mtf_testlist_open(struct inode *inode, struct file *file) -{ - return single_open(file, mtf_testlist_show, inode->i_private); -} - -static const struct file_operations mmc_test_fops_testlist = { - .open = mtf_testlist_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(mtf_testlist); static void mmc_test_free_dbgfs_file(struct mmc_card *card) { @@ -3216,7 +3206,7 @@ static int mmc_test_register_dbgfs_file(struct mmc_card *card) goto err; ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO, - &mmc_test_fops_testlist); + &mtf_testlist_fops); if (ret) goto err; diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 86803a3a04dc..319ccd93383d 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -9,7 +9,6 @@ */ #include <linux/err.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/jiffies.h> @@ -27,8 +26,8 @@ struct mmc_gpio { bool override_cd_active_level; irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id); char *ro_label; + char *cd_label; u32 cd_debounce_delay_ms; - char cd_label[]; }; static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) @@ -45,15 +44,19 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) int mmc_gpio_alloc(struct mmc_host *host) { - size_t len = strlen(dev_name(host->parent)) + 4; struct mmc_gpio *ctx = devm_kzalloc(host->parent, - sizeof(*ctx) + 2 * len, GFP_KERNEL); + sizeof(*ctx), GFP_KERNEL); if (ctx) { - ctx->ro_label = ctx->cd_label + len; ctx->cd_debounce_delay_ms = 200; - snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); - snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); + ctx->cd_label = devm_kasprintf(host->parent, GFP_KERNEL, + "%s cd", dev_name(host->parent)); + if (!ctx->cd_label) + return -ENOMEM; + ctx->ro_label = devm_kasprintf(host->parent, GFP_KERNEL, + "%s ro", dev_name(host->parent)); + if (!ctx->ro_label) + return -ENOMEM; host->slot.handler_priv = ctx; host->slot.cd_irq = -EINVAL; } @@ -98,36 +101,6 @@ int mmc_gpio_get_cd(struct mmc_host *host) } EXPORT_SYMBOL(mmc_gpio_get_cd); -/** - * mmc_gpio_request_ro - request a gpio for write-protection - * @host: mmc host - * @gpio: gpio number requested - * - * As devm_* managed functions are used in mmc_gpio_request_ro(), client - * drivers do not need to worry about freeing up memory. - * - * Returns zero on success, else an error. - */ -int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) -{ - struct mmc_gpio *ctx = host->slot.handler_priv; - int ret; - - if (!gpio_is_valid(gpio)) - return -EINVAL; - - ret = devm_gpio_request_one(host->parent, gpio, GPIOF_DIR_IN, - ctx->ro_label); - if (ret < 0) - return ret; - - ctx->override_ro_active_level = true; - ctx->ro_gpio = gpio_to_desc(gpio); - - return 0; -} -EXPORT_SYMBOL(mmc_gpio_request_ro); - void mmc_gpiod_request_cd_irq(struct mmc_host *host) { struct mmc_gpio *ctx = host->slot.handler_priv; @@ -197,50 +170,6 @@ void mmc_gpio_set_cd_isr(struct mmc_host *host, EXPORT_SYMBOL(mmc_gpio_set_cd_isr); /** - * mmc_gpio_request_cd - request a gpio for card-detection - * @host: mmc host - * @gpio: gpio number requested - * @debounce: debounce time in microseconds - * - * As devm_* managed functions are used in mmc_gpio_request_cd(), client - * drivers do not need to worry about freeing up memory. - * - * If GPIO debouncing is desired, set the debounce parameter to a non-zero - * value. The caller is responsible for ensuring that the GPIO driver associated - * with the GPIO supports debouncing, otherwise an error will be returned. - * - * Returns zero on success, else an error. - */ -int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, - unsigned int debounce) -{ - struct mmc_gpio *ctx = host->slot.handler_priv; - int ret; - - ret = devm_gpio_request_one(host->parent, gpio, GPIOF_DIR_IN, - ctx->cd_label); - if (ret < 0) - /* - * don't bother freeing memory. It might still get used by other - * slot functions, in any case it will be freed, when the device - * is destroyed. - */ - return ret; - - if (debounce) { - ret = gpio_set_debounce(gpio, debounce); - if (ret < 0) - return ret; - } - - ctx->override_cd_active_level = true; - ctx->cd_gpio = gpio_to_desc(gpio); - - return 0; -} -EXPORT_SYMBOL(mmc_gpio_request_cd); - -/** * mmc_gpiod_request_cd - request a gpio descriptor for card-detection * @host: mmc host * @con_id: function within the GPIO consumer @@ -250,8 +179,7 @@ EXPORT_SYMBOL(mmc_gpio_request_cd); * @gpio_invert: will return whether the GPIO line is inverted or not, set * to NULL to ignore * - * Use this function in place of mmc_gpio_request_cd() to use the GPIO - * descriptor API. Note that it must be called prior to mmc_add_host() + * Note that this must be called prior to mmc_add_host() * otherwise the caller must also call mmc_gpiod_request_cd_irq(). * * Returns zero on success, else an error. @@ -302,9 +230,6 @@ EXPORT_SYMBOL(mmc_can_gpio_cd); * @gpio_invert: will return whether the GPIO line is inverted or not, * set to NULL to ignore * - * Use this function in place of mmc_gpio_request_ro() to use the GPIO - * descriptor API. - * * Returns zero on success, else an error. */ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, |