summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/i2c-core-base.c21
-rw-r--r--include/linux/i2c.h3
2 files changed, 23 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);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index e5d8b9dad6bf..e8f2ac8c9c3d 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -309,6 +309,8 @@ struct i2c_driver {
* userspace_devices list
* @slave_cb: Callback when I2C slave mode of an adapter is used. The adapter
* calls it to pass on slave events to the slave driver.
+ * @devres_group_id: id of the devres group that will be created for resources
+ * acquired when probing this device.
*
* An i2c_client identifies a single device (i.e. chip) connected to an
* i2c bus. The behaviour exposed to Linux is defined by the driver
@@ -337,6 +339,7 @@ struct i2c_client {
#if IS_ENABLED(CONFIG_I2C_SLAVE)
i2c_slave_cb_t slave_cb; /* callback for slave mode */
#endif
+ void *devres_group_id; /* ID of probe devres group */
};
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)