From 61868ed263b6a04629f990ea7221c5fa8984cd30 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 21 Sep 2021 11:50:56 -0700 Subject: [PATCH 1/4] Revert "Revert "trace: Kconfig: disable filtering by default"" revert the revert just for testing. This reverts commit d8a19a4d2062cde129f2a18e414b07ce9ab31c73. Signed-off-by: Ranjani Sridharan --- src/trace/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/trace/Kconfig b/src/trace/Kconfig index 2e7cdfc2f1e6..f26aabf5cc73 100644 --- a/src/trace/Kconfig +++ b/src/trace/Kconfig @@ -35,14 +35,14 @@ config TRACEM config TRACE_FILTERING bool "Trace filtering" depends on TRACE - default y + default n help Filtering of trace messages based on their verbosity level and frequency. config TRACE_FILTERING_VERBOSITY bool "Filter by verbosity" depends on TRACE_FILTERING - default y + default n help Filtering by log verbosity level, where maximum verbosity allowed is specified for each context and may be adjusted in runtime. @@ -50,7 +50,7 @@ config TRACE_FILTERING_VERBOSITY config TRACE_FILTERING_ADAPTIVE bool "Adaptive rate limiting" depends on TRACE_FILTERING - default y + default n help Adaptive filtering of trace messages, tracking up to CONFIG_TRACE_RECENT_ENTRIES_COUNT, suppressing all repeated messages for up to CONFIG_TRACE_RECENT_TIME_THRESHOLD cycles. From 7f3f8f1590f858b4bf5649939ca0aa26f6987d2a Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 21 Sep 2021 17:35:08 -0700 Subject: [PATCH 2/4] DMA: add reset op Add a new reset op in struct dma_ops that can be used to perform actions after the DMA is stopped during host_reset() and dai_reset(). Signed-off-by: Ranjani Sridharan --- src/audio/dai.c | 9 +++++++++ src/audio/host.c | 7 +++++++ src/include/sof/lib/dma.h | 9 +++++++++ 3 files changed, 25 insertions(+) diff --git a/src/audio/dai.c b/src/audio/dai.c index bc437939b36e..77c3c880c19f 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -683,9 +683,18 @@ static int dai_reset(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); struct dma_sg_config *config = &dd->config; + int ret; comp_info(dev, "dai_reset()"); + if (dd->chan) { + ret = dma_reset(dd->chan); + if (ret < 0) { + comp_err(dev, "dai_reset(): failed to reset DMA chan"); + return ret; + } + } + dai_config_reset(dev); dma_sg_free(&config->elem_array); diff --git a/src/audio/host.c b/src/audio/host.c index 69479d150469..bd1b45771500 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -855,6 +855,13 @@ static int host_reset(struct comp_dev *dev) comp_dbg(dev, "host_reset()"); if (hd->chan) { + int ret = dma_reset(hd->chan); + + if (ret < 0) { + comp_err(dev, "host_reset(): failed to reset DMA chan"); + return ret; + } + /* remove callback */ notifier_unregister(dev, hd->chan, NOTIFIER_ID_DMA_COPY); dma_channel_put(hd->chan); diff --git a/src/include/sof/lib/dma.h b/src/include/sof/lib/dma.h index 43726b52441c..8b08317a1c0e 100644 --- a/src/include/sof/lib/dma.h +++ b/src/include/sof/lib/dma.h @@ -160,6 +160,7 @@ struct dma_ops { int (*start)(struct dma_chan_data *channel); int (*stop)(struct dma_chan_data *channel); + int (*reset)(struct dma_chan_data *channel); int (*copy)(struct dma_chan_data *channel, int bytes, uint32_t flags); int (*pause)(struct dma_chan_data *channel); int (*release)(struct dma_chan_data *channel); @@ -318,6 +319,14 @@ static inline int dma_stop(struct dma_chan_data *channel) return ret; } +static inline int dma_reset(struct dma_chan_data *channel) +{ + if (channel->dma->ops->reset) + return channel->dma->ops->reset(channel); + + return 0; +} + /** \defgroup sof_dma_copy_func static int dma_copy (struct dma_chan_data * channel, int bytes, uint32_t flags) * * This function is in a separate subgroup to solve a name clash with From 5f5ff42d64d1ccfcdb5e55e22bea0ef4251cbcbe Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 21 Sep 2021 17:38:09 -0700 Subject: [PATCH 3/4] drivers: Intel: hda-dma: Implement reset op Implement the reset op for HDA DMA. The recommended HW programming sequence for HDA DMA calls for keeping the DGCS_GEN bit set to 1 when the host DMA is stopped by the host. It should be cleared during the reset op and after resetting, the GBUSY bit must be verfied to ensure that the DMA is idle. Also, because we do not clear the GEN bit until dma_reset, skip checking for the status during start to avoid issues with restarting the DMA during pause release. Signed-off-by: Ranjani Sridharan --- src/drivers/intel/hda/hda-dma.c | 36 ++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/drivers/intel/hda/hda-dma.c b/src/drivers/intel/hda/hda-dma.c index 8d3e56b40bb6..591d528a3e69 100644 --- a/src/drivers/intel/hda/hda-dma.c +++ b/src/drivers/intel/hda/hda-dma.c @@ -50,6 +50,7 @@ DECLARE_TR_CTX(hdma_tr, SOF_UUID(hda_dma_uuid), LOG_LEVEL_INFO); #define DGCS_SCS BIT(31) #define DGCS_GEN BIT(26) #define DGCS_FWCB BIT(23) +#define DGCS_GBUSY BIT(15) #define DGCS_BSC BIT(11) /* NOTE: both XRUN bits are the same, just direction is different */ #define DGCS_BOR BIT(10) /* buffer overrun (input streams) */ @@ -522,7 +523,6 @@ static void hda_dma_channel_put(struct dma_chan_data *channel) static int hda_dma_start(struct dma_chan_data *channel) { uint32_t flags; - uint32_t dgcs; int ret = 0; irq_local_disable(flags); @@ -532,13 +532,12 @@ static int hda_dma_start(struct dma_chan_data *channel) hda_dma_dbg_count_reset(channel); - /* is channel idle, disabled and ready ? */ - dgcs = dma_chan_reg_read(channel, DGCS); - if (channel->status != COMP_STATE_PREPARE || (dgcs & DGCS_GEN)) { + /* is channel active? */ + if (channel->status != COMP_STATE_PREPARE) { ret = -EBUSY; - tr_err(&hdma_tr, "hda-dmac: %d channel %d busy. dgcs 0x%x status %d", + tr_err(&hdma_tr, "hda-dmac: %d channel %d status %d", channel->dma->plat_data.id, - channel->index, dgcs, channel->status); + channel->index, channel->status); goto out; } @@ -618,7 +617,7 @@ static int hda_dma_stop(struct dma_chan_data *channel) hda_dma_host_stop(channel); /* disable the channel */ - dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN | DGCS_FIFORDY, 0); + dma_chan_reg_update_bits(channel, DGCS, DGCS_FIFORDY, 0); channel->status = COMP_STATE_PREPARE; hda_chan = dma_chan_get_data(channel); hda_chan->state = 0; @@ -630,6 +629,28 @@ static int hda_dma_stop(struct dma_chan_data *channel) return 0; } +static int hda_dma_reset(struct dma_chan_data *channel) +{ + uint32_t val, flags; + + irq_local_disable(flags); + + /* reset GEN bit */ + dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN, 0); + + val = dma_chan_reg_read(channel, DGCS); + + irq_local_enable(flags); + + /* and verify if channel is idle */ + if (!(val & DGCS_GBUSY)) + return 0; + + tr_err(&hdma_tr, "hda-dmac: %d channel %d busy", channel->dma->plat_data.id, + channel->index); + return -EBUSY; +} + /* fill in "status" with current DMA channel state and position */ static int hda_dma_status(struct dma_chan_data *channel, struct dma_chan_status *status, uint8_t direction) @@ -1004,6 +1025,7 @@ const struct dma_ops hda_link_dma_ops = { .channel_put = hda_dma_channel_put, .start = hda_dma_start, .stop = hda_dma_stop, + .reset = hda_dma_reset, .copy = hda_dma_link_copy, .pause = hda_dma_pause, .release = hda_dma_release, From 88795bdb789d60c06af0851bca92148736ffd6bd Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 21 Sep 2021 17:41:19 -0700 Subject: [PATCH 4/4] trace: disable trace during CTX_SAVE IPC Trace DMA needs to be reset after it has been stopped. Since there is no IPC for freeing trace, use the CTX_SAVE IPC to ensure that the trace DMA is reset and freed during suspend. Signed-off-by: Ranjani Sridharan --- src/include/sof/trace/dma-trace.h | 1 + src/ipc/ipc3/handler.c | 5 +++++ src/trace/dma-trace.c | 7 +++++++ 3 files changed, 13 insertions(+) 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..d7e3d0a3d28d 100644 --- a/src/ipc/ipc3/handler.c +++ b/src/ipc/ipc3/handler.c @@ -602,6 +602,11 @@ static int ipc_pm_context_save(uint32_t header) //struct sof_ipc_pm_ctx *pm_ctx = _ipc->comp_data; tr_info(&ipc_tr, "ipc: pm -> save"); +#if CONFIG_TRACE + struct dma_trace_data *dmat = dma_trace_data_get(); + + dma_trace_disable(dmat); +#endif sa_exit(sof_get()); diff --git a/src/trace/dma-trace.c b/src/trace/dma-trace.c index e757c1a94fae..f5c77f1deb3a 100644 --- a/src/trace/dma-trace.c +++ b/src/trace/dma-trace.c @@ -420,6 +420,13 @@ int dma_trace_enable(struct dma_trace_data *d) return err; } +void dma_trace_disable(struct dma_trace_data *d) +{ + schedule_task_cancel(&d->dmat_work); + dma_reset(d->dc.chan); + dma_trace_buffer_free(d); +} + /** Sends all pending DMA messages to mailbox (for emergencies) */ void dma_trace_flush(void *t) {