diff options
author | Tony Lindgren <tony@atomide.com> | 2014-04-21 22:26:13 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2014-04-21 22:26:13 -0400 |
commit | efe8072316a899294212055c147d3d9adca940a4 (patch) | |
tree | dfff7743527b0cf46032bcbf5d3ecc9dcaa56bde /arch/arm/mach-omap2/gpmc.c | |
parent | ef78f3869c37c480f1d58462a760a40dabc823f4 (diff) |
ARM: OMAP2+: Fix oops for GPMC free
If gpmc_cs_remap() fails we will get an error because we are calling
release_resource() on an uninitialized resource. Let's fix that by
checking the resource flags. And while at it, let's also make
gpmc_cs_delete_mem() use the res pointer that we already have to
avoid confusion.
Without this patch we can get the following error:
omap-gpmc 6e000000.gpmc: cannot remap GPMC CS 1 to 0x01000300
Unable to handle kernel NULL pointer dereference at virtual address 00000018
...
(gpmc_cs_free+0x94/0xc8)
(gpmc_probe_generic_child+0x178/0x1ec)
(gpmc_probe_dt+0x1bc/0x2cc)
(gpmc_probe+0x250/0x44c)
(platform_drv_probe+0x3c/0x6c)
(really_probe+0x74/0x208)
(driver_probe_device+0x34/0x50)
(bus_for_each_drv+0x60/0x8c)
(device_attach+0x80/0xa4)
(bus_probe_device+0x88/0xb0)
(device_add+0x320/0x450)
(of_platform_device_create_pdata+0x80/0x9c)
(of_platform_bus_create+0xd0/0x170)
(of_platform_bus_create+0x12c/0x170)
(of_platform_populate+0x60/0x98)
(pdata_quirks_init+0x30/0x48)
(customize_machine+0x20/0x48)
(do_one_initcall+0x2c/0x14c)
(do_basic_setup+0x98/0xd8)
(kernel_init_freeable+0x12c/0x1e0)
(kernel_init+0x8/0xf0)
(ret_from_fork+0x14/0x2c)
Code: e1a04000 e59f0070 eb195136 e5942010 (e5923018)
Cc: Pekon Gupta <pekon@ti.com>
Reviewed-by: Javier Martinez Canillas <javier@dowhile0.org>
Signed-off-by: tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap2/gpmc.c')
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index ab43755364f5..84e57e6fbc26 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -501,7 +501,7 @@ static int gpmc_cs_delete_mem(int cs) | |||
501 | int r; | 501 | int r; |
502 | 502 | ||
503 | spin_lock(&gpmc_mem_lock); | 503 | spin_lock(&gpmc_mem_lock); |
504 | r = release_resource(&gpmc_cs_mem[cs]); | 504 | r = release_resource(res); |
505 | res->start = 0; | 505 | res->start = 0; |
506 | res->end = 0; | 506 | res->end = 0; |
507 | spin_unlock(&gpmc_mem_lock); | 507 | spin_unlock(&gpmc_mem_lock); |
@@ -586,6 +586,8 @@ EXPORT_SYMBOL(gpmc_cs_request); | |||
586 | 586 | ||
587 | void gpmc_cs_free(int cs) | 587 | void gpmc_cs_free(int cs) |
588 | { | 588 | { |
589 | struct resource *res = &gpmc_cs_mem[cs]; | ||
590 | |||
589 | spin_lock(&gpmc_mem_lock); | 591 | spin_lock(&gpmc_mem_lock); |
590 | if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) { | 592 | if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) { |
591 | printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs); | 593 | printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs); |
@@ -594,7 +596,8 @@ void gpmc_cs_free(int cs) | |||
594 | return; | 596 | return; |
595 | } | 597 | } |
596 | gpmc_cs_disable_mem(cs); | 598 | gpmc_cs_disable_mem(cs); |
597 | release_resource(&gpmc_cs_mem[cs]); | 599 | if (res->flags) |
600 | release_resource(res); | ||
598 | gpmc_cs_set_reserved(cs, 0); | 601 | gpmc_cs_set_reserved(cs, 0); |
599 | spin_unlock(&gpmc_mem_lock); | 602 | spin_unlock(&gpmc_mem_lock); |
600 | } | 603 | } |