]> www.infradead.org Git - users/hch/misc.git/commitdiff
drm/xe/hwmon: Add SW clamp for power limits writes
authorKarthik Poosa <karthik.poosa@intel.com>
Fri, 8 Aug 2025 18:53:10 +0000 (00:23 +0530)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Tue, 12 Aug 2025 16:52:26 +0000 (12:52 -0400)
Clamp writes to power limits powerX_crit/currX_crit, powerX_cap,
powerX_max, to the maximum supported by the pcode mailbox
when sysfs-provided values exceed this limit.
Although the pcode already performs clamping, values beyond the pcode
mailbox's supported range get truncated, leading to incorrect
critical power settings.
This patch ensures proper clamping to prevent such truncation.

v2:
 - Address below review comments. (Riana)
 - Split comments into multiple sentences.
 - Use local variables for readability.
 - Add a debug log.
 - Use u64 instead of unsigned long.

v3:
 - Change drm_dbg logs to drm_info. (Badal)

v4:
 - Rephrase the drm_info log. (Rodrigo, Riana)
 - Rename variable max_mbx_power_limit to max_supp_power_limit, as
   limit is same for platforms with and without mailbox power limit
   support.

Signed-off-by: Karthik Poosa <karthik.poosa@intel.com>
Fixes: 92d44a422d0d ("drm/xe/hwmon: Expose card reactive critical power")
Fixes: fb1b70607f73 ("drm/xe/hwmon: Expose power attributes")
Reviewed-by: Riana Tauro <riana.tauro@intel.com>
Link: https://lore.kernel.org/r/20250808185310.3466529-1-karthik.poosa@intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
(cherry picked from commit d301eb950da59f962bafe874cf5eb6d61a85b2c2)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_hwmon.c

index f08fc4377d25e239f3ebdddf379320910bbecdcb..c17ed1ae86493cfc5542460575c170870bbcab79 100644 (file)
@@ -332,6 +332,7 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, u32 attr, int channe
        int ret = 0;
        u32 reg_val, max;
        struct xe_reg rapl_limit;
+       u64 max_supp_power_limit = 0;
 
        mutex_lock(&hwmon->hwmon_lock);
 
@@ -356,6 +357,20 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, u32 attr, int channe
                goto unlock;
        }
 
+       /*
+        * If the sysfs value exceeds the maximum pcode supported power limit value, clamp it to
+        * the supported maximum (U12.3 format).
+        * This is to avoid truncation during reg_val calculation below and ensure the valid
+        * power limit is sent for pcode which would clamp it to card-supported value.
+        */
+       max_supp_power_limit = ((PWR_LIM_VAL) >> hwmon->scl_shift_power) * SF_POWER;
+       if (value > max_supp_power_limit) {
+               value = max_supp_power_limit;
+               drm_info(&hwmon->xe->drm,
+                        "Power limit clamped as selected %s exceeds channel %d limit\n",
+                        PWR_ATTR_TO_STR(attr), channel);
+       }
+
        /* Computation in 64-bits to avoid overflow. Round to nearest. */
        reg_val = DIV_ROUND_CLOSEST_ULL((u64)value << hwmon->scl_shift_power, SF_POWER);
 
@@ -739,9 +754,23 @@ static int xe_hwmon_power_curr_crit_write(struct xe_hwmon *hwmon, int channel,
 {
        int ret;
        u32 uval;
+       u64 max_crit_power_curr = 0;
 
        mutex_lock(&hwmon->hwmon_lock);
 
+       /*
+        * If the sysfs value exceeds the pcode mailbox cmd POWER_SETUP_SUBCOMMAND_WRITE_I1
+        * max supported value, clamp it to the command's max (U10.6 format).
+        * This is to avoid truncation during uval calculation below and ensure the valid power
+        * limit is sent for pcode which would clamp it to card-supported value.
+        */
+       max_crit_power_curr = (POWER_SETUP_I1_DATA_MASK >> POWER_SETUP_I1_SHIFT) * scale_factor;
+       if (value > max_crit_power_curr) {
+               value = max_crit_power_curr;
+               drm_info(&hwmon->xe->drm,
+                        "Power limit clamped as selected exceeds channel %d limit\n",
+                        channel);
+       }
        uval = DIV_ROUND_CLOSEST_ULL(value << POWER_SETUP_I1_SHIFT, scale_factor);
        ret = xe_hwmon_pcode_write_i1(hwmon, uval);