Commit 3a40a2c1 authored by Len Brown's avatar Len Brown

Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.7

into intel.com:/home/lenb/bk/linux-acpi-test-2.6.7
parents 331cc23e c76f4547
......@@ -437,6 +437,35 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
return 0;
}
unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
{
unsigned int irq;
#ifdef CONFIG_PCI
/*
* Make sure all (legacy) PCI IRQs are set as level-triggered.
*/
if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
static u16 irq_mask;
extern void eisa_set_level_irq(unsigned int irq);
if ((gsi < 16) && !((1 << gsi) & irq_mask)) {
Dprintk(KERN_DEBUG PREFIX "Setting GSI %u as level-triggered\n", gsi);
irq_mask |= (1 << gsi);
eisa_set_level_irq(gsi);
}
}
#endif
#ifdef CONFIG_X86_IO_APIC
if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
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,
......
......@@ -1025,96 +1025,56 @@ void __init mp_config_acpi_legacy_irqs (void)
}
}
extern FADT_DESCRIPTOR acpi_fadt;
#ifdef CONFIG_ACPI_PCI
int (*platform_rename_gsi)(int ioapic, int gsi);
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);
/* 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;
}
#ifdef CONFIG_ACPI_BUS
/* Don't set up the ACPI SCI because it's already set up */
if (acpi_fadt.sci_int == gsi)
return;
#endif
/* 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 (platform_rename_gsi)
gsi = platform_rename_gsi(ioapic, gsi);
/*
* 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;
}
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
return;
}
mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
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 (platform_rename_gsi)
gsi = platform_rename_gsi(ioapic, gsi);
/*
* 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();
mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
return;
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_ACPI_BOOT*/
#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,31 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
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);
#ifdef CONFIG_X86_IO_APIC
if (acpi_ioapic)
print_IO_APIC();
#endif
return 0;
}
......
......@@ -521,9 +521,14 @@ acpi_numa_arch_fixup (void)
#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);
......@@ -548,7 +553,7 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
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;
}
......@@ -662,16 +667,4 @@ acpi_gsi_to_irq (u32 gsi, unsigned int *irq)
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 */
......@@ -483,7 +483,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
index = find_iosapic(gsi);
if (index < 0) {
printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi);
printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", __FUNCTION__, gsi);
return;
}
......@@ -512,6 +512,42 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
}
}
static unsigned int
get_target_cpu (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 @@ iosapic_register_intr (unsigned int gsi,
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 = get_target_cpu();
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 %u (%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 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
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 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
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 %u (%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 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
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 %u (%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_init (unsigned long phys_addr, unsigned int gsi_base)
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 */
......@@ -134,10 +134,18 @@ static struct pci_ops pci_root_ops = {
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;
}
......
......@@ -888,91 +888,54 @@ void __init mp_config_acpi_legacy_irqs (void)
return;
}
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);
/* 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;
}
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
return;
/* 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;
}
#ifdef CONFIG_ACPI_BUS
/* Don't set up the ACPI SCI because it's already set up */
if (acpi_fadt.sci_int == gsi)
return;
#endif
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0)
continue;
ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
return;
}
/*
* 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;
}
ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
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);
/*
* 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*/
......@@ -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 @@ ACPI_MODULE_NAME ("pci_irq")
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 @@ acpi_pci_irq_add_prt (
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_pci_irq_lookup (struct pci_bus *bus, int device, int pin)
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 @@ acpi_pci_irq_derive (
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 @@ acpi_pci_irq_enable (
{
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 @@ acpi_pci_irq_enable (
* 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 @@ acpi_pci_irq_enable (
}
}
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 %u "
"(%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);
}
......@@ -487,13 +487,13 @@ static int __initdata acpi_irq_penalty[ACPI_MAX_IRQS] = {
};
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.
......
......@@ -131,7 +131,7 @@ acpi_table_print_madt_entry (
{
struct acpi_table_ioapic *p =
(struct acpi_table_ioapic*) header;
printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] global_irq_base[0x%x])\n",
printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
p->id, p->address, p->global_irq_base);
}
break;
......@@ -185,8 +185,8 @@ acpi_table_print_madt_entry (
{
struct acpi_table_iosapic *p =
(struct acpi_table_iosapic*) header;
printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] global_irq_base[0x%x] address[%p])\n",
p->id, p->global_irq_base, (void *) (unsigned long) p->address);
printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
p->id, (void *) (unsigned long) p->address, p->global_irq_base);
}
break;
......
......@@ -57,28 +57,18 @@ static acpi_status acpi_serial_port(struct serial_struct *req,
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;
}
......
......@@ -183,16 +183,12 @@ setup_serial_hcdp(void *tablep)
}
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))
......
......@@ -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) */
......
......@@ -33,7 +33,7 @@ extern void mp_register_lapic_address (u64 address);
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)
......
......@@ -60,7 +60,6 @@ extern void __init iosapic_init (unsigned long address,
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);
......
......@@ -189,7 +189,7 @@ extern void mp_register_lapic_address (u64 address);
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
......
......@@ -413,6 +413,8 @@ static inline int acpi_boot_init(void)
#endif /*!CONFIG_ACPI_BOOT*/
unsigned int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low);
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
#ifdef CONFIG_ACPI_PCI
......@@ -437,8 +439,6 @@ extern struct acpi_prt_list acpi_prt;
struct pci_dev;
int acpi_pci_irq_enable (struct pci_dev *dev);
int acpi_pci_irq_init (void);
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
struct acpi_pci_driver {
struct acpi_pci_driver *next;
......
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