]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/powerpc/platforms/pseries/xics.c
powerpc/xics: Consolidate ipi message encode and decode
[linux-2.6-omap-h63xx.git] / arch / powerpc / platforms / pseries / xics.c
1 /*
2  * arch/powerpc/platforms/pseries/xics.c
3  *
4  * Copyright 2000 IBM Corporation.
5  *
6  *  This program is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  as published by the Free Software Foundation; either version
9  *  2 of the License, or (at your option) any later version.
10  */
11
12
13 #include <linux/types.h>
14 #include <linux/threads.h>
15 #include <linux/kernel.h>
16 #include <linux/irq.h>
17 #include <linux/smp.h>
18 #include <linux/interrupt.h>
19 #include <linux/signal.h>
20 #include <linux/init.h>
21 #include <linux/gfp.h>
22 #include <linux/radix-tree.h>
23 #include <linux/cpu.h>
24
25 #include <asm/firmware.h>
26 #include <asm/prom.h>
27 #include <asm/io.h>
28 #include <asm/pgtable.h>
29 #include <asm/smp.h>
30 #include <asm/rtas.h>
31 #include <asm/hvcall.h>
32 #include <asm/machdep.h>
33 #include <asm/i8259.h>
34
35 #include "xics.h"
36 #include "plpar_wrappers.h"
37
38 #define XICS_IPI                2
39 #define XICS_IRQ_SPURIOUS       0
40
41 /* Want a priority other than 0.  Various HW issues require this. */
42 #define DEFAULT_PRIORITY        5
43
44 /*
45  * Mark IPIs as higher priority so we can take them inside interrupts that
46  * arent marked IRQF_DISABLED
47  */
48 #define IPI_PRIORITY            4
49
50 struct xics_ipl {
51         union {
52                 u32 word;
53                 u8 bytes[4];
54         } xirr_poll;
55         union {
56                 u32 word;
57                 u8 bytes[4];
58         } xirr;
59         u32 dummy;
60         union {
61                 u32 word;
62                 u8 bytes[4];
63         } qirr;
64 };
65
66 static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
67
68 static unsigned int default_server = 0xFF;
69 static unsigned int default_distrib_server = 0;
70 static unsigned int interrupt_server_size = 8;
71
72 static struct irq_host *xics_host;
73
74 /* RTAS service tokens */
75 static int ibm_get_xive;
76 static int ibm_set_xive;
77 static int ibm_int_on;
78 static int ibm_int_off;
79
80
81 /* Direct HW low level accessors */
82
83
84 static inline unsigned int direct_xirr_info_get(void)
85 {
86         int cpu = smp_processor_id();
87
88         return in_be32(&xics_per_cpu[cpu]->xirr.word);
89 }
90
91 static inline void direct_xirr_info_set(int value)
92 {
93         int cpu = smp_processor_id();
94
95         out_be32(&xics_per_cpu[cpu]->xirr.word, value);
96 }
97
98 static inline void direct_cppr_info(u8 value)
99 {
100         int cpu = smp_processor_id();
101
102         out_8(&xics_per_cpu[cpu]->xirr.bytes[0], value);
103 }
104
105 static inline void direct_qirr_info(int n_cpu, u8 value)
106 {
107         out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value);
108 }
109
110
111 /* LPAR low level accessors */
112
113
114 static inline unsigned int lpar_xirr_info_get(void)
115 {
116         unsigned long lpar_rc;
117         unsigned long return_value;
118
119         lpar_rc = plpar_xirr(&return_value);
120         if (lpar_rc != H_SUCCESS)
121                 panic(" bad return code xirr - rc = %lx \n", lpar_rc);
122         return (unsigned int)return_value;
123 }
124
125 static inline void lpar_xirr_info_set(int value)
126 {
127         unsigned long lpar_rc;
128         unsigned long val64 = value & 0xffffffff;
129
130         lpar_rc = plpar_eoi(val64);
131         if (lpar_rc != H_SUCCESS)
132                 panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
133                       val64);
134 }
135
136 static inline void lpar_cppr_info(u8 value)
137 {
138         unsigned long lpar_rc;
139
140         lpar_rc = plpar_cppr(value);
141         if (lpar_rc != H_SUCCESS)
142                 panic("bad return code cppr - rc = %lx\n", lpar_rc);
143 }
144
145 static inline void lpar_qirr_info(int n_cpu , u8 value)
146 {
147         unsigned long lpar_rc;
148
149         lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value);
150         if (lpar_rc != H_SUCCESS)
151                 panic("bad return code qirr - rc = %lx\n", lpar_rc);
152 }
153
154
155 /* High level handlers and init code */
156
157 static void xics_update_irq_servers(void)
158 {
159         int i, j;
160         struct device_node *np;
161         u32 ilen;
162         const u32 *ireg, *isize;
163         u32 hcpuid;
164
165         /* Find the server numbers for the boot cpu. */
166         np = of_get_cpu_node(boot_cpuid, NULL);
167         BUG_ON(!np);
168
169         ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
170         if (!ireg) {
171                 of_node_put(np);
172                 return;
173         }
174
175         i = ilen / sizeof(int);
176         hcpuid = get_hard_smp_processor_id(boot_cpuid);
177
178         /* Global interrupt distribution server is specified in the last
179          * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
180          * entry fom this property for current boot cpu id and use it as
181          * default distribution server
182          */
183         for (j = 0; j < i; j += 2) {
184                 if (ireg[j] == hcpuid) {
185                         default_server = hcpuid;
186                         default_distrib_server = ireg[j+1];
187
188                         isize = of_get_property(np,
189                                         "ibm,interrupt-server#-size", NULL);
190                         if (isize)
191                                 interrupt_server_size = *isize;
192                 }
193         }
194
195         of_node_put(np);
196 }
197
198 #ifdef CONFIG_SMP
199 /*
200  * XICS only has a single IPI, so encode the messages per CPU
201  */
202 struct xics_ipi_struct {
203         unsigned long value;
204         } ____cacheline_aligned;
205
206 static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
207
208 static int get_irq_server(unsigned int virq, unsigned int strict_check)
209 {
210         int server;
211         /* For the moment only implement delivery to all cpus or one cpu */
212         cpumask_t cpumask = irq_desc[virq].affinity;
213         cpumask_t tmp = CPU_MASK_NONE;
214
215         if (!distribute_irqs)
216                 return default_server;
217
218         if (!cpus_equal(cpumask, CPU_MASK_ALL)) {
219                 cpus_and(tmp, cpu_online_map, cpumask);
220
221                 server = first_cpu(tmp);
222
223                 if (server < NR_CPUS)
224                         return get_hard_smp_processor_id(server);
225
226                 if (strict_check)
227                         return -1;
228         }
229
230         if (cpus_equal(cpu_online_map, cpu_present_map))
231                 return default_distrib_server;
232
233         return default_server;
234 }
235 #else
236 static int get_irq_server(unsigned int virq, unsigned int strict_check)
237 {
238         return default_server;
239 }
240 #endif
241
242
243 static void xics_unmask_irq(unsigned int virq)
244 {
245         unsigned int irq;
246         int call_status;
247         int server;
248
249         pr_debug("xics: unmask virq %d\n", virq);
250
251         irq = (unsigned int)irq_map[virq].hwirq;
252         pr_debug(" -> map to hwirq 0x%x\n", irq);
253         if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
254                 return;
255
256         server = get_irq_server(virq, 0);
257
258         call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
259                                 DEFAULT_PRIORITY);
260         if (call_status != 0) {
261                 printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
262                        "returned %d\n", irq, call_status);
263                 printk("set_xive %x, server %x\n", ibm_set_xive, server);
264                 return;
265         }
266
267         /* Now unmask the interrupt (often a no-op) */
268         call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
269         if (call_status != 0) {
270                 printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
271                        "returned %d\n", irq, call_status);
272                 return;
273         }
274 }
275
276 static void xics_mask_real_irq(unsigned int irq)
277 {
278         int call_status;
279
280         if (irq == XICS_IPI)
281                 return;
282
283         call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
284         if (call_status != 0) {
285                 printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
286                        "ibm_int_off returned %d\n", irq, call_status);
287                 return;
288         }
289
290         /* Have to set XIVE to 0xff to be able to remove a slot */
291         call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
292                                 default_server, 0xff);
293         if (call_status != 0) {
294                 printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
295                        " returned %d\n", irq, call_status);
296                 return;
297         }
298 }
299
300 static void xics_mask_irq(unsigned int virq)
301 {
302         unsigned int irq;
303
304         pr_debug("xics: mask virq %d\n", virq);
305
306         irq = (unsigned int)irq_map[virq].hwirq;
307         if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
308                 return;
309         xics_mask_real_irq(irq);
310 }
311
312 static unsigned int xics_startup(unsigned int virq)
313 {
314         /* unmask it */
315         xics_unmask_irq(virq);
316         return 0;
317 }
318
319 static void xics_eoi_direct(unsigned int virq)
320 {
321         unsigned int irq = (unsigned int)irq_map[virq].hwirq;
322
323         iosync();
324         direct_xirr_info_set((0xff << 24) | irq);
325 }
326
327
328 static void xics_eoi_lpar(unsigned int virq)
329 {
330         unsigned int irq = (unsigned int)irq_map[virq].hwirq;
331
332         iosync();
333         lpar_xirr_info_set((0xff << 24) | irq);
334 }
335
336 static inline unsigned int xics_xirr_vector(unsigned int xirr)
337 {
338         /*
339          * The top byte is the old cppr, to be restored on EOI.
340          * The remaining 24 bits are the vector.
341          */
342         return xirr & 0x00ffffff;
343 }
344
345 static void xics_mask_unknown_vec(unsigned int vec)
346 {
347         printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
348         xics_mask_real_irq(vec);
349 }
350
351 static unsigned int xics_get_irq_direct(void)
352 {
353         unsigned int xirr = direct_xirr_info_get();
354         unsigned int vec = xics_xirr_vector(xirr);
355         unsigned int irq;
356
357         if (vec == XICS_IRQ_SPURIOUS)
358                 return NO_IRQ;
359
360         irq = irq_radix_revmap_lookup(xics_host, vec);
361         if (likely(irq != NO_IRQ))
362                 return irq;
363
364         /* We don't have a linux mapping, so have rtas mask it. */
365         xics_mask_unknown_vec(vec);
366
367         /* We might learn about it later, so EOI it */
368         direct_xirr_info_set(xirr);
369         return NO_IRQ;
370 }
371
372 static unsigned int xics_get_irq_lpar(void)
373 {
374         unsigned int xirr = lpar_xirr_info_get();
375         unsigned int vec = xics_xirr_vector(xirr);
376         unsigned int irq;
377
378         if (vec == XICS_IRQ_SPURIOUS)
379                 return NO_IRQ;
380
381         irq = irq_radix_revmap_lookup(xics_host, vec);
382         if (likely(irq != NO_IRQ))
383                 return irq;
384
385         /* We don't have a linux mapping, so have RTAS mask it. */
386         xics_mask_unknown_vec(vec);
387
388         /* We might learn about it later, so EOI it */
389         lpar_xirr_info_set(xirr);
390         return NO_IRQ;
391 }
392
393 #ifdef CONFIG_SMP
394 static irqreturn_t xics_ipi_dispatch(int cpu)
395 {
396         WARN_ON(cpu_is_offline(cpu));
397
398         while (xics_ipi_message[cpu].value) {
399                 if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
400                                        &xics_ipi_message[cpu].value)) {
401                         mb();
402                         smp_message_recv(PPC_MSG_CALL_FUNCTION);
403                 }
404                 if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
405                                        &xics_ipi_message[cpu].value)) {
406                         mb();
407                         smp_message_recv(PPC_MSG_RESCHEDULE);
408                 }
409                 if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,
410                                        &xics_ipi_message[cpu].value)) {
411                         mb();
412                         smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
413                 }
414 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
415                 if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
416                                        &xics_ipi_message[cpu].value)) {
417                         mb();
418                         smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
419                 }
420 #endif
421         }
422         return IRQ_HANDLED;
423 }
424
425 static inline void smp_xics_do_message(int cpu, int msg)
426 {
427         set_bit(msg, &xics_ipi_message[cpu].value);
428         mb();
429         if (firmware_has_feature(FW_FEATURE_LPAR))
430                 lpar_qirr_info(cpu, IPI_PRIORITY);
431         else
432                 direct_qirr_info(cpu, IPI_PRIORITY);
433 }
434
435 void smp_xics_message_pass(int target, int msg)
436 {
437         unsigned int i;
438
439         if (target < NR_CPUS) {
440                 smp_xics_do_message(target, msg);
441         } else {
442                 for_each_online_cpu(i) {
443                         if (target == MSG_ALL_BUT_SELF
444                             && i == smp_processor_id())
445                                 continue;
446                         smp_xics_do_message(i, msg);
447                 }
448         }
449 }
450
451
452 static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
453 {
454         int cpu = smp_processor_id();
455
456         direct_qirr_info(cpu, 0xff);
457
458         return xics_ipi_dispatch(cpu);
459 }
460
461 static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
462 {
463         int cpu = smp_processor_id();
464
465         lpar_qirr_info(cpu, 0xff);
466
467         return xics_ipi_dispatch(cpu);
468 }
469 #endif /* CONFIG_SMP */
470
471 static void xics_set_cpu_priority(unsigned char cppr)
472 {
473         if (firmware_has_feature(FW_FEATURE_LPAR))
474                 lpar_cppr_info(cppr);
475         else
476                 direct_cppr_info(cppr);
477         iosync();
478 }
479
480 static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
481 {
482         unsigned int irq;
483         int status;
484         int xics_status[2];
485         int irq_server;
486
487         irq = (unsigned int)irq_map[virq].hwirq;
488         if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
489                 return;
490
491         status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
492
493         if (status) {
494                 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
495                        "returns %d\n", irq, status);
496                 return;
497         }
498
499         /*
500          * For the moment only implement delivery to all cpus or one cpu.
501          * Get current irq_server for the given irq
502          */
503         irq_server = get_irq_server(virq, 1);
504         if (irq_server == -1) {
505                 char cpulist[128];
506                 cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
507                 printk(KERN_WARNING "xics_set_affinity: No online cpus in "
508                                 "the mask %s for irq %d\n", cpulist, virq);
509                 return;
510         }
511
512         status = rtas_call(ibm_set_xive, 3, 1, NULL,
513                                 irq, irq_server, xics_status[1]);
514
515         if (status) {
516                 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
517                        "returns %d\n", irq, status);
518                 return;
519         }
520 }
521
522 void xics_setup_cpu(void)
523 {
524         xics_set_cpu_priority(0xff);
525
526         /*
527          * Put the calling processor into the GIQ.  This is really only
528          * necessary from a secondary thread as the OF start-cpu interface
529          * performs this function for us on primary threads.
530          *
531          * XXX: undo of teardown on kexec needs this too, as may hotplug
532          */
533         rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
534                 (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
535 }
536
537
538 static struct irq_chip xics_pic_direct = {
539         .typename = " XICS     ",
540         .startup = xics_startup,
541         .mask = xics_mask_irq,
542         .unmask = xics_unmask_irq,
543         .eoi = xics_eoi_direct,
544         .set_affinity = xics_set_affinity
545 };
546
547
548 static struct irq_chip xics_pic_lpar = {
549         .typename = " XICS     ",
550         .startup = xics_startup,
551         .mask = xics_mask_irq,
552         .unmask = xics_unmask_irq,
553         .eoi = xics_eoi_lpar,
554         .set_affinity = xics_set_affinity
555 };
556
557 /* Points to the irq_chip we're actually using */
558 static struct irq_chip *xics_irq_chip;
559
560 static int xics_host_match(struct irq_host *h, struct device_node *node)
561 {
562         /* IBM machines have interrupt parents of various funky types for things
563          * like vdevices, events, etc... The trick we use here is to match
564          * everything here except the legacy 8259 which is compatible "chrp,iic"
565          */
566         return !of_device_is_compatible(node, "chrp,iic");
567 }
568
569 static int xics_host_map(struct irq_host *h, unsigned int virq,
570                          irq_hw_number_t hw)
571 {
572         pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
573
574         /* Insert the interrupt mapping into the radix tree for fast lookup */
575         irq_radix_revmap_insert(xics_host, virq, hw);
576
577         get_irq_desc(virq)->status |= IRQ_LEVEL;
578         set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
579         return 0;
580 }
581
582 static int xics_host_xlate(struct irq_host *h, struct device_node *ct,
583                            u32 *intspec, unsigned int intsize,
584                            irq_hw_number_t *out_hwirq, unsigned int *out_flags)
585
586 {
587         /* Current xics implementation translates everything
588          * to level. It is not technically right for MSIs but this
589          * is irrelevant at this point. We might get smarter in the future
590          */
591         *out_hwirq = intspec[0];
592         *out_flags = IRQ_TYPE_LEVEL_LOW;
593
594         return 0;
595 }
596
597 static struct irq_host_ops xics_host_ops = {
598         .match = xics_host_match,
599         .map = xics_host_map,
600         .xlate = xics_host_xlate,
601 };
602
603 static void __init xics_init_host(void)
604 {
605         if (firmware_has_feature(FW_FEATURE_LPAR))
606                 xics_irq_chip = &xics_pic_lpar;
607         else
608                 xics_irq_chip = &xics_pic_direct;
609
610         xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, &xics_host_ops,
611                                    XICS_IRQ_SPURIOUS);
612         BUG_ON(xics_host == NULL);
613         irq_set_default_host(xics_host);
614 }
615
616 static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
617                                      unsigned long size)
618 {
619 #ifdef CONFIG_SMP
620         int i;
621
622         /* This may look gross but it's good enough for now, we don't quite
623          * have a hard -> linux processor id matching.
624          */
625         for_each_possible_cpu(i) {
626                 if (!cpu_present(i))
627                         continue;
628                 if (hw_id == get_hard_smp_processor_id(i)) {
629                         xics_per_cpu[i] = ioremap(addr, size);
630                         return;
631                 }
632         }
633 #else
634         if (hw_id != 0)
635                 return;
636         xics_per_cpu[0] = ioremap(addr, size);
637 #endif /* CONFIG_SMP */
638 }
639
640 static void __init xics_init_one_node(struct device_node *np,
641                                       unsigned int *indx)
642 {
643         unsigned int ilen;
644         const u32 *ireg;
645
646         /* This code does the theorically broken assumption that the interrupt
647          * server numbers are the same as the hard CPU numbers.
648          * This happens to be the case so far but we are playing with fire...
649          * should be fixed one of these days. -BenH.
650          */
651         ireg = of_get_property(np, "ibm,interrupt-server-ranges", NULL);
652
653         /* Do that ever happen ? we'll know soon enough... but even good'old
654          * f80 does have that property ..
655          */
656         WARN_ON(ireg == NULL);
657         if (ireg) {
658                 /*
659                  * set node starting index for this node
660                  */
661                 *indx = *ireg;
662         }
663         ireg = of_get_property(np, "reg", &ilen);
664         if (!ireg)
665                 panic("xics_init_IRQ: can't find interrupt reg property");
666
667         while (ilen >= (4 * sizeof(u32))) {
668                 unsigned long addr, size;
669
670                 /* XXX Use proper OF parsing code here !!! */
671                 addr = (unsigned long)*ireg++ << 32;
672                 ilen -= sizeof(u32);
673                 addr |= *ireg++;
674                 ilen -= sizeof(u32);
675                 size = (unsigned long)*ireg++ << 32;
676                 ilen -= sizeof(u32);
677                 size |= *ireg++;
678                 ilen -= sizeof(u32);
679                 xics_map_one_cpu(*indx, addr, size);
680                 (*indx)++;
681         }
682 }
683
684 void __init xics_init_IRQ(void)
685 {
686         struct device_node *np;
687         u32 indx = 0;
688         int found = 0;
689
690         ppc64_boot_msg(0x20, "XICS Init");
691
692         ibm_get_xive = rtas_token("ibm,get-xive");
693         ibm_set_xive = rtas_token("ibm,set-xive");
694         ibm_int_on  = rtas_token("ibm,int-on");
695         ibm_int_off = rtas_token("ibm,int-off");
696
697         for_each_node_by_type(np, "PowerPC-External-Interrupt-Presentation") {
698                 found = 1;
699                 if (firmware_has_feature(FW_FEATURE_LPAR))
700                         break;
701                 xics_init_one_node(np, &indx);
702         }
703         if (found == 0)
704                 return;
705
706         xics_update_irq_servers();
707         xics_init_host();
708
709         if (firmware_has_feature(FW_FEATURE_LPAR))
710                 ppc_md.get_irq = xics_get_irq_lpar;
711         else
712                 ppc_md.get_irq = xics_get_irq_direct;
713
714         xics_setup_cpu();
715
716         ppc64_boot_msg(0x21, "XICS Done");
717 }
718
719
720 #ifdef CONFIG_SMP
721 static void xics_request_ipi(void)
722 {
723         unsigned int ipi;
724         int rc;
725
726         ipi = irq_create_mapping(xics_host, XICS_IPI);
727         BUG_ON(ipi == NO_IRQ);
728
729         /*
730          * IPIs are marked IRQF_DISABLED as they must run with irqs
731          * disabled
732          */
733         set_irq_handler(ipi, handle_percpu_irq);
734         if (firmware_has_feature(FW_FEATURE_LPAR))
735                 rc = request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
736                                 "IPI", NULL);
737         else
738                 rc = request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
739                                 "IPI", NULL);
740         BUG_ON(rc);
741 }
742
743 int __init smp_xics_probe(void)
744 {
745         xics_request_ipi();
746
747         return cpus_weight(cpu_possible_map);
748 }
749
750 #endif /* CONFIG_SMP */
751
752 void xics_teardown_cpu(void)
753 {
754         int cpu = smp_processor_id();
755
756         xics_set_cpu_priority(0);
757
758         /*
759          * Clear IPI
760          */
761         if (firmware_has_feature(FW_FEATURE_LPAR))
762                 lpar_qirr_info(cpu, 0xff);
763         else
764                 direct_qirr_info(cpu, 0xff);
765 }
766
767 void xics_kexec_teardown_cpu(int secondary)
768 {
769         unsigned int ipi;
770         struct irq_desc *desc;
771
772         xics_teardown_cpu();
773
774         /*
775          * we need to EOI the IPI
776          *
777          * probably need to check all the other interrupts too
778          * should we be flagging idle loop instead?
779          * or creating some task to be scheduled?
780          */
781
782         ipi = irq_find_mapping(xics_host, XICS_IPI);
783         if (ipi == XICS_IRQ_SPURIOUS)
784                 return;
785         desc = get_irq_desc(ipi);
786         if (desc->chip && desc->chip->eoi)
787                 desc->chip->eoi(ipi);
788
789         /*
790          * Some machines need to have at least one cpu in the GIQ,
791          * so leave the master cpu in the group.
792          */
793         if (secondary)
794                 rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
795                                    (1UL << interrupt_server_size) - 1 -
796                                    default_distrib_server, 0);
797 }
798
799 #ifdef CONFIG_HOTPLUG_CPU
800
801 /* Interrupts are disabled. */
802 void xics_migrate_irqs_away(void)
803 {
804         int status;
805         int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
806         unsigned int irq, virq;
807
808         /* If we used to be the default server, move to the new "boot_cpuid" */
809         if (hw_cpu == default_server)
810                 xics_update_irq_servers();
811
812         /* Reject any interrupt that was queued to us... */
813         xics_set_cpu_priority(0);
814
815         /* remove ourselves from the global interrupt queue */
816         status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
817                 (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
818         WARN_ON(status < 0);
819
820         /* Allow IPIs again... */
821         xics_set_cpu_priority(DEFAULT_PRIORITY);
822
823         for_each_irq(virq) {
824                 struct irq_desc *desc;
825                 int xics_status[2];
826                 unsigned long flags;
827
828                 /* We cant set affinity on ISA interrupts */
829                 if (virq < NUM_ISA_INTERRUPTS)
830                         continue;
831                 if (irq_map[virq].host != xics_host)
832                         continue;
833                 irq = (unsigned int)irq_map[virq].hwirq;
834                 /* We need to get IPIs still. */
835                 if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
836                         continue;
837                 desc = get_irq_desc(virq);
838
839                 /* We only need to migrate enabled IRQS */
840                 if (desc == NULL || desc->chip == NULL
841                     || desc->action == NULL
842                     || desc->chip->set_affinity == NULL)
843                         continue;
844
845                 spin_lock_irqsave(&desc->lock, flags);
846
847                 status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
848                 if (status) {
849                         printk(KERN_ERR "migrate_irqs_away: irq=%u "
850                                         "ibm,get-xive returns %d\n",
851                                         virq, status);
852                         goto unlock;
853                 }
854
855                 /*
856                  * We only support delivery to all cpus or to one cpu.
857                  * The irq has to be migrated only in the single cpu
858                  * case.
859                  */
860                 if (xics_status[0] != hw_cpu)
861                         goto unlock;
862
863                 printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
864                        virq, cpu);
865
866                 /* Reset affinity to all cpus */
867                 irq_desc[virq].affinity = CPU_MASK_ALL;
868                 desc->chip->set_affinity(virq, CPU_MASK_ALL);
869 unlock:
870                 spin_unlock_irqrestore(&desc->lock, flags);
871         }
872 }
873 #endif