dma-trace: Make dmatb and DMA_GW dma_sg persistent after first allocation

Do not free the dmatb so that the trace code can continue collecting
information continuously in it's buffer.

We also have another memory leak (when CONFIG_DMA_GW is set) which can be
handled this way:
Every time the dma_trace_start() is called we allocate a new dma_sg. This
is fine when the dma_trace_start() is only called once right after the
DSP finished booting, but multiple calls would eventually going to lead to
OOM.

Move the dma_sg allocation at the same place where the dmatb is allocated
to make it persistent as well.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
This commit is contained in:
Peter Ujfalusi 2021-12-17 12:08:52 +02:00 committed by Liam Girdwood
parent 1ae525ad37
commit 64c7b9868e
2 changed files with 50 additions and 39 deletions

View File

@ -30,6 +30,9 @@ struct dma_trace_buf {
struct dma_trace_data {
struct dma_sg_config config;
struct dma_trace_buf dmatb;
#if CONFIG_DMA_GW
struct dma_sg_config gw_config;
#endif
struct dma_copy dc;
struct sof_ipc_dma_trace_posn posn;
struct ipc_msg *msg;

View File

@ -59,6 +59,10 @@ static enum task_state trace_work(void *data)
int32_t size;
uint32_t overflow;
/* The host DMA channel is not available */
if (!d->dc.chan)
return SOF_TASK_STATE_RESCHEDULE;
/* make sure we don't write more than buffer */
if (avail > DMA_TRACE_LOCAL_SIZE) {
overflow = avail - DMA_TRACE_LOCAL_SIZE;
@ -218,8 +222,26 @@ int dma_trace_host_buffer(struct dma_trace_data *d,
}
#endif
static void dma_trace_buffer_free(struct dma_trace_data *d)
{
struct dma_trace_buf *buffer = &d->dmatb;
k_spinlock_key_t key;
key = k_spin_lock(&d->lock);
rfree(buffer->addr);
memset(buffer, 0, sizeof(*buffer));
k_spin_unlock(&d->lock, key);
}
static int dma_trace_buffer_init(struct dma_trace_data *d)
{
#if CONFIG_DMA_GW
struct dma_sg_config *config = &d->gw_config;
uint32_t elem_size, elem_addr, elem_num;
int ret;
#endif
struct dma_trace_buf *buffer = &d->dmatb;
void *buf;
k_spinlock_key_t key;
@ -271,6 +293,30 @@ static int dma_trace_buffer_init(struct dma_trace_data *d)
k_spin_unlock(&d->lock, key);
#if CONFIG_DMA_GW
/* size of every trace record */
elem_size = sizeof(uint64_t) * 2;
/* Initialize address of local elem */
elem_addr = (uint32_t)buffer->addr;
/* the number of elem list */
elem_num = DMA_TRACE_LOCAL_SIZE / elem_size;
config->direction = DMA_DIR_LMEM_TO_HMEM;
config->src_width = sizeof(uint32_t);
config->dest_width = sizeof(uint32_t);
config->cyclic = 0;
ret = dma_sg_alloc(&config->elem_array, SOF_MEM_ZONE_SYS,
config->direction, elem_num, elem_size,
elem_addr, 0);
if (ret < 0) {
dma_trace_buffer_free(d);
return ret;
}
#endif
#ifdef __ZEPHYR__
#define ZEPHYR_VER_OPT " zephyr:" META_QUOTE(BUILD_VERSION)
#else
@ -299,25 +345,10 @@ static int dma_trace_buffer_init(struct dma_trace_data *d)
return 0;
}
static void dma_trace_buffer_free(struct dma_trace_data *d)
{
struct dma_trace_buf *buffer = &d->dmatb;
k_spinlock_key_t key;
key = k_spin_lock(&d->lock);
rfree(buffer->addr);
memset(buffer, 0, sizeof(*buffer));
k_spin_unlock(&d->lock, key);
}
#if CONFIG_DMA_GW
static int dma_trace_start(struct dma_trace_data *d)
{
struct dma_sg_config config;
uint32_t elem_size, elem_addr, elem_num;
int err = 0;
/* DMA Controller initialization is platform-specific */
@ -361,27 +392,7 @@ static int dma_trace_start(struct dma_trace_data *d)
d->active_stream_tag = d->stream_tag;
/* size of every trace record */
elem_size = sizeof(uint64_t) * 2;
/* Initialize address of local elem */
elem_addr = (uint32_t)d->dmatb.addr;
/* the number of elem list */
elem_num = DMA_TRACE_LOCAL_SIZE / elem_size;
config.direction = DMA_DIR_LMEM_TO_HMEM;
config.src_width = sizeof(uint32_t);
config.dest_width = sizeof(uint32_t);
config.cyclic = 0;
err = dma_sg_alloc(&config.elem_array, SOF_MEM_ZONE_SYS,
config.direction,
elem_num, elem_size, elem_addr, 0);
if (err < 0)
goto error;
err = dma_set_config(d->dc.chan, &config);
err = dma_set_config(d->dc.chan, &d->gw_config);
if (err < 0) {
mtrace_printf(LOG_LEVEL_ERROR, "dma_set_config() failed: %d", err);
goto error;
@ -501,9 +512,6 @@ void dma_trace_disable(struct dma_trace_data *d)
d->dc.chan = NULL;
}
/* free trace buffer */
dma_trace_buffer_free(d);
#if (CONFIG_HOST_PTABLE)
/* Free up the host SG if it is set */
if (d->host_size) {