Linux Serial subsystem development
 help / color / mirror / Atom feed
* [PATCH v3 6/7] serial: imx: set_mctrl(): correctly restore autoRTS state
From: Sergey Organov @ 2019-07-04 13:00 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Sascha Hauer, Sergey Organov, NXP Linux Team,
	Pengutronix Kernel Team, Uwe Kleine-König, linux-arm-kernel
In-Reply-To: <1562245229-709-1-git-send-email-sorganov@gmail.com>

imx_uart_set_mctrl() happened to set UCR2_CTSC bit whenever TIOCM_RTS
was set, no matter if RTS/CTS handshake is enabled or not. Now fixed by
turning handshake on only when CRTSCTS bit for the port is set.

Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Sergey Organov <sorganov@gmail.com>
---
 drivers/tty/serial/imx.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 5532887..582a3fd 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -970,10 +970,22 @@ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	if (!(port->rs485.flags & SER_RS485_ENABLED)) {
 		u32 ucr2;
 
+		/*
+		 * Turn off autoRTS if RTS is lowered and restore autoRTS
+		 * setting if RTS is raised.
+		 */
 		ucr2 = imx_uart_readl(sport, UCR2);
 		ucr2 &= ~(UCR2_CTS | UCR2_CTSC);
-		if (mctrl & TIOCM_RTS)
-			ucr2 |= UCR2_CTS | UCR2_CTSC;
+		if (mctrl & TIOCM_RTS) {
+			ucr2 |= UCR2_CTS;
+			/*
+			 * UCR2_IRTS is unset if and only if the port is
+			 * configured for CRTSCTS, so we use inverted UCR2_IRTS
+			 * to get the state to restore to.
+			 */
+			if (!(ucr2 & UCR2_IRTS))
+				ucr2 |= UCR2_CTSC;
+		}
 		imx_uart_writel(sport, ucr2, UCR2);
 	}
 
-- 
2.10.0.1.g57b01a3

^ permalink raw reply related

* [PATCH v3 5/7] serial: imx: set_termios(): do not enable autoRTS if RTS is unset
From: Sergey Organov @ 2019-07-04 13:00 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Sascha Hauer, Sergey Organov, NXP Linux Team,
	Pengutronix Kernel Team, Uwe Kleine-König, linux-arm-kernel
In-Reply-To: <1562245229-709-1-git-send-email-sorganov@gmail.com>

set_termios() shouldn't set UCR2_CTSC bit if UCR2_CTS (=TIOCM_RTS) is
cleared. Added corresponding check in imx_uart_rts_auto() to fix this.

Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Sergey Organov <sorganov@gmail.com>
---
 drivers/tty/serial/imx.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index e0f5365..5532887 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -405,7 +405,8 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
 /* called with port.lock taken and irqs caller dependent */
 static void imx_uart_rts_auto(struct imx_port *sport, u32 *ucr2)
 {
-	*ucr2 |= UCR2_CTSC;
+	if (*ucr2 & UCR2_CTS)
+		*ucr2 |= UCR2_CTSC;
 }
 
 /* called with port.lock taken and irqs off */
@@ -1588,8 +1589,9 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 		else
 			imx_uart_rts_inactive(sport, &ucr2);
 
-	} else if (termios->c_cflag & CRTSCTS)
+	} else if (termios->c_cflag & CRTSCTS) {
 		imx_uart_rts_auto(sport, &ucr2);
+	}
 
 	if (termios->c_cflag & CRTSCTS)
 		ucr2 &= ~UCR2_IRTS;
-- 
2.10.0.1.g57b01a3

^ permalink raw reply related

* [PATCH v3 4/7] serial: imx: set_termios(): preserve RTS state
From: Sergey Organov @ 2019-07-04 13:00 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Sascha Hauer, Sergey Organov, NXP Linux Team,
	Pengutronix Kernel Team, Uwe Kleine-König, linux-arm-kernel
In-Reply-To: <1562245229-709-1-git-send-email-sorganov@gmail.com>

imx_set_termios() cleared RTS on every call, now fixed.

Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Sergey Organov <sorganov@gmail.com>
---
 drivers/tty/serial/imx.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 17e2322..e0f5365 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1563,7 +1563,14 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
-	ucr2 = UCR2_SRST | UCR2_IRTS;
+	/*
+	 * Read current UCR2 and save it for future use, then clear all the bits
+	 * except those we will or may need to preserve.
+	 */
+	old_ucr2 = imx_uart_readl(sport, UCR2);
+	ucr2 = old_ucr2 & (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN | UCR2_CTS);
+
+	ucr2 |= UCR2_SRST | UCR2_IRTS;
 	if ((termios->c_cflag & CSIZE) == CS8)
 		ucr2 |= UCR2_WS;
 
@@ -1632,7 +1639,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 	imx_uart_writel(sport,
 			old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
 			UCR1);
-	old_ucr2 = imx_uart_readl(sport, UCR2);
 	imx_uart_writel(sport, old_ucr2 & ~UCR2_ATEN, UCR2);
 
 	while (!(imx_uart_readl(sport, USR2) & USR2_TXDC))
@@ -1640,7 +1646,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	/* then, disable everything */
 	imx_uart_writel(sport, old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN | UCR2_ATEN), UCR2);
-	old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN);
 
 	/* custom-baudrate handling */
 	div = sport->port.uartclk / (baud * 16);
@@ -1678,8 +1683,7 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	imx_uart_writel(sport, old_ucr1, UCR1);
 
-	/* set the parity, stop bits and data size */
-	imx_uart_writel(sport, ucr2 | old_ucr2, UCR2);
+	imx_uart_writel(sport, ucr2, UCR2);
 
 	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
 		imx_uart_enable_ms(&sport->port);
-- 
2.10.0.1.g57b01a3

^ permalink raw reply related

* [PATCH v3 3/7] serial: imx: set_termios(): clarify RTS/CTS bits calculation
From: Sergey Organov @ 2019-07-04 13:00 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Sascha Hauer, Sergey Organov, NXP Linux Team,
	Pengutronix Kernel Team, Uwe Kleine-König, linux-arm-kernel
In-Reply-To: <1562245229-709-1-git-send-email-sorganov@gmail.com>

Avoid repeating the same code for rs485 twice.

Make it obvious we clear CRTSCTS bit in termios->c_cflag whenever
sport->have_rtscts is false.

Make it obvious we clear UCR2_IRTS whenever CRTSCTS is set.

Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Sergey Organov <sorganov@gmail.com>
---
 drivers/tty/serial/imx.c | 36 +++++++++++++-----------------------
 1 file changed, 13 insertions(+), 23 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 87802fd..17e2322 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1567,35 +1567,25 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 	if ((termios->c_cflag & CSIZE) == CS8)
 		ucr2 |= UCR2_WS;
 
-	if (termios->c_cflag & CRTSCTS) {
-		if (sport->have_rtscts) {
-			ucr2 &= ~UCR2_IRTS;
+	if (!sport->have_rtscts)
+		termios->c_cflag &= ~CRTSCTS;
 
-			if (port->rs485.flags & SER_RS485_ENABLED) {
-				/*
-				 * RTS is mandatory for rs485 operation, so keep
-				 * it under manual control and keep transmitter
-				 * disabled.
-				 */
-				if (port->rs485.flags &
-				    SER_RS485_RTS_AFTER_SEND)
-					imx_uart_rts_active(sport, &ucr2);
-				else
-					imx_uart_rts_inactive(sport, &ucr2);
-			} else {
-				imx_uart_rts_auto(sport, &ucr2);
-			}
-		} else {
-			termios->c_cflag &= ~CRTSCTS;
-		}
-	} else if (port->rs485.flags & SER_RS485_ENABLED) {
-		/* disable transmitter */
+	if (port->rs485.flags & SER_RS485_ENABLED) {
+		/*
+		 * RTS is mandatory for rs485 operation, so keep
+		 * it under manual control and keep transmitter
+		 * disabled.
+		 */
 		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
 			imx_uart_rts_active(sport, &ucr2);
 		else
 			imx_uart_rts_inactive(sport, &ucr2);
-	}
 
+	} else if (termios->c_cflag & CRTSCTS)
+		imx_uart_rts_auto(sport, &ucr2);
+
+	if (termios->c_cflag & CRTSCTS)
+		ucr2 &= ~UCR2_IRTS;
 
 	if (termios->c_cflag & CSTOPB)
 		ucr2 |= UCR2_STPB;
-- 
2.10.0.1.g57b01a3

^ permalink raw reply related

* [PATCH v3 2/7] serial: imx: set_termios(): factor-out 'ucr2' initial value
From: Sergey Organov @ 2019-07-04 13:00 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Sascha Hauer, Sergey Organov, NXP Linux Team,
	Pengutronix Kernel Team, Uwe Kleine-König, linux-arm-kernel
In-Reply-To: <1562245229-709-1-git-send-email-sorganov@gmail.com>

Set common bits in a separate statement to make initialization
explicit and not repeat the common part.

Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

Signed-off-by: Sergey Organov <sorganov@gmail.com>
---
 drivers/tty/serial/imx.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 1055124..87802fd 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1563,10 +1563,9 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
+	ucr2 = UCR2_SRST | UCR2_IRTS;
 	if ((termios->c_cflag & CSIZE) == CS8)
-		ucr2 = UCR2_WS | UCR2_SRST | UCR2_IRTS;
-	else
-		ucr2 = UCR2_SRST | UCR2_IRTS;
+		ucr2 |= UCR2_WS;
 
 	if (termios->c_cflag & CRTSCTS) {
 		if (sport->have_rtscts) {
-- 
2.10.0.1.g57b01a3


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v3 1/7] serial: imx: fix locking in set_termios()
From: Sergey Organov @ 2019-07-04 13:00 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Sascha Hauer, Sergey Organov, NXP Linux Team,
	Pengutronix Kernel Team, Uwe Kleine-König, linux-arm-kernel
In-Reply-To: <1562245229-709-1-git-send-email-sorganov@gmail.com>

imx_uart_set_termios() called imx_uart_rts_active(), or
imx_uart_rts_inactive() before taking port->port.lock.

As a consequence, sport->port.mctrl that these functions modify
could have been changed without holding port->port.lock.

Moved locking of port->port.lock above the calls to fix the issue.

Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

Signed-off-by: Sergey Organov <sorganov@gmail.com>
---
 drivers/tty/serial/imx.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index dff75dc..1055124 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -383,6 +383,7 @@ static void imx_uart_ucrs_restore(struct imx_port *sport,
 }
 #endif
 
+/* called with port.lock taken and irqs caller dependent */
 static void imx_uart_rts_active(struct imx_port *sport, u32 *ucr2)
 {
 	*ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
@@ -391,6 +392,7 @@ static void imx_uart_rts_active(struct imx_port *sport, u32 *ucr2)
 	mctrl_gpio_set(sport->gpios, sport->port.mctrl);
 }
 
+/* called with port.lock taken and irqs caller dependent */
 static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
 {
 	*ucr2 &= ~UCR2_CTSC;
@@ -400,6 +402,7 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
 	mctrl_gpio_set(sport->gpios, sport->port.mctrl);
 }
 
+/* called with port.lock taken and irqs caller dependent */
 static void imx_uart_rts_auto(struct imx_port *sport, u32 *ucr2)
 {
 	*ucr2 |= UCR2_CTSC;
@@ -1550,6 +1553,16 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 		old_csize = CS8;
 	}
 
+	del_timer_sync(&sport->timer);
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
+	quot = uart_get_divisor(port, baud);
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
 	if ((termios->c_cflag & CSIZE) == CS8)
 		ucr2 = UCR2_WS | UCR2_SRST | UCR2_IRTS;
 	else
@@ -1593,16 +1606,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 			ucr2 |= UCR2_PROE;
 	}
 
-	del_timer_sync(&sport->timer);
-
-	/*
-	 * Ask the core to calculate the divisor for us.
-	 */
-	baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
-	quot = uart_get_divisor(port, baud);
-
-	spin_lock_irqsave(&sport->port.lock, flags);
-
 	sport->port.read_status_mask = 0;
 	if (termios->c_iflag & INPCK)
 		sport->port.read_status_mask |= (URXD_FRMERR | URXD_PRERR);
-- 
2.10.0.1.g57b01a3


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v3 0/7] serial: imx: fix RTS and RTS/CTS handling
From: Sergey Organov @ 2019-07-04 13:00 UTC (permalink / raw)
  To: linux-serial
  Cc: Greg Kroah-Hartman, Sascha Hauer, Sergey Organov, NXP Linux Team,
	Pengutronix Kernel Team, Uwe Kleine-König, linux-arm-kernel
In-Reply-To: <20190614072801.3187-1-s.hauer@pengutronix.de>

RTS signal and RTS/CTS handshake handling had a few problems these
patches fix.

In addition, minor cleanups are made to the involved code.

Changelog:

  v3:

      * Appended: "Reviewed-by:"
        Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
        to the first 2 patches

      * Added braces to one-line 'else if', to the "serial: imx:
        set_termios(): clarify RTS/CTS bits calculation", as suggested
        by Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

      * Improved comments in "serial: imx: set_mctrl(): correctly
        restore autoRTS state", as suggested by Uwe Kleine-König
        <u.kleine-koenig@pengutronix.de>

  v2:

      * Appended: "Reviewed-by:" and "Tested-by:"
        Sascha Hauer <s.hauer@pengutronix.de>

      * Removed "RFC" from header

  v1:

      * Fixed in "serial: imx: set_termios(): preserve RTS state"

-+	ucr2 = UCR2_SRST | UCR2_IRTS;
++	ucr2 |= UCR2_SRST | UCR2_IRTS;

        as noticed by Lothar Waßmann <LW@KARO-electronics.de>

      * Fixed in "serial: imx: set_termios(): preserve RTS state"

-+	ucr2 = old_ucr2 & (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN | UCR2_CTSC);
++	ucr2 = old_ucr2 & (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN | UCR2_CTS);

        as the fix for the problem found by Sascha Hauer
        <s.hauer@pengutronix.de>

      * Reordered:

        serial: imx: set_termios(): preserve RTS state
        serial: imx: set_termios(): do not enable autoRTS if RTS is unset

        as the latter makes sense only provided the former is already applied.


Sergey Organov (7):
  serial: imx: fix locking in set_termios()
  serial: imx: set_termios(): factor-out 'ucr2' initial value
  serial: imx: set_termios(): clarify RTS/CTS bits calculation
  serial: imx: set_termios(): preserve RTS state
  serial: imx: set_termios(): do not enable autoRTS if RTS is unset
  serial: imx: set_mctrl(): correctly restore autoRTS state
  serial: imx: get rid of imx_uart_rts_auto()

 drivers/tty/serial/imx.c | 96 +++++++++++++++++++++++++-----------------------
 1 file changed, 50 insertions(+), 46 deletions(-)

--
2.10.0.1.g57b01a3

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 03/11] serial: sh-sci: use driver core functions, not sysfs ones.
From: Greg Kroah-Hartman @ 2019-07-04  8:46 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial
In-Reply-To: <20190704084617.3602-1-gregkh@linuxfoundation.org>

This is a driver, do not call "raw" sysfs functions, instead call driver
core ones.  Specifically convert the use of sysfs_create_file() and
sysfs_remove_file() to use device_create_file() and device_remove_file()

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-serial@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/tty/serial/sh-sci.c | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index abc705716aa0..69f9072505f7 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -3137,14 +3137,10 @@ static int sci_remove(struct platform_device *dev)
 
 	sci_cleanup_single(port);
 
-	if (port->port.fifosize > 1) {
-		sysfs_remove_file(&dev->dev.kobj,
-				  &dev_attr_rx_fifo_trigger.attr);
-	}
-	if (type == PORT_SCIFA || type == PORT_SCIFB || type == PORT_HSCIF) {
-		sysfs_remove_file(&dev->dev.kobj,
-				  &dev_attr_rx_fifo_timeout.attr);
-	}
+	if (port->port.fifosize > 1)
+		device_remove_file(&dev->dev, &dev_attr_rx_fifo_trigger);
+	if (type == PORT_SCIFA || type == PORT_SCIFB || type == PORT_HSCIF)
+		device_remove_file(&dev->dev, &dev_attr_rx_fifo_timeout);
 
 	return 0;
 }
