diff mbox

[Vivid,maybe,pre-stable] Fix various issues when running as dom0

Message ID 1423575637-6170-1-git-send-email-stefan.bader@canonical.com
State New
Headers show

Commit Message

Stefan Bader Feb. 10, 2015, 1:40 p.m. UTC
I was discussing this backport upstream and it should come back
via stable sooner or later. So whether we want to pick it up before
or not I would leave up to you.

Right now this causes some kind of weird side-effects as Sander
had problems with the power button getting recognized (which I would
rather understand) and I am having all attached USB devices failing
to get initialized (which is rather odd). Nevertheless all those things
are gone when acpi is getting its interrupt back.

-Stefan

---

From 8b5b328b62248d95743ca9af7aa71c06dd808dfe Mon Sep 17 00:00:00 2001
From: Jiang Liu <jiang.liu@linux.intel.com>
Date: Tue, 20 Jan 2015 10:21:05 +0800
Subject: [PATCH] x86/xen: Treat SCI interrupt as normal GSI interrupt

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>

(backported from commit b568b8601f05a591a7ff09d8ee1cedb5b2e815fe)
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
---
 arch/x86/kernel/acpi/boot.c | 23 +++++++++++-----------
 arch/x86/pci/xen.c          | 47 ---------------------------------------------
 2 files changed, 12 insertions(+), 58 deletions(-)

Comments

Andy Whitcroft Feb. 10, 2015, 2:59 p.m. UTC | #1
On Tue, Feb 10, 2015 at 02:40:37PM +0100, Stefan Bader wrote:
> I was discussing this backport upstream and it should come back
> via stable sooner or later. So whether we want to pick it up before
> or not I would leave up to you.
> 
> Right now this causes some kind of weird side-effects as Sander
> had problems with the power button getting recognized (which I would
> rather understand) and I am having all attached USB devices failing
> to get initialized (which is rather odd). Nevertheless all those things
> are gone when acpi is getting its interrupt back.
> 
> -Stefan
> 
> ---
> 
> From 8b5b328b62248d95743ca9af7aa71c06dd808dfe Mon Sep 17 00:00:00 2001
> From: Jiang Liu <jiang.liu@linux.intel.com>
> Date: Tue, 20 Jan 2015 10:21:05 +0800
> Subject: [PATCH] x86/xen: Treat SCI interrupt as normal GSI interrupt
> 
> 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>
> 
> (backported from commit b568b8601f05a591a7ff09d8ee1cedb5b2e815fe)
> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
> ---
>  arch/x86/kernel/acpi/boot.c | 23 +++++++++++-----------
>  arch/x86/pci/xen.c          | 47 ---------------------------------------------
>  2 files changed, 12 insertions(+), 58 deletions(-)
> 
> diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
> index a142e77..460f498 100644
> --- a/arch/x86/kernel/acpi/boot.c
> +++ b/arch/x86/kernel/acpi/boot.c
> @@ -604,18 +604,19 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
>  
>  int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
>  {
> -	int irq;
> -
> -	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
> -		*irqp = gsi;
> -	} else {
> -		irq = mp_map_gsi_to_irq(gsi,
> -					IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
> -		if (irq < 0)
> -			return -1;
> -		*irqp = irq;
> +	int rc, irq, trigger, polarity;
> +
> +	rc = acpi_get_override_irq(gsi, &trigger, &polarity);
> +	if (rc == 0) {
> +		trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
> +		polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
> +		irq = acpi_register_gsi(NULL, gsi, trigger, polarity);
> +		if (irq >= 0) {
> +			*irqp = irq;
> +			return 0;
> +		}
>  	}
> -	return 0;
> +	return -1;
>  }
>  EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
>  
> diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
> index 093f5f4..6b3cf7c 100644
> --- a/arch/x86/pci/xen.c
> +++ b/arch/x86/pci/xen.c
> @@ -452,52 +452,6 @@ int __init pci_xen_hvm_init(void)
>  }
>  
>  #ifdef CONFIG_XEN_DOM0
> -static __init void xen_setup_acpi_sci(void)
> -{
> -	int rc;
> -	int trigger, polarity;
> -	int gsi = acpi_sci_override_gsi;
> -	int irq = -1;
> -	int gsi_override = -1;
> -
> -	if (!gsi)
> -		return;
> -
> -	rc = acpi_get_override_irq(gsi, &trigger, &polarity);
> -	if (rc) {
> -		printk(KERN_WARNING "xen: acpi_get_override_irq failed for acpi"
> -				" sci, rc=%d\n", rc);
> -		return;
> -	}
> -	trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
> -	polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
> -
> -	printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
> -			"polarity=%d\n", gsi, trigger, polarity);
> -
> -	/* Before we bind the GSI to a Linux IRQ, check whether
> -	 * we need to override it with bus_irq (IRQ) value. Usually for
> -	 * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
> -	 *  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
> -	 * but there are oddballs where the IRQ != GSI:
> -	 *  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
> -	 * which ends up being: gsi_to_irq[9] == 20
> -	 * (which is what acpi_gsi_to_irq ends up calling when starting the
> -	 * the ACPI interpreter and keels over since IRQ 9 has not been
> -	 * setup as we had setup IRQ 20 for it).
> -	 */
> -	if (acpi_gsi_to_irq(gsi, &irq) == 0) {
> -		/* Use the provided value if it's valid. */
> -		if (irq >= 0)
> -			gsi_override = irq;
> -	}
> -
> -	gsi = xen_register_gsi(gsi, gsi_override, trigger, polarity);
> -	printk(KERN_INFO "xen: acpi sci %d\n", gsi);
> -
> -	return;
> -}
> -
>  int __init pci_xen_initial_domain(void)
>  {
>  	int irq;
> @@ -509,7 +463,6 @@ int __init pci_xen_initial_domain(void)
>  	x86_msi.msi_mask_irq = xen_nop_msi_mask_irq;
>  	x86_msi.msix_mask_irq = xen_nop_msix_mask_irq;
>  #endif
> -	xen_setup_acpi_sci();
>  	__acpi_register_gsi = acpi_register_gsi_xen;
>  	/* Pre-allocate legacy irqs */
>  	for (irq = 0; irq < nr_legacy_irqs(); irq++) {

As this is applied in mainline in v3.19 I assume this is master-next
material:

    git describe --contains b568b8601f05a591a7ff09d8ee1cedb5b2e815fe v3.19-rc6~1^2~14

-apw
Andy Whitcroft Feb. 10, 2015, 3:02 p.m. UTC | #2
Applied to vivid master-next.

-apw
diff mbox

Patch

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index a142e77..460f498 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -604,18 +604,19 @@  void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 {
-	int irq;
-
-	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
-		*irqp = gsi;
-	} else {
-		irq = mp_map_gsi_to_irq(gsi,
-					IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
-		if (irq < 0)
-			return -1;
-		*irqp = irq;
+	int rc, irq, trigger, polarity;
+
+	rc = acpi_get_override_irq(gsi, &trigger, &polarity);
+	if (rc == 0) {
+		trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
+		polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
+		irq = acpi_register_gsi(NULL, gsi, trigger, polarity);
+		if (irq >= 0) {
+			*irqp = irq;
+			return 0;
+		}
 	}
-	return 0;
+	return -1;
 }
 EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 093f5f4..6b3cf7c 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -452,52 +452,6 @@  int __init pci_xen_hvm_init(void)
 }
 
 #ifdef CONFIG_XEN_DOM0
-static __init void xen_setup_acpi_sci(void)
-{
-	int rc;
-	int trigger, polarity;
-	int gsi = acpi_sci_override_gsi;
-	int irq = -1;
-	int gsi_override = -1;
-
-	if (!gsi)
-		return;
-
-	rc = acpi_get_override_irq(gsi, &trigger, &polarity);
-	if (rc) {
-		printk(KERN_WARNING "xen: acpi_get_override_irq failed for acpi"
-				" sci, rc=%d\n", rc);
-		return;
-	}
-	trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
-	polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
-
-	printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
-			"polarity=%d\n", gsi, trigger, polarity);
-
-	/* Before we bind the GSI to a Linux IRQ, check whether
-	 * we need to override it with bus_irq (IRQ) value. Usually for
-	 * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
-	 *  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
-	 * but there are oddballs where the IRQ != GSI:
-	 *  ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
-	 * which ends up being: gsi_to_irq[9] == 20
-	 * (which is what acpi_gsi_to_irq ends up calling when starting the
-	 * the ACPI interpreter and keels over since IRQ 9 has not been
-	 * setup as we had setup IRQ 20 for it).
-	 */
-	if (acpi_gsi_to_irq(gsi, &irq) == 0) {
-		/* Use the provided value if it's valid. */
-		if (irq >= 0)
-			gsi_override = irq;
-	}
-
-	gsi = xen_register_gsi(gsi, gsi_override, trigger, polarity);
-	printk(KERN_INFO "xen: acpi sci %d\n", gsi);
-
-	return;
-}
-
 int __init pci_xen_initial_domain(void)
 {
 	int irq;
@@ -509,7 +463,6 @@  int __init pci_xen_initial_domain(void)
 	x86_msi.msi_mask_irq = xen_nop_msi_mask_irq;
 	x86_msi.msix_mask_irq = xen_nop_msix_mask_irq;
 #endif
-	xen_setup_acpi_sci();
 	__acpi_register_gsi = acpi_register_gsi_xen;
 	/* Pre-allocate legacy irqs */
 	for (irq = 0; irq < nr_legacy_irqs(); irq++) {