All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: Hardware Monitoring <linux-hwmon@vger.kernel.org>
Cc: Jean Delvare <jdelvare@suse.com>, Guenter Roeck <linux@roeck-us.net>
Subject: [PATCH 03/17] hwmon: (lm93) Fix overflows seen when writing into limit attributes
Date: Sun,  4 Dec 2016 20:55:26 -0800	[thread overview]
Message-ID: <1480913740-5678-3-git-send-email-linux@roeck-us.net> (raw)
In-Reply-To: <1480913740-5678-1-git-send-email-linux@roeck-us.net>

Module test shows a large number of overflows, caused by missing clamps
as well as various conversions between variable types.

Also fix temperature calculations for hysteresis and offset registers.
For those, temperature calculations were a mix of millisecond and second
based, causing reported and accepted hysteresis and offset temperatures
to be widely off target.

This also changes the offset and base temperature attributes to be
officially reported and set in milli-degrees C. This was already the case
for the base temperature attribute, even though it was documented to be
reported and set in degrees C.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 Documentation/hwmon/lm93 | 26 ++++++++++++-------------
 drivers/hwmon/lm93.c     | 49 +++++++++++++++++++++++++-----------------------
 2 files changed, 39 insertions(+), 36 deletions(-)

diff --git a/Documentation/hwmon/lm93 b/Documentation/hwmon/lm93
index f3b2ad2ceb01..7bda7f0291e4 100644
--- a/Documentation/hwmon/lm93
+++ b/Documentation/hwmon/lm93
@@ -174,25 +174,25 @@ a "0" disables it. The h/w default is 0x0f (all temperatures bound).
 
 The function y = f(x) takes a source temperature x to a PWM output y.  This
 function of the LM93 is derived from a base temperature and a table of 12
-temperature offsets.  The base temperature is expressed in degrees C in the
-sysfs files temp<n>_auto_base.  The offsets are expressed in cumulative
-degrees C, with the value of offset <i> for temperature value <n> being
+temperature offsets.  The base temperature is expressed in milli-degrees C in
+the sysfs files temp<n>_auto_base.  The offsets are expressed in cumulative
+milli-degrees C, with the value of offset <i> for temperature value <n> being
 contained in the file temp<n>_auto_offset<i>.  E.g. if the base temperature
 is 40C:
 
      offset #	temp<n>_auto_offset<i>	range		pwm
 	 1		0		-		 25.00%
 	 2		0		-		 28.57%
-	 3		1		40C - 41C	 32.14%
-	 4		1		41C - 42C	 35.71%
-	 5		2		42C - 44C	 39.29%
-	 6		2		44C - 46C	 42.86%
-	 7		2		48C - 50C	 46.43%
-	 8		2		50C - 52C	 50.00%
-	 9		2		52C - 54C	 53.57%
-	10		2		54C - 56C	 57.14%
-	11		2		56C - 58C	 71.43%
-	12		2		58C - 60C	 85.71%
+	 3		500		40C - 41C	 32.14%
+	 4		500		41C - 42C	 35.71%
+	 5		1000		42C - 44C	 39.29%
+	 6		1000		44C - 46C	 42.86%
+	 7		1000		48C - 50C	 46.43%
+	 8		1000		50C - 52C	 50.00%
+	 9		1000		52C - 54C	 53.57%
+	10		1000		54C - 56C	 57.14%
+	11		1000		56C - 58C	 71.43%
+	12		1000		58C - 60C	 85.71%
 					> 60C		100.00%
 
 Valid offsets are in the range 0C <= x <= 7.5C in 0.5C increments.
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index 90bb04858117..7b3152368e3b 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -368,7 +368,7 @@ static unsigned LM93_IN_FROM_REG(int nr, u8 reg)
  * IN: mV, limits determined by channel nr
  * REG: scaling determined by channel nr
  */
