[PATCH v3 0/4] tty: TX helpers

Arnd Bergmann arnd at arndb.de
Wed Sep 7 07:56:03 PDT 2022


On Wed, Sep 7, 2022, at 3:52 PM, Russell King (Oracle) wrote:
> On Wed, Sep 07, 2022 at 02:36:37PM +0200, Greg Kroah-Hartman wrote:
>
> Of course, it would have been nicer to see the definition of this
> macro, because then we can understand what the "ch" argument is to
> this macro, and how that relates to the macro argument that is
> shown in the example as a writel().

I pulled out the 'ch' variable from the macro to avoid having
the macro define local variables that are then passed to the
inner expressions. 

> Maybe a more complete example would help clear up the confusion?
> Arnd?

Here is a patch on top of the series that would implement the
uart_port_tx_helper_limited() and uart_port_tx_helper()
macros that can be used directly from drivers in place of defining
local functions, with the (alphabetically) first two drivers
converted to that.

I left the (now trivial) DEFINE_UART_PORT_TX_HELPER_LIMITED() and
DEFINE_UART_PORT_TX_HELPER() macros in place to keep it building,
but they would get removed if we decide to use something like
my suggested approach for all drivers.

   Arnd

diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c
index 40cf1bb534f3..a0f5c59d6128 100644
--- a/drivers/tty/serial/21285.c
+++ b/drivers/tty/serial/21285.c
@@ -151,16 +151,14 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static DEFINE_UART_PORT_TX_HELPER_LIMITED(serial21285_do_tx_chars,
-		!(*CSR_UARTFLG & 0x20),
-		*CSR_UARTDR = ch,
-		({}));
-
 static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
 {
 	struct uart_port *port = dev_id;
+	unsigned int count = 256;
+	unsigned char ch;
 
-	serial21285_do_tx_chars(port, 256);
+	uart_port_tx_helper_limited(port, !(*CSR_UARTFLG & 0x20),
+				    *CSR_UARTDR = ch, ({}), count, ch);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 70c0ad431cf9..f81dd950cd39 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -246,10 +246,14 @@ static void altera_uart_rx_chars(struct altera_uart *pp)
 	tty_flip_buffer_push(&port->state->port);
 }
 
-static DEFINE_UART_PORT_TX_HELPER(altera_uart_tx_chars,
-		altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
-		                ALTERA_UART_STATUS_TRDY_MSK,
-		altera_uart_writel(port, ch, ALTERA_UART_TXDATA_REG));
+static int altera_uart_tx_chars(struct uart_port *port)
+{
+	u8 ch;
+
+	return uart_port_tx_helper(port, 
+		altera_uart_readl(port, ALTERA_UART_STATUS_REG) & ALTERA_UART_STATUS_TRDY_MSK,
+		altera_uart_writel(port, ch, ALTERA_UART_TXDATA_REG), ch);
+}
 
 static irqreturn_t altera_uart_interrupt(int irq, void *data)
 {
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 7236fc76ba22..d48d2301d1b7 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -638,13 +638,11 @@ struct uart_driver {
 
 void uart_write_wakeup(struct uart_port *port);
 
-#define __DEFINE_UART_PORT_TX_HELPER(name, tx_ready, put_char, tx_done,	  \
-		for_test, for_post, ...)				  \
-unsigned int name(struct uart_port *port __VA_OPT__(,) __VA_ARGS__)	  \
-{									  \
+#define __uart_port_tx_helper(port, tx_ready, put_char, tx_done,	  \
+	       	for_test, for_post, ch)					  \
+({									  \
 	struct circ_buf *xmit = &port->state->xmit;			  \
 	unsigned int pending;						  \
-	u8 ch;								  \
 									  \
 	for (; (for_test) && (tx_ready); (for_post), port->icount.tx++) { \
 		if (port->x_char) {					  \
@@ -672,8 +670,15 @@ unsigned int name(struct uart_port *port __VA_OPT__(,) __VA_ARGS__)	  \
 			port->ops->stop_tx(port);			  \
 	}								  \
 									  \
-	return pending;							  \
-}
+	pending;							  \
+})
+
+#define uart_port_tx_helper_limited(port, tx_ready, put_char, tx_done, count, ch) \
+	__uart_port_tx_helper(port, tx_ready, put_char, tx_done, count, count--, ch)
+
+#define uart_port_tx_helper(port, tx_ready, put_char, ch)		  \
+	__uart_port_tx_helper(port, tx_ready, put_char, ({}), true, ({}), ch)
+
 
 /**
  * DEFINE_UART_PORT_TX_HELPER_LIMITED -- generate transmit helper for uart_port
@@ -703,9 +708,13 @@ unsigned int name(struct uart_port *port __VA_OPT__(,) __VA_ARGS__)	  \
  * For all of them, @port->lock is held, interrupts are locally disabled and
  * the expressions must not sleep.
  */
-#define DEFINE_UART_PORT_TX_HELPER_LIMITED(name, tx_ready, put_char, tx_done) \
-	__DEFINE_UART_PORT_TX_HELPER(name, tx_ready, put_char, tx_done,	      \
-			count, count--, unsigned int count)
+#define DEFINE_UART_PORT_TX_HELPER_LIMITED(name, tx_ready, put_char, tx_done)	\
+unsigned int name(struct uart_port *port, unsigned int count)			\
+{										\
+	u8 ch;									\
+	return uart_port_tx_helper_limited(port, tx_ready, put_char, tx_done,	\
+					   count, ch);				\
+}
 
 /**
  * DEFINE_UART_PORT_TX_HELPER -- generate transmit helper for uart_port
@@ -715,9 +724,12 @@ unsigned int name(struct uart_port *port __VA_OPT__(,) __VA_ARGS__)	  \
  *
  * See DEFINE_UART_PORT_TX_HELPER_LIMITED() for more details.
  */
-#define DEFINE_UART_PORT_TX_HELPER(name, tx_ready, put_char)		\
-	__DEFINE_UART_PORT_TX_HELPER(name, tx_ready, put_char, ({}),	\
-			true, ({}))
+#define DEFINE_UART_PORT_TX_HELPER(name, tx_ready, put_char, ...)	  \
+unsigned int name(struct uart_port *port __VA_OPT__(,) __VA_ARGS__)	  \
+{									  \
+	u8 ch;								  \
+	return uart_port_tx_helper(port, tx_ready, put_char, ch);	  \
+}
 
 /*
  * Baud rate helpers.




More information about the linux-riscv mailing list