]> git.pld-linux.org Git - packages/kernel.git/blob - irqbalance-2.4.20-MRC.patch
#
[packages/kernel.git] / irqbalance-2.4.20-MRC.patch
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
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
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 @@
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  {
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
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  
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
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);
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
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.055831 seconds and 3 git commands to generate.