console: adjust IRQ initialization In order for a Xen internal PCI device driver to enable MSI on the device, we need another hook which the driver can use to create the IRQ (doing this in the init_preirq hook is too early, since IRQ code hasn't got initialized at that time yet, and doing it in init_postirq is too late because at least on x86 smp_intr_init() needs to know the IRQ number). On x86 this additionally requires a slight ordering change to IRQ initialization, to facilitate calling the new hook between basic initialization and the call path leading to smp_intr_init(). Signed-off-by: Jan Beulich --- a/xen/arch/x86/i8259.c +++ b/xen/arch/x86/i8259.c @@ -342,8 +342,6 @@ void __init init_IRQ(void) init_8259A(0); - BUG_ON(init_irq_data() < 0); - for (irq = 0; platform_legacy_irq(irq); irq++) { struct irq_desc *desc = irq_to_desc(irq); --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -576,6 +576,7 @@ void __init noreturn __start_xen(unsigne unsigned long nr_pages, raw_max_page, modules_headroom, *module_map; int i, j, e820_warn = 0, bytes = 0; bool_t acpi_boot_table_init_done = 0; + int ret; struct domain *dom0; struct ns16550_defaults ns16550 = { .data_bits = 8, @@ -1281,6 +1282,12 @@ void __init noreturn __start_xen(unsigne x2apic_bsp_setup(); + ret = init_irq_data(); + if ( ret < 0 ) + panic("Error %d setting up IRQ data\n", ret); + + console_init_irq(); + init_IRQ(); module_map = xmalloc_array(unsigned long, BITS_TO_LONGS(mbi->mods_count)); @@ -1366,7 +1373,7 @@ void __init noreturn __start_xen(unsigne if ( (num_online_cpus() < max_cpus) && !cpu_online(i) ) { - int ret = cpu_up(i); + ret = cpu_up(i); if ( ret != 0 ) printk("Failed to bring up CPU %u (error %d)\n", i, ret); } --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -771,6 +771,11 @@ void __init console_init_ring(void) printk("Allocated console ring of %u KiB.\n", opt_conring_size >> 10); } +void __init console_init_irq(void) +{ + serial_init_irq(); +} + void __init console_init_postirq(void) { serial_init_postirq(); --- a/xen/drivers/char/serial.c +++ b/xen/drivers/char/serial.c @@ -504,6 +504,15 @@ void __init serial_init_preirq(void) com[i].driver->init_preirq(&com[i]); } +void __init serial_init_irq(void) +{ + unsigned int i; + + for ( i = 0; i < ARRAY_SIZE(com); i++ ) + if ( com[i].driver && com[i].driver->init_irq ) + com[i].driver->init_irq(&com[i]); +} + void __init serial_init_postirq(void) { int i; --- a/xen/include/xen/console.h +++ b/xen/include/xen/console.h @@ -15,6 +15,7 @@ int console_loglvl_op(struct xen_sysctl_ void console_init_preirq(void); void console_init_ring(void); +void console_init_irq(void); void console_init_postirq(void); void console_endboot(void); int console_has(const char *device); --- a/xen/include/xen/serial.h +++ b/xen/include/xen/serial.h @@ -64,6 +64,7 @@ struct serial_port { struct uart_driver { /* Driver initialisation (pre- and post-IRQ subsystem setup). */ void (*init_preirq)(struct serial_port *); + void (*init_irq)(struct serial_port *); void (*init_postirq)(struct serial_port *); /* Hook to clean up after Xen bootstrap (before domain 0 runs). */ void (*endboot)(struct serial_port *); @@ -99,8 +100,9 @@ struct uart_driver { #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). */ +/* Three-stage initialisation (before/during/after IRQ-subsystem setup). */ void serial_init_preirq(void); +void serial_init_irq(void); void serial_init_postirq(void); /* Clean-up hook before domain 0 runs. */