aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@freescale.com>2013-07-05 02:10:24 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:00:35 -0400
commitfe34e008e6ccddc578ee02e2d28c2edf7c5fa4fe (patch)
tree536a36111b66bdfa5819b40fcb241aa68fe7cb3b
parent65cc1ec3e9015918833c71c29e8f6b9994081574 (diff)
mmc: sdhci: request irq after sdhci_init() is called
Generally request_irq() should be called after hardware has been initialized into a sane state. However, sdhci driver currently calls request_irq() before sdhci_init(). At least, the following kernel panic seen on i.MX6 is caused by that. The sdhci controller on i.MX6 may have noisy glitch on DAT1 line, which will trigger SDIO interrupt handling once request_irq() is called. But at this point, the SDIO interrupt handler host->sdio_irq_thread has not been registered yet. Thus, we see the NULL pointer access with wake_up_process(host->sdio_irq_thread) in mmc_signal_sdio_irq(). sdhci-pltfm: SDHCI platform and OF driver helper mmc0: no vqmmc regulator found mmc0: no vmmc regulator found Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = 80004000 [00000000] *pgd=00000000 Internal error: Oops: 5 [#1] SMP ARM Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.0+ #3 task: 9f860000 ti: 9f862000 task.ti: 9f862000 PC is at wake_up_process+0xc/0x44 LR is at sdhci_irq+0x378/0x93c ... Backtrace: [<8004f75c>] (wake_up_process+0x0/0x44) from [<803fb698>] (sdhci_irq+0x378/0x93c) r4:9fa68000 r3:00000001 [<803fb320>] (sdhci_irq+0x0/0x93c) from [<80075154>] (handle_irq_event_percpu+0x54/0x19c) [<80075100>] (handle_irq_event_percpu+0x0/0x19c) from [<800752ec>] (handle_irq_event+0x50/0x70) [<8007529c>] (handle_irq_event+0x0/0x70) from [<80078324>] (handle_fasteoi_irq+0x9c/0x170) r5:00000001 r4:9f807900 [<80078288>] (handle_fasteoi_irq+0x0/0x170) from [<80074ac0>] (generic_handle_irq+0x28/0x38) r5:8071fd64 r4:00000036 [<80074a98>] (generic_handle_irq+0x0/0x38) from [<8000ee34>] (handle_IRQ+0x54/0xb4) r4:8072ab78 r3:00000140 [<8000ede0>] (handle_IRQ+0x0/0xb4) from [<80008600>] (gic_handle_irq+0x30/0x64) r8:00000036 r7:a080e100 r6:9f863cd0 r5:8072acbc r4:a080e10c r3:00000000 [<800085d0>] (gic_handle_irq+0x0/0x64) from [<8000e0c0>] (__irq_svc+0x40/0x54) ... ---[ end trace e9af3588936b63f0 ]--- Kernel panic - not syncing: Fatal exception in interrupt Fix the panic by simply reverse the calling sequence between request_irq() and sdhci_init(). Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
-rw-r--r--drivers/mmc/host/sdhci.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2ea429c27714..a821b7157b51 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3174,6 +3174,8 @@ int sdhci_add_host(struct sdhci_host *host)
3174 host->tuning_timer.function = sdhci_tuning_timer; 3174 host->tuning_timer.function = sdhci_tuning_timer;
3175 } 3175 }
3176 3176
3177 sdhci_init(host, 0);
3178
3177 ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 3179 ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
3178 mmc_hostname(mmc), host); 3180 mmc_hostname(mmc), host);
3179 if (ret) { 3181 if (ret) {
@@ -3182,8 +3184,6 @@ int sdhci_add_host(struct sdhci_host *host)
3182 goto untasklet; 3184 goto untasklet;
3183 } 3185 }
3184 3186
3185 sdhci_init(host, 0);
3186
3187#ifdef CONFIG_MMC_DEBUG 3187#ifdef CONFIG_MMC_DEBUG
3188 sdhci_dumpregs(host); 3188 sdhci_dumpregs(host);
3189#endif 3189#endif