@@ -3332,19 +3328,17 @@ static int sci_probe(struct platform_device *dev)
 		return ret;
 
 	if (sp->port.fifosize > 1) {
-		ret = sysfs_create_file(&dev->dev.kobj,
-				&dev_attr_rx_fifo_trigger.attr);
+		ret = device_create_file(&dev->dev, &dev_attr_rx_fifo_trigger);
 		if (ret)
 			return ret;
 	}
 	if (sp->port.type == PORT_SCIFA || sp->port.type == PORT_SCIFB ||
 	    sp->port.type == PORT_HSCIF) {
-		ret = sysfs_create_file(&dev->dev.kobj,
-				&dev_attr_rx_fifo_timeout.attr);
+		ret = device_create_file(&dev->dev, &dev_attr_rx_fifo_timeout);
 		if (ret) {
 			if (sp->port.fifosize > 1) {
-				sysfs_remove_file(&dev->dev.kobj,
-					&dev_attr_rx_fifo_trigger.attr);
+				device_remove_file(&dev->dev,
+						   &dev_attr_rx_fifo_trigger);
 			}
 			return ret;
 		}
-- 
2.22.0

^ permalink raw reply related

* [PATCH 00/11] Platform drivers, provide a way to add sysfs groups easily
From: Greg Kroah-Hartman @ 2019-07-04  8:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fbdev, Randy Dunlap, Rafael J. Wysocki, dri-devel,
	platform-driver-x86, Mans Rullgard, H. Peter Anvin, Romain Izard,
	Richard Gong, Florian Fainelli, x86, Bartosz Golaszewski,
	Ingo Molnar, linux-serial, Jiri Slaby, Darren Hart,
	Bartlomiej Zolnierkiewicz, linux-input, Borislav Petkov,
	Thomas Gleixner, Andy Shevchenko, linux-arm-kernel,
	Greg Kroah-Hartman, Dmitry Torokhov <dmitr>

If a platform driver wants to add a sysfs group, it has to do so in a
racy way, adding it after the driver is bound.  To resolve this issue,
have the platform driver core do this for the driver, making the
individual drivers logic smaller and simpler, and solving the race at
the same time.

All of these patches depend on the first patch.  I'll take the first one
through my driver-core tree, and any subsystem maintainer can either ack
their individul patch and I will be glad to also merge it, or they can
wait until after 5.3-rc1 when the core patch hits Linus's tree and then
take it, it's up to them.

Thank to Richard Gong for the idea and the testing of the platform
driver patch.

Greg Kroah-Hartman (11):
  Platform: add a dev_groups pointer to struct platform_driver
  uio: uio_fsl_elbc_gpcm: convert platform driver to use dev_groups
  serial: sh-sci: use driver core functions, not sysfs ones.
  firmware: arm_scpi: convert platform driver to use dev_groups
  olpc: x01: convert platform driver to use dev_groups
  platform: x86: hp-wmi: convert platform driver to use dev_groups
  video: fbdev: wm8505fb: convert platform driver to use dev_groups
  video: fbdev: w100fb: convert platform driver to use dev_groups
  video: fbdev: sm501fb: convert platform driver to use dev_groups
  input: keyboard: gpio_keys: convert platform driver to use dev_groups
  input: axp20x-pek: convert platform driver to use dev_groups

 arch/x86/platform/olpc/olpc-xo1-sci.c | 17 ++++------
 drivers/base/platform.c               | 40 +++++++++++++++--------
 drivers/firmware/arm_scpi.c           |  5 +--
 drivers/input/keyboard/gpio_keys.c    | 13 ++------
 drivers/input/misc/axp20x-pek.c       | 15 ++-------
 drivers/platform/x86/hp-wmi.c         | 47 +++++++--------------------
 drivers/tty/serial/sh-sci.c           | 22 +++++--------
 drivers/uio/uio_fsl_elbc_gpcm.c       | 23 +++++--------
 drivers/video/fbdev/sm501fb.c         | 37 +++++----------------
 drivers/video/fbdev/w100fb.c          | 23 ++++++-------
 drivers/video/fbdev/wm8505fb.c        | 13 ++++----
 include/linux/platform_device.h       |  1 +
 12 files changed, 94 insertions(+), 162 deletions(-)

-- 
2.22.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* RE: Re: Re: [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: Je Yen Tam @ 2019-07-04  8:20 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20190704081500.GA6438@kroah.com>



> -----Original Message-----
> From: Greg KH <gregkh@linuxfoundation.org>
> Sent: Thursday, July 4, 2019 4:15 PM
> To: Je Yen Tam <je.yen.tam@ni.com>
> Cc: linux-serial@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [EXTERNAL] Re: Re: [PATCH V2 1/2] serial/8250: Add support for NI-Serial
> PXI/PXIe+485 devices
> 
> On Thu, Jul 04, 2019 at 07:55:33AM +0000, Je Yen Tam wrote:
> > > On Wed, Jul 03, 2019 at 12:24:35AM -0700, jeyentam wrote:
> > > > Add support for NI-Serial PXIe-RS232, PXI-RS485 and PXIe-RS485 devices.
> > > >
> > > > Signed-off-by: jeyentam <je.yen.tam@ni.com>
> > >
> > > I need a "full" name here please.
> >
> > Ok, will do so.
> >
> > >
> > > Also, this patch breaks the build, which is not allowed, and makes me wonder
> how
> > > you tested it :(
> >
> > I've tested my changes with the steps as follows, it did not break.
> >
> > 1. Clone the Linux repo, check out the source and work on my project.
> > 2. Compile the kernel source with "make j4".
> > 3. Build the kernel modules with "make modules_install".
> > 4. Install the kernel with "make install".
> > 5. Reboot into the newly built kernel.
> > 6. The kernel worked well and able to fit my needs.
> >
> > Noted that my source is checked out from the latest Linux kernel 5.2.0-rc6.
> >
> > Also, I checked my patch using checkpatch.pl, it did not show any errors and
> > warnings too.
> >
> > May I know what do you mean by breaking the build?
> 
> If you only apply patch 1/2, the build breaks as you add new device ids
> in the second patch.  At every individual patch, you can not break the
> build.

Understood, will move the #defines into this file which needed it.

> 
> thanks,
> 
> greg k-h

^ permalink raw reply

* RE: Re: Re: [PATCH V2 2/2] PCI: Add NI-Serial PXI/PXIe+485 device IDs
From: Je Yen Tam @ 2019-07-04  8:17 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20190704081615.GB6438@kroah.com>

> -----Original Message-----
> From: Greg KH <gregkh@linuxfoundation.org>
> Sent: Thursday, July 4, 2019 4:16 PM
> To: Je Yen Tam <je.yen.tam@ni.com>
> Cc: linux-serial@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [EXTERNAL] Re: Re: [PATCH V2 2/2] PCI: Add NI-Serial PXI/PXIe+485 device
> IDs
> 
> On Thu, Jul 04, 2019 at 06:58:39AM +0000, Je Yen Tam wrote:
> > > On Wed, Jul 03, 2019 at 12:25:16AM -0700, jeyentam wrote:
> > > > Add NI PXIe-RS232, PXI-RS485 and PXIe-RS485 device IDs.
> > > >
> > > > Signed-off-by: jeyentam <je.yen.tam@ni.com>
> > > > ---
> > > >  include/linux/pci_ids.h | 12 ++++++++++++
> > > >  1 file changed, 12 insertions(+)
> > >
> > > You have read the comment at the top of this file, right?  If so, why
> > > are you adding these entries?
> >
> > Yes, but I think these entries should be added in because the NI-Serial PXI
> > (RS232) device IDs already been defined in this file originally, so now I'm
> > adding the newly supported NI-Serial PXI (RS485), PXIe (RS232) and PXIe
> > (RS485) device IDs into here as they are the same product.
> 
> No, do not add new device ids to this file, only put them in the single
> file that needs it.  This file is for device ids that are shared across
> multiple drivers/files.
> 
> You should not need to touch this file at all.

Ok, understood. Will do so.

> 
> thanks,
> 
> greg k-h

Thank you,
Je Yen

^ permalink raw reply

* Re: Re: [PATCH V2 2/2] PCI: Add NI-Serial PXI/PXIe+485 device IDs
From: Greg KH @ 2019-07-04  8:16 UTC (permalink / raw)
  To: Je Yen Tam; +Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <MN2PR04MB5920BB86A99B1ABF946B2373B7FA0@MN2PR04MB5920.namprd04.prod.outlook.com>

On Thu, Jul 04, 2019 at 06:58:39AM +0000, Je Yen Tam wrote:
> > On Wed, Jul 03, 2019 at 12:25:16AM -0700, jeyentam wrote:
> > > Add NI PXIe-RS232, PXI-RS485 and PXIe-RS485 device IDs.
> > >
> > > Signed-off-by: jeyentam <je.yen.tam@ni.com>
> > > ---
> > >  include/linux/pci_ids.h | 12 ++++++++++++
> > >  1 file changed, 12 insertions(+)
> > 
> > You have read the comment at the top of this file, right?  If so, why 
> > are you adding these entries?
> 
> Yes, but I think these entries should be added in because the NI-Serial PXI 
> (RS232) device IDs already been defined in this file originally, so now I'm 
> adding the newly supported NI-Serial PXI (RS485), PXIe (RS232) and PXIe 
> (RS485) device IDs into here as they are the same product.

No, do not add new device ids to this file, only put them in the single
file that needs it.  This file is for device ids that are shared across
multiple drivers/files.

You should not need to touch this file at all.

thanks,

greg k-h

^ permalink raw reply

* Re: Re: [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: Greg KH @ 2019-07-04  8:15 UTC (permalink / raw)
  To: Je Yen Tam; +Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <MN2PR04MB59207BEC9DBAB5E69656DD42B7FA0@MN2PR04MB5920.namprd04.prod.outlook.com>

On Thu, Jul 04, 2019 at 07:55:33AM +0000, Je Yen Tam wrote:
> > On Wed, Jul 03, 2019 at 12:24:35AM -0700, jeyentam wrote:
> > > Add support for NI-Serial PXIe-RS232, PXI-RS485 and PXIe-RS485 devices.
> > >
> > > Signed-off-by: jeyentam <je.yen.tam@ni.com>
> > 
> > I need a "full" name here please.
> 
> Ok, will do so.
> 
> > 
> > Also, this patch breaks the build, which is not allowed, and makes me wonder how
> > you tested it :(
> 
> I've tested my changes with the steps as follows, it did not break.
> 
> 1. Clone the Linux repo, check out the source and work on my project.
> 2. Compile the kernel source with "make j4".
> 3. Build the kernel modules with "make modules_install".
> 4. Install the kernel with "make install".
> 5. Reboot into the newly built kernel.
> 6. The kernel worked well and able to fit my needs.
> 
> Noted that my source is checked out from the latest Linux kernel 5.2.0-rc6.
> 
> Also, I checked my patch using checkpatch.pl, it did not show any errors and 
> warnings too.
> 
> May I know what do you mean by breaking the build?

If you only apply patch 1/2, the build breaks as you add new device ids
in the second patch.  At every individual patch, you can not break the
build.

thanks,

greg k-h

^ permalink raw reply

* RE: Re: [PATCH 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices.
From: Je Yen Tam @ 2019-07-04  8:12 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20190703172554.GA27719@kroah.com>

> On Mon, Jul 01, 2019 at 08:23:23PM -0700, jeyentam wrote:
> > Add support for NI-Serial PXIe-RS232, PXI-RS485 and PXIe-RS485 devices.
> >
> > Signed-off-by: jeyentam <je.yen.tam@ni.com>
> > ---
> >  drivers/tty/serial/8250/8250_pci.c | 879 +++++++++++++++++++----------
> >  1 file changed, 582 insertions(+), 297 deletions(-)
> >
> > diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
> > index df41397de478..0a711b895b33 100644
> > --- a/drivers/tty/serial/8250/8250_pci.c
> > +++ b/drivers/tty/serial/8250/8250_pci.c
> > @@ -1,10 +1,10 @@
> >  // SPDX-License-Identifier: GPL-2.0
> >  /*
> > - *  Probe module for 8250/16550-type PCI serial ports.
> > + *	Probe module for 8250/16550-type PCI serial ports.
> >   *
> > - *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
> > + *	Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
> >   *
> > - *  Copyright (C) 2001 Russell King, All Rights Reserved.
> > + *	Copyright (C) 2001 Russell King, All Rights Reserved.
> >   */
> 
> Why are you changing comments for no reason?

These changes are not intended, I believe the editor I used messed up the
spacing, will remove it and resubmit the patch.

^ permalink raw reply

* RE: Re: [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: Je Yen Tam @ 2019-07-04  7:55 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20190703084220.GD8996@kroah.com>

> On Wed, Jul 03, 2019 at 12:24:35AM -0700, jeyentam wrote:
> > Add support for NI-Serial PXIe-RS232, PXI-RS485 and PXIe-RS485 devices.
> >
> > Signed-off-by: jeyentam <je.yen.tam@ni.com>
> 
> I need a "full" name here please.

Ok, will do so.

> 
> Also, this patch breaks the build, which is not allowed, and makes me wonder how
> you tested it :(

I've tested my changes with the steps as follows, it did not break.

1. Clone the Linux repo, check out the source and work on my project.
2. Compile the kernel source with "make j4".
3. Build the kernel modules with "make modules_install".
4. Install the kernel with "make install".
5. Reboot into the newly built kernel.
6. The kernel worked well and able to fit my needs.

Noted that my source is checked out from the latest Linux kernel 5.2.0-rc6.

Also, I checked my patch using checkpatch.pl, it did not show any errors and 
warnings too.

May I know what do you mean by breaking the build?

> 
> Please fix up properly and resend.
> 
> Also, some comments below:
> 
> > ---
> >  drivers/tty/serial/8250/8250_pci.c | 293
> > ++++++++++++++++++++++++++++-
> >  1 file changed, 289 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/tty/serial/8250/8250_pci.c
> > b/drivers/tty/serial/8250/8250_pci.c
> > index df41397de478..ac8138adea9c 100644
> > --- a/drivers/tty/serial/8250/8250_pci.c
> > +++ b/drivers/tty/serial/8250/8250_pci.c
> > @@ -730,8 +730,16 @@ static int pci_ni8430_init(struct pci_dev *dev)
> > }
> >
> >  /* UART Port Control Register */
> > -#define NI8430_PORTCON	0x0f
> > -#define NI8430_PORTCON_TXVR_ENABLE	(1 << 3)
> 
> Why are you renaming these #defines?

NI8430 device is using standard 16550 UART chip so I standardize all the 16550 
UART related #defines to UART chip specific name rather than device specific.

> 
> > +#define NI16550_PCR_OFFSET	0x0f
> > +#define NI16550_PCR_RS422	0x00
> > +#define NI16550_PCR_ECHO_RS485	0x01
> > +#define NI16550_PCR_DTR_RS485	0x02
> > +#define NI16550_PCR_AUTO_RS485	0x03
> > +#define NI16550_PCR_WIRE_MODE_MASK	0x03
> > +#define NI16550_PCR_TXVR_ENABLE_BIT	(1 << 3)
> 
> BIT(3)?

Ok, will change to this style.

> 
> > +#define NI16550_PCR_RS485_TERMINATION_BIT	(1 << 6)
> 
> BIT(6)?

Also, will change this.

> 
> > +#define NI16550_ACR_DTR_AUTO_DTR	(0x2 << 3)
> > +#define NI16550_ACR_DTR_MANUAL_DTR	(0x0 << 3)
> >
> >  static int
> >  pci_ni8430_setup(struct serial_private *priv, @@ -753,14 +761,127 @@
> > pci_ni8430_setup(struct serial_private *priv,
> >  		return -ENOMEM;
> >
> >  	/* enable the transceiver */
> > -	writeb(readb(p + offset + NI8430_PORTCON) |
> NI8430_PORTCON_TXVR_ENABLE,
> > -	       p + offset + NI8430_PORTCON);
> > +	writeb(readb(p + offset + NI16550_PCR_OFFSET) |
> > +			NI16550_PCR_TXVR_ENABLE_BIT,
> > +			p + offset + NI16550_PCR_OFFSET);
> 
> Why indent like this?  Please follow the indentation that used to be there.

I moved the indentation because it complained this line exceeded 80 characters 
when I check the patch. I will change back to original indentation.

> 
> >
> >  	iounmap(p);
> >
> >  	return setup_port(priv, port, bar, offset, board->reg_shift);  }
> >
> > +static int pci_ni8431_config_rs485(struct uart_port *port,
> > +	struct serial_rs485 *rs485)
> > +{
> > +	u8 pcr, acr;
> > +
> > +	struct uart_8250_port *up;
> > +
> > +	up = container_of(port, struct uart_8250_port, port);
> > +
> > +	acr = up->acr;
> > +
> > +	dev_dbg(port->dev, "ni16550_config_rs485\n");
> 
> No need for debugging lines like this, use ftrace please.

Ok, will update this.

> 
> > +
> > +	/* "rs485" should be given to us non-NULL. */
> > +	WARN_ON(rs485 == NULL);
> 
> Don't crash people's machines, if this can never happen, then no need for this line.  If
> it can happen, test and properly return an error.

This is more like a fail safe approach, it should never happen, will remove this line.

> 
> > +
> > +	pcr = port->serial_in(port, NI16550_PCR_OFFSET);
> > +	pcr &= ~NI16550_PCR_WIRE_MODE_MASK;
> > +
> > +	if (rs485->flags & SER_RS485_ENABLED) {
> > +		/* RS-485 */
> > +		if ((rs485->flags & SER_RS485_RX_DURING_TX) &&
> > +			(rs485->flags & SER_RS485_RTS_ON_SEND)) {
> > +			dev_dbg(port->dev, "Invalid 2-wire mode\n");
> > +			return -EINVAL;
> > +		}
> > +
> > +		if (rs485->flags & SER_RS485_RX_DURING_TX) {
> > +			/* Echo */
> > +			dev_vdbg(port->dev, "2-wire DTR with echo\n");
> > +			pcr |= NI16550_PCR_ECHO_RS485;
> > +			acr |= NI16550_ACR_DTR_MANUAL_DTR;
> > +		} else {
> > +			/* Auto or DTR */
> > +			if (rs485->flags & SER_RS485_RTS_ON_SEND) {
> > +				/* Auto */
> > +				dev_vdbg(port->dev, "2-wire Auto\n");
> > +				pcr |= NI16550_PCR_AUTO_RS485;
> > +				acr |= NI16550_ACR_DTR_AUTO_DTR;
> > +			} else {
> > +				/* DTR-controlled */
> > +				/* No Echo */
> > +				dev_vdbg(port->dev, "2-wire DTR no echo\n");
> > +				pcr |= NI16550_PCR_DTR_RS485;
> > +				acr |= NI16550_ACR_DTR_MANUAL_DTR;
> > +			}
> > +		}
> > +	} else {
> > +		/* RS-422 */
> > +		dev_vdbg(port->dev, "4-wire\n");
> > +		pcr |= NI16550_PCR_RS422;
> > +		acr |= NI16550_ACR_DTR_MANUAL_DTR;
> > +	}
> > +
> > +	dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr);
> > +	port->serial_out(port, NI16550_PCR_OFFSET, pcr);
> > +
> > +	up->acr = acr;
> > +	port->serial_out(port, UART_SCR, UART_ACR);
> > +	port->serial_out(port, UART_ICR, up->acr);
> > +
> > +	/* Update the cache. */
> > +	port->rs485 = *rs485;
> > +
> > +	dev_dbg(port->dev, "ni16550_config_rs485\n");
> 
> Again, use ftrace, not dev_dbg() for stuff like this.

Will do so.

> 
> thanks,
> 
> greg k-h


Thank you.
Regards,
Je Yen Tam
Staff Software Engineer
National Instruments 
o   604-3776397
e   je.yen.tam@ni.com

^ permalink raw reply

* RE: Re: [PATCH V2 2/2] PCI: Add NI-Serial PXI/PXIe+485 device IDs
From: Je Yen Tam @ 2019-07-04  6:58 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20190703083605.GA8996@kroah.com>

> On Wed, Jul 03, 2019 at 12:25:16AM -0700, jeyentam wrote:
> > Add NI PXIe-RS232, PXI-RS485 and PXIe-RS485 device IDs.
> >
> > Signed-off-by: jeyentam <je.yen.tam@ni.com>
> > ---
> >  include/linux/pci_ids.h | 12 ++++++++++++
> >  1 file changed, 12 insertions(+)
> 
> You have read the comment at the top of this file, right?  If so, why 
> are you adding these entries?

Yes, but I think these entries should be added in because the NI-Serial PXI 
(RS232) device IDs already been defined in this file originally, so now I'm 
adding the newly supported NI-Serial PXI (RS485), PXIe (RS232) and PXIe 
(RS485) device IDs into here as they are the same product.

> 
> > diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 
> > 70e86148cb1e..7fad4794789f 100644
> > --- a/include/linux/pci_ids.h
> > +++ b/include/linux/pci_ids.h
> > @@ -1027,7 +1027,9 @@
> >  #define PCI_DEVICE_ID_SUN_TOMATILLO	0xa801
> >  #define PCI_DEVICE_ID_SUN_CASSINI	0xabba
> >
> > +/* NI-Serial Device IDs */
> >  #define PCI_VENDOR_ID_NI		0x1093
> 
> That's a vendor id, not a serial device id.

Yes, will change it to vendor id.

> 
> thanks,
> 
> greg k-h


Thank you.
Regards,
Je Yen Tam
Staff Software Engineer
National Instruments 
o   604-3776397
e   je.yen.tam@ni.com

^ permalink raw reply

* Re: [patch v3 1/5] AST2500 DMA UART driver
From: Benjamin Herrenschmidt @ 2019-07-03 23:04 UTC (permalink / raw)
  To: Greg KH, sudheer.v
  Cc: jslaby, joel, andrew, robh+dt, mark.rutland,
	shivahshankar.shankarnarayanrao, shivahshankar, sudheer.veliseti,
	sudheer veliseti, linux-kernel, linux-serial, devicetree,
	linux-aspeed
In-Reply-To: <20190703174926.GA12813@kroah.com>

On Wed, 2019-07-03 at 19:49 +0200, Greg KH wrote:
> > +
> > +     if (tx_sts & UART_SDMA0_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA0_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[0]));
> > +     } else if (tx_sts & UART_SDMA1_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA1_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[1]));
> > +     } else if (tx_sts & UART_SDMA2_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA2_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[2]));
> > +     } else if (tx_sts & UART_SDMA3_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA3_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[3]));
> > +     } else if (tx_sts & UART_SDMA4_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA4_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[4]));
> > +     } else if (tx_sts & UART_SDMA5_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA5_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[5]));
> > +     } else if (tx_sts & UART_SDMA6_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA6_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[6]));
> > +     } else if (tx_sts & UART_SDMA7_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA7_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[7]));
> > +     } else if (tx_sts & UART_SDMA8_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA8_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[8]));
> > +     } else if (tx_sts & UART_SDMA9_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA9_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[9]));
> > +     } else if (tx_sts & UART_SDMA10_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA10_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[10]));
> > +     } else if (tx_sts & UART_SDMA11_INT) {
> > +             ast_uart_sdma_write(sdma, UART_SDMA11_INT, UART_TX_SDMA_ISR);
> > +             ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[11]));
> > +     } else {
> > +     }

