drop tx_fifo_size ... in favor of having what so far was called tx_empty() return the amount of space available. Note that in the pl011.c case, original code and comment disagreed, and I picked the conservative value for it's ->tx_ready() handler's return value. Signed-off-by: Jan Beulich --- a/xen/drivers/char/ehci-dbgp.c +++ b/xen/drivers/char/ehci-dbgp.c @@ -1204,7 +1204,7 @@ static void ehci_dbgp_putc(struct serial ehci_dbgp_flush(port); } -static int ehci_dbgp_tx_empty(struct serial_port *port) +static unsigned int ehci_dbgp_tx_ready(struct serial_port *port) { struct ehci_dbgp *dbgp = port->uart; @@ -1219,11 +1219,8 @@ static int ehci_dbgp_tx_empty(struct ser if ( dbgp->state != dbgp_idle && dbgp->out.chunk >= DBGP_MAX_PACKET ) return 0; - port->tx_fifo_size = DBGP_MAX_PACKET - dbgp->out.chunk; - if ( dbgp->state == dbgp_idle ) - port->tx_fifo_size += DBGP_MAX_PACKET; - - return 1; + return DBGP_MAX_PACKET - dbgp->out.chunk + + (dbgp->state == dbgp_idle) * DBGP_MAX_PACKET; } static int ehci_dbgp_getc(struct serial_port *port, char *pc) @@ -1347,7 +1344,6 @@ static void __init ehci_dbgp_init_preirq if ( ehci_dbgp_setup_preirq(dbgp) ) ehci_dbgp_status(dbgp, "ehci_dbgp_init_preirq complete"); - port->tx_fifo_size = DBGP_MAX_PACKET; dbgp->lock = &port->tx_lock; } @@ -1448,7 +1444,7 @@ static struct uart_driver __read_mostly .endboot = ehci_dbgp_endboot, .suspend = ehci_dbgp_suspend, .resume = ehci_dbgp_resume, - .tx_empty = ehci_dbgp_tx_empty, + .tx_ready = ehci_dbgp_tx_ready, .putc = ehci_dbgp_putc, .flush = ehci_dbgp_flush, .getc = ehci_dbgp_getc --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -38,7 +38,7 @@ string_param("com1", opt_com1); string_param("com2", opt_com2); static struct ns16550 { - int baud, clock_hz, data_bits, parity, stop_bits, irq; + int baud, clock_hz, data_bits, parity, stop_bits, fifo_size, irq; unsigned long io_base; /* I/O port or memory-mapped I/O address. */ char __iomem *remapped_io_base; /* Remapped virtual address of MMIO. */ /* UART with IRQ line: interrupt-driven I/O. */ @@ -185,10 +185,11 @@ static void ns16550_poll(void *data) #endif } -static int ns16550_tx_empty(struct serial_port *port) +static unsigned int ns16550_tx_ready(struct serial_port *port) { struct ns16550 *uart = port->uart; - return !!(ns_read_reg(uart, LSR) & LSR_THRE); + + return ns_read_reg(uart, LSR) & LSR_THRE ? uart->fifo_size : 0; } static void ns16550_putc(struct serial_port *port, char c) @@ -288,7 +289,7 @@ static void __init ns16550_init_preirq(s /* Check this really is a 16550+. Otherwise we have no FIFOs. */ if ( ((ns_read_reg(uart, IIR) & 0xc0) == 0xc0) && ((ns_read_reg(uart, FCR) & FCR_TRG14) == FCR_TRG14) ) - port->tx_fifo_size = 16; + uart->fifo_size = 16; } static void ns16550_setup_postirq(struct ns16550 *uart) @@ -321,7 +322,7 @@ static void __init ns16550_init_postirq( /* Calculate time to fill RX FIFO and/or empty TX FIFO for polling. */ bits = uart->data_bits + uart->stop_bits + !!uart->parity; uart->timeout_ms = max_t( - unsigned int, 1, (bits * port->tx_fifo_size * 1000) / uart->baud); + unsigned int, 1, (bits * uart->fifo_size * 1000) / uart->baud); if ( uart->irq > 0 ) { @@ -388,7 +389,7 @@ static struct uart_driver __read_mostly .endboot = ns16550_endboot, .suspend = ns16550_suspend, .resume = ns16550_resume, - .tx_empty = ns16550_tx_empty, + .tx_ready = ns16550_tx_ready, .putc = ns16550_putc, .getc = ns16550_getc, .irq = ns16550_irq @@ -642,6 +643,8 @@ void __init ns16550_init(int index, stru uart->stop_bits = defaults->stop_bits; uart->irq = defaults->irq; uart->io_base = defaults->io_base; + /* Default is no transmit FIFO. */ + uart->fifo_size = 1; ns16550_parse_port_config(uart, (index == 0) ? opt_com1 : opt_com2); } --- a/xen/drivers/char/pl011.c +++ b/xen/drivers/char/pl011.c @@ -156,9 +156,6 @@ static void __init pl011_init_preirq(str /* Enable the UART for RX and TX; no flow ctrl */ uart->regs[CR] = RXE | TXE | UARTEN; - - /* Tell the serial framework about our fine 156-character FIFO */ - port->tx_fifo_size = 16; } static void __init pl011_init_postirq(struct serial_port *port) @@ -192,10 +189,10 @@ static void pl011_resume(struct serial_p BUG(); // XXX } -static int pl011_tx_empty(struct serial_port *port) +static unsigned int pl011_tx_ready(struct serial_port *port) { struct pl011 *uart = port->uart; - return !!(uart->regs[FR] & TXFE); + return uart->regs[FR] & TXFE ? 16 : 0; } static void pl011_putc(struct serial_port *port, char c) @@ -227,7 +224,7 @@ static struct uart_driver __read_mostly .endboot = NULL, .suspend = pl011_suspend, .resume = pl011_resume, - .tx_empty = pl011_tx_empty, + .tx_ready = pl011_tx_ready, .putc = pl011_putc, .getc = pl011_getc, .irq = pl011_irq --- a/xen/drivers/char/serial.c +++ b/xen/drivers/char/serial.c @@ -59,7 +59,7 @@ void serial_rx_interrupt(struct serial_p void serial_tx_interrupt(struct serial_port *port, struct cpu_user_regs *regs) { - int i; + unsigned int i, n; unsigned long flags; local_irq_save(flags); @@ -71,23 +71,20 @@ void serial_tx_interrupt(struct serial_p */ while ( !spin_trylock(&port->tx_lock) ) { - if ( !port->driver->tx_empty(port) ) + if ( !port->driver->tx_ready(port) ) goto out; cpu_relax(); } - if ( port->driver->tx_empty(port) ) + for ( i = 0, n = port->driver->tx_ready(port); i < n; i++ ) { - for ( i = 0; i < port->tx_fifo_size; i++ ) - { - if ( port->txbufc == port->txbufp ) - break; - port->driver->putc( - port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]); - } - if ( i && port->driver->flush ) - port->driver->flush(port); + if ( port->txbufc == port->txbufp ) + break; + port->driver->putc( + port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]); } + if ( i && port->driver->flush ) + port->driver->flush(port); spin_unlock(&port->tx_lock); @@ -114,10 +111,11 @@ static void __serial_putc(struct serial_ if ( port->tx_log_everything ) { /* Buffer is full: we spin waiting for space to appear. */ - int i; - while ( !port->driver->tx_empty(port) ) + unsigned int n; + + while ( (n = port->driver->tx_ready(port)) == 0 ) cpu_relax(); - for ( i = 0; i < port->tx_fifo_size; i++ ) + while ( n-- ) port->driver->putc( port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]); @@ -132,7 +130,7 @@ static void __serial_putc(struct serial_ } if ( ((port->txbufp - port->txbufc) == 0) && - port->driver->tx_empty(port) ) + port->driver->tx_ready(port) ) { /* Buffer and UART FIFO are both empty. */ port->driver->putc(port, c); @@ -143,10 +141,10 @@ static void __serial_putc(struct serial_ port->txbuf[mask_serial_txbuf_idx(port->txbufp++)] = c; } } - else if ( port->driver->tx_empty ) + else if ( port->driver->tx_ready ) { /* Synchronous finite-capacity transmitter. */ - while ( !port->driver->tx_empty(port) ) + while ( !port->driver->tx_ready(port) ) cpu_relax(); port->driver->putc(port, c); } @@ -386,7 +384,7 @@ void serial_start_sync(int handle) { while ( (port->txbufp - port->txbufc) != 0 ) { - while ( !port->driver->tx_empty(port) ) + while ( !port->driver->tx_ready(port) ) cpu_relax(); port->driver->putc( port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]); @@ -506,14 +504,11 @@ void __init serial_register_uart(int idx /* Store UART-specific info. */ com[idx].driver = driver; com[idx].uart = uart; - - /* Default is no transmit FIFO. */ - com[idx].tx_fifo_size = 1; } void __init serial_async_transmit(struct serial_port *port) { - BUG_ON(!port->driver->tx_empty); + BUG_ON(!port->driver->tx_ready); if ( port->txbuf != NULL ) return; if ( serial_txbufsz < PAGE_SIZE ) --- a/xen/include/xen/serial.h +++ b/xen/include/xen/serial.h @@ -36,8 +36,6 @@ struct serial_port { struct uart_driver *driver; void *uart; enum serial_port_state state; - /* Number of characters the port can hold for transmit. */ - int tx_fifo_size; /* Transmit data buffer (interrupt-driven uart). */ char *txbuf; unsigned int txbufp, txbufc; @@ -63,8 +61,8 @@ struct uart_driver { /* Driver suspend/resume. */ void (*suspend)(struct serial_port *); void (*resume)(struct serial_port *); - /* Transmit FIFO ready to receive up to @tx_fifo_size characters? */ - int (*tx_empty)(struct serial_port *); + /* Return number of characters the port can hold for transmit. */ + unsigned int (*tx_ready)(struct serial_port *); /* Put a character onto the serial line. */ void (*putc)(struct serial_port *, char); /* Flush accumulated characters. */