Re: [Intel-gfx] [PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-10-13 Thread Dixit, Ashutosh
On Mon, 03 Oct 2022 14:32:36 -0700, Andi Shyti wrote:
>

Hi Andi,

> > diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
> > b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
> > index f9d6d3b08bba..19b9fe3ef237 100644
> > --- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
> > +++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
> > @@ -26,6 +26,15 @@ Description: RO. Card default power limit (default 
> > TDP setting).
> >
> > Only supported for particular Intel i915 graphics platforms.
> >
> > +What:  /sys/devices/.../hwmon/hwmon/power1_max_interval
> > +Date:  February 2023
> > +KernelVersion: 6.2
> > +Contact:   dri-devel@lists.freedesktop.org
>
> same question here.
>
> > +Description:   RW. Sustained power limit interval (Tau in PL1/Tau) in
> > +   milliseconds over which sustained power is averaged.
> > +
> > +   Only supported for particular Intel i915 graphics platforms.
> > +
> >  What:  /sys/devices/.../hwmon/hwmon/power1_crit
> >  Date:  February 2023
> >  KernelVersion: 6.2
> > diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
> > b/drivers/gpu/drm/i915/i915_hwmon.c
> > index 2394fa789793..641143956c45 100644
> > --- a/drivers/gpu/drm/i915/i915_hwmon.c
> > +++ b/drivers/gpu/drm/i915/i915_hwmon.c
> > @@ -20,11 +20,13 @@
> >   * - power  - microwatts
> >   * - curr   - milliamperes
> >   * - energy - microjoules
> > + * - time   - milliseconds
> >   */
> >  #define SF_VOLTAGE 1000
> >  #define SF_POWER   100
> >  #define SF_CURR1000
> >  #define SF_ENERGY  100
> > +#define SF_TIME1000
> >
> >  struct hwm_reg {
> > i915_reg_t gt_perf_status;
> > @@ -53,6 +55,7 @@ struct i915_hwmon {
> > struct hwm_reg rg;
> > int scl_shift_power;
> > int scl_shift_energy;
> > +   int scl_shift_time;
> >  };
> >
> >  static void
> > @@ -161,6 +164,115 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
> > return 0;
> >  }
> >
> > +static ssize_t
> > +hwm_power1_max_interval_show(struct device *dev, struct device_attribute 
> > *attr,
> > +char *buf)
> > +{
> > +   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
> > +   struct i915_hwmon *hwmon = ddat->hwmon;
> > +   intel_wakeref_t wakeref;
> > +   u32 r, x, y, x_w = 2; /* 2 bits */
> > +   u64 tau4, out;
> > +
> > +   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
> > +   r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
> > +
> > +   x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
> > +   y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
> > +   /*
> > +* tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
> > +* = (4 | x) << (y - 2)
> > +* where (y - 2) ensures a 1.x fixed point representation of 1.x
> > +* However because y can be < 2, we compute
> > +* tau4 = (4 | x) << y
> > +* but add 2 when doing the final right shift to account for units
> > +*/
> > +   tau4 = ((1 << x_w) | x) << y;
> > +   /* val in hwmon interface units (millisec) */
> > +   out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
> > +
> > +   return sysfs_emit(buf, "%llu\n", out);
> > +}
> > +
> > +static ssize_t
> > +hwm_power1_max_interval_store(struct device *dev,
> > + struct device_attribute *attr,
> > + const char *buf, size_t count)
> > +{
> > +   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
> > +   struct i915_hwmon *hwmon = ddat->hwmon;
> > +   long val, max_win, ret;
>
> you have some type mismatch here:
>
>  - val should be unsigned long
>  - max_win should be u64
>  - ret should be int

Thanks, fixed in v9.

>
> > +   u32 x, y, rxy, x_w = 2; /* 2 bits */
> > +   u64 tau4, r;
> > +
> > +#define PKG_MAX_WIN_DEFAULT 0x12ull
>
> could you please add a comment here?

Done.

> > +
> > +   ret = kstrtoul(buf, 0, &val);
> > +   if (ret)
> > +   return ret;
> > +
> > +   /*
> > +* val must be < max in hwmon interface units. The steps below are
> > +* explained in i915_power1_max_interval_show()
> > +*/
> > +   r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
> > +
> > +   x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
> > +   y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
> > +   tau4 = ((1 << x_w) | x) << y;
> > +   max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
> > +
> > +   if (val > max_win)
> > +   return -EINVAL;
> > +
> > +   /* val in hw units */
> > +   val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME);
> > +   /* Convert to 1.x * power(2,y) */
> > +   if (!val)
> > +   return -EINVAL;
> > +   y = ilog2(val);
> > +   /* x = (val - (1 << y)) >> (y - 2); */
>
> some leftover

No, it's a comment describing what's happening in the line below. I've left
it as is for now. Can remove it if you think it's unnecessary.

>
> > +   x = (val - (1ul << y)) << x_w >> y;
> > +
> > +   rxy = REG_FI

[PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-10-13 Thread Ashutosh Dixit
Expose power1_max_interval, that is the tau corresponding to PL1, as a
custom hwmon attribute. Some bit manipulation is needed because of the
format of PKG_PWR_LIM_1_TIME in
GT0_PACKAGE_RAPL_LIMIT register (1.x * power(2,y)).

v2: Update date and kernel version in Documentation (Badal)
v3: Cleaned up hwm_power1_max_interval_store() (Badal)
v4:
  - Fixed review comments (Anshuman)
  - In hwm_power1_max_interval_store() get PKG_MAX_WIN from
pkg_power_sku when it is valid (Ashutosh)
  - KernelVersion: 6.2, Date: February 2023 in doc (Tvrtko)
v5: On some of the DGFX setups it is seen that although pkg_power_sku
is valid the field PKG_WIN_MAX is not populated. So it is
decided to stick to default value of PKG_WIN_MAX (Ashutosh)
v6: Change contact to intel-gfx (Rodrigo)
Fixed variable types in hwm_power1_max_interval_store (Andi)
Documented PKG_MAX_WIN_DEFAULT (Andi)
Removed else in hwm_attributes_visible (Andi)

Signed-off-by: Ashutosh Dixit 
Signed-off-by: Badal Nilawar 
Acked-by: Guenter Roeck 
Reviewed-by: Anshuman Gupta 
---
 .../ABI/testing/sysfs-driver-intel-i915-hwmon |   9 ++
 drivers/gpu/drm/i915/i915_hwmon.c | 119 +-
 drivers/gpu/drm/i915/intel_mchbar_regs.h  |   7 ++
 3 files changed, 134 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
index a7a6512fcc8ca..9dc5ff14107bb 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
+++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
@@ -26,6 +26,15 @@ Description: RO. Card default power limit (default TDP 
setting).
 
Only supported for particular Intel i915 graphics platforms.
 
+What:  /sys/devices/.../hwmon/hwmon/power1_max_interval
+Date:  February 2023
+KernelVersion: 6.2
+Contact:   intel-...@lists.freedesktop.org
+Description:   RW. Sustained power limit interval (Tau in PL1/Tau) in
+   milliseconds over which sustained power is averaged.
+
+   Only supported for particular Intel i915 graphics platforms.
+
 What:  /sys/devices/.../hwmon/hwmon/power1_crit
 Date:  February 2023
 KernelVersion: 6.2
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
b/drivers/gpu/drm/i915/i915_hwmon.c
index 2b24a7a711400..58f80380e5427 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.c
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -20,11 +20,13 @@
  * - power  - microwatts
  * - curr   - milliamperes
  * - energy - microjoules
+ * - time   - milliseconds
  */
 #define SF_VOLTAGE 1000
 #define SF_POWER   100
 #define SF_CURR1000
 #define SF_ENERGY  100
+#define SF_TIME1000
 
 struct hwm_reg {
i915_reg_t gt_perf_status;
@@ -53,6 +55,7 @@ struct i915_hwmon {
struct hwm_reg rg;
int scl_shift_power;
int scl_shift_energy;
+   int scl_shift_time;
 };
 
 static void
@@ -159,6 +162,119 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
mutex_unlock(&hwmon->hwmon_lock);
 }
 
+static ssize_t
+hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   intel_wakeref_t wakeref;
+   u32 r, x, y, x_w = 2; /* 2 bits */
+   u64 tau4, out;
+
+   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+   r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+   x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
+   y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
+   /*
+* tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
+* = (4 | x) << (y - 2)
+* where (y - 2) ensures a 1.x fixed point representation of 1.x
+* However because y can be < 2, we compute
+* tau4 = (4 | x) << y
+* but add 2 when doing the final right shift to account for units
+*/
+   tau4 = ((1 << x_w) | x) << y;
+   /* val in hwmon interface units (millisec) */
+   out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   return sysfs_emit(buf, "%llu\n", out);
+}
+
+static ssize_t
+hwm_power1_max_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   u32 x, y, rxy, x_w = 2; /* 2 bits */
+   u64 tau4, r, max_win;
+   unsigned long val;
+   int ret;
+
+   ret = kstrtoul(buf, 0, &val);
+   if (ret)
+   return ret;
+
+   /*
+* Max HW supported tau in '1.x * power(2,y)' format, x = 0, y = 0x12
+* The hwmon->scl_shift_time default of 0xa results in a max tau of 256 
seconds
+*/
+#define PKG_MAX_WIN_DEFAULT 0

Re: [Intel-gfx] [PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-10-03 Thread Andi Shyti
Hi Badal,

> diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
> b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
> index f9d6d3b08bba..19b9fe3ef237 100644
> --- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
> +++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
> @@ -26,6 +26,15 @@ Description:   RO. Card default power limit (default 
> TDP setting).
>  
>   Only supported for particular Intel i915 graphics platforms.
>  
> +What:/sys/devices/.../hwmon/hwmon/power1_max_interval
> +Date:February 2023
> +KernelVersion:   6.2
> +Contact: dri-devel@lists.freedesktop.org

same question here.

> +Description: RW. Sustained power limit interval (Tau in PL1/Tau) in
> + milliseconds over which sustained power is averaged.
> +
> + Only supported for particular Intel i915 graphics platforms.
> +
>  What:/sys/devices/.../hwmon/hwmon/power1_crit
>  Date:February 2023
>  KernelVersion:   6.2
> diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
> b/drivers/gpu/drm/i915/i915_hwmon.c
> index 2394fa789793..641143956c45 100644
> --- a/drivers/gpu/drm/i915/i915_hwmon.c
> +++ b/drivers/gpu/drm/i915/i915_hwmon.c
> @@ -20,11 +20,13 @@
>   * - power  - microwatts
>   * - curr   - milliamperes
>   * - energy - microjoules
> + * - time   - milliseconds
>   */
>  #define SF_VOLTAGE   1000
>  #define SF_POWER 100
>  #define SF_CURR  1000
>  #define SF_ENERGY100
> +#define SF_TIME  1000
>  
>  struct hwm_reg {
>   i915_reg_t gt_perf_status;
> @@ -53,6 +55,7 @@ struct i915_hwmon {
>   struct hwm_reg rg;
>   int scl_shift_power;
>   int scl_shift_energy;
> + int scl_shift_time;
>  };
>  
>  static void
> @@ -161,6 +164,115 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
>   return 0;
>  }
>  
> +static ssize_t
> +hwm_power1_max_interval_show(struct device *dev, struct device_attribute 
> *attr,
> +  char *buf)
> +{
> + struct hwm_drvdata *ddat = dev_get_drvdata(dev);
> + struct i915_hwmon *hwmon = ddat->hwmon;
> + intel_wakeref_t wakeref;
> + u32 r, x, y, x_w = 2; /* 2 bits */
> + u64 tau4, out;
> +
> + with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
> + r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
> +
> + x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
> + y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
> + /*
> +  * tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
> +  * = (4 | x) << (y - 2)
> +  * where (y - 2) ensures a 1.x fixed point representation of 1.x
> +  * However because y can be < 2, we compute
> +  * tau4 = (4 | x) << y
> +  * but add 2 when doing the final right shift to account for units
> +  */
> + tau4 = ((1 << x_w) | x) << y;
> + /* val in hwmon interface units (millisec) */
> + out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
> +
> + return sysfs_emit(buf, "%llu\n", out);
> +}
> +
> +static ssize_t
> +hwm_power1_max_interval_store(struct device *dev,
> +   struct device_attribute *attr,
> +   const char *buf, size_t count)
> +{
> + struct hwm_drvdata *ddat = dev_get_drvdata(dev);
> + struct i915_hwmon *hwmon = ddat->hwmon;
> + long val, max_win, ret;

you have some type mismatch here:

 - val should be unsigned long
 - max_win should be u64
 - ret should be int 

> + u32 x, y, rxy, x_w = 2; /* 2 bits */
> + u64 tau4, r;
> +
> +#define PKG_MAX_WIN_DEFAULT 0x12ull

could you please add a comment here?

> +
> + ret = kstrtoul(buf, 0, &val);
> + if (ret)
> + return ret;
> +
> + /*
> +  * val must be < max in hwmon interface units. The steps below are
> +  * explained in i915_power1_max_interval_show()
> +  */
> + r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
> +
> + x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
> + y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
> + tau4 = ((1 << x_w) | x) << y;
> + max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
> +
> + if (val > max_win)
> + return -EINVAL;
> +
> + /* val in hw units */
> + val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME);
> + /* Convert to 1.x * power(2,y) */
> + if (!val)
> + return -EINVAL;
> + y = ilog2(val);
> + /* x = (val - (1 << y)) >> (y - 2); */

some leftover

> + x = (val - (1ul << y)) << x_w >> y;
> +
> + rxy = REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_X, x) | 
> REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_Y, y);
> +
> + hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit,
> + PKG_PWR_LIM_1_TIME, rxy);
> + return count;
> +}
> +
> +static SENSOR_DEVICE_ATTR(power1_max_interval, 0664,
> +   hwm

Re: [PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-28 Thread Gupta, Anshuman




On 9/27/2022 11:20 AM, Badal Nilawar wrote:

From: Ashutosh Dixit 

Expose power1_max_interval, that is the tau corresponding to PL1, as a
custom hwmon attribute. Some bit manipulation is needed because of the
format of PKG_PWR_LIM_1_TIME in
GT0_PACKAGE_RAPL_LIMIT register (1.x * power(2,y)).

v2: Update date and kernel version in Documentation (Badal)
v3: Cleaned up hwm_power1_max_interval_store() (Badal)
v4:
   - Fixed review comments (Anshuman)
   - In hwm_power1_max_interval_store() get PKG_MAX_WIN from
 pkg_power_sku when it is valid (Ashutosh)
   - KernelVersion: 6.2, Date: February 2023 in doc (Tvrtko)
v5: On some of the DGFX setups it is seen that although pkg_power_sku
 is valid the field PKG_WIN_MAX is not populated. So it is
 decided to stick to default value of PKG_WIN_MAX (Ashutosh)

Signed-off-by: Ashutosh Dixit 
Signed-off-by: Badal Nilawar 
Acked-by: Guenter Roeck 

LGTM,
Reviewed-by: Anshuman Gupta 

---
  .../ABI/testing/sysfs-driver-intel-i915-hwmon |   9 ++
  drivers/gpu/drm/i915/i915_hwmon.c | 115 +-
  drivers/gpu/drm/i915/intel_mchbar_regs.h  |   7 ++
  3 files changed, 130 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
index f9d6d3b08bba..19b9fe3ef237 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
+++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
@@ -26,6 +26,15 @@ Description: RO. Card default power limit (default TDP 
setting).
  
  		Only supported for particular Intel i915 graphics platforms.
  
+What:		/sys/devices/.../hwmon/hwmon/power1_max_interval

+Date:  February 2023
+KernelVersion: 6.2
+Contact:   dri-devel@lists.freedesktop.org
+Description:   RW. Sustained power limit interval (Tau in PL1/Tau) in
+   milliseconds over which sustained power is averaged.
+
+   Only supported for particular Intel i915 graphics platforms.
+
  What: /sys/devices/.../hwmon/hwmon/power1_crit
  Date: February 2023
  KernelVersion:6.2
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
b/drivers/gpu/drm/i915/i915_hwmon.c
index 2394fa789793..641143956c45 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.c
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -20,11 +20,13 @@
   * - power  - microwatts
   * - curr   - milliamperes
   * - energy - microjoules
+ * - time   - milliseconds
   */
  #define SF_VOLTAGE1000
  #define SF_POWER  100
  #define SF_CURR   1000
  #define SF_ENERGY 100
+#define SF_TIME1000
  
  struct hwm_reg {

i915_reg_t gt_perf_status;
@@ -53,6 +55,7 @@ struct i915_hwmon {
struct hwm_reg rg;
int scl_shift_power;
int scl_shift_energy;
+   int scl_shift_time;
  };
  
  static void

@@ -161,6 +164,115 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
return 0;
  }
  
+static ssize_t

+hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   intel_wakeref_t wakeref;
+   u32 r, x, y, x_w = 2; /* 2 bits */
+   u64 tau4, out;
+
+   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+   r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+   x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
+   y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
+   /*
+* tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
+* = (4 | x) << (y - 2)
+* where (y - 2) ensures a 1.x fixed point representation of 1.x
+* However because y can be < 2, we compute
+* tau4 = (4 | x) << y
+* but add 2 when doing the final right shift to account for units
+*/
+   tau4 = ((1 << x_w) | x) << y;
+   /* val in hwmon interface units (millisec) */
+   out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   return sysfs_emit(buf, "%llu\n", out);
+}
+
+static ssize_t
+hwm_power1_max_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   long val, max_win, ret;
+   u32 x, y, rxy, x_w = 2; /* 2 bits */
+   u64 tau4, r;
+
+#define PKG_MAX_WIN_DEFAULT 0x12ull
+
+   ret = kstrtoul(buf, 0, &val);
+   if (ret)
+   return ret;
+
+   /*
+* val must be < max in hwmon interface units. The steps below are
+* explained in i915_power1_max_interval_show()
+*/
+   r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
+
+   x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+   y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+   tau4 = ((1 << x_w) | x

Re: [PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-27 Thread Gupta, Anshuman




On 9/26/2022 11:22 PM, Badal Nilawar wrote:

From: Ashutosh Dixit 

Expose power1_max_interval, that is the tau corresponding to PL1, as a
custom hwmon attribute. Some bit manipulation is needed because of the
format of PKG_PWR_LIM_1_TIME in
GT0_PACKAGE_RAPL_LIMIT register (1.x * power(2,y)).

v2: Update date and kernel version in Documentation (Badal)
v3: Cleaned up hwm_power1_max_interval_store() (Badal)
v4:
   - Fixed review comments (Anshuman)
   - In hwm_power1_max_interval_store() get PKG_MAX_WIN from
 pkg_power_sku when it is valid (Ashutosh)
   - KernelVersion: 6.2, Date: February 2023 in doc (Tvrtko)
v5: On some of the DGFX setups it is seen that although pkg_power_sku
 is valid the field PKG_WIN_MAX is not populated. So it is
 decided to stick to default value of PKG_WIN_MAX (Ashutosh)

Signed-off-by: Ashutosh Dixit 
Signed-off-by: Badal Nilawar 
Acked-by: Guenter Roeck 

LGTM
Reviewed-by: Anshuman Gupta 

---
  .../ABI/testing/sysfs-driver-intel-i915-hwmon |   9 ++
  drivers/gpu/drm/i915/i915_hwmon.c | 115 +-
  drivers/gpu/drm/i915/intel_mchbar_regs.h  |   7 ++
  3 files changed, 130 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
index f9d6d3b08bba..19b9fe3ef237 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
+++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
@@ -26,6 +26,15 @@ Description: RO. Card default power limit (default TDP 
setting).
  
  		Only supported for particular Intel i915 graphics platforms.
  
+What:		/sys/devices/.../hwmon/hwmon/power1_max_interval

+Date:  February 2023
+KernelVersion: 6.2
+Contact:   dri-devel@lists.freedesktop.org
+Description:   RW. Sustained power limit interval (Tau in PL1/Tau) in
+   milliseconds over which sustained power is averaged.
+
+   Only supported for particular Intel i915 graphics platforms.
+
  What: /sys/devices/.../hwmon/hwmon/power1_crit
  Date: February 2023
  KernelVersion:6.2
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
b/drivers/gpu/drm/i915/i915_hwmon.c
index 2394fa789793..641143956c45 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.c
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -20,11 +20,13 @@
   * - power  - microwatts
   * - curr   - milliamperes
   * - energy - microjoules
+ * - time   - milliseconds
   */
  #define SF_VOLTAGE1000
  #define SF_POWER  100
  #define SF_CURR   1000
  #define SF_ENERGY 100
+#define SF_TIME1000
  
  struct hwm_reg {

i915_reg_t gt_perf_status;
@@ -53,6 +55,7 @@ struct i915_hwmon {
struct hwm_reg rg;
int scl_shift_power;
int scl_shift_energy;
+   int scl_shift_time;
  };
  
  static void

@@ -161,6 +164,115 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
return 0;
  }
  
+static ssize_t

+hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   intel_wakeref_t wakeref;
+   u32 r, x, y, x_w = 2; /* 2 bits */
+   u64 tau4, out;
+
+   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+   r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+   x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
+   y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
+   /*
+* tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
+* = (4 | x) << (y - 2)
+* where (y - 2) ensures a 1.x fixed point representation of 1.x
+* However because y can be < 2, we compute
+* tau4 = (4 | x) << y
+* but add 2 when doing the final right shift to account for units
+*/
+   tau4 = ((1 << x_w) | x) << y;
+   /* val in hwmon interface units (millisec) */
+   out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   return sysfs_emit(buf, "%llu\n", out);
+}
+
+static ssize_t
+hwm_power1_max_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   long val, max_win, ret;
+   u32 x, y, rxy, x_w = 2; /* 2 bits */
+   u64 tau4, r;
+
+#define PKG_MAX_WIN_DEFAULT 0x12ull
+
+   ret = kstrtoul(buf, 0, &val);
+   if (ret)
+   return ret;
+
+   /*
+* val must be < max in hwmon interface units. The steps below are
+* explained in i915_power1_max_interval_show()
+*/
+   r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
+
+   x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+   y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+   tau4 = ((1 << x_w) | x)

[PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-26 Thread Badal Nilawar
From: Ashutosh Dixit 

Expose power1_max_interval, that is the tau corresponding to PL1, as a
custom hwmon attribute. Some bit manipulation is needed because of the
format of PKG_PWR_LIM_1_TIME in
GT0_PACKAGE_RAPL_LIMIT register (1.x * power(2,y)).

v2: Update date and kernel version in Documentation (Badal)
v3: Cleaned up hwm_power1_max_interval_store() (Badal)
v4:
  - Fixed review comments (Anshuman)
  - In hwm_power1_max_interval_store() get PKG_MAX_WIN from
pkg_power_sku when it is valid (Ashutosh)
  - KernelVersion: 6.2, Date: February 2023 in doc (Tvrtko)
v5: On some of the DGFX setups it is seen that although pkg_power_sku
is valid the field PKG_WIN_MAX is not populated. So it is
decided to stick to default value of PKG_WIN_MAX (Ashutosh)

Signed-off-by: Ashutosh Dixit 
Signed-off-by: Badal Nilawar 
Acked-by: Guenter Roeck 
---
 .../ABI/testing/sysfs-driver-intel-i915-hwmon |   9 ++
 drivers/gpu/drm/i915/i915_hwmon.c | 115 +-
 drivers/gpu/drm/i915/intel_mchbar_regs.h  |   7 ++
 3 files changed, 130 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
index f9d6d3b08bba..19b9fe3ef237 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
+++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
@@ -26,6 +26,15 @@ Description: RO. Card default power limit (default TDP 
setting).
 
Only supported for particular Intel i915 graphics platforms.
 
+What:  /sys/devices/.../hwmon/hwmon/power1_max_interval
+Date:  February 2023
+KernelVersion: 6.2
+Contact:   dri-devel@lists.freedesktop.org
+Description:   RW. Sustained power limit interval (Tau in PL1/Tau) in
+   milliseconds over which sustained power is averaged.
+
+   Only supported for particular Intel i915 graphics platforms.
+
 What:  /sys/devices/.../hwmon/hwmon/power1_crit
 Date:  February 2023
 KernelVersion: 6.2
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
b/drivers/gpu/drm/i915/i915_hwmon.c
index 2394fa789793..641143956c45 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.c
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -20,11 +20,13 @@
  * - power  - microwatts
  * - curr   - milliamperes
  * - energy - microjoules
+ * - time   - milliseconds
  */
 #define SF_VOLTAGE 1000
 #define SF_POWER   100
 #define SF_CURR1000
 #define SF_ENERGY  100
+#define SF_TIME1000
 
 struct hwm_reg {
i915_reg_t gt_perf_status;
@@ -53,6 +55,7 @@ struct i915_hwmon {
struct hwm_reg rg;
int scl_shift_power;
int scl_shift_energy;
+   int scl_shift_time;
 };
 
 static void
@@ -161,6 +164,115 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
return 0;
 }
 
+static ssize_t
+hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   intel_wakeref_t wakeref;
+   u32 r, x, y, x_w = 2; /* 2 bits */
+   u64 tau4, out;
+
+   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+   r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+   x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
+   y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
+   /*
+* tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
+* = (4 | x) << (y - 2)
+* where (y - 2) ensures a 1.x fixed point representation of 1.x
+* However because y can be < 2, we compute
+* tau4 = (4 | x) << y
+* but add 2 when doing the final right shift to account for units
+*/
+   tau4 = ((1 << x_w) | x) << y;
+   /* val in hwmon interface units (millisec) */
+   out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   return sysfs_emit(buf, "%llu\n", out);
+}
+
+static ssize_t
+hwm_power1_max_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   long val, max_win, ret;
+   u32 x, y, rxy, x_w = 2; /* 2 bits */
+   u64 tau4, r;
+
+#define PKG_MAX_WIN_DEFAULT 0x12ull
+
+   ret = kstrtoul(buf, 0, &val);
+   if (ret)
+   return ret;
+
+   /*
+* val must be < max in hwmon interface units. The steps below are
+* explained in i915_power1_max_interval_show()
+*/
+   r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
+
+   x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+   y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+   tau4 = ((1 << x_w) | x) << y;
+   max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   if (

[PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-26 Thread Badal Nilawar
From: Ashutosh Dixit 

Expose power1_max_interval, that is the tau corresponding to PL1, as a
custom hwmon attribute. Some bit manipulation is needed because of the
format of PKG_PWR_LIM_1_TIME in
GT0_PACKAGE_RAPL_LIMIT register (1.x * power(2,y)).

v2: Update date and kernel version in Documentation (Badal)
v3: Cleaned up hwm_power1_max_interval_store() (Badal)
v4:
  - Fixed review comments (Anshuman)
  - In hwm_power1_max_interval_store() get PKG_MAX_WIN from
pkg_power_sku when it is valid (Ashutosh)
  - KernelVersion: 6.2, Date: February 2023 in doc (Tvrtko)
v5: On some of the DGFX setups it is seen that although pkg_power_sku
is valid the field PKG_WIN_MAX is not populated. So it is
decided to stick to default value of PKG_WIN_MAX (Ashutosh)

Signed-off-by: Ashutosh Dixit 
Signed-off-by: Badal Nilawar 
Acked-by: Guenter Roeck 
---
 .../ABI/testing/sysfs-driver-intel-i915-hwmon |   9 ++
 drivers/gpu/drm/i915/i915_hwmon.c | 115 +-
 drivers/gpu/drm/i915/intel_mchbar_regs.h  |   7 ++
 3 files changed, 130 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
index f9d6d3b08bba..19b9fe3ef237 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
+++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
@@ -26,6 +26,15 @@ Description: RO. Card default power limit (default TDP 
setting).
 
Only supported for particular Intel i915 graphics platforms.
 
+What:  /sys/devices/.../hwmon/hwmon/power1_max_interval
+Date:  February 2023
+KernelVersion: 6.2
+Contact:   dri-devel@lists.freedesktop.org
+Description:   RW. Sustained power limit interval (Tau in PL1/Tau) in
+   milliseconds over which sustained power is averaged.
+
+   Only supported for particular Intel i915 graphics platforms.
+
 What:  /sys/devices/.../hwmon/hwmon/power1_crit
 Date:  February 2023
 KernelVersion: 6.2
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
b/drivers/gpu/drm/i915/i915_hwmon.c
index 2394fa789793..641143956c45 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.c
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -20,11 +20,13 @@
  * - power  - microwatts
  * - curr   - milliamperes
  * - energy - microjoules
+ * - time   - milliseconds
  */
 #define SF_VOLTAGE 1000
 #define SF_POWER   100
 #define SF_CURR1000
 #define SF_ENERGY  100
+#define SF_TIME1000
 
 struct hwm_reg {
i915_reg_t gt_perf_status;
@@ -53,6 +55,7 @@ struct i915_hwmon {
struct hwm_reg rg;
int scl_shift_power;
int scl_shift_energy;
+   int scl_shift_time;
 };
 
 static void
@@ -161,6 +164,115 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
return 0;
 }
 
+static ssize_t
+hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   intel_wakeref_t wakeref;
+   u32 r, x, y, x_w = 2; /* 2 bits */
+   u64 tau4, out;
+
+   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+   r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+   x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
+   y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
+   /*
+* tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
+* = (4 | x) << (y - 2)
+* where (y - 2) ensures a 1.x fixed point representation of 1.x
+* However because y can be < 2, we compute
+* tau4 = (4 | x) << y
+* but add 2 when doing the final right shift to account for units
+*/
+   tau4 = ((1 << x_w) | x) << y;
+   /* val in hwmon interface units (millisec) */
+   out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   return sysfs_emit(buf, "%llu\n", out);
+}
+
+static ssize_t
+hwm_power1_max_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   long val, max_win, ret;
+   u32 x, y, rxy, x_w = 2; /* 2 bits */
+   u64 tau4, r;
+
+#define PKG_MAX_WIN_DEFAULT 0x12ull
+
+   ret = kstrtoul(buf, 0, &val);
+   if (ret)
+   return ret;
+
+   /*
+* val must be < max in hwmon interface units. The steps below are
+* explained in i915_power1_max_interval_show()
+*/
+   r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
+
+   x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+   y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+   tau4 = ((1 << x_w) | x) << y;
+   max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   if (

Re: [PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-23 Thread Dixit, Ashutosh
On Fri, 23 Sep 2022 12:56:42 -0700, Badal Nilawar wrote:
>
> From: Ashutosh Dixit 
>
> Expose power1_max_interval, that is the tau corresponding to PL1.

I think let's change the above sentence to: "Expose power1_max_interval,
that is the tau corresponding to PL1, as a custom hwmon attribute".

This is the only custom attribute we are exposing so better to mention this
in the commit message I think.

Thanks.
--
Ashutosh


[PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-23 Thread Badal Nilawar
From: Ashutosh Dixit 

Expose power1_max_interval, that is the tau corresponding to PL1. Some bit
manipulation is needed because of the format of PKG_PWR_LIM_1_TIME in
GT0_PACKAGE_RAPL_LIMIT register (1.x * power(2,y)).

v2: Update date and kernel version in Documentation (Badal)
v3: Cleaned up hwm_power1_max_interval_store() (Badal)
v4:
  - Fixed review comments (Anshuman)
  - In hwm_power1_max_interval_store() get PKG_MAX_WIN from
pkg_power_sku when it is valid (Ashutosh)
  - KernelVersion: 6.2, Date: February 2023 in doc (Tvrtko)

Signed-off-by: Ashutosh Dixit 
Signed-off-by: Badal Nilawar 
Acked-by: Guenter Roeck 
---
 .../ABI/testing/sysfs-driver-intel-i915-hwmon |   9 ++
 drivers/gpu/drm/i915/i915_hwmon.c | 120 +-
 drivers/gpu/drm/i915/intel_mchbar_regs.h  |   7 +
 3 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
index f9d6d3b08bba..19b9fe3ef237 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
+++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
@@ -26,6 +26,15 @@ Description: RO. Card default power limit (default TDP 
setting).
 
Only supported for particular Intel i915 graphics platforms.
 
+What:  /sys/devices/.../hwmon/hwmon/power1_max_interval
+Date:  February 2023
+KernelVersion: 6.2
+Contact:   dri-devel@lists.freedesktop.org
+Description:   RW. Sustained power limit interval (Tau in PL1/Tau) in
+   milliseconds over which sustained power is averaged.
+
+   Only supported for particular Intel i915 graphics platforms.
+
 What:  /sys/devices/.../hwmon/hwmon/power1_crit
 Date:  February 2023
 KernelVersion: 6.2
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
b/drivers/gpu/drm/i915/i915_hwmon.c
index f743ac5c59c4..b95f54d274be 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.c
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -20,11 +20,13 @@
  * - power  - microwatts
  * - curr   - milliamperes
  * - energy - microjoules
+ * - time   - milliseconds
  */
 #define SF_VOLTAGE 1000
 #define SF_POWER   100
 #define SF_CURR1000
 #define SF_ENERGY  100
+#define SF_TIME1000
 
 struct hwm_reg {
i915_reg_t gt_perf_status;
@@ -53,6 +55,7 @@ struct i915_hwmon {
struct hwm_reg rg;
int scl_shift_power;
int scl_shift_energy;
+   int scl_shift_time;
 };
 
 static void
@@ -161,6 +164,120 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
return 0;
 }
 
+static ssize_t
+hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   intel_wakeref_t wakeref;
+   u32 r, x, y, x_w = 2; /* 2 bits */
+   u64 tau4, out;
+
+   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+   r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+   x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
+   y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
+   /*
+* tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
+* = (4 | x) << (y - 2)
+* where (y - 2) ensures a 1.x fixed point representation of 1.x
+* However because y can be < 2, we compute
+* tau4 = (4 | x) << y
+* but add 2 when doing the final right shift to account for units
+*/
+   tau4 = ((1 << x_w) | x) << y;
+   /* val in hwmon interface units (millisec) */
+   out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   return sysfs_emit(buf, "%llu\n", out);
+}
+
+static ssize_t
+hwm_power1_max_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   intel_wakeref_t wakeref;
+   long val, max_win, ret;
+   u32 x, y, rxy, x_w = 2; /* 2 bits */
+   u64 tau4, r;
+
+#define PKG_MAX_WIN_DEFAULT 0x12ull
+
+   ret = kstrtoul(buf, 0, &val);
+   if (ret)
+   return ret;
+
+   /*
+* val must be < max in hwmon interface units. The steps below are
+* explained in i915_power1_max_interval_show()
+*/
+   if (i915_mmio_reg_valid(hwmon->rg.pkg_power_sku))
+   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+   r = intel_uncore_read64(ddat->uncore, 
hwmon->rg.pkg_power_sku);
+   else
+   r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
+
+   x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+   y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+   tau4 = ((1 << x_w) | x) << y;
+   max_win = mul_u64_u32_shr(tau4, SF_TIME, hwm

Re: [PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-22 Thread Dixit, Ashutosh
On Thu, 22 Sep 2022 19:51:45 -0700, Dixit, Ashutosh wrote:
>
> On Thu, 22 Sep 2022 00:13:00 -0700, Gupta, Anshuman wrote:
> >
>
> Hi Anshuman,
>
> > > +static ssize_t
> > > +hwm_power1_max_interval_store(struct device *dev,
> > > +   struct device_attribute *attr,
> > > +   const char *buf, size_t count)
> > > +{
> > > + struct hwm_drvdata *ddat = dev_get_drvdata(dev);
> > > + struct i915_hwmon *hwmon = ddat->hwmon;
> > > + long val, max_win, ret;
> > > + u32 x, y, rxy, x_w = 2; /* 2 bits */
> > > + u64 tau4, r;
> > > +
> > > +#define PKG_MAX_WIN_DEFAULT 0x12ull
> > > +
> > > + ret = kstrtoul(buf, 0, &val);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + /*
> > > +  * val must be < max in hwmon interface units. The steps below are
> > > +  * explained in i915_power1_max_interval_show()
> > > +  */
> > > + r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
> >
> > AFAIU we need to read r from PACKAGE_POWER_SKU reg untill unless it has
> > some known issue?
>
> The platform on which I tried had an incorrect value (that is why I didn't
> read it from PACKAGE_POWER_SKU) but let me investigate it some more for
> other platforms and get back.

I checked, the value is correct on DG1/DG2 which have a valid
PACKAGE_POWER_SKU (XEHPSDV does not have a valid
PACKAGE_POWER_SKU). Therefore the one line above should be replaced with
the code below:

if (i915_mmio_reg_valid(hwmon->rg.pkg_power_sku))
with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
r = intel_uncore_read64(ddat->uncore, 
hwmon->rg.pkg_power_sku);
else
r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);

> > > + x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
> > > + y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
> > > + tau4 = ((1 << x_w) | x) << y;
> > > + max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
> > > +
> > > + if (val > max_win)
> > > + return -EINVAL;
> > > +
> > > + /* val in hw units */
> > > + val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME);
> > > + /* Convert to 1.x * power(2,y) */
> > > + if (!val)
> > > + return -EINVAL;
> > > + y = ilog2(val);
> > > + /* x = (val - (1 << y)) >> (y - 2); */
> > > + x = (val - (1ul << y)) << x_w >> y;
> > > +
> > > + rxy = REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_X, x) | 
> > > REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_Y, y);
> > > +
> > > + hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit,
> > > + PKG_PWR_LIM_1_TIME, rxy);
> > > + return count;
> > > +}
> > > +
> > /snip
> > >   if (IS_ERR(hwmon_dev)) {
> > >   mutex_destroy(&hwmon->hwmon_lock);
> > >   i915->hwmon = NULL;
> > > diff --git a/drivers/gpu/drm/i915/i915_reg.h 
> > > b/drivers/gpu/drm/i915/i915_reg.h
> > > index 956e5298ef1e..68e7cc85dc53 100644
> > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > @@ -1811,6 +1811,9 @@
> > >* *_PACKAGE_POWER_SKU - SKU power and timing parameters.
> > >*/
> > >   #define   PKG_PKG_TDP   GENMASK_ULL(14, 0)
> > > +#define   PKG_MAX_WINGENMASK_ULL(54, 48)
> > > +#define PKG_MAX_WIN_XGENMASK_ULL(54, 53)
> > > +#define PKG_MAX_WIN_YGENMASK_ULL(52, 48)
> > These GENMASK fields needs a reg definition.
>
> Yes this is the same _PACKAGE_POWER_SKU register so should get fixed when
> we add it in Patch 3.

Looks like PCU_PACKAGE_POWER_SKU for DG1/DG2 will need to be declared in
intel_mchbar_regs.h so these fields will need to also move there (in
Patch 3).

Thanks.
--
Ashutosh


Re: [PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-22 Thread Dixit, Ashutosh
On Thu, 22 Sep 2022 00:13:00 -0700, Gupta, Anshuman wrote:
>

Hi Anshuman,

> > +static ssize_t
> > +hwm_power1_max_interval_store(struct device *dev,
> > + struct device_attribute *attr,
> > + const char *buf, size_t count)
> > +{
> > +   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
> > +   struct i915_hwmon *hwmon = ddat->hwmon;
> > +   long val, max_win, ret;
> > +   u32 x, y, rxy, x_w = 2; /* 2 bits */
> > +   u64 tau4, r;
> > +
> > +#define PKG_MAX_WIN_DEFAULT 0x12ull
> > +
> > +   ret = kstrtoul(buf, 0, &val);
> > +   if (ret)
> > +   return ret;
> > +
> > +   /*
> > +* val must be < max in hwmon interface units. The steps below are
> > +* explained in i915_power1_max_interval_show()
> > +*/
> > +   r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
>
> AFAIU we need to read r from PACKAGE_POWER_SKU reg untill unless it has
> some known issue?

The platform on which I tried had an incorrect value (that is why I didn't
read it from PACKAGE_POWER_SKU) but let me investigate it some more for
other platforms and get back.

> > +   x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
> > +   y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
> > +   tau4 = ((1 << x_w) | x) << y;
> > +   max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
> > +
> > +   if (val > max_win)
> > +   return -EINVAL;
> > +
> > +   /* val in hw units */
> > +   val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME);
> > +   /* Convert to 1.x * power(2,y) */
> > +   if (!val)
> > +   return -EINVAL;
> > +   y = ilog2(val);
> > +   /* x = (val - (1 << y)) >> (y - 2); */
> > +   x = (val - (1ul << y)) << x_w >> y;
> > +
> > +   rxy = REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_X, x) | 
> > REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_Y, y);
> > +
> > +   hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit,
> > +   PKG_PWR_LIM_1_TIME, rxy);
> > +   return count;
> > +}
> > +
> /snip
> > if (IS_ERR(hwmon_dev)) {
> > mutex_destroy(&hwmon->hwmon_lock);
> > i915->hwmon = NULL;
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h 
> > b/drivers/gpu/drm/i915/i915_reg.h
> > index 956e5298ef1e..68e7cc85dc53 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -1811,6 +1811,9 @@
> >* *_PACKAGE_POWER_SKU - SKU power and timing parameters.
> >*/
> >   #define   PKG_PKG_TDP GENMASK_ULL(14, 0)
> > +#define   PKG_MAX_WIN  GENMASK_ULL(54, 48)
> > +#define PKG_MAX_WIN_X  GENMASK_ULL(54, 53)
> > +#define PKG_MAX_WIN_Y  GENMASK_ULL(52, 48)
> These GENMASK fields needs a reg definition.

Yes this is the same _PACKAGE_POWER_SKU register so should get fixed when
we add it in Patch 3.

Thanks.
--
Ashutosh


Re: [PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-22 Thread Gupta, Anshuman




On 9/16/2022 8:30 PM, Badal Nilawar wrote:

From: Ashutosh Dixit 

Expose power1_max_interval, that is the tau corresponding to PL1. Some bit
manipulation is needed because of the format of PKG_PWR_LIM_1_TIME in
GT0_PACKAGE_RAPL_LIMIT register (1.x * power(2,y)).

v2: Update date and kernel version in Documentation (Badal)
v3: Cleaned up hwm_power1_max_interval_store() (Badal)

Signed-off-by: Ashutosh Dixit 
Signed-off-by: Badal Nilawar 
Acked-by: Guenter Roeck 
---
  .../ABI/testing/sysfs-driver-intel-i915-hwmon |   9 ++
  drivers/gpu/drm/i915/i915_hwmon.c | 114 +-
  drivers/gpu/drm/i915/i915_reg.h   |   3 +
  drivers/gpu/drm/i915/intel_mchbar_regs.h  |   4 +
  4 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
index cc70596fff44..7995a885c9d6 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
+++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
@@ -26,6 +26,15 @@ Description: RO. Card default power limit (default TDP 
setting).
  
  		Only supported for particular Intel i915 graphics platforms.
  
+What:		/sys/devices/.../hwmon/hwmon/power1_max_interval

+Date:  September 2022
+KernelVersion: 6
+Contact:   dri-devel@lists.freedesktop.org
+Description:   RW. Sustained power limit interval (Tau in PL1/Tau) in
+   milliseconds over which sustained power is averaged.
+
+   Only supported for particular Intel i915 graphics platforms.
+
  What: /sys/devices/.../hwmon/hwmon/power1_crit
  Date: September 2022
  KernelVersion:6
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
b/drivers/gpu/drm/i915/i915_hwmon.c
index bd9ba312c474..7d85a81bc39b 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.c
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -20,11 +20,13 @@
   * - power  - microwatts
   * - curr   - milliamperes
   * - energy - microjoules
+ * - time   - milliseconds
   */
  #define SF_VOLTAGE1000
  #define SF_POWER  100
  #define SF_CURR   1000
  #define SF_ENERGY 100
+#define SF_TIME1000
  
  struct hwm_reg {

i915_reg_t gt_perf_status;
@@ -53,6 +55,7 @@ struct i915_hwmon {
struct hwm_reg rg;
int scl_shift_power;
int scl_shift_energy;
+   int scl_shift_time;
  };
  
  static void

@@ -161,6 +164,114 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
return 0;
  }
  
+static ssize_t

+hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   intel_wakeref_t wakeref;
+   u32 r, x, y, x_w = 2; /* 2 bits */
+   u64 tau4, out;
+
+   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+   r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+   x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
+   y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
+   /*
+* tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
+* = (4 | x) << (y - 2)
+* where (y - 2) ensures a 1.x fixed point representation of 1.x
+* However because y can be < 2, we compute
+* tau4 = (4 | x) << y
+* but add 2 when doing the final right shift to account for units
+*/
+   tau4 = ((1 << x_w) | x) << y;
+   /* val in hwmon interface units (millisec) */
+   out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   return sysfs_emit(buf, "%llu\n", out);
+}
+
+static ssize_t
+hwm_power1_max_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   long val, max_win, ret;
+   u32 x, y, rxy, x_w = 2; /* 2 bits */
+   u64 tau4, r;
+
+#define PKG_MAX_WIN_DEFAULT 0x12ull
+
+   ret = kstrtoul(buf, 0, &val);
+   if (ret)
+   return ret;
+
+   /*
+* val must be < max in hwmon interface units. The steps below are
+* explained in i915_power1_max_interval_show()
+*/
+   r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
AFAIU we need to read r from PACKAGE_POWER_SKU reg untill unless it has 
some known issue?

+   x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+   y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+   tau4 = ((1 << x_w) | x) << y;
+   max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   if (val > max_win)
+   return -EINVAL;
+
+   /* val in hw units */
+   val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME);
+   /* Convert to 1.x * power(2,y) */
+   if (!val)
+   

