All of lore.kernel.org
 help / color / mirror / Atom feed
From: Krzysztof Kozlowski <krzk@kernel.org>
To: "Andrew F. Davis" <afd@ti.com>, "Pali Rohár" <pali@kernel.org>,
	"Sebastian Reichel" <sre@kernel.org>,
	"Krzysztof Kozlowski" <krzysztof.kozlowski@proceq.com>,
	linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Subject: [PATCH 2/2] power: supply: bq27xxx_battery: Notify about voltage and current changes
Date: Mon, 25 May 2020 16:12:00 +0200	[thread overview]
Message-ID: <20200525141200.17199-2-krzk@kernel.org> (raw)
In-Reply-To: <20200525141200.17199-1-krzk@kernel.org>

Read voltage and current and store them in the cache (like other
properties).  This has benefits:
1. User-space will be notified on voltage or current change.  These
   are important properties of charging so user-space might be
   interested in getting them.
2. Closes possible resource exhaustion attack through continuous I2C
   reads triggered by unprivileged power supply sysfs API.  User could
   just keep reading voltage_now or current_now sysfs entries leading
   to excessive I2C transfers.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 drivers/power/supply/bq27xxx_battery.c | 97 ++++++++++++--------------
 include/linux/power/bq27xxx_battery.h  |  2 +
 2 files changed, 48 insertions(+), 51 deletions(-)

diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
index 33c26d42cd02..048618c13e17 100644
--- a/drivers/power/supply/bq27xxx_battery.c
+++ b/drivers/power/supply/bq27xxx_battery.c
@@ -1520,6 +1520,48 @@ static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di)
 		return tval;
 }
 
+/*
+ * Return the battery average current in µA
+ * Note that current can be negative signed as well
+ * Or 0 if something fails.
+ */
+static int bq27xxx_battery_read_current(struct bq27xxx_device_info *di,
+					int flags)
+{
+	int curr;
+
+	curr = bq27xxx_read(di, BQ27XXX_REG_AI, false);
+	if (curr < 0) {
+		dev_err(di->dev, "error reading current\n");
+		return 0;
+	}
+
+	if (di->opts & BQ27XXX_O_ZERO) {
+		if (flags & BQ27000_FLAG_CHGS) {
+			dev_dbg(di->dev, "negative current!\n");
+			curr = -curr;
+		}
+
+		return curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
+	}
+
+	/* else: Other gauges return signed value */
+	return (int)((s16)curr) * 1000;
+}
+
+static int bq27xxx_battery_read_voltage(struct bq27xxx_device_info *di)
+{
+	int volt;
+
+	volt = bq27xxx_read(di, BQ27XXX_REG_VOLT, false);
+	if (volt < 0) {
+		dev_err(di->dev, "error reading voltage\n");
+		return volt;
+	}
+
+	return volt * 1000;
+}
+
 /*
  * Returns true if a battery over temperature condition is detected
  */
@@ -1606,6 +1648,8 @@ void bq27xxx_battery_update(struct bq27xxx_device_info *di)
 			cache.cycle_count = bq27xxx_battery_read_cyct(di);
 		if (di->regs[BQ27XXX_REG_AP] != INVALID_REG_ADDR)
 			cache.power_avg = bq27xxx_battery_read_pwr_avg(di);
+		cache.curr = bq27xxx_battery_read_current(di, cache.flags);
+		cache.voltage = bq27xxx_battery_read_voltage(di);
 
 		/* We only have to read charge design full once */
 		if (di->charge_design_full <= 0)
@@ -1633,39 +1677,6 @@ static void bq27xxx_battery_poll(struct work_struct *work)
 		schedule_delayed_work(&di->work, poll_interval * HZ);
 }
 
-/*
- * Return the battery average current in µA
- * Note that current can be negative signed as well
- * Or 0 if something fails.
- */
-static int bq27xxx_battery_current(struct bq27xxx_device_info *di,
-				   union power_supply_propval *val)
-{
-	int curr;
-	int flags;
-
-	curr = bq27xxx_read(di, BQ27XXX_REG_AI, false);
-	if (curr < 0) {
-		dev_err(di->dev, "error reading current\n");
-		return curr;
-	}
-
-	if (di->opts & BQ27XXX_O_ZERO) {
-		flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, true);
-		if (flags & BQ27000_FLAG_CHGS) {
-			dev_dbg(di->dev, "negative current!\n");
-			curr = -curr;
-		}
-
-		val->intval = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
-	} else {
-		/* Other gauges return signed value */
-		val->intval = (int)((s16)curr) * 1000;
-	}
-
-	return 0;
-}
-
 static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
 				  union power_supply_propval *val)
 {
@@ -1728,22 +1739,6 @@ static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
  * Return the battery Voltage in millivolts
  * Or < 0 if something fails.
  */
-static int bq27xxx_battery_voltage(struct bq27xxx_device_info *di,
-				   union power_supply_propval *val)
-{
-	int volt;
-
-	volt = bq27xxx_read(di, BQ27XXX_REG_VOLT, false);
-	if (volt < 0) {
-		dev_err(di->dev, "error reading voltage\n");
-		return volt;
-	}
-
-	val->intval = volt * 1000;
-
-	return 0;
-}
-
 static int bq27xxx_simple_value(int value,
 				union power_supply_propval *val)
 {
@@ -1777,13 +1772,13 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
 		ret = bq27xxx_battery_status(di, val);
 		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-		ret = bq27xxx_battery_voltage(di, val);
+		ret = bq27xxx_simple_value(di->cache.voltage, val);
 		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = di->cache.flags < 0 ? 0 : 1;
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
-		ret = bq27xxx_battery_current(di, val);
+		val->intval = di->cache.curr; /* Can be negative */
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
 		ret = bq27xxx_simple_value(di->cache.capacity, val);
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
index 507c5e214c42..418ba5e4029a 100644
--- a/include/linux/power/bq27xxx_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -49,6 +49,8 @@ struct bq27xxx_reg_cache {
 	int cycle_count;
 	int capacity;
 	int energy;
+	int curr;
+	int voltage;
 	int flags;
 	int power_avg;
 	int health;
-- 
2.17.1


  reply	other threads:[~2020-05-25 14:12 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-25 14:11 [PATCH 1/2] power: supply: bq27xxx_battery: Notify about all battery changes Krzysztof Kozlowski
2020-05-25 14:12 ` Krzysztof Kozlowski [this message]
2020-05-27  1:24 ` Andrew F. Davis
2020-05-27  7:22   ` Krzysztof Kozlowski
2020-05-27  7:30     ` Krzysztof Kozlowski
2020-06-16 10:52   ` Pavel Machek
2020-06-16 11:57     ` Krzysztof Kozlowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200525141200.17199-2-krzk@kernel.org \
    --to=krzk@kernel.org \
    --cc=afd@ti.com \
    --cc=krzysztof.kozlowski@proceq.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=pali@kernel.org \
    --cc=sre@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.