xref: /openbmc/linux/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c (revision fac59652993f075d57860769c99045b3ca18780d)
1d38ceaf9SAlex Deucher /*
2d38ceaf9SAlex Deucher  * Copyright 2008 Advanced Micro Devices, Inc.
3d38ceaf9SAlex Deucher  * Copyright 2008 Red Hat Inc.
4d38ceaf9SAlex Deucher  * Copyright 2009 Jerome Glisse.
5d38ceaf9SAlex Deucher  *
6d38ceaf9SAlex Deucher  * Permission is hereby granted, free of charge, to any person obtaining a
7d38ceaf9SAlex Deucher  * copy of this software and associated documentation files (the "Software"),
8d38ceaf9SAlex Deucher  * to deal in the Software without restriction, including without limitation
9d38ceaf9SAlex Deucher  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10d38ceaf9SAlex Deucher  * and/or sell copies of the Software, and to permit persons to whom the
11d38ceaf9SAlex Deucher  * Software is furnished to do so, subject to the following conditions:
12d38ceaf9SAlex Deucher  *
13d38ceaf9SAlex Deucher  * The above copyright notice and this permission notice shall be included in
14d38ceaf9SAlex Deucher  * all copies or substantial portions of the Software.
15d38ceaf9SAlex Deucher  *
16d38ceaf9SAlex Deucher  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d38ceaf9SAlex Deucher  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d38ceaf9SAlex Deucher  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19d38ceaf9SAlex Deucher  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20d38ceaf9SAlex Deucher  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21d38ceaf9SAlex Deucher  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22d38ceaf9SAlex Deucher  * OTHER DEALINGS IN THE SOFTWARE.
23d38ceaf9SAlex Deucher  *
24d38ceaf9SAlex Deucher  * Authors: Dave Airlie
25d38ceaf9SAlex Deucher  *          Alex Deucher
26d38ceaf9SAlex Deucher  *          Jerome Glisse
27d38ceaf9SAlex Deucher  */
28fdf2f6c5SSam Ravnborg 
29d38ceaf9SAlex Deucher #include "amdgpu.h"
30d38ceaf9SAlex Deucher #include <drm/amdgpu_drm.h>
3172c8c97bSAndrey Grodzovsky #include <drm/drm_drv.h>
3245b64fd9SThomas Zimmermann #include <drm/drm_fb_helper.h>
33d38ceaf9SAlex Deucher #include "amdgpu_uvd.h"
34d38ceaf9SAlex Deucher #include "amdgpu_vce.h"
3532d8c662SAlex Deucher #include "atom.h"
36d38ceaf9SAlex Deucher 
37d38ceaf9SAlex Deucher #include <linux/vga_switcheroo.h>
38d38ceaf9SAlex Deucher #include <linux/slab.h>
39fdf2f6c5SSam Ravnborg #include <linux/uaccess.h>
40fdf2f6c5SSam Ravnborg #include <linux/pci.h>
41d38ceaf9SAlex Deucher #include <linux/pm_runtime.h>
42130e0371SOded Gabbay #include "amdgpu_amdkfd.h"
432cddc50eSHuang Rui #include "amdgpu_gem.h"
445df58525SHuang Rui #include "amdgpu_display.h"
455cb77114Sxinhui pan #include "amdgpu_ras.h"
46*8361e3f7SVictor Skvortsov #include "amdgpu_reset.h"
47e3e84b0aSMarek Olšák #include "amd_pcie.h"
48d38ceaf9SAlex Deucher 
amdgpu_unregister_gpu_instance(struct amdgpu_device * adev)49fdafb359SEvan Quan void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
5062d73fbcSEvan Quan {
5162d73fbcSEvan Quan 	struct amdgpu_gpu_instance *gpu_instance;
5262d73fbcSEvan Quan 	int i;
5362d73fbcSEvan Quan 
5462d73fbcSEvan Quan 	mutex_lock(&mgpu_info.mutex);
5562d73fbcSEvan Quan 
5662d73fbcSEvan Quan 	for (i = 0; i < mgpu_info.num_gpu; i++) {
5762d73fbcSEvan Quan 		gpu_instance = &(mgpu_info.gpu_ins[i]);
5862d73fbcSEvan Quan 		if (gpu_instance->adev == adev) {
5962d73fbcSEvan Quan 			mgpu_info.gpu_ins[i] =
6062d73fbcSEvan Quan 				mgpu_info.gpu_ins[mgpu_info.num_gpu - 1];
6162d73fbcSEvan Quan 			mgpu_info.num_gpu--;
6262d73fbcSEvan Quan 			if (adev->flags & AMD_IS_APU)
6362d73fbcSEvan Quan 				mgpu_info.num_apu--;
6462d73fbcSEvan Quan 			else
6562d73fbcSEvan Quan 				mgpu_info.num_dgpu--;
6662d73fbcSEvan Quan 			break;
6762d73fbcSEvan Quan 		}
6862d73fbcSEvan Quan 	}
6962d73fbcSEvan Quan 
7062d73fbcSEvan Quan 	mutex_unlock(&mgpu_info.mutex);
7162d73fbcSEvan Quan }
7262d73fbcSEvan Quan 
73d38ceaf9SAlex Deucher /**
74d38ceaf9SAlex Deucher  * amdgpu_driver_unload_kms - Main unload function for KMS.
75d38ceaf9SAlex Deucher  *
76d38ceaf9SAlex Deucher  * @dev: drm dev pointer
77d38ceaf9SAlex Deucher  *
78d38ceaf9SAlex Deucher  * This is the main unload function for KMS (all asics).
79d38ceaf9SAlex Deucher  * Returns 0 on success.
80d38ceaf9SAlex Deucher  */
amdgpu_driver_unload_kms(struct drm_device * dev)8111b3c20bSGabriel Krisman Bertazi void amdgpu_driver_unload_kms(struct drm_device *dev)
82d38ceaf9SAlex Deucher {
831348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
84d38ceaf9SAlex Deucher 
85d38ceaf9SAlex Deucher 	if (adev == NULL)
8611b3c20bSGabriel Krisman Bertazi 		return;
87d38ceaf9SAlex Deucher 
8862d73fbcSEvan Quan 	amdgpu_unregister_gpu_instance(adev);
8962d73fbcSEvan Quan 
90d38ceaf9SAlex Deucher 	if (adev->rmmio == NULL)
918aba21b7SLuben Tuikov 		return;
92d38ceaf9SAlex Deucher 
933fa8f89dSSathishkumar S 	if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_UNLOAD))
943fa8f89dSSathishkumar S 		DRM_WARN("smart shift update failed\n");
953fa8f89dSSathishkumar S 
96d38ceaf9SAlex Deucher 	amdgpu_acpi_fini(adev);
9772c8c97bSAndrey Grodzovsky 	amdgpu_device_fini_hw(adev);
98d38ceaf9SAlex Deucher }
99d38ceaf9SAlex Deucher 
amdgpu_register_gpu_instance(struct amdgpu_device * adev)100fdafb359SEvan Quan void amdgpu_register_gpu_instance(struct amdgpu_device *adev)
10162d73fbcSEvan Quan {
10262d73fbcSEvan Quan 	struct amdgpu_gpu_instance *gpu_instance;
10362d73fbcSEvan Quan 
10462d73fbcSEvan Quan 	mutex_lock(&mgpu_info.mutex);
10562d73fbcSEvan Quan 
10662d73fbcSEvan Quan 	if (mgpu_info.num_gpu >= MAX_GPU_INSTANCE) {
10762d73fbcSEvan Quan 		DRM_ERROR("Cannot register more gpu instance\n");
10862d73fbcSEvan Quan 		mutex_unlock(&mgpu_info.mutex);
10962d73fbcSEvan Quan 		return;
11062d73fbcSEvan Quan 	}
11162d73fbcSEvan Quan 
11262d73fbcSEvan Quan 	gpu_instance = &(mgpu_info.gpu_ins[mgpu_info.num_gpu]);
11362d73fbcSEvan Quan 	gpu_instance->adev = adev;
11462d73fbcSEvan Quan 	gpu_instance->mgpu_fan_enabled = 0;
11562d73fbcSEvan Quan 
11662d73fbcSEvan Quan 	mgpu_info.num_gpu++;
11762d73fbcSEvan Quan 	if (adev->flags & AMD_IS_APU)
11862d73fbcSEvan Quan 		mgpu_info.num_apu++;
11962d73fbcSEvan Quan 	else
12062d73fbcSEvan Quan 		mgpu_info.num_dgpu++;
12162d73fbcSEvan Quan 
12262d73fbcSEvan Quan 	mutex_unlock(&mgpu_info.mutex);
12362d73fbcSEvan Quan }
12462d73fbcSEvan Quan 
125d38ceaf9SAlex Deucher /**
126d38ceaf9SAlex Deucher  * amdgpu_driver_load_kms - Main load function for KMS.
127d38ceaf9SAlex Deucher  *
1288aba21b7SLuben Tuikov  * @adev: pointer to struct amdgpu_device
129d38ceaf9SAlex Deucher  * @flags: device flags
130d38ceaf9SAlex Deucher  *
131d38ceaf9SAlex Deucher  * This is the main load function for KMS (all asics).
132d38ceaf9SAlex Deucher  * Returns 0 on success, error on failure.
133d38ceaf9SAlex Deucher  */
amdgpu_driver_load_kms(struct amdgpu_device * adev,unsigned long flags)1348aba21b7SLuben Tuikov int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
135d38ceaf9SAlex Deucher {
1368aba21b7SLuben Tuikov 	struct drm_device *dev;
1371daee8b4SPixel Ding 	int r, acpi_status;
138d38ceaf9SAlex Deucher 
1398aba21b7SLuben Tuikov 	dev = adev_to_drm(adev);
140d38ceaf9SAlex Deucher 
141d38ceaf9SAlex Deucher 	/* amdgpu_device_init should report only fatal error
142d38ceaf9SAlex Deucher 	 * like memory allocation failure or iomapping failure,
143d38ceaf9SAlex Deucher 	 * or memory manager initialization failure, it must
144d38ceaf9SAlex Deucher 	 * properly initialize the GPU MC controller and permit
145d38ceaf9SAlex Deucher 	 * VRAM allocation
146d38ceaf9SAlex Deucher 	 */
1478aba21b7SLuben Tuikov 	r = amdgpu_device_init(adev, flags);
1481daee8b4SPixel Ding 	if (r) {
1498f66090bSThomas Zimmermann 		dev_err(dev->dev, "Fatal error during GPU init\n");
150d38ceaf9SAlex Deucher 		goto out;
151d38ceaf9SAlex Deucher 	}
152d38ceaf9SAlex Deucher 
1539c913f38SGuchun Chen 	adev->pm.rpm_mode = AMDGPU_RUNPM_NONE;
154b98c6299SAlex Deucher 	if (amdgpu_device_supports_px(dev) &&
1559c913f38SGuchun Chen 	    (amdgpu_runtime_pm != 0)) { /* enable PX as runtime mode */
15650fe04d4SGuchun Chen 		adev->pm.rpm_mode = AMDGPU_RUNPM_PX;
157d00a88abSAlex Deucher 		dev_info(adev->dev, "Using ATPX for runtime pm\n");
158157e8306SAlex Deucher 	} else if (amdgpu_device_supports_boco(dev) &&
1599c913f38SGuchun Chen 		   (amdgpu_runtime_pm != 0)) { /* enable boco as runtime mode */
16050fe04d4SGuchun Chen 		adev->pm.rpm_mode = AMDGPU_RUNPM_BOCO;
161d00a88abSAlex Deucher 		dev_info(adev->dev, "Using BOCO for runtime pm\n");
162b38c6968SAlex Deucher 	} else if (amdgpu_device_supports_baco(dev) &&
163b38c6968SAlex Deucher 		   (amdgpu_runtime_pm != 0)) {
164b38c6968SAlex Deucher 		switch (adev->asic_type) {
165b38c6968SAlex Deucher 		case CHIP_VEGA20:
166b38c6968SAlex Deucher 		case CHIP_ARCTURUS:
1679c913f38SGuchun Chen 			/* enable BACO as runpm mode if runpm=1 */
168b38c6968SAlex Deucher 			if (amdgpu_runtime_pm > 0)
1699c913f38SGuchun Chen 				adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
170b38c6968SAlex Deucher 			break;
171cd527780SAlex Deucher 		case CHIP_VEGA10:
1729c913f38SGuchun Chen 			/* enable BACO as runpm mode if noretry=0 */
1739b498efaSAlex Deucher 			if (!adev->gmc.noretry)
1749c913f38SGuchun Chen 				adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
175cd527780SAlex Deucher 			break;
176b38c6968SAlex Deucher 		default:
1779c913f38SGuchun Chen 			/* enable BACO as runpm mode on CI+ */
1789c913f38SGuchun Chen 			adev->pm.rpm_mode = AMDGPU_RUNPM_BACO;
179b38c6968SAlex Deucher 			break;
180b38c6968SAlex Deucher 		}
181d1acd68bSGuchun Chen 
1829c913f38SGuchun Chen 		if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO)
183d00a88abSAlex Deucher 			dev_info(adev->dev, "Using BACO for runtime pm\n");
184b38c6968SAlex Deucher 	}
18572f058b7SAlex Deucher 
186d38ceaf9SAlex Deucher 	/* Call ACPI methods: require modeset init
187d38ceaf9SAlex Deucher 	 * but failure is not fatal
188d38ceaf9SAlex Deucher 	 */
189ad36d71bSAurabindo Pillai 
190d38ceaf9SAlex Deucher 	acpi_status = amdgpu_acpi_init(adev);
191d38ceaf9SAlex Deucher 	if (acpi_status)
1928f66090bSThomas Zimmermann 		dev_dbg(dev->dev, "Error during ACPI methods call\n");
193d38ceaf9SAlex Deucher 
1943fa8f89dSSathishkumar S 	if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_LOAD))
1953fa8f89dSSathishkumar S 		DRM_WARN("smart shift update failed\n");
1963fa8f89dSSathishkumar S 
197d38ceaf9SAlex Deucher out:
198d0d66b8cSAlex Deucher 	if (r)
199d38ceaf9SAlex Deucher 		amdgpu_driver_unload_kms(dev);
200d38ceaf9SAlex Deucher 
201d38ceaf9SAlex Deucher 	return r;
202d38ceaf9SAlex Deucher }
203d38ceaf9SAlex Deucher 
amdgpu_firmware_info(struct drm_amdgpu_info_firmware * fw_info,struct drm_amdgpu_query_fw * query_fw,struct amdgpu_device * adev)204000cab9aSHuang Rui static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
205000cab9aSHuang Rui 				struct drm_amdgpu_query_fw *query_fw,
206000cab9aSHuang Rui 				struct amdgpu_device *adev)
207000cab9aSHuang Rui {
208000cab9aSHuang Rui 	switch (query_fw->fw_type) {
209000cab9aSHuang Rui 	case AMDGPU_INFO_FW_VCE:
210000cab9aSHuang Rui 		fw_info->ver = adev->vce.fw_version;
211000cab9aSHuang Rui 		fw_info->feature = adev->vce.fb_version;
212000cab9aSHuang Rui 		break;
213000cab9aSHuang Rui 	case AMDGPU_INFO_FW_UVD:
214000cab9aSHuang Rui 		fw_info->ver = adev->uvd.fw_version;
215000cab9aSHuang Rui 		fw_info->feature = 0;
216000cab9aSHuang Rui 		break;
2173ac952b1SAlex Deucher 	case AMDGPU_INFO_FW_VCN:
2183ac952b1SAlex Deucher 		fw_info->ver = adev->vcn.fw_version;
2193ac952b1SAlex Deucher 		fw_info->feature = 0;
2203ac952b1SAlex Deucher 		break;
221000cab9aSHuang Rui 	case AMDGPU_INFO_FW_GMC:
222770d13b1SChristian König 		fw_info->ver = adev->gmc.fw_version;
223000cab9aSHuang Rui 		fw_info->feature = 0;
224000cab9aSHuang Rui 		break;
225000cab9aSHuang Rui 	case AMDGPU_INFO_FW_GFX_ME:
226000cab9aSHuang Rui 		fw_info->ver = adev->gfx.me_fw_version;
227000cab9aSHuang Rui 		fw_info->feature = adev->gfx.me_feature_version;
228000cab9aSHuang Rui 		break;
229000cab9aSHuang Rui 	case AMDGPU_INFO_FW_GFX_PFP:
230000cab9aSHuang Rui 		fw_info->ver = adev->gfx.pfp_fw_version;
231000cab9aSHuang Rui 		fw_info->feature = adev->gfx.pfp_feature_version;
232000cab9aSHuang Rui 		break;
233000cab9aSHuang Rui 	case AMDGPU_INFO_FW_GFX_CE:
234000cab9aSHuang Rui 		fw_info->ver = adev->gfx.ce_fw_version;
235000cab9aSHuang Rui 		fw_info->feature = adev->gfx.ce_feature_version;
236000cab9aSHuang Rui 		break;
237000cab9aSHuang Rui 	case AMDGPU_INFO_FW_GFX_RLC:
238000cab9aSHuang Rui 		fw_info->ver = adev->gfx.rlc_fw_version;
239000cab9aSHuang Rui 		fw_info->feature = adev->gfx.rlc_feature_version;
240000cab9aSHuang Rui 		break;
241621a6318SHuang Rui 	case AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_CNTL:
242621a6318SHuang Rui 		fw_info->ver = adev->gfx.rlc_srlc_fw_version;
243621a6318SHuang Rui 		fw_info->feature = adev->gfx.rlc_srlc_feature_version;
244621a6318SHuang Rui 		break;
245621a6318SHuang Rui 	case AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM:
246621a6318SHuang Rui 		fw_info->ver = adev->gfx.rlc_srlg_fw_version;
247621a6318SHuang Rui 		fw_info->feature = adev->gfx.rlc_srlg_feature_version;
248621a6318SHuang Rui 		break;
249621a6318SHuang Rui 	case AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM:
250621a6318SHuang Rui 		fw_info->ver = adev->gfx.rlc_srls_fw_version;
251621a6318SHuang Rui 		fw_info->feature = adev->gfx.rlc_srls_feature_version;
252621a6318SHuang Rui 		break;
253670c6edfSHawking Zhang 	case AMDGPU_INFO_FW_GFX_RLCP:
254670c6edfSHawking Zhang 		fw_info->ver = adev->gfx.rlcp_ucode_version;
255670c6edfSHawking Zhang 		fw_info->feature = adev->gfx.rlcp_ucode_feature_version;
256670c6edfSHawking Zhang 		break;
257670c6edfSHawking Zhang 	case AMDGPU_INFO_FW_GFX_RLCV:
258670c6edfSHawking Zhang 		fw_info->ver = adev->gfx.rlcv_ucode_version;
259670c6edfSHawking Zhang 		fw_info->feature = adev->gfx.rlcv_ucode_feature_version;
260670c6edfSHawking Zhang 		break;
261000cab9aSHuang Rui 	case AMDGPU_INFO_FW_GFX_MEC:
262000cab9aSHuang Rui 		if (query_fw->index == 0) {
263000cab9aSHuang Rui 			fw_info->ver = adev->gfx.mec_fw_version;
264000cab9aSHuang Rui 			fw_info->feature = adev->gfx.mec_feature_version;
265000cab9aSHuang Rui 		} else if (query_fw->index == 1) {
266000cab9aSHuang Rui 			fw_info->ver = adev->gfx.mec2_fw_version;
267000cab9aSHuang Rui 			fw_info->feature = adev->gfx.mec2_feature_version;
268000cab9aSHuang Rui 		} else
269000cab9aSHuang Rui 			return -EINVAL;
270000cab9aSHuang Rui 		break;
271000cab9aSHuang Rui 	case AMDGPU_INFO_FW_SMC:
272000cab9aSHuang Rui 		fw_info->ver = adev->pm.fw_version;
273000cab9aSHuang Rui 		fw_info->feature = 0;
274000cab9aSHuang Rui 		break;
2759b9ca62dSxinhui pan 	case AMDGPU_INFO_FW_TA:
276f399d4deSChangfeng 		switch (query_fw->index) {
2774d5ae731SKevin Wang 		case TA_FW_TYPE_PSP_XGMI:
2784320e6f8SCandice Li 			fw_info->ver = adev->psp.xgmi_context.context.bin_desc.fw_version;
279de3a1e33SCandice Li 			fw_info->feature = adev->psp.xgmi_context.context
280de3a1e33SCandice Li 						   .bin_desc.feature_version;
281f399d4deSChangfeng 			break;
2824d5ae731SKevin Wang 		case TA_FW_TYPE_PSP_RAS:
2834320e6f8SCandice Li 			fw_info->ver = adev->psp.ras_context.context.bin_desc.fw_version;
284de3a1e33SCandice Li 			fw_info->feature = adev->psp.ras_context.context
285de3a1e33SCandice Li 						   .bin_desc.feature_version;
286f399d4deSChangfeng 			break;
2874d5ae731SKevin Wang 		case TA_FW_TYPE_PSP_HDCP:
2884320e6f8SCandice Li 			fw_info->ver = adev->psp.hdcp_context.context.bin_desc.fw_version;
289de3a1e33SCandice Li 			fw_info->feature = adev->psp.hdcp_context.context
290de3a1e33SCandice Li 						   .bin_desc.feature_version;
291f399d4deSChangfeng 			break;
2924d5ae731SKevin Wang 		case TA_FW_TYPE_PSP_DTM:
2934320e6f8SCandice Li 			fw_info->ver = adev->psp.dtm_context.context.bin_desc.fw_version;
294de3a1e33SCandice Li 			fw_info->feature = adev->psp.dtm_context.context
295de3a1e33SCandice Li 						   .bin_desc.feature_version;
296f399d4deSChangfeng 			break;
2974d5ae731SKevin Wang 		case TA_FW_TYPE_PSP_RAP:
2984320e6f8SCandice Li 			fw_info->ver = adev->psp.rap_context.context.bin_desc.fw_version;
299de3a1e33SCandice Li 			fw_info->feature = adev->psp.rap_context.context
300de3a1e33SCandice Li 						   .bin_desc.feature_version;
3014890d4e9SKevin Wang 			break;
302e7bdf00eSKevin Wang 		case TA_FW_TYPE_PSP_SECUREDISPLAY:
3034320e6f8SCandice Li 			fw_info->ver = adev->psp.securedisplay_context.context.bin_desc.fw_version;
304de3a1e33SCandice Li 			fw_info->feature =
305de3a1e33SCandice Li 				adev->psp.securedisplay_context.context.bin_desc
306de3a1e33SCandice Li 					.feature_version;
307e7bdf00eSKevin Wang 			break;
308f399d4deSChangfeng 		default:
309f399d4deSChangfeng 			return -EINVAL;
3109b9ca62dSxinhui pan 		}
3119b9ca62dSxinhui pan 		break;
312000cab9aSHuang Rui 	case AMDGPU_INFO_FW_SDMA:
313000cab9aSHuang Rui 		if (query_fw->index >= adev->sdma.num_instances)
314000cab9aSHuang Rui 			return -EINVAL;
315000cab9aSHuang Rui 		fw_info->ver = adev->sdma.instance[query_fw->index].fw_version;
316000cab9aSHuang Rui 		fw_info->feature = adev->sdma.instance[query_fw->index].feature_version;
317000cab9aSHuang Rui 		break;
3186a7ed07eSHuang Rui 	case AMDGPU_INFO_FW_SOS:
319222e0a71SCandice Li 		fw_info->ver = adev->psp.sos.fw_version;
320222e0a71SCandice Li 		fw_info->feature = adev->psp.sos.feature_version;
3216a7ed07eSHuang Rui 		break;
3226a7ed07eSHuang Rui 	case AMDGPU_INFO_FW_ASD:
323de3a1e33SCandice Li 		fw_info->ver = adev->psp.asd_context.bin_desc.fw_version;
324de3a1e33SCandice Li 		fw_info->feature = adev->psp.asd_context.bin_desc.feature_version;
3256a7ed07eSHuang Rui 		break;
3264d11b4b2SDavid Francis 	case AMDGPU_INFO_FW_DMCU:
3274d11b4b2SDavid Francis 		fw_info->ver = adev->dm.dmcu_fw_version;
3284d11b4b2SDavid Francis 		fw_info->feature = 0;
3294d11b4b2SDavid Francis 		break;
330976e51a7SNicholas Kazlauskas 	case AMDGPU_INFO_FW_DMCUB:
331976e51a7SNicholas Kazlauskas 		fw_info->ver = adev->dm.dmcub_fw_version;
332976e51a7SNicholas Kazlauskas 		fw_info->feature = 0;
333976e51a7SNicholas Kazlauskas 		break;
3345120cb54SHuang Rui 	case AMDGPU_INFO_FW_TOC:
335222e0a71SCandice Li 		fw_info->ver = adev->psp.toc.fw_version;
336222e0a71SCandice Li 		fw_info->feature = adev->psp.toc.feature_version;
3375120cb54SHuang Rui 		break;
338c4381d0eSBokun Zhang 	case AMDGPU_INFO_FW_CAP:
339c4381d0eSBokun Zhang 		fw_info->ver = adev->psp.cap_fw_version;
340c4381d0eSBokun Zhang 		fw_info->feature = adev->psp.cap_feature_version;
341c4381d0eSBokun Zhang 		break;
34210faf078SYifan Zhang 	case AMDGPU_INFO_FW_MES_KIQ:
3431d522b51SGraham Sider 		fw_info->ver = adev->mes.kiq_version & AMDGPU_MES_VERSION_MASK;
3441d522b51SGraham Sider 		fw_info->feature = (adev->mes.kiq_version & AMDGPU_MES_FEAT_VERSION_MASK)
3451d522b51SGraham Sider 					>> AMDGPU_MES_FEAT_VERSION_SHIFT;
34610faf078SYifan Zhang 		break;
34710faf078SYifan Zhang 	case AMDGPU_INFO_FW_MES:
3481d522b51SGraham Sider 		fw_info->ver = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK;
3491d522b51SGraham Sider 		fw_info->feature = (adev->mes.sched_version & AMDGPU_MES_FEAT_VERSION_MASK)
3501d522b51SGraham Sider 					>> AMDGPU_MES_FEAT_VERSION_SHIFT;
35110faf078SYifan Zhang 		break;
352b7236296SDavid Francis 	case AMDGPU_INFO_FW_IMU:
353b7236296SDavid Francis 		fw_info->ver = adev->gfx.imu_fw_version;
354b7236296SDavid Francis 		fw_info->feature = 0;
355b7236296SDavid Francis 		break;
356000cab9aSHuang Rui 	default:
357000cab9aSHuang Rui 		return -EINVAL;
358000cab9aSHuang Rui 	}
359000cab9aSHuang Rui 	return 0;
360000cab9aSHuang Rui }
361000cab9aSHuang Rui 
amdgpu_hw_ip_info(struct amdgpu_device * adev,struct drm_amdgpu_info * info,struct drm_amdgpu_info_hw_ip * result)362a245daf3SChristian König static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
363a245daf3SChristian König 			     struct drm_amdgpu_info *info,
364a245daf3SChristian König 			     struct drm_amdgpu_info_hw_ip *result)
365d38ceaf9SAlex Deucher {
36671062f43SKen Wang 	uint32_t ib_start_alignment = 0;
36771062f43SKen Wang 	uint32_t ib_size_alignment = 0;
368a245daf3SChristian König 	enum amd_ip_block_type type;
3691b1f2fecSChristian König 	unsigned int num_rings = 0;
370a245daf3SChristian König 	unsigned int i, j;
371d38ceaf9SAlex Deucher 
372d38ceaf9SAlex Deucher 	if (info->query_hw_ip.ip_instance >= AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
373d38ceaf9SAlex Deucher 		return -EINVAL;
374d38ceaf9SAlex Deucher 
375d38ceaf9SAlex Deucher 	switch (info->query_hw_ip.type) {
376d38ceaf9SAlex Deucher 	case AMDGPU_HW_IP_GFX:
3775fc3aeebSyanyang1 		type = AMD_IP_BLOCK_TYPE_GFX;
378d38ceaf9SAlex Deucher 		for (i = 0; i < adev->gfx.num_gfx_rings; i++)
379c66ed765SAndrey Grodzovsky 			if (adev->gfx.gfx_ring[i].sched.ready)
3801b1f2fecSChristian König 				++num_rings;
3818e2c7ad9SChunming Zhou 		ib_start_alignment = 32;
3828e2c7ad9SChunming Zhou 		ib_size_alignment = 32;
383d38ceaf9SAlex Deucher 		break;
384d38ceaf9SAlex Deucher 	case AMDGPU_HW_IP_COMPUTE:
3855fc3aeebSyanyang1 		type = AMD_IP_BLOCK_TYPE_GFX;
386d38ceaf9SAlex Deucher 		for (i = 0; i < adev->gfx.num_compute_rings; i++)
387c66ed765SAndrey Grodzovsky 			if (adev->gfx.compute_ring[i].sched.ready)
3881b1f2fecSChristian König 				++num_rings;
3898e2c7ad9SChunming Zhou 		ib_start_alignment = 32;
3908e2c7ad9SChunming Zhou 		ib_size_alignment = 32;
391d38ceaf9SAlex Deucher 		break;
392d38ceaf9SAlex Deucher 	case AMDGPU_HW_IP_DMA:
3935fc3aeebSyanyang1 		type = AMD_IP_BLOCK_TYPE_SDMA;
394c113ea1cSAlex Deucher 		for (i = 0; i < adev->sdma.num_instances; i++)
395c66ed765SAndrey Grodzovsky 			if (adev->sdma.instance[i].ring.sched.ready)
3961b1f2fecSChristian König 				++num_rings;
3978e2c7ad9SChunming Zhou 		ib_start_alignment = 256;
3988e2c7ad9SChunming Zhou 		ib_size_alignment = 4;
399d38ceaf9SAlex Deucher 		break;
400d38ceaf9SAlex Deucher 	case AMDGPU_HW_IP_UVD:
4015fc3aeebSyanyang1 		type = AMD_IP_BLOCK_TYPE_UVD;
402f1e582ebSAlex Deucher 		for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
403f1e582ebSAlex Deucher 			if (adev->uvd.harvest_config & (1 << i))
404f1e582ebSAlex Deucher 				continue;
4051b1f2fecSChristian König 
406c66ed765SAndrey Grodzovsky 			if (adev->uvd.inst[i].ring.sched.ready)
4071b1f2fecSChristian König 				++num_rings;
408f1e582ebSAlex Deucher 		}
4098e2c7ad9SChunming Zhou 		ib_start_alignment = 64;
4108e2c7ad9SChunming Zhou 		ib_size_alignment = 64;
411d38ceaf9SAlex Deucher 		break;
412d38ceaf9SAlex Deucher 	case AMDGPU_HW_IP_VCE:
4135fc3aeebSyanyang1 		type = AMD_IP_BLOCK_TYPE_VCE;
41475c65480SAlex Deucher 		for (i = 0; i < adev->vce.num_rings; i++)
415c66ed765SAndrey Grodzovsky 			if (adev->vce.ring[i].sched.ready)
4161b1f2fecSChristian König 				++num_rings;
4178e2c7ad9SChunming Zhou 		ib_start_alignment = 4;
418a22f803cSAlex Deucher 		ib_size_alignment = 1;
419d38ceaf9SAlex Deucher 		break;
42063defd3fSLeo Liu 	case AMDGPU_HW_IP_UVD_ENC:
42163defd3fSLeo Liu 		type = AMD_IP_BLOCK_TYPE_UVD;
422f1e582ebSAlex Deucher 		for (i = 0; i < adev->uvd.num_uvd_inst; i++) {
423f1e582ebSAlex Deucher 			if (adev->uvd.harvest_config & (1 << i))
424f1e582ebSAlex Deucher 				continue;
4251b1f2fecSChristian König 
426f1e582ebSAlex Deucher 			for (j = 0; j < adev->uvd.num_enc_rings; j++)
427c66ed765SAndrey Grodzovsky 				if (adev->uvd.inst[i].ring_enc[j].sched.ready)
4281b1f2fecSChristian König 					++num_rings;
429f1e582ebSAlex Deucher 		}
4308e2c7ad9SChunming Zhou 		ib_start_alignment = 64;
4318e2c7ad9SChunming Zhou 		ib_size_alignment = 64;
43263defd3fSLeo Liu 		break;
433bdc799e5SLeo Liu 	case AMDGPU_HW_IP_VCN_DEC:
434bdc799e5SLeo Liu 		type = AMD_IP_BLOCK_TYPE_VCN;
435fa739f4bSJames Zhu 		for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
43656ee5122SKonstantin Meskhidze 			if (adev->vcn.harvest_config & (1 << i))
437cd1fd7b3SJames Zhu 				continue;
438cd1fd7b3SJames Zhu 
439fa739f4bSJames Zhu 			if (adev->vcn.inst[i].ring_dec.sched.ready)
4401b1f2fecSChristian König 				++num_rings;
441fa739f4bSJames Zhu 		}
4428e2c7ad9SChunming Zhou 		ib_start_alignment = 16;
443bdc799e5SLeo Liu 		ib_size_alignment = 16;
444bdc799e5SLeo Liu 		break;
445cefbc598SLeo Liu 	case AMDGPU_HW_IP_VCN_ENC:
446cefbc598SLeo Liu 		type = AMD_IP_BLOCK_TYPE_VCN;
447fa739f4bSJames Zhu 		for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
44856ee5122SKonstantin Meskhidze 			if (adev->vcn.harvest_config & (1 << i))
449cd1fd7b3SJames Zhu 				continue;
450cd1fd7b3SJames Zhu 
451fa739f4bSJames Zhu 			for (j = 0; j < adev->vcn.num_enc_rings; j++)
452fa739f4bSJames Zhu 				if (adev->vcn.inst[i].ring_enc[j].sched.ready)
4531b1f2fecSChristian König 					++num_rings;
454fa739f4bSJames Zhu 		}
4558e2c7ad9SChunming Zhou 		ib_start_alignment = 64;
456cefbc598SLeo Liu 		ib_size_alignment = 1;
457cefbc598SLeo Liu 		break;
4584bafe440SBoyuan Zhang 	case AMDGPU_HW_IP_VCN_JPEG:
45952f2e779SLeo Liu 		type = (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_JPEG)) ?
46052f2e779SLeo Liu 			AMD_IP_BLOCK_TYPE_JPEG : AMD_IP_BLOCK_TYPE_VCN;
46152f2e779SLeo Liu 
4620388aee7SLeo Liu 		for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) {
4630388aee7SLeo Liu 			if (adev->jpeg.harvest_config & (1 << i))
464cd1fd7b3SJames Zhu 				continue;
465cd1fd7b3SJames Zhu 
466bc224553SJames Zhu 			for (j = 0; j < adev->jpeg.num_jpeg_rings; j++)
467bc224553SJames Zhu 				if (adev->jpeg.inst[i].ring_dec[j].sched.ready)
4681b1f2fecSChristian König 					++num_rings;
469fa739f4bSJames Zhu 		}
4708e2c7ad9SChunming Zhou 		ib_start_alignment = 16;
4714bafe440SBoyuan Zhang 		ib_size_alignment = 16;
4724bafe440SBoyuan Zhang 		break;
473d38ceaf9SAlex Deucher 	default:
474d38ceaf9SAlex Deucher 		return -EINVAL;
475d38ceaf9SAlex Deucher 	}
476d38ceaf9SAlex Deucher 
477a245daf3SChristian König 	for (i = 0; i < adev->num_ip_blocks; i++)
478a1255107SAlex Deucher 		if (adev->ip_blocks[i].version->type == type &&
479a245daf3SChristian König 		    adev->ip_blocks[i].status.valid)
480a245daf3SChristian König 			break;
481a245daf3SChristian König 
482a245daf3SChristian König 	if (i == adev->num_ip_blocks)
483a245daf3SChristian König 		return 0;
484a245daf3SChristian König 
4851b1f2fecSChristian König 	num_rings = min(amdgpu_ctx_num_entities[info->query_hw_ip.type],
4861b1f2fecSChristian König 			num_rings);
4871b1f2fecSChristian König 
488a245daf3SChristian König 	result->hw_ip_version_major = adev->ip_blocks[i].version->major;
489a245daf3SChristian König 	result->hw_ip_version_minor = adev->ip_blocks[i].version->minor;
490af14e7c2SAlex Deucher 
491af14e7c2SAlex Deucher 	if (adev->asic_type >= CHIP_VEGA10) {
492af14e7c2SAlex Deucher 		switch (type) {
493af14e7c2SAlex Deucher 		case AMD_IP_BLOCK_TYPE_GFX:
494af14e7c2SAlex Deucher 			result->ip_discovery_version = adev->ip_versions[GC_HWIP][0];
495af14e7c2SAlex Deucher 			break;
496af14e7c2SAlex Deucher 		case AMD_IP_BLOCK_TYPE_SDMA:
497af14e7c2SAlex Deucher 			result->ip_discovery_version = adev->ip_versions[SDMA0_HWIP][0];
498af14e7c2SAlex Deucher 			break;
499af14e7c2SAlex Deucher 		case AMD_IP_BLOCK_TYPE_UVD:
500af14e7c2SAlex Deucher 		case AMD_IP_BLOCK_TYPE_VCN:
501af14e7c2SAlex Deucher 		case AMD_IP_BLOCK_TYPE_JPEG:
502af14e7c2SAlex Deucher 			result->ip_discovery_version = adev->ip_versions[UVD_HWIP][0];
503af14e7c2SAlex Deucher 			break;
504af14e7c2SAlex Deucher 		case AMD_IP_BLOCK_TYPE_VCE:
505af14e7c2SAlex Deucher 			result->ip_discovery_version = adev->ip_versions[VCE_HWIP][0];
506af14e7c2SAlex Deucher 			break;
507af14e7c2SAlex Deucher 		default:
508af14e7c2SAlex Deucher 			result->ip_discovery_version = 0;
509af14e7c2SAlex Deucher 			break;
510af14e7c2SAlex Deucher 		}
511af14e7c2SAlex Deucher 	} else {
512af14e7c2SAlex Deucher 		result->ip_discovery_version = 0;
513af14e7c2SAlex Deucher 	}
514a245daf3SChristian König 	result->capabilities_flags = 0;
5151b1f2fecSChristian König 	result->available_rings = (1 << num_rings) - 1;
516a245daf3SChristian König 	result->ib_start_alignment = ib_start_alignment;
517a245daf3SChristian König 	result->ib_size_alignment = ib_size_alignment;
518a245daf3SChristian König 	return 0;
519a245daf3SChristian König }
520a245daf3SChristian König 
521a245daf3SChristian König /*
522a245daf3SChristian König  * Userspace get information ioctl
523a245daf3SChristian König  */
524a245daf3SChristian König /**
525a245daf3SChristian König  * amdgpu_info_ioctl - answer a device specific request.
526a245daf3SChristian König  *
5278970b698SLee Jones  * @dev: drm device pointer
528a245daf3SChristian König  * @data: request object
529a245daf3SChristian König  * @filp: drm filp
530a245daf3SChristian König  *
531a245daf3SChristian König  * This function is used to pass device specific parameters to the userspace
532a245daf3SChristian König  * drivers.  Examples include: pci device id, pipeline parms, tiling params,
533a245daf3SChristian König  * etc. (all asics).
534a245daf3SChristian König  * Returns 0 on success, -EINVAL on failure.
535a245daf3SChristian König  */
amdgpu_info_ioctl(struct drm_device * dev,void * data,struct drm_file * filp)5365088d657SLuben Tuikov int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
537a245daf3SChristian König {
5381348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
539a245daf3SChristian König 	struct drm_amdgpu_info *info = data;
540a245daf3SChristian König 	struct amdgpu_mode_info *minfo = &adev->mode_info;
541a245daf3SChristian König 	void __user *out = (void __user *)(uintptr_t)info->return_pointer;
542a245daf3SChristian König 	uint32_t size = info->return_size;
543a245daf3SChristian König 	struct drm_crtc *crtc;
544a245daf3SChristian König 	uint32_t ui32 = 0;
545a245daf3SChristian König 	uint64_t ui64 = 0;
546a245daf3SChristian König 	int i, found;
547a245daf3SChristian König 	int ui32_size = sizeof(ui32);
548a245daf3SChristian König 
549a245daf3SChristian König 	if (!info->return_size || !info->return_pointer)
550a245daf3SChristian König 		return -EINVAL;
551a245daf3SChristian König 
552a245daf3SChristian König 	switch (info->query) {
553a245daf3SChristian König 	case AMDGPU_INFO_ACCEL_WORKING:
554a245daf3SChristian König 		ui32 = adev->accel_working;
555a245daf3SChristian König 		return copy_to_user(out, &ui32, min(size, 4u)) ? -EFAULT : 0;
556a245daf3SChristian König 	case AMDGPU_INFO_CRTC_FROM_ID:
557a245daf3SChristian König 		for (i = 0, found = 0; i < adev->mode_info.num_crtc; i++) {
558a245daf3SChristian König 			crtc = (struct drm_crtc *)minfo->crtcs[i];
559a245daf3SChristian König 			if (crtc && crtc->base.id == info->mode_crtc.id) {
560a245daf3SChristian König 				struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
561a0cc8e15SSrinivasan Shanmugam 
562a245daf3SChristian König 				ui32 = amdgpu_crtc->crtc_id;
563a245daf3SChristian König 				found = 1;
564d38ceaf9SAlex Deucher 				break;
565d38ceaf9SAlex Deucher 			}
566d38ceaf9SAlex Deucher 		}
567a245daf3SChristian König 		if (!found) {
568a245daf3SChristian König 			DRM_DEBUG_KMS("unknown crtc id %d\n", info->mode_crtc.id);
569a245daf3SChristian König 			return -EINVAL;
570a245daf3SChristian König 		}
571a245daf3SChristian König 		return copy_to_user(out, &ui32, min(size, 4u)) ? -EFAULT : 0;
572a245daf3SChristian König 	case AMDGPU_INFO_HW_IP_INFO: {
573a245daf3SChristian König 		struct drm_amdgpu_info_hw_ip ip = {};
574a245daf3SChristian König 		int ret;
575a245daf3SChristian König 
576a245daf3SChristian König 		ret = amdgpu_hw_ip_info(adev, info, &ip);
577a245daf3SChristian König 		if (ret)
578a245daf3SChristian König 			return ret;
579a245daf3SChristian König 
580a0cc8e15SSrinivasan Shanmugam 		ret = copy_to_user(out, &ip, min_t(size_t, size, sizeof(ip)));
581a245daf3SChristian König 		return ret ? -EFAULT : 0;
582d38ceaf9SAlex Deucher 	}
583d38ceaf9SAlex Deucher 	case AMDGPU_INFO_HW_IP_COUNT: {
5845fc3aeebSyanyang1 		enum amd_ip_block_type type;
585d38ceaf9SAlex Deucher 		uint32_t count = 0;
586d38ceaf9SAlex Deucher 
587d38ceaf9SAlex Deucher 		switch (info->query_hw_ip.type) {
588d38ceaf9SAlex Deucher 		case AMDGPU_HW_IP_GFX:
5895fc3aeebSyanyang1 			type = AMD_IP_BLOCK_TYPE_GFX;
590d38ceaf9SAlex Deucher 			break;
591d38ceaf9SAlex Deucher 		case AMDGPU_HW_IP_COMPUTE:
5925fc3aeebSyanyang1 			type = AMD_IP_BLOCK_TYPE_GFX;
593d38ceaf9SAlex Deucher 			break;
594d38ceaf9SAlex Deucher 		case AMDGPU_HW_IP_DMA:
5955fc3aeebSyanyang1 			type = AMD_IP_BLOCK_TYPE_SDMA;
596d38ceaf9SAlex Deucher 			break;
597d38ceaf9SAlex Deucher 		case AMDGPU_HW_IP_UVD:
5985fc3aeebSyanyang1 			type = AMD_IP_BLOCK_TYPE_UVD;
599d38ceaf9SAlex Deucher 			break;
600d38ceaf9SAlex Deucher 		case AMDGPU_HW_IP_VCE:
6015fc3aeebSyanyang1 			type = AMD_IP_BLOCK_TYPE_VCE;
602d38ceaf9SAlex Deucher 			break;
60363defd3fSLeo Liu 		case AMDGPU_HW_IP_UVD_ENC:
60463defd3fSLeo Liu 			type = AMD_IP_BLOCK_TYPE_UVD;
60563defd3fSLeo Liu 			break;
606bdc799e5SLeo Liu 		case AMDGPU_HW_IP_VCN_DEC:
607cefbc598SLeo Liu 		case AMDGPU_HW_IP_VCN_ENC:
608bdc799e5SLeo Liu 			type = AMD_IP_BLOCK_TYPE_VCN;
609bdc799e5SLeo Liu 			break;
61052f2e779SLeo Liu 		case AMDGPU_HW_IP_VCN_JPEG:
61152f2e779SLeo Liu 			type = (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_JPEG)) ?
61252f2e779SLeo Liu 				AMD_IP_BLOCK_TYPE_JPEG : AMD_IP_BLOCK_TYPE_VCN;
61352f2e779SLeo Liu 			break;
614d38ceaf9SAlex Deucher 		default:
615d38ceaf9SAlex Deucher 			return -EINVAL;
616d38ceaf9SAlex Deucher 		}
617d38ceaf9SAlex Deucher 
618d38ceaf9SAlex Deucher 		for (i = 0; i < adev->num_ip_blocks; i++)
619a1255107SAlex Deucher 			if (adev->ip_blocks[i].version->type == type &&
620a1255107SAlex Deucher 			    adev->ip_blocks[i].status.valid &&
621d38ceaf9SAlex Deucher 			    count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
622d38ceaf9SAlex Deucher 				count++;
623d38ceaf9SAlex Deucher 
624d38ceaf9SAlex Deucher 		return copy_to_user(out, &count, min(size, 4u)) ? -EFAULT : 0;
625d38ceaf9SAlex Deucher 	}
626d38ceaf9SAlex Deucher 	case AMDGPU_INFO_TIMESTAMP:
627b95e31fdSAlex Deucher 		ui64 = amdgpu_gfx_get_gpu_clock_counter(adev);
628d38ceaf9SAlex Deucher 		return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
629d38ceaf9SAlex Deucher 	case AMDGPU_INFO_FW_VERSION: {
630d38ceaf9SAlex Deucher 		struct drm_amdgpu_info_firmware fw_info;
631000cab9aSHuang Rui 		int ret;
632d38ceaf9SAlex Deucher 
633d38ceaf9SAlex Deucher 		/* We only support one instance of each IP block right now. */
634d38ceaf9SAlex Deucher 		if (info->query_fw.ip_instance != 0)
635d38ceaf9SAlex Deucher 			return -EINVAL;
636d38ceaf9SAlex Deucher 
637000cab9aSHuang Rui 		ret = amdgpu_firmware_info(&fw_info, &info->query_fw, adev);
638000cab9aSHuang Rui 		if (ret)
639000cab9aSHuang Rui 			return ret;
640000cab9aSHuang Rui 
641d38ceaf9SAlex Deucher 		return copy_to_user(out, &fw_info,
642d38ceaf9SAlex Deucher 				    min((size_t)size, sizeof(fw_info))) ? -EFAULT : 0;
643d38ceaf9SAlex Deucher 	}
644d38ceaf9SAlex Deucher 	case AMDGPU_INFO_NUM_BYTES_MOVED:
645d38ceaf9SAlex Deucher 		ui64 = atomic64_read(&adev->num_bytes_moved);
646d38ceaf9SAlex Deucher 		return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
64783a59b63SMarek Olšák 	case AMDGPU_INFO_NUM_EVICTIONS:
64883a59b63SMarek Olšák 		ui64 = atomic64_read(&adev->num_evictions);
64983a59b63SMarek Olšák 		return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
65068e2c5ffSMarek Olšák 	case AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS:
65168e2c5ffSMarek Olšák 		ui64 = atomic64_read(&adev->num_vram_cpu_page_faults);
65268e2c5ffSMarek Olšák 		return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
653d38ceaf9SAlex Deucher 	case AMDGPU_INFO_VRAM_USAGE:
6547db47b83SChristian König 		ui64 = ttm_resource_manager_usage(&adev->mman.vram_mgr.manager);
655d38ceaf9SAlex Deucher 		return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
656d38ceaf9SAlex Deucher 	case AMDGPU_INFO_VIS_VRAM_USAGE:
657ec6aae97SNirmoy Das 		ui64 = amdgpu_vram_mgr_vis_usage(&adev->mman.vram_mgr);
658d38ceaf9SAlex Deucher 		return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
659d38ceaf9SAlex Deucher 	case AMDGPU_INFO_GTT_USAGE:
660dfa714b8SChristian König 		ui64 = ttm_resource_manager_usage(&adev->mman.gtt_mgr.manager);
661d38ceaf9SAlex Deucher 		return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
662d38ceaf9SAlex Deucher 	case AMDGPU_INFO_GDS_CONFIG: {
663d38ceaf9SAlex Deucher 		struct drm_amdgpu_info_gds gds_info;
664d38ceaf9SAlex Deucher 
665c92b90ccSAlex Deucher 		memset(&gds_info, 0, sizeof(gds_info));
666dca29491SChristian König 		gds_info.compute_partition_size = adev->gds.gds_size;
667dca29491SChristian König 		gds_info.gds_total_size = adev->gds.gds_size;
668dca29491SChristian König 		gds_info.gws_per_compute_partition = adev->gds.gws_size;
669dca29491SChristian König 		gds_info.oa_per_compute_partition = adev->gds.oa_size;
670d38ceaf9SAlex Deucher 		return copy_to_user(out, &gds_info,
671d38ceaf9SAlex Deucher 				    min((size_t)size, sizeof(gds_info))) ? -EFAULT : 0;
672d38ceaf9SAlex Deucher 	}
673d38ceaf9SAlex Deucher 	case AMDGPU_INFO_VRAM_GTT: {
674d38ceaf9SAlex Deucher 		struct drm_amdgpu_info_vram_gtt vram_gtt;
675d38ceaf9SAlex Deucher 
676a5ccfe5cSMichel Dänzer 		vram_gtt.vram_size = adev->gmc.real_vram_size -
6779d1b3c78SChristian König 			atomic64_read(&adev->vram_pin_size) -
6789d1b3c78SChristian König 			AMDGPU_VM_RESERVED_VRAM;
6799d1b3c78SChristian König 		vram_gtt.vram_cpu_accessible_size =
6809d1b3c78SChristian König 			min(adev->gmc.visible_vram_size -
6819d1b3c78SChristian König 			    atomic64_read(&adev->visible_pin_size),
6829d1b3c78SChristian König 			    vram_gtt.vram_size);
6836c28aed6SDave Airlie 		vram_gtt.gtt_size = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT)->size;
684a5ccfe5cSMichel Dänzer 		vram_gtt.gtt_size -= atomic64_read(&adev->gart_pin_size);
685d38ceaf9SAlex Deucher 		return copy_to_user(out, &vram_gtt,
686d38ceaf9SAlex Deucher 				    min((size_t)size, sizeof(vram_gtt))) ? -EFAULT : 0;
687d38ceaf9SAlex Deucher 	}
688e0adf6c8SJunwei Zhang 	case AMDGPU_INFO_MEMORY: {
689e0adf6c8SJunwei Zhang 		struct drm_amdgpu_memory_info mem;
6909de59bc2SDave Airlie 		struct ttm_resource_manager *gtt_man =
691dfa714b8SChristian König 			&adev->mman.gtt_mgr.manager;
6927db47b83SChristian König 		struct ttm_resource_manager *vram_man =
6937db47b83SChristian König 			&adev->mman.vram_mgr.manager;
694dfa714b8SChristian König 
695e0adf6c8SJunwei Zhang 		memset(&mem, 0, sizeof(mem));
696770d13b1SChristian König 		mem.vram.total_heap_size = adev->gmc.real_vram_size;
697a5ccfe5cSMichel Dänzer 		mem.vram.usable_heap_size = adev->gmc.real_vram_size -
6989d1b3c78SChristian König 			atomic64_read(&adev->vram_pin_size) -
6999d1b3c78SChristian König 			AMDGPU_VM_RESERVED_VRAM;
7003c848bb3SChristian König 		mem.vram.heap_usage =
7017db47b83SChristian König 			ttm_resource_manager_usage(vram_man);
702e0adf6c8SJunwei Zhang 		mem.vram.max_allocation = mem.vram.usable_heap_size * 3 / 4;
703cfa32556SJunwei Zhang 
704e0adf6c8SJunwei Zhang 		mem.cpu_accessible_vram.total_heap_size =
705770d13b1SChristian König 			adev->gmc.visible_vram_size;
7069d1b3c78SChristian König 		mem.cpu_accessible_vram.usable_heap_size =
7079d1b3c78SChristian König 			min(adev->gmc.visible_vram_size -
7089d1b3c78SChristian König 			    atomic64_read(&adev->visible_pin_size),
7099d1b3c78SChristian König 			    mem.vram.usable_heap_size);
710e0adf6c8SJunwei Zhang 		mem.cpu_accessible_vram.heap_usage =
711ec6aae97SNirmoy Das 			amdgpu_vram_mgr_vis_usage(&adev->mman.vram_mgr);
712e0adf6c8SJunwei Zhang 		mem.cpu_accessible_vram.max_allocation =
713e0adf6c8SJunwei Zhang 			mem.cpu_accessible_vram.usable_heap_size * 3 / 4;
714cfa32556SJunwei Zhang 
7156c28aed6SDave Airlie 		mem.gtt.total_heap_size = gtt_man->size;
716a5ccfe5cSMichel Dänzer 		mem.gtt.usable_heap_size = mem.gtt.total_heap_size -
717a5ccfe5cSMichel Dänzer 			atomic64_read(&adev->gart_pin_size);
718dfa714b8SChristian König 		mem.gtt.heap_usage = ttm_resource_manager_usage(gtt_man);
719e0adf6c8SJunwei Zhang 		mem.gtt.max_allocation = mem.gtt.usable_heap_size * 3 / 4;
720cfa32556SJunwei Zhang 
721e0adf6c8SJunwei Zhang 		return copy_to_user(out, &mem,
722e0adf6c8SJunwei Zhang 				    min((size_t)size, sizeof(mem)))
723cfa32556SJunwei Zhang 				    ? -EFAULT : 0;
724cfa32556SJunwei Zhang 	}
725d38ceaf9SAlex Deucher 	case AMDGPU_INFO_READ_MMR_REG: {
726*8361e3f7SVictor Skvortsov 		int ret = 0;
727a0cc8e15SSrinivasan Shanmugam 		unsigned int n, alloc_size;
728d38ceaf9SAlex Deucher 		uint32_t *regs;
729a0cc8e15SSrinivasan Shanmugam 		unsigned int se_num = (info->read_mmr_reg.instance >>
730d38ceaf9SAlex Deucher 				   AMDGPU_INFO_MMR_SE_INDEX_SHIFT) &
731d38ceaf9SAlex Deucher 				  AMDGPU_INFO_MMR_SE_INDEX_MASK;
732a0cc8e15SSrinivasan Shanmugam 		unsigned int sh_num = (info->read_mmr_reg.instance >>
733d38ceaf9SAlex Deucher 				   AMDGPU_INFO_MMR_SH_INDEX_SHIFT) &
734d38ceaf9SAlex Deucher 				  AMDGPU_INFO_MMR_SH_INDEX_MASK;
735d38ceaf9SAlex Deucher 
736*8361e3f7SVictor Skvortsov 		if (!down_read_trylock(&adev->reset_domain->sem))
737*8361e3f7SVictor Skvortsov 			return -ENOENT;
738*8361e3f7SVictor Skvortsov 
739d38ceaf9SAlex Deucher 		/* set full masks if the userspace set all bits
740a0cc8e15SSrinivasan Shanmugam 		 * in the bitfields
741a0cc8e15SSrinivasan Shanmugam 		 */
742*8361e3f7SVictor Skvortsov 		if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK) {
743d38ceaf9SAlex Deucher 			se_num = 0xffffffff;
744*8361e3f7SVictor Skvortsov 		} else if (se_num >= AMDGPU_GFX_MAX_SE) {
745*8361e3f7SVictor Skvortsov 			ret = -EINVAL;
746*8361e3f7SVictor Skvortsov 			goto out;
747*8361e3f7SVictor Skvortsov 		}
748d38ceaf9SAlex Deucher 
749*8361e3f7SVictor Skvortsov 		if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK) {
750*8361e3f7SVictor Skvortsov 			sh_num = 0xffffffff;
751*8361e3f7SVictor Skvortsov 		} else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE) {
752*8361e3f7SVictor Skvortsov 			ret = -EINVAL;
753*8361e3f7SVictor Skvortsov 			goto out;
754*8361e3f7SVictor Skvortsov 		}
755*8361e3f7SVictor Skvortsov 
756*8361e3f7SVictor Skvortsov 		if (info->read_mmr_reg.count > 128) {
757*8361e3f7SVictor Skvortsov 			ret = -EINVAL;
758*8361e3f7SVictor Skvortsov 			goto out;
759*8361e3f7SVictor Skvortsov 		}
76073d8e6c7STrek 
7610d2edd37SDan Carpenter 		regs = kmalloc_array(info->read_mmr_reg.count, sizeof(*regs), GFP_KERNEL);
762*8361e3f7SVictor Skvortsov 		if (!regs) {
763*8361e3f7SVictor Skvortsov 			ret = -ENOMEM;
764*8361e3f7SVictor Skvortsov 			goto out;
765*8361e3f7SVictor Skvortsov 		}
766*8361e3f7SVictor Skvortsov 
7670d2edd37SDan Carpenter 		alloc_size = info->read_mmr_reg.count * sizeof(*regs);
768d38ceaf9SAlex Deucher 
769ca9317b9SAlex Deucher 		amdgpu_gfx_off_ctrl(adev, false);
770ca9317b9SAlex Deucher 		for (i = 0; i < info->read_mmr_reg.count; i++) {
771d38ceaf9SAlex Deucher 			if (amdgpu_asic_read_register(adev, se_num, sh_num,
772d38ceaf9SAlex Deucher 						      info->read_mmr_reg.dword_offset + i,
773d38ceaf9SAlex Deucher 						      &regs[i])) {
774d38ceaf9SAlex Deucher 				DRM_DEBUG_KMS("unallowed offset %#x\n",
775d38ceaf9SAlex Deucher 					      info->read_mmr_reg.dword_offset + i);
776d38ceaf9SAlex Deucher 				kfree(regs);
777ca9317b9SAlex Deucher 				amdgpu_gfx_off_ctrl(adev, true);
778*8361e3f7SVictor Skvortsov 				ret = -EFAULT;
779*8361e3f7SVictor Skvortsov 				goto out;
780d38ceaf9SAlex Deucher 			}
781ca9317b9SAlex Deucher 		}
782ca9317b9SAlex Deucher 		amdgpu_gfx_off_ctrl(adev, true);
783d38ceaf9SAlex Deucher 		n = copy_to_user(out, regs, min(size, alloc_size));
784d38ceaf9SAlex Deucher 		kfree(regs);
785*8361e3f7SVictor Skvortsov 		ret = (n ? -EFAULT : 0);
786*8361e3f7SVictor Skvortsov out:
787*8361e3f7SVictor Skvortsov 		up_read(&adev->reset_domain->sem);
788*8361e3f7SVictor Skvortsov 		return ret;
789d38ceaf9SAlex Deucher 	}
790d38ceaf9SAlex Deucher 	case AMDGPU_INFO_DEV_INFO: {
791a5a52a43SLee Jones 		struct drm_amdgpu_info_device *dev_info;
7925b565e0eSChristian König 		uint64_t vm_size;
793e3e84b0aSMarek Olšák 		uint32_t pcie_gen_mask;
794a5a52a43SLee Jones 		int ret;
795d38ceaf9SAlex Deucher 
796a5a52a43SLee Jones 		dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
797a5a52a43SLee Jones 		if (!dev_info)
798a5a52a43SLee Jones 			return -ENOMEM;
799a5a52a43SLee Jones 
8008f66090bSThomas Zimmermann 		dev_info->device_id = adev->pdev->device;
801a5a52a43SLee Jones 		dev_info->chip_rev = adev->rev_id;
802a5a52a43SLee Jones 		dev_info->external_rev = adev->external_rev_id;
8038f66090bSThomas Zimmermann 		dev_info->pci_rev = adev->pdev->revision;
804a5a52a43SLee Jones 		dev_info->family = adev->family;
805a5a52a43SLee Jones 		dev_info->num_shader_engines = adev->gfx.config.max_shader_engines;
806a5a52a43SLee Jones 		dev_info->num_shader_arrays_per_engine = adev->gfx.config.max_sh_per_se;
807d38ceaf9SAlex Deucher 		/* return all clocks in KHz */
808a5a52a43SLee Jones 		dev_info->gpu_counter_freq = amdgpu_asic_get_xclk(adev) * 10;
80932bf7106SKen Wang 		if (adev->pm.dpm_enabled) {
810a5a52a43SLee Jones 			dev_info->max_engine_clock = amdgpu_dpm_get_sclk(adev, false) * 10;
811a5a52a43SLee Jones 			dev_info->max_memory_clock = amdgpu_dpm_get_mclk(adev, false) * 10;
81288347fa1SEvan Quan 			dev_info->min_engine_clock = amdgpu_dpm_get_sclk(adev, true) * 10;
81388347fa1SEvan Quan 			dev_info->min_memory_clock = amdgpu_dpm_get_mclk(adev, true) * 10;
81432bf7106SKen Wang 		} else {
81588347fa1SEvan Quan 			dev_info->max_engine_clock =
81688347fa1SEvan Quan 				dev_info->min_engine_clock =
81788347fa1SEvan Quan 					adev->clock.default_sclk * 10;
81888347fa1SEvan Quan 			dev_info->max_memory_clock =
81988347fa1SEvan Quan 				dev_info->min_memory_clock =
82088347fa1SEvan Quan 					adev->clock.default_mclk * 10;
82132bf7106SKen Wang 		}
822a5a52a43SLee Jones 		dev_info->enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask;
823a5a52a43SLee Jones 		dev_info->num_rb_pipes = adev->gfx.config.max_backends_per_se *
8240b10029dSAlex Deucher 			adev->gfx.config.max_shader_engines;
825a5a52a43SLee Jones 		dev_info->num_hw_gfx_contexts = adev->gfx.config.max_hw_contexts;
826a5a52a43SLee Jones 		dev_info->ids_flags = 0;
8272f7d10b3SJammy Zhou 		if (adev->flags & AMD_IS_APU)
828a5a52a43SLee Jones 			dev_info->ids_flags |= AMDGPU_IDS_FLAGS_FUSION;
82902ff519eSAlex Deucher 		if (adev->gfx.mcbp)
830a5a52a43SLee Jones 			dev_info->ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION;
83116c642ecSPierre-Eric Pelloux-Prayer 		if (amdgpu_is_tmz(adev))
832a5a52a43SLee Jones 			dev_info->ids_flags |= AMDGPU_IDS_FLAGS_TMZ;
833b299221fSMarek Olšák 		if (adev->gfx.config.ta_cntl2_truncate_coord_mode)
834b299221fSMarek Olšák 			dev_info->ids_flags |= AMDGPU_IDS_FLAGS_CONFORMANT_TRUNC_COORD;
8355b565e0eSChristian König 
8365b565e0eSChristian König 		vm_size = adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE;
837a3e9a15aSChristian König 		vm_size -= AMDGPU_VA_RESERVED_SIZE;
8386b034e25SChristian König 
8396b034e25SChristian König 		/* Older VCE FW versions are buggy and can handle only 40bits */
84009b6f25bSChristian König 		if (adev->vce.fw_version &&
84109b6f25bSChristian König 		    adev->vce.fw_version < AMDGPU_VCE_FW_53_45)
8426b034e25SChristian König 			vm_size = min(vm_size, 1ULL << 40);
8436b034e25SChristian König 
844a5a52a43SLee Jones 		dev_info->virtual_address_offset = AMDGPU_VA_RESERVED_SIZE;
845a5a52a43SLee Jones 		dev_info->virtual_address_max =
846ad9a5b78SChristian König 			min(vm_size, AMDGPU_GMC_HOLE_START);
8475b565e0eSChristian König 
848ad9a5b78SChristian König 		if (vm_size > AMDGPU_GMC_HOLE_START) {
849a5a52a43SLee Jones 			dev_info->high_va_offset = AMDGPU_GMC_HOLE_END;
850a5a52a43SLee Jones 			dev_info->high_va_max = AMDGPU_GMC_HOLE_END | vm_size;
8515b565e0eSChristian König 		}
852f4d3da72SHuacai Chen 		dev_info->virtual_address_alignment = max_t(u32, PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE);
853a5a52a43SLee Jones 		dev_info->pte_fragment_size = (1 << adev->vm_manager.fragment_size) * AMDGPU_GPU_PAGE_SIZE;
854f4d3da72SHuacai Chen 		dev_info->gart_page_size = max_t(u32, PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE);
855a5a52a43SLee Jones 		dev_info->cu_active_number = adev->gfx.cu_info.number;
856a5a52a43SLee Jones 		dev_info->cu_ao_mask = adev->gfx.cu_info.ao_cu_mask;
857a5a52a43SLee Jones 		dev_info->ce_ram_size = adev->gfx.ce_ram_size;
858a5a52a43SLee Jones 		memcpy(&dev_info->cu_ao_bitmap[0], &adev->gfx.cu_info.ao_cu_bitmap[0],
859dbfe85eaSFlora Cui 		       sizeof(adev->gfx.cu_info.ao_cu_bitmap));
860a5a52a43SLee Jones 		memcpy(&dev_info->cu_bitmap[0], &adev->gfx.cu_info.bitmap[0],
86197e3c6a8SMukul Joshi 		       sizeof(dev_info->cu_bitmap));
862a5a52a43SLee Jones 		dev_info->vram_type = adev->gmc.vram_type;
863a5a52a43SLee Jones 		dev_info->vram_bit_width = adev->gmc.vram_width;
864a5a52a43SLee Jones 		dev_info->vce_harvest_config = adev->vce.harvest_config;
865a5a52a43SLee Jones 		dev_info->gc_double_offchip_lds_buf =
866df6e2c4aSJunwei Zhang 			adev->gfx.config.double_offchip_lds_buf;
867a5a52a43SLee Jones 		dev_info->wave_front_size = adev->gfx.cu_info.wave_front_size;
868a5a52a43SLee Jones 		dev_info->num_shader_visible_vgprs = adev->gfx.config.max_gprs;
869a5a52a43SLee Jones 		dev_info->num_cu_per_sh = adev->gfx.config.max_cu_per_sh;
870a5a52a43SLee Jones 		dev_info->num_tcc_blocks = adev->gfx.config.max_texture_channel_caches;
871a5a52a43SLee Jones 		dev_info->gs_vgt_table_depth = adev->gfx.config.gs_vgt_table_depth;
872a5a52a43SLee Jones 		dev_info->gs_prim_buffer_depth = adev->gfx.config.gs_prim_buffer_depth;
873a5a52a43SLee Jones 		dev_info->max_gs_waves_per_vgt = adev->gfx.config.max_gs_threads;
874bce23e00SAlex Deucher 
875be9250fbSHawking Zhang 		if (adev->family >= AMDGPU_FAMILY_NV)
876a5a52a43SLee Jones 			dev_info->pa_sc_tile_steering_override =
877be9250fbSHawking Zhang 				adev->gfx.config.pa_sc_tile_steering_override;
878be9250fbSHawking Zhang 
879a5a52a43SLee Jones 		dev_info->tcc_disabled_mask = adev->gfx.config.tcc_disabled_mask;
880815fb4c9SMarek Olšák 
881e3e84b0aSMarek Olšák 		/* Combine the chip gen mask with the platform (CPU/mobo) mask. */
882e3e84b0aSMarek Olšák 		pcie_gen_mask = adev->pm.pcie_gen_mask & (adev->pm.pcie_gen_mask >> 16);
883e3e84b0aSMarek Olšák 		dev_info->pcie_gen = fls(pcie_gen_mask);
884e3e84b0aSMarek Olšák 		dev_info->pcie_num_lanes =
885e3e84b0aSMarek Olšák 			adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 ? 32 :
886e3e84b0aSMarek Olšák 			adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 ? 16 :
887e3e84b0aSMarek Olšák 			adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 ? 12 :
888e3e84b0aSMarek Olšák 			adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 ? 8 :
889e3e84b0aSMarek Olšák 			adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 ? 4 :
890e3e84b0aSMarek Olšák 			adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 ? 2 : 1;
891e3e84b0aSMarek Olšák 
892b299221fSMarek Olšák 		dev_info->tcp_cache_size = adev->gfx.config.gc_tcp_l1_size;
893b299221fSMarek Olšák 		dev_info->num_sqc_per_wgp = adev->gfx.config.gc_num_sqc_per_wgp;
894b299221fSMarek Olšák 		dev_info->sqc_data_cache_size = adev->gfx.config.gc_l1_data_cache_size_per_sqc;
895b299221fSMarek Olšák 		dev_info->sqc_inst_cache_size = adev->gfx.config.gc_l1_instruction_cache_size_per_sqc;
896b299221fSMarek Olšák 		dev_info->gl1c_cache_size = adev->gfx.config.gc_gl1c_size_per_instance *
897b299221fSMarek Olšák 					    adev->gfx.config.gc_gl1c_per_sa;
898b299221fSMarek Olšák 		dev_info->gl2c_cache_size = adev->gfx.config.gc_gl2c_per_gpu;
899b299221fSMarek Olšák 		dev_info->mall_size = adev->gmc.mall_size;
900b299221fSMarek Olšák 
9011ba91b54SAlex Deucher 
9021ba91b54SAlex Deucher 		if (adev->gfx.funcs->get_gfx_shadow_info) {
9031ba91b54SAlex Deucher 			struct amdgpu_gfx_shadow_info shadow_info;
9041ba91b54SAlex Deucher 
9051ba91b54SAlex Deucher 			ret = amdgpu_gfx_get_gfx_shadow_info(adev, &shadow_info);
9061ba91b54SAlex Deucher 			if (!ret) {
9071ba91b54SAlex Deucher 				dev_info->shadow_size = shadow_info.shadow_size;
9081ba91b54SAlex Deucher 				dev_info->shadow_alignment = shadow_info.shadow_alignment;
9091ba91b54SAlex Deucher 				dev_info->csa_size = shadow_info.csa_size;
9101ba91b54SAlex Deucher 				dev_info->csa_alignment = shadow_info.csa_alignment;
9111ba91b54SAlex Deucher 			}
9121ba91b54SAlex Deucher 		}
9131ba91b54SAlex Deucher 
914a5a52a43SLee Jones 		ret = copy_to_user(out, dev_info,
915a5a52a43SLee Jones 				   min((size_t)size, sizeof(*dev_info))) ? -EFAULT : 0;
916a5a52a43SLee Jones 		kfree(dev_info);
917a5a52a43SLee Jones 		return ret;
918d38ceaf9SAlex Deucher 	}
91907fecde5SAlex Deucher 	case AMDGPU_INFO_VCE_CLOCK_TABLE: {
920a0cc8e15SSrinivasan Shanmugam 		unsigned int i;
92107fecde5SAlex Deucher 		struct drm_amdgpu_info_vce_clock_table vce_clk_table = {};
92207fecde5SAlex Deucher 		struct amd_vce_state *vce_state;
92307fecde5SAlex Deucher 
92407fecde5SAlex Deucher 		for (i = 0; i < AMDGPU_VCE_CLOCK_TABLE_ENTRIES; i++) {
92507fecde5SAlex Deucher 			vce_state = amdgpu_dpm_get_vce_clock_state(adev, i);
92607fecde5SAlex Deucher 			if (vce_state) {
92707fecde5SAlex Deucher 				vce_clk_table.entries[i].sclk = vce_state->sclk;
92807fecde5SAlex Deucher 				vce_clk_table.entries[i].mclk = vce_state->mclk;
92907fecde5SAlex Deucher 				vce_clk_table.entries[i].eclk = vce_state->evclk;
93007fecde5SAlex Deucher 				vce_clk_table.num_valid_entries++;
93107fecde5SAlex Deucher 			}
93207fecde5SAlex Deucher 		}
93307fecde5SAlex Deucher 
93407fecde5SAlex Deucher 		return copy_to_user(out, &vce_clk_table,
93507fecde5SAlex Deucher 				    min((size_t)size, sizeof(vce_clk_table))) ? -EFAULT : 0;
93607fecde5SAlex Deucher 	}
93740ee5888SEvan Quan 	case AMDGPU_INFO_VBIOS: {
93840ee5888SEvan Quan 		uint32_t bios_size = adev->bios_size;
93940ee5888SEvan Quan 
94040ee5888SEvan Quan 		switch (info->vbios_info.type) {
94140ee5888SEvan Quan 		case AMDGPU_INFO_VBIOS_SIZE:
94240ee5888SEvan Quan 			return copy_to_user(out, &bios_size,
94340ee5888SEvan Quan 					min((size_t)size, sizeof(bios_size)))
94440ee5888SEvan Quan 					? -EFAULT : 0;
94540ee5888SEvan Quan 		case AMDGPU_INFO_VBIOS_IMAGE: {
94640ee5888SEvan Quan 			uint8_t *bios;
94740ee5888SEvan Quan 			uint32_t bios_offset = info->vbios_info.offset;
94840ee5888SEvan Quan 
94940ee5888SEvan Quan 			if (bios_offset >= bios_size)
95040ee5888SEvan Quan 				return -EINVAL;
95140ee5888SEvan Quan 
95240ee5888SEvan Quan 			bios = adev->bios + bios_offset;
95340ee5888SEvan Quan 			return copy_to_user(out, bios,
95440ee5888SEvan Quan 					    min((size_t)size, (size_t)(bios_size - bios_offset)))
95540ee5888SEvan Quan 					? -EFAULT : 0;
95640ee5888SEvan Quan 		}
95729b4c589SJiawei Gu 		case AMDGPU_INFO_VBIOS_INFO: {
95829b4c589SJiawei Gu 			struct drm_amdgpu_info_vbios vbios_info = {};
95929b4c589SJiawei Gu 			struct atom_context *atom_context;
96029b4c589SJiawei Gu 
96129b4c589SJiawei Gu 			atom_context = adev->mode_info.atom_context;
9625e7e8225SDavid Francis 			if (atom_context) {
9635e7e8225SDavid Francis 				memcpy(vbios_info.name, atom_context->name,
9645e7e8225SDavid Francis 				       sizeof(atom_context->name));
9655e7e8225SDavid Francis 				memcpy(vbios_info.vbios_pn, atom_context->vbios_pn,
9665e7e8225SDavid Francis 				       sizeof(atom_context->vbios_pn));
96729b4c589SJiawei Gu 				vbios_info.version = atom_context->version;
96829b4c589SJiawei Gu 				memcpy(vbios_info.vbios_ver_str, atom_context->vbios_ver_str,
96929b4c589SJiawei Gu 				       sizeof(atom_context->vbios_ver_str));
9705e7e8225SDavid Francis 				memcpy(vbios_info.date, atom_context->date,
9715e7e8225SDavid Francis 				       sizeof(atom_context->date));
9725e7e8225SDavid Francis 			}
97329b4c589SJiawei Gu 
97429b4c589SJiawei Gu 			return copy_to_user(out, &vbios_info,
97529b4c589SJiawei Gu 						min((size_t)size, sizeof(vbios_info))) ? -EFAULT : 0;
97629b4c589SJiawei Gu 		}
97740ee5888SEvan Quan 		default:
97840ee5888SEvan Quan 			DRM_DEBUG_KMS("Invalid request %d\n",
97940ee5888SEvan Quan 					info->vbios_info.type);
98040ee5888SEvan Quan 			return -EINVAL;
98140ee5888SEvan Quan 		}
98240ee5888SEvan Quan 	}
98344879b62SArindam Nath 	case AMDGPU_INFO_NUM_HANDLES: {
98444879b62SArindam Nath 		struct drm_amdgpu_info_num_handles handle;
98544879b62SArindam Nath 
98644879b62SArindam Nath 		switch (info->query_hw_ip.type) {
98744879b62SArindam Nath 		case AMDGPU_HW_IP_UVD:
98844879b62SArindam Nath 			/* Starting Polaris, we support unlimited UVD handles */
98944879b62SArindam Nath 			if (adev->asic_type < CHIP_POLARIS10) {
99044879b62SArindam Nath 				handle.uvd_max_handles = adev->uvd.max_handles;
99144879b62SArindam Nath 				handle.uvd_used_handles = amdgpu_uvd_used_handles(adev);
99244879b62SArindam Nath 
99344879b62SArindam Nath 				return copy_to_user(out, &handle,
99444879b62SArindam Nath 					min((size_t)size, sizeof(handle))) ? -EFAULT : 0;
99544879b62SArindam Nath 			} else {
99644879b62SArindam Nath 				return -ENODATA;
99744879b62SArindam Nath 			}
99844879b62SArindam Nath 
99944879b62SArindam Nath 			break;
100044879b62SArindam Nath 		default:
100144879b62SArindam Nath 			return -EINVAL;
100244879b62SArindam Nath 		}
100344879b62SArindam Nath 	}
10045ebbac4bSAlex Deucher 	case AMDGPU_INFO_SENSOR: {
1005b13aa109SRex Zhu 		if (!adev->pm.dpm_enabled)
10065ebbac4bSAlex Deucher 			return -ENOENT;
10075ebbac4bSAlex Deucher 
10085ebbac4bSAlex Deucher 		switch (info->sensor_info.type) {
10095ebbac4bSAlex Deucher 		case AMDGPU_INFO_SENSOR_GFX_SCLK:
10105ebbac4bSAlex Deucher 			/* get sclk in Mhz */
10115ebbac4bSAlex Deucher 			if (amdgpu_dpm_read_sensor(adev,
10125ebbac4bSAlex Deucher 						   AMDGPU_PP_SENSOR_GFX_SCLK,
10135ebbac4bSAlex Deucher 						   (void *)&ui32, &ui32_size)) {
10145ebbac4bSAlex Deucher 				return -EINVAL;
10155ebbac4bSAlex Deucher 			}
10165ebbac4bSAlex Deucher 			ui32 /= 100;
10175ebbac4bSAlex Deucher 			break;
10185ebbac4bSAlex Deucher 		case AMDGPU_INFO_SENSOR_GFX_MCLK:
10195ebbac4bSAlex Deucher 			/* get mclk in Mhz */
10205ebbac4bSAlex Deucher 			if (amdgpu_dpm_read_sensor(adev,
10215ebbac4bSAlex Deucher 						   AMDGPU_PP_SENSOR_GFX_MCLK,
10225ebbac4bSAlex Deucher 						   (void *)&ui32, &ui32_size)) {
10235ebbac4bSAlex Deucher 				return -EINVAL;
10245ebbac4bSAlex Deucher 			}
10255ebbac4bSAlex Deucher 			ui32 /= 100;
10265ebbac4bSAlex Deucher 			break;
10275ebbac4bSAlex Deucher 		case AMDGPU_INFO_SENSOR_GPU_TEMP:
10285ebbac4bSAlex Deucher 			/* get temperature in millidegrees C */
10295ebbac4bSAlex Deucher 			if (amdgpu_dpm_read_sensor(adev,
10305ebbac4bSAlex Deucher 						   AMDGPU_PP_SENSOR_GPU_TEMP,
10315ebbac4bSAlex Deucher 						   (void *)&ui32, &ui32_size)) {
10325ebbac4bSAlex Deucher 				return -EINVAL;
10335ebbac4bSAlex Deucher 			}
10345ebbac4bSAlex Deucher 			break;
10355ebbac4bSAlex Deucher 		case AMDGPU_INFO_SENSOR_GPU_LOAD:
10365ebbac4bSAlex Deucher 			/* get GPU load */
10375ebbac4bSAlex Deucher 			if (amdgpu_dpm_read_sensor(adev,
10385ebbac4bSAlex Deucher 						   AMDGPU_PP_SENSOR_GPU_LOAD,
10395ebbac4bSAlex Deucher 						   (void *)&ui32, &ui32_size)) {
10405ebbac4bSAlex Deucher 				return -EINVAL;
10415ebbac4bSAlex Deucher 			}
10425ebbac4bSAlex Deucher 			break;
10435ebbac4bSAlex Deucher 		case AMDGPU_INFO_SENSOR_GPU_AVG_POWER:
10445ebbac4bSAlex Deucher 			/* get average GPU power */
10455ebbac4bSAlex Deucher 			if (amdgpu_dpm_read_sensor(adev,
10469366c2e8SMario Limonciello 						   AMDGPU_PP_SENSOR_GPU_AVG_POWER,
10475b79d048SRex Zhu 						   (void *)&ui32, &ui32_size)) {
1048836e236bSAlex Deucher 				/* fall back to input power for backwards compat */
1049836e236bSAlex Deucher 				if (amdgpu_dpm_read_sensor(adev,
1050836e236bSAlex Deucher 							   AMDGPU_PP_SENSOR_GPU_INPUT_POWER,
1051836e236bSAlex Deucher 							   (void *)&ui32, &ui32_size)) {
10525ebbac4bSAlex Deucher 					return -EINVAL;
10535ebbac4bSAlex Deucher 				}
1054836e236bSAlex Deucher 			}
10555b79d048SRex Zhu 			ui32 >>= 8;
10565ebbac4bSAlex Deucher 			break;
10575ebbac4bSAlex Deucher 		case AMDGPU_INFO_SENSOR_VDDNB:
10585ebbac4bSAlex Deucher 			/* get VDDNB in millivolts */
10595ebbac4bSAlex Deucher 			if (amdgpu_dpm_read_sensor(adev,
10605ebbac4bSAlex Deucher 						   AMDGPU_PP_SENSOR_VDDNB,
10615ebbac4bSAlex Deucher 						   (void *)&ui32, &ui32_size)) {
10625ebbac4bSAlex Deucher 				return -EINVAL;
10635ebbac4bSAlex Deucher 			}
10645ebbac4bSAlex Deucher 			break;
10655ebbac4bSAlex Deucher 		case AMDGPU_INFO_SENSOR_VDDGFX:
10665ebbac4bSAlex Deucher 			/* get VDDGFX in millivolts */
10675ebbac4bSAlex Deucher 			if (amdgpu_dpm_read_sensor(adev,
10685ebbac4bSAlex Deucher 						   AMDGPU_PP_SENSOR_VDDGFX,
10695ebbac4bSAlex Deucher 						   (void *)&ui32, &ui32_size)) {
10705ebbac4bSAlex Deucher 				return -EINVAL;
10715ebbac4bSAlex Deucher 			}
10725ebbac4bSAlex Deucher 			break;
107360bbade2SRex Zhu 		case AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_SCLK:
107460bbade2SRex Zhu 			/* get stable pstate sclk in Mhz */
107560bbade2SRex Zhu 			if (amdgpu_dpm_read_sensor(adev,
107660bbade2SRex Zhu 						   AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK,
107760bbade2SRex Zhu 						   (void *)&ui32, &ui32_size)) {
107860bbade2SRex Zhu 				return -EINVAL;
107960bbade2SRex Zhu 			}
108060bbade2SRex Zhu 			ui32 /= 100;
108160bbade2SRex Zhu 			break;
108260bbade2SRex Zhu 		case AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_MCLK:
108360bbade2SRex Zhu 			/* get stable pstate mclk in Mhz */
108460bbade2SRex Zhu 			if (amdgpu_dpm_read_sensor(adev,
108560bbade2SRex Zhu 						   AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK,
108660bbade2SRex Zhu 						   (void *)&ui32, &ui32_size)) {
108760bbade2SRex Zhu 				return -EINVAL;
108860bbade2SRex Zhu 			}
108960bbade2SRex Zhu 			ui32 /= 100;
109060bbade2SRex Zhu 			break;
10915cfd9784SEvan Quan 		case AMDGPU_INFO_SENSOR_PEAK_PSTATE_GFX_SCLK:
10925cfd9784SEvan Quan 			/* get peak pstate sclk in Mhz */
10935cfd9784SEvan Quan 			if (amdgpu_dpm_read_sensor(adev,
10945cfd9784SEvan Quan 						   AMDGPU_PP_SENSOR_PEAK_PSTATE_SCLK,
10955cfd9784SEvan Quan 						   (void *)&ui32, &ui32_size)) {
10965cfd9784SEvan Quan 				return -EINVAL;
10975cfd9784SEvan Quan 			}
10985cfd9784SEvan Quan 			ui32 /= 100;
10995cfd9784SEvan Quan 			break;
11005cfd9784SEvan Quan 		case AMDGPU_INFO_SENSOR_PEAK_PSTATE_GFX_MCLK:
11015cfd9784SEvan Quan 			/* get peak pstate mclk in Mhz */
11025cfd9784SEvan Quan 			if (amdgpu_dpm_read_sensor(adev,
11035cfd9784SEvan Quan 						   AMDGPU_PP_SENSOR_PEAK_PSTATE_MCLK,
11045cfd9784SEvan Quan 						   (void *)&ui32, &ui32_size)) {
11055cfd9784SEvan Quan 				return -EINVAL;
11065cfd9784SEvan Quan 			}
11075cfd9784SEvan Quan 			ui32 /= 100;
11085cfd9784SEvan Quan 			break;
11095ebbac4bSAlex Deucher 		default:
11105ebbac4bSAlex Deucher 			DRM_DEBUG_KMS("Invalid request %d\n",
11115ebbac4bSAlex Deucher 				      info->sensor_info.type);
11125ebbac4bSAlex Deucher 			return -EINVAL;
11135ebbac4bSAlex Deucher 		}
11145ebbac4bSAlex Deucher 		return copy_to_user(out, &ui32, min(size, 4u)) ? -EFAULT : 0;
11155ebbac4bSAlex Deucher 	}
11161f7251b7SChristian König 	case AMDGPU_INFO_VRAM_LOST_COUNTER:
11171f7251b7SChristian König 		ui32 = atomic_read(&adev->vram_lost_counter);
11181f7251b7SChristian König 		return copy_to_user(out, &ui32, min(size, 4u)) ? -EFAULT : 0;
11195cb77114Sxinhui pan 	case AMDGPU_INFO_RAS_ENABLED_FEATURES: {
11205cb77114Sxinhui pan 		struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
11211febb00eSxinhui pan 		uint64_t ras_mask;
11225cb77114Sxinhui pan 
11235cb77114Sxinhui pan 		if (!ras)
11245cb77114Sxinhui pan 			return -EINVAL;
11258ab0d6f0SLuben Tuikov 		ras_mask = (uint64_t)adev->ras_enabled << 32 | ras->features;
11261febb00eSxinhui pan 
11271febb00eSxinhui pan 		return copy_to_user(out, &ras_mask,
11281febb00eSxinhui pan 				min_t(u64, size, sizeof(ras_mask))) ?
11295cb77114Sxinhui pan 			-EFAULT : 0;
11305cb77114Sxinhui pan 	}
1131f35e9bdbSAlex Deucher 	case AMDGPU_INFO_VIDEO_CAPS: {
1132f35e9bdbSAlex Deucher 		const struct amdgpu_video_codecs *codecs;
1133f35e9bdbSAlex Deucher 		struct drm_amdgpu_info_video_caps *caps;
1134f35e9bdbSAlex Deucher 		int r;
1135f35e9bdbSAlex Deucher 
1136bc8ba5f2SAlex Deucher 		if (!adev->asic_funcs->query_video_codecs)
1137bc8ba5f2SAlex Deucher 			return -EINVAL;
1138bc8ba5f2SAlex Deucher 
1139f35e9bdbSAlex Deucher 		switch (info->video_cap.type) {
1140f35e9bdbSAlex Deucher 		case AMDGPU_INFO_VIDEO_CAPS_DECODE:
1141f35e9bdbSAlex Deucher 			r = amdgpu_asic_query_video_codecs(adev, false, &codecs);
1142f35e9bdbSAlex Deucher 			if (r)
1143f35e9bdbSAlex Deucher 				return -EINVAL;
1144f35e9bdbSAlex Deucher 			break;
1145f35e9bdbSAlex Deucher 		case AMDGPU_INFO_VIDEO_CAPS_ENCODE:
1146f35e9bdbSAlex Deucher 			r = amdgpu_asic_query_video_codecs(adev, true, &codecs);
1147f35e9bdbSAlex Deucher 			if (r)
1148f35e9bdbSAlex Deucher 				return -EINVAL;
1149f35e9bdbSAlex Deucher 			break;
1150f35e9bdbSAlex Deucher 		default:
1151f35e9bdbSAlex Deucher 			DRM_DEBUG_KMS("Invalid request %d\n",
1152f35e9bdbSAlex Deucher 				      info->video_cap.type);
1153f35e9bdbSAlex Deucher 			return -EINVAL;
1154f35e9bdbSAlex Deucher 		}
1155f35e9bdbSAlex Deucher 
1156f35e9bdbSAlex Deucher 		caps = kzalloc(sizeof(*caps), GFP_KERNEL);
1157f35e9bdbSAlex Deucher 		if (!caps)
1158f35e9bdbSAlex Deucher 			return -ENOMEM;
1159f35e9bdbSAlex Deucher 
1160f35e9bdbSAlex Deucher 		for (i = 0; i < codecs->codec_count; i++) {
1161f35e9bdbSAlex Deucher 			int idx = codecs->codec_array[i].codec_type;
1162f35e9bdbSAlex Deucher 
1163f35e9bdbSAlex Deucher 			switch (idx) {
11646f786950SAlex Deucher 			case AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2:
11656f786950SAlex Deucher 			case AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4:
11666f786950SAlex Deucher 			case AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1:
11676f786950SAlex Deucher 			case AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC:
11686f786950SAlex Deucher 			case AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC:
11696f786950SAlex Deucher 			case AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG:
11706f786950SAlex Deucher 			case AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9:
11716f786950SAlex Deucher 			case AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1:
1172f35e9bdbSAlex Deucher 				caps->codec_info[idx].valid = 1;
1173f35e9bdbSAlex Deucher 				caps->codec_info[idx].max_width =
1174f35e9bdbSAlex Deucher 					codecs->codec_array[i].max_width;
1175f35e9bdbSAlex Deucher 				caps->codec_info[idx].max_height =
1176f35e9bdbSAlex Deucher 					codecs->codec_array[i].max_height;
1177f35e9bdbSAlex Deucher 				caps->codec_info[idx].max_pixels_per_frame =
1178f35e9bdbSAlex Deucher 					codecs->codec_array[i].max_pixels_per_frame;
1179f35e9bdbSAlex Deucher 				caps->codec_info[idx].max_level =
1180f35e9bdbSAlex Deucher 					codecs->codec_array[i].max_level;
1181f35e9bdbSAlex Deucher 				break;
1182f35e9bdbSAlex Deucher 			default:
1183f35e9bdbSAlex Deucher 				break;
1184f35e9bdbSAlex Deucher 			}
1185f35e9bdbSAlex Deucher 		}
1186f35e9bdbSAlex Deucher 		r = copy_to_user(out, caps,
1187f35e9bdbSAlex Deucher 				 min((size_t)size, sizeof(*caps))) ? -EFAULT : 0;
1188f35e9bdbSAlex Deucher 		kfree(caps);
1189f35e9bdbSAlex Deucher 		return r;
1190f35e9bdbSAlex Deucher 	}
11914f18b9a6SBas Nieuwenhuizen 	case AMDGPU_INFO_MAX_IBS: {
11924f18b9a6SBas Nieuwenhuizen 		uint32_t max_ibs[AMDGPU_HW_IP_NUM];
11934f18b9a6SBas Nieuwenhuizen 
11944f18b9a6SBas Nieuwenhuizen 		for (i = 0; i < AMDGPU_HW_IP_NUM; ++i)
11954f18b9a6SBas Nieuwenhuizen 			max_ibs[i] = amdgpu_ring_max_ibs(i);
11964f18b9a6SBas Nieuwenhuizen 
11974f18b9a6SBas Nieuwenhuizen 		return copy_to_user(out, max_ibs,
11984f18b9a6SBas Nieuwenhuizen 				    min((size_t)size, sizeof(max_ibs))) ? -EFAULT : 0;
11994f18b9a6SBas Nieuwenhuizen 	}
1200d38ceaf9SAlex Deucher 	default:
1201d38ceaf9SAlex Deucher 		DRM_DEBUG_KMS("Invalid request %d\n", info->query);
1202d38ceaf9SAlex Deucher 		return -EINVAL;
1203d38ceaf9SAlex Deucher 	}
1204d38ceaf9SAlex Deucher 	return 0;
1205d38ceaf9SAlex Deucher }
1206d38ceaf9SAlex Deucher 
1207d38ceaf9SAlex Deucher 
1208d38ceaf9SAlex Deucher /*
1209d38ceaf9SAlex Deucher  * Outdated mess for old drm with Xorg being in charge (void function now).
1210d38ceaf9SAlex Deucher  */
1211d38ceaf9SAlex Deucher /**
12128b7530b1SAlex Deucher  * amdgpu_driver_lastclose_kms - drm callback for last close
1213d38ceaf9SAlex Deucher  *
1214d38ceaf9SAlex Deucher  * @dev: drm dev pointer
1215d38ceaf9SAlex Deucher  *
12161694467bSLukas Wunner  * Switch vga_switcheroo state after last close (all asics).
1217d38ceaf9SAlex Deucher  */
amdgpu_driver_lastclose_kms(struct drm_device * dev)1218d38ceaf9SAlex Deucher void amdgpu_driver_lastclose_kms(struct drm_device *dev)
1219d38ceaf9SAlex Deucher {
1220ab77e02cSNoralf Trønnes 	drm_fb_helper_lastclose(dev);
1221d38ceaf9SAlex Deucher 	vga_switcheroo_process_delayed_switch();
1222d38ceaf9SAlex Deucher }
1223d38ceaf9SAlex Deucher 
1224396bcb41SChristian König /**
1225d38ceaf9SAlex Deucher  * amdgpu_driver_open_kms - drm callback for open
1226d38ceaf9SAlex Deucher  *
1227d38ceaf9SAlex Deucher  * @dev: drm dev pointer
1228d38ceaf9SAlex Deucher  * @file_priv: drm file
1229d38ceaf9SAlex Deucher  *
1230d38ceaf9SAlex Deucher  * On device open, init vm on cayman+ (all asics).
1231d38ceaf9SAlex Deucher  * Returns 0 on success, error on failure.
1232d38ceaf9SAlex Deucher  */
amdgpu_driver_open_kms(struct drm_device * dev,struct drm_file * file_priv)1233d38ceaf9SAlex Deucher int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
1234d38ceaf9SAlex Deucher {
12351348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
1236d38ceaf9SAlex Deucher 	struct amdgpu_fpriv *fpriv;
12375c2ff9a6SChristian König 	int r, pasid;
1238d38ceaf9SAlex Deucher 
12392c486cc4SChristian König 	/* Ensure IB tests are run on ring */
1240beff74bcSAlex Deucher 	flush_delayed_work(&adev->delayed_init_work);
12412c486cc4SChristian König 
12427c6e68c7SAndrey Grodzovsky 
12437c6e68c7SAndrey Grodzovsky 	if (amdgpu_ras_intr_triggered()) {
12447c6e68c7SAndrey Grodzovsky 		DRM_ERROR("RAS Intr triggered, device disabled!!");
12457c6e68c7SAndrey Grodzovsky 		return -EHWPOISON;
12467c6e68c7SAndrey Grodzovsky 	}
12477c6e68c7SAndrey Grodzovsky 
1248d38ceaf9SAlex Deucher 	file_priv->driver_priv = NULL;
1249d38ceaf9SAlex Deucher 
1250d38ceaf9SAlex Deucher 	r = pm_runtime_get_sync(dev->dev);
1251d38ceaf9SAlex Deucher 	if (r < 0)
12529ba8923cSNavid Emamdoost 		goto pm_put;
1253d38ceaf9SAlex Deucher 
1254d38ceaf9SAlex Deucher 	fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
1255dc08267aSAlex Deucher 	if (unlikely(!fpriv)) {
1256dc08267aSAlex Deucher 		r = -ENOMEM;
1257dc08267aSAlex Deucher 		goto out_suspend;
1258dc08267aSAlex Deucher 	}
1259d38ceaf9SAlex Deucher 
12605c2ff9a6SChristian König 	pasid = amdgpu_pasid_alloc(16);
12615c2ff9a6SChristian König 	if (pasid < 0) {
12625c2ff9a6SChristian König 		dev_warn(adev->dev, "No more PASIDs available!");
12635c2ff9a6SChristian König 		pasid = 0;
1264dc08267aSAlex Deucher 	}
1265a35455d0SNirmoy Das 
126650e63308SGuchun Chen 	r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
12675c2ff9a6SChristian König 	if (r)
12685c2ff9a6SChristian König 		goto error_pasid;
1269d38ceaf9SAlex Deucher 
12705003ca63SGuchun Chen 	r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id);
1271934deb64SPhilip Yang 	if (r)
127250e63308SGuchun Chen 		goto error_pasid;
1273934deb64SPhilip Yang 
127488f7f881SNirmoy Das 	r = amdgpu_vm_set_pasid(adev, &fpriv->vm, pasid);
127588f7f881SNirmoy Das 	if (r)
127688f7f881SNirmoy Das 		goto error_vm;
127788f7f881SNirmoy Das 
1278b85891bdSJunwei Zhang 	fpriv->prt_va = amdgpu_vm_bo_add(adev, &fpriv->vm, NULL);
1279b85891bdSJunwei Zhang 	if (!fpriv->prt_va) {
1280b85891bdSJunwei Zhang 		r = -ENOMEM;
12815c2ff9a6SChristian König 		goto error_vm;
1282b85891bdSJunwei Zhang 	}
1283b85891bdSJunwei Zhang 
128402ff519eSAlex Deucher 	if (adev->gfx.mcbp) {
12851e256e27SRex Zhu 		uint64_t csa_addr = amdgpu_csa_vaddr(adev) & AMDGPU_GMC_HOLE_MASK;
12861e256e27SRex Zhu 
12871e256e27SRex Zhu 		r = amdgpu_map_static_csa(adev, &fpriv->vm, adev->virt.csa_obj,
12881e256e27SRex Zhu 						&fpriv->csa_va, csa_addr, AMDGPU_CSA_SIZE);
12895c2ff9a6SChristian König 		if (r)
12905c2ff9a6SChristian König 			goto error_vm;
1291ab5d6227SMonk Liu 	}
12922493664fSMonk Liu 
1293d38ceaf9SAlex Deucher 	mutex_init(&fpriv->bo_list_lock);
1294c4f306e3SDanilo Krummrich 	idr_init_base(&fpriv->bo_list_handles, 1);
1295d38ceaf9SAlex Deucher 
129669493c03SChristian König 	amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev);
1297d38ceaf9SAlex Deucher 
1298d38ceaf9SAlex Deucher 	file_priv->driver_priv = fpriv;
12995c2ff9a6SChristian König 	goto out_suspend;
13005c2ff9a6SChristian König 
13015c2ff9a6SChristian König error_vm:
13025c2ff9a6SChristian König 	amdgpu_vm_fini(adev, &fpriv->vm);
13035c2ff9a6SChristian König 
13045c2ff9a6SChristian König error_pasid:
130588f7f881SNirmoy Das 	if (pasid) {
13065c2ff9a6SChristian König 		amdgpu_pasid_free(pasid);
130788f7f881SNirmoy Das 		amdgpu_vm_set_pasid(adev, &fpriv->vm, 0);
130888f7f881SNirmoy Das 	}
13095c2ff9a6SChristian König 
13105c2ff9a6SChristian König 	kfree(fpriv);
1311d38ceaf9SAlex Deucher 
1312dc08267aSAlex Deucher out_suspend:
1313d38ceaf9SAlex Deucher 	pm_runtime_mark_last_busy(dev->dev);
13149ba8923cSNavid Emamdoost pm_put:
1315d38ceaf9SAlex Deucher 	pm_runtime_put_autosuspend(dev->dev);
1316d38ceaf9SAlex Deucher 
1317d38ceaf9SAlex Deucher 	return r;
1318d38ceaf9SAlex Deucher }
1319d38ceaf9SAlex Deucher 
1320d38ceaf9SAlex Deucher /**
1321d38ceaf9SAlex Deucher  * amdgpu_driver_postclose_kms - drm callback for post close
1322d38ceaf9SAlex Deucher  *
1323d38ceaf9SAlex Deucher  * @dev: drm dev pointer
1324d38ceaf9SAlex Deucher  * @file_priv: drm file
1325d38ceaf9SAlex Deucher  *
1326d38ceaf9SAlex Deucher  * On device post close, tear down vm on cayman+ (all asics).
1327d38ceaf9SAlex Deucher  */
amdgpu_driver_postclose_kms(struct drm_device * dev,struct drm_file * file_priv)1328d38ceaf9SAlex Deucher void amdgpu_driver_postclose_kms(struct drm_device *dev,
1329d38ceaf9SAlex Deucher 				 struct drm_file *file_priv)
1330d38ceaf9SAlex Deucher {
13311348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
1332d38ceaf9SAlex Deucher 	struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
1333d38ceaf9SAlex Deucher 	struct amdgpu_bo_list *list;
13345c2ff9a6SChristian König 	struct amdgpu_bo *pd;
1335c7b6bac9SFenghua Yu 	u32 pasid;
1336d38ceaf9SAlex Deucher 	int handle;
1337d38ceaf9SAlex Deucher 
1338d38ceaf9SAlex Deucher 	if (!fpriv)
1339d38ceaf9SAlex Deucher 		return;
1340d38ceaf9SAlex Deucher 
134104e30c9cSDaniel Vetter 	pm_runtime_get_sync(dev->dev);
134202537d63SChristian König 
134344876ae2SAlex Deucher 	if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_UVD) != NULL)
1344cd437e37SLeo Liu 		amdgpu_uvd_free_handles(adev, file_priv);
134544876ae2SAlex Deucher 	if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE) != NULL)
1346cd437e37SLeo Liu 		amdgpu_vce_free_handles(adev, file_priv);
1347cd437e37SLeo Liu 
13485daff15cSLang Yu 	if (fpriv->csa_va) {
13495daff15cSLang Yu 		uint64_t csa_addr = amdgpu_csa_vaddr(adev) & AMDGPU_GMC_HOLE_MASK;
13505daff15cSLang Yu 
13515daff15cSLang Yu 		WARN_ON(amdgpu_unmap_static_csa(adev, &fpriv->vm, adev->virt.csa_obj,
13525daff15cSLang Yu 						fpriv->csa_va, csa_addr));
13530f4b3c68SChristian König 		fpriv->csa_va = NULL;
13542493664fSMonk Liu 	}
13552493664fSMonk Liu 
13565c2ff9a6SChristian König 	pasid = fpriv->vm.pasid;
1357391629bdSNirmoy Das 	pd = amdgpu_bo_ref(fpriv->vm.root.bo);
1358b6fba4ecSChristian König 	if (!WARN_ON(amdgpu_bo_reserve(pd, true))) {
1359b6fba4ecSChristian König 		amdgpu_vm_bo_del(adev, fpriv->prt_va);
1360b6fba4ecSChristian König 		amdgpu_bo_unreserve(pd);
1361b6fba4ecSChristian König 	}
13625c2ff9a6SChristian König 
13638ee3a52eSEmily Deng 	amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
13646ffb6b7fSRex Zhu 	amdgpu_vm_fini(adev, &fpriv->vm);
13658ee3a52eSEmily Deng 
13665c2ff9a6SChristian König 	if (pasid)
13675a5011a7SGerd Hoffmann 		amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
13685c2ff9a6SChristian König 	amdgpu_bo_unref(&pd);
1369d38ceaf9SAlex Deucher 
1370d38ceaf9SAlex Deucher 	idr_for_each_entry(&fpriv->bo_list_handles, list, handle)
1371a0f20845SChristian König 		amdgpu_bo_list_put(list);
1372d38ceaf9SAlex Deucher 
1373d38ceaf9SAlex Deucher 	idr_destroy(&fpriv->bo_list_handles);
1374d38ceaf9SAlex Deucher 	mutex_destroy(&fpriv->bo_list_lock);
1375d38ceaf9SAlex Deucher 
1376d38ceaf9SAlex Deucher 	kfree(fpriv);
1377d38ceaf9SAlex Deucher 	file_priv->driver_priv = NULL;
1378d6bda7b4SAlex Deucher 
1379d6bda7b4SAlex Deucher 	pm_runtime_mark_last_busy(dev->dev);
1380d6bda7b4SAlex Deucher 	pm_runtime_put_autosuspend(dev->dev);
1381d38ceaf9SAlex Deucher }
1382d38ceaf9SAlex Deucher 
138372c8c97bSAndrey Grodzovsky 
amdgpu_driver_release_kms(struct drm_device * dev)138472c8c97bSAndrey Grodzovsky void amdgpu_driver_release_kms(struct drm_device *dev)
138572c8c97bSAndrey Grodzovsky {
138672c8c97bSAndrey Grodzovsky 	struct amdgpu_device *adev = drm_to_adev(dev);
138772c8c97bSAndrey Grodzovsky 
138872c8c97bSAndrey Grodzovsky 	amdgpu_device_fini_sw(adev);
138972c8c97bSAndrey Grodzovsky 	pci_set_drvdata(adev->pdev, NULL);
139072c8c97bSAndrey Grodzovsky }
139172c8c97bSAndrey Grodzovsky 
1392d38ceaf9SAlex Deucher /*
1393d38ceaf9SAlex Deucher  * VBlank related functions.
1394d38ceaf9SAlex Deucher  */
1395d38ceaf9SAlex Deucher /**
1396d38ceaf9SAlex Deucher  * amdgpu_get_vblank_counter_kms - get frame count
1397d38ceaf9SAlex Deucher  *
1398e3eff4b5SThomas Zimmermann  * @crtc: crtc to get the frame count from
1399d38ceaf9SAlex Deucher  *
1400d38ceaf9SAlex Deucher  * Gets the frame count on the requested crtc (all asics).
1401d38ceaf9SAlex Deucher  * Returns frame count on success, -EINVAL on failure.
1402d38ceaf9SAlex Deucher  */
amdgpu_get_vblank_counter_kms(struct drm_crtc * crtc)1403e3eff4b5SThomas Zimmermann u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc)
1404d38ceaf9SAlex Deucher {
1405e3eff4b5SThomas Zimmermann 	struct drm_device *dev = crtc->dev;
1406e3eff4b5SThomas Zimmermann 	unsigned int pipe = crtc->index;
14071348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
14088e36f9d3SAlex Deucher 	int vpos, hpos, stat;
14098e36f9d3SAlex Deucher 	u32 count;
1410d38ceaf9SAlex Deucher 
141188e72717SThierry Reding 	if (pipe >= adev->mode_info.num_crtc) {
141288e72717SThierry Reding 		DRM_ERROR("Invalid crtc %u\n", pipe);
1413d38ceaf9SAlex Deucher 		return -EINVAL;
1414d38ceaf9SAlex Deucher 	}
1415d38ceaf9SAlex Deucher 
14168e36f9d3SAlex Deucher 	/* The hw increments its frame counter at start of vsync, not at start
14178e36f9d3SAlex Deucher 	 * of vblank, as is required by DRM core vblank counter handling.
14188e36f9d3SAlex Deucher 	 * Cook the hw count here to make it appear to the caller as if it
14198e36f9d3SAlex Deucher 	 * incremented at start of vblank. We measure distance to start of
14208e36f9d3SAlex Deucher 	 * vblank in vpos. vpos therefore will be >= 0 between start of vblank
14218e36f9d3SAlex Deucher 	 * and start of vsync, so vpos >= 0 means to bump the hw frame counter
14228e36f9d3SAlex Deucher 	 * result by 1 to give the proper appearance to caller.
14238e36f9d3SAlex Deucher 	 */
14248e36f9d3SAlex Deucher 	if (adev->mode_info.crtcs[pipe]) {
14258e36f9d3SAlex Deucher 		/* Repeat readout if needed to provide stable result if
14268e36f9d3SAlex Deucher 		 * we cross start of vsync during the queries.
14278e36f9d3SAlex Deucher 		 */
14288e36f9d3SAlex Deucher 		do {
14298e36f9d3SAlex Deucher 			count = amdgpu_display_vblank_get_counter(adev, pipe);
1430aa8e286aSSamuel Li 			/* Ask amdgpu_display_get_crtc_scanoutpos to return
1431aa8e286aSSamuel Li 			 * vpos as distance to start of vblank, instead of
1432aa8e286aSSamuel Li 			 * regular vertical scanout pos.
14338e36f9d3SAlex Deucher 			 */
1434aa8e286aSSamuel Li 			stat = amdgpu_display_get_crtc_scanoutpos(
14358e36f9d3SAlex Deucher 				dev, pipe, GET_DISTANCE_TO_VBLANKSTART,
14368e36f9d3SAlex Deucher 				&vpos, &hpos, NULL, NULL,
14378e36f9d3SAlex Deucher 				&adev->mode_info.crtcs[pipe]->base.hwmode);
14388e36f9d3SAlex Deucher 		} while (count != amdgpu_display_vblank_get_counter(adev, pipe));
14398e36f9d3SAlex Deucher 
14408e36f9d3SAlex Deucher 		if (((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) !=
14418e36f9d3SAlex Deucher 		    (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE))) {
14428e36f9d3SAlex Deucher 			DRM_DEBUG_VBL("Query failed! stat %d\n", stat);
14438e36f9d3SAlex Deucher 		} else {
14448e36f9d3SAlex Deucher 			DRM_DEBUG_VBL("crtc %d: dist from vblank start %d\n",
14458e36f9d3SAlex Deucher 				      pipe, vpos);
14468e36f9d3SAlex Deucher 
14478e36f9d3SAlex Deucher 			/* Bump counter if we are at >= leading edge of vblank,
14488e36f9d3SAlex Deucher 			 * but before vsync where vpos would turn negative and
14498e36f9d3SAlex Deucher 			 * the hw counter really increments.
14508e36f9d3SAlex Deucher 			 */
14518e36f9d3SAlex Deucher 			if (vpos >= 0)
14528e36f9d3SAlex Deucher 				count++;
14538e36f9d3SAlex Deucher 		}
14548e36f9d3SAlex Deucher 	} else {
14558e36f9d3SAlex Deucher 		/* Fallback to use value as is. */
14568e36f9d3SAlex Deucher 		count = amdgpu_display_vblank_get_counter(adev, pipe);
14578e36f9d3SAlex Deucher 		DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n");
14588e36f9d3SAlex Deucher 	}
14598e36f9d3SAlex Deucher 
14608e36f9d3SAlex Deucher 	return count;
1461d38ceaf9SAlex Deucher }
1462d38ceaf9SAlex Deucher 
1463d38ceaf9SAlex Deucher /**
1464d38ceaf9SAlex Deucher  * amdgpu_enable_vblank_kms - enable vblank interrupt
1465d38ceaf9SAlex Deucher  *
1466e3eff4b5SThomas Zimmermann  * @crtc: crtc to enable vblank interrupt for
1467d38ceaf9SAlex Deucher  *
1468d38ceaf9SAlex Deucher  * Enable the interrupt on the requested crtc (all asics).
1469d38ceaf9SAlex Deucher  * Returns 0 on success, -EINVAL on failure.
1470d38ceaf9SAlex Deucher  */
amdgpu_enable_vblank_kms(struct drm_crtc * crtc)1471e3eff4b5SThomas Zimmermann int amdgpu_enable_vblank_kms(struct drm_crtc *crtc)
1472d38ceaf9SAlex Deucher {
1473e3eff4b5SThomas Zimmermann 	struct drm_device *dev = crtc->dev;
1474e3eff4b5SThomas Zimmermann 	unsigned int pipe = crtc->index;
14751348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
1476734dd01dSSamuel Li 	int idx = amdgpu_display_crtc_idx_to_irq_type(adev, pipe);
1477d38ceaf9SAlex Deucher 
1478d38ceaf9SAlex Deucher 	return amdgpu_irq_get(adev, &adev->crtc_irq, idx);
1479d38ceaf9SAlex Deucher }
1480d38ceaf9SAlex Deucher 
1481d38ceaf9SAlex Deucher /**
1482d38ceaf9SAlex Deucher  * amdgpu_disable_vblank_kms - disable vblank interrupt
1483d38ceaf9SAlex Deucher  *
1484e3eff4b5SThomas Zimmermann  * @crtc: crtc to disable vblank interrupt for
1485d38ceaf9SAlex Deucher  *
1486d38ceaf9SAlex Deucher  * Disable the interrupt on the requested crtc (all asics).
1487d38ceaf9SAlex Deucher  */
amdgpu_disable_vblank_kms(struct drm_crtc * crtc)1488e3eff4b5SThomas Zimmermann void amdgpu_disable_vblank_kms(struct drm_crtc *crtc)
1489d38ceaf9SAlex Deucher {
1490e3eff4b5SThomas Zimmermann 	struct drm_device *dev = crtc->dev;
1491e3eff4b5SThomas Zimmermann 	unsigned int pipe = crtc->index;
14921348969aSLuben Tuikov 	struct amdgpu_device *adev = drm_to_adev(dev);
1493734dd01dSSamuel Li 	int idx = amdgpu_display_crtc_idx_to_irq_type(adev, pipe);
1494d38ceaf9SAlex Deucher 
1495d38ceaf9SAlex Deucher 	amdgpu_irq_put(adev, &adev->crtc_irq, idx);
1496d38ceaf9SAlex Deucher }
1497d38ceaf9SAlex Deucher 
149850ab2533SHuang Rui /*
149950ab2533SHuang Rui  * Debugfs info
150050ab2533SHuang Rui  */
150150ab2533SHuang Rui #if defined(CONFIG_DEBUG_FS)
150250ab2533SHuang Rui 
amdgpu_debugfs_firmware_info_show(struct seq_file * m,void * unused)150398d28ac2SNirmoy Das static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
150450ab2533SHuang Rui {
1505109b4d8cSSu Hui 	struct amdgpu_device *adev = m->private;
150650ab2533SHuang Rui 	struct drm_amdgpu_info_firmware fw_info;
150750ab2533SHuang Rui 	struct drm_amdgpu_query_fw query_fw;
150832d8c662SAlex Deucher 	struct atom_context *ctx = adev->mode_info.atom_context;
150982890466SMario Limonciello 	uint8_t smu_program, smu_major, smu_minor, smu_debug;
151050ab2533SHuang Rui 	int ret, i;
151150ab2533SHuang Rui 
15124d5ae731SKevin Wang 	static const char *ta_fw_name[TA_FW_TYPE_MAX_INDEX] = {
15134d5ae731SKevin Wang #define TA_FW_NAME(type)[TA_FW_TYPE_PSP_##type] = #type
15144d5ae731SKevin Wang 		TA_FW_NAME(XGMI),
15154d5ae731SKevin Wang 		TA_FW_NAME(RAS),
15164d5ae731SKevin Wang 		TA_FW_NAME(HDCP),
15174d5ae731SKevin Wang 		TA_FW_NAME(DTM),
15184d5ae731SKevin Wang 		TA_FW_NAME(RAP),
1519e7bdf00eSKevin Wang 		TA_FW_NAME(SECUREDISPLAY),
15204d5ae731SKevin Wang #undef TA_FW_NAME
15214d5ae731SKevin Wang 	};
15224d5ae731SKevin Wang 
152350ab2533SHuang Rui 	/* VCE */
152450ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_VCE;
152550ab2533SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
152650ab2533SHuang Rui 	if (ret)
152750ab2533SHuang Rui 		return ret;
152850ab2533SHuang Rui 	seq_printf(m, "VCE feature version: %u, firmware version: 0x%08x\n",
152950ab2533SHuang Rui 		   fw_info.feature, fw_info.ver);
153050ab2533SHuang Rui 
153150ab2533SHuang Rui 	/* UVD */
153250ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_UVD;
153350ab2533SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
153450ab2533SHuang Rui 	if (ret)
153550ab2533SHuang Rui 		return ret;
153650ab2533SHuang Rui 	seq_printf(m, "UVD feature version: %u, firmware version: 0x%08x\n",
153750ab2533SHuang Rui 		   fw_info.feature, fw_info.ver);
153850ab2533SHuang Rui 
153950ab2533SHuang Rui 	/* GMC */
154050ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_GMC;
154150ab2533SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
154250ab2533SHuang Rui 	if (ret)
154350ab2533SHuang Rui 		return ret;
154450ab2533SHuang Rui 	seq_printf(m, "MC feature version: %u, firmware version: 0x%08x\n",
154550ab2533SHuang Rui 		   fw_info.feature, fw_info.ver);
154650ab2533SHuang Rui 
154750ab2533SHuang Rui 	/* ME */
154850ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_ME;
154950ab2533SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
155050ab2533SHuang Rui 	if (ret)
155150ab2533SHuang Rui 		return ret;
155250ab2533SHuang Rui 	seq_printf(m, "ME feature version: %u, firmware version: 0x%08x\n",
155350ab2533SHuang Rui 		   fw_info.feature, fw_info.ver);
155450ab2533SHuang Rui 
155550ab2533SHuang Rui 	/* PFP */
155650ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_PFP;
155750ab2533SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
155850ab2533SHuang Rui 	if (ret)
155950ab2533SHuang Rui 		return ret;
156050ab2533SHuang Rui 	seq_printf(m, "PFP feature version: %u, firmware version: 0x%08x\n",
156150ab2533SHuang Rui 		   fw_info.feature, fw_info.ver);
156250ab2533SHuang Rui 
156350ab2533SHuang Rui 	/* CE */
156450ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_CE;
156550ab2533SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
156650ab2533SHuang Rui 	if (ret)
156750ab2533SHuang Rui 		return ret;
156850ab2533SHuang Rui 	seq_printf(m, "CE feature version: %u, firmware version: 0x%08x\n",
156950ab2533SHuang Rui 		   fw_info.feature, fw_info.ver);
157050ab2533SHuang Rui 
157150ab2533SHuang Rui 	/* RLC */
157250ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_RLC;
157350ab2533SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
157450ab2533SHuang Rui 	if (ret)
157550ab2533SHuang Rui 		return ret;
157650ab2533SHuang Rui 	seq_printf(m, "RLC feature version: %u, firmware version: 0x%08x\n",
157750ab2533SHuang Rui 		   fw_info.feature, fw_info.ver);
157850ab2533SHuang Rui 
1579621a6318SHuang Rui 	/* RLC SAVE RESTORE LIST CNTL */
1580621a6318SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_CNTL;
1581621a6318SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
1582621a6318SHuang Rui 	if (ret)
1583621a6318SHuang Rui 		return ret;
1584621a6318SHuang Rui 	seq_printf(m, "RLC SRLC feature version: %u, firmware version: 0x%08x\n",
1585621a6318SHuang Rui 		   fw_info.feature, fw_info.ver);
1586621a6318SHuang Rui 
1587621a6318SHuang Rui 	/* RLC SAVE RESTORE LIST GPM MEM */
1588621a6318SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM;
1589621a6318SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
1590621a6318SHuang Rui 	if (ret)
1591621a6318SHuang Rui 		return ret;
1592621a6318SHuang Rui 	seq_printf(m, "RLC SRLG feature version: %u, firmware version: 0x%08x\n",
1593621a6318SHuang Rui 		   fw_info.feature, fw_info.ver);
1594621a6318SHuang Rui 
1595621a6318SHuang Rui 	/* RLC SAVE RESTORE LIST SRM MEM */
1596621a6318SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM;
1597621a6318SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
1598621a6318SHuang Rui 	if (ret)
1599621a6318SHuang Rui 		return ret;
1600621a6318SHuang Rui 	seq_printf(m, "RLC SRLS feature version: %u, firmware version: 0x%08x\n",
1601621a6318SHuang Rui 		   fw_info.feature, fw_info.ver);
1602621a6318SHuang Rui 
1603670c6edfSHawking Zhang 	/* RLCP */
1604670c6edfSHawking Zhang 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_RLCP;
1605670c6edfSHawking Zhang 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
1606670c6edfSHawking Zhang 	if (ret)
1607670c6edfSHawking Zhang 		return ret;
1608670c6edfSHawking Zhang 	seq_printf(m, "RLCP feature version: %u, firmware version: 0x%08x\n",
1609670c6edfSHawking Zhang 		   fw_info.feature, fw_info.ver);
1610670c6edfSHawking Zhang 
1611670c6edfSHawking Zhang 	/* RLCV */
1612670c6edfSHawking Zhang 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_RLCV;
1613670c6edfSHawking Zhang 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
1614670c6edfSHawking Zhang 	if (ret)
1615670c6edfSHawking Zhang 		return ret;
1616670c6edfSHawking Zhang 	seq_printf(m, "RLCV feature version: %u, firmware version: 0x%08x\n",
1617670c6edfSHawking Zhang 		   fw_info.feature, fw_info.ver);
1618670c6edfSHawking Zhang 
161950ab2533SHuang Rui 	/* MEC */
162050ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_GFX_MEC;
162150ab2533SHuang Rui 	query_fw.index = 0;
162250ab2533SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
162350ab2533SHuang Rui 	if (ret)
162450ab2533SHuang Rui 		return ret;
162550ab2533SHuang Rui 	seq_printf(m, "MEC feature version: %u, firmware version: 0x%08x\n",
162650ab2533SHuang Rui 		   fw_info.feature, fw_info.ver);
162750ab2533SHuang Rui 
162850ab2533SHuang Rui 	/* MEC2 */
1629d7aca4f0SAlex Deucher 	if (adev->gfx.mec2_fw) {
163050ab2533SHuang Rui 		query_fw.index = 1;
163150ab2533SHuang Rui 		ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
163250ab2533SHuang Rui 		if (ret)
163350ab2533SHuang Rui 			return ret;
163450ab2533SHuang Rui 		seq_printf(m, "MEC2 feature version: %u, firmware version: 0x%08x\n",
163550ab2533SHuang Rui 			   fw_info.feature, fw_info.ver);
163650ab2533SHuang Rui 	}
163750ab2533SHuang Rui 
1638b7236296SDavid Francis 	/* IMU */
1639b7236296SDavid Francis 	query_fw.fw_type = AMDGPU_INFO_FW_IMU;
1640b7236296SDavid Francis 	query_fw.index = 0;
1641b7236296SDavid Francis 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
1642b7236296SDavid Francis 	if (ret)
1643b7236296SDavid Francis 		return ret;
1644b7236296SDavid Francis 	seq_printf(m, "IMU feature version: %u, firmware version: 0x%08x\n",
1645b7236296SDavid Francis 		   fw_info.feature, fw_info.ver);
1646b7236296SDavid Francis 
16476a7ed07eSHuang Rui 	/* PSP SOS */
16486a7ed07eSHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_SOS;
16496a7ed07eSHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
16506a7ed07eSHuang Rui 	if (ret)
16516a7ed07eSHuang Rui 		return ret;
16526a7ed07eSHuang Rui 	seq_printf(m, "SOS feature version: %u, firmware version: 0x%08x\n",
16536a7ed07eSHuang Rui 		   fw_info.feature, fw_info.ver);
16546a7ed07eSHuang Rui 
16556a7ed07eSHuang Rui 
16566a7ed07eSHuang Rui 	/* PSP ASD */
16576a7ed07eSHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_ASD;
16586a7ed07eSHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
16596a7ed07eSHuang Rui 	if (ret)
16606a7ed07eSHuang Rui 		return ret;
16616a7ed07eSHuang Rui 	seq_printf(m, "ASD feature version: %u, firmware version: 0x%08x\n",
16626a7ed07eSHuang Rui 		   fw_info.feature, fw_info.ver);
16636a7ed07eSHuang Rui 
16649b9ca62dSxinhui pan 	query_fw.fw_type = AMDGPU_INFO_FW_TA;
16654d5ae731SKevin Wang 	for (i = TA_FW_TYPE_PSP_XGMI; i < TA_FW_TYPE_MAX_INDEX; i++) {
16669b9ca62dSxinhui pan 		query_fw.index = i;
16679b9ca62dSxinhui pan 		ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
16689b9ca62dSxinhui pan 		if (ret)
16699b9ca62dSxinhui pan 			continue;
16704d5ae731SKevin Wang 
1671f399d4deSChangfeng 		seq_printf(m, "TA %s feature version: 0x%08x, firmware version: 0x%08x\n",
16724d5ae731SKevin Wang 			   ta_fw_name[i], fw_info.feature, fw_info.ver);
16739b9ca62dSxinhui pan 	}
16749b9ca62dSxinhui pan 
167550ab2533SHuang Rui 	/* SMC */
167650ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_SMC;
167750ab2533SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
167850ab2533SHuang Rui 	if (ret)
167950ab2533SHuang Rui 		return ret;
168082890466SMario Limonciello 	smu_program = (fw_info.ver >> 24) & 0xff;
168182890466SMario Limonciello 	smu_major = (fw_info.ver >> 16) & 0xff;
1682c92f9096SMario Limonciello 	smu_minor = (fw_info.ver >> 8) & 0xff;
1683c92f9096SMario Limonciello 	smu_debug = (fw_info.ver >> 0) & 0xff;
168482890466SMario Limonciello 	seq_printf(m, "SMC feature version: %u, program: %d, firmware version: 0x%08x (%d.%d.%d)\n",
168582890466SMario Limonciello 		   fw_info.feature, smu_program, fw_info.ver, smu_major, smu_minor, smu_debug);
168650ab2533SHuang Rui 
168750ab2533SHuang Rui 	/* SDMA */
168850ab2533SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_SDMA;
168950ab2533SHuang Rui 	for (i = 0; i < adev->sdma.num_instances; i++) {
169050ab2533SHuang Rui 		query_fw.index = i;
169150ab2533SHuang Rui 		ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
169250ab2533SHuang Rui 		if (ret)
169350ab2533SHuang Rui 			return ret;
169450ab2533SHuang Rui 		seq_printf(m, "SDMA%d feature version: %u, firmware version: 0x%08x\n",
169550ab2533SHuang Rui 			   i, fw_info.feature, fw_info.ver);
169650ab2533SHuang Rui 	}
169750ab2533SHuang Rui 
16983ac952b1SAlex Deucher 	/* VCN */
16993ac952b1SAlex Deucher 	query_fw.fw_type = AMDGPU_INFO_FW_VCN;
17003ac952b1SAlex Deucher 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
17013ac952b1SAlex Deucher 	if (ret)
17023ac952b1SAlex Deucher 		return ret;
17033ac952b1SAlex Deucher 	seq_printf(m, "VCN feature version: %u, firmware version: 0x%08x\n",
17043ac952b1SAlex Deucher 		   fw_info.feature, fw_info.ver);
17053ac952b1SAlex Deucher 
17064d11b4b2SDavid Francis 	/* DMCU */
17074d11b4b2SDavid Francis 	query_fw.fw_type = AMDGPU_INFO_FW_DMCU;
17084d11b4b2SDavid Francis 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
17094d11b4b2SDavid Francis 	if (ret)
17104d11b4b2SDavid Francis 		return ret;
17114d11b4b2SDavid Francis 	seq_printf(m, "DMCU feature version: %u, firmware version: 0x%08x\n",
17124d11b4b2SDavid Francis 		   fw_info.feature, fw_info.ver);
17134d11b4b2SDavid Francis 
1714976e51a7SNicholas Kazlauskas 	/* DMCUB */
1715976e51a7SNicholas Kazlauskas 	query_fw.fw_type = AMDGPU_INFO_FW_DMCUB;
1716976e51a7SNicholas Kazlauskas 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
1717976e51a7SNicholas Kazlauskas 	if (ret)
1718976e51a7SNicholas Kazlauskas 		return ret;
1719976e51a7SNicholas Kazlauskas 	seq_printf(m, "DMCUB feature version: %u, firmware version: 0x%08x\n",
1720976e51a7SNicholas Kazlauskas 		   fw_info.feature, fw_info.ver);
1721976e51a7SNicholas Kazlauskas 
17225120cb54SHuang Rui 	/* TOC */
17235120cb54SHuang Rui 	query_fw.fw_type = AMDGPU_INFO_FW_TOC;
17245120cb54SHuang Rui 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
17255120cb54SHuang Rui 	if (ret)
17265120cb54SHuang Rui 		return ret;
17275120cb54SHuang Rui 	seq_printf(m, "TOC feature version: %u, firmware version: 0x%08x\n",
17285120cb54SHuang Rui 		   fw_info.feature, fw_info.ver);
172932d8c662SAlex Deucher 
1730c4381d0eSBokun Zhang 	/* CAP */
1731c4381d0eSBokun Zhang 	if (adev->psp.cap_fw) {
1732c4381d0eSBokun Zhang 		query_fw.fw_type = AMDGPU_INFO_FW_CAP;
1733c4381d0eSBokun Zhang 		ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
1734c4381d0eSBokun Zhang 		if (ret)
1735c4381d0eSBokun Zhang 			return ret;
1736c4381d0eSBokun Zhang 		seq_printf(m, "CAP feature version: %u, firmware version: 0x%08x\n",
1737c4381d0eSBokun Zhang 				fw_info.feature, fw_info.ver);
1738c4381d0eSBokun Zhang 	}
1739c4381d0eSBokun Zhang 
174010faf078SYifan Zhang 	/* MES_KIQ */
174110faf078SYifan Zhang 	query_fw.fw_type = AMDGPU_INFO_FW_MES_KIQ;
174210faf078SYifan Zhang 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
174310faf078SYifan Zhang 	if (ret)
174410faf078SYifan Zhang 		return ret;
174510faf078SYifan Zhang 	seq_printf(m, "MES_KIQ feature version: %u, firmware version: 0x%08x\n",
174610faf078SYifan Zhang 		   fw_info.feature, fw_info.ver);
174710faf078SYifan Zhang 
174810faf078SYifan Zhang 	/* MES */
174910faf078SYifan Zhang 	query_fw.fw_type = AMDGPU_INFO_FW_MES;
175010faf078SYifan Zhang 	ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
175110faf078SYifan Zhang 	if (ret)
175210faf078SYifan Zhang 		return ret;
175310faf078SYifan Zhang 	seq_printf(m, "MES feature version: %u, firmware version: 0x%08x\n",
175410faf078SYifan Zhang 		   fw_info.feature, fw_info.ver);
175510faf078SYifan Zhang 
1756adf64e21SMario Limonciello 	seq_printf(m, "VBIOS version: %s\n", ctx->vbios_pn);
175732d8c662SAlex Deucher 
175850ab2533SHuang Rui 	return 0;
175950ab2533SHuang Rui }
176050ab2533SHuang Rui 
176198d28ac2SNirmoy Das DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_firmware_info);
176298d28ac2SNirmoy Das 
176350ab2533SHuang Rui #endif
176450ab2533SHuang Rui 
amdgpu_debugfs_firmware_init(struct amdgpu_device * adev)176598d28ac2SNirmoy Das void amdgpu_debugfs_firmware_init(struct amdgpu_device *adev)
176650ab2533SHuang Rui {
176750ab2533SHuang Rui #if defined(CONFIG_DEBUG_FS)
176898d28ac2SNirmoy Das 	struct drm_minor *minor = adev_to_drm(adev)->primary;
176998d28ac2SNirmoy Das 	struct dentry *root = minor->debugfs_root;
177098d28ac2SNirmoy Das 
177198d28ac2SNirmoy Das 	debugfs_create_file("amdgpu_firmware_info", 0444, root,
177298d28ac2SNirmoy Das 			    adev, &amdgpu_debugfs_firmware_info_fops);
177398d28ac2SNirmoy Das 
177450ab2533SHuang Rui #endif
177550ab2533SHuang Rui }
1776