[PATCH] -rt: x86_64 ioapic register cache

From: Karsten Wiese
Date: Sun Nov 27 2005 - 12:02:36 EST



x86_64 ioapic register cache

new "_init setup_IO_APIC_early()" to consolidate data structs.
Config selectable register cache.
Removes "int sis_apic_bug". Sensible?

signed-off-by: Karsten Wiese <annabellesgarden@xxxxxxxx>


diff -urp rt12/arch/x86_64/Kconfig rt12-kw/arch/x86_64/Kconfig
--- rt12/arch/x86_64/Kconfig 2005-11-13 23:49:27.000000000 +0100
+++ rt12-kw/arch/x86_64/Kconfig 2005-11-13 23:51:26.000000000 +0100
@@ -171,6 +171,16 @@ config X86_IO_APIC
bool
default y

+config X86_IOAPIC_FAST
+ bool "enhanced IO-APIC support"
+ depends on X86_IO_APIC
+ default y
+ help
+ this option will activate further optimizations in the IO-APIC
+ code. NOTE: this is experimental code, and disabled by default.
+ Symptoms of non-working systems are boot-time lockups, stray or
+ screaming interrupts and other interrupt related weirdnesses.
+
config X86_LOCAL_APIC
bool
default y
diff -urp rt12/arch/x86_64/kernel/apic.c rt12-kw/arch/x86_64/kernel/apic.c
--- rt12/arch/x86_64/kernel/apic.c 2005-11-13 23:49:27.000000000 +0100
+++ rt12-kw/arch/x86_64/kernel/apic.c 2005-11-13 23:51:26.000000000 +0100
@@ -628,15 +628,13 @@ void __init init_apic_mappings(void)
int i;

for (i = 0; i < nr_ioapics; i++) {
- if (smp_found_config) {
- ioapic_phys = mp_ioapics[i].mpc_apicaddr;
- } else {
+ if (!smp_found_config) {
ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
ioapic_phys = __pa(ioapic_phys);
+ set_fixmap_nocache(idx, ioapic_phys);
+ printk("faked IOAPIC to %016lx (%016lx)\n",
+ __fix_to_virt(idx), ioapic_phys);
}
- set_fixmap_nocache(idx, ioapic_phys);
- apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n",
- __fix_to_virt(idx), ioapic_phys);
idx++;
}
}
diff -urp rt12/arch/x86_64/kernel/io_apic.c rt12-kw/arch/x86_64/kernel/io_apic.c
--- rt12/arch/x86_64/kernel/io_apic.c 2005-11-13 23:49:27.000000000 +0100
+++ rt12-kw/arch/x86_64/kernel/io_apic.c 2005-11-13 23:51:26.000000000 +0100
@@ -30,6 +30,7 @@
#include <linux/mc146818rtc.h>
#include <linux/acpi.h>
#include <linux/sysdev.h>
+#include <linux/bootmem.h>

#include <asm/io.h>
#include <asm/smp.h>
@@ -40,8 +41,6 @@

#define __apicdebuginit __init

-int sis_apic_bug; /* not actually supported, dummy for compile */
-
static int no_timer_check;

int disable_timer_pin_1 __initdata;
@@ -49,11 +48,6 @@ int disable_timer_pin_1 __initdata;
static DEFINE_RAW_SPINLOCK(ioapic_lock);

/*
- * # of IRQ routing registers
- */
-int nr_ioapic_registers[MAX_IO_APICS];
-
-/*
* Rough estimation of how many shared IRQs there are, can
* be changed anytime.
*/
@@ -79,22 +73,138 @@ int vector_irq[NR_VECTORS] __read_mostly
#define vector_to_irq(vector) (vector)
#endif

