]> git.pld-linux.org Git - packages/kernel.git/blame - irqbalance-2.4.20-MRC.patch
- replaced by linux-2.4-sfq.patch
[packages/kernel.git] / irqbalance-2.4.20-MRC.patch
CommitLineData
445bafdd 1diff -ruN linux-2.4.20.orig/arch/i386/kernel/io_apic.c linux-2.4.20/arch/i386/kernel/io_apic.c
2--- linux-2.4.20.orig/arch/i386/kernel/io_apic.c Thu Nov 28 16:53:09 2002
3+++ linux-2.4.20/arch/i386/kernel/io_apic.c Tue Dec 17 10:37:58 2002
4@@ -28,6 +28,7 @@
5 #include <linux/config.h>
6 #include <linux/smp_lock.h>
7 #include <linux/mc146818rtc.h>
8+#include <linux/compiler.h>
9
10 #include <asm/io.h>
11 #include <asm/smp.h>
12@@ -188,6 +189,86 @@
13 clear_IO_APIC_pin(apic, pin);
14 }
15
16+static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
17+{
18+ unsigned long flags;
19+
20+ /*
21+ * Only the first 8 bits are valid.
22+ */
23+ mask = mask << 24;
24+ spin_lock_irqsave(&ioapic_lock, flags);
25+ __DO_ACTION(1, = mask, )
26+ spin_unlock_irqrestore(&ioapic_lock, flags);
27+}
28+
29+#if CONFIG_SMP
30+
31+typedef struct {
32+ unsigned int cpu;
33+ unsigned long timestamp;
34+} ____cacheline_aligned irq_balance_t;
35+
36+static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned
37+ = { [ 0 ... NR_IRQS-1 ] = { 1, 0 } };
38+
39+extern unsigned long irq_affinity [NR_IRQS];
40+
41+#endif
42+
43+#define IDLE_ENOUGH(cpu,now) \
44+ (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1))
45+
46+#define IRQ_ALLOWED(cpu,allowed_mask) \
47+ ((1 << cpu) & (allowed_mask))
48+
49+static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction)
50+{
51+ int search_idle = 1;
52+ int cpu = curr_cpu;
53+
54+ goto inside;
55+
56+ do {
57+ if (unlikely(cpu == curr_cpu))
58+ search_idle = 0;
59+inside:
60+ if (direction == 1) {
61+ cpu++;
62+ if (cpu >= smp_num_cpus)
63+ cpu = 0;
64+ } else {
65+ cpu--;
66+ if (cpu == -1)
67+ cpu = smp_num_cpus-1;
68+ }
69+ } while (!IRQ_ALLOWED(cpu,allowed_mask) ||
70+ (search_idle && !IDLE_ENOUGH(cpu,now)));
71+
72+ return cpu;
73+}
74+
75+static inline void balance_irq(int irq)
76+{
77+#if CONFIG_SMP
78+ irq_balance_t *entry = irq_balance + irq;
79+ unsigned long now = jiffies;
80+
81+ if (unlikely(entry->timestamp != now)) {
82+ unsigned long allowed_mask;
83+ int random_number;
84+
85+ rdtscl(random_number);
86+ random_number &= 1;
87+
88+ allowed_mask = cpu_online_map & irq_affinity[irq];
89+ entry->timestamp = now;
90+ entry->cpu = move(entry->cpu, allowed_mask, now, random_number);
91+ set_ioapic_affinity(irq, 1 << entry->cpu);
92+ }
93+#endif
94+}
95+
96 /*
97 * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
98 * specific CPU-side IRQs.
99@@ -693,8 +774,7 @@
100 }
101
102 /*
103- * Set up the 8259A-master output pin as broadcast to all
104- * CPUs.
105+ * Set up the 8259A-master output pin:
106 */
107 void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
108 {
109@@ -1214,6 +1294,7 @@
110 */
111 static void ack_edge_ioapic_irq(unsigned int irq)
112 {
113+ balance_irq(irq);
114 if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
115 == (IRQ_PENDING | IRQ_DISABLED))
116 mask_IO_APIC_irq(irq);
117@@ -1253,6 +1334,7 @@
118 unsigned long v;
119 int i;
120
121+ balance_irq(irq);
122 /*
123 * It appears there is an erratum which affects at least version 0x11
124 * of I/O APIC (that's the 82093AA and cores integrated into various
125@@ -1309,19 +1391,6 @@
126
127 static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ }
128
129-static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
130-{
131- unsigned long flags;
132- /*
133- * Only the first 8 bits are valid.
134- */
135- mask = mask << 24;
136-
137- spin_lock_irqsave(&ioapic_lock, flags);
138- __DO_ACTION(1, = mask, )
139- spin_unlock_irqrestore(&ioapic_lock, flags);
140-}
141-
142 /*
143 * Level and edge triggered IO-APIC interrupts need different handling,
144 * so we use two separate IRQ descriptors. Edge triggered IRQs can be
145diff -ruN linux-2.4.20.orig/arch/i386/kernel/irq.c linux-2.4.20/arch/i386/kernel/irq.c
146--- linux-2.4.20.orig/arch/i386/kernel/irq.c Thu Nov 28 16:53:09 2002
147+++ linux-2.4.20/arch/i386/kernel/irq.c Tue Dec 17 10:37:58 2002
148@@ -1090,7 +1090,7 @@
149
150 static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
151
152-static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
153+unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
154 static int irq_affinity_read_proc (char *page, char **start, off_t off,
155 int count, int *eof, void *data)
156 {
157diff -ruN linux-2.4.20.orig/include/asm-i386/hardirq.h linux-2.4.20/include/asm-i386/hardirq.h
158--- linux-2.4.20.orig/include/asm-i386/hardirq.h Thu Nov 22 12:46:19 2001
159+++ linux-2.4.20/include/asm-i386/hardirq.h Tue Dec 17 10:37:58 2002
160@@ -12,6 +12,7 @@
161 unsigned int __local_bh_count;
162 unsigned int __syscall_count;
163 struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
164+ unsigned long idle_timestamp;
165 unsigned int __nmi_count; /* arch dependent */
166 } ____cacheline_aligned irq_cpustat_t;
167
168diff -ruN linux-2.4.20.orig/include/linux/sched.h linux-2.4.20/include/linux/sched.h
169--- linux-2.4.20.orig/include/linux/sched.h Thu Nov 28 16:53:15 2002
170+++ linux-2.4.20/include/linux/sched.h Tue Dec 17 10:37:58 2002
171@@ -147,6 +147,7 @@
172
173 extern void sched_init(void);
174 extern void init_idle(void);
175+extern int idle_cpu(int cpu);
176 extern void show_state(void);
177 extern void cpu_init (void);
178 extern void trap_init(void);
179diff -ruN linux-2.4.20.orig/kernel/sched.c linux-2.4.20/kernel/sched.c
180--- linux-2.4.20.orig/kernel/sched.c Thu Nov 28 16:53:15 2002
181+++ linux-2.4.20/kernel/sched.c Tue Dec 17 10:37:58 2002
182@@ -118,6 +118,11 @@
183 #define can_schedule(p,cpu) \
184 ((p)->cpus_runnable & (p)->cpus_allowed & (1 << cpu))
185
186+int idle_cpu(int cpu)
187+{
188+ return cpu_curr(cpu) == idle_task(cpu);
189+}
190+
191 #else
192
193 #define idle_task(cpu) (&init_task)
This page took 0.146648 seconds and 4 git commands to generate.