Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: Introduce 64-bit energy attribute support

Many chips require 64-bit variables to display the accumulated energy,
even more so since the energy units are micro-Joule. Add new sensor type
"energy64" to support reporting the chip energy as 64-bit values.

Changing the entire hardware monitoring API is not feasible, and it is only
really necessary to support reading 64-bit values for the "energyX_input"
attribute. For this reason, keep the API as-is and use type casts on both
ends to pass 64-bit pointers when reading the accumulated energy. On the
write side (which is only useful for the energyX_enable attribute), keep
passing the written value as long.

Reviewed-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Tested-by: Chris Packham <chris.packham@alliedtelesis.co.nz> # INA780
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

+20 -10
+3
Documentation/hwmon/hwmon-kernel-api.rst
··· 159 159 hwmon_curr Current sensor 160 160 hwmon_power Power sensor 161 161 hwmon_energy Energy sensor 162 + hwmon_energy64 Energy sensor, reported as 64-bit signed value 162 163 hwmon_humidity Humidity sensor 163 164 hwmon_fan Fan speed sensor 164 165 hwmon_pwm PWM control ··· 289 288 The sensor channel number. 290 289 val: 291 290 Pointer to attribute value. 291 + For hwmon_energy64, `'val`' is passed as `long *` but needs 292 + a typecast to `s64 *`. 292 293 293 294 Return value: 294 295 0 on success, a negative error number otherwise.
+11 -5
drivers/hwmon/hwmon.c
··· 426 426 struct device_attribute *devattr, char *buf) 427 427 { 428 428 struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr); 429 + s64 val64; 429 430 long val; 430 431 int ret; 431 432 432 433 ret = hattr->ops->read(dev, hattr->type, hattr->attr, hattr->index, 433 - &val); 434 + (hattr->type == hwmon_energy64) ? (long *)&val64 : &val); 434 435 if (ret < 0) 435 436 return ret; 436 437 437 - trace_hwmon_attr_show(hattr->index + hwmon_attr_base(hattr->type), 438 - hattr->name, val); 438 + if (hattr->type != hwmon_energy64) 439 + val64 = val; 439 440 440 - return sprintf(buf, "%ld\n", val); 441 + trace_hwmon_attr_show(hattr->index + hwmon_attr_base(hattr->type), 442 + hattr->name, val64); 443 + 444 + return sprintf(buf, "%lld\n", val64); 441 445 } 442 446 443 447 static ssize_t hwmon_attr_show_string(struct device *dev, ··· 482 478 return ret; 483 479 484 480 trace_hwmon_attr_store(hattr->index + hwmon_attr_base(hattr->type), 485 - hattr->name, val); 481 + hattr->name, (s64)val); 486 482 487 483 return count; 488 484 } ··· 738 734 [hwmon_curr] = hwmon_curr_attr_templates, 739 735 [hwmon_power] = hwmon_power_attr_templates, 740 736 [hwmon_energy] = hwmon_energy_attr_templates, 737 + [hwmon_energy64] = hwmon_energy_attr_templates, 741 738 [hwmon_humidity] = hwmon_humidity_attr_templates, 742 739 [hwmon_fan] = hwmon_fan_attr_templates, 743 740 [hwmon_pwm] = hwmon_pwm_attr_templates, ··· 752 747 [hwmon_curr] = ARRAY_SIZE(hwmon_curr_attr_templates), 753 748 [hwmon_power] = ARRAY_SIZE(hwmon_power_attr_templates), 754 749 [hwmon_energy] = ARRAY_SIZE(hwmon_energy_attr_templates), 750 + [hwmon_energy64] = ARRAY_SIZE(hwmon_energy_attr_templates), 755 751 [hwmon_humidity] = ARRAY_SIZE(hwmon_humidity_attr_templates), 756 752 [hwmon_fan] = ARRAY_SIZE(hwmon_fan_attr_templates), 757 753 [hwmon_pwm] = ARRAY_SIZE(hwmon_pwm_attr_templates),
+1
include/linux/hwmon.h
··· 24 24 hwmon_curr, 25 25 hwmon_power, 26 26 hwmon_energy, 27 + hwmon_energy64, 27 28 hwmon_humidity, 28 29 hwmon_fan, 29 30 hwmon_pwm,
+5 -5
include/trace/events/hwmon.h
··· 9 9 10 10 DECLARE_EVENT_CLASS(hwmon_attr_class, 11 11 12 - TP_PROTO(int index, const char *attr_name, long val), 12 + TP_PROTO(int index, const char *attr_name, long long val), 13 13 14 14 TP_ARGS(index, attr_name, val), 15 15 16 16 TP_STRUCT__entry( 17 17 __field(int, index) 18 18 __string(attr_name, attr_name) 19 - __field(long, val) 19 + __field(long long, val) 20 20 ), 21 21 22 22 TP_fast_assign( ··· 25 25 __entry->val = val; 26 26 ), 27 27 28 - TP_printk("index=%d, attr_name=%s, val=%ld", 28 + TP_printk("index=%d, attr_name=%s, val=%lld", 29 29 __entry->index, __get_str(attr_name), __entry->val) 30 30 ); 31 31 32 32 DEFINE_EVENT(hwmon_attr_class, hwmon_attr_show, 33 33 34 - TP_PROTO(int index, const char *attr_name, long val), 34 + TP_PROTO(int index, const char *attr_name, long long val), 35 35 36 36 TP_ARGS(index, attr_name, val) 37 37 ); 38 38 39 39 DEFINE_EVENT(hwmon_attr_class, hwmon_attr_store, 40 40 41 - TP_PROTO(int index, const char *attr_name, long val), 41 + TP_PROTO(int index, const char *attr_name, long long val), 42 42 43 43 TP_ARGS(index, attr_name, val) 44 44 );