Commit 70732504 authored by Yongqiang Sun's avatar Yongqiang Sun Committed by Alex Deucher

drm/amd/display: Implement dmub trace event

[Why & How]
DMUB FW send trace event via outbox0 interrupt.  Driver will handle it.
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarYongqiang Sun <yongqiang.sun@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 8039bc71
...@@ -663,3 +663,9 @@ void dm_helpers_free_gpu_mem( ...@@ -663,3 +663,9 @@ void dm_helpers_free_gpu_mem(
{ {
// TODO // TODO
} }
bool dm_helpes_dmub_outbox0_interrupt_control(struct dc_context *ctx, bool enable)
{
// TODO
return true;
}
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "dc.h" #include "dc.h"
#include "dc_dmub_srv.h" #include "dc_dmub_srv.h"
#include "../dmub/dmub_srv.h" #include "../dmub/dmub_srv.h"
#include "dm_helpers.h"
#define CTX dc_dmub_srv->ctx #define CTX dc_dmub_srv->ctx
#define DC_LOGGER CTX->logger #define DC_LOGGER CTX->logger
...@@ -170,3 +171,18 @@ bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, ...@@ -170,3 +171,18 @@ bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv,
dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK, dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK,
stream_mask, timeout) == DMUB_STATUS_OK; stream_mask, timeout) == DMUB_STATUS_OK;
} }
enum dmub_status dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_buf_entry *entry)
{
struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub;
enum dmub_status status;
status = dmub_srv_get_outbox0_msg(dmub, entry);
return status;
}
void dc_dmub_trace_event_control(struct dc *dc, bool enable)
{
dm_helpes_dmub_outbox0_interrupt_control(dc->ctx, enable);
}
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "dmub/dmub_srv.h" #include "dmub/dmub_srv.h"
struct dmub_srv; struct dmub_srv;
struct dc;
struct dc_reg_helper_state { struct dc_reg_helper_state {
bool gather_in_progress; bool gather_in_progress;
...@@ -60,4 +61,9 @@ bool dc_dmub_srv_cmd_with_reply_data(struct dc_dmub_srv *dc_dmub_srv, union dmub ...@@ -60,4 +61,9 @@ bool dc_dmub_srv_cmd_with_reply_data(struct dc_dmub_srv *dc_dmub_srv, union dmub
bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv,
unsigned int stream_mask); unsigned int stream_mask);
enum dmub_status dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_buf_entry *entry);
void dc_dmub_trace_event_control(struct dc *dc, bool enable);
#endif /* _DMUB_DC_SRV_H_ */ #endif /* _DMUB_DC_SRV_H_ */
...@@ -156,4 +156,6 @@ void dm_set_dcn_clocks( ...@@ -156,4 +156,6 @@ void dm_set_dcn_clocks(
struct dc_context *ctx, struct dc_context *ctx,
struct dc_clocks *clks); struct dc_clocks *clks);
bool dm_helpes_dmub_outbox0_interrupt_control(struct dc_context *ctx, bool enable);
#endif /* __DM_HELPERS__ */ #endif /* __DM_HELPERS__ */
...@@ -151,6 +151,7 @@ enum dc_irq_source { ...@@ -151,6 +151,7 @@ enum dc_irq_source {
DC_IRQ_SOURCE_DC5_VLINE1, DC_IRQ_SOURCE_DC5_VLINE1,
DC_IRQ_SOURCE_DC6_VLINE1, DC_IRQ_SOURCE_DC6_VLINE1,
DC_IRQ_DMCUB_OUTBOX1, DC_IRQ_DMCUB_OUTBOX1,
DC_IRQ_SOURCE_DMCUB_OUTBOX0,
DAL_IRQ_SOURCES_NUMBER DAL_IRQ_SOURCES_NUMBER
}; };
......
...@@ -74,6 +74,8 @@ extern "C" { ...@@ -74,6 +74,8 @@ extern "C" {
struct dmub_srv; struct dmub_srv;
struct dmub_srv_common_regs; struct dmub_srv_common_regs;
struct dmcub_trace_buf_entry;
/* enum dmub_status - return code for dmcub functions */ /* enum dmub_status - return code for dmcub functions */
enum dmub_status { enum dmub_status {
DMUB_STATUS_OK = 0, DMUB_STATUS_OK = 0,
...@@ -272,6 +274,13 @@ struct dmub_srv_hw_funcs { ...@@ -272,6 +274,13 @@ struct dmub_srv_hw_funcs {
void (*set_outbox1_rptr)(struct dmub_srv *dmub, uint32_t rptr_offset); void (*set_outbox1_rptr)(struct dmub_srv *dmub, uint32_t rptr_offset);
void (*setup_outbox0)(struct dmub_srv *dmub,
const struct dmub_region *outbox0);
uint32_t (*get_outbox0_wptr)(struct dmub_srv *dmub);
void (*set_outbox0_rptr)(struct dmub_srv *dmub, uint32_t rptr_offset);
uint32_t (*emul_get_inbox1_rptr)(struct dmub_srv *dmub); uint32_t (*emul_get_inbox1_rptr)(struct dmub_srv *dmub);
void (*emul_set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset); void (*emul_set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset);
...@@ -295,6 +304,7 @@ struct dmub_srv_hw_funcs { ...@@ -295,6 +304,7 @@ struct dmub_srv_hw_funcs {
union dmub_gpint_data_register reg); union dmub_gpint_data_register reg);
uint32_t (*get_gpint_response)(struct dmub_srv *dmub); uint32_t (*get_gpint_response)(struct dmub_srv *dmub);
}; };
/** /**
...@@ -360,6 +370,8 @@ struct dmub_srv { ...@@ -360,6 +370,8 @@ struct dmub_srv {
*/ */
struct dmub_rb outbox1_rb; struct dmub_rb outbox1_rb;
struct dmub_rb outbox0_rb;
bool sw_init; bool sw_init;
bool hw_init; bool hw_init;
...@@ -655,6 +667,8 @@ enum dmub_status dmub_srv_get_fw_boot_status(struct dmub_srv *dmub, ...@@ -655,6 +667,8 @@ enum dmub_status dmub_srv_get_fw_boot_status(struct dmub_srv *dmub,
enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub, enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub,
union dmub_rb_cmd *cmd); union dmub_rb_cmd *cmd);
enum dmub_status dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif
......
...@@ -79,6 +79,9 @@ ...@@ -79,6 +79,9 @@
/* Maximum number of planes on any ASIC. */ /* Maximum number of planes on any ASIC. */
#define DMUB_MAX_PLANES 6 #define DMUB_MAX_PLANES 6
/* Trace buffer offset for entry */
#define TRACE_BUFFER_ENTRY_OFFSET 16
#ifndef PHYSICAL_ADDRESS_LOC #ifndef PHYSICAL_ADDRESS_LOC
#define PHYSICAL_ADDRESS_LOC union large_integer #define PHYSICAL_ADDRESS_LOC union large_integer
#endif #endif
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#ifndef _DMUB_TRACE_BUFFER_H_ #ifndef _DMUB_TRACE_BUFFER_H_
#define _DMUB_TRACE_BUFFER_H_ #define _DMUB_TRACE_BUFFER_H_
#include "dmub_types.h" #include "dmub_cmd.h"
#define LOAD_DMCU_FW 1 #define LOAD_DMCU_FW 1
#define LOAD_PHY_FW 2 #define LOAD_PHY_FW 2
...@@ -65,5 +65,4 @@ struct dmcub_trace_buf { ...@@ -65,5 +65,4 @@ struct dmcub_trace_buf {
struct dmcub_trace_buf_entry entries[PERF_TRACE_MAX_ENTRY]; struct dmcub_trace_buf_entry entries[PERF_TRACE_MAX_ENTRY];
}; };
#endif /* _DMUB_TRACE_BUFFER_H_ */ #endif /* _DMUB_TRACE_BUFFER_H_ */
...@@ -319,6 +319,24 @@ void dmub_dcn20_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset) ...@@ -319,6 +319,24 @@ void dmub_dcn20_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
REG_WRITE(DMCUB_OUTBOX1_RPTR, rptr_offset); REG_WRITE(DMCUB_OUTBOX1_RPTR, rptr_offset);
} }
void dmub_dcn20_setup_outbox0(struct dmub_srv *dmub,
const struct dmub_region *outbox0)
{
REG_WRITE(DMCUB_OUTBOX0_BASE_ADDRESS, outbox0->base);
REG_WRITE(DMCUB_OUTBOX0_SIZE, outbox0->top - outbox0->base);
}
uint32_t dmub_dcn20_get_outbox0_wptr(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_OUTBOX0_WPTR);
}
void dmub_dcn20_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
{
REG_WRITE(DMCUB_OUTBOX0_RPTR, rptr_offset);
}
bool dmub_dcn20_is_hw_init(struct dmub_srv *dmub) bool dmub_dcn20_is_hw_init(struct dmub_srv *dmub)
{ {
uint32_t is_hw_init; uint32_t is_hw_init;
......
...@@ -40,6 +40,10 @@ struct dmub_srv; ...@@ -40,6 +40,10 @@ struct dmub_srv;
DMUB_SR(DMCUB_INBOX1_SIZE) \ DMUB_SR(DMCUB_INBOX1_SIZE) \
DMUB_SR(DMCUB_INBOX1_RPTR) \ DMUB_SR(DMCUB_INBOX1_RPTR) \
DMUB_SR(DMCUB_INBOX1_WPTR) \ DMUB_SR(DMCUB_INBOX1_WPTR) \
DMUB_SR(DMCUB_OUTBOX0_BASE_ADDRESS) \
DMUB_SR(DMCUB_OUTBOX0_SIZE) \
DMUB_SR(DMCUB_OUTBOX0_RPTR) \
DMUB_SR(DMCUB_OUTBOX0_WPTR) \
DMUB_SR(DMCUB_OUTBOX1_BASE_ADDRESS) \ DMUB_SR(DMCUB_OUTBOX1_BASE_ADDRESS) \
DMUB_SR(DMCUB_OUTBOX1_SIZE) \ DMUB_SR(DMCUB_OUTBOX1_SIZE) \
DMUB_SR(DMCUB_OUTBOX1_RPTR) \ DMUB_SR(DMCUB_OUTBOX1_RPTR) \
...@@ -102,7 +106,8 @@ struct dmub_srv; ...@@ -102,7 +106,8 @@ struct dmub_srv;
DMUB_SR(CC_DC_PIPE_DIS) \ DMUB_SR(CC_DC_PIPE_DIS) \
DMUB_SR(MMHUBBUB_SOFT_RESET) \ DMUB_SR(MMHUBBUB_SOFT_RESET) \
DMUB_SR(DCN_VM_FB_LOCATION_BASE) \ DMUB_SR(DCN_VM_FB_LOCATION_BASE) \
DMUB_SR(DCN_VM_FB_OFFSET) DMUB_SR(DCN_VM_FB_OFFSET) \
DMUB_SR(DMCUB_INTERRUPT_ACK)
#define DMUB_COMMON_FIELDS() \ #define DMUB_COMMON_FIELDS() \
DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
...@@ -135,7 +140,8 @@ struct dmub_srv; ...@@ -135,7 +140,8 @@ struct dmub_srv;
DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) \ DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) \
DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \ DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \ DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \
DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX0_READY_INT_ACK)
struct dmub_srv_common_reg_offset { struct dmub_srv_common_reg_offset {
#define DMUB_SR(reg) uint32_t reg; #define DMUB_SR(reg) uint32_t reg;
...@@ -196,6 +202,13 @@ uint32_t dmub_dcn20_get_outbox1_wptr(struct dmub_srv *dmub); ...@@ -196,6 +202,13 @@ uint32_t dmub_dcn20_get_outbox1_wptr(struct dmub_srv *dmub);
void dmub_dcn20_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset); void dmub_dcn20_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset);
void dmub_dcn20_setup_outbox0(struct dmub_srv *dmub,
const struct dmub_region *outbox0);
uint32_t dmub_dcn20_get_outbox0_wptr(struct dmub_srv *dmub);
void dmub_dcn20_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset);
bool dmub_dcn20_is_hw_init(struct dmub_srv *dmub); bool dmub_dcn20_is_hw_init(struct dmub_srv *dmub);
bool dmub_dcn20_is_supported(struct dmub_srv *dmub); bool dmub_dcn20_is_supported(struct dmub_srv *dmub);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "dmub_dcn301.h" #include "dmub_dcn301.h"
#include "dmub_dcn302.h" #include "dmub_dcn302.h"
#include "os_types.h" #include "os_types.h"
#include "dmub_trace_buffer.h"
/* /*
* Note: the DMUB service is standalone. No additional headers should be * Note: the DMUB service is standalone. No additional headers should be
* added below or above this line unless they reside within the DMUB * added below or above this line unless they reside within the DMUB
...@@ -55,6 +56,7 @@ ...@@ -55,6 +56,7 @@
/* Default tracebuffer size if meta is absent. */ /* Default tracebuffer size if meta is absent. */
#define DMUB_TRACE_BUFFER_SIZE (64 * 1024) #define DMUB_TRACE_BUFFER_SIZE (64 * 1024)
/* Default scratch mem size. */ /* Default scratch mem size. */
#define DMUB_SCRATCH_MEM_SIZE (256) #define DMUB_SCRATCH_MEM_SIZE (256)
...@@ -69,6 +71,8 @@ ...@@ -69,6 +71,8 @@
#define DMUB_CW5_BASE (0x65000000) #define DMUB_CW5_BASE (0x65000000)
#define DMUB_CW6_BASE (0x66000000) #define DMUB_CW6_BASE (0x66000000)
#define DMUB_REGION5_BASE (0xA0000000)
static inline uint32_t dmub_align(uint32_t val, uint32_t factor) static inline uint32_t dmub_align(uint32_t val, uint32_t factor)
{ {
return (val + factor - 1) / factor * factor; return (val + factor - 1) / factor * factor;
...@@ -162,6 +166,11 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) ...@@ -162,6 +166,11 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->get_outbox1_wptr = dmub_dcn20_get_outbox1_wptr; funcs->get_outbox1_wptr = dmub_dcn20_get_outbox1_wptr;
funcs->set_outbox1_rptr = dmub_dcn20_set_outbox1_rptr; funcs->set_outbox1_rptr = dmub_dcn20_set_outbox1_rptr;
//outbox0 call stacks
funcs->setup_outbox0 = dmub_dcn20_setup_outbox0;
funcs->get_outbox0_wptr = dmub_dcn20_get_outbox0_wptr;
funcs->set_outbox0_rptr = dmub_dcn20_set_outbox0_rptr;
if (asic == DMUB_ASIC_DCN21) { if (asic == DMUB_ASIC_DCN21) {
dmub->regs = &dmub_srv_dcn21_regs; dmub->regs = &dmub_srv_dcn21_regs;
...@@ -400,9 +409,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, ...@@ -400,9 +409,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
struct dmub_fb *fw_state_fb = params->fb[DMUB_WINDOW_6_FW_STATE]; struct dmub_fb *fw_state_fb = params->fb[DMUB_WINDOW_6_FW_STATE];
struct dmub_fb *scratch_mem_fb = params->fb[DMUB_WINDOW_7_SCRATCH_MEM]; struct dmub_fb *scratch_mem_fb = params->fb[DMUB_WINDOW_7_SCRATCH_MEM];
struct dmub_rb_init_params rb_params; struct dmub_rb_init_params rb_params, outbox0_rb_params;
struct dmub_window cw0, cw1, cw2, cw3, cw4, cw5, cw6; struct dmub_window cw0, cw1, cw2, cw3, cw4, cw5, cw6;
struct dmub_region inbox1, outbox1; struct dmub_region inbox1, outbox1, outbox0;
if (!dmub->sw_init) if (!dmub->sw_init)
return DMUB_STATUS_INVALID; return DMUB_STATUS_INVALID;
...@@ -465,6 +474,10 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, ...@@ -465,6 +474,10 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
cw5.region.base = DMUB_CW5_BASE; cw5.region.base = DMUB_CW5_BASE;
cw5.region.top = cw5.region.base + tracebuff_fb->size; cw5.region.top = cw5.region.base + tracebuff_fb->size;
outbox0.base = DMUB_REGION5_BASE + TRACE_BUFFER_ENTRY_OFFSET;
outbox0.top = outbox0.base + sizeof(struct dmcub_trace_buf_entry) * PERF_TRACE_MAX_ENTRY;
cw6.offset.quad_part = fw_state_fb->gpu_addr; cw6.offset.quad_part = fw_state_fb->gpu_addr;
cw6.region.base = DMUB_CW6_BASE; cw6.region.base = DMUB_CW6_BASE;
cw6.region.top = cw6.region.base + fw_state_fb->size; cw6.region.top = cw6.region.base + fw_state_fb->size;
...@@ -477,6 +490,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, ...@@ -477,6 +490,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
dmub->hw_funcs.setup_windows(dmub, &cw2, &cw3, &cw4, dmub->hw_funcs.setup_windows(dmub, &cw2, &cw3, &cw4,
&cw5, &cw6); &cw5, &cw6);
if (dmub->hw_funcs.setup_outbox0)
dmub->hw_funcs.setup_outbox0(dmub, &outbox0);
if (dmub->hw_funcs.setup_mailbox) if (dmub->hw_funcs.setup_mailbox)
dmub->hw_funcs.setup_mailbox(dmub, &inbox1); dmub->hw_funcs.setup_mailbox(dmub, &inbox1);
if (dmub->hw_funcs.setup_out_mailbox) if (dmub->hw_funcs.setup_out_mailbox)
...@@ -499,6 +515,12 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, ...@@ -499,6 +515,12 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
} }
dmub_memset(&outbox0_rb_params, 0, sizeof(outbox0_rb_params));
outbox0_rb_params.ctx = dmub;
outbox0_rb_params.base_address = (void *)((uint64_t)(tracebuff_fb->cpu_addr) + TRACE_BUFFER_ENTRY_OFFSET);
outbox0_rb_params.capacity = sizeof(struct dmcub_trace_buf_entry) * PERF_TRACE_MAX_ENTRY;
dmub_rb_init(&dmub->outbox0_rb, &outbox0_rb_params);
if (dmub->hw_funcs.reset_release) if (dmub->hw_funcs.reset_release)
dmub->hw_funcs.reset_release(dmub); dmub->hw_funcs.reset_release(dmub);
...@@ -697,3 +719,25 @@ enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub, ...@@ -697,3 +719,25 @@ enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub,
return status; return status;
} }
static inline void dmub_rb_out_trace_buffer_front(struct dmub_rb *rb,
void *entry)
{
const uint64_t *src = (const uint64_t *)(rb->base_address) + rb->rptr / sizeof(uint64_t);
uint64_t *dst = (uint64_t *)entry;
uint8_t i;
// copying data
for (i = 0; i < sizeof(struct dmcub_trace_buf_entry) / sizeof(uint64_t); i++)
*dst++ = *src++;
}
enum dmub_status dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry)
{
dmub->outbox0_rb.wrpt = dmub->hw_funcs.get_outbox0_wptr(dmub);
dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry);
return DMUB_STATUS_OK;
}
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