diff options
author | Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com> | 2015-07-27 17:30:48 +0300 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2015-08-01 12:11:58 +0200 |
commit | e3311469734093724b10c2a81c1193197db03b78 (patch) | |
tree | 435b300b8fb5257f2d3cbd7003860241bd8a5f80 /drivers/i2c | |
parent | e952849a02524a247967bf7105f36fbb13cd00c2 (diff) | |
download | lwn-e3311469734093724b10c2a81c1193197db03b78.tar.gz lwn-e3311469734093724b10c2a81c1193197db03b78.zip |
i2c: fix leaked device refcount on of_find_i2c_* error path
If of_find_i2c_device_by_node() or of_find_i2c_adapter_by_node() find
a device by node, but its type does not match, a reference to that
device is still held. This change fixes the problem.
Signed-off-by: Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 8b64cf38beac..c83e4d13cfc5 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1340,13 +1340,17 @@ static int of_dev_node_match(struct device *dev, void *data) struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) { struct device *dev; + struct i2c_client *client; - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); + dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match); if (!dev) return NULL; - return i2c_verify_client(dev); + client = i2c_verify_client(dev); + if (!client) + put_device(dev); + + return client; } EXPORT_SYMBOL(of_find_i2c_device_by_node); @@ -1354,13 +1358,17 @@ EXPORT_SYMBOL(of_find_i2c_device_by_node); struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) { struct device *dev; + struct i2c_adapter *adapter; - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); + dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match); if (!dev) return NULL; - return i2c_verify_adapter(dev); + adapter = i2c_verify_adapter(dev); + if (!adapter) + put_device(dev); + + return adapter; } EXPORT_SYMBOL(of_find_i2c_adapter_by_node); #else |