When open some kernel debug options including LOCKDEP, hot plug sd
will meet the following dump message:
[ 883.769343] BUG: sleeping function called from invalid context at /home/b29397/work/projects/linux-imx/kernel/locki
ng/mutex.c:620
[ 883.781212] in_atomic(): 1, irqs_disabled(): 0, pid: 1497, name: kworker/0:2
[ 883.788307] 4 locks held by kworker/0:2/1497:
[ 883.792697] #0: ("events_freezable"){.+.+.+}, at: [<
ffff2000080db228>] process_one_work+0x120/0x3b8
[ 883.802021] #1: ((&(&host->detect)->work)){+.+.+.}, at: [<
ffff2000080db228>] process_one_work+0x120/0x3b8
[ 883.811854] #2: (&dev->mutex){......}, at: [<
ffff200008630b3c>] __device_attach+0x28/0x154
[ 883.820388] #3: (mmc_blk_lock){+.+...}, at: [<
ffff200008962414>] mmc_blk_alloc_req+0x60/0x3f8
[ 883.829181] CPU: 0 PID: 1497 Comm: kworker/0:2 Not tainted
4.9.11-03102-gd9ab0a1-dirty #523
[ 883.837542] Hardware name: Freescale i.MX8QXP MEK (DT)
[ 883.842692] Workqueue: events_freezable mmc_rescan
[ 883.847490] Call trace:
[ 883.849945] [<
ffff200008089234>] dump_backtrace+0x0/0x1e0
[ 883.855354] [<
ffff200008089428>] show_stack+0x14/0x1c
[ 883.860413] [<
ffff2000084046f4>] dump_stack+0xb0/0xec
[ 883.865468] [<
ffff2000080e8540>] ___might_sleep+0x144/0x1e4
[ 883.871044] [<
ffff2000080e8634>] __might_sleep+0x54/0x88
[ 883.876364] [<
ffff200008bfc99c>] mutex_lock_nested+0x3c/0x3cc
[ 883.882113] [<
ffff2000089cd164>] of_alias_get_id+0x34/0x98
[ 883.887602] [<
ffff20000895258c>] mmc_get_reserved_index+0x1c/0x24
[ 883.893702] [<
ffff20000896241c>] mmc_blk_alloc_req+0x68/0x3f8
[ 883.899450] [<
ffff2000089640d0>] mmc_blk_probe+0x74/0x2c0
[ 883.904856] [<
ffff2000089553b4>] mmc_bus_probe+0x1c/0x24
[ 883.910174] [<
ffff200008630fe4>] driver_probe_device+0x27c/0x418
[ 883.916182] [<
ffff200008631360>] __device_attach_driver+0x98/0x130
[ 883.922370] [<
ffff20000862ed48>] bus_for_each_drv+0x54/0x94
[ 883.927947] [<
ffff200008630bdc>] __device_attach+0xc8/0x154
[ 883.933525] [<
ffff200008631540>] device_initial_probe+0x10/0x18
[ 883.939450] [<
ffff20000862ff98>] bus_probe_device+0x94/0x9c
[ 883.945026] [<
ffff20000862dd08>] device_add+0x40c/0x58c
[ 883.950257] [<
ffff20000895589c>] mmc_add_card+0xf0/0x2a4
[ 883.955576] [<
ffff20000895bb78>] mmc_attach_sd+0x94/0x138
[ 883.960975] [<
ffff200008955070>] mmc_rescan+0x2d8/0x350
[ 883.966208] [<
ffff2000080db294>] process_one_work+0x18c/0x3b8
[ 883.971959] [<
ffff2000080db518>] worker_thread+0x58/0x440
[ 883.977362] [<
ffff2000080e1f48>] kthread+0xe0/0xf4
[ 883.982157] [<
ffff200008083680>] ret_from_fork+0x10/0x50
This is caused by commit
6e9e049fac59 ("mmc: Allow setting slot index via
devicetree alias"). Function mmc_get_reserved_index(), ida_simple_get() and
mmc_get_reserved_index() do not need addtional lock protect, these function
already contain the mutex_lock() inside. Only ida_get_new_above() need
required lock. spin_lock() nested with mutex_lock() or spin_lock() may cause
dead lock.
This patch fix the potential dead lock.
Fixes:
6e9e049fac59 ("mmc: Allow setting slot index via devicetree alias")
Reported-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
if (!ida_pre_get(&mmc_blk_ida, GFP_KERNEL))
return ERR_PTR(-ENOMEM);
- spin_lock(&mmc_blk_lock);
devidx = mmc_get_reserved_index(card->host);
if (devidx >= 0)
devidx = ida_simple_get(&mmc_blk_ida, devidx, devidx,
GFP_NOWAIT);
ret = 0;
- if (devidx < 0)
+ if (devidx < 0) {
+ spin_lock(&mmc_blk_lock);
ret = ida_get_new_above(&mmc_blk_ida,
mmc_first_nonreserved_index(), &devidx);
- spin_unlock(&mmc_blk_lock);
+ spin_unlock(&mmc_blk_lock);
+ }
if (ret == -EAGAIN)
goto again;
return NULL;
}
- spin_lock(&mmc_host_lock);
-
alias_id = mmc_get_reserved_index(host);
+
if (alias_id >= 0) {
min_idx = alias_id;
max_idx = alias_id + 1;
max_idx = 0;
}
+ spin_lock(&mmc_host_lock);
+
err = ida_get_new_above(&mmc_host_ida, min_idx, &host->index);
if (!err) {
if (host->index > max_idx) {