Merge tag 'tty-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
[sfrench/cifs-2.6.git] / include / linux / serial_core.h
index 91871464b99d36d51d86691e413a3f1b2bcb6408..fd59f600094a0673fd76af07583687ba910eaad3 100644 (file)
@@ -664,6 +664,86 @@ struct uart_driver {
 
 void uart_write_wakeup(struct uart_port *port);
 
+#define __uart_port_tx(uport, ch, tx_ready, put_char, tx_done, for_test,      \
+               for_post)                                                     \
+({                                                                           \
+       struct uart_port *__port = (uport);                                   \
+       struct circ_buf *xmit = &__port->state->xmit;                         \
+       unsigned int pending;                                                 \
+                                                                             \
+       for (; (for_test) && (tx_ready); (for_post), __port->icount.tx++) {   \
+               if (__port->x_char) {                                         \
+                       (ch) = __port->x_char;                                \
+                       (put_char);                                           \
+                       __port->x_char = 0;                                   \
+                       continue;                                             \
+               }                                                             \
+                                                                             \
+               if (uart_circ_empty(xmit) || uart_tx_stopped(__port))         \
+                       break;                                                \
+                                                                             \
+               (ch) = xmit->buf[xmit->tail];                                 \
+               (put_char);                                                   \
+               xmit->tail = (xmit->tail + 1) % UART_XMIT_SIZE;               \
+       }                                                                     \
+                                                                             \
+       (tx_done);                                                            \
+                                                                             \
+       pending = uart_circ_chars_pending(xmit);                              \
+       if (pending < WAKEUP_CHARS) {                                         \
+               uart_write_wakeup(__port);                                    \
+                                                                             \
+               if (pending == 0)                                             \
+                       __port->ops->stop_tx(__port);                         \
+       }                                                                     \
+                                                                             \
+       pending;                                                              \
+})
+
+/**
+ * uart_port_tx_limited -- transmit helper for uart_port with count limiting
+ * @port: uart port
+ * @ch: variable to store a character to be written to the HW
+ * @count: a limit of characters to send
+ * @tx_ready: can HW accept more data function
+ * @put_char: function to write a character
+ * @tx_done: function to call after the loop is done
+ *
+ * This helper transmits characters from the xmit buffer to the hardware using
+ * @put_char(). It does so until @count characters are sent and while @tx_ready
+ * evaluates to true.
+ *
+ * Returns: the number of characters in the xmit buffer when done.
+ *
+ * The expression in macro parameters shall be designed as follows:
+ *  * **tx_ready:** should evaluate to true if the HW can accept more data to
+ *    be sent. This parameter can be %true, which means the HW is always ready.
+ *  * **put_char:** shall write @ch to the device of @port.
+ *  * **tx_done:** when the write loop is done, this can perform arbitrary
+ *    action before potential invocation of ops->stop_tx() happens. If the
+ *    driver does not need to do anything, use e.g. ({}).
+ *
+ * For all of them, @port->lock is held, interrupts are locally disabled and
+ * the expressions must not sleep.
+ */
+#define uart_port_tx_limited(port, ch, count, tx_ready, put_char, tx_done) ({ \
+       unsigned int __count = (count);                                       \
+       __uart_port_tx(port, ch, tx_ready, put_char, tx_done, __count,        \
+                       __count--);                                           \
+})
+
+/**
+ * uart_port_tx -- transmit helper for uart_port
+ * @port: uart port
+ * @ch: variable to store a character to be written to the HW
+ * @tx_ready: can HW accept more data function
+ * @put_char: function to write a character
+ *
+ * See uart_port_tx_limited() for more details.
+ */
+#define uart_port_tx(port, ch, tx_ready, put_char)                     \
+       __uart_port_tx(port, ch, tx_ready, put_char, ({}), true, ({}))
+
 /*
  * Baud rate helpers.
  */