Also this should be a for () loop...

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH 0/3] serdev support for n_gsm
From: Pavel Machek @ 2019-07-03 22:33 UTC (permalink / raw)
  To: Johan Hovold
  Cc: Tony Lindgren, Greg Kroah-Hartman, linux-kernel, Alan Cox,
	Jiri Slaby, Peter Hurley, Rob Herring, Sebastian Reichel,
	linux-serial, Marcel Holtmann, Kishon Vijay Abraham I, Mark Brown
In-Reply-To: <20190124163932.GZ3691@localhost>

[-- Attachment #1: Type: text/plain, Size: 5006 bytes --]

Hi!

> and sorry about the reply latency. This is quite a lot to think about.
> 
> I'm also adding Kishon and Mark on CC (e.g. for the phy and ASoC
> bits).

I just wanted to ask... any news here?

> > For some user space examples, I have posted scripts to send and receive
> > SMS at [3], and Pavel has ofono patches [4] below. Seems like we can
> > also add support to ModemManager along the similar lines. And for the
> > serdev drivers, those implement standard Linux interfaces for apps
> > to use.
> > 
> > For PM, about a year ago I tried making things work with a user space
> > solution and it sucked big time[5]. The power management makes sense
> > to do in the kernel driver at least in this case as there are shared
> > GPIO pins between the USB PHY and TS 27.010 UART. The shared GPIOs
> > are handled by the phy-mapphone-mdm6600 driver.
> > 
> > With the serdev n_gsm MFD driver, the only thing that needs to be done
> > to idle the modem is to enable autosuspend for the OHCI interface. So
> > no spefific coordination between various components is needed for PM
> > beyond that. Things idle just fine using PM runtime.
> 
> Yeah, I don't envy you trying to get this to work (and now I'm getting
> dragged into it ;) ).

Yeah, and now I'm in, too. I'd really like to have an useful
phone. Droid4 seems like best candidate.

> It would really help with a high-level outline of the modem and its
> components. I've done my best to derive it from these patches and the
> code you link to, but that info needs to go in the patch descriptions
> (or cover letter).

Are you ready for the crazyness?

There are two modems in droid 4. I don't care about the LTE one. The
GSM one is connected with few USB channels, and few multiplexed
channels over UART.

One of USB channels is standard AT commands.
One of USB channels is QMI.
But using USB means big power consumption, so it is better to use
multiplexed channels over UART.

Few of those look vaguely like AT commands, but voice and sms and
... are going over separate channels. One of those contains NMEA data
(packet in AT lookalike).

> > Sure that's doable. But notice that we actually need to kick the
> > serdev GNSS interface to get more data. It's not a passive GNSS
> > data feed in this case. So it's not going to be just a case of
> > cat /dev/motmdm4 > /dev/ugnss. Without the serdev GNSS driver,
> > it would be some-custom-app -i /dev/motmdm4 -o /dev/ugnss.
> 
> Yeah, I remember us discussing that briefly off list.
>  
> > And without the n_gsm serdev support, it's a mess of some app
> > similar to [5] initializing n_gsm, trying to deal with the USB
> > PHY PM, dealing with Motorola custom packet numbering, kicking
> > GNSS device, feeding data to /dev/ugnss. Hmm I think I've already
> > been there just to be able to type AT commands to the modem and
> > it did not work :)
> 
> It's a mess indeed, but I'd rather see user-space dealing with until we
> figure out how best to do it in the kernel. ;)

