Commit 4f001fd3 authored by Pantelis Antoniou's avatar Pantelis Antoniou Committed by Wolfram Sang

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: default avatarPantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent eb8173e3
...@@ -1012,6 +1012,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device); ...@@ -1012,6 +1012,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
*/ */
void i2c_unregister_device(struct i2c_client *client) void i2c_unregister_device(struct i2c_client *client)
{ {
if (client->dev.of_node)
of_node_clear_flag(client->dev.of_node, OF_POPULATED);
device_unregister(&client->dev); device_unregister(&client->dev);
} }
EXPORT_SYMBOL_GPL(i2c_unregister_device); EXPORT_SYMBOL_GPL(i2c_unregister_device);
...@@ -1320,8 +1322,11 @@ static void of_i2c_register_devices(struct i2c_adapter *adap) ...@@ -1320,8 +1322,11 @@ static void of_i2c_register_devices(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
for_each_available_child_of_node(adap->dev.of_node, node) for_each_available_child_of_node(adap->dev.of_node, node) {
if (of_node_test_and_set_flag(node, OF_POPULATED))
continue;
of_i2c_register_device(adap, node); of_i2c_register_device(adap, node);
}
} }
static int of_dev_node_match(struct device *dev, void *data) 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,6 +1858,11 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
if (adap == NULL) if (adap == NULL)
return NOTIFY_OK; /* not for us */ return NOTIFY_OK; /* not for us */
if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) {
put_device(&adap->dev);
return NOTIFY_OK;
}
client = of_i2c_register_device(adap, rd->dn); client = of_i2c_register_device(adap, rd->dn);
put_device(&adap->dev); put_device(&adap->dev);
...@@ -1863,6 +1873,10 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, ...@@ -1863,6 +1873,10 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
} }
break; break;
case OF_RECONFIG_CHANGE_REMOVE: case OF_RECONFIG_CHANGE_REMOVE:
/* already depopulated? */
if (!of_node_check_flag(rd->dn, OF_POPULATED))
return NOTIFY_OK;
/* find our device by node */ /* find our device by node */
client = of_find_i2c_device_by_node(rd->dn); client = of_find_i2c_device_by_node(rd->dn);
if (client == NULL) if (client == NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment