diff options
author | Olof Johansson <olof@lixom.net> | 2007-01-29 00:33:18 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-02-06 22:03:19 -0500 |
commit | 7df2457db83bc922fcc8b462526b77f1ffe8c84b (patch) | |
tree | 7029d9e27b858e435c2fc4ce9a6d83a2b028e290 /arch/powerpc/sysdev/mpic.c | |
parent | 6529c13dfe413e437ad1ed0e97783dcf69137114 (diff) |
[POWERPC] MPIC: support more than 256 sources
Allow more than the default 256 MPIC sources. Allocates a new flag
(MPIC_LARGE_VECTORS) to be used by platform code when instantiating
the mpic.
I picked 11 bits worth right now since it would cover the number of
sources on any hardware I have seen. It can always be increased later
if needed.
Signed-off-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 62262f2a4a83..aa701cc27ecc 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -496,13 +496,18 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) | |||
496 | static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) | 496 | static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) |
497 | { | 497 | { |
498 | unsigned int src = mpic_irq_to_hw(irq); | 498 | unsigned int src = mpic_irq_to_hw(irq); |
499 | struct mpic *mpic; | ||
499 | 500 | ||
500 | if (irq < NUM_ISA_INTERRUPTS) | 501 | if (irq < NUM_ISA_INTERRUPTS) |
501 | return NULL; | 502 | return NULL; |
503 | |||
504 | mpic = irq_desc[irq].chip_data; | ||
505 | |||
502 | if (is_ipi) | 506 | if (is_ipi) |
503 | *is_ipi = (src >= MPIC_VEC_IPI_0 && src <= MPIC_VEC_IPI_3); | 507 | *is_ipi = (src >= mpic->ipi_vecs[0] && |
508 | src <= mpic->ipi_vecs[3]); | ||
504 | 509 | ||
505 | return irq_desc[irq].chip_data; | 510 | return mpic; |
506 | } | 511 | } |
507 | 512 | ||
508 | /* Convert a cpu mask from logical to physical cpu numbers. */ | 513 | /* Convert a cpu mask from logical to physical cpu numbers. */ |
@@ -540,7 +545,11 @@ static inline void mpic_eoi(struct mpic *mpic) | |||
540 | #ifdef CONFIG_SMP | 545 | #ifdef CONFIG_SMP |
541 | static irqreturn_t mpic_ipi_action(int irq, void *dev_id) | 546 | static irqreturn_t mpic_ipi_action(int irq, void *dev_id) |
542 | { | 547 | { |
543 | smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0); | 548 | struct mpic *mpic; |
549 | |||
550 | mpic = mpic_find(irq, NULL); | ||
551 | smp_message_recv(mpic_irq_to_hw(irq) - mpic->ipi_vecs[0]); | ||
552 | |||
544 | return IRQ_HANDLED; | 553 | return IRQ_HANDLED; |
545 | } | 554 | } |
546 | #endif /* CONFIG_SMP */ | 555 | #endif /* CONFIG_SMP */ |
@@ -663,7 +672,7 @@ static void mpic_end_ht_irq(unsigned int irq) | |||
663 | static void mpic_unmask_ipi(unsigned int irq) | 672 | static void mpic_unmask_ipi(unsigned int irq) |
664 | { | 673 | { |
665 | struct mpic *mpic = mpic_from_ipi(irq); | 674 | struct mpic *mpic = mpic_from_ipi(irq); |
666 | unsigned int src = mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0; | 675 | unsigned int src = mpic_irq_to_hw(irq) - mpic->ipi_vecs[0]; |
667 | 676 | ||
668 | DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); | 677 | DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); |
669 | mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); | 678 | mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); |
@@ -807,11 +816,11 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, | |||
807 | 816 | ||
808 | DBG("mpic: map virq %d, hwirq 0x%lx\n", virq, hw); | 817 | DBG("mpic: map virq %d, hwirq 0x%lx\n", virq, hw); |
809 | 818 | ||
810 | if (hw == MPIC_VEC_SPURRIOUS) | 819 | if (hw == mpic->spurious_vec) |
811 | return -EINVAL; | 820 | return -EINVAL; |
812 | 821 | ||
813 | #ifdef CONFIG_SMP | 822 | #ifdef CONFIG_SMP |
814 | else if (hw >= MPIC_VEC_IPI_0) { | 823 | else if (hw >= mpic->ipi_vecs[0]) { |
815 | WARN_ON(!(mpic->flags & MPIC_PRIMARY)); | 824 | WARN_ON(!(mpic->flags & MPIC_PRIMARY)); |
816 | 825 | ||
817 | DBG("mpic: mapping as IPI\n"); | 826 | DBG("mpic: mapping as IPI\n"); |
@@ -904,6 +913,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
904 | u32 reg; | 913 | u32 reg; |
905 | const char *vers; | 914 | const char *vers; |
906 | int i; | 915 | int i; |
916 | int intvec_top; | ||
907 | u64 paddr = phys_addr; | 917 | u64 paddr = phys_addr; |
908 | 918 | ||
909 | mpic = alloc_bootmem(sizeof(struct mpic)); | 919 | mpic = alloc_bootmem(sizeof(struct mpic)); |
@@ -914,9 +924,9 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
914 | mpic->name = name; | 924 | mpic->name = name; |
915 | mpic->of_node = of_node_get(node); | 925 | mpic->of_node = of_node_get(node); |
916 | 926 | ||
917 | mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 256, | 927 | mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, isu_size, |
918 | &mpic_host_ops, | 928 | &mpic_host_ops, |
919 | MPIC_VEC_SPURRIOUS); | 929 | flags & MPIC_LARGE_VECTORS ? 2048 : 256); |
920 | if (mpic->irqhost == NULL) { | 930 | if (mpic->irqhost == NULL) { |
921 | of_node_put(node); | 931 | of_node_put(node); |
922 | return NULL; | 932 | return NULL; |
@@ -944,6 +954,21 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
944 | mpic->irq_count = irq_count; | 954 | mpic->irq_count = irq_count; |
945 | mpic->num_sources = 0; /* so far */ | 955 | mpic->num_sources = 0; /* so far */ |
946 | 956 | ||
957 | if (flags & MPIC_LARGE_VECTORS) | ||
958 | intvec_top = 2047; | ||
959 | else | ||
960 | intvec_top = 255; | ||
961 | |||
962 | mpic->timer_vecs[0] = intvec_top - 8; | ||
963 | mpic->timer_vecs[1] = intvec_top - 7; | ||
964 | mpic->timer_vecs[2] = intvec_top - 6; | ||
965 | mpic->timer_vecs[3] = intvec_top - 5; | ||
966 | mpic->ipi_vecs[0] = intvec_top - 4; | ||
967 | mpic->ipi_vecs[1] = intvec_top - 3; | ||
968 | mpic->ipi_vecs[2] = intvec_top - 2; | ||
969 | mpic->ipi_vecs[3] = intvec_top - 1; | ||
970 | mpic->spurious_vec = intvec_top; | ||
971 | |||
947 | /* Check for "big-endian" in device-tree */ | 972 | /* Check for "big-endian" in device-tree */ |
948 | if (node && get_property(node, "big-endian", NULL) != NULL) | 973 | if (node && get_property(node, "big-endian", NULL) != NULL) |
949 | mpic->flags |= MPIC_BIG_ENDIAN; | 974 | mpic->flags |= MPIC_BIG_ENDIAN; |
@@ -1084,11 +1109,6 @@ void __init mpic_init(struct mpic *mpic) | |||
1084 | int i; | 1109 | int i; |
1085 | 1110 | ||
1086 | BUG_ON(mpic->num_sources == 0); | 1111 | BUG_ON(mpic->num_sources == 0); |
1087 | WARN_ON(mpic->num_sources > MPIC_VEC_IPI_0); | ||
1088 | |||
1089 | /* Sanitize source count */ | ||
1090 | if (mpic->num_sources > MPIC_VEC_IPI_0) | ||
1091 | mpic->num_sources = MPIC_VEC_IPI_0; | ||
1092 | 1112 | ||
1093 | printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); | 1113 | printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); |
1094 | 1114 | ||
@@ -1104,7 +1124,7 @@ void __init mpic_init(struct mpic *mpic) | |||
1104 | i * MPIC_INFO(TIMER_STRIDE) + | 1124 | i * MPIC_INFO(TIMER_STRIDE) + |
1105 | MPIC_INFO(TIMER_VECTOR_PRI), | 1125 | MPIC_INFO(TIMER_VECTOR_PRI), |
1106 | MPIC_VECPRI_MASK | | 1126 | MPIC_VECPRI_MASK | |
1107 | (MPIC_VEC_TIMER_0 + i)); | 1127 | (mpic->timer_vecs[0] + i)); |
1108 | } | 1128 | } |
1109 | 1129 | ||
1110 | /* Initialize IPIs to our reserved vectors and mark them disabled for now */ | 1130 | /* Initialize IPIs to our reserved vectors and mark them disabled for now */ |
@@ -1113,7 +1133,7 @@ void __init mpic_init(struct mpic *mpic) | |||
1113 | mpic_ipi_write(i, | 1133 | mpic_ipi_write(i, |
1114 | MPIC_VECPRI_MASK | | 1134 | MPIC_VECPRI_MASK | |
1115 | (10 << MPIC_VECPRI_PRIORITY_SHIFT) | | 1135 | (10 << MPIC_VECPRI_PRIORITY_SHIFT) | |
1116 | (MPIC_VEC_IPI_0 + i)); | 1136 | (mpic->ipi_vecs[0] + i)); |
1117 | } | 1137 | } |
1118 | 1138 | ||
1119 | /* Initialize interrupt sources */ | 1139 | /* Initialize interrupt sources */ |
@@ -1136,8 +1156,8 @@ void __init mpic_init(struct mpic *mpic) | |||
1136 | 1 << hard_smp_processor_id()); | 1156 | 1 << hard_smp_processor_id()); |
1137 | } | 1157 | } |
1138 | 1158 | ||
1139 | /* Init spurrious vector */ | 1159 | /* Init spurious vector */ |
1140 | mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS); | 1160 | mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec); |
1141 | 1161 | ||
1142 | /* Disable 8259 passthrough, if supported */ | 1162 | /* Disable 8259 passthrough, if supported */ |
1143 | if (!(mpic->flags & MPIC_NO_PTHROU_DIS)) | 1163 | if (!(mpic->flags & MPIC_NO_PTHROU_DIS)) |
@@ -1184,9 +1204,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri) | |||
1184 | 1204 | ||
1185 | spin_lock_irqsave(&mpic_lock, flags); | 1205 | spin_lock_irqsave(&mpic_lock, flags); |
1186 | if (is_ipi) { | 1206 | if (is_ipi) { |
1187 | reg = mpic_ipi_read(src - MPIC_VEC_IPI_0) & | 1207 | reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) & |
1188 | ~MPIC_VECPRI_PRIORITY_MASK; | 1208 | ~MPIC_VECPRI_PRIORITY_MASK; |
1189 | mpic_ipi_write(src - MPIC_VEC_IPI_0, | 1209 | mpic_ipi_write(src - mpic->ipi_vecs[0], |
1190 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); | 1210 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); |
1191 | } else { | 1211 | } else { |
1192 | reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) | 1212 | reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
@@ -1207,7 +1227,7 @@ unsigned int mpic_irq_get_priority(unsigned int irq) | |||
1207 | 1227 | ||
1208 | spin_lock_irqsave(&mpic_lock, flags); | 1228 | spin_lock_irqsave(&mpic_lock, flags); |
1209 | if (is_ipi) | 1229 | if (is_ipi) |
1210 | reg = mpic_ipi_read(src = MPIC_VEC_IPI_0); | 1230 | reg = mpic_ipi_read(src = mpic->ipi_vecs[0]); |
1211 | else | 1231 | else |
1212 | reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); | 1232 | reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); |
1213 | spin_unlock_irqrestore(&mpic_lock, flags); | 1233 | spin_unlock_irqrestore(&mpic_lock, flags); |
@@ -1313,7 +1333,7 @@ unsigned int mpic_get_one_irq(struct mpic *mpic) | |||
1313 | #ifdef DEBUG_LOW | 1333 | #ifdef DEBUG_LOW |
1314 | DBG("%s: get_one_irq(): %d\n", mpic->name, src); | 1334 | DBG("%s: get_one_irq(): %d\n", mpic->name, src); |
1315 | #endif | 1335 | #endif |
1316 | if (unlikely(src == MPIC_VEC_SPURRIOUS)) | 1336 | if (unlikely(src == mpic->spurious_vec)) |
1317 | return NO_IRQ; | 1337 | return NO_IRQ; |
1318 | return irq_linear_revmap(mpic->irqhost, src); | 1338 | return irq_linear_revmap(mpic->irqhost, src); |
1319 | } | 1339 | } |
@@ -1345,7 +1365,7 @@ void mpic_request_ipis(void) | |||
1345 | 1365 | ||
1346 | for (i = 0; i < 4; i++) { | 1366 | for (i = 0; i < 4; i++) { |
1347 | unsigned int vipi = irq_create_mapping(mpic->irqhost, | 1367 | unsigned int vipi = irq_create_mapping(mpic->irqhost, |
1348 | MPIC_VEC_IPI_0 + i); | 1368 | mpic->ipi_vecs[0] + i); |
1349 | if (vipi == NO_IRQ) { | 1369 | if (vipi == NO_IRQ) { |
1350 | printk(KERN_ERR "Failed to map IPI %d\n", i); | 1370 | printk(KERN_ERR "Failed to map IPI %d\n", i); |
1351 | break; | 1371 | break; |