diff options
Diffstat (limited to 'drivers/mmc/core')
43 files changed, 6527 insertions, 2787 deletions
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index 2f38a7ad07e0..14d2ecbb04d3 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only # # MMC core configuration # @@ -14,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 != n || BT_MRVL_SDIO != n || LIBERTAS_SDIO != n || WILC1000_SDIO != n) help This selects hardware reset support for the SD8787 BT + Wifi module. By default this option is set to n. @@ -36,6 +37,8 @@ config PWRSEQ_SIMPLE config MMC_BLOCK tristate "MMC block device driver" depends on BLOCK + depends on RPMB || !RPMB + imply IOSCHED_BFQ default y help Say Y here to enable the MMC block device driver support. @@ -80,3 +83,11 @@ config MMC_TEST This driver is only of interest to those developing or testing a host driver. Most people should say N here. +config MMC_CRYPTO + bool "MMC Crypto Engine Support" + depends on BLK_INLINE_ENCRYPTION + help + Enable Crypto Engine Support in MMC. + Enabling this makes it possible for the kernel to use the crypto + capabilities of the MMC device (if present) to perform crypto + operations on data being transferred to/from the device. diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index abba078f7f49..15b067e8b0d1 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile @@ -7,8 +7,8 @@ obj-$(CONFIG_MMC) += mmc_core.o mmc_core-y := core.o bus.o host.o \ mmc.o mmc_ops.o sd.o sd_ops.o \ sdio.o sdio_ops.o sdio_bus.o \ - sdio_cis.o sdio_io.o sdio_irq.o \ - slot-gpio.o + sdio_cis.o sdio_io.o sdio_irq.o sd_uhs2.o\ + slot-gpio.o regulator.o mmc_core-$(CONFIG_OF) += pwrseq.o obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o obj-$(CONFIG_PWRSEQ_SD8787) += pwrseq_sd8787.o @@ -18,3 +18,4 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o mmc_block-objs := block.o queue.o obj-$(CONFIG_MMC_TEST) += mmc_test.o obj-$(CONFIG_SDIO_UART) += sdio_uart.o +mmc_core-$(CONFIG_MMC_CRYPTO) += crypto.o diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index aef1185f383d..fb6eb2d79b4f 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Block driver for media (i.e., flash cards) * @@ -27,10 +28,12 @@ #include <linux/errno.h> #include <linux/hdreg.h> #include <linux/kdev_t.h> +#include <linux/kref.h> #include <linux/blkdev.h> #include <linux/cdev.h> #include <linux/mutex.h> #include <linux/scatterlist.h> +#include <linux/string.h> #include <linux/string_helpers.h> #include <linux/delay.h> #include <linux/capability.h> @@ -38,6 +41,7 @@ #include <linux/pm_runtime.h> #include <linux/idr.h> #include <linux/debugfs.h> +#include <linux/rpmb.h> #include <linux/mmc/ioctl.h> #include <linux/mmc/card.h> @@ -46,11 +50,13 @@ #include <linux/mmc/sd.h> #include <linux/uaccess.h> +#include <linux/unaligned.h> #include "queue.h" #include "block.h" #include "core.h" #include "card.h" +#include "crypto.h" #include "host.h" #include "bus.h" #include "mmc_ops.h" @@ -70,12 +76,13 @@ MODULE_ALIAS("mmc:block"); * ample. */ #define MMC_BLK_TIMEOUT_MS (10 * 1000) -#define MMC_SANITIZE_REQ_TIMEOUT 240000 #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) #define MMC_EXTRACT_VALUE_FROM_ARG(x) ((x & 0x0000FF00) >> 8) -#define mmc_req_rel_wr(req) ((req->cmd_flags & REQ_FUA) && \ - (rq_data_dir(req) == WRITE)) +#define RPMB_FRAME_SIZE sizeof(struct rpmb_frame) +#define CHECK_SIZE_NEQ(val) ((val) != sizeof(struct rpmb_frame)) +#define CHECK_SIZE_ALIGNED(val) IS_ALIGNED((val), sizeof(struct rpmb_frame)) + static DEFINE_MUTEX(block_mutex); /* @@ -96,6 +103,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. */ @@ -110,7 +122,7 @@ struct mmc_blk_data { #define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */ #define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */ - unsigned int usage; + struct kref kref; unsigned int read_only; unsigned int part_type; unsigned int reset_done; @@ -119,6 +131,7 @@ struct mmc_blk_data { #define MMC_BLK_DISCARD BIT(2) #define MMC_BLK_SECDISCARD BIT(3) #define MMC_BLK_CQE_RECOVERY BIT(4) +#define MMC_BLK_TRIM BIT(5) /* * Only set in main mmc_blk_data associated @@ -126,8 +139,7 @@ struct mmc_blk_data { * track of the current selected device partition. */ unsigned int part_curr; - struct device_attribute force_ro; - struct device_attribute power_ro_lock; +#define MMC_BLK_PART_INVALID UINT_MAX /* Unknown partition active */ int area_type; /* debugfs files (only in main mmc_blk_data) */ @@ -139,7 +151,7 @@ struct mmc_blk_data { static dev_t mmc_rpmb_devt; /* Bus type for RPMB character devices */ -static struct bus_type mmc_rpmb_bus_type = { +static const struct bus_type mmc_rpmb_bus_type = { .name = "mmc_rpmb", }; @@ -150,6 +162,7 @@ static struct bus_type mmc_rpmb_bus_type = { * @id: unique device ID number * @part_index: partition index (0 on first) * @md: parent MMC block device + * @rdev: registered RPMB device * @node: list item, so we can put this device on a list */ struct mmc_rpmb_data { @@ -158,6 +171,7 @@ struct mmc_rpmb_data { int id; unsigned int part_index; struct mmc_blk_data *md; + struct rpmb_dev *rdev; struct list_head node; }; @@ -168,6 +182,13 @@ MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); static inline int mmc_blk_part_switch(struct mmc_card *card, unsigned int part_type); +static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + struct mmc_card *card, + int recovery_mode, + struct mmc_queue *mq); +static void mmc_blk_hsq_req_done(struct mmc_request *mrq); +static int mmc_spi_err_check(struct mmc_card *card); +static int mmc_blk_busy_cb(void *cb_data, bool *busy); static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) { @@ -175,10 +196,8 @@ static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) mutex_lock(&open_lock); md = disk->private_data; - if (md && md->usage == 0) + if (md && !kref_get_unless_zero(&md->kref)) md = NULL; - if (md) - md->usage++; mutex_unlock(&open_lock); return md; @@ -190,18 +209,25 @@ static inline int mmc_get_devidx(struct gendisk *disk) return devidx; } -static void mmc_blk_put(struct mmc_blk_data *md) +static void mmc_blk_kref_release(struct kref *ref) { + struct mmc_blk_data *md = container_of(ref, struct mmc_blk_data, kref); + int devidx; + + devidx = mmc_get_devidx(md->disk); + ida_free(&mmc_blk_ida, devidx); + mutex_lock(&open_lock); - md->usage--; - if (md->usage == 0) { - int devidx = mmc_get_devidx(md->disk); - blk_put_queue(md->queue.queue); - ida_simple_remove(&mmc_blk_ida, devidx); - put_disk(md->disk); - kfree(md); - } + md->disk->private_data = NULL; mutex_unlock(&open_lock); + + put_disk(md->disk); + kfree(md); +} + +static void mmc_blk_put(struct mmc_blk_data *md) +{ + kref_put(&md->kref, mmc_blk_kref_release); } static ssize_t power_ro_lock_show(struct device *dev, @@ -217,7 +243,7 @@ static ssize_t power_ro_lock_show(struct device *dev, else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN) locked = 1; - ret = snprintf(buf, PAGE_SIZE, "%d\n", locked); + ret = sysfs_emit(buf, "%d\n", locked); mmc_blk_put(md); @@ -243,15 +269,16 @@ static ssize_t power_ro_lock_store(struct device *dev, mq = &md->queue; /* Dispatch locking to the block layer */ - req = blk_get_request(mq->queue, REQ_OP_DRV_OUT, 0); + req = blk_mq_alloc_request(mq->queue, REQ_OP_DRV_OUT, 0); if (IS_ERR(req)) { count = PTR_ERR(req); goto out_put; } req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP; - blk_execute_rq(mq->queue, NULL, req, 0); + req_to_mmc_queue_req(req)->drv_op_result = -EIO; + blk_execute_rq(req, false); ret = req_to_mmc_queue_req(req)->drv_op_result; - blk_put_request(req); + blk_mq_free_request(req); if (!ret) { pr_info("%s: Locking boot partition ro until next power on\n", @@ -269,15 +296,18 @@ out_put: return count; } +static DEVICE_ATTR(ro_lock_until_next_power_on, 0, + power_ro_lock_show, power_ro_lock_store); + static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret; struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); - ret = snprintf(buf, PAGE_SIZE, "%d\n", - get_disk_ro(dev_to_disk(dev)) ^ - md->read_only); + ret = sysfs_emit(buf, "%d\n", + get_disk_ro(dev_to_disk(dev)) ^ + md->read_only); mmc_blk_put(md); return ret; } @@ -286,10 +316,10 @@ static ssize_t force_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int ret; - char *end; struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); - unsigned long set = simple_strtoul(buf, &end, 0); - if (end == buf) { + unsigned long set; + + if (kstrtoul(buf, 0, &set)) { ret = -EINVAL; goto out; } @@ -301,18 +331,53 @@ out: return ret; } -static int mmc_blk_open(struct block_device *bdev, fmode_t mode) +static DEVICE_ATTR(force_ro, 0644, force_ro_show, force_ro_store); + +static struct attribute *mmc_disk_attrs[] = { + &dev_attr_force_ro.attr, + &dev_attr_ro_lock_until_next_power_on.attr, + NULL, +}; + +static umode_t mmc_disk_attrs_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); + umode_t mode = a->mode; + + if (a == &dev_attr_ro_lock_until_next_power_on.attr && + (md->area_type & MMC_BLK_DATA_AREA_BOOT) && + md->queue.card->ext_csd.boot_ro_lockable) { + mode = 0444; + if (!(md->queue.card->ext_csd.boot_ro_lock & + EXT_CSD_BOOT_WP_B_PWR_WP_DIS)) + mode |= 0200; + } + + mmc_blk_put(md); + return mode; +} + +static const struct attribute_group mmc_disk_attr_group = { + .is_visible = mmc_disk_attrs_is_visible, + .attrs = mmc_disk_attrs, +}; + +static const struct attribute_group *mmc_disk_attr_groups[] = { + &mmc_disk_attr_group, + NULL, +}; + +static int mmc_blk_open(struct gendisk *disk, blk_mode_t mode) { - struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); + struct mmc_blk_data *md = mmc_blk_get(disk); int ret = -ENXIO; mutex_lock(&block_mutex); if (md) { - if (md->usage == 2) - check_disk_change(bdev); ret = 0; - - if ((mode & FMODE_WRITE) && md->read_only) { + if ((mode & BLK_OPEN_WRITE) && md->read_only) { mmc_blk_put(md); ret = -EROFS; } @@ -322,7 +387,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode) return ret; } -static void mmc_blk_release(struct gendisk *disk, fmode_t mode) +static void mmc_blk_release(struct gendisk *disk) { struct mmc_blk_data *md = disk->private_data; @@ -332,9 +397,9 @@ static void mmc_blk_release(struct gendisk *disk, fmode_t mode) } static int -mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) +mmc_blk_getgeo(struct gendisk *disk, struct hd_geometry *geo) { - geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); + geo->cylinders = get_capacity(disk) / (4 * 16); geo->heads = 4; geo->sectors = 16; return 0; @@ -344,6 +409,10 @@ struct mmc_blk_ioc_data { struct mmc_ioc_cmd ic; unsigned char *buf; u64 buf_bytes; + unsigned int flags; +#define MMC_BLK_IOC_DROP BIT(0) /* drop this mrq */ +#define MMC_BLK_IOC_SBC BIT(1) /* use mrq.sbc */ + struct mmc_rpmb_data *rpmb; }; @@ -353,7 +422,7 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user( struct mmc_blk_ioc_data *idata; int err; - idata = kmalloc(sizeof(*idata), GFP_KERNEL); + idata = kzalloc(sizeof(*idata), GFP_KERNEL); if (!idata) { err = -ENOMEM; goto out; @@ -408,80 +477,29 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr, return 0; } -static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, - u32 retries_max) -{ - int err; - u32 retry_count = 0; - - if (!status || !retries_max) - return -EINVAL; - - do { - err = __mmc_send_status(card, status, 5); - if (err) - break; - - if (!R1_STATUS(*status) && - (R1_CURRENT_STATE(*status) != R1_STATE_PRG)) - break; /* RPMB programming operation complete */ - - /* - * Rechedule to give the MMC device a chance to continue - * processing the previous command without being polled too - * frequently. - */ - usleep_range(1000, 5000); - } while (++retry_count < retries_max); - - if (retry_count == retries_max) - err = -EPERM; - - return err; -} - -static int ioctl_do_sanitize(struct mmc_card *card) -{ - int err; - - if (!mmc_can_sanitize(card)) { - pr_warn("%s: %s - SANITIZE is not supported\n", - mmc_hostname(card->host), __func__); - err = -EOPNOTSUPP; - goto out; - } - - pr_debug("%s: %s - SANITIZE IN PROGRESS...\n", - mmc_hostname(card->host), __func__); - - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_SANITIZE_START, 1, - MMC_SANITIZE_REQ_TIMEOUT); - - if (err) - pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n", - mmc_hostname(card->host), __func__, err); - - pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host), - __func__); -out: - return err; -} - static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, - struct mmc_blk_ioc_data *idata) + struct mmc_blk_ioc_data **idatas, int i) { struct mmc_command cmd = {}, sbc = {}; struct mmc_data data = {}; struct mmc_request mrq = {}; struct scatterlist sg; + bool r1b_resp; + unsigned int busy_timeout_ms; int err; unsigned int target_part; - u32 status = 0; + struct mmc_blk_ioc_data *idata = idatas[i]; + struct mmc_blk_ioc_data *prev_idata = NULL; if (!card || !md || !idata) return -EINVAL; + if (idata->flags & MMC_BLK_IOC_DROP) + return 0; + + if (idata->flags & MMC_BLK_IOC_SBC && i > 0) + prev_idata = idatas[i - 1]; + /* * The RPMB accesses comes in from the character device, so we * need to target these explicitly. Else we just target the @@ -520,19 +538,6 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, if (idata->ic.data_timeout_ns) data.timeout_ns = idata->ic.data_timeout_ns; - if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) { - /* - * Pretend this is a data transfer and rely on the - * host driver to compute timeout. When all host - * drivers support cmd.cmd_timeout for R1B, this - * can be changed to: - * - * mrq.data = NULL; - * cmd.cmd_timeout = idata->ic.cmd_timeout_ms; - */ - data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000; - } - mrq.data = &data; } @@ -548,7 +553,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, return err; } - if (idata->rpmb) { + if (idata->rpmb || prev_idata) { sbc.opcode = MMC_SET_BLOCK_COUNT; /* * We don't do any blockcount validation because the max size @@ -556,22 +561,33 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, * 'Reliable Write' bit here. */ sbc.arg = data.blocks | (idata->ic.write_flag & BIT(31)); + if (prev_idata) + sbc.arg = prev_idata->ic.arg; sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; mrq.sbc = &sbc; } if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) && - (cmd.opcode == MMC_SWITCH)) { - err = ioctl_do_sanitize(card); + (cmd.opcode == MMC_SWITCH)) + return mmc_sanitize(card, idata->ic.cmd_timeout_ms); - if (err) - pr_err("%s: ioctl_do_sanitize() failed. err = %d", - __func__, err); - - return err; - } + /* If it's an R1B response we need some more preparations. */ + busy_timeout_ms = idata->ic.cmd_timeout_ms ? : MMC_BLK_TIMEOUT_MS; + r1b_resp = (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B; + if (r1b_resp) + mmc_prepare_busy_cmd(card->host, &cmd, busy_timeout_ms); mmc_wait_for_req(card->host, &mrq); + memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp)); + + if (prev_idata) { + memcpy(&prev_idata->ic.response, sbc.resp, sizeof(sbc.resp)); + if (sbc.error) { + dev_err(mmc_dev(card->host), "%s: sbc error %d\n", + __func__, sbc.error); + return sbc.error; + } + } if (cmd.error) { dev_err(mmc_dev(card->host), "%s: cmd error %d\n", @@ -603,24 +619,45 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, } /* + * Make sure to update CACHE_CTRL in case it was changed. The cache + * will get turned back on if the card is re-initialized, e.g. + * suspend/resume or hw reset in recovery. + */ + if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_CACHE_CTRL) && + (cmd.opcode == MMC_SWITCH)) { + u8 value = MMC_EXTRACT_VALUE_FROM_ARG(cmd.arg) & 1; + + card->ext_csd.cache_ctrl = value; + } + + /* * According to the SD specs, some commands require a delay after * issuing the command. */ 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 (mmc_host_is_spi(card->host)) { + if (idata->ic.write_flag || r1b_resp || cmd.flags & MMC_RSP_SPI_BUSY) + return mmc_spi_err_check(card); + return err; + } - if (idata->rpmb) { - /* - * Ensure RPMB command has completed by polling CMD13 - * "Send Status". - */ - err = ioctl_rpmb_card_status_poll(card, &status, 5); - if (err) - dev_err(mmc_dev(card->host), - "%s: Card Status=0x%08X, error %d\n", - __func__, status, err); + /* + * Ensure RPMB, writes and R1B responses are completed by polling with + * CMD13. Note that, usually we don't need to poll when using HW busy + * detection, but here it's needed since some commands may indicate the + * error through the R1 status bits. + */ + if (idata->rpmb || idata->ic.write_flag || r1b_resp) { + struct mmc_blk_busy_data cb_data = { + .card = card, + }; + + err = __mmc_poll_for_busy(card->host, 0, busy_timeout_ms, + &mmc_blk_busy_cb, &cb_data); + + idata->ic.response[0] = cb_data.status; } return err; @@ -653,7 +690,7 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md, * Dispatch the ioctl() into the block request queue. */ mq = &md->queue; - req = blk_get_request(mq->queue, + req = blk_mq_alloc_request(mq->queue, idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); if (IS_ERR(req)) { err = PTR_ERR(req); @@ -662,12 +699,13 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md, idatas[0] = idata; req_to_mmc_queue_req(req)->drv_op = rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL; + req_to_mmc_queue_req(req)->drv_op_result = -EIO; req_to_mmc_queue_req(req)->drv_op_data = idatas; req_to_mmc_queue_req(req)->ioc_count = 1; - blk_execute_rq(mq->queue, NULL, req, 0); + blk_execute_rq(req, false); ioc_err = req_to_mmc_queue_req(req)->drv_op_result; err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata); - blk_put_request(req); + blk_mq_free_request(req); cmd_done: kfree(idata->buf); @@ -683,8 +721,9 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md, struct mmc_ioc_cmd __user *cmds = user->cmds; struct mmc_card *card; struct mmc_queue *mq; - int i, err = 0, ioc_err = 0; + int err = 0, ioc_err = 0; __u64 num_of_cmds; + unsigned int i, n; struct request *req; if (copy_from_user(&num_of_cmds, &user->num_of_cmds, @@ -697,15 +736,16 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md, if (num_of_cmds > MMC_IOC_MAX_CMDS) return -EINVAL; - idata = kcalloc(num_of_cmds, sizeof(*idata), GFP_KERNEL); + n = num_of_cmds; + idata = kcalloc(n, sizeof(*idata), GFP_KERNEL); if (!idata) return -ENOMEM; - for (i = 0; i < num_of_cmds; i++) { + for (i = 0; i < n; i++) { idata[i] = mmc_blk_ioctl_copy_from_user(&cmds[i]); if (IS_ERR(idata[i])) { err = PTR_ERR(idata[i]); - num_of_cmds = i; + n = i; goto cmd_err; } /* This will be NULL on non-RPMB ioctl():s */ @@ -723,7 +763,7 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md, * Dispatch the ioctl()s into the block request queue. */ mq = &md->queue; - req = blk_get_request(mq->queue, + req = blk_mq_alloc_request(mq->queue, idata[0]->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); if (IS_ERR(req)) { err = PTR_ERR(req); @@ -731,19 +771,20 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md, } req_to_mmc_queue_req(req)->drv_op = rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL; + req_to_mmc_queue_req(req)->drv_op_result = -EIO; req_to_mmc_queue_req(req)->drv_op_data = idata; - req_to_mmc_queue_req(req)->ioc_count = num_of_cmds; - blk_execute_rq(mq->queue, NULL, req, 0); + req_to_mmc_queue_req(req)->ioc_count = n; + blk_execute_rq(req, false); ioc_err = req_to_mmc_queue_req(req)->drv_op_result; /* copy to user if data and response */ - for (i = 0; i < num_of_cmds && !err; i++) + for (i = 0; i < n && !err; i++) err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]); - blk_put_request(req); + blk_mq_free_request(req); cmd_err: - for (i = 0; i < num_of_cmds; i++) { + for (i = 0; i < n; i++) { kfree(idata[i]->buf); kfree(idata[i]); } @@ -758,12 +799,12 @@ static int mmc_blk_check_blkdev(struct block_device *bdev) * whole block device, not on a partition. This prevents overspray * between sibling partitions. */ - if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains)) + if (!capable(CAP_SYS_RAWIO) || bdev_is_partition(bdev)) return -EPERM; return 0; } -static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, +static int mmc_blk_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { struct mmc_blk_data *md; @@ -800,13 +841,33 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, } #ifdef CONFIG_COMPAT -static int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode, +static int mmc_blk_compat_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg) { return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg)); } #endif +static int mmc_blk_alternative_gpt_sector(struct gendisk *disk, + sector_t *sector) +{ + struct mmc_blk_data *md; + int ret; + + md = mmc_blk_get(disk); + if (!md) + return -EINVAL; + + if (md->queue.card) + ret = mmc_card_alternative_gpt_sector(md->queue.card, sector); + else + ret = -ENODEV; + + mmc_blk_put(md); + + return ret; +} + static const struct block_device_operations mmc_bdops = { .open = mmc_blk_open, .release = mmc_blk_release, @@ -816,14 +877,17 @@ static const struct block_device_operations mmc_bdops = { #ifdef CONFIG_COMPAT .compat_ioctl = mmc_blk_compat_ioctl, #endif + .alternative_gpt_sector = mmc_blk_alternative_gpt_sector, }; static int mmc_blk_part_switch_pre(struct mmc_card *card, unsigned int part_type) { + const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_MASK; + const unsigned int rpmb = EXT_CSD_PART_CONFIG_ACC_RPMB; int ret = 0; - if (part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) { + if ((part_type & mask) == rpmb) { if (card->ext_csd.cmdq_en) { ret = mmc_cmdq_disable(card); if (ret) @@ -838,9 +902,11 @@ static int mmc_blk_part_switch_pre(struct mmc_card *card, static int mmc_blk_part_switch_post(struct mmc_card *card, unsigned int part_type) { + const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_MASK; + const unsigned int rpmb = EXT_CSD_PART_CONFIG_ACC_RPMB; int ret = 0; - if (part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) { + if ((part_type & mask) == rpmb) { mmc_retune_unpause(card->host); if (card->reenable_cmdq && !card->ext_csd.cmdq_en) ret = mmc_cmdq_enable(card); @@ -890,30 +956,22 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks) int err; u32 result; __be32 *blocks; + u8 resp_sz = mmc_card_ult_capacity(card) ? 8 : 4; struct mmc_request mrq = {}; struct mmc_command cmd = {}; struct mmc_data data = {}; - struct scatterlist sg; - cmd.opcode = MMC_APP_CMD; - cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; - - err = mmc_wait_for_cmd(card->host, &cmd, 0); + err = mmc_app_cmd(card->host, card); if (err) return err; - if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD)) - return -EIO; - - memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = SD_APP_SEND_NUM_WR_BLKS; cmd.arg = 0; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; - data.blksz = 4; + data.blksz = resp_sz; data.blocks = 1; data.flags = MMC_DATA_READ; data.sg = &sg; @@ -923,15 +981,27 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks) mrq.cmd = &cmd; mrq.data = &data; - blocks = kmalloc(4, GFP_KERNEL); + blocks = kmalloc(resp_sz, GFP_NOIO); if (!blocks) return -ENOMEM; - sg_init_one(&sg, blocks, 4); + sg_init_one(&sg, blocks, resp_sz); mmc_wait_for_req(card->host, &mrq); - result = ntohl(*blocks); + if (mmc_card_ult_capacity(card)) { + /* + * Normally, ACMD22 returns the number of written sectors as + * u32. SDUC, however, returns it as u64. This is not a + * superfluous requirement, because SDUC writes may exceed 2TB. + * For Linux mmc however, the previously write operation could + * not be more than the block layer limits, thus just make room + * for a u64 and cast the response back to u32. + */ + result = clamp_val(get_unaligned_be64(blocks), 0, UINT_MAX); + } else { + result = ntohl(*blocks); + } kfree(blocks); if (cmd.error || data.error) @@ -970,85 +1040,39 @@ static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host, return ms; } -static inline bool mmc_blk_in_tran_state(u32 status) -{ - /* - * Some cards mishandle the status bits, so make sure to check both the - * busy indication and the card state. - */ - return status & R1_READY_FOR_DATA && - (R1_CURRENT_STATE(status) == R1_STATE_TRAN); -} - -static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, - struct request *req, 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) { - pr_err("%s: error %d requesting status\n", - req->rq_disk->disk_name, 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) { - pr_err("%s: Card stuck in wrong state! %s %s status: %#x\n", - mmc_hostname(card->host), - req->rq_disk->disk_name, __func__, status); - return -ETIMEDOUT; - } - - /* - * Some cards mishandle the status bits, - * so make sure to check both the busy - * indication and the card state. - */ - } while (!mmc_blk_in_tran_state(status)); - - return err; -} - +/* + * Attempts to reset the card and get back to the requested partition. + * Therefore any error here must result in cancelling the block layer + * request, it must not be reattempted without going through the mmc_blk + * partition sanity checks. + */ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, int type) { int err; + struct mmc_blk_data *main_md = dev_get_drvdata(&host->card->dev); if (md->reset_done & type) return -EEXIST; md->reset_done |= type; - err = mmc_hw_reset(host); + err = mmc_hw_reset(host->card); + /* + * A successful reset will leave the card in the main partition, but + * upon failure it might not be, so set it to MMC_BLK_PART_INVALID + * in that case. + */ + main_md->part_curr = err ? MMC_BLK_PART_INVALID : main_md->part_type; + if (err) + return err; /* Ensure we switch back to the correct partition */ - if (err != -EOPNOTSUPP) { - struct mmc_blk_data *main_md = - dev_get_drvdata(&host->card->dev); - int part_err; - - main_md->part_curr = main_md->part_type; - part_err = mmc_blk_part_switch(host->card, md->part_type); - if (part_err) { - /* - * We have failed to get back into the correct - * partition, so we need to abort the whole request. - */ - return -ENODEV; - } - } - return err; + if (mmc_blk_part_switch(host->card, md->part_type)) + /* + * We have failed to get back into the correct + * partition, so we need to abort the whole request. + */ + return -ENODEV; + return 0; } static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) @@ -1056,6 +1080,20 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) md->reset_done &= ~type; } +static void mmc_blk_check_sbc(struct mmc_queue_req *mq_rq) +{ + struct mmc_blk_ioc_data **idata = mq_rq->drv_op_data; + int i; + + for (i = 1; i < mq_rq->ioc_count; i++) { + if (idata[i - 1]->ic.opcode == MMC_SET_BLOCK_COUNT && + mmc_op_multi(idata[i]->ic.opcode)) { + idata[i - 1]->flags |= MMC_BLK_IOC_DROP; + idata[i]->flags |= MMC_BLK_IOC_SBC; + } + } +} + /* * The non-block commands come back from the block layer after it queued it and * processed it with all other requests and then they get issued in this @@ -1078,16 +1116,27 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) switch (mq_rq->drv_op) { case MMC_DRV_OP_IOCTL: + if (card->ext_csd.cmdq_en) { + ret = mmc_cmdq_disable(card); + if (ret) + break; + } + + mmc_blk_check_sbc(mq_rq); + + fallthrough; case MMC_DRV_OP_IOCTL_RPMB: idata = mq_rq->drv_op_data; for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) { - ret = __mmc_blk_ioctl_cmd(card, md, idata[i]); + ret = __mmc_blk_ioctl_cmd(card, md, idata, i); if (ret) break; } /* Always switch back to main area after RPMB access */ if (rpmb_ioctl) mmc_blk_part_switch(card, 0); + else if (card->reenable_cmdq && !card->ext_csd.cmdq_en) + mmc_cmdq_enable(card); break; case MMC_DRV_OP_BOOT_WP: ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, @@ -1120,15 +1169,17 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK); } -static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) +static void mmc_blk_issue_erase_rq(struct mmc_queue *mq, struct request *req, + int type, unsigned int erase_arg) { struct mmc_blk_data *md = mq->blkdata; struct mmc_card *card = md->queue.card; - unsigned int from, nr, arg; - int err = 0, type = MMC_BLK_DISCARD; + unsigned int nr; + sector_t from; + int err = 0; blk_status_t status = BLK_STS_OK; - if (!mmc_can_erase(card)) { + if (!mmc_card_can_erase(card)) { status = BLK_STS_NOTSUPP; goto fail; } @@ -1136,24 +1187,18 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) from = blk_rq_pos(req); nr = blk_rq_sectors(req); - if (mmc_can_discard(card)) - arg = MMC_DISCARD_ARG; - else if (mmc_can_trim(card)) - arg = MMC_TRIM_ARG; - else - arg = MMC_ERASE_ARG; do { err = 0; if (card->quirks & MMC_QUIRK_INAND_CMD38) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, INAND_CMD38_ARG_EXT_CSD, - arg == MMC_TRIM_ARG ? + erase_arg == MMC_TRIM_ARG ? INAND_CMD38_ARG_TRIM : INAND_CMD38_ARG_ERASE, - 0); + card->ext_csd.generic_cmd6_time); } if (!err) - err = mmc_erase(card, from, nr, arg); + err = mmc_erase(card, from, nr, erase_arg); } while (err == -EIO && !mmc_blk_reset(md, card->host, type)); if (err) status = BLK_STS_IOERR; @@ -1163,16 +1208,34 @@ fail: blk_mq_end_request(req, status); } +static void mmc_blk_issue_trim_rq(struct mmc_queue *mq, struct request *req) +{ + mmc_blk_issue_erase_rq(mq, req, MMC_BLK_TRIM, MMC_TRIM_ARG); +} + +static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) +{ + struct mmc_blk_data *md = mq->blkdata; + struct mmc_card *card = md->queue.card; + unsigned int arg = card->erase_arg; + + if (mmc_card_broken_sd_discard(card)) + arg = SD_ERASE_ARG; + + mmc_blk_issue_erase_rq(mq, req, MMC_BLK_DISCARD, arg); +} + static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, struct request *req) { struct mmc_blk_data *md = mq->blkdata; struct mmc_card *card = md->queue.card; - unsigned int from, nr, arg; + unsigned int nr, arg; + sector_t from; int err = 0, type = MMC_BLK_SECDISCARD; blk_status_t status = BLK_STS_OK; - if (!(mmc_can_secure_erase_trim(card))) { + if (!(mmc_card_can_secure_erase_trim(card))) { status = BLK_STS_NOTSUPP; goto out; } @@ -1180,7 +1243,7 @@ static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, from = blk_rq_pos(req); nr = blk_rq_sectors(req); - if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) + if (mmc_card_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) arg = MMC_SECURE_TRIM1_ARG; else arg = MMC_SECURE_ERASE_ARG; @@ -1192,7 +1255,7 @@ retry: arg == MMC_SECURE_TRIM1_ARG ? INAND_CMD38_ARG_SECTRIM1 : INAND_CMD38_ARG_SECERASE, - 0); + card->ext_csd.generic_cmd6_time); if (err) goto out_retry; } @@ -1210,7 +1273,7 @@ retry: err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, INAND_CMD38_ARG_EXT_CSD, INAND_CMD38_ARG_SECTRIM2, - 0); + card->ext_csd.generic_cmd6_time); if (err) goto out_retry; } @@ -1239,7 +1302,7 @@ static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) struct mmc_card *card = md->queue.card; int ret = 0; - ret = mmc_flush_cache(card); + ret = mmc_flush_cache(card->host); blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK); } @@ -1321,7 +1384,7 @@ static void mmc_blk_eval_resp_error(struct mmc_blk_request *brq) } static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, - int disable_multi, bool *do_rel_wr_p, + int recovery_mode, bool *do_rel_wr_p, bool *do_data_tag_p) { struct mmc_blk_data *md = mq->blkdata; @@ -1340,6 +1403,8 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, memset(brq, 0, sizeof(struct mmc_blk_request)); + mmc_crypto_prepare_req(mqrq); + brq->mrq.data = &brq->data; brq->mrq.tag = req->tag; @@ -1385,12 +1450,12 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, brq->data.blocks--; /* - * After a read error, we redo the request one sector + * After a read error, we redo the request one (native) sector * at a time in order to accurately determine which * sectors can be read successfully. */ - if (disable_multi) - brq->data.blocks = 1; + if (recovery_mode) + brq->data.blocks = queue_physical_block_size(mq->queue) >> 9; /* * Some controllers have HW issues while operating @@ -1460,6 +1525,7 @@ static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req) struct mmc_request *mrq = &mqrq->brq.mrq; struct request_queue *q = req->q; struct mmc_host *host = mq->card->host; + enum mmc_issue_type issue_type = mmc_issue_type(mq, req); unsigned long flags; bool put_card; int err; @@ -1483,13 +1549,15 @@ static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req) blk_mq_requeue_request(req, true); else __blk_mq_end_request(req, BLK_STS_OK); + } else if (mq->in_recovery) { + blk_mq_requeue_request(req, true); } else { blk_mq_end_request(req, BLK_STS_OK); } spin_lock_irqsave(&mq->lock, flags); - mq->in_flight[mmc_issue_type(mq, req)] -= 1; + mq->in_flight[issue_type] -= 1; put_card = (mmc_tot_in_flight(mq) == 0); @@ -1515,8 +1583,7 @@ void mmc_blk_cqe_recovery(struct mmc_queue *mq) err = mmc_cqe_recovery(host); if (err) mmc_blk_reset(mq->blkdata, host, MMC_BLK_CQE_RECOVERY); - else - mmc_blk_reset_success(mq->blkdata, MMC_BLK_CQE_RECOVERY); + mmc_blk_reset_success(mq->blkdata, MMC_BLK_CQE_RECOVERY); pr_debug("%s: CQE recovery done\n", mmc_hostname(host)); } @@ -1535,7 +1602,7 @@ static void mmc_blk_cqe_req_done(struct mmc_request *mrq) */ if (mq->in_recovery) mmc_blk_cqe_complete_rq(mq, req); - else + else if (likely(!blk_should_fake_timeout(req->q))) blk_mq_complete_request(req); } @@ -1575,9 +1642,30 @@ static int mmc_blk_cqe_issue_flush(struct mmc_queue *mq, struct request *req) return mmc_blk_cqe_start_req(mq->card->host, mrq); } +static int mmc_blk_hsq_issue_rw_rq(struct mmc_queue *mq, struct request *req) +{ + struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); + struct mmc_host *host = mq->card->host; + int err; + + mmc_blk_rw_rq_prep(mqrq, mq->card, 0, mq); + mqrq->brq.mrq.done = mmc_blk_hsq_req_done; + mmc_pre_req(host, &mqrq->brq.mrq); + + err = mmc_cqe_start_req(host, &mqrq->brq.mrq); + if (err) + mmc_post_req(host, &mqrq->brq.mrq, err); + + return err; +} + static int mmc_blk_cqe_issue_rw_rq(struct mmc_queue *mq, struct request *req) { struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); + struct mmc_host *host = mq->card->host; + + if (host->hsq_enabled) + return mmc_blk_hsq_issue_rw_rq(mq, req); mmc_blk_data_prep(mq, mqrq, 0, NULL, NULL); @@ -1586,7 +1674,7 @@ static int mmc_blk_cqe_issue_rw_rq(struct mmc_queue *mq, struct request *req) static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, struct mmc_card *card, - int disable_multi, + int recovery_mode, struct mmc_queue *mq) { u32 readcmd, writecmd; @@ -1595,7 +1683,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, struct mmc_blk_data *md = mq->blkdata; bool do_rel_wr, do_data_tag; - mmc_blk_data_prep(mq, mqrq, disable_multi, &do_rel_wr, &do_data_tag); + mmc_blk_data_prep(mq, mqrq, recovery_mode, &do_rel_wr, &do_data_tag); brq->mrq.cmd = &brq->cmd; @@ -1639,8 +1727,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, * these, while retaining features like reliable writes. */ if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) && - (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) || - do_data_tag)) { + (do_rel_wr || !mmc_card_blk_no_cmd23(card) || do_data_tag)) { brq->sbc.opcode = MMC_SET_BLOCK_COUNT; brq->sbc.arg = brq->data.blocks | (do_rel_wr ? (1 << 31) : 0) | @@ -1648,6 +1735,11 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; brq->mrq.sbc = &brq->sbc; } + + if (mmc_card_ult_capacity(card)) { + brq->cmd.ext_addr = blk_rq_pos(req) >> 32; + brq->cmd.has_ext_addr = true; + } } #define MMC_MAX_RETRIES 5 @@ -1677,7 +1769,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, req, NULL); + err = mmc_poll_for_busy(card, timeout, false, MMC_BUSY_IO); mmc_retune_release(card->host); @@ -1686,7 +1778,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req) #define MMC_READ_SINGLE_RETRIES 2 -/* Single sector read during recovery */ +/* Single (native) sector read during recovery */ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) { struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); @@ -1694,31 +1786,32 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) struct mmc_card *card = mq->card; struct mmc_host *host = card->host; blk_status_t error = BLK_STS_OK; - int retries = 0; + size_t bytes_per_read = queue_physical_block_size(mq->queue); do { u32 status; int err; + int retries = 0; - mmc_blk_rw_rq_prep(mqrq, card, 1, mq); + while (retries++ <= MMC_READ_SINGLE_RETRIES) { + mmc_blk_rw_rq_prep(mqrq, card, 1, mq); - mmc_wait_for_req(host, mrq); + mmc_wait_for_req(host, mrq); - err = mmc_send_status(card, &status); - if (err) - goto error_exit; - - if (!mmc_host_is_spi(host) && - !mmc_blk_in_tran_state(status)) { - err = mmc_blk_fix_state(card, req); + err = mmc_send_status(card, &status); if (err) goto error_exit; - } - if (mrq->cmd->error && retries++ < MMC_READ_SINGLE_RETRIES) - continue; + if (!mmc_host_is_spi(host) && + !mmc_ready_for_data(status)) { + err = mmc_blk_fix_state(card, req); + if (err) + goto error_exit; + } - retries = 0; + if (!mrq->cmd->error) + break; + } if (mrq->cmd->error || mrq->data->error || @@ -1728,13 +1821,13 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) else error = BLK_STS_OK; - } while (blk_update_request(req, error, 512)); + } while (blk_update_request(req, error, bytes_per_read)); return; error_exit: mrq->data->bytes_xfered = 0; - blk_update_request(req, BLK_STS_IOERR, 512); + blk_update_request(req, BLK_STS_IOERR, bytes_per_read); /* Let it try the remaining request again */ if (mqrq->retries > MMC_MAX_RETRIES - 1) mqrq->retries = MMC_MAX_RETRIES - 1; @@ -1769,7 +1862,7 @@ static bool mmc_blk_status_error(struct request *req, u32 status) return brq->cmd.resp[0] & CMD_ERRORS || brq->stop.resp[0] & stop_err_bits || status & stop_err_bits || - (rq_data_dir(req) == WRITE && !mmc_blk_in_tran_state(status)); + (rq_data_dir(req) == WRITE && !mmc_ready_for_data(status)); } static inline bool mmc_blk_cmd_started(struct mmc_blk_request *brq) @@ -1831,7 +1924,7 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) /* Try to get back to "tran" state */ if (!mmc_host_is_spi(mq->card->host) && - (err || !mmc_blk_in_tran_state(status))) + (err || !mmc_ready_for_data(status))) err = mmc_blk_fix_state(mq->card, req); /* @@ -1849,7 +1942,7 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) /* Reset if the card is in a bad state */ if (!mmc_host_is_spi(mq->card->host) && err && mmc_blk_reset(md, card->host, type)) { - pr_err("%s: recovery failed!\n", req->rq_disk->disk_name); + pr_err("%s: recovery failed!\n", req->q->disk->disk_name); mqrq->retries = MMC_NO_RETRIES; return; } @@ -1862,8 +1955,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) return; /* Reset before last retry */ - if (mqrq->retries + 1 == MMC_MAX_RETRIES) - mmc_blk_reset(md, card->host, type); + if (mqrq->retries + 1 == MMC_MAX_RETRIES && + mmc_blk_reset(md, card->host, type)) + return; /* Command errors fail fast, so use all MMC_MAX_RETRIES */ if (brq->sbc.error || brq->cmd.error) @@ -1875,10 +1969,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) return; } - /* FIXME: Missing single sector read for large sector size */ - if (!mmc_large_sector(card) && rq_data_dir(req) == READ && - brq->data.blocks > 1) { - /* Read one sector at a time */ + if (rq_data_dir(req) == READ && brq->data.blocks > + queue_physical_block_size(mq->queue) >> 9) { + /* Read one (native) sector at a time */ mmc_blk_read_single(mq, req); return; } @@ -1892,28 +1985,80 @@ static inline bool mmc_blk_rq_error(struct mmc_blk_request *brq) brq->data.error || brq->cmd.resp[0] & CMD_ERRORS; } +static int mmc_spi_err_check(struct mmc_card *card) +{ + u32 status = 0; + int err; + + /* + * SPI does not have a TRAN state we have to wait on, instead the + * card is ready again when it no longer holds the line LOW. + * We still have to ensure two things here before we know the write + * was successful: + * 1. The card has not disconnected during busy and we actually read our + * own pull-up, thinking it was still connected, so ensure it + * still responds. + * 2. Check for any error bits, in particular R1_SPI_IDLE to catch a + * just reconnected card after being disconnected during busy. + */ + err = __mmc_send_status(card, &status, 0); + if (err) + return err; + /* All R1 and R2 bits of SPI are errors in our case */ + if (status) + return -EIO; + return 0; +} + +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) + if (rq_data_dir(req) == READ) return 0; - err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &status); + if (mmc_host_is_spi(card->host)) { + err = mmc_spi_err_check(card); + if (err) + mqrq->brq.data.bytes_xfered = 0; + return err; + } + + cb_data.card = card; + cb_data.status = 0; + err = __mmc_poll_for_busy(card->host, 0, 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; @@ -1963,13 +2108,49 @@ static void mmc_blk_urgent_bkops(struct mmc_queue *mq, mmc_run_bkops(mq->card); } +static void mmc_blk_hsq_req_done(struct mmc_request *mrq) +{ + struct mmc_queue_req *mqrq = + container_of(mrq, struct mmc_queue_req, brq.mrq); + struct request *req = mmc_queue_req_to_req(mqrq); + struct request_queue *q = req->q; + struct mmc_queue *mq = q->queuedata; + struct mmc_host *host = mq->card->host; + unsigned long flags; + + if (mmc_blk_rq_error(&mqrq->brq) || + mmc_blk_urgent_bkops_needed(mq, mqrq)) { + spin_lock_irqsave(&mq->lock, flags); + mq->recovery_needed = true; + mq->recovery_req = req; + spin_unlock_irqrestore(&mq->lock, flags); + + host->cqe_ops->cqe_recovery_start(host); + + schedule_work(&mq->recovery_work); + return; + } + + mmc_blk_rw_reset_success(mq, req); + + /* + * Block layer timeouts race with completions which means the normal + * completion path cannot be used during recovery. + */ + if (mq->in_recovery) + mmc_blk_cqe_complete_rq(mq, req); + else if (likely(!blk_should_fake_timeout(req->q))) + blk_mq_complete_request(req); +} + void mmc_blk_mq_complete(struct request *req) { struct mmc_queue *mq = req->q->queuedata; + struct mmc_host *host = mq->card->host; - if (mq->use_cqe) + if (host->cqe_enabled) mmc_blk_cqe_complete_rq(mq, req); - else + else if (likely(!blk_should_fake_timeout(req->q))) mmc_blk_mq_complete_rq(mq, req); } @@ -1990,14 +2171,14 @@ static void mmc_blk_mq_poll_completion(struct mmc_queue *mq, mmc_blk_urgent_bkops(mq, mqrq); } -static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req) +static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type) { unsigned long flags; bool put_card; spin_lock_irqsave(&mq->lock, flags); - mq->in_flight[mmc_issue_type(mq, req)] -= 1; + mq->in_flight[issue_type] -= 1; put_card = (mmc_tot_in_flight(mq) == 0); @@ -2007,8 +2188,10 @@ static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req) mmc_put_card(mq->card, &mq->ctx); } -static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req) +static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req, + bool can_sleep) { + enum mmc_issue_type issue_type = mmc_issue_type(mq, req); struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); struct mmc_request *mrq = &mqrq->brq.mrq; struct mmc_host *host = mq->card->host; @@ -2019,12 +2202,16 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req) * Block layer timeouts race with completions which means the normal * completion path cannot be used during recovery. */ - if (mq->in_recovery) + if (mq->in_recovery) { mmc_blk_mq_complete_rq(mq, req); - else - blk_mq_complete_request(req); + } else if (likely(!blk_should_fake_timeout(req->q))) { + if (can_sleep) + blk_mq_complete_request_direct(req, mmc_blk_mq_complete); + else + blk_mq_complete_request(req); + } - mmc_blk_mq_dec_in_flight(mq, req); + mmc_blk_mq_dec_in_flight(mq, issue_type); } void mmc_blk_mq_recovery(struct mmc_queue *mq) @@ -2043,13 +2230,13 @@ void mmc_blk_mq_recovery(struct mmc_queue *mq) mmc_blk_urgent_bkops(mq, mqrq); - mmc_blk_mq_post_req(mq, req); + mmc_blk_mq_post_req(mq, req, true); } static void mmc_blk_mq_complete_prev_req(struct mmc_queue *mq, struct request **prev_req) { - if (mmc_host_done_complete(mq->card->host)) + if (mmc_host_can_done_complete(mq->card->host)) return; mutex_lock(&mq->complete_lock); @@ -2062,7 +2249,7 @@ static void mmc_blk_mq_complete_prev_req(struct mmc_queue *mq, if (prev_req) *prev_req = mq->complete_req; else - mmc_blk_mq_post_req(mq, mq->complete_req); + mmc_blk_mq_post_req(mq, mq->complete_req, true); mq->complete_req = NULL; @@ -2088,7 +2275,7 @@ static void mmc_blk_mq_req_done(struct mmc_request *mrq) struct mmc_host *host = mq->card->host; unsigned long flags; - if (!mmc_host_done_complete(host)) { + if (!mmc_host_can_done_complete(host)) { bool waiting; /* @@ -2112,7 +2299,7 @@ static void mmc_blk_mq_req_done(struct mmc_request *mrq) if (waiting) wake_up(&mq->wait); else - kblockd_schedule_work(&mq->complete_work); + queue_work(mq->card->complete_wq, &mq->complete_work); return; } @@ -2134,7 +2321,8 @@ static void mmc_blk_mq_req_done(struct mmc_request *mrq) mq->rw_wait = false; wake_up(&mq->wait); - mmc_blk_mq_post_req(mq, req); + /* context unknown */ + mmc_blk_mq_post_req(mq, req, false); } static bool mmc_blk_rw_wait_cond(struct mmc_queue *mq, int *err) @@ -2194,13 +2382,13 @@ static int mmc_blk_mq_issue_rw_rq(struct mmc_queue *mq, err = mmc_start_request(host, &mqrq->brq.mrq); if (prev_req) - mmc_blk_mq_post_req(mq, prev_req); + mmc_blk_mq_post_req(mq, prev_req, true); if (err) mq->rw_wait = false; /* Release re-tuning here where there is no synchronization required */ - if (err || mmc_host_done_complete(host)) + if (err || mmc_host_can_done_complete(host)) mmc_retune_release(host); out_post_req: @@ -2212,7 +2400,7 @@ out_post_req: static int mmc_blk_wait_for_idle(struct mmc_queue *mq, struct mmc_host *host) { - if (mq->use_cqe) + if (host->cqe_enabled) return host->cqe_ops->cqe_wait_for_idle(host); return mmc_blk_rw_wait(mq, NULL); @@ -2245,6 +2433,9 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request *req) case REQ_OP_SECURE_ERASE: mmc_blk_issue_secdiscard_rq(mq, req); break; + case REQ_OP_WRITE_ZEROES: + mmc_blk_issue_trim_rq(mq, req); + break; case REQ_OP_FLUSH: mmc_blk_issue_flush(mq, req); break; @@ -2257,11 +2448,17 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request *req) case MMC_ISSUE_ASYNC: switch (req_op(req)) { case REQ_OP_FLUSH: + if (!mmc_cache_enabled(host)) { + blk_mq_end_request(req, BLK_STS_OK); + return MMC_REQ_FINISHED; + } ret = mmc_blk_cqe_issue_flush(mq, req); break; - case REQ_OP_READ: case REQ_OP_WRITE: - if (mq->use_cqe) + card->written_flag = true; + fallthrough; + case REQ_OP_READ: + if (host->cqe_enabled) ret = mmc_blk_cqe_issue_rw_rq(mq, req); else ret = mmc_blk_mq_issue_rw_rq(mq, req); @@ -2285,17 +2482,71 @@ static inline int mmc_blk_readonly(struct mmc_card *card) !(card->csd.cmdclass & CCC_BLOCK_WRITE); } +/* + * Search for a declared partitions node for the disk in mmc-card related node. + * + * This is to permit support for partition table defined in DT in special case + * where a partition table is not written in the disk and is expected to be + * passed from the running system. + * + * For the user disk, "partitions" node is searched. + * For the special HW disk, "partitions-" node with the appended name is used + * following this conversion table (to adhere to JEDEC naming) + * - boot0 -> partitions-boot1 + * - boot1 -> partitions-boot2 + * - gp0 -> partitions-gp1 + * - gp1 -> partitions-gp2 + * - gp2 -> partitions-gp3 + * - gp3 -> partitions-gp4 + */ +static struct fwnode_handle *mmc_blk_get_partitions_node(struct device *mmc_dev, + const char *subname) +{ + const char *node_name = "partitions"; + + if (subname) { + mmc_dev = mmc_dev->parent; + + /* + * Check if we are allocating a BOOT disk boot0/1 disk. + * In DT we use the JEDEC naming boot1/2. + */ + if (!strcmp(subname, "boot0")) + node_name = "partitions-boot1"; + if (!strcmp(subname, "boot1")) + node_name = "partitions-boot2"; + /* + * Check if we are allocating a GP disk gp0/1/2/3 disk. + * In DT we use the JEDEC naming gp1/2/3/4. + */ + if (!strcmp(subname, "gp0")) + node_name = "partitions-gp1"; + if (!strcmp(subname, "gp1")) + node_name = "partitions-gp2"; + if (!strcmp(subname, "gp2")) + node_name = "partitions-gp3"; + if (!strcmp(subname, "gp3")) + node_name = "partitions-gp4"; + } + + return device_get_named_child_node(mmc_dev, node_name); +} + static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, struct device *parent, sector_t size, bool default_ro, const char *subname, - int area_type) + int area_type, + unsigned int part_type) { + struct fwnode_handle *disk_fwnode; struct mmc_blk_data *md; int devidx, ret; + char cap_str[10]; + unsigned int features = 0; - devidx = ida_simple_get(&mmc_blk_ida, 0, max_devices, GFP_KERNEL); + devidx = ida_alloc_max(&mmc_blk_ida, max_devices - 1, GFP_KERNEL); if (devidx < 0) { /* * We get -ENOSPC because there are no more any available @@ -2311,7 +2562,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, return ERR_PTR(devidx); } - md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL); + md = kzalloc(sizeof(*md), GFP_KERNEL); if (!md) { ret = -ENOMEM; goto out; @@ -2325,45 +2576,40 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, */ md->read_only = mmc_blk_readonly(card); - md->disk = alloc_disk(perdev_minors); - if (md->disk == NULL) { - ret = -ENOMEM; + if (mmc_host_can_cmd23(card->host) && mmc_card_can_cmd23(card)) + md->flags |= MMC_BLK_CMD23; + + if (md->flags & MMC_BLK_CMD23 && + ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || + card->ext_csd.rel_sectors)) { + md->flags |= MMC_BLK_REL_WR; + features |= (BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA); + } else if (mmc_cache_enabled(card->host)) { + features |= BLK_FEAT_WRITE_CACHE; + } + + md->disk = mmc_init_queue(&md->queue, card, features); + if (IS_ERR(md->disk)) { + ret = PTR_ERR(md->disk); goto err_kfree; } INIT_LIST_HEAD(&md->part); INIT_LIST_HEAD(&md->rpmbs); - md->usage = 1; - - ret = mmc_init_queue(&md->queue, card); - if (ret) - goto err_putdisk; + kref_init(&md->kref); md->queue.blkdata = md; - - /* - * Keep an extra reference to the queue so that we can shutdown the - * queue (i.e. call blk_cleanup_queue()) while there are still - * references to the 'md'. The corresponding blk_put_queue() is in - * mmc_blk_put(). - */ - if (!blk_get_queue(md->queue.queue)) { - mmc_cleanup_queue(&md->queue); - ret = -ENODEV; - goto err_putdisk; - } + md->part_type = part_type; md->disk->major = MMC_BLOCK_MAJOR; + md->disk->minors = perdev_minors; md->disk->first_minor = devidx * perdev_minors; md->disk->fops = &mmc_bdops; md->disk->private_data = md; - md->disk->queue = md->queue.queue; md->parent = parent; set_disk_ro(md->disk, md->read_only || default_ro); - md->disk->flags = GENHD_FL_EXT_DEVT; - if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT)) - md->disk->flags |= GENHD_FL_NO_PART_SCAN - | GENHD_FL_SUPPRESS_PARTITION_INFO; + if (area_type & MMC_BLK_DATA_AREA_RPMB) + md->disk->flags |= GENHD_FL_NO_PART; /* * As discussed on lkml, GENHD_FL_REMOVABLE should: @@ -2380,38 +2626,31 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), "mmcblk%u%s", card->host->index, subname ? subname : ""); - if (mmc_card_mmc(card)) - blk_queue_logical_block_size(md->queue.queue, - card->ext_csd.data_sector_size); - else - blk_queue_logical_block_size(md->queue.queue, 512); - set_capacity(md->disk, size); - if (mmc_host_cmd23(card->host)) { - if ((mmc_card_mmc(card) && - card->csd.mmca_vsn >= CSD_SPEC_VER_3) || - (mmc_card_sd(card) && - card->scr.cmds & SD_SCR_CMD23_SUPPORT)) - md->flags |= MMC_BLK_CMD23; - } - - if (mmc_card_mmc(card) && - md->flags & MMC_BLK_CMD23 && - ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || - card->ext_csd.rel_sectors)) { - md->flags |= MMC_BLK_REL_WR; - blk_queue_write_cache(md->queue.queue, true, true); - } - + string_get_size((u64)size, 512, STRING_UNITS_2, + cap_str, sizeof(cap_str)); + pr_info("%s: %s %s %s%s\n", + md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), + cap_str, md->read_only ? " (ro)" : ""); + + /* used in ->open, must be set before add_disk: */ + if (area_type == MMC_BLK_DATA_AREA_MAIN) + dev_set_drvdata(&card->dev, md); + disk_fwnode = mmc_blk_get_partitions_node(parent, subname); + ret = add_disk_fwnode(md->parent, md->disk, mmc_disk_attr_groups, + disk_fwnode); + if (ret) + goto err_put_disk; return md; - err_putdisk: + err_put_disk: put_disk(md->disk); + blk_mq_free_tag_set(&md->queue.tag_set); err_kfree: kfree(md); out: - ida_simple_remove(&mmc_blk_ida, devidx); + ida_free(&mmc_blk_ida, devidx); return ERR_PTR(ret); } @@ -2435,7 +2674,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) } return mmc_blk_alloc_req(card, &card->dev, size, false, NULL, - MMC_BLK_DATA_AREA_MAIN); + MMC_BLK_DATA_AREA_MAIN, 0); } static int mmc_blk_alloc_part(struct mmc_card *card, @@ -2446,21 +2685,14 @@ static int mmc_blk_alloc_part(struct mmc_card *card, const char *subname, int area_type) { - char cap_str[10]; struct mmc_blk_data *part_md; part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro, - subname, area_type); + subname, area_type, part_type); if (IS_ERR(part_md)) return PTR_ERR(part_md); - part_md->part_type = part_type; list_add(&part_md->part, &md->part); - string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2, - cap_str, sizeof(cap_str)); - pr_info("%s: %s %s partition %u %s\n", - part_md->disk->disk_name, mmc_card_id(card), - mmc_card_name(card), part_md->part_type, cap_str); return 0; } @@ -2513,7 +2745,6 @@ static int mmc_rpmb_chrdev_open(struct inode *inode, struct file *filp) get_device(&rpmb->dev); filp->private_data = rpmb; - mmc_blk_get(rpmb->md->disk); return nonseekable_open(inode, filp); } @@ -2524,7 +2755,6 @@ static int mmc_rpmb_chrdev_release(struct inode *inode, struct file *filp) struct mmc_rpmb_data, chrdev); put_device(&rpmb->dev); - mmc_blk_put(rpmb->md); return 0; } @@ -2533,7 +2763,6 @@ static const struct file_operations mmc_rpmb_fileops = { .release = mmc_rpmb_chrdev_release, .open = mmc_rpmb_chrdev_open, .owner = THIS_MODULE, - .llseek = no_llseek, .unlocked_ioctl = mmc_rpmb_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = mmc_rpmb_ioctl_compat, @@ -2544,10 +2773,159 @@ static void mmc_blk_rpmb_device_release(struct device *dev) { struct mmc_rpmb_data *rpmb = dev_get_drvdata(dev); - ida_simple_remove(&mmc_rpmb_ida, rpmb->id); + rpmb_dev_unregister(rpmb->rdev); + mmc_blk_put(rpmb->md); + ida_free(&mmc_rpmb_ida, rpmb->id); kfree(rpmb); } +static void free_idata(struct mmc_blk_ioc_data **idata, unsigned int cmd_count) +{ + unsigned int n; + + for (n = 0; n < cmd_count; n++) + kfree(idata[n]); + kfree(idata); +} + +static struct mmc_blk_ioc_data **alloc_idata(struct mmc_rpmb_data *rpmb, + unsigned int cmd_count) +{ + struct mmc_blk_ioc_data **idata; + unsigned int n; + + idata = kcalloc(cmd_count, sizeof(*idata), GFP_KERNEL); + if (!idata) + return NULL; + + for (n = 0; n < cmd_count; n++) { + idata[n] = kcalloc(1, sizeof(**idata), GFP_KERNEL); + if (!idata[n]) { + free_idata(idata, n); + return NULL; + } + idata[n]->rpmb = rpmb; + } + + return idata; +} + +static void set_idata(struct mmc_blk_ioc_data *idata, u32 opcode, + int write_flag, u8 *buf, unsigned int buf_bytes) +{ + /* + * The size of an RPMB frame must match what's expected by the + * hardware. + */ + static_assert(!CHECK_SIZE_NEQ(512), "RPMB frame size must be 512 bytes"); + + idata->ic.opcode = opcode; + idata->ic.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + idata->ic.write_flag = write_flag; + idata->ic.blksz = RPMB_FRAME_SIZE; + idata->ic.blocks = buf_bytes / idata->ic.blksz; + idata->buf = buf; + idata->buf_bytes = buf_bytes; +} + +static int mmc_route_rpmb_frames(struct device *dev, u8 *req, + unsigned int req_len, u8 *resp, + unsigned int resp_len) +{ + struct rpmb_frame *frm = (struct rpmb_frame *)req; + struct mmc_rpmb_data *rpmb = dev_get_drvdata(dev); + struct mmc_blk_data *md = rpmb->md; + struct mmc_blk_ioc_data **idata; + struct mmc_queue_req *mq_rq; + unsigned int cmd_count; + struct request *rq; + u16 req_type; + bool write; + int ret; + + if (IS_ERR(md->queue.card)) + return PTR_ERR(md->queue.card); + + if (req_len < RPMB_FRAME_SIZE) + return -EINVAL; + + req_type = be16_to_cpu(frm->req_resp); + switch (req_type) { + case RPMB_PROGRAM_KEY: + if (CHECK_SIZE_NEQ(req_len) || CHECK_SIZE_NEQ(resp_len)) + return -EINVAL; + write = true; + break; + case RPMB_GET_WRITE_COUNTER: + if (CHECK_SIZE_NEQ(req_len) || CHECK_SIZE_NEQ(resp_len)) + return -EINVAL; + write = false; + break; + case RPMB_WRITE_DATA: + if (!CHECK_SIZE_ALIGNED(req_len) || CHECK_SIZE_NEQ(resp_len)) + return -EINVAL; + write = true; + break; + case RPMB_READ_DATA: + if (CHECK_SIZE_NEQ(req_len) || !CHECK_SIZE_ALIGNED(resp_len)) + return -EINVAL; + write = false; + break; + default: + return -EINVAL; + } + + /* Write operations require 3 commands, read operations require 2 */ + cmd_count = write ? 3 : 2; + + idata = alloc_idata(rpmb, cmd_count); + if (!idata) + return -ENOMEM; + + if (write) { + struct rpmb_frame *resp_frm = (struct rpmb_frame *)resp; + + /* Send write request frame(s) */ + set_idata(idata[0], MMC_WRITE_MULTIPLE_BLOCK, + 1 | MMC_CMD23_ARG_REL_WR, req, req_len); + + /* Send result request frame */ + memset(resp_frm, 0, RPMB_FRAME_SIZE); + resp_frm->req_resp = cpu_to_be16(RPMB_RESULT_READ); + set_idata(idata[1], MMC_WRITE_MULTIPLE_BLOCK, 1, resp, + resp_len); + + /* Read response frame */ + set_idata(idata[2], MMC_READ_MULTIPLE_BLOCK, 0, resp, resp_len); + } else { + /* Send write request frame(s) */ + set_idata(idata[0], MMC_WRITE_MULTIPLE_BLOCK, 1, req, req_len); + + /* Read response frame */ + set_idata(idata[1], MMC_READ_MULTIPLE_BLOCK, 0, resp, resp_len); + } + + rq = blk_mq_alloc_request(md->queue.queue, REQ_OP_DRV_OUT, 0); + if (IS_ERR(rq)) { + ret = PTR_ERR(rq); + goto out; + } + + mq_rq = req_to_mmc_queue_req(rq); + mq_rq->drv_op = MMC_DRV_OP_IOCTL_RPMB; + mq_rq->drv_op_result = -EIO; + mq_rq->drv_op_data = idata; + mq_rq->ioc_count = cmd_count; + blk_execute_rq(rq, false); + ret = req_to_mmc_queue_req(rq)->drv_op_result; + + blk_mq_free_request(rq); + +out: + free_idata(idata, cmd_count); + return ret; +} + static int mmc_blk_alloc_rpmb_part(struct mmc_card *card, struct mmc_blk_data *md, unsigned int part_index, @@ -2560,13 +2938,13 @@ static int mmc_blk_alloc_rpmb_part(struct mmc_card *card, struct mmc_rpmb_data *rpmb; /* This creates the minor number for the RPMB char device */ - devidx = ida_simple_get(&mmc_rpmb_ida, 0, max_devices, GFP_KERNEL); + devidx = ida_alloc_max(&mmc_rpmb_ida, max_devices - 1, GFP_KERNEL); if (devidx < 0) return devidx; rpmb = kzalloc(sizeof(*rpmb), GFP_KERNEL); if (!rpmb) { - ida_simple_remove(&mmc_rpmb_ida, devidx); + ida_free(&mmc_rpmb_ida, devidx); return -ENOMEM; } @@ -2582,6 +2960,7 @@ static int mmc_blk_alloc_rpmb_part(struct mmc_card *card, rpmb->dev.release = mmc_blk_rpmb_device_release; device_initialize(&rpmb->dev); dev_set_drvdata(&rpmb->dev, rpmb); + mmc_blk_get(md->disk); rpmb->md = md; cdev_init(&rpmb->chrdev, &mmc_rpmb_fileops); @@ -2597,9 +2976,8 @@ static int mmc_blk_alloc_rpmb_part(struct mmc_card *card, string_get_size((u64)size, 512, STRING_UNITS_2, cap_str, sizeof(cap_str)); - pr_info("%s: %s %s partition %u %s, chardev (%d:%d)\n", - rpmb_name, mmc_card_id(card), - mmc_card_name(card), EXT_CSD_PART_CONFIG_ACC_RPMB, cap_str, + pr_info("%s: %s %s %s, chardev (%d:%d)\n", + rpmb_name, mmc_card_id(card), mmc_card_name(card), cap_str, MAJOR(mmc_rpmb_devt), rpmb->id); return 0; @@ -2660,27 +3038,13 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) static void mmc_blk_remove_req(struct mmc_blk_data *md) { - struct mmc_card *card; - - if (md) { - /* - * Flush remaining requests and free queues. It - * is freeing the queue that stops new requests - * from being accepted. - */ - card = md->queue.card; - if (md->disk->flags & GENHD_FL_UP) { - device_remove_file(disk_to_dev(md->disk), &md->force_ro); - if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) && - card->ext_csd.boot_ro_lockable) - device_remove_file(disk_to_dev(md->disk), - &md->power_ro_lock); - - del_gendisk(md->disk); - } - mmc_cleanup_queue(&md->queue); - mmc_blk_put(md); - } + /* + * Flush remaining requests and free queues. It is freeing the queue + * that stops new requests from being accepted. + */ + del_gendisk(md->disk); + mmc_cleanup_queue(&md->queue); + mmc_blk_put(md); } static void mmc_blk_remove_parts(struct mmc_card *card, @@ -2704,51 +3068,6 @@ static void mmc_blk_remove_parts(struct mmc_card *card, } } -static int mmc_add_disk(struct mmc_blk_data *md) -{ - int ret; - struct mmc_card *card = md->queue.card; - - device_add_disk(md->parent, md->disk, NULL); - md->force_ro.show = force_ro_show; - md->force_ro.store = force_ro_store; - sysfs_attr_init(&md->force_ro.attr); - md->force_ro.attr.name = "force_ro"; - md->force_ro.attr.mode = S_IRUGO | S_IWUSR; - ret = device_create_file(disk_to_dev(md->disk), &md->force_ro); - if (ret) - goto force_ro_fail; - - if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) && - card->ext_csd.boot_ro_lockable) { - umode_t mode; - - if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS) - mode = S_IRUGO; - else - mode = S_IRUGO | S_IWUSR; - - md->power_ro_lock.show = power_ro_lock_show; - md->power_ro_lock.store = power_ro_lock_store; - sysfs_attr_init(&md->power_ro_lock.attr); - md->power_ro_lock.attr.mode = mode; - md->power_ro_lock.attr.name = - "ro_lock_until_next_power_on"; - ret = device_create_file(disk_to_dev(md->disk), - &md->power_ro_lock); - if (ret) - goto power_ro_lock_fail; - } - return ret; - -power_ro_lock_fail: - device_remove_file(disk_to_dev(md->disk), &md->force_ro); -force_ro_fail: - del_gendisk(md->disk); - - return ret; -} - #ifdef CONFIG_DEBUG_FS static int mmc_dbg_card_status_get(void *data, u64 *val) @@ -2760,22 +3079,23 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) int ret; /* Ask the block layer about the card status */ - req = blk_get_request(mq->queue, REQ_OP_DRV_IN, 0); + req = blk_mq_alloc_request(mq->queue, REQ_OP_DRV_IN, 0); if (IS_ERR(req)) return PTR_ERR(req); req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS; - blk_execute_rq(mq->queue, NULL, req, 0); + req_to_mmc_queue_req(req)->drv_op_result = -EIO; + blk_execute_rq(req, false); ret = req_to_mmc_queue_req(req)->drv_op_result; if (ret >= 0) { *val = ret; ret = 0; } - blk_put_request(req); + blk_mq_free_request(req); return ret; } -DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, - NULL, "%08llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, + NULL, "%08llx\n"); /* That is two digits * 512 + 1 for newline */ #define EXT_CSD_STR_LEN 1025 @@ -2796,16 +3116,17 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp) return -ENOMEM; /* Ask the block layer for the EXT CSD */ - req = blk_get_request(mq->queue, REQ_OP_DRV_IN, 0); + req = blk_mq_alloc_request(mq->queue, REQ_OP_DRV_IN, 0); if (IS_ERR(req)) { err = PTR_ERR(req); goto out_free; } req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD; + req_to_mmc_queue_req(req)->drv_op_result = -EIO; req_to_mmc_queue_req(req)->drv_op_data = &ext_csd; - blk_execute_rq(mq->queue, NULL, req, 0); + blk_execute_rq(req, false); err = req_to_mmc_queue_req(req)->drv_op_result; - blk_put_request(req); + blk_mq_free_request(req); if (err) { pr_err("FAILED %d\n", err); goto out_free; @@ -2852,32 +3173,27 @@ static const struct file_operations mmc_dbg_ext_csd_fops = { .llseek = default_llseek, }; -static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) +static void mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) { struct dentry *root; if (!card->debugfs_root) - return 0; + return; root = card->debugfs_root; if (mmc_card_mmc(card) || mmc_card_sd(card)) { md->status_dentry = - debugfs_create_file("status", S_IRUSR, root, card, - &mmc_dbg_card_status_fops); - if (!md->status_dentry) - return -EIO; + debugfs_create_file_unsafe("status", 0400, root, + card, + &mmc_dbg_card_status_fops); } if (mmc_card_mmc(card)) { md->ext_csd_dentry = - debugfs_create_file("ext_csd", S_IRUSR, root, card, + debugfs_create_file("ext_csd", 0400, root, card, &mmc_dbg_ext_csd_fops); - if (!md->ext_csd_dentry) - return -EIO; } - - return 0; } static void mmc_blk_remove_debugfs(struct mmc_card *card, @@ -2886,22 +3202,17 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card, if (!card->debugfs_root) return; - if (!IS_ERR_OR_NULL(md->status_dentry)) { - debugfs_remove(md->status_dentry); - md->status_dentry = NULL; - } + debugfs_remove(md->status_dentry); + md->status_dentry = NULL; - if (!IS_ERR_OR_NULL(md->ext_csd_dentry)) { - debugfs_remove(md->ext_csd_dentry); - md->ext_csd_dentry = NULL; - } + debugfs_remove(md->ext_csd_dentry); + md->ext_csd_dentry = NULL; } #else -static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) +static void mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md) { - return 0; } static void mmc_blk_remove_debugfs(struct mmc_card *card, @@ -2911,10 +3222,46 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card, #endif /* CONFIG_DEBUG_FS */ +static void mmc_blk_rpmb_add(struct mmc_card *card) +{ + struct mmc_blk_data *md = dev_get_drvdata(&card->dev); + struct mmc_rpmb_data *rpmb; + struct rpmb_dev *rdev; + unsigned int n; + u32 cid[4]; + struct rpmb_descr descr = { + .type = RPMB_TYPE_EMMC, + .route_frames = mmc_route_rpmb_frames, + .reliable_wr_count = card->ext_csd.enhanced_rpmb_supported ? + 2 : 32, + .capacity = card->ext_csd.raw_rpmb_size_mult, + .dev_id = (void *)cid, + .dev_id_len = sizeof(cid), + }; + + /* + * Provice CID as an octet array. The CID needs to be interpreted + * when used as input to derive the RPMB key since some fields + * will change due to firmware updates. + */ + for (n = 0; n < 4; n++) + cid[n] = be32_to_cpu((__force __be32)card->raw_cid[n]); + + list_for_each_entry(rpmb, &md->rpmbs, node) { + rdev = rpmb_dev_register(&rpmb->dev, &descr); + if (IS_ERR(rdev)) { + pr_warn("%s: could not register RPMB device\n", + dev_name(&rpmb->dev)); + continue; + } + rpmb->rdev = rdev; + } +} + static int mmc_blk_probe(struct mmc_card *card) { - struct mmc_blk_data *md, *part_md; - char cap_str[10]; + struct mmc_blk_data *md; + int ret = 0; /* * Check that the card supports the command class(es) we need. @@ -2924,29 +3271,24 @@ static int mmc_blk_probe(struct mmc_card *card) mmc_fixup_device(card, mmc_blk_fixups); - md = mmc_blk_alloc(card); - if (IS_ERR(md)) - return PTR_ERR(md); - - string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2, - cap_str, sizeof(cap_str)); - pr_info("%s: %s %s %s %s\n", - md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), - cap_str, md->read_only ? "(ro)" : ""); - - if (mmc_blk_alloc_parts(card, md)) - goto out; + card->complete_wq = alloc_workqueue("mmc_complete", + WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU, + 0); + if (!card->complete_wq) { + pr_err("Failed to create mmc completion workqueue"); + return -ENOMEM; + } - dev_set_drvdata(&card->dev, md); + md = mmc_blk_alloc(card); + if (IS_ERR(md)) { + ret = PTR_ERR(md); + goto out_free; + } - if (mmc_add_disk(md)) + ret = mmc_blk_alloc_parts(card, md); + if (ret) goto out; - list_for_each_entry(part_md, &md->part, part) { - if (mmc_add_disk(part_md)) - goto out; - } - /* Add two debugfs entries */ mmc_blk_add_debugfs(card, md); @@ -2957,17 +3299,21 @@ static int mmc_blk_probe(struct mmc_card *card) * Don't enable runtime PM for SD-combo cards here. Leave that * decision to be taken during the SDIO init sequence instead. */ - if (card->type != MMC_TYPE_SD_COMBO) { + if (!mmc_card_sd_combo(card)) { pm_runtime_set_active(&card->dev); pm_runtime_enable(&card->dev); } + mmc_blk_rpmb_add(card); + return 0; - out: +out: mmc_blk_remove_parts(card, md); mmc_blk_remove_req(md); - return 0; +out_free: + destroy_workqueue(card->complete_wq); + return ret; } static void mmc_blk_remove(struct mmc_card *card) @@ -2982,11 +3328,11 @@ static void mmc_blk_remove(struct mmc_card *card) mmc_blk_part_switch(card, md->part_type); mmc_release_host(card->host); } - if (card->type != MMC_TYPE_SD_COMBO) + if (!mmc_card_sd_combo(card)) pm_runtime_disable(&card->dev); pm_runtime_put_noidle(&card->dev); mmc_blk_remove_req(md); - dev_set_drvdata(&card->dev, NULL); + destroy_workqueue(card->complete_wq); } static int _mmc_blk_suspend(struct mmc_card *card) @@ -3100,4 +3446,3 @@ module_exit(mmc_blk_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver"); - diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index fc92c6c1c9a4..ec4f3462bf80 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/mmc/core/bus.c * * Copyright (C) 2003 Russell King, All Rights Reserved. * Copyright (C) 2007 Pierre Ossman * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * * MMC card bus driver model */ @@ -18,9 +15,11 @@ #include <linux/stat.h> #include <linux/of.h> #include <linux/pm_runtime.h> +#include <linux/sysfs.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> +#include <linux/mmc/mmc.h> #include "core.h" #include "card.h" @@ -37,13 +36,13 @@ static ssize_t type_show(struct device *dev, switch (card->type) { case MMC_TYPE_MMC: - return sprintf(buf, "MMC\n"); + return sysfs_emit(buf, "MMC\n"); case MMC_TYPE_SD: - return sprintf(buf, "SD\n"); + return sysfs_emit(buf, "SD\n"); case MMC_TYPE_SDIO: - return sprintf(buf, "SDIO\n"); + return sysfs_emit(buf, "SDIO\n"); case MMC_TYPE_SD_COMBO: - return sprintf(buf, "SDcombo\n"); + return sysfs_emit(buf, "SDcombo\n"); default: return -EFAULT; } @@ -56,21 +55,12 @@ static struct attribute *mmc_dev_attrs[] = { }; ATTRIBUTE_GROUPS(mmc_dev); -/* - * This currently matches any MMC driver to any MMC card - drivers - * themselves make the decision whether to drive this card in their - * probe method. - */ -static int mmc_bus_match(struct device *dev, struct device_driver *drv) -{ - return 1; -} - static int -mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +mmc_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct mmc_card *card = mmc_dev_to_card(dev); + const struct mmc_card *card = mmc_dev_to_card(dev); const char *type; + unsigned int i; int retval = 0; switch (card->type) { @@ -96,6 +86,31 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) return retval; } + if (mmc_card_sdio(card) || mmc_card_sd_combo(card)) { + retval = add_uevent_var(env, "SDIO_ID=%04X:%04X", + card->cis.vendor, card->cis.device); + if (retval) + return retval; + + retval = add_uevent_var(env, "SDIO_REVISION=%u.%u", + card->major_rev, card->minor_rev); + if (retval) + return retval; + + for (i = 0; i < card->num_info; i++) { + retval = add_uevent_var(env, "SDIO_INFO%u=%s", i+1, card->info[i]); + if (retval) + return retval; + } + } + + /* + * SDIO (non-combo) cards are not handled by mmc_block driver and do not + * have accessible CID register which used by mmc_card_name() function. + */ + if (mmc_card_sdio(card)) + return 0; + retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); if (retval) return retval; @@ -117,14 +132,12 @@ static int mmc_bus_probe(struct device *dev) return drv->probe(card); } -static int mmc_bus_remove(struct device *dev) +static void mmc_bus_remove(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); drv->remove(card); - - return 0; } static void mmc_bus_shutdown(struct device *dev) @@ -137,6 +150,8 @@ static void mmc_bus_shutdown(struct device *dev) if (dev->driver && drv->shutdown) drv->shutdown(card); + __mmc_stop_host(host); + if (host->bus_ops->shutdown) { ret = host->bus_ops->shutdown(host); if (ret) @@ -202,10 +217,9 @@ static const struct dev_pm_ops mmc_bus_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume) }; -static struct bus_type mmc_bus_type = { +static const struct bus_type mmc_bus_type = { .name = "mmc", .dev_groups = mmc_dev_groups, - .match = mmc_bus_match, .uevent = mmc_bus_uevent, .probe = mmc_bus_probe, .remove = mmc_bus_remove, @@ -261,7 +275,7 @@ static void mmc_release_card(struct device *dev) /* * Allocate and initialise a new MMC card structure. */ -struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) +struct mmc_card *mmc_alloc_card(struct mmc_host *host, const struct device_type *type) { struct mmc_card *card; @@ -288,6 +302,7 @@ int mmc_add_card(struct mmc_card *card) { int ret; const char *type; + const char *speed_mode = ""; const char *uhs_bus_speed_mode = ""; static const char *const uhs_speeds[] = { [UHS_SDR12_BUS_SPEED] = "SDR12 ", @@ -299,6 +314,9 @@ int mmc_add_card(struct mmc_card *card) dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); + dev_set_removable(&card->dev, + mmc_card_is_removable(card->host) ? + DEVICE_REMOVABLE : DEVICE_FIXED); switch (card->type) { case MMC_TYPE_MMC: @@ -307,7 +325,9 @@ int mmc_add_card(struct mmc_card *card) case MMC_TYPE_SD: type = "SD"; if (mmc_card_blockaddr(card)) { - if (mmc_card_ext_capacity(card)) + if (mmc_card_ult_capacity(card)) + type = "SDUC"; + else if (mmc_card_ext_capacity(card)) type = "SDXC"; else type = "SDHC"; @@ -326,31 +346,34 @@ int mmc_add_card(struct mmc_card *card) break; } + if (mmc_card_hs(card)) + speed_mode = "high speed "; + else if (mmc_card_uhs(card)) + speed_mode = "UHS-I speed "; + else if (mmc_card_uhs2(card->host)) + speed_mode = "UHS-II speed "; + else if (mmc_card_ddr52(card)) + speed_mode = "high speed DDR "; + else if (mmc_card_hs200(card)) + speed_mode = "HS200 "; + else if (mmc_card_hs400es(card)) + speed_mode = "HS400 Enhanced strobe "; + else if (mmc_card_hs400(card)) + speed_mode = "HS400 "; + if (mmc_card_uhs(card) && (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; - if (mmc_host_is_spi(card->host)) { - pr_info("%s: new %s%s%s card on SPI\n", - mmc_hostname(card->host), - mmc_card_hs(card) ? "high speed " : "", - mmc_card_ddr52(card) ? "DDR " : "", - type); - } else { - pr_info("%s: new %s%s%s%s%s%s card at address %04x\n", - mmc_hostname(card->host), - mmc_card_uhs(card) ? "ultra high speed " : - (mmc_card_hs(card) ? "high speed " : ""), - mmc_card_hs400(card) ? "HS400 " : - (mmc_card_hs200(card) ? "HS200 " : ""), - mmc_card_hs400es(card) ? "Enhanced strobe " : "", - mmc_card_ddr52(card) ? "DDR " : "", + if (mmc_host_is_spi(card->host)) + pr_info("%s: new %s%s card on SPI\n", + mmc_hostname(card->host), speed_mode, type); + else + pr_info("%s: new %s%s%s card at address %04x\n", + mmc_hostname(card->host), speed_mode, uhs_bus_speed_mode, type, card->rca); - } -#ifdef CONFIG_DEBUG_FS mmc_add_card_debugfs(card); -#endif card->dev.of_node = mmc_of_find_child_device(card->host, 0); device_enable_async_suspend(&card->dev); @@ -361,6 +384,14 @@ int mmc_add_card(struct mmc_card *card) mmc_card_set_present(card); + /* + * Register for undervoltage notification if the card supports + * power-off notification, enabling emergency shutdowns. + */ + if (mmc_card_mmc(card) && + card->ext_csd.power_off_notification == EXT_CSD_POWER_ON) + mmc_regulator_register_undervoltage_notifier(card->host); + return 0; } @@ -372,14 +403,10 @@ void mmc_remove_card(struct mmc_card *card) { struct mmc_host *host = card->host; -#ifdef CONFIG_DEBUG_FS - mmc_remove_card_debugfs(card); -#endif + if (mmc_card_present(card)) + mmc_regulator_unregister_undervoltage_notifier(host); - if (host->cqe_enabled) { - host->cqe_ops->cqe_disable(host); - host->cqe_enabled = false; - } + mmc_remove_card_debugfs(card); if (mmc_card_present(card)) { if (mmc_host_is_spi(card->host)) { @@ -393,6 +420,10 @@ void mmc_remove_card(struct mmc_card *card) of_node_put(card->dev.of_node); } + if (host->cqe_enabled) { + host->cqe_ops->cqe_disable(host); + host->cqe_enabled = false; + } + put_device(&card->dev); } - diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h index 72b0ef03f10a..8b69624fa46e 100644 --- a/drivers/mmc/core/bus.h +++ b/drivers/mmc/core/bus.h @@ -1,17 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * linux/drivers/mmc/core/bus.h * * Copyright (C) 2003 Russell King, All Rights Reserved. * Copyright 2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef _MMC_CORE_BUS_H #define _MMC_CORE_BUS_H #include <linux/device.h> +#include <linux/sysfs.h> struct mmc_host; struct mmc_card; @@ -20,12 +18,12 @@ struct mmc_card; static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct mmc_card *card = mmc_dev_to_card(dev); \ - return sprintf(buf, fmt, args); \ + return sysfs_emit(buf, fmt, args); \ } \ -static DEVICE_ATTR(name, S_IRUGO, mmc_##name##_show, NULL) +static DEVICE_ATTR(name, 0444, mmc_##name##_show, NULL) struct mmc_card *mmc_alloc_card(struct mmc_host *host, - struct device_type *type); + const struct device_type *type); int mmc_add_card(struct mmc_card *card); void mmc_remove_card(struct mmc_card *card); diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index eef301452406..1200951bab08 100644 --- a/drivers/mmc/core/card.h +++ b/drivers/mmc/core/card.h @@ -1,11 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Private header for the mmc subsystem * * Copyright (C) 2016 Linaro Ltd * * Author: Ulf Hansson <ulf.hansson@linaro.org> - * - * License terms: GNU General Public License (GPL) version 2 */ #ifndef _MMC_CORE_CARD_H @@ -24,6 +23,7 @@ #define MMC_CARD_SDXC (1<<3) /* card is SDXC */ #define MMC_CARD_REMOVED (1<<4) /* card has been removed */ #define MMC_STATE_SUSPENDED (1<<5) /* card is suspended */ +#define MMC_CARD_SDUC (1<<6) /* card is SDUC */ #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT) #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) @@ -31,11 +31,13 @@ #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_suspended(c) ((c)->state & MMC_STATE_SUSPENDED) +#define mmc_card_ult_capacity(c) ((c)->state & MMC_CARD_SDUC) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) #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_ult_capacity(c) ((c)->state |= MMC_CARD_SDUC) #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) #define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED) #define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED) @@ -54,41 +56,57 @@ struct mmc_fixup { unsigned int manfid; unsigned short oemid; + /* Manufacturing date */ + unsigned short year; + unsigned char month; + /* SDIO-specific fields. You can use SDIO_ANY_ID here of course */ u16 cis_vendor, cis_device; /* for MMC cards */ unsigned int ext_csd_rev; + /* Match against functions declared in device tree */ + const char *of_compatible; + void (*vendor_fixup)(struct mmc_card *card, int data); int data; }; #define CID_MANFID_ANY (-1u) #define CID_OEMID_ANY ((unsigned short) -1) +#define CID_YEAR_ANY ((unsigned short) -1) +#define CID_MONTH_ANY ((unsigned char) -1) #define CID_NAME_ANY (NULL) #define EXT_CSD_REV_ANY (-1u) #define CID_MANFID_SANDISK 0x2 +#define CID_MANFID_SANDISK_SD 0x3 #define CID_MANFID_ATP 0x9 #define CID_MANFID_TOSHIBA 0x11 +#define CID_MANFID_GIGASTONE 0x12 #define CID_MANFID_MICRON 0x13 #define CID_MANFID_SAMSUNG 0x15 #define CID_MANFID_APACER 0x27 +#define CID_MANFID_SWISSBIT 0x5D #define CID_MANFID_KINGSTON 0x70 #define CID_MANFID_HYNIX 0x90 +#define CID_MANFID_KINGSTON_SD 0x9F #define CID_MANFID_NUMONYX 0xFE #define END_FIXUP { NULL } -#define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \ - _cis_vendor, _cis_device, \ - _fixup, _data, _ext_csd_rev) \ +#define _FIXUP_EXT(_name, _manfid, _oemid, _year, _month, \ + _rev_start, _rev_end, \ + _cis_vendor, _cis_device, \ + _fixup, _data, _ext_csd_rev) \ { \ .name = (_name), \ .manfid = (_manfid), \ .oemid = (_oemid), \ + .year = (_year), \ + .month = (_month), \ .rev_start = (_rev_start), \ .rev_end = (_rev_end), \ .cis_vendor = (_cis_vendor), \ @@ -100,8 +118,8 @@ struct mmc_fixup { #define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end, \ _fixup, _data, _ext_csd_rev) \ - _FIXUP_EXT(_name, _manfid, \ - _oemid, _rev_start, _rev_end, \ + _FIXUP_EXT(_name, _manfid, _oemid, CID_YEAR_ANY, CID_MONTH_ANY, \ + _rev_start, _rev_end, \ SDIO_ANY_ID, SDIO_ANY_ID, \ _fixup, _data, _ext_csd_rev) \ @@ -115,11 +133,27 @@ struct mmc_fixup { _ext_csd_rev) #define SDIO_FIXUP(_vendor, _device, _fixup, _data) \ - _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, \ - CID_OEMID_ANY, 0, -1ull, \ + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, CID_OEMID_ANY, \ + CID_YEAR_ANY, CID_MONTH_ANY, \ + 0, -1ull, \ _vendor, _device, \ _fixup, _data, EXT_CSD_REV_ANY) \ +#define SDIO_FIXUP_COMPATIBLE(_compatible, _fixup, _data) \ + { \ + .name = CID_NAME_ANY, \ + .manfid = CID_MANFID_ANY, \ + .oemid = CID_OEMID_ANY, \ + .rev_start = 0, \ + .rev_end = -1ull, \ + .cis_vendor = SDIO_ANY_ID, \ + .cis_device = SDIO_ANY_ID, \ + .vendor_fixup = (_fixup), \ + .data = (_data), \ + .ext_csd_rev = EXT_CSD_REV_ANY, \ + .of_compatible = _compatible, \ + } + #define cid_rev(hwrev, fwrev, year, month) \ (((u64) hwrev) << 40 | \ ((u64) fwrev) << 32 | \ @@ -151,6 +185,24 @@ static inline void __maybe_unused add_limit_rate_quirk(struct mmc_card *card, card->quirk_max_rate = data; } +static inline void __maybe_unused wl1251_quirk(struct mmc_card *card, + int data) +{ + /* + * We have TI wl1251 attached to this mmc. Pass this + * information to the SDIO core because it can't be + * probed by normal methods. + */ + + dev_info(card->host->parent, "found wl1251\n"); + card->quirks |= MMC_QUIRK_NONSTD_SDIO; + card->cccr.wide_bus = 1; + card->cis.vendor = 0x104c; + card->cis.device = 0x9066; + card->cis.blksize = 512; + card->cis.max_dtr = 24000000; +} + /* * Quirk add/remove for MMC products. */ @@ -193,14 +245,19 @@ static inline int mmc_blksz_for_byte_mode(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; } +static inline int mmc_card_nonstd_func_interface(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_NONSTD_FUNC_IF; +} + static inline int mmc_card_disable_cd(const struct mmc_card *c) { return c->quirks & MMC_QUIRK_DISABLE_CD; } -static inline int mmc_card_nonstd_func_interface(const struct mmc_card *c) +static inline int mmc_card_blk_no_cmd23(const struct mmc_card *c) { - return c->quirks & MMC_QUIRK_NONSTD_FUNC_IF; + return c->quirks & MMC_QUIRK_BLK_NO_CMD23; } static inline int mmc_card_broken_byte_mode_512(const struct mmc_card *c) @@ -223,4 +280,29 @@ static inline int mmc_card_broken_hpi(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BROKEN_HPI; } +static inline int mmc_card_broken_sd_discard(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_BROKEN_SD_DISCARD; +} + +static inline int mmc_card_broken_sd_cache(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_BROKEN_SD_CACHE; +} + +static inline int mmc_card_broken_cache_flush(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_BROKEN_CACHE_FLUSH; +} + +static inline int mmc_card_broken_sd_poweroff_notify(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY; +} + +static inline int mmc_card_no_uhs_ddr50_tuning(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_NO_UHS_DDR50_TUNING; +} + #endif diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5bd58b95d318..860378bea557 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/mmc/core/core.c * @@ -5,10 +6,6 @@ * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/init.h> @@ -21,9 +18,7 @@ #include <linux/leds.h> #include <linux/scatterlist.h> #include <linux/log2.h> -#include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> -#include <linux/pm_wakeup.h> #include <linux/suspend.h> #include <linux/fault-inject.h> #include <linux/random.h> @@ -41,6 +36,7 @@ #include "core.h" #include "card.h" +#include "crypto.h" #include "bus.h" #include "host.h" #include "sdio_bus.h" @@ -52,13 +48,14 @@ /* The max erase timeout, used when host->max_busy_timeout isn't specified */ #define MMC_ERASE_TIMEOUT_MS (60 * 1000) /* 60 s */ +#define SD_DISCARD_TIMEOUT_MS (250) static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; /* * Enabling software CRCs on the data blocks can be a significant (30%) * performance cost, and for other reasons may not always be desired. - * So we allow it it to be disabled. + * So we allow it to be disabled. */ bool use_spi_crc = 1; module_param(use_spi_crc, bool, 0); @@ -95,12 +92,12 @@ static void mmc_should_fail_request(struct mmc_host *host, if (!data) return; - if (cmd->error || data->error || + if ((cmd && cmd->error) || data->error || !should_fail(&host->fail_mmc_request, data->blksz * data->blocks)) return; - data->error = data_errors[prandom_u32() % ARRAY_SIZE(data_errors)]; - data->bytes_xfered = (prandom_u32() % (data->bytes_xfered >> 9)) << 9; + data->error = data_errors[get_random_u32_below(ARRAY_SIZE(data_errors))]; + data->bytes_xfered = get_random_u32_below(data->bytes_xfered >> 9) << 9; } #else /* CONFIG_FAIL_MMC_REQUEST */ @@ -144,8 +141,8 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) int err = cmd->error; /* Flag re-tuning needed on CRC errors */ - if ((cmd->opcode != MMC_SEND_TUNING_BLOCK && - cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) && + if (!mmc_op_tuning(cmd->opcode) && + !host->retune_crc_disable && (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) || (mrq->data && mrq->data->error == -EILSEQ) || (mrq->stop && mrq->stop->error == -EILSEQ))) @@ -338,6 +335,9 @@ int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { int err; + if (mrq->cmd->has_ext_addr) + mmc_send_ext_addr(host, mrq->cmd->ext_addr); + init_completion(&mrq->cmd_completion); mmc_retune_hold(host); @@ -353,6 +353,9 @@ int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) if (err) return err; + if (host->uhs2_sd_tran) + mmc_uhs2_prepare_cmd(host, mrq); + led_trigger_event(host->led, LED_FULL); __mmc_start_request(host, mrq); @@ -405,23 +408,6 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) cmd = mrq->cmd; - /* - * If host has timed out waiting for the sanitize - * to complete, card might be still in programming state - * so let's try to bring the card out of programming - * state. - */ - if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT) { - if (!mmc_interrupt_hpi(host->card)) { - pr_warn("%s: %s: Interrupted sanitize\n", - mmc_hostname(host), __func__); - cmd->error = 0; - break; - } else { - pr_err("%s: %s: Failed to interrupt sanitize\n", - mmc_hostname(host), __func__); - } - } if (!cmd->error || !cmd->retries || mmc_card_removed(host->card)) break; @@ -469,6 +455,9 @@ int mmc_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq) if (err) goto out_err; + if (host->uhs2_sd_tran) + mmc_uhs2_prepare_cmd(host, mrq); + err = host->cqe_ops->cqe_request(host, mrq); if (err) goto out_err; @@ -545,7 +534,7 @@ EXPORT_SYMBOL(mmc_cqe_post_req); * mmc_cqe_recovery - Recover from CQE errors. * @host: MMC host to recover * - * Recovery consists of stopping CQE, stopping eMMC, discarding the queue in + * Recovery consists of stopping CQE, stopping eMMC, discarding the queue * in eMMC, and discarding the queue in CQE. CQE must call * mmc_cqe_request_done() on all requests. An error is returned if the eMMC * fails to discard its queue. @@ -566,22 +555,25 @@ int mmc_cqe_recovery(struct mmc_host *host) host->cqe_ops->cqe_recovery_start(host); memset(&cmd, 0, sizeof(cmd)); - cmd.opcode = MMC_STOP_TRANSMISSION, - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC, - cmd.flags &= ~MMC_RSP_CRC; /* Ignore CRC */ - cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT, - mmc_wait_for_cmd(host, &cmd, 0); + cmd.opcode = MMC_STOP_TRANSMISSION; + cmd.flags = MMC_RSP_R1B_NO_CRC | MMC_CMD_AC; /* Ignore CRC */ + cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT; + mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + + mmc_poll_for_busy(host->card, MMC_CQE_RECOVERY_TIMEOUT, true, MMC_BUSY_IO); memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_CMDQ_TASK_MGMT; cmd.arg = 1; /* Discard entire queue */ - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - cmd.flags &= ~MMC_RSP_CRC; /* Ignore CRC */ - cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT, - err = mmc_wait_for_cmd(host, &cmd, 0); + cmd.flags = MMC_RSP_R1B_NO_CRC | MMC_CMD_AC; /* Ignore CRC */ + cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT; + err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); host->cqe_ops->cqe_recovery_finish(host); + if (err) + err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + mmc_retune_release(host); return err; @@ -758,33 +750,6 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) } EXPORT_SYMBOL(mmc_set_data_timeout); -/** - * mmc_align_data_size - pads a transfer size to a more optimal value - * @card: the MMC card associated with the data transfer - * @sz: original transfer size - * - * Pads the original data size with a number of extra bytes in - * order to avoid controller bugs and/or performance hits - * (e.g. some controllers revert to PIO for certain sizes). - * - * Returns the improved size, which might be unmodified. - * - * Note that this function is only relevant when issuing a - * single scatter gather entry. - */ -unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz) -{ - /* - * FIXME: We don't have a system for the controller to tell - * the core about its problems yet, so for now we just 32-bit - * align the size. - */ - sz = ((sz + 3) / 4) * 4; - - return sz; -} -EXPORT_SYMBOL(mmc_align_data_size); - /* * Allow claiming an already claimed host if the context is the same or there is * no context but the task is the same. @@ -917,7 +882,6 @@ void mmc_put_card(struct mmc_card *card, struct mmc_ctx *ctx) WARN_ON(ctx && host->claimer != ctx); mmc_release_host(host); - pm_runtime_mark_last_busy(&card->dev); pm_runtime_put_autosuspend(&card->dev); } EXPORT_SYMBOL(mmc_put_card); @@ -981,12 +945,18 @@ int mmc_execute_tuning(struct mmc_card *card) opcode = MMC_SEND_TUNING_BLOCK; err = host->ops->execute_tuning(host, opcode); + if (!err) { + mmc_retune_clear(host); + mmc_retune_enable(host); + return 0; + } - if (err) + /* 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); - else - mmc_retune_enable(host); + mmc_debugfs_err_stats_inc(host, MMC_ERR_TUNING); + } return err; } @@ -1038,6 +1008,8 @@ void mmc_set_initial_state(struct mmc_host *host) host->ops->hs400_enhanced_strobe(host, &host->ios); mmc_set_ios(host); + + mmc_crypto_set_initial_state(host); } /** @@ -1112,55 +1084,6 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max) return mask; } -EXPORT_SYMBOL(mmc_vddrange_to_ocrmask); - -#ifdef CONFIG_OF - -/** - * mmc_of_parse_voltage - return mask of supported voltages - * @np: The device node need to be parsed. - * @mask: mask of voltages available for MMC/SD/SDIO - * - * Parse the "voltage-ranges" DT property, returning zero if it is not - * found, negative errno if the voltage-range specification is invalid, - * or one if the voltage-range is specified and successfully parsed. - */ -int mmc_of_parse_voltage(struct device_node *np, u32 *mask) -{ - const u32 *voltage_ranges; - int num_ranges, i; - - voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges); - num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; - if (!voltage_ranges) { - pr_debug("%pOF: voltage-ranges unspecified\n", np); - return 0; - } - if (!num_ranges) { - pr_err("%pOF: voltage-ranges empty\n", np); - return -EINVAL; - } - - for (i = 0; i < num_ranges; i++) { - const int j = i * 2; - u32 ocr_mask; - - ocr_mask = mmc_vddrange_to_ocrmask( - be32_to_cpu(voltage_ranges[j]), - be32_to_cpu(voltage_ranges[j + 1])); - if (!ocr_mask) { - pr_err("%pOF: voltage-range #%d is invalid\n", - np, i); - return -EINVAL; - } - *mask |= ocr_mask; - } - - return 1; -} -EXPORT_SYMBOL(mmc_of_parse_voltage); - -#endif /* CONFIG_OF */ static int mmc_of_get_func_num(struct device_node *node) { @@ -1190,246 +1113,6 @@ struct device_node *mmc_of_find_child_device(struct mmc_host *host, return NULL; } -#ifdef CONFIG_REGULATOR - -/** - * mmc_ocrbitnum_to_vdd - Convert a OCR bit number to its voltage - * @vdd_bit: OCR bit number - * @min_uV: minimum voltage value (mV) - * @max_uV: maximum voltage value (mV) - * - * This function returns the voltage range according to the provided OCR - * bit number. If conversion is not possible a negative errno value returned. - */ -static int mmc_ocrbitnum_to_vdd(int vdd_bit, int *min_uV, int *max_uV) -{ - int tmp; - - if (!vdd_bit) - return -EINVAL; - - /* - * REVISIT mmc_vddrange_to_ocrmask() may have set some - * bits this regulator doesn't quite support ... don't - * be too picky, most cards and regulators are OK with - * a 0.1V range goof (it's a small error percentage). - */ - tmp = vdd_bit - ilog2(MMC_VDD_165_195); - if (tmp == 0) { - *min_uV = 1650 * 1000; - *max_uV = 1950 * 1000; - } else { - *min_uV = 1900 * 1000 + tmp * 100 * 1000; - *max_uV = *min_uV + 100 * 1000; - } - - return 0; -} - -/** - * mmc_regulator_get_ocrmask - return mask of supported voltages - * @supply: regulator to use - * - * This returns either a negative errno, or a mask of voltages that - * can be provided to MMC/SD/SDIO devices using the specified voltage - * regulator. This would normally be called before registering the - * MMC host adapter. - */ -int mmc_regulator_get_ocrmask(struct regulator *supply) -{ - int result = 0; - int count; - int i; - int vdd_uV; - int vdd_mV; - - count = regulator_count_voltages(supply); - if (count < 0) - return count; - - for (i = 0; i < count; i++) { - vdd_uV = regulator_list_voltage(supply, i); - if (vdd_uV <= 0) - continue; - - vdd_mV = vdd_uV / 1000; - result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); - } - - if (!result) { - vdd_uV = regulator_get_voltage(supply); - if (vdd_uV <= 0) - return vdd_uV; - - vdd_mV = vdd_uV / 1000; - result = mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); - } - - return result; -} -EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask); - -/** - * mmc_regulator_set_ocr - set regulator to match host->ios voltage - * @mmc: the host to regulate - * @supply: regulator to use - * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) - * - * Returns zero on success, else negative errno. - * - * MMC host drivers may use this to enable or disable a regulator using - * a particular supply voltage. This would normally be called from the - * set_ios() method. - */ -int mmc_regulator_set_ocr(struct mmc_host *mmc, - struct regulator *supply, - unsigned short vdd_bit) -{ - int result = 0; - int min_uV, max_uV; - - if (vdd_bit) { - mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV); - - result = regulator_set_voltage(supply, min_uV, max_uV); - if (result == 0 && !mmc->regulator_enabled) { - result = regulator_enable(supply); - if (!result) - mmc->regulator_enabled = true; - } - } else if (mmc->regulator_enabled) { - result = regulator_disable(supply); - if (result == 0) - mmc->regulator_enabled = false; - } - - if (result) - dev_err(mmc_dev(mmc), - "could not set regulator OCR (%d)\n", result); - return result; -} -EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); - -static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator, - int min_uV, int target_uV, - int max_uV) -{ - /* - * Check if supported first to avoid errors since we may try several - * signal levels during power up and don't want to show errors. - */ - if (!regulator_is_supported_voltage(regulator, min_uV, max_uV)) - return -EINVAL; - - return regulator_set_voltage_triplet(regulator, min_uV, target_uV, - max_uV); -} - -/** - * mmc_regulator_set_vqmmc - Set VQMMC as per the ios - * - * For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible. - * That will match the behavior of old boards where VQMMC and VMMC were supplied - * by the same supply. The Bus Operating conditions for 3.3V signaling in the - * SD card spec also define VQMMC in terms of VMMC. - * If this is not possible we'll try the full 2.7-3.6V of the spec. - * - * For 1.2V and 1.8V signaling we'll try to get as close as possible to the - * requested voltage. This is definitely a good idea for UHS where there's a - * separate regulator on the card that's trying to make 1.8V and it's best if - * we match. - * - * This function is expected to be used by a controller's - * start_signal_voltage_switch() function. - */ -int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios) -{ - struct device *dev = mmc_dev(mmc); - int ret, volt, min_uV, max_uV; - - /* If no vqmmc supply then we can't change the voltage */ - if (IS_ERR(mmc->supply.vqmmc)) - return -EINVAL; - - switch (ios->signal_voltage) { - case MMC_SIGNAL_VOLTAGE_120: - return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, - 1100000, 1200000, 1300000); - case MMC_SIGNAL_VOLTAGE_180: - return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, - 1700000, 1800000, 1950000); - case MMC_SIGNAL_VOLTAGE_330: - ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV); - if (ret < 0) - return ret; - - dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n", - __func__, volt, max_uV); - - min_uV = max(volt - 300000, 2700000); - max_uV = min(max_uV + 200000, 3600000); - - /* - * Due to a limitation in the current implementation of - * regulator_set_voltage_triplet() which is taking the lowest - * voltage possible if below the target, search for a suitable - * voltage in two steps and try to stay close to vmmc - * with a 0.3V tolerance at first. - */ - if (!mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, - min_uV, volt, max_uV)) - return 0; - - return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, - 2700000, volt, 3600000); - default: - return -EINVAL; - } -} -EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc); - -#endif /* CONFIG_REGULATOR */ - -/** - * mmc_regulator_get_supply - try to get VMMC and VQMMC regulators for a host - * @mmc: the host to regulate - * - * Returns 0 or errno. errno should be handled, it is either a critical error - * or -EPROBE_DEFER. 0 means no critical error but it does not mean all - * regulators have been found because they all are optional. If you require - * certain regulators, you need to check separately in your driver if they got - * populated after calling this function. - */ -int mmc_regulator_get_supply(struct mmc_host *mmc) -{ - struct device *dev = mmc_dev(mmc); - int ret; - - mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc"); - mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); - - if (IS_ERR(mmc->supply.vmmc)) { - if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) - return -EPROBE_DEFER; - dev_dbg(dev, "No vmmc regulator found\n"); - } else { - ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc); - if (ret > 0) - mmc->ocr_avail = ret; - else - dev_warn(dev, "Failed getting OCR mask: %d\n", ret); - } - - if (IS_ERR(mmc->supply.vqmmc)) { - if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER) - return -EPROBE_DEFER; - dev_dbg(dev, "No vqmmc regulator found\n"); - } - - return 0; -} -EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); - /* * Mask off any voltages we don't support and select * the lowest voltage @@ -1454,13 +1137,19 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) return 0; } - if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) { + if (!mmc_card_uhs2(host) && host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) { bit = ffs(ocr) - 1; ocr &= 3 << bit; mmc_power_cycle(host, ocr); } else { bit = fls(ocr) - 1; - ocr &= 3 << bit; + /* + * The bit variable represents the highest voltage bit set in + * the OCR register. + * To keep a range of 2 values (e.g. 3.2V/3.3V and 3.3V/3.4V), + * we must shift the mask '3' with (bit - 1). + */ + ocr &= 3 << (bit - 1); if (bit != host->ios.vdd) dev_warn(mmc_dev(host), "exceeding card's volts\n"); } @@ -1539,7 +1228,7 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) err = mmc_wait_for_cmd(host, &cmd, 0); if (err) - return err; + goto power_cycle; if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) return -EIO; @@ -1709,41 +1398,27 @@ void mmc_power_cycle(struct mmc_host *host, u32 ocr) mmc_power_up(host, ocr); } -/* - * Cleanup when the last reference to the bus operator is dropped. - */ -static void __mmc_release_bus(struct mmc_host *host) -{ - WARN_ON(!host->bus_dead); - - host->bus_ops = NULL; -} - -/* - * Increase reference count of bus operator +/** + * mmc_handle_undervoltage - Handle an undervoltage event on the MMC bus + * @host: The MMC host that detected the undervoltage condition + * + * This function is called when an undervoltage event is detected on one of + * the MMC regulators. + * + * Returns: 0 on success or a negative error code on failure. */ -static inline void mmc_bus_get(struct mmc_host *host) +int mmc_handle_undervoltage(struct mmc_host *host) { - unsigned long flags; + /* Stop the host to prevent races with card removal */ + __mmc_stop_host(host); - spin_lock_irqsave(&host->lock, flags); - host->bus_refs++; - spin_unlock_irqrestore(&host->lock, flags); -} + if (!host->bus_ops || !host->bus_ops->handle_undervoltage) + return 0; -/* - * Decrease reference count of bus operator and free it if - * it is the last reference. - */ -static inline void mmc_bus_put(struct mmc_host *host) -{ - unsigned long flags; + dev_warn(mmc_dev(host), "%s: Undervoltage detected, initiating emergency stop\n", + mmc_hostname(host)); - spin_lock_irqsave(&host->lock, flags); - host->bus_refs--; - if ((host->bus_refs == 0) && host->bus_ops) - __mmc_release_bus(host); - spin_unlock_irqrestore(&host->lock, flags); + return host->bus_ops->handle_undervoltage(host); } /* @@ -1752,20 +1427,7 @@ static inline void mmc_bus_put(struct mmc_host *host) */ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) { - unsigned long flags; - - WARN_ON(!host->claimed); - - spin_lock_irqsave(&host->lock, flags); - - WARN_ON(host->bus_ops); - WARN_ON(host->bus_refs); - host->bus_ops = ops; - host->bus_refs = 1; - host->bus_dead = 0; - - spin_unlock_irqrestore(&host->lock, flags); } /* @@ -1773,30 +1435,18 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) */ void mmc_detach_bus(struct mmc_host *host) { - unsigned long flags; - - WARN_ON(!host->claimed); - WARN_ON(!host->bus_ops); - - spin_lock_irqsave(&host->lock, flags); - - host->bus_dead = 1; - - spin_unlock_irqrestore(&host->lock, flags); - - mmc_bus_put(host); + host->bus_ops = NULL; } -static void _mmc_detect_change(struct mmc_host *host, unsigned long delay, - bool cd_irq) +void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq) { /* - * If the device is configured as wakeup, we prevent a new sleep for - * 5 s to give provision for user space to consume the event. + * Prevent system sleep for 5s to allow user space to consume the + * corresponding uevent. This is especially useful, when CD irq is used + * as a system wakeup, but doesn't hurt in other cases. */ - if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) && - device_can_wakeup(mmc_dev(host))) - pm_wakeup_event(mmc_dev(host), 5000); + if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL)) + __pm_wakeup_event(host->ws, 5000); host->detect_change = 1; mmc_schedule_delayed_work(&host->detect, delay); @@ -1866,6 +1516,11 @@ void mmc_init_erase(struct mmc_card *card) card->pref_erase = 0; } +static bool is_trim_arg(unsigned int arg) +{ + return (arg & MMC_TRIM_OR_DISCARD_ARGS) && arg != MMC_DISCARD_ARG; +} + static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card, unsigned int arg, unsigned int qty) { @@ -1936,6 +1591,12 @@ static unsigned int mmc_sd_erase_timeout(struct mmc_card *card, { unsigned int erase_timeout; + /* for DISCARD none of the below calculation applies. + * the busy timeout is 250msec per discard command. + */ + if (arg == SD_DISCARD_ARG) + return SD_DISCARD_TIMEOUT_MS; + if (card->ssr.erase_timeout) { /* Erase timeout specified in SD Status Register (SSR) */ erase_timeout = card->ssr.erase_timeout * qty + @@ -1965,14 +1626,12 @@ static unsigned int mmc_erase_timeout(struct mmc_card *card, return mmc_mmc_erase_timeout(card, arg, qty); } -static int mmc_do_erase(struct mmc_card *card, unsigned int from, - unsigned int to, unsigned int arg) +static int mmc_do_erase(struct mmc_card *card, sector_t from, + sector_t to, unsigned int arg) { struct mmc_command cmd = {}; unsigned int qty = 0, busy_timeout = 0; - bool use_r1b_resp = false; - unsigned long timeout; - int loop_udelay=64, udelay_max=32768; + bool use_r1b_resp; int err; mmc_retune_hold(card->host); @@ -1999,8 +1658,8 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, else if (mmc_card_sd(card)) qty += to - from + 1; else - qty += ((to / card->erase_size) - - (from / card->erase_size)) + 1; + qty += (mmc_sector_div(to, card->erase_size) - + mmc_sector_div(from, card->erase_size)) + 1; if (!mmc_card_blockaddr(card)) { from <<= 9; @@ -2013,6 +1672,12 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, cmd.opcode = MMC_ERASE_GROUP_START; cmd.arg = from; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + + if (mmc_card_ult_capacity(card)) { + cmd.ext_addr = from >> 32; + cmd.has_ext_addr = true; + } + err = mmc_wait_for_cmd(card->host, &cmd, 0); if (err) { pr_err("mmc_erase: group start error %d, " @@ -2028,6 +1693,12 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, cmd.opcode = MMC_ERASE_GROUP_END; cmd.arg = to; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + + if (mmc_card_ult_capacity(card)) { + cmd.ext_addr = to >> 32; + cmd.has_ext_addr = true; + } + err = mmc_wait_for_cmd(card->host, &cmd, 0); if (err) { pr_err("mmc_erase: group end error %d, status %#x\n", @@ -2040,20 +1711,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, cmd.opcode = MMC_ERASE; cmd.arg = arg; busy_timeout = mmc_erase_timeout(card, arg, qty); - /* - * If the host controller supports busy signalling and the timeout for - * the erase operation does not exceed the max_busy_timeout, we should - * use R1B response. Or we need to prevent the host from doing hw busy - * detection, which is done by converting to a R1 response instead. - */ - if (card->host->max_busy_timeout && - busy_timeout > card->host->max_busy_timeout) { - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; - } else { - cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; - cmd.busy_timeout = busy_timeout; - use_r1b_resp = true; - } + use_r1b_resp = mmc_prepare_busy_cmd(card->host, &cmd, busy_timeout); err = mmc_wait_for_cmd(card->host, &cmd, 0); if (err) { @@ -2073,38 +1731,8 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) goto out; - timeout = jiffies + msecs_to_jiffies(busy_timeout); - do { - memset(&cmd, 0, sizeof(struct mmc_command)); - cmd.opcode = MMC_SEND_STATUS; - cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - /* Do not retry else we can't see errors */ - err = mmc_wait_for_cmd(card->host, &cmd, 0); - if (err || R1_STATUS(cmd.resp[0])) { - pr_err("error %d requesting status %#x\n", - err, cmd.resp[0]); - err = -EIO; - goto out; - } - - /* Timeout if the device never becomes ready for data and - * never leaves the program state. - */ - if (time_after(jiffies, timeout)) { - pr_err("%s: Card stuck in programming state! %s\n", - mmc_hostname(card->host), __func__); - err = -EIO; - goto out; - } - if ((cmd.resp[0] & R1_READY_FOR_DATA) && - R1_CURRENT_STATE(cmd.resp[0]) != R1_STATE_PRG) - break; - - usleep_range(loop_udelay, loop_udelay*2); - if (loop_udelay < udelay_max) - loop_udelay *= 2; - } while (1); + /* Let's poll to find out when the erase operation completes. */ + err = mmc_poll_for_busy(card, busy_timeout, false, MMC_BUSY_ERASE); out: mmc_retune_release(card->host); @@ -2112,18 +1740,19 @@ out: } static unsigned int mmc_align_erase_size(struct mmc_card *card, - unsigned int *from, - unsigned int *to, + sector_t *from, + sector_t *to, unsigned int nr) { - unsigned int from_new = *from, nr_new = nr, rem; + sector_t from_new = *from; + unsigned int nr_new = nr, rem; /* * When the 'card->erase_size' is power of 2, we can use round_up/down() * to align the erase size efficiently. */ if (is_power_of_2(card->erase_size)) { - unsigned int temp = from_new; + sector_t temp = from_new; from_new = round_up(temp, card->erase_size); rem = from_new - temp; @@ -2135,7 +1764,7 @@ static unsigned int mmc_align_erase_size(struct mmc_card *card, nr_new = round_down(nr_new, card->erase_size); } else { - rem = from_new % card->erase_size; + rem = mmc_sector_mod(from_new, card->erase_size); if (rem) { rem = card->erase_size - rem; from_new += rem; @@ -2164,36 +1793,37 @@ static unsigned int mmc_align_erase_size(struct mmc_card *card, * @card: card to erase * @from: first sector to erase * @nr: number of sectors to erase - * @arg: erase command argument (SD supports only %MMC_ERASE_ARG) + * @arg: erase command argument * * Caller must claim host before calling this function. */ -int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, +int mmc_erase(struct mmc_card *card, sector_t from, unsigned int nr, unsigned int arg) { - unsigned int rem, to = from + nr; + unsigned int rem; + sector_t to = from + nr; + int err; - if (!(card->host->caps & MMC_CAP_ERASE) || - !(card->csd.cmdclass & CCC_ERASE)) + if (!(card->csd.cmdclass & CCC_ERASE)) return -EOPNOTSUPP; if (!card->erase_size) return -EOPNOTSUPP; - if (mmc_card_sd(card) && arg != MMC_ERASE_ARG) + if (mmc_card_sd(card) && arg != SD_ERASE_ARG && arg != SD_DISCARD_ARG) return -EOPNOTSUPP; - if ((arg & MMC_SECURE_ARGS) && + if (mmc_card_mmc(card) && (arg & MMC_SECURE_ARGS) && !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)) return -EOPNOTSUPP; - if ((arg & MMC_TRIM_ARGS) && + if (mmc_card_mmc(card) && is_trim_arg(arg) && !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)) return -EOPNOTSUPP; if (arg == MMC_SECURE_ERASE_ARG) { - if (from % card->erase_size || nr % card->erase_size) + if (mmc_sector_mod(from, card->erase_size) || nr % card->erase_size) return -EINVAL; } @@ -2217,8 +1847,8 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, * and call mmc_do_erase() twice if necessary. This special case is * identified by the card->eg_boundary flag. */ - rem = card->erase_size - (from % card->erase_size); - if ((arg & MMC_TRIM_ARGS) && (card->eg_boundary) && (nr > rem)) { + rem = card->erase_size - mmc_sector_mod(from, card->erase_size); + if ((arg & MMC_TRIM_OR_DISCARD_ARGS) && card->eg_boundary && nr > rem) { err = mmc_do_erase(card, from, from + rem - 1, arg); from += rem; if ((err) || (to <= from)) @@ -2229,61 +1859,60 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, } EXPORT_SYMBOL(mmc_erase); -int mmc_can_erase(struct mmc_card *card) +bool mmc_card_can_erase(struct mmc_card *card) { - if ((card->host->caps & MMC_CAP_ERASE) && - (card->csd.cmdclass & CCC_ERASE) && card->erase_size) - return 1; - return 0; + return (card->csd.cmdclass & CCC_ERASE && card->erase_size); } -EXPORT_SYMBOL(mmc_can_erase); +EXPORT_SYMBOL(mmc_card_can_erase); -int mmc_can_trim(struct mmc_card *card) +bool mmc_card_can_trim(struct mmc_card *card) { - if ((card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) && - (!(card->quirks & MMC_QUIRK_TRIM_BROKEN))) - return 1; - return 0; + return ((card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) && + (!(card->quirks & MMC_QUIRK_TRIM_BROKEN))); } -EXPORT_SYMBOL(mmc_can_trim); +EXPORT_SYMBOL(mmc_card_can_trim); -int mmc_can_discard(struct mmc_card *card) +bool mmc_card_can_discard(struct mmc_card *card) { /* * As there's no way to detect the discard support bit at v4.5 * use the s/w feature support filed. */ - if (card->ext_csd.feature_support & MMC_DISCARD_FEATURE) - return 1; - return 0; + return (card->ext_csd.feature_support & MMC_DISCARD_FEATURE); } -EXPORT_SYMBOL(mmc_can_discard); +EXPORT_SYMBOL(mmc_card_can_discard); -int mmc_can_sanitize(struct mmc_card *card) +bool mmc_card_can_sanitize(struct mmc_card *card) { - if (!mmc_can_trim(card) && !mmc_can_erase(card)) - return 0; + if (!mmc_card_can_trim(card) && !mmc_card_can_erase(card)) + return false; if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE) - return 1; - return 0; + return true; + return false; } -EXPORT_SYMBOL(mmc_can_sanitize); -int mmc_can_secure_erase_trim(struct mmc_card *card) +bool mmc_card_can_secure_erase_trim(struct mmc_card *card) { - if ((card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN) && - !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) - return 1; - return 0; + return ((card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN) && + !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)); } -EXPORT_SYMBOL(mmc_can_secure_erase_trim); +EXPORT_SYMBOL(mmc_card_can_secure_erase_trim); -int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, +bool mmc_card_can_cmd23(struct mmc_card *card) +{ + return ((mmc_card_mmc(card) && + card->csd.mmca_vsn >= CSD_SPEC_VER_3) || + (mmc_card_sd(card) && !mmc_card_ult_capacity(card) && + card->scr.cmds & SD_SCR_CMD23_SUPPORT)); +} +EXPORT_SYMBOL(mmc_card_can_cmd23); + +int mmc_erase_group_aligned(struct mmc_card *card, sector_t from, unsigned int nr) { if (!card->erase_size) return 0; - if (from % card->erase_size || nr % card->erase_size) + if (mmc_sector_mod(from, card->erase_size) || nr % card->erase_size) return 0; return 1; } @@ -2381,9 +2010,9 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) return card->pref_erase; max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG); - if (max_discard && mmc_can_trim(card)) { + if (mmc_card_can_trim(card)) { max_trim = mmc_do_calc_max_discard(card, MMC_TRIM_ARG); - if (max_trim < max_discard) + if (max_trim < max_discard || max_discard == 0) max_discard = max_trim; } else if (max_discard < card->erase_size) { max_discard = 0; @@ -2420,28 +2049,28 @@ static void mmc_hw_reset_for_init(struct mmc_host *host) { mmc_pwrseq_reset(host); - if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) + if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->card_hw_reset) return; - host->ops->hw_reset(host); + host->ops->card_hw_reset(host); } -int mmc_hw_reset(struct mmc_host *host) +/** + * mmc_hw_reset - reset the card in hardware + * @card: card to be reset + * + * Hard reset the card. This function is only for upper layers, like the + * block layer or card drivers. You cannot use it in host drivers (struct + * mmc_card might be gone then). + * + * Return: 0 on success, -errno on failure + */ +int mmc_hw_reset(struct mmc_card *card) { + struct mmc_host *host = card->host; int ret; - if (!host->card) - return -EINVAL; - - mmc_bus_get(host); - if (!host->bus_ops || host->bus_dead || !host->bus_ops->hw_reset) { - mmc_bus_put(host); - return -EOPNOTSUPP; - } - ret = host->bus_ops->hw_reset(host); - mmc_bus_put(host); - - if (ret) + if (ret < 0) pr_warn("%s: tried to HW reset card, got error %d\n", mmc_hostname(host), ret); @@ -2449,22 +2078,15 @@ int mmc_hw_reset(struct mmc_host *host) } EXPORT_SYMBOL(mmc_hw_reset); -int mmc_sw_reset(struct mmc_host *host) +int mmc_sw_reset(struct mmc_card *card) { + struct mmc_host *host = card->host; int ret; - if (!host->card) - return -EINVAL; - - mmc_bus_get(host); - if (!host->bus_ops || host->bus_dead || !host->bus_ops->sw_reset) { - mmc_bus_put(host); + if (!host->bus_ops->sw_reset) return -EOPNOTSUPP; - } ret = host->bus_ops->sw_reset(host); - mmc_bus_put(host); - if (ret) pr_warn("%s: tried to SW reset card, got error %d\n", mmc_hostname(host), ret); @@ -2499,8 +2121,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) mmc_go_idle(host); - if (!(host->caps2 & MMC_CAP2_NO_SD)) - mmc_send_if_cond(host, host->ocr_avail); + if (!(host->caps2 & MMC_CAP2_NO_SD)) { + if (mmc_send_if_cond_pcie(host, host->ocr_avail)) + goto out; + if (mmc_card_sd_express(host)) + return 0; + } /* Order's important: probe SDIO, then SD, then MMC */ if (!(host->caps2 & MMC_CAP2_NO_SDIO)) @@ -2515,6 +2141,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) if (!mmc_attach_mmc(host)) return 0; +out: mmc_power_off(host); return -EIO; } @@ -2586,6 +2213,41 @@ int mmc_detect_card_removed(struct mmc_host *host) } EXPORT_SYMBOL(mmc_detect_card_removed); +int mmc_card_alternative_gpt_sector(struct mmc_card *card, sector_t *gpt_sector) +{ + unsigned int boot_sectors_num; + + if ((!(card->host->caps2 & MMC_CAP2_ALT_GPT_TEGRA))) + return -EOPNOTSUPP; + + /* filter out unrelated cards */ + if (card->ext_csd.rev < 3 || + !mmc_card_mmc(card) || + !mmc_card_is_blockaddr(card) || + mmc_card_is_removable(card->host)) + return -ENOENT; + + /* + * eMMC storage has two special boot partitions in addition to the + * main one. NVIDIA's bootloader linearizes eMMC boot0->boot1->main + * accesses, this means that the partition table addresses are shifted + * by the size of boot partitions. In accordance with the eMMC + * specification, the boot partition size is calculated as follows: + * + * boot partition size = 128K byte x BOOT_SIZE_MULT + * + * Calculate number of sectors occupied by the both boot partitions. + */ + boot_sectors_num = card->ext_csd.raw_boot_mult * SZ_128K / + SZ_512 * MMC_NUM_BOOT_PARTITION; + + /* Defined by NVIDIA and used by Android devices. */ + *gpt_sector = card->ext_csd.sectors - boot_sectors_num - 1; + + return 0; +} +EXPORT_SYMBOL(mmc_card_alternative_gpt_sector); + void mmc_rescan(struct work_struct *work) { struct mmc_host *host = @@ -2607,35 +2269,15 @@ void mmc_rescan(struct work_struct *work) host->trigger_card_event = false; } - mmc_bus_get(host); - - /* - * if there is a _removable_ card registered, check whether it is - * still present - */ - if (host->bus_ops && !host->bus_dead && mmc_card_is_removable(host)) + /* Verify a registered card to be functional, else remove it. */ + if (host->bus_ops) host->bus_ops->detect(host); host->detect_change = 0; - /* - * Let mmc_bus_put() free the bus/bus_ops if we've found that - * the card is no longer present. - */ - mmc_bus_put(host); - mmc_bus_get(host); - /* if there still is a card present, stop here */ - if (host->bus_ops != NULL) { - mmc_bus_put(host); + if (host->bus_ops != NULL) goto out; - } - - /* - * Only we can add a new handler, so it's safe to - * release the lock here. - */ - mmc_bus_put(host); mmc_claim_host(host); if (mmc_card_is_removable(host) && host->ops->get_cd && @@ -2645,12 +2287,47 @@ void mmc_rescan(struct work_struct *work) goto out; } + /* If an SD express card is present, then leave it as is. */ + if (mmc_card_sd_express(host)) { + mmc_release_host(host); + goto out; + } + + /* + * Ideally we should favor initialization of legacy SD cards and defer + * UHS-II enumeration. However, it seems like cards doesn't reliably + * announce their support for UHS-II in the response to the ACMD41, + * while initializing the legacy SD interface. Therefore, let's start + * with UHS-II for now. + */ + if (!mmc_attach_sd_uhs2(host)) { + mmc_release_host(host); + goto out; + } + for (i = 0; i < ARRAY_SIZE(freqs); i++) { - if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) + unsigned int freq = freqs[i]; + if (freq > host->f_max) { + if (i + 1 < ARRAY_SIZE(freqs)) + continue; + freq = host->f_max; + } + if (!mmc_rescan_try_freq(host, max(freq, host->f_min))) break; if (freqs[i] <= host->f_min) break; } + + /* A non-removable card should have been detected by now. */ + if (!mmc_card_is_removable(host) && !host->bus_ops) + pr_info("%s: Failed to initialize a non-removable card", + mmc_hostname(host)); + + /* + * Ignore the command timeout errors observed during + * the card init as those are excepted. + */ + host->err_stats[MMC_ERR_CMD_TIMEOUT] = 0; mmc_release_host(host); out: @@ -2660,11 +2337,13 @@ void mmc_rescan(struct work_struct *work) void mmc_start_host(struct mmc_host *host) { - host->f_init = max(freqs[0], host->f_min); + bool power_up = !(host->caps2 & + (MMC_CAP2_NO_PRESCAN_POWERUP | MMC_CAP2_SD_UHS2)); + + host->f_init = max(min(freqs[0], host->f_max), host->f_min); host->rescan_disable = 0; - host->ios.power_mode = MMC_POWER_UNDEFINED; - if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) { + if (power_up) { mmc_claim_host(host); mmc_power_up(host, host->ocr_avail); mmc_release_host(host); @@ -2674,8 +2353,11 @@ void mmc_start_host(struct mmc_host *host) _mmc_detect_change(host, 0, false); } -void mmc_stop_host(struct mmc_host *host) +void __mmc_stop_host(struct mmc_host *host) { + if (host->rescan_disable) + return; + if (host->slot.cd_irq >= 0) { mmc_gpio_set_cd_wake(host, false); disable_irq(host->slot.cd_irq); @@ -2683,102 +2365,30 @@ void mmc_stop_host(struct mmc_host *host) host->rescan_disable = 1; cancel_delayed_work_sync(&host->detect); +} + +void mmc_stop_host(struct mmc_host *host) +{ + __mmc_stop_host(host); /* clear pm flags now and let card drivers set them as needed */ host->pm_flags = 0; - mmc_bus_get(host); - if (host->bus_ops && !host->bus_dead) { + if (host->bus_ops) { /* Calling bus_ops->remove() with a claimed host can deadlock */ host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_power_off(host); mmc_release_host(host); - mmc_bus_put(host); return; } - mmc_bus_put(host); mmc_claim_host(host); mmc_power_off(host); mmc_release_host(host); } -#ifdef CONFIG_PM_SLEEP -/* Do the card removal on suspend if card is assumed removeable - * Do that in pm notifier while userspace isn't yet frozen, so we will be able - to sync the card. -*/ -static int mmc_pm_notify(struct notifier_block *notify_block, - unsigned long mode, void *unused) -{ - struct mmc_host *host = container_of( - notify_block, struct mmc_host, pm_notify); - unsigned long flags; - int err = 0; - - switch (mode) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - case PM_RESTORE_PREPARE: - spin_lock_irqsave(&host->lock, flags); - host->rescan_disable = 1; - spin_unlock_irqrestore(&host->lock, flags); - cancel_delayed_work_sync(&host->detect); - - if (!host->bus_ops) - break; - - /* Validate prerequisites for suspend */ - if (host->bus_ops->pre_suspend) - err = host->bus_ops->pre_suspend(host); - if (!err) - break; - - if (!mmc_card_is_removable(host)) { - dev_warn(mmc_dev(host), - "pre_suspend failed for non-removable host: " - "%d\n", err); - /* Avoid removing non-removable hosts */ - break; - } - - /* Calling bus_ops->remove() with a claimed host can deadlock */ - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_power_off(host); - mmc_release_host(host); - host->pm_flags = 0; - break; - - case PM_POST_SUSPEND: - case PM_POST_HIBERNATION: - case PM_POST_RESTORE: - - spin_lock_irqsave(&host->lock, flags); - host->rescan_disable = 0; - spin_unlock_irqrestore(&host->lock, flags); - _mmc_detect_change(host, 0, false); - - } - - return 0; -} - -void mmc_register_pm_notifier(struct mmc_host *host) -{ - host->pm_notify.notifier_call = mmc_pm_notify; - register_pm_notifier(&host->pm_notify); -} - -void mmc_unregister_pm_notifier(struct mmc_host *host) -{ - unregister_pm_notifier(&host->pm_notify); -} -#endif - static int __init mmc_init(void) { int ret; @@ -2814,4 +2424,5 @@ static void __exit mmc_exit(void) subsys_initcall(mmc_init); module_exit(mmc_exit); +MODULE_DESCRIPTION("MMC core driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 8fb6bc37f808..a028b48be164 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -1,12 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * linux/drivers/mmc/core/core.h * * Copyright (C) 2003 Russell King, All Rights Reserved. * Copyright 2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef _MMC_CORE_CORE_H #define _MMC_CORE_CORE_H @@ -32,6 +29,9 @@ struct mmc_bus_ops { int (*shutdown)(struct mmc_host *); int (*hw_reset)(struct mmc_host *); int (*sw_reset)(struct mmc_host *); + bool (*cache_enabled)(struct mmc_host *); + int (*flush_cache)(struct mmc_host *); + int (*handle_undervoltage)(struct mmc_host *host); }; void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); @@ -59,6 +59,11 @@ void mmc_power_up(struct mmc_host *host, u32 ocr); void mmc_power_off(struct mmc_host *host); void mmc_power_cycle(struct mmc_host *host, u32 ocr); void mmc_set_initial_state(struct mmc_host *host); +u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max); +int mmc_handle_undervoltage(struct mmc_host *host); +void mmc_regulator_register_undervoltage_notifier(struct mmc_host *host); +void mmc_regulator_unregister_undervoltage_notifier(struct mmc_host *host); +void mmc_undervoltage_workfn(struct work_struct *work); static inline void mmc_delay(unsigned int ms) { @@ -70,51 +75,61 @@ static inline void mmc_delay(unsigned int ms) void mmc_rescan(struct work_struct *work); void mmc_start_host(struct mmc_host *host); +void __mmc_stop_host(struct mmc_host *host); void mmc_stop_host(struct mmc_host *host); +void _mmc_detect_change(struct mmc_host *host, unsigned long delay, + bool cd_irq); int _mmc_detect_card_removed(struct mmc_host *host); int mmc_detect_card_removed(struct mmc_host *host); int mmc_attach_mmc(struct mmc_host *host); int mmc_attach_sd(struct mmc_host *host); int mmc_attach_sdio(struct mmc_host *host); +int mmc_attach_sd_uhs2(struct mmc_host *host); /* Module parameters */ extern bool use_spi_crc; /* Debugfs information for hosts and cards */ +#ifdef CONFIG_DEBUG_FS void mmc_add_host_debugfs(struct mmc_host *host); void mmc_remove_host_debugfs(struct mmc_host *host); void mmc_add_card_debugfs(struct mmc_card *card); void mmc_remove_card_debugfs(struct mmc_card *card); +#else +static inline void mmc_add_host_debugfs(struct mmc_host *host) +{ +} +static inline void mmc_remove_host_debugfs(struct mmc_host *host) +{ +} +static inline void mmc_add_card_debugfs(struct mmc_card *card) +{ +} +static inline void mmc_remove_card_debugfs(struct mmc_card *card) +{ +} +#endif int mmc_execute_tuning(struct mmc_card *card); int mmc_hs200_to_hs400(struct mmc_card *card); int mmc_hs400_to_hs200(struct mmc_card *card); -#ifdef CONFIG_PM_SLEEP -void mmc_register_pm_notifier(struct mmc_host *host); -void mmc_unregister_pm_notifier(struct mmc_host *host); -#else -static inline void mmc_register_pm_notifier(struct mmc_host *host) { } -static inline void mmc_unregister_pm_notifier(struct mmc_host *host) { } -#endif - void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq); bool mmc_is_req_done(struct mmc_host *host, struct mmc_request *mrq); int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq); -int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, - unsigned int arg); -int mmc_can_erase(struct mmc_card *card); -int mmc_can_trim(struct mmc_card *card); -int mmc_can_discard(struct mmc_card *card); -int mmc_can_sanitize(struct mmc_card *card); -int mmc_can_secure_erase_trim(struct mmc_card *card); -int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, - unsigned int nr); +int mmc_erase(struct mmc_card *card, sector_t from, unsigned int nr, unsigned int arg); +bool mmc_card_can_erase(struct mmc_card *card); +bool mmc_card_can_trim(struct mmc_card *card); +bool mmc_card_can_discard(struct mmc_card *card); +bool mmc_card_can_sanitize(struct mmc_card *card); +bool mmc_card_can_secure_erase_trim(struct mmc_card *card); +bool mmc_card_can_cmd23(struct mmc_card *card); +int mmc_erase_group_aligned(struct mmc_card *card, sector_t from, unsigned int nr); unsigned int mmc_calc_max_discard(struct mmc_card *card); int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen); @@ -125,6 +140,8 @@ void mmc_release_host(struct mmc_host *host); void mmc_get_card(struct mmc_card *card, struct mmc_ctx *ctx); void mmc_put_card(struct mmc_card *card, struct mmc_ctx *ctx); +int mmc_card_alternative_gpt_sector(struct mmc_card *card, sector_t *sector); + /** * mmc_claim_host - exclusively claim a host * @host: mmc host to claim @@ -171,4 +188,30 @@ static inline void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, host->ops->post_req(host, mrq, err); } +static inline bool mmc_cache_enabled(struct mmc_host *host) +{ + if (host->bus_ops->cache_enabled) + return host->bus_ops->cache_enabled(host); + + return false; +} + +static inline int mmc_flush_cache(struct mmc_host *host) +{ + if (host->bus_ops->flush_cache) + return host->bus_ops->flush_cache(host); + + return 0; +} + +static inline unsigned int mmc_sector_div(sector_t dividend, u32 divisor) +{ + return div_u64(dividend, divisor); +} + +static inline unsigned int mmc_sector_mod(sector_t dividend, u32 divisor) +{ + return sector_div(dividend, divisor); +} + #endif diff --git a/drivers/mmc/core/crypto.c b/drivers/mmc/core/crypto.c new file mode 100644 index 000000000000..fec4fbf16a5b --- /dev/null +++ b/drivers/mmc/core/crypto.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MMC crypto engine (inline encryption) support + * + * Copyright 2020 Google LLC + */ + +#include <linux/blk-crypto.h> +#include <linux/mmc/host.h> + +#include "core.h" +#include "crypto.h" +#include "queue.h" + +void mmc_crypto_set_initial_state(struct mmc_host *host) +{ + /* Reset might clear all keys, so reprogram all the keys. */ + if (host->caps2 & MMC_CAP2_CRYPTO) + blk_crypto_reprogram_all_keys(&host->crypto_profile); +} + +void mmc_crypto_setup_queue(struct request_queue *q, struct mmc_host *host) +{ + if (host->caps2 & MMC_CAP2_CRYPTO) + blk_crypto_register(&host->crypto_profile, q); +} +EXPORT_SYMBOL_GPL(mmc_crypto_setup_queue); + +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; + struct blk_crypto_keyslot *keyslot; + + if (!req->crypt_ctx) + return; + + mrq->crypto_ctx = req->crypt_ctx; + + keyslot = req->crypt_keyslot; + if (keyslot) + mrq->crypto_key_slot = blk_crypto_keyslot_index(keyslot); +} +EXPORT_SYMBOL_GPL(mmc_crypto_prepare_req); diff --git a/drivers/mmc/core/crypto.h b/drivers/mmc/core/crypto.h new file mode 100644 index 000000000000..fbe9a520bf90 --- /dev/null +++ b/drivers/mmc/core/crypto.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * MMC crypto engine (inline encryption) support + * + * Copyright 2020 Google LLC + */ + +#ifndef _MMC_CORE_CRYPTO_H +#define _MMC_CORE_CRYPTO_H + +struct mmc_host; +struct mmc_queue_req; +struct request_queue; + +#ifdef CONFIG_MMC_CRYPTO + +void mmc_crypto_set_initial_state(struct mmc_host *host); + +void mmc_crypto_setup_queue(struct request_queue *q, struct mmc_host *host); + +void mmc_crypto_prepare_req(struct mmc_queue_req *mqrq); + +#else /* CONFIG_MMC_CRYPTO */ + +static inline void mmc_crypto_set_initial_state(struct mmc_host *host) +{ +} + +static inline void mmc_crypto_setup_queue(struct request_queue *q, + struct mmc_host *host) +{ +} + +static inline void mmc_crypto_prepare_req(struct mmc_queue_req *mqrq) +{ +} + +#endif /* !CONFIG_MMC_CRYPTO */ + +#endif /* _MMC_CORE_CRYPTO_H */ diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index d2275c5a2311..91ea00a0f61d 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Debugfs support for hosts and cards * * Copyright (C) 2008 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/moduleparam.h> #include <linux/export.h> @@ -15,9 +12,12 @@ #include <linux/slab.h> #include <linux/stat.h> #include <linux/fault-inject.h> +#include <linux/time.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> +#include <linux/mmc/mmc.h> +#include <linux/mmc/sd.h> #include "core.h" #include "card.h" @@ -29,6 +29,7 @@ static DECLARE_FAULT_ATTR(fail_default_attr); static char *fail_request; module_param(fail_request, charp, 0); +MODULE_PARM_DESC(fail_request, "default fault injection attributes"); #endif /* CONFIG_FAIL_MMC_REQUEST */ @@ -222,53 +223,159 @@ static int mmc_clock_opt_set(void *data, u64 val) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, +DEFINE_DEBUGFS_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, "%llu\n"); +static int mmc_err_state_get(void *data, u64 *val) +{ + struct mmc_host *host = data; + int i; + + if (!host) + return -EINVAL; + + *val = 0; + for (i = 0; i < MMC_ERR_MAX; i++) { + if (host->err_stats[i]) { + *val = 1; + break; + } + } + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(mmc_err_state, mmc_err_state_get, NULL, "%llu\n"); + +static int mmc_err_stats_show(struct seq_file *file, void *data) +{ + struct mmc_host *host = file->private; + const char *desc[MMC_ERR_MAX] = { + [MMC_ERR_CMD_TIMEOUT] = "Command Timeout Occurred", + [MMC_ERR_CMD_CRC] = "Command CRC Errors Occurred", + [MMC_ERR_DAT_TIMEOUT] = "Data Timeout Occurred", + [MMC_ERR_DAT_CRC] = "Data CRC Errors Occurred", + [MMC_ERR_AUTO_CMD] = "Auto-Cmd Error Occurred", + [MMC_ERR_ADMA] = "ADMA Error Occurred", + [MMC_ERR_TUNING] = "Tuning Error Occurred", + [MMC_ERR_CMDQ_RED] = "CMDQ RED Errors", + [MMC_ERR_CMDQ_GCE] = "CMDQ GCE Errors", + [MMC_ERR_CMDQ_ICCE] = "CMDQ ICCE Errors", + [MMC_ERR_REQ_TIMEOUT] = "Request Timedout", + [MMC_ERR_CMDQ_REQ_TIMEOUT] = "CMDQ Request Timedout", + [MMC_ERR_ICE_CFG] = "ICE Config Errors", + [MMC_ERR_CTRL_TIMEOUT] = "Controller Timedout errors", + [MMC_ERR_UNEXPECTED_IRQ] = "Unexpected IRQ errors", + }; + int i; + + for (i = 0; i < MMC_ERR_MAX; i++) { + if (desc[i]) + seq_printf(file, "# %s:\t %d\n", + desc[i], host->err_stats[i]); + } + + return 0; +} + +static int mmc_err_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, mmc_err_stats_show, inode->i_private); +} + +static ssize_t mmc_err_stats_write(struct file *filp, const char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct mmc_host *host = filp->f_mapping->host->i_private; + + pr_debug("%s: Resetting MMC error statistics\n", __func__); + memset(host->err_stats, 0, sizeof(host->err_stats)); + + return cnt; +} + +static const struct file_operations mmc_err_stats_fops = { + .open = mmc_err_stats_open, + .read = seq_read, + .write = mmc_err_stats_write, + .release = single_release, +}; + +static int mmc_caps_get(void *data, u64 *val) +{ + *val = *(u32 *)data; + return 0; +} + +static int mmc_caps_set(void *data, u64 val) +{ + u32 *caps = data; + u32 diff = *caps ^ val; + u32 allowed = MMC_CAP_AGGRESSIVE_PM | + MMC_CAP_SD_HIGHSPEED | + MMC_CAP_MMC_HIGHSPEED | + MMC_CAP_UHS | + MMC_CAP_DDR | + MMC_CAP_4_BIT_DATA | + MMC_CAP_8_BIT_DATA | + MMC_CAP_CMD23; + + if (diff & ~allowed) + return -EINVAL; + + *caps = val; + + return 0; +} + +static int mmc_caps2_set(void *data, u64 val) +{ + u32 allowed = MMC_CAP2_HSX00_1_8V | + MMC_CAP2_HSX00_1_2V | + MMC_CAP2_CQE | + MMC_CAP2_CQE_DCMD; + u32 *caps = data; + u32 diff = *caps ^ val; + + if (diff & ~allowed) + return -EINVAL; + + *caps = val; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(mmc_caps_fops, mmc_caps_get, mmc_caps_set, + "0x%08llx\n"); +DEFINE_DEBUGFS_ATTRIBUTE(mmc_caps2_fops, mmc_caps_get, mmc_caps2_set, + "0x%08llx\n"); + void mmc_add_host_debugfs(struct mmc_host *host) { struct dentry *root; root = debugfs_create_dir(mmc_hostname(host), NULL); - if (IS_ERR(root)) - /* Don't complain -- debugfs just isn't enabled */ - return; - if (!root) - /* Complain -- debugfs is enabled, but it failed to - * create the directory. */ - goto err_root; - host->debugfs_root = root; - if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) - goto err_node; - - if (!debugfs_create_x32("caps", S_IRUSR, root, &host->caps)) - goto err_node; + debugfs_create_file("ios", 0400, root, host, &mmc_ios_fops); + debugfs_create_file("caps", 0600, root, &host->caps, &mmc_caps_fops); + debugfs_create_file("caps2", 0600, root, &host->caps2, + &mmc_caps2_fops); + debugfs_create_file_unsafe("clock", 0600, root, host, + &mmc_clock_fops); - if (!debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2)) - goto err_node; - - if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, - &mmc_clock_fops)) - goto err_node; + debugfs_create_file_unsafe("err_state", 0600, root, host, + &mmc_err_state); + debugfs_create_file("err_stats", 0600, root, host, + &mmc_err_stats_fops); #ifdef CONFIG_FAIL_MMC_REQUEST if (fail_request) setup_fault_attr(&fail_default_attr, fail_request); host->fail_mmc_request = fail_default_attr; - if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request", - root, - &host->fail_mmc_request))) - goto err_node; + fault_create_debugfs_attr("fail_mmc_request", root, + &host->fail_mmc_request); #endif - return; - -err_node: - debugfs_remove_recursive(root); - host->debugfs_root = NULL; -err_root: - dev_err(&host->class_dev, "failed to initialize debugfs\n"); } void mmc_remove_host_debugfs(struct mmc_host *host) @@ -285,25 +392,10 @@ void mmc_add_card_debugfs(struct mmc_card *card) return; root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root); - if (IS_ERR(root)) - /* Don't complain -- debugfs just isn't enabled */ - return; - if (!root) - /* Complain -- debugfs is enabled, but it failed to - * create the directory. */ - goto err; - card->debugfs_root = root; - if (!debugfs_create_x32("state", S_IRUSR, root, &card->state)) - goto err; - - return; - -err: - debugfs_remove_recursive(root); - card->debugfs_root = NULL; - dev_err(&card->dev, "failed to initialize debugfs\n"); + debugfs_create_x32("state", 0400, root, &card->state); + debugfs_create_x32("quirks", 0400, root, &card->quirks); } void mmc_remove_card_debugfs(struct mmc_card *card) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index cf58ccaf22d5..88c95dbfd9cf 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/mmc/core/host.c * @@ -5,10 +6,6 @@ * Copyright (C) 2007-2008 Pierre Ossman * Copyright (C) 2010 Linus Walleij * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * * MMC host class device management */ @@ -16,7 +13,6 @@ #include <linux/err.h> #include <linux/idr.h> #include <linux/of.h> -#include <linux/of_gpio.h> #include <linux/pagemap.h> #include <linux/export.h> #include <linux/leds.h> @@ -27,6 +23,7 @@ #include <linux/mmc/slot-gpio.h> #include "core.h" +#include "crypto.h" #include "host.h" #include "slot-gpio.h" #include "pwrseq.h" @@ -36,16 +33,64 @@ static DEFINE_IDA(mmc_host_ida); +#ifdef CONFIG_PM_SLEEP +static int mmc_host_class_prepare(struct device *dev) +{ + struct mmc_host *host = cls_dev_to_mmc_host(dev); + + /* + * It's safe to access the bus_ops pointer, as both userspace and the + * workqueue for detecting cards are frozen at this point. + */ + if (!host->bus_ops) + return 0; + + /* Validate conditions for system suspend. */ + if (host->bus_ops->pre_suspend) + return host->bus_ops->pre_suspend(host); + + return 0; +} + +static void mmc_host_class_complete(struct device *dev) +{ + struct mmc_host *host = cls_dev_to_mmc_host(dev); + + _mmc_detect_change(host, 0, false); +} + +static const struct dev_pm_ops mmc_host_class_dev_pm_ops = { + .prepare = mmc_host_class_prepare, + .complete = mmc_host_class_complete, +}; + +#define MMC_HOST_CLASS_DEV_PM_OPS (&mmc_host_class_dev_pm_ops) +#else +#define MMC_HOST_CLASS_DEV_PM_OPS NULL +#endif + static void mmc_host_classdev_release(struct device *dev) { struct mmc_host *host = cls_dev_to_mmc_host(dev); - ida_simple_remove(&mmc_host_ida, host->index); + wakeup_source_unregister(host->ws); + if (of_alias_get_id(host->parent->of_node, "mmc") < 0) + ida_free(&mmc_host_ida, host->index); kfree(host); } -static struct class mmc_host_class = { +static int mmc_host_classdev_shutdown(struct device *dev) +{ + struct mmc_host *host = cls_dev_to_mmc_host(dev); + + __mmc_stop_host(host); + return 0; +} + +static const struct class mmc_host_class = { .name = "mmc_host", .dev_release = mmc_host_classdev_release, + .shutdown_pre = mmc_host_classdev_shutdown, + .pm = MMC_HOST_CLASS_DEV_PM_OPS, }; int mmc_register_host_class(void) @@ -58,6 +103,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; @@ -68,13 +117,12 @@ void mmc_retune_enable(struct mmc_host *host) /* * Pause re-tuning for a small set of operations. The pause begins after the - * next command and after first doing re-tuning. + * next command. */ void mmc_retune_pause(struct mmc_host *host) { if (!host->retune_paused) { host->retune_paused = 1; - mmc_retune_needed(host); mmc_retune_hold(host); } } @@ -89,18 +137,23 @@ 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); host->can_retune = 0; - del_timer_sync(&host->retune_timer); - host->retune_now = 0; - host->need_retune = 0; + timer_delete_sync(&host->retune_timer); + mmc_retune_clear(host); } void mmc_retune_timer_stop(struct mmc_host *host) { - del_timer_sync(&host->retune_timer); + timer_delete_sync(&host->retune_timer); } EXPORT_SYMBOL(mmc_retune_timer_stop); @@ -159,17 +212,59 @@ out: static void mmc_retune_timer(struct timer_list *t) { - struct mmc_host *host = from_timer(host, t, retune_timer); + struct mmc_host *host = timer_container_of(host, t, retune_timer); mmc_retune_needed(host); } +static void mmc_of_parse_timing_phase(struct device *dev, const char *prop, + struct mmc_clk_phase *phase) +{ + int degrees[2] = {0}; + int rc; + + rc = device_property_read_u32_array(dev, prop, degrees, 2); + phase->valid = !rc; + if (phase->valid) { + phase->in_deg = degrees[0]; + phase->out_deg = degrees[1]; + } +} + +void +mmc_of_parse_clk_phase(struct device *dev, struct mmc_clk_phase_map *map) +{ + mmc_of_parse_timing_phase(dev, "clk-phase-legacy", + &map->phase[MMC_TIMING_LEGACY]); + mmc_of_parse_timing_phase(dev, "clk-phase-mmc-hs", + &map->phase[MMC_TIMING_MMC_HS]); + mmc_of_parse_timing_phase(dev, "clk-phase-sd-hs", + &map->phase[MMC_TIMING_SD_HS]); + mmc_of_parse_timing_phase(dev, "clk-phase-uhs-sdr12", + &map->phase[MMC_TIMING_UHS_SDR12]); + mmc_of_parse_timing_phase(dev, "clk-phase-uhs-sdr25", + &map->phase[MMC_TIMING_UHS_SDR25]); + mmc_of_parse_timing_phase(dev, "clk-phase-uhs-sdr50", + &map->phase[MMC_TIMING_UHS_SDR50]); + mmc_of_parse_timing_phase(dev, "clk-phase-uhs-sdr104", + &map->phase[MMC_TIMING_UHS_SDR104]); + mmc_of_parse_timing_phase(dev, "clk-phase-uhs-ddr50", + &map->phase[MMC_TIMING_UHS_DDR50]); + mmc_of_parse_timing_phase(dev, "clk-phase-mmc-ddr52", + &map->phase[MMC_TIMING_MMC_DDR52]); + mmc_of_parse_timing_phase(dev, "clk-phase-mmc-hs200", + &map->phase[MMC_TIMING_MMC_HS200]); + mmc_of_parse_timing_phase(dev, "clk-phase-mmc-hs400", + &map->phase[MMC_TIMING_MMC_HS400]); +} +EXPORT_SYMBOL(mmc_of_parse_clk_phase); + /** - * mmc_of_parse() - parse host's device-tree node - * @host: host whose node should be parsed. + * mmc_of_parse() - parse host's device properties + * @host: host whose properties should be parsed. * * To keep the rest of the MMC subsystem unaware of whether DT has been - * used to to instantiate and configure this host instance or not, we + * used to instantiate and configure this host instance or not, we * parse the properties and set respective generic mmc-host flags and * parameters. */ @@ -178,8 +273,6 @@ int mmc_of_parse(struct mmc_host *host) struct device *dev = host->parent; u32 bus_width, drv_type, cd_debounce_delay_ms; int ret; - bool cd_cap_invert, cd_gpio_invert = false; - bool ro_cap_invert, ro_gpio_invert = false; if (!dev || !dev_fwnode(dev)) return 0; @@ -194,7 +287,7 @@ int mmc_of_parse(struct mmc_host *host) switch (bus_width) { case 8: host->caps |= MMC_CAP_8_BIT_DATA; - /* Hosts capable of 8-bit transfers can also do 4 bits */ + fallthrough; /* Hosts capable of 8-bit can also do 4 bits */ case 4: host->caps |= MMC_CAP_4_BIT_DATA; break; @@ -209,6 +302,8 @@ int mmc_of_parse(struct mmc_host *host) /* f_max is obtained from the optional "max-frequency" property */ device_property_read_u32(dev, "max-frequency", &host->f_max); + device_property_read_u32(dev, "max-sd-hs-hz", &host->max_sd_hs_hz); + /* * Configure CD and WP pins. They are both by default active low to * match the SDHCI spec. If GPIOs are provided for CD and / or WP, the @@ -222,10 +317,12 @@ int mmc_of_parse(struct mmc_host *host) */ /* Parse Card Detection */ + if (device_property_read_bool(dev, "non-removable")) { host->caps |= MMC_CAP_NONREMOVABLE; } else { - cd_cap_invert = device_property_read_bool(dev, "cd-inverted"); + if (device_property_read_bool(dev, "cd-inverted")) + host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; if (device_property_read_u32(dev, "cd-debounce-delay-ms", &cd_debounce_delay_ms)) @@ -235,32 +332,19 @@ int mmc_of_parse(struct mmc_host *host) host->caps |= MMC_CAP_NEEDS_POLL; ret = mmc_gpiod_request_cd(host, "cd", 0, false, - cd_debounce_delay_ms * 1000, - &cd_gpio_invert); + cd_debounce_delay_ms * 1000); if (!ret) dev_info(host->parent, "Got CD GPIO\n"); else if (ret != -ENOENT && ret != -ENOSYS) return ret; - - /* - * There are two ways to flag that the CD line is inverted: - * through the cd-inverted flag and by the GPIO line itself - * being inverted from the GPIO subsystem. This is a leftover - * from the times when the GPIO subsystem did not make it - * possible to flag a line as inverted. - * - * If the capability on the host AND the GPIO line are - * both inverted, the end result is that the CD line is - * not inverted. - */ - if (cd_cap_invert ^ cd_gpio_invert) - host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; } /* Parse Write Protection */ - ro_cap_invert = device_property_read_bool(dev, "wp-inverted"); - ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert); + if (device_property_read_bool(dev, "wp-inverted")) + host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + + ret = mmc_gpiod_request_ro(host, "wp", 0, 0); if (!ret) dev_info(host->parent, "Got WP GPIO\n"); else if (ret != -ENOENT && ret != -ENOSYS) @@ -269,10 +353,6 @@ int mmc_of_parse(struct mmc_host *host) if (device_property_read_bool(dev, "disable-wp")) host->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; - /* See the comment on CD inversion above */ - if (ro_cap_invert ^ ro_gpio_invert) - host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; - if (device_property_read_bool(dev, "cap-sd-highspeed")) host->caps |= MMC_CAP_SD_HIGHSPEED; if (device_property_read_bool(dev, "cap-mmc-highspeed")) @@ -295,6 +375,8 @@ int mmc_of_parse(struct mmc_host *host) host->caps |= MMC_CAP_SDIO_IRQ; if (device_property_read_bool(dev, "full-pwr-cycle")) host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE; + if (device_property_read_bool(dev, "full-pwr-cycle-in-suspend")) + host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND; if (device_property_read_bool(dev, "keep-power-in-suspend")) host->pm_caps |= MMC_PM_KEEP_POWER; if (device_property_read_bool(dev, "wakeup-source") || @@ -322,6 +404,9 @@ int mmc_of_parse(struct mmc_host *host) host->caps2 |= MMC_CAP2_NO_SD; if (device_property_read_bool(dev, "no-mmc")) host->caps2 |= MMC_CAP2_NO_MMC; + if (device_property_read_bool(dev, "no-mmc-hs400")) + host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V | + MMC_CAP2_HS400_ES); /* Must be after "non-removable" check */ if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) { @@ -349,6 +434,82 @@ int mmc_of_parse(struct mmc_host *host) EXPORT_SYMBOL(mmc_of_parse); /** + * mmc_of_parse_voltage - return mask of supported voltages + * @host: host whose properties should be parsed. + * @mask: mask of voltages available for MMC/SD/SDIO + * + * Parse the "voltage-ranges" property, returning zero if it is not + * found, negative errno if the voltage-range specification is invalid, + * or one if the voltage-range is specified and successfully parsed. + */ +int mmc_of_parse_voltage(struct mmc_host *host, u32 *mask) +{ + const char *prop = "voltage-ranges"; + struct device *dev = host->parent; + u32 *voltage_ranges; + int num_ranges, i; + int ret; + + if (!device_property_present(dev, prop)) { + dev_dbg(dev, "%s unspecified\n", prop); + return 0; + } + + ret = device_property_count_u32(dev, prop); + if (ret < 0) + return ret; + + num_ranges = ret / 2; + if (!num_ranges) { + dev_err(dev, "%s empty\n", prop); + return -EINVAL; + } + + voltage_ranges = kcalloc(2 * num_ranges, sizeof(*voltage_ranges), GFP_KERNEL); + if (!voltage_ranges) + return -ENOMEM; + + ret = device_property_read_u32_array(dev, prop, voltage_ranges, 2 * num_ranges); + if (ret) { + kfree(voltage_ranges); + return ret; + } + + for (i = 0; i < num_ranges; i++) { + const int j = i * 2; + u32 ocr_mask; + + ocr_mask = mmc_vddrange_to_ocrmask(voltage_ranges[j + 0], + voltage_ranges[j + 1]); + if (!ocr_mask) { + dev_err(dev, "range #%d in %s is invalid\n", i, prop); + kfree(voltage_ranges); + return -EINVAL; + } + *mask |= ocr_mask; + } + + kfree(voltage_ranges); + + return 1; +} +EXPORT_SYMBOL(mmc_of_parse_voltage); + +/** + * mmc_first_nonreserved_index() - get the first index that is not reserved + */ +static int mmc_first_nonreserved_index(void) +{ + int max; + + max = of_alias_get_highest_id("mmc"); + if (max < 0) + return 0; + + return max + 1; +} + +/** * mmc_alloc_host - initialise the per-host structure. * @extra: sizeof private data structure * @dev: pointer to host device model structure @@ -357,8 +518,9 @@ EXPORT_SYMBOL(mmc_of_parse); */ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) { - int err; + int index; struct mmc_host *host; + int alias_id, min_idx, max_idx; host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); if (!host) @@ -367,15 +529,25 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) /* scanning will be enabled when we're ready */ host->rescan_disable = 1; - err = ida_simple_get(&mmc_host_ida, 0, 0, GFP_KERNEL); - if (err < 0) { - kfree(host); - return NULL; + alias_id = of_alias_get_id(dev->of_node, "mmc"); + if (alias_id >= 0) { + index = alias_id; + } else { + min_idx = mmc_first_nonreserved_index(); + max_idx = 0; + + index = ida_alloc_range(&mmc_host_ida, min_idx, max_idx - 1, + GFP_KERNEL); + if (index < 0) { + kfree(host); + return NULL; + } } - host->index = err; + host->index = index; dev_set_name(&host->class_dev, "mmc%d", host->index); + host->ws = wakeup_source_register(NULL, dev_name(&host->class_dev)); host->parent = dev; host->class_dev.parent = dev; @@ -385,17 +557,17 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) if (mmc_gpio_alloc(host)) { put_device(&host->class_dev); - ida_simple_remove(&mmc_host_ida, host->index); - kfree(host); return NULL; } spin_lock_init(&host->lock); init_waitqueue_head(&host->wq); INIT_DELAYED_WORK(&host->detect, mmc_rescan); - INIT_DELAYED_WORK(&host->sdio_irq_work, sdio_irq_work); + INIT_WORK(&host->sdio_irq_work, sdio_irq_work); timer_setup(&host->retune_timer, mmc_retune_timer, 0); + INIT_WORK(&host->supply.uv_work, mmc_undervoltage_workfn); + /* * By default, hosts do not support SGIO or large requests. * They have to set these according to their abilities. @@ -409,12 +581,58 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) host->fixed_drv_type = -EINVAL; host->ios.power_delay_ms = 10; + host->ios.power_mode = MMC_POWER_UNDEFINED; return host; } EXPORT_SYMBOL(mmc_alloc_host); +static void devm_mmc_host_release(struct device *dev, void *res) +{ + mmc_free_host(*(struct mmc_host **)res); +} + +struct mmc_host *devm_mmc_alloc_host(struct device *dev, int extra) +{ + struct mmc_host **dr, *host; + + dr = devres_alloc(devm_mmc_host_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return NULL; + + host = mmc_alloc_host(extra, dev); + if (!host) { + devres_free(dr); + return NULL; + } + + *dr = host; + devres_add(dev, dr); + + return host; +} +EXPORT_SYMBOL(devm_mmc_alloc_host); + +static int mmc_validate_host_caps(struct mmc_host *host) +{ + struct device *dev = host->parent; + u32 caps = host->caps, caps2 = host->caps2; + + if (caps & MMC_CAP_SDIO_IRQ && !host->ops->enable_sdio_irq) { + dev_warn(dev, "missing ->enable_sdio_irq() ops\n"); + return -EINVAL; + } + + if (caps2 & (MMC_CAP2_HS400_ES | MMC_CAP2_HS400) && + !(caps & MMC_CAP_8_BIT_DATA) && !(caps2 & MMC_CAP2_NO_MMC)) { + dev_warn(dev, "drop HS400 support since no 8-bit bus\n"); + host->caps2 = caps2 & ~MMC_CAP2_HS400_ES & ~MMC_CAP2_HS400; + } + + return 0; +} + /** * mmc_add_host - initialise host hardware * @host: mmc host @@ -427,8 +645,9 @@ int mmc_add_host(struct mmc_host *host) { int err; - WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) && - !host->ops->enable_sdio_irq); + err = mmc_validate_host_caps(host); + if (err) + return err; err = device_add(&host->class_dev); if (err) @@ -436,13 +655,9 @@ int mmc_add_host(struct mmc_host *host) led_trigger_register_simple(dev_name(&host->class_dev), &host->led); -#ifdef CONFIG_DEBUG_FS mmc_add_host_debugfs(host); -#endif mmc_start_host(host); - mmc_register_pm_notifier(host); - return 0; } @@ -458,12 +673,9 @@ EXPORT_SYMBOL(mmc_add_host); */ void mmc_remove_host(struct mmc_host *host) { - mmc_unregister_pm_notifier(host); mmc_stop_host(host); -#ifdef CONFIG_DEBUG_FS mmc_remove_host_debugfs(host); -#endif device_del(&host->class_dev); @@ -480,6 +692,7 @@ EXPORT_SYMBOL(mmc_remove_host); */ void mmc_free_host(struct mmc_host *host) { + cancel_delayed_work_sync(&host->detect); mmc_pwrseq_free(host); put_device(&host->class_dev); } diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h index 4805438c02ff..5941d68ff989 100644 --- a/drivers/mmc/core/host.h +++ b/drivers/mmc/core/host.h @@ -1,12 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * linux/drivers/mmc/core/host.h * * Copyright (C) 2003 Russell King, All Rights Reserved. * Copyright 2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef _MMC_CORE_HOST_H #define _MMC_CORE_HOST_H @@ -24,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; @@ -36,22 +39,22 @@ static inline void mmc_retune_recheck(struct mmc_host *host) host->retune_now = 1; } -static inline int mmc_host_cmd23(struct mmc_host *host) +static inline int mmc_host_can_cmd23(struct mmc_host *host) { return host->caps & MMC_CAP_CMD23; } -static inline bool mmc_host_done_complete(struct mmc_host *host) +static inline bool mmc_host_can_done_complete(struct mmc_host *host) { return host->caps & MMC_CAP_DONE_COMPLETE; } -static inline int mmc_boot_partition_access(struct mmc_host *host) +static inline int mmc_host_can_access_boot(struct mmc_host *host) { return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC); } -static inline int mmc_host_uhs(struct mmc_host *host) +static inline int mmc_host_can_uhs(struct mmc_host *host) { return host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | @@ -80,5 +83,11 @@ static inline bool mmc_card_hs400es(struct mmc_card *card) return card->host->ios.enhanced_strobe; } +static inline bool mmc_card_sd_express(struct mmc_host *host) +{ + return host->ios.timing == MMC_TIMING_SD_EXP || + host->ios.timing == MMC_TIMING_SD_EXP_1_2V; +} + #endif diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index da892a599524..7c86efb1044a 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1,20 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/mmc/core/mmc.c * * Copyright (C) 2003-2004 Russell King, All Rights Reserved. * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/err.h> #include <linux/of.h> #include <linux/slab.h> #include <linux/stat.h> +#include <linux/string.h> #include <linux/pm_runtime.h> +#include <linux/random.h> +#include <linux/sysfs.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> @@ -31,6 +31,14 @@ #define DEFAULT_CMD6_TIMEOUT_MS 500 #define MIN_CACHE_EN_TIMEOUT_MS 1600 +#define CACHE_FLUSH_TIMEOUT_MS 30000 /* 30s */ + +enum mmc_poweroff_type { + MMC_POWEROFF_SUSPEND, + MMC_POWEROFF_SHUTDOWN, + MMC_POWEROFF_UNDERVOLTAGE, + MMC_POWEROFF_UNBIND, +}; static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, @@ -51,20 +59,6 @@ static const unsigned int taac_mant[] = { 35, 40, 45, 50, 55, 60, 70, 80, }; -#define UNSTUFF_BITS(resp,start,size) \ - ({ \ - const int __size = size; \ - const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \ - const int __off = 3 - ((start) / 32); \ - const int __shft = (start) & 31; \ - u32 __res; \ - \ - __res = resp[__off] >> __shft; \ - if (__size + __shft > 32) \ - __res |= resp[__off-1] << ((32 - __shft) % 32); \ - __res & __mask; \ - }) - /* * Given the decoded CSD structure, decode the raw CID to our CID structure. */ @@ -73,42 +67,48 @@ static int mmc_decode_cid(struct mmc_card *card) u32 *resp = card->raw_cid; /* + * Add the raw card ID (cid) data to the entropy pool. It doesn't + * matter that not all of it is unique, it's just bonus entropy. + */ + add_device_randomness(&card->raw_cid, sizeof(card->raw_cid)); + + /* * The selection of the format here is based upon published - * specs from sandisk and from what people have reported. + * specs from SanDisk and from what people have reported. */ switch (card->csd.mmca_vsn) { case 0: /* MMC v1.0 - v1.2 */ case 1: /* MMC v1.4 */ - card->cid.manfid = UNSTUFF_BITS(resp, 104, 24); - card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); - card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); - card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); - card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); - card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); - card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); - card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8); - card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4); - card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4); - card->cid.serial = UNSTUFF_BITS(resp, 16, 24); - card->cid.month = UNSTUFF_BITS(resp, 12, 4); - card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; + card->cid.manfid = unstuff_bits(resp, 104, 24); + card->cid.prod_name[0] = unstuff_bits(resp, 96, 8); + card->cid.prod_name[1] = unstuff_bits(resp, 88, 8); + card->cid.prod_name[2] = unstuff_bits(resp, 80, 8); + card->cid.prod_name[3] = unstuff_bits(resp, 72, 8); + card->cid.prod_name[4] = unstuff_bits(resp, 64, 8); + card->cid.prod_name[5] = unstuff_bits(resp, 56, 8); + card->cid.prod_name[6] = unstuff_bits(resp, 48, 8); + card->cid.hwrev = unstuff_bits(resp, 44, 4); + card->cid.fwrev = unstuff_bits(resp, 40, 4); + card->cid.serial = unstuff_bits(resp, 16, 24); + card->cid.month = unstuff_bits(resp, 12, 4); + card->cid.year = unstuff_bits(resp, 8, 4) + 1997; break; case 2: /* MMC v2.0 - v2.2 */ case 3: /* MMC v3.1 - v3.3 */ case 4: /* MMC v4 */ - card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); - card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); - card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); - card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); - card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); - card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); - card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); - card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); - card->cid.prv = UNSTUFF_BITS(resp, 48, 8); - card->cid.serial = UNSTUFF_BITS(resp, 16, 32); - card->cid.month = UNSTUFF_BITS(resp, 12, 4); - card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; + card->cid.manfid = unstuff_bits(resp, 120, 8); + card->cid.oemid = unstuff_bits(resp, 104, 16); + card->cid.prod_name[0] = unstuff_bits(resp, 96, 8); + card->cid.prod_name[1] = unstuff_bits(resp, 88, 8); + card->cid.prod_name[2] = unstuff_bits(resp, 80, 8); + card->cid.prod_name[3] = unstuff_bits(resp, 72, 8); + card->cid.prod_name[4] = unstuff_bits(resp, 64, 8); + card->cid.prod_name[5] = unstuff_bits(resp, 56, 8); + card->cid.prv = unstuff_bits(resp, 48, 8); + card->cid.serial = unstuff_bits(resp, 16, 32); + card->cid.month = unstuff_bits(resp, 12, 4); + card->cid.year = unstuff_bits(resp, 8, 4) + 1997; break; default: @@ -117,6 +117,9 @@ static int mmc_decode_cid(struct mmc_card *card) return -EINVAL; } + /* some product names include trailing whitespace */ + strim(card->cid.prod_name); + return 0; } @@ -130,6 +133,17 @@ static void mmc_set_erase_size(struct mmc_card *card) mmc_init_erase(card); } + +static void mmc_set_wp_grp_size(struct mmc_card *card) +{ + if (card->ext_csd.erase_group_def & 1) + card->wp_grp_size = card->ext_csd.hc_erase_size * + card->ext_csd.raw_hc_erase_gap_size; + else + card->wp_grp_size = card->csd.erase_size * + (card->csd.wp_grp_size + 1); +} + /* * Given a 128-bit response, decode to our card CSD structure. */ @@ -144,42 +158,43 @@ static int mmc_decode_csd(struct mmc_card *card) * v1.2 has extra information in bits 15, 11 and 10. * We also support eMMC v4.4 & v4.41. */ - csd->structure = UNSTUFF_BITS(resp, 126, 2); + csd->structure = unstuff_bits(resp, 126, 2); if (csd->structure == 0) { pr_err("%s: unrecognised CSD structure version %d\n", mmc_hostname(card->host), csd->structure); return -EINVAL; } - csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4); - m = UNSTUFF_BITS(resp, 115, 4); - e = UNSTUFF_BITS(resp, 112, 3); + csd->mmca_vsn = unstuff_bits(resp, 122, 4); + m = unstuff_bits(resp, 115, 4); + e = unstuff_bits(resp, 112, 3); csd->taac_ns = (taac_exp[e] * taac_mant[m] + 9) / 10; - csd->taac_clks = UNSTUFF_BITS(resp, 104, 8) * 100; + csd->taac_clks = unstuff_bits(resp, 104, 8) * 100; - m = UNSTUFF_BITS(resp, 99, 4); - e = UNSTUFF_BITS(resp, 96, 3); + m = unstuff_bits(resp, 99, 4); + e = unstuff_bits(resp, 96, 3); csd->max_dtr = tran_exp[e] * tran_mant[m]; - csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); + csd->cmdclass = unstuff_bits(resp, 84, 12); - e = UNSTUFF_BITS(resp, 47, 3); - m = UNSTUFF_BITS(resp, 62, 12); + e = unstuff_bits(resp, 47, 3); + m = unstuff_bits(resp, 62, 12); csd->capacity = (1 + m) << (e + 2); - csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); - csd->read_partial = UNSTUFF_BITS(resp, 79, 1); - csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); - csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); - csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1); - csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); - csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); - csd->write_partial = UNSTUFF_BITS(resp, 21, 1); + csd->read_blkbits = unstuff_bits(resp, 80, 4); + csd->read_partial = unstuff_bits(resp, 79, 1); + csd->write_misalign = unstuff_bits(resp, 78, 1); + csd->read_misalign = unstuff_bits(resp, 77, 1); + csd->dsr_imp = unstuff_bits(resp, 76, 1); + csd->r2w_factor = unstuff_bits(resp, 26, 3); + csd->write_blkbits = unstuff_bits(resp, 22, 4); + csd->write_partial = unstuff_bits(resp, 21, 1); if (csd->write_blkbits >= 9) { - a = UNSTUFF_BITS(resp, 42, 5); - b = UNSTUFF_BITS(resp, 37, 5); + a = unstuff_bits(resp, 42, 5); + b = unstuff_bits(resp, 37, 5); csd->erase_size = (a + 1) * (b + 1); csd->erase_size <<= csd->write_blkbits - 9; + csd->wp_grp_size = unstuff_bits(resp, 32, 5); } return 0; @@ -300,7 +315,7 @@ static void mmc_manage_enhanced_area(struct mmc_card *card, u8 *ext_csd) } } -static void mmc_part_add(struct mmc_card *card, unsigned int size, +static void mmc_part_add(struct mmc_card *card, u64 size, unsigned int part_cfg, char *name, int idx, bool ro, int area_type) { @@ -316,7 +331,7 @@ static void mmc_manage_gp_partitions(struct mmc_card *card, u8 *ext_csd) { int idx; u8 hc_erase_grp_sz, hc_wp_grp_sz; - unsigned int part_size; + u64 part_size; /* * General purpose partition feature support -- @@ -346,8 +361,7 @@ static void mmc_manage_gp_partitions(struct mmc_card *card, u8 *ext_csd) (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] << 8) + ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3]; - part_size *= (size_t)(hc_erase_grp_sz * - hc_wp_grp_sz); + part_size *= (hc_erase_grp_sz * hc_wp_grp_sz); mmc_part_add(card, part_size << 19, EXT_CSD_PART_CONFIG_ACC_GP0 + idx, "gp%d", idx, false, @@ -365,7 +379,7 @@ static void mmc_manage_gp_partitions(struct mmc_card *card, u8 *ext_csd) static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) { int err = 0, idx; - unsigned int part_size; + u64 part_size; struct device_node *np; bool broken_hpi = false; @@ -414,23 +428,20 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) card->ext_csd.strobe_support = ext_csd[EXT_CSD_STROBE_SUPPORT]; card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; - mmc_select_card_type(card); card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.raw_erase_timeout_mult = ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.raw_hc_erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; + card->ext_csd.raw_boot_mult = + ext_csd[EXT_CSD_BOOT_MULT]; if (card->ext_csd.rev >= 3) { u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG]; /* EXT_CSD value is in units of 10ms, but we store in ms */ card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME]; - /* Some eMMC set the value too low so set a minimum */ - if (card->ext_csd.part_time && - card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME) - card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME; /* Sleep / awake timeout in 100ns units */ if (sa_shift > 0 && sa_shift <= 0x17) @@ -449,7 +460,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) * There are two boot regions of equal size, defined in * multiples of 128K. */ - if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_boot_partition_access(card->host)) { + if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_host_can_access_boot(card->host)) { for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) { part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; mmc_part_add(card, part_size, @@ -568,7 +579,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) * RPMB regions are defined in multiples of 128K. */ card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT]; - if (ext_csd[EXT_CSD_RPMB_MULT] && mmc_host_cmd23(card->host)) { + if (ext_csd[EXT_CSD_RPMB_MULT] && mmc_host_can_cmd23(card->host)) { mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17, EXT_CSD_PART_CONFIG_ACC_RPMB, "rpmb", 0, false, @@ -611,15 +622,21 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) } else { card->ext_csd.data_tag_unit_size = 0; } - - card->ext_csd.max_packed_writes = - ext_csd[EXT_CSD_MAX_PACKED_WRITES]; - card->ext_csd.max_packed_reads = - ext_csd[EXT_CSD_MAX_PACKED_READS]; } else { card->ext_csd.data_sector_size = 512; } + /* + * GENERIC_CMD6_TIME is to be used "unless a specific timeout is defined + * when accessing a specific field", so use it here if there is no + * PARTITION_SWITCH_TIME. + */ + if (!card->ext_csd.part_time) + card->ext_csd.part_time = card->ext_csd.generic_cmd6_time; + /* Some eMMC set the value too low so set a minimum */ + if (card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME) + card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME; + /* eMMC v5 or later */ if (card->ext_csd.rev >= 7) { memcpy(card->ext_csd.fwrev, &ext_csd[EXT_CSD_FIRMWARE_VERSION], @@ -651,6 +668,9 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) mmc_hostname(card->host), card->ext_csd.cmdq_depth); } + card->ext_csd.enhanced_rpmb_supported = + (card->ext_csd.rel_param & + EXT_CSD_WR_REL_PARAM_EN_RPMB_REL_WR); } out: return err; @@ -661,7 +681,7 @@ static int mmc_read_ext_csd(struct mmc_card *card) u8 *ext_csd; int err; - if (!mmc_can_ext_csd(card)) + if (!mmc_card_can_ext_csd(card)) return 0; err = mmc_get_ext_csd(card, &ext_csd); @@ -774,6 +794,7 @@ MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); +MMC_DEV_ATTR(wp_grp_size, "%u\n", card->wp_grp_size << 9); MMC_DEV_ATTR(ffu_capable, "%d\n", card->ext_csd.ffu_capable); MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); @@ -790,6 +811,8 @@ MMC_DEV_ATTR(enhanced_area_offset, "%llu\n", card->ext_csd.enhanced_area_offset); MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); +MMC_DEV_ATTR(enhanced_rpmb_supported, "%#x\n", + card->ext_csd.enhanced_rpmb_supported); MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); @@ -801,15 +824,14 @@ static ssize_t mmc_fwrev_show(struct device *dev, { struct mmc_card *card = mmc_dev_to_card(dev); - if (card->ext_csd.rev < 7) { - return sprintf(buf, "0x%x\n", card->cid.fwrev); - } else { - return sprintf(buf, "0x%*phN\n", MMC_FIRMWARE_LEN, - card->ext_csd.fwrev); - } + if (card->ext_csd.rev < 7) + return sysfs_emit(buf, "0x%x\n", card->cid.fwrev); + else + return sysfs_emit(buf, "0x%*phN\n", MMC_FIRMWARE_LEN, + card->ext_csd.fwrev); } -static DEVICE_ATTR(fwrev, S_IRUGO, mmc_fwrev_show, NULL); +static DEVICE_ATTR(fwrev, 0444, mmc_fwrev_show, NULL); static ssize_t mmc_dsr_show(struct device *dev, struct device_attribute *attr, @@ -819,13 +841,13 @@ static ssize_t mmc_dsr_show(struct device *dev, struct mmc_host *host = card->host; if (card->csd.dsr_imp && host->dsr_req) - return sprintf(buf, "0x%x\n", host->dsr); + return sysfs_emit(buf, "0x%x\n", host->dsr); else /* return default DSR value */ - return sprintf(buf, "0x%x\n", 0x404); + return sysfs_emit(buf, "0x%x\n", 0x404); } -static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL); +static DEVICE_ATTR(dsr, 0444, mmc_dsr_show, NULL); static struct attribute *mmc_std_attrs[] = { &dev_attr_cid.attr, @@ -833,6 +855,7 @@ static struct attribute *mmc_std_attrs[] = { &dev_attr_date.attr, &dev_attr_erase_size.attr, &dev_attr_preferred_erase_size.attr, + &dev_attr_wp_grp_size.attr, &dev_attr_fwrev.attr, &dev_attr_ffu_capable.attr, &dev_attr_hwrev.attr, @@ -847,6 +870,7 @@ static struct attribute *mmc_std_attrs[] = { &dev_attr_enhanced_area_offset.attr, &dev_attr_enhanced_area_size.attr, &dev_attr_raw_rpmb_size_mult.attr, + &dev_attr_enhanced_rpmb_supported.attr, &dev_attr_rel_sectors.attr, &dev_attr_ocr.attr, &dev_attr_rca.attr, @@ -856,7 +880,7 @@ static struct attribute *mmc_std_attrs[] = { }; ATTRIBUTE_GROUPS(mmc_std); -static struct device_type mmc_type = { +static const struct device_type mmc_type = { .groups = mmc_std_groups, }; @@ -936,7 +960,7 @@ static int mmc_select_powerclass(struct mmc_card *card) int err, ddr; /* Power class selection is supported for versions >= 4.0 */ - if (!mmc_can_ext_csd(card)) + if (!mmc_card_can_ext_csd(card)) return 0; bus_width = host->ios.bus_width; @@ -988,16 +1012,18 @@ static int mmc_select_bus_width(struct mmc_card *card) static unsigned ext_csd_bits[] = { EXT_CSD_BUS_WIDTH_8, EXT_CSD_BUS_WIDTH_4, + EXT_CSD_BUS_WIDTH_1, }; static unsigned bus_widths[] = { MMC_BUS_WIDTH_8, MMC_BUS_WIDTH_4, + MMC_BUS_WIDTH_1, }; struct mmc_host *host = card->host; unsigned idx, bus_width = 0; int err = 0; - if (!mmc_can_ext_csd(card) || + if (!mmc_card_can_ext_csd(card) || !(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) return 0; @@ -1059,7 +1085,7 @@ 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, MMC_TIMING_MMC_HS, - true, true, true); + true, true, MMC_CMD_RETRIES); if (err) pr_warn("%s: switch to high-speed failed, err:%d\n", mmc_hostname(card->host), err); @@ -1091,7 +1117,7 @@ static int mmc_select_hs_ddr(struct mmc_card *card) ext_csd_bits, card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_DDR52, - true, true, true); + true, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to bus width %d ddr failed\n", mmc_hostname(host), 1 << bus_width); @@ -1159,25 +1185,25 @@ static int mmc_select_hs400(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", mmc_hostname(host), err); return err; } - /* Set host controller to HS timing */ - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); - /* Prepare host to downgrade to HS timing */ if (host->ops->hs400_downgrade) host->ops->hs400_downgrade(host); + /* Set host controller to HS timing */ + mmc_set_timing(host, MMC_TIMING_MMC_HS); + /* Reduce frequency to HS frequency */ max_dtr = card->ext_csd.hs_max_dtr; mmc_set_clock(host, max_dtr); - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; @@ -1201,7 +1227,7 @@ static int mmc_select_hs400(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to hs400 failed, err:%d\n", mmc_hostname(host), err); @@ -1212,13 +1238,21 @@ static int mmc_select_hs400(struct mmc_card *card) mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_bus_speed(card); - err = mmc_switch_status(card); - if (err) - goto out_err; + if (host->ops->execute_hs400_tuning) { + mmc_retune_disable(host); + err = host->ops->execute_hs400_tuning(host, card); + mmc_retune_enable(host); + if (err) + goto out_err; + } if (host->ops->hs400_complete) host->ops->hs400_complete(host); + err = mmc_switch_status(card, true); + if (err) + goto out_err; + return 0; out_err: @@ -1247,29 +1281,29 @@ int mmc_hs400_to_hs200(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, 0, - true, false, true); + false, true, MMC_CMD_RETRIES); if (err) goto out_err; + if (host->ops->hs400_downgrade) + host->ops->hs400_downgrade(host); + mmc_set_timing(host, MMC_TIMING_MMC_DDR52); - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; /* 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, - 0, true, false, true); + 0, false, true, MMC_CMD_RETRIES); if (err) goto out_err; mmc_set_timing(host, MMC_TIMING_MMC_HS); - if (host->ops->hs400_downgrade) - host->ops->hs400_downgrade(host); - - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; @@ -1278,7 +1312,7 @@ int mmc_hs400_to_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, 0, - true, false, true); + false, true, MMC_CMD_RETRIES); if (err) goto out_err; @@ -1289,7 +1323,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card) * 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); + err = mmc_switch_status(card, false); if (err) goto out_err; @@ -1335,11 +1369,6 @@ static int mmc_select_hs400es(struct mmc_card *card) int err = -EINVAL; u8 val; - if (!(host->caps & MMC_CAP_8_BIT_DATA)) { - err = -ENOTSUPP; - goto out_err; - } - if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_2V) err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); @@ -1362,20 +1391,24 @@ static int mmc_select_hs400es(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, 0, - true, false, true); + false, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to hs for hs400es failed, err:%d\n", mmc_hostname(host), err); goto out_err; } + /* + * Bump to HS timing and frequency. Some cards don't handle + * SEND_STATUS reliably at the initial frequency. + */ mmc_set_timing(host, MMC_TIMING_MMC_HS); - err = mmc_switch_status(card); + mmc_set_bus_speed(card); + + err = mmc_switch_status(card, true); 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, @@ -1396,7 +1429,7 @@ static int mmc_select_hs400es(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to hs400es failed, err:%d\n", mmc_hostname(host), err); @@ -1411,7 +1444,7 @@ static int mmc_select_hs400es(struct mmc_card *card) if (host->ops->hs400_enhanced_strobe) host->ops->hs400_enhanced_strobe(host, &host->ios); - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err) goto out_err; @@ -1433,7 +1466,7 @@ out_err: static int mmc_select_hs200(struct mmc_card *card) { struct mmc_host *host = card->host; - unsigned int old_timing, old_signal_voltage; + unsigned int old_timing, old_signal_voltage, old_clock; int err = -EINVAL; u8 val; @@ -1461,25 +1494,36 @@ static int mmc_select_hs200(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); + false, true, MMC_CMD_RETRIES); if (err) goto err; + + /* + * Bump to HS timing and frequency. Some cards don't handle + * SEND_STATUS reliably at the initial frequency. + * NB: We can't move to full (HS200) speeds until after we've + * successfully switched over. + */ old_timing = host->ios.timing; + old_clock = host->ios.clock; mmc_set_timing(host, MMC_TIMING_MMC_HS200); + mmc_set_clock(card->host, card->ext_csd.hs_max_dtr); /* * 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); + err = mmc_switch_status(card, false); /* * mmc_select_timing() assumes timing has not changed if * it is a switch error. */ - if (err == -EBADMSG) + if (err == -EBADMSG) { + mmc_set_clock(host, old_clock); mmc_set_timing(host, old_timing); + } } err: if (err) { @@ -1500,16 +1544,26 @@ static int mmc_select_timing(struct mmc_card *card) { int err = 0; - if (!mmc_can_ext_csd(card)) + if (!mmc_card_can_ext_csd(card)) goto bus_speed; - if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400ES) + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400ES) { err = mmc_select_hs400es(card); - else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) + goto out; + } + + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) { err = mmc_select_hs200(card); - else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) + if (err == -EBADMSG) + card->mmc_avail_type &= ~EXT_CSD_CARD_TYPE_HS200; + else + goto out; + } + + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) err = mmc_select_hs(card); +out: if (err && err != -EBADMSG) return err; @@ -1594,6 +1648,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, if (oldcard) { if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { + pr_debug("%s: Perhaps the card was replaced\n", + mmc_hostname(host)); err = -ENOENT; goto err; } @@ -1683,6 +1739,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, mmc_set_erase_size(card); } + /* + * Reselect the card type since host caps could have been changed when + * debugging even if the card is not new. + */ + mmc_select_card_type(card); + /* Enable ERASE_GRP_DEF. This bit is lost after a reset or power off. */ if (card->ext_csd.rev >= 3) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, @@ -1693,7 +1755,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, goto free_card; if (err) { - err = 0; /* * Just disable enhanced area off & sz * will try to enable ERASE_GROUP_DEF @@ -1711,7 +1772,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, mmc_set_erase_size(card); } } - + mmc_set_wp_grp_size(card); /* * Ensure eMMC user default partition is enabled */ @@ -1743,6 +1804,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card->ext_csd.power_off_notification = EXT_CSD_POWER_ON; } + /* set erase_arg */ + if (mmc_card_can_discard(card)) + card->erase_arg = MMC_DISCARD_ARG; + else if (mmc_card_can_trim(card)) + card->erase_arg = MMC_TRIM_ARG; + else + card->erase_arg = MMC_ERASE_ARG; + /* * Select timing interface */ @@ -1751,14 +1820,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, goto free_card; if (mmc_card_hs200(card)) { + host->doing_init_tune = 1; + err = mmc_hs200_tuning(card); - if (err) - goto free_card; + if (!err) + err = mmc_select_hs400(card); + + host->doing_init_tune = 0; - err = mmc_select_hs400(card); if (err) goto free_card; - } else if (!mmc_card_hs400es(card)) { + } else if (mmc_card_hs400es(card)) { + if (host->ops->execute_hs400_tuning) { + err = host->ops->execute_hs400_tuning(host, card); + if (err) + goto free_card; + } + } else { /* Select the desired bus width optionally */ err = mmc_select_bus_width(card); if (err > 0 && mmc_card_hs(card)) { @@ -1786,7 +1864,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, pr_warn("%s: Enabling HPI failed\n", mmc_hostname(card->host)); card->ext_csd.hpi_en = 0; - err = 0; } else { card->ext_csd.hpi_en = 1; } @@ -1815,7 +1892,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, pr_warn("%s: Cache is supported, but failed to turn on (%d)\n", mmc_hostname(card->host), err); card->ext_csd.cache_ctrl = 0; - err = 0; } else { card->ext_csd.cache_ctrl = 1; } @@ -1835,7 +1911,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, mmc_hostname(card->host)); card->ext_csd.cmdq_support = false; card->ext_csd.cmdq_depth = 0; - err = 0; } } /* @@ -1845,15 +1920,19 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, */ card->reenable_cmdq = card->ext_csd.cmdq_en; - if (card->ext_csd.cmdq_en && !host->cqe_enabled) { + if (host->cqe_ops && !host->cqe_enabled) { err = host->cqe_ops->cqe_enable(host, card); - if (err) { - pr_err("%s: Failed to enable CQE, error %d\n", - mmc_hostname(host), err); - } else { + if (!err) { host->cqe_enabled = true; - pr_info("%s: Command Queue Engine enabled\n", - mmc_hostname(host)); + + if (card->ext_csd.cmdq_en) { + pr_info("%s: Command Queue Engine enabled\n", + mmc_hostname(host)); + } else { + host->hsq_enabled = true; + pr_info("%s: Host Software Queue enabled\n", + mmc_hostname(host)); + } } } @@ -1877,9 +1956,17 @@ err: return err; } -static int mmc_can_sleep(struct mmc_card *card) +static bool mmc_card_can_sleep(struct mmc_card *card) +{ + return card->ext_csd.rev >= 3; +} + +static int mmc_sleep_busy_cb(void *cb_data, bool *busy) { - return (card && card->ext_csd.rev >= 3); + struct mmc_host *host = cb_data; + + *busy = host->ops->card_busy(host); + return 0; } static int mmc_sleep(struct mmc_host *host) @@ -1887,6 +1974,7 @@ static int mmc_sleep(struct mmc_host *host) struct mmc_command cmd = {}; struct mmc_card *card = host->card; unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000); + bool use_r1b_resp; int err; /* Re-tuning can't be done once the card is deselected */ @@ -1899,45 +1987,53 @@ static int mmc_sleep(struct mmc_host *host) cmd.opcode = MMC_SLEEP_AWAKE; cmd.arg = card->rca << 16; cmd.arg |= 1 << 15; - - /* - * If the max_busy_timeout of the host is specified, validate it against - * the sleep cmd timeout. A failure means we need to prevent the host - * from doing hw busy detection, which is done by converting to a R1 - * response instead of a R1B. - */ - if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) { - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - } else { - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - cmd.busy_timeout = timeout_ms; - } + use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms); err = mmc_wait_for_cmd(host, &cmd, 0); if (err) goto out_release; /* - * If the host does not wait while the card signals busy, then we will - * will have to wait the sleep/awake timeout. Note, we cannot use the - * SEND_STATUS command to poll the status because that command (and most - * others) is invalid while the card sleeps. + * If the host does not wait while the card signals busy, then we can + * try to poll, but only if the host supports HW polling, as the + * SEND_STATUS cmd is not allowed. If we can't poll, then we simply need + * to wait the sleep/awake timeout. */ - if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) + if (host->caps & MMC_CAP_WAIT_WHILE_BUSY && use_r1b_resp) + goto out_release; + + if (!host->ops->card_busy) { mmc_delay(timeout_ms); + goto out_release; + } + + err = __mmc_poll_for_busy(host, 0, timeout_ms, &mmc_sleep_busy_cb, host); out_release: mmc_retune_release(host); return err; } -static int mmc_can_poweroff_notify(const struct mmc_card *card) +static bool mmc_card_can_poweroff_notify(const struct mmc_card *card) { return card && mmc_card_mmc(card) && (card->ext_csd.power_off_notification == EXT_CSD_POWER_ON); } +static bool mmc_host_can_poweroff_notify(const struct mmc_host *host, + enum mmc_poweroff_type pm_type) +{ + if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) + return true; + + if (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND && + pm_type == MMC_POWEROFF_SUSPEND) + return true; + + return pm_type == MMC_POWEROFF_SHUTDOWN; +} + static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) { unsigned int timeout = card->ext_csd.generic_cmd6_time; @@ -1949,7 +2045,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, 0, true, false, false); + notify_type, timeout, 0, false, false, MMC_CMD_RETRIES); if (err) pr_err("%s: Power Off Notification timed out, %u\n", mmc_hostname(card->host), timeout); @@ -1961,15 +2057,6 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) } /* - * Host is being removed. Free up the current card. - */ -static void mmc_remove(struct mmc_host *host) -{ - mmc_remove_card(host->card); - host->card = NULL; -} - -/* * Card detection - card is alive. */ static int mmc_alive(struct mmc_host *host) @@ -1994,7 +2081,8 @@ static void mmc_detect(struct mmc_host *host) mmc_put_card(host->card, NULL); if (err) { - mmc_remove(host); + mmc_remove_card(host->card); + host->card = NULL; mmc_claim_host(host); mmc_detach_bus(host); @@ -2003,25 +2091,62 @@ static void mmc_detect(struct mmc_host *host) } } -static int _mmc_suspend(struct mmc_host *host, bool is_suspend) +static bool _mmc_cache_enabled(struct mmc_host *host) +{ + return host->card->ext_csd.cache_size > 0 && + host->card->ext_csd.cache_ctrl & 1; +} + +/* + * Flush the internal cache of the eMMC to non-volatile storage. + */ +static int _mmc_flush_cache(struct mmc_host *host) +{ + int err = 0; + + if (mmc_card_broken_cache_flush(host->card) && !host->card->written_flag) + return 0; + + if (_mmc_cache_enabled(host)) { + err = mmc_switch(host->card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_FLUSH_CACHE, 1, + CACHE_FLUSH_TIMEOUT_MS); + if (err) + pr_err("%s: cache flush error %d\n", mmc_hostname(host), err); + else + host->card->written_flag = false; + } + + return err; +} + +static int _mmc_suspend(struct mmc_host *host, enum mmc_poweroff_type pm_type) { + unsigned int notify_type = EXT_CSD_POWER_OFF_SHORT; int err = 0; - unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT : - EXT_CSD_POWER_OFF_LONG; + + if (pm_type == MMC_POWEROFF_SHUTDOWN) + notify_type = EXT_CSD_POWER_OFF_LONG; mmc_claim_host(host); if (mmc_card_suspended(host->card)) goto out; - err = mmc_flush_cache(host->card); - if (err) - goto out; + /* + * For the undervoltage case, we care more about device integrity. + * Avoid cache flush and notify the device to power off quickly. + */ + if (pm_type != MMC_POWEROFF_UNDERVOLTAGE) { + err = _mmc_flush_cache(host); + if (err) + goto out; + } - if (mmc_can_poweroff_notify(host->card) && - ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend)) + if (mmc_card_can_poweroff_notify(host->card) && + mmc_host_can_poweroff_notify(host, pm_type)) err = mmc_poweroff_notify(host->card, notify_type); - else if (mmc_can_sleep(host->card)) + else if (mmc_card_can_sleep(host->card)) err = mmc_sleep(host); else if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); @@ -2036,13 +2161,27 @@ out: } /* + * Host is being removed. Free up the current card and do a graceful power-off. + */ +static void mmc_remove(struct mmc_host *host) +{ + get_device(&host->card->dev); + mmc_remove_card(host->card); + + _mmc_suspend(host, MMC_POWEROFF_UNBIND); + + put_device(&host->card->dev); + host->card = NULL; +} + +/* * Suspend callback */ static int mmc_suspend(struct mmc_host *host) { int err; - err = _mmc_suspend(host, true); + err = _mmc_suspend(host, MMC_POWEROFF_SUSPEND); if (!err) { pm_runtime_disable(&host->card->dev); pm_runtime_set_suspended(&host->card->dev); @@ -2081,15 +2220,23 @@ static int mmc_shutdown(struct mmc_host *host) int err = 0; /* - * In a specific case for poweroff notify, we need to resume the card - * before we can shutdown it properly. + * In case of undervoltage, the card will be powered off (removed) by + * _mmc_handle_undervoltage() + */ + if (mmc_card_removed(host->card)) + return 0; + + /* + * If the card remains suspended at this point and it was done by using + * the sleep-cmd (CMD5), we may need to re-initialize it first, to allow + * us to send the preferred poweroff-notification cmd at shutdown. */ - if (mmc_can_poweroff_notify(host->card) && - !(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE)) + if (mmc_card_can_poweroff_notify(host->card) && + !mmc_host_can_poweroff_notify(host, MMC_POWEROFF_SUSPEND)) err = _mmc_resume(host); if (!err) - err = _mmc_suspend(host, false); + err = _mmc_suspend(host, MMC_POWEROFF_SHUTDOWN); return err; } @@ -2113,7 +2260,7 @@ static int mmc_runtime_suspend(struct mmc_host *host) if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; - err = _mmc_suspend(host, true); + err = _mmc_suspend(host, MMC_POWEROFF_SUSPEND); if (err) pr_err("%s: error %d doing aggressive suspend\n", mmc_hostname(host), err); @@ -2136,14 +2283,12 @@ static int mmc_runtime_resume(struct mmc_host *host) return 0; } -static int mmc_can_reset(struct mmc_card *card) +static bool mmc_card_can_reset(struct mmc_card *card) { u8 rst_n_function; rst_n_function = card->ext_csd.rst_n_function; - if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED) - return 0; - return 1; + return ((rst_n_function & EXT_CSD_RST_N_EN_MASK) == EXT_CSD_RST_N_ENABLED); } static int _mmc_hw_reset(struct mmc_host *host) @@ -2154,13 +2299,13 @@ static int _mmc_hw_reset(struct mmc_host *host) * In the case of recovery, we can't expect flushing the cache to work * always, but we have a go and ignore errors. */ - mmc_flush_cache(host->card); + _mmc_flush_cache(host); - if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset && - mmc_can_reset(card)) { + if ((host->caps & MMC_CAP_HW_RESET) && host->ops->card_hw_reset && + mmc_card_can_reset(card)) { /* If the card accept RST_n signal, send it. */ mmc_set_clock(host, host->f_init); - host->ops->hw_reset(host); + host->ops->card_hw_reset(host); /* Set initial state and call mmc_set_ios */ mmc_set_initial_state(host); } else { @@ -2171,6 +2316,55 @@ static int _mmc_hw_reset(struct mmc_host *host) return mmc_init_card(host, card->ocr, card); } +/** + * _mmc_handle_undervoltage - Handle an undervoltage event for MMC/eMMC devices + * @host: MMC host structure + * + * This function is triggered when an undervoltage condition is detected. + * It attempts to transition the device into a low-power or safe state to + * prevent data corruption. + * + * Steps performed: + * - Perform an emergency suspend using EXT_CSD_POWER_OFF_SHORT if possible. + * - If power-off notify is not supported, fallback mechanisms like sleep or + * deselecting the card are attempted. + * - Cache flushing is skipped to reduce execution time. + * - Mark the card as removed to prevent further interactions after + * undervoltage. + * + * Note: This function does not handle host claiming or releasing. The caller + * must ensure that the host is properly claimed before calling this + * function and released afterward. + * + * Returns: 0 on success, or a negative error code if any step fails. + */ +static int _mmc_handle_undervoltage(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + int err; + + /* + * Perform an emergency suspend to power off the eMMC quickly. + * This ensures the device enters a safe state before power is lost. + * We first attempt EXT_CSD_POWER_OFF_SHORT, but if power-off notify + * is not supported, we fall back to sleep mode or deselecting the card. + * Cache flushing is skipped to minimize delay. + */ + err = _mmc_suspend(host, MMC_POWEROFF_UNDERVOLTAGE); + if (err) + pr_err("%s: undervoltage suspend failed: %pe\n", + mmc_hostname(host), ERR_PTR(err)); + + /* + * Mark the card as removed to prevent further operations. + * This ensures the system does not attempt to access the device + * after an undervoltage event, avoiding potential corruption. + */ + mmc_card_set_removed(card); + + return err; +} + static const struct mmc_bus_ops mmc_ops = { .remove = mmc_remove, .detect = mmc_detect, @@ -2181,6 +2375,9 @@ static const struct mmc_bus_ops mmc_ops = { .alive = mmc_alive, .shutdown = mmc_shutdown, .hw_reset = _mmc_hw_reset, + .cache_enabled = _mmc_cache_enabled, + .flush_cache = _mmc_flush_cache, + .handle_undervoltage = _mmc_handle_undervoltage, }; /* diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 9054329fe903..a952cc8265af 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/mmc/core/mmc_ops.h * * Copyright 2006-2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #include <linux/slab.h> @@ -23,7 +19,10 @@ #include "host.h" #include "mmc_ops.h" -#define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ +#define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */ +#define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */ +#define MMC_OP_COND_PERIOD_US (4 * 1000) /* 4ms */ +#define MMC_OP_COND_TIMEOUT_MS 1000 /* 1s */ static const u8 tuning_blk_pattern_4bit[] = { 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, @@ -55,6 +54,18 @@ static const u8 tuning_blk_pattern_8bit[] = { 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, }; +struct mmc_busy_data { + struct mmc_card *card; + bool retry_crc_err; + enum mmc_busy_cmd busy_cmd; +}; + +struct mmc_op_cond_busy_data { + struct mmc_host *host; + u32 ocr; + struct mmc_command *cmd; +}; + int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries) { int err; @@ -133,10 +144,24 @@ int mmc_set_dsr(struct mmc_host *host) return mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); } +int __mmc_go_idle(struct mmc_host *host) +{ + struct mmc_command cmd = {}; + int err; + + cmd.opcode = MMC_GO_IDLE_STATE; + cmd.arg = 0; + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC; + + err = mmc_wait_for_cmd(host, &cmd, 0); + mmc_delay(1); + + return err; +} + int mmc_go_idle(struct mmc_host *host) { int err; - struct mmc_command cmd = {}; /* * Non-SPI hosts need to prevent chipselect going active during @@ -152,13 +177,7 @@ int mmc_go_idle(struct mmc_host *host) mmc_delay(1); } - cmd.opcode = MMC_GO_IDLE_STATE; - cmd.arg = 0; - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC; - - err = mmc_wait_for_cmd(host, &cmd, 0); - - mmc_delay(1); + err = __mmc_go_idle(host); if (!mmc_host_is_spi(host)) { mmc_set_chip_select(host, MMC_CS_DONTCARE); @@ -170,37 +189,64 @@ int mmc_go_idle(struct mmc_host *host) return err; } +static int __mmc_send_op_cond_cb(void *cb_data, bool *busy) +{ + struct mmc_op_cond_busy_data *data = cb_data; + struct mmc_host *host = data->host; + struct mmc_command *cmd = data->cmd; + u32 ocr = data->ocr; + int err = 0; + + err = mmc_wait_for_cmd(host, cmd, 0); + if (err) + return err; + + if (mmc_host_is_spi(host)) { + if (!(cmd->resp[0] & R1_SPI_IDLE)) { + *busy = false; + return 0; + } + } else { + if (cmd->resp[0] & MMC_CARD_BUSY) { + *busy = false; + return 0; + } + } + + *busy = true; + + /* + * According to eMMC specification v5.1 section 6.4.3, we + * should issue CMD1 repeatedly in the idle state until + * the eMMC is ready. Otherwise some eMMC devices seem to enter + * the inactive mode after mmc_init_card() issued CMD0 when + * the eMMC device is busy. + */ + if (!ocr && !mmc_host_is_spi(host)) + cmd->arg = cmd->resp[0] | BIT(30); + + return 0; +} + int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) { struct mmc_command cmd = {}; - int i, err = 0; + int err = 0; + struct mmc_op_cond_busy_data cb_data = { + .host = host, + .ocr = ocr, + .cmd = &cmd + }; 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; - for (i = 100; i; i--) { - err = mmc_wait_for_cmd(host, &cmd, 0); - if (err) - break; - - /* if we're just probing, do a single pass */ - if (ocr == 0) - break; - - /* otherwise wait until reset completes */ - if (mmc_host_is_spi(host)) { - if (!(cmd.resp[0] & R1_SPI_IDLE)) - break; - } else { - if (cmd.resp[0] & MMC_CARD_BUSY) - break; - } - - err = -ETIMEDOUT; - - mmc_delay(10); - } + err = __mmc_poll_for_busy(host, MMC_OP_COND_PERIOD_US, + MMC_OP_COND_TIMEOUT_MS, + &__mmc_send_op_cond_cb, &cb_data); + if (err) + return err; if (rocr && !mmc_host_is_spi(host)) *rocr = cmd.resp[0]; @@ -242,9 +288,8 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) * NOTE: void *buf, caller for the buf is required to use DMA-capable * buffer or on-stack buffer (with some overhead in callee). */ -static int -mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, - u32 opcode, void *buf, unsigned len) +int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode, + u32 args, void *buf, unsigned len) { struct mmc_request mrq = {}; struct mmc_command cmd = {}; @@ -255,7 +300,7 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, mrq.data = &data; cmd.opcode = opcode; - cmd.arg = 0; + cmd.arg = args; /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we * rely on callers to never use this with "native" calls for reading @@ -292,61 +337,40 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, return 0; } -static int mmc_spi_send_csd(struct mmc_card *card, u32 *csd) +static int mmc_spi_send_cxd(struct mmc_host *host, u32 *cxd, u32 opcode) { int ret, i; - __be32 *csd_tmp; + __be32 *cxd_tmp; - csd_tmp = kzalloc(16, GFP_KERNEL); - if (!csd_tmp) + cxd_tmp = kzalloc(16, GFP_KERNEL); + if (!cxd_tmp) return -ENOMEM; - ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd_tmp, 16); + ret = mmc_send_adtc_data(NULL, host, opcode, 0, cxd_tmp, 16); if (ret) goto err; for (i = 0; i < 4; i++) - csd[i] = be32_to_cpu(csd_tmp[i]); + cxd[i] = be32_to_cpu(cxd_tmp[i]); err: - kfree(csd_tmp); + kfree(cxd_tmp); return ret; } int mmc_send_csd(struct mmc_card *card, u32 *csd) { if (mmc_host_is_spi(card->host)) - return mmc_spi_send_csd(card, csd); + return mmc_spi_send_cxd(card->host, csd, MMC_SEND_CSD); return mmc_send_cxd_native(card->host, card->rca << 16, csd, MMC_SEND_CSD); } -static int mmc_spi_send_cid(struct mmc_host *host, u32 *cid) -{ - int ret, i; - __be32 *cid_tmp; - - cid_tmp = kzalloc(16, GFP_KERNEL); - if (!cid_tmp) - return -ENOMEM; - - ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid_tmp, 16); - if (ret) - goto err; - - for (i = 0; i < 4; i++) - cid[i] = be32_to_cpu(cid_tmp[i]); - -err: - kfree(cid_tmp); - return ret; -} - int mmc_send_cid(struct mmc_host *host, u32 *cid) { if (mmc_host_is_spi(host)) - return mmc_spi_send_cid(host, cid); + return mmc_spi_send_cxd(host, cid, MMC_SEND_CID); return mmc_send_cxd_native(host, 0, cid, MMC_ALL_SEND_CID); } @@ -359,7 +383,7 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) if (!card || !new_ext_csd) return -EINVAL; - if (!mmc_can_ext_csd(card)) + if (!mmc_card_can_ext_csd(card)) return -EOPNOTSUPP; /* @@ -370,7 +394,7 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) if (!ext_csd) return -ENOMEM; - err = mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, ext_csd, + err = mmc_send_adtc_data(card, card->host, MMC_SEND_EXT_CSD, 0, ext_csd, 512); if (err) kfree(ext_csd); @@ -427,7 +451,7 @@ static int mmc_switch_status_error(struct mmc_host *host, u32 status) } /* Caller must hold re-tuning */ -int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) +int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) { u32 status; int err; @@ -441,35 +465,59 @@ int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) return mmc_switch_status_error(card->host, status); } -int mmc_switch_status(struct mmc_card *card) +static int mmc_busy_cb(void *cb_data, bool *busy) { - return __mmc_switch_status(card, true); + struct mmc_busy_data *data = cb_data; + struct mmc_host *host = data->card->host; + u32 status = 0; + int err; + + if (data->busy_cmd != MMC_BUSY_IO && host->ops->card_busy) { + *busy = host->ops->card_busy(host); + return 0; + } + + err = mmc_send_status(data->card, &status); + if (data->retry_crc_err && err == -EILSEQ) { + *busy = true; + return 0; + } + if (err) + return err; + + switch (data->busy_cmd) { + case MMC_BUSY_CMD6: + err = mmc_switch_status_error(host, status); + break; + case MMC_BUSY_ERASE: + err = R1_STATUS(status) ? -EIO : 0; + break; + case MMC_BUSY_HPI: + case MMC_BUSY_EXTR_SINGLE: + case MMC_BUSY_IO: + break; + default: + err = -EINVAL; + } + + if (err) + return err; + + *busy = !mmc_ready_for_data(status); + return 0; } -static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - bool send_status, bool retry_crc_err) +int __mmc_poll_for_busy(struct mmc_host *host, unsigned int period_us, + unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data) { - struct mmc_host *host = card->host; int err; unsigned long timeout; - u32 status = 0; + unsigned int udelay = period_us ? period_us : 32, udelay_max = 32768; 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 { /* @@ -478,21 +526,9 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, */ 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; - } - } + err = (*busy_cb)(cb_data, &busy); + if (err) + return err; /* Timeout if the device still remains busy. */ if (expired && busy) { @@ -500,10 +536,54 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, mmc_hostname(host), __func__); return -ETIMEDOUT; } + + /* Throttle the polling rate to avoid hogging the CPU. */ + if (busy) { + usleep_range(udelay, udelay * 2); + if (udelay < udelay_max) + udelay *= 2; + } } while (busy); 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) +{ + struct mmc_host *host = card->host; + struct mmc_busy_data cb_data; + + cb_data.card = card; + cb_data.retry_crc_err = retry_crc_err; + cb_data.busy_cmd = busy_cmd; + + return __mmc_poll_for_busy(host, 0, 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) +{ + /* + * If the max_busy_timeout of the host is specified, make sure it's + * enough to fit the used timeout_ms. In case it's not, let's instruct + * the host to avoid HW busy detection, by converting to a R1 response + * instead of a R1B. Note, some hosts requires R1B, which also means + * they are on their own when it comes to deal with the busy timeout. + */ + if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout && + (timeout_ms > host->max_busy_timeout)) { + cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1 | MMC_RSP_R1; + return false; + } + + cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1B | MMC_RSP_R1B; + cmd->busy_timeout = timeout_ms; + return true; +} +EXPORT_SYMBOL_GPL(mmc_prepare_busy_cmd); /** * __mmc_switch - modify EXT_CSD register @@ -514,69 +594,58 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, * @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 * @retry_crc_err: retry when CRC errors when polling with CMD13 for busy + * @retries: number of retries * * 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, unsigned char timing, - bool use_busy_signal, bool send_status, bool retry_crc_err) + bool send_status, bool retry_crc_err, unsigned int retries) { struct mmc_host *host = card->host; int err; struct mmc_command cmd = {}; - bool use_r1b_resp = use_busy_signal; + bool use_r1b_resp; unsigned char old_timing = host->ios.timing; mmc_retune_hold(host); - /* - * If the cmd timeout and the max_busy_timeout of the host are both - * specified, let's validate them. A failure means we need to prevent - * the host from doing hw busy detection, which is done by converting - * to a R1 response instead of a R1B. - */ - if (timeout_ms && host->max_busy_timeout && - (timeout_ms > host->max_busy_timeout)) - use_r1b_resp = false; + if (!timeout_ms) { + pr_warn("%s: unspecified timeout for CMD6 - use generic\n", + mmc_hostname(host)); + timeout_ms = card->ext_csd.generic_cmd6_time; + } cmd.opcode = MMC_SWITCH; cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8) | set; - cmd.flags = MMC_CMD_AC; - if (use_r1b_resp) { - cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; - /* - * A busy_timeout of zero means the host can decide to use - * whatever value it finds suitable. - */ - cmd.busy_timeout = timeout_ms; - } else { - cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; - } + use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms); - if (index == EXT_CSD_SANITIZE_START) - cmd.sanitize_busy = true; - - err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + err = mmc_wait_for_cmd(host, &cmd, retries); if (err) goto out; - /* No need to check card status in case of unblocking command */ - if (!use_busy_signal) - 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)) goto out_tim; + /* + * If the host doesn't support HW polling via the ->card_busy() ops and + * when it's not allowed to poll by using CMD13, then we need to rely on + * waiting the stated timeout to be sufficient. + */ + if (!send_status && !host->ops->card_busy) { + mmc_delay(timeout_ms); + goto out_tim; + } + /* 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_poll_for_busy(card, timeout_ms, retry_crc_err, MMC_BUSY_CMD6); if (err) goto out; @@ -586,7 +655,7 @@ out_tim: mmc_set_timing(host, timing); if (send_status) { - err = mmc_switch_status(card); + err = mmc_switch_status(card, true); if (err && timing) mmc_set_timing(host, old_timing); } @@ -600,7 +669,7 @@ 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, 0, - true, true, false); + true, false, MMC_CMD_RETRIES); } EXPORT_SYMBOL_GPL(mmc_switch); @@ -673,7 +742,7 @@ out: } EXPORT_SYMBOL_GPL(mmc_send_tuning); -int mmc_abort_tuning(struct mmc_host *host, u32 opcode) +int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode) { struct mmc_command cmd = {}; @@ -696,7 +765,7 @@ int mmc_abort_tuning(struct mmc_host *host, u32 opcode) return mmc_wait_for_cmd(host, &cmd, 0); } -EXPORT_SYMBOL_GPL(mmc_abort_tuning); +EXPORT_SYMBOL_GPL(mmc_send_abort_tuning); static int mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, @@ -796,32 +865,35 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width) return mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width); } -static int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) +static int mmc_send_hpi_cmd(struct mmc_card *card) { + unsigned int busy_timeout_ms = card->ext_csd.out_of_int_time; + struct mmc_host *host = card->host; + bool use_r1b_resp = false; struct mmc_command cmd = {}; - unsigned int opcode; int err; - opcode = card->ext_csd.hpi_cmd; - if (opcode == MMC_STOP_TRANSMISSION) - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - else if (opcode == MMC_SEND_STATUS) - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - - cmd.opcode = opcode; + cmd.opcode = card->ext_csd.hpi_cmd; cmd.arg = card->rca << 16 | 1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - err = mmc_wait_for_cmd(card->host, &cmd, 0); + if (cmd.opcode == MMC_STOP_TRANSMISSION) + use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, + busy_timeout_ms); + + err = mmc_wait_for_cmd(host, &cmd, 0); if (err) { - pr_warn("%s: error %d interrupting operation. " - "HPI command response %#x\n", mmc_hostname(card->host), - err, cmd.resp[0]); + pr_warn("%s: HPI error %d. Command response %#x\n", + mmc_hostname(host), err, cmd.resp[0]); return err; } - if (status) - *status = cmd.resp[0]; - return 0; + /* No need to poll when using HW busy detection. */ + if (host->caps & MMC_CAP_WAIT_WHILE_BUSY && use_r1b_resp) + return 0; + + /* Let's poll to find out when the HPI request completes. */ + return mmc_poll_for_busy(card, busy_timeout_ms, false, MMC_BUSY_HPI); } /** @@ -831,11 +903,10 @@ static int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) * Issued High Priority Interrupt, and check for card status * until out-of prg-state. */ -int mmc_interrupt_hpi(struct mmc_card *card) +static int mmc_interrupt_hpi(struct mmc_card *card) { int err; u32 status; - unsigned long prg_wait; if (!card->ext_csd.hpi_en) { pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host)); @@ -868,25 +939,12 @@ int mmc_interrupt_hpi(struct mmc_card *card) goto out; } - err = mmc_send_hpi_cmd(card, &status); - if (err) - goto out; - - prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time); - do { - err = mmc_send_status(card, &status); - - if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN) - break; - if (time_after(jiffies, prg_wait)) - err = -ETIMEDOUT; - } while (!err); - + err = mmc_send_hpi_cmd(card); out: return err; } -int mmc_can_ext_csd(struct mmc_card *card) +bool mmc_card_can_ext_csd(struct mmc_card *card) { return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3); } @@ -939,36 +997,22 @@ void mmc_run_bkops(struct mmc_card *card) * 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", + EXT_CSD_BKOPS_START, 1, MMC_BKOPS_TIMEOUT_MS); + /* + * 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); } EXPORT_SYMBOL(mmc_run_bkops); -/* - * Flush the cache to the non-volatile storage. - */ -int mmc_flush_cache(struct mmc_card *card) -{ - int err = 0; - - if (mmc_card_mmc(card) && - (card->ext_csd.cache_size > 0) && - (card->ext_csd.cache_ctrl & 1)) { - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_FLUSH_CACHE, 1, 0); - if (err) - pr_err("%s: cache flush error %d\n", - mmc_hostname(card->host), err); - } - - return err; -} -EXPORT_SYMBOL(mmc_flush_cache); - static int mmc_cmdq_switch(struct mmc_card *card, bool enable) { u8 val = enable ? EXT_CSD_CMDQ_MODE_ENABLED : 0; @@ -996,3 +1040,112 @@ int mmc_cmdq_disable(struct mmc_card *card) return mmc_cmdq_switch(card, false); } EXPORT_SYMBOL_GPL(mmc_cmdq_disable); + +int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms) +{ + struct mmc_host *host = card->host; + int err; + + if (!mmc_card_can_sanitize(card)) { + pr_warn("%s: Sanitize not supported\n", mmc_hostname(host)); + return -EOPNOTSUPP; + } + + if (!timeout_ms) + timeout_ms = MMC_SANITIZE_TIMEOUT_MS; + + pr_debug("%s: Sanitize in progress...\n", mmc_hostname(host)); + + mmc_retune_hold(host); + + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_SANITIZE_START, + 1, timeout_ms, 0, true, false, 0); + if (err) + pr_err("%s: Sanitize failed err=%d\n", mmc_hostname(host), err); + + /* + * If the sanitize operation 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: Sanitize aborted\n", mmc_hostname(host)); + + mmc_retune_release(host); + + pr_debug("%s: Sanitize completed\n", mmc_hostname(host)); + return err; +} +EXPORT_SYMBOL_GPL(mmc_sanitize); + +/** + * mmc_read_tuning() - read data blocks from the mmc + * @host: mmc host doing the read + * @blksz: data block size + * @blocks: number of blocks to read + * + * Read one or more blocks of data from the beginning of the mmc. This is a + * low-level helper for tuning operation. It is assumed that CMD23 can be used + * for multi-block read if the host supports it. + * + * Note: Allocate and free a temporary buffer to store the data read. The data + * is not available outside of the function, only the status of the read + * operation. + * + * Return: 0 in case of success, otherwise -EIO / -ENOMEM / -E2BIG + */ +int mmc_read_tuning(struct mmc_host *host, unsigned int blksz, unsigned int blocks) +{ + struct mmc_request mrq = {}; + struct mmc_command sbc = {}; + struct mmc_command cmd = {}; + struct mmc_command stop = {}; + struct mmc_data data = {}; + struct scatterlist sg; + void *buf; + unsigned int len; + + if (blocks > 1) { + if (mmc_host_can_cmd23(host)) { + mrq.sbc = &sbc; + sbc.opcode = MMC_SET_BLOCK_COUNT; + sbc.arg = blocks; + sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; + } + cmd.opcode = MMC_READ_MULTIPLE_BLOCK; + mrq.stop = &stop; + stop.opcode = MMC_STOP_TRANSMISSION; + stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + } else { + cmd.opcode = MMC_READ_SINGLE_BLOCK; + } + + mrq.cmd = &cmd; + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + + mrq.data = &data; + data.flags = MMC_DATA_READ; + data.blksz = blksz; + data.blocks = blocks; + data.blk_addr = 0; + data.sg = &sg; + data.sg_len = 1; + data.timeout_ns = 1000000000; + + if (check_mul_overflow(blksz, blocks, &len)) + return -E2BIG; + buf = kmalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + sg_init_one(&sg, buf, len); + + mmc_wait_for_req(host, &mrq); + kfree(buf); + + if (sbc.error || cmd.error || data.error) + return -EIO; + + return 0; +} +EXPORT_SYMBOL_GPL(mmc_read_tuning); diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 018a5e3f66d6..514c40ff4b4e 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -1,12 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * linux/drivers/mmc/core/mmc_ops.h * * Copyright 2006-2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #ifndef _MMC_MMC_OPS_H @@ -14,36 +10,66 @@ #include <linux/types.h> +enum mmc_busy_cmd { + MMC_BUSY_CMD6, + MMC_BUSY_ERASE, + MMC_BUSY_HPI, + MMC_BUSY_EXTR_SINGLE, + MMC_BUSY_IO, +}; + struct mmc_host; struct mmc_card; +struct mmc_command; int mmc_select_card(struct mmc_card *card); int mmc_deselect_cards(struct mmc_host *host); int mmc_set_dsr(struct mmc_host *host); +int __mmc_go_idle(struct mmc_host *host); int mmc_go_idle(struct mmc_host *host); int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int mmc_set_relative_addr(struct mmc_card *card); +int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode, + u32 args, void *buf, unsigned len); int mmc_send_csd(struct mmc_card *card, u32 *csd); int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries); -int mmc_send_status(struct mmc_card *card, u32 *status); int mmc_send_cid(struct mmc_host *host, u32 *cid); int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); 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_interrupt_hpi(struct mmc_card *card); -int mmc_can_ext_csd(struct mmc_card *card); -int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); -int mmc_switch_status(struct mmc_card *card); -int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); +bool mmc_card_can_ext_csd(struct mmc_card *card); +int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); +bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, + unsigned int timeout_ms); +int __mmc_poll_for_busy(struct mmc_host *host, unsigned int period_us, + unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data); +int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + bool retry_crc_err, enum mmc_busy_cmd busy_cmd); int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms, unsigned char timing, - bool use_busy_signal, bool send_status, bool retry_crc_err); + bool send_status, bool retry_crc_err, unsigned int retries); int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms); 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); +int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms); + +static inline u32 unstuff_bits(const u32 *resp, int start, int size) +{ + const int __size = size; + const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; + const int __off = 3 - (start / 32); + const int __shft = start & 31; + u32 __res = resp[__off] >> __shft; + + if (__size + __shft > 32) + __res |= resp[__off - 1] << ((32 - __shft) % 32); + + return __res & __mask; +} #endif diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c index eabb1cab1765..01d1e62c2ce7 100644 --- a/drivers/mmc/core/mmc_test.c +++ b/drivers/mmc/core/mmc_test.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 2007-2008 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #include <linux/mmc/core.h> @@ -14,7 +10,6 @@ #include <linux/slab.h> #include <linux/scatterlist.h> -#include <linux/swap.h> /* For nr_free_buffer_pages() */ #include <linux/list.h> #include <linux/debugfs.h> @@ -75,6 +70,7 @@ struct mmc_test_mem { * @sg_len: length of currently mapped scatterlist @sg * @mem: allocated memory * @sg: scatterlist + * @sg_areq: scatterlist for non-blocking request */ struct mmc_test_area { unsigned long max_sz; @@ -86,6 +82,7 @@ struct mmc_test_area { unsigned int sg_len; struct mmc_test_mem *mem; struct scatterlist *sg; + struct scatterlist *sg_areq; }; /** @@ -183,20 +180,14 @@ static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) return mmc_set_blocklen(test->card, size); } -static bool mmc_test_card_cmd23(struct mmc_card *card) -{ - return mmc_card_mmc(card) || - (mmc_card_sd(card) && card->scr.cmds & SD_SCR_CMD23_SUPPORT); -} - static void mmc_test_prepare_sbc(struct mmc_test_card *test, struct mmc_request *mrq, unsigned int blocks) { struct mmc_card *card = test->card; - if (!mrq->sbc || !mmc_host_cmd23(card->host) || - !mmc_test_card_cmd23(card) || !mmc_op_multi(mrq->cmd->opcode) || - (card->quirks & MMC_QUIRK_BLK_NO_CMD23)) { + if (!mrq->sbc || !mmc_host_can_cmd23(card->host) || + !mmc_card_can_cmd23(card) || !mmc_op_multi(mrq->cmd->opcode) || + mmc_card_blk_no_cmd23(card)) { mrq->sbc = NULL; return; } @@ -595,14 +586,11 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes, rate = mmc_test_rate(tot, &ts); iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */ - pr_info("%s: Transfer of %u x %u sectors (%u x %u%s KiB) took " - "%llu.%09u seconds (%u kB/s, %u KiB/s, " - "%u.%02u IOPS, sg_len %d)\n", - mmc_hostname(test->card->host), count, sectors, count, - sectors >> 1, (sectors & 1 ? ".5" : ""), - (u64)ts.tv_sec, (u32)ts.tv_nsec, - rate / 1000, rate / 1024, iops / 100, iops % 100, - test->area.sg_len); + pr_info("%s: Transfer of %u x %u sectors (%u x %u%s KiB) took %ptSp seconds (%u kB/s, %u KiB/s, %u.%02u IOPS, sg_len %d)\n", + mmc_hostname(test->card->host), count, sectors, count, + sectors >> 1, (sectors & 1 ? ".5" : ""), &ts, + rate / 1000, rate / 1024, iops / 100, iops % 100, + test->area.sg_len); mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops); } @@ -626,7 +614,7 @@ static unsigned int mmc_test_capacity(struct mmc_card *card) * Fill the first couple of sectors of the card with known data * so that bad reads/writes can be detected */ -static int __mmc_test_prepare(struct mmc_test_card *test, int write) +static int __mmc_test_prepare(struct mmc_test_card *test, int write, int val) { int ret, i; @@ -635,7 +623,7 @@ static int __mmc_test_prepare(struct mmc_test_card *test, int write) return ret; if (write) - memset(test->buffer, 0xDF, 512); + memset(test->buffer, val, 512); else { for (i = 0; i < 512; i++) test->buffer[i] = i; @@ -652,31 +640,17 @@ static int __mmc_test_prepare(struct mmc_test_card *test, int write) static int mmc_test_prepare_write(struct mmc_test_card *test) { - return __mmc_test_prepare(test, 1); + return __mmc_test_prepare(test, 1, 0xDF); } static int mmc_test_prepare_read(struct mmc_test_card *test) { - return __mmc_test_prepare(test, 0); + return __mmc_test_prepare(test, 0, 0); } static int mmc_test_cleanup(struct mmc_test_card *test) { - int ret, i; - - ret = mmc_test_set_blksize(test, 512); - if (ret) - return ret; - - memset(test->buffer, 0, 512); - - for (i = 0; i < BUFFER_SIZE / 512; i++) { - ret = mmc_test_buffer_transfer(test, test->buffer, i, 512, 1); - if (ret) - return ret; - } - - return 0; + return __mmc_test_prepare(test, 1, 0); } /*******************************************************************/ @@ -840,14 +814,16 @@ static int mmc_test_start_areq(struct mmc_test_card *test, } static int mmc_test_nonblock_transfer(struct mmc_test_card *test, - struct scatterlist *sg, unsigned sg_len, - unsigned dev_addr, unsigned blocks, - unsigned blksz, int write, int count) + unsigned int dev_addr, int write, + int count) { struct mmc_test_req *rq1, *rq2; struct mmc_request *mrq, *prev_mrq; int i; int ret = RESULT_OK; + struct mmc_test_area *t = &test->area; + struct scatterlist *sg = t->sg; + struct scatterlist *sg_areq = t->sg_areq; rq1 = mmc_test_req_alloc(); rq2 = mmc_test_req_alloc(); @@ -861,8 +837,8 @@ static int mmc_test_nonblock_transfer(struct mmc_test_card *test, for (i = 0; i < count; i++) { mmc_test_req_reset(container_of(mrq, struct mmc_test_req, mrq)); - mmc_test_prepare_mrq(test, mrq, sg, sg_len, dev_addr, blocks, - blksz, write); + mmc_test_prepare_mrq(test, mrq, sg, t->sg_len, dev_addr, + t->blocks, 512, write); ret = mmc_test_start_areq(test, mrq, prev_mrq); if (ret) goto err; @@ -871,7 +847,8 @@ static int mmc_test_nonblock_transfer(struct mmc_test_card *test, prev_mrq = &rq2->mrq; swap(mrq, prev_mrq); - dev_addr += blocks; + swap(sg, sg_areq); + dev_addr += t->blocks; } ret = mmc_test_start_areq(test, NULL, prev_mrq); @@ -946,7 +923,6 @@ static int mmc_test_transfer(struct mmc_test_card *test, unsigned blocks, unsigned blksz, int write) { int ret, i; - unsigned long flags; if (write) { for (i = 0; i < blocks * blksz; i++) @@ -954,9 +930,7 @@ static int mmc_test_transfer(struct mmc_test_card *test, } else { memset(test->scratch, 0, BUFFER_SIZE); } - local_irq_save(flags); sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); - local_irq_restore(flags); ret = mmc_test_set_blksize(test, blksz); if (ret) @@ -1001,9 +975,7 @@ static int mmc_test_transfer(struct mmc_test_card *test, return RESULT_FAIL; } } else { - local_irq_save(flags); sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); - local_irq_restore(flags); for (i = 0; i < blocks * blksz; i++) { if (test->scratch[i] != (u8)i) return RESULT_FAIL; @@ -1400,10 +1372,11 @@ static int mmc_test_no_highmem(struct mmc_test_card *test) * Map sz bytes so that it can be transferred. */ static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz, - int max_scatter, int min_sg_len) + int max_scatter, int min_sg_len, bool nonblock) { struct mmc_test_area *t = &test->area; int err; + unsigned int sg_len = 0; t->blocks = sz >> 9; @@ -1415,6 +1388,22 @@ static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz, err = mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs, t->max_seg_sz, &t->sg_len, min_sg_len); } + + if (err || !nonblock) + goto err; + + if (max_scatter) { + err = mmc_test_map_sg_max_scatter(t->mem, sz, t->sg_areq, + t->max_segs, t->max_seg_sz, + &sg_len); + } else { + err = mmc_test_map_sg(t->mem, sz, t->sg_areq, 1, t->max_segs, + t->max_seg_sz, &sg_len, min_sg_len); + } + if (!err && sg_len != t->sg_len) + err = -EINVAL; + +err: if (err) pr_info("%s: Failed to map sg list\n", mmc_hostname(test->card->host)); @@ -1444,7 +1433,6 @@ static int mmc_test_area_io_seq(struct mmc_test_card *test, unsigned long sz, struct timespec64 ts1, ts2; int ret = 0; int i; - struct mmc_test_area *t = &test->area; /* * In the case of a maximally scattered transfer, the maximum transfer @@ -1462,15 +1450,14 @@ static int mmc_test_area_io_seq(struct mmc_test_card *test, unsigned long sz, sz = max_tfr; } - ret = mmc_test_area_map(test, sz, max_scatter, min_sg_len); + ret = mmc_test_area_map(test, sz, max_scatter, min_sg_len, nonblock); if (ret) return ret; if (timed) ktime_get_ts64(&ts1); if (nonblock) - ret = mmc_test_nonblock_transfer(test, t->sg, t->sg_len, - dev_addr, t->blocks, 512, write, count); + ret = mmc_test_nonblock_transfer(test, dev_addr, write, count); else for (i = 0; i < count && ret == 0; i++) { ret = mmc_test_area_transfer(test, dev_addr, write); @@ -1514,7 +1501,7 @@ static int mmc_test_area_erase(struct mmc_test_card *test) { struct mmc_test_area *t = &test->area; - if (!mmc_can_erase(test->card)) + if (!mmc_card_can_erase(test->card)) return 0; return mmc_erase(test->card, t->dev_addr, t->max_sz >> 9, @@ -1529,6 +1516,7 @@ static int mmc_test_area_cleanup(struct mmc_test_card *test) struct mmc_test_area *t = &test->area; kfree(t->sg); + kfree(t->sg_areq); mmc_test_free_mem(t->mem); return 0; @@ -1588,6 +1576,13 @@ static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill) goto out_free; } + t->sg_areq = kmalloc_array(t->max_segs, sizeof(*t->sg_areq), + GFP_KERNEL); + if (!t->sg_areq) { + ret = -ENOMEM; + goto out_free; + } + t->dev_addr = mmc_test_capacity(test->card) / 2; t->dev_addr -= t->dev_addr % (t->max_sz >> 9); @@ -1742,10 +1737,10 @@ static int mmc_test_profile_trim_perf(struct mmc_test_card *test) struct timespec64 ts1, ts2; int ret; - if (!mmc_can_trim(test->card)) + if (!mmc_card_can_trim(test->card)) return RESULT_UNSUP_CARD; - if (!mmc_can_erase(test->card)) + if (!mmc_card_can_erase(test->card)) return RESULT_UNSUP_HOST; for (sz = 512; sz < t->max_sz; sz <<= 1) { @@ -1859,10 +1854,10 @@ static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test) struct timespec64 ts1, ts2; int ret; - if (!mmc_can_trim(test->card)) + if (!mmc_card_can_trim(test->card)) return RESULT_UNSUP_CARD; - if (!mmc_can_erase(test->card)) + if (!mmc_card_can_erase(test->card)) return RESULT_UNSUP_HOST; for (sz = 512; sz <= t->max_sz; sz <<= 1) { @@ -1900,7 +1895,7 @@ static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt) } static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print, - unsigned long sz) + unsigned long sz, int secs, int force_retuning) { unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea; unsigned int ssz; @@ -1917,7 +1912,7 @@ static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print, for (cnt = 0; cnt < UINT_MAX; cnt++) { ktime_get_ts64(&ts2); ts = timespec64_sub(ts2, ts1); - if (ts.tv_sec >= 10) + if (ts.tv_sec >= secs) break; ea = mmc_test_rnd_num(range1); if (ea == last_ea) @@ -1925,6 +1920,8 @@ static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print, last_ea = ea; dev_addr = rnd_addr + test->card->pref_erase * ea + ssz * mmc_test_rnd_num(range2); + if (force_retuning) + mmc_retune_needed(test->card->host); ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0); if (ret) return ret; @@ -1949,24 +1946,35 @@ static int mmc_test_random_perf(struct mmc_test_card *test, int write) */ if (write) { next = rnd_next; - ret = mmc_test_rnd_perf(test, write, 0, sz); + ret = mmc_test_rnd_perf(test, write, 0, sz, 10, 0); if (ret) return ret; rnd_next = next; } - ret = mmc_test_rnd_perf(test, write, 1, sz); + ret = mmc_test_rnd_perf(test, write, 1, sz, 10, 0); if (ret) return ret; } sz = t->max_tfr; if (write) { next = rnd_next; - ret = mmc_test_rnd_perf(test, write, 0, sz); + ret = mmc_test_rnd_perf(test, write, 0, sz, 10, 0); if (ret) return ret; rnd_next = next; } - return mmc_test_rnd_perf(test, write, 1, sz); + return mmc_test_rnd_perf(test, write, 1, sz, 10, 0); +} + +static int mmc_test_retuning(struct mmc_test_card *test) +{ + if (!mmc_can_retune(test->card->host)) { + pr_info("%s: No retuning - test skipped\n", + mmc_hostname(test->card->host)); + return RESULT_UNSUP_HOST; + } + + return mmc_test_rnd_perf(test, 0, 0, 8192, 30, 1); } /* @@ -2097,10 +2105,10 @@ static int mmc_test_rw_multiple(struct mmc_test_card *test, return 0; /* prepare test area */ - if (mmc_can_erase(test->card) && + if (mmc_card_can_erase(test->card) && tdata->prepare & MMC_TEST_PREP_ERASE) { ret = mmc_erase(test->card, dev_addr, - size / 512, MMC_SECURE_ERASE_ARG); + size / 512, test->card->erase_arg); if (ret) ret = mmc_erase(test->card, dev_addr, size / 512, MMC_ERASE_ARG); @@ -2316,10 +2324,9 @@ static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test) static int mmc_test_reset(struct mmc_test_card *test) { struct mmc_card *card = test->card; - struct mmc_host *host = card->host; int err; - err = mmc_hw_reset(host); + err = mmc_hw_reset(card); if (!err) { /* * Reset will re-enable the card's command queue, but tests @@ -2374,7 +2381,7 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test, 512, write); if (use_sbc && t->blocks > 1 && !mrq->sbc) { - ret = mmc_host_cmd23(host) ? + ret = mmc_host_can_cmd23(host) ? RESULT_UNSUP_CARD : RESULT_UNSUP_HOST; goto out_free; @@ -2472,7 +2479,7 @@ static int __mmc_test_cmds_during_tfr(struct mmc_test_card *test, if (!(test->card->host->caps & MMC_CAP_CMD_DURING_TFR)) return RESULT_UNSUP_HOST; - ret = mmc_test_area_map(test, sz, 0, 0); + ret = mmc_test_area_map(test, sz, 0, 0, use_areq); if (ret) return ret; @@ -2645,22 +2652,22 @@ static const struct mmc_test_case mmc_test_cases[] = { }, { - .name = "Correct xfer_size at write (start failure)", + .name = "Proper xfer_size at write (start failure)", .run = mmc_test_xfersize_write, }, { - .name = "Correct xfer_size at read (start failure)", + .name = "Proper xfer_size at read (start failure)", .run = mmc_test_xfersize_read, }, { - .name = "Correct xfer_size at write (midway failure)", + .name = "Proper xfer_size at write (midway failure)", .run = mmc_test_multi_xfersize_write, }, { - .name = "Correct xfer_size at read (midway failure)", + .name = "Proper xfer_size at read (midway failure)", .run = mmc_test_multi_xfersize_read, }, @@ -2918,6 +2925,14 @@ static const struct mmc_test_case mmc_test_cases[] = { .run = mmc_test_cmds_during_write_cmd23_nonblock, .cleanup = mmc_test_area_cleanup, }, + + { + .name = "Re-tuning reliability", + .prepare = mmc_test_area_prepare, + .run = mmc_test_retuning, + .cleanup = mmc_test_area_cleanup, + }, + }; static DEFINE_MUTEX(mmc_test_lock); @@ -3042,7 +3057,7 @@ static LIST_HEAD(mmc_test_file_test); static int mtf_test_show(struct seq_file *sf, void *data) { - struct mmc_card *card = (struct mmc_card *)sf->private; + struct mmc_card *card = sf->private; struct mmc_test_general_result *gr; mutex_lock(&mmc_test_lock); @@ -3056,10 +3071,9 @@ static int mtf_test_show(struct seq_file *sf, void *data) seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result); list_for_each_entry(tr, &gr->tr_lst, link) { - seq_printf(sf, "%u %d %llu.%09u %u %u.%02u\n", - tr->count, tr->sectors, - (u64)tr->ts.tv_sec, (u32)tr->ts.tv_nsec, - tr->rate, tr->iops / 100, tr->iops % 100); + seq_printf(sf, "%u %d %ptSp %u %u.%02u\n", + tr->count, tr->sectors, &tr->ts, tr->rate, + tr->iops / 100, tr->iops % 100); } } @@ -3076,8 +3090,8 @@ static int mtf_test_open(struct inode *inode, struct file *file) static ssize_t mtf_test_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { - struct seq_file *sf = (struct seq_file *)file->private_data; - struct mmc_card *card = (struct mmc_card *)sf->private; + struct seq_file *sf = file->private_data; + struct mmc_card *card = sf->private; struct mmc_test_card *test; long testcase; int ret; @@ -3101,13 +3115,13 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf, test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL); #ifdef CONFIG_HIGHMEM test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER); + if (!test->highmem) { + count = -ENOMEM; + goto free_test_buffer; + } #endif -#ifdef CONFIG_HIGHMEM - if (test->buffer && test->highmem) { -#else if (test->buffer) { -#endif mutex_lock(&mmc_test_lock); mmc_test_run(test, testcase); mutex_unlock(&mmc_test_lock); @@ -3115,6 +3129,7 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf, #ifdef CONFIG_HIGHMEM __free_pages(test->highmem, BUFFER_ORDER); +free_test_buffer: #endif kfree(test->buffer); kfree(test); @@ -3172,14 +3187,7 @@ static int __mmc_test_register_dbgfs_file(struct mmc_card *card, if (card->debugfs_root) file = debugfs_create_file(name, mode, card->debugfs_root, - card, fops); - - if (IS_ERR_OR_NULL(file)) { - dev_err(&card->dev, - "Can't create %s. Perhaps debugfs is disabled.\n", - name); - return -ENODEV; - } + card, fops); df = kmalloc(sizeof(*df), GFP_KERNEL); if (!df) { @@ -3200,12 +3208,12 @@ static int mmc_test_register_dbgfs_file(struct mmc_card *card) mutex_lock(&mmc_test_lock); - ret = __mmc_test_register_dbgfs_file(card, "test", S_IWUSR | S_IRUGO, + ret = __mmc_test_register_dbgfs_file(card, "test", 0644, &mmc_test_fops_test); if (ret) goto err; - ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO, + ret = __mmc_test_register_dbgfs_file(card, "testlist", 0444, &mtf_testlist_fops); if (ret) goto err; @@ -3223,6 +3231,12 @@ static int mmc_test_probe(struct mmc_card *card) if (!mmc_card_mmc(card) && !mmc_card_sd(card)) return -ENODEV; + if (mmc_card_ult_capacity(card)) { + pr_info("%s: mmc-test currently UNSUPPORTED for SDUC\n", + mmc_hostname(card->host)); + return -EOPNOTSUPP; + } + ret = mmc_test_register_dbgfs_file(card); if (ret) return ret; @@ -3251,17 +3265,12 @@ static void mmc_test_remove(struct mmc_card *card) mmc_test_free_dbgfs_file(card); } -static void mmc_test_shutdown(struct mmc_card *card) -{ -} - static struct mmc_driver mmc_driver = { .drv = { .name = "mmc_test", }, .probe = mmc_test_probe, .remove = mmc_test_remove, - .shutdown = mmc_test_shutdown, }; static int __init mmc_test_init(void) diff --git a/drivers/mmc/core/pwrseq.c b/drivers/mmc/core/pwrseq.c index e3ad30fa8307..2374669b588a 100644 --- a/drivers/mmc/core/pwrseq.c +++ b/drivers/mmc/core/pwrseq.c @@ -1,10 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2014 Linaro Ltd * * Author: Ulf Hansson <ulf.hansson@linaro.org> * - * License terms: GNU General Public License (GPL) version 2 - * * MMC power sequence management */ #include <linux/kernel.h> @@ -30,7 +29,7 @@ int mmc_pwrseq_alloc(struct mmc_host *host) mutex_lock(&pwrseq_list_mutex); list_for_each_entry(p, &pwrseq_list, pwrseq_node) { - if (p->dev->of_node == np) { + if (device_match_of_node(p->dev, np)) { if (!try_module_get(p->owner)) dev_err(host->parent, "increasing module refcount failed\n"); diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h index 819386f4ec61..f3bb103db9ad 100644 --- a/drivers/mmc/core/pwrseq.h +++ b/drivers/mmc/core/pwrseq.h @@ -1,9 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2014 Linaro Ltd * * Author: Ulf Hansson <ulf.hansson@linaro.org> - * - * License terms: GNU General Public License (GPL) version 2 */ #ifndef _MMC_CORE_PWRSEQ_H #define _MMC_CORE_PWRSEQ_H diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c index efb8a7965dd4..35af67e26945 100644 --- a/drivers/mmc/core/pwrseq_emmc.c +++ b/drivers/mmc/core/pwrseq_emmc.c @@ -1,10 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2015, Samsung Electronics Co., Ltd. * * Author: Marek Szyprowski <m.szyprowski@samsung.com> * - * License terms: GNU General Public License (GPL) version 2 - * * Simple eMMC hardware reset provider */ #include <linux/delay.h> @@ -30,19 +29,14 @@ struct mmc_pwrseq_emmc { #define to_pwrseq_emmc(p) container_of(p, struct mmc_pwrseq_emmc, pwrseq) -static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq) -{ - gpiod_set_value(pwrseq->reset_gpio, 1); - udelay(1); - gpiod_set_value(pwrseq->reset_gpio, 0); - udelay(200); -} - static void mmc_pwrseq_emmc_reset(struct mmc_host *host) { struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); - __mmc_pwrseq_emmc_reset(pwrseq); + gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); + udelay(1); + gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); + udelay(200); } static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, @@ -50,8 +44,11 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, { struct mmc_pwrseq_emmc *pwrseq = container_of(this, struct mmc_pwrseq_emmc, reset_nb); + gpiod_set_value(pwrseq->reset_gpio, 1); + udelay(1); + gpiod_set_value(pwrseq->reset_gpio, 0); + udelay(200); - __mmc_pwrseq_emmc_reset(pwrseq); return NOTIFY_DONE; } @@ -72,14 +69,18 @@ static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) if (IS_ERR(pwrseq->reset_gpio)) return PTR_ERR(pwrseq->reset_gpio); - /* - * register reset handler to ensure emmc reset also from - * emergency_reboot(), priority 255 is the highest priority - * so it will be executed before any system reboot handler. - */ - pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; - pwrseq->reset_nb.priority = 255; - register_restart_handler(&pwrseq->reset_nb); + if (!gpiod_cansleep(pwrseq->reset_gpio)) { + /* + * register reset handler to ensure emmc reset also from + * emergency_reboot(), priority 255 is the highest priority + * so it will be executed before any system reboot handler. + */ + pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; + pwrseq->reset_nb.priority = 255; + register_restart_handler(&pwrseq->reset_nb); + } else { + dev_notice(dev, "EMMC reset pin tied to a sleepy GPIO driver; reset on emergency-reboot disabled\n"); + } pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; pwrseq->pwrseq.dev = dev; @@ -89,14 +90,12 @@ static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) return mmc_pwrseq_register(&pwrseq->pwrseq); } -static int mmc_pwrseq_emmc_remove(struct platform_device *pdev) +static void mmc_pwrseq_emmc_remove(struct platform_device *pdev) { struct mmc_pwrseq_emmc *pwrseq = platform_get_drvdata(pdev); unregister_restart_handler(&pwrseq->reset_nb); mmc_pwrseq_unregister(&pwrseq->pwrseq); - - return 0; } static const struct of_device_id mmc_pwrseq_emmc_of_match[] = { @@ -116,4 +115,5 @@ static struct platform_driver mmc_pwrseq_emmc_driver = { }; module_platform_driver(mmc_pwrseq_emmc_driver); +MODULE_DESCRIPTION("Hardware reset support for eMMC"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/core/pwrseq_sd8787.c b/drivers/mmc/core/pwrseq_sd8787.c index 1a21e14458d3..30282155a0e1 100644 --- a/drivers/mmc/core/pwrseq_sd8787.c +++ b/drivers/mmc/core/pwrseq_sd8787.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * pwrseq_sd8787.c - power sequence support for Marvell SD8787 BT + Wifi chip * @@ -6,17 +7,6 @@ * Based on the original work pwrseq_simple.c * Copyright (C) 2014 Linaro Ltd * Author: Ulf Hansson <ulf.hansson@linaro.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <linux/delay.h> @@ -24,6 +14,7 @@ #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/slab.h> #include <linux/device.h> #include <linux/err.h> @@ -59,13 +50,37 @@ static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host) gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); } +static void mmc_pwrseq_wilc1000_pre_power_on(struct mmc_host *host) +{ + struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq); + + /* The pwrdn_gpio is really CHIP_EN, reset_gpio is RESETN */ + gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1); + msleep(5); + gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); +} + +static void mmc_pwrseq_wilc1000_power_off(struct mmc_host *host) +{ + struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq); + + gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); + gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0); +} + static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = { .pre_power_on = mmc_pwrseq_sd8787_pre_power_on, .power_off = mmc_pwrseq_sd8787_power_off, }; +static const struct mmc_pwrseq_ops mmc_pwrseq_wilc1000_ops = { + .pre_power_on = mmc_pwrseq_wilc1000_pre_power_on, + .power_off = mmc_pwrseq_wilc1000_power_off, +}; + static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = { - { .compatible = "mmc-pwrseq-sd8787",}, + { .compatible = "mmc-pwrseq-sd8787", .data = &mmc_pwrseq_sd8787_ops }, + { .compatible = "mmc-pwrseq-wilc1000", .data = &mmc_pwrseq_wilc1000_ops }, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match); @@ -74,11 +89,14 @@ 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->pwrdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW); if (IS_ERR(pwrseq->pwrdn_gpio)) return PTR_ERR(pwrseq->pwrdn_gpio); @@ -88,20 +106,18 @@ static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev) return PTR_ERR(pwrseq->reset_gpio); pwrseq->pwrseq.dev = dev; - pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops; + pwrseq->pwrseq.ops = match->data; pwrseq->pwrseq.owner = THIS_MODULE; platform_set_drvdata(pdev, pwrseq); return mmc_pwrseq_register(&pwrseq->pwrseq); } -static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev) +static void mmc_pwrseq_sd8787_remove(struct platform_device *pdev) { struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev); mmc_pwrseq_unregister(&pwrseq->pwrseq); - - return 0; } static struct platform_driver mmc_pwrseq_sd8787_driver = { @@ -114,4 +130,5 @@ static struct platform_driver mmc_pwrseq_sd8787_driver = { }; module_platform_driver(mmc_pwrseq_sd8787_driver); +MODULE_DESCRIPTION("Power sequence support for Marvell SD8787 BT + Wifi chip"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c index ece34c734693..4b47e6c3b04b 100644 --- a/drivers/mmc/core/pwrseq_simple.c +++ b/drivers/mmc/core/pwrseq_simple.c @@ -1,10 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2014 Linaro Ltd * * Author: Ulf Hansson <ulf.hansson@linaro.org> * - * License terms: GNU General Public License (GPL) version 2 - * * Simple MMC power sequence management */ #include <linux/clk.h> @@ -18,6 +17,8 @@ #include <linux/gpio/consumer.h> #include <linux/delay.h> #include <linux/property.h> +#include <linux/of.h> +#include <linux/reset.h> #include <linux/mmc/host.h> @@ -30,6 +31,7 @@ struct mmc_pwrseq_simple { u32 power_off_delay_us; struct clk *ext_clk; struct gpio_descs *reset_gpios; + struct reset_control *reset_ctrl; }; #define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq) @@ -52,10 +54,9 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, else bitmap_zero(values, nvalues); - gpiod_set_array_value_cansleep(nvalues, reset_gpios->desc, - reset_gpios->info, values); + gpiod_multi_set_value_cansleep(reset_gpios, values); - kfree(values); + bitmap_free(values); } } @@ -68,14 +69,21 @@ static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) pwrseq->clk_enabled = true; } - mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); + if (pwrseq->reset_ctrl) { + reset_control_deassert(pwrseq->reset_ctrl); + reset_control_assert(pwrseq->reset_ctrl); + } else + mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); } static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host) { struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); - mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); + if (pwrseq->reset_ctrl) + reset_control_deassert(pwrseq->reset_ctrl); + else + mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); if (pwrseq->post_power_on_delay_ms) msleep(pwrseq->post_power_on_delay_ms); @@ -85,7 +93,10 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host) { struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); - mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); + if (pwrseq->reset_ctrl) + reset_control_assert(pwrseq->reset_ctrl); + else + mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); if (pwrseq->power_off_delay_us) usleep_range(pwrseq->power_off_delay_us, @@ -113,6 +124,7 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev) { struct mmc_pwrseq_simple *pwrseq; struct device *dev = &pdev->dev; + int ngpio; pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); if (!pwrseq) @@ -120,14 +132,28 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev) pwrseq->ext_clk = devm_clk_get(dev, "ext_clock"); if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT) - return PTR_ERR(pwrseq->ext_clk); - - pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", - GPIOD_OUT_HIGH); - if (IS_ERR(pwrseq->reset_gpios) && - PTR_ERR(pwrseq->reset_gpios) != -ENOENT && - PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) { - return PTR_ERR(pwrseq->reset_gpios); + return dev_err_probe(dev, PTR_ERR(pwrseq->ext_clk), "external clock not ready\n"); + + ngpio = of_count_phandle_with_args(dev->of_node, "reset-gpios", "#gpio-cells"); + if (ngpio == 1) { + pwrseq->reset_ctrl = devm_reset_control_get_optional_shared(dev, NULL); + if (IS_ERR(pwrseq->reset_ctrl)) + return dev_err_probe(dev, PTR_ERR(pwrseq->reset_ctrl), + "reset control not ready\n"); + } + + /* + * Fallback to GPIO based reset control in case of multiple reset lines + * are specified or the platform doesn't have support for RESET at all. + */ + if (!pwrseq->reset_ctrl) { + pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(pwrseq->reset_gpios) && + PTR_ERR(pwrseq->reset_gpios) != -ENOENT && + PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) { + return dev_err_probe(dev, PTR_ERR(pwrseq->reset_gpios), + "reset GPIOs not ready\n"); + } } device_property_read_u32(dev, "post-power-on-delay-ms", @@ -143,13 +169,11 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev) return mmc_pwrseq_register(&pwrseq->pwrseq); } -static int mmc_pwrseq_simple_remove(struct platform_device *pdev) +static void mmc_pwrseq_simple_remove(struct platform_device *pdev) { struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev); mmc_pwrseq_unregister(&pwrseq->pwrseq); - - return 0; } static struct platform_driver mmc_pwrseq_simple_driver = { @@ -162,4 +186,5 @@ static struct platform_driver mmc_pwrseq_simple_driver = { }; module_platform_driver(mmc_pwrseq_simple_driver); +MODULE_DESCRIPTION("Simple power sequence management for MMC"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 35cc138b096d..284856c8f655 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -1,19 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2003 Russell King, All Rights Reserved. * Copyright 2006-2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include <linux/slab.h> #include <linux/module.h> #include <linux/blkdev.h> #include <linux/freezer.h> -#include <linux/kthread.h> #include <linux/scatterlist.h> #include <linux/dma-mapping.h> +#include <linux/backing-dev.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> @@ -22,8 +18,11 @@ #include "block.h" #include "core.h" #include "card.h" +#include "crypto.h" #include "host.h" +#define MMC_DMA_MAP_MERGE_SEGMENTS 512 + static inline bool mmc_cqe_dcmd_busy(struct mmc_queue *mq) { /* Allow only 1 DCMD at a time */ @@ -34,8 +33,6 @@ void mmc_cqe_check_busy(struct mmc_queue *mq) { if ((mq->cqe_busy & MMC_CQE_DCMD_BUSY) && !mmc_cqe_dcmd_busy(mq)) mq->cqe_busy &= ~MMC_CQE_DCMD_BUSY; - - mq->cqe_busy &= ~MMC_CQE_QUEUE_FULL; } static inline bool mmc_cqe_can_dcmd(struct mmc_host *host) @@ -51,6 +48,7 @@ static enum mmc_issue_type mmc_cqe_issue_type(struct mmc_host *host, case REQ_OP_DRV_OUT: case REQ_OP_DISCARD: case REQ_OP_SECURE_ERASE: + case REQ_OP_WRITE_ZEROES: return MMC_ISSUE_SYNC; case REQ_OP_FLUSH: return mmc_cqe_can_dcmd(host) ? MMC_ISSUE_DCMD : MMC_ISSUE_SYNC; @@ -63,7 +61,7 @@ enum mmc_issue_type mmc_issue_type(struct mmc_queue *mq, struct request *req) { struct mmc_host *host = mq->card->host; - if (mq->use_cqe) + if (host->cqe_enabled && !host->hsq_enabled) return mmc_cqe_issue_type(host, req); if (req_op(req) == REQ_OP_READ || req_op(req) == REQ_OP_WRITE) @@ -108,11 +106,10 @@ static enum blk_eh_timer_return mmc_cqe_timed_out(struct request *req) case MMC_ISSUE_DCMD: if (host->cqe_ops->cqe_timeout(host, mrq, &recovery_needed)) { if (recovery_needed) - __mmc_cqe_recovery_notifier(mq); + mmc_cqe_recovery_notifier(mrq); return BLK_EH_RESET_TIMER; } - /* No timeout (XXX: huh? comment doesn't make much sense) */ - blk_mq_complete_request(req); + /* The request has gone already */ return BLK_EH_DONE; default: /* Timeout is handled by mmc core */ @@ -120,24 +117,20 @@ static enum blk_eh_timer_return mmc_cqe_timed_out(struct request *req) } } -static enum blk_eh_timer_return mmc_mq_timed_out(struct request *req, - bool reserved) +static enum blk_eh_timer_return mmc_mq_timed_out(struct request *req) { struct request_queue *q = req->q; struct mmc_queue *mq = q->queuedata; + struct mmc_card *card = mq->card; + struct mmc_host *host = card->host; unsigned long flags; - int ret; + bool ignore_tout; spin_lock_irqsave(&mq->lock, flags); - - if (mq->recovery_needed || !mq->use_cqe) - ret = BLK_EH_RESET_TIMER; - else - ret = mmc_cqe_timed_out(req); - + ignore_tout = mq->recovery_needed || !host->cqe_enabled || host->hsq_enabled; spin_unlock_irqrestore(&mq->lock, flags); - return ret; + return ignore_tout ? BLK_EH_RESET_TIMER : mmc_cqe_timed_out(req); } static void mmc_mq_recovery_handler(struct work_struct *work) @@ -145,12 +138,13 @@ static void mmc_mq_recovery_handler(struct work_struct *work) struct mmc_queue *mq = container_of(work, struct mmc_queue, recovery_work); struct request_queue *q = mq->queue; + struct mmc_host *host = mq->card->host; mmc_get_card(mq->card, &mq->ctx); mq->in_recovery = true; - if (mq->use_cqe) + if (host->cqe_enabled && !host->hsq_enabled) mmc_blk_cqe_recovery(mq); else mmc_blk_mq_recovery(mq); @@ -161,12 +155,15 @@ static void mmc_mq_recovery_handler(struct work_struct *work) mq->recovery_needed = false; spin_unlock_irq(&mq->lock); + if (host->hsq_enabled) + host->cqe_ops->cqe_recovery_finish(host); + mmc_put_card(mq->card, &mq->ctx); 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; @@ -177,8 +174,8 @@ static struct scatterlist *mmc_alloc_sg(int sg_len, gfp_t gfp) return sg; } -static void mmc_queue_setup_discard(struct request_queue *q, - struct mmc_card *card) +static void mmc_queue_setup_discard(struct mmc_card *card, + struct queue_limits *lim) { unsigned max_discard; @@ -186,37 +183,42 @@ static void mmc_queue_setup_discard(struct request_queue *q, if (!max_discard) return; - blk_queue_flag_set(QUEUE_FLAG_DISCARD, q); - blk_queue_max_discard_sectors(q, max_discard); - q->limits.discard_granularity = card->pref_erase << 9; + lim->max_hw_discard_sectors = max_discard; + if (mmc_card_can_secure_erase_trim(card)) + lim->max_secure_erase_sectors = max_discard; + if (mmc_card_can_trim(card) && card->erased_byte == 0) + lim->max_write_zeroes_sectors = max_discard; + /* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) - q->limits.discard_granularity = 0; - if (mmc_can_secure_erase_trim(card)) - blk_queue_flag_set(QUEUE_FLAG_SECERASE, q); + lim->discard_granularity = SECTOR_SIZE; + else + lim->discard_granularity = card->pref_erase << 9; } -/** - * mmc_init_request() - initialize the MMC-specific per-request data - * @q: 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 unsigned short mmc_get_max_segments(struct mmc_host *host) +{ + return host->can_dma_map_merge ? MMC_DMA_MAP_MERGE_SEGMENTS : + host->max_segs; +} + +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(host->max_segs, 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); @@ -224,20 +226,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) { @@ -249,7 +237,7 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, enum mmc_issue_type issue_type; enum mmc_issued issued; bool get_card, cqe_retune_ok; - int ret; + blk_status_t ret; if (mmc_card_removed(mq->card)) { req->rq_flags |= RQF_QUIET; @@ -274,6 +262,10 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, } break; case MMC_ISSUE_ASYNC: + if (host->hsq_enabled && mq->in_flight[issue_type] > host->hsq_depth) { + spin_unlock_irq(&mq->lock); + return BLK_STS_RESOURCE; + } break; default: /* @@ -304,7 +296,7 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, if (get_card) mmc_get_card(card, &mq->ctx); - if (mq->use_cqe) { + if (host->cqe_enabled) { host->retune_now = host->need_retune && cqe_retune_ok && !host->hold_retune; } @@ -351,24 +343,53 @@ static const struct blk_mq_ops mmc_mq_ops = { .timeout = mmc_mq_timed_out, }; -static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card) +static struct gendisk *mmc_alloc_disk(struct mmc_queue *mq, + struct mmc_card *card, unsigned int features) { struct mmc_host *host = card->host; - u64 limit = BLK_BOUNCE_HIGH; + struct queue_limits lim = { + .features = features, + }; + struct gendisk *disk; + + if (mmc_card_can_erase(card)) + mmc_queue_setup_discard(card, &lim); + + lim.max_hw_sectors = min(host->max_blk_count, host->max_req_size / 512); + + if (mmc_card_mmc(card) && card->ext_csd.data_sector_size) + lim.logical_block_size = card->ext_csd.data_sector_size; + else + lim.logical_block_size = 512; + + WARN_ON_ONCE(lim.logical_block_size != 512 && + lim.logical_block_size != 4096); - if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) - limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; + /* + * Setting a virt_boundary implicity sets a max_segment_size, so try + * to set the hardware one here. + */ + if (host->can_dma_map_merge) { + lim.virt_boundary_mask = dma_get_merge_boundary(mmc_dev(host)); + lim.max_segments = MMC_DMA_MAP_MERGE_SEGMENTS; + } else { + lim.max_segment_size = + round_down(host->max_seg_size, lim.logical_block_size); + lim.max_segments = host->max_segs; + } - blk_queue_flag_set(QUEUE_FLAG_NONROT, mq->queue); - blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, mq->queue); - if (mmc_can_erase(card)) - mmc_queue_setup_discard(mq->queue, card); + if (mmc_host_is_spi(host) && host->use_spi_crc) + lim.features |= BLK_FEAT_STABLE_WRITES; - blk_queue_bounce_limit(mq->queue, limit); - blk_queue_max_hw_sectors(mq->queue, - min(host->max_blk_count, host->max_req_size / 512)); - blk_queue_max_segments(mq->queue, host->max_segs); - blk_queue_max_segment_size(mq->queue, host->max_seg_size); + disk = blk_mq_alloc_disk(&mq->tag_set, &lim, mq); + if (IS_ERR(disk)) + return disk; + mq->queue = disk->queue; + + blk_queue_rq_timeout(mq->queue, 60 * HZ); + + if (mmc_dev(host)->dma_parms) + dma_set_max_seg_size(mmc_dev(host), queue_max_segment_size(mq->queue)); INIT_WORK(&mq->recovery_work, mmc_mq_recovery_handler); INIT_WORK(&mq->complete_work, mmc_blk_mq_complete_work); @@ -376,6 +397,14 @@ static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card) mutex_init(&mq->complete_lock); init_waitqueue_head(&mq->wait); + + mmc_crypto_setup_queue(mq->queue, host); + return disk; +} + +static inline bool mmc_merge_capable(struct mmc_host *host) +{ + return host->caps2 & MMC_CAP2_MERGE_CAPABLE; } /* Set queue depth to get a reasonable value for q->nr_requests */ @@ -385,16 +414,18 @@ static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card) * mmc_init_queue - initialise a queue structure. * @mq: mmc queue * @card: mmc card to attach this queue + * @features: block layer features (BLK_FEAT_*) * * Initialise a MMC card request queue. */ -int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card) +struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, + unsigned int features) { struct mmc_host *host = card->host; + struct gendisk *disk; int ret; mq->card = card; - mq->use_cqe = host->cqe_enabled; spin_lock_init(&mq->lock); @@ -404,37 +435,38 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card) * The queue depth for CQE must match the hardware because the request * tag is used to index the hardware queue. */ - if (mq->use_cqe) + if (host->cqe_enabled && !host->hsq_enabled) mq->tag_set.queue_depth = min_t(int, card->ext_csd.cmdq_depth, host->cqe_qdepth); else mq->tag_set.queue_depth = MMC_QUEUE_DEPTH; mq->tag_set.numa_node = NUMA_NO_NODE; - mq->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE | - BLK_MQ_F_BLOCKING; + mq->tag_set.flags = BLK_MQ_F_BLOCKING; mq->tag_set.nr_hw_queues = 1; mq->tag_set.cmd_size = sizeof(struct mmc_queue_req); mq->tag_set.driver_data = mq; + /* + * Since blk_mq_alloc_tag_set() calls .init_request() of mmc_mq_ops, + * the host->can_dma_map_merge should be set before to get max_segs + * from mmc_get_max_segments(). + */ + if (mmc_merge_capable(host) && + host->max_segs < MMC_DMA_MAP_MERGE_SEGMENTS && + dma_get_merge_boundary(mmc_dev(host))) + host->can_dma_map_merge = 1; + else + host->can_dma_map_merge = 0; + ret = blk_mq_alloc_tag_set(&mq->tag_set); if (ret) - return ret; - - mq->queue = blk_mq_init_queue(&mq->tag_set); - if (IS_ERR(mq->queue)) { - ret = PTR_ERR(mq->queue); - goto free_tag_set; - } - - mq->queue->queuedata = mq; - blk_queue_rq_timeout(mq->queue, 60 * HZ); - - mmc_setup_queue(mq, card); - return 0; + return ERR_PTR(ret); + -free_tag_set: - blk_mq_free_tag_set(&mq->tag_set); - return ret; + disk = mmc_alloc_disk(mq, card, features); + if (IS_ERR(disk)) + blk_mq_free_tag_set(&mq->tag_set); + return disk; } void mmc_queue_suspend(struct mmc_queue *mq) @@ -465,7 +497,14 @@ void mmc_cleanup_queue(struct mmc_queue *mq) if (blk_queue_quiesced(q)) blk_mq_unquiesce_queue(q); - blk_cleanup_queue(q); + /* + * If the recovery completes the last (and only remaining) request in + * the queue, and the card has been removed, we could end up here with + * the recovery not quite finished yet, so cancel it. + */ + cancel_work_sync(&mq->recovery_work); + + blk_mq_free_tag_set(&mq->tag_set); /* * A request can be completed before the next request, potentially @@ -484,5 +523,5 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq) { struct request *req = mmc_queue_req_to_req(mqrq); - return blk_rq_map_sg(mq->queue, req, mqrq->sg); + return blk_rq_map_sg(req, mqrq->sg); } diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index fd11491ced9f..1498840a4ea0 100644 --- a/drivers/mmc/core/queue.h +++ b/drivers/mmc/core/queue.h @@ -81,9 +81,7 @@ struct mmc_queue { int in_flight[MMC_ISSUE_MAX]; unsigned int cqe_busy; #define MMC_CQE_DCMD_BUSY BIT(0) -#define MMC_CQE_QUEUE_FULL BIT(1) bool busy; - bool use_cqe; bool recovery_needed; bool in_recovery; bool rw_wait; @@ -96,7 +94,8 @@ struct mmc_queue { struct work_struct complete_work; }; -extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *); +struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, + unsigned int features); extern void mmc_cleanup_queue(struct mmc_queue *); extern void mmc_queue_suspend(struct mmc_queue *); extern void mmc_queue_resume(struct mmc_queue *); diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h index dd2f73af8f2c..c417ed34c057 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h @@ -10,11 +10,50 @@ * */ +#include <linux/of.h> #include <linux/mmc/sdio_ids.h> #include "card.h" -static const struct mmc_fixup mmc_blk_fixups[] = { +static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = { + /* + * Kingston Canvas Go! Plus microSD cards never finish SD cache flush. + * This has so far only been observed on cards from 11/2019, while new + * cards from 2023/05 do not exhibit this behavior. + */ + _FIXUP_EXT("SD64G", CID_MANFID_KINGSTON_SD, 0x5449, 2019, 11, + 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + + /* + * GIGASTONE Gaming Plus microSD cards manufactured on 02/2022 never + * clear Flush Cache bit and set Poweroff Notification Ready bit. + */ + _FIXUP_EXT("ASTC", CID_MANFID_GIGASTONE, 0x3456, 2022, 2, + 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_CACHE | MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY, + EXT_CSD_REV_ANY), + + /* + * Swissbit series S46-u cards throw I/O errors during tuning requests + * after the initial tuning request expectedly times out. This has + * only been observed on cards manufactured on 01/2019 that are using + * Bay Trail host controllers. + */ + _FIXUP_EXT("0016G", CID_MANFID_SWISSBIT, 0x5342, 2019, 1, + 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_NO_UHS_DDR50_TUNING, EXT_CSD_REV_ANY), + + /* + * Some SD cards reports discard support while they don't + */ + MMC_FIXUP(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_DISCARD), + + END_FIXUP +}; + +static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = { #define INAND_CMD38_ARG_EXT_CSD 113 #define INAND_CMD38_ARG_ERASE 0x00 #define INAND_CMD38_ARG_TRIM 0x01 @@ -99,10 +138,25 @@ static const struct mmc_fixup mmc_blk_fixups[] = { MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_TRIM_BROKEN), + /* + * Micron MTFC4GACAJCN-1M supports TRIM but does not appear to support + * WRITE_ZEROES offloading. It also supports caching, but the cache can + * only be flushed after a write has occurred. + */ + MMC_FIXUP("Q2J54A", CID_MANFID_MICRON, 0x014e, add_quirk_mmc, + MMC_QUIRK_TRIM_BROKEN | MMC_QUIRK_BROKEN_CACHE_FLUSH), + + /* + * Kingston EMMC04G-M627 advertises TRIM but it does not seems to + * support being used to offload WRITE_ZEROES. + */ + MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc, + MMC_QUIRK_TRIM_BROKEN), + END_FIXUP }; -static const struct mmc_fixup mmc_ext_csd_fixups[] = { +static const struct mmc_fixup __maybe_unused mmc_ext_csd_fixups[] = { /* * Certain Hynix eMMC 4.41 cards might get broken when HPI feature * is used so disable the HPI feature for such buggy cards. @@ -119,7 +173,14 @@ static const struct mmc_fixup mmc_ext_csd_fixups[] = { END_FIXUP }; -static const struct mmc_fixup sdio_fixup_methods[] = { + +static const struct mmc_fixup __maybe_unused sdio_fixup_methods[] = { + SDIO_FIXUP(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251, + add_quirk, MMC_QUIRK_NONSTD_FUNC_IF), + + SDIO_FIXUP(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251, + add_quirk, MMC_QUIRK_DISABLE_CD), + SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, add_quirk, MMC_QUIRK_NONSTD_FUNC_IF), @@ -132,12 +193,38 @@ static const struct mmc_fixup sdio_fixup_methods[] = { SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_F0, add_quirk, MMC_QUIRK_BROKEN_IRQ_POLLING), - SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887WLAN, + SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887_F0, add_limit_rate_quirk, 150000000), END_FIXUP }; +static const struct mmc_fixup __maybe_unused sdio_card_init_methods[] = { + SDIO_FIXUP_COMPATIBLE("ti,wl1251", wl1251_quirk, 0), + + SDIO_FIXUP_COMPATIBLE("silabs,wf200", add_quirk, + MMC_QUIRK_BROKEN_BYTE_MODE_512 | + MMC_QUIRK_LENIENT_FN0 | + MMC_QUIRK_BLKSZ_FOR_BYTE_MODE), + + END_FIXUP +}; + +static inline bool mmc_fixup_of_compatible_match(struct mmc_card *card, + const char *compatible) +{ + struct device_node *np; + + for_each_child_of_node(mmc_dev(card->host)->of_node, np) { + if (of_device_is_compatible(np, compatible)) { + of_node_put(np); + return true; + } + } + + return false; +} + static inline void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) { @@ -145,22 +232,36 @@ static inline void mmc_fixup_device(struct mmc_card *card, u64 rev = cid_rev_card(card); for (f = table; f->vendor_fixup; f++) { - if ((f->manfid == CID_MANFID_ANY || - f->manfid == card->cid.manfid) && - (f->oemid == CID_OEMID_ANY || - f->oemid == card->cid.oemid) && - (f->name == CID_NAME_ANY || - !strncmp(f->name, card->cid.prod_name, - sizeof(card->cid.prod_name))) && - (f->cis_vendor == card->cis.vendor || - f->cis_vendor == (u16) SDIO_ANY_ID) && - (f->cis_device == card->cis.device || - f->cis_device == (u16) SDIO_ANY_ID) && - (f->ext_csd_rev == EXT_CSD_REV_ANY || - f->ext_csd_rev == card->ext_csd.rev) && - rev >= f->rev_start && rev <= f->rev_end) { - dev_dbg(&card->dev, "calling %pf\n", f->vendor_fixup); - f->vendor_fixup(card, f->data); - } + if (f->manfid != CID_MANFID_ANY && + f->manfid != card->cid.manfid) + continue; + if (f->oemid != CID_OEMID_ANY && + f->oemid != card->cid.oemid) + continue; + if (f->name != CID_NAME_ANY && + strncmp(f->name, card->cid.prod_name, + sizeof(card->cid.prod_name))) + continue; + if (f->cis_vendor != (u16)SDIO_ANY_ID && + f->cis_vendor != card->cis.vendor) + continue; + if (f->cis_device != (u16)SDIO_ANY_ID && + f->cis_device != card->cis.device) + continue; + if (f->ext_csd_rev != EXT_CSD_REV_ANY && + f->ext_csd_rev != card->ext_csd.rev) + continue; + if (rev < f->rev_start || rev > f->rev_end) + continue; + if (f->of_compatible && + !mmc_fixup_of_compatible_match(card, f->of_compatible)) + continue; + if (f->year != CID_YEAR_ANY && f->year != card->cid.year) + continue; + if (f->month != CID_MONTH_ANY && f->month != card->cid.month) + continue; + + dev_dbg(&card->dev, "calling %ps\n", f->vendor_fixup); + f->vendor_fixup(card, f->data); } } diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c new file mode 100644 index 000000000000..a85179f1a4de --- /dev/null +++ b/drivers/mmc/core/regulator.c @@ -0,0 +1,432 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Helper functions for MMC regulators. + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/log2.h> +#include <linux/regulator/consumer.h> +#include <linux/workqueue.h> + +#include <linux/mmc/host.h> + +#include "core.h" +#include "host.h" + +#ifdef CONFIG_REGULATOR + +/** + * mmc_ocrbitnum_to_vdd - Convert a OCR bit number to its voltage + * @vdd_bit: OCR bit number + * @min_uV: minimum voltage value (mV) + * @max_uV: maximum voltage value (mV) + * + * This function returns the voltage range according to the provided OCR + * bit number. If conversion is not possible a negative errno value returned. + */ +static int mmc_ocrbitnum_to_vdd(int vdd_bit, int *min_uV, int *max_uV) +{ + int tmp; + + if (!vdd_bit) + return -EINVAL; + + /* + * REVISIT mmc_vddrange_to_ocrmask() may have set some + * bits this regulator doesn't quite support ... don't + * be too picky, most cards and regulators are OK with + * a 0.1V range goof (it's a small error percentage). + */ + tmp = vdd_bit - ilog2(MMC_VDD_165_195); + if (tmp == 0) { + *min_uV = 1650 * 1000; + *max_uV = 1950 * 1000; + } else { + *min_uV = 1900 * 1000 + tmp * 100 * 1000; + *max_uV = *min_uV + 100 * 1000; + } + + return 0; +} + +/** + * mmc_regulator_get_ocrmask - return mask of supported voltages + * @supply: regulator to use + * + * This returns either a negative errno, or a mask of voltages that + * can be provided to MMC/SD/SDIO devices using the specified voltage + * regulator. This would normally be called before registering the + * MMC host adapter. + */ +static int mmc_regulator_get_ocrmask(struct regulator *supply) +{ + int result = 0; + int count; + int i; + int vdd_uV; + int vdd_mV; + + count = regulator_count_voltages(supply); + if (count < 0) + return count; + + for (i = 0; i < count; i++) { + vdd_uV = regulator_list_voltage(supply, i); + if (vdd_uV <= 0) + continue; + + vdd_mV = vdd_uV / 1000; + result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); + } + + if (!result) { + vdd_uV = regulator_get_voltage(supply); + if (vdd_uV <= 0) + return vdd_uV; + + vdd_mV = vdd_uV / 1000; + result = mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV); + } + + return result; +} + +/** + * mmc_regulator_set_ocr - set regulator to match host->ios voltage + * @mmc: the host to regulate + * @supply: regulator to use + * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) + * + * Returns zero on success, else negative errno. + * + * MMC host drivers may use this to enable or disable a regulator using + * a particular supply voltage. This would normally be called from the + * set_ios() method. + */ +int mmc_regulator_set_ocr(struct mmc_host *mmc, + struct regulator *supply, + unsigned short vdd_bit) +{ + int result = 0; + int min_uV, max_uV; + + if (IS_ERR(supply)) + return 0; + + if (vdd_bit) { + mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV); + + result = regulator_set_voltage(supply, min_uV, max_uV); + if (result == 0 && !mmc->regulator_enabled) { + result = regulator_enable(supply); + if (!result) + mmc->regulator_enabled = true; + } + } else if (mmc->regulator_enabled) { + result = regulator_disable(supply); + if (result == 0) + mmc->regulator_enabled = false; + } + + if (result) + dev_err(mmc_dev(mmc), + "could not set regulator OCR (%d)\n", result); + return result; +} +EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr); + +static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator, + int min_uV, int target_uV, + int max_uV) +{ + int current_uV; + + /* + * Check if supported first to avoid errors since we may try several + * signal levels during power up and don't want to show errors. + */ + if (!regulator_is_supported_voltage(regulator, min_uV, max_uV)) + return -EINVAL; + + /* + * The voltage is already set, no need to switch. + * Return 1 to indicate that no switch happened. + */ + current_uV = regulator_get_voltage(regulator); + if (current_uV == target_uV) + return 1; + + return regulator_set_voltage_triplet(regulator, min_uV, target_uV, + max_uV); +} + +/** + * mmc_regulator_set_vqmmc - Set VQMMC as per the ios + * @mmc: the host to regulate + * @ios: io bus settings + * + * For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible. + * That will match the behavior of old boards where VQMMC and VMMC were supplied + * by the same supply. The Bus Operating conditions for 3.3V signaling in the + * SD card spec also define VQMMC in terms of VMMC. + * If this is not possible we'll try the full 2.7-3.6V of the spec. + * + * For 1.2V and 1.8V signaling we'll try to get as close as possible to the + * requested voltage. This is definitely a good idea for UHS where there's a + * separate regulator on the card that's trying to make 1.8V and it's best if + * we match. + * + * This function is expected to be used by a controller's + * start_signal_voltage_switch() function. + */ +int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct device *dev = mmc_dev(mmc); + int ret, volt, min_uV, max_uV; + + /* If no vqmmc supply then we can't change the voltage */ + if (IS_ERR(mmc->supply.vqmmc)) + return -EINVAL; + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_120: + return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + 1100000, 1200000, 1300000); + case MMC_SIGNAL_VOLTAGE_180: + return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + 1700000, 1800000, 1950000); + case MMC_SIGNAL_VOLTAGE_330: + ret = mmc_ocrbitnum_to_vdd(mmc->ios.vdd, &volt, &max_uV); + if (ret < 0) + return ret; + + dev_dbg(dev, "%s: found vmmc voltage range of %d-%duV\n", + __func__, volt, max_uV); + + min_uV = max(volt - 300000, 2700000); + max_uV = min(max_uV + 200000, 3600000); + + /* + * Due to a limitation in the current implementation of + * regulator_set_voltage_triplet() which is taking the lowest + * voltage possible if below the target, search for a suitable + * voltage in two steps and try to stay close to vmmc + * with a 0.3V tolerance at first. + */ + ret = mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + min_uV, volt, max_uV); + if (ret >= 0) + return ret; + + return mmc_regulator_set_voltage_if_supported(mmc->supply.vqmmc, + 2700000, volt, 3600000); + default: + return -EINVAL; + } +} +EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc); + +/** + * mmc_regulator_set_vqmmc2 - Set vqmmc2 as per the ios->vqmmc2_voltage + * @mmc: The mmc host to regulate + * @ios: The io bus settings + * + * Sets a new voltage level for the vqmmc2 regulator, which may correspond to + * the vdd2 regulator for an SD UHS-II interface. This function is expected to + * be called by mmc host drivers. + * + * Returns a negative error code on failure, zero if the voltage level was + * changed successfully or a positive value if the level didn't need to change. + */ +int mmc_regulator_set_vqmmc2(struct mmc_host *mmc, struct mmc_ios *ios) +{ + if (IS_ERR(mmc->supply.vqmmc2)) + return -EINVAL; + + switch (ios->vqmmc2_voltage) { + case MMC_VQMMC2_VOLTAGE_180: + return mmc_regulator_set_voltage_if_supported( + mmc->supply.vqmmc2, 1700000, 1800000, 1950000); + default: + return -EINVAL; + } +} +EXPORT_SYMBOL_GPL(mmc_regulator_set_vqmmc2); + +#else + +static inline int mmc_regulator_get_ocrmask(struct regulator *supply) +{ + return 0; +} + +#endif /* CONFIG_REGULATOR */ + +/* To be called from a high-priority workqueue */ +void mmc_undervoltage_workfn(struct work_struct *work) +{ + struct mmc_supply *supply; + struct mmc_host *host; + + supply = container_of(work, struct mmc_supply, uv_work); + host = container_of(supply, struct mmc_host, supply); + + mmc_handle_undervoltage(host); +} + +static int mmc_handle_regulator_event(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct mmc_supply *supply = container_of(nb, struct mmc_supply, + vmmc_nb); + struct mmc_host *host = container_of(supply, struct mmc_host, supply); + unsigned long flags; + + switch (event) { + case REGULATOR_EVENT_UNDER_VOLTAGE: + spin_lock_irqsave(&host->lock, flags); + if (host->undervoltage) { + spin_unlock_irqrestore(&host->lock, flags); + return NOTIFY_OK; + } + + host->undervoltage = true; + spin_unlock_irqrestore(&host->lock, flags); + + queue_work(system_highpri_wq, &host->supply.uv_work); + break; + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +/** + * mmc_regulator_register_undervoltage_notifier - Register for undervoltage + * events + * @host: MMC host + * + * To be called by a bus driver when a card supporting graceful shutdown + * is attached. + */ +void mmc_regulator_register_undervoltage_notifier(struct mmc_host *host) +{ + int ret; + + if (IS_ERR_OR_NULL(host->supply.vmmc)) + return; + + host->supply.vmmc_nb.notifier_call = mmc_handle_regulator_event; + ret = regulator_register_notifier(host->supply.vmmc, + &host->supply.vmmc_nb); + if (ret) + dev_warn(mmc_dev(host), "Failed to register vmmc notifier: %d\n", ret); +} + +/** + * mmc_regulator_unregister_undervoltage_notifier - Unregister undervoltage + * notifier + * @host: MMC host + */ +void mmc_regulator_unregister_undervoltage_notifier(struct mmc_host *host) +{ + if (IS_ERR_OR_NULL(host->supply.vmmc)) + return; + + regulator_unregister_notifier(host->supply.vmmc, &host->supply.vmmc_nb); + cancel_work_sync(&host->supply.uv_work); +} + +/** + * mmc_regulator_get_supply - try to get VMMC and VQMMC regulators for a host + * @mmc: the host to regulate + * + * Returns 0 or errno. errno should be handled, it is either a critical error + * or -EPROBE_DEFER. 0 means no critical error but it does not mean all + * regulators have been found because they all are optional. If you require + * certain regulators, you need to check separately in your driver if they got + * populated after calling this function. + */ +int mmc_regulator_get_supply(struct mmc_host *mmc) +{ + struct device *dev = mmc_dev(mmc); + int ret; + + mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc"); + mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); + mmc->supply.vqmmc2 = devm_regulator_get_optional(dev, "vqmmc2"); + + if (IS_ERR(mmc->supply.vmmc)) { + if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) + return dev_err_probe(dev, -EPROBE_DEFER, + "vmmc regulator not available\n"); + + dev_dbg(dev, "No vmmc regulator found\n"); + } else { + ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc); + if (ret > 0) + mmc->ocr_avail = ret; + else + dev_warn(dev, "Failed getting OCR mask: %d\n", ret); + } + + if (IS_ERR(mmc->supply.vqmmc)) { + if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER) + return dev_err_probe(dev, -EPROBE_DEFER, + "vqmmc regulator not available\n"); + + dev_dbg(dev, "No vqmmc regulator found\n"); + } + + if (IS_ERR(mmc->supply.vqmmc2)) { + if (PTR_ERR(mmc->supply.vqmmc2) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_dbg(dev, "No vqmmc2 regulator found\n"); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); + +/** + * mmc_regulator_enable_vqmmc - enable VQMMC regulator for a host + * @mmc: the host to regulate + * + * Returns 0 or errno. Enables the regulator for vqmmc. + * Keeps track of the enable status for ensuring that calls to + * regulator_enable/disable are balanced. + */ +int mmc_regulator_enable_vqmmc(struct mmc_host *mmc) +{ + int ret = 0; + + if (!IS_ERR(mmc->supply.vqmmc) && !mmc->vqmmc_enabled) { + ret = regulator_enable(mmc->supply.vqmmc); + if (ret < 0) + dev_err(mmc_dev(mmc), "enabling vqmmc regulator failed\n"); + else + mmc->vqmmc_enabled = true; + } + + return ret; +} +EXPORT_SYMBOL_GPL(mmc_regulator_enable_vqmmc); + +/** + * mmc_regulator_disable_vqmmc - disable VQMMC regulator for a host + * @mmc: the host to regulate + * + * Returns 0 or errno. Disables the regulator for vqmmc. + * Keeps track of the enable status for ensuring that calls to + * regulator_enable/disable are balanced. + */ +void mmc_regulator_disable_vqmmc(struct mmc_host *mmc) +{ + if (!IS_ERR(mmc->supply.vqmmc) && mmc->vqmmc_enabled) { + regulator_disable(mmc->supply.vqmmc); + mmc->vqmmc_enabled = false; + } +} +EXPORT_SYMBOL_GPL(mmc_regulator_disable_vqmmc); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index d0d9f90e7cdf..948948ca9b4a 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1,20 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/mmc/core/sd.c * * Copyright (C) 2003-2004 Russell King, All Rights Reserved. * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/err.h> #include <linux/sizes.h> #include <linux/slab.h> #include <linux/stat.h> +#include <linux/string.h> #include <linux/pm_runtime.h> +#include <linux/random.h> +#include <linux/scatterlist.h> +#include <linux/sysfs.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> @@ -26,6 +27,7 @@ #include "host.h" #include "bus.h" #include "mmc_ops.h" +#include "quirks.h" #include "sd.h" #include "sd_ops.h" @@ -55,19 +57,13 @@ static const unsigned int sd_au_size[] = { SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512, }; -#define UNSTUFF_BITS(resp,start,size) \ - ({ \ - const int __size = size; \ - const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \ - const int __off = 3 - ((start) / 32); \ - const int __shft = (start) & 31; \ - u32 __res; \ - \ - __res = resp[__off] >> __shft; \ - if (__size + __shft > 32) \ - __res |= resp[__off-1] << ((32 - __shft) % 32); \ - __res & __mask; \ - }) +#define SD_POWEROFF_NOTIFY_TIMEOUT_MS 1000 +#define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000 + +struct sd_busy_data { + struct mmc_card *card; + u8 *reg_buf; +}; /* * Given the decoded CSD structure, decode the raw CID to our CID structure. @@ -77,72 +73,85 @@ void mmc_decode_cid(struct mmc_card *card) u32 *resp = card->raw_cid; /* + * Add the raw card ID (cid) data to the entropy pool. It doesn't + * matter that not all of it is unique, it's just bonus entropy. + */ + add_device_randomness(&card->raw_cid, sizeof(card->raw_cid)); + + /* * SD doesn't currently have a version field so we will * have to assume we can parse this. */ - card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); - card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); - card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); - card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); - card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); - card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); - card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); - card->cid.hwrev = UNSTUFF_BITS(resp, 60, 4); - card->cid.fwrev = UNSTUFF_BITS(resp, 56, 4); - card->cid.serial = UNSTUFF_BITS(resp, 24, 32); - card->cid.year = UNSTUFF_BITS(resp, 12, 8); - card->cid.month = UNSTUFF_BITS(resp, 8, 4); + card->cid.manfid = unstuff_bits(resp, 120, 8); + card->cid.oemid = unstuff_bits(resp, 104, 16); + card->cid.prod_name[0] = unstuff_bits(resp, 96, 8); + card->cid.prod_name[1] = unstuff_bits(resp, 88, 8); + card->cid.prod_name[2] = unstuff_bits(resp, 80, 8); + card->cid.prod_name[3] = unstuff_bits(resp, 72, 8); + card->cid.prod_name[4] = unstuff_bits(resp, 64, 8); + card->cid.hwrev = unstuff_bits(resp, 60, 4); + card->cid.fwrev = unstuff_bits(resp, 56, 4); + card->cid.serial = unstuff_bits(resp, 24, 32); + card->cid.year = unstuff_bits(resp, 12, 8); + card->cid.month = unstuff_bits(resp, 8, 4); card->cid.year += 2000; /* SD cards year offset */ + + /* some product names may include trailing whitespace */ + strim(card->cid.prod_name); } /* * Given a 128-bit response, decode to our card CSD structure. */ -static int mmc_decode_csd(struct mmc_card *card) +static int mmc_decode_csd(struct mmc_card *card, bool is_sduc) { struct mmc_csd *csd = &card->csd; unsigned int e, m, csd_struct; u32 *resp = card->raw_csd; - csd_struct = UNSTUFF_BITS(resp, 126, 2); + csd_struct = unstuff_bits(resp, 126, 2); switch (csd_struct) { case 0: - m = UNSTUFF_BITS(resp, 115, 4); - e = UNSTUFF_BITS(resp, 112, 3); + m = unstuff_bits(resp, 115, 4); + e = unstuff_bits(resp, 112, 3); csd->taac_ns = (taac_exp[e] * taac_mant[m] + 9) / 10; - csd->taac_clks = UNSTUFF_BITS(resp, 104, 8) * 100; + csd->taac_clks = unstuff_bits(resp, 104, 8) * 100; - m = UNSTUFF_BITS(resp, 99, 4); - e = UNSTUFF_BITS(resp, 96, 3); + m = unstuff_bits(resp, 99, 4); + e = unstuff_bits(resp, 96, 3); csd->max_dtr = tran_exp[e] * tran_mant[m]; - csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); + csd->cmdclass = unstuff_bits(resp, 84, 12); - e = UNSTUFF_BITS(resp, 47, 3); - m = UNSTUFF_BITS(resp, 62, 12); + e = unstuff_bits(resp, 47, 3); + m = unstuff_bits(resp, 62, 12); csd->capacity = (1 + m) << (e + 2); - csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); - csd->read_partial = UNSTUFF_BITS(resp, 79, 1); - csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); - csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); - csd->dsr_imp = UNSTUFF_BITS(resp, 76, 1); - csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); - csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); - csd->write_partial = UNSTUFF_BITS(resp, 21, 1); + csd->read_blkbits = unstuff_bits(resp, 80, 4); + csd->read_partial = unstuff_bits(resp, 79, 1); + csd->write_misalign = unstuff_bits(resp, 78, 1); + csd->read_misalign = unstuff_bits(resp, 77, 1); + csd->dsr_imp = unstuff_bits(resp, 76, 1); + csd->r2w_factor = unstuff_bits(resp, 26, 3); + csd->write_blkbits = unstuff_bits(resp, 22, 4); + csd->write_partial = unstuff_bits(resp, 21, 1); - if (UNSTUFF_BITS(resp, 46, 1)) { + if (unstuff_bits(resp, 46, 1)) { csd->erase_size = 1; } else if (csd->write_blkbits >= 9) { - csd->erase_size = UNSTUFF_BITS(resp, 39, 7) + 1; + csd->erase_size = unstuff_bits(resp, 39, 7) + 1; csd->erase_size <<= csd->write_blkbits - 9; } + + if (unstuff_bits(resp, 13, 1)) + mmc_card_set_readonly(card); break; case 1: + case 2: /* - * This is a block-addressed SDHC or SDXC card. Most - * interesting fields are unused and have fixed + * This is a block-addressed SDHC, SDXC or SDUC card. + * Most interesting fields are unused and have fixed * values. To avoid getting tripped by buggy cards, * we assume those fixed values ourselves. */ @@ -151,18 +160,23 @@ static int mmc_decode_csd(struct mmc_card *card) csd->taac_ns = 0; /* Unused */ csd->taac_clks = 0; /* Unused */ - m = UNSTUFF_BITS(resp, 99, 4); - e = UNSTUFF_BITS(resp, 96, 3); + m = unstuff_bits(resp, 99, 4); + e = unstuff_bits(resp, 96, 3); csd->max_dtr = tran_exp[e] * tran_mant[m]; - csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); - csd->c_size = UNSTUFF_BITS(resp, 48, 22); + csd->cmdclass = unstuff_bits(resp, 84, 12); - /* SDXC cards have a minimum C_SIZE of 0x00FFFF */ - if (csd->c_size >= 0xFFFF) + if (csd_struct == 1) + m = unstuff_bits(resp, 48, 22); + else + m = unstuff_bits(resp, 48, 28); + csd->c_size = m; + + if (csd->c_size >= 0x400000 && is_sduc) + mmc_card_set_ult_capacity(card); + else if (csd->c_size >= 0xFFFF) mmc_card_set_ext_capacity(card); - m = UNSTUFF_BITS(resp, 48, 22); - csd->capacity = (1 + m) << 10; + csd->capacity = (1 + (typeof(sector_t))m) << 10; csd->read_blkbits = 9; csd->read_partial = 0; @@ -172,6 +186,9 @@ static int mmc_decode_csd(struct mmc_card *card) csd->write_blkbits = 9; csd->write_partial = 0; csd->erase_size = 1; + + if (unstuff_bits(resp, 13, 1)) + mmc_card_set_readonly(card); break; default: pr_err("%s: unrecognised CSD structure version %d\n", @@ -187,7 +204,7 @@ static int mmc_decode_csd(struct mmc_card *card) /* * Given a 64-bit response, decode to our card SCR structure. */ -static int mmc_decode_scr(struct mmc_card *card) +int mmc_decode_scr(struct mmc_card *card) { struct sd_scr *scr = &card->scr; unsigned int scr_struct; @@ -196,26 +213,41 @@ static int mmc_decode_scr(struct mmc_card *card) resp[3] = card->raw_scr[1]; resp[2] = card->raw_scr[0]; - scr_struct = UNSTUFF_BITS(resp, 60, 4); + scr_struct = unstuff_bits(resp, 60, 4); if (scr_struct != 0) { pr_err("%s: unrecognised SCR structure version %d\n", mmc_hostname(card->host), scr_struct); return -EINVAL; } - scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); - scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); + scr->sda_vsn = unstuff_bits(resp, 56, 4); + scr->bus_widths = unstuff_bits(resp, 48, 4); if (scr->sda_vsn == SCR_SPEC_VER_2) /* Check if Physical Layer Spec v3.0 is supported */ - scr->sda_spec3 = UNSTUFF_BITS(resp, 47, 1); + scr->sda_spec3 = unstuff_bits(resp, 47, 1); + + if (scr->sda_spec3) { + scr->sda_spec4 = unstuff_bits(resp, 42, 1); + scr->sda_specx = unstuff_bits(resp, 38, 4); + } - if (UNSTUFF_BITS(resp, 55, 1)) + if (unstuff_bits(resp, 55, 1)) card->erased_byte = 0xFF; else card->erased_byte = 0x0; - if (scr->sda_spec3) - scr->cmds = UNSTUFF_BITS(resp, 32, 2); + if (scr->sda_spec4) + scr->cmds = unstuff_bits(resp, 32, 4); + else if (scr->sda_spec3) + scr->cmds = unstuff_bits(resp, 32, 2); + + /* SD Spec says: any SD Card shall set at least bits 0 and 2 */ + if (!(scr->bus_widths & SD_SCR_BUS_WIDTH_1) || + !(scr->bus_widths & SD_SCR_BUS_WIDTH_4)) { + pr_err("%s: invalid bus width\n", mmc_hostname(card->host)); + return -EINVAL; + } + return 0; } @@ -226,6 +258,8 @@ static int mmc_read_ssr(struct mmc_card *card) { unsigned int au, es, et, eo; __be32 *raw_ssr; + u32 resp[4] = {}; + u8 discard_support; int i; if (!(card->csd.cmdclass & CCC_APP_SPEC)) { @@ -251,17 +285,17 @@ static int mmc_read_ssr(struct mmc_card *card) kfree(raw_ssr); /* - * UNSTUFF_BITS only works with four u32s so we have to offset the + * unstuff_bits only works with four u32s so we have to offset the * bitfield positions accordingly. */ - au = UNSTUFF_BITS(card->raw_ssr, 428 - 384, 4); + au = unstuff_bits(card->raw_ssr, 428 - 384, 4); if (au) { if (au <= 9 || card->scr.sda_spec3) { card->ssr.au = sd_au_size[au]; - es = UNSTUFF_BITS(card->raw_ssr, 408 - 384, 16); - et = UNSTUFF_BITS(card->raw_ssr, 402 - 384, 6); + es = unstuff_bits(card->raw_ssr, 408 - 384, 16); + et = unstuff_bits(card->raw_ssr, 402 - 384, 6); if (es && et) { - eo = UNSTUFF_BITS(card->raw_ssr, 400 - 384, 2); + eo = unstuff_bits(card->raw_ssr, 400 - 384, 2); card->ssr.erase_timeout = (et * 1000) / es; card->ssr.erase_offset = eo * 1000; } @@ -271,6 +305,14 @@ static int mmc_read_ssr(struct mmc_card *card) } } + /* + * starting SD5.1 discard is supported if DISCARD_SUPPORT (b313) is set + */ + resp[3] = card->raw_ssr[6]; + discard_support = unstuff_bits(resp, 313 - 288, 1); + card->erase_arg = (card->scr.sda_specx && discard_support) ? + SD_DISCARD_ARG : SD_ERASE_ARG; + return 0; } @@ -300,7 +342,7 @@ static int mmc_read_switch(struct mmc_card *card) * The argument does not matter, as the support bits do not * change with the arguments. */ - err = mmc_sd_switch(card, 0, 0, 0, status); + err = mmc_sd_switch(card, SD_SWITCH_CHECK, 0, 0, status); if (err) { /* * If the host or the card can't do the switch, @@ -317,7 +359,7 @@ static int mmc_read_switch(struct mmc_card *card) } if (status[13] & SD_MODE_HIGH_SPEED) - card->sw_caps.hs_max_dtr = HIGH_SPEED_MAX_DTR; + card->sw_caps.hs_max_dtr = card->host->max_sd_hs_hz ?: HIGH_SPEED_MAX_DTR; if (card->scr.sda_spec3) { card->sw_caps.sd3_bus_mode = status[13]; @@ -356,11 +398,12 @@ int mmc_sd_switch_hs(struct mmc_card *card) if (!status) return -ENOMEM; - err = mmc_sd_switch(card, 1, 0, 1, status); + err = mmc_sd_switch(card, SD_SWITCH_SET, 0, + HIGH_SPEED_BUS_SPEED, status); if (err) goto out; - if ((status[16] & 0xF) != 1) { + if ((status[16] & 0xF) != HIGH_SPEED_BUS_SPEED) { pr_warn("%s: Problem switching card into high-speed mode!\n", mmc_hostname(card->host)); err = 0; @@ -388,7 +431,8 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status) card_drv_type, &drv_type); if (drive_strength) { - err = mmc_sd_switch(card, 1, 2, drive_strength, status); + err = mmc_sd_switch(card, SD_SWITCH_SET, 2, + drive_strength, status); if (err) return err; if ((status[15] & 0xF) != drive_strength) { @@ -411,7 +455,7 @@ static void sd_update_bus_speed_mode(struct mmc_card *card) * If the host doesn't support any of the UHS-I modes, fallback on * default speed. */ - if (!mmc_host_uhs(card->host)) { + if (!mmc_host_can_uhs(card->host)) { card->sd_bus_speed = 0; return; } @@ -468,7 +512,7 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status) return 0; } - err = mmc_sd_switch(card, 1, 0, card->sd_bus_speed, status); + err = mmc_sd_switch(card, SD_SWITCH_SET, 0, card->sd_bus_speed, status); if (err) return err; @@ -510,7 +554,7 @@ static u32 sd_get_host_max_current(struct mmc_host *host) static int sd_set_current_limit(struct mmc_card *card, u8 *status) { - int current_limit = SD_SET_CURRENT_NO_CHANGE; + int current_limit = SD_SET_CURRENT_LIMIT_200; int err; u32 max_current; @@ -554,12 +598,10 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status) else if (max_current >= 400 && card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400) current_limit = SD_SET_CURRENT_LIMIT_400; - else if (max_current >= 200 && - card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_200) - current_limit = SD_SET_CURRENT_LIMIT_200; - if (current_limit != SD_SET_CURRENT_NO_CHANGE) { - err = mmc_sd_switch(card, 1, 3, current_limit, status); + if (current_limit != SD_SET_CURRENT_LIMIT_200) { + err = mmc_sd_switch(card, SD_SWITCH_SET, 3, + current_limit, status); if (err) return err; @@ -573,6 +615,29 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status) } /* + * Determine if the card should tune or not. + */ +static bool mmc_sd_use_tuning(struct mmc_card *card) +{ + /* + * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and + * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. + */ + if (mmc_host_is_spi(card->host)) + return false; + + switch (card->host->ios.timing) { + case MMC_TIMING_UHS_SDR50: + case MMC_TIMING_UHS_SDR104: + return true; + case MMC_TIMING_UHS_DDR50: + return !mmc_card_no_uhs_ddr50_tuning(card); + } + + return false; +} + +/* * UHS-I specific initialization procedure */ static int mmc_sd_init_uhs_card(struct mmc_card *card) @@ -615,14 +680,7 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) if (err) goto out; - /* - * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and - * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. - */ - if (!mmc_host_is_spi(card->host) && - (card->host->ios.timing == MMC_TIMING_UHS_SDR50 || - card->host->ios.timing == MMC_TIMING_UHS_DDR50 || - card->host->ios.timing == MMC_TIMING_UHS_SDR104)) { + if (mmc_sd_use_tuning(card)) { err = mmc_execute_tuning(card); /* @@ -671,23 +729,50 @@ MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); -static ssize_t mmc_dsr_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t mmc_dsr_show(struct device *dev, struct device_attribute *attr, + char *buf) { - struct mmc_card *card = mmc_dev_to_card(dev); - struct mmc_host *host = card->host; - - if (card->csd.dsr_imp && host->dsr_req) - return sprintf(buf, "0x%x\n", host->dsr); - else - /* return default DSR value */ - return sprintf(buf, "0x%x\n", 0x404); + struct mmc_card *card = mmc_dev_to_card(dev); + struct mmc_host *host = card->host; + + if (card->csd.dsr_imp && host->dsr_req) + return sysfs_emit(buf, "0x%x\n", host->dsr); + /* return default DSR value */ + return sysfs_emit(buf, "0x%x\n", 0x404); } -static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL); +static DEVICE_ATTR(dsr, 0444, mmc_dsr_show, NULL); + +MMC_DEV_ATTR(vendor, "0x%04x\n", card->cis.vendor); +MMC_DEV_ATTR(device, "0x%04x\n", card->cis.device); +MMC_DEV_ATTR(revision, "%u.%u\n", card->major_rev, card->minor_rev); + +#define sdio_info_attr(num) \ +static ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct mmc_card *card = mmc_dev_to_card(dev); \ + \ + if (num > card->num_info) \ + return -ENODATA; \ + if (!card->info[num - 1][0]) \ + return 0; \ + return sysfs_emit(buf, "%s\n", card->info[num - 1]); \ +} \ +static DEVICE_ATTR_RO(info##num) + +sdio_info_attr(1); +sdio_info_attr(2); +sdio_info_attr(3); +sdio_info_attr(4); static struct attribute *sd_std_attrs[] = { + &dev_attr_vendor.attr, + &dev_attr_device.attr, + &dev_attr_revision.attr, + &dev_attr_info1.attr, + &dev_attr_info2.attr, + &dev_attr_info3.attr, + &dev_attr_info4.attr, &dev_attr_cid.attr, &dev_attr_csd.attr, &dev_attr_scr.attr, @@ -706,9 +791,34 @@ static struct attribute *sd_std_attrs[] = { &dev_attr_dsr.attr, NULL, }; -ATTRIBUTE_GROUPS(sd_std); -struct device_type sd_type = { +static umode_t sd_std_is_visible(struct kobject *kobj, struct attribute *attr, + int index) +{ + struct device *dev = kobj_to_dev(kobj); + struct mmc_card *card = mmc_dev_to_card(dev); + + /* CIS vendor and device ids, revision and info string are available only for Combo cards */ + if ((attr == &dev_attr_vendor.attr || + attr == &dev_attr_device.attr || + attr == &dev_attr_revision.attr || + attr == &dev_attr_info1.attr || + attr == &dev_attr_info2.attr || + attr == &dev_attr_info3.attr || + attr == &dev_attr_info4.attr + ) &&!mmc_card_sd_combo(card)) + return 0; + + return attr->mode; +} + +static const struct attribute_group sd_std_group = { + .attrs = sd_std_attrs, + .is_visible = sd_std_is_visible, +}; +__ATTRIBUTE_GROUPS(sd_std); + +const struct device_type sd_type = { .groups = sd_std_groups, }; @@ -743,15 +853,18 @@ try_again: * block-addressed SDHC cards. */ err = mmc_send_if_cond(host, ocr); - if (!err) + if (!err) { ocr |= SD_OCR_CCS; + /* Set HO2T as well - SDUC card won't respond otherwise */ + ocr |= SD_OCR_2T; + } /* * If the host supports one of UHS-I modes, request the card * to switch to 1.8V signaling level. If the card has failed * repeatedly to switch however, skip this. */ - if (retries && mmc_host_uhs(host)) + if (retries && mmc_host_can_uhs(host)) ocr |= SD_OCR_S18R; /* @@ -767,11 +880,14 @@ try_again: return err; /* - * In case CCS and S18A in the response is set, start Signal Voltage - * Switch procedure. SPI mode doesn't support CMD11. + * In case the S18A bit is set in the response, let's start the signal + * voltage switch procedure. SPI mode doesn't support CMD11. + * Note that, according to the spec, the S18A bit is not valid unless + * the CCS bit is set as well. We deliberately deviate from the spec in + * regards to this, which allows UHS-I to be supported for SDSC cards. */ - if (!mmc_host_is_spi(host) && rocr && - ((*rocr & 0x41000000) == 0x41000000)) { + if (!mmc_host_is_spi(host) && (ocr & SD_OCR_S18R) && + rocr && (*rocr & SD_ROCR_S18A)) { err = mmc_set_uhs_voltage(host, pocr); if (err == -EAGAIN) { retries--; @@ -786,7 +902,7 @@ try_again: return err; } -int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card) +int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc) { int err; @@ -797,14 +913,14 @@ int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card) if (err) return err; - err = mmc_decode_csd(card); + err = mmc_decode_csd(card, is_sduc); if (err) return err; return 0; } -static int mmc_sd_get_ro(struct mmc_host *host) +int mmc_sd_get_ro(struct mmc_host *host) { int ro; @@ -850,16 +966,17 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, /* Erase init depends on CSD and SSR */ mmc_init_erase(card); - - /* - * Fetch switch information from card. - */ - err = mmc_read_switch(card); - if (err) - return err; } /* + * Fetch switch information from card. Note, sd3_bus_mode can change if + * voltage switch outcome changes, so do this always. + */ + err = mmc_read_switch(card); + if (err) + return err; + + /* * For SPI, enable CRC as appropriate. * This CRC enable is located AFTER the reading of the * card registers because some SDHC cards are not able @@ -914,6 +1031,385 @@ static bool mmc_sd_card_using_v18(struct mmc_card *card) (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); } +static int sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset, + u8 reg_data) +{ + struct mmc_host *host = card->host; + struct mmc_request mrq = {}; + struct mmc_command cmd = {}; + struct mmc_data data = {}; + struct scatterlist sg; + u8 *reg_buf; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + mrq.cmd = &cmd; + mrq.data = &data; + + /* + * Arguments of CMD49: + * [31:31] MIO (0 = memory). + * [30:27] FNO (function number). + * [26:26] MW - mask write mode (0 = disable). + * [25:18] page number. + * [17:9] offset address. + * [8:0] length (0 = 1 byte). + */ + cmd.arg = fno << 27 | page << 18 | offset << 9; + + /* The first byte in the buffer is the data to be written. */ + reg_buf[0] = reg_data; + + data.flags = MMC_DATA_WRITE; + data.blksz = 512; + data.blocks = 1; + data.sg = &sg; + data.sg_len = 1; + sg_init_one(&sg, reg_buf, 512); + + cmd.opcode = SD_WRITE_EXTR_SINGLE; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + mmc_set_data_timeout(&data, card); + mmc_wait_for_req(host, &mrq); + + kfree(reg_buf); + + /* + * Note that, the SD card is allowed to signal busy on DAT0 up to 1s + * after the CMD49. Although, let's leave this to be managed by the + * caller. + */ + + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + + return 0; +} + +static int sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page, + u16 offset, u16 len, u8 *reg_buf) +{ + u32 cmd_args; + + /* + * Command arguments of CMD48: + * [31:31] MIO (0 = memory). + * [30:27] FNO (function number). + * [26:26] reserved (0). + * [25:18] page number. + * [17:9] offset address. + * [8:0] length (0 = 1 byte, 1ff = 512 bytes). + */ + cmd_args = fno << 27 | page << 18 | offset << 9 | (len -1); + + return mmc_send_adtc_data(card, card->host, SD_READ_EXTR_SINGLE, + cmd_args, reg_buf, 512); +} + +static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page, + u16 offset) +{ + int err; + u8 *reg_buf; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* Read the extension register for power management function. */ + err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); + if (err) { + pr_warn("%s: error %d reading PM func of ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + + /* PM revision consists of 4 bits. */ + card->ext_power.rev = reg_buf[0] & 0xf; + + /* Power Off Notification support at bit 4. */ + if ((reg_buf[1] & BIT(4)) && !mmc_card_broken_sd_poweroff_notify(card)) + card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY; + + /* Power Sustenance support at bit 5. */ + if (reg_buf[1] & BIT(5)) + card->ext_power.feature_support |= SD_EXT_POWER_SUSTENANCE; + + /* Power Down Mode support at bit 6. */ + if (reg_buf[1] & BIT(6)) + card->ext_power.feature_support |= SD_EXT_POWER_DOWN_MODE; + + card->ext_power.fno = fno; + card->ext_power.page = page; + card->ext_power.offset = offset; + +out: + kfree(reg_buf); + return err; +} + +static int sd_parse_ext_reg_perf(struct mmc_card *card, u8 fno, u8 page, + u16 offset) +{ + int err; + u8 *reg_buf; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); + if (err) { + pr_warn("%s: error %d reading PERF func of ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + + /* PERF revision. */ + card->ext_perf.rev = reg_buf[0]; + + /* FX_EVENT support at bit 0. */ + if (reg_buf[1] & BIT(0)) + card->ext_perf.feature_support |= SD_EXT_PERF_FX_EVENT; + + /* Card initiated self-maintenance support at bit 0. */ + if (reg_buf[2] & BIT(0)) + card->ext_perf.feature_support |= SD_EXT_PERF_CARD_MAINT; + + /* Host initiated self-maintenance support at bit 1. */ + if (reg_buf[2] & BIT(1)) + card->ext_perf.feature_support |= SD_EXT_PERF_HOST_MAINT; + + /* Cache support at bit 0. */ + if ((reg_buf[4] & BIT(0)) && !mmc_card_broken_sd_cache(card)) + card->ext_perf.feature_support |= SD_EXT_PERF_CACHE; + + /* Command queue support indicated via queue depth bits (0 to 4). */ + if (reg_buf[6] & 0x1f) + card->ext_perf.feature_support |= SD_EXT_PERF_CMD_QUEUE; + + card->ext_perf.fno = fno; + card->ext_perf.page = page; + card->ext_perf.offset = offset; + +out: + kfree(reg_buf); + return err; +} + +static int sd_parse_ext_reg(struct mmc_card *card, u8 *gen_info_buf, + u16 *next_ext_addr) +{ + u8 num_regs, fno, page; + u16 sfc, offset, ext = *next_ext_addr; + u32 reg_addr; + + /* + * Parse only one register set per extension, as that is sufficient to + * support the standard functions. This means another 48 bytes in the + * buffer must be available. + */ + if (ext + 48 > 512) + return -EFAULT; + + /* Standard Function Code */ + memcpy(&sfc, &gen_info_buf[ext], 2); + + /* Address to the next extension. */ + memcpy(next_ext_addr, &gen_info_buf[ext + 40], 2); + + /* Number of registers for this extension. */ + num_regs = gen_info_buf[ext + 42]; + + /* We support only one register per extension. */ + if (num_regs != 1) + return 0; + + /* Extension register address. */ + memcpy(®_addr, &gen_info_buf[ext + 44], 4); + + /* 9 bits (0 to 8) contains the offset address. */ + offset = reg_addr & 0x1ff; + + /* 8 bits (9 to 16) contains the page number. */ + page = reg_addr >> 9 & 0xff ; + + /* 4 bits (18 to 21) contains the function number. */ + fno = reg_addr >> 18 & 0xf; + + /* Standard Function Code for power management. */ + if (sfc == 0x1) + return sd_parse_ext_reg_power(card, fno, page, offset); + + /* Standard Function Code for performance enhancement. */ + if (sfc == 0x2) + return sd_parse_ext_reg_perf(card, fno, page, offset); + + return 0; +} + +static int sd_read_ext_regs(struct mmc_card *card) +{ + int err, i; + u8 num_ext, *gen_info_buf; + u16 rev, len, next_ext_addr; + + if (mmc_host_is_spi(card->host)) + return 0; + + if (!(card->scr.cmds & SD_SCR_CMD48_SUPPORT)) + return 0; + + gen_info_buf = kzalloc(512, GFP_KERNEL); + if (!gen_info_buf) + return -ENOMEM; + + /* + * Read 512 bytes of general info, which is found at function number 0, + * at page 0 and with no offset. + */ + err = sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf); + if (err) { + pr_err("%s: error %d reading general info of SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + + /* General info structure revision. */ + memcpy(&rev, &gen_info_buf[0], 2); + + /* Length of general info in bytes. */ + memcpy(&len, &gen_info_buf[2], 2); + + /* Number of extensions to be find. */ + num_ext = gen_info_buf[4]; + + /* + * We only support revision 0 and limit it to 512 bytes for simplicity. + * No matter what, let's return zero to allow us to continue using the + * card, even if we can't support the features from the SD function + * extensions registers. + */ + if (rev != 0 || len > 512) { + pr_warn("%s: non-supported SD ext reg layout\n", + mmc_hostname(card->host)); + goto out; + } + + /* + * Parse the extension registers. The first extension should start + * immediately after the general info header (16 bytes). + */ + next_ext_addr = 16; + for (i = 0; i < num_ext; i++) { + err = sd_parse_ext_reg(card, gen_info_buf, &next_ext_addr); + if (err) { + pr_err("%s: error %d parsing SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + } + +out: + kfree(gen_info_buf); + return err; +} + +static bool sd_cache_enabled(struct mmc_host *host) +{ + return host->card->ext_perf.feature_enabled & SD_EXT_PERF_CACHE; +} + +static int sd_flush_cache(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + u8 *reg_buf, fno, page; + u16 offset; + int err; + + if (!sd_cache_enabled(host)) + return 0; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set Flush Cache at bit 0 in the performance enhancement register at + * 261 bytes offset. + */ + fno = card->ext_perf.fno; + page = card->ext_perf.page; + offset = card->ext_perf.offset + 261; + + err = sd_write_ext_reg(card, fno, page, offset, BIT(0)); + if (err) { + pr_warn("%s: error %d writing Cache Flush bit\n", + mmc_hostname(host), err); + goto out; + } + + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, + MMC_BUSY_EXTR_SINGLE); + if (err) + goto out; + + /* + * Read the Flush Cache bit. The card shall reset it, to confirm that + * it's has completed the flushing of the cache. + */ + err = sd_read_ext_reg(card, fno, page, offset, 1, reg_buf); + if (err) { + pr_warn("%s: error %d reading Cache Flush bit\n", + mmc_hostname(host), err); + goto out; + } + + if (reg_buf[0] & BIT(0)) + err = -ETIMEDOUT; +out: + kfree(reg_buf); + return err; +} + +static int sd_enable_cache(struct mmc_card *card) +{ + u8 *reg_buf; + int err; + + card->ext_perf.feature_enabled &= ~SD_EXT_PERF_CACHE; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set Cache Enable at bit 0 in the performance enhancement register at + * 260 bytes offset. + */ + err = sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page, + card->ext_perf.offset + 260, BIT(0)); + if (err) { + pr_warn("%s: error %d writing Cache Enable bit\n", + mmc_hostname(card->host), err); + goto out; + } + + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, + MMC_BUSY_EXTR_SINGLE); + if (!err) + card->ext_perf.feature_enabled |= SD_EXT_PERF_CACHE; + +out: + kfree(reg_buf); + return err; +} + /* * Handle the detection and initialisation of a card. * @@ -936,8 +1432,11 @@ retry: return err; if (oldcard) { - if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) + if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { + pr_debug("%s: Perhaps the card was replaced\n", + mmc_hostname(host)); return -ENOENT; + } card = oldcard; } else { @@ -969,7 +1468,10 @@ retry: } if (!oldcard) { - err = mmc_sd_get_csd(host, card); + u32 sduc_arg = SD_OCR_CCS | SD_OCR_2T; + bool is_sduc = (rocr & sduc_arg) == sduc_arg; + + err = mmc_sd_get_csd(card, is_sduc); if (err) goto free_card; @@ -992,6 +1494,9 @@ retry: goto free_card; } + /* Apply quirks prior to card setup */ + mmc_fixup_device(card, mmc_sd_fixups); + err = mmc_sd_setup_card(host, card, oldcard != NULL); if (err) goto free_card; @@ -1001,33 +1506,22 @@ retry: * signaling. Detect that situation and try to initialize a UHS-I (1.8V) * transfer mode. */ - if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_uhs(host) && + if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_can_uhs(host) && mmc_sd_card_using_v18(card) && host->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_180) { - /* - * Re-read switch information in case it has changed since - * oldcard was initialized. - */ - if (oldcard) { - err = mmc_read_switch(card); - if (err) - goto free_card; - } - if (mmc_sd_card_using_v18(card)) { - if (mmc_host_set_uhs_voltage(host) || - mmc_sd_init_uhs_card(card)) { - v18_fixup_failed = true; - mmc_power_cycle(host, ocr); - if (!oldcard) - mmc_remove_card(card); - goto retry; - } - goto done; + if (mmc_host_set_uhs_voltage(host) || + mmc_sd_init_uhs_card(card)) { + v18_fixup_failed = true; + mmc_power_cycle(host, ocr); + if (!oldcard) + mmc_remove_card(card); + goto retry; } + goto cont; } /* Initialization sequence for UHS-I cards */ - if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { + if (rocr & SD_ROCR_S18A && mmc_host_can_uhs(host)) { err = mmc_sd_init_uhs_card(card); if (err) goto free_card; @@ -1046,6 +1540,13 @@ retry: */ mmc_set_clock(host, mmc_sd_get_max_clock(card)); + if (host->ios.timing == MMC_TIMING_SD_HS && + host->ops->prepare_sd_hs_tuning) { + err = host->ops->prepare_sd_hs_tuning(host, card); + if (err) + goto free_card; + } + /* * Switch to wider bus (if supported). */ @@ -1057,6 +1558,37 @@ retry: mmc_set_bus_width(host, MMC_BUS_WIDTH_4); } + + if (host->ios.timing == MMC_TIMING_SD_HS && + host->ops->execute_sd_hs_tuning) { + err = host->ops->execute_sd_hs_tuning(host, card); + if (err) + goto free_card; + } + } +cont: + if (!oldcard) { + /* Read/parse the extension registers. */ + err = sd_read_ext_regs(card); + if (err) + goto free_card; + } + + /* Enable internal SD cache if supported. */ + if (card->ext_perf.feature_support & SD_EXT_PERF_CACHE) { + err = sd_enable_cache(card); + if (err) + goto free_card; + } + + if (!mmc_card_ult_capacity(card) && host->cqe_ops && !host->cqe_enabled) { + err = host->cqe_ops->cqe_enable(host, card); + if (!err) { + host->cqe_enabled = true; + host->hsq_enabled = true; + pr_info("%s: Host Software Queue enabled\n", + mmc_hostname(host)); + } } if (host->caps2 & MMC_CAP2_AVOID_3_3V && @@ -1066,7 +1598,7 @@ retry: err = -EINVAL; goto free_card; } -done: + host->card = card; return 0; @@ -1078,15 +1610,6 @@ free_card: } /* - * Host is being removed. Free up the current card. - */ -static void mmc_sd_remove(struct mmc_host *host) -{ - mmc_remove_card(host->card); - host->card = NULL; -} - -/* * Card detection - card is alive. */ static int mmc_sd_alive(struct mmc_host *host) @@ -1111,7 +1634,8 @@ static void mmc_sd_detect(struct mmc_host *host) mmc_put_card(host->card, NULL); if (err) { - mmc_sd_remove(host); + mmc_remove_card(host->card); + host->card = NULL; mmc_claim_host(host); mmc_detach_bus(host); @@ -1120,21 +1644,90 @@ static void mmc_sd_detect(struct mmc_host *host) } } +static int sd_can_poweroff_notify(struct mmc_card *card) +{ + return card->ext_power.feature_support & SD_EXT_POWER_OFF_NOTIFY; +} + +static int sd_busy_poweroff_notify_cb(void *cb_data, bool *busy) +{ + struct sd_busy_data *data = cb_data; + struct mmc_card *card = data->card; + int err; + + /* + * Read the status register for the power management function. It's at + * one byte offset and is one byte long. The Power Off Notification + * Ready is bit 0. + */ + err = sd_read_ext_reg(card, card->ext_power.fno, card->ext_power.page, + card->ext_power.offset + 1, 1, data->reg_buf); + if (err) { + pr_warn("%s: error %d reading status reg of PM func\n", + mmc_hostname(card->host), err); + return err; + } + + *busy = !(data->reg_buf[0] & BIT(0)); + return 0; +} + +static int sd_poweroff_notify(struct mmc_card *card) +{ + struct sd_busy_data cb_data; + u8 *reg_buf; + int err; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set the Power Off Notification bit in the power management settings + * register at 2 bytes offset. + */ + err = sd_write_ext_reg(card, card->ext_power.fno, card->ext_power.page, + card->ext_power.offset + 2, BIT(0)); + if (err) { + pr_warn("%s: error %d writing Power Off Notify bit\n", + mmc_hostname(card->host), err); + goto out; + } + + /* Find out when the command is completed. */ + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, + MMC_BUSY_EXTR_SINGLE); + if (err) + goto out; + + cb_data.card = card; + cb_data.reg_buf = reg_buf; + err = __mmc_poll_for_busy(card->host, 0, SD_POWEROFF_NOTIFY_TIMEOUT_MS, + &sd_busy_poweroff_notify_cb, &cb_data); + +out: + kfree(reg_buf); + return err; +} + static int _mmc_sd_suspend(struct mmc_host *host) { + struct mmc_card *card = host->card; int err = 0; mmc_claim_host(host); - if (mmc_card_suspended(host->card)) + if (mmc_card_suspended(card)) goto out; - if (!mmc_host_is_spi(host)) + if (sd_can_poweroff_notify(card)) + err = sd_poweroff_notify(card); + else if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); if (!err) { mmc_power_off(host); - mmc_card_set_suspended(host->card); + mmc_card_set_suspended(card); } out: @@ -1143,6 +1736,19 @@ out: } /* + * Host is being removed. Free up the current card and do a graceful power-off. + */ +static void mmc_sd_remove(struct mmc_host *host) +{ + get_device(&host->card->dev); + mmc_remove_card(host->card); + + _mmc_sd_suspend(host); + + put_device(&host->card->dev); + host->card = NULL; +} +/* * Callback for suspend */ static int mmc_sd_suspend(struct mmc_host *host) @@ -1238,6 +1844,8 @@ static const struct mmc_bus_ops mmc_sd_ops = { .alive = mmc_sd_alive, .shutdown = mmc_sd_suspend, .hw_reset = mmc_sd_hw_reset, + .cache_enabled = sd_cache_enabled, + .flush_cache = sd_flush_cache, }; /* @@ -1269,6 +1877,12 @@ int mmc_attach_sd(struct mmc_host *host) goto err; } + /* + * Some SD cards claims an out of spec VDD voltage range. Let's treat + * these bits as being in-valid and especially also bit7. + */ + ocr &= ~0x7FFF; + rocr = mmc_select_voltage(host, ocr); /* diff --git a/drivers/mmc/core/sd.h b/drivers/mmc/core/sd.h index 497c026a5c5a..301dc34b8b63 100644 --- a/drivers/mmc/core/sd.h +++ b/drivers/mmc/core/sd.h @@ -4,13 +4,15 @@ #include <linux/types.h> -extern struct device_type sd_type; +extern const struct device_type sd_type; struct mmc_host; struct mmc_card; int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr); -int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card); +int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc); +int mmc_decode_scr(struct mmc_card *card); +int mmc_sd_get_ro(struct mmc_host *host); void mmc_decode_cid(struct mmc_card *card); int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, bool reinit); diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 47056d8d1bac..cd86463dd306 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/mmc/core/sd_ops.h * * Copyright 2006-2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #include <linux/slab.h> @@ -20,7 +16,23 @@ #include <linux/mmc/sd.h> #include "core.h" +#include "card.h" #include "sd_ops.h" +#include "mmc_ops.h" + +/* + * Extensive testing has shown that some specific SD cards + * require an increased command timeout to be successfully + * initialized. + */ +#define SD_APP_OP_COND_PERIOD_US (10 * 1000) /* 10ms */ +#define SD_APP_OP_COND_TIMEOUT_MS 2000 /* 2s */ + +struct sd_app_op_cond_busy_data { + struct mmc_host *host; + u32 ocr; + struct mmc_command *cmd; +}; int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) { @@ -30,6 +42,15 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) if (WARN_ON(card && card->host != host)) return -EINVAL; + /* + * UHS2 packet has APP bit so only set APP_CMD flag here. + * Will set the APP bit when assembling UHS2 packet. + */ + if (host->uhs2_sd_tran) { + host->uhs2_app_cmd = true; + return 0; + } + cmd.opcode = MMC_APP_CMD; if (card) { @@ -52,36 +73,17 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) } EXPORT_SYMBOL_GPL(mmc_app_cmd); -/** - * mmc_wait_for_app_cmd - start an application command and wait for - completion - * @host: MMC host to start command - * @card: Card to send MMC_APP_CMD to - * @cmd: MMC command to start - * @retries: maximum number of retries - * - * Sends a MMC_APP_CMD, checks the card response, sends the command - * in the parameter and waits for it to complete. Return any error - * that occurred while the command was executing. Do not attempt to - * parse the response. - */ -int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, - struct mmc_command *cmd, int retries) +static int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, + struct mmc_command *cmd) { struct mmc_request mrq = {}; - - int i, err; - - if (retries < 0) - retries = MMC_CMD_RETRIES; - - err = -EIO; + int i, err = -EIO; /* * We have to resend MMC_APP_CMD for each attempt so * we cannot use the retries field in mmc_command. */ - for (i = 0;i <= retries;i++) { + for (i = 0; i <= MMC_CMD_RETRIES; i++) { err = mmc_app_cmd(host, card); if (err) { /* no point in retrying; no APP commands allowed */ @@ -116,8 +118,6 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, return err; } -EXPORT_SYMBOL(mmc_wait_for_app_cmd); - int mmc_app_set_bus_width(struct mmc_card *card, int width) { struct mmc_command cmd = {}; @@ -136,13 +136,48 @@ int mmc_app_set_bus_width(struct mmc_card *card, int width) return -EINVAL; } - return mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES); + return mmc_wait_for_app_cmd(card->host, card, &cmd); +} + +static int sd_app_op_cond_cb(void *cb_data, bool *busy) +{ + struct sd_app_op_cond_busy_data *data = cb_data; + struct mmc_host *host = data->host; + struct mmc_command *cmd = data->cmd; + u32 ocr = data->ocr; + int err; + + *busy = false; + + err = mmc_wait_for_app_cmd(host, NULL, cmd); + if (err) + return err; + + /* If we're just probing, do a single pass. */ + if (ocr == 0) + return 0; + + /* Wait until reset completes. */ + if (mmc_host_is_spi(host)) { + if (!(cmd->resp[0] & R1_SPI_IDLE)) + return 0; + } else if (cmd->resp[0] & MMC_CARD_BUSY) { + return 0; + } + + *busy = true; + return 0; } int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) { struct mmc_command cmd = {}; - int i, err = 0; + struct sd_app_op_cond_busy_data cb_data = { + .host = host, + .ocr = ocr, + .cmd = &cmd + }; + int err; cmd.opcode = SD_APP_OP_COND; if (mmc_host_is_spi(host)) @@ -151,39 +186,34 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) cmd.arg = ocr; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; - for (i = 100; i; i--) { - err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES); - if (err) - break; - - /* if we're just probing, do a single pass */ - if (ocr == 0) - break; - - /* otherwise wait until reset completes */ - if (mmc_host_is_spi(host)) { - if (!(cmd.resp[0] & R1_SPI_IDLE)) - break; - } else { - if (cmd.resp[0] & MMC_CARD_BUSY) - break; - } + err = __mmc_poll_for_busy(host, SD_APP_OP_COND_PERIOD_US, + SD_APP_OP_COND_TIMEOUT_MS, &sd_app_op_cond_cb, + &cb_data); + if (err) + return err; - err = -ETIMEDOUT; + if (rocr && !mmc_host_is_spi(host)) + *rocr = cmd.resp[0]; - mmc_delay(10); - } + return 0; +} - if (!i) - pr_err("%s: card never left busy state\n", mmc_hostname(host)); +int mmc_send_ext_addr(struct mmc_host *host, u32 addr) +{ + struct mmc_command cmd = { + .opcode = SD_ADDR_EXT, + .arg = addr, + .flags = MMC_RSP_R1 | MMC_CMD_AC, + }; - if (rocr && !mmc_host_is_spi(host)) - *rocr = cmd.resp[0]; + if (!mmc_card_ult_capacity(host->card)) + return 0; - return err; + return mmc_wait_for_cmd(host, &cmd, 0); } -int mmc_send_if_cond(struct mmc_host *host, u32 ocr) +static int __mmc_send_if_cond(struct mmc_host *host, u32 ocr, u8 pcie_bits, + u32 *resp) { struct mmc_command cmd = {}; int err; @@ -196,7 +226,7 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr) * SD 1.0 cards. */ cmd.opcode = SD_SEND_IF_COND; - cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; + cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | pcie_bits << 8 | test_pattern; cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR; err = mmc_wait_for_cmd(host, &cmd, 0); @@ -211,6 +241,50 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr) if (result_pattern != test_pattern) return -EIO; + if (resp) + *resp = cmd.resp[0]; + + return 0; +} + +int mmc_send_if_cond(struct mmc_host *host, u32 ocr) +{ + return __mmc_send_if_cond(host, ocr, 0, NULL); +} + +int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr) +{ + u32 resp = 0; + u8 pcie_bits = 0; + int ret; + + if (host->caps2 & MMC_CAP2_SD_EXP) { + /* Probe card for SD express support via PCIe. */ + pcie_bits = 0x10; + if (host->caps2 & MMC_CAP2_SD_EXP_1_2V) + /* Probe also for 1.2V support. */ + pcie_bits = 0x30; + } + + ret = __mmc_send_if_cond(host, ocr, pcie_bits, &resp); + if (ret) + return 0; + + /* Continue with the SD express init, if the card supports it. */ + resp &= 0x3000; + if (pcie_bits && resp) { + if (resp == 0x3000) + host->ios.timing = MMC_TIMING_SD_EXP_1_2V; + else + host->ios.timing = MMC_TIMING_SD_EXP; + + /* + * According to the spec the clock shall also be gated, but + * let's leave this to the host driver for more flexibility. + */ + return host->ops->init_sd_express(host, &host->ios); + } + return 0; } @@ -286,47 +360,22 @@ int mmc_app_send_scr(struct mmc_card *card) return 0; } -int mmc_sd_switch(struct mmc_card *card, int mode, int group, +int mmc_sd_switch(struct mmc_card *card, bool mode, int group, u8 value, u8 *resp) { - struct mmc_request mrq = {}; - struct mmc_command cmd = {}; - struct mmc_data data = {}; - struct scatterlist sg; + u32 cmd_args; /* NOTE: caller guarantees resp is heap-allocated */ - mode = !!mode; value &= 0xF; + cmd_args = mode << 31 | 0x00FFFFFF; + cmd_args &= ~(0xF << (group * 4)); + cmd_args |= value << (group * 4); - mrq.cmd = &cmd; - mrq.data = &data; - - cmd.opcode = SD_SWITCH; - cmd.arg = mode << 31 | 0x00FFFFFF; - cmd.arg &= ~(0xF << (group * 4)); - cmd.arg |= value << (group * 4); - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; - - data.blksz = 64; - data.blocks = 1; - data.flags = MMC_DATA_READ; - data.sg = &sg; - data.sg_len = 1; - - sg_init_one(&sg, resp, 64); - - mmc_set_data_timeout(&data, card); - - mmc_wait_for_req(card->host, &mrq); - - if (cmd.error) - return cmd.error; - if (data.error) - return data.error; - - return 0; + return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp, + 64); } +EXPORT_SYMBOL_GPL(mmc_sd_switch); int mmc_app_sd_status(struct mmc_card *card, void *ssr) { diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h index 0e6c3d51e66d..8fffc1b29757 100644 --- a/drivers/mmc/core/sd_ops.h +++ b/drivers/mmc/core/sd_ops.h @@ -1,12 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * linux/drivers/mmc/core/sd_ops.h * * Copyright 2006-2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #ifndef _MMC_SD_OPS_H @@ -16,19 +12,18 @@ struct mmc_card; struct mmc_host; -struct mmc_command; +struct mmc_request; int mmc_app_set_bus_width(struct mmc_card *card, int width); int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int mmc_send_if_cond(struct mmc_host *host, u32 ocr); +int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr); int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca); int mmc_app_send_scr(struct mmc_card *card); -int mmc_sd_switch(struct mmc_card *card, int mode, int group, - u8 value, u8 *resp); int mmc_app_sd_status(struct mmc_card *card, void *ssr); int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card); -int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, - struct mmc_command *cmd, int retries); +int mmc_send_ext_addr(struct mmc_host *host, u32 addr); +void mmc_uhs2_prepare_cmd(struct mmc_host *host, struct mmc_request *mrq); #endif diff --git a/drivers/mmc/core/sd_uhs2.c b/drivers/mmc/core/sd_uhs2.c new file mode 100644 index 000000000000..de17d1611290 --- /dev/null +++ b/drivers/mmc/core/sd_uhs2.c @@ -0,0 +1,1304 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 Linaro Ltd + * Author: Ulf Hansson <ulf.hansson@linaro.org> + * + * Copyright (C) 2014 Intel Corp, All Rights Reserved. + * Author: Yi Sun <yi.y.sun@intel.com> + * + * Copyright (C) 2020 Genesys Logic, Inc. + * Authors: Ben Chuang <ben.chuang@genesyslogic.com.tw> + * + * Copyright (C) 2020 Linaro Limited + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org> + * + * Copyright (C) 2022 Genesys Logic, Inc. + * Authors: Jason Lai <jason.lai@genesyslogic.com.tw> + * + * Copyright (C) 2023 Genesys Logic, Inc. + * Authors: Victor Shih <victor.shih@genesyslogic.com.tw> + * + * Support for SD UHS-II cards + */ +#include <linux/err.h> +#include <linux/pm_runtime.h> + +#include <linux/mmc/host.h> +#include <linux/mmc/card.h> +#include <linux/mmc/mmc.h> +#include <linux/mmc/sd.h> +#include <linux/mmc/sd_uhs2.h> + +#include "card.h" +#include "core.h" +#include "bus.h" +#include "sd.h" +#include "sd_ops.h" +#include "mmc_ops.h" + +#define UHS2_WAIT_CFG_COMPLETE_PERIOD_US (1 * 1000) +#define UHS2_WAIT_CFG_COMPLETE_TIMEOUT_MS 100 + +static const unsigned int sd_uhs2_freqs[] = { 52000000, 26000000 }; + +struct sd_uhs2_wait_active_state_data { + struct mmc_host *host; + struct mmc_command *cmd; +}; + +static int sd_uhs2_power_up(struct mmc_host *host) +{ + if (host->ios.power_mode == MMC_POWER_ON) + return 0; + + host->ios.vdd = fls(host->ocr_avail) - 1; + host->ios.clock = host->f_init; + host->ios.timing = MMC_TIMING_UHS2_SPEED_A; + host->ios.power_mode = MMC_POWER_ON; + + return host->ops->uhs2_control(host, UHS2_SET_IOS); +} + +static int sd_uhs2_power_off(struct mmc_host *host) +{ + int err; + + if (host->ios.power_mode == MMC_POWER_OFF) + return 0; + + host->ios.vdd = 0; + host->ios.clock = 0; + host->ios.power_mode = MMC_POWER_OFF; + host->uhs2_sd_tran = false; + + err = host->ops->uhs2_control(host, UHS2_SET_IOS); + if (err) + return err; + + /* For consistency, let's restore the initial timing. */ + host->ios.timing = MMC_TIMING_LEGACY; + return 0; +} + +/* + * Run the phy initialization sequence, which mainly relies on the UHS-II host + * to check that we reach the expected electrical state, between the host and + * the card. + */ +static int sd_uhs2_phy_init(struct mmc_host *host) +{ + int err; + + err = host->ops->uhs2_control(host, UHS2_PHY_INIT); + if (err) { + pr_debug("%s: failed to initial phy for UHS-II!\n", + mmc_hostname(host)); + } + + return err; +} + +/* + * sd_uhs2_cmd_assemble() - build up UHS-II command packet which is embedded in + * mmc_command structure + * @cmd: MMC command to executed + * @uhs2_cmd: UHS2 command corresponded to MMC command + * @header: Header field of UHS-II command cxpacket + * @arg: Argument field of UHS-II command packet + * @payload: Payload field of UHS-II command packet + * @plen: Payload length + * @resp: Response buffer is allocated by caller and it is used to keep + * the response of CM-TRAN command. For SD-TRAN command, uhs2_resp + * should be null and SD-TRAN command response should be stored in + * resp of mmc_command. + * @resp_len: Response buffer length + * + * The uhs2_command structure contains message packets which are transmited/ + * received on UHS-II bus. This function fills in the contents of uhs2_command + * structure and embededs UHS2 command into mmc_command structure, which is used + * in legacy SD operation functions. + * + */ +static void sd_uhs2_cmd_assemble(struct mmc_command *cmd, + struct uhs2_command *uhs2_cmd, + u8 plen, u8 resp_len) +{ + uhs2_cmd->payload_len = plen * sizeof(u32); + uhs2_cmd->packet_len = uhs2_cmd->payload_len + 4; + + cmd->uhs2_cmd = uhs2_cmd; + cmd->uhs2_cmd->uhs2_resp_len = resp_len; +} + +/* + * Do the early initialization of the card, by sending the device init broadcast + * command and wait for the process to be completed. + */ +static int sd_uhs2_dev_init(struct mmc_host *host) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + u32 cnt; + u32 dap, gap, resp_gap; + u32 payload0; + u8 gd = 0; + int err; + + dap = host->uhs2_caps.dap; + gap = host->uhs2_caps.gap; + + /* + * Refer to UHS-II Addendum Version 1.02 Figure 6-21 to see DEVICE_INIT CCMD format. + * Head: + * - Control Write(R/W=1) with 4-Byte payload(PLEN=01b). + * - IOADR = CMD_BASE + 002h + * Payload: + * - bit [3:0] : GAP(Group Allocated Power) + * - bit [7:4] : GD(Group Descriptor) + * - bit [11] : Complete Flag + * - bit [15:12]: DAP(Device Allocated Power) + */ + uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD; + uhs2_cmd.arg = ((UHS2_DEV_CMD_DEVICE_INIT & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_4B | + (UHS2_DEV_CMD_DEVICE_INIT >> 8); + + /* + * Refer to UHS-II Addendum Version 1.02 section 6.3.1. + * Max. time from DEVICE_INIT CCMD EOP reception on Device + * Rx to its SOP transmission on Device Tx(Tfwd_init_cmd) is + * 1 second. + */ + cmd.busy_timeout = 1000; + + /* + * Refer to UHS-II Addendum Version 1.02 section 6.2.6.3. + * Let's retry the DEVICE_INIT command no more than 30 times. + */ + for (cnt = 0; cnt < 30; cnt++) { + payload0 = ((dap & 0xF) << 12) | + UHS2_DEV_INIT_COMPLETE_FLAG | + ((gd & 0xF) << 4) | + (gap & 0xF); + uhs2_cmd.payload[0] = (__force __be32)payload0; + + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_DEV_INIT_PAYLOAD_LEN, + UHS2_DEV_INIT_RESP_LEN); + + err = mmc_wait_for_cmd(host, &cmd, 0); + + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + continue; + } + + if (uhs2_cmd.uhs2_resp[3] != (UHS2_DEV_CMD_DEVICE_INIT & 0xFF)) { + pr_err("%s: DEVICE_INIT response is wrong!\n", + mmc_hostname(host)); + return -EIO; + } + + if (uhs2_cmd.uhs2_resp[5] & 0x8) { + host->uhs2_caps.group_desc = gd; + return 0; + } + resp_gap = uhs2_cmd.uhs2_resp[4] & 0x0F; + if (gap == resp_gap) + gd++; + } + + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + return 0; +} + +/* + * Run the enumeration process by sending the enumerate command to the card. + * Note that, we currently support only the point to point connection, which + * means only one card can be attached per host/slot. + */ +static int sd_uhs2_enum(struct mmc_host *host, u32 *node_id) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + u32 payload0; + u8 id_f = 0xF, id_l = 0x0; + int err; + + /* + * Refer to UHS-II Addendum Version 1.02 Figure 6-28 to see ENUMERATE CCMD format. + * Header: + * - Control Write(R/W=1) with 4-Byte payload(PLEN=01b). + * - IOADR = CMD_BASE + 003h + * Payload: + * - bit [3:0]: ID_L(Last Node ID) + * - bit [7:4]: ID_F(First Node ID) + */ + uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD; + uhs2_cmd.arg = ((UHS2_DEV_CMD_ENUMERATE & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_4B | + (UHS2_DEV_CMD_ENUMERATE >> 8); + + payload0 = (id_f << 4) | id_l; + uhs2_cmd.payload[0] = cpu_to_be32(payload0); + + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_DEV_ENUM_PAYLOAD_LEN, UHS2_DEV_ENUM_RESP_LEN); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + if (uhs2_cmd.uhs2_resp[3] != (UHS2_DEV_CMD_ENUMERATE & 0xFF)) { + pr_err("%s: ENUMERATE response is wrong!\n", + mmc_hostname(host)); + return -EIO; + } + + id_f = (uhs2_cmd.uhs2_resp[4] >> 4) & 0xF; + id_l = uhs2_cmd.uhs2_resp[4] & 0xF; + *node_id = id_f; + + return 0; +} + +/* + * Read the UHS-II configuration registers (CFG_REG) of the card, by sending it + * commands and by parsing the responses. Store a copy of the relevant data in + * card->uhs2_config. + */ +static int sd_uhs2_config_read(struct mmc_host *host, struct mmc_card *card) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + u32 cap; + int err; + + /* + * Use Control Read CCMD to read Generic Capability from Configuration Register. + * - Control Write(R/W=1) with 4-Byte payload(PLEN=01b). + * - IOADR = Generic Capability Register(CFG_BASE + 000h) + */ + uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD | card->uhs2_config.node_id; + uhs2_cmd.arg = ((UHS2_DEV_CONFIG_GEN_CAPS & 0xFF) << 8) | + UHS2_NATIVE_CMD_READ | + UHS2_NATIVE_CMD_PLEN_4B | + (UHS2_DEV_CONFIG_GEN_CAPS >> 8); + + /* + * There is no payload because per spec, there should be + * no payload field for read CCMD. + * Plen is set in arg. Per spec, plen for read CCMD + * represents the len of read data which is assigned in payload + * of following RES (p136). + */ + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + /* + * Generic Capability Register: + * bit [7:0] : Reserved + * bit [13:8] : Device-Specific Number of Lanes and Functionality + * bit 8: 2L-HD + * bit 9: 2D-1U FD + * bit 10: 1D-2U FD + * bit 11: 2D-2U FD + * Others: Reserved + * bit [14] : DADR Length + * 0: 4 bytes + * 1: Reserved + * bit [23:16]: Application Type + * bit 16: 0=Non-SD memory, 1=SD memory + * bit 17: 0=Non-SDIO, 1=SDIO + * bit 18: 0=Card, 1=Embedded + * bit [63:24]: Reserved + */ + cap = cmd.resp[0]; + card->uhs2_config.n_lanes = + (cap >> UHS2_DEV_CONFIG_N_LANES_POS) & + UHS2_DEV_CONFIG_N_LANES_MASK; + card->uhs2_config.dadr_len = + (cap >> UHS2_DEV_CONFIG_DADR_POS) & + UHS2_DEV_CONFIG_DADR_MASK; + card->uhs2_config.app_type = + (cap >> UHS2_DEV_CONFIG_APP_POS) & + UHS2_DEV_CONFIG_APP_MASK; + + /* + * Use Control Read CCMD to read PHY Capability from Configuration Register. + * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b). + * - IOADR = PHY Capability Register(CFG_BASE + 002h) + */ + uhs2_cmd.arg = ((UHS2_DEV_CONFIG_PHY_CAPS & 0xFF) << 8) | + UHS2_NATIVE_CMD_READ | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_PHY_CAPS >> 8); + + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + /* + * PHY Capability Register: + * bit [3:0] : PHY Minor Revision + * bit [5:4] : PHY Major Revision + * bit [15] : Support Hibernate Mode + * 0: Not support Hibernate Mode + * 1: Support Hibernate Mode + * bit [31:16]: Reserved + * bit [35:32]: Device-Specific N_LSS_SYN + * bit [39:36]: Device-Specific N_LSS_DIR + * bit [63:40]: Reserved + */ + cap = cmd.resp[0]; + card->uhs2_config.phy_minor_rev = + cap & UHS2_DEV_CONFIG_PHY_MINOR_MASK; + card->uhs2_config.phy_major_rev = + (cap >> UHS2_DEV_CONFIG_PHY_MAJOR_POS) & + UHS2_DEV_CONFIG_PHY_MAJOR_MASK; + card->uhs2_config.can_hibernate = + (cap >> UHS2_DEV_CONFIG_CAN_HIBER_POS) & + UHS2_DEV_CONFIG_CAN_HIBER_MASK; + + cap = cmd.resp[1]; + card->uhs2_config.n_lss_sync = + cap & UHS2_DEV_CONFIG_N_LSS_SYN_MASK; + card->uhs2_config.n_lss_dir = + (cap >> UHS2_DEV_CONFIG_N_LSS_DIR_POS) & + UHS2_DEV_CONFIG_N_LSS_DIR_MASK; + if (card->uhs2_config.n_lss_sync == 0) + card->uhs2_config.n_lss_sync = 16 << 2; + else + card->uhs2_config.n_lss_sync <<= 2; + + if (card->uhs2_config.n_lss_dir == 0) + card->uhs2_config.n_lss_dir = 16 << 3; + else + card->uhs2_config.n_lss_dir <<= 3; + + /* + * Use Control Read CCMD to read LINK/TRAN Capability from Configuration Register. + * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b). + * - IOADR = LINK/TRAN Capability Register(CFG_BASE + 004h) + */ + uhs2_cmd.arg = ((UHS2_DEV_CONFIG_LINK_TRAN_CAPS & 0xFF) << 8) | + UHS2_NATIVE_CMD_READ | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_LINK_TRAN_CAPS >> 8); + + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + /* + * LINK/TRAN Capability Register: + * bit [3:0] : LINK_TRAN Minor Revision + * bit [5:4] : LINK/TRAN Major Revision + * bit [7:6] : Reserved + * bit [15:8] : Device-Specific N_FCU + * bit [18:16]: Device Type + * 001b=Host + * 010b=Device + * 011b=Reserved for CMD issuable Device + * bit [19] : Reserved + * bit [31:20]: Device-Specific MAX_BLKLEN + * bit [39:32]: Device-Specific N_DATA_GAP + * bit [63:40]: Reserved + */ + cap = cmd.resp[0]; + card->uhs2_config.link_minor_rev = + cap & UHS2_DEV_CONFIG_LT_MINOR_MASK; + card->uhs2_config.link_major_rev = + (cap >> UHS2_DEV_CONFIG_LT_MAJOR_POS) & + UHS2_DEV_CONFIG_LT_MAJOR_MASK; + card->uhs2_config.n_fcu = + (cap >> UHS2_DEV_CONFIG_N_FCU_POS) & + UHS2_DEV_CONFIG_N_FCU_MASK; + card->uhs2_config.dev_type = + (cap >> UHS2_DEV_CONFIG_DEV_TYPE_POS) & + UHS2_DEV_CONFIG_DEV_TYPE_MASK; + card->uhs2_config.maxblk_len = + (cap >> UHS2_DEV_CONFIG_MAX_BLK_LEN_POS) & + UHS2_DEV_CONFIG_MAX_BLK_LEN_MASK; + + cap = cmd.resp[1]; + card->uhs2_config.n_data_gap = + cap & UHS2_DEV_CONFIG_N_DATA_GAP_MASK; + if (card->uhs2_config.n_fcu == 0) + card->uhs2_config.n_fcu = 256; + + return 0; +} + +/* + * Based on the card's and host's UHS-II capabilities, let's update the + * configuration of the card and the host. This may also include to move to a + * greater speed range/mode. Depending on the updated configuration, we may need + * to do a soft reset of the card via sending it a GO_DORMANT_STATE command. + * + * In the final step, let's check if the card signals "config completion", which + * indicates that the card has moved from config state into active state. + */ +static int sd_uhs2_config_write(struct mmc_host *host, struct mmc_card *card) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + u32 payload0, payload1; + u8 nMinDataGap; + int err; + + /* + * Use Control Write CCMD to set Generic Setting in Configuration Register. + * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b). + * - IOADR = Generic Setting Register(CFG_BASE + 008h) + * - Payload = New contents to be written to Generic Setting Register + */ + uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD | card->uhs2_config.node_id; + uhs2_cmd.arg = ((UHS2_DEV_CONFIG_GEN_SET & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_GEN_SET >> 8); + + /* + * Most UHS-II cards only support FD and 2L-HD mode. Other lane numbers + * defined in UHS-II addendem Ver1.01 are optional. + */ + host->uhs2_caps.n_lanes_set = UHS2_DEV_CONFIG_GEN_SET_2L_FD_HD; + card->uhs2_config.n_lanes_set = UHS2_DEV_CONFIG_GEN_SET_2L_FD_HD; + + payload0 = card->uhs2_config.n_lanes_set << UHS2_DEV_CONFIG_N_LANES_POS; + payload1 = 0; + uhs2_cmd.payload[0] = cpu_to_be32(payload0); + uhs2_cmd.payload[1] = cpu_to_be32(payload1); + + /* + * There is no payload because per spec, there should be + * no payload field for read CCMD. + * Plen is set in arg. Per spec, plen for read CCMD + * represents the len of read data which is assigned in payload + * of following RES (p136). + */ + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_CFG_WRITE_PAYLOAD_LEN, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + /* + * Use Control Write CCMD to set PHY Setting in Configuration Register. + * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b). + * - IOADR = PHY Setting Register(CFG_BASE + 00Ah) + * - Payload = New contents to be written to PHY Setting Register + */ + uhs2_cmd.arg = ((UHS2_DEV_CONFIG_PHY_SET & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_PHY_SET >> 8); + + if (host->uhs2_caps.speed_range == UHS2_DEV_CONFIG_PHY_SET_SPEED_B) { + if (card->uhs2_config.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD && + host->uhs2_caps.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD) { + /* Support HD */ + host->ios.timing = MMC_TIMING_UHS2_SPEED_B_HD; + nMinDataGap = 1; + } else { + /* Only support 2L-FD so far */ + host->ios.timing = MMC_TIMING_UHS2_SPEED_B; + nMinDataGap = 3; + } + card->uhs2_config.speed_range_set = UHS2_DEV_CONFIG_PHY_SET_SPEED_B; + } else { + if (card->uhs2_config.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD && + host->uhs2_caps.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD) { + /* Support HD */ + host->ios.timing = MMC_TIMING_UHS2_SPEED_A_HD; + nMinDataGap = 1; + } else { + /* Only support 2L-FD so far */ + host->ios.timing = MMC_TIMING_UHS2_SPEED_A; + nMinDataGap = 3; + } + card->uhs2_config.speed_range_set = UHS2_DEV_CONFIG_PHY_SET_SPEED_A; + } + + payload0 = card->uhs2_config.speed_range_set << UHS2_DEV_CONFIG_PHY_SET_SPEED_POS; + + card->uhs2_config.n_lss_sync_set = (max(card->uhs2_config.n_lss_sync, + host->uhs2_caps.n_lss_sync) >> 2) & + UHS2_DEV_CONFIG_N_LSS_SYN_MASK; + host->uhs2_caps.n_lss_sync_set = card->uhs2_config.n_lss_sync_set; + + card->uhs2_config.n_lss_dir_set = (max(card->uhs2_config.n_lss_dir, + host->uhs2_caps.n_lss_dir) >> 3) & + UHS2_DEV_CONFIG_N_LSS_DIR_MASK; + host->uhs2_caps.n_lss_dir_set = card->uhs2_config.n_lss_dir_set; + + payload1 = (card->uhs2_config.n_lss_dir_set << UHS2_DEV_CONFIG_N_LSS_DIR_POS) | + card->uhs2_config.n_lss_sync_set; + uhs2_cmd.payload[0] = cpu_to_be32(payload0); + uhs2_cmd.payload[1] = cpu_to_be32(payload1); + + memset(uhs2_cmd.uhs2_resp, 0, sizeof(uhs2_cmd.uhs2_resp)); + + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_CFG_WRITE_PAYLOAD_LEN, + UHS2_CFG_WRITE_PHY_SET_RESP_LEN); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + if ((uhs2_cmd.uhs2_resp[2] & 0x80)) { + pr_err("%s: %s: UHS2 CMD not accepted, resp= 0x%x!\n", + mmc_hostname(host), __func__, uhs2_cmd.uhs2_resp[2]); + return -EIO; + } + + /* + * Use Control Write CCMD to set LINK/TRAN Setting in Configuration Register. + * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b). + * - IOADR = LINK/TRAN Setting Register(CFG_BASE + 00Ch) + * - Payload = New contents to be written to LINK/TRAN Setting Register + */ + uhs2_cmd.arg = ((UHS2_DEV_CONFIG_LINK_TRAN_SET & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_LINK_TRAN_SET >> 8); + + if (card->uhs2_config.app_type == UHS2_DEV_CONFIG_APP_SD_MEM) + card->uhs2_config.maxblk_len_set = UHS2_DEV_CONFIG_LT_SET_MAX_BLK_LEN; + else + card->uhs2_config.maxblk_len_set = min(card->uhs2_config.maxblk_len, + host->uhs2_caps.maxblk_len); + host->uhs2_caps.maxblk_len_set = card->uhs2_config.maxblk_len_set; + + card->uhs2_config.n_fcu_set = min(card->uhs2_config.n_fcu, host->uhs2_caps.n_fcu); + host->uhs2_caps.n_fcu_set = card->uhs2_config.n_fcu_set; + + card->uhs2_config.n_data_gap_set = max(nMinDataGap, card->uhs2_config.n_data_gap); + host->uhs2_caps.n_data_gap_set = card->uhs2_config.n_data_gap_set; + + host->uhs2_caps.max_retry_set = 3; + card->uhs2_config.max_retry_set = host->uhs2_caps.max_retry_set; + + payload0 = (card->uhs2_config.maxblk_len_set << UHS2_DEV_CONFIG_MAX_BLK_LEN_POS) | + (card->uhs2_config.max_retry_set << UHS2_DEV_CONFIG_LT_SET_MAX_RETRY_POS) | + (card->uhs2_config.n_fcu_set << UHS2_DEV_CONFIG_N_FCU_POS); + payload1 = card->uhs2_config.n_data_gap_set; + uhs2_cmd.payload[0] = cpu_to_be32(payload0); + uhs2_cmd.payload[1] = cpu_to_be32(payload1); + + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_CFG_WRITE_PAYLOAD_LEN, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + /* + * Use Control Write CCMD to set Config Completion(payload bit 63) in Generic Setting + * Register. + * Header: + * - Control Write(R/W=1) with 8-Byte payload(PLEN=10b). + * - IOADR = PGeneric Setting Register(CFG_BASE + 008h) + * Payload: + * - bit [63]: Config Completion + * + * DLSM transits to Active state immediately when Config Completion is set to 1. + */ + uhs2_cmd.arg = ((UHS2_DEV_CONFIG_GEN_SET & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_GEN_SET >> 8); + + payload0 = 0; + payload1 = UHS2_DEV_CONFIG_GEN_SET_CFG_COMPLETE; + uhs2_cmd.payload[0] = cpu_to_be32(payload0); + uhs2_cmd.payload[1] = cpu_to_be32(payload1); + + memset(uhs2_cmd.uhs2_resp, 0, sizeof(uhs2_cmd.uhs2_resp)); + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_CFG_WRITE_PAYLOAD_LEN, + UHS2_CFG_WRITE_GENERIC_SET_RESP_LEN); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + /* Set host Config Setting registers */ + err = host->ops->uhs2_control(host, UHS2_SET_CONFIG); + if (err) { + pr_err("%s: %s: UHS2 SET_CONFIG fail!\n", mmc_hostname(host), __func__); + return err; + } + + return 0; +} + +static int sd_uhs2_go_dormant(struct mmc_host *host, u32 node_id) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + int err; + + /* Disable Normal INT */ + err = host->ops->uhs2_control(host, UHS2_DISABLE_INT); + if (err) { + pr_err("%s: %s: UHS2 DISABLE_INT fail!\n", + mmc_hostname(host), __func__); + return err; + } + + /* + * Refer to UHS-II Addendum Version 1.02 Figure 6-17 to see GO_DORMANT_STATE CCMD format. + * Header: + * - Control Write(R/W=1) with 4-Byte payload(PLEN=01b). + * - IOADR = CMD_BASE + 001h + * Payload: + * - bit [7]: HBR(Entry to Hibernate Mode) + * 1: Host intends to enter Hibernate mode during Dormant state. + * The default setting is 0 because hibernate is currently not supported. + */ + uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD | node_id; + uhs2_cmd.arg = ((UHS2_DEV_CMD_GO_DORMANT_STATE & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_4B | + (UHS2_DEV_CMD_GO_DORMANT_STATE >> 8); + + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, UHS2_GO_DORMANT_PAYLOAD_LEN, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + /* Check Dormant State in Present */ + err = host->ops->uhs2_control(host, UHS2_CHECK_DORMANT); + if (err) + return err; + + /* Disable UHS2 card clock */ + err = host->ops->uhs2_control(host, UHS2_DISABLE_CLK); + if (err) + return err; + + /* Restore sd clock */ + mmc_delay(5); + err = host->ops->uhs2_control(host, UHS2_ENABLE_CLK); + if (err) + return err; + + /* Enable Normal INT */ + err = host->ops->uhs2_control(host, UHS2_ENABLE_INT); + if (err) + return err; + + /* Detect UHS2 */ + err = host->ops->uhs2_control(host, UHS2_PHY_INIT); + if (err) + return err; + + return 0; +} + +static int sd_uhs2_wait_active_state_cb(void *cb_data, bool *busy) +{ + struct sd_uhs2_wait_active_state_data *data = cb_data; + struct mmc_host *host = data->host; + struct mmc_command *cmd = data->cmd; + int err; + + err = mmc_wait_for_cmd(host, cmd, 0); + if (err) + return err; + + if (cmd->resp[1] & UHS2_DEV_CONFIG_GEN_SET_CFG_COMPLETE) + *busy = false; + else + *busy = true; + + return 0; +} + +static int sd_uhs2_go_dormant_state(struct mmc_host *host, u32 node_id) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + int err; + struct sd_uhs2_wait_active_state_data cb_data = { + .host = host, + .cmd = &cmd + }; + + err = sd_uhs2_go_dormant(host, node_id); + if (err) { + pr_err("%s: %s: UHS2 GO_DORMANT_STATE fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return err; + } + + /* + * Use Control Read CCMD to check Config Completion(bit 63) in Generic Setting Register. + * - Control Read(R/W=0) with 8-Byte payload(PLEN=10b). + * - IOADR = Generic Setting Register(CFG_BASE + 008h) + * + * When UHS-II card been switched to new speed mode, it will set Config Completion to 1. + */ + uhs2_cmd.header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD | node_id; + uhs2_cmd.arg = ((UHS2_DEV_CONFIG_GEN_SET & 0xFF) << 8) | + UHS2_NATIVE_CMD_READ | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_GEN_SET >> 8); + + sd_uhs2_cmd_assemble(&cmd, &uhs2_cmd, 0, 0); + err = __mmc_poll_for_busy(host, UHS2_WAIT_CFG_COMPLETE_PERIOD_US, + UHS2_WAIT_CFG_COMPLETE_TIMEOUT_MS, + &sd_uhs2_wait_active_state_cb, &cb_data); + if (err) { + pr_err("%s: %s: Not switch to Active in 100 ms\n", mmc_hostname(host), __func__); + return err; + } + + return 0; +} + +/* + * Allocate the data structure for the mmc_card and run the UHS-II specific + * initialization sequence. + */ +static int sd_uhs2_init_card(struct mmc_host *host, struct mmc_card *oldcard) +{ + struct mmc_card *card; + u32 node_id = 0; + int err; + + err = sd_uhs2_dev_init(host); + if (err) + return err; + + err = sd_uhs2_enum(host, &node_id); + if (err) + return err; + + if (oldcard) { + card = oldcard; + } else { + card = mmc_alloc_card(host, &sd_type); + if (IS_ERR(card)) + return PTR_ERR(card); + } + + card->uhs2_config.node_id = node_id; + card->type = MMC_TYPE_SD; + + err = sd_uhs2_config_read(host, card); + if (err) + goto err; + + err = sd_uhs2_config_write(host, card); + if (err) + goto err; + + /* If change speed to Range B, need to GO_DORMANT_STATE */ + if (host->ios.timing == MMC_TIMING_UHS2_SPEED_B || + host->ios.timing == MMC_TIMING_UHS2_SPEED_B_HD) { + err = sd_uhs2_go_dormant_state(host, node_id); + if (err) + goto err; + } + + host->uhs2_sd_tran = true; + host->card = card; + return 0; + +err: + if (!oldcard) + mmc_remove_card(card); + return err; +} + +/* + * Initialize the UHS-II card through the SD-TRAN transport layer. This enables + * commands/requests to be backwards compatible through the legacy SD protocol. + * UHS-II cards has a specific power limit specified for VDD1/VDD2, that should + * be set through a legacy CMD6. Note that, the power limit that becomes set, + * survives a soft reset through the GO_DORMANT_STATE command. + */ +static int sd_uhs2_legacy_init(struct mmc_host *host, struct mmc_card *card, + bool reinit) +{ + int err; + u32 cid[4]; + u32 ocr; + u32 rocr; + u8 *status; + int ro; + + /* Send CMD0 to reset SD card */ + err = __mmc_go_idle(host); + if (err) + return err; + + mmc_delay(1); + + /* Send CMD8 to communicate SD interface operation condition */ + err = mmc_send_if_cond(host, host->ocr_avail); + if (err) + return err; + + /* + * Probe SD card working voltage. + */ + err = mmc_send_app_op_cond(host, 0, &ocr); + if (err) + return err; + + card->ocr = ocr; + + /* + * Some SD cards claims an out of spec VDD voltage range. Let's treat + * these bits as being in-valid and especially also bit7. + */ + ocr &= ~0x7FFF; + rocr = mmc_select_voltage(host, ocr); + /* + * Some cards have zero value of rocr in UHS-II mode. Assign host's + * ocr value to rocr. + */ + if (!rocr) + rocr = host->ocr_avail; + + rocr |= (SD_OCR_CCS | SD_OCR_XPC); + + /* Wait SD power on ready */ + ocr = rocr; + + err = mmc_send_app_op_cond(host, ocr, &rocr); + if (err) + return err; + + err = mmc_send_cid(host, cid); + if (err) + return err; + + if (reinit) { + if (memcmp(cid, card->raw_cid, sizeof(cid)) != 0) { + pr_debug("%s: Perhaps the card was replaced\n", + mmc_hostname(host)); + return -ENOENT; + } + } else { + memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); + mmc_decode_cid(card); + } + + /* + * For native busses: get card RCA and quit open drain mode. + */ + err = mmc_send_relative_addr(host, &card->rca); + if (err) + return err; + + err = mmc_sd_get_csd(card, false); + if (err) + return err; + + /* + * Select card, as all following commands rely on that. + */ + err = mmc_select_card(card); + if (err) + return err; + + /* + * Fetch SCR from card. + */ + err = mmc_app_send_scr(card); + if (err) + return err; + + err = mmc_decode_scr(card); + if (err) + return err; + + /* + * Switch to high power consumption mode. + * Even switch failed, sd card can still work at lower power consumption mode, but + * performance will be lower than high power consumption mode. + */ + status = kmalloc(64, GFP_KERNEL); + if (!status) + return -ENOMEM; + + if (!(card->csd.cmdclass & CCC_SWITCH)) { + pr_warn("%s: card lacks mandatory switch function, performance might suffer\n", + mmc_hostname(card->host)); + } else { + /* + * Send CMD6 to set Maximum Power Consumption to get better + * performance. Ignore errors and continue. + */ + err = mmc_sd_switch(card, 0, 3, SD4_SET_POWER_LIMIT_1_80W, status); + if (!err) + mmc_sd_switch(card, 1, 3, SD4_SET_POWER_LIMIT_1_80W, status); + } + + /* + * Check if read-only switch is active. + */ + ro = mmc_sd_get_ro(host); + if (ro < 0) + pr_warn("%s: host does not support read-only switch, assuming write-enable\n", + mmc_hostname(host)); + else if (ro > 0) + mmc_card_set_readonly(card); + + kfree(status); + return 0; +} + +static int sd_uhs2_reinit(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + int err; + + err = sd_uhs2_power_up(host); + if (err) + return err; + + err = sd_uhs2_phy_init(host); + if (err) + return err; + + err = sd_uhs2_init_card(host, card); + if (err) + return err; + + return sd_uhs2_legacy_init(host, card, true); +} + +static void sd_uhs2_remove(struct mmc_host *host) +{ + mmc_remove_card(host->card); + host->card = NULL; +} + +static int sd_uhs2_alive(struct mmc_host *host) +{ + return mmc_send_status(host->card, NULL); +} + +static void sd_uhs2_detect(struct mmc_host *host) +{ + int err; + + mmc_get_card(host->card, NULL); + err = _mmc_detect_card_removed(host); + mmc_put_card(host->card, NULL); + + if (err) { + sd_uhs2_remove(host); + + mmc_claim_host(host); + mmc_detach_bus(host); + sd_uhs2_power_off(host); + mmc_release_host(host); + } +} + +static int _sd_uhs2_suspend(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + + mmc_claim_host(host); + + if (mmc_card_suspended(card)) + goto out; + + sd_uhs2_power_off(host); + mmc_card_set_suspended(card); + +out: + mmc_release_host(host); + return 0; +} + +/* + * Callback for suspend + */ +static int sd_uhs2_suspend(struct mmc_host *host) +{ + int err; + + err = _sd_uhs2_suspend(host); + if (!err) { + pm_runtime_disable(&host->card->dev); + pm_runtime_set_suspended(&host->card->dev); + } + + return err; +} + +/* + * This function tries to determine if the same card is still present + * and, if so, restore all state to it. + */ +static int _mmc_sd_uhs2_resume(struct mmc_host *host) +{ + int err = 0; + + mmc_claim_host(host); + + if (!mmc_card_suspended(host->card)) + goto out; + + /* Power up UHS2 SD card and re-initialize it. */ + err = sd_uhs2_reinit(host); + mmc_card_clr_suspended(host->card); + +out: + mmc_release_host(host); + return err; +} + +/* + * Callback for resume + */ +static int sd_uhs2_resume(struct mmc_host *host) +{ + pm_runtime_enable(&host->card->dev); + return 0; +} + +/* + * Callback for runtime_suspend. + */ +static int sd_uhs2_runtime_suspend(struct mmc_host *host) +{ + int err; + + if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) + return 0; + + err = _sd_uhs2_suspend(host); + if (err) + pr_err("%s: error %d doing aggressive suspend\n", mmc_hostname(host), err); + + return err; +} + +static int sd_uhs2_runtime_resume(struct mmc_host *host) +{ + int err; + + err = _mmc_sd_uhs2_resume(host); + if (err && err != -ENOMEDIUM) + pr_err("%s: error %d doing runtime resume\n", mmc_hostname(host), err); + + return err; +} + +static int sd_uhs2_hw_reset(struct mmc_host *host) +{ + sd_uhs2_power_off(host); + /* Wait at least 1 ms according to SD spec */ + mmc_delay(1); + + return sd_uhs2_reinit(host); +} + +static const struct mmc_bus_ops sd_uhs2_ops = { + .remove = sd_uhs2_remove, + .alive = sd_uhs2_alive, + .detect = sd_uhs2_detect, + .suspend = sd_uhs2_suspend, + .resume = sd_uhs2_resume, + .runtime_suspend = sd_uhs2_runtime_suspend, + .runtime_resume = sd_uhs2_runtime_resume, + .shutdown = sd_uhs2_suspend, + .hw_reset = sd_uhs2_hw_reset, +}; + +static int sd_uhs2_attach(struct mmc_host *host) +{ + int err; + + err = sd_uhs2_power_up(host); + if (err) + goto err; + + err = sd_uhs2_phy_init(host); + if (err) + goto err; + + err = sd_uhs2_init_card(host, NULL); + if (err) + goto err; + + err = sd_uhs2_legacy_init(host, host->card, false); + if (err) + goto remove_card; + + mmc_attach_bus(host, &sd_uhs2_ops); + + mmc_release_host(host); + + err = mmc_add_card(host->card); + if (err) + goto remove_card; + + mmc_claim_host(host); + return 0; + +remove_card: + sd_uhs2_remove(host); + mmc_claim_host(host); +err: + mmc_detach_bus(host); + sd_uhs2_power_off(host); + return err; +} + +/** + * mmc_attach_sd_uhs2 - select UHS2 interface + * @host: MMC host + * + * Try to select UHS2 interface and initialize the bus for a given + * frequency, @freq. + * + * Return: 0 on success, non-zero error on failure + */ +int mmc_attach_sd_uhs2(struct mmc_host *host) +{ + int i, err; + + if (!(host->caps2 & MMC_CAP2_SD_UHS2)) + return -EOPNOTSUPP; + + /* Turn off the legacy SD interface before trying with UHS-II. */ + mmc_power_off(host); + + /* + * Start UHS-II initialization at 52MHz and possibly make a retry at + * 26MHz according to the spec. It's required that the host driver + * validates ios->clock, to set a rate within the correct range. + */ + for (i = 0; i < ARRAY_SIZE(sd_uhs2_freqs); i++) { + host->f_init = sd_uhs2_freqs[i]; + pr_debug("%s: %s: trying to init UHS-II card at %u Hz\n", + mmc_hostname(host), __func__, host->f_init); + err = sd_uhs2_attach(host); + if (!err) + break; + } + + return err; +} + +/* + * mmc_uhs2_prepare_cmd - prepare for SD command packet + * @host: MMC host + * @mrq: MMC request + * + * Initialize and fill in a header and a payload of SD command packet. + * The caller should allocate uhs2_command in host->cmd->uhs2_cmd in + * advance. + * + * Return: 0 on success, non-zero error on failure + */ +void mmc_uhs2_prepare_cmd(struct mmc_host *host, struct mmc_request *mrq) +{ + struct mmc_command *cmd; + struct uhs2_command *uhs2_cmd; + u8 plen; + + cmd = mrq->cmd; + cmd->uhs2_cmd = &mrq->uhs2_cmd; + uhs2_cmd = cmd->uhs2_cmd; + uhs2_cmd->header = host->card->uhs2_config.node_id; + if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) + uhs2_cmd->header |= UHS2_PACKET_TYPE_DCMD; + else + uhs2_cmd->header |= UHS2_PACKET_TYPE_CCMD; + + uhs2_cmd->arg = cmd->opcode << UHS2_SD_CMD_INDEX_POS; + if (host->uhs2_app_cmd) { + uhs2_cmd->arg |= UHS2_SD_CMD_APP; + host->uhs2_app_cmd = false; + } + + /* + * UHS-II Addendum 7.2.1.2 + * Host may set DM to 1 for DCMD which supports multi-block read/write regardless of + * data transfer length (e.g., CMD18, CMD25). Otherwise, it shall not set DM to 1. + * (e.g., CMD6, CMD17, CMD24). These rules are also applied to other multi-block read/write + * commands defined in other Part of SD specifications (for example, Host may set DM to 1 + * for ACMD18 or ACMD25). + */ + if (mmc_op_multi(cmd->opcode)) + cmd->uhs2_cmd->tmode_half_duplex = mmc_card_uhs2_hd_mode(host); + else + cmd->uhs2_cmd->tmode_half_duplex = 0; + + uhs2_cmd = cmd->uhs2_cmd; + plen = 2; /* at the maximum */ + + if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC && + cmd->uhs2_cmd->tmode_half_duplex) { + if (mmc_card_uhs2_hd_mode(host)) + uhs2_cmd->arg |= UHS2_DCMD_2L_HD_MODE; + + uhs2_cmd->arg |= UHS2_DCMD_LM_TLEN_EXIST; + + if (cmd->data->blocks == 1 && + cmd->data->blksz != 512 && + cmd->opcode != MMC_READ_SINGLE_BLOCK && + cmd->opcode != MMC_WRITE_BLOCK) { + uhs2_cmd->arg |= UHS2_DCMD_TLUM_BYTE_MODE; + uhs2_cmd->payload[1] = cpu_to_be32(cmd->data->blksz); + } else { + uhs2_cmd->payload[1] = cpu_to_be32(cmd->data->blocks); + } + } else { + plen = 1; + } + + uhs2_cmd->payload[0] = cpu_to_be32(cmd->arg); + sd_uhs2_cmd_assemble(cmd, uhs2_cmd, plen, 0); +} diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index d8e17ea6126d..83085e76486a 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1,16 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/mmc/sdio.c * * Copyright 2006-2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #include <linux/err.h> #include <linux/pm_runtime.h> +#include <linux/sysfs.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> @@ -31,6 +28,48 @@ #include "sdio_ops.h" #include "sdio_cis.h" +MMC_DEV_ATTR(vendor, "0x%04x\n", card->cis.vendor); +MMC_DEV_ATTR(device, "0x%04x\n", card->cis.device); +MMC_DEV_ATTR(revision, "%u.%u\n", card->major_rev, card->minor_rev); +MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); +MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); + +#define sdio_info_attr(num) \ +static ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct mmc_card *card = mmc_dev_to_card(dev); \ + \ + if (num > card->num_info) \ + return -ENODATA; \ + if (!card->info[num - 1][0]) \ + return 0; \ + return sysfs_emit(buf, "%s\n", card->info[num - 1]); \ +} \ +static DEVICE_ATTR_RO(info##num) + +sdio_info_attr(1); +sdio_info_attr(2); +sdio_info_attr(3); +sdio_info_attr(4); + +static struct attribute *sdio_std_attrs[] = { + &dev_attr_vendor.attr, + &dev_attr_device.attr, + &dev_attr_revision.attr, + &dev_attr_info1.attr, + &dev_attr_info2.attr, + &dev_attr_info3.attr, + &dev_attr_info4.attr, + &dev_attr_ocr.attr, + &dev_attr_rca.attr, + NULL, +}; +ATTRIBUTE_GROUPS(sdio_std); + +static const struct device_type sdio_type = { + .groups = sdio_std_groups, +}; + static int sdio_read_fbr(struct sdio_func *func) { int ret; @@ -159,18 +198,21 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr) if (ret) goto out; - if (mmc_host_uhs(card->host)) { + if (mmc_host_can_uhs(card->host)) { if (data & SDIO_UHS_DDR50) card->sw_caps.sd3_bus_mode - |= SD_MODE_UHS_DDR50; + |= SD_MODE_UHS_DDR50 | SD_MODE_UHS_SDR50 + | SD_MODE_UHS_SDR25 | SD_MODE_UHS_SDR12; if (data & SDIO_UHS_SDR50) card->sw_caps.sd3_bus_mode - |= SD_MODE_UHS_SDR50; + |= SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR25 + | SD_MODE_UHS_SDR12; if (data & SDIO_UHS_SDR104) card->sw_caps.sd3_bus_mode - |= SD_MODE_UHS_SDR104; + |= SD_MODE_UHS_SDR104 | SD_MODE_UHS_SDR50 + | SD_MODE_UHS_SDR25 | SD_MODE_UHS_SDR12; } ret = mmc_io_rw_direct(card, 0, 0, @@ -184,6 +226,20 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr) card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_C; if (data & SDIO_DRIVE_SDTD) card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_D; + + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTERRUPT_EXT, 0, &data); + if (ret) + goto out; + + if (data & SDIO_INTERRUPT_EXT_SAI) { + data |= SDIO_INTERRUPT_EXT_EAI; + ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_INTERRUPT_EXT, + data, NULL); + if (ret) + goto out; + + card->cccr.enable_async_irq = 1; + } } /* if no uhs mode ensure we check for high speed */ @@ -289,30 +345,49 @@ static int sdio_disable_wide(struct mmc_card *card) return 0; } +static int sdio_disable_4bit_bus(struct mmc_card *card) +{ + int err; + + if (mmc_card_sdio(card)) + goto out; + + if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) + return 0; + + if (!(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) + return 0; + + err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); + if (err) + return err; + +out: + return sdio_disable_wide(card); +} + static int sdio_enable_4bit_bus(struct mmc_card *card) { int err; - if (card->type == MMC_TYPE_SDIO) - err = sdio_enable_wide(card); - else if ((card->host->caps & MMC_CAP_4_BIT_DATA) && - (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { + err = sdio_enable_wide(card); + if (err <= 0) + return err; + if (mmc_card_sdio(card)) + goto out; + + if (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4) { err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); - if (err) + if (err) { + sdio_disable_wide(card); return err; - err = sdio_enable_wide(card); - if (err <= 0) - mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1); - } else - return 0; - - if (err > 0) { - mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); - err = 0; + } } +out: + mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); - return err; + return 0; } @@ -354,7 +429,7 @@ static int sdio_enable_hs(struct mmc_card *card) int ret; ret = mmc_sdio_switch_hs(card, true); - if (ret <= 0 || card->type == MMC_TYPE_SDIO) + if (ret <= 0 || mmc_card_sdio(card)) return ret; ret = mmc_sd_switch_hs(card); @@ -380,9 +455,11 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) max_dtr = card->cis.max_dtr; } - if (card->type == MMC_TYPE_SD_COMBO) + if (mmc_card_sd_combo(card)) max_dtr = min(max_dtr, mmc_sd_get_max_clock(card)); + max_dtr = min_not_zero(max_dtr, card->quirk_max_rate); + return max_dtr; } @@ -450,7 +527,7 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card) * If the host doesn't support any of the UHS-I modes, fallback on * default speed. */ - if (!mmc_host_uhs(card->host)) + if (!mmc_host_can_uhs(card->host)) return 0; bus_speed = SDIO_SPEED_SDR12; @@ -504,10 +581,8 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card) max_rate = min_not_zero(card->quirk_max_rate, card->sw_caps.uhs_max_dtr); - if (bus_speed) { - mmc_set_timing(card->host, timing); - mmc_set_clock(card->host, max_rate); - } + mmc_set_timing(card->host, timing); + mmc_set_clock(card->host, max_rate); return 0; } @@ -547,13 +622,33 @@ out: return err; } -static void mmc_sdio_resend_if_cond(struct mmc_host *host, - struct mmc_card *card) +static int mmc_sdio_pre_init(struct mmc_host *host, u32 ocr, + struct mmc_card *card) { + if (card) + mmc_remove_card(card); + + /* + * Reset the card by performing the same steps that are taken by + * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe. + * + * sdio_reset() is technically not needed. Having just powered up the + * hardware, it should already be in reset state. However, some + * platforms (such as SD8686 on OLPC) do not instantly cut power, + * meaning that a reset is required when restoring power soon after + * powering off. It is harmless in other cases. + * + * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec, + * is not necessary for non-removable cards. However, it is required + * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and + * harmless in other situations. + * + */ + sdio_reset(host); mmc_go_idle(host); - mmc_send_if_cond(host, host->ocr_avail); - mmc_remove_card(card); + mmc_send_if_cond(host, ocr); + return mmc_send_io_op_cond(host, 0, NULL); } /* @@ -563,7 +658,7 @@ static void mmc_sdio_resend_if_cond(struct mmc_host *host, * we're trying to reinitialise. */ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, - struct mmc_card *oldcard, int powered_resume) + struct mmc_card *oldcard) { struct mmc_card *card; int err; @@ -574,7 +669,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, WARN_ON(!host->claimed); /* to query card if 1.8V signalling is supported */ - if (mmc_host_uhs(host)) + if (mmc_host_can_uhs(host)) ocr |= R4_18V_PRESENT; try_again: @@ -586,11 +681,9 @@ try_again: /* * Inform the card of the voltage */ - if (!powered_resume) { - err = mmc_send_io_op_cond(host, ocr, &rocr); - if (err) - goto err; - } + err = mmc_send_io_op_cond(host, ocr, &rocr); + if (err) + return err; /* * For SPI, enable CRC as appropriate. @@ -598,33 +691,31 @@ try_again: if (mmc_host_is_spi(host)) { err = mmc_spi_set_crc(host, use_spi_crc); if (err) - goto err; + return err; } /* * Allocate card structure. */ - card = mmc_alloc_card(host, NULL); - if (IS_ERR(card)) { - err = PTR_ERR(card); - goto err; - } + card = mmc_alloc_card(host, &sdio_type); + if (IS_ERR(card)) + return PTR_ERR(card); if ((rocr & R4_MEMORY_PRESENT) && mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) { card->type = MMC_TYPE_SD_COMBO; - if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || + if (oldcard && (!mmc_card_sd_combo(oldcard) || memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) { - mmc_remove_card(card); - return -ENOENT; + err = -ENOENT; + goto mismatch; } } else { card->type = MMC_TYPE_SDIO; - if (oldcard && oldcard->type != MMC_TYPE_SDIO) { - mmc_remove_card(card); - return -ENOENT; + if (oldcard && !mmc_card_sdio(oldcard)) { + err = -ENOENT; + goto mismatch; } } @@ -633,6 +724,9 @@ try_again: */ if (host->ops->init_card) host->ops->init_card(host, card); + mmc_fixup_device(card, sdio_card_init_methods); + + card->ocr = ocr_card; /* * If the host and card support UHS-I mode request the card @@ -645,10 +739,10 @@ try_again: * try to init uhs card. sdio_read_cccr will take over this task * to make sure which speed mode should work. */ - if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) { + if (rocr & ocr & R4_18V_PRESENT) { err = mmc_set_uhs_voltage(host, ocr_card); if (err == -EAGAIN) { - mmc_sdio_resend_if_cond(host, card); + mmc_sdio_pre_init(host, ocr_card, card); retries--; goto try_again; } else if (err) { @@ -659,7 +753,7 @@ try_again: /* * For native busses: set card RCA and quit open drain mode. */ - if (!powered_resume && !mmc_host_is_spi(host)) { + if (!mmc_host_is_spi(host)) { err = mmc_send_relative_addr(host, &card->rca); if (err) goto remove; @@ -676,10 +770,10 @@ try_again: /* * Read CSD, before selecting the card */ - if (!oldcard && card->type == MMC_TYPE_SD_COMBO) { - err = mmc_sd_get_csd(host, card); + if (!oldcard && mmc_card_sd_combo(card)) { + err = mmc_sd_get_csd(card, false); if (err) - return err; + goto remove; mmc_decode_cid(card); } @@ -687,7 +781,7 @@ try_again: /* * Select card, as all following commands rely on that. */ - if (!powered_resume && !mmc_host_is_spi(host)) { + if (!mmc_host_is_spi(host)) { err = mmc_select_card(card); if (err) goto remove; @@ -706,7 +800,12 @@ try_again: mmc_set_timing(card->host, MMC_TIMING_SD_HS); } - goto finish; + if (oldcard) + mmc_remove_card(card); + else + host->card = card; + + return 0; } /* @@ -715,14 +814,13 @@ try_again: */ err = sdio_read_cccr(card, ocr); if (err) { - mmc_sdio_resend_if_cond(host, card); + mmc_sdio_pre_init(host, ocr_card, card); if (ocr & R4_18V_PRESENT) { /* Retry init sequence, but without R4_18V_PRESENT. */ retries = 0; goto try_again; - } else { - goto remove; } + return err; } /* @@ -733,18 +831,19 @@ try_again: goto remove; if (oldcard) { - int same = (card->cis.vendor == oldcard->cis.vendor && - card->cis.device == oldcard->cis.device); - mmc_remove_card(card); - if (!same) - return -ENOENT; - - card = oldcard; + if (card->cis.vendor == oldcard->cis.vendor && + card->cis.device == oldcard->cis.device) { + mmc_remove_card(card); + card = oldcard; + } else { + err = -ENOENT; + goto mismatch; + } } - card->ocr = ocr_card; + mmc_fixup_device(card, sdio_fixup_methods); - if (card->type == MMC_TYPE_SD_COMBO) { + if (mmc_card_sd_combo(card)) { err = mmc_sd_setup_card(host, card, oldcard != NULL); /* handle as SDIO-only card if memory init failed */ if (err) { @@ -800,33 +899,27 @@ try_again: err = -EINVAL; goto remove; } -finish: - if (!oldcard) - host->card = card; + + host->card = card; return 0; +mismatch: + pr_debug("%s: Perhaps the card was replaced\n", mmc_hostname(host)); remove: - if (!oldcard) + if (oldcard != card) mmc_remove_card(card); - -err: return err; } -static int mmc_sdio_reinit_card(struct mmc_host *host, bool powered_resume) +static int mmc_sdio_reinit_card(struct mmc_host *host) { int ret; - sdio_reset(host); - mmc_go_idle(host); - mmc_send_if_cond(host, host->card->ocr); - - ret = mmc_send_io_op_cond(host, 0, NULL); + ret = mmc_sdio_pre_init(host, host->card->ocr, NULL); if (ret) return ret; - return mmc_sdio_init_card(host, host->card->ocr, host->card, - powered_resume); + return mmc_sdio_init_card(host, host->card->ocr, host->card); } /* @@ -852,7 +945,11 @@ static void mmc_sdio_remove(struct mmc_host *host) */ static int mmc_sdio_alive(struct mmc_host *host) { - return mmc_select_card(host->card); + if (!mmc_host_is_spi(host)) + return mmc_select_card(host->card); + else + return mmc_io_rw_direct(host->card, 0, 0, SDIO_CCCR_CCCR, 0, + NULL); } /* @@ -864,11 +961,9 @@ static void mmc_sdio_detect(struct mmc_host *host) /* Make sure card is powered before detecting it */ if (host->caps & MMC_CAP_POWER_OFF_CARD) { - err = pm_runtime_get_sync(&host->card->dev); - if (err < 0) { - pm_runtime_put_noidle(&host->card->dev); + err = pm_runtime_resume_and_get(&host->card->dev); + if (err < 0) goto out; - } } mmc_claim_host(host); @@ -912,21 +1007,37 @@ out: */ static int mmc_sdio_pre_suspend(struct mmc_host *host) { - int i, err = 0; + int i; for (i = 0; i < host->card->sdio_funcs; i++) { struct sdio_func *func = host->card->sdio_func[i]; if (func && sdio_func_present(func) && func->dev.driver) { const struct dev_pm_ops *pmops = func->dev.driver->pm; - if (!pmops || !pmops->suspend || !pmops->resume) { + if (!pmops || !pmops->suspend || !pmops->resume) /* force removal of entire card in that case */ - err = -ENOSYS; - break; - } + goto remove; } } - return err; + return 0; + +remove: + if (!mmc_card_is_removable(host)) { + dev_warn(mmc_dev(host), + "missing suspend/resume ops for non-removable SDIO card\n"); + /* Don't remove a non-removable card - we can't re-detect it. */ + return 0; + } + + /* Remove the SDIO card and let it be re-detected later on. */ + mmc_sdio_remove(host); + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_power_off(host); + mmc_release_host(host); + host->pm_flags = 0; + + return 0; } /* @@ -934,10 +1045,16 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host) */ static int mmc_sdio_suspend(struct mmc_host *host) { + WARN_ON(host->sdio_irqs && !mmc_card_keep_power(host)); + + /* Prevent processing of SDIO IRQs in suspended state. */ + mmc_card_set_suspended(host->card); + cancel_work_sync(&host->sdio_irq_work); + mmc_claim_host(host); if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) - sdio_disable_wide(host->card); + sdio_disable_4bit_bus(host->card); if (!mmc_card_keep_power(host)) { mmc_power_off(host); @@ -958,7 +1075,11 @@ static int mmc_sdio_resume(struct mmc_host *host) /* Basic card reinitialization. */ mmc_claim_host(host); - /* Restore power if needed */ + /* + * Restore power and reinitialize the card when needed. Note that a + * removable card is checked from a detect work later on in the resume + * process. + */ if (!mmc_card_keep_power(host)) { mmc_power_up(host, host->card->ocr); /* @@ -972,61 +1093,38 @@ static int mmc_sdio_resume(struct mmc_host *host) pm_runtime_set_active(&host->card->dev); pm_runtime_enable(&host->card->dev); } - } - - /* No need to reinitialize powered-resumed nonremovable cards */ - if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { - err = mmc_sdio_reinit_card(host, mmc_card_keep_power(host)); - } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { - /* We may have switched to 1-bit mode during suspend */ + err = mmc_sdio_reinit_card(host); + } else if (mmc_card_wake_sdio_irq(host)) { + /* + * We may have switched to 1-bit mode during suspend, + * need to hold retuning, because tuning only supprt + * 4-bit mode or 8 bit mode. + */ + mmc_retune_hold_now(host); err = sdio_enable_4bit_bus(host->card); + mmc_retune_release(host); } - if (!err && host->sdio_irqs) { + if (err) + goto out; + + /* Allow SDIO IRQs to be processed again. */ + mmc_card_clr_suspended(host->card); + + if (host->sdio_irqs) { if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) wake_up_process(host->sdio_irq_thread); else if (host->caps & MMC_CAP_SDIO_IRQ) - host->ops->enable_sdio_irq(host, 1); + schedule_work(&host->sdio_irq_work); } +out: mmc_release_host(host); host->pm_flags &= ~MMC_PM_KEEP_POWER; return err; } -static int mmc_sdio_power_restore(struct mmc_host *host) -{ - int ret; - - /* - * Reset the card by performing the same steps that are taken by - * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe. - * - * sdio_reset() is technically not needed. Having just powered up the - * hardware, it should already be in reset state. However, some - * platforms (such as SD8686 on OLPC) do not instantly cut power, - * meaning that a reset is required when restoring power soon after - * powering off. It is harmless in other cases. - * - * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec, - * is not necessary for non-removable cards. However, it is required - * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and - * harmless in other situations. - * - */ - - mmc_claim_host(host); - - ret = mmc_sdio_reinit_card(host, mmc_card_keep_power(host)); - if (!ret && host->sdio_irqs) - mmc_signal_sdio_irq(host); - - mmc_release_host(host); - - return ret; -} - static int mmc_sdio_runtime_suspend(struct mmc_host *host) { /* No references to the card, cut the power to it. */ @@ -1044,16 +1142,42 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host) /* Restore power and re-initialize. */ mmc_claim_host(host); mmc_power_up(host, host->card->ocr); - ret = mmc_sdio_power_restore(host); + ret = mmc_sdio_reinit_card(host); mmc_release_host(host); return ret; } +/* + * SDIO HW reset + * + * Returns 0 if the HW reset was executed synchronously, returns 1 if the HW + * reset was asynchronously scheduled, else a negative error code. + */ static int mmc_sdio_hw_reset(struct mmc_host *host) { - mmc_power_cycle(host, host->card->ocr); - return mmc_sdio_power_restore(host); + struct mmc_card *card = host->card; + + /* + * In case the card is shared among multiple func drivers, reset the + * card through a rescan work. In this way it will be removed and + * re-detected, thus all func drivers becomes informed about it. + */ + if (atomic_read(&card->sdio_funcs_probed) > 1) { + if (mmc_card_removed(card)) + return 1; + host->rescan_entered = 0; + mmc_card_set_removed(card); + _mmc_detect_change(host, 0, false); + return 1; + } + + /* + * A single func driver has been probed, then let's skip the heavy + * hotplug dance above and execute the reset immediately. + */ + mmc_power_cycle(host, card->ocr); + return mmc_sdio_reinit_card(host); } static int mmc_sdio_sw_reset(struct mmc_host *host) @@ -1065,7 +1189,7 @@ static int mmc_sdio_sw_reset(struct mmc_host *host) mmc_set_initial_state(host); mmc_set_initial_signal_voltage(host); - return mmc_sdio_reinit_card(host, 0); + return mmc_sdio_reinit_card(host); } static const struct mmc_bus_ops mmc_sdio_ops = { @@ -1115,7 +1239,7 @@ int mmc_attach_sdio(struct mmc_host *host) /* * Detect and init the card. */ - err = mmc_sdio_init_card(host, rocr, NULL, 0); + err = mmc_sdio_init_card(host, rocr, NULL); if (err) goto err; diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index b6d8203e46eb..10799772494a 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/mmc/core/sdio_bus.c * * Copyright 2007 Pierre Ossman * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * * SDIO function driver model */ @@ -18,6 +14,7 @@ #include <linux/pm_runtime.h> #include <linux/pm_domain.h> #include <linux/acpi.h> +#include <linux/sysfs.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> @@ -29,37 +26,53 @@ #include "sdio_cis.h" #include "sdio_bus.h" -#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) +#define to_sdio_driver(d) container_of_const(d, struct sdio_driver, drv) /* show configuration fields */ -#define sdio_config_attr(field, format_string) \ +#define sdio_config_attr(field, format_string, args...) \ static ssize_t \ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct sdio_func *func; \ \ func = dev_to_sdio_func (dev); \ - return sprintf (buf, format_string, func->field); \ + return sysfs_emit(buf, format_string, args); \ } \ static DEVICE_ATTR_RO(field) -sdio_config_attr(class, "0x%02x\n"); -sdio_config_attr(vendor, "0x%04x\n"); -sdio_config_attr(device, "0x%04x\n"); - -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sdio_func *func = dev_to_sdio_func (dev); - - return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n", - func->class, func->vendor, func->device); -} -static DEVICE_ATTR_RO(modalias); +sdio_config_attr(class, "0x%02x\n", func->class); +sdio_config_attr(vendor, "0x%04x\n", func->vendor); +sdio_config_attr(device, "0x%04x\n", func->device); +sdio_config_attr(revision, "%u.%u\n", func->major_rev, func->minor_rev); +sdio_config_attr(modalias, "sdio:c%02Xv%04Xd%04X\n", func->class, func->vendor, func->device); + +#define sdio_info_attr(num) \ +static ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct sdio_func *func = dev_to_sdio_func(dev); \ + \ + if (num > func->num_info) \ + return -ENODATA; \ + if (!func->info[num - 1][0]) \ + return 0; \ + return sysfs_emit(buf, "%s\n", func->info[num - 1]); \ +} \ +static DEVICE_ATTR_RO(info##num) + +sdio_info_attr(1); +sdio_info_attr(2); +sdio_info_attr(3); +sdio_info_attr(4); static struct attribute *sdio_dev_attrs[] = { &dev_attr_class.attr, &dev_attr_vendor.attr, &dev_attr_device.attr, + &dev_attr_revision.attr, + &dev_attr_info1.attr, + &dev_attr_info2.attr, + &dev_attr_info3.attr, + &dev_attr_info4.attr, &dev_attr_modalias.attr, NULL, }; @@ -78,7 +91,7 @@ static const struct sdio_device_id *sdio_match_one(struct sdio_func *func, } static const struct sdio_device_id *sdio_match_device(struct sdio_func *func, - struct sdio_driver *sdrv) + const struct sdio_driver *sdrv) { const struct sdio_device_id *ids; @@ -95,10 +108,10 @@ static const struct sdio_device_id *sdio_match_device(struct sdio_func *func, return NULL; } -static int sdio_bus_match(struct device *dev, struct device_driver *drv) +static int sdio_bus_match(struct device *dev, const struct device_driver *drv) { struct sdio_func *func = dev_to_sdio_func(dev); - struct sdio_driver *sdrv = to_sdio_driver(drv); + const struct sdio_driver *sdrv = to_sdio_driver(drv); if (sdio_match_device(func, sdrv)) return 1; @@ -107,19 +120,29 @@ static int sdio_bus_match(struct device *dev, struct device_driver *drv) } static int -sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +sdio_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct sdio_func *func = dev_to_sdio_func(dev); + const struct sdio_func *func = dev_to_sdio_func(dev); + unsigned int i; if (add_uevent_var(env, "SDIO_CLASS=%02X", func->class)) return -ENOMEM; - if (add_uevent_var(env, + if (add_uevent_var(env, "SDIO_ID=%04X:%04X", func->vendor, func->device)) return -ENOMEM; if (add_uevent_var(env, + "SDIO_REVISION=%u.%u", func->major_rev, func->minor_rev)) + return -ENOMEM; + + for (i = 0; i < func->num_info; i++) { + if (add_uevent_var(env, "SDIO_INFO%u=%s", i+1, func->info[i])) + return -ENOMEM; + } + + if (add_uevent_var(env, "MODALIAS=sdio:c%02Xv%04Xd%04X", func->class, func->vendor, func->device)) return -ENOMEM; @@ -138,10 +161,12 @@ static int sdio_bus_probe(struct device *dev) if (!id) return -ENODEV; - ret = dev_pm_domain_attach(dev, false); + ret = dev_pm_domain_attach(dev, 0); if (ret) return ret; + atomic_inc(&func->card->sdio_funcs_probed); + /* Unbound SDIO functions are always suspended. * During probe, the function is set active and the usage count * is incremented. If the driver supports runtime PM, @@ -157,7 +182,10 @@ static int sdio_bus_probe(struct device *dev) /* Set the default block size so the driver is sure it's something * sensible. */ sdio_claim_host(func); - ret = sdio_set_block_size(func, 0); + if (mmc_card_removed(func->card)) + ret = -ENOMEDIUM; + else + ret = sdio_set_block_size(func, 0); sdio_release_host(func); if (ret) goto disable_runtimepm; @@ -169,23 +197,23 @@ static int sdio_bus_probe(struct device *dev) return 0; disable_runtimepm: + atomic_dec(&func->card->sdio_funcs_probed); if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) pm_runtime_put_noidle(dev); - dev_pm_domain_detach(dev, false); return ret; } -static int sdio_bus_remove(struct device *dev) +static void sdio_bus_remove(struct device *dev) { struct sdio_driver *drv = to_sdio_driver(dev->driver); struct sdio_func *func = dev_to_sdio_func(dev); - int ret = 0; /* Make sure card is powered before invoking ->remove() */ if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) pm_runtime_get_sync(dev); drv->remove(func); + atomic_dec(&func->card->sdio_funcs_probed); if (func->irq_handler) { pr_warn("WARNING: driver %s did not remove its interrupt handler!\n", @@ -202,10 +230,6 @@ static int sdio_bus_remove(struct device *dev) /* Then undo the runtime PM settings in sdio_bus_probe() */ if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) pm_runtime_put_sync(dev); - - dev_pm_domain_detach(dev, false); - - return ret; } static const struct dev_pm_ops sdio_bus_pm_ops = { @@ -217,7 +241,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = { ) }; -static struct bus_type sdio_bus_type = { +static const struct bus_type sdio_bus_type = { .name = "sdio", .dev_groups = sdio_dev_groups, .match = sdio_bus_match, @@ -238,16 +262,19 @@ void sdio_unregister_bus(void) } /** - * sdio_register_driver - register a function driver + * __sdio_register_driver - register a function driver * @drv: SDIO function driver + * @owner: owning module/driver */ -int sdio_register_driver(struct sdio_driver *drv) +int __sdio_register_driver(struct sdio_driver *drv, struct module *owner) { drv->drv.name = drv->name; drv->drv.bus = &sdio_bus_type; + drv->drv.owner = owner; + return driver_register(&drv->drv); } -EXPORT_SYMBOL_GPL(sdio_register_driver); +EXPORT_SYMBOL_GPL(__sdio_register_driver); /** * sdio_unregister_driver - unregister a function driver @@ -264,7 +291,14 @@ static void sdio_release_func(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); - sdio_free_func_cis(func); + if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO)) + sdio_free_func_cis(func); + + /* + * We have now removed the link to the tuples in the + * card structure, so remove the reference. + */ + put_device(&func->card->dev); kfree(func->info); kfree(func->tmpbuf); @@ -296,6 +330,12 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card) device_initialize(&func->dev); + /* + * We may link to tuples in the card structure, + * we need make sure we have a reference to it. + */ + get_device(&func->card->dev); + func->dev.parent = &card->dev; func->dev.bus = &sdio_bus_type; func->dev.release = sdio_release_func; @@ -349,10 +389,9 @@ int sdio_add_func(struct sdio_func *func) */ void sdio_remove_func(struct sdio_func *func) { - if (!sdio_func_present(func)) - return; + if (sdio_func_present(func)) + device_del(&func->dev); - device_del(&func->dev); of_node_put(func->dev.of_node); put_device(&func->dev); } diff --git a/drivers/mmc/core/sdio_bus.h b/drivers/mmc/core/sdio_bus.h index b69a2540a076..27b8069a72ab 100644 --- a/drivers/mmc/core/sdio_bus.h +++ b/drivers/mmc/core/sdio_bus.h @@ -1,12 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * linux/drivers/mmc/core/sdio_bus.h * * Copyright 2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #ifndef _MMC_CORE_SDIO_BUS_H #define _MMC_CORE_SDIO_BUS_H diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index f8c372839d24..afaa6cab1adc 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/mmc/core/sdio_cis.c * @@ -6,11 +7,6 @@ * Copyright: MontaVista Software Inc. * * Copyright 2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #include <linux/kernel.h> @@ -24,12 +20,21 @@ #include "sdio_cis.h" #include "sdio_ops.h" +#define SDIO_READ_CIS_TIMEOUT_MS (10 * 1000) /* 10s */ + static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func, const unsigned char *buf, unsigned size) { + u8 major_rev, minor_rev; unsigned i, nr_strings; char **buffer, *string; + if (size < 2) + return 0; + + major_rev = buf[0]; + minor_rev = buf[1]; + /* Find all null-terminated (including zero length) strings in the TPLLV1_INFO field. Trailing garbage is ignored. */ buf += 2; @@ -61,9 +66,13 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func, } if (func) { + func->major_rev = major_rev; + func->minor_rev = minor_rev; func->num_info = nr_strings; func->info = (const char**)buffer; } else { + card->major_rev = major_rev; + card->minor_rev = minor_rev; card->num_info = nr_strings; card->info = (const char**)buffer; } @@ -267,6 +276,8 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) do { unsigned char tpl_code, tpl_link; + unsigned long timeout = jiffies + + msecs_to_jiffies(SDIO_READ_CIS_TIMEOUT_MS); ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_code); if (ret) @@ -319,11 +330,25 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) prev = &this->next; if (ret == -ENOENT) { - /* 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); + + if (time_after(jiffies, timeout)) + break; + +#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 + */ + if (tpl_code >= 0x80 && tpl_code <= 0x8f) + pr_debug_ratelimited(FMT("vendor"), + mmc_hostname(card->host), + tpl_code, tpl_link, this->data, + tpl_link); + else + pr_warn_ratelimited(FMT("unknown"), + mmc_hostname(card->host), + tpl_code, tpl_link, this->data, + tpl_link); } /* keep on analyzing tuples */ @@ -379,12 +404,6 @@ int sdio_read_func_cis(struct sdio_func *func) return ret; /* - * Since we've linked to tuples in the card structure, - * we must make sure we have a reference to it. - */ - get_device(&func->card->dev); - - /* * Vendor/device id is optional for function CIS, so * copy it from the card structure as needed. */ @@ -409,11 +428,5 @@ void sdio_free_func_cis(struct sdio_func *func) } func->tuples = NULL; - - /* - * We have now removed the link to the tuples in the - * card structure, so remove the reference. - */ - put_device(&func->card->dev); } diff --git a/drivers/mmc/core/sdio_cis.h b/drivers/mmc/core/sdio_cis.h index 16aa563faa00..6d76f6fa608c 100644 --- a/drivers/mmc/core/sdio_cis.h +++ b/drivers/mmc/core/sdio_cis.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * linux/drivers/mmc/core/sdio_cis.h * * Author: Nicolas Pitre * Created: June 11, 2007 * Copyright: MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #ifndef _MMC_SDIO_CIS_H diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index d40744bbafa9..b774bf51981d 100644 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c @@ -1,15 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/mmc/core/sdio_io.c * * Copyright 2007-2008 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #include <linux/export.h> +#include <linux/kernel.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/mmc/sdio.h> @@ -18,6 +15,7 @@ #include "sdio_ops.h" #include "core.h" #include "card.h" +#include "host.h" /** * sdio_claim_host - exclusively claim a bus for a certain SDIO function @@ -135,7 +133,7 @@ int sdio_disable_func(struct sdio_func *func) err: pr_debug("SDIO: Failed to disable device %s\n", sdio_func_id(func)); - return -EIO; + return ret; } EXPORT_SYMBOL_GPL(sdio_disable_func); @@ -203,6 +201,21 @@ static inline unsigned int sdio_max_byte_size(struct sdio_func *func) return min(mval, 512u); /* maximum size for byte mode */ } +/* + * This is legacy code, which needs to be re-worked some day. Basically we need + * to take into account the properties of the host, as to enable the SDIO func + * driver layer to allocate optimal buffers. + */ +static inline unsigned int _sdio_align_size(unsigned int sz) +{ + /* + * FIXME: We don't have a system for the controller to tell + * the core about its problems yet, so for now we just 32-bit + * align the size. + */ + return ALIGN(sz, 4); +} + /** * sdio_align_size - pads a transfer size to a more optimal value * @func: SDIO function @@ -230,7 +243,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz) * wants to increase the size up to a point where it * might need more than one block. */ - sz = mmc_align_data_size(func->card, sz); + sz = _sdio_align_size(sz); /* * If we can still do this with just a byte transfer, then @@ -252,7 +265,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz) */ blk_sz = ((sz + func->cur_blksize - 1) / func->cur_blksize) * func->cur_blksize; - blk_sz = mmc_align_data_size(func->card, blk_sz); + blk_sz = _sdio_align_size(blk_sz); /* * This value is only good if it is still just @@ -265,8 +278,7 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz) * We failed to do one request, but at least try to * pad the remainder properly. */ - byte_sz = mmc_align_data_size(func->card, - sz % func->cur_blksize); + byte_sz = _sdio_align_size(sz % func->cur_blksize); if (byte_sz <= sdio_max_byte_size(func)) { blk_sz = sz / func->cur_blksize; return blk_sz * func->cur_blksize + byte_sz; @@ -276,16 +288,14 @@ unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz) * We need multiple requests, so first check that the * controller can handle the chunk size; */ - chunk_sz = mmc_align_data_size(func->card, - sdio_max_byte_size(func)); + chunk_sz = _sdio_align_size(sdio_max_byte_size(func)); if (chunk_sz == sdio_max_byte_size(func)) { /* * Fix up the size of the remainder (if any) */ byte_sz = orig_sz % chunk_sz; if (byte_sz) { - byte_sz = mmc_align_data_size(func->card, - byte_sz); + byte_sz = _sdio_align_size(byte_sz); } return (orig_sz / chunk_sz) * chunk_sz + byte_sz; @@ -699,6 +709,7 @@ EXPORT_SYMBOL_GPL(sdio_get_host_pm_caps); /** * sdio_set_host_pm_flags - set wanted host power management capabilities * @func: SDIO function attached to host + * @flags: Power Management flags to set * * Set a capability bitmask corresponding to wanted host controller * power management features for the upcoming suspend state. @@ -725,3 +736,79 @@ int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags) return 0; } EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags); + +/** + * sdio_retune_crc_disable - temporarily disable retuning on CRC errors + * @func: SDIO function attached to host + * + * If the SDIO card is known to be in a state where it might produce + * CRC errors on the bus in response to commands (like if we know it is + * transitioning between power states), an SDIO function driver can + * call this function to temporarily disable the SD/MMC core behavior of + * triggering an automatic retuning. + * + * This function should be called while the host is claimed and the host + * should remain claimed until sdio_retune_crc_enable() is called. + * Specifically, the expected sequence of calls is: + * - sdio_claim_host() + * - sdio_retune_crc_disable() + * - some number of calls like sdio_writeb() and sdio_readb() + * - sdio_retune_crc_enable() + * - sdio_release_host() + */ +void sdio_retune_crc_disable(struct sdio_func *func) +{ + func->card->host->retune_crc_disable = true; +} +EXPORT_SYMBOL_GPL(sdio_retune_crc_disable); + +/** + * sdio_retune_crc_enable - re-enable retuning on CRC errors + * @func: SDIO function attached to host + * + * This is the complement to sdio_retune_crc_disable(). + */ +void sdio_retune_crc_enable(struct sdio_func *func) +{ + func->card->host->retune_crc_disable = false; +} +EXPORT_SYMBOL_GPL(sdio_retune_crc_enable); + +/** + * sdio_retune_hold_now - start deferring retuning requests till release + * @func: SDIO function attached to host + * + * This function can be called if it's currently a bad time to do + * a retune of the SDIO card. Retune requests made during this time + * will be held and we'll actually do the retune sometime after the + * release. + * + * This function could be useful if an SDIO card is in a power state + * where it can respond to a small subset of commands that doesn't + * include the retuning command. Care should be taken when using + * this function since (presumably) the retuning request we might be + * deferring was made for a good reason. + * + * This function should be called while the host is claimed. + */ +void sdio_retune_hold_now(struct sdio_func *func) +{ + mmc_retune_hold_now(func->card->host); +} +EXPORT_SYMBOL_GPL(sdio_retune_hold_now); + +/** + * sdio_retune_release - signal that it's OK to retune now + * @func: SDIO function attached to host + * + * This is the complement to sdio_retune_hold_now(). Calling this + * function won't make a retune happen right away but will allow + * them to be scheduled normally. + * + * This function should be called while the host is claimed. + */ +void sdio_retune_release(struct sdio_func *func) +{ + mmc_retune_release(func->card->host); +} +EXPORT_SYMBOL_GPL(sdio_retune_release); diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 7ca7b99413f0..2b24bdf38296 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/mmc/core/sdio_irq.c * @@ -6,11 +7,6 @@ * Copyright: MontaVista Software Inc. * * Copyright 2008 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #include <linux/kernel.h> @@ -31,32 +27,21 @@ #include "core.h" #include "card.h" -static int process_sdio_pending_irqs(struct mmc_host *host) +static int sdio_get_pending_irqs(struct mmc_host *host, u8 *pending) { struct mmc_card *card = host->card; - int i, ret, count; - unsigned char pending; - struct sdio_func *func; + int ret; - /* - * Optimization, if there is only 1 function interrupt registered - * and we know an IRQ was signaled then call irq handler directly. - * Otherwise do the full probe. - */ - func = card->sdio_single_irq; - if (func && host->sdio_irq_pending) { - func->irq_handler(func); - return 1; - } + WARN_ON(!host->claimed); - ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending); + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, pending); if (ret) { pr_debug("%s: error %d reading SDIO_CCCR_INTx\n", mmc_card_id(card), ret); return ret; } - if (pending && mmc_card_broken_irq_polling(card) && + if (*pending && mmc_card_broken_irq_polling(card) && !(host->caps & MMC_CAP_SDIO_IRQ)) { unsigned char dummy; @@ -67,6 +52,39 @@ static int process_sdio_pending_irqs(struct mmc_host *host) mmc_io_rw_direct(card, 0, 0, 0xff, 0, &dummy); } + return 0; +} + +static int process_sdio_pending_irqs(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + int i, ret, count; + bool sdio_irq_pending = host->sdio_irq_pending; + unsigned char pending; + struct sdio_func *func; + + /* Don't process SDIO IRQs if the card is suspended. */ + if (mmc_card_suspended(card)) + return 0; + + /* Clear the flag to indicate that we have processed the IRQ. */ + host->sdio_irq_pending = false; + + /* + * Optimization, if there is only 1 function interrupt registered + * and we know an IRQ was signaled then call irq handler directly. + * Otherwise do the full probe. + */ + func = card->sdio_single_irq; + if (func && sdio_irq_pending) { + func->irq_handler(func); + return 1; + } + + ret = sdio_get_pending_irqs(host, &pending); + if (ret) + return ret; + count = 0; for (i = 1; i <= 7; i++) { if (pending & (1 << i)) { @@ -92,41 +110,39 @@ static int process_sdio_pending_irqs(struct mmc_host *host) return ret; } -void sdio_run_irqs(struct mmc_host *host) +static void sdio_run_irqs(struct mmc_host *host) { mmc_claim_host(host); if (host->sdio_irqs) { - host->sdio_irq_pending = true; process_sdio_pending_irqs(host); - if (host->ops->ack_sdio_irq) + if (!host->sdio_irq_pending) host->ops->ack_sdio_irq(host); } mmc_release_host(host); } -EXPORT_SYMBOL_GPL(sdio_run_irqs); void sdio_irq_work(struct work_struct *work) { struct mmc_host *host = - container_of(work, struct mmc_host, sdio_irq_work.work); + container_of(work, struct mmc_host, sdio_irq_work); sdio_run_irqs(host); } void sdio_signal_irq(struct mmc_host *host) { - queue_delayed_work(system_wq, &host->sdio_irq_work, 0); + host->sdio_irq_pending = true; + schedule_work(&host->sdio_irq_work); } EXPORT_SYMBOL_GPL(sdio_signal_irq); static int sdio_irq_thread(void *_host) { struct mmc_host *host = _host; - struct sched_param param = { .sched_priority = 1 }; unsigned long period, idle_period; int ret; - sched_setscheduler(current, SCHED_FIFO, ¶m); + sched_set_fifo_low(current); /* * We want to allow for SDIO cards to work even on non SDIO @@ -160,7 +176,6 @@ static int sdio_irq_thread(void *_host) if (ret) break; ret = process_sdio_pending_irqs(host); - host->sdio_irq_pending = false; mmc_release_host(host); /* @@ -260,14 +275,15 @@ static void sdio_single_irq_set(struct mmc_card *card) card->sdio_single_irq = NULL; if ((card->host->caps & MMC_CAP_SDIO_IRQ) && - card->host->sdio_irqs == 1) + card->host->sdio_irqs == 1) { for (i = 0; i < card->sdio_funcs; i++) { - func = card->sdio_func[i]; - if (func && func->irq_handler) { - card->sdio_single_irq = func; - break; - } - } + func = card->sdio_func[i]; + if (func && func->irq_handler) { + card->sdio_single_irq = func; + break; + } + } + } } /** diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index abaaba38514f..4c229dd2b6e5 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/mmc/sdio_ops.c * * Copyright 2006-2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #include <linux/scatterlist.h> @@ -125,6 +121,7 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, struct sg_table sgtable; unsigned int nents, left_size, i; unsigned int seg_size = card->host->max_seg_size; + int err; WARN_ON(blksz == 0); @@ -174,28 +171,32 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, mmc_set_data_timeout(&data, card); - mmc_wait_for_req(card->host, &mrq); + mmc_pre_req(card->host, &mrq); - if (nents > 1) - sg_free_table(&sgtable); + mmc_wait_for_req(card->host, &mrq); if (cmd.error) - return cmd.error; - if (data.error) - return data.error; - - if (mmc_host_is_spi(card->host)) { + err = cmd.error; + else if (data.error) + err = data.error; + else if (mmc_host_is_spi(card->host)) /* host driver already reported errors */ - } else { - if (cmd.resp[0] & R5_ERROR) - return -EIO; - if (cmd.resp[0] & R5_FUNCTION_NUMBER) - return -EINVAL; - if (cmd.resp[0] & R5_OUT_OF_RANGE) - return -ERANGE; - } + err = 0; + else if (cmd.resp[0] & R5_ERROR) + err = -EIO; + else if (cmd.resp[0] & R5_FUNCTION_NUMBER) + err = -EINVAL; + else if (cmd.resp[0] & R5_OUT_OF_RANGE) + err = -ERANGE; + else + err = 0; - return 0; + mmc_post_req(card->host, &mrq, err); + + if (nents > 1) + sg_free_table(&sgtable); + + return err; } int sdio_reset(struct mmc_host *host) diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h index 96945cafbf0b..37f79732a206 100644 --- a/drivers/mmc/core/sdio_ops.h +++ b/drivers/mmc/core/sdio_ops.h @@ -1,12 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * linux/drivers/mmc/sdio_ops.c * * Copyright 2006-2007 Pierre Ossman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ #ifndef _MMC_SDIO_OPS_H @@ -25,7 +21,6 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); int sdio_reset(struct mmc_host *host); -unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz); void sdio_irq_work(struct work_struct *work); static inline bool sdio_is_io_busy(u32 opcode, u32 arg) diff --git a/drivers/mmc/core/sdio_uart.c b/drivers/mmc/core/sdio_uart.c index 25e113001a3c..7423a601e1e5 100644 --- a/drivers/mmc/core/sdio_uart.c +++ b/drivers/mmc/core/sdio_uart.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * SDIO UART/GPS driver * @@ -7,11 +8,6 @@ * Author: Nicolas Pitre * Created: June 15, 2007 * Copyright: MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. */ /* @@ -32,6 +28,7 @@ #include <linux/sched.h> #include <linux/mutex.h> #include <linux/seq_file.h> +#include <linux/serial.h> #include <linux/serial_reg.h> #include <linux/circ_buf.h> #include <linux/tty.h> @@ -181,11 +178,9 @@ static inline void sdio_uart_release_func(struct sdio_uart_port *port) sdio_release_host(port->func); } -static inline unsigned int sdio_in(struct sdio_uart_port *port, int offset) +static inline u8 sdio_in(struct sdio_uart_port *port, int offset) { - unsigned char c; - c = sdio_readb(port->func, port->regs_offset + offset, NULL); - return c; + return sdio_readb(port->func, port->regs_offset + offset, NULL); } static inline void sdio_out(struct sdio_uart_port *port, int offset, int value) @@ -195,8 +190,8 @@ static inline void sdio_out(struct sdio_uart_port *port, int offset, int value) static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port) { - unsigned char status; unsigned int ret; + u8 status; /* FIXME: What stops this losing the delta bits and breaking sdio_uart_check_modem_status ? */ @@ -249,26 +244,12 @@ static inline void sdio_uart_update_mctrl(struct sdio_uart_port *port, static void sdio_uart_change_speed(struct sdio_uart_port *port, struct ktermios *termios, - struct ktermios *old) + const struct ktermios *old) { unsigned char cval, fcr = 0; unsigned int baud, quot; - switch (termios->c_cflag & CSIZE) { - case CS5: - cval = UART_LCR_WLEN5; - break; - case CS6: - cval = UART_LCR_WLEN6; - break; - case CS7: - cval = UART_LCR_WLEN7; - break; - default: - case CS8: - cval = UART_LCR_WLEN8; - break; - } + cval = UART_LCR_WLEN(tty_get_char_size(termios->c_cflag)); if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; @@ -371,15 +352,13 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port) sdio_out(port, UART_IER, port->ier); } -static void sdio_uart_receive_chars(struct sdio_uart_port *port, - unsigned int *status) +static void sdio_uart_receive_chars(struct sdio_uart_port *port, u8 *status) { - unsigned int ch, flag; int max_count = 256; do { - ch = sdio_in(port, UART_RX); - flag = TTY_NORMAL; + u8 ch = sdio_in(port, UART_RX); + u8 flag = TTY_NORMAL; port->icount.rx++; if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | @@ -443,7 +422,7 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) tty = tty_port_tty_get(&port->port); if (tty == NULL || !kfifo_len(xmit) || - tty->stopped || tty->hw_stopped) { + tty->flow.stopped || tty->hw_stopped) { sdio_uart_stop_tx(port); tty_kref_put(tty); return; @@ -466,8 +445,8 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) static void sdio_uart_check_modem_status(struct sdio_uart_port *port) { - int status; struct tty_struct *tty; + u8 status; status = sdio_in(port, UART_MSR); @@ -492,16 +471,16 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) port->icount.cts++; tty = tty_port_tty_get(&port->port); if (tty && C_CRTSCTS(tty)) { - int cts = (status & UART_MSR_CTS); + bool cts = status & UART_MSR_CTS; if (tty->hw_stopped) { if (cts) { - tty->hw_stopped = 0; + tty->hw_stopped = false; sdio_uart_start_tx(port); tty_wakeup(tty); } } else { if (!cts) { - tty->hw_stopped = 1; + tty->hw_stopped = true; sdio_uart_stop_tx(port); } } @@ -516,7 +495,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) static void sdio_uart_irq(struct sdio_func *func) { struct sdio_uart_port *port = sdio_get_drvdata(func); - unsigned int iir, lsr; + u8 iir, lsr; /* * In a few places sdio_uart_irq() is called directly instead of @@ -543,7 +522,7 @@ static void sdio_uart_irq(struct sdio_func *func) port->in_sdio_uart_irq = NULL; } -static int uart_carrier_raised(struct tty_port *tport) +static bool uart_carrier_raised(struct tty_port *tport) { struct sdio_uart_port *port = container_of(tport, struct sdio_uart_port, port); @@ -552,28 +531,27 @@ static int uart_carrier_raised(struct tty_port *tport) return 1; ret = sdio_uart_get_mctrl(port); sdio_uart_release_func(port); - if (ret & TIOCM_CAR) - return 1; - return 0; + + return ret & TIOCM_CAR; } /** * uart_dtr_rts - port helper to set uart signals * @tport: tty port to be updated - * @onoff: set to turn on DTR/RTS + * @active: set to turn on DTR/RTS * * Called by the tty port helpers when the modem signals need to be * adjusted during an open, close and hangup. */ -static void uart_dtr_rts(struct tty_port *tport, int onoff) +static void uart_dtr_rts(struct tty_port *tport, bool active) { struct sdio_uart_port *port = container_of(tport, struct sdio_uart_port, port); int ret = sdio_uart_claim_func(port); if (ret) return; - if (onoff == 0) + if (!active) sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); else sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); @@ -651,7 +629,7 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) if (C_CRTSCTS(tty)) if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) - tty->hw_stopped = 1; + tty->hw_stopped = true; clear_bit(TTY_IO_ERROR, &tty->flags); @@ -778,8 +756,8 @@ static void sdio_uart_hangup(struct tty_struct *tty) tty_port_hangup(&port->port); } -static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, - int count) +static ssize_t sdio_uart_write(struct tty_struct *tty, const u8 *buf, + size_t count) { struct sdio_uart_port *port = tty->driver_data; int ret; @@ -801,19 +779,19 @@ static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, return ret; } -static int sdio_uart_write_room(struct tty_struct *tty) +static unsigned int sdio_uart_write_room(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; return FIFO_SIZE - kfifo_len(&port->xmit_fifo); } -static int sdio_uart_chars_in_buffer(struct tty_struct *tty) +static unsigned int sdio_uart_chars_in_buffer(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; return kfifo_len(&port->xmit_fifo); } -static void sdio_uart_send_xchar(struct tty_struct *tty, char ch) +static void sdio_uart_send_xchar(struct tty_struct *tty, u8 ch) { struct sdio_uart_port *port = tty->driver_data; @@ -876,7 +854,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) } static void sdio_uart_set_termios(struct tty_struct *tty, - struct ktermios *old_termios) + const struct ktermios *old_termios) { struct sdio_uart_port *port = tty->driver_data; unsigned int cflag = tty->termios.c_cflag; @@ -900,14 +878,14 @@ static void sdio_uart_set_termios(struct tty_struct *tty, /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { - tty->hw_stopped = 0; + tty->hw_stopped = false; sdio_uart_start_tx(port); } /* Handle turning on CRTSCTS */ if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) { - tty->hw_stopped = 1; + tty->hw_stopped = true; sdio_uart_stop_tx(port); } } @@ -1139,9 +1117,10 @@ static int __init sdio_uart_init(void) int ret; struct tty_driver *tty_drv; - sdio_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR); - if (!tty_drv) - return -ENOMEM; + sdio_uart_tty_driver = tty_drv = tty_alloc_driver(UART_NR, + TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV); + if (IS_ERR(tty_drv)) + return PTR_ERR(tty_drv); tty_drv->driver_name = "sdio_uart"; tty_drv->name = "ttySDIO"; @@ -1149,7 +1128,6 @@ static int __init sdio_uart_init(void) tty_drv->minor_start = 0; tty_drv->type = TTY_DRIVER_TYPE_SERIAL; tty_drv->subtype = SERIAL_TYPE_NORMAL; - tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_drv->init_termios = tty_std_termios; tty_drv->init_termios.c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL; tty_drv->init_termios.c_ispeed = 4800; @@ -1169,7 +1147,7 @@ static int __init sdio_uart_init(void) err2: tty_unregister_driver(tty_drv); err1: - put_tty_driver(tty_drv); + tty_driver_kref_put(tty_drv); return ret; } @@ -1177,11 +1155,12 @@ static void __exit sdio_uart_exit(void) { sdio_unregister_driver(&sdio_uart_driver); tty_unregister_driver(sdio_uart_tty_driver); - put_tty_driver(sdio_uart_tty_driver); + tty_driver_kref_put(sdio_uart_tty_driver); } module_init(sdio_uart_init); module_exit(sdio_uart_exit); MODULE_AUTHOR("Nicolas Pitre"); +MODULE_DESCRIPTION("SDIO UART/GPS driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 319ccd93383d..c5bc6268803e 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Generic GPIO card-detect helper * * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/err.h> @@ -22,12 +19,11 @@ struct mmc_gpio { struct gpio_desc *ro_gpio; struct gpio_desc *cd_gpio; - bool override_ro_active_level; - bool override_cd_active_level; - irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id); + irq_handler_t cd_gpio_isr; char *ro_label; char *cd_label; u32 cd_debounce_delay_ms; + int cd_irq; }; static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) @@ -44,38 +40,50 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) int mmc_gpio_alloc(struct mmc_host *host) { - struct mmc_gpio *ctx = devm_kzalloc(host->parent, - sizeof(*ctx), GFP_KERNEL); - - if (ctx) { - ctx->cd_debounce_delay_ms = 200; - 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; - } + const char *devname = dev_name(host->parent); + struct mmc_gpio *ctx; + + ctx = devm_kzalloc(host->parent, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->cd_debounce_delay_ms = 200; + ctx->cd_label = devm_kasprintf(host->parent, GFP_KERNEL, "%s cd", devname); + if (!ctx->cd_label) + return -ENOMEM; + ctx->ro_label = devm_kasprintf(host->parent, GFP_KERNEL, "%s ro", devname); + if (!ctx->ro_label) + return -ENOMEM; + ctx->cd_irq = -EINVAL; + host->slot.handler_priv = ctx; + host->slot.cd_irq = -EINVAL; + + return 0; +} + +void mmc_gpio_set_cd_irq(struct mmc_host *host, int irq) +{ + struct mmc_gpio *ctx = host->slot.handler_priv; + + if (!ctx || irq < 0) + return; - return ctx ? 0 : -ENOMEM; + ctx->cd_irq = irq; } +EXPORT_SYMBOL(mmc_gpio_set_cd_irq); int mmc_gpio_get_ro(struct mmc_host *host) { struct mmc_gpio *ctx = host->slot.handler_priv; + int cansleep; if (!ctx || !ctx->ro_gpio) return -ENOSYS; - if (ctx->override_ro_active_level) - return !gpiod_get_raw_value_cansleep(ctx->ro_gpio) ^ - !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); - - return gpiod_get_value_cansleep(ctx->ro_gpio); + cansleep = gpiod_cansleep(ctx->ro_gpio); + return cansleep ? + gpiod_get_value_cansleep(ctx->ro_gpio) : + gpiod_get_value(ctx->ro_gpio); } EXPORT_SYMBOL(mmc_gpio_get_ro); @@ -88,13 +96,6 @@ int mmc_gpio_get_cd(struct mmc_host *host) return -ENOSYS; cansleep = gpiod_cansleep(ctx->cd_gpio); - if (ctx->override_cd_active_level) { - int value = cansleep ? - gpiod_get_raw_value_cansleep(ctx->cd_gpio) : - gpiod_get_raw_value(ctx->cd_gpio); - return !value ^ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); - } - return cansleep ? gpiod_get_value_cansleep(ctx->cd_gpio) : gpiod_get_value(ctx->cd_gpio); @@ -114,7 +115,9 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host) * Do not use IRQ if the platform prefers to poll, e.g., because that * IRQ number is already used by another unit and cannot be shared. */ - if (!(host->caps & MMC_CAP_NEEDS_POLL)) + if (ctx->cd_irq >= 0) + irq = ctx->cd_irq; + else if (!(host->caps & MMC_CAP_NEEDS_POLL)) irq = gpiod_to_irq(ctx->cd_gpio); if (irq >= 0) { @@ -156,19 +159,6 @@ int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on) } EXPORT_SYMBOL(mmc_gpio_set_cd_wake); -/* Register an alternate interrupt service routine for - * the card-detect GPIO. - */ -void mmc_gpio_set_cd_isr(struct mmc_host *host, - irqreturn_t (*isr)(int irq, void *dev_id)) -{ - struct mmc_gpio *ctx = host->slot.handler_priv; - - WARN_ON(ctx->cd_gpio_isr); - ctx->cd_gpio_isr = isr; -} -EXPORT_SYMBOL(mmc_gpio_set_cd_isr); - /** * mmc_gpiod_request_cd - request a gpio descriptor for card-detection * @host: mmc host @@ -176,8 +166,6 @@ EXPORT_SYMBOL(mmc_gpio_set_cd_isr); * @idx: index of the GPIO to obtain in the consumer * @override_active_level: ignore %GPIO_ACTIVE_LOW flag * @debounce: debounce time in microseconds - * @gpio_invert: will return whether the GPIO line is inverted or not, set - * to NULL to ignore * * Note that this must be called prior to mmc_add_host() * otherwise the caller must also call mmc_gpiod_request_cd_irq(). @@ -186,7 +174,7 @@ EXPORT_SYMBOL(mmc_gpio_set_cd_isr); */ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, unsigned int idx, bool override_active_level, - unsigned int debounce, bool *gpio_invert) + unsigned int debounce) { struct mmc_gpio *ctx = host->slot.handler_priv; struct gpio_desc *desc; @@ -196,45 +184,69 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, if (IS_ERR(desc)) return PTR_ERR(desc); + /* Update default label if no con_id provided */ + if (!con_id) + gpiod_set_consumer_name(desc, ctx->cd_label); + if (debounce) { ret = gpiod_set_debounce(desc, debounce); if (ret < 0) ctx->cd_debounce_delay_ms = debounce / 1000; } - if (gpio_invert) - *gpio_invert = !gpiod_is_active_low(desc); + /* override forces default (active-low) polarity ... */ + if (override_active_level && !gpiod_is_active_low(desc)) + gpiod_toggle_active_low(desc); + + /* ... or active-high */ + if (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) + gpiod_toggle_active_low(desc); - ctx->override_cd_active_level = override_active_level; ctx->cd_gpio = desc; return 0; } EXPORT_SYMBOL(mmc_gpiod_request_cd); -bool mmc_can_gpio_cd(struct mmc_host *host) +/** + * mmc_gpiod_set_cd_config - set config for card-detection GPIO + * @host: mmc host + * @config: Generic pinconf config (from pinconf_to_config_packed()) + * + * This can be used by mmc host drivers to fixup a card-detection GPIO's config + * (e.g. set PIN_CONFIG_BIAS_PULL_UP) after acquiring the GPIO descriptor + * through mmc_gpiod_request_cd(). + * + * Returns: + * 0 on success, or a negative errno value on error. + */ +int mmc_gpiod_set_cd_config(struct mmc_host *host, unsigned long config) +{ + struct mmc_gpio *ctx = host->slot.handler_priv; + + return gpiod_set_config(ctx->cd_gpio, config); +} +EXPORT_SYMBOL(mmc_gpiod_set_cd_config); + +bool mmc_host_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); +EXPORT_SYMBOL(mmc_host_can_gpio_cd); /** * mmc_gpiod_request_ro - request a gpio descriptor for write protection * @host: mmc host * @con_id: function within the GPIO consumer * @idx: index of the GPIO to obtain in the consumer - * @override_active_level: ignore %GPIO_ACTIVE_LOW flag * @debounce: debounce time in microseconds - * @gpio_invert: will return whether the GPIO line is inverted or not, - * set to NULL to ignore * * Returns zero on success, else an error. */ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, - unsigned int idx, bool override_active_level, - unsigned int debounce, bool *gpio_invert) + unsigned int idx, unsigned int debounce) { struct mmc_gpio *ctx = host->slot.handler_priv; struct gpio_desc *desc; @@ -244,26 +256,29 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, if (IS_ERR(desc)) return PTR_ERR(desc); + /* Update default label if no con_id provided */ + if (!con_id) + gpiod_set_consumer_name(desc, ctx->ro_label); + if (debounce) { ret = gpiod_set_debounce(desc, debounce); if (ret < 0) return ret; } - if (gpio_invert) - *gpio_invert = !gpiod_is_active_low(desc); + if (host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH) + gpiod_toggle_active_low(desc); - ctx->override_ro_active_level = override_active_level; ctx->ro_gpio = desc; return 0; } EXPORT_SYMBOL(mmc_gpiod_request_ro); -bool mmc_can_gpio_ro(struct mmc_host *host) +bool mmc_host_can_gpio_ro(struct mmc_host *host) { struct mmc_gpio *ctx = host->slot.handler_priv; return ctx->ro_gpio ? true : false; } -EXPORT_SYMBOL(mmc_can_gpio_ro); +EXPORT_SYMBOL(mmc_host_can_gpio_ro); diff --git a/drivers/mmc/core/slot-gpio.h b/drivers/mmc/core/slot-gpio.h index a06fd843f025..546a5843b40b 100644 --- a/drivers/mmc/core/slot-gpio.h +++ b/drivers/mmc/core/slot-gpio.h @@ -1,9 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2014 Linaro Ltd * * Author: Ulf Hansson <ulf.hansson@linaro.org> - * - * License terms: GNU General Public License (GPL) version 2 */ #ifndef _MMC_CORE_SLOTGPIO_H #define _MMC_CORE_SLOTGPIO_H |