Userspace should be shielded from hardware-specific mess :-(.

> > Anyways, for the serdev kernel drivers, the criteria I've tried
> > to follow is: "Can this serdev device driver make user space
> > apps use standard Linux interfaces for the hardware?"
> > 
> > So for the serdev Alsa ASoC driver, user space can use the standard
> > Alsa interface for setting voice call volume. And for the serdev
> > GNSS driver, user space can use /dev/gnss0.
> 
> I understand. Both drivers appears to be using AT commands for control.
> It would be interesting to hear what Mark has to say about the codec
> driver too. Moving AT handling into the kernel scares me a bit. If we
> already have a telephony stack to deal with it in user-space, my
> inclination is to let it continue to handle it.

These "Motorola AT" commands are really a bit different from standard
AT commands. I was working on userspace, and got something... but
could not get SMSes to work.

> Modem-managed GNSS is also different from receivers connected directly
> to the host. It's really the modem that drives the GNSS receiver, and
> offers a higher-level interface to the host, for example, by buffering
> output which the host can later request. It may or may not be the
> kernel's job to periodically poll the modem to recreate an NMEA feed so
> to speak.
> 
> But the end-result of having it accessible through a standard interface
> is of course appealing.

We'd really like unified interface for the GPS receivers, please. In
the Droid4 case, there's separate channel on the UART that has just
the GPS... so it is really quite similar to normal GPS.

We won't have proper driver for the modem anytime soon, but it would
be good to be able to use the GPS in the meantime.

Best regards,

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply

* Re: [patch v3 1/5] AST2500 DMA UART driver
From: Joe Perches @ 2019-07-03 19:16 UTC (permalink / raw)
  To: Greg KH, sudheer.v
  Cc: jslaby, joel, andrew, benh, robh+dt, mark.rutland,
	shivahshankar.shankarnarayanrao, shivahshankar, sudheer.veliseti,
	sudheer veliseti, linux-kernel, linux-serial, devicetree,
	linux-aspeed
In-Reply-To: <20190703174926.GA12813@kroah.com>

On Wed, 2019-07-03 at 19:49 +0200, Greg KH wrote:
> On Tue, Jun 25, 2019 at 04:14:32PM +0530, sudheer.v wrote:
> > +#define UART_TX_R_POINT(x) (0x40 + (x * 0x20))
> > +#define UART_TX_W_POINT(x) (0x44 + (x * 0x20))
> > +#define UART_TX_SDMA_ADDR(x) (0x48 + (x * 0x20))
> > +#define UART_RX_R_POINT(x) (0x50 + (x * 0x20))
> > +#define UART_RX_W_POINT(x) (0x54 + (x * 0x20))
> > +#define UART_RX_SDMA_ADDR(x) (0x58 + (x * 0x20))
> 
> Please use a tab to line these up.

Also x should be surrounded by parentheses

#define UART_TX_R_POINT(x)	(0x40 + ((x) * 0x20))

etc...

^ permalink raw reply

* Re: [patch v3 4/5] defconfig and MAINTAINERS updated for AST2500 DMA UART driver
From: Greg KH @ 2019-07-03 17:51 UTC (permalink / raw)
  To: sudheer.v
  Cc: jslaby, joel, andrew, benh, robh+dt, mark.rutland,
	shivahshankar.shankarnarayanrao, shivahshankar, sudheer.veliseti,
	sudheer veliseti, linux-kernel, linux-serial, devicetree,
	linux-aspeed
In-Reply-To: <1561459476-14268-5-git-send-email-open.sudheer@gmail.com>

On Tue, Jun 25, 2019 at 04:14:35PM +0530, sudheer.v wrote:
> From: sudheer veliseti <sudheer.open@gmail.com>
> 
> defconfig changes to add DMA based UART in AST2500
> Maintainers File updated.
> Signed-off-by: sudheer veliseti <sudheer.open@gmail.com>

Blank line needed before signed-off-by.


> ---
> 
> Changes in v3:
> - Added changes logs 
> 
>  MAINTAINERS                          | 13 +++++++++++++
>  arch/arm/configs/aspeed_g5_defconfig |  1 +
>  2 files changed, 14 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 997e27ab492f..c9a9790b97f6 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1347,6 +1347,19 @@ F:	drivers/crypto/axis
>  F:	drivers/pinctrl/pinctrl-artpec*
>  F:	Documentation/devicetree/bindings/pinctrl/axis,artpec6-pinctrl.txt
>  
> +ARM/ASPEED DMA UART DRIVER
> +M:	sudheer v <sudheer.open@gmail.com>
> +M:	ShivahShankar <shivahshankar.shankarnarayanrao@aspeedtech.com>
> +R:	Joel Stanley <joel@jms.id.au>
> +R:	Andrew Jeffery <andrew@aj.id.au>
> +R:	Vinod Koul <vkoul@kernel.org>
> +L:	dmaengine@vger.kernel.org
> +L:	openbmc@lists.ozlabs.org
> +L:	linux-aspeed@lists.ozlabs.org
> +S:	Maintained
> +F:	drivers/tty/serial/8250/8250_aspeed_uart_dma.c
> +F:	Documentation/devicetree/bindings/serial/ast-sdma-uart.txt
> +
>  ARM/ASPEED I2C DRIVER
>  M:	Brendan Higgins <brendanhiggins@google.com>
>  R:	Benjamin Herrenschmidt <benh@kernel.crashing.org>
> diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
> index 1849cbc161b4..25bf26630939 100644
> --- a/arch/arm/configs/aspeed_g5_defconfig
> +++ b/arch/arm/configs/aspeed_g5_defconfig
> @@ -144,6 +144,7 @@ CONFIG_SERIAL_8250=y
>  CONFIG_SERIAL_8250_CONSOLE=y
>  CONFIG_SERIAL_8250_NR_UARTS=6
>  CONFIG_SERIAL_8250_RUNTIME_UARTS=6
> +CONFIG_AST_SERIAL_DMA_UART=y

This shows that the config option should be:
	CONFIG_SERIAL_AST_DMA_UART
right?

thanks,

greg k-h

^ permalink raw reply

* Re: [patch v3 3/5] DT nodes for AST2500 DMA UART driver
From: Greg KH @ 2019-07-03 17:50 UTC (permalink / raw)
  To: sudheer.v
  Cc: jslaby, joel, andrew, benh, robh+dt, mark.rutland,
	shivahshankar.shankarnarayanrao, shivahshankar, sudheer.veliseti,
	sudheer veliseti, linux-kernel, linux-serial, devicetree,
	linux-aspeed
In-Reply-To: <1561459476-14268-4-git-send-email-open.sudheer@gmail.com>

On Tue, Jun 25, 2019 at 04:14:34PM +0530, sudheer.v wrote:
> From: sudheer veliseti <sudheer.open@gmail.com>
> 
> DT node for DMA controller(ast_uart_sdma) doesn't bind to any DMA controller driver.
> This is because Software for DMA controller is not based on DMA framework,but is dedicated
> and serves only UARTs in AST2500. ast_uart_sdma node is searched by compatible string in the 
> driver software.basic use of this node is to provide register base address of DMA controller and DMA irq number(<50>).
> IRQ of DMA controller is of crucial importance, which does RX and TX of UART data. 

Properly line-wrap your changelog.

thanks,

greg k-h

^ permalink raw reply

* Re: [patch v3 2/5] build configuration for AST2500 DMA UART driver
From: Greg KH @ 2019-07-03 17:50 UTC (permalink / raw)
  To: sudheer.v
  Cc: jslaby, joel, andrew, benh, robh+dt, mark.rutland,
	shivahshankar.shankarnarayanrao, shivahshankar, sudheer.veliseti,
	sudheer veliseti, linux-kernel, linux-serial, devicetree,
	linux-aspeed
In-Reply-To: <1561459476-14268-3-git-send-email-open.sudheer@gmail.com>

On Tue, Jun 25, 2019 at 04:14:33PM +0530, sudheer.v wrote:
> From: sudheer veliseti <sudheer.open@gmail.com>
> 
> build config for DMA based UART driver in AST2500.
> Total Available  UARTs in AST2500 are 4
> 
> Signed-off-by: sudheer veliseti <sudheer.open@gmail.com>
> ---
> 
> Changes in v3:
> - change logs added
> 
> drivers/tty/serial/8250/Kconfig  | 35 +++++++++++++++++++++++++++++++-
>  drivers/tty/serial/8250/Makefile |  1 +
>  2 files changed, 35 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
> index 15c2c5463835..c793466a1c47 100644
> --- a/drivers/tty/serial/8250/Kconfig
> +++ b/drivers/tty/serial/8250/Kconfig
> @@ -45,7 +45,7 @@ config SERIAL_8250_DEPRECATED_OPTIONS
>  	  keep the 8250_core.* options around until they revert the changes
>  	  they already did.
>  
> -	  If 8250 is built as a module, this adds 8250_core alias instead. 
> +	  If 8250 is built as a module, this adds 8250_core alias instead.
>  
>  	  If you did not notice yet and/or you have userspace from pre-3.7, it
>  	  is safe (and recommended) to say N here.

Why did you change this line?

> @@ -189,6 +189,39 @@ config SERIAL_8250_RUNTIME_UARTS
>  	  with the module parameter "nr_uarts", or boot-time parameter
>  	  8250.nr_uarts
>  
> +config  AST_SERIAL_DMA_UART
> +        tristate "AST UART driver with DMA"
> +        select SERIAL_CORE
> +        help
> +          UART driver with DMA support for Aspeed BMC AST25XX.
> +          this driver supports UARTs in AST2500,AST2600. It uses
> +          DMA channel of DMA engines present in these chips.
> +          since this dma engine is used only by UARTs it is not
> +          added as a separate DMA driver instead added as a layer
> +          within UART driver.
> +
> +
> +config AST_NR_DMA_UARTS
> +        int "Maximum number of uart dma serial ports"
> +        depends on AST_SERIAL_DMA_UART
> +        default "4"
> +        help
> +          Set this to the number of serial ports you want the driver
> +          to support.  This includes any ports discovered via ACPI or
> +          PCI enumeration and any ports that may be added at run-time
> +          via hot-plug, or any ISA multi-port serial cards.
> +
> +config AST_RUNTIME_DMA_UARTS
> +        int "Number of uart dma serial ports to register at runtime"
> +        depends on AST_SERIAL_DMA_UART
> +        range 0 AST_NR_DMA_UARTS
> +        default "4"
> +        help
> +          Set this to the maximum number of serial ports you want
> +          the kernel to register at boot time.  This can be overridden
> +          with the module parameter "nr_uarts", or boot-time parameter
> +          8250.nr_uarts

That boot paramter is not correct, right?

Are you sure these all work like you think they work?

thanks,

greg k-h

^ permalink raw reply

* Re: [patch v3 1/5] AST2500 DMA UART driver
From: Greg KH @ 2019-07-03 17:49 UTC (permalink / raw)
  To: sudheer.v
  Cc: jslaby, joel, andrew, benh, robh+dt, mark.rutland,
	shivahshankar.shankarnarayanrao, shivahshankar, sudheer.veliseti,
	sudheer veliseti, linux-kernel, linux-serial, devicetree,
	linux-aspeed
In-Reply-To: <1561459476-14268-2-git-send-email-open.sudheer@gmail.com>

On Tue, Jun 25, 2019 at 04:14:32PM +0530, sudheer.v wrote:
> From: sudheer veliseti <sudheer.open@gmail.com>
> 
> UART driver for Aspeed's bmc chip AST2500
> 
> Design approch:
> AST2500 has dedicated Uart DMA controller which has 12 sets of Tx and RX channels
> connected to UART controller directly.
> Since the DMA controller have dedicated buffers and registers,
> there would be little benifit in adding DMA framework overhead.
> So the software for DMA controller is included within the UART driver itself.
> 
> implementation details:
> 'struct uart_8250_port' serial port  is populated and registered with 8250_core.
> Rx and Tx dma channels are requested from DMA controller software Layer, which
> is part of uart driver itself.
> Interrupt service routine for DMA controller is the crucial one for Handling all
> the tx and rx data. ISRs installed for individual uarts are just dummy,and are helpful 
> only to report any spurious interrupts in hardware.
> 
> 
> Signed-off-by: sudheer veliseti <sudheer.open@gmail.com>
> ---
> 
> Changes in v3:
> -custom debug replaced by in kerenl dynamic debug: pr_debug 
> -change-logs added 
> 
> .../tty/serial/8250/8250_ast2500_uart_dma.c   | 1879 +++++++++++++++++
>  1 file changed, 1879 insertions(+)
>  create mode 100644 drivers/tty/serial/8250/8250_ast2500_uart_dma.c
> 
> diff --git a/drivers/tty/serial/8250/8250_ast2500_uart_dma.c b/drivers/tty/serial/8250/8250_ast2500_uart_dma.c
> new file mode 100644
> index 000000000000..13911a0a745a
> --- /dev/null
> +++ b/drivers/tty/serial/8250/8250_ast2500_uart_dma.c
> @@ -0,0 +1,1879 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + *  DMA UART Driver for ASPEED BMC chip: AST2500
> + *
> + *  Copyright (C) 2019 sudheer Kumar veliseti, Aspeed technology Inc.
> + *  <open.sudheer@gmail.com>
> + *
> + */
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/clk.h>
> +#include <linux/console.h>
> +#include <linux/delay.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/init.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/ioport.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/mutex.h>
> +#include <linux/nmi.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/serial.h>
> +#include <linux/serial_8250.h>
> +#include <linux/serial_core.h>
> +#include <linux/serial_reg.h>
> +#include <linux/slab.h>
> +#include <linux/tty.h>
> +#include <linux/tty_flip.h>

Do you really need all of these include files?  Seems like a lot...

> +
> +#include "8250.h"
> +
> +#define DMA_BUFF_SIZE 0x1000      // 4096
> +#define SDMA_RX_BUFF_SIZE 0x10000 // 65536

We know what 0x1000 and 0x10000 is :)

Also, try to line up your defines.

> +
> +#define SDDMA_RX_FIX 1
> +/* enum ast_uart_chan_op
> + * operation codes passed to the DMA code by the user, and also used
> + * to inform the current channel owner of any changes to the system state
> + */
> +
> +enum ast_uart_chan_op {

Very odd spacing, add one above the comment and remove the one below.

> +	AST_UART_DMAOP_TRIGGER,
> +	AST_UART_DMAOP_STOP,
> +	AST_UART_DMAOP_PAUSE,
> +};
> +
> +/* ast_uart_dma_cbfn_t *  * buffer callback routine type */

Do not use _t if possible.  ANd odd placement of "*  *"

> +typedef void (*ast_uart_dma_cbfn_t)(void *dev_id, u16 len);
> +
> +struct ast_sdma_info {
> +	u8 ch_no;
> +	u8 direction;
> +	u8 enable;
> +	void *priv;
> +	char *sdma_virt_addr;
> +	dma_addr_t dma_phy_addr;
> +	/* cdriver callbacks */
> +	ast_uart_dma_cbfn_t callback_fn; /* buffer done callback */
> +};
> +
> +#define AST_UART_SDMA_CH 12
> +
> +struct ast_sdma_ch {
> +	struct ast_sdma_info tx_dma_info[AST_UART_SDMA_CH];
> +	struct ast_sdma_info rx_dma_info[AST_UART_SDMA_CH];
> +};
> +
> +struct ast_sdma {
> +	void __iomem *reg_base;
> +	int dma_irq;
> +	struct ast_sdma_ch *dma_ch;
> +	struct regmap *map;
> +};
> +
> +
> +
> +#define UART_TX_SDMA_EN 0x00
> +#define UART_RX_SDMA_EN 0x04
> +#define UART_SDMA_CONF 0x08
> +#define UART_SDMA_TIMER 0x0C
> +#define UART_TX_SDMA_REST 0x20
> +#define UART_RX_SDMA_REST 0x24
> +#define UART_TX_SDMA_IER 0x30
> +#define UART_TX_SDMA_ISR 0x34
> +#define UART_RX_SDMA_IER 0x38
> +#define UART_RX_SDMA_ISR 0x3C
> +#define UART_TX_R_POINT(x) (0x40 + (x * 0x20))
> +#define UART_TX_W_POINT(x) (0x44 + (x * 0x20))
> +#define UART_TX_SDMA_ADDR(x) (0x48 + (x * 0x20))
> +#define UART_RX_R_POINT(x) (0x50 + (x * 0x20))
> +#define UART_RX_W_POINT(x) (0x54 + (x * 0x20))
> +#define UART_RX_SDMA_ADDR(x) (0x58 + (x * 0x20))

Please use a tab to line these up.

> +/* UART_TX_SDMA_EN-0x00 : UART TX DMA Enable */
> +/* UART_RX_SDMA_EN-0x04 : UART RX DMA Enable */

What are these for?

> +#define SDMA_CH_EN(x) (0x1 << (x))

BIT()?

> +
> +/* UART_SDMA_CONF - 0x08 : Misc, Buffer size  */
> +#define SDMA_TX_BUFF_SIZE_MASK (0x3)
> +#define SDMA_SET_TX_BUFF_SIZE(x) (x)
> +#define SDMA_BUFF_SIZE_1KB (0x0)
> +#define SDMA_BUFF_SIZE_4KB (0x1)
> +#define SDMA_BUFF_SIZE_16KB (0x2)
> +#define SDMA_BUFF_SIZE_64KB (0x3)
> +#define SDMA_RX_BUFF_SIZE_MASK (0x3 << 2)
> +#define SDMA_SET_RX_BUFF_SIZE(x) (x << 2)
> +#define SDMA_TIMEOUT_DIS (0x1 << 4)
> +
> +/* UART_SDMA_TIMER-0x0C :  UART DMA time out timer */
> +
> +/* UART_TX_SDMA_IER			0x30	*/
> +/* UART_TX_SDMA_ISR			0x34	*/

What is this?

> +
> +#define UART_SDMA11_INT (1 << 11)
> +#define UART_SDMA10_INT (1 << 10)
> +#define UART_SDMA9_INT (1 << 9)
> +#define UART_SDMA8_INT (1 << 8)
> +#define UART_SDMA7_INT (1 << 7)
> +#define UART_SDMA6_INT (1 << 6)
> +#define UART_SDMA5_INT (1 << 5)
> +#define UART_SDMA4_INT (1 << 4)
> +#define UART_SDMA3_INT (1 << 3)
> +#define UART_SDMA2_INT (1 << 2)
> +#define UART_SDMA1_INT (1 << 1)
> +#define UART_SDMA0_INT (1 << 0)

Please use BIT()

> +
> +
> +/*
> + * Configuration:
> + *   share_irqs - whether we pass IRQF_SHARED to request_irq().  This option
> + *                is unsafe when used on edge-triggered interrupts.
> + */
> +static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
> +
> +static unsigned int nr_uarts = CONFIG_AST_RUNTIME_DMA_UARTS;
> +
> +
> +#define PASS_LIMIT 256
> +
> +#include <asm/serial.h>

Why way down here?

> +
> +#define UART_DMA_NR CONFIG_AST_NR_DMA_UARTS
> +
> +
> +struct ast_uart_priv_data {
> +
> +	unsigned short line; //index of uart port

No need for a blank line.

> +	struct uart_8250_port *up;
> +	u8 dma_ch; // dma channel number
> +	struct circ_buf rx_dma_buf;
> +	struct circ_buf tx_dma_buf;
> +	dma_addr_t dma_rx_addr; /* Mapped ADMA descr. table */
> +	dma_addr_t dma_tx_addr; /* Mapped ADMA descr. table */
> +#ifdef SDDMA_RX_FIX
> +	struct tasklet_struct rx_tasklet;
> +#else
> +	struct timer_list rx_timer;
> +#endif
> +	struct tasklet_struct tx_tasklet;
> +	spinlock_t lock;
> +	int tx_done;
> +	int tx_count;
> +};
> +
> +
> +static inline struct uart_8250_port *
> +to_uart_8250_port(struct uart_port *uart) {
> +	return container_of(uart, struct uart_8250_port, port);
> +}

Use a #define for a container_of() macro please.

