drm/amd/display: Fixed read/write pointer issue for get dmub trace
authorYongqiang Sun <yongqiang.sun@amd.com>
Fri, 26 Feb 2021 16:07:37 +0000 (11:07 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 24 Mar 2021 03:02:46 +0000 (23:02 -0400)
[Why]
Driver get wrap around dmub trace data due to read pointer being
increased incorrectly when there are multiple interrupt
queues with very short interval

[How]
Check read/write pointer before copying data from ring buffer

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: Eryk Brol <eryk.brol@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
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/dmub/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

index b9d8cfe..68453c2 100644 (file)
@@ -172,14 +172,10 @@ bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv,
                       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)
+bool 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;
+       return dmub_srv_get_outbox0_msg(dmub, entry);
 }
 
 void dc_dmub_trace_event_control(struct dc *dc, bool enable)
index eefec9c..338f776 100644 (file)
@@ -62,7 +62,7 @@ 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);
+bool 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);
 
index 16d1976..b4e1496 100644 (file)
@@ -667,7 +667,7 @@ 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);
+bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry);
 
 #if defined(__cplusplus)
 }
index 1f1375c..1ee2000 100644 (file)
@@ -725,27 +725,26 @@ static inline bool dmub_rb_out_trace_buffer_front(struct dmub_rb *rb,
        const uint64_t *src = (const uint64_t *)(rb->base_address) + rb->rptr / sizeof(uint64_t);
        uint64_t *dst = (uint64_t *)entry;
        uint8_t i;
+       uint8_t loop_count;
 
+       if (rb->rptr == rb->wrpt)
+               return false;
+
+       loop_count = sizeof(struct dmcub_trace_buf_entry) / sizeof(uint64_t);
        // copying data
-       for (i = 0; i < sizeof(struct dmcub_trace_buf_entry) / sizeof(uint64_t); i++)
+       for (i = 0; i < loop_count; i++)
                *dst++ = *src++;
 
        rb->rptr += sizeof(struct dmcub_trace_buf_entry);
 
        rb->rptr %= rb->capacity;
 
-       if (rb->rptr == rb->wrpt)
-               return true;
-
-       return false;
+       return true;
 }
 
-enum dmub_status dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry)
+bool 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);
 
-       if (dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry))
-               return DMUB_STATUS_OK;
-
-       return DMUB_STATUS_QUEUE_FULL;
+       return dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry);
 }