| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Saravana Kannan <saravanak@google.com> |
| Date: Wed, 4 Sep 2019 14:11:25 -0700 |
| Subject: FROMGIT: of: property: Create device links for all child-supplier |
| depencencies |
| |
| A parent device can have child devices that it adds when it probes. But |
| this probing of the parent device can happen way after kernel init is done |
| -- for example, when the parent device's driver is loaded as a module. |
| |
| In such cases, if the child devices depend on a supplier in the system, we |
| need to make sure the supplier gets the sync_state() callback only after |
| these child devices are added and probed. |
| |
| To achieve this, when creating device links for a device by looking at its |
| DT node, don't just look at DT references at the top node level. Look at DT |
| references in all the descendant nodes too and create device links from the |
| ancestor device to all these supplier devices. |
| |
| This way, when the parent device probes and adds child devices, the child |
| devices can then create their own device links to the suppliers and further |
| delay the supplier's sync_state() callback to after the child devices are |
| probed. |
| |
| Example: |
| In this illustration, -> denotes DT references and indentation |
| represents child status. |
| |
| Device node A |
| Device node B -> D |
| Device node C -> B, D |
| |
| Device node D |
| |
| Assume all these devices have their drivers loaded as modules. |
| |
| Without this patch, this is the sequence of events: |
| 1. D is added. |
| 2. A is added. |
| 3. Device D probes. |
| 4. Device D gets its sync_state() callback. |
| 5. Device B and C might malfunction because their resources got |
| altered/turned off before they can make active requests for them. |
| |
| With this patch, this is the sequence of events: |
| 1. D is added. |
| 2. A is added and creates device links to D. |
| 3. Device link from A to B is not added because A is a parent of B. |
| 4. Device D probes. |
| 5. Device D does not get it's sync_state() callback because consumer A |
| hasn't probed yet. |
| 5. Device A probes. |
| 5. a. Devices B and C are added. |
| 5. b. Device links from B and C to D are added. |
| 5. c. Device A's probe completes. |
| 6. Device D does not get it's sync_state() callback because consumer A |
| has probed but consumers B and C haven't probed yet. |
| 7. Device B and C probe. |
| 8. Device D gets it's sync_state() callback because all its consumers |
| have probed. |
| 9. None of the devices malfunction. |
| |
| Signed-off-by: Saravana Kannan <saravanak@google.com> |
| Link: https://lore.kernel.org/r/20190904211126.47518-7-saravanak@google.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| (cherry-picked from commit d4387cd117414ba80230f27a514be5ca4a09cfcc |
| https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-next) |
| |
| Fixes: 141703324 |
| Change-Id: I38186d6cc4671bd8747dae8c440b09717a487088 |
| --- |
| drivers/of/property.c | 4 ++++ |
| 1 file changed, 4 insertions(+) |
| |
| diff --git a/drivers/of/property.c b/drivers/of/property.c |
| index 23b5ee5b0570..923d6f88a99c 100644 |
| --- a/drivers/of/property.c |
| +++ b/drivers/of/property.c |
| @@ -1207,6 +1207,10 @@ static int __of_link_to_suppliers(struct device *dev, |
| if (of_link_property(dev, con_np, p->name)) |
| ret = -EAGAIN; |
| |
| + for_each_child_of_node(con_np, child) |
| + if (__of_link_to_suppliers(dev, child)) |
| + ret = -EAGAIN; |
| + |
| return ret; |
| } |
| |