Commit d7e48886e503d5c7413c8f546c9d4dadab58da3c

Authored by Jiang Liu
Committed by Greg Kroah-Hartman
1 parent 0b4a17fc63

x86/xen: Treat SCI interrupt as normal GSI interrupt

commit b568b8601f05a591a7ff09d8ee1cedb5b2e815fe upstream.

Currently Xen Domain0 has special treatment for ACPI SCI interrupt,
that is initialize irq for ACPI SCI at early stage in a special way as:
xen_init_IRQ()
	->pci_xen_initial_domain()
		->xen_setup_acpi_sci()
			Allocate and initialize irq for ACPI SCI

Function xen_setup_acpi_sci() calls acpi_gsi_to_irq() to get an irq
number for ACPI SCI. But unfortunately acpi_gsi_to_irq() depends on
IOAPIC irqdomains through following path
acpi_gsi_to_irq()
	->mp_map_gsi_to_irq()
		->mp_map_pin_to_irq()
			->check IOAPIC irqdomain

For PV domains, it uses Xen event based interrupt manangement and
doesn't make uses of native IOAPIC, so no irqdomains created for IOAPIC.
This causes Xen domain0 fail to install interrupt handler for ACPI SCI
and all ACPI events will be lost. Please refer to:
https://lkml.org/lkml/2014/12/19/178

So the fix is to get rid of special treatment for ACPI SCI, just treat
ACPI SCI as normal GSI interrupt as:
acpi_gsi_to_irq()
	->acpi_register_gsi()
		->acpi_register_gsi_xen()
			->xen_register_gsi()

With above change, there's no need for xen_setup_acpi_sci() anymore.
The above change also works with bare metal kernel too.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Tested-by: Sander Eikelenboom <linux@eikelenboom.it>
Cc: Tony Luck <tony.luck@intel.com>
Cc: xen-devel@lists.xenproject.org
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Len Brown <len.brown@intel.com>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Link: http://lkml.kernel.org/r/1421720467-7709-2-git-send-email-jiang.liu@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 2 changed files with 12 additions and 58 deletions Side-by-side Diff

arch/x86/kernel/acpi/boot.c
... ... @@ -604,18 +604,19 @@
604 604  
605 605 int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
606 606 {
607   - int irq;
  607 + int rc, irq, trigger, polarity;
608 608  
609   - if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
610   - *irqp = gsi;
611   - } else {
612   - irq = mp_map_gsi_to_irq(gsi,
613   - IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
614   - if (irq < 0)
615   - return -1;
616   - *irqp = irq;
  609 + rc = acpi_get_override_irq(gsi, &trigger, &polarity);
  610 + if (rc == 0) {
  611 + trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
  612 + polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
  613 + irq = acpi_register_gsi(NULL, gsi, trigger, polarity);
  614 + if (irq >= 0) {
  615 + *irqp = irq;
  616 + return 0;
  617 + }
617 618 }
618   - return 0;
  619 + return -1;
619 620 }
620 621 EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
621 622  
... ... @@ -452,52 +452,6 @@
452 452 }
453 453  
454 454 #ifdef CONFIG_XEN_DOM0
455   -static __init void xen_setup_acpi_sci(void)
456   -{
457   - int rc;
458   - int trigger, polarity;
459   - int gsi = acpi_sci_override_gsi;
460   - int irq = -1;
461   - int gsi_override = -1;
462   -
463   - if (!gsi)
464   - return;
465   -
466   - rc = acpi_get_override_irq(gsi, &trigger, &polarity);
467   - if (rc) {
468   - printk(KERN_WARNING "xen: acpi_get_override_irq failed for acpi"
469   - " sci, rc=%d\n", rc);
470   - return;
471   - }
472   - trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
473   - polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
474   -
475   - printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
476   - "polarity=%d\n", gsi, trigger, polarity);
477   -
478   - /* Before we bind the GSI to a Linux IRQ, check whether
479   - * we need to override it with bus_irq (IRQ) value. Usually for
480   - * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
481   - * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
482   - * but there are oddballs where the IRQ != GSI:
483   - * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
484   - * which ends up being: gsi_to_irq[9] == 20
485   - * (which is what acpi_gsi_to_irq ends up calling when starting the
486   - * the ACPI interpreter and keels over since IRQ 9 has not been
487   - * setup as we had setup IRQ 20 for it).
488   - */
489   - if (acpi_gsi_to_irq(gsi, &irq) == 0) {
490   - /* Use the provided value if it's valid. */
491   - if (irq >= 0)
492   - gsi_override = irq;
493   - }
494   -
495   - gsi = xen_register_gsi(gsi, gsi_override, trigger, polarity);
496   - printk(KERN_INFO "xen: acpi sci %d\n", gsi);
497   -
498   - return;
499   -}
500   -
501 455 int __init pci_xen_initial_domain(void)
502 456 {
503 457 int irq;
... ... @@ -509,7 +463,6 @@
509 463 x86_msi.msi_mask_irq = xen_nop_msi_mask_irq;
510 464 x86_msi.msix_mask_irq = xen_nop_msix_mask_irq;
511 465 #endif
512   - xen_setup_acpi_sci();
513 466 __acpi_register_gsi = acpi_register_gsi_xen;
514 467 /* Pre-allocate legacy irqs */
515 468 for (irq = 0; irq < nr_legacy_irqs(); irq++) {