/**
  * pcs_add_function() - adds a new function to the function list
  * @pcs: pcs driver instance
- * @np: device node of the mux entry
+ * @fcn: new function allocated
  * @name: name of the function
  * @vals: array of mux register value pairs used by the function
  * @nvals: number of mux register value pairs
  * @pgnames: array of pingroup names for the function
  * @npgnames: number of pingroup names
+ *
+ * Caller must take care of locking.
  */
-static struct pcs_function *pcs_add_function(struct pcs_device *pcs,
-                                       struct device_node *np,
-                                       const char *name,
-                                       struct pcs_func_vals *vals,
-                                       unsigned nvals,
-                                       const char **pgnames,
-                                       unsigned npgnames)
+static int pcs_add_function(struct pcs_device *pcs,
+                           struct pcs_function **fcn,
+                           const char *name,
+                           struct pcs_func_vals *vals,
+                           unsigned int nvals,
+                           const char **pgnames,
+                           unsigned int npgnames)
 {
        struct pcs_function *function;
-       int res;
+       int selector;
 
        function = devm_kzalloc(pcs->dev, sizeof(*function), GFP_KERNEL);
        if (!function)
-               return NULL;
+               return -ENOMEM;
 
        function->vals = vals;
        function->nvals = nvals;
 
-       res = pinmux_generic_add_function(pcs->pctl, name,
-                                         pgnames, npgnames,
-                                         function);
-       if (res)
-               return NULL;
+       selector = pinmux_generic_add_function(pcs->pctl, name,
+                                              pgnames, npgnames,
+                                              function);
+       if (selector < 0) {
+               devm_kfree(pcs->dev, function);
+               *fcn = NULL;
+       } else {
+               *fcn = function;
+       }
 
-       return function;
+       return selector;
 }
 
 /**
 {
        const char *name = "pinctrl-single,pins";
        struct pcs_func_vals *vals;
-       int rows, *pins, found = 0, res = -ENOMEM, i;
-       struct pcs_function *function;
+       int rows, *pins, found = 0, res = -ENOMEM, i, fsel, gsel;
+       struct pcs_function *function = NULL;
 
        rows = pinctrl_count_index_with_args(np, name);
        if (rows <= 0) {
        }
 
        pgnames[0] = np->name;
-       function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1);
-       if (!function) {
-               res = -ENOMEM;
+       mutex_lock(&pcs->mutex);
+       fsel = pcs_add_function(pcs, &function, np->name, vals, found,
+                               pgnames, 1);
+       if (fsel < 0) {
+               res = fsel;
                goto free_pins;
        }
 
-       res = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
-       if (res < 0)
+       gsel = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
+       if (gsel < 0) {
+               res = gsel;
                goto free_function;
+       }
 
        (*map)->type = PIN_MAP_TYPE_MUX_GROUP;
        (*map)->data.mux.group = np->name;
        (*map)->data.mux.function = np->name;
 
-       if (PCS_HAS_PINCONF) {
+       if (PCS_HAS_PINCONF && function) {
                res = pcs_parse_pinconf(pcs, np, function, map);
                if (res)
                        goto free_pingroups;
        } else {
                *num_maps = 1;
        }
+       mutex_unlock(&pcs->mutex);
+
        return 0;
 
 free_pingroups:
-       pinctrl_generic_remove_last_group(pcs->pctl);
+       pinctrl_generic_remove_group(pcs->pctl, gsel);
        *num_maps = 1;
 free_function:
-       pinmux_generic_remove_last_function(pcs->pctl);
-
+       pinmux_generic_remove_function(pcs->pctl, fsel);
+       mutex_unlock(&pcs->mutex);
 free_pins:
        devm_kfree(pcs->dev, pins);
 
 {
        const char *name = "pinctrl-single,bits";
        struct pcs_func_vals *vals;
-       int rows, *pins, found = 0, res = -ENOMEM, i;
+       int rows, *pins, found = 0, res = -ENOMEM, i, fsel, gsel;
        int npins_in_row;
-       struct pcs_function *function;
+       struct pcs_function *function = NULL;
 
        rows = pinctrl_count_index_with_args(np, name);
        if (rows <= 0) {
        }
 
        pgnames[0] = np->name;
-       function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1);
-       if (!function) {
-               res = -ENOMEM;
+       mutex_lock(&pcs->mutex);
+       fsel = pcs_add_function(pcs, &function, np->name, vals, found,
+                               pgnames, 1);
+       if (fsel < 0) {
+               res = fsel;
                goto free_pins;
        }
 
-       res = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
-       if (res < 0)
+       gsel = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
+       if (gsel < 0) {
+               res = gsel;
                goto free_function;
+       }
 
        (*map)->type = PIN_MAP_TYPE_MUX_GROUP;
        (*map)->data.mux.group = np->name;
        }
 
        *num_maps = 1;
+       mutex_unlock(&pcs->mutex);
+
        return 0;
 
 free_pingroups:
-       pinctrl_generic_remove_last_group(pcs->pctl);
+       pinctrl_generic_remove_group(pcs->pctl, gsel);
        *num_maps = 1;
 free_function:
-       pinmux_generic_remove_last_function(pcs->pctl);
+       pinmux_generic_remove_function(pcs->pctl, fsel);
+       mutex_unlock(&pcs->mutex);
 free_pins:
        devm_kfree(pcs->dev, pins);