Re: [Intel-gfx] [PATCH 3/7] drm/i915/hwmon: Power PL1 limit and TDP setting

Dixit, Ashutosh
2022-08-30T02:34:40Z

On Thu, 25 Aug 2022 06:21:14 -0700, Badal Nilawar wrote:
>
> diff --git a/drivers/gpu/drm/i915/i915_hwmon.c b/drivers/gpu/drm/i915/i915_hwmon.c
> index 2192d0fd4c66..922463da65bf 100644
> --- a/drivers/gpu/drm/i915/i915_hwmon.c
> +++ b/drivers/gpu/drm/i915/i915_hwmon.c
> @@ -13,8 +13,22 @@
> #include "intel_mchbar_regs.h"
> #include "gt/intel_gt_regs.h"
>
> +/*
> + * SF_* - scale factors for particular quantities according to hwmon spec.
> + * - power - microwatts
> + */
> +#define SF_POWER 1000000
> +
> +#define FIELD_SHIFT(__mask) \
> + (BUILD_BUG_ON_ZERO(!__builtin_constant_p(__mask)) + \
> + BUILD_BUG_ON_ZERO((__mask) == 0) + \
> + __bf_shf(__mask))

Let's remove this macro, it's not needed, see below.

> +/*
> + * This function's return type of u64 allows for the case where the scaling
> + * of the field taken from the 32-bit register value might cause a result to
> + * exceed 32 bits.
> + */
> +static u64
> +hwm_field_read_and_scale(struct hwm_drvdata *ddat, i915_reg_t rgadr,
> + u32 field_msk, int field_shift,

Let's remove field_shift arg.

> + int nshift, u32 scale_factor)
> +{
> + struct intel_uncore *uncore = ddat->uncore;
> + intel_wakeref_t wakeref;
> + u32 reg_value;
> +
> + with_intel_runtime_pm(uncore->rpm, wakeref)
> + reg_value = intel_uncore_read(uncore, rgadr);
> +
> + reg_value = (reg_value & field_msk) >> field_shift;

This is just 'REG_FIELD_GET(field_msk, reg_value)'.

> +
> + return mul_u64_u32_shr(reg_value, scale_factor, nshift);
> +}
> +
> +static void
> +hwm_field_scale_and_write(struct hwm_drvdata *ddat, i915_reg_t rgadr,
> + u32 field_msk, int field_shift,

Let's remove field_shift arg.

> + int nshift, unsigned int scale_factor, long lval)
> +{
> + u32 nval;
> + u32 bits_to_clear;
> + u32 bits_to_set;
> +
> + /* Computation in 64-bits to avoid overflow. Round to nearest. */
> + nval = DIV_ROUND_CLOSEST_ULL((u64)lval << nshift, scale_factor);
> +
> + bits_to_clear = field_msk;
> + bits_to_set = (nval << field_shift) & field_msk;

This is just 'REG_FIELD_PREP(field_msk, nval)'.

> @@ -118,11 +260,40 @@ static void
> hwm_get_preregistration_info(struct drm_i915_private *i915)
> {
> struct i915_hwmon *hwmon = i915->hwmon;
> + struct intel_uncore *uncore = &i915->uncore;
> + intel_wakeref_t wakeref;
> + u32 val_sku_unit;
>
> - if (IS_DG1(i915) || IS_DG2(i915))
> + if (IS_DG1(i915) || IS_DG2(i915)) {
> hwmon->rg.gt_perf_status = GEN12_RPSTAT1;
> - else
> + hwmon->rg.pkg_power_sku_unit = PCU_PACKAGE_POWER_SKU_UNIT;
> + hwmon->rg.pkg_power_sku = INVALID_MMIO_REG;
> + hwmon->rg.pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT;
> + } else {
> hwmon->rg.gt_perf_status = INVALID_MMIO_REG;
> + hwmon->rg.pkg_power_sku_unit = INVALID_MMIO_REG;
> + hwmon->rg.pkg_power_sku = INVALID_MMIO_REG;
> + hwmon->rg.pkg_rapl_limit = INVALID_MMIO_REG;
> + }
> +
> + with_intel_runtime_pm(uncore->rpm, wakeref) {
> + /*
> + * The contents of register hwmon->rg.pkg_power_sku_unit do not change,
> + * so read it once and store the shift values.
> + *
> + * For some platforms, this value is defined as available "for all
> + * tiles", with the values consistent across all tiles.
> + * In this case, use the tile 0 value for all.
> + */

Let's delete this 2nd paragraph above, if values are available per tile we
should just be using per tile counters consistently (this is only true for
energy in our case, that patch will need to be fixed).

> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 2e3aa684cf1b..fd13411a28d9 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1866,6 +1866,22 @@
> #define POWER_LIMIT_1_MASK REG_BIT(11)
> #define POWER_LIMIT_2_MASK REG_BIT(12)
>
> +/*
> + * *_PACKAGE_POWER_SKU - SKU power and timing parameters.
> + * Used herein as a 64-bit register.
> + * These masks are defined using GENMASK_ULL as REG_GENMASK is limited to u32
> + * and as GENMASK is "long" and therefore 32-bits on a 32-bit system.
> + * PKG_PKG_TDP, PKG_MIN_PWR, and PKG_MAX_PWR are scaled in the same way as
> + * PKG_PWR_LIM_*, above.
> + * PKG_MAX_WIN has sub-fields for x and y, and has the value: is 1.x * 2^y.
> + */
> +#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_Y GENMASK_ULL(54, 53)
> +#define PKG_MAX_WIN_X GENMASK_ULL(52, 48)

Let's change this entire block above to just the following for this patch:

/* *_PACKAGE_POWER_SKU - SKU power and timing parameters */
#define PKG_PKG_TDP GENMASK_ULL(14, 0)

That is because none of the following #define's are used in this patch,
they will be added in the patches they are used (PKG_MIN_PWR and
PKG_MAX_PWR are not used at all). Also these fields are explained in
i915_hwmon.c, no need to explain so much in a common header file.

Thanks.
--
Ashutosh