Merge branch 'topic/coupled' of https://git.kernel.org/pub/scm/linux/kernel/git/broon...
authorMark Brown <broonie@kernel.org>
Mon, 19 Nov 2018 13:16:15 +0000 (13:16 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 19 Nov 2018 13:16:15 +0000 (13:16 +0000)
1  2 
Documentation/devicetree/bindings/regulator/regulator.txt
drivers/regulator/core.c
drivers/regulator/of_regulator.c

index 55207264c212b984412d4ef5c3213edeab7345cb,fd237bc0fa7cdc3aea5edf1cd13a4f6cc35b5411..d7ffd7b1247228a0b5730f3e9834022f2c0f8910
@@@ -209,55 -334,46 +334,77 @@@ static void regulator_unlock_dependent(
  }
  
  /**
-  * regulator_unlock_supply - unlock a regulator and its supplies
-  * @rdev:         regulator source
+  * regulator_lock_dependent - lock regulator's suppliers and coupled regulators
+  * @rdev:                     regulator source
+  * @ww_ctx:                   w/w mutex acquire context
+  *
+  * This function as a wrapper on regulator_lock_recursive(), which locks
+  * all regulators related with rdev by coupling or suppling.
   */
- static void regulator_unlock_supply(struct regulator_dev *rdev)
+ static void regulator_lock_dependent(struct regulator_dev *rdev,
+                                    struct ww_acquire_ctx *ww_ctx)
  {
-       struct regulator *supply;
+       struct regulator_dev *new_contended_rdev = NULL;
+       struct regulator_dev *old_contended_rdev = NULL;
+       int err;
  
-       while (1) {
-               regulator_unlock(rdev);
-               supply = rdev->supply;
+       mutex_lock(&regulator_list_mutex);
  
-               if (!rdev->supply)
-                       return;
+       ww_acquire_init(ww_ctx, &regulator_ww_class);
  
-               rdev = supply->rdev;
-       }
+       do {
+               if (new_contended_rdev) {
+                       ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
+                       old_contended_rdev = new_contended_rdev;
+                       old_contended_rdev->ref_cnt++;
+               }
+               err = regulator_lock_recursive(rdev,
+                                              &new_contended_rdev,
+                                              &old_contended_rdev,
+                                              ww_ctx);
+               if (old_contended_rdev)
+                       regulator_unlock(old_contended_rdev);
+       } while (err == -EDEADLK);
+       ww_acquire_done(ww_ctx);
+       mutex_unlock(&regulator_list_mutex);
  }
  
 +/**
 + * of_get_child_regulator - get a child regulator device node
 + * based on supply name
 + * @parent: Parent device node
 + * @prop_name: Combination regulator supply name and "-supply"
 + *
 + * Traverse all child nodes.
 + * Extract the child regulator device node corresponding to the supply name.
 + * returns the device node corresponding to the regulator if found, else
 + * returns NULL.
 + */
 +static struct device_node *of_get_child_regulator(struct device_node *parent,
 +                                                const char *prop_name)
 +{
 +      struct device_node *regnode = NULL;
 +      struct device_node *child = NULL;
 +
 +      for_each_child_of_node(parent, child) {
 +              regnode = of_parse_phandle(child, prop_name, 0);
 +
 +              if (!regnode) {
 +                      regnode = of_get_child_regulator(child, prop_name);
 +                      if (regnode)
 +                              return regnode;
 +              } else {
 +                      return regnode;
 +              }
 +      }
 +      return NULL;
 +}
 +
  /**
   * of_get_regulator - get a regulator device node based on supply name
   * @dev: Device pointer for the consumer (of regulator) device
Simple merge