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 75175758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 75275758255SAlex Deucher return -EINVAL; 75375758255SAlex Deucher 7544a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 7559eee152aSAlex Deucher if (r < 0) { 7564a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 757a9ffe2a9SAlex Deucher return r; 7589eee152aSAlex Deucher } 759a9ffe2a9SAlex Deucher 76095a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 7619eee152aSAlex Deucher if (r < 0) { 7624a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 76395a2f917SYintian Tao return r; 7649eee152aSAlex Deucher } 76595a2f917SYintian Tao 76675758255SAlex Deucher while (size) { 76775758255SAlex Deucher uint32_t value; 76875758255SAlex Deucher 76975758255SAlex Deucher value = RREG32_SMC(*pos); 77075758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 771edadd6fcSAndré Almeida if (r) 772edadd6fcSAndré Almeida goto out; 77375758255SAlex Deucher 77475758255SAlex Deucher result += 4; 77575758255SAlex Deucher buf += 4; 77675758255SAlex Deucher *pos += 4; 77775758255SAlex Deucher size -= 4; 77875758255SAlex Deucher } 77975758255SAlex Deucher 780edadd6fcSAndré Almeida r = result; 781edadd6fcSAndré Almeida out: 7824a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 7834a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 78495a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 785edadd6fcSAndré Almeida return r; 78675758255SAlex Deucher } 78775758255SAlex Deucher 7887e4237dbSTom St Denis /** 7897e4237dbSTom St Denis * amdgpu_debugfs_regs_smc_write - Write to a SMC register 7907e4237dbSTom St Denis * 7917e4237dbSTom St Denis * @f: open file handle 7927e4237dbSTom St Denis * @buf: User buffer to write data from 7937e4237dbSTom St Denis * @size: Number of bytes to write 7947e4237dbSTom St Denis * @pos: Offset to seek to 7957e4237dbSTom St Denis * 7967e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 7977e4237dbSTom St Denis * allows writing multiple registers in a single call and having 7987e4237dbSTom St Denis * the returned size reflect that. 7997e4237dbSTom St Denis */ 80075758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf, 80175758255SAlex Deucher size_t size, loff_t *pos) 80275758255SAlex Deucher { 80375758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 80475758255SAlex Deucher ssize_t result = 0; 80575758255SAlex Deucher int r; 80675758255SAlex Deucher 80775758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 80875758255SAlex Deucher return -EINVAL; 80975758255SAlex Deucher 8104a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 8119eee152aSAlex Deucher if (r < 0) { 8124a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 813a9ffe2a9SAlex Deucher return r; 8149eee152aSAlex Deucher } 815a9ffe2a9SAlex Deucher 81695a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 8179eee152aSAlex Deucher if (r < 0) { 8184a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 81995a2f917SYintian Tao return r; 8209eee152aSAlex Deucher } 82195a2f917SYintian Tao 82275758255SAlex Deucher while (size) { 82375758255SAlex Deucher uint32_t value; 82475758255SAlex Deucher 82575758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 826edadd6fcSAndré Almeida if (r) 827edadd6fcSAndré Almeida goto out; 82875758255SAlex Deucher 82975758255SAlex Deucher WREG32_SMC(*pos, value); 83075758255SAlex Deucher 83175758255SAlex Deucher result += 4; 83275758255SAlex Deucher buf += 4; 83375758255SAlex Deucher *pos += 4; 83475758255SAlex Deucher size -= 4; 83575758255SAlex Deucher } 83675758255SAlex Deucher 837edadd6fcSAndré Almeida r = result; 838edadd6fcSAndré Almeida out: 8394a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 8404a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 84195a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 842edadd6fcSAndré Almeida return r; 84375758255SAlex Deucher } 84475758255SAlex Deucher 8457e4237dbSTom St Denis /** 8467e4237dbSTom St Denis * amdgpu_debugfs_gca_config_read - Read from gfx config data 8477e4237dbSTom St Denis * 8487e4237dbSTom St Denis * @f: open file handle 8497e4237dbSTom St Denis * @buf: User buffer to store read data in 8507e4237dbSTom St Denis * @size: Number of bytes to read 8517e4237dbSTom St Denis * @pos: Offset to seek to 8527e4237dbSTom St Denis * 8537e4237dbSTom St Denis * This file is used to access configuration data in a somewhat 8547e4237dbSTom St Denis * stable fashion. The format is a series of DWORDs with the first 8557e4237dbSTom St Denis * indicating which revision it is. New content is appended to the 8567e4237dbSTom St Denis * end so that older software can still read the data. 8577e4237dbSTom St Denis */ 8587e4237dbSTom St Denis 85975758255SAlex Deucher static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, 86075758255SAlex Deucher size_t size, loff_t *pos) 86175758255SAlex Deucher { 86275758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 86375758255SAlex Deucher ssize_t result = 0; 86475758255SAlex Deucher int r; 86575758255SAlex Deucher uint32_t *config, no_regs = 0; 86675758255SAlex Deucher 86775758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 86875758255SAlex Deucher return -EINVAL; 86975758255SAlex Deucher 87075758255SAlex Deucher config = kmalloc_array(256, sizeof(*config), GFP_KERNEL); 87175758255SAlex Deucher if (!config) 87275758255SAlex Deucher return -ENOMEM; 87375758255SAlex Deucher 87475758255SAlex Deucher /* version, increment each time something is added */ 875dc2947b3STom St Denis config[no_regs++] = 5; 87675758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_shader_engines; 87775758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_tile_pipes; 87875758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_cu_per_sh; 87975758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_sh_per_se; 88075758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_backends_per_se; 88175758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_texture_channel_caches; 88275758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_gprs; 88375758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_gs_threads; 88475758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_hw_contexts; 88575758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_frontend; 88675758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_backend; 88775758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_hiz_tile_fifo_size; 88875758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_earlyz_tile_fifo_size; 88975758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_tile_pipes; 89075758255SAlex Deucher config[no_regs++] = adev->gfx.config.backend_enable_mask; 89175758255SAlex Deucher config[no_regs++] = adev->gfx.config.mem_max_burst_length_bytes; 89275758255SAlex Deucher config[no_regs++] = adev->gfx.config.mem_row_size_in_kb; 89375758255SAlex Deucher config[no_regs++] = adev->gfx.config.shader_engine_tile_size; 89475758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_gpus; 89575758255SAlex Deucher config[no_regs++] = adev->gfx.config.multi_gpu_tile_size; 89675758255SAlex Deucher config[no_regs++] = adev->gfx.config.mc_arb_ramcfg; 89775758255SAlex Deucher config[no_regs++] = adev->gfx.config.gb_addr_config; 89875758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_rbs; 89975758255SAlex Deucher 90075758255SAlex Deucher /* rev==1 */ 90175758255SAlex Deucher config[no_regs++] = adev->rev_id; 902dc2947b3STom St Denis config[no_regs++] = lower_32_bits(adev->pg_flags); 90325faeddcSEvan Quan config[no_regs++] = lower_32_bits(adev->cg_flags); 90475758255SAlex Deucher 90575758255SAlex Deucher /* rev==2 */ 90675758255SAlex Deucher config[no_regs++] = adev->family; 90775758255SAlex Deucher config[no_regs++] = adev->external_rev_id; 90875758255SAlex Deucher 90975758255SAlex Deucher /* rev==3 */ 91075758255SAlex Deucher config[no_regs++] = adev->pdev->device; 91175758255SAlex Deucher config[no_regs++] = adev->pdev->revision; 91275758255SAlex Deucher config[no_regs++] = adev->pdev->subsystem_device; 91375758255SAlex Deucher config[no_regs++] = adev->pdev->subsystem_vendor; 91475758255SAlex Deucher 9158f74f68dSTom St Denis /* rev==4 APU flag */ 9168f74f68dSTom St Denis config[no_regs++] = adev->flags & AMD_IS_APU ? 1 : 0; 9178f74f68dSTom St Denis 918dc2947b3STom St Denis /* rev==5 PG/CG flag upper 32bit */ 919dc2947b3STom St Denis config[no_regs++] = upper_32_bits(adev->pg_flags); 92025faeddcSEvan Quan config[no_regs++] = upper_32_bits(adev->cg_flags); 92125faeddcSEvan Quan 92275758255SAlex Deucher while (size && (*pos < no_regs * 4)) { 92375758255SAlex Deucher uint32_t value; 92475758255SAlex Deucher 92575758255SAlex Deucher value = config[*pos >> 2]; 92675758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 92775758255SAlex Deucher if (r) { 92875758255SAlex Deucher kfree(config); 92975758255SAlex Deucher return r; 93075758255SAlex Deucher } 93175758255SAlex Deucher 93275758255SAlex Deucher result += 4; 93375758255SAlex Deucher buf += 4; 93475758255SAlex Deucher *pos += 4; 93575758255SAlex Deucher size -= 4; 93675758255SAlex Deucher } 93775758255SAlex Deucher 93875758255SAlex Deucher kfree(config); 93975758255SAlex Deucher return result; 94075758255SAlex Deucher } 94175758255SAlex Deucher 9427e4237dbSTom St Denis /** 9437e4237dbSTom St Denis * amdgpu_debugfs_sensor_read - Read from the powerplay sensors 9447e4237dbSTom St Denis * 9457e4237dbSTom St Denis * @f: open file handle 9467e4237dbSTom St Denis * @buf: User buffer to store read data in 9477e4237dbSTom St Denis * @size: Number of bytes to read 9487e4237dbSTom St Denis * @pos: Offset to seek to 9497e4237dbSTom St Denis * 9507e4237dbSTom St Denis * The offset is treated as the BYTE address of one of the sensors 9517e4237dbSTom St Denis * enumerated in amd/include/kgd_pp_interface.h under the 9527e4237dbSTom St Denis * 'amd_pp_sensors' enumeration. For instance to read the UVD VCLK 9537e4237dbSTom St Denis * you would use the offset 3 * 4 = 12. 9547e4237dbSTom St Denis */ 95575758255SAlex Deucher static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, 95675758255SAlex Deucher size_t size, loff_t *pos) 95775758255SAlex Deucher { 95875758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 95975758255SAlex Deucher int idx, x, outsize, r, valuesize; 96075758255SAlex Deucher uint32_t values[16]; 96175758255SAlex Deucher 96275758255SAlex Deucher if (size & 3 || *pos & 0x3) 96375758255SAlex Deucher return -EINVAL; 96475758255SAlex Deucher 965b13aa109SRex Zhu if (!adev->pm.dpm_enabled) 96675758255SAlex Deucher return -EINVAL; 96775758255SAlex Deucher 96875758255SAlex Deucher /* convert offset to sensor number */ 96975758255SAlex Deucher idx = *pos >> 2; 97075758255SAlex Deucher 97175758255SAlex Deucher valuesize = sizeof(values); 972a9ffe2a9SAlex Deucher 9734a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 9749eee152aSAlex Deucher if (r < 0) { 9754a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 976a9ffe2a9SAlex Deucher return r; 9779eee152aSAlex Deucher } 978a9ffe2a9SAlex Deucher 97995a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 9809eee152aSAlex Deucher if (r < 0) { 9814a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 98295a2f917SYintian Tao return r; 9839eee152aSAlex Deucher } 98495a2f917SYintian Tao 98575758255SAlex Deucher r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize); 986a9ffe2a9SAlex Deucher 9874a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 9884a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 989a9ffe2a9SAlex Deucher 99095a2f917SYintian Tao if (r) { 99195a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 9924a5a2de6SKevin Wang return r; 99395a2f917SYintian Tao } 99475758255SAlex Deucher 99595a2f917SYintian Tao if (size > valuesize) { 99695a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 99775758255SAlex Deucher return -EINVAL; 99895a2f917SYintian Tao } 99975758255SAlex Deucher 100075758255SAlex Deucher outsize = 0; 100175758255SAlex Deucher x = 0; 100275758255SAlex Deucher if (!r) { 100375758255SAlex Deucher while (size) { 100475758255SAlex Deucher r = put_user(values[x++], (int32_t *)buf); 100575758255SAlex Deucher buf += 4; 100675758255SAlex Deucher size -= 4; 100775758255SAlex Deucher outsize += 4; 100875758255SAlex Deucher } 100975758255SAlex Deucher } 101075758255SAlex Deucher 101195a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 101275758255SAlex Deucher return !r ? outsize : r; 101375758255SAlex Deucher } 101475758255SAlex Deucher 10157e4237dbSTom St Denis /** amdgpu_debugfs_wave_read - Read WAVE STATUS data 10167e4237dbSTom St Denis * 10177e4237dbSTom St Denis * @f: open file handle 10187e4237dbSTom St Denis * @buf: User buffer to store read data in 10197e4237dbSTom St Denis * @size: Number of bytes to read 10207e4237dbSTom St Denis * @pos: Offset to seek to 10217e4237dbSTom St Denis * 10227e4237dbSTom St Denis * The offset being sought changes which wave that the status data 10237e4237dbSTom St Denis * will be returned for. The bits are used as follows: 10247e4237dbSTom St Denis * 10257e4237dbSTom St Denis * Bits 0..6: Byte offset into data 10267e4237dbSTom St Denis * Bits 7..14: SE selector 10277e4237dbSTom St Denis * Bits 15..22: SH/SA selector 10287e4237dbSTom St Denis * Bits 23..30: CU/{WGP+SIMD} selector 10297e4237dbSTom St Denis * Bits 31..36: WAVE ID selector 10307e4237dbSTom St Denis * Bits 37..44: SIMD ID selector 10317e4237dbSTom St Denis * 10327e4237dbSTom St Denis * The returned data begins with one DWORD of version information 10337e4237dbSTom St Denis * Followed by WAVE STATUS registers relevant to the GFX IP version 10347e4237dbSTom St Denis * being used. See gfx_v8_0_read_wave_data() for an example output. 10357e4237dbSTom St Denis */ 103675758255SAlex Deucher static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, 103775758255SAlex Deucher size_t size, loff_t *pos) 103875758255SAlex Deucher { 103975758255SAlex Deucher struct amdgpu_device *adev = f->f_inode->i_private; 104075758255SAlex Deucher int r, x; 104175758255SAlex Deucher ssize_t result = 0; 104275758255SAlex Deucher uint32_t offset, se, sh, cu, wave, simd, data[32]; 104375758255SAlex Deucher 104475758255SAlex Deucher if (size & 3 || *pos & 3) 104575758255SAlex Deucher return -EINVAL; 104675758255SAlex Deucher 104775758255SAlex Deucher /* decode offset */ 104875758255SAlex Deucher offset = (*pos & GENMASK_ULL(6, 0)); 104975758255SAlex Deucher se = (*pos & GENMASK_ULL(14, 7)) >> 7; 105075758255SAlex Deucher sh = (*pos & GENMASK_ULL(22, 15)) >> 15; 105175758255SAlex Deucher cu = (*pos & GENMASK_ULL(30, 23)) >> 23; 105275758255SAlex Deucher wave = (*pos & GENMASK_ULL(36, 31)) >> 31; 105375758255SAlex Deucher simd = (*pos & GENMASK_ULL(44, 37)) >> 37; 105475758255SAlex Deucher 10554a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 10569eee152aSAlex Deucher if (r < 0) { 10574a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1058a9ffe2a9SAlex Deucher return r; 10599eee152aSAlex Deucher } 1060a9ffe2a9SAlex Deucher 106195a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 10629eee152aSAlex Deucher if (r < 0) { 10634a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 106495a2f917SYintian Tao return r; 10659eee152aSAlex Deucher } 106695a2f917SYintian Tao 106775758255SAlex Deucher /* switch to the specific se/sh/cu */ 106875758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 1069d51ac6d0SLe Ma amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0); 107075758255SAlex Deucher 107175758255SAlex Deucher x = 0; 107275758255SAlex Deucher if (adev->gfx.funcs->read_wave_data) 1073553f973aSTom St Denis adev->gfx.funcs->read_wave_data(adev, 0, simd, wave, data, &x); 107475758255SAlex Deucher 1075d51ac6d0SLe Ma amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0); 107675758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 107775758255SAlex Deucher 10784a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 10794a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1080a9ffe2a9SAlex Deucher 108195a2f917SYintian Tao if (!x) { 108295a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 108375758255SAlex Deucher return -EINVAL; 108495a2f917SYintian Tao } 108575758255SAlex Deucher 108675758255SAlex Deucher while (size && (offset < x * 4)) { 108775758255SAlex Deucher uint32_t value; 108875758255SAlex Deucher 108975758255SAlex Deucher value = data[offset >> 2]; 109075758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 109195a2f917SYintian Tao if (r) { 109295a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 109375758255SAlex Deucher return r; 109495a2f917SYintian Tao } 109575758255SAlex Deucher 109675758255SAlex Deucher result += 4; 109775758255SAlex Deucher buf += 4; 109875758255SAlex Deucher offset += 4; 109975758255SAlex Deucher size -= 4; 110075758255SAlex Deucher } 110175758255SAlex Deucher 110295a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 110375758255SAlex Deucher return result; 110475758255SAlex Deucher } 110575758255SAlex Deucher 11067e4237dbSTom St Denis /** amdgpu_debugfs_gpr_read - Read wave gprs 11077e4237dbSTom St Denis * 11087e4237dbSTom St Denis * @f: open file handle 11097e4237dbSTom St Denis * @buf: User buffer to store read data in 11107e4237dbSTom St Denis * @size: Number of bytes to read 11117e4237dbSTom St Denis * @pos: Offset to seek to 11127e4237dbSTom St Denis * 11137e4237dbSTom St Denis * The offset being sought changes which wave that the status data 11147e4237dbSTom St Denis * will be returned for. The bits are used as follows: 11157e4237dbSTom St Denis * 11167e4237dbSTom St Denis * Bits 0..11: Byte offset into data 11177e4237dbSTom St Denis * Bits 12..19: SE selector 11187e4237dbSTom St Denis * Bits 20..27: SH/SA selector 11197e4237dbSTom St Denis * Bits 28..35: CU/{WGP+SIMD} selector 11207e4237dbSTom St Denis * Bits 36..43: WAVE ID selector 11217e4237dbSTom St Denis * Bits 37..44: SIMD ID selector 11227e4237dbSTom St Denis * Bits 52..59: Thread selector 11237e4237dbSTom St Denis * Bits 60..61: Bank selector (VGPR=0,SGPR=1) 11247e4237dbSTom St Denis * 11257e4237dbSTom St Denis * The return data comes from the SGPR or VGPR register bank for 11267e4237dbSTom St Denis * the selected operational unit. 11277e4237dbSTom St Denis */ 112875758255SAlex Deucher static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, 112975758255SAlex Deucher size_t size, loff_t *pos) 113075758255SAlex Deucher { 113175758255SAlex Deucher struct amdgpu_device *adev = f->f_inode->i_private; 113275758255SAlex Deucher int r; 113375758255SAlex Deucher ssize_t result = 0; 113475758255SAlex Deucher uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; 113575758255SAlex Deucher 11366397ec58STom St Denis if (size > 4096 || size & 3 || *pos & 3) 113775758255SAlex Deucher return -EINVAL; 113875758255SAlex Deucher 113975758255SAlex Deucher /* decode offset */ 11406397ec58STom St Denis offset = (*pos & GENMASK_ULL(11, 0)) >> 2; 114175758255SAlex Deucher se = (*pos & GENMASK_ULL(19, 12)) >> 12; 114275758255SAlex Deucher sh = (*pos & GENMASK_ULL(27, 20)) >> 20; 114375758255SAlex Deucher cu = (*pos & GENMASK_ULL(35, 28)) >> 28; 114475758255SAlex Deucher wave = (*pos & GENMASK_ULL(43, 36)) >> 36; 114575758255SAlex Deucher simd = (*pos & GENMASK_ULL(51, 44)) >> 44; 114675758255SAlex Deucher thread = (*pos & GENMASK_ULL(59, 52)) >> 52; 114775758255SAlex Deucher bank = (*pos & GENMASK_ULL(61, 60)) >> 60; 114875758255SAlex Deucher 1149929e571cSWang Xiayang data = kcalloc(1024, sizeof(*data), GFP_KERNEL); 115075758255SAlex Deucher if (!data) 115175758255SAlex Deucher return -ENOMEM; 115275758255SAlex Deucher 11534a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 1154a9ffe2a9SAlex Deucher if (r < 0) 11553e4aeff3SChen Tao goto err; 1156a9ffe2a9SAlex Deucher 115795a2f917SYintian Tao r = amdgpu_virt_enable_access_debugfs(adev); 115895a2f917SYintian Tao if (r < 0) 1159888e32d7SChen Tao goto err; 116095a2f917SYintian Tao 116175758255SAlex Deucher /* switch to the specific se/sh/cu */ 116275758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 1163d51ac6d0SLe Ma amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0); 116475758255SAlex Deucher 116575758255SAlex Deucher if (bank == 0) { 116675758255SAlex Deucher if (adev->gfx.funcs->read_wave_vgprs) 1167553f973aSTom St Denis adev->gfx.funcs->read_wave_vgprs(adev, 0, simd, wave, thread, offset, size>>2, data); 116875758255SAlex Deucher } else { 116975758255SAlex Deucher if (adev->gfx.funcs->read_wave_sgprs) 1170553f973aSTom St Denis adev->gfx.funcs->read_wave_sgprs(adev, 0, simd, wave, offset, size>>2, data); 117175758255SAlex Deucher } 117275758255SAlex Deucher 1173d51ac6d0SLe Ma amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0); 117475758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 117575758255SAlex Deucher 11764a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 11774a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1178a9ffe2a9SAlex Deucher 117975758255SAlex Deucher while (size) { 118075758255SAlex Deucher uint32_t value; 118175758255SAlex Deucher 11826397ec58STom St Denis value = data[result >> 2]; 118375758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 118475758255SAlex Deucher if (r) { 11853e4aeff3SChen Tao amdgpu_virt_disable_access_debugfs(adev); 118675758255SAlex Deucher goto err; 118775758255SAlex Deucher } 118875758255SAlex Deucher 118975758255SAlex Deucher result += 4; 119075758255SAlex Deucher buf += 4; 119175758255SAlex Deucher size -= 4; 119275758255SAlex Deucher } 119375758255SAlex Deucher 119475758255SAlex Deucher kfree(data); 119595a2f917SYintian Tao amdgpu_virt_disable_access_debugfs(adev); 119675758255SAlex Deucher return result; 11973e4aeff3SChen Tao 11983e4aeff3SChen Tao err: 11994a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12003e4aeff3SChen Tao kfree(data); 12013e4aeff3SChen Tao return r; 120275758255SAlex Deucher } 120375758255SAlex Deucher 1204669e2f91STom St Denis /** 12050ad7347aSAndré Almeida * amdgpu_debugfs_gfxoff_residency_read - Read GFXOFF residency 12060ad7347aSAndré Almeida * 12070ad7347aSAndré Almeida * @f: open file handle 12080ad7347aSAndré Almeida * @buf: User buffer to store read data in 12090ad7347aSAndré Almeida * @size: Number of bytes to read 12100ad7347aSAndré Almeida * @pos: Offset to seek to 12110ad7347aSAndré Almeida * 12120ad7347aSAndré Almeida * Read the last residency value logged. It doesn't auto update, one needs to 12130ad7347aSAndré Almeida * stop logging before getting the current value. 12140ad7347aSAndré Almeida */ 12150ad7347aSAndré Almeida static ssize_t amdgpu_debugfs_gfxoff_residency_read(struct file *f, char __user *buf, 12160ad7347aSAndré Almeida size_t size, loff_t *pos) 12170ad7347aSAndré Almeida { 12180ad7347aSAndré Almeida struct amdgpu_device *adev = file_inode(f)->i_private; 12190ad7347aSAndré Almeida ssize_t result = 0; 12200ad7347aSAndré Almeida int r; 12210ad7347aSAndré Almeida 12220ad7347aSAndré Almeida if (size & 0x3 || *pos & 0x3) 12230ad7347aSAndré Almeida return -EINVAL; 12240ad7347aSAndré Almeida 12250ad7347aSAndré Almeida r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 12260ad7347aSAndré Almeida if (r < 0) { 12270ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12280ad7347aSAndré Almeida return r; 12290ad7347aSAndré Almeida } 12300ad7347aSAndré Almeida 12310ad7347aSAndré Almeida while (size) { 12320ad7347aSAndré Almeida uint32_t value; 12330ad7347aSAndré Almeida 12340ad7347aSAndré Almeida r = amdgpu_get_gfx_off_residency(adev, &value); 12350ad7347aSAndré Almeida if (r) 12360ad7347aSAndré Almeida goto out; 12370ad7347aSAndré Almeida 12380ad7347aSAndré Almeida r = put_user(value, (uint32_t *)buf); 12390ad7347aSAndré Almeida if (r) 12400ad7347aSAndré Almeida goto out; 12410ad7347aSAndré Almeida 12420ad7347aSAndré Almeida result += 4; 12430ad7347aSAndré Almeida buf += 4; 12440ad7347aSAndré Almeida *pos += 4; 12450ad7347aSAndré Almeida size -= 4; 12460ad7347aSAndré Almeida } 12470ad7347aSAndré Almeida 12480ad7347aSAndré Almeida r = result; 12490ad7347aSAndré Almeida out: 12500ad7347aSAndré Almeida pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 12510ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12520ad7347aSAndré Almeida 12530ad7347aSAndré Almeida return r; 12540ad7347aSAndré Almeida } 12550ad7347aSAndré Almeida 12560ad7347aSAndré Almeida /** 12570ad7347aSAndré Almeida * amdgpu_debugfs_gfxoff_residency_write - Log GFXOFF Residency 12580ad7347aSAndré Almeida * 12590ad7347aSAndré Almeida * @f: open file handle 12600ad7347aSAndré Almeida * @buf: User buffer to write data from 12610ad7347aSAndré Almeida * @size: Number of bytes to write 12620ad7347aSAndré Almeida * @pos: Offset to seek to 12630ad7347aSAndré Almeida * 12640ad7347aSAndré Almeida * Write a 32-bit non-zero to start logging; write a 32-bit zero to stop 12650ad7347aSAndré Almeida */ 12660ad7347aSAndré Almeida static ssize_t amdgpu_debugfs_gfxoff_residency_write(struct file *f, const char __user *buf, 12670ad7347aSAndré Almeida size_t size, loff_t *pos) 12680ad7347aSAndré Almeida { 12690ad7347aSAndré Almeida struct amdgpu_device *adev = file_inode(f)->i_private; 12700ad7347aSAndré Almeida ssize_t result = 0; 12710ad7347aSAndré Almeida int r; 12720ad7347aSAndré Almeida 12730ad7347aSAndré Almeida if (size & 0x3 || *pos & 0x3) 12740ad7347aSAndré Almeida return -EINVAL; 12750ad7347aSAndré Almeida 12760ad7347aSAndré Almeida r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 12770ad7347aSAndré Almeida if (r < 0) { 12780ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 12790ad7347aSAndré Almeida return r; 12800ad7347aSAndré Almeida } 12810ad7347aSAndré Almeida 12820ad7347aSAndré Almeida while (size) { 12830ad7347aSAndré Almeida u32 value; 12840ad7347aSAndré Almeida 12850ad7347aSAndré Almeida r = get_user(value, (uint32_t *)buf); 12860ad7347aSAndré Almeida if (r) 12870ad7347aSAndré Almeida goto out; 12880ad7347aSAndré Almeida 12890ad7347aSAndré Almeida amdgpu_set_gfx_off_residency(adev, value ? true : false); 12900ad7347aSAndré Almeida 12910ad7347aSAndré Almeida result += 4; 12920ad7347aSAndré Almeida buf += 4; 12930ad7347aSAndré Almeida *pos += 4; 12940ad7347aSAndré Almeida size -= 4; 12950ad7347aSAndré Almeida } 12960ad7347aSAndré Almeida 12970ad7347aSAndré Almeida r = result; 12980ad7347aSAndré Almeida out: 12990ad7347aSAndré Almeida pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 13000ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 13010ad7347aSAndré Almeida 13020ad7347aSAndré Almeida return r; 13030ad7347aSAndré Almeida } 13040ad7347aSAndré Almeida 13050ad7347aSAndré Almeida 13060ad7347aSAndré Almeida /** 13070ad7347aSAndré Almeida * amdgpu_debugfs_gfxoff_count_read - Read GFXOFF entry count 13080ad7347aSAndré Almeida * 13090ad7347aSAndré Almeida * @f: open file handle 13100ad7347aSAndré Almeida * @buf: User buffer to store read data in 13110ad7347aSAndré Almeida * @size: Number of bytes to read 13120ad7347aSAndré Almeida * @pos: Offset to seek to 13130ad7347aSAndré Almeida */ 13140ad7347aSAndré Almeida static ssize_t amdgpu_debugfs_gfxoff_count_read(struct file *f, char __user *buf, 13150ad7347aSAndré Almeida size_t size, loff_t *pos) 13160ad7347aSAndré Almeida { 13170ad7347aSAndré Almeida struct amdgpu_device *adev = file_inode(f)->i_private; 13180ad7347aSAndré Almeida ssize_t result = 0; 13190ad7347aSAndré Almeida int r; 13200ad7347aSAndré Almeida 13210ad7347aSAndré Almeida if (size & 0x3 || *pos & 0x3) 13220ad7347aSAndré Almeida return -EINVAL; 13230ad7347aSAndré Almeida 13240ad7347aSAndré Almeida r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 13250ad7347aSAndré Almeida if (r < 0) { 13260ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 13270ad7347aSAndré Almeida return r; 13280ad7347aSAndré Almeida } 13290ad7347aSAndré Almeida 13300ad7347aSAndré Almeida while (size) { 13310ad7347aSAndré Almeida u64 value = 0; 13320ad7347aSAndré Almeida 13330ad7347aSAndré Almeida r = amdgpu_get_gfx_off_entrycount(adev, &value); 13340ad7347aSAndré Almeida if (r) 13350ad7347aSAndré Almeida goto out; 13360ad7347aSAndré Almeida 13370ad7347aSAndré Almeida r = put_user(value, (u64 *)buf); 13380ad7347aSAndré Almeida if (r) 13390ad7347aSAndré Almeida goto out; 13400ad7347aSAndré Almeida 13410ad7347aSAndré Almeida result += 4; 13420ad7347aSAndré Almeida buf += 4; 13430ad7347aSAndré Almeida *pos += 4; 13440ad7347aSAndré Almeida size -= 4; 13450ad7347aSAndré Almeida } 13460ad7347aSAndré Almeida 13470ad7347aSAndré Almeida r = result; 13480ad7347aSAndré Almeida out: 13490ad7347aSAndré Almeida pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 13500ad7347aSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 13510ad7347aSAndré Almeida 13520ad7347aSAndré Almeida return r; 13530ad7347aSAndré Almeida } 13540ad7347aSAndré Almeida 13550ad7347aSAndré Almeida /** 1356e72d4a8bSLee Jones * amdgpu_debugfs_gfxoff_write - Enable/disable GFXOFF 1357669e2f91STom St Denis * 1358669e2f91STom St Denis * @f: open file handle 1359669e2f91STom St Denis * @buf: User buffer to write data from 1360669e2f91STom St Denis * @size: Number of bytes to write 1361669e2f91STom St Denis * @pos: Offset to seek to 1362669e2f91STom St Denis * 1363669e2f91STom St Denis * Write a 32-bit zero to disable or a 32-bit non-zero to enable 1364669e2f91STom St Denis */ 1365669e2f91STom St Denis static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *buf, 1366669e2f91STom St Denis size_t size, loff_t *pos) 1367669e2f91STom St Denis { 1368669e2f91STom St Denis struct amdgpu_device *adev = file_inode(f)->i_private; 1369669e2f91STom St Denis ssize_t result = 0; 1370669e2f91STom St Denis int r; 1371669e2f91STom St Denis 1372669e2f91STom St Denis if (size & 0x3 || *pos & 0x3) 1373669e2f91STom St Denis return -EINVAL; 1374669e2f91STom St Denis 13754a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 13769eee152aSAlex Deucher if (r < 0) { 13774a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1378669e2f91STom St Denis return r; 13799eee152aSAlex Deucher } 1380669e2f91STom St Denis 1381669e2f91STom St Denis while (size) { 1382669e2f91STom St Denis uint32_t value; 1383669e2f91STom St Denis 1384669e2f91STom St Denis r = get_user(value, (uint32_t *)buf); 1385edadd6fcSAndré Almeida if (r) 1386edadd6fcSAndré Almeida goto out; 1387669e2f91STom St Denis 1388669e2f91STom St Denis amdgpu_gfx_off_ctrl(adev, value ? true : false); 1389669e2f91STom St Denis 1390669e2f91STom St Denis result += 4; 1391669e2f91STom St Denis buf += 4; 1392669e2f91STom St Denis *pos += 4; 1393669e2f91STom St Denis size -= 4; 1394669e2f91STom St Denis } 1395669e2f91STom St Denis 1396edadd6fcSAndré Almeida r = result; 1397edadd6fcSAndré Almeida out: 13984a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 13994a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1400669e2f91STom St Denis 1401edadd6fcSAndré Almeida return r; 1402669e2f91STom St Denis } 1403669e2f91STom St Denis 1404669e2f91STom St Denis 1405443c7f3cSJinzhou.Su /** 1406e72d4a8bSLee Jones * amdgpu_debugfs_gfxoff_read - read gfxoff status 1407443c7f3cSJinzhou.Su * 1408443c7f3cSJinzhou.Su * @f: open file handle 1409443c7f3cSJinzhou.Su * @buf: User buffer to store read data in 1410443c7f3cSJinzhou.Su * @size: Number of bytes to read 1411443c7f3cSJinzhou.Su * @pos: Offset to seek to 1412443c7f3cSJinzhou.Su */ 1413443c7f3cSJinzhou.Su static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, 1414443c7f3cSJinzhou.Su size_t size, loff_t *pos) 1415443c7f3cSJinzhou.Su { 1416443c7f3cSJinzhou.Su struct amdgpu_device *adev = file_inode(f)->i_private; 1417443c7f3cSJinzhou.Su ssize_t result = 0; 1418443c7f3cSJinzhou.Su int r; 1419443c7f3cSJinzhou.Su 1420443c7f3cSJinzhou.Su if (size & 0x3 || *pos & 0x3) 1421443c7f3cSJinzhou.Su return -EINVAL; 1422443c7f3cSJinzhou.Su 14234a580877SLuben Tuikov r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 14244bd8dd0dSYongzhi Liu if (r < 0) { 14254bd8dd0dSYongzhi Liu pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1426443c7f3cSJinzhou.Su return r; 14274bd8dd0dSYongzhi Liu } 1428443c7f3cSJinzhou.Su 1429443c7f3cSJinzhou.Su while (size) { 14304686177fSAndré Almeida u32 value = adev->gfx.gfx_off_state; 14314686177fSAndré Almeida 14324686177fSAndré Almeida r = put_user(value, (u32 *)buf); 14334686177fSAndré Almeida if (r) 14344686177fSAndré Almeida goto out; 14354686177fSAndré Almeida 14364686177fSAndré Almeida result += 4; 14374686177fSAndré Almeida buf += 4; 14384686177fSAndré Almeida *pos += 4; 14394686177fSAndré Almeida size -= 4; 14404686177fSAndré Almeida } 14414686177fSAndré Almeida 14424686177fSAndré Almeida r = result; 14434686177fSAndré Almeida out: 14444686177fSAndré Almeida pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 14454686177fSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 14464686177fSAndré Almeida 14474686177fSAndré Almeida return r; 14484686177fSAndré Almeida } 14494686177fSAndré Almeida 14504686177fSAndré Almeida static ssize_t amdgpu_debugfs_gfxoff_status_read(struct file *f, char __user *buf, 14514686177fSAndré Almeida size_t size, loff_t *pos) 14524686177fSAndré Almeida { 14534686177fSAndré Almeida struct amdgpu_device *adev = file_inode(f)->i_private; 14544686177fSAndré Almeida ssize_t result = 0; 14554686177fSAndré Almeida int r; 14564686177fSAndré Almeida 14574686177fSAndré Almeida if (size & 0x3 || *pos & 0x3) 14584686177fSAndré Almeida return -EINVAL; 14594686177fSAndré Almeida 14604686177fSAndré Almeida r = pm_runtime_get_sync(adev_to_drm(adev)->dev); 14614686177fSAndré Almeida if (r < 0) { 14624686177fSAndré Almeida pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 14634686177fSAndré Almeida return r; 14644686177fSAndré Almeida } 14654686177fSAndré Almeida 14664686177fSAndré Almeida while (size) { 14674686177fSAndré Almeida u32 value; 1468443c7f3cSJinzhou.Su 1469443c7f3cSJinzhou.Su r = amdgpu_get_gfx_off_status(adev, &value); 1470edadd6fcSAndré Almeida if (r) 1471edadd6fcSAndré Almeida goto out; 1472443c7f3cSJinzhou.Su 14734686177fSAndré Almeida r = put_user(value, (u32 *)buf); 1474edadd6fcSAndré Almeida if (r) 1475edadd6fcSAndré Almeida goto out; 1476443c7f3cSJinzhou.Su 1477443c7f3cSJinzhou.Su result += 4; 1478443c7f3cSJinzhou.Su buf += 4; 1479443c7f3cSJinzhou.Su *pos += 4; 1480443c7f3cSJinzhou.Su size -= 4; 1481443c7f3cSJinzhou.Su } 1482443c7f3cSJinzhou.Su 1483edadd6fcSAndré Almeida r = result; 1484edadd6fcSAndré Almeida out: 14854a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 14864a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 1487443c7f3cSJinzhou.Su 1488edadd6fcSAndré Almeida return r; 1489443c7f3cSJinzhou.Su } 1490443c7f3cSJinzhou.Su 149137df9560STom St Denis static const struct file_operations amdgpu_debugfs_regs2_fops = { 149237df9560STom St Denis .owner = THIS_MODULE, 149337df9560STom St Denis .unlocked_ioctl = amdgpu_debugfs_regs2_ioctl, 149437df9560STom St Denis .read = amdgpu_debugfs_regs2_read, 149537df9560STom St Denis .write = amdgpu_debugfs_regs2_write, 149637df9560STom St Denis .open = amdgpu_debugfs_regs2_open, 149737df9560STom St Denis .release = amdgpu_debugfs_regs2_release, 149837df9560STom St Denis .llseek = default_llseek 149937df9560STom St Denis }; 150037df9560STom St Denis 1501553f973aSTom St Denis static const struct file_operations amdgpu_debugfs_gprwave_fops = { 1502553f973aSTom St Denis .owner = THIS_MODULE, 1503553f973aSTom St Denis .unlocked_ioctl = amdgpu_debugfs_gprwave_ioctl, 1504553f973aSTom St Denis .read = amdgpu_debugfs_gprwave_read, 1505553f973aSTom St Denis .open = amdgpu_debugfs_gprwave_open, 1506553f973aSTom St Denis .release = amdgpu_debugfs_gprwave_release, 1507553f973aSTom St Denis .llseek = default_llseek 1508553f973aSTom St Denis }; 1509553f973aSTom St Denis 151075758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_fops = { 151175758255SAlex Deucher .owner = THIS_MODULE, 151275758255SAlex Deucher .read = amdgpu_debugfs_regs_read, 151375758255SAlex Deucher .write = amdgpu_debugfs_regs_write, 151475758255SAlex Deucher .llseek = default_llseek 151575758255SAlex Deucher }; 151675758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_didt_fops = { 151775758255SAlex Deucher .owner = THIS_MODULE, 151875758255SAlex Deucher .read = amdgpu_debugfs_regs_didt_read, 151975758255SAlex Deucher .write = amdgpu_debugfs_regs_didt_write, 152075758255SAlex Deucher .llseek = default_llseek 152175758255SAlex Deucher }; 152275758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_pcie_fops = { 152375758255SAlex Deucher .owner = THIS_MODULE, 152475758255SAlex Deucher .read = amdgpu_debugfs_regs_pcie_read, 152575758255SAlex Deucher .write = amdgpu_debugfs_regs_pcie_write, 152675758255SAlex Deucher .llseek = default_llseek 152775758255SAlex Deucher }; 152875758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_smc_fops = { 152975758255SAlex Deucher .owner = THIS_MODULE, 153075758255SAlex Deucher .read = amdgpu_debugfs_regs_smc_read, 153175758255SAlex Deucher .write = amdgpu_debugfs_regs_smc_write, 153275758255SAlex Deucher .llseek = default_llseek 153375758255SAlex Deucher }; 153475758255SAlex Deucher 153575758255SAlex Deucher static const struct file_operations amdgpu_debugfs_gca_config_fops = { 153675758255SAlex Deucher .owner = THIS_MODULE, 153775758255SAlex Deucher .read = amdgpu_debugfs_gca_config_read, 153875758255SAlex Deucher .llseek = default_llseek 153975758255SAlex Deucher }; 154075758255SAlex Deucher 154175758255SAlex Deucher static const struct file_operations amdgpu_debugfs_sensors_fops = { 154275758255SAlex Deucher .owner = THIS_MODULE, 154375758255SAlex Deucher .read = amdgpu_debugfs_sensor_read, 154475758255SAlex Deucher .llseek = default_llseek 154575758255SAlex Deucher }; 154675758255SAlex Deucher 154775758255SAlex Deucher static const struct file_operations amdgpu_debugfs_wave_fops = { 154875758255SAlex Deucher .owner = THIS_MODULE, 154975758255SAlex Deucher .read = amdgpu_debugfs_wave_read, 155075758255SAlex Deucher .llseek = default_llseek 155175758255SAlex Deucher }; 155275758255SAlex Deucher static const struct file_operations amdgpu_debugfs_gpr_fops = { 155375758255SAlex Deucher .owner = THIS_MODULE, 155475758255SAlex Deucher .read = amdgpu_debugfs_gpr_read, 155575758255SAlex Deucher .llseek = default_llseek 155675758255SAlex Deucher }; 155775758255SAlex Deucher 1558669e2f91STom St Denis static const struct file_operations amdgpu_debugfs_gfxoff_fops = { 1559669e2f91STom St Denis .owner = THIS_MODULE, 1560443c7f3cSJinzhou.Su .read = amdgpu_debugfs_gfxoff_read, 1561669e2f91STom St Denis .write = amdgpu_debugfs_gfxoff_write, 1562443c7f3cSJinzhou.Su .llseek = default_llseek 1563669e2f91STom St Denis }; 1564669e2f91STom St Denis 15654686177fSAndré Almeida static const struct file_operations amdgpu_debugfs_gfxoff_status_fops = { 15664686177fSAndré Almeida .owner = THIS_MODULE, 15674686177fSAndré Almeida .read = amdgpu_debugfs_gfxoff_status_read, 15684686177fSAndré Almeida .llseek = default_llseek 15694686177fSAndré Almeida }; 15704686177fSAndré Almeida 15710ad7347aSAndré Almeida static const struct file_operations amdgpu_debugfs_gfxoff_count_fops = { 15720ad7347aSAndré Almeida .owner = THIS_MODULE, 15730ad7347aSAndré Almeida .read = amdgpu_debugfs_gfxoff_count_read, 15740ad7347aSAndré Almeida .llseek = default_llseek 15750ad7347aSAndré Almeida }; 15760ad7347aSAndré Almeida 15770ad7347aSAndré Almeida static const struct file_operations amdgpu_debugfs_gfxoff_residency_fops = { 15780ad7347aSAndré Almeida .owner = THIS_MODULE, 15790ad7347aSAndré Almeida .read = amdgpu_debugfs_gfxoff_residency_read, 15800ad7347aSAndré Almeida .write = amdgpu_debugfs_gfxoff_residency_write, 15810ad7347aSAndré Almeida .llseek = default_llseek 15820ad7347aSAndré Almeida }; 15830ad7347aSAndré Almeida 158475758255SAlex Deucher static const struct file_operations *debugfs_regs[] = { 158575758255SAlex Deucher &amdgpu_debugfs_regs_fops, 158637df9560STom St Denis &amdgpu_debugfs_regs2_fops, 1587553f973aSTom St Denis &amdgpu_debugfs_gprwave_fops, 158875758255SAlex Deucher &amdgpu_debugfs_regs_didt_fops, 158975758255SAlex Deucher &amdgpu_debugfs_regs_pcie_fops, 159075758255SAlex Deucher &amdgpu_debugfs_regs_smc_fops, 159175758255SAlex Deucher &amdgpu_debugfs_gca_config_fops, 159275758255SAlex Deucher &amdgpu_debugfs_sensors_fops, 159375758255SAlex Deucher &amdgpu_debugfs_wave_fops, 159475758255SAlex Deucher &amdgpu_debugfs_gpr_fops, 1595669e2f91STom St Denis &amdgpu_debugfs_gfxoff_fops, 15964686177fSAndré Almeida &amdgpu_debugfs_gfxoff_status_fops, 15970ad7347aSAndré Almeida &amdgpu_debugfs_gfxoff_count_fops, 15980ad7347aSAndré Almeida &amdgpu_debugfs_gfxoff_residency_fops, 159975758255SAlex Deucher }; 160075758255SAlex Deucher 16018fa76350SSrinivasan Shanmugam static const char * const debugfs_regs_names[] = { 160275758255SAlex Deucher "amdgpu_regs", 160337df9560STom St Denis "amdgpu_regs2", 1604553f973aSTom St Denis "amdgpu_gprwave", 160575758255SAlex Deucher "amdgpu_regs_didt", 160675758255SAlex Deucher "amdgpu_regs_pcie", 160775758255SAlex Deucher "amdgpu_regs_smc", 160875758255SAlex Deucher "amdgpu_gca_config", 160975758255SAlex Deucher "amdgpu_sensors", 161075758255SAlex Deucher "amdgpu_wave", 161175758255SAlex Deucher "amdgpu_gpr", 1612669e2f91STom St Denis "amdgpu_gfxoff", 16134686177fSAndré Almeida "amdgpu_gfxoff_status", 16140ad7347aSAndré Almeida "amdgpu_gfxoff_count", 16150ad7347aSAndré Almeida "amdgpu_gfxoff_residency", 161675758255SAlex Deucher }; 161775758255SAlex Deucher 16187e4237dbSTom St Denis /** 16197e4237dbSTom St Denis * amdgpu_debugfs_regs_init - Initialize debugfs entries that provide 16207e4237dbSTom St Denis * register access. 16217e4237dbSTom St Denis * 16227e4237dbSTom St Denis * @adev: The device to attach the debugfs entries to 16237e4237dbSTom St Denis */ 162475758255SAlex Deucher int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) 162575758255SAlex Deucher { 16264a580877SLuben Tuikov struct drm_minor *minor = adev_to_drm(adev)->primary; 162775758255SAlex Deucher struct dentry *ent, *root = minor->debugfs_root; 1628d344b21bSDan Carpenter unsigned int i; 162975758255SAlex Deucher 163075758255SAlex Deucher for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) { 163175758255SAlex Deucher ent = debugfs_create_file(debugfs_regs_names[i], 16328fa76350SSrinivasan Shanmugam S_IFREG | 0444, root, 163375758255SAlex Deucher adev, debugfs_regs[i]); 1634d344b21bSDan Carpenter if (!i && !IS_ERR_OR_NULL(ent)) 163575758255SAlex Deucher i_size_write(ent->d_inode, adev->rmmio_size); 163675758255SAlex Deucher } 163775758255SAlex Deucher 163875758255SAlex Deucher return 0; 163975758255SAlex Deucher } 164075758255SAlex Deucher 164198d28ac2SNirmoy Das static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) 164275758255SAlex Deucher { 1643109b4d8cSSu Hui struct amdgpu_device *adev = m->private; 164498d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 164575758255SAlex Deucher int r = 0, i; 164675758255SAlex Deucher 1647a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 16489eee152aSAlex Deucher if (r < 0) { 164998d28ac2SNirmoy Das pm_runtime_put_autosuspend(dev->dev); 1650a9ffe2a9SAlex Deucher return r; 16519eee152aSAlex Deucher } 1652a9ffe2a9SAlex Deucher 1653a28fda31SAndrey Grodzovsky /* Avoid accidently unparking the sched thread during GPU reset */ 1654d0fb18b5SAndrey Grodzovsky r = down_write_killable(&adev->reset_domain->sem); 16556049db43SDennis Li if (r) 16566049db43SDennis Li return r; 1657a28fda31SAndrey Grodzovsky 165875758255SAlex Deucher /* hold on the scheduler */ 165975758255SAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 166075758255SAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 166175758255SAlex Deucher 166275758255SAlex Deucher if (!ring || !ring->sched.thread) 166375758255SAlex Deucher continue; 166475758255SAlex Deucher kthread_park(ring->sched.thread); 166575758255SAlex Deucher } 166675758255SAlex Deucher 16678fa76350SSrinivasan Shanmugam seq_puts(m, "run ib test:\n"); 166875758255SAlex Deucher r = amdgpu_ib_ring_tests(adev); 166975758255SAlex Deucher if (r) 167075758255SAlex Deucher seq_printf(m, "ib ring tests failed (%d).\n", r); 167175758255SAlex Deucher else 16728fa76350SSrinivasan Shanmugam seq_puts(m, "ib ring tests passed.\n"); 167375758255SAlex Deucher 167475758255SAlex Deucher /* go on the scheduler */ 167575758255SAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 167675758255SAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 167775758255SAlex Deucher 167875758255SAlex Deucher if (!ring || !ring->sched.thread) 167975758255SAlex Deucher continue; 168075758255SAlex Deucher kthread_unpark(ring->sched.thread); 168175758255SAlex Deucher } 168275758255SAlex Deucher 1683d0fb18b5SAndrey Grodzovsky up_write(&adev->reset_domain->sem); 1684a28fda31SAndrey Grodzovsky 1685a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1686a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1687a9ffe2a9SAlex Deucher 168875758255SAlex Deucher return 0; 168975758255SAlex Deucher } 169075758255SAlex Deucher 169198d28ac2SNirmoy Das static int amdgpu_debugfs_evict_vram(void *data, u64 *val) 169275758255SAlex Deucher { 169398d28ac2SNirmoy Das struct amdgpu_device *adev = (struct amdgpu_device *)data; 169498d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 1695a9ffe2a9SAlex Deucher int r; 1696a9ffe2a9SAlex Deucher 1697a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 16989eee152aSAlex Deucher if (r < 0) { 169998d28ac2SNirmoy Das pm_runtime_put_autosuspend(dev->dev); 1700a9ffe2a9SAlex Deucher return r; 17019eee152aSAlex Deucher } 170275758255SAlex Deucher 170358144d28SNirmoy Das *val = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM); 1704a9ffe2a9SAlex Deucher 1705a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1706a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1707a9ffe2a9SAlex Deucher 170875758255SAlex Deucher return 0; 170975758255SAlex Deucher } 171075758255SAlex Deucher 171198d28ac2SNirmoy Das 171298d28ac2SNirmoy Das static int amdgpu_debugfs_evict_gtt(void *data, u64 *val) 171387e90c76SChristian König { 171498d28ac2SNirmoy Das struct amdgpu_device *adev = (struct amdgpu_device *)data; 171598d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 1716a9ffe2a9SAlex Deucher int r; 1717a9ffe2a9SAlex Deucher 1718a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 17199eee152aSAlex Deucher if (r < 0) { 172058144d28SNirmoy Das pm_runtime_put_autosuspend(dev->dev); 1721a9ffe2a9SAlex Deucher return r; 17229eee152aSAlex Deucher } 172387e90c76SChristian König 172458144d28SNirmoy Das *val = amdgpu_ttm_evict_resources(adev, TTM_PL_TT); 1725a9ffe2a9SAlex Deucher 1726a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1727a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1728a9ffe2a9SAlex Deucher 172987e90c76SChristian König return 0; 173087e90c76SChristian König } 173187e90c76SChristian König 1732e7c47231SAlex Deucher static int amdgpu_debugfs_benchmark(void *data, u64 val) 1733e7c47231SAlex Deucher { 1734e7c47231SAlex Deucher struct amdgpu_device *adev = (struct amdgpu_device *)data; 1735e7c47231SAlex Deucher struct drm_device *dev = adev_to_drm(adev); 1736e7c47231SAlex Deucher int r; 1737e7c47231SAlex Deucher 1738e7c47231SAlex Deucher r = pm_runtime_get_sync(dev->dev); 1739e7c47231SAlex Deucher if (r < 0) { 1740e7c47231SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1741e7c47231SAlex Deucher return r; 1742e7c47231SAlex Deucher } 1743e7c47231SAlex Deucher 1744e7c47231SAlex Deucher r = amdgpu_benchmark(adev, val); 1745e7c47231SAlex Deucher 1746e7c47231SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1747e7c47231SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1748e7c47231SAlex Deucher 1749e7c47231SAlex Deucher return r; 1750e7c47231SAlex Deucher } 175198d28ac2SNirmoy Das 175298d28ac2SNirmoy Das static int amdgpu_debugfs_vm_info_show(struct seq_file *m, void *unused) 1753ff72bc40SMihir Bhogilal Patel { 1754109b4d8cSSu Hui struct amdgpu_device *adev = m->private; 175598d28ac2SNirmoy Das struct drm_device *dev = adev_to_drm(adev); 1756ff72bc40SMihir Bhogilal Patel struct drm_file *file; 1757ff72bc40SMihir Bhogilal Patel int r; 1758ff72bc40SMihir Bhogilal Patel 1759ff72bc40SMihir Bhogilal Patel r = mutex_lock_interruptible(&dev->filelist_mutex); 1760ff72bc40SMihir Bhogilal Patel if (r) 1761ff72bc40SMihir Bhogilal Patel return r; 1762ff72bc40SMihir Bhogilal Patel 1763ff72bc40SMihir Bhogilal Patel list_for_each_entry(file, &dev->filelist, lhead) { 1764ff72bc40SMihir Bhogilal Patel struct amdgpu_fpriv *fpriv = file->driver_priv; 1765ff72bc40SMihir Bhogilal Patel struct amdgpu_vm *vm = &fpriv->vm; 1766ff72bc40SMihir Bhogilal Patel 1767ff72bc40SMihir Bhogilal Patel seq_printf(m, "pid:%d\tProcess:%s ----------\n", 1768ff72bc40SMihir Bhogilal Patel vm->task_info.pid, vm->task_info.process_name); 1769391629bdSNirmoy Das r = amdgpu_bo_reserve(vm->root.bo, true); 1770ff72bc40SMihir Bhogilal Patel if (r) 1771ff72bc40SMihir Bhogilal Patel break; 1772ff72bc40SMihir Bhogilal Patel amdgpu_debugfs_vm_bo_info(vm, m); 1773391629bdSNirmoy Das amdgpu_bo_unreserve(vm->root.bo); 1774ff72bc40SMihir Bhogilal Patel } 1775ff72bc40SMihir Bhogilal Patel 1776ff72bc40SMihir Bhogilal Patel mutex_unlock(&dev->filelist_mutex); 1777ff72bc40SMihir Bhogilal Patel 1778ff72bc40SMihir Bhogilal Patel return r; 1779ff72bc40SMihir Bhogilal Patel } 1780ff72bc40SMihir Bhogilal Patel 178198d28ac2SNirmoy Das DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_test_ib); 178298d28ac2SNirmoy Das DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_vm_info); 178398d28ac2SNirmoy Das DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_vram_fops, amdgpu_debugfs_evict_vram, 178498d28ac2SNirmoy Das NULL, "%lld\n"); 178598d28ac2SNirmoy Das DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_gtt_fops, amdgpu_debugfs_evict_gtt, 178698d28ac2SNirmoy Das NULL, "%lld\n"); 1787e7c47231SAlex Deucher DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_benchmark_fops, NULL, amdgpu_debugfs_benchmark, 1788e7c47231SAlex Deucher "%lld\n"); 178975758255SAlex Deucher 17906698a3d0SJack Xiao static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring, 17916698a3d0SJack Xiao struct dma_fence **fences) 17926698a3d0SJack Xiao { 17936698a3d0SJack Xiao struct amdgpu_fence_driver *drv = &ring->fence_drv; 17946698a3d0SJack Xiao uint32_t sync_seq, last_seq; 17956698a3d0SJack Xiao 17966698a3d0SJack Xiao last_seq = atomic_read(&ring->fence_drv.last_seq); 17976698a3d0SJack Xiao sync_seq = ring->fence_drv.sync_seq; 17986698a3d0SJack Xiao 17996698a3d0SJack Xiao last_seq &= drv->num_fences_mask; 18006698a3d0SJack Xiao sync_seq &= drv->num_fences_mask; 18016698a3d0SJack Xiao 18026698a3d0SJack Xiao do { 18036698a3d0SJack Xiao struct dma_fence *fence, **ptr; 18046698a3d0SJack Xiao 18056698a3d0SJack Xiao ++last_seq; 18066698a3d0SJack Xiao last_seq &= drv->num_fences_mask; 18076698a3d0SJack Xiao ptr = &drv->fences[last_seq]; 18086698a3d0SJack Xiao 18096698a3d0SJack Xiao fence = rcu_dereference_protected(*ptr, 1); 18106698a3d0SJack Xiao RCU_INIT_POINTER(*ptr, NULL); 18116698a3d0SJack Xiao 18126698a3d0SJack Xiao if (!fence) 18136698a3d0SJack Xiao continue; 18146698a3d0SJack Xiao 18156698a3d0SJack Xiao fences[last_seq] = fence; 18166698a3d0SJack Xiao 18176698a3d0SJack Xiao } while (last_seq != sync_seq); 18186698a3d0SJack Xiao } 18196698a3d0SJack Xiao 18206698a3d0SJack Xiao static void amdgpu_ib_preempt_signal_fences(struct dma_fence **fences, 18216698a3d0SJack Xiao int length) 18226698a3d0SJack Xiao { 18236698a3d0SJack Xiao int i; 18246698a3d0SJack Xiao struct dma_fence *fence; 18256698a3d0SJack Xiao 18266698a3d0SJack Xiao for (i = 0; i < length; i++) { 18276698a3d0SJack Xiao fence = fences[i]; 18286698a3d0SJack Xiao if (!fence) 18296698a3d0SJack Xiao continue; 18306698a3d0SJack Xiao dma_fence_signal(fence); 18316698a3d0SJack Xiao dma_fence_put(fence); 18326698a3d0SJack Xiao } 18336698a3d0SJack Xiao } 18346698a3d0SJack Xiao 18356698a3d0SJack Xiao static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched) 18366698a3d0SJack Xiao { 18376698a3d0SJack Xiao struct drm_sched_job *s_job; 18386698a3d0SJack Xiao struct dma_fence *fence; 18396698a3d0SJack Xiao 18406698a3d0SJack Xiao spin_lock(&sched->job_list_lock); 18416efa4b46SLuben Tuikov list_for_each_entry(s_job, &sched->pending_list, list) { 18426698a3d0SJack Xiao fence = sched->ops->run_job(s_job); 18436698a3d0SJack Xiao dma_fence_put(fence); 18446698a3d0SJack Xiao } 18456698a3d0SJack Xiao spin_unlock(&sched->job_list_lock); 18466698a3d0SJack Xiao } 18476698a3d0SJack Xiao 184880f8fb91SJack Xiao static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring) 184980f8fb91SJack Xiao { 185080f8fb91SJack Xiao struct amdgpu_job *job; 18517bdb0899SJack Xiao struct drm_sched_job *s_job, *tmp; 185280f8fb91SJack Xiao uint32_t preempt_seq; 185380f8fb91SJack Xiao struct dma_fence *fence, **ptr; 185480f8fb91SJack Xiao struct amdgpu_fence_driver *drv = &ring->fence_drv; 185580f8fb91SJack Xiao struct drm_gpu_scheduler *sched = &ring->sched; 18567bdb0899SJack Xiao bool preempted = true; 185780f8fb91SJack Xiao 185880f8fb91SJack Xiao if (ring->funcs->type != AMDGPU_RING_TYPE_GFX) 185980f8fb91SJack Xiao return; 186080f8fb91SJack Xiao 186180f8fb91SJack Xiao preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2)); 18627bdb0899SJack Xiao if (preempt_seq <= atomic_read(&drv->last_seq)) { 18637bdb0899SJack Xiao preempted = false; 18647bdb0899SJack Xiao goto no_preempt; 18657bdb0899SJack Xiao } 186680f8fb91SJack Xiao 186780f8fb91SJack Xiao preempt_seq &= drv->num_fences_mask; 186880f8fb91SJack Xiao ptr = &drv->fences[preempt_seq]; 186980f8fb91SJack Xiao fence = rcu_dereference_protected(*ptr, 1); 187080f8fb91SJack Xiao 18717bdb0899SJack Xiao no_preempt: 187280f8fb91SJack Xiao spin_lock(&sched->job_list_lock); 18736efa4b46SLuben Tuikov list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) { 18747bdb0899SJack Xiao if (dma_fence_is_signaled(&s_job->s_fence->finished)) { 18757bdb0899SJack Xiao /* remove job from ring_mirror_list */ 18768935ff00SLuben Tuikov list_del_init(&s_job->list); 18777bdb0899SJack Xiao sched->ops->free_job(s_job); 18787bdb0899SJack Xiao continue; 18797bdb0899SJack Xiao } 188080f8fb91SJack Xiao job = to_amdgpu_job(s_job); 1881c530b02fSJack Zhang if (preempted && (&job->hw_fence) == fence) 188280f8fb91SJack Xiao /* mark the job as preempted */ 188380f8fb91SJack Xiao job->preemption_status |= AMDGPU_IB_PREEMPTED; 188480f8fb91SJack Xiao } 188580f8fb91SJack Xiao spin_unlock(&sched->job_list_lock); 188680f8fb91SJack Xiao } 188780f8fb91SJack Xiao 18886698a3d0SJack Xiao static int amdgpu_debugfs_ib_preempt(void *data, u64 val) 18896698a3d0SJack Xiao { 1890cd3a8a59SChristian König int r, length; 18916698a3d0SJack Xiao struct amdgpu_ring *ring; 18926698a3d0SJack Xiao struct dma_fence **fences = NULL; 18936698a3d0SJack Xiao struct amdgpu_device *adev = (struct amdgpu_device *)data; 18946698a3d0SJack Xiao 18956698a3d0SJack Xiao if (val >= AMDGPU_MAX_RINGS) 18966698a3d0SJack Xiao return -EINVAL; 18976698a3d0SJack Xiao 18986698a3d0SJack Xiao ring = adev->rings[val]; 18996698a3d0SJack Xiao 19006698a3d0SJack Xiao if (!ring || !ring->funcs->preempt_ib || !ring->sched.thread) 19016698a3d0SJack Xiao return -EINVAL; 19026698a3d0SJack Xiao 19036698a3d0SJack Xiao /* the last preemption failed */ 19046698a3d0SJack Xiao if (ring->trail_seq != le32_to_cpu(*ring->trail_fence_cpu_addr)) 19056698a3d0SJack Xiao return -EBUSY; 19066698a3d0SJack Xiao 19076698a3d0SJack Xiao length = ring->fence_drv.num_fences_mask + 1; 19086698a3d0SJack Xiao fences = kcalloc(length, sizeof(void *), GFP_KERNEL); 19096698a3d0SJack Xiao if (!fences) 19106698a3d0SJack Xiao return -ENOMEM; 19116698a3d0SJack Xiao 1912a28fda31SAndrey Grodzovsky /* Avoid accidently unparking the sched thread during GPU reset */ 1913d0fb18b5SAndrey Grodzovsky r = down_read_killable(&adev->reset_domain->sem); 19146049db43SDennis Li if (r) 19156049db43SDennis Li goto pro_end; 1916a28fda31SAndrey Grodzovsky 19176698a3d0SJack Xiao /* stop the scheduler */ 19186698a3d0SJack Xiao kthread_park(ring->sched.thread); 19196698a3d0SJack Xiao 19206698a3d0SJack Xiao /* preempt the IB */ 19216698a3d0SJack Xiao r = amdgpu_ring_preempt_ib(ring); 19226698a3d0SJack Xiao if (r) { 19236698a3d0SJack Xiao DRM_WARN("failed to preempt ring %d\n", ring->idx); 19246698a3d0SJack Xiao goto failure; 19256698a3d0SJack Xiao } 19266698a3d0SJack Xiao 19276698a3d0SJack Xiao amdgpu_fence_process(ring); 19286698a3d0SJack Xiao 19296698a3d0SJack Xiao if (atomic_read(&ring->fence_drv.last_seq) != 19306698a3d0SJack Xiao ring->fence_drv.sync_seq) { 19316698a3d0SJack Xiao DRM_INFO("ring %d was preempted\n", ring->idx); 19326698a3d0SJack Xiao 193380f8fb91SJack Xiao amdgpu_ib_preempt_mark_partial_job(ring); 193480f8fb91SJack Xiao 19356698a3d0SJack Xiao /* swap out the old fences */ 19366698a3d0SJack Xiao amdgpu_ib_preempt_fences_swap(ring, fences); 19376698a3d0SJack Xiao 19386698a3d0SJack Xiao amdgpu_fence_driver_force_completion(ring); 19396698a3d0SJack Xiao 19406698a3d0SJack Xiao /* resubmit unfinished jobs */ 19416698a3d0SJack Xiao amdgpu_ib_preempt_job_recovery(&ring->sched); 19426698a3d0SJack Xiao 19436698a3d0SJack Xiao /* wait for jobs finished */ 19446698a3d0SJack Xiao amdgpu_fence_wait_empty(ring); 19456698a3d0SJack Xiao 19466698a3d0SJack Xiao /* signal the old fences */ 19476698a3d0SJack Xiao amdgpu_ib_preempt_signal_fences(fences, length); 19486698a3d0SJack Xiao } 19496698a3d0SJack Xiao 19506698a3d0SJack Xiao failure: 19516698a3d0SJack Xiao /* restart the scheduler */ 19526698a3d0SJack Xiao kthread_unpark(ring->sched.thread); 19536698a3d0SJack Xiao 1954d0fb18b5SAndrey Grodzovsky up_read(&adev->reset_domain->sem); 1955a28fda31SAndrey Grodzovsky 19566049db43SDennis Li pro_end: 19576698a3d0SJack Xiao kfree(fences); 19586698a3d0SJack Xiao 19596049db43SDennis Li return r; 19606698a3d0SJack Xiao } 19616698a3d0SJack Xiao 19620cf64555SChengming Gui static int amdgpu_debugfs_sclk_set(void *data, u64 val) 19630cf64555SChengming Gui { 19640cf64555SChengming Gui int ret = 0; 19650cf64555SChengming Gui uint32_t max_freq, min_freq; 19660cf64555SChengming Gui struct amdgpu_device *adev = (struct amdgpu_device *)data; 19670cf64555SChengming Gui 19680cf64555SChengming Gui if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) 19690cf64555SChengming Gui return -EINVAL; 19700cf64555SChengming Gui 19714a580877SLuben Tuikov ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); 19729eee152aSAlex Deucher if (ret < 0) { 19734a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 19740cf64555SChengming Gui return ret; 19759eee152aSAlex Deucher } 19760cf64555SChengming Gui 1977bc143d8bSEvan Quan ret = amdgpu_dpm_get_dpm_freq_range(adev, PP_SCLK, &min_freq, &max_freq); 1978bc143d8bSEvan Quan if (ret == -EOPNOTSUPP) { 1979bc143d8bSEvan Quan ret = 0; 1980bc143d8bSEvan Quan goto out; 1981bc143d8bSEvan Quan } 1982bc143d8bSEvan Quan if (ret || val > max_freq || val < min_freq) { 1983bc143d8bSEvan Quan ret = -EINVAL; 1984bc143d8bSEvan Quan goto out; 19850cf64555SChengming Gui } 19860cf64555SChengming Gui 1987bc143d8bSEvan Quan ret = amdgpu_dpm_set_soft_freq_range(adev, PP_SCLK, (uint32_t)val, (uint32_t)val); 1988bc143d8bSEvan Quan if (ret) 1989bc143d8bSEvan Quan ret = -EINVAL; 1990bc143d8bSEvan Quan 1991bc143d8bSEvan Quan out: 19924a580877SLuben Tuikov pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); 19934a580877SLuben Tuikov pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); 19940cf64555SChengming Gui 1995bc143d8bSEvan Quan return ret; 19960cf64555SChengming Gui } 19970cf64555SChengming Gui 19987271a5c2SYang Li DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL, 19996698a3d0SJack Xiao amdgpu_debugfs_ib_preempt, "%llu\n"); 20006698a3d0SJack Xiao 20017271a5c2SYang Li DEFINE_DEBUGFS_ATTRIBUTE(fops_sclk_set, NULL, 20020cf64555SChengming Gui amdgpu_debugfs_sclk_set, "%llu\n"); 20030cf64555SChengming Gui 20045ce5a584SSomalapuram Amaranath static ssize_t amdgpu_reset_dump_register_list_read(struct file *f, 20055ce5a584SSomalapuram Amaranath char __user *buf, size_t size, loff_t *pos) 20065ce5a584SSomalapuram Amaranath { 20075ce5a584SSomalapuram Amaranath struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; 20085ce5a584SSomalapuram Amaranath char reg_offset[12]; 20095ce5a584SSomalapuram Amaranath int i, ret, len = 0; 20105ce5a584SSomalapuram Amaranath 20115ce5a584SSomalapuram Amaranath if (*pos) 20125ce5a584SSomalapuram Amaranath return 0; 20135ce5a584SSomalapuram Amaranath 20145ce5a584SSomalapuram Amaranath memset(reg_offset, 0, 12); 201538a15ad9SDave Airlie ret = down_read_killable(&adev->reset_domain->sem); 20165ce5a584SSomalapuram Amaranath if (ret) 20175ce5a584SSomalapuram Amaranath return ret; 20185ce5a584SSomalapuram Amaranath 2019*2d6a2a28SAndré Almeida for (i = 0; i < adev->reset_info.num_regs; i++) { 2020*2d6a2a28SAndré Almeida sprintf(reg_offset, "0x%x\n", adev->reset_info.reset_dump_reg_list[i]); 202138a15ad9SDave Airlie up_read(&adev->reset_domain->sem); 20225ce5a584SSomalapuram Amaranath if (copy_to_user(buf + len, reg_offset, strlen(reg_offset))) 20235ce5a584SSomalapuram Amaranath return -EFAULT; 20245ce5a584SSomalapuram Amaranath 20255ce5a584SSomalapuram Amaranath len += strlen(reg_offset); 202638a15ad9SDave Airlie ret = down_read_killable(&adev->reset_domain->sem); 20275ce5a584SSomalapuram Amaranath if (ret) 20285ce5a584SSomalapuram Amaranath return ret; 20295ce5a584SSomalapuram Amaranath } 20305ce5a584SSomalapuram Amaranath 203138a15ad9SDave Airlie up_read(&adev->reset_domain->sem); 20325ce5a584SSomalapuram Amaranath *pos += len; 20335ce5a584SSomalapuram Amaranath 20345ce5a584SSomalapuram Amaranath return len; 20355ce5a584SSomalapuram Amaranath } 20365ce5a584SSomalapuram Amaranath 20375ce5a584SSomalapuram Amaranath static ssize_t amdgpu_reset_dump_register_list_write(struct file *f, 20385ce5a584SSomalapuram Amaranath const char __user *buf, size_t size, loff_t *pos) 20395ce5a584SSomalapuram Amaranath { 20405ce5a584SSomalapuram Amaranath struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; 20415ce5a584SSomalapuram Amaranath char reg_offset[11]; 2042ad2feebdSSebin Sebastian uint32_t *new = NULL, *tmp = NULL; 20435ce5a584SSomalapuram Amaranath int ret, i = 0, len = 0; 20445ce5a584SSomalapuram Amaranath 20455ce5a584SSomalapuram Amaranath do { 20465ce5a584SSomalapuram Amaranath memset(reg_offset, 0, 11); 20475ce5a584SSomalapuram Amaranath if (copy_from_user(reg_offset, buf + len, 20485ce5a584SSomalapuram Amaranath min(10, ((int)size-len)))) { 20495ce5a584SSomalapuram Amaranath ret = -EFAULT; 20505ce5a584SSomalapuram Amaranath goto error_free; 20515ce5a584SSomalapuram Amaranath } 20525ce5a584SSomalapuram Amaranath 2053ca6fcfa8STom Rix new = krealloc_array(tmp, i + 1, sizeof(uint32_t), GFP_KERNEL); 2054ca6fcfa8STom Rix if (!new) { 2055ca6fcfa8STom Rix ret = -ENOMEM; 2056ca6fcfa8STom Rix goto error_free; 2057ca6fcfa8STom Rix } 2058ca6fcfa8STom Rix tmp = new; 20595ce5a584SSomalapuram Amaranath if (sscanf(reg_offset, "%X %n", &tmp[i], &ret) != 1) { 20605ce5a584SSomalapuram Amaranath ret = -EINVAL; 20615ce5a584SSomalapuram Amaranath goto error_free; 20625ce5a584SSomalapuram Amaranath } 20635ce5a584SSomalapuram Amaranath 20645ce5a584SSomalapuram Amaranath len += ret; 20655ce5a584SSomalapuram Amaranath i++; 20665ce5a584SSomalapuram Amaranath } while (len < size); 20675ce5a584SSomalapuram Amaranath 2068651d7ee6SSomalapuram Amaranath new = kmalloc_array(i, sizeof(uint32_t), GFP_KERNEL); 2069651d7ee6SSomalapuram Amaranath if (!new) { 2070651d7ee6SSomalapuram Amaranath ret = -ENOMEM; 2071651d7ee6SSomalapuram Amaranath goto error_free; 2072651d7ee6SSomalapuram Amaranath } 207338a15ad9SDave Airlie ret = down_write_killable(&adev->reset_domain->sem); 20745ce5a584SSomalapuram Amaranath if (ret) 20755ce5a584SSomalapuram Amaranath goto error_free; 20765ce5a584SSomalapuram Amaranath 2077*2d6a2a28SAndré Almeida swap(adev->reset_info.reset_dump_reg_list, tmp); 2078*2d6a2a28SAndré Almeida swap(adev->reset_info.reset_dump_reg_value, new); 2079*2d6a2a28SAndré Almeida adev->reset_info.num_regs = i; 208038a15ad9SDave Airlie up_write(&adev->reset_domain->sem); 20815ce5a584SSomalapuram Amaranath ret = size; 20825ce5a584SSomalapuram Amaranath 20835ce5a584SSomalapuram Amaranath error_free: 2084ad2feebdSSebin Sebastian if (tmp != new) 20855ce5a584SSomalapuram Amaranath kfree(tmp); 2086651d7ee6SSomalapuram Amaranath kfree(new); 20875ce5a584SSomalapuram Amaranath return ret; 20885ce5a584SSomalapuram Amaranath } 20895ce5a584SSomalapuram Amaranath 20905ce5a584SSomalapuram Amaranath static const struct file_operations amdgpu_reset_dump_register_list = { 20915ce5a584SSomalapuram Amaranath .owner = THIS_MODULE, 20925ce5a584SSomalapuram Amaranath .read = amdgpu_reset_dump_register_list_read, 20935ce5a584SSomalapuram Amaranath .write = amdgpu_reset_dump_register_list_write, 20945ce5a584SSomalapuram Amaranath .llseek = default_llseek 20955ce5a584SSomalapuram Amaranath }; 20965ce5a584SSomalapuram Amaranath 209775758255SAlex Deucher int amdgpu_debugfs_init(struct amdgpu_device *adev) 209875758255SAlex Deucher { 209998d28ac2SNirmoy Das struct dentry *root = adev_to_drm(adev)->primary->debugfs_root; 210088293c03SNirmoy Das struct dentry *ent; 2101fd23cfccSAlex Deucher int r, i; 2102c5820361SAlex Deucher 21035b9581dfSNirmoy Das if (!debugfs_initialized()) 21045b9581dfSNirmoy Das return 0; 21055b9581dfSNirmoy Das 21066ff7fddbSLang Yu debugfs_create_x32("amdgpu_smu_debug", 0600, root, 21077e31a858SEvan Quan &adev->pm.smu_debug_mask); 21086ff7fddbSLang Yu 210998d28ac2SNirmoy Das ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev, 211044b582b3SGeert Uytterhoeven &fops_ib_preempt); 211159715cffSNirmoy Das if (IS_ERR(ent)) { 21126698a3d0SJack Xiao DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); 211359715cffSNirmoy Das return PTR_ERR(ent); 21146698a3d0SJack Xiao } 21156698a3d0SJack Xiao 211698d28ac2SNirmoy Das ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev, 21170cf64555SChengming Gui &fops_sclk_set); 211859715cffSNirmoy Das if (IS_ERR(ent)) { 21190cf64555SChengming Gui DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); 212059715cffSNirmoy Das return PTR_ERR(ent); 21210cf64555SChengming Gui } 21220cf64555SChengming Gui 2123c5820361SAlex Deucher /* Register debugfs entries for amdgpu_ttm */ 212498d28ac2SNirmoy Das amdgpu_ttm_debugfs_init(adev); 2125373720f7SNirmoy Das amdgpu_debugfs_pm_init(adev); 212698d28ac2SNirmoy Das amdgpu_debugfs_sa_init(adev); 212798d28ac2SNirmoy Das amdgpu_debugfs_fence_init(adev); 212898d28ac2SNirmoy Das amdgpu_debugfs_gem_init(adev); 21293f5cea67SAlex Deucher 2130f9d64e6cSAlex Deucher r = amdgpu_debugfs_regs_init(adev); 2131f9d64e6cSAlex Deucher if (r) 2132f9d64e6cSAlex Deucher DRM_ERROR("registering register debugfs failed (%d).\n", r); 2133f9d64e6cSAlex Deucher 213498d28ac2SNirmoy Das amdgpu_debugfs_firmware_init(adev); 2135e50d9ba0SCandice Li amdgpu_ta_if_debugfs_init(adev); 2136cd9e29e7SAlex Deucher 2137d090e7dbSAlex Deucher #if defined(CONFIG_DRM_AMD_DC) 2138d09ef243SAlex Deucher if (adev->dc_enabled) 2139afd3a359SNirmoy Das dtn_debugfs_init(adev); 2140d090e7dbSAlex Deucher #endif 2141d090e7dbSAlex Deucher 2142fd23cfccSAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { 2143fd23cfccSAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 2144fd23cfccSAlex Deucher 2145fd23cfccSAlex Deucher if (!ring) 2146fd23cfccSAlex Deucher continue; 2147fd23cfccSAlex Deucher 214862d266b2SNirmoy Das amdgpu_debugfs_ring_init(adev, ring); 2149fd23cfccSAlex Deucher } 2150fd23cfccSAlex Deucher 215111eb648dSRuijing Dong for (i = 0; i < adev->vcn.num_vcn_inst; i++) { 215211eb648dSRuijing Dong if (!amdgpu_vcnfw_log) 215311eb648dSRuijing Dong break; 215411eb648dSRuijing Dong 215511eb648dSRuijing Dong if (adev->vcn.harvest_config & (1 << i)) 215611eb648dSRuijing Dong continue; 215711eb648dSRuijing Dong 215811eb648dSRuijing Dong amdgpu_debugfs_vcn_fwlog_init(adev, i, &adev->vcn.inst[i]); 215911eb648dSRuijing Dong } 216011eb648dSRuijing Dong 2161204eaac6STao Zhou amdgpu_ras_debugfs_create_all(adev); 2162a4322e18SWenhui Sheng amdgpu_rap_debugfs_init(adev); 2163ecaafb7bSJinzhou Su amdgpu_securedisplay_debugfs_init(adev); 216419ae3330SJohn Clements amdgpu_fw_attestation_debugfs_init(adev); 216519ae3330SJohn Clements 216698d28ac2SNirmoy Das debugfs_create_file("amdgpu_evict_vram", 0444, root, adev, 216798d28ac2SNirmoy Das &amdgpu_evict_vram_fops); 216898d28ac2SNirmoy Das debugfs_create_file("amdgpu_evict_gtt", 0444, root, adev, 216998d28ac2SNirmoy Das &amdgpu_evict_gtt_fops); 217098d28ac2SNirmoy Das debugfs_create_file("amdgpu_test_ib", 0444, root, adev, 217198d28ac2SNirmoy Das &amdgpu_debugfs_test_ib_fops); 217298d28ac2SNirmoy Das debugfs_create_file("amdgpu_vm_info", 0444, root, adev, 217398d28ac2SNirmoy Das &amdgpu_debugfs_vm_info_fops); 2174e7c47231SAlex Deucher debugfs_create_file("amdgpu_benchmark", 0200, root, adev, 2175e7c47231SAlex Deucher &amdgpu_benchmark_fops); 21765ce5a584SSomalapuram Amaranath debugfs_create_file("amdgpu_reset_dump_register_list", 0644, root, adev, 21775ce5a584SSomalapuram Amaranath &amdgpu_reset_dump_register_list); 217898d28ac2SNirmoy Das 217998d28ac2SNirmoy Das adev->debugfs_vbios_blob.data = adev->bios; 218098d28ac2SNirmoy Das adev->debugfs_vbios_blob.size = adev->bios_size; 218198d28ac2SNirmoy Das debugfs_create_blob("amdgpu_vbios", 0444, root, 218298d28ac2SNirmoy Das &adev->debugfs_vbios_blob); 218398d28ac2SNirmoy Das 218481d1bf01SAlex Deucher adev->debugfs_discovery_blob.data = adev->mman.discovery_bin; 218581d1bf01SAlex Deucher adev->debugfs_discovery_blob.size = adev->mman.discovery_tmr_size; 218681d1bf01SAlex Deucher debugfs_create_blob("amdgpu_discovery", 0444, root, 218781d1bf01SAlex Deucher &adev->debugfs_discovery_blob); 218881d1bf01SAlex Deucher 218998d28ac2SNirmoy Das return 0; 219075758255SAlex Deucher } 219175758255SAlex Deucher 219275758255SAlex Deucher #else 219375758255SAlex Deucher int amdgpu_debugfs_init(struct amdgpu_device *adev) 219475758255SAlex Deucher { 219575758255SAlex Deucher return 0; 219675758255SAlex Deucher } 219775758255SAlex Deucher int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) 219875758255SAlex Deucher { 219975758255SAlex Deucher return 0; 220075758255SAlex Deucher } 220175758255SAlex Deucher #endif 2202