Messages in this thread Patch in this message |  | | From | David Brownell <> | Subject | [patch 2.6.28-rc5] regulator: enable/disable refcounting | Date | Sun, 16 Nov 2008 11:44:46 -0800 |
| |
From: David Brownell <dbrownell@users.sourceforge.net>
Make the <linux/regulator.h> framework treat enable/disable call pairs like the <linux/clk.h> and <linux/interrupt.h> frameworks do: they're refcounted, so that different parts of a driver don't need to put work into coordination that frameworks normally handle. It's a minor object code shrink.
It also makes the regulator_is_disabled() kerneldoc say what it's actually returning: return value is not a refcount, and may report an error (e.g. I/O error from I2C).
It also fixes some minor regulator_put() goofage: removing unlocked access to the enable state. (But still not making regulator put/get match the refcounting pattern they invoke.)
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> --- drivers/regulator/core.c | 71 ++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 35 deletions(-)
--- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -79,7 +79,7 @@ struct regulator { int uA_load; int min_uV; int max_uV; - int enabled; /* client has called enabled */ + int enabled; /* count of client enables */ char *supply_name; struct device_attribute dev_attr; struct regulator_dev *rdev; @@ -933,16 +933,13 @@ void regulator_put(struct regulator *reg if (regulator == NULL || IS_ERR(regulator)) return; - if (regulator->enabled) { - printk(KERN_WARNING "Releasing supply %s while enabled\n", - regulator->supply_name); - WARN_ON(regulator->enabled); - regulator_disable(regulator); - } - mutex_lock(®ulator_list_mutex); rdev = regulator->rdev; + if (WARN(regulator->enabled, "Releasing supply %s while enabled\n", + regulator->supply_name)) + _regulator_disable(rdev); + /* remove any sysfs entries */ if (regulator->dev) { sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); @@ -1012,21 +1009,17 @@ static int _regulator_enable(struct regu */ int regulator_enable(struct regulator *regulator) { - int ret; - - if (regulator->enabled) { - printk(KERN_CRIT "Regulator %s already enabled\n", - regulator->supply_name); - WARN_ON(regulator->enabled); - return 0; - } + struct regulator_dev *rdev = regulator->rdev; + int ret = 0; - mutex_lock(®ulator->rdev->mutex); - regulator->enabled = 1; - ret = _regulator_enable(regulator->rdev); - if (ret != 0) - regulator->enabled = 0; - mutex_unlock(®ulator->rdev->mutex); + mutex_lock(&rdev->mutex); + if (regulator->enabled == 0) + ret = _regulator_enable(rdev); + else if (regulator->enabled < 0) + ret = -EIO; + if (ret == 0) + regulator->enabled++; + mutex_unlock(&rdev->mutex); return ret; } EXPORT_SYMBOL_GPL(regulator_enable); @@ -1078,19 +1071,21 @@ static int _regulator_disable(struct reg */ int regulator_disable(struct regulator *regulator) { - int ret; - - if (!regulator->enabled) { - printk(KERN_ERR "%s: not in use by this consumer\n", - __func__); - return 0; - } + struct regulator_dev *rdev = regulator->rdev; + int ret = 0; - mutex_lock(®ulator->rdev->mutex); - regulator->enabled = 0; - regulator->uA_load = 0; - ret = _regulator_disable(regulator->rdev); - mutex_unlock(®ulator->rdev->mutex); + mutex_lock(&rdev->mutex); + if (regulator->enabled == 1) { + ret = _regulator_disable(rdev); + if (ret == 0) + regulator->uA_load = 0; + } else if (WARN(regulator->enabled <= 0, + "unbalanced disables for supply %s\n", + regulator->supply_name)) + ret = -EIO; + if (ret == 0) + regulator->enabled--; + mutex_unlock(&rdev->mutex); return ret; } EXPORT_SYMBOL_GPL(regulator_disable); @@ -1166,7 +1161,13 @@ out: * regulator_is_enabled - is the regulator output enabled * @regulator: regulator source * - * Returns zero for disabled otherwise return number of enable requests. + * Returns positive if the regulator driver backing the source/client + * has requested that the device be enabled, zero if it hasn't, else a + * negative errno code. + * + * Note that the device backing this regulator handle can have multiple + * users, so it might be enabled even if regulator_enable() was never + * called for this particular source. */ int regulator_is_enabled(struct regulator *regulator) {
|  |