[PATCH 6/7] drm/i915/hwmon: Expose power1_max_interval

2022-09-16 Thread Badal Nilawar
From: Ashutosh Dixit 

Expose power1_max_interval, that is the tau corresponding to PL1. Some bit
manipulation is needed because of the format of PKG_PWR_LIM_1_TIME in
GT0_PACKAGE_RAPL_LIMIT register (1.x * power(2,y)).

v2: Update date and kernel version in Documentation (Badal)
v3: Cleaned up hwm_power1_max_interval_store() (Badal)

Signed-off-by: Ashutosh Dixit 
Signed-off-by: Badal Nilawar 
Acked-by: Guenter Roeck 
---
 .../ABI/testing/sysfs-driver-intel-i915-hwmon |   9 ++
 drivers/gpu/drm/i915/i915_hwmon.c | 114 +-
 drivers/gpu/drm/i915/i915_reg.h   |   3 +
 drivers/gpu/drm/i915/intel_mchbar_regs.h  |   4 +
 4 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon 
b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
index cc70596fff44..7995a885c9d6 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
+++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
@@ -26,6 +26,15 @@ Description: RO. Card default power limit (default TDP 
setting).
 
Only supported for particular Intel i915 graphics platforms.
 
+What:  /sys/devices/.../hwmon/hwmon/power1_max_interval
+Date:  September 2022
+KernelVersion: 6
+Contact:   dri-devel@lists.freedesktop.org
+Description:   RW. Sustained power limit interval (Tau in PL1/Tau) in
+   milliseconds over which sustained power is averaged.
+
+   Only supported for particular Intel i915 graphics platforms.
+
 What:  /sys/devices/.../hwmon/hwmon/power1_crit
 Date:  September 2022
 KernelVersion: 6
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c 
b/drivers/gpu/drm/i915/i915_hwmon.c
index bd9ba312c474..7d85a81bc39b 100644
--- a/drivers/gpu/drm/i915/i915_hwmon.c
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -20,11 +20,13 @@
  * - power  - microwatts
  * - curr   - milliamperes
  * - energy - microjoules
