Call to mfd_add_devices() after mfd_remove_devices() will always
fail in device tree use-case, because new device will find a matching node
in the global mfd_of_node_list resulting in mfd_match_of_node_to_dev()
to return -EAGAIN.

This is one of the use-case with WCD934x where mfd devices can disappear and
reappear when ADSP either restarts or its services restarts.

Fix this issue by removing the state entry in global mfd_of_node_list
during mfd_remove_devices.

Fixes: 466a62d7642f ("mfd: core: Make a best effort attempt to match devices 
with the correct of_nodes")
Signed-off-by: Srinivas Kandagatla <srinivas.kandaga...@linaro.org>
---
 drivers/mfd/mfd-core.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index fc00aaccb5f7..3e845be895ac 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -359,6 +359,7 @@ static int mfd_remove_devices_fn(struct device *dev, void 
*data)
        struct platform_device *pdev;
        const struct mfd_cell *cell;
        int *level = data;
+       struct mfd_of_node_entry *of_entry, *tmp;
 
        if (dev->type != &mfd_dev_type)
                return 0;
@@ -372,6 +373,12 @@ static int mfd_remove_devices_fn(struct device *dev, void 
*data)
        regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
                                               cell->num_parent_supplies);
 
+       list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
+               if (of_entry->dev == &pdev->dev) {
+                       list_del(&of_entry->list);
+                       kfree(of_entry);
+               }
+
        platform_device_unregister(pdev);
        return 0;
 }
-- 
2.21.0

Reply via email to