|
|
|
@@ -37,15 +37,10 @@
|
|
|
|
|
#include <asm/pgtable.h>
|
|
|
|
|
#include <asm/io_apic.h>
|
|
|
|
|
#include <asm/apic.h>
|
|
|
|
|
#include <asm/genapic.h>
|
|
|
|
|
#include <asm/io.h>
|
|
|
|
|
#include <asm/mpspec.h>
|
|
|
|
|
#include <asm/smp.h>
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
|
|
|
# include <mach_apic.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static int __initdata acpi_force = 0;
|
|
|
|
|
u32 acpi_rsdt_forced;
|
|
|
|
|
#ifdef CONFIG_ACPI
|
|
|
|
@@ -56,16 +51,7 @@ int acpi_disabled = 1;
|
|
|
|
|
EXPORT_SYMBOL(acpi_disabled);
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_X86_64
|
|
|
|
|
|
|
|
|
|
#include <asm/proto.h>
|
|
|
|
|
|
|
|
|
|
#else /* X86 */
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
|
|
|
#include <mach_apic.h>
|
|
|
|
|
#include <mach_mpparse.h>
|
|
|
|
|
#endif /* CONFIG_X86_LOCAL_APIC */
|
|
|
|
|
|
|
|
|
|
# include <asm/proto.h>
|
|
|
|
|
#endif /* X86 */
|
|
|
|
|
|
|
|
|
|
#define BAD_MADT_ENTRY(entry, end) ( \
|
|
|
|
@@ -222,7 +208,8 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
|
|
|
|
|
madt->address);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id);
|
|
|
|
|
default_acpi_madt_oem_check(madt->header.oem_id,
|
|
|
|
|
madt->header.oem_table_id);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@@ -867,7 +854,7 @@ static struct {
|
|
|
|
|
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
|
|
|
|
|
} mp_ioapic_routing[MAX_IO_APICS];
|
|
|
|
|
|
|
|
|
|
static int mp_find_ioapic(int gsi)
|
|
|
|
|
int mp_find_ioapic(int gsi)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
@@ -882,6 +869,16 @@ static int mp_find_ioapic(int gsi)
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int mp_find_ioapic_pin(int ioapic, int gsi)
|
|
|
|
|
{
|
|
|
|
|
if (WARN_ON(ioapic == -1))
|
|
|
|
|
return -1;
|
|
|
|
|
if (WARN_ON(gsi > mp_ioapic_routing[ioapic].gsi_end))
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
return gsi - mp_ioapic_routing[ioapic].gsi_base;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u8 __init uniq_ioapic_id(u8 id)
|
|
|
|
|
{
|
|
|
|
|
#ifdef CONFIG_X86_32
|
|
|
|
@@ -895,8 +892,8 @@ static u8 __init uniq_ioapic_id(u8 id)
|
|
|
|
|
DECLARE_BITMAP(used, 256);
|
|
|
|
|
bitmap_zero(used, 256);
|
|
|
|
|
for (i = 0; i < nr_ioapics; i++) {
|
|
|
|
|
struct mp_config_ioapic *ia = &mp_ioapics[i];
|
|
|
|
|
__set_bit(ia->mp_apicid, used);
|
|
|
|
|
struct mpc_ioapic *ia = &mp_ioapics[i];
|
|
|
|
|
__set_bit(ia->apicid, used);
|
|
|
|
|
}
|
|
|
|
|
if (!test_bit(id, used))
|
|
|
|
|
return id;
|
|
|
|
@@ -928,47 +925,70 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
|
|
|
|
|
|
|
|
|
|
idx = nr_ioapics;
|
|
|
|
|
|
|
|
|
|
mp_ioapics[idx].mp_type = MP_IOAPIC;
|
|
|
|
|
mp_ioapics[idx].mp_flags = MPC_APIC_USABLE;
|
|
|
|
|
mp_ioapics[idx].mp_apicaddr = address;
|
|
|
|
|
mp_ioapics[idx].type = MP_IOAPIC;
|
|
|
|
|
mp_ioapics[idx].flags = MPC_APIC_USABLE;
|
|
|
|
|
mp_ioapics[idx].apicaddr = address;
|
|
|
|
|
|
|
|
|
|
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
|
|
|
|
|
mp_ioapics[idx].mp_apicid = uniq_ioapic_id(id);
|
|
|
|
|
mp_ioapics[idx].apicid = uniq_ioapic_id(id);
|
|
|
|
|
#ifdef CONFIG_X86_32
|
|
|
|
|
mp_ioapics[idx].mp_apicver = io_apic_get_version(idx);
|
|
|
|
|
mp_ioapics[idx].apicver = io_apic_get_version(idx);
|
|
|
|
|
#else
|
|
|
|
|
mp_ioapics[idx].mp_apicver = 0;
|
|
|
|
|
mp_ioapics[idx].apicver = 0;
|
|
|
|
|
#endif
|
|
|
|
|
/*
|
|
|
|
|
* Build basic GSI lookup table to facilitate gsi->io_apic lookups
|
|
|
|
|
* and to prevent reprogramming of IOAPIC pins (PCI GSIs).
|
|
|
|
|
*/
|
|
|
|
|
mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mp_apicid;
|
|
|
|
|
mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;
|
|
|
|
|
mp_ioapic_routing[idx].gsi_base = gsi_base;
|
|
|
|
|
mp_ioapic_routing[idx].gsi_end = gsi_base +
|
|
|
|
|
io_apic_get_redir_entries(idx);
|
|
|
|
|
|
|
|
|
|
printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, "
|
|
|
|
|
"GSI %d-%d\n", idx, mp_ioapics[idx].mp_apicid,
|
|
|
|
|
mp_ioapics[idx].mp_apicver, mp_ioapics[idx].mp_apicaddr,
|
|
|
|
|
printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
|
|
|
|
|
"GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
|
|
|
|
|
mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr,
|
|
|
|
|
mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end);
|
|
|
|
|
|
|
|
|
|
nr_ioapics++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void assign_to_mp_irq(struct mp_config_intsrc *m,
|
|
|
|
|
struct mp_config_intsrc *mp_irq)
|
|
|
|
|
int __init acpi_probe_gsi(void)
|
|
|
|
|
{
|
|
|
|
|
memcpy(mp_irq, m, sizeof(struct mp_config_intsrc));
|
|
|
|
|
int idx;
|
|
|
|
|
int gsi;
|
|
|
|
|
int max_gsi = 0;
|
|
|
|
|
|
|
|
|
|
if (acpi_disabled)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (!acpi_ioapic)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
max_gsi = 0;
|
|
|
|
|
for (idx = 0; idx < nr_ioapics; idx++) {
|
|
|
|
|
gsi = mp_ioapic_routing[idx].gsi_end;
|
|
|
|
|
|
|
|
|
|
if (gsi > max_gsi)
|
|
|
|
|
max_gsi = gsi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return max_gsi + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int mp_irq_cmp(struct mp_config_intsrc *mp_irq,
|
|
|
|
|
struct mp_config_intsrc *m)
|
|
|
|
|
static void assign_to_mp_irq(struct mpc_intsrc *m,
|
|
|
|
|
struct mpc_intsrc *mp_irq)
|
|
|
|
|
{
|
|
|
|
|
return memcmp(mp_irq, m, sizeof(struct mp_config_intsrc));
|
|
|
|
|
memcpy(mp_irq, m, sizeof(struct mpc_intsrc));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void save_mp_irq(struct mp_config_intsrc *m)
|
|
|
|
|
static int mp_irq_cmp(struct mpc_intsrc *mp_irq,
|
|
|
|
|
struct mpc_intsrc *m)
|
|
|
|
|
{
|
|
|
|
|
return memcmp(mp_irq, m, sizeof(struct mpc_intsrc));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void save_mp_irq(struct mpc_intsrc *m)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
@@ -986,7 +1006,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
|
|
|
|
|
{
|
|
|
|
|
int ioapic;
|
|
|
|
|
int pin;
|
|
|
|
|
struct mp_config_intsrc mp_irq;
|
|
|
|
|
struct mpc_intsrc mp_irq;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Convert 'gsi' to 'ioapic.pin'.
|
|
|
|
@@ -994,7 +1014,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
|
|
|
|
|
ioapic = mp_find_ioapic(gsi);
|
|
|
|
|
if (ioapic < 0)
|
|
|
|
|
return;
|
|
|
|
|
pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
|
|
|
|
|
pin = mp_find_ioapic_pin(ioapic, gsi);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TBD: This check is for faulty timer entries, where the override
|
|
|
|
@@ -1004,13 +1024,13 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
|
|
|
|
|
if ((bus_irq == 0) && (trigger == 3))
|
|
|
|
|
trigger = 1;
|
|
|
|
|
|
|
|
|
|
mp_irq.mp_type = MP_INTSRC;
|
|
|
|
|
mp_irq.mp_irqtype = mp_INT;
|
|
|
|
|
mp_irq.mp_irqflag = (trigger << 2) | polarity;
|
|
|
|
|
mp_irq.mp_srcbus = MP_ISA_BUS;
|
|
|
|
|
mp_irq.mp_srcbusirq = bus_irq; /* IRQ */
|
|
|
|
|
mp_irq.mp_dstapic = mp_ioapics[ioapic].mp_apicid; /* APIC ID */
|
|
|
|
|
mp_irq.mp_dstirq = pin; /* INTIN# */
|
|
|
|
|
mp_irq.type = MP_INTSRC;
|
|
|
|
|
mp_irq.irqtype = mp_INT;
|
|
|
|
|
mp_irq.irqflag = (trigger << 2) | polarity;
|
|
|
|
|
mp_irq.srcbus = MP_ISA_BUS;
|
|
|
|
|
mp_irq.srcbusirq = bus_irq; /* IRQ */
|
|
|
|
|
mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */
|
|
|
|
|
mp_irq.dstirq = pin; /* INTIN# */
|
|
|
|
|
|
|
|
|
|
save_mp_irq(&mp_irq);
|
|
|
|
|
}
|
|
|
|
@@ -1020,7 +1040,7 @@ void __init mp_config_acpi_legacy_irqs(void)
|
|
|
|
|
int i;
|
|
|
|
|
int ioapic;
|
|
|
|
|
unsigned int dstapic;
|
|
|
|
|
struct mp_config_intsrc mp_irq;
|
|
|
|
|
struct mpc_intsrc mp_irq;
|
|
|
|
|
|
|
|
|
|
#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
|
|
|
|
|
/*
|
|
|
|
@@ -1045,7 +1065,7 @@ void __init mp_config_acpi_legacy_irqs(void)
|
|
|
|
|
ioapic = mp_find_ioapic(0);
|
|
|
|
|
if (ioapic < 0)
|
|
|
|
|
return;
|
|
|
|
|
dstapic = mp_ioapics[ioapic].mp_apicid;
|
|
|
|
|
dstapic = mp_ioapics[ioapic].apicid;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Use the default configuration for the IRQs 0-15. Unless
|
|
|
|
@@ -1055,16 +1075,14 @@ void __init mp_config_acpi_legacy_irqs(void)
|
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
|
|
for (idx = 0; idx < mp_irq_entries; idx++) {
|
|
|
|
|
struct mp_config_intsrc *irq = mp_irqs + idx;
|
|
|
|
|
struct mpc_intsrc *irq = mp_irqs + idx;
|
|
|
|
|
|
|
|
|
|
/* Do we already have a mapping for this ISA IRQ? */
|
|
|
|
|
if (irq->mp_srcbus == MP_ISA_BUS
|
|
|
|
|
&& irq->mp_srcbusirq == i)
|
|
|
|
|
if (irq->srcbus == MP_ISA_BUS && irq->srcbusirq == i)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Do we already have a mapping for this IOAPIC pin */
|
|
|
|
|
if (irq->mp_dstapic == dstapic &&
|
|
|
|
|
irq->mp_dstirq == i)
|
|
|
|
|
if (irq->dstapic == dstapic && irq->dstirq == i)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1073,13 +1091,13 @@ void __init mp_config_acpi_legacy_irqs(void)
|
|
|
|
|
continue; /* IRQ already used */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mp_irq.mp_type = MP_INTSRC;
|
|
|
|
|
mp_irq.mp_irqflag = 0; /* Conforming */
|
|
|
|
|
mp_irq.mp_srcbus = MP_ISA_BUS;
|
|
|
|
|
mp_irq.mp_dstapic = dstapic;
|
|
|
|
|
mp_irq.mp_irqtype = mp_INT;
|
|
|
|
|
mp_irq.mp_srcbusirq = i; /* Identity mapped */
|
|
|
|
|
mp_irq.mp_dstirq = i;
|
|
|
|
|
mp_irq.type = MP_INTSRC;
|
|
|
|
|
mp_irq.irqflag = 0; /* Conforming */
|
|
|
|
|
mp_irq.srcbus = MP_ISA_BUS;
|
|
|
|
|
mp_irq.dstapic = dstapic;
|
|
|
|
|
mp_irq.irqtype = mp_INT;
|
|
|
|
|
mp_irq.srcbusirq = i; /* Identity mapped */
|
|
|
|
|
mp_irq.dstirq = i;
|
|
|
|
|
|
|
|
|
|
save_mp_irq(&mp_irq);
|
|
|
|
|
}
|
|
|
|
@@ -1116,7 +1134,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
|
|
|
|
return gsi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
|
|
|
|
|
ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_X86_32
|
|
|
|
|
if (ioapic_renumber_irq)
|
|
|
|
@@ -1190,22 +1208,22 @@ int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
|
|
|
|
|
u32 gsi, int triggering, int polarity)
|
|
|
|
|
{
|
|
|
|
|
#ifdef CONFIG_X86_MPPARSE
|
|
|
|
|
struct mp_config_intsrc mp_irq;
|
|
|
|
|
struct mpc_intsrc mp_irq;
|
|
|
|
|
int ioapic;
|
|
|
|
|
|
|
|
|
|
if (!acpi_ioapic)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* print the entry should happen on mptable identically */
|
|
|
|
|
mp_irq.mp_type = MP_INTSRC;
|
|
|
|
|
mp_irq.mp_irqtype = mp_INT;
|
|
|
|
|
mp_irq.mp_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
|
|
|
|
|
mp_irq.type = MP_INTSRC;
|
|
|
|
|
mp_irq.irqtype = mp_INT;
|
|
|
|
|
mp_irq.irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
|
|
|
|
|
(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
|
|
|
|
|
mp_irq.mp_srcbus = number;
|
|
|
|
|
mp_irq.mp_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
|
|
|
|
|
mp_irq.srcbus = number;
|
|
|
|
|
mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
|
|
|
|
|
ioapic = mp_find_ioapic(gsi);
|
|
|
|
|
mp_irq.mp_dstapic = mp_ioapic_routing[ioapic].apic_id;
|
|
|
|
|
mp_irq.mp_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
|
|
|
|
|
mp_irq.dstapic = mp_ioapic_routing[ioapic].apic_id;
|
|
|
|
|
mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
|
|
|
|
|
|
|
|
|
|
save_mp_irq(&mp_irq);
|
|
|
|
|
#endif
|
|
|
|
@@ -1332,7 +1350,7 @@ static void __init acpi_process_madt(void)
|
|
|
|
|
if (!error) {
|
|
|
|
|
acpi_lapic = 1;
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_X86_GENERICARCH
|
|
|
|
|
#ifdef CONFIG_X86_BIGSMP
|
|
|
|
|
generic_bigsmp_probe();
|
|
|
|
|
#endif
|
|
|
|
|
/*
|
|
|
|
@@ -1344,9 +1362,8 @@ static void __init acpi_process_madt(void)
|
|
|
|
|
acpi_ioapic = 1;
|
|
|
|
|
|
|
|
|
|
smp_found_config = 1;
|
|
|
|
|
#ifdef CONFIG_X86_32
|
|
|
|
|
setup_apic_routing();
|
|
|
|
|
#endif
|
|
|
|
|
if (apic->setup_apic_routing)
|
|
|
|
|
apic->setup_apic_routing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (error == -EINVAL) {
|
|
|
|
|