diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 53 |
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 | ||
335 | static inline unsigned int xics_remap_irq(unsigned int vec) | 335 | static 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; | 344 | static 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 | |||
350 | static 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 | ||
353 | static 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 | ||
358 | static unsigned int xics_get_irq_lpar(void) | 371 | static 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 |