+#ifdef CONFIG_X86_IOAPIC_FAST
+# define IOAPIC_CACHE
+#endif
+
+/*
+ * some chips need this commented out:
+ */
+// #define IOAPIC_POSTFLUSH
+/*
+ * K8T800 seams not to need it.
+ */
+
+struct ioapic_data_struct {
+ volatile unsigned int *base;
+#ifdef IOAPIC_CACHE
+ unsigned int reg_set;
+#endif
+ int nr_registers; // # of IRQ routing registers
+ struct sys_device dev;
+ struct IO_APIC_route_entry *entry;
+#ifdef IOAPIC_CACHE
+ u32 cached_val[0];
+#endif
+};
+
+static struct ioapic_data_struct *ioapic_data[MAX_IO_APICS];
+
+
+static int nr_ioapic_registers(int apic)
+{
+ return ioapic_data[apic]->nr_registers;
+}
+
+static inline unsigned int __raw_io_apic_read(struct ioapic_data_struct *ioapic, unsigned int reg)
+{
+#ifdef IOAPIC_CACHE
+ ioapic->reg_set = reg;
+#endif
+ ioapic->base[0] = reg;
+ return ioapic->base[4];
+}
+
+
+#ifdef IOAPIC_CACHE
+static void __init ioapic_cache_init(struct ioapic_data_struct *ioapic)
+{
+ int reg;
+ for (reg = 0; reg < (0x10 + 2 * ioapic->nr_registers); reg++)
+ ioapic->cached_val[reg] = __raw_io_apic_read(ioapic, reg);
+}
+#endif
+
+#if !defined(IOAPIC_CACHE) || defined(IOAPIC_POSTFLUSH)
+static unsigned int raw_io_apic_read(struct ioapic_data_struct *ioapic, unsigned int reg)
+{
+ unsig ned int val = __raw_io_apic_read(ioapic, reg);
+
+#ifdef IOAPIC_CACHE
+ ioapic->cached_val[reg] = val;
+#endif
+ return val;
+}
+#endif
+
+static inline unsigned int __io_apic_read(struct ioapic_data_struct *ioapic, unsigned int reg)
+{
+#ifdef IOAPIC_CACHE
+ ioapic->reg_set = -1;
+ return ioapic->cached_val[reg];
+#else
+ return raw_io_apic_read(ioapic, reg);
+#endif
+}
+
+static unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+{
+ return __io_apic_read(ioapic_data[apic], reg);
+}
+
+static void __io_apic_write(struct ioapic_data_struct *ioapic, unsigned int reg, unsigned int val)
+{
+#ifdef IOAPIC_CACHE
+ ioapic->cached_val[reg] = val;
+ ioapic->reg_set = reg;
+#endif
+ ioapic->base[0] = reg;
+ ioapic->base[4] = val;
+}
+
+static void io_apic_write(unsigned int apic, unsigned int reg, unsigned int val)
+{
+ return __io_apic_write(ioapic_data[apic], reg, val);
+}
+
+/*
+ * Re-write a value: to be used for read-modify-write
+ * cycles where the read already set up the index register.
+ */
+static inline void io_apic_modify(struct ioapic_data_struct *ioapic, unsigned int reg, unsigned int val)
+{
+#ifdef IOAPIC_CACHE
+ if (ioapic->reg_set != reg) {
+ ioapic->base[0] = reg;
+ ioapic->reg_set = reg;
+ }
+ ioapic->cached_val[reg] = val;
+#endif
+ ioapic->base[4] = val;
+
+#ifdef IOAPIC_POSTFLUSH
+ /* Force POST flush by reading: */
+ val = raw_io_apic_read(ioapic, reg);
+#endif
+}
+
#define __DO_ACTION(R, ACTION, FINAL) \
\
{ \
int pin; \
struct irq_pin_list *entry = irq_2_pin + irq; \
+ struct ioapic_data_struct *ioapic; \
\
for (;;) { \
- unsigned int reg; \
+ unsigned int reg, val; \
pin = entry->pin; \
if (pin == -1) \
break; \
- reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \
- reg ACTION; \
- io_apic_modify(entry->apic, reg); \
- /* Force POST flush by reading: */ \
- reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \
+ ioapic = ioapic_data[entry->apic]; \
+ reg = 0x10 + R + pin*2; \
+ val = __io_apic_read(ioapic, reg); \
+ val ACTION; \
+ io_apic_modify(ioapic, reg, val); \
\
if (!entry->next) \
break; \
@@ -207,9 +317,10 @@ static void clear_IO_APIC (void)
{
int apic, pin;

- for (apic = 0; apic < nr_ioapics; apic++)
- for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+ for (apic = 0; apic < nr_ioapics; apic++) {
+ for (pin = 0; pin < nr_ioapic_registers(apic); pin++)
clear_IO_APIC_pin(apic, pin);
+ }
}

/*
@@ -638,7 +749,7 @@ static int pin_2_irq(int idx, int apic,
*/
i = irq = 0;
while (i < apic)
- irq += nr_ioapic_registers[i++];
+ irq += nr_ioapic_registers(i++);
irq += pin;
break;
}
@@ -672,7 +783,7 @@ static inline int IO_APIC_irq_trigger(in
int apic, idx, pin;

for (apic = 0; apic < nr_ioapics; apic++) {
- for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+ for (pin = 0; pin < nr_ioapic_registers(apic); pin++) {
idx = find_irq_entry(apic,pin,mp_INT);
if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
return irq_trigger(idx);
@@ -749,7 +860,7 @@ static void __init setup_IO_APIC_irqs(vo
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");

for (apic = 0; apic < nr_ioapics; apic++) {
- for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+ for (pin = 0; pin < nr_ioapic_registers(apic); pin++) {

/*
* add it to the IO-APIC irq-routing table:
@@ -869,7 +980,7 @@ void __apicdebuginit print_IO_APIC(void)
printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
for (i = 0; i < nr_ioapics; i++)
printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
- mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);
+ mp_ioapics[i].mpc_apicid, nr_ioapic_registers(i));

/*
* We are a bit conservative about what we expect. We have to
@@ -1123,9 +1234,7 @@ void __apicdebuginit print_PIC(void)

static void __init enable_IO_APIC(void)
{
- union IO_APIC_reg_01 reg_01;
int i;
- unsigned long flags;

for (i = 0; i < PIN_MAP_SIZE; i++) {
irq_2_pin[i].pin = -1;
@@ -1136,16 +1245,6 @@ static void __init enable_IO_APIC(void)
pirq_entries[i] = -1;

/*
- * The number of IO-APIC IRQ registers (== #pins):
- */
- for (i = 0; i < nr_ioapics; i++) {
- spin_lock_irqsave(&ioapic_lock, flags);
- reg_01.raw = io_apic_read(i, 1);
- spin_unlock_irqrestore(&ioapic_lock, flags);
- nr_ioapic_registers[i] = reg_01.bits.entries+1;
- }
-
- /*
* Do not trust the IO-APIC being empty at bootup
*/
clear_IO_APIC();
@@ -1206,7 +1305,7 @@ void disable_IO_APIC(void)
static void __init setup_ioapic_ids_from_mpc (void)
{
union IO_APIC_reg_00 reg_00;
- int apic;
+ int ioapic;
int i;
unsigned char old_id;
unsigned long flags;
@@ -1214,51 +1313,51 @@ static void __init setup_ioapic_ids_from
/*
* Set the IOAPIC ID to the value stored in the MPC table.
*/
- for (apic = 0; apic < nr_ioapics; apic++) {
+ for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {

/* Read the register 0 value */
spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(apic, 0);
+ reg_00.raw = io_apic_read(ioapic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);

- old_id = mp_ioapics[apic].mpc_apicid;
+ old_id = mp_ioapics[ioapic].mpc_apicid;


- printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid);
+ printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[ioapic].mpc_apicid);


/*
* We need to adjust the IRQ routing table
* if the ID changed.
*/
- if (old_id != mp_ioapics[apic].mpc_apicid)
+ if (old_id != mp_ioapics[ioapic].mpc_apicid)
for (i = 0; i < mp_irq_entries; i++)
if (mp_irqs[i].mpc_dstapic == old_id)
mp_irqs[i].mpc_dstapic
- = mp_ioapics[apic].mpc_apicid;
+ = mp_ioapics[ioapic].mpc_apicid;

/*
* Read the right value from the MPC table and
* write it into the ID register.
*/
apic_printk(APIC_VERBOSE,KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
- mp_ioapics[apic].mpc_apicid);
+ mp_ioapics[ioapic].mpc_apicid);

- reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
+ reg_00.bits.ID = mp_ioapics[ioapic].mpc_apicid;
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0, reg_00.raw);
+ io_apic_write(ioapic, 0, reg_00.raw);
spin_unlock_irqrestore(&ioapic_lock, flags);

/*
* Sanity check
*/
spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(apic, 0);
+ reg_00.raw = io_apic_read(ioapic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);
- if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
+ if (reg_00.bits.ID != mp_ioapics[ioapic].mpc_apicid)
printk("could not set ID!\n");
else
- apic_printk(APIC_VERBOSE," ok.\n");
+ apic_printk(APIC_VERBOSE, " ok.\n");
}
}

@@ -1314,7 +1413,6 @@ static int __init timer_irq_works(void)
* This is not complete - we should be able to fake
* an edge even if it isn't on the 8259A...
*/
-
static unsigned int startup_edge_ioapic_irq(unsigned int irq)
{
int was_pending = 0;
@@ -1783,6 +1881,46 @@ static int __init notimercheck(char *s)
}
__setup("no_timer_check", notimercheck);

+void __init setup_IO_APIC_early(int _ioapic)
+{
+ union IO_APIC_reg_01 reg_01;
+ unsigned long flags;
+ int size, nr_ioapic_registers;
+ volatile int *ioapic;
+ if (ioapic_data[_ioapic]) {
+ printk("been in %s before !!!!!\n", __FUNCTION__);
+ return;
+ }
+
+ set_fixmap_nocache(FIX_IO_APIC_BASE_0 + _ioapic, mp_ioapics[_ioapic].mpc_apicaddr);
+ printk(KERN_DEBUG "mapped IOAPIC to %016lx (%016x)\n",
+ __fix_to_virt(FIX_IO_APIC_BASE_0 + _ioapic), mp_ioapics[_ioapic].mpc_apicaddr);
+ /*
+ * The number of IO-APIC IRQ registers (== #pins):
+ */
+ ioapic = IO_APIC_BASE(_ioapic);
+ spin_lock_irqsave(&ioapic_lock, flags);
+ ioapic[0] = 1;
+ reg_01.raw = ioapic[4];
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+ nr_ioapic_registers = reg_01.bits.entries+1;
+
+ /*
+ * Initialsize ioapic_data struct:
+ */
+ size = sizeof(struct ioapic_data_struct);
+#ifdef IOAPIC_CACHE
+ size += 0x10 * sizeof(u32) + nr_ioapic_registers * sizeof(struct IO_APIC_route_entry);
+#endif
+ ioapic_data[_ioapic] = alloc_bootmem(size);
+ memset(ioapic_data[_ioapic], 0, size);
+ ioapic_data[_ioapic]->nr_registers = nr_ioapic_registers;
+ ioapic_data[_ioapic]->base = ioapic;
+#ifdef IOAPIC_CACHE
+ ioapic_cache_init(ioapic_data[_ioapic]);
+#endif
+}
+
/*
*
* IRQ's that are handled by the PIC in the MPS IOAPIC case.
@@ -1816,25 +1954,20 @@ void __init setup_IO_APIC(void)
print_IO_APIC();
}

-struct sysfs_ioapic_data {
- struct sys_device dev;
- struct IO_APIC_route_entry entry[0];
-};
-static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
-
static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
{
struct IO_APIC_route_entry *entry;
- struct sysfs_ioapic_data *data;
unsigned long flags;
int i;
+ struct ioapic_data_struct *ioapic;
+
+ ioapic = ioapic_data[dev->id];
+ entry = ioapic->entry;

- data = container_of(dev, struct sysfs_ioapic_data, dev);
- entry = data->entry;
spin_lock_irqsave(&ioapic_lock, flags);
- for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
- *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
- *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
+ for (i = 0; i < ioapic_data[dev->id]->nr_registers; i ++, entry ++) {
+ *(((int *)entry) + 1) = __io_apic_read(ioapic, 0x11 + 2 * i);
+ *(((int *)entry) + 0) = __io_apic_read(ioapic, 0x10 + 2 * i);
}
spin_unlock_irqrestore(&ioapic_lock, flags);

@@ -1844,23 +1977,23 @@ static int ioapic_suspend(struct sys_dev
static int ioapic_resume(struct sys_device *dev)
{
struct IO_APIC_route_entry *entry;
- struct sysfs_ioapic_data *data;
unsigned long flags;
union IO_APIC_reg_00 reg_00;
int i;
+ struct ioapic_data_struct *ioapic;

- data = container_of(dev, struct sysfs_ioapic_data, dev);
- entry = data->entry;
+ ioapic = ioapic_data[dev->id];
+ entry = ioapic->entry;

spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(dev->id, 0);
+ reg_00.raw = __io_apic_read(ioapic, 0);
if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
- io_apic_write(dev->id, 0, reg_00.raw);
+ __io_apic_write(ioapic, 0, reg_00.raw);
}
- for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
- io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
- io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
+ for (i = 0; i < ioapic_data[dev->id]->nr_registers; i ++, entry ++) {
+ __io_apic_write(ioapic, 0x11+2*i, *(((int *)entry)+1));
+ __io_apic_write(ioapic, 0x10+2*i, *(((int *)entry)+0));
}
spin_unlock_irqrestore(&ioapic_lock, flags);

@@ -1883,21 +2016,20 @@ static int __init ioapic_init_sysfs(void
return error;

for (i = 0; i < nr_ioapics; i++ ) {
- size = sizeof(struct sys_device) + nr_ioapic_registers[i]
- * sizeof(struct IO_APIC_route_entry);
- mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
- if (!mp_ioapic_data[i]) {
+ size = ioapic_data[i]->nr_registers * sizeof(struct IO_APIC_route_entry);
+ ioapic_data[i]->entry = kmalloc(size, GFP_KERNEL);
+ if (!ioapic_data[i]->entry) {
printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
continue;
}
- memset(mp_ioapic_data[i], 0, size);
- dev = &mp_ioapic_data[i]->dev;
- dev->id = i;
+ memset(ioapic_data[i]->entry, 0, size);
+ dev = &ioapic_data[i]->dev;
+ dev->id = i;
dev->cls = &ioapic_sysdev_class;
error = sysdev_register(dev);
if (error) {
- kfree(mp_ioapic_data[i]);
- mp_ioapic_data[i] = NULL;
+ kfree(ioapic_data[i]->entry);
+ ioapic_data[i]->entry = NULL;
printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
continue;
}
@@ -2012,7 +2144,7 @@ void __init setup_ioapic_dest(void)
return;

for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
- for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+ for (pin = 0; pin < nr_ioapic_registers(ioapic); pin++) {
irq_entry = find_irq_entry(ioapic, pin, mp_INT);
if (irq_entry == -1)
continue;
diff -urp rt12/arch/x86_64/kernel/mpparse.c rt12-kw/arch/x86_64/kernel/mpparse.c
--- rt12/arch/x86_64/kernel/mpparse.c 2005-11-01 11:31:49.000000000 +0100
+++ rt12-kw/arch/x86_64/kernel/mpparse.c 2005-11-13 23:51:26.000000000 +0100
@@ -207,6 +207,7 @@ static void __init MP_ioapic_info (struc
return;
}
mp_ioapics[nr_ioapics] = *m;
+ setup_IO_APIC_early(nr_ioapics);
nr_ioapics++;
}

@@ -769,7 +770,7 @@ void __init mp_register_ioapic (
mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
mp_ioapics[idx].mpc_apicaddr = address;

- set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+ setup_IO_APIC_early(idx);
mp_ioapics[idx].mpc_apicid = id;
mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);

diff -urp rt12/include/asm-x86_64/io_apic.h rt12-kw/include/asm-x86_64/io_apic.h
--- rt12/include/asm-x86_64/io_apic.h 2005-11-13 23:49:32.000000000 +0100
+++ rt12-kw/include/asm-x86_64/io_apic.h 2005-11-13 23:51:26.000000000 +0100
@@ -103,7 +103,6 @@ union IO_APIC_reg_03 {
* # of IO-APICs and # of IRQ routing registers
*/
extern int nr_ioapics;
-extern int nr_ioapic_registers[MAX_IO_APICS];

enum ioapic_irq_destination_types {
dest_Fixed = 0,
@@ -160,27 +159,6 @@ extern struct mpc_config_intsrc mp_irqs[
/* non-0 if default (table-less) MP configuration */
extern int mpc_default_type;

-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
-{
- *IO_APIC_BASE(apic) = reg;
- return *(IO_APIC_BASE(apic)+4);
-}
-
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
-{
- *IO_APIC_BASE(apic) = reg;
- *(IO_APIC_BASE(apic)+4) = value;
-}
-
-/*
- * Re-write a value: to be used for read-modify-write
- * cycles where the read already set up the index register.
- */
-static inline void io_apic_modify(unsigned int apic, unsigned int value)
-{
- *(IO_APIC_BASE(apic)+4) = value;
-}
-
/*
* Synchronize the IO-APIC and the CPU by doing
* a dummy read from the IO-APIC
@@ -205,7 +183,7 @@ extern int io_apic_get_redir_entries (in
extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int, int);
#endif

-extern int sis_apic_bug; /* dummy */
+extern void setup_IO_APIC_early(int ioapic);

#else /* !CONFIG_X86_IO_APIC */
#define io_apic_assign_pci_irqs 0
diff -urp rt12/drivers/pci/quirks.c rt12-kw/drivers/pci/quirks.c
--- rt12/drivers/pci/quirks.c 2005-11-01 11:31:51.000000000 +0100
+++ rt12-kw/drivers/pci/quirks.c 2005-11-13 23:51:26.000000000 +0100
@@ -543,12 +543,14 @@ static void __devinit quirk_amd_ioapic(s
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic );

+#if !defined(CONFIG_X86_64)
static void __init quirk_ioapic_rmw(struct pci_dev *dev)
{
if (dev->devfn == 0 && dev->bus->number == 0)
sis_apic_bug = 1;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw );
+#endif

int pci_msi_quirk;

diff -urp rt12/kernel/irq/spurious.c rt12-kw/kernel/irq/spurious.c
--- rt12/kernel/irq/spurious.c 2005-11-13 23:49:33.000000000 +0100
+++ rt12-kw/kernel/irq/spurious.c 2005-11-13 23:51:26.000000000 +0100
@@ -164,11 +164,13 @@ void note_interrupt(unsigned int irq, ir
* The interrupt is stuck
*/
__report_bad_irq(irq, desc, action_ret);
-#ifdef CONFIG_X86_IO_APIC
- if (!sis_apic_bug) {
- sis_apic_bug = 1;
- printk(KERN_ERR "turning off IO-APIC fast mode.\n");
- }
+#ifndef CONFIG_X86_64
+# ifdef CONFIG_X86_IO_APIC
+ if (!sis_apic_bug) {
+ sis_apic_bug = 1;
+ printk(KERN_ERR "turning off IO-APIC fast mode.\n");
+ }
+# endif
#else
/*
* Now kill the IRQ