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
