File Index
Files and directories
Sign in
FILE

vega10_smumgr.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c C
  1/*
  2 * Copyright 2016 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#include <linux/pci.h>
 25
 26#include "smumgr.h"
 27#include "vega10_inc.h"
 28#include "soc15_common.h"
 29#include "vega10_smumgr.h"
 30#include "vega10_hwmgr.h"
 31#include "vega10_ppsmc.h"
 32#include "smu9_driver_if.h"
 33#include "smu9_smumgr.h"
 34#include "ppatomctrl.h"
 35#include "pp_debug.h"
 36
 37
 38static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
 39		uint8_t *table, int16_t table_id)
 40{
 41	struct vega10_smumgr *priv = hwmgr->smu_backend;
 42	struct amdgpu_device *adev = hwmgr->adev;
 43
 44	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
 45			"Invalid SMU Table ID!", return -EINVAL);
 46	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
 47			"Invalid SMU Table version!", return -EINVAL);
 48	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
 49			"Invalid SMU Table Length!", return -EINVAL);
 50	smum_send_msg_to_smc_with_parameter(hwmgr,
 51			PPSMC_MSG_SetDriverDramAddrHigh,
 52			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
 53			NULL);
 54	smum_send_msg_to_smc_with_parameter(hwmgr,
 55			PPSMC_MSG_SetDriverDramAddrLow,
 56			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
 57			NULL);
 58	smum_send_msg_to_smc_with_parameter(hwmgr,
 59			PPSMC_MSG_TransferTableSmu2Dram,
 60			priv->smu_tables.entry[table_id].table_id,
 61			NULL);
 62
 63	amdgpu_hdp_invalidate(adev, NULL);
 64
 65	memcpy(table, priv->smu_tables.entry[table_id].table,
 66			priv->smu_tables.entry[table_id].size);
 67
 68	return 0;
 69}
 70
 71static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
 72		uint8_t *table, int16_t table_id)
 73{
 74	struct vega10_smumgr *priv = hwmgr->smu_backend;
 75	struct amdgpu_device *adev = hwmgr->adev;
 76
 77	/* under sriov, vbios or hypervisor driver
 78	 * has already copy table to smc so here only skip it
 79	 */
 80	if (!hwmgr->not_vf)
 81		return 0;
 82
 83	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
 84			"Invalid SMU Table ID!", return -EINVAL);
 85	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
 86			"Invalid SMU Table version!", return -EINVAL);
 87	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
 88			"Invalid SMU Table Length!", return -EINVAL);
 89
 90	memcpy(priv->smu_tables.entry[table_id].table, table,
 91			priv->smu_tables.entry[table_id].size);
 92
 93	amdgpu_hdp_flush(adev, NULL);
 94
 95	smum_send_msg_to_smc_with_parameter(hwmgr,
 96			PPSMC_MSG_SetDriverDramAddrHigh,
 97			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
 98			NULL);
 99	smum_send_msg_to_smc_with_parameter(hwmgr,
100			PPSMC_MSG_SetDriverDramAddrLow,
101			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
102			NULL);
103	smum_send_msg_to_smc_with_parameter(hwmgr,
104			PPSMC_MSG_TransferTableDram2Smu,
105			priv->smu_tables.entry[table_id].table_id,
106			NULL);
107
108	return 0;
109}
110
111int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
112			       bool enable, uint32_t feature_mask)
113{
114	int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
115			PPSMC_MSG_DisableSmuFeatures;
116
117	/* VF has no permission to change smu feature due
118	 * to security concern even under pp one vf mode
119	 * it still can't do it. For vega10, the smu in
120	 * vbios will enable the appropriate features.
121	 * */
122	if (!hwmgr->not_vf)
123		return 0;
124
125	return smum_send_msg_to_smc_with_parameter(hwmgr,
126			msg, feature_mask, NULL);
127}
128
129int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
130			    uint64_t *features_enabled)
131{
132	uint32_t enabled_features;
133	int ret;
134
135	if (features_enabled == NULL)
136		return -EINVAL;
137
138	ret = smum_send_msg_to_smc(hwmgr,
139			PPSMC_MSG_GetEnabledSmuFeatures,
140			&enabled_features);
141	if (ret)
142		return ret;
143
144	*features_enabled = enabled_features;
145
146	return 0;
147}
148
149static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
150{
151	uint64_t features_enabled = 0;
152
153	vega10_get_enabled_smc_features(hwmgr, &features_enabled);
154
155	if (features_enabled & SMC_DPM_FEATURES)
156		return true;
157	else
158		return false;
159}
160
161static int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
162{
163	struct vega10_smumgr *priv = hwmgr->smu_backend;
164
165	if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) {
166		smum_send_msg_to_smc_with_parameter(hwmgr,
167				PPSMC_MSG_SetToolsDramAddrHigh,
168				upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr),
169				NULL);
170		smum_send_msg_to_smc_with_parameter(hwmgr,
171				PPSMC_MSG_SetToolsDramAddrLow,
172				lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr),
173				NULL);
174	}
175	return 0;
176}
177
178static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
179{
180	uint32_t smc_driver_if_version;
181	struct amdgpu_device *adev = hwmgr->adev;
182	uint32_t dev_id;
183	uint32_t rev_id;
184
185	PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
186			PPSMC_MSG_GetDriverIfVersion,
187			&smc_driver_if_version),
188			"Attempt to get SMC IF Version Number Failed!",
189			return -EINVAL);
190
191	dev_id = adev->pdev->device;
192	rev_id = adev->pdev->revision;
193
194	if (!((dev_id == 0x687f) &&
195		((rev_id == 0xc0) ||
196		(rev_id == 0xc1) ||
197		(rev_id == 0xc3)))) {
198		if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
199			pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n",
200			       smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
201			return -EINVAL;
202		}
203	}
204
205	return 0;
206}
207
208static int vega10_smu_init(struct pp_hwmgr *hwmgr)
209{
210	struct vega10_smumgr *priv;
211	unsigned long tools_size;
212	int ret;
213	struct cgs_firmware_info info = {0};
214
215	ret = cgs_get_firmware_info(hwmgr->device,
216					CGS_UCODE_ID_SMU,
217					&info);
218	if (ret || !info.kptr)
219		return -EINVAL;
220
221	priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL);
222
223	if (!priv)
224		return -ENOMEM;
225
226	hwmgr->smu_backend = priv;
227
228	/* allocate space for pptable */
229	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
230			sizeof(PPTable_t),
231			PAGE_SIZE,
232			AMDGPU_GEM_DOMAIN_VRAM,
233			&priv->smu_tables.entry[PPTABLE].handle,
234			&priv->smu_tables.entry[PPTABLE].mc_addr,
235			&priv->smu_tables.entry[PPTABLE].table);
236	if (ret)
237		goto free_backend;
238
239	priv->smu_tables.entry[PPTABLE].version = 0x01;
240	priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
241	priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE;
242
243	/* allocate space for watermarks table */
244	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
245			sizeof(Watermarks_t),
246			PAGE_SIZE,
247			AMDGPU_GEM_DOMAIN_VRAM,
248			&priv->smu_tables.entry[WMTABLE].handle,
249			&priv->smu_tables.entry[WMTABLE].mc_addr,
250			&priv->smu_tables.entry[WMTABLE].table);
251
252	if (ret)
253		goto err0;
254
255	priv->smu_tables.entry[WMTABLE].version = 0x01;
256	priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
257	priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
258
259	/* allocate space for AVFS table */
260	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
261			sizeof(AvfsTable_t),
262			PAGE_SIZE,
263			AMDGPU_GEM_DOMAIN_VRAM,
264			&priv->smu_tables.entry[AVFSTABLE].handle,
265			&priv->smu_tables.entry[AVFSTABLE].mc_addr,
266			&priv->smu_tables.entry[AVFSTABLE].table);
267
268	if (ret)
269		goto err1;
270
271	priv->smu_tables.entry[AVFSTABLE].version = 0x01;
272	priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
273	priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS;
274
275	tools_size = 0x19000;
276	if (tools_size) {
277		ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
278				tools_size,
279				PAGE_SIZE,
280				AMDGPU_GEM_DOMAIN_VRAM,
281				&priv->smu_tables.entry[TOOLSTABLE].handle,
282				&priv->smu_tables.entry[TOOLSTABLE].mc_addr,
283				&priv->smu_tables.entry[TOOLSTABLE].table);
284		if (ret)
285			goto err2;
286		priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
287		priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
288		priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
289	}
290
291	/* allocate space for AVFS Fuse table */
292	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
293			sizeof(AvfsFuseOverride_t),
294			PAGE_SIZE,
295			AMDGPU_GEM_DOMAIN_VRAM,
296			&priv->smu_tables.entry[AVFSFUSETABLE].handle,
297			&priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
298			&priv->smu_tables.entry[AVFSFUSETABLE].table);
299	if (ret)
300		goto err3;
301
302	priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
303	priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
304	priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
305
306
307	return 0;
308
309err3:
310	if (priv->smu_tables.entry[TOOLSTABLE].table)
311		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
312				&priv->smu_tables.entry[TOOLSTABLE].mc_addr,
313				&priv->smu_tables.entry[TOOLSTABLE].table);
314err2:
315	amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
316				&priv->smu_tables.entry[AVFSTABLE].mc_addr,
317				&priv->smu_tables.entry[AVFSTABLE].table);
318err1:
319	amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
320				&priv->smu_tables.entry[WMTABLE].mc_addr,
321				&priv->smu_tables.entry[WMTABLE].table);
322err0:
323	amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
324			&priv->smu_tables.entry[PPTABLE].mc_addr,
325			&priv->smu_tables.entry[PPTABLE].table);
326free_backend:
327	kfree(hwmgr->smu_backend);
328
329	return -EINVAL;
330}
331
332static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
333{
334	struct vega10_smumgr *priv = hwmgr->smu_backend;
335
336	if (priv) {
337		amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
338				&priv->smu_tables.entry[PPTABLE].mc_addr,
339				&priv->smu_tables.entry[PPTABLE].table);
340		amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
341					&priv->smu_tables.entry[WMTABLE].mc_addr,
342					&priv->smu_tables.entry[WMTABLE].table);
343		amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
344					&priv->smu_tables.entry[AVFSTABLE].mc_addr,
345					&priv->smu_tables.entry[AVFSTABLE].table);
346		if (priv->smu_tables.entry[TOOLSTABLE].table)
347			amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
348					&priv->smu_tables.entry[TOOLSTABLE].mc_addr,
349					&priv->smu_tables.entry[TOOLSTABLE].table);
350		amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle,
351					&priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
352					&priv->smu_tables.entry[AVFSFUSETABLE].table);
353		kfree(hwmgr->smu_backend);
354		hwmgr->smu_backend = NULL;
355	}
356	return 0;
357}
358
359static int vega10_start_smu(struct pp_hwmgr *hwmgr)
360{
361	if (!smu9_is_smc_ram_running(hwmgr))
362		return -EINVAL;
363
364	PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
365			"Failed to verify SMC interface!",
366			return -EINVAL);
367
368	vega10_set_tools_address(hwmgr);
369
370	return 0;
371}
372
373static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
374				    uint16_t table_id, bool rw)
375{
376	int ret;
377
378	if (rw)
379		ret = vega10_copy_table_from_smc(hwmgr, table, table_id);
380	else
381		ret = vega10_copy_table_to_smc(hwmgr, table, table_id);
382
383	return ret;
384}
385
386const struct pp_smumgr_func vega10_smu_funcs = {
387	.name = "vega10_smu",
388	.smu_init = &vega10_smu_init,
389	.smu_fini = &vega10_smu_fini,
390	.start_smu = &vega10_start_smu,
391	.request_smu_load_specific_fw = NULL,
392	.send_msg_to_smc = &smu9_send_msg_to_smc,
393	.send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
394	.download_pptable_settings = NULL,
395	.upload_pptable_settings = NULL,
396	.is_dpm_running = vega10_is_dpm_running,
397	.get_argument = smu9_get_argument,
398	.smc_table_manager = vega10_smc_table_manager,
399};
~/ Read-only file preview.