MLK-17285 dma: imx-sdma: fix sound mute in high loading
authorRobin Gong <yibin.gong@nxp.com>
Tue, 2 Jan 2018 08:32:26 +0000 (16:32 +0800)
committerJosep Orga <jorga@somdevices.com>
Tue, 27 Jun 2023 14:03:03 +0000 (16:03 +0200)
SDMA channel will stop in case of cpu high loading. That caused by
sdma ISR can't be handled in time while all cyclic bds consumed by
sdma side, then sdma channel stopped. Re-enable channel in this case
to workaound the issue.

Signed-off-by: Robin Gong <yibin.gong@nxp.com>
Reviewed-by: Shengjiu Wang <shengjiu.wang@nxp.com>
(cherry picked from commit 98c43d24d19d28ae364e7fedf48d61e98a2ec9e4)
(cherry picked from commit 65f426ddd092175602993cf4494e75f84f50b58a)

drivers/dma/imx-sdma.c

index 31fee48..0ebf0e1 100644 (file)
@@ -943,6 +943,7 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
        struct sdma_buffer_descriptor *bd;
        int error = 0;
        enum dma_status old_status = sdmac->status;
+       int count = 0;
 
        /*
         * loop mode. Iterate over descriptors, re-setup them and
@@ -953,6 +954,17 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
 
                bd = &desc->bd[desc->buf_tail];
 
+               /*
+                * re-enable HSTART_HE if all bds consumed at the last time,
+                * that happens in high loading case which sdma_handle_channel_
+                * loop can't be handled in time while all bds run out in sdma
+                * side, then sdma script clear HE and cause channel stop.
+                */
+               if (count == desc->num_bd) {
+                       dev_warn(sdmac->sdma->dev, "All bds consumed,restart now.\n");
+                       sdma_enable_channel(sdmac->sdma, sdmac->channel);
+               }
+
                if (bd->mode.status & BD_DONE)
                        break;
 
@@ -978,6 +990,7 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
                bd->mode.count = desc->period_len;
                desc->buf_ptail = desc->buf_tail;
                desc->buf_tail = (desc->buf_tail + 1) % desc->num_bd;
+               count++;
 
                /*
                 * The callback is called from the interrupt context in order