]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/pm: fix amdgpu_pm_info power display units
authorYang Wang <kevinyang.wang@amd.com>
Thu, 18 Jun 2026 04:54:14 +0000 (12:54 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jul 2026 16:58:16 +0000 (12:58 -0400)
amdgpu_pm_info displayed power sensor readings with the wrong fractional unit.
It treated the low byte of the raw sensor value as the decimal part of watts,
while that field represents milliwatts in the decoded value. As a result,
debugfs could report misleading SoC power when the remainder was not already
a two-digit centiwatt value.

Example with query = 0x00000354:

  raw field        value
  ---------------------
  query >> 8       3 W
  query & 0xff     84 mW
  decoded power    3084 mW

  output           value
  ---------------------
  before           3.84 W
  after            3.08 W

Fixes: f0b8f65b4825 ("drm/amd/amdgpu: fix the GPU power print error in pm info")
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Asad Kamal <asad.kamal@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 01992b121fb652c753d37e0c1427a2d1a557d2b1)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/pm/amdgpu_pm.c

index 2703f95d3d98f2bdd4dc0ae437cf585e5545d462..97da01aff76c7e69a69e04e3074c94b190af393d 100644 (file)
@@ -41,6 +41,8 @@
 
 #define DEVICE_ATTR_IS(_name)          (attr_id == device_attr_id__##_name)
 
+#define power_2_mwatt(power)   (((power) >> 8) * 1000 + ((power) & 0xff))
+
 struct od_attribute {
        struct kobj_attribute   attribute;
        struct list_head        entry;
@@ -3354,7 +3356,6 @@ static int amdgpu_hwmon_get_power(struct device *dev,
                                  enum amd_pp_sensors sensor)
 {
        struct amdgpu_device *adev = dev_get_drvdata(dev);
-       unsigned int uw;
        u32 query = 0;
        int r;
 
@@ -3363,9 +3364,7 @@ static int amdgpu_hwmon_get_power(struct device *dev,
                return r;
 
        /* convert to microwatts */
-       uw = (query >> 8) * 1000000 + (query & 0xff) * 1000;
-
-       return uw;
+       return power_2_mwatt(query) * 1000;
 }
 
 static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev,
@@ -4908,7 +4907,7 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
 {
        uint32_t mp1_ver = amdgpu_ip_version(adev, MP1_HWIP, 0);
        uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0);
-       uint32_t value;
+       uint32_t value, mwatt, centiwatt;
        uint64_t value64 = 0;
        uint32_t query = 0;
        int size;
@@ -4933,17 +4932,21 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
                seq_printf(m, "\t%u mV (VDDNB)\n", value);
        size = sizeof(uint32_t);
        if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_AVG_POWER, (void *)&query, &size)) {
+               mwatt = power_2_mwatt(query);
+               centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
                if (adev->flags & AMD_IS_APU)
-                       seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n", query >> 8, query & 0xff);
+                       seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
                else
-                       seq_printf(m, "\t%u.%02u W (average SoC)\n", query >> 8, query & 0xff);
+                       seq_printf(m, "\t%u.%02u W (average SoC)\n", centiwatt / 100, centiwatt % 100);
        }
        size = sizeof(uint32_t);
        if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_INPUT_POWER, (void *)&query, &size)) {
+               mwatt = power_2_mwatt(query);
+               centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
                if (adev->flags & AMD_IS_APU)
-                       seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n", query >> 8, query & 0xff);
+                       seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
                else
-                       seq_printf(m, "\t%u.%02u W (current SoC)\n", query >> 8, query & 0xff);
+                       seq_printf(m, "\t%u.%02u W (current SoC)\n", centiwatt / 100, centiwatt % 100);
        }
        size = sizeof(value);
        seq_printf(m, "\n");