diff mbox

[01/13] OMAP: Introduce a user list for each voltage domain instance in the voltage driver.

Message ID 4C7FF100.5090204@ti.com (mailing list archive)
State Awaiting Upstream, archived
Headers show

Commit Message

Nishanth Menon Sept. 2, 2010, 6:46 p.m. UTC
None
diff mbox

Patch

From 3145fa45029fbdbfed2b2a2a6e335a72f8c47d36 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Thu, 2 Sep 2010 13:40:40 -0500
Subject: {HACK}[PATCH 2/2] regulator: core: introduce unsafe operations

introduce unsafe operations for consumers who can manage
their own operation sequencing and dont want core to bother
locking out multiple accesses exclusive of each other.

Signed-off-by: Nishanth Menon <nm@ti.com>
---
this patch is for demonstration purpose only

 drivers/regulator/core.c           |  121 ++++++++++++++++++++++++++----------
 include/linux/regulator/consumer.h |    2 +
 include/linux/regulator/driver.h   |    1 +
 3 files changed, 91 insertions(+), 33 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 0a1e199..c4c0e98 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -223,9 +223,11 @@  static ssize_t regulator_uV_show(struct device *dev,
 	struct regulator_dev *rdev = dev_get_drvdata(dev);
 	ssize_t ret;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 	ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev));
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 
 	return ret;
 }
@@ -288,9 +290,11 @@  static ssize_t regulator_state_show(struct device *dev,
 	struct regulator_dev *rdev = dev_get_drvdata(dev);
 	ssize_t ret;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 	ret = regulator_print_state(buf, _regulator_is_enabled(rdev));
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 
 	return ret;
 }
@@ -392,10 +396,12 @@  static ssize_t regulator_total_uA_show(struct device *dev,
 	struct regulator *regulator;
 	int uA = 0;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 	list_for_each_entry(regulator, &rdev->consumer_list, list)
 		uA += regulator->uA_load;
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 	return sprintf(buf, "%d\n", uA);
 }
 static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL);
@@ -1078,7 +1084,7 @@  static int _regulator_get_enable_time(struct regulator_dev *rdev)
 
 /* Internal regulator request function */
 static struct regulator *_regulator_get(struct device *dev, const char *id,
-					int exclusive)
+					int exclusive, int unsafe)
 {
 	struct regulator_dev *rdev;
 	struct regulator_map *map;
@@ -1156,6 +1162,8 @@  found:
 		else
 			rdev->use_count = 0;
 	}
+	if (unsafe)
+		rdev->flags |= REGULATOR_UNSAFEOPS_FLAG;
 
 out:
 	mutex_unlock(&regulator_list_mutex);
@@ -1178,7 +1186,7 @@  out:
  */
 struct regulator *regulator_get(struct device *dev, const char *id)
 {
-	return _regulator_get(dev, id, 0);
+	return _regulator_get(dev, id, 0, 0);
 }
 EXPORT_SYMBOL_GPL(regulator_get);
 
@@ -1205,11 +1213,27 @@  EXPORT_SYMBOL_GPL(regulator_get);
  */
 struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 {
-	return _regulator_get(dev, id, 1);
+	return _regulator_get(dev, id, 1, 0);
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
 /**
+ * regulator_get_exclusive_unsafe() - completely unsafe operations!
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Use of this function is strictly dangerous - caller should maintain
+ * exclusivity of access between operations, core will not take care of
+ * the same. this operation will fail unless the regulator can be
+ * exclusively openend
+ */
+struct regulator *regulator_get_exclusive_unsafe(struct device *dev,
+		const char *id)
+{
+	return _regulator_get(dev, id, 1, 1);
+}
+EXPORT_SYMBOL_GPL(regulator_get_exclusive);
+/**
  * regulator_put - "free" the regulator source
  * @regulator: regulator source
  *
@@ -1239,6 +1263,7 @@  void regulator_put(struct regulator *regulator)
 
 	rdev->open_count--;
 	rdev->flags &= ~REGULATOR_EXCLUSIVE_FLAG;
+	rdev->flags &= ~REGULATOR_UNSAFEOPS_FLAG;
 
 	module_put(rdev->owner);
 	mutex_unlock(&regulator_list_mutex);
@@ -1340,9 +1365,11 @@  int regulator_enable(struct regulator *regulator)
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret = 0;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 	ret = _regulator_enable(rdev);
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_enable);
@@ -1409,9 +1436,11 @@  int regulator_disable(struct regulator *regulator)
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret = 0;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 	ret = _regulator_disable(rdev);
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_disable);
@@ -1456,10 +1485,12 @@  int regulator_force_disable(struct regulator *regulator)
 {
 	int ret;
 
-	mutex_lock(&regulator->rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&regulator->rdev->mutex);
 	regulator->uA_load = 0;
 	ret = _regulator_force_disable(regulator->rdev);
-	mutex_unlock(&regulator->rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&regulator->rdev->mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_force_disable);
@@ -1489,9 +1520,11 @@  int regulator_is_enabled(struct regulator *regulator)
 {
 	int ret;
 
-	mutex_lock(&regulator->rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&regulator->rdev->mutex);
 	ret = _regulator_is_enabled(regulator->rdev);
-	mutex_unlock(&regulator->rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&regulator->rdev->mutex);
 
 	return ret;
 }
@@ -1532,9 +1565,11 @@  int regulator_list_voltage(struct regulator *regulator, unsigned selector)
 	if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
 		return -EINVAL;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 	ret = ops->list_voltage(rdev, selector);
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 
 	if (ret > 0) {
 		if (ret < rdev->constraints->min_uV)
@@ -1599,7 +1634,8 @@  int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 
 	/* sanity check */
 	if (!rdev->desc->ops->set_voltage) {
@@ -1617,7 +1653,8 @@  int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
 
 out:
 	_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL);
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_set_voltage);
@@ -1644,11 +1681,13 @@  int regulator_get_voltage(struct regulator *regulator)
 {
 	int ret;
 
-	mutex_lock(&regulator->rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&regulator->rdev->mutex);
 
 	ret = _regulator_get_voltage(regulator->rdev);
 
-	mutex_unlock(&regulator->rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&regulator->rdev->mutex);
 
 	return ret;
 }
