xref: /openbsd/sys/dev/pci/drm/amd/amdgpu/amdgpu_debugfs.c (revision 8fc7c305)
1fb4d8502Sjsg /*
2fb4d8502Sjsg  * Copyright 2008 Advanced Micro Devices, Inc.
3fb4d8502Sjsg  * Copyright 2008 Red Hat Inc.
4fb4d8502Sjsg  * Copyright 2009 Jerome Glisse.
5fb4d8502Sjsg  *
6fb4d8502Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
7fb4d8502Sjsg  * copy of this software and associated documentation files (the "Software"),
8fb4d8502Sjsg  * to deal in the Software without restriction, including without limitation
9fb4d8502Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10fb4d8502Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
11fb4d8502Sjsg  * Software is furnished to do so, subject to the following conditions:
12fb4d8502Sjsg  *
13fb4d8502Sjsg  * The above copyright notice and this permission notice shall be included in
14fb4d8502Sjsg  * all copies or substantial portions of the Software.
15fb4d8502Sjsg  *
16fb4d8502Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17fb4d8502Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18fb4d8502Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19fb4d8502Sjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20fb4d8502Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21fb4d8502Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22fb4d8502Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
23fb4d8502Sjsg  *
24fb4d8502Sjsg  */
25fb4d8502Sjsg 
26fb4d8502Sjsg #include <linux/kthread.h>
27c349dbc7Sjsg #include <linux/pci.h>
28c349dbc7Sjsg #include <linux/uaccess.h>
29c349dbc7Sjsg #include <linux/pm_runtime.h>
30c349dbc7Sjsg 
31fb4d8502Sjsg #include "amdgpu.h"
32c349dbc7Sjsg #include "amdgpu_pm.h"
33c349dbc7Sjsg #include "amdgpu_dm_debugfs.h"
34c349dbc7Sjsg #include "amdgpu_ras.h"
35ad8b1aafSjsg #include "amdgpu_rap.h"
365ca02815Sjsg #include "amdgpu_securedisplay.h"
375ca02815Sjsg #include "amdgpu_fw_attestation.h"
381bb76ff1Sjsg #include "amdgpu_umr.h"
391bb76ff1Sjsg 
401bb76ff1Sjsg #include "amdgpu_reset.h"
411bb76ff1Sjsg #include "amdgpu_psp_ta.h"
42fb4d8502Sjsg 
43fb4d8502Sjsg #if defined(CONFIG_DEBUG_FS)
44fb4d8502Sjsg 
45fb4d8502Sjsg /**
46fb4d8502Sjsg  * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes
47fb4d8502Sjsg  *
48fb4d8502Sjsg  * @read: True if reading
49fb4d8502Sjsg  * @f: open file handle
50fb4d8502Sjsg  * @buf: User buffer to write/read to
51fb4d8502Sjsg  * @size: Number of bytes to write/read
52fb4d8502Sjsg  * @pos:  Offset to seek to
53fb4d8502Sjsg  *
54fb4d8502Sjsg  * This debugfs entry has special meaning on the offset being sought.
55fb4d8502Sjsg  * Various bits have different meanings:
56fb4d8502Sjsg  *
57fb4d8502Sjsg  * Bit 62:  Indicates a GRBM bank switch is needed
58fb4d8502Sjsg  * Bit 61:  Indicates a SRBM bank switch is needed (implies bit 62 is
59fb4d8502Sjsg  *	    zero)
60fb4d8502Sjsg  * Bits 24..33: The SE or ME selector if needed
61fb4d8502Sjsg  * Bits 34..43: The SH (or SA) or PIPE selector if needed
62fb4d8502Sjsg  * Bits 44..53: The INSTANCE (or CU/WGP) or QUEUE selector if needed
63fb4d8502Sjsg  *
64fb4d8502Sjsg  * Bit 23:  Indicates that the PM power gating lock should be held
65fb4d8502Sjsg  *	    This is necessary to read registers that might be
66fb4d8502Sjsg  *	    unreliable during a power gating transistion.
67fb4d8502Sjsg  *
68fb4d8502Sjsg  * The lower bits are the BYTE offset of the register to read.  This
69fb4d8502Sjsg  * allows reading multiple registers in a single call and having
70fb4d8502Sjsg  * the returned size reflect that.
71fb4d8502Sjsg  */
amdgpu_debugfs_process_reg_op(bool read,struct file * f,char __user * buf,size_t size,loff_t * pos)72fb4d8502Sjsg static int  amdgpu_debugfs_process_reg_op(bool read, struct file *f,
73fb4d8502Sjsg 		char __user *buf, size_t size, loff_t *pos)
74fb4d8502Sjsg {
75fb4d8502Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
76fb4d8502Sjsg 	ssize_t result = 0;
77fb4d8502Sjsg 	int r;
78fb4d8502Sjsg 	bool pm_pg_lock, use_bank, use_ring;
79f005ef32Sjsg 	unsigned int instance_bank, sh_bank, se_bank, me, pipe, queue, vmid;
80fb4d8502Sjsg 
81fb4d8502Sjsg 	pm_pg_lock = use_bank = use_ring = false;
82c349dbc7Sjsg 	instance_bank = sh_bank = se_bank = me = pipe = queue = vmid = 0;
83fb4d8502Sjsg 
84fb4d8502Sjsg 	if (size & 0x3 || *pos & 0x3 ||
85fb4d8502Sjsg 			((*pos & (1ULL << 62)) && (*pos & (1ULL << 61))))
86fb4d8502Sjsg 		return -EINVAL;
87fb4d8502Sjsg 
88fb4d8502Sjsg 	/* are we reading registers for which a PG lock is necessary? */
89fb4d8502Sjsg 	pm_pg_lock = (*pos >> 23) & 1;
90fb4d8502Sjsg 
91fb4d8502Sjsg 	if (*pos & (1ULL << 62)) {
92fb4d8502Sjsg 		se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24;
93fb4d8502Sjsg 		sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34;
94fb4d8502Sjsg 		instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44;
95fb4d8502Sjsg 
96fb4d8502Sjsg 		if (se_bank == 0x3FF)
97fb4d8502Sjsg 			se_bank = 0xFFFFFFFF;
98fb4d8502Sjsg 		if (sh_bank == 0x3FF)
99fb4d8502Sjsg 			sh_bank = 0xFFFFFFFF;
100fb4d8502Sjsg 		if (instance_bank == 0x3FF)
101fb4d8502Sjsg 			instance_bank = 0xFFFFFFFF;
102c349dbc7Sjsg 		use_bank = true;
103fb4d8502Sjsg 	} else if (*pos & (1ULL << 61)) {
104fb4d8502Sjsg 
105fb4d8502Sjsg 		me = (*pos & GENMASK_ULL(33, 24)) >> 24;
106fb4d8502Sjsg 		pipe = (*pos & GENMASK_ULL(43, 34)) >> 34;
107fb4d8502Sjsg 		queue = (*pos & GENMASK_ULL(53, 44)) >> 44;
108c349dbc7Sjsg 		vmid = (*pos & GENMASK_ULL(58, 54)) >> 54;
109fb4d8502Sjsg 
110c349dbc7Sjsg 		use_ring = true;
111fb4d8502Sjsg 	} else {
112c349dbc7Sjsg 		use_bank = use_ring = false;
113fb4d8502Sjsg 	}
114fb4d8502Sjsg 
115fb4d8502Sjsg 	*pos &= (1UL << 22) - 1;
116fb4d8502Sjsg 
117ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
118ad8b1aafSjsg 	if (r < 0) {
119ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
120c349dbc7Sjsg 		return r;
121ad8b1aafSjsg 	}
122ad8b1aafSjsg 
123ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
124ad8b1aafSjsg 	if (r < 0) {
125ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
126ad8b1aafSjsg 		return r;
127ad8b1aafSjsg 	}
128c349dbc7Sjsg 
129fb4d8502Sjsg 	if (use_bank) {
130fb4d8502Sjsg 		if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) ||
131c349dbc7Sjsg 		    (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) {
132ad8b1aafSjsg 			pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
133ad8b1aafSjsg 			pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
134ad8b1aafSjsg 			amdgpu_virt_disable_access_debugfs(adev);
135fb4d8502Sjsg 			return -EINVAL;
136c349dbc7Sjsg 		}
137fb4d8502Sjsg 		mutex_lock(&adev->grbm_idx_mutex);
138fb4d8502Sjsg 		amdgpu_gfx_select_se_sh(adev, se_bank,
139f005ef32Sjsg 					sh_bank, instance_bank, 0);
140fb4d8502Sjsg 	} else if (use_ring) {
141fb4d8502Sjsg 		mutex_lock(&adev->srbm_mutex);
142f005ef32Sjsg 		amdgpu_gfx_select_me_pipe_q(adev, me, pipe, queue, vmid, 0);
143fb4d8502Sjsg 	}
144fb4d8502Sjsg 
145fb4d8502Sjsg 	if (pm_pg_lock)
146fb4d8502Sjsg 		mutex_lock(&adev->pm.mutex);
147fb4d8502Sjsg 
148fb4d8502Sjsg 	while (size) {
149fb4d8502Sjsg 		uint32_t value;
150fb4d8502Sjsg 
151fb4d8502Sjsg 		if (read) {
152fb4d8502Sjsg 			value = RREG32(*pos >> 2);
153fb4d8502Sjsg 			r = put_user(value, (uint32_t *)buf);
154fb4d8502Sjsg 		} else {
155fb4d8502Sjsg 			r = get_user(value, (uint32_t *)buf);
156fb4d8502Sjsg 			if (!r)
157f005ef32Sjsg 				amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value, 0);
158fb4d8502Sjsg 		}
159fb4d8502Sjsg 		if (r) {
160fb4d8502Sjsg 			result = r;
161fb4d8502Sjsg 			goto end;
162fb4d8502Sjsg 		}
163fb4d8502Sjsg 
164fb4d8502Sjsg 		result += 4;
165fb4d8502Sjsg 		buf += 4;
166fb4d8502Sjsg 		*pos += 4;
167fb4d8502Sjsg 		size -= 4;
168fb4d8502Sjsg 	}
169fb4d8502Sjsg 
170fb4d8502Sjsg end:
171fb4d8502Sjsg 	if (use_bank) {
172f005ef32Sjsg 		amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
173fb4d8502Sjsg 		mutex_unlock(&adev->grbm_idx_mutex);
174fb4d8502Sjsg 	} else if (use_ring) {
175f005ef32Sjsg 		amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, 0);
176fb4d8502Sjsg 		mutex_unlock(&adev->srbm_mutex);
177fb4d8502Sjsg 	}
178fb4d8502Sjsg 
179fb4d8502Sjsg 	if (pm_pg_lock)
180fb4d8502Sjsg 		mutex_unlock(&adev->pm.mutex);
181fb4d8502Sjsg 
182ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
183ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
184c349dbc7Sjsg 
185ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
186fb4d8502Sjsg 	return result;
187fb4d8502Sjsg }
188fb4d8502Sjsg 
1895ca02815Sjsg /*
190fb4d8502Sjsg  * amdgpu_debugfs_regs_read - Callback for reading MMIO registers
191fb4d8502Sjsg  */
amdgpu_debugfs_regs_read(struct file * f,char __user * buf,size_t size,loff_t * pos)192fb4d8502Sjsg static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
193fb4d8502Sjsg 					size_t size, loff_t *pos)
194fb4d8502Sjsg {
195fb4d8502Sjsg 	return amdgpu_debugfs_process_reg_op(true, f, buf, size, pos);
196fb4d8502Sjsg }
197fb4d8502Sjsg 
1985ca02815Sjsg /*
199fb4d8502Sjsg  * amdgpu_debugfs_regs_write - Callback for writing MMIO registers
200fb4d8502Sjsg  */
amdgpu_debugfs_regs_write(struct file * f,const char __user * buf,size_t size,loff_t * pos)201fb4d8502Sjsg static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf,
202fb4d8502Sjsg 					 size_t size, loff_t *pos)
203fb4d8502Sjsg {
204fb4d8502Sjsg 	return amdgpu_debugfs_process_reg_op(false, f, (char __user *)buf, size, pos);
205fb4d8502Sjsg }
206fb4d8502Sjsg 
amdgpu_debugfs_regs2_open(struct inode * inode,struct file * file)2071bb76ff1Sjsg static int amdgpu_debugfs_regs2_open(struct inode *inode, struct file *file)
2081bb76ff1Sjsg {
2091bb76ff1Sjsg 	struct amdgpu_debugfs_regs2_data *rd;
2101bb76ff1Sjsg 
211f005ef32Sjsg 	rd = kzalloc(sizeof(*rd), GFP_KERNEL);
2121bb76ff1Sjsg 	if (!rd)
2131bb76ff1Sjsg 		return -ENOMEM;
2141bb76ff1Sjsg 	rd->adev = file_inode(file)->i_private;
2151bb76ff1Sjsg 	file->private_data = rd;
2161bb76ff1Sjsg 	mutex_init(&rd->lock);
2171bb76ff1Sjsg 
2181bb76ff1Sjsg 	return 0;
2191bb76ff1Sjsg }
2201bb76ff1Sjsg 
amdgpu_debugfs_regs2_release(struct inode * inode,struct file * file)2211bb76ff1Sjsg static int amdgpu_debugfs_regs2_release(struct inode *inode, struct file *file)
2221bb76ff1Sjsg {
2231bb76ff1Sjsg 	struct amdgpu_debugfs_regs2_data *rd = file->private_data;
224f005ef32Sjsg 
2251bb76ff1Sjsg 	mutex_destroy(&rd->lock);
2261bb76ff1Sjsg 	kfree(file->private_data);
2271bb76ff1Sjsg 	return 0;
2281bb76ff1Sjsg }
2291bb76ff1Sjsg 
amdgpu_debugfs_regs2_op(struct file * f,char __user * buf,u32 offset,size_t size,int write_en)2301bb76ff1Sjsg static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 offset, size_t size, int write_en)
2311bb76ff1Sjsg {
2321bb76ff1Sjsg 	struct amdgpu_debugfs_regs2_data *rd = f->private_data;
2331bb76ff1Sjsg 	struct amdgpu_device *adev = rd->adev;
2341bb76ff1Sjsg 	ssize_t result = 0;
2351bb76ff1Sjsg 	int r;
2361bb76ff1Sjsg 	uint32_t value;
2371bb76ff1Sjsg 
2381bb76ff1Sjsg 	if (size & 0x3 || offset & 0x3)
2391bb76ff1Sjsg 		return -EINVAL;
2401bb76ff1Sjsg 
2411bb76ff1Sjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
2421bb76ff1Sjsg 	if (r < 0) {
2431bb76ff1Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
2441bb76ff1Sjsg 		return r;
2451bb76ff1Sjsg 	}
2461bb76ff1Sjsg 
2471bb76ff1Sjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
2481bb76ff1Sjsg 	if (r < 0) {
2491bb76ff1Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
2501bb76ff1Sjsg 		return r;
2511bb76ff1Sjsg 	}
2521bb76ff1Sjsg 
2531bb76ff1Sjsg 	mutex_lock(&rd->lock);
2541bb76ff1Sjsg 
2551bb76ff1Sjsg 	if (rd->id.use_grbm) {
2561bb76ff1Sjsg 		if ((rd->id.grbm.sh != 0xFFFFFFFF && rd->id.grbm.sh >= adev->gfx.config.max_sh_per_se) ||
2571bb76ff1Sjsg 		    (rd->id.grbm.se != 0xFFFFFFFF && rd->id.grbm.se >= adev->gfx.config.max_shader_engines)) {
2581bb76ff1Sjsg 			pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
2591bb76ff1Sjsg 			pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
2601bb76ff1Sjsg 			amdgpu_virt_disable_access_debugfs(adev);
2611bb76ff1Sjsg 			mutex_unlock(&rd->lock);
2621bb76ff1Sjsg 			return -EINVAL;
2631bb76ff1Sjsg 		}
2641bb76ff1Sjsg 		mutex_lock(&adev->grbm_idx_mutex);
2651bb76ff1Sjsg 		amdgpu_gfx_select_se_sh(adev, rd->id.grbm.se,
2661bb76ff1Sjsg 						  rd->id.grbm.sh,
267f005ef32Sjsg 						  rd->id.grbm.instance, rd->id.xcc_id);
2681bb76ff1Sjsg 	}
2691bb76ff1Sjsg 
2701bb76ff1Sjsg 	if (rd->id.use_srbm) {
2711bb76ff1Sjsg 		mutex_lock(&adev->srbm_mutex);
2721bb76ff1Sjsg 		amdgpu_gfx_select_me_pipe_q(adev, rd->id.srbm.me, rd->id.srbm.pipe,
273f005ef32Sjsg 					    rd->id.srbm.queue, rd->id.srbm.vmid, rd->id.xcc_id);
2741bb76ff1Sjsg 	}
2751bb76ff1Sjsg 
2761bb76ff1Sjsg 	if (rd->id.pg_lock)
2771bb76ff1Sjsg 		mutex_lock(&adev->pm.mutex);
2781bb76ff1Sjsg 
2791bb76ff1Sjsg 	while (size) {
2801bb76ff1Sjsg 		if (!write_en) {
2811bb76ff1Sjsg 			value = RREG32(offset >> 2);
2821bb76ff1Sjsg 			r = put_user(value, (uint32_t *)buf);
2831bb76ff1Sjsg 		} else {
2841bb76ff1Sjsg 			r = get_user(value, (uint32_t *)buf);
2851bb76ff1Sjsg 			if (!r)
286f005ef32Sjsg 				amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, value, rd->id.xcc_id);
2871bb76ff1Sjsg 		}
2881bb76ff1Sjsg 		if (r) {
2891bb76ff1Sjsg 			result = r;
2901bb76ff1Sjsg 			goto end;
2911bb76ff1Sjsg 		}
2921bb76ff1Sjsg 		offset += 4;
2931bb76ff1Sjsg 		size -= 4;
2941bb76ff1Sjsg 		result += 4;
2951bb76ff1Sjsg 		buf += 4;
2961bb76ff1Sjsg 	}
2971bb76ff1Sjsg end:
2981bb76ff1Sjsg 	if (rd->id.use_grbm) {
299f005ef32Sjsg 		amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, rd->id.xcc_id);
3001bb76ff1Sjsg 		mutex_unlock(&adev->grbm_idx_mutex);
3011bb76ff1Sjsg 	}
3021bb76ff1Sjsg 
3031bb76ff1Sjsg 	if (rd->id.use_srbm) {
304f005ef32Sjsg 		amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, rd->id.xcc_id);
3051bb76ff1Sjsg 		mutex_unlock(&adev->srbm_mutex);
3061bb76ff1Sjsg 	}
3071bb76ff1Sjsg 
3081bb76ff1Sjsg 	if (rd->id.pg_lock)
3091bb76ff1Sjsg 		mutex_unlock(&adev->pm.mutex);
3101bb76ff1Sjsg 
3111bb76ff1Sjsg 	mutex_unlock(&rd->lock);
3121bb76ff1Sjsg 
3131bb76ff1Sjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
3141bb76ff1Sjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
3151bb76ff1Sjsg 
3161bb76ff1Sjsg 	amdgpu_virt_disable_access_debugfs(adev);
3171bb76ff1Sjsg 	return result;
3181bb76ff1Sjsg }
3191bb76ff1Sjsg 
amdgpu_debugfs_regs2_ioctl(struct file * f,unsigned int cmd,unsigned long data)3201bb76ff1Sjsg static long amdgpu_debugfs_regs2_ioctl(struct file *f, unsigned int cmd, unsigned long data)
3211bb76ff1Sjsg {
3221bb76ff1Sjsg 	struct amdgpu_debugfs_regs2_data *rd = f->private_data;
323f005ef32Sjsg 	struct amdgpu_debugfs_regs2_iocdata v1_data;
3241bb76ff1Sjsg 	int r;
3251bb76ff1Sjsg 
3261bb76ff1Sjsg 	mutex_lock(&rd->lock);
327f005ef32Sjsg 
328f005ef32Sjsg 	switch (cmd) {
329f005ef32Sjsg 	case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE_V2:
330f005ef32Sjsg 		r = copy_from_user(&rd->id, (struct amdgpu_debugfs_regs2_iocdata_v2 *)data,
331f005ef32Sjsg 				   sizeof(rd->id));
332f005ef32Sjsg 		if (r)
333f005ef32Sjsg 			r = -EINVAL;
334f005ef32Sjsg 		goto done;
335f005ef32Sjsg 	case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE:
336f005ef32Sjsg 		r = copy_from_user(&v1_data, (struct amdgpu_debugfs_regs2_iocdata *)data,
337f005ef32Sjsg 				   sizeof(v1_data));
338f005ef32Sjsg 		if (r) {
339f005ef32Sjsg 			r = -EINVAL;
340f005ef32Sjsg 			goto done;
3411bb76ff1Sjsg 		}
342f005ef32Sjsg 		goto v1_copy;
343f005ef32Sjsg 	default:
344f005ef32Sjsg 		r = -EINVAL;
345f005ef32Sjsg 		goto done;
346f005ef32Sjsg 	}
347f005ef32Sjsg 
348f005ef32Sjsg v1_copy:
349f005ef32Sjsg 	rd->id.use_srbm = v1_data.use_srbm;
350f005ef32Sjsg 	rd->id.use_grbm = v1_data.use_grbm;
351f005ef32Sjsg 	rd->id.pg_lock = v1_data.pg_lock;
352f005ef32Sjsg 	rd->id.grbm.se = v1_data.grbm.se;
353f005ef32Sjsg 	rd->id.grbm.sh = v1_data.grbm.sh;
354f005ef32Sjsg 	rd->id.grbm.instance = v1_data.grbm.instance;
355f005ef32Sjsg 	rd->id.srbm.me = v1_data.srbm.me;
356f005ef32Sjsg 	rd->id.srbm.pipe = v1_data.srbm.pipe;
357f005ef32Sjsg 	rd->id.srbm.queue = v1_data.srbm.queue;
358f005ef32Sjsg 	rd->id.xcc_id = 0;
359f005ef32Sjsg done:
360f005ef32Sjsg 	mutex_unlock(&rd->lock);
361f005ef32Sjsg 	return r;
3621bb76ff1Sjsg }
3631bb76ff1Sjsg 
amdgpu_debugfs_regs2_read(struct file * f,char __user * buf,size_t size,loff_t * pos)3641bb76ff1Sjsg static ssize_t amdgpu_debugfs_regs2_read(struct file *f, char __user *buf, size_t size, loff_t *pos)
3651bb76ff1Sjsg {
3661bb76ff1Sjsg 	return amdgpu_debugfs_regs2_op(f, buf, *pos, size, 0);
3671bb76ff1Sjsg }
3681bb76ff1Sjsg 
amdgpu_debugfs_regs2_write(struct file * f,const char __user * buf,size_t size,loff_t * pos)3691bb76ff1Sjsg static ssize_t amdgpu_debugfs_regs2_write(struct file *f, const char __user *buf, size_t size, loff_t *pos)
3701bb76ff1Sjsg {
3711bb76ff1Sjsg 	return amdgpu_debugfs_regs2_op(f, (char __user *)buf, *pos, size, 1);
3721bb76ff1Sjsg }
3731bb76ff1Sjsg 
amdgpu_debugfs_gprwave_open(struct inode * inode,struct file * file)374f005ef32Sjsg static int amdgpu_debugfs_gprwave_open(struct inode *inode, struct file *file)
375f005ef32Sjsg {
376f005ef32Sjsg 	struct amdgpu_debugfs_gprwave_data *rd;
377f005ef32Sjsg 
378f005ef32Sjsg 	rd = kzalloc(sizeof(*rd), GFP_KERNEL);
379f005ef32Sjsg 	if (!rd)
380f005ef32Sjsg 		return -ENOMEM;
381f005ef32Sjsg 	rd->adev = file_inode(file)->i_private;
382f005ef32Sjsg 	file->private_data = rd;
383f005ef32Sjsg 	mutex_init(&rd->lock);
384f005ef32Sjsg 
385f005ef32Sjsg 	return 0;
386f005ef32Sjsg }
387f005ef32Sjsg 
amdgpu_debugfs_gprwave_release(struct inode * inode,struct file * file)388f005ef32Sjsg static int amdgpu_debugfs_gprwave_release(struct inode *inode, struct file *file)
389f005ef32Sjsg {
390f005ef32Sjsg 	struct amdgpu_debugfs_gprwave_data *rd = file->private_data;
391f005ef32Sjsg 
392f005ef32Sjsg 	mutex_destroy(&rd->lock);
393f005ef32Sjsg 	kfree(file->private_data);
394f005ef32Sjsg 	return 0;
395f005ef32Sjsg }
396f005ef32Sjsg 
amdgpu_debugfs_gprwave_read(struct file * f,char __user * buf,size_t size,loff_t * pos)397f005ef32Sjsg static ssize_t amdgpu_debugfs_gprwave_read(struct file *f, char __user *buf, size_t size, loff_t *pos)
398f005ef32Sjsg {
399f005ef32Sjsg 	struct amdgpu_debugfs_gprwave_data *rd = f->private_data;
400f005ef32Sjsg 	struct amdgpu_device *adev = rd->adev;
401f005ef32Sjsg 	ssize_t result = 0;
402f005ef32Sjsg 	int r;
403f005ef32Sjsg 	uint32_t *data, x;
404f005ef32Sjsg 
405f005ef32Sjsg 	if (size & 0x3 || *pos & 0x3)
406f005ef32Sjsg 		return -EINVAL;
407f005ef32Sjsg 
408f005ef32Sjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
409f005ef32Sjsg 	if (r < 0) {
410f005ef32Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
411f005ef32Sjsg 		return r;
412f005ef32Sjsg 	}
413f005ef32Sjsg 
414f005ef32Sjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
415f005ef32Sjsg 	if (r < 0) {
416f005ef32Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
417f005ef32Sjsg 		return r;
418f005ef32Sjsg 	}
419f005ef32Sjsg 
420f005ef32Sjsg 	data = kcalloc(1024, sizeof(*data), GFP_KERNEL);
421f005ef32Sjsg 	if (!data) {
422f005ef32Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
423f005ef32Sjsg 		amdgpu_virt_disable_access_debugfs(adev);
424f005ef32Sjsg 		return -ENOMEM;
425f005ef32Sjsg 	}
426f005ef32Sjsg 
427f005ef32Sjsg 	/* switch to the specific se/sh/cu */
428f005ef32Sjsg 	mutex_lock(&adev->grbm_idx_mutex);
429f005ef32Sjsg 	amdgpu_gfx_select_se_sh(adev, rd->id.se, rd->id.sh, rd->id.cu, rd->id.xcc_id);
430f005ef32Sjsg 
431f005ef32Sjsg 	if (!rd->id.gpr_or_wave) {
432f005ef32Sjsg 		x = 0;
433f005ef32Sjsg 		if (adev->gfx.funcs->read_wave_data)
434f005ef32Sjsg 			adev->gfx.funcs->read_wave_data(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, data, &x);
435f005ef32Sjsg 	} else {
436f005ef32Sjsg 		x = size >> 2;
437f005ef32Sjsg 		if (rd->id.gpr.vpgr_or_sgpr) {
438f005ef32Sjsg 			if (adev->gfx.funcs->read_wave_vgprs)
439f005ef32Sjsg 				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);
440f005ef32Sjsg 		} else {
441f005ef32Sjsg 			if (adev->gfx.funcs->read_wave_sgprs)
442f005ef32Sjsg 				adev->gfx.funcs->read_wave_sgprs(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, *pos, size>>2, data);
443f005ef32Sjsg 		}
444f005ef32Sjsg 	}
445f005ef32Sjsg 
446f005ef32Sjsg 	amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, rd->id.xcc_id);
447f005ef32Sjsg 	mutex_unlock(&adev->grbm_idx_mutex);
448f005ef32Sjsg 
449f005ef32Sjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
450f005ef32Sjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
451f005ef32Sjsg 
452f005ef32Sjsg 	if (!x) {
453f005ef32Sjsg 		result = -EINVAL;
454f005ef32Sjsg 		goto done;
455f005ef32Sjsg 	}
456f005ef32Sjsg 
457f005ef32Sjsg 	while (size && (*pos < x * 4)) {
458f005ef32Sjsg 		uint32_t value;
459f005ef32Sjsg 
460f005ef32Sjsg 		value = data[*pos >> 2];
461f005ef32Sjsg 		r = put_user(value, (uint32_t *)buf);
462f005ef32Sjsg 		if (r) {
463f005ef32Sjsg 			result = r;
464f005ef32Sjsg 			goto done;
465f005ef32Sjsg 		}
466f005ef32Sjsg 
467f005ef32Sjsg 		result += 4;
468f005ef32Sjsg 		buf += 4;
469f005ef32Sjsg 		*pos += 4;
470f005ef32Sjsg 		size -= 4;
471f005ef32Sjsg 	}
472f005ef32Sjsg 
473f005ef32Sjsg done:
474f005ef32Sjsg 	amdgpu_virt_disable_access_debugfs(adev);
475f005ef32Sjsg 	kfree(data);
476f005ef32Sjsg 	return result;
477f005ef32Sjsg }
478f005ef32Sjsg 
amdgpu_debugfs_gprwave_ioctl(struct file * f,unsigned int cmd,unsigned long data)479f005ef32Sjsg static long amdgpu_debugfs_gprwave_ioctl(struct file *f, unsigned int cmd, unsigned long data)
480f005ef32Sjsg {
481f005ef32Sjsg 	struct amdgpu_debugfs_gprwave_data *rd = f->private_data;
482f005ef32Sjsg 	int r = 0;
483f005ef32Sjsg 
484f005ef32Sjsg 	mutex_lock(&rd->lock);
485f005ef32Sjsg 
486f005ef32Sjsg 	switch (cmd) {
487f005ef32Sjsg 	case AMDGPU_DEBUGFS_GPRWAVE_IOC_SET_STATE:
488f005ef32Sjsg 		if (copy_from_user(&rd->id,
489f005ef32Sjsg 				   (struct amdgpu_debugfs_gprwave_iocdata *)data,
490f005ef32Sjsg 				   sizeof(rd->id)))
491f005ef32Sjsg 			r = -EFAULT;
492f005ef32Sjsg 		goto done;
493f005ef32Sjsg 	default:
494f005ef32Sjsg 		r = -EINVAL;
495f005ef32Sjsg 		goto done;
496f005ef32Sjsg 	}
497f005ef32Sjsg 
498f005ef32Sjsg done:
499f005ef32Sjsg 	mutex_unlock(&rd->lock);
500f005ef32Sjsg 	return r;
501f005ef32Sjsg }
502f005ef32Sjsg 
503f005ef32Sjsg 
504f005ef32Sjsg 
505fb4d8502Sjsg 
506fb4d8502Sjsg /**
507fb4d8502Sjsg  * amdgpu_debugfs_regs_pcie_read - Read from a PCIE register
508fb4d8502Sjsg  *
509fb4d8502Sjsg  * @f: open file handle
510fb4d8502Sjsg  * @buf: User buffer to store read data in
511fb4d8502Sjsg  * @size: Number of bytes to read
512fb4d8502Sjsg  * @pos:  Offset to seek to
513fb4d8502Sjsg  *
514fb4d8502Sjsg  * The lower bits are the BYTE offset of the register to read.  This
515fb4d8502Sjsg  * allows reading multiple registers in a single call and having
516fb4d8502Sjsg  * the returned size reflect that.
517fb4d8502Sjsg  */
amdgpu_debugfs_regs_pcie_read(struct file * f,char __user * buf,size_t size,loff_t * pos)518fb4d8502Sjsg static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf,
519fb4d8502Sjsg 					size_t size, loff_t *pos)
520fb4d8502Sjsg {
521fb4d8502Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
522fb4d8502Sjsg 	ssize_t result = 0;
523fb4d8502Sjsg 	int r;
524fb4d8502Sjsg 
525fb4d8502Sjsg 	if (size & 0x3 || *pos & 0x3)
526fb4d8502Sjsg 		return -EINVAL;
527fb4d8502Sjsg 
528ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
529ad8b1aafSjsg 	if (r < 0) {
530ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
531c349dbc7Sjsg 		return r;
532ad8b1aafSjsg 	}
533ad8b1aafSjsg 
534ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
535ad8b1aafSjsg 	if (r < 0) {
536ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
537ad8b1aafSjsg 		return r;
538ad8b1aafSjsg 	}
539c349dbc7Sjsg 
540fb4d8502Sjsg 	while (size) {
541fb4d8502Sjsg 		uint32_t value;
542fb4d8502Sjsg 
543ad8b1aafSjsg 		value = RREG32_PCIE(*pos);
544fb4d8502Sjsg 		r = put_user(value, (uint32_t *)buf);
5451bb76ff1Sjsg 		if (r)
5461bb76ff1Sjsg 			goto out;
547fb4d8502Sjsg 
548fb4d8502Sjsg 		result += 4;
549fb4d8502Sjsg 		buf += 4;
550fb4d8502Sjsg 		*pos += 4;
551fb4d8502Sjsg 		size -= 4;
552fb4d8502Sjsg 	}
553fb4d8502Sjsg 
5541bb76ff1Sjsg 	r = result;
5551bb76ff1Sjsg out:
556ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
557ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
558ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
5591bb76ff1Sjsg 	return r;
560fb4d8502Sjsg }
561fb4d8502Sjsg 
562fb4d8502Sjsg /**
563fb4d8502Sjsg  * amdgpu_debugfs_regs_pcie_write - Write to a PCIE register
564fb4d8502Sjsg  *
565fb4d8502Sjsg  * @f: open file handle
566fb4d8502Sjsg  * @buf: User buffer to write data from
567fb4d8502Sjsg  * @size: Number of bytes to write
568fb4d8502Sjsg  * @pos:  Offset to seek to
569fb4d8502Sjsg  *
570fb4d8502Sjsg  * The lower bits are the BYTE offset of the register to write.  This
571fb4d8502Sjsg  * allows writing multiple registers in a single call and having
572fb4d8502Sjsg  * the returned size reflect that.
573fb4d8502Sjsg  */
amdgpu_debugfs_regs_pcie_write(struct file * f,const char __user * buf,size_t size,loff_t * pos)574fb4d8502Sjsg static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf,
575fb4d8502Sjsg 					 size_t size, loff_t *pos)
576fb4d8502Sjsg {
577fb4d8502Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
578fb4d8502Sjsg 	ssize_t result = 0;
579fb4d8502Sjsg 	int r;
580fb4d8502Sjsg 
581fb4d8502Sjsg 	if (size & 0x3 || *pos & 0x3)
582fb4d8502Sjsg 		return -EINVAL;
583fb4d8502Sjsg 
584ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
585ad8b1aafSjsg 	if (r < 0) {
586ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
587c349dbc7Sjsg 		return r;
588ad8b1aafSjsg 	}
589ad8b1aafSjsg 
590ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
591ad8b1aafSjsg 	if (r < 0) {
592ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
593ad8b1aafSjsg 		return r;
594ad8b1aafSjsg 	}
595c349dbc7Sjsg 
596fb4d8502Sjsg 	while (size) {
597fb4d8502Sjsg 		uint32_t value;
598fb4d8502Sjsg 
599fb4d8502Sjsg 		r = get_user(value, (uint32_t *)buf);
6001bb76ff1Sjsg 		if (r)
6011bb76ff1Sjsg 			goto out;
602fb4d8502Sjsg 
603ad8b1aafSjsg 		WREG32_PCIE(*pos, value);
604fb4d8502Sjsg 
605fb4d8502Sjsg 		result += 4;
606fb4d8502Sjsg 		buf += 4;
607fb4d8502Sjsg 		*pos += 4;
608fb4d8502Sjsg 		size -= 4;
609fb4d8502Sjsg 	}
610fb4d8502Sjsg 
6111bb76ff1Sjsg 	r = result;
6121bb76ff1Sjsg out:
613ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
614ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
615ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
6161bb76ff1Sjsg 	return r;
617fb4d8502Sjsg }
618fb4d8502Sjsg 
619fb4d8502Sjsg /**
620fb4d8502Sjsg  * amdgpu_debugfs_regs_didt_read - Read from a DIDT register
621fb4d8502Sjsg  *
622fb4d8502Sjsg  * @f: open file handle
623fb4d8502Sjsg  * @buf: User buffer to store read data in
624fb4d8502Sjsg  * @size: Number of bytes to read
625fb4d8502Sjsg  * @pos:  Offset to seek to
626fb4d8502Sjsg  *
627fb4d8502Sjsg  * The lower bits are the BYTE offset of the register to read.  This
628fb4d8502Sjsg  * allows reading multiple registers in a single call and having
629fb4d8502Sjsg  * the returned size reflect that.
630fb4d8502Sjsg  */
amdgpu_debugfs_regs_didt_read(struct file * f,char __user * buf,size_t size,loff_t * pos)631fb4d8502Sjsg static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf,
632fb4d8502Sjsg 					size_t size, loff_t *pos)
633fb4d8502Sjsg {
634fb4d8502Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
635fb4d8502Sjsg 	ssize_t result = 0;
636fb4d8502Sjsg 	int r;
637fb4d8502Sjsg 
638fb4d8502Sjsg 	if (size & 0x3 || *pos & 0x3)
639fb4d8502Sjsg 		return -EINVAL;
640fb4d8502Sjsg 
64141d7f58fSjsg 	if (!adev->didt_rreg)
64241d7f58fSjsg 		return -EOPNOTSUPP;
64341d7f58fSjsg 
644ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
645ad8b1aafSjsg 	if (r < 0) {
646ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
647c349dbc7Sjsg 		return r;
648ad8b1aafSjsg 	}
649ad8b1aafSjsg 
650ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
651ad8b1aafSjsg 	if (r < 0) {
652ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
653ad8b1aafSjsg 		return r;
654ad8b1aafSjsg 	}
655c349dbc7Sjsg 
656fb4d8502Sjsg 	while (size) {
657fb4d8502Sjsg 		uint32_t value;
658fb4d8502Sjsg 
659fb4d8502Sjsg 		value = RREG32_DIDT(*pos >> 2);
660fb4d8502Sjsg 		r = put_user(value, (uint32_t *)buf);
6611bb76ff1Sjsg 		if (r)
6621bb76ff1Sjsg 			goto out;
663fb4d8502Sjsg 
664fb4d8502Sjsg 		result += 4;
665fb4d8502Sjsg 		buf += 4;
666fb4d8502Sjsg 		*pos += 4;
667fb4d8502Sjsg 		size -= 4;
668fb4d8502Sjsg 	}
669fb4d8502Sjsg 
6701bb76ff1Sjsg 	r = result;
6711bb76ff1Sjsg out:
672ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
673ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
674ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
6751bb76ff1Sjsg 	return r;
676fb4d8502Sjsg }
677fb4d8502Sjsg 
678fb4d8502Sjsg /**
679fb4d8502Sjsg  * amdgpu_debugfs_regs_didt_write - Write to a DIDT register
680fb4d8502Sjsg  *
681fb4d8502Sjsg  * @f: open file handle
682fb4d8502Sjsg  * @buf: User buffer to write data from
683fb4d8502Sjsg  * @size: Number of bytes to write
684fb4d8502Sjsg  * @pos:  Offset to seek to
685fb4d8502Sjsg  *
686fb4d8502Sjsg  * The lower bits are the BYTE offset of the register to write.  This
687fb4d8502Sjsg  * allows writing multiple registers in a single call and having
688fb4d8502Sjsg  * the returned size reflect that.
689fb4d8502Sjsg  */
amdgpu_debugfs_regs_didt_write(struct file * f,const char __user * buf,size_t size,loff_t * pos)690fb4d8502Sjsg static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf,
691fb4d8502Sjsg 					 size_t size, loff_t *pos)
692fb4d8502Sjsg {
693fb4d8502Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
694fb4d8502Sjsg 	ssize_t result = 0;
695fb4d8502Sjsg 	int r;
696fb4d8502Sjsg 
697fb4d8502Sjsg 	if (size & 0x3 || *pos & 0x3)
698fb4d8502Sjsg 		return -EINVAL;
699fb4d8502Sjsg 
70041d7f58fSjsg 	if (!adev->didt_wreg)
70141d7f58fSjsg 		return -EOPNOTSUPP;
70241d7f58fSjsg 
703ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
704ad8b1aafSjsg 	if (r < 0) {
705ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
706c349dbc7Sjsg 		return r;
707ad8b1aafSjsg 	}
708ad8b1aafSjsg 
709ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
710ad8b1aafSjsg 	if (r < 0) {
711ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
712ad8b1aafSjsg 		return r;
713ad8b1aafSjsg 	}
714c349dbc7Sjsg 
715fb4d8502Sjsg 	while (size) {
716fb4d8502Sjsg 		uint32_t value;
717fb4d8502Sjsg 
718fb4d8502Sjsg 		r = get_user(value, (uint32_t *)buf);
7191bb76ff1Sjsg 		if (r)
7201bb76ff1Sjsg 			goto out;
721fb4d8502Sjsg 
722fb4d8502Sjsg 		WREG32_DIDT(*pos >> 2, value);
723fb4d8502Sjsg 
724fb4d8502Sjsg 		result += 4;
725fb4d8502Sjsg 		buf += 4;
726fb4d8502Sjsg 		*pos += 4;
727fb4d8502Sjsg 		size -= 4;
728fb4d8502Sjsg 	}
729fb4d8502Sjsg 
7301bb76ff1Sjsg 	r = result;
7311bb76ff1Sjsg out:
732ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
733ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
734ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
7351bb76ff1Sjsg 	return r;
736fb4d8502Sjsg }
737fb4d8502Sjsg 
738fb4d8502Sjsg /**
739fb4d8502Sjsg  * amdgpu_debugfs_regs_smc_read - Read from a SMC register
740fb4d8502Sjsg  *
741fb4d8502Sjsg  * @f: open file handle
742fb4d8502Sjsg  * @buf: User buffer to store read data in
743fb4d8502Sjsg  * @size: Number of bytes to read
744fb4d8502Sjsg  * @pos:  Offset to seek to
745fb4d8502Sjsg  *
746fb4d8502Sjsg  * The lower bits are the BYTE offset of the register to read.  This
747fb4d8502Sjsg  * allows reading multiple registers in a single call and having
748fb4d8502Sjsg  * the returned size reflect that.
749fb4d8502Sjsg  */
amdgpu_debugfs_regs_smc_read(struct file * f,char __user * buf,size_t size,loff_t * pos)750fb4d8502Sjsg static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf,
751fb4d8502Sjsg 					size_t size, loff_t *pos)
752fb4d8502Sjsg {
753fb4d8502Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
754fb4d8502Sjsg 	ssize_t result = 0;
755fb4d8502Sjsg 	int r;
756fb4d8502Sjsg 
7579bc9405eSjsg 	if (!adev->smc_rreg)
758*8fc7c305Sjsg 		return -EOPNOTSUPP;
7599bc9405eSjsg 
760fb4d8502Sjsg 	if (size & 0x3 || *pos & 0x3)
761fb4d8502Sjsg 		return -EINVAL;
762fb4d8502Sjsg 
763ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
764ad8b1aafSjsg 	if (r < 0) {
765ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
766c349dbc7Sjsg 		return r;
767ad8b1aafSjsg 	}
768ad8b1aafSjsg 
769ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
770ad8b1aafSjsg 	if (r < 0) {
771ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
772ad8b1aafSjsg 		return r;
773ad8b1aafSjsg 	}
774c349dbc7Sjsg 
775fb4d8502Sjsg 	while (size) {
776fb4d8502Sjsg 		uint32_t value;
777fb4d8502Sjsg 
778fb4d8502Sjsg 		value = RREG32_SMC(*pos);
779fb4d8502Sjsg 		r = put_user(value, (uint32_t *)buf);
7801bb76ff1Sjsg 		if (r)
7811bb76ff1Sjsg 			goto out;
782fb4d8502Sjsg 
783fb4d8502Sjsg 		result += 4;
784fb4d8502Sjsg 		buf += 4;
785fb4d8502Sjsg 		*pos += 4;
786fb4d8502Sjsg 		size -= 4;
787fb4d8502Sjsg 	}
788fb4d8502Sjsg 
7891bb76ff1Sjsg 	r = result;
7901bb76ff1Sjsg out:
791ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
792ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
793ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
7941bb76ff1Sjsg 	return r;
795fb4d8502Sjsg }
796fb4d8502Sjsg 
797fb4d8502Sjsg /**
798fb4d8502Sjsg  * amdgpu_debugfs_regs_smc_write - Write to a SMC register
799fb4d8502Sjsg  *
800fb4d8502Sjsg  * @f: open file handle
801fb4d8502Sjsg  * @buf: User buffer to write data from
802fb4d8502Sjsg  * @size: Number of bytes to write
803fb4d8502Sjsg  * @pos:  Offset to seek to
804fb4d8502Sjsg  *
805fb4d8502Sjsg  * The lower bits are the BYTE offset of the register to write.  This
806fb4d8502Sjsg  * allows writing multiple registers in a single call and having
807fb4d8502Sjsg  * the returned size reflect that.
808fb4d8502Sjsg  */
amdgpu_debugfs_regs_smc_write(struct file * f,const char __user * buf,size_t size,loff_t * pos)809fb4d8502Sjsg static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf,
810fb4d8502Sjsg 					 size_t size, loff_t *pos)
811fb4d8502Sjsg {
812fb4d8502Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
813fb4d8502Sjsg 	ssize_t result = 0;
814fb4d8502Sjsg 	int r;
815fb4d8502Sjsg 
8169bc9405eSjsg 	if (!adev->smc_wreg)
817*8fc7c305Sjsg 		return -EOPNOTSUPP;
8189bc9405eSjsg 
819fb4d8502Sjsg 	if (size & 0x3 || *pos & 0x3)
820fb4d8502Sjsg 		return -EINVAL;
821fb4d8502Sjsg 
822ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
823ad8b1aafSjsg 	if (r < 0) {
824ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
825c349dbc7Sjsg 		return r;
826ad8b1aafSjsg 	}
827ad8b1aafSjsg 
828ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
829ad8b1aafSjsg 	if (r < 0) {
830ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
831ad8b1aafSjsg 		return r;
832ad8b1aafSjsg 	}
833c349dbc7Sjsg 
834fb4d8502Sjsg 	while (size) {
835fb4d8502Sjsg 		uint32_t value;
836fb4d8502Sjsg 
837fb4d8502Sjsg 		r = get_user(value, (uint32_t *)buf);
8381bb76ff1Sjsg 		if (r)
8391bb76ff1Sjsg 			goto out;
840fb4d8502Sjsg 
841fb4d8502Sjsg 		WREG32_SMC(*pos, value);
842fb4d8502Sjsg 
843fb4d8502Sjsg 		result += 4;
844fb4d8502Sjsg 		buf += 4;
845fb4d8502Sjsg 		*pos += 4;
846fb4d8502Sjsg 		size -= 4;
847fb4d8502Sjsg 	}
848fb4d8502Sjsg 
8491bb76ff1Sjsg 	r = result;
8501bb76ff1Sjsg out:
851ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
852ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
853ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
8541bb76ff1Sjsg 	return r;
855fb4d8502Sjsg }
856fb4d8502Sjsg 
857fb4d8502Sjsg /**
858fb4d8502Sjsg  * amdgpu_debugfs_gca_config_read - Read from gfx config data
859fb4d8502Sjsg  *
860fb4d8502Sjsg  * @f: open file handle
861fb4d8502Sjsg  * @buf: User buffer to store read data in
862fb4d8502Sjsg  * @size: Number of bytes to read
863fb4d8502Sjsg  * @pos:  Offset to seek to
864fb4d8502Sjsg  *
865fb4d8502Sjsg  * This file is used to access configuration data in a somewhat
866fb4d8502Sjsg  * stable fashion.  The format is a series of DWORDs with the first
867fb4d8502Sjsg  * indicating which revision it is.  New content is appended to the
868fb4d8502Sjsg  * end so that older software can still read the data.
869fb4d8502Sjsg  */
870fb4d8502Sjsg 
amdgpu_debugfs_gca_config_read(struct file * f,char __user * buf,size_t size,loff_t * pos)871fb4d8502Sjsg static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
872fb4d8502Sjsg 					size_t size, loff_t *pos)
873fb4d8502Sjsg {
874fb4d8502Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
875fb4d8502Sjsg 	ssize_t result = 0;
876fb4d8502Sjsg 	int r;
877fb4d8502Sjsg 	uint32_t *config, no_regs = 0;
878fb4d8502Sjsg 
879fb4d8502Sjsg 	if (size & 0x3 || *pos & 0x3)
880fb4d8502Sjsg 		return -EINVAL;
881fb4d8502Sjsg 
882fb4d8502Sjsg 	config = kmalloc_array(256, sizeof(*config), GFP_KERNEL);
883fb4d8502Sjsg 	if (!config)
884fb4d8502Sjsg 		return -ENOMEM;
885fb4d8502Sjsg 
886fb4d8502Sjsg 	/* version, increment each time something is added */
8871bb76ff1Sjsg 	config[no_regs++] = 5;
888fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.max_shader_engines;
889fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.max_tile_pipes;
890fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.max_cu_per_sh;
891fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.max_sh_per_se;
892fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.max_backends_per_se;
893fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.max_texture_channel_caches;
894fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.max_gprs;
895fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.max_gs_threads;
896fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.max_hw_contexts;
897fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_frontend;
898fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_backend;
899fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.sc_hiz_tile_fifo_size;
900fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.sc_earlyz_tile_fifo_size;
901fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.num_tile_pipes;
902fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.backend_enable_mask;
903fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.mem_max_burst_length_bytes;
904fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.mem_row_size_in_kb;
905fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.shader_engine_tile_size;
906fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.num_gpus;
907fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.multi_gpu_tile_size;
908fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.mc_arb_ramcfg;
909fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.gb_addr_config;
910fb4d8502Sjsg 	config[no_regs++] = adev->gfx.config.num_rbs;
911fb4d8502Sjsg 
912fb4d8502Sjsg 	/* rev==1 */
913fb4d8502Sjsg 	config[no_regs++] = adev->rev_id;
9141bb76ff1Sjsg 	config[no_regs++] = lower_32_bits(adev->pg_flags);
9151bb76ff1Sjsg 	config[no_regs++] = lower_32_bits(adev->cg_flags);
916fb4d8502Sjsg 
917fb4d8502Sjsg 	/* rev==2 */
918fb4d8502Sjsg 	config[no_regs++] = adev->family;
919fb4d8502Sjsg 	config[no_regs++] = adev->external_rev_id;
920fb4d8502Sjsg 
921fb4d8502Sjsg 	/* rev==3 */
922fb4d8502Sjsg 	config[no_regs++] = adev->pdev->device;
923fb4d8502Sjsg 	config[no_regs++] = adev->pdev->revision;
924fb4d8502Sjsg 	config[no_regs++] = adev->pdev->subsystem_device;
925fb4d8502Sjsg 	config[no_regs++] = adev->pdev->subsystem_vendor;
926fb4d8502Sjsg 
9271bb76ff1Sjsg 	/* rev==4 APU flag */
9281bb76ff1Sjsg 	config[no_regs++] = adev->flags & AMD_IS_APU ? 1 : 0;
9291bb76ff1Sjsg 
9301bb76ff1Sjsg 	/* rev==5 PG/CG flag upper 32bit */
9311bb76ff1Sjsg 	config[no_regs++] = upper_32_bits(adev->pg_flags);
9321bb76ff1Sjsg 	config[no_regs++] = upper_32_bits(adev->cg_flags);
9331bb76ff1Sjsg 
934fb4d8502Sjsg 	while (size && (*pos < no_regs * 4)) {
935fb4d8502Sjsg 		uint32_t value;
936fb4d8502Sjsg 
937fb4d8502Sjsg 		value = config[*pos >> 2];
938fb4d8502Sjsg 		r = put_user(value, (uint32_t *)buf);
939fb4d8502Sjsg 		if (r) {
940fb4d8502Sjsg 			kfree(config);
941fb4d8502Sjsg 			return r;
942fb4d8502Sjsg 		}
943fb4d8502Sjsg 
944fb4d8502Sjsg 		result += 4;
945fb4d8502Sjsg 		buf += 4;
946fb4d8502Sjsg 		*pos += 4;
947fb4d8502Sjsg 		size -= 4;
948fb4d8502Sjsg 	}
949fb4d8502Sjsg 
950fb4d8502Sjsg 	kfree(config);
951fb4d8502Sjsg 	return result;
952fb4d8502Sjsg }
953fb4d8502Sjsg 
954fb4d8502Sjsg /**
955fb4d8502Sjsg  * amdgpu_debugfs_sensor_read - Read from the powerplay sensors
956fb4d8502Sjsg  *
957fb4d8502Sjsg  * @f: open file handle
958fb4d8502Sjsg  * @buf: User buffer to store read data in
959fb4d8502Sjsg  * @size: Number of bytes to read
960fb4d8502Sjsg  * @pos:  Offset to seek to
961fb4d8502Sjsg  *
962fb4d8502Sjsg  * The offset is treated as the BYTE address of one of the sensors
963fb4d8502Sjsg  * enumerated in amd/include/kgd_pp_interface.h under the
964fb4d8502Sjsg  * 'amd_pp_sensors' enumeration.  For instance to read the UVD VCLK
965fb4d8502Sjsg  * you would use the offset 3 * 4 = 12.
966fb4d8502Sjsg  */
amdgpu_debugfs_sensor_read(struct file * f,char __user * buf,size_t size,loff_t * pos)967fb4d8502Sjsg static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf,
968fb4d8502Sjsg 					size_t size, loff_t *pos)
969fb4d8502Sjsg {
970fb4d8502Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
971fb4d8502Sjsg 	int idx, x, outsize, r, valuesize;
972fb4d8502Sjsg 	uint32_t values[16];
973fb4d8502Sjsg 
974fb4d8502Sjsg 	if (size & 3 || *pos & 0x3)
975fb4d8502Sjsg 		return -EINVAL;
976fb4d8502Sjsg 
977fb4d8502Sjsg 	if (!adev->pm.dpm_enabled)
978fb4d8502Sjsg 		return -EINVAL;
979fb4d8502Sjsg 
980fb4d8502Sjsg 	/* convert offset to sensor number */
981fb4d8502Sjsg 	idx = *pos >> 2;
982fb4d8502Sjsg 
983fb4d8502Sjsg 	valuesize = sizeof(values);
984c349dbc7Sjsg 
985ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
986ad8b1aafSjsg 	if (r < 0) {
987ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
988c349dbc7Sjsg 		return r;
989ad8b1aafSjsg 	}
990ad8b1aafSjsg 
991ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
992ad8b1aafSjsg 	if (r < 0) {
993ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
994ad8b1aafSjsg 		return r;
995ad8b1aafSjsg 	}
996c349dbc7Sjsg 
997fb4d8502Sjsg 	r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize);
998c349dbc7Sjsg 
999ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
1000ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1001c349dbc7Sjsg 
1002ad8b1aafSjsg 	if (r) {
1003ad8b1aafSjsg 		amdgpu_virt_disable_access_debugfs(adev);
1004c349dbc7Sjsg 		return r;
1005ad8b1aafSjsg 	}
1006fb4d8502Sjsg 
1007ad8b1aafSjsg 	if (size > valuesize) {
1008ad8b1aafSjsg 		amdgpu_virt_disable_access_debugfs(adev);
1009fb4d8502Sjsg 		return -EINVAL;
1010ad8b1aafSjsg 	}
1011fb4d8502Sjsg 
1012fb4d8502Sjsg 	outsize = 0;
1013fb4d8502Sjsg 	x = 0;
1014fb4d8502Sjsg 	if (!r) {
1015fb4d8502Sjsg 		while (size) {
1016fb4d8502Sjsg 			r = put_user(values[x++], (int32_t *)buf);
1017fb4d8502Sjsg 			buf += 4;
1018fb4d8502Sjsg 			size -= 4;
1019fb4d8502Sjsg 			outsize += 4;
1020fb4d8502Sjsg 		}
1021fb4d8502Sjsg 	}
1022fb4d8502Sjsg 
1023ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
1024fb4d8502Sjsg 	return !r ? outsize : r;
1025fb4d8502Sjsg }
1026fb4d8502Sjsg 
1027fb4d8502Sjsg /** amdgpu_debugfs_wave_read - Read WAVE STATUS data
1028fb4d8502Sjsg  *
1029fb4d8502Sjsg  * @f: open file handle
1030fb4d8502Sjsg  * @buf: User buffer to store read data in
1031fb4d8502Sjsg  * @size: Number of bytes to read
1032fb4d8502Sjsg  * @pos:  Offset to seek to
1033fb4d8502Sjsg  *
1034fb4d8502Sjsg  * The offset being sought changes which wave that the status data
1035fb4d8502Sjsg  * will be returned for.  The bits are used as follows:
1036fb4d8502Sjsg  *
1037fb4d8502Sjsg  * Bits 0..6:	Byte offset into data
1038fb4d8502Sjsg  * Bits 7..14:	SE selector
1039fb4d8502Sjsg  * Bits 15..22:	SH/SA selector
1040fb4d8502Sjsg  * Bits 23..30: CU/{WGP+SIMD} selector
1041fb4d8502Sjsg  * Bits 31..36: WAVE ID selector
1042fb4d8502Sjsg  * Bits 37..44: SIMD ID selector
1043fb4d8502Sjsg  *
1044fb4d8502Sjsg  * The returned data begins with one DWORD of version information
1045fb4d8502Sjsg  * Followed by WAVE STATUS registers relevant to the GFX IP version
1046fb4d8502Sjsg  * being used.  See gfx_v8_0_read_wave_data() for an example output.
1047fb4d8502Sjsg  */
amdgpu_debugfs_wave_read(struct file * f,char __user * buf,size_t size,loff_t * pos)1048fb4d8502Sjsg static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf,
1049fb4d8502Sjsg 					size_t size, loff_t *pos)
1050fb4d8502Sjsg {
1051fb4d8502Sjsg 	struct amdgpu_device *adev = f->f_inode->i_private;
1052fb4d8502Sjsg 	int r, x;
1053fb4d8502Sjsg 	ssize_t result = 0;
1054fb4d8502Sjsg 	uint32_t offset, se, sh, cu, wave, simd, data[32];
1055fb4d8502Sjsg 
1056fb4d8502Sjsg 	if (size & 3 || *pos & 3)
1057fb4d8502Sjsg 		return -EINVAL;
1058fb4d8502Sjsg 
1059fb4d8502Sjsg 	/* decode offset */
1060fb4d8502Sjsg 	offset = (*pos & GENMASK_ULL(6, 0));
1061fb4d8502Sjsg 	se = (*pos & GENMASK_ULL(14, 7)) >> 7;
1062fb4d8502Sjsg 	sh = (*pos & GENMASK_ULL(22, 15)) >> 15;
1063fb4d8502Sjsg 	cu = (*pos & GENMASK_ULL(30, 23)) >> 23;
1064fb4d8502Sjsg 	wave = (*pos & GENMASK_ULL(36, 31)) >> 31;
1065fb4d8502Sjsg 	simd = (*pos & GENMASK_ULL(44, 37)) >> 37;
1066fb4d8502Sjsg 
1067ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
1068ad8b1aafSjsg 	if (r < 0) {
1069ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1070c349dbc7Sjsg 		return r;
1071ad8b1aafSjsg 	}
1072ad8b1aafSjsg 
1073ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
1074ad8b1aafSjsg 	if (r < 0) {
1075ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1076ad8b1aafSjsg 		return r;
1077ad8b1aafSjsg 	}
1078c349dbc7Sjsg 
1079fb4d8502Sjsg 	/* switch to the specific se/sh/cu */
1080fb4d8502Sjsg 	mutex_lock(&adev->grbm_idx_mutex);
1081f005ef32Sjsg 	amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0);
1082fb4d8502Sjsg 
1083fb4d8502Sjsg 	x = 0;
1084fb4d8502Sjsg 	if (adev->gfx.funcs->read_wave_data)
1085f005ef32Sjsg 		adev->gfx.funcs->read_wave_data(adev, 0, simd, wave, data, &x);
1086fb4d8502Sjsg 
1087f005ef32Sjsg 	amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0);
1088fb4d8502Sjsg 	mutex_unlock(&adev->grbm_idx_mutex);
1089fb4d8502Sjsg 
1090ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
1091ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1092c349dbc7Sjsg 
1093ad8b1aafSjsg 	if (!x) {
1094ad8b1aafSjsg 		amdgpu_virt_disable_access_debugfs(adev);
1095fb4d8502Sjsg 		return -EINVAL;
1096ad8b1aafSjsg 	}
1097fb4d8502Sjsg 
1098fb4d8502Sjsg 	while (size && (offset < x * 4)) {
1099fb4d8502Sjsg 		uint32_t value;
1100fb4d8502Sjsg 
1101fb4d8502Sjsg 		value = data[offset >> 2];
1102fb4d8502Sjsg 		r = put_user(value, (uint32_t *)buf);
1103ad8b1aafSjsg 		if (r) {
1104ad8b1aafSjsg 			amdgpu_virt_disable_access_debugfs(adev);
1105fb4d8502Sjsg 			return r;
1106ad8b1aafSjsg 		}
1107fb4d8502Sjsg 
1108fb4d8502Sjsg 		result += 4;
1109fb4d8502Sjsg 		buf += 4;
1110fb4d8502Sjsg 		offset += 4;
1111fb4d8502Sjsg 		size -= 4;
1112fb4d8502Sjsg 	}
1113fb4d8502Sjsg 
1114ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
1115fb4d8502Sjsg 	return result;
1116fb4d8502Sjsg }
1117fb4d8502Sjsg 
1118fb4d8502Sjsg /** amdgpu_debugfs_gpr_read - Read wave gprs
1119fb4d8502Sjsg  *
1120fb4d8502Sjsg  * @f: open file handle
1121fb4d8502Sjsg  * @buf: User buffer to store read data in
1122fb4d8502Sjsg  * @size: Number of bytes to read
1123fb4d8502Sjsg  * @pos:  Offset to seek to
1124fb4d8502Sjsg  *
1125fb4d8502Sjsg  * The offset being sought changes which wave that the status data
1126fb4d8502Sjsg  * will be returned for.  The bits are used as follows:
1127fb4d8502Sjsg  *
1128fb4d8502Sjsg  * Bits 0..11:	Byte offset into data
1129fb4d8502Sjsg  * Bits 12..19:	SE selector
1130fb4d8502Sjsg  * Bits 20..27:	SH/SA selector
1131fb4d8502Sjsg  * Bits 28..35: CU/{WGP+SIMD} selector
1132fb4d8502Sjsg  * Bits 36..43: WAVE ID selector
1133fb4d8502Sjsg  * Bits 37..44: SIMD ID selector
1134fb4d8502Sjsg  * Bits 52..59: Thread selector
1135fb4d8502Sjsg  * Bits 60..61: Bank selector (VGPR=0,SGPR=1)
1136fb4d8502Sjsg  *
1137fb4d8502Sjsg  * The return data comes from the SGPR or VGPR register bank for
1138fb4d8502Sjsg  * the selected operational unit.
1139fb4d8502Sjsg  */
amdgpu_debugfs_gpr_read(struct file * f,char __user * buf,size_t size,loff_t * pos)1140fb4d8502Sjsg static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
1141fb4d8502Sjsg 					size_t size, loff_t *pos)
1142fb4d8502Sjsg {
1143fb4d8502Sjsg 	struct amdgpu_device *adev = f->f_inode->i_private;
1144fb4d8502Sjsg 	int r;
1145fb4d8502Sjsg 	ssize_t result = 0;
1146fb4d8502Sjsg 	uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data;
1147fb4d8502Sjsg 
11483f25a8deSjsg 	if (size > 4096 || size & 3 || *pos & 3)
1149fb4d8502Sjsg 		return -EINVAL;
1150fb4d8502Sjsg 
1151fb4d8502Sjsg 	/* decode offset */
11523f25a8deSjsg 	offset = (*pos & GENMASK_ULL(11, 0)) >> 2;
1153fb4d8502Sjsg 	se = (*pos & GENMASK_ULL(19, 12)) >> 12;
1154fb4d8502Sjsg 	sh = (*pos & GENMASK_ULL(27, 20)) >> 20;
1155fb4d8502Sjsg 	cu = (*pos & GENMASK_ULL(35, 28)) >> 28;
1156fb4d8502Sjsg 	wave = (*pos & GENMASK_ULL(43, 36)) >> 36;
1157fb4d8502Sjsg 	simd = (*pos & GENMASK_ULL(51, 44)) >> 44;
1158fb4d8502Sjsg 	thread = (*pos & GENMASK_ULL(59, 52)) >> 52;
1159fb4d8502Sjsg 	bank = (*pos & GENMASK_ULL(61, 60)) >> 60;
1160fb4d8502Sjsg 
11612be7e6d1Sjsg 	data = kcalloc(1024, sizeof(*data), GFP_KERNEL);
1162fb4d8502Sjsg 	if (!data)
1163fb4d8502Sjsg 		return -ENOMEM;
1164fb4d8502Sjsg 
1165ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
1166c349dbc7Sjsg 	if (r < 0)
1167ad8b1aafSjsg 		goto err;
1168ad8b1aafSjsg 
1169ad8b1aafSjsg 	r = amdgpu_virt_enable_access_debugfs(adev);
1170ad8b1aafSjsg 	if (r < 0)
1171ad8b1aafSjsg 		goto err;
1172c349dbc7Sjsg 
1173fb4d8502Sjsg 	/* switch to the specific se/sh/cu */
1174fb4d8502Sjsg 	mutex_lock(&adev->grbm_idx_mutex);
1175f005ef32Sjsg 	amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0);
1176fb4d8502Sjsg 
1177fb4d8502Sjsg 	if (bank == 0) {
1178fb4d8502Sjsg 		if (adev->gfx.funcs->read_wave_vgprs)
1179f005ef32Sjsg 			adev->gfx.funcs->read_wave_vgprs(adev, 0, simd, wave, thread, offset, size>>2, data);
1180fb4d8502Sjsg 	} else {
1181fb4d8502Sjsg 		if (adev->gfx.funcs->read_wave_sgprs)
1182f005ef32Sjsg 			adev->gfx.funcs->read_wave_sgprs(adev, 0, simd, wave, offset, size>>2, data);
1183fb4d8502Sjsg 	}
1184fb4d8502Sjsg 
1185f005ef32Sjsg 	amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0);
1186fb4d8502Sjsg 	mutex_unlock(&adev->grbm_idx_mutex);
1187fb4d8502Sjsg 
1188ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
1189ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1190c349dbc7Sjsg 
1191fb4d8502Sjsg 	while (size) {
1192fb4d8502Sjsg 		uint32_t value;
1193fb4d8502Sjsg 
11943f25a8deSjsg 		value = data[result >> 2];
1195fb4d8502Sjsg 		r = put_user(value, (uint32_t *)buf);
1196fb4d8502Sjsg 		if (r) {
1197ad8b1aafSjsg 			amdgpu_virt_disable_access_debugfs(adev);
1198fb4d8502Sjsg 			goto err;
1199fb4d8502Sjsg 		}
1200fb4d8502Sjsg 
1201fb4d8502Sjsg 		result += 4;
1202fb4d8502Sjsg 		buf += 4;
1203fb4d8502Sjsg 		size -= 4;
1204fb4d8502Sjsg 	}
1205fb4d8502Sjsg 
1206fb4d8502Sjsg 	kfree(data);
1207ad8b1aafSjsg 	amdgpu_virt_disable_access_debugfs(adev);
1208fb4d8502Sjsg 	return result;
1209ad8b1aafSjsg 
1210ad8b1aafSjsg err:
1211ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1212ad8b1aafSjsg 	kfree(data);
1213ad8b1aafSjsg 	return r;
1214fb4d8502Sjsg }
1215fb4d8502Sjsg 
1216c349dbc7Sjsg /**
12171bb76ff1Sjsg  * amdgpu_debugfs_gfxoff_residency_read - Read GFXOFF residency
12181bb76ff1Sjsg  *
12191bb76ff1Sjsg  * @f: open file handle
12201bb76ff1Sjsg  * @buf: User buffer to store read data in
12211bb76ff1Sjsg  * @size: Number of bytes to read
12221bb76ff1Sjsg  * @pos:  Offset to seek to
12231bb76ff1Sjsg  *
12241bb76ff1Sjsg  * Read the last residency value logged. It doesn't auto update, one needs to
12251bb76ff1Sjsg  * stop logging before getting the current value.
12261bb76ff1Sjsg  */
amdgpu_debugfs_gfxoff_residency_read(struct file * f,char __user * buf,size_t size,loff_t * pos)12271bb76ff1Sjsg static ssize_t amdgpu_debugfs_gfxoff_residency_read(struct file *f, char __user *buf,
12281bb76ff1Sjsg 						    size_t size, loff_t *pos)
12291bb76ff1Sjsg {
12301bb76ff1Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
12311bb76ff1Sjsg 	ssize_t result = 0;
12321bb76ff1Sjsg 	int r;
12331bb76ff1Sjsg 
12341bb76ff1Sjsg 	if (size & 0x3 || *pos & 0x3)
12351bb76ff1Sjsg 		return -EINVAL;
12361bb76ff1Sjsg 
12371bb76ff1Sjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
12381bb76ff1Sjsg 	if (r < 0) {
12391bb76ff1Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
12401bb76ff1Sjsg 		return r;
12411bb76ff1Sjsg 	}
12421bb76ff1Sjsg 
12431bb76ff1Sjsg 	while (size) {
12441bb76ff1Sjsg 		uint32_t value;
12451bb76ff1Sjsg 
12461bb76ff1Sjsg 		r = amdgpu_get_gfx_off_residency(adev, &value);
12471bb76ff1Sjsg 		if (r)
12481bb76ff1Sjsg 			goto out;
12491bb76ff1Sjsg 
12501bb76ff1Sjsg 		r = put_user(value, (uint32_t *)buf);
12511bb76ff1Sjsg 		if (r)
12521bb76ff1Sjsg 			goto out;
12531bb76ff1Sjsg 
12541bb76ff1Sjsg 		result += 4;
12551bb76ff1Sjsg 		buf += 4;
12561bb76ff1Sjsg 		*pos += 4;
12571bb76ff1Sjsg 		size -= 4;
12581bb76ff1Sjsg 	}
12591bb76ff1Sjsg 
12601bb76ff1Sjsg 	r = result;
12611bb76ff1Sjsg out:
12621bb76ff1Sjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
12631bb76ff1Sjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
12641bb76ff1Sjsg 
12651bb76ff1Sjsg 	return r;
12661bb76ff1Sjsg }
12671bb76ff1Sjsg 
12681bb76ff1Sjsg /**
12691bb76ff1Sjsg  * amdgpu_debugfs_gfxoff_residency_write - Log GFXOFF Residency
12701bb76ff1Sjsg  *
12711bb76ff1Sjsg  * @f: open file handle
12721bb76ff1Sjsg  * @buf: User buffer to write data from
12731bb76ff1Sjsg  * @size: Number of bytes to write
12741bb76ff1Sjsg  * @pos:  Offset to seek to
12751bb76ff1Sjsg  *
12761bb76ff1Sjsg  * Write a 32-bit non-zero to start logging; write a 32-bit zero to stop
12771bb76ff1Sjsg  */
amdgpu_debugfs_gfxoff_residency_write(struct file * f,const char __user * buf,size_t size,loff_t * pos)12781bb76ff1Sjsg static ssize_t amdgpu_debugfs_gfxoff_residency_write(struct file *f, const char __user *buf,
12791bb76ff1Sjsg 						     size_t size, loff_t *pos)
12801bb76ff1Sjsg {
12811bb76ff1Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
12821bb76ff1Sjsg 	ssize_t result = 0;
12831bb76ff1Sjsg 	int r;
12841bb76ff1Sjsg 
12851bb76ff1Sjsg 	if (size & 0x3 || *pos & 0x3)
12861bb76ff1Sjsg 		return -EINVAL;
12871bb76ff1Sjsg 
12881bb76ff1Sjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
12891bb76ff1Sjsg 	if (r < 0) {
12901bb76ff1Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
12911bb76ff1Sjsg 		return r;
12921bb76ff1Sjsg 	}
12931bb76ff1Sjsg 
12941bb76ff1Sjsg 	while (size) {
12951bb76ff1Sjsg 		u32 value;
12961bb76ff1Sjsg 
12971bb76ff1Sjsg 		r = get_user(value, (uint32_t *)buf);
12981bb76ff1Sjsg 		if (r)
12991bb76ff1Sjsg 			goto out;
13001bb76ff1Sjsg 
13011bb76ff1Sjsg 		amdgpu_set_gfx_off_residency(adev, value ? true : false);
13021bb76ff1Sjsg 
13031bb76ff1Sjsg 		result += 4;
13041bb76ff1Sjsg 		buf += 4;
13051bb76ff1Sjsg 		*pos += 4;
13061bb76ff1Sjsg 		size -= 4;
13071bb76ff1Sjsg 	}
13081bb76ff1Sjsg 
13091bb76ff1Sjsg 	r = result;
13101bb76ff1Sjsg out:
13111bb76ff1Sjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
13121bb76ff1Sjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
13131bb76ff1Sjsg 
13141bb76ff1Sjsg 	return r;
13151bb76ff1Sjsg }
13161bb76ff1Sjsg 
13171bb76ff1Sjsg 
13181bb76ff1Sjsg /**
13191bb76ff1Sjsg  * amdgpu_debugfs_gfxoff_count_read - Read GFXOFF entry count
13201bb76ff1Sjsg  *
13211bb76ff1Sjsg  * @f: open file handle
13221bb76ff1Sjsg  * @buf: User buffer to store read data in
13231bb76ff1Sjsg  * @size: Number of bytes to read
13241bb76ff1Sjsg  * @pos:  Offset to seek to
13251bb76ff1Sjsg  */
amdgpu_debugfs_gfxoff_count_read(struct file * f,char __user * buf,size_t size,loff_t * pos)13261bb76ff1Sjsg static ssize_t amdgpu_debugfs_gfxoff_count_read(struct file *f, char __user *buf,
13271bb76ff1Sjsg 						size_t size, loff_t *pos)
13281bb76ff1Sjsg {
13291bb76ff1Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
13301bb76ff1Sjsg 	ssize_t result = 0;
13311bb76ff1Sjsg 	int r;
13321bb76ff1Sjsg 
13331bb76ff1Sjsg 	if (size & 0x3 || *pos & 0x3)
13341bb76ff1Sjsg 		return -EINVAL;
13351bb76ff1Sjsg 
13361bb76ff1Sjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
13371bb76ff1Sjsg 	if (r < 0) {
13381bb76ff1Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
13391bb76ff1Sjsg 		return r;
13401bb76ff1Sjsg 	}
13411bb76ff1Sjsg 
13421bb76ff1Sjsg 	while (size) {
13431bb76ff1Sjsg 		u64 value = 0;
13441bb76ff1Sjsg 
13451bb76ff1Sjsg 		r = amdgpu_get_gfx_off_entrycount(adev, &value);
13461bb76ff1Sjsg 		if (r)
13471bb76ff1Sjsg 			goto out;
13481bb76ff1Sjsg 
13491bb76ff1Sjsg 		r = put_user(value, (u64 *)buf);
13501bb76ff1Sjsg 		if (r)
13511bb76ff1Sjsg 			goto out;
13521bb76ff1Sjsg 
13531bb76ff1Sjsg 		result += 4;
13541bb76ff1Sjsg 		buf += 4;
13551bb76ff1Sjsg 		*pos += 4;
13561bb76ff1Sjsg 		size -= 4;
13571bb76ff1Sjsg 	}
13581bb76ff1Sjsg 
13591bb76ff1Sjsg 	r = result;
13601bb76ff1Sjsg out:
13611bb76ff1Sjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
13621bb76ff1Sjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
13631bb76ff1Sjsg 
13641bb76ff1Sjsg 	return r;
13651bb76ff1Sjsg }
13661bb76ff1Sjsg 
13671bb76ff1Sjsg /**
13685ca02815Sjsg  * amdgpu_debugfs_gfxoff_write - Enable/disable GFXOFF
1369c349dbc7Sjsg  *
1370c349dbc7Sjsg  * @f: open file handle
1371c349dbc7Sjsg  * @buf: User buffer to write data from
1372c349dbc7Sjsg  * @size: Number of bytes to write
1373c349dbc7Sjsg  * @pos:  Offset to seek to
1374c349dbc7Sjsg  *
1375c349dbc7Sjsg  * Write a 32-bit zero to disable or a 32-bit non-zero to enable
1376c349dbc7Sjsg  */
amdgpu_debugfs_gfxoff_write(struct file * f,const char __user * buf,size_t size,loff_t * pos)1377c349dbc7Sjsg static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *buf,
1378c349dbc7Sjsg 					 size_t size, loff_t *pos)
1379c349dbc7Sjsg {
1380c349dbc7Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
1381c349dbc7Sjsg 	ssize_t result = 0;
1382c349dbc7Sjsg 	int r;
1383c349dbc7Sjsg 
1384c349dbc7Sjsg 	if (size & 0x3 || *pos & 0x3)
1385c349dbc7Sjsg 		return -EINVAL;
1386c349dbc7Sjsg 
1387ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
1388ad8b1aafSjsg 	if (r < 0) {
1389ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1390c349dbc7Sjsg 		return r;
1391ad8b1aafSjsg 	}
1392c349dbc7Sjsg 
1393c349dbc7Sjsg 	while (size) {
1394c349dbc7Sjsg 		uint32_t value;
1395c349dbc7Sjsg 
1396c349dbc7Sjsg 		r = get_user(value, (uint32_t *)buf);
13971bb76ff1Sjsg 		if (r)
13981bb76ff1Sjsg 			goto out;
1399c349dbc7Sjsg 
1400c349dbc7Sjsg 		amdgpu_gfx_off_ctrl(adev, value ? true : false);
1401c349dbc7Sjsg 
1402c349dbc7Sjsg 		result += 4;
1403c349dbc7Sjsg 		buf += 4;
1404c349dbc7Sjsg 		*pos += 4;
1405c349dbc7Sjsg 		size -= 4;
1406c349dbc7Sjsg 	}
1407c349dbc7Sjsg 
14081bb76ff1Sjsg 	r = result;
14091bb76ff1Sjsg out:
1410ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
1411ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1412c349dbc7Sjsg 
14131bb76ff1Sjsg 	return r;
1414c349dbc7Sjsg }
1415c349dbc7Sjsg 
1416c349dbc7Sjsg 
1417ad8b1aafSjsg /**
14185ca02815Sjsg  * amdgpu_debugfs_gfxoff_read - read gfxoff status
1419ad8b1aafSjsg  *
1420ad8b1aafSjsg  * @f: open file handle
1421ad8b1aafSjsg  * @buf: User buffer to store read data in
1422ad8b1aafSjsg  * @size: Number of bytes to read
1423ad8b1aafSjsg  * @pos:  Offset to seek to
1424ad8b1aafSjsg  */
amdgpu_debugfs_gfxoff_read(struct file * f,char __user * buf,size_t size,loff_t * pos)1425ad8b1aafSjsg static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf,
1426ad8b1aafSjsg 					 size_t size, loff_t *pos)
1427ad8b1aafSjsg {
1428ad8b1aafSjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
1429ad8b1aafSjsg 	ssize_t result = 0;
1430ad8b1aafSjsg 	int r;
1431ad8b1aafSjsg 
1432ad8b1aafSjsg 	if (size & 0x3 || *pos & 0x3)
1433ad8b1aafSjsg 		return -EINVAL;
1434ad8b1aafSjsg 
1435ad8b1aafSjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
14361bb76ff1Sjsg 	if (r < 0) {
14371bb76ff1Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1438ad8b1aafSjsg 		return r;
14391bb76ff1Sjsg 	}
1440ad8b1aafSjsg 
1441ad8b1aafSjsg 	while (size) {
14421bb76ff1Sjsg 		u32 value = adev->gfx.gfx_off_state;
1443ad8b1aafSjsg 
14441bb76ff1Sjsg 		r = put_user(value, (u32 *)buf);
14451bb76ff1Sjsg 		if (r)
14461bb76ff1Sjsg 			goto out;
1447ad8b1aafSjsg 
1448ad8b1aafSjsg 		result += 4;
1449ad8b1aafSjsg 		buf += 4;
1450ad8b1aafSjsg 		*pos += 4;
1451ad8b1aafSjsg 		size -= 4;
1452ad8b1aafSjsg 	}
1453ad8b1aafSjsg 
14541bb76ff1Sjsg 	r = result;
14551bb76ff1Sjsg out:
1456ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
1457ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1458ad8b1aafSjsg 
14591bb76ff1Sjsg 	return r;
1460ad8b1aafSjsg }
1461ad8b1aafSjsg 
amdgpu_debugfs_gfxoff_status_read(struct file * f,char __user * buf,size_t size,loff_t * pos)14621bb76ff1Sjsg static ssize_t amdgpu_debugfs_gfxoff_status_read(struct file *f, char __user *buf,
14631bb76ff1Sjsg 						 size_t size, loff_t *pos)
14641bb76ff1Sjsg {
14651bb76ff1Sjsg 	struct amdgpu_device *adev = file_inode(f)->i_private;
14661bb76ff1Sjsg 	ssize_t result = 0;
14671bb76ff1Sjsg 	int r;
14681bb76ff1Sjsg 
14691bb76ff1Sjsg 	if (size & 0x3 || *pos & 0x3)
14701bb76ff1Sjsg 		return -EINVAL;
14711bb76ff1Sjsg 
14721bb76ff1Sjsg 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
14731bb76ff1Sjsg 	if (r < 0) {
14741bb76ff1Sjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
14751bb76ff1Sjsg 		return r;
14761bb76ff1Sjsg 	}
14771bb76ff1Sjsg 
14781bb76ff1Sjsg 	while (size) {
14791bb76ff1Sjsg 		u32 value;
14801bb76ff1Sjsg 
14811bb76ff1Sjsg 		r = amdgpu_get_gfx_off_status(adev, &value);
14821bb76ff1Sjsg 		if (r)
14831bb76ff1Sjsg 			goto out;
14841bb76ff1Sjsg 
14851bb76ff1Sjsg 		r = put_user(value, (u32 *)buf);
14861bb76ff1Sjsg 		if (r)
14871bb76ff1Sjsg 			goto out;
14881bb76ff1Sjsg 
14891bb76ff1Sjsg 		result += 4;
14901bb76ff1Sjsg 		buf += 4;
14911bb76ff1Sjsg 		*pos += 4;
14921bb76ff1Sjsg 		size -= 4;
14931bb76ff1Sjsg 	}
14941bb76ff1Sjsg 
14951bb76ff1Sjsg 	r = result;
14961bb76ff1Sjsg out:
14971bb76ff1Sjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
14981bb76ff1Sjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
14991bb76ff1Sjsg 
15001bb76ff1Sjsg 	return r;
15011bb76ff1Sjsg }
15021bb76ff1Sjsg 
15031bb76ff1Sjsg static const struct file_operations amdgpu_debugfs_regs2_fops = {
15041bb76ff1Sjsg 	.owner = THIS_MODULE,
15051bb76ff1Sjsg 	.unlocked_ioctl = amdgpu_debugfs_regs2_ioctl,
15061bb76ff1Sjsg 	.read = amdgpu_debugfs_regs2_read,
15071bb76ff1Sjsg 	.write = amdgpu_debugfs_regs2_write,
15081bb76ff1Sjsg 	.open = amdgpu_debugfs_regs2_open,
15091bb76ff1Sjsg 	.release = amdgpu_debugfs_regs2_release,
15101bb76ff1Sjsg 	.llseek = default_llseek
15111bb76ff1Sjsg };
15121bb76ff1Sjsg 
1513f005ef32Sjsg static const struct file_operations amdgpu_debugfs_gprwave_fops = {
1514f005ef32Sjsg 	.owner = THIS_MODULE,
1515f005ef32Sjsg 	.unlocked_ioctl = amdgpu_debugfs_gprwave_ioctl,
1516f005ef32Sjsg 	.read = amdgpu_debugfs_gprwave_read,
1517f005ef32Sjsg 	.open = amdgpu_debugfs_gprwave_open,
1518f005ef32Sjsg 	.release = amdgpu_debugfs_gprwave_release,
1519f005ef32Sjsg 	.llseek = default_llseek
1520f005ef32Sjsg };
1521f005ef32Sjsg 
1522fb4d8502Sjsg static const struct file_operations amdgpu_debugfs_regs_fops = {
1523fb4d8502Sjsg 	.owner = THIS_MODULE,
1524fb4d8502Sjsg 	.read = amdgpu_debugfs_regs_read,
1525fb4d8502Sjsg 	.write = amdgpu_debugfs_regs_write,
1526fb4d8502Sjsg 	.llseek = default_llseek
1527fb4d8502Sjsg };
1528fb4d8502Sjsg static const struct file_operations amdgpu_debugfs_regs_didt_fops = {
1529fb4d8502Sjsg 	.owner = THIS_MODULE,
1530fb4d8502Sjsg 	.read = amdgpu_debugfs_regs_didt_read,
1531fb4d8502Sjsg 	.write = amdgpu_debugfs_regs_didt_write,
1532fb4d8502Sjsg 	.llseek = default_llseek
1533fb4d8502Sjsg };
1534fb4d8502Sjsg static const struct file_operations amdgpu_debugfs_regs_pcie_fops = {
1535fb4d8502Sjsg 	.owner = THIS_MODULE,
1536fb4d8502Sjsg 	.read = amdgpu_debugfs_regs_pcie_read,
1537fb4d8502Sjsg 	.write = amdgpu_debugfs_regs_pcie_write,
1538fb4d8502Sjsg 	.llseek = default_llseek
1539fb4d8502Sjsg };
1540fb4d8502Sjsg static const struct file_operations amdgpu_debugfs_regs_smc_fops = {
1541fb4d8502Sjsg 	.owner = THIS_MODULE,
1542fb4d8502Sjsg 	.read = amdgpu_debugfs_regs_smc_read,
1543fb4d8502Sjsg 	.write = amdgpu_debugfs_regs_smc_write,
1544fb4d8502Sjsg 	.llseek = default_llseek
1545fb4d8502Sjsg };
1546fb4d8502Sjsg 
1547fb4d8502Sjsg static const struct file_operations amdgpu_debugfs_gca_config_fops = {
1548fb4d8502Sjsg 	.owner = THIS_MODULE,
1549fb4d8502Sjsg 	.read = amdgpu_debugfs_gca_config_read,
1550fb4d8502Sjsg 	.llseek = default_llseek
1551fb4d8502Sjsg };
1552fb4d8502Sjsg 
1553fb4d8502Sjsg static const struct file_operations amdgpu_debugfs_sensors_fops = {
1554fb4d8502Sjsg 	.owner = THIS_MODULE,
1555fb4d8502Sjsg 	.read = amdgpu_debugfs_sensor_read,
1556fb4d8502Sjsg 	.llseek = default_llseek
1557fb4d8502Sjsg };
1558fb4d8502Sjsg 
1559fb4d8502Sjsg static const struct file_operations amdgpu_debugfs_wave_fops = {
1560fb4d8502Sjsg 	.owner = THIS_MODULE,
1561fb4d8502Sjsg 	.read = amdgpu_debugfs_wave_read,
1562fb4d8502Sjsg 	.llseek = default_llseek
1563fb4d8502Sjsg };
1564fb4d8502Sjsg static const struct file_operations amdgpu_debugfs_gpr_fops = {
1565fb4d8502Sjsg 	.owner = THIS_MODULE,
1566fb4d8502Sjsg 	.read = amdgpu_debugfs_gpr_read,
1567fb4d8502Sjsg 	.llseek = default_llseek
1568fb4d8502Sjsg };
1569fb4d8502Sjsg 
1570c349dbc7Sjsg static const struct file_operations amdgpu_debugfs_gfxoff_fops = {
1571c349dbc7Sjsg 	.owner = THIS_MODULE,
1572ad8b1aafSjsg 	.read = amdgpu_debugfs_gfxoff_read,
1573c349dbc7Sjsg 	.write = amdgpu_debugfs_gfxoff_write,
1574ad8b1aafSjsg 	.llseek = default_llseek
1575c349dbc7Sjsg };
1576c349dbc7Sjsg 
15771bb76ff1Sjsg static const struct file_operations amdgpu_debugfs_gfxoff_status_fops = {
15781bb76ff1Sjsg 	.owner = THIS_MODULE,
15791bb76ff1Sjsg 	.read = amdgpu_debugfs_gfxoff_status_read,
15801bb76ff1Sjsg 	.llseek = default_llseek
15811bb76ff1Sjsg };
15821bb76ff1Sjsg 
15831bb76ff1Sjsg static const struct file_operations amdgpu_debugfs_gfxoff_count_fops = {
15841bb76ff1Sjsg 	.owner = THIS_MODULE,
15851bb76ff1Sjsg 	.read = amdgpu_debugfs_gfxoff_count_read,
15861bb76ff1Sjsg 	.llseek = default_llseek
15871bb76ff1Sjsg };
15881bb76ff1Sjsg 
15891bb76ff1Sjsg static const struct file_operations amdgpu_debugfs_gfxoff_residency_fops = {
15901bb76ff1Sjsg 	.owner = THIS_MODULE,
15911bb76ff1Sjsg 	.read = amdgpu_debugfs_gfxoff_residency_read,
15921bb76ff1Sjsg 	.write = amdgpu_debugfs_gfxoff_residency_write,
15931bb76ff1Sjsg 	.llseek = default_llseek
15941bb76ff1Sjsg };
15951bb76ff1Sjsg 
1596fb4d8502Sjsg static const struct file_operations *debugfs_regs[] = {
1597fb4d8502Sjsg 	&amdgpu_debugfs_regs_fops,
15981bb76ff1Sjsg 	&amdgpu_debugfs_regs2_fops,
1599f005ef32Sjsg 	&amdgpu_debugfs_gprwave_fops,
1600fb4d8502Sjsg 	&amdgpu_debugfs_regs_didt_fops,
1601fb4d8502Sjsg 	&amdgpu_debugfs_regs_pcie_fops,
1602fb4d8502Sjsg 	&amdgpu_debugfs_regs_smc_fops,
1603fb4d8502Sjsg 	&amdgpu_debugfs_gca_config_fops,
1604fb4d8502Sjsg 	&amdgpu_debugfs_sensors_fops,
1605fb4d8502Sjsg 	&amdgpu_debugfs_wave_fops,
1606fb4d8502Sjsg 	&amdgpu_debugfs_gpr_fops,
1607c349dbc7Sjsg 	&amdgpu_debugfs_gfxoff_fops,
16081bb76ff1Sjsg 	&amdgpu_debugfs_gfxoff_status_fops,
16091bb76ff1Sjsg 	&amdgpu_debugfs_gfxoff_count_fops,
16101bb76ff1Sjsg 	&amdgpu_debugfs_gfxoff_residency_fops,
1611fb4d8502Sjsg };
1612fb4d8502Sjsg 
1613f005ef32Sjsg static const char * const debugfs_regs_names[] = {
1614fb4d8502Sjsg 	"amdgpu_regs",
16151bb76ff1Sjsg 	"amdgpu_regs2",
1616f005ef32Sjsg 	"amdgpu_gprwave",
1617fb4d8502Sjsg 	"amdgpu_regs_didt",
1618fb4d8502Sjsg 	"amdgpu_regs_pcie",
1619fb4d8502Sjsg 	"amdgpu_regs_smc",
1620fb4d8502Sjsg 	"amdgpu_gca_config",
1621fb4d8502Sjsg 	"amdgpu_sensors",
1622fb4d8502Sjsg 	"amdgpu_wave",
1623fb4d8502Sjsg 	"amdgpu_gpr",
1624c349dbc7Sjsg 	"amdgpu_gfxoff",
16251bb76ff1Sjsg 	"amdgpu_gfxoff_status",
16261bb76ff1Sjsg 	"amdgpu_gfxoff_count",
16271bb76ff1Sjsg 	"amdgpu_gfxoff_residency",
1628fb4d8502Sjsg };
1629fb4d8502Sjsg 
1630fb4d8502Sjsg /**
1631fb4d8502Sjsg  * amdgpu_debugfs_regs_init -	Initialize debugfs entries that provide
1632fb4d8502Sjsg  *				register access.
1633fb4d8502Sjsg  *
1634fb4d8502Sjsg  * @adev: The device to attach the debugfs entries to
1635fb4d8502Sjsg  */
amdgpu_debugfs_regs_init(struct amdgpu_device * adev)1636fb4d8502Sjsg int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
1637fb4d8502Sjsg {
1638ad8b1aafSjsg 	struct drm_minor *minor = adev_to_drm(adev)->primary;
1639fb4d8502Sjsg 	struct dentry *ent, *root = minor->debugfs_root;
1640c349dbc7Sjsg 	unsigned int i;
1641fb4d8502Sjsg 
1642fb4d8502Sjsg 	for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) {
1643fb4d8502Sjsg 		ent = debugfs_create_file(debugfs_regs_names[i],
1644f005ef32Sjsg 					  S_IFREG | 0444, root,
1645fb4d8502Sjsg 					  adev, debugfs_regs[i]);
1646c349dbc7Sjsg 		if (!i && !IS_ERR_OR_NULL(ent))
1647fb4d8502Sjsg 			i_size_write(ent->d_inode, adev->rmmio_size);
1648fb4d8502Sjsg 	}
1649fb4d8502Sjsg 
1650fb4d8502Sjsg 	return 0;
1651fb4d8502Sjsg }
1652fb4d8502Sjsg 
amdgpu_debugfs_test_ib_show(struct seq_file * m,void * unused)16535ca02815Sjsg static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused)
1654fb4d8502Sjsg {
1655f005ef32Sjsg 	struct amdgpu_device *adev = m->private;
16565ca02815Sjsg 	struct drm_device *dev = adev_to_drm(adev);
1657fb4d8502Sjsg 	int r = 0, i;
1658fb4d8502Sjsg 
1659c349dbc7Sjsg 	r = pm_runtime_get_sync(dev->dev);
1660ad8b1aafSjsg 	if (r < 0) {
16615ca02815Sjsg 		pm_runtime_put_autosuspend(dev->dev);
1662c349dbc7Sjsg 		return r;
1663ad8b1aafSjsg 	}
1664c349dbc7Sjsg 
1665c349dbc7Sjsg 	/* Avoid accidently unparking the sched thread during GPU reset */
16661bb76ff1Sjsg 	r = down_write_killable(&adev->reset_domain->sem);
1667ad8b1aafSjsg 	if (r)
1668ad8b1aafSjsg 		return r;
1669c349dbc7Sjsg 
1670fb4d8502Sjsg 	/* hold on the scheduler */
1671fb4d8502Sjsg 	for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
1672fb4d8502Sjsg 		struct amdgpu_ring *ring = adev->rings[i];
1673fb4d8502Sjsg 
1674fb4d8502Sjsg 		if (!ring || !ring->sched.thread)
1675fb4d8502Sjsg 			continue;
1676fb4d8502Sjsg 		kthread_park(ring->sched.thread);
1677fb4d8502Sjsg 	}
1678fb4d8502Sjsg 
1679f005ef32Sjsg 	seq_puts(m, "run ib test:\n");
1680fb4d8502Sjsg 	r = amdgpu_ib_ring_tests(adev);
1681fb4d8502Sjsg 	if (r)
1682fb4d8502Sjsg 		seq_printf(m, "ib ring tests failed (%d).\n", r);
1683fb4d8502Sjsg 	else
1684f005ef32Sjsg 		seq_puts(m, "ib ring tests passed.\n");
1685fb4d8502Sjsg 
1686fb4d8502Sjsg 	/* go on the scheduler */
1687fb4d8502Sjsg 	for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
1688fb4d8502Sjsg 		struct amdgpu_ring *ring = adev->rings[i];
1689fb4d8502Sjsg 
1690fb4d8502Sjsg 		if (!ring || !ring->sched.thread)
1691fb4d8502Sjsg 			continue;
1692fb4d8502Sjsg 		kthread_unpark(ring->sched.thread);
1693fb4d8502Sjsg 	}
1694fb4d8502Sjsg 
16951bb76ff1Sjsg 	up_write(&adev->reset_domain->sem);
1696c349dbc7Sjsg 
1697c349dbc7Sjsg 	pm_runtime_mark_last_busy(dev->dev);
1698c349dbc7Sjsg 	pm_runtime_put_autosuspend(dev->dev);
1699c349dbc7Sjsg 
1700fb4d8502Sjsg 	return 0;
1701fb4d8502Sjsg }
1702fb4d8502Sjsg 
amdgpu_debugfs_evict_vram(void * data,u64 * val)17035ca02815Sjsg static int amdgpu_debugfs_evict_vram(void *data, u64 *val)
1704fb4d8502Sjsg {
17055ca02815Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)data;
17065ca02815Sjsg 	struct drm_device *dev = adev_to_drm(adev);
17075ca02815Sjsg 	int r;
1708fb4d8502Sjsg 
17095ca02815Sjsg 	r = pm_runtime_get_sync(dev->dev);
17105ca02815Sjsg 	if (r < 0) {
17115ca02815Sjsg 		pm_runtime_put_autosuspend(dev->dev);
17125ca02815Sjsg 		return r;
17135ca02815Sjsg 	}
17145ca02815Sjsg 
17158e01f7deSjsg 	*val = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM);
17165ca02815Sjsg 
17175ca02815Sjsg 	pm_runtime_mark_last_busy(dev->dev);
17185ca02815Sjsg 	pm_runtime_put_autosuspend(dev->dev);
17195ca02815Sjsg 
1720fb4d8502Sjsg 	return 0;
1721fb4d8502Sjsg }
1722fb4d8502Sjsg 
17235ca02815Sjsg 
amdgpu_debugfs_evict_gtt(void * data,u64 * val)17245ca02815Sjsg static int amdgpu_debugfs_evict_gtt(void *data, u64 *val)
1725fb4d8502Sjsg {
17265ca02815Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)data;
17275ca02815Sjsg 	struct drm_device *dev = adev_to_drm(adev);
1728c349dbc7Sjsg 	int r;
1729c349dbc7Sjsg 
1730c349dbc7Sjsg 	r = pm_runtime_get_sync(dev->dev);
1731ad8b1aafSjsg 	if (r < 0) {
17328e01f7deSjsg 		pm_runtime_put_autosuspend(dev->dev);
1733c349dbc7Sjsg 		return r;
1734ad8b1aafSjsg 	}
1735fb4d8502Sjsg 
17368e01f7deSjsg 	*val = amdgpu_ttm_evict_resources(adev, TTM_PL_TT);
1737c349dbc7Sjsg 
1738c349dbc7Sjsg 	pm_runtime_mark_last_busy(dev->dev);
1739c349dbc7Sjsg 	pm_runtime_put_autosuspend(dev->dev);
1740c349dbc7Sjsg 
1741fb4d8502Sjsg 	return 0;
1742fb4d8502Sjsg }
1743fb4d8502Sjsg 
amdgpu_debugfs_benchmark(void * data,u64 val)17441bb76ff1Sjsg static int amdgpu_debugfs_benchmark(void *data, u64 val)
17451bb76ff1Sjsg {
17461bb76ff1Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)data;
17471bb76ff1Sjsg 	struct drm_device *dev = adev_to_drm(adev);
17481bb76ff1Sjsg 	int r;
17491bb76ff1Sjsg 
17501bb76ff1Sjsg 	r = pm_runtime_get_sync(dev->dev);
17511bb76ff1Sjsg 	if (r < 0) {
17521bb76ff1Sjsg 		pm_runtime_put_autosuspend(dev->dev);
17531bb76ff1Sjsg 		return r;
17541bb76ff1Sjsg 	}
17551bb76ff1Sjsg 
17561bb76ff1Sjsg 	r = amdgpu_benchmark(adev, val);
17571bb76ff1Sjsg 
17581bb76ff1Sjsg 	pm_runtime_mark_last_busy(dev->dev);
17591bb76ff1Sjsg 	pm_runtime_put_autosuspend(dev->dev);
17601bb76ff1Sjsg 
17611bb76ff1Sjsg 	return r;
17621bb76ff1Sjsg }
17635ca02815Sjsg 
amdgpu_debugfs_vm_info_show(struct seq_file * m,void * unused)17645ca02815Sjsg static int amdgpu_debugfs_vm_info_show(struct seq_file *m, void *unused)
1765fb4d8502Sjsg {
1766f005ef32Sjsg 	struct amdgpu_device *adev = m->private;
17675ca02815Sjsg 	struct drm_device *dev = adev_to_drm(adev);
17685ca02815Sjsg 	struct drm_file *file;
1769c349dbc7Sjsg 	int r;
1770c349dbc7Sjsg 
17715ca02815Sjsg 	r = mutex_lock_interruptible(&dev->filelist_mutex);
17725ca02815Sjsg 	if (r)
17735ca02815Sjsg 		return r;
17745ca02815Sjsg 
17755ca02815Sjsg 	list_for_each_entry(file, &dev->filelist, lhead) {
17765ca02815Sjsg 		struct amdgpu_fpriv *fpriv = file->driver_priv;
17775ca02815Sjsg 		struct amdgpu_vm *vm = &fpriv->vm;
17785ca02815Sjsg 
17795ca02815Sjsg 		seq_printf(m, "pid:%d\tProcess:%s ----------\n",
17805ca02815Sjsg 				vm->task_info.pid, vm->task_info.process_name);
17815ca02815Sjsg 		r = amdgpu_bo_reserve(vm->root.bo, true);
17825ca02815Sjsg 		if (r)
17835ca02815Sjsg 			break;
17845ca02815Sjsg 		amdgpu_debugfs_vm_bo_info(vm, m);
17855ca02815Sjsg 		amdgpu_bo_unreserve(vm->root.bo);
17865ca02815Sjsg 	}
17875ca02815Sjsg 
17885ca02815Sjsg 	mutex_unlock(&dev->filelist_mutex);
17895ca02815Sjsg 
1790c349dbc7Sjsg 	return r;
1791ad8b1aafSjsg }
1792fb4d8502Sjsg 
17935ca02815Sjsg DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_test_ib);
17945ca02815Sjsg DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_vm_info);
17955ca02815Sjsg DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_vram_fops, amdgpu_debugfs_evict_vram,
17965ca02815Sjsg 			 NULL, "%lld\n");
17975ca02815Sjsg DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_gtt_fops, amdgpu_debugfs_evict_gtt,
17985ca02815Sjsg 			 NULL, "%lld\n");
17991bb76ff1Sjsg DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_benchmark_fops, NULL, amdgpu_debugfs_benchmark,
18001bb76ff1Sjsg 			 "%lld\n");
1801fb4d8502Sjsg 
amdgpu_ib_preempt_fences_swap(struct amdgpu_ring * ring,struct dma_fence ** fences)1802c349dbc7Sjsg static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring,
1803c349dbc7Sjsg 					  struct dma_fence **fences)
1804c349dbc7Sjsg {
1805c349dbc7Sjsg 	struct amdgpu_fence_driver *drv = &ring->fence_drv;
1806c349dbc7Sjsg 	uint32_t sync_seq, last_seq;
1807c349dbc7Sjsg 
1808c349dbc7Sjsg 	last_seq = atomic_read(&ring->fence_drv.last_seq);
1809c349dbc7Sjsg 	sync_seq = ring->fence_drv.sync_seq;
1810c349dbc7Sjsg 
1811c349dbc7Sjsg 	last_seq &= drv->num_fences_mask;
1812c349dbc7Sjsg 	sync_seq &= drv->num_fences_mask;
1813c349dbc7Sjsg 
1814c349dbc7Sjsg 	do {
1815c349dbc7Sjsg 		struct dma_fence *fence, **ptr;
1816c349dbc7Sjsg 
1817c349dbc7Sjsg 		++last_seq;
1818c349dbc7Sjsg 		last_seq &= drv->num_fences_mask;
1819c349dbc7Sjsg 		ptr = &drv->fences[last_seq];
1820c349dbc7Sjsg 
1821c349dbc7Sjsg 		fence = rcu_dereference_protected(*ptr, 1);
1822c349dbc7Sjsg 		RCU_INIT_POINTER(*ptr, NULL);
1823c349dbc7Sjsg 
1824c349dbc7Sjsg 		if (!fence)
1825c349dbc7Sjsg 			continue;
1826c349dbc7Sjsg 
1827c349dbc7Sjsg 		fences[last_seq] = fence;
1828c349dbc7Sjsg 
1829c349dbc7Sjsg 	} while (last_seq != sync_seq);
1830c349dbc7Sjsg }
1831c349dbc7Sjsg 
amdgpu_ib_preempt_signal_fences(struct dma_fence ** fences,int length)1832c349dbc7Sjsg static void amdgpu_ib_preempt_signal_fences(struct dma_fence **fences,
1833c349dbc7Sjsg 					    int length)
1834c349dbc7Sjsg {
1835c349dbc7Sjsg 	int i;
1836c349dbc7Sjsg 	struct dma_fence *fence;
1837c349dbc7Sjsg 
1838c349dbc7Sjsg 	for (i = 0; i < length; i++) {
1839c349dbc7Sjsg 		fence = fences[i];
1840c349dbc7Sjsg 		if (!fence)
1841c349dbc7Sjsg 			continue;
1842c349dbc7Sjsg 		dma_fence_signal(fence);
1843c349dbc7Sjsg 		dma_fence_put(fence);
1844c349dbc7Sjsg 	}
1845c349dbc7Sjsg }
1846c349dbc7Sjsg 
amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler * sched)1847c349dbc7Sjsg static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched)
1848c349dbc7Sjsg {
1849c349dbc7Sjsg 	struct drm_sched_job *s_job;
1850c349dbc7Sjsg 	struct dma_fence *fence;
1851c349dbc7Sjsg 
1852c349dbc7Sjsg 	spin_lock(&sched->job_list_lock);
18535ca02815Sjsg 	list_for_each_entry(s_job, &sched->pending_list, list) {
1854c349dbc7Sjsg 		fence = sched->ops->run_job(s_job);
1855c349dbc7Sjsg 		dma_fence_put(fence);
1856c349dbc7Sjsg 	}
1857c349dbc7Sjsg 	spin_unlock(&sched->job_list_lock);
1858c349dbc7Sjsg }
1859c349dbc7Sjsg 
amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring * ring)1860c349dbc7Sjsg static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring)
1861c349dbc7Sjsg {
1862c349dbc7Sjsg 	struct amdgpu_job *job;
186371f14979Sjsg 	struct drm_sched_job *s_job, *tmp;
1864c349dbc7Sjsg 	uint32_t preempt_seq;
1865c349dbc7Sjsg 	struct dma_fence *fence, **ptr;
1866c349dbc7Sjsg 	struct amdgpu_fence_driver *drv = &ring->fence_drv;
1867c349dbc7Sjsg 	struct drm_gpu_scheduler *sched = &ring->sched;
186871f14979Sjsg 	bool preempted = true;
1869c349dbc7Sjsg 
1870c349dbc7Sjsg 	if (ring->funcs->type != AMDGPU_RING_TYPE_GFX)
1871c349dbc7Sjsg 		return;
1872c349dbc7Sjsg 
1873c349dbc7Sjsg 	preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2));
187471f14979Sjsg 	if (preempt_seq <= atomic_read(&drv->last_seq)) {
187571f14979Sjsg 		preempted = false;
187671f14979Sjsg 		goto no_preempt;
187771f14979Sjsg 	}
1878c349dbc7Sjsg 
1879c349dbc7Sjsg 	preempt_seq &= drv->num_fences_mask;
1880c349dbc7Sjsg 	ptr = &drv->fences[preempt_seq];
1881c349dbc7Sjsg 	fence = rcu_dereference_protected(*ptr, 1);
1882c349dbc7Sjsg 
188371f14979Sjsg no_preempt:
1884c349dbc7Sjsg 	spin_lock(&sched->job_list_lock);
18855ca02815Sjsg 	list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) {
188671f14979Sjsg 		if (dma_fence_is_signaled(&s_job->s_fence->finished)) {
188771f14979Sjsg 			/* remove job from ring_mirror_list */
18885ca02815Sjsg 			list_del_init(&s_job->list);
188971f14979Sjsg 			sched->ops->free_job(s_job);
189071f14979Sjsg 			continue;
189171f14979Sjsg 		}
1892c349dbc7Sjsg 		job = to_amdgpu_job(s_job);
18935ca02815Sjsg 		if (preempted && (&job->hw_fence) == fence)
1894c349dbc7Sjsg 			/* mark the job as preempted */
1895c349dbc7Sjsg 			job->preemption_status |= AMDGPU_IB_PREEMPTED;
1896c349dbc7Sjsg 	}
1897c349dbc7Sjsg 	spin_unlock(&sched->job_list_lock);
1898c349dbc7Sjsg }
1899c349dbc7Sjsg 
amdgpu_debugfs_ib_preempt(void * data,u64 val)1900c349dbc7Sjsg static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
1901c349dbc7Sjsg {
1902f005ef32Sjsg 	int r, length;
1903c349dbc7Sjsg 	struct amdgpu_ring *ring;
1904c349dbc7Sjsg 	struct dma_fence **fences = NULL;
1905c349dbc7Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)data;
1906c349dbc7Sjsg 
1907c349dbc7Sjsg 	if (val >= AMDGPU_MAX_RINGS)
1908c349dbc7Sjsg 		return -EINVAL;
1909c349dbc7Sjsg 
1910c349dbc7Sjsg 	ring = adev->rings[val];
1911c349dbc7Sjsg 
1912c349dbc7Sjsg 	if (!ring || !ring->funcs->preempt_ib || !ring->sched.thread)
1913c349dbc7Sjsg 		return -EINVAL;
1914c349dbc7Sjsg 
1915c349dbc7Sjsg 	/* the last preemption failed */
1916c349dbc7Sjsg 	if (ring->trail_seq != le32_to_cpu(*ring->trail_fence_cpu_addr))
1917c349dbc7Sjsg 		return -EBUSY;
1918c349dbc7Sjsg 
1919c349dbc7Sjsg 	length = ring->fence_drv.num_fences_mask + 1;
1920c349dbc7Sjsg 	fences = kcalloc(length, sizeof(void *), GFP_KERNEL);
1921c349dbc7Sjsg 	if (!fences)
1922c349dbc7Sjsg 		return -ENOMEM;
1923c349dbc7Sjsg 
1924c349dbc7Sjsg 	/* Avoid accidently unparking the sched thread during GPU reset */
19251bb76ff1Sjsg 	r = down_read_killable(&adev->reset_domain->sem);
1926ad8b1aafSjsg 	if (r)
1927ad8b1aafSjsg 		goto pro_end;
1928c349dbc7Sjsg 
1929c349dbc7Sjsg 	/* stop the scheduler */
1930c349dbc7Sjsg 	kthread_park(ring->sched.thread);
1931c349dbc7Sjsg 
1932c349dbc7Sjsg 	/* preempt the IB */
1933c349dbc7Sjsg 	r = amdgpu_ring_preempt_ib(ring);
1934c349dbc7Sjsg 	if (r) {
1935c349dbc7Sjsg 		DRM_WARN("failed to preempt ring %d\n", ring->idx);
1936c349dbc7Sjsg 		goto failure;
1937c349dbc7Sjsg 	}
1938c349dbc7Sjsg 
1939c349dbc7Sjsg 	amdgpu_fence_process(ring);
1940c349dbc7Sjsg 
1941c349dbc7Sjsg 	if (atomic_read(&ring->fence_drv.last_seq) !=
1942c349dbc7Sjsg 	    ring->fence_drv.sync_seq) {
1943c349dbc7Sjsg 		DRM_INFO("ring %d was preempted\n", ring->idx);
1944c349dbc7Sjsg 
1945c349dbc7Sjsg 		amdgpu_ib_preempt_mark_partial_job(ring);
1946c349dbc7Sjsg 
1947c349dbc7Sjsg 		/* swap out the old fences */
1948c349dbc7Sjsg 		amdgpu_ib_preempt_fences_swap(ring, fences);
1949c349dbc7Sjsg 
1950c349dbc7Sjsg 		amdgpu_fence_driver_force_completion(ring);
1951c349dbc7Sjsg 
1952c349dbc7Sjsg 		/* resubmit unfinished jobs */
1953c349dbc7Sjsg 		amdgpu_ib_preempt_job_recovery(&ring->sched);
1954c349dbc7Sjsg 
1955c349dbc7Sjsg 		/* wait for jobs finished */
1956c349dbc7Sjsg 		amdgpu_fence_wait_empty(ring);
1957c349dbc7Sjsg 
1958c349dbc7Sjsg 		/* signal the old fences */
1959c349dbc7Sjsg 		amdgpu_ib_preempt_signal_fences(fences, length);
1960c349dbc7Sjsg 	}
1961c349dbc7Sjsg 
1962c349dbc7Sjsg failure:
1963c349dbc7Sjsg 	/* restart the scheduler */
1964c349dbc7Sjsg 	kthread_unpark(ring->sched.thread);
1965c349dbc7Sjsg 
19661bb76ff1Sjsg 	up_read(&adev->reset_domain->sem);
1967c349dbc7Sjsg 
1968ad8b1aafSjsg pro_end:
1969c349dbc7Sjsg 	kfree(fences);
1970c349dbc7Sjsg 
1971ad8b1aafSjsg 	return r;
1972c349dbc7Sjsg }
1973c349dbc7Sjsg 
amdgpu_debugfs_sclk_set(void * data,u64 val)1974c349dbc7Sjsg static int amdgpu_debugfs_sclk_set(void *data, u64 val)
1975c349dbc7Sjsg {
1976c349dbc7Sjsg 	int ret = 0;
1977c349dbc7Sjsg 	uint32_t max_freq, min_freq;
1978c349dbc7Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)data;
1979c349dbc7Sjsg 
1980c349dbc7Sjsg 	if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
1981c349dbc7Sjsg 		return -EINVAL;
1982c349dbc7Sjsg 
1983ad8b1aafSjsg 	ret = pm_runtime_get_sync(adev_to_drm(adev)->dev);
1984ad8b1aafSjsg 	if (ret < 0) {
1985ad8b1aafSjsg 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
1986c349dbc7Sjsg 		return ret;
1987ad8b1aafSjsg 	}
1988c349dbc7Sjsg 
19891bb76ff1Sjsg 	ret = amdgpu_dpm_get_dpm_freq_range(adev, PP_SCLK, &min_freq, &max_freq);
19901bb76ff1Sjsg 	if (ret == -EOPNOTSUPP) {
19911bb76ff1Sjsg 		ret = 0;
19921bb76ff1Sjsg 		goto out;
19931bb76ff1Sjsg 	}
19941bb76ff1Sjsg 	if (ret || val > max_freq || val < min_freq) {
19951bb76ff1Sjsg 		ret = -EINVAL;
19961bb76ff1Sjsg 		goto out;
1997c349dbc7Sjsg 	}
1998c349dbc7Sjsg 
19991bb76ff1Sjsg 	ret = amdgpu_dpm_set_soft_freq_range(adev, PP_SCLK, (uint32_t)val, (uint32_t)val);
20001bb76ff1Sjsg 	if (ret)
20011bb76ff1Sjsg 		ret = -EINVAL;
20021bb76ff1Sjsg 
20031bb76ff1Sjsg out:
2004ad8b1aafSjsg 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
2005ad8b1aafSjsg 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
2006c349dbc7Sjsg 
20071bb76ff1Sjsg 	return ret;
2008c349dbc7Sjsg }
2009c349dbc7Sjsg 
20105ca02815Sjsg DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL,
2011c349dbc7Sjsg 			amdgpu_debugfs_ib_preempt, "%llu\n");
2012c349dbc7Sjsg 
20135ca02815Sjsg DEFINE_DEBUGFS_ATTRIBUTE(fops_sclk_set, NULL,
2014c349dbc7Sjsg 			amdgpu_debugfs_sclk_set, "%llu\n");
2015c349dbc7Sjsg 
amdgpu_reset_dump_register_list_read(struct file * f,char __user * buf,size_t size,loff_t * pos)20161bb76ff1Sjsg static ssize_t amdgpu_reset_dump_register_list_read(struct file *f,
20171bb76ff1Sjsg 				char __user *buf, size_t size, loff_t *pos)
20181bb76ff1Sjsg {
20191bb76ff1Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
20201bb76ff1Sjsg 	char reg_offset[12];
20211bb76ff1Sjsg 	int i, ret, len = 0;
20221bb76ff1Sjsg 
20231bb76ff1Sjsg 	if (*pos)
20241bb76ff1Sjsg 		return 0;
20251bb76ff1Sjsg 
20261bb76ff1Sjsg 	memset(reg_offset, 0, 12);
20271bb76ff1Sjsg 	ret = down_read_killable(&adev->reset_domain->sem);
20281bb76ff1Sjsg 	if (ret)
20291bb76ff1Sjsg 		return ret;
20301bb76ff1Sjsg 
20311bb76ff1Sjsg 	for (i = 0; i < adev->num_regs; i++) {
20321bb76ff1Sjsg 		sprintf(reg_offset, "0x%x\n", adev->reset_dump_reg_list[i]);
20331bb76ff1Sjsg 		up_read(&adev->reset_domain->sem);
20341bb76ff1Sjsg 		if (copy_to_user(buf + len, reg_offset, strlen(reg_offset)))
20351bb76ff1Sjsg 			return -EFAULT;
20361bb76ff1Sjsg 
20371bb76ff1Sjsg 		len += strlen(reg_offset);
20381bb76ff1Sjsg 		ret = down_read_killable(&adev->reset_domain->sem);
20391bb76ff1Sjsg 		if (ret)
20401bb76ff1Sjsg 			return ret;
20411bb76ff1Sjsg 	}
20421bb76ff1Sjsg 
20431bb76ff1Sjsg 	up_read(&adev->reset_domain->sem);
20441bb76ff1Sjsg 	*pos += len;
20451bb76ff1Sjsg 
20461bb76ff1Sjsg 	return len;
20471bb76ff1Sjsg }
20481bb76ff1Sjsg 
amdgpu_reset_dump_register_list_write(struct file * f,const char __user * buf,size_t size,loff_t * pos)20491bb76ff1Sjsg static ssize_t amdgpu_reset_dump_register_list_write(struct file *f,
20501bb76ff1Sjsg 			const char __user *buf, size_t size, loff_t *pos)
20511bb76ff1Sjsg {
20521bb76ff1Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
20531bb76ff1Sjsg 	char reg_offset[11];
20541bb76ff1Sjsg 	uint32_t *new = NULL, *tmp = NULL;
20551bb76ff1Sjsg 	int ret, i = 0, len = 0;
20561bb76ff1Sjsg 
20571bb76ff1Sjsg 	do {
20581bb76ff1Sjsg 		memset(reg_offset, 0, 11);
20591bb76ff1Sjsg 		if (copy_from_user(reg_offset, buf + len,
20601bb76ff1Sjsg 					min(10, ((int)size-len)))) {
20611bb76ff1Sjsg 			ret = -EFAULT;
20621bb76ff1Sjsg 			goto error_free;
20631bb76ff1Sjsg 		}
20641bb76ff1Sjsg 
20651bb76ff1Sjsg 		new = krealloc_array(tmp, i + 1, sizeof(uint32_t), GFP_KERNEL);
20661bb76ff1Sjsg 		if (!new) {
20671bb76ff1Sjsg 			ret = -ENOMEM;
20681bb76ff1Sjsg 			goto error_free;
20691bb76ff1Sjsg 		}
20701bb76ff1Sjsg 		tmp = new;
20711bb76ff1Sjsg 		if (sscanf(reg_offset, "%X %n", &tmp[i], &ret) != 1) {
20721bb76ff1Sjsg 			ret = -EINVAL;
20731bb76ff1Sjsg 			goto error_free;
20741bb76ff1Sjsg 		}
20751bb76ff1Sjsg 
20761bb76ff1Sjsg 		len += ret;
20771bb76ff1Sjsg 		i++;
20781bb76ff1Sjsg 	} while (len < size);
20791bb76ff1Sjsg 
20801bb76ff1Sjsg 	new = kmalloc_array(i, sizeof(uint32_t), GFP_KERNEL);
20811bb76ff1Sjsg 	if (!new) {
20821bb76ff1Sjsg 		ret = -ENOMEM;
20831bb76ff1Sjsg 		goto error_free;
20841bb76ff1Sjsg 	}
20851bb76ff1Sjsg 	ret = down_write_killable(&adev->reset_domain->sem);
20861bb76ff1Sjsg 	if (ret)
20871bb76ff1Sjsg 		goto error_free;
20881bb76ff1Sjsg 
20891bb76ff1Sjsg 	swap(adev->reset_dump_reg_list, tmp);
20901bb76ff1Sjsg 	swap(adev->reset_dump_reg_value, new);
20911bb76ff1Sjsg 	adev->num_regs = i;
20921bb76ff1Sjsg 	up_write(&adev->reset_domain->sem);
20931bb76ff1Sjsg 	ret = size;
20941bb76ff1Sjsg 
20951bb76ff1Sjsg error_free:
20961bb76ff1Sjsg 	if (tmp != new)
20971bb76ff1Sjsg 		kfree(tmp);
20981bb76ff1Sjsg 	kfree(new);
20991bb76ff1Sjsg 	return ret;
21001bb76ff1Sjsg }
21011bb76ff1Sjsg 
21021bb76ff1Sjsg static const struct file_operations amdgpu_reset_dump_register_list = {
21031bb76ff1Sjsg 	.owner = THIS_MODULE,
21041bb76ff1Sjsg 	.read = amdgpu_reset_dump_register_list_read,
21051bb76ff1Sjsg 	.write = amdgpu_reset_dump_register_list_write,
21061bb76ff1Sjsg 	.llseek = default_llseek
21071bb76ff1Sjsg };
21081bb76ff1Sjsg 
amdgpu_debugfs_init(struct amdgpu_device * adev)2109fb4d8502Sjsg int amdgpu_debugfs_init(struct amdgpu_device *adev)
2110fb4d8502Sjsg {
21115ca02815Sjsg 	struct dentry *root = adev_to_drm(adev)->primary->debugfs_root;
21125ca02815Sjsg 	struct dentry *ent;
2113c349dbc7Sjsg 	int r, i;
2114c349dbc7Sjsg 
21151bb76ff1Sjsg 	if (!debugfs_initialized())
21161bb76ff1Sjsg 		return 0;
21171bb76ff1Sjsg 
21181bb76ff1Sjsg 	debugfs_create_x32("amdgpu_smu_debug", 0600, root,
21191bb76ff1Sjsg 			   &adev->pm.smu_debug_mask);
21201bb76ff1Sjsg 
21215ca02815Sjsg 	ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev,
2122c349dbc7Sjsg 				  &fops_ib_preempt);
21235ca02815Sjsg 	if (IS_ERR(ent)) {
2124c349dbc7Sjsg 		DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n");
21255ca02815Sjsg 		return PTR_ERR(ent);
2126c349dbc7Sjsg 	}
2127c349dbc7Sjsg 
21285ca02815Sjsg 	ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev,
2129c349dbc7Sjsg 				  &fops_sclk_set);
21305ca02815Sjsg 	if (IS_ERR(ent)) {
2131c349dbc7Sjsg 		DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n");
21325ca02815Sjsg 		return PTR_ERR(ent);
2133c349dbc7Sjsg 	}
2134c349dbc7Sjsg 
2135c349dbc7Sjsg 	/* Register debugfs entries for amdgpu_ttm */
21365ca02815Sjsg 	amdgpu_ttm_debugfs_init(adev);
21375ca02815Sjsg 	amdgpu_debugfs_pm_init(adev);
21385ca02815Sjsg 	amdgpu_debugfs_sa_init(adev);
21395ca02815Sjsg 	amdgpu_debugfs_fence_init(adev);
21405ca02815Sjsg 	amdgpu_debugfs_gem_init(adev);
2141c349dbc7Sjsg 
2142c349dbc7Sjsg 	r = amdgpu_debugfs_regs_init(adev);
2143c349dbc7Sjsg 	if (r)
2144c349dbc7Sjsg 		DRM_ERROR("registering register debugfs failed (%d).\n", r);
2145c349dbc7Sjsg 
21465ca02815Sjsg 	amdgpu_debugfs_firmware_init(adev);
21471bb76ff1Sjsg 	amdgpu_ta_if_debugfs_init(adev);
2148c349dbc7Sjsg 
2149c349dbc7Sjsg #if defined(CONFIG_DRM_AMD_DC)
2150f005ef32Sjsg 	if (adev->dc_enabled)
21515ca02815Sjsg 		dtn_debugfs_init(adev);
2152c349dbc7Sjsg #endif
2153c349dbc7Sjsg 
2154c349dbc7Sjsg 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
2155c349dbc7Sjsg 		struct amdgpu_ring *ring = adev->rings[i];
2156c349dbc7Sjsg 
2157c349dbc7Sjsg 		if (!ring)
2158c349dbc7Sjsg 			continue;
2159c349dbc7Sjsg 
21601bb76ff1Sjsg 		amdgpu_debugfs_ring_init(adev, ring);
2161c349dbc7Sjsg 	}
21621bb76ff1Sjsg 
21631bb76ff1Sjsg 	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
21641bb76ff1Sjsg 		if (!amdgpu_vcnfw_log)
21651bb76ff1Sjsg 			break;
21661bb76ff1Sjsg 
21671bb76ff1Sjsg 		if (adev->vcn.harvest_config & (1 << i))
21681bb76ff1Sjsg 			continue;
21691bb76ff1Sjsg 
21701bb76ff1Sjsg 		amdgpu_debugfs_vcn_fwlog_init(adev, i, &adev->vcn.inst[i]);
2171c349dbc7Sjsg 	}
2172c349dbc7Sjsg 
2173c349dbc7Sjsg 	amdgpu_ras_debugfs_create_all(adev);
2174ad8b1aafSjsg 	amdgpu_rap_debugfs_init(adev);
21755ca02815Sjsg 	amdgpu_securedisplay_debugfs_init(adev);
21765ca02815Sjsg 	amdgpu_fw_attestation_debugfs_init(adev);
2177ad8b1aafSjsg 
21785ca02815Sjsg 	debugfs_create_file("amdgpu_evict_vram", 0444, root, adev,
21795ca02815Sjsg 			    &amdgpu_evict_vram_fops);
21805ca02815Sjsg 	debugfs_create_file("amdgpu_evict_gtt", 0444, root, adev,
21815ca02815Sjsg 			    &amdgpu_evict_gtt_fops);
21825ca02815Sjsg 	debugfs_create_file("amdgpu_test_ib", 0444, root, adev,
21835ca02815Sjsg 			    &amdgpu_debugfs_test_ib_fops);
21845ca02815Sjsg 	debugfs_create_file("amdgpu_vm_info", 0444, root, adev,
21855ca02815Sjsg 			    &amdgpu_debugfs_vm_info_fops);
21861bb76ff1Sjsg 	debugfs_create_file("amdgpu_benchmark", 0200, root, adev,
21871bb76ff1Sjsg 			    &amdgpu_benchmark_fops);
21881bb76ff1Sjsg 	debugfs_create_file("amdgpu_reset_dump_register_list", 0644, root, adev,
21891bb76ff1Sjsg 			    &amdgpu_reset_dump_register_list);
21905ca02815Sjsg 
21915ca02815Sjsg 	adev->debugfs_vbios_blob.data = adev->bios;
21925ca02815Sjsg 	adev->debugfs_vbios_blob.size = adev->bios_size;
21935ca02815Sjsg 	debugfs_create_blob("amdgpu_vbios", 0444, root,
21945ca02815Sjsg 			    &adev->debugfs_vbios_blob);
21955ca02815Sjsg 
21961bb76ff1Sjsg 	adev->debugfs_discovery_blob.data = adev->mman.discovery_bin;
21971bb76ff1Sjsg 	adev->debugfs_discovery_blob.size = adev->mman.discovery_tmr_size;
21981bb76ff1Sjsg 	debugfs_create_blob("amdgpu_discovery", 0444, root,
21991bb76ff1Sjsg 			    &adev->debugfs_discovery_blob);
22001bb76ff1Sjsg 
22015ca02815Sjsg 	return 0;
2202fb4d8502Sjsg }
2203fb4d8502Sjsg 
2204fb4d8502Sjsg #else
amdgpu_debugfs_init(struct amdgpu_device * adev)2205fb4d8502Sjsg int amdgpu_debugfs_init(struct amdgpu_device *adev)
2206fb4d8502Sjsg {
2207fb4d8502Sjsg 	return 0;
2208fb4d8502Sjsg }
amdgpu_debugfs_regs_init(struct amdgpu_device * adev)2209fb4d8502Sjsg int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
2210fb4d8502Sjsg {
2211fb4d8502Sjsg 	return 0;
2212fb4d8502Sjsg }
2213fb4d8502Sjsg #endif
2214