* [PATCH 1/8 v5] mmc: block: Anonymize the drv op data pointer
2017-08-20 21:39 [PATCH 0/8] debugfs and RPMB cleanups Linus Walleij
@ 2017-08-20 21:39 ` Linus Walleij
2017-08-20 21:39 ` [PATCH 2/8 v5] mmc: ops: export mmc_get_status() Linus Walleij
` (7 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Linus Walleij @ 2017-08-20 21:39 UTC (permalink / raw)
To: linux-mmc, Ulf Hansson; +Cc: Linus Walleij
We have a data pointer for the ioctl() data, but we need to
pass other data along with the DRV_OP:s, so make this a
void * so it can be reused.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v3->v5:
- No changes just resending
ChangeLog v3->v4:
- No changes just resending
ChangeLog v2->v3:
- No changes just resending
---
drivers/mmc/core/block.c | 8 +++++---
drivers/mmc/core/queue.h | 2 +-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 91e1e93f40e3..30b8b979ea62 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -596,7 +596,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
__GFP_RECLAIM);
idatas[0] = idata;
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL;
- req_to_mmc_queue_req(req)->idata = idatas;
+ 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);
ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
@@ -675,7 +675,7 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
idata[0]->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
__GFP_RECLAIM);
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL;
- req_to_mmc_queue_req(req)->idata = idata;
+ 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);
ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
@@ -1176,6 +1176,7 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
struct mmc_queue_req *mq_rq;
struct mmc_card *card = mq->card;
struct mmc_blk_data *md = mq->blkdata;
+ struct mmc_blk_ioc_data **idata;
int ret;
int i;
@@ -1183,8 +1184,9 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
switch (mq_rq->drv_op) {
case MMC_DRV_OP_IOCTL:
+ idata = mq_rq->drv_op_data;
for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
- ret = __mmc_blk_ioctl_cmd(card, md, mq_rq->idata[i]);
+ ret = __mmc_blk_ioctl_cmd(card, md, idata[i]);
if (ret)
break;
}
diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
index 361b46408e0f..cf26a15a64bf 100644
--- a/drivers/mmc/core/queue.h
+++ b/drivers/mmc/core/queue.h
@@ -51,7 +51,7 @@ struct mmc_queue_req {
struct mmc_async_req areq;
enum mmc_drv_op drv_op;
int drv_op_result;
- struct mmc_blk_ioc_data **idata;
+ void *drv_op_data;
unsigned int ioc_count;
};
--
2.13.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 2/8 v5] mmc: ops: export mmc_get_status()
2017-08-20 21:39 [PATCH 0/8] debugfs and RPMB cleanups Linus Walleij
2017-08-20 21:39 ` [PATCH 1/8 v5] mmc: block: Anonymize the drv op data pointer Linus Walleij
@ 2017-08-20 21:39 ` Linus Walleij
2017-08-20 21:39 ` [PATCH 3/8 v5] mmc: debugfs: Move block debugfs into block module Linus Walleij
` (6 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Linus Walleij @ 2017-08-20 21:39 UTC (permalink / raw)
To: linux-mmc, Ulf Hansson; +Cc: Linus Walleij
This function retrieves the status of the card with the default
number of retries. Since the block layer wants to use this, and
since the block layer is a loadable kernel module, we need to
export this symbol.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v4->v5:
- No changes just resending
ChangeLog v3->v4:
- No changes just resending
ChangeLog v2->v3:
- New patch to fix a build error, enumerating v3 to keep it
together with the other patches.
---
drivers/mmc/core/mmc_ops.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 6dd8ecde5079..54686ca4bfb7 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -83,6 +83,7 @@ int mmc_send_status(struct mmc_card *card, u32 *status)
{
return __mmc_send_status(card, status, MMC_CMD_RETRIES);
}
+EXPORT_SYMBOL_GPL(mmc_send_status);
static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{
--
2.13.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 3/8 v5] mmc: debugfs: Move block debugfs into block module
2017-08-20 21:39 [PATCH 0/8] debugfs and RPMB cleanups Linus Walleij
2017-08-20 21:39 ` [PATCH 1/8 v5] mmc: block: Anonymize the drv op data pointer Linus Walleij
2017-08-20 21:39 ` [PATCH 2/8 v5] mmc: ops: export mmc_get_status() Linus Walleij
@ 2017-08-20 21:39 ` Linus Walleij
2017-08-20 21:39 ` [PATCH 4/8 v5] mmc: block: Move duplicate check Linus Walleij
` (5 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Linus Walleij @ 2017-08-20 21:39 UTC (permalink / raw)
To: linux-mmc, Ulf Hansson; +Cc: Linus Walleij
If we don't have the block layer enabled, we do not present card
status and extcsd in the debugfs.
Debugfs is not ABI, and maintaining files of no relevance for
non-block devices comes at a high maintenance cost if we shall
support it with the block layer compiled out.
The debugfs entries suffer from all the same starvation
issues as the other userspace things, under e.g. a heavy
dd operation.
The expected number of debugfs users utilizing these two
debugfs files is already low as there is an ioctl() to get the
same information using the mmc-tools, and of these few users
the expected number of people using it on SDIO or combo cards
are expected to be zero.
It is therefore logical to move this over to the block layer
when it is enabled, using the new custom requests and issue
it using the block request queue.
On the other hand it moves some debugfs code from debugfs.c
and into block.c.
Tested during heavy dd load by cat:in the status file.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v4->v5:
- Rebased, resending
ChangeLog v3->v4:
- Squash all the refactorings of these operations into a big
commit simply moving all the debugfs over to the block layer
and only creating the files from there.
- Avoid the whole middle-step of creating #if IS_ENABLED()
that was required to move it stepwise from the debugfs file
to the block file.
---
drivers/mmc/core/block.c | 143 +++++++++++++++++++++++++++++++++++++++++++++
drivers/mmc/core/debugfs.c | 89 ----------------------------
drivers/mmc/core/queue.h | 4 ++
3 files changed, 147 insertions(+), 89 deletions(-)
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 30b8b979ea62..6c91e125ab72 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -36,6 +36,7 @@
#include <linux/compat.h>
#include <linux/pm_runtime.h>
#include <linux/idr.h>
+#include <linux/debugfs.h>
#include <linux/mmc/ioctl.h>
#include <linux/mmc/card.h>
@@ -1177,6 +1178,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
struct mmc_card *card = mq->card;
struct mmc_blk_data *md = mq->blkdata;
struct mmc_blk_ioc_data **idata;
+ u8 **ext_csd;
+ u32 status;
int ret;
int i;
@@ -1206,6 +1209,15 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
card->ext_csd.boot_ro_lock |=
EXT_CSD_BOOT_WP_B_PWR_WP_EN;
break;
+ case MMC_DRV_OP_GET_CARD_STATUS:
+ ret = mmc_send_status(card, &status);
+ if (!ret)
+ ret = status;
+ break;
+ case MMC_DRV_OP_GET_EXT_CSD:
+ ext_csd = mq_rq->drv_op_data;
+ ret = mmc_get_ext_csd(card, ext_csd);
+ break;
default:
pr_err("%s: unknown driver specific operation\n",
md->disk->disk_name);
@@ -2246,6 +2258,134 @@ static int mmc_add_disk(struct mmc_blk_data *md)
return ret;
}
+#ifdef CONFIG_DEBUG_FS
+
+static int mmc_dbg_card_status_get(void *data, u64 *val)
+{
+ struct mmc_card *card = data;
+ struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
+ struct mmc_queue *mq = &md->queue;
+ struct request *req;
+ int ret;
+
+ /* Ask the block layer about the card status */
+ req = blk_get_request(mq->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
+ req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
+ blk_execute_rq(mq->queue, NULL, req, 0);
+ ret = req_to_mmc_queue_req(req)->drv_op_result;
+ if (ret >= 0) {
+ *val = ret;
+ ret = 0;
+ }
+
+ return ret;
+}
+DEFINE_SIMPLE_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
+
+static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
+{
+ struct mmc_card *card = inode->i_private;
+ struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
+ struct mmc_queue *mq = &md->queue;
+ struct request *req;
+ char *buf;
+ ssize_t n = 0;
+ u8 *ext_csd;
+ int err, i;
+
+ buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Ask the block layer for the EXT CSD */
+ req = blk_get_request(mq->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
+ req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD;
+ req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
+ blk_execute_rq(mq->queue, NULL, req, 0);
+ err = req_to_mmc_queue_req(req)->drv_op_result;
+ if (err) {
+ pr_err("FAILED %d\n", err);
+ goto out_free;
+ }
+
+ for (i = 0; i < 512; i++)
+ n += sprintf(buf + n, "%02x", ext_csd[i]);
+ n += sprintf(buf + n, "\n");
+
+ if (n != EXT_CSD_STR_LEN) {
+ err = -EINVAL;
+ goto out_free;
+ }
+
+ filp->private_data = buf;
+ kfree(ext_csd);
+ return 0;
+
+out_free:
+ kfree(buf);
+ return err;
+}
+
+static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ char *buf = filp->private_data;
+
+ return simple_read_from_buffer(ubuf, cnt, ppos,
+ buf, EXT_CSD_STR_LEN);
+}
+
+static int mmc_ext_csd_release(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+ return 0;
+}
+
+static const struct file_operations mmc_dbg_ext_csd_fops = {
+ .open = mmc_ext_csd_open,
+ .read = mmc_ext_csd_read,
+ .release = mmc_ext_csd_release,
+ .llseek = default_llseek,
+};
+
+static int mmc_blk_add_debugfs(struct mmc_card *card)
+{
+ struct dentry *root;
+
+ if (!card->debugfs_root)
+ return 0;
+
+ root = card->debugfs_root;
+
+ if (mmc_card_mmc(card) || mmc_card_sd(card)) {
+ if (!debugfs_create_file("status", S_IRUSR, root, card,
+ &mmc_dbg_card_status_fops))
+ return -EIO;
+ }
+
+ if (mmc_card_mmc(card)) {
+ if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
+ &mmc_dbg_ext_csd_fops))
+ return -EIO;
+ }
+
+ return 0;
+}
+
+
+#else
+
+static int mmc_blk_add_debugfs(struct mmc_card *card)
+{
+ return 0;
+}
+
+#endif /* CONFIG_DEBUG_FS */
+
static int mmc_blk_probe(struct mmc_card *card)
{
struct mmc_blk_data *md, *part_md;
@@ -2282,6 +2422,9 @@ static int mmc_blk_probe(struct mmc_card *card)
goto out;
}
+ /* Add two debugfs entries */
+ mmc_blk_add_debugfs(card);
+
pm_runtime_set_autosuspend_delay(&card->dev, 3000);
pm_runtime_use_autosuspend(&card->dev);
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index a1fba5732d66..01e459a34f33 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -281,85 +281,6 @@ void mmc_remove_host_debugfs(struct mmc_host *host)
debugfs_remove_recursive(host->debugfs_root);
}
-static int mmc_dbg_card_status_get(void *data, u64 *val)
-{
- struct mmc_card *card = data;
- u32 status;
- int ret;
-
- mmc_get_card(card);
-
- ret = mmc_send_status(data, &status);
- if (!ret)
- *val = status;
-
- mmc_put_card(card);
-
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
- NULL, "%08llx\n");
-
-#define EXT_CSD_STR_LEN 1025
-
-static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
-{
- struct mmc_card *card = inode->i_private;
- char *buf;
- ssize_t n = 0;
- u8 *ext_csd;
- int err, i;
-
- buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- mmc_get_card(card);
- err = mmc_get_ext_csd(card, &ext_csd);
- mmc_put_card(card);
- if (err)
- goto out_free;
-
- for (i = 0; i < 512; i++)
- n += sprintf(buf + n, "%02x", ext_csd[i]);
- n += sprintf(buf + n, "\n");
-
- if (n != EXT_CSD_STR_LEN) {
- err = -EINVAL;
- goto out_free;
- }
-
- filp->private_data = buf;
- kfree(ext_csd);
- return 0;
-
-out_free:
- kfree(buf);
- return err;
-}
-
-static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf,
- size_t cnt, loff_t *ppos)
-{
- char *buf = filp->private_data;
-
- return simple_read_from_buffer(ubuf, cnt, ppos,
- buf, EXT_CSD_STR_LEN);
-}
-
-static int mmc_ext_csd_release(struct inode *inode, struct file *file)
-{
- kfree(file->private_data);
- return 0;
-}
-
-static const struct file_operations mmc_dbg_ext_csd_fops = {
- .open = mmc_ext_csd_open,
- .read = mmc_ext_csd_read,
- .release = mmc_ext_csd_release,
- .llseek = default_llseek,
-};
-
void mmc_add_card_debugfs(struct mmc_card *card)
{
struct mmc_host *host = card->host;
@@ -382,16 +303,6 @@ void mmc_add_card_debugfs(struct mmc_card *card)
if (!debugfs_create_x32("state", S_IRUSR, root, &card->state))
goto err;
- if (mmc_card_mmc(card) || mmc_card_sd(card))
- if (!debugfs_create_file("status", S_IRUSR, root, card,
- &mmc_dbg_card_status_fops))
- goto err;
-
- if (mmc_card_mmc(card))
- if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
- &mmc_dbg_ext_csd_fops))
- goto err;
-
return;
err:
diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
index cf26a15a64bf..04fc89360a7a 100644
--- a/drivers/mmc/core/queue.h
+++ b/drivers/mmc/core/queue.h
@@ -36,10 +36,14 @@ struct mmc_blk_request {
* enum mmc_drv_op - enumerates the operations in the mmc_queue_req
* @MMC_DRV_OP_IOCTL: ioctl operation
* @MMC_DRV_OP_BOOT_WP: write protect boot partitions
+ * @MMC_DRV_OP_GET_CARD_STATUS: get card status
+ * @MMC_DRV_OP_GET_EXT_CSD: get the EXT CSD from an eMMC card
*/
enum mmc_drv_op {
MMC_DRV_OP_IOCTL,
MMC_DRV_OP_BOOT_WP,
+ MMC_DRV_OP_GET_CARD_STATUS,
+ MMC_DRV_OP_GET_EXT_CSD,
};
struct mmc_queue_req {
--
2.13.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 4/8 v5] mmc: block: Move duplicate check
2017-08-20 21:39 [PATCH 0/8] debugfs and RPMB cleanups Linus Walleij
` (2 preceding siblings ...)
2017-08-20 21:39 ` [PATCH 3/8 v5] mmc: debugfs: Move block debugfs into block module Linus Walleij
@ 2017-08-20 21:39 ` Linus Walleij
2017-08-20 21:39 ` [PATCH 5/8 v5] mmc: block: Refactor mmc_blk_part_switch() Linus Walleij
` (4 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Linus Walleij @ 2017-08-20 21:39 UTC (permalink / raw)
To: linux-mmc, Ulf Hansson; +Cc: Linus Walleij, Shawn Lin
mmc_blk_ioctl() calls either mmc_blk_ioctl_cmd() or
mmc_blk_ioctl_multi_cmd() and each of these make the same
check. Factor it into a new helper function, call it on
both branches of the switch() statement and save a chunk
of duplicate code.
Cc: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v5:
- Rebase, put on top of the other cleanups.
- Number v5 to keep together with the rest of the series.
ChangeLog v1->v2:
- We need to check the block device only if an actual
well-known ioctl() is coming in, on the path of the
switch() statments, only those branches that handle
actual ioctl()s. Create a new helper function to check
the block device and call that.
---
drivers/mmc/core/block.c | 36 ++++++++++++++++++++----------------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 6c91e125ab72..b0585f7971f1 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -564,14 +564,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
int err = 0, ioc_err = 0;
struct request *req;
- /*
- * The caller must have CAP_SYS_RAWIO, and must be calling this on the
- * whole block device, not on a partition. This prevents overspray
- * between sibling partitions.
- */
- if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
- return -EPERM;
-
idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
if (IS_ERR(idata))
return PTR_ERR(idata);
@@ -624,14 +616,6 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
__u64 num_of_cmds;
struct request *req;
- /*
- * The caller must have CAP_SYS_RAWIO, and must be calling this on the
- * whole block device, not on a partition. This prevents overspray
- * between sibling partitions.
- */
- if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
- return -EPERM;
-
if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
sizeof(num_of_cmds)))
return -EFAULT;
@@ -698,14 +682,34 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
return ioc_err ? ioc_err : err;
}
+static int mmc_blk_check_blkdev(struct block_device *bdev)
+{
+ /*
+ * The caller must have CAP_SYS_RAWIO, and must be calling this on the
+ * whole block device, not on a partition. This prevents overspray
+ * between sibling partitions.
+ */
+ if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
+ return -EPERM;
+ return 0;
+}
+
static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
+ int ret;
+
switch (cmd) {
case MMC_IOC_CMD:
+ ret = mmc_blk_check_blkdev(bdev);
+ if (ret)
+ return ret;
return mmc_blk_ioctl_cmd(bdev,
(struct mmc_ioc_cmd __user *)arg);
case MMC_IOC_MULTI_CMD:
+ ret = mmc_blk_check_blkdev(bdev);
+ if (ret)
+ return ret;
return mmc_blk_ioctl_multi_cmd(bdev,
(struct mmc_ioc_multi_cmd __user *)arg);
default:
--
2.13.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 5/8 v5] mmc: block: Refactor mmc_blk_part_switch()
2017-08-20 21:39 [PATCH 0/8] debugfs and RPMB cleanups Linus Walleij
` (3 preceding siblings ...)
2017-08-20 21:39 ` [PATCH 4/8 v5] mmc: block: Move duplicate check Linus Walleij
@ 2017-08-20 21:39 ` Linus Walleij
2017-08-20 21:39 ` [PATCH 6/8 v5] mmc: block: Reparametrize mmc_blk_ioctl_[multi]_cmd() Linus Walleij
` (3 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Linus Walleij @ 2017-08-20 21:39 UTC (permalink / raw)
To: linux-mmc, Ulf Hansson; +Cc: Linus Walleij
Instead of passing a struct mmc_blk_data * to mmc_blk_part_switch()
let's pass the actual partition type we want to switch to. This
is necessary in order not to have a block device with a backing
mmc_blk_data and request queue and all for every hardware partition,
such as RPMB.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v5:
- Rebase.
- Renumber v5 to keep together with the rest of the series.
---
drivers/mmc/core/block.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index b0585f7971f1..3abdbab401ad 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -127,7 +127,7 @@ module_param(perdev_minors, int, 0444);
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
static inline int mmc_blk_part_switch(struct mmc_card *card,
- struct mmc_blk_data *md);
+ unsigned int part_type);
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
@@ -488,7 +488,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
mrq.cmd = &cmd;
- err = mmc_blk_part_switch(card, md);
+ err = mmc_blk_part_switch(card, md->part_type);
if (err)
return err;
@@ -768,29 +768,29 @@ static int mmc_blk_part_switch_post(struct mmc_card *card,
}
static inline int mmc_blk_part_switch(struct mmc_card *card,
- struct mmc_blk_data *md)
+ unsigned int part_type)
{
int ret = 0;
struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
- if (main_md->part_curr == md->part_type)
+ if (main_md->part_curr == part_type)
return 0;
if (mmc_card_mmc(card)) {
u8 part_config = card->ext_csd.part_config;
- ret = mmc_blk_part_switch_pre(card, md->part_type);
+ ret = mmc_blk_part_switch_pre(card, part_type);
if (ret)
return ret;
part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
- part_config |= md->part_type;
+ part_config |= part_type;
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_PART_CONFIG, part_config,
card->ext_csd.part_time);
if (ret) {
- mmc_blk_part_switch_post(card, md->part_type);
+ mmc_blk_part_switch_post(card, part_type);
return ret;
}
@@ -799,7 +799,7 @@ static inline int mmc_blk_part_switch(struct mmc_card *card,
ret = mmc_blk_part_switch_post(card, main_md->part_curr);
}
- main_md->part_curr = md->part_type;
+ main_md->part_curr = part_type;
return ret;
}
@@ -1142,7 +1142,7 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
int part_err;
main_md->part_curr = main_md->part_type;
- part_err = mmc_blk_part_switch(host->card, md);
+ part_err = mmc_blk_part_switch(host->card, md->part_type);
if (part_err) {
/*
* We have failed to get back into the correct
@@ -1181,6 +1181,7 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
struct mmc_queue_req *mq_rq;
struct mmc_card *card = mq->card;
struct mmc_blk_data *md = mq->blkdata;
+ struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
struct mmc_blk_ioc_data **idata;
u8 **ext_csd;
u32 status;
@@ -1199,7 +1200,7 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
}
/* Always switch back to main area after RPMB access */
if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
- mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
+ mmc_blk_part_switch(card, main_md->part_type);
break;
case MMC_DRV_OP_BOOT_WP:
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
@@ -1922,7 +1923,7 @@ void mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
/* claim host only for the first request */
mmc_get_card(card);
- ret = mmc_blk_part_switch(card, md);
+ ret = mmc_blk_part_switch(card, md->part_type);
if (ret) {
if (req) {
blk_end_request_all(req, BLK_STS_IOERR);
@@ -2456,7 +2457,7 @@ static void mmc_blk_remove(struct mmc_card *card)
mmc_blk_remove_parts(card, md);
pm_runtime_get_sync(&card->dev);
mmc_claim_host(card->host);
- mmc_blk_part_switch(card, md);
+ mmc_blk_part_switch(card, md->part_type);
mmc_release_host(card->host);
if (card->type != MMC_TYPE_SD_COMBO)
pm_runtime_disable(&card->dev);
--
2.13.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 6/8 v5] mmc: block: Reparametrize mmc_blk_ioctl_[multi]_cmd()
2017-08-20 21:39 [PATCH 0/8] debugfs and RPMB cleanups Linus Walleij
` (4 preceding siblings ...)
2017-08-20 21:39 ` [PATCH 5/8 v5] mmc: block: Refactor mmc_blk_part_switch() Linus Walleij
@ 2017-08-20 21:39 ` Linus Walleij
2017-08-20 21:39 ` [PATCH 7/8 v5] mmc: block: Convert RPMB to a character device Linus Walleij
` (2 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Linus Walleij @ 2017-08-20 21:39 UTC (permalink / raw)
To: linux-mmc, Ulf Hansson; +Cc: Linus Walleij
Instead of passing a block device to
mmc_blk_ioctl[_multi]_cmd(), let's pass struct mmc_blk_data()
so we operate ioctl()s on the MMC block device representation
rather than the vanilla block device.
This saves a little duplicated code and makes it possible to
issue ioctl()s not targeted for a specific block device but
rather for a specific partition/area.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v5:
- Rebase.
- Renumber v5 to keep together with the rest of the series.
---
drivers/mmc/core/block.c | 43 ++++++++++++++++++-------------------------
1 file changed, 18 insertions(+), 25 deletions(-)
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 3abdbab401ad..502068b155b9 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -553,12 +553,11 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
return err;
}
-static int mmc_blk_ioctl_cmd(struct block_device *bdev,
+static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
struct mmc_ioc_cmd __user *ic_ptr)
{
struct mmc_blk_ioc_data *idata;
struct mmc_blk_ioc_data *idatas[1];
- struct mmc_blk_data *md;
struct mmc_queue *mq;
struct mmc_card *card;
int err = 0, ioc_err = 0;
@@ -568,12 +567,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
if (IS_ERR(idata))
return PTR_ERR(idata);
- md = mmc_blk_get(bdev->bd_disk);
- if (!md) {
- err = -EINVAL;
- goto cmd_err;
- }
-
card = md->queue.card;
if (IS_ERR(card)) {
err = PTR_ERR(card);
@@ -597,20 +590,17 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
blk_put_request(req);
cmd_done:
- mmc_blk_put(md);
-cmd_err:
kfree(idata->buf);
kfree(idata);
return ioc_err ? ioc_err : err;
}
-static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
+static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
struct mmc_ioc_multi_cmd __user *user)
{
struct mmc_blk_ioc_data **idata = NULL;
struct mmc_ioc_cmd __user *cmds = user->cmds;
struct mmc_card *card;
- struct mmc_blk_data *md;
struct mmc_queue *mq;
int i, err = 0, ioc_err = 0;
__u64 num_of_cmds;
@@ -639,16 +629,10 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
}
}
- md = mmc_blk_get(bdev->bd_disk);
- if (!md) {
- err = -EINVAL;
- goto cmd_err;
- }
-
card = md->queue.card;
if (IS_ERR(card)) {
err = PTR_ERR(card);
- goto cmd_done;
+ goto cmd_err;
}
@@ -671,8 +655,6 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
blk_put_request(req);
-cmd_done:
- mmc_blk_put(md);
cmd_err:
for (i = 0; i < num_of_cmds; i++) {
kfree(idata[i]->buf);
@@ -697,6 +679,7 @@ static int mmc_blk_check_blkdev(struct block_device *bdev)
static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
+ struct mmc_blk_data *md;
int ret;
switch (cmd) {
@@ -704,14 +687,24 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
ret = mmc_blk_check_blkdev(bdev);
if (ret)
return ret;
- return mmc_blk_ioctl_cmd(bdev,
- (struct mmc_ioc_cmd __user *)arg);
+ md = mmc_blk_get(bdev->bd_disk);
+ if (!md)
+ return -EINVAL;
+ ret = mmc_blk_ioctl_cmd(md,
+ (struct mmc_ioc_cmd __user *)arg);
+ mmc_blk_put(md);
+ return ret;
case MMC_IOC_MULTI_CMD:
ret = mmc_blk_check_blkdev(bdev);
if (ret)
return ret;
- return mmc_blk_ioctl_multi_cmd(bdev,
- (struct mmc_ioc_multi_cmd __user *)arg);
+ md = mmc_blk_get(bdev->bd_disk);
+ if (!md)
+ return -EINVAL;
+ ret = mmc_blk_ioctl_multi_cmd(md,
+ (struct mmc_ioc_multi_cmd __user *)arg);
+ mmc_blk_put(md);
+ return ret;
default:
return -EINVAL;
}
--
2.13.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 7/8 v5] mmc: block: Convert RPMB to a character device
2017-08-20 21:39 [PATCH 0/8] debugfs and RPMB cleanups Linus Walleij
` (5 preceding siblings ...)
2017-08-20 21:39 ` [PATCH 6/8 v5] mmc: block: Reparametrize mmc_blk_ioctl_[multi]_cmd() Linus Walleij
@ 2017-08-20 21:39 ` Linus Walleij
2017-08-21 18:59 ` Winkler, Tomas
2017-08-20 21:39 ` [PATCH 8/8 v5] mmc: block: Delete mmc_access_rpmb() Linus Walleij
2017-08-22 11:15 ` [PATCH 0/8] debugfs and RPMB cleanups Ulf Hansson
8 siblings, 1 reply; 13+ messages in thread
From: Linus Walleij @ 2017-08-20 21:39 UTC (permalink / raw)
To: linux-mmc, Ulf Hansson; +Cc: Linus Walleij, Tomas Winkler
The RPMB partition on the eMMC devices is a special area used
for storing cryptographically safe information signed by a
special secret key. To write and read records from this special
area, authentication is needed.
The RPMB area is *only* and *exclusively* accessed using
ioctl():s from userspace. It is not really a block device,
as blocks cannot be read or written from the device, also
the signed chunks that can be stored on the RPMB are actually
256 bytes, not 512 making a block device a real bad fit.
Currently the RPMB partition spawns a separate block device
named /dev/mmcblkNrpmb for each device with an RPMB partition,
including the creation of a block queue with its own kernel
thread and all overhead associated with this. On the Ux500
HREFv60 platform, for example, the two eMMCs means that two
block queues with separate threads are created for no use
whatsoever.
I have concluded that this block device design for RPMB is
actually pretty wrong. The RPMB area should have been designed
to be accessed from /dev/mmcblkN directly, using ioctl()s on
the main block device. It is however way too late to change
that, since userspace expects to open an RPMB device in
/dev/mmcblkNrpmb and we cannot break userspace.
This patch tries to amend the situation using the following
strategy:
- Stop creating a block device for the RPMB partition/area
- Instead create a custom, dynamic character device with
the same name.
- Make this new character device support exactly the same
set of ioctl()s as the old block device.
- Wrap the requests back to the same ioctl() handlers, but
issue them on the block queue of the main partition/area,
i.e. /dev/mmcblkN
We need to create a special "rpmb" bus type in order to get
udev and/or busybox hot/coldplug to instantiate the device
node properly.
Before the patch, this appears in 'ps aux':
101 root 0:00 [mmcqd/2rpmb]
123 root 0:00 [mmcqd/3rpmb]
After applying the patch these surplus block queue threads
are gone, but RPMB is as usable as ever using the userspace
MMC tools, such as 'mmc rpmb read-counter'.
We get instead those dynamice devices in /dev:
brw-rw---- 1 root root 179, 0 Jan 1 2000 mmcblk0
brw-rw---- 1 root root 179, 1 Jan 1 2000 mmcblk0p1
brw-rw---- 1 root root 179, 2 Jan 1 2000 mmcblk0p2
brw-rw---- 1 root root 179, 5 Jan 1 2000 mmcblk0p5
brw-rw---- 1 root root 179, 8 Jan 1 2000 mmcblk2
brw-rw---- 1 root root 179, 16 Jan 1 2000 mmcblk2boot0
brw-rw---- 1 root root 179, 24 Jan 1 2000 mmcblk2boot1
crw-rw---- 1 root root 248, 0 Jan 1 2000 mmcblk2rpmb
brw-rw---- 1 root root 179, 32 Jan 1 2000 mmcblk3
brw-rw---- 1 root root 179, 40 Jan 1 2000 mmcblk3boot0
brw-rw---- 1 root root 179, 48 Jan 1 2000 mmcblk3boot1
brw-rw---- 1 root root 179, 33 Jan 1 2000 mmcblk3p1
crw-rw---- 1 root root 248, 1 Jan 1 2000 mmcblk3rpmb
Notice the (248,0) and (248,1) character devices for RPMB.
Cc: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1 (RFC) -> v5:
- Rebase.
- Drop discussion comments, let's go for this unless someone
has a better idea.
- Rename rpmb_devt and rpmb_bus_type to mmc_rpmb_devt and
mmc_rpmb_bus_type as requested by Tomas.
- Handle multiple RPMB partitions as requested by Tomas.
- Renumber v5 to keep together with the rest of the series.
---
drivers/mmc/core/block.c | 286 +++++++++++++++++++++++++++++++++++++++++++----
drivers/mmc/core/queue.h | 2 +
2 files changed, 266 insertions(+), 22 deletions(-)
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 502068b155b9..27e1cf07a7a2 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -28,6 +28,7 @@
#include <linux/hdreg.h>
#include <linux/kdev_t.h>
#include <linux/blkdev.h>
+#include <linux/cdev.h>
#include <linux/mutex.h>
#include <linux/scatterlist.h>
#include <linux/string_helpers.h>
@@ -86,6 +87,7 @@ static int max_devices;
#define MAX_DEVICES 256
static DEFINE_IDA(mmc_blk_ida);
+static DEFINE_IDA(mmc_rpmb_ida);
/*
* There is one mmc_blk_data per slot.
@@ -96,6 +98,7 @@ struct mmc_blk_data {
struct gendisk *disk;
struct mmc_queue queue;
struct list_head part;
+ struct list_head rpmbs;
unsigned int flags;
#define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */
@@ -121,6 +124,32 @@ struct mmc_blk_data {
int area_type;
};
+/* Device type for RPMB character devices */
+static dev_t mmc_rpmb_devt;
+
+/* Bus type for RPMB character devices */
+static struct bus_type mmc_rpmb_bus_type = {
+ .name = "rpmb",
+};
+
+/**
+ * struct mmc_rpmb_data - special RPMB device type for these areas
+ * @dev: the device for the RPMB area
+ * @chrdev: character device for the RPMB area
+ * @id: unique device ID number
+ * @part_index: partition index (0 on first)
+ * @md: parent MMC block device
+ * @node: list item, so we can put this device on a list
+ */
+struct mmc_rpmb_data {
+ struct device dev;
+ struct cdev chrdev;
+ int id;
+ unsigned int part_index;
+ struct mmc_blk_data *md;
+ struct list_head node;
+};
+
static DEFINE_MUTEX(open_lock);
module_param(perdev_minors, int, 0444);
@@ -299,6 +328,7 @@ struct mmc_blk_ioc_data {
struct mmc_ioc_cmd ic;
unsigned char *buf;
u64 buf_bytes;
+ struct mmc_rpmb_data *rpmb;
};
static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
@@ -437,14 +467,25 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
struct mmc_request mrq = {};
struct scatterlist sg;
int err;
- bool is_rpmb = false;
+ unsigned int target_part;
u32 status = 0;
if (!card || !md || !idata)
return -EINVAL;
- if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
- is_rpmb = true;
+ /*
+ * The RPMB accesses comes in from the character device, so we
+ * need to target these explicitly. Else we just target the
+ * partition type for the block device the ioctl() was issued
+ * on.
+ */
+ if (idata->rpmb) {
+ /* Support multiple RPMB partitions */
+ target_part = idata->rpmb->part_index;
+ target_part |= EXT_CSD_PART_CONFIG_ACC_RPMB;
+ } else {
+ target_part = md->part_type;
+ }
cmd.opcode = idata->ic.opcode;
cmd.arg = idata->ic.arg;
@@ -488,7 +529,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
mrq.cmd = &cmd;
- err = mmc_blk_part_switch(card, md->part_type);
+ err = mmc_blk_part_switch(card, target_part);
if (err)
return err;
@@ -498,7 +539,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
return err;
}
- if (is_rpmb) {
+ if (idata->rpmb) {
err = mmc_set_blockcount(card, data.blocks,
idata->ic.write_flag & (1 << 31));
if (err)
@@ -538,7 +579,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
- if (is_rpmb) {
+ if (idata->rpmb) {
/*
* Ensure RPMB command has completed by polling CMD13
* "Send Status".
@@ -554,7 +595,8 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
}
static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
- struct mmc_ioc_cmd __user *ic_ptr)
+ struct mmc_ioc_cmd __user *ic_ptr,
+ struct mmc_rpmb_data *rpmb)
{
struct mmc_blk_ioc_data *idata;
struct mmc_blk_ioc_data *idatas[1];
@@ -566,6 +608,8 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
if (IS_ERR(idata))
return PTR_ERR(idata);
+ /* This will be NULL on non-RPMB ioctl():s */
+ idata->rpmb = rpmb;
card = md->queue.card;
if (IS_ERR(card)) {
@@ -581,7 +625,10 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
__GFP_RECLAIM);
idatas[0] = idata;
- req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL;
+ if (rpmb)
+ req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL_RPMB;
+ else
+ req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL;
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);
@@ -596,7 +643,8 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
}
static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
- struct mmc_ioc_multi_cmd __user *user)
+ struct mmc_ioc_multi_cmd __user *user,
+ struct mmc_rpmb_data *rpmb)
{
struct mmc_blk_ioc_data **idata = NULL;
struct mmc_ioc_cmd __user *cmds = user->cmds;
@@ -627,6 +675,8 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
num_of_cmds = i;
goto cmd_err;
}
+ /* This will be NULL on non-RPMB ioctl():s */
+ idata[i]->rpmb = rpmb;
}
card = md->queue.card;
@@ -643,7 +693,10 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
req = blk_get_request(mq->queue,
idata[0]->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
__GFP_RECLAIM);
- req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL;
+ if (rpmb)
+ req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL_RPMB;
+ else
+ req_to_mmc_queue_req(req)->drv_op = 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;
blk_execute_rq(mq->queue, NULL, req, 0);
@@ -691,7 +744,8 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
if (!md)
return -EINVAL;
ret = mmc_blk_ioctl_cmd(md,
- (struct mmc_ioc_cmd __user *)arg);
+ (struct mmc_ioc_cmd __user *)arg,
+ NULL);
mmc_blk_put(md);
return ret;
case MMC_IOC_MULTI_CMD:
@@ -702,7 +756,8 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
if (!md)
return -EINVAL;
ret = mmc_blk_ioctl_multi_cmd(md,
- (struct mmc_ioc_multi_cmd __user *)arg);
+ (struct mmc_ioc_multi_cmd __user *)arg,
+ NULL);
mmc_blk_put(md);
return ret;
default:
@@ -1174,17 +1229,19 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
struct mmc_queue_req *mq_rq;
struct mmc_card *card = mq->card;
struct mmc_blk_data *md = mq->blkdata;
- struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
struct mmc_blk_ioc_data **idata;
+ bool rpmb_ioctl;
u8 **ext_csd;
u32 status;
int ret;
int i;
mq_rq = req_to_mmc_queue_req(req);
+ rpmb_ioctl = (mq_rq->drv_op == MMC_DRV_OP_IOCTL_RPMB);
switch (mq_rq->drv_op) {
case MMC_DRV_OP_IOCTL:
+ 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]);
@@ -1192,8 +1249,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
break;
}
/* Always switch back to main area after RPMB access */
- if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
- mmc_blk_part_switch(card, main_md->part_type);
+ if (rpmb_ioctl)
+ mmc_blk_part_switch(card, 0);
break;
case MMC_DRV_OP_BOOT_WP:
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
@@ -2022,6 +2079,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
spin_lock_init(&md->lock);
INIT_LIST_HEAD(&md->part);
+ INIT_LIST_HEAD(&md->rpmbs);
md->usage = 1;
ret = mmc_init_queue(&md->queue, card, &md->lock, subname);
@@ -2140,6 +2198,153 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
return 0;
}
+/**
+ * rpmb_ioctl() - ioctl handler for the RPMB chardev
+ * @filp: the character device file
+ * @cmd: the ioctl() command
+ * @arg: the argument from userspace
+ *
+ * This will essentially just redirect the ioctl()s coming in over to
+ * the main block device spawning the RPMB character device.
+ */
+static long rpmb_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct mmc_rpmb_data *rpmb = filp->private_data;
+ int ret;
+
+ switch (cmd) {
+ case MMC_IOC_CMD:
+ ret = mmc_blk_ioctl_cmd(rpmb->md,
+ (struct mmc_ioc_cmd __user *)arg,
+ rpmb);
+ break;
+ case MMC_IOC_MULTI_CMD:
+ ret = mmc_blk_ioctl_multi_cmd(rpmb->md,
+ (struct mmc_ioc_multi_cmd __user *)arg,
+ rpmb);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static long rpmb_ioctl_compat(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ return rpmb_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+static int rpmb_chrdev_open(struct inode *inode, struct file *filp)
+{
+ struct mmc_rpmb_data *rpmb = container_of(inode->i_cdev,
+ struct mmc_rpmb_data, chrdev);
+
+ get_device(&rpmb->dev);
+ filp->private_data = rpmb;
+ mutex_lock(&open_lock);
+ rpmb->md->usage++;
+ mutex_unlock(&open_lock);
+
+ return nonseekable_open(inode, filp);
+}
+
+static int rpmb_chrdev_release(struct inode *inode, struct file *filp)
+{
+ struct mmc_rpmb_data *rpmb = container_of(inode->i_cdev,
+ struct mmc_rpmb_data, chrdev);
+
+ put_device(&rpmb->dev);
+ mutex_lock(&open_lock);
+ rpmb->md->usage--;
+ mutex_unlock(&open_lock);
+
+ return 0;
+}
+
+static const struct file_operations rpmb_fileops = {
+ .release = rpmb_chrdev_release,
+ .open = rpmb_chrdev_open,
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .unlocked_ioctl = rpmb_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = rpmb_ioctl_compat,
+#endif
+};
+
+
+static int mmc_blk_alloc_rpmb_part(struct mmc_card *card,
+ struct mmc_blk_data *md,
+ unsigned int part_index,
+ sector_t size,
+ const char *subname)
+{
+ int devidx, ret;
+ char rpmb_name[DISK_NAME_LEN];
+ char cap_str[10];
+ 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);
+ if (devidx < 0)
+ return devidx;
+
+ rpmb = kzalloc(sizeof(*rpmb), GFP_KERNEL);
+ if (!rpmb)
+ return -ENOMEM;
+
+ snprintf(rpmb_name, sizeof(rpmb_name),
+ "mmcblk%u%s", card->host->index, subname ? subname : "");
+
+ rpmb->id = devidx;
+ rpmb->part_index = part_index;
+ rpmb->dev.init_name = rpmb_name;
+ rpmb->dev.bus = &mmc_rpmb_bus_type;
+ rpmb->dev.devt = MKDEV(MAJOR(mmc_rpmb_devt), rpmb->id);
+ rpmb->dev.parent = &card->dev;
+ device_initialize(&rpmb->dev);
+ dev_set_drvdata(&rpmb->dev, rpmb);
+ rpmb->md = md;
+
+ cdev_init(&rpmb->chrdev, &rpmb_fileops);
+ rpmb->chrdev.owner = THIS_MODULE;
+ ret = cdev_device_add(&rpmb->chrdev, &rpmb->dev);
+ if (ret) {
+ pr_err("%s: could not add character device\n", rpmb_name);
+ goto out_remove_ida;
+ }
+
+ list_add(&rpmb->node, &md->rpmbs);
+
+ 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,
+ MAJOR(mmc_rpmb_devt), rpmb->id);
+
+ return 0;
+
+out_remove_ida:
+ ida_simple_remove(&mmc_rpmb_ida, rpmb->id);
+ kfree(rpmb);
+ return ret;
+}
+
+static void mmc_blk_remove_rpmb_part(struct mmc_rpmb_data *rpmb)
+{
+ cdev_device_del(&rpmb->chrdev, &rpmb->dev);
+ device_del(&rpmb->dev);
+ ida_simple_remove(&mmc_rpmb_ida, rpmb->id);
+ kfree(rpmb);
+}
+
/* MMC Physical partitions consist of two boot partitions and
* up to four general purpose partitions.
* For each partition enabled in EXT_CSD a block device will be allocatedi
@@ -2148,13 +2353,26 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
{
- int idx, ret = 0;
+ int idx, ret;
if (!mmc_card_mmc(card))
return 0;
for (idx = 0; idx < card->nr_parts; idx++) {
- if (card->part[idx].size) {
+ if (card->part[idx].area_type & MMC_BLK_DATA_AREA_RPMB) {
+ /*
+ * RPMB partitions does not provide block access, they
+ * are only accessed using ioctl():s. Thus create
+ * special RPMB block devices that do not have a
+ * backing block queue for these.
+ */
+ ret = mmc_blk_alloc_rpmb_part(card, md,
+ card->part[idx].part_cfg,
+ card->part[idx].size >> 9,
+ card->part[idx].name);
+ if (ret)
+ return ret;
+ } else if (card->part[idx].size) {
ret = mmc_blk_alloc_part(card, md,
card->part[idx].part_cfg,
card->part[idx].size >> 9,
@@ -2166,7 +2384,7 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
}
}
- return ret;
+ return 0;
}
static void mmc_blk_remove_req(struct mmc_blk_data *md)
@@ -2203,7 +2421,15 @@ static void mmc_blk_remove_parts(struct mmc_card *card,
{
struct list_head *pos, *q;
struct mmc_blk_data *part_md;
+ struct mmc_rpmb_data *rpmb;
+ /* Remove RPMB partitions */
+ list_for_each_safe(pos, q, &md->rpmbs) {
+ rpmb = list_entry(pos, struct mmc_rpmb_data, node);
+ list_del(pos);
+ mmc_blk_remove_rpmb_part(rpmb);
+ }
+ /* Remove block partitions */
list_for_each_safe(pos, q, &md->part) {
part_md = list_entry(pos, struct mmc_blk_data, part);
list_del(pos);
@@ -2522,6 +2748,17 @@ static int __init mmc_blk_init(void)
{
int res;
+ res = bus_register(&mmc_rpmb_bus_type);
+ if (res < 0) {
+ pr_err("mmcblk: could not register RPMB bus type\n");
+ return res;
+ }
+ res = alloc_chrdev_region(&mmc_rpmb_devt, 0, MAX_DEVICES, "rpmb");
+ if (res < 0) {
+ pr_err("mmcblk: failed to allocate rpmb chrdev region\n");
+ goto out_bus_unreg;
+ }
+
if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
pr_info("mmcblk: using %d minors per device\n", perdev_minors);
@@ -2529,16 +2766,20 @@ static int __init mmc_blk_init(void)
res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
if (res)
- goto out;
+ goto out_chrdev_unreg;
res = mmc_register_driver(&mmc_driver);
if (res)
- goto out2;
+ goto out_blkdev_unreg;
return 0;
- out2:
+
+out_blkdev_unreg:
unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
- out:
+out_chrdev_unreg:
+ unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
+out_bus_unreg:
+ bus_unregister(&mmc_rpmb_bus_type);
return res;
}
@@ -2546,6 +2787,7 @@ static void __exit mmc_blk_exit(void)
{
mmc_unregister_driver(&mmc_driver);
unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
+ unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
}
module_init(mmc_blk_init);
diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
index 04fc89360a7a..a2b6a9fcab01 100644
--- a/drivers/mmc/core/queue.h
+++ b/drivers/mmc/core/queue.h
@@ -35,12 +35,14 @@ struct mmc_blk_request {
/**
* enum mmc_drv_op - enumerates the operations in the mmc_queue_req
* @MMC_DRV_OP_IOCTL: ioctl operation
+ * @MMC_DRV_OP_IOCTL_RPMB: RPMB-oriented ioctl operation
* @MMC_DRV_OP_BOOT_WP: write protect boot partitions
* @MMC_DRV_OP_GET_CARD_STATUS: get card status
* @MMC_DRV_OP_GET_EXT_CSD: get the EXT CSD from an eMMC card
*/
enum mmc_drv_op {
MMC_DRV_OP_IOCTL,
+ MMC_DRV_OP_IOCTL_RPMB,
MMC_DRV_OP_BOOT_WP,
MMC_DRV_OP_GET_CARD_STATUS,
MMC_DRV_OP_GET_EXT_CSD,
--
2.13.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 7/8 v5] mmc: block: Convert RPMB to a character device
2017-08-20 21:39 ` [PATCH 7/8 v5] mmc: block: Convert RPMB to a character device Linus Walleij
@ 2017-08-21 18:59 ` Winkler, Tomas
0 siblings, 0 replies; 13+ messages in thread
From: Winkler, Tomas @ 2017-08-21 18:59 UTC (permalink / raw)
To: ulf.hansson@linaro.org, linux-mmc@vger.kernel.org,
linus.walleij@linaro.org
On Sun, 2017-08-20 at 23:39 +0200, Linus Walleij wrote:
> The RPMB partition on the eMMC devices is a special area used
> for storing cryptographically safe information signed by a
> special secret key. To write and read records from this special
> area, authentication is needed.
>
> The RPMB area is *only* and *exclusively* accessed using
> ioctl():s from userspace. It is not really a block device,
> as blocks cannot be read or written from the device, also
> the signed chunks that can be stored on the RPMB are actually
> 256 bytes, not 512 making a block device a real bad fit.
>
> Currently the RPMB partition spawns a separate block device
> named /dev/mmcblkNrpmb for each device with an RPMB partition,
> including the creation of a block queue with its own kernel
> thread and all overhead associated with this. On the Ux500
> HREFv60 platform, for example, the two eMMCs means that two
> block queues with separate threads are created for no use
> whatsoever.
>
> I have concluded that this block device design for RPMB is
> actually pretty wrong. The RPMB area should have been designed
> to be accessed from /dev/mmcblkN directly, using ioctl()s on
> the main block device. It is however way too late to change
> that, since userspace expects to open an RPMB device in
> /dev/mmcblkNrpmb and we cannot break userspace.
>
> This patch tries to amend the situation using the following
> strategy:
>
> - Stop creating a block device for the RPMB partition/area
>
> - Instead create a custom, dynamic character device with
> the same name.
>
> - Make this new character device support exactly the same
> set of ioctl()s as the old block device.
>
> - Wrap the requests back to the same ioctl() handlers, but
> issue them on the block queue of the main partition/area,
> i.e. /dev/mmcblkN
>
> We need to create a special "rpmb" bus type in order to get
> udev and/or busybox hot/coldplug to instantiate the device
> node properly.
>
> Before the patch, this appears in 'ps aux':
>
> 101 root 0:00 [mmcqd/2rpmb]
> 123 root 0:00 [mmcqd/3rpmb]
>
> After applying the patch these surplus block queue threads
> are gone, but RPMB is as usable as ever using the userspace
> MMC tools, such as 'mmc rpmb read-counter'.
>
> We get instead those dynamice devices in /dev:
>
> brw-rw---- 1 root root 179, 0 Jan 1 2000 mmcblk0
> brw-rw---- 1 root root 179, 1 Jan 1 2000 mmcblk0p1
> brw-rw---- 1 root root 179, 2 Jan 1 2000 mmcblk0p2
> brw-rw---- 1 root root 179, 5 Jan 1 2000 mmcblk0p5
> brw-rw---- 1 root root 179, 8 Jan 1 2000 mmcblk2
> brw-rw---- 1 root root 179, 16 Jan 1 2000 mmcblk2boot0
> brw-rw---- 1 root root 179, 24 Jan 1 2000 mmcblk2boot1
> crw-rw---- 1 root root 248, 0 Jan 1 2000 mmcblk2rpmb
> brw-rw---- 1 root root 179, 32 Jan 1 2000 mmcblk3
> brw-rw---- 1 root root 179, 40 Jan 1 2000 mmcblk3boot0
> brw-rw---- 1 root root 179, 48 Jan 1 2000 mmcblk3boot1
> brw-rw---- 1 root root 179, 33 Jan 1 2000 mmcblk3p1
> crw-rw---- 1 root root 248, 1 Jan 1 2000 mmcblk3rpmb
>
> Notice the (248,0) and (248,1) character devices for RPMB.
>
> Cc: Tomas Winkler <tomas.winkler@intel.com>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v1 (RFC) -> v5:
> - Rebase.
> - Drop discussion comments, let's go for this unless someone
> has a better idea.
> - Rename rpmb_devt and rpmb_bus_type to mmc_rpmb_devt and
> mmc_rpmb_bus_type as requested by Tomas.
> - Handle multiple RPMB partitions as requested by Tomas.
> - Renumber v5 to keep together with the rest of the series.
> ---
> drivers/mmc/core/block.c | 286 +++++++++++++++++++++++++++++++++++++++++++----
> drivers/mmc/core/queue.h | 2 +
> 2 files changed, 266 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 502068b155b9..27e1cf07a7a2 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -28,6 +28,7 @@
> #include <linux/hdreg.h>
> #include <linux/kdev_t.h>
> #include <linux/blkdev.h>
> +#include <linux/cdev.h>
> #include <linux/mutex.h>
> #include <linux/scatterlist.h>
> #include <linux/string_helpers.h>
> @@ -86,6 +87,7 @@ static int max_devices;
> #define MAX_DEVICES 256
>
> static DEFINE_IDA(mmc_blk_ida);
> +static DEFINE_IDA(mmc_rpmb_ida);
>
> /*
> * There is one mmc_blk_data per slot.
> @@ -96,6 +98,7 @@ struct mmc_blk_data {
> struct gendisk *disk;
> struct mmc_queue queue;
> struct list_head part;
> + struct list_head rpmbs;
>
> unsigned int flags;
> #define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */
> @@ -121,6 +124,32 @@ struct mmc_blk_data {
> int area_type;
> };
>
> +/* Device type for RPMB character devices */
> +static dev_t mmc_rpmb_devt;
> +
> +/* Bus type for RPMB character devices */
> +static struct bus_type mmc_rpmb_bus_type = {
> + .name = "rpmb",
Also need renaming to 'mmc_rpmb', this goes to ABI /sys/bus/mmc_rpmb/
I'm not CCed to whole series so not sure you've updated also
Documentation/ABI/testing/sysfs-bus-*
> +};
> +
> +/**
> + * struct mmc_rpmb_data - special RPMB device type for these areas
> + * @dev: the device for the RPMB area
> + * @chrdev: character device for the RPMB area
> + * @id: unique device ID number
> + * @part_index: partition index (0 on first)
> + * @md: parent MMC block device
> + * @node: list item, so we can put this device on a list
> + */
> +struct mmc_rpmb_data {
> + struct device dev;
> + struct cdev chrdev;
> + int id;
> + unsigned int part_index;
> + struct mmc_blk_data *md;
> + struct list_head node;
> +};
> +
> static DEFINE_MUTEX(open_lock);
>
> module_param(perdev_minors, int, 0444);
> @@ -299,6 +328,7 @@ struct mmc_blk_ioc_data {
> struct mmc_ioc_cmd ic;
> unsigned char *buf;
> u64 buf_bytes;
> + struct mmc_rpmb_data *rpmb;
> };
>
> static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
> @@ -437,14 +467,25 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
> struct mmc_request mrq = {};
> struct scatterlist sg;
> int err;
> - bool is_rpmb = false;
> + unsigned int target_part;
> u32 status = 0;
>
> if (!card || !md || !idata)
> return -EINVAL;
>
> - if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
> - is_rpmb = true;
> + /*
> + * The RPMB accesses comes in from the character device, so we
> + * need to target these explicitly. Else we just target the
> + * partition type for the block device the ioctl() was issued
> + * on.
> + */
> + if (idata->rpmb) {
> + /* Support multiple RPMB partitions */
> + target_part = idata->rpmb->part_index;
> + target_part |= EXT_CSD_PART_CONFIG_ACC_RPMB;
> + } else {
> + target_part = md->part_type;
> + }
>
> cmd.opcode = idata->ic.opcode;
> cmd.arg = idata->ic.arg;
> @@ -488,7 +529,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
>
> mrq.cmd = &cmd;
>
> - err = mmc_blk_part_switch(card, md->part_type);
> + err = mmc_blk_part_switch(card, target_part);
> if (err)
> return err;
>
> @@ -498,7 +539,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
> return err;
> }
>
> - if (is_rpmb) {
> + if (idata->rpmb) {
> err = mmc_set_blockcount(card, data.blocks,
> idata->ic.write_flag & (1 << 31));
> if (err)
> @@ -538,7 +579,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
>
> memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
>
> - if (is_rpmb) {
> + if (idata->rpmb) {
> /*
> * Ensure RPMB command has completed by polling CMD13
> * "Send Status".
> @@ -554,7 +595,8 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
> }
>
> static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
> - struct mmc_ioc_cmd __user *ic_ptr)
> + struct mmc_ioc_cmd __user *ic_ptr,
> + struct mmc_rpmb_data *rpmb)
> {
> struct mmc_blk_ioc_data *idata;
> struct mmc_blk_ioc_data *idatas[1];
> @@ -566,6 +608,8 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
> idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
> if (IS_ERR(idata))
> return PTR_ERR(idata);
> + /* This will be NULL on non-RPMB ioctl():s */
> + idata->rpmb = rpmb;
>
> card = md->queue.card;
> if (IS_ERR(card)) {
> @@ -581,7 +625,10 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
> idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
> __GFP_RECLAIM);
> idatas[0] = idata;
> - req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL;
> + if (rpmb)
> + req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL_RPMB;
> + else
> + req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL;
maybe neater to use = ?: here, it's used in this module often
> 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);
> @@ -596,7 +643,8 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
> }
>
> static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
> - struct mmc_ioc_multi_cmd __user *user)
> + struct mmc_ioc_multi_cmd __user *user,
> + struct mmc_rpmb_data *rpmb)
> {
> struct mmc_blk_ioc_data **idata = NULL;
> struct mmc_ioc_cmd __user *cmds = user->cmds;
> @@ -627,6 +675,8 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
> num_of_cmds = i;
> goto cmd_err;
> }
> + /* This will be NULL on non-RPMB ioctl():s */
> + idata[i]->rpmb = rpmb;
> }
>
> card = md->queue.card;
> @@ -643,7 +693,10 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
> req = blk_get_request(mq->queue,
> idata[0]->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
> __GFP_RECLAIM);
> - req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL;
> + if (rpmb)
> + req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_IOCTL_RPMB;
> + else
> + req_to_mmc_queue_req(req)->drv_op = 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;
> blk_execute_rq(mq->queue, NULL, req, 0);
> @@ -691,7 +744,8 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
> if (!md)
> return -EINVAL;
> ret = mmc_blk_ioctl_cmd(md,
> - (struct mmc_ioc_cmd __user *)arg);
> + (struct mmc_ioc_cmd __user *)arg,
> + NULL);
> mmc_blk_put(md);
> return ret;
> case MMC_IOC_MULTI_CMD:
> @@ -702,7 +756,8 @@ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
> if (!md)
> return -EINVAL;
> ret = mmc_blk_ioctl_multi_cmd(md,
> - (struct mmc_ioc_multi_cmd __user *)arg);
> + (struct mmc_ioc_multi_cmd __user *)arg,
> + NULL);
> mmc_blk_put(md);
> return ret;
> default:
> @@ -1174,17 +1229,19 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
> struct mmc_queue_req *mq_rq;
> struct mmc_card *card = mq->card;
> struct mmc_blk_data *md = mq->blkdata;
> - struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
> struct mmc_blk_ioc_data **idata;
> + bool rpmb_ioctl;
> u8 **ext_csd;
> u32 status;
> int ret;
> int i;
>
> mq_rq = req_to_mmc_queue_req(req);
> + rpmb_ioctl = (mq_rq->drv_op == MMC_DRV_OP_IOCTL_RPMB);
>
> switch (mq_rq->drv_op) {
> case MMC_DRV_OP_IOCTL:
> + 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]);
> @@ -1192,8 +1249,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
> break;
> }
> /* Always switch back to main area after RPMB access */
> - if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
> - mmc_blk_part_switch(card, main_md->part_type);
> + if (rpmb_ioctl)
> + mmc_blk_part_switch(card, 0);
> break;
> case MMC_DRV_OP_BOOT_WP:
> ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
> @@ -2022,6 +2079,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
>
> spin_lock_init(&md->lock);
> INIT_LIST_HEAD(&md->part);
> + INIT_LIST_HEAD(&md->rpmbs);
> md->usage = 1;
>
> ret = mmc_init_queue(&md->queue, card, &md->lock, subname);
> @@ -2140,6 +2198,153 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
> return 0;
> }
>
> +/**
> + * rpmb_ioctl() - ioctl handler for the RPMB chardev
> + * @filp: the character device file
> + * @cmd: the ioctl() command
> + * @arg: the argument from userspace
> + *
> + * This will essentially just redirect the ioctl()s coming in over to
> + * the main block device spawning the RPMB character device.
> + */
> +static long rpmb_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
will keep the mmc_ prefix also here
> +{
> + struct mmc_rpmb_data *rpmb = filp->private_data;
> + int ret;
> +
> + switch (cmd) {
> + case MMC_IOC_CMD:
> + ret = mmc_blk_ioctl_cmd(rpmb->md,
> + (struct mmc_ioc_cmd __user *)arg,
> + rpmb);
> + break;
> + case MMC_IOC_MULTI_CMD:
> + ret = mmc_blk_ioctl_multi_cmd(rpmb->md,
> + (struct mmc_ioc_multi_cmd __user *)arg,
> + rpmb);
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_COMPAT
> +static long rpmb_ioctl_compat(struct file *filp, unsigned int cmd,
> + unsigned long arg)
same here, the mmc_ prefix
> +{
> + return rpmb_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
> +}
> +#endif
> +
> +static int rpmb_chrdev_open(struct inode *inode, struct file *filp)
> +{
prefix
> + struct mmc_rpmb_data *rpmb = container_of(inode->i_cdev,
> + struct mmc_rpmb_data, chrdev);
> +
> + get_device(&rpmb->dev);
> + filp->private_data = rpmb;
> + mutex_lock(&open_lock);
> + rpmb->md->usage++;
> + mutex_unlock(&open_lock);
> +
> + return nonseekable_open(inode, filp);
> +}
> +
> +static int rpmb_chrdev_release(struct inode *inode, struct file *filp)
> +{
> + struct mmc_rpmb_data *rpmb = container_of(inode->i_cdev,
> + struct mmc_rpmb_data, chrdev);
> +
> + put_device(&rpmb->dev);
> + mutex_lock(&open_lock);
> + rpmb->md->usage--;
> + mutex_unlock(&open_lock);
> +
> + return 0;
> +}
> +
> +static const struct file_operations rpmb_fileops = {
> + .release = rpmb_chrdev_release,
> + .open = rpmb_chrdev_open,
> + .owner = THIS_MODULE,
> + .llseek = no_llseek,
> + .unlocked_ioctl = rpmb_ioctl,
> +#ifdef CONFIG_COMPAT
> + .compat_ioctl = rpmb_ioctl_compat,
> +#endif
> +};
> +
> +
> +static int mmc_blk_alloc_rpmb_part(struct mmc_card *card,
> + struct mmc_blk_data *md,
> + unsigned int part_index,
> + sector_t size,
> + const char *subname)
> +{
> + int devidx, ret;
> + char rpmb_name[DISK_NAME_LEN];
> + char cap_str[10];
> + 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);
> + if (devidx < 0)
> + return devidx;
> +
> + rpmb = kzalloc(sizeof(*rpmb), GFP_KERNEL);
> + if (!rpmb)
> + return -ENOMEM;
> +
> + snprintf(rpmb_name, sizeof(rpmb_name),
> + "mmcblk%u%s", card->host->index, subname ? subname : "");
> +
> + rpmb->id = devidx;
> + rpmb->part_index = part_index;
> + rpmb->dev.init_name = rpmb_name;
> + rpmb->dev.bus = &mmc_rpmb_bus_type;
> + rpmb->dev.devt = MKDEV(MAJOR(mmc_rpmb_devt), rpmb->id);
> + rpmb->dev.parent = &card->dev;
> + device_initialize(&rpmb->dev);
> + dev_set_drvdata(&rpmb->dev, rpmb);
> + rpmb->md = md;
> +
> + cdev_init(&rpmb->chrdev, &rpmb_fileops);
> + rpmb->chrdev.owner = THIS_MODULE;
> + ret = cdev_device_add(&rpmb->chrdev, &rpmb->dev);
> + if (ret) {
> + pr_err("%s: could not add character device\n", rpmb_name);
> + goto out_remove_ida;
> + }
> +
> + list_add(&rpmb->node, &md->rpmbs);
> +
> + 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,
> + MAJOR(mmc_rpmb_devt), rpmb->id);
> +
> + return 0;
> +
> +out_remove_ida:
> + ida_simple_remove(&mmc_rpmb_ida, rpmb->id);
> + kfree(rpmb);
> + return ret;
> +}
> +
> +static void mmc_blk_remove_rpmb_part(struct mmc_rpmb_data *rpmb)
> +{
> + cdev_device_del(&rpmb->chrdev, &rpmb->dev);
> + device_del(&rpmb->dev);
> + ida_simple_remove(&mmc_rpmb_ida, rpmb->id);
> + kfree(rpmb);
> +}
> +
> /* MMC Physical partitions consist of two boot partitions and
> * up to four general purpose partitions.
> * For each partition enabled in EXT_CSD a block device will be allocatedi
> @@ -2148,13 +2353,26 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
>
> static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
> {
> - int idx, ret = 0;
> + int idx, ret;
>
> if (!mmc_card_mmc(card))
> return 0;
>
> for (idx = 0; idx < card->nr_parts; idx++) {
> - if (card->part[idx].size) {
> + if (card->part[idx].area_type & MMC_BLK_DATA_AREA_RPMB) {
> + /*
> + * RPMB partitions does not provide block access, they
> + * are only accessed using ioctl():s. Thus create
> + * special RPMB block devices that do not have a
> + * backing block queue for these.
> + */
> + ret = mmc_blk_alloc_rpmb_part(card, md,
> + card->part[idx].part_cfg,
> + card->part[idx].size >> 9,
> + card->part[idx].name);
> + if (ret)
> + return ret;
> + } else if (card->part[idx].size) {
> ret = mmc_blk_alloc_part(card, md,
> card->part[idx].part_cfg,
> card->part[idx].size >> 9,
> @@ -2166,7 +2384,7 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
> }
> }
>
> - return ret;
> + return 0;
> }
>
> static void mmc_blk_remove_req(struct mmc_blk_data *md)
> @@ -2203,7 +2421,15 @@ static void mmc_blk_remove_parts(struct mmc_card *card,
> {
> struct list_head *pos, *q;
> struct mmc_blk_data *part_md;
> + struct mmc_rpmb_data *rpmb;
>
> + /* Remove RPMB partitions */
> + list_for_each_safe(pos, q, &md->rpmbs) {
> + rpmb = list_entry(pos, struct mmc_rpmb_data, node);
> + list_del(pos);
> + mmc_blk_remove_rpmb_part(rpmb);
> + }
> + /* Remove block partitions */
> list_for_each_safe(pos, q, &md->part) {
> part_md = list_entry(pos, struct mmc_blk_data, part);
> list_del(pos);
> @@ -2522,6 +2748,17 @@ static int __init mmc_blk_init(void)
> {
> int res;
>
> + res = bus_register(&mmc_rpmb_bus_type);
> + if (res < 0) {
> + pr_err("mmcblk: could not register RPMB bus type\n");
> + return res;
> + }
> + res = alloc_chrdev_region(&mmc_rpmb_devt, 0, MAX_DEVICES, "rpmb");
> + if (res < 0) {
> + pr_err("mmcblk: failed to allocate rpmb chrdev region\n");
> + goto out_bus_unreg;
> + }
> +
> if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
> pr_info("mmcblk: using %d minors per device\n", perdev_minors);
>
> @@ -2529,16 +2766,20 @@ static int __init mmc_blk_init(void)
>
> res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
> if (res)
> - goto out;
> + goto out_chrdev_unreg;
>
> res = mmc_register_driver(&mmc_driver);
> if (res)
> - goto out2;
> + goto out_blkdev_unreg;
>
> return 0;
> - out2:
> +
> +out_blkdev_unreg:
> unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
> - out:
> +out_chrdev_unreg:
> + unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
> +out_bus_unreg:
> + bus_unregister(&mmc_rpmb_bus_type);
> return res;
> }
>
> @@ -2546,6 +2787,7 @@ static void __exit mmc_blk_exit(void)
> {
> mmc_unregister_driver(&mmc_driver);
> unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
> + unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
> }
>
> module_init(mmc_blk_init);
> diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
> index 04fc89360a7a..a2b6a9fcab01 100644
> --- a/drivers/mmc/core/queue.h
> +++ b/drivers/mmc/core/queue.h
> @@ -35,12 +35,14 @@ struct mmc_blk_request {
> /**
> * enum mmc_drv_op - enumerates the operations in the mmc_queue_req
> * @MMC_DRV_OP_IOCTL: ioctl operation
> + * @MMC_DRV_OP_IOCTL_RPMB: RPMB-oriented ioctl operation
> * @MMC_DRV_OP_BOOT_WP: write protect boot partitions
> * @MMC_DRV_OP_GET_CARD_STATUS: get card status
> * @MMC_DRV_OP_GET_EXT_CSD: get the EXT CSD from an eMMC card
> */
> enum mmc_drv_op {
> MMC_DRV_OP_IOCTL,
> + MMC_DRV_OP_IOCTL_RPMB,
> MMC_DRV_OP_BOOT_WP,
> MMC_DRV_OP_GET_CARD_STATUS,
> MMC_DRV_OP_GET_EXT_CSD,
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 8/8 v5] mmc: block: Delete mmc_access_rpmb()
2017-08-20 21:39 [PATCH 0/8] debugfs and RPMB cleanups Linus Walleij
` (6 preceding siblings ...)
2017-08-20 21:39 ` [PATCH 7/8 v5] mmc: block: Convert RPMB to a character device Linus Walleij
@ 2017-08-20 21:39 ` Linus Walleij
2017-08-21 12:51 ` Adrian Hunter
2017-08-22 11:15 ` [PATCH 0/8] debugfs and RPMB cleanups Ulf Hansson
8 siblings, 1 reply; 13+ messages in thread
From: Linus Walleij @ 2017-08-20 21:39 UTC (permalink / raw)
To: linux-mmc, Ulf Hansson; +Cc: Linus Walleij
This function is used by the block layer queue to bail out of
requests if the current request is an RPMB request.
However this makes no sense: RPMB is only used from ioctl():s,
there are no RPMB accesses coming from the block layer.
An RPMB ioctl() always switches to the RPMB partition and
then back to the main partition before completing.
The only (possible) use of this check must have been to
duct-tape over a race between RPMB ioctl()s colliding with
concurrent non-RPMB accesses to the same device.
This could happen in the past because the RPMB device was
created as a separate block device/disk with its own submit
queue competing with the main partition, and submitting
requests in parallel. This is now gone as we removed the
offending RPMB block device in another patch.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v5:
- Renumber to keep together with the rest of the series.
---
drivers/mmc/core/block.c | 12 ------------
drivers/mmc/core/queue.c | 2 +-
drivers/mmc/core/queue.h | 2 --
3 files changed, 1 insertion(+), 15 deletions(-)
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 27e1cf07a7a2..61ea402f2569 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -1207,18 +1207,6 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
md->reset_done &= ~type;
}
-int mmc_access_rpmb(struct mmc_queue *mq)
-{
- struct mmc_blk_data *md = mq->blkdata;
- /*
- * If this is a RPMB partition access, return ture
- */
- if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
- return true;
-
- return false;
-}
-
/*
* 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
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index affa7370ba82..3baccbf16f3d 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -32,7 +32,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
{
struct mmc_queue *mq = q->queuedata;
- if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq)))
+ if (mq && mmc_card_removed(mq->card))
return BLKPREP_KILL;
req->rq_flags |= RQF_DONTPREP;
diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
index a2b6a9fcab01..7649ed6cbef7 100644
--- a/drivers/mmc/core/queue.h
+++ b/drivers/mmc/core/queue.h
@@ -89,6 +89,4 @@ extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
extern void mmc_queue_bounce_post(struct mmc_queue_req *);
-extern int mmc_access_rpmb(struct mmc_queue *);
-
#endif
--
2.13.5
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 8/8 v5] mmc: block: Delete mmc_access_rpmb()
2017-08-20 21:39 ` [PATCH 8/8 v5] mmc: block: Delete mmc_access_rpmb() Linus Walleij
@ 2017-08-21 12:51 ` Adrian Hunter
2017-08-22 8:58 ` Tomas Winkler
0 siblings, 1 reply; 13+ messages in thread
From: Adrian Hunter @ 2017-08-21 12:51 UTC (permalink / raw)
To: Linus Walleij, linux-mmc, Ulf Hansson
On 21/08/17 00:39, Linus Walleij wrote:
> This function is used by the block layer queue to bail out of
> requests if the current request is an RPMB request.
>
> However this makes no sense: RPMB is only used from ioctl():s,
> there are no RPMB accesses coming from the block layer.
> An RPMB ioctl() always switches to the RPMB partition and
> then back to the main partition before completing.
>
> The only (possible) use of this check must have been to
> duct-tape over a race between RPMB ioctl()s colliding with
> concurrent non-RPMB accesses to the same device.
It was always possible to read / write (unsuccessfully) the rpmb block
device. i.e. dd of=/dev/mmcblk0rpmb
Actually one thing to look at is that it looks like it was blocking your
IOCTL requests. i.e. wouldn't the IOCTL request also get killed.
>
> This could happen in the past because the RPMB device was
> created as a separate block device/disk with its own submit
> queue competing with the main partition, and submitting
> requests in parallel. This is now gone as we removed the
> offending RPMB block device in another patch.
>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v1->v5:
> - Renumber to keep together with the rest of the series.
> ---
> drivers/mmc/core/block.c | 12 ------------
> drivers/mmc/core/queue.c | 2 +-
> drivers/mmc/core/queue.h | 2 --
> 3 files changed, 1 insertion(+), 15 deletions(-)
>
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 27e1cf07a7a2..61ea402f2569 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -1207,18 +1207,6 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
> md->reset_done &= ~type;
> }
>
> -int mmc_access_rpmb(struct mmc_queue *mq)
> -{
> - struct mmc_blk_data *md = mq->blkdata;
> - /*
> - * If this is a RPMB partition access, return ture
> - */
> - if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
> - return true;
> -
> - return false;
> -}
> -
> /*
> * 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
> diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
> index affa7370ba82..3baccbf16f3d 100644
> --- a/drivers/mmc/core/queue.c
> +++ b/drivers/mmc/core/queue.c
> @@ -32,7 +32,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
> {
> struct mmc_queue *mq = q->queuedata;
>
> - if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq)))
> + if (mq && mmc_card_removed(mq->card))
> return BLKPREP_KILL;
>
> req->rq_flags |= RQF_DONTPREP;
> diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
> index a2b6a9fcab01..7649ed6cbef7 100644
> --- a/drivers/mmc/core/queue.h
> +++ b/drivers/mmc/core/queue.h
> @@ -89,6 +89,4 @@ extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
> extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
> extern void mmc_queue_bounce_post(struct mmc_queue_req *);
>
> -extern int mmc_access_rpmb(struct mmc_queue *);
> -
> #endif
>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH 8/8 v5] mmc: block: Delete mmc_access_rpmb()
2017-08-21 12:51 ` Adrian Hunter
@ 2017-08-22 8:58 ` Tomas Winkler
0 siblings, 0 replies; 13+ messages in thread
From: Tomas Winkler @ 2017-08-22 8:58 UTC (permalink / raw)
To: Adrian Hunter; +Cc: Linus Walleij, linux-mmc, Ulf Hansson, Tomas Winkler
This was done to prevent boot time scanning of the block device.
Thanks
Tomas
On Mon, Aug 21, 2017 at 3:51 PM, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 21/08/17 00:39, Linus Walleij wrote:
>> This function is used by the block layer queue to bail out of
>> requests if the current request is an RPMB request.
>>
>> However this makes no sense: RPMB is only used from ioctl():s,
>> there are no RPMB accesses coming from the block layer.
>> An RPMB ioctl() always switches to the RPMB partition and
>> then back to the main partition before completing.
>>
>> The only (possible) use of this check must have been to
>> duct-tape over a race between RPMB ioctl()s colliding with
>> concurrent non-RPMB accesses to the same device.
>
> It was always possible to read / write (unsuccessfully) the rpmb block
> device. i.e. dd of=/dev/mmcblk0rpmb
>
> Actually one thing to look at is that it looks like it was blocking your
> IOCTL requests. i.e. wouldn't the IOCTL request also get killed.
>
>>
>> This could happen in the past because the RPMB device was
>> created as a separate block device/disk with its own submit
>> queue competing with the main partition, and submitting
>> requests in parallel. This is now gone as we removed the
>> offending RPMB block device in another patch.
>>
>> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
>> ---
>> ChangeLog v1->v5:
>> - Renumber to keep together with the rest of the series.
>> ---
>> drivers/mmc/core/block.c | 12 ------------
>> drivers/mmc/core/queue.c | 2 +-
>> drivers/mmc/core/queue.h | 2 --
>> 3 files changed, 1 insertion(+), 15 deletions(-)
>>
>> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
>> index 27e1cf07a7a2..61ea402f2569 100644
>> --- a/drivers/mmc/core/block.c
>> +++ b/drivers/mmc/core/block.c
>> @@ -1207,18 +1207,6 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
>> md->reset_done &= ~type;
>> }
>>
>> -int mmc_access_rpmb(struct mmc_queue *mq)
>> -{
>> - struct mmc_blk_data *md = mq->blkdata;
>> - /*
>> - * If this is a RPMB partition access, return ture
>> - */
>> - if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
>> - return true;
>> -
>> - return false;
>> -}
>> -
>> /*
>> * 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
>> diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
>> index affa7370ba82..3baccbf16f3d 100644
>> --- a/drivers/mmc/core/queue.c
>> +++ b/drivers/mmc/core/queue.c
>> @@ -32,7 +32,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
>> {
>> struct mmc_queue *mq = q->queuedata;
>>
>> - if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq)))
>> + if (mq && mmc_card_removed(mq->card))
>> return BLKPREP_KILL;
>>
>> req->rq_flags |= RQF_DONTPREP;
>> diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
>> index a2b6a9fcab01..7649ed6cbef7 100644
>> --- a/drivers/mmc/core/queue.h
>> +++ b/drivers/mmc/core/queue.h
>> @@ -89,6 +89,4 @@ extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
>> extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
>> extern void mmc_queue_bounce_post(struct mmc_queue_req *);
>>
>> -extern int mmc_access_rpmb(struct mmc_queue *);
>> -
>> #endif
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 0/8] debugfs and RPMB cleanups
2017-08-20 21:39 [PATCH 0/8] debugfs and RPMB cleanups Linus Walleij
` (7 preceding siblings ...)
2017-08-20 21:39 ` [PATCH 8/8 v5] mmc: block: Delete mmc_access_rpmb() Linus Walleij
@ 2017-08-22 11:15 ` Ulf Hansson
8 siblings, 0 replies; 13+ messages in thread
From: Ulf Hansson @ 2017-08-22 11:15 UTC (permalink / raw)
To: Linus Walleij; +Cc: linux-mmc@vger.kernel.org
On 20 August 2017 at 23:39, Linus Walleij <linus.walleij@linaro.org> wrote:
> Here is a series of all the cleanup patches and RPMB rewrite
> I didn't manage to finish for the last merge window, hoping we can
> include these cleanups/refactorings for v4.14.
>
> It's OK to stop applying at any step if there is any problem.
Applied patch 1->6.
Seems like a re-spin may be need for patch7 and 8, in any case I
postpone to apply them for a little while.
>
> Linus Walleij (8):
> mmc: block: Anonymize the drv op data pointer
> mmc: ops: export mmc_get_status()
> mmc: debugfs: Move block debugfs into block module
> mmc: block: Move duplicate check
> mmc: block: Refactor mmc_blk_part_switch()
> mmc: block: Reparametrize mmc_blk_ioctl_[multi]_cmd()
> mmc: block: Convert RPMB to a character device
> mmc: block: Delete mmc_access_rpmb()
>
> drivers/mmc/core/block.c | 543 ++++++++++++++++++++++++++++++++++++++-------
> drivers/mmc/core/debugfs.c | 89 --------
> drivers/mmc/core/mmc_ops.c | 1 +
> drivers/mmc/core/queue.c | 2 +-
> drivers/mmc/core/queue.h | 10 +-
> 5 files changed, 467 insertions(+), 178 deletions(-)
>
> --
> 2.13.5
>
Kind regards
Uffe
^ permalink raw reply [flat|nested] 13+ messages in thread