Merge pull request #498 from bkokoszx/dma-buffer-overflow

dma-trace: handling dma trace buffer overflow
This commit is contained in:
Liam Girdwood 2018-10-25 10:34:22 +01:00 committed by GitHub
commit 61e689c9f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 20 deletions

View File

@ -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

View File

@ -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)