From ea52fb043fae3f84bbc8af51919bc52e51a8bf6c Mon Sep 17 00:00:00 2001 From: Bartosz Kokoszko Date: Fri, 19 Oct 2018 09:25:56 +0200 Subject: [PATCH] dma-trace: handling dma trace buffer overflow In dtrace_add_event function I've added handling dma trace buffer overflow. If there is not enough memory, log will be dropped. Amount of dropped entries is counted and it will be logged. Signed-off-by: Bartosz Kokoszko --- src/include/sof/dma-trace.h | 5 ++ src/lib/dma-trace.c | 95 +++++++++++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/include/sof/dma-trace.h b/src/include/sof/dma-trace.h index e970e5361..5b2e5f0df 100644 --- a/src/include/sof/dma-trace.h +++ b/src/include/sof/dma-trace.h @@ -79,4 +79,9 @@ void dma_trace_flush(void *t); void dtrace_event(const char *e, uint32_t size); void dtrace_event_atomic(const char *e, uint32_t length); +static inline uint32_t dtrace_calc_buf_margin(struct dma_trace_buf *buffer) +{ + return buffer->end_addr - buffer->w_ptr; +} + #endif diff --git a/src/lib/dma-trace.c b/src/lib/dma-trace.c index 065849f71..3de42d7cb 100644 --- a/src/lib/dma-trace.c +++ b/src/lib/dma-trace.c @@ -43,6 +43,9 @@ static struct dma_trace_data *trace_data = NULL; +/* amount of dropped entries */ +static uint32_t dropped_entries; + static int dma_trace_get_avail_data(struct dma_trace_data *d, struct dma_trace_buf *buffer, int avail); @@ -365,34 +368,86 @@ void dma_trace_flush(void *t) dcache_writeback_invalidate_region((void *)t, size); } -static void dtrace_add_event(const char *e, uint32_t length) +static int dtrace_calc_buf_overflow(struct dma_trace_buf *buffer, + uint32_t length) { - struct dma_trace_buf *buffer = &trace_data->dmatb; - int margin; + uint32_t margin; + uint32_t overflow_margin; + uint32_t overflow = 0; margin = buffer->end_addr - buffer->w_ptr; - /* check for buffer wrap */ - if (margin > length) { - /* no wrap */ - memcpy(buffer->w_ptr, e, length); - dcache_writeback_invalidate_region(buffer->w_ptr, length); - buffer->w_ptr += length; - } else { + /* overflow calculating */ + if (buffer->w_ptr < buffer->r_ptr) + overflow_margin = buffer->r_ptr - buffer->w_ptr; + else + overflow_margin = margin + buffer->r_ptr - buffer->addr; - /* data is bigger than remaining margin so we wrap */ - memcpy(buffer->w_ptr, e, margin); - dcache_writeback_invalidate_region(buffer->w_ptr, margin); - buffer->w_ptr = buffer->addr; + if (overflow_margin < length) + overflow = length - overflow_margin; - memcpy(buffer->w_ptr, e + margin, length - margin); - dcache_writeback_invalidate_region(buffer->w_ptr, - length - margin); - buffer->w_ptr += length - margin; + return overflow; +} + +static void dtrace_add_event(const char *e, uint32_t length) +{ + struct dma_trace_buf *buffer = &trace_data->dmatb; + uint32_t margin; + uint32_t overflow = 0; + + margin = dtrace_calc_buf_margin(buffer); + overflow = dtrace_calc_buf_overflow(buffer, length); + + /* tracing dropped entries */ + if (dropped_entries) { + if (!overflow) { + /* + * if any dropped entries have appeared and there + * is not any overflow, their amount will be logged + */ + uint32_t tmp_dropped_entries = dropped_entries; + + dropped_entries = 0; + /* + * this trace_error invocation causes recursion, + * so after it we have to recalculate margin and + * overflow + */ + trace_error(0, "Number of dropped logs: %u", + tmp_dropped_entries); + margin = dtrace_calc_buf_margin(buffer); + overflow = dtrace_calc_buf_overflow(buffer, length); + } } - buffer->avail += length; - trace_data->messages++; + /* checking overflow */ + if (!overflow) { + /* check for buffer wrap */ + if (margin > length) { + /* no wrap */ + memcpy(buffer->w_ptr, e, length); + dcache_writeback_invalidate_region(buffer->w_ptr, + length); + buffer->w_ptr += length; + } else { + /* data is bigger than remaining margin so we wrap */ + memcpy(buffer->w_ptr, e, margin); + dcache_writeback_invalidate_region(buffer->w_ptr, + margin); + buffer->w_ptr = buffer->addr; + + memcpy(buffer->w_ptr, e + margin, length - margin); + dcache_writeback_invalidate_region(buffer->w_ptr, + length - margin); + buffer->w_ptr += length - margin; + } + + buffer->avail += length; + trace_data->messages++; + } else { + /* if there is not enough memory for new log, we drop it */ + dropped_entries++; + } } void dtrace_event(const char *e, uint32_t length)