Commit 11eb648d authored by Ruijing Dong's avatar Ruijing Dong Committed by Alex Deucher
Browse files

drm/amdgpu/vcn: Add vcn firmware log



vcn fwlog is for debugging purpose only,
by default, it is disabled.

Signed-off-by: default avatarRuijing Dong <ruijing.dong@amd.com>
Reviewed-by: default avatarLeo Liu <leo.liu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b6065ebf
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -233,6 +233,9 @@ extern int amdgpu_cik_support;
#endif
extern int amdgpu_num_kcq;

#define AMDGPU_VCNFW_LOG_SIZE (32 * 1024)
extern int amdgpu_vcnfw_log;

#define AMDGPU_VM_MAX_NUM_CTX			4096
#define AMDGPU_SG_THRESHOLD			(256*1024*1024)
#define AMDGPU_DEFAULT_GTT_SIZE_MB		3072ULL /* 3GB by default */
+10 −0
Original line number Diff line number Diff line
@@ -1778,6 +1778,16 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
		amdgpu_debugfs_ring_init(adev, ring);
	}

	for ( i = 0; i < adev->vcn.num_vcn_inst; i++) {
		if (!amdgpu_vcnfw_log)
			break;

		if (adev->vcn.harvest_config & (1 << i))
			continue;

		amdgpu_debugfs_vcn_fwlog_init(adev, i, &adev->vcn.inst[i]);
	}

	amdgpu_ras_debugfs_create_all(adev);
	amdgpu_rap_debugfs_init(adev);
	amdgpu_securedisplay_debugfs_init(adev);
+8 −0
Original line number Diff line number Diff line
@@ -178,6 +178,7 @@ int amdgpu_reset_method = -1; /* auto */
int amdgpu_num_kcq = -1;
int amdgpu_smartshift_bias;
int amdgpu_use_xgmi_p2p = 1;
int amdgpu_vcnfw_log;

static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);

@@ -855,6 +856,13 @@ module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444);
MODULE_PARM_DESC(num_kcq, "number of kernel compute queue user want to setup (8 if set to greater than 8 or less than 0, only affect gfx 8+)");
module_param_named(num_kcq, amdgpu_num_kcq, int, 0444);

/**
 * DOC: vcnfw_log (int)
 * Enable vcnfw log output for debugging, the default is disabled.
 */
MODULE_PARM_DESC(vcnfw_log, "Enable vcnfw log(0 = disable (default value), 1 = enable)");
module_param_named(vcnfw_log, amdgpu_vcnfw_log, int, 0444);

/**
 * DOC: smu_pptable_id (int)
 * Used to override pptable id. id = 0 use VBIOS pptable.
+121 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/debugfs.h>
#include <drm/drm_drv.h>

#include "amdgpu.h"
@@ -79,7 +80,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
	const char *fw_name;
	const struct common_firmware_header *hdr;
	unsigned char fw_check;
	unsigned int fw_shared_size;
	unsigned int fw_shared_size, log_offset;
	int i, r;

	INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);
@@ -228,8 +229,12 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
	fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));
	log_offset = offsetof(struct amdgpu_fw_shared, fw_log);
	bo_size += fw_shared_size;

	if (amdgpu_vcnfw_log)
		bo_size += AMDGPU_VCNFW_LOG_SIZE;

	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
		if (adev->vcn.harvest_config & (1 << i))
			continue;
@@ -249,6 +254,12 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)

		adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size;

		if (amdgpu_vcnfw_log) {
			adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
			adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE;
			adev->vcn.inst[i].fw_shared.log_offset = log_offset;
		}

		if (adev->vcn.indirect_sram) {
			r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
					AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.inst[i].dpg_sram_bo,
@@ -983,3 +994,112 @@ void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)
		dev_info(adev->dev, "Will use PSP to load VCN firmware\n");
	}
}

/*
 * debugfs for mapping vcn firmware log buffer.
 */