> +
> +struct irq_info {
> +	spinlock_t lock;
> +	struct uart_8250_port *up;
> +};
> +
> +static struct irq_info ast_uart_irq[1];
> +static DEFINE_MUTEX(ast_uart_mutex);
> +
> +/*
> + * Here we define the default xmit fifo size used for each type of UART.
> + */
> +static const struct serial8250_config uart_config[] = {
> +	[PORT_UNKNOWN] = {
> +		.name		= "unknown",
> +		.fifo_size	= 1,
> +		.tx_loadsz	= 1,
> +	},
> +	[PORT_8250] = {
> +		.name		= "8250",
> +		.fifo_size	= 1,
> +		.tx_loadsz	= 1,
> +	},
> +	[PORT_16450] = {
> +		.name		= "16450",
> +		.fifo_size	= 1,
> +		.tx_loadsz	= 1,
> +	},
> +	[PORT_16550] = {
> +		.name		= "16550",
> +		.fifo_size	= 1,
> +		.tx_loadsz	= 1,
> +	},
> +	[PORT_16550A] = {
> +		.name		= "16550A",
> +		.fifo_size	= 16,
> +		.tx_loadsz	= 16,
> +		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10
> +							| UART_FCR_DMA_SELECT,
> +		.flags		= UART_CAP_FIFO,
> +	},
> +};
> +
> +/* sane hardware needs no mapping */
> +#define map_8250_in_reg(up, offset) (offset)
> +#define map_8250_out_reg(up, offset) (offset)


Why is this even needed?


> +
> +// SDMA - software Layer : (previously was in ast-uart-sdma.c)

"previously"?

> +static inline void ast_uart_sdma_write(struct ast_sdma *sdma,
> +						u32 val, u32 reg)
> +{
> +	pr_debug("uart dma write:val:%x,reg:%x\n", val, reg);

No need for debugging, use ftrace.

> +	writel(val, sdma->reg_base + reg);
> +}
> +
> +static inline u32 ast_uart_sdma_read(struct ast_sdma *sdma, u32 reg)
> +{
> +	return readl(sdma->reg_base + reg);
> +}
> +
> +struct ast_sdma ast_uart_sdma;

static?

> +
> +int ast_uart_rx_sdma_enqueue(u8 ch, dma_addr_t rx_buff)
> +{
> +	unsigned long flags;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +
> +	pr_debug("ch = %d, rx buff = %x\n", ch, rx_buff);

Remove debugging please, use ftrace.

> +
> +	local_irq_save(flags);
> +	ast_uart_sdma_write(sdma, rx_buff, UART_RX_SDMA_ADDR(ch));
> +	local_irq_restore(flags);
> +
> +	return 0;
> +}

If these functions are not used, why are they here?



> +
> +int ast_uart_tx_sdma_enqueue(u8 ch, dma_addr_t tx_buff)
> +{
> +	unsigned long flags;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +
> +	pr_debug("ch = %d, tx buff = %x\n", ch, tx_buff);
> +
> +	local_irq_save(flags);
> +	ast_uart_sdma_write(sdma, tx_buff, UART_TX_SDMA_ADDR(ch));
> +	local_irq_restore(flags);
> +
> +	return 0;
> +}
> +
> +int ast_uart_rx_sdma_ctrl(u8 ch, enum ast_uart_chan_op op)
> +{
> +	unsigned long flags;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +	struct ast_sdma_info *dma_ch = &(sdma->dma_ch->rx_dma_info[ch]);
> +
> +	pr_debug("RX DMA CTRL [ch %d]\n", ch);

Again, please remove.  Same thing everywhere in these patches.

> +
> +	local_irq_save(flags);
> +
> +	switch (op) {
> +	case AST_UART_DMAOP_TRIGGER:
> +	pr_debug("Trigger\n");
> +	dma_ch->enable = 1;
> +#ifdef SDDMA_RX_FIX

If you can not define this as a build option, then just remove it from
here.

> +#else
> +	ast_uart_set_sdma_time_out(0xffff);
> +#endif
> +	// set enable
> +	ast_uart_sdma_write(sdma,
> +			ast_uart_sdma_read(sdma, UART_RX_SDMA_EN) | (0x1 << ch),
> +			UART_RX_SDMA_EN);
> +	break;

Did you run this patch through checkpatch?  Please properly indent the
case statement blocks.

> +	case AST_UART_DMAOP_STOP:
> +	// disable engine
> +	pr_debug("STOP\n");
> +	dma_ch->enable = 0;
> +	ast_uart_sdma_write(sdma, ast_uart_sdma_read(sdma, UART_RX_SDMA_EN) &
> +				  ~(0x1 << ch),
> +			UART_RX_SDMA_EN);
> +	// set reset
> +	ast_uart_sdma_write(sdma, ast_uart_sdma_read(sdma, UART_RX_SDMA_REST) |
> +				  (0x1 << ch),
> +			UART_RX_SDMA_REST);
> +	ast_uart_sdma_write(sdma, ast_uart_sdma_read(sdma, UART_RX_SDMA_REST) &
> +				  ~(0x1 << ch),
> +			UART_RX_SDMA_REST);
> +
> +	ast_uart_sdma_write(sdma, 0, UART_RX_R_POINT(ch));
> +	ast_uart_sdma_write(sdma, dma_ch->dma_phy_addr, UART_RX_SDMA_ADDR(ch));
> +	break;
> +	case AST_UART_DMAOP_PAUSE:
> +	// disable engine
> +	dma_ch->enable = 0;
> +	ast_uart_sdma_write(sdma, ast_uart_sdma_read(sdma, UART_RX_SDMA_EN) &
> +				  ~(0x1 << ch),
> +			UART_RX_SDMA_EN);
> +	break;
> +	}
> +
> +	local_irq_restore(flags);
> +	return 0;
> +}
> +
> +int ast_uart_tx_sdma_ctrl(u8 ch, enum ast_uart_chan_op op)
> +{
> +	unsigned long flags;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +	struct ast_sdma_info *dma_ch = &(sdma->dma_ch->tx_dma_info[ch]);
> +
> +	pr_debug("TX DMA CTRL [ch %d]\n", ch);
> +
> +	local_irq_save(flags);
> +
> +	switch (op) {
> +	case AST_UART_DMAOP_TRIGGER:
> +	pr_debug("TRIGGER : Enable\n");
> +	dma_ch->enable = 1;
> +	// set enable
> +	ast_uart_sdma_write(sdma,
> +			ast_uart_sdma_read(sdma, UART_TX_SDMA_EN) | (0x1 << ch),
> +			UART_TX_SDMA_EN);
> +	break;
> +	case AST_UART_DMAOP_STOP:
> +	pr_debug("STOP : DISABLE & RESET\n");
> +	dma_ch->enable = 0;
> +	// disable engine
> +	ast_uart_sdma_write(sdma, ast_uart_sdma_read(sdma, UART_TX_SDMA_EN) &
> +				  ~(0x1 << ch),
> +			UART_TX_SDMA_EN);
> +	// set reset
> +	ast_uart_sdma_write(sdma, ast_uart_sdma_read(sdma, UART_TX_SDMA_REST) |
> +				  (0x1 << ch),
> +			UART_TX_SDMA_REST);
> +	ast_uart_sdma_write(sdma, ast_uart_sdma_read(sdma, UART_TX_SDMA_REST) &
> +				  ~(0x1 << ch),
> +			UART_TX_SDMA_REST);
> +
> +	ast_uart_sdma_write(sdma, 0, UART_TX_W_POINT(ch));
> +	break;
> +	case AST_UART_DMAOP_PAUSE:
> +	pr_debug("PAUSE : DISABLE\n");
> +	dma_ch->enable = 0;
> +	// disable engine
> +	ast_uart_sdma_write(sdma, ast_uart_sdma_read(sdma, UART_TX_SDMA_EN) &
> +				  ~(0x1 << ch),
> +			UART_TX_SDMA_EN);
> +	}
> +
> +	local_irq_restore(flags);
> +	return 0;
> +}
> +
> +u32 ast_uart_get_tx_sdma_pt(u8 ch)
> +{
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +
> +	return ast_uart_sdma_read(sdma, UART_TX_R_POINT(ch));
> +}
> +
> +int ast_uart_tx_sdma_update(u8 ch, u16 point)
> +{
> +	unsigned long flags;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +
> +	pr_debug("TX DMA CTRL [ch %d] point %d\n", ch, point);
> +	local_irq_save(flags);
> +	ast_uart_sdma_write(sdma, point, UART_TX_W_POINT(ch));
> +	local_irq_restore(flags);
> +	return 0;
> +}
> +
> +int ast_uart_tx_sdma_request(u8 ch, ast_uart_dma_cbfn_t rtn, void *id)
> +{
> +	unsigned long flags;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +	struct ast_sdma_info *dma_ch = &(sdma->dma_ch->tx_dma_info[ch]);
> +
> +	pr_debug("TX DMA REQUEST ch = %d\n", ch);
> +
> +	local_irq_save(flags);
> +
> +	if (dma_ch->enable) {
> +		local_irq_restore(flags);
> +		return -EBUSY;
> +	}
> +	dma_ch->priv = id;
> +	dma_ch->callback_fn = rtn;
> +
> +	// DMA IRQ En
> +	ast_uart_sdma_write(sdma,
> +		      ast_uart_sdma_read(sdma, UART_TX_SDMA_IER) | (1 << ch),
> +		      UART_TX_SDMA_IER);
> +
> +	local_irq_restore(flags);
> +
> +	return 0;
> +}
> +
> +int ast_uart_rx_sdma_update(u8 ch, u16 point)
> +{
> +	unsigned long flags;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +
> +	pr_debug("RX DMA CTRL [ch %d] point %x\n", ch, point);
> +
> +	local_irq_save(flags);
> +	ast_uart_sdma_write(sdma, point, UART_RX_R_POINT(ch));
> +	local_irq_restore(flags);
> +	return 0;
> +}
> +
> +#ifdef SDDMA_RX_FIX
> +char *ast_uart_rx_sdma_request(u8 ch, ast_uart_dma_cbfn_t rtn, void *id)
> +{
> +	unsigned long flags;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +	struct ast_sdma_info *dma_ch = &(sdma->dma_ch->rx_dma_info[ch]);
> +
> +	pr_debug("RX DMA REQUEST ch = %d\n", ch);
> +
> +	local_irq_save(flags);
> +
> +	if (dma_ch->enable) {
> +		local_irq_restore(flags);
> +		return 0;
> +	}
> +	dma_ch->priv = id;
> +
> +	dma_ch->callback_fn = rtn;
> +
> +	// DMA IRQ En
> +	ast_uart_sdma_write(sdma,
> +		      ast_uart_sdma_read(sdma, UART_RX_SDMA_IER) | (1 << ch),
> +		      UART_RX_SDMA_IER);
> +
> +	local_irq_restore(flags);
> +
> +	return dma_ch->sdma_virt_addr;
> +}
> +
> +#else
> +char *ast_uart_rx_sdma_request(u8 ch, void *id)
> +{
> +	unsigned long flags;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +	struct ast_sdma_info *dma_ch = &(sdma->dma_ch->rx_dma_info[ch]);
> +
> +	pr_debug("RX DMA REQUEST ch = %d\n", ch);
> +
> +	local_irq_save(flags);
> +
> +	if (dma_ch->enable) {
> +		local_irq_restore(flags);
> +		return -EBUSY;
> +	}
> +	dma_ch->priv = id;
> +
> +	local_irq_restore(flags);
> +	return dma_ch->sdma_virt_addr;
> +}
> +#endif
> +
> +u16 ast_uart_get_rx_sdma_pt(u8 ch)
> +{
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +
> +	return ast_uart_sdma_read(sdma, UART_RX_W_POINT(ch));
> +}
> +
> +void ast_uart_set_sdma_time_out(u16 val)
> +{
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +
> +	ast_uart_sdma_write(sdma, val, UART_SDMA_TIMER);
> +}
> +
> +static inline void ast_sdma_bufffdone(struct ast_sdma_info *sdma_ch)
> +{
> +	u32 len;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +
> +	if (sdma_ch->enable == 0) {
> +		pr_debug("sdma Please check ch_no %x %s!!!!!\n",
> +			sdma_ch->ch_no, sdma_ch->direction ? "TX" : "RX");
> +		if (sdma_ch->direction) {
> +			ast_uart_sdma_write(sdma,
> +				ast_uart_sdma_read(sdma, UART_TX_SDMA_EN)
> +				& ~(0x1 << sdma_ch->ch_no), UART_TX_SDMA_EN);
> +		} else {
> +			ast_uart_sdma_write(sdma,
> +				ast_uart_sdma_read(sdma, UART_RX_SDMA_EN) &
> +				~(0x1 << sdma_ch->ch_no), UART_RX_SDMA_EN);
> +			ast_uart_rx_sdma_update(sdma_ch->ch_no,
> +				ast_uart_get_rx_sdma_pt(sdma_ch->ch_no));
> +			pr_debug("OFFSET : UART_RX_SDMA_EN = %x\n ",
> +				ast_uart_sdma_read(sdma, UART_RX_SDMA_EN));
> +		}
> +		return;
> +	}
> +
> +	if (sdma_ch->direction) {
> +		len = ast_uart_sdma_read(sdma, UART_TX_R_POINT(sdma_ch->ch_no));
> +		pr_debug("tx rp %x , wp %x\n",
> +		ast_uart_sdma_read(sdma, UART_TX_R_POINT(sdma_ch->ch_no)),
> +		ast_uart_sdma_read(sdma, UART_TX_W_POINT(sdma_ch->ch_no))
> +		);
> +	} else {
> +		pr_debug("rx rp %x , wp %x\n",
> +		ast_uart_sdma_read(sdma, UART_RX_R_POINT(sdma_ch->ch_no)),
> +		ast_uart_sdma_read(sdma, UART_RX_W_POINT(sdma_ch->ch_no))
> +		);
> +		len = ast_uart_sdma_read(sdma, UART_RX_W_POINT(sdma_ch->ch_no));
> +	}
> +
> +	pr_debug("<dma dwn>: ch[%d] : %s ,len : %d\n", sdma_ch->ch_no,
> +				sdma_ch->direction ? "tx" : "rx", len);
> +
> +	if (sdma_ch->callback_fn != NULL)
> +		(sdma_ch->callback_fn)(sdma_ch->priv, len);
> +}
> +
> +static irqreturn_t ast_uart_sdma_isr(int irq, void *dev_id)
> +{
> +	struct ast_sdma *sdma = (struct ast_sdma *)dev_id;
> +
> +	u32 tx_sts = ast_uart_sdma_read(sdma, UART_TX_SDMA_ISR);
> +	u32 rx_sts = ast_uart_sdma_read(sdma, UART_RX_SDMA_ISR);
> +
> +	pr_debug("tx sts : %x, rx sts : %x\n", tx_sts, rx_sts);
> +
> +	if ((tx_sts == 0) && (rx_sts == 0)) {
> +		pr_debug("SDMA IRQ ERROR !!!\n");
> +		return IRQ_HANDLED;
> +	}
> +
> +	if (rx_sts & UART_SDMA0_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA0_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[0]));
> +	} else if (rx_sts & UART_SDMA1_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA1_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[1]));
> +	} else if (rx_sts & UART_SDMA2_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA2_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[2]));
> +	} else if (rx_sts & UART_SDMA3_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA3_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[3]));
> +	} else if (rx_sts & UART_SDMA4_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA4_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[4]));
> +	} else if (rx_sts & UART_SDMA5_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA5_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[5]));
> +	} else if (rx_sts & UART_SDMA6_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA6_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[6]));
> +	} else if (rx_sts & UART_SDMA7_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA7_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[7]));
> +	} else if (rx_sts & UART_SDMA8_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA8_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[8]));
> +	} else if (rx_sts & UART_SDMA9_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA9_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[9]));
> +	} else if (rx_sts & UART_SDMA10_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA10_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[10]));
> +	} else if (rx_sts & UART_SDMA11_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA11_INT, UART_RX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->rx_dma_info[11]));
> +	} else {
> +
> +	}

Why a blank else {} ?

