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 | |
| 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')
| -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) |
