Sometimes we may meet the following lockdep issue.
The root cause is .set_clock callback is executed with spin_lock_irqsave
in sdhci_do_set_ios. However, the IMX set_clock callback will try to access
clk_get_rate which is using a mutex lock.
The fix avoids access mutex in .set_clock callback by initializing the
pltfm_host->clock at probe time and use it later instead of calling
clk_get_rate again in atomic context.
[ INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected ]
3.13.0-rc1+ #285 Not tainted
------------------------------------------------------
kworker/u8:1/29 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire:
(prepare_lock){+.+...}, at: [<
80480b08>] clk_prepare_lock+0x44/0xe4
and this task is already holding:
(&(&host->lock)->rlock#2){-.-...}, at: [<
804611f4>] sdhci_do_set_ios+0x20/0x720
which would create a new lock dependency:
(&(&host->lock)->rlock#2){-.-...} -> (prepare_lock){+.+...}
but this new dependency connects a HARDIRQ-irq-safe lock:
(&(&host->lock)->rlock#2){-.-...}
... which became HARDIRQ-irq-safe at:
[<
8005f030>] mark_lock+0x140/0x6ac
[<
80060760>] __lock_acquire+0xb30/0x1cbc
[<
800620d0>] lock_acquire+0x70/0x84
[<
8061d2f0>] _raw_spin_lock+0x30/0x40
[<
80460668>] sdhci_irq+0x24/0xa68
[<
8006b1d4>] handle_irq_event_percpu+0x54/0x18c
[<
8006b350>] handle_irq_event+0x44/0x64
[<
8006e50c>] handle_fasteoi_irq+0xa0/0x170
[<
8006a8f0>] generic_handle_irq+0x30/0x44
[<
8000f238>] handle_IRQ+0x54/0xbc
[<
8000864c>] gic_handle_irq+0x30/0x64
[<
80013024>] __irq_svc+0x44/0x5c
[<
80614c58>] printk+0x38/0x40
[<
804622a8>] sdhci_add_host+0x844/0xbcc
[<
80464948>] sdhci_esdhc_imx_probe+0x378/0x67c
[<
8032ee88>] platform_drv_probe+0x20/0x50
[<
8032d48c>] driver_probe_device+0x118/0x234
[<
8032d690>] __driver_attach+0x9c/0xa0
[<
8032b89c>] bus_for_each_dev+0x68/0x9c
[<
8032cf44>] driver_attach+0x20/0x28
[<
8032cbc8>] bus_add_driver+0x148/0x1f4
[<
8032dce0>] driver_register+0x80/0x100
[<
8032ee54>] __platform_driver_register+0x50/0x64
[<
8084b094>] sdhci_esdhc_imx_driver_init+0x18/0x20
[<
80008980>] do_one_initcall+0x108/0x16c
[<
8081cca4>] kernel_init_freeable+0x10c/0x1d0
[<
80611c50>] kernel_init+0x10/0x120
[<
8000e9c8>] ret_from_fork+0x14/0x2c
to a HARDIRQ-irq-unsafe lock:
(prepare_lock){+.+...}
... which became HARDIRQ-irq-unsafe at:
... [<
8005f030>] mark_lock+0x140/0x6ac
[<
8005f604>] mark_held_locks+0x68/0x12c
[<
8005f780>] trace_hardirqs_on_caller+0xb8/0x1d8
[<
8005f8b4>] trace_hardirqs_on+0x14/0x18
[<
8061a130>] mutex_trylock+0x180/0x20c
[<
80480ad8>] clk_prepare_lock+0x14/0xe4
[<
804816a4>] clk_notifier_register+0x28/0xf0
[<
80015120>] twd_clk_init+0x50/0x68
[<
80008980>] do_one_initcall+0x108/0x16c
[<
8081cca4>] kernel_init_freeable+0x10c/0x1d0
[<
80611c50>] kernel_init+0x10/0x120
[<
8000e9c8>] ret_from_fork+0x14/0x2c
other info that might help us debug this:
Possible interrupt unsafe locking scenario:
CPU0 CPU1
---- ----
lock(prepare_lock);
local_irq_disable();
lock(&(&host->lock)->rlock#2);
lock(prepare_lock);
<Interrupt>
lock(&(&host->lock)->rlock#2);
*** DEADLOCK ***
3 locks held by kworker/u8:1/29:
#0: (kmmcd){.+.+.+}, at: [<
8003db18>] process_one_work+0x128/0x468
#1: ((&(&host->detect)->work)){+.+.+.}, at: [<
8003db18>] process_one_work+0x128/0x468
#2: (&(&host->lock)->rlock#2){-.-...}, at: [<
804611f4>] sdhci_do_set_ios+0x20/0x720
the dependencies between HARDIRQ-irq-safe lock and the holding lock:
-> (&(&host->lock)->rlock#2){-.-...} ops: 330 {
IN-HARDIRQ-W at:
[<
8005f030>] mark_lock+0x140/0x6ac
[<
80060760>] __lock_acquire+0xb30/0x1cbc
[<
800620d0>] lock_acquire+0x70/0x84
[<
8061d2f0>] _raw_spin_lock+0x30/0x40
[<
80460668>] sdhci_irq+0x24/0xa68
[<
8006b1d4>] handle_irq_event_percpu+0x54/0x18c
[<
8006b350>] handle_irq_event+0x44/0x64
[<
8006e50c>] handle_fasteoi_irq+0xa0/0x170
[<
8006a8f0>] generic_handle_irq+0x30/0x44
[<
8000f238>] handle_IRQ+0x54/0xbc
[<
8000864c>] gic_handle_irq+0x30/0x64
[<
80013024>] __irq_svc+0x44/0x5c
[<
80614c58>] printk+0x38/0x40
[<
804622a8>] sdhci_add_host+0x844/0xbcc
[<
80464948>] sdhci_esdhc_imx_probe+0x378/0x67c
[<
8032ee88>] platform_drv_probe+0x20/0x50
[<
8032d48c>] driver_probe_device+0x118/0x234
[<
8032d690>] __driver_attach+0x9c/0xa0
[<
8032b89c>] bus_for_each_dev+0x68/0x9c
[<
8032cf44>] driver_attach+0x20/0x28
[<
8032cbc8>] bus_add_driver+0x148/0x1f4
[<
8032dce0>] driver_register+0x80/0x100
[<
8032ee54>] __platform_driver_register+0x50/0x64
[<
8084b094>] sdhci_esdhc_imx_driver_init+0x18/0x20
[<
80008980>] do_one_initcall+0x108/0x16c
[<
8081cca4>] kernel_init_freeable+0x10c/0x1d0
[<
80611c50>] kernel_init+0x10/0x120
[<
8000e9c8>] ret_from_fork+0x14/0x2c
IN-SOFTIRQ-W at:
[<
8005f030>] mark_lock+0x140/0x6ac
[<
80060204>] __lock_acquire+0x5d4/0x1cbc
[<
800620d0>] lock_acquire+0x70/0x84
[<
8061d40c>] _raw_spin_lock_irqsave+0x40/0x54
[<
8045e4a4>] sdhci_tasklet_finish+0x1c/0x120
[<
8002b538>] tasklet_action+0xa0/0x15c
[<
8002b778>] __do_softirq+0x118/0x290
[<
8002bcf4>] irq_exit+0xb4/0x10c
[<
8000f240>] handle_IRQ+0x5c/0xbc
[<
8000864c>] gic_handle_irq+0x30/0x64
[<
80013024>] __irq_svc+0x44/0x5c
[<
80614c58>] printk+0x38/0x40
[<
804622a8>] sdhci_add_host+0x844/0xbcc
[<
80464948>] sdhci_esdhc_imx_probe+0x378/0x67c
[<
8032ee88>] platform_drv_probe+0x20/0x50
[<
8032d48c>] driver_probe_device+0x118/0x234
[<
8032d690>] __driver_attach+0x9c/0xa0
[<
8032b89c>] bus_for_each_dev+0x68/0x9c
[<
8032cf44>] driver_attach+0x20/0x28
[<
8032cbc8>] bus_add_driver+0x148/0x1f4
[<
8032dce0>] driver_register+0x80/0x100
[<
8032ee54>] __platform_driver_register+0x50/0x64
[<
8084b094>] sdhci_esdhc_imx_driver_init+0x18/0x20
[<
80008980>] do_one_initcall+0x108/0x16c
[<
8081cca4>] kernel_init_freeable+0x10c/0x1d0
[<
80611c50>] kernel_init+0x10/0x120
[<
8000e9c8>] ret_from_fork+0x14/0x2c
INITIAL USE at:
[<
8005f030>] mark_lock+0x140/0x6ac
[<
8005ff0c>] __lock_acquire+0x2dc/0x1cbc
[<
800620d0>] lock_acquire+0x70/0x84
[<
8061d40c>] _raw_spin_lock_irqsave+0x40/0x54
[<
804611f4>] sdhci_do_set_ios+0x20/0x720
[<
80461924>] sdhci_set_ios+0x30/0x3c
[<
8044cea0>] mmc_power_up+0x6c/0xd0
[<
8044dac4>] mmc_start_host+0x60/0x70
[<
8044eb3c>] mmc_add_host+0x60/0x88
[<
8046225c>] sdhci_add_host+0x7f8/0xbcc
[<
80464948>] sdhci_esdhc_imx_probe+0x378/0x67c
[<
8032ee88>] platform_drv_probe+0x20/0x50
[<
8032d48c>] driver_probe_device+0x118/0x234
[<
8032d690>] __driver_attach+0x9c/0xa0
[<
8032b89c>] bus_for_each_dev+0x68/0x9c
[<
8032cf44>] driver_attach+0x20/0x28
[<
8032cbc8>] bus_add_driver+0x148/0x1f4
[<
8032dce0>] driver_register+0x80/0x100
[<
8032ee54>] __platform_driver_register+0x50/0x64
[<
8084b094>] sdhci_esdhc_imx_driver_init+0x18/0x20
[<
80008980>] do_one_initcall+0x108/0x16c
[<
8081cca4>] kernel_init_freeable+0x10c/0x1d0
[<
80611c50>] kernel_init+0x10/0x120
[<
8000e9c8>] ret_from_fork+0x14/0x2c
}
... key at: [<
80e040e8>] __key.26952+0x0/0x8
... acquired at:
[<
8005eb60>] check_usage+0x3d0/0x5c0
[<
8005edac>] check_irq_usage+0x5c/0xb8
[<
80060d38>] __lock_acquire+0x1108/0x1cbc
[<
800620d0>] lock_acquire+0x70/0x84
[<
8061a210>] mutex_lock_nested+0x54/0x3c0
[<
80480b08>] clk_prepare_lock+0x44/0xe4
[<
8048188c>] clk_get_rate+0x14/0x64
[<
8046374c>] esdhc_pltfm_set_clock+0x20/0x2a4
[<
8045d70c>] sdhci_set_clock+0x4c/0x498
[<
80461518>] sdhci_do_set_ios+0x344/0x720
[<
80461924>] sdhci_set_ios+0x30/0x3c
[<
8044c390>] __mmc_set_clock+0x44/0x60
[<
8044cd4c>] mmc_set_clock+0x10/0x14
[<
8044f8f4>] mmc_init_card+0x1b4/0x1520
[<
80450f00>] mmc_attach_mmc+0xb4/0x194
[<
8044da08>] mmc_rescan+0x294/0x2f0
[<
8003db94>] process_one_work+0x1a4/0x468
[<
8003e850>] worker_thread+0x118/0x3e0
[<
80044de0>] kthread+0xd4/0xf0
[<
8000e9c8>] ret_from_fork+0x14/0x2c
the dependencies between the lock to be acquired and HARDIRQ-irq-unsafe lock:
-> (prepare_lock){+.+...} ops: 395 {
HARDIRQ-ON-W at:
[<
8005f030>] mark_lock+0x140/0x6ac
[<
8005f604>] mark_held_locks+0x68/0x12c
[<
8005f780>] trace_hardirqs_on_caller+0xb8/0x1d8
[<
8005f8b4>] trace_hardirqs_on+0x14/0x18
[<
8061a130>] mutex_trylock+0x180/0x20c
[<
80480ad8>] clk_prepare_lock+0x14/0xe4
[<
804816a4>] clk_notifier_register+0x28/0xf0
[<
80015120>] twd_clk_init+0x50/0x68
[<
80008980>] do_one_initcall+0x108/0x16c
[<
8081cca4>] kernel_init_freeable+0x10c/0x1d0
[<
80611c50>] kernel_init+0x10/0x120
[<
8000e9c8>] ret_from_fork+0x14/0x2c
SOFTIRQ-ON-W at:
[<
8005f030>] mark_lock+0x140/0x6ac
[<
8005f604>] mark_held_locks+0x68/0x12c
[<
8005f7c8>] trace_hardirqs_on_caller+0x100/0x1d8
[<
8005f8b4>] trace_hardirqs_on+0x14/0x18
[<
8061a130>] mutex_trylock+0x180/0x20c
[<
80480ad8>] clk_prepare_lock+0x14/0xe4
[<
804816a4>] clk_notifier_register+0x28/0xf0
[<
80015120>] twd_clk_init+0x50/0x68
[<
80008980>] do_one_initcall+0x108/0x16c
[<
8081cca4>] kernel_init_freeable+0x10c/0x1d0
[<
80611c50>] kernel_init+0x10/0x120
[<
8000e9c8>] ret_from_fork+0x14/0x2c
INITIAL USE at:
[<
8005f030>] mark_lock+0x140/0x6ac
[<
8005ff0c>] __lock_acquire+0x2dc/0x1cbc
[<
800620d0>] lock_acquire+0x70/0x84
[<
8061a0c8>] mutex_trylock+0x118/0x20c
[<
80480ad8>] clk_prepare_lock+0x14/0xe4
[<
80482af8>] __clk_init+0x1c/0x45c
[<
8048306c>] _clk_register+0xd0/0x170
[<
80483148>] clk_register+0x3c/0x7c
[<
80483b4c>] clk_register_fixed_rate+0x88/0xd8
[<
80483c04>] of_fixed_clk_setup+0x68/0x94
[<
8084c6fc>] of_clk_init+0x44/0x68
[<
808202b0>] time_init+0x2c/0x38
[<
8081ca14>] start_kernel+0x1e4/0x368
[<
10008074>] 0x10008074
}
... key at: [<
808afebc>] prepare_lock+0x38/0x48
... acquired at:
[<
8005eb94>] check_usage+0x404/0x5c0
[<
8005edac>] check_irq_usage+0x5c/0xb8
[<
80060d38>] __lock_acquire+0x1108/0x1cbc
[<
800620d0>] lock_acquire+0x70/0x84
[<
8061a210>] mutex_lock_nested+0x54/0x3c0
[<
80480b08>] clk_prepare_lock+0x44/0xe4
[<
8048188c>] clk_get_rate+0x14/0x64
[<
8046374c>] esdhc_pltfm_set_clock+0x20/0x2a4
[<
8045d70c>] sdhci_set_clock+0x4c/0x498
[<
80461518>] sdhci_do_set_ios+0x344/0x720
[<
80461924>] sdhci_set_ios+0x30/0x3c
[<
8044c390>] __mmc_set_clock+0x44/0x60
[<
8044cd4c>] mmc_set_clock+0x10/0x14
[<
8044f8f4>] mmc_init_card+0x1b4/0x1520
[<
80450f00>] mmc_attach_mmc+0xb4/0x194
[<
8044da08>] mmc_rescan+0x294/0x2f0
[<
8003db94>] process_one_work+0x1a4/0x468
[<
8003e850>] worker_thread+0x118/0x3e0
[<
80044de0>] kthread+0xd4/0xf0
[<
8000e9c8>] ret_from_fork+0x14/0x2c
stack backtrace:
CPU: 2 PID: 29 Comm: kworker/u8:1 Not tainted 3.13.0-rc1+ #285
Workqueue: kmmcd mmc_rescan
Backtrace:
[<
80012160>] (dump_backtrace+0x0/0x10c) from [<
80012438>] (show_stack+0x18/0x1c)
r6:
00000000 r5:
00000000 r4:
8088ecc8 r3:
bfa11200
[<
80012420>] (show_stack+0x0/0x1c) from [<
80616b14>] (dump_stack+0x84/0x9c)
[<
80616a90>] (dump_stack+0x0/0x9c) from [<
8005ebb4>] (check_usage+0x424/0x5c0)
r5:
80979940 r4:
bfa29b44
[<
8005e790>] (check_usage+0x0/0x5c0) from [<
8005edac>] (check_irq_usage+0x5c/0xb8)
[<
8005ed50>] (check_irq_usage+0x0/0xb8) from [<
80060d38>] (__lock_acquire+0x1108/0x1cbc)
r8:
bfa115e8 r7:
80df9884 r6:
80dafa9c r5:
00000003 r4:
bfa115d0
[<
8005fc30>] (__lock_acquire+0x0/0x1cbc) from [<
800620d0>] (lock_acquire+0x70/0x84)
[<
80062060>] (lock_acquire+0x0/0x84) from [<
8061a210>] (mutex_lock_nested+0x54/0x3c0)
r7:
bfa11200 r6:
80dafa9c r5:
00000000 r4:
80480b08
[<
8061a1bc>] (mutex_lock_nested+0x0/0x3c0) from [<
80480b08>] (clk_prepare_lock+0x44/0xe4)
[<
80480ac4>] (clk_prepare_lock+0x0/0xe4) from [<
8048188c>] (clk_get_rate+0x14/0x64)
r6:
03197500 r5:
bf0e9aa8 r4:
bf827400 r3:
808ae128
[<
80481878>] (clk_get_rate+0x0/0x64) from [<
8046374c>] (esdhc_pltfm_set_clock+0x20/0x2a4)
r5:
bf0e9aa8 r4:
bf0e9c40
[<
8046372c>] (esdhc_pltfm_set_clock+0x0/0x2a4) from [<
8045d70c>] (sdhci_set_clock+0x4c/0x498)
[<
8045d6c0>] (sdhci_set_clock+0x0/0x498) from [<
80461518>] (sdhci_do_set_ios+0x344/0x720)
r8:
0000003b r7:
20000113 r6:
bf0e9d68 r5:
bf0e9aa8 r4:
bf0e9c40
r3:
00000000
[<
804611d4>] (sdhci_do_set_ios+0x0/0x720) from [<
80461924>] (sdhci_set_ios+0x30/0x3c)
r9:
00000004 r8:
bf131000 r7:
bf131048 r6:
00000000 r5:
bf0e9aa8
r4:
bf0e9800
[<
804618f4>] (sdhci_set_ios+0x0/0x3c) from [<
8044c390>] (__mmc_set_clock+0x44/0x60)
r5:
03197500 r4:
bf0e9800
[<
8044c34c>] (__mmc_set_clock+0x0/0x60) from [<
8044cd4c>] (mmc_set_clock+0x10/0x14)
r5:
00000000 r4:
bf0e9800
[<
8044cd3c>] (mmc_set_clock+0x0/0x14) from [<
8044f8f4>] (mmc_init_card+0x1b4/0x1520)
[<
8044f740>] (mmc_init_card+0x0/0x1520) from [<
80450f00>] (mmc_attach_mmc+0xb4/0x194)
[<
80450e4c>] (mmc_attach_mmc+0x0/0x194) from [<
8044da08>] (mmc_rescan+0x294/0x2f0)
r5:
8065f358 r4:
bf0e9af8
[<
8044d774>] (mmc_rescan+0x0/0x2f0) from [<
8003db94>] (process_one_work+0x1a4/0x468)
r8:
00000000 r7:
bfa29eb0 r6:
bf80dc00 r5:
bf0e9af8 r4:
bf9e3f00
r3:
8044d774
[<
8003d9f0>] (process_one_work+0x0/0x468) from [<
8003e850>] (worker_thread+0x118/0x3e0)
[<
8003e738>] (worker_thread+0x0/0x3e0) from [<
80044de0>] (kthread+0xd4/0xf0)
[<
80044d0c>] (kthread+0x0/0xf0) from [<
8000e9c8>] (ret_from_fork+0x14/0x2c)
r7:
00000000 r6:
00000000 r5:
80044d0c r4:
bf9e7f00
Fixes: 0ddf03c mmc: esdhc-imx: parse max-frequency from devicetree
Signed-off-by: Dong Aisheng <b29396@freescale.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Tested-by: Philippe De Muyter <phdm@macqel.be>
Cc: stable <stable@vger.kernel.org> # 3.13
Signed-off-by: Chris Ball <chris@printf.net>