-static u8 LM93_IN_TO_REG(int nr, unsigned val)
+static u8 LM93_IN_TO_REG(int nr, unsigned long val)
 {
 	/* range limit */
 	const long mv = clamp_val(val,
@@ -407,9 +407,13 @@ static unsigned LM93_IN_REL_FROM_REG(u8 reg, int upper, int vid)
  * upper also determines which nibble of the register is returned
  * (the other nibble will be 0x0)
  */
-static u8 LM93_IN_REL_TO_REG(unsigned val, int upper, int vid)
+static u8 LM93_IN_REL_TO_REG(unsigned long val, int upper, int vid)
 {
-	long uv_offset = vid * 1000 - val * 10000;
+	long uv_offset;
+
+	val = clamp_val(val, 0, 1000000);
+	uv_offset = vid * 1000 - val * 10000;
+
 	if (upper) {
 		uv_offset = clamp_val(uv_offset, 12500, 200000);
 		return (u8)((uv_offset /  12500 - 1) << 4);
@@ -453,28 +457,23 @@ static int LM93_TEMP_OFFSET_MODE_FROM_REG(u8 sfc2, int nr)
  * This function is common to all 4-bit temperature offsets
  * reg is 4 bits right justified
  * mode 0 => 1C/bit, mode !0 => 0.5C/bit
+ * Return value in milli-degrees C.
  */
 static int LM93_TEMP_OFFSET_FROM_REG(u8 reg, int mode)
 {
-	return (reg & 0x0f) * (mode ? 5 : 10);
+	return (reg & 0x0f) * (mode ? 500 : 1000);
 }
 
-#define LM93_TEMP_OFFSET_MIN  (0)
-#define LM93_TEMP_OFFSET_MAX0 (150)
-#define LM93_TEMP_OFFSET_MAX1 (75)
-
 /*
  * This function is common to all 4-bit temperature offsets
  * returns 4 bits right justified
  * mode 0 => 1C/bit, mode !0 => 0.5C/bit
+ * Input value is in milli-degrees C.
  */
-static u8 LM93_TEMP_OFFSET_TO_REG(int off, int mode)
+static u8 LM93_TEMP_OFFSET_TO_REG(unsigned long off, int mode)
 {
-	int factor = mode ? 5 : 10;
-
-	off = clamp_val(off, LM93_TEMP_OFFSET_MIN,
-		mode ? LM93_TEMP_OFFSET_MAX1 : LM93_TEMP_OFFSET_MAX0);
-	return (u8)((off + factor/2) / factor);
+	off = clamp_val(off, 0, mode ? 7500 : 15000);
+	return DIV_ROUND_CLOSEST(off, mode ? 500 : 1000);
 }
 
 /* 0 <= nr <= 3 */
@@ -494,7 +493,8 @@ static int LM93_TEMP_AUTO_OFFSET_FROM_REG(u8 reg, int nr, int mode)
  * REG: 1.0C/bit (mode 0) or 0.5C/bit (mode non-zero)
  * 0 <= nr <= 3
  */
-static u8 LM93_TEMP_AUTO_OFFSET_TO_REG(u8 old, int off, int nr, int mode)
+static u8 LM93_TEMP_AUTO_OFFSET_TO_REG(u8 old, unsigned long off, int nr,
+				       int mode)
 {
 	u8 new = LM93_TEMP_OFFSET_TO_REG(off, mode);
 
@@ -532,10 +532,13 @@ static int LM93_AUTO_BOOST_HYST_FROM_REGS(struct lm93_data *data, int nr,
 			LM93_TEMP_OFFSET_FROM_REG(reg, mode);
 }
 
-static u8 LM93_AUTO_BOOST_HYST_TO_REG(struct lm93_data *data, long hyst,
-		int nr, int mode)
+static u8 LM93_AUTO_BOOST_HYST_TO_REG(struct lm93_data *data,
+				      long hyst, int nr, int mode)
 {
-	u8 reg = LM93_TEMP_OFFSET_TO_REG(
+	u8 reg;
+
+	hyst = clamp_val(hyst, LM93_TEMP_MIN, LM93_TEMP_MAX);
+	reg = LM93_TEMP_OFFSET_TO_REG(
 			(LM93_TEMP_FROM_REG(data->boost[nr]) - hyst), mode);
 
 	switch (nr) {
@@ -592,7 +595,7 @@ static int LM93_PWM_FROM_REG(u8 reg, enum pwm_freq freq)
 }
 
 /* round up to nearest match */
-static u8 LM93_PWM_TO_REG(int pwm, enum pwm_freq freq)
+static u8 LM93_PWM_TO_REG(unsigned long pwm, enum pwm_freq freq)
 {
 	int i;
 	for (i = 0; i < 13; i++)
@@ -613,7 +616,7 @@ static int LM93_FAN_FROM_REG(u16 regs)
  * RPM: (82.5 to 1350000)
  * REG: 14-bits, LE, *left* justified
  */
-static u16 LM93_FAN_TO_REG(long rpm)
+static u16 LM93_FAN_TO_REG(unsigned long rpm)
 {
 	u16 count, regs;
 
@@ -642,7 +645,7 @@ static int LM93_PWM_FREQ_FROM_REG(u8 reg)
 }
 
 /* round up to nearest match */
-static u8 LM93_PWM_FREQ_TO_REG(int freq)
+static u8 LM93_PWM_FREQ_TO_REG(unsigned long freq)
 {
 	int i;
 	for (i = 7; i > 0; i--)
@@ -1471,10 +1474,10 @@ static ssize_t store_temp_auto_boost_hyst(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = dev_get_drvdata(dev);
 	struct i2c_client *client = data->client;
-	unsigned long val;
+	long val;
 	int err;
 
-	err = kstrtoul(buf, 10, &val);
+	err = kstrtol(buf, 10, &val);
 	if (err)
 		return err;
 
-- 
2.5.0


  parent reply	other threads:[~2016-12-05  6:04 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-05  4:55 [PATCH 01/17] hwmon: (adm9240) Fix overflows seen when writing into limit attributes Guenter Roeck
2016-12-05  4:55 ` [PATCH 02/17] hwmon: (ds620) Fix overflows seen when writing temperature limits Guenter Roeck
2016-12-08 13:47   ` Jean Delvare
2016-12-05  4:55 ` Guenter Roeck [this message]
2016-12-13 14:01   ` [PATCH 03/17] hwmon: (lm93) Fix overflows seen when writing into limit attributes Jean Delvare
2016-12-13 14:52     ` Guenter Roeck
2016-12-05  4:55 ` [PATCH 04/17] hwmon: (smsc47m192) " Guenter Roeck
2016-12-08 13:57   ` Jean Delvare
2016-12-08 19:24     ` Guenter Roeck
2016-12-05  4:55 ` [PATCH 05/17] hwmon: (adm1025) Fix overflows seen when writing voltage limits Guenter Roeck
2016-12-08 14:04   ` Jean Delvare
2016-12-05  4:55 ` [PATCH 06/17] hwmon: (adm1026) Fix overflows seen when writing into limit attributes Guenter Roeck
2016-12-08 14:33   ` Jean Delvare
2016-12-08 15:34     ` Guenter Roeck
2016-12-09  9:29       ` Jean Delvare
2016-12-05  4:55 ` [PATCH 07/17] hwmon: (adt7462) " Guenter Roeck
2016-12-08 15:08   ` Jean Delvare
2016-12-05  4:55 ` [PATCH 08/17] hwmon: (adt7470) " Guenter Roeck
2016-12-08 15:14   ` Jean Delvare
2016-12-08 18:14     ` Guenter Roeck
2016-12-05  4:55 ` [PATCH 09/17] hwmon: (nct7802) " Guenter Roeck
2016-12-09  9:49   ` Jean Delvare
2016-12-09 14:22     ` Guenter Roeck
2016-12-09 15:25       ` Jean Delvare
2016-12-09 18:11         ` Guenter Roeck
2016-12-05  4:55 ` [PATCH 10/17] hwmon: (lm87) Fix overflow seen when writing voltage " Guenter Roeck
2016-12-09 15:07   ` Jean Delvare
2016-12-05  4:55 ` [PATCH 11/17] hwmon: (lm85) Fix overflows " Guenter Roeck
2016-12-09 16:07   ` Jean Delvare
2016-12-05  4:55 ` [PATCH 12/17] hwmon: (dme1737) Fix overflows seen when writing into " Guenter Roeck
2016-12-12  9:33   ` Jean Delvare
2016-12-12 14:21     ` Guenter Roeck
2016-12-05  4:55 ` [PATCH 13/17] hwmon: (emc2103) Fix overflows seen when temperature " Guenter Roeck
2016-12-12 10:44   ` Jean Delvare
2016-12-05  4:55 ` [PATCH 14/17] hwmon: (emcw201) Fix overflows seen when writing into " Guenter Roeck
2016-12-12 10:48   ` Jean Delvare
2016-12-12 14:23     ` Guenter Roeck
2016-12-05  4:55 ` [PATCH 15/17] hwmln: (g762) Fix overflows and crash seen when writing " Guenter Roeck
2016-12-12 11:14   ` Jean Delvare
2016-12-12 14:19     ` Guenter Roeck
2016-12-05  4:55 ` [PATCH 16/17] hwmon: (gl518sm) Fix overflows seen when writing into " Guenter Roeck
2016-12-13  9:48   ` Jean Delvare
2016-12-13 21:56     ` Guenter Roeck
2016-12-05  4:55 ` [PATCH 17/17] hwmon: (gl520sm) " Guenter Roeck
2016-12-13  9:56   ` Jean Delvare
2016-12-13 14:49     ` Guenter Roeck
2016-12-08 13:29 ` [PATCH 01/17] hwmon: (adm9240) " Jean Delvare
2016-12-08 15:18   ` Guenter Roeck

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=1480913740-5678-3-git-send-email-linux@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=jdelvare@suse.com \
    --cc=linux-hwmon@vger.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.