aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/pseries/xics.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 6b1a005cc0cc..1bccd4a56b57 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -332,32 +332,61 @@ static void xics_eoi_lpar(unsigned int virq)
332 lpar_xirr_info_set((0xff << 24) | irq); 332 lpar_xirr_info_set((0xff << 24) | irq);
333} 333}
334 334
335static inline unsigned int xics_remap_irq(unsigned int vec) 335static inline unsigned int xics_xirr_vector(unsigned int xirr)
336{ 336{
337 unsigned int irq; 337 /*
338 * The top byte is the old cppr, to be restored on EOI.
339 * The remaining 24 bits are the vector.
340 */
341 return xirr & 0x00ffffff;
342}
338 343
339 vec &= 0x00ffffff; 344static void xics_mask_unknown_vec(unsigned int vec)
345{
346 printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
347 xics_mask_real_irq(vec);
348}
349
350static unsigned int xics_get_irq_direct(void)
351{
352 unsigned int xirr = direct_xirr_info_get();
353 unsigned int vec = xics_xirr_vector(xirr);
354 unsigned int irq;
340 355
341 if (vec == XICS_IRQ_SPURIOUS) 356 if (vec == XICS_IRQ_SPURIOUS)
342 return NO_IRQ; 357 return NO_IRQ;
358
343 irq = irq_radix_revmap_lookup(xics_host, vec); 359 irq = irq_radix_revmap_lookup(xics_host, vec);
344 if (likely(irq != NO_IRQ)) 360 if (likely(irq != NO_IRQ))
345 return irq; 361 return irq;
346 362
347 printk(KERN_ERR "Interrupt %u (real) is invalid," 363 /* We don't have a linux mapping, so have rtas mask it. */
348 " disabling it.\n", vec); 364 xics_mask_unknown_vec(vec);
349 xics_mask_real_irq(vec);
350 return NO_IRQ;
351}
352 365
353static unsigned int xics_get_irq_direct(void) 366 /* We might learn about it later, so EOI it */
354{ 367 direct_xirr_info_set(xirr);
355 return xics_remap_irq(direct_xirr_info_get()); 368 return NO_IRQ;
356} 369}
357 370
358static unsigned int xics_get_irq_lpar(void) 371static unsigned int xics_get_irq_lpar(void)
359{ 372{
360 return xics_remap_irq(lpar_xirr_info_get()); 373 unsigned int xirr = lpar_xirr_info_get();
374 unsigned int vec = xics_xirr_vector(xirr);
375 unsigned int irq;
376
377 if (vec == XICS_IRQ_SPURIOUS)
378 return NO_IRQ;
379
380 irq = irq_radix_revmap_lookup(xics_host, vec);
381 if (likely(irq != NO_IRQ))
382 return irq;
383
384 /* We don't have a linux mapping, so have RTAS mask it. */
385 xics_mask_unknown_vec(vec);
386
387 /* We might learn about it later, so EOI it */
388 lpar_xirr_info_set(xirr);
389 return NO_IRQ;
361} 390}
362 391
363#ifdef CONFIG_SMP 392#ifdef CONFIG_SMP