drm/amd/display: Implement dmub trace event
authorYongqiang Sun <yongqiang.sun@amd.com>
Fri, 19 Feb 2021 19:50:23 +0000 (14:50 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 2 Mar 2021 19:07:10 +0000 (14:07 -0500)
[Why & How]
DMUB FW send trace event via outbox0 interrupt.  Driver will handle it.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
drivers/gpu/drm/amd/display/dc/dm_helpers.h
drivers/gpu/drm/amd/display/dc/irq_types.h
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_trace_buffer.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

index 5159399..618c70f 100644 (file)
@@ -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;
+}
index 421af1a..b9d8cfe 100644 (file)
@@ -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);
+}
index d76f9f2..eefec9c 100644 (file)
@@ -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_ */
index 07e349b..65704f4 100644 (file)
@@ -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__ */
index 125b9be..ae8f47e 100644 (file)
@@ -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
 };
index 6e4f558..16d1976 100644 (file)
@@ -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
index 6311135..7100089 100644 (file)
@@ -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
index 6b3ee42..8a122ce 100644 (file)
@@ -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_ */
index 071331b..6934906 100644 (file)
@@ -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;
index df85c3b..de5351c 100644 (file)
@@ -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);
index 6943bf6..eb9bf4d 100644 (file)
@@ -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;
+}