Merge tag 'zonefs-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal...
[sfrench/cifs-2.6.git] / drivers / dma / dw-edma / dw-edma-v0-core.c
index b38786f0ad7995d9b0d22aa18fdd6d2407320c26..b75fdaffad9a4ea6cd8d15e8f43bea550848b46c 100644 (file)
@@ -346,6 +346,20 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
        dw_edma_v0_write_ll_link(chunk, i, control, chunk->ll_region.paddr);
 }
 
+static void dw_edma_v0_sync_ll_data(struct dw_edma_chunk *chunk)
+{
+       /*
+        * In case of remote eDMA engine setup, the DW PCIe RP/EP internal
+        * configuration registers and application memory are normally accessed
+        * over different buses. Ensure LL-data reaches the memory before the
+        * doorbell register is toggled by issuing the dummy-read from the remote
+        * LL memory in a hope that the MRd TLP will return only after the
+        * last MWr TLP is completed
+        */
+       if (!(chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
+               readl(chunk->ll_region.vaddr.io);
+}
+
 static void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
 {
        struct dw_edma_chan *chan = chunk->chan;
@@ -412,6 +426,9 @@ static void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
                SET_CH_32(dw, chan->dir, chan->id, llp.msb,
                          upper_32_bits(chunk->ll_region.paddr));
        }
+
+       dw_edma_v0_sync_ll_data(chunk);
+
        /* Doorbell */
        SET_RW_32(dw, chan->dir, doorbell,
                  FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id));