mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
UPSTREAM: regulator: core: fix crash in error path of regulator_register
This problem was introduced by: commitdaad134d66("regulator: core: Request GPIO before creating sysfs entries") The error path was not updated correctly after moving GPIO registration code and in case regulator_ena_gpio_free failed, device_unregister() was called even though device_register() was not yet called. This problem breaks the boot at least on all Tegra 32-bit devices. It will also crash each device that specifices GPIO that is unavaiable at regulator_register call. Here's error log I've got when forced GPIO to be invalid: [ 1.116612] usb-otg-vbus-reg: Failed to request enable GPIO10: -22 [ 1.122794] Unable to handle kernel NULL pointer dereference at virtual address 00000044 [ 1.130894] pgd = c0004000 [ 1.133598] [00000044] *pgd=00000000 [ 1.137205] Internal error: Oops: 5 [#1] SMP ARM and here's backtrace from KDB: Exception stack(0xef11fbd0 to 0xef11fc18) fbc0: 00000000 c0738a14 00000000 00000000 fbe0: c0b2a0b0 00000000 00000000 c0738a14 c0b5fdf8 00000001 ef7f6074 ef11fc4c fc00: ef11fc50 ef11fc20 c02a8344 c02a7f1c 60000013 ffffffff [<c010cee0>] (__dabt_svc) from [<c02a7f1c>] (kernfs_find_ns+0x18/0xf8) [<c02a7f1c>] (kernfs_find_ns) from [<c02a8344>] (kernfs_find_and_get_ns+0x40/0x58) [<c02a8344>] (kernfs_find_and_get_ns) from [<c02ac4a4>] (sysfs_unmerge_group+0x28/0x68) [<c02ac4a4>] (sysfs_unmerge_group) from [<c044389c>] (dpm_sysfs_remove+0x30/0x5c) [<c044389c>] (dpm_sysfs_remove) from [<c0436ba8>] (device_del+0x48/0x1f4) [<c0436ba8>] (device_del) from [<c0436d84>] (device_unregister+0x30/0x6c) [<c0436d84>] (device_unregister) from [<c0403910>] (regulator_register+0x6d0/0xdac) [<c0403910>] (regulator_register) from [<c04052d4>] (devm_regulator_register+0x50/0x84) [<c04052d4>] (devm_regulator_register) from [<c0406298>] (reg_fixed_voltage_probe+0x25c/0x3c0) [<c0406298>] (reg_fixed_voltage_probe) from [<c043d21c>] (platform_drv_probe+0x60/0xb0) [<c043d21c>] (platform_drv_probe) from [<c043b078>] (driver_probe_device+0x24c/0x440) [<c043b078>] (driver_probe_device) from [<c043b5e8>] (__device_attach_driver+0xc0/0x120) [<c043b5e8>] (__device_attach_driver) from [<c043901c>] (bus_for_each_drv+0x6c/0x98) [<c043901c>] (bus_for_each_drv) from [<c043ad20>] (__device_attach+0xac/0x138) [<c043ad20>] (__device_attach) from [<c043b664>] (device_initial_probe+0x1c/0x20) [<c043b664>] (device_initial_probe) from [<c043a074>] (bus_probe_device+0x94/0x9c) [<c043a074>] (bus_probe_device) from [<c043a610>] (deferred_probe_work_func+0x80/0xcc) [<c043a610>] (deferred_probe_work_func) from [<c01381d0>] (process_one_work+0x158/0x454) [<c01381d0>] (process_one_work) from [<c013854c>] (worker_thread+0x38/0x510) [<c013854c>] (worker_thread) from [<c013e154>] (kthread+0xe8/0x104) [<c013e154>] (kthread) from [<c0108638>] (ret_from_fork+0x14/0x3c) Signed-off-by: Krzysztof Adamski <krzysztof.adamski@tieto.com> Reported-by: Jon Hunter <jonathanh@nvidia.com> Acked-by: Jon Hunter <jonathanh@nvidia.com> Tested-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Mark Brown <broonie@kernel.org> (cherry picked from commit32165230eb) Change-Id: I08cf9670f329d917478f86f38ac343d6c55f3827 Signed-off-by: David Wu <david.wu@rock-chips.com>
This commit is contained in:
committed by
Huang, Tao
parent
bd0d179b27
commit
edcefe0034
@@ -3917,7 +3917,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
|
||||
if (ret != 0) {
|
||||
rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
|
||||
config->ena_gpio, ret);
|
||||
goto wash;
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3929,7 +3929,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
|
||||
ret = device_register(&rdev->dev);
|
||||
if (ret != 0) {
|
||||
put_device(&rdev->dev);
|
||||
goto clean;
|
||||
goto wash;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&rdev->dev, rdev);
|
||||
@@ -3972,13 +3972,13 @@ unset_supplies:
|
||||
|
||||
scrub:
|
||||
regulator_ena_gpio_free(rdev);
|
||||
|
||||
wash:
|
||||
device_unregister(&rdev->dev);
|
||||
/* device core frees rdev */
|
||||
rdev = ERR_PTR(ret);
|
||||
goto out;
|
||||
|
||||
wash:
|
||||
regulator_ena_gpio_free(rdev);
|
||||
clean:
|
||||
kfree(rdev);
|
||||
rdev = ERR_PTR(ret);
|
||||
|
||||
Reference in New Issue
Block a user