Skip to content

Commit 118222e

Browse files
Shyam Sundar S Kij-intel
authored andcommitted
platform/x86/amd/pmf: Introduce new interface to export NPU metrics
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> [lizhi: save return value of is_npu_metrics_supported() and return it] Signed-off-by: Lizhi Hou <lizhi.hou@amd.com> Link: https://patch.msgid.link/20260115173448.403826-1-lizhi.hou@amd.com Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
1 parent 7b85137 commit 118222e

3 files changed

Lines changed: 99 additions & 0 deletions

File tree

drivers/platform/x86/amd/pmf/core.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
* Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
99
*/
1010

11+
#include <linux/array_size.h>
12+
#include <linux/cleanup.h>
1113
#include <linux/debugfs.h>
1214
#include <linux/iopoll.h>
1315
#include <linux/module.h>
1416
#include <linux/mutex.h>
1517
#include <linux/pci.h>
1618
#include <linux/platform_device.h>
1719
#include <linux/power_supply.h>
20+
#include <linux/string.h>
1821
#include <asm/amd/node.h>
1922
#include "pmf.h"
2023

@@ -54,6 +57,8 @@ static bool force_load;
5457
module_param(force_load, bool, 0444);
5558
MODULE_PARM_DESC(force_load, "Force load this driver on supported older platforms (experimental)");
5659

60+
static struct device *pmf_device;
61+
5762
static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data)
5863
{
5964
struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier);
@@ -315,6 +320,71 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
315320
return 0;
316321
}
317322

323+
static int is_npu_metrics_supported(struct amd_pmf_dev *pdev)
324+
{
325+
switch (pdev->cpu_id) {
326+
case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT:
327+
case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT:
328+
return 0;
329+
default:
330+
return -EOPNOTSUPP;
331+
}
332+
}
333+
334+
static int amd_pmf_get_smu_metrics(struct amd_pmf_dev *dev, struct amd_pmf_npu_metrics *data)
335+
{
336+
int ret, i;
337+
338+
guard(mutex)(&dev->metrics_mutex);
339+
340+
ret = is_npu_metrics_supported(dev);
341+
if (ret)
342+
return ret;
343+
344+
ret = amd_pmf_set_dram_addr(dev, true);
345+
if (ret)
346+
return ret;
347+
348+
memset(dev->buf, 0, dev->mtable_size);
349+
350+
/* Send SMU command to get NPU metrics */
351+
ret = amd_pmf_send_cmd(dev, SET_TRANSFER_TABLE, SET_CMD, METRICS_TABLE_ID, NULL);
352+
if (ret) {
353+
dev_err(dev->dev, "SMU command failed to get NPU metrics: %d\n", ret);
354+
return ret;
355+
}
356+
357+
memcpy(&dev->m_table_v2, dev->buf, dev->mtable_size);
358+
359+
data->npuclk_freq = dev->m_table_v2.npuclk_freq;
360+
for (i = 0; i < ARRAY_SIZE(data->npu_busy); i++)
361+
data->npu_busy[i] = dev->m_table_v2.npu_busy[i];
362+
data->npu_power = dev->m_table_v2.npu_power;
363+
data->mpnpuclk_freq = dev->m_table_v2.mpnpuclk_freq;
364+
data->npu_reads = dev->m_table_v2.npu_reads;
365+
data->npu_writes = dev->m_table_v2.npu_writes;
366+
367+
return 0;
368+
}
369+
370+
int amd_pmf_get_npu_data(struct amd_pmf_npu_metrics *info)
371+
{
372+
struct amd_pmf_dev *pdev;
373+
374+
if (!info)
375+
return -EINVAL;
376+
377+
if (!pmf_device)
378+
return -ENODEV;
379+
380+
pdev = dev_get_drvdata(pmf_device);
381+
if (!pdev)
382+
return -ENODEV;
383+
384+
return amd_pmf_get_smu_metrics(pdev, info);
385+
}
386+
EXPORT_SYMBOL_NS_GPL(amd_pmf_get_npu_data, "AMD_PMF");
387+
318388
static int amd_pmf_reinit_ta(struct amd_pmf_dev *pdev)
319389
{
320390
bool status;
@@ -542,6 +612,10 @@ static int amd_pmf_probe(struct platform_device *pdev)
542612
if (err)
543613
return err;
544614

615+
err = devm_mutex_init(dev->dev, &dev->metrics_mutex);
616+
if (err)
617+
return err;
618+
545619
apmf_acpi_init(dev);
546620
platform_set_drvdata(pdev, dev);
547621
amd_pmf_dbgfs_register(dev);
@@ -550,6 +624,8 @@ static int amd_pmf_probe(struct platform_device *pdev)
550624
if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
551625
amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_LOAD);
552626

627+
pmf_device = dev->dev;
628+
553629
dev_info(dev->dev, "registered PMF device successfully\n");
554630

555631
return 0;

drivers/platform/x86/amd/pmf/pmf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define PMF_H
1313

1414
#include <linux/acpi.h>
15+
#include <linux/amd-pmf-io.h>
1516
#include <linux/circ_buf.h>
1617
#include <linux/input.h>
1718
#include <linux/mutex_types.h>
@@ -440,6 +441,7 @@ struct amd_pmf_dev {
440441
bool cb_flag; /* To handle first custom BIOS input */
441442
struct pmf_cbi_ring_buffer cbi_buf;
442443
struct mutex cbi_mutex; /* Protects ring buffer access */
444+
struct mutex metrics_mutex;
443445
};
444446

445447
struct apmf_sps_prop_granular_v2 {

include/linux/amd-pmf-io.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,26 @@ enum laptop_placement {
6161
LP_UNDEFINED,
6262
};
6363

64+
/**
65+
* struct amd_pmf_npu_metrics: Get NPU metrics data from PMF driver
66+
* @npuclk_freq: NPU clock frequency [MHz]
67+
* @npu_busy: NPU busy % [0-100]
68+
* @npu_power: NPU power [mW]
69+
* @mpnpuclk_freq: MPNPU [MHz]
70+
* @npu_reads: NPU read bandwidth [MB/sec]
71+
* @npu_writes: NPU write bandwidth [MB/sec]
72+
*/
73+
struct amd_pmf_npu_metrics {
74+
u16 npuclk_freq;
75+
u16 npu_busy[8];
76+
u16 npu_power;
77+
u16 mpnpuclk_freq;
78+
u16 npu_reads;
79+
u16 npu_writes;
80+
};
81+
6482
int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op);
83+
84+
/* AMD PMF and NPU interface */
85+
int amd_pmf_get_npu_data(struct amd_pmf_npu_metrics *info);
6586
#endif

0 commit comments

Comments
 (0)