aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/pseries/xics.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 690f87584f6b..7d01b58f3989 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -20,6 +20,7 @@
20#include <linux/cpu.h> 20#include <linux/cpu.h>
21#include <linux/msi.h> 21#include <linux/msi.h>
22#include <linux/of.h> 22#include <linux/of.h>
23#include <linux/percpu.h>
23 24
24#include <asm/firmware.h> 25#include <asm/firmware.h>
25#include <asm/io.h> 26#include <asm/io.h>
@@ -46,6 +47,12 @@ static struct irq_host *xics_host;
46 */ 47 */
47#define IPI_PRIORITY 4 48#define IPI_PRIORITY 4
48 49
50/* The least favored priority */
51#define LOWEST_PRIORITY 0xFF
52
53/* The number of priorities defined above */
54#define MAX_NUM_PRIORITIES 3
55
49static unsigned int default_server = 0xFF; 56static unsigned int default_server = 0xFF;
50static unsigned int default_distrib_server = 0; 57static unsigned int default_distrib_server = 0;
51static unsigned int interrupt_server_size = 8; 58static unsigned int interrupt_server_size = 8;
@@ -56,6 +63,12 @@ static int ibm_set_xive;
56static int ibm_int_on; 63static int ibm_int_on;
57static int ibm_int_off; 64static int ibm_int_off;
58 65
66struct xics_cppr {
67 unsigned char stack[MAX_NUM_PRIORITIES];
68 int index;
69};
70
71static DEFINE_PER_CPU(struct xics_cppr, xics_cppr);
59 72
60/* Direct hardware low level accessors */ 73/* Direct hardware low level accessors */
61 74
@@ -284,6 +297,19 @@ static inline unsigned int xics_xirr_vector(unsigned int xirr)
284 return xirr & 0x00ffffff; 297 return xirr & 0x00ffffff;
285} 298}
286 299
300static void push_cppr(unsigned int vec)
301{
302 struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
303
304 if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
305 return;
306
307 if (vec == XICS_IPI)
308 os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
309 else
310 os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
311}
312
287static unsigned int xics_get_irq_direct(void) 313static unsigned int xics_get_irq_direct(void)
288{ 314{
289 unsigned int xirr = direct_xirr_info_get(); 315 unsigned int xirr = direct_xirr_info_get();
@@ -294,8 +320,10 @@ static unsigned int xics_get_irq_direct(void)
294 return NO_IRQ; 320 return NO_IRQ;
295 321
296 irq = irq_radix_revmap_lookup(xics_host, vec); 322 irq = irq_radix_revmap_lookup(xics_host, vec);
297 if (likely(irq != NO_IRQ)) 323 if (likely(irq != NO_IRQ)) {
324 push_cppr(vec);
298 return irq; 325 return irq;
326 }
299 327
300 /* We don't have a linux mapping, so have rtas mask it. */ 328 /* We don't have a linux mapping, so have rtas mask it. */
301 xics_mask_unknown_vec(vec); 329 xics_mask_unknown_vec(vec);
@@ -315,8 +343,10 @@ static unsigned int xics_get_irq_lpar(void)
315 return NO_IRQ; 343 return NO_IRQ;
316 344
317 irq = irq_radix_revmap_lookup(xics_host, vec); 345 irq = irq_radix_revmap_lookup(xics_host, vec);
318 if (likely(irq != NO_IRQ)) 346 if (likely(irq != NO_IRQ)) {
347 push_cppr(vec);
319 return irq; 348 return irq;
349 }
320 350
321 /* We don't have a linux mapping, so have RTAS mask it. */ 351 /* We don't have a linux mapping, so have RTAS mask it. */
322 xics_mask_unknown_vec(vec); 352 xics_mask_unknown_vec(vec);
@@ -326,12 +356,22 @@ static unsigned int xics_get_irq_lpar(void)
326 return NO_IRQ; 356 return NO_IRQ;
327} 357}
328 358
359static unsigned char pop_cppr(void)
360{
361 struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
362
363 if (WARN_ON(os_cppr->index < 1))
364 return LOWEST_PRIORITY;
365
366 return os_cppr->stack[--os_cppr->index];
367}
368
329static void xics_eoi_direct(unsigned int virq) 369static void xics_eoi_direct(unsigned int virq)
330{ 370{
331 unsigned int irq = (unsigned int)irq_map[virq].hwirq; 371 unsigned int irq = (unsigned int)irq_map[virq].hwirq;
332 372
333 iosync(); 373 iosync();
334 direct_xirr_info_set((0xff << 24) | irq); 374 direct_xirr_info_set((pop_cppr() << 24) | irq);
335} 375}
336 376
337static void xics_eoi_lpar(unsigned int virq) 377static void xics_eoi_lpar(unsigned int virq)
@@ -339,7 +379,7 @@ static void xics_eoi_lpar(unsigned int virq)
339 unsigned int irq = (unsigned int)irq_map[virq].hwirq; 379 unsigned int irq = (unsigned int)irq_map[virq].hwirq;
340 380
341 iosync(); 381 iosync();
342 lpar_xirr_info_set((0xff << 24) | irq); 382 lpar_xirr_info_set((pop_cppr() << 24) | irq);
343} 383}
344 384
345static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) 385static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
@@ -746,6 +786,12 @@ void __init xics_init_IRQ(void)
746 786
747static void xics_set_cpu_priority(unsigned char cppr) 787static void xics_set_cpu_priority(unsigned char cppr)
748{ 788{
789 struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
790
791 BUG_ON(os_cppr->index != 0);
792
793 os_cppr->stack[os_cppr->index] = cppr;
794
749 if (firmware_has_feature(FW_FEATURE_LPAR)) 795 if (firmware_has_feature(FW_FEATURE_LPAR))
750 lpar_cppr_info(cppr); 796 lpar_cppr_info(cppr);
751 else 797 else
@@ -772,7 +818,7 @@ static void xics_set_cpu_giq(unsigned int gserver, unsigned int join)
772 818
773void xics_setup_cpu(void) 819void xics_setup_cpu(void)
774{ 820{
775 xics_set_cpu_priority(0xff); 821 xics_set_cpu_priority(LOWEST_PRIORITY);
776 822
777 xics_set_cpu_giq(default_distrib_server, 1); 823 xics_set_cpu_giq(default_distrib_server, 1);
778} 824}