2021-05-23 23:59:15 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Block driver for media (i.e., flash cards)
|
|
|
|
*
|
|
|
|
* Copyright 2002 Hewlett-Packard Company
|
2008-06-29 18:19:47 +08:00
|
|
|
* Copyright 2005-2008 Pierre Ossman
|
2005-04-17 06:20:36 +08: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 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/hdreg.h>
|
|
|
|
#include <linux/kdev_t.h>
|
mmc: core: Use kref in place of struct mmc_blk_data::usage
Ulf reported the following KASAN splat after adding some manual hacks
into mmc-utils[1].
DEBUG: mmc_blk_open: Let's sleep for 10s..
mmc1: card 0007 removed
BUG: KASAN: use-after-free in mmc_blk_get+0x58/0xb8
Read of size 4 at addr ffff00000a394a28 by task mmc/180
CPU: 2 PID: 180 Comm: mmc Not tainted 5.10.0-rc4-00069-gcc758c8c7127-dirty #5
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Call trace:
dump_backtrace+0x0/0x2b4
show_stack+0x18/0x6c
dump_stack+0xfc/0x168
print_address_description.constprop.0+0x6c/0x488
kasan_report+0x118/0x210
__asan_load4+0x94/0xd0
mmc_blk_get+0x58/0xb8
mmc_blk_open+0x7c/0xdc
__blkdev_get+0x3b4/0x964
blkdev_get+0x64/0x100
blkdev_open+0xe8/0x104
do_dentry_open+0x234/0x61c
vfs_open+0x54/0x64
path_openat+0xe04/0x1584
do_filp_open+0xe8/0x1e4
do_sys_openat2+0x120/0x230
__arm64_sys_openat+0xf0/0x15c
el0_svc_common.constprop.0+0xac/0x234
do_el0_svc+0x84/0xa0
el0_sync_handler+0x264/0x270
el0_sync+0x174/0x180
Allocated by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
__kasan_kmalloc.constprop.0+0xc8/0xf0
kasan_kmalloc+0x10/0x20
mmc_blk_alloc_req+0x94/0x4b0
mmc_blk_probe+0x2d4/0xaa4
mmc_bus_probe+0x34/0x4c
really_probe+0x148/0x6e0
driver_probe_device+0x78/0xec
__device_attach_driver+0x108/0x16c
bus_for_each_drv+0xf4/0x15c
__device_attach+0x168/0x240
device_initial_probe+0x14/0x20
bus_probe_device+0xec/0x100
device_add+0x55c/0xaf0
mmc_add_card+0x288/0x380
mmc_attach_sd+0x18c/0x22c
mmc_rescan+0x444/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
Freed by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
kasan_set_track+0x28/0x40
kasan_set_free_info+0x24/0x4c
__kasan_slab_free+0x100/0x180
kasan_slab_free+0x14/0x20
kfree+0xb8/0x46c
mmc_blk_put+0xe4/0x11c
mmc_blk_remove_req.part.0+0x6c/0xe4
mmc_blk_remove+0x368/0x370
mmc_bus_remove+0x34/0x50
__device_release_driver+0x228/0x31c
device_release_driver+0x2c/0x44
bus_remove_device+0x1e4/0x200
device_del+0x2b0/0x770
mmc_remove_card+0xf0/0x150
mmc_sd_detect+0x9c/0x150
mmc_rescan+0x110/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
The buggy address belongs to the object at ffff00000a394800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 552 bytes inside of
1024-byte region [ffff00000a394800, ffff00000a394c00)
The buggy address belongs to the page:
page:00000000ff84ed53 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8a390
head:00000000ff84ed53 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x3fffc0000010200(slab|head)
raw: 03fffc0000010200 dead000000000100 dead000000000122 ffff000009f03800
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff00000a394900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff00000a394a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff00000a394a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Looking closer at the problem, it looks like a classic dangling pointer
bug. The 'struct mmc_blk_data' that is used after being freed in
mmc_blk_put() is stashed away in 'md->disk->private_data' via
mmc_blk_alloc_req() but used in mmc_blk_get() because the 'usage' count
isn't properly aligned with the lifetime of the pointer. You'd expect
the 'usage' member to be in sync with the kfree(), and it mostly is,
except that mmc_blk_get() needs to dereference the potentially freed
memory storage for the 'struct mmc_blk_data' stashed away in the
private_data member to look at 'usage' before it actually figures out if
it wants to consider it a valid pointer or not. That's not going to work
if the freed memory has been overwritten by something else after the
free, and KASAN rightly complains here.
To fix the immediate problem, let's set the private_data member to NULL
in mmc_blk_put() so that mmc_blk_get() can consider the object "on the
way out" if the pointer is NULL and not even try to look at 'usage' if
the object isn't going to be around much longer. With that set to NULL
on the last mmc_blk_put(), optimize the get path further and use a kref
underneath the 'open_lock' mutex to only up the reference count if it's
non-zero, i.e. alive, and otherwise make mmc_blk_get() return NULL,
without actually testing the reference count if we're in the process of
removing the object from the system.
Finally, tighten the locking region on the put side to only be around
the parts that are removing the 'mmc_blk_data' from the system and
publishing that fact to the gendisk and then drop the lock as soon as we
can to avoid holding the lock around code that doesn't need it. This
fixes the KASAN issue.
Cc: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Cc: Sujit Kautkar <sujitka@chromium.org>
Cc: Zubin Mithra <zsm@chromium.org>
Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/linux-mmc/CAPDyKFryT63Jc7+DXWSpAC19qpZRqFr1orxwYGMuSqx247O8cQ@mail.gmail.com/ [1]
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20210623075002.1746924-2-swboyd@chromium.org
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2021-06-23 15:50:01 +08:00
|
|
|
#include <linux/kref.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#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 16:02:00 +08:00
|
|
|
#include <linux/cdev.h>
|
2006-01-13 02:43:35 +08:00
|
|
|
#include <linux/mutex.h>
|
2006-10-06 15:44:03 +08:00
|
|
|
#include <linux/scatterlist.h>
|
2008-09-06 16:57:57 +08:00
|
|
|
#include <linux/string_helpers.h>
|
2011-04-27 06:56:29 +08:00
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/capability.h>
|
|
|
|
#include <linux/compat.h>
|
2013-05-02 20:02:38 +08:00
|
|
|
#include <linux/pm_runtime.h>
|
2016-04-07 20:36:46 +08:00
|
|
|
#include <linux/idr.h>
|
2017-08-21 05:39:08 +08:00
|
|
|
#include <linux/debugfs.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-04-27 06:56:29 +08:00
|
|
|
#include <linux/mmc/ioctl.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/mmc/card.h>
|
2006-06-18 20:34:37 +08:00
|
|
|
#include <linux/mmc/host.h>
|
2006-12-25 05:46:55 +08:00
|
|
|
#include <linux/mmc/mmc.h>
|
|
|
|
#include <linux/mmc/sd.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-12-25 03:46:01 +08:00
|
|
|
#include <linux/uaccess.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-12-24 03:03:02 +08:00
|
|
|
#include "queue.h"
|
2016-09-30 09:37:38 +08:00
|
|
|
#include "block.h"
|
2017-01-13 21:14:08 +08:00
|
|
|
#include "core.h"
|
2017-01-13 21:14:14 +08:00
|
|
|
#include "card.h"
|
2021-01-26 08:14:48 +08:00
|
|
|
#include "crypto.h"
|
2017-01-13 21:14:15 +08:00
|
|
|
#include "host.h"
|
2017-01-13 21:14:14 +08:00
|
|
|
#include "bus.h"
|
2017-01-13 21:14:08 +08:00
|
|
|
#include "mmc_ops.h"
|
2017-02-15 16:35:28 +08:00
|
|
|
#include "quirks.h"
|
2017-01-13 21:14:08 +08:00
|
|
|
#include "sd_ops.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-02-23 20:38:41 +08:00
|
|
|
MODULE_ALIAS("mmc:block");
|
2010-09-18 09:19:57 +08:00
|
|
|
#ifdef MODULE_PARAM_PREFIX
|
|
|
|
#undef MODULE_PARAM_PREFIX
|
|
|
|
#endif
|
|
|
|
#define MODULE_PARAM_PREFIX "mmcblk."
|
|
|
|
|
2017-11-29 21:41:14 +08: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 20:41:55 +08:00
|
|
|
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
|
2018-03-08 22:08:11 +08:00
|
|
|
#define MMC_EXTRACT_VALUE_FROM_ARG(x) ((x & 0x0000FF00) >> 8)
|
2011-04-13 04:06:53 +08:00
|
|
|
|
2010-09-18 09:19:57 +08:00
|
|
|
static DEFINE_MUTEX(block_mutex);
|
2009-02-23 20:38:41 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2010-09-18 09:19:57 +08:00
|
|
|
* The defaults come from config options but can be overriden by module
|
|
|
|
* or bootarg options.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2010-09-18 09:19:57 +08:00
|
|
|
static int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
|
2007-11-22 01:45:12 +08:00
|
|
|
|
2010-09-18 09:19:57 +08:00
|
|
|
/*
|
|
|
|
* We've only got one major, so number of mmcblk devices is
|
2014-11-06 11:35:09 +08:00
|
|
|
* limited to (1 << 20) / number of minors per device. It is also
|
2016-04-07 20:36:46 +08:00
|
|
|
* limited by the MAX_DEVICES below.
|
2010-09-18 09:19:57 +08:00
|
|
|
*/
|
|
|
|
static int max_devices;
|
|
|
|
|
2014-11-06 11:35:09 +08:00
|
|
|
#define MAX_DEVICES 256
|
|
|
|
|
2016-04-07 20:36:46 +08: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 16:02:00 +08:00
|
|
|
static DEFINE_IDA(mmc_rpmb_ida);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2021-07-02 21:42:29 +08:00
|
|
|
struct mmc_blk_busy_data {
|
|
|
|
struct mmc_card *card;
|
|
|
|
u32 status;
|
|
|
|
};
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* There is one mmc_blk_data per slot.
|
|
|
|
*/
|
|
|
|
struct mmc_blk_data {
|
2016-06-21 01:40:44 +08:00
|
|
|
struct device *parent;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct gendisk *disk;
|
|
|
|
struct mmc_queue queue;
|
2011-04-12 07:10:25 +08: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 16:02:00 +08:00
|
|
|
struct list_head rpmbs;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-05-24 04:06:36 +08: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 */
|
|
|
|
|
mmc: core: Use kref in place of struct mmc_blk_data::usage
Ulf reported the following KASAN splat after adding some manual hacks
into mmc-utils[1].
DEBUG: mmc_blk_open: Let's sleep for 10s..
mmc1: card 0007 removed
BUG: KASAN: use-after-free in mmc_blk_get+0x58/0xb8
Read of size 4 at addr ffff00000a394a28 by task mmc/180
CPU: 2 PID: 180 Comm: mmc Not tainted 5.10.0-rc4-00069-gcc758c8c7127-dirty #5
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Call trace:
dump_backtrace+0x0/0x2b4
show_stack+0x18/0x6c
dump_stack+0xfc/0x168
print_address_description.constprop.0+0x6c/0x488
kasan_report+0x118/0x210
__asan_load4+0x94/0xd0
mmc_blk_get+0x58/0xb8
mmc_blk_open+0x7c/0xdc
__blkdev_get+0x3b4/0x964
blkdev_get+0x64/0x100
blkdev_open+0xe8/0x104
do_dentry_open+0x234/0x61c
vfs_open+0x54/0x64
path_openat+0xe04/0x1584
do_filp_open+0xe8/0x1e4
do_sys_openat2+0x120/0x230
__arm64_sys_openat+0xf0/0x15c
el0_svc_common.constprop.0+0xac/0x234
do_el0_svc+0x84/0xa0
el0_sync_handler+0x264/0x270
el0_sync+0x174/0x180
Allocated by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
__kasan_kmalloc.constprop.0+0xc8/0xf0
kasan_kmalloc+0x10/0x20
mmc_blk_alloc_req+0x94/0x4b0
mmc_blk_probe+0x2d4/0xaa4
mmc_bus_probe+0x34/0x4c
really_probe+0x148/0x6e0
driver_probe_device+0x78/0xec
__device_attach_driver+0x108/0x16c
bus_for_each_drv+0xf4/0x15c
__device_attach+0x168/0x240
device_initial_probe+0x14/0x20
bus_probe_device+0xec/0x100
device_add+0x55c/0xaf0
mmc_add_card+0x288/0x380
mmc_attach_sd+0x18c/0x22c
mmc_rescan+0x444/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
Freed by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
kasan_set_track+0x28/0x40
kasan_set_free_info+0x24/0x4c
__kasan_slab_free+0x100/0x180
kasan_slab_free+0x14/0x20
kfree+0xb8/0x46c
mmc_blk_put+0xe4/0x11c
mmc_blk_remove_req.part.0+0x6c/0xe4
mmc_blk_remove+0x368/0x370
mmc_bus_remove+0x34/0x50
__device_release_driver+0x228/0x31c
device_release_driver+0x2c/0x44
bus_remove_device+0x1e4/0x200
device_del+0x2b0/0x770
mmc_remove_card+0xf0/0x150
mmc_sd_detect+0x9c/0x150
mmc_rescan+0x110/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
The buggy address belongs to the object at ffff00000a394800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 552 bytes inside of
1024-byte region [ffff00000a394800, ffff00000a394c00)
The buggy address belongs to the page:
page:00000000ff84ed53 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8a390
head:00000000ff84ed53 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x3fffc0000010200(slab|head)
raw: 03fffc0000010200 dead000000000100 dead000000000122 ffff000009f03800
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff00000a394900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff00000a394a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff00000a394a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Looking closer at the problem, it looks like a classic dangling pointer
bug. The 'struct mmc_blk_data' that is used after being freed in
mmc_blk_put() is stashed away in 'md->disk->private_data' via
mmc_blk_alloc_req() but used in mmc_blk_get() because the 'usage' count
isn't properly aligned with the lifetime of the pointer. You'd expect
the 'usage' member to be in sync with the kfree(), and it mostly is,
except that mmc_blk_get() needs to dereference the potentially freed
memory storage for the 'struct mmc_blk_data' stashed away in the
private_data member to look at 'usage' before it actually figures out if
it wants to consider it a valid pointer or not. That's not going to work
if the freed memory has been overwritten by something else after the
free, and KASAN rightly complains here.
To fix the immediate problem, let's set the private_data member to NULL
in mmc_blk_put() so that mmc_blk_get() can consider the object "on the
way out" if the pointer is NULL and not even try to look at 'usage' if
the object isn't going to be around much longer. With that set to NULL
on the last mmc_blk_put(), optimize the get path further and use a kref
underneath the 'open_lock' mutex to only up the reference count if it's
non-zero, i.e. alive, and otherwise make mmc_blk_get() return NULL,
without actually testing the reference count if we're in the process of
removing the object from the system.
Finally, tighten the locking region on the put side to only be around
the parts that are removing the 'mmc_blk_data' from the system and
publishing that fact to the gendisk and then drop the lock as soon as we
can to avoid holding the lock around code that doesn't need it. This
fixes the KASAN issue.
Cc: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Cc: Sujit Kautkar <sujitka@chromium.org>
Cc: Zubin Mithra <zsm@chromium.org>
Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/linux-mmc/CAPDyKFryT63Jc7+DXWSpAC19qpZRqFr1orxwYGMuSqx247O8cQ@mail.gmail.com/ [1]
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20210623075002.1746924-2-swboyd@chromium.org
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2021-06-23 15:50:01 +08:00
|
|
|
struct kref kref;
|
2006-01-04 06:38:44 +08:00
|
|
|
unsigned int read_only;
|
2011-04-12 07:10:25 +08:00
|
|
|
unsigned int part_type;
|
2011-08-29 21:42:15 +08: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 21:41:04 +08:00
|
|
|
#define MMC_BLK_CQE_RECOVERY BIT(4)
|
2022-04-29 23:21:18 +08:00
|
|
|
#define MMC_BLK_TRIM BIT(5)
|
2011-04-12 07:10:25 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Only set in main mmc_blk_data associated
|
2014-10-06 20:34:09 +08:00
|
|
|
* with mmc_card with dev_set_drvdata, and keeps
|
2011-04-12 07:10:25 +08:00
|
|
|
* track of the current selected device partition.
|
|
|
|
*/
|
|
|
|
unsigned int part_curr;
|
2022-10-13 19:16:37 +08:00
|
|
|
#define MMC_BLK_PART_INVALID UINT_MAX /* Unknown partition active */
|
2011-12-02 15:51:06 +08:00
|
|
|
int area_type;
|
2017-11-21 21:42:30 +08:00
|
|
|
|
|
|
|
/* debugfs files (only in main mmc_blk_data) */
|
|
|
|
struct dentry *status_dentry;
|
|
|
|
struct dentry *ext_csd_dentry;
|
2005-04-17 06:20:36 +08: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 16:02:00 +08: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-13 02:43:35 +08:00
|
|
|
static DEFINE_MUTEX(open_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-09-18 09:19:57 +08:00
|
|
|
module_param(perdev_minors, int, 0444);
|
|
|
|
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
|
|
|
|
|
2012-08-06 23:12:31 +08:00
|
|
|
static inline int mmc_blk_part_switch(struct mmc_card *card,
|
2017-08-21 05:39:10 +08: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 12:12:56 +08:00
|
|
|
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
|
|
|
|
struct mmc_card *card,
|
2022-07-01 20:43:09 +08:00
|
|
|
int recovery_mode,
|
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 12:12:56 +08:00
|
|
|
struct mmc_queue *mq);
|
|
|
|
static void mmc_blk_hsq_req_done(struct mmc_request *mrq);
|
2017-03-13 20:36:35 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
|
|
|
|
{
|
|
|
|
struct mmc_blk_data *md;
|
|
|
|
|
2006-01-13 02:43:35 +08:00
|
|
|
mutex_lock(&open_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
md = disk->private_data;
|
mmc: core: Use kref in place of struct mmc_blk_data::usage
Ulf reported the following KASAN splat after adding some manual hacks
into mmc-utils[1].
DEBUG: mmc_blk_open: Let's sleep for 10s..
mmc1: card 0007 removed
BUG: KASAN: use-after-free in mmc_blk_get+0x58/0xb8
Read of size 4 at addr ffff00000a394a28 by task mmc/180
CPU: 2 PID: 180 Comm: mmc Not tainted 5.10.0-rc4-00069-gcc758c8c7127-dirty #5
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Call trace:
dump_backtrace+0x0/0x2b4
show_stack+0x18/0x6c
dump_stack+0xfc/0x168
print_address_description.constprop.0+0x6c/0x488
kasan_report+0x118/0x210
__asan_load4+0x94/0xd0
mmc_blk_get+0x58/0xb8
mmc_blk_open+0x7c/0xdc
__blkdev_get+0x3b4/0x964
blkdev_get+0x64/0x100
blkdev_open+0xe8/0x104
do_dentry_open+0x234/0x61c
vfs_open+0x54/0x64
path_openat+0xe04/0x1584
do_filp_open+0xe8/0x1e4
do_sys_openat2+0x120/0x230
__arm64_sys_openat+0xf0/0x15c
el0_svc_common.constprop.0+0xac/0x234
do_el0_svc+0x84/0xa0
el0_sync_handler+0x264/0x270
el0_sync+0x174/0x180
Allocated by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
__kasan_kmalloc.constprop.0+0xc8/0xf0
kasan_kmalloc+0x10/0x20
mmc_blk_alloc_req+0x94/0x4b0
mmc_blk_probe+0x2d4/0xaa4
mmc_bus_probe+0x34/0x4c
really_probe+0x148/0x6e0
driver_probe_device+0x78/0xec
__device_attach_driver+0x108/0x16c
bus_for_each_drv+0xf4/0x15c
__device_attach+0x168/0x240
device_initial_probe+0x14/0x20
bus_probe_device+0xec/0x100
device_add+0x55c/0xaf0
mmc_add_card+0x288/0x380
mmc_attach_sd+0x18c/0x22c
mmc_rescan+0x444/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
Freed by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
kasan_set_track+0x28/0x40
kasan_set_free_info+0x24/0x4c
__kasan_slab_free+0x100/0x180
kasan_slab_free+0x14/0x20
kfree+0xb8/0x46c
mmc_blk_put+0xe4/0x11c
mmc_blk_remove_req.part.0+0x6c/0xe4
mmc_blk_remove+0x368/0x370
mmc_bus_remove+0x34/0x50
__device_release_driver+0x228/0x31c
device_release_driver+0x2c/0x44
bus_remove_device+0x1e4/0x200
device_del+0x2b0/0x770
mmc_remove_card+0xf0/0x150
mmc_sd_detect+0x9c/0x150
mmc_rescan+0x110/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
The buggy address belongs to the object at ffff00000a394800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 552 bytes inside of
1024-byte region [ffff00000a394800, ffff00000a394c00)
The buggy address belongs to the page:
page:00000000ff84ed53 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8a390
head:00000000ff84ed53 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x3fffc0000010200(slab|head)
raw: 03fffc0000010200 dead000000000100 dead000000000122 ffff000009f03800
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff00000a394900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff00000a394a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff00000a394a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Looking closer at the problem, it looks like a classic dangling pointer
bug. The 'struct mmc_blk_data' that is used after being freed in
mmc_blk_put() is stashed away in 'md->disk->private_data' via
mmc_blk_alloc_req() but used in mmc_blk_get() because the 'usage' count
isn't properly aligned with the lifetime of the pointer. You'd expect
the 'usage' member to be in sync with the kfree(), and it mostly is,
except that mmc_blk_get() needs to dereference the potentially freed
memory storage for the 'struct mmc_blk_data' stashed away in the
private_data member to look at 'usage' before it actually figures out if
it wants to consider it a valid pointer or not. That's not going to work
if the freed memory has been overwritten by something else after the
free, and KASAN rightly complains here.
To fix the immediate problem, let's set the private_data member to NULL
in mmc_blk_put() so that mmc_blk_get() can consider the object "on the
way out" if the pointer is NULL and not even try to look at 'usage' if
the object isn't going to be around much longer. With that set to NULL
on the last mmc_blk_put(), optimize the get path further and use a kref
underneath the 'open_lock' mutex to only up the reference count if it's
non-zero, i.e. alive, and otherwise make mmc_blk_get() return NULL,
without actually testing the reference count if we're in the process of
removing the object from the system.
Finally, tighten the locking region on the put side to only be around
the parts that are removing the 'mmc_blk_data' from the system and
publishing that fact to the gendisk and then drop the lock as soon as we
can to avoid holding the lock around code that doesn't need it. This
fixes the KASAN issue.
Cc: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Cc: Sujit Kautkar <sujitka@chromium.org>
Cc: Zubin Mithra <zsm@chromium.org>
Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/linux-mmc/CAPDyKFryT63Jc7+DXWSpAC19qpZRqFr1orxwYGMuSqx247O8cQ@mail.gmail.com/ [1]
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20210623075002.1746924-2-swboyd@chromium.org
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2021-06-23 15:50:01 +08:00
|
|
|
if (md && !kref_get_unless_zero(&md->kref))
|
2005-04-17 06:20:36 +08:00
|
|
|
md = NULL;
|
2006-01-13 02:43:35 +08:00
|
|
|
mutex_unlock(&open_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return md;
|
|
|
|
}
|
|
|
|
|
2011-04-12 07:10:25 +08:00
|
|
|
static inline int mmc_get_devidx(struct gendisk *disk)
|
|
|
|
{
|
2015-10-23 01:00:41 +08:00
|
|
|
int devidx = disk->first_minor / perdev_minors;
|
2011-04-12 07:10:25 +08:00
|
|
|
return devidx;
|
|
|
|
}
|
|
|
|
|
mmc: core: Use kref in place of struct mmc_blk_data::usage
Ulf reported the following KASAN splat after adding some manual hacks
into mmc-utils[1].
DEBUG: mmc_blk_open: Let's sleep for 10s..
mmc1: card 0007 removed
BUG: KASAN: use-after-free in mmc_blk_get+0x58/0xb8
Read of size 4 at addr ffff00000a394a28 by task mmc/180
CPU: 2 PID: 180 Comm: mmc Not tainted 5.10.0-rc4-00069-gcc758c8c7127-dirty #5
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Call trace:
dump_backtrace+0x0/0x2b4
show_stack+0x18/0x6c
dump_stack+0xfc/0x168
print_address_description.constprop.0+0x6c/0x488
kasan_report+0x118/0x210
__asan_load4+0x94/0xd0
mmc_blk_get+0x58/0xb8
mmc_blk_open+0x7c/0xdc
__blkdev_get+0x3b4/0x964
blkdev_get+0x64/0x100
blkdev_open+0xe8/0x104
do_dentry_open+0x234/0x61c
vfs_open+0x54/0x64
path_openat+0xe04/0x1584
do_filp_open+0xe8/0x1e4
do_sys_openat2+0x120/0x230
__arm64_sys_openat+0xf0/0x15c
el0_svc_common.constprop.0+0xac/0x234
do_el0_svc+0x84/0xa0
el0_sync_handler+0x264/0x270
el0_sync+0x174/0x180
Allocated by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
__kasan_kmalloc.constprop.0+0xc8/0xf0
kasan_kmalloc+0x10/0x20
mmc_blk_alloc_req+0x94/0x4b0
mmc_blk_probe+0x2d4/0xaa4
mmc_bus_probe+0x34/0x4c
really_probe+0x148/0x6e0
driver_probe_device+0x78/0xec
__device_attach_driver+0x108/0x16c
bus_for_each_drv+0xf4/0x15c
__device_attach+0x168/0x240
device_initial_probe+0x14/0x20
bus_probe_device+0xec/0x100
device_add+0x55c/0xaf0
mmc_add_card+0x288/0x380
mmc_attach_sd+0x18c/0x22c
mmc_rescan+0x444/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
Freed by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
kasan_set_track+0x28/0x40
kasan_set_free_info+0x24/0x4c
__kasan_slab_free+0x100/0x180
kasan_slab_free+0x14/0x20
kfree+0xb8/0x46c
mmc_blk_put+0xe4/0x11c
mmc_blk_remove_req.part.0+0x6c/0xe4
mmc_blk_remove+0x368/0x370
mmc_bus_remove+0x34/0x50
__device_release_driver+0x228/0x31c
device_release_driver+0x2c/0x44
bus_remove_device+0x1e4/0x200
device_del+0x2b0/0x770
mmc_remove_card+0xf0/0x150
mmc_sd_detect+0x9c/0x150
mmc_rescan+0x110/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
The buggy address belongs to the object at ffff00000a394800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 552 bytes inside of
1024-byte region [ffff00000a394800, ffff00000a394c00)
The buggy address belongs to the page:
page:00000000ff84ed53 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8a390
head:00000000ff84ed53 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x3fffc0000010200(slab|head)
raw: 03fffc0000010200 dead000000000100 dead000000000122 ffff000009f03800
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff00000a394900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff00000a394a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff00000a394a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Looking closer at the problem, it looks like a classic dangling pointer
bug. The 'struct mmc_blk_data' that is used after being freed in
mmc_blk_put() is stashed away in 'md->disk->private_data' via
mmc_blk_alloc_req() but used in mmc_blk_get() because the 'usage' count
isn't properly aligned with the lifetime of the pointer. You'd expect
the 'usage' member to be in sync with the kfree(), and it mostly is,
except that mmc_blk_get() needs to dereference the potentially freed
memory storage for the 'struct mmc_blk_data' stashed away in the
private_data member to look at 'usage' before it actually figures out if
it wants to consider it a valid pointer or not. That's not going to work
if the freed memory has been overwritten by something else after the
free, and KASAN rightly complains here.
To fix the immediate problem, let's set the private_data member to NULL
in mmc_blk_put() so that mmc_blk_get() can consider the object "on the
way out" if the pointer is NULL and not even try to look at 'usage' if
the object isn't going to be around much longer. With that set to NULL
on the last mmc_blk_put(), optimize the get path further and use a kref
underneath the 'open_lock' mutex to only up the reference count if it's
non-zero, i.e. alive, and otherwise make mmc_blk_get() return NULL,
without actually testing the reference count if we're in the process of
removing the object from the system.
Finally, tighten the locking region on the put side to only be around
the parts that are removing the 'mmc_blk_data' from the system and
publishing that fact to the gendisk and then drop the lock as soon as we
can to avoid holding the lock around code that doesn't need it. This
fixes the KASAN issue.
Cc: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Cc: Sujit Kautkar <sujitka@chromium.org>
Cc: Zubin Mithra <zsm@chromium.org>
Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/linux-mmc/CAPDyKFryT63Jc7+DXWSpAC19qpZRqFr1orxwYGMuSqx247O8cQ@mail.gmail.com/ [1]
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20210623075002.1746924-2-swboyd@chromium.org
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2021-06-23 15:50:01 +08:00
|
|
|
static void mmc_blk_kref_release(struct kref *ref)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
mmc: core: Use kref in place of struct mmc_blk_data::usage
Ulf reported the following KASAN splat after adding some manual hacks
into mmc-utils[1].
DEBUG: mmc_blk_open: Let's sleep for 10s..
mmc1: card 0007 removed
BUG: KASAN: use-after-free in mmc_blk_get+0x58/0xb8
Read of size 4 at addr ffff00000a394a28 by task mmc/180
CPU: 2 PID: 180 Comm: mmc Not tainted 5.10.0-rc4-00069-gcc758c8c7127-dirty #5
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Call trace:
dump_backtrace+0x0/0x2b4
show_stack+0x18/0x6c
dump_stack+0xfc/0x168
print_address_description.constprop.0+0x6c/0x488
kasan_report+0x118/0x210
__asan_load4+0x94/0xd0
mmc_blk_get+0x58/0xb8
mmc_blk_open+0x7c/0xdc
__blkdev_get+0x3b4/0x964
blkdev_get+0x64/0x100
blkdev_open+0xe8/0x104
do_dentry_open+0x234/0x61c
vfs_open+0x54/0x64
path_openat+0xe04/0x1584
do_filp_open+0xe8/0x1e4
do_sys_openat2+0x120/0x230
__arm64_sys_openat+0xf0/0x15c
el0_svc_common.constprop.0+0xac/0x234
do_el0_svc+0x84/0xa0
el0_sync_handler+0x264/0x270
el0_sync+0x174/0x180
Allocated by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
__kasan_kmalloc.constprop.0+0xc8/0xf0
kasan_kmalloc+0x10/0x20
mmc_blk_alloc_req+0x94/0x4b0
mmc_blk_probe+0x2d4/0xaa4
mmc_bus_probe+0x34/0x4c
really_probe+0x148/0x6e0
driver_probe_device+0x78/0xec
__device_attach_driver+0x108/0x16c
bus_for_each_drv+0xf4/0x15c
__device_attach+0x168/0x240
device_initial_probe+0x14/0x20
bus_probe_device+0xec/0x100
device_add+0x55c/0xaf0
mmc_add_card+0x288/0x380
mmc_attach_sd+0x18c/0x22c
mmc_rescan+0x444/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
Freed by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
kasan_set_track+0x28/0x40
kasan_set_free_info+0x24/0x4c
__kasan_slab_free+0x100/0x180
kasan_slab_free+0x14/0x20
kfree+0xb8/0x46c
mmc_blk_put+0xe4/0x11c
mmc_blk_remove_req.part.0+0x6c/0xe4
mmc_blk_remove+0x368/0x370
mmc_bus_remove+0x34/0x50
__device_release_driver+0x228/0x31c
device_release_driver+0x2c/0x44
bus_remove_device+0x1e4/0x200
device_del+0x2b0/0x770
mmc_remove_card+0xf0/0x150
mmc_sd_detect+0x9c/0x150
mmc_rescan+0x110/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
The buggy address belongs to the object at ffff00000a394800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 552 bytes inside of
1024-byte region [ffff00000a394800, ffff00000a394c00)
The buggy address belongs to the page:
page:00000000ff84ed53 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8a390
head:00000000ff84ed53 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x3fffc0000010200(slab|head)
raw: 03fffc0000010200 dead000000000100 dead000000000122 ffff000009f03800
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff00000a394900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff00000a394a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff00000a394a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Looking closer at the problem, it looks like a classic dangling pointer
bug. The 'struct mmc_blk_data' that is used after being freed in
mmc_blk_put() is stashed away in 'md->disk->private_data' via
mmc_blk_alloc_req() but used in mmc_blk_get() because the 'usage' count
isn't properly aligned with the lifetime of the pointer. You'd expect
the 'usage' member to be in sync with the kfree(), and it mostly is,
except that mmc_blk_get() needs to dereference the potentially freed
memory storage for the 'struct mmc_blk_data' stashed away in the
private_data member to look at 'usage' before it actually figures out if
it wants to consider it a valid pointer or not. That's not going to work
if the freed memory has been overwritten by something else after the
free, and KASAN rightly complains here.
To fix the immediate problem, let's set the private_data member to NULL
in mmc_blk_put() so that mmc_blk_get() can consider the object "on the
way out" if the pointer is NULL and not even try to look at 'usage' if
the object isn't going to be around much longer. With that set to NULL
on the last mmc_blk_put(), optimize the get path further and use a kref
underneath the 'open_lock' mutex to only up the reference count if it's
non-zero, i.e. alive, and otherwise make mmc_blk_get() return NULL,
without actually testing the reference count if we're in the process of
removing the object from the system.
Finally, tighten the locking region on the put side to only be around
the parts that are removing the 'mmc_blk_data' from the system and
publishing that fact to the gendisk and then drop the lock as soon as we
can to avoid holding the lock around code that doesn't need it. This
fixes the KASAN issue.
Cc: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Cc: Sujit Kautkar <sujitka@chromium.org>
Cc: Zubin Mithra <zsm@chromium.org>
Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/linux-mmc/CAPDyKFryT63Jc7+DXWSpAC19qpZRqFr1orxwYGMuSqx247O8cQ@mail.gmail.com/ [1]
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20210623075002.1746924-2-swboyd@chromium.org
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2021-06-23 15:50:01 +08:00
|
|
|
struct mmc_blk_data *md = container_of(ref, struct mmc_blk_data, kref);
|
|
|
|
int devidx;
|
2021-06-16 13:39:33 +08:00
|
|
|
|
mmc: core: Use kref in place of struct mmc_blk_data::usage
Ulf reported the following KASAN splat after adding some manual hacks
into mmc-utils[1].
DEBUG: mmc_blk_open: Let's sleep for 10s..
mmc1: card 0007 removed
BUG: KASAN: use-after-free in mmc_blk_get+0x58/0xb8
Read of size 4 at addr ffff00000a394a28 by task mmc/180
CPU: 2 PID: 180 Comm: mmc Not tainted 5.10.0-rc4-00069-gcc758c8c7127-dirty #5
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Call trace:
dump_backtrace+0x0/0x2b4
show_stack+0x18/0x6c
dump_stack+0xfc/0x168
print_address_description.constprop.0+0x6c/0x488
kasan_report+0x118/0x210
__asan_load4+0x94/0xd0
mmc_blk_get+0x58/0xb8
mmc_blk_open+0x7c/0xdc
__blkdev_get+0x3b4/0x964
blkdev_get+0x64/0x100
blkdev_open+0xe8/0x104
do_dentry_open+0x234/0x61c
vfs_open+0x54/0x64
path_openat+0xe04/0x1584
do_filp_open+0xe8/0x1e4
do_sys_openat2+0x120/0x230
__arm64_sys_openat+0xf0/0x15c
el0_svc_common.constprop.0+0xac/0x234
do_el0_svc+0x84/0xa0
el0_sync_handler+0x264/0x270
el0_sync+0x174/0x180
Allocated by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
__kasan_kmalloc.constprop.0+0xc8/0xf0
kasan_kmalloc+0x10/0x20
mmc_blk_alloc_req+0x94/0x4b0
mmc_blk_probe+0x2d4/0xaa4
mmc_bus_probe+0x34/0x4c
really_probe+0x148/0x6e0
driver_probe_device+0x78/0xec
__device_attach_driver+0x108/0x16c
bus_for_each_drv+0xf4/0x15c
__device_attach+0x168/0x240
device_initial_probe+0x14/0x20
bus_probe_device+0xec/0x100
device_add+0x55c/0xaf0
mmc_add_card+0x288/0x380
mmc_attach_sd+0x18c/0x22c
mmc_rescan+0x444/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
Freed by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
kasan_set_track+0x28/0x40
kasan_set_free_info+0x24/0x4c
__kasan_slab_free+0x100/0x180
kasan_slab_free+0x14/0x20
kfree+0xb8/0x46c
mmc_blk_put+0xe4/0x11c
mmc_blk_remove_req.part.0+0x6c/0xe4
mmc_blk_remove+0x368/0x370
mmc_bus_remove+0x34/0x50
__device_release_driver+0x228/0x31c
device_release_driver+0x2c/0x44
bus_remove_device+0x1e4/0x200
device_del+0x2b0/0x770
mmc_remove_card+0xf0/0x150
mmc_sd_detect+0x9c/0x150
mmc_rescan+0x110/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
The buggy address belongs to the object at ffff00000a394800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 552 bytes inside of
1024-byte region [ffff00000a394800, ffff00000a394c00)
The buggy address belongs to the page:
page:00000000ff84ed53 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8a390
head:00000000ff84ed53 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x3fffc0000010200(slab|head)
raw: 03fffc0000010200 dead000000000100 dead000000000122 ffff000009f03800
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff00000a394900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff00000a394a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff00000a394a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Looking closer at the problem, it looks like a classic dangling pointer
bug. The 'struct mmc_blk_data' that is used after being freed in
mmc_blk_put() is stashed away in 'md->disk->private_data' via
mmc_blk_alloc_req() but used in mmc_blk_get() because the 'usage' count
isn't properly aligned with the lifetime of the pointer. You'd expect
the 'usage' member to be in sync with the kfree(), and it mostly is,
except that mmc_blk_get() needs to dereference the potentially freed
memory storage for the 'struct mmc_blk_data' stashed away in the
private_data member to look at 'usage' before it actually figures out if
it wants to consider it a valid pointer or not. That's not going to work
if the freed memory has been overwritten by something else after the
free, and KASAN rightly complains here.
To fix the immediate problem, let's set the private_data member to NULL
in mmc_blk_put() so that mmc_blk_get() can consider the object "on the
way out" if the pointer is NULL and not even try to look at 'usage' if
the object isn't going to be around much longer. With that set to NULL
on the last mmc_blk_put(), optimize the get path further and use a kref
underneath the 'open_lock' mutex to only up the reference count if it's
non-zero, i.e. alive, and otherwise make mmc_blk_get() return NULL,
without actually testing the reference count if we're in the process of
removing the object from the system.
Finally, tighten the locking region on the put side to only be around
the parts that are removing the 'mmc_blk_data' from the system and
publishing that fact to the gendisk and then drop the lock as soon as we
can to avoid holding the lock around code that doesn't need it. This
fixes the KASAN issue.
Cc: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Cc: Sujit Kautkar <sujitka@chromium.org>
Cc: Zubin Mithra <zsm@chromium.org>
Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/linux-mmc/CAPDyKFryT63Jc7+DXWSpAC19qpZRqFr1orxwYGMuSqx247O8cQ@mail.gmail.com/ [1]
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20210623075002.1746924-2-swboyd@chromium.org
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2021-06-23 15:50:01 +08:00
|
|
|
devidx = mmc_get_devidx(md->disk);
|
|
|
|
ida_simple_remove(&mmc_blk_ida, devidx);
|
|
|
|
|
|
|
|
mutex_lock(&open_lock);
|
|
|
|
md->disk->private_data = NULL;
|
2006-01-13 02:43:35 +08:00
|
|
|
mutex_unlock(&open_lock);
|
mmc: core: Use kref in place of struct mmc_blk_data::usage
Ulf reported the following KASAN splat after adding some manual hacks
into mmc-utils[1].
DEBUG: mmc_blk_open: Let's sleep for 10s..
mmc1: card 0007 removed
BUG: KASAN: use-after-free in mmc_blk_get+0x58/0xb8
Read of size 4 at addr ffff00000a394a28 by task mmc/180
CPU: 2 PID: 180 Comm: mmc Not tainted 5.10.0-rc4-00069-gcc758c8c7127-dirty #5
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Call trace:
dump_backtrace+0x0/0x2b4
show_stack+0x18/0x6c
dump_stack+0xfc/0x168
print_address_description.constprop.0+0x6c/0x488
kasan_report+0x118/0x210
__asan_load4+0x94/0xd0
mmc_blk_get+0x58/0xb8
mmc_blk_open+0x7c/0xdc
__blkdev_get+0x3b4/0x964
blkdev_get+0x64/0x100
blkdev_open+0xe8/0x104
do_dentry_open+0x234/0x61c
vfs_open+0x54/0x64
path_openat+0xe04/0x1584
do_filp_open+0xe8/0x1e4
do_sys_openat2+0x120/0x230
__arm64_sys_openat+0xf0/0x15c
el0_svc_common.constprop.0+0xac/0x234
do_el0_svc+0x84/0xa0
el0_sync_handler+0x264/0x270
el0_sync+0x174/0x180
Allocated by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
__kasan_kmalloc.constprop.0+0xc8/0xf0
kasan_kmalloc+0x10/0x20
mmc_blk_alloc_req+0x94/0x4b0
mmc_blk_probe+0x2d4/0xaa4
mmc_bus_probe+0x34/0x4c
really_probe+0x148/0x6e0
driver_probe_device+0x78/0xec
__device_attach_driver+0x108/0x16c
bus_for_each_drv+0xf4/0x15c
__device_attach+0x168/0x240
device_initial_probe+0x14/0x20
bus_probe_device+0xec/0x100
device_add+0x55c/0xaf0
mmc_add_card+0x288/0x380
mmc_attach_sd+0x18c/0x22c
mmc_rescan+0x444/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
Freed by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
kasan_set_track+0x28/0x40
kasan_set_free_info+0x24/0x4c
__kasan_slab_free+0x100/0x180
kasan_slab_free+0x14/0x20
kfree+0xb8/0x46c
mmc_blk_put+0xe4/0x11c
mmc_blk_remove_req.part.0+0x6c/0xe4
mmc_blk_remove+0x368/0x370
mmc_bus_remove+0x34/0x50
__device_release_driver+0x228/0x31c
device_release_driver+0x2c/0x44
bus_remove_device+0x1e4/0x200
device_del+0x2b0/0x770
mmc_remove_card+0xf0/0x150
mmc_sd_detect+0x9c/0x150
mmc_rescan+0x110/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
The buggy address belongs to the object at ffff00000a394800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 552 bytes inside of
1024-byte region [ffff00000a394800, ffff00000a394c00)
The buggy address belongs to the page:
page:00000000ff84ed53 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8a390
head:00000000ff84ed53 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x3fffc0000010200(slab|head)
raw: 03fffc0000010200 dead000000000100 dead000000000122 ffff000009f03800
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff00000a394900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff00000a394a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff00000a394a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Looking closer at the problem, it looks like a classic dangling pointer
bug. The 'struct mmc_blk_data' that is used after being freed in
mmc_blk_put() is stashed away in 'md->disk->private_data' via
mmc_blk_alloc_req() but used in mmc_blk_get() because the 'usage' count
isn't properly aligned with the lifetime of the pointer. You'd expect
the 'usage' member to be in sync with the kfree(), and it mostly is,
except that mmc_blk_get() needs to dereference the potentially freed
memory storage for the 'struct mmc_blk_data' stashed away in the
private_data member to look at 'usage' before it actually figures out if
it wants to consider it a valid pointer or not. That's not going to work
if the freed memory has been overwritten by something else after the
free, and KASAN rightly complains here.
To fix the immediate problem, let's set the private_data member to NULL
in mmc_blk_put() so that mmc_blk_get() can consider the object "on the
way out" if the pointer is NULL and not even try to look at 'usage' if
the object isn't going to be around much longer. With that set to NULL
on the last mmc_blk_put(), optimize the get path further and use a kref
underneath the 'open_lock' mutex to only up the reference count if it's
non-zero, i.e. alive, and otherwise make mmc_blk_get() return NULL,
without actually testing the reference count if we're in the process of
removing the object from the system.
Finally, tighten the locking region on the put side to only be around
the parts that are removing the 'mmc_blk_data' from the system and
publishing that fact to the gendisk and then drop the lock as soon as we
can to avoid holding the lock around code that doesn't need it. This
fixes the KASAN issue.
Cc: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Cc: Sujit Kautkar <sujitka@chromium.org>
Cc: Zubin Mithra <zsm@chromium.org>
Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/linux-mmc/CAPDyKFryT63Jc7+DXWSpAC19qpZRqFr1orxwYGMuSqx247O8cQ@mail.gmail.com/ [1]
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20210623075002.1746924-2-swboyd@chromium.org
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2021-06-23 15:50:01 +08:00
|
|
|
|
|
|
|
put_disk(md->disk);
|
|
|
|
kfree(md);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_put(struct mmc_blk_data *md)
|
|
|
|
{
|
|
|
|
kref_put(&md->kref, mmc_blk_kref_release);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2011-12-02 15:51:06 +08: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 21:50:45 +08:00
|
|
|
mmc_blk_put(md);
|
|
|
|
|
2011-12-02 15:51:06 +08: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 21:37:30 +08:00
|
|
|
struct mmc_queue *mq;
|
|
|
|
struct request *req;
|
2011-12-02 15:51:06 +08: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 21:37:30 +08:00
|
|
|
mq = &md->queue;
|
2011-12-02 15:51:06 +08:00
|
|
|
|
2017-05-19 21:37:30 +08:00
|
|
|
/* Dispatch locking to the block layer */
|
2021-10-25 15:05:07 +08:00
|
|
|
req = blk_mq_alloc_request(mq->queue, REQ_OP_DRV_OUT, 0);
|
2017-11-21 21:42:28 +08:00
|
|
|
if (IS_ERR(req)) {
|
|
|
|
count = PTR_ERR(req);
|
|
|
|
goto out_put;
|
|
|
|
}
|
2017-05-19 21:37:30 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP;
|
2023-04-27 00:59:39 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_result = -EIO;
|
2021-11-26 20:18:01 +08:00
|
|
|
blk_execute_rq(req, false);
|
2017-05-19 21:37:30 +08:00
|
|
|
ret = req_to_mmc_queue_req(req)->drv_op_result;
|
2021-10-25 15:05:07 +08:00
|
|
|
blk_mq_free_request(req);
|
2011-12-02 15:51:06 +08: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 21:42:28 +08:00
|
|
|
out_put:
|
2011-12-02 15:51:06 +08:00
|
|
|
mmc_blk_put(md);
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2021-08-09 14:40:21 +08:00
|
|
|
static DEVICE_ATTR(ro_lock_until_next_power_on, 0,
|
|
|
|
power_ro_lock_show, power_ro_lock_store);
|
|
|
|
|
2011-04-12 07:10:25 +08: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 15:12:51 +08:00
|
|
|
ret = snprintf(buf, PAGE_SIZE, "%d\n",
|
2011-04-12 07:10:25 +08: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;
|
|
|
|
}
|
|
|
|
|
2021-08-09 14:40:21 +08:00
|
|
|
static DEVICE_ATTR(force_ro, 0644, force_ro_show, force_ro_store);
|
|
|
|
|
|
|
|
static struct attribute *mmc_disk_attrs[] = {
|
|
|
|
&dev_attr_force_ro.attr,
|
|
|
|
&dev_attr_ro_lock_until_next_power_on.attr,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
static umode_t mmc_disk_attrs_is_visible(struct kobject *kobj,
|
|
|
|
struct attribute *a, int n)
|
|
|
|
{
|
2022-04-25 18:53:39 +08:00
|
|
|
struct device *dev = kobj_to_dev(kobj);
|
2021-08-09 14:40:21 +08:00
|
|
|
struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
|
|
|
|
umode_t mode = a->mode;
|
|
|
|
|
|
|
|
if (a == &dev_attr_ro_lock_until_next_power_on.attr &&
|
|
|
|
(md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
|
|
|
|
md->queue.card->ext_csd.boot_ro_lockable) {
|
|
|
|
mode = S_IRUGO;
|
|
|
|
if (!(md->queue.card->ext_csd.boot_ro_lock &
|
|
|
|
EXT_CSD_BOOT_WP_B_PWR_WP_DIS))
|
|
|
|
mode |= S_IWUSR;
|
|
|
|
}
|
|
|
|
|
|
|
|
mmc_blk_put(md);
|
|
|
|
return mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct attribute_group mmc_disk_attr_group = {
|
|
|
|
.is_visible = mmc_disk_attrs_is_visible,
|
|
|
|
.attrs = mmc_disk_attrs,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct attribute_group *mmc_disk_attr_groups[] = {
|
|
|
|
&mmc_disk_attr_group,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
2008-03-02 23:33:30 +08:00
|
|
|
static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2008-03-02 23:33:30 +08:00
|
|
|
struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
|
2005-04-17 06:20:36 +08:00
|
|
|
int ret = -ENXIO;
|
|
|
|
|
2010-06-02 20:28:52 +08:00
|
|
|
mutex_lock(&block_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (md) {
|
|
|
|
ret = 0;
|
2008-03-02 23:33:30 +08:00
|
|
|
if ((mode & FMODE_WRITE) && md->read_only) {
|
2008-09-06 05:00:24 +08:00
|
|
|
mmc_blk_put(md);
|
2005-09-07 06:18:52 +08:00
|
|
|
ret = -EROFS;
|
2008-09-06 05:00:24 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2010-06-02 20:28:52 +08:00
|
|
|
mutex_unlock(&block_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-05-06 09:52:57 +08:00
|
|
|
static void mmc_blk_release(struct gendisk *disk, fmode_t mode)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2008-03-02 23:33:30 +08:00
|
|
|
struct mmc_blk_data *md = disk->private_data;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-06-02 20:28:52 +08:00
|
|
|
mutex_lock(&block_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
mmc_blk_put(md);
|
2010-06-02 20:28:52 +08:00
|
|
|
mutex_unlock(&block_mutex);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-01-08 17:02:50 +08:00
|
|
|
mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-01-08 17:02:50 +08:00
|
|
|
geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
|
|
|
|
geo->heads = 4;
|
|
|
|
geo->sectors = 16;
|
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2011-04-27 06:56:29 +08: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 16:02:00 +08:00
|
|
|
struct mmc_rpmb_data *rpmb;
|
2011-04-27 06:56:29 +08: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 19:27:11 +08:00
|
|
|
idata = kmalloc(sizeof(*idata), GFP_KERNEL);
|
2011-04-27 06:56:29 +08:00
|
|
|
if (!idata) {
|
|
|
|
err = -ENOMEM;
|
2011-05-11 12:00:43 +08:00
|
|
|
goto out;
|
2011-04-27 06:56:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) {
|
|
|
|
err = -EFAULT;
|
2011-05-11 12:00:43 +08:00
|
|
|
goto idata_err;
|
2011-04-27 06:56:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks;
|
|
|
|
if (idata->buf_bytes > MMC_IOC_MAX_BYTES) {
|
|
|
|
err = -EOVERFLOW;
|
2011-05-11 12:00:43 +08:00
|
|
|
goto idata_err;
|
2011-04-27 06:56:29 +08:00
|
|
|
}
|
|
|
|
|
2016-07-08 23:27:02 +08:00
|
|
|
if (!idata->buf_bytes) {
|
|
|
|
idata->buf = NULL;
|
2011-11-23 16:05:58 +08:00
|
|
|
return idata;
|
2016-07-08 23:27:02 +08:00
|
|
|
}
|
2011-11-23 16:05:58 +08:00
|
|
|
|
2018-03-05 18:33:21 +08: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 12:00:43 +08:00
|
|
|
goto idata_err;
|
2011-04-27 06:56:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return idata;
|
|
|
|
|
2011-05-11 12:00:43 +08:00
|
|
|
idata_err:
|
2011-04-27 06:56:29 +08:00
|
|
|
kfree(idata);
|
2011-05-11 12:00:43 +08:00
|
|
|
out:
|
2011-04-27 06:56:29 +08:00
|
|
|
return ERR_PTR(err);
|
|
|
|
}
|
|
|
|
|
2015-09-22 17:27:53 +08: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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
|
|
|
|
struct mmc_blk_ioc_data *idata)
|
2011-04-27 06:56:29 +08:00
|
|
|
{
|
2018-11-26 21:38:13 +08:00
|
|
|
struct mmc_command cmd = {}, sbc = {};
|
2016-12-19 19:51:18 +08:00
|
|
|
struct mmc_data data = {};
|
|
|
|
struct mmc_request mrq = {};
|
2011-04-27 06:56:29 +08:00
|
|
|
struct scatterlist sg;
|
2023-02-13 21:37:07 +08:00
|
|
|
bool r1b_resp, use_r1b_resp = false;
|
|
|
|
unsigned int busy_timeout_ms;
|
2011-04-27 06:56:29 +08:00
|
|
|
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 16:02:00 +08:00
|
|
|
unsigned int target_part;
|
2011-04-27 06:56:29 +08:00
|
|
|
|
2015-09-22 17:27:53 +08:00
|
|
|
if (!card || !md || !idata)
|
|
|
|
return -EINVAL;
|
2011-04-27 06:56:29 +08: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 16:02:00 +08: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 23:12:31 +08:00
|
|
|
|
2011-11-23 16:05:58 +08: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;
|
|
|
|
|
|
|
|
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 16:02:00 +08:00
|
|
|
err = mmc_blk_part_switch(card, target_part);
|
2012-08-06 23:12:31 +08:00
|
|
|
if (err)
|
2015-09-22 17:27:53 +08:00
|
|
|
return err;
|
2012-08-06 23:12:31 +08:00
|
|
|
|
2011-04-27 06:56:29 +08:00
|
|
|
if (idata->ic.is_acmd) {
|
|
|
|
err = mmc_app_cmd(card->host, card);
|
|
|
|
if (err)
|
2015-09-22 17:27:53 +08:00
|
|
|
return err;
|
2011-04-27 06:56:29 +08: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 16:02:00 +08:00
|
|
|
if (idata->rpmb) {
|
2018-11-26 21:38:13 +08: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 23:12:31 +08:00
|
|
|
}
|
|
|
|
|
2013-06-05 19:13:08 +08:00
|
|
|
if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
|
2020-03-16 23:21:52 +08:00
|
|
|
(cmd.opcode == MMC_SWITCH))
|
2021-04-02 17:24:31 +08:00
|
|
|
return mmc_sanitize(card, idata->ic.cmd_timeout_ms);
|
2013-04-18 20:41:55 +08:00
|
|
|
|
2023-02-13 21:37:07 +08:00
|
|
|
/* If it's an R1B response we need some more preparations. */
|
|
|
|
busy_timeout_ms = idata->ic.cmd_timeout_ms ? : MMC_BLK_TIMEOUT_MS;
|
|
|
|
r1b_resp = (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B;
|
|
|
|
if (r1b_resp)
|
|
|
|
use_r1b_resp = mmc_prepare_busy_cmd(card->host, &cmd,
|
|
|
|
busy_timeout_ms);
|
|
|
|
|
2011-04-27 06:56:29 +08:00
|
|
|
mmc_wait_for_req(card->host, &mrq);
|
mmc: core: Return correct emmc response in case of ioctl error
When a read/write command is sent via ioctl to the kernel,
and the command fails, the actual error response of the emmc
is not sent to the user.
IOCTL read/write tests are carried out using commands
17 (Single BLock Read), 24 (Single Block Write),
18 (Multi Block Read), 25 (Multi Block Write)
The tests are carried out on a 64Gb emmc device. All of these
tests try to access an "out of range" sector address (0x09B2FFFF).
It is seen that without the patch the response received by the user
is not OUT_OF_RANGE error (R1 response 31st bit is not set) as per
JEDEC specification. After applying the patch proper response is seen.
This is because the function returns without copying the response to
the user in case of failure. This patch fixes the issue.
Hence, this memcpy is required whether we get an error response or not.
Therefor it is moved up from the current position up to immediately
after we have called mmc_wait_for_req().
The test code and the output of only the CMD17 is included in the
commit to limit the message length.
CMD17 (Test Code Snippet):
==========================
printf("Forming CMD%d\n", opt_idx);
/* single block read */
cmd.blksz = 512;
cmd.blocks = 1;
cmd.write_flag = 0;
cmd.opcode = 17;
//cmd.arg = atoi(argv[3]);
cmd.arg = 0x09B2FFFF;
/* Expecting response R1B */
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
memset(data, 0, sizeof(__u8) * 512);
mmc_ioc_cmd_set_data(cmd, data);
printf("Sending CMD%d: ARG[0x%08x]\n", opt_idx, cmd.arg);
if(ioctl(fd, MMC_IOC_CMD, &cmd))
perror("Error");
printf("\nResponse: %08x\n", cmd.response[0]);
CMD17 (Output without patch):
=============================
test@test-LIVA-Z:~$ sudo ./mmc cmd_test /dev/mmcblk0 17
Entering the do_mmc_commands:Device: /dev/mmcblk0 nargs:4
Entering the do_mmc_commands:Device: /dev/mmcblk0 options[17, 0x09B2FFF]
Forming CMD17
Sending CMD17: ARG[0x09b2ffff]
Error: Connection timed out
Response: 00000000
(Incorrect response)
CMD17 (Output with patch):
==========================
test@test-LIVA-Z:~$ sudo ./mmc cmd_test /dev/mmcblk0 17
[sudo] password for test:
Entering the do_mmc_commands:Device: /dev/mmcblk0 nargs:4
Entering the do_mmc_commands:Device: /dev/mmcblk0 options[17, 09B2FFFF]
Forming CMD17
Sending CMD17: ARG[0x09b2ffff]
Error: Connection timed out
Response: 80000900
(Correct OUT_OF_ERROR response as per JEDEC specification)
Signed-off-by: Nishad Kamdar <nishadkamdar@gmail.com>
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Link: https://lore.kernel.org/r/20210824191726.8296-1-nishadkamdar@gmail.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2021-08-25 03:17:26 +08:00
|
|
|
memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp));
|
2011-04-27 06:56:29 +08:00
|
|
|
|
|
|
|
if (cmd.error) {
|
|
|
|
dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
|
|
|
|
__func__, cmd.error);
|
2015-09-22 17:27:53 +08:00
|
|
|
return cmd.error;
|
2011-04-27 06:56:29 +08:00
|
|
|
}
|
|
|
|
if (data.error) {
|
|
|
|
dev_err(mmc_dev(card->host), "%s: data error %d\n",
|
|
|
|
__func__, data.error);
|
2015-09-22 17:27:53 +08:00
|
|
|
return data.error;
|
2011-04-27 06:56:29 +08:00
|
|
|
}
|
|
|
|
|
2018-03-08 22:08:11 +08: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;
|
|
|
|
}
|
|
|
|
|
2021-04-20 21:46:41 +08:00
|
|
|
/*
|
|
|
|
* Make sure to update CACHE_CTRL in case it was changed. The cache
|
|
|
|
* will get turned back on if the card is re-initialized, e.g.
|
|
|
|
* suspend/resume or hw reset in recovery.
|
|
|
|
*/
|
|
|
|
if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_CACHE_CTRL) &&
|
|
|
|
(cmd.opcode == MMC_SWITCH)) {
|
|
|
|
u8 value = MMC_EXTRACT_VALUE_FROM_ARG(cmd.arg) & 1;
|
|
|
|
|
|
|
|
card->ext_csd.cache_ctrl = value;
|
|
|
|
}
|
|
|
|
|
2011-04-27 06:56:29 +08: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);
|
|
|
|
|
2023-02-13 21:37:07 +08:00
|
|
|
/* No need to poll when using HW busy detection. */
|
|
|
|
if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Ensure RPMB/R1B command has completed by polling with CMD13. */
|
|
|
|
if (idata->rpmb || r1b_resp)
|
|
|
|
err = mmc_poll_for_busy(card, busy_timeout_ms, false,
|
|
|
|
MMC_BUSY_IO);
|
2012-08-06 23:12:31 +08:00
|
|
|
|
2015-09-22 17:27:53 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2017-08-21 05:39:11 +08: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 16:02:00 +08:00
|
|
|
struct mmc_ioc_cmd __user *ic_ptr,
|
|
|
|
struct mmc_rpmb_data *rpmb)
|
2015-09-22 17:27:53 +08:00
|
|
|
{
|
|
|
|
struct mmc_blk_ioc_data *idata;
|
2017-05-18 17:29:35 +08:00
|
|
|
struct mmc_blk_ioc_data *idatas[1];
|
2017-05-18 17:29:34 +08:00
|
|
|
struct mmc_queue *mq;
|
2015-09-22 17:27:53 +08:00
|
|
|
struct mmc_card *card;
|
2015-09-24 09:30:33 +08:00
|
|
|
int err = 0, ioc_err = 0;
|
2017-05-18 17:29:34 +08:00
|
|
|
struct request *req;
|
2015-09-22 17:27:53 +08: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 16:02:00 +08:00
|
|
|
/* This will be NULL on non-RPMB ioctl():s */
|
|
|
|
idata->rpmb = rpmb;
|
2015-09-22 17:27:53 +08:00
|
|
|
|
|
|
|
card = md->queue.card;
|
|
|
|
if (IS_ERR(card)) {
|
|
|
|
err = PTR_ERR(card);
|
|
|
|
goto cmd_done;
|
|
|
|
}
|
|
|
|
|
2017-05-18 17:29:34 +08:00
|
|
|
/*
|
|
|
|
* Dispatch the ioctl() into the block request queue.
|
|
|
|
*/
|
|
|
|
mq = &md->queue;
|
2021-10-25 15:05:07 +08:00
|
|
|
req = blk_mq_alloc_request(mq->queue,
|
2018-05-09 15:54:05 +08:00
|
|
|
idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
|
2017-11-21 21:42:28 +08:00
|
|
|
if (IS_ERR(req)) {
|
|
|
|
err = PTR_ERR(req);
|
|
|
|
goto cmd_done;
|
|
|
|
}
|
2017-05-18 17:29:35 +08: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 16:02:00 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op =
|
|
|
|
rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
|
2023-04-27 00:59:39 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_result = -EIO;
|
2017-08-21 05:39:06 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_data = idatas;
|
2017-05-18 17:29:35 +08:00
|
|
|
req_to_mmc_queue_req(req)->ioc_count = 1;
|
2021-11-26 20:18:01 +08:00
|
|
|
blk_execute_rq(req, false);
|
2017-05-19 21:37:30 +08:00
|
|
|
ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
|
2015-09-24 09:30:33 +08:00
|
|
|
err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
|
2021-10-25 15:05:07 +08:00
|
|
|
blk_mq_free_request(req);
|
2015-09-22 17:27:53 +08:00
|
|
|
|
2011-04-27 06:56:29 +08:00
|
|
|
cmd_done:
|
|
|
|
kfree(idata->buf);
|
|
|
|
kfree(idata);
|
2015-09-24 09:30:33 +08:00
|
|
|
return ioc_err ? ioc_err : err;
|
2011-04-27 06:56:29 +08:00
|
|
|
}
|
|
|
|
|
2017-08-21 05:39:11 +08: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 16:02:00 +08:00
|
|
|
struct mmc_ioc_multi_cmd __user *user,
|
|
|
|
struct mmc_rpmb_data *rpmb)
|
2015-09-22 17:27:53 +08:00
|
|
|
{
|
|
|
|
struct mmc_blk_ioc_data **idata = NULL;
|
|
|
|
struct mmc_ioc_cmd __user *cmds = user->cmds;
|
|
|
|
struct mmc_card *card;
|
2017-05-18 17:29:35 +08:00
|
|
|
struct mmc_queue *mq;
|
2022-03-31 05:09:07 +08:00
|
|
|
int err = 0, ioc_err = 0;
|
2015-09-22 17:27:53 +08:00
|
|
|
__u64 num_of_cmds;
|
2022-03-31 05:09:07 +08:00
|
|
|
unsigned int i, n;
|
2017-05-18 17:29:35 +08:00
|
|
|
struct request *req;
|
2015-09-22 17:27:53 +08:00
|
|
|
|
|
|
|
if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
|
|
|
|
sizeof(num_of_cmds)))
|
|
|
|
return -EFAULT;
|
|
|
|
|
2017-07-05 23:09:42 +08:00
|
|
|
if (!num_of_cmds)
|
|
|
|
return 0;
|
|
|
|
|
2015-09-22 17:27:53 +08:00
|
|
|
if (num_of_cmds > MMC_IOC_MAX_CMDS)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2022-03-31 05:09:07 +08:00
|
|
|
n = num_of_cmds;
|
|
|
|
idata = kcalloc(n, sizeof(*idata), GFP_KERNEL);
|
2015-09-22 17:27:53 +08:00
|
|
|
if (!idata)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2022-03-31 05:09:07 +08:00
|
|
|
for (i = 0; i < n; i++) {
|
2015-09-22 17:27:53 +08:00
|
|
|
idata[i] = mmc_blk_ioctl_copy_from_user(&cmds[i]);
|
|
|
|
if (IS_ERR(idata[i])) {
|
|
|
|
err = PTR_ERR(idata[i]);
|
2022-03-31 05:09:07 +08:00
|
|
|
n = i;
|
2015-09-22 17:27:53 +08:00
|
|
|
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 16:02:00 +08:00
|
|
|
/* This will be NULL on non-RPMB ioctl():s */
|
|
|
|
idata[i]->rpmb = rpmb;
|
2015-09-22 17:27:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
card = md->queue.card;
|
|
|
|
if (IS_ERR(card)) {
|
|
|
|
err = PTR_ERR(card);
|
2017-08-21 05:39:11 +08:00
|
|
|
goto cmd_err;
|
2015-09-22 17:27:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-18 17:29:35 +08:00
|
|
|
/*
|
|
|
|
* Dispatch the ioctl()s into the block request queue.
|
|
|
|
*/
|
|
|
|
mq = &md->queue;
|
2021-10-25 15:05:07 +08:00
|
|
|
req = blk_mq_alloc_request(mq->queue,
|
2018-05-09 15:54:05 +08:00
|
|
|
idata[0]->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
|
2017-11-21 21:42:28 +08: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 16:02:00 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op =
|
|
|
|
rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
|
2023-04-27 00:59:39 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_result = -EIO;
|
2017-08-21 05:39:06 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_data = idata;
|
2022-03-31 05:09:07 +08:00
|
|
|
req_to_mmc_queue_req(req)->ioc_count = n;
|
2021-11-26 20:18:01 +08:00
|
|
|
blk_execute_rq(req, false);
|
2017-05-19 21:37:30 +08:00
|
|
|
ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
|
2015-09-22 17:27:53 +08:00
|
|
|
|
|
|
|
/* copy to user if data and response */
|
2022-03-31 05:09:07 +08:00
|
|
|
for (i = 0; i < n && !err; i++)
|
2015-09-22 17:27:53 +08:00
|
|
|
err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
|
|
|
|
|
2021-10-25 15:05:07 +08:00
|
|
|
blk_mq_free_request(req);
|
2017-05-18 17:29:35 +08:00
|
|
|
|
2015-09-22 17:27:53 +08:00
|
|
|
cmd_err:
|
2022-03-31 05:09:07 +08:00
|
|
|
for (i = 0; i < n; i++) {
|
2015-09-22 17:27:53 +08:00
|
|
|
kfree(idata[i]->buf);
|
|
|
|
kfree(idata[i]);
|
|
|
|
}
|
|
|
|
kfree(idata);
|
2015-09-24 09:30:33 +08:00
|
|
|
return ioc_err ? ioc_err : err;
|
2015-09-22 17:27:53 +08:00
|
|
|
}
|
|
|
|
|
2017-08-21 05:39:09 +08: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 13:40:57 +08:00
|
|
|
if (!capable(CAP_SYS_RAWIO) || bdev_is_partition(bdev))
|
2017-08-21 05:39:09 +08:00
|
|
|
return -EPERM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-27 06:56:29 +08:00
|
|
|
static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
|
|
|
|
unsigned int cmd, unsigned long arg)
|
|
|
|
{
|
2017-08-21 05:39:11 +08:00
|
|
|
struct mmc_blk_data *md;
|
2017-08-21 05:39:09 +08:00
|
|
|
int ret;
|
|
|
|
|
2015-09-22 17:27:53 +08:00
|
|
|
switch (cmd) {
|
|
|
|
case MMC_IOC_CMD:
|
2017-08-21 05:39:09 +08:00
|
|
|
ret = mmc_blk_check_blkdev(bdev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2017-08-21 05:39:11 +08: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 16:02:00 +08:00
|
|
|
(struct mmc_ioc_cmd __user *)arg,
|
|
|
|
NULL);
|
2017-08-21 05:39:11 +08:00
|
|
|
mmc_blk_put(md);
|
|
|
|
return ret;
|
2015-09-22 17:27:53 +08:00
|
|
|
case MMC_IOC_MULTI_CMD:
|
2017-08-21 05:39:09 +08:00
|
|
|
ret = mmc_blk_check_blkdev(bdev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2017-08-21 05:39:11 +08: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 16:02:00 +08:00
|
|
|
(struct mmc_ioc_multi_cmd __user *)arg,
|
|
|
|
NULL);
|
2017-08-21 05:39:11 +08:00
|
|
|
mmc_blk_put(md);
|
|
|
|
return ret;
|
2015-09-22 17:27:53 +08:00
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2011-04-27 06:56:29 +08: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
|
|
|
|
|
2021-08-20 08:45:35 +08:00
|
|
|
static int mmc_blk_alternative_gpt_sector(struct gendisk *disk,
|
|
|
|
sector_t *sector)
|
|
|
|
{
|
|
|
|
struct mmc_blk_data *md;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
md = mmc_blk_get(disk);
|
|
|
|
if (!md)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (md->queue.card)
|
|
|
|
ret = mmc_card_alternative_gpt_sector(md->queue.card, sector);
|
|
|
|
else
|
|
|
|
ret = -ENODEV;
|
|
|
|
|
|
|
|
mmc_blk_put(md);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-09-22 08:01:13 +08:00
|
|
|
static const struct block_device_operations mmc_bdops = {
|
2008-03-02 23:33:30 +08:00
|
|
|
.open = mmc_blk_open,
|
|
|
|
.release = mmc_blk_release,
|
2006-01-08 17:02:50 +08:00
|
|
|
.getgeo = mmc_blk_getgeo,
|
2005-04-17 06:20:36 +08:00
|
|
|
.owner = THIS_MODULE,
|
2011-04-27 06:56:29 +08:00
|
|
|
.ioctl = mmc_blk_ioctl,
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
.compat_ioctl = mmc_blk_compat_ioctl,
|
|
|
|
#endif
|
2021-08-20 08:45:35 +08:00
|
|
|
.alternative_gpt_sector = mmc_blk_alternative_gpt_sector,
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
2017-03-13 20:36:39 +08: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 07:10:25 +08:00
|
|
|
static inline int mmc_blk_part_switch(struct mmc_card *card,
|
2017-08-21 05:39:10 +08:00
|
|
|
unsigned int part_type)
|
2011-04-12 07:10:25 +08:00
|
|
|
{
|
2017-03-13 20:36:39 +08:00
|
|
|
int ret = 0;
|
2014-10-06 20:34:09 +08:00
|
|
|
struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
|
2011-09-23 17:48:20 +08:00
|
|
|
|
2017-08-21 05:39:10 +08:00
|
|
|
if (main_md->part_curr == part_type)
|
2011-04-12 07:10:25 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (mmc_card_mmc(card)) {
|
2011-09-23 17:48:20 +08:00
|
|
|
u8 part_config = card->ext_csd.part_config;
|
|
|
|
|
2017-08-21 05:39:10 +08:00
|
|
|
ret = mmc_blk_part_switch_pre(card, part_type);
|
2017-03-13 20:36:39 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2016-05-04 19:38:13 +08:00
|
|
|
|
2011-09-23 17:48:20 +08:00
|
|
|
part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
|
2017-08-21 05:39:10 +08:00
|
|
|
part_config |= part_type;
|
2011-04-12 07:10:25 +08:00
|
|
|
|
|
|
|
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
2011-09-23 17:48:20 +08:00
|
|
|
EXT_CSD_PART_CONFIG, part_config,
|
2011-04-12 07:10:25 +08:00
|
|
|
card->ext_csd.part_time);
|
2016-05-04 19:38:13 +08:00
|
|
|
if (ret) {
|
2017-08-21 05:39:10 +08:00
|
|
|
mmc_blk_part_switch_post(card, part_type);
|
2011-04-12 07:10:25 +08:00
|
|
|
return ret;
|
2016-05-04 19:38:13 +08:00
|
|
|
}
|
2011-09-23 17:48:20 +08:00
|
|
|
|
|
|
|
card->ext_csd.part_config = part_config;
|
2016-05-04 19:38:13 +08:00
|
|
|
|
2017-03-13 20:36:39 +08:00
|
|
|
ret = mmc_blk_part_switch_post(card, main_md->part_curr);
|
2011-08-29 21:42:15 +08:00
|
|
|
}
|
2011-04-12 07:10:25 +08:00
|
|
|
|
2017-08-21 05:39:10 +08:00
|
|
|
main_md->part_curr = part_type;
|
2017-03-13 20:36:39 +08:00
|
|
|
return ret;
|
2011-04-12 07:10:25 +08:00
|
|
|
}
|
|
|
|
|
2017-02-01 20:47:57 +08:00
|
|
|
static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
|
2006-10-06 15:44:03 +08:00
|
|
|
{
|
|
|
|
int err;
|
2009-06-09 06:33:57 +08:00
|
|
|
u32 result;
|
|
|
|
__be32 *blocks;
|
2006-10-06 15:44:03 +08:00
|
|
|
|
2016-12-19 19:51:18 +08:00
|
|
|
struct mmc_request mrq = {};
|
|
|
|
struct mmc_command cmd = {};
|
|
|
|
struct mmc_data data = {};
|
2006-10-06 15:44:03 +08:00
|
|
|
|
|
|
|
struct scatterlist sg;
|
|
|
|
|
|
|
|
cmd.opcode = MMC_APP_CMD;
|
|
|
|
cmd.arg = card->rca << 16;
|
2007-08-09 00:10:23 +08:00
|
|
|
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
|
2006-10-06 15:44:03 +08:00
|
|
|
|
|
|
|
err = mmc_wait_for_cmd(card->host, &cmd, 0);
|
2007-08-09 00:10:23 +08:00
|
|
|
if (err)
|
2017-02-01 20:47:57 +08:00
|
|
|
return err;
|
2007-08-09 00:10:23 +08:00
|
|
|
if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
|
2017-02-01 20:47:57 +08:00
|
|
|
return -EIO;
|
2006-10-06 15:44:03 +08:00
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(struct mmc_command));
|
|
|
|
|
|
|
|
cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
|
|
|
|
cmd.arg = 0;
|
2007-08-09 00:10:23 +08:00
|
|
|
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
|
2006-10-06 15:44:03 +08:00
|
|
|
|
|
|
|
data.blksz = 4;
|
|
|
|
data.blocks = 1;
|
|
|
|
data.flags = MMC_DATA_READ;
|
|
|
|
data.sg = &sg;
|
|
|
|
data.sg_len = 1;
|
2012-06-13 19:40:43 +08:00
|
|
|
mmc_set_data_timeout(&data, card);
|
2006-10-06 15:44:03 +08:00
|
|
|
|
|
|
|
mrq.cmd = &cmd;
|
|
|
|
mrq.data = &data;
|
|
|
|
|
2009-06-09 06:33:57 +08:00
|
|
|
blocks = kmalloc(4, GFP_KERNEL);
|
|
|
|
if (!blocks)
|
2017-02-01 20:47:57 +08:00
|
|
|
return -ENOMEM;
|
2009-06-09 06:33:57 +08:00
|
|
|
|
|
|
|
sg_init_one(&sg, blocks, 4);
|
2006-10-06 15:44:03 +08:00
|
|
|
|
|
|
|
mmc_wait_for_req(card->host, &mrq);
|
|
|
|
|
2009-06-09 06:33:57 +08:00
|
|
|
result = ntohl(*blocks);
|
|
|
|
kfree(blocks);
|
|
|
|
|
2007-07-23 04:18:46 +08:00
|
|
|
if (cmd.error || data.error)
|
2017-02-01 20:47:57 +08:00
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
*written_blocks = result;
|
2006-10-06 15:44:03 +08:00
|
|
|
|
2017-02-01 20:47:57 +08:00
|
|
|
return 0;
|
2006-10-06 15:44:03 +08:00
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:13 +08: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;
|
|
|
|
}
|
|
|
|
|
2022-10-13 19:16:37 +08:00
|
|
|
/*
|
|
|
|
* Attempts to reset the card and get back to the requested partition.
|
|
|
|
* Therefore any error here must result in cancelling the block layer
|
|
|
|
* request, it must not be reattempted without going through the mmc_blk
|
|
|
|
* partition sanity checks.
|
|
|
|
*/
|
2011-08-29 21:42:15 +08:00
|
|
|
static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
|
|
|
|
int type)
|
|
|
|
{
|
|
|
|
int err;
|
2022-10-13 19:16:37 +08:00
|
|
|
struct mmc_blk_data *main_md = dev_get_drvdata(&host->card->dev);
|
2011-08-29 21:42:15 +08:00
|
|
|
|
|
|
|
if (md->reset_done & type)
|
|
|
|
return -EEXIST;
|
|
|
|
|
|
|
|
md->reset_done |= type;
|
2022-04-08 16:00:42 +08:00
|
|
|
err = mmc_hw_reset(host->card);
|
2022-10-13 19:16:37 +08:00
|
|
|
/*
|
|
|
|
* A successful reset will leave the card in the main partition, but
|
|
|
|
* upon failure it might not be, so set it to MMC_BLK_PART_INVALID
|
|
|
|
* in that case.
|
|
|
|
*/
|
|
|
|
main_md->part_curr = err ? MMC_BLK_PART_INVALID : main_md->part_type;
|
|
|
|
if (err)
|
|
|
|
return err;
|
2011-08-29 21:42:15 +08:00
|
|
|
/* Ensure we switch back to the correct partition */
|
2022-10-13 19:16:37 +08:00
|
|
|
if (mmc_blk_part_switch(host->card, md->part_type))
|
|
|
|
/*
|
|
|
|
* We have failed to get back into the correct
|
|
|
|
* partition, so we need to abort the whole request.
|
|
|
|
*/
|
|
|
|
return -ENODEV;
|
|
|
|
return 0;
|
2011-08-29 21:42:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
|
|
|
|
{
|
|
|
|
md->reset_done &= ~type;
|
|
|
|
}
|
|
|
|
|
2017-05-19 21:37:29 +08: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 05:39:06 +08: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 16:02:00 +08:00
|
|
|
bool rpmb_ioctl;
|
2017-08-21 05:39:08 +08:00
|
|
|
u8 **ext_csd;
|
|
|
|
u32 status;
|
2017-05-19 21:37:30 +08:00
|
|
|
int ret;
|
2017-05-19 21:37:29 +08: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 16:02:00 +08:00
|
|
|
rpmb_ioctl = (mq_rq->drv_op == MMC_DRV_OP_IOCTL_RPMB);
|
2017-05-19 21:37:29 +08:00
|
|
|
|
|
|
|
switch (mq_rq->drv_op) {
|
|
|
|
case MMC_DRV_OP_IOCTL:
|
2021-05-05 04:32:09 +08:00
|
|
|
if (card->ext_csd.cmdq_en) {
|
|
|
|
ret = mmc_cmdq_disable(card);
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fallthrough;
|
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 16:02:00 +08:00
|
|
|
case MMC_DRV_OP_IOCTL_RPMB:
|
2017-08-21 05:39:06 +08:00
|
|
|
idata = mq_rq->drv_op_data;
|
2017-07-05 23:09:41 +08:00
|
|
|
for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
|
2017-08-21 05:39:06 +08:00
|
|
|
ret = __mmc_blk_ioctl_cmd(card, md, idata[i]);
|
2017-05-19 21:37:30 +08:00
|
|
|
if (ret)
|
2017-05-19 21:37:29 +08: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 16:02:00 +08:00
|
|
|
if (rpmb_ioctl)
|
|
|
|
mmc_blk_part_switch(card, 0);
|
2021-05-05 04:32:09 +08:00
|
|
|
else if (card->reenable_cmdq && !card->ext_csd.cmdq_en)
|
|
|
|
mmc_cmdq_enable(card);
|
2017-05-19 21:37:30 +08: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 21:37:29 +08:00
|
|
|
break;
|
2017-08-21 05:39:08 +08: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 21:37:29 +08:00
|
|
|
default:
|
2017-05-19 21:37:30 +08:00
|
|
|
pr_err("%s: unknown driver specific operation\n",
|
|
|
|
md->disk->disk_name);
|
|
|
|
ret = -EINVAL;
|
2017-05-19 21:37:29 +08:00
|
|
|
break;
|
|
|
|
}
|
2017-05-19 21:37:30 +08:00
|
|
|
mq_rq->drv_op_result = ret;
|
2017-11-29 21:41:18 +08:00
|
|
|
blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK);
|
2017-05-19 21:37:29 +08:00
|
|
|
}
|
|
|
|
|
2022-04-29 23:21:18 +08:00
|
|
|
static void mmc_blk_issue_erase_rq(struct mmc_queue *mq, struct request *req,
|
|
|
|
int type, unsigned int erase_arg)
|
2010-08-12 05:17:47 +08:00
|
|
|
{
|
2016-11-18 20:36:15 +08:00
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
2010-08-12 05:17:47 +08:00
|
|
|
struct mmc_card *card = md->queue.card;
|
2019-02-06 19:28:05 +08:00
|
|
|
unsigned int from, nr;
|
2022-04-29 23:21:18 +08:00
|
|
|
int err = 0;
|
2017-06-03 15:38:04 +08:00
|
|
|
blk_status_t status = BLK_STS_OK;
|
2010-08-12 05:17:47 +08:00
|
|
|
|
|
|
|
if (!mmc_can_erase(card)) {
|
2017-06-03 15:38:04 +08:00
|
|
|
status = BLK_STS_NOTSUPP;
|
2016-12-19 22:03:44 +08:00
|
|
|
goto fail;
|
2010-08-12 05:17:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
from = blk_rq_pos(req);
|
|
|
|
nr = blk_rq_sectors(req);
|
|
|
|
|
2016-12-19 22:03:45 +08: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,
|
2022-04-29 23:21:18 +08:00
|
|
|
erase_arg == MMC_TRIM_ARG ?
|
2016-12-19 22:03:45 +08:00
|
|
|
INAND_CMD38_ARG_TRIM :
|
|
|
|
INAND_CMD38_ARG_ERASE,
|
2020-01-22 22:27:46 +08:00
|
|
|
card->ext_csd.generic_cmd6_time);
|
2016-12-19 22:03:45 +08:00
|
|
|
}
|
|
|
|
if (!err)
|
2022-04-29 23:21:18 +08:00
|
|
|
err = mmc_erase(card, from, nr, erase_arg);
|
2016-12-19 22:03:45 +08:00
|
|
|
} while (err == -EIO && !mmc_blk_reset(md, card->host, type));
|
2017-06-03 15:38:04 +08:00
|
|
|
if (err)
|
|
|
|
status = BLK_STS_IOERR;
|
|
|
|
else
|
2011-08-29 21:42:15 +08:00
|
|
|
mmc_blk_reset_success(md, type);
|
2016-12-19 22:03:44 +08:00
|
|
|
fail:
|
2017-11-29 21:41:18 +08:00
|
|
|
blk_mq_end_request(req, status);
|
2010-08-12 05:17:47 +08:00
|
|
|
}
|
|
|
|
|
2022-04-29 23:21:18 +08:00
|
|
|
static void mmc_blk_issue_trim_rq(struct mmc_queue *mq, struct request *req)
|
|
|
|
{
|
|
|
|
mmc_blk_issue_erase_rq(mq, req, MMC_BLK_TRIM, MMC_TRIM_ARG);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
|
|
|
struct mmc_card *card = md->queue.card;
|
2022-09-28 17:57:44 +08:00
|
|
|
unsigned int arg = card->erase_arg;
|
2022-04-29 23:21:18 +08:00
|
|
|
|
2022-09-28 17:57:44 +08:00
|
|
|
if (mmc_card_broken_sd_discard(card))
|
|
|
|
arg = SD_ERASE_ARG;
|
|
|
|
|
|
|
|
mmc_blk_issue_erase_rq(mq, req, MMC_BLK_DISCARD, arg);
|
2022-04-29 23:21:18 +08:00
|
|
|
}
|
|
|
|
|
2017-01-24 18:17:57 +08:00
|
|
|
static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
|
2010-08-12 05:17:50 +08:00
|
|
|
struct request *req)
|
|
|
|
{
|
2016-11-18 20:36:15 +08:00
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
2010-08-12 05:17:50 +08:00
|
|
|
struct mmc_card *card = md->queue.card;
|
2013-04-18 20:41:55 +08:00
|
|
|
unsigned int from, nr, arg;
|
2011-08-29 21:42:15 +08:00
|
|
|
int err = 0, type = MMC_BLK_SECDISCARD;
|
2017-06-03 15:38:04 +08:00
|
|
|
blk_status_t status = BLK_STS_OK;
|
2010-08-12 05:17:50 +08:00
|
|
|
|
2013-04-18 20:41:55 +08:00
|
|
|
if (!(mmc_can_secure_erase_trim(card))) {
|
2017-06-03 15:38:04 +08:00
|
|
|
status = BLK_STS_NOTSUPP;
|
2010-08-12 05:17:50 +08:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2012-04-05 19:45:48 +08:00
|
|
|
from = blk_rq_pos(req);
|
|
|
|
nr = blk_rq_sectors(req);
|
|
|
|
|
2013-04-18 20:41:55 +08: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 13:15:48 +08:00
|
|
|
|
2011-08-29 21:42:15 +08:00
|
|
|
retry:
|
2011-04-13 04:06:53 +08: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 22:27:46 +08:00
|
|
|
card->ext_csd.generic_cmd6_time);
|
2011-04-13 04:06:53 +08:00
|
|
|
if (err)
|
2012-04-05 19:45:48 +08:00
|
|
|
goto out_retry;
|
2011-04-13 04:06:53 +08:00
|
|
|
}
|
2012-04-05 19:45:48 +08:00
|
|
|
|
2010-08-12 05:17:50 +08:00
|
|
|
err = mmc_erase(card, from, nr, arg);
|
2012-04-05 19:45:48 +08:00
|
|
|
if (err == -EIO)
|
|
|
|
goto out_retry;
|
2017-06-03 15:38:04 +08:00
|
|
|
if (err) {
|
|
|
|
status = BLK_STS_IOERR;
|
2012-04-05 19:45:48 +08:00
|
|
|
goto out;
|
2017-06-03 15:38:04 +08:00
|
|
|
}
|
2012-04-05 19:45:48 +08:00
|
|
|
|
|
|
|
if (arg == MMC_SECURE_TRIM1_ARG) {
|
2011-04-13 04:06:53 +08: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 22:27:46 +08:00
|
|
|
card->ext_csd.generic_cmd6_time);
|
2011-04-13 04:06:53 +08:00
|
|
|
if (err)
|
2012-04-05 19:45:48 +08:00
|
|
|
goto out_retry;
|
2011-04-13 04:06:53 +08:00
|
|
|
}
|
2012-04-05 19:45:48 +08:00
|
|
|
|
2010-08-12 05:17:50 +08:00
|
|
|
err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
|
2012-04-05 19:45:48 +08:00
|
|
|
if (err == -EIO)
|
|
|
|
goto out_retry;
|
2017-06-03 15:38:04 +08:00
|
|
|
if (err) {
|
|
|
|
status = BLK_STS_IOERR;
|
2012-04-05 19:45:48 +08:00
|
|
|
goto out;
|
2017-06-03 15:38:04 +08:00
|
|
|
}
|
2011-04-13 04:06:53 +08:00
|
|
|
}
|
2012-04-05 19:45:48 +08:00
|
|
|
|
|
|
|
out_retry:
|
|
|
|
if (err && !mmc_blk_reset(md, card->host, type))
|
2011-08-29 21:42:15 +08:00
|
|
|
goto retry;
|
|
|
|
if (!err)
|
|
|
|
mmc_blk_reset_success(md, type);
|
2012-04-05 19:45:48 +08:00
|
|
|
out:
|
2017-11-29 21:41:18 +08:00
|
|
|
blk_mq_end_request(req, status);
|
2010-08-12 05:17:50 +08:00
|
|
|
}
|
|
|
|
|
2017-01-24 18:17:57 +08:00
|
|
|
static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
|
2011-04-01 07:40:00 +08:00
|
|
|
{
|
2016-11-18 20:36:15 +08:00
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
2011-10-14 13:03:21 +08:00
|
|
|
struct mmc_card *card = md->queue.card;
|
|
|
|
int ret = 0;
|
|
|
|
|
2021-05-06 22:58:28 +08:00
|
|
|
ret = mmc_flush_cache(card->host);
|
2017-11-29 21:41:18 +08:00
|
|
|
blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK);
|
2011-04-01 07:40:00 +08: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 04:06:36 +08:00
|
|
|
static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
|
|
|
|
struct mmc_card *card,
|
|
|
|
struct request *req)
|
2011-04-01 07:40:00 +08:00
|
|
|
{
|
|
|
|
if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) {
|
|
|
|
/* Legacy mode imposes restrictions on transfers. */
|
2017-03-13 20:36:40 +08:00
|
|
|
if (!IS_ALIGNED(blk_rq_pos(req), card->ext_csd.rel_sectors))
|
2011-04-01 07:40:00 +08: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 21:41:10 +08:00
|
|
|
#define CMD_ERRORS_EXCL_OOR \
|
|
|
|
(R1_ADDRESS_ERROR | /* Misaligned address */ \
|
2011-06-21 03:10:49 +08:00
|
|
|
R1_BLOCK_LEN_ERROR | /* Transferred block length incorrect */\
|
|
|
|
R1_WP_VIOLATION | /* Tried to write to protected block */ \
|
2017-04-09 04:20:05 +08:00
|
|
|
R1_CARD_ECC_FAILED | /* Card ECC failed */ \
|
2011-06-21 03:10:49 +08:00
|
|
|
R1_CC_ERROR | /* Card controller error */ \
|
|
|
|
R1_ERROR) /* General/unknown error */
|
|
|
|
|
2017-11-29 21:41:10 +08:00
|
|
|
#define CMD_ERRORS \
|
|
|
|
(CMD_ERRORS_EXCL_OOR | \
|
|
|
|
R1_OUT_OF_RANGE) /* Command argument out of range */ \
|
|
|
|
|
2017-08-18 09:16:08 +08:00
|
|
|
static void mmc_blk_eval_resp_error(struct mmc_blk_request *brq)
|
2017-04-09 04:20:05 +08:00
|
|
|
{
|
2017-08-18 09:16:08 +08:00
|
|
|
u32 val;
|
2017-04-09 04:20:05 +08:00
|
|
|
|
2017-08-18 09:16:08 +08: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-09 04:20:05 +08:00
|
|
|
}
|
|
|
|
|
2017-03-13 20:36:41 +08:00
|
|
|
static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq,
|
2022-07-01 20:43:09 +08:00
|
|
|
int recovery_mode, bool *do_rel_wr_p,
|
2017-09-22 20:36:55 +08:00
|
|
|
bool *do_data_tag_p)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2017-03-13 20:36:41 +08:00
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
|
|
|
struct mmc_card *card = md->queue.card;
|
2011-07-02 00:55:29 +08:00
|
|
|
struct mmc_blk_request *brq = &mqrq->brq;
|
2017-05-19 21:37:27 +08:00
|
|
|
struct request *req = mmc_queue_req_to_req(mqrq);
|
2017-09-22 20:36:55 +08:00
|
|
|
bool do_rel_wr, do_data_tag;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-04-01 07:40:00 +08:00
|
|
|
/*
|
|
|
|
* Reliable writes are used to implement Forced Unit Access and
|
2015-11-06 23:12:26 +08:00
|
|
|
* are supported only on MMCs.
|
2011-04-01 07:40:00 +08:00
|
|
|
*/
|
2017-09-22 20:36:55 +08:00
|
|
|
do_rel_wr = (req->cmd_flags & REQ_FUA) &&
|
|
|
|
rq_data_dir(req) == WRITE &&
|
|
|
|
(md->flags & MMC_BLK_REL_WR);
|
2011-04-01 07:40:00 +08:00
|
|
|
|
2011-07-02 00:55:29 +08:00
|
|
|
memset(brq, 0, sizeof(struct mmc_blk_request));
|
2017-03-13 20:36:41 +08:00
|
|
|
|
2021-01-26 08:14:48 +08:00
|
|
|
mmc_crypto_prepare_req(mqrq);
|
|
|
|
|
2011-07-02 00:55:29 +08:00
|
|
|
brq->mrq.data = &brq->data;
|
2017-09-22 20:36:56 +08:00
|
|
|
brq->mrq.tag = req->tag;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-07-02 00:55:29 +08:00
|
|
|
brq->stop.opcode = MMC_STOP_TRANSMISSION;
|
|
|
|
brq->stop.arg = 0;
|
2017-03-13 20:36:41 +08: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-02 00:55:29 +08:00
|
|
|
brq->data.blocks = blk_rq_sectors(req);
|
2017-09-22 20:36:56 +08: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.
|
|
|
|
*/
|
2009-01-01 01:21:17 +08:00
|
|
|
|
2011-07-02 00:55:29 +08: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 06:20:36 +08:00
|
|
|
|
2011-10-07 04:50:33 +08:00
|
|
|
if (brq->data.blocks > 1) {
|
2018-10-08 23:07:30 +08: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 04:50:33 +08:00
|
|
|
/*
|
2022-07-01 20:43:09 +08:00
|
|
|
* After a read error, we redo the request one (native) sector
|
2011-10-07 04:50:33 +08:00
|
|
|
* at a time in order to accurately determine which
|
|
|
|
* sectors can be read successfully.
|
|
|
|
*/
|
2022-07-01 20:43:09 +08:00
|
|
|
if (recovery_mode)
|
|
|
|
brq->data.blocks = queue_physical_block_size(mq->queue) >> 9;
|
2011-10-07 04:50:33 +08:00
|
|
|
|
2014-09-03 10:08:53 +08: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 04:50:33 +08:00
|
|
|
}
|
2011-05-24 04:06:36 +08:00
|
|
|
|
2017-09-22 20:36:56 +08:00
|
|
|
if (do_rel_wr) {
|
2017-03-13 20:36:41 +08:00
|
|
|
mmc_apply_rel_rw(brq, card, req);
|
2017-09-22 20:36:56 +08:00
|
|
|
brq->data.flags |= MMC_DATA_REL_WR;
|
|
|
|
}
|
2017-03-13 20:36:41 +08: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 20:36:55 +08: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 20:36:41 +08:00
|
|
|
|
2017-09-22 20:36:56 +08:00
|
|
|
if (do_data_tag)
|
|
|
|
brq->data.flags |= MMC_DATA_DAT_TAG;
|
|
|
|
|
2017-03-13 20:36:41 +08: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 20:36:55 +08: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 20:36:41 +08:00
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:04 +08: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 22:34:02 +08:00
|
|
|
enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
|
2017-11-29 21:41:04 +08: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 16:10:06 +08:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 21:41:04 +08:00
|
|
|
|
2020-05-06 22:34:02 +08:00
|
|
|
mq->in_flight[issue_type] -= 1;
|
2017-11-29 21:41:04 +08:00
|
|
|
|
|
|
|
put_card = (mmc_tot_in_flight(mq) == 0);
|
|
|
|
|
|
|
|
mmc_cqe_check_busy(mq);
|
|
|
|
|
2018-11-16 16:10:06 +08:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 21:41:04 +08: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);
|
2022-06-01 01:19:22 +08:00
|
|
|
mmc_blk_reset_success(mq->blkdata, MMC_BLK_CQE_RECOVERY);
|
2017-11-29 21:41:04 +08:00
|
|
|
|
|
|
|
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 14:44:47 +08:00
|
|
|
else if (likely(!blk_should_fake_timeout(req->q)))
|
2017-11-29 21:41:04 +08: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 12:12:56 +08: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 21:41:04 +08: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 12:12:56 +08:00
|
|
|
struct mmc_host *host = mq->card->host;
|
|
|
|
|
|
|
|
if (host->hsq_enabled)
|
|
|
|
return mmc_blk_hsq_issue_rw_rq(mq, req);
|
2017-11-29 21:41:04 +08: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 20:36:41 +08:00
|
|
|
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
|
|
|
|
struct mmc_card *card,
|
2022-07-01 20:43:09 +08:00
|
|
|
int recovery_mode,
|
2017-03-13 20:36:41 +08:00
|
|
|
struct mmc_queue *mq)
|
|
|
|
{
|
|
|
|
u32 readcmd, writecmd;
|
|
|
|
struct mmc_blk_request *brq = &mqrq->brq;
|
2017-05-19 21:37:27 +08:00
|
|
|
struct request *req = mmc_queue_req_to_req(mqrq);
|
2017-03-13 20:36:41 +08:00
|
|
|
struct mmc_blk_data *md = mq->blkdata;
|
|
|
|
bool do_rel_wr, do_data_tag;
|
|
|
|
|
2022-07-01 20:43:09 +08:00
|
|
|
mmc_blk_data_prep(mq, mqrq, recovery_mode, &do_rel_wr, &do_data_tag);
|
2017-03-13 20:36:41 +08:00
|
|
|
|
|
|
|
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-02 00:55:29 +08: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 04:06:36 +08:00
|
|
|
*/
|
2011-07-02 00:55:29 +08: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 20:36:41 +08:00
|
|
|
brq->cmd.opcode = rq_data_dir(req) == READ ? readcmd : writecmd;
|
2011-12-21 15:39:17 +08:00
|
|
|
|
2011-07-02 00:55:29 +08: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 15:39:17 +08: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-02 00:55:29 +08:00
|
|
|
brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
|
|
|
|
brq->sbc.arg = brq->data.blocks |
|
2011-12-21 15:39:17 +08:00
|
|
|
(do_rel_wr ? (1 << 31) : 0) |
|
|
|
|
(do_data_tag ? (1 << 29) : 0);
|
2011-07-02 00:55:29 +08:00
|
|
|
brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
|
|
|
brq->mrq.sbc = &brq->sbc;
|
|
|
|
}
|
|
|
|
}
|
2009-01-01 01:21:17 +08:00
|
|
|
|
2017-11-29 21:41:03 +08:00
|
|
|
#define MMC_MAX_RETRIES 5
|
2017-11-29 21:41:15 +08:00
|
|
|
#define MMC_DATA_RETRIES 2
|
2017-11-29 21:41:03 +08:00
|
|
|
#define MMC_NO_RETRIES (MMC_MAX_RETRIES + 1)
|
|
|
|
|
2017-11-29 21:41:15 +08: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);
|
|
|
|
|
2021-07-02 21:42:27 +08:00
|
|
|
err = mmc_poll_for_busy(card, timeout, false, MMC_BUSY_IO);
|
2017-11-29 21:41:15 +08:00
|
|
|
|
|
|
|
mmc_retune_release(card->host);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:03 +08:00
|
|
|
#define MMC_READ_SINGLE_RETRIES 2
|
|
|
|
|
2022-07-01 20:43:09 +08:00
|
|
|
/* Single (native) sector read during recovery */
|
2017-11-29 21:41:03 +08:00
|
|
|
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;
|
2022-07-01 20:43:09 +08:00
|
|
|
size_t bytes_per_read = queue_physical_block_size(mq->queue);
|
2017-11-29 21:41:03 +08:00
|
|
|
|
|
|
|
do {
|
|
|
|
u32 status;
|
|
|
|
int err;
|
2022-02-04 23:11:37 +08:00
|
|
|
int retries = 0;
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2022-02-04 23:11:37 +08:00
|
|
|
while (retries++ <= MMC_READ_SINGLE_RETRIES) {
|
|
|
|
mmc_blk_rw_rq_prep(mqrq, card, 1, mq);
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2022-02-04 23:11:37 +08:00
|
|
|
mmc_wait_for_req(host, mrq);
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2022-02-04 23:11:37 +08:00
|
|
|
err = mmc_send_status(card, &status);
|
2017-11-29 21:41:03 +08:00
|
|
|
if (err)
|
|
|
|
goto error_exit;
|
|
|
|
|
2022-02-04 23:11:37 +08:00
|
|
|
if (!mmc_host_is_spi(host) &&
|
|
|
|
!mmc_ready_for_data(status)) {
|
|
|
|
err = mmc_blk_fix_state(card, req);
|
|
|
|
if (err)
|
|
|
|
goto error_exit;
|
|
|
|
}
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2022-02-04 23:11:37 +08:00
|
|
|
if (!mrq->cmd->error)
|
|
|
|
break;
|
|
|
|
}
|
2017-11-29 21:41:03 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2022-07-01 20:43:09 +08:00
|
|
|
} while (blk_update_request(req, error, bytes_per_read));
|
2017-11-29 21:41:03 +08:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
error_exit:
|
|
|
|
mrq->data->bytes_xfered = 0;
|
2022-07-01 20:43:09 +08:00
|
|
|
blk_update_request(req, BLK_STS_IOERR, bytes_per_read);
|
2017-11-29 21:41:03 +08:00
|
|
|
/* Let it try the remaining request again */
|
|
|
|
if (mqrq->retries > MMC_MAX_RETRIES - 1)
|
|
|
|
mqrq->retries = MMC_MAX_RETRIES - 1;
|
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:15 +08: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 05:54:24 +08:00
|
|
|
return false;
|
2017-11-29 21:41:15 +08: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 16:54:43 +08:00
|
|
|
(rq_data_dir(req) == WRITE && !mmc_ready_for_data(status));
|
2017-11-29 21:41:15 +08: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 21:41:03 +08: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 21:41:15 +08:00
|
|
|
u32 status;
|
|
|
|
u32 blocks;
|
|
|
|
int err;
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2017-11-29 21:41:15 +08: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 21:41:03 +08:00
|
|
|
|
|
|
|
mmc_retune_release(card->host);
|
|
|
|
|
|
|
|
/*
|
2017-11-29 21:41:15 +08:00
|
|
|
* Try again to get the status. This also provides an opportunity for
|
|
|
|
* re-tuning.
|
2017-11-29 21:41:03 +08:00
|
|
|
*/
|
2017-11-29 21:41:15 +08:00
|
|
|
if (err)
|
|
|
|
err = __mmc_send_status(card, &status, 0);
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2017-11-29 21:41:15 +08: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 21:41:03 +08:00
|
|
|
|
2017-11-29 21:41:15 +08:00
|
|
|
/* Try to get back to "tran" state */
|
|
|
|
if (!mmc_host_is_spi(mq->card->host) &&
|
2020-02-04 16:54:43 +08:00
|
|
|
(err || !mmc_ready_for_data(status)))
|
2017-11-29 21:41:15 +08: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 21:41:03 +08:00
|
|
|
}
|
2017-11-29 21:41:15 +08: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)) {
|
2021-11-26 20:18:00 +08:00
|
|
|
pr_err("%s: recovery failed!\n", req->q->disk->disk_name);
|
2017-11-29 21:41:03 +08:00
|
|
|
mqrq->retries = MMC_NO_RETRIES;
|
2017-11-29 21:41:15 +08: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 */
|
2022-10-13 19:16:37 +08:00
|
|
|
if (mqrq->retries + 1 == MMC_MAX_RETRIES &&
|
|
|
|
mmc_blk_reset(md, card->host, type))
|
|
|
|
return;
|
2017-11-29 21:41:15 +08:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2022-07-01 20:43:09 +08:00
|
|
|
if (rq_data_dir(req) == READ && brq->data.blocks >
|
|
|
|
queue_physical_block_size(mq->queue) >> 9) {
|
|
|
|
/* Read one (native) sector at a time */
|
2017-11-29 21:41:15 +08:00
|
|
|
mmc_blk_read_single(mq, req);
|
|
|
|
return;
|
2017-11-29 21:41:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:07 +08: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;
|
|
|
|
}
|
|
|
|
|
2022-03-24 22:18:41 +08:00
|
|
|
static int mmc_spi_err_check(struct mmc_card *card)
|
|
|
|
{
|
|
|
|
u32 status = 0;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SPI does not have a TRAN state we have to wait on, instead the
|
|
|
|
* card is ready again when it no longer holds the line LOW.
|
|
|
|
* We still have to ensure two things here before we know the write
|
|
|
|
* was successful:
|
|
|
|
* 1. The card has not disconnected during busy and we actually read our
|
|
|
|
* own pull-up, thinking it was still connected, so ensure it
|
|
|
|
* still responds.
|
|
|
|
* 2. Check for any error bits, in particular R1_SPI_IDLE to catch a
|
|
|
|
* just reconnected card after being disconnected during busy.
|
|
|
|
*/
|
|
|
|
err = __mmc_send_status(card, &status, 0);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
/* All R1 and R2 bits of SPI are errors in our case */
|
|
|
|
if (status)
|
|
|
|
return -EIO;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-02 21:42:29 +08:00
|
|
|
static int mmc_blk_busy_cb(void *cb_data, bool *busy)
|
|
|
|
{
|
|
|
|
struct mmc_blk_busy_data *data = cb_data;
|
|
|
|
u32 status = 0;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = mmc_send_status(data->card, &status);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
/* Accumulate response error bits. */
|
|
|
|
data->status |= status;
|
|
|
|
|
|
|
|
*busy = !mmc_ready_for_data(status);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:08 +08: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);
|
2021-07-02 21:42:29 +08:00
|
|
|
struct mmc_blk_busy_data cb_data;
|
2017-11-29 21:41:08 +08:00
|
|
|
int err;
|
|
|
|
|
2022-03-24 22:18:41 +08:00
|
|
|
if (rq_data_dir(req) == READ)
|
2017-11-29 21:41:08 +08:00
|
|
|
return 0;
|
|
|
|
|
2022-03-24 22:18:41 +08:00
|
|
|
if (mmc_host_is_spi(card->host)) {
|
|
|
|
err = mmc_spi_err_check(card);
|
|
|
|
if (err)
|
|
|
|
mqrq->brq.data.bytes_xfered = 0;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-07-02 21:42:29 +08:00
|
|
|
cb_data.card = card;
|
|
|
|
cb_data.status = 0;
|
2022-03-04 18:56:56 +08:00
|
|
|
err = __mmc_poll_for_busy(card->host, 0, MMC_BLK_TIMEOUT_MS,
|
2021-11-04 14:32:30 +08:00
|
|
|
&mmc_blk_busy_cb, &cb_data);
|
2017-11-29 21:41:08 +08:00
|
|
|
|
2017-11-29 21:41:10 +08:00
|
|
|
/*
|
|
|
|
* Do not assume data transferred correctly if there are any error bits
|
|
|
|
* set.
|
|
|
|
*/
|
2021-07-02 21:42:29 +08:00
|
|
|
if (cb_data.status & mmc_blk_stop_err_bits(&mqrq->brq)) {
|
2017-11-29 21:41:10 +08:00
|
|
|
mqrq->brq.data.bytes_xfered = 0;
|
2017-11-29 21:41:08 +08:00
|
|
|
err = err ? err : -EIO;
|
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:10 +08:00
|
|
|
/* Copy the exception bit so it will be seen later on */
|
2021-07-02 21:42:29 +08:00
|
|
|
if (mmc_card_mmc(card) && cb_data.status & R1_EXCEPTION_EVENT)
|
2017-11-29 21:41:10 +08:00
|
|
|
mqrq->brq.cmd.resp[0] |= R1_EXCEPTION_EVENT;
|
|
|
|
|
2017-11-29 21:41:08 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:07 +08: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 21:41:03 +08: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-11 00:52:40 +08:00
|
|
|
mmc_run_bkops(mq->card);
|
2017-11-29 21:41:03 +08: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 12:12:56 +08: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 14:44:47 +08: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 12:12:56 +08:00
|
|
|
blk_mq_complete_request(req);
|
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:03 +08:00
|
|
|
void mmc_blk_mq_complete(struct request *req)
|
|
|
|
{
|
|
|
|
struct mmc_queue *mq = req->q->queuedata;
|
2021-02-15 08:32:18 +08:00
|
|
|
struct mmc_host *host = mq->card->host;
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2021-02-15 08:32:18 +08:00
|
|
|
if (host->cqe_enabled)
|
2017-11-29 21:41:04 +08:00
|
|
|
mmc_blk_cqe_complete_rq(mq, req);
|
2020-06-11 14:44:47 +08:00
|
|
|
else if (likely(!blk_should_fake_timeout(req->q)))
|
2017-11-29 21:41:04 +08:00
|
|
|
mmc_blk_mq_complete_rq(mq, req);
|
2017-11-29 21:41:03 +08: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 21:41:08 +08:00
|
|
|
struct mmc_host *host = mq->card->host;
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2017-11-29 21:41:08 +08: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 21:41:03 +08: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 16:10:06 +08:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 21:41:03 +08:00
|
|
|
|
|
|
|
mq->in_flight[mmc_issue_type(mq, req)] -= 1;
|
|
|
|
|
|
|
|
put_card = (mmc_tot_in_flight(mq) == 0);
|
|
|
|
|
2018-11-16 16:10:06 +08:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 21:41:03 +08:00
|
|
|
|
|
|
|
if (put_card)
|
|
|
|
mmc_put_card(mq->card, &mq->ctx);
|
|
|
|
}
|
|
|
|
|
2021-10-25 15:06:58 +08:00
|
|
|
static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req,
|
|
|
|
bool can_sleep)
|
2017-11-29 21:41:03 +08:00
|
|
|
{
|
|
|
|
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 21:41:07 +08:00
|
|
|
/*
|
|
|
|
* Block layer timeouts race with completions which means the normal
|
|
|
|
* completion path cannot be used during recovery.
|
|
|
|
*/
|
2021-10-25 15:06:58 +08:00
|
|
|
if (mq->in_recovery) {
|
2017-11-29 21:41:07 +08:00
|
|
|
mmc_blk_mq_complete_rq(mq, req);
|
2021-10-25 15:06:58 +08:00
|
|
|
} else if (likely(!blk_should_fake_timeout(req->q))) {
|
|
|
|
if (can_sleep)
|
|
|
|
blk_mq_complete_request_direct(req, mmc_blk_mq_complete);
|
|
|
|
else
|
|
|
|
blk_mq_complete_request(req);
|
|
|
|
}
|
2017-11-29 21:41:03 +08:00
|
|
|
|
|
|
|
mmc_blk_mq_dec_in_flight(mq, req);
|
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:07 +08: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);
|
|
|
|
|
2021-10-25 15:06:58 +08:00
|
|
|
mmc_blk_mq_post_req(mq, req, true);
|
2017-11-29 21:41:07 +08:00
|
|
|
}
|
|
|
|
|
2017-11-29 21:41:03 +08:00
|
|
|
static void mmc_blk_mq_complete_prev_req(struct mmc_queue *mq,
|
|
|
|
struct request **prev_req)
|
|
|
|
{
|
2017-11-29 21:41:07 +08:00
|
|
|
if (mmc_host_done_complete(mq->card->host))
|
|
|
|
return;
|
|
|
|
|
2017-11-29 21:41:03 +08: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
|
2021-10-25 15:06:58 +08:00
|
|
|
mmc_blk_mq_post_req(mq, mq->complete_req, true);
|
2017-11-29 21:41:03 +08:00
|
|
|
|
|
|
|
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 21:41:07 +08:00
|
|
|
struct mmc_host *host = mq->card->host;
|
2017-11-29 21:41:03 +08:00
|
|
|
unsigned long flags;
|
|
|
|
|
2017-11-29 21:41:07 +08:00
|
|
|
if (!mmc_host_done_complete(host)) {
|
|
|
|
bool waiting;
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2017-11-29 21:41:07 +08: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 16:10:06 +08:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 21:41:07 +08:00
|
|
|
mq->complete_req = req;
|
|
|
|
mq->rw_wait = false;
|
|
|
|
waiting = mq->waiting;
|
2018-11-16 16:10:06 +08:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 21:41:07 +08: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 23:03:08 +08:00
|
|
|
queue_work(mq->card->complete_wq, &mq->complete_work);
|
2017-11-29 21:41:07 +08: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 16:10:06 +08:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 21:41:07 +08:00
|
|
|
mq->recovery_needed = true;
|
|
|
|
mq->recovery_req = req;
|
2018-11-16 16:10:06 +08:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 21:41:03 +08:00
|
|
|
wake_up(&mq->wait);
|
2017-11-29 21:41:07 +08:00
|
|
|
schedule_work(&mq->recovery_work);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mmc_blk_rw_reset_success(mq, req);
|
|
|
|
|
|
|
|
mq->rw_wait = false;
|
|
|
|
wake_up(&mq->wait);
|
|
|
|
|
2021-10-25 15:06:58 +08:00
|
|
|
/* context unknown */
|
|
|
|
mmc_blk_mq_post_req(mq, req, false);
|
2017-11-29 21:41:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool mmc_blk_rw_wait_cond(struct mmc_queue *mq, int *err)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
bool done;
|
|
|
|
|
|
|
|
/*
|
2017-11-29 21:41:07 +08: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 21:41:03 +08:00
|
|
|
*/
|
2018-11-16 16:10:06 +08:00
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
2017-11-29 21:41:07 +08:00
|
|
|
if (mq->recovery_needed) {
|
|
|
|
*err = -EBUSY;
|
|
|
|
done = true;
|
|
|
|
} else {
|
|
|
|
done = !mq->rw_wait;
|
|
|
|
}
|
2017-11-29 21:41:03 +08:00
|
|
|
mq->waiting = !done;
|
2018-11-16 16:10:06 +08:00
|
|
|
spin_unlock_irqrestore(&mq->lock, flags);
|
2017-11-29 21:41:03 +08: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)
|
2021-10-25 15:06:58 +08:00
|
|
|
mmc_blk_mq_post_req(mq, prev_req, true);
|
2017-11-29 21:41:03 +08:00
|
|
|
|
2017-11-29 21:41:07 +08:00
|
|
|
if (err)
|
2017-11-29 21:41:03 +08:00
|
|
|
mq->rw_wait = false;
|
2017-11-29 21:41:07 +08:00
|
|
|
|
|
|
|
/* Release re-tuning here where there is no synchronization required */
|
|
|
|
if (err || mmc_host_done_complete(host))
|
2017-11-29 21:41:03 +08: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)
|
|
|
|
{
|
2021-02-15 08:32:18 +08:00
|
|
|
if (host->cqe_enabled)
|
2017-11-29 21:41:04 +08:00
|
|
|
return host->cqe_ops->cqe_wait_for_idle(host);
|
|
|
|
|
2017-11-29 21:41:03 +08: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;
|
2022-04-29 23:21:18 +08:00
|
|
|
case REQ_OP_WRITE_ZEROES:
|
|
|
|
mmc_blk_issue_trim_rq(mq, req);
|
|
|
|
break;
|
2017-11-29 21:41:03 +08:00
|
|
|
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 21:41:04 +08:00
|
|
|
case MMC_ISSUE_DCMD:
|
2017-11-29 21:41:03 +08:00
|
|
|
case MMC_ISSUE_ASYNC:
|
|
|
|
switch (req_op(req)) {
|
2017-11-29 21:41:04 +08:00
|
|
|
case REQ_OP_FLUSH:
|
2021-04-25 14:02:06 +08:00
|
|
|
if (!mmc_cache_enabled(host)) {
|
|
|
|
blk_mq_end_request(req, BLK_STS_OK);
|
|
|
|
return MMC_REQ_FINISHED;
|
|
|
|
}
|
2017-11-29 21:41:04 +08:00
|
|
|
ret = mmc_blk_cqe_issue_flush(mq, req);
|
|
|
|
break;
|
2017-11-29 21:41:03 +08:00
|
|
|
case REQ_OP_READ:
|
|
|
|
case REQ_OP_WRITE:
|
2021-02-15 08:32:18 +08:00
|
|
|
if (host->cqe_enabled)
|
2017-11-29 21:41:04 +08:00
|
|
|
ret = mmc_blk_cqe_issue_rw_rq(mq, req);
|
|
|
|
else
|
|
|
|
ret = mmc_blk_mq_issue_rw_rq(mq, req);
|
2017-11-29 21:41:03 +08: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 06:38:44 +08: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 07:10:25 +08: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 15:51:06 +08:00
|
|
|
const char *subname,
|
2021-08-09 14:40:22 +08:00
|
|
|
int area_type,
|
|
|
|
unsigned int part_type)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct mmc_blk_data *md;
|
|
|
|
int devidx, ret;
|
2021-03-03 20:20:48 +08:00
|
|
|
char cap_str[10];
|
2022-03-31 15:32:23 +08:00
|
|
|
bool cache_enabled = false;
|
|
|
|
bool fua_enabled = false;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2017-02-02 02:44:22 +08:00
|
|
|
devidx = ida_simple_get(&mmc_blk_ida, 0, max_devices, GFP_KERNEL);
|
2017-08-23 15:38:31 +08: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-02 02:44:22 +08:00
|
|
|
return ERR_PTR(devidx);
|
2017-08-23 15:38:31 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08: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 16:49:03 +08:00
|
|
|
md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
|
2006-01-04 06:38:44 +08:00
|
|
|
if (!md) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto out;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-12-02 15:51:06 +08:00
|
|
|
md->area_type = area_type;
|
|
|
|
|
2006-01-04 06:38:44 +08: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 06:20:36 +08:00
|
|
|
|
2021-06-16 13:39:34 +08:00
|
|
|
md->disk = mmc_init_queue(&md->queue, card);
|
|
|
|
if (IS_ERR(md->disk)) {
|
|
|
|
ret = PTR_ERR(md->disk);
|
2006-01-04 06:38:44 +08:00
|
|
|
goto err_kfree;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-04-12 07:10:25 +08: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 16:02:00 +08:00
|
|
|
INIT_LIST_HEAD(&md->rpmbs);
|
mmc: core: Use kref in place of struct mmc_blk_data::usage
Ulf reported the following KASAN splat after adding some manual hacks
into mmc-utils[1].
DEBUG: mmc_blk_open: Let's sleep for 10s..
mmc1: card 0007 removed
BUG: KASAN: use-after-free in mmc_blk_get+0x58/0xb8
Read of size 4 at addr ffff00000a394a28 by task mmc/180
CPU: 2 PID: 180 Comm: mmc Not tainted 5.10.0-rc4-00069-gcc758c8c7127-dirty #5
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Call trace:
dump_backtrace+0x0/0x2b4
show_stack+0x18/0x6c
dump_stack+0xfc/0x168
print_address_description.constprop.0+0x6c/0x488
kasan_report+0x118/0x210
__asan_load4+0x94/0xd0
mmc_blk_get+0x58/0xb8
mmc_blk_open+0x7c/0xdc
__blkdev_get+0x3b4/0x964
blkdev_get+0x64/0x100
blkdev_open+0xe8/0x104
do_dentry_open+0x234/0x61c
vfs_open+0x54/0x64
path_openat+0xe04/0x1584
do_filp_open+0xe8/0x1e4
do_sys_openat2+0x120/0x230
__arm64_sys_openat+0xf0/0x15c
el0_svc_common.constprop.0+0xac/0x234
do_el0_svc+0x84/0xa0
el0_sync_handler+0x264/0x270
el0_sync+0x174/0x180
Allocated by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
__kasan_kmalloc.constprop.0+0xc8/0xf0
kasan_kmalloc+0x10/0x20
mmc_blk_alloc_req+0x94/0x4b0
mmc_blk_probe+0x2d4/0xaa4
mmc_bus_probe+0x34/0x4c
really_probe+0x148/0x6e0
driver_probe_device+0x78/0xec
__device_attach_driver+0x108/0x16c
bus_for_each_drv+0xf4/0x15c
__device_attach+0x168/0x240
device_initial_probe+0x14/0x20
bus_probe_device+0xec/0x100
device_add+0x55c/0xaf0
mmc_add_card+0x288/0x380
mmc_attach_sd+0x18c/0x22c
mmc_rescan+0x444/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
Freed by task 33:
stack_trace_save+0x9c/0xdc
kasan_save_stack+0x28/0x60
kasan_set_track+0x28/0x40
kasan_set_free_info+0x24/0x4c
__kasan_slab_free+0x100/0x180
kasan_slab_free+0x14/0x20
kfree+0xb8/0x46c
mmc_blk_put+0xe4/0x11c
mmc_blk_remove_req.part.0+0x6c/0xe4
mmc_blk_remove+0x368/0x370
mmc_bus_remove+0x34/0x50
__device_release_driver+0x228/0x31c
device_release_driver+0x2c/0x44
bus_remove_device+0x1e4/0x200
device_del+0x2b0/0x770
mmc_remove_card+0xf0/0x150
mmc_sd_detect+0x9c/0x150
mmc_rescan+0x110/0x4f0
process_one_work+0x3b8/0x650
worker_thread+0xa0/0x724
kthread+0x218/0x220
ret_from_fork+0x10/0x38
The buggy address belongs to the object at ffff00000a394800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 552 bytes inside of
1024-byte region [ffff00000a394800, ffff00000a394c00)
The buggy address belongs to the page:
page:00000000ff84ed53 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8a390
head:00000000ff84ed53 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x3fffc0000010200(slab|head)
raw: 03fffc0000010200 dead000000000100 dead000000000122 ffff000009f03800
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff00000a394900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff00000a394a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff00000a394a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00000a394b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Looking closer at the problem, it looks like a classic dangling pointer
bug. The 'struct mmc_blk_data' that is used after being freed in
mmc_blk_put() is stashed away in 'md->disk->private_data' via
mmc_blk_alloc_req() but used in mmc_blk_get() because the 'usage' count
isn't properly aligned with the lifetime of the pointer. You'd expect
the 'usage' member to be in sync with the kfree(), and it mostly is,
except that mmc_blk_get() needs to dereference the potentially freed
memory storage for the 'struct mmc_blk_data' stashed away in the
private_data member to look at 'usage' before it actually figures out if
it wants to consider it a valid pointer or not. That's not going to work
if the freed memory has been overwritten by something else after the
free, and KASAN rightly complains here.
To fix the immediate problem, let's set the private_data member to NULL
in mmc_blk_put() so that mmc_blk_get() can consider the object "on the
way out" if the pointer is NULL and not even try to look at 'usage' if
the object isn't going to be around much longer. With that set to NULL
on the last mmc_blk_put(), optimize the get path further and use a kref
underneath the 'open_lock' mutex to only up the reference count if it's
non-zero, i.e. alive, and otherwise make mmc_blk_get() return NULL,
without actually testing the reference count if we're in the process of
removing the object from the system.
Finally, tighten the locking region on the put side to only be around
the parts that are removing the 'mmc_blk_data' from the system and
publishing that fact to the gendisk and then drop the lock as soon as we
can to avoid holding the lock around code that doesn't need it. This
fixes the KASAN issue.
Cc: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Cc: Sujit Kautkar <sujitka@chromium.org>
Cc: Zubin Mithra <zsm@chromium.org>
Reported-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/linux-mmc/CAPDyKFryT63Jc7+DXWSpAC19qpZRqFr1orxwYGMuSqx247O8cQ@mail.gmail.com/ [1]
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20210623075002.1746924-2-swboyd@chromium.org
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2021-06-23 15:50:01 +08:00
|
|
|
kref_init(&md->kref);
|
|
|
|
|
2016-11-18 20:36:15 +08:00
|
|
|
md->queue.blkdata = md;
|
2021-08-09 14:40:22 +08:00
|
|
|
md->part_type = part_type;
|
2005-12-23 07:21:38 +08:00
|
|
|
|
2007-05-14 23:27:29 +08:00
|
|
|
md->disk->major = MMC_BLOCK_MAJOR;
|
2021-06-21 16:01:44 +08:00
|
|
|
md->disk->minors = perdev_minors;
|
2010-09-18 09:19:57 +08:00
|
|
|
md->disk->first_minor = devidx * perdev_minors;
|
2006-01-04 06:38:44 +08:00
|
|
|
md->disk->fops = &mmc_bdops;
|
|
|
|
md->disk->private_data = md;
|
2016-06-21 01:40:44 +08:00
|
|
|
md->parent = parent;
|
2011-04-12 07:10:25 +08:00
|
|
|
set_disk_ro(md->disk, md->read_only || default_ro);
|
2014-09-03 17:02:23 +08:00
|
|
|
if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT))
|
2021-11-22 21:06:20 +08:00
|
|
|
md->disk->flags |= GENHD_FL_NO_PART;
|
2006-01-04 06:38:44 +08: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 11:46:13 +08: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 22:12:08 +08:00
|
|
|
"mmcblk%u%s", card->host->index, subname ? subname : "");
|
2006-01-04 06:38:44 +08:00
|
|
|
|
2011-04-12 07:10:25 +08:00
|
|
|
set_capacity(md->disk, size);
|
2011-05-24 04:06:36 +08:00
|
|
|
|
2011-05-24 04:06:38 +08:00
|
|
|
if (mmc_host_cmd23(card->host)) {
|
2016-08-30 20:17:30 +08:00
|
|
|
if ((mmc_card_mmc(card) &&
|
|
|
|
card->csd.mmca_vsn >= CSD_SPEC_VER_3) ||
|
2011-05-24 04:06:38 +08:00
|
|
|
(mmc_card_sd(card) &&
|
|
|
|
card->scr.cmds & SD_SCR_CMD23_SUPPORT))
|
|
|
|
md->flags |= MMC_BLK_CMD23;
|
|
|
|
}
|
2011-05-24 04:06:36 +08:00
|
|
|
|
2022-03-31 15:32:23 +08:00
|
|
|
if (md->flags & MMC_BLK_CMD23 &&
|
2011-05-24 04:06:36 +08:00
|
|
|
((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
|
|
|
|
card->ext_csd.rel_sectors)) {
|
|
|
|
md->flags |= MMC_BLK_REL_WR;
|
2022-03-31 15:32:23 +08:00
|
|
|
fua_enabled = true;
|
|
|
|
cache_enabled = true;
|
2011-05-24 04:06:36 +08:00
|
|
|
}
|
2022-03-31 15:32:23 +08:00
|
|
|
if (mmc_cache_enabled(card->host))
|
|
|
|
cache_enabled = true;
|
|
|
|
|
|
|
|
blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled);
|
2011-05-24 04:06:36 +08:00
|
|
|
|
2021-03-03 20:20:48 +08:00
|
|
|
string_get_size((u64)size, 512, STRING_UNITS_2,
|
|
|
|
cap_str, sizeof(cap_str));
|
|
|
|
pr_info("%s: %s %s %s %s\n",
|
|
|
|
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
|
|
|
|
cap_str, md->read_only ? "(ro)" : "");
|
|
|
|
|
2021-08-09 14:40:22 +08:00
|
|
|
/* used in ->open, must be set before add_disk: */
|
|
|
|
if (area_type == MMC_BLK_DATA_AREA_MAIN)
|
|
|
|
dev_set_drvdata(&card->dev, md);
|
2021-08-31 05:25:34 +08:00
|
|
|
ret = device_add_disk(md->parent, md->disk, mmc_disk_attr_groups);
|
|
|
|
if (ret)
|
2022-07-19 00:08:51 +08:00
|
|
|
goto err_put_disk;
|
2011-04-12 07:10:25 +08:00
|
|
|
return md;
|
|
|
|
|
2022-07-19 00:08:51 +08:00
|
|
|
err_put_disk:
|
|
|
|
put_disk(md->disk);
|
2021-08-31 05:25:34 +08:00
|
|
|
blk_mq_free_tag_set(&md->queue.tag_set);
|
2011-04-12 07:10:25 +08:00
|
|
|
err_kfree:
|
|
|
|
kfree(md);
|
|
|
|
out:
|
2017-02-02 02:44:22 +08:00
|
|
|
ida_simple_remove(&mmc_blk_ida, devidx);
|
2011-04-12 07:10:25 +08:00
|
|
|
return ERR_PTR(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
|
|
|
|
{
|
|
|
|
sector_t size;
|
2006-01-04 06:38:44 +08:00
|
|
|
|
2007-02-18 05:15:27 +08: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 07:10:25 +08:00
|
|
|
size = card->ext_csd.sectors;
|
2007-02-18 05:15:27 +08:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* The CSD capacity field is in units of read_blkbits.
|
|
|
|
* set_capacity takes units of 512 bytes.
|
|
|
|
*/
|
2015-05-11 15:35:28 +08:00
|
|
|
size = (typeof(sector_t))card->csd.capacity
|
|
|
|
<< (card->csd.read_blkbits - 9);
|
2007-02-18 05:15:27 +08:00
|
|
|
}
|
2011-04-12 07:10:25 +08:00
|
|
|
|
2015-01-21 22:56:44 +08:00
|
|
|
return mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
|
2021-08-09 14:40:22 +08:00
|
|
|
MMC_BLK_DATA_AREA_MAIN, 0);
|
2011-04-12 07:10:25 +08:00
|
|
|
}
|
2006-01-04 06:38:44 +08:00
|
|
|
|
2011-04-12 07:10:25 +08: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 15:51:06 +08:00
|
|
|
const char *subname,
|
|
|
|
int area_type)
|
2011-04-12 07:10:25 +08:00
|
|
|
{
|
|
|
|
struct mmc_blk_data *part_md;
|
|
|
|
|
|
|
|
part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
|
2021-08-09 14:40:22 +08:00
|
|
|
subname, area_type, part_type);
|
2011-04-12 07:10:25 +08:00
|
|
|
if (IS_ERR(part_md))
|
|
|
|
return PTR_ERR(part_md);
|
|
|
|
list_add(&part_md->part, &md->part);
|
|
|
|
|
|
|
|
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 16:02:00 +08: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-17 03:20:20 +08: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 16:02:00 +08: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 17:10:07 +08: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 16:02:00 +08: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 17:10:07 +08:00
|
|
|
mmc_blk_put(rpmb->md);
|
2020-05-22 17:29:25 +08: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 16:02:00 +08: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 17:10:07 +08: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 16:02:00 +08: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 17:10:07 +08: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 16:02:00 +08:00
|
|
|
return -ENOMEM;
|
2017-10-04 17:10:07 +08: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 16:02:00 +08: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 17:10:07 +08: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 16:02:00 +08: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 17:10:07 +08: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 16:02:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
list_add(&rpmb->node, &md->rpmbs);
|
|
|
|
|
|
|
|
string_get_size((u64)size, 512, STRING_UNITS_2,
|
|
|
|
cap_str, sizeof(cap_str));
|
|
|
|
|
2021-03-03 20:20:48 +08:00
|
|
|
pr_info("%s: %s %s %s, chardev (%d:%d)\n",
|
|
|
|
rpmb_name, mmc_card_id(card), mmc_card_name(card), cap_str,
|
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 16:02:00 +08:00
|
|
|
MAJOR(mmc_rpmb_devt), rpmb->id);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2017-10-04 17:10:07 +08: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 16:02:00 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mmc_blk_remove_rpmb_part(struct mmc_rpmb_data *rpmb)
|
2017-10-04 17:10:07 +08: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 16:02:00 +08:00
|
|
|
{
|
|
|
|
cdev_device_del(&rpmb->chrdev, &rpmb->dev);
|
2017-10-04 17:10:07 +08: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 16:02:00 +08:00
|
|
|
}
|
|
|
|
|
2011-10-06 22:41:38 +08: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 07:10:25 +08: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 16:02:00 +08:00
|
|
|
int idx, ret;
|
2011-04-12 07:10:25 +08:00
|
|
|
|
|
|
|
if (!mmc_card_mmc(card))
|
|
|
|
return 0;
|
|
|
|
|
2011-10-06 22:41:38 +08: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 16:02:00 +08: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 22:41:38 +08: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 15:51:06 +08:00
|
|
|
card->part[idx].name,
|
|
|
|
card->part[idx].area_type);
|
2011-10-06 22:41:38 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
2011-04-12 07:10:25 +08: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 16:02:00 +08:00
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2011-04-12 07:10:25 +08:00
|
|
|
static void mmc_blk_remove_req(struct mmc_blk_data *md)
|
|
|
|
{
|
2021-08-09 14:40:22 +08:00
|
|
|
/*
|
|
|
|
* Flush remaining requests and free queues. It is freeing the queue
|
|
|
|
* that stops new requests from being accepted.
|
|
|
|
*/
|
|
|
|
del_gendisk(md->disk);
|
|
|
|
mmc_cleanup_queue(&md->queue);
|
|
|
|
mmc_blk_put(md);
|
2011-04-12 07:10:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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 16:02:00 +08:00
|
|
|
struct mmc_rpmb_data *rpmb;
|
2011-04-12 07:10:25 +08: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 16:02:00 +08: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 07:10:25 +08: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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-21 05:39:08 +08: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 */
|
2021-10-25 15:05:07 +08:00
|
|
|
req = blk_mq_alloc_request(mq->queue, REQ_OP_DRV_IN, 0);
|
2017-11-21 21:42:28 +08:00
|
|
|
if (IS_ERR(req))
|
|
|
|
return PTR_ERR(req);
|
2017-08-21 05:39:08 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
|
2023-04-27 00:59:39 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_result = -EIO;
|
2021-11-26 20:18:01 +08:00
|
|
|
blk_execute_rq(req, false);
|
2017-08-21 05:39:08 +08:00
|
|
|
ret = req_to_mmc_queue_req(req)->drv_op_result;
|
|
|
|
if (ret >= 0) {
|
|
|
|
*val = ret;
|
|
|
|
ret = 0;
|
|
|
|
}
|
2021-10-25 15:05:07 +08:00
|
|
|
blk_mq_free_request(req);
|
2017-08-21 05:39:08 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2018-12-29 09:43:48 +08:00
|
|
|
DEFINE_DEBUGFS_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
|
|
|
|
NULL, "%08llx\n");
|
2017-08-21 05:39:08 +08: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 */
|
2021-10-25 15:05:07 +08:00
|
|
|
req = blk_mq_alloc_request(mq->queue, REQ_OP_DRV_IN, 0);
|
2017-11-21 21:42:28 +08:00
|
|
|
if (IS_ERR(req)) {
|
|
|
|
err = PTR_ERR(req);
|
|
|
|
goto out_free;
|
|
|
|
}
|
2017-08-21 05:39:08 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD;
|
2023-04-27 00:59:39 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_result = -EIO;
|
2017-08-21 05:39:08 +08:00
|
|
|
req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
|
2021-11-26 20:18:01 +08:00
|
|
|
blk_execute_rq(req, false);
|
2017-08-21 05:39:08 +08:00
|
|
|
err = req_to_mmc_queue_req(req)->drv_op_result;
|
2021-10-25 15:05:07 +08:00
|
|
|
blk_mq_free_request(req);
|
2017-08-21 05:39:08 +08: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 23:15:45 +08:00
|
|
|
kfree(ext_csd);
|
2017-08-21 05:39:08 +08: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 21:42:30 +08:00
|
|
|
static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
|
2017-08-21 05:39:08 +08: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 21:42:30 +08:00
|
|
|
md->status_dentry =
|
2018-12-29 09:43:48 +08:00
|
|
|
debugfs_create_file_unsafe("status", 0400, root,
|
|
|
|
card,
|
|
|
|
&mmc_dbg_card_status_fops);
|
2017-11-21 21:42:30 +08:00
|
|
|
if (!md->status_dentry)
|
2017-08-21 05:39:08 +08:00
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mmc_card_mmc(card)) {
|
2017-11-21 21:42:30 +08: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 05:39:08 +08:00
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-21 21:42:30 +08: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 05:39:08 +08:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2017-11-21 21:42:30 +08:00
|
|
|
static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
|
2017-08-21 05:39:08 +08:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-21 21:42:30 +08:00
|
|
|
static void mmc_blk_remove_debugfs(struct mmc_card *card,
|
|
|
|
struct mmc_blk_data *md)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-08-21 05:39:08 +08:00
|
|
|
#endif /* CONFIG_DEBUG_FS */
|
|
|
|
|
2015-04-14 19:06:12 +08:00
|
|
|
static int mmc_blk_probe(struct mmc_card *card)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2021-08-09 14:40:22 +08:00
|
|
|
struct mmc_blk_data *md;
|
2021-03-03 20:20:49 +08:00
|
|
|
int ret = 0;
|
2008-09-06 16:57:57 +08:00
|
|
|
|
2005-05-21 17:27:02 +08:00
|
|
|
/*
|
|
|
|
* Check that the card supports the command class(es) we need.
|
|
|
|
*/
|
|
|
|
if (!(card->csd.cmdclass & CCC_BLOCK_READ))
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ENODEV;
|
|
|
|
|
2017-02-15 16:36:47 +08:00
|
|
|
mmc_fixup_device(card, mmc_blk_fixups);
|
2014-06-18 19:18:07 +08:00
|
|
|
|
2019-02-07 23:03:08 +08:00
|
|
|
card->complete_wq = alloc_workqueue("mmc_complete",
|
|
|
|
WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
|
2021-03-03 20:20:47 +08:00
|
|
|
if (!card->complete_wq) {
|
2019-02-07 23:03:08 +08:00
|
|
|
pr_err("Failed to create mmc completion workqueue");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
md = mmc_blk_alloc(card);
|
2021-03-03 20:20:49 +08:00
|
|
|
if (IS_ERR(md)) {
|
|
|
|
ret = PTR_ERR(md);
|
|
|
|
goto out_free;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2021-03-03 20:20:49 +08:00
|
|
|
ret = mmc_blk_alloc_parts(card, md);
|
|
|
|
if (ret)
|
2011-04-12 07:10:25 +08:00
|
|
|
goto out;
|
|
|
|
|
2017-08-21 05:39:08 +08:00
|
|
|
/* Add two debugfs entries */
|
2017-11-21 21:42:30 +08:00
|
|
|
mmc_blk_add_debugfs(card, md);
|
2017-08-21 05:39:08 +08:00
|
|
|
|
2013-05-02 20:02:38 +08: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.
|
|
|
|
*/
|
2022-07-13 11:36:34 +08:00
|
|
|
if (!mmc_card_sd_combo(card)) {
|
2013-05-02 20:02:38 +08:00
|
|
|
pm_runtime_set_active(&card->dev);
|
|
|
|
pm_runtime_enable(&card->dev);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
|
2021-03-03 20:20:49 +08:00
|
|
|
out:
|
2011-04-12 07:10:25 +08:00
|
|
|
mmc_blk_remove_parts(card, md);
|
|
|
|
mmc_blk_remove_req(md);
|
2021-03-03 20:20:49 +08:00
|
|
|
out_free:
|
|
|
|
destroy_workqueue(card->complete_wq);
|
|
|
|
return ret;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2015-04-14 19:06:12 +08:00
|
|
|
static void mmc_blk_remove(struct mmc_card *card)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2015-04-14 19:06:12 +08:00
|
|
|
struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2017-11-21 21:42:30 +08:00
|
|
|
mmc_blk_remove_debugfs(card, md);
|
2011-04-12 07:10:25 +08:00
|
|
|
mmc_blk_remove_parts(card, md);
|
2013-05-02 20:02:38 +08:00
|
|
|
pm_runtime_get_sync(&card->dev);
|
2018-05-17 15:47:42 +08: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);
|
|
|
|
}
|
2022-07-13 11:36:34 +08:00
|
|
|
if (!mmc_card_sd_combo(card))
|
2013-05-02 20:02:38 +08:00
|
|
|
pm_runtime_disable(&card->dev);
|
|
|
|
pm_runtime_put_noidle(&card->dev);
|
2011-04-12 07:10:25 +08:00
|
|
|
mmc_blk_remove_req(md);
|
2015-04-14 19:06:12 +08:00
|
|
|
dev_set_drvdata(&card->dev, NULL);
|
2019-02-07 23:03:08 +08:00
|
|
|
destroy_workqueue(card->complete_wq);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2015-04-14 19:06:12 +08:00
|
|
|
static int _mmc_blk_suspend(struct mmc_card *card)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2011-04-12 07:10:25 +08:00
|
|
|
struct mmc_blk_data *part_md;
|
2015-04-14 19:06:12 +08:00
|
|
|
struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (md) {
|
|
|
|
mmc_queue_suspend(&md->queue);
|
2011-04-12 07:10:25 +08:00
|
|
|
list_for_each_entry(part_md, &md->part, part) {
|
|
|
|
mmc_queue_suspend(&part_md->queue);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-14 19:06:12 +08:00
|
|
|
static void mmc_blk_shutdown(struct mmc_card *card)
|
2013-06-10 23:03:40 +08:00
|
|
|
{
|
2015-04-14 19:06:12 +08:00
|
|
|
_mmc_blk_suspend(card);
|
2013-06-10 23:03:40 +08:00
|
|
|
}
|
|
|
|
|
2014-10-06 17:29:42 +08:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
static int mmc_blk_suspend(struct device *dev)
|
2013-06-10 23:03:40 +08:00
|
|
|
{
|
2015-04-14 19:06:12 +08:00
|
|
|
struct mmc_card *card = mmc_dev_to_card(dev);
|
|
|
|
|
|
|
|
return _mmc_blk_suspend(card);
|
2013-06-10 23:03:40 +08:00
|
|
|
}
|
|
|
|
|
2014-10-06 17:29:42 +08:00
|
|
|
static int mmc_blk_resume(struct device *dev)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2011-04-12 07:10:25 +08:00
|
|
|
struct mmc_blk_data *part_md;
|
2014-10-06 20:34:09 +08:00
|
|
|
struct mmc_blk_data *md = dev_get_drvdata(dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (md) {
|
2011-04-12 07:10:25 +08: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 06:20:36 +08:00
|
|
|
mmc_queue_resume(&md->queue);
|
2011-04-12 07:10:25 +08:00
|
|
|
list_for_each_entry(part_md, &md->part, part) {
|
|
|
|
mmc_queue_resume(&part_md->queue);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-10-06 17:29:42 +08:00
|
|
|
static SIMPLE_DEV_PM_OPS(mmc_blk_pm_ops, mmc_blk_suspend, mmc_blk_resume);
|
|
|
|
|
2015-04-14 19:06:12 +08:00
|
|
|
static struct mmc_driver mmc_driver = {
|
|
|
|
.drv = {
|
|
|
|
.name = "mmcblk",
|
|
|
|
.pm = &mmc_blk_pm_ops,
|
|
|
|
},
|
2005-04-17 06:20:36 +08:00
|
|
|
.probe = mmc_blk_probe,
|
|
|
|
.remove = mmc_blk_remove,
|
2013-06-10 23:03:40 +08:00
|
|
|
.shutdown = mmc_blk_shutdown,
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int __init mmc_blk_init(void)
|
|
|
|
{
|
2008-09-13 18:02:07 +08:00
|
|
|
int res;
|
2005-04-17 06:20:36 +08: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 16:02:00 +08: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 09:19:57 +08:00
|
|
|
if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
|
|
|
|
pr_info("mmcblk: using %d minors per device\n", perdev_minors);
|
|
|
|
|
2014-11-06 11:35:09 +08:00
|
|
|
max_devices = min(MAX_DEVICES, (1 << MINORBITS) / perdev_minors);
|
2010-09-18 09:19:57 +08:00
|
|
|
|
2007-05-14 23:27:29 +08: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 16:02:00 +08:00
|
|
|
goto out_chrdev_unreg;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-09-13 18:02:07 +08: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 16:02:00 +08:00
|
|
|
goto out_blkdev_unreg;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-09-13 18:02:07 +08: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 16:02:00 +08:00
|
|
|
|
|
|
|
out_blkdev_unreg:
|
2008-09-13 18:02:07 +08: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 16:02:00 +08:00
|
|
|
out_chrdev_unreg:
|
|
|
|
unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
|
|
|
|
out_bus_unreg:
|
|
|
|
bus_unregister(&mmc_rpmb_bus_type);
|
2005-04-17 06:20:36 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit mmc_blk_exit(void)
|
|
|
|
{
|
|
|
|
mmc_unregister_driver(&mmc_driver);
|
2007-05-14 23:27:29 +08: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 16:02:00 +08:00
|
|
|
unregister_chrdev_region(mmc_rpmb_devt, MAX_DEVICES);
|
2018-03-29 06:18:31 +08:00
|
|
|
bus_unregister(&mmc_rpmb_bus_type);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
module_init(mmc_blk_init);
|
|
|
|
module_exit(mmc_blk_exit);
|
|
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
|
|
|
|
|