Skip to content

Commit 5b215c2

Browse files
Tomasz Mońvinodkoul
authored andcommitted
dmaengine: imx-sdma: restart cyclic channel if needed
Under heavy load resulting in high interrupt latencies, it is possible for imx UART requests to completely fill DMA buffer. When DMA channel is triggered and no SDMA owned buffer is available, SDMA stops. Thanks to the autoRTS feature, there is no data loss due to the SDMA stop if the UART is using hardware flow control. According to DMA Engine API Guide, DMA cyclic operation is performed until explicitly stopped. Restart the buffer after handling channel loop if the channel was stopped by SDMA. Signed-off-by: Tomasz Moń <tomasz.mon@camlingroup.com> Link: https://lore.kernel.org/r/20220117091955.1038937-1-tomasz.mon@camlingroup.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 4ae7094 commit 5b215c2

1 file changed

Lines changed: 14 additions & 0 deletions

File tree

drivers/dma/imx-sdma.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,11 @@ static int sdma_config_ownership(struct sdma_channel *sdmac,
701701
return 0;
702702
}
703703

704+
static int is_sdma_channel_enabled(struct sdma_engine *sdma, int channel)
705+
{
706+
return !!(readl(sdma->regs + SDMA_H_STATSTOP) & BIT(channel));
707+
}
708+
704709
static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
705710
{
706711
writel(BIT(channel), sdma->regs + SDMA_H_START);
@@ -860,6 +865,15 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
860865
if (error)
861866
sdmac->status = old_status;
862867
}
868+
869+
/*
870+
* SDMA stops cyclic channel when DMA request triggers a channel and no SDMA
871+
* owned buffer is available (i.e. BD_DONE was set too late).
872+
*/
873+
if (!is_sdma_channel_enabled(sdmac->sdma, sdmac->channel)) {
874+
dev_warn(sdmac->sdma->dev, "restart cyclic channel %d\n", sdmac->channel);
875+
sdma_enable_channel(sdmac->sdma, sdmac->channel);
876+
}
863877
}
864878

865879
static void mxc_sdma_handle_channel_normal(struct sdma_channel *data)

0 commit comments

Comments
 (0)