2005-04-17 02:20:36 +04:00
|
|
|
/*
|
|
|
|
* Block driver for media (i.e., flash cards)
|
|
|
|
*
|
|
|
|
* Copyright 2002 Hewlett-Packard Company
|
2008-06-29 14:19:47 +04:00
|
|
|
* Copyright 2005-2008 Pierre Ossman
|
2005-04-17 02:20:36 +04:00
|
|
|
*
|
|
|
|
* Use consistent with the GNU GPL is permitted,
|
|
|
|
* provided that this copyright notice is
|
|
|
|
* preserved in its entirety in all copies and derived works.
|
|
|
|
*
|
|
|
|
* HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
|
|
|
|
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
|
|
|
|
* FITNESS FOR ANY PARTICULAR PURPOSE.
|
|
|
|
*
|
|
|
|
* Many thanks to Alessandro Rubini and Jonathan Corbet!
|
|
|
|
*
|
|
|
|
* Author: Andrew Christian
|
|
|
|
* 28 May 2002
|
|
|
|
*/
|
|
|
|
#include <linux/moduleparam.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/fs.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 11:04:11 +03:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/hdreg.h>
|
|
|
|
#include <linux/kdev_t.h>
|
|
|
|
#include <linux/blkdev.h>
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
#include <linux/cdev.h>
|
2006-01-12 21:43:35 +03:00
|
|
|
#include <linux/mutex.h>
|
2006-10-06 11:44:03 +04:00
|
|
|
#include <linux/scatterlist.h>
|
2008-09-06 12:57:57 +04:00
|
|
|
#include <linux/string_helpers.h>
|
2011-04-27 02:56:29 +04:00
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/capability.h>
|
|
|
|
#include <linux/compat.h>
|
2013-05-02 16:02:38 +04:00
|
|
|
#include <linux/pm_runtime.h>
|
2016-04-07 15:36:46 +03:00
|
|
|
#include <linux/idr.h>
|
2017-08-21 00:39:08 +03:00
|
|
|
#include <linux/debugfs.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2011-04-27 02:56:29 +04:00
|
|
|
#include <linux/mmc/ioctl.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
#include <linux/mmc/card.h>
|
2006-06-18 16:34:37 +04:00
|
|
|
#include <linux/mmc/host.h>
|
2006-12-25 00:46:55 +03:00
|
|
|
#include <linux/mmc/mmc.h>
|
|
|
|
#include <linux/mmc/sd.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2016-12-24 22:46:01 +03:00
|
|
|
#include <linux/uaccess.h>
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2006-12-23 22:03:02 +03:00
|
|
|
#include "queue.h"
|
2016-09-30 04:37:38 +03:00
|
|
|
#include "block.h"
|
2017-01-13 16:14:08 +03:00
|
|
|
#include "core.h"
|
2017-01-13 16:14:14 +03:00
|
|
|
#include "card.h"
|
2021-01-26 03:14:48 +03:00
|
|
|
#include "crypto.h"
|
2017-01-13 16:14:15 +03:00
|
|
|
#include "host.h"
|
2017-01-13 16:14:14 +03:00
|
|
|
#include "bus.h"
|
2017-01-13 16:14:08 +03:00
|
|
|
#include "mmc_ops.h"
|
2017-02-15 11:35:28 +03:00
|
|
|
#include "quirks.h"
|
2017-01-13 16:14:08 +03:00
|
|
|
#include "sd_ops.h"
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2009-02-23 15:38:41 +03:00
|
|
|
MODULE_ALIAS("mmc:block");
|
2010-09-18 05:19:57 +04:00
|
|
|
#ifdef MODULE_PARAM_PREFIX
|
|
|
|
#undef MODULE_PARAM_PREFIX
|
|
|
|
#endif
|
|
|
|
#define MODULE_PARAM_PREFIX "mmcblk."
|
|
|
|
|
2017-11-29 16:41:14 +03:00
|
|
|
/*
|
|
|
|
* Set a 10 second timeout for polling write request busy state. Note, mmc core
|
|
|
|
* is setting a 3 second timeout for SD cards, and SDHCI has long had a 10
|
|
|
|
* second software timer to timeout the whole request, so 10 seconds should be
|
|
|
|
* ample.
|
|
|
|
*/
|
|
|
|
#define MMC_BLK_TIMEOUT_MS (10 * 1000)
|
2013-04-18 16:41:55 +04:00
|
|
|
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
|
2018-03-08 17:08:11 +03:00
|
|
|
#define MMC_EXTRACT_VALUE_FROM_ARG(x) ((x & 0x0000FF00) >> 8)
|
2011-04-13 00:06:53 +04:00
|
|
|
|
2015-11-06 18:12:26 +03:00
|
|
|
#define mmc_req_rel_wr(req) ((req->cmd_flags & REQ_FUA) && \
|
2013-02-06 12:02:46 +04:00
|
|
|
(rq_data_dir(req) == WRITE))
|
2010-09-18 05:19:57 +04:00
|
|
|
static DEFINE_MUTEX(block_mutex);
|
2009-02-23 15:38:41 +03:00
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
/*
|
2010-09-18 05:19:57 +04:00
|
|
|
* The defaults come from config options but can be overriden by module
|
|
|
|
* or bootarg options.
|
2005-04-17 02:20:36 +04:00
|
|
|
*/
|
2010-09-18 05:19:57 +04:00
|
|
|
static int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
|
2007-11-21 20:45:12 +03:00
|
|
|
|
2010-09-18 05:19:57 +04:00
|
|
|
/*
|
|
|
|
* We've only got one major, so number of mmcblk devices is
|
2014-11-06 06:35:09 +03:00
|
|
|
* limited to (1 << 20) / number of minors per device. It is also
|
2016-04-07 15:36:46 +03:00
|
|
|
* limited by the MAX_DEVICES below.
|
2010-09-18 05:19:57 +04:00
|
|
|
*/
|
|
|
|
static int max_devices;
|
|
|
|
|
2014-11-06 06:35:09 +03:00
|
|
|
#define MAX_DEVICES 256
|
|
|
|
|
2016-04-07 15:36:46 +03:00
|
|
|
static DEFINE_IDA(mmc_blk_ida);
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
static DEFINE_IDA(mmc_rpmb_ida);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* There is one mmc_blk_data per slot.
|
|
|
|
*/
|
|
|
|
struct mmc_blk_data {
|
2016-06-20 20:40:44 +03:00
|
|
|
struct device *parent;
|
2005-04-17 02:20:36 +04:00
|
|
|
struct gendisk *disk;
|
|
|
|
struct mmc_queue queue;
|
2011-04-12 03:10:25 +04:00
|
|
|
struct list_head part;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
struct list_head rpmbs;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2011-05-24 00:06:36 +04:00
|
|
|
unsigned int flags;
|
|
|
|
#define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */
|
|
|
|
#define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
unsigned int usage;
|
2006-01-04 01:38:44 +03:00
|
|
|
unsigned int read_only;
|
2011-04-12 03:10:25 +04:00
|
|
|
unsigned int part_type;
|
2011-08-29 17:42:15 +04:00
|
|
|
unsigned int reset_done;
|
|
|
|
#define MMC_BLK_READ BIT(0)
|
|
|
|
#define MMC_BLK_WRITE BIT(1)
|
|
|
|
#define MMC_BLK_DISCARD BIT(2)
|
|
|
|
#define MMC_BLK_SECDISCARD BIT(3)
|
2017-11-29 16:41:04 +03:00
|
|
|
#define MMC_BLK_CQE_RECOVERY BIT(4)
|
2011-04-12 03:10:25 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Only set in main mmc_blk_data associated
|
2014-10-06 16:34:09 +04:00
|
|
|
* with mmc_card with dev_set_drvdata, and keeps
|
2011-04-12 03:10:25 +04:00
|
|
|
* track of the current selected device partition.
|
|
|
|
*/
|
|
|
|
unsigned int part_curr;
|
|
|
|
struct device_attribute force_ro;
|
2011-12-02 11:51:06 +04:00
|
|
|
struct device_attribute power_ro_lock;
|
|
|
|
int area_type;
|
2017-11-21 16:42:30 +03:00
|
|
|
|
|
|
|
/* debugfs files (only in main mmc_blk_data) */
|
|
|
|
struct dentry *status_dentry;
|
|
|
|
struct dentry *ext_csd_dentry;
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
/* 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 = "mmc_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;
|
|
|
|
};
|
|
|
|
|
2006-01-12 21:43:35 +03:00
|
|
|
static DEFINE_MUTEX(open_lock);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2010-09-18 05:19:57 +04:00
|
|
|
module_param(perdev_minors, int, 0444);
|
|
|
|
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
|
|
|
|
|
2012-08-06 19:12:31 +04:00
|
|
|
static inline int mmc_blk_part_switch(struct mmc_card *card,
|
2017-08-21 00:39:10 +03:00
|
|
|
unsigned int part_type);
|
mmc: Add MMC host software queue support
Now the MMC read/write stack will always wait for previous request is
completed by mmc_blk_rw_wait(), before sending a new request to hardware,
or queue a work to complete request, that will bring context switching
overhead and spend some extra time to poll the card for busy completion
for I/O writes via sending CMD13, especially for high I/O per second
rates, to affect the IO performance.
Thus this patch introduces MMC software queue interface based on the
hardware command queue engine's interfaces, which is similar with the
hardware command queue engine's idea, that can remove the context
switching. Moreover we set the default queue depth as 64 for software
queue, which allows more requests to be prepared, merged and inserted
into IO scheduler to improve performance, but we only allow 2 requests
in flight, that is enough to let the irq handler always trigger the
next request without a context switch, as well as avoiding a long latency.
Moreover the host controller should support HW busy detection for I/O
operations when enabling the host software queue. That means, the host
controller must not complete a data transfer request, until after the
card stops signals busy.
From the fio testing data in cover letter, we can see the software
queue can improve some performance with 4K block size, increasing
about 16% for random read, increasing about 90% for random write,
though no obvious improvement for sequential read and write.
Moreover we can expand the software queue interface to support MMC
packed request or packed command in future.
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Baolin Wang <baolin.wang7@gmail.com>
Link: https://lore.kernel.org/r/4409c1586a9b3ed20d57ad2faf6c262fc3ccb6e2.1581478568.git.baolin.wang7@gmail.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2020-02-12 07:12:56 +03:00
|
|
|
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
|
|
|
|
struct mmc_card *card,
|
|
|
|
int disable_multi,
|
|
|
|
struct mmc_queue *mq);
|
|
|
|
static void mmc_blk_hsq_req_done(struct mmc_request *mrq);
|
2017-03-13 15:36:35 +03:00
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
|
|
|
|
{
|
|
|
|
struct mmc_blk_data *md;
|
|
|
|
|
2006-01-12 21:43:35 +03:00
|
|
|
mutex_lock(&open_lock);
|
2005-04-17 02:20:36 +04:00
|
|
|
md = disk->private_data;
|
|
|
|
if (md && md->usage == 0)
|
|
|
|
md = NULL;
|
|
|
|
if (md)
|
|
|
|
md->usage++;
|
2006-01-12 21:43:35 +03:00
|
|
|
mutex_unlock(&open_lock);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
return md;
|
|
|
|
}
|
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
static inline int mmc_get_devidx(struct gendisk *disk)
|
|
|
|
{
|
2015-10-22 20:00:41 +03:00
|
|
|
int devidx = disk->first_minor / perdev_minors;
|
2011-04-12 03:10:25 +04:00
|
|
|
return devidx;
|
|
|
|
}
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
static void mmc_blk_put(struct mmc_blk_data *md)
|
|
|
|
{
|
2006-01-12 21:43:35 +03:00
|
|
|
mutex_lock(&open_lock);
|
2005-04-17 02:20:36 +04:00
|
|
|
md->usage--;
|
|
|
|
if (md->usage == 0) {
|
2011-04-12 03:10:25 +04:00
|
|
|
int devidx = mmc_get_devidx(md->disk);
|
2017-11-29 16:40:59 +03:00
|
|
|
blk_put_queue(md->queue.queue);
|
2017-02-01 21:44:22 +03:00
|
|
|
ida_simple_remove(&mmc_blk_ida, devidx);
|
2005-04-17 02:20:36 +04:00
|
|
|
put_disk(md->disk);
|
|
|
|
kfree(md);
|
|
|
|
}
|
2006-01-12 21:43:35 +03:00
|
|
|
mutex_unlock(&open_lock);
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
2011-12-02 11:51:06 +04:00
|
|
|
static ssize_t power_ro_lock_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
|
|
|
|
struct mmc_card *card = md->queue.card;
|
|
|
|
int locked = 0;
|
|
|
|
|
|
|
|
if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
|
|
|
|
locked = 2;
|
|
|
|
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);
|
|
|
|
|
2015-07-16 16:50:45 +03:00
|
|
|
mmc_blk_put(md);
|
|
|
|
|
2011-12-02 11:51:06 +04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t power_ro_lock_store(struct device *dev,
|
|
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct mmc_blk_data *md, *part_md;
|
2017-05-19 16:37:30 +03:00
|
|
|
struct mmc_queue *mq;
|
|
|
|
struct request *req;
|
2011-12-02 11:51:06 +04:00
|
|
|
unsigned long set;
|
|
|
|
|
|
|
|
if (kstrtoul(buf, 0, &set))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (set != 1)
|
|
|
|
return count;
|
|
|
|
|
|
|
|
md = mmc_blk_get(dev_to_disk(dev));
|
2017-05-19 16:37:30 +03:00
|
|
|
mq = &md->queue;
|
2011-12-02 11:51:06 +04:00
|
|
|
|
2017-05-19 16:37:30 +03:00
|
|
|
/* Dispatch locking to the block layer */
|
2018-05-09 10:54:05 +03:00
|
|
|
req = blk_get_request(mq->queue, REQ_OP_DRV_OUT, 0);
|
2017-11-21 16:42:28 +03:00
|
|
|
if (IS_ERR(req)) {
|
|
|
|
count = PTR_ERR(req);
|
|
|
|
goto out_put;
|
|
|
|
}
|
2017-05-19 16:37:30 +03:00
|
|
|
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP;
|
2021-01-25 07:49:58 +03:00
|
|
|
blk_execute_rq(NULL, req, 0);
|
2017-05-19 16:37:30 +03:00
|
|
|
ret = req_to_mmc_queue_req(req)->drv_op_result;
|
2017-11-21 16:42:27 +03:00
|
|
|
blk_put_request(req);
|
2011-12-02 11:51:06 +04:00
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
pr_info("%s: Locking boot partition ro until next power on\n",
|
|
|
|
md->disk->disk_name);
|
|
|
|
set_disk_ro(md->disk, 1);
|
|
|
|
|
|
|
|
list_for_each_entry(part_md, &md->part, part)
|
|
|
|
if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
|
|
|
|
pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name);
|
|
|
|
set_disk_ro(part_md->disk, 1);
|
|
|
|
}
|
|
|
|
}
|
2017-11-21 16:42:28 +03:00
|
|
|
out_put:
|
2011-12-02 11:51:06 +04:00
|
|
|
mmc_blk_put(md);
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
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));
|
|
|
|
|
2014-09-22 11:12:51 +04:00
|
|
|
ret = snprintf(buf, PAGE_SIZE, "%d\n",
|
2011-04-12 03:10:25 +04:00
|
|
|
get_disk_ro(dev_to_disk(dev)) ^
|
|
|
|
md->read_only);
|
|
|
|
mmc_blk_put(md);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_disk_ro(dev_to_disk(dev), set || md->read_only);
|
|
|
|
ret = count;
|
|
|
|
out:
|
|
|
|
mmc_blk_put(md);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-03-02 18:33:30 +03:00
|
|
|
static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2008-03-02 18:33:30 +03:00
|
|
|
struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
|
2005-04-17 02:20:36 +04:00
|
|
|
int ret = -ENXIO;
|
|
|
|
|
2010-06-02 16:28:52 +04:00
|
|
|
mutex_lock(&block_mutex);
|
2005-04-17 02:20:36 +04:00
|
|
|
if (md) {
|
|
|
|
ret = 0;
|
2008-03-02 18:33:30 +03:00
|
|
|
if ((mode & FMODE_WRITE) && md->read_only) {
|
2008-09-06 01:00:24 +04:00
|
|
|
mmc_blk_put(md);
|
2005-09-07 02:18:52 +04:00
|
|
|
ret = -EROFS;
|
2008-09-06 01:00:24 +04:00
|
|
|
}
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
2010-06-02 16:28:52 +04:00
|
|
|
mutex_unlock(&block_mutex);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-05-06 05:52:57 +04:00
|
|
|
static void mmc_blk_release(struct gendisk *disk, fmode_t mode)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2008-03-02 18:33:30 +03:00
|
|
|
struct mmc_blk_data *md = disk->private_data;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2010-06-02 16:28:52 +04:00
|
|
|
mutex_lock(&block_mutex);
|
2005-04-17 02:20:36 +04:00
|
|
|
mmc_blk_put(md);
|
2010-06-02 16:28:52 +04:00
|
|
|
mutex_unlock(&block_mutex);
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-01-08 12:02:50 +03:00
|
|
|
mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2006-01-08 12:02:50 +03:00
|
|
|
geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
|
|
|
|
geo->heads = 4;
|
|
|
|
geo->sectors = 16;
|
|
|
|
return 0;
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
2011-04-27 02:56:29 +04:00
|
|
|
struct mmc_blk_ioc_data {
|
|
|
|
struct mmc_ioc_cmd ic;
|
|
|
|
unsigned char *buf;
|
|
|
|
u64 buf_bytes;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
struct mmc_rpmb_data *rpmb;
|
2011-04-27 02:56:29 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
|
|
|
|
struct mmc_ioc_cmd __user *user)
|
|
|
|
{
|
|
|
|
struct mmc_blk_ioc_data *idata;
|
|
|
|
int err;
|
|
|
|
|
2015-11-12 14:27:11 +03:00
|
|
|
idata = kmalloc(sizeof(*idata), GFP_KERNEL);
|
2011-04-27 02:56:29 +04:00
|
|
|
if (!idata) {
|
|
|
|
err = -ENOMEM;
|
2011-05-11 08:00:43 +04:00
|
|
|
goto out;
|
2011-04-27 02:56:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) {
|
|
|
|
err = -EFAULT;
|
2011-05-11 08:00:43 +04:00
|
|
|
goto idata_err;
|
2011-04-27 02:56:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks;
|
|
|
|
if (idata->buf_bytes > MMC_IOC_MAX_BYTES) {
|
|
|
|
err = -EOVERFLOW;
|
2011-05-11 08:00:43 +04:00
|
|
|
goto idata_err;
|
2011-04-27 02:56:29 +04:00
|
|
|
}
|
|
|
|
|
2016-07-08 18:27:02 +03:00
|
|
|
if (!idata->buf_bytes) {
|
|
|
|
idata->buf = NULL;
|
2011-11-23 12:05:58 +04:00
|
|
|
return idata;
|
2016-07-08 18:27:02 +03:00
|
|
|
}
|
2011-11-23 12:05:58 +04:00
|
|
|
|
2018-03-05 13:33:21 +03:00
|
|
|
idata->buf = memdup_user((void __user *)(unsigned long)
|
|
|
|
idata->ic.data_ptr, idata->buf_bytes);
|
|
|
|
if (IS_ERR(idata->buf)) {
|
|
|
|
err = PTR_ERR(idata->buf);
|
2011-05-11 08:00:43 +04:00
|
|
|
goto idata_err;
|
2011-04-27 02:56:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return idata;
|
|
|
|
|
2011-05-11 08:00:43 +04:00
|
|
|
idata_err:
|
2011-04-27 02:56:29 +04:00
|
|
|
kfree(idata);
|
2011-05-11 08:00:43 +04:00
|
|
|
out:
|
2011-04-27 02:56:29 +04:00
|
|
|
return ERR_PTR(err);
|
|
|
|
}
|
|
|
|
|
2015-09-22 12:27:53 +03:00
|
|
|
static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
|
|
|
|
struct mmc_blk_ioc_data *idata)
|
|
|
|
{
|
|
|
|
struct mmc_ioc_cmd *ic = &idata->ic;
|
|
|
|
|
|
|
|
if (copy_to_user(&(ic_ptr->response), ic->response,
|
|
|
|
sizeof(ic->response)))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
if (!idata->ic.write_flag) {
|
|
|
|
if (copy_to_user((void __user *)(unsigned long)ic->data_ptr,
|
|
|
|
idata->buf, idata->buf_bytes))
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-05 10:53:18 +03:00
|
|
|
static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
|
|
|
|
u32 *resp_errs)
|
|
|
|
{
|
|
|
|
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
|
|
|
|
int err = 0;
|
|
|
|
u32 status;
|
|
|
|
|
|
|
|
do {
|
|
|
|
bool done = time_after(jiffies, timeout);
|
|
|
|
|
|
|
|
err = __mmc_send_status(card, &status, 5);
|
|
|
|
if (err) {
|
|
|
|
dev_err(mmc_dev(card->host),
|
|
|
|
"error %d requesting status\n", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Accumulate any response error bits seen */
|
|
|
|
if (resp_errs)
|
|
|
|
*resp_errs |= status;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Timeout if the device never becomes ready for data and never
|
|
|
|
* leaves the program state.
|
|
|
|
*/
|
|
|
|
if (done) {
|
|
|
|
dev_err(mmc_dev(card->host),
|
|
|
|
"Card stuck in wrong state! %s status: %#x\n",
|
|
|
|
__func__, status);
|
|
|
|
return -ETIMEDOUT;
|
|
|
|
}
|
2020-02-04 11:54:43 +03:00
|
|
|
} while (!mmc_ready_for_data(status));
|
2019-09-05 10:53:18 +03:00
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2015-09-22 12:27:53 +03:00
|
|
|
static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
|
|
|
|
struct mmc_blk_ioc_data *idata)
|
2011-04-27 02:56:29 +04:00
|
|
|
{
|
2018-11-26 16:38:13 +03:00
|
|
|
struct mmc_command cmd = {}, sbc = {};
|
2016-12-19 14:51:18 +03:00
|
|
|
struct mmc_data data = {};
|
|
|
|
struct mmc_request mrq = {};
|
2011-04-27 02:56:29 +04:00
|
|
|
struct scatterlist sg;
|
|
|
|
int err;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
unsigned int target_part;
|
2011-04-27 02:56:29 +04:00
|
|
|
|
2015-09-22 12:27:53 +03:00
|
|
|
if (!card || !md || !idata)
|
|
|
|
return -EINVAL;
|
2011-04-27 02:56:29 +04:00
|
|
|
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
2012-08-06 19:12:31 +04:00
|
|
|
|
2011-11-23 12:05:58 +04:00
|
|
|
cmd.opcode = idata->ic.opcode;
|
|
|
|
cmd.arg = idata->ic.arg;
|
|
|
|
cmd.flags = idata->ic.flags;
|
|
|
|
|
|
|
|
if (idata->buf_bytes) {
|
|
|
|
data.sg = &sg;
|
|
|
|
data.sg_len = 1;
|
|
|
|
data.blksz = idata->ic.blksz;
|
|
|
|
data.blocks = idata->ic.blocks;
|
|
|
|
|
|
|
|
sg_init_one(data.sg, idata->buf, idata->buf_bytes);
|
|
|
|
|
|
|
|
if (idata->ic.write_flag)
|
|
|
|
data.flags = MMC_DATA_WRITE;
|
|
|
|
else
|
|
|
|
data.flags = MMC_DATA_READ;
|
|
|
|
|
|
|
|
/* data.flags must already be set before doing this. */
|
|
|
|
mmc_set_data_timeout(&data, card);
|
|
|
|
|
|
|
|
/* Allow overriding the timeout_ns for empirical tuning. */
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
mrq.cmd = &cmd;
|
|
|
|
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
err = mmc_blk_part_switch(card, target_part);
|
2012-08-06 19:12:31 +04:00
|
|
|
if (err)
|
2015-09-22 12:27:53 +03:00
|
|
|
return err;
|
2012-08-06 19:12:31 +04:00
|
|
|
|
2011-04-27 02:56:29 +04:00
|
|
|
if (idata->ic.is_acmd) {
|
|
|
|
err = mmc_app_cmd(card->host, card);
|
|
|
|
if (err)
|
2015-09-22 12:27:53 +03:00
|
|
|
return err;
|
2011-04-27 02:56:29 +04:00
|
|
|
}
|
|
|
|
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
if (idata->rpmb) {
|
2018-11-26 16:38:13 +03:00
|
|
|
sbc.opcode = MMC_SET_BLOCK_COUNT;
|
|
|
|
/*
|
|
|
|
* We don't do any blockcount validation because the max size
|
|
|
|
* may be increased by a future standard. We just copy the
|
|
|
|
* 'Reliable Write' bit here.
|
|
|
|
*/
|
|
|
|
sbc.arg = data.blocks | (idata->ic.write_flag & BIT(31));
|
|
|
|
sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
|
|
|
mrq.sbc = &sbc;
|
2012-08-06 19:12:31 +04:00
|
|
|
}
|
|
|
|
|
2013-06-05 15:13:08 +04:00
|
|
|
if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
|
2020-03-16 18:21:52 +03:00
|
|
|
(cmd.opcode == MMC_SWITCH))
|
|
|
|
return mmc_sanitize(card);
|
2013-04-18 16:41:55 +04:00
|
|
|
|
2011-04-27 02:56:29 +04:00
|
|
|
mmc_wait_for_req(card->host, &mrq);
|
|
|
|
|
|
|
|
if (cmd.error) {
|
|
|
|
dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
|
|
|
|
__func__, cmd.error);
|
2015-09-22 12:27:53 +03:00
|
|
|
return cmd.error;
|
2011-04-27 02:56:29 +04:00
|
|
|
}
|
|
|
|
if (data.error) {
|
|
|
|
dev_err(mmc_dev(card->host), "%s: data error %d\n",
|
|
|
|
__func__, data.error);
|
2015-09-22 12:27:53 +03:00
|
|
|
return data.error;
|
2011-04-27 02:56:29 +04:00
|
|
|
}
|
|
|
|
|
2018-03-08 17:08:11 +03:00
|
|
|
/*
|
|
|
|
* Make sure the cache of the PARTITION_CONFIG register and
|
|
|
|
* PARTITION_ACCESS bits is updated in case the ioctl ext_csd write
|
|
|
|
* changed it successfully.
|
|
|
|
*/
|
|
|
|
if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_PART_CONFIG) &&
|
|
|
|
(cmd.opcode == MMC_SWITCH)) {
|
|
|
|
struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
|
|
|
|
u8 value = MMC_EXTRACT_VALUE_FROM_ARG(cmd.arg);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update cache so the next mmc_blk_part_switch call operates
|
|
|
|
* on up-to-date data.
|
|
|
|
*/
|
|
|
|
card->ext_csd.part_config = value;
|
|
|
|
main_md->part_curr = value & EXT_CSD_PART_CONFIG_ACC_MASK;
|
|
|
|
}
|
|
|
|
|
2011-04-27 02:56:29 +04:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
|
2015-09-22 12:27:53 +03:00
|
|
|
memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
|
2011-04-27 02:56:29 +04:00
|
|
|
|
2020-12-02 23:23:20 +03:00
|
|
|
if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
|
2012-08-06 19:12:31 +04:00
|
|
|
/*
|
2019-09-05 10:53:18 +03:00
|
|
|
* Ensure RPMB/R1B command has completed by polling CMD13
|
2012-08-06 19:12:31 +04:00
|
|
|
* "Send Status".
|
|
|
|
*/
|
2019-09-05 10:53:18 +03:00
|
|
|
err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
|
2012-08-06 19:12:31 +04:00
|
|
|
}
|
|
|
|
|
2015-09-22 12:27:53 +03:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2017-08-21 00:39:11 +03:00
|
|
|
static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
struct mmc_ioc_cmd __user *ic_ptr,
|
|
|
|
struct mmc_rpmb_data *rpmb)
|
2015-09-22 12:27:53 +03:00
|
|
|
{
|
|
|
|
struct mmc_blk_ioc_data *idata;
|
2017-05-18 12:29:35 +03:00
|
|
|
struct mmc_blk_ioc_data *idatas[1];
|
2017-05-18 12:29:34 +03:00
|
|
|
struct mmc_queue *mq;
|
2015-09-22 12:27:53 +03:00
|
|
|
struct mmc_card *card;
|
2015-09-24 04:30:33 +03:00
|
|
|
int err = 0, ioc_err = 0;
|
2017-05-18 12:29:34 +03:00
|
|
|
struct request *req;
|
2015-09-22 12:27:53 +03:00
|
|
|
|
|
|
|
idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
|
|
|
|
if (IS_ERR(idata))
|
|
|
|
return PTR_ERR(idata);
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
/* This will be NULL on non-RPMB ioctl():s */
|
|
|
|
idata->rpmb = rpmb;
|
2015-09-22 12:27:53 +03:00
|
|
|
|
|
|
|
card = md->queue.card;
|
|
|
|
if (IS_ERR(card)) {
|
|
|
|
err = PTR_ERR(card);
|
|
|
|
goto cmd_done;
|
|
|
|
}
|
|
|
|
|
2017-05-18 12:29:34 +03:00
|
|
|
/*
|
|
|
|
* Dispatch the ioctl() into the block request queue.
|
|
|
|
*/
|
|
|
|
mq = &md->queue;
|
|
|
|
req = blk_get_request(mq->queue,
|
2018-05-09 10:54:05 +03:00
|
|
|
idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
|
2017-11-21 16:42:28 +03:00
|
|
|
if (IS_ERR(req)) {
|
|
|
|
err = PTR_ERR(req);
|
|
|
|
goto cmd_done;
|
|
|
|
}
|
2017-05-18 12:29:35 +03:00
|
|
|
idatas[0] = idata;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
req_to_mmc_queue_req(req)->drv_op =
|
|
|
|
rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
|
2017-08-21 00:39:06 +03:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_data = idatas;
|
2017-05-18 12:29:35 +03:00
|
|
|
req_to_mmc_queue_req(req)->ioc_count = 1;
|
2021-01-25 07:49:58 +03:00
|
|
|
blk_execute_rq(NULL, req, 0);
|
2017-05-19 16:37:30 +03:00
|
|
|
ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
|
2015-09-24 04:30:33 +03:00
|
|
|
err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
|
2017-05-18 12:29:34 +03:00
|
|
|
blk_put_request(req);
|
2015-09-22 12:27:53 +03:00
|
|
|
|
2011-04-27 02:56:29 +04:00
|
|
|
cmd_done:
|
|
|
|
kfree(idata->buf);
|
|
|
|
kfree(idata);
|
2015-09-24 04:30:33 +03:00
|
|
|
return ioc_err ? ioc_err : err;
|
2011-04-27 02:56:29 +04:00
|
|
|
}
|
|
|
|
|
2017-08-21 00:39:11 +03:00
|
|
|
static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
struct mmc_ioc_multi_cmd __user *user,
|
|
|
|
struct mmc_rpmb_data *rpmb)
|
2015-09-22 12:27:53 +03:00
|
|
|
{
|
|
|
|
struct mmc_blk_ioc_data **idata = NULL;
|
|
|
|
struct mmc_ioc_cmd __user *cmds = user->cmds;
|
|
|
|
struct mmc_card *card;
|
2017-05-18 12:29:35 +03:00
|
|
|
struct mmc_queue *mq;
|
2015-09-24 04:30:33 +03:00
|
|
|
int i, err = 0, ioc_err = 0;
|
2015-09-22 12:27:53 +03:00
|
|
|
__u64 num_of_cmds;
|
2017-05-18 12:29:35 +03:00
|
|
|
struct request *req;
|
2015-09-22 12:27:53 +03:00
|
|
|
|
|
|
|
if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
|
|
|
|
sizeof(num_of_cmds)))
|
|
|
|
return -EFAULT;
|
|
|
|
|
2017-07-05 18:09:42 +03:00
|
|
|
if (!num_of_cmds)
|
|
|
|
return 0;
|
|
|
|
|
2015-09-22 12:27:53 +03:00
|
|
|
if (num_of_cmds > MMC_IOC_MAX_CMDS)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
idata = kcalloc(num_of_cmds, sizeof(*idata), GFP_KERNEL);
|
|
|
|
if (!idata)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
for (i = 0; i < num_of_cmds; 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;
|
|
|
|
goto cmd_err;
|
|
|
|
}
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
/* This will be NULL on non-RPMB ioctl():s */
|
|
|
|
idata[i]->rpmb = rpmb;
|
2015-09-22 12:27:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
card = md->queue.card;
|
|
|
|
if (IS_ERR(card)) {
|
|
|
|
err = PTR_ERR(card);
|
2017-08-21 00:39:11 +03:00
|
|
|
goto cmd_err;
|
2015-09-22 12:27:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-18 12:29:35 +03:00
|
|
|
/*
|
|
|
|
* Dispatch the ioctl()s into the block request queue.
|
|
|
|
*/
|
|
|
|
mq = &md->queue;
|
|
|
|
req = blk_get_request(mq->queue,
|
2018-05-09 10:54:05 +03:00
|
|
|
idata[0]->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
|
2017-11-21 16:42:28 +03:00
|
|
|
if (IS_ERR(req)) {
|
|
|
|
err = PTR_ERR(req);
|
|
|
|
goto cmd_err;
|
|
|
|
}
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
req_to_mmc_queue_req(req)->drv_op =
|
|
|
|
rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
|
2017-08-21 00:39:06 +03:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_data = idata;
|
2017-05-18 12:29:35 +03:00
|
|
|
req_to_mmc_queue_req(req)->ioc_count = num_of_cmds;
|
2021-01-25 07:49:58 +03:00
|
|
|
blk_execute_rq(NULL, req, 0);
|
2017-05-19 16:37:30 +03:00
|
|
|
ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
|
2015-09-22 12:27:53 +03:00
|
|
|
|
|
|
|
/* copy to user if data and response */
|
2015-09-24 04:30:33 +03:00
|
|
|
for (i = 0; i < num_of_cmds && !err; i++)
|
2015-09-22 12:27:53 +03:00
|
|
|
err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
|
|
|
|
|
2017-05-18 12:29:35 +03:00
|
|
|
blk_put_request(req);
|
|
|
|
|
2015-09-22 12:27:53 +03:00
|
|
|
cmd_err:
|
|
|
|
for (i = 0; i < num_of_cmds; i++) {
|
|
|
|
kfree(idata[i]->buf);
|
|
|
|
kfree(idata[i]);
|
|
|
|
}
|
|
|
|
kfree(idata);
|
2015-09-24 04:30:33 +03:00
|
|
|
return ioc_err ? ioc_err : err;
|
2015-09-22 12:27:53 +03:00
|
|
|
}
|
|
|
|
|
2017-08-21 00:39:09 +03:00
|
|
|
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.
|
|
|
|
*/
|
2020-09-03 08:40:57 +03:00
|
|
|
if (!capable(CAP_SYS_RAWIO) || bdev_is_partition(bdev))
|
2017-08-21 00:39:09 +03:00
|
|
|
return -EPERM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-27 02:56:29 +04:00
|
|
|
static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
|
|
|
|
unsigned int cmd, unsigned long arg)
|
|
|
|
{
|
2017-08-21 00:39:11 +03:00
|
|
|
struct mmc_blk_data *md;
|
2017-08-21 00:39:09 +03:00
|
|
|
int ret;
|
|
|
|
|
2015-09-22 12:27:53 +03:00
|
|
|
switch (cmd) {
|
|
|
|
case MMC_IOC_CMD:
|
2017-08-21 00:39:09 +03:00
|
|
|
ret = mmc_blk_check_blkdev(bdev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2017-08-21 00:39:11 +03:00
|
|
|
md = mmc_blk_get(bdev->bd_disk);
|
|
|
|
if (!md)
|
|
|
|
return -EINVAL;
|
|
|
|
ret = mmc_blk_ioctl_cmd(md,
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
(struct mmc_ioc_cmd __user *)arg,
|
|
|
|
NULL);
|
2017-08-21 00:39:11 +03:00
|
|
|
mmc_blk_put(md);
|
|
|
|
return ret;
|
2015-09-22 12:27:53 +03:00
|
|
|
case MMC_IOC_MULTI_CMD:
|
2017-08-21 00:39:09 +03:00
|
|
|
ret = mmc_blk_check_blkdev(bdev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2017-08-21 00:39:11 +03:00
|
|
|
md = mmc_blk_get(bdev->bd_disk);
|
|
|
|
if (!md)
|
|
|
|
return -EINVAL;
|
|
|
|
ret = mmc_blk_ioctl_multi_cmd(md,
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
(struct mmc_ioc_multi_cmd __user *)arg,
|
|
|
|
NULL);
|
2017-08-21 00:39:11 +03:00
|
|
|
mmc_blk_put(md);
|
|
|
|
return ret;
|
2015-09-22 12:27:53 +03:00
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2011-04-27 02:56:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
static int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode,
|
|
|
|
unsigned int cmd, unsigned long arg)
|
|
|
|
{
|
|
|
|
return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-09-22 04:01:13 +04:00
|
|
|
static const struct block_device_operations mmc_bdops = {
|
2008-03-02 18:33:30 +03:00
|
|
|
.open = mmc_blk_open,
|
|
|
|
.release = mmc_blk_release,
|
2006-01-08 12:02:50 +03:00
|
|
|
.getgeo = mmc_blk_getgeo,
|
2005-04-17 02:20:36 +04:00
|
|
|
.owner = THIS_MODULE,
|
2011-04-27 02:56:29 +04:00
|
|
|
.ioctl = mmc_blk_ioctl,
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
.compat_ioctl = mmc_blk_compat_ioctl,
|
|
|
|
#endif
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
2017-03-13 15:36:39 +03:00
|
|
|
static int mmc_blk_part_switch_pre(struct mmc_card *card,
|
|
|
|
unsigned int part_type)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
|
|
|
|
if (card->ext_csd.cmdq_en) {
|
|
|
|
ret = mmc_cmdq_disable(card);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
mmc_retune_pause(card->host);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mmc_blk_part_switch_post(struct mmc_card *card,
|
|
|
|
unsigned int part_type)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
|
|
|
|
mmc_retune_unpause(card->host);
|
|
|
|
if (card->reenable_cmdq && !card->ext_csd.cmdq_en)
|
|
|
|
ret = mmc_cmdq_enable(card);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
static inline int mmc_blk_part_switch(struct mmc_card *card,
|
2017-08-21 00:39:10 +03:00
|
|
|
unsigned int part_type)
|
2011-04-12 03:10:25 +04:00
|
|
|
{
|
2017-03-13 15:36:39 +03:00
|
|
|
int ret = 0;
|
2014-10-06 16:34:09 +04:00
|
|
|
struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
|
2011-09-23 13:48:20 +04:00
|
|
|
|
2017-08-21 00:39:10 +03:00
|
|
|
if (main_md->part_curr == part_type)
|
2011-04-12 03:10:25 +04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (mmc_card_mmc(card)) {
|
2011-09-23 13:48:20 +04:00
|
|
|
u8 part_config = card->ext_csd.part_config;
|
|
|
|
|
2017-08-21 00:39:10 +03:00
|
|
|
ret = mmc_blk_part_switch_pre(card, part_type);
|
2017-03-13 15:36:39 +03:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2016-05-04 14:38:13 +03:00
|
|
|
|
2011-09-23 13:48:20 +04:00
|
|
|
part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
|
2017-08-21 00:39:10 +03:00
|
|
|
part_config |= part_type;
|
2011-04-12 03:10:25 +04:00
|
|
|
|
|
|
|
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
2011-09-23 13:48:20 +04:00
|
|
|
EXT_CSD_PART_CONFIG, part_config,
|
2011-04-12 03:10:25 +04:00
|
|
|
card->ext_csd.part_time);
|
2016-05-04 14:38:13 +03:00
|
|
|
if (ret) {
|
2017-08-21 00:39:10 +03:00
|
|
|
mmc_blk_part_switch_post(card, part_type);
|
2011-04-12 03:10:25 +04:00
|
|
|
return ret;
|
2016-05-04 14:38:13 +03:00
|
|
|
}
|
2011-09-23 13:48:20 +04:00
|
|
|
|
|
|
|
card->ext_csd.part_config = part_config;
|
2016-05-04 14:38:13 +03:00
|
|
|
|
2017-03-13 15:36:39 +03:00
|
|
|
ret = mmc_blk_part_switch_post(card, main_md->part_curr);
|
2011-08-29 17:42:15 +04:00
|
|
|
}
|
2011-04-12 03:10:25 +04:00
|
|
|
|
2017-08-21 00:39:10 +03:00
|
|
|
main_md->part_curr = part_type;
|
2017-03-13 15:36:39 +03:00
|
|
|
return ret;
|
2011-04-12 03:10:25 +04:00
|
|
|
}
|
|
|
|
|
2017-02-01 15:47:57 +03:00
|
|
|
static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
|
2006-10-06 11:44:03 +04:00
|
|
|
{
|
|
|
|
int err;
|
2009-06-09 02:33:57 +04:00
|
|
|
u32 result;
|
|
|
|
__be32 *blocks;
|
2006-10-06 11:44:03 +04:00
|
|
|
|
2016-12-19 14:51:18 +03:00
|
|
|
struct mmc_request mrq = {};
|
|
|
|
struct mmc_command cmd = {};
|
|
|
|
struct mmc_data data = {};
|
2006-10-06 11:44:03 +04:00
|
|
|
|
|
|
|
struct scatterlist sg;
|
|
|
|
|
|
|
|
cmd.opcode = MMC_APP_CMD;
|
|
|
|
cmd.arg = card->rca << 16;
|
2007-08-08 20:10:23 +04:00
|
|
|
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
|
2006-10-06 11:44:03 +04:00
|
|
|
|
|
|
|
err = mmc_wait_for_cmd(card->host, &cmd, 0);
|
2007-08-08 20:10:23 +04:00
|
|
|
if (err)
|
2017-02-01 15:47:57 +03:00
|
|
|
return err;
|
2007-08-08 20:10:23 +04:00
|
|
|
if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
|
2017-02-01 15:47:57 +03:00
|
|
|
return -EIO;
|
2006-10-06 11:44:03 +04:00
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(struct mmc_command));
|
|
|
|
|
|
|
|
cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
|
|
|
|
cmd.arg = 0;
|
2007-08-08 20:10:23 +04:00
|
|
|
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
|
2006-10-06 11:44:03 +04:00
|
|
|
|
|
|
|
data.blksz = 4;
|
|
|
|
data.blocks = 1;
|
|
|
|
data.flags = MMC_DATA_READ;
|
|
|
|
data.sg = &sg;
|
|
|
|
data.sg_len = 1;
|
2012-06-13 15:40:43 +04:00
|
|
|
mmc_set_data_timeout(&data, card);
|
2006-10-06 11:44:03 +04:00
|
|
|
|
|
|
|
mrq.cmd = &cmd;
|
|
|
|
mrq.data = &data;
|
|
|
|
|
2009-06-09 02:33:57 +04:00
|
|
|
blocks = kmalloc(4, GFP_KERNEL);
|
|
|
|
if (!blocks)
|
2017-02-01 15:47:57 +03:00
|
|
|
return -ENOMEM;
|
2009-06-09 02:33:57 +04:00
|
|
|
|
|
|
|
sg_init_one(&sg, blocks, 4);
|
2006-10-06 11:44:03 +04:00
|
|
|
|
|
|
|
mmc_wait_for_req(card->host, &mrq);
|
|
|
|
|
2009-06-09 02:33:57 +04:00
|
|
|
result = ntohl(*blocks);
|
|
|
|
kfree(blocks);
|
|
|
|
|
2007-07-23 00:18:46 +04:00
|
|
|
if (cmd.error || data.error)
|
2017-02-01 15:47:57 +03:00
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
*written_blocks = result;
|
2006-10-06 11:44:03 +04:00
|
|
|
|
2017-02-01 15:47:57 +03:00
|
|
|
return 0;
|
2006-10-06 11:44:03 +04:00
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:13 +03:00
|
|
|
static unsigned int mmc_blk_clock_khz(struct mmc_host *host)
|
|
|
|
{
|
|
|
|
if (host->actual_clock)
|
|
|
|
return host->actual_clock / 1000;
|
|
|
|
|
|
|
|
/* Clock may be subject to a divisor, fudge it by a factor of 2. */
|
|
|
|
if (host->ios.clock)
|
|
|
|
return host->ios.clock / 2000;
|
|
|
|
|
|
|
|
/* How can there be no clock */
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
return 100; /* 100 kHz is minimum possible value */
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host,
|
|
|
|
struct mmc_data *data)
|
|
|
|
{
|
|
|
|
unsigned int ms = DIV_ROUND_UP(data->timeout_ns, 1000000);
|
|
|
|
unsigned int khz;
|
|
|
|
|
|
|
|
if (data->timeout_clks) {
|
|
|
|
khz = mmc_blk_clock_khz(host);
|
|
|
|
ms += DIV_ROUND_UP(data->timeout_clks, khz);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ms;
|
|
|
|
}
|
|
|
|
|
2011-08-29 17:42:15 +04:00
|
|
|
static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
|
|
|
|
int type)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (md->reset_done & type)
|
|
|
|
return -EEXIST;
|
|
|
|
|
|
|
|
md->reset_done |= type;
|
|
|
|
err = mmc_hw_reset(host);
|
|
|
|
/* Ensure we switch back to the correct partition */
|
|
|
|
if (err != -EOPNOTSUPP) {
|
2014-10-06 16:34:09 +04:00
|
|
|
struct mmc_blk_data *main_md =
|
|
|
|
dev_get_drvdata(&host->card->dev);
|
2011-08-29 17:42:15 +04:00
|
|
|
int part_err;
|
|
|
|
|
|
|
|
main_md->part_curr = main_md->part_type;
|
2017-08-21 00:39:10 +03:00
|
|
|
part_err = mmc_blk_part_switch(host->card, md->part_type);
|
2011-08-29 17:42:15 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
|
|
|
|
{
|
|
|
|
md->reset_done &= ~type;
|
|
|
|
}
|
|
|
|
|
2017-05-19 16:37:29 +03:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
* function.
|
|
|
|
*/
|
|
|
|
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;
|
2017-08-21 00:39:06 +03:00
|
|
|
struct mmc_blk_ioc_data **idata;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
bool rpmb_ioctl;
|
2017-08-21 00:39:08 +03:00
|
|
|
u8 **ext_csd;
|
|
|
|
u32 status;
|
2017-05-19 16:37:30 +03:00
|
|
|
int ret;
|
2017-05-19 16:37:29 +03:00
|
|
|
int i;
|
|
|
|
|
|
|
|
mq_rq = req_to_mmc_queue_req(req);
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
rpmb_ioctl = (mq_rq->drv_op == MMC_DRV_OP_IOCTL_RPMB);
|
2017-05-19 16:37:29 +03:00
|
|
|
|
|
|
|
switch (mq_rq->drv_op) {
|
|
|
|
case MMC_DRV_OP_IOCTL:
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
case MMC_DRV_OP_IOCTL_RPMB:
|
2017-08-21 00:39:06 +03:00
|
|
|
idata = mq_rq->drv_op_data;
|
2017-07-05 18:09:41 +03:00
|
|
|
for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
|
2017-08-21 00:39:06 +03:00
|
|
|
ret = __mmc_blk_ioctl_cmd(card, md, idata[i]);
|
2017-05-19 16:37:30 +03:00
|
|
|
if (ret)
|
2017-05-19 16:37:29 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Always switch back to main area after RPMB access */
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
if (rpmb_ioctl)
|
|
|
|
mmc_blk_part_switch(card, 0);
|
2017-05-19 16:37:30 +03:00
|
|
|
break;
|
|
|
|
case MMC_DRV_OP_BOOT_WP:
|
|
|
|
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
|
|
|
|
card->ext_csd.boot_ro_lock |
|
|
|
|
EXT_CSD_BOOT_WP_B_PWR_WP_EN,
|
|
|
|
card->ext_csd.part_time);
|
|
|
|
if (ret)
|
|
|
|
pr_err("%s: Locking boot partition ro until next power on failed: %d\n",
|
|
|
|
md->disk->disk_name, ret);
|
|
|
|
else
|
|
|
|
card->ext_csd.boot_ro_lock |=
|
|
|
|
EXT_CSD_BOOT_WP_B_PWR_WP_EN;
|
2017-05-19 16:37:29 +03:00
|
|
|
break;
|
2017-08-21 00:39:08 +03:00
|
|
|
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;
|
2017-05-19 16:37:29 +03:00
|
|
|
default:
|
2017-05-19 16:37:30 +03:00
|
|
|
pr_err("%s: unknown driver specific operation\n",
|
|
|
|
md->disk->disk_name);
|
|
|
|
ret = -EINVAL;
|
2017-05-19 16:37:29 +03:00
|
|
|
break;
|
|
|
|
}
|
2017-05-19 16:37:30 +03:00
|
|
|
mq_rq->drv_op_result = ret;
|
2017-11-29 16:41:18 +03:00
|
|
|
blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK);
|
2017-05-19 16:37:29 +03:00
|
|
|
}
|
|
|
|
|
2017-01-24 13:17:57 +03:00
|
|
|
static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
|
2010-08-12 01:17:47 +04:00
|
|
|
{
|
2016-11-18 15:36:15 +03:00
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
2010-08-12 01:17:47 +04:00
|
|
|
struct mmc_card *card = md->queue.card;
|
2019-02-06 14:28:05 +03:00
|
|
|
unsigned int from, nr;
|
2011-08-29 17:42:15 +04:00
|
|
|
int err = 0, type = MMC_BLK_DISCARD;
|
2017-06-03 10:38:04 +03:00
|
|
|
blk_status_t status = BLK_STS_OK;
|
2010-08-12 01:17:47 +04:00
|
|
|
|
|
|
|
if (!mmc_can_erase(card)) {
|
2017-06-03 10:38:04 +03:00
|
|
|
status = BLK_STS_NOTSUPP;
|
2016-12-19 17:03:44 +03:00
|
|
|
goto fail;
|
2010-08-12 01:17:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
from = blk_rq_pos(req);
|
|
|
|
nr = blk_rq_sectors(req);
|
|
|
|
|
2016-12-19 17:03:45 +03:00
|
|
|
do {
|
|
|
|
err = 0;
|
|
|
|
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
|
|
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
|
INAND_CMD38_ARG_EXT_CSD,
|
2019-02-06 14:28:05 +03:00
|
|
|
card->erase_arg == MMC_TRIM_ARG ?
|
2016-12-19 17:03:45 +03:00
|
|
|
INAND_CMD38_ARG_TRIM :
|
|
|
|
INAND_CMD38_ARG_ERASE,
|
2020-01-22 17:27:46 +03:00
|
|
|
card->ext_csd.generic_cmd6_time);
|
2016-12-19 17:03:45 +03:00
|
|
|
}
|
|
|
|
if (!err)
|
2019-02-06 14:28:05 +03:00
|
|
|
err = mmc_erase(card, from, nr, card->erase_arg);
|
2016-12-19 17:03:45 +03:00
|
|
|
} while (err == -EIO && !mmc_blk_reset(md, card->host, type));
|
2017-06-03 10:38:04 +03:00
|
|
|
if (err)
|
|
|
|
status = BLK_STS_IOERR;
|
|
|
|
else
|
2011-08-29 17:42:15 +04:00
|
|
|
mmc_blk_reset_success(md, type);
|
2016-12-19 17:03:44 +03:00
|
|
|
fail:
|
2017-11-29 16:41:18 +03:00
|
|
|
blk_mq_end_request(req, status);
|
2010-08-12 01:17:47 +04:00
|
|
|
}
|
|
|
|
|
2017-01-24 13:17:57 +03:00
|
|
|
static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
|
2010-08-12 01:17:50 +04:00
|
|
|
struct request *req)
|
|
|
|
{
|
2016-11-18 15:36:15 +03:00
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
2010-08-12 01:17:50 +04:00
|
|
|
struct mmc_card *card = md->queue.card;
|
2013-04-18 16:41:55 +04:00
|
|
|
unsigned int from, nr, arg;
|
2011-08-29 17:42:15 +04:00
|
|
|
int err = 0, type = MMC_BLK_SECDISCARD;
|
2017-06-03 10:38:04 +03:00
|
|
|
blk_status_t status = BLK_STS_OK;
|
2010-08-12 01:17:50 +04:00
|
|
|
|
2013-04-18 16:41:55 +04:00
|
|
|
if (!(mmc_can_secure_erase_trim(card))) {
|
2017-06-03 10:38:04 +03:00
|
|
|
status = BLK_STS_NOTSUPP;
|
2010-08-12 01:17:50 +04:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2012-04-05 15:45:48 +04:00
|
|
|
from = blk_rq_pos(req);
|
|
|
|
nr = blk_rq_sectors(req);
|
|
|
|
|
2013-04-18 16:41:55 +04:00
|
|
|
if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
|
|
|
|
arg = MMC_SECURE_TRIM1_ARG;
|
|
|
|
else
|
|
|
|
arg = MMC_SECURE_ERASE_ARG;
|
2011-10-14 09:15:48 +04:00
|
|
|
|
2011-08-29 17:42:15 +04:00
|
|
|
retry:
|
2011-04-13 00:06:53 +04:00
|
|
|
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
|
|
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
|
INAND_CMD38_ARG_EXT_CSD,
|
|
|
|
arg == MMC_SECURE_TRIM1_ARG ?
|
|
|
|
INAND_CMD38_ARG_SECTRIM1 :
|
|
|
|
INAND_CMD38_ARG_SECERASE,
|
2020-01-22 17:27:46 +03:00
|
|
|
card->ext_csd.generic_cmd6_time);
|
2011-04-13 00:06:53 +04:00
|
|
|
if (err)
|
2012-04-05 15:45:48 +04:00
|
|
|
goto out_retry;
|
2011-04-13 00:06:53 +04:00
|
|
|
}
|
2012-04-05 15:45:48 +04:00
|
|
|
|
2010-08-12 01:17:50 +04:00
|
|
|
err = mmc_erase(card, from, nr, arg);
|
2012-04-05 15:45:48 +04:00
|
|
|
if (err == -EIO)
|
|
|
|
goto out_retry;
|
2017-06-03 10:38:04 +03:00
|
|
|
if (err) {
|
|
|
|
status = BLK_STS_IOERR;
|
2012-04-05 15:45:48 +04:00
|
|
|
goto out;
|
2017-06-03 10:38:04 +03:00
|
|
|
}
|
2012-04-05 15:45:48 +04:00
|
|
|
|
|
|
|
if (arg == MMC_SECURE_TRIM1_ARG) {
|
2011-04-13 00:06:53 +04:00
|
|
|
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
|
|
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
|
INAND_CMD38_ARG_EXT_CSD,
|
|
|
|
INAND_CMD38_ARG_SECTRIM2,
|
2020-01-22 17:27:46 +03:00
|
|
|
card->ext_csd.generic_cmd6_time);
|
2011-04-13 00:06:53 +04:00
|
|
|
if (err)
|
2012-04-05 15:45:48 +04:00
|
|
|
goto out_retry;
|
2011-04-13 00:06:53 +04:00
|
|
|
}
|
2012-04-05 15:45:48 +04:00
|
|
|
|
2010-08-12 01:17:50 +04:00
|
|
|
err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
|
2012-04-05 15:45:48 +04:00
|
|
|
if (err == -EIO)
|
|
|
|
goto out_retry;
|
2017-06-03 10:38:04 +03:00
|
|
|
if (err) {
|
|
|
|
status = BLK_STS_IOERR;
|
2012-04-05 15:45:48 +04:00
|
|
|
goto out;
|
2017-06-03 10:38:04 +03:00
|
|
|
}
|
2011-04-13 00:06:53 +04:00
|
|
|
}
|
2012-04-05 15:45:48 +04:00
|
|
|
|
|
|
|
out_retry:
|
|
|
|
if (err && !mmc_blk_reset(md, card->host, type))
|
2011-08-29 17:42:15 +04:00
|
|
|
goto retry;
|
|
|
|
if (!err)
|
|
|
|
mmc_blk_reset_success(md, type);
|
2012-04-05 15:45:48 +04:00
|
|
|
out:
|
2017-11-29 16:41:18 +03:00
|
|
|
blk_mq_end_request(req, status);
|
2010-08-12 01:17:50 +04:00
|
|
|
}
|
|
|
|
|
2017-01-24 13:17:57 +03:00
|
|
|
static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
|
2011-04-01 03:40:00 +04:00
|
|
|
{
|
2016-11-18 15:36:15 +03:00
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
2011-10-14 09:03:21 +04:00
|
|
|
struct mmc_card *card = md->queue.card;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
ret = mmc_flush_cache(card);
|
2017-11-29 16:41:18 +03:00
|
|
|
blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK);
|
2011-04-01 03:40:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reformat current write as a reliable write, supporting
|
|
|
|
* both legacy and the enhanced reliable write MMC cards.
|
|
|
|
* In each transfer we'll handle only as much as a single
|
|
|
|
* reliable write can handle, thus finish the request in
|
|
|
|
* partial completions.
|
|
|
|
*/
|
2011-05-24 00:06:36 +04:00
|
|
|
static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
|
|
|
|
struct mmc_card *card,
|
|
|
|
struct request *req)
|
2011-04-01 03:40:00 +04:00
|
|
|
{
|
|
|
|
if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) {
|
|
|
|
/* Legacy mode imposes restrictions on transfers. */
|
2017-03-13 15:36:40 +03:00
|
|
|
if (!IS_ALIGNED(blk_rq_pos(req), card->ext_csd.rel_sectors))
|
2011-04-01 03:40:00 +04:00
|
|
|
brq->data.blocks = 1;
|
|
|
|
|
|
|
|
if (brq->data.blocks > card->ext_csd.rel_sectors)
|
|
|
|
brq->data.blocks = card->ext_csd.rel_sectors;
|
|
|
|
else if (brq->data.blocks < card->ext_csd.rel_sectors)
|
|
|
|
brq->data.blocks = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:10 +03:00
|
|
|
#define CMD_ERRORS_EXCL_OOR \
|
|
|
|
(R1_ADDRESS_ERROR | /* Misaligned address */ \
|
2011-06-20 23:10:49 +04:00
|
|
|
R1_BLOCK_LEN_ERROR | /* Transferred block length incorrect */\
|
|
|
|
R1_WP_VIOLATION | /* Tried to write to protected block */ \
|
2017-04-08 23:20:05 +03:00
|
|
|
R1_CARD_ECC_FAILED | /* Card ECC failed */ \
|
2011-06-20 23:10:49 +04:00
|
|
|
R1_CC_ERROR | /* Card controller error */ \
|
|
|
|
R1_ERROR) /* General/unknown error */
|
|
|
|
|
2017-11-29 16:41:10 +03:00
|
|
|
#define CMD_ERRORS \
|
|
|
|
(CMD_ERRORS_EXCL_OOR | \
|
|
|
|
R1_OUT_OF_RANGE) /* Command argument out of range */ \
|
|
|
|
|
2017-08-18 04:16:08 +03:00
|
|
|
static void mmc_blk_eval_resp_error(struct mmc_blk_request *brq)
|
2017-04-08 23:20:05 +03:00
|
|
|
{
|
2017-08-18 04:16:08 +03:00
|
|
|
u32 val;
|
2017-04-08 23:20:05 +03:00
|
|
|
|
2017-08-18 04:16:08 +03:00
|
|
|
/*
|
|
|
|
* Per the SD specification(physical layer version 4.10)[1],
|
|
|
|
* section 4.3.3, it explicitly states that "When the last
|
|
|
|
* block of user area is read using CMD18, the host should
|
|
|
|
* ignore OUT_OF_RANGE error that may occur even the sequence
|
|
|
|
* is correct". And JESD84-B51 for eMMC also has a similar
|
|
|
|
* statement on section 6.8.3.
|
|
|
|
*
|
|
|
|
* Multiple block read/write could be done by either predefined
|
|
|
|
* method, namely CMD23, or open-ending mode. For open-ending mode,
|
|
|
|
* we should ignore the OUT_OF_RANGE error as it's normal behaviour.
|
|
|
|
*
|
|
|
|
* However the spec[1] doesn't tell us whether we should also
|
|
|
|
* ignore that for predefined method. But per the spec[1], section
|
|
|
|
* 4.15 Set Block Count Command, it says"If illegal block count
|
|
|
|
* is set, out of range error will be indicated during read/write
|
|
|
|
* operation (For example, data transfer is stopped at user area
|
|
|
|
* boundary)." In another word, we could expect a out of range error
|
|
|
|
* in the response for the following CMD18/25. And if argument of
|
|
|
|
* CMD23 + the argument of CMD18/25 exceed the max number of blocks,
|
|
|
|
* we could also expect to get a -ETIMEDOUT or any error number from
|
|
|
|
* the host drivers due to missing data response(for write)/data(for
|
|
|
|
* read), as the cards will stop the data transfer by itself per the
|
|
|
|
* spec. So we only need to check R1_OUT_OF_RANGE for open-ending mode.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!brq->stop.error) {
|
|
|
|
bool oor_with_open_end;
|
|
|
|
/* If there is no error yet, check R1 response */
|
|
|
|
|
|
|
|
val = brq->stop.resp[0] & CMD_ERRORS;
|
|
|
|
oor_with_open_end = val & R1_OUT_OF_RANGE && !brq->mrq.sbc;
|
|
|
|
|
|
|
|
if (val && !oor_with_open_end)
|
|
|
|
brq->stop.error = -EIO;
|
|
|
|
}
|
2017-04-08 23:20:05 +03:00
|
|
|
}
|
|
|
|
|
2017-03-13 15:36:41 +03:00
|
|
|
static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq,
|
2017-09-22 15:36:55 +03:00
|
|
|
int disable_multi, bool *do_rel_wr_p,
|
|
|
|
bool *do_data_tag_p)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2017-03-13 15:36:41 +03:00
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
|
|
|
struct mmc_card *card = md->queue.card;
|
2011-07-01 20:55:29 +04:00
|
|
|
struct mmc_blk_request *brq = &mqrq->brq;
|
2017-05-19 16:37:27 +03:00
|
|
|
struct request *req = mmc_queue_req_to_req(mqrq);
|
2017-09-22 15:36:55 +03:00
|
|
|
bool do_rel_wr, do_data_tag;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2011-04-01 03:40:00 +04:00
|
|
|
/*
|
|
|
|
* Reliable writes are used to implement Forced Unit Access and
|
2015-11-06 18:12:26 +03:00
|
|
|
* are supported only on MMCs.
|
2011-04-01 03:40:00 +04:00
|
|
|
*/
|
2017-09-22 15:36:55 +03:00
|
|
|
do_rel_wr = (req->cmd_flags & REQ_FUA) &&
|
|
|
|
rq_data_dir(req) == WRITE &&
|
|
|
|
(md->flags & MMC_BLK_REL_WR);
|
2011-04-01 03:40:00 +04:00
|
|
|
|
2011-07-01 20:55:29 +04:00
|
|
|
memset(brq, 0, sizeof(struct mmc_blk_request));
|
2017-03-13 15:36:41 +03:00
|
|
|
|
2021-01-26 03:14:48 +03:00
|
|
|
mmc_crypto_prepare_req(mqrq);
|
|
|
|
|
2011-07-01 20:55:29 +04:00
|
|
|
brq->mrq.data = &brq->data;
|
2017-09-22 15:36:56 +03:00
|
|
|
brq->mrq.tag = req->tag;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2011-07-01 20:55:29 +04:00
|
|
|
brq->stop.opcode = MMC_STOP_TRANSMISSION;
|
|
|
|
brq->stop.arg = 0;
|
2017-03-13 15:36:41 +03:00
|
|
|
|
|
|
|
if (rq_data_dir(req) == READ) {
|
|
|
|
brq->data.flags = MMC_DATA_READ;
|
|
|
|
brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
|
|
|
|
} else {
|
|
|
|
brq->data.flags = MMC_DATA_WRITE;
|
|
|
|
brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
|
|
|
|
}
|
|
|
|
|
|
|
|
brq->data.blksz = 512;
|
2011-07-01 20:55:29 +04:00
|
|
|
brq->data.blocks = blk_rq_sectors(req);
|
2017-09-22 15:36:56 +03:00
|
|
|
brq->data.blk_addr = blk_rq_pos(req);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The command queue supports 2 priorities: "high" (1) and "simple" (0).
|
|
|
|
* The eMMC will give "high" priority tasks priority over "simple"
|
|
|
|
* priority tasks. Here we always set "simple" priority by not setting
|
|
|
|
* MMC_DATA_PRIO.
|
|
|
|
*/
|
2008-12-31 20:21:17 +03:00
|
|
|
|
2011-07-01 20:55:29 +04:00
|
|
|
/*
|
|
|
|
* The block layer doesn't support all sector count
|
|
|
|
* restrictions, so we need to be prepared for too big
|
|
|
|
* requests.
|
|
|
|
*/
|
|
|
|
if (brq->data.blocks > card->host->max_blk_count)
|
|
|
|
brq->data.blocks = card->host->max_blk_count;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2011-10-07 00:50:33 +04:00
|
|
|
if (brq->data.blocks > 1) {
|
2018-10-08 18:07:30 +03:00
|
|
|
/*
|
|
|
|
* Some SD cards in SPI mode return a CRC error or even lock up
|
|
|
|
* completely when trying to read the last block using a
|
|
|
|
* multiblock read command.
|
|
|
|
*/
|
|
|
|
if (mmc_host_is_spi(card->host) && (rq_data_dir(req) == READ) &&
|
|
|
|
(blk_rq_pos(req) + blk_rq_sectors(req) ==
|
|
|
|
get_capacity(md->disk)))
|
|
|
|
brq->data.blocks--;
|
|
|
|
|
2011-10-07 00:50:33 +04:00
|
|
|
/*
|
|
|
|
* After a read error, we redo the request one sector
|
|
|
|
* at a time in order to accurately determine which
|
|
|
|
* sectors can be read successfully.
|
|
|
|
*/
|
|
|
|
if (disable_multi)
|
|
|
|
brq->data.blocks = 1;
|
|
|
|
|
2014-09-03 06:08:53 +04:00
|
|
|
/*
|
|
|
|
* Some controllers have HW issues while operating
|
|
|
|
* in multiple I/O mode
|
|
|
|
*/
|
|
|
|
if (card->host->ops->multi_io_quirk)
|
|
|
|
brq->data.blocks = card->host->ops->multi_io_quirk(card,
|
|
|
|
(rq_data_dir(req) == READ) ?
|
|
|
|
MMC_DATA_READ : MMC_DATA_WRITE,
|
|
|
|
brq->data.blocks);
|
2011-10-07 00:50:33 +04:00
|
|
|
}
|
2011-05-24 00:06:36 +04:00
|
|
|
|
2017-09-22 15:36:56 +03:00
|
|
|
if (do_rel_wr) {
|
2017-03-13 15:36:41 +03:00
|
|
|
mmc_apply_rel_rw(brq, card, req);
|
2017-09-22 15:36:56 +03:00
|
|
|
brq->data.flags |= MMC_DATA_REL_WR;
|
|
|
|
}
|
2017-03-13 15:36:41 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Data tag is used only during writing meta data to speed
|
|
|
|
* up write and any subsequent read of this meta data
|
|
|
|
*/
|
2017-09-22 15:36:55 +03:00
|
|
|
do_data_tag = card->ext_csd.data_tag_unit_size &&
|
|
|
|
(req->cmd_flags & REQ_META) &&
|
|
|
|
(rq_data_dir(req) == WRITE) &&
|
|
|
|
((brq->data.blocks * brq->data.blksz) >=
|
|
|
|
card->ext_csd.data_tag_unit_size);
|
2017-03-13 15:36:41 +03:00
|
|
|
|
2017-09-22 15:36:56 +03:00
|
|
|
if (do_data_tag)
|
|
|
|
brq->data.flags |= MMC_DATA_DAT_TAG;
|
|
|
|
|
2017-03-13 15:36:41 +03:00
|
|
|
mmc_set_data_timeout(&brq->data, card);
|
|
|
|
|
|
|
|
brq->data.sg = mqrq->sg;
|
|
|
|
brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adjust the sg list so it is the same size as the
|
|
|
|
* request.
|
|
|
|
*/
|
|
|
|
if (brq->data.blocks != blk_rq_sectors(req)) {
|
|
|
|
int i, data_size = brq->data.blocks << 9;
|
|
|
|
struct scatterlist *sg;
|
|
|
|
|
|
|
|
for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) {
|
|
|
|
data_size -= sg->length;
|
|
|
|
if (data_size <= 0) {
|
|
|
|
sg->length += data_size;
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
brq->data.sg_len = i;
|
|
|
|
}
|
|
|
|
|
2017-09-22 15:36:55 +03:00
|
|
|
if (do_rel_wr_p)
|
|
|
|
*do_rel_wr_p = do_rel_wr;
|
|
|
|
|
|
|
|
if (do_data_tag_p)
|
|
|
|
*do_data_tag_p = do_data_tag;
|
2017-03-13 15:36:41 +03:00
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:04 +03:00
|
|
|
#define MMC_CQE_RETRIES 2
|
|
|
|
|
|
|
|
static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
|
|
|
struct mmc_request *mrq = &mqrq->brq.mrq;
|
|
|
|
struct request_queue *q = req->q;
|
|
|
|
struct mmc_host *host = mq->card->host;
|
2020-05-06 17:34:02 +03:00
|
|
|
enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
|
2017-11-29 16:41:04 +03:00
|
|
|
unsigned long flags;
|
|
|
|
bool put_card;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
mmc_cqe_post_req(host, mrq);
|
|
|
|
|
|
|
|
if (mrq->cmd && mrq->cmd->error)
|
|
|
|
err = mrq->cmd->error;
|
|
|
|
else if (mrq->data && mrq->data->error)
|
|
|
|
err = mrq->data->error;
|
|
|
|
else
|
|
|
|
err = 0;
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
if (mqrq->retries++ < MMC_CQE_RETRIES)
|
|
|
|
blk_mq_requeue_request(req, true);
|
|
|
|
else
|
|
|
|
blk_mq_end_request(req, BLK_STS_IOERR);
|
|
|
|
} else if (mrq->data) {
|
|
|
|
if (blk_update_request(req, BLK_STS_OK, mrq->data->bytes_xfered))
|
|
|
|
blk_mq_requeue_request(req, true);
|
|
|
|
else
|
|
|
|
__blk_mq_end_request(req, BLK_STS_OK);
|
|
|
|
} else {
|
|
|
|
blk_mq_end_request(req, BLK_STS_OK);
|
|
|
|
}
|
|
|
|
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 16:41:04 +03:00
|
|
|
|
2020-05-06 17:34:02 +03:00
|
|
|
mq->in_flight[issue_type] -= 1;
|
2017-11-29 16:41:04 +03:00
|
|
|
|
|
|
|
put_card = (mmc_tot_in_flight(mq) == 0);
|
|
|
|
|
|
|
|
mmc_cqe_check_busy(mq);
|
|
|
|
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 16:41:04 +03:00
|
|
|
|
|
|
|
if (!mq->cqe_busy)
|
|
|
|
blk_mq_run_hw_queues(q, true);
|
|
|
|
|
|
|
|
if (put_card)
|
|
|
|
mmc_put_card(mq->card, &mq->ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mmc_blk_cqe_recovery(struct mmc_queue *mq)
|
|
|
|
{
|
|
|
|
struct mmc_card *card = mq->card;
|
|
|
|
struct mmc_host *host = card->host;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
pr_debug("%s: CQE recovery start\n", mmc_hostname(host));
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
pr_debug("%s: CQE recovery done\n", mmc_hostname(host));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_cqe_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;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
2020-06-11 09:44:47 +03:00
|
|
|
else if (likely(!blk_should_fake_timeout(req->q)))
|
2017-11-29 16:41:04 +03:00
|
|
|
blk_mq_complete_request(req);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mmc_blk_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq)
|
|
|
|
{
|
|
|
|
mrq->done = mmc_blk_cqe_req_done;
|
|
|
|
mrq->recovery_notifier = mmc_cqe_recovery_notifier;
|
|
|
|
|
|
|
|
return mmc_cqe_start_req(host, mrq);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct mmc_request *mmc_blk_cqe_prep_dcmd(struct mmc_queue_req *mqrq,
|
|
|
|
struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_blk_request *brq = &mqrq->brq;
|
|
|
|
|
|
|
|
memset(brq, 0, sizeof(*brq));
|
|
|
|
|
|
|
|
brq->mrq.cmd = &brq->cmd;
|
|
|
|
brq->mrq.tag = req->tag;
|
|
|
|
|
|
|
|
return &brq->mrq;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mmc_blk_cqe_issue_flush(struct mmc_queue *mq, struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
|
|
|
struct mmc_request *mrq = mmc_blk_cqe_prep_dcmd(mqrq, req);
|
|
|
|
|
|
|
|
mrq->cmd->opcode = MMC_SWITCH;
|
|
|
|
mrq->cmd->arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
|
|
|
(EXT_CSD_FLUSH_CACHE << 16) |
|
|
|
|
(1 << 8) |
|
|
|
|
EXT_CSD_CMD_SET_NORMAL;
|
|
|
|
mrq->cmd->flags = MMC_CMD_AC | MMC_RSP_R1B;
|
|
|
|
|
|
|
|
return mmc_blk_cqe_start_req(mq->card->host, mrq);
|
|
|
|
}
|
|
|
|
|
mmc: Add MMC host software queue support
Now the MMC read/write stack will always wait for previous request is
completed by mmc_blk_rw_wait(), before sending a new request to hardware,
or queue a work to complete request, that will bring context switching
overhead and spend some extra time to poll the card for busy completion
for I/O writes via sending CMD13, especially for high I/O per second
rates, to affect the IO performance.
Thus this patch introduces MMC software queue interface based on the
hardware command queue engine's interfaces, which is similar with the
hardware command queue engine's idea, that can remove the context
switching. Moreover we set the default queue depth as 64 for software
queue, which allows more requests to be prepared, merged and inserted
into IO scheduler to improve performance, but we only allow 2 requests
in flight, that is enough to let the irq handler always trigger the
next request without a context switch, as well as avoiding a long latency.
Moreover the host controller should support HW busy detection for I/O
operations when enabling the host software queue. That means, the host
controller must not complete a data transfer request, until after the
card stops signals busy.
From the fio testing data in cover letter, we can see the software
queue can improve some performance with 4K block size, increasing
about 16% for random read, increasing about 90% for random write,
though no obvious improvement for sequential read and write.
Moreover we can expand the software queue interface to support MMC
packed request or packed command in future.
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Baolin Wang <baolin.wang7@gmail.com>
Link: https://lore.kernel.org/r/4409c1586a9b3ed20d57ad2faf6c262fc3ccb6e2.1581478568.git.baolin.wang7@gmail.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2020-02-12 07:12:56 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:04 +03:00
|
|
|
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);
|
mmc: Add MMC host software queue support
Now the MMC read/write stack will always wait for previous request is
completed by mmc_blk_rw_wait(), before sending a new request to hardware,
or queue a work to complete request, that will bring context switching
overhead and spend some extra time to poll the card for busy completion
for I/O writes via sending CMD13, especially for high I/O per second
rates, to affect the IO performance.
Thus this patch introduces MMC software queue interface based on the
hardware command queue engine's interfaces, which is similar with the
hardware command queue engine's idea, that can remove the context
switching. Moreover we set the default queue depth as 64 for software
queue, which allows more requests to be prepared, merged and inserted
into IO scheduler to improve performance, but we only allow 2 requests
in flight, that is enough to let the irq handler always trigger the
next request without a context switch, as well as avoiding a long latency.
Moreover the host controller should support HW busy detection for I/O
operations when enabling the host software queue. That means, the host
controller must not complete a data transfer request, until after the
card stops signals busy.
From the fio testing data in cover letter, we can see the software
queue can improve some performance with 4K block size, increasing
about 16% for random read, increasing about 90% for random write,
though no obvious improvement for sequential read and write.
Moreover we can expand the software queue interface to support MMC
packed request or packed command in future.
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Baolin Wang <baolin.wang7@gmail.com>
Link: https://lore.kernel.org/r/4409c1586a9b3ed20d57ad2faf6c262fc3ccb6e2.1581478568.git.baolin.wang7@gmail.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2020-02-12 07:12:56 +03:00
|
|
|
struct mmc_host *host = mq->card->host;
|
|
|
|
|
|
|
|
if (host->hsq_enabled)
|
|
|
|
return mmc_blk_hsq_issue_rw_rq(mq, req);
|
2017-11-29 16:41:04 +03:00
|
|
|
|
|
|
|
mmc_blk_data_prep(mq, mqrq, 0, NULL, NULL);
|
|
|
|
|
|
|
|
return mmc_blk_cqe_start_req(mq->card->host, &mqrq->brq.mrq);
|
|
|
|
}
|
|
|
|
|
2017-03-13 15:36:41 +03:00
|
|
|
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
|
|
|
|
struct mmc_card *card,
|
|
|
|
int disable_multi,
|
|
|
|
struct mmc_queue *mq)
|
|
|
|
{
|
|
|
|
u32 readcmd, writecmd;
|
|
|
|
struct mmc_blk_request *brq = &mqrq->brq;
|
2017-05-19 16:37:27 +03:00
|
|
|
struct request *req = mmc_queue_req_to_req(mqrq);
|
2017-03-13 15:36:41 +03:00
|
|
|
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);
|
|
|
|
|
|
|
|
brq->mrq.cmd = &brq->cmd;
|
|
|
|
|
|
|
|
brq->cmd.arg = blk_rq_pos(req);
|
|
|
|
if (!mmc_card_blockaddr(card))
|
|
|
|
brq->cmd.arg <<= 9;
|
|
|
|
brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
|
|
|
|
|
2011-07-01 20:55:29 +04:00
|
|
|
if (brq->data.blocks > 1 || do_rel_wr) {
|
|
|
|
/* SPI multiblock writes terminate using a special
|
|
|
|
* token, not a STOP_TRANSMISSION request.
|
2011-05-24 00:06:36 +04:00
|
|
|
*/
|
2011-07-01 20:55:29 +04:00
|
|
|
if (!mmc_host_is_spi(card->host) ||
|
|
|
|
rq_data_dir(req) == READ)
|
|
|
|
brq->mrq.stop = &brq->stop;
|
|
|
|
readcmd = MMC_READ_MULTIPLE_BLOCK;
|
|
|
|
writecmd = MMC_WRITE_MULTIPLE_BLOCK;
|
|
|
|
} else {
|
|
|
|
brq->mrq.stop = NULL;
|
|
|
|
readcmd = MMC_READ_SINGLE_BLOCK;
|
|
|
|
writecmd = MMC_WRITE_BLOCK;
|
|
|
|
}
|
2017-03-13 15:36:41 +03:00
|
|
|
brq->cmd.opcode = rq_data_dir(req) == READ ? readcmd : writecmd;
|
2011-12-21 11:39:17 +04:00
|
|
|
|
2011-07-01 20:55:29 +04:00
|
|
|
/*
|
|
|
|
* Pre-defined multi-block transfers are preferable to
|
|
|
|
* open ended-ones (and necessary for reliable writes).
|
|
|
|
* However, it is not sufficient to just send CMD23,
|
|
|
|
* and avoid the final CMD12, as on an error condition
|
|
|
|
* CMD12 (stop) needs to be sent anyway. This, coupled
|
|
|
|
* with Auto-CMD23 enhancements provided by some
|
|
|
|
* hosts, means that the complexity of dealing
|
|
|
|
* with this is best left to the host. If CMD23 is
|
|
|
|
* supported by card and host, we'll fill sbc in and let
|
|
|
|
* the host deal with handling it correctly. This means
|
|
|
|
* that for hosts that don't expose MMC_CAP_CMD23, no
|
|
|
|
* change of behavior will be observed.
|
|
|
|
*
|
|
|
|
* N.B: Some MMC cards experience perf degradation.
|
|
|
|
* We'll avoid using CMD23-bounded multiblock writes for
|
|
|
|
* these, while retaining features like reliable writes.
|
|
|
|
*/
|
2011-12-21 11:39:17 +04:00
|
|
|
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)) {
|
2011-07-01 20:55:29 +04:00
|
|
|
brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
|
|
|
|
brq->sbc.arg = brq->data.blocks |
|
2011-12-21 11:39:17 +04:00
|
|
|
(do_rel_wr ? (1 << 31) : 0) |
|
|
|
|
(do_data_tag ? (1 << 29) : 0);
|
2011-07-01 20:55:29 +04:00
|
|
|
brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
|
|
|
brq->mrq.sbc = &brq->sbc;
|
|
|
|
}
|
|
|
|
}
|
2008-12-31 20:21:17 +03:00
|
|
|
|
2017-11-29 16:41:03 +03:00
|
|
|
#define MMC_MAX_RETRIES 5
|
2017-11-29 16:41:15 +03:00
|
|
|
#define MMC_DATA_RETRIES 2
|
2017-11-29 16:41:03 +03:00
|
|
|
#define MMC_NO_RETRIES (MMC_MAX_RETRIES + 1)
|
|
|
|
|
2017-11-29 16:41:15 +03:00
|
|
|
static int mmc_blk_send_stop(struct mmc_card *card, unsigned int timeout)
|
|
|
|
{
|
|
|
|
struct mmc_command cmd = {
|
|
|
|
.opcode = MMC_STOP_TRANSMISSION,
|
|
|
|
.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC,
|
|
|
|
/* Some hosts wait for busy anyway, so provide a busy timeout */
|
|
|
|
.busy_timeout = timeout,
|
|
|
|
};
|
|
|
|
|
|
|
|
return mmc_wait_for_cmd(card->host, &cmd, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mmc_blk_fix_state(struct mmc_card *card, struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
|
|
|
struct mmc_blk_request *brq = &mqrq->brq;
|
|
|
|
unsigned int timeout = mmc_blk_data_timeout_ms(card->host, &brq->data);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
mmc_retune_hold_now(card->host);
|
|
|
|
|
|
|
|
mmc_blk_send_stop(card, timeout);
|
|
|
|
|
2019-09-05 10:53:17 +03:00
|
|
|
err = card_busy_detect(card, timeout, NULL);
|
2017-11-29 16:41:15 +03:00
|
|
|
|
|
|
|
mmc_retune_release(card->host);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:03 +03:00
|
|
|
#define MMC_READ_SINGLE_RETRIES 2
|
|
|
|
|
|
|
|
/* Single 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);
|
|
|
|
struct mmc_request *mrq = &mqrq->brq.mrq;
|
|
|
|
struct mmc_card *card = mq->card;
|
|
|
|
struct mmc_host *host = card->host;
|
|
|
|
blk_status_t error = BLK_STS_OK;
|
|
|
|
int retries = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
u32 status;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
mmc_blk_rw_rq_prep(mqrq, card, 1, mq);
|
|
|
|
|
|
|
|
mmc_wait_for_req(host, mrq);
|
|
|
|
|
|
|
|
err = mmc_send_status(card, &status);
|
|
|
|
if (err)
|
|
|
|
goto error_exit;
|
|
|
|
|
|
|
|
if (!mmc_host_is_spi(host) &&
|
2020-02-04 11:54:43 +03:00
|
|
|
!mmc_ready_for_data(status)) {
|
2017-11-29 16:41:15 +03:00
|
|
|
err = mmc_blk_fix_state(card, req);
|
2017-11-29 16:41:03 +03:00
|
|
|
if (err)
|
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mrq->cmd->error && retries++ < MMC_READ_SINGLE_RETRIES)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
retries = 0;
|
|
|
|
|
|
|
|
if (mrq->cmd->error ||
|
|
|
|
mrq->data->error ||
|
|
|
|
(!mmc_host_is_spi(host) &&
|
|
|
|
(mrq->cmd->resp[0] & CMD_ERRORS || status & CMD_ERRORS)))
|
|
|
|
error = BLK_STS_IOERR;
|
|
|
|
else
|
|
|
|
error = BLK_STS_OK;
|
|
|
|
|
|
|
|
} while (blk_update_request(req, error, 512));
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
error_exit:
|
|
|
|
mrq->data->bytes_xfered = 0;
|
|
|
|
blk_update_request(req, BLK_STS_IOERR, 512);
|
|
|
|
/* Let it try the remaining request again */
|
|
|
|
if (mqrq->retries > MMC_MAX_RETRIES - 1)
|
|
|
|
mqrq->retries = MMC_MAX_RETRIES - 1;
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:15 +03:00
|
|
|
static inline bool mmc_blk_oor_valid(struct mmc_blk_request *brq)
|
|
|
|
{
|
|
|
|
return !!brq->mrq.sbc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline u32 mmc_blk_stop_err_bits(struct mmc_blk_request *brq)
|
|
|
|
{
|
|
|
|
return mmc_blk_oor_valid(brq) ? CMD_ERRORS : CMD_ERRORS_EXCL_OOR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for errors the host controller driver might not have seen such as
|
|
|
|
* response mode errors or invalid card state.
|
|
|
|
*/
|
|
|
|
static bool mmc_blk_status_error(struct request *req, u32 status)
|
|
|
|
{
|
|
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
|
|
|
struct mmc_blk_request *brq = &mqrq->brq;
|
|
|
|
struct mmc_queue *mq = req->q->queuedata;
|
|
|
|
u32 stop_err_bits;
|
|
|
|
|
|
|
|
if (mmc_host_is_spi(mq->card->host))
|
2017-11-30 00:54:24 +03:00
|
|
|
return false;
|
2017-11-29 16:41:15 +03:00
|
|
|
|
|
|
|
stop_err_bits = mmc_blk_stop_err_bits(brq);
|
|
|
|
|
|
|
|
return brq->cmd.resp[0] & CMD_ERRORS ||
|
|
|
|
brq->stop.resp[0] & stop_err_bits ||
|
|
|
|
status & stop_err_bits ||
|
2020-02-04 11:54:43 +03:00
|
|
|
(rq_data_dir(req) == WRITE && !mmc_ready_for_data(status));
|
2017-11-29 16:41:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool mmc_blk_cmd_started(struct mmc_blk_request *brq)
|
|
|
|
{
|
|
|
|
return !brq->sbc.error && !brq->cmd.error &&
|
|
|
|
!(brq->cmd.resp[0] & CMD_ERRORS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Requests are completed by mmc_blk_mq_complete_rq() which sets simple
|
|
|
|
* policy:
|
|
|
|
* 1. A request that has transferred at least some data is considered
|
|
|
|
* successful and will be requeued if there is remaining data to
|
|
|
|
* transfer.
|
|
|
|
* 2. Otherwise the number of retries is incremented and the request
|
|
|
|
* will be requeued if there are remaining retries.
|
|
|
|
* 3. Otherwise the request will be errored out.
|
|
|
|
* That means mmc_blk_mq_complete_rq() is controlled by bytes_xfered and
|
|
|
|
* mqrq->retries. So there are only 4 possible actions here:
|
|
|
|
* 1. do not accept the bytes_xfered value i.e. set it to zero
|
|
|
|
* 2. change mqrq->retries to determine the number of retries
|
|
|
|
* 3. try to reset the card
|
|
|
|
* 4. read one sector at a time
|
|
|
|
*/
|
2017-11-29 16:41:03 +03:00
|
|
|
static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req)
|
|
|
|
{
|
|
|
|
int type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
|
|
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
|
|
|
struct mmc_blk_request *brq = &mqrq->brq;
|
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
|
|
|
struct mmc_card *card = mq->card;
|
2017-11-29 16:41:15 +03:00
|
|
|
u32 status;
|
|
|
|
u32 blocks;
|
|
|
|
int err;
|
2017-11-29 16:41:03 +03:00
|
|
|
|
2017-11-29 16:41:15 +03:00
|
|
|
/*
|
|
|
|
* Some errors the host driver might not have seen. Set the number of
|
|
|
|
* bytes transferred to zero in that case.
|
|
|
|
*/
|
|
|
|
err = __mmc_send_status(card, &status, 0);
|
|
|
|
if (err || mmc_blk_status_error(req, status))
|
|
|
|
brq->data.bytes_xfered = 0;
|
2017-11-29 16:41:03 +03:00
|
|
|
|
|
|
|
mmc_retune_release(card->host);
|
|
|
|
|
|
|
|
/*
|
2017-11-29 16:41:15 +03:00
|
|
|
* Try again to get the status. This also provides an opportunity for
|
|
|
|
* re-tuning.
|
2017-11-29 16:41:03 +03:00
|
|
|
*/
|
2017-11-29 16:41:15 +03:00
|
|
|
if (err)
|
|
|
|
err = __mmc_send_status(card, &status, 0);
|
2017-11-29 16:41:03 +03:00
|
|
|
|
2017-11-29 16:41:15 +03:00
|
|
|
/*
|
|
|
|
* Nothing more to do after the number of bytes transferred has been
|
|
|
|
* updated and there is no card.
|
|
|
|
*/
|
|
|
|
if (err && mmc_detect_card_removed(card->host))
|
|
|
|
return;
|
2017-11-29 16:41:03 +03:00
|
|
|
|
2017-11-29 16:41:15 +03:00
|
|
|
/* Try to get back to "tran" state */
|
|
|
|
if (!mmc_host_is_spi(mq->card->host) &&
|
2020-02-04 11:54:43 +03:00
|
|
|
(err || !mmc_ready_for_data(status)))
|
2017-11-29 16:41:15 +03:00
|
|
|
err = mmc_blk_fix_state(mq->card, req);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Special case for SD cards where the card might record the number of
|
|
|
|
* blocks written.
|
|
|
|
*/
|
|
|
|
if (!err && mmc_blk_cmd_started(brq) && mmc_card_sd(card) &&
|
|
|
|
rq_data_dir(req) == WRITE) {
|
|
|
|
if (mmc_sd_num_wr_blocks(card, &blocks))
|
|
|
|
brq->data.bytes_xfered = 0;
|
|
|
|
else
|
|
|
|
brq->data.bytes_xfered = blocks << 9;
|
2017-11-29 16:41:03 +03:00
|
|
|
}
|
2017-11-29 16:41:15 +03:00
|
|
|
|
|
|
|
/* 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);
|
2017-11-29 16:41:03 +03:00
|
|
|
mqrq->retries = MMC_NO_RETRIES;
|
2017-11-29 16:41:15 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If anything was done, just return and if there is anything remaining
|
|
|
|
* on the request it will get requeued.
|
|
|
|
*/
|
|
|
|
if (brq->data.bytes_xfered)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Reset before last retry */
|
|
|
|
if (mqrq->retries + 1 == MMC_MAX_RETRIES)
|
|
|
|
mmc_blk_reset(md, card->host, type);
|
|
|
|
|
|
|
|
/* Command errors fail fast, so use all MMC_MAX_RETRIES */
|
|
|
|
if (brq->sbc.error || brq->cmd.error)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Reduce the remaining retries for data errors */
|
|
|
|
if (mqrq->retries < MMC_MAX_RETRIES - MMC_DATA_RETRIES) {
|
|
|
|
mqrq->retries = MMC_MAX_RETRIES - MMC_DATA_RETRIES;
|
|
|
|
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 */
|
|
|
|
mmc_blk_read_single(mq, req);
|
|
|
|
return;
|
2017-11-29 16:41:03 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:07 +03:00
|
|
|
static inline bool mmc_blk_rq_error(struct mmc_blk_request *brq)
|
|
|
|
{
|
|
|
|
mmc_blk_eval_resp_error(brq);
|
|
|
|
|
|
|
|
return brq->sbc.error || brq->cmd.error || brq->stop.error ||
|
|
|
|
brq->data.error || brq->cmd.resp[0] & CMD_ERRORS;
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:08 +03:00
|
|
|
static int mmc_blk_card_busy(struct mmc_card *card, struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
2017-11-29 16:41:10 +03:00
|
|
|
u32 status = 0;
|
2017-11-29 16:41:08 +03:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
|
|
|
|
return 0;
|
|
|
|
|
2019-09-05 10:53:17 +03:00
|
|
|
err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status);
|
2017-11-29 16:41:08 +03:00
|
|
|
|
2017-11-29 16:41:10 +03:00
|
|
|
/*
|
|
|
|
* Do not assume data transferred correctly if there are any error bits
|
|
|
|
* set.
|
|
|
|
*/
|
|
|
|
if (status & mmc_blk_stop_err_bits(&mqrq->brq)) {
|
|
|
|
mqrq->brq.data.bytes_xfered = 0;
|
2017-11-29 16:41:08 +03:00
|
|
|
err = err ? err : -EIO;
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:10 +03:00
|
|
|
/* Copy the exception bit so it will be seen later on */
|
|
|
|
if (mmc_card_mmc(card) && status & R1_EXCEPTION_EVENT)
|
|
|
|
mqrq->brq.cmd.resp[0] |= R1_EXCEPTION_EVENT;
|
|
|
|
|
2017-11-29 16:41:08 +03:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:07 +03:00
|
|
|
static inline void mmc_blk_rw_reset_success(struct mmc_queue *mq,
|
|
|
|
struct request *req)
|
|
|
|
{
|
|
|
|
int type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
|
|
|
|
|
|
|
|
mmc_blk_reset_success(mq->blkdata, type);
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:03 +03:00
|
|
|
static void mmc_blk_mq_complete_rq(struct mmc_queue *mq, struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
|
|
|
unsigned int nr_bytes = mqrq->brq.data.bytes_xfered;
|
|
|
|
|
|
|
|
if (nr_bytes) {
|
|
|
|
if (blk_update_request(req, BLK_STS_OK, nr_bytes))
|
|
|
|
blk_mq_requeue_request(req, true);
|
|
|
|
else
|
|
|
|
__blk_mq_end_request(req, BLK_STS_OK);
|
|
|
|
} else if (!blk_rq_bytes(req)) {
|
|
|
|
__blk_mq_end_request(req, BLK_STS_IOERR);
|
|
|
|
} else if (mqrq->retries++ < MMC_MAX_RETRIES) {
|
|
|
|
blk_mq_requeue_request(req, true);
|
|
|
|
} else {
|
|
|
|
if (mmc_card_removed(mq->card))
|
|
|
|
req->rq_flags |= RQF_QUIET;
|
|
|
|
blk_mq_end_request(req, BLK_STS_IOERR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool mmc_blk_urgent_bkops_needed(struct mmc_queue *mq,
|
|
|
|
struct mmc_queue_req *mqrq)
|
|
|
|
{
|
|
|
|
return mmc_card_mmc(mq->card) && !mmc_host_is_spi(mq->card->host) &&
|
|
|
|
(mqrq->brq.cmd.resp[0] & R1_EXCEPTION_EVENT ||
|
|
|
|
mqrq->brq.stop.resp[0] & R1_EXCEPTION_EVENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_urgent_bkops(struct mmc_queue *mq,
|
|
|
|
struct mmc_queue_req *mqrq)
|
|
|
|
{
|
|
|
|
if (mmc_blk_urgent_bkops_needed(mq, mqrq))
|
2018-12-10 19:52:40 +03:00
|
|
|
mmc_run_bkops(mq->card);
|
2017-11-29 16:41:03 +03:00
|
|
|
}
|
|
|
|
|
mmc: Add MMC host software queue support
Now the MMC read/write stack will always wait for previous request is
completed by mmc_blk_rw_wait(), before sending a new request to hardware,
or queue a work to complete request, that will bring context switching
overhead and spend some extra time to poll the card for busy completion
for I/O writes via sending CMD13, especially for high I/O per second
rates, to affect the IO performance.
Thus this patch introduces MMC software queue interface based on the
hardware command queue engine's interfaces, which is similar with the
hardware command queue engine's idea, that can remove the context
switching. Moreover we set the default queue depth as 64 for software
queue, which allows more requests to be prepared, merged and inserted
into IO scheduler to improve performance, but we only allow 2 requests
in flight, that is enough to let the irq handler always trigger the
next request without a context switch, as well as avoiding a long latency.
Moreover the host controller should support HW busy detection for I/O
operations when enabling the host software queue. That means, the host
controller must not complete a data transfer request, until after the
card stops signals busy.
From the fio testing data in cover letter, we can see the software
queue can improve some performance with 4K block size, increasing
about 16% for random read, increasing about 90% for random write,
though no obvious improvement for sequential read and write.
Moreover we can expand the software queue interface to support MMC
packed request or packed command in future.
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Baolin Wang <baolin.wang7@gmail.com>
Link: https://lore.kernel.org/r/4409c1586a9b3ed20d57ad2faf6c262fc3ccb6e2.1581478568.git.baolin.wang7@gmail.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2020-02-12 07:12:56 +03:00
|
|
|
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);
|
2020-06-11 09:44:47 +03:00
|
|
|
else if (likely(!blk_should_fake_timeout(req->q)))
|
mmc: Add MMC host software queue support
Now the MMC read/write stack will always wait for previous request is
completed by mmc_blk_rw_wait(), before sending a new request to hardware,
or queue a work to complete request, that will bring context switching
overhead and spend some extra time to poll the card for busy completion
for I/O writes via sending CMD13, especially for high I/O per second
rates, to affect the IO performance.
Thus this patch introduces MMC software queue interface based on the
hardware command queue engine's interfaces, which is similar with the
hardware command queue engine's idea, that can remove the context
switching. Moreover we set the default queue depth as 64 for software
queue, which allows more requests to be prepared, merged and inserted
into IO scheduler to improve performance, but we only allow 2 requests
in flight, that is enough to let the irq handler always trigger the
next request without a context switch, as well as avoiding a long latency.
Moreover the host controller should support HW busy detection for I/O
operations when enabling the host software queue. That means, the host
controller must not complete a data transfer request, until after the
card stops signals busy.
From the fio testing data in cover letter, we can see the software
queue can improve some performance with 4K block size, increasing
about 16% for random read, increasing about 90% for random write,
though no obvious improvement for sequential read and write.
Moreover we can expand the software queue interface to support MMC
packed request or packed command in future.
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Baolin Wang <baolin.wang7@gmail.com>
Link: https://lore.kernel.org/r/4409c1586a9b3ed20d57ad2faf6c262fc3ccb6e2.1581478568.git.baolin.wang7@gmail.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2020-02-12 07:12:56 +03:00
|
|
|
blk_mq_complete_request(req);
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:03 +03:00
|
|
|
void mmc_blk_mq_complete(struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_queue *mq = req->q->queuedata;
|
|
|
|
|
2017-11-29 16:41:04 +03:00
|
|
|
if (mq->use_cqe)
|
|
|
|
mmc_blk_cqe_complete_rq(mq, req);
|
2020-06-11 09:44:47 +03:00
|
|
|
else if (likely(!blk_should_fake_timeout(req->q)))
|
2017-11-29 16:41:04 +03:00
|
|
|
mmc_blk_mq_complete_rq(mq, req);
|
2017-11-29 16:41:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_mq_poll_completion(struct mmc_queue *mq,
|
|
|
|
struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
2017-11-29 16:41:08 +03:00
|
|
|
struct mmc_host *host = mq->card->host;
|
2017-11-29 16:41:03 +03:00
|
|
|
|
2017-11-29 16:41:08 +03:00
|
|
|
if (mmc_blk_rq_error(&mqrq->brq) ||
|
|
|
|
mmc_blk_card_busy(mq->card, req)) {
|
|
|
|
mmc_blk_mq_rw_recovery(mq, req);
|
|
|
|
} else {
|
|
|
|
mmc_blk_rw_reset_success(mq, req);
|
|
|
|
mmc_retune_release(host);
|
|
|
|
}
|
2017-11-29 16:41:03 +03:00
|
|
|
|
|
|
|
mmc_blk_urgent_bkops(mq, mqrq);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
bool put_card;
|
|
|
|
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 16:41:03 +03:00
|
|
|
|
|
|
|
mq->in_flight[mmc_issue_type(mq, req)] -= 1;
|
|
|
|
|
|
|
|
put_card = (mmc_tot_in_flight(mq) == 0);
|
|
|
|
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 16:41:03 +03:00
|
|
|
|
|
|
|
if (put_card)
|
|
|
|
mmc_put_card(mq->card, &mq->ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *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;
|
|
|
|
|
|
|
|
mmc_post_req(host, mrq, 0);
|
|
|
|
|
2017-11-29 16:41:07 +03:00
|
|
|
/*
|
|
|
|
* Block layer timeouts race with completions which means the normal
|
|
|
|
* completion path cannot be used during recovery.
|
|
|
|
*/
|
|
|
|
if (mq->in_recovery)
|
|
|
|
mmc_blk_mq_complete_rq(mq, req);
|
2020-06-11 09:44:47 +03:00
|
|
|
else if (likely(!blk_should_fake_timeout(req->q)))
|
2017-11-29 16:41:07 +03:00
|
|
|
blk_mq_complete_request(req);
|
2017-11-29 16:41:03 +03:00
|
|
|
|
|
|
|
mmc_blk_mq_dec_in_flight(mq, req);
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:07 +03:00
|
|
|
void mmc_blk_mq_recovery(struct mmc_queue *mq)
|
|
|
|
{
|
|
|
|
struct request *req = mq->recovery_req;
|
|
|
|
struct mmc_host *host = mq->card->host;
|
|
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
|
|
|
|
|
|
|
mq->recovery_req = NULL;
|
|
|
|
mq->rw_wait = false;
|
|
|
|
|
|
|
|
if (mmc_blk_rq_error(&mqrq->brq)) {
|
|
|
|
mmc_retune_hold_now(host);
|
|
|
|
mmc_blk_mq_rw_recovery(mq, req);
|
|
|
|
}
|
|
|
|
|
|
|
|
mmc_blk_urgent_bkops(mq, mqrq);
|
|
|
|
|
|
|
|
mmc_blk_mq_post_req(mq, req);
|
|
|
|
}
|
|
|
|
|
2017-11-29 16:41:03 +03:00
|
|
|
static void mmc_blk_mq_complete_prev_req(struct mmc_queue *mq,
|
|
|
|
struct request **prev_req)
|
|
|
|
{
|
2017-11-29 16:41:07 +03:00
|
|
|
if (mmc_host_done_complete(mq->card->host))
|
|
|
|
return;
|
|
|
|
|
2017-11-29 16:41:03 +03:00
|
|
|
mutex_lock(&mq->complete_lock);
|
|
|
|
|
|
|
|
if (!mq->complete_req)
|
|
|
|
goto out_unlock;
|
|
|
|
|
|
|
|
mmc_blk_mq_poll_completion(mq, mq->complete_req);
|
|
|
|
|
|
|
|
if (prev_req)
|
|
|
|
*prev_req = mq->complete_req;
|
|
|
|
else
|
|
|
|
mmc_blk_mq_post_req(mq, mq->complete_req);
|
|
|
|
|
|
|
|
mq->complete_req = NULL;
|
|
|
|
|
|
|
|
out_unlock:
|
|
|
|
mutex_unlock(&mq->complete_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mmc_blk_mq_complete_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct mmc_queue *mq = container_of(work, struct mmc_queue,
|
|
|
|
complete_work);
|
|
|
|
|
|
|
|
mmc_blk_mq_complete_prev_req(mq, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_mq_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;
|
2017-11-29 16:41:07 +03:00
|
|
|
struct mmc_host *host = mq->card->host;
|
2017-11-29 16:41:03 +03:00
|
|
|
unsigned long flags;
|
|
|
|
|
2017-11-29 16:41:07 +03:00
|
|
|
if (!mmc_host_done_complete(host)) {
|
|
|
|
bool waiting;
|
2017-11-29 16:41:03 +03:00
|
|
|
|
2017-11-29 16:41:07 +03:00
|
|
|
/*
|
|
|
|
* We cannot complete the request in this context, so record
|
|
|
|
* that there is a request to complete, and that a following
|
|
|
|
* request does not need to wait (although it does need to
|
|
|
|
* complete complete_req first).
|
|
|
|
*/
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 16:41:07 +03:00
|
|
|
mq->complete_req = req;
|
|
|
|
mq->rw_wait = false;
|
|
|
|
waiting = mq->waiting;
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 16:41:07 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If 'waiting' then the waiting task will complete this
|
|
|
|
* request, otherwise queue a work to do it. Note that
|
|
|
|
* complete_work may still race with the dispatch of a following
|
|
|
|
* request.
|
|
|
|
*/
|
|
|
|
if (waiting)
|
|
|
|
wake_up(&mq->wait);
|
|
|
|
else
|
2019-02-07 18:03:08 +03:00
|
|
|
queue_work(mq->card->complete_wq, &mq->complete_work);
|
2017-11-29 16:41:07 +03:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Take the recovery path for errors or urgent background operations */
|
|
|
|
if (mmc_blk_rq_error(&mqrq->brq) ||
|
|
|
|
mmc_blk_urgent_bkops_needed(mq, mqrq)) {
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 16:41:07 +03:00
|
|
|
mq->recovery_needed = true;
|
|
|
|
mq->recovery_req = req;
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 16:41:03 +03:00
|
|
|
wake_up(&mq->wait);
|
2017-11-29 16:41:07 +03:00
|
|
|
schedule_work(&mq->recovery_work);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mmc_blk_rw_reset_success(mq, req);
|
|
|
|
|
|
|
|
mq->rw_wait = false;
|
|
|
|
wake_up(&mq->wait);
|
|
|
|
|
|
|
|
mmc_blk_mq_post_req(mq, req);
|
2017-11-29 16:41:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool mmc_blk_rw_wait_cond(struct mmc_queue *mq, int *err)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
bool done;
|
|
|
|
|
|
|
|
/*
|
2017-11-29 16:41:07 +03:00
|
|
|
* Wait while there is another request in progress, but not if recovery
|
|
|
|
* is needed. Also indicate whether there is a request waiting to start.
|
2017-11-29 16:41:03 +03:00
|
|
|
*/
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 16:41:07 +03:00
|
|
|
if (mq->recovery_needed) {
|
|
|
|
*err = -EBUSY;
|
|
|
|
done = true;
|
|
|
|
} else {
|
|
|
|
done = !mq->rw_wait;
|
|
|
|
}
|
2017-11-29 16:41:03 +03:00
|
|
|
mq->waiting = !done;
|
2018-11-16 11:10:06 +03:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 16:41:03 +03:00
|
|
|
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mmc_blk_rw_wait(struct mmc_queue *mq, struct request **prev_req)
|
|
|
|
{
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
wait_event(mq->wait, mmc_blk_rw_wait_cond(mq, &err));
|
|
|
|
|
|
|
|
/* Always complete the previous request if there is one */
|
|
|
|
mmc_blk_mq_complete_prev_req(mq, prev_req);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mmc_blk_mq_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;
|
|
|
|
struct request *prev_req = NULL;
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
mmc_blk_rw_rq_prep(mqrq, mq->card, 0, mq);
|
|
|
|
|
|
|
|
mqrq->brq.mrq.done = mmc_blk_mq_req_done;
|
|
|
|
|
|
|
|
mmc_pre_req(host, &mqrq->brq.mrq);
|
|
|
|
|
|
|
|
err = mmc_blk_rw_wait(mq, &prev_req);
|
|
|
|
if (err)
|
|
|
|
goto out_post_req;
|
|
|
|
|
|
|
|
mq->rw_wait = true;
|
|
|
|
|
|
|
|
err = mmc_start_request(host, &mqrq->brq.mrq);
|
|
|
|
|
|
|
|
if (prev_req)
|
|
|
|
mmc_blk_mq_post_req(mq, prev_req);
|
|
|
|
|
2017-11-29 16:41:07 +03:00
|
|
|
if (err)
|
2017-11-29 16:41:03 +03:00
|
|
|
mq->rw_wait = false;
|
2017-11-29 16:41:07 +03:00
|
|
|
|
|
|
|
/* Release re-tuning here where there is no synchronization required */
|
|
|
|
if (err || mmc_host_done_complete(host))
|
2017-11-29 16:41:03 +03:00
|
|
|
mmc_retune_release(host);
|
|
|
|
|
|
|
|
out_post_req:
|
|
|
|
if (err)
|
|
|
|
mmc_post_req(host, &mqrq->brq.mrq, err);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mmc_blk_wait_for_idle(struct mmc_queue *mq, struct mmc_host *host)
|
|
|
|
{
|
2017-11-29 16:41:04 +03:00
|
|
|
if (mq->use_cqe)
|
|
|
|
return host->cqe_ops->cqe_wait_for_idle(host);
|
|
|
|
|
2017-11-29 16:41:03 +03:00
|
|
|
return mmc_blk_rw_wait(mq, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
|
|
|
struct mmc_card *card = md->queue.card;
|
|
|
|
struct mmc_host *host = card->host;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = mmc_blk_part_switch(card, md->part_type);
|
|
|
|
if (ret)
|
|
|
|
return MMC_REQ_FAILED_TO_START;
|
|
|
|
|
|
|
|
switch (mmc_issue_type(mq, req)) {
|
|
|
|
case MMC_ISSUE_SYNC:
|
|
|
|
ret = mmc_blk_wait_for_idle(mq, host);
|
|
|
|
if (ret)
|
|
|
|
return MMC_REQ_BUSY;
|
|
|
|
switch (req_op(req)) {
|
|
|
|
case REQ_OP_DRV_IN:
|
|
|
|
case REQ_OP_DRV_OUT:
|
|
|
|
mmc_blk_issue_drv_op(mq, req);
|
|
|
|
break;
|
|
|
|
case REQ_OP_DISCARD:
|
|
|
|
mmc_blk_issue_discard_rq(mq, req);
|
|
|
|
break;
|
|
|
|
case REQ_OP_SECURE_ERASE:
|
|
|
|
mmc_blk_issue_secdiscard_rq(mq, req);
|
|
|
|
break;
|
|
|
|
case REQ_OP_FLUSH:
|
|
|
|
mmc_blk_issue_flush(mq, req);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
return MMC_REQ_FAILED_TO_START;
|
|
|
|
}
|
|
|
|
return MMC_REQ_FINISHED;
|
2017-11-29 16:41:04 +03:00
|
|
|
case MMC_ISSUE_DCMD:
|
2017-11-29 16:41:03 +03:00
|
|
|
case MMC_ISSUE_ASYNC:
|
|
|
|
switch (req_op(req)) {
|
2017-11-29 16:41:04 +03:00
|
|
|
case REQ_OP_FLUSH:
|
|
|
|
ret = mmc_blk_cqe_issue_flush(mq, req);
|
|
|
|
break;
|
2017-11-29 16:41:03 +03:00
|
|
|
case REQ_OP_READ:
|
|
|
|
case REQ_OP_WRITE:
|
2017-11-29 16:41:04 +03:00
|
|
|
if (mq->use_cqe)
|
|
|
|
ret = mmc_blk_cqe_issue_rw_rq(mq, req);
|
|
|
|
else
|
|
|
|
ret = mmc_blk_mq_issue_rw_rq(mq, req);
|
2017-11-29 16:41:03 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
|
|
|
if (!ret)
|
|
|
|
return MMC_REQ_STARTED;
|
|
|
|
return ret == -EBUSY ? MMC_REQ_BUSY : MMC_REQ_FAILED_TO_START;
|
|
|
|
default:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
return MMC_REQ_FAILED_TO_START;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-04 01:38:44 +03:00
|
|
|
static inline int mmc_blk_readonly(struct mmc_card *card)
|
|
|
|
{
|
|
|
|
return mmc_card_readonly(card) ||
|
|
|
|
!(card->csd.cmdclass & CCC_BLOCK_WRITE);
|
|
|
|
}
|
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
|
|
|
|
struct device *parent,
|
|
|
|
sector_t size,
|
|
|
|
bool default_ro,
|
2011-12-02 11:51:06 +04:00
|
|
|
const char *subname,
|
|
|
|
int area_type)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
|
|
|
struct mmc_blk_data *md;
|
|
|
|
int devidx, ret;
|
|
|
|
|
2017-02-01 21:44:22 +03:00
|
|
|
devidx = ida_simple_get(&mmc_blk_ida, 0, max_devices, GFP_KERNEL);
|
2017-08-23 10:38:31 +03:00
|
|
|
if (devidx < 0) {
|
|
|
|
/*
|
|
|
|
* We get -ENOSPC because there are no more any available
|
|
|
|
* devidx. The reason may be that, either userspace haven't yet
|
|
|
|
* unmounted the partitions, which postpones mmc_blk_release()
|
|
|
|
* from being called, or the device has more partitions than
|
|
|
|
* what we support.
|
|
|
|
*/
|
|
|
|
if (devidx == -ENOSPC)
|
|
|
|
dev_err(mmc_dev(card->host),
|
|
|
|
"no more device IDs available\n");
|
|
|
|
|
2017-02-01 21:44:22 +03:00
|
|
|
return ERR_PTR(devidx);
|
2017-08-23 10:38:31 +03:00
|
|
|
}
|
2005-04-17 02:20:36 +04:00
|
|
|
|
some kmalloc/memset ->kzalloc (tree wide)
Transform some calls to kmalloc/memset to a single kzalloc (or kcalloc).
Here is a short excerpt of the semantic patch performing
this transformation:
@@
type T2;
expression x;
identifier f,fld;
expression E;
expression E1,E2;
expression e1,e2,e3,y;
statement S;
@@
x =
- kmalloc
+ kzalloc
(E1,E2)
... when != \(x->fld=E;\|y=f(...,x,...);\|f(...,x,...);\|x=E;\|while(...) S\|for(e1;e2;e3) S\)
- memset((T2)x,0,E1);
@@
expression E1,E2,E3;
@@
- kzalloc(E1 * E2,E3)
+ kcalloc(E1,E2,E3)
[akpm@linux-foundation.org: get kcalloc args the right way around]
Signed-off-by: Yoann Padioleau <padator@wanadoo.fr>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Bryan Wu <bryan.wu@analog.com>
Acked-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Dave Airlie <airlied@linux.ie>
Acked-by: Roland Dreier <rolandd@cisco.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Acked-by: Pierre Ossman <drzeus-list@drzeus.cx>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: "David S. Miller" <davem@davemloft.net>
Acked-by: Greg KH <greg@kroah.com>
Cc: James Bottomley <James.Bottomley@steeleye.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-19 12:49:03 +04:00
|
|
|
md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
|
2006-01-04 01:38:44 +03:00
|
|
|
if (!md) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto out;
|
|
|
|
}
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2011-12-02 11:51:06 +04:00
|
|
|
md->area_type = area_type;
|
|
|
|
|
2006-01-04 01:38:44 +03:00
|
|
|
/*
|
|
|
|
* Set the read-only status based on the supported commands
|
|
|
|
* and the write protect switch.
|
|
|
|
*/
|
|
|
|
md->read_only = mmc_blk_readonly(card);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2010-09-18 05:19:57 +04:00
|
|
|
md->disk = alloc_disk(perdev_minors);
|
2006-01-04 01:38:44 +03:00
|
|
|
if (md->disk == NULL) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto err_kfree;
|
|
|
|
}
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
INIT_LIST_HEAD(&md->part);
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
INIT_LIST_HEAD(&md->rpmbs);
|
2006-01-04 01:38:44 +03:00
|
|
|
md->usage = 1;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2018-11-16 11:10:06 +03:00
|
|
|
ret = mmc_init_queue(&md->queue, card);
|
2006-01-04 01:38:44 +03:00
|
|
|
if (ret)
|
|
|
|
goto err_putdisk;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2016-11-18 15:36:15 +03:00
|
|
|
md->queue.blkdata = md;
|
2005-12-23 02:21:38 +03:00
|
|
|
|
2017-11-29 16:40:59 +03:00
|
|
|
/*
|
|
|
|
* 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);
|
2017-12-08 14:55:16 +03:00
|
|
|
ret = -ENODEV;
|
2017-11-29 16:40:59 +03:00
|
|
|
goto err_putdisk;
|
|
|
|
}
|
|
|
|
|
2007-05-14 19:27:29 +04:00
|
|
|
md->disk->major = MMC_BLOCK_MAJOR;
|
2010-09-18 05:19:57 +04:00
|
|
|
md->disk->first_minor = devidx * perdev_minors;
|
2006-01-04 01:38:44 +03:00
|
|
|
md->disk->fops = &mmc_bdops;
|
|
|
|
md->disk->private_data = md;
|
|
|
|
md->disk->queue = md->queue.queue;
|
2016-06-20 20:40:44 +03:00
|
|
|
md->parent = parent;
|
2011-04-12 03:10:25 +04:00
|
|
|
set_disk_ro(md->disk, md->read_only || default_ro);
|
2015-10-22 20:00:41 +03:00
|
|
|
md->disk->flags = GENHD_FL_EXT_DEVT;
|
2014-09-03 13:02:23 +04:00
|
|
|
if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT))
|
2018-02-27 14:33:49 +03:00
|
|
|
md->disk->flags |= GENHD_FL_NO_PART_SCAN
|
|
|
|
| GENHD_FL_SUPPRESS_PARTITION_INFO;
|
2006-01-04 01:38:44 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* As discussed on lkml, GENHD_FL_REMOVABLE should:
|
|
|
|
*
|
|
|
|
* - be set for removable media with permanent block devices
|
|
|
|
* - be unset for removable block devices with permanent media
|
|
|
|
*
|
|
|
|
* Since MMC block devices clearly fall under the second
|
|
|
|
* case, we do not set GENHD_FL_REMOVABLE. Userspace
|
|
|
|
* should use the block device creation/destruction hotplug
|
|
|
|
* messages to tell when the card is present.
|
|
|
|
*/
|
|
|
|
|
2011-04-22 07:46:13 +04:00
|
|
|
snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
|
mmc: block: Use the mmc host device index as the mmcblk device index
Commit 520bd7a8b415 ("mmc: core: Optimize boot time by detecting cards
simultaneously") causes regressions for some platforms.
These platforms relies on fixed mmcblk device indexes, instead of
deploying the defacto standard with UUID/PARTUUID. In other words their
rootfs needs to be available at hardcoded paths, like /dev/mmcblk0p2.
Such guarantees have never been made by the kernel, but clearly the above
commit changes the behaviour. More precisely, because of that the order
changes of how cards becomes detected, so do their corresponding mmcblk
device indexes.
As the above commit significantly improves boot time for some platforms
(magnitude of seconds), let's avoid reverting this change but instead
restore the behaviour of how mmcblk device indexes becomes picked.
By using the same index for the mmcblk device as for the corresponding mmc
host device, the probe order of mmc host devices decides the index we get
for the mmcblk device.
For those platforms that suffers from a regression, one could expect that
this updated behaviour should be sufficient to meet their expectations of
"fixed" mmcblk device indexes.
Another side effect from this change, is that the same index is used for
the mmc host device, the mmcblk device and the mmc block queue. That
should clarify their relationship.
Reported-by: Peter Hurley <peter@hurleysoftware.com>
Reported-by: Laszlo Fiat <laszlo.fiat@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Fixes: 520bd7a8b415 ("mmc: core: Optimize boot time by detecting cards
simultaneously")
Cc: <stable@vger.kernel.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2016-04-06 17:12:08 +03:00
|
|
|
"mmcblk%u%s", card->host->index, subname ? subname : "");
|
2006-01-04 01:38:44 +03:00
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
set_capacity(md->disk, size);
|
2011-05-24 00:06:36 +04:00
|
|
|
|
2011-05-24 00:06:38 +04:00
|
|
|
if (mmc_host_cmd23(card->host)) {
|
2016-08-30 15:17:30 +03:00
|
|
|
if ((mmc_card_mmc(card) &&
|
|
|
|
card->csd.mmca_vsn >= CSD_SPEC_VER_3) ||
|
2011-05-24 00:06:38 +04:00
|
|
|
(mmc_card_sd(card) &&
|
|
|
|
card->scr.cmds & SD_SCR_CMD23_SUPPORT))
|
|
|
|
md->flags |= MMC_BLK_CMD23;
|
|
|
|
}
|
2011-05-24 00:06:36 +04:00
|
|
|
|
|
|
|
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;
|
2016-03-30 19:17:20 +03:00
|
|
|
blk_queue_write_cache(md->queue.queue, true, true);
|
2011-05-24 00:06:36 +04:00
|
|
|
}
|
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
return md;
|
|
|
|
|
|
|
|
err_putdisk:
|
|
|
|
put_disk(md->disk);
|
|
|
|
err_kfree:
|
|
|
|
kfree(md);
|
|
|
|
out:
|
2017-02-01 21:44:22 +03:00
|
|
|
ida_simple_remove(&mmc_blk_ida, devidx);
|
2011-04-12 03:10:25 +04:00
|
|
|
return ERR_PTR(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
|
|
|
|
{
|
|
|
|
sector_t size;
|
2006-01-04 01:38:44 +03:00
|
|
|
|
2007-02-18 00:15:27 +03:00
|
|
|
if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
|
|
|
|
/*
|
|
|
|
* The EXT_CSD sector count is in number or 512 byte
|
|
|
|
* sectors.
|
|
|
|
*/
|
2011-04-12 03:10:25 +04:00
|
|
|
size = card->ext_csd.sectors;
|
2007-02-18 00:15:27 +03:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* The CSD capacity field is in units of read_blkbits.
|
|
|
|
* set_capacity takes units of 512 bytes.
|
|
|
|
*/
|
2015-05-11 10:35:28 +03:00
|
|
|
size = (typeof(sector_t))card->csd.capacity
|
|
|
|
<< (card->csd.read_blkbits - 9);
|
2007-02-18 00:15:27 +03:00
|
|
|
}
|
2011-04-12 03:10:25 +04:00
|
|
|
|
2015-01-21 17:56:44 +03:00
|
|
|
return mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
|
2011-12-02 11:51:06 +04:00
|
|
|
MMC_BLK_DATA_AREA_MAIN);
|
2011-04-12 03:10:25 +04:00
|
|
|
}
|
2006-01-04 01:38:44 +03:00
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
static int mmc_blk_alloc_part(struct mmc_card *card,
|
|
|
|
struct mmc_blk_data *md,
|
|
|
|
unsigned int part_type,
|
|
|
|
sector_t size,
|
|
|
|
bool default_ro,
|
2011-12-02 11:51:06 +04:00
|
|
|
const char *subname,
|
|
|
|
int area_type)
|
2011-04-12 03:10:25 +04:00
|
|
|
{
|
|
|
|
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,
|
2011-12-02 11:51:06 +04:00
|
|
|
subname, area_type);
|
2011-04-12 03:10:25 +04:00
|
|
|
if (IS_ERR(part_md))
|
|
|
|
return PTR_ERR(part_md);
|
|
|
|
part_md->part_type = part_type;
|
|
|
|
list_add(&part_md->part, &md->part);
|
|
|
|
|
sd, mmc, virtio_blk, string_helpers: fix block size units
The current string_get_size() overflows when the device size goes over
2^64 bytes because the string helper routine computes the suffix from
the size in bytes. However, the entirety of Linux thinks in terms of
blocks, not bytes, so this will artificially induce an overflow on very
large devices. Fix this by making the function string_get_size() take
blocks and the block size instead of bytes. This should allow us to
keep working until the current SCSI standard overflows.
Also fix virtio_blk and mmc (both of which were also artificially
multiplying by the block size to pass a byte side to string_get_size()).
The mathematics of this is pretty simple: we're taking a product of
size in blocks (S) and block size (B) and trying to re-express this in
exponential form: S*B = R*N^E (where N, the exponent is either 1000 or
1024) and R < N. Mathematically, S = RS*N^ES and B=RB*N^EB, so if RS*RB
< N it's easy to see that S*B = RS*RB*N^(ES+EB). However, if RS*BS > N,
we can see that this can be re-expressed as RS*BS = R*N (where R =
RS*BS/N < N) so the whole exponent becomes R*N^(ES+EB+1)
[jejb: fix incorrect 32 bit do_div spotted by kbuild test robot <fengguang.wu@intel.com>]
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
2015-03-06 05:47:01 +03:00
|
|
|
string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2,
|
2011-04-12 03:10:25 +04:00
|
|
|
cap_str, sizeof(cap_str));
|
2011-10-11 10:14:09 +04:00
|
|
|
pr_info("%s: %s %s partition %u %s\n",
|
2011-04-12 03:10:25 +04:00
|
|
|
part_md->disk->disk_name, mmc_card_id(card),
|
|
|
|
mmc_card_name(card), part_md->part_type, cap_str);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
/**
|
|
|
|
* mmc_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 mmc_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;
|
|
|
|
}
|
|
|
|
|
2018-05-16 22:20:20 +03:00
|
|
|
return ret;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
static long mmc_rpmb_ioctl_compat(struct file *filp, unsigned int cmd,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
return mmc_rpmb_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int mmc_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;
|
2017-10-04 12:10:07 +03:00
|
|
|
mmc_blk_get(rpmb->md->disk);
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
|
|
|
|
return nonseekable_open(inode, filp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mmc_rpmb_chrdev_release(struct inode *inode, struct file *filp)
|
|
|
|
{
|
|
|
|
struct mmc_rpmb_data *rpmb = container_of(inode->i_cdev,
|
|
|
|
struct mmc_rpmb_data, chrdev);
|
|
|
|
|
2017-10-04 12:10:07 +03:00
|
|
|
mmc_blk_put(rpmb->md);
|
2020-05-22 12:29:25 +03:00
|
|
|
put_device(&rpmb->dev);
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2017-10-04 12:10:07 +03:00
|
|
|
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);
|
|
|
|
kfree(rpmb);
|
|
|
|
}
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
|
|
|
|
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);
|
2017-10-04 12:10:07 +03:00
|
|
|
if (!rpmb) {
|
|
|
|
ida_simple_remove(&mmc_rpmb_ida, devidx);
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
return -ENOMEM;
|
2017-10-04 12:10:07 +03:00
|
|
|
}
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
|
|
|
|
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;
|
2017-10-04 12:10:07 +03:00
|
|
|
rpmb->dev.release = mmc_blk_rpmb_device_release;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
device_initialize(&rpmb->dev);
|
|
|
|
dev_set_drvdata(&rpmb->dev, rpmb);
|
|
|
|
rpmb->md = md;
|
|
|
|
|
|
|
|
cdev_init(&rpmb->chrdev, &mmc_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);
|
2017-10-04 12:10:07 +03:00
|
|
|
goto out_put_device;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2017-10-04 12:10:07 +03:00
|
|
|
out_put_device:
|
|
|
|
put_device(&rpmb->dev);
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_remove_rpmb_part(struct mmc_rpmb_data *rpmb)
|
2017-10-04 12:10:07 +03:00
|
|
|
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
{
|
|
|
|
cdev_device_del(&rpmb->chrdev, &rpmb->dev);
|
2017-10-04 12:10:07 +03:00
|
|
|
put_device(&rpmb->dev);
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
}
|
|
|
|
|
2011-10-06 18:41:38 +04:00
|
|
|
/* 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
|
|
|
|
* to provide access to the partition.
|
|
|
|
*/
|
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
|
|
|
|
{
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
int idx, ret;
|
2011-04-12 03:10:25 +04:00
|
|
|
|
|
|
|
if (!mmc_card_mmc(card))
|
|
|
|
return 0;
|
|
|
|
|
2011-10-06 18:41:38 +04:00
|
|
|
for (idx = 0; idx < card->nr_parts; idx++) {
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
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) {
|
2011-10-06 18:41:38 +04:00
|
|
|
ret = mmc_blk_alloc_part(card, md,
|
|
|
|
card->part[idx].part_cfg,
|
|
|
|
card->part[idx].size >> 9,
|
|
|
|
card->part[idx].force_ro,
|
2011-12-02 11:51:06 +04:00
|
|
|
card->part[idx].name,
|
|
|
|
card->part[idx].area_type);
|
2011-10-06 18:41:38 +04:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
2011-04-12 03:10:25 +04:00
|
|
|
}
|
|
|
|
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
return 0;
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
static void mmc_blk_remove_req(struct mmc_blk_data *md)
|
|
|
|
{
|
2011-12-02 11:51:06 +04:00
|
|
|
struct mmc_card *card;
|
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
if (md) {
|
2013-06-05 01:42:40 +04:00
|
|
|
/*
|
|
|
|
* Flush remaining requests and free queues. It
|
|
|
|
* is freeing the queue that stops new requests
|
|
|
|
* from being accepted.
|
|
|
|
*/
|
2013-07-24 17:17:48 +04:00
|
|
|
card = md->queue.card;
|
2011-04-12 03:10:25 +04:00
|
|
|
if (md->disk->flags & GENHD_FL_UP) {
|
|
|
|
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
|
2011-12-02 11:51:06 +04:00
|
|
|
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);
|
2011-04-12 03:10:25 +04:00
|
|
|
|
|
|
|
del_gendisk(md->disk);
|
|
|
|
}
|
2018-03-22 13:56:16 +03:00
|
|
|
mmc_cleanup_queue(&md->queue);
|
2011-04-12 03:10:25 +04:00
|
|
|
mmc_blk_put(md);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_remove_parts(struct mmc_card *card,
|
|
|
|
struct mmc_blk_data *md)
|
|
|
|
{
|
|
|
|
struct list_head *pos, *q;
|
|
|
|
struct mmc_blk_data *part_md;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
struct mmc_rpmb_data *rpmb;
|
2011-04-12 03:10:25 +04:00
|
|
|
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
/* 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 */
|
2011-04-12 03:10:25 +04:00
|
|
|
list_for_each_safe(pos, q, &md->part) {
|
|
|
|
part_md = list_entry(pos, struct mmc_blk_data, part);
|
|
|
|
list_del(pos);
|
|
|
|
mmc_blk_remove_req(part_md);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mmc_add_disk(struct mmc_blk_data *md)
|
|
|
|
{
|
|
|
|
int ret;
|
2011-12-02 11:51:06 +04:00
|
|
|
struct mmc_card *card = md->queue.card;
|
2011-04-12 03:10:25 +04:00
|
|
|
|
2018-09-28 09:17:19 +03:00
|
|
|
device_add_disk(md->parent, md->disk, NULL);
|
2011-04-12 03:10:25 +04:00
|
|
|
md->force_ro.show = force_ro_show;
|
|
|
|
md->force_ro.store = force_ro_store;
|
2011-04-23 19:22:58 +04:00
|
|
|
sysfs_attr_init(&md->force_ro.attr);
|
2011-04-12 03:10:25 +04:00
|
|
|
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)
|
2011-12-02 11:51:06 +04:00
|
|
|
goto force_ro_fail;
|
|
|
|
|
|
|
|
if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
|
|
|
|
card->ext_csd.boot_ro_lockable) {
|
2012-03-20 14:00:24 +04:00
|
|
|
umode_t mode;
|
2011-12-02 11:51:06 +04:00
|
|
|
|
|
|
|
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;
|
2012-02-01 19:31:56 +04:00
|
|
|
sysfs_attr_init(&md->power_ro_lock.attr);
|
2011-12-02 11:51:06 +04:00
|
|
|
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);
|
2011-04-12 03:10:25 +04:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-08-21 00:39:08 +03:00
|
|
|
#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 */
|
2018-05-09 10:54:05 +03:00
|
|
|
req = blk_get_request(mq->queue, REQ_OP_DRV_IN, 0);
|
2017-11-21 16:42:28 +03:00
|
|
|
if (IS_ERR(req))
|
|
|
|
return PTR_ERR(req);
|
2017-08-21 00:39:08 +03:00
|
|
|
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
|
2021-01-25 07:49:58 +03:00
|
|
|
blk_execute_rq(NULL, req, 0);
|
2017-08-21 00:39:08 +03:00
|
|
|
ret = req_to_mmc_queue_req(req)->drv_op_result;
|
|
|
|
if (ret >= 0) {
|
|
|
|
*val = ret;
|
|
|
|
ret = 0;
|
|
|
|
}
|
2017-11-21 16:42:27 +03:00
|
|
|
blk_put_request(req);
|
2017-08-21 00:39:08 +03:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2018-12-29 04:43:48 +03:00
|
|
|
DEFINE_DEBUGFS_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
|
|
|
|
NULL, "%08llx\n");
|
2017-08-21 00:39:08 +03:00
|
|
|
|
|
|
|
/* 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 */
|
2018-05-09 10:54:05 +03:00
|
|
|
req = blk_get_request(mq->queue, REQ_OP_DRV_IN, 0);
|
2017-11-21 16:42:28 +03:00
|
|
|
if (IS_ERR(req)) {
|
|
|
|
err = PTR_ERR(req);
|
|
|
|
goto out_free;
|
|
|
|
}
|
2017-08-21 00:39:08 +03:00
|
|
|
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;
|
2021-01-25 07:49:58 +03:00
|
|
|
blk_execute_rq(NULL, req, 0);
|
2017-08-21 00:39:08 +03:00
|
|
|
err = req_to_mmc_queue_req(req)->drv_op_result;
|
2017-11-21 16:42:27 +03:00
|
|
|
blk_put_request(req);
|
2017-08-21 00:39:08 +03:00
|
|
|
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;
|
2017-12-16 18:15:45 +03:00
|
|
|
kfree(ext_csd);
|
2017-08-21 00:39:08 +03:00
|
|
|
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,
|
|
|
|
};
|
|
|
|
|
2017-11-21 16:42:30 +03:00
|
|
|
static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
|
2017-08-21 00:39:08 +03:00
|
|
|
{
|
|
|
|
struct dentry *root;
|
|
|
|
|
|
|
|
if (!card->debugfs_root)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
root = card->debugfs_root;
|
|
|
|
|
|
|
|
if (mmc_card_mmc(card) || mmc_card_sd(card)) {
|
2017-11-21 16:42:30 +03:00
|
|
|
md->status_dentry =
|
2018-12-29 04:43:48 +03:00
|
|
|
debugfs_create_file_unsafe("status", 0400, root,
|
|
|
|
card,
|
|
|
|
&mmc_dbg_card_status_fops);
|
2017-11-21 16:42:30 +03:00
|
|
|
if (!md->status_dentry)
|
2017-08-21 00:39:08 +03:00
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mmc_card_mmc(card)) {
|
2017-11-21 16:42:30 +03:00
|
|
|
md->ext_csd_dentry =
|
|
|
|
debugfs_create_file("ext_csd", S_IRUSR, root, card,
|
|
|
|
&mmc_dbg_ext_csd_fops);
|
|
|
|
if (!md->ext_csd_dentry)
|
2017-08-21 00:39:08 +03:00
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-21 16:42:30 +03:00
|
|
|
static void mmc_blk_remove_debugfs(struct mmc_card *card,
|
|
|
|
struct mmc_blk_data *md)
|
|
|
|
{
|
|
|
|
if (!card->debugfs_root)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!IS_ERR_OR_NULL(md->status_dentry)) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2017-08-21 00:39:08 +03:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2017-11-21 16:42:30 +03:00
|
|
|
static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
|
2017-08-21 00:39:08 +03:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-21 16:42:30 +03:00
|
|
|
static void mmc_blk_remove_debugfs(struct mmc_card *card,
|
|
|
|
struct mmc_blk_data *md)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-08-21 00:39:08 +03:00
|
|
|
#endif /* CONFIG_DEBUG_FS */
|
|
|
|
|
2015-04-14 14:06:12 +03:00
|
|
|
static int mmc_blk_probe(struct mmc_card *card)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2011-04-12 03:10:25 +04:00
|
|
|
struct mmc_blk_data *md, *part_md;
|
2008-09-06 12:57:57 +04:00
|
|
|
char cap_str[10];
|
|
|
|
|
2005-05-21 13:27:02 +04:00
|
|
|
/*
|
|
|
|
* Check that the card supports the command class(es) we need.
|
|
|
|
*/
|
|
|
|
if (!(card->csd.cmdclass & CCC_BLOCK_READ))
|
2005-04-17 02:20:36 +04:00
|
|
|
return -ENODEV;
|
|
|
|
|
2017-02-15 11:36:47 +03:00
|
|
|
mmc_fixup_device(card, mmc_blk_fixups);
|
2014-06-18 15:18:07 +04:00
|
|
|
|
2019-02-07 18:03:08 +03:00
|
|
|
card->complete_wq = alloc_workqueue("mmc_complete",
|
|
|
|
WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
|
|
|
|
if (unlikely(!card->complete_wq)) {
|
|
|
|
pr_err("Failed to create mmc completion workqueue");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
md = mmc_blk_alloc(card);
|
mmc: core: Allocate per-request data using the block layer core
The mmc_queue_req is a per-request state container the MMC core uses
to carry bounce buffers, pointers to asynchronous requests and so on.
Currently allocated as a static array of objects, then as a request
comes in, a mmc_queue_req is assigned to it, and used during the
lifetime of the request.
This is backwards compared to how other block layer drivers work:
they usally let the block core provide a per-request struct that get
allocated right beind the struct request, and which can be obtained
using the blk_mq_rq_to_pdu() helper. (The _mq_ infix in this function
name is misleading: it is used by both the old and the MQ block
layer.)
The per-request struct gets allocated to the size stored in the queue
variable .cmd_size initialized using the .init_rq_fn() and
cleaned up using .exit_rq_fn().
The block layer code makes the MMC core rely on this mechanism to
allocate the per-request mmc_queue_req state container.
Doing this make a lot of complicated queue handling go away. We only
need to keep the .qnct that keeps count of how many request are
currently being processed by the MMC layer. The MQ block layer will
replace also this once we transition to it.
Doing this refactoring is necessary to move the ioctl() operations
into custom block layer requests tagged with REQ_OP_DRV_[IN|OUT]
instead of the custom code using the BigMMCHostLock that we have
today: those require that per-request data be obtainable easily from
a request after creating a custom request with e.g.:
struct request *rq = blk_get_request(q, REQ_OP_DRV_IN, __GFP_RECLAIM);
struct mmc_queue_req *mq_rq = req_to_mq_rq(rq);
And this is not possible with the current construction, as the request
is not immediately assigned the per-request state container, but
instead it gets assigned when the request finally enters the MMC
queue, which is way too late for custom requests.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
[Ulf: Folded in the fix to drop a call to blk_cleanup_queue()]
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Heiner Kallweit <hkallweit1@gmail.com>
2017-05-18 12:29:32 +03:00
|
|
|
if (IS_ERR(md))
|
2005-04-17 02:20:36 +04:00
|
|
|
return PTR_ERR(md);
|
|
|
|
|
sd, mmc, virtio_blk, string_helpers: fix block size units
The current string_get_size() overflows when the device size goes over
2^64 bytes because the string helper routine computes the suffix from
the size in bytes. However, the entirety of Linux thinks in terms of
blocks, not bytes, so this will artificially induce an overflow on very
large devices. Fix this by making the function string_get_size() take
blocks and the block size instead of bytes. This should allow us to
keep working until the current SCSI standard overflows.
Also fix virtio_blk and mmc (both of which were also artificially
multiplying by the block size to pass a byte side to string_get_size()).
The mathematics of this is pretty simple: we're taking a product of
size in blocks (S) and block size (B) and trying to re-express this in
exponential form: S*B = R*N^E (where N, the exponent is either 1000 or
1024) and R < N. Mathematically, S = RS*N^ES and B=RB*N^EB, so if RS*RB
< N it's easy to see that S*B = RS*RB*N^(ES+EB). However, if RS*BS > N,
we can see that this can be re-expressed as RS*BS = R*N (where R =
RS*BS/N < N) so the whole exponent becomes R*N^(ES+EB+1)
[jejb: fix incorrect 32 bit do_div spotted by kbuild test robot <fengguang.wu@intel.com>]
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
2015-03-06 05:47:01 +03:00
|
|
|
string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2,
|
2008-09-06 12:57:57 +04:00
|
|
|
cap_str, sizeof(cap_str));
|
2011-10-11 10:14:09 +04:00
|
|
|
pr_info("%s: %s %s %s %s\n",
|
2005-04-17 02:20:36 +04:00
|
|
|
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
|
2008-09-06 12:57:57 +04:00
|
|
|
cap_str, md->read_only ? "(ro)" : "");
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
if (mmc_blk_alloc_parts(card, md))
|
|
|
|
goto out;
|
|
|
|
|
2015-04-14 14:06:12 +03:00
|
|
|
dev_set_drvdata(&card->dev, md);
|
2011-04-12 03:11:04 +04:00
|
|
|
|
2011-04-12 03:10:25 +04:00
|
|
|
if (mmc_add_disk(md))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
list_for_each_entry(part_md, &md->part, part) {
|
|
|
|
if (mmc_add_disk(part_md))
|
|
|
|
goto out;
|
|
|
|
}
|
2013-05-02 16:02:38 +04:00
|
|
|
|
2017-08-21 00:39:08 +03:00
|
|
|
/* Add two debugfs entries */
|
2017-11-21 16:42:30 +03:00
|
|
|
mmc_blk_add_debugfs(card, md);
|
2017-08-21 00:39:08 +03:00
|
|
|
|
2013-05-02 16:02:38 +04:00
|
|
|
pm_runtime_set_autosuspend_delay(&card->dev, 3000);
|
|
|
|
pm_runtime_use_autosuspend(&card->dev);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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) {
|
|
|
|
pm_runtime_set_active(&card->dev);
|
|
|
|
pm_runtime_enable(&card->dev);
|
|
|
|
}
|
|
|
|
|
2005-04-17 02:20:36 +04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
out:
|
2011-04-12 03:10:25 +04:00
|
|
|
mmc_blk_remove_parts(card, md);
|
|
|
|
mmc_blk_remove_req(md);
|
2012-03-22 14:47:26 +04:00
|
|
|
return 0;
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 14:06:12 +03:00
|
|
|
static void mmc_blk_remove(struct mmc_card *card)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2015-04-14 14:06:12 +03:00
|
|
|
struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2017-11-21 16:42:30 +03:00
|
|
|
mmc_blk_remove_debugfs(card, md);
|
2011-04-12 03:10:25 +04:00
|
|
|
mmc_blk_remove_parts(card, md);
|
2013-05-02 16:02:38 +04:00
|
|
|
pm_runtime_get_sync(&card->dev);
|
2018-05-17 10:47:42 +03:00
|
|
|
if (md->part_curr != md->part_type) {
|
|
|
|
mmc_claim_host(card->host);
|
|
|
|
mmc_blk_part_switch(card, md->part_type);
|
|
|
|
mmc_release_host(card->host);
|
|
|
|
}
|
2013-05-02 16:02:38 +04:00
|
|
|
if (card->type != MMC_TYPE_SD_COMBO)
|
|
|
|
pm_runtime_disable(&card->dev);
|
|
|
|
pm_runtime_put_noidle(&card->dev);
|
2011-04-12 03:10:25 +04:00
|
|
|
mmc_blk_remove_req(md);
|
2015-04-14 14:06:12 +03:00
|
|
|
dev_set_drvdata(&card->dev, NULL);
|
2019-02-07 18:03:08 +03:00
|
|
|
destroy_workqueue(card->complete_wq);
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
2015-04-14 14:06:12 +03:00
|
|
|
static int _mmc_blk_suspend(struct mmc_card *card)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2011-04-12 03:10:25 +04:00
|
|
|
struct mmc_blk_data *part_md;
|
2015-04-14 14:06:12 +03:00
|
|
|
struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
if (md) {
|
|
|
|
mmc_queue_suspend(&md->queue);
|
2011-04-12 03:10:25 +04:00
|
|
|
list_for_each_entry(part_md, &md->part, part) {
|
|
|
|
mmc_queue_suspend(&part_md->queue);
|
|
|
|
}
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-14 14:06:12 +03:00
|
|
|
static void mmc_blk_shutdown(struct mmc_card *card)
|
2013-06-10 19:03:40 +04:00
|
|
|
{
|
2015-04-14 14:06:12 +03:00
|
|
|
_mmc_blk_suspend(card);
|
2013-06-10 19:03:40 +04:00
|
|
|
}
|
|
|
|
|
2014-10-06 13:29:42 +04:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
static int mmc_blk_suspend(struct device *dev)
|
2013-06-10 19:03:40 +04:00
|
|
|
{
|
2015-04-14 14:06:12 +03:00
|
|
|
struct mmc_card *card = mmc_dev_to_card(dev);
|
|
|
|
|
|
|
|
return _mmc_blk_suspend(card);
|
2013-06-10 19:03:40 +04:00
|
|
|
}
|
|
|
|
|
2014-10-06 13:29:42 +04:00
|
|
|
static int mmc_blk_resume(struct device *dev)
|
2005-04-17 02:20:36 +04:00
|
|
|
{
|
2011-04-12 03:10:25 +04:00
|
|
|
struct mmc_blk_data *part_md;
|
2014-10-06 16:34:09 +04:00
|
|
|
struct mmc_blk_data *md = dev_get_drvdata(dev);
|
2005-04-17 02:20:36 +04:00
|
|
|
|
|
|
|
if (md) {
|
2011-04-12 03:10:25 +04:00
|
|
|
/*
|
|
|
|
* Resume involves the card going into idle state,
|
|
|
|
* so current partition is always the main one.
|
|
|
|
*/
|
|
|
|
md->part_curr = md->part_type;
|
2005-04-17 02:20:36 +04:00
|
|
|
mmc_queue_resume(&md->queue);
|
2011-04-12 03:10:25 +04:00
|
|
|
list_for_each_entry(part_md, &md->part, part) {
|
|
|
|
mmc_queue_resume(&part_md->queue);
|
|
|
|
}
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-10-06 13:29:42 +04:00
|
|
|
static SIMPLE_DEV_PM_OPS(mmc_blk_pm_ops, mmc_blk_suspend, mmc_blk_resume);
|
|
|
|
|
2015-04-14 14:06:12 +03:00
|
|
|
static struct mmc_driver mmc_driver = {
|
|
|
|
.drv = {
|
|
|
|
.name = "mmcblk",
|
|
|
|
.pm = &mmc_blk_pm_ops,
|
|
|
|
},
|
2005-04-17 02:20:36 +04:00
|
|
|
.probe = mmc_blk_probe,
|
|
|
|
.remove = mmc_blk_remove,
|
2013-06-10 19:03:40 +04:00
|
|
|
.shutdown = mmc_blk_shutdown,
|
2005-04-17 02:20:36 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static int __init mmc_blk_init(void)
|
|
|
|
{
|
2008-09-13 14:02:07 +04:00
|
|
|
int res;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-09-18 05:19:57 +04:00
|
|
|
if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
|
|
|
|
pr_info("mmcblk: using %d minors per device\n", perdev_minors);
|
|
|
|
|
2014-11-06 06:35:09 +03:00
|
|
|
max_devices = min(MAX_DEVICES, (1 << MINORBITS) / perdev_minors);
|
2010-09-18 05:19:57 +04:00
|
|
|
|
2007-05-14 19:27:29 +04:00
|
|
|
res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
|
|
|
|
if (res)
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
goto out_chrdev_unreg;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-09-13 14:02:07 +04:00
|
|
|
res = mmc_register_driver(&mmc_driver);
|
|
|
|
if (res)
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
goto out_blkdev_unreg;
|
2005-04-17 02:20:36 +04:00
|
|
|
|
2008-09-13 14:02:07 +04:00
|
|
|
return 0;
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
|
|
|
|
out_blkdev_unreg:
|
2008-09-13 14:02:07 +04:00
|
|
|
unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
out_chrdev_unreg:
|
|
|
|
unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
|
|
|
|
out_bus_unreg:
|
|
|
|
bus_unregister(&mmc_rpmb_bus_type);
|
2005-04-17 02:20:36 +04:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit mmc_blk_exit(void)
|
|
|
|
{
|
|
|
|
mmc_unregister_driver(&mmc_driver);
|
2007-05-14 19:27:29 +04:00
|
|
|
unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
|
mmc: block: Convert RPMB to a character device
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>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-09-20 11:02:00 +03:00
|
|
|
unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
|
2018-03-29 01:18:31 +03:00
|
|
|
bus_unregister(&mmc_rpmb_bus_type);
|
2005-04-17 02:20:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
module_init(mmc_blk_init);
|
|
|
|
module_exit(mmc_blk_exit);
|
|
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
|
|
|
|
|