Add dw_edma_core_ll_cur_idx() to get completed DMA link entry position to
prepare support dymatic add DMA request during DMA running.

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

diff --git a/drivers/dma/dw-edma/dw-edma-core.h 
b/drivers/dma/dw-edma/dw-edma-core.h
index 
31039eb85079cbbd38a90d249091113ad646c6f9..d68c4592c6177e4fe2a2ae8a645bb065279ac45d
 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -123,6 +123,7 @@ struct dw_edma_core_ops {
        void (*ll_data)(struct dw_edma_chan *chan, struct dw_edma_burst *burst,
                        u32 idx, bool cb, bool irq);
        void (*ll_link)(struct dw_edma_chan *chan, u32 idx, bool cb, u64 addr);
+       int (*ll_cur_idx)(struct dw_edma_chan *chan);
        void (*ch_doorbell)(struct dw_edma_chan *chan);
        void (*ch_enable)(struct dw_edma_chan *chan);
        void (*ch_config)(struct dw_edma_chan *chan);
@@ -164,6 +165,15 @@ struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan 
*dchan)
        return vc2dw_edma_chan(to_virt_chan(dchan));
 }
 
+/*
+ * Get current DMA running idx.
+ * < 0 means channel have not initialized or hardware reset by PCI link lost
+ */
+static inline int dw_edma_core_ll_cur_idx(struct dw_edma_chan *chan)
+{
+       return chan->dw->core->ll_cur_idx(chan);
+}
+
 static inline u64 dw_edma_core_get_ll_paddr(struct dw_edma_chan *chan)
 {
        if (chan->dir == EDMA_DIR_WRITE)
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c 
b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 
7b4591f984ad8b6f9909db16775368ff471db2b8..edc71a4dbc798386508e15f44e85c23e7e50f2ee
 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -504,6 +504,22 @@ static void dw_edma_v0_core_ch_doorbell(struct 
dw_edma_chan *chan)
                  FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id));
 }
 
+static int dw_edma_v0_core_ll_cur_idx(struct dw_edma_chan *chan)
+{
+       u64 paddr;
+       u32 val;
+
+       /* LL region never cross 4G memory boundary, so only check low 32bit */
+       val = GET_CH_32(chan->dw, chan->dir, chan->id, llp.lsb);
+       paddr = dw_edma_core_get_ll_paddr(chan);
+
+       /* DMA have not setup or DMA engine reset because PCIe link lost */
+       if (!val)
+               return -EINVAL;
+
+       return (val - (paddr & 0xFFFFFFFF)) / EDMA_LL_SZ;
+}
+
 /* eDMA debugfs callbacks */
 static void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
 {
@@ -517,6 +533,7 @@ static const struct dw_edma_core_ops dw_edma_v0_core = {
        .handle_int = dw_edma_v0_core_handle_int,
        .ll_data = dw_edma_v0_core_ll_data,
        .ll_link = dw_edma_v0_core_ll_link,
+       .ll_cur_idx = dw_edma_v0_core_ll_cur_idx,
        .ch_doorbell = dw_edma_v0_core_ch_doorbell,
        .ch_enable = dw_edma_v0_core_ch_enable,
        .ch_config = dw_edma_v0_core_ch_config,
diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c 
b/drivers/dma/dw-edma/dw-hdma-v0-core.c
index 
7f9fe3a6edd94583fd09c80a8d79527ed6383a8c..8e5bdcd208b5c2553ac45f744a4c678932ea5a03
 100644
--- a/drivers/dma/dw-edma/dw-hdma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c
@@ -285,6 +285,22 @@ static void dw_hdma_v0_core_ch_doorbell(struct 
dw_edma_chan *chan)
        SET_CH_32(dw, chan->dir, chan->id, doorbell, HDMA_V0_DOORBELL_START);
 }
 
+static int dw_hdma_v0_core_ll_cur_idx(struct dw_edma_chan *chan)
+{
+       u64 paddr;
+       u32 val;
+
+       /* LL region never cross 4G memory boundary, so only check low 32bit */
+       val = GET_CH_32(chan->dw, chan->dir, chan->id, llp.lsb);
+       paddr = dw_edma_core_get_ll_paddr(chan);
+
+       /* DMA have not setup or DMA engine reset because PCIe link lost */
+       if (!val)
+               return -EINVAL;
+
+       return (val - (paddr & 0xFFFFFFFF)) / EDMA_LL_SZ;
+}
+
 /* HDMA debugfs callbacks */
 static void dw_hdma_v0_core_debugfs_on(struct dw_edma *dw)
 {
@@ -298,6 +314,7 @@ static const struct dw_edma_core_ops dw_hdma_v0_core = {
        .handle_int = dw_hdma_v0_core_handle_int,
        .ll_data = dw_hdma_v0_core_ll_data,
        .ll_link = dw_hdma_v0_core_ll_link,
+       .ll_cur_idx = dw_hdma_v0_core_ll_cur_idx,
        .ch_doorbell = dw_hdma_v0_core_ch_doorbell,
        .ch_enable = dw_hdma_v0_core_ch_enable,
        .ch_config = dw_hdma_v0_core_ch_config,

-- 
2.34.1


Reply via email to