pinctrl: starfive: Serialize adding groups and functions
authorJianlong Huang <jianlong.huang@starfivetech.com>
Mon, 27 Jun 2022 08:53:33 +0000 (10:53 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 11 Jul 2022 08:22:57 +0000 (10:22 +0200)
The pinctrl dt_node_to_map method may be called in parallel which leads
us to call pinconf_generic_add_group and pinconf_generic_add_function
in parallel. This is not supported though and leads to errors, so add a
mutex to serialize these calls.

Signed-off-by: Jianlong Huang <jianlong.huang@starfivetech.com>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Link: https://lore.kernel.org/r/20220627085333.1774396-1-emil.renner.berthing@canonical.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/pinctrl-starfive.c

index 2a86c10..3eb40e2 100644 (file)
@@ -207,6 +207,7 @@ struct starfive_pinctrl {
        void __iomem *base;
        void __iomem *padctl;
        struct pinctrl_dev *pctl;
+       struct mutex mutex; /* serialize adding groups and functions */
 };
 
 static inline unsigned int starfive_pin_to_gpio(const struct starfive_pinctrl *sfp,
@@ -522,6 +523,7 @@ static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
 
        nmaps = 0;
        ngroups = 0;
+       mutex_lock(&sfp->mutex);
        for_each_child_of_node(np, child) {
                int npins;
                int i;
@@ -615,12 +617,14 @@ static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
 
        *maps = map;
        *num_maps = nmaps;
+       mutex_unlock(&sfp->mutex);
        return 0;
 
 put_child:
        of_node_put(child);
 free_map:
        pinctrl_utils_free_map(pctldev, map, nmaps);
+       mutex_unlock(&sfp->mutex);
        return ret;
 }
 
@@ -1267,6 +1271,7 @@ static int starfive_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, sfp);
        sfp->gc.parent = dev;
        raw_spin_lock_init(&sfp->lock);
+       mutex_init(&sfp->mutex);
 
        ret = devm_pinctrl_register_and_init(dev, &starfive_desc, sfp, &sfp->pctl);
        if (ret)