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 ®s[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