From: Mark Brown Date: Mon, 19 Nov 2018 13:16:15 +0000 (+0000) Subject: Merge branch 'topic/coupled' of https://git.kernel.org/pub/scm/linux/kernel/git/broon... X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=ffb8c1e45e7ae648a3a1689aa71be50fb459316e;p=openwrt%2Fstaging%2Fblogic.git Merge branch 'topic/coupled' of https://git./linux/kernel/git/broonie/regulator into regulator-4.21 for trivial conflict --- ffb8c1e45e7ae648a3a1689aa71be50fb459316e diff --cc drivers/regulator/core.c index 55207264c212,fd237bc0fa7c..d7ffd7b12472 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@@ -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(®ulator_list_mutex); - if (!rdev->supply) - return; + ww_acquire_init(ww_ctx, ®ulator_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(®ulator_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