xref: /linux/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c (revision e9ef810dfee7a2227da9d423aecb0ced35faddbe)
1 /*
2  * Copyright 2021 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 
24 #define SWSMU_CODE_LAYER_L2
25 
26 #include <linux/firmware.h>
27 #include "amdgpu.h"
28 #include "amdgpu_smu.h"
29 #include "smu_v13_0_12_pmfw.h"
30 #include "smu_v13_0_6_ppt.h"
31 #include "smu_v13_0_12_ppsmc.h"
32 #include "smu_v13_0.h"
33 #include "amdgpu_xgmi.h"
34 #include "amdgpu_fru_eeprom.h"
35 #include <linux/pci.h>
36 #include "smu_cmn.h"
37 
38 #undef MP1_Public
39 #undef smnMP1_FIRMWARE_FLAGS
40 
41 /*
42  * DO NOT use these for err/warn/info/debug messages.
43  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
44  * They are more MGPU friendly.
45  */
46 #undef pr_err
47 #undef pr_warn
48 #undef pr_info
49 #undef pr_debug
50 
51 #define SMU_13_0_12_FEA_MAP(smu_feature, smu_13_0_12_feature)                    \
52 	[smu_feature] = { 1, (smu_13_0_12_feature) }
53 
54 #define FEATURE_MASK(feature) (1ULL << feature)
55 #define SMC_DPM_FEATURE                                                        \
56 	(FEATURE_MASK(FEATURE_DATA_CALCULATION) |                              \
57 	 FEATURE_MASK(FEATURE_DPM_GFXCLK) | FEATURE_MASK(FEATURE_DPM_FCLK))
58 
59 #define NUM_JPEG_RINGS_FW	10
60 #define NUM_JPEG_RINGS_GPU_METRICS(gpu_metrics) \
61 	(ARRAY_SIZE(gpu_metrics->xcp_stats[0].jpeg_busy) / 4)
62 
63 const struct cmn2asic_mapping smu_v13_0_12_feature_mask_map[SMU_FEATURE_COUNT] = {
64 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DATA_CALCULATIONS_BIT, 		FEATURE_DATA_CALCULATION),
65 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DPM_GFXCLK_BIT, 		FEATURE_DPM_GFXCLK),
66 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DPM_FCLK_BIT, 			FEATURE_DPM_FCLK),
67 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DS_GFXCLK_BIT, 			FEATURE_DS_GFXCLK),
68 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DS_SOCCLK_BIT, 			FEATURE_DS_SOCCLK),
69 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DS_LCLK_BIT, 			FEATURE_DS_LCLK),
70 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DS_FCLK_BIT, 			FEATURE_DS_FCLK),
71 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_PPT_BIT, 			FEATURE_PPT),
72 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_TDC_BIT, 			FEATURE_TDC),
73 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_APCC_DFLL_BIT, 			FEATURE_APCC_DFLL),
74 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_MP1_CG_BIT, 			FEATURE_SMU_CG),
75 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_FW_CTF_BIT, 			FEATURE_FW_CTF),
76 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_THERMAL_BIT, 			FEATURE_THERMAL),
77 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_SOC_PCC_BIT, 			FEATURE_SOC_PCC),
78 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_XGMI_PER_LINK_PWR_DWN_BIT,	FEATURE_XGMI_PER_LINK_PWR_DOWN),
79 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DS_VCN_BIT,			FEATURE_DS_VCN),
80 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DS_MP1CLK_BIT,			FEATURE_DS_MP1CLK),
81 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DS_MPIOCLK_BIT,			FEATURE_DS_MPIOCLK),
82 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_DS_MP0CLK_BIT,			FEATURE_DS_MP0CLK),
83 	SMU_13_0_12_FEA_MAP(SMU_FEATURE_PIT_BIT,			FEATURE_PIT),
84 };
85 
86 // clang-format off
87 const struct cmn2asic_msg_mapping smu_v13_0_12_message_map[SMU_MSG_MAX_COUNT] = {
88 	MSG_MAP(TestMessage,			     PPSMC_MSG_TestMessage,			0),
89 	MSG_MAP(GetSmuVersion,			     PPSMC_MSG_GetSmuVersion,			1),
90 	MSG_MAP(GetDriverIfVersion,		     PPSMC_MSG_GetDriverIfVersion,		1),
91 	MSG_MAP(EnableAllSmuFeatures,		     PPSMC_MSG_EnableAllSmuFeatures,		0),
92 	MSG_MAP(DisableAllSmuFeatures,		     PPSMC_MSG_DisableAllSmuFeatures,		0),
93 	MSG_MAP(RequestI2cTransaction,		     PPSMC_MSG_RequestI2cTransaction,		0),
94 	MSG_MAP(GetMetricsTable,		     PPSMC_MSG_GetMetricsTable,			1),
95 	MSG_MAP(GetMetricsVersion,		     PPSMC_MSG_GetMetricsVersion,		1),
96 	MSG_MAP(GetEnabledSmuFeaturesHigh,	     PPSMC_MSG_GetEnabledSmuFeaturesHigh,	1),
97 	MSG_MAP(GetEnabledSmuFeaturesLow,	     PPSMC_MSG_GetEnabledSmuFeaturesLow,	1),
98 	MSG_MAP(SetDriverDramAddrHigh,		     PPSMC_MSG_SetDriverDramAddrHigh,		1),
99 	MSG_MAP(SetDriverDramAddrLow,		     PPSMC_MSG_SetDriverDramAddrLow,		1),
100 	MSG_MAP(SetToolsDramAddrHigh,		     PPSMC_MSG_SetToolsDramAddrHigh,		0),
101 	MSG_MAP(SetToolsDramAddrLow,		     PPSMC_MSG_SetToolsDramAddrLow,		0),
102 	MSG_MAP(SetSoftMinByFreq,		     PPSMC_MSG_SetSoftMinByFreq,		0),
103 	MSG_MAP(SetSoftMaxByFreq,		     PPSMC_MSG_SetSoftMaxByFreq,		1),
104 	MSG_MAP(GetMinDpmFreq,			     PPSMC_MSG_GetMinDpmFreq,			1),
105 	MSG_MAP(GetMaxDpmFreq,			     PPSMC_MSG_GetMaxDpmFreq,			1),
106 	MSG_MAP(GetDpmFreqByIndex,		     PPSMC_MSG_GetDpmFreqByIndex,		1),
107 	MSG_MAP(SetPptLimit,			     PPSMC_MSG_SetPptLimit,			0),
108 	MSG_MAP(GetPptLimit,			     PPSMC_MSG_GetPptLimit,			1),
109 	MSG_MAP(GfxDeviceDriverReset,		     PPSMC_MSG_GfxDriverReset,			SMU_MSG_RAS_PRI),
110 	MSG_MAP(DramLogSetDramAddrHigh,		     PPSMC_MSG_DramLogSetDramAddrHigh,		0),
111 	MSG_MAP(DramLogSetDramAddrLow,		     PPSMC_MSG_DramLogSetDramAddrLow,		0),
112 	MSG_MAP(DramLogSetDramSize,		     PPSMC_MSG_DramLogSetDramSize,		0),
113 	MSG_MAP(GetDebugData,			     PPSMC_MSG_GetDebugData,			0),
114 	MSG_MAP(SetNumBadHbmPagesRetired,	     PPSMC_MSG_SetNumBadHbmPagesRetired,	0),
115 	MSG_MAP(DFCstateControl,		     PPSMC_MSG_DFCstateControl,			0),
116 	MSG_MAP(GetGmiPwrDnHyst,		     PPSMC_MSG_GetGmiPwrDnHyst,			0),
117 	MSG_MAP(SetGmiPwrDnHyst,		     PPSMC_MSG_SetGmiPwrDnHyst,			0),
118 	MSG_MAP(GmiPwrDnControl,		     PPSMC_MSG_GmiPwrDnControl,			0),
119 	MSG_MAP(EnterGfxoff,			     PPSMC_MSG_EnterGfxoff,			0),
120 	MSG_MAP(ExitGfxoff,			     PPSMC_MSG_ExitGfxoff,			0),
121 	MSG_MAP(EnableDeterminism,		     PPSMC_MSG_EnableDeterminism,		0),
122 	MSG_MAP(DisableDeterminism,		     PPSMC_MSG_DisableDeterminism,		0),
123 	MSG_MAP(GfxDriverResetRecovery,		     PPSMC_MSG_GfxDriverResetRecovery,		0),
124 	MSG_MAP(GetMinGfxclkFrequency,               PPSMC_MSG_GetMinGfxDpmFreq,                1),
125 	MSG_MAP(GetMaxGfxclkFrequency,               PPSMC_MSG_GetMaxGfxDpmFreq,                1),
126 	MSG_MAP(SetSoftMinGfxclk,                    PPSMC_MSG_SetSoftMinGfxClk,                1),
127 	MSG_MAP(SetSoftMaxGfxClk,                    PPSMC_MSG_SetSoftMaxGfxClk,                1),
128 	MSG_MAP(PrepareMp1ForUnload,                 PPSMC_MSG_PrepareForDriverUnload,          0),
129 	MSG_MAP(GetCTFLimit,                         PPSMC_MSG_GetCTFLimit,                     0),
130 	MSG_MAP(GetThermalLimit,                     PPSMC_MSG_ReadThrottlerLimit,              0),
131 	MSG_MAP(ClearMcaOnRead,	                     PPSMC_MSG_ClearMcaOnRead,                  0),
132 	MSG_MAP(QueryValidMcaCount,                  PPSMC_MSG_QueryValidMcaCount,              SMU_MSG_RAS_PRI),
133 	MSG_MAP(QueryValidMcaCeCount,                PPSMC_MSG_QueryValidMcaCeCount,            SMU_MSG_RAS_PRI),
134 	MSG_MAP(McaBankDumpDW,                       PPSMC_MSG_McaBankDumpDW,                   SMU_MSG_RAS_PRI),
135 	MSG_MAP(McaBankCeDumpDW,                     PPSMC_MSG_McaBankCeDumpDW,                 SMU_MSG_RAS_PRI),
136 	MSG_MAP(SelectPLPDMode,                      PPSMC_MSG_SelectPLPDMode,                  0),
137 	MSG_MAP(RmaDueToBadPageThreshold,            PPSMC_MSG_RmaDueToBadPageThreshold,        0),
138 	MSG_MAP(SetThrottlingPolicy,                 PPSMC_MSG_SetThrottlingPolicy,             0),
139 	MSG_MAP(ResetSDMA,                           PPSMC_MSG_ResetSDMA,                       0),
140 	MSG_MAP(GetStaticMetricsTable,               PPSMC_MSG_GetStaticMetricsTable,           1),
141 };
142 
smu_v13_0_12_get_enabled_mask(struct smu_context * smu,uint64_t * feature_mask)143 static int smu_v13_0_12_get_enabled_mask(struct smu_context *smu,
144 					 uint64_t *feature_mask)
145 {
146 	int ret;
147 
148 	ret = smu_cmn_get_enabled_mask(smu, feature_mask);
149 
150 	if (ret == -EIO) {
151 		*feature_mask = 0;
152 		ret = 0;
153 	}
154 
155 	return ret;
156 }
157 
smu_v13_0_12_fru_get_product_info(struct smu_context * smu,StaticMetricsTable_t * static_metrics)158 static int smu_v13_0_12_fru_get_product_info(struct smu_context *smu,
159 					     StaticMetricsTable_t *static_metrics)
160 {
161 	struct amdgpu_fru_info *fru_info;
162 	struct amdgpu_device *adev = smu->adev;
163 
164 	if (!adev->fru_info) {
165 		adev->fru_info = kzalloc(sizeof(*adev->fru_info), GFP_KERNEL);
166 		if (!adev->fru_info)
167 			return -ENOMEM;
168 	}
169 
170 	fru_info = adev->fru_info;
171 	strscpy(fru_info->product_number, static_metrics->ProductInfo.ModelNumber,
172 		sizeof(fru_info->product_number));
173 	strscpy(fru_info->product_name, static_metrics->ProductInfo.Name,
174 		sizeof(fru_info->product_name));
175 	strscpy(fru_info->serial, static_metrics->ProductInfo.Serial,
176 		sizeof(fru_info->serial));
177 	strscpy(fru_info->manufacturer_name, static_metrics->ProductInfo.ManufacturerName,
178 		sizeof(fru_info->manufacturer_name));
179 	strscpy(fru_info->fru_id, static_metrics->ProductInfo.FruId,
180 		sizeof(fru_info->fru_id));
181 
182 	return 0;
183 }
184 
smu_v13_0_12_get_max_metrics_size(void)185 int smu_v13_0_12_get_max_metrics_size(void)
186 {
187 	return max(sizeof(StaticMetricsTable_t), sizeof(MetricsTable_t));
188 }
189 
smu_v13_0_12_init_xgmi_data(struct smu_context * smu,StaticMetricsTable_t * static_metrics)190 static void smu_v13_0_12_init_xgmi_data(struct smu_context *smu,
191 					StaticMetricsTable_t *static_metrics)
192 {
193 	struct smu_table_context *smu_table = &smu->smu_table;
194 	uint16_t max_speed;
195 	uint8_t max_width;
196 	int ret;
197 
198 	if (smu_table->tables[SMU_TABLE_SMU_METRICS].version >= 0x13) {
199 		max_width = (uint8_t)static_metrics->MaxXgmiWidth;
200 		max_speed = (uint16_t)static_metrics->MaxXgmiBitrate;
201 		ret = 0;
202 	} else {
203 		MetricsTable_t *metrics = (MetricsTable_t *)smu_table->metrics_table;
204 
205 		ret = smu_v13_0_6_get_metrics_table(smu, NULL, true);
206 		if (!ret) {
207 			max_width = (uint8_t)metrics->XgmiWidth;
208 			max_speed = (uint16_t)metrics->XgmiBitrate;
209 		}
210 	}
211 	if (!ret)
212 		amgpu_xgmi_set_max_speed_width(smu->adev, max_speed, max_width);
213 }
214 
smu_v13_0_12_setup_driver_pptable(struct smu_context * smu)215 int smu_v13_0_12_setup_driver_pptable(struct smu_context *smu)
216 {
217 	struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
218 	struct smu_table_context *smu_table = &smu->smu_table;
219 	StaticMetricsTable_t *static_metrics = (StaticMetricsTable_t *)smu_table->metrics_table;
220 	struct PPTable_t *pptable =
221 		(struct PPTable_t *)smu_table->driver_pptable;
222 	uint32_t table_version;
223 	int ret, i;
224 
225 	if (!pptable->Init) {
226 		ret = smu_v13_0_6_get_static_metrics_table(smu);
227 		if (ret)
228 			return ret;
229 
230 		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMetricsVersion,
231 					   &table_version);
232 		if (ret)
233 			return ret;
234 		smu_table->tables[SMU_TABLE_SMU_METRICS].version =
235 			table_version;
236 
237 		pptable->MaxSocketPowerLimit =
238 			SMUQ10_ROUND(static_metrics->MaxSocketPowerLimit);
239 		pptable->MaxGfxclkFrequency =
240 			SMUQ10_ROUND(static_metrics->MaxGfxclkFrequency);
241 		pptable->MinGfxclkFrequency =
242 			SMUQ10_ROUND(static_metrics->MinGfxclkFrequency);
243 
244 		for (i = 0; i < 4; ++i) {
245 			pptable->FclkFrequencyTable[i] =
246 				SMUQ10_ROUND(static_metrics->FclkFrequencyTable[i]);
247 			pptable->UclkFrequencyTable[i] =
248 				SMUQ10_ROUND(static_metrics->UclkFrequencyTable[i]);
249 			pptable->SocclkFrequencyTable[i] =
250 				SMUQ10_ROUND(static_metrics->SocclkFrequencyTable[i]);
251 			pptable->VclkFrequencyTable[i] =
252 				SMUQ10_ROUND(static_metrics->VclkFrequencyTable[i]);
253 			pptable->DclkFrequencyTable[i] =
254 				SMUQ10_ROUND(static_metrics->DclkFrequencyTable[i]);
255 			pptable->LclkFrequencyTable[i] =
256 				SMUQ10_ROUND(static_metrics->LclkFrequencyTable[i]);
257 		}
258 
259 		/* use AID0 serial number by default */
260 		pptable->PublicSerialNumber_AID =
261 			static_metrics->PublicSerialNumber_AID[0];
262 		ret = smu_v13_0_12_fru_get_product_info(smu, static_metrics);
263 		if (ret)
264 			return ret;
265 
266 		if (smu_v13_0_6_cap_supported(smu, SMU_CAP(BOARD_VOLTAGE))) {
267 			if (!static_metrics->InputTelemetryVoltageInmV) {
268 				dev_warn(smu->adev->dev, "Invalid board voltage %d\n",
269 						static_metrics->InputTelemetryVoltageInmV);
270 			}
271 			dpm_context->board_volt = static_metrics->InputTelemetryVoltageInmV;
272 		}
273 		if (smu_v13_0_6_cap_supported(smu, SMU_CAP(PLDM_VERSION)) &&
274 			static_metrics->pldmVersion[0] != 0xFFFFFFFF)
275 			smu->adev->firmware.pldm_version =
276 				static_metrics->pldmVersion[0];
277 		smu_v13_0_12_init_xgmi_data(smu, static_metrics);
278 		pptable->Init = true;
279 	}
280 
281 	return 0;
282 }
283 
smu_v13_0_12_is_dpm_running(struct smu_context * smu)284 bool smu_v13_0_12_is_dpm_running(struct smu_context *smu)
285 {
286 	int ret;
287 	uint64_t feature_enabled;
288 
289 	ret = smu_v13_0_12_get_enabled_mask(smu, &feature_enabled);
290 
291 	if (ret)
292 		return false;
293 
294 	return !!(feature_enabled & SMC_DPM_FEATURE);
295 }
296 
smu_v13_0_12_get_smu_metrics_data(struct smu_context * smu,MetricsMember_t member,uint32_t * value)297 int smu_v13_0_12_get_smu_metrics_data(struct smu_context *smu,
298 				      MetricsMember_t member,
299 				      uint32_t *value)
300 {
301 	struct smu_table_context *smu_table = &smu->smu_table;
302 	MetricsTable_t *metrics = (MetricsTable_t *)smu_table->metrics_table;
303 	struct amdgpu_device *adev = smu->adev;
304 	int xcc_id;
305 
306 	/* For clocks with multiple instances, only report the first one */
307 	switch (member) {
308 	case METRICS_CURR_GFXCLK:
309 	case METRICS_AVERAGE_GFXCLK:
310 		xcc_id = GET_INST(GC, 0);
311 		*value = SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]);
312 		break;
313 	case METRICS_CURR_SOCCLK:
314 	case METRICS_AVERAGE_SOCCLK:
315 		*value = SMUQ10_ROUND(metrics->SocclkFrequency[0]);
316 		break;
317 	case METRICS_CURR_UCLK:
318 	case METRICS_AVERAGE_UCLK:
319 		*value = SMUQ10_ROUND(metrics->UclkFrequency);
320 		break;
321 	case METRICS_CURR_VCLK:
322 		*value = SMUQ10_ROUND(metrics->VclkFrequency[0]);
323 		break;
324 	case METRICS_CURR_DCLK:
325 		*value = SMUQ10_ROUND(metrics->DclkFrequency[0]);
326 		break;
327 	case METRICS_CURR_FCLK:
328 		*value = SMUQ10_ROUND(metrics->FclkFrequency);
329 		break;
330 	case METRICS_AVERAGE_GFXACTIVITY:
331 		*value = SMUQ10_ROUND(metrics->SocketGfxBusy);
332 		break;
333 	case METRICS_AVERAGE_MEMACTIVITY:
334 		*value = SMUQ10_ROUND(metrics->DramBandwidthUtilization);
335 		break;
336 	case METRICS_CURR_SOCKETPOWER:
337 		*value = SMUQ10_ROUND(metrics->SocketPower) << 8;
338 		break;
339 	case METRICS_TEMPERATURE_HOTSPOT:
340 		*value = SMUQ10_ROUND(metrics->MaxSocketTemperature) *
341 			 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
342 		break;
343 	case METRICS_TEMPERATURE_MEM:
344 		*value = SMUQ10_ROUND(metrics->MaxHbmTemperature) *
345 			 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
346 		break;
347 	/* This is the max of all VRs and not just SOC VR.
348 	 * No need to define another data type for the same.
349 	 */
350 	case METRICS_TEMPERATURE_VRSOC:
351 		*value = SMUQ10_ROUND(metrics->MaxVrTemperature) *
352 			 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
353 		break;
354 	default:
355 		*value = UINT_MAX;
356 		break;
357 	}
358 
359 	return 0;
360 }
361 
smu_v13_0_12_get_xcp_metrics(struct smu_context * smu,struct amdgpu_xcp * xcp,void * table,void * smu_metrics)362 ssize_t smu_v13_0_12_get_xcp_metrics(struct smu_context *smu, struct amdgpu_xcp *xcp, void *table, void *smu_metrics)
363 {
364 	const u8 num_jpeg_rings = NUM_JPEG_RINGS_FW;
365 	struct amdgpu_partition_metrics_v1_0 *xcp_metrics;
366 	struct amdgpu_device *adev = smu->adev;
367 	MetricsTable_t *metrics;
368 	int inst, j, k, idx;
369 	u32 inst_mask;
370 
371 	metrics = (MetricsTable_t *)smu_metrics;
372 	xcp_metrics = (struct amdgpu_partition_metrics_v1_0 *) table;
373 	smu_cmn_init_partition_metrics(xcp_metrics, 1, 0);
374 	amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_VCN, &inst_mask);
375 	idx = 0;
376 	for_each_inst(k, inst_mask) {
377 		/* Both JPEG and VCN has same instance */
378 		inst = GET_INST(VCN, k);
379 		for (j = 0; j < num_jpeg_rings; ++j) {
380 			xcp_metrics->jpeg_busy[(idx * num_jpeg_rings) + j] =
381 				SMUQ10_ROUND(metrics->
382 					JpegBusy[(inst * num_jpeg_rings) + j]);
383 		}
384 		xcp_metrics->vcn_busy[idx] =
385 			SMUQ10_ROUND(metrics->VcnBusy[inst]);
386 		xcp_metrics->current_vclk0[idx] = SMUQ10_ROUND(
387 			metrics->VclkFrequency[inst]);
388 		xcp_metrics->current_dclk0[idx] = SMUQ10_ROUND(
389 			metrics->DclkFrequency[inst]);
390 		xcp_metrics->current_socclk[idx] = SMUQ10_ROUND(
391 			metrics->SocclkFrequency[inst]);
392 
393 		idx++;
394 	}
395 
396 	xcp_metrics->current_uclk =
397 		SMUQ10_ROUND(metrics->UclkFrequency);
398 
399 	amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_GFX, &inst_mask);
400 	idx = 0;
401 	for_each_inst(k, inst_mask) {
402 		inst = GET_INST(GC, k);
403 		xcp_metrics->current_gfxclk[idx] = SMUQ10_ROUND(metrics->GfxclkFrequency[inst]);
404 		xcp_metrics->gfx_busy_inst[idx] = SMUQ10_ROUND(metrics->GfxBusy[inst]);
405 		xcp_metrics->gfx_busy_acc[idx] = SMUQ10_ROUND(metrics->GfxBusyAcc[inst]);
406 		if (smu_v13_0_6_cap_supported(smu, SMU_CAP(HST_LIMIT_METRICS))) {
407 			xcp_metrics->gfx_below_host_limit_ppt_acc[idx] = SMUQ10_ROUND(metrics->GfxclkBelowHostLimitPptAcc[inst]);
408 			xcp_metrics->gfx_below_host_limit_thm_acc[idx] = SMUQ10_ROUND(metrics->GfxclkBelowHostLimitThmAcc[inst]);
409 			xcp_metrics->gfx_low_utilization_acc[idx] = SMUQ10_ROUND(metrics->GfxclkLowUtilizationAcc[inst]);
410 			xcp_metrics->gfx_below_host_limit_total_acc[idx] = SMUQ10_ROUND(metrics->GfxclkBelowHostLimitTotalAcc[inst]);
411 		}
412 		idx++;
413 	}
414 
415 	return sizeof(*xcp_metrics);
416 }
417 
smu_v13_0_12_get_gpu_metrics(struct smu_context * smu,void ** table,void * smu_metrics)418 ssize_t smu_v13_0_12_get_gpu_metrics(struct smu_context *smu, void **table, void *smu_metrics)
419 {
420 	struct smu_table_context *smu_table = &smu->smu_table;
421 	struct gpu_metrics_v1_8 *gpu_metrics =
422 		(struct gpu_metrics_v1_8 *)smu_table->gpu_metrics_table;
423 	int ret = 0, xcc_id, inst, i, j, k, idx;
424 	struct amdgpu_device *adev = smu->adev;
425 	u8 num_jpeg_rings_gpu_metrics;
426 	MetricsTable_t *metrics;
427 	struct amdgpu_xcp *xcp;
428 	u32 inst_mask;
429 
430 	metrics = (MetricsTable_t *)smu_metrics;
431 
432 	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 8);
433 
434 	gpu_metrics->temperature_hotspot =
435 		SMUQ10_ROUND(metrics->MaxSocketTemperature);
436 	/* Individual HBM stack temperature is not reported */
437 	gpu_metrics->temperature_mem =
438 		SMUQ10_ROUND(metrics->MaxHbmTemperature);
439 	/* Reports max temperature of all voltage rails */
440 	gpu_metrics->temperature_vrsoc =
441 		SMUQ10_ROUND(metrics->MaxVrTemperature);
442 
443 	gpu_metrics->average_gfx_activity =
444 		SMUQ10_ROUND(metrics->SocketGfxBusy);
445 	gpu_metrics->average_umc_activity =
446 		SMUQ10_ROUND(metrics->DramBandwidthUtilization);
447 
448 	gpu_metrics->mem_max_bandwidth =
449 		SMUQ10_ROUND(metrics->MaxDramBandwidth);
450 
451 	gpu_metrics->curr_socket_power =
452 		SMUQ10_ROUND(metrics->SocketPower);
453 	/* Energy counter reported in 15.259uJ (2^-16) units */
454 	gpu_metrics->energy_accumulator = metrics->SocketEnergyAcc;
455 
456 	for (i = 0; i < MAX_GFX_CLKS; i++) {
457 		xcc_id = GET_INST(GC, i);
458 		if (xcc_id >= 0)
459 			gpu_metrics->current_gfxclk[i] =
460 				SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]);
461 
462 		if (i < MAX_CLKS) {
463 			gpu_metrics->current_socclk[i] =
464 				SMUQ10_ROUND(metrics->SocclkFrequency[i]);
465 			inst = GET_INST(VCN, i);
466 			if (inst >= 0) {
467 				gpu_metrics->current_vclk0[i] =
468 					SMUQ10_ROUND(metrics->VclkFrequency[inst]);
469 				gpu_metrics->current_dclk0[i] =
470 					SMUQ10_ROUND(metrics->DclkFrequency[inst]);
471 			}
472 		}
473 	}
474 
475 	gpu_metrics->current_uclk = SMUQ10_ROUND(metrics->UclkFrequency);
476 
477 	/* Total accumulated cycle counter */
478 	gpu_metrics->accumulation_counter = metrics->AccumulationCounter;
479 
480 	/* Accumulated throttler residencies */
481 	gpu_metrics->prochot_residency_acc = metrics->ProchotResidencyAcc;
482 	gpu_metrics->ppt_residency_acc = metrics->PptResidencyAcc;
483 	gpu_metrics->socket_thm_residency_acc = metrics->SocketThmResidencyAcc;
484 	gpu_metrics->vr_thm_residency_acc = metrics->VrThmResidencyAcc;
485 	gpu_metrics->hbm_thm_residency_acc = metrics->HbmThmResidencyAcc;
486 
487 	/* Clock Lock Status. Each bit corresponds to each GFXCLK instance */
488 	gpu_metrics->gfxclk_lock_status = metrics->GfxLockXCDMak >> GET_INST(GC, 0);
489 
490 	gpu_metrics->pcie_link_width = metrics->PCIeLinkWidth;
491 	gpu_metrics->pcie_link_speed =
492 		pcie_gen_to_speed(metrics->PCIeLinkSpeed);
493 	gpu_metrics->pcie_bandwidth_acc =
494 		SMUQ10_ROUND(metrics->PcieBandwidthAcc[0]);
495 	gpu_metrics->pcie_bandwidth_inst =
496 		SMUQ10_ROUND(metrics->PcieBandwidth[0]);
497 	gpu_metrics->pcie_l0_to_recov_count_acc = metrics->PCIeL0ToRecoveryCountAcc;
498 	gpu_metrics->pcie_replay_count_acc = metrics->PCIenReplayAAcc;
499 	gpu_metrics->pcie_replay_rover_count_acc =
500 		metrics->PCIenReplayARolloverCountAcc;
501 	gpu_metrics->pcie_nak_sent_count_acc = metrics->PCIeNAKSentCountAcc;
502 	gpu_metrics->pcie_nak_rcvd_count_acc = metrics->PCIeNAKReceivedCountAcc;
503 	gpu_metrics->pcie_lc_perf_other_end_recovery = metrics->PCIeOtherEndRecoveryAcc;
504 
505 	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
506 
507 	gpu_metrics->gfx_activity_acc = SMUQ10_ROUND(metrics->SocketGfxBusyAcc);
508 	gpu_metrics->mem_activity_acc = SMUQ10_ROUND(metrics->DramBandwidthUtilizationAcc);
509 
510 	for (i = 0; i < NUM_XGMI_LINKS; i++) {
511 		j = amdgpu_xgmi_get_ext_link(adev, i);
512 		if (j < 0 || j >= NUM_XGMI_LINKS)
513 			continue;
514 		gpu_metrics->xgmi_read_data_acc[j] =
515 			SMUQ10_ROUND(metrics->XgmiReadDataSizeAcc[i]);
516 		gpu_metrics->xgmi_write_data_acc[j] =
517 			SMUQ10_ROUND(metrics->XgmiWriteDataSizeAcc[i]);
518 		ret = amdgpu_get_xgmi_link_status(adev, i);
519 		if (ret >= 0)
520 			gpu_metrics->xgmi_link_status[j] = ret;
521 	}
522 
523 	gpu_metrics->num_partition = adev->xcp_mgr->num_xcps;
524 
525 	num_jpeg_rings_gpu_metrics = NUM_JPEG_RINGS_GPU_METRICS(gpu_metrics);
526 	for_each_xcp(adev->xcp_mgr, xcp, i) {
527 		amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_VCN, &inst_mask);
528 		idx = 0;
529 		for_each_inst(k, inst_mask) {
530 			/* Both JPEG and VCN has same instances */
531 			inst = GET_INST(VCN, k);
532 
533 			for (j = 0; j < num_jpeg_rings_gpu_metrics; ++j) {
534 				gpu_metrics->xcp_stats[i].jpeg_busy
535 					[(idx * num_jpeg_rings_gpu_metrics) + j] =
536 					SMUQ10_ROUND(metrics->JpegBusy
537 							[(inst * NUM_JPEG_RINGS_FW) + j]);
538 			}
539 			gpu_metrics->xcp_stats[i].vcn_busy[idx] =
540 			       SMUQ10_ROUND(metrics->VcnBusy[inst]);
541 			idx++;
542 		}
543 
544 		amdgpu_xcp_get_inst_details(xcp, AMDGPU_XCP_GFX, &inst_mask);
545 		idx = 0;
546 		for_each_inst(k, inst_mask) {
547 			inst = GET_INST(GC, k);
548 			gpu_metrics->xcp_stats[i].gfx_busy_inst[idx] =
549 				SMUQ10_ROUND(metrics->GfxBusy[inst]);
550 			gpu_metrics->xcp_stats[i].gfx_busy_acc[idx] =
551 				SMUQ10_ROUND(metrics->GfxBusyAcc[inst]);
552 			if (smu_v13_0_6_cap_supported(smu, SMU_CAP(HST_LIMIT_METRICS))) {
553 				gpu_metrics->xcp_stats[i].gfx_below_host_limit_ppt_acc[idx] =
554 					SMUQ10_ROUND(metrics->GfxclkBelowHostLimitPptAcc[inst]);
555 				gpu_metrics->xcp_stats[i].gfx_below_host_limit_thm_acc[idx] =
556 					SMUQ10_ROUND(metrics->GfxclkBelowHostLimitThmAcc[inst]);
557 				gpu_metrics->xcp_stats[i].gfx_low_utilization_acc[idx] =
558 					SMUQ10_ROUND(metrics->GfxclkLowUtilizationAcc[inst]);
559 				gpu_metrics->xcp_stats[i].gfx_below_host_limit_total_acc[idx] =
560 					SMUQ10_ROUND(metrics->GfxclkBelowHostLimitTotalAcc[inst]);
561 			}
562 			idx++;
563 		}
564 	}
565 
566 	gpu_metrics->xgmi_link_width = metrics->XgmiWidth;
567 	gpu_metrics->xgmi_link_speed = metrics->XgmiBitrate;
568 
569 	gpu_metrics->firmware_timestamp = metrics->Timestamp;
570 
571 	*table = (void *)gpu_metrics;
572 
573 	return sizeof(*gpu_metrics);
574 }
575