I don't like the fact that irqtune helsp interrupt performance, because the
way Linux tries to handle interrupts it _shouldn't_ make a difference. The
fact that irqtune obviously _does_ make a difference would indicate that the
irq handling has some problem, and irqtune just masks that problem by
changing the interrupt priority levels.
Essentially, Linux does a "EOI" immediately when it gets the interrupt, and
that EOI _should_ mean that all other interrupts will get through, regardless
of whether they have lower or higher priority (because the EOI tells the
interrupt controller that it can forget about the interrupt that we're now
handling). As such there should be no effect from irqtune, because the
interrupt priorities shouldn't really matter.
However, Linux uses the "nonspecific" EOI to do this, and while that should
work, it may turn out that some interrupt controllers don't like it, and for
some reason mask the wrong interrupt. People who see a difference with
irqtune, could you test this patch instead (it changes the low-level
interrupt handlers to use the "specific" EOI to tell the controller that that
specific interrupt is now handled).
I'd be very interested in reactions to this patch indeed, can you please
try it out and tell me whether this makes any difference?
(This is against 2.0.14, but it should patch in cleanly against just about
any reasonably recent kernel. Certainly all of the 2.0.x series)
Linus
----
--- v2.0.14/linux/include/asm-i386/irq.h Sun Mar 10 09:28:56 1996
+++ linux/include/asm-i386/irq.h Fri Aug 23 08:18:12 1996
@@ -81,7 +81,7 @@
* a bit - without them it seems that the harddisk driver won't work on
* all hardware. Arghh.
*/
-#define ACK_FIRST(mask) \
+#define ACK_FIRST(mask,nr) \
"inb $0x21,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
@@ -90,10 +90,10 @@
"outb %al,$0x21\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
- "1:\tmovb $0x20,%al\n\t" \
+ "1:\tmovb $0x60+"#nr",%al\n\t" \
"outb %al,$0x20\n\t"
-#define ACK_SECOND(mask) \
+#define ACK_SECOND(mask,nr) \
"inb $0xA1,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
@@ -102,11 +102,12 @@
"outb %al,$0xA1\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
- "1:\tmovb $0x20,%al\n\t" \
+ "1:\tmovb $0x60+"#nr",%al\n\t" \
"outb %al,$0xA0\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
- "1:\toutb %al,$0x20\n\t"
+ "1:\tmovb $0x62,%al\n\t" \
+ "outb %al,$0x20\n\t"
#define UNBLK_FIRST(mask) \
"inb $0x21,%al\n\t" \
@@ -207,7 +208,7 @@
"pushl $-"#nr"-2\n\t" \
SAVE_ALL \
ENTER_KERNEL \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
"incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
"sti\n\t" \
"movl %esp,%ebx\n\t" \
@@ -224,7 +225,7 @@
SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
ENTER_KERNEL \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
"incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
"pushl $" #nr "\n\t" \
"call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
@@ -238,7 +239,7 @@
SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
ENTER_KERNEL \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
LEAVE_KERNEL \
RESTORE_MOST);
@@ -255,7 +256,7 @@
"pushl $-"#nr"-2\n\t" \
SAVE_ALL \
ENTER_KERNEL \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
"incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
"movl %esp,%ebx\n\t" \
"pushl %ebx\n\t" \
@@ -283,7 +284,7 @@
"pushl $-"#nr"-2\n\t" \
SAVE_ALL \
ENTER_KERNEL \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
"incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
"sti\n\t" \
"movl %esp,%ebx\n\t" \
@@ -301,7 +302,7 @@
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
SMP_PROF_IPI_CNT \
"pushl $" #nr "\n\t" \
"call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
@@ -312,7 +313,7 @@
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
RESTORE_MOST);
#define BUILD_RESCHEDIRQ(nr) \
@@ -345,7 +346,7 @@
SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
"pushl $-"#nr"-2\n\t" \
SAVE_ALL \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
"incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
"sti\n\t" \
"movl %esp,%ebx\n\t" \
@@ -360,7 +361,7 @@
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
"incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
"pushl $" #nr "\n\t" \
"call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
@@ -372,7 +373,7 @@
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
RESTORE_MOST);
#define BUILD_TIMER_IRQ(chip,nr,mask) \
@@ -386,7 +387,7 @@
SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
"pushl $-"#nr"-2\n\t" \
SAVE_ALL \
- ACK_##chip(mask) \
+ ACK_##chip(mask,(nr&7)) \
"incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
"movl %esp,%ebx\n\t" \
"pushl %ebx\n\t" \
-----