diff options
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/block.c | 52 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 7 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 11 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 2 | ||||
-rw-r--r-- | drivers/mmc/core/queue.c | 5 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 7 |
6 files changed, 60 insertions, 24 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 506dc900f5c7..1259ca22d625 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -126,6 +126,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 @@ -330,7 +331,7 @@ static struct attribute *mmc_disk_attrs[] = { static umode_t mmc_disk_attrs_is_visible(struct kobject *kobj, struct attribute *a, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); umode_t mode = a->mode; @@ -609,11 +610,11 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) { /* - * Ensure RPMB/R1B command has completed by polling CMD13 - * "Send Status". + * Ensure RPMB/R1B command has completed by polling CMD13 "Send Status". Here we + * allow to override the default timeout value if a custom timeout is specified. */ - err = mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, false, - MMC_BUSY_IO); + err = mmc_poll_for_busy(card, idata->ic.cmd_timeout_ms ? : MMC_BLK_TIMEOUT_MS, + false, MMC_BUSY_IO); } return err; @@ -676,8 +677,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, @@ -690,15 +692,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 */ @@ -725,18 +728,18 @@ 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_data = idata; - req_to_mmc_queue_req(req)->ioc_count = num_of_cmds; + 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_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]); } @@ -1090,12 +1093,13 @@ 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; - int err = 0, type = MMC_BLK_DISCARD; + int err = 0; blk_status_t status = BLK_STS_OK; if (!mmc_can_erase(card)) { @@ -1111,13 +1115,13 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) if (card->quirks & MMC_QUIRK_INAND_CMD38) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, INAND_CMD38_ARG_EXT_CSD, - card->erase_arg == MMC_TRIM_ARG ? + erase_arg == MMC_TRIM_ARG ? INAND_CMD38_ARG_TRIM : INAND_CMD38_ARG_ERASE, card->ext_csd.generic_cmd6_time); } if (!err) - err = mmc_erase(card, from, nr, card->erase_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; @@ -1127,6 +1131,19 @@ 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; + + mmc_blk_issue_erase_rq(mq, req, MMC_BLK_DISCARD, card->erase_arg); +} + static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, struct request *req) { @@ -2327,6 +2344,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; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index c6ae16d40766..4b70cbfc6d5d 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1988,9 +1988,9 @@ 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); } /** @@ -2017,8 +2017,9 @@ int mmc_hw_reset(struct mmc_card *card) } 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->bus_ops->sw_reset) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index efa95dc4fc4e..89cd48fcec79 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/stat.h> #include <linux/pm_runtime.h> +#include <linux/random.h> #include <linux/sysfs.h> #include <linux/mmc/host.h> @@ -72,6 +73,12 @@ 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. */ @@ -2240,11 +2247,11 @@ static int _mmc_hw_reset(struct mmc_host *host) */ _mmc_flush_cache(host); - if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset && + if ((host->caps & MMC_CAP_HW_RESET) && host->ops->card_hw_reset && mmc_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 { diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 180d7e9d3400..81c55bfd6e0c 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -21,7 +21,7 @@ #define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */ #define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */ -#define MMC_OP_COND_PERIOD_US (1 * 1000) /* 1ms */ +#define MMC_OP_COND_PERIOD_US (4 * 1000) /* 4ms */ #define MMC_OP_COND_TIMEOUT_MS 1000 /* 1s */ static const u8 tuning_blk_pattern_4bit[] = { diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index c69b2d9df6f1..fa5324ceeebe 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -183,14 +183,15 @@ 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; /* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity = SECTOR_SIZE; if (mmc_can_secure_erase_trim(card)) - blk_queue_flag_set(QUEUE_FLAG_SECERASE, q); + blk_queue_max_secure_erase_sectors(q, max_discard); + if (mmc_can_trim(card) && card->erased_byte == 0) + blk_queue_max_write_zeroes_sectors(q, max_discard); } static unsigned short mmc_get_max_segments(struct mmc_host *host) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 68df6b2f49cc..c5f1df6ce4c0 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/stat.h> #include <linux/pm_runtime.h> +#include <linux/random.h> #include <linux/scatterlist.h> #include <linux/sysfs.h> @@ -84,6 +85,12 @@ 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. */ |