console: prepare for non-COMn port support Widen SERHND_IDX (and use it where needed), introduce a flush low level driver method, and remove unnecessary peeking of the common code at the (driver specific) serial port identification string in the "console=" command line option value. Signed-off-by: Jan Beulich --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -1017,7 +1017,7 @@ void __init smp_intr_init(void) * Also ensure serial interrupts are high priority. We do not * want them to be blocked by unacknowledged guest-bound interrupts. */ - for ( seridx = 0; seridx < 2; seridx++ ) + for ( seridx = 0; seridx <= SERHND_IDX; seridx++ ) { if ( (irq = serial_irq(seridx)) < 0 ) continue; --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -539,6 +539,7 @@ void printk(const char *fmt, ...) void __init console_init_preirq(void) { char *p; + int sh; serial_init_preirq(); @@ -551,8 +552,9 @@ void __init console_init_preirq(void) vga_init(); else if ( !strncmp(p, "none", 4) ) continue; - else if ( strncmp(p, "com", 3) || - (sercon_handle = serial_parse_handle(p)) == -1 ) + else if ( (sh = serial_parse_handle(p)) >= 0 ) + sercon_handle = sh; + else { char *q = strchr(p, ','); if ( q != NULL ) --- a/xen/drivers/char/serial.c +++ b/xen/drivers/char/serial.c @@ -22,9 +22,11 @@ size_param("serial_tx_buffer", serial_tx #define mask_serial_rxbuf_idx(_i) ((_i)&(serial_rxbufsz-1)) #define mask_serial_txbuf_idx(_i) ((_i)&(serial_txbufsz-1)) -static struct serial_port com[2] = { - { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED }, - { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED } +static struct serial_port com[SERHND_IDX + 1] = { + [0 ... SERHND_IDX] = { + .rx_lock = SPIN_LOCK_UNLOCKED, + .tx_lock = SPIN_LOCK_UNLOCKED + } }; void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs) @@ -81,6 +83,8 @@ void serial_tx_interrupt(struct serial_p 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); @@ -175,6 +179,9 @@ void serial_putc(int handle, char c) __serial_putc(port, c); + if ( port->driver->flush ) + port->driver->flush(port); + spin_unlock_irqrestore(&port->tx_lock, flags); } @@ -206,6 +213,9 @@ void serial_puts(int handle, const char __serial_putc(port, c); } + if ( port->driver->flush ) + port->driver->flush(port); + spin_unlock_irqrestore(&port->tx_lock, flags); } @@ -261,10 +271,10 @@ int __init serial_parse_handle(char *con switch ( conf[3] ) { case '1': - handle = 0; + handle = SERHND_COM1; break; case '2': - handle = 1; + handle = SERHND_COM2; break; default: goto fail; @@ -365,6 +375,8 @@ void serial_start_sync(int handle) port->driver->putc( port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]); } + if ( port->driver->flush ) + port->driver->flush(port); } spin_unlock_irqrestore(&port->tx_lock, flags); --- a/xen/include/xen/serial.h +++ b/xen/include/xen/serial.h @@ -60,6 +60,8 @@ struct uart_driver { int (*tx_empty)(struct serial_port *); /* Put a character onto the serial line. */ void (*putc)(struct serial_port *, char); + /* Flush accumulated characters. */ + void (*flush)(struct serial_port *); /* Get a character from the serial line: returns 0 if none available. */ int (*getc)(struct serial_port *, char *); /* Get IRQ number for this port's serial line: returns -1 if none. */ @@ -67,10 +69,12 @@ struct uart_driver { }; /* 'Serial handles' are composed from the following fields. */ -#define SERHND_IDX (1<<0) /* COM1 or COM2? */ -#define SERHND_HI (1<<1) /* Mux/demux each transferred char by MSB. */ -#define SERHND_LO (1<<2) /* Ditto, except that the MSB is cleared. */ -#define SERHND_COOKED (1<<3) /* Newline/carriage-return translation? */ +#define SERHND_IDX (3<<0) /* COM1 or COM2? */ +# define SERHND_COM1 (0<<0) +# define SERHND_COM2 (1<<0) +#define SERHND_HI (1<<2) /* Mux/demux each transferred char by MSB. */ +#define SERHND_LO (1<<3) /* Ditto, except that the MSB is cleared. */ +#define SERHND_COOKED (1<<4) /* Newline/carriage-return translation? */ /* Two-stage initialisation (before/after IRQ-subsystem initialisation). */ void serial_init_preirq(void);