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

drm/i915/hwmon: expose package temperature

Add hwmon support for temp1_input attribute, which will expose package
temperature in millidegree Celsius. With this in place we can monitor
package temperature using lm-sensors tool.

$ sensors
i915-pci-0300
Adapter: PCI adapter
in0: 990.00 mV
fan1: 1260 RPM
temp1: +45.0°C
power1: N/A (max = 35.00 W)
energy1: 12.62 kJ

v2: Use switch case (Anshuman)
v3: Comment adjustment (Riana)

Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11276
Signed-off-by: Raag Jadav <raag.jadav@intel.com>
Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
Reviewed-by: Riana Tauro <riana.tauro@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240910105242.3357276-1-raag.jadav@intel.com

authored by

Raag Jadav and committed by
Andi Shyti
0f47fed5 8967549f

+52
+8
Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
··· 83 83 Description: RO. Fan speed of device in RPM. 84 84 85 85 Only supported for particular Intel i915 graphics platforms. 86 + 87 + What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/temp1_input 88 + Date: November 2024 89 + KernelVersion: 6.12 90 + Contact: intel-gfx@lists.freedesktop.org 91 + Description: RO. GPU package temperature in millidegree Celsius. 92 + 93 + Only supported for particular Intel i915 graphics platforms.
+40
drivers/gpu/drm/i915/i915_hwmon.c
··· 7 7 #include <linux/hwmon-sysfs.h> 8 8 #include <linux/jiffies.h> 9 9 #include <linux/types.h> 10 + #include <linux/units.h> 10 11 11 12 #include "i915_drv.h" 12 13 #include "i915_hwmon.h" ··· 33 32 34 33 struct hwm_reg { 35 34 i915_reg_t gt_perf_status; 35 + i915_reg_t pkg_temp; 36 36 i915_reg_t pkg_power_sku_unit; 37 37 i915_reg_t pkg_power_sku; 38 38 i915_reg_t pkg_rapl_limit; ··· 282 280 }; 283 281 284 282 static const struct hwmon_channel_info * const hwm_info[] = { 283 + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), 285 284 HWMON_CHANNEL_INFO(in, HWMON_I_INPUT), 286 285 HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT), 287 286 HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT), ··· 311 308 { 312 309 return snb_pcode_write_p(&i915->uncore, PCODE_POWER_SETUP, 313 310 POWER_SETUP_SUBCOMMAND_WRITE_I1, 0, uval); 311 + } 312 + 313 + static umode_t 314 + hwm_temp_is_visible(const struct hwm_drvdata *ddat, u32 attr) 315 + { 316 + struct i915_hwmon *hwmon = ddat->hwmon; 317 + 318 + if (attr == hwmon_temp_input && i915_mmio_reg_valid(hwmon->rg.pkg_temp)) 319 + return 0444; 320 + 321 + return 0; 322 + } 323 + 324 + static int 325 + hwm_temp_read(struct hwm_drvdata *ddat, u32 attr, long *val) 326 + { 327 + struct i915_hwmon *hwmon = ddat->hwmon; 328 + intel_wakeref_t wakeref; 329 + u32 reg_val; 330 + 331 + switch (attr) { 332 + case hwmon_temp_input: 333 + with_intel_runtime_pm(ddat->uncore->rpm, wakeref) 334 + reg_val = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_temp); 335 + 336 + /* HW register value is in degrees Celsius, convert to millidegrees. */ 337 + *val = REG_FIELD_GET(TEMP_MASK, reg_val) * MILLIDEGREE_PER_DEGREE; 338 + return 0; 339 + default: 340 + return -EOPNOTSUPP; 341 + } 314 342 } 315 343 316 344 static umode_t ··· 726 692 struct hwm_drvdata *ddat = (struct hwm_drvdata *)drvdata; 727 693 728 694 switch (type) { 695 + case hwmon_temp: 696 + return hwm_temp_is_visible(ddat, attr); 729 697 case hwmon_in: 730 698 return hwm_in_is_visible(ddat, attr); 731 699 case hwmon_power: ··· 750 714 struct hwm_drvdata *ddat = dev_get_drvdata(dev); 751 715 752 716 switch (type) { 717 + case hwmon_temp: 718 + return hwm_temp_read(ddat, attr, val); 753 719 case hwmon_in: 754 720 return hwm_in_read(ddat, attr, val); 755 721 case hwmon_power: ··· 848 810 hwmon->rg.gt_perf_status = GEN12_RPSTAT1; 849 811 850 812 if (IS_DG1(i915) || IS_DG2(i915)) { 813 + hwmon->rg.pkg_temp = PCU_PACKAGE_TEMPERATURE; 851 814 hwmon->rg.pkg_power_sku_unit = PCU_PACKAGE_POWER_SKU_UNIT; 852 815 hwmon->rg.pkg_power_sku = PCU_PACKAGE_POWER_SKU; 853 816 hwmon->rg.pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT; ··· 856 817 hwmon->rg.energy_status_tile = INVALID_MMIO_REG; 857 818 hwmon->rg.fan_speed = PCU_PWM_FAN_SPEED; 858 819 } else { 820 + hwmon->rg.pkg_temp = INVALID_MMIO_REG; 859 821 hwmon->rg.pkg_power_sku_unit = INVALID_MMIO_REG; 860 822 hwmon->rg.pkg_power_sku = INVALID_MMIO_REG; 861 823 hwmon->rg.pkg_rapl_limit = INVALID_MMIO_REG;
+4
drivers/gpu/drm/i915/intel_mchbar_regs.h
··· 207 207 #define PCU_PACKAGE_ENERGY_STATUS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x593c) 208 208 209 209 #define GEN6_GT_PERF_STATUS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5948) 210 + 211 + #define PCU_PACKAGE_TEMPERATURE _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5978) 212 + #define TEMP_MASK REG_GENMASK(7, 0) 213 + 210 214 #define GEN6_RP_STATE_LIMITS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5994) 211 215 #define GEN6_RP_STATE_CAP _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5998) 212 216 #define RP0_CAP_MASK REG_GENMASK(7, 0)