diff options
author | Pantelis Antoniou <pantelis.antoniou@konsulko.com> | 2015-01-24 02:16:29 -0500 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2015-07-09 16:25:54 -0400 |
commit | 4f001fd30145a6a8f72f9544c982cfd3dcb7c6df (patch) | |
tree | 5d21ee5c7ded9bc74c2f1448bd045f71c53d312f /drivers/i2c/i2c-core.c | |
parent | eb8173e3d7b94664ecd3acf34942c9c9d6f6cb73 (diff) |
i2c: Mark instantiated device nodes with OF_POPULATE
Mark (and unmark) device nodes with the POPULATE flag as appropriate.
This is required to avoid multi probing when using I2C and device
overlays containing a mux.
This patch is also more careful with the release of the adapter device
which caused a deadlock with muxes, and does not break the build
on !OF since the node flag accessors are not defined then.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 069a41f116dd..e6d4935161e4 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -1012,6 +1012,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device); | |||
1012 | */ | 1012 | */ |
1013 | void i2c_unregister_device(struct i2c_client *client) | 1013 | void i2c_unregister_device(struct i2c_client *client) |
1014 | { | 1014 | { |
1015 | if (client->dev.of_node) | ||
1016 | of_node_clear_flag(client->dev.of_node, OF_POPULATED); | ||
1015 | device_unregister(&client->dev); | 1017 | device_unregister(&client->dev); |
1016 | } | 1018 | } |
1017 | EXPORT_SYMBOL_GPL(i2c_unregister_device); | 1019 | EXPORT_SYMBOL_GPL(i2c_unregister_device); |
@@ -1320,8 +1322,11 @@ static void of_i2c_register_devices(struct i2c_adapter *adap) | |||
1320 | 1322 | ||
1321 | dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); | 1323 | dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); |
1322 | 1324 | ||
1323 | for_each_available_child_of_node(adap->dev.of_node, node) | 1325 | for_each_available_child_of_node(adap->dev.of_node, node) { |
1326 | if (of_node_test_and_set_flag(node, OF_POPULATED)) | ||
1327 | continue; | ||
1324 | of_i2c_register_device(adap, node); | 1328 | of_i2c_register_device(adap, node); |
1329 | } | ||
1325 | } | 1330 | } |
1326 | 1331 | ||
1327 | static int of_dev_node_match(struct device *dev, void *data) | 1332 | static int of_dev_node_match(struct device *dev, void *data) |
@@ -1853,6 +1858,11 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, | |||
1853 | if (adap == NULL) | 1858 | if (adap == NULL) |
1854 | return NOTIFY_OK; /* not for us */ | 1859 | return NOTIFY_OK; /* not for us */ |
1855 | 1860 | ||
1861 | if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) { | ||
1862 | put_device(&adap->dev); | ||
1863 | return NOTIFY_OK; | ||
1864 | } | ||
1865 | |||
1856 | client = of_i2c_register_device(adap, rd->dn); | 1866 | client = of_i2c_register_device(adap, rd->dn); |
1857 | put_device(&adap->dev); | 1867 | put_device(&adap->dev); |
1858 | 1868 | ||
@@ -1863,6 +1873,10 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, | |||
1863 | } | 1873 | } |
1864 | break; | 1874 | break; |
1865 | case OF_RECONFIG_CHANGE_REMOVE: | 1875 | case OF_RECONFIG_CHANGE_REMOVE: |
1876 | /* already depopulated? */ | ||
1877 | if (!of_node_check_flag(rd->dn, OF_POPULATED)) | ||
1878 | return NOTIFY_OK; | ||
1879 | |||
1866 | /* find our device by node */ | 1880 | /* find our device by node */ |
1867 | client = of_find_i2c_device_by_node(rd->dn); | 1881 | client = of_find_i2c_device_by_node(rd->dn); |
1868 | if (client == NULL) | 1882 | if (client == NULL) |