From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
To: Bjorn Helgaas <bjorn.helgaas@hp.com>,
Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Cc: "'Li, Shaohua'" <shaohua.li@intel.com>,
acpi-devel@lists.sourceforge.net, "'Brown,
Len'" <len.brown@intel.com>,
'David Mosberger' <davidm@hpl.hp.com>, 'Andi Kleen' <ak@suse.de>,
"'Nakajima, Jun'" <jun.nakajima@intel.com>,
linux-ia64@vger.kernel.org
Subject: RE: [ACPI] Re: [PATCH] ACPI PCI IRQ routing rework
Date: Tue, 18 May 2004 09:30:38 +0000 [thread overview]
Message-ID: <MDEEKOKJPMPMKGHIFAMACEPJEAAA.kaneshige.kenji@jp.fujitsu.com> (raw)
In-Reply-To: <200405171241.24071.bjorn.helgaas@hp.com>
> Out of curiosity, do you have a machine that routes INIT or
> PMI through an IOSAPIC? It's certainly allowed, and we should
> support it, but the HP and Intel boxes I've seen don't seem to
> do that.
No, I don't. My machine is Tiger4. As you said, it doesn't have
PMI and INIT through an IOSAPIC.
Thanks,
Kenji Kaneshige
> -----Original Message-----
> From: linux-ia64-owner@vger.kernel.org
> [mailto:linux-ia64-owner@vger.kernel.org]On Behalf Of Bjorn Helgaas
> Sent: Tuesday, May 18, 2004 3:41 AM
> To: Kenji Kaneshige
> Cc: 'Li, Shaohua'; acpi-devel@lists.sourceforge.net; 'Brown,
> Len'; 'David Mosberger'; 'Andi Kleen'; 'Nakajima, Jun';
> linux-ia64@vger.kernel.org
> Subject: Re: [ACPI] Re: [PATCH] ACPI PCI IRQ routing rework
>
>
> On Monday 17 May 2004 10:16 am, Kenji Kaneshige wrote:
> > I agree with you about CPEI, but how about PMI and INIT?
> > I think PMI and INIT need to be unmasked in somewhere.
>
> Yes, you're right.
>
> The following patch unmasks platform interrupt IOSAPIC entries
> (except for CPEI) when we process them from the MADT.
>
> Out of curiosity, do you have a machine that routes INIT or
> PMI through an IOSAPIC? It's certainly allowed, and we should
> support it, but the HP and Intel boxes I've seen don't seem to
> do that.
>
> === arch/i386/kernel/mpparse.c 1.71 vs edited ==> --- 1.71/arch/i386/kernel/mpparse.c Fri Apr 30 23:27:25 2004
> +++ edited/arch/i386/kernel/mpparse.c Mon May 17 10:39:37 2004
> @@ -1027,94 +1027,58 @@
>
> extern FADT_DESCRIPTOR acpi_fadt;
>
> -#ifdef CONFIG_ACPI_PCI
> +#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
> +
> +#ifdef CONFIG_X86_IO_APIC
>
> -void __init mp_parse_prt (void)
> +void mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
> {
> - struct list_head *node = NULL;
> - struct acpi_prt_entry *entry = NULL;
> int ioapic = -1;
> int ioapic_pin = 0;
> - int gsi = 0;
> int idx, bit = 0;
> - int edge_level = 0;
> - int active_high_low = 0;
>
> - /*
> - * Parsing through the PCI Interrupt Routing Table (PRT) and program
> - * routing for all entries.
> - */
> - list_for_each(node, &acpi_prt.entries) {
> - entry = list_entry(node, struct acpi_prt_entry, node);
> + /* Don't set up the ACPI SCI because it's already set up */
> + if (acpi_fadt.sci_int = gsi)
> + return;
> +
> + ioapic = mp_find_ioapic(gsi);
> + if (ioapic < 0) {
> + printk(KERN_WARNING "No IOAPIC for GSI 0x%x\n", gsi);
> + return;
> + }
> +
> + ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
>
> - /* Need to get gsi for dynamic entry */
> - if (entry->link.handle) {
> - gsi > acpi_pci_link_get_irq(entry->link.handle, entry->link.index,
> &edge_level, &active_high_low);
> - if (!gsi)
> - continue;
> - }
> - else {
> - /* Hardwired GSI. Assume PCI standard settings */
> - gsi = entry->link.index;
> - edge_level = 1;
> - active_high_low = 1;
> - }
> -
> - /* Don't set up the ACPI SCI because it's already set up */
> - if (acpi_fadt.sci_int = gsi) {
> - /* we still need to set entry's irq */
> - acpi_gsi_to_irq(gsi, &entry->irq);
> - continue;
> - }
> -
> - ioapic = mp_find_ioapic(gsi);
> - if (ioapic < 0)
> - continue;
> - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
> -
> - if (es7000_plat) {
> - if (!ioapic && (gsi < 16))
> - gsi += 16;
> - }
> -
> - /*
> - * Avoid pin reprogramming. PRTs typically include
> entries
> - * with redundant pin->gsi mappings (but unique PCI
> devices);
> - * we only only program the IOAPIC on the first.
> - */
> - bit = ioapic_pin % 32;
> - idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
> - if (idx > 3) {
> - printk(KERN_ERR "Invalid reference to IOAPIC pin "
> - "%d-%d\n",
> mp_ioapic_routing[ioapic].apic_id,
> - ioapic_pin);
> - continue;
> - }
> - if ((1<<bit) &
> mp_ioapic_routing[ioapic].pin_programmed[idx]) {
> - Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
> - mp_ioapic_routing[ioapic].apic_id,
> ioapic_pin);
> - acpi_gsi_to_irq(gsi, &entry->irq);
> - continue;
> - }
> -
> - mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
> -
> - if (!io_apic_set_pci_routing(ioapic, ioapic_pin,
> gsi, edge_level, active_high_low)) {
> - acpi_gsi_to_irq(gsi, &entry->irq);
> - }
> - printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d ->
> IRQ %d %s %s\n",
> - entry->id.segment, entry->id.bus,
> - entry->id.device, ('A' + entry->pin),
> - mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
> - entry->irq, edge_level ? "level" : "edge",
> - active_high_low ? "low" : "high");
> + if (es7000_plat) {
> + if (!ioapic && (gsi < 16))
> + gsi += 16;
> }
>
> - print_IO_APIC();
> + /*
> + * Avoid pin reprogramming. PRTs typically include entries
> + * with redundant pin->gsi mappings (but unique PCI devices);
> + * we only program the IOAPIC on the first.
> + */
> + bit = ioapic_pin % 32;
> + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
> + if (idx > 3) {
> + printk(KERN_ERR "Invalid reference to IOAPIC pin "
> + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
> + ioapic_pin);
> + return;
> + }
> + if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
> + Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
> + mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
> + return;
> + }
>
> - return;
> + mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
> +
> + io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
> + edge_level = ACPI_EDGE_SENSITIVE ? 0 : 1,
> + active_high_low = ACPI_ACTIVE_HIGH ? 0 : 1);
> }
>
> -#endif /*CONFIG_ACPI_PCI*/
> -#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
> +#endif /*CONFIG_X86_IO_APIC*/
> #endif /*CONFIG_ACPI_BOOT*/
> === arch/i386/kernel/acpi/boot.c 1.61 vs edited ==> --- 1.61/arch/i386/kernel/acpi/boot.c Sat May 15 00:11:59 2004
> +++ edited/arch/i386/kernel/acpi/boot.c Mon May 17 10:39:37 2004
> @@ -428,6 +428,28 @@
> return 0;
> }
>
> +unsigned int acpi_register_gsi(u32 gsi, int edge_level, int
> active_high_low)
> +{
> + static u16 irq_mask;
> + unsigned int irq;
> + extern void eisa_set_level_irq(unsigned int irq);
> +
> + /*
> + * Make sure all (legacy) PCI IRQs are set as level-triggered.
> + */
> + if ((gsi < 16) && !((1 << gsi) & irq_mask)) {
> + printk(KERN_DEBUG PREFIX "Setting GSI 0x%x as
> level-triggered\n", gsi);
> + irq_mask |= (1 << gsi);
> + eisa_set_level_irq(gsi);
> + }
> +
> +#ifdef CONFIG_X86_IO_APIC
> + mp_register_gsi(gsi, edge_level, active_high_low);
> +#endif
> + acpi_gsi_to_irq(gsi, &irq);
> + return irq;
> +}
> +
> static unsigned long __init
> acpi_scan_rsdp (
> unsigned long start,
> === arch/i386/pci/acpi.c 1.13 vs edited ==> --- 1.13/arch/i386/pci/acpi.c Fri Apr 30 23:27:25 2004
> +++ edited/arch/i386/pci/acpi.c Mon May 17 10:39:37 2004
> @@ -1,6 +1,8 @@
> #include <linux/pci.h>
> #include <linux/acpi.h>
> #include <linux/init.h>
> +#include <linux/irq.h>
> +#include <asm/hw_irq.h>
> #include "pci.h"
>
> struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device
> *device, int domain, int busnum)
> @@ -15,18 +17,28 @@
>
> static int __init pci_acpi_init(void)
> {
> + struct pci_dev *dev = NULL;
> +
> if (pcibios_scanned)
> return 0;
>
> - if (!acpi_noirq) {
> - if (!acpi_pci_irq_init()) {
> - printk(KERN_INFO "PCI: Using ACPI for IRQ
> routing\n");
> - pcibios_scanned++;
> - pcibios_enable_irq = acpi_pci_irq_enable;
> - } else
> - printk(KERN_WARNING "PCI: Invalid ACPI-PCI
> IRQ routing table\n");
> + if (acpi_noirq)
> + return 0;
>
> - }
> + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
> + acpi_irq_penalty_init();
> + pcibios_scanned++;
> + pcibios_enable_irq = acpi_pci_irq_enable;
> +
> + /*
> + * PCI IRQ routing is set up by pci_enable_device(), but we
> + * also do it here in case there are still broken drivers that
> + * don't use pci_enable_device().
> + */
> + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
> + acpi_pci_irq_enable(dev);
> +
> + print_IO_APIC();
>
> return 0;
> }
> === arch/ia64/kernel/acpi.c 1.69 vs edited ==> --- 1.69/arch/ia64/kernel/acpi.c Sat May 15 00:11:59 2004
> +++ edited/arch/ia64/kernel/acpi.c Mon May 17 10:39:37 2004
> @@ -508,9 +508,14 @@
> #endif /* CONFIG_ACPI_NUMA */
>
> unsigned int
> -acpi_register_gsi (u32 gsi, int polarity, int trigger)
> +acpi_register_gsi (u32 gsi, int edge_level, int active_high_low)
> {
> - return acpi_register_irq(gsi, polarity, trigger);
> + if (has_8259 && gsi < 16)
> + return isa_irq_to_vector(gsi);
> +
> + return iosapic_register_intr(gsi,
> + (active_high_low = ACPI_ACTIVE_HIGH) ?
> IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
> + (edge_level = ACPI_EDGE_SENSITIVE) ?
> IOSAPIC_EDGE : IOSAPIC_LEVEL);
> }
> EXPORT_SYMBOL(acpi_register_gsi);
>
> @@ -535,7 +540,7 @@
> if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES)
> acpi_legacy_devices = 1;
>
> - acpi_register_gsi(fadt->sci_int, ACPI_ACTIVE_LOW,
> ACPI_LEVEL_SENSITIVE);
> + acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE,
> ACPI_ACTIVE_LOW);
> return 0;
> }
>
> @@ -648,17 +653,5 @@
> }
> return 0;
> }
> -
> -int
> -acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
> -{
> - if (has_8259 && gsi < 16)
> - return isa_irq_to_vector(gsi);
> -
> - return iosapic_register_intr(gsi,
> - (polarity = ACPI_ACTIVE_HIGH) ?
> IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
> - (trigger = ACPI_EDGE_SENSITIVE) ?
> IOSAPIC_EDGE : IOSAPIC_LEVEL);
> -}
> -EXPORT_SYMBOL(acpi_register_irq);
>
> #endif /* CONFIG_ACPI_BOOT */
> === arch/ia64/kernel/iosapic.c 1.42 vs edited ==> --- 1.42/arch/ia64/kernel/iosapic.c Fri May 14 20:00:12 2004
> +++ edited/arch/ia64/kernel/iosapic.c Mon May 17 11:51:35 2004
> @@ -512,6 +512,42 @@
> }
> }
>
> +static unsigned int
> +dest_cpu_lid (void)
> +{
> +#ifdef CONFIG_SMP
> + static int cpu = -1;
> +
> + /*
> + * If the platform supports redirection via XTP, let it
> + * distribute interrupts.
> + */
> + if (smp_int_redirect & SMP_IRQ_REDIRECTION)
> + return hard_smp_processor_id();
> +
> + /*
> + * Some interrupts (ACPI SCI, for instance) are registered
> + * before the BSP is marked as online.
> + */
> + if (!cpu_online(smp_processor_id()))
> + return hard_smp_processor_id();
> +
> + /*
> + * Otherwise, round-robin interrupt vectors across all the
> + * processors. (It'd be nice if we could be smarter in the
> + * case of NUMA.)
> + */
> + do {
> + if (++cpu >= NR_CPUS)
> + cpu = 0;
> + } while (!cpu_online(cpu));
> +
> + return cpu_physical_id(cpu);
> +#else
> + return hard_smp_processor_id();
> +#endif
> +}
> +
> /*
> * ACPI can describe IOSAPIC interrupts via static tables and namespace
> * methods. This provides an interface to register those interrupts and
> @@ -522,21 +558,35 @@
> unsigned long polarity, unsigned long trigger)
> {
> int vector;
> - unsigned int dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff;
> + unsigned int dest;
> + unsigned long flags;
>
> - vector = gsi_to_vector(gsi);
> - if (vector < 0)
> - vector = assign_irq_vector(AUTO_ASSIGN);
> + /*
> + * If this GSI has already been registered (i.e., it's a
> + * shared interrupt, or we lost a race to register it),
> + * don't touch the RTE.
> + */
> + spin_lock_irqsave(&iosapic_lock, flags);
> + {
> + vector = gsi_to_vector(gsi);
> + if (vector > 0) {
> + spin_unlock_irqrestore(&iosapic_lock, flags);
> + return vector;
> + }
>
> - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
> - polarity, trigger);
> + vector = assign_irq_vector(AUTO_ASSIGN);
> + dest = dest_cpu_lid();
> + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
> + polarity, trigger);
> + }
> + spin_unlock_irqrestore(&iosapic_lock, flags);
>
> - printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
> - gsi, (polarity = IOSAPIC_POL_HIGH ? "high" : "low"),
> - (trigger = IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
> + printk(KERN_INFO "GSI 0x%x (%s, %s) -> CPU %d (0x%04x) vector %d\n",
> + gsi, (trigger = IOSAPIC_EDGE ? "edge" : "level"),
> + (polarity = IOSAPIC_POL_HIGH ? "high" : "low"),
> + cpu_logical_id(dest), dest, vector);
>
> - /* program the IOSAPIC routing table */
> - set_rte(vector, dest, 0);
> + set_rte(vector, dest, 1);
> return vector;
> }
>
> @@ -549,8 +599,9 @@
> int iosapic_vector, u16 eid, u16 id,
> unsigned long polarity, unsigned
> long trigger)
> {
> + static const char * const name[] = {"unknown", "PMI",
> "INIT", "CPEI"};
> unsigned char delivery;
> - int vector;
> + int vector, mask = 0;
> unsigned int dest = ((id << 8) | eid) & 0xffff;
>
> switch (int_type) {
> @@ -570,21 +621,22 @@
> case ACPI_INTERRUPT_CPEI:
> vector = IA64_CPE_VECTOR;
> delivery = IOSAPIC_LOWEST_PRIORITY;
> + mask = 1;
> break;
> default:
> - printk(KERN_ERR "iosapic_register_platform_irq():
> invalid int type\n");
> + printk(KERN_ERR "iosapic_register_platform_irq():
> invalid int type 0x%x\n", int_type);
> return -1;
> }
>
> - register_intr(gsi, vector, delivery, polarity,
> - trigger);
> + register_intr(gsi, vector, delivery, polarity, trigger);
>
> - printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU
> 0x%04x vector %d\n",
> - int_type, gsi, (polarity = IOSAPIC_POL_HIGH ?
> "high" : "low"),
> - (trigger = IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
> + printk(KERN_INFO "PLATFORM int %s (0x%x): GSI 0x%x (%s, %s)
> -> CPU %d (0x%04x) vector %d\n",
> + int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",
> + int_type, gsi, (trigger = IOSAPIC_EDGE ? "edge" : "level"),
> + (polarity = IOSAPIC_POL_HIGH ? "high" : "low"),
> + cpu_logical_id(dest), dest, vector);
>
> - /* program the IOSAPIC routing table */
> - set_rte(vector, dest, 0);
> + set_rte(vector, dest, mask);
> return vector;
> }
>
> @@ -599,18 +651,18 @@
> unsigned long trigger)
> {
> int vector;
> - unsigned int dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff;
> + unsigned int dest = hard_smp_processor_id();
>
> vector = isa_irq_to_vector(isa_irq);
>
> register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
> polarity, trigger);
>
> - DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",
> - isa_irq, gsi, polarity = IOSAPIC_POL_HIGH ? "high" : "low",
> - trigger = IOSAPIC_EDGE ? "edge" : "level", dest, vector);
> + DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU %d (0x%04x)
> vector %d\n",
> + isa_irq, gsi, trigger = IOSAPIC_EDGE ? "edge" : "level",
> + polarity = IOSAPIC_POL_HIGH ? "high" : "low",
> + cpu_logical_id(dest), dest, vector);
>
> - /* program the IOSAPIC routing table */
> - set_rte(vector, dest, 0);
> + set_rte(vector, dest, 1);
> }
>
> void __init
> @@ -665,104 +717,3 @@
> iosapic_override_isa_irq(isa_irq, isa_irq,
> IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
> }
> }
> -
> -void
> -iosapic_enable_intr (unsigned int vector)
> -{
> - unsigned int dest;
> - irq_desc_t *desc;
> -
> - /*
> - * In the case of a shared interrupt, do not re-route the
> vector, and
> - * especially do not mask a running interrupt (startup will not get
> - * called for a shared interrupt).
> - */
> - desc = irq_descp(vector);
> - if (desc->action)
> - return;
> -
> -#ifdef CONFIG_SMP
> - /*
> - * For platforms that do not support interrupt redirect via
> the XTP interface, we
> - * can round-robin the PCI device interrupts to the processors
> - */
> - if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {
> - static int cpu_index = -1;
> -
> - do
> - if (++cpu_index >= NR_CPUS)
> - cpu_index = 0;
> - while (!cpu_online(cpu_index));
> -
> - dest = cpu_physical_id(cpu_index) & 0xffff;
> - } else {
> - /*
> - * Direct the interrupt vector to the current cpu,
> platform redirection
> - * will distribute them.
> - */
> - dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff;
> - }
> -#else
> - /* direct the interrupt vector to the running cpu id */
> - dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff;
> -#endif
> - set_rte(vector, dest, 1);
> -
> - printk(KERN_INFO "IOSAPIC: vector %d -> CPU 0x%04x, enabled\n",
> - vector, dest);
> -}
> -
> -#ifdef CONFIG_ACPI_PCI
> -
> -void __init
> -iosapic_parse_prt (void)
> -{
> - struct acpi_prt_entry *entry;
> - struct list_head *node;
> - unsigned int gsi;
> - int vector;
> - char pci_id[16];
> - struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
> - irq_desc_t *idesc;
> -
> - list_for_each(node, &acpi_prt.entries) {
> - entry = list_entry(node, struct acpi_prt_entry, node);
> -
> - /* We're only interested in static (non-link) entries. */
> - if (entry->link.handle)
> - continue;
> -
> - gsi = entry->link.index;
> -
> - vector = gsi_to_vector(gsi);
> - if (vector < 0) {
> - if (find_iosapic(gsi) < 0)
> - continue;
> -
> - /* allocate a vector for this interrupt line */
> - if (pcat_compat && (gsi < 16))
> - vector = isa_irq_to_vector(gsi);
> - else
> - /* new GSI; allocate a vector for it */
> - vector = assign_irq_vector(AUTO_ASSIGN);
> -
> - register_intr(gsi, vector,
> IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
> - IOSAPIC_LEVEL);
> - }
> - entry->irq = vector;
> - snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]",
> - entry->id.segment, entry->id.bus,
> entry->id.device, 'A' + entry->pin);
> -
> - /*
> - * If vector was previously initialized to a different
> - * handler, re-initialize.
> - */
> - idesc = irq_descp(vector);
> - if (idesc->handler != irq_type)
> - register_intr(gsi, vector,
> IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
> - IOSAPIC_LEVEL);
> -
> - }
> -}
> -
> -#endif /* CONFIG_ACPI */
> === arch/ia64/pci/pci.c 1.48 vs edited ==> --- 1.48/arch/ia64/pci/pci.c Wed Apr 21 15:26:09 2004
> +++ edited/arch/ia64/pci/pci.c Mon May 17 10:39:38 2004
> @@ -134,10 +134,18 @@
> static int __init
> pci_acpi_init (void)
> {
> - if (!acpi_pci_irq_init())
> - printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
> - else
> - printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ
> routing table\n");
> + struct pci_dev *dev = NULL;
> +
> + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
> +
> + /*
> + * PCI IRQ routing is set up by pci_enable_device(), but we
> + * also do it here in case there are still broken drivers that
> + * don't use pci_enable_device().
> + */
> + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
> + acpi_pci_irq_enable(dev);
> +
> return 0;
> }
>
> === arch/x86_64/kernel/mpparse.c 1.27 vs edited ==> --- 1.27/arch/x86_64/kernel/mpparse.c Sat May 15 07:32:27 2004
> +++ edited/arch/x86_64/kernel/mpparse.c Mon May 17 10:39:38 2004
> @@ -887,88 +887,49 @@
>
> extern FADT_DESCRIPTOR acpi_fadt;
>
> -#ifdef CONFIG_ACPI_PCI
> -
> -void __init mp_parse_prt (void)
> +void mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
> {
> - struct list_head *node = NULL;
> - struct acpi_prt_entry *entry = NULL;
> int ioapic = -1;
> int ioapic_pin = 0;
> - int gsi = 0;
> int idx, bit = 0;
> - int edge_level = 0;
> - int active_high_low = 0;
>
> - /*
> - * Parsing through the PCI Interrupt Routing Table (PRT) and program
> - * routing for all static (IOAPIC-direct) entries.
> - */
> - list_for_each(node, &acpi_prt.entries) {
> - entry = list_entry(node, struct acpi_prt_entry, node);
> + /* Don't set up the ACPI SCI because it's already set up */
> + if (acpi_fadt.sci_int = gsi)
> + return;
> +
> + ioapic = mp_find_ioapic(gsi);
> + if (ioapic < 0) {
> + printk(KERN_WARNING "No IOAPIC for GSI 0x%x\n", gsi);
> + return;
> + }
>
> - /* Need to get gsi for dynamic entry */
> - if (entry->link.handle) {
> - gsi > acpi_pci_link_get_irq(entry->link.handle, entry->link.index,
> &edge_level, &active_high_low);
> - if (!gsi)
> - continue;
> - } else {
> - /* Hardwired GSI. Assume PCI standard settings */
> - gsi = entry->link.index;
> - edge_level = 1;
> - active_high_low = 1;
> - }
> -
> - /* Don't set up the ACPI SCI because it's already set up */
> - if (acpi_fadt.sci_int = gsi) {
> - /* we still need to set up the entry's irq */
> - acpi_gsi_to_irq(gsi, &entry->irq);
> - continue;
> - }
> -
> - ioapic = mp_find_ioapic(gsi);
> - if (ioapic < 0)
> - continue;
> - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
> -
> - /*
> - * Avoid pin reprogramming. PRTs typically include
> entries
> - * with redundant pin->gsi mappings (but unique PCI
> devices);
> - * we only only program the IOAPIC on the first.
> - */
> - bit = ioapic_pin % 32;
> - idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
> - if (idx > 3) {
> - printk(KERN_ERR "Invalid reference to IOAPIC pin "
> - "%d-%d\n",
> mp_ioapic_routing[ioapic].apic_id,
> - ioapic_pin);
> - continue;
> - }
> - if ((1<<bit) &
> mp_ioapic_routing[ioapic].pin_programmed[idx]) {
> - Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
> - mp_ioapic_routing[ioapic].apic_id,
> ioapic_pin);
> - acpi_gsi_to_irq(gsi, &entry->irq);
> - continue;
> - }
> -
> - mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
> - if (!io_apic_set_pci_routing(ioapic, ioapic_pin,
> gsi, edge_level, active_high_low)) {
> - acpi_gsi_to_irq(gsi, &entry->irq);
> - }
> - printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n",
> - entry->id.segment, entry->id.bus,
> - entry->id.device, ('A' + entry->pin),
> - mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
> - entry->irq);
> + ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
> +
> + /*
> + * Avoid pin reprogramming. PRTs typically include entries
> + * with redundant pin->gsi mappings (but unique PCI devices);
> + * we only program the IOAPIC on the first.
> + */
> + bit = ioapic_pin % 32;
> + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
> + if (idx > 3) {
> + printk(KERN_ERR "Invalid reference to IOAPIC pin "
> + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
> + ioapic_pin);
> + return;
> + }
> + if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
> + Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
> + mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
> + return;
> }
> -
> - print_IO_APIC();
>
> - return;
> -}
> + mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
>
> -#endif /*CONFIG_ACPI_PCI*/
> + io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
> + edge_level = ACPI_EDGE_SENSITIVE ? 0 : 1,
> + active_high_low = ACPI_ACTIVE_HIGH ? 0 : 1);
> +}
>
> #endif /*CONFIG_X86_IO_APIC*/
> -
> #endif /*CONFIG_ACPI_BOOT*/
> === drivers/acpi/pci_irq.c 1.27 vs edited ==> --- 1.27/drivers/acpi/pci_irq.c Sat Apr 24 00:17:22 2004
> +++ edited/drivers/acpi/pci_irq.c Mon May 17 10:39:38 2004
> @@ -35,12 +35,6 @@
> #include <linux/pm.h>
> #include <linux/pci.h>
> #include <linux/acpi.h>
> -#ifdef CONFIG_X86_IO_APIC
> -#include <asm/mpspec.h>
> -#endif
> -#ifdef CONFIG_IOSAPIC
> -# include <asm/iosapic.h>
> -#endif
> #include <acpi/acpi_bus.h>
> #include <acpi/acpi_drivers.h>
>
> @@ -50,10 +44,6 @@
>
> struct acpi_prt_list acpi_prt;
>
> -#ifdef CONFIG_X86
> -extern void eisa_set_level_irq(unsigned int irq);
> -#endif
> -
>
> /*
> --------------------------------------------------------------------------
> PCI IRQ Routing Table (PRT) Support
> @@ -237,12 +227,18 @@
> PCI Interrupt Routing Support
>
> ------------------------------------------------------------------
> -------- */
>
> -int
> -acpi_pci_irq_lookup (struct pci_bus *bus, int device, int pin)
> +static int
> +acpi_pci_irq_lookup (
> + struct pci_bus *bus,
> + int device,
> + int pin,
> + int *edge_level,
> + int *active_high_low)
> {
> struct acpi_prt_entry *entry = NULL;
> int segment = pci_domain_nr(bus);
> int bus_nr = bus->number;
> + int irq;
>
> ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
>
> @@ -255,28 +251,30 @@
> ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n"));
> return_VALUE(0);
> }
> -
> - if (!entry->irq && entry->link.handle) {
> - entry->irq > acpi_pci_link_get_irq(entry->link.handle, entry->link.index, NULL, NULL);
> - if (!entry->irq) {
> +
> + if (entry->link.handle) {
> + irq = acpi_pci_link_get_irq(entry->link.handle,
> entry->link.index, edge_level, active_high_low);
> + if (!irq) {
> ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid
> IRQ link routing entry\n"));
> return_VALUE(0);
> }
> - }
> - else if (!entry->irq) {
> - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid static
> routing entry (IRQ 0)\n"));
> - return_VALUE(0);
> + } else {
> + irq = entry->link.index;
> + *edge_level = ACPI_LEVEL_SENSITIVE;
> + *active_high_low = ACPI_ACTIVE_LOW;
> }
>
> - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", entry->irq));
> + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
>
> - return_VALUE(entry->irq);
> + return_VALUE(irq);
> }
>
> static int
> acpi_pci_irq_derive (
> struct pci_dev *dev,
> - int pin)
> + int pin,
> + int *edge_level,
> + int *active_high_low)
> {
> struct pci_dev *bridge = dev;
> int irq = 0;
> @@ -308,8 +306,8 @@
> pin = bridge_pin;
> }
>
> - irq = acpi_pci_irq_lookup(bridge->bus,
> - PCI_SLOT(bridge->devfn), pin);
> + irq = acpi_pci_irq_lookup(bridge->bus,
> PCI_SLOT(bridge->devfn),
> + pin, edge_level, active_high_low);
> }
>
> if (!irq) {
> @@ -330,6 +328,8 @@
> {
> int irq = 0;
> u8 pin = 0;
> + int edge_level = ACPI_LEVEL_SENSITIVE;
> + int active_high_low = ACPI_ACTIVE_LOW;
>
> ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
>
> @@ -352,21 +352,22 @@
> * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT
> * values override any BIOS-assigned IRQs set during boot.
> */
> - irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin);
> + irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn),
> pin, &edge_level, &active_high_low);
>
> /*
> * If no PRT entry was found, we'll try to derive an IRQ from the
> * device's parent bridge.
> */
> if (!irq)
> - irq = acpi_pci_irq_derive(dev, pin);
> + irq = acpi_pci_irq_derive(dev, pin, &edge_level,
> &active_high_low);
>
> /*
> * No IRQ known to the ACPI subsystem - maybe the BIOS /
> * driver reported one, then use it. Exit in any case.
> */
> if (!irq) {
> - printk(KERN_WARNING PREFIX "No IRQ known for
> interrupt pin %c of device %s", ('A' + pin), pci_name(dev));
> + printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI",
> + pci_name(dev), ('A' + pin));
> /* Interrupt Line values above 0xF are forbidden */
> if (dev->irq && (dev->irq <= 0xF)) {
> printk(" - using IRQ %d\n", dev->irq);
> @@ -378,62 +379,14 @@
> }
> }
>
> - dev->irq = irq;
> + dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
>
> - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s using IRQ %d\n",
> pci_name(dev), dev->irq));
> -
> - /*
> - * Make sure all (legacy) PCI IRQs are set as level-triggered.
> - */
> -#ifdef CONFIG_X86
> - {
> - static u16 irq_mask;
> - if ((dev->irq < 16) && !((1 << dev->irq) & irq_mask)) {
> - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Setting
> IRQ %d as level-triggered\n", dev->irq));
> - irq_mask |= (1 << dev->irq);
> - eisa_set_level_irq(dev->irq);
> - }
> - }
> -#endif
> -#ifdef CONFIG_IOSAPIC
> - if (acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC)
> - iosapic_enable_intr(dev->irq);
> -#endif
> + printk(KERN_INFO PREFIX "PCI interrupt %s[%c] -> GSI 0x%x "
> + "(%s, %s) -> IRQ %d\n",
> + pci_name(dev), 'A' + pin, irq,
> + (edge_level = ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
> + (active_high_low = ACPI_ACTIVE_LOW) ? "low" : "high",
> + dev->irq);
>
> return_VALUE(dev->irq);
> -}
> -
> -
> -int __init
> -acpi_pci_irq_init (void)
> -{
> - struct pci_dev *dev = NULL;
> -
> - ACPI_FUNCTION_TRACE("acpi_pci_irq_init");
> -
> - if (!acpi_prt.count) {
> - printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ "
> - "routing entries\n");
> - return_VALUE(-ENODEV);
> - }
> -
> - /* Make sure all link devices have a valid IRQ. */
> - if (acpi_pci_link_check()) {
> - return_VALUE(-ENODEV);
> - }
> -
> -#ifdef CONFIG_X86_IO_APIC
> - /* Program IOAPICs using data from PRT entries. */
> - if (acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC)
> - mp_parse_prt();
> -#endif
> -#ifdef CONFIG_IOSAPIC
> - if (acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC)
> - iosapic_parse_prt();
> -#endif
> -
> - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
> - acpi_pci_irq_enable(dev);
> -
> - return_VALUE(0);
> }
> === drivers/acpi/pci_link.c 1.28 vs edited ==> --- 1.28/drivers/acpi/pci_link.c Mon May 10 14:42:35 2004
> +++ edited/drivers/acpi/pci_link.c Mon May 17 10:39:39 2004
> @@ -487,13 +487,13 @@
> };
>
> int
> -acpi_pci_link_check (void)
> +acpi_irq_penalty_init(void)
> {
> struct list_head *node = NULL;
> struct acpi_pci_link *link = NULL;
> int i = 0;
>
> - ACPI_FUNCTION_TRACE("acpi_pci_link_check");
> + ACPI_FUNCTION_TRACE("acpi_irq_penalty_init");
>
> /*
> * Update penalties to facilitate IRQ balancing.
> === drivers/serial/8250_acpi.c 1.8 vs edited ==> --- 1.8/drivers/serial/8250_acpi.c Mon Mar 15 15:53:32 2004
> +++ edited/drivers/serial/8250_acpi.c Mon May 17 10:39:39 2004
> @@ -58,28 +58,18 @@
> static acpi_status acpi_serial_ext_irq(struct serial_struct *req,
> struct acpi_resource_ext_irq
> *ext_irq)
> {
> - if (ext_irq->number_of_interrupts > 0) {
> -#ifdef CONFIG_IA64
> - req->irq = acpi_register_irq(ext_irq->interrupts[0],
> - ext_irq->active_high_low, ext_irq->edge_level);
> -#else
> - req->irq = ext_irq->interrupts[0];
> -#endif
> - }
> + if (ext_irq->number_of_interrupts > 0)
> + req->irq = acpi_register_gsi(ext_irq->interrupts[0],
> + ext_irq->edge_level, ext_irq->active_high_low);
> return AE_OK;
> }
>
> static acpi_status acpi_serial_irq(struct serial_struct *req,
> struct acpi_resource_irq *irq)
> {
> - if (irq->number_of_interrupts > 0) {
> -#ifdef CONFIG_IA64
> - req->irq = acpi_register_irq(irq->interrupts[0],
> - irq->active_high_low, irq->edge_level);
> -#else
> - req->irq = irq->interrupts[0];
> -#endif
> - }
> + if (irq->number_of_interrupts > 0)
> + req->irq = acpi_register_gsi(irq->interrupts[0],
> + irq->edge_level, irq->active_high_low);
> return AE_OK;
> }
>
> === drivers/serial/8250_hcdp.c 1.6 vs edited ==> --- 1.6/drivers/serial/8250_hcdp.c Tue May 4 10:54:32 2004
> +++ edited/drivers/serial/8250_hcdp.c Mon May 17 10:39:39 2004
> @@ -183,16 +183,12 @@
> }
>
> if (HCDP_IRQ_SUPPORTED(hcdp_dev)) {
> -#ifdef CONFIG_IA64
> if (HCDP_PCI_UART(hcdp_dev))
> - port.irq = acpi_register_irq(gsi,
> - ACPI_ACTIVE_LOW,
> ACPI_LEVEL_SENSITIVE);
> + port.irq = acpi_register_gsi(gsi,
> + ACPI_LEVEL_SENSITIVE,
> ACPI_ACTIVE_LOW);
> else
> - port.irq = acpi_register_irq(gsi,
> - ACPI_ACTIVE_HIGH,
> ACPI_EDGE_SENSITIVE);
> -#else
> - port.irq = gsi;
> -#endif
> + port.irq = acpi_register_gsi(gsi,
> + ACPI_EDGE_SENSITIVE,
> ACPI_ACTIVE_HIGH);
> port.flags |= UPF_AUTO_IRQ;
>
> if (HCDP_PCI_UART(hcdp_dev))
> === include/acpi/acpi_drivers.h 1.17 vs edited ==> --- 1.17/include/acpi/acpi_drivers.h Mon Dec 15 17:46:29 2003
> +++ edited/include/acpi/acpi_drivers.h Mon May 17 10:39:40 2004
> @@ -55,7 +55,7 @@
>
> /* ACPI PCI Interrupt Link (pci_link.c) */
>
> -int acpi_pci_link_check (void);
> +int acpi_irq_penalty_init (void);
> int acpi_pci_link_get_irq (acpi_handle handle, int index, int*
> edge_level, int* active_high_low);
>
> /* ACPI PCI Interrupt Routing (pci_irq.c) */
> === include/asm-i386/mpspec.h 1.20 vs edited ==> --- 1.20/include/asm-i386/mpspec.h Mon Apr 12 11:55:30 2004
> +++ edited/include/asm-i386/mpspec.h Mon May 17 10:39:40 2004
> @@ -33,7 +33,7 @@
> extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
> extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8
> trigger, u32 gsi);
> extern void mp_config_acpi_legacy_irqs (void);
> -extern void mp_parse_prt (void);
> +extern void mp_register_gsi (u32 gsi, int edge_level, int
> active_high_low);
> #endif /*CONFIG_ACPI_BOOT*/
>
> #define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
> === include/asm-ia64/iosapic.h 1.13 vs edited ==> --- 1.13/include/asm-ia64/iosapic.h Fri Feb 27 04:39:17 2004
> +++ edited/include/asm-ia64/iosapic.h Mon May 17 10:39:40 2004
> @@ -60,7 +60,6 @@
> unsigned int gsi_base);
> extern int gsi_to_vector (unsigned int gsi);
> extern int gsi_to_irq (unsigned int gsi);
> -extern void __init iosapic_parse_prt (void);
> extern void iosapic_enable_intr (unsigned int vector);
> extern int iosapic_register_intr (unsigned int gsi, unsigned
> long polarity,
> unsigned long trigger);
> === include/asm-x86_64/mpspec.h 1.11 vs edited ==> --- 1.11/include/asm-x86_64/mpspec.h Mon Apr 12 11:55:30 2004
> +++ edited/include/asm-x86_64/mpspec.h Mon May 17 10:39:40 2004
> @@ -189,7 +189,7 @@
> extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
> extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8
> trigger, u32 gsi);
> extern void mp_config_acpi_legacy_irqs (void);
> -extern void mp_parse_prt (void);
> +extern void mp_register_gsi (u32 gsi, int edge_level, int
> active_high_low);
> #endif /*CONFIG_X86_IO_APIC*/
> #endif
>
> === include/linux/acpi.h 1.33 vs edited ==> --- 1.33/include/linux/acpi.h Fri Apr 2 06:48:53 2004
> +++ edited/include/linux/acpi.h Mon May 17 10:39:41 2004
> @@ -437,7 +437,7 @@
> struct pci_dev;
>
> int acpi_pci_irq_enable (struct pci_dev *dev);
> -int acpi_pci_irq_init (void);
> +unsigned int acpi_register_gsi (u32 gsi, int edge_level, int
> active_high_low);
> int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>
> struct acpi_pci_driver {
> -
> To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
prev parent reply other threads:[~2004-05-18 9:30 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-05-17 9:58 [ACPI] Re: [PATCH] ACPI PCI IRQ routing rework Li, Shaohua
2004-05-17 15:41 ` Bjorn Helgaas
2004-05-17 16:16 ` Kenji Kaneshige
2004-05-17 18:41 ` Bjorn Helgaas
2004-05-18 9:30 ` Kenji Kaneshige [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MDEEKOKJPMPMKGHIFAMACEPJEAAA.kaneshige.kenji@jp.fujitsu.com \
--to=kaneshige.kenji@jp.fujitsu.com \
--cc=acpi-devel@lists.sourceforge.net \
--cc=ak@suse.de \
--cc=bjorn.helgaas@hp.com \
--cc=davidm@hpl.hp.com \
--cc=jun.nakajima@intel.com \
--cc=len.brown@intel.com \
--cc=linux-ia64@vger.kernel.org \
--cc=shaohua.li@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox