diff options
author | Douglas Anderson <dianders@chromium.org> | 2018-08-16 23:28:03 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-08-28 23:10:23 +0300 |
commit | 7e4d9683d6a716533f5c5026795b7b1ebdbcb2ed (patch) | |
tree | 422533b4d3a8a905f2217c312ba7b5b52598b44c /drivers/regulator | |
parent | 7d3827b5954840ff7765aef282257b7368b5ea67 (diff) | |
download | linux-7e4d9683d6a716533f5c5026795b7b1ebdbcb2ed.tar.xz |
regulator: core: Add locking to debugfs regulator_summary
Most functions that access the rdev lock the rdev mutex before looking
at data. ...but not the code that implements the debugfs
regulator_summary. It probably should though, so let's do it.
Note: this fixes no known issues. The problem was found only by code
inspection.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/core.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index df55cf8f09f0..f686f2311317 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3475,21 +3475,23 @@ out: } EXPORT_SYMBOL_GPL(regulator_set_current_limit); +static int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev) +{ + /* sanity check */ + if (!rdev->desc->ops->get_current_limit) + return -EINVAL; + + return rdev->desc->ops->get_current_limit(rdev); +} + static int _regulator_get_current_limit(struct regulator_dev *rdev) { int ret; regulator_lock(rdev); - - /* sanity check */ - if (!rdev->desc->ops->get_current_limit) { - ret = -EINVAL; - goto out; - } - - ret = rdev->desc->ops->get_current_limit(rdev); -out: + ret = _regulator_get_current_limit_unlocked(rdev); regulator_unlock(rdev); + return ret; } @@ -3554,21 +3556,23 @@ out: } EXPORT_SYMBOL_GPL(regulator_set_mode); +static unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev) +{ + /* sanity check */ + if (!rdev->desc->ops->get_mode) + return -EINVAL; + + return rdev->desc->ops->get_mode(rdev); +} + static unsigned int _regulator_get_mode(struct regulator_dev *rdev) { int ret; regulator_lock(rdev); - - /* sanity check */ - if (!rdev->desc->ops->get_mode) { - ret = -EINVAL; - goto out; - } - - ret = rdev->desc->ops->get_mode(rdev); -out: + ret = _regulator_get_mode_unlocked(rdev); regulator_unlock(rdev); + return ret; } @@ -4675,18 +4679,23 @@ static void regulator_summary_show_subtree(struct seq_file *s, struct regulation_constraints *c; struct regulator *consumer; struct summary_data summary_data; + unsigned int opmode; 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, "", 30 - level * 3, rdev_get_name(rdev), rdev->use_count, rdev->open_count, rdev->bypass_count, - regulator_opmode_to_str(_regulator_get_mode(rdev))); + regulator_opmode_to_str(opmode)); seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); - seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); + seq_printf(s, "%5dmA ", + _regulator_get_current_limit_unlocked(rdev) / 1000); c = rdev->constraints; if (c) { @@ -4733,6 +4742,8 @@ static void regulator_summary_show_subtree(struct seq_file *s, class_for_each_device(®ulator_class, NULL, &summary_data, regulator_summary_show_children); + + regulator_unlock(rdev); } static int regulator_summary_show_roots(struct device *dev, void *data) |