summaryrefslogtreecommitdiff
path: root/drivers/mfd/mfd-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/mfd-core.c')
-rw-r--r--drivers/mfd/mfd-core.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 7d14a1e7631e..6be58eb5a746 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -22,6 +22,7 @@
#include <linux/regulator/consumer.h>
static LIST_HEAD(mfd_of_node_list);
+static DEFINE_MUTEX(mfd_of_node_mutex);
struct mfd_of_node_entry {
struct list_head list;
@@ -100,14 +101,15 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev,
struct device_node *np,
const struct mfd_cell *cell)
{
-#if IS_ENABLED(CONFIG_OF)
struct mfd_of_node_entry *of_entry;
u64 of_node_addr;
/* Skip if OF node has previously been allocated to a device */
- list_for_each_entry(of_entry, &mfd_of_node_list, list)
- if (of_entry->np == np)
- return -EAGAIN;
+ scoped_guard(mutex, &mfd_of_node_mutex) {
+ list_for_each_entry(of_entry, &mfd_of_node_list, list)
+ if (of_entry->np == np)
+ return -EAGAIN;
+ }
if (!cell->use_of_reg)
/* No of_reg defined - allocate first free compatible match */
@@ -128,12 +130,11 @@ allocate_of_node:
return -ENOMEM;
of_entry->dev = &pdev->dev;
- of_entry->np = np;
- list_add_tail(&of_entry->list, &mfd_of_node_list);
+ of_entry->np = of_node_get(np);
+ scoped_guard(mutex, &mfd_of_node_mutex)
+ list_add_tail(&of_entry->list, &mfd_of_node_list);
- of_node_get(np);
device_set_node(&pdev->dev, of_fwnode_handle(np));
-#endif
return 0;
}
@@ -144,7 +145,6 @@ static int mfd_add_device(struct device *parent, int id,
{
struct resource *res;
struct platform_device *pdev;
- struct device_node *np = NULL;
struct mfd_of_node_entry *of_entry, *tmp;
bool disabled = false;
int ret = -ENOMEM;
@@ -182,7 +182,7 @@ static int mfd_add_device(struct device *parent, int id,
goto fail_res;
if (IS_ENABLED(CONFIG_OF) && parent->of_node && cell->of_compatible) {
- for_each_child_of_node(parent->of_node, np) {
+ for_each_child_of_node_scoped(parent->of_node, np) {
if (of_device_is_compatible(np, cell->of_compatible)) {
/* Skip 'disabled' devices */
if (!of_device_is_available(np)) {
@@ -193,7 +193,6 @@ static int mfd_add_device(struct device *parent, int id,
ret = mfd_match_of_node_to_dev(pdev, np, cell);
if (ret == -EAGAIN)
continue;
- of_node_put(np);
if (ret)
goto fail_alias;
@@ -286,11 +285,13 @@ fail_res_conflict:
if (cell->swnode)
device_remove_software_node(&pdev->dev);
fail_of_entry:
- 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);
- }
+ scoped_guard(mutex, &mfd_of_node_mutex) {
+ 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);
+ }
+ }
fail_alias:
regulator_bulk_unregister_supply_alias(&pdev->dev,
cell->parent_supplies,
@@ -360,11 +361,13 @@ 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);
- }
+ scoped_guard(mutex, &mfd_of_node_mutex) {
+ 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);