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-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230419-dynamic-vmon-v2-1-c303bcc75ebc@skidata.com>
Date:   Fri, 21 Apr 2023 11:13:06 +0200
From:   Benjamin Bara <bbara93@...il.com>
To:     Liam Girdwood <lgirdwood@...il.com>,
        Mark Brown <broonie@...nel.org>, support.opensource@...semi.com
Cc:     DLG-Adam.Ward.opensource@...renesas.com,
        linux-kernel@...r.kernel.org,
        Matti Vaittinen <mazziesaccount@...il.com>,
        Benjamin Bara <benjamin.bara@...data.com>
Subject: [PATCH RFC v2 1/2] regulator: add properties to disable monitoring
 on actions

From: Benjamin Bara <benjamin.bara@...data.com>

These are useful when the state of the regulator might change during
runtime, but the monitors state (in hardware) are not implicitly changed
with the change of the regulator state or mode (in hardware). Also, when
the monitors should be disabled while ramping after a set_value().

Signed-off-by: Benjamin Bara <benjamin.bara@...data.com>
---
 drivers/regulator/core.c         | 64 ++++++++++++++++++++++++++++++++++++----
 include/linux/regulator/driver.h | 10 +++++++
 2 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 4fcd36055b02..5052e1da85a7 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1360,7 +1360,7 @@ static int notif_set_limit(struct regulator_dev *rdev,
 
 static int handle_notify_limits(struct regulator_dev *rdev,
 			int (*set)(struct regulator_dev *, int, int, bool),
-			struct notification_limit *limits)
+			const struct notification_limit *limits)
 {
 	int ret = 0;
 
@@ -1385,6 +1385,29 @@ static int handle_notify_limits(struct regulator_dev *rdev,
 
 	return ret;
 }
+
+static const struct notification_limit disable_limits = {
+	.prot = REGULATOR_NOTIF_LIMIT_DISABLE,
+	.err = REGULATOR_NOTIF_LIMIT_DISABLE,
+	.warn = REGULATOR_NOTIF_LIMIT_DISABLE,
+};
+
+static int monitors_set_state(struct regulator_dev *rdev, bool enable)
+{
+	const struct regulation_constraints *reg_c = rdev->constraints;
+	const struct regulator_ops *ops = rdev->desc->ops;
+	int ret = 0;
+
+	/* only set the state if monitoring is activated in the device-tree. */
+	if (reg_c->over_voltage_detection)
+		ret = handle_notify_limits(rdev, ops->set_over_voltage_protection,
+					   enable ? &reg_c->over_voltage_limits : &disable_limits);
+	if (!ret && reg_c->under_voltage_detection)
+		ret = handle_notify_limits(rdev, ops->set_under_voltage_protection,
+					   enable ? &reg_c->under_voltage_limits : &disable_limits);
+	return ret;
+}
+
 /**
  * set_machine_constraints - sets regulator constraints
  * @rdev: regulator source
@@ -1512,7 +1535,7 @@ static int set_machine_constraints(struct regulator_dev *rdev)
 			  "IC does not support requested over-current limits\n");
 	}
 
-	if (rdev->constraints->over_voltage_detection)
+	if (rdev->constraints->over_voltage_detection && !rdev->desc->mon_disable_while_reg_off)
 		ret = handle_notify_limits(rdev,
 					   ops->set_over_voltage_protection,
 					   &rdev->constraints->over_voltage_limits);
@@ -1526,7 +1549,7 @@ static int set_machine_constraints(struct regulator_dev *rdev)
 			  "IC does not support requested over voltage limits\n");
 	}
 
-	if (rdev->constraints->under_voltage_detection)
+	if (rdev->constraints->under_voltage_detection && !rdev->desc->mon_disable_while_reg_off)
 		ret = handle_notify_limits(rdev,
 					   ops->set_under_voltage_protection,
 					   &rdev->constraints->under_voltage_limits);
@@ -2734,7 +2757,10 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
 
 	trace_regulator_enable_complete(rdev_get_name(rdev));
 
-	return 0;
+	if (rdev->desc->mon_disable_while_reg_off)
+		ret = monitors_set_state(rdev, true);
+
+	return ret;
 }
 
 /**
@@ -2893,7 +2919,12 @@ EXPORT_SYMBOL_GPL(regulator_enable);
 
 static int _regulator_do_disable(struct regulator_dev *rdev)
 {
-	int ret;
+	int ret = 0;
+
+	if (rdev->desc->mon_disable_while_reg_off)
+		ret = monitors_set_state(rdev, false);
+	if (ret)
+		return ret;
 
 	trace_regulator_disable(rdev_get_name(rdev));
 
@@ -3537,7 +3568,7 @@ static int _regulator_set_voltage_time(struct regulator_dev *rdev,
 static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 				     int min_uV, int max_uV)
 {
-	int ret;
+	int ret = 0;
 	int delay = 0;
 	int best_val = 0;
 	unsigned int selector;
@@ -3545,6 +3576,11 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 	const struct regulator_ops *ops = rdev->desc->ops;
 	int old_uV = regulator_get_voltage_rdev(rdev);
 
+	if (rdev->desc->mon_disable_while_reg_set)
+		ret = monitors_set_state(rdev, false);
+	if (ret)
+		return ret;
+
 	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
 
 	min_uV += rdev->constraints->uV_offset;
@@ -3636,6 +3672,10 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 out:
 	trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
 
+	if (rdev->desc->mon_disable_while_reg_set)
+		/* TODO: ignore return value here when ret already !0? */
+		ret = monitors_set_state(rdev, true);
+
 	return ret;
 }
 
@@ -4545,7 +4585,19 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode)
 	if (ret < 0)
 		goto out;
 
+	if (mode & rdev->desc->mon_unsupported_reg_modes)
+		ret = monitors_set_state(rdev, false);
+	if (ret)
+		goto out;
+
 	ret = rdev->desc->ops->set_mode(rdev, mode);
+	if (ret)
+		goto out;
+
+	if (mode & ~rdev->desc->mon_unsupported_reg_modes)
+		/* TODO: if set_mode fails, we stay unmonitored */
+		ret = monitors_set_state(rdev, true);
+
 out:
 	regulator_unlock(rdev);
 	return ret;
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index d3b4a3d4514a..2fdc2c78e4bd 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -357,6 +357,12 @@ enum regulator_type {
  *                     the regulator was actually enabled. Max upto enable_time.
  *
  * @of_map_mode: Maps a hardware mode defined in a DeviceTree to a standard mode
+ *
+ * @mon_disable_while_reg_off: Disables regulator's monitors while it is off.
+ * @mon_disable_while_reg_set: Disables regulator's monitors while it is changing its value.
+ * @mon_unsupported_reg_modes: Disables regulator's monitors before an unsupported mode is entered.
+ *                             Unsupported REGULATOR_MODE_* are OR'ed. REGULATOR_MODE_INVALID means
+ *                             all modes can be monitored.
  */
 struct regulator_desc {
 	const char *name;
@@ -431,6 +437,10 @@ struct regulator_desc {
 	unsigned int poll_enabled_time;
 
 	unsigned int (*of_map_mode)(unsigned int mode);
+
+	unsigned int mon_disable_while_reg_off;
+	unsigned int mon_disable_while_reg_set;
+	unsigned int mon_unsupported_reg_modes;
 };
 
 /**

-- 
2.34.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