Commit d2c3c8c3 authored by Ashutosh Dixit's avatar Ashutosh Dixit Committed by Anshuman Gupta

drm/i915/hwmon: Display clamped PL1 limit

HW allows arbitrary PL1 limits to be set but silently clamps these values
to "typical but not guaranteed" min/max values in pkg_power_sku
register. Follow the same pattern for sysfs, allow arbitrary PL1 limits to
be set but display clamped values when read, so that users see PL1 limits
HW is likely using. Otherwise users think HW is using arbitrarily high/low
PL1 limits they might have set. The previous write/read I1 power1_crit
limit also follows the same clamping pattern.

v2: Explain "why" in commit message and include bug link (Jani Nikula)

Bug: https://gitlab.freedesktop.org/drm/intel/-/issues/7704Signed-off-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Reviewed-by: default avatarAnshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: default avatarAnshuman Gupta <anshuman.gupta@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221215191727.2468770-1-ashutosh.dixit@intel.com
parent bed4b455
...@@ -359,6 +359,38 @@ hwm_power_is_visible(const struct hwm_drvdata *ddat, u32 attr, int chan) ...@@ -359,6 +359,38 @@ hwm_power_is_visible(const struct hwm_drvdata *ddat, u32 attr, int chan)
} }
} }
/*
* HW allows arbitrary PL1 limits to be set but silently clamps these values to
* "typical but not guaranteed" min/max values in rg.pkg_power_sku. Follow the
* same pattern for sysfs, allow arbitrary PL1 limits to be set but display
* clamped values when read. Write/read I1 also follows the same pattern.
*/
static int
hwm_power_max_read(struct hwm_drvdata *ddat, long *val)
{
struct i915_hwmon *hwmon = ddat->hwmon;
intel_wakeref_t wakeref;
u64 r, min, max;
*val = hwm_field_read_and_scale(ddat,
hwmon->rg.pkg_rapl_limit,
PKG_PWR_LIM_1,
hwmon->scl_shift_power,
SF_POWER);
with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
r = intel_uncore_read64(ddat->uncore, hwmon->rg.pkg_power_sku);
min = REG_FIELD_GET(PKG_MIN_PWR, r);
min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power);
max = REG_FIELD_GET(PKG_MAX_PWR, r);
max = mul_u64_u32_shr(max, SF_POWER, hwmon->scl_shift_power);
if (min && max)
*val = clamp_t(u64, *val, min, max);
return 0;
}
static int static int
hwm_power_read(struct hwm_drvdata *ddat, u32 attr, int chan, long *val) hwm_power_read(struct hwm_drvdata *ddat, u32 attr, int chan, long *val)
{ {
...@@ -368,12 +400,7 @@ hwm_power_read(struct hwm_drvdata *ddat, u32 attr, int chan, long *val) ...@@ -368,12 +400,7 @@ hwm_power_read(struct hwm_drvdata *ddat, u32 attr, int chan, long *val)
switch (attr) { switch (attr) {
case hwmon_power_max: case hwmon_power_max:
*val = hwm_field_read_and_scale(ddat, return hwm_power_max_read(ddat, val);
hwmon->rg.pkg_rapl_limit,
PKG_PWR_LIM_1,
hwmon->scl_shift_power,
SF_POWER);
return 0;
case hwmon_power_rated_max: case hwmon_power_rated_max:
*val = hwm_field_read_and_scale(ddat, *val = hwm_field_read_and_scale(ddat,
hwmon->rg.pkg_power_sku, hwmon->rg.pkg_power_sku,
......
...@@ -194,6 +194,8 @@ ...@@ -194,6 +194,8 @@
*/ */
#define PCU_PACKAGE_POWER_SKU _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5930) #define PCU_PACKAGE_POWER_SKU _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5930)
#define PKG_PKG_TDP GENMASK_ULL(14, 0) #define PKG_PKG_TDP GENMASK_ULL(14, 0)
#define PKG_MIN_PWR GENMASK_ULL(30, 16)
#define PKG_MAX_PWR GENMASK_ULL(46, 32)
#define PKG_MAX_WIN GENMASK_ULL(54, 48) #define PKG_MAX_WIN GENMASK_ULL(54, 48)
#define PKG_MAX_WIN_X GENMASK_ULL(54, 53) #define PKG_MAX_WIN_X GENMASK_ULL(54, 53)
#define PKG_MAX_WIN_Y GENMASK_ULL(52, 48) #define PKG_MAX_WIN_Y GENMASK_ULL(52, 48)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment