Commit 5ce5a584 authored by Somalapuram Amaranath's avatar Somalapuram Amaranath Committed by Alex Deucher
Browse files

drm/amdgpu: add debugfs for reset registers list



List of register populated for dump collection during the GPU reset.

Signed-off-by: default avatarSomalapuram Amaranath <Amaranath.Somalapuram@amd.com>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b74e2476
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1094,6 +1094,10 @@ struct amdgpu_device {
	struct ip_discovery_top         *ip_top;

	struct mutex			benchmark_mutex;

	/* reset dump register */
	uint32_t                        *reset_dump_reg_list;
	int                             num_regs;
};

static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
+82 −0
Original line number Diff line number Diff line
@@ -1638,6 +1638,86 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL,
DEFINE_DEBUGFS_ATTRIBUTE(fops_sclk_set, NULL,
			amdgpu_debugfs_sclk_set, "%llu\n");

static ssize_t amdgpu_reset_dump_register_list_read(struct file *f,
				char __user *buf, size_t size, loff_t *pos)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
	char reg_offset[12];
	int i, ret, len = 0;

	if (*pos)
		return 0;

	memset(reg_offset, 0, 12);
	ret = down_read_killable(&adev->reset_sem);
	if (ret)
		return ret;

	for (i = 0; i < adev->num_regs; i++) {
		sprintf(reg_offset, "0x%x\n", adev->reset_dump_reg_list[i]);
		up_read(&adev->reset_sem);
		if (copy_to_user(buf + len, reg_offset, strlen(reg_offset)))
			return -EFAULT;

		len += strlen(reg_offset);
		ret = down_read_killable(&adev->reset_sem);
		if (ret)
			return ret;
	}

	up_read(&adev->reset_sem);
	*pos += len;

	return len;
}

static ssize_t amdgpu_reset_dump_register_list_write(struct file *f,
			const char __user *buf, size_t size, loff_t *pos)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
	char reg_offset[11];
	uint32_t *tmp;
	int ret, i = 0, len = 0;

	do {
		memset(reg_offset, 0, 11);
		if (copy_from_user(reg_offset, buf + len,
					min(10, ((int)size-len)))) {
			ret = -EFAULT;
			goto error_free;
		}

		tmp = krealloc_array(tmp, i + 1, sizeof(uint32_t), GFP_KERNEL);
		if (sscanf(reg_offset, "%X %n", &tmp[i], &ret) != 1) {
			ret = -EINVAL;
			goto error_free;
		}

		len += ret;
		i++;
	} while (len < size);

	ret = down_write_killable(&adev->reset_sem);
	if (ret)
		goto error_free;

	swap(adev->reset_dump_reg_list, tmp);
	adev->num_regs = i;
	up_write(&adev->reset_sem);
	ret = size;

error_free:
	kfree(tmp);
	return ret;
}

static const struct file_operations amdgpu_reset_dump_register_list = {
	.owner = THIS_MODULE,
	.read = amdgpu_reset_dump_register_list_read,
	.write = amdgpu_reset_dump_register_list_write,
	.llseek = default_llseek
};

int amdgpu_debugfs_init(struct amdgpu_device *adev)
{
	struct dentry *root = adev_to_drm(adev)->primary->debugfs_root;
@@ -1706,6 +1786,8 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
			    &amdgpu_debugfs_vm_info_fops);
	debugfs_create_file("amdgpu_benchmark", 0200, root, adev,
			    &amdgpu_benchmark_fops);
	debugfs_create_file("amdgpu_reset_dump_register_list", 0644, root, adev,
			    &amdgpu_reset_dump_register_list);

	adev->debugfs_vbios_blob.data = adev->bios;
	adev->debugfs_vbios_blob.size = adev->bios_size;