aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-03-11 20:43:34 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2009-03-31 04:56:28 -0400
commitcd94b5053081963614f6ad77b9b66a7968056c84 (patch)
tree42e2ae16a14457a4e755f63fd5ff95511220f9c8
parent1dc60343f874ce4bfbbc2c3d2f7865fc897df479 (diff)
regulator: refcount fixes
Fix some refcounting issues in the regulator framework, supporting regulator_disable() for regulators that were enabled at boot time via machine constraints: - Update those regulators' usecounts after enabling, so they can cleanly be disabled at that level. - Remove the problematic per-consumer usecount, so there's only one level of enable/disable. Buggy consumers could notice different bug symptoms. The main example would be refcounting bugs; also, any (out-of-tree) users of the experimental regulator_set_optimum_mode() stuff which don't call it when they're done using a regulator. This is a net minor codeshrink. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
-rw-r--r--drivers/regulator/core.c30
1 files changed, 8 insertions, 22 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 019a8a42ac18..944887578d66 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -52,7 +52,6 @@ struct regulator {
52 int uA_load; 52 int uA_load;
53 int min_uV; 53 int min_uV;
54 int max_uV; 54 int max_uV;
55 int enabled; /* count of client enables */
56 char *supply_name; 55 char *supply_name;
57 struct device_attribute dev_attr; 56 struct device_attribute dev_attr;
58 struct regulator_dev *rdev; 57 struct regulator_dev *rdev;
@@ -815,6 +814,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
815 rdev->constraints = NULL; 814 rdev->constraints = NULL;
816 goto out; 815 goto out;
817 } 816 }
817 rdev->use_count = 1;
818 } 818 }
819 819
820 print_constraints(rdev); 820 print_constraints(rdev);
@@ -1068,10 +1068,6 @@ void regulator_put(struct regulator *regulator)
1068 mutex_lock(&regulator_list_mutex); 1068 mutex_lock(&regulator_list_mutex);
1069 rdev = regulator->rdev; 1069 rdev = regulator->rdev;
1070 1070
1071 if (WARN(regulator->enabled, "Releasing supply %s while enabled\n",
1072 regulator->supply_name))
1073 _regulator_disable(rdev);
1074
1075 /* remove any sysfs entries */ 1071 /* remove any sysfs entries */
1076 if (regulator->dev) { 1072 if (regulator->dev) {
1077 sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 1073 sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
@@ -1146,12 +1142,7 @@ int regulator_enable(struct regulator *regulator)
1146 int ret = 0; 1142 int ret = 0;
1147 1143
1148 mutex_lock(&rdev->mutex); 1144 mutex_lock(&rdev->mutex);
1149 if (regulator->enabled == 0) 1145 ret = _regulator_enable(rdev);
1150 ret = _regulator_enable(rdev);
1151 else if (regulator->enabled < 0)
1152 ret = -EIO;
1153 if (ret == 0)
1154 regulator->enabled++;
1155 mutex_unlock(&rdev->mutex); 1146 mutex_unlock(&rdev->mutex);
1156 return ret; 1147 return ret;
1157} 1148}
@@ -1162,6 +1153,11 @@ static int _regulator_disable(struct regulator_dev *rdev)
1162{ 1153{
1163 int ret = 0; 1154 int ret = 0;
1164 1155
1156 if (WARN(rdev->use_count <= 0,
1157 "unbalanced disables for %s\n",
1158 rdev->desc->name))
1159 return -EIO;
1160
1165 /* are we the last user and permitted to disable ? */ 1161 /* are we the last user and permitted to disable ? */
1166 if (rdev->use_count == 1 && !rdev->constraints->always_on) { 1162 if (rdev->use_count == 1 && !rdev->constraints->always_on) {
1167 1163
@@ -1210,16 +1206,7 @@ int regulator_disable(struct regulator *regulator)
1210 int ret = 0; 1206 int ret = 0;
1211 1207
1212 mutex_lock(&rdev->mutex); 1208 mutex_lock(&rdev->mutex);
1213 if (regulator->enabled == 1) { 1209 ret = _regulator_disable(rdev);
1214 ret = _regulator_disable(rdev);
1215 if (ret == 0)
1216 regulator->uA_load = 0;
1217 } else if (WARN(regulator->enabled <= 0,
1218 "unbalanced disables for supply %s\n",
1219 regulator->supply_name))
1220 ret = -EIO;
1221 if (ret == 0)
1222 regulator->enabled--;
1223 mutex_unlock(&rdev->mutex); 1210 mutex_unlock(&rdev->mutex);
1224 return ret; 1211 return ret;
1225} 1212}
@@ -1266,7 +1253,6 @@ int regulator_force_disable(struct regulator *regulator)
1266 int ret; 1253 int ret;
1267 1254
1268 mutex_lock(&regulator->rdev->mutex); 1255 mutex_lock(&regulator->rdev->mutex);
1269 regulator->enabled = 0;
1270 regulator->uA_load = 0; 1256 regulator->uA_load = 0;
1271 ret = _regulator_force_disable(regulator->rdev); 1257 ret = _regulator_force_disable(regulator->rdev);
1272 mutex_unlock(&regulator->rdev->mutex); 1258 mutex_unlock(&regulator->rdev->mutex);