[PATCH] serial: imx-serial - move DMA buffer configuration to DT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Nandor Han <nandor.han@xxxxxx>

The size of the DMA buffer can affect the delta time between data being
produced and data being consumed. Basically the DMA system will move
data to tty buffer when a) DMA buffer is full b) serial line is idle.
The situation is visible when producer generates data continuously and
there is no possibility for idle line. At this point the DMA buffer is
directly affecting the delta time.

The patch will add the possibility to configure the DMA buffers in DT,
which case by case can be configured separately for every driver
instance. The DT configuration is optional and in case missing the
driver will use the 4096 buffer with 4 periods (as before), therefore no
clients are impacted by this change.

Signed-off-by: Nandor Han <nandor.han@xxxxxx>
Signed-off-by: Romain Perier <romain.perier@xxxxxxxxxxxxx>
---
 .../devicetree/bindings/serial/fsl-imx-uart.txt    |  2 ++
 drivers/tty/serial/imx.c                           | 25 +++++++++++++++-------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt
index 574c3a2..e6b5724 100644
--- a/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt
+++ b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt
@@ -9,6 +9,7 @@ Optional properties:
 - fsl,irda-mode : Indicate the uart supports irda mode
 - fsl,dte-mode : Indicate the uart works in DTE mode. The uart works
                   in DCE mode by default.
+- fsl,dma-size : Indicate the size of the DMA buffer and its periods
 
 Please check Documentation/devicetree/bindings/serial/serial.txt
 for the complete list of generic properties.
@@ -28,4 +29,5 @@ uart1: serial@73fbc000 {
 	interrupts = <31>;
 	uart-has-rtscts;
 	fsl,dte-mode;
+	fsl,dma-size = <1024 4>;
 };
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index bbefddd..7327477 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -186,6 +186,11 @@
 
 #define UART_NR 8
 
+/* RX DMA buffer periods */
+#define RX_DMA_PERIODS 4
+#define RX_BUF_SIZE	(PAGE_SIZE)
+
+
 /* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */
 enum imx_uart_type {
 	IMX1_UART,
@@ -224,6 +229,7 @@ struct imx_port {
 	struct dma_chan		*dma_chan_rx, *dma_chan_tx;
 	struct scatterlist	rx_sgl, tx_sgl[2];
 	void			*rx_buf;
+	unsigned int		rx_buf_size;
 	struct circ_buf		rx_ring;
 	unsigned int		rx_periods;
 	dma_cookie_t		rx_cookie;
@@ -964,8 +970,6 @@ static void imx_timeout(unsigned long data)
 	}
 }
 
-#define RX_BUF_SIZE	(PAGE_SIZE)
-
 /*
  * There are two kinds of RX DMA interrupts(such as in the MX6Q):
  *   [1] the RX DMA buffer is full.
@@ -1048,9 +1052,6 @@ static void dma_rx_callback(void *data)
 	}
 }
 
-/* RX DMA buffer periods */
-#define RX_DMA_PERIODS 4
-
 static int start_rx_dma(struct imx_port *sport)
 {
 	struct scatterlist *sgl = &sport->rx_sgl;
@@ -1061,9 +1062,8 @@ static int start_rx_dma(struct imx_port *sport)
 
 	sport->rx_ring.head = 0;
 	sport->rx_ring.tail = 0;
-	sport->rx_periods = RX_DMA_PERIODS;
 
-	sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
+	sg_init_one(sgl, sport->rx_buf, sport->rx_buf_size);
 	ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
 	if (ret == 0) {
 		dev_err(dev, "DMA mapping error for RX.\n");
@@ -1174,7 +1174,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
 		goto err;
 	}
 
-	sport->rx_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	sport->rx_buf = kzalloc(sport->rx_buf_size, GFP_KERNEL);
 	if (!sport->rx_buf) {
 		ret = -ENOMEM;
 		goto err;
@@ -2053,6 +2053,7 @@ static int serial_imx_probe_dt(struct imx_port *sport,
 {
 	struct device_node *np = pdev->dev.of_node;
 	int ret;
+	u32 dma_buf_size[2];
 
 	sport->devdata = of_device_get_match_data(&pdev->dev);
 	if (!sport->devdata)
@@ -2076,6 +2077,14 @@ static int serial_imx_probe_dt(struct imx_port *sport,
 	if (of_get_property(np, "rts-gpios", NULL))
 		sport->have_rtsgpio = 1;
 
+	if (!of_property_read_u32_array(np, "fsl,dma-size", dma_buf_size, 2)) {
+		sport->rx_buf_size = dma_buf_size[0] * dma_buf_size[1];
+		sport->rx_periods = dma_buf_size[1];
+	} else {
+		sport->rx_buf_size = RX_BUF_SIZE;
+		sport->rx_periods = RX_DMA_PERIODS;
+	}
+
 	return 0;
 }
 #else
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux