[PATCH v2 1/2] hwmon: (nct6775) Fix temperature alarm attributes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Driver displays wrong alarms for temperature attributes.

Turns out that temperature alarm bits are not fixed, but determined
by temperature source mapping. To fix the problem, walk through
the temperature sources to determine the correct alarm bit associated
with a given attribute.

Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx>
---
v2: Only create temperature alarm attributes if alarms are supported for a
    given temperature.
    Number of temperature alarms is either 2 (NCT6779) or 3 (other chips).
    Introduce function to determine temperature source for a given alarim.
    The limit is passed as parameter, since we'll use the same function later
    for temperature beeps.

 drivers/hwmon/nct6775.c |   80 +++++++++++++++++++++++++++++++++--------------
 1 file changed, 57 insertions(+), 23 deletions(-)

diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index 04638ae..2405ab4 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -625,6 +625,7 @@ struct nct6775_data {
 	u8 has_fan_min;		/* some fans don't have min register */
 	bool has_fan_div;
 
+	u8 num_temp_alarms;	/* 2 or 3 */
 	u8 temp_fixed_num;	/* 3 or 6 */
 	u8 temp_type[NUM_TEMP_FIXED];
 	s8 temp_offset[NUM_TEMP_FIXED];
@@ -1193,6 +1194,42 @@ show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
 		       (unsigned int)((data->alarms >> nr) & 0x01));
 }
 
+static int find_temp_source(struct nct6775_data *data, int index, int count)
+{
+	int source = data->temp_src[index];
+	int nr;
+
+	for (nr = 0; nr < count; nr++) {
+		int src;
+
+		src = nct6775_read_value(data,
+					 data->REG_TEMP_SOURCE[nr]) & 0x1f;
+		if (src == source)
+			return nr;
+	}
+	return -1;
+}
+
+static ssize_t
+show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	struct nct6775_data *data = nct6775_update_device(dev);
+	unsigned int alarm = 0;
+	int nr;
+
+	/*
+	 * For temperatures, there is no fixed mapping from registers to alarm
+	 * bits. Alarm bits are determined by the temperature source mapping.
+	 */
+	nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
+	if (nr >= 0) {
+		int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
+		alarm = (data->alarms >> bit) & 0x01;
+	}
+	return sprintf(buf, "%u\n", alarm);
+}
+
 static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0);
 static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0);
 static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0);
@@ -1874,22 +1911,18 @@ static struct sensor_device_attribute sda_temp_type[] = {
 };
 
 static struct sensor_device_attribute sda_temp_alarm[] = {
-	SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
-		    TEMP_ALARM_BASE),
-	SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
-		    TEMP_ALARM_BASE + 1),
-	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
-		    TEMP_ALARM_BASE + 2),
-	SENSOR_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL,
-		    TEMP_ALARM_BASE + 3),
-	SENSOR_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL,
-		    TEMP_ALARM_BASE + 4),
-	SENSOR_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL,
-		    TEMP_ALARM_BASE + 5),
+	SENSOR_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0),
+	SENSOR_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1),
+	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2),
+	SENSOR_ATTR(temp4_alarm, S_IRUGO, show_temp_alarm, NULL, 3),
+	SENSOR_ATTR(temp5_alarm, S_IRUGO, show_temp_alarm, NULL, 4),
+	SENSOR_ATTR(temp6_alarm, S_IRUGO, show_temp_alarm, NULL, 5),
+	SENSOR_ATTR(temp7_alarm, S_IRUGO, show_temp_alarm, NULL, 6),
+	SENSOR_ATTR(temp8_alarm, S_IRUGO, show_temp_alarm, NULL, 7),
+	SENSOR_ATTR(temp9_alarm, S_IRUGO, show_temp_alarm, NULL, 8),
+	SENSOR_ATTR(temp10_alarm, S_IRUGO, show_temp_alarm, NULL, 9),
 };
 
-#define NUM_TEMP_ALARM	ARRAY_SIZE(sda_temp_alarm)
-
 static ssize_t
 show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -3215,13 +3248,11 @@ static void nct6775_device_remove_files(struct device *dev)
 		device_remove_file(dev, &sda_temp_max[i].dev_attr);
 		device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
 		device_remove_file(dev, &sda_temp_crit[i].dev_attr);
+		device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
 		if (!(data->have_temp_fixed & (1 << i)))
 			continue;
 		device_remove_file(dev, &sda_temp_type[i].dev_attr);
 		device_remove_file(dev, &sda_temp_offset[i].dev_attr);
-		if (i >= NUM_TEMP_ALARM)
-			continue;
-		device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
 	}
 
 	device_remove_file(dev, &sda_caseopen[0].dev_attr);
@@ -3419,6 +3450,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->auto_pwm_num = 6;
 		data->has_fan_div = true;
 		data->temp_fixed_num = 3;
+		data->num_temp_alarms = 3;
 
 		data->ALARM_BITS = NCT6775_ALARM_BITS;
 
@@ -3483,6 +3515,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->auto_pwm_num = 4;
 		data->has_fan_div = false;
 		data->temp_fixed_num = 3;
+		data->num_temp_alarms = 3;
 
 		data->ALARM_BITS = NCT6776_ALARM_BITS;
 
@@ -3547,6 +3580,7 @@ static int nct6775_probe(struct platform_device *pdev)
 		data->auto_pwm_num = 4;
 		data->has_fan_div = false;
 		data->temp_fixed_num = 6;
+		data->num_temp_alarms = 2;
 
 		data->ALARM_BITS = NCT6779_ALARM_BITS;
 
@@ -3897,6 +3931,12 @@ static int nct6775_probe(struct platform_device *pdev)
 			if (err)
 				goto exit_remove;
 		}
+		if (find_temp_source(data, i, data->num_temp_alarms) >= 0) {
+			err = device_create_file(dev,
+						 &sda_temp_alarm[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
 		if (!(data->have_temp_fixed & (1 << i)))
 			continue;
 		err = device_create_file(dev, &sda_temp_type[i].dev_attr);
@@ -3905,12 +3945,6 @@ static int nct6775_probe(struct platform_device *pdev)
 		err = device_create_file(dev, &sda_temp_offset[i].dev_attr);
 		if (err)
 			goto exit_remove;
-		if (i >= NUM_TEMP_ALARM ||
-		    data->ALARM_BITS[TEMP_ALARM_BASE + i] < 0)
-			continue;
-		err = device_create_file(dev, &sda_temp_alarm[i].dev_attr);
-		if (err)
-			goto exit_remove;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) {
-- 
1.7.9.7


_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors




[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux