diff options
Diffstat (limited to 'drivers/mfd/mfd-core.c')
-rw-r--r-- | drivers/mfd/mfd-core.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 684a011a6396..16d1861e9682 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -60,12 +60,29 @@ int mfd_cell_disable(struct platform_device *pdev) EXPORT_SYMBOL(mfd_cell_disable); #if IS_ENABLED(CONFIG_ACPI) +struct match_ids_walk_data { + struct acpi_device_id *ids; + struct acpi_device *adev; +}; + +static int match_device_ids(struct acpi_device *adev, void *data) +{ + struct match_ids_walk_data *wd = data; + + if (!acpi_match_device_ids(adev, wd->ids)) { + wd->adev = adev; + return 1; + } + + return 0; +} + static void mfd_acpi_add_device(const struct mfd_cell *cell, struct platform_device *pdev) { const struct mfd_cell_acpi_match *match = cell->acpi_match; - struct acpi_device *parent, *child; struct acpi_device *adev = NULL; + struct acpi_device *parent; parent = ACPI_COMPANION(pdev->dev.parent); if (!parent) @@ -83,14 +100,14 @@ static void mfd_acpi_add_device(const struct mfd_cell *cell, if (match) { if (match->pnpid) { struct acpi_device_id ids[2] = {}; - - strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id)); - list_for_each_entry(child, &parent->children, node) { - if (!acpi_match_device_ids(child, ids)) { - adev = child; - break; - } - } + struct match_ids_walk_data wd = { + .adev = NULL, + .ids = ids, + }; + + strscpy(ids[0].id, match->pnpid, sizeof(ids[0].id)); + acpi_dev_for_each_child(parent, match_device_ids, &wd); + adev = wd.adev; } else { adev = acpi_find_child_device(parent, match->adr, false); } @@ -351,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) @@ -365,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); |