@@ -1676,7 +1715,8 @@  int regulator_set_current_limit(struct regulator *regulator,
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 
 	/* sanity check */
 	if (!rdev->desc->ops->set_current_limit) {
@@ -1691,7 +1731,8 @@  int regulator_set_current_limit(struct regulator *regulator,
 
 	ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
 out:
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_set_current_limit);
@@ -1700,7 +1741,8 @@  static int _regulator_get_current_limit(struct regulator_dev *rdev)
 {
 	int ret;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 
 	/* sanity check */
 	if (!rdev->desc->ops->get_current_limit) {
@@ -1710,7 +1752,8 @@  static int _regulator_get_current_limit(struct regulator_dev *rdev)
 
 	ret = rdev->desc->ops->get_current_limit(rdev);
 out:
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 	return ret;
 }
 
@@ -1746,7 +1789,8 @@  int regulator_set_mode(struct regulator *regulator, unsigned int mode)
 	int ret;
 	int regulator_curr_mode;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 
 	/* sanity check */
 	if (!rdev->desc->ops->set_mode) {
@@ -1770,7 +1814,8 @@  int regulator_set_mode(struct regulator *regulator, unsigned int mode)
 
 	ret = rdev->desc->ops->set_mode(rdev, mode);
 out:
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_set_mode);
@@ -1779,7 +1824,8 @@  static unsigned int _regulator_get_mode(struct regulator_dev *rdev)
 {
 	int ret;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 
 	/* sanity check */
 	if (!rdev->desc->ops->get_mode) {
@@ -1789,7 +1835,8 @@  static unsigned int _regulator_get_mode(struct regulator_dev *rdev)
 
 	ret = rdev->desc->ops->get_mode(rdev);
 out:
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 	return ret;
 }
 
@@ -1838,7 +1885,8 @@  int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
 	int ret, output_uV, input_uV, total_uA_load = 0;
 	unsigned int mode;
 
-	mutex_lock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_lock(&rdev->mutex);
 
 	regulator->uA_load = uA_load;
 	ret = regulator_check_drms(rdev);
@@ -1892,7 +1940,8 @@  int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
 	}
 	ret = mode;
 out:
-	mutex_unlock(&rdev->mutex);
+	if (!(rdev->flags & REGULATOR_UNSAFEOPS_FLAG))
+		mutex_unlock(&rdev->mutex);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
@@ -1934,6 +1983,9 @@  static void _notifier_call_chain(struct regulator_dev *rdev,
 				  unsigned long event, void *data)
 {
 	struct regulator_dev *_rdev;
+	/* We will not have notifiers in this mode */
+	if (rdev->flags & REGULATOR_UNSAFEOPS_FLAG)
+		return;
 
 	/* call rdev chain first */
 	blocking_notifier_call_chain(&rdev->notifier, event, NULL);
@@ -2423,6 +2475,9 @@  int regulator_suspend_prepare(suspend_state_t state)
 	/* ON is handled by regulator active state */
 	if (state == PM_SUSPEND_ON)
 		return -EINVAL;
+	/* we will not suspend if we are opened unsafe */
+	if (rdev->flags & REGULATOR_UNSAFEOPS_FLAG)
+		return -EINVAL;
 
 	mutex_lock(&regulator_list_mutex);
 	list_for_each_entry(rdev, &regulator_list, list) {
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index ebd7472..c071992 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -131,6 +131,8 @@  struct regulator *__must_check regulator_get(struct device *dev,
 					     const char *id);
 struct regulator *__must_check regulator_get_exclusive(struct device *dev,
 						       const char *id);
+struct regulator *__must_check regulator_get_exclusive_unsafe(struct device *dev,
+						       const char *id);
 void regulator_put(struct regulator *regulator);
 
 /* regulator output control and status */
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 6397ab3..6d117d9 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -157,6 +157,7 @@  struct regulator_desc {
 };
 
 #define REGULATOR_EXCLUSIVE_FLAG	(0x1 << 1)
+#define REGULATOR_UNSAFEOPS_FLAG	(0x2 << 1)
 
 /*
  * struct regulator_dev
-- 
1.6.3.3