DMA clients (ethernet driver) can use this interface to pass get/set coalesce information. Signed-off-by: Sarath Babu Naidu Gaddam <sarath.babu.naidu.gaddam@xxxxxxx> --- At present device_config support to program coalesce is only for AXIDMA and once the RFC is accepted it will extended to other IP variants. Changes in V3: - New patch. --- drivers/dma/xilinx/xilinx_dma.c | 37 ++++++++++++++++++++++++++++++++- include/linux/dma/xilinx_dma.h | 16 ++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index bd8f09837141..0a994c5f3ae0 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -414,6 +414,7 @@ struct xilinx_dma_tx_descriptor { * @tdest: TDEST value for mcdma * @has_vflip: S2MM vertical flip * @irq_delay: Interrupt delay timeout + * @has_static_coalesce: Used to check static/dynamic coalesce selection */ struct xilinx_dma_chan { struct xilinx_dma_device *xdev; @@ -453,6 +454,7 @@ struct xilinx_dma_chan { u16 tdest; bool has_vflip; u8 irq_delay; + u8 has_static_coalesce; }; /** @@ -1555,7 +1557,7 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR); - if (chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) { + if (!(chan->has_static_coalesce) && chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) { reg &= ~XILINX_DMA_CR_COALESCE_MAX; reg |= chan->desc_pendingcount << XILINX_DMA_CR_COALESCE_SHIFT; @@ -1696,6 +1698,39 @@ static void xilinx_dma_issue_pending(struct dma_chan *dchan) static int xilinx_dma_device_config(struct dma_chan *dchan, struct dma_slave_config *config) { + struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); + u32 regval; + + if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) { + struct xilinx_peri_config *pconfig = config->peripheral_config; + + if (!pconfig || config->peripheral_size != sizeof(*pconfig)) + return -EINVAL; + + switch (pconfig->cmd) { + case XILINX_DMA_GET_COALESCE: + regval = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR); + regval &= XILINX_DMA_CR_COALESCE_MAX; + *((int *)pconfig->data) = regval >> XILINX_DMA_CR_COALESCE_SHIFT; + + break; + case XILINX_DMA_SET_COALESCE: + if ((*(int *)pconfig->data) <= XILINX_DMA_COALESCE_MAX) { + regval = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR); + regval &= ~XILINX_DMA_CR_COALESCE_MAX; + regval |= ((*(int *)pconfig->data) << + XILINX_DMA_CR_COALESCE_SHIFT); + + dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, regval); + chan->has_static_coalesce = 1; + } + + break; + default: + return -EINVAL; + } + } + return 0; } diff --git a/include/linux/dma/xilinx_dma.h b/include/linux/dma/xilinx_dma.h index 0dde1a46ab75..ce0267baf5eb 100644 --- a/include/linux/dma/xilinx_dma.h +++ b/include/linux/dma/xilinx_dma.h @@ -41,5 +41,21 @@ struct xilinx_vdma_config { int xilinx_vdma_channel_set_config(struct dma_chan *dchan, struct xilinx_vdma_config *cfg); +/** + * struct xilinx_peri_config -Configuration structure for user + * configurable commands and associated data. + *cmd: cmd for passing any slave info. Example: ethtool get/set coalesce + *data: data for cmd argument + */ +struct xilinx_peri_config { + int cmd; + void *data; +}; + +/** + * XILINX_DMA_GET/SET COALSCE -setting IP coalesce parameters + */ +#define XILINX_DMA_GET_COALESCE 1 +#define XILINX_DMA_SET_COALESCE 2 #endif -- 2.25.1