lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <54D2A91D.5090700@sonymobile.com>
Date:	Wed, 4 Feb 2015 15:19:57 -0800
From:	Tim Bird <tim.bird@...ymobile.com>
To:	<broonie@...nel.org>, <lgirdwood@...il.com>
CC:	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
	Bjorn Andersson <Bjorn.Andersson@...ymobile.com>
Subject: [PATCH] regulator: Support different config and dev of_nodes in regulator_register

Support calling regulator_register with a dev node and a config node
with different of_nodes.  This is useful when a single driver
wishes to register multiple child regulators.

Without this you get silent failures allocating a supply
for a regulator which is registered using the device node of the
regulator's DT parent (but it's own DT node).

Signed-off-by: Tim Bird <tim.bird@...ymobile.com>
---
I encountered a problem where I did a devm_regulator_register with
a dev (for a charger driver) and a config (for the regulator child
of the driver) that had different of_nodes.  In this case, inside
regulator_dev_lookup the code did not find the supply that I had
specified in the child regulator's DT node.  The DT setup looked
as follows:

charger@...0 {
      compatible = "qcom,pm8941-charger";
      reg = <0x1000 0x700>;
      ....
      chg_otg {
          regulator_name = "chg_otg";
          otg-supply = <&pm8941_mvs1>;
          ...
      }
}

This code checks the of_node of specified in the struct regulator_config
if the supply is not found in the dev.of_node.  This code has no effect
if dev.of_node and config.of_node are the same, so it shouldn't affect
any existing (working) code.

 drivers/regulator/core.c | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 128b432..36c5d78 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -128,13 +128,16 @@ static bool have_full_constraints(void)
 /**
  * of_get_regulator - get a regulator device node based on supply name
  * @dev: Device pointer for the consumer (of regulator) device
+ * @config: pointer to config for regulator registration
  * @supply: regulator supply name
  *
  * Extract the 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_regulator(struct device *dev, const char *supply)
+static struct device_node *of_get_regulator(struct device *dev,
+				const struct regulator_config *config,
+				const char *supply)
 {
 	struct device_node *regnode = NULL;
 	char prop_name[32]; /* 32 is max size of property name */
@@ -147,7 +150,15 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
 	if (!regnode) {
 		dev_dbg(dev, "Looking up %s property in node %s failed",
 				prop_name, dev->of_node->full_name);
-		return NULL;
+		if (!config || !config->of_node ||
+				config->of_node == dev->of_node)
+			return NULL;
+		regnode = of_parse_phandle(config->of_node, prop_name, 0);
+		if (!regnode) {
+			dev_dbg(dev, "Looking up %s property in node %s failed",
+				prop_name, dev->of_node->full_name);
+			return NULL;
+		}
 	}
 	return regnode;
 }
@@ -1284,9 +1295,10 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
 	}
 }
 
-static struct regulator_dev *regulator_dev_lookup(struct device *dev,
-						  const char *supply,
-						  int *ret)
+static struct regulator_dev *regulator_dev_config_lookup(struct device *dev,
+					const struct regulator_config *config,
+					const char *supply,
+					int *ret)
 {
 	struct regulator_dev *r;
 	struct device_node *node;
@@ -1297,7 +1309,7 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
 
 	/* first do a dt based lookup */
 	if (dev && dev->of_node) {
-		node = of_get_regulator(dev, supply);
+		node = of_get_regulator(dev, config, supply);
 		if (node) {
 			list_for_each_entry(r, &regulator_list, list)
 				if (r->dev.parent &&
@@ -1334,7 +1346,6 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
 			return map->regulator;
 	}
 
-
 	return NULL;
 }
 
@@ -1362,7 +1373,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
 
 	mutex_lock(&regulator_list_mutex);
 
-	rdev = regulator_dev_lookup(dev, id, &ret);
+	rdev = regulator_dev_config_lookup(dev, NULL, id, &ret);
 	if (rdev)
 		goto found;
 
@@ -3642,7 +3653,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
 	if (supply) {
 		struct regulator_dev *r;
 
-		r = regulator_dev_lookup(dev, supply, &ret);
+		r = regulator_dev_config_lookup(dev, config, supply, &ret);
 
 		if (ret == -ENODEV) {
 			/*
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