diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 | 
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 | 
| commit | 5e66dd6d66ffe758b39b6dcadf2330753ee1159b (patch) | |
| tree | a72cdcff4448e4af9425cc213ddf56ab23e697fe /arch/powerpc/sysdev/mpic.c | |
| parent | 026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (diff) | |
| parent | ca78f6baca863afe2e6a244a0fe94b3a70211d46 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 482 | 
1 files changed, 292 insertions, 190 deletions
| diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 7e469358895f..7d31d7cc392d 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -100,8 +100,8 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)  	if (mpic->flags & MPIC_PRIMARY)  		cpu = hard_smp_processor_id(); - -	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg); +	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, +			  mpic->cpuregs[cpu], reg);  }  static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) @@ -340,27 +340,19 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)  #endif /* CONFIG_MPIC_BROKEN_U3 */ +#define mpic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq) +  /* Find an mpic associated with a given linux interrupt */  static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)  { -	struct mpic *mpic = mpics; - -	while(mpic) { -		/* search IPIs first since they may override the main interrupts */ -		if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) { -			if (is_ipi) -				*is_ipi = 1; -			return mpic; -		} -		if (irq >= mpic->irq_offset && -		    irq < (mpic->irq_offset + mpic->irq_count)) { -			if (is_ipi) -				*is_ipi = 0; -			return mpic; -		} -		mpic = mpic -> next; -	} -	return NULL; +	unsigned int src = mpic_irq_to_hw(irq); + +	if (irq < NUM_ISA_INTERRUPTS) +		return NULL; +	if (is_ipi) +		*is_ipi = (src >= MPIC_VEC_IPI_0 && src <= MPIC_VEC_IPI_3); + +	return irq_desc[irq].chip_data;  }  /* Convert a cpu mask from logical to physical cpu numbers. */ @@ -378,14 +370,14 @@ static inline u32 mpic_physmask(u32 cpumask)  /* Get the mpic structure from the IPI number */  static inline struct mpic * mpic_from_ipi(unsigned int ipi)  { -	return container_of(irq_desc[ipi].chip, struct mpic, hc_ipi); +	return irq_desc[ipi].chip_data;  }  #endif  /* Get the mpic structure from the irq number */  static inline struct mpic * mpic_from_irq(unsigned int irq)  { -	return container_of(irq_desc[irq].chip, struct mpic, hc_irq); +	return irq_desc[irq].chip_data;  }  /* Send an EOI */ @@ -398,9 +390,7 @@ static inline void mpic_eoi(struct mpic *mpic)  #ifdef CONFIG_SMP  static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)  { -	struct mpic *mpic = dev_id; - -	smp_message_recv(irq - mpic->ipi_offset, regs); +	smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0, regs);  	return IRQ_HANDLED;  }  #endif /* CONFIG_SMP */ @@ -410,11 +400,11 @@ static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)   */ -static void mpic_enable_irq(unsigned int irq) +static void mpic_unmask_irq(unsigned int irq)  {  	unsigned int loops = 100000;  	struct mpic *mpic = mpic_from_irq(irq); -	unsigned int src = irq - mpic->irq_offset; +	unsigned int src = mpic_irq_to_hw(irq);  	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); @@ -429,39 +419,13 @@ static void mpic_enable_irq(unsigned int irq)  			break;  		}  	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);	 - -#ifdef CONFIG_MPIC_BROKEN_U3 -	if (mpic->flags & MPIC_BROKEN_U3) { -		unsigned int src = irq - mpic->irq_offset; -		if (mpic_is_ht_interrupt(mpic, src) && -		    (irq_desc[irq].status & IRQ_LEVEL)) -			mpic_ht_end_irq(mpic, src); -	} -#endif /* CONFIG_MPIC_BROKEN_U3 */ -} - -static unsigned int mpic_startup_irq(unsigned int irq) -{ -#ifdef CONFIG_MPIC_BROKEN_U3 -	struct mpic *mpic = mpic_from_irq(irq); -	unsigned int src = irq - mpic->irq_offset; -#endif /* CONFIG_MPIC_BROKEN_U3 */ - -	mpic_enable_irq(irq); - -#ifdef CONFIG_MPIC_BROKEN_U3 -	if (mpic_is_ht_interrupt(mpic, src)) -		mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); -#endif /* CONFIG_MPIC_BROKEN_U3 */ - -	return 0;  } -static void mpic_disable_irq(unsigned int irq) +static void mpic_mask_irq(unsigned int irq)  {  	unsigned int loops = 100000;  	struct mpic *mpic = mpic_from_irq(irq); -	unsigned int src = irq - mpic->irq_offset; +	unsigned int src = mpic_irq_to_hw(irq);  	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); @@ -478,23 +442,58 @@ static void mpic_disable_irq(unsigned int irq)  	} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));  } -static void mpic_shutdown_irq(unsigned int irq) +static void mpic_end_irq(unsigned int irq)  { +	struct mpic *mpic = mpic_from_irq(irq); + +#ifdef DEBUG_IRQ +	DBG("%s: end_irq: %d\n", mpic->name, irq); +#endif +	/* We always EOI on end_irq() even for edge interrupts since that +	 * should only lower the priority, the MPIC should have properly +	 * latched another edge interrupt coming in anyway +	 */ + +	mpic_eoi(mpic); +} +  #ifdef CONFIG_MPIC_BROKEN_U3 + +static void mpic_unmask_ht_irq(unsigned int irq) +{  	struct mpic *mpic = mpic_from_irq(irq); -	unsigned int src = irq - mpic->irq_offset; +	unsigned int src = mpic_irq_to_hw(irq); -	if (mpic_is_ht_interrupt(mpic, src)) -		mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); +	mpic_unmask_irq(irq); -#endif /* CONFIG_MPIC_BROKEN_U3 */ +	if (irq_desc[irq].status & IRQ_LEVEL) +		mpic_ht_end_irq(mpic, src); +} + +static unsigned int mpic_startup_ht_irq(unsigned int irq) +{ +	struct mpic *mpic = mpic_from_irq(irq); +	unsigned int src = mpic_irq_to_hw(irq); + +	mpic_unmask_irq(irq); +	mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); -	mpic_disable_irq(irq); +	return 0;  } -static void mpic_end_irq(unsigned int irq) +static void mpic_shutdown_ht_irq(unsigned int irq)  {  	struct mpic *mpic = mpic_from_irq(irq); +	unsigned int src = mpic_irq_to_hw(irq); + +	mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); +	mpic_mask_irq(irq); +} + +static void mpic_end_ht_irq(unsigned int irq) +{ +	struct mpic *mpic = mpic_from_irq(irq); +	unsigned int src = mpic_irq_to_hw(irq);  #ifdef DEBUG_IRQ  	DBG("%s: end_irq: %d\n", mpic->name, irq); @@ -504,30 +503,25 @@ static void mpic_end_irq(unsigned int irq)  	 * latched another edge interrupt coming in anyway  	 */ -#ifdef CONFIG_MPIC_BROKEN_U3 -	if (mpic->flags & MPIC_BROKEN_U3) { -		unsigned int src = irq - mpic->irq_offset; -		if (mpic_is_ht_interrupt(mpic, src) && -		    (irq_desc[irq].status & IRQ_LEVEL)) -			mpic_ht_end_irq(mpic, src); -	} -#endif /* CONFIG_MPIC_BROKEN_U3 */ - +	if (irq_desc[irq].status & IRQ_LEVEL) +		mpic_ht_end_irq(mpic, src);  	mpic_eoi(mpic);  } +#endif /* CONFIG_MPIC_BROKEN_U3 */ +  #ifdef CONFIG_SMP -static void mpic_enable_ipi(unsigned int irq) +static void mpic_unmask_ipi(unsigned int irq)  {  	struct mpic *mpic = mpic_from_ipi(irq); -	unsigned int src = irq - mpic->ipi_offset; +	unsigned int src = mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0;  	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);  	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);  } -static void mpic_disable_ipi(unsigned int irq) +static void mpic_mask_ipi(unsigned int irq)  {  	/* NEVER disable an IPI... that's just plain wrong! */  } @@ -551,29 +545,176 @@ static void mpic_end_ipi(unsigned int irq)  static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)  {  	struct mpic *mpic = mpic_from_irq(irq); +	unsigned int src = mpic_irq_to_hw(irq);  	cpumask_t tmp;  	cpus_and(tmp, cpumask, cpu_online_map); -	mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION, +	mpic_irq_write(src, MPIC_IRQ_DESTINATION,  		       mpic_physmask(cpus_addr(tmp)[0]));	  } +static unsigned int mpic_flags_to_vecpri(unsigned int flags, int *level) +{ +	unsigned int vecpri; + +	/* Now convert sense value */ +	switch(flags & IRQ_TYPE_SENSE_MASK) { +	case IRQ_TYPE_EDGE_RISING: +		vecpri = MPIC_VECPRI_SENSE_EDGE | +			MPIC_VECPRI_POLARITY_POSITIVE; +		*level = 0; +		break; +	case IRQ_TYPE_EDGE_FALLING: +		vecpri = MPIC_VECPRI_SENSE_EDGE | +			MPIC_VECPRI_POLARITY_NEGATIVE; +		*level = 0; +		break; +	case IRQ_TYPE_LEVEL_HIGH: +		vecpri = MPIC_VECPRI_SENSE_LEVEL | +			MPIC_VECPRI_POLARITY_POSITIVE; +		*level = 1; +		break; +	case IRQ_TYPE_LEVEL_LOW: +	default: +		vecpri = MPIC_VECPRI_SENSE_LEVEL | +			MPIC_VECPRI_POLARITY_NEGATIVE; +		*level = 1; +	} +	return vecpri; +} + +static struct irq_chip mpic_irq_chip = { +	.mask	= mpic_mask_irq, +	.unmask	= mpic_unmask_irq, +	.eoi	= mpic_end_irq, +}; + +#ifdef CONFIG_SMP +static struct irq_chip mpic_ipi_chip = { +	.mask	= mpic_mask_ipi, +	.unmask	= mpic_unmask_ipi, +	.eoi	= mpic_end_ipi, +}; +#endif /* CONFIG_SMP */ + +#ifdef CONFIG_MPIC_BROKEN_U3 +static struct irq_chip mpic_irq_ht_chip = { +	.startup	= mpic_startup_ht_irq, +	.shutdown	= mpic_shutdown_ht_irq, +	.mask		= mpic_mask_irq, +	.unmask		= mpic_unmask_ht_irq, +	.eoi		= mpic_end_ht_irq, +}; +#endif /* CONFIG_MPIC_BROKEN_U3 */ + + +static int mpic_host_match(struct irq_host *h, struct device_node *node) +{ +	struct mpic *mpic = h->host_data; + +	/* Exact match, unless mpic node is NULL */ +	return mpic->of_node == NULL || mpic->of_node == node; +} + +static int mpic_host_map(struct irq_host *h, unsigned int virq, +			 irq_hw_number_t hw, unsigned int flags) +{ +	struct irq_desc *desc = get_irq_desc(virq); +	struct irq_chip *chip; +	struct mpic *mpic = h->host_data; +	unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL | +		MPIC_VECPRI_POLARITY_NEGATIVE; +	int level; + +	pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n", +		 virq, hw, flags); + +	if (hw == MPIC_VEC_SPURRIOUS) +		return -EINVAL; +#ifdef CONFIG_SMP +	else if (hw >= MPIC_VEC_IPI_0) { +		WARN_ON(!(mpic->flags & MPIC_PRIMARY)); + +		pr_debug("mpic: mapping as IPI\n"); +		set_irq_chip_data(virq, mpic); +		set_irq_chip_and_handler(virq, &mpic->hc_ipi, +					 handle_percpu_irq); +		return 0; +	} +#endif /* CONFIG_SMP */ + +	if (hw >= mpic->irq_count) +		return -EINVAL; + +	/* If no sense provided, check default sense array */ +	if (((flags & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE) && +	    mpic->senses && hw < mpic->senses_count) +		flags |= mpic->senses[hw]; + +	vecpri = mpic_flags_to_vecpri(flags, &level); +	if (level) +		desc->status |= IRQ_LEVEL; +	chip = &mpic->hc_irq; + +#ifdef CONFIG_MPIC_BROKEN_U3 +	/* Check for HT interrupts, override vecpri */ +	if (mpic_is_ht_interrupt(mpic, hw)) { +		vecpri &= ~(MPIC_VECPRI_SENSE_MASK | +			    MPIC_VECPRI_POLARITY_MASK); +		vecpri |= MPIC_VECPRI_POLARITY_POSITIVE; +		chip = &mpic->hc_ht_irq; +	} +#endif + +	/* Reconfigure irq */ +	vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT); +	mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri); + +	pr_debug("mpic: mapping as IRQ\n"); + +	set_irq_chip_data(virq, mpic); +	set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq); +	return 0; +} + +static int mpic_host_xlate(struct irq_host *h, struct device_node *ct, +			   u32 *intspec, unsigned int intsize, +			   irq_hw_number_t *out_hwirq, unsigned int *out_flags) + +{ +	static unsigned char map_mpic_senses[4] = { +		IRQ_TYPE_EDGE_RISING, +		IRQ_TYPE_LEVEL_LOW, +		IRQ_TYPE_LEVEL_HIGH, +		IRQ_TYPE_EDGE_FALLING, +	}; + +	*out_hwirq = intspec[0]; +	if (intsize > 1 && intspec[1] < 4) +		*out_flags = map_mpic_senses[intspec[1]]; +	else +		*out_flags = IRQ_TYPE_NONE; + +	return 0; +} + +static struct irq_host_ops mpic_host_ops = { +	.match = mpic_host_match, +	.map = mpic_host_map, +	.xlate = mpic_host_xlate, +};  /*   * Exported functions   */ - -struct mpic * __init mpic_alloc(unsigned long phys_addr, +struct mpic * __init mpic_alloc(struct device_node *node, +				unsigned long phys_addr,  				unsigned int flags,  				unsigned int isu_size, -				unsigned int irq_offset,  				unsigned int irq_count, -				unsigned int ipi_offset, -				unsigned char *senses, -				unsigned int senses_count,  				const char *name)  {  	struct mpic	*mpic; @@ -585,33 +726,38 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,  	if (mpic == NULL)  		return NULL; -  	memset(mpic, 0, sizeof(struct mpic));  	mpic->name = name; +	mpic->of_node = node ? of_node_get(node) : NULL; +	mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 256, +				       &mpic_host_ops, +				       MPIC_VEC_SPURRIOUS); +	if (mpic->irqhost == NULL) { +		of_node_put(node); +		return NULL; +	} + +	mpic->irqhost->host_data = mpic; +	mpic->hc_irq = mpic_irq_chip;  	mpic->hc_irq.typename = name; -	mpic->hc_irq.startup = mpic_startup_irq; -	mpic->hc_irq.shutdown = mpic_shutdown_irq; -	mpic->hc_irq.enable = mpic_enable_irq; -	mpic->hc_irq.disable = mpic_disable_irq; -	mpic->hc_irq.end = mpic_end_irq;  	if (flags & MPIC_PRIMARY)  		mpic->hc_irq.set_affinity = mpic_set_affinity; +#ifdef CONFIG_MPIC_BROKEN_U3 +	mpic->hc_ht_irq = mpic_irq_ht_chip; +	mpic->hc_ht_irq.typename = name; +	if (flags & MPIC_PRIMARY) +		mpic->hc_ht_irq.set_affinity = mpic_set_affinity; +#endif /* CONFIG_MPIC_BROKEN_U3 */  #ifdef CONFIG_SMP +	mpic->hc_ipi = mpic_ipi_chip;  	mpic->hc_ipi.typename = name; -	mpic->hc_ipi.enable = mpic_enable_ipi; -	mpic->hc_ipi.disable = mpic_disable_ipi; -	mpic->hc_ipi.end = mpic_end_ipi;  #endif /* CONFIG_SMP */  	mpic->flags = flags;  	mpic->isu_size = isu_size; -	mpic->irq_offset = irq_offset;  	mpic->irq_count = irq_count; -	mpic->ipi_offset = ipi_offset;  	mpic->num_sources = 0; /* so far */ -	mpic->senses = senses; -	mpic->senses_count = senses_count;  	/* Map the global registers */  	mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); @@ -679,8 +825,10 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,  	mpic->next = mpics;  	mpics = mpic; -	if (flags & MPIC_PRIMARY) +	if (flags & MPIC_PRIMARY) {  		mpic_primary = mpic; +		irq_set_default_host(mpic->irqhost); +	}  	return mpic;  } @@ -697,26 +845,10 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,  		mpic->num_sources = isu_first + mpic->isu_size;  } -void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler, -			       void *data) +void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)  { -	struct mpic *mpic = mpic_find(irq, NULL); -	unsigned long flags; - -	/* Synchronization here is a bit dodgy, so don't try to replace cascade -	 * interrupts on the fly too often ... but normally it's set up at boot. -	 */ -	spin_lock_irqsave(&mpic_lock, flags); -	if (mpic->cascade)	        -		mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset); -	mpic->cascade = NULL; -	wmb(); -	mpic->cascade_vec = irq - mpic->irq_offset; -	mpic->cascade_data = data; -	wmb(); -	mpic->cascade = handler; -	mpic_enable_irq(irq); -	spin_unlock_irqrestore(&mpic_lock, flags); +	mpic->senses = senses; +	mpic->senses_count = count;  }  void __init mpic_init(struct mpic *mpic) @@ -724,6 +856,11 @@ 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); @@ -747,12 +884,6 @@ void __init mpic_init(struct mpic *mpic)  			       MPIC_VECPRI_MASK |  			       (10 << MPIC_VECPRI_PRIORITY_SHIFT) |  			       (MPIC_VEC_IPI_0 + i)); -#ifdef CONFIG_SMP -		if (!(mpic->flags & MPIC_PRIMARY)) -			continue; -		irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU; -		irq_desc[mpic->ipi_offset+i].chip = &mpic->hc_ipi; -#endif /* CONFIG_SMP */  	}  	/* Initialize interrupt sources */ @@ -763,31 +894,21 @@ void __init mpic_init(struct mpic *mpic)  	/* Do the HT PIC fixups on U3 broken mpic */  	DBG("MPIC flags: %x\n", mpic->flags);  	if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) -		mpic_scan_ht_pics(mpic); + 		mpic_scan_ht_pics(mpic);  #endif /* CONFIG_MPIC_BROKEN_U3 */  	for (i = 0; i < mpic->num_sources; i++) {  		/* start with vector = source number, and masked */  		u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT); -		int level = 0; +		int level = 1; -		/* if it's an IPI, we skip it */ -		if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) && -		    (mpic->irq_offset + i) <  (mpic->ipi_offset + i + 4)) -			continue; -  		/* do senses munging */ -		if (mpic->senses && i < mpic->senses_count) { -			if (mpic->senses[i] & IRQ_SENSE_LEVEL) -				vecpri |= MPIC_VECPRI_SENSE_LEVEL; -			if (mpic->senses[i] & IRQ_POLARITY_POSITIVE) -				vecpri |= MPIC_VECPRI_POLARITY_POSITIVE; -		} else +		if (mpic->senses && i < mpic->senses_count) +			vecpri = mpic_flags_to_vecpri(mpic->senses[i], +						      &level); +		else  			vecpri |= MPIC_VECPRI_SENSE_LEVEL; -		/* remember if it was a level interrupts */ -		level = (vecpri & MPIC_VECPRI_SENSE_LEVEL); -  		/* deal with broken U3 */  		if (mpic->flags & MPIC_BROKEN_U3) {  #ifdef CONFIG_MPIC_BROKEN_U3 @@ -808,12 +929,6 @@ void __init mpic_init(struct mpic *mpic)  		mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);  		mpic_irq_write(i, MPIC_IRQ_DESTINATION,  			       1 << hard_smp_processor_id()); - -		/* init linux descriptors */ -		if (i < mpic->irq_count) { -			irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0; -			irq_desc[mpic->irq_offset+i].chip = &mpic->hc_irq; -		}  	}  	/* Init spurrious vector */ @@ -854,19 +969,20 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)  {  	int is_ipi;  	struct mpic *mpic = mpic_find(irq, &is_ipi); +	unsigned int src = mpic_irq_to_hw(irq);  	unsigned long flags;  	u32 reg;  	spin_lock_irqsave(&mpic_lock, flags);  	if (is_ipi) { -		reg = mpic_ipi_read(irq - mpic->ipi_offset) & +		reg = mpic_ipi_read(src - MPIC_VEC_IPI_0) &  			~MPIC_VECPRI_PRIORITY_MASK; -		mpic_ipi_write(irq - mpic->ipi_offset, +		mpic_ipi_write(src - MPIC_VEC_IPI_0,  			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));  	} else { -		reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI) +		reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI)  			& ~MPIC_VECPRI_PRIORITY_MASK; -		mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI, +		mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,  			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));  	}  	spin_unlock_irqrestore(&mpic_lock, flags); @@ -876,14 +992,15 @@ unsigned int mpic_irq_get_priority(unsigned int irq)  {  	int is_ipi;  	struct mpic *mpic = mpic_find(irq, &is_ipi); +	unsigned int src = mpic_irq_to_hw(irq);  	unsigned long flags;  	u32 reg;  	spin_lock_irqsave(&mpic_lock, flags);  	if (is_ipi) -		reg = mpic_ipi_read(irq - mpic->ipi_offset); +		reg = mpic_ipi_read(src = MPIC_VEC_IPI_0);  	else -		reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI); +		reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);  	spin_unlock_irqrestore(&mpic_lock, flags);  	return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;  } @@ -978,37 +1095,20 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)  		       mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));  } -int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) +unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)  { -	u32 irq; +	u32 src; -	irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; +	src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;  #ifdef DEBUG_LOW -	DBG("%s: get_one_irq(): %d\n", mpic->name, irq); +	DBG("%s: get_one_irq(): %d\n", mpic->name, src);  #endif -	if (mpic->cascade && irq == mpic->cascade_vec) { -#ifdef DEBUG_LOW -		DBG("%s: cascading ...\n", mpic->name); -#endif -		irq = mpic->cascade(regs, mpic->cascade_data); -		mpic_eoi(mpic); -		return irq; -	} -	if (unlikely(irq == MPIC_VEC_SPURRIOUS)) -		return -1; -	if (irq < MPIC_VEC_IPI_0) { -#ifdef DEBUG_IRQ -		DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset); -#endif -		return irq + mpic->irq_offset; -	} -#ifdef DEBUG_IPI -       	DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0); -#endif -	return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset; +	if (unlikely(src == MPIC_VEC_SPURRIOUS)) +		return NO_IRQ; +	return irq_linear_revmap(mpic->irqhost, src);  } -int mpic_get_irq(struct pt_regs *regs) +unsigned int mpic_get_irq(struct pt_regs *regs)  {  	struct mpic *mpic = mpic_primary; @@ -1022,25 +1122,27 @@ int mpic_get_irq(struct pt_regs *regs)  void mpic_request_ipis(void)  {  	struct mpic *mpic = mpic_primary; - +	int i; +	static char *ipi_names[] = { +		"IPI0 (call function)", +		"IPI1 (reschedule)", +		"IPI2 (unused)", +		"IPI3 (debugger break)", +	};  	BUG_ON(mpic == NULL); -	 -	printk("requesting IPIs ... \n"); -	/* -	 * IPIs are marked IRQF_DISABLED as they must run with irqs -	 * disabled -	 */ -	request_irq(mpic->ipi_offset+0, mpic_ipi_action, IRQF_DISABLED, -		    "IPI0 (call function)", mpic); -	request_irq(mpic->ipi_offset+1, mpic_ipi_action, IRQF_DISABLED, -		   "IPI1 (reschedule)", mpic); -	request_irq(mpic->ipi_offset+2, mpic_ipi_action, IRQF_DISABLED, -		   "IPI2 (unused)", mpic); -	request_irq(mpic->ipi_offset+3, mpic_ipi_action, IRQF_DISABLED, -		   "IPI3 (debugger break)", mpic); - -	printk("IPIs requested... \n"); +	printk(KERN_INFO "mpic: requesting IPIs ... \n"); + +	for (i = 0; i < 4; i++) { +		unsigned int vipi = irq_create_mapping(mpic->irqhost, +						       MPIC_VEC_IPI_0 + i, 0); +		if (vipi == NO_IRQ) { +			printk(KERN_ERR "Failed to map IPI %d\n", i); +			break; +		} +		request_irq(vipi, mpic_ipi_action, IRQF_DISABLED, +			    ipi_names[i], mpic); +	}  }  void smp_mpic_message_pass(int target, int msg) | 
