aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2007-01-29 00:33:18 -0500
committerPaul Mackerras <paulus@samba.org>2007-02-06 22:03:19 -0500
commit7df2457db83bc922fcc8b462526b77f1ffe8c84b (patch)
tree7029d9e27b858e435c2fc4ce9a6d83a2b028e290 /arch/powerpc/sysdev/mpic.c
parent6529c13dfe413e437ad1ed0e97783dcf69137114 (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.c64
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)
496static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) 496static 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
541static irqreturn_t mpic_ipi_action(int irq, void *dev_id) 546static 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)
663static void mpic_unmask_ipi(unsigned int irq) 672static 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;