175758255SAlex Deucher /* 275758255SAlex Deucher * Copyright 2008 Advanced Micro Devices, Inc. 375758255SAlex Deucher * Copyright 2008 Red Hat Inc. 475758255SAlex Deucher * Copyright 2009 Jerome Glisse. 575758255SAlex Deucher * 675758255SAlex Deucher * Permission is hereby granted, free of charge, to any person obtaining a 775758255SAlex Deucher * copy of this software and associated documentation files (the "Software"), 875758255SAlex Deucher * to deal in the Software without restriction, including without limitation 975758255SAlex Deucher * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1075758255SAlex Deucher * and/or sell copies of the Software, and to permit persons to whom the 1175758255SAlex Deucher * Software is furnished to do so, subject to the following conditions: 1275758255SAlex Deucher * 1375758255SAlex Deucher * The above copyright notice and this permission notice shall be included in 1475758255SAlex Deucher * all copies or substantial portions of the Software. 1575758255SAlex Deucher * 1675758255SAlex Deucher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1775758255SAlex Deucher * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1875758255SAlex Deucher * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1975758255SAlex Deucher * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2075758255SAlex Deucher * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2175758255SAlex Deucher * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2275758255SAlex Deucher * OTHER DEALINGS IN THE SOFTWARE. 2375758255SAlex Deucher * 2475758255SAlex Deucher */ 2575758255SAlex Deucher 2675758255SAlex Deucher #include <linux/kthread.h> 27fdf2f6c5SSam Ravnborg #include <linux/pci.h> 28fdf2f6c5SSam Ravnborg #include <linux/uaccess.h> 29a9ffe2a9SAlex Deucher #include <linux/pm_runtime.h> 30fdf2f6c5SSam Ravnborg 3175758255SAlex Deucher #include "amdgpu.h" 32a4c5b1bbSAlex Deucher #include "amdgpu_pm.h" 33d090e7dbSAlex Deucher #include "amdgpu_dm_debugfs.h" 3417cb04f2SStanley.Yang #include "amdgpu_ras.h" 35a4322e18SWenhui Sheng #include "amdgpu_rap.h" 36ecaafb7bSJinzhou Su #include "amdgpu_securedisplay.h" 3719ae3330SJohn Clements #include "amdgpu_fw_attestation.h" 3837df9560STom St Denis #include "amdgpu_umr.h" 3975758255SAlex Deucher 40d0fb18b5SAndrey Grodzovsky #include "amdgpu_reset.h" 41d0fb18b5SAndrey Grodzovsky 4275758255SAlex Deucher #if defined(CONFIG_DEBUG_FS) 4375758255SAlex Deucher 447e4237dbSTom St Denis /** 457e4237dbSTom St Denis * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes 467e4237dbSTom St Denis * 477e4237dbSTom St Denis * @read: True if reading 487e4237dbSTom St Denis * @f: open file handle 497e4237dbSTom St Denis * @buf: User buffer to write/read to 507e4237dbSTom St Denis * @size: Number of bytes to write/read 517e4237dbSTom St Denis * @pos: Offset to seek to 527e4237dbSTom St Denis * 537e4237dbSTom St Denis * This debugfs entry has special meaning on the offset being sought. 547e4237dbSTom St Denis * Various bits have different meanings: 557e4237dbSTom St Denis * 567e4237dbSTom St Denis * Bit 62: Indicates a GRBM bank switch is needed 577e4237dbSTom St Denis * Bit 61: Indicates a SRBM bank switch is needed (implies bit 62 is 587e4237dbSTom St Denis * zero) 597e4237dbSTom St Denis * Bits 24..33: The SE or ME selector if needed 607e4237dbSTom St Denis * Bits 34..43: The SH (or SA) or PIPE selector if needed 617e4237dbSTom St Denis * Bits 44..53: The INSTANCE (or CU/WGP) or QUEUE selector if needed 627e4237dbSTom St Denis * 637e4237dbSTom St Denis * Bit 23: Indicates that the PM power gating lock should be held 647e4237dbSTom St Denis * This is necessary to read registers that might be 657e4237dbSTom St Denis * unreliable during a power gating transistion. 667e4237dbSTom St Denis * 677e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 687e4237dbSTom St Denis * allows reading multiple registers in a single call and having 697e4237dbSTom St Denis * the returned size reflect that. 707e4237dbSTom St Denis */ 71f7a9ee81SAndrey Grodzovsky static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, 72f7a9ee81SAndrey Grodzovsky char __user *buf, size_t size, loff_t *pos) 7375758255SAlex Deucher { 7475758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 7575758255SAlex Deucher ssize_t result = 0; 7675758255SAlex Deucher int r; 77f7a9ee81SAndrey Grodzovsky bool pm_pg_lock, use_bank, use_ring; 780fa4246eSTom St Denis unsigned instance_bank, sh_bank, se_bank, me, pipe, queue, vmid; 7975758255SAlex Deucher 80f7a9ee81SAndrey Grodzovsky pm_pg_lock = use_bank = use_ring = false; 810fa4246eSTom St Denis instance_bank = sh_bank = se_bank = me = pipe = queue = vmid = 0; 82f7a9ee81SAndrey Grodzovsky 83f7a9ee81SAndrey Grodzovsky if (size & 0x3 || *pos & 0x3 || 84f7a9ee81SAndrey Grodzovsky ((*pos & (1ULL << 62)) && (*pos & (1ULL << 61)))) 8575758255SAlex Deucher return -EINVAL; 8675758255SAlex Deucher 8775758255SAlex Deucher /* are we reading registers for which a PG lock is necessary? */ 8875758255SAlex Deucher pm_pg_lock = (*pos >> 23) & 1; 8975758255SAlex Deucher 9075758255SAlex Deucher if (*pos & (1ULL << 62)) { 9175758255SAlex Deucher se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24; 9275758255SAlex Deucher sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34; 9375758255SAlex Deucher instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44; 9475758255SAlex Deucher 9575758255SAlex Deucher if (se_bank == 0x3FF) 9675758255SAlex Deucher se_bank = 0xFFFFFFFF; 9775758255SAlex Deucher if (sh_bank == 0x3FF) 9875758255SAlex Deucher sh_bank = 0xFFFFFFFF; 9975758255SAlex Deucher if (instance_bank == 0x3FF) 10075758255SAlex Deucher instance_bank = 0xFFFFFFFF; 101c5b2bd5dSzhengbin use_bank = true; 102f7a9ee81SAndrey Grodzovsky } else if (*pos & (1ULL << 61)) { 103f7a9ee81SAndrey Grodzovsky 104f7a9ee81SAndrey Grodzovsky me = (*pos & GENMASK_ULL(33, 24)) >> 24; 105f7a9ee81SAndrey Grodzovsky pipe = (*pos & GENMASK_ULL(43, 34)) >> 34; 106f7a9ee81SAndrey Grodzovsky queue = (*pos & GENMASK_ULL(53, 44)) >> 44; 10788891430STom St Denis vmid = (*pos & GENMASK_ULL(58, 54)) >> 54; 108f7a9ee81SAndrey Grodzovsky 109c5b2bd5dSzhengbin use_ring = true; 11075758255SAlex Deucher } else { 111c5b2bd5dSzhengbin use_bank = use_ring = false; 11275758255SAlex Deucher } 11375758255SAlex Deucher 11475758255SAlex Deucher *pos &= (1UL << 22) - 1; 11575758255SAlex Deucher 1164a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 1179eee152aSAlex Deucher if (r < 0) { 1184a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 119a9ffe2a9SAlex Deucher return r; 1209eee152aSAlex Deucher } 121a9ffe2a9SAlex Deucher 12295a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 1239eee152aSAlex Deucher if (r < 0) { 1244a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12595a2f917SYintian Tao return r; 1269eee152aSAlex Deucher } 12795a2f917SYintian Tao 12875758255SAlex Deucher if (use_bank) { 12975758255SAlex Deucher if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || 130a9ffe2a9SAlex Deucher (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) { 1314a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 1324a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 13395a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 13475758255SAlex Deucher return -EINVAL; 135a9ffe2a9SAlex Deucher } 13675758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 13775758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, se_bank, 13875758255SAlex Deucher sh_bank, instance_bank); 139f7a9ee81SAndrey Grodzovsky } else if (use_ring) { 140f7a9ee81SAndrey Grodzovsky mutex_lock(&adev->srbm_mutex); 1410fa4246eSTom St Denis amdgpu_gfx_select_me_pipe_q(adev, me, pipe, queue, vmid); 14275758255SAlex Deucher } 14375758255SAlex Deucher 14475758255SAlex Deucher if (pm_pg_lock) 14575758255SAlex Deucher mutex_lock(&adev->pm.mutex); 14675758255SAlex Deucher 14775758255SAlex Deucher while (size) { 14875758255SAlex Deucher uint32_t value; 14975758255SAlex Deucher 150f7a9ee81SAndrey Grodzovsky if (read) { 15175758255SAlex Deucher value = RREG32(*pos >> 2); 15275758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 153f7a9ee81SAndrey Grodzovsky } else { 154f7a9ee81SAndrey Grodzovsky r = get_user(value, (uint32_t *)buf); 155f7a9ee81SAndrey Grodzovsky if (!r) 156f7ee1874SHawking Zhang amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value); 157f7a9ee81SAndrey Grodzovsky } 15875758255SAlex Deucher if (r) { 15975758255SAlex Deucher result = r; 16075758255SAlex Deucher goto end; 16175758255SAlex Deucher } 16275758255SAlex Deucher 16375758255SAlex Deucher result += 4; 16475758255SAlex Deucher buf += 4; 16575758255SAlex Deucher *pos += 4; 16675758255SAlex Deucher size -= 4; 16775758255SAlex Deucher } 16875758255SAlex Deucher 16975758255SAlex Deucher end: 17075758255SAlex Deucher if (use_bank) { 17175758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); 17275758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 173f7a9ee81SAndrey Grodzovsky } else if (use_ring) { 1740fa4246eSTom St Denis amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0); 175f7a9ee81SAndrey Grodzovsky mutex_unlock(&adev->srbm_mutex); 17675758255SAlex Deucher } 17775758255SAlex Deucher 17875758255SAlex Deucher if (pm_pg_lock) 17975758255SAlex Deucher mutex_unlock(&adev->pm.mutex); 18075758255SAlex Deucher 1814a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 1824a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 183a9ffe2a9SAlex Deucher 18495a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 18575758255SAlex Deucher return result; 18675758255SAlex Deucher } 18775758255SAlex Deucher 18820ed491bSLee Jones /* 1897e4237dbSTom St Denis * amdgpu_debugfs_regs_read - Callback for reading MMIO registers 1907e4237dbSTom St Denis */ 191f7a9ee81SAndrey Grodzovsky static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, 192f7a9ee81SAndrey Grodzovsky size_t size, loff_t *pos) 193f7a9ee81SAndrey Grodzovsky { 194f7a9ee81SAndrey Grodzovsky return amdgpu_debugfs_process_reg_op(true, f, buf, size, pos); 195f7a9ee81SAndrey Grodzovsky } 196f7a9ee81SAndrey Grodzovsky 19720ed491bSLee Jones /* 1987e4237dbSTom St Denis * amdgpu_debugfs_regs_write - Callback for writing MMIO registers 1997e4237dbSTom St Denis */ 20075758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, 20175758255SAlex Deucher size_t size, loff_t *pos) 20275758255SAlex Deucher { 203f7a9ee81SAndrey Grodzovsky return amdgpu_debugfs_process_reg_op(false, f, (char __user *)buf, size, pos); 20475758255SAlex Deucher } 20575758255SAlex Deucher 20637df9560STom St Denis static int amdgpu_debugfs_regs2_open(struct inode *inode, struct file *file) 20737df9560STom St Denis { 20837df9560STom St Denis struct amdgpu_debugfs_regs2_data *rd; 20937df9560STom St Denis 21037df9560STom St Denis rd = kzalloc(sizeof *rd, GFP_KERNEL); 21137df9560STom St Denis if (!rd) 21237df9560STom St Denis return -ENOMEM; 21337df9560STom St Denis rd->adev = file_inode(file)->i_private; 21437df9560STom St Denis file->private_data = rd; 21537df9560STom St Denis mutex_init(&rd->lock); 21637df9560STom St Denis 21737df9560STom St Denis return 0; 21837df9560STom St Denis } 21937df9560STom St Denis 22037df9560STom St Denis static int amdgpu_debugfs_regs2_release(struct inode *inode, struct file *file) 22137df9560STom St Denis { 22237df9560STom St Denis struct amdgpu_debugfs_regs2_data *rd = file->private_data; 22337df9560STom St Denis mutex_destroy(&rd->lock); 22437df9560STom St Denis kfree(file->private_data); 22537df9560STom St Denis return 0; 22637df9560STom St Denis } 22737df9560STom St Denis 22837df9560STom St Denis static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 offset, size_t size, int write_en) 22937df9560STom St Denis { 23037df9560STom St Denis struct amdgpu_debugfs_regs2_data *rd = f->private_data; 23137df9560STom St Denis struct amdgpu_device *adev = rd->adev; 23237df9560STom St Denis ssize_t result = 0; 23337df9560STom St Denis int r; 23437df9560STom St Denis uint32_t value; 23537df9560STom St Denis 23637df9560STom St Denis if (size & 0x3 || offset & 0x3) 23737df9560STom St Denis return -EINVAL; 23837df9560STom St Denis 23937df9560STom St Denis r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 24037df9560STom St Denis if (r < 0) { 24137df9560STom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 24237df9560STom St Denis return r; 24337df9560STom St Denis } 24437df9560STom St Denis 24537df9560STom St Denis r = amdgpu_virt_enable_access_debugfs(adev); 24637df9560STom St Denis if (r < 0) { 24737df9560STom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 24837df9560STom St Denis return r; 24937df9560STom St Denis } 25037df9560STom St Denis 25137df9560STom St Denis mutex_lock(&rd->lock); 25237df9560STom St Denis 25337df9560STom St Denis if (rd->id.use_grbm) { 25437df9560STom St Denis if ((rd->id.grbm.sh != 0xFFFFFFFF && rd->id.grbm.sh >= adev->gfx.config.max_sh_per_se) || 25537df9560STom St Denis (rd->id.grbm.se != 0xFFFFFFFF && rd->id.grbm.se >= adev->gfx.config.max_shader_engines)) { 25637df9560STom St Denis pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 25737df9560STom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 25837df9560STom St Denis amdgpu_virt_disable_access_debugfs(adev); 25937df9560STom St Denis mutex_unlock(&rd->lock); 26037df9560STom St Denis return -EINVAL; 26137df9560STom St Denis } 26237df9560STom St Denis mutex_lock(&adev->grbm_idx_mutex); 26337df9560STom St Denis amdgpu_gfx_select_se_sh(adev, rd->id.grbm.se, 26437df9560STom St Denis rd->id.grbm.sh, 26537df9560STom St Denis rd->id.grbm.instance); 26637df9560STom St Denis } 26737df9560STom St Denis 26837df9560STom St Denis if (rd->id.use_srbm) { 26937df9560STom St Denis mutex_lock(&adev->srbm_mutex); 27037df9560STom St Denis amdgpu_gfx_select_me_pipe_q(adev, rd->id.srbm.me, rd->id.srbm.pipe, 27137df9560STom St Denis rd->id.srbm.queue, rd->id.srbm.vmid); 27237df9560STom St Denis } 27337df9560STom St Denis 27437df9560STom St Denis if (rd->id.pg_lock) 27537df9560STom St Denis mutex_lock(&adev->pm.mutex); 27637df9560STom St Denis 27737df9560STom St Denis while (size) { 27837df9560STom St Denis if (!write_en) { 27937df9560STom St Denis value = RREG32(offset >> 2); 28037df9560STom St Denis r = put_user(value, (uint32_t *)buf); 28137df9560STom St Denis } else { 28237df9560STom St Denis r = get_user(value, (uint32_t *)buf); 28337df9560STom St Denis if (!r) 28437df9560STom St Denis amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, value); 28537df9560STom St Denis } 28637df9560STom St Denis if (r) { 28737df9560STom St Denis result = r; 28837df9560STom St Denis goto end; 28937df9560STom St Denis } 29037df9560STom St Denis offset += 4; 29137df9560STom St Denis size -= 4; 29237df9560STom St Denis result += 4; 29337df9560STom St Denis buf += 4; 29437df9560STom St Denis } 29537df9560STom St Denis end: 29637df9560STom St Denis if (rd->id.use_grbm) { 29737df9560STom St Denis amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); 29837df9560STom St Denis mutex_unlock(&adev->grbm_idx_mutex); 29937df9560STom St Denis } 30037df9560STom St Denis 30137df9560STom St Denis if (rd->id.use_srbm) { 30237df9560STom St Denis amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0); 30337df9560STom St Denis mutex_unlock(&adev->srbm_mutex); 30437df9560STom St Denis } 30537df9560STom St Denis 30637df9560STom St Denis if (rd->id.pg_lock) 30737df9560STom St Denis mutex_unlock(&adev->pm.mutex); 30837df9560STom St Denis 30937df9560STom St Denis mutex_unlock(&rd->lock); 31037df9560STom St Denis 31137df9560STom St Denis pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 31237df9560STom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 31337df9560STom St Denis 31437df9560STom St Denis amdgpu_virt_disable_access_debugfs(adev); 31537df9560STom St Denis return result; 31637df9560STom St Denis } 31737df9560STom St Denis 31837df9560STom St Denis static long amdgpu_debugfs_regs2_ioctl(struct file *f, unsigned int cmd, unsigned long data) 31937df9560STom St Denis { 32037df9560STom St Denis struct amdgpu_debugfs_regs2_data *rd = f->private_data; 32137df9560STom St Denis int r; 32237df9560STom St Denis 32337df9560STom St Denis switch (cmd) { 32437df9560STom St Denis case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE: 32537df9560STom St Denis mutex_lock(&rd->lock); 32637df9560STom St Denis r = copy_from_user(&rd->id, (struct amdgpu_debugfs_regs2_iocdata *)data, sizeof rd->id); 32737df9560STom St Denis mutex_unlock(&rd->lock); 32837df9560STom St Denis return r ? -EINVAL : 0; 32937df9560STom St Denis default: 33037df9560STom St Denis return -EINVAL; 33137df9560STom St Denis } 33237df9560STom St Denis return 0; 33337df9560STom St Denis } 33437df9560STom St Denis 33537df9560STom St Denis static ssize_t amdgpu_debugfs_regs2_read(struct file *f, char __user *buf, size_t size, loff_t *pos) 33637df9560STom St Denis { 33737df9560STom St Denis return amdgpu_debugfs_regs2_op(f, buf, *pos, size, 0); 33837df9560STom St Denis } 33937df9560STom St Denis 34037df9560STom St Denis static ssize_t amdgpu_debugfs_regs2_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) 34137df9560STom St Denis { 34237df9560STom St Denis return amdgpu_debugfs_regs2_op(f, (char __user *)buf, *pos, size, 1); 34337df9560STom St Denis } 34437df9560STom St Denis 3457e4237dbSTom St Denis 3467e4237dbSTom St Denis /** 3477e4237dbSTom St Denis * amdgpu_debugfs_regs_pcie_read - Read from a PCIE register 3487e4237dbSTom St Denis * 3497e4237dbSTom St Denis * @f: open file handle 3507e4237dbSTom St Denis * @buf: User buffer to store read data in 3517e4237dbSTom St Denis * @size: Number of bytes to read 3527e4237dbSTom St Denis * @pos: Offset to seek to 3537e4237dbSTom St Denis * 3547e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 3557e4237dbSTom St Denis * allows reading multiple registers in a single call and having 3567e4237dbSTom St Denis * the returned size reflect that. 3577e4237dbSTom St Denis */ 35875758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, 35975758255SAlex Deucher size_t size, loff_t *pos) 36075758255SAlex Deucher { 36175758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 36275758255SAlex Deucher ssize_t result = 0; 36375758255SAlex Deucher int r; 36475758255SAlex Deucher 36575758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 36675758255SAlex Deucher return -EINVAL; 36775758255SAlex Deucher 3684a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 3699eee152aSAlex Deucher if (r < 0) { 3704a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 371a9ffe2a9SAlex Deucher return r; 3729eee152aSAlex Deucher } 373a9ffe2a9SAlex Deucher 37495a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 3759eee152aSAlex Deucher if (r < 0) { 3764a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 37795a2f917SYintian Tao return r; 3789eee152aSAlex Deucher } 37995a2f917SYintian Tao 38075758255SAlex Deucher while (size) { 38175758255SAlex Deucher uint32_t value; 38275758255SAlex Deucher 38343fb6c19SKevin Wang value = RREG32_PCIE(*pos); 38475758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 385a9ffe2a9SAlex Deucher if (r) { 3864a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 3874a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 38895a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 38975758255SAlex Deucher return r; 390a9ffe2a9SAlex Deucher } 39175758255SAlex Deucher 39275758255SAlex Deucher result += 4; 39375758255SAlex Deucher buf += 4; 39475758255SAlex Deucher *pos += 4; 39575758255SAlex Deucher size -= 4; 39675758255SAlex Deucher } 39775758255SAlex Deucher 3984a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 3994a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 400a9ffe2a9SAlex Deucher 40195a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 40275758255SAlex Deucher return result; 40375758255SAlex Deucher } 40475758255SAlex Deucher 4057e4237dbSTom St Denis /** 4067e4237dbSTom St Denis * amdgpu_debugfs_regs_pcie_write - Write to a PCIE register 4077e4237dbSTom St Denis * 4087e4237dbSTom St Denis * @f: open file handle 4097e4237dbSTom St Denis * @buf: User buffer to write data from 4107e4237dbSTom St Denis * @size: Number of bytes to write 4117e4237dbSTom St Denis * @pos: Offset to seek to 4127e4237dbSTom St Denis * 4137e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 4147e4237dbSTom St Denis * allows writing multiple registers in a single call and having 4157e4237dbSTom St Denis * the returned size reflect that. 4167e4237dbSTom St Denis */ 41775758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf, 41875758255SAlex Deucher size_t size, loff_t *pos) 41975758255SAlex Deucher { 42075758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 42175758255SAlex Deucher ssize_t result = 0; 42275758255SAlex Deucher int r; 42375758255SAlex Deucher 42475758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 42575758255SAlex Deucher return -EINVAL; 42675758255SAlex Deucher 4274a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 4289eee152aSAlex Deucher if (r < 0) { 4294a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 430a9ffe2a9SAlex Deucher return r; 4319eee152aSAlex Deucher } 432a9ffe2a9SAlex Deucher 43395a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 4349eee152aSAlex Deucher if (r < 0) { 4354a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 43695a2f917SYintian Tao return r; 4379eee152aSAlex Deucher } 43895a2f917SYintian Tao 43975758255SAlex Deucher while (size) { 44075758255SAlex Deucher uint32_t value; 44175758255SAlex Deucher 44275758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 443a9ffe2a9SAlex Deucher if (r) { 4444a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 4454a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 44695a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 44775758255SAlex Deucher return r; 448a9ffe2a9SAlex Deucher } 44975758255SAlex Deucher 45043fb6c19SKevin Wang WREG32_PCIE(*pos, value); 45175758255SAlex Deucher 45275758255SAlex Deucher result += 4; 45375758255SAlex Deucher buf += 4; 45475758255SAlex Deucher *pos += 4; 45575758255SAlex Deucher size -= 4; 45675758255SAlex Deucher } 45775758255SAlex Deucher 4584a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 4594a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 460a9ffe2a9SAlex Deucher 46195a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 46275758255SAlex Deucher return result; 46375758255SAlex Deucher } 46475758255SAlex Deucher 4657e4237dbSTom St Denis /** 4667e4237dbSTom St Denis * amdgpu_debugfs_regs_didt_read - Read from a DIDT register 4677e4237dbSTom St Denis * 4687e4237dbSTom St Denis * @f: open file handle 4697e4237dbSTom St Denis * @buf: User buffer to store read data in 4707e4237dbSTom St Denis * @size: Number of bytes to read 4717e4237dbSTom St Denis * @pos: Offset to seek to 4727e4237dbSTom St Denis * 4737e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 4747e4237dbSTom St Denis * allows reading multiple registers in a single call and having 4757e4237dbSTom St Denis * the returned size reflect that. 4767e4237dbSTom St Denis */ 47775758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, 47875758255SAlex Deucher size_t size, loff_t *pos) 47975758255SAlex Deucher { 48075758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 48175758255SAlex Deucher ssize_t result = 0; 48275758255SAlex Deucher int r; 48375758255SAlex Deucher 48475758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 48575758255SAlex Deucher return -EINVAL; 48675758255SAlex Deucher 4874a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 4889eee152aSAlex Deucher if (r < 0) { 4894a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 490a9ffe2a9SAlex Deucher return r; 4919eee152aSAlex Deucher } 492a9ffe2a9SAlex Deucher 49395a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 4949eee152aSAlex Deucher if (r < 0) { 4954a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 49695a2f917SYintian Tao return r; 4979eee152aSAlex Deucher } 49895a2f917SYintian Tao 49975758255SAlex Deucher while (size) { 50075758255SAlex Deucher uint32_t value; 50175758255SAlex Deucher 50275758255SAlex Deucher value = RREG32_DIDT(*pos >> 2); 50375758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 504a9ffe2a9SAlex Deucher if (r) { 5054a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 5064a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 50795a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 50875758255SAlex Deucher return r; 509a9ffe2a9SAlex Deucher } 51075758255SAlex Deucher 51175758255SAlex Deucher result += 4; 51275758255SAlex Deucher buf += 4; 51375758255SAlex Deucher *pos += 4; 51475758255SAlex Deucher size -= 4; 51575758255SAlex Deucher } 51675758255SAlex Deucher 5174a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 5184a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 519a9ffe2a9SAlex Deucher 52095a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 52175758255SAlex Deucher return result; 52275758255SAlex Deucher } 52375758255SAlex Deucher 5247e4237dbSTom St Denis /** 5257e4237dbSTom St Denis * amdgpu_debugfs_regs_didt_write - Write to a DIDT register 5267e4237dbSTom St Denis * 5277e4237dbSTom St Denis * @f: open file handle 5287e4237dbSTom St Denis * @buf: User buffer to write data from 5297e4237dbSTom St Denis * @size: Number of bytes to write 5307e4237dbSTom St Denis * @pos: Offset to seek to 5317e4237dbSTom St Denis * 5327e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 5337e4237dbSTom St Denis * allows writing multiple registers in a single call and having 5347e4237dbSTom St Denis * the returned size reflect that. 5357e4237dbSTom St Denis */ 53675758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf, 53775758255SAlex Deucher size_t size, loff_t *pos) 53875758255SAlex Deucher { 53975758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 54075758255SAlex Deucher ssize_t result = 0; 54175758255SAlex Deucher int r; 54275758255SAlex Deucher 54375758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 54475758255SAlex Deucher return -EINVAL; 54575758255SAlex Deucher 5464a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 5479eee152aSAlex Deucher if (r < 0) { 5484a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 549a9ffe2a9SAlex Deucher return r; 5509eee152aSAlex Deucher } 551a9ffe2a9SAlex Deucher 55295a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 5539eee152aSAlex Deucher if (r < 0) { 5544a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 55595a2f917SYintian Tao return r; 5569eee152aSAlex Deucher } 55795a2f917SYintian Tao 55875758255SAlex Deucher while (size) { 55975758255SAlex Deucher uint32_t value; 56075758255SAlex Deucher 56175758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 562a9ffe2a9SAlex Deucher if (r) { 5634a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 5644a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 56595a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 56675758255SAlex Deucher return r; 567a9ffe2a9SAlex Deucher } 56875758255SAlex Deucher 56975758255SAlex Deucher WREG32_DIDT(*pos >> 2, value); 57075758255SAlex Deucher 57175758255SAlex Deucher result += 4; 57275758255SAlex Deucher buf += 4; 57375758255SAlex Deucher *pos += 4; 57475758255SAlex Deucher size -= 4; 57575758255SAlex Deucher } 57675758255SAlex Deucher 5774a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 5784a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 579a9ffe2a9SAlex Deucher 58095a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 58175758255SAlex Deucher return result; 58275758255SAlex Deucher } 58375758255SAlex Deucher 5847e4237dbSTom St Denis /** 5857e4237dbSTom St Denis * amdgpu_debugfs_regs_smc_read - Read from a SMC register 5867e4237dbSTom St Denis * 5877e4237dbSTom St Denis * @f: open file handle 5887e4237dbSTom St Denis * @buf: User buffer to store read data in 5897e4237dbSTom St Denis * @size: Number of bytes to read 5907e4237dbSTom St Denis * @pos: Offset to seek to 5917e4237dbSTom St Denis * 5927e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 5937e4237dbSTom St Denis * allows reading multiple registers in a single call and having 5947e4237dbSTom St Denis * the returned size reflect that. 5957e4237dbSTom St Denis */ 59675758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, 59775758255SAlex Deucher size_t size, loff_t *pos) 59875758255SAlex Deucher { 59975758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 60075758255SAlex Deucher ssize_t result = 0; 60175758255SAlex Deucher int r; 60275758255SAlex Deucher 60375758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 60475758255SAlex Deucher return -EINVAL; 60575758255SAlex Deucher 6064a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 6079eee152aSAlex Deucher if (r < 0) { 6084a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 609a9ffe2a9SAlex Deucher return r; 6109eee152aSAlex Deucher } 611a9ffe2a9SAlex Deucher 61295a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 6139eee152aSAlex Deucher if (r < 0) { 6144a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 61595a2f917SYintian Tao return r; 6169eee152aSAlex Deucher } 61795a2f917SYintian Tao 61875758255SAlex Deucher while (size) { 61975758255SAlex Deucher uint32_t value; 62075758255SAlex Deucher 62175758255SAlex Deucher value = RREG32_SMC(*pos); 62275758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 623a9ffe2a9SAlex Deucher if (r) { 6244a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 6254a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 62695a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 62775758255SAlex Deucher return r; 628a9ffe2a9SAlex Deucher } 62975758255SAlex Deucher 63075758255SAlex Deucher result += 4; 63175758255SAlex Deucher buf += 4; 63275758255SAlex Deucher *pos += 4; 63375758255SAlex Deucher size -= 4; 63475758255SAlex Deucher } 63575758255SAlex Deucher 6364a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 6374a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 638a9ffe2a9SAlex Deucher 63995a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 64075758255SAlex Deucher return result; 64175758255SAlex Deucher } 64275758255SAlex Deucher 6437e4237dbSTom St Denis /** 6447e4237dbSTom St Denis * amdgpu_debugfs_regs_smc_write - Write to a SMC register 6457e4237dbSTom St Denis * 6467e4237dbSTom St Denis * @f: open file handle 6477e4237dbSTom St Denis * @buf: User buffer to write data from 6487e4237dbSTom St Denis * @size: Number of bytes to write 6497e4237dbSTom St Denis * @pos: Offset to seek to 6507e4237dbSTom St Denis * 6517e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 6527e4237dbSTom St Denis * allows writing multiple registers in a single call and having 6537e4237dbSTom St Denis * the returned size reflect that. 6547e4237dbSTom St Denis */ 65575758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf, 65675758255SAlex Deucher size_t size, loff_t *pos) 65775758255SAlex Deucher { 65875758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 65975758255SAlex Deucher ssize_t result = 0; 66075758255SAlex Deucher int r; 66175758255SAlex Deucher 66275758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 66375758255SAlex Deucher return -EINVAL; 66475758255SAlex Deucher 6654a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 6669eee152aSAlex Deucher if (r < 0) { 6674a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 668a9ffe2a9SAlex Deucher return r; 6699eee152aSAlex Deucher } 670a9ffe2a9SAlex Deucher 67195a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 6729eee152aSAlex Deucher if (r < 0) { 6734a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 67495a2f917SYintian Tao return r; 6759eee152aSAlex Deucher } 67695a2f917SYintian Tao 67775758255SAlex Deucher while (size) { 67875758255SAlex Deucher uint32_t value; 67975758255SAlex Deucher 68075758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 681a9ffe2a9SAlex Deucher if (r) { 6824a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 6834a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 68495a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 68575758255SAlex Deucher return r; 686a9ffe2a9SAlex Deucher } 68775758255SAlex Deucher 68875758255SAlex Deucher WREG32_SMC(*pos, value); 68975758255SAlex Deucher 69075758255SAlex Deucher result += 4; 69175758255SAlex Deucher buf += 4; 69275758255SAlex Deucher *pos += 4; 69375758255SAlex Deucher size -= 4; 69475758255SAlex Deucher } 69575758255SAlex Deucher 6964a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 6974a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 698a9ffe2a9SAlex Deucher 69995a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 70075758255SAlex Deucher return result; 70175758255SAlex Deucher } 70275758255SAlex Deucher 7037e4237dbSTom St Denis /** 7047e4237dbSTom St Denis * amdgpu_debugfs_gca_config_read - Read from gfx config data 7057e4237dbSTom St Denis * 7067e4237dbSTom St Denis * @f: open file handle 7077e4237dbSTom St Denis * @buf: User buffer to store read data in 7087e4237dbSTom St Denis * @size: Number of bytes to read 7097e4237dbSTom St Denis * @pos: Offset to seek to 7107e4237dbSTom St Denis * 7117e4237dbSTom St Denis * This file is used to access configuration data in a somewhat 7127e4237dbSTom St Denis * stable fashion. The format is a series of DWORDs with the first 7137e4237dbSTom St Denis * indicating which revision it is. New content is appended to the 7147e4237dbSTom St Denis * end so that older software can still read the data. 7157e4237dbSTom St Denis */ 7167e4237dbSTom St Denis 71775758255SAlex Deucher static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, 71875758255SAlex Deucher size_t size, loff_t *pos) 71975758255SAlex Deucher { 72075758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 72175758255SAlex Deucher ssize_t result = 0; 72275758255SAlex Deucher int r; 72375758255SAlex Deucher uint32_t *config, no_regs = 0; 72475758255SAlex Deucher 72575758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 72675758255SAlex Deucher return -EINVAL; 72775758255SAlex Deucher 72875758255SAlex Deucher config = kmalloc_array(256, sizeof(*config), GFP_KERNEL); 72975758255SAlex Deucher if (!config) 73075758255SAlex Deucher return -ENOMEM; 73175758255SAlex Deucher 73275758255SAlex Deucher /* version, increment each time something is added */ 7338f74f68dSTom St Denis config[no_regs++] = 4; 73475758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_shader_engines; 73575758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_tile_pipes; 73675758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_cu_per_sh; 73775758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_sh_per_se; 73875758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_backends_per_se; 73975758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_texture_channel_caches; 74075758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_gprs; 74175758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_gs_threads; 74275758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_hw_contexts; 74375758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_frontend; 74475758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_backend; 74575758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_hiz_tile_fifo_size; 74675758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_earlyz_tile_fifo_size; 74775758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_tile_pipes; 74875758255SAlex Deucher config[no_regs++] = adev->gfx.config.backend_enable_mask; 74975758255SAlex Deucher config[no_regs++] = adev->gfx.config.mem_max_burst_length_bytes; 75075758255SAlex Deucher config[no_regs++] = adev->gfx.config.mem_row_size_in_kb; 75175758255SAlex Deucher config[no_regs++] = adev->gfx.config.shader_engine_tile_size; 75275758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_gpus; 75375758255SAlex Deucher config[no_regs++] = adev->gfx.config.multi_gpu_tile_size; 75475758255SAlex Deucher config[no_regs++] = adev->gfx.config.mc_arb_ramcfg; 75575758255SAlex Deucher config[no_regs++] = adev->gfx.config.gb_addr_config; 75675758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_rbs; 75775758255SAlex Deucher 75875758255SAlex Deucher /* rev==1 */ 75975758255SAlex Deucher config[no_regs++] = adev->rev_id; 76075758255SAlex Deucher config[no_regs++] = adev->pg_flags; 76175758255SAlex Deucher config[no_regs++] = adev->cg_flags; 76275758255SAlex Deucher 76375758255SAlex Deucher /* rev==2 */ 76475758255SAlex Deucher config[no_regs++] = adev->family; 76575758255SAlex Deucher config[no_regs++] = adev->external_rev_id; 76675758255SAlex Deucher 76775758255SAlex Deucher /* rev==3 */ 76875758255SAlex Deucher config[no_regs++] = adev->pdev->device; 76975758255SAlex Deucher config[no_regs++] = adev->pdev->revision; 77075758255SAlex Deucher config[no_regs++] = adev->pdev->subsystem_device; 77175758255SAlex Deucher config[no_regs++] = adev->pdev->subsystem_vendor; 77275758255SAlex Deucher 7738f74f68dSTom St Denis /* rev==4 APU flag */ 7748f74f68dSTom St Denis config[no_regs++] = adev->flags & AMD_IS_APU ? 1 : 0; 7758f74f68dSTom St Denis 77675758255SAlex Deucher while (size && (*pos < no_regs * 4)) { 77775758255SAlex Deucher uint32_t value; 77875758255SAlex Deucher 77975758255SAlex Deucher value = config[*pos >> 2]; 78075758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 78175758255SAlex Deucher if (r) { 78275758255SAlex Deucher kfree(config); 78375758255SAlex Deucher return r; 78475758255SAlex Deucher } 78575758255SAlex Deucher 78675758255SAlex Deucher result += 4; 78775758255SAlex Deucher buf += 4; 78875758255SAlex Deucher *pos += 4; 78975758255SAlex Deucher size -= 4; 79075758255SAlex Deucher } 79175758255SAlex Deucher 79275758255SAlex Deucher kfree(config); 79375758255SAlex Deucher return result; 79475758255SAlex Deucher } 79575758255SAlex Deucher 7967e4237dbSTom St Denis /** 7977e4237dbSTom St Denis * amdgpu_debugfs_sensor_read - Read from the powerplay sensors 7987e4237dbSTom St Denis * 7997e4237dbSTom St Denis * @f: open file handle 8007e4237dbSTom St Denis * @buf: User buffer to store read data in 8017e4237dbSTom St Denis * @size: Number of bytes to read 8027e4237dbSTom St Denis * @pos: Offset to seek to 8037e4237dbSTom St Denis * 8047e4237dbSTom St Denis * The offset is treated as the BYTE address of one of the sensors 8057e4237dbSTom St Denis * enumerated in amd/include/kgd_pp_interface.h under the 8067e4237dbSTom St Denis * 'amd_pp_sensors' enumeration. For instance to read the UVD VCLK 8077e4237dbSTom St Denis * you would use the offset 3 * 4 = 12. 8087e4237dbSTom St Denis */ 80975758255SAlex Deucher static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, 81075758255SAlex Deucher size_t size, loff_t *pos) 81175758255SAlex Deucher { 81275758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 81375758255SAlex Deucher int idx, x, outsize, r, valuesize; 81475758255SAlex Deucher uint32_t values[16]; 81575758255SAlex Deucher 81675758255SAlex Deucher if (size & 3 || *pos & 0x3) 81775758255SAlex Deucher return -EINVAL; 81875758255SAlex Deucher 819b13aa109SRex Zhu if (!adev->pm.dpm_enabled) 82075758255SAlex Deucher return -EINVAL; 82175758255SAlex Deucher 82275758255SAlex Deucher /* convert offset to sensor number */ 82375758255SAlex Deucher idx = *pos >> 2; 82475758255SAlex Deucher 82575758255SAlex Deucher valuesize = sizeof(values); 826a9ffe2a9SAlex Deucher 8274a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 8289eee152aSAlex Deucher if (r < 0) { 8294a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 830a9ffe2a9SAlex Deucher return r; 8319eee152aSAlex Deucher } 832a9ffe2a9SAlex Deucher 83395a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 8349eee152aSAlex Deucher if (r < 0) { 8354a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 83695a2f917SYintian Tao return r; 8379eee152aSAlex Deucher } 83895a2f917SYintian Tao 83975758255SAlex Deucher r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize); 840a9ffe2a9SAlex Deucher 8414a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 8424a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 843a9ffe2a9SAlex Deucher 84495a2f917SYintian Tao if (r) { 84595a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 8464a5a2de6SKevin Wang return r; 84795a2f917SYintian Tao } 84875758255SAlex Deucher 84995a2f917SYintian Tao if (size > valuesize) { 85095a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 85175758255SAlex Deucher return -EINVAL; 85295a2f917SYintian Tao } 85375758255SAlex Deucher 85475758255SAlex Deucher outsize = 0; 85575758255SAlex Deucher x = 0; 85675758255SAlex Deucher if (!r) { 85775758255SAlex Deucher while (size) { 85875758255SAlex Deucher r = put_user(values[x++], (int32_t *)buf); 85975758255SAlex Deucher buf += 4; 86075758255SAlex Deucher size -= 4; 86175758255SAlex Deucher outsize += 4; 86275758255SAlex Deucher } 86375758255SAlex Deucher } 86475758255SAlex Deucher 86595a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 86675758255SAlex Deucher return !r ? outsize : r; 86775758255SAlex Deucher } 86875758255SAlex Deucher 8697e4237dbSTom St Denis /** amdgpu_debugfs_wave_read - Read WAVE STATUS data 8707e4237dbSTom St Denis * 8717e4237dbSTom St Denis * @f: open file handle 8727e4237dbSTom St Denis * @buf: User buffer to store read data in 8737e4237dbSTom St Denis * @size: Number of bytes to read 8747e4237dbSTom St Denis * @pos: Offset to seek to 8757e4237dbSTom St Denis * 8767e4237dbSTom St Denis * The offset being sought changes which wave that the status data 8777e4237dbSTom St Denis * will be returned for. The bits are used as follows: 8787e4237dbSTom St Denis * 8797e4237dbSTom St Denis * Bits 0..6: Byte offset into data 8807e4237dbSTom St Denis * Bits 7..14: SE selector 8817e4237dbSTom St Denis * Bits 15..22: SH/SA selector 8827e4237dbSTom St Denis * Bits 23..30: CU/{WGP+SIMD} selector 8837e4237dbSTom St Denis * Bits 31..36: WAVE ID selector 8847e4237dbSTom St Denis * Bits 37..44: SIMD ID selector 8857e4237dbSTom St Denis * 8867e4237dbSTom St Denis * The returned data begins with one DWORD of version information 8877e4237dbSTom St Denis * Followed by WAVE STATUS registers relevant to the GFX IP version 8887e4237dbSTom St Denis * being used. See gfx_v8_0_read_wave_data() for an example output. 8897e4237dbSTom St Denis */ 89075758255SAlex Deucher static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, 89175758255SAlex Deucher size_t size, loff_t *pos) 89275758255SAlex Deucher { 89375758255SAlex Deucher struct amdgpu_device *adev = f->f_inode->i_private; 89475758255SAlex Deucher int r, x; 89575758255SAlex Deucher ssize_t result = 0; 89675758255SAlex Deucher uint32_t offset, se, sh, cu, wave, simd, data[32]; 89775758255SAlex Deucher 89875758255SAlex Deucher if (size & 3 || *pos & 3) 89975758255SAlex Deucher return -EINVAL; 90075758255SAlex Deucher 90175758255SAlex Deucher /* decode offset */ 90275758255SAlex Deucher offset = (*pos & GENMASK_ULL(6, 0)); 90375758255SAlex Deucher se = (*pos & GENMASK_ULL(14, 7)) >> 7; 90475758255SAlex Deucher sh = (*pos & GENMASK_ULL(22, 15)) >> 15; 90575758255SAlex Deucher cu = (*pos & GENMASK_ULL(30, 23)) >> 23; 90675758255SAlex Deucher wave = (*pos & GENMASK_ULL(36, 31)) >> 31; 90775758255SAlex Deucher simd = (*pos & GENMASK_ULL(44, 37)) >> 37; 90875758255SAlex Deucher 9094a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 9109eee152aSAlex Deucher if (r < 0) { 9114a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 912a9ffe2a9SAlex Deucher return r; 9139eee152aSAlex Deucher } 914a9ffe2a9SAlex Deucher 91595a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 9169eee152aSAlex Deucher if (r < 0) { 9174a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 91895a2f917SYintian Tao return r; 9199eee152aSAlex Deucher } 92095a2f917SYintian Tao 92175758255SAlex Deucher /* switch to the specific se/sh/cu */ 92275758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 92375758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, se, sh, cu); 92475758255SAlex Deucher 92575758255SAlex Deucher x = 0; 92675758255SAlex Deucher if (adev->gfx.funcs->read_wave_data) 92775758255SAlex Deucher adev->gfx.funcs->read_wave_data(adev, simd, wave, data, &x); 92875758255SAlex Deucher 92975758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); 93075758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 93175758255SAlex Deucher 9324a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 9334a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 934a9ffe2a9SAlex Deucher 93595a2f917SYintian Tao if (!x) { 93695a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 93775758255SAlex Deucher return -EINVAL; 93895a2f917SYintian Tao } 93975758255SAlex Deucher 94075758255SAlex Deucher while (size && (offset < x * 4)) { 94175758255SAlex Deucher uint32_t value; 94275758255SAlex Deucher 94375758255SAlex Deucher value = data[offset >> 2]; 94475758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 94595a2f917SYintian Tao if (r) { 94695a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 94775758255SAlex Deucher return r; 94895a2f917SYintian Tao } 94975758255SAlex Deucher 95075758255SAlex Deucher result += 4; 95175758255SAlex Deucher buf += 4; 95275758255SAlex Deucher offset += 4; 95375758255SAlex Deucher size -= 4; 95475758255SAlex Deucher } 95575758255SAlex Deucher 95695a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 95775758255SAlex Deucher return result; 95875758255SAlex Deucher } 95975758255SAlex Deucher 9607e4237dbSTom St Denis /** amdgpu_debugfs_gpr_read - Read wave gprs 9617e4237dbSTom St Denis * 9627e4237dbSTom St Denis * @f: open file handle 9637e4237dbSTom St Denis * @buf: User buffer to store read data in 9647e4237dbSTom St Denis * @size: Number of bytes to read 9657e4237dbSTom St Denis * @pos: Offset to seek to 9667e4237dbSTom St Denis * 9677e4237dbSTom St Denis * The offset being sought changes which wave that the status data 9687e4237dbSTom St Denis * will be returned for. The bits are used as follows: 9697e4237dbSTom St Denis * 9707e4237dbSTom St Denis * Bits 0..11: Byte offset into data 9717e4237dbSTom St Denis * Bits 12..19: SE selector 9727e4237dbSTom St Denis * Bits 20..27: SH/SA selector 9737e4237dbSTom St Denis * Bits 28..35: CU/{WGP+SIMD} selector 9747e4237dbSTom St Denis * Bits 36..43: WAVE ID selector 9757e4237dbSTom St Denis * Bits 37..44: SIMD ID selector 9767e4237dbSTom St Denis * Bits 52..59: Thread selector 9777e4237dbSTom St Denis * Bits 60..61: Bank selector (VGPR=0,SGPR=1) 9787e4237dbSTom St Denis * 9797e4237dbSTom St Denis * The return data comes from the SGPR or VGPR register bank for 9807e4237dbSTom St Denis * the selected operational unit. 9817e4237dbSTom St Denis */ 98275758255SAlex Deucher static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, 98375758255SAlex Deucher size_t size, loff_t *pos) 98475758255SAlex Deucher { 98575758255SAlex Deucher struct amdgpu_device *adev = f->f_inode->i_private; 98675758255SAlex Deucher int r; 98775758255SAlex Deucher ssize_t result = 0; 98875758255SAlex Deucher uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; 98975758255SAlex Deucher 9906397ec58STom St Denis if (size > 4096 || size & 3 || *pos & 3) 99175758255SAlex Deucher return -EINVAL; 99275758255SAlex Deucher 99375758255SAlex Deucher /* decode offset */ 9946397ec58STom St Denis offset = (*pos & GENMASK_ULL(11, 0)) >> 2; 99575758255SAlex Deucher se = (*pos & GENMASK_ULL(19, 12)) >> 12; 99675758255SAlex Deucher sh = (*pos & GENMASK_ULL(27, 20)) >> 20; 99775758255SAlex Deucher cu = (*pos & GENMASK_ULL(35, 28)) >> 28; 99875758255SAlex Deucher wave = (*pos & GENMASK_ULL(43, 36)) >> 36; 99975758255SAlex Deucher simd = (*pos & GENMASK_ULL(51, 44)) >> 44; 100075758255SAlex Deucher thread = (*pos & GENMASK_ULL(59, 52)) >> 52; 100175758255SAlex Deucher bank = (*pos & GENMASK_ULL(61, 60)) >> 60; 100275758255SAlex Deucher 1003929e571cSWang Xiayang data = kcalloc(1024, sizeof(*data), GFP_KERNEL); 100475758255SAlex Deucher if (!data) 100575758255SAlex Deucher return -ENOMEM; 100675758255SAlex Deucher 10074a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 1008a9ffe2a9SAlex Deucher if (r < 0) 10093e4aeff3SChen Tao goto err; 1010a9ffe2a9SAlex Deucher 101195a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 101295a2f917SYintian Tao if (r < 0) 1013888e32d7SChen Tao goto err; 101495a2f917SYintian Tao 101575758255SAlex Deucher /* switch to the specific se/sh/cu */ 101675758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 101775758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, se, sh, cu); 101875758255SAlex Deucher 101975758255SAlex Deucher if (bank == 0) { 102075758255SAlex Deucher if (adev->gfx.funcs->read_wave_vgprs) 102175758255SAlex Deucher adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data); 102275758255SAlex Deucher } else { 102375758255SAlex Deucher if (adev->gfx.funcs->read_wave_sgprs) 102475758255SAlex Deucher adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data); 102575758255SAlex Deucher } 102675758255SAlex Deucher 102775758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); 102875758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 102975758255SAlex Deucher 10304a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 10314a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1032a9ffe2a9SAlex Deucher 103375758255SAlex Deucher while (size) { 103475758255SAlex Deucher uint32_t value; 103575758255SAlex Deucher 10366397ec58STom St Denis value = data[result >> 2]; 103775758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 103875758255SAlex Deucher if (r) { 10393e4aeff3SChen Tao amdgpu_virt_disable_access_debugfs(adev); 104075758255SAlex Deucher goto err; 104175758255SAlex Deucher } 104275758255SAlex Deucher 104375758255SAlex Deucher result += 4; 104475758255SAlex Deucher buf += 4; 104575758255SAlex Deucher size -= 4; 104675758255SAlex Deucher } 104775758255SAlex Deucher 104875758255SAlex Deucher kfree(data); 104995a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 105075758255SAlex Deucher return result; 10513e4aeff3SChen Tao 10523e4aeff3SChen Tao err: 10534a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 10543e4aeff3SChen Tao kfree(data); 10553e4aeff3SChen Tao return r; 105675758255SAlex Deucher } 105775758255SAlex Deucher 1058669e2f91STom St Denis /** 1059e72d4a8bSLee Jones * amdgpu_debugfs_gfxoff_write - Enable/disable GFXOFF 1060669e2f91STom St Denis * 1061669e2f91STom St Denis * @f: open file handle 1062669e2f91STom St Denis * @buf: User buffer to write data from 1063669e2f91STom St Denis * @size: Number of bytes to write 1064669e2f91STom St Denis * @pos: Offset to seek to 1065669e2f91STom St Denis * 1066669e2f91STom St Denis * Write a 32-bit zero to disable or a 32-bit non-zero to enable 1067669e2f91STom St Denis */ 1068669e2f91STom St Denis static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *buf, 1069669e2f91STom St Denis size_t size, loff_t *pos) 1070669e2f91STom St Denis { 1071669e2f91STom St Denis struct amdgpu_device *adev = file_inode(f)->i_private; 1072669e2f91STom St Denis ssize_t result = 0; 1073669e2f91STom St Denis int r; 1074669e2f91STom St Denis 1075669e2f91STom St Denis if (size & 0x3 || *pos & 0x3) 1076669e2f91STom St Denis return -EINVAL; 1077669e2f91STom St Denis 10784a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 10799eee152aSAlex Deucher if (r < 0) { 10804a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1081669e2f91STom St Denis return r; 10829eee152aSAlex Deucher } 1083669e2f91STom St Denis 1084669e2f91STom St Denis while (size) { 1085669e2f91STom St Denis uint32_t value; 1086669e2f91STom St Denis 1087669e2f91STom St Denis r = get_user(value, (uint32_t *)buf); 1088669e2f91STom St Denis if (r) { 10894a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 10904a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1091669e2f91STom St Denis return r; 1092669e2f91STom St Denis } 1093669e2f91STom St Denis 1094669e2f91STom St Denis amdgpu_gfx_off_ctrl(adev, value ? true : false); 1095669e2f91STom St Denis 1096669e2f91STom St Denis result += 4; 1097669e2f91STom St Denis buf += 4; 1098669e2f91STom St Denis *pos += 4; 1099669e2f91STom St Denis size -= 4; 1100669e2f91STom St Denis } 1101669e2f91STom St Denis 11024a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 11034a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1104669e2f91STom St Denis 1105669e2f91STom St Denis return result; 1106669e2f91STom St Denis } 1107669e2f91STom St Denis 1108669e2f91STom St Denis 1109443c7f3cSJinzhou.Su /** 1110e72d4a8bSLee Jones * amdgpu_debugfs_gfxoff_read - read gfxoff status 1111443c7f3cSJinzhou.Su * 1112443c7f3cSJinzhou.Su * @f: open file handle 1113443c7f3cSJinzhou.Su * @buf: User buffer to store read data in 1114443c7f3cSJinzhou.Su * @size: Number of bytes to read 1115443c7f3cSJinzhou.Su * @pos: Offset to seek to 1116443c7f3cSJinzhou.Su */ 1117443c7f3cSJinzhou.Su static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, 1118443c7f3cSJinzhou.Su size_t size, loff_t *pos) 1119443c7f3cSJinzhou.Su { 1120443c7f3cSJinzhou.Su struct amdgpu_device *adev = file_inode(f)->i_private; 1121443c7f3cSJinzhou.Su ssize_t result = 0; 1122443c7f3cSJinzhou.Su int r; 1123443c7f3cSJinzhou.Su 1124443c7f3cSJinzhou.Su if (size & 0x3 || *pos & 0x3) 1125443c7f3cSJinzhou.Su return -EINVAL; 1126443c7f3cSJinzhou.Su 11274a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 11284bd8dd0dSYongzhi Liu if (r < 0) { 11294bd8dd0dSYongzhi Liu pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1130443c7f3cSJinzhou.Su return r; 11314bd8dd0dSYongzhi Liu } 1132443c7f3cSJinzhou.Su 1133443c7f3cSJinzhou.Su while (size) { 1134443c7f3cSJinzhou.Su uint32_t value; 1135443c7f3cSJinzhou.Su 1136443c7f3cSJinzhou.Su r = amdgpu_get_gfx_off_status(adev, &value); 1137443c7f3cSJinzhou.Su if (r) { 11384a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 11394a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1140443c7f3cSJinzhou.Su return r; 1141443c7f3cSJinzhou.Su } 1142443c7f3cSJinzhou.Su 1143443c7f3cSJinzhou.Su r = put_user(value, (uint32_t *)buf); 1144443c7f3cSJinzhou.Su if (r) { 11454a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 11464a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1147443c7f3cSJinzhou.Su return r; 1148443c7f3cSJinzhou.Su } 1149443c7f3cSJinzhou.Su 1150443c7f3cSJinzhou.Su result += 4; 1151443c7f3cSJinzhou.Su buf += 4; 1152443c7f3cSJinzhou.Su *pos += 4; 1153443c7f3cSJinzhou.Su size -= 4; 1154443c7f3cSJinzhou.Su } 1155443c7f3cSJinzhou.Su 11564a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 11574a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1158443c7f3cSJinzhou.Su 1159443c7f3cSJinzhou.Su return result; 1160443c7f3cSJinzhou.Su } 1161443c7f3cSJinzhou.Su 116237df9560STom St Denis static const struct file_operations amdgpu_debugfs_regs2_fops = { 116337df9560STom St Denis .owner = THIS_MODULE, 116437df9560STom St Denis .unlocked_ioctl = amdgpu_debugfs_regs2_ioctl, 116537df9560STom St Denis .read = amdgpu_debugfs_regs2_read, 116637df9560STom St Denis .write = amdgpu_debugfs_regs2_write, 116737df9560STom St Denis .open = amdgpu_debugfs_regs2_open, 116837df9560STom St Denis .release = amdgpu_debugfs_regs2_release, 116937df9560STom St Denis .llseek = default_llseek 117037df9560STom St Denis }; 117137df9560STom St Denis 117275758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_fops = { 117375758255SAlex Deucher .owner = THIS_MODULE, 117475758255SAlex Deucher .read = amdgpu_debugfs_regs_read, 117575758255SAlex Deucher .write = amdgpu_debugfs_regs_write, 117675758255SAlex Deucher .llseek = default_llseek 117775758255SAlex Deucher }; 117875758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_didt_fops = { 117975758255SAlex Deucher .owner = THIS_MODULE, 118075758255SAlex Deucher .read = amdgpu_debugfs_regs_didt_read, 118175758255SAlex Deucher .write = amdgpu_debugfs_regs_didt_write, 118275758255SAlex Deucher .llseek = default_llseek 118375758255SAlex Deucher }; 118475758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_pcie_fops = { 118575758255SAlex Deucher .owner = THIS_MODULE, 118675758255SAlex Deucher .read = amdgpu_debugfs_regs_pcie_read, 118775758255SAlex Deucher .write = amdgpu_debugfs_regs_pcie_write, 118875758255SAlex Deucher .llseek = default_llseek 118975758255SAlex Deucher }; 119075758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_smc_fops = { 119175758255SAlex Deucher .owner = THIS_MODULE, 119275758255SAlex Deucher .read = amdgpu_debugfs_regs_smc_read, 119375758255SAlex Deucher .write = amdgpu_debugfs_regs_smc_write, 119475758255SAlex Deucher .llseek = default_llseek 119575758255SAlex Deucher }; 119675758255SAlex Deucher 119775758255SAlex Deucher static const struct file_operations amdgpu_debugfs_gca_config_fops = { 119875758255SAlex Deucher .owner = THIS_MODULE, 119975758255SAlex Deucher .read = amdgpu_debugfs_gca_config_read, 120075758255SAlex Deucher .llseek = default_llseek 120175758255SAlex Deucher }; 120275758255SAlex Deucher 120375758255SAlex Deucher static const struct file_operations amdgpu_debugfs_sensors_fops = { 120475758255SAlex Deucher .owner = THIS_MODULE, 120575758255SAlex Deucher .read = amdgpu_debugfs_sensor_read, 120675758255SAlex Deucher .llseek = default_llseek 120775758255SAlex Deucher }; 120875758255SAlex Deucher 120975758255SAlex Deucher static const struct file_operations amdgpu_debugfs_wave_fops = { 121075758255SAlex Deucher .owner = THIS_MODULE, 121175758255SAlex Deucher .read = amdgpu_debugfs_wave_read, 121275758255SAlex Deucher .llseek = default_llseek 121375758255SAlex Deucher }; 121475758255SAlex Deucher static const struct file_operations amdgpu_debugfs_gpr_fops = { 121575758255SAlex Deucher .owner = THIS_MODULE, 121675758255SAlex Deucher .read = amdgpu_debugfs_gpr_read, 121775758255SAlex Deucher .llseek = default_llseek 121875758255SAlex Deucher }; 121975758255SAlex Deucher 1220669e2f91STom St Denis static const struct file_operations amdgpu_debugfs_gfxoff_fops = { 1221669e2f91STom St Denis .owner = THIS_MODULE, 1222443c7f3cSJinzhou.Su .read = amdgpu_debugfs_gfxoff_read, 1223669e2f91STom St Denis .write = amdgpu_debugfs_gfxoff_write, 1224443c7f3cSJinzhou.Su .llseek = default_llseek 1225669e2f91STom St Denis }; 1226669e2f91STom St Denis 122775758255SAlex Deucher static const struct file_operations *debugfs_regs[] = { 122875758255SAlex Deucher &amdgpu_debugfs_regs_fops, 122937df9560STom St Denis &amdgpu_debugfs_regs2_fops, 123075758255SAlex Deucher &amdgpu_debugfs_regs_didt_fops, 123175758255SAlex Deucher &amdgpu_debugfs_regs_pcie_fops, 123275758255SAlex Deucher &amdgpu_debugfs_regs_smc_fops, 123375758255SAlex Deucher &amdgpu_debugfs_gca_config_fops, 123475758255SAlex Deucher &amdgpu_debugfs_sensors_fops, 123575758255SAlex Deucher &amdgpu_debugfs_wave_fops, 123675758255SAlex Deucher &amdgpu_debugfs_gpr_fops, 1237669e2f91STom St Denis &amdgpu_debugfs_gfxoff_fops, 123875758255SAlex Deucher }; 123975758255SAlex Deucher 124075758255SAlex Deucher static const char *debugfs_regs_names[] = { 124175758255SAlex Deucher "amdgpu_regs", 124237df9560STom St Denis "amdgpu_regs2", 124375758255SAlex Deucher "amdgpu_regs_didt", 124475758255SAlex Deucher "amdgpu_regs_pcie", 124575758255SAlex Deucher "amdgpu_regs_smc", 124675758255SAlex Deucher "amdgpu_gca_config", 124775758255SAlex Deucher "amdgpu_sensors", 124875758255SAlex Deucher "amdgpu_wave", 124975758255SAlex Deucher "amdgpu_gpr", 1250669e2f91STom St Denis "amdgpu_gfxoff", 125175758255SAlex Deucher }; 125275758255SAlex Deucher 12537e4237dbSTom St Denis /** 12547e4237dbSTom St Denis * amdgpu_debugfs_regs_init - Initialize debugfs entries that provide 12557e4237dbSTom St Denis * register access. 12567e4237dbSTom St Denis * 12577e4237dbSTom St Denis * @adev: The device to attach the debugfs entries to 12587e4237dbSTom St Denis */ 125975758255SAlex Deucher int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) 126075758255SAlex Deucher { 12614a580877SLuben Tuikov struct drm_minor *minor = adev_to_drm(adev)->primary; 126275758255SAlex Deucher struct dentry *ent, *root = minor->debugfs_root; 1263d344b21bSDan Carpenter unsigned int i; 126475758255SAlex Deucher 126575758255SAlex Deucher for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) { 126675758255SAlex Deucher ent = debugfs_create_file(debugfs_regs_names[i], 126775758255SAlex Deucher S_IFREG | S_IRUGO, root, 126875758255SAlex Deucher adev, debugfs_regs[i]); 1269d344b21bSDan Carpenter if (!i && !IS_ERR_OR_NULL(ent)) 127075758255SAlex Deucher i_size_write(ent->d_inode, adev->rmmio_size); 127175758255SAlex Deucher } 127275758255SAlex Deucher 127375758255SAlex Deucher return 0; 127475758255SAlex Deucher } 127575758255SAlex Deucher 127698d28ac2SNirmoy Das static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) 127775758255SAlex Deucher { 127898d28ac2SNirmoy Das struct amdgpu_device *adev = (struct amdgpu_device *)m->private; 127998d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 128075758255SAlex Deucher int r = 0, i; 128175758255SAlex Deucher 1282a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 12839eee152aSAlex Deucher if (r < 0) { 128498d28ac2SNirmoy Das pm_runtime_put_autosuspend(dev->dev); 1285a9ffe2a9SAlex Deucher return r; 12869eee152aSAlex Deucher } 1287a9ffe2a9SAlex Deucher 1288a28fda31SAndrey Grodzovsky /* Avoid accidently unparking the sched thread during GPU reset */ 1289d0fb18b5SAndrey Grodzovsky r = down_write_killable(&adev->reset_domain->sem); 12906049db43SDennis Li if (r) 12916049db43SDennis Li return r; 1292a28fda31SAndrey Grodzovsky 129375758255SAlex Deucher /* hold on the scheduler */ 129475758255SAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 129575758255SAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 129675758255SAlex Deucher 129775758255SAlex Deucher if (!ring || !ring->sched.thread) 129875758255SAlex Deucher continue; 129975758255SAlex Deucher kthread_park(ring->sched.thread); 130075758255SAlex Deucher } 130175758255SAlex Deucher 130275758255SAlex Deucher seq_printf(m, "run ib test:\n"); 130375758255SAlex Deucher r = amdgpu_ib_ring_tests(adev); 130475758255SAlex Deucher if (r) 130575758255SAlex Deucher seq_printf(m, "ib ring tests failed (%d).\n", r); 130675758255SAlex Deucher else 130775758255SAlex Deucher seq_printf(m, "ib ring tests passed.\n"); 130875758255SAlex Deucher 130975758255SAlex Deucher /* go on the scheduler */ 131075758255SAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 131175758255SAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 131275758255SAlex Deucher 131375758255SAlex Deucher if (!ring || !ring->sched.thread) 131475758255SAlex Deucher continue; 131575758255SAlex Deucher kthread_unpark(ring->sched.thread); 131675758255SAlex Deucher } 131775758255SAlex Deucher 1318d0fb18b5SAndrey Grodzovsky up_write(&adev->reset_domain->sem); 1319a28fda31SAndrey Grodzovsky 1320a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1321a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1322a9ffe2a9SAlex Deucher 132375758255SAlex Deucher return 0; 132475758255SAlex Deucher } 132575758255SAlex Deucher 132698d28ac2SNirmoy Das static int amdgpu_debugfs_evict_vram(void *data, u64 *val) 132775758255SAlex Deucher { 132898d28ac2SNirmoy Das struct amdgpu_device *adev = (struct amdgpu_device *)data; 132998d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 1330a9ffe2a9SAlex Deucher int r; 1331a9ffe2a9SAlex Deucher 1332a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 13339eee152aSAlex Deucher if (r < 0) { 133498d28ac2SNirmoy Das pm_runtime_put_autosuspend(dev->dev); 1335a9ffe2a9SAlex Deucher return r; 13369eee152aSAlex Deucher } 133775758255SAlex Deucher 133858144d28SNirmoy Das *val = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM); 1339a9ffe2a9SAlex Deucher 1340a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1341a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1342a9ffe2a9SAlex Deucher 134375758255SAlex Deucher return 0; 134475758255SAlex Deucher } 134575758255SAlex Deucher 134698d28ac2SNirmoy Das 134798d28ac2SNirmoy Das static int amdgpu_debugfs_evict_gtt(void *data, u64 *val) 134887e90c76SChristian König { 134998d28ac2SNirmoy Das struct amdgpu_device *adev = (struct amdgpu_device *)data; 135098d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 1351a9ffe2a9SAlex Deucher int r; 1352a9ffe2a9SAlex Deucher 1353a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 13549eee152aSAlex Deucher if (r < 0) { 135558144d28SNirmoy Das pm_runtime_put_autosuspend(dev->dev); 1356a9ffe2a9SAlex Deucher return r; 13579eee152aSAlex Deucher } 135887e90c76SChristian König 135958144d28SNirmoy Das *val = amdgpu_ttm_evict_resources(adev, TTM_PL_TT); 1360a9ffe2a9SAlex Deucher 1361a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1362a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1363a9ffe2a9SAlex Deucher 136487e90c76SChristian König return 0; 136587e90c76SChristian König } 136687e90c76SChristian König 1367e7c47231SAlex Deucher static int amdgpu_debugfs_benchmark(void *data, u64 val) 1368e7c47231SAlex Deucher { 1369e7c47231SAlex Deucher struct amdgpu_device *adev = (struct amdgpu_device *)data; 1370e7c47231SAlex Deucher struct drm_device *dev = adev_to_drm(adev); 1371e7c47231SAlex Deucher int r; 1372e7c47231SAlex Deucher 1373e7c47231SAlex Deucher r = pm_runtime_get_sync(dev->dev); 1374e7c47231SAlex Deucher if (r < 0) { 1375e7c47231SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1376e7c47231SAlex Deucher return r; 1377e7c47231SAlex Deucher } 1378e7c47231SAlex Deucher 1379e7c47231SAlex Deucher r = amdgpu_benchmark(adev, val); 1380e7c47231SAlex Deucher 1381e7c47231SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1382e7c47231SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1383e7c47231SAlex Deucher 1384e7c47231SAlex Deucher return r; 1385e7c47231SAlex Deucher } 138698d28ac2SNirmoy Das 138798d28ac2SNirmoy Das static int amdgpu_debugfs_vm_info_show(struct seq_file *m, void *unused) 1388ff72bc40SMihir Bhogilal Patel { 138998d28ac2SNirmoy Das struct amdgpu_device *adev = (struct amdgpu_device *)m->private; 139098d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 1391ff72bc40SMihir Bhogilal Patel struct drm_file *file; 1392ff72bc40SMihir Bhogilal Patel int r; 1393ff72bc40SMihir Bhogilal Patel 1394ff72bc40SMihir Bhogilal Patel r = mutex_lock_interruptible(&dev->filelist_mutex); 1395ff72bc40SMihir Bhogilal Patel if (r) 1396ff72bc40SMihir Bhogilal Patel return r; 1397ff72bc40SMihir Bhogilal Patel 1398ff72bc40SMihir Bhogilal Patel list_for_each_entry(file, &dev->filelist, lhead) { 1399ff72bc40SMihir Bhogilal Patel struct amdgpu_fpriv *fpriv = file->driver_priv; 1400ff72bc40SMihir Bhogilal Patel struct amdgpu_vm *vm = &fpriv->vm; 1401ff72bc40SMihir Bhogilal Patel 1402ff72bc40SMihir Bhogilal Patel seq_printf(m, "pid:%d\tProcess:%s ----------\n", 1403ff72bc40SMihir Bhogilal Patel vm->task_info.pid, vm->task_info.process_name); 1404391629bdSNirmoy Das r = amdgpu_bo_reserve(vm->root.bo, true); 1405ff72bc40SMihir Bhogilal Patel if (r) 1406ff72bc40SMihir Bhogilal Patel break; 1407ff72bc40SMihir Bhogilal Patel amdgpu_debugfs_vm_bo_info(vm, m); 1408391629bdSNirmoy Das amdgpu_bo_unreserve(vm->root.bo); 1409ff72bc40SMihir Bhogilal Patel } 1410ff72bc40SMihir Bhogilal Patel 1411ff72bc40SMihir Bhogilal Patel mutex_unlock(&dev->filelist_mutex); 1412ff72bc40SMihir Bhogilal Patel 1413ff72bc40SMihir Bhogilal Patel return r; 1414ff72bc40SMihir Bhogilal Patel } 1415ff72bc40SMihir Bhogilal Patel 141698d28ac2SNirmoy Das DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_test_ib); 141798d28ac2SNirmoy Das DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_vm_info); 141898d28ac2SNirmoy Das DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_vram_fops, amdgpu_debugfs_evict_vram, 141998d28ac2SNirmoy Das NULL, "%lld\n"); 142098d28ac2SNirmoy Das DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_gtt_fops, amdgpu_debugfs_evict_gtt, 142198d28ac2SNirmoy Das NULL, "%lld\n"); 1422e7c47231SAlex Deucher DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_benchmark_fops, NULL, amdgpu_debugfs_benchmark, 1423e7c47231SAlex Deucher "%lld\n"); 142475758255SAlex Deucher 14256698a3d0SJack Xiao static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring, 14266698a3d0SJack Xiao struct dma_fence **fences) 14276698a3d0SJack Xiao { 14286698a3d0SJack Xiao struct amdgpu_fence_driver *drv = &ring->fence_drv; 14296698a3d0SJack Xiao uint32_t sync_seq, last_seq; 14306698a3d0SJack Xiao 14316698a3d0SJack Xiao last_seq = atomic_read(&ring->fence_drv.last_seq); 14326698a3d0SJack Xiao sync_seq = ring->fence_drv.sync_seq; 14336698a3d0SJack Xiao 14346698a3d0SJack Xiao last_seq &= drv->num_fences_mask; 14356698a3d0SJack Xiao sync_seq &= drv->num_fences_mask; 14366698a3d0SJack Xiao 14376698a3d0SJack Xiao do { 14386698a3d0SJack Xiao struct dma_fence *fence, **ptr; 14396698a3d0SJack Xiao 14406698a3d0SJack Xiao ++last_seq; 14416698a3d0SJack Xiao last_seq &= drv->num_fences_mask; 14426698a3d0SJack Xiao ptr = &drv->fences[last_seq]; 14436698a3d0SJack Xiao 14446698a3d0SJack Xiao fence = rcu_dereference_protected(*ptr, 1); 14456698a3d0SJack Xiao RCU_INIT_POINTER(*ptr, NULL); 14466698a3d0SJack Xiao 14476698a3d0SJack Xiao if (!fence) 14486698a3d0SJack Xiao continue; 14496698a3d0SJack Xiao 14506698a3d0SJack Xiao fences[last_seq] = fence; 14516698a3d0SJack Xiao 14526698a3d0SJack Xiao } while (last_seq != sync_seq); 14536698a3d0SJack Xiao } 14546698a3d0SJack Xiao 14556698a3d0SJack Xiao static void amdgpu_ib_preempt_signal_fences(struct dma_fence **fences, 14566698a3d0SJack Xiao int length) 14576698a3d0SJack Xiao { 14586698a3d0SJack Xiao int i; 14596698a3d0SJack Xiao struct dma_fence *fence; 14606698a3d0SJack Xiao 14616698a3d0SJack Xiao for (i = 0; i < length; i++) { 14626698a3d0SJack Xiao fence = fences[i]; 14636698a3d0SJack Xiao if (!fence) 14646698a3d0SJack Xiao continue; 14656698a3d0SJack Xiao dma_fence_signal(fence); 14666698a3d0SJack Xiao dma_fence_put(fence); 14676698a3d0SJack Xiao } 14686698a3d0SJack Xiao } 14696698a3d0SJack Xiao 14706698a3d0SJack Xiao static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched) 14716698a3d0SJack Xiao { 14726698a3d0SJack Xiao struct drm_sched_job *s_job; 14736698a3d0SJack Xiao struct dma_fence *fence; 14746698a3d0SJack Xiao 14756698a3d0SJack Xiao spin_lock(&sched->job_list_lock); 14766efa4b46SLuben Tuikov list_for_each_entry(s_job, &sched->pending_list, list) { 14776698a3d0SJack Xiao fence = sched->ops->run_job(s_job); 14786698a3d0SJack Xiao dma_fence_put(fence); 14796698a3d0SJack Xiao } 14806698a3d0SJack Xiao spin_unlock(&sched->job_list_lock); 14816698a3d0SJack Xiao } 14826698a3d0SJack Xiao 148380f8fb91SJack Xiao static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring) 148480f8fb91SJack Xiao { 148580f8fb91SJack Xiao struct amdgpu_job *job; 14867bdb0899SJack Xiao struct drm_sched_job *s_job, *tmp; 148780f8fb91SJack Xiao uint32_t preempt_seq; 148880f8fb91SJack Xiao struct dma_fence *fence, **ptr; 148980f8fb91SJack Xiao struct amdgpu_fence_driver *drv = &ring->fence_drv; 149080f8fb91SJack Xiao struct drm_gpu_scheduler *sched = &ring->sched; 14917bdb0899SJack Xiao bool preempted = true; 149280f8fb91SJack Xiao 149380f8fb91SJack Xiao if (ring->funcs->type != AMDGPU_RING_TYPE_GFX) 149480f8fb91SJack Xiao return; 149580f8fb91SJack Xiao 149680f8fb91SJack Xiao preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2)); 14977bdb0899SJack Xiao if (preempt_seq <= atomic_read(&drv->last_seq)) { 14987bdb0899SJack Xiao preempted = false; 14997bdb0899SJack Xiao goto no_preempt; 15007bdb0899SJack Xiao } 150180f8fb91SJack Xiao 150280f8fb91SJack Xiao preempt_seq &= drv->num_fences_mask; 150380f8fb91SJack Xiao ptr = &drv->fences[preempt_seq]; 150480f8fb91SJack Xiao fence = rcu_dereference_protected(*ptr, 1); 150580f8fb91SJack Xiao 15067bdb0899SJack Xiao no_preempt: 150780f8fb91SJack Xiao spin_lock(&sched->job_list_lock); 15086efa4b46SLuben Tuikov list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) { 15097bdb0899SJack Xiao if (dma_fence_is_signaled(&s_job->s_fence->finished)) { 15107bdb0899SJack Xiao /* remove job from ring_mirror_list */ 15118935ff00SLuben Tuikov list_del_init(&s_job->list); 15127bdb0899SJack Xiao sched->ops->free_job(s_job); 15137bdb0899SJack Xiao continue; 15147bdb0899SJack Xiao } 151580f8fb91SJack Xiao job = to_amdgpu_job(s_job); 1516c530b02fSJack Zhang if (preempted && (&job->hw_fence) == fence) 151780f8fb91SJack Xiao /* mark the job as preempted */ 151880f8fb91SJack Xiao job->preemption_status |= AMDGPU_IB_PREEMPTED; 151980f8fb91SJack Xiao } 152080f8fb91SJack Xiao spin_unlock(&sched->job_list_lock); 152180f8fb91SJack Xiao } 152280f8fb91SJack Xiao 15236698a3d0SJack Xiao static int amdgpu_debugfs_ib_preempt(void *data, u64 val) 15246698a3d0SJack Xiao { 15256698a3d0SJack Xiao int r, resched, length; 15266698a3d0SJack Xiao struct amdgpu_ring *ring; 15276698a3d0SJack Xiao struct dma_fence **fences = NULL; 15286698a3d0SJack Xiao struct amdgpu_device *adev = (struct amdgpu_device *)data; 15296698a3d0SJack Xiao 15306698a3d0SJack Xiao if (val >= AMDGPU_MAX_RINGS) 15316698a3d0SJack Xiao return -EINVAL; 15326698a3d0SJack Xiao 15336698a3d0SJack Xiao ring = adev->rings[val]; 15346698a3d0SJack Xiao 15356698a3d0SJack Xiao if (!ring || !ring->funcs->preempt_ib || !ring->sched.thread) 15366698a3d0SJack Xiao return -EINVAL; 15376698a3d0SJack Xiao 15386698a3d0SJack Xiao /* the last preemption failed */ 15396698a3d0SJack Xiao if (ring->trail_seq != le32_to_cpu(*ring->trail_fence_cpu_addr)) 15406698a3d0SJack Xiao return -EBUSY; 15416698a3d0SJack Xiao 15426698a3d0SJack Xiao length = ring->fence_drv.num_fences_mask + 1; 15436698a3d0SJack Xiao fences = kcalloc(length, sizeof(void *), GFP_KERNEL); 15446698a3d0SJack Xiao if (!fences) 15456698a3d0SJack Xiao return -ENOMEM; 15466698a3d0SJack Xiao 1547a28fda31SAndrey Grodzovsky /* Avoid accidently unparking the sched thread during GPU reset */ 1548d0fb18b5SAndrey Grodzovsky r = down_read_killable(&adev->reset_domain->sem); 15496049db43SDennis Li if (r) 15506049db43SDennis Li goto pro_end; 1551a28fda31SAndrey Grodzovsky 15526698a3d0SJack Xiao /* stop the scheduler */ 15536698a3d0SJack Xiao kthread_park(ring->sched.thread); 15546698a3d0SJack Xiao 15556698a3d0SJack Xiao resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); 15566698a3d0SJack Xiao 15576698a3d0SJack Xiao /* preempt the IB */ 15586698a3d0SJack Xiao r = amdgpu_ring_preempt_ib(ring); 15596698a3d0SJack Xiao if (r) { 15606698a3d0SJack Xiao DRM_WARN("failed to preempt ring %d\n", ring->idx); 15616698a3d0SJack Xiao goto failure; 15626698a3d0SJack Xiao } 15636698a3d0SJack Xiao 15646698a3d0SJack Xiao amdgpu_fence_process(ring); 15656698a3d0SJack Xiao 15666698a3d0SJack Xiao if (atomic_read(&ring->fence_drv.last_seq) != 15676698a3d0SJack Xiao ring->fence_drv.sync_seq) { 15686698a3d0SJack Xiao DRM_INFO("ring %d was preempted\n", ring->idx); 15696698a3d0SJack Xiao 157080f8fb91SJack Xiao amdgpu_ib_preempt_mark_partial_job(ring); 157180f8fb91SJack Xiao 15726698a3d0SJack Xiao /* swap out the old fences */ 15736698a3d0SJack Xiao amdgpu_ib_preempt_fences_swap(ring, fences); 15746698a3d0SJack Xiao 15756698a3d0SJack Xiao amdgpu_fence_driver_force_completion(ring); 15766698a3d0SJack Xiao 15776698a3d0SJack Xiao /* resubmit unfinished jobs */ 15786698a3d0SJack Xiao amdgpu_ib_preempt_job_recovery(&ring->sched); 15796698a3d0SJack Xiao 15806698a3d0SJack Xiao /* wait for jobs finished */ 15816698a3d0SJack Xiao amdgpu_fence_wait_empty(ring); 15826698a3d0SJack Xiao 15836698a3d0SJack Xiao /* signal the old fences */ 15846698a3d0SJack Xiao amdgpu_ib_preempt_signal_fences(fences, length); 15856698a3d0SJack Xiao } 15866698a3d0SJack Xiao 15876698a3d0SJack Xiao failure: 15886698a3d0SJack Xiao /* restart the scheduler */ 15896698a3d0SJack Xiao kthread_unpark(ring->sched.thread); 15906698a3d0SJack Xiao 1591d0fb18b5SAndrey Grodzovsky up_read(&adev->reset_domain->sem); 1592a28fda31SAndrey Grodzovsky 15936698a3d0SJack Xiao ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); 15946698a3d0SJack Xiao 15956049db43SDennis Li pro_end: 15966698a3d0SJack Xiao kfree(fences); 15976698a3d0SJack Xiao 15986049db43SDennis Li return r; 15996698a3d0SJack Xiao } 16006698a3d0SJack Xiao 16010cf64555SChengming Gui static int amdgpu_debugfs_sclk_set(void *data, u64 val) 16020cf64555SChengming Gui { 16030cf64555SChengming Gui int ret = 0; 16040cf64555SChengming Gui uint32_t max_freq, min_freq; 16050cf64555SChengming Gui struct amdgpu_device *adev = (struct amdgpu_device *)data; 16060cf64555SChengming Gui 16070cf64555SChengming Gui if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) 16080cf64555SChengming Gui return -EINVAL; 16090cf64555SChengming Gui 16104a580877SLuben Tuikov ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); 16119eee152aSAlex Deucher if (ret < 0) { 16124a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 16130cf64555SChengming Gui return ret; 16149eee152aSAlex Deucher } 16150cf64555SChengming Gui 1616bc143d8bSEvan Quan ret = amdgpu_dpm_get_dpm_freq_range(adev, PP_SCLK, &min_freq, &max_freq); 1617bc143d8bSEvan Quan if (ret == -EOPNOTSUPP) { 1618bc143d8bSEvan Quan ret = 0; 1619bc143d8bSEvan Quan goto out; 1620bc143d8bSEvan Quan } 1621bc143d8bSEvan Quan if (ret || val > max_freq || val < min_freq) { 1622bc143d8bSEvan Quan ret = -EINVAL; 1623bc143d8bSEvan Quan goto out; 16240cf64555SChengming Gui } 16250cf64555SChengming Gui 1626bc143d8bSEvan Quan ret = amdgpu_dpm_set_soft_freq_range(adev, PP_SCLK, (uint32_t)val, (uint32_t)val); 1627bc143d8bSEvan Quan if (ret) 1628bc143d8bSEvan Quan ret = -EINVAL; 1629bc143d8bSEvan Quan 1630bc143d8bSEvan Quan out: 16314a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 16324a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 16330cf64555SChengming Gui 1634bc143d8bSEvan Quan return ret; 16350cf64555SChengming Gui } 16360cf64555SChengming Gui 16377271a5c2SYang Li DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL, 16386698a3d0SJack Xiao amdgpu_debugfs_ib_preempt, "%llu\n"); 16396698a3d0SJack Xiao 16407271a5c2SYang Li DEFINE_DEBUGFS_ATTRIBUTE(fops_sclk_set, NULL, 16410cf64555SChengming Gui amdgpu_debugfs_sclk_set, "%llu\n"); 16420cf64555SChengming Gui 1643*5ce5a584SSomalapuram Amaranath static ssize_t amdgpu_reset_dump_register_list_read(struct file *f, 1644*5ce5a584SSomalapuram Amaranath char __user *buf, size_t size, loff_t *pos) 1645*5ce5a584SSomalapuram Amaranath { 1646*5ce5a584SSomalapuram Amaranath struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; 1647*5ce5a584SSomalapuram Amaranath char reg_offset[12]; 1648*5ce5a584SSomalapuram Amaranath int i, ret, len = 0; 1649*5ce5a584SSomalapuram Amaranath 1650*5ce5a584SSomalapuram Amaranath if (*pos) 1651*5ce5a584SSomalapuram Amaranath return 0; 1652*5ce5a584SSomalapuram Amaranath 1653*5ce5a584SSomalapuram Amaranath memset(reg_offset, 0, 12); 165438a15ad9SDave Airlie ret = down_read_killable(&adev->reset_domain->sem); 1655*5ce5a584SSomalapuram Amaranath if (ret) 1656*5ce5a584SSomalapuram Amaranath return ret; 1657*5ce5a584SSomalapuram Amaranath 1658*5ce5a584SSomalapuram Amaranath for (i = 0; i < adev->num_regs; i++) { 1659*5ce5a584SSomalapuram Amaranath sprintf(reg_offset, "0x%x\n", adev->reset_dump_reg_list[i]); 166038a15ad9SDave Airlie up_read(&adev->reset_domain->sem); 1661*5ce5a584SSomalapuram Amaranath if (copy_to_user(buf + len, reg_offset, strlen(reg_offset))) 1662*5ce5a584SSomalapuram Amaranath return -EFAULT; 1663*5ce5a584SSomalapuram Amaranath 1664*5ce5a584SSomalapuram Amaranath len += strlen(reg_offset); 166538a15ad9SDave Airlie ret = down_read_killable(&adev->reset_domain->sem); 1666*5ce5a584SSomalapuram Amaranath if (ret) 1667*5ce5a584SSomalapuram Amaranath return ret; 1668*5ce5a584SSomalapuram Amaranath } 1669*5ce5a584SSomalapuram Amaranath 167038a15ad9SDave Airlie up_read(&adev->reset_domain->sem); 1671*5ce5a584SSomalapuram Amaranath *pos += len; 1672*5ce5a584SSomalapuram Amaranath 1673*5ce5a584SSomalapuram Amaranath return len; 1674*5ce5a584SSomalapuram Amaranath } 1675*5ce5a584SSomalapuram Amaranath 1676*5ce5a584SSomalapuram Amaranath static ssize_t amdgpu_reset_dump_register_list_write(struct file *f, 1677*5ce5a584SSomalapuram Amaranath const char __user *buf, size_t size, loff_t *pos) 1678*5ce5a584SSomalapuram Amaranath { 1679*5ce5a584SSomalapuram Amaranath struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; 1680*5ce5a584SSomalapuram Amaranath char reg_offset[11]; 1681*5ce5a584SSomalapuram Amaranath uint32_t *tmp; 1682*5ce5a584SSomalapuram Amaranath int ret, i = 0, len = 0; 1683*5ce5a584SSomalapuram Amaranath 1684*5ce5a584SSomalapuram Amaranath do { 1685*5ce5a584SSomalapuram Amaranath memset(reg_offset, 0, 11); 1686*5ce5a584SSomalapuram Amaranath if (copy_from_user(reg_offset, buf + len, 1687*5ce5a584SSomalapuram Amaranath min(10, ((int)size-len)))) { 1688*5ce5a584SSomalapuram Amaranath ret = -EFAULT; 1689*5ce5a584SSomalapuram Amaranath goto error_free; 1690*5ce5a584SSomalapuram Amaranath } 1691*5ce5a584SSomalapuram Amaranath 1692*5ce5a584SSomalapuram Amaranath tmp = krealloc_array(tmp, i + 1, sizeof(uint32_t), GFP_KERNEL); 1693*5ce5a584SSomalapuram Amaranath if (sscanf(reg_offset, "%X %n", &tmp[i], &ret) != 1) { 1694*5ce5a584SSomalapuram Amaranath ret = -EINVAL; 1695*5ce5a584SSomalapuram Amaranath goto error_free; 1696*5ce5a584SSomalapuram Amaranath } 1697*5ce5a584SSomalapuram Amaranath 1698*5ce5a584SSomalapuram Amaranath len += ret; 1699*5ce5a584SSomalapuram Amaranath i++; 1700*5ce5a584SSomalapuram Amaranath } while (len < size); 1701*5ce5a584SSomalapuram Amaranath 170238a15ad9SDave Airlie ret = down_write_killable(&adev->reset_domain->sem); 1703*5ce5a584SSomalapuram Amaranath if (ret) 1704*5ce5a584SSomalapuram Amaranath goto error_free; 1705*5ce5a584SSomalapuram Amaranath 1706*5ce5a584SSomalapuram Amaranath swap(adev->reset_dump_reg_list, tmp); 1707*5ce5a584SSomalapuram Amaranath adev->num_regs = i; 170838a15ad9SDave Airlie up_write(&adev->reset_domain->sem); 1709*5ce5a584SSomalapuram Amaranath ret = size; 1710*5ce5a584SSomalapuram Amaranath 1711*5ce5a584SSomalapuram Amaranath error_free: 1712*5ce5a584SSomalapuram Amaranath kfree(tmp); 1713*5ce5a584SSomalapuram Amaranath return ret; 1714*5ce5a584SSomalapuram Amaranath } 1715*5ce5a584SSomalapuram Amaranath 1716*5ce5a584SSomalapuram Amaranath static const struct file_operations amdgpu_reset_dump_register_list = { 1717*5ce5a584SSomalapuram Amaranath .owner = THIS_MODULE, 1718*5ce5a584SSomalapuram Amaranath .read = amdgpu_reset_dump_register_list_read, 1719*5ce5a584SSomalapuram Amaranath .write = amdgpu_reset_dump_register_list_write, 1720*5ce5a584SSomalapuram Amaranath .llseek = default_llseek 1721*5ce5a584SSomalapuram Amaranath }; 1722*5ce5a584SSomalapuram Amaranath 172375758255SAlex Deucher int amdgpu_debugfs_init(struct amdgpu_device *adev) 172475758255SAlex Deucher { 172598d28ac2SNirmoy Das struct dentry *root = adev_to_drm(adev)->primary->debugfs_root; 172688293c03SNirmoy Das struct dentry *ent; 1727fd23cfccSAlex Deucher int r, i; 1728c5820361SAlex Deucher 17295b9581dfSNirmoy Das if (!debugfs_initialized()) 17305b9581dfSNirmoy Das return 0; 17315b9581dfSNirmoy Das 17326ff7fddbSLang Yu debugfs_create_x32("amdgpu_smu_debug", 0600, root, 17337e31a858SEvan Quan &adev->pm.smu_debug_mask); 17346ff7fddbSLang Yu 173598d28ac2SNirmoy Das ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev, 173644b582b3SGeert Uytterhoeven &fops_ib_preempt); 173759715cffSNirmoy Das if (IS_ERR(ent)) { 17386698a3d0SJack Xiao DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); 173959715cffSNirmoy Das return PTR_ERR(ent); 17406698a3d0SJack Xiao } 17416698a3d0SJack Xiao 174298d28ac2SNirmoy Das ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev, 17430cf64555SChengming Gui &fops_sclk_set); 174459715cffSNirmoy Das if (IS_ERR(ent)) { 17450cf64555SChengming Gui DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); 174659715cffSNirmoy Das return PTR_ERR(ent); 17470cf64555SChengming Gui } 17480cf64555SChengming Gui 1749c5820361SAlex Deucher /* Register debugfs entries for amdgpu_ttm */ 175098d28ac2SNirmoy Das amdgpu_ttm_debugfs_init(adev); 1751373720f7SNirmoy Das amdgpu_debugfs_pm_init(adev); 175298d28ac2SNirmoy Das amdgpu_debugfs_sa_init(adev); 175398d28ac2SNirmoy Das amdgpu_debugfs_fence_init(adev); 175498d28ac2SNirmoy Das amdgpu_debugfs_gem_init(adev); 17553f5cea67SAlex Deucher 1756f9d64e6cSAlex Deucher r = amdgpu_debugfs_regs_init(adev); 1757f9d64e6cSAlex Deucher if (r) 1758f9d64e6cSAlex Deucher DRM_ERROR("registering register debugfs failed (%d).\n", r); 1759f9d64e6cSAlex Deucher 176098d28ac2SNirmoy Das amdgpu_debugfs_firmware_init(adev); 1761cd9e29e7SAlex Deucher 1762d090e7dbSAlex Deucher #if defined(CONFIG_DRM_AMD_DC) 1763afd3a359SNirmoy Das if (amdgpu_device_has_dc_support(adev)) 1764afd3a359SNirmoy Das dtn_debugfs_init(adev); 1765d090e7dbSAlex Deucher #endif 1766d090e7dbSAlex Deucher 1767fd23cfccSAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { 1768fd23cfccSAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 1769fd23cfccSAlex Deucher 1770fd23cfccSAlex Deucher if (!ring) 1771fd23cfccSAlex Deucher continue; 1772fd23cfccSAlex Deucher 177362d266b2SNirmoy Das amdgpu_debugfs_ring_init(adev, ring); 1774fd23cfccSAlex Deucher } 1775fd23cfccSAlex Deucher 1776204eaac6STao Zhou amdgpu_ras_debugfs_create_all(adev); 1777a4322e18SWenhui Sheng amdgpu_rap_debugfs_init(adev); 1778ecaafb7bSJinzhou Su amdgpu_securedisplay_debugfs_init(adev); 177919ae3330SJohn Clements amdgpu_fw_attestation_debugfs_init(adev); 178019ae3330SJohn Clements 178198d28ac2SNirmoy Das debugfs_create_file("amdgpu_evict_vram", 0444, root, adev, 178298d28ac2SNirmoy Das &amdgpu_evict_vram_fops); 178398d28ac2SNirmoy Das debugfs_create_file("amdgpu_evict_gtt", 0444, root, adev, 178498d28ac2SNirmoy Das &amdgpu_evict_gtt_fops); 178598d28ac2SNirmoy Das debugfs_create_file("amdgpu_test_ib", 0444, root, adev, 178698d28ac2SNirmoy Das &amdgpu_debugfs_test_ib_fops); 178798d28ac2SNirmoy Das debugfs_create_file("amdgpu_vm_info", 0444, root, adev, 178898d28ac2SNirmoy Das &amdgpu_debugfs_vm_info_fops); 1789e7c47231SAlex Deucher debugfs_create_file("amdgpu_benchmark", 0200, root, adev, 1790e7c47231SAlex Deucher &amdgpu_benchmark_fops); 1791*5ce5a584SSomalapuram Amaranath debugfs_create_file("amdgpu_reset_dump_register_list", 0644, root, adev, 1792*5ce5a584SSomalapuram Amaranath &amdgpu_reset_dump_register_list); 179398d28ac2SNirmoy Das 179498d28ac2SNirmoy Das adev->debugfs_vbios_blob.data = adev->bios; 179598d28ac2SNirmoy Das adev->debugfs_vbios_blob.size = adev->bios_size; 179698d28ac2SNirmoy Das debugfs_create_blob("amdgpu_vbios", 0444, root, 179798d28ac2SNirmoy Das &adev->debugfs_vbios_blob); 179898d28ac2SNirmoy Das 179981d1bf01SAlex Deucher adev->debugfs_discovery_blob.data = adev->mman.discovery_bin; 180081d1bf01SAlex Deucher adev->debugfs_discovery_blob.size = adev->mman.discovery_tmr_size; 180181d1bf01SAlex Deucher debugfs_create_blob("amdgpu_discovery", 0444, root, 180281d1bf01SAlex Deucher &adev->debugfs_discovery_blob); 180381d1bf01SAlex Deucher 180498d28ac2SNirmoy Das return 0; 180575758255SAlex Deucher } 180675758255SAlex Deucher 180775758255SAlex Deucher #else 180875758255SAlex Deucher int amdgpu_debugfs_init(struct amdgpu_device *adev) 180975758255SAlex Deucher { 181075758255SAlex Deucher return 0; 181175758255SAlex Deucher } 181275758255SAlex Deucher int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) 181375758255SAlex Deucher { 181475758255SAlex Deucher return 0; 181575758255SAlex Deucher } 181675758255SAlex Deucher #endif 1817