diff --git a/src/drivers/intel/hda/hda-dma.c b/src/drivers/intel/hda/hda-dma.c index 7edb93279c98..8aa6461f7de5 100644 --- a/src/drivers/intel/hda/hda-dma.c +++ b/src/drivers/intel/hda/hda-dma.c @@ -818,12 +818,20 @@ static int hda_dma_set_config(struct dma_chan_data *channel, /* buffer size must be multiple of hda dma burst size */ if (buffer_bytes % HDA_DMA_BUFFER_ALIGNMENT) { - tr_err(&hdma_tr, "hda-dmac: %d chan %d - buffer not DMA aligned 0x%x", + tr_err(&hdma_tr, "hda-dmac: %d chan %d - buffer size not DMA aligned 0x%x", dma->plat_data.id, channel->index, buffer_bytes); ret = -EINVAL; goto out; } + /* buffer base address must be correctly aligned */ + if (buffer_addr % HDA_DMA_BUFFER_ADDRESS_ALIGNMENT) { + tr_err(&hdma_tr, "hda-dmac: %d chan %d - buffer address not DMA aligned 0x%x", + dma->plat_data.id, + channel->index, buffer_addr); + ret = -EINVAL; + goto out; + } hda_chan = dma_chan_get_data(channel); hda_chan->period_bytes = period_bytes; hda_chan->buffer_bytes = buffer_bytes; diff --git a/src/include/sof/lib/dma.h b/src/include/sof/lib/dma.h index 1edc72a2bc4e..b95581128300 100644 --- a/src/include/sof/lib/dma.h +++ b/src/include/sof/lib/dma.h @@ -541,8 +541,8 @@ int dma_copy_from_host_nowait(struct dma_copy *dc, int32_t size); /* DMA copy data from DSP to host */ -int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, - int32_t host_offset, void *local_ptr, int32_t size); +int dma_copy_to_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); int dma_copy_set_stream_tag(struct dma_copy *dc, uint32_t stream_tag); diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index f7caec41c2d7..16ee09d2f463 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -59,13 +59,13 @@ static struct dma_sg_elem *sg_get_elem_at(struct dma_sg_config *host_sg, */ #if CONFIG_DMA_GW -int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, - int32_t host_offset, void *local_ptr, int32_t size) +int dma_copy_to_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size) { int ret; /* tell gateway to copy */ - ret = dma_copy(dc->chan, size, 0); + ret = dma_copy(dc->chan, size, DMA_COPY_BLOCKING); if (ret < 0) return ret; @@ -75,8 +75,8 @@ int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, #else /* CONFIG_DMA_GW */ -int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, - int32_t host_offset, void *local_ptr, int32_t size) +int dma_copy_to_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size) { struct dma_sg_config config; struct dma_sg_elem *host_sg_elem; diff --git a/src/probe/probe.c b/src/probe/probe.c index 5d4f4a65576d..7b3f462d26cb 100644 --- a/src/probe/probe.c +++ b/src/probe/probe.c @@ -201,15 +201,15 @@ static enum task_state probe_task(void *data) int err; if (_probe->ext_dma.dmapb.avail > 0) - err = dma_copy_to_host_nowait(&_probe->ext_dma.dc, - &_probe->ext_dma.config, 0, - (void *)_probe->ext_dma.dmapb.r_ptr, - _probe->ext_dma.dmapb.avail); + err = dma_copy_to_host(&_probe->ext_dma.dc, + &_probe->ext_dma.config, 0, + (void *)_probe->ext_dma.dmapb.r_ptr, + _probe->ext_dma.dmapb.avail); else return SOF_TASK_STATE_RESCHEDULE; if (err < 0) { - tr_err(&pr_tr, "probe_task(): dma_copy_to_host_nowait() failed."); + tr_err(&pr_tr, "probe_task(): dma_copy_to_host() failed."); return err; } diff --git a/src/trace/dma-trace.c b/src/trace/dma-trace.c index e3bd79207f5c..701278d311d4 100644 --- a/src/trace/dma-trace.c +++ b/src/trace/dma-trace.c @@ -83,10 +83,10 @@ static enum task_state trace_work(void *data) d->copy_in_progress = 1; /* copy this section to host */ - size = dma_copy_to_host_nowait(&d->dc, config, d->posn.host_offset, - buffer->r_ptr, size); + size = dma_copy_to_host(&d->dc, config, d->posn.host_offset, + buffer->r_ptr, size); if (size < 0) { - tr_err(&dt_tr, "trace_work(): dma_copy_to_host_nowait() failed"); + tr_err(&dt_tr, "trace_work(): dma_copy_to_host() failed"); goto out; } @@ -223,10 +223,23 @@ static int dma_trace_buffer_init(struct dma_trace_data *d) struct dma_trace_buf *buffer = &d->dmatb; void *buf; k_spinlock_key_t key; + uint32_t addr_align; + int err; + + if (!d || !d->dc.dmac) { + mtrace_printf(LOG_LEVEL_ERROR, + "%s failed: no DMAC!", __func__); + return -ENODEV; + } + + err = dma_get_attribute(d->dc.dmac, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + if (err < 0) + return err; - /* allocate new buffer */ - buf = rballoc(0, SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, - DMA_TRACE_LOCAL_SIZE); + /* For DMA to work properly the buffer must be correctly aligned */ + buf = rballoc_align(0, SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + DMA_TRACE_LOCAL_SIZE, addr_align); if (!buf) { tr_err(&dt_tr, "dma_trace_buffer_init(): alloc failed"); return -ENOMEM;