1 diff -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
5 #include <linux/config.h>
6 #include <linux/smp_lock.h>
7 #include <linux/mc146818rtc.h>
8 +#include <linux/compiler.h>
13 clear_IO_APIC_pin(apic, pin);
16 +static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
18 + unsigned long flags;
21 + * Only the first 8 bits are valid.
24 + spin_lock_irqsave(&ioapic_lock, flags);
25 + __DO_ACTION(1, = mask, )
26 + spin_unlock_irqrestore(&ioapic_lock, flags);
33 + unsigned long timestamp;
34 +} ____cacheline_aligned irq_balance_t;
36 +static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned
37 + = { [ 0 ... NR_IRQS-1 ] = { 1, 0 } };
39 +extern unsigned long irq_affinity [NR_IRQS];
43 +#define IDLE_ENOUGH(cpu,now) \
44 + (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1))
46 +#define IRQ_ALLOWED(cpu,allowed_mask) \
47 + ((1 << cpu) & (allowed_mask))
49 +static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction)
51 + int search_idle = 1;
57 + if (unlikely(cpu == curr_cpu))
60 + if (direction == 1) {
62 + if (cpu >= smp_num_cpus)
67 + cpu = smp_num_cpus-1;
69 + } while (!IRQ_ALLOWED(cpu,allowed_mask) ||
70 + (search_idle && !IDLE_ENOUGH(cpu,now)));
75 +static inline void balance_irq(int irq)
78 + irq_balance_t *entry = irq_balance + irq;
79 + unsigned long now = jiffies;
81 + if (unlikely(entry->timestamp != now)) {
82 + unsigned long allowed_mask;
85 + rdtscl(random_number);
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);
97 * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
98 * specific CPU-side IRQs.
103 - * Set up the 8259A-master output pin as broadcast to all
105 + * Set up the 8259A-master output pin:
107 void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
109 @@ -1214,6 +1294,7 @@
111 static void ack_edge_ioapic_irq(unsigned int 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 @@
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 @@
127 static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ }
129 -static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
131 - unsigned long flags;
133 - * Only the first 8 bits are valid.
137 - spin_lock_irqsave(&ioapic_lock, flags);
138 - __DO_ACTION(1, = mask, )
139 - spin_unlock_irqrestore(&ioapic_lock, flags);
143 * Level and edge triggered IO-APIC interrupts need different handling,
144 * so we use two separate IRQ descriptors. Edge triggered IRQs can be
145 diff -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 @@
150 static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
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)
157 diff -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
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;
168 diff -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
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);
179 diff -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
183 #define can_schedule(p,cpu) \
184 ((p)->cpus_runnable & (p)->cpus_allowed & (1 << cpu))
186 +int idle_cpu(int cpu)
188 + return cpu_curr(cpu) == idle_task(cpu);
193 #define idle_task(cpu) (&init_task)