diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 75aad38179f0..74c64c0d3b71 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -877,6 +877,8 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, | |||
877 | 877 | ||
878 | if (hw == mpic->spurious_vec) | 878 | if (hw == mpic->spurious_vec) |
879 | return -EINVAL; | 879 | return -EINVAL; |
880 | if (mpic->protected && test_bit(hw, mpic->protected)) | ||
881 | return -EINVAL; | ||
880 | 882 | ||
881 | #ifdef CONFIG_SMP | 883 | #ifdef CONFIG_SMP |
882 | else if (hw >= mpic->ipi_vecs[0]) { | 884 | else if (hw >= mpic->ipi_vecs[0]) { |
@@ -1034,6 +1036,25 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1034 | if (node && of_get_property(node, "big-endian", NULL) != NULL) | 1036 | if (node && of_get_property(node, "big-endian", NULL) != NULL) |
1035 | mpic->flags |= MPIC_BIG_ENDIAN; | 1037 | mpic->flags |= MPIC_BIG_ENDIAN; |
1036 | 1038 | ||
1039 | /* Look for protected sources */ | ||
1040 | if (node) { | ||
1041 | unsigned int psize, bits, mapsize; | ||
1042 | const u32 *psrc = | ||
1043 | of_get_property(node, "protected-sources", &psize); | ||
1044 | if (psrc) { | ||
1045 | psize /= 4; | ||
1046 | bits = intvec_top + 1; | ||
1047 | mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long); | ||
1048 | mpic->protected = alloc_bootmem(mapsize); | ||
1049 | BUG_ON(mpic->protected == NULL); | ||
1050 | memset(mpic->protected, 0, mapsize); | ||
1051 | for (i = 0; i < psize; i++) { | ||
1052 | if (psrc[i] > intvec_top) | ||
1053 | continue; | ||
1054 | __set_bit(psrc[i], mpic->protected); | ||
1055 | } | ||
1056 | } | ||
1057 | } | ||
1037 | 1058 | ||
1038 | #ifdef CONFIG_MPIC_WEIRD | 1059 | #ifdef CONFIG_MPIC_WEIRD |
1039 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; | 1060 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; |
@@ -1213,6 +1234,9 @@ void __init mpic_init(struct mpic *mpic) | |||
1213 | u32 vecpri = MPIC_VECPRI_MASK | i | | 1234 | u32 vecpri = MPIC_VECPRI_MASK | i | |
1214 | (8 << MPIC_VECPRI_PRIORITY_SHIFT); | 1235 | (8 << MPIC_VECPRI_PRIORITY_SHIFT); |
1215 | 1236 | ||
1237 | /* check if protected */ | ||
1238 | if (mpic->protected && test_bit(i, mpic->protected)) | ||
1239 | continue; | ||
1216 | /* init hw */ | 1240 | /* init hw */ |
1217 | mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); | 1241 | mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); |
1218 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), | 1242 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), |
@@ -1407,6 +1431,14 @@ unsigned int mpic_get_one_irq(struct mpic *mpic) | |||
1407 | mpic_eoi(mpic); | 1431 | mpic_eoi(mpic); |
1408 | return NO_IRQ; | 1432 | return NO_IRQ; |
1409 | } | 1433 | } |
1434 | if (unlikely(mpic->protected && test_bit(src, mpic->protected))) { | ||
1435 | if (printk_ratelimit()) | ||
1436 | printk(KERN_WARNING "%s: Got protected source %d !\n", | ||
1437 | mpic->name, (int)src); | ||
1438 | mpic_eoi(mpic); | ||
1439 | return NO_IRQ; | ||
1440 | } | ||
1441 | |||
1410 | return irq_linear_revmap(mpic->irqhost, src); | 1442 | return irq_linear_revmap(mpic->irqhost, src); |
1411 | } | 1443 | } |
1412 | 1444 | ||