diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 792 | 
1 files changed, 792 insertions, 0 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c new file mode 100644 index 000000000000..ee76b468774a --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -0,0 +1,792 @@ +/* + * 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 <drm/drmP.h> +#include <linux/debugfs.h> +#include "amdgpu.h" + +/* + * Debugfs + */ +int amdgpu_debugfs_add_files(struct amdgpu_device *adev, +			     const struct drm_info_list *files, +			     unsigned nfiles) +{ +	unsigned i; + +	for (i = 0; i < adev->debugfs_count; i++) { +		if (adev->debugfs[i].files == files) { +			/* Already registered */ +			return 0; +		} +	} + +	i = adev->debugfs_count + 1; +	if (i > AMDGPU_DEBUGFS_MAX_COMPONENTS) { +		DRM_ERROR("Reached maximum number of debugfs components.\n"); +		DRM_ERROR("Report so we increase " +			  "AMDGPU_DEBUGFS_MAX_COMPONENTS.\n"); +		return -EINVAL; +	} +	adev->debugfs[adev->debugfs_count].files = files; +	adev->debugfs[adev->debugfs_count].num_files = nfiles; +	adev->debugfs_count = i; +#if defined(CONFIG_DEBUG_FS) +	drm_debugfs_create_files(files, nfiles, +				 adev->ddev->primary->debugfs_root, +				 adev->ddev->primary); +#endif +	return 0; +} + +#if defined(CONFIG_DEBUG_FS) + +static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, +					size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	ssize_t result = 0; +	int r; +	bool pm_pg_lock, use_bank; +	unsigned instance_bank, sh_bank, se_bank; + +	if (size & 0x3 || *pos & 0x3) +		return -EINVAL; + +	/* are we reading registers for which a PG lock is necessary? */ +	pm_pg_lock = (*pos >> 23) & 1; + +	if (*pos & (1ULL << 62)) { +		se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24; +		sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34; +		instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44; + +		if (se_bank == 0x3FF) +			se_bank = 0xFFFFFFFF; +		if (sh_bank == 0x3FF) +			sh_bank = 0xFFFFFFFF; +		if (instance_bank == 0x3FF) +			instance_bank = 0xFFFFFFFF; +		use_bank = 1; +	} else { +		use_bank = 0; +	} + +	*pos &= (1UL << 22) - 1; + +	if (use_bank) { +		if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || +		    (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) +			return -EINVAL; +		mutex_lock(&adev->grbm_idx_mutex); +		amdgpu_gfx_select_se_sh(adev, se_bank, +					sh_bank, instance_bank); +	} + +	if (pm_pg_lock) +		mutex_lock(&adev->pm.mutex); + +	while (size) { +		uint32_t value; + +		if (*pos > adev->rmmio_size) +			goto end; + +		value = RREG32(*pos >> 2); +		r = put_user(value, (uint32_t *)buf); +		if (r) { +			result = r; +			goto end; +		} + +		result += 4; +		buf += 4; +		*pos += 4; +		size -= 4; +	} + +end: +	if (use_bank) { +		amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); +		mutex_unlock(&adev->grbm_idx_mutex); +	} + +	if (pm_pg_lock) +		mutex_unlock(&adev->pm.mutex); + +	return result; +} + +static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, +					 size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	ssize_t result = 0; +	int r; +	bool pm_pg_lock, use_bank; +	unsigned instance_bank, sh_bank, se_bank; + +	if (size & 0x3 || *pos & 0x3) +		return -EINVAL; + +	/* are we reading registers for which a PG lock is necessary? */ +	pm_pg_lock = (*pos >> 23) & 1; + +	if (*pos & (1ULL << 62)) { +		se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24; +		sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34; +		instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44; + +		if (se_bank == 0x3FF) +			se_bank = 0xFFFFFFFF; +		if (sh_bank == 0x3FF) +			sh_bank = 0xFFFFFFFF; +		if (instance_bank == 0x3FF) +			instance_bank = 0xFFFFFFFF; +		use_bank = 1; +	} else { +		use_bank = 0; +	} + +	*pos &= (1UL << 22) - 1; + +	if (use_bank) { +		if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || +		    (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) +			return -EINVAL; +		mutex_lock(&adev->grbm_idx_mutex); +		amdgpu_gfx_select_se_sh(adev, se_bank, +					sh_bank, instance_bank); +	} + +	if (pm_pg_lock) +		mutex_lock(&adev->pm.mutex); + +	while (size) { +		uint32_t value; + +		if (*pos > adev->rmmio_size) +			return result; + +		r = get_user(value, (uint32_t *)buf); +		if (r) +			return r; + +		WREG32(*pos >> 2, value); + +		result += 4; +		buf += 4; +		*pos += 4; +		size -= 4; +	} + +	if (use_bank) { +		amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); +		mutex_unlock(&adev->grbm_idx_mutex); +	} + +	if (pm_pg_lock) +		mutex_unlock(&adev->pm.mutex); + +	return result; +} + +static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, +					size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	ssize_t result = 0; +	int r; + +	if (size & 0x3 || *pos & 0x3) +		return -EINVAL; + +	while (size) { +		uint32_t value; + +		value = RREG32_PCIE(*pos >> 2); +		r = put_user(value, (uint32_t *)buf); +		if (r) +			return r; + +		result += 4; +		buf += 4; +		*pos += 4; +		size -= 4; +	} + +	return result; +} + +static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf, +					 size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	ssize_t result = 0; +	int r; + +	if (size & 0x3 || *pos & 0x3) +		return -EINVAL; + +	while (size) { +		uint32_t value; + +		r = get_user(value, (uint32_t *)buf); +		if (r) +			return r; + +		WREG32_PCIE(*pos >> 2, value); + +		result += 4; +		buf += 4; +		*pos += 4; +		size -= 4; +	} + +	return result; +} + +static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, +					size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	ssize_t result = 0; +	int r; + +	if (size & 0x3 || *pos & 0x3) +		return -EINVAL; + +	while (size) { +		uint32_t value; + +		value = RREG32_DIDT(*pos >> 2); +		r = put_user(value, (uint32_t *)buf); +		if (r) +			return r; + +		result += 4; +		buf += 4; +		*pos += 4; +		size -= 4; +	} + +	return result; +} + +static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf, +					 size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	ssize_t result = 0; +	int r; + +	if (size & 0x3 || *pos & 0x3) +		return -EINVAL; + +	while (size) { +		uint32_t value; + +		r = get_user(value, (uint32_t *)buf); +		if (r) +			return r; + +		WREG32_DIDT(*pos >> 2, value); + +		result += 4; +		buf += 4; +		*pos += 4; +		size -= 4; +	} + +	return result; +} + +static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, +					size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	ssize_t result = 0; +	int r; + +	if (size & 0x3 || *pos & 0x3) +		return -EINVAL; + +	while (size) { +		uint32_t value; + +		value = RREG32_SMC(*pos); +		r = put_user(value, (uint32_t *)buf); +		if (r) +			return r; + +		result += 4; +		buf += 4; +		*pos += 4; +		size -= 4; +	} + +	return result; +} + +static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf, +					 size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	ssize_t result = 0; +	int r; + +	if (size & 0x3 || *pos & 0x3) +		return -EINVAL; + +	while (size) { +		uint32_t value; + +		r = get_user(value, (uint32_t *)buf); +		if (r) +			return r; + +		WREG32_SMC(*pos, value); + +		result += 4; +		buf += 4; +		*pos += 4; +		size -= 4; +	} + +	return result; +} + +static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, +					size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	ssize_t result = 0; +	int r; +	uint32_t *config, no_regs = 0; + +	if (size & 0x3 || *pos & 0x3) +		return -EINVAL; + +	config = kmalloc_array(256, sizeof(*config), GFP_KERNEL); +	if (!config) +		return -ENOMEM; + +	/* version, increment each time something is added */ +	config[no_regs++] = 3; +	config[no_regs++] = adev->gfx.config.max_shader_engines; +	config[no_regs++] = adev->gfx.config.max_tile_pipes; +	config[no_regs++] = adev->gfx.config.max_cu_per_sh; +	config[no_regs++] = adev->gfx.config.max_sh_per_se; +	config[no_regs++] = adev->gfx.config.max_backends_per_se; +	config[no_regs++] = adev->gfx.config.max_texture_channel_caches; +	config[no_regs++] = adev->gfx.config.max_gprs; +	config[no_regs++] = adev->gfx.config.max_gs_threads; +	config[no_regs++] = adev->gfx.config.max_hw_contexts; +	config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_frontend; +	config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_backend; +	config[no_regs++] = adev->gfx.config.sc_hiz_tile_fifo_size; +	config[no_regs++] = adev->gfx.config.sc_earlyz_tile_fifo_size; +	config[no_regs++] = adev->gfx.config.num_tile_pipes; +	config[no_regs++] = adev->gfx.config.backend_enable_mask; +	config[no_regs++] = adev->gfx.config.mem_max_burst_length_bytes; +	config[no_regs++] = adev->gfx.config.mem_row_size_in_kb; +	config[no_regs++] = adev->gfx.config.shader_engine_tile_size; +	config[no_regs++] = adev->gfx.config.num_gpus; +	config[no_regs++] = adev->gfx.config.multi_gpu_tile_size; +	config[no_regs++] = adev->gfx.config.mc_arb_ramcfg; +	config[no_regs++] = adev->gfx.config.gb_addr_config; +	config[no_regs++] = adev->gfx.config.num_rbs; + +	/* rev==1 */ +	config[no_regs++] = adev->rev_id; +	config[no_regs++] = adev->pg_flags; +	config[no_regs++] = adev->cg_flags; + +	/* rev==2 */ +	config[no_regs++] = adev->family; +	config[no_regs++] = adev->external_rev_id; + +	/* rev==3 */ +	config[no_regs++] = adev->pdev->device; +	config[no_regs++] = adev->pdev->revision; +	config[no_regs++] = adev->pdev->subsystem_device; +	config[no_regs++] = adev->pdev->subsystem_vendor; + +	while (size && (*pos < no_regs * 4)) { +		uint32_t value; + +		value = config[*pos >> 2]; +		r = put_user(value, (uint32_t *)buf); +		if (r) { +			kfree(config); +			return r; +		} + +		result += 4; +		buf += 4; +		*pos += 4; +		size -= 4; +	} + +	kfree(config); +	return result; +} + +static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, +					size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = file_inode(f)->i_private; +	int idx, x, outsize, r, valuesize; +	uint32_t values[16]; + +	if (size & 3 || *pos & 0x3) +		return -EINVAL; + +	if (amdgpu_dpm == 0) +		return -EINVAL; + +	/* convert offset to sensor number */ +	idx = *pos >> 2; + +	valuesize = sizeof(values); +	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) +		r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize); +	else +		return -EINVAL; + +	if (size > valuesize) +		return -EINVAL; + +	outsize = 0; +	x = 0; +	if (!r) { +		while (size) { +			r = put_user(values[x++], (int32_t *)buf); +			buf += 4; +			size -= 4; +			outsize += 4; +		} +	} + +	return !r ? outsize : r; +} + +static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, +					size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = f->f_inode->i_private; +	int r, x; +	ssize_t result=0; +	uint32_t offset, se, sh, cu, wave, simd, data[32]; + +	if (size & 3 || *pos & 3) +		return -EINVAL; + +	/* decode offset */ +	offset = (*pos & GENMASK_ULL(6, 0)); +	se = (*pos & GENMASK_ULL(14, 7)) >> 7; +	sh = (*pos & GENMASK_ULL(22, 15)) >> 15; +	cu = (*pos & GENMASK_ULL(30, 23)) >> 23; +	wave = (*pos & GENMASK_ULL(36, 31)) >> 31; +	simd = (*pos & GENMASK_ULL(44, 37)) >> 37; + +	/* switch to the specific se/sh/cu */ +	mutex_lock(&adev->grbm_idx_mutex); +	amdgpu_gfx_select_se_sh(adev, se, sh, cu); + +	x = 0; +	if (adev->gfx.funcs->read_wave_data) +		adev->gfx.funcs->read_wave_data(adev, simd, wave, data, &x); + +	amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); +	mutex_unlock(&adev->grbm_idx_mutex); + +	if (!x) +		return -EINVAL; + +	while (size && (offset < x * 4)) { +		uint32_t value; + +		value = data[offset >> 2]; +		r = put_user(value, (uint32_t *)buf); +		if (r) +			return r; + +		result += 4; +		buf += 4; +		offset += 4; +		size -= 4; +	} + +	return result; +} + +static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, +					size_t size, loff_t *pos) +{ +	struct amdgpu_device *adev = f->f_inode->i_private; +	int r; +	ssize_t result = 0; +	uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; + +	if (size & 3 || *pos & 3) +		return -EINVAL; + +	/* decode offset */ +	offset = *pos & GENMASK_ULL(11, 0); +	se = (*pos & GENMASK_ULL(19, 12)) >> 12; +	sh = (*pos & GENMASK_ULL(27, 20)) >> 20; +	cu = (*pos & GENMASK_ULL(35, 28)) >> 28; +	wave = (*pos & GENMASK_ULL(43, 36)) >> 36; +	simd = (*pos & GENMASK_ULL(51, 44)) >> 44; +	thread = (*pos & GENMASK_ULL(59, 52)) >> 52; +	bank = (*pos & GENMASK_ULL(61, 60)) >> 60; + +	data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL); +	if (!data) +		return -ENOMEM; + +	/* switch to the specific se/sh/cu */ +	mutex_lock(&adev->grbm_idx_mutex); +	amdgpu_gfx_select_se_sh(adev, se, sh, cu); + +	if (bank == 0) { +		if (adev->gfx.funcs->read_wave_vgprs) +			adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data); +	} else { +		if (adev->gfx.funcs->read_wave_sgprs) +			adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data); +	} + +	amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); +	mutex_unlock(&adev->grbm_idx_mutex); + +	while (size) { +		uint32_t value; + +		value = data[offset++]; +		r = put_user(value, (uint32_t *)buf); +		if (r) { +			result = r; +			goto err; +		} + +		result += 4; +		buf += 4; +		size -= 4; +	} + +err: +	kfree(data); +	return result; +} + +static const struct file_operations amdgpu_debugfs_regs_fops = { +	.owner = THIS_MODULE, +	.read = amdgpu_debugfs_regs_read, +	.write = amdgpu_debugfs_regs_write, +	.llseek = default_llseek +}; +static const struct file_operations amdgpu_debugfs_regs_didt_fops = { +	.owner = THIS_MODULE, +	.read = amdgpu_debugfs_regs_didt_read, +	.write = amdgpu_debugfs_regs_didt_write, +	.llseek = default_llseek +}; +static const struct file_operations amdgpu_debugfs_regs_pcie_fops = { +	.owner = THIS_MODULE, +	.read = amdgpu_debugfs_regs_pcie_read, +	.write = amdgpu_debugfs_regs_pcie_write, +	.llseek = default_llseek +}; +static const struct file_operations amdgpu_debugfs_regs_smc_fops = { +	.owner = THIS_MODULE, +	.read = amdgpu_debugfs_regs_smc_read, +	.write = amdgpu_debugfs_regs_smc_write, +	.llseek = default_llseek +}; + +static const struct file_operations amdgpu_debugfs_gca_config_fops = { +	.owner = THIS_MODULE, +	.read = amdgpu_debugfs_gca_config_read, +	.llseek = default_llseek +}; + +static const struct file_operations amdgpu_debugfs_sensors_fops = { +	.owner = THIS_MODULE, +	.read = amdgpu_debugfs_sensor_read, +	.llseek = default_llseek +}; + +static const struct file_operations amdgpu_debugfs_wave_fops = { +	.owner = THIS_MODULE, +	.read = amdgpu_debugfs_wave_read, +	.llseek = default_llseek +}; +static const struct file_operations amdgpu_debugfs_gpr_fops = { +	.owner = THIS_MODULE, +	.read = amdgpu_debugfs_gpr_read, +	.llseek = default_llseek +}; + +static const struct file_operations *debugfs_regs[] = { +	&amdgpu_debugfs_regs_fops, +	&amdgpu_debugfs_regs_didt_fops, +	&amdgpu_debugfs_regs_pcie_fops, +	&amdgpu_debugfs_regs_smc_fops, +	&amdgpu_debugfs_gca_config_fops, +	&amdgpu_debugfs_sensors_fops, +	&amdgpu_debugfs_wave_fops, +	&amdgpu_debugfs_gpr_fops, +}; + +static const char *debugfs_regs_names[] = { +	"amdgpu_regs", +	"amdgpu_regs_didt", +	"amdgpu_regs_pcie", +	"amdgpu_regs_smc", +	"amdgpu_gca_config", +	"amdgpu_sensors", +	"amdgpu_wave", +	"amdgpu_gpr", +}; + +int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) +{ +	struct drm_minor *minor = adev->ddev->primary; +	struct dentry *ent, *root = minor->debugfs_root; +	unsigned i, j; + +	for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) { +		ent = debugfs_create_file(debugfs_regs_names[i], +					  S_IFREG | S_IRUGO, root, +					  adev, debugfs_regs[i]); +		if (IS_ERR(ent)) { +			for (j = 0; j < i; j++) { +				debugfs_remove(adev->debugfs_regs[i]); +				adev->debugfs_regs[i] = NULL; +			} +			return PTR_ERR(ent); +		} + +		if (!i) +			i_size_write(ent->d_inode, adev->rmmio_size); +		adev->debugfs_regs[i] = ent; +	} + +	return 0; +} + +void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev) +{ +	unsigned i; + +	for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) { +		if (adev->debugfs_regs[i]) { +			debugfs_remove(adev->debugfs_regs[i]); +			adev->debugfs_regs[i] = NULL; +		} +	} +} + +static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) +{ +	struct drm_info_node *node = (struct drm_info_node *) m->private; +	struct drm_device *dev = node->minor->dev; +	struct amdgpu_device *adev = dev->dev_private; +	int r = 0, i; + +	/* hold on the scheduler */ +	for (i = 0; i < AMDGPU_MAX_RINGS; i++) { +		struct amdgpu_ring *ring = adev->rings[i]; + +		if (!ring || !ring->sched.thread) +			continue; +		kthread_park(ring->sched.thread); +	} + +	seq_printf(m, "run ib test:\n"); +	r = amdgpu_ib_ring_tests(adev); +	if (r) +		seq_printf(m, "ib ring tests failed (%d).\n", r); +	else +		seq_printf(m, "ib ring tests passed.\n"); + +	/* go on the scheduler */ +	for (i = 0; i < AMDGPU_MAX_RINGS; i++) { +		struct amdgpu_ring *ring = adev->rings[i]; + +		if (!ring || !ring->sched.thread) +			continue; +		kthread_unpark(ring->sched.thread); +	} + +	return 0; +} + +static int amdgpu_debugfs_get_vbios_dump(struct seq_file *m, void *data) +{ +	struct drm_info_node *node = (struct drm_info_node *) m->private; +	struct drm_device *dev = node->minor->dev; +	struct amdgpu_device *adev = dev->dev_private; + +	seq_write(m, adev->bios, adev->bios_size); +	return 0; +} + +static int amdgpu_debugfs_evict_vram(struct seq_file *m, void *data) +{ +	struct drm_info_node *node = (struct drm_info_node *)m->private; +	struct drm_device *dev = node->minor->dev; +	struct amdgpu_device *adev = dev->dev_private; + +	seq_printf(m, "(%d)\n", amdgpu_bo_evict_vram(adev)); +	return 0; +} + +static const struct drm_info_list amdgpu_debugfs_list[] = { +	{"amdgpu_vbios", amdgpu_debugfs_get_vbios_dump}, +	{"amdgpu_test_ib", &amdgpu_debugfs_test_ib}, +	{"amdgpu_evict_vram", &amdgpu_debugfs_evict_vram} +}; + +int amdgpu_debugfs_init(struct amdgpu_device *adev) +{ +	return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list, +					ARRAY_SIZE(amdgpu_debugfs_list)); +} + +#else +int amdgpu_debugfs_init(struct amdgpu_device *adev) +{ +	return 0; +} +int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) +{ +	return 0; +} +void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev) { } +#endif |