From 6804287bd1421f290065081db4b1a93c2fd2c591 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 26 Feb 2021 11:07:37 -0500 Subject: [PATCH] drm/amd/display: Fixed read/write pointer issue for get dmub trace [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 Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 8 ++------ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 2 +- drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 +- .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 19 +++++++++---------- 4 files changed, 13 insertions(+), 18 deletions(-) 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 b9d8cfef0a1a..68453c29c617 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -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) 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 eefec9cc21a8..338f776990db 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -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); diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 16d1976b041f..b4e14960b164 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -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) } 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 1f1375c49aa5..1ee2000ad099 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -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); } -- 2.34.1