| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Saravana Kannan <saravanak@google.com> |
| Date: Wed, 4 Sep 2019 14:11:24 -0700 |
| Subject: FROMGIT: of/platform: Pause/resume sync state during init and |
| of_platform_populate() |
| |
| When all the top level devices are populated from DT during kernel |
| init, the supplier devices could be added and probed before the |
| consumer devices are added and linked to the suppliers. To avoid the |
| sync_state() callback from being called prematurely, pause the |
| sync_state() callbacks before populating the devices and resume them |
| at late_initcall_sync(). |
| |
| Similarly, when children devices are populated from a module using |
| of_platform_populate(), there could be supplier-consumer dependencies |
| between the children devices that are populated. To avoid the same |
| problem with sync_state() being called prematurely, pause and resume |
| sync_state() callbacks across of_platform_populate(). |
| |
| Signed-off-by: Saravana Kannan <saravanak@google.com> |
| Link: https://lore.kernel.org/r/20190904211126.47518-6-saravanak@google.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| (cherry-picked from commit 5e6669387e2287f25f09fd0abd279dae104cfa7e |
| https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-next) |
| |
| Bug: 141703324 |
| Change-Id: Ia43ebbc9071d4d6a59b347ccae99fcf0ab192269 |
| --- |
| drivers/of/platform.c | 12 ++++++++++++ |
| 1 file changed, 12 insertions(+) |
| |
| diff --git a/drivers/of/platform.c b/drivers/of/platform.c |
| index b47a2292fe8e..d93891a05f60 100644 |
| --- a/drivers/of/platform.c |
| +++ b/drivers/of/platform.c |
| @@ -480,6 +480,7 @@ int of_platform_populate(struct device_node *root, |
| pr_debug("%s()\n", __func__); |
| pr_debug(" starting at: %pOF\n", root); |
| |
| + device_links_supplier_sync_state_pause(); |
| for_each_child_of_node(root, child) { |
| rc = of_platform_bus_create(child, matches, lookup, parent, true); |
| if (rc) { |
| @@ -487,6 +488,8 @@ int of_platform_populate(struct device_node *root, |
| break; |
| } |
| } |
| + device_links_supplier_sync_state_resume(); |
| + |
| of_node_set_flag(root, OF_POPULATED_BUS); |
| |
| of_node_put(root); |
| @@ -518,6 +521,7 @@ static int __init of_platform_default_populate_init(void) |
| if (!of_have_populated_dt()) |
| return -ENODEV; |
| |
| + device_links_supplier_sync_state_pause(); |
| /* |
| * Handle certain compatibles explicitly, since we don't want to create |
| * platform_devices for every node in /reserved-memory with a |
| @@ -538,6 +542,14 @@ static int __init of_platform_default_populate_init(void) |
| return 0; |
| } |
| arch_initcall_sync(of_platform_default_populate_init); |
| + |
| +static int __init of_platform_sync_state_init(void) |
| +{ |
| + if (of_have_populated_dt()) |
| + device_links_supplier_sync_state_resume(); |
| + return 0; |
| +} |
| +late_initcall_sync(of_platform_sync_state_init); |
| #endif |
| |
| int of_platform_device_destroy(struct device *dev, void *data) |