Re: [PATCH V3 1/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
From: Lizhi Hou
Date: Thu Jan 15 2026 - 11:49:07 EST
On 1/15/26 07:18, Ilpo Järvinen wrote:
On Mon, 5 Jan 2026, Lizhi Hou wrote:
From: Shyam Sundar S K <Shyam-sundar.S-k@xxxxxxx>One more thing, the export should be namespaced.
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@xxxxxxx>
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@xxxxxxx>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@xxxxxxx>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@xxxxxxx>
[lizhi: save return value of is_npu_metrics_supported() and return it]
Signed-off-by: Lizhi Hou <lizhi.hou@xxxxxxx>
---
drivers/platform/x86/amd/pmf/core.c | 76 +++++++++++++++++++++++++++++
drivers/platform/x86/amd/pmf/pmf.h | 2 +
include/linux/amd-pmf-io.h | 21 ++++++++
3 files changed, 99 insertions(+)
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index 8fc293c9c538..d180a39e03bf 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@xxxxxxx>
*/
+#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,71 @@ 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);
+
+ ret = is_npu_metrics_supported(dev);
+ if (ret)
+ 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;
+ 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);
And since I'll be applying only this patch and not do an IB, can you also
rebase it on top for the for-next branch.
Sure, I will send a V4 patch.
Lizhi