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 | |
| 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')
| -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; |
