diff --git a/src/include/ipc/header.h b/src/include/ipc/header.h index e6db7f19d3c3..18b4ec3dc495 100644 --- a/src/include/ipc/header.h +++ b/src/include/ipc/header.h @@ -268,6 +268,7 @@ #define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002) #define SOF_IPC_TRACE_DMA_PARAMS_EXT SOF_CMD_TYPE(0x003) #define SOF_IPC_TRACE_FILTER_UPDATE SOF_CMD_TYPE(0x004) /**< ABI3.17 */ +#define SOF_IPC_TRACE_DMA_FREE SOF_CMD_TYPE(0x005) /**< ABI3.20 */ /** @} */ diff --git a/src/include/sof/trace/dma-trace.h b/src/include/sof/trace/dma-trace.h index 53cd8bac2fb8..493d948fa1e3 100644 --- a/src/include/sof/trace/dma-trace.h +++ b/src/include/sof/trace/dma-trace.h @@ -52,6 +52,7 @@ int dma_trace_host_buffer(struct dma_trace_data *d, struct dma_sg_elem_array *elem_array, uint32_t host_size); int dma_trace_enable(struct dma_trace_data *d); +void dma_trace_disable(struct dma_trace_data *d); void dma_trace_flush(void *destination); void dma_trace_on(void); void dma_trace_off(void); diff --git a/src/ipc/ipc3/handler.c b/src/ipc/ipc3/handler.c index a87dd30ef9d7..10e8f355c4ba 100644 --- a/src/ipc/ipc3/handler.c +++ b/src/ipc/ipc3/handler.c @@ -746,7 +746,17 @@ static int ipc_dma_trace_config(uint32_t header) { return 0; } + +static void ipc_dma_trace_free(uint32_t header) {} + #else +static void ipc_dma_trace_free(uint32_t header) +{ + struct dma_trace_data *dmat = dma_trace_data_get(); + + dma_trace_disable(dmat); +} + static int ipc_dma_trace_config(uint32_t header) { #if CONFIG_HOST_PTABLE @@ -872,6 +882,9 @@ static int ipc_glb_trace_message(uint32_t header) case SOF_IPC_TRACE_DMA_PARAMS: case SOF_IPC_TRACE_DMA_PARAMS_EXT: return ipc_dma_trace_config(header); + case SOF_IPC_TRACE_DMA_FREE: + ipc_dma_trace_free(header); + return 0; case SOF_IPC_TRACE_FILTER_UPDATE: return ipc_trace_filter_update(header); default: diff --git a/src/trace/dma-trace.c b/src/trace/dma-trace.c index e757c1a94fae..d852a74fbf9b 100644 --- a/src/trace/dma-trace.c +++ b/src/trace/dma-trace.c @@ -420,6 +420,21 @@ int dma_trace_enable(struct dma_trace_data *d) return err; } +void dma_trace_disable(struct dma_trace_data *d) +{ + /* cancel trace work */ + schedule_task_cancel(&d->dmat_work); + + if (d->dc.chan) { + dma_stop(d->dc.chan); + dma_channel_put(d->dc.chan); + d->dc.chan = NULL; + } + + /* free trace buffer */ + dma_trace_buffer_free(d); +} + /** Sends all pending DMA messages to mailbox (for emergencies) */ void dma_trace_flush(void *t) {