* [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
* 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
* [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
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 a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox