[PATCH V3 3/3] drm/amdgpu/smu15: set up metrics DRAM mapping and prev buffer once

Shubhankar Milind Sardeshpande <[email protected]> Fri, 24 Jul 2026 17:33:44 +0530
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
The metrics path re-resolved and ioremap()'d the firmware log DRAM
address on every read, and kzalloc()/kfree()'d a previous-sample
scratch buffer on every sensor query.

Set both up once at table init and tear them down at fini:

- Add cpu_addr and prev_metrics to SMU_15_0_0_MetricsInfo_t.
- Add smu_v15_0_0_get_metrics_table_dram_addr() to query the address
  and ioremap_wc() it from init_smc_tables(); allocate prev_metrics
  there too, extending the error-unwind ladder.
- get_metrics_table() reuses the persistent cpu_addr.
- get_smu_metrics_data() reuses the persistent prev_metrics buffer.
- fini_smc_tables() iounmap()s cpu_addr and frees prev_metrics.

Signed-off-by: Shubhankar Milind Sardeshpande <[email protected]>
---
 .../drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c  | 99 +++++++++++--------
 .../drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.h  |  2 +
 2 files changed, 62 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
index 1d268a02992e..31cf538246fa 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
@@ -165,10 +165,37 @@ static struct cmn2asic_mapping smu_v15_0_0_table_map[SMU_TABLE_COUNT] = {
 	TAB_MAP_VALID(DPMCLOCKS),
 };
 
