With no modular drivers, all interrupt setup is supposed to happen during boot. Signed-off-by: Jan Beulich --- a/xen/arch/ia64/xen/irq.c +++ b/xen/arch/ia64/xen/irq.c @@ -266,7 +266,7 @@ int setup_vector(unsigned int vector, st /* Vectors reserved by xen (and thus not sharable with domains). */ unsigned long ia64_xen_vector[BITS_TO_LONGS(NR_IRQS)]; -int setup_irq_vector(unsigned int vec, struct irqaction * new) +int __init setup_irq_vector(unsigned int vec, struct irqaction * new) { int res; @@ -279,7 +279,7 @@ int setup_irq_vector(unsigned int vec, s return res; } -void release_irq_vector(unsigned int vec) +void __init release_irq_vector(unsigned int vec) { unsigned long flags; irq_desc_t *desc; --- a/xen/arch/ia64/xen/sn_console.c +++ b/xen/arch/ia64/xen/sn_console.c @@ -46,7 +46,7 @@ static int sn_getc(struct serial_port *p return 1; } -static void sn_endboot(struct serial_port *port) +static void __init sn_endboot(struct serial_port *port) { struct sn_console_data *sndata = port->uart; @@ -69,7 +69,7 @@ static void sn_poll(void *data) } -static void sn_init_postirq(struct serial_port *port) +static void __init sn_init_postirq(struct serial_port *port) { struct sn_console_data *sndata = port->uart; @@ -77,9 +77,16 @@ static void sn_init_postirq(struct seria set_timer(&sndata->timer, NOW() + MILLISECS(console_data.timeout_ms)); } +static void sn_resume(struct serial_port *port) +{ + struct sn_console_data *sndata = port->uart; + + set_timer(&sndata->timer, NOW() + MILLISECS(console_data.timeout_ms)); +} static struct uart_driver sn_sal_console = { .init_postirq = sn_init_postirq, + .resume = sn_resume, .putc = sn_putc, .getc = sn_getc, .endboot = sn_endboot, --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -677,7 +677,7 @@ int __init request_irq(unsigned int irq, return retval; } -void release_irq(unsigned int irq) +void __init release_irq(unsigned int irq) { struct irq_desc *desc; unsigned long flags; @@ -700,7 +700,7 @@ void release_irq(unsigned int irq) xfree(action); } -int setup_irq(unsigned int irq, struct irqaction *new) +int __init setup_irq(unsigned int irq, struct irqaction *new) { struct irq_desc *desc; unsigned long flags; --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -224,18 +224,13 @@ static void pci_serial_early_init(struct 0x4, 0x1); } -static void __devinit ns16550_init_preirq(struct serial_port *port) +static void ns16550_setup_preirq(struct ns16550 *uart) { - struct ns16550 *uart = port->uart; unsigned char lcr; unsigned int divisor; pci_serial_early_init(uart); - /* I/O ports are distinguished by their size (16 bits). */ - if ( uart->io_base >= 0x10000 ) - uart->remapped_io_base = (char *)ioremap(uart->io_base, 8); - lcr = (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity; /* No interrupts. */ @@ -264,6 +259,17 @@ static void __devinit ns16550_init_preir /* Enable and clear the FIFOs. Set a large trigger threshold. */ ns_write_reg(uart, FCR, FCR_ENABLE | FCR_CLRX | FCR_CLTX | FCR_TRG14); +} + +static void __init ns16550_init_preirq(struct serial_port *port) +{ + struct ns16550 *uart = port->uart; + + /* I/O ports are distinguished by their size (16 bits). */ + if ( uart->io_base >= 0x10000 ) + uart->remapped_io_base = (char *)ioremap(uart->io_base, 8); + + ns16550_setup_preirq(uart); /* Check this really is a 16550+. Otherwise we have no FIFOs. */ if ( ((ns_read_reg(uart, IIR) & 0xc0) == 0xc0) && @@ -271,7 +277,27 @@ static void __devinit ns16550_init_preir port->tx_fifo_size = 16; } -static void __devinit ns16550_init_postirq(struct serial_port *port) +static void ns16550_setup_postirq(struct ns16550 *uart) +{ + if ( uart->irq > 0 ) + { + /* Master interrupt enable; also keep DTR/RTS asserted. */ + ns_write_reg(uart, MCR, MCR_OUT2 | MCR_DTR | MCR_RTS); + + /* Enable receive and transmit interrupts. */ + ns_write_reg(uart, IER, IER_ERDAI | IER_ETHREI); + + /* Do a timed write to make sure we are getting interrupts. */ + uart->probing = 1; + uart->intr_works = 0; + ns_write_reg(uart, THR, 0xff); + } + + if ( uart->irq >= 0 ) + set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); +} + +static void __init ns16550_init_postirq(struct serial_port *port) { struct ns16550 *uart = port->uart; int rc, bits; @@ -281,36 +307,29 @@ static void __devinit ns16550_init_posti serial_async_transmit(port); - if ( !uart->timer.function ) - init_timer(&uart->timer, ns16550_poll, port, 0); + init_timer(&uart->timer, ns16550_poll, port, 0); /* 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); - if ( uart->irq == 0 ) - set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); - else + if ( uart->irq > 0 ) { uart->irqaction.handler = ns16550_interrupt; uart->irqaction.name = "ns16550"; uart->irqaction.dev_id = port; if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 ) printk("ERROR: Failed to allocate ns16550 IRQ %d\n", uart->irq); + } - /* Master interrupt enable; also keep DTR/RTS asserted. */ - ns_write_reg(uart, MCR, MCR_OUT2 | MCR_DTR | MCR_RTS); - - /* Enable receive and transmit interrupts. */ - ns_write_reg(uart, IER, IER_ERDAI | IER_ETHREI); + ns16550_setup_postirq(uart); +} - /* Do a timed write to make sure we are getting interrupts. */ - uart->probing = 1; - uart->intr_works = 0; - ns_write_reg(uart, THR, 0xff); - set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); - } +static void ns16550_resume(struct serial_port *port) +{ + ns16550_setup_preirq(port->uart); + ns16550_setup_postirq(port->uart); } #ifdef CONFIG_X86 @@ -334,6 +353,7 @@ static struct uart_driver __read_mostly .init_preirq = ns16550_init_preirq, .init_postirq = ns16550_init_postirq, .endboot = ns16550_endboot, + .resume = ns16550_resume, .tx_empty = ns16550_tx_empty, .putc = ns16550_putc, .getc = ns16550_getc, --- a/xen/drivers/char/serial.c +++ b/xen/drivers/char/serial.c @@ -420,7 +420,7 @@ void serial_end_log_everything(int handl spin_unlock_irqrestore(&port->tx_lock, flags); } -void __devinit serial_init_preirq(void) +void __init serial_init_preirq(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) @@ -428,7 +428,7 @@ void __devinit serial_init_preirq(void) com[i].driver->init_preirq(&com[i]); } -void __devinit serial_init_postirq(void) +void __init serial_init_postirq(void) { int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) @@ -455,16 +455,18 @@ int serial_irq(int idx) void serial_suspend(void) { - int i, irq; + int i; for ( i = 0; i < ARRAY_SIZE(com); i++ ) - if ( (irq = serial_irq(i)) >= 0 ) - release_irq(irq); + if ( com[i].driver && com[i].driver->suspend ) + com[i].driver->suspend(&com[i]); } void serial_resume(void) { - serial_init_preirq(); - serial_init_postirq(); + int i; + for ( i = 0; i < ARRAY_SIZE(com); i++ ) + if ( com[i].driver && com[i].driver->resume ) + com[i].driver->resume(&com[i]); } void __init serial_register_uart(int idx, struct uart_driver *driver, @@ -478,7 +480,7 @@ void __init serial_register_uart(int idx com[idx].tx_fifo_size = 1; } -void serial_async_transmit(struct serial_port *port) +void __init serial_async_transmit(struct serial_port *port) { BUG_ON(!port->driver->tx_empty); if ( port->txbuf != NULL ) --- a/xen/include/xen/serial.h +++ b/xen/include/xen/serial.h @@ -51,6 +51,9 @@ struct uart_driver { void (*init_postirq)(struct serial_port *); /* Hook to clean up after Xen bootstrap (before domain 0 runs). */ void (*endboot)(struct serial_port *); + /* 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 *); /* Put a character onto the serial line. */