Re: [PATCH v2] dmaengine: dw-edma: Fix multiple times setting of the CYCLE_STATE and CYCLE_BIT bits for HDMA.

From: Frank Li

Date: Thu Mar 05 2026 - 11:24:53 EST


On Wed, Mar 04, 2026 at 02:45:09PM +0800, LUO Haowen wrote:
> Others have submitted this issue (https://lore.kernel.org/dmaengine/
> 20240722030405.3385-1-zhengdongxiong@xxxxxxxxxx/),
> but it has not been fixed yet. Therefore, more supplementary information
> is provided here.
>
> As mentioned in the "PCS-CCS-CB-TCB" Producer-Consumer Synchronization of
> "DesignWare Cores PCI Express Controller Databook, version 6.00a":
>
> 1. The Consumer CYCLE_STATE (CCS) bit in the register only needs to be
> initialized once; the value will update automatically to be
> ~CYCLE_BIT (CB) in the next chunk.
> 2. The Consumer CYCLE_BIT bit in the register is loaded from the LL
> element and tested against CCS. When CB = CCS, the data transfer is
> executed. Otherwise not.
>
> The current logic sets customer (HDMA) CS and CB bits to 1 in each chunk
> while setting the producer (software) CB of odd chunks to 0 and even
> chunks to 1 in the linked list. This is leading to a mismatch between
> the producer CB and consumer CS bits.
>
> This issue can be reproduced by setting the transmission data size to
> exceed one chunk. By the way, in the EDMA using the same "PCS-CCS-CB-TCB"
> mechanism, the CS bit is only initialized once and this issue was not
> found. Refer to
> drivers/dma/dw-edma/dw-edma-v0-core.c:dw_edma_v0_core_start.
>
> So fix this issue by initializing the CYCLE_STATE and CYCLE_BIT bits
> only once.
>
> Fixes: e74c39573d35 ("dmaengine: dw-edma: Add support for native HDMA")
> Signed-off-by: LUO Haowen <luo-hw@xxxxxxxxxxx>
> ---

Reviewed-by: Frank Li <Frank.Li@xxxxxxx>
> v2:
> - Add Fixes tag as suggested by maintainer
>
> drivers/dma/dw-edma/dw-hdma-v0-core.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c
> index e3f8db4fe..ce8f7254b 100644
> --- a/drivers/dma/dw-edma/dw-hdma-v0-core.c
> +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c
> @@ -252,10 +252,10 @@ static void dw_hdma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> lower_32_bits(chunk->ll_region.paddr));
> SET_CH_32(dw, chan->dir, chan->id, llp.msb,
> upper_32_bits(chunk->ll_region.paddr));
> + /* Set consumer cycle */
> + SET_CH_32(dw, chan->dir, chan->id, cycle_sync,
> + HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT);
> }
> - /* Set consumer cycle */
> - SET_CH_32(dw, chan->dir, chan->id, cycle_sync,
> - HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT);
>
> dw_hdma_v0_sync_ll_data(chunk);
>
> --
> 2.34.1
>