* [PATCH V2 0/2] Get real time power input via AMD PMF
@ 2025-12-12 18:18 Lizhi Hou
2025-12-12 18:18 ` [PATCH V2 1/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics Lizhi Hou
2025-12-12 18:18 ` [PATCH V2 2/2] accel/amdxdna: Add IOCTL to retrieve realtime NPU power estimate Lizhi Hou
0 siblings, 2 replies; 5+ messages in thread
From: Lizhi Hou @ 2025-12-12 18:18 UTC (permalink / raw)
To: ilpo.jarvinen, hansg, ogabbay, quic_jhugo, maciej.falkowski
Cc: Lizhi Hou, linux-kernel, max.zhen, sonal.santan,
mario.limonciello, dri-devel, platform-driver-x86,
Shyam-sundar.S-k, VinitKumar.Shukla
Adding new NPU metrics API to AMD PMF driver is pending because of
lacking real case.
https://lore.kernel.org/all/d344b850-f68d-f9a5-f0dc-55af4b48b714@linux.intel.com/
Create xdna driver patch to fetch real time power input via PMF API.
Here is an example output with xrt-smi(1) tool.
# xrt-smi examine -r all | grep Power
Power Mode : Default
Estimated Power : 0.563 Watts
V2:
Including header file for struct mutex will be added by
https://patchwork.kernel.org/project/platform-driver-x86/patch/20251202042219.245173-1-Shyam-sundar.S-k@amd.com/
Add include for U32_MAX
Replace snprintf by scnprintf
Fix coding style
Lizhi Hou (1):
accel/amdxdna: Add IOCTL to retrieve realtime NPU power estimate
Shyam Sundar S K (1):
platform/x86/amd/pmf: Introduce new interface to export NPU metrics
drivers/accel/amdxdna/aie2_pci.c | 29 ++++++++++
drivers/accel/amdxdna/aie2_pci.h | 20 +++++++
drivers/accel/amdxdna/amdxdna_pci_drv.c | 3 +-
drivers/platform/x86/amd/pmf/core.c | 75 +++++++++++++++++++++++++
drivers/platform/x86/amd/pmf/pmf.h | 2 +
include/linux/amd-pmf-io.h | 21 +++++++
6 files changed, 149 insertions(+), 1 deletion(-)
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH V2 1/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
2025-12-12 18:18 [PATCH V2 0/2] Get real time power input via AMD PMF Lizhi Hou
@ 2025-12-12 18:18 ` Lizhi Hou
2026-01-05 15:27 ` Ilpo Järvinen
2025-12-12 18:18 ` [PATCH V2 2/2] accel/amdxdna: Add IOCTL to retrieve realtime NPU power estimate Lizhi Hou
1 sibling, 1 reply; 5+ messages in thread
From: Lizhi Hou @ 2025-12-12 18:18 UTC (permalink / raw)
To: ilpo.jarvinen, hansg, ogabbay, quic_jhugo, maciej.falkowski
Cc: Shyam Sundar S K, linux-kernel, max.zhen, sonal.santan,
mario.limonciello, dri-devel, platform-driver-x86,
VinitKumar.Shukla, Patil Rajesh Reddy, Lizhi Hou
From: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
The PMF driver retrieves NPU metrics data from the PMFW. Introduce a new
interface to make NPU metrics accessible to other drivers like AMDXDNA
driver, which can access and utilize this information as needed.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
---
drivers/platform/x86/amd/pmf/core.c | 75 +++++++++++++++++++++++++++++
drivers/platform/x86/amd/pmf/pmf.h | 2 +
include/linux/amd-pmf-io.h | 21 ++++++++
3 files changed, 98 insertions(+)
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index a6a5d416edf9..8e4ce91b3527 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -8,12 +8,15 @@
* Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
*/
+#include <linux/array_size.h>
+#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
+#include <linux/string.h>
#include <asm/amd/node.h>
#include "pmf.h"
@@ -53,6 +56,8 @@ static bool force_load;
module_param(force_load, bool, 0444);
MODULE_PARM_DESC(force_load, "Force load this driver on supported older platforms (experimental)");
+static struct device *pmf_device;
+
static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data)
{
struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier);
@@ -314,6 +319,70 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
return 0;
}
+static int is_npu_metrics_supported(struct amd_pmf_dev *pdev)
+{
+ switch (pdev->cpu_id) {
+ case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT:
+ case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT:
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int amd_pmf_get_smu_metrics(struct amd_pmf_dev *dev, struct amd_pmf_npu_metrics *data)
+{
+ int ret, i;
+
+ guard(mutex)(&dev->metrics_mutex);
+
+ if (is_npu_metrics_supported(dev))
+ return -EOPNOTSUPP;
+
+ ret = amd_pmf_set_dram_addr(dev, true);
+ if (ret)
+ return ret;
+
+ memset(dev->buf, 0, dev->mtable_size);
+
+ /* Send SMU command to get NPU metrics */
+ ret = amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, SET_CMD, METRICS_TABLE_ID, NULL);
+ if (ret) {
+ dev_err(dev->dev, "SMU command failed to get NPU metrics: %d\n", ret);
+ return ret;
+ }
+
+ memcpy(&dev->m_table_v2, dev->buf, dev->mtable_size);
+
+ data->npuclk_freq = dev->m_table_v2.npuclk_freq;
+ for (i = 0; i < ARRAY_SIZE(data->npu_busy); i++)
+ data->npu_busy[i] = dev->m_table_v2.npu_busy[i];
+ data->npu_power = dev->m_table_v2.npu_power;
+ data->mpnpuclk_freq = dev->m_table_v2.mpnpuclk_freq;
+ data->npu_reads = dev->m_table_v2.npu_reads;
+ data->npu_writes = dev->m_table_v2.npu_writes;
+
+ return 0;
+}
+
+int amd_pmf_get_npu_data(struct amd_pmf_npu_metrics *info)
+{
+ struct amd_pmf_dev *pdev;
+
+ if (!info)
+ return -EINVAL;
+
+ if (!pmf_device)
+ return -ENODEV;
+
+ pdev = dev_get_drvdata(pmf_device);
+ if (!pdev)
+ return -ENODEV;
+
+ return amd_pmf_get_smu_metrics(pdev, info);
+}
+EXPORT_SYMBOL_GPL(amd_pmf_get_npu_data);
+
static int amd_pmf_suspend_handler(struct device *dev)
{
struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
@@ -469,6 +538,10 @@ static int amd_pmf_probe(struct platform_device *pdev)
mutex_init(&dev->update_mutex);
mutex_init(&dev->cb_mutex);
+ err = devm_mutex_init(dev->dev, &dev->metrics_mutex);
+ if (err)
+ return err;
+
apmf_acpi_init(dev);
platform_set_drvdata(pdev, dev);
amd_pmf_dbgfs_register(dev);
@@ -477,6 +550,8 @@ static int amd_pmf_probe(struct platform_device *pdev)
if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_LOAD);
+ pmf_device = dev->dev;
+
dev_info(dev->dev, "registered PMF device successfully\n");
return 0;
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index f07e9f4c660a..0354cc5dc79e 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -12,6 +12,7 @@
#define PMF_H
#include <linux/acpi.h>
+#include <linux/amd-pmf-io.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/platform_profile.h>
@@ -412,6 +413,7 @@ struct amd_pmf_dev {
struct apmf_sbios_req_v1 req1;
struct pmf_bios_inputs_prev cb_prev; /* To preserve custom BIOS inputs */
bool cb_flag; /* To handle first custom BIOS input */
+ struct mutex metrics_mutex;
};
struct apmf_sps_prop_granular_v2 {
diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
index 6fa510f419c0..55198d2875cc 100644
--- a/include/linux/amd-pmf-io.h
+++ b/include/linux/amd-pmf-io.h
@@ -61,5 +61,26 @@ enum laptop_placement {
LP_UNDEFINED,
};
+/**
+ * struct amd_pmf_npu_metrics: Get NPU metrics data from PMF driver
+ * @npuclk_freq: NPU clock frequency [MHz]
+ * @npu_busy: NPU busy % [0-100]
+ * @npu_power: NPU power [mW]
+ * @mpnpuclk_freq: MPNPU [MHz]
+ * @npu_reads: NPU read bandwidth [MB/sec]
+ * @npu_writes: NPU write bandwidth [MB/sec]
+ */
+struct amd_pmf_npu_metrics {
+ u16 npuclk_freq;
+ u16 npu_busy[8];
+ u16 npu_power;
+ u16 mpnpuclk_freq;
+ u16 npu_reads;
+ u16 npu_writes;
+};
+
int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
+
+/* AMD PMF and NPU interface */
+int amd_pmf_get_npu_data(struct amd_pmf_npu_metrics *info);
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH V2 2/2] accel/amdxdna: Add IOCTL to retrieve realtime NPU power estimate
2025-12-12 18:18 [PATCH V2 0/2] Get real time power input via AMD PMF Lizhi Hou
2025-12-12 18:18 ` [PATCH V2 1/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics Lizhi Hou
@ 2025-12-12 18:18 ` Lizhi Hou
1 sibling, 0 replies; 5+ messages in thread
From: Lizhi Hou @ 2025-12-12 18:18 UTC (permalink / raw)
To: ilpo.jarvinen, hansg, ogabbay, quic_jhugo, maciej.falkowski
Cc: Lizhi Hou, linux-kernel, max.zhen, sonal.santan,
mario.limonciello, dri-devel, platform-driver-x86,
Shyam-sundar.S-k, VinitKumar.Shukla, Mario Limonciello
The AMD PMF driver provides an interface to obtain realtime power
estimates for the NPU. Expose this information to userspace through a
new DRM_IOCTL_AMDXDNA_GET_INFO parameter, allowing applications to query
the current NPU power level.
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Reviewed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
---
drivers/accel/amdxdna/aie2_pci.c | 29 +++++++++++++++++++++++++
drivers/accel/amdxdna/aie2_pci.h | 20 +++++++++++++++++
drivers/accel/amdxdna/amdxdna_pci_drv.c | 3 ++-
3 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c
index 81a8e4137bfd..55fbc8f0f455 100644
--- a/drivers/accel/amdxdna/aie2_pci.c
+++ b/drivers/accel/amdxdna/aie2_pci.c
@@ -10,6 +10,7 @@
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
#include <drm/gpu_scheduler.h>
+#include <linux/amd-pmf-io.h>
#include <linux/cleanup.h>
#include <linux/errno.h>
#include <linux/firmware.h>
@@ -777,6 +778,31 @@ static int aie2_get_clock_metadata(struct amdxdna_client *client,
return ret;
}
+static int aie2_get_sensors(struct amdxdna_client *client,
+ struct amdxdna_drm_get_info *args)
+{
+ struct amdxdna_drm_query_sensor sensor = {};
+ int ret;
+
+ if (args->buffer_size < sizeof(sensor))
+ return -EINVAL;
+
+ ret = AIE2_GET_PMF_NPU_DATA(npu_power, sensor.input);
+ if (ret)
+ return ret;
+ sensor.type = AMDXDNA_SENSOR_TYPE_POWER;
+ sensor.unitm = -3;
+ scnprintf(sensor.label, sizeof(sensor.label), "Total Power");
+ scnprintf(sensor.units, sizeof(sensor.units), "mW");
+
+ if (copy_to_user(u64_to_user_ptr(args->buffer), &sensor, sizeof(sensor)))
+ return -EFAULT;
+
+ args->buffer_size = sizeof(sensor);
+
+ return 0;
+}
+
static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg)
{
struct amdxdna_drm_hwctx_entry *tmp __free(kfree) = NULL;
@@ -980,6 +1006,9 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
case DRM_AMDXDNA_QUERY_CLOCK_METADATA:
ret = aie2_get_clock_metadata(client, args);
break;
+ case DRM_AMDXDNA_QUERY_SENSORS:
+ ret = aie2_get_sensors(client, args);
+ break;
case DRM_AMDXDNA_QUERY_HW_CONTEXTS:
ret = aie2_get_hwctx_status(client, args);
break;
diff --git a/drivers/accel/amdxdna/aie2_pci.h b/drivers/accel/amdxdna/aie2_pci.h
index c6b5cf4ae5c4..7f588ad99240 100644
--- a/drivers/accel/amdxdna/aie2_pci.h
+++ b/drivers/accel/amdxdna/aie2_pci.h
@@ -7,6 +7,7 @@
#define _AIE2_PCI_H_
#include <drm/amdxdna_accel.h>
+#include <linux/limits.h>
#include <linux/semaphore.h>
#include "amdxdna_mailbox.h"
@@ -46,6 +47,25 @@
pci_resource_len(NDEV2PDEV(_ndev), (_ndev)->xdna->dev_info->mbox_bar); \
})
+#if IS_ENABLED(CONFIG_AMD_PMF)
+#define AIE2_GET_PMF_NPU_DATA(field, val) \
+({ \
+ struct amd_pmf_npu_metrics _npu_metrics; \
+ int _ret; \
+ \
+ _ret = amd_pmf_get_npu_data(&_npu_metrics); \
+ val = _ret ? U32_MAX : _npu_metrics.field; \
+ (_ret); \
+})
+#else
+#define SENSOR_DEFAULT_npu_power U32_MAX
+#define AIE2_GET_PMF_NPU_DATA(field, val) \
+({ \
+ val = SENSOR_DEFAULT_##field; \
+ (-EOPNOTSUPP); \
+})
+#endif
+
enum aie2_smu_reg_idx {
SMU_CMD_REG = 0,
SMU_ARG_REG,
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c
index 1973ab67721b..643ebd387074 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
@@ -32,9 +32,10 @@ MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");
* 0.4: Support getting resource information
* 0.5: Support getting telemetry data
* 0.6: Support preemption
+ * 0.7: Support getting power data
*/
#define AMDXDNA_DRIVER_MAJOR 0
-#define AMDXDNA_DRIVER_MINOR 6
+#define AMDXDNA_DRIVER_MINOR 7
/*
* Bind the driver base on (vendor_id, device_id) pair and later use the
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH V2 1/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
2025-12-12 18:18 ` [PATCH V2 1/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics Lizhi Hou
@ 2026-01-05 15:27 ` Ilpo Järvinen
2026-01-05 16:28 ` Lizhi Hou
0 siblings, 1 reply; 5+ messages in thread
From: Ilpo Järvinen @ 2026-01-05 15:27 UTC (permalink / raw)
To: Lizhi Hou
Cc: Hans de Goede, ogabbay, quic_jhugo, maciej.falkowski,
Shyam Sundar S K, LKML, max.zhen, sonal.santan, mario.limonciello,
dri-devel, platform-driver-x86, VinitKumar.Shukla,
Patil Rajesh Reddy
On Fri, 12 Dec 2025, Lizhi Hou wrote:
> From: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>
> The PMF driver retrieves NPU metrics data from the PMFW. Introduce a new
> interface to make NPU metrics accessible to other drivers like AMDXDNA
> driver, which can access and utilize this information as needed.
>
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
> Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
> ---
> drivers/platform/x86/amd/pmf/core.c | 75 +++++++++++++++++++++++++++++
> drivers/platform/x86/amd/pmf/pmf.h | 2 +
> include/linux/amd-pmf-io.h | 21 ++++++++
> 3 files changed, 98 insertions(+)
>
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index a6a5d416edf9..8e4ce91b3527 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -8,12 +8,15 @@
> * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
> */
>
> +#include <linux/array_size.h>
> +#include <linux/cleanup.h>
> #include <linux/debugfs.h>
> #include <linux/iopoll.h>
> #include <linux/module.h>
> #include <linux/pci.h>
> #include <linux/platform_device.h>
> #include <linux/power_supply.h>
> +#include <linux/string.h>
> #include <asm/amd/node.h>
> #include "pmf.h"
>
> @@ -53,6 +56,8 @@ static bool force_load;
> module_param(force_load, bool, 0444);
> MODULE_PARM_DESC(force_load, "Force load this driver on supported older platforms (experimental)");
>
> +static struct device *pmf_device;
> +
> static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data)
> {
> struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier);
> @@ -314,6 +319,70 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
> return 0;
> }
>
> +static int is_npu_metrics_supported(struct amd_pmf_dev *pdev)
> +{
> + switch (pdev->cpu_id) {
> + case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT:
> + case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT:
> + return 0;
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +
> +static int amd_pmf_get_smu_metrics(struct amd_pmf_dev *dev, struct amd_pmf_npu_metrics *data)
> +{
> + int ret, i;
> +
> + guard(mutex)(&dev->metrics_mutex);
> +
> + if (is_npu_metrics_supported(dev))
> + return -EOPNOTSUPP;
Generally, we don't want to shadow error codes like this so please save it
from is_npu_metrics_supported() and do return ret;
> +
> + ret = amd_pmf_set_dram_addr(dev, true);
> + if (ret)
> + return ret;
> +
> + memset(dev->buf, 0, dev->mtable_size);
> +
> + /* Send SMU command to get NPU metrics */
> + ret = amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, SET_CMD, METRICS_TABLE_ID, NULL);
> + if (ret) {
> + dev_err(dev->dev, "SMU command failed to get NPU metrics: %d\n", ret);
> + return ret;
> + }
> +
> + memcpy(&dev->m_table_v2, dev->buf, dev->mtable_size);
> +
> + data->npuclk_freq = dev->m_table_v2.npuclk_freq;
> + for (i = 0; i < ARRAY_SIZE(data->npu_busy); i++)
> + data->npu_busy[i] = dev->m_table_v2.npu_busy[i];
> + data->npu_power = dev->m_table_v2.npu_power;
To confirm, so only this field is currently going to be used?
--
i.
> + data->mpnpuclk_freq = dev->m_table_v2.mpnpuclk_freq;
> + data->npu_reads = dev->m_table_v2.npu_reads;
> + data->npu_writes = dev->m_table_v2.npu_writes;
> +
> + return 0;
> +}
> +
> +int amd_pmf_get_npu_data(struct amd_pmf_npu_metrics *info)
> +{
> + struct amd_pmf_dev *pdev;
> +
> + if (!info)
> + return -EINVAL;
> +
> + if (!pmf_device)
> + return -ENODEV;
> +
> + pdev = dev_get_drvdata(pmf_device);
> + if (!pdev)
> + return -ENODEV;
> +
> + return amd_pmf_get_smu_metrics(pdev, info);
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_get_npu_data);
> +
> static int amd_pmf_suspend_handler(struct device *dev)
> {
> struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
> @@ -469,6 +538,10 @@ static int amd_pmf_probe(struct platform_device *pdev)
> mutex_init(&dev->update_mutex);
> mutex_init(&dev->cb_mutex);
>
> + err = devm_mutex_init(dev->dev, &dev->metrics_mutex);
> + if (err)
> + return err;
> +
> apmf_acpi_init(dev);
> platform_set_drvdata(pdev, dev);
> amd_pmf_dbgfs_register(dev);
> @@ -477,6 +550,8 @@ static int amd_pmf_probe(struct platform_device *pdev)
> if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
> amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_LOAD);
>
> + pmf_device = dev->dev;
> +
> dev_info(dev->dev, "registered PMF device successfully\n");
>
> return 0;
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index f07e9f4c660a..0354cc5dc79e 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -12,6 +12,7 @@
> #define PMF_H
>
> #include <linux/acpi.h>
> +#include <linux/amd-pmf-io.h>
> #include <linux/input.h>
> #include <linux/platform_device.h>
> #include <linux/platform_profile.h>
> @@ -412,6 +413,7 @@ struct amd_pmf_dev {
> struct apmf_sbios_req_v1 req1;
> struct pmf_bios_inputs_prev cb_prev; /* To preserve custom BIOS inputs */
> bool cb_flag; /* To handle first custom BIOS input */
> + struct mutex metrics_mutex;
> };
>
> struct apmf_sps_prop_granular_v2 {
> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
> index 6fa510f419c0..55198d2875cc 100644
> --- a/include/linux/amd-pmf-io.h
> +++ b/include/linux/amd-pmf-io.h
> @@ -61,5 +61,26 @@ enum laptop_placement {
> LP_UNDEFINED,
> };
>
> +/**
> + * struct amd_pmf_npu_metrics: Get NPU metrics data from PMF driver
> + * @npuclk_freq: NPU clock frequency [MHz]
> + * @npu_busy: NPU busy % [0-100]
> + * @npu_power: NPU power [mW]
> + * @mpnpuclk_freq: MPNPU [MHz]
> + * @npu_reads: NPU read bandwidth [MB/sec]
> + * @npu_writes: NPU write bandwidth [MB/sec]
> + */
> +struct amd_pmf_npu_metrics {
> + u16 npuclk_freq;
> + u16 npu_busy[8];
> + u16 npu_power;
> + u16 mpnpuclk_freq;
> + u16 npu_reads;
> + u16 npu_writes;
> +};
> +
> int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
> +
> +/* AMD PMF and NPU interface */
> +int amd_pmf_get_npu_data(struct amd_pmf_npu_metrics *info);
> #endif
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH V2 1/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
2026-01-05 15:27 ` Ilpo Järvinen
@ 2026-01-05 16:28 ` Lizhi Hou
0 siblings, 0 replies; 5+ messages in thread
From: Lizhi Hou @ 2026-01-05 16:28 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: Hans de Goede, ogabbay, quic_jhugo, maciej.falkowski,
Shyam Sundar S K, LKML, max.zhen, sonal.santan, mario.limonciello,
dri-devel, platform-driver-x86, VinitKumar.Shukla,
Patil Rajesh Reddy
On 1/5/26 07:27, Ilpo Järvinen wrote:
> On Fri, 12 Dec 2025, Lizhi Hou wrote:
>
>> From: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>
>> The PMF driver retrieves NPU metrics data from the PMFW. Introduce a new
>> interface to make NPU metrics accessible to other drivers like AMDXDNA
>> driver, which can access and utilize this information as needed.
>>
>> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
>> Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
>> Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
>> ---
>> drivers/platform/x86/amd/pmf/core.c | 75 +++++++++++++++++++++++++++++
>> drivers/platform/x86/amd/pmf/pmf.h | 2 +
>> include/linux/amd-pmf-io.h | 21 ++++++++
>> 3 files changed, 98 insertions(+)
>>
>> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
>> index a6a5d416edf9..8e4ce91b3527 100644
>> --- a/drivers/platform/x86/amd/pmf/core.c
>> +++ b/drivers/platform/x86/amd/pmf/core.c
>> @@ -8,12 +8,15 @@
>> * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>> */
>>
>> +#include <linux/array_size.h>
>> +#include <linux/cleanup.h>
>> #include <linux/debugfs.h>
>> #include <linux/iopoll.h>
>> #include <linux/module.h>
>> #include <linux/pci.h>
>> #include <linux/platform_device.h>
>> #include <linux/power_supply.h>
>> +#include <linux/string.h>
>> #include <asm/amd/node.h>
>> #include "pmf.h"
>>
>> @@ -53,6 +56,8 @@ static bool force_load;
>> module_param(force_load, bool, 0444);
>> MODULE_PARM_DESC(force_load, "Force load this driver on supported older platforms (experimental)");
>>
>> +static struct device *pmf_device;
>> +
>> static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data)
>> {
>> struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier);
>> @@ -314,6 +319,70 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
>> return 0;
>> }
>>
>> +static int is_npu_metrics_supported(struct amd_pmf_dev *pdev)
>> +{
>> + switch (pdev->cpu_id) {
>> + case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT:
>> + case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT:
>> + return 0;
>> + default:
>> + return -EOPNOTSUPP;
>> + }
>> +}
>> +
>> +static int amd_pmf_get_smu_metrics(struct amd_pmf_dev *dev, struct amd_pmf_npu_metrics *data)
>> +{
>> + int ret, i;
>> +
>> + guard(mutex)(&dev->metrics_mutex);
>> +
>> + if (is_npu_metrics_supported(dev))
>> + return -EOPNOTSUPP;
> Generally, we don't want to shadow error codes like this so please save it
> from is_npu_metrics_supported() and do return ret;
Sure.
>
>> +
>> + ret = amd_pmf_set_dram_addr(dev, true);
>> + if (ret)
>> + return ret;
>> +
>> + memset(dev->buf, 0, dev->mtable_size);
>> +
>> + /* Send SMU command to get NPU metrics */
>> + ret = amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, SET_CMD, METRICS_TABLE_ID, NULL);
>> + if (ret) {
>> + dev_err(dev->dev, "SMU command failed to get NPU metrics: %d\n", ret);
>> + return ret;
>> + }
>> +
>> + memcpy(&dev->m_table_v2, dev->buf, dev->mtable_size);
>> +
>> + data->npuclk_freq = dev->m_table_v2.npuclk_freq;
>> + for (i = 0; i < ARRAY_SIZE(data->npu_busy); i++)
>> + data->npu_busy[i] = dev->m_table_v2.npu_busy[i];
>> + data->npu_power = dev->m_table_v2.npu_power;
> To confirm, so only this field is currently going to be used?
Yes. Only this field will be used for now.
Lizhi
>
> --
> i.
>
>> + data->mpnpuclk_freq = dev->m_table_v2.mpnpuclk_freq;
>> + data->npu_reads = dev->m_table_v2.npu_reads;
>> + data->npu_writes = dev->m_table_v2.npu_writes;
>> +
>> + return 0;
>> +}
>> +
>> +int amd_pmf_get_npu_data(struct amd_pmf_npu_metrics *info)
>> +{
>> + struct amd_pmf_dev *pdev;
>> +
>> + if (!info)
>> + return -EINVAL;
>> +
>> + if (!pmf_device)
>> + return -ENODEV;
>> +
>> + pdev = dev_get_drvdata(pmf_device);
>> + if (!pdev)
>> + return -ENODEV;
>> +
>> + return amd_pmf_get_smu_metrics(pdev, info);
>> +}
>> +EXPORT_SYMBOL_GPL(amd_pmf_get_npu_data);
>> +
>> static int amd_pmf_suspend_handler(struct device *dev)
>> {
>> struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
>> @@ -469,6 +538,10 @@ static int amd_pmf_probe(struct platform_device *pdev)
>> mutex_init(&dev->update_mutex);
>> mutex_init(&dev->cb_mutex);
>>
>> + err = devm_mutex_init(dev->dev, &dev->metrics_mutex);
>> + if (err)
>> + return err;
>> +
>> apmf_acpi_init(dev);
>> platform_set_drvdata(pdev, dev);
>> amd_pmf_dbgfs_register(dev);
>> @@ -477,6 +550,8 @@ static int amd_pmf_probe(struct platform_device *pdev)
>> if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
>> amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_LOAD);
>>
>> + pmf_device = dev->dev;
>> +
>> dev_info(dev->dev, "registered PMF device successfully\n");
>>
>> return 0;
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
>> index f07e9f4c660a..0354cc5dc79e 100644
>> --- a/drivers/platform/x86/amd/pmf/pmf.h
>> +++ b/drivers/platform/x86/amd/pmf/pmf.h
>> @@ -12,6 +12,7 @@
>> #define PMF_H
>>
>> #include <linux/acpi.h>
>> +#include <linux/amd-pmf-io.h>
>> #include <linux/input.h>
>> #include <linux/platform_device.h>
>> #include <linux/platform_profile.h>
>> @@ -412,6 +413,7 @@ struct amd_pmf_dev {
>> struct apmf_sbios_req_v1 req1;
>> struct pmf_bios_inputs_prev cb_prev; /* To preserve custom BIOS inputs */
>> bool cb_flag; /* To handle first custom BIOS input */
>> + struct mutex metrics_mutex;
>> };
>>
>> struct apmf_sps_prop_granular_v2 {
>> diff --git a/include/linux/amd-pmf-io.h b/include/linux/amd-pmf-io.h
>> index 6fa510f419c0..55198d2875cc 100644
>> --- a/include/linux/amd-pmf-io.h
>> +++ b/include/linux/amd-pmf-io.h
>> @@ -61,5 +61,26 @@ enum laptop_placement {
>> LP_UNDEFINED,
>> };
>>
>> +/**
>> + * struct amd_pmf_npu_metrics: Get NPU metrics data from PMF driver
>> + * @npuclk_freq: NPU clock frequency [MHz]
>> + * @npu_busy: NPU busy % [0-100]
>> + * @npu_power: NPU power [mW]
>> + * @mpnpuclk_freq: MPNPU [MHz]
>> + * @npu_reads: NPU read bandwidth [MB/sec]
>> + * @npu_writes: NPU write bandwidth [MB/sec]
>> + */
>> +struct amd_pmf_npu_metrics {
>> + u16 npuclk_freq;
>> + u16 npu_busy[8];
>> + u16 npu_power;
>> + u16 mpnpuclk_freq;
>> + u16 npu_reads;
>> + u16 npu_writes;
>> +};
>> +
>> int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
>> +
>> +/* AMD PMF and NPU interface */
>> +int amd_pmf_get_npu_data(struct amd_pmf_npu_metrics *info);
>> #endif
>>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-01-05 16:29 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-12 18:18 [PATCH V2 0/2] Get real time power input via AMD PMF Lizhi Hou
2025-12-12 18:18 ` [PATCH V2 1/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics Lizhi Hou
2026-01-05 15:27 ` Ilpo Järvinen
2026-01-05 16:28 ` Lizhi Hou
2025-12-12 18:18 ` [PATCH V2 2/2] accel/amdxdna: Add IOCTL to retrieve realtime NPU power estimate Lizhi Hou
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.