The control field in a DMA link list entry must be updated as the final
step because it includes the CB bit, which indicates whether the entry is
ready. Add dma_wmb() to ensure the correct memory write ordering.

Currently the driver does not update DMA link entries while the DMA is
running, so no visible failure occurs. However, fixing the ordering now
prepares the driver for supporting link entry updates during DMA operation.

Signed-off-by: Frank Li <[email protected]>
---
 drivers/dma/dw-edma/dw-edma-v0-core.c | 10 ++++++----
 drivers/dma/dw-edma/dw-hdma-v0-core.c | 10 ++++++----
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c 
b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 
2850a9df80f54d00789144415ed2dfe31dea3965..1b0add95ed655d8d16d381c8294acb252b7bcd2d
 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -284,17 +284,18 @@ static void dw_edma_v0_write_ll_data(struct dw_edma_chunk 
*chunk, int i,
        if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
                struct dw_edma_v0_lli *lli = chunk->ll_region.vaddr.mem + ofs;
 
-               lli->control = control;
                lli->transfer_size = size;
                lli->sar.reg = sar;
                lli->dar.reg = dar;
+               dma_wmb();
+               lli->control = control;
        } else {
                struct dw_edma_v0_lli __iomem *lli = chunk->ll_region.vaddr.io 
+ ofs;
 
-               writel(control, &lli->control);
                writel(size, &lli->transfer_size);
                writeq(sar, &lli->sar.reg);
                writeq(dar, &lli->dar.reg);
+               writel(control, &lli->control);
        }
 }
 
@@ -306,13 +307,14 @@ static void dw_edma_v0_write_ll_link(struct dw_edma_chunk 
*chunk,
        if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
                struct dw_edma_v0_llp *llp = chunk->ll_region.vaddr.mem + ofs;
 
-               llp->control = control;
                llp->llp.reg = pointer;
+               dma_wmb();
+               llp->control = control;
        } else {
                struct dw_edma_v0_llp __iomem *llp = chunk->ll_region.vaddr.io 
+ ofs;
 
-               writel(control, &llp->control);
                writeq(pointer, &llp->llp.reg);
+               writel(control, &llp->control);
        }
 }
 
diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c 
b/drivers/dma/dw-edma/dw-hdma-v0-core.c
index 
e3f8db4fe909a1776bb5899e0b4c9c7a9d178c05..f1fc1060d3f77e3b12dea48efa72c5b3a0a58c8b
 100644
--- a/drivers/dma/dw-edma/dw-hdma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c
@@ -160,17 +160,18 @@ static void dw_hdma_v0_write_ll_data(struct dw_edma_chunk 
*chunk, int i,
        if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
                struct dw_hdma_v0_lli *lli = chunk->ll_region.vaddr.mem + ofs;
 
-               lli->control = control;
                lli->transfer_size = size;
                lli->sar.reg = sar;
                lli->dar.reg = dar;
+               dma_wmb();
+               lli->control = control;
        } else {
                struct dw_hdma_v0_lli __iomem *lli = chunk->ll_region.vaddr.io 
+ ofs;
 
-               writel(control, &lli->control);
                writel(size, &lli->transfer_size);
                writeq(sar, &lli->sar.reg);
                writeq(dar, &lli->dar.reg);
+               writel(control, &lli->control);
        }
 }
 
@@ -182,13 +183,14 @@ static void dw_hdma_v0_write_ll_link(struct dw_edma_chunk 
*chunk,
        if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
                struct dw_hdma_v0_llp *llp = chunk->ll_region.vaddr.mem + ofs;
 
-               llp->control = control;
                llp->llp.reg = pointer;
+               dma_wmb();
+               llp->control = control;
        } else {
                struct dw_hdma_v0_llp __iomem *llp = chunk->ll_region.vaddr.io 
+ ofs;
 
-               writel(control, &llp->control);
                writeq(pointer, &llp->llp.reg);
+               writel(control, &llp->control);
        }
 }
 

-- 
2.34.1


Reply via email to