/* * Copyright 2008 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. * Copyright 2009 Jerome Glisse. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * */ #include <linux/kthread.h> #include <linux/pci.h> #include <linux/uaccess.h> #include <linux/pm_runtime.h> #include "amdgpu.h" #include "amdgpu_pm.h" #include "amdgpu_dm_debugfs.h" #include "amdgpu_ras.h" #include "amdgpu_rap.h" #include "amdgpu_securedisplay.h" #include "amdgpu_fw_attestation.h" #include "amdgpu_umr.h" #include "amdgpu_reset.h" #include "amdgpu_psp_ta.h" #if defined(CONFIG_DEBUG_FS) /** * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes * * @read: True if reading * @f: open file handle * @buf: User buffer to write/read to * @size: Number of bytes to write/read * @pos: Offset to seek to * * This debugfs entry has special meaning on the offset being sought. * Various bits have different meanings: * * Bit 62: Indicates a GRBM bank switch is needed * Bit 61: Indicates a SRBM bank switch is needed (implies bit 62 is * zero) * Bits 24..33: The SE or ME selector if needed * Bits 34..43: The SH (or SA) or PIPE selector if needed * Bits 44..53: The INSTANCE (or CU/WGP) or QUEUE selector if needed * * Bit 23: Indicates that the PM power gating lock should be held * This is necessary to read registers that might be * unreliable during a power gating transistion. * * The lower bits are the BYTE offset of the register to read. This * allows reading multiple registers in a single call and having * the returned size reflect that. */ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /* * amdgpu_debugfs_regs_read - Callback for reading MMIO registers */ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /* * amdgpu_debugfs_regs_write - Callback for writing MMIO registers */ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { … } static int amdgpu_debugfs_regs2_open(struct inode *inode, struct file *file) { … } static int amdgpu_debugfs_regs2_release(struct inode *inode, struct file *file) { … } static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 offset, size_t size, int write_en) { … } static long amdgpu_debugfs_regs2_ioctl(struct file *f, unsigned int cmd, unsigned long data) { … } static ssize_t amdgpu_debugfs_regs2_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } static ssize_t amdgpu_debugfs_regs2_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { … } static int amdgpu_debugfs_gprwave_open(struct inode *inode, struct file *file) { … } static int amdgpu_debugfs_gprwave_release(struct inode *inode, struct file *file) { … } static ssize_t amdgpu_debugfs_gprwave_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } static long amdgpu_debugfs_gprwave_ioctl(struct file *f, unsigned int cmd, unsigned long data) { … } /** * amdgpu_debugfs_regs_pcie_read - Read from a PCIE register * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to read. This * allows reading multiple registers in a single call and having * the returned size reflect that. */ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_regs_pcie_write - Write to a PCIE register * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to write. This * allows writing multiple registers in a single call and having * the returned size reflect that. */ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_regs_didt_read - Read from a DIDT register * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to read. This * allows reading multiple registers in a single call and having * the returned size reflect that. */ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_regs_didt_write - Write to a DIDT register * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to write. This * allows writing multiple registers in a single call and having * the returned size reflect that. */ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_regs_smc_read - Read from a SMC register * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to read. This * allows reading multiple registers in a single call and having * the returned size reflect that. */ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_regs_smc_write - Write to a SMC register * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to write. This * allows writing multiple registers in a single call and having * the returned size reflect that. */ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_gca_config_read - Read from gfx config data * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * This file is used to access configuration data in a somewhat * stable fashion. The format is a series of DWORDs with the first * indicating which revision it is. New content is appended to the * end so that older software can still read the data. */ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_sensor_read - Read from the powerplay sensors * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The offset is treated as the BYTE address of one of the sensors * enumerated in amd/include/kgd_pp_interface.h under the * 'amd_pp_sensors' enumeration. For instance to read the UVD VCLK * you would use the offset 3 * 4 = 12. */ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /** amdgpu_debugfs_wave_read - Read WAVE STATUS data * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The offset being sought changes which wave that the status data * will be returned for. The bits are used as follows: * * Bits 0..6: Byte offset into data * Bits 7..14: SE selector * Bits 15..22: SH/SA selector * Bits 23..30: CU/{WGP+SIMD} selector * Bits 31..36: WAVE ID selector * Bits 37..44: SIMD ID selector * * The returned data begins with one DWORD of version information * Followed by WAVE STATUS registers relevant to the GFX IP version * being used. See gfx_v8_0_read_wave_data() for an example output. */ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /** amdgpu_debugfs_gpr_read - Read wave gprs * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The offset being sought changes which wave that the status data * will be returned for. The bits are used as follows: * * Bits 0..11: Byte offset into data * Bits 12..19: SE selector * Bits 20..27: SH/SA selector * Bits 28..35: CU/{WGP+SIMD} selector * Bits 36..43: WAVE ID selector * Bits 37..44: SIMD ID selector * Bits 52..59: Thread selector * Bits 60..61: Bank selector (VGPR=0,SGPR=1) * * The return data comes from the SGPR or VGPR register bank for * the selected operational unit. */ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_gfxoff_residency_read - Read GFXOFF residency * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * Read the last residency value logged. It doesn't auto update, one needs to * stop logging before getting the current value. */ static ssize_t amdgpu_debugfs_gfxoff_residency_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_gfxoff_residency_write - Log GFXOFF Residency * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * Write a 32-bit non-zero to start logging; write a 32-bit zero to stop */ static ssize_t amdgpu_debugfs_gfxoff_residency_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_gfxoff_count_read - Read GFXOFF entry count * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to */ static ssize_t amdgpu_debugfs_gfxoff_count_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_gfxoff_write - Enable/disable GFXOFF * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * Write a 32-bit zero to disable or a 32-bit non-zero to enable */ static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { … } /** * amdgpu_debugfs_gfxoff_read - read gfxoff status * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to */ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } static ssize_t amdgpu_debugfs_gfxoff_status_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } static const struct file_operations amdgpu_debugfs_regs2_fops = …; static const struct file_operations amdgpu_debugfs_gprwave_fops = …; static const struct file_operations amdgpu_debugfs_regs_fops = …; static const struct file_operations amdgpu_debugfs_regs_didt_fops = …; static const struct file_operations amdgpu_debugfs_regs_pcie_fops = …; static const struct file_operations amdgpu_debugfs_regs_smc_fops = …; static const struct file_operations amdgpu_debugfs_gca_config_fops = …; static const struct file_operations amdgpu_debugfs_sensors_fops = …; static const struct file_operations amdgpu_debugfs_wave_fops = …; static const struct file_operations amdgpu_debugfs_gpr_fops = …; static const struct file_operations amdgpu_debugfs_gfxoff_fops = …; static const struct file_operations amdgpu_debugfs_gfxoff_status_fops = …; static const struct file_operations amdgpu_debugfs_gfxoff_count_fops = …; static const struct file_operations amdgpu_debugfs_gfxoff_residency_fops = …; static const struct file_operations *debugfs_regs[] = …; static const char * const debugfs_regs_names[] = …; /** * amdgpu_debugfs_regs_init - Initialize debugfs entries that provide * register access. * * @adev: The device to attach the debugfs entries to */ int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) { … } static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) { … } static int amdgpu_debugfs_evict_vram(void *data, u64 *val) { … } static int amdgpu_debugfs_evict_gtt(void *data, u64 *val) { … } static int amdgpu_debugfs_benchmark(void *data, u64 val) { … } static int amdgpu_debugfs_vm_info_show(struct seq_file *m, void *unused) { … } DEFINE_SHOW_ATTRIBUTE(…); DEFINE_SHOW_ATTRIBUTE(…); DEFINE_DEBUGFS_ATTRIBUTE(…); DEFINE_DEBUGFS_ATTRIBUTE(…); DEFINE_DEBUGFS_ATTRIBUTE(…); static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring, struct dma_fence **fences) { … } static void amdgpu_ib_preempt_signal_fences(struct dma_fence **fences, int length) { … } static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched) { … } static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring) { … } static int amdgpu_debugfs_ib_preempt(void *data, u64 val) { … } static int amdgpu_debugfs_sclk_set(void *data, u64 val) { … } DEFINE_DEBUGFS_ATTRIBUTE(…); DEFINE_DEBUGFS_ATTRIBUTE(…); static ssize_t amdgpu_reset_dump_register_list_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { … } static ssize_t amdgpu_reset_dump_register_list_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { … } static const struct file_operations amdgpu_reset_dump_register_list = …; int amdgpu_debugfs_init(struct amdgpu_device *adev) { … } #else int amdgpu_debugfs_init(struct amdgpu_device *adev) { return 0; } int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) { return 0; } #endif