Skip to content

Commit a2054ae

Browse files
committed
dai: fix error handling when DMA is stuck
When the DMA is stuck, e.g. in slave mode when the external clock is not active, the Linux kernel will trigger a stop after a timeout. Since the DMA will never complete, the current code returns an IPC error on stop (DMA completion fails) and will not reset DMA channel status and reference counts. Force the DMA and DAI to be stopped to solve the problem. We probably need to look at all error handling since it's likely to be a recurring issue. Also simplify the Xrun code, no need for an extra return. Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
1 parent b480595 commit a2054ae

1 file changed

Lines changed: 7 additions & 2 deletions

File tree

src/audio/dai.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,7 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd)
552552

553553
switch (cmd) {
554554
case COMP_TRIGGER_START:
555+
trace_dai("tsa");
555556
if (!dd->pointer_init)
556557
dai_pointer_init(dev);
557558
/* only start the DAI if we are not XRUN handling */
@@ -595,15 +596,15 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd)
595596
platform_dai_wallclock(dev, &dd->wallclock);
596597
break;
597598
case COMP_TRIGGER_XRUN:
599+
trace_dai("txr");
598600
dd->xrun = 1;
599601
/* stop the DAI unconditionally */
600602
dai_trigger(dd->dai, COMP_TRIGGER_STOP, dev->params.direction);
601603
ret = dma_stop(dd->dma, dd->chan);
602-
if (ret < 0)
603-
return ret;
604604
break;
605605
case COMP_TRIGGER_PAUSE:
606606
case COMP_TRIGGER_STOP:
607+
trace_dai("tsp");
607608
wait_init(&dd->complete);
608609

609610
/* wait for DMA to complete */
@@ -612,6 +613,10 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd)
612613
if (ret < 0) {
613614
trace_dai_error("ed0");
614615
trace_error_value(cmd);
616+
/* forced stop of DMA+DAI to avoid refcount issues */
617+
dai_trigger(dd->dai, COMP_TRIGGER_STOP,
618+
dev->params.direction);
619+
ret = dma_stop(dd->dma, dd->chan);
615620
}
616621
break;
617622
default:

0 commit comments

Comments
 (0)