[RFC V3 PATCH 8/8] dmaengine: xilinx_dma: Add device_config support

Sarath Babu Naidu Gaddam sarath.babu.naidu.gaddam at amd.com
Mon Sep 19 22:51:19 PDT 2022


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 at amd.com>
---
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




More information about the linux-arm-kernel mailing list