Commit 98a2e3a0 authored by Saleemkhan Jamadar's avatar Saleemkhan Jamadar Committed by Alex Deucher

drm/amdgpu/umsch: add support to capture fw debug log

Added support to capture unsch fw debug logs in debugfs.
To enable set amdgpu_umschfw_log =1 in boot args.

v1 - rename variable to umsch_mm_fwlog (Veera)
Signed-off-by: default avatarSaleemkhan Jamadar <saleemkhan.jamadar@amd.com>
Reviewed-by: default avatarVeerabadhran Gopalakrishnan <Veerabadhran.Gopalakrishnan@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4b0497d2
......@@ -112,6 +112,7 @@
#include "amdgpu_xcp.h"
#include "amdgpu_seq64.h"
#include "amdgpu_reg_state.h"
#include "amdgpu_umsch_mm.h"
#define MAX_GPU_INSTANCE 64
......@@ -254,10 +255,12 @@ extern int amdgpu_cik_support;
extern int amdgpu_num_kcq;
#define AMDGPU_VCNFW_LOG_SIZE (32 * 1024)
#define AMDGPU_UMSCHFW_LOG_SIZE (32 * 1024)
extern int amdgpu_vcnfw_log;
extern int amdgpu_sg_display;
extern int amdgpu_umsch_mm;
extern int amdgpu_seamless;
extern int amdgpu_umsch_mm_fwlog;
extern int amdgpu_user_partt_mode;
extern int amdgpu_agp;
......
......@@ -2186,6 +2186,9 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
amdgpu_debugfs_vcn_fwlog_init(adev, i, &adev->vcn.inst[i]);
}
if (amdgpu_umsch_mm & amdgpu_umsch_mm_fwlog)
amdgpu_debugfs_umsch_fwlog_init(adev, &adev->umsch_mm);
amdgpu_ras_debugfs_create_all(adev);
amdgpu_rap_debugfs_init(adev);
amdgpu_securedisplay_debugfs_init(adev);
......
......@@ -215,6 +215,7 @@ uint amdgpu_debug_mask;
int amdgpu_agp = -1; /* auto */
int amdgpu_wbrf = -1;
int amdgpu_damage_clips = -1; /* auto */
int amdgpu_umsch_mm_fwlog;
static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
......@@ -975,6 +976,13 @@ MODULE_PARM_DESC(umsch_mm,
"Enable Multi Media User Mode Scheduler (0 = disabled (default), 1 = enabled)");
module_param_named(umsch_mm, amdgpu_umsch_mm, int, 0444);
/**
* DOC: umsch_mm_fwlog (int)
* Enable umschfw log output for debugging, the default is disabled.
*/
MODULE_PARM_DESC(umsch_mm_fwlog, "Enable umschfw log(0 = disable (default value), 1 = enable)");
module_param_named(umsch_mm_fwlog, amdgpu_umsch_mm_fwlog, int, 0444);
/**
* DOC: smu_pptable_id (int)
* Used to override pptable id. id = 0 use VBIOS pptable.
......
......@@ -23,7 +23,10 @@
*/
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/debugfs.h>
#include <drm/drm_exec.h>
#include <drm/drm_drv.h>
#include "amdgpu.h"
#include "amdgpu_umsch_mm.h"
......@@ -743,6 +746,17 @@ static int umsch_mm_init(struct amdgpu_device *adev)
return r;
}
r = amdgpu_bo_create_kernel(adev, AMDGPU_UMSCHFW_LOG_SIZE, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM |
AMDGPU_GEM_DOMAIN_GTT,
&adev->umsch_mm.dbglog_bo,
&adev->umsch_mm.log_gpu_addr,
&adev->umsch_mm.log_cpu_addr);
if (r) {
dev_err(adev->dev, "(%d) failed to allocate umsch debug bo\n", r);
return r;
}
mutex_init(&adev->umsch_mm.mutex_hidden);
umsch_mm_agdb_index_init(adev);
......@@ -789,6 +803,7 @@ static int umsch_mm_sw_init(void *handle)
if (r)
return r;
amdgpu_umsch_fwlog_init(&adev->umsch_mm);
r = umsch_mm_ring_init(&adev->umsch_mm);
if (r)
return r;
......@@ -815,6 +830,10 @@ static int umsch_mm_sw_fini(void *handle)
&adev->umsch_mm.cmd_buf_gpu_addr,
(void **)&adev->umsch_mm.cmd_buf_ptr);
amdgpu_bo_free_kernel(&adev->umsch_mm.dbglog_bo,
&adev->umsch_mm.log_gpu_addr,
(void **)&adev->umsch_mm.log_cpu_addr);
amdgpu_device_wb_free(adev, adev->umsch_mm.wb_index);
return 0;
......@@ -868,6 +887,106 @@ static int umsch_mm_resume(void *handle)
return umsch_mm_hw_init(adev);
}
void amdgpu_umsch_fwlog_init(struct amdgpu_umsch_mm *umsch_mm)
{
#if defined(CONFIG_DEBUG_FS)
void *fw_log_cpu_addr = umsch_mm->log_cpu_addr;
volatile struct amdgpu_umsch_fwlog *log_buf = fw_log_cpu_addr;
log_buf->header_size = sizeof(struct amdgpu_umsch_fwlog);
log_buf->buffer_size = AMDGPU_UMSCHFW_LOG_SIZE;
log_buf->rptr = log_buf->header_size;
log_buf->wptr = log_buf->header_size;
log_buf->wrapped = 0;
#endif
}
/*
* debugfs for mapping umsch firmware log buffer.
*/
#if defined(CONFIG_DEBUG_FS)
static ssize_t amdgpu_debugfs_umsch_fwlog_read(struct file *f, char __user *buf,
size_t size, loff_t *pos)
{
struct amdgpu_umsch_mm *umsch_mm;
void *log_buf;
volatile struct amdgpu_umsch_fwlog *plog;
unsigned int read_pos, write_pos, available, i, read_bytes = 0;
unsigned int read_num[2] = {0};
umsch_mm = file_inode(f)->i_private;
if (!umsch_mm)
return -ENODEV;
if (!umsch_mm->log_cpu_addr)
return -EFAULT;
log_buf = umsch_mm->log_cpu_addr;
plog = (volatile struct amdgpu_umsch_fwlog *)log_buf;
read_pos = plog->rptr;
write_pos = plog->wptr;
if (read_pos > AMDGPU_UMSCHFW_LOG_SIZE || write_pos > AMDGPU_UMSCHFW_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_t(size_t, size, available);
} else {
read_num[0] = AMDGPU_UMSCHFW_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_UMSCHFW_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_umschfwlog_fops = {
.owner = THIS_MODULE,
.read = amdgpu_debugfs_umsch_fwlog_read,
.llseek = default_llseek
};
#endif
void amdgpu_debugfs_umsch_fwlog_init(struct amdgpu_device *adev,
struct amdgpu_umsch_mm *umsch_mm)
{
#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_umsch_fwlog");
debugfs_create_file_size(name, S_IFREG | 0444, root, umsch_mm,
&amdgpu_debugfs_umschfwlog_fops,
AMDGPU_UMSCHFW_LOG_SIZE);
#endif
}
static const struct amd_ip_funcs umsch_mm_v4_0_ip_funcs = {
.name = "umsch_mm_v4_0",
.early_init = umsch_mm_early_init,
......
......@@ -58,6 +58,14 @@ struct umsch_mm_set_resource_input {
};
};
struct amdgpu_umsch_fwlog {
uint32_t rptr;
uint32_t wptr;
uint32_t buffer_size;
uint32_t header_size;
uint32_t wrapped;
};
struct umsch_mm_add_queue_input {
uint32_t process_id;
uint64_t page_table_base_addr;
......@@ -166,6 +174,11 @@ struct amdgpu_umsch_mm {
uint32_t agdb_index[CONTEXT_PRIORITY_NUM_LEVELS];
struct mutex mutex_hidden;
struct amdgpu_bo *dbglog_bo;
void *log_cpu_addr;
uint64_t log_gpu_addr;
uint32_t mem_size;
uint32_t log_offset;
};
int amdgpu_umsch_mm_submit_pkt(struct amdgpu_umsch_mm *umsch, void *pkt, int ndws);
......@@ -179,6 +192,11 @@ int amdgpu_umsch_mm_psp_execute_cmd_buf(struct amdgpu_umsch_mm *umsch);
int amdgpu_umsch_mm_ring_init(struct amdgpu_umsch_mm *umsch);
void amdgpu_debugfs_umsch_fwlog_init(struct amdgpu_device *adev,
struct amdgpu_umsch_mm *umsch);
void amdgpu_umsch_fwlog_init(struct amdgpu_umsch_mm *umsch_mm);
#define WREG32_SOC15_UMSCH(reg, value) \
do { \
uint32_t reg_offset = adev->reg_offset[VCN_HWIP][0][reg##_BASE_IDX] + reg; \
......
......@@ -24,6 +24,7 @@
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/debugfs.h>
#include "amdgpu.h"
#include "soc15_common.h"
#include "soc21.h"
......@@ -143,6 +144,11 @@ static int umsch_mm_v4_0_load_microcode(struct amdgpu_umsch_mm *umsch)
WREG32_SOC15_UMSCH(regVCN_MES_GP0_LO, 0);
WREG32_SOC15_UMSCH(regVCN_MES_GP0_HI, 0);
#if defined(CONFIG_DEBUG_FS)
WREG32_SOC15_UMSCH(regVCN_MES_GP0_LO, lower_32_bits(umsch->log_gpu_addr));
WREG32_SOC15_UMSCH(regVCN_MES_GP0_HI, upper_32_bits(umsch->log_gpu_addr));
#endif
WREG32_SOC15_UMSCH(regVCN_MES_GP1_LO, 0);
WREG32_SOC15_UMSCH(regVCN_MES_GP1_HI, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment