https://github.com/torvalds/linux
Revision 1a41741fd60b0a2d1102c3d1ff9d58cb324a8d29 authored by Viresh Kumar on 27 October 2016, 10:20:18 UTC, committed by Lee Jones on 25 November 2016, 11:10:55 UTC
The kernel WARNs and then crashes today if wm8994_device_init() fails
after calling devm_regulator_bulk_get().

That happens because there are multiple devices involved here and the
order in which managed resources are freed isn't correct.

The regulators are added as children of wm8994->dev.  Whereas,
devm_regulator_bulk_get() receives wm8994->dev as the device, though it
gets the same regulators which were added as children of wm8994->dev
earlier.

During failures, the children are removed first and the core eventually
calls regulator_unregister() for them. As regulator_put() was never done
for them (opposite of devm_regulator_bulk_get()), the kernel WARNs at

	WARN_ON(rdev->open_count);

And eventually it crashes from debugfs_remove_recursive().

--------x------------------x----------------

 wm8994 3-001a: Device is not a WM8994, ID is 0
 ------------[ cut here ]------------
 WARNING: CPU: 0 PID: 1 at /mnt/ssd/all/work/repos/devel/linux/drivers/regulator/core.c:4072 regulator_unregister+0xc8/0xd0
 Modules linked in:
 CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.8.0-rc6-00154-g54fe84cbd50b #41
 Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
 [<c010e24c>] (unwind_backtrace) from [<c010af38>] (show_stack+0x10/0x14)
 [<c010af38>] (show_stack) from [<c032a1c4>] (dump_stack+0x88/0x9c)
 [<c032a1c4>] (dump_stack) from [<c011a98c>] (__warn+0xe8/0x100)
 [<c011a98c>] (__warn) from [<c011aa54>] (warn_slowpath_null+0x20/0x28)
 [<c011aa54>] (warn_slowpath_null) from [<c0384a0c>] (regulator_unregister+0xc8/0xd0)
 [<c0384a0c>] (regulator_unregister) from [<c0406434>] (release_nodes+0x16c/0x1dc)
 [<c0406434>] (release_nodes) from [<c04039c4>] (__device_release_driver+0x8c/0x110)
 [<c04039c4>] (__device_release_driver) from [<c0403a64>] (device_release_driver+0x1c/0x28)
 [<c0403a64>] (device_release_driver) from [<c0402b24>] (bus_remove_device+0xd8/0x104)
 [<c0402b24>] (bus_remove_device) from [<c03ffcd8>] (device_del+0x10c/0x218)
 [<c03ffcd8>] (device_del) from [<c0404e4c>] (platform_device_del+0x1c/0x88)
 [<c0404e4c>] (platform_device_del) from [<c0404ec4>] (platform_device_unregister+0xc/0x20)
 [<c0404ec4>] (platform_device_unregister) from [<c0428bc0>] (mfd_remove_devices_fn+0x5c/0x64)
 [<c0428bc0>] (mfd_remove_devices_fn) from [<c03ff9d8>] (device_for_each_child_reverse+0x4c/0x78)
 [<c03ff9d8>] (device_for_each_child_reverse) from [<c04288c4>] (mfd_remove_devices+0x20/0x30)
 [<c04288c4>] (mfd_remove_devices) from [<c042758c>] (wm8994_device_init+0x2ac/0x7f0)
 [<c042758c>] (wm8994_device_init) from [<c04f14a8>] (i2c_device_probe+0x178/0x1fc)
 [<c04f14a8>] (i2c_device_probe) from [<c04036fc>] (driver_probe_device+0x214/0x2c0)
 [<c04036fc>] (driver_probe_device) from [<c0403854>] (__driver_attach+0xac/0xb0)
 [<c0403854>] (__driver_attach) from [<c0401a74>] (bus_for_each_dev+0x68/0x9c)
 [<c0401a74>] (bus_for_each_dev) from [<c0402cf0>] (bus_add_driver+0x1a0/0x218)
 [<c0402cf0>] (bus_add_driver) from [<c040406c>] (driver_register+0x78/0xf8)
 [<c040406c>] (driver_register) from [<c04f20a0>] (i2c_register_driver+0x34/0x84)
 [<c04f20a0>] (i2c_register_driver) from [<c01017d0>] (do_one_initcall+0x40/0x170)
 [<c01017d0>] (do_one_initcall) from [<c0a00dbc>] (kernel_init_freeable+0x15c/0x1fc)
 [<c0a00dbc>] (kernel_init_freeable) from [<c06e07b0>] (kernel_init+0x8/0x114)
 [<c06e07b0>] (kernel_init) from [<c0107978>] (ret_from_fork+0x14/0x3c)
 ---[ end trace 0919d3d0bc998260 ]---

 [snip..]

 Unable to handle kernel NULL pointer dereference at virtual address 00000078
 pgd = c0004000
 [00000078] *pgd=00000000
 Internal error: Oops: 5 [#1] PREEMPT SMP ARM
 Modules linked in:
 CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       4.8.0-rc6-00154-g54fe84cbd50b #41
 Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
 task: ee874000 task.stack: ee878000
 PC is at down_write+0x14/0x54
 LR is at debugfs_remove_recursive+0x30/0x150

 [snip..]

 [<c06e489c>] (down_write) from [<c02e9954>] (debugfs_remove_recursive+0x30/0x150)
 [<c02e9954>] (debugfs_remove_recursive) from [<c0382b78>] (_regulator_put+0x24/0xac)
 [<c0382b78>] (_regulator_put) from [<c0382c1c>] (regulator_put+0x1c/0x2c)
 [<c0382c1c>] (regulator_put) from [<c0406434>] (release_nodes+0x16c/0x1dc)
 [<c0406434>] (release_nodes) from [<c04035d4>] (driver_probe_device+0xec/0x2c0)
 [<c04035d4>] (driver_probe_device) from [<c0403854>] (__driver_attach+0xac/0xb0)
 [<c0403854>] (__driver_attach) from [<c0401a74>] (bus_for_each_dev+0x68/0x9c)
 [<c0401a74>] (bus_for_each_dev) from [<c0402cf0>] (bus_add_driver+0x1a0/0x218)
 [<c0402cf0>] (bus_add_driver) from [<c040406c>] (driver_register+0x78/0xf8)
 [<c040406c>] (driver_register) from [<c04f20a0>] (i2c_register_driver+0x34/0x84)
 [<c04f20a0>] (i2c_register_driver) from [<c01017d0>] (do_one_initcall+0x40/0x170)
 [<c01017d0>] (do_one_initcall) from [<c0a00dbc>] (kernel_init_freeable+0x15c/0x1fc)
 [<c0a00dbc>] (kernel_init_freeable) from [<c06e07b0>] (kernel_init+0x8/0x114)
 [<c06e07b0>] (kernel_init) from [<c0107978>] (ret_from_fork+0x14/0x3c)
 Code: e1a04000 f590f000 e3a03001 e34f3fff (e1902f9f)
 ---[ end trace 0919d3d0bc998262 ]---

--------x------------------x----------------

Fix the kernel warnings and crashes by using regulator_bulk_get()
instead of devm_regulator_bulk_get() and explicitly freeing the supplies
in exit paths.

Tested on Exynos 5250, dual core ARM A15 machine.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
1 parent 3cfc43d
History
Tip revision: 1a41741fd60b0a2d1102c3d1ff9d58cb324a8d29 authored by Viresh Kumar on 27 October 2016, 10:20:18 UTC
mfd: wm8994-core: Don't use managed regulator bulk get API
Tip revision: 1a41741
File Mode Size
kasan
Kconfig -rw-r--r-- 24.0 KB
Kconfig.debug -rw-r--r-- 3.6 KB
Makefile -rw-r--r-- 3.4 KB
backing-dev.c -rw-r--r-- 26.3 KB
balloon_compaction.c -rw-r--r-- 4.7 KB
bootmem.c -rw-r--r-- 20.8 KB
cleancache.c -rw-r--r-- 9.9 KB
cma.c -rw-r--r-- 12.2 KB
cma.h -rw-r--r-- 515 bytes
cma_debug.c -rw-r--r-- 4.4 KB
compaction.c -rw-r--r-- 56.7 KB
debug.c -rw-r--r-- 4.2 KB
debug_page_ref.c -rw-r--r-- 1.3 KB
dmapool.c -rw-r--r-- 13.8 KB
early_ioremap.c -rw-r--r-- 6.2 KB
fadvise.c -rw-r--r-- 4.0 KB
failslab.c -rw-r--r-- 1.4 KB
filemap.c -rw-r--r-- 77.5 KB
frame_vector.c -rw-r--r-- 6.1 KB
frontswap.c -rw-r--r-- 14.3 KB
gup.c -rw-r--r-- 42.6 KB
highmem.c -rw-r--r-- 11.7 KB
huge_memory.c -rw-r--r-- 63.2 KB
hugetlb.c -rw-r--r-- 122.5 KB
hugetlb_cgroup.c -rw-r--r-- 10.9 KB
hwpoison-inject.c -rw-r--r-- 3.2 KB
init-mm.c -rw-r--r-- 619 bytes
internal.h -rw-r--r-- 15.3 KB
interval_tree.c -rw-r--r-- 3.1 KB
khugepaged.c -rw-r--r-- 48.0 KB
kmemcheck.c -rw-r--r-- 2.9 KB
kmemleak-test.c -rw-r--r-- 3.2 KB
kmemleak.c -rw-r--r-- 56.1 KB
ksm.c -rw-r--r-- 63.5 KB
list_lru.c -rw-r--r-- 12.6 KB
maccess.c -rw-r--r-- 3.0 KB
madvise.c -rw-r--r-- 19.4 KB
memblock.c -rw-r--r-- 49.5 KB
memcontrol.c -rw-r--r-- 154.2 KB
memory-failure.c -rw-r--r-- 49.0 KB
memory.c -rw-r--r-- 110.4 KB
memory_hotplug.c -rw-r--r-- 55.4 KB
mempolicy.c -rw-r--r-- 71.3 KB
mempool.c -rw-r--r-- 13.9 KB
memtest.c -rw-r--r-- 2.7 KB
migrate.c -rw-r--r-- 52.1 KB
mincore.c -rw-r--r-- 6.7 KB
mlock.c -rw-r--r-- 22.5 KB
mm_init.c -rw-r--r-- 4.8 KB
mmap.c -rw-r--r-- 94.7 KB
mmu_context.c -rw-r--r-- 1.3 KB
mmu_notifier.c -rw-r--r-- 11.7 KB
mmzone.c -rw-r--r-- 2.4 KB
mprotect.c -rw-r--r-- 13.0 KB
mremap.c -rw-r--r-- 15.5 KB
msync.c -rw-r--r-- 2.6 KB
nobootmem.c -rw-r--r-- 11.1 KB
nommu.c -rw-r--r-- 48.4 KB
oom_kill.c -rw-r--r-- 28.6 KB
page-writeback.c -rw-r--r-- 84.3 KB
page_alloc.c -rw-r--r-- 201.7 KB
page_counter.c -rw-r--r-- 4.8 KB
page_ext.c -rw-r--r-- 11.4 KB
page_idle.c -rw-r--r-- 5.4 KB
page_io.c -rw-r--r-- 9.5 KB
page_isolation.c -rw-r--r-- 8.4 KB
page_owner.c -rw-r--r-- 14.7 KB
page_poison.c -rw-r--r-- 3.5 KB
pagewalk.c -rw-r--r-- 7.5 KB
percpu-km.c -rw-r--r-- 2.8 KB
percpu-vm.c -rw-r--r-- 10.0 KB
percpu.c -rw-r--r-- 66.2 KB
pgtable-generic.c -rw-r--r-- 4.8 KB
process_vm_access.c -rw-r--r-- 10.0 KB
quicklist.c -rw-r--r-- 2.4 KB
readahead.c -rw-r--r-- 15.5 KB
rmap.c -rw-r--r-- 51.2 KB
shmem.c -rw-r--r-- 105.8 KB
slab.c -rw-r--r-- 111.4 KB
slab.h -rw-r--r-- 13.3 KB
slab_common.c -rw-r--r-- 31.2 KB
slob.c -rw-r--r-- 16.0 KB
slub.c -rw-r--r-- 138.3 KB
sparse-vmemmap.c -rw-r--r-- 7.8 KB
sparse.c -rw-r--r-- 20.8 KB
swap.c -rw-r--r-- 27.0 KB
swap_cgroup.c -rw-r--r-- 4.6 KB
swap_state.c -rw-r--r-- 13.2 KB
swapfile.c -rw-r--r-- 77.1 KB
truncate.c -rw-r--r-- 24.0 KB
usercopy.c -rw-r--r-- 7.7 KB
userfaultfd.c -rw-r--r-- 7.2 KB
util.c -rw-r--r-- 15.9 KB
vmacache.c -rw-r--r-- 3.1 KB
vmalloc.c -rw-r--r-- 68.6 KB
vmpressure.c -rw-r--r-- 12.5 KB
vmscan.c -rw-r--r-- 110.9 KB
vmstat.c -rw-r--r-- 47.4 KB
workingset.c -rw-r--r-- 16.8 KB
z3fold.c -rw-r--r-- 21.3 KB
zbud.c -rw-r--r-- 18.2 KB
zpool.c -rw-r--r-- 10.0 KB
zsmalloc.c -rw-r--r-- 60.3 KB
zswap.c -rw-r--r-- 32.3 KB

back to top