Commit 034004ee authored by Andy Grover's avatar Andy Grover Committed by Andy Grover

MADT parsing improvements (Paul D & Richard Schaal)

ACPI PCI IRQ improvements (Dominik Brodowski and Paul D)
Wakeup fix (Pavel Machek)
parent bb721a7a
...@@ -48,6 +48,10 @@ ...@@ -48,6 +48,10 @@
#define PREFIX "ACPI: " #define PREFIX "ACPI: "
extern struct acpi_boot_flags acpi_boot;
int acpi_mp_config = 0;
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Boot-time Configuration Boot-time Configuration
...@@ -104,13 +108,15 @@ static int total_cpus __initdata = 0; ...@@ -104,13 +108,15 @@ static int total_cpus __initdata = 0;
/* From mpparse.c */ /* From mpparse.c */
extern void __init MP_processor_info(struct mpc_config_processor *); extern void __init MP_processor_info(struct mpc_config_processor *);
extern void __init MP_ioapic_info (struct mpc_config_ioapic *);
extern void __init MP_lintsrc_info(struct mpc_config_lintsrc *);
int __init int __init
acpi_parse_lapic ( acpi_parse_lapic (
acpi_table_entry_header *header) acpi_table_entry_header *header)
{ {
struct acpi_table_lapic *cpu = NULL; struct acpi_table_lapic *cpu = NULL;
struct mpc_config_processor proc_entry; struct mpc_config_processor processor;
cpu = (struct acpi_table_lapic*) header; cpu = (struct acpi_table_lapic*) header;
if (!cpu) if (!cpu)
...@@ -134,21 +140,21 @@ acpi_parse_lapic ( ...@@ -134,21 +140,21 @@ acpi_parse_lapic (
* the processor ID. Processor features aren't present in * the processor ID. Processor features aren't present in
* the table. * the table.
*/ */
proc_entry.mpc_type = MP_PROCESSOR; processor.mpc_type = MP_PROCESSOR;
proc_entry.mpc_apicid = cpu->id; processor.mpc_apicid = cpu->id;
proc_entry.mpc_cpuflag = CPU_ENABLED; processor.mpc_cpuflag = CPU_ENABLED;
if (cpu->id == boot_cpu_physical_apicid) { if (cpu->id == boot_cpu_physical_apicid) {
/* TBD: Circular reference trying to establish BSP */ /* TBD: Circular reference trying to establish BSP */
proc_entry.mpc_cpuflag |= CPU_BOOTPROCESSOR; processor.mpc_cpuflag |= CPU_BOOTPROCESSOR;
} }
proc_entry.mpc_cpufeature = (boot_cpu_data.x86 << 8) processor.mpc_cpufeature = (boot_cpu_data.x86 << 8)
| (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; | (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
proc_entry.mpc_featureflag = boot_cpu_data.x86_capability[0]; processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
proc_entry.mpc_reserved[0] = 0; processor.mpc_reserved[0] = 0;
proc_entry.mpc_reserved[1] = 0; processor.mpc_reserved[1] = 0;
proc_entry.mpc_apicver = 0x10; /* integrated APIC */ processor.mpc_apicver = 0x10; /* Integrated APIC */
MP_processor_info(&proc_entry); MP_processor_info(&processor);
total_cpus++; total_cpus++;
...@@ -184,7 +190,7 @@ acpi_parse_lapic_nmi ( ...@@ -184,7 +190,7 @@ acpi_parse_lapic_nmi (
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
/* TBD: Support local APIC NMI entries */ /* TBD: Support lapic_nmi entries */
return 0; return 0;
} }
...@@ -199,6 +205,10 @@ acpi_parse_ioapic ( ...@@ -199,6 +205,10 @@ acpi_parse_ioapic (
acpi_table_entry_header *header) acpi_table_entry_header *header)
{ {
struct acpi_table_ioapic *ioapic = NULL; struct acpi_table_ioapic *ioapic = NULL;
/*
struct mpc_config_ioapic mp_ioapic;
struct IO_APIC_reg_01 reg_01;
*/
ioapic = (struct acpi_table_ioapic*) header; ioapic = (struct acpi_table_ioapic*) header;
if (!ioapic) if (!ioapic)
...@@ -206,11 +216,91 @@ acpi_parse_ioapic ( ...@@ -206,11 +216,91 @@ acpi_parse_ioapic (
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
/* TBD: Support ioapic entries */ /*
* Cobble up an entry for the IOAPIC (just as we do for LAPIC entries).
* Note that we aren't doing anything with ioapic->vector, and
* mpc_apicver gets read directly from ioapic.
*/
/*
* TBD: Complete I/O APIC support.
*
mp_ioapic.mpc_type = MP_IOAPIC;
mp_ioapic.mpc_apicid = ioapic->id;
mp_ioapic.mpc_flags = MPC_APIC_USABLE;
mp_ioapic.mpc_apicaddr = ioapic->address;
set_fixmap_nocache(nr_ioapics + FIX_IO_APIC_BASE_0,
mp_ioapic.mpc_apicaddr);
printk("mapped IOAPIC to %08lx (%08lx)\n",
__fix_to_virt(nr_ioapics), mp_ioapic.mpc_apicaddr);
*(int *)&reg_01 = io_apic_read(nr_ioapics, 1);
mp_ioapic.mpc_apicver = reg_01.version;
MP_ioapic_info(&mp_ioapic);
*/
return 0; return 0;
} }
int __init
acpi_parse_int_src_ovr (
acpi_table_entry_header *header)
{
struct acpi_table_int_src_ovr *int_src_ovr = NULL;
/*
struct mpc_config_intsrc my_intsrc;
int i = 0;
*/
int_src_ovr = (struct acpi_table_int_src_ovr*) header;
if (!int_src_ovr)
return -EINVAL;
acpi_table_print_madt_entry(header);
/*
* TBD: Complete I/O APIC support.
*
my_intsrc.mpc_type = MP_INTSRC;
my_intsrc.mpc_irqtype = mp_INT;
my_intsrc.mpc_irqflag = *(unsigned short*)(&(int_src_ovr->flags));
my_intsrc.mpc_srcbus = int_src_ovr->bus;
my_intsrc.mpc_srcbusirq = int_src_ovr->bus_irq;
my_intsrc.mpc_dstapic = 0;
my_intsrc.mpc_dstirq = int_src_ovr->global_irq;
for (i = 0; i < mp_irq_entries; i++) {
if (mp_irqs[i].mpc_srcbusirq == my_intsrc.mpc_srcbusirq) {
mp_irqs[i] = my_intsrc;
break;
}
}
*/
return 0;
}
int __init
acpi_parse_nmi_src (
acpi_table_entry_header *header)
{
struct acpi_table_nmi_src *nmi_src = NULL;
nmi_src = (struct acpi_table_nmi_src*) header;
if (!nmi_src)
return -EINVAL;
acpi_table_print_madt_entry(header);
/* TBD: Support nimsrc entries */
return 0;
}
#endif /*CONFIG_X86_IO_APIC*/ #endif /*CONFIG_X86_IO_APIC*/
...@@ -288,14 +378,115 @@ acpi_find_rsdp ( ...@@ -288,14 +378,115 @@ acpi_find_rsdp (
} }
#endif /*CONFIG_ACPI_BOOT*/ int __init
acpi_boot_init (
char *cmdline)
{
int result = 0;
/* Initialize the ACPI boot-time table parser */
result = acpi_table_init(cmdline);
if (0 != result)
return result;
#ifdef CONFIG_X86_LOCAL_APIC
#ifdef CONFIG_X86_IO_APIC
/*
* MADT
* ----
* Parse the Multiple APIC Description Table (MADT), if exists.
* Note that this table provides platform SMP configuration
* information -- the successor to MPS tables.
*/
if (!acpi_boot.madt) {
printk(KERN_INFO PREFIX "MADT parsing disabled via command-line\n");
return 0;
}
result = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
if (0 == result) {
printk(KERN_WARNING PREFIX "MADT not present\n");
return 0;
}
else if (0 > result) {
printk(KERN_ERR PREFIX "Error parsing MADT\n");
return result;
}
else if (1 < result)
printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n");
/* Local APIC */
result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr);
if (0 > result) {
printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
return result;
}
result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic);
if (1 > result) {
printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries!\n");
return -ENODEV;
}
result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi);
if (0 > result) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
return result;
}
/* I/O APIC */
result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic);
if (1 > result) {
printk(KERN_ERR PREFIX "Error parsing MADT - no IOAPIC entries!\n");
return -ENODEV;
}
acpi_mp_config = 1;
/*
* TBD: Complete I/O APIC support.
*
construct_default_ACPI_table();
*/
result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr);
if (0 > result) {
printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
return result;
}
result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
if (0 > result) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
return result;
}
/* Make boot-up look pretty */
printk("%d CPUs total\n", total_cpus);
#endif /*CONFIG_X86_IO_APIC*/
#endif /*CONFIG_X86_LOCAL_APIC*/
#ifdef CONFIG_SERIAL_ACPI
/*
* TBD: Need phased approach to table parsing (only do those absolutely
* required during boot-up). Recommend expanding concept of fix-
* feature devices (ACPI Bus driver) to include table-based devices
* such as serial ports, EC, SMBus, etc.
*/
/* acpi_table_parse(ACPI_SPCR, acpi_parse_spcr);*/
#endif /*CONFIG_SERIAL_ACPI*/
return 0;
}
#endif /*CONFIG_ACPI_BOOT*/
/* --------------------------------------------------------------------------
PCI Interrupt Routing Support
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PCI
int __init int __init
acpi_get_interrupt_model ( acpi_get_interrupt_model (
int *type) int *type)
...@@ -304,15 +495,13 @@ acpi_get_interrupt_model ( ...@@ -304,15 +495,13 @@ acpi_get_interrupt_model (
return -EINVAL; return -EINVAL;
#ifdef CONFIG_X86_IO_APIC #ifdef CONFIG_X86_IO_APIC
if (io_apic_assign_pci_irqs) *type = ACPI_INT_MODEL_IOAPIC;
*type = ACPI_PCI_ROUTING_IOAPIC; #else
else *type = ACPI_INT_MODEL_PIC;
#endif #endif
*type = ACPI_PCI_ROUTING_PIC;
return 0; return 0;
} }
#endif
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
......
...@@ -18,6 +18,8 @@ wakeup_code: ...@@ -18,6 +18,8 @@ wakeup_code:
addw $(wakeup_data - wakeup_code) >> 4, %ax addw $(wakeup_data - wakeup_code) >> 4, %ax
movw %ax, %ds movw %ax, %ds
movw %ax, %ss
mov $(wakeup_stack - wakeup_data), %sp # Private stack is needed for ASUS board
# set up page table # set up page table
movl (real_save_cr3 - wakeup_data), %eax movl (real_save_cr3 - wakeup_data), %eax
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/acpi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/config.h> #include <linux/config.h>
...@@ -24,6 +23,7 @@ ...@@ -24,6 +23,7 @@
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/acpi.h>
#include <asm/mtrr.h> #include <asm/mtrr.h>
#include <asm/mpspec.h> #include <asm/mpspec.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -31,9 +31,6 @@ ...@@ -31,9 +31,6 @@
/* Have we found an MP table */ /* Have we found an MP table */
int smp_found_config; int smp_found_config;
/* Have we found an ACPI MADT table */
int acpi_found_madt = 0;
/* /*
* Various Linux-internal data structures created from the * Various Linux-internal data structures created from the
* MP-table. * MP-table.
...@@ -41,8 +38,6 @@ int acpi_found_madt = 0; ...@@ -41,8 +38,6 @@ int acpi_found_madt = 0;
int apic_version [MAX_APICS]; int apic_version [MAX_APICS];
int mp_bus_id_to_type [MAX_MP_BUSSES]; int mp_bus_id_to_type [MAX_MP_BUSSES];
int mp_bus_id_to_node [MAX_MP_BUSSES]; int mp_bus_id_to_node [MAX_MP_BUSSES];
int mp_bus_id_to_local [MAX_MP_BUSSES];
int quad_local_to_mp_bus_id [NR_CPUS/4][4];
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
int mp_current_pci_id; int mp_current_pci_id;
...@@ -69,19 +64,6 @@ static unsigned int num_processors; ...@@ -69,19 +64,6 @@ static unsigned int num_processors;
/* Bitmask of physically existing CPUs */ /* Bitmask of physically existing CPUs */
unsigned long phys_cpu_present_map; unsigned long phys_cpu_present_map;
/* ACPI MADT entry parsing functions */
#ifdef CONFIG_ACPI_BOOT
extern struct acpi_boot_flags acpi_boot;
#ifdef CONFIG_X86_LOCAL_APIC
extern int acpi_parse_lapic (acpi_table_entry_header *header);
extern int acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header);
extern int acpi_parse_lapic_nmi (acpi_table_entry_header *header);
#endif /*CONFIG_X86_LOCAL_APIC*/
#ifdef CONFIG_X86_IO_APIC
extern int acpi_parse_ioapic (acpi_table_entry_header *header);
#endif /*CONFIG_X86_IO_APIC*/
#endif /*CONFIG_ACPI_BOOT*/
/* /*
* Intel MP BIOS table parsing routines: * Intel MP BIOS table parsing routines:
*/ */
...@@ -255,17 +237,13 @@ void __init MP_processor_info (struct mpc_config_processor *m) ...@@ -255,17 +237,13 @@ void __init MP_processor_info (struct mpc_config_processor *m)
static void __init MP_bus_info (struct mpc_config_bus *m) static void __init MP_bus_info (struct mpc_config_bus *m)
{ {
char str[7]; char str[7];
int quad;
memcpy(str, m->mpc_bustype, 6); memcpy(str, m->mpc_bustype, 6);
str[6] = 0; str[6] = 0;
if (clustered_apic_mode) { if (clustered_apic_mode) {
quad = translation_table[mpc_record]->trans_quad; mp_bus_id_to_node[m->mpc_busid] = translation_table[mpc_record]->trans_quad;
mp_bus_id_to_node[m->mpc_busid] = quad; printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, mp_bus_id_to_node[m->mpc_busid]);
mp_bus_id_to_local[m->mpc_busid] = translation_table[mpc_record]->trans_local;
quad_local_to_mp_bus_id[quad][translation_table[mpc_record]->trans_local] = m->mpc_busid;
printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, quad);
} else { } else {
Dprintk("Bus #%d is %s\n", m->mpc_busid, str); Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
} }
...@@ -342,14 +320,13 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m) ...@@ -342,14 +320,13 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
static void __init MP_translation_info (struct mpc_config_translation *m) static void __init MP_translation_info (struct mpc_config_translation *m)
{ {
printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local); printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type,
m->trans_quad, m->trans_global, m->trans_local);
if (mpc_record >= MAX_MPC_ENTRY) if (mpc_record >= MAX_MPC_ENTRY)
printk("MAX_MPC_ENTRY exceeded!\n"); printk("MAX_MPC_ENTRY exceeded!\n");
else else
translation_table[mpc_record] = m; /* stash this for later */ translation_table[mpc_record] = m; /* stash this for later */
if (m->trans_quad+1 > numnodes)
numnodes = m->trans_quad+1;
} }
/* /*
...@@ -440,10 +417,10 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) ...@@ -440,10 +417,10 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
printk("APIC at: 0x%lX\n",mpc->mpc_lapic); printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
/* /*
* Save the local APIC address, it might be non-default, * Save the local APIC address (it might be non-default), but only
* but only if we're not using the ACPI tables * if we're not using the ACPI tables.
*/ */
if (!acpi_found_madt) if (!acpi_mp_config)
mp_lapic_addr = mpc->mpc_lapic; mp_lapic_addr = mpc->mpc_lapic;
if (clustered_apic_mode && mpc->mpc_oemptr) { if (clustered_apic_mode && mpc->mpc_oemptr) {
...@@ -464,7 +441,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) ...@@ -464,7 +441,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
(struct mpc_config_processor *)mpt; (struct mpc_config_processor *)mpt;
/* ACPI may already have provided this one for us */ /* ACPI may already have provided this one for us */
if (!acpi_found_madt) if (!acpi_mp_config)
MP_processor_info(m); MP_processor_info(m);
mpt += sizeof(*m); mpt += sizeof(*m);
count += sizeof(*m); count += sizeof(*m);
...@@ -515,6 +492,10 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) ...@@ -515,6 +492,10 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
} }
++mpc_record; ++mpc_record;
} }
if (clustered_apic_mode && nr_ioapics > 2) {
/* don't initialise IO apics on secondary quads */
nr_ioapics = 2;
}
if (!num_processors) if (!num_processors)
printk(KERN_ERR "SMP mptable: no processors registered!\n"); printk(KERN_ERR "SMP mptable: no processors registered!\n");
return num_processors; return num_processors;
...@@ -686,20 +667,6 @@ void __init get_smp_config (void) ...@@ -686,20 +667,6 @@ void __init get_smp_config (void)
{ {
struct intel_mp_floating *mpf = mpf_found; struct intel_mp_floating *mpf = mpf_found;
#ifdef CONFIG_ACPI_BOOT
/*
* Check if the MADT exists, and if so, use it to get processor
* information (ACPI_MADT_LAPIC). The MADT supports the concept
* of both logical (e.g. HT) and physical processor(s); where the
* MPS only supports physical.
*/
if (acpi_boot.madt) {
acpi_found_madt = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
if (acpi_found_madt > 0)
acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic);
}
#endif /*CONFIG_ACPI_BOOT*/
printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
if (mpf->mpf_feature2 & (1<<7)) { if (mpf->mpf_feature2 & (1<<7)) {
printk(" IMCR and PIC compatibility mode.\n"); printk(" IMCR and PIC compatibility mode.\n");
......
...@@ -540,6 +540,18 @@ static void __init pirq_find_router(void) ...@@ -540,6 +540,18 @@ static void __init pirq_find_router(void)
pirq_router_dev->slot_name); pirq_router_dev->slot_name);
} }
static struct irq_info *pirq_get_info(struct pci_dev *dev)
{
struct irq_routing_table *rt = pirq_table;
int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
struct irq_info *info;
for (info = rt->slots; entries--; info++)
if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
return info;
return NULL;
}
static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs) static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{ {
} }
...@@ -557,44 +569,67 @@ static int acpi_lookup_irq ( ...@@ -557,44 +569,67 @@ static int acpi_lookup_irq (
/* TBD: Select IRQ from possible to improve routing performance. */ /* TBD: Select IRQ from possible to improve routing performance. */
result = acpi_prt_get_irq(dev, pin, &irq); result = acpi_prt_get_irq(dev, pin, &irq);
if ((0 != result) || !irq) { if (!irq)
printk(KERN_ERR "PCI: Unable to resolve IRQ for device %s\n", result = -ENODEV;
dev->slot_name); if (0 != result) {
printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s\n",
'A'+pin, dev->slot_name);
return result; return result;
} }
dev->irq = irq;
if (!assign) {
/* only check for the IRQ */
printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", irq, printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", irq,
dev->slot_name); dev->slot_name);
return 1;
}
dev->irq = irq; /* also assign an IRQ */
if (irq && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
result = acpi_prt_set_irq(dev, pin, irq);
if (0 != result) {
printk(KERN_WARNING "PCI: Could not assign IRQ %d to device %s\n", irq, dev->slot_name);
return result;
}
pirq_penalty[irq]++; eisa_set_level_irq(irq);
printk(KERN_INFO "PCI: Assigned IRQ %d for device %s\n", irq, dev->slot_name);
}
return 1; return 1;
} }
#endif /* CONFIG_ACPI_PCI */ #endif /* CONFIG_ACPI_PCI */
static struct irq_info *pirq_get_info(struct pci_dev *dev) static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
{ {
struct irq_routing_table *rt = pirq_table; u8 pin;
int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
struct irq_info *info; struct irq_info *info;
int i, pirq, newirq;
for (info = rt->slots; entries--; info++) int irq = 0;
if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn)) u32 mask;
return info;
return NULL;
}
static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
{
struct irq_router *r = pirq_router; struct irq_router *r = pirq_router;
struct irq_info *info;
int newirq, pirq, i, irq = 0;
struct pci_dev *dev2; struct pci_dev *dev2;
char *msg = NULL; char *msg = NULL;
u32 mask;
/* Find IRQ pin */
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (!pin) {
DBG(" -> no interrupt pin\n");
return 0;
}
pin = pin - 1;
#ifdef CONFIG_ACPI_PCI
/* Use ACPI to lookup IRQ */
if (pci_use_acpi_routing)
return acpi_lookup_irq(dev, pin, assign);
#endif
/* Find IRQ routing entry */
if (!pirq_table) if (!pirq_table)
return 0; return 0;
...@@ -605,7 +640,6 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign) ...@@ -605,7 +640,6 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
DBG(" -> not found in routing table\n"); DBG(" -> not found in routing table\n");
return 0; return 0;
} }
pirq = info->irq[pin].link; pirq = info->irq[pin].link;
mask = info->irq[pin].bitmap; mask = info->irq[pin].bitmap;
if (!pirq) { if (!pirq) {
...@@ -629,10 +663,6 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign) ...@@ -629,10 +663,6 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
* reported by the device if possible. * reported by the device if possible.
*/ */
newirq = dev->irq; newirq = dev->irq;
if (!((1 << newirq) & mask)) {
if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0;
else printk(KERN_WARNING "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n", newirq, dev->slot_name);
}
if (!newirq && assign) { if (!newirq && assign) {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if (!(mask & (1 << i))) if (!(mask & (1 << i)))
...@@ -651,8 +681,7 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign) ...@@ -651,8 +681,7 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
irq = pirq & 0xf; irq = pirq & 0xf;
DBG(" -> hardcoded IRQ %d\n", irq); DBG(" -> hardcoded IRQ %d\n", irq);
msg = "Hardcoded"; msg = "Hardcoded";
} else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \ } else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq))) {
((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
DBG(" -> got IRQ %d\n", irq); DBG(" -> got IRQ %d\n", irq);
msg = "Found"; msg = "Found";
} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
...@@ -686,9 +715,7 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign) ...@@ -686,9 +715,7 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
continue; continue;
if (info->irq[pin].link == pirq) { if (info->irq[pin].link == pirq) {
/* We refuse to override the dev->irq information. Give a warning! */ /* We refuse to override the dev->irq information. Give a warning! */
if ( dev2->irq && dev2->irq != irq && \ if (dev2->irq && dev2->irq != irq) {
(!(pci_probe & PCI_USE_PIRQ_MASK) || \
((1 << dev2->irq) & mask)) ) {
printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n", printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
dev2->slot_name, dev2->irq, irq); dev2->slot_name, dev2->irq, irq);
continue; continue;
...@@ -702,38 +729,20 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign) ...@@ -702,38 +729,20 @@ static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
return 1; return 1;
} }
static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
{
u8 pin;
/* Find IRQ routing entry */
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (!pin) {
DBG("PCI: %s: no interrupt pin\n", dev->slot_name);
return 0;
}
pin -= 1;
#ifdef CONFIG_ACPI_PCI
if (pci_use_acpi_routing)
return acpi_lookup_irq(dev, pin, assign);
else
#endif
return pirq_lookup_irq(dev, pin, assign);
}
void __init pcibios_irq_init(void) void __init pcibios_irq_init(void)
{ {
DBG("PCI: IRQ init\n"); DBG("PCI: IRQ init\n");
#ifdef CONFIG_ACPI_PCI #ifdef CONFIG_ACPI_PCI
if (acpi_prts.count && !(pci_probe & PCI_NO_ACPI_ROUTING)) { if (!(pci_probe & PCI_NO_ACPI_ROUTING)) {
if (acpi_prts.count) {
printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
pci_use_acpi_routing = 1; pci_use_acpi_routing = 1;
return; return;
} }
if (!acpi_prts.count) else
printk(KERN_INFO "PCI: Invalid acpi_prts [%d]\n", acpi_prts.count); printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");
}
#endif #endif
pirq_table = pirq_find_routing_table(); pirq_table = pirq_find_routing_table();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment