mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
1a41741fd6
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> |
||
---|---|---|
.. | ||
88pm80x.c | ||
88pm800.c | ||
88pm805.c | ||
88pm860x-core.c | ||
88pm860x-i2c.c | ||
aat2870-core.c | ||
ab3100-core.c | ||
ab3100-otp.c | ||
ab8500-core.c | ||
ab8500-debugfs.c | ||
ab8500-gpadc.c | ||
ab8500-sysctrl.c | ||
abx500-core.c | ||
ac100.c | ||
act8945a.c | ||
adp5520.c | ||
altera-a10sr.c | ||
arizona-core.c | ||
arizona-i2c.c | ||
arizona-irq.c | ||
arizona-spi.c | ||
arizona.h | ||
as3711.c | ||
as3722.c | ||
asic3.c | ||
atmel-flexcom.c | ||
atmel-hlcdc.c | ||
axp20x-i2c.c | ||
axp20x-rsb.c | ||
axp20x.c | ||
bcm590xx.c | ||
cros_ec.c | ||
cros_ec_i2c.c | ||
cros_ec_spi.c | ||
cs47l24-tables.c | ||
cs5535-mfd.c | ||
da903x.c | ||
da9052-core.c | ||
da9052-i2c.c | ||
da9052-irq.c | ||
da9052-spi.c | ||
da9055-core.c | ||
da9055-i2c.c | ||
da9062-core.c | ||
da9063-core.c | ||
da9063-i2c.c | ||
da9063-irq.c | ||
da9150-core.c | ||
davinci_voicecodec.c | ||
db8500-prcmu.c | ||
dbx500-prcmu-regs.h | ||
dln2.c | ||
dm355evm_msp.c | ||
exynos-lpass.c | ||
ezx-pcap.c | ||
fsl-imx25-tsadc.c | ||
hi655x-pmic.c | ||
hi6421-pmic-core.c | ||
htc-i2cpld.c | ||
htc-pasic3.c | ||
intel-lpss-acpi.c | ||
intel-lpss-pci.c | ||
intel-lpss.c | ||
intel-lpss.h | ||
intel_msic.c | ||
intel_quark_i2c_gpio.c | ||
intel_soc_pmic_bxtwc.c | ||
intel_soc_pmic_core.c | ||
intel_soc_pmic_core.h | ||
intel_soc_pmic_crc.c | ||
ipaq-micro.c | ||
janz-cmodio.c | ||
jz4740-adc.c | ||
Kconfig | ||
kempld-core.c | ||
lm3533-core.c | ||
lm3533-ctrlbank.c | ||
lp873x.c | ||
lp3943.c | ||
lp8788-irq.c | ||
lp8788.c | ||
lpc_ich.c | ||
lpc_sch.c | ||
Makefile | ||
max8907.c | ||
max8925-core.c | ||
max8925-i2c.c | ||
max8997-irq.c | ||
max8997.c | ||
max8998-irq.c | ||
max8998.c | ||
max14577.c | ||
max77620.c | ||
max77686.c | ||
max77693.c | ||
max77843.c | ||
mc13xxx-core.c | ||
mc13xxx-i2c.c | ||
mc13xxx-spi.c | ||
mc13xxx.h | ||
mcp-core.c | ||
mcp-sa11x0.c | ||
menelaus.c | ||
menf21bmc.c | ||
mfd-core.c | ||
mt6397-core.c | ||
omap-usb-host.c | ||
omap-usb-tll.c | ||
omap-usb.h | ||
palmas.c | ||
pcf50633-adc.c | ||
pcf50633-core.c | ||
pcf50633-gpio.c | ||
pcf50633-irq.c | ||
pm8921-core.c | ||
qcom-spmi-pmic.c | ||
qcom_rpm.c | ||
rc5t583-irq.c | ||
rc5t583.c | ||
rdc321x-southbridge.c | ||
retu-mfd.c | ||
rk808.c | ||
rn5t618.c | ||
rt5033.c | ||
rtl8411.c | ||
rts5209.c | ||
rts5227.c | ||
rts5229.c | ||
rts5249.c | ||
rtsx_pcr.c | ||
rtsx_pcr.h | ||
rtsx_usb.c | ||
sec-core.c | ||
sec-irq.c | ||
si476x-cmd.c | ||
si476x-i2c.c | ||
si476x-prop.c | ||
sky81452.c | ||
sm501.c | ||
smsc-ece1099.c | ||
ssbi.c | ||
sta2x11-mfd.c | ||
stmpe-i2c.c | ||
stmpe-spi.c | ||
stmpe.c | ||
stmpe.h | ||
stw481x.c | ||
sun6i-prcm.c | ||
syscon.c | ||
t7l66xb.c | ||
tc3589x.c | ||
tc6387xb.c | ||
tc6393xb.c | ||
ti_am335x_tscadc.c | ||
timberdale.c | ||
timberdale.h | ||
tmio_core.c | ||
tps6105x.c | ||
tps6507x.c | ||
tps6586x.c | ||
tps65010.c | ||
tps65086.c | ||
tps65090.c | ||
tps65217.c | ||
tps65218.c | ||
tps65910.c | ||
tps65911-comparator.c | ||
tps65912-core.c | ||
tps65912-i2c.c | ||
tps65912-spi.c | ||
tps80031.c | ||
twl-core.c | ||
twl-core.h | ||
twl4030-audio.c | ||
twl4030-irq.c | ||
twl4030-power.c | ||
twl6030-irq.c | ||
twl6040.c | ||
ucb1x00-assabet.c | ||
ucb1x00-core.c | ||
ucb1x00-ts.c | ||
ucb1400_core.c | ||
vexpress-sysreg.c | ||
viperboard.c | ||
vx855.c | ||
wl1273-core.c | ||
wm831x-auxadc.c | ||
wm831x-core.c | ||
wm831x-i2c.c | ||
wm831x-irq.c | ||
wm831x-otp.c | ||
wm831x-spi.c | ||
wm5102-tables.c | ||
wm5110-tables.c | ||
wm8350-core.c | ||
wm8350-gpio.c | ||
wm8350-i2c.c | ||
wm8350-irq.c | ||
wm8350-regmap.c | ||
wm8400-core.c | ||
wm8994-core.c | ||
wm8994-irq.c | ||
wm8994-regmap.c | ||
wm8994.h | ||
wm8997-tables.c | ||
wm8998-tables.c |