diff options
author | Tony Lindgren <tony@atomide.com> | 2012-06-06 09:45:50 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-06-06 09:45:50 -0400 |
commit | 3caf41406dd67b412abae7df86cc2a09bef9621f (patch) | |
tree | 0c6e4b99e644a6980b15c0c6889788c7e07e8c5c /drivers/mmc | |
parent | 4f837791d90bca76384b665eb2649feab169cc13 (diff) |
mmc: omap: Fix NULL pointer dereference if mmc_omap_new_slot() fails
Commit b01a4f1c (mmc: omap: convert to per instance workqueue) initializes
the workqueue too late causing the following:
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 5 [#1] SMP ARM
Modules linked in:
CPU: 0 Not tainted (3.4.0-08218-gb48b2c3 #158)
PC is at __queue_work+0x8/0x46c
LR is at queue_work_on+0x38/0x40
pc : [<c005bb4c>] lr : [<c005c00c>] psr: 60000193
sp : c0691e1c ip : 00000000 fp : c07374ac
r10: c7aae400 r9 : c0395700 r8 : 00000100
r7 : c0691e70 r6 : 00000000 r5 : 00000000 r4 : c7aae440
r3 : 00000001 r2 : c7aae440 r1 : 00000000 r0 : 00000000
Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 00c5387d Table: 80004000 DAC: 00000017
Process swapper/0 (pid: 0, stack limit = 0xc06902f8)
Stack: (0xc0691e1c to 0xc0692000)
Fix this by initializing the workqueue before mmc_omap_remove_slot()
get called. Tested on n770, looks like n800 at least still has some
other issue with MMC.
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/omap.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index feda3064b2cd..6b07730598da 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -1485,24 +1485,27 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev) | |||
1485 | } | 1485 | } |
1486 | 1486 | ||
1487 | host->nr_slots = pdata->nr_slots; | 1487 | host->nr_slots = pdata->nr_slots; |
1488 | |||
1489 | host->mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0); | ||
1490 | if (!host->mmc_omap_wq) | ||
1491 | goto err_plat_cleanup; | ||
1492 | |||
1488 | for (i = 0; i < pdata->nr_slots; i++) { | 1493 | for (i = 0; i < pdata->nr_slots; i++) { |
1489 | ret = mmc_omap_new_slot(host, i); | 1494 | ret = mmc_omap_new_slot(host, i); |
1490 | if (ret < 0) { | 1495 | if (ret < 0) { |
1491 | while (--i >= 0) | 1496 | while (--i >= 0) |
1492 | mmc_omap_remove_slot(host->slots[i]); | 1497 | mmc_omap_remove_slot(host->slots[i]); |
1493 | 1498 | ||
1494 | goto err_plat_cleanup; | 1499 | goto err_destroy_wq; |
1495 | } | 1500 | } |
1496 | } | 1501 | } |
1497 | 1502 | ||
1498 | host->reg_shift = (cpu_is_omap7xx() ? 1 : 2); | 1503 | host->reg_shift = (cpu_is_omap7xx() ? 1 : 2); |
1499 | 1504 | ||
1500 | host->mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0); | ||
1501 | if (!host->mmc_omap_wq) | ||
1502 | goto err_plat_cleanup; | ||
1503 | |||
1504 | return 0; | 1505 | return 0; |
1505 | 1506 | ||
1507 | err_destroy_wq: | ||
1508 | destroy_workqueue(host->mmc_omap_wq); | ||
1506 | err_plat_cleanup: | 1509 | err_plat_cleanup: |
1507 | if (pdata->cleanup) | 1510 | if (pdata->cleanup) |
1508 | pdata->cleanup(&pdev->dev); | 1511 | pdata->cleanup(&pdev->dev); |