Am Mittwoch, 29. Juni 2005 11:15 schrieb William Weston:
> On Wed, 29 Jun 2005, Ingo Molnar wrote:
>
> > > [...] but i think i'm going to revert that, it's causing too many
> > > problems all around.
> >
> > reverted it and this enabled the removal of the extra ->disable() you
> > noticed - this should further speed up the IOAPIC code. These changes
> > are in the -50-34 kernel i just uploaded.
>
> -50-34 fixed the wakeup latency regression I was seeing on my Athlon box
> with -50-33, and seems a bit more responsive than -50-25. Max wakeup
> latency is back down to 14us (from 39us), even while running JACK (xrun
> free) and two instances of burnK7. Overall system response is probably
> the best I've seen with the RT kernels ;-}
>
attached patch for io_apic.c lets
1. gcc 3.4.3 optimize io_apic access a little better.
2. CONFIG_X86_UP_IOAPIC_FAST work here.
Didn't check, if it really speeds up things.
Karsten
--- arch/i386/kernel/io_apic.c-50-33 2005-06-29 16:27:40.000000000 +0200
+++ arch/i386/kernel/io_apic.c 2005-06-29 16:27:40.000000000 +0200
@@ -138,14 +138,22 @@
/*
* Cache register values:
*/
-static unsigned int io_apic_cache[MAX_IO_APICS][MAX_IOAPIC_CACHE]
+static struct {
+ unsigned int reg;
+ unsigned int val[MAX_IOAPIC_CACHE];
+} io_apic_cache[MAX_IO_APICS]
____cacheline_aligned_in_smp;
#endif
inline unsigned int __raw_io_apic_read(unsigned int apic, unsigned int reg)
{
- *IO_APIC_BASE(apic) = reg;
- return *(IO_APIC_BASE(apic)+4);
+ volatile unsigned int *io_apic;
+ io_apic = IO_APIC_BASE(apic);
+#ifdef IOAPIC_CACHE
+ io_apic_cache[apic].reg = reg;
+#endif
+ io_apic[0] = reg;
+ return io_apic[4];
}
unsigned int raw_io_apic_read(unsigned int apic, unsigned int reg)
@@ -153,7 +161,7 @@
unsigned int val = __raw_io_apic_read(apic, reg);
#ifdef IOAPIC_CACHE
- io_apic_cache[apic][reg] = val;
+ io_apic_cache[apic].val[reg] = val;
#endif
return val;
}
@@ -172,14 +180,17 @@
}
return __raw_io_apic_read(apic, reg);
}
- if (io_apic_cache[apic][reg] && !sis_apic_bug)
- return io_apic_cache[apic][reg];
+ if (io_apic_cache[apic].val[reg] && !sis_apic_bug) {
+ io_apic_cache[apic].reg = -1;
+ return io_apic_cache[apic].val[reg];
+ }
#endif
return raw_io_apic_read(apic, reg);
}
void io_apic_write(unsigned int apic, unsigned int reg, unsigned int val)
{
+ volatile unsigned int *io_apic;
#ifdef IOAPIC_CACHE
if (unlikely(reg >= MAX_IOAPIC_CACHE)) {
static int once = 1;
@@ -191,10 +202,14 @@
dump_stack();
}
} else
- io_apic_cache[apic][reg] = val;
+ io_apic_cache[apic].val[reg] = val;
#endif
- *IO_APIC_BASE(apic) = reg;
- *(IO_APIC_BASE(apic)+4) = val;
+ io_apic = IO_APIC_BASE(apic);
+#ifdef IOAPIC_CACHE
+ io_apic_cache[apic].reg = reg;
+#endif
+ io_apic[0] = reg;
+ io_apic[4] = val;
}
/*
@@ -214,34 +229,42 @@
*/
void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val)
{
+ volatile unsigned int *io_apic;
#ifdef IOAPIC_CACHE
- io_apic_cache[apic][reg] = val;
+ io_apic_cache[apic].val[reg] = val;
#endif
- if (unlikely(sis_apic_bug))
- *IO_APIC_BASE(apic) = reg;
- *(IO_APIC_BASE(apic)+4) = val;
+ io_apic = IO_APIC_BASE(apic);
+#ifdef IOAPIC_CACHE
+ if (io_apic_cache[apic].reg != reg || sis_apic_bug) {
+ io_apic_cache[apic].reg = reg;
+#else
+ if (unlikely(sis_apic_bug)) {
+#endif
+ io_apic[0] = reg;
+ }
+ io_apic[4] = val;
#ifndef IOAPIC_POSTFLUSH
if (unlikely(sis_apic_bug))
#endif
/*
* Force POST flush by reading:
*/
- val = *(IO_APIC_BASE(apic)+4);
+ val = io_apic[4];
}
static void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable)
{
struct irq_pin_list *entry = irq_2_pin + irq;
- unsigned int pin, reg;
+ unsigned int pin, val;
for (;;) {
pin = entry->pin;
if (pin == -1)
break;
- reg = io_apic_read(entry->apic, 0x10 + pin*2);
- reg &= ~disable;
- reg |= enable;
- io_apic_modify(entry->apic, 0x10 + pin*2, reg);
+ val = io_apic_read(entry->apic, 0x10 + pin*2);
+ val &= ~disable;
+ val |= enable;
+ io_apic_modify(entry->apic, 0x10 + pin*2, val);
if (!entry->next)
break;
entry = irq_2_pin + entry->next;
@@ -306,9 +329,13 @@
{
int apic, pin;
- for (apic = 0; apic < nr_ioapics; apic++)
+ for (apic = 0; apic < nr_ioapics; apic++) {
+#ifdef IOAPIC_CACHE
+ io_apic_cache[apic].reg = -1;
+#endif
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
clear_IO_APIC_pin(apic, pin);
+ }
}
static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]