Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Olof Johansson and committed by
Paul Mackerras
7df2457d 6529c13d

+55 -40
+3 -2
arch/powerpc/platforms/pasemi/setup.c
··· 130 130 openpic_addr = of_read_number(opprop, naddr); 131 131 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); 132 132 133 - mpic = mpic_alloc(mpic_node, openpic_addr, MPIC_PRIMARY, 0, 0, 134 - " PAS-OPIC "); 133 + mpic = mpic_alloc(mpic_node, openpic_addr, 134 + MPIC_PRIMARY|MPIC_LARGE_VECTORS, 135 + 0, 0, " PAS-OPIC "); 135 136 BUG_ON(!mpic); 136 137 137 138 mpic_assign_isu(mpic, 0, openpic_addr + 0x10000);
+43 -23
arch/powerpc/sysdev/mpic.c
··· 496 496 static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) 497 497 { 498 498 unsigned int src = mpic_irq_to_hw(irq); 499 + struct mpic *mpic; 499 500 500 501 if (irq < NUM_ISA_INTERRUPTS) 501 502 return NULL; 502 - if (is_ipi) 503 - *is_ipi = (src >= MPIC_VEC_IPI_0 && src <= MPIC_VEC_IPI_3); 504 503 505 - return irq_desc[irq].chip_data; 504 + mpic = irq_desc[irq].chip_data; 505 + 506 + if (is_ipi) 507 + *is_ipi = (src >= mpic->ipi_vecs[0] && 508 + src <= mpic->ipi_vecs[3]); 509 + 510 + return mpic; 506 511 } 507 512 508 513 /* Convert a cpu mask from logical to physical cpu numbers. */ ··· 545 540 #ifdef CONFIG_SMP 546 541 static irqreturn_t mpic_ipi_action(int irq, void *dev_id) 547 542 { 548 - smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0); 543 + struct mpic *mpic; 544 + 545 + mpic = mpic_find(irq, NULL); 546 + smp_message_recv(mpic_irq_to_hw(irq) - mpic->ipi_vecs[0]); 547 + 549 548 return IRQ_HANDLED; 550 549 } 551 550 #endif /* CONFIG_SMP */ ··· 672 663 static void mpic_unmask_ipi(unsigned int irq) 673 664 { 674 665 struct mpic *mpic = mpic_from_ipi(irq); 675 - unsigned int src = mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0; 666 + unsigned int src = mpic_irq_to_hw(irq) - mpic->ipi_vecs[0]; 676 667 677 668 DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); 678 669 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); ··· 816 807 817 808 DBG("mpic: map virq %d, hwirq 0x%lx\n", virq, hw); 818 809 819 - if (hw == MPIC_VEC_SPURRIOUS) 810 + if (hw == mpic->spurious_vec) 820 811 return -EINVAL; 821 812 822 813 #ifdef CONFIG_SMP 823 - else if (hw >= MPIC_VEC_IPI_0) { 814 + else if (hw >= mpic->ipi_vecs[0]) { 824 815 WARN_ON(!(mpic->flags & MPIC_PRIMARY)); 825 816 826 817 DBG("mpic: mapping as IPI\n"); ··· 913 904 u32 reg; 914 905 const char *vers; 915 906 int i; 907 + int intvec_top; 916 908 u64 paddr = phys_addr; 917 909 918 910 mpic = alloc_bootmem(sizeof(struct mpic)); ··· 924 914 mpic->name = name; 925 915 mpic->of_node = of_node_get(node); 926 916 927 - mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 256, 917 + mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, isu_size, 928 918 &mpic_host_ops, 929 - MPIC_VEC_SPURRIOUS); 919 + flags & MPIC_LARGE_VECTORS ? 2048 : 256); 930 920 if (mpic->irqhost == NULL) { 931 921 of_node_put(node); 932 922 return NULL; ··· 953 943 mpic->isu_size = isu_size; 954 944 mpic->irq_count = irq_count; 955 945 mpic->num_sources = 0; /* so far */ 946 + 947 + if (flags & MPIC_LARGE_VECTORS) 948 + intvec_top = 2047; 949 + else 950 + intvec_top = 255; 951 + 952 + mpic->timer_vecs[0] = intvec_top - 8; 953 + mpic->timer_vecs[1] = intvec_top - 7; 954 + mpic->timer_vecs[2] = intvec_top - 6; 955 + mpic->timer_vecs[3] = intvec_top - 5; 956 + mpic->ipi_vecs[0] = intvec_top - 4; 957 + mpic->ipi_vecs[1] = intvec_top - 3; 958 + mpic->ipi_vecs[2] = intvec_top - 2; 959 + mpic->ipi_vecs[3] = intvec_top - 1; 960 + mpic->spurious_vec = intvec_top; 956 961 957 962 /* Check for "big-endian" in device-tree */ 958 963 if (node && get_property(node, "big-endian", NULL) != NULL) ··· 1109 1084 int i; 1110 1085 1111 1086 BUG_ON(mpic->num_sources == 0); 1112 - WARN_ON(mpic->num_sources > MPIC_VEC_IPI_0); 1113 - 1114 - /* Sanitize source count */ 1115 - if (mpic->num_sources > MPIC_VEC_IPI_0) 1116 - mpic->num_sources = MPIC_VEC_IPI_0; 1117 1087 1118 1088 printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); 1119 1089 ··· 1124 1104 i * MPIC_INFO(TIMER_STRIDE) + 1125 1105 MPIC_INFO(TIMER_VECTOR_PRI), 1126 1106 MPIC_VECPRI_MASK | 1127 - (MPIC_VEC_TIMER_0 + i)); 1107 + (mpic->timer_vecs[0] + i)); 1128 1108 } 1129 1109 1130 1110 /* Initialize IPIs to our reserved vectors and mark them disabled for now */ ··· 1133 1113 mpic_ipi_write(i, 1134 1114 MPIC_VECPRI_MASK | 1135 1115 (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 1136 - (MPIC_VEC_IPI_0 + i)); 1116 + (mpic->ipi_vecs[0] + i)); 1137 1117 } 1138 1118 1139 1119 /* Initialize interrupt sources */ ··· 1156 1136 1 << hard_smp_processor_id()); 1157 1137 } 1158 1138 1159 - /* Init spurrious vector */ 1160 - mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS); 1139 + /* Init spurious vector */ 1140 + mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec); 1161 1141 1162 1142 /* Disable 8259 passthrough, if supported */ 1163 1143 if (!(mpic->flags & MPIC_NO_PTHROU_DIS)) ··· 1204 1184 1205 1185 spin_lock_irqsave(&mpic_lock, flags); 1206 1186 if (is_ipi) { 1207 - reg = mpic_ipi_read(src - MPIC_VEC_IPI_0) & 1187 + reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) & 1208 1188 ~MPIC_VECPRI_PRIORITY_MASK; 1209 - mpic_ipi_write(src - MPIC_VEC_IPI_0, 1189 + mpic_ipi_write(src - mpic->ipi_vecs[0], 1210 1190 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 1211 1191 } else { 1212 1192 reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) ··· 1227 1207 1228 1208 spin_lock_irqsave(&mpic_lock, flags); 1229 1209 if (is_ipi) 1230 - reg = mpic_ipi_read(src = MPIC_VEC_IPI_0); 1210 + reg = mpic_ipi_read(src = mpic->ipi_vecs[0]); 1231 1211 else 1232 1212 reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); 1233 1213 spin_unlock_irqrestore(&mpic_lock, flags); ··· 1333 1313 #ifdef DEBUG_LOW 1334 1314 DBG("%s: get_one_irq(): %d\n", mpic->name, src); 1335 1315 #endif 1336 - if (unlikely(src == MPIC_VEC_SPURRIOUS)) 1316 + if (unlikely(src == mpic->spurious_vec)) 1337 1317 return NO_IRQ; 1338 1318 return irq_linear_revmap(mpic->irqhost, src); 1339 1319 } ··· 1365 1345 1366 1346 for (i = 0; i < 4; i++) { 1367 1347 unsigned int vipi = irq_create_mapping(mpic->irqhost, 1368 - MPIC_VEC_IPI_0 + i); 1348 + mpic->ipi_vecs[0] + i); 1369 1349 if (vipi == NO_IRQ) { 1370 1350 printk(KERN_ERR "Failed to map IPI %d\n", i); 1371 1351 break;
+9 -15
include/asm-powerpc/mpic.h
··· 103 103 #define MPIC_MAX_ISU 32 104 104 105 105 /* 106 - * Special vector numbers (internal use only) 107 - */ 108 - #define MPIC_VEC_SPURRIOUS 255 109 - #define MPIC_VEC_IPI_3 254 110 - #define MPIC_VEC_IPI_2 253 111 - #define MPIC_VEC_IPI_1 252 112 - #define MPIC_VEC_IPI_0 251 113 - 114 - /* unused */ 115 - #define MPIC_VEC_TIMER_3 250 116 - #define MPIC_VEC_TIMER_2 249 117 - #define MPIC_VEC_TIMER_1 248 118 - #define MPIC_VEC_TIMER_0 247 119 - 120 - /* 121 106 * Tsi108 implementation of MPIC has many differences from the original one 122 107 */ 123 108 ··· 261 276 unsigned char *senses; 262 277 unsigned int senses_count; 263 278 279 + /* vector numbers used for internal sources (ipi/timers) */ 280 + unsigned int ipi_vecs[4]; 281 + unsigned int timer_vecs[4]; 282 + 283 + /* Spurious vector to program into unused sources */ 284 + unsigned int spurious_vec; 285 + 264 286 #ifdef CONFIG_MPIC_BROKEN_U3 265 287 /* The fixup table */ 266 288 struct mpic_irq_fixup *fixups; ··· 324 332 #define MPIC_NO_PTHROU_DIS 0x00000040 325 333 /* DCR based MPIC */ 326 334 #define MPIC_USES_DCR 0x00000080 335 + /* MPIC has 11-bit vector fields (or larger) */ 336 + #define MPIC_LARGE_VECTORS 0x00000100 327 337 328 338 /* MPIC HW modification ID */ 329 339 #define MPIC_REGSET_MASK 0xf0000000