diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2021-03-22 04:38:32 +0300 |
---|---|---|
committer | Wolfram Sang <wsa@kernel.org> | 2021-04-10 22:59:21 +0300 |
commit | 5b5475826c5265cead7ce4ca6d34ec0c566c70aa (patch) | |
tree | cc4e7b918d2eacf131398d59037c74649c873fd0 /drivers/i2c/i2c-core-base.c | |
parent | 71aee62783e9dc16472acf7657ce16318613ad2f (diff) | |
download | linux-5b5475826c5265cead7ce4ca6d34ec0c566c70aa.tar.xz |
i2c: ensure timely release of driver-allocated resources
More and more drivers rely on devres to manage their resources, however
if bus' probe() and release() methods are not trivial and control some
of resources as well (for example enable or disable clocks, or attach
device to a power domain), we need to make sure that driver-allocated
resources are released immediately after driver's remove() method
returns, and not postponed until driver core gets around to releasing
resources. To fix that we open a new devres group before calling
driver's probe() and explicitly release it when we return from driver's
remove().
Tested-by: Jeff LaBundy <jeff@labundy.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
Diffstat (limited to 'drivers/i2c/i2c-core-base.c')
-rw-r--r-- | drivers/i2c/i2c-core-base.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 5c16083694bf..4351bf529d0f 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -539,6 +539,13 @@ static int i2c_device_probe(struct device *dev) if (status) goto err_clear_wakeup_irq; + client->devres_group_id = devres_open_group(&client->dev, NULL, + GFP_KERNEL); + if (!client->devres_group_id) { + status = -ENOMEM; + goto err_detach_pm_domain; + } + /* * When there are no more users of probe(), * rename probe_new to probe. @@ -551,11 +558,21 @@ static int i2c_device_probe(struct device *dev) else status = -EINVAL; + /* + * Note that we are not closing the devres group opened above so + * even resources that were attached to the device after probe is + * run are released when i2c_device_remove() is executed. This is + * needed as some drivers would allocate additional resources, + * for example when updating firmware. + */ + if (status) - goto err_detach_pm_domain; + goto err_release_driver_resources; return 0; +err_release_driver_resources: + devres_release_group(&client->dev, client->devres_group_id); err_detach_pm_domain: dev_pm_domain_detach(&client->dev, true); err_clear_wakeup_irq: @@ -584,6 +601,8 @@ static int i2c_device_remove(struct device *dev) dev_warn(dev, "remove failed (%pe), will be ignored\n", ERR_PTR(status)); } + devres_release_group(&client->dev, client->devres_group_id); + dev_pm_domain_detach(&client->dev, true); dev_pm_clear_wake_irq(&client->dev); |