+static int smu_v15_0_0_get_metrics_table_dram_addr(struct smu_context *smu,
+					SMU_15_0_0_MetricsInfo_t *metrics_info)
+{
+	struct smu_msg_ctl *ctl = &smu->msg_ctl;
+	struct smu_msg_args args = {
+		.msg = SMU_MSG_GetMetricsTableLogDramAddr,
+		.num_args = 0,
+		.num_out_args = 3,
+	};
+	int ret;
+
+	ret = ctl->ops->send_msg(ctl, &args);
+	if (ret)
+		return ret;
+
+	metrics_info->addr = ((uint64_t)args.out_args[1] << 32) | args.out_args[0];
+	metrics_info->table_size = args.out_args[2];
+
+	metrics_info->cpu_addr = ioremap_wc(metrics_info->addr,
+					    metrics_info->table_size);
+	if (!metrics_info->cpu_addr)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int smu_v15_0_0_init_smc_tables(struct smu_context *smu)
 {
 	struct smu_table_context *smu_table = &smu->smu_table;
 	struct smu_table *tables = smu_table->tables;
+	SMU_15_0_0_MetricsInfo_t *metrics_info;
 	int ret;
 
 	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
@@ -197,8 +224,24 @@ static int smu_v15_0_0_init_smc_tables(struct smu_context *smu)
 	if (ret)
 		goto err3_out;
 
+	metrics_info = (SMU_15_0_0_MetricsInfo_t *)smu_table->metrics_table;
+
+	metrics_info->prev_metrics = kzalloc_obj(SMU_15_0_0_MetricsInfo_t);
+	if (!metrics_info->prev_metrics)
+		goto err4_out;
+
+	if (metrics_info->addr == 0) {
+		ret = smu_v15_0_0_get_metrics_table_dram_addr(smu, metrics_info);
+		if (ret)
+			goto err5_out;
+	}
+
 	return 0;
 
+err5_out:
+	kfree(metrics_info->prev_metrics);
+err4_out:
+	smu_driver_table_fini(smu, SMU_DRIVER_TABLE_GPU_METRICS);
 err3_out:
 	kfree(smu_table->watermarks_table);
 err2_out:
@@ -212,6 +255,16 @@ static int smu_v15_0_0_init_smc_tables(struct smu_context *smu)
 static int smu_v15_0_0_fini_smc_tables(struct smu_context *smu)
 {
 	struct smu_table_context *smu_table = &smu->smu_table;
+	SMU_15_0_0_MetricsInfo_t *metrics_info = smu_table->metrics_table;
+
+	if (metrics_info) {
+		if (metrics_info->cpu_addr) {
+			iounmap(metrics_info->cpu_addr);
+			metrics_info->cpu_addr = NULL;
+		}
+		kfree(metrics_info->prev_metrics);
+		metrics_info->prev_metrics = NULL;
+	}
 
 	kfree(smu_table->clocks_table);
 	smu_table->clocks_table = NULL;
@@ -334,41 +387,20 @@ static int smu_v15_0_0_get_gpu_metrics_table(struct smu_context *smu,
 	return 0;
 }
 
-
 static int smu_v15_0_0_get_metrics_table(struct smu_context *smu,
 					SMU_15_0_0_MetricsInfo_t *metrics_info)
 {
 	struct smu_table_context *smu_table = &smu->smu_table;
-	void __iomem *cpu_addr = NULL;
+	void __iomem *cpu_addr = metrics_info->cpu_addr;
 	struct smu_msg_ctl *ctl = &smu->msg_ctl;
 	struct smu_msg_args args = {0};
 	int table_size = metrics_info->table_size;
-	uint64_t addr = metrics_info->addr;
 	int ret;
 
 	if (smu_table->metrics_time &&
 	    !time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1)))
 		return 0;
 
-	if (addr == 0) {
-		struct smu_msg_args args = {
-			.msg = SMU_MSG_GetMetricsTableLogDramAddr,
-			.num_args = 0,
-			.num_out_args = 3,
-		};
-
-		ret = ctl->ops->send_msg(ctl, &args);
-
-		if (ret)
-			return ret;
-
-		addr = ((uint64_t)args.out_args[1] << 32) | args.out_args[0];
-		table_size = args.out_args[2];
-		metrics_info->addr = addr;
-		metrics_info->table_size = table_size;
-	}
-
-	cpu_addr = ioremap_wc(addr, table_size);
 	if (!cpu_addr)
 		return -ENOMEM;
 
@@ -384,7 +416,6 @@ static int smu_v15_0_0_get_metrics_table(struct smu_context *smu,
 		else
 			memcpy(&metrics_info->metrics, cpu_addr, sizeof(MetricsTable_t));
 	}
-	iounmap(cpu_addr);
 	return ret;
 }
 
@@ -455,25 +486,16 @@ static int smu_v15_0_0_get_smu_metrics_data(struct smu_context *smu,
 					    uint32_t *value)
 {
 	struct smu_table_context *smu_table = &smu->smu_table;
-
-	SMU_15_0_0_MetricsInfo_t *prev_metrics;
-	SMU_15_0_0_MetricsInfo_t *curr_metrics;
+	SMU_15_0_0_MetricsInfo_t *curr_metrics =
+		(SMU_15_0_0_MetricsInfo_t *)smu_table->metrics_table;
+	SMU_15_0_0_MetricsInfo_t *prev_metrics = curr_metrics->prev_metrics;
 	int ret;
 
-	prev_metrics = kzalloc_obj(SMU_15_0_0_MetricsInfo_t);
-	if (!prev_metrics)
-		return -ENOMEM;
-
-	memcpy(prev_metrics, smu_table->metrics_table,
+	memcpy(prev_metrics, curr_metrics,
 			sizeof(SMU_15_0_0_MetricsInfo_t));
-	ret = smu_v15_0_0_get_metrics_table(smu,
-			(SMU_15_0_0_MetricsInfo_t *)smu_table->metrics_table);
-	if (ret) {
-		kfree(prev_metrics);
+	ret = smu_v15_0_0_get_metrics_table(smu, curr_metrics);
+	if (ret)
 		return ret;
-	}
-
-	curr_metrics = (SMU_15_0_0_MetricsInfo_t *)smu_table->metrics_table;
 
 	if (prev_metrics->metrics.IOD.AccumulationCounter !=
 		curr_metrics->metrics.IOD.AccumulationCounter) {
@@ -483,7 +505,6 @@ static int smu_v15_0_0_get_smu_metrics_data(struct smu_context *smu,
 
 	*value = curr_metrics->avg_metric[member];
 
-	kfree(prev_metrics);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.h
index 8ee45591e9a6..27e7c60be15c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.h
@@ -31,6 +31,8 @@ typedef struct {
 	MetricsTable_t metrics;
 	uint32_t table_size;
 	uint64_t addr;
+	void __iomem *cpu_addr;
+	void *prev_metrics;
 	uint32_t avg_metric[METRICS_AVERAGE_NPUCLK+1];
 } SMU_15_0_0_MetricsInfo_t;
 
-- 
2.43.0