serial: avoid fully initializing unused consoles Defer calling the drivers' post-IRQ initialization functions (generally doing allocation of transmit buffers) until it is known that the respective console is actually going to be used. Signed-off-by: Jan Beulich --- a/xen/drivers/char/serial.c +++ b/xen/drivers/char/serial.c @@ -29,6 +29,8 @@ static struct serial_port com[SERHND_IDX } }; +static bool_t __read_mostly post_irq; + void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs) { char c; @@ -263,14 +265,12 @@ char serial_getc(int handle) int __init serial_parse_handle(char *conf) { - int handle; + int handle, flags = 0; if ( !strncmp(conf, "dbgp", 4) && (!conf[4] || conf[4] == ',') ) { - if ( !com[SERHND_DBGP].driver ) - goto fail; - - return SERHND_DBGP | SERHND_COOKED; + handle = SERHND_DBGP; + goto common; } if ( strncmp(conf, "com", 3) ) @@ -288,17 +288,25 @@ int __init serial_parse_handle(char *con goto fail; } - if ( !com[handle].driver ) - goto fail; - if ( conf[4] == 'H' ) - handle |= SERHND_HI; + flags |= SERHND_HI; else if ( conf[4] == 'L' ) - handle |= SERHND_LO; + flags |= SERHND_LO; - handle |= SERHND_COOKED; + common: + if ( !com[handle].driver ) + goto fail; + + if ( !post_irq ) + com[handle].state = serial_parsed; + else if ( com[handle].state != serial_initialized ) + { + if ( com[handle].driver->init_postirq ) + com[handle].driver->init_postirq(&com[handle]); + com[handle].state = serial_initialized; + } - return handle; + return handle | flags | SERHND_COOKED; fail: return -1; @@ -450,8 +458,13 @@ void __init serial_init_postirq(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) - if ( com[i].driver && com[i].driver->init_postirq ) - com[i].driver->init_postirq(&com[i]); + if ( com[i].state == serial_parsed ) + { + if ( com[i].driver->init_postirq ) + com[i].driver->init_postirq(&com[i]); + com[i].state = serial_initialized; + } + post_irq = 1; } void __init serial_endboot(void) @@ -475,7 +488,7 @@ void serial_suspend(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) - if ( com[i].driver && com[i].driver->suspend ) + if ( com[i].state == serial_initialized && com[i].driver->suspend ) com[i].driver->suspend(&com[i]); } @@ -483,7 +496,7 @@ void serial_resume(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) - if ( com[i].driver && com[i].driver->resume ) + if ( com[i].state == serial_initialized && com[i].driver->resume ) com[i].driver->resume(&com[i]); } --- a/xen/include/xen/serial.h +++ b/xen/include/xen/serial.h @@ -25,10 +25,17 @@ extern unsigned int serial_txbufsz; struct uart_driver; +enum serial_port_state { + serial_unused, + serial_parsed, + serial_initialized +}; + struct serial_port { /* Uart-driver parameters. */ 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). */