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" 41e50d9ba0SCandice Li #include "amdgpu_psp_ta.h" 42d0fb18b5SAndrey Grodzovsky 4375758255SAlex Deucher #if defined(CONFIG_DEBUG_FS) 4475758255SAlex Deucher 457e4237dbSTom St Denis /** 467e4237dbSTom St Denis * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes 477e4237dbSTom St Denis * 487e4237dbSTom St Denis * @read: True if reading 497e4237dbSTom St Denis * @f: open file handle 507e4237dbSTom St Denis * @buf: User buffer to write/read to 517e4237dbSTom St Denis * @size: Number of bytes to write/read 527e4237dbSTom St Denis * @pos: Offset to seek to 537e4237dbSTom St Denis * 547e4237dbSTom St Denis * This debugfs entry has special meaning on the offset being sought. 557e4237dbSTom St Denis * Various bits have different meanings: 567e4237dbSTom St Denis * 577e4237dbSTom St Denis * Bit 62: Indicates a GRBM bank switch is needed 587e4237dbSTom St Denis * Bit 61: Indicates a SRBM bank switch is needed (implies bit 62 is 597e4237dbSTom St Denis * zero) 607e4237dbSTom St Denis * Bits 24..33: The SE or ME selector if needed 617e4237dbSTom St Denis * Bits 34..43: The SH (or SA) or PIPE selector if needed 627e4237dbSTom St Denis * Bits 44..53: The INSTANCE (or CU/WGP) or QUEUE selector if needed 637e4237dbSTom St Denis * 647e4237dbSTom St Denis * Bit 23: Indicates that the PM power gating lock should be held 657e4237dbSTom St Denis * This is necessary to read registers that might be 667e4237dbSTom St Denis * unreliable during a power gating transistion. 677e4237dbSTom St Denis * 687e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 697e4237dbSTom St Denis * allows reading multiple registers in a single call and having 707e4237dbSTom St Denis * the returned size reflect that. 717e4237dbSTom St Denis */ 72f7a9ee81SAndrey Grodzovsky static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, 73f7a9ee81SAndrey Grodzovsky char __user *buf, size_t size, loff_t *pos) 7475758255SAlex Deucher { 7575758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 7675758255SAlex Deucher ssize_t result = 0; 7775758255SAlex Deucher int r; 78f7a9ee81SAndrey Grodzovsky bool pm_pg_lock, use_bank, use_ring; 798fa76350SSrinivasan Shanmugam unsigned int instance_bank, sh_bank, se_bank, me, pipe, queue, vmid; 8075758255SAlex Deucher 81f7a9ee81SAndrey Grodzovsky pm_pg_lock = use_bank = use_ring = false; 820fa4246eSTom St Denis instance_bank = sh_bank = se_bank = me = pipe = queue = vmid = 0; 83f7a9ee81SAndrey Grodzovsky 84f7a9ee81SAndrey Grodzovsky if (size & 0x3 || *pos & 0x3 || 85f7a9ee81SAndrey Grodzovsky ((*pos & (1ULL << 62)) && (*pos & (1ULL << 61)))) 8675758255SAlex Deucher return -EINVAL; 8775758255SAlex Deucher 8875758255SAlex Deucher /* are we reading registers for which a PG lock is necessary? */ 8975758255SAlex Deucher pm_pg_lock = (*pos >> 23) & 1; 9075758255SAlex Deucher 9175758255SAlex Deucher if (*pos & (1ULL << 62)) { 9275758255SAlex Deucher se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24; 9375758255SAlex Deucher sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34; 9475758255SAlex Deucher instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44; 9575758255SAlex Deucher 9675758255SAlex Deucher if (se_bank == 0x3FF) 9775758255SAlex Deucher se_bank = 0xFFFFFFFF; 9875758255SAlex Deucher if (sh_bank == 0x3FF) 9975758255SAlex Deucher sh_bank = 0xFFFFFFFF; 10075758255SAlex Deucher if (instance_bank == 0x3FF) 10175758255SAlex Deucher instance_bank = 0xFFFFFFFF; 102c5b2bd5dSzhengbin use_bank = true; 103f7a9ee81SAndrey Grodzovsky } else if (*pos & (1ULL << 61)) { 104f7a9ee81SAndrey Grodzovsky 105f7a9ee81SAndrey Grodzovsky me = (*pos & GENMASK_ULL(33, 24)) >> 24; 106f7a9ee81SAndrey Grodzovsky pipe = (*pos & GENMASK_ULL(43, 34)) >> 34; 107f7a9ee81SAndrey Grodzovsky queue = (*pos & GENMASK_ULL(53, 44)) >> 44; 10888891430STom St Denis vmid = (*pos & GENMASK_ULL(58, 54)) >> 54; 109f7a9ee81SAndrey Grodzovsky 110c5b2bd5dSzhengbin use_ring = true; 11175758255SAlex Deucher } else { 112c5b2bd5dSzhengbin use_bank = use_ring = false; 11375758255SAlex Deucher } 11475758255SAlex Deucher 11575758255SAlex Deucher *pos &= (1UL << 22) - 1; 11675758255SAlex Deucher 1174a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 1189eee152aSAlex Deucher if (r < 0) { 1194a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 120a9ffe2a9SAlex Deucher return r; 1219eee152aSAlex Deucher } 122a9ffe2a9SAlex Deucher 12395a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 1249eee152aSAlex Deucher if (r < 0) { 1254a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12695a2f917SYintian Tao return r; 1279eee152aSAlex Deucher } 12895a2f917SYintian Tao 12975758255SAlex Deucher if (use_bank) { 13075758255SAlex Deucher if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || 131a9ffe2a9SAlex Deucher (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) { 1324a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 1334a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 13495a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 13575758255SAlex Deucher return -EINVAL; 136a9ffe2a9SAlex Deucher } 13775758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 13875758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, se_bank, 139d51ac6d0SLe Ma sh_bank, instance_bank, 0); 140f7a9ee81SAndrey Grodzovsky } else if (use_ring) { 141f7a9ee81SAndrey Grodzovsky mutex_lock(&adev->srbm_mutex); 142553f973aSTom St Denis amdgpu_gfx_select_me_pipe_q(adev, me, pipe, queue, vmid, 0); 14375758255SAlex Deucher } 14475758255SAlex Deucher 14575758255SAlex Deucher if (pm_pg_lock) 14675758255SAlex Deucher mutex_lock(&adev->pm.mutex); 14775758255SAlex Deucher 14875758255SAlex Deucher while (size) { 14975758255SAlex Deucher uint32_t value; 15075758255SAlex Deucher 151f7a9ee81SAndrey Grodzovsky if (read) { 15275758255SAlex Deucher value = RREG32(*pos >> 2); 15375758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 154f7a9ee81SAndrey Grodzovsky } else { 155f7a9ee81SAndrey Grodzovsky r = get_user(value, (uint32_t *)buf); 156f7a9ee81SAndrey Grodzovsky if (!r) 1578ed49dd1SVictor Lu amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value, 0); 158f7a9ee81SAndrey Grodzovsky } 15975758255SAlex Deucher if (r) { 16075758255SAlex Deucher result = r; 16175758255SAlex Deucher goto end; 16275758255SAlex Deucher } 16375758255SAlex Deucher 16475758255SAlex Deucher result += 4; 16575758255SAlex Deucher buf += 4; 16675758255SAlex Deucher *pos += 4; 16775758255SAlex Deucher size -= 4; 16875758255SAlex Deucher } 16975758255SAlex Deucher 17075758255SAlex Deucher end: 17175758255SAlex Deucher if (use_bank) { 172d51ac6d0SLe Ma amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0); 17375758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 174f7a9ee81SAndrey Grodzovsky } else if (use_ring) { 175553f973aSTom St Denis amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, 0); 176f7a9ee81SAndrey Grodzovsky mutex_unlock(&adev->srbm_mutex); 17775758255SAlex Deucher } 17875758255SAlex Deucher 17975758255SAlex Deucher if (pm_pg_lock) 18075758255SAlex Deucher mutex_unlock(&adev->pm.mutex); 18175758255SAlex Deucher 1824a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 1834a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 184a9ffe2a9SAlex Deucher 18595a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 18675758255SAlex Deucher return result; 18775758255SAlex Deucher } 18875758255SAlex Deucher 18920ed491bSLee Jones /* 1907e4237dbSTom St Denis * amdgpu_debugfs_regs_read - Callback for reading MMIO registers 1917e4237dbSTom St Denis */ 192f7a9ee81SAndrey Grodzovsky static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, 193f7a9ee81SAndrey Grodzovsky size_t size, loff_t *pos) 194f7a9ee81SAndrey Grodzovsky { 195f7a9ee81SAndrey Grodzovsky return amdgpu_debugfs_process_reg_op(true, f, buf, size, pos); 196f7a9ee81SAndrey Grodzovsky } 197f7a9ee81SAndrey Grodzovsky 19820ed491bSLee Jones /* 1997e4237dbSTom St Denis * amdgpu_debugfs_regs_write - Callback for writing MMIO registers 2007e4237dbSTom St Denis */ 20175758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, 20275758255SAlex Deucher size_t size, loff_t *pos) 20375758255SAlex Deucher { 204f7a9ee81SAndrey Grodzovsky return amdgpu_debugfs_process_reg_op(false, f, (char __user *)buf, size, pos); 20575758255SAlex Deucher } 20675758255SAlex Deucher 20737df9560STom St Denis static int amdgpu_debugfs_regs2_open(struct inode *inode, struct file *file) 20837df9560STom St Denis { 20937df9560STom St Denis struct amdgpu_debugfs_regs2_data *rd; 21037df9560STom St Denis 2118fa76350SSrinivasan Shanmugam rd = kzalloc(sizeof(*rd), GFP_KERNEL); 21237df9560STom St Denis if (!rd) 21337df9560STom St Denis return -ENOMEM; 21437df9560STom St Denis rd->adev = file_inode(file)->i_private; 21537df9560STom St Denis file->private_data = rd; 21637df9560STom St Denis mutex_init(&rd->lock); 21737df9560STom St Denis 21837df9560STom St Denis return 0; 21937df9560STom St Denis } 22037df9560STom St Denis 22137df9560STom St Denis static int amdgpu_debugfs_regs2_release(struct inode *inode, struct file *file) 22237df9560STom St Denis { 22337df9560STom St Denis struct amdgpu_debugfs_regs2_data *rd = file->private_data; 2248fa76350SSrinivasan Shanmugam 22537df9560STom St Denis mutex_destroy(&rd->lock); 22637df9560STom St Denis kfree(file->private_data); 22737df9560STom St Denis return 0; 22837df9560STom St Denis } 22937df9560STom St Denis 23037df9560STom St Denis static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 offset, size_t size, int write_en) 23137df9560STom St Denis { 23237df9560STom St Denis struct amdgpu_debugfs_regs2_data *rd = f->private_data; 23337df9560STom St Denis struct amdgpu_device *adev = rd->adev; 23437df9560STom St Denis ssize_t result = 0; 23537df9560STom St Denis int r; 23637df9560STom St Denis uint32_t value; 23737df9560STom St Denis 23837df9560STom St Denis if (size & 0x3 || offset & 0x3) 23937df9560STom St Denis return -EINVAL; 24037df9560STom St Denis 24137df9560STom St Denis r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 24237df9560STom St Denis if (r < 0) { 24337df9560STom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 24437df9560STom St Denis return r; 24537df9560STom St Denis } 24637df9560STom St Denis 24737df9560STom St Denis r = amdgpu_virt_enable_access_debugfs(adev); 24837df9560STom St Denis if (r < 0) { 24937df9560STom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 25037df9560STom St Denis return r; 25137df9560STom St Denis } 25237df9560STom St Denis 25337df9560STom St Denis mutex_lock(&rd->lock); 25437df9560STom St Denis 25537df9560STom St Denis if (rd->id.use_grbm) { 25637df9560STom St Denis if ((rd->id.grbm.sh != 0xFFFFFFFF && rd->id.grbm.sh >= adev->gfx.config.max_sh_per_se) || 25737df9560STom St Denis (rd->id.grbm.se != 0xFFFFFFFF && rd->id.grbm.se >= adev->gfx.config.max_shader_engines)) { 25837df9560STom St Denis pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 25937df9560STom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 26037df9560STom St Denis amdgpu_virt_disable_access_debugfs(adev); 26137df9560STom St Denis mutex_unlock(&rd->lock); 26237df9560STom St Denis return -EINVAL; 26337df9560STom St Denis } 26437df9560STom St Denis mutex_lock(&adev->grbm_idx_mutex); 26537df9560STom St Denis amdgpu_gfx_select_se_sh(adev, rd->id.grbm.se, 26637df9560STom St Denis rd->id.grbm.sh, 267553f973aSTom St Denis rd->id.grbm.instance, rd->id.xcc_id); 26837df9560STom St Denis } 26937df9560STom St Denis 27037df9560STom St Denis if (rd->id.use_srbm) { 27137df9560STom St Denis mutex_lock(&adev->srbm_mutex); 27237df9560STom St Denis amdgpu_gfx_select_me_pipe_q(adev, rd->id.srbm.me, rd->id.srbm.pipe, 273553f973aSTom St Denis rd->id.srbm.queue, rd->id.srbm.vmid, rd->id.xcc_id); 27437df9560STom St Denis } 27537df9560STom St Denis 27637df9560STom St Denis if (rd->id.pg_lock) 27737df9560STom St Denis mutex_lock(&adev->pm.mutex); 27837df9560STom St Denis 27937df9560STom St Denis while (size) { 28037df9560STom St Denis if (!write_en) { 28137df9560STom St Denis value = RREG32(offset >> 2); 28237df9560STom St Denis r = put_user(value, (uint32_t *)buf); 28337df9560STom St Denis } else { 28437df9560STom St Denis r = get_user(value, (uint32_t *)buf); 28537df9560STom St Denis if (!r) 2868ed49dd1SVictor Lu amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, value, rd->id.xcc_id); 28737df9560STom St Denis } 28837df9560STom St Denis if (r) { 28937df9560STom St Denis result = r; 29037df9560STom St Denis goto end; 29137df9560STom St Denis } 29237df9560STom St Denis offset += 4; 29337df9560STom St Denis size -= 4; 29437df9560STom St Denis result += 4; 29537df9560STom St Denis buf += 4; 29637df9560STom St Denis } 29737df9560STom St Denis end: 29837df9560STom St Denis if (rd->id.use_grbm) { 299553f973aSTom St Denis amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, rd->id.xcc_id); 30037df9560STom St Denis mutex_unlock(&adev->grbm_idx_mutex); 30137df9560STom St Denis } 30237df9560STom St Denis 30337df9560STom St Denis if (rd->id.use_srbm) { 304553f973aSTom St Denis amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, rd->id.xcc_id); 30537df9560STom St Denis mutex_unlock(&adev->srbm_mutex); 30637df9560STom St Denis } 30737df9560STom St Denis 30837df9560STom St Denis if (rd->id.pg_lock) 30937df9560STom St Denis mutex_unlock(&adev->pm.mutex); 31037df9560STom St Denis 31137df9560STom St Denis mutex_unlock(&rd->lock); 31237df9560STom St Denis 31337df9560STom St Denis pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 31437df9560STom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 31537df9560STom St Denis 31637df9560STom St Denis amdgpu_virt_disable_access_debugfs(adev); 31737df9560STom St Denis return result; 31837df9560STom St Denis } 31937df9560STom St Denis 32037df9560STom St Denis static long amdgpu_debugfs_regs2_ioctl(struct file *f, unsigned int cmd, unsigned long data) 32137df9560STom St Denis { 32237df9560STom St Denis struct amdgpu_debugfs_regs2_data *rd = f->private_data; 323553f973aSTom St Denis struct amdgpu_debugfs_regs2_iocdata v1_data; 32437df9560STom St Denis int r; 32537df9560STom St Denis 32637df9560STom St Denis mutex_lock(&rd->lock); 327553f973aSTom St Denis 328553f973aSTom St Denis switch (cmd) { 329553f973aSTom St Denis case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE_V2: 330553f973aSTom St Denis r = copy_from_user(&rd->id, (struct amdgpu_debugfs_regs2_iocdata_v2 *)data, 3318fa76350SSrinivasan Shanmugam sizeof(rd->id)); 332553f973aSTom St Denis if (r) 333553f973aSTom St Denis r = -EINVAL; 334553f973aSTom St Denis goto done; 335553f973aSTom St Denis case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE: 336553f973aSTom St Denis r = copy_from_user(&v1_data, (struct amdgpu_debugfs_regs2_iocdata *)data, 337553f973aSTom St Denis sizeof(v1_data)); 338553f973aSTom St Denis if (r) { 339553f973aSTom St Denis r = -EINVAL; 340553f973aSTom St Denis goto done; 34137df9560STom St Denis } 342553f973aSTom St Denis goto v1_copy; 343553f973aSTom St Denis default: 344553f973aSTom St Denis r = -EINVAL; 345553f973aSTom St Denis goto done; 346553f973aSTom St Denis } 347553f973aSTom St Denis 348553f973aSTom St Denis v1_copy: 349553f973aSTom St Denis rd->id.use_srbm = v1_data.use_srbm; 350553f973aSTom St Denis rd->id.use_grbm = v1_data.use_grbm; 351553f973aSTom St Denis rd->id.pg_lock = v1_data.pg_lock; 352553f973aSTom St Denis rd->id.grbm.se = v1_data.grbm.se; 353553f973aSTom St Denis rd->id.grbm.sh = v1_data.grbm.sh; 354553f973aSTom St Denis rd->id.grbm.instance = v1_data.grbm.instance; 355553f973aSTom St Denis rd->id.srbm.me = v1_data.srbm.me; 356553f973aSTom St Denis rd->id.srbm.pipe = v1_data.srbm.pipe; 357553f973aSTom St Denis rd->id.srbm.queue = v1_data.srbm.queue; 358553f973aSTom St Denis rd->id.xcc_id = 0; 359553f973aSTom St Denis done: 360553f973aSTom St Denis mutex_unlock(&rd->lock); 361553f973aSTom St Denis return r; 36237df9560STom St Denis } 36337df9560STom St Denis 36437df9560STom St Denis static ssize_t amdgpu_debugfs_regs2_read(struct file *f, char __user *buf, size_t size, loff_t *pos) 36537df9560STom St Denis { 36637df9560STom St Denis return amdgpu_debugfs_regs2_op(f, buf, *pos, size, 0); 36737df9560STom St Denis } 36837df9560STom St Denis 36937df9560STom St Denis static ssize_t amdgpu_debugfs_regs2_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) 37037df9560STom St Denis { 37137df9560STom St Denis return amdgpu_debugfs_regs2_op(f, (char __user *)buf, *pos, size, 1); 37237df9560STom St Denis } 37337df9560STom St Denis 374553f973aSTom St Denis static int amdgpu_debugfs_gprwave_open(struct inode *inode, struct file *file) 375553f973aSTom St Denis { 376553f973aSTom St Denis struct amdgpu_debugfs_gprwave_data *rd; 377553f973aSTom St Denis 378ad19c200SPraful Swarnakar rd = kzalloc(sizeof(*rd), GFP_KERNEL); 379553f973aSTom St Denis if (!rd) 380553f973aSTom St Denis return -ENOMEM; 381553f973aSTom St Denis rd->adev = file_inode(file)->i_private; 382553f973aSTom St Denis file->private_data = rd; 383553f973aSTom St Denis mutex_init(&rd->lock); 384553f973aSTom St Denis 385553f973aSTom St Denis return 0; 386553f973aSTom St Denis } 387553f973aSTom St Denis 388553f973aSTom St Denis static int amdgpu_debugfs_gprwave_release(struct inode *inode, struct file *file) 389553f973aSTom St Denis { 390553f973aSTom St Denis struct amdgpu_debugfs_gprwave_data *rd = file->private_data; 391ad19c200SPraful Swarnakar 392553f973aSTom St Denis mutex_destroy(&rd->lock); 393553f973aSTom St Denis kfree(file->private_data); 394553f973aSTom St Denis return 0; 395553f973aSTom St Denis } 396553f973aSTom St Denis 397553f973aSTom St Denis static ssize_t amdgpu_debugfs_gprwave_read(struct file *f, char __user *buf, size_t size, loff_t *pos) 398553f973aSTom St Denis { 399553f973aSTom St Denis struct amdgpu_debugfs_gprwave_data *rd = f->private_data; 400553f973aSTom St Denis struct amdgpu_device *adev = rd->adev; 401553f973aSTom St Denis ssize_t result = 0; 402553f973aSTom St Denis int r; 403553f973aSTom St Denis uint32_t *data, x; 404553f973aSTom St Denis 405553f973aSTom St Denis if (size & 0x3 || *pos & 0x3) 406553f973aSTom St Denis return -EINVAL; 407553f973aSTom St Denis 408553f973aSTom St Denis r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 409553f973aSTom St Denis if (r < 0) { 410553f973aSTom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 411553f973aSTom St Denis return r; 412553f973aSTom St Denis } 413553f973aSTom St Denis 414553f973aSTom St Denis r = amdgpu_virt_enable_access_debugfs(adev); 415553f973aSTom St Denis if (r < 0) { 416553f973aSTom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 417553f973aSTom St Denis return r; 418553f973aSTom St Denis } 419553f973aSTom St Denis 420553f973aSTom St Denis data = kcalloc(1024, sizeof(*data), GFP_KERNEL); 421553f973aSTom St Denis if (!data) { 422553f973aSTom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 423553f973aSTom St Denis amdgpu_virt_disable_access_debugfs(adev); 424553f973aSTom St Denis return -ENOMEM; 425553f973aSTom St Denis } 426553f973aSTom St Denis 427553f973aSTom St Denis /* switch to the specific se/sh/cu */ 428553f973aSTom St Denis mutex_lock(&adev->grbm_idx_mutex); 429553f973aSTom St Denis amdgpu_gfx_select_se_sh(adev, rd->id.se, rd->id.sh, rd->id.cu, rd->id.xcc_id); 430553f973aSTom St Denis 431553f973aSTom St Denis if (!rd->id.gpr_or_wave) { 432553f973aSTom St Denis x = 0; 433553f973aSTom St Denis if (adev->gfx.funcs->read_wave_data) 434553f973aSTom St Denis adev->gfx.funcs->read_wave_data(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, data, &x); 435553f973aSTom St Denis } else { 436553f973aSTom St Denis x = size >> 2; 437553f973aSTom St Denis if (rd->id.gpr.vpgr_or_sgpr) { 438553f973aSTom St Denis if (adev->gfx.funcs->read_wave_vgprs) 439553f973aSTom St Denis adev->gfx.funcs->read_wave_vgprs(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, rd->id.gpr.thread, *pos, size>>2, data); 440553f973aSTom St Denis } else { 441553f973aSTom St Denis if (adev->gfx.funcs->read_wave_sgprs) 442553f973aSTom St Denis adev->gfx.funcs->read_wave_sgprs(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, *pos, size>>2, data); 443553f973aSTom St Denis } 444553f973aSTom St Denis } 445553f973aSTom St Denis 446553f973aSTom St Denis amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, rd->id.xcc_id); 447553f973aSTom St Denis mutex_unlock(&adev->grbm_idx_mutex); 448553f973aSTom St Denis 449553f973aSTom St Denis pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 450553f973aSTom St Denis pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 451553f973aSTom St Denis 452553f973aSTom St Denis if (!x) { 453553f973aSTom St Denis result = -EINVAL; 454553f973aSTom St Denis goto done; 455553f973aSTom St Denis } 456553f973aSTom St Denis 457553f973aSTom St Denis while (size && (*pos < x * 4)) { 458553f973aSTom St Denis uint32_t value; 459553f973aSTom St Denis 460553f973aSTom St Denis value = data[*pos >> 2]; 461553f973aSTom St Denis r = put_user(value, (uint32_t *)buf); 462553f973aSTom St Denis if (r) { 463553f973aSTom St Denis result = r; 464553f973aSTom St Denis goto done; 465553f973aSTom St Denis } 466553f973aSTom St Denis 467553f973aSTom St Denis result += 4; 468553f973aSTom St Denis buf += 4; 469553f973aSTom St Denis *pos += 4; 470553f973aSTom St Denis size -= 4; 471553f973aSTom St Denis } 472553f973aSTom St Denis 473553f973aSTom St Denis done: 474553f973aSTom St Denis amdgpu_virt_disable_access_debugfs(adev); 475553f973aSTom St Denis kfree(data); 476553f973aSTom St Denis return result; 477553f973aSTom St Denis } 478553f973aSTom St Denis 479553f973aSTom St Denis static long amdgpu_debugfs_gprwave_ioctl(struct file *f, unsigned int cmd, unsigned long data) 480553f973aSTom St Denis { 481553f973aSTom St Denis struct amdgpu_debugfs_gprwave_data *rd = f->private_data; 4829c9d501bSDan Carpenter int r = 0; 483553f973aSTom St Denis 484553f973aSTom St Denis mutex_lock(&rd->lock); 485553f973aSTom St Denis 486553f973aSTom St Denis switch (cmd) { 487553f973aSTom St Denis case AMDGPU_DEBUGFS_GPRWAVE_IOC_SET_STATE: 4889c9d501bSDan Carpenter if (copy_from_user(&rd->id, 4899c9d501bSDan Carpenter (struct amdgpu_debugfs_gprwave_iocdata *)data, 4909c9d501bSDan Carpenter sizeof(rd->id))) 4919c9d501bSDan Carpenter r = -EFAULT; 492553f973aSTom St Denis goto done; 493553f973aSTom St Denis default: 494553f973aSTom St Denis r = -EINVAL; 495553f973aSTom St Denis goto done; 496553f973aSTom St Denis } 497553f973aSTom St Denis 498553f973aSTom St Denis done: 499553f973aSTom St Denis mutex_unlock(&rd->lock); 500553f973aSTom St Denis return r; 501553f973aSTom St Denis } 502553f973aSTom St Denis 503553f973aSTom St Denis 504553f973aSTom St Denis 5057e4237dbSTom St Denis 5067e4237dbSTom St Denis /** 5077e4237dbSTom St Denis * amdgpu_debugfs_regs_pcie_read - Read from a PCIE register 5087e4237dbSTom St Denis * 5097e4237dbSTom St Denis * @f: open file handle 5107e4237dbSTom St Denis * @buf: User buffer to store read data in 5117e4237dbSTom St Denis * @size: Number of bytes to read 5127e4237dbSTom St Denis * @pos: Offset to seek to 5137e4237dbSTom St Denis * 5147e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 5157e4237dbSTom St Denis * allows reading multiple registers in a single call and having 5167e4237dbSTom St Denis * the returned size reflect that. 5177e4237dbSTom St Denis */ 51875758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, 51975758255SAlex Deucher size_t size, loff_t *pos) 52075758255SAlex Deucher { 52175758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 52275758255SAlex Deucher ssize_t result = 0; 52375758255SAlex Deucher int r; 52475758255SAlex Deucher 52575758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 52675758255SAlex Deucher return -EINVAL; 52775758255SAlex Deucher 5284a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 5299eee152aSAlex Deucher if (r < 0) { 5304a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 531a9ffe2a9SAlex Deucher return r; 5329eee152aSAlex Deucher } 533a9ffe2a9SAlex Deucher 53495a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 5359eee152aSAlex Deucher if (r < 0) { 5364a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 53795a2f917SYintian Tao return r; 5389eee152aSAlex Deucher } 53995a2f917SYintian Tao 54075758255SAlex Deucher while (size) { 54175758255SAlex Deucher uint32_t value; 54275758255SAlex Deucher 54343fb6c19SKevin Wang value = RREG32_PCIE(*pos); 54475758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 545edadd6fcSAndré Almeida if (r) 546edadd6fcSAndré Almeida goto out; 54775758255SAlex Deucher 54875758255SAlex Deucher result += 4; 54975758255SAlex Deucher buf += 4; 55075758255SAlex Deucher *pos += 4; 55175758255SAlex Deucher size -= 4; 55275758255SAlex Deucher } 55375758255SAlex Deucher 554edadd6fcSAndré Almeida r = result; 555edadd6fcSAndré Almeida out: 5564a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 5574a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 55895a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 559edadd6fcSAndré Almeida return r; 56075758255SAlex Deucher } 56175758255SAlex Deucher 5627e4237dbSTom St Denis /** 5637e4237dbSTom St Denis * amdgpu_debugfs_regs_pcie_write - Write to a PCIE register 5647e4237dbSTom St Denis * 5657e4237dbSTom St Denis * @f: open file handle 5667e4237dbSTom St Denis * @buf: User buffer to write data from 5677e4237dbSTom St Denis * @size: Number of bytes to write 5687e4237dbSTom St Denis * @pos: Offset to seek to 5697e4237dbSTom St Denis * 5707e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 5717e4237dbSTom St Denis * allows writing multiple registers in a single call and having 5727e4237dbSTom St Denis * the returned size reflect that. 5737e4237dbSTom St Denis */ 57475758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf, 57575758255SAlex Deucher size_t size, loff_t *pos) 57675758255SAlex Deucher { 57775758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 57875758255SAlex Deucher ssize_t result = 0; 57975758255SAlex Deucher int r; 58075758255SAlex Deucher 58175758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 58275758255SAlex Deucher return -EINVAL; 58375758255SAlex Deucher 5844a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 5859eee152aSAlex Deucher if (r < 0) { 5864a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 587a9ffe2a9SAlex Deucher return r; 5889eee152aSAlex Deucher } 589a9ffe2a9SAlex Deucher 59095a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 5919eee152aSAlex Deucher if (r < 0) { 5924a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 59395a2f917SYintian Tao return r; 5949eee152aSAlex Deucher } 59595a2f917SYintian Tao 59675758255SAlex Deucher while (size) { 59775758255SAlex Deucher uint32_t value; 59875758255SAlex Deucher 59975758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 600edadd6fcSAndré Almeida if (r) 601edadd6fcSAndré Almeida goto out; 60275758255SAlex Deucher 60343fb6c19SKevin Wang WREG32_PCIE(*pos, value); 60475758255SAlex Deucher 60575758255SAlex Deucher result += 4; 60675758255SAlex Deucher buf += 4; 60775758255SAlex Deucher *pos += 4; 60875758255SAlex Deucher size -= 4; 60975758255SAlex Deucher } 61075758255SAlex Deucher 611edadd6fcSAndré Almeida r = result; 612edadd6fcSAndré Almeida out: 6134a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 6144a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 61595a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 616edadd6fcSAndré Almeida return r; 61775758255SAlex Deucher } 61875758255SAlex Deucher 6197e4237dbSTom St Denis /** 6207e4237dbSTom St Denis * amdgpu_debugfs_regs_didt_read - Read from a DIDT register 6217e4237dbSTom St Denis * 6227e4237dbSTom St Denis * @f: open file handle 6237e4237dbSTom St Denis * @buf: User buffer to store read data in 6247e4237dbSTom St Denis * @size: Number of bytes to read 6257e4237dbSTom St Denis * @pos: Offset to seek to 6267e4237dbSTom St Denis * 6277e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 6287e4237dbSTom St Denis * allows reading multiple registers in a single call and having 6297e4237dbSTom St Denis * the returned size reflect that. 6307e4237dbSTom St Denis */ 63175758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, 63275758255SAlex Deucher size_t size, loff_t *pos) 63375758255SAlex Deucher { 63475758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 63575758255SAlex Deucher ssize_t result = 0; 63675758255SAlex Deucher int r; 63775758255SAlex Deucher 63875758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 63975758255SAlex Deucher return -EINVAL; 64075758255SAlex Deucher 6414a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 6429eee152aSAlex Deucher if (r < 0) { 6434a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 644a9ffe2a9SAlex Deucher return r; 6459eee152aSAlex Deucher } 646a9ffe2a9SAlex Deucher 64795a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 6489eee152aSAlex Deucher if (r < 0) { 6494a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 65095a2f917SYintian Tao return r; 6519eee152aSAlex Deucher } 65295a2f917SYintian Tao 65375758255SAlex Deucher while (size) { 65475758255SAlex Deucher uint32_t value; 65575758255SAlex Deucher 65675758255SAlex Deucher value = RREG32_DIDT(*pos >> 2); 65775758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 658edadd6fcSAndré Almeida if (r) 659edadd6fcSAndré Almeida goto out; 66075758255SAlex Deucher 66175758255SAlex Deucher result += 4; 66275758255SAlex Deucher buf += 4; 66375758255SAlex Deucher *pos += 4; 66475758255SAlex Deucher size -= 4; 66575758255SAlex Deucher } 66675758255SAlex Deucher 667edadd6fcSAndré Almeida r = result; 668edadd6fcSAndré Almeida out: 6694a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 6704a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 67195a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 672edadd6fcSAndré Almeida return r; 67375758255SAlex Deucher } 67475758255SAlex Deucher 6757e4237dbSTom St Denis /** 6767e4237dbSTom St Denis * amdgpu_debugfs_regs_didt_write - Write to a DIDT register 6777e4237dbSTom St Denis * 6787e4237dbSTom St Denis * @f: open file handle 6797e4237dbSTom St Denis * @buf: User buffer to write data from 6807e4237dbSTom St Denis * @size: Number of bytes to write 6817e4237dbSTom St Denis * @pos: Offset to seek to 6827e4237dbSTom St Denis * 6837e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 6847e4237dbSTom St Denis * allows writing multiple registers in a single call and having 6857e4237dbSTom St Denis * the returned size reflect that. 6867e4237dbSTom St Denis */ 68775758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf, 68875758255SAlex Deucher size_t size, loff_t *pos) 68975758255SAlex Deucher { 69075758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 69175758255SAlex Deucher ssize_t result = 0; 69275758255SAlex Deucher int r; 69375758255SAlex Deucher 69475758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 69575758255SAlex Deucher return -EINVAL; 69675758255SAlex Deucher 6974a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 6989eee152aSAlex Deucher if (r < 0) { 6994a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 700a9ffe2a9SAlex Deucher return r; 7019eee152aSAlex Deucher } 702a9ffe2a9SAlex Deucher 70395a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 7049eee152aSAlex Deucher if (r < 0) { 7054a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 70695a2f917SYintian Tao return r; 7079eee152aSAlex Deucher } 70895a2f917SYintian Tao 70975758255SAlex Deucher while (size) { 71075758255SAlex Deucher uint32_t value; 71175758255SAlex Deucher 71275758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 713edadd6fcSAndré Almeida if (r) 714edadd6fcSAndré Almeida goto out; 71575758255SAlex Deucher 71675758255SAlex Deucher WREG32_DIDT(*pos >> 2, value); 71775758255SAlex Deucher 71875758255SAlex Deucher result += 4; 71975758255SAlex Deucher buf += 4; 72075758255SAlex Deucher *pos += 4; 72175758255SAlex Deucher size -= 4; 72275758255SAlex Deucher } 72375758255SAlex Deucher 724edadd6fcSAndré Almeida r = result; 725edadd6fcSAndré Almeida out: 7264a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 7274a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 72895a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 729edadd6fcSAndré Almeida return r; 73075758255SAlex Deucher } 73175758255SAlex Deucher 7327e4237dbSTom St Denis /** 7337e4237dbSTom St Denis * amdgpu_debugfs_regs_smc_read - Read from a SMC register 7347e4237dbSTom St Denis * 7357e4237dbSTom St Denis * @f: open file handle 7367e4237dbSTom St Denis * @buf: User buffer to store read data in 7377e4237dbSTom St Denis * @size: Number of bytes to read 7387e4237dbSTom St Denis * @pos: Offset to seek to 7397e4237dbSTom St Denis * 7407e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 7417e4237dbSTom St Denis * allows reading multiple registers in a single call and having 7427e4237dbSTom St Denis * the returned size reflect that. 7437e4237dbSTom St Denis */ 74475758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, 74575758255SAlex Deucher size_t size, loff_t *pos) 74675758255SAlex Deucher { 74775758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 74875758255SAlex Deucher ssize_t result = 0; 74975758255SAlex Deucher int r; 75075758255SAlex Deucher 751*5104fdf5SQu Huang if (!adev->smc_rreg) 752*5104fdf5SQu Huang return -EPERM; 753*5104fdf5SQu Huang 75475758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 75575758255SAlex Deucher return -EINVAL; 75675758255SAlex Deucher 7574a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 7589eee152aSAlex Deucher if (r < 0) { 7594a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 760a9ffe2a9SAlex Deucher return r; 7619eee152aSAlex Deucher } 762a9ffe2a9SAlex Deucher 76395a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 7649eee152aSAlex Deucher if (r < 0) { 7654a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 76695a2f917SYintian Tao return r; 7679eee152aSAlex Deucher } 76895a2f917SYintian Tao 76975758255SAlex Deucher while (size) { 77075758255SAlex Deucher uint32_t value; 77175758255SAlex Deucher 77275758255SAlex Deucher value = RREG32_SMC(*pos); 77375758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 774edadd6fcSAndré Almeida if (r) 775edadd6fcSAndré Almeida goto out; 77675758255SAlex Deucher 77775758255SAlex Deucher result += 4; 77875758255SAlex Deucher buf += 4; 77975758255SAlex Deucher *pos += 4; 78075758255SAlex Deucher size -= 4; 78175758255SAlex Deucher } 78275758255SAlex Deucher 783edadd6fcSAndré Almeida r = result; 784edadd6fcSAndré Almeida out: 7854a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 7864a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 78795a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 788edadd6fcSAndré Almeida return r; 78975758255SAlex Deucher } 79075758255SAlex Deucher 7917e4237dbSTom St Denis /** 7927e4237dbSTom St Denis * amdgpu_debugfs_regs_smc_write - Write to a SMC register 7937e4237dbSTom St Denis * 7947e4237dbSTom St Denis * @f: open file handle 7957e4237dbSTom St Denis * @buf: User buffer to write data from 7967e4237dbSTom St Denis * @size: Number of bytes to write 7977e4237dbSTom St Denis * @pos: Offset to seek to 7987e4237dbSTom St Denis * 7997e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 8007e4237dbSTom St Denis * allows writing multiple registers in a single call and having 8017e4237dbSTom St Denis * the returned size reflect that. 8027e4237dbSTom St Denis */ 80375758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf, 80475758255SAlex Deucher size_t size, loff_t *pos) 80575758255SAlex Deucher { 80675758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 80775758255SAlex Deucher ssize_t result = 0; 80875758255SAlex Deucher int r; 80975758255SAlex Deucher 810*5104fdf5SQu Huang if (!adev->smc_wreg) 811*5104fdf5SQu Huang return -EPERM; 812*5104fdf5SQu Huang 81375758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 81475758255SAlex Deucher return -EINVAL; 81575758255SAlex Deucher 8164a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 8179eee152aSAlex Deucher if (r < 0) { 8184a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 819a9ffe2a9SAlex Deucher return r; 8209eee152aSAlex Deucher } 821a9ffe2a9SAlex Deucher 82295a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 8239eee152aSAlex Deucher if (r < 0) { 8244a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 82595a2f917SYintian Tao return r; 8269eee152aSAlex Deucher } 82795a2f917SYintian Tao 82875758255SAlex Deucher while (size) { 82975758255SAlex Deucher uint32_t value; 83075758255SAlex Deucher 83175758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 832edadd6fcSAndré Almeida if (r) 833edadd6fcSAndré Almeida goto out; 83475758255SAlex Deucher 83575758255SAlex Deucher WREG32_SMC(*pos, value); 83675758255SAlex Deucher 83775758255SAlex Deucher result += 4; 83875758255SAlex Deucher buf += 4; 83975758255SAlex Deucher *pos += 4; 84075758255SAlex Deucher size -= 4; 84175758255SAlex Deucher } 84275758255SAlex Deucher 843edadd6fcSAndré Almeida r = result; 844edadd6fcSAndré Almeida out: 8454a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 8464a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 84795a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 848edadd6fcSAndré Almeida return r; 84975758255SAlex Deucher } 85075758255SAlex Deucher 8517e4237dbSTom St Denis /** 8527e4237dbSTom St Denis * amdgpu_debugfs_gca_config_read - Read from gfx config data 8537e4237dbSTom St Denis * 8547e4237dbSTom St Denis * @f: open file handle 8557e4237dbSTom St Denis * @buf: User buffer to store read data in 8567e4237dbSTom St Denis * @size: Number of bytes to read 8577e4237dbSTom St Denis * @pos: Offset to seek to 8587e4237dbSTom St Denis * 8597e4237dbSTom St Denis * This file is used to access configuration data in a somewhat 8607e4237dbSTom St Denis * stable fashion. The format is a series of DWORDs with the first 8617e4237dbSTom St Denis * indicating which revision it is. New content is appended to the 8627e4237dbSTom St Denis * end so that older software can still read the data. 8637e4237dbSTom St Denis */ 8647e4237dbSTom St Denis 86575758255SAlex Deucher static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, 86675758255SAlex Deucher size_t size, loff_t *pos) 86775758255SAlex Deucher { 86875758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 86975758255SAlex Deucher ssize_t result = 0; 87075758255SAlex Deucher int r; 87175758255SAlex Deucher uint32_t *config, no_regs = 0; 87275758255SAlex Deucher 87375758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 87475758255SAlex Deucher return -EINVAL; 87575758255SAlex Deucher 87675758255SAlex Deucher config = kmalloc_array(256, sizeof(*config), GFP_KERNEL); 87775758255SAlex Deucher if (!config) 87875758255SAlex Deucher return -ENOMEM; 87975758255SAlex Deucher 88075758255SAlex Deucher /* version, increment each time something is added */ 881dc2947b3STom St Denis config[no_regs++] = 5; 88275758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_shader_engines; 88375758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_tile_pipes; 88475758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_cu_per_sh; 88575758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_sh_per_se; 88675758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_backends_per_se; 88775758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_texture_channel_caches; 88875758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_gprs; 88975758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_gs_threads; 89075758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_hw_contexts; 89175758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_frontend; 89275758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_backend; 89375758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_hiz_tile_fifo_size; 89475758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_earlyz_tile_fifo_size; 89575758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_tile_pipes; 89675758255SAlex Deucher config[no_regs++] = adev->gfx.config.backend_enable_mask; 89775758255SAlex Deucher config[no_regs++] = adev->gfx.config.mem_max_burst_length_bytes; 89875758255SAlex Deucher config[no_regs++] = adev->gfx.config.mem_row_size_in_kb; 89975758255SAlex Deucher config[no_regs++] = adev->gfx.config.shader_engine_tile_size; 90075758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_gpus; 90175758255SAlex Deucher config[no_regs++] = adev->gfx.config.multi_gpu_tile_size; 90275758255SAlex Deucher config[no_regs++] = adev->gfx.config.mc_arb_ramcfg; 90375758255SAlex Deucher config[no_regs++] = adev->gfx.config.gb_addr_config; 90475758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_rbs; 90575758255SAlex Deucher 90675758255SAlex Deucher /* rev==1 */ 90775758255SAlex Deucher config[no_regs++] = adev->rev_id; 908dc2947b3STom St Denis config[no_regs++] = lower_32_bits(adev->pg_flags); 90925faeddcSEvan Quan config[no_regs++] = lower_32_bits(adev->cg_flags); 91075758255SAlex Deucher 91175758255SAlex Deucher /* rev==2 */ 91275758255SAlex Deucher config[no_regs++] = adev->family; 91375758255SAlex Deucher config[no_regs++] = adev->external_rev_id; 91475758255SAlex Deucher 91575758255SAlex Deucher /* rev==3 */ 91675758255SAlex Deucher config[no_regs++] = adev->pdev->device; 91775758255SAlex Deucher config[no_regs++] = adev->pdev->revision; 91875758255SAlex Deucher config[no_regs++] = adev->pdev->subsystem_device; 91975758255SAlex Deucher config[no_regs++] = adev->pdev->subsystem_vendor; 92075758255SAlex Deucher 9218f74f68dSTom St Denis /* rev==4 APU flag */ 9228f74f68dSTom St Denis config[no_regs++] = adev->flags & AMD_IS_APU ? 1 : 0; 9238f74f68dSTom St Denis 924dc2947b3STom St Denis /* rev==5 PG/CG flag upper 32bit */ 925dc2947b3STom St Denis config[no_regs++] = upper_32_bits(adev->pg_flags); 92625faeddcSEvan Quan config[no_regs++] = upper_32_bits(adev->cg_flags); 92725faeddcSEvan Quan 92875758255SAlex Deucher while (size && (*pos < no_regs * 4)) { 92975758255SAlex Deucher uint32_t value; 93075758255SAlex Deucher 93175758255SAlex Deucher value = config[*pos >> 2]; 93275758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 93375758255SAlex Deucher if (r) { 93475758255SAlex Deucher kfree(config); 93575758255SAlex Deucher return r; 93675758255SAlex Deucher } 93775758255SAlex Deucher 93875758255SAlex Deucher result += 4; 93975758255SAlex Deucher buf += 4; 94075758255SAlex Deucher *pos += 4; 94175758255SAlex Deucher size -= 4; 94275758255SAlex Deucher } 94375758255SAlex Deucher 94475758255SAlex Deucher kfree(config); 94575758255SAlex Deucher return result; 94675758255SAlex Deucher } 94775758255SAlex Deucher 9487e4237dbSTom St Denis /** 9497e4237dbSTom St Denis * amdgpu_debugfs_sensor_read - Read from the powerplay sensors 9507e4237dbSTom St Denis * 9517e4237dbSTom St Denis * @f: open file handle 9527e4237dbSTom St Denis * @buf: User buffer to store read data in 9537e4237dbSTom St Denis * @size: Number of bytes to read 9547e4237dbSTom St Denis * @pos: Offset to seek to 9557e4237dbSTom St Denis * 9567e4237dbSTom St Denis * The offset is treated as the BYTE address of one of the sensors 9577e4237dbSTom St Denis * enumerated in amd/include/kgd_pp_interface.h under the 9587e4237dbSTom St Denis * 'amd_pp_sensors' enumeration. For instance to read the UVD VCLK 9597e4237dbSTom St Denis * you would use the offset 3 * 4 = 12. 9607e4237dbSTom St Denis */ 96175758255SAlex Deucher static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, 96275758255SAlex Deucher size_t size, loff_t *pos) 96375758255SAlex Deucher { 96475758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 96575758255SAlex Deucher int idx, x, outsize, r, valuesize; 96675758255SAlex Deucher uint32_t values[16]; 96775758255SAlex Deucher 96875758255SAlex Deucher if (size & 3 || *pos & 0x3) 96975758255SAlex Deucher return -EINVAL; 97075758255SAlex Deucher 971b13aa109SRex Zhu if (!adev->pm.dpm_enabled) 97275758255SAlex Deucher return -EINVAL; 97375758255SAlex Deucher 97475758255SAlex Deucher /* convert offset to sensor number */ 97575758255SAlex Deucher idx = *pos >> 2; 97675758255SAlex Deucher 97775758255SAlex Deucher valuesize = sizeof(values); 978a9ffe2a9SAlex Deucher 9794a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 9809eee152aSAlex Deucher if (r < 0) { 9814a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 982a9ffe2a9SAlex Deucher return r; 9839eee152aSAlex Deucher } 984a9ffe2a9SAlex Deucher 98595a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 9869eee152aSAlex Deucher if (r < 0) { 9874a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 98895a2f917SYintian Tao return r; 9899eee152aSAlex Deucher } 99095a2f917SYintian Tao 99175758255SAlex Deucher r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize); 992a9ffe2a9SAlex Deucher 9934a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 9944a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 995a9ffe2a9SAlex Deucher 99695a2f917SYintian Tao if (r) { 99795a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 9984a5a2de6SKevin Wang return r; 99995a2f917SYintian Tao } 100075758255SAlex Deucher 100195a2f917SYintian Tao if (size > valuesize) { 100295a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 100375758255SAlex Deucher return -EINVAL; 100495a2f917SYintian Tao } 100575758255SAlex Deucher 100675758255SAlex Deucher outsize = 0; 100775758255SAlex Deucher x = 0; 100875758255SAlex Deucher if (!r) { 100975758255SAlex Deucher while (size) { 101075758255SAlex Deucher r = put_user(values[x++], (int32_t *)buf); 101175758255SAlex Deucher buf += 4; 101275758255SAlex Deucher size -= 4; 101375758255SAlex Deucher outsize += 4; 101475758255SAlex Deucher } 101575758255SAlex Deucher } 101675758255SAlex Deucher 101795a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 101875758255SAlex Deucher return !r ? outsize : r; 101975758255SAlex Deucher } 102075758255SAlex Deucher 10217e4237dbSTom St Denis /** amdgpu_debugfs_wave_read - Read WAVE STATUS data 10227e4237dbSTom St Denis * 10237e4237dbSTom St Denis * @f: open file handle 10247e4237dbSTom St Denis * @buf: User buffer to store read data in 10257e4237dbSTom St Denis * @size: Number of bytes to read 10267e4237dbSTom St Denis * @pos: Offset to seek to 10277e4237dbSTom St Denis * 10287e4237dbSTom St Denis * The offset being sought changes which wave that the status data 10297e4237dbSTom St Denis * will be returned for. The bits are used as follows: 10307e4237dbSTom St Denis * 10317e4237dbSTom St Denis * Bits 0..6: Byte offset into data 10327e4237dbSTom St Denis * Bits 7..14: SE selector 10337e4237dbSTom St Denis * Bits 15..22: SH/SA selector 10347e4237dbSTom St Denis * Bits 23..30: CU/{WGP+SIMD} selector 10357e4237dbSTom St Denis * Bits 31..36: WAVE ID selector 10367e4237dbSTom St Denis * Bits 37..44: SIMD ID selector 10377e4237dbSTom St Denis * 10387e4237dbSTom St Denis * The returned data begins with one DWORD of version information 10397e4237dbSTom St Denis * Followed by WAVE STATUS registers relevant to the GFX IP version 10407e4237dbSTom St Denis * being used. See gfx_v8_0_read_wave_data() for an example output. 10417e4237dbSTom St Denis */ 104275758255SAlex Deucher static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, 104375758255SAlex Deucher size_t size, loff_t *pos) 104475758255SAlex Deucher { 104575758255SAlex Deucher struct amdgpu_device *adev = f->f_inode->i_private; 104675758255SAlex Deucher int r, x; 104775758255SAlex Deucher ssize_t result = 0; 104875758255SAlex Deucher uint32_t offset, se, sh, cu, wave, simd, data[32]; 104975758255SAlex Deucher 105075758255SAlex Deucher if (size & 3 || *pos & 3) 105175758255SAlex Deucher return -EINVAL; 105275758255SAlex Deucher 105375758255SAlex Deucher /* decode offset */ 105475758255SAlex Deucher offset = (*pos & GENMASK_ULL(6, 0)); 105575758255SAlex Deucher se = (*pos & GENMASK_ULL(14, 7)) >> 7; 105675758255SAlex Deucher sh = (*pos & GENMASK_ULL(22, 15)) >> 15; 105775758255SAlex Deucher cu = (*pos & GENMASK_ULL(30, 23)) >> 23; 105875758255SAlex Deucher wave = (*pos & GENMASK_ULL(36, 31)) >> 31; 105975758255SAlex Deucher simd = (*pos & GENMASK_ULL(44, 37)) >> 37; 106075758255SAlex Deucher 10614a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 10629eee152aSAlex Deucher if (r < 0) { 10634a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1064a9ffe2a9SAlex Deucher return r; 10659eee152aSAlex Deucher } 1066a9ffe2a9SAlex Deucher 106795a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 10689eee152aSAlex Deucher if (r < 0) { 10694a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 107095a2f917SYintian Tao return r; 10719eee152aSAlex Deucher } 107295a2f917SYintian Tao 107375758255SAlex Deucher /* switch to the specific se/sh/cu */ 107475758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 1075d51ac6d0SLe Ma amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0); 107675758255SAlex Deucher 107775758255SAlex Deucher x = 0; 107875758255SAlex Deucher if (adev->gfx.funcs->read_wave_data) 1079553f973aSTom St Denis adev->gfx.funcs->read_wave_data(adev, 0, simd, wave, data, &x); 108075758255SAlex Deucher 1081d51ac6d0SLe Ma amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0); 108275758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 108375758255SAlex Deucher 10844a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 10854a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1086a9ffe2a9SAlex Deucher 108795a2f917SYintian Tao if (!x) { 108895a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 108975758255SAlex Deucher return -EINVAL; 109095a2f917SYintian Tao } 109175758255SAlex Deucher 109275758255SAlex Deucher while (size && (offset < x * 4)) { 109375758255SAlex Deucher uint32_t value; 109475758255SAlex Deucher 109575758255SAlex Deucher value = data[offset >> 2]; 109675758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 109795a2f917SYintian Tao if (r) { 109895a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 109975758255SAlex Deucher return r; 110095a2f917SYintian Tao } 110175758255SAlex Deucher 110275758255SAlex Deucher result += 4; 110375758255SAlex Deucher buf += 4; 110475758255SAlex Deucher offset += 4; 110575758255SAlex Deucher size -= 4; 110675758255SAlex Deucher } 110775758255SAlex Deucher 110895a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 110975758255SAlex Deucher return result; 111075758255SAlex Deucher } 111175758255SAlex Deucher 11127e4237dbSTom St Denis /** amdgpu_debugfs_gpr_read - Read wave gprs 11137e4237dbSTom St Denis * 11147e4237dbSTom St Denis * @f: open file handle 11157e4237dbSTom St Denis * @buf: User buffer to store read data in 11167e4237dbSTom St Denis * @size: Number of bytes to read 11177e4237dbSTom St Denis * @pos: Offset to seek to 11187e4237dbSTom St Denis * 11197e4237dbSTom St Denis * The offset being sought changes which wave that the status data 11207e4237dbSTom St Denis * will be returned for. The bits are used as follows: 11217e4237dbSTom St Denis * 11227e4237dbSTom St Denis * Bits 0..11: Byte offset into data 11237e4237dbSTom St Denis * Bits 12..19: SE selector 11247e4237dbSTom St Denis * Bits 20..27: SH/SA selector 11257e4237dbSTom St Denis * Bits 28..35: CU/{WGP+SIMD} selector 11267e4237dbSTom St Denis * Bits 36..43: WAVE ID selector 11277e4237dbSTom St Denis * Bits 37..44: SIMD ID selector 11287e4237dbSTom St Denis * Bits 52..59: Thread selector 11297e4237dbSTom St Denis * Bits 60..61: Bank selector (VGPR=0,SGPR=1) 11307e4237dbSTom St Denis * 11317e4237dbSTom St Denis * The return data comes from the SGPR or VGPR register bank for 11327e4237dbSTom St Denis * the selected operational unit. 11337e4237dbSTom St Denis */ 113475758255SAlex Deucher static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, 113575758255SAlex Deucher size_t size, loff_t *pos) 113675758255SAlex Deucher { 113775758255SAlex Deucher struct amdgpu_device *adev = f->f_inode->i_private; 113875758255SAlex Deucher int r; 113975758255SAlex Deucher ssize_t result = 0; 114075758255SAlex Deucher uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; 114175758255SAlex Deucher 11426397ec58STom St Denis if (size > 4096 || size & 3 || *pos & 3) 114375758255SAlex Deucher return -EINVAL; 114475758255SAlex Deucher 114575758255SAlex Deucher /* decode offset */ 11466397ec58STom St Denis offset = (*pos & GENMASK_ULL(11, 0)) >> 2; 114775758255SAlex Deucher se = (*pos & GENMASK_ULL(19, 12)) >> 12; 114875758255SAlex Deucher sh = (*pos & GENMASK_ULL(27, 20)) >> 20; 114975758255SAlex Deucher cu = (*pos & GENMASK_ULL(35, 28)) >> 28; 115075758255SAlex Deucher wave = (*pos & GENMASK_ULL(43, 36)) >> 36; 115175758255SAlex Deucher simd = (*pos & GENMASK_ULL(51, 44)) >> 44; 115275758255SAlex Deucher thread = (*pos & GENMASK_ULL(59, 52)) >> 52; 115375758255SAlex Deucher bank = (*pos & GENMASK_ULL(61, 60)) >> 60; 115475758255SAlex Deucher 1155929e571cSWang Xiayang data = kcalloc(1024, sizeof(*data), GFP_KERNEL); 115675758255SAlex Deucher if (!data) 115775758255SAlex Deucher return -ENOMEM; 115875758255SAlex Deucher 11594a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 1160a9ffe2a9SAlex Deucher if (r < 0) 11613e4aeff3SChen Tao goto err; 1162a9ffe2a9SAlex Deucher 116395a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 116495a2f917SYintian Tao if (r < 0) 1165888e32d7SChen Tao goto err; 116695a2f917SYintian Tao 116775758255SAlex Deucher /* switch to the specific se/sh/cu */ 116875758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 1169d51ac6d0SLe Ma amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0); 117075758255SAlex Deucher 117175758255SAlex Deucher if (bank == 0) { 117275758255SAlex Deucher if (adev->gfx.funcs->read_wave_vgprs) 1173553f973aSTom St Denis adev->gfx.funcs->read_wave_vgprs(adev, 0, simd, wave, thread, offset, size>>2, data); 117475758255SAlex Deucher } else { 117575758255SAlex Deucher if (adev->gfx.funcs->read_wave_sgprs) 1176553f973aSTom St Denis adev->gfx.funcs->read_wave_sgprs(adev, 0, simd, wave, offset, size>>2, data); 117775758255SAlex Deucher } 117875758255SAlex Deucher 1179d51ac6d0SLe Ma amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0); 118075758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 118175758255SAlex Deucher 11824a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 11834a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1184a9ffe2a9SAlex Deucher 118575758255SAlex Deucher while (size) { 118675758255SAlex Deucher uint32_t value; 118775758255SAlex Deucher 11886397ec58STom St Denis value = data[result >> 2]; 118975758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 119075758255SAlex Deucher if (r) { 11913e4aeff3SChen Tao amdgpu_virt_disable_access_debugfs(adev); 119275758255SAlex Deucher goto err; 119375758255SAlex Deucher } 119475758255SAlex Deucher 119575758255SAlex Deucher result += 4; 119675758255SAlex Deucher buf += 4; 119775758255SAlex Deucher size -= 4; 119875758255SAlex Deucher } 119975758255SAlex Deucher 120075758255SAlex Deucher kfree(data); 120195a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 120275758255SAlex Deucher return result; 12033e4aeff3SChen Tao 12043e4aeff3SChen Tao err: 12054a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12063e4aeff3SChen Tao kfree(data); 12073e4aeff3SChen Tao return r; 120875758255SAlex Deucher } 120975758255SAlex Deucher 1210669e2f91STom St Denis /** 12110ad7347aSAndré Almeida * amdgpu_debugfs_gfxoff_residency_read - Read GFXOFF residency 12120ad7347aSAndré Almeida * 12130ad7347aSAndré Almeida * @f: open file handle 12140ad7347aSAndré Almeida * @buf: User buffer to store read data in 12150ad7347aSAndré Almeida * @size: Number of bytes to read 12160ad7347aSAndré Almeida * @pos: Offset to seek to 12170ad7347aSAndré Almeida * 12180ad7347aSAndré Almeida * Read the last residency value logged. It doesn't auto update, one needs to 12190ad7347aSAndré Almeida * stop logging before getting the current value. 12200ad7347aSAndré Almeida */ 12210ad7347aSAndré Almeida static ssize_t amdgpu_debugfs_gfxoff_residency_read(struct file *f, char __user *buf, 12220ad7347aSAndré Almeida size_t size, loff_t *pos) 12230ad7347aSAndré Almeida { 12240ad7347aSAndré Almeida struct amdgpu_device *adev = file_inode(f)->i_private; 12250ad7347aSAndré Almeida ssize_t result = 0; 12260ad7347aSAndré Almeida int r; 12270ad7347aSAndré Almeida 12280ad7347aSAndré Almeida if (size & 0x3 || *pos & 0x3) 12290ad7347aSAndré Almeida return -EINVAL; 12300ad7347aSAndré Almeida 12310ad7347aSAndré Almeida r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 12320ad7347aSAndré Almeida if (r < 0) { 12330ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12340ad7347aSAndré Almeida return r; 12350ad7347aSAndré Almeida } 12360ad7347aSAndré Almeida 12370ad7347aSAndré Almeida while (size) { 12380ad7347aSAndré Almeida uint32_t value; 12390ad7347aSAndré Almeida 12400ad7347aSAndré Almeida r = amdgpu_get_gfx_off_residency(adev, &value); 12410ad7347aSAndré Almeida if (r) 12420ad7347aSAndré Almeida goto out; 12430ad7347aSAndré Almeida 12440ad7347aSAndré Almeida r = put_user(value, (uint32_t *)buf); 12450ad7347aSAndré Almeida if (r) 12460ad7347aSAndré Almeida goto out; 12470ad7347aSAndré Almeida 12480ad7347aSAndré Almeida result += 4; 12490ad7347aSAndré Almeida buf += 4; 12500ad7347aSAndré Almeida *pos += 4; 12510ad7347aSAndré Almeida size -= 4; 12520ad7347aSAndré Almeida } 12530ad7347aSAndré Almeida 12540ad7347aSAndré Almeida r = result; 12550ad7347aSAndré Almeida out: 12560ad7347aSAndré Almeida pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 12570ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12580ad7347aSAndré Almeida 12590ad7347aSAndré Almeida return r; 12600ad7347aSAndré Almeida } 12610ad7347aSAndré Almeida 12620ad7347aSAndré Almeida /** 12630ad7347aSAndré Almeida * amdgpu_debugfs_gfxoff_residency_write - Log GFXOFF Residency 12640ad7347aSAndré Almeida * 12650ad7347aSAndré Almeida * @f: open file handle 12660ad7347aSAndré Almeida * @buf: User buffer to write data from 12670ad7347aSAndré Almeida * @size: Number of bytes to write 12680ad7347aSAndré Almeida * @pos: Offset to seek to 12690ad7347aSAndré Almeida * 12700ad7347aSAndré Almeida * Write a 32-bit non-zero to start logging; write a 32-bit zero to stop 12710ad7347aSAndré Almeida */ 12720ad7347aSAndré Almeida static ssize_t amdgpu_debugfs_gfxoff_residency_write(struct file *f, const char __user *buf, 12730ad7347aSAndré Almeida size_t size, loff_t *pos) 12740ad7347aSAndré Almeida { 12750ad7347aSAndré Almeida struct amdgpu_device *adev = file_inode(f)->i_private; 12760ad7347aSAndré Almeida ssize_t result = 0; 12770ad7347aSAndré Almeida int r; 12780ad7347aSAndré Almeida 12790ad7347aSAndré Almeida if (size & 0x3 || *pos & 0x3) 12800ad7347aSAndré Almeida return -EINVAL; 12810ad7347aSAndré Almeida 12820ad7347aSAndré Almeida r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 12830ad7347aSAndré Almeida if (r < 0) { 12840ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12850ad7347aSAndré Almeida return r; 12860ad7347aSAndré Almeida } 12870ad7347aSAndré Almeida 12880ad7347aSAndré Almeida while (size) { 12890ad7347aSAndré Almeida u32 value; 12900ad7347aSAndré Almeida 12910ad7347aSAndré Almeida r = get_user(value, (uint32_t *)buf); 12920ad7347aSAndré Almeida if (r) 12930ad7347aSAndré Almeida goto out; 12940ad7347aSAndré Almeida 12950ad7347aSAndré Almeida amdgpu_set_gfx_off_residency(adev, value ? true : false); 12960ad7347aSAndré Almeida 12970ad7347aSAndré Almeida result += 4; 12980ad7347aSAndré Almeida buf += 4; 12990ad7347aSAndré Almeida *pos += 4; 13000ad7347aSAndré Almeida size -= 4; 13010ad7347aSAndré Almeida } 13020ad7347aSAndré Almeida 13030ad7347aSAndré Almeida r = result; 13040ad7347aSAndré Almeida out: 13050ad7347aSAndré Almeida pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 13060ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 13070ad7347aSAndré Almeida 13080ad7347aSAndré Almeida return r; 13090ad7347aSAndré Almeida } 13100ad7347aSAndré Almeida 13110ad7347aSAndré Almeida 13120ad7347aSAndré Almeida /** 13130ad7347aSAndré Almeida * amdgpu_debugfs_gfxoff_count_read - Read GFXOFF entry count 13140ad7347aSAndré Almeida * 13150ad7347aSAndré Almeida * @f: open file handle 13160ad7347aSAndré Almeida * @buf: User buffer to store read data in 13170ad7347aSAndré Almeida * @size: Number of bytes to read 13180ad7347aSAndré Almeida * @pos: Offset to seek to 13190ad7347aSAndré Almeida */ 13200ad7347aSAndré Almeida static ssize_t amdgpu_debugfs_gfxoff_count_read(struct file *f, char __user *buf, 13210ad7347aSAndré Almeida size_t size, loff_t *pos) 13220ad7347aSAndré Almeida { 13230ad7347aSAndré Almeida struct amdgpu_device *adev = file_inode(f)->i_private; 13240ad7347aSAndré Almeida ssize_t result = 0; 13250ad7347aSAndré Almeida int r; 13260ad7347aSAndré Almeida 13270ad7347aSAndré Almeida if (size & 0x3 || *pos & 0x3) 13280ad7347aSAndré Almeida return -EINVAL; 13290ad7347aSAndré Almeida 13300ad7347aSAndré Almeida r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 13310ad7347aSAndré Almeida if (r < 0) { 13320ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 13330ad7347aSAndré Almeida return r; 13340ad7347aSAndré Almeida } 13350ad7347aSAndré Almeida 13360ad7347aSAndré Almeida while (size) { 13370ad7347aSAndré Almeida u64 value = 0; 13380ad7347aSAndré Almeida 13390ad7347aSAndré Almeida r = amdgpu_get_gfx_off_entrycount(adev, &value); 13400ad7347aSAndré Almeida if (r) 13410ad7347aSAndré Almeida goto out; 13420ad7347aSAndré Almeida 13430ad7347aSAndré Almeida r = put_user(value, (u64 *)buf); 13440ad7347aSAndré Almeida if (r) 13450ad7347aSAndré Almeida goto out; 13460ad7347aSAndré Almeida 13470ad7347aSAndré Almeida result += 4; 13480ad7347aSAndré Almeida buf += 4; 13490ad7347aSAndré Almeida *pos += 4; 13500ad7347aSAndré Almeida size -= 4; 13510ad7347aSAndré Almeida } 13520ad7347aSAndré Almeida 13530ad7347aSAndré Almeida r = result; 13540ad7347aSAndré Almeida out: 13550ad7347aSAndré Almeida pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 13560ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 13570ad7347aSAndré Almeida 13580ad7347aSAndré Almeida return r; 13590ad7347aSAndré Almeida } 13600ad7347aSAndré Almeida 13610ad7347aSAndré Almeida /** 1362e72d4a8bSLee Jones * amdgpu_debugfs_gfxoff_write - Enable/disable GFXOFF 1363669e2f91STom St Denis * 1364669e2f91STom St Denis * @f: open file handle 1365669e2f91STom St Denis * @buf: User buffer to write data from 1366669e2f91STom St Denis * @size: Number of bytes to write 1367669e2f91STom St Denis * @pos: Offset to seek to 1368669e2f91STom St Denis * 1369669e2f91STom St Denis * Write a 32-bit zero to disable or a 32-bit non-zero to enable 1370669e2f91STom St Denis */ 1371669e2f91STom St Denis static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *buf, 1372669e2f91STom St Denis size_t size, loff_t *pos) 1373669e2f91STom St Denis { 1374669e2f91STom St Denis struct amdgpu_device *adev = file_inode(f)->i_private; 1375669e2f91STom St Denis ssize_t result = 0; 1376669e2f91STom St Denis int r; 1377669e2f91STom St Denis 1378669e2f91STom St Denis if (size & 0x3 || *pos & 0x3) 1379669e2f91STom St Denis return -EINVAL; 1380669e2f91STom St Denis 13814a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 13829eee152aSAlex Deucher if (r < 0) { 13834a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1384669e2f91STom St Denis return r; 13859eee152aSAlex Deucher } 1386669e2f91STom St Denis 1387669e2f91STom St Denis while (size) { 1388669e2f91STom St Denis uint32_t value; 1389669e2f91STom St Denis 1390669e2f91STom St Denis r = get_user(value, (uint32_t *)buf); 1391edadd6fcSAndré Almeida if (r) 1392edadd6fcSAndré Almeida goto out; 1393669e2f91STom St Denis 1394669e2f91STom St Denis amdgpu_gfx_off_ctrl(adev, value ? true : false); 1395669e2f91STom St Denis 1396669e2f91STom St Denis result += 4; 1397669e2f91STom St Denis buf += 4; 1398669e2f91STom St Denis *pos += 4; 1399669e2f91STom St Denis size -= 4; 1400669e2f91STom St Denis } 1401669e2f91STom St Denis 1402edadd6fcSAndré Almeida r = result; 1403edadd6fcSAndré Almeida out: 14044a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 14054a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1406669e2f91STom St Denis 1407edadd6fcSAndré Almeida return r; 1408669e2f91STom St Denis } 1409669e2f91STom St Denis 1410669e2f91STom St Denis 1411443c7f3cSJinzhou.Su /** 1412e72d4a8bSLee Jones * amdgpu_debugfs_gfxoff_read - read gfxoff status 1413443c7f3cSJinzhou.Su * 1414443c7f3cSJinzhou.Su * @f: open file handle 1415443c7f3cSJinzhou.Su * @buf: User buffer to store read data in 1416443c7f3cSJinzhou.Su * @size: Number of bytes to read 1417443c7f3cSJinzhou.Su * @pos: Offset to seek to 1418443c7f3cSJinzhou.Su */ 1419443c7f3cSJinzhou.Su static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, 1420443c7f3cSJinzhou.Su size_t size, loff_t *pos) 1421443c7f3cSJinzhou.Su { 1422443c7f3cSJinzhou.Su struct amdgpu_device *adev = file_inode(f)->i_private; 1423443c7f3cSJinzhou.Su ssize_t result = 0; 1424443c7f3cSJinzhou.Su int r; 1425443c7f3cSJinzhou.Su 1426443c7f3cSJinzhou.Su if (size & 0x3 || *pos & 0x3) 1427443c7f3cSJinzhou.Su return -EINVAL; 1428443c7f3cSJinzhou.Su 14294a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 14304bd8dd0dSYongzhi Liu if (r < 0) { 14314bd8dd0dSYongzhi Liu pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1432443c7f3cSJinzhou.Su return r; 14334bd8dd0dSYongzhi Liu } 1434443c7f3cSJinzhou.Su 1435443c7f3cSJinzhou.Su while (size) { 14364686177fSAndré Almeida u32 value = adev->gfx.gfx_off_state; 14374686177fSAndré Almeida 14384686177fSAndré Almeida r = put_user(value, (u32 *)buf); 14394686177fSAndré Almeida if (r) 14404686177fSAndré Almeida goto out; 14414686177fSAndré Almeida 14424686177fSAndré Almeida result += 4; 14434686177fSAndré Almeida buf += 4; 14444686177fSAndré Almeida *pos += 4; 14454686177fSAndré Almeida size -= 4; 14464686177fSAndré Almeida } 14474686177fSAndré Almeida 14484686177fSAndré Almeida r = result; 14494686177fSAndré Almeida out: 14504686177fSAndré Almeida pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 14514686177fSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 14524686177fSAndré Almeida 14534686177fSAndré Almeida return r; 14544686177fSAndré Almeida } 14554686177fSAndré Almeida 14564686177fSAndré Almeida static ssize_t amdgpu_debugfs_gfxoff_status_read(struct file *f, char __user *buf, 14574686177fSAndré Almeida size_t size, loff_t *pos) 14584686177fSAndré Almeida { 14594686177fSAndré Almeida struct amdgpu_device *adev = file_inode(f)->i_private; 14604686177fSAndré Almeida ssize_t result = 0; 14614686177fSAndré Almeida int r; 14624686177fSAndré Almeida 14634686177fSAndré Almeida if (size & 0x3 || *pos & 0x3) 14644686177fSAndré Almeida return -EINVAL; 14654686177fSAndré Almeida 14664686177fSAndré Almeida r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 14674686177fSAndré Almeida if (r < 0) { 14684686177fSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 14694686177fSAndré Almeida return r; 14704686177fSAndré Almeida } 14714686177fSAndré Almeida 14724686177fSAndré Almeida while (size) { 14734686177fSAndré Almeida u32 value; 1474443c7f3cSJinzhou.Su 1475443c7f3cSJinzhou.Su r = amdgpu_get_gfx_off_status(adev, &value); 1476edadd6fcSAndré Almeida if (r) 1477edadd6fcSAndré Almeida goto out; 1478443c7f3cSJinzhou.Su 14794686177fSAndré Almeida r = put_user(value, (u32 *)buf); 1480edadd6fcSAndré Almeida if (r) 1481edadd6fcSAndré Almeida goto out; 1482443c7f3cSJinzhou.Su 1483443c7f3cSJinzhou.Su result += 4; 1484443c7f3cSJinzhou.Su buf += 4; 1485443c7f3cSJinzhou.Su *pos += 4; 1486443c7f3cSJinzhou.Su size -= 4; 1487443c7f3cSJinzhou.Su } 1488443c7f3cSJinzhou.Su 1489edadd6fcSAndré Almeida r = result; 1490edadd6fcSAndré Almeida out: 14914a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 14924a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1493443c7f3cSJinzhou.Su 1494edadd6fcSAndré Almeida return r; 1495443c7f3cSJinzhou.Su } 1496443c7f3cSJinzhou.Su 149737df9560STom St Denis static const struct file_operations amdgpu_debugfs_regs2_fops = { 149837df9560STom St Denis .owner = THIS_MODULE, 149937df9560STom St Denis .unlocked_ioctl = amdgpu_debugfs_regs2_ioctl, 150037df9560STom St Denis .read = amdgpu_debugfs_regs2_read, 150137df9560STom St Denis .write = amdgpu_debugfs_regs2_write, 150237df9560STom St Denis .open = amdgpu_debugfs_regs2_open, 150337df9560STom St Denis .release = amdgpu_debugfs_regs2_release, 150437df9560STom St Denis .llseek = default_llseek 150537df9560STom St Denis }; 150637df9560STom St Denis 1507553f973aSTom St Denis static const struct file_operations amdgpu_debugfs_gprwave_fops = { 1508553f973aSTom St Denis .owner = THIS_MODULE, 1509553f973aSTom St Denis .unlocked_ioctl = amdgpu_debugfs_gprwave_ioctl, 1510553f973aSTom St Denis .read = amdgpu_debugfs_gprwave_read, 1511553f973aSTom St Denis .open = amdgpu_debugfs_gprwave_open, 1512553f973aSTom St Denis .release = amdgpu_debugfs_gprwave_release, 1513553f973aSTom St Denis .llseek = default_llseek 1514553f973aSTom St Denis }; 1515553f973aSTom St Denis 151675758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_fops = { 151775758255SAlex Deucher .owner = THIS_MODULE, 151875758255SAlex Deucher .read = amdgpu_debugfs_regs_read, 151975758255SAlex Deucher .write = amdgpu_debugfs_regs_write, 152075758255SAlex Deucher .llseek = default_llseek 152175758255SAlex Deucher }; 152275758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_didt_fops = { 152375758255SAlex Deucher .owner = THIS_MODULE, 152475758255SAlex Deucher .read = amdgpu_debugfs_regs_didt_read, 152575758255SAlex Deucher .write = amdgpu_debugfs_regs_didt_write, 152675758255SAlex Deucher .llseek = default_llseek 152775758255SAlex Deucher }; 152875758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_pcie_fops = { 152975758255SAlex Deucher .owner = THIS_MODULE, 153075758255SAlex Deucher .read = amdgpu_debugfs_regs_pcie_read, 153175758255SAlex Deucher .write = amdgpu_debugfs_regs_pcie_write, 153275758255SAlex Deucher .llseek = default_llseek 153375758255SAlex Deucher }; 153475758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_smc_fops = { 153575758255SAlex Deucher .owner = THIS_MODULE, 153675758255SAlex Deucher .read = amdgpu_debugfs_regs_smc_read, 153775758255SAlex Deucher .write = amdgpu_debugfs_regs_smc_write, 153875758255SAlex Deucher .llseek = default_llseek 153975758255SAlex Deucher }; 154075758255SAlex Deucher 154175758255SAlex Deucher static const struct file_operations amdgpu_debugfs_gca_config_fops = { 154275758255SAlex Deucher .owner = THIS_MODULE, 154375758255SAlex Deucher .read = amdgpu_debugfs_gca_config_read, 154475758255SAlex Deucher .llseek = default_llseek 154575758255SAlex Deucher }; 154675758255SAlex Deucher 154775758255SAlex Deucher static const struct file_operations amdgpu_debugfs_sensors_fops = { 154875758255SAlex Deucher .owner = THIS_MODULE, 154975758255SAlex Deucher .read = amdgpu_debugfs_sensor_read, 155075758255SAlex Deucher .llseek = default_llseek 155175758255SAlex Deucher }; 155275758255SAlex Deucher 155375758255SAlex Deucher static const struct file_operations amdgpu_debugfs_wave_fops = { 155475758255SAlex Deucher .owner = THIS_MODULE, 155575758255SAlex Deucher .read = amdgpu_debugfs_wave_read, 155675758255SAlex Deucher .llseek = default_llseek 155775758255SAlex Deucher }; 155875758255SAlex Deucher static const struct file_operations amdgpu_debugfs_gpr_fops = { 155975758255SAlex Deucher .owner = THIS_MODULE, 156075758255SAlex Deucher .read = amdgpu_debugfs_gpr_read, 156175758255SAlex Deucher .llseek = default_llseek 156275758255SAlex Deucher }; 156375758255SAlex Deucher 1564669e2f91STom St Denis static const struct file_operations amdgpu_debugfs_gfxoff_fops = { 1565669e2f91STom St Denis .owner = THIS_MODULE, 1566443c7f3cSJinzhou.Su .read = amdgpu_debugfs_gfxoff_read, 1567669e2f91STom St Denis .write = amdgpu_debugfs_gfxoff_write, 1568443c7f3cSJinzhou.Su .llseek = default_llseek 1569669e2f91STom St Denis }; 1570669e2f91STom St Denis 15714686177fSAndré Almeida static const struct file_operations amdgpu_debugfs_gfxoff_status_fops = { 15724686177fSAndré Almeida .owner = THIS_MODULE, 15734686177fSAndré Almeida .read = amdgpu_debugfs_gfxoff_status_read, 15744686177fSAndré Almeida .llseek = default_llseek 15754686177fSAndré Almeida }; 15764686177fSAndré Almeida 15770ad7347aSAndré Almeida static const struct file_operations amdgpu_debugfs_gfxoff_count_fops = { 15780ad7347aSAndré Almeida .owner = THIS_MODULE, 15790ad7347aSAndré Almeida .read = amdgpu_debugfs_gfxoff_count_read, 15800ad7347aSAndré Almeida .llseek = default_llseek 15810ad7347aSAndré Almeida }; 15820ad7347aSAndré Almeida 15830ad7347aSAndré Almeida static const struct file_operations amdgpu_debugfs_gfxoff_residency_fops = { 15840ad7347aSAndré Almeida .owner = THIS_MODULE, 15850ad7347aSAndré Almeida .read = amdgpu_debugfs_gfxoff_residency_read, 15860ad7347aSAndré Almeida .write = amdgpu_debugfs_gfxoff_residency_write, 15870ad7347aSAndré Almeida .llseek = default_llseek 15880ad7347aSAndré Almeida }; 15890ad7347aSAndré Almeida 159075758255SAlex Deucher static const struct file_operations *debugfs_regs[] = { 159175758255SAlex Deucher &amdgpu_debugfs_regs_fops, 159237df9560STom St Denis &amdgpu_debugfs_regs2_fops, 1593553f973aSTom St Denis &amdgpu_debugfs_gprwave_fops, 159475758255SAlex Deucher &amdgpu_debugfs_regs_didt_fops, 159575758255SAlex Deucher &amdgpu_debugfs_regs_pcie_fops, 159675758255SAlex Deucher &amdgpu_debugfs_regs_smc_fops, 159775758255SAlex Deucher &amdgpu_debugfs_gca_config_fops, 159875758255SAlex Deucher &amdgpu_debugfs_sensors_fops, 159975758255SAlex Deucher &amdgpu_debugfs_wave_fops, 160075758255SAlex Deucher &amdgpu_debugfs_gpr_fops, 1601669e2f91STom St Denis &amdgpu_debugfs_gfxoff_fops, 16024686177fSAndré Almeida &amdgpu_debugfs_gfxoff_status_fops, 16030ad7347aSAndré Almeida &amdgpu_debugfs_gfxoff_count_fops, 16040ad7347aSAndré Almeida &amdgpu_debugfs_gfxoff_residency_fops, 160575758255SAlex Deucher }; 160675758255SAlex Deucher 16078fa76350SSrinivasan Shanmugam static const char * const debugfs_regs_names[] = { 160875758255SAlex Deucher "amdgpu_regs", 160937df9560STom St Denis "amdgpu_regs2", 1610553f973aSTom St Denis "amdgpu_gprwave", 161175758255SAlex Deucher "amdgpu_regs_didt", 161275758255SAlex Deucher "amdgpu_regs_pcie", 161375758255SAlex Deucher "amdgpu_regs_smc", 161475758255SAlex Deucher "amdgpu_gca_config", 161575758255SAlex Deucher "amdgpu_sensors", 161675758255SAlex Deucher "amdgpu_wave", 161775758255SAlex Deucher "amdgpu_gpr", 1618669e2f91STom St Denis "amdgpu_gfxoff", 16194686177fSAndré Almeida "amdgpu_gfxoff_status", 16200ad7347aSAndré Almeida "amdgpu_gfxoff_count", 16210ad7347aSAndré Almeida "amdgpu_gfxoff_residency", 162275758255SAlex Deucher }; 162375758255SAlex Deucher 16247e4237dbSTom St Denis /** 16257e4237dbSTom St Denis * amdgpu_debugfs_regs_init - Initialize debugfs entries that provide 16267e4237dbSTom St Denis * register access. 16277e4237dbSTom St Denis * 16287e4237dbSTom St Denis * @adev: The device to attach the debugfs entries to 16297e4237dbSTom St Denis */ 163075758255SAlex Deucher int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) 163175758255SAlex Deucher { 16324a580877SLuben Tuikov struct drm_minor *minor = adev_to_drm(adev)->primary; 163375758255SAlex Deucher struct dentry *ent, *root = minor->debugfs_root; 1634d344b21bSDan Carpenter unsigned int i; 163575758255SAlex Deucher 163675758255SAlex Deucher for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) { 163775758255SAlex Deucher ent = debugfs_create_file(debugfs_regs_names[i], 16388fa76350SSrinivasan Shanmugam S_IFREG | 0444, root, 163975758255SAlex Deucher adev, debugfs_regs[i]); 1640d344b21bSDan Carpenter if (!i && !IS_ERR_OR_NULL(ent)) 164175758255SAlex Deucher i_size_write(ent->d_inode, adev->rmmio_size); 164275758255SAlex Deucher } 164375758255SAlex Deucher 164475758255SAlex Deucher return 0; 164575758255SAlex Deucher } 164675758255SAlex Deucher 164798d28ac2SNirmoy Das static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) 164875758255SAlex Deucher { 1649109b4d8cSSu Hui struct amdgpu_device *adev = m->private; 165098d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 165175758255SAlex Deucher int r = 0, i; 165275758255SAlex Deucher 1653a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 16549eee152aSAlex Deucher if (r < 0) { 165598d28ac2SNirmoy Das pm_runtime_put_autosuspend(dev->dev); 1656a9ffe2a9SAlex Deucher return r; 16579eee152aSAlex Deucher } 1658a9ffe2a9SAlex Deucher 1659a28fda31SAndrey Grodzovsky /* Avoid accidently unparking the sched thread during GPU reset */ 1660d0fb18b5SAndrey Grodzovsky r = down_write_killable(&adev->reset_domain->sem); 16616049db43SDennis Li if (r) 16626049db43SDennis Li return r; 1663a28fda31SAndrey Grodzovsky 166475758255SAlex Deucher /* hold on the scheduler */ 166575758255SAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 166675758255SAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 166775758255SAlex Deucher 166875758255SAlex Deucher if (!ring || !ring->sched.thread) 166975758255SAlex Deucher continue; 167075758255SAlex Deucher kthread_park(ring->sched.thread); 167175758255SAlex Deucher } 167275758255SAlex Deucher 16738fa76350SSrinivasan Shanmugam seq_puts(m, "run ib test:\n"); 167475758255SAlex Deucher r = amdgpu_ib_ring_tests(adev); 167575758255SAlex Deucher if (r) 167675758255SAlex Deucher seq_printf(m, "ib ring tests failed (%d).\n", r); 167775758255SAlex Deucher else 16788fa76350SSrinivasan Shanmugam seq_puts(m, "ib ring tests passed.\n"); 167975758255SAlex Deucher 168075758255SAlex Deucher /* go on the scheduler */ 168175758255SAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 168275758255SAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 168375758255SAlex Deucher 168475758255SAlex Deucher if (!ring || !ring->sched.thread) 168575758255SAlex Deucher continue; 168675758255SAlex Deucher kthread_unpark(ring->sched.thread); 168775758255SAlex Deucher } 168875758255SAlex Deucher 1689d0fb18b5SAndrey Grodzovsky up_write(&adev->reset_domain->sem); 1690a28fda31SAndrey Grodzovsky 1691a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1692a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1693a9ffe2a9SAlex Deucher 169475758255SAlex Deucher return 0; 169575758255SAlex Deucher } 169675758255SAlex Deucher 169798d28ac2SNirmoy Das static int amdgpu_debugfs_evict_vram(void *data, u64 *val) 169875758255SAlex Deucher { 169998d28ac2SNirmoy Das struct amdgpu_device *adev = (struct amdgpu_device *)data; 170098d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 1701a9ffe2a9SAlex Deucher int r; 1702a9ffe2a9SAlex Deucher 1703a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 17049eee152aSAlex Deucher if (r < 0) { 170598d28ac2SNirmoy Das pm_runtime_put_autosuspend(dev->dev); 1706a9ffe2a9SAlex Deucher return r; 17079eee152aSAlex Deucher } 170875758255SAlex Deucher 170958144d28SNirmoy Das *val = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM); 1710a9ffe2a9SAlex Deucher 1711a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1712a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1713a9ffe2a9SAlex Deucher 171475758255SAlex Deucher return 0; 171575758255SAlex Deucher } 171675758255SAlex Deucher 171798d28ac2SNirmoy Das 171898d28ac2SNirmoy Das static int amdgpu_debugfs_evict_gtt(void *data, u64 *val) 171987e90c76SChristian König { 172098d28ac2SNirmoy Das struct amdgpu_device *adev = (struct amdgpu_device *)data; 172198d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 1722a9ffe2a9SAlex Deucher int r; 1723a9ffe2a9SAlex Deucher 1724a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 17259eee152aSAlex Deucher if (r < 0) { 172658144d28SNirmoy Das pm_runtime_put_autosuspend(dev->dev); 1727a9ffe2a9SAlex Deucher return r; 17289eee152aSAlex Deucher } 172987e90c76SChristian König 173058144d28SNirmoy Das *val = amdgpu_ttm_evict_resources(adev, TTM_PL_TT); 1731a9ffe2a9SAlex Deucher 1732a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1733a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1734a9ffe2a9SAlex Deucher 173587e90c76SChristian König return 0; 173687e90c76SChristian König } 173787e90c76SChristian König 1738e7c47231SAlex Deucher static int amdgpu_debugfs_benchmark(void *data, u64 val) 1739e7c47231SAlex Deucher { 1740e7c47231SAlex Deucher struct amdgpu_device *adev = (struct amdgpu_device *)data; 1741e7c47231SAlex Deucher struct drm_device *dev = adev_to_drm(adev); 1742e7c47231SAlex Deucher int r; 1743e7c47231SAlex Deucher 1744e7c47231SAlex Deucher r = pm_runtime_get_sync(dev->dev); 1745e7c47231SAlex Deucher if (r < 0) { 1746e7c47231SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1747e7c47231SAlex Deucher return r; 1748e7c47231SAlex Deucher } 1749e7c47231SAlex Deucher 1750e7c47231SAlex Deucher r = amdgpu_benchmark(adev, val); 1751e7c47231SAlex Deucher 1752e7c47231SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1753e7c47231SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1754e7c47231SAlex Deucher 1755e7c47231SAlex Deucher return r; 1756e7c47231SAlex Deucher } 175798d28ac2SNirmoy Das 175898d28ac2SNirmoy Das static int amdgpu_debugfs_vm_info_show(struct seq_file *m, void *unused) 1759ff72bc40SMihir Bhogilal Patel { 1760109b4d8cSSu Hui struct amdgpu_device *adev = m->private; 176198d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 1762ff72bc40SMihir Bhogilal Patel struct drm_file *file; 1763ff72bc40SMihir Bhogilal Patel int r; 1764ff72bc40SMihir Bhogilal Patel 1765ff72bc40SMihir Bhogilal Patel r = mutex_lock_interruptible(&dev->filelist_mutex); 1766ff72bc40SMihir Bhogilal Patel if (r) 1767ff72bc40SMihir Bhogilal Patel return r; 1768ff72bc40SMihir Bhogilal Patel 1769ff72bc40SMihir Bhogilal Patel list_for_each_entry(file, &dev->filelist, lhead) { 1770ff72bc40SMihir Bhogilal Patel struct amdgpu_fpriv *fpriv = file->driver_priv; 1771ff72bc40SMihir Bhogilal Patel struct amdgpu_vm *vm = &fpriv->vm; 1772ff72bc40SMihir Bhogilal Patel 1773ff72bc40SMihir Bhogilal Patel seq_printf(m, "pid:%d\tProcess:%s ----------\n", 1774ff72bc40SMihir Bhogilal Patel vm->task_info.pid, vm->task_info.process_name); 1775391629bdSNirmoy Das r = amdgpu_bo_reserve(vm->root.bo, true); 1776ff72bc40SMihir Bhogilal Patel if (r) 1777ff72bc40SMihir Bhogilal Patel break; 1778ff72bc40SMihir Bhogilal Patel amdgpu_debugfs_vm_bo_info(vm, m); 1779391629bdSNirmoy Das amdgpu_bo_unreserve(vm->root.bo); 1780ff72bc40SMihir Bhogilal Patel } 1781ff72bc40SMihir Bhogilal Patel 1782ff72bc40SMihir Bhogilal Patel mutex_unlock(&dev->filelist_mutex); 1783ff72bc40SMihir Bhogilal Patel 1784ff72bc40SMihir Bhogilal Patel return r; 1785ff72bc40SMihir Bhogilal Patel } 1786ff72bc40SMihir Bhogilal Patel 178798d28ac2SNirmoy Das DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_test_ib); 178898d28ac2SNirmoy Das DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_vm_info); 178998d28ac2SNirmoy Das DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_vram_fops, amdgpu_debugfs_evict_vram, 179098d28ac2SNirmoy Das NULL, "%lld\n"); 179198d28ac2SNirmoy Das DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_gtt_fops, amdgpu_debugfs_evict_gtt, 179298d28ac2SNirmoy Das NULL, "%lld\n"); 1793e7c47231SAlex Deucher DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_benchmark_fops, NULL, amdgpu_debugfs_benchmark, 1794e7c47231SAlex Deucher "%lld\n"); 179575758255SAlex Deucher 17966698a3d0SJack Xiao static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring, 17976698a3d0SJack Xiao struct dma_fence **fences) 17986698a3d0SJack Xiao { 17996698a3d0SJack Xiao struct amdgpu_fence_driver *drv = &ring->fence_drv; 18006698a3d0SJack Xiao uint32_t sync_seq, last_seq; 18016698a3d0SJack Xiao 18026698a3d0SJack Xiao last_seq = atomic_read(&ring->fence_drv.last_seq); 18036698a3d0SJack Xiao sync_seq = ring->fence_drv.sync_seq; 18046698a3d0SJack Xiao 18056698a3d0SJack Xiao last_seq &= drv->num_fences_mask; 18066698a3d0SJack Xiao sync_seq &= drv->num_fences_mask; 18076698a3d0SJack Xiao 18086698a3d0SJack Xiao do { 18096698a3d0SJack Xiao struct dma_fence *fence, **ptr; 18106698a3d0SJack Xiao 18116698a3d0SJack Xiao ++last_seq; 18126698a3d0SJack Xiao last_seq &= drv->num_fences_mask; 18136698a3d0SJack Xiao ptr = &drv->fences[last_seq]; 18146698a3d0SJack Xiao 18156698a3d0SJack Xiao fence = rcu_dereference_protected(*ptr, 1); 18166698a3d0SJack Xiao RCU_INIT_POINTER(*ptr, NULL); 18176698a3d0SJack Xiao 18186698a3d0SJack Xiao if (!fence) 18196698a3d0SJack Xiao continue; 18206698a3d0SJack Xiao 18216698a3d0SJack Xiao fences[last_seq] = fence; 18226698a3d0SJack Xiao 18236698a3d0SJack Xiao } while (last_seq != sync_seq); 18246698a3d0SJack Xiao } 18256698a3d0SJack Xiao 18266698a3d0SJack Xiao static void amdgpu_ib_preempt_signal_fences(struct dma_fence **fences, 18276698a3d0SJack Xiao int length) 18286698a3d0SJack Xiao { 18296698a3d0SJack Xiao int i; 18306698a3d0SJack Xiao struct dma_fence *fence; 18316698a3d0SJack Xiao 18326698a3d0SJack Xiao for (i = 0; i < length; i++) { 18336698a3d0SJack Xiao fence = fences[i]; 18346698a3d0SJack Xiao if (!fence) 18356698a3d0SJack Xiao continue; 18366698a3d0SJack Xiao dma_fence_signal(fence); 18376698a3d0SJack Xiao dma_fence_put(fence); 18386698a3d0SJack Xiao } 18396698a3d0SJack Xiao } 18406698a3d0SJack Xiao 18416698a3d0SJack Xiao static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched) 18426698a3d0SJack Xiao { 18436698a3d0SJack Xiao struct drm_sched_job *s_job; 18446698a3d0SJack Xiao struct dma_fence *fence; 18456698a3d0SJack Xiao 18466698a3d0SJack Xiao spin_lock(&sched->job_list_lock); 18476efa4b46SLuben Tuikov list_for_each_entry(s_job, &sched->pending_list, list) { 18486698a3d0SJack Xiao fence = sched->ops->run_job(s_job); 18496698a3d0SJack Xiao dma_fence_put(fence); 18506698a3d0SJack Xiao } 18516698a3d0SJack Xiao spin_unlock(&sched->job_list_lock); 18526698a3d0SJack Xiao } 18536698a3d0SJack Xiao 185480f8fb91SJack Xiao static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring) 185580f8fb91SJack Xiao { 185680f8fb91SJack Xiao struct amdgpu_job *job; 18577bdb0899SJack Xiao struct drm_sched_job *s_job, *tmp; 185880f8fb91SJack Xiao uint32_t preempt_seq; 185980f8fb91SJack Xiao struct dma_fence *fence, **ptr; 186080f8fb91SJack Xiao struct amdgpu_fence_driver *drv = &ring->fence_drv; 186180f8fb91SJack Xiao struct drm_gpu_scheduler *sched = &ring->sched; 18627bdb0899SJack Xiao bool preempted = true; 186380f8fb91SJack Xiao 186480f8fb91SJack Xiao if (ring->funcs->type != AMDGPU_RING_TYPE_GFX) 186580f8fb91SJack Xiao return; 186680f8fb91SJack Xiao 186780f8fb91SJack Xiao preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2)); 18687bdb0899SJack Xiao if (preempt_seq <= atomic_read(&drv->last_seq)) { 18697bdb0899SJack Xiao preempted = false; 18707bdb0899SJack Xiao goto no_preempt; 18717bdb0899SJack Xiao } 187280f8fb91SJack Xiao 187380f8fb91SJack Xiao preempt_seq &= drv->num_fences_mask; 187480f8fb91SJack Xiao ptr = &drv->fences[preempt_seq]; 187580f8fb91SJack Xiao fence = rcu_dereference_protected(*ptr, 1); 187680f8fb91SJack Xiao 18777bdb0899SJack Xiao no_preempt: 187880f8fb91SJack Xiao spin_lock(&sched->job_list_lock); 18796efa4b46SLuben Tuikov list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) { 18807bdb0899SJack Xiao if (dma_fence_is_signaled(&s_job->s_fence->finished)) { 18817bdb0899SJack Xiao /* remove job from ring_mirror_list */ 18828935ff00SLuben Tuikov list_del_init(&s_job->list); 18837bdb0899SJack Xiao sched->ops->free_job(s_job); 18847bdb0899SJack Xiao continue; 18857bdb0899SJack Xiao } 188680f8fb91SJack Xiao job = to_amdgpu_job(s_job); 1887c530b02fSJack Zhang if (preempted && (&job->hw_fence) == fence) 188880f8fb91SJack Xiao /* mark the job as preempted */ 188980f8fb91SJack Xiao job->preemption_status |= AMDGPU_IB_PREEMPTED; 189080f8fb91SJack Xiao } 189180f8fb91SJack Xiao spin_unlock(&sched->job_list_lock); 189280f8fb91SJack Xiao } 189380f8fb91SJack Xiao 18946698a3d0SJack Xiao static int amdgpu_debugfs_ib_preempt(void *data, u64 val) 18956698a3d0SJack Xiao { 1896cd3a8a59SChristian König int r, length; 18976698a3d0SJack Xiao struct amdgpu_ring *ring; 18986698a3d0SJack Xiao struct dma_fence **fences = NULL; 18996698a3d0SJack Xiao struct amdgpu_device *adev = (struct amdgpu_device *)data; 19006698a3d0SJack Xiao 19016698a3d0SJack Xiao if (val >= AMDGPU_MAX_RINGS) 19026698a3d0SJack Xiao return -EINVAL; 19036698a3d0SJack Xiao 19046698a3d0SJack Xiao ring = adev->rings[val]; 19056698a3d0SJack Xiao 19066698a3d0SJack Xiao if (!ring || !ring->funcs->preempt_ib || !ring->sched.thread) 19076698a3d0SJack Xiao return -EINVAL; 19086698a3d0SJack Xiao 19096698a3d0SJack Xiao /* the last preemption failed */ 19106698a3d0SJack Xiao if (ring->trail_seq != le32_to_cpu(*ring->trail_fence_cpu_addr)) 19116698a3d0SJack Xiao return -EBUSY; 19126698a3d0SJack Xiao 19136698a3d0SJack Xiao length = ring->fence_drv.num_fences_mask + 1; 19146698a3d0SJack Xiao fences = kcalloc(length, sizeof(void *), GFP_KERNEL); 19156698a3d0SJack Xiao if (!fences) 19166698a3d0SJack Xiao return -ENOMEM; 19176698a3d0SJack Xiao 1918a28fda31SAndrey Grodzovsky /* Avoid accidently unparking the sched thread during GPU reset */ 1919d0fb18b5SAndrey Grodzovsky r = down_read_killable(&adev->reset_domain->sem); 19206049db43SDennis Li if (r) 19216049db43SDennis Li goto pro_end; 1922a28fda31SAndrey Grodzovsky 19236698a3d0SJack Xiao /* stop the scheduler */ 19246698a3d0SJack Xiao kthread_park(ring->sched.thread); 19256698a3d0SJack Xiao 19266698a3d0SJack Xiao /* preempt the IB */ 19276698a3d0SJack Xiao r = amdgpu_ring_preempt_ib(ring); 19286698a3d0SJack Xiao if (r) { 19296698a3d0SJack Xiao DRM_WARN("failed to preempt ring %d\n", ring->idx); 19306698a3d0SJack Xiao goto failure; 19316698a3d0SJack Xiao } 19326698a3d0SJack Xiao 19336698a3d0SJack Xiao amdgpu_fence_process(ring); 19346698a3d0SJack Xiao 19356698a3d0SJack Xiao if (atomic_read(&ring->fence_drv.last_seq) != 19366698a3d0SJack Xiao ring->fence_drv.sync_seq) { 19376698a3d0SJack Xiao DRM_INFO("ring %d was preempted\n", ring->idx); 19386698a3d0SJack Xiao 193980f8fb91SJack Xiao amdgpu_ib_preempt_mark_partial_job(ring); 194080f8fb91SJack Xiao 19416698a3d0SJack Xiao /* swap out the old fences */ 19426698a3d0SJack Xiao amdgpu_ib_preempt_fences_swap(ring, fences); 19436698a3d0SJack Xiao 19446698a3d0SJack Xiao amdgpu_fence_driver_force_completion(ring); 19456698a3d0SJack Xiao 19466698a3d0SJack Xiao /* resubmit unfinished jobs */ 19476698a3d0SJack Xiao amdgpu_ib_preempt_job_recovery(&ring->sched); 19486698a3d0SJack Xiao 19496698a3d0SJack Xiao /* wait for jobs finished */ 19506698a3d0SJack Xiao amdgpu_fence_wait_empty(ring); 19516698a3d0SJack Xiao 19526698a3d0SJack Xiao /* signal the old fences */ 19536698a3d0SJack Xiao amdgpu_ib_preempt_signal_fences(fences, length); 19546698a3d0SJack Xiao } 19556698a3d0SJack Xiao 19566698a3d0SJack Xiao failure: 19576698a3d0SJack Xiao /* restart the scheduler */ 19586698a3d0SJack Xiao kthread_unpark(ring->sched.thread); 19596698a3d0SJack Xiao 1960d0fb18b5SAndrey Grodzovsky up_read(&adev->reset_domain->sem); 1961a28fda31SAndrey Grodzovsky 19626049db43SDennis Li pro_end: 19636698a3d0SJack Xiao kfree(fences); 19646698a3d0SJack Xiao 19656049db43SDennis Li return r; 19666698a3d0SJack Xiao } 19676698a3d0SJack Xiao 19680cf64555SChengming Gui static int amdgpu_debugfs_sclk_set(void *data, u64 val) 19690cf64555SChengming Gui { 19700cf64555SChengming Gui int ret = 0; 19710cf64555SChengming Gui uint32_t max_freq, min_freq; 19720cf64555SChengming Gui struct amdgpu_device *adev = (struct amdgpu_device *)data; 19730cf64555SChengming Gui 19740cf64555SChengming Gui if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) 19750cf64555SChengming Gui return -EINVAL; 19760cf64555SChengming Gui 19774a580877SLuben Tuikov ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); 19789eee152aSAlex Deucher if (ret < 0) { 19794a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 19800cf64555SChengming Gui return ret; 19819eee152aSAlex Deucher } 19820cf64555SChengming Gui 1983bc143d8bSEvan Quan ret = amdgpu_dpm_get_dpm_freq_range(adev, PP_SCLK, &min_freq, &max_freq); 1984bc143d8bSEvan Quan if (ret == -EOPNOTSUPP) { 1985bc143d8bSEvan Quan ret = 0; 1986bc143d8bSEvan Quan goto out; 1987bc143d8bSEvan Quan } 1988bc143d8bSEvan Quan if (ret || val > max_freq || val < min_freq) { 1989bc143d8bSEvan Quan ret = -EINVAL; 1990bc143d8bSEvan Quan goto out; 19910cf64555SChengming Gui } 19920cf64555SChengming Gui 1993bc143d8bSEvan Quan ret = amdgpu_dpm_set_soft_freq_range(adev, PP_SCLK, (uint32_t)val, (uint32_t)val); 1994bc143d8bSEvan Quan if (ret) 1995bc143d8bSEvan Quan ret = -EINVAL; 1996bc143d8bSEvan Quan 1997bc143d8bSEvan Quan out: 19984a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 19994a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 20000cf64555SChengming Gui 2001bc143d8bSEvan Quan return ret; 20020cf64555SChengming Gui } 20030cf64555SChengming Gui 20047271a5c2SYang Li DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL, 20056698a3d0SJack Xiao amdgpu_debugfs_ib_preempt, "%llu\n"); 20066698a3d0SJack Xiao 20077271a5c2SYang Li DEFINE_DEBUGFS_ATTRIBUTE(fops_sclk_set, NULL, 20080cf64555SChengming Gui amdgpu_debugfs_sclk_set, "%llu\n"); 20090cf64555SChengming Gui 20105ce5a584SSomalapuram Amaranath static ssize_t amdgpu_reset_dump_register_list_read(struct file *f, 20115ce5a584SSomalapuram Amaranath char __user *buf, size_t size, loff_t *pos) 20125ce5a584SSomalapuram Amaranath { 20135ce5a584SSomalapuram Amaranath struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; 20145ce5a584SSomalapuram Amaranath char reg_offset[12]; 20155ce5a584SSomalapuram Amaranath int i, ret, len = 0; 20165ce5a584SSomalapuram Amaranath 20175ce5a584SSomalapuram Amaranath if (*pos) 20185ce5a584SSomalapuram Amaranath return 0; 20195ce5a584SSomalapuram Amaranath 20205ce5a584SSomalapuram Amaranath memset(reg_offset, 0, 12); 202138a15ad9SDave Airlie ret = down_read_killable(&adev->reset_domain->sem); 20225ce5a584SSomalapuram Amaranath if (ret) 20235ce5a584SSomalapuram Amaranath return ret; 20245ce5a584SSomalapuram Amaranath 20252d6a2a28SAndré Almeida for (i = 0; i < adev->reset_info.num_regs; i++) { 20262d6a2a28SAndré Almeida sprintf(reg_offset, "0x%x\n", adev->reset_info.reset_dump_reg_list[i]); 202738a15ad9SDave Airlie up_read(&adev->reset_domain->sem); 20285ce5a584SSomalapuram Amaranath if (copy_to_user(buf + len, reg_offset, strlen(reg_offset))) 20295ce5a584SSomalapuram Amaranath return -EFAULT; 20305ce5a584SSomalapuram Amaranath 20315ce5a584SSomalapuram Amaranath len += strlen(reg_offset); 203238a15ad9SDave Airlie ret = down_read_killable(&adev->reset_domain->sem); 20335ce5a584SSomalapuram Amaranath if (ret) 20345ce5a584SSomalapuram Amaranath return ret; 20355ce5a584SSomalapuram Amaranath } 20365ce5a584SSomalapuram Amaranath 203738a15ad9SDave Airlie up_read(&adev->reset_domain->sem); 20385ce5a584SSomalapuram Amaranath *pos += len; 20395ce5a584SSomalapuram Amaranath 20405ce5a584SSomalapuram Amaranath return len; 20415ce5a584SSomalapuram Amaranath } 20425ce5a584SSomalapuram Amaranath 20435ce5a584SSomalapuram Amaranath static ssize_t amdgpu_reset_dump_register_list_write(struct file *f, 20445ce5a584SSomalapuram Amaranath const char __user *buf, size_t size, loff_t *pos) 20455ce5a584SSomalapuram Amaranath { 20465ce5a584SSomalapuram Amaranath struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; 20475ce5a584SSomalapuram Amaranath char reg_offset[11]; 2048ad2feebdSSebin Sebastian uint32_t *new = NULL, *tmp = NULL; 20495ce5a584SSomalapuram Amaranath int ret, i = 0, len = 0; 20505ce5a584SSomalapuram Amaranath 20515ce5a584SSomalapuram Amaranath do { 20525ce5a584SSomalapuram Amaranath memset(reg_offset, 0, 11); 20535ce5a584SSomalapuram Amaranath if (copy_from_user(reg_offset, buf + len, 20545ce5a584SSomalapuram Amaranath min(10, ((int)size-len)))) { 20555ce5a584SSomalapuram Amaranath ret = -EFAULT; 20565ce5a584SSomalapuram Amaranath goto error_free; 20575ce5a584SSomalapuram Amaranath } 20585ce5a584SSomalapuram Amaranath 2059ca6fcfa8STom Rix new = krealloc_array(tmp, i + 1, sizeof(uint32_t), GFP_KERNEL); 2060ca6fcfa8STom Rix if (!new) { 2061ca6fcfa8STom Rix ret = -ENOMEM; 2062ca6fcfa8STom Rix goto error_free; 2063ca6fcfa8STom Rix } 2064ca6fcfa8STom Rix tmp = new; 20655ce5a584SSomalapuram Amaranath if (sscanf(reg_offset, "%X %n", &tmp[i], &ret) != 1) { 20665ce5a584SSomalapuram Amaranath ret = -EINVAL; 20675ce5a584SSomalapuram Amaranath goto error_free; 20685ce5a584SSomalapuram Amaranath } 20695ce5a584SSomalapuram Amaranath 20705ce5a584SSomalapuram Amaranath len += ret; 20715ce5a584SSomalapuram Amaranath i++; 20725ce5a584SSomalapuram Amaranath } while (len < size); 20735ce5a584SSomalapuram Amaranath 2074651d7ee6SSomalapuram Amaranath new = kmalloc_array(i, sizeof(uint32_t), GFP_KERNEL); 2075651d7ee6SSomalapuram Amaranath if (!new) { 2076651d7ee6SSomalapuram Amaranath ret = -ENOMEM; 2077651d7ee6SSomalapuram Amaranath goto error_free; 2078651d7ee6SSomalapuram Amaranath } 207938a15ad9SDave Airlie ret = down_write_killable(&adev->reset_domain->sem); 20805ce5a584SSomalapuram Amaranath if (ret) 20815ce5a584SSomalapuram Amaranath goto error_free; 20825ce5a584SSomalapuram Amaranath 20832d6a2a28SAndré Almeida swap(adev->reset_info.reset_dump_reg_list, tmp); 20842d6a2a28SAndré Almeida swap(adev->reset_info.reset_dump_reg_value, new); 20852d6a2a28SAndré Almeida adev->reset_info.num_regs = i; 208638a15ad9SDave Airlie up_write(&adev->reset_domain->sem); 20875ce5a584SSomalapuram Amaranath ret = size; 20885ce5a584SSomalapuram Amaranath 20895ce5a584SSomalapuram Amaranath error_free: 2090ad2feebdSSebin Sebastian if (tmp != new) 20915ce5a584SSomalapuram Amaranath kfree(tmp); 2092651d7ee6SSomalapuram Amaranath kfree(new); 20935ce5a584SSomalapuram Amaranath return ret; 20945ce5a584SSomalapuram Amaranath } 20955ce5a584SSomalapuram Amaranath 20965ce5a584SSomalapuram Amaranath static const struct file_operations amdgpu_reset_dump_register_list = { 20975ce5a584SSomalapuram Amaranath .owner = THIS_MODULE, 20985ce5a584SSomalapuram Amaranath .read = amdgpu_reset_dump_register_list_read, 20995ce5a584SSomalapuram Amaranath .write = amdgpu_reset_dump_register_list_write, 21005ce5a584SSomalapuram Amaranath .llseek = default_llseek 21015ce5a584SSomalapuram Amaranath }; 21025ce5a584SSomalapuram Amaranath 210375758255SAlex Deucher int amdgpu_debugfs_init(struct amdgpu_device *adev) 210475758255SAlex Deucher { 210598d28ac2SNirmoy Das struct dentry *root = adev_to_drm(adev)->primary->debugfs_root; 210688293c03SNirmoy Das struct dentry *ent; 2107fd23cfccSAlex Deucher int r, i; 2108c5820361SAlex Deucher 21095b9581dfSNirmoy Das if (!debugfs_initialized()) 21105b9581dfSNirmoy Das return 0; 21115b9581dfSNirmoy Das 21126ff7fddbSLang Yu debugfs_create_x32("amdgpu_smu_debug", 0600, root, 21137e31a858SEvan Quan &adev->pm.smu_debug_mask); 21146ff7fddbSLang Yu 211598d28ac2SNirmoy Das ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev, 211644b582b3SGeert Uytterhoeven &fops_ib_preempt); 211759715cffSNirmoy Das if (IS_ERR(ent)) { 21186698a3d0SJack Xiao DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); 211959715cffSNirmoy Das return PTR_ERR(ent); 21206698a3d0SJack Xiao } 21216698a3d0SJack Xiao 212298d28ac2SNirmoy Das ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev, 21230cf64555SChengming Gui &fops_sclk_set); 212459715cffSNirmoy Das if (IS_ERR(ent)) { 21250cf64555SChengming Gui DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); 212659715cffSNirmoy Das return PTR_ERR(ent); 21270cf64555SChengming Gui } 21280cf64555SChengming Gui 2129c5820361SAlex Deucher /* Register debugfs entries for amdgpu_ttm */ 213098d28ac2SNirmoy Das amdgpu_ttm_debugfs_init(adev); 2131373720f7SNirmoy Das amdgpu_debugfs_pm_init(adev); 213298d28ac2SNirmoy Das amdgpu_debugfs_sa_init(adev); 213398d28ac2SNirmoy Das amdgpu_debugfs_fence_init(adev); 213498d28ac2SNirmoy Das amdgpu_debugfs_gem_init(adev); 21353f5cea67SAlex Deucher 2136f9d64e6cSAlex Deucher r = amdgpu_debugfs_regs_init(adev); 2137f9d64e6cSAlex Deucher if (r) 2138f9d64e6cSAlex Deucher DRM_ERROR("registering register debugfs failed (%d).\n", r); 2139f9d64e6cSAlex Deucher 214098d28ac2SNirmoy Das amdgpu_debugfs_firmware_init(adev); 2141e50d9ba0SCandice Li amdgpu_ta_if_debugfs_init(adev); 2142cd9e29e7SAlex Deucher 2143d090e7dbSAlex Deucher #if defined(CONFIG_DRM_AMD_DC) 2144d09ef243SAlex Deucher if (adev->dc_enabled) 2145afd3a359SNirmoy Das dtn_debugfs_init(adev); 2146d090e7dbSAlex Deucher #endif 2147d090e7dbSAlex Deucher 2148fd23cfccSAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { 2149fd23cfccSAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 2150fd23cfccSAlex Deucher 2151fd23cfccSAlex Deucher if (!ring) 2152fd23cfccSAlex Deucher continue; 2153fd23cfccSAlex Deucher 215462d266b2SNirmoy Das amdgpu_debugfs_ring_init(adev, ring); 2155fd23cfccSAlex Deucher } 2156fd23cfccSAlex Deucher 215711eb648dSRuijing Dong for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 215811eb648dSRuijing Dong if (!amdgpu_vcnfw_log) 215911eb648dSRuijing Dong break; 216011eb648dSRuijing Dong 216111eb648dSRuijing Dong if (adev->vcn.harvest_config & (1 << i)) 216211eb648dSRuijing Dong continue; 216311eb648dSRuijing Dong 216411eb648dSRuijing Dong amdgpu_debugfs_vcn_fwlog_init(adev, i, &adev->vcn.inst[i]); 216511eb648dSRuijing Dong } 216611eb648dSRuijing Dong 2167204eaac6STao Zhou amdgpu_ras_debugfs_create_all(adev); 2168a4322e18SWenhui Sheng amdgpu_rap_debugfs_init(adev); 2169ecaafb7bSJinzhou Su amdgpu_securedisplay_debugfs_init(adev); 217019ae3330SJohn Clements amdgpu_fw_attestation_debugfs_init(adev); 217119ae3330SJohn Clements 217298d28ac2SNirmoy Das debugfs_create_file("amdgpu_evict_vram", 0444, root, adev, 217398d28ac2SNirmoy Das &amdgpu_evict_vram_fops); 217498d28ac2SNirmoy Das debugfs_create_file("amdgpu_evict_gtt", 0444, root, adev, 217598d28ac2SNirmoy Das &amdgpu_evict_gtt_fops); 217698d28ac2SNirmoy Das debugfs_create_file("amdgpu_test_ib", 0444, root, adev, 217798d28ac2SNirmoy Das &amdgpu_debugfs_test_ib_fops); 217898d28ac2SNirmoy Das debugfs_create_file("amdgpu_vm_info", 0444, root, adev, 217998d28ac2SNirmoy Das &amdgpu_debugfs_vm_info_fops); 2180e7c47231SAlex Deucher debugfs_create_file("amdgpu_benchmark", 0200, root, adev, 2181e7c47231SAlex Deucher &amdgpu_benchmark_fops); 21825ce5a584SSomalapuram Amaranath debugfs_create_file("amdgpu_reset_dump_register_list", 0644, root, adev, 21835ce5a584SSomalapuram Amaranath &amdgpu_reset_dump_register_list); 218498d28ac2SNirmoy Das 218598d28ac2SNirmoy Das adev->debugfs_vbios_blob.data = adev->bios; 218698d28ac2SNirmoy Das adev->debugfs_vbios_blob.size = adev->bios_size; 218798d28ac2SNirmoy Das debugfs_create_blob("amdgpu_vbios", 0444, root, 218898d28ac2SNirmoy Das &adev->debugfs_vbios_blob); 218998d28ac2SNirmoy Das 219081d1bf01SAlex Deucher adev->debugfs_discovery_blob.data = adev->mman.discovery_bin; 219181d1bf01SAlex Deucher adev->debugfs_discovery_blob.size = adev->mman.discovery_tmr_size; 219281d1bf01SAlex Deucher debugfs_create_blob("amdgpu_discovery", 0444, root, 219381d1bf01SAlex Deucher &adev->debugfs_discovery_blob); 219481d1bf01SAlex Deucher 219598d28ac2SNirmoy Das return 0; 219675758255SAlex Deucher } 219775758255SAlex Deucher 219875758255SAlex Deucher #else 219975758255SAlex Deucher int amdgpu_debugfs_init(struct amdgpu_device *adev) 220075758255SAlex Deucher { 220175758255SAlex Deucher return 0; 220275758255SAlex Deucher } 220375758255SAlex Deucher int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) 220475758255SAlex Deucher { 220575758255SAlex Deucher return 0; 220675758255SAlex Deucher } 220775758255SAlex Deucher #endif 2208