drivers: base: Free devm resources when unregistering a device
[ Upstream commit 699fb50d99039a50e7494de644f96c889279aca3 ] In the current code, devres_release_all() only gets called if the device has a bus and has been probed. This leads to issues when using bus-less or driver-less devices where the device might never get freed if a managed resource holds a reference to the device. This is happening in the DRM framework for example. We should thus call devres_release_all() in the device_del() function to make sure that the device-managed actions are properly executed when the device is unregistered, even if it has neither a bus nor a driver. This is effectively the same change than commit2f8d16a996("devres: release resources on device_del()") that got reverted by commita525a3ddea("driver core: free devres in device_release") over memory leaks concerns. This patch effectively combines the two commits mentioned above to release the resources both on device_del() and device_release() and get the best of both worlds. Fixes:a525a3ddea("driver core: free devres in device_release") Signed-off-by: David Gow <davidgow@google.com> Signed-off-by: Maxime Ripard <mripard@kernel.org> Link: https://lore.kernel.org/r/20230720-kunit-devm-inconsistencies-test-v3-3-6aa7e074f373@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
66eb45e7d5
commit
297992e5c6
1 changed files with 11 additions and 0 deletions
|
|
@ -3855,6 +3855,17 @@ void device_del(struct device *dev)
|
|||
device_platform_notify_remove(dev);
|
||||
device_links_purge(dev);
|
||||
|
||||
/*
|
||||
* If a device does not have a driver attached, we need to clean
|
||||
* up any managed resources. We do this in device_release(), but
|
||||
* it's never called (and we leak the device) if a managed
|
||||
* resource holds a reference to the device. So release all
|
||||
* managed resources here, like we do in driver_detach(). We
|
||||
* still need to do so again in device_release() in case someone
|
||||
* adds a new resource after this point, though.
|
||||
*/
|
||||
devres_release_all(dev);
|
||||
|
||||
if (dev->bus)
|
||||
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
|
||||
BUS_NOTIFY_REMOVED_DEVICE, dev);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue