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 31fdf2f6c5SSam Ravnborg #include <drm/drm_debugfs.h> 32fdf2f6c5SSam Ravnborg 3375758255SAlex Deucher #include "amdgpu.h" 34a4c5b1bbSAlex Deucher #include "amdgpu_pm.h" 35d090e7dbSAlex Deucher #include "amdgpu_dm_debugfs.h" 3617cb04f2SStanley.Yang #include "amdgpu_ras.h" 3775758255SAlex Deucher 387e4237dbSTom St Denis /** 397e4237dbSTom St Denis * amdgpu_debugfs_add_files - Add simple debugfs entries 407e4237dbSTom St Denis * 417e4237dbSTom St Denis * @adev: Device to attach debugfs entries to 427e4237dbSTom St Denis * @files: Array of function callbacks that respond to reads 437e4237dbSTom St Denis * @nfiles: Number of callbacks to register 447e4237dbSTom St Denis * 4575758255SAlex Deucher */ 4675758255SAlex Deucher int amdgpu_debugfs_add_files(struct amdgpu_device *adev, 4775758255SAlex Deucher const struct drm_info_list *files, 4875758255SAlex Deucher unsigned nfiles) 4975758255SAlex Deucher { 5075758255SAlex Deucher unsigned i; 5175758255SAlex Deucher 5275758255SAlex Deucher for (i = 0; i < adev->debugfs_count; i++) { 5375758255SAlex Deucher if (adev->debugfs[i].files == files) { 5475758255SAlex Deucher /* Already registered */ 5575758255SAlex Deucher return 0; 5675758255SAlex Deucher } 5775758255SAlex Deucher } 5875758255SAlex Deucher 5975758255SAlex Deucher i = adev->debugfs_count + 1; 6075758255SAlex Deucher if (i > AMDGPU_DEBUGFS_MAX_COMPONENTS) { 6175758255SAlex Deucher DRM_ERROR("Reached maximum number of debugfs components.\n"); 6275758255SAlex Deucher DRM_ERROR("Report so we increase " 6375758255SAlex Deucher "AMDGPU_DEBUGFS_MAX_COMPONENTS.\n"); 6475758255SAlex Deucher return -EINVAL; 6575758255SAlex Deucher } 6675758255SAlex Deucher adev->debugfs[adev->debugfs_count].files = files; 6775758255SAlex Deucher adev->debugfs[adev->debugfs_count].num_files = nfiles; 6875758255SAlex Deucher adev->debugfs_count = i; 6975758255SAlex Deucher #if defined(CONFIG_DEBUG_FS) 7075758255SAlex Deucher drm_debugfs_create_files(files, nfiles, 7175758255SAlex Deucher adev->ddev->primary->debugfs_root, 7275758255SAlex Deucher adev->ddev->primary); 7375758255SAlex Deucher #endif 7475758255SAlex Deucher return 0; 7575758255SAlex Deucher } 7675758255SAlex Deucher 7775758255SAlex Deucher #if defined(CONFIG_DEBUG_FS) 7875758255SAlex Deucher 797e4237dbSTom St Denis /** 807e4237dbSTom St Denis * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes 817e4237dbSTom St Denis * 827e4237dbSTom St Denis * @read: True if reading 837e4237dbSTom St Denis * @f: open file handle 847e4237dbSTom St Denis * @buf: User buffer to write/read to 857e4237dbSTom St Denis * @size: Number of bytes to write/read 867e4237dbSTom St Denis * @pos: Offset to seek to 877e4237dbSTom St Denis * 887e4237dbSTom St Denis * This debugfs entry has special meaning on the offset being sought. 897e4237dbSTom St Denis * Various bits have different meanings: 907e4237dbSTom St Denis * 917e4237dbSTom St Denis * Bit 62: Indicates a GRBM bank switch is needed 927e4237dbSTom St Denis * Bit 61: Indicates a SRBM bank switch is needed (implies bit 62 is 937e4237dbSTom St Denis * zero) 947e4237dbSTom St Denis * Bits 24..33: The SE or ME selector if needed 957e4237dbSTom St Denis * Bits 34..43: The SH (or SA) or PIPE selector if needed 967e4237dbSTom St Denis * Bits 44..53: The INSTANCE (or CU/WGP) or QUEUE selector if needed 977e4237dbSTom St Denis * 987e4237dbSTom St Denis * Bit 23: Indicates that the PM power gating lock should be held 997e4237dbSTom St Denis * This is necessary to read registers that might be 1007e4237dbSTom St Denis * unreliable during a power gating transistion. 1017e4237dbSTom St Denis * 1027e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 1037e4237dbSTom St Denis * allows reading multiple registers in a single call and having 1047e4237dbSTom St Denis * the returned size reflect that. 1057e4237dbSTom St Denis */ 106f7a9ee81SAndrey Grodzovsky static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, 107f7a9ee81SAndrey Grodzovsky char __user *buf, size_t size, loff_t *pos) 10875758255SAlex Deucher { 10975758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 11075758255SAlex Deucher ssize_t result = 0; 11175758255SAlex Deucher int r; 112f7a9ee81SAndrey Grodzovsky bool pm_pg_lock, use_bank, use_ring; 1130fa4246eSTom St Denis unsigned instance_bank, sh_bank, se_bank, me, pipe, queue, vmid; 11475758255SAlex Deucher 115f7a9ee81SAndrey Grodzovsky pm_pg_lock = use_bank = use_ring = false; 1160fa4246eSTom St Denis instance_bank = sh_bank = se_bank = me = pipe = queue = vmid = 0; 117f7a9ee81SAndrey Grodzovsky 118f7a9ee81SAndrey Grodzovsky if (size & 0x3 || *pos & 0x3 || 119f7a9ee81SAndrey Grodzovsky ((*pos & (1ULL << 62)) && (*pos & (1ULL << 61)))) 12075758255SAlex Deucher return -EINVAL; 12175758255SAlex Deucher 12275758255SAlex Deucher /* are we reading registers for which a PG lock is necessary? */ 12375758255SAlex Deucher pm_pg_lock = (*pos >> 23) & 1; 12475758255SAlex Deucher 12575758255SAlex Deucher if (*pos & (1ULL << 62)) { 12675758255SAlex Deucher se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24; 12775758255SAlex Deucher sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34; 12875758255SAlex Deucher instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44; 12975758255SAlex Deucher 13075758255SAlex Deucher if (se_bank == 0x3FF) 13175758255SAlex Deucher se_bank = 0xFFFFFFFF; 13275758255SAlex Deucher if (sh_bank == 0x3FF) 13375758255SAlex Deucher sh_bank = 0xFFFFFFFF; 13475758255SAlex Deucher if (instance_bank == 0x3FF) 13575758255SAlex Deucher instance_bank = 0xFFFFFFFF; 136c5b2bd5dSzhengbin use_bank = true; 137f7a9ee81SAndrey Grodzovsky } else if (*pos & (1ULL << 61)) { 138f7a9ee81SAndrey Grodzovsky 139f7a9ee81SAndrey Grodzovsky me = (*pos & GENMASK_ULL(33, 24)) >> 24; 140f7a9ee81SAndrey Grodzovsky pipe = (*pos & GENMASK_ULL(43, 34)) >> 34; 141f7a9ee81SAndrey Grodzovsky queue = (*pos & GENMASK_ULL(53, 44)) >> 44; 14288891430STom St Denis vmid = (*pos & GENMASK_ULL(58, 54)) >> 54; 143f7a9ee81SAndrey Grodzovsky 144c5b2bd5dSzhengbin use_ring = true; 14575758255SAlex Deucher } else { 146c5b2bd5dSzhengbin use_bank = use_ring = false; 14775758255SAlex Deucher } 14875758255SAlex Deucher 14975758255SAlex Deucher *pos &= (1UL << 22) - 1; 15075758255SAlex Deucher 151a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 152a9ffe2a9SAlex Deucher if (r < 0) 153a9ffe2a9SAlex Deucher return r; 154a9ffe2a9SAlex Deucher 15575758255SAlex Deucher if (use_bank) { 15675758255SAlex Deucher if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || 157a9ffe2a9SAlex Deucher (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) { 158a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 159a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 16075758255SAlex Deucher return -EINVAL; 161a9ffe2a9SAlex Deucher } 16275758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 16375758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, se_bank, 16475758255SAlex Deucher sh_bank, instance_bank); 165f7a9ee81SAndrey Grodzovsky } else if (use_ring) { 166f7a9ee81SAndrey Grodzovsky mutex_lock(&adev->srbm_mutex); 1670fa4246eSTom St Denis amdgpu_gfx_select_me_pipe_q(adev, me, pipe, queue, vmid); 16875758255SAlex Deucher } 16975758255SAlex Deucher 17075758255SAlex Deucher if (pm_pg_lock) 17175758255SAlex Deucher mutex_lock(&adev->pm.mutex); 17275758255SAlex Deucher 17375758255SAlex Deucher while (size) { 17475758255SAlex Deucher uint32_t value; 17575758255SAlex Deucher 176f7a9ee81SAndrey Grodzovsky if (read) { 17775758255SAlex Deucher value = RREG32(*pos >> 2); 17875758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 179f7a9ee81SAndrey Grodzovsky } else { 180f7a9ee81SAndrey Grodzovsky r = get_user(value, (uint32_t *)buf); 181f7a9ee81SAndrey Grodzovsky if (!r) 182*2e0cc4d4SMonk Liu amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value, 0); 183f7a9ee81SAndrey Grodzovsky } 18475758255SAlex Deucher if (r) { 18575758255SAlex Deucher result = r; 18675758255SAlex Deucher goto end; 18775758255SAlex Deucher } 18875758255SAlex Deucher 18975758255SAlex Deucher result += 4; 19075758255SAlex Deucher buf += 4; 19175758255SAlex Deucher *pos += 4; 19275758255SAlex Deucher size -= 4; 19375758255SAlex Deucher } 19475758255SAlex Deucher 19575758255SAlex Deucher end: 19675758255SAlex Deucher if (use_bank) { 19775758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); 19875758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 199f7a9ee81SAndrey Grodzovsky } else if (use_ring) { 2000fa4246eSTom St Denis amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0); 201f7a9ee81SAndrey Grodzovsky mutex_unlock(&adev->srbm_mutex); 20275758255SAlex Deucher } 20375758255SAlex Deucher 20475758255SAlex Deucher if (pm_pg_lock) 20575758255SAlex Deucher mutex_unlock(&adev->pm.mutex); 20675758255SAlex Deucher 207a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 208a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 209a9ffe2a9SAlex Deucher 21075758255SAlex Deucher return result; 21175758255SAlex Deucher } 21275758255SAlex Deucher 2137e4237dbSTom St Denis /** 2147e4237dbSTom St Denis * amdgpu_debugfs_regs_read - Callback for reading MMIO registers 2157e4237dbSTom St Denis */ 216f7a9ee81SAndrey Grodzovsky static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, 217f7a9ee81SAndrey Grodzovsky size_t size, loff_t *pos) 218f7a9ee81SAndrey Grodzovsky { 219f7a9ee81SAndrey Grodzovsky return amdgpu_debugfs_process_reg_op(true, f, buf, size, pos); 220f7a9ee81SAndrey Grodzovsky } 221f7a9ee81SAndrey Grodzovsky 2227e4237dbSTom St Denis /** 2237e4237dbSTom St Denis * amdgpu_debugfs_regs_write - Callback for writing MMIO registers 2247e4237dbSTom St Denis */ 22575758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, 22675758255SAlex Deucher size_t size, loff_t *pos) 22775758255SAlex Deucher { 228f7a9ee81SAndrey Grodzovsky return amdgpu_debugfs_process_reg_op(false, f, (char __user *)buf, size, pos); 22975758255SAlex Deucher } 23075758255SAlex Deucher 2317e4237dbSTom St Denis 2327e4237dbSTom St Denis /** 2337e4237dbSTom St Denis * amdgpu_debugfs_regs_pcie_read - Read from a PCIE register 2347e4237dbSTom St Denis * 2357e4237dbSTom St Denis * @f: open file handle 2367e4237dbSTom St Denis * @buf: User buffer to store read data in 2377e4237dbSTom St Denis * @size: Number of bytes to read 2387e4237dbSTom St Denis * @pos: Offset to seek to 2397e4237dbSTom St Denis * 2407e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 2417e4237dbSTom St Denis * allows reading multiple registers in a single call and having 2427e4237dbSTom St Denis * the returned size reflect that. 2437e4237dbSTom St Denis */ 24475758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, 24575758255SAlex Deucher size_t size, loff_t *pos) 24675758255SAlex Deucher { 24775758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 24875758255SAlex Deucher ssize_t result = 0; 24975758255SAlex Deucher int r; 25075758255SAlex Deucher 25175758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 25275758255SAlex Deucher return -EINVAL; 25375758255SAlex Deucher 254a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 255a9ffe2a9SAlex Deucher if (r < 0) 256a9ffe2a9SAlex Deucher return r; 257a9ffe2a9SAlex Deucher 25875758255SAlex Deucher while (size) { 25975758255SAlex Deucher uint32_t value; 26075758255SAlex Deucher 26175758255SAlex Deucher value = RREG32_PCIE(*pos >> 2); 26275758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 263a9ffe2a9SAlex Deucher if (r) { 264a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 265a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 26675758255SAlex Deucher return r; 267a9ffe2a9SAlex Deucher } 26875758255SAlex Deucher 26975758255SAlex Deucher result += 4; 27075758255SAlex Deucher buf += 4; 27175758255SAlex Deucher *pos += 4; 27275758255SAlex Deucher size -= 4; 27375758255SAlex Deucher } 27475758255SAlex Deucher 275a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 276a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 277a9ffe2a9SAlex Deucher 27875758255SAlex Deucher return result; 27975758255SAlex Deucher } 28075758255SAlex Deucher 2817e4237dbSTom St Denis /** 2827e4237dbSTom St Denis * amdgpu_debugfs_regs_pcie_write - Write to a PCIE register 2837e4237dbSTom St Denis * 2847e4237dbSTom St Denis * @f: open file handle 2857e4237dbSTom St Denis * @buf: User buffer to write data from 2867e4237dbSTom St Denis * @size: Number of bytes to write 2877e4237dbSTom St Denis * @pos: Offset to seek to 2887e4237dbSTom St Denis * 2897e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 2907e4237dbSTom St Denis * allows writing multiple registers in a single call and having 2917e4237dbSTom St Denis * the returned size reflect that. 2927e4237dbSTom St Denis */ 29375758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf, 29475758255SAlex Deucher size_t size, loff_t *pos) 29575758255SAlex Deucher { 29675758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 29775758255SAlex Deucher ssize_t result = 0; 29875758255SAlex Deucher int r; 29975758255SAlex Deucher 30075758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 30175758255SAlex Deucher return -EINVAL; 30275758255SAlex Deucher 303a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 304a9ffe2a9SAlex Deucher if (r < 0) 305a9ffe2a9SAlex Deucher return r; 306a9ffe2a9SAlex Deucher 30775758255SAlex Deucher while (size) { 30875758255SAlex Deucher uint32_t value; 30975758255SAlex Deucher 31075758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 311a9ffe2a9SAlex Deucher if (r) { 312a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 313a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 31475758255SAlex Deucher return r; 315a9ffe2a9SAlex Deucher } 31675758255SAlex Deucher 31775758255SAlex Deucher WREG32_PCIE(*pos >> 2, value); 31875758255SAlex Deucher 31975758255SAlex Deucher result += 4; 32075758255SAlex Deucher buf += 4; 32175758255SAlex Deucher *pos += 4; 32275758255SAlex Deucher size -= 4; 32375758255SAlex Deucher } 32475758255SAlex Deucher 325a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 326a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 327a9ffe2a9SAlex Deucher 32875758255SAlex Deucher return result; 32975758255SAlex Deucher } 33075758255SAlex Deucher 3317e4237dbSTom St Denis /** 3327e4237dbSTom St Denis * amdgpu_debugfs_regs_didt_read - Read from a DIDT register 3337e4237dbSTom St Denis * 3347e4237dbSTom St Denis * @f: open file handle 3357e4237dbSTom St Denis * @buf: User buffer to store read data in 3367e4237dbSTom St Denis * @size: Number of bytes to read 3377e4237dbSTom St Denis * @pos: Offset to seek to 3387e4237dbSTom St Denis * 3397e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 3407e4237dbSTom St Denis * allows reading multiple registers in a single call and having 3417e4237dbSTom St Denis * the returned size reflect that. 3427e4237dbSTom St Denis */ 34375758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, 34475758255SAlex Deucher size_t size, loff_t *pos) 34575758255SAlex Deucher { 34675758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 34775758255SAlex Deucher ssize_t result = 0; 34875758255SAlex Deucher int r; 34975758255SAlex Deucher 35075758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 35175758255SAlex Deucher return -EINVAL; 35275758255SAlex Deucher 353a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 354a9ffe2a9SAlex Deucher if (r < 0) 355a9ffe2a9SAlex Deucher return r; 356a9ffe2a9SAlex Deucher 35775758255SAlex Deucher while (size) { 35875758255SAlex Deucher uint32_t value; 35975758255SAlex Deucher 36075758255SAlex Deucher value = RREG32_DIDT(*pos >> 2); 36175758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 362a9ffe2a9SAlex Deucher if (r) { 363a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 364a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 36575758255SAlex Deucher return r; 366a9ffe2a9SAlex Deucher } 36775758255SAlex Deucher 36875758255SAlex Deucher result += 4; 36975758255SAlex Deucher buf += 4; 37075758255SAlex Deucher *pos += 4; 37175758255SAlex Deucher size -= 4; 37275758255SAlex Deucher } 37375758255SAlex Deucher 374a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 375a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 376a9ffe2a9SAlex Deucher 37775758255SAlex Deucher return result; 37875758255SAlex Deucher } 37975758255SAlex Deucher 3807e4237dbSTom St Denis /** 3817e4237dbSTom St Denis * amdgpu_debugfs_regs_didt_write - Write to a DIDT register 3827e4237dbSTom St Denis * 3837e4237dbSTom St Denis * @f: open file handle 3847e4237dbSTom St Denis * @buf: User buffer to write data from 3857e4237dbSTom St Denis * @size: Number of bytes to write 3867e4237dbSTom St Denis * @pos: Offset to seek to 3877e4237dbSTom St Denis * 3887e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 3897e4237dbSTom St Denis * allows writing multiple registers in a single call and having 3907e4237dbSTom St Denis * the returned size reflect that. 3917e4237dbSTom St Denis */ 39275758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf, 39375758255SAlex Deucher size_t size, loff_t *pos) 39475758255SAlex Deucher { 39575758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 39675758255SAlex Deucher ssize_t result = 0; 39775758255SAlex Deucher int r; 39875758255SAlex Deucher 39975758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 40075758255SAlex Deucher return -EINVAL; 40175758255SAlex Deucher 402a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 403a9ffe2a9SAlex Deucher if (r < 0) 404a9ffe2a9SAlex Deucher return r; 405a9ffe2a9SAlex Deucher 40675758255SAlex Deucher while (size) { 40775758255SAlex Deucher uint32_t value; 40875758255SAlex Deucher 40975758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 410a9ffe2a9SAlex Deucher if (r) { 411a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 412a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 41375758255SAlex Deucher return r; 414a9ffe2a9SAlex Deucher } 41575758255SAlex Deucher 41675758255SAlex Deucher WREG32_DIDT(*pos >> 2, value); 41775758255SAlex Deucher 41875758255SAlex Deucher result += 4; 41975758255SAlex Deucher buf += 4; 42075758255SAlex Deucher *pos += 4; 42175758255SAlex Deucher size -= 4; 42275758255SAlex Deucher } 42375758255SAlex Deucher 424a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 425a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 426a9ffe2a9SAlex Deucher 42775758255SAlex Deucher return result; 42875758255SAlex Deucher } 42975758255SAlex Deucher 4307e4237dbSTom St Denis /** 4317e4237dbSTom St Denis * amdgpu_debugfs_regs_smc_read - Read from a SMC register 4327e4237dbSTom St Denis * 4337e4237dbSTom St Denis * @f: open file handle 4347e4237dbSTom St Denis * @buf: User buffer to store read data in 4357e4237dbSTom St Denis * @size: Number of bytes to read 4367e4237dbSTom St Denis * @pos: Offset to seek to 4377e4237dbSTom St Denis * 4387e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to read. This 4397e4237dbSTom St Denis * allows reading multiple registers in a single call and having 4407e4237dbSTom St Denis * the returned size reflect that. 4417e4237dbSTom St Denis */ 44275758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, 44375758255SAlex Deucher size_t size, loff_t *pos) 44475758255SAlex Deucher { 44575758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 44675758255SAlex Deucher ssize_t result = 0; 44775758255SAlex Deucher int r; 44875758255SAlex Deucher 44975758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 45075758255SAlex Deucher return -EINVAL; 45175758255SAlex Deucher 452a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 453a9ffe2a9SAlex Deucher if (r < 0) 454a9ffe2a9SAlex Deucher return r; 455a9ffe2a9SAlex Deucher 45675758255SAlex Deucher while (size) { 45775758255SAlex Deucher uint32_t value; 45875758255SAlex Deucher 45975758255SAlex Deucher value = RREG32_SMC(*pos); 46075758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 461a9ffe2a9SAlex Deucher if (r) { 462a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 463a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 46475758255SAlex Deucher return r; 465a9ffe2a9SAlex Deucher } 46675758255SAlex Deucher 46775758255SAlex Deucher result += 4; 46875758255SAlex Deucher buf += 4; 46975758255SAlex Deucher *pos += 4; 47075758255SAlex Deucher size -= 4; 47175758255SAlex Deucher } 47275758255SAlex Deucher 473a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 474a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 475a9ffe2a9SAlex Deucher 47675758255SAlex Deucher return result; 47775758255SAlex Deucher } 47875758255SAlex Deucher 4797e4237dbSTom St Denis /** 4807e4237dbSTom St Denis * amdgpu_debugfs_regs_smc_write - Write to a SMC register 4817e4237dbSTom St Denis * 4827e4237dbSTom St Denis * @f: open file handle 4837e4237dbSTom St Denis * @buf: User buffer to write data from 4847e4237dbSTom St Denis * @size: Number of bytes to write 4857e4237dbSTom St Denis * @pos: Offset to seek to 4867e4237dbSTom St Denis * 4877e4237dbSTom St Denis * The lower bits are the BYTE offset of the register to write. This 4887e4237dbSTom St Denis * allows writing multiple registers in a single call and having 4897e4237dbSTom St Denis * the returned size reflect that. 4907e4237dbSTom St Denis */ 49175758255SAlex Deucher static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf, 49275758255SAlex Deucher size_t size, loff_t *pos) 49375758255SAlex Deucher { 49475758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 49575758255SAlex Deucher ssize_t result = 0; 49675758255SAlex Deucher int r; 49775758255SAlex Deucher 49875758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 49975758255SAlex Deucher return -EINVAL; 50075758255SAlex Deucher 501a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 502a9ffe2a9SAlex Deucher if (r < 0) 503a9ffe2a9SAlex Deucher return r; 504a9ffe2a9SAlex Deucher 50575758255SAlex Deucher while (size) { 50675758255SAlex Deucher uint32_t value; 50775758255SAlex Deucher 50875758255SAlex Deucher r = get_user(value, (uint32_t *)buf); 509a9ffe2a9SAlex Deucher if (r) { 510a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 511a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 51275758255SAlex Deucher return r; 513a9ffe2a9SAlex Deucher } 51475758255SAlex Deucher 51575758255SAlex Deucher WREG32_SMC(*pos, value); 51675758255SAlex Deucher 51775758255SAlex Deucher result += 4; 51875758255SAlex Deucher buf += 4; 51975758255SAlex Deucher *pos += 4; 52075758255SAlex Deucher size -= 4; 52175758255SAlex Deucher } 52275758255SAlex Deucher 523a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 524a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 525a9ffe2a9SAlex Deucher 52675758255SAlex Deucher return result; 52775758255SAlex Deucher } 52875758255SAlex Deucher 5297e4237dbSTom St Denis /** 5307e4237dbSTom St Denis * amdgpu_debugfs_gca_config_read - Read from gfx config data 5317e4237dbSTom St Denis * 5327e4237dbSTom St Denis * @f: open file handle 5337e4237dbSTom St Denis * @buf: User buffer to store read data in 5347e4237dbSTom St Denis * @size: Number of bytes to read 5357e4237dbSTom St Denis * @pos: Offset to seek to 5367e4237dbSTom St Denis * 5377e4237dbSTom St Denis * This file is used to access configuration data in a somewhat 5387e4237dbSTom St Denis * stable fashion. The format is a series of DWORDs with the first 5397e4237dbSTom St Denis * indicating which revision it is. New content is appended to the 5407e4237dbSTom St Denis * end so that older software can still read the data. 5417e4237dbSTom St Denis */ 5427e4237dbSTom St Denis 54375758255SAlex Deucher static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, 54475758255SAlex Deucher size_t size, loff_t *pos) 54575758255SAlex Deucher { 54675758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 54775758255SAlex Deucher ssize_t result = 0; 54875758255SAlex Deucher int r; 54975758255SAlex Deucher uint32_t *config, no_regs = 0; 55075758255SAlex Deucher 55175758255SAlex Deucher if (size & 0x3 || *pos & 0x3) 55275758255SAlex Deucher return -EINVAL; 55375758255SAlex Deucher 55475758255SAlex Deucher config = kmalloc_array(256, sizeof(*config), GFP_KERNEL); 55575758255SAlex Deucher if (!config) 55675758255SAlex Deucher return -ENOMEM; 55775758255SAlex Deucher 55875758255SAlex Deucher /* version, increment each time something is added */ 55975758255SAlex Deucher config[no_regs++] = 3; 56075758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_shader_engines; 56175758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_tile_pipes; 56275758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_cu_per_sh; 56375758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_sh_per_se; 56475758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_backends_per_se; 56575758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_texture_channel_caches; 56675758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_gprs; 56775758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_gs_threads; 56875758255SAlex Deucher config[no_regs++] = adev->gfx.config.max_hw_contexts; 56975758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_frontend; 57075758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_backend; 57175758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_hiz_tile_fifo_size; 57275758255SAlex Deucher config[no_regs++] = adev->gfx.config.sc_earlyz_tile_fifo_size; 57375758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_tile_pipes; 57475758255SAlex Deucher config[no_regs++] = adev->gfx.config.backend_enable_mask; 57575758255SAlex Deucher config[no_regs++] = adev->gfx.config.mem_max_burst_length_bytes; 57675758255SAlex Deucher config[no_regs++] = adev->gfx.config.mem_row_size_in_kb; 57775758255SAlex Deucher config[no_regs++] = adev->gfx.config.shader_engine_tile_size; 57875758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_gpus; 57975758255SAlex Deucher config[no_regs++] = adev->gfx.config.multi_gpu_tile_size; 58075758255SAlex Deucher config[no_regs++] = adev->gfx.config.mc_arb_ramcfg; 58175758255SAlex Deucher config[no_regs++] = adev->gfx.config.gb_addr_config; 58275758255SAlex Deucher config[no_regs++] = adev->gfx.config.num_rbs; 58375758255SAlex Deucher 58475758255SAlex Deucher /* rev==1 */ 58575758255SAlex Deucher config[no_regs++] = adev->rev_id; 58675758255SAlex Deucher config[no_regs++] = adev->pg_flags; 58775758255SAlex Deucher config[no_regs++] = adev->cg_flags; 58875758255SAlex Deucher 58975758255SAlex Deucher /* rev==2 */ 59075758255SAlex Deucher config[no_regs++] = adev->family; 59175758255SAlex Deucher config[no_regs++] = adev->external_rev_id; 59275758255SAlex Deucher 59375758255SAlex Deucher /* rev==3 */ 59475758255SAlex Deucher config[no_regs++] = adev->pdev->device; 59575758255SAlex Deucher config[no_regs++] = adev->pdev->revision; 59675758255SAlex Deucher config[no_regs++] = adev->pdev->subsystem_device; 59775758255SAlex Deucher config[no_regs++] = adev->pdev->subsystem_vendor; 59875758255SAlex Deucher 59975758255SAlex Deucher while (size && (*pos < no_regs * 4)) { 60075758255SAlex Deucher uint32_t value; 60175758255SAlex Deucher 60275758255SAlex Deucher value = config[*pos >> 2]; 60375758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 60475758255SAlex Deucher if (r) { 60575758255SAlex Deucher kfree(config); 60675758255SAlex Deucher return r; 60775758255SAlex Deucher } 60875758255SAlex Deucher 60975758255SAlex Deucher result += 4; 61075758255SAlex Deucher buf += 4; 61175758255SAlex Deucher *pos += 4; 61275758255SAlex Deucher size -= 4; 61375758255SAlex Deucher } 61475758255SAlex Deucher 61575758255SAlex Deucher kfree(config); 61675758255SAlex Deucher return result; 61775758255SAlex Deucher } 61875758255SAlex Deucher 6197e4237dbSTom St Denis /** 6207e4237dbSTom St Denis * amdgpu_debugfs_sensor_read - Read from the powerplay sensors 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 offset is treated as the BYTE address of one of the sensors 6287e4237dbSTom St Denis * enumerated in amd/include/kgd_pp_interface.h under the 6297e4237dbSTom St Denis * 'amd_pp_sensors' enumeration. For instance to read the UVD VCLK 6307e4237dbSTom St Denis * you would use the offset 3 * 4 = 12. 6317e4237dbSTom St Denis */ 63275758255SAlex Deucher static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, 63375758255SAlex Deucher size_t size, loff_t *pos) 63475758255SAlex Deucher { 63575758255SAlex Deucher struct amdgpu_device *adev = file_inode(f)->i_private; 63675758255SAlex Deucher int idx, x, outsize, r, valuesize; 63775758255SAlex Deucher uint32_t values[16]; 63875758255SAlex Deucher 63975758255SAlex Deucher if (size & 3 || *pos & 0x3) 64075758255SAlex Deucher return -EINVAL; 64175758255SAlex Deucher 642b13aa109SRex Zhu if (!adev->pm.dpm_enabled) 64375758255SAlex Deucher return -EINVAL; 64475758255SAlex Deucher 64575758255SAlex Deucher /* convert offset to sensor number */ 64675758255SAlex Deucher idx = *pos >> 2; 64775758255SAlex Deucher 64875758255SAlex Deucher valuesize = sizeof(values); 649a9ffe2a9SAlex Deucher 650a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 651a9ffe2a9SAlex Deucher if (r < 0) 652a9ffe2a9SAlex Deucher return r; 653a9ffe2a9SAlex Deucher 65475758255SAlex Deucher r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize); 655a9ffe2a9SAlex Deucher 656a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 657a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 658a9ffe2a9SAlex Deucher 6594a5a2de6SKevin Wang if (r) 6604a5a2de6SKevin Wang return r; 66175758255SAlex Deucher 66275758255SAlex Deucher if (size > valuesize) 66375758255SAlex Deucher return -EINVAL; 66475758255SAlex Deucher 66575758255SAlex Deucher outsize = 0; 66675758255SAlex Deucher x = 0; 66775758255SAlex Deucher if (!r) { 66875758255SAlex Deucher while (size) { 66975758255SAlex Deucher r = put_user(values[x++], (int32_t *)buf); 67075758255SAlex Deucher buf += 4; 67175758255SAlex Deucher size -= 4; 67275758255SAlex Deucher outsize += 4; 67375758255SAlex Deucher } 67475758255SAlex Deucher } 67575758255SAlex Deucher 67675758255SAlex Deucher return !r ? outsize : r; 67775758255SAlex Deucher } 67875758255SAlex Deucher 6797e4237dbSTom St Denis /** amdgpu_debugfs_wave_read - Read WAVE STATUS data 6807e4237dbSTom St Denis * 6817e4237dbSTom St Denis * @f: open file handle 6827e4237dbSTom St Denis * @buf: User buffer to store read data in 6837e4237dbSTom St Denis * @size: Number of bytes to read 6847e4237dbSTom St Denis * @pos: Offset to seek to 6857e4237dbSTom St Denis * 6867e4237dbSTom St Denis * The offset being sought changes which wave that the status data 6877e4237dbSTom St Denis * will be returned for. The bits are used as follows: 6887e4237dbSTom St Denis * 6897e4237dbSTom St Denis * Bits 0..6: Byte offset into data 6907e4237dbSTom St Denis * Bits 7..14: SE selector 6917e4237dbSTom St Denis * Bits 15..22: SH/SA selector 6927e4237dbSTom St Denis * Bits 23..30: CU/{WGP+SIMD} selector 6937e4237dbSTom St Denis * Bits 31..36: WAVE ID selector 6947e4237dbSTom St Denis * Bits 37..44: SIMD ID selector 6957e4237dbSTom St Denis * 6967e4237dbSTom St Denis * The returned data begins with one DWORD of version information 6977e4237dbSTom St Denis * Followed by WAVE STATUS registers relevant to the GFX IP version 6987e4237dbSTom St Denis * being used. See gfx_v8_0_read_wave_data() for an example output. 6997e4237dbSTom St Denis */ 70075758255SAlex Deucher static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, 70175758255SAlex Deucher size_t size, loff_t *pos) 70275758255SAlex Deucher { 70375758255SAlex Deucher struct amdgpu_device *adev = f->f_inode->i_private; 70475758255SAlex Deucher int r, x; 70575758255SAlex Deucher ssize_t result=0; 70675758255SAlex Deucher uint32_t offset, se, sh, cu, wave, simd, data[32]; 70775758255SAlex Deucher 70875758255SAlex Deucher if (size & 3 || *pos & 3) 70975758255SAlex Deucher return -EINVAL; 71075758255SAlex Deucher 71175758255SAlex Deucher /* decode offset */ 71275758255SAlex Deucher offset = (*pos & GENMASK_ULL(6, 0)); 71375758255SAlex Deucher se = (*pos & GENMASK_ULL(14, 7)) >> 7; 71475758255SAlex Deucher sh = (*pos & GENMASK_ULL(22, 15)) >> 15; 71575758255SAlex Deucher cu = (*pos & GENMASK_ULL(30, 23)) >> 23; 71675758255SAlex Deucher wave = (*pos & GENMASK_ULL(36, 31)) >> 31; 71775758255SAlex Deucher simd = (*pos & GENMASK_ULL(44, 37)) >> 37; 71875758255SAlex Deucher 719a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 720a9ffe2a9SAlex Deucher if (r < 0) 721a9ffe2a9SAlex Deucher return r; 722a9ffe2a9SAlex Deucher 72375758255SAlex Deucher /* switch to the specific se/sh/cu */ 72475758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 72575758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, se, sh, cu); 72675758255SAlex Deucher 72775758255SAlex Deucher x = 0; 72875758255SAlex Deucher if (adev->gfx.funcs->read_wave_data) 72975758255SAlex Deucher adev->gfx.funcs->read_wave_data(adev, simd, wave, data, &x); 73075758255SAlex Deucher 73175758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); 73275758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 73375758255SAlex Deucher 734a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 735a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 736a9ffe2a9SAlex Deucher 73775758255SAlex Deucher if (!x) 73875758255SAlex Deucher return -EINVAL; 73975758255SAlex Deucher 74075758255SAlex Deucher while (size && (offset < x * 4)) { 74175758255SAlex Deucher uint32_t value; 74275758255SAlex Deucher 74375758255SAlex Deucher value = data[offset >> 2]; 74475758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 74575758255SAlex Deucher if (r) 74675758255SAlex Deucher return r; 74775758255SAlex Deucher 74875758255SAlex Deucher result += 4; 74975758255SAlex Deucher buf += 4; 75075758255SAlex Deucher offset += 4; 75175758255SAlex Deucher size -= 4; 75275758255SAlex Deucher } 75375758255SAlex Deucher 75475758255SAlex Deucher return result; 75575758255SAlex Deucher } 75675758255SAlex Deucher 7577e4237dbSTom St Denis /** amdgpu_debugfs_gpr_read - Read wave gprs 7587e4237dbSTom St Denis * 7597e4237dbSTom St Denis * @f: open file handle 7607e4237dbSTom St Denis * @buf: User buffer to store read data in 7617e4237dbSTom St Denis * @size: Number of bytes to read 7627e4237dbSTom St Denis * @pos: Offset to seek to 7637e4237dbSTom St Denis * 7647e4237dbSTom St Denis * The offset being sought changes which wave that the status data 7657e4237dbSTom St Denis * will be returned for. The bits are used as follows: 7667e4237dbSTom St Denis * 7677e4237dbSTom St Denis * Bits 0..11: Byte offset into data 7687e4237dbSTom St Denis * Bits 12..19: SE selector 7697e4237dbSTom St Denis * Bits 20..27: SH/SA selector 7707e4237dbSTom St Denis * Bits 28..35: CU/{WGP+SIMD} selector 7717e4237dbSTom St Denis * Bits 36..43: WAVE ID selector 7727e4237dbSTom St Denis * Bits 37..44: SIMD ID selector 7737e4237dbSTom St Denis * Bits 52..59: Thread selector 7747e4237dbSTom St Denis * Bits 60..61: Bank selector (VGPR=0,SGPR=1) 7757e4237dbSTom St Denis * 7767e4237dbSTom St Denis * The return data comes from the SGPR or VGPR register bank for 7777e4237dbSTom St Denis * the selected operational unit. 7787e4237dbSTom St Denis */ 77975758255SAlex Deucher static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, 78075758255SAlex Deucher size_t size, loff_t *pos) 78175758255SAlex Deucher { 78275758255SAlex Deucher struct amdgpu_device *adev = f->f_inode->i_private; 78375758255SAlex Deucher int r; 78475758255SAlex Deucher ssize_t result = 0; 78575758255SAlex Deucher uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; 78675758255SAlex Deucher 7876397ec58STom St Denis if (size > 4096 || size & 3 || *pos & 3) 78875758255SAlex Deucher return -EINVAL; 78975758255SAlex Deucher 79075758255SAlex Deucher /* decode offset */ 7916397ec58STom St Denis offset = (*pos & GENMASK_ULL(11, 0)) >> 2; 79275758255SAlex Deucher se = (*pos & GENMASK_ULL(19, 12)) >> 12; 79375758255SAlex Deucher sh = (*pos & GENMASK_ULL(27, 20)) >> 20; 79475758255SAlex Deucher cu = (*pos & GENMASK_ULL(35, 28)) >> 28; 79575758255SAlex Deucher wave = (*pos & GENMASK_ULL(43, 36)) >> 36; 79675758255SAlex Deucher simd = (*pos & GENMASK_ULL(51, 44)) >> 44; 79775758255SAlex Deucher thread = (*pos & GENMASK_ULL(59, 52)) >> 52; 79875758255SAlex Deucher bank = (*pos & GENMASK_ULL(61, 60)) >> 60; 79975758255SAlex Deucher 800929e571cSWang Xiayang data = kcalloc(1024, sizeof(*data), GFP_KERNEL); 80175758255SAlex Deucher if (!data) 80275758255SAlex Deucher return -ENOMEM; 80375758255SAlex Deucher 804a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(adev->ddev->dev); 805a9ffe2a9SAlex Deucher if (r < 0) 806a9ffe2a9SAlex Deucher return r; 807a9ffe2a9SAlex Deucher 80875758255SAlex Deucher /* switch to the specific se/sh/cu */ 80975758255SAlex Deucher mutex_lock(&adev->grbm_idx_mutex); 81075758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, se, sh, cu); 81175758255SAlex Deucher 81275758255SAlex Deucher if (bank == 0) { 81375758255SAlex Deucher if (adev->gfx.funcs->read_wave_vgprs) 81475758255SAlex Deucher adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data); 81575758255SAlex Deucher } else { 81675758255SAlex Deucher if (adev->gfx.funcs->read_wave_sgprs) 81775758255SAlex Deucher adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data); 81875758255SAlex Deucher } 81975758255SAlex Deucher 82075758255SAlex Deucher amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); 82175758255SAlex Deucher mutex_unlock(&adev->grbm_idx_mutex); 82275758255SAlex Deucher 823a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(adev->ddev->dev); 824a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(adev->ddev->dev); 825a9ffe2a9SAlex Deucher 82675758255SAlex Deucher while (size) { 82775758255SAlex Deucher uint32_t value; 82875758255SAlex Deucher 8296397ec58STom St Denis value = data[result >> 2]; 83075758255SAlex Deucher r = put_user(value, (uint32_t *)buf); 83175758255SAlex Deucher if (r) { 83275758255SAlex Deucher result = r; 83375758255SAlex Deucher goto err; 83475758255SAlex Deucher } 83575758255SAlex Deucher 83675758255SAlex Deucher result += 4; 83775758255SAlex Deucher buf += 4; 83875758255SAlex Deucher size -= 4; 83975758255SAlex Deucher } 84075758255SAlex Deucher 84175758255SAlex Deucher err: 84275758255SAlex Deucher kfree(data); 84375758255SAlex Deucher return result; 84475758255SAlex Deucher } 84575758255SAlex Deucher 846669e2f91STom St Denis /** 847669e2f91STom St Denis * amdgpu_debugfs_regs_gfxoff_write - Enable/disable GFXOFF 848669e2f91STom St Denis * 849669e2f91STom St Denis * @f: open file handle 850669e2f91STom St Denis * @buf: User buffer to write data from 851669e2f91STom St Denis * @size: Number of bytes to write 852669e2f91STom St Denis * @pos: Offset to seek to 853669e2f91STom St Denis * 854669e2f91STom St Denis * Write a 32-bit zero to disable or a 32-bit non-zero to enable 855669e2f91STom St Denis */ 856669e2f91STom St Denis static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *buf, 857669e2f91STom St Denis size_t size, loff_t *pos) 858669e2f91STom St Denis { 859669e2f91STom St Denis struct amdgpu_device *adev = file_inode(f)->i_private; 860669e2f91STom St Denis ssize_t result = 0; 861669e2f91STom St Denis int r; 862669e2f91STom St Denis 863669e2f91STom St Denis if (size & 0x3 || *pos & 0x3) 864669e2f91STom St Denis return -EINVAL; 865669e2f91STom St Denis 866669e2f91STom St Denis r = pm_runtime_get_sync(adev->ddev->dev); 867669e2f91STom St Denis if (r < 0) 868669e2f91STom St Denis return r; 869669e2f91STom St Denis 870669e2f91STom St Denis while (size) { 871669e2f91STom St Denis uint32_t value; 872669e2f91STom St Denis 873669e2f91STom St Denis r = get_user(value, (uint32_t *)buf); 874669e2f91STom St Denis if (r) { 875669e2f91STom St Denis pm_runtime_mark_last_busy(adev->ddev->dev); 876669e2f91STom St Denis pm_runtime_put_autosuspend(adev->ddev->dev); 877669e2f91STom St Denis return r; 878669e2f91STom St Denis } 879669e2f91STom St Denis 880669e2f91STom St Denis amdgpu_gfx_off_ctrl(adev, value ? true : false); 881669e2f91STom St Denis 882669e2f91STom St Denis result += 4; 883669e2f91STom St Denis buf += 4; 884669e2f91STom St Denis *pos += 4; 885669e2f91STom St Denis size -= 4; 886669e2f91STom St Denis } 887669e2f91STom St Denis 888669e2f91STom St Denis pm_runtime_mark_last_busy(adev->ddev->dev); 889669e2f91STom St Denis pm_runtime_put_autosuspend(adev->ddev->dev); 890669e2f91STom St Denis 891669e2f91STom St Denis return result; 892669e2f91STom St Denis } 893669e2f91STom St Denis 894669e2f91STom St Denis 89575758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_fops = { 89675758255SAlex Deucher .owner = THIS_MODULE, 89775758255SAlex Deucher .read = amdgpu_debugfs_regs_read, 89875758255SAlex Deucher .write = amdgpu_debugfs_regs_write, 89975758255SAlex Deucher .llseek = default_llseek 90075758255SAlex Deucher }; 90175758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_didt_fops = { 90275758255SAlex Deucher .owner = THIS_MODULE, 90375758255SAlex Deucher .read = amdgpu_debugfs_regs_didt_read, 90475758255SAlex Deucher .write = amdgpu_debugfs_regs_didt_write, 90575758255SAlex Deucher .llseek = default_llseek 90675758255SAlex Deucher }; 90775758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_pcie_fops = { 90875758255SAlex Deucher .owner = THIS_MODULE, 90975758255SAlex Deucher .read = amdgpu_debugfs_regs_pcie_read, 91075758255SAlex Deucher .write = amdgpu_debugfs_regs_pcie_write, 91175758255SAlex Deucher .llseek = default_llseek 91275758255SAlex Deucher }; 91375758255SAlex Deucher static const struct file_operations amdgpu_debugfs_regs_smc_fops = { 91475758255SAlex Deucher .owner = THIS_MODULE, 91575758255SAlex Deucher .read = amdgpu_debugfs_regs_smc_read, 91675758255SAlex Deucher .write = amdgpu_debugfs_regs_smc_write, 91775758255SAlex Deucher .llseek = default_llseek 91875758255SAlex Deucher }; 91975758255SAlex Deucher 92075758255SAlex Deucher static const struct file_operations amdgpu_debugfs_gca_config_fops = { 92175758255SAlex Deucher .owner = THIS_MODULE, 92275758255SAlex Deucher .read = amdgpu_debugfs_gca_config_read, 92375758255SAlex Deucher .llseek = default_llseek 92475758255SAlex Deucher }; 92575758255SAlex Deucher 92675758255SAlex Deucher static const struct file_operations amdgpu_debugfs_sensors_fops = { 92775758255SAlex Deucher .owner = THIS_MODULE, 92875758255SAlex Deucher .read = amdgpu_debugfs_sensor_read, 92975758255SAlex Deucher .llseek = default_llseek 93075758255SAlex Deucher }; 93175758255SAlex Deucher 93275758255SAlex Deucher static const struct file_operations amdgpu_debugfs_wave_fops = { 93375758255SAlex Deucher .owner = THIS_MODULE, 93475758255SAlex Deucher .read = amdgpu_debugfs_wave_read, 93575758255SAlex Deucher .llseek = default_llseek 93675758255SAlex Deucher }; 93775758255SAlex Deucher static const struct file_operations amdgpu_debugfs_gpr_fops = { 93875758255SAlex Deucher .owner = THIS_MODULE, 93975758255SAlex Deucher .read = amdgpu_debugfs_gpr_read, 94075758255SAlex Deucher .llseek = default_llseek 94175758255SAlex Deucher }; 94275758255SAlex Deucher 943669e2f91STom St Denis static const struct file_operations amdgpu_debugfs_gfxoff_fops = { 944669e2f91STom St Denis .owner = THIS_MODULE, 945669e2f91STom St Denis .write = amdgpu_debugfs_gfxoff_write, 946669e2f91STom St Denis }; 947669e2f91STom St Denis 94875758255SAlex Deucher static const struct file_operations *debugfs_regs[] = { 94975758255SAlex Deucher &amdgpu_debugfs_regs_fops, 95075758255SAlex Deucher &amdgpu_debugfs_regs_didt_fops, 95175758255SAlex Deucher &amdgpu_debugfs_regs_pcie_fops, 95275758255SAlex Deucher &amdgpu_debugfs_regs_smc_fops, 95375758255SAlex Deucher &amdgpu_debugfs_gca_config_fops, 95475758255SAlex Deucher &amdgpu_debugfs_sensors_fops, 95575758255SAlex Deucher &amdgpu_debugfs_wave_fops, 95675758255SAlex Deucher &amdgpu_debugfs_gpr_fops, 957669e2f91STom St Denis &amdgpu_debugfs_gfxoff_fops, 95875758255SAlex Deucher }; 95975758255SAlex Deucher 96075758255SAlex Deucher static const char *debugfs_regs_names[] = { 96175758255SAlex Deucher "amdgpu_regs", 96275758255SAlex Deucher "amdgpu_regs_didt", 96375758255SAlex Deucher "amdgpu_regs_pcie", 96475758255SAlex Deucher "amdgpu_regs_smc", 96575758255SAlex Deucher "amdgpu_gca_config", 96675758255SAlex Deucher "amdgpu_sensors", 96775758255SAlex Deucher "amdgpu_wave", 96875758255SAlex Deucher "amdgpu_gpr", 969669e2f91STom St Denis "amdgpu_gfxoff", 97075758255SAlex Deucher }; 97175758255SAlex Deucher 9727e4237dbSTom St Denis /** 9737e4237dbSTom St Denis * amdgpu_debugfs_regs_init - Initialize debugfs entries that provide 9747e4237dbSTom St Denis * register access. 9757e4237dbSTom St Denis * 9767e4237dbSTom St Denis * @adev: The device to attach the debugfs entries to 9777e4237dbSTom St Denis */ 97875758255SAlex Deucher int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) 97975758255SAlex Deucher { 98075758255SAlex Deucher struct drm_minor *minor = adev->ddev->primary; 98175758255SAlex Deucher struct dentry *ent, *root = minor->debugfs_root; 982d344b21bSDan Carpenter unsigned int i; 98375758255SAlex Deucher 98475758255SAlex Deucher for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) { 98575758255SAlex Deucher ent = debugfs_create_file(debugfs_regs_names[i], 98675758255SAlex Deucher S_IFREG | S_IRUGO, root, 98775758255SAlex Deucher adev, debugfs_regs[i]); 988d344b21bSDan Carpenter if (!i && !IS_ERR_OR_NULL(ent)) 98975758255SAlex Deucher i_size_write(ent->d_inode, adev->rmmio_size); 99075758255SAlex Deucher adev->debugfs_regs[i] = ent; 99175758255SAlex Deucher } 99275758255SAlex Deucher 99375758255SAlex Deucher return 0; 99475758255SAlex Deucher } 99575758255SAlex Deucher 99675758255SAlex Deucher static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) 99775758255SAlex Deucher { 99875758255SAlex Deucher struct drm_info_node *node = (struct drm_info_node *) m->private; 99975758255SAlex Deucher struct drm_device *dev = node->minor->dev; 100075758255SAlex Deucher struct amdgpu_device *adev = dev->dev_private; 100175758255SAlex Deucher int r = 0, i; 100275758255SAlex Deucher 1003a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 1004a9ffe2a9SAlex Deucher if (r < 0) 1005a9ffe2a9SAlex Deucher return r; 1006a9ffe2a9SAlex Deucher 1007a28fda31SAndrey Grodzovsky /* Avoid accidently unparking the sched thread during GPU reset */ 1008a28fda31SAndrey Grodzovsky mutex_lock(&adev->lock_reset); 1009a28fda31SAndrey Grodzovsky 101075758255SAlex Deucher /* hold on the scheduler */ 101175758255SAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 101275758255SAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 101375758255SAlex Deucher 101475758255SAlex Deucher if (!ring || !ring->sched.thread) 101575758255SAlex Deucher continue; 101675758255SAlex Deucher kthread_park(ring->sched.thread); 101775758255SAlex Deucher } 101875758255SAlex Deucher 101975758255SAlex Deucher seq_printf(m, "run ib test:\n"); 102075758255SAlex Deucher r = amdgpu_ib_ring_tests(adev); 102175758255SAlex Deucher if (r) 102275758255SAlex Deucher seq_printf(m, "ib ring tests failed (%d).\n", r); 102375758255SAlex Deucher else 102475758255SAlex Deucher seq_printf(m, "ib ring tests passed.\n"); 102575758255SAlex Deucher 102675758255SAlex Deucher /* go on the scheduler */ 102775758255SAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 102875758255SAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 102975758255SAlex Deucher 103075758255SAlex Deucher if (!ring || !ring->sched.thread) 103175758255SAlex Deucher continue; 103275758255SAlex Deucher kthread_unpark(ring->sched.thread); 103375758255SAlex Deucher } 103475758255SAlex Deucher 1035a28fda31SAndrey Grodzovsky mutex_unlock(&adev->lock_reset); 1036a28fda31SAndrey Grodzovsky 1037a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1038a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1039a9ffe2a9SAlex Deucher 104075758255SAlex Deucher return 0; 104175758255SAlex Deucher } 104275758255SAlex Deucher 104375758255SAlex Deucher static int amdgpu_debugfs_get_vbios_dump(struct seq_file *m, void *data) 104475758255SAlex Deucher { 104575758255SAlex Deucher struct drm_info_node *node = (struct drm_info_node *) m->private; 104675758255SAlex Deucher struct drm_device *dev = node->minor->dev; 104775758255SAlex Deucher struct amdgpu_device *adev = dev->dev_private; 104875758255SAlex Deucher 104975758255SAlex Deucher seq_write(m, adev->bios, adev->bios_size); 105075758255SAlex Deucher return 0; 105175758255SAlex Deucher } 105275758255SAlex Deucher 105375758255SAlex Deucher static int amdgpu_debugfs_evict_vram(struct seq_file *m, void *data) 105475758255SAlex Deucher { 105575758255SAlex Deucher struct drm_info_node *node = (struct drm_info_node *)m->private; 105675758255SAlex Deucher struct drm_device *dev = node->minor->dev; 105775758255SAlex Deucher struct amdgpu_device *adev = dev->dev_private; 1058a9ffe2a9SAlex Deucher int r; 1059a9ffe2a9SAlex Deucher 1060a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 1061a9ffe2a9SAlex Deucher if (r < 0) 1062a9ffe2a9SAlex Deucher return r; 106375758255SAlex Deucher 106475758255SAlex Deucher seq_printf(m, "(%d)\n", amdgpu_bo_evict_vram(adev)); 1065a9ffe2a9SAlex Deucher 1066a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1067a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1068a9ffe2a9SAlex Deucher 106975758255SAlex Deucher return 0; 107075758255SAlex Deucher } 107175758255SAlex Deucher 107287e90c76SChristian König static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data) 107387e90c76SChristian König { 107487e90c76SChristian König struct drm_info_node *node = (struct drm_info_node *)m->private; 107587e90c76SChristian König struct drm_device *dev = node->minor->dev; 107687e90c76SChristian König struct amdgpu_device *adev = dev->dev_private; 1077a9ffe2a9SAlex Deucher int r; 1078a9ffe2a9SAlex Deucher 1079a9ffe2a9SAlex Deucher r = pm_runtime_get_sync(dev->dev); 1080a9ffe2a9SAlex Deucher if (r < 0) 1081a9ffe2a9SAlex Deucher return r; 108287e90c76SChristian König 108387e90c76SChristian König seq_printf(m, "(%d)\n", ttm_bo_evict_mm(&adev->mman.bdev, TTM_PL_TT)); 1084a9ffe2a9SAlex Deucher 1085a9ffe2a9SAlex Deucher pm_runtime_mark_last_busy(dev->dev); 1086a9ffe2a9SAlex Deucher pm_runtime_put_autosuspend(dev->dev); 1087a9ffe2a9SAlex Deucher 108887e90c76SChristian König return 0; 108987e90c76SChristian König } 109087e90c76SChristian König 109175758255SAlex Deucher static const struct drm_info_list amdgpu_debugfs_list[] = { 109275758255SAlex Deucher {"amdgpu_vbios", amdgpu_debugfs_get_vbios_dump}, 109375758255SAlex Deucher {"amdgpu_test_ib", &amdgpu_debugfs_test_ib}, 109487e90c76SChristian König {"amdgpu_evict_vram", &amdgpu_debugfs_evict_vram}, 109587e90c76SChristian König {"amdgpu_evict_gtt", &amdgpu_debugfs_evict_gtt}, 109675758255SAlex Deucher }; 109775758255SAlex Deucher 10986698a3d0SJack Xiao static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring, 10996698a3d0SJack Xiao struct dma_fence **fences) 11006698a3d0SJack Xiao { 11016698a3d0SJack Xiao struct amdgpu_fence_driver *drv = &ring->fence_drv; 11026698a3d0SJack Xiao uint32_t sync_seq, last_seq; 11036698a3d0SJack Xiao 11046698a3d0SJack Xiao last_seq = atomic_read(&ring->fence_drv.last_seq); 11056698a3d0SJack Xiao sync_seq = ring->fence_drv.sync_seq; 11066698a3d0SJack Xiao 11076698a3d0SJack Xiao last_seq &= drv->num_fences_mask; 11086698a3d0SJack Xiao sync_seq &= drv->num_fences_mask; 11096698a3d0SJack Xiao 11106698a3d0SJack Xiao do { 11116698a3d0SJack Xiao struct dma_fence *fence, **ptr; 11126698a3d0SJack Xiao 11136698a3d0SJack Xiao ++last_seq; 11146698a3d0SJack Xiao last_seq &= drv->num_fences_mask; 11156698a3d0SJack Xiao ptr = &drv->fences[last_seq]; 11166698a3d0SJack Xiao 11176698a3d0SJack Xiao fence = rcu_dereference_protected(*ptr, 1); 11186698a3d0SJack Xiao RCU_INIT_POINTER(*ptr, NULL); 11196698a3d0SJack Xiao 11206698a3d0SJack Xiao if (!fence) 11216698a3d0SJack Xiao continue; 11226698a3d0SJack Xiao 11236698a3d0SJack Xiao fences[last_seq] = fence; 11246698a3d0SJack Xiao 11256698a3d0SJack Xiao } while (last_seq != sync_seq); 11266698a3d0SJack Xiao } 11276698a3d0SJack Xiao 11286698a3d0SJack Xiao static void amdgpu_ib_preempt_signal_fences(struct dma_fence **fences, 11296698a3d0SJack Xiao int length) 11306698a3d0SJack Xiao { 11316698a3d0SJack Xiao int i; 11326698a3d0SJack Xiao struct dma_fence *fence; 11336698a3d0SJack Xiao 11346698a3d0SJack Xiao for (i = 0; i < length; i++) { 11356698a3d0SJack Xiao fence = fences[i]; 11366698a3d0SJack Xiao if (!fence) 11376698a3d0SJack Xiao continue; 11386698a3d0SJack Xiao dma_fence_signal(fence); 11396698a3d0SJack Xiao dma_fence_put(fence); 11406698a3d0SJack Xiao } 11416698a3d0SJack Xiao } 11426698a3d0SJack Xiao 11436698a3d0SJack Xiao static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched) 11446698a3d0SJack Xiao { 11456698a3d0SJack Xiao struct drm_sched_job *s_job; 11466698a3d0SJack Xiao struct dma_fence *fence; 11476698a3d0SJack Xiao 11486698a3d0SJack Xiao spin_lock(&sched->job_list_lock); 11496698a3d0SJack Xiao list_for_each_entry(s_job, &sched->ring_mirror_list, node) { 11506698a3d0SJack Xiao fence = sched->ops->run_job(s_job); 11516698a3d0SJack Xiao dma_fence_put(fence); 11526698a3d0SJack Xiao } 11536698a3d0SJack Xiao spin_unlock(&sched->job_list_lock); 11546698a3d0SJack Xiao } 11556698a3d0SJack Xiao 115680f8fb91SJack Xiao static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring) 115780f8fb91SJack Xiao { 115880f8fb91SJack Xiao struct amdgpu_job *job; 115980f8fb91SJack Xiao struct drm_sched_job *s_job; 116080f8fb91SJack Xiao uint32_t preempt_seq; 116180f8fb91SJack Xiao struct dma_fence *fence, **ptr; 116280f8fb91SJack Xiao struct amdgpu_fence_driver *drv = &ring->fence_drv; 116380f8fb91SJack Xiao struct drm_gpu_scheduler *sched = &ring->sched; 116480f8fb91SJack Xiao 116580f8fb91SJack Xiao if (ring->funcs->type != AMDGPU_RING_TYPE_GFX) 116680f8fb91SJack Xiao return; 116780f8fb91SJack Xiao 116880f8fb91SJack Xiao preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2)); 116980f8fb91SJack Xiao if (preempt_seq <= atomic_read(&drv->last_seq)) 117080f8fb91SJack Xiao return; 117180f8fb91SJack Xiao 117280f8fb91SJack Xiao preempt_seq &= drv->num_fences_mask; 117380f8fb91SJack Xiao ptr = &drv->fences[preempt_seq]; 117480f8fb91SJack Xiao fence = rcu_dereference_protected(*ptr, 1); 117580f8fb91SJack Xiao 117680f8fb91SJack Xiao spin_lock(&sched->job_list_lock); 117780f8fb91SJack Xiao list_for_each_entry(s_job, &sched->ring_mirror_list, node) { 117880f8fb91SJack Xiao job = to_amdgpu_job(s_job); 117980f8fb91SJack Xiao if (job->fence == fence) 118080f8fb91SJack Xiao /* mark the job as preempted */ 118180f8fb91SJack Xiao job->preemption_status |= AMDGPU_IB_PREEMPTED; 118280f8fb91SJack Xiao } 118380f8fb91SJack Xiao spin_unlock(&sched->job_list_lock); 118480f8fb91SJack Xiao } 118580f8fb91SJack Xiao 11866698a3d0SJack Xiao static int amdgpu_debugfs_ib_preempt(void *data, u64 val) 11876698a3d0SJack Xiao { 11886698a3d0SJack Xiao int r, resched, length; 11896698a3d0SJack Xiao struct amdgpu_ring *ring; 11906698a3d0SJack Xiao struct dma_fence **fences = NULL; 11916698a3d0SJack Xiao struct amdgpu_device *adev = (struct amdgpu_device *)data; 11926698a3d0SJack Xiao 11936698a3d0SJack Xiao if (val >= AMDGPU_MAX_RINGS) 11946698a3d0SJack Xiao return -EINVAL; 11956698a3d0SJack Xiao 11966698a3d0SJack Xiao ring = adev->rings[val]; 11976698a3d0SJack Xiao 11986698a3d0SJack Xiao if (!ring || !ring->funcs->preempt_ib || !ring->sched.thread) 11996698a3d0SJack Xiao return -EINVAL; 12006698a3d0SJack Xiao 12016698a3d0SJack Xiao /* the last preemption failed */ 12026698a3d0SJack Xiao if (ring->trail_seq != le32_to_cpu(*ring->trail_fence_cpu_addr)) 12036698a3d0SJack Xiao return -EBUSY; 12046698a3d0SJack Xiao 12056698a3d0SJack Xiao length = ring->fence_drv.num_fences_mask + 1; 12066698a3d0SJack Xiao fences = kcalloc(length, sizeof(void *), GFP_KERNEL); 12076698a3d0SJack Xiao if (!fences) 12086698a3d0SJack Xiao return -ENOMEM; 12096698a3d0SJack Xiao 1210a28fda31SAndrey Grodzovsky /* Avoid accidently unparking the sched thread during GPU reset */ 1211a28fda31SAndrey Grodzovsky mutex_lock(&adev->lock_reset); 1212a28fda31SAndrey Grodzovsky 12136698a3d0SJack Xiao /* stop the scheduler */ 12146698a3d0SJack Xiao kthread_park(ring->sched.thread); 12156698a3d0SJack Xiao 12166698a3d0SJack Xiao resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); 12176698a3d0SJack Xiao 12186698a3d0SJack Xiao /* preempt the IB */ 12196698a3d0SJack Xiao r = amdgpu_ring_preempt_ib(ring); 12206698a3d0SJack Xiao if (r) { 12216698a3d0SJack Xiao DRM_WARN("failed to preempt ring %d\n", ring->idx); 12226698a3d0SJack Xiao goto failure; 12236698a3d0SJack Xiao } 12246698a3d0SJack Xiao 12256698a3d0SJack Xiao amdgpu_fence_process(ring); 12266698a3d0SJack Xiao 12276698a3d0SJack Xiao if (atomic_read(&ring->fence_drv.last_seq) != 12286698a3d0SJack Xiao ring->fence_drv.sync_seq) { 12296698a3d0SJack Xiao DRM_INFO("ring %d was preempted\n", ring->idx); 12306698a3d0SJack Xiao 123180f8fb91SJack Xiao amdgpu_ib_preempt_mark_partial_job(ring); 123280f8fb91SJack Xiao 12336698a3d0SJack Xiao /* swap out the old fences */ 12346698a3d0SJack Xiao amdgpu_ib_preempt_fences_swap(ring, fences); 12356698a3d0SJack Xiao 12366698a3d0SJack Xiao amdgpu_fence_driver_force_completion(ring); 12376698a3d0SJack Xiao 12386698a3d0SJack Xiao /* resubmit unfinished jobs */ 12396698a3d0SJack Xiao amdgpu_ib_preempt_job_recovery(&ring->sched); 12406698a3d0SJack Xiao 12416698a3d0SJack Xiao /* wait for jobs finished */ 12426698a3d0SJack Xiao amdgpu_fence_wait_empty(ring); 12436698a3d0SJack Xiao 12446698a3d0SJack Xiao /* signal the old fences */ 12456698a3d0SJack Xiao amdgpu_ib_preempt_signal_fences(fences, length); 12466698a3d0SJack Xiao } 12476698a3d0SJack Xiao 12486698a3d0SJack Xiao failure: 12496698a3d0SJack Xiao /* restart the scheduler */ 12506698a3d0SJack Xiao kthread_unpark(ring->sched.thread); 12516698a3d0SJack Xiao 1252a28fda31SAndrey Grodzovsky mutex_unlock(&adev->lock_reset); 1253a28fda31SAndrey Grodzovsky 12546698a3d0SJack Xiao ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); 12556698a3d0SJack Xiao 12566698a3d0SJack Xiao kfree(fences); 12576698a3d0SJack Xiao 12586698a3d0SJack Xiao return 0; 12596698a3d0SJack Xiao } 12606698a3d0SJack Xiao 12610cf64555SChengming Gui static int amdgpu_debugfs_sclk_set(void *data, u64 val) 12620cf64555SChengming Gui { 12630cf64555SChengming Gui int ret = 0; 12640cf64555SChengming Gui uint32_t max_freq, min_freq; 12650cf64555SChengming Gui struct amdgpu_device *adev = (struct amdgpu_device *)data; 12660cf64555SChengming Gui 12670cf64555SChengming Gui if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) 12680cf64555SChengming Gui return -EINVAL; 12690cf64555SChengming Gui 12700cf64555SChengming Gui ret = pm_runtime_get_sync(adev->ddev->dev); 12710cf64555SChengming Gui if (ret < 0) 12720cf64555SChengming Gui return ret; 12730cf64555SChengming Gui 12740cf64555SChengming Gui if (is_support_sw_smu(adev)) { 12750cf64555SChengming Gui ret = smu_get_dpm_freq_range(&adev->smu, SMU_SCLK, &min_freq, &max_freq, true); 12760cf64555SChengming Gui if (ret || val > max_freq || val < min_freq) 12770cf64555SChengming Gui return -EINVAL; 12780cf64555SChengming Gui ret = smu_set_soft_freq_range(&adev->smu, SMU_SCLK, (uint32_t)val, (uint32_t)val, true); 12790cf64555SChengming Gui } else { 12800cf64555SChengming Gui return 0; 12810cf64555SChengming Gui } 12820cf64555SChengming Gui 12830cf64555SChengming Gui pm_runtime_mark_last_busy(adev->ddev->dev); 12840cf64555SChengming Gui pm_runtime_put_autosuspend(adev->ddev->dev); 12850cf64555SChengming Gui 12860cf64555SChengming Gui if (ret) 12870cf64555SChengming Gui return -EINVAL; 12880cf64555SChengming Gui 12890cf64555SChengming Gui return 0; 12900cf64555SChengming Gui } 12910cf64555SChengming Gui 12926698a3d0SJack Xiao DEFINE_SIMPLE_ATTRIBUTE(fops_ib_preempt, NULL, 12936698a3d0SJack Xiao amdgpu_debugfs_ib_preempt, "%llu\n"); 12946698a3d0SJack Xiao 12950cf64555SChengming Gui DEFINE_SIMPLE_ATTRIBUTE(fops_sclk_set, NULL, 12960cf64555SChengming Gui amdgpu_debugfs_sclk_set, "%llu\n"); 12970cf64555SChengming Gui 129875758255SAlex Deucher int amdgpu_debugfs_init(struct amdgpu_device *adev) 129975758255SAlex Deucher { 1300fd23cfccSAlex Deucher int r, i; 1301c5820361SAlex Deucher 13026698a3d0SJack Xiao adev->debugfs_preempt = 13036698a3d0SJack Xiao debugfs_create_file("amdgpu_preempt_ib", 0600, 130444b582b3SGeert Uytterhoeven adev->ddev->primary->debugfs_root, adev, 130544b582b3SGeert Uytterhoeven &fops_ib_preempt); 13066698a3d0SJack Xiao if (!(adev->debugfs_preempt)) { 13076698a3d0SJack Xiao DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); 13086698a3d0SJack Xiao return -EIO; 13096698a3d0SJack Xiao } 13106698a3d0SJack Xiao 13110cf64555SChengming Gui adev->smu.debugfs_sclk = 13120cf64555SChengming Gui debugfs_create_file("amdgpu_force_sclk", 0200, 13130cf64555SChengming Gui adev->ddev->primary->debugfs_root, adev, 13140cf64555SChengming Gui &fops_sclk_set); 13150cf64555SChengming Gui if (!(adev->smu.debugfs_sclk)) { 13160cf64555SChengming Gui DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); 13170cf64555SChengming Gui return -EIO; 13180cf64555SChengming Gui } 13190cf64555SChengming Gui 1320c5820361SAlex Deucher /* Register debugfs entries for amdgpu_ttm */ 1321c5820361SAlex Deucher r = amdgpu_ttm_debugfs_init(adev); 1322c5820361SAlex Deucher if (r) { 1323c5820361SAlex Deucher DRM_ERROR("Failed to init debugfs\n"); 1324c5820361SAlex Deucher return r; 1325c5820361SAlex Deucher } 1326c5820361SAlex Deucher 1327a4c5b1bbSAlex Deucher r = amdgpu_debugfs_pm_init(adev); 1328a4c5b1bbSAlex Deucher if (r) { 1329a4c5b1bbSAlex Deucher DRM_ERROR("Failed to register debugfs file for dpm!\n"); 1330a4c5b1bbSAlex Deucher return r; 1331a4c5b1bbSAlex Deucher } 1332a4c5b1bbSAlex Deucher 133315997544SAlex Deucher if (amdgpu_debugfs_sa_init(adev)) { 133415997544SAlex Deucher dev_err(adev->dev, "failed to register debugfs file for SA\n"); 133515997544SAlex Deucher } 133615997544SAlex Deucher 133724038d58SAlex Deucher if (amdgpu_debugfs_fence_init(adev)) 133824038d58SAlex Deucher dev_err(adev->dev, "fence debugfs file creation failed\n"); 133924038d58SAlex Deucher 13403f5cea67SAlex Deucher r = amdgpu_debugfs_gem_init(adev); 13413f5cea67SAlex Deucher if (r) 13423f5cea67SAlex Deucher DRM_ERROR("registering gem debugfs failed (%d).\n", r); 13433f5cea67SAlex Deucher 1344f9d64e6cSAlex Deucher r = amdgpu_debugfs_regs_init(adev); 1345f9d64e6cSAlex Deucher if (r) 1346f9d64e6cSAlex Deucher DRM_ERROR("registering register debugfs failed (%d).\n", r); 1347f9d64e6cSAlex Deucher 1348cd9e29e7SAlex Deucher r = amdgpu_debugfs_firmware_init(adev); 1349cd9e29e7SAlex Deucher if (r) 1350cd9e29e7SAlex Deucher DRM_ERROR("registering firmware debugfs failed (%d).\n", r); 1351cd9e29e7SAlex Deucher 1352d090e7dbSAlex Deucher #if defined(CONFIG_DRM_AMD_DC) 1353d090e7dbSAlex Deucher if (amdgpu_device_has_dc_support(adev)) { 1354d090e7dbSAlex Deucher if (dtn_debugfs_init(adev)) 1355d090e7dbSAlex Deucher DRM_ERROR("amdgpu: failed initialize dtn debugfs support.\n"); 1356d090e7dbSAlex Deucher } 1357d090e7dbSAlex Deucher #endif 1358d090e7dbSAlex Deucher 1359fd23cfccSAlex Deucher for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { 1360fd23cfccSAlex Deucher struct amdgpu_ring *ring = adev->rings[i]; 1361fd23cfccSAlex Deucher 1362fd23cfccSAlex Deucher if (!ring) 1363fd23cfccSAlex Deucher continue; 1364fd23cfccSAlex Deucher 1365fd23cfccSAlex Deucher if (amdgpu_debugfs_ring_init(adev, ring)) { 1366fd23cfccSAlex Deucher DRM_ERROR("Failed to register debugfs file for rings !\n"); 1367fd23cfccSAlex Deucher } 1368fd23cfccSAlex Deucher } 1369fd23cfccSAlex Deucher 1370204eaac6STao Zhou amdgpu_ras_debugfs_create_all(adev); 1371204eaac6STao Zhou 137275758255SAlex Deucher return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list, 137375758255SAlex Deucher ARRAY_SIZE(amdgpu_debugfs_list)); 137475758255SAlex Deucher } 137575758255SAlex Deucher 137675758255SAlex Deucher #else 137775758255SAlex Deucher int amdgpu_debugfs_init(struct amdgpu_device *adev) 137875758255SAlex Deucher { 137975758255SAlex Deucher return 0; 138075758255SAlex Deucher } 138175758255SAlex Deucher int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) 138275758255SAlex Deucher { 138375758255SAlex Deucher return 0; 138475758255SAlex Deucher } 138575758255SAlex Deucher #endif 1386