platform-driver-x86.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] platform/x86/amd/pmf: Rename ipu fields to npu in smu_pmf_metrics_v2 structure
@ 2025-09-19  5:54 Shyam Sundar S K
  2025-09-19  5:54 ` [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics Shyam Sundar S K
  2025-09-19 14:06 ` [PATCH 1/2] platform/x86/amd/pmf: Rename ipu fields to npu in smu_pmf_metrics_v2 structure Mario Limonciello (AMD) (kernel.org)
  0 siblings, 2 replies; 8+ messages in thread
From: Shyam Sundar S K @ 2025-09-19  5:54 UTC (permalink / raw)
  To: hdegoede, ilpo.jarvinen
  Cc: platform-driver-x86, Patil.Reddy, Shyam Sundar S K

Rename multiple fields in the struct smu_pmf_metrics_v2 from "ipu" to "npu"
to align with updated hardware terminology and enhance code clarity.

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>
---
Hi Ilpo, this can be applied on origin/review-ilpo-next with git tip commit
"8236b4667aca"

 drivers/platform/x86/amd/pmf/pmf.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index bd19f2a6bc78..6ea5380f3b23 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -243,12 +243,12 @@ struct smu_pmf_metrics_v2 {
 	u16 vclk_freq;			/* MHz */
 	u16 vcn_activity;		/* VCN busy % [0-100] */
 	u16 vpeclk_freq;		/* MHz */
-	u16 ipuclk_freq;		/* MHz */
-	u16 ipu_busy[8];		/* NPU busy % [0-100] */
+	u16 npuclk_freq;		/* MHz */
+	u16 npu_busy[8];		/* NPU busy % [0-100] */
 	u16 dram_reads;			/* MB/sec */
 	u16 dram_writes;		/* MB/sec */
 	u16 core_c0residency[16];	/* C0 residency % [0-100] */
-	u16 ipu_power;			/* mW */
+	u16 npu_power;			/* mW */
 	u32 apu_power;			/* mW */
 	u32 gfx_power;			/* mW */
 	u32 dgpu_power;			/* mW */
@@ -257,9 +257,9 @@ struct smu_pmf_metrics_v2 {
 	u32 filter_alpha_value;		/* time constant [us] */
 	u32 metrics_counter;
 	u16 memclk_freq;		/* MHz */
-	u16 mpipuclk_freq;		/* MHz */
-	u16 ipu_reads;			/* MB/sec */
-	u16 ipu_writes;			/* MB/sec */
+	u16 mpnpuclk_freq;		/* MHz */
+	u16 npu_reads;			/* MB/sec */
+	u16 npu_writes;			/* MB/sec */
 	u32 throttle_residency_prochot;
 	u32 throttle_residency_spl;
 	u32 throttle_residency_fppt;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
  2025-09-19  5:54 [PATCH 1/2] platform/x86/amd/pmf: Rename ipu fields to npu in smu_pmf_metrics_v2 structure Shyam Sundar S K
@ 2025-09-19  5:54 ` Shyam Sundar S K
  2025-09-19 14:21   ` Mario Limonciello
  2025-09-19 20:26   ` Lizhi Hou
  2025-09-19 14:06 ` [PATCH 1/2] platform/x86/amd/pmf: Rename ipu fields to npu in smu_pmf_metrics_v2 structure Mario Limonciello (AMD) (kernel.org)
  1 sibling, 2 replies; 8+ messages in thread
From: Shyam Sundar S K @ 2025-09-19  5:54 UTC (permalink / raw)
  To: hdegoede, ilpo.jarvinen
  Cc: platform-driver-x86, Patil.Reddy, Shyam Sundar S K

The PMF driver retrieves NPU metrics data from the PMFW. This commit
introduces a new interface to make NPU metrics accessible to other
drivers like AMDXDNA driver, which can access and utilize this
information as needed.

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>
---
Hi Ilpo, this can be applied on origin/review-ilpo-next with git tip commit
"8236b4667aca"

 drivers/platform/x86/amd/pmf/core.c | 60 +++++++++++++++++++++++++++++
 drivers/platform/x86/amd/pmf/pmf.h  |  1 +
 include/linux/amd-pmf-io.h          | 21 ++++++++++
 3 files changed, 82 insertions(+)

diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index ef988605c4da..75529047377c 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -8,6 +8,7 @@
  * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
  */
 
+#include <linux/amd-pmf-io.h>
 #include <linux/debugfs.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
@@ -53,6 +54,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;
+
 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 +317,61 @@ 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;
+
+	if (is_npu_metrics_supported(dev))
+		return -EINVAL;
+
+	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, 0, 7, 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 = dev_get_drvdata(pmf);
+
+	if (!pdev || !info)
+		return -EINVAL;
+
+	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);
@@ -431,6 +489,8 @@ static int amd_pmf_probe(struct platform_device *pdev)
 
 	dev->dev = &pdev->dev;
 
+	pmf = dev->dev;
+
 	rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
 	if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
 		pci_dev_put(rdev);
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 6ea5380f3b23..622404e71136 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>
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] 8+ messages in thread

* Re: [PATCH 1/2] platform/x86/amd/pmf: Rename ipu fields to npu in smu_pmf_metrics_v2 structure
  2025-09-19  5:54 [PATCH 1/2] platform/x86/amd/pmf: Rename ipu fields to npu in smu_pmf_metrics_v2 structure Shyam Sundar S K
  2025-09-19  5:54 ` [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics Shyam Sundar S K
@ 2025-09-19 14:06 ` Mario Limonciello (AMD) (kernel.org)
  1 sibling, 0 replies; 8+ messages in thread
From: Mario Limonciello (AMD) (kernel.org) @ 2025-09-19 14:06 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, ilpo.jarvinen
  Cc: platform-driver-x86, Patil.Reddy



On 9/19/2025 12:54 AM, Shyam Sundar S K wrote:
> Rename multiple fields in the struct smu_pmf_metrics_v2 from "ipu" to "npu"
> to align with updated hardware terminology and enhance code clarity.
> 
> 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>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>> ---
> Hi Ilpo, this can be applied on origin/review-ilpo-next with git tip commit
> "8236b4667aca"
> 
>   drivers/platform/x86/amd/pmf/pmf.h | 12 ++++++------
>   1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index bd19f2a6bc78..6ea5380f3b23 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -243,12 +243,12 @@ struct smu_pmf_metrics_v2 {
>   	u16 vclk_freq;			/* MHz */
>   	u16 vcn_activity;		/* VCN busy % [0-100] */
>   	u16 vpeclk_freq;		/* MHz */
> -	u16 ipuclk_freq;		/* MHz */
> -	u16 ipu_busy[8];		/* NPU busy % [0-100] */
> +	u16 npuclk_freq;		/* MHz */
> +	u16 npu_busy[8];		/* NPU busy % [0-100] */
>   	u16 dram_reads;			/* MB/sec */
>   	u16 dram_writes;		/* MB/sec */
>   	u16 core_c0residency[16];	/* C0 residency % [0-100] */
> -	u16 ipu_power;			/* mW */
> +	u16 npu_power;			/* mW */
>   	u32 apu_power;			/* mW */
>   	u32 gfx_power;			/* mW */
>   	u32 dgpu_power;			/* mW */
> @@ -257,9 +257,9 @@ struct smu_pmf_metrics_v2 {
>   	u32 filter_alpha_value;		/* time constant [us] */
>   	u32 metrics_counter;
>   	u16 memclk_freq;		/* MHz */
> -	u16 mpipuclk_freq;		/* MHz */
> -	u16 ipu_reads;			/* MB/sec */
> -	u16 ipu_writes;			/* MB/sec */
> +	u16 mpnpuclk_freq;		/* MHz */
> +	u16 npu_reads;			/* MB/sec */
> +	u16 npu_writes;			/* MB/sec */
>   	u32 throttle_residency_prochot;
>   	u32 throttle_residency_spl;
>   	u32 throttle_residency_fppt;


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
  2025-09-19  5:54 ` [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics Shyam Sundar S K
@ 2025-09-19 14:21   ` Mario Limonciello
  2025-09-22 16:07     ` Shyam Sundar S K
  2025-09-19 20:26   ` Lizhi Hou
  1 sibling, 1 reply; 8+ messages in thread
From: Mario Limonciello @ 2025-09-19 14:21 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, ilpo.jarvinen, Lizhi Hou
  Cc: platform-driver-x86, Patil.Reddy

On 9/19/2025 12:54 AM, Shyam Sundar S K wrote:
> The PMF driver retrieves NPU metrics data from the PMFW. This commit
> introduces a new interface to make NPU metrics accessible to other
> drivers like AMDXDNA driver, which can access and utilize this
> information as needed.
> 
> 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 for comments.

As this interface will be something amdxdna uses I think we should make 
sure there is a R-b from Lizhi.

I have a few comments below as well.

> ---
> Hi Ilpo, this can be applied on origin/review-ilpo-next with git tip commit
> "8236b4667aca"
> 
>   drivers/platform/x86/amd/pmf/core.c | 60 +++++++++++++++++++++++++++++
>   drivers/platform/x86/amd/pmf/pmf.h  |  1 +
>   include/linux/amd-pmf-io.h          | 21 ++++++++++
>   3 files changed, 82 insertions(+)
> 
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index ef988605c4da..75529047377c 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -8,6 +8,7 @@
>    * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>    */
>   
> +#include <linux/amd-pmf-io.h>
>   #include <linux/debugfs.h>
>   #include <linux/iopoll.h>
>   #include <linux/module.h>
> @@ -53,6 +54,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;
> +
>   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 +317,61 @@ 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:

I'm a bit surprised AMD_CPU_ID_PS isn't in this list.  Does it not have 
the same interface?

> +		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;
> +
> +	if (is_npu_metrics_supported(dev))
> +		return -EINVAL;
> +
> +	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, 0, 7, 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 = dev_get_drvdata(pmf);
> +
> +	if (!pdev || !info)
> +		return -EINVAL;
> +
> +	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);
> @@ -431,6 +489,8 @@ static int amd_pmf_probe(struct platform_device *pdev)
>   
>   	dev->dev = &pdev->dev;
>   
> +	pmf = dev->dev;
> +
>   	rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
>   	if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
>   		pci_dev_put(rdev);
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 6ea5380f3b23..622404e71136 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>
> 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];

This 8 comes from there being 8 columns, right?  What happens when we 
have a product with more?  It seems like this doesn't scale well outside 
of that design.

I know it is a simple memcpy() right now and the structure resembles the 
firmware structure, but would it make sense for inter-kernel 
commnication to define a different structure that would remain stable no 
matter how many columns?

Something like this:

struct amd_pmf_npu_metrics {
	u16 npuclk_freq;
	u16 npu_power;
	u16 mpnpuclk_freq;
	u16 npu_reads;
	u16 npu_writes;
	u8 npu_columns;
	u16 *npu_busy;
};

The size of npu_busy could be allocated dynamically, but this would also 
mean putting the responsibility of freeing it on the caller.

The alternative is of course a amd_pmf_npu_metrics_v2 if/when that 
happens.

I just thought it was worth considering right now.
> +	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] 8+ messages in thread

* Re: [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
  2025-09-19  5:54 ` [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics Shyam Sundar S K
  2025-09-19 14:21   ` Mario Limonciello
@ 2025-09-19 20:26   ` Lizhi Hou
  2025-09-22 16:08     ` Shyam Sundar S K
  1 sibling, 1 reply; 8+ messages in thread
From: Lizhi Hou @ 2025-09-19 20:26 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, ilpo.jarvinen
  Cc: platform-driver-x86, Patil.Reddy


On 9/18/25 22:54, Shyam Sundar S K wrote:
> The PMF driver retrieves NPU metrics data from the PMFW. This commit
> introduces a new interface to make NPU metrics accessible to other
> drivers like AMDXDNA driver, which can access and utilize this
> information as needed.
>
> 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>
> ---
> Hi Ilpo, this can be applied on origin/review-ilpo-next with git tip commit
> "8236b4667aca"
>
>   drivers/platform/x86/amd/pmf/core.c | 60 +++++++++++++++++++++++++++++
>   drivers/platform/x86/amd/pmf/pmf.h  |  1 +
>   include/linux/amd-pmf-io.h          | 21 ++++++++++
>   3 files changed, 82 insertions(+)
>
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index ef988605c4da..75529047377c 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -8,6 +8,7 @@
>    * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>    */
>   
> +#include <linux/amd-pmf-io.h>
>   #include <linux/debugfs.h>
>   #include <linux/iopoll.h>
>   #include <linux/module.h>
> @@ -53,6 +54,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;
So there will never be more than one pmf device in the future?
> +
>   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 +317,61 @@ 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;
> +
> +	if (is_npu_metrics_supported(dev))
> +		return -EINVAL;
> +
> +	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, 0, 7, NULL);
s/0/false/ ?

What does the 7 mean? Is defining a macro better?

> +	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 = dev_get_drvdata(pmf);
Could 'pmf' be invalid pointer if the driver is unbound from the device?
> +
> +	if (!pdev || !info)
> +		return -EINVAL;
> +
> +	return amd_pmf_get_smu_metrics(pdev, info);
> +}
> +EXPORT_SYMBOL_GPL(amd_pmf_get_npu_data);
Should the interface be thread safe? I do not see any lock to protect 
dev->m_table_v2 or dev->buf.
> +
>   static int amd_pmf_suspend_handler(struct device *dev)
>   {
>   	struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
> @@ -431,6 +489,8 @@ static int amd_pmf_probe(struct platform_device *pdev)
>   
>   	dev->dev = &pdev->dev;
>   
> +	pmf = dev->dev;

Maybe set pmf after probe is success? And clear it in remove?

Because driver could be bound/unbound, simply using global pointer might 
be unreliable.


Thanks,

Lizhi

> +
>   	rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
>   	if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
>   		pci_dev_put(rdev);
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 6ea5380f3b23..622404e71136 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>
> 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] 8+ messages in thread

* Re: [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
  2025-09-19 14:21   ` Mario Limonciello
@ 2025-09-22 16:07     ` Shyam Sundar S K
  2025-09-22 16:19       ` Mario Limonciello (AMD) (kernel.org)
  0 siblings, 1 reply; 8+ messages in thread
From: Shyam Sundar S K @ 2025-09-22 16:07 UTC (permalink / raw)
  To: Mario Limonciello, hdegoede, ilpo.jarvinen, Lizhi Hou
  Cc: platform-driver-x86, Patil.Reddy



On 9/19/2025 19:51, Mario Limonciello wrote:
> On 9/19/2025 12:54 AM, Shyam Sundar S K wrote:
>> The PMF driver retrieves NPU metrics data from the PMFW. This commit
>> introduces a new interface to make NPU metrics accessible to other
>> drivers like AMDXDNA driver, which can access and utilize this
>> information as needed.
>>
>> 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 for comments.
> 
> As this interface will be something amdxdna uses I think we should
> make sure there is a R-b from Lizhi.

Sure.

> 
> I have a few comments below as well.
> 
>> ---
>> Hi Ilpo, this can be applied on origin/review-ilpo-next with git tip
>> commit
>> "8236b4667aca"
>>
>>   drivers/platform/x86/amd/pmf/core.c | 60 +++++++++++++++++++++++++
>> ++++
>>   drivers/platform/x86/amd/pmf/pmf.h  |  1 +
>>   include/linux/amd-pmf-io.h          | 21 ++++++++++
>>   3 files changed, 82 insertions(+)
>>
>> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/
>> x86/amd/pmf/core.c
>> index ef988605c4da..75529047377c 100644
>> --- a/drivers/platform/x86/amd/pmf/core.c
>> +++ b/drivers/platform/x86/amd/pmf/core.c
>> @@ -8,6 +8,7 @@
>>    * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>    */
>>   +#include <linux/amd-pmf-io.h>
>>   #include <linux/debugfs.h>
>>   #include <linux/iopoll.h>
>>   #include <linux/module.h>
>> @@ -53,6 +54,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;
>> +
>>   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 +317,61 @@ 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:
> 
> I'm a bit surprised AMD_CPU_ID_PS isn't in this list.  Does it not
> have the same interface?

Intial thoughts is to have support starting from 1Ah. Based on futher
tests we can extend this to older platforms as well, albeit I am not
sure if PMFW provides this information for older ones. So it would be
on the wishlist.


> 
>> +        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;
>> +
>> +    if (is_npu_metrics_supported(dev))
>> +        return -EINVAL;
>> +
>> +    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, 0, 7, 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 = dev_get_drvdata(pmf);
>> +
>> +    if (!pdev || !info)
>> +        return -EINVAL;
>> +
>> +    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);
>> @@ -431,6 +489,8 @@ static int amd_pmf_probe(struct platform_device
>> *pdev)
>>         dev->dev = &pdev->dev;
>>   +    pmf = dev->dev;
>> +
>>       rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
>>       if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
>>           pci_dev_put(rdev);
>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/
>> x86/amd/pmf/pmf.h
>> index 6ea5380f3b23..622404e71136 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>
>> 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];
> 
> This 8 comes from there being 8 columns, right?  What happens when we
> have a product with more?  It seems like this doesn't scale well
> outside of that design.
> 
> I know it is a simple memcpy() right now and the structure resembles
> the firmware structure, but would it make sense for inter-kernel
> commnication to define a different structure that would remain stable
> no matter how many columns?
> 
> Something like this:
> 
> struct amd_pmf_npu_metrics {
>     u16 npuclk_freq;
>     u16 npu_power;
>     u16 mpnpuclk_freq;
>     u16 npu_reads;
>     u16 npu_writes;
>     u8 npu_columns;
>     u16 *npu_busy;
> };
> 
> The size of npu_busy could be allocated dynamically, but this would
> also mean putting the responsibility of freeing it on the caller.
> 
> The alternative is of course a amd_pmf_npu_metrics_v2 if/when that
> happens.
> 

I can give it a shot. But I presume structure changes would not be
more frequent. So, I would still lean to having a _v2/_v3 whenever
that happens in the future.

Thanks,
Shyam


> I just thought it was worth considering right now.
>> +    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] 8+ messages in thread

* Re: [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
  2025-09-19 20:26   ` Lizhi Hou
@ 2025-09-22 16:08     ` Shyam Sundar S K
  0 siblings, 0 replies; 8+ messages in thread
From: Shyam Sundar S K @ 2025-09-22 16:08 UTC (permalink / raw)
  To: Lizhi Hou, hdegoede, ilpo.jarvinen; +Cc: platform-driver-x86, Patil.Reddy



On 9/20/2025 01:56, Lizhi Hou wrote:
> 
> On 9/18/25 22:54, Shyam Sundar S K wrote:
>> The PMF driver retrieves NPU metrics data from the PMFW. This commit
>> introduces a new interface to make NPU metrics accessible to other
>> drivers like AMDXDNA driver, which can access and utilize this
>> information as needed.
>>
>> 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>
>> ---
>> Hi Ilpo, this can be applied on origin/review-ilpo-next with git tip
>> commit
>> "8236b4667aca"
>>
>>   drivers/platform/x86/amd/pmf/core.c | 60 +++++++++++++++++++++++++
>> ++++
>>   drivers/platform/x86/amd/pmf/pmf.h  |  1 +
>>   include/linux/amd-pmf-io.h          | 21 ++++++++++
>>   3 files changed, 82 insertions(+)
>>
>> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/
>> x86/amd/pmf/core.c
>> index ef988605c4da..75529047377c 100644
>> --- a/drivers/platform/x86/amd/pmf/core.c
>> +++ b/drivers/platform/x86/amd/pmf/core.c
>> @@ -8,6 +8,7 @@
>>    * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>    */
>>   +#include <linux/amd-pmf-io.h>
>>   #include <linux/debugfs.h>
>>   #include <linux/iopoll.h>
>>   #include <linux/module.h>
>> @@ -53,6 +54,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;
> So there will never be more than one pmf device in the future?
>> +
>>   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 +317,61 @@ 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;
>> +
>> +    if (is_npu_metrics_supported(dev))
>> +        return -EINVAL;
>> +
>> +    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, 0, 7, NULL);
> s/0/false/ ?
> 
> What does the 7 mean? Is defining a macro better?
> 
>> +    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 = dev_get_drvdata(pmf);
> Could 'pmf' be invalid pointer if the driver is unbound from the device?
>> +
>> +    if (!pdev || !info)
>> +        return -EINVAL;
>> +
>> +    return amd_pmf_get_smu_metrics(pdev, info);
>> +}
>> +EXPORT_SYMBOL_GPL(amd_pmf_get_npu_data);
> Should the interface be thread safe? I do not see any lock to protect
> dev->m_table_v2 or dev->buf.
>> +
>>   static int amd_pmf_suspend_handler(struct device *dev)
>>   {
>>       struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
>> @@ -431,6 +489,8 @@ static int amd_pmf_probe(struct platform_device
>> *pdev)
>>         dev->dev = &pdev->dev;
>>   +    pmf = dev->dev;
> 
> Maybe set pmf after probe is success? And clear it in remove?
> 
> Because driver could be bound/unbound, simply using global pointer
> might be unreliable.
> 

Ack for all your comments. I will address them in v2.

Thanks,
Shyam

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics
  2025-09-22 16:07     ` Shyam Sundar S K
@ 2025-09-22 16:19       ` Mario Limonciello (AMD) (kernel.org)
  0 siblings, 0 replies; 8+ messages in thread
From: Mario Limonciello (AMD) (kernel.org) @ 2025-09-22 16:19 UTC (permalink / raw)
  To: Shyam Sundar S K, hdegoede, ilpo.jarvinen, Lizhi Hou
  Cc: platform-driver-x86, Patil.Reddy



On 9/22/2025 11:07 AM, Shyam Sundar S K wrote:
> 
> 
> On 9/19/2025 19:51, Mario Limonciello wrote:
>> On 9/19/2025 12:54 AM, Shyam Sundar S K wrote:
>>> The PMF driver retrieves NPU metrics data from the PMFW. This commit
>>> introduces a new interface to make NPU metrics accessible to other
>>> drivers like AMDXDNA driver, which can access and utilize this
>>> information as needed.
>>>
>>> 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 for comments.
>>
>> As this interface will be something amdxdna uses I think we should
>> make sure there is a R-b from Lizhi.
> 
> Sure.

With the comments you shared I personally have no concerns that need 
addressing.

Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>

> 
>>
>> I have a few comments below as well.
>>
>>> ---
>>> Hi Ilpo, this can be applied on origin/review-ilpo-next with git tip
>>> commit
>>> "8236b4667aca"
>>>
>>>    drivers/platform/x86/amd/pmf/core.c | 60 +++++++++++++++++++++++++
>>> ++++
>>>    drivers/platform/x86/amd/pmf/pmf.h  |  1 +
>>>    include/linux/amd-pmf-io.h          | 21 ++++++++++
>>>    3 files changed, 82 insertions(+)
>>>
>>> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/
>>> x86/amd/pmf/core.c
>>> index ef988605c4da..75529047377c 100644
>>> --- a/drivers/platform/x86/amd/pmf/core.c
>>> +++ b/drivers/platform/x86/amd/pmf/core.c
>>> @@ -8,6 +8,7 @@
>>>     * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>>     */
>>>    +#include <linux/amd-pmf-io.h>
>>>    #include <linux/debugfs.h>
>>>    #include <linux/iopoll.h>
>>>    #include <linux/module.h>
>>> @@ -53,6 +54,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;
>>> +
>>>    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 +317,61 @@ 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:
>>
>> I'm a bit surprised AMD_CPU_ID_PS isn't in this list.  Does it not
>> have the same interface?
> 
> Intial thoughts is to have support starting from 1Ah. Based on futher
> tests we can extend this to older platforms as well, albeit I am not
> sure if PMFW provides this information for older ones. So it would be
> on the wishlist.

Got it, thanks for clarification.

> 
> 
>>
>>> +        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;
>>> +
>>> +    if (is_npu_metrics_supported(dev))
>>> +        return -EINVAL;
>>> +
>>> +    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, 0, 7, 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 = dev_get_drvdata(pmf);
>>> +
>>> +    if (!pdev || !info)
>>> +        return -EINVAL;
>>> +
>>> +    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);
>>> @@ -431,6 +489,8 @@ static int amd_pmf_probe(struct platform_device
>>> *pdev)
>>>          dev->dev = &pdev->dev;
>>>    +    pmf = dev->dev;
>>> +
>>>        rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
>>>        if (!rdev || !pci_match_id(pmf_pci_ids, rdev)) {
>>>            pci_dev_put(rdev);
>>> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/
>>> x86/amd/pmf/pmf.h
>>> index 6ea5380f3b23..622404e71136 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>
>>> 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];
>>
>> This 8 comes from there being 8 columns, right?  What happens when we
>> have a product with more?  It seems like this doesn't scale well
>> outside of that design.
>>
>> I know it is a simple memcpy() right now and the structure resembles
>> the firmware structure, but would it make sense for inter-kernel
>> commnication to define a different structure that would remain stable
>> no matter how many columns?
>>
>> Something like this:
>>
>> struct amd_pmf_npu_metrics {
>>      u16 npuclk_freq;
>>      u16 npu_power;
>>      u16 mpnpuclk_freq;
>>      u16 npu_reads;
>>      u16 npu_writes;
>>      u8 npu_columns;
>>      u16 *npu_busy;
>> };
>>
>> The size of npu_busy could be allocated dynamically, but this would
>> also mean putting the responsibility of freeing it on the caller.
>>
>> The alternative is of course a amd_pmf_npu_metrics_v2 if/when that
>> happens.
>>
> 
> I can give it a shot. But I presume structure changes would not be
> more frequent. So, I would still lean to having a _v2/_v3 whenever
> that happens in the future.
> 

Yeah if it's not going to be a frequent update, it might not be worth 
the extra complexity.  You can make a decision here, and if you want to 
stick with what you've got that is fine.

> Thanks,
> Shyam
> 
> 
>> I just thought it was worth considering right now.
>>> +    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] 8+ messages in thread

end of thread, other threads:[~2025-09-22 16:19 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-19  5:54 [PATCH 1/2] platform/x86/amd/pmf: Rename ipu fields to npu in smu_pmf_metrics_v2 structure Shyam Sundar S K
2025-09-19  5:54 ` [PATCH 2/2] platform/x86/amd/pmf: Introduce new interface to export NPU metrics Shyam Sundar S K
2025-09-19 14:21   ` Mario Limonciello
2025-09-22 16:07     ` Shyam Sundar S K
2025-09-22 16:19       ` Mario Limonciello (AMD) (kernel.org)
2025-09-19 20:26   ` Lizhi Hou
2025-09-22 16:08     ` Shyam Sundar S K
2025-09-19 14:06 ` [PATCH 1/2] platform/x86/amd/pmf: Rename ipu fields to npu in smu_pmf_metrics_v2 structure Mario Limonciello (AMD) (kernel.org)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).