From 8e88c61d6f3432f27a2c6b8bc58ae4fe974f4b6d Mon Sep 17 00:00:00 2001 From: Michal Oleszczyk Date: Tue, 9 Aug 2022 08:03:36 +0200 Subject: [PATCH] mfd: core: Delete corresponding OF node entries from list on MFD removal When we consider MFD which implements hotplug (e.g. USB hotplug driver based on product and vendor IDs) functionality it turns out that its sub-devices are correctly matched with corresponding device tree nodes only at the first time. When physical device reboots or is replugged (and MFD driver is disconnected and probed back again) all sub-devices fails in mfd_add_device() with error 'Failed to locate of_node'. The reason of that behavior is that when any MFD sub-device is created for the first time (and matched with device tree node) it is added to the mfd_of_node_list. It looks like this list is never cleaned even if devices added there are intentionally removed from the system. So when MFD device is replugged and all sub-devices are matched with their device tree nodes again they fail as matched nodes already exist in mfd_of_node_list. In other words current implementation does not support MFD with hotplug feature. This commit extends MFD core for hotplugging support by removing appropriate OF node entry from mfd_of_node_list when corresponding device is removed from the system. Thanks to that when device is added once again it can be matched with its device tree node successfully. Signed-off-by: Michal Oleszczyk Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20220809060336.31892-1-m.oleszczyk@grinn-global.com --- 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 8b058200d5ad..5ec5d76a667d 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -368,6 +368,7 @@ static int mfd_remove_devices_fn(struct device *dev, void *data) { struct platform_device *pdev; const struct mfd_cell *cell; + struct mfd_of_node_entry *of_entry, *tmp; int *level = data; if (dev->type != &mfd_dev_type) @@ -382,6 +383,12 @@ static int mfd_remove_devices_fn(struct device *dev, void *data) if (cell->swnode) device_remove_software_node(&pdev->dev); + 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); + } + regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, cell->num_parent_supplies);