diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 78 | 
1 files changed, 77 insertions, 1 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 1a4894fa3693..d33cb344be69 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -27,7 +27,7 @@  #include <linux/pci.h>  #include <linux/uaccess.h>  #include <linux/pm_runtime.h> - +#include <linux/poll.h>  #include <drm/drm_debugfs.h>  #include "amdgpu.h" @@ -74,8 +74,82 @@ int amdgpu_debugfs_add_files(struct amdgpu_device *adev,  	return 0;  } +int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev) +{ +#if defined(CONFIG_DEBUG_FS) +	unsigned long timeout = 600 * HZ; +	int ret; + +	wake_up_interruptible(&adev->autodump.gpu_hang); + +	ret = wait_for_completion_interruptible_timeout(&adev->autodump.dumping, timeout); +	if (ret == 0) { +		pr_err("autodump: timeout, move on to gpu recovery\n"); +		return -ETIMEDOUT; +	} +#endif +	return 0; +} +  #if defined(CONFIG_DEBUG_FS) +static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file) +{ +	struct amdgpu_device *adev = inode->i_private; +	int ret; + +	file->private_data = adev; + +	mutex_lock(&adev->lock_reset); +	if (adev->autodump.dumping.done) { +		reinit_completion(&adev->autodump.dumping); +		ret = 0; +	} else { +		ret = -EBUSY; +	} +	mutex_unlock(&adev->lock_reset); + +	return ret; +} + +static int amdgpu_debugfs_autodump_release(struct inode *inode, struct file *file) +{ +	struct amdgpu_device *adev = file->private_data; + +	complete_all(&adev->autodump.dumping); +	return 0; +} + +static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_table_struct *poll_table) +{ +	struct amdgpu_device *adev = file->private_data; + +	poll_wait(file, &adev->autodump.gpu_hang, poll_table); + +	if (adev->in_gpu_reset) +		return POLLIN | POLLRDNORM | POLLWRNORM; + +	return 0; +} + +static const struct file_operations autodump_debug_fops = { +	.owner = THIS_MODULE, +	.open = amdgpu_debugfs_autodump_open, +	.poll = amdgpu_debugfs_autodump_poll, +	.release = amdgpu_debugfs_autodump_release, +}; + +static void amdgpu_debugfs_autodump_init(struct amdgpu_device *adev) +{ +	init_completion(&adev->autodump.dumping); +	complete_all(&adev->autodump.dumping); +	init_waitqueue_head(&adev->autodump.gpu_hang); + +	debugfs_create_file("amdgpu_autodump", 0600, +		adev->ddev->primary->debugfs_root, +		adev, &autodump_debug_fops); +} +  /**   * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes   * @@ -1434,6 +1508,8 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)  	amdgpu_ras_debugfs_create_all(adev); +	amdgpu_debugfs_autodump_init(adev); +  	return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list,  					ARRAY_SIZE(amdgpu_debugfs_list));  } | 
