From: "Poosa, Karthik" <karthik.poosa@intel.com>
To: Raag Jadav <raag.jadav@intel.com>, <lucas.demarchi@intel.com>,
<rodrigo.vivi@intel.com>, <matthew.d.roper@intel.com>,
<andi.shyti@linux.intel.com>
Cc: <intel-xe@lists.freedesktop.org>, <anshuman.gupta@intel.com>,
<riana.tauro@intel.com>, <badal.nilawar@intel.com>
Subject: Re: [PATCH v1] drm/xe/hwmon: expose fan speed
Date: Fri, 21 Feb 2025 20:32:01 +0530 [thread overview]
Message-ID: <bbda9792-7126-4961-8767-b435780f0cff@intel.com> (raw)
In-Reply-To: <20250210100515.2205584-1-raag.jadav@intel.com>
On 10-02-2025 15:35, Raag Jadav wrote:
> Add hwmon support for fan1_input, fan2_input and fan3_input attributes,
> which will expose fan speed of respective channels in RPM when supported
> by hardware. With this in place we can monitor fan speed using lm-sensors
> tool.
>
> Signed-off-by: Raag Jadav <raag.jadav@intel.com>
> ---
> .../ABI/testing/sysfs-driver-intel-xe-hwmon | 24 ++++
> drivers/gpu/drm/xe/regs/xe_pcode_regs.h | 3 +
> drivers/gpu/drm/xe/xe_hwmon.c | 124 +++++++++++++++++-
> drivers/gpu/drm/xe/xe_pcode_api.h | 3 +
> 4 files changed, 153 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon
> index 9bce281314df..adbb9bce15a5 100644
> --- a/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon
> +++ b/Documentation/ABI/testing/sysfs-driver-intel-xe-hwmon
> @@ -124,3 +124,27 @@ Contact: intel-xe@lists.freedesktop.org
> Description: RO. VRAM temperature in millidegree Celsius.
>
> Only supported for particular Intel Xe graphics platforms.
> +
> +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/fan1_input
> +Date: March 2025
> +KernelVersion: 6.14
> +Contact: intel-xe@lists.freedesktop.org
> +Description: RO. Fan 1 speed in RPM.
> +
> + Only supported for particular Intel Xe graphics platforms.
> +
> +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/fan2_input
> +Date: March 2025
> +KernelVersion: 6.14
> +Contact: intel-xe@lists.freedesktop.org
> +Description: RO. Fan 2 speed in RPM.
> +
> + Only supported for particular Intel Xe graphics platforms.
> +
> +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/fan3_input
> +Date: March 2025
> +KernelVersion: 6.14
> +Contact: intel-xe@lists.freedesktop.org
> +Description: RO. Fan 3 speed in RPM.
> +
> + Only supported for particular Intel Xe graphics platforms.
> diff --git a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h
> index 8846eb9ce2a4..c7d5d782e3f9 100644
> --- a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h
> @@ -21,6 +21,9 @@
> #define BMG_PACKAGE_POWER_SKU XE_REG(0x138098)
> #define BMG_PACKAGE_POWER_SKU_UNIT XE_REG(0x1380dc)
> #define BMG_PACKAGE_ENERGY_STATUS XE_REG(0x138120)
> +#define BMG_FAN_1_SPEED XE_REG(0x138140)
> +#define BMG_FAN_2_SPEED XE_REG(0x138170)
> +#define BMG_FAN_3_SPEED XE_REG(0x1381a0)
Can you rename macros without having platform names, as this register is
available for both DG2 and BMG, like FAN_1_SPEED.
> #define BMG_VRAM_TEMPERATURE XE_REG(0x1382c0)
> #define BMG_PACKAGE_TEMPERATURE XE_REG(0x138434)
> #define BMG_PACKAGE_RAPL_LIMIT XE_REG(0x138440)
> diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c
> index 7f327e334212..f1f95655d9fb 100644
> --- a/drivers/gpu/drm/xe/xe_hwmon.c
> +++ b/drivers/gpu/drm/xe/xe_hwmon.c
> @@ -5,6 +5,7 @@
>
> #include <linux/hwmon-sysfs.h>
> #include <linux/hwmon.h>
> +#include <linux/jiffies.h>
> #include <linux/types.h>
> #include <linux/units.h>
>
> @@ -27,6 +28,7 @@ enum xe_hwmon_reg {
> REG_PKG_POWER_SKU_UNIT,
> REG_GT_PERF_STATUS,
> REG_PKG_ENERGY_STATUS,
> + REG_FAN_SPEED,
> };
>
> enum xe_hwmon_reg_operation {
> @@ -42,6 +44,13 @@ enum xe_hwmon_channel {
> CHANNEL_MAX,
> };
>
> +enum xe_fan_channel {
> + FAN_1,
> + FAN_2,
> + FAN_3,
> + FAN_MAX,
> +};
> +
> /*
> * SF_* - scale factors for particular quantities according to hwmon spec.
> */
> @@ -61,6 +70,16 @@ struct xe_hwmon_energy_info {
> long accum_energy;
> };
>
> +/**
> + * struct xe_hwmon_fan_info - to cache previous fan reading
> + */
> +struct xe_hwmon_fan_info {
> + /** @reg_val_prev: previous fan reg val */
> + u32 reg_val_prev;
> + /** @time_prev: previous timestamp */
> + u64 time_prev;
> +};
> +
> /**
> * struct xe_hwmon - xe hwmon data structure
> */
> @@ -79,6 +98,8 @@ struct xe_hwmon {
> int scl_shift_time;
> /** @ei: Energy info for energyN_input */
> struct xe_hwmon_energy_info ei[CHANNEL_MAX];
> + /** @fi: Fan info for fanN_input */
> + struct xe_hwmon_fan_info fi[FAN_MAX];
> };
>
> static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg hwmon_reg,
> @@ -144,6 +165,16 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg
> return PCU_CR_PACKAGE_ENERGY_STATUS;
> }
> break;
> + case REG_FAN_SPEED:
> + if (xe->info.platform == XE_BATTLEMAGE || xe->info.platform == XE_DG2) {
> + if (channel == FAN_1)
> + return BMG_FAN_1_SPEED;
> + else if (channel == FAN_2)
> + return BMG_FAN_2_SPEED;
> + else if (channel == FAN_3)
> + return BMG_FAN_3_SPEED;
> + }
> + break;
> default:
> drm_warn(&xe->drm, "Unknown xe hwmon reg id: %d\n", hwmon_reg);
> break;
> @@ -454,6 +485,7 @@ static const struct hwmon_channel_info * const hwmon_info[] = {
> HWMON_CHANNEL_INFO(curr, HWMON_C_LABEL, HWMON_C_CRIT | HWMON_C_LABEL),
> HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL),
> HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT | HWMON_E_LABEL, HWMON_E_INPUT | HWMON_E_LABEL),
> + HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT, HWMON_F_INPUT),
> NULL
> };
>
> @@ -480,6 +512,14 @@ static int xe_hwmon_pcode_write_i1(const struct xe_hwmon *hwmon, u32 uval)
> (uval & POWER_SETUP_I1_DATA_MASK));
> }
>
> +static int xe_hwmon_pcode_read_num_fans(const struct xe_hwmon *hwmon, u32 *uval)
> +{
> + struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe);
> +
> + return xe_pcode_read(root_tile, PCODE_MBOX(FAN_SPEED_CONTROL,
> + FSC_READ_NUM_FANS, 0), uval, NULL);
> +}
> +
> static int xe_hwmon_power_curr_crit_read(struct xe_hwmon *hwmon, int channel,
> long *value, u32 scale_factor)
> {
> @@ -705,6 +745,77 @@ xe_hwmon_energy_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val)
> }
> }
>
> +static umode_t
> +xe_hwmon_fan_is_visible(struct xe_hwmon *hwmon, u32 attr, int channel)
> +{
> + struct xe_device *xe = hwmon->xe;
> + u32 uval;
> +
> + switch (attr) {
> + case hwmon_fan_input:
> + if (xe_hwmon_pcode_read_num_fans(hwmon, &uval))
> + return 0;
> +
> + /* Platforms that don't return correct value */
This can be rephrased to - "Platforms that don't support fan pcode
mailbox cmds"
> + if (xe->info.platform == XE_DG2)
> + uval = 2;
> +
> + return channel < uval ? 0444 : 0;
> + default:
> + return 0;
> + }
> +}
> +
> +static int
> +xe_hwmon_fan_input_read(struct xe_hwmon *hwmon, int channel, long *val)
> +{
> + struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe);
> + struct xe_hwmon_fan_info *fi = &hwmon->fi[channel];
> + u64 rotations, time_now, time;
> + u32 reg_val;
> + int ret = 0;
> +
> + mutex_lock(&hwmon->hwmon_lock);
> +
> + reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_FAN_SPEED, channel));
> + time_now = get_jiffies_64();
> +
> + /*
> + * HW register value is accumulated count of pulses from PWM fan with the scale
> + * of 2 pulses per rotation.
> + */
> + rotations = (reg_val - fi->reg_val_prev) / 2;
> +
> + time = jiffies_delta_to_msecs(time_now - fi->time_prev);
> + if (unlikely(!time)) {
> + ret = -EAGAIN;
> + goto unlock;
> + }
> +
> + /*
> + * Calculate fan speed in RPM by time averaging two subsequent readings in minutes.
> + * RPM = number of rotations * msecs per minute / time in msecs
> + */
> + *val = DIV_ROUND_UP_ULL(rotations * (MSEC_PER_SEC * 60), time);
> +
> + fi->reg_val_prev = reg_val;
> + fi->time_prev = time_now;
> +unlock:
> + mutex_unlock(&hwmon->hwmon_lock);
> + return ret;
> +}
> +
> +static int
> +xe_hwmon_fan_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *val)
> +{
> + switch (attr) {
> + case hwmon_fan_input:
> + return xe_hwmon_fan_input_read(hwmon, channel, val);
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> static umode_t
> xe_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
> u32 attr, int channel)
> @@ -730,6 +841,9 @@ xe_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
> case hwmon_energy:
> ret = xe_hwmon_energy_is_visible(hwmon, attr, channel);
> break;
> + case hwmon_fan:
> + ret = xe_hwmon_fan_is_visible(hwmon, attr, channel);
> + break;
> default:
> ret = 0;
> break;
> @@ -765,6 +879,9 @@ xe_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
> case hwmon_energy:
> ret = xe_hwmon_energy_read(hwmon, attr, channel, val);
> break;
> + case hwmon_fan:
> + ret = xe_hwmon_fan_read(hwmon, attr, channel, val);
> + break;
> default:
> ret = -EOPNOTSUPP;
> break;
> @@ -843,7 +960,7 @@ xe_hwmon_get_preregistration_info(struct xe_device *xe)
> {
> struct xe_mmio *mmio = xe_root_tile_mmio(xe);
> struct xe_hwmon *hwmon = xe->hwmon;
> - long energy;
> + long energy, fan_speed;
> u64 val_sku_unit = 0;
> int channel;
> struct xe_reg pkg_power_sku_unit;
> @@ -867,6 +984,11 @@ xe_hwmon_get_preregistration_info(struct xe_device *xe)
> for (channel = 0; channel < CHANNEL_MAX; channel++)
> if (xe_hwmon_is_visible(hwmon, hwmon_energy, hwmon_energy_input, channel))
> xe_hwmon_energy_get(hwmon, channel, &energy);
> +
> + /* Initialize 'struct xe_hwmon_fan_info' with initial fan register reading. */
> + for (channel = 0; channel < FAN_MAX; channel++)
> + if (xe_hwmon_is_visible(hwmon, hwmon_fan, hwmon_fan_input, channel))
> + xe_hwmon_fan_input_read(hwmon, channel, &fan_speed);
> }
>
> static void xe_hwmon_mutex_destroy(void *arg)
> diff --git a/drivers/gpu/drm/xe/xe_pcode_api.h b/drivers/gpu/drm/xe/xe_pcode_api.h
> index 2bae9afdbd35..e622ae17f08d 100644
> --- a/drivers/gpu/drm/xe/xe_pcode_api.h
> +++ b/drivers/gpu/drm/xe/xe_pcode_api.h
> @@ -49,6 +49,9 @@
> /* Domain IDs (param2) */
> #define PCODE_MBOX_DOMAIN_HBM 0x2
>
> +#define FAN_SPEED_CONTROL 0x7D
> +#define FSC_READ_NUM_FANS 0x4
> +
> #define PCODE_SCRATCH(x) XE_REG(0x138320 + ((x) * 4))
> /* PCODE_SCRATCH0 */
> #define AUXINFO_REG_OFFSET REG_GENMASK(17, 15)
next prev parent reply other threads:[~2025-02-21 15:02 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-10 10:05 [PATCH v1] drm/xe/hwmon: expose fan speed Raag Jadav
2025-02-10 10:23 ` ✓ CI.Patch_applied: success for " Patchwork
2025-02-10 10:23 ` ✓ CI.checkpatch: " Patchwork
2025-02-10 10:24 ` ✓ CI.KUnit: " Patchwork
2025-02-10 10:41 ` ✓ CI.Build: " Patchwork
2025-02-10 10:43 ` ✓ CI.Hooks: " Patchwork
2025-02-10 10:44 ` ✓ CI.checksparse: " Patchwork
2025-02-10 16:15 ` [PATCH v1] " Andi Shyti
2025-02-11 14:06 ` Raag Jadav
2025-02-11 6:24 ` ✗ Xe.CI.BAT: failure for " Patchwork
2025-02-12 9:36 ` ✗ Xe.CI.Full: " Patchwork
2025-02-21 15:02 ` Poosa, Karthik [this message]
2025-02-24 7:46 ` [PATCH v1] " Raag Jadav
2025-03-06 14:51 ` Poosa, Karthik
2025-03-06 18:08 ` Raag Jadav
2025-03-03 7:26 ` Raag Jadav
2025-03-03 17:44 ` Rodrigo Vivi
2025-03-03 19:30 ` Raag Jadav
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bbda9792-7126-4961-8767-b435780f0cff@intel.com \
--to=karthik.poosa@intel.com \
--cc=andi.shyti@linux.intel.com \
--cc=anshuman.gupta@intel.com \
--cc=badal.nilawar@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=lucas.demarchi@intel.com \
--cc=matthew.d.roper@intel.com \
--cc=raag.jadav@intel.com \
--cc=riana.tauro@intel.com \
--cc=rodrigo.vivi@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.