]>
Commit | Line | Data |
---|---|---|
cc90b958 BS |
1 | From: jbeulich@novell.com |
2 | Subject: fold per-CPU VIRQs onto a single IRQ each | |
3 | Patch-mainline: obsolete | |
4 | ||
00e5a55c BS |
5 | --- sle11-2009-06-04.orig/arch/x86/kernel/time_32-xen.c 2009-06-04 10:47:20.000000000 +0200 |
6 | +++ sle11-2009-06-04/arch/x86/kernel/time_32-xen.c 2009-06-04 10:47:28.000000000 +0200 | |
7 | @@ -725,19 +725,17 @@ int xen_update_persistent_clock(void) | |
cc90b958 BS |
8 | } |
9 | ||
10 | /* Dynamically-mapped IRQ. */ | |
11 | -DEFINE_PER_CPU(int, timer_irq); | |
12 | +static int __read_mostly timer_irq = -1; | |
13 | +static struct irqaction timer_action = { | |
14 | + .handler = timer_interrupt, | |
15 | + .flags = IRQF_DISABLED, | |
16 | + .name = "timer" | |
17 | +}; | |
18 | ||
19 | static void __init setup_cpu0_timer_irq(void) | |
20 | { | |
21 | - per_cpu(timer_irq, 0) = | |
22 | - bind_virq_to_irqhandler( | |
23 | - VIRQ_TIMER, | |
24 | - 0, | |
25 | - timer_interrupt, | |
26 | - IRQF_DISABLED|IRQF_NOBALANCING, | |
27 | - "timer0", | |
28 | - NULL); | |
29 | - BUG_ON(per_cpu(timer_irq, 0) < 0); | |
30 | + timer_irq = bind_virq_to_irqaction(VIRQ_TIMER, 0, &timer_action); | |
31 | + BUG_ON(timer_irq < 0); | |
32 | } | |
33 | ||
34 | void __init time_init(void) | |
00e5a55c | 35 | @@ -864,8 +862,6 @@ void xen_halt(void) |
cc90b958 BS |
36 | EXPORT_SYMBOL(xen_halt); |
37 | ||
38 | #ifdef CONFIG_SMP | |
39 | -static char timer_name[NR_CPUS][15]; | |
40 | - | |
41 | int __cpuinit local_setup_timer(unsigned int cpu) | |
42 | { | |
43 | int seq, irq; | |
00e5a55c | 44 | @@ -891,16 +887,10 @@ int __cpuinit local_setup_timer(unsigned |
cc90b958 BS |
45 | init_missing_ticks_accounting(cpu); |
46 | } while (read_seqretry(&xtime_lock, seq)); | |
47 | ||
48 | - sprintf(timer_name[cpu], "timer%u", cpu); | |
49 | - irq = bind_virq_to_irqhandler(VIRQ_TIMER, | |
50 | - cpu, | |
51 | - timer_interrupt, | |
52 | - IRQF_DISABLED|IRQF_NOBALANCING, | |
53 | - timer_name[cpu], | |
54 | - NULL); | |
55 | + irq = bind_virq_to_irqaction(VIRQ_TIMER, cpu, &timer_action); | |
56 | if (irq < 0) | |
57 | return irq; | |
58 | - per_cpu(timer_irq, cpu) = irq; | |
59 | + BUG_ON(timer_irq != irq); | |
60 | ||
61 | return 0; | |
62 | } | |
00e5a55c | 63 | @@ -908,7 +898,7 @@ int __cpuinit local_setup_timer(unsigned |
cc90b958 BS |
64 | void __cpuinit local_teardown_timer(unsigned int cpu) |
65 | { | |
66 | BUG_ON(cpu == 0); | |
67 | - unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL); | |
68 | + unbind_from_per_cpu_irq(timer_irq, cpu, &timer_action); | |
69 | } | |
70 | #endif | |
71 | ||
00e5a55c BS |
72 | --- sle11-2009-06-04.orig/drivers/xen/core/evtchn.c 2009-06-04 10:47:21.000000000 +0200 |
73 | +++ sle11-2009-06-04/drivers/xen/core/evtchn.c 2009-06-04 10:47:28.000000000 +0200 | |
74 | @@ -58,6 +58,23 @@ static DEFINE_SPINLOCK(irq_mapping_updat | |
cc90b958 BS |
75 | static int evtchn_to_irq[NR_EVENT_CHANNELS] = { |
76 | [0 ... NR_EVENT_CHANNELS-1] = -1 }; | |
77 | ||
78 | +#if defined(CONFIG_SMP) && defined(CONFIG_X86) | |
79 | +static struct per_cpu_irqaction { | |
80 | + struct irqaction action; /* must be first */ | |
81 | + struct per_cpu_irqaction *next; | |
82 | + cpumask_t cpus; | |
83 | +} *virq_actions[NR_VIRQS]; | |
84 | +/* IRQ <-> VIRQ mapping. */ | |
85 | +static DECLARE_BITMAP(virq_per_cpu, NR_VIRQS) __read_mostly; | |
00e5a55c | 86 | +static DEFINE_PER_CPU(int[NR_VIRQS], virq_to_evtchn); |
cc90b958 BS |
87 | +#define BUG_IF_VIRQ_PER_CPU(irq) \ |
88 | + BUG_ON(type_from_irq(irq) == IRQT_VIRQ \ | |
89 | + && test_bit(index_from_irq(irq), virq_per_cpu)) | |
90 | +#else | |
91 | +#define BUG_IF_VIRQ_PER_CPU(irq) ((void)(irq)) | |
92 | +#define PER_CPU_VIRQ_IRQ | |
93 | +#endif | |
94 | + | |
95 | /* IRQ <-> IPI mapping. */ | |
96 | #ifndef NR_IPIS | |
97 | #define NR_IPIS 1 | |
00e5a55c | 98 | @@ -114,13 +131,6 @@ static inline u32 mk_irq_info(u32 type, |
cc90b958 BS |
99 | * Accessors for packed IRQ information. |
100 | */ | |
101 | ||
102 | -#ifdef PER_CPU_IPI_IRQ | |
103 | -static inline unsigned int evtchn_from_irq(int irq) | |
104 | -{ | |
105 | - return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1); | |
106 | -} | |
107 | -#endif | |
108 | - | |
109 | static inline unsigned int index_from_irq(int irq) | |
110 | { | |
111 | return (irq_info[irq] >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1); | |
00e5a55c | 112 | @@ -131,20 +141,35 @@ static inline unsigned int type_from_irq |
cc90b958 BS |
113 | return irq_info[irq] >> (32 - _IRQT_BITS); |
114 | } | |
115 | ||
116 | -#ifndef PER_CPU_IPI_IRQ | |
117 | static inline unsigned int evtchn_from_per_cpu_irq(unsigned int irq, unsigned int cpu) | |
118 | { | |
119 | - BUG_ON(type_from_irq(irq) != IRQT_IPI); | |
120 | - return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)]; | |
121 | + switch (type_from_irq(irq)) { | |
122 | +#ifndef PER_CPU_VIRQ_IRQ | |
123 | + case IRQT_VIRQ: | |
124 | + return per_cpu(virq_to_evtchn, cpu)[index_from_irq(irq)]; | |
125 | +#endif | |
126 | +#ifndef PER_CPU_IPI_IRQ | |
127 | + case IRQT_IPI: | |
128 | + return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)]; | |
129 | +#endif | |
130 | + } | |
131 | + BUG(); | |
00e5a55c | 132 | + return 0; |
cc90b958 BS |
133 | } |
134 | ||
135 | static inline unsigned int evtchn_from_irq(unsigned int irq) | |
136 | { | |
137 | - if (type_from_irq(irq) != IRQT_IPI) | |
138 | - return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1); | |
139 | - return evtchn_from_per_cpu_irq(irq, smp_processor_id()); | |
140 | -} | |
141 | + switch (type_from_irq(irq)) { | |
142 | +#ifndef PER_CPU_VIRQ_IRQ | |
143 | + case IRQT_VIRQ: | |
144 | +#endif | |
145 | +#ifndef PER_CPU_IPI_IRQ | |
146 | + case IRQT_IPI: | |
147 | #endif | |
148 | + return evtchn_from_per_cpu_irq(irq, smp_processor_id()); | |
149 | + } | |
150 | + return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1); | |
151 | +} | |
152 | ||
153 | /* IRQ <-> VIRQ mapping. */ | |
154 | DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1}; | |
00e5a55c | 155 | @@ -479,6 +504,14 @@ static int bind_virq_to_irq(unsigned int |
cc90b958 BS |
156 | evtchn = bind_virq.port; |
157 | ||
158 | evtchn_to_irq[evtchn] = irq; | |
159 | +#ifndef PER_CPU_VIRQ_IRQ | |
160 | + { | |
161 | + unsigned int cpu; | |
162 | + | |
163 | + for_each_possible_cpu(cpu) | |
164 | + per_cpu(virq_to_evtchn, cpu)[virq] = evtchn; | |
165 | + } | |
166 | +#endif | |
167 | irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); | |
168 | ||
169 | per_cpu(virq_to_irq, cpu)[virq] = irq; | |
00e5a55c | 170 | @@ -533,7 +566,9 @@ static void unbind_from_irq(unsigned int |
cc90b958 BS |
171 | unsigned int cpu; |
172 | int evtchn = evtchn_from_irq(irq); | |
173 | ||
174 | + BUG_IF_VIRQ_PER_CPU(irq); | |
175 | BUG_IF_IPI(irq); | |
176 | + | |
177 | spin_lock(&irq_mapping_update_lock); | |
178 | ||
179 | if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) { | |
00e5a55c | 180 | @@ -546,6 +581,11 @@ static void unbind_from_irq(unsigned int |
cc90b958 BS |
181 | case IRQT_VIRQ: |
182 | per_cpu(virq_to_irq, cpu_from_evtchn(evtchn)) | |
183 | [index_from_irq(irq)] = -1; | |
184 | +#ifndef PER_CPU_VIRQ_IRQ | |
185 | + for_each_possible_cpu(cpu) | |
186 | + per_cpu(virq_to_evtchn, cpu) | |
00e5a55c | 187 | + [index_from_irq(irq)] = 0; |
cc90b958 BS |
188 | +#endif |
189 | break; | |
190 | #if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ) | |
191 | case IRQT_IPI: | |
00e5a55c | 192 | @@ -571,11 +611,13 @@ static void unbind_from_irq(unsigned int |
cc90b958 BS |
193 | spin_unlock(&irq_mapping_update_lock); |
194 | } | |
195 | ||
196 | -#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ) | |
197 | -void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu) | |
198 | +#if defined(CONFIG_SMP) && (!defined(PER_CPU_IPI_IRQ) || !defined(PER_CPU_VIRQ_IRQ)) | |
199 | +void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu, | |
200 | + struct irqaction *action) | |
201 | { | |
202 | struct evtchn_close close; | |
203 | int evtchn = evtchn_from_per_cpu_irq(irq, cpu); | |
204 | + struct irqaction *free_action = NULL; | |
205 | ||
206 | spin_lock(&irq_mapping_update_lock); | |
207 | ||
00e5a55c | 208 | @@ -586,6 +628,32 @@ void unbind_from_per_cpu_irq(unsigned in |
cc90b958 BS |
209 | |
210 | BUG_ON(irq_bindcount[irq] <= 1); | |
211 | irq_bindcount[irq]--; | |
212 | + | |
213 | +#ifndef PER_CPU_VIRQ_IRQ | |
214 | + if (type_from_irq(irq) == IRQT_VIRQ) { | |
215 | + unsigned int virq = index_from_irq(irq); | |
216 | + struct per_cpu_irqaction *cur, *prev = NULL; | |
217 | + | |
218 | + cur = virq_actions[virq]; | |
219 | + while (cur) { | |
220 | + if (cur->action.dev_id == action) { | |
221 | + cpu_clear(cpu, cur->cpus); | |
222 | + if (cpus_empty(cur->cpus)) { | |
223 | + if (prev) | |
224 | + prev->next = cur->next; | |
225 | + else | |
226 | + virq_actions[virq] = cur->next; | |
227 | + free_action = action; | |
228 | + } | |
229 | + } else if (cpu_isset(cpu, cur->cpus)) | |
230 | + evtchn = 0; | |
231 | + cur = (prev = cur)->next; | |
232 | + } | |
233 | + if (!VALID_EVTCHN(evtchn)) | |
234 | + goto done; | |
235 | + } | |
236 | +#endif | |
237 | + | |
238 | cpu_clear(cpu, desc->affinity); | |
239 | ||
240 | close.port = evtchn; | |
00e5a55c | 241 | @@ -593,9 +661,16 @@ void unbind_from_per_cpu_irq(unsigned in |
cc90b958 BS |
242 | BUG(); |
243 | ||
244 | switch (type_from_irq(irq)) { | |
245 | +#ifndef PER_CPU_VIRQ_IRQ | |
246 | + case IRQT_VIRQ: | |
00e5a55c | 247 | + per_cpu(virq_to_evtchn, cpu)[index_from_irq(irq)] = 0; |
cc90b958 BS |
248 | + break; |
249 | +#endif | |
250 | +#ifndef PER_CPU_IPI_IRQ | |
251 | case IRQT_IPI: | |
00e5a55c | 252 | per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)] = 0; |
cc90b958 BS |
253 | break; |
254 | +#endif | |
255 | default: | |
256 | BUG(); | |
257 | break; | |
00e5a55c | 258 | @@ -607,9 +682,16 @@ void unbind_from_per_cpu_irq(unsigned in |
cc90b958 BS |
259 | evtchn_to_irq[evtchn] = -1; |
260 | } | |
261 | ||
262 | +#ifndef PER_CPU_VIRQ_IRQ | |
263 | +done: | |
264 | +#endif | |
265 | spin_unlock(&irq_mapping_update_lock); | |
266 | + | |
267 | + if (free_action) | |
268 | + free_irq(irq, free_action); | |
269 | } | |
270 | -#endif /* CONFIG_SMP && !PER_CPU_IPI_IRQ */ | |
271 | +EXPORT_SYMBOL_GPL(unbind_from_per_cpu_irq); | |
272 | +#endif /* CONFIG_SMP && (!PER_CPU_IPI_IRQ || !PER_CPU_VIRQ_IRQ) */ | |
273 | ||
274 | int bind_caller_port_to_irqhandler( | |
275 | unsigned int caller_port, | |
00e5a55c | 276 | @@ -691,6 +773,8 @@ int bind_virq_to_irqhandler( |
cc90b958 BS |
277 | { |
278 | int irq, retval; | |
279 | ||
280 | + BUG_IF_VIRQ_PER_CPU(virq); | |
281 | + | |
282 | irq = bind_virq_to_irq(virq, cpu); | |
283 | if (irq < 0) | |
284 | return irq; | |
00e5a55c | 285 | @@ -706,6 +790,108 @@ int bind_virq_to_irqhandler( |
cc90b958 BS |
286 | EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler); |
287 | ||
288 | #ifdef CONFIG_SMP | |
289 | +#ifndef PER_CPU_VIRQ_IRQ | |
290 | +int bind_virq_to_irqaction( | |
291 | + unsigned int virq, | |
292 | + unsigned int cpu, | |
293 | + struct irqaction *action) | |
294 | +{ | |
295 | + struct evtchn_bind_virq bind_virq; | |
296 | + int evtchn, irq, retval = 0; | |
297 | + struct per_cpu_irqaction *cur = NULL, *new; | |
298 | + | |
299 | + BUG_ON(!test_bit(virq, virq_per_cpu)); | |
300 | + | |
301 | + if (action->dev_id) | |
302 | + return -EINVAL; | |
303 | + | |
304 | + new = kzalloc(sizeof(*new), GFP_ATOMIC); | |
305 | + if (new) { | |
306 | + new->action = *action; | |
307 | + new->action.dev_id = action; | |
308 | + } | |
309 | + | |
310 | + spin_lock(&irq_mapping_update_lock); | |
311 | + | |
312 | + for (cur = virq_actions[virq]; cur; cur = cur->next) | |
313 | + if (cur->action.dev_id == action) | |
314 | + break; | |
315 | + if (!cur) { | |
316 | + if (!new) { | |
317 | + spin_unlock(&irq_mapping_update_lock); | |
318 | + return -ENOMEM; | |
319 | + } | |
320 | + new->next = virq_actions[virq]; | |
321 | + virq_actions[virq] = cur = new; | |
322 | + retval = 1; | |
323 | + } | |
324 | + cpu_set(cpu, cur->cpus); | |
325 | + action = &cur->action; | |
326 | + | |
327 | + if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) { | |
328 | + unsigned int cpu; | |
329 | + | |
330 | + BUG_ON(!retval); | |
331 | + | |
00e5a55c | 332 | + if ((irq = find_unbound_irq(true)) < 0) { |
cc90b958 BS |
333 | + if (cur) |
334 | + virq_actions[virq] = cur->next; | |
335 | + spin_unlock(&irq_mapping_update_lock); | |
336 | + if (cur != new) | |
337 | + kfree(new); | |
338 | + return irq; | |
339 | + } | |
340 | + | |
341 | + /* Extra reference so count will never drop to zero. */ | |
342 | + irq_bindcount[irq]++; | |
343 | + | |
344 | + for_each_possible_cpu(cpu) | |
345 | + per_cpu(virq_to_irq, cpu)[virq] = irq; | |
346 | + irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, 0); | |
cc90b958 BS |
347 | + } |
348 | + | |
00e5a55c BS |
349 | + evtchn = per_cpu(virq_to_evtchn, cpu)[virq]; |
350 | + if (!VALID_EVTCHN(evtchn)) { | |
cc90b958 BS |
351 | + bind_virq.virq = virq; |
352 | + bind_virq.vcpu = cpu; | |
353 | + if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, | |
354 | + &bind_virq) != 0) | |
355 | + BUG(); | |
356 | + evtchn = bind_virq.port; | |
357 | + evtchn_to_irq[evtchn] = irq; | |
358 | + per_cpu(virq_to_evtchn, cpu)[virq] = evtchn; | |
359 | + | |
360 | + bind_evtchn_to_cpu(evtchn, cpu); | |
361 | + } | |
362 | + | |
363 | + irq_bindcount[irq]++; | |
364 | + | |
365 | + spin_unlock(&irq_mapping_update_lock); | |
366 | + | |
367 | + if (cur != new) | |
368 | + kfree(new); | |
369 | + | |
370 | + if (retval == 0) { | |
371 | + unsigned long flags; | |
372 | + | |
373 | + local_irq_save(flags); | |
374 | + unmask_evtchn(evtchn); | |
375 | + local_irq_restore(flags); | |
376 | + } else { | |
377 | + action->flags |= IRQF_PERCPU; | |
378 | + retval = setup_irq(irq, action); | |
379 | + if (retval) { | |
380 | + unbind_from_per_cpu_irq(irq, cpu, cur->action.dev_id); | |
381 | + BUG_ON(retval > 0); | |
382 | + irq = retval; | |
383 | + } | |
384 | + } | |
385 | + | |
386 | + return irq; | |
387 | +} | |
388 | +EXPORT_SYMBOL_GPL(bind_virq_to_irqaction); | |
389 | +#endif | |
390 | + | |
391 | #ifdef PER_CPU_IPI_IRQ | |
392 | int bind_ipi_to_irqhandler( | |
393 | unsigned int ipi, | |
00e5a55c | 394 | @@ -784,7 +970,7 @@ int __cpuinit bind_ipi_to_irqaction( |
cc90b958 BS |
395 | action->flags |= IRQF_PERCPU; |
396 | retval = setup_irq(irq, action); | |
397 | if (retval) { | |
398 | - unbind_from_per_cpu_irq(irq, cpu); | |
399 | + unbind_from_per_cpu_irq(irq, cpu, NULL); | |
400 | BUG_ON(retval > 0); | |
401 | irq = retval; | |
402 | } | |
00e5a55c | 403 | @@ -819,7 +1005,9 @@ static void rebind_irq_to_cpu(unsigned i |
cc90b958 BS |
404 | { |
405 | int evtchn = evtchn_from_irq(irq); | |
406 | ||
407 | + BUG_IF_VIRQ_PER_CPU(irq); | |
408 | BUG_IF_IPI(irq); | |
409 | + | |
410 | if (VALID_EVTCHN(evtchn)) | |
411 | rebind_evtchn_to_cpu(evtchn, tcpu); | |
412 | } | |
00e5a55c | 413 | @@ -1098,7 +1286,9 @@ void notify_remote_via_irq(int irq) |
cc90b958 BS |
414 | { |
415 | int evtchn = evtchn_from_irq(irq); | |
416 | ||
417 | + BUG_ON(type_from_irq(irq) == IRQT_VIRQ); | |
418 | BUG_IF_IPI(irq); | |
419 | + | |
420 | if (VALID_EVTCHN(evtchn)) | |
421 | notify_remote_via_evtchn(evtchn); | |
422 | } | |
00e5a55c | 423 | @@ -1106,6 +1296,7 @@ EXPORT_SYMBOL_GPL(notify_remote_via_irq) |
cc90b958 BS |
424 | |
425 | int irq_to_evtchn_port(int irq) | |
426 | { | |
427 | + BUG_IF_VIRQ_PER_CPU(irq); | |
428 | BUG_IF_IPI(irq); | |
429 | return evtchn_from_irq(irq); | |
430 | } | |
00e5a55c | 431 | @@ -1200,6 +1391,12 @@ static void restore_cpu_virqs(unsigned i |
cc90b958 BS |
432 | if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) |
433 | continue; | |
434 | ||
435 | +#ifndef PER_CPU_VIRQ_IRQ | |
00e5a55c BS |
436 | + if (test_bit(virq, virq_per_cpu) |
437 | + && !VALID_EVTCHN(per_cpu(virq_to_evtchn, cpu)[virq])) | |
438 | + continue; | |
cc90b958 BS |
439 | +#endif |
440 | + | |
441 | BUG_ON(irq_info[irq] != mk_irq_info(IRQT_VIRQ, virq, 0)); | |
442 | ||
443 | /* Get a new binding from Xen. */ | |
00e5a55c | 444 | @@ -1212,7 +1409,19 @@ static void restore_cpu_virqs(unsigned i |
cc90b958 BS |
445 | |
446 | /* Record the new mapping. */ | |
447 | evtchn_to_irq[evtchn] = irq; | |
00e5a55c BS |
448 | +#ifdef PER_CPU_VIRQ_IRQ |
449 | irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); | |
450 | +#else | |
cc90b958 BS |
451 | + if (test_bit(virq, virq_per_cpu)) |
452 | + per_cpu(virq_to_evtchn, cpu)[virq] = evtchn; | |
453 | + else { | |
454 | + unsigned int cpu; | |
455 | + | |
456 | + irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); | |
457 | + for_each_possible_cpu(cpu) | |
458 | + per_cpu(virq_to_evtchn, cpu)[virq] = evtchn; | |
459 | + } | |
cc90b958 BS |
460 | +#endif |
461 | bind_evtchn_to_cpu(evtchn, cpu); | |
462 | ||
463 | /* Ready for use. */ | |
00e5a55c | 464 | @@ -1267,7 +1476,11 @@ static int evtchn_resume(struct sys_devi |
cc90b958 BS |
465 | |
466 | /* Avoid doing anything in the 'suspend cancelled' case. */ | |
467 | status.dom = DOMID_SELF; | |
468 | +#ifdef PER_CPU_VIRQ_IRQ | |
469 | status.port = evtchn_from_irq(__get_cpu_var(virq_to_irq)[VIRQ_TIMER]); | |
470 | +#else | |
471 | + status.port = __get_cpu_var(virq_to_evtchn)[VIRQ_TIMER]; | |
472 | +#endif | |
473 | if (HYPERVISOR_event_channel_op(EVTCHNOP_status, &status)) | |
474 | BUG(); | |
475 | if (status.status == EVTCHNSTAT_virq | |
00e5a55c | 476 | @@ -1407,6 +1620,15 @@ void __init xen_init_IRQ(void) |
cc90b958 | 477 | unsigned int i; |
00e5a55c | 478 | struct physdev_pirq_eoi_gmfn eoi_gmfn; |
cc90b958 BS |
479 | |
480 | +#ifndef PER_CPU_VIRQ_IRQ | |
481 | + __set_bit(VIRQ_TIMER, virq_per_cpu); | |
482 | + __set_bit(VIRQ_DEBUG, virq_per_cpu); | |
483 | + __set_bit(VIRQ_XENOPROF, virq_per_cpu); | |
484 | +#ifdef CONFIG_IA64 | |
485 | + __set_bit(VIRQ_ITC, virq_per_cpu); | |
486 | +#endif | |
487 | +#endif | |
488 | + | |
489 | init_evtchn_cpu_bindings(); | |
490 | ||
00e5a55c BS |
491 | pirq_needs_eoi = alloc_bootmem_pages(sizeof(unsigned long) |
492 | --- sle11-2009-06-04.orig/drivers/xen/core/smpboot.c 2009-06-04 10:47:21.000000000 +0200 | |
493 | +++ sle11-2009-06-04/drivers/xen/core/smpboot.c 2009-06-04 10:47:28.000000000 +0200 | |
494 | @@ -163,11 +163,11 @@ static int __cpuinit xen_smp_intr_init(u | |
cc90b958 | 495 | fail: |
cc90b958 | 496 | xen_spinlock_cleanup(cpu); |
00e5a55c BS |
497 | unbind_call1: |
498 | - unbind_from_per_cpu_irq(call1func_irq, cpu); | |
499 | + unbind_from_per_cpu_irq(call1func_irq, cpu, NULL); | |
500 | unbind_call: | |
501 | - unbind_from_per_cpu_irq(callfunc_irq, cpu); | |
502 | + unbind_from_per_cpu_irq(callfunc_irq, cpu, NULL); | |
503 | unbind_resched: | |
504 | - unbind_from_per_cpu_irq(resched_irq, cpu); | |
505 | + unbind_from_per_cpu_irq(resched_irq, cpu, NULL); | |
cc90b958 BS |
506 | return rc; |
507 | } | |
00e5a55c BS |
508 | |
509 | @@ -177,9 +177,9 @@ static void __cpuinit xen_smp_intr_exit( | |
cc90b958 BS |
510 | if (cpu != 0) |
511 | local_teardown_timer(cpu); | |
512 | ||
513 | - unbind_from_per_cpu_irq(resched_irq, cpu); | |
514 | - unbind_from_per_cpu_irq(callfunc_irq, cpu); | |
515 | - unbind_from_per_cpu_irq(call1func_irq, cpu); | |
516 | + unbind_from_per_cpu_irq(resched_irq, cpu, NULL); | |
517 | + unbind_from_per_cpu_irq(callfunc_irq, cpu, NULL); | |
518 | + unbind_from_per_cpu_irq(call1func_irq, cpu, NULL); | |
519 | xen_spinlock_cleanup(cpu); | |
520 | } | |
521 | #endif | |
00e5a55c BS |
522 | --- sle11-2009-06-04.orig/drivers/xen/core/spinlock.c 2009-06-04 10:47:21.000000000 +0200 |
523 | +++ sle11-2009-06-04/drivers/xen/core/spinlock.c 2009-06-04 10:47:28.000000000 +0200 | |
524 | @@ -57,7 +57,7 @@ int __cpuinit xen_spinlock_init(unsigned | |
525 | ||
cc90b958 BS |
526 | void __cpuinit xen_spinlock_cleanup(unsigned int cpu) |
527 | { | |
00e5a55c BS |
528 | - unbind_from_per_cpu_irq(spinlock_irq, cpu); |
529 | + unbind_from_per_cpu_irq(spinlock_irq, cpu, NULL); | |
cc90b958 BS |
530 | } |
531 | ||
532 | int xen_spin_wait(raw_spinlock_t *lock, unsigned int token) | |
00e5a55c BS |
533 | --- sle11-2009-06-04.orig/drivers/xen/netback/netback.c 2009-06-04 10:20:21.000000000 +0200 |
534 | +++ sle11-2009-06-04/drivers/xen/netback/netback.c 2009-06-04 10:47:28.000000000 +0200 | |
535 | @@ -1561,6 +1561,12 @@ static irqreturn_t netif_be_dbg(int irq, | |
cc90b958 BS |
536 | |
537 | return IRQ_HANDLED; | |
538 | } | |
539 | + | |
540 | +static struct irqaction netif_be_dbg_action = { | |
541 | + .handler = netif_be_dbg, | |
542 | + .flags = IRQF_SHARED, | |
543 | + .name = "net-be-dbg" | |
544 | +}; | |
545 | #endif | |
546 | ||
547 | static int __init netback_init(void) | |
00e5a55c | 548 | @@ -1620,12 +1626,9 @@ static int __init netback_init(void) |
cc90b958 BS |
549 | netif_xenbus_init(); |
550 | ||
551 | #ifdef NETBE_DEBUG_INTERRUPT | |
552 | - (void)bind_virq_to_irqhandler(VIRQ_DEBUG, | |
553 | - 0, | |
554 | - netif_be_dbg, | |
555 | - IRQF_SHARED, | |
556 | - "net-be-dbg", | |
557 | - &netif_be_dbg); | |
558 | + (void)bind_virq_to_irqaction(VIRQ_DEBUG, | |
559 | + 0, | |
560 | + &netif_be_dbg_action); | |
561 | #endif | |
562 | ||
563 | return 0; | |
00e5a55c BS |
564 | --- sle11-2009-06-04.orig/drivers/xen/xenoprof/xenoprofile.c 2009-06-04 10:20:39.000000000 +0200 |
565 | +++ sle11-2009-06-04/drivers/xen/xenoprof/xenoprofile.c 2009-06-04 10:47:28.000000000 +0200 | |
566 | @@ -210,6 +210,11 @@ static irqreturn_t xenoprof_ovf_interrup | |
cc90b958 BS |
567 | return IRQ_HANDLED; |
568 | } | |
569 | ||
570 | +static struct irqaction ovf_action = { | |
571 | + .handler = xenoprof_ovf_interrupt, | |
572 | + .flags = IRQF_DISABLED, | |
573 | + .name = "xenoprof" | |
574 | +}; | |
575 | ||
576 | static void unbind_virq(void) | |
577 | { | |
00e5a55c | 578 | @@ -217,7 +222,7 @@ static void unbind_virq(void) |
cc90b958 BS |
579 | |
580 | for_each_online_cpu(i) { | |
581 | if (ovf_irq[i] >= 0) { | |
582 | - unbind_from_irqhandler(ovf_irq[i], NULL); | |
583 | + unbind_from_per_cpu_irq(ovf_irq[i], i, &ovf_action); | |
584 | ovf_irq[i] = -1; | |
585 | } | |
586 | } | |
00e5a55c | 587 | @@ -230,12 +235,7 @@ static int bind_virq(void) |
cc90b958 BS |
588 | int result; |
589 | ||
590 | for_each_online_cpu(i) { | |
591 | - result = bind_virq_to_irqhandler(VIRQ_XENOPROF, | |
592 | - i, | |
593 | - xenoprof_ovf_interrupt, | |
594 | - IRQF_DISABLED|IRQF_NOBALANCING, | |
595 | - "xenoprof", | |
596 | - NULL); | |
597 | + result = bind_virq_to_irqaction(VIRQ_XENOPROF, i, &ovf_action); | |
598 | ||
599 | if (result < 0) { | |
600 | unbind_virq(); | |
00e5a55c BS |
601 | --- sle11-2009-06-04.orig/include/xen/evtchn.h 2009-06-04 10:47:21.000000000 +0200 |
602 | +++ sle11-2009-06-04/include/xen/evtchn.h 2009-06-04 10:47:28.000000000 +0200 | |
cc90b958 BS |
603 | @@ -78,6 +78,17 @@ int bind_virq_to_irqhandler( |
604 | unsigned long irqflags, | |
605 | const char *devname, | |
606 | void *dev_id); | |
607 | +#if defined(CONFIG_SMP) && defined(CONFIG_XEN) && defined(CONFIG_X86) | |
608 | +int bind_virq_to_irqaction( | |
609 | + unsigned int virq, | |
610 | + unsigned int cpu, | |
611 | + struct irqaction *action); | |
612 | +#else | |
613 | +#define bind_virq_to_irqaction(virq, cpu, action) \ | |
614 | + bind_virq_to_irqhandler(virq, cpu, (action)->handler, \ | |
615 | + (action)->flags | IRQF_NOBALANCING, \ | |
616 | + (action)->name, action) | |
617 | +#endif | |
618 | #if defined(CONFIG_SMP) && !defined(MODULE) | |
619 | #ifndef CONFIG_X86 | |
620 | int bind_ipi_to_irqhandler( | |
621 | @@ -102,9 +113,13 @@ int bind_ipi_to_irqaction( | |
622 | */ | |
623 | void unbind_from_irqhandler(unsigned int irq, void *dev_id); | |
624 | ||
625 | -#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86) | |
626 | +#if defined(CONFIG_SMP) && defined(CONFIG_XEN) && defined(CONFIG_X86) | |
627 | /* Specialized unbind function for per-CPU IRQs. */ | |
628 | -void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu); | |
629 | +void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu, | |
630 | + struct irqaction *); | |
631 | +#else | |
632 | +#define unbind_from_per_cpu_irq(irq, cpu, action) \ | |
633 | + unbind_from_irqhandler(irq, action) | |
634 | #endif | |
635 | ||
636 | #ifndef CONFIG_XEN |