From 70732504c53b2d3aae2cebc457515a304672d5bb Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 19 Feb 2021 14:50:23 -0500 Subject: [PATCH] drm/amd/display: Implement dmub trace event [Why & How] DMUB FW send trace event via outbox0 interrupt. Driver will handle it. Tested-by: Daniel Wheeler Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 +++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 16 +++++++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 6 +++ drivers/gpu/drm/amd/display/dc/dm_helpers.h | 2 + drivers/gpu/drm/amd/display/dc/irq_types.h | 1 + drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 14 ++++++ .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 3 ++ .../amd/display/dmub/inc/dmub_trace_buffer.h | 3 +- .../gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 18 +++++++ .../gpu/drm/amd/display/dmub/src/dmub_dcn20.h | 17 ++++++- .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 48 ++++++++++++++++++- 11 files changed, 128 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 5159399f8239..618c70f95573 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -663,3 +663,9 @@ void dm_helpers_free_gpu_mem( { // TODO } + +bool dm_helpes_dmub_outbox0_interrupt_control(struct dc_context *ctx, bool enable) +{ + // TODO + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 421af1a19dfa..b9d8cfef0a1a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -26,6 +26,7 @@ #include "dc.h" #include "dc_dmub_srv.h" #include "../dmub/dmub_srv.h" +#include "dm_helpers.h" #define CTX dc_dmub_srv->ctx #define DC_LOGGER CTX->logger @@ -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, 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); +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index d76f9f2410cb..eefec9cc21a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -30,6 +30,7 @@ #include "dmub/dmub_srv.h" struct dmub_srv; +struct dc; struct dc_reg_helper_state { 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 bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, 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_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 07e349b1067b..65704f46c79b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -156,4 +156,6 @@ void dm_set_dcn_clocks( struct dc_context *ctx, struct dc_clocks *clks); +bool dm_helpes_dmub_outbox0_interrupt_control(struct dc_context *ctx, bool enable); + #endif /* __DM_HELPERS__ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h index 125b9beb505a..ae8f47ec0f8c 100644 --- a/drivers/gpu/drm/amd/display/dc/irq_types.h +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -151,6 +151,7 @@ enum dc_irq_source { DC_IRQ_SOURCE_DC5_VLINE1, DC_IRQ_SOURCE_DC6_VLINE1, DC_IRQ_DMCUB_OUTBOX1, + DC_IRQ_SOURCE_DMCUB_OUTBOX0, DAL_IRQ_SOURCES_NUMBER }; diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 6e4f558fe97e..16d1976b041f 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -74,6 +74,8 @@ extern "C" { struct dmub_srv; struct dmub_srv_common_regs; +struct dmcub_trace_buf_entry; + /* enum dmub_status - return code for dmcub functions */ enum dmub_status { DMUB_STATUS_OK = 0, @@ -272,6 +274,13 @@ struct dmub_srv_hw_funcs { 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); void (*emul_set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset); @@ -295,6 +304,7 @@ struct dmub_srv_hw_funcs { union dmub_gpint_data_register reg); uint32_t (*get_gpint_response)(struct dmub_srv *dmub); + }; /** @@ -360,6 +370,8 @@ struct dmub_srv { */ struct dmub_rb outbox1_rb; + struct dmub_rb outbox0_rb; + bool sw_init; bool hw_init; @@ -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, 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) } #endif diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 63111351d1e3..7100089bf7df 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -79,6 +79,9 @@ /* Maximum number of planes on any ASIC. */ #define DMUB_MAX_PLANES 6 +/* Trace buffer offset for entry */ +#define TRACE_BUFFER_ENTRY_OFFSET 16 + #ifndef PHYSICAL_ADDRESS_LOC #define PHYSICAL_ADDRESS_LOC union large_integer #endif diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_trace_buffer.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_trace_buffer.h index 6b3ee42db350..8a122ceabb3a 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_trace_buffer.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_trace_buffer.h @@ -25,7 +25,7 @@ #ifndef _DMUB_TRACE_BUFFER_H_ #define _DMUB_TRACE_BUFFER_H_ -#include "dmub_types.h" +#include "dmub_cmd.h" #define LOAD_DMCU_FW 1 #define LOAD_PHY_FW 2 @@ -65,5 +65,4 @@ struct dmcub_trace_buf { struct dmcub_trace_buf_entry entries[PERF_TRACE_MAX_ENTRY]; }; - #endif /* _DMUB_TRACE_BUFFER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index 071331bcc427..6934906c665e 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -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); } +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) { uint32_t is_hw_init; diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h index df85c3b86607..de5351cd5abc 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h @@ -40,6 +40,10 @@ struct dmub_srv; DMUB_SR(DMCUB_INBOX1_SIZE) \ DMUB_SR(DMCUB_INBOX1_RPTR) \ 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_SIZE) \ DMUB_SR(DMCUB_OUTBOX1_RPTR) \ @@ -102,7 +106,8 @@ struct dmub_srv; DMUB_SR(CC_DC_PIPE_DIS) \ DMUB_SR(MMHUBBUB_SOFT_RESET) \ 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() \ DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ @@ -135,7 +140,8 @@ struct dmub_srv; DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) \ DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \ 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 { #define DMUB_SR(reg) uint32_t reg; @@ -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_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_supported(struct dmub_srv *dmub); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 6943bf679b42..eb9bf4da088a 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -31,6 +31,7 @@ #include "dmub_dcn301.h" #include "dmub_dcn302.h" #include "os_types.h" +#include "dmub_trace_buffer.h" /* * Note: the DMUB service is standalone. No additional headers should be * added below or above this line unless they reside within the DMUB @@ -55,6 +56,7 @@ /* Default tracebuffer size if meta is absent. */ #define DMUB_TRACE_BUFFER_SIZE (64 * 1024) + /* Default scratch mem size. */ #define DMUB_SCRATCH_MEM_SIZE (256) @@ -69,6 +71,8 @@ #define DMUB_CW5_BASE (0x65000000) #define DMUB_CW6_BASE (0x66000000) +#define DMUB_REGION5_BASE (0xA0000000) + static inline uint32_t dmub_align(uint32_t val, uint32_t 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) funcs->get_outbox1_wptr = dmub_dcn20_get_outbox1_wptr; 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) { dmub->regs = &dmub_srv_dcn21_regs; @@ -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 *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_region inbox1, outbox1; + struct dmub_region inbox1, outbox1, outbox0; if (!dmub->sw_init) return DMUB_STATUS_INVALID; @@ -465,6 +474,10 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, cw5.region.base = DMUB_CW5_BASE; 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.region.base = DMUB_CW6_BASE; 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, dmub->hw_funcs.setup_windows(dmub, &cw2, &cw3, &cw4, &cw5, &cw6); + if (dmub->hw_funcs.setup_outbox0) + dmub->hw_funcs.setup_outbox0(dmub, &outbox0); + if (dmub->hw_funcs.setup_mailbox) dmub->hw_funcs.setup_mailbox(dmub, &inbox1); if (dmub->hw_funcs.setup_out_mailbox) @@ -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) dmub->hw_funcs.reset_release(dmub); @@ -697,3 +719,25 @@ enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub, 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; +} -- 2.25.1