> +
> +	if (tx_sts & UART_SDMA0_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA0_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[0]));
> +	} else if (tx_sts & UART_SDMA1_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA1_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[1]));
> +	} else if (tx_sts & UART_SDMA2_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA2_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[2]));
> +	} else if (tx_sts & UART_SDMA3_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA3_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[3]));
> +	} else if (tx_sts & UART_SDMA4_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA4_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[4]));
> +	} else if (tx_sts & UART_SDMA5_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA5_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[5]));
> +	} else if (tx_sts & UART_SDMA6_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA6_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[6]));
> +	} else if (tx_sts & UART_SDMA7_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA7_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[7]));
> +	} else if (tx_sts & UART_SDMA8_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA8_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[8]));
> +	} else if (tx_sts & UART_SDMA9_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA9_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[9]));
> +	} else if (tx_sts & UART_SDMA10_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA10_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[10]));
> +	} else if (tx_sts & UART_SDMA11_INT) {
> +		ast_uart_sdma_write(sdma, UART_SDMA11_INT, UART_TX_SDMA_ISR);
> +		ast_sdma_bufffdone(&(sdma->dma_ch->tx_dma_info[11]));
> +	} else {
> +	}

Why a blank else {} ?

> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int ast_uart_sdma_probe(void)
> +{
> +	int i;
> +	struct device_node *node;
> +	int ret;
> +	struct ast_sdma *sdma = &ast_uart_sdma;
> +	char *rx_dma_virt_addr;
> +	dma_addr_t rx_dma_phy_addr;
> +
> +	sdma->dma_ch = kzalloc(sizeof(struct ast_sdma_ch), GFP_KERNEL);
> +	if (!sdma->dma_ch)
> +		return -ENOMEM;
> +
> +	// sdma memory mapping
> +	node = of_find_compatible_node(NULL, NULL, "aspeed,ast-uart-sdma");
> +	if (!node)
> +		return -ENODEV;
> +
> +	sdma->reg_base = of_iomap(node, 0);
> +	if (IS_ERR(sdma->reg_base))
> +		return PTR_ERR(sdma->map);
> +	rx_dma_virt_addr = dma_alloc_coherent(NULL,
> +	SDMA_RX_BUFF_SIZE * AST_UART_SDMA_CH, &rx_dma_phy_addr, GFP_KERNEL);

Properly indent things, this is impossible to read.

> +
> +	if (!rx_dma_virt_addr) {
> +		pr_debug("rx_dma_virt_addr Err:dma alloc Failed\n");
> +		return -ENOMEM;
> +	}
> +	for (i = 0; i < AST_UART_SDMA_CH; i++) {
> +		// TX ------------------------
> +		sdma->dma_ch->tx_dma_info[i].enable = 0;
> +		sdma->dma_ch->tx_dma_info[i].ch_no = i;
> +		sdma->dma_ch->tx_dma_info[i].direction = 1;
> +		ast_uart_sdma_write(sdma, 0, UART_TX_W_POINT(i));
> +		// RX ------------------------
> +		sdma->dma_ch->rx_dma_info[i].enable = 0;
> +		sdma->dma_ch->rx_dma_info[i].ch_no = i;
> +		sdma->dma_ch->rx_dma_info[i].direction = 0;
> +		sdma->dma_ch->rx_dma_info[i].sdma_virt_addr =
> +		rx_dma_virt_addr + (SDMA_RX_BUFF_SIZE * i);
> +		sdma->dma_ch->rx_dma_info[i].dma_phy_addr =
> +		rx_dma_phy_addr + (SDMA_RX_BUFF_SIZE * i);
> +		ast_uart_sdma_write(sdma,
> +			sdma->dma_ch->rx_dma_info[i].dma_phy_addr,
> +			UART_RX_SDMA_ADDR(i));
> +		ast_uart_sdma_write(sdma, 0, UART_RX_R_POINT(i));
> +	}
> +
> +	ast_uart_sdma_write(sdma, 0xffffffff, UART_TX_SDMA_REST);
> +	ast_uart_sdma_write(sdma, 0x0, UART_TX_SDMA_REST);
> +
> +	ast_uart_sdma_write(sdma, 0xffffffff, UART_RX_SDMA_REST);
> +	ast_uart_sdma_write(sdma, 0x0, UART_RX_SDMA_REST);
> +
> +	ast_uart_sdma_write(sdma, 0, UART_TX_SDMA_EN);
> +	ast_uart_sdma_write(sdma, 0, UART_RX_SDMA_EN);
> +
> +#ifdef SDDMA_RX_FIX
> +	ast_uart_sdma_write(sdma, 0x200, UART_SDMA_TIMER);
> +#else
> +	ast_uart_sdma_write(sdma, 0xffff, UART_SDMA_TIMER);
> +#endif
> +
> +	// TX
> +	ast_uart_sdma_write(sdma, 0xfff, UART_TX_SDMA_ISR);
> +	ast_uart_sdma_write(sdma, 0, UART_TX_SDMA_IER);
> +
> +	// RX
> +	ast_uart_sdma_write(sdma, 0xfff, UART_RX_SDMA_ISR);
> +	ast_uart_sdma_write(sdma, 0, UART_RX_SDMA_IER);
> +
> +	sdma->dma_irq = of_irq_get(node, 0);
> +	ret = request_irq(sdma->dma_irq, ast_uart_sdma_isr, 0,
> +						"sdma-intr", sdma);
> +	if (ret) {
> +		pr_debug("Unable to get UART SDMA IRQ %x\n", ret);
> +		return -ENODEV;
> +	}
> +
> +	ast_uart_sdma_write(sdma, SDMA_SET_TX_BUFF_SIZE(SDMA_BUFF_SIZE_4KB) |
> +				SDMA_SET_RX_BUFF_SIZE(SDMA_BUFF_SIZE_64KB),
> +		      UART_SDMA_CONF);
> +	return 0;
> +}
> +
> +// END of SDMA Layer
> +
> +// UART Driver Layer
> +
> +static unsigned int ast_serial_in(struct uart_8250_port *up, int offset)
> +{
> +	offset = map_8250_in_reg(up, offset) << up->port.regshift;
> +	return readb(up->port.membase + offset);
> +}
> +
> +static void ast_serial_out(struct uart_8250_port  *up, int offset, int value)
> +{
> +	/* Save the offset before it's remapped */
> +	offset = map_8250_out_reg(up, offset) << up->port.regshift;
> +	writeb(value, up->port.membase + offset);
> +}
> +
> +/*
> + * We used to support using pause I/O for certain machines.  We
> + * haven't supported this for a while, but just in case it's badly
> + * needed for certain old 386 machines, I've left these #define's
> + * in....

It looks like you copied this whole thing from somewhere else, please
make it your own and do not leave things in for no good reason.


> + */
> +#define serial_inp(up, offset) ast_serial_in(up, offset)
> +#define serial_outp(up, offset, value) ast_serial_out(up, offset, value)
> +
> +/* Uart divisor latch read */
> +static inline int _serial_dl_read(struct uart_8250_port *up)
> +{
> +	return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
> +}
> +
> +/* Uart divisor latch write */
> +static inline void _serial_dl_write(struct uart_8250_port *up, int value)
> +{
> +	serial_outp(up, UART_DLL, value & 0xff);
> +	serial_outp(up, UART_DLM, value >> 8 & 0xff);
> +}
> +
> +#define serial_dl_read(up) _serial_dl_read(up)
> +#define serial_dl_write(up, value) _serial_dl_write(up, value)
> +
> +static void ast_uart_tx_sdma_tasklet_func(unsigned long data)
> +{
> +
> +	struct ast_uart_priv_data *priv = (struct ast_uart_priv_data *)data;
> +	struct uart_8250_port *up = priv->up;
> +	struct circ_buf *xmit = NULL;
> +	u32 tx_pt;
> +
> +
> +	if (!up)
> +		return;
> +	xmit = &up->port.state->xmit;
> +	spin_lock(&up->port.lock);
> +	priv->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
> +	dma_sync_single_for_device(up->port.dev, priv->dma_tx_addr,
> +					UART_XMIT_SIZE, DMA_TO_DEVICE);
> +	tx_pt = ast_uart_get_tx_sdma_pt(priv->dma_ch);
> +
> +	if (tx_pt > xmit->head)	{
> +		if ((tx_pt & 0xfffc) == 0)
> +			ast_uart_tx_sdma_update(priv->dma_ch, 0xffff);
> +		else
> +			ast_uart_tx_sdma_update(priv->dma_ch, 0);
> +	} else {
> +		ast_uart_tx_sdma_update(priv->dma_ch, xmit->head);
> +	}
> +	ast_uart_tx_sdma_update(priv->dma_ch, xmit->head);
> +	spin_unlock(&up->port.lock);
> +}
> +
> +static void ast_uart_tx_buffdone(void *dev_id, u16 len)
> +{
> +
> +	struct ast_uart_priv_data *priv = (struct ast_uart_priv_data *)dev_id;
> +	struct uart_8250_port *up = priv->up;
> +	struct circ_buf *xmit;
> +
> +	if (!up)
> +		return;
> +	xmit = &(up->port.state->xmit);
> +
> +	pr_debug("line[%d] : tx len = % d\n", priv->line, len);
> +	spin_lock(&up->port.lock);
> +	xmit->tail = len;
> +	pr_debug(" line[%d], xmit->head = %d, xmit->tail = % d\n",
> +			priv->line, xmit->head, xmit->tail);
> +
> +	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
> +		uart_write_wakeup(&up->port);
> +
> +	if (xmit->head != xmit->tail)
> +		tasklet_schedule(&priv->tx_tasklet);
> +
> +	spin_unlock(&up->port.lock);
> +}
> +
> +#ifdef SDDMA_RX_FIX
> +static void ast_uart_rx_sdma_tasklet_func(unsigned long data)
> +{
> +	struct ast_uart_priv_data *priv = (struct ast_uart_priv_data *)data;
> +	struct circ_buf *rx_ring = &priv->rx_dma_buf;
> +	struct tty_port *ttyport;
> +	int count;
> +	int copy = 0;
> +	struct uart_8250_port *up = priv->up;
> +
> +	if (!up)
> +		return;
> +
> +	ttyport = &up->port.state->port;
> +
> +	pr_debug("line[%d], rx_ring->head = % d, rx_ring->tail = % d\n",
> +			 up->port.line, rx_ring->head, rx_ring->tail);
> +	spin_lock(&up->port.lock);
> +	if (rx_ring->head > rx_ring->tail) {
> +		count = rx_ring->head - rx_ring->tail;
> +		copy = tty_insert_flip_string(ttyport,
> +				rx_ring->buf + rx_ring->tail, count);
> +	} else if (rx_ring->head < rx_ring->tail) {
> +		count = SDMA_RX_BUFF_SIZE - rx_ring->tail;
> +		copy = tty_insert_flip_string(ttyport,
> +					rx_ring->buf + rx_ring->tail, count);
> +	} else {
> +		count = 0;
> +	}
> +
> +	if (copy != count)
> +		pr_debug(" !!!!!!!!ERROR 111\n");

That's useless.  Make it a real error with dev_err() please.

> +	if (count) {
> +		rx_ring->tail += count;
> +		rx_ring->tail &= (SDMA_RX_BUFF_SIZE - 1);
> +		up->port.icount.rx += count;
> +		tty_flip_buffer_push(ttyport);
> +		ast_uart_rx_sdma_update(priv->dma_ch, rx_ring->tail);
> +	}
> +	spin_unlock(&up->port.lock);
> +}
> +
> +static void ast_uart_rx_buffdone(void *dev_id, u16 len)
> +{
> +	struct ast_uart_priv_data *priv = (struct ast_uart_priv_data *)dev_id;
> +	struct circ_buf *rx_ring = &priv->rx_dma_buf;
> +	struct uart_8250_port *up = priv->up;
> +
> +	if (!up)
> +		return;
> +	pr_debug("line[%d], head = %d,len:%d\n",
> +			 priv->line, priv->rx_dma_buf.head, len);
> +	spin_lock(&up->port.lock);
> +	rx_ring->head = len;
> +	spin_unlock(&up->port.lock);
> +	tasklet_schedule(&priv->rx_tasklet);
> +}
> +
> +#else
> +static void ast_uart_rx_timer_func(unsigned long data)
> +{
> +	struct ast_uart_priv_data *priv = (struct ast_uart_priv_data *)data;
> +	struct uart_8250_port *up = priv->up;
> +	struct tty_port *ttyport;
> +	struct circ_buf *rx_ring;
> +	struct tty_struct *tty;
> +	char flag;
> +	int count;
> +	int copy;
> +
> +
> +	if (!up)
> +		return;
> +	ttyport = &up->port.state->port;
> +	rx_ring = &up->rx_dma_buf;
> +	tty = up->port.state->port.tty;
> +
> +	pr_debug("line[%d], rx_ring->head = % d, rx_ring->tail = % d\n",
> +				up->port.line, rx_ring->head, rx_ring->tail);
> +	rx_ring->head = ast_uart_get_rx_sdma_pt(priv->dma_ch);
> +	del_timer(&up->rx_timer);
> +
> +	if (rx_ring->head > rx_ring->tail) {
> +		ast_uart_set_sdma_time_out(0xffff);
> +		count = rx_ring->head - rx_ring->tail;
> +		copy = tty_insert_flip_string(ttyport,
> +				 rx_ring->buf + rx_ring->tail, count);
> +	} else if (rx_ring->head < rx_ring->tail) {
> +		ast_uart_set_sdma_time_out(0xffff);
> +		count = SDMA_RX_BUFF_SIZE - rx_ring->tail;
> +		copy = tty_insert_flip_string(ttyport,
> +				 rx_ring->buf + rx_ring->tail, count);
> +	} else {
> +		count = 0;
> +		// pr_debug("@@--%s-- ch = 0x%x\n", __func__, ch);
> +	}
> +
> +	if (copy != count)
> +		pr_debug(" !!!!!!!!ERROR 111\n");
> +		rx_ring->tail += count;
> +		rx_ring->tail &= (SDMA_RX_BUFF_SIZE - 1);
> +
> +	if (count) {
> +		//pr_debug("\n count = % d\n", count);
> +		up->port.icount.rx += count;
> +		spin_lock(&up->port.lock);
> +		tty_flip_buffer_push(ttyport);
> +		spin_unlock(&up->port.lock);
> +		//pr_debug("update rx_ring->tail % x\n", rx_ring->tail);
> +		ast_uart_rx_sdma_update(priv->dma_ch, rx_ring->tail);
> +		priv->workaround = 1;
> +	} else {
> +		if (priv->workaround) {
> +			priv->workaround++;
> +			if (priv->workaround > 1)
> +				ast_uart_set_sdma_time_out(0);
> +			else
> +				ast_uart_set_sdma_time_out(0xffff);
> +		}
> +	}
> +	add_timer(&up->rx_timer);
> +}
> +#endif
> +
> +/*
> + * FIFO support.
> + */
> +static inline void ast25xx_uart_clear_fifos(struct uart_8250_port *p)
> +{
> +	serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
> +	serial_outp(p, UART_FCR,
> +	      UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
> +	serial_outp(p, UART_FCR, 0);
> +}
> +
> +/*
> + * This routine is called by rs_init() to initialize a specific serial
> + * port.
> + */
> +static void autoconfig(struct uart_8250_port *up)
> +{
> +	unsigned long flags;
> +
> +	pr_debug("line[%d]\n", up->port.line);
> +	if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
> +		return;
> +
> +	pr_debug("ttyDMA%d : autoconf (0x%04lx, 0x%p) : ", up->port.line,
> +		 up->port.iobase, up->port.membase);
> +
> +	spin_lock_irqsave(&up->port.lock, flags);
> +
> +	up->capabilities = 0;
> +	up->bugs = 0;
> +
> +	up->port.type = PORT_16550A;
> +	up->capabilities |= UART_CAP_FIFO;
> +
> +	up->port.fifosize = uart_config[up->port.type].fifo_size;
> +	up->capabilities = uart_config[up->port.type].flags;
> +	up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
> +
> +	if (up->port.type == PORT_UNKNOWN)
> +		goto out;
> +
> +	/*
> +	 * Reset the UART.
> +	 */
> +	ast25xx_uart_clear_fifos(up);
> +	ast_serial_in(up, UART_RX);
> +	serial_outp(up, UART_IER, 0);
> +
> +out:
> +	spin_unlock_irqrestore(&up->port.lock, flags);
> +	pr_debug("type=%s\n", uart_config[up->port.type].name);
> +}
> +
> +static inline void __stop_tx(struct uart_8250_port *p)
> +{
> +	if (p->ier & UART_IER_THRI) {
> +		p->ier &= ~UART_IER_THRI;
> +		ast_serial_out(p, UART_IER, p->ier);
> +	}
> +}
> +
> +static void ast25xx_uart_stop_tx(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +
> +	pr_debug("line[%d]\n", up->port.line);
> +	__stop_tx(up);
> +}
> +
> +static void transmit_chars(struct uart_8250_port *up);
> +
> +static void ast25xx_uart_start_tx(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	struct ast_uart_priv_data *priv = up->port.private_data;
> +
> +	pr_debug("line[%d]\n", port->line);
> +	tasklet_schedule(&priv->tx_tasklet);
> +}
> +
> +static void ast25xx_uart_stop_rx(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +
> +	pr_debug("line[%d]\n", port->line);
> +	up->ier &= ~UART_IER_RLSI;
> +	up->port.read_status_mask &= ~UART_LSR_DR;
> +	ast_serial_out(up, UART_IER, up->ier);
> +}
> +
> +static void ast25xx_uart_enable_ms(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +
> +	pr_debug("line[%d]\n", port->line);
> +	up->ier |= UART_IER_MSI;
> +	ast_serial_out(up, UART_IER, up->ier);
> +}
> +
> +static void transmit_chars(struct uart_8250_port *up)
> +{
> +	struct circ_buf *xmit = &up->port.state->xmit;
> +	int count;
> +
> +	if (up->port.x_char) {
> +		serial_outp(up, UART_TX, up->port.x_char);
> +		up->port.icount.tx++;
> +		up->port.x_char = 0;
> +		return;
> +	}
> +	if (uart_tx_stopped(&up->port)) {
> +		ast25xx_uart_stop_tx(&up->port);
> +		return;
> +	}
> +	if (uart_circ_empty(xmit)) {
> +		__stop_tx(up);
> +		return;
> +	}
> +
> +	count = up->tx_loadsz;
> +	do {
> +		ast_serial_out(up, UART_TX, xmit->buf[xmit->tail]);
> +		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
> +		up->port.icount.tx++;
> +		if (uart_circ_empty(xmit))
> +			break;
> +	} while (--count > 0);
> +
> +	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
> +		uart_write_wakeup(&up->port);
> +
> +	if (uart_circ_empty(xmit))
> +		__stop_tx(up);
> +}
> +
> +static unsigned int check_modem_status(struct uart_8250_port *up)
> +{
> +	unsigned int status = ast_serial_in(up, UART_MSR);
> +
> +	pr_debug("line[%d]\n", up->port.line);
> +	status |= up->msr_saved_flags;
> +	up->msr_saved_flags = 0;
> +	if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI
> +					&& up->port.state != NULL) {
> +		if (status & UART_MSR_TERI)
> +			up->port.icount.rng++;
> +		if (status & UART_MSR_DDSR)
> +			up->port.icount.dsr++;
> +		if (status & UART_MSR_DDCD)
> +			uart_handle_dcd_change(&up->port,
> +					status & UART_MSR_DCD);
> +		if (status & UART_MSR_DCTS)
> +			uart_handle_cts_change(&up->port,
> +					status & UART_MSR_CTS);
> +
> +		wake_up_interruptible(&up->port.state->port.delta_msr_wait);
> +	}
> +
> +	return status;
> +}
> +
> +/*
> + * This handles the interrupt from one port.
> + */
> +static inline void ast25xx_uart_handle_port(struct uart_8250_port *up)
> +{
> +	unsigned int status;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&up->port.lock, flags);
> +
> +	status = serial_inp(up, UART_LSR);
> +
> +	pr_debug("status = %x\n", status);
> +
> +	check_modem_status(up);
> +	if (status & UART_LSR_THRE)
> +		transmit_chars(up);
> +
> +	spin_unlock_irqrestore(&up->port.lock, flags);
> +}
> +
> +/*
> + * This is the serial driver's interrupt routine.
> + */
> +static irqreturn_t ast_uart_interrupt(int irq, void *dev_id)
> +{
> +	struct irq_info *i = dev_id;
> +	int pass_counter = 0, handled = 0, end = 0;
> +
> +	pr_debug("(%d)-", irq);
> +	spin_lock(&i->lock);
> +
> +	do {
> +		struct uart_8250_port *up;
> +		unsigned int iir;
> +
> +		up = (struct uart_8250_port *)(i->up);
> +
> +		iir = ast_serial_in(up, UART_IIR);
> +		if (!(iir & UART_IIR_NO_INT)) {
> +			ast25xx_uart_handle_port(up);
> +			handled = 1;
> +
> +		} else
> +			end = 1;
> +
> +		if (pass_counter++ > PASS_LIMIT) {
> +			/* If we hit this, we're dead. */
> +			pr_err("ast-uart-dma:too much work for irq%d\n", irq);
> +			break;
> +		}
> +	} while (end);
> +
> +	spin_unlock(&i->lock);
> +
> +	pr_debug("-(%d)\n", irq);
> +
> +	return IRQ_RETVAL(handled);
> +}
> +
> +static unsigned int ast25xx_uart_tx_empty(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	unsigned long flags;
> +	unsigned int lsr;
> +
> +	pr_debug("line[%d]\n", up->port.line);
> +
> +	spin_lock_irqsave(&up->port.lock, flags);
> +	lsr = ast_serial_in(up, UART_LSR);
> +	up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
> +	spin_unlock_irqrestore(&up->port.lock, flags);
> +
> +	return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
> +}
> +
> +static unsigned int ast25xx_uart_get_mctrl(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	unsigned int status;
> +	unsigned int ret;
> +
> +	status = check_modem_status(up);
> +
> +	ret = 0;
> +	if (status & UART_MSR_DCD)
> +		ret |= TIOCM_CAR;
> +	if (status & UART_MSR_RI)
> +		ret |= TIOCM_RNG;
> +	if (status & UART_MSR_DSR)
> +		ret |= TIOCM_DSR;
> +	if (status & UART_MSR_CTS)
> +		ret |= TIOCM_CTS;
> +	return ret;
> +}
> +
> +static void ast25xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	unsigned char mcr = 0;
> +
> +	mctrl = 0;
> +
> +	if (mctrl & TIOCM_RTS)
> +		mcr |= UART_MCR_RTS;
> +	if (mctrl & TIOCM_DTR)
> +		mcr |= UART_MCR_DTR;
> +	if (mctrl & TIOCM_OUT1)
> +		mcr |= UART_MCR_OUT1;
> +	if (mctrl & TIOCM_OUT2)
> +		mcr |= UART_MCR_OUT2;
> +	if (mctrl & TIOCM_LOOP)
> +		mcr |= UART_MCR_LOOP;
> +
> +	mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
> +
> +	ast_serial_out(up, UART_MCR, mcr);
> +
> +}
> +
> +static void ast25xx_uart_break_ctl(struct uart_port *port, int break_state)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&up->port.lock, flags);
> +	if (break_state == -1)
> +		up->lcr |= UART_LCR_SBC;
> +	else
> +		up->lcr &= ~UART_LCR_SBC;
> +	ast_serial_out(up, UART_LCR, up->lcr);
> +	spin_unlock_irqrestore(&up->port.lock, flags);
> +}
> +
> +static int ast25xx_uart_startup(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	// TX DMA
> +	struct circ_buf *xmit = &up->port.state->xmit;
> +	struct ast_uart_priv_data *priv = up->port.private_data;
> +	unsigned long flags;
> +	unsigned char lsr, iir;
> +	int retval;
> +	int irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
> +
> +	priv->up = up;
> +	pr_debug("line[%d]\n", port->line);
> +	up->capabilities = uart_config[up->port.type].flags;
> +	up->mcr = 0;
> +	/*
> +	 * Clear the FIFO buffers and disable them.
> +	 * (they will be reenabled in set_termios())
> +	 */
> +	ast25xx_uart_clear_fifos(up);
> +	/*
> +	 * Clear the interrupt registers.
> +	 */
> +	(void)serial_inp(up, UART_LSR);
> +	(void)serial_inp(up, UART_RX);
> +	(void)serial_inp(up, UART_IIR);
> +	(void)serial_inp(up, UART_MSR);
> +
> +	ast_uart_irq[0].up = up;
> +	retval = request_irq(up->port.irq, ast_uart_interrupt, irq_flags,
> +		       "ast-uart-dma", ast_uart_irq);
> +	if (retval)
> +		return retval;
> +
> +	/*
> +	 * Now, initialize the UART
> +	 */
> +	serial_outp(up, UART_LCR, UART_LCR_WLEN8);
> +
> +	spin_lock_irqsave(&up->port.lock, flags);
> +	up->port.mctrl |= TIOCM_OUT2;
> +
> +	ast25xx_uart_set_mctrl(&up->port, up->port.mctrl);
> +
> +	/*
> +	 * Do a quick test to see if we receive an
> +	 * interrupt when we enable the TX irq.
> +	 */
> +	serial_outp(up, UART_IER, UART_IER_THRI);
> +	lsr = ast_serial_in(up, UART_LSR);
> +	iir = ast_serial_in(up, UART_IIR);
> +	serial_outp(up, UART_IER, 0);
> +
> +	if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
> +		if (!(up->bugs & UART_BUG_TXEN)) {
> +			up->bugs |= UART_BUG_TXEN;
> +			pr_debug("ttyDMA%d-enabling bad tx status\n",
> +								 port->line);
> +		}
> +	} else {
> +		up->bugs &= ~UART_BUG_TXEN;
> +	}
> +
> +	spin_unlock_irqrestore(&up->port.lock, flags);
> +
> +	/*
> +	 * Clear the interrupt registers again for luck, and clear the
> +	 * saved flags to avoid getting false values from polling
> +	 * routines or the previous session.
> +	 */
> +	serial_inp(up, UART_LSR);
> +	serial_inp(up, UART_RX);
> +	serial_inp(up, UART_IIR);
> +	serial_inp(up, UART_MSR);
> +	up->lsr_saved_flags = 0;
> +	up->msr_saved_flags = 0;
> +
> +	// RX DMA
> +	priv->rx_dma_buf.head = 0;
> +	priv->rx_dma_buf.tail = 0;
> +	up->port.icount.rx = 0;
> +
> +	priv->tx_done = 1;
> +	priv->tx_count = 0;
> +
> +	priv->rx_dma_buf.head = 0;
> +	priv->rx_dma_buf.tail = 0;
> +#ifdef SDDMA_RX_FIX
> +#else
> +	priv->workaround = 0;
> +#endif
> +	// pr_debug("Sending trigger for % x\n", priv->dma_ch);
> +	ast_uart_rx_sdma_ctrl(priv->dma_ch, AST_UART_DMAOP_STOP);
> +	ast_uart_rx_sdma_ctrl(priv->dma_ch, AST_UART_DMAOP_TRIGGER);
> +#ifdef SDDMA_RX_FIX
> +#else
> +	add_timer(&priv->rx_timer);
> +#endif
> +	priv->tx_dma_buf.head = 0;
> +	priv->tx_dma_buf.tail = 0;
> +	priv->tx_dma_buf.buf = xmit->buf;
> +
> +	pr_debug("head:0x%x tail:0x%x\n", xmit->head, xmit->tail);
> +	xmit->head = 0;
> +	xmit->tail = 0;
> +
> +	priv->dma_tx_addr = dma_map_single(port->dev, priv->tx_dma_buf.buf,
> +				   UART_XMIT_SIZE, DMA_TO_DEVICE);
> +
> +	ast_uart_tx_sdma_ctrl(priv->dma_ch, AST_UART_DMAOP_STOP);
> +	ast_uart_tx_sdma_enqueue(priv->dma_ch, priv->dma_tx_addr);
> +	ast_uart_tx_sdma_update(priv->dma_ch, 0);
> +	ast_uart_tx_sdma_ctrl(priv->dma_ch, AST_UART_DMAOP_TRIGGER);
> +	return 0;
> +}
> +
> +static void ast25xx_uart_shutdown(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	struct ast_uart_priv_data *priv = up->port.private_data;
> +	unsigned long flags;
> +
> +	pr_debug("line[%d]\n", port->line);
> +	priv->up = NULL;
> +
> +	up->ier = 0;
> +	serial_outp(up, UART_IER, 0);
> +
> +	spin_lock_irqsave(&up->port.lock, flags);
> +	up->port.mctrl &= ~TIOCM_OUT2;
> +
> +	ast25xx_uart_set_mctrl(&up->port, up->port.mctrl);
> +	spin_unlock_irqrestore(&up->port.lock, flags);
> +
> +	/*
> +	 * Disable break condition and FIFOs
> +	 */
> +	ast_serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
> +	ast25xx_uart_clear_fifos(up);
> +
> +	(void)ast_serial_in(up, UART_RX);
> +
> +	ast_uart_rx_sdma_ctrl(priv->dma_ch, AST_UART_DMAOP_PAUSE);
> +	ast_uart_tx_sdma_ctrl(priv->dma_ch, AST_UART_DMAOP_PAUSE);
> +#ifdef SDDMA_RX_FIX
> +#else
> +	del_timer_sync(&up->rx_timer);
> +#endif
> +
> +	// Tx buffer will free by serial_core.c
> +	free_irq(up->port.irq, ast_uart_irq);
> +}
> +
> +static unsigned int ast25xx_uart_get_divisor(struct uart_port *port,
> +					   unsigned int baud)
> +{
> +	unsigned int quot;
> +
> +	quot = uart_get_divisor(port, baud);
> +
> +	return quot;
> +}
> +
> +static void ast25xx_uart_set_termios(struct uart_port *port,
> +				   struct ktermios *termios,
> +				   struct ktermios *old)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	unsigned char cval, fcr = 0;
> +	unsigned long flags;
> +	unsigned int baud, quot;
> +
> +	switch (termios->c_cflag & CSIZE) {
> +	case CS5:
> +		cval = UART_LCR_WLEN5;
> +		break;
> +	case CS6:
> +		cval = UART_LCR_WLEN6;
> +		break;
> +	case CS7:
> +		cval = UART_LCR_WLEN7;
> +		break;
> +	default:
> +	case CS8:
> +		cval = UART_LCR_WLEN8;
> +		break;
> +	}
> +
> +	if (termios->c_cflag & CSTOPB)
> +		cval |= UART_LCR_STOP;
> +	if (termios->c_cflag & PARENB)
> +		cval |= UART_LCR_PARITY;
> +	if (!(termios->c_cflag & PARODD))
> +		cval |= UART_LCR_EPAR;
> +#ifdef CMSPAR
> +	if (termios->c_cflag & CMSPAR)
> +		cval |= UART_LCR_SPAR;
> +#endif
> +
> +	/*
> +	 * Ask the core to calculate the divisor for us.
> +	 */
> +	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
> +	quot = ast25xx_uart_get_divisor(port, baud);
> +
> +	if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
> +		if (baud < 2400)
> +			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
> +		else
> +			fcr = uart_config[up->port.type].fcr;
> +	}
> +
> +	/*
> +	 * Ok, we're now changing the port state.  Do it with
> +	 * interrupts disabled.
> +	 */
> +	spin_lock_irqsave(&up->port.lock, flags);
> +
> +	/*
> +	 * Update the per-port timeout.
> +	 */
> +	uart_update_timeout(port, termios->c_cflag, baud);
> +
> +	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
> +	if (termios->c_iflag & INPCK)
> +		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
> +	if (termios->c_iflag & (BRKINT | PARMRK))
> +		up->port.read_status_mask |= UART_LSR_BI;
> +
> +	/*
> +	 * Characteres to ignore
> +	 */
> +	up->port.ignore_status_mask = 0;
> +	if (termios->c_iflag & IGNPAR)
> +		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
> +	if (termios->c_iflag & IGNBRK) {
> +		up->port.ignore_status_mask |= UART_LSR_BI;
> +	/*
> +	 * If we're ignoring parity and break indicators,
> +	 * ignore overruns too (for real raw support).
> +	 */
> +	if (termios->c_iflag & IGNPAR)
> +		up->port.ignore_status_mask |= UART_LSR_OE;
> +	}
> +
> +	/*
> +	 * ignore all characters if CREAD is not set
> +	 */
> +	if ((termios->c_cflag & CREAD) == 0)
> +		up->port.ignore_status_mask |= UART_LSR_DR;
> +
> +	/*
> +	 * CTS flow control flag and modem status interrupts
> +	 */
> +	up->ier &= ~UART_IER_MSI;
> +	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
> +		up->ier |= UART_IER_MSI;
> +
> +	ast_serial_out(up, UART_IER, up->ier);
> +
> +	serial_outp(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
> +
> +	serial_dl_write(up, quot);
> +
> +	/*
> +	 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
> +	 * is written without DLAB set, this mode will be disabled.
> +	 */
> +
> +	serial_outp(up, UART_LCR, cval); /* reset DLAB */
> +	up->lcr = cval;                  /* Save LCR */
> +	if (fcr & UART_FCR_ENABLE_FIFO) {
> +	/* emulated UARTs (Lucent Venus 167x) need two steps */
> +		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
> +	}
> +	serial_outp(up, UART_FCR, fcr); /* set fcr */
> +	ast25xx_uart_set_mctrl(&up->port, up->port.mctrl);
> +	spin_unlock_irqrestore(&up->port.lock, flags);
> +	/* Don't rewrite B0 */
> +	if (tty_termios_baud_rate(termios))
> +		tty_termios_encode_baud_rate(termios, baud, baud);
> +}
> +
> +/*
> + * Resource handling.
> + */
> +static int ast25xx_uart_request_std_resource(struct uart_8250_port  *up)
> +{
> +	unsigned int size = 8 << up->port.regshift;
> +	int ret = 0;
> +
> +	if (!up->port.mapbase)
> +		return ret;
> +
> +	if (!request_mem_region(up->port.mapbase, size, "ast-uart-dma")) {
> +		ret = -EBUSY;
> +		return ret;
> +	}
> +
> +	if (up->port.flags & UPF_IOREMAP) {
> +		up->port.membase = ioremap_nocache(up->port.mapbase, size);
> +		if (!up->port.membase) {
> +			release_mem_region(up->port.mapbase, size);
> +			ret = -ENOMEM;
> +			return ret;
> +		}
> +	}
> +	return ret;
> +}
> +
> +static void ast25xx_uart_release_std_resource(struct uart_8250_port *up)
> +{
> +	unsigned int size = 8 << up->port.regshift;
> +
> +	if (!up->port.mapbase)
> +		return;
> +
> +	if (up->port.flags & UPF_IOREMAP) {
> +		iounmap(up->port.membase);
> +		up->port.membase = NULL;
> +	}
> +
> +	release_mem_region(up->port.mapbase, size);
> +}
> +
> +static void ast25xx_uart_release_port(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +
> +	ast25xx_uart_release_std_resource(up);
> +}
> +
> +static int ast25xx_uart_request_port(struct uart_port *port)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	int ret;
> +
> +	ret = ast25xx_uart_request_std_resource(up);
> +	if (ret == 0)
> +		ast25xx_uart_release_std_resource(up);
> +
> +	return ret;
> +}
> +
> +static void ast25xx_uart_config_port(struct uart_port *port, int flags)
> +{
> +	struct uart_8250_port *up = to_uart_8250_port(port);
> +	int ret;
> +
> +	/*
> +	 * Find the region that we can probe for.  This in turn
> +	 * tells us whether we can probe for the type of port.
> +	 */
> +	ret = ast25xx_uart_request_std_resource(up);
> +	if (ret < 0)
> +		return;
> +
> +	if (flags & UART_CONFIG_TYPE)
> +		autoconfig(up);
> +
> +	if (up->port.type == PORT_UNKNOWN)
> +		ast25xx_uart_release_std_resource(up);
> +}
> +
> +static int ast25xx_uart_verify_port(struct uart_port *port,
> +				  struct serial_struct *ser)
> +{
> +	return 0;
> +}
> +
> +static const char *ast25xx_uart_type(struct uart_port *port)
> +{
> +	int type = port->type;
> +
> +	if (type >= ARRAY_SIZE(uart_config))
> +		type = 0;
> +	return uart_config[type].name;
> +}
> +
> +
> +
> +static unsigned int ast25xx_uart_serial_in(struct uart_port *port, int offset)
> +{
> +	offset = offset << port->regshift;
> +	return readb(port->membase + offset);
> +
> +}
> +
> +
> +static void ast25xx_uart_serial_out(struct uart_port *port,
> +						 int offset, int value)
> +{
> +	offset =  offset << port->regshift;
> +	writeb(value, port->membase + offset);
> +}
> +
> +static const struct uart_ops ast25xx_uart_pops = {
> +	.tx_empty = ast25xx_uart_tx_empty,
> +	.set_mctrl = ast25xx_uart_set_mctrl,
> +	.get_mctrl = ast25xx_uart_get_mctrl,
> +	.stop_tx = ast25xx_uart_stop_tx,
> +	.start_tx = ast25xx_uart_start_tx,
> +	.stop_rx = ast25xx_uart_stop_rx,
> +	.enable_ms = ast25xx_uart_enable_ms,
> +	.break_ctl = ast25xx_uart_break_ctl,
> +	.startup = ast25xx_uart_startup,
> +	.shutdown = ast25xx_uart_shutdown,
> +	.set_termios = ast25xx_uart_set_termios,
> +	.type = ast25xx_uart_type,
> +	.release_port = ast25xx_uart_release_port,
> +	.request_port = ast25xx_uart_request_port,
> +	.config_port = ast25xx_uart_config_port,
> +	.verify_port = ast25xx_uart_verify_port,
> +};
> +
> +
> +
> +/*
> + * Register a set of serial devices attached to a platform device.  The
> + * list is terminated with a zero flags entry, which means we expect
> + * all entries to have at least UPF_BOOT_AUTOCONF set.
> + */
> +struct clk *clk;

static?


> +
> +static int ast25xx_uart_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct ast_uart_priv_data *priv;
> +	struct uart_8250_port port_8250;
> +	struct uart_8250_port *up;
> +	int ret;
> +	u32 read, dma_channel = 0;
> +	struct resource *res;
> +
> +	if (UART_XMIT_SIZE > DMA_BUFF_SIZE)
> +		pr_debug("UART_XMIT_SIZE > DMA_BUFF_SIZE : Please Check\n");
> +
> +	priv = (struct ast_uart_priv_data *)devm_kzalloc(&pdev->dev,
> +			sizeof(struct ast_uart_priv_data), GFP_KERNEL);
> +	if (priv == NULL)
> +		return -ENOMEM;
> +
> +	up = &port_8250;
> +	memset(up, 0, sizeof(struct uart_8250_port));
> +	up->port.flags = UPF_IOREMAP;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (res == NULL) {
> +		dev_err(&pdev->dev, "IRQ resource not found");
> +		return -ENODEV;
> +	}
> +	up->port.irq = res->start;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		dev_err(&pdev->dev, "Register base not found");
> +		return -ENODEV;
> +	}
> +	up->port.mapbase = res->start;
> +
> +	ret = ast25xx_uart_request_std_resource(up);
> +	if (ret) {
> +		dev_err(&pdev->dev, "ioremap_nocache Failed");
> +		return ret;
> +	}
> +
> +	clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(clk))
> +		dev_err(&pdev->dev, "missing controller clock");
> +
> +	ret = clk_prepare_enable(clk);
> +	if (ret)
> +		dev_err(&pdev->dev, "failed to enable DMA UART Clk");
> +
> +	up->port.uartclk = clk_get_rate(clk);
> +
> +	if (of_property_read_u32(np, "reg-shift", &read) == 0)
> +		up->port.regshift = read;
> +	if (of_property_read_u32(np, "dma-channel", &read) == 0) {
> +		dma_channel = read;
> +		priv->dma_ch = dma_channel;
> +	}
> +	up->port.iotype = UPIO_MEM;
> +	up->port.flags |= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
> +	up->port.dev        = &pdev->dev;
> +	if (share_irqs)
> +		up->port.flags |= UPF_SHARE_IRQ;
> +	up->port.fifosize = uart_config[up->port.type].fifo_size;
> +	up->port.type = PORT_16550;
> +	up->port.iotype = UPIO_MEM;
> +	up->port.flags =  UPF_FIXED_TYPE;
> +	up->port.startup = ast25xx_uart_startup;
> +	up->port.shutdown = ast25xx_uart_shutdown;
> +	up->port.set_termios = ast25xx_uart_set_termios;
> +	up->port.set_mctrl = ast25xx_uart_set_mctrl;
> +	up->port.serial_in = ast25xx_uart_serial_in;
> +	up->port.serial_out = ast25xx_uart_serial_out;
> +	up->capabilities = uart_config[up->port.type].flags;
> +	up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
> +	up->capabilities |= UART_CAP_FIFO;
> +
> +	up->port.private_data = priv;
> +
> +	ret = serial8250_register_8250_port(up);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev,
> +		"unable to registr port (IO%lx MEM%llx IRQ%d):%d\n",
> +			up->port.iobase, (unsigned long long)up->port.mapbase,
> +							 up->port.irq, ret);
> +		return ret;
> +	}
> +	priv->line = ret;
> +
> +	tasklet_init(&priv->tx_tasklet, ast_uart_tx_sdma_tasklet_func,
> +							 (unsigned long)priv);
> +#ifdef SDDMA_RX_FIX
> +	tasklet_init(&priv->rx_tasklet, ast_uart_rx_sdma_tasklet_func,
> +							 (unsigned long)priv);
> +#else
> +	uart->rx_timer.data = (unsigned long)port;
> +	uart->rx_timer.expires = jiffies + (HZ);
> +	uart->rx_timer.function = ast_uart_rx_timer_func;
> +	init_timer(&priv->rx_timer);
> +#endif
> +
> +//DMA request
> +#ifdef SDDMA_RX_FIX
> +	priv->rx_dma_buf.buf =
> +	ast_uart_rx_sdma_request(priv->dma_ch, ast_uart_rx_buffdone,
> +			      priv);
> +	if (priv->rx_dma_buf.buf < 0) {
> +		pr_debug("Error : failed to get rx dma channel[%d]\n",
> +						 priv->dma_ch);
> +		return -EBUSY;
> +}
> +#else
> +	priv->rx_dma_buf.buf = ast_uart_rx_sdma_request(
> +	priv->dma_ch, priv);
> +	if (priv->rx_dma_buf.buf < 0) {
> +		pr_debug("Error : failed to get rx dma channel[%d]\n",
> +						 priv->dma_ch);
> +		return -EBUSY;
> +	}
> +#endif
> +	if (ast_uart_tx_sdma_request(
> +			priv->dma_ch, ast_uart_tx_buffdone, priv) < 0) {
> +		pr_debug("Error : failed to get tx dma channel[%d]\n",
> +						 priv->dma_ch);
> +		return -EBUSY;
> +	}
> +
> +	platform_set_drvdata(pdev, priv);
> +	return 0;
> +}
> +
> +/*
> + * Remove serial ports registered against a platform device.
> + */
> +static int ast25xx_uart_remove(struct platform_device *pdev)
> +{
> +	struct ast_uart_priv_data *priv;
> +
> +	priv = platform_get_drvdata(pdev);
> +	serial8250_unregister_port(priv->line);
> +	return 0;
> +}
> +
> +static int ast25xx_uart_suspend(struct platform_device *pdev,
> +			      pm_message_t state)
> +{
> +	struct ast_uart_priv_data *priv;
> +
> +	priv = platform_get_drvdata(pdev);
> +	serial8250_suspend_port(priv->line);
> +	return 0;
> +}
> +
> +static int ast25xx_uart_resume(struct platform_device *pdev)
> +{
> +	struct ast_uart_priv_data *priv;
> +
> +	priv = platform_get_drvdata(pdev);
> +	serial8250_resume_port(priv->line);
> +	return 0;
> +}
> +
> +static const struct of_device_id ast_serial_dt_ids[] = {
> +	{ .compatible = "aspeed,ast-sdma-uart", },
> +	{ /* sentinel */ }
> +};
> +
> +static struct platform_driver ast25xx_uart_driver = {
> +	.probe = ast25xx_uart_probe,
> +	.remove = ast25xx_uart_remove,
> +	.suspend = ast25xx_uart_suspend,
> +	.resume = ast25xx_uart_resume,
> +	.driver = {
> +	    .name = "ast-uart-dma",
> +	    .of_match_table = of_match_ptr(ast_serial_dt_ids),

Indent properly.

This whole file looks like it can be made smaller, please remove the
unneeded and unused code for your next submission.

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices.
From: Greg KH @ 2019-07-03 17:25 UTC (permalink / raw)
  To: jeyentam; +Cc: linux-serial, linux-kernel
In-Reply-To: <20190702032323.28967-1-je.yen.tam@ni.com>

On Mon, Jul 01, 2019 at 08:23:23PM -0700, jeyentam wrote:
> Add support for NI-Serial PXIe-RS232, PXI-RS485 and PXIe-RS485 devices.
> 
> Signed-off-by: jeyentam <je.yen.tam@ni.com>
> ---
>  drivers/tty/serial/8250/8250_pci.c | 879 +++++++++++++++++++----------
>  1 file changed, 582 insertions(+), 297 deletions(-)
> 
> diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
> index df41397de478..0a711b895b33 100644
> --- a/drivers/tty/serial/8250/8250_pci.c
> +++ b/drivers/tty/serial/8250/8250_pci.c
> @@ -1,10 +1,10 @@
>  // SPDX-License-Identifier: GPL-2.0
>  /*
> - *  Probe module for 8250/16550-type PCI serial ports.
> + *	Probe module for 8250/16550-type PCI serial ports.
>   *
> - *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
> + *	Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
>   *
> - *  Copyright (C) 2001 Russell King, All Rights Reserved.
> + *	Copyright (C) 2001 Russell King, All Rights Reserved.
>   */

Why are you changing comments for no reason?

^ permalink raw reply

* Re: [PATCH V2 1/2] serial/8250: Add support for NI-Serial PXI/PXIe+485 devices
From: Greg KH @ 2019-07-03 15:59 UTC (permalink / raw)
  To: Enrico Weigelt, metux IT consult; +Cc: jeyentam, linux-serial, linux-kernel
In-Reply-To: <d6910b29-3ba6-4a3b-04e2-bc7c3c012554@metux.net>

On Wed, Jul 03, 2019 at 05:41:25PM +0200, Enrico Weigelt, metux IT consult wrote:
> On 03.07.19 16:47, Greg KH wrote:
> > On Wed, Jul 03, 2019 at 03:27:11PM +0200, Enrico Weigelt, metux IT consult wrote:
> >>>  /* UART Port Control Register */> -#define NI8430_PORTCON	0x0f> -#define NI8430_PORTCON_TXVR_ENABLE	(1 << 3)
> >> Can we have that renaming as a separate patch, to ease review ?
> >>
> >> And what about introducing a config sym for the new device specific
> >> stuff ? These devices seem to be pretty rare - never seen them in
> >> embeded world, where we do need to care of kernel size.
> > 
> > No, that's not the way this driver works, sorry.
> 
> That's sad, because in embedded world we often have to care about
> code size, so making those devices optional would be of great help.

Really?  are you sure?  Try it and see what you really end up saving.

greg k-h

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox