159 lines
4.6 KiB
Plaintext
159 lines
4.6 KiB
Plaintext
From: jbeulich@novell.com
|
|
Subject: pass trigger mode and polarity information to Xen for all interrupts
|
|
Patch-mainline: n/a
|
|
|
|
For Xen to be able to use non-legacy IRQs e.g. for its serial console,
|
|
it needs to know trigger mode and polarity for them regardless of
|
|
whether the kernel is also going to (try to) use those interrupts.
|
|
|
|
--- head-2011-01-30.orig/arch/x86/kernel/apic/io_apic-xen.c 2011-02-01 16:05:51.000000000 +0100
|
|
+++ head-2011-01-30/arch/x86/kernel/apic/io_apic-xen.c 2011-02-02 15:10:38.000000000 +0100
|
|
@@ -1400,6 +1400,10 @@ static int setup_ioapic_entry(int apic_i
|
|
return 0;
|
|
}
|
|
|
|
+static struct {
|
|
+ DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
|
|
+} mp_ioapic_routing[MAX_IO_APICS];
|
|
+
|
|
static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
|
|
struct irq_cfg *cfg, int trigger, int polarity)
|
|
{
|
|
@@ -1416,6 +1420,42 @@ static void setup_ioapic_irq(int apic_id
|
|
*/
|
|
if (irq < legacy_pic->nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain))
|
|
apic->vector_allocation_domain(0, cfg->domain);
|
|
+#else
|
|
+ /*
|
|
+ * For legacy IRQs we may get here before trigger mode and polarity
|
|
+ * get obtained, but Xen refuses to set those through
|
|
+ * PHYSDEVOP_setup_gsi more than once (perhaps even at all).
|
|
+ */
|
|
+ if (irq >= legacy_pic->nr_legacy_irqs
|
|
+ || test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
|
|
+ struct physdev_setup_gsi setup_gsi = {
|
|
+ .gsi = irq,
|
|
+ .triggering = trigger,
|
|
+ .polarity = polarity
|
|
+ };
|
|
+ struct physdev_map_pirq map_pirq = {
|
|
+ .domid = DOMID_SELF,
|
|
+ .type = MAP_PIRQ_TYPE_GSI,
|
|
+ .index = irq,
|
|
+ .pirq = irq
|
|
+ };
|
|
+
|
|
+ switch (HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi,
|
|
+ &setup_gsi)) {
|
|
+ case -EEXIST:
|
|
+ if (irq < legacy_pic->nr_legacy_irqs)
|
|
+ break;
|
|
+ /* fall through */
|
|
+ case 0:
|
|
+ evtchn_register_pirq(irq);
|
|
+ if (HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
|
|
+ &map_pirq) == 0) {
|
|
+ /* fake (for init_IO_APIC_traps()): */
|
|
+ cfg->vector = irq;
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
#endif
|
|
|
|
if (assign_irq_vector(irq, cfg, apic->target_cpus()))
|
|
@@ -1451,10 +1491,6 @@ static void setup_ioapic_irq(int apic_id
|
|
ioapic_write_entry(apic_id, pin, entry);
|
|
}
|
|
|
|
-static struct {
|
|
- DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
|
|
-} mp_ioapic_routing[MAX_IO_APICS];
|
|
-
|
|
static void __init setup_IO_APIC_irqs(void)
|
|
{
|
|
int apic_id, pin, idx, irq, notcon = 0;
|
|
--- head-2011-01-30.orig/drivers/acpi/pci_irq.c 2011-01-05 01:50:19.000000000 +0100
|
|
+++ head-2011-01-30/drivers/acpi/pci_irq.c 2011-02-02 15:10:38.000000000 +0100
|
|
@@ -469,3 +469,80 @@ void acpi_pci_irq_disable(struct pci_dev
|
|
dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
|
|
acpi_unregister_gsi(gsi);
|
|
}
|
|
+
|
|
+#if defined(CONFIG_XEN) && defined(CONFIG_PCI)
|
|
+static int __init xen_setup_gsi(void)
|
|
+{
|
|
+ struct pci_dev *dev = NULL;
|
|
+
|
|
+ if (acpi_noirq)
|
|
+ return 0;
|
|
+
|
|
+ /* Loop body is a clone of acpi_pci_irq_enable(). */
|
|
+ for_each_pci_dev(dev) {
|
|
+ const struct acpi_prt_entry *entry;
|
|
+ int gsi;
|
|
+ int triggering = ACPI_LEVEL_SENSITIVE;
|
|
+ int polarity = ACPI_ACTIVE_LOW;
|
|
+ struct physdev_setup_gsi setup_gsi;
|
|
+
|
|
+ if (!dev->pin)
|
|
+ continue;
|
|
+
|
|
+ entry = acpi_pci_irq_lookup(dev, dev->pin);
|
|
+ if (!entry) {
|
|
+ /*
|
|
+ * IDE legacy mode controller IRQs are magic. Why do
|
|
+ * compat extensions always make such a nasty mess.
|
|
+ */
|
|
+ if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
|
|
+ (dev->class & 0x05) == 0)
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ gsi = entry
|
|
+ ? entry->link
|
|
+ ? acpi_pci_link_allocate_irq(entry->link,
|
|
+ entry->index,
|
|
+ &triggering, &polarity,
|
|
+ NULL)
|
|
+ : entry->index
|
|
+ : -1;
|
|
+
|
|
+ if (gsi >= 0) {
|
|
+ setup_gsi.gsi = gsi;
|
|
+ setup_gsi.triggering
|
|
+ = (triggering == ACPI_LEVEL_SENSITIVE);
|
|
+ setup_gsi.polarity = (polarity == ACPI_ACTIVE_LOW);
|
|
+ if (HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi,
|
|
+ &setup_gsi) < 0)
|
|
+ continue;
|
|
+
|
|
+ dev_info(&dev->dev, "GSI%d: %s-%s\n", gsi,
|
|
+ triggering == ACPI_LEVEL_SENSITIVE ? "level"
|
|
+ : "edge",
|
|
+ polarity == ACPI_ACTIVE_LOW ? "low" : "high");
|
|
+ } else {
|
|
+ /*
|
|
+ * No IRQ known to the ACPI subsystem - maybe the
|
|
+ * BIOS / driver reported one, then use it.
|
|
+ */
|
|
+ dev_warn(&dev->dev, "PCI INT %c: no GSI",
|
|
+ pin_name(dev->pin));
|
|
+ /* Interrupt Line values above 0xF are forbidden */
|
|
+ if (dev->irq > 0 && (dev->irq <= 0xF)) {
|
|
+ pr_cont(" - using IRQ %d\n", dev->irq);
|
|
+ setup_gsi.gsi = dev->irq;
|
|
+ setup_gsi.triggering = 1;
|
|
+ setup_gsi.polarity = 1;
|
|
+ VOID(HYPERVISOR_physdev_op(PHYSDEVOP_setup_gsi,
|
|
+ &setup_gsi));
|
|
+ } else
|
|
+ pr_cont("\n");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+subsys_initcall(xen_setup_gsi);
|
|
+#endif
|