+ * - time   - milliseconds
  */
 #define SF_VOLTAGE 1000
 #define SF_POWER   100
 #define SF_CURR1000
 #define SF_ENERGY  100
+#define SF_TIME1000
 
 struct hwm_reg {
i915_reg_t gt_perf_status;
@@ -53,6 +55,7 @@ struct i915_hwmon {
struct hwm_reg rg;
int scl_shift_power;
int scl_shift_energy;
+   int scl_shift_time;
 };
 
 static void
@@ -161,6 +164,114 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
return 0;
 }
 
+static ssize_t
+hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   intel_wakeref_t wakeref;
+   u32 r, x, y, x_w = 2; /* 2 bits */
+   u64 tau4, out;
+
+   with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+   r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+   x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
+   y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
+   /*
+* tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
+* = (4 | x) << (y - 2)
+* where (y - 2) ensures a 1.x fixed point representation of 1.x
+* However because y can be < 2, we compute
+* tau4 = (4 | x) << y
+* but add 2 when doing the final right shift to account for units
+*/
+   tau4 = ((1 << x_w) | x) << y;
+   /* val in hwmon interface units (millisec) */
+   out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   return sysfs_emit(buf, "%llu\n", out);
+}
+
+static ssize_t
+hwm_power1_max_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+   struct i915_hwmon *hwmon = ddat->hwmon;
+   long val, max_win, ret;
+   u32 x, y, rxy, x_w = 2; /* 2 bits */
+   u64 tau4, r;
+
+#define PKG_MAX_WIN_DEFAULT 0x12ull
+
+   ret = kstrtoul(buf, 0, &val);
+   if (ret)
+   return ret;
+
+   /*
+* val must be < max in hwmon interface units. The steps below are
+* explained in i915_power1_max_interval_show()
+*/
+   r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
+   x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+   y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+   tau4 = ((1 << x_w) | x) << y;
+   max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+   if (val > max_win)
+   return -EINVAL;
+
+   /* val in hw units */
+   val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME);
+   /* Convert to 1.x * power(2,y) */
+   if (!val)
+   return -EINVAL;
+   y = ilog2(val);
+   /* x = (val - (1 << y)) >> (y - 2); */
+   x = (val - (1ul << y)) << x_w >> y;
+
+   rxy =