[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 878 if (hw == mpic->spurious_vec) 879 return -EINVAL; 880 881 #ifdef CONFIG_SMP 882 else if (hw >= mpic->ipi_vecs[0]) { ··· 1036 if (node && of_get_property(node, "big-endian", NULL) != NULL) 1037 mpic->flags |= MPIC_BIG_ENDIAN; 1038 1039 1040 #ifdef CONFIG_MPIC_WEIRD 1041 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; ··· 1234 u32 vecpri = MPIC_VECPRI_MASK | i | 1235 (8 << MPIC_VECPRI_PRIORITY_SHIFT); 1236 1237 /* init hw */ 1238 mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); 1239 mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), ··· 1431 mpic_eoi(mpic); 1432 return NO_IRQ; 1433 } 1434 return irq_linear_revmap(mpic->irqhost, src); 1435 } 1436
··· 877 878 if (hw == mpic->spurious_vec) 879 return -EINVAL; 880 + if (mpic->protected && test_bit(hw, mpic->protected)) 881 + return -EINVAL; 882 883 #ifdef CONFIG_SMP 884 else if (hw >= mpic->ipi_vecs[0]) { ··· 1034 if (node && of_get_property(node, "big-endian", NULL) != NULL) 1035 mpic->flags |= MPIC_BIG_ENDIAN; 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 + } 1056 1057 #ifdef CONFIG_MPIC_WEIRD 1058 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; ··· 1213 u32 vecpri = MPIC_VECPRI_MASK | i | 1214 (8 << MPIC_VECPRI_PRIORITY_SHIFT); 1215 1216 + /* check if protected */ 1217 + if (mpic->protected && test_bit(i, mpic->protected)) 1218 + continue; 1219 /* init hw */ 1220 mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); 1221 mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), ··· 1407 mpic_eoi(mpic); 1408 return NO_IRQ; 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 + 1418 return irq_linear_revmap(mpic->irqhost, src); 1419 } 1420
+3
include/asm-powerpc/mpic.h
··· 296 unsigned int dcr_base; 297 #endif 298 299 #ifdef CONFIG_MPIC_WEIRD 300 /* Pointer to HW info array */ 301 u32 *hw_set;
··· 296 unsigned int dcr_base; 297 #endif 298 299 + /* Protected sources */ 300 + unsigned long *protected; 301 + 302 #ifdef CONFIG_MPIC_WEIRD 303 /* Pointer to HW info array */ 304 u32 *hw_set;