mirror of
https://github.com/torvalds/linux.git
synced 2026-07-02 19:17:03 +02:00
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_i2c.c | ||
| cros_ec_spi.c | ||
| cros_ec.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_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 | ||
| intel-lpss-acpi.c | ||
| intel-lpss-pci.c | ||
| intel-lpss.c | ||
| intel-lpss.h | ||
| 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_rpm.c | ||
| qcom-spmi-pmic.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 | ||