#if defined(CONFIG_DEBUG_FS)
static ssize_t amdgpu_debugfs_vcn_fwlog_read(struct file *f, char __user *buf,
                                             size_t size, loff_t *pos)
{
	struct amdgpu_vcn_inst *vcn;
	void *log_buf;
	volatile struct amdgpu_vcn_fwlog *plog;
	unsigned int read_pos, write_pos, available, i, read_bytes = 0;
	unsigned int read_num[2] = {0};

	vcn = file_inode(f)->i_private;
	if (!vcn)
		return -ENODEV;

	if (!vcn->fw_shared.cpu_addr || !amdgpu_vcnfw_log)
		return -EFAULT;

	log_buf = vcn->fw_shared.cpu_addr + vcn->fw_shared.mem_size;

	plog = (volatile struct amdgpu_vcn_fwlog *)log_buf;
	read_pos = plog->rptr;
	write_pos = plog->wptr;

	if (read_pos > AMDGPU_VCNFW_LOG_SIZE || write_pos > AMDGPU_VCNFW_LOG_SIZE)
		return -EFAULT;

	if (!size || (read_pos == write_pos))
		return 0;

	if (write_pos > read_pos) {
		available = write_pos - read_pos;
		read_num[0] = min(size, (size_t)available);
	} else {
		read_num[0] = AMDGPU_VCNFW_LOG_SIZE - read_pos;
		available = read_num[0] + write_pos - plog->header_size;
		if (size > available)
			read_num[1] = write_pos - plog->header_size;
		else if (size > read_num[0])
			read_num[1] = size - read_num[0];
		else
			read_num[0] = size;
	}

	for (i = 0; i < 2; i++) {
		if (read_num[i]) {
			if (read_pos == AMDGPU_VCNFW_LOG_SIZE)
				read_pos = plog->header_size;
			if (read_num[i] == copy_to_user((buf + read_bytes),
			                                (log_buf + read_pos), read_num[i]))
				return -EFAULT;

			read_bytes += read_num[i];
			read_pos += read_num[i];
		}
	}

	plog->rptr = read_pos;
	*pos += read_bytes;
	return read_bytes;
}

static const struct file_operations amdgpu_debugfs_vcnfwlog_fops = {
	.owner = THIS_MODULE,
	.read = amdgpu_debugfs_vcn_fwlog_read,
	.llseek = default_llseek
};
#endif

void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev, uint8_t i,
                                   struct amdgpu_vcn_inst *vcn)
{
#if defined(CONFIG_DEBUG_FS)
	struct drm_minor *minor = adev_to_drm(adev)->primary;
	struct dentry *root = minor->debugfs_root;
	char name[32];

	sprintf(name, "amdgpu_vcn_%d_fwlog", i);
	debugfs_create_file_size(name, S_IFREG | S_IRUGO, root, vcn,
				 &amdgpu_debugfs_vcnfwlog_fops,
				 AMDGPU_VCNFW_LOG_SIZE);
#endif
}

void amdgpu_vcn_fwlog_init(struct amdgpu_vcn_inst *vcn)
{
#if defined(CONFIG_DEBUG_FS)
	volatile uint32_t *flag = vcn->fw_shared.cpu_addr;
	void *fw_log_cpu_addr = vcn->fw_shared.cpu_addr + vcn->fw_shared.mem_size;
	uint64_t fw_log_gpu_addr = vcn->fw_shared.gpu_addr + vcn->fw_shared.mem_size;
	volatile struct amdgpu_vcn_fwlog *log_buf = fw_log_cpu_addr;
	volatile struct amdgpu_fw_shared_fw_logging *fw_log = vcn->fw_shared.cpu_addr
                                                         + vcn->fw_shared.log_offset;
	*flag |= cpu_to_le32(AMDGPU_VCN_FW_LOGGING_FLAG);
	fw_log->is_enabled = 1;
	fw_log->addr_lo = cpu_to_le32(fw_log_gpu_addr & 0xFFFFFFFF);
	fw_log->addr_hi = cpu_to_le32(fw_log_gpu_addr >> 32);
	fw_log->size = cpu_to_le32(AMDGPU_VCNFW_LOG_SIZE);

	log_buf->header_size = sizeof(struct amdgpu_vcn_fwlog);
	log_buf->buffer_size = AMDGPU_VCNFW_LOG_SIZE;
	log_buf->rptr = log_buf->header_size;
	log_buf->wptr = log_buf->header_size;
	log_buf->wrapped = 0;
#endif
}
+4 −0
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@
#define AMDGPU_VCN_FW_SHARED_FLAG_0_RB	(1 << 6)
#define AMDGPU_VCN_MULTI_QUEUE_FLAG	(1 << 8)
#define AMDGPU_VCN_SW_RING_FLAG		(1 << 9)
#define AMDGPU_VCN_FW_LOGGING_FLAG	(1 << 10)

#define AMDGPU_VCN_IB_FLAG_DECODE_BUFFER	0x00000001
#define AMDGPU_VCN_CMD_FLAG_MSG_BUFFER		0x00000001
@@ -335,4 +336,7 @@ enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring);

void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev);

void amdgpu_vcn_fwlog_init(struct amdgpu_vcn_inst *vcn);
void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev,
                                   uint8_t i, struct amdgpu_vcn_inst *vcn);
#endif
Loading