powerpc: MPIC: support more than 256 sources
PATCH 1/1 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.
arch/powerpc/sysdev/mpic.c +42 -22
@@ -496,13 +496,18 @@ static void __init mpic_scan_ht_pics(strstatic struct mpic *mpic_find (unsigned int irq,unsigned int *is_ipi) {unsigned int src =mpic_irq_to_hw (irq); +struct mpic *mpic;if (irq <NUM_ISA_INTERRUPTS )return NULL ; + + mpic = irq_desc[irq].chip_data; +if (is_ipi) - *is_ipi = (src >=MPIC_VEC_IPI_0 && src <=MPIC_VEC_IPI_3 ); + *is_ipi = (src >= mpic->ipi_vecs[0 ] && + src <= mpic->ipi_vecs[3 ]); -return irq_desc[irq].chip_data; +return mpic; }/* Convert a cpu mask from logical to physical cpu numbers. */
@@ -540,7 +545,11 @@ static inline void mpic_eoi(struct mpic#ifdef CONFIG_SMP static irqreturn_t mpic_ipi_action (int irq,void *dev_id) { -smp_message_recv (mpic_irq_to_hw (irq) -MPIC_VEC_IPI_0 ); +struct mpic *mpic; + + mpic =mpic_find (irq,NULL ); +smp_message_recv (mpic_irq_to_hw (irq) - mpic->ipi_vecs[0 ]); +return IRQ_HANDLED ; }#endif /* CONFIG_SMP */
@@ -663,7 +672,7 @@ static void mpic_end_ht_irq(unsigned intstatic void mpic_unmask_ipi (unsigned int irq) {struct mpic *mpic =mpic_from_ipi (irq); -unsigned int src =mpic_irq_to_hw (irq) -MPIC_VEC_IPI_0 ; +unsigned int src =mpic_irq_to_hw (irq) - mpic->ipi_vecs[0 ];DBG ("%s: enable_ipi: %d (ipi %d)\n" , mpic->name, irq, src);mpic_ipi_write (src,mpic_ipi_read (src) & ~MPIC_VECPRI_MASK );
@@ -807,11 +816,11 @@ static int mpic_host_map(struct irq_hostDBG ("mpic: map virq %d, hwirq 0x%lx\n" , virq, hw); -if (hw ==MPIC_VEC_SPURRIOUS ) +if (hw == mpic->spurious_vec)return -EINVAL ;#ifdef CONFIG_SMP - else if (hw >= MPIC_VEC_IPI_0) { + else if (hw >= mpic->ipi_vecs[0]) {WARN_ON (!(mpic->flags &MPIC_PRIMARY ));DBG ("mpic: mapping as IPI\n" );
@@ -904,6 +913,7 @@ struct mpic * __init mpic_alloc(struct du32 reg;const char *vers;int i; +int intvec_base;u64 paddr = phys_addr; mpic =alloc_bootmem (sizeof (struct mpic ));
@@ -914,9 +924,9 @@ struct mpic * __init mpic_alloc(struct d mpic->name = name; mpic->of_node =of_node_get (node); - mpic->irqhost =irq_alloc_host (IRQ_HOST_MAP_LINEAR ,256 , + mpic->irqhost =irq_alloc_host (IRQ_HOST_MAP_LINEAR , isu_size, &mpic_host_ops, -MPIC_VEC_SPURRIOUS ); + flags &MPIC_LARGE_VECTORS ?2048 :256 );if (mpic->irqhost ==NULL ) {of_node_put (node);return NULL ;
@@ -944,6 +954,21 @@ struct mpic * __init mpic_alloc(struct d mpic->irq_count = irq_count; mpic->num_sources =0 ;/* so far */ +if (flags &MPIC_LARGE_VECTORS ) + intvec_base =2039 ; +else + intvec_base =247 ; + + mpic->timer_vecs[0 ] = intvec_base; + mpic->timer_vecs[1 ] = intvec_base+1 ; + mpic->timer_vecs[2 ] = intvec_base+2 ; + mpic->timer_vecs[3 ] = intvec_base+3 ; + mpic->ipi_vecs[0 ] = intvec_base+4 ; + mpic->ipi_vecs[1 ] = intvec_base+5 ; + mpic->ipi_vecs[2 ] = intvec_base+6 ; + mpic->ipi_vecs[3 ] = intvec_base+7 ; + mpic->spurious_vec = intvec_base+8 ; +/* Check for "big-endian" in device-tree */ if (node &&get_property (node,"big-endian" ,NULL ) !=NULL ) mpic->flags |=MPIC_BIG_ENDIAN ;
@@ -1084,11 +1109,6 @@ void __init mpic_init(struct mpic *mpic)int i;BUG_ON (mpic->num_sources ==0 ); -WARN_ON (mpic->num_sources >MPIC_VEC_IPI_0 ); - -/* Sanitize source count */ -if (mpic->num_sources >MPIC_VEC_IPI_0 ) - mpic->num_sources =MPIC_VEC_IPI_0 ;printk (KERN_INFO "mpic: Initializing for %d sources\n" , mpic->num_sources);
@@ -1104,7 +1124,7 @@ void __init mpic_init(struct mpic *mpic) i *MPIC_INFO (TIMER_STRIDE ) +MPIC_INFO (TIMER_VECTOR_PRI ),MPIC_VECPRI_MASK | - (MPIC_VEC_TIMER_0 + i)); + (mpic->timer_vecs[0] + i)); }/* Initialize IPIs to our reserved vectors and mark them disabled for now */
@@ -1113,7 +1133,7 @@ void __init mpic_init(struct mpic *mpic)mpic_ipi_write (i,MPIC_VECPRI_MASK | (10 <<MPIC_VECPRI_PRIORITY_SHIFT ) | - (MPIC_VEC_IPI_0 + i)); + (mpic->ipi_vecs[0 ] + i)); }/* Initialize interrupt sources */
@@ -1136,8 +1156,8 @@ void __init mpic_init(struct mpic *mpic) 1 << hard_smp_processor_id()); } -/* Init spurrious vector */ -mpic_write (mpic->gregs,MPIC_INFO (GREG_SPURIOUS ),MPIC_VEC_SPURRIOUS ); +/* Init spurious vector */ +mpic_write (mpic->gregs,MPIC_INFO (GREG_SPURIOUS ), mpic->spurious_vec);/* Disable 8259 passthrough, if supported */ if (!(mpic->flags &MPIC_NO_PTHROU_DIS ))
@@ -1184,9 +1204,9 @@ void mpic_irq_set_priority(unsigned intspin_lock_irqsave (&mpic_lock, flags);if (is_ipi) { - reg =mpic_ipi_read (src -MPIC_VEC_IPI_0 ) & + reg =mpic_ipi_read (src - mpic->ipi_vecs[0 ]) & ~MPIC_VECPRI_PRIORITY_MASK ; -mpic_ipi_write (src -MPIC_VEC_IPI_0 , +mpic_ipi_write (src - mpic->ipi_vecs[0 ], reg | (pri <<MPIC_VECPRI_PRIORITY_SHIFT )); }else { reg =mpic_irq_read (src,MPIC_INFO (IRQ_VECTOR_PRI ))
@@ -1207,7 +1227,7 @@ unsigned int mpic_irq_get_priority(unsigspin_lock_irqsave (&mpic_lock, flags);if (is_ipi) - reg =mpic_ipi_read (src =MPIC_VEC_IPI_0 ); + reg =mpic_ipi_read (src = mpic->ipi_vecs[0 ]);else reg =mpic_irq_read (src,MPIC_INFO (IRQ_VECTOR_PRI ));spin_unlock_irqrestore (&mpic_lock, flags);
@@ -1313,7 +1333,7 @@ unsigned int mpic_get_one_irq(struct mpi#ifdef DEBUG_LOW DBG ("%s: get_one_irq(): %d\n" , mpic->name, src);#endif -if (unlikely (src ==MPIC_VEC_SPURRIOUS )) +if (unlikely (src == mpic->spurious_vec))return NO_IRQ ;return irq_linear_revmap (mpic->irqhost, src); }
@@ -1345,7 +1365,7 @@ void mpic_request_ipis(void)for (i =0 ; i <4 ; i++) {unsigned int vipi =irq_create_mapping (mpic->irqhost, -MPIC_VEC_IPI_0 + i); + mpic->ipi_vecs[0 ] + i);if (vipi ==NO_IRQ ) {printk (KERN_ERR "Failed to map IPI %d\n" , i);break ;
include/asm-powerpc/mpic.h +9 -15
@@ -103,21 +103,6 @@#define MPIC_MAX_ISU 32/* -* Special vector numbers (internal use only) -*/ -#define MPIC_VEC_SPURRIOUS 255 -#define MPIC_VEC_IPI_3 254 -#define MPIC_VEC_IPI_2 253 -#define MPIC_VEC_IPI_1 252 -#define MPIC_VEC_IPI_0 251 - -/* unused */ -#define MPIC_VEC_TIMER_3 250 -#define MPIC_VEC_TIMER_2 249 -#define MPIC_VEC_TIMER_1 248 -#define MPIC_VEC_TIMER_0 247 - -/* * Tsi108 implementation of MPIC has many differences from the original one */
@@ -276,6 +261,13 @@ struct mpicunsigned char *senses;unsigned int senses_count; +/* vector numbers used for internal sources (ipi/timers) */ +unsigned int ipi_vecs[4 ]; +unsigned int timer_vecs[4 ]; + +/* Spurious vector to program into unused sources */ +unsigned int spurious_vec; +#ifdef CONFIG_MPIC_BROKEN_U3 /* The fixup table */ struct mpic_irq_fixup *fixups;
@@ -332,6 +324,8 @@ struct mpic#define MPIC_NO_PTHROU_DIS 0x00000040/* DCR based MPIC */ #define MPIC_USES_DCR 0x00000080 +/* MPIC has 11-bit vector fields (or larger) */ +#define MPIC_LARGE_VECTORS 0x00000100/* MPIC HW modification ID */ #define MPIC_REGSET_MASK 0xf0000000
arch/powerpc/platforms/pasemi/setup.c +3 -2
@@ -130,8 +130,9 @@ static __init void pas_init_IRQ(void) openpic_addr =of_read_number (opprop, naddr);printk (KERN_DEBUG "OpenPIC addr: %lx\n" , openpic_addr); - mpic =mpic_alloc (mpic_node, openpic_addr,MPIC_PRIMARY ,0 ,0 , -" PAS-OPIC " ); + mpic =mpic_alloc (mpic_node, openpic_addr, +MPIC_PRIMARY |MPIC_LARGE_VECTORS , +0 ,0 ," PAS-OPIC " );BUG_ON (!mpic);mpic_assign_isu (mpic,0 , openpic_addr +0x10000 );
Why is this a flag and not just passed into mpic_alloc()? -JX
Quoted 268 lines · Olof Johansson
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 <[email protected]>Index:
powerpc/arch/powerpc/sysdev/mpic.c
===================================================================arch/powerpc/sysdev/mpic.c +34
-14@@ -496,13 +496,18 @@ static void __init mpic_scan_ht_pics(strstatic struct mpic *mpic_find (unsigned int irq,unsigned int *is_ipi) {unsigned int src =mpic_irq_to_hw (irq); +struct mpic *mpic;if (irq <NUM_ISA_INTERRUPTS )return NULL ; + + mpic = irq_desc[irq].chip_data; +if (is_ipi) - *is_ipi = (src >=MPIC_VEC_IPI_0 && src <=MPIC_VEC_IPI_3 ); + *is_ipi = (src >= mpic->ipi_vecs[0 ] && + src <= mpic->ipi_vecs[3 ]); -return irq_desc[irq].chip_data; +return mpic; }/* Convert a cpu mask from logical to physical cpu numbers. */ @@ -540,7 +545,11 @@ static inline void mpic_eoi(struct mpic#ifdef CONFIG_SMP static irqreturn_t mpic_ipi_action (int irq,void *dev_id) { -smp_message_recv (mpic_irq_to_hw (irq) -MPIC_VEC_IPI_0 ); +struct mpic *mpic; + + mpic =mpic_find (irq,NULL ); +smp_message_recv (mpic_irq_to_hw (irq) - mpic->ipi_vecs[0 ]); +return IRQ_HANDLED ; }#endif /* CONFIG_SMP */ @@ -663,7 +672,7 @@ static void mpic_end_ht_irq(unsigned intstatic void mpic_unmask_ipi (unsigned int irq) {struct mpic *mpic =mpic_from_ipi (irq); -unsigned int src =mpic_irq_to_hw (irq) -MPIC_VEC_IPI_0 ; +unsigned int src =mpic_irq_to_hw (irq) - mpic->ipi_vecs[0 ];DBG ("%s: enable_ipi: %d (ipi %d)\n" , mpic->name, irq, src);mpic_ipi_write (src,mpic_ipi_read (src) & ~MPIC_VECPRI_MASK );@@ -807,11 +816,11 @@ static int mpic_host_map(struct irq_hostDBG ("mpic: map virq %d, hwirq 0x%lx\n" , virq, hw); -if (hw ==MPIC_VEC_SPURRIOUS ) +if (hw == mpic->spurious_vec)return -EINVAL ;#ifdef CONFIG_SMP - else if (hw >= MPIC_VEC_IPI_0) { + else if (hw >= mpic->ipi_vecs[0]) {WARN_ON (!(mpic->flags &MPIC_PRIMARY ));DBG ("mpic: mapping as IPI\n" );@@ -904,6 +913,7 @@ struct mpic * __init mpic_alloc(struct du32 reg;const char *vers;int i; +int intvec_base;u64 paddr = phys_addr; mpic =alloc_bootmem (sizeof (struct mpic ));@@ -914,9 +924,9 @@ struct mpic * __init mpic_alloc(struct d mpic->name = name; mpic->of_node =of_node_get (node); - mpic->irqhost =irq_alloc_host (IRQ_HOST_MAP_LINEAR ,256 , + mpic->irqhost =irq_alloc_host (IRQ_HOST_MAP_LINEAR , isu_size, &mpic_host_ops, -MPIC_VEC_SPURRIOUS ); + flags &MPIC_LARGE_VECTORS ?2048 :256 );if (mpic->irqhost ==NULL ) {of_node_put (node);return NULL ;@@ -944,6 +954,21 @@ struct mpic * __init mpic_alloc(struct d mpic->irq_count = irq_count; mpic->num_sources =0 ;/* so far */ +if (flags &MPIC_LARGE_VECTORS ) + intvec_base =2039 ; +else + intvec_base =247 ; + + mpic->timer_vecs[0 ] = intvec_base; + mpic->timer_vecs[1 ] = intvec_base+1 ; + mpic->timer_vecs[2 ] = intvec_base+2 ; + mpic->timer_vecs[3 ] = intvec_base+3 ; + mpic->ipi_vecs[0 ] = intvec_base+4 ; + mpic->ipi_vecs[1 ] = intvec_base+5 ; + mpic->ipi_vecs[2 ] = intvec_base+6 ; + mpic->ipi_vecs[3 ] = intvec_base+7 ; + mpic->spurious_vec = intvec_base+8 ; +/* Check for "big-endian" in device-tree */ if (node &&get_property (node,"big-endian" ,NULL ) !=NULL ) mpic->flags |=MPIC_BIG_ENDIAN ;@@ -1084,11 +1109,6 @@ void __init mpic_init(struct mpic *mpic)int i;BUG_ON (mpic->num_sources ==0 ); -WARN_ON (mpic->num_sources >MPIC_VEC_IPI_0 ); - -/* Sanitize source count */ -if (mpic->num_sources >MPIC_VEC_IPI_0 ) - mpic->num_sources =MPIC_VEC_IPI_0 ;printk (KERN_INFO "mpic: Initializing for %d sources\n" , mpic- >num_sources);@@ -1104,7 +1124,7 @@ void __init mpic_init(struct mpic *mpic) i *MPIC_INFO (TIMER_STRIDE ) +MPIC_INFO (TIMER_VECTOR_PRI ),MPIC_VECPRI_MASK | - (MPIC_VEC_TIMER_0 + i)); + (mpic->timer_vecs[0] + i)); }/* Initialize IPIs to our reserved vectors and mark them disabled for now */
arch/powerpc/sysdev/mpic.c +3
-3@@ -1113,7 +1133,7 @@ void __init mpic_init(struct mpic *mpic)mpic_ipi_write (i,MPIC_VECPRI_MASK | (10 <<MPIC_VECPRI_PRIORITY_SHIFT ) | - (MPIC_VEC_IPI_0 + i)); + (mpic->ipi_vecs[0 ] + i)); }/* Initialize interrupt sources */ @@ -1136,8 +1156,8 @@ void __init mpic_init(struct mpic *mpic) 1 << hard_smp_processor_id()); } -/* Init spurrious vector */ -mpic_write (mpic->gregs,MPIC_INFO (GREG_SPURIOUS ), MPIC_VEC_SPURRIOUS); +/* Init spurious vector */ +mpic_write (mpic->gregs,MPIC_INFO (GREG_SPURIOUS ), mpic- >spurious_vec);arch/powerpc/sysdev/mpic.c +5
-5/* Disable 8259 passthrough, if supported */ if (!(mpic->flags &MPIC_NO_PTHROU_DIS ))@@ -1184,9 +1204,9 @@ void mpic_irq_set_priority(unsigned intspin_lock_irqsave (&mpic_lock, flags);if (is_ipi) { - reg =mpic_ipi_read (src -MPIC_VEC_IPI_0 ) & + reg =mpic_ipi_read (src - mpic->ipi_vecs[0 ]) & ~MPIC_VECPRI_PRIORITY_MASK ; -mpic_ipi_write (src -MPIC_VEC_IPI_0 , +mpic_ipi_write (src - mpic->ipi_vecs[0 ], reg | (pri <<MPIC_VECPRI_PRIORITY_SHIFT )); }else { reg =mpic_irq_read (src,MPIC_INFO (IRQ_VECTOR_PRI ))@@ -1207,7 +1227,7 @@ unsigned int mpic_irq_get_priority(unsigspin_lock_irqsave (&mpic_lock, flags);if (is_ipi) - reg =mpic_ipi_read (src =MPIC_VEC_IPI_0 ); + reg =mpic_ipi_read (src = mpic->ipi_vecs[0 ]);else reg =mpic_irq_read (src,MPIC_INFO (IRQ_VECTOR_PRI ));spin_unlock_irqrestore (&mpic_lock, flags);@@ -1313,7 +1333,7 @@ unsigned int mpic_get_one_irq(struct mpi#ifdef DEBUG_LOW DBG ("%s: get_one_irq(): %d\n" , mpic->name, src);#endif -if (unlikely (src ==MPIC_VEC_SPURRIOUS )) +if (unlikely (src == mpic->spurious_vec))return NO_IRQ ;return irq_linear_revmap (mpic->irqhost, src); }@@ -1345,7 +1365,7 @@ void mpic_request_ipis(void)for (i =0 ; i <4 ; i++) {unsigned int vipi =irq_create_mapping (mpic->irqhost, -MPIC_VEC_IPI_0 + i); + mpic->ipi_vecs[0 ] + i);if (vipi ==NO_IRQ ) {printk (KERN_ERR "Failed to map IPI %d\n" , i);break ;Index:
powerpc/include/asm-powerpc/mpic.h
===================================================================include/asm-powerpc/mpic.h +0
-15@@ -103,21 +103,6 @@#define MPIC_MAX_ISU 32/* -* Special vector numbers (internal use only) -*/ -#define MPIC_VEC_SPURRIOUS 255 -#define MPIC_VEC_IPI_3 254 -#define MPIC_VEC_IPI_2 253 -#define MPIC_VEC_IPI_1 252 -#define MPIC_VEC_IPI_0 251 - -/* unused */ -#define MPIC_VEC_TIMER_3 250 -#define MPIC_VEC_TIMER_2 249 -#define MPIC_VEC_TIMER_1 248 -#define MPIC_VEC_TIMER_0 247 - -/* * Tsi108 implementation of MPIC has many differences from the original one
*/include/asm-powerpc/mpic.h +9
-0@@ -276,6 +261,13 @@ struct mpicunsigned char *senses;unsigned int senses_count; +/* vector numbers used for internal sources (ipi/timers) */ +unsigned int ipi_vecs[4 ]; +unsigned int timer_vecs[4 ]; + +/* Spurious vector to program into unused sources */ +unsigned int spurious_vec; +#ifdef CONFIG_MPIC_BROKEN_U3 /* The fixup table */ struct mpic_irq_fixup *fixups;@@ -332,6 +324,8 @@ struct mpic#define MPIC_NO_PTHROU_DIS 0x00000040/* DCR based MPIC */ #define MPIC_USES_DCR 0x00000080 +/* MPIC has 11-bit vector fields (or larger) */ +#define MPIC_LARGE_VECTORS 0x00000100/* MPIC HW modification ID */ #define MPIC_REGSET_MASK 0xf0000000Index:
powerpc/arch/powerpc/platforms/pasemi/setup.c
===================================================================arch/powerpc/platforms/pasemi/setup.c +3
-2@@ -130,8 +130,9 @@ static __init void pas_init_IRQ(void) openpic_addr =of_read_number (opprop, naddr);printk (KERN_DEBUG "OpenPIC addr: %lx\n" , openpic_addr); - mpic =mpic_alloc (mpic_node, openpic_addr,MPIC_PRIMARY ,0 ,0 , -" PAS-OPIC " ); + mpic =mpic_alloc (mpic_node, openpic_addr, +MPIC_PRIMARY |MPIC_LARGE_VECTORS , +0 ,0 ," PAS-OPIC " );BUG_ON (!mpic);mpic_assign_isu (mpic,0 , openpic_addr +0x10000 );_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev
Quoted 1 line · Jimi Xenidis
Why is this a flag and not just passed into
mpic_alloc()?
I didn't want to make it automatic because the openpic specification says you only have to support 8-bit vectors. So if there's an implementation out there with 256 sources and only 8-bit vectors (and we put IPI/timers above 256), things will break instead of the uppermost sources just not being usable/valid.
If noone is worried about that, then I'm fine with doing it automatically instead.
-Olof
Quoted 100 lines · Olof Johansson
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 <[email protected]>Index:
powerpc/arch/powerpc/sysdev/mpic.c
===================================================================arch/powerpc/sysdev/mpic.c +22
-8@@ -496,13 +496,18 @@ static void __init mpic_scan_ht_pics(strstatic struct mpic *mpic_find (unsigned int irq,unsigned int *is_ipi) {unsigned int src =mpic_irq_to_hw (irq); +struct mpic *mpic;if (irq <NUM_ISA_INTERRUPTS )return NULL ; + + mpic = irq_desc[irq].chip_data; +if (is_ipi) - *is_ipi = (src >=MPIC_VEC_IPI_0 && src <=MPIC_VEC_IPI_3 ); + *is_ipi = (src >= mpic->ipi_vecs[0 ] && + src <= mpic->ipi_vecs[3 ]); -return irq_desc[irq].chip_data; +return mpic; }/* Convert a cpu mask from logical to physical cpu numbers. */ @@ -540,7 +545,11 @@ static inline void mpic_eoi(struct mpic#ifdef CONFIG_SMP static irqreturn_t mpic_ipi_action (int irq,void *dev_id) { -smp_message_recv (mpic_irq_to_hw (irq) -MPIC_VEC_IPI_0 ); +struct mpic *mpic; + + mpic =mpic_find (irq,NULL ); +smp_message_recv (mpic_irq_to_hw (irq) - mpic->ipi_vecs[0 ]); +return IRQ_HANDLED ; }#endif /* CONFIG_SMP */ @@ -663,7 +672,7 @@ static void mpic_end_ht_irq(unsigned intstatic void mpic_unmask_ipi (unsigned int irq) {struct mpic *mpic =mpic_from_ipi (irq); -unsigned int src =mpic_irq_to_hw (irq) -MPIC_VEC_IPI_0 ; +unsigned int src =mpic_irq_to_hw (irq) - mpic->ipi_vecs[0 ];DBG ("%s: enable_ipi: %d (ipi %d)\n" , mpic->name, irq, src);mpic_ipi_write (src,mpic_ipi_read (src) & ~MPIC_VECPRI_MASK );@@ -807,11 +816,11 @@ static int mpic_host_map(struct irq_hostDBG ("mpic: map virq %d, hwirq 0x%lx\n" , virq, hw); -if (hw ==MPIC_VEC_SPURRIOUS ) +if (hw == mpic->spurious_vec)return -EINVAL ;#ifdef CONFIG_SMP - else if (hw >= MPIC_VEC_IPI_0) { + else if (hw >= mpic->ipi_vecs[0]) {WARN_ON (!(mpic->flags &MPIC_PRIMARY ));DBG ("mpic: mapping as IPI\n" );@@ -904,6 +913,7 @@ struct mpic * __init mpic_alloc(struct du32 reg;const char *vers;int i; +int intvec_base;u64 paddr = phys_addr; mpic =alloc_bootmem (sizeof (struct mpic ));@@ -914,9 +924,9 @@ struct mpic * __init mpic_alloc(struct d mpic->name = name; mpic->of_node =of_node_get (node); - mpic->irqhost =irq_alloc_host (IRQ_HOST_MAP_LINEAR ,256 , + mpic->irqhost =irq_alloc_host (IRQ_HOST_MAP_LINEAR , isu_size, &mpic_host_ops, -MPIC_VEC_SPURRIOUS ); + flags &MPIC_LARGE_VECTORS ?2048 :256 );if (mpic->irqhost ==NULL ) {of_node_put (node);return NULL ;@@ -944,6 +954,21 @@ struct mpic * __init mpic_alloc(struct d mpic->irq_count = irq_count; mpic->num_sources =0 ;/* so far */ +if (flags &MPIC_LARGE_VECTORS ) + intvec_base =2039 ; +else + intvec_base =247 ;
arch/powerpc/sysdev/mpic.c struct mpic * __init mpic_alloc(struct d · line 970
Quoted 10 lines
arch/powerpc/sysdev/mpic.c +10
-0+ + mpic->timer_vecs[0 ] = intvec_base; + mpic->timer_vecs[1 ] = intvec_base+1 ; + mpic->timer_vecs[2 ] = intvec_base+2 ; + mpic->timer_vecs[3 ] = intvec_base+3 ; + mpic->ipi_vecs[0 ] = intvec_base+4 ; + mpic->ipi_vecs[1 ] = intvec_base+5 ; + mpic->ipi_vecs[2 ] = intvec_base+6 ; + mpic->ipi_vecs[3 ] = intvec_base+7 ; + mpic->spurious_vec = intvec_base+8 ;
It took me a minute to work out where 2039 and 247 came from, it might be clearer as:
+ if (flags & MPIC_LARGE_VECTORS)
+ intvec_top = 2047;
+ else
+ intvec_top = 255;
+
+ mpic->timer_vecs[0] = intvec_top - 8;
+ mpic->timer_vecs[1] = intvec_top - 7;
+ mpic->timer_vecs[2] = intvec_top - 6;
+ mpic->timer_vecs[3] = intvec_top - 5;
+ mpic->ipi_vecs[0] = intvec_top - 4; + mpic->ipi_vecs[1] = intvec_top - 3; + mpic->ipi_vecs[2] = intvec_top - 2; + mpic->ipi_vecs[3] = intvec_top - 1; + mpic->spurious_vec = intvec_top;
Better still, can you get 255/2047 as (num_sources - 1) or something?
cheers
Signature · 8 lines
Michael Ellerman OzLabs, IBM Australia Development Lab wwweb: http://michael.ellerman.id.au phone: +61 2 6212 1183 (tie line 70 21183) We do not inherit the earth from our ancestors, we borrow it from our children. - S.M.A.R.T Person
Quoted 2 lines · Michael Ellerman
It took me a minute to work out where 2039 and 247 came from, it might be clearer as:
[..]
Yep, that's a good idea. Thanks.
Quoted 1 line
Better still, can you get 255/2047 as (
num_sources- 1) or something?
Unfortunately, num_sources has nothing to do with supported vector space, and it would really have to be num_sources+7, this possibly overrunning the available range, hardware-wise (instead of just losing the topmost sources to the software uses).
I'll repost the patch with the change above together with the rest of the series.
-Olof
PATCH v2 1/1 powerpc: MPIC: support more than 256 sources
In reply to Olof JohanssonAllow 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.
arch/powerpc/sysdev/mpic.c +42 -22
@@ -496,13 +496,18 @@ static void __init mpic_scan_ht_pics(strstatic struct mpic *mpic_find (unsigned int irq,unsigned int *is_ipi) {unsigned int src =mpic_irq_to_hw (irq); +struct mpic *mpic;if (irq <NUM_ISA_INTERRUPTS )return NULL ; + + mpic = irq_desc[irq].chip_data; +if (is_ipi) - *is_ipi = (src >=MPIC_VEC_IPI_0 && src <=MPIC_VEC_IPI_3 ); + *is_ipi = (src >= mpic->ipi_vecs[0 ] && + src <= mpic->ipi_vecs[3 ]); -return irq_desc[irq].chip_data; +return mpic; }/* Convert a cpu mask from logical to physical cpu numbers. */
@@ -540,7 +545,11 @@ static inline void mpic_eoi(struct mpic#ifdef CONFIG_SMP static irqreturn_t mpic_ipi_action (int irq,void *dev_id) { -smp_message_recv (mpic_irq_to_hw (irq) -MPIC_VEC_IPI_0 ); +struct mpic *mpic; + + mpic =mpic_find (irq,NULL ); +smp_message_recv (mpic_irq_to_hw (irq) - mpic->ipi_vecs[0 ]); +return IRQ_HANDLED ; }#endif /* CONFIG_SMP */
@@ -663,7 +672,7 @@ static void mpic_end_ht_irq(unsigned intstatic void mpic_unmask_ipi (unsigned int irq) {struct mpic *mpic =mpic_from_ipi (irq); -unsigned int src =mpic_irq_to_hw (irq) -MPIC_VEC_IPI_0 ; +unsigned int src =mpic_irq_to_hw (irq) - mpic->ipi_vecs[0 ];DBG ("%s: enable_ipi: %d (ipi %d)\n" , mpic->name, irq, src);mpic_ipi_write (src,mpic_ipi_read (src) & ~MPIC_VECPRI_MASK );
@@ -807,11 +816,11 @@ static int mpic_host_map(struct irq_hostDBG ("mpic: map virq %d, hwirq 0x%lx\n" , virq, hw); -if (hw ==MPIC_VEC_SPURRIOUS ) +if (hw == mpic->spurious_vec)return -EINVAL ;#ifdef CONFIG_SMP - else if (hw >= MPIC_VEC_IPI_0) { + else if (hw >= mpic->ipi_vecs[0]) {WARN_ON (!(mpic->flags &MPIC_PRIMARY ));DBG ("mpic: mapping as IPI\n" );
@@ -904,6 +913,7 @@ struct mpic * __init mpic_alloc(struct du32 reg;const char *vers;int i; +int intvec_top;u64 paddr = phys_addr; mpic =alloc_bootmem (sizeof (struct mpic ));
@@ -914,9 +924,9 @@ struct mpic * __init mpic_alloc(struct d mpic->name = name; mpic->of_node = node ?of_node_get (node) :NULL ; - mpic->irqhost =irq_alloc_host (IRQ_HOST_MAP_LINEAR ,256 , + mpic->irqhost =irq_alloc_host (IRQ_HOST_MAP_LINEAR , isu_size, &mpic_host_ops, -MPIC_VEC_SPURRIOUS ); + flags &MPIC_LARGE_VECTORS ?2048 :256 );if (mpic->irqhost ==NULL ) {of_node_put (node);return NULL ;
@@ -944,6 +954,21 @@ struct mpic * __init mpic_alloc(struct d mpic->irq_count = irq_count; mpic->num_sources =0 ;/* so far */ +if (flags &MPIC_LARGE_VECTORS ) + intvec_top =2047 ; +else + intvec_top =255 ; + + mpic->timer_vecs[0 ] = intvec_top -8 ; + mpic->timer_vecs[1 ] = intvec_top -7 ; + mpic->timer_vecs[2 ] = intvec_top -6 ; + mpic->timer_vecs[3 ] = intvec_top -5 ; + mpic->ipi_vecs[0 ] = intvec_top -4 ; + mpic->ipi_vecs[1 ] = intvec_top -3 ; + mpic->ipi_vecs[2 ] = intvec_top -2 ; + mpic->ipi_vecs[3 ] = intvec_top -1 ; + mpic->spurious_vec = intvec_top; +/* Check for "big-endian" in device-tree */ if (node &&get_property (node,"big-endian" ,NULL ) !=NULL ) mpic->flags |=MPIC_BIG_ENDIAN ;
@@ -1084,11 +1109,6 @@ void __init mpic_init(struct mpic *mpic)int i;BUG_ON (mpic->num_sources ==0 ); -WARN_ON (mpic->num_sources >MPIC_VEC_IPI_0 ); - -/* Sanitize source count */ -if (mpic->num_sources >MPIC_VEC_IPI_0 ) - mpic->num_sources =MPIC_VEC_IPI_0 ;printk (KERN_INFO "mpic: Initializing for %d sources\n" , mpic->num_sources);
@@ -1104,7 +1124,7 @@ void __init mpic_init(struct mpic *mpic) i *MPIC_INFO (TIMER_STRIDE ) +MPIC_INFO (TIMER_VECTOR_PRI ),MPIC_VECPRI_MASK | - (MPIC_VEC_TIMER_0 + i)); + (mpic->timer_vecs[0] + i)); }/* Initialize IPIs to our reserved vectors and mark them disabled for now */
@@ -1113,7 +1133,7 @@ void __init mpic_init(struct mpic *mpic)mpic_ipi_write (i,MPIC_VECPRI_MASK | (10 <<MPIC_VECPRI_PRIORITY_SHIFT ) | - (MPIC_VEC_IPI_0 + i)); + (mpic->ipi_vecs[0 ] + i)); }/* Initialize interrupt sources */
@@ -1136,8 +1156,8 @@ void __init mpic_init(struct mpic *mpic) 1 << hard_smp_processor_id()); } -/* Init spurrious vector */ -mpic_write (mpic->gregs,MPIC_INFO (GREG_SPURIOUS ),MPIC_VEC_SPURRIOUS ); +/* Init spurious vector */ +mpic_write (mpic->gregs,MPIC_INFO (GREG_SPURIOUS ), mpic->spurious_vec);/* Disable 8259 passthrough, if supported */ if (!(mpic->flags &MPIC_NO_PTHROU_DIS ))
@@ -1184,9 +1204,9 @@ void mpic_irq_set_priority(unsigned intspin_lock_irqsave (&mpic_lock, flags);if (is_ipi) { - reg =mpic_ipi_read (src -MPIC_VEC_IPI_0 ) & + reg =mpic_ipi_read (src - mpic->ipi_vecs[0 ]) & ~MPIC_VECPRI_PRIORITY_MASK ; -mpic_ipi_write (src -MPIC_VEC_IPI_0 , +mpic_ipi_write (src - mpic->ipi_vecs[0 ], reg | (pri <<MPIC_VECPRI_PRIORITY_SHIFT )); }else { reg =mpic_irq_read (src,MPIC_INFO (IRQ_VECTOR_PRI ))
@@ -1207,7 +1227,7 @@ unsigned int mpic_irq_get_priority(unsigspin_lock_irqsave (&mpic_lock, flags);if (is_ipi) - reg =mpic_ipi_read (src =MPIC_VEC_IPI_0 ); + reg =mpic_ipi_read (src = mpic->ipi_vecs[0 ]);else reg =mpic_irq_read (src,MPIC_INFO (IRQ_VECTOR_PRI ));spin_unlock_irqrestore (&mpic_lock, flags);
@@ -1313,7 +1333,7 @@ unsigned int mpic_get_one_irq(struct mpi#ifdef DEBUG_LOW DBG ("%s: get_one_irq(): %d\n" , mpic->name, src);#endif -if (unlikely (src ==MPIC_VEC_SPURRIOUS )) +if (unlikely (src == mpic->spurious_vec))return NO_IRQ ;return irq_linear_revmap (mpic->irqhost, src); }
@@ -1345,7 +1365,7 @@ void mpic_request_ipis(void)for (i =0 ; i <4 ; i++) {unsigned int vipi =irq_create_mapping (mpic->irqhost, -MPIC_VEC_IPI_0 + i); + mpic->ipi_vecs[0 ] + i);if (vipi ==NO_IRQ ) {printk (KERN_ERR "Failed to map IPI %d\n" , i);break ;
include/asm-powerpc/mpic.h +9 -15
@@ -103,21 +103,6 @@#define MPIC_MAX_ISU 32/* -* Special vector numbers (internal use only) -*/ -#define MPIC_VEC_SPURRIOUS 255 -#define MPIC_VEC_IPI_3 254 -#define MPIC_VEC_IPI_2 253 -#define MPIC_VEC_IPI_1 252 -#define MPIC_VEC_IPI_0 251 - -/* unused */ -#define MPIC_VEC_TIMER_3 250 -#define MPIC_VEC_TIMER_2 249 -#define MPIC_VEC_TIMER_1 248 -#define MPIC_VEC_TIMER_0 247 - -/* * Tsi108 implementation of MPIC has many differences from the original one */
@@ -276,6 +261,13 @@ struct mpicunsigned char *senses;unsigned int senses_count; +/* vector numbers used for internal sources (ipi/timers) */ +unsigned int ipi_vecs[4 ]; +unsigned int timer_vecs[4 ]; + +/* Spurious vector to program into unused sources */ +unsigned int spurious_vec; +#ifdef CONFIG_MPIC_BROKEN_U3 /* The fixup table */ struct mpic_irq_fixup *fixups;
@@ -332,6 +324,8 @@ struct mpic#define MPIC_NO_PTHROU_DIS 0x00000040/* DCR based MPIC */ #define MPIC_USES_DCR 0x00000080 +/* MPIC has 11-bit vector fields (or larger) */ +#define MPIC_LARGE_VECTORS 0x00000100/* MPIC HW modification ID */ #define MPIC_REGSET_MASK 0xf0000000
arch/powerpc/platforms/pasemi/setup.c +3 -2
@@ -130,8 +130,9 @@ static __init void pas_init_IRQ(void) openpic_addr =of_read_number (opprop, naddr);printk (KERN_DEBUG "OpenPIC addr: %lx\n" , openpic_addr); - mpic =mpic_alloc (mpic_node, openpic_addr,MPIC_PRIMARY ,0 ,0 , -" PAS-OPIC " ); + mpic =mpic_alloc (mpic_node, openpic_addr, +MPIC_PRIMARY |MPIC_LARGE_VECTORS , +0 ,0 ," PAS-OPIC " );BUG_ON (!mpic);mpic_assign_isu (mpic,0 , openpic_addr +0x10000 );
Quoted 23 lines · Olof Johansson
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 <[email protected]>Index:
merge/arch/powerpc/sysdev/mpic.c
===================================================================arch/powerpc/sysdev/mpic.c +4
-0@@ -944,6 +954,21 @@ struct mpic * __init mpic_alloc(struct d mpic->irq_count = irq_count; mpic->num_sources =0 ;/* so far */ +if (flags &MPIC_LARGE_VECTORS ) + intvec_top =2047 ; +else + intvec_top =255 ;
arch/powerpc/sysdev/mpic.c struct mpic * __init mpic_alloc(struct d · line 970
Quoted 10 lines
arch/powerpc/sysdev/mpic.c +10
-0+ + mpic->timer_vecs[0 ] = intvec_top -8 ; + mpic->timer_vecs[1 ] = intvec_top -7 ; + mpic->timer_vecs[2 ] = intvec_top -6 ; + mpic->timer_vecs[3 ] = intvec_top -5 ; + mpic->ipi_vecs[0 ] = intvec_top -4 ; + mpic->ipi_vecs[1 ] = intvec_top -3 ; + mpic->ipi_vecs[2 ] = intvec_top -2 ; + mpic->ipi_vecs[3 ] = intvec_top -1 ; + mpic->spurious_vec = intvec_top;
I like it :)
cheers
Signature · 8 lines
Michael Ellerman OzLabs, IBM Australia Development Lab wwweb: http://michael.ellerman.id.au phone: +61 2 6212 1183 (tie line 70 21183) We do not inherit the earth from our ancestors, we borrow it from our children. - S.M.A.R.T Person