diff mbox

[V2,1/2] mmc: sdhci-esdhc-imx: fix access hardirq-unsafe lock in atomic context

Message ID 1388042634-17281-1-git-send-email-b29396@freescale.com (mailing list archive)
State New, archived
Headers show

Commit Message

Aisheng Dong Dec. 26, 2013, 7:23 a.m. UTC
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

Cc: Chris Ball <cjb@laptop.org>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
Fixes: 0ddf03c mmc: esdhc-imx: parse max-frequency from devicetree
Signed-off-by: Dong Aisheng <b29396@freescale.com>
---
ChangeLog:
no changes
---
 drivers/mmc/host/sdhci-esdhc-imx.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)

Comments

Shawn Guo Dec. 31, 2013, 5:24 a.m. UTC | #1
On Thu, Dec 26, 2013 at 03:23:53PM +0800, Dong Aisheng wrote:
> 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.

<snip>

> Cc: Chris Ball <cjb@laptop.org>
> Cc: Fabio Estevam <fabio.estevam@freescale.com>
> Cc: Shawn Guo <shawn.guo@linaro.org>

For both,

Acked-by: Shawn Guo <shawn.guo@linaro.org>

> Fixes: 0ddf03c mmc: esdhc-imx: parse max-frequency from devicetree
> Signed-off-by: Dong Aisheng <b29396@freescale.com>

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Dong Aisheng Jan. 13, 2014, 10:52 a.m. UTC | #2
Hi Chris,

On Tue, Dec 31, 2013 at 1:24 PM, Shawn Guo <shawn.guo@linaro.org> wrote:
> On Thu, Dec 26, 2013 at 03:23:53PM +0800, Dong Aisheng wrote:
>> 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.
>
> <snip>
>
>> Cc: Chris Ball <cjb@laptop.org>
>> Cc: Fabio Estevam <fabio.estevam@freescale.com>
>> Cc: Shawn Guo <shawn.guo@linaro.org>
>
> For both,
>
> Acked-by: Shawn Guo <shawn.guo@linaro.org>
>
>> Fixes: 0ddf03c mmc: esdhc-imx: parse max-frequency from devicetree
>> Signed-off-by: Dong Aisheng <b29396@freescale.com>
>
>

Can we make patch 1 go into 3.13 final since the issue exists
since 3.13 rc1.

Patch 2 in that series is the fix for sdhci-esdhc-imx runtime pm which is
newly added in chris/mmc-next and seems target for 3.14.

BTW, pls add:
Tested-by: Philippe De Muyter <phdm@macqel.be>

See:
https://lkml.org/lkml/2014/1/13/77

Regards
Dong Aisheng

> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Chris Ball Jan. 13, 2014, 6:41 p.m. UTC | #3
Hi,

On Thu, Dec 26 2013, Dong Aisheng wrote:
> 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 ]

Thanks, pushed to mmc-next.

- Chris.
Ed Jan. 22, 2014, 5:09 p.m. UTC | #4
Tested-by: Edward Cragg <edward.cragg@codethink.co.uk>

I tested this patch on a i.MX6q Wandboard, it appears to have fixed the issue on this board. Tested on mainline v3.13.
 
On Thu, 26 Dec 2013 15:23:53 +0800, Dong Aisheng wrote:
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
> 
> Cc: Chris Ball <cjb@xxxxxxxxxx>
> Cc: Fabio Estevam <fabio.estevam@xxxxxxxxxxxxx>
> Cc: Shawn Guo <shawn.guo@xxxxxxxxxx>
> Fixes: 0ddf03c mmc: esdhc-imx: parse max-frequency from devicetree
> Signed-off-by: Dong Aisheng <b29396@xxxxxxxxxxxxx>
> ---
> ChangeLog:
> no changes
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c |   12 +++++-------
>  1 files changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 2a04847..745ee1e 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -576,19 +576,17 @@ static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
>  	struct pltfm_imx_data *imx_data = pltfm_host->priv;
>  	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
>  
> -	u32 f_host = clk_get_rate(pltfm_host->clk);
> -
> -	if (boarddata->f_max && (boarddata->f_max < f_host))
> +	if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock))
>  		return boarddata->f_max;
>  	else
> -		return f_host;
> +		return pltfm_host->clock;
>  }
>  
>  static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
>  {
>  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>  
> -	return clk_get_rate(pltfm_host->clk) / 256 / 16;
> +	return pltfm_host->clock / 256 / 16;
>  }
>  
>  static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
> @@ -596,7 +594,7 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
>  {
>  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>  	struct pltfm_imx_data *imx_data = pltfm_host->priv;
> -	unsigned int host_clock = clk_get_rate(pltfm_host->clk);
> +	unsigned int host_clock = pltfm_host->clock;
>  	int pre_div = 2;
>  	int div = 1;
>  	u32 temp, val;
> @@ -1017,7 +1015,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  	}
>  
>  	pltfm_host->clk = imx_data->clk_per;
> -
> +	pltfm_host->clock = clk_get_rate(pltfm_host->clk);
>  	clk_prepare_enable(imx_data->clk_per);
>  	clk_prepare_enable(imx_data->clk_ipg);
>  	clk_prepare_enable(imx_data->clk_ahb);
> -- 
> 1.7.2.rc3
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@xxxxxxxxxxxxxxxxxxx
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 2a04847..745ee1e 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -576,19 +576,17 @@  static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
 	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
-	u32 f_host = clk_get_rate(pltfm_host->clk);
-
-	if (boarddata->f_max && (boarddata->f_max < f_host))
+	if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock))
 		return boarddata->f_max;
 	else
-		return f_host;
+		return pltfm_host->clock;
 }
 
 static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 
-	return clk_get_rate(pltfm_host->clk) / 256 / 16;
+	return pltfm_host->clock / 256 / 16;
 }
 
 static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
@@ -596,7 +594,7 @@  static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
-	unsigned int host_clock = clk_get_rate(pltfm_host->clk);
+	unsigned int host_clock = pltfm_host->clock;
 	int pre_div = 2;
 	int div = 1;
 	u32 temp, val;
@@ -1017,7 +1015,7 @@  static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	}
 
 	pltfm_host->clk = imx_data->clk_per;
-
+	pltfm_host->clock = clk_get_rate(pltfm_host->clk);
 	clk_prepare_enable(imx_data->clk_per);
 	clk_prepare_enable(imx_data->clk_ipg);
 	clk_prepare_enable(imx_data->clk_ahb);