X-Git-Url: http://git.monstr.eu/?a=blobdiff_plain;f=drivers%2Fregulator%2Fcore.c;h=b9d7b45c7295459f0928e8436623b45897be23d1;hb=2573be22e5b6f24a0cabc97715c808c47e29eaaf;hp=925df9e6f1e37383de8e98040da73baffa87aa23;hpb=f9503385b1877ac34514cd5ea7683eee61c4bec3;p=linux-2.6-microblaze.git diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 925df9e6f1e3..b9d7b45c7295 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -50,6 +50,8 @@ #define rdev_dbg(rdev, fmt, ...) \ pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) +static DEFINE_WW_CLASS(regulator_ww_class); +static DEFINE_MUTEX(regulator_nesting_mutex); static DEFINE_MUTEX(regulator_list_mutex); static LIST_HEAD(regulator_map_list); static LIST_HEAD(regulator_ena_gpio_list); @@ -97,7 +99,7 @@ struct regulator_supply_alias { }; static int _regulator_is_enabled(struct regulator_dev *rdev); -static int _regulator_disable(struct regulator_dev *rdev); +static int _regulator_disable(struct regulator *regulator); static int _regulator_get_voltage(struct regulator_dev *rdev); static int _regulator_get_current_limit(struct regulator_dev *rdev); static unsigned int _regulator_get_mode(struct regulator_dev *rdev); @@ -154,7 +156,7 @@ static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) /** * regulator_lock_nested - lock a single regulator * @rdev: regulator source - * @subclass: mutex subclass used for lockdep + * @ww_ctx: w/w mutex acquire context * * This function can be called many times by one task on * a single regulator and its mutex will be locked only @@ -162,25 +164,54 @@ static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) * than the one, which initially locked the mutex, it will * wait on mutex. */ -static void regulator_lock_nested(struct regulator_dev *rdev, - unsigned int subclass) +static inline int regulator_lock_nested(struct regulator_dev *rdev, + struct ww_acquire_ctx *ww_ctx) { - if (!mutex_trylock(&rdev->mutex)) { - if (rdev->mutex_owner == current) { + bool lock = false; + int ret = 0; + + mutex_lock(®ulator_nesting_mutex); + + if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) { + if (rdev->mutex_owner == current) rdev->ref_cnt++; - return; + else + lock = true; + + if (lock) { + mutex_unlock(®ulator_nesting_mutex); + ret = ww_mutex_lock(&rdev->mutex, ww_ctx); + mutex_lock(®ulator_nesting_mutex); } - mutex_lock_nested(&rdev->mutex, subclass); + } else { + lock = true; } - rdev->ref_cnt = 1; - rdev->mutex_owner = current; + if (lock && ret != -EDEADLK) { + rdev->ref_cnt++; + rdev->mutex_owner = current; + } + + mutex_unlock(®ulator_nesting_mutex); + + return ret; } -static inline void regulator_lock(struct regulator_dev *rdev) +/** + * regulator_lock - lock a single regulator + * @rdev: regulator source + * + * This function can be called many times by one task on + * a single regulator and its mutex will be locked only + * once. If a task, which is calling this function is other + * than the one, which initially locked the mutex, it will + * wait on mutex. + */ +void regulator_lock(struct regulator_dev *rdev) { - regulator_lock_nested(rdev, 0); + regulator_lock_nested(rdev, NULL); } +EXPORT_SYMBOL_GPL(regulator_lock); /** * regulator_unlock - unlock a single regulator @@ -189,52 +220,64 @@ static inline void regulator_lock(struct regulator_dev *rdev) * This function unlocks the mutex when the * reference counter reaches 0. */ -static void regulator_unlock(struct regulator_dev *rdev) +void regulator_unlock(struct regulator_dev *rdev) { - if (rdev->ref_cnt != 0) { - rdev->ref_cnt--; + mutex_lock(®ulator_nesting_mutex); - if (!rdev->ref_cnt) { - rdev->mutex_owner = NULL; - mutex_unlock(&rdev->mutex); - } + if (--rdev->ref_cnt == 0) { + rdev->mutex_owner = NULL; + ww_mutex_unlock(&rdev->mutex); } + + WARN_ON_ONCE(rdev->ref_cnt < 0); + + mutex_unlock(®ulator_nesting_mutex); } +EXPORT_SYMBOL_GPL(regulator_unlock); -static int regulator_lock_recursive(struct regulator_dev *rdev, - unsigned int subclass) +static bool regulator_supply_is_couple(struct regulator_dev *rdev) { struct regulator_dev *c_rdev; int i; - for (i = 0; i < rdev->coupling_desc.n_coupled; i++) { + for (i = 1; i < rdev->coupling_desc.n_coupled; i++) { c_rdev = rdev->coupling_desc.coupled_rdevs[i]; + if (rdev->supply->rdev == c_rdev) + return true; + } + + return false; +} + +static void regulator_unlock_recursive(struct regulator_dev *rdev, + unsigned int n_coupled) +{ + struct regulator_dev *c_rdev; + int i; + + for (i = n_coupled; i > 0; i--) { + c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1]; + if (!c_rdev) continue; - regulator_lock_nested(c_rdev, subclass++); + if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) + regulator_unlock_recursive( + c_rdev->supply->rdev, + c_rdev->coupling_desc.n_coupled); - if (c_rdev->supply) - subclass = - regulator_lock_recursive(c_rdev->supply->rdev, - subclass); + regulator_unlock(c_rdev); } - - return subclass; } -/** - * regulator_unlock_dependent - unlock regulator's suppliers and coupled - * regulators - * @rdev: regulator source - * - * Unlock all regulators related with rdev by coupling or suppling. - */ -static void regulator_unlock_dependent(struct regulator_dev *rdev) +static int regulator_lock_recursive(struct regulator_dev *rdev, + struct regulator_dev **new_contended_rdev, + struct regulator_dev **old_contended_rdev, + struct ww_acquire_ctx *ww_ctx) { struct regulator_dev *c_rdev; - int i; + int i, err; for (i = 0; i < rdev->coupling_desc.n_coupled; i++) { c_rdev = rdev->coupling_desc.coupled_rdevs[i]; @@ -242,23 +285,126 @@ static void regulator_unlock_dependent(struct regulator_dev *rdev) if (!c_rdev) continue; - regulator_unlock(c_rdev); + if (c_rdev != *old_contended_rdev) { + err = regulator_lock_nested(c_rdev, ww_ctx); + if (err) { + if (err == -EDEADLK) { + *new_contended_rdev = c_rdev; + goto err_unlock; + } + + /* shouldn't happen */ + WARN_ON_ONCE(err != -EALREADY); + } + } else { + *old_contended_rdev = NULL; + } - if (c_rdev->supply) - regulator_unlock_dependent(c_rdev->supply->rdev); + if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { + err = regulator_lock_recursive(c_rdev->supply->rdev, + new_contended_rdev, + old_contended_rdev, + ww_ctx); + if (err) { + regulator_unlock(c_rdev); + goto err_unlock; + } + } } + + return 0; + +err_unlock: + regulator_unlock_recursive(rdev, i); + + return err; +} + +/** + * regulator_unlock_dependent - unlock regulator's suppliers and coupled + * regulators + * @rdev: regulator source + * @ww_ctx: w/w mutex acquire context + * + * Unlock all regulators related with rdev by coupling or suppling. + */ +static void regulator_unlock_dependent(struct regulator_dev *rdev, + struct ww_acquire_ctx *ww_ctx) +{ + regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled); + ww_acquire_fini(ww_ctx); } /** * 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 inline void regulator_lock_dependent(struct regulator_dev *rdev) +static void regulator_lock_dependent(struct regulator_dev *rdev, + struct ww_acquire_ctx *ww_ctx) +{ + struct regulator_dev *new_contended_rdev = NULL; + struct regulator_dev *old_contended_rdev = NULL; + int err; + + mutex_lock(®ulator_list_mutex); + + ww_acquire_init(ww_ctx, ®ulator_ww_class); + + 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) { - regulator_lock_recursive(rdev, 0); + 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; } /** @@ -281,6 +427,10 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp regnode = of_parse_phandle(dev->of_node, prop_name, 0); if (!regnode) { + regnode = of_get_child_regulator(dev->of_node, prop_name); + if (regnode) + return regnode; + dev_dbg(dev, "Looking up %s property in node %pOF failed\n", prop_name, dev->of_node); return NULL; @@ -616,8 +766,10 @@ static ssize_t regulator_total_uA_show(struct device *dev, int uA = 0; regulator_lock(rdev); - list_for_each_entry(regulator, &rdev->consumer_list, list) - uA += regulator->uA_load; + list_for_each_entry(regulator, &rdev->consumer_list, list) { + if (regulator->enable_count) + uA += regulator->uA_load; + } regulator_unlock(rdev); return sprintf(buf, "%d\n", uA); } @@ -772,7 +924,7 @@ static int drms_uA_update(struct regulator_dev *rdev) int current_uA = 0, output_uV, input_uV, err; unsigned int mode; - lockdep_assert_held_once(&rdev->mutex); + lockdep_assert_held_once(&rdev->mutex.base); /* * first check to see if we can set modes at all, otherwise just @@ -790,8 +942,10 @@ static int drms_uA_update(struct regulator_dev *rdev) return -EINVAL; /* calc total requested load */ - list_for_each_entry(sibling, &rdev->consumer_list, list) - current_uA += sibling->uA_load; + list_for_each_entry(sibling, &rdev->consumer_list, list) { + if (sibling->enable_count) + current_uA += sibling->uA_load; + } current_uA += rdev->constraints->system_load; @@ -1190,17 +1344,12 @@ static int set_machine_constraints(struct regulator_dev *rdev, rdev_err(rdev, "failed to set initial mode: %d\n", ret); return ret; } - } - - /* If the constraints say the regulator should be on at this point - * and we have control then make sure it is enabled. - */ - if (rdev->constraints->always_on || rdev->constraints->boot_on) { - ret = _regulator_do_enable(rdev); - if (ret < 0 && ret != -EINVAL) { - rdev_err(rdev, "failed to enable\n"); - return ret; - } + } else if (rdev->constraints->system_load) { + /* + * We'll only apply the initial system load if an + * initial mode wasn't specified. + */ + drms_uA_update(rdev); } if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) @@ -1248,6 +1397,27 @@ static int set_machine_constraints(struct regulator_dev *rdev, } } + /* If the constraints say the regulator should be on at this point + * and we have control then make sure it is enabled. + */ + if (rdev->constraints->always_on || rdev->constraints->boot_on) { + if (rdev->supply) { + ret = regulator_enable(rdev->supply); + if (ret < 0) { + _regulator_put(rdev->supply); + rdev->supply = NULL; + return ret; + } + } + + ret = _regulator_do_enable(rdev); + if (ret < 0 && ret != -EINVAL) { + rdev_err(rdev, "failed to enable\n"); + return ret; + } + rdev->use_count++; + } + print_constraints(rdev); return 0; } @@ -1662,8 +1832,12 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) return ret; } - /* Cascade always-on state to supply */ - if (_regulator_is_enabled(rdev)) { + /* + * In set_machine_constraints() we may have turned this regulator on + * but we couldn't propagate to the supply if it hadn't been resolved + * yet. Do it now. + */ + if (rdev->use_count) { ret = regulator_enable(rdev->supply); if (ret < 0) { _regulator_put(rdev->supply); @@ -1747,6 +1921,16 @@ struct regulator *_regulator_get(struct device *dev, const char *id, return regulator; } + mutex_lock(®ulator_list_mutex); + ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled); + mutex_unlock(®ulator_list_mutex); + + if (ret != 0) { + regulator = ERR_PTR(-EPROBE_DEFER); + put_device(&rdev->dev); + return regulator; + } + ret = regulator_resolve_supply(rdev); if (ret < 0) { regulator = ERR_PTR(ret); @@ -1866,6 +2050,9 @@ static void _regulator_put(struct regulator *regulator) lockdep_assert_held_once(®ulator_list_mutex); + /* Docs say you must disable before calling regulator_put() */ + WARN_ON(regulator->enable_count); + rdev = regulator->rdev; debugfs_remove_recursive(regulator->debugfs); @@ -2259,34 +2446,109 @@ static int _regulator_do_enable(struct regulator_dev *rdev) return 0; } +/** + * _regulator_handle_consumer_enable - handle that a consumer enabled + * @regulator: regulator source + * + * Some things on a regulator consumer (like the contribution towards total + * load on the regulator) only have an effect when the consumer wants the + * regulator enabled. Explained in example with two consumers of the same + * regulator: + * consumer A: set_load(100); => total load = 0 + * consumer A: regulator_enable(); => total load = 100 + * consumer B: set_load(1000); => total load = 100 + * consumer B: regulator_enable(); => total load = 1100 + * consumer A: regulator_disable(); => total_load = 1000 + * + * This function (together with _regulator_handle_consumer_disable) is + * responsible for keeping track of the refcount for a given regulator consumer + * and applying / unapplying these things. + * + * Returns 0 upon no error; -error upon error. + */ +static int _regulator_handle_consumer_enable(struct regulator *regulator) +{ + struct regulator_dev *rdev = regulator->rdev; + + lockdep_assert_held_once(&rdev->mutex.base); + + regulator->enable_count++; + if (regulator->uA_load && regulator->enable_count == 1) + return drms_uA_update(rdev); + + return 0; +} + +/** + * _regulator_handle_consumer_disable - handle that a consumer disabled + * @regulator: regulator source + * + * The opposite of _regulator_handle_consumer_enable(). + * + * Returns 0 upon no error; -error upon error. + */ +static int _regulator_handle_consumer_disable(struct regulator *regulator) +{ + struct regulator_dev *rdev = regulator->rdev; + + lockdep_assert_held_once(&rdev->mutex.base); + + if (!regulator->enable_count) { + rdev_err(rdev, "Underflow of regulator enable count\n"); + return -EINVAL; + } + + regulator->enable_count--; + if (regulator->uA_load && regulator->enable_count == 0) + return drms_uA_update(rdev); + + return 0; +} + /* locks held by regulator_enable() */ -static int _regulator_enable(struct regulator_dev *rdev) +static int _regulator_enable(struct regulator *regulator) { + struct regulator_dev *rdev = regulator->rdev; int ret; - lockdep_assert_held_once(&rdev->mutex); + lockdep_assert_held_once(&rdev->mutex.base); - /* check voltage and requested load before enabling */ - if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) - drms_uA_update(rdev); + if (rdev->use_count == 0 && rdev->supply) { + ret = _regulator_enable(rdev->supply); + if (ret < 0) + return ret; + } + + /* balance only if there are regulators coupled */ + if (rdev->coupling_desc.n_coupled > 1) { + ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); + if (ret < 0) + goto err_disable_supply; + } + + ret = _regulator_handle_consumer_enable(regulator); + if (ret < 0) + goto err_disable_supply; if (rdev->use_count == 0) { /* The regulator may on if it's not switchable or left on */ ret = _regulator_is_enabled(rdev); if (ret == -EINVAL || ret == 0) { if (!regulator_ops_is_valid(rdev, - REGULATOR_CHANGE_STATUS)) - return -EPERM; + REGULATOR_CHANGE_STATUS)) { + ret = -EPERM; + goto err_consumer_disable; + } ret = _regulator_do_enable(rdev); if (ret < 0) - return ret; + goto err_consumer_disable; _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, NULL); } else if (ret < 0) { rdev_err(rdev, "is_enabled() failed: %d\n", ret); - return ret; + goto err_consumer_disable; } /* Fallthrough on positive return values - already enabled */ } @@ -2294,6 +2556,15 @@ static int _regulator_enable(struct regulator_dev *rdev) rdev->use_count++; return 0; + +err_consumer_disable: + _regulator_handle_consumer_disable(regulator); + +err_disable_supply: + if (rdev->use_count == 0 && rdev->supply) + _regulator_disable(rdev->supply); + + return ret; } /** @@ -2310,30 +2581,12 @@ static int _regulator_enable(struct regulator_dev *rdev) int regulator_enable(struct regulator *regulator) { struct regulator_dev *rdev = regulator->rdev; - int ret = 0; - - if (regulator->always_on) - return 0; - - if (rdev->supply) { - ret = regulator_enable(rdev->supply); - if (ret != 0) - return ret; - } - - regulator_lock_dependent(rdev); - /* balance only if there are regulators coupled */ - if (rdev->coupling_desc.n_coupled > 1) { - ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); - if (ret != 0) - goto unlock; - } - ret = _regulator_enable(rdev); -unlock: - regulator_unlock_dependent(rdev); + struct ww_acquire_ctx ww_ctx; + int ret; - if (ret != 0 && rdev->supply) - regulator_disable(rdev->supply); + regulator_lock_dependent(rdev, &ww_ctx); + ret = _regulator_enable(regulator); + regulator_unlock_dependent(rdev, &ww_ctx); return ret; } @@ -2371,11 +2624,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev) } /* locks held by regulator_disable() */ -static int _regulator_disable(struct regulator_dev *rdev) +static int _regulator_disable(struct regulator *regulator) { + struct regulator_dev *rdev = regulator->rdev; int ret = 0; - lockdep_assert_held_once(&rdev->mutex); + lockdep_assert_held_once(&rdev->mutex.base); if (WARN(rdev->use_count <= 0, "unbalanced disables for %s\n", rdev_get_name(rdev))) @@ -2407,12 +2661,18 @@ static int _regulator_disable(struct regulator_dev *rdev) rdev->use_count = 0; } else if (rdev->use_count > 1) { - if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) - drms_uA_update(rdev); - rdev->use_count--; } + if (ret == 0) + ret = _regulator_handle_consumer_disable(regulator); + + if (ret == 0 && rdev->coupling_desc.n_coupled > 1) + ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); + + if (ret == 0 && rdev->use_count == 0 && rdev->supply) + ret = _regulator_disable(rdev->supply); + return ret; } @@ -2431,19 +2691,12 @@ static int _regulator_disable(struct regulator_dev *rdev) int regulator_disable(struct regulator *regulator) { struct regulator_dev *rdev = regulator->rdev; - int ret = 0; - - if (regulator->always_on) - return 0; - - regulator_lock_dependent(rdev); - ret = _regulator_disable(rdev); - if (rdev->coupling_desc.n_coupled > 1) - regulator_balance_voltage(rdev, PM_SUSPEND_ON); - regulator_unlock_dependent(rdev); + struct ww_acquire_ctx ww_ctx; + int ret; - if (ret == 0 && rdev->supply) - regulator_disable(rdev->supply); + regulator_lock_dependent(rdev, &ww_ctx); + ret = _regulator_disable(regulator); + regulator_unlock_dependent(rdev, &ww_ctx); return ret; } @@ -2454,7 +2707,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev) { int ret = 0; - lockdep_assert_held_once(&rdev->mutex); + lockdep_assert_held_once(&rdev->mutex.base); ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | REGULATOR_EVENT_PRE_DISABLE, NULL); @@ -2487,18 +2740,25 @@ static int _regulator_force_disable(struct regulator_dev *rdev) int regulator_force_disable(struct regulator *regulator) { struct regulator_dev *rdev = regulator->rdev; + struct ww_acquire_ctx ww_ctx; int ret; - regulator_lock_dependent(rdev); - regulator->uA_load = 0; + regulator_lock_dependent(rdev, &ww_ctx); + ret = _regulator_force_disable(regulator->rdev); + if (rdev->coupling_desc.n_coupled > 1) regulator_balance_voltage(rdev, PM_SUSPEND_ON); - regulator_unlock_dependent(rdev); - if (rdev->supply) - while (rdev->open_count--) - regulator_disable(rdev->supply); + if (regulator->uA_load) { + regulator->uA_load = 0; + ret = drms_uA_update(rdev); + } + + if (rdev->use_count != 0 && rdev->supply) + _regulator_disable(rdev->supply); + + regulator_unlock_dependent(rdev, &ww_ctx); return ret; } @@ -2508,14 +2768,12 @@ static void regulator_disable_work(struct work_struct *work) { struct regulator_dev *rdev = container_of(work, struct regulator_dev, disable_work.work); + struct ww_acquire_ctx ww_ctx; int count, i, ret; + struct regulator *regulator; + int total_count = 0; - regulator_lock(rdev); - - BUG_ON(!rdev->deferred_disables); - - count = rdev->deferred_disables; - rdev->deferred_disables = 0; + regulator_lock_dependent(rdev, &ww_ctx); /* * Workqueue functions queue the new work instance while the previous @@ -2525,23 +2783,27 @@ static void regulator_disable_work(struct work_struct *work) */ cancel_delayed_work(&rdev->disable_work); - for (i = 0; i < count; i++) { - ret = _regulator_disable(rdev); - if (ret != 0) - rdev_err(rdev, "Deferred disable failed: %d\n", ret); - } + list_for_each_entry(regulator, &rdev->consumer_list, list) { + count = regulator->deferred_disables; - regulator_unlock(rdev); + if (!count) + continue; + + total_count += count; + regulator->deferred_disables = 0; - if (rdev->supply) { for (i = 0; i < count; i++) { - ret = regulator_disable(rdev->supply); - if (ret != 0) { - rdev_err(rdev, - "Supply disable failed: %d\n", ret); - } + ret = _regulator_disable(regulator); + if (ret != 0) + rdev_err(rdev, "Deferred disable failed: %d\n", ret); } } + WARN_ON(!total_count); + + if (rdev->coupling_desc.n_coupled > 1) + regulator_balance_voltage(rdev, PM_SUSPEND_ON); + + regulator_unlock_dependent(rdev, &ww_ctx); } /** @@ -2560,14 +2822,11 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) { struct regulator_dev *rdev = regulator->rdev; - if (regulator->always_on) - return 0; - if (!ms) return regulator_disable(regulator); regulator_lock(rdev); - rdev->deferred_disables++; + regulator->deferred_disables++; mod_delayed_work(system_power_efficient_wq, &rdev->disable_work, msecs_to_jiffies(ms)); regulator_unlock(rdev); @@ -2642,9 +2901,9 @@ int regulator_is_enabled(struct regulator *regulator) if (regulator->always_on) return 1; - regulator_lock_dependent(regulator->rdev); + regulator_lock(regulator->rdev); ret = _regulator_is_enabled(regulator->rdev); - regulator_unlock_dependent(regulator->rdev); + regulator_unlock(regulator->rdev); return ret; } @@ -3181,6 +3440,36 @@ out: return ret; } +static int regulator_limit_voltage_step(struct regulator_dev *rdev, + int *current_uV, int *min_uV) +{ + struct regulation_constraints *constraints = rdev->constraints; + + /* Limit voltage change only if necessary */ + if (!constraints->max_uV_step || !_regulator_is_enabled(rdev)) + return 1; + + if (*current_uV < 0) { + *current_uV = _regulator_get_voltage(rdev); + + if (*current_uV < 0) + return *current_uV; + } + + if (abs(*current_uV - *min_uV) <= constraints->max_uV_step) + return 1; + + /* Clamp target voltage within the given step */ + if (*current_uV < *min_uV) + *min_uV = min(*current_uV + constraints->max_uV_step, + *min_uV); + else + *min_uV = max(*current_uV - constraints->max_uV_step, + *min_uV); + + return 0; +} + static int regulator_get_optimal_voltage(struct regulator_dev *rdev, int *current_uV, int *min_uV, int *max_uV, @@ -3228,7 +3517,7 @@ static int regulator_get_optimal_voltage(struct regulator_dev *rdev, int tmp_min = 0; int tmp_max = INT_MAX; - lockdep_assert_held_once(&c_rdevs[i]->mutex); + lockdep_assert_held_once(&c_rdevs[i]->mutex.base); ret = regulator_check_consumers(c_rdevs[i], &tmp_min, @@ -3292,6 +3581,17 @@ static int regulator_get_optimal_voltage(struct regulator_dev *rdev, desired_min_uV = possible_uV; finish: + /* Apply max_uV_step constraint if necessary */ + if (state == PM_SUSPEND_ON) { + ret = regulator_limit_voltage_step(rdev, current_uV, + &desired_min_uV); + if (ret < 0) + return ret; + + if (ret == 0) + done = false; + } + /* Set current_uV if wasn't done earlier in the code and if necessary */ if (n_coupled > 1 && *current_uV == -1) { @@ -3428,14 +3728,15 @@ out: */ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) { - int ret = 0; + struct ww_acquire_ctx ww_ctx; + int ret; - regulator_lock_dependent(regulator->rdev); + regulator_lock_dependent(regulator->rdev, &ww_ctx); ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, PM_SUSPEND_ON); - regulator_unlock_dependent(regulator->rdev); + regulator_unlock_dependent(regulator->rdev, &ww_ctx); return ret; } @@ -3507,18 +3808,19 @@ static int _regulator_set_suspend_voltage(struct regulator *regulator, int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, int max_uV, suspend_state_t state) { - int ret = 0; + struct ww_acquire_ctx ww_ctx; + int ret; /* PM_SUSPEND_ON is handled by regulator_set_voltage() */ if (regulator_check_states(state) || state == PM_SUSPEND_ON) return -EINVAL; - regulator_lock_dependent(regulator->rdev); + regulator_lock_dependent(regulator->rdev, &ww_ctx); ret = _regulator_set_suspend_voltage(regulator, min_uV, max_uV, state); - regulator_unlock_dependent(regulator->rdev); + regulator_unlock_dependent(regulator->rdev, &ww_ctx); return ret; } @@ -3708,13 +4010,12 @@ static int _regulator_get_voltage(struct regulator_dev *rdev) */ int regulator_get_voltage(struct regulator *regulator) { + struct ww_acquire_ctx ww_ctx; int ret; - regulator_lock_dependent(regulator->rdev); - + regulator_lock_dependent(regulator->rdev, &ww_ctx); ret = _regulator_get_voltage(regulator->rdev); - - regulator_unlock_dependent(regulator->rdev); + regulator_unlock_dependent(regulator->rdev, &ww_ctx); return ret; } @@ -3932,16 +4233,30 @@ EXPORT_SYMBOL_GPL(regulator_get_error_flags); * DRMS will sum the total requested load on the regulator and change * to the most efficient operating mode if platform constraints allow. * + * NOTE: when a regulator consumer requests to have a regulator + * disabled then any load that consumer requested no longer counts + * toward the total requested load. If the regulator is re-enabled + * then the previously requested load will start counting again. + * + * If a regulator is an always-on regulator then an individual consumer's + * load will still be removed if that consumer is fully disabled. + * * On error a negative errno is returned. */ int regulator_set_load(struct regulator *regulator, int uA_load) { struct regulator_dev *rdev = regulator->rdev; - int ret; + int old_uA_load; + int ret = 0; regulator_lock(rdev); + old_uA_load = regulator->uA_load; regulator->uA_load = uA_load; - ret = drms_uA_update(rdev); + if (regulator->enable_count && old_uA_load != uA_load) { + ret = drms_uA_update(rdev); + if (ret < 0) + regulator->uA_load = old_uA_load; + } regulator_unlock(rdev); return ret; @@ -4112,11 +4427,8 @@ int regulator_bulk_enable(int num_consumers, int ret = 0; for (i = 0; i < num_consumers; i++) { - if (consumers[i].consumer->always_on) - consumers[i].ret = 0; - else - async_schedule_domain(regulator_bulk_enable_async, - &consumers[i], &async_domain); + async_schedule_domain(regulator_bulk_enable_async, + &consumers[i], &async_domain); } async_synchronize_full_domain(&async_domain); @@ -4250,7 +4562,7 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free); int regulator_notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data) { - lockdep_assert_held_once(&rdev->mutex); + lockdep_assert_held_once(&rdev->mutex.base); _notifier_call_chain(rdev, event, data); return NOTIFY_DONE; @@ -4352,10 +4664,6 @@ static umode_t regulator_attr_is_visible(struct kobject *kobj, if (attr == &dev_attr_bypass.attr) return ops->get_bypass ? mode : 0; - /* some attributes are type-specific */ - if (attr == &dev_attr_requested_microamps.attr) - return rdev->desc->type == REGULATOR_CURRENT ? mode : 0; - /* constraints need specific supporting methods */ if (attr == &dev_attr_min_microvolts.attr || attr == &dev_attr_max_microvolts.attr) @@ -4467,6 +4775,43 @@ static void regulator_resolve_coupling(struct regulator_dev *rdev) } } +static void regulator_remove_coupling(struct regulator_dev *rdev) +{ + struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc; + struct regulator_dev *__c_rdev, *c_rdev; + unsigned int __n_coupled, n_coupled; + int i, k; + + n_coupled = c_desc->n_coupled; + + for (i = 1; i < n_coupled; i++) { + c_rdev = c_desc->coupled_rdevs[i]; + + if (!c_rdev) + continue; + + regulator_lock(c_rdev); + + __c_desc = &c_rdev->coupling_desc; + __n_coupled = __c_desc->n_coupled; + + for (k = 1; k < __n_coupled; k++) { + __c_rdev = __c_desc->coupled_rdevs[k]; + + if (__c_rdev == rdev) { + __c_desc->coupled_rdevs[k] = NULL; + __c_desc->n_resolved--; + break; + } + } + + regulator_unlock(c_rdev); + + c_desc->coupled_rdevs[i] = NULL; + c_desc->n_resolved--; + } +} + static int regulator_init_coupling(struct regulator_dev *rdev) { int n_phandles; @@ -4528,21 +4873,33 @@ regulator_register(const struct regulator_desc *regulator_desc, struct regulator_config *config = NULL; static atomic_t regulator_no = ATOMIC_INIT(-1); struct regulator_dev *rdev; + bool dangling_cfg_gpiod = false; + bool dangling_of_gpiod = false; struct device *dev; int ret, i; - if (regulator_desc == NULL || cfg == NULL) + if (cfg == NULL) return ERR_PTR(-EINVAL); + if (cfg->ena_gpiod) + dangling_cfg_gpiod = true; + if (regulator_desc == NULL) { + ret = -EINVAL; + goto rinse; + } dev = cfg->dev; WARN_ON(!dev); - if (regulator_desc->name == NULL || regulator_desc->ops == NULL) - return ERR_PTR(-EINVAL); + if (regulator_desc->name == NULL || regulator_desc->ops == NULL) { + ret = -EINVAL; + goto rinse; + } if (regulator_desc->type != REGULATOR_VOLTAGE && - regulator_desc->type != REGULATOR_CURRENT) - return ERR_PTR(-EINVAL); + regulator_desc->type != REGULATOR_CURRENT) { + ret = -EINVAL; + goto rinse; + } /* Only one of each should be implemented */ WARN_ON(regulator_desc->ops->get_voltage && @@ -4553,16 +4910,20 @@ regulator_register(const struct regulator_desc *regulator_desc, /* If we're using selectors we must implement list_voltage. */ if (regulator_desc->ops->get_voltage_sel && !regulator_desc->ops->list_voltage) { - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto rinse; } if (regulator_desc->ops->set_voltage_sel && !regulator_desc->ops->list_voltage) { - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto rinse; } rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); - if (rdev == NULL) - return ERR_PTR(-ENOMEM); + if (rdev == NULL) { + ret = -ENOMEM; + goto rinse; + } /* * Duplicate the config so the driver could override it after @@ -4571,17 +4932,28 @@ regulator_register(const struct regulator_desc *regulator_desc, config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); if (config == NULL) { kfree(rdev); - return ERR_PTR(-ENOMEM); + ret = -ENOMEM; + goto rinse; } init_data = regulator_of_get_init_data(dev, regulator_desc, config, &rdev->dev.of_node); + /* + * We need to keep track of any GPIO descriptor coming from the + * device tree until we have handled it over to the core. If the + * config that was passed in to this function DOES NOT contain + * a descriptor, and the config after this call DOES contain + * a descriptor, we definately got one from parsing the device + * tree. + */ + if (!cfg->ena_gpiod && config->ena_gpiod) + dangling_of_gpiod = true; if (!init_data) { init_data = config->init_data; rdev->dev.of_node = of_node_get(config->of_node); } - mutex_init(&rdev->mutex); + ww_mutex_init(&rdev->mutex, ®ulator_ww_class); rdev->reg_data = config->driver_data; rdev->owner = regulator_desc->owner; rdev->desc = regulator_desc; @@ -4614,6 +4986,9 @@ regulator_register(const struct regulator_desc *regulator_desc, config->ena_gpio, ret); goto clean; } + /* The regulator core took over the GPIO descriptor */ + dangling_cfg_gpiod = false; + dangling_of_gpiod = false; } /* register with sysfs */ @@ -4699,8 +5074,13 @@ wash: regulator_ena_gpio_free(rdev); mutex_unlock(®ulator_list_mutex); clean: + if (dangling_of_gpiod) + gpiod_put(config->ena_gpiod); kfree(rdev); kfree(config); +rinse: + if (dangling_cfg_gpiod) + gpiod_put(cfg->ena_gpiod); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(regulator_register); @@ -4721,15 +5101,19 @@ void regulator_unregister(struct regulator_dev *rdev) regulator_disable(rdev->supply); regulator_put(rdev->supply); } + mutex_lock(®ulator_list_mutex); + debugfs_remove_recursive(rdev->debugfs); flush_work(&rdev->disable_work.work); WARN_ON(rdev->open_count); + regulator_remove_coupling(rdev); unset_regulator_supplies(rdev); list_del(&rdev->list); regulator_ena_gpio_free(rdev); - mutex_unlock(®ulator_list_mutex); device_unregister(&rdev->dev); + + mutex_unlock(®ulator_list_mutex); } EXPORT_SYMBOL_GPL(regulator_unregister); @@ -4886,23 +5270,8 @@ static int supply_map_show(struct seq_file *sf, void *data) return 0; } +DEFINE_SHOW_ATTRIBUTE(supply_map); -static int supply_map_open(struct inode *inode, struct file *file) -{ - return single_open(file, supply_map_show, inode->i_private); -} -#endif - -static const struct file_operations supply_map_fops = { -#ifdef CONFIG_DEBUG_FS - .open = supply_map_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -#endif -}; - -#ifdef CONFIG_DEBUG_FS struct summary_data { struct seq_file *s; struct regulator_dev *parent; @@ -4937,8 +5306,6 @@ static void regulator_summary_show_subtree(struct seq_file *s, if (!rdev) return; - regulator_lock_nested(rdev, level); - opmode = _regulator_get_mode_unlocked(rdev); seq_printf(s, "%*s%-*s %3d %4d %6d %7s ", level * 3 + 1, "", @@ -4977,8 +5344,11 @@ static void regulator_summary_show_subtree(struct seq_file *s, switch (rdev->desc->type) { case REGULATOR_VOLTAGE: - seq_printf(s, "%37dmA %5dmV %5dmV", + seq_printf(s, "%3d %33dmA%c%5dmV %5dmV", + consumer->enable_count, consumer->uA_load / 1000, + consumer->uA_load && !consumer->enable_count ? + '*' : ' ', consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); break; @@ -4995,8 +5365,105 @@ static void regulator_summary_show_subtree(struct seq_file *s, class_for_each_device(®ulator_class, NULL, &summary_data, regulator_summary_show_children); +} + +struct summary_lock_data { + struct ww_acquire_ctx *ww_ctx; + struct regulator_dev **new_contended_rdev; + struct regulator_dev **old_contended_rdev; +}; + +static int regulator_summary_lock_one(struct device *dev, void *data) +{ + struct regulator_dev *rdev = dev_to_rdev(dev); + struct summary_lock_data *lock_data = data; + int ret = 0; + + if (rdev != *lock_data->old_contended_rdev) { + ret = regulator_lock_nested(rdev, lock_data->ww_ctx); + + if (ret == -EDEADLK) + *lock_data->new_contended_rdev = rdev; + else + WARN_ON_ONCE(ret); + } else { + *lock_data->old_contended_rdev = NULL; + } + + return ret; +} + +static int regulator_summary_unlock_one(struct device *dev, void *data) +{ + struct regulator_dev *rdev = dev_to_rdev(dev); + struct summary_lock_data *lock_data = data; + + if (lock_data) { + if (rdev == *lock_data->new_contended_rdev) + return -EDEADLK; + } regulator_unlock(rdev); + + return 0; +} + +static int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx, + struct regulator_dev **new_contended_rdev, + struct regulator_dev **old_contended_rdev) +{ + struct summary_lock_data lock_data; + int ret; + + lock_data.ww_ctx = ww_ctx; + lock_data.new_contended_rdev = new_contended_rdev; + lock_data.old_contended_rdev = old_contended_rdev; + + ret = class_for_each_device(®ulator_class, NULL, &lock_data, + regulator_summary_lock_one); + if (ret) + class_for_each_device(®ulator_class, NULL, &lock_data, + regulator_summary_unlock_one); + + return ret; +} + +static void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx) +{ + struct regulator_dev *new_contended_rdev = NULL; + struct regulator_dev *old_contended_rdev = NULL; + int err; + + mutex_lock(®ulator_list_mutex); + + ww_acquire_init(ww_ctx, ®ulator_ww_class); + + 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_summary_lock_all(ww_ctx, + &new_contended_rdev, + &old_contended_rdev); + + if (old_contended_rdev) + regulator_unlock(old_contended_rdev); + + } while (err == -EDEADLK); + + ww_acquire_done(ww_ctx); +} + +static void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx) +{ + class_for_each_device(®ulator_class, NULL, NULL, + regulator_summary_unlock_one); + ww_acquire_fini(ww_ctx); + + mutex_unlock(®ulator_list_mutex); } static int regulator_summary_show_roots(struct device *dev, void *data) @@ -5012,29 +5479,22 @@ static int regulator_summary_show_roots(struct device *dev, void *data) static int regulator_summary_show(struct seq_file *s, void *data) { + struct ww_acquire_ctx ww_ctx; + seq_puts(s, " regulator use open bypass opmode voltage current min max\n"); seq_puts(s, "---------------------------------------------------------------------------------------\n"); + regulator_summary_lock(&ww_ctx); + class_for_each_device(®ulator_class, NULL, s, regulator_summary_show_roots); - return 0; -} + regulator_summary_unlock(&ww_ctx); -static int regulator_summary_open(struct inode *inode, struct file *file) -{ - return single_open(file, regulator_summary_show, inode->i_private); + return 0; } -#endif - -static const struct file_operations regulator_summary_fops = { -#ifdef CONFIG_DEBUG_FS - .open = regulator_summary_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -#endif -}; +DEFINE_SHOW_ATTRIBUTE(regulator_summary); +#endif /* CONFIG_DEBUG_FS */ static int __init regulator_init(void) { @@ -5046,12 +5506,13 @@ static int __init regulator_init(void) if (!debugfs_root) pr_warn("regulator: Failed to create debugfs directory\n"); +#ifdef CONFIG_DEBUG_FS debugfs_create_file("supply_map", 0444, debugfs_root, NULL, &supply_map_fops); debugfs_create_file("regulator_summary", 0444, debugfs_root, NULL, ®ulator_summary_fops); - +#endif regulator_dummy_init(); return ret;