[POWERPC] MPIC protected sources

Some HW platforms, such as the new cell blades, requires some MPIC sources
to be left alone by the operating system. This implements support for
a "protected-sources" property in the mpic controller node containing a list
of source numbers to be protected against operating system interference.

For those interested in the gory details, the MPIC on the southbridge of
those blades has some of the processor outputs routed to the cell, and
at least one routed as a GPIO to the service processor. It will be used
in the GA product for routing some of the southbridge error interrupts
to the service processor which implements some of the RAS stuff, such
as checkstopping when fatal errors occurs before they can propagate.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by Benjamin Herrenschmidt and committed by Paul Mackerras 7fd72186 34f329db

+35
+32
arch/powerpc/sysdev/mpic.c
··· 877 877 878 878 if (hw == mpic->spurious_vec) 879 879 return -EINVAL; 880 + if (mpic->protected && test_bit(hw, mpic->protected)) 881 + return -EINVAL; 880 882 881 883 #ifdef CONFIG_SMP 882 884 else if (hw >= mpic->ipi_vecs[0]) { ··· 1036 1034 if (node && of_get_property(node, "big-endian", NULL) != NULL) 1037 1035 mpic->flags |= MPIC_BIG_ENDIAN; 1038 1036 1037 + /* Look for protected sources */ 1038 + if (node) { 1039 + unsigned int psize, bits, mapsize; 1040 + const u32 *psrc = 1041 + of_get_property(node, "protected-sources", &psize); 1042 + if (psrc) { 1043 + psize /= 4; 1044 + bits = intvec_top + 1; 1045 + mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long); 1046 + mpic->protected = alloc_bootmem(mapsize); 1047 + BUG_ON(mpic->protected == NULL); 1048 + memset(mpic->protected, 0, mapsize); 1049 + for (i = 0; i < psize; i++) { 1050 + if (psrc[i] > intvec_top) 1051 + continue; 1052 + __set_bit(psrc[i], mpic->protected); 1053 + } 1054 + } 1055 + } 1039 1056 1040 1057 #ifdef CONFIG_MPIC_WEIRD 1041 1058 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; ··· 1234 1213 u32 vecpri = MPIC_VECPRI_MASK | i | 1235 1214 (8 << MPIC_VECPRI_PRIORITY_SHIFT); 1236 1215 1216 + /* check if protected */ 1217 + if (mpic->protected && test_bit(i, mpic->protected)) 1218 + continue; 1237 1219 /* init hw */ 1238 1220 mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); 1239 1221 mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), ··· 1431 1407 mpic_eoi(mpic); 1432 1408 return NO_IRQ; 1433 1409 } 1410 + if (unlikely(mpic->protected && test_bit(src, mpic->protected))) { 1411 + if (printk_ratelimit()) 1412 + printk(KERN_WARNING "%s: Got protected source %d !\n", 1413 + mpic->name, (int)src); 1414 + mpic_eoi(mpic); 1415 + return NO_IRQ; 1416 + } 1417 + 1434 1418 return irq_linear_revmap(mpic->irqhost, src); 1435 1419 } 1436 1420
+3
include/asm-powerpc/mpic.h
··· 296 296 unsigned int dcr_base; 297 297 #endif 298 298 299 + /* Protected sources */ 300 + unsigned long *protected; 301 + 299 302 #ifdef CONFIG_MPIC_WEIRD 300 303 /* Pointer to HW info array */ 301 304 u32 *hw_set;