LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] of_mmc_spi: add card detect irq support
From: Grant Likely @ 2011-03-08  3:52 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: David Brownell, Esben Haabendal, linux-mmc, David Brownell,
	Andrew Morton, linuxppc-dev
In-Reply-To: <20101228160526.GA20087@oksana.dev.rtsoft.ru>

On Tue, Dec 28, 2010 at 07:05:26PM +0300, Anton Vorontsov wrote:
> On Mon, Aug 30, 2010 at 11:49:08AM -0600, Grant Likely wrote:
> > On Mon, Aug 30, 2010 at 10:38 AM, David Brownell <david-b@pacbell.net> wrote:
> > > Since I don't do OpenFirmware, let's hear from
> > > Grant on this one.
> > 
> > Looks good to me.
> > 
> > Acked-by: Grant Likely <grant.likely@secretlab.ca>
> 
> I wonder what happened with this patch?

Merged, thanks.  :-)

g.

^ permalink raw reply

* Re: [PATCH 01/28] powerpc: mpic irq_data conversion.
From: Grant Likely @ 2011-03-08  4:13 UTC (permalink / raw)
  To: Lennert Buytenhek; +Cc: Thomas Gleixner, linuxppc-dev, Stephen Rothwell
In-Reply-To: <20110307235902.GF16649@mail.wantstofly.org>

On Tue, Mar 08, 2011 at 12:59:02AM +0100, Lennert Buytenhek wrote:
> Signed-off-by: Lennert Buytenhek <buytenh@secretlab.ca>

Hi Lennert,

I'm taking a look over now and running some build testing.

However, this needs a wider audience for review before it gets merged.
Can you please repost and cc: benh, sfr, tglx, and linux-kernel?

Thanks,
g.

> ---
>  arch/powerpc/include/asm/mpic.h       |    6 +-
>  arch/powerpc/platforms/pasemi/setup.c |    4 +-
>  arch/powerpc/sysdev/mpic.c            |  131 +++++++++++++++++----------------
>  arch/powerpc/sysdev/mpic.h            |    5 +-
>  arch/powerpc/sysdev/mpic_pasemi_msi.c |   18 ++--
>  arch/powerpc/sysdev/mpic_u3msi.c      |   18 ++--
>  6 files changed, 92 insertions(+), 90 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
> index e000cce..946ec49 100644
> --- a/arch/powerpc/include/asm/mpic.h
> +++ b/arch/powerpc/include/asm/mpic.h
> @@ -467,11 +467,11 @@ extern void mpic_request_ipis(void);
>  void smp_mpic_message_pass(int target, int msg);
>  
>  /* Unmask a specific virq */
> -extern void mpic_unmask_irq(unsigned int irq);
> +extern void mpic_unmask_irq(struct irq_data *d);
>  /* Mask a specific virq */
> -extern void mpic_mask_irq(unsigned int irq);
> +extern void mpic_mask_irq(struct irq_data *d);
>  /* EOI a specific virq */
> -extern void mpic_end_irq(unsigned int irq);
> +extern void mpic_end_irq(struct irq_data *d);
>  
>  /* Fetch interrupt from a given mpic */
>  extern unsigned int mpic_get_one_irq(struct mpic *mpic);
> diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
> index f372ec1..a6067b3 100644
> --- a/arch/powerpc/platforms/pasemi/setup.c
> +++ b/arch/powerpc/platforms/pasemi/setup.c
> @@ -240,7 +240,7 @@ static __init void pas_init_IRQ(void)
>  		nmi_virq = irq_create_mapping(NULL, *nmiprop);
>  		mpic_irq_set_priority(nmi_virq, 15);
>  		set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
> -		mpic_unmask_irq(nmi_virq);
> +		mpic_unmask_irq(irq_get_irq_data(nmi_virq));
>  	}
>  
>  	of_node_put(mpic_node);
> @@ -266,7 +266,7 @@ static int pas_machine_check_handler(struct pt_regs *regs)
>  	if (nmi_virq != NO_IRQ && mpic_get_mcirq() == nmi_virq) {
>  		printk(KERN_ERR "NMI delivered\n");
>  		debugger(regs);
> -		mpic_end_irq(nmi_virq);
> +		mpic_end_irq(irq_get_irq_data(nmi_virq));
>  		goto out;
>  	}
>  
> diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
> index b0c8469..95712f6 100644
> --- a/arch/powerpc/sysdev/mpic.c
> +++ b/arch/powerpc/sysdev/mpic.c
> @@ -611,7 +611,7 @@ static struct mpic *mpic_find(unsigned int irq)
>  	if (irq < NUM_ISA_INTERRUPTS)
>  		return NULL;
>  
> -	return irq_to_desc(irq)->chip_data;
> +	return get_irq_chip_data(irq);
>  }
>  
>  /* Determine if the linux irq is an IPI */
> @@ -636,16 +636,16 @@ static inline u32 mpic_physmask(u32 cpumask)
>  
>  #ifdef CONFIG_SMP
>  /* Get the mpic structure from the IPI number */
> -static inline struct mpic * mpic_from_ipi(unsigned int ipi)
> +static inline struct mpic * mpic_from_ipi(struct irq_data *d)
>  {
> -	return irq_to_desc(ipi)->chip_data;
> +	return irq_data_get_irq_chip_data(d);
>  }
>  #endif
>  
>  /* Get the mpic structure from the irq number */
>  static inline struct mpic * mpic_from_irq(unsigned int irq)
>  {
> -	return irq_to_desc(irq)->chip_data;
> +	return get_irq_chip_data(irq);
>  }
>  
>  /* Send an EOI */
> @@ -660,13 +660,13 @@ static inline void mpic_eoi(struct mpic *mpic)
>   */
>  
>  
> -void mpic_unmask_irq(unsigned int irq)
> +void mpic_unmask_irq(struct irq_data *d)
>  {
>  	unsigned int loops = 100000;
> -	struct mpic *mpic = mpic_from_irq(irq);
> -	unsigned int src = mpic_irq_to_hw(irq);
> +	struct mpic *mpic = mpic_from_irq(d->irq);
> +	unsigned int src = mpic_irq_to_hw(d->irq);
>  
> -	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
> +	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src);
>  
>  	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
>  		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
> @@ -681,13 +681,13 @@ void mpic_unmask_irq(unsigned int irq)
>  	} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
>  }
>  
> -void mpic_mask_irq(unsigned int irq)
> +void mpic_mask_irq(struct irq_data *d)
>  {
>  	unsigned int loops = 100000;
> -	struct mpic *mpic = mpic_from_irq(irq);
> -	unsigned int src = mpic_irq_to_hw(irq);
> +	struct mpic *mpic = mpic_from_irq(d->irq);
> +	unsigned int src = mpic_irq_to_hw(d->irq);
>  
> -	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
> +	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src);
>  
>  	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
>  		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
> @@ -703,12 +703,12 @@ void mpic_mask_irq(unsigned int irq)
>  	} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
>  }
>  
> -void mpic_end_irq(unsigned int irq)
> +void mpic_end_irq(struct irq_data *d)
>  {
> -	struct mpic *mpic = mpic_from_irq(irq);
> +	struct mpic *mpic = mpic_from_irq(d->irq);
>  
>  #ifdef DEBUG_IRQ
> -	DBG("%s: end_irq: %d\n", mpic->name, irq);
> +	DBG("%s: end_irq: %d\n", mpic->name, d->irq);
>  #endif
>  	/* We always EOI on end_irq() even for edge interrupts since that
>  	 * should only lower the priority, the MPIC should have properly
> @@ -720,51 +720,51 @@ void mpic_end_irq(unsigned int irq)
>  
>  #ifdef CONFIG_MPIC_U3_HT_IRQS
>  
> -static void mpic_unmask_ht_irq(unsigned int irq)
> +static void mpic_unmask_ht_irq(struct irq_data *d)
>  {
> -	struct mpic *mpic = mpic_from_irq(irq);
> -	unsigned int src = mpic_irq_to_hw(irq);
> +	struct mpic *mpic = mpic_from_irq(d->irq);
> +	unsigned int src = mpic_irq_to_hw(d->irq);
>  
> -	mpic_unmask_irq(irq);
> +	mpic_unmask_irq(d);
>  
> -	if (irq_to_desc(irq)->status & IRQ_LEVEL)
> +	if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
>  		mpic_ht_end_irq(mpic, src);
>  }
>  
> -static unsigned int mpic_startup_ht_irq(unsigned int irq)
> +static unsigned int mpic_startup_ht_irq(struct irq_data *d)
>  {
> -	struct mpic *mpic = mpic_from_irq(irq);
> -	unsigned int src = mpic_irq_to_hw(irq);
> +	struct mpic *mpic = mpic_from_irq(d->irq);
> +	unsigned int src = mpic_irq_to_hw(d->irq);
>  
> -	mpic_unmask_irq(irq);
> -	mpic_startup_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
> +	mpic_unmask_irq(d);
> +	mpic_startup_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
>  
>  	return 0;
>  }
>  
> -static void mpic_shutdown_ht_irq(unsigned int irq)
> +static void mpic_shutdown_ht_irq(struct irq_data *d)
>  {
> -	struct mpic *mpic = mpic_from_irq(irq);
> -	unsigned int src = mpic_irq_to_hw(irq);
> +	struct mpic *mpic = mpic_from_irq(d->irq);
> +	unsigned int src = mpic_irq_to_hw(d->irq);
>  
> -	mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
> -	mpic_mask_irq(irq);
> +	mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
> +	mpic_mask_irq(d);
>  }
>  
> -static void mpic_end_ht_irq(unsigned int irq)
> +static void mpic_end_ht_irq(struct irq_data *d)
>  {
> -	struct mpic *mpic = mpic_from_irq(irq);
> -	unsigned int src = mpic_irq_to_hw(irq);
> +	struct mpic *mpic = mpic_from_irq(d->irq);
> +	unsigned int src = mpic_irq_to_hw(d->irq);
>  
>  #ifdef DEBUG_IRQ
> -	DBG("%s: end_irq: %d\n", mpic->name, irq);
> +	DBG("%s: end_irq: %d\n", mpic->name, d->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
>  	 */
>  
> -	if (irq_to_desc(irq)->status & IRQ_LEVEL)
> +	if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
>  		mpic_ht_end_irq(mpic, src);
>  	mpic_eoi(mpic);
>  }
> @@ -772,23 +772,23 @@ static void mpic_end_ht_irq(unsigned int irq)
>  
>  #ifdef CONFIG_SMP
>  
> -static void mpic_unmask_ipi(unsigned int irq)
> +static void mpic_unmask_ipi(struct irq_data *d)
>  {
> -	struct mpic *mpic = mpic_from_ipi(irq);
> -	unsigned int src = mpic_irq_to_hw(irq) - mpic->ipi_vecs[0];
> +	struct mpic *mpic = mpic_from_ipi(d);
> +	unsigned int src = mpic_irq_to_hw(d->irq) - mpic->ipi_vecs[0];
>  
> -	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
> +	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
>  	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
>  }
>  
> -static void mpic_mask_ipi(unsigned int irq)
> +static void mpic_mask_ipi(struct irq_data *d)
>  {
>  	/* NEVER disable an IPI... that's just plain wrong! */
>  }
>  
> -static void mpic_end_ipi(unsigned int irq)
> +static void mpic_end_ipi(struct irq_data *d)
>  {
> -	struct mpic *mpic = mpic_from_ipi(irq);
> +	struct mpic *mpic = mpic_from_ipi(d);
>  
>  	/*
>  	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
> @@ -802,10 +802,11 @@ static void mpic_end_ipi(unsigned int irq)
>  
>  #endif /* CONFIG_SMP */
>  
> -int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
> +int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
> +		      bool force)
>  {
> -	struct mpic *mpic = mpic_from_irq(irq);
> -	unsigned int src = mpic_irq_to_hw(irq);
> +	struct mpic *mpic = mpic_from_irq(d->irq);
> +	unsigned int src = mpic_irq_to_hw(d->irq);
>  
>  	if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
>  		int cpuid = irq_choose_cpu(cpumask);
> @@ -848,15 +849,15 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
>  	}
>  }
>  
> -int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
> +int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
>  {
> -	struct mpic *mpic = mpic_from_irq(virq);
> -	unsigned int src = mpic_irq_to_hw(virq);
> -	struct irq_desc *desc = irq_to_desc(virq);
> +	struct mpic *mpic = mpic_from_irq(d->irq);
> +	unsigned int src = mpic_irq_to_hw(d->irq);
> +	struct irq_desc *desc = irq_to_desc(d->irq);
>  	unsigned int vecpri, vold, vnew;
>  
>  	DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
> -	    mpic, virq, src, flow_type);
> +	    mpic, d->irq, src, flow_type);
>  
>  	if (src >= mpic->irq_count)
>  		return -EINVAL;
> @@ -907,28 +908,28 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
>  }
>  
>  static struct irq_chip mpic_irq_chip = {
> -	.mask		= mpic_mask_irq,
> -	.unmask		= mpic_unmask_irq,
> -	.eoi		= mpic_end_irq,
> -	.set_type	= mpic_set_irq_type,
> +	.irq_mask	= mpic_mask_irq,
> +	.irq_unmask	= mpic_unmask_irq,
> +	.irq_eoi	= mpic_end_irq,
> +	.irq_set_type	= mpic_set_irq_type,
>  };
>  
>  #ifdef CONFIG_SMP
>  static struct irq_chip mpic_ipi_chip = {
> -	.mask		= mpic_mask_ipi,
> -	.unmask		= mpic_unmask_ipi,
> -	.eoi		= mpic_end_ipi,
> +	.irq_mask	= mpic_mask_ipi,
> +	.irq_unmask	= mpic_unmask_ipi,
> +	.irq_eoi	= mpic_end_ipi,
>  };
>  #endif /* CONFIG_SMP */
>  
>  #ifdef CONFIG_MPIC_U3_HT_IRQS
>  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,
> -	.set_type	= mpic_set_irq_type,
> +	.irq_startup	= mpic_startup_ht_irq,
> +	.irq_shutdown	= mpic_shutdown_ht_irq,
> +	.irq_mask	= mpic_mask_irq,
> +	.irq_unmask	= mpic_unmask_ht_irq,
> +	.irq_eoi	= mpic_end_ht_irq,
> +	.irq_set_type	= mpic_set_irq_type,
>  };
>  #endif /* CONFIG_MPIC_U3_HT_IRQS */
>  
> @@ -1060,12 +1061,12 @@ struct mpic * __init mpic_alloc(struct device_node *node,
>  	mpic->hc_irq = mpic_irq_chip;
>  	mpic->hc_irq.name = name;
>  	if (flags & MPIC_PRIMARY)
> -		mpic->hc_irq.set_affinity = mpic_set_affinity;
> +		mpic->hc_irq.irq_set_affinity = mpic_set_affinity;
>  #ifdef CONFIG_MPIC_U3_HT_IRQS
>  	mpic->hc_ht_irq = mpic_irq_ht_chip;
>  	mpic->hc_ht_irq.name = name;
>  	if (flags & MPIC_PRIMARY)
> -		mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
> +		mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity;
>  #endif /* CONFIG_MPIC_U3_HT_IRQS */
>  
>  #ifdef CONFIG_SMP
> diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
> index e4a6df7..13f3e89 100644
> --- a/arch/powerpc/sysdev/mpic.h
> +++ b/arch/powerpc/sysdev/mpic.h
> @@ -34,9 +34,10 @@ static inline int mpic_pasemi_msi_init(struct mpic *mpic)
>  }
>  #endif
>  
> -extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
> +extern int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type);
>  extern void mpic_set_vector(unsigned int virq, unsigned int vector);
> -extern int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
> +extern int mpic_set_affinity(struct irq_data *d,
> +			     const struct cpumask *cpumask, bool force);
>  extern void mpic_reset_core(int cpu);
>  
>  #endif /* _POWERPC_SYSDEV_MPIC_H */
> diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
> index 320ad5a..0b7794a 100644
> --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
> +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
> @@ -43,24 +43,24 @@ static void mpic_pasemi_msi_mask_irq(struct irq_data *data)
>  {
>  	pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq);
>  	mask_msi_irq(data);
> -	mpic_mask_irq(data->irq);
> +	mpic_mask_irq(data);
>  }
>  
>  static void mpic_pasemi_msi_unmask_irq(struct irq_data *data)
>  {
>  	pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq);
> -	mpic_unmask_irq(data->irq);
> +	mpic_unmask_irq(data);
>  	unmask_msi_irq(data);
>  }
>  
>  static struct irq_chip mpic_pasemi_msi_chip = {
> -	.irq_shutdown	= mpic_pasemi_msi_mask_irq,
> -	.irq_mask	= mpic_pasemi_msi_mask_irq,
> -	.irq_unmask	= mpic_pasemi_msi_unmask_irq,
> -	.eoi		= mpic_end_irq,
> -	.set_type	= mpic_set_irq_type,
> -	.set_affinity	= mpic_set_affinity,
> -	.name		= "PASEMI-MSI",
> +	.irq_shutdown		= mpic_pasemi_msi_mask_irq,
> +	.irq_mask		= mpic_pasemi_msi_mask_irq,
> +	.irq_unmask		= mpic_pasemi_msi_unmask_irq,
> +	.irq_eoi		= mpic_end_irq,
> +	.irq_set_type		= mpic_set_irq_type,
> +	.irq_set_affinity	= mpic_set_affinity,
> +	.name			= "PASEMI-MSI",
>  };
>  
>  static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
> diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
> index a2b028b..71900ac 100644
> --- a/arch/powerpc/sysdev/mpic_u3msi.c
> +++ b/arch/powerpc/sysdev/mpic_u3msi.c
> @@ -26,23 +26,23 @@ static struct mpic *msi_mpic;
>  static void mpic_u3msi_mask_irq(struct irq_data *data)
>  {
>  	mask_msi_irq(data);
> -	mpic_mask_irq(data->irq);
> +	mpic_mask_irq(data);
>  }
>  
>  static void mpic_u3msi_unmask_irq(struct irq_data *data)
>  {
> -	mpic_unmask_irq(data->irq);
> +	mpic_unmask_irq(data);
>  	unmask_msi_irq(data);
>  }
>  
>  static struct irq_chip mpic_u3msi_chip = {
> -	.irq_shutdown	= mpic_u3msi_mask_irq,
> -	.irq_mask	= mpic_u3msi_mask_irq,
> -	.irq_unmask	= mpic_u3msi_unmask_irq,
> -	.eoi		= mpic_end_irq,
> -	.set_type	= mpic_set_irq_type,
> -	.set_affinity	= mpic_set_affinity,
> -	.name		= "MPIC-U3MSI",
> +	.irq_shutdown		= mpic_u3msi_mask_irq,
> +	.irq_mask		= mpic_u3msi_mask_irq,
> +	.irq_unmask		= mpic_u3msi_unmask_irq,
> +	.irq_eoi		= mpic_end_irq,
> +	.irq_set_type		= mpic_set_irq_type,
> +	.irq_set_affinity	= mpic_set_affinity,
> +	.name			= "MPIC-U3MSI",
>  };
>  
>  static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
> -- 
> 1.7.4
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: Mpc8315erdb openvpn segmentation fault
From: Vasanth Ragavendran @ 2011-03-08  4:28 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20110307142207.6e879798@schlenkerla>


Thanks a ton Scott. Actually i was working with the same version of the
kernel on both the boards.
it was 2.6.29.6. neither i changed the u-boot. it was the same in both.
however i recompiled the kernel and i installed on both the boards and it
worked fine! :) thanks again for responding. however i've another question.
my filesystem in the board is non-persistent i.e. the files i create are
erased after i reboot i know the files are getting stored in RAM and i wish
to make them persistent. what do i need to do for this? should i create a
separate partition in the flash and load certain files into that partition?
or how should i make it persistent so that files stay beyond reboot! thanks
again! eagerly awaiting your response.


Scott Wood-2 wrote:
> 
> On Mon, 7 Mar 2011 03:09:27 -0800
> Vasanth Ragavendran <ragavendrapec@yahoo.co.in> wrote:
> 
>> 
>> i'm facing a problem. i've installed openvpn on mpc8315erdb board and
>> when i
>> give the command
>> 
>> openvpn --mktun --dev tap0 i get the error
>> 
>>  
>> 
>> [root@mpc8315erdb /]# openvpn --mktun --dev tap0
>> Sat Jan  1 01:04:21 2000 OpenVPNUnable to handle kernel paging request
>> for
>> data
>> at address 0x00000000
>>  2.0.9 ppc-rpm-lFaulting instruction address: 0xc90a208c
>> inux-gnu [SSL] [Oops: Kernel access of bad area, sig: 11 [#1]
>> MPC831x RDB
>> Modules linked in: tun
>> **bleep**: c90a208c LR: c90a2068 CTR: c0288e58
>> REGS: c294fd80 TRAP: 0300   Not tainted  (2.6.29.6)
>> MSR: 00009032 <EE,ME,IR,DR>  CR: 24002424  XER: 20000000
>> DAR: 00000000, DSISR: 20000000
>> TASK = c70b6440[1635] 'openvpn' THREAD: c294e000
>> GPR00: 00000001 c294fe30 c70b6440 c03ebcf4 bfafa0d4 0000001c c294fe58
>> 0fd8dc58
>> GPR08: 00000000 00000001 ffffffe7 00000000 84002428 100787e0 07ff9000
>> 00000004
>> GPR16: 00000000 00000000 bfafa930 00010000 00010000 ffffffff 00000005
>> 3b9aca00
>> GPR24: c7023d20 c294fe3c bfafa0b8 c653e6e0 00000000 c040baf4 bfafa0b8
>> 800454ca
>> Call Trace:
>> [c294fe30] [c90a2068] 0xc90a2068 (unreliable)
>> [c294fe90] [c008054c] 0xc008054c
>> [c294fea0] [c00809c4] 0xc00809c4
>> [c294ff10] [c0080c9c] 0xc0080c9c
>> [c294ff40] [c001141c] 0xc001141c
>> --- Exception: c01 at 0xfce8268
>>     LR = 0xfd6bdec
>> Instruction dump:
>> 4bfffecc 9b81001b 480008ed 3d20c90a 38000001 8129306c 81620308 2f890000
>> 830201a4 83ab0014 817d0124 419e0014 <800b0000> 7c090010 7c000110 7c0000d0
>> LZO] [EPOLL] bui---[ end trace 54eee2a93ccf53d1 ]---
>> lt on Mar  2 2011
>> Sat Jan  1 01:04:21 2000 IMPORTANT: OpenVPN's default port number is now
>> 1194, b
>> ased on an official port number assignment by IANA.  OpenVPN 2.0-beta16
>> and
>> earl
>> ier used 5000 as the default port.
>> Sat Jan  1 01:04:21 2000 ******* WARNING *******: all encryption and
>> authenticat
>> ion features disabled -- all data will be tunnelled as cleartext
>> Segmentation fault
>> 
>>  
>> 
>> Some one plz help me out! wat does this mean? Coz with the same kernel
>> image
>> and the same settings  i'm able to successfully run the above command on
>> another mpc8315erdb board. but it fails on one of the board! any ideas
>> would
>> be of great help to me!! plz!
> 
> Please turn on CONFIG_KALLSYMS, so that symbols will be reported in the
> crash dump, and let us know which kernel you're using.
> 
> Are the other boards where it does not fail running the same kernel?  Same
> userspace?  Same U-Boot?  Anything else different?
> 
> -Scott
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 
> 

-- 
View this message in context: http://old.nabble.com/Mpc8315erdb-openvpn-segmentation-fault-tp31086738p31094242.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.

^ permalink raw reply

* Re: [PATCH 28/28] powerpc: Enable GENERIC_HARDIRQS_NO_DEPRECATED.
From: Grant Likely @ 2011-03-08  4:38 UTC (permalink / raw)
  To: Lennert Buytenhek; +Cc: Thomas Gleixner, linuxppc-dev, Stephen Rothwell
In-Reply-To: <20110308000023.GG16649@mail.wantstofly.org>

On Tue, Mar 08, 2011 at 01:00:23AM +0100, Lennert Buytenhek wrote:
> Signed-off-by: Lennert Buytenhek <buytenh@secretlab.ca>

All 28 look good to me, it compiles with all the defconfigs I tried,
and it boots on mpc5200.  Feel free to add:

Acked-by: Grant Likely <grant.likely@secretlab.ca>

Ben, I've got this series applied against 2.6.38-rc7 in a branch on my
private repo.  If you want me to I can push it out to my powerpc/next
branch so that it gets some linux-next exposure.

g.

> ---
>  arch/powerpc/Kconfig |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 7d69e9b..71ba047 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -134,6 +134,7 @@ config PPC
>  	select HAVE_GENERIC_HARDIRQS
>  	select HAVE_SPARSE_IRQ
>  	select IRQ_PER_CPU
> +	select GENERIC_HARDIRQS_NO_DEPRECATED
>  
>  config EARLY_PRINTK
>  	bool
> -- 
> 1.7.4
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 28/28] powerpc: Enable GENERIC_HARDIRQS_NO_DEPRECATED.
From: Benjamin Herrenschmidt @ 2011-03-08  4:48 UTC (permalink / raw)
  To: Grant Likely
  Cc: Stephen Rothwell, Thomas Gleixner, linuxppc-dev,
	Lennert Buytenhek
In-Reply-To: <20110308043858.GC23260@angua.secretlab.ca>

On Mon, 2011-03-07 at 21:38 -0700, Grant Likely wrote:
> 
> All 28 look good to me, it compiles with all the defconfigs I tried,
> and it boots on mpc5200.  Feel free to add:
> 
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
> 
> Ben, I've got this series applied against 2.6.38-rc7 in a branch on my
> private repo.  If you want me to I can push it out to my powerpc/next
> branch so that it gets some linux-next exposure.

Nah, I'll pick it up, will do some tests first. I'm just finishing some
CPU hotplug fixes/cleanups now and will do that next.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH 01/28] powerpc: mpic irq_data conversion.
From: Benjamin Herrenschmidt @ 2011-03-08  4:51 UTC (permalink / raw)
  To: Grant Likely
  Cc: Stephen Rothwell, Thomas Gleixner, linuxppc-dev,
	Lennert Buytenhek
In-Reply-To: <20110308041332.GB23260@angua.secretlab.ca>

On Mon, 2011-03-07 at 21:13 -0700, Grant Likely wrote:
> On Tue, Mar 08, 2011 at 12:59:02AM +0100, Lennert Buytenhek wrote:
> > Signed-off-by: Lennert Buytenhek <buytenh@secretlab.ca>
> 
> Hi Lennert,
> 
> I'm taking a look over now and running some build testing.
> 
> However, this needs a wider audience for review before it gets merged.
> Can you please repost and cc: benh, sfr, tglx, and linux-kernel?

No need to re-CC me. I have picked it up from the list and it's on
patchwork.

If Thomas is interested, he can look at patchwork I suppose :-)

Cheers,
Ben.

> Thanks,
> g.
> 
> > ---
> >  arch/powerpc/include/asm/mpic.h       |    6 +-
> >  arch/powerpc/platforms/pasemi/setup.c |    4 +-
> >  arch/powerpc/sysdev/mpic.c            |  131 +++++++++++++++++----------------
> >  arch/powerpc/sysdev/mpic.h            |    5 +-
> >  arch/powerpc/sysdev/mpic_pasemi_msi.c |   18 ++--
> >  arch/powerpc/sysdev/mpic_u3msi.c      |   18 ++--
> >  6 files changed, 92 insertions(+), 90 deletions(-)
> > 
> > diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
> > index e000cce..946ec49 100644
> > --- a/arch/powerpc/include/asm/mpic.h
> > +++ b/arch/powerpc/include/asm/mpic.h
> > @@ -467,11 +467,11 @@ extern void mpic_request_ipis(void);
> >  void smp_mpic_message_pass(int target, int msg);
> >  
> >  /* Unmask a specific virq */
> > -extern void mpic_unmask_irq(unsigned int irq);
> > +extern void mpic_unmask_irq(struct irq_data *d);
> >  /* Mask a specific virq */
> > -extern void mpic_mask_irq(unsigned int irq);
> > +extern void mpic_mask_irq(struct irq_data *d);
> >  /* EOI a specific virq */
> > -extern void mpic_end_irq(unsigned int irq);
> > +extern void mpic_end_irq(struct irq_data *d);
> >  
> >  /* Fetch interrupt from a given mpic */
> >  extern unsigned int mpic_get_one_irq(struct mpic *mpic);
> > diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
> > index f372ec1..a6067b3 100644
> > --- a/arch/powerpc/platforms/pasemi/setup.c
> > +++ b/arch/powerpc/platforms/pasemi/setup.c
> > @@ -240,7 +240,7 @@ static __init void pas_init_IRQ(void)
> >  		nmi_virq = irq_create_mapping(NULL, *nmiprop);
> >  		mpic_irq_set_priority(nmi_virq, 15);
> >  		set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
> > -		mpic_unmask_irq(nmi_virq);
> > +		mpic_unmask_irq(irq_get_irq_data(nmi_virq));
> >  	}
> >  
> >  	of_node_put(mpic_node);
> > @@ -266,7 +266,7 @@ static int pas_machine_check_handler(struct pt_regs *regs)
> >  	if (nmi_virq != NO_IRQ && mpic_get_mcirq() == nmi_virq) {
> >  		printk(KERN_ERR "NMI delivered\n");
> >  		debugger(regs);
> > -		mpic_end_irq(nmi_virq);
> > +		mpic_end_irq(irq_get_irq_data(nmi_virq));
> >  		goto out;
> >  	}
> >  
> > diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
> > index b0c8469..95712f6 100644
> > --- a/arch/powerpc/sysdev/mpic.c
> > +++ b/arch/powerpc/sysdev/mpic.c
> > @@ -611,7 +611,7 @@ static struct mpic *mpic_find(unsigned int irq)
> >  	if (irq < NUM_ISA_INTERRUPTS)
> >  		return NULL;
> >  
> > -	return irq_to_desc(irq)->chip_data;
> > +	return get_irq_chip_data(irq);
> >  }
> >  
> >  /* Determine if the linux irq is an IPI */
> > @@ -636,16 +636,16 @@ static inline u32 mpic_physmask(u32 cpumask)
> >  
> >  #ifdef CONFIG_SMP
> >  /* Get the mpic structure from the IPI number */
> > -static inline struct mpic * mpic_from_ipi(unsigned int ipi)
> > +static inline struct mpic * mpic_from_ipi(struct irq_data *d)
> >  {
> > -	return irq_to_desc(ipi)->chip_data;
> > +	return irq_data_get_irq_chip_data(d);
> >  }
> >  #endif
> >  
> >  /* Get the mpic structure from the irq number */
> >  static inline struct mpic * mpic_from_irq(unsigned int irq)
> >  {
> > -	return irq_to_desc(irq)->chip_data;
> > +	return get_irq_chip_data(irq);
> >  }
> >  
> >  /* Send an EOI */
> > @@ -660,13 +660,13 @@ static inline void mpic_eoi(struct mpic *mpic)
> >   */
> >  
> >  
> > -void mpic_unmask_irq(unsigned int irq)
> > +void mpic_unmask_irq(struct irq_data *d)
> >  {
> >  	unsigned int loops = 100000;
> > -	struct mpic *mpic = mpic_from_irq(irq);
> > -	unsigned int src = mpic_irq_to_hw(irq);
> > +	struct mpic *mpic = mpic_from_irq(d->irq);
> > +	unsigned int src = mpic_irq_to_hw(d->irq);
> >  
> > -	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
> > +	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src);
> >  
> >  	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
> >  		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
> > @@ -681,13 +681,13 @@ void mpic_unmask_irq(unsigned int irq)
> >  	} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
> >  }
> >  
> > -void mpic_mask_irq(unsigned int irq)
> > +void mpic_mask_irq(struct irq_data *d)
> >  {
> >  	unsigned int loops = 100000;
> > -	struct mpic *mpic = mpic_from_irq(irq);
> > -	unsigned int src = mpic_irq_to_hw(irq);
> > +	struct mpic *mpic = mpic_from_irq(d->irq);
> > +	unsigned int src = mpic_irq_to_hw(d->irq);
> >  
> > -	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
> > +	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src);
> >  
> >  	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
> >  		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
> > @@ -703,12 +703,12 @@ void mpic_mask_irq(unsigned int irq)
> >  	} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
> >  }
> >  
> > -void mpic_end_irq(unsigned int irq)
> > +void mpic_end_irq(struct irq_data *d)
> >  {
> > -	struct mpic *mpic = mpic_from_irq(irq);
> > +	struct mpic *mpic = mpic_from_irq(d->irq);
> >  
> >  #ifdef DEBUG_IRQ
> > -	DBG("%s: end_irq: %d\n", mpic->name, irq);
> > +	DBG("%s: end_irq: %d\n", mpic->name, d->irq);
> >  #endif
> >  	/* We always EOI on end_irq() even for edge interrupts since that
> >  	 * should only lower the priority, the MPIC should have properly
> > @@ -720,51 +720,51 @@ void mpic_end_irq(unsigned int irq)
> >  
> >  #ifdef CONFIG_MPIC_U3_HT_IRQS
> >  
> > -static void mpic_unmask_ht_irq(unsigned int irq)
> > +static void mpic_unmask_ht_irq(struct irq_data *d)
> >  {
> > -	struct mpic *mpic = mpic_from_irq(irq);
> > -	unsigned int src = mpic_irq_to_hw(irq);
> > +	struct mpic *mpic = mpic_from_irq(d->irq);
> > +	unsigned int src = mpic_irq_to_hw(d->irq);
> >  
> > -	mpic_unmask_irq(irq);
> > +	mpic_unmask_irq(d);
> >  
> > -	if (irq_to_desc(irq)->status & IRQ_LEVEL)
> > +	if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
> >  		mpic_ht_end_irq(mpic, src);
> >  }
> >  
> > -static unsigned int mpic_startup_ht_irq(unsigned int irq)
> > +static unsigned int mpic_startup_ht_irq(struct irq_data *d)
> >  {
> > -	struct mpic *mpic = mpic_from_irq(irq);
> > -	unsigned int src = mpic_irq_to_hw(irq);
> > +	struct mpic *mpic = mpic_from_irq(d->irq);
> > +	unsigned int src = mpic_irq_to_hw(d->irq);
> >  
> > -	mpic_unmask_irq(irq);
> > -	mpic_startup_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
> > +	mpic_unmask_irq(d);
> > +	mpic_startup_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
> >  
> >  	return 0;
> >  }
> >  
> > -static void mpic_shutdown_ht_irq(unsigned int irq)
> > +static void mpic_shutdown_ht_irq(struct irq_data *d)
> >  {
> > -	struct mpic *mpic = mpic_from_irq(irq);
> > -	unsigned int src = mpic_irq_to_hw(irq);
> > +	struct mpic *mpic = mpic_from_irq(d->irq);
> > +	unsigned int src = mpic_irq_to_hw(d->irq);
> >  
> > -	mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
> > -	mpic_mask_irq(irq);
> > +	mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
> > +	mpic_mask_irq(d);
> >  }
> >  
> > -static void mpic_end_ht_irq(unsigned int irq)
> > +static void mpic_end_ht_irq(struct irq_data *d)
> >  {
> > -	struct mpic *mpic = mpic_from_irq(irq);
> > -	unsigned int src = mpic_irq_to_hw(irq);
> > +	struct mpic *mpic = mpic_from_irq(d->irq);
> > +	unsigned int src = mpic_irq_to_hw(d->irq);
> >  
> >  #ifdef DEBUG_IRQ
> > -	DBG("%s: end_irq: %d\n", mpic->name, irq);
> > +	DBG("%s: end_irq: %d\n", mpic->name, d->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
> >  	 */
> >  
> > -	if (irq_to_desc(irq)->status & IRQ_LEVEL)
> > +	if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
> >  		mpic_ht_end_irq(mpic, src);
> >  	mpic_eoi(mpic);
> >  }
> > @@ -772,23 +772,23 @@ static void mpic_end_ht_irq(unsigned int irq)
> >  
> >  #ifdef CONFIG_SMP
> >  
> > -static void mpic_unmask_ipi(unsigned int irq)
> > +static void mpic_unmask_ipi(struct irq_data *d)
> >  {
> > -	struct mpic *mpic = mpic_from_ipi(irq);
> > -	unsigned int src = mpic_irq_to_hw(irq) - mpic->ipi_vecs[0];
> > +	struct mpic *mpic = mpic_from_ipi(d);
> > +	unsigned int src = mpic_irq_to_hw(d->irq) - mpic->ipi_vecs[0];
> >  
> > -	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
> > +	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
> >  	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
> >  }
> >  
> > -static void mpic_mask_ipi(unsigned int irq)
> > +static void mpic_mask_ipi(struct irq_data *d)
> >  {
> >  	/* NEVER disable an IPI... that's just plain wrong! */
> >  }
> >  
> > -static void mpic_end_ipi(unsigned int irq)
> > +static void mpic_end_ipi(struct irq_data *d)
> >  {
> > -	struct mpic *mpic = mpic_from_ipi(irq);
> > +	struct mpic *mpic = mpic_from_ipi(d);
> >  
> >  	/*
> >  	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
> > @@ -802,10 +802,11 @@ static void mpic_end_ipi(unsigned int irq)
> >  
> >  #endif /* CONFIG_SMP */
> >  
> > -int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
> > +int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
> > +		      bool force)
> >  {
> > -	struct mpic *mpic = mpic_from_irq(irq);
> > -	unsigned int src = mpic_irq_to_hw(irq);
> > +	struct mpic *mpic = mpic_from_irq(d->irq);
> > +	unsigned int src = mpic_irq_to_hw(d->irq);
> >  
> >  	if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
> >  		int cpuid = irq_choose_cpu(cpumask);
> > @@ -848,15 +849,15 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
> >  	}
> >  }
> >  
> > -int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
> > +int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
> >  {
> > -	struct mpic *mpic = mpic_from_irq(virq);
> > -	unsigned int src = mpic_irq_to_hw(virq);
> > -	struct irq_desc *desc = irq_to_desc(virq);
> > +	struct mpic *mpic = mpic_from_irq(d->irq);
> > +	unsigned int src = mpic_irq_to_hw(d->irq);
> > +	struct irq_desc *desc = irq_to_desc(d->irq);
> >  	unsigned int vecpri, vold, vnew;
> >  
> >  	DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
> > -	    mpic, virq, src, flow_type);
> > +	    mpic, d->irq, src, flow_type);
> >  
> >  	if (src >= mpic->irq_count)
> >  		return -EINVAL;
> > @@ -907,28 +908,28 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
> >  }
> >  
> >  static struct irq_chip mpic_irq_chip = {
> > -	.mask		= mpic_mask_irq,
> > -	.unmask		= mpic_unmask_irq,
> > -	.eoi		= mpic_end_irq,
> > -	.set_type	= mpic_set_irq_type,
> > +	.irq_mask	= mpic_mask_irq,
> > +	.irq_unmask	= mpic_unmask_irq,
> > +	.irq_eoi	= mpic_end_irq,
> > +	.irq_set_type	= mpic_set_irq_type,
> >  };
> >  
> >  #ifdef CONFIG_SMP
> >  static struct irq_chip mpic_ipi_chip = {
> > -	.mask		= mpic_mask_ipi,
> > -	.unmask		= mpic_unmask_ipi,
> > -	.eoi		= mpic_end_ipi,
> > +	.irq_mask	= mpic_mask_ipi,
> > +	.irq_unmask	= mpic_unmask_ipi,
> > +	.irq_eoi	= mpic_end_ipi,
> >  };
> >  #endif /* CONFIG_SMP */
> >  
> >  #ifdef CONFIG_MPIC_U3_HT_IRQS
> >  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,
> > -	.set_type	= mpic_set_irq_type,
> > +	.irq_startup	= mpic_startup_ht_irq,
> > +	.irq_shutdown	= mpic_shutdown_ht_irq,
> > +	.irq_mask	= mpic_mask_irq,
> > +	.irq_unmask	= mpic_unmask_ht_irq,
> > +	.irq_eoi	= mpic_end_ht_irq,
> > +	.irq_set_type	= mpic_set_irq_type,
> >  };
> >  #endif /* CONFIG_MPIC_U3_HT_IRQS */
> >  
> > @@ -1060,12 +1061,12 @@ struct mpic * __init mpic_alloc(struct device_node *node,
> >  	mpic->hc_irq = mpic_irq_chip;
> >  	mpic->hc_irq.name = name;
> >  	if (flags & MPIC_PRIMARY)
> > -		mpic->hc_irq.set_affinity = mpic_set_affinity;
> > +		mpic->hc_irq.irq_set_affinity = mpic_set_affinity;
> >  #ifdef CONFIG_MPIC_U3_HT_IRQS
> >  	mpic->hc_ht_irq = mpic_irq_ht_chip;
> >  	mpic->hc_ht_irq.name = name;
> >  	if (flags & MPIC_PRIMARY)
> > -		mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
> > +		mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity;
> >  #endif /* CONFIG_MPIC_U3_HT_IRQS */
> >  
> >  #ifdef CONFIG_SMP
> > diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
> > index e4a6df7..13f3e89 100644
> > --- a/arch/powerpc/sysdev/mpic.h
> > +++ b/arch/powerpc/sysdev/mpic.h
> > @@ -34,9 +34,10 @@ static inline int mpic_pasemi_msi_init(struct mpic *mpic)
> >  }
> >  #endif
> >  
> > -extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
> > +extern int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type);
> >  extern void mpic_set_vector(unsigned int virq, unsigned int vector);
> > -extern int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
> > +extern int mpic_set_affinity(struct irq_data *d,
> > +			     const struct cpumask *cpumask, bool force);
> >  extern void mpic_reset_core(int cpu);
> >  
> >  #endif /* _POWERPC_SYSDEV_MPIC_H */
> > diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
> > index 320ad5a..0b7794a 100644
> > --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
> > +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
> > @@ -43,24 +43,24 @@ static void mpic_pasemi_msi_mask_irq(struct irq_data *data)
> >  {
> >  	pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq);
> >  	mask_msi_irq(data);
> > -	mpic_mask_irq(data->irq);
> > +	mpic_mask_irq(data);
> >  }
> >  
> >  static void mpic_pasemi_msi_unmask_irq(struct irq_data *data)
> >  {
> >  	pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq);
> > -	mpic_unmask_irq(data->irq);
> > +	mpic_unmask_irq(data);
> >  	unmask_msi_irq(data);
> >  }
> >  
> >  static struct irq_chip mpic_pasemi_msi_chip = {
> > -	.irq_shutdown	= mpic_pasemi_msi_mask_irq,
> > -	.irq_mask	= mpic_pasemi_msi_mask_irq,
> > -	.irq_unmask	= mpic_pasemi_msi_unmask_irq,
> > -	.eoi		= mpic_end_irq,
> > -	.set_type	= mpic_set_irq_type,
> > -	.set_affinity	= mpic_set_affinity,
> > -	.name		= "PASEMI-MSI",
> > +	.irq_shutdown		= mpic_pasemi_msi_mask_irq,
> > +	.irq_mask		= mpic_pasemi_msi_mask_irq,
> > +	.irq_unmask		= mpic_pasemi_msi_unmask_irq,
> > +	.irq_eoi		= mpic_end_irq,
> > +	.irq_set_type		= mpic_set_irq_type,
> > +	.irq_set_affinity	= mpic_set_affinity,
> > +	.name			= "PASEMI-MSI",
> >  };
> >  
> >  static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
> > diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
> > index a2b028b..71900ac 100644
> > --- a/arch/powerpc/sysdev/mpic_u3msi.c
> > +++ b/arch/powerpc/sysdev/mpic_u3msi.c
> > @@ -26,23 +26,23 @@ static struct mpic *msi_mpic;
> >  static void mpic_u3msi_mask_irq(struct irq_data *data)
> >  {
> >  	mask_msi_irq(data);
> > -	mpic_mask_irq(data->irq);
> > +	mpic_mask_irq(data);
> >  }
> >  
> >  static void mpic_u3msi_unmask_irq(struct irq_data *data)
> >  {
> > -	mpic_unmask_irq(data->irq);
> > +	mpic_unmask_irq(data);
> >  	unmask_msi_irq(data);
> >  }
> >  
> >  static struct irq_chip mpic_u3msi_chip = {
> > -	.irq_shutdown	= mpic_u3msi_mask_irq,
> > -	.irq_mask	= mpic_u3msi_mask_irq,
> > -	.irq_unmask	= mpic_u3msi_unmask_irq,
> > -	.eoi		= mpic_end_irq,
> > -	.set_type	= mpic_set_irq_type,
> > -	.set_affinity	= mpic_set_affinity,
> > -	.name		= "MPIC-U3MSI",
> > +	.irq_shutdown		= mpic_u3msi_mask_irq,
> > +	.irq_mask		= mpic_u3msi_mask_irq,
> > +	.irq_unmask		= mpic_u3msi_unmask_irq,
> > +	.irq_eoi		= mpic_end_irq,
> > +	.irq_set_type		= mpic_set_irq_type,
> > +	.irq_set_affinity	= mpic_set_affinity,
> > +	.name			= "MPIC-U3MSI",
> >  };
> >  
> >  static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
> > -- 
> > 1.7.4
> > 
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH] powerpc: disable MSI using new interface if possible
From: Nishanth Aravamudan @ 2011-03-08  5:34 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, paulus, miltonm
In-Reply-To: <20110304072444.GA2080@us.ibm.com>

On 03.03.2011 [23:24:44 -0800], Nishanth Aravamudan wrote:
> On 04.03.2011 [14:01:24 +1100], Michael Ellerman wrote:
> > On Thu, 2011-03-03 at 17:41 -0800, Nishanth Aravamudan wrote:
> > > On 04.03.2011 [12:05:29 +1100], Michael Ellerman wrote:
> > > > On Thu, 2011-03-03 at 11:39 -0800, Nishanth Aravamudan wrote:
> > > > > On upcoming hardware, we have a PCI adapter with two functions, one of
> > > > > which uses MSI and the other uses MSI-X. This adapter, when MSI is
> > > > > disabled using the "old" firmware interface (RTAS_CHANGE_FN), still
> > > > > signals an MSI-X interrupt and triggers an EEH. We are working with the
> > > > > vendor to ensure that the hardware is not at fault, but if we use the
> > > > > "new" interface (RTAS_CHANGE_MSI_FN) to disable MSI, we also
> > > > > automatically disable MSI-X and the adapter does not appear to signal
> > > > > any stray MSI-X interrupt.
> > > > 
> > > > It seems this could also be a firmware bug, have we heard anything from
> > > > them? PAPR explicitly says that RTAS_CHANGE_FN (function=1) should
> > > > disable MSI _and_ MSI-X (R1???7.3.10.5.1???1).
> > > 
> > > We're tracking that down too. I think the fact that the interrupt is
> > > coming in is a hardware bug in this particular adapter.
> > > 
> > > I'm looking at PAPR again and I see what might be a contradiction:
> > > 
> > > 7.3.10.5.1: "To removing all MSIs, set the Requested Number of
> > > Interrupts to zero."
> > > 
> > > Table 71: "Function ... 1: Request to set to a new number of MSI or
> > > MSI-X (platform choice) interrupts (including set to 0)"
> > > 
> > > It seems like the Table claims that using RTAS_CHANGE_FN with 0, could
> > > change only MSI or MSI-X and still be not a bug?
> > 
> > Yeah I guess you could read it that way, though I think that would be a
> > bug.
> > 
> > The idea is that it chooses for you whether it uses MSI or MSI-X. So the
> > only sane semantic is that when deconfiguring it deconfigures either,
> > ie. both, kinds.
> 
> I agree with you that is how it should be :) I'm asking the firmware
> folks to make sure I'm not misunderstanding the underlying issue.

It would appear that if a device does support both MSI and MSI-X and the
old (non-explicit) interface is used, only one of MSI or MSI-X is
guaranteed to be disabled, with preference given to MSI. Now, it turns
out that there is also a firmware dragon here (because this particular
device is misbehaving), but we can also fix it by using the new
interface, which shouldn't cause any harm, given the fallback.

> > Looking closer at your patch, now I don't understand :)
> > 
> > +       /*
> > +        * disabling MSI with the explicit interface also disables MSI-X
> > +        */
> > +       if (rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, 0) != 0) {
> > 
> > 
> > So we first disable using function 3, which should:
> > 
> >         3: Request to set to a new number of MSI interrupts (including set to 0)
> > 
> > Which does not mention MSI-X at all, implying it has no effect on them.
> > Which contradicts what you see, and the comment in the code?
> 
> Thanks for the thorough review!
> 
> Per PAPR 2.4 from Power.org, look at the page before that table, page
> 169:
> 
> "Specifying Function 3 (MSI) also disables MSI-X for the specified IOA
> function, and likewise specifying Function 4 (MSI-X) disables MSI for
> the IOA function....Specifying the Requested Number of Interrupts to
> zero for either Function 3 or 4 removes all MSI & MSI-X interrupts from
> the IOA function."
> 
> So I'm relying on this aspect of PAPR being enforced by the firmware,
> which I think it is in my testing.

Given all that, do I have your Ack? :)

Thanks,
Nish

-- 
Nishanth Aravamudan <nacc@us.ibm.com>
IBM Linux Technology Center

^ permalink raw reply

* [PATCH 03/18] powerpc/smp: Fix generic_mach_cpu_die()
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

This is used by some "soft" hotplug implementations. I needs to
call idle_task_exit() when the CPU is going away, and we remove
the now no-longer needed set_cpu_online() and local_irq_enable()
which are handled by the return to start_secondary

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/smp.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 1c9956c..3c0fab5 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -362,14 +362,13 @@ void generic_mach_cpu_die(void)
 	unsigned int cpu;
 
 	local_irq_disable();
+	idle_task_exit();
 	cpu = smp_processor_id();
 	printk(KERN_DEBUG "CPU%d offline\n", cpu);
 	__get_cpu_var(cpu_state) = CPU_DEAD;
 	smp_wmb();
 	while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
 		cpu_relax();
-	set_cpu_online(cpu, true);
-	local_irq_enable();
 }
 #endif
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 08/18] powerpc/pmac/smp: Fixup smp_core99_cpu_disable() and use it on 64-bit
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Use the generic code, just add the MPIC priority setting,

I don't see any use in mucking around with the decrementer,
as 32-bit will have EE off all along, and 64-bit will be able
to deal with it.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powermac/smp.c |   17 +++++------------
 1 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index e0ac7bb..eda4709 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -867,16 +867,14 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
 
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
 
-int smp_core99_cpu_disable(void)
+static int smp_core99_cpu_disable(void)
 {
-	set_cpu_online(smp_processor_id(), false);
+	int rc = generic_cpu_disable();
+	if (rc)
+		return rc;
 
-	/* XXX reset cpu affinity here */
 	mpic_cpu_set_priority(0xf);
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-	mb();
-	udelay(20);
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
 	return 0;
 }
 
@@ -902,12 +900,7 @@ struct smp_ops_t core99_smp_ops = {
 	.give_timebase	= smp_core99_give_timebase,
 	.take_timebase	= smp_core99_take_timebase,
 #if defined(CONFIG_HOTPLUG_CPU)
-# if defined(CONFIG_PPC32)
 	.cpu_disable	= smp_core99_cpu_disable,
-# endif
-# if defined(CONFIG_PPC64)
-	.cpu_disable	= generic_cpu_disable,
-# endif
 	.cpu_die	= generic_cpu_die,
 #endif
 };
-- 
1.7.1

^ permalink raw reply related

* [PATCH 05/18] powerpc/smp: Remove unused smp_ops->cpu_enable()
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Remove the last remnants of cpu_enable(), everybody uses the normal
__cpu_up() path now

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/machdep.h    |    1 -
 arch/powerpc/kernel/smp.c             |   10 ----------
 arch/powerpc/platforms/powermac/smp.c |    2 --
 3 files changed, 0 insertions(+), 13 deletions(-)

diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index fe56a23..bcfc0da 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -37,7 +37,6 @@ struct smp_ops_t {
 	void  (*setup_cpu)(int nr);
 	void  (*take_timebase)(void);
 	void  (*give_timebase)(void);
-	int   (*cpu_enable)(unsigned int nr);
 	int   (*cpu_disable)(void);
 	void  (*cpu_die)(unsigned int nr);
 	int   (*cpu_bootable)(unsigned int nr);
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 19d0c25..be7d728 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -350,21 +350,11 @@ void generic_mach_cpu_die(void)
 }
 #endif
 
-static int __devinit cpu_enable(unsigned int cpu)
-{
-	if (smp_ops && smp_ops->cpu_enable)
-		return smp_ops->cpu_enable(cpu);
-
-	return -ENOSYS;
-}
-
 int __cpuinit __cpu_up(unsigned int cpu)
 {
 	int c;
 
 	secondary_ti = current_set[cpu];
-	if (!cpu_enable(cpu))
-		return 0;
 
 	if (smp_ops == NULL ||
 	    (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index c95215f..ebd2b7e 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -923,8 +923,6 @@ struct smp_ops_t core99_smp_ops = {
 # if defined(CONFIG_PPC64)
 	.cpu_disable	= generic_cpu_disable,
 	.cpu_die	= generic_cpu_die,
-	/* intentionally do *NOT* assign cpu_enable,
-	 * the generic code will use kick_cpu then! */
 # endif
 #endif
 };
-- 
1.7.1

^ permalink raw reply related

* [PATCH 04/18] powerpc/smp: Remove unused generic_cpu_enable()
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Nobody uses it, besides we should always use the normal __cpu_up
path anyways

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/smp.h |    1 -
 arch/powerpc/kernel/smp.c      |   22 ----------------------
 2 files changed, 0 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 1de0e97..a629b6f 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -43,7 +43,6 @@ DECLARE_PER_CPU(unsigned int, cpu_pvr);
 #ifdef CONFIG_HOTPLUG_CPU
 extern void fixup_irqs(const struct cpumask *map);
 int generic_cpu_disable(void);
-int generic_cpu_enable(unsigned int cpu);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
 #endif
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 3c0fab5..19d0c25 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -322,28 +322,6 @@ int generic_cpu_disable(void)
 	return 0;
 }
 
-int generic_cpu_enable(unsigned int cpu)
-{
-	/* Do the normal bootup if we haven't
-	 * already bootstrapped. */
-	if (system_state != SYSTEM_RUNNING)
-		return -ENOSYS;
-
-	/* get the target out of it's holding state */
-	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
-	smp_wmb();
-
-	while (!cpu_online(cpu))
-		cpu_relax();
-
-#ifdef CONFIG_PPC64
-	fixup_irqs(cpu_online_mask);
-	/* counter the irq disable in fixup_irqs */
-	local_irq_enable();
-#endif
-	return 0;
-}
-
 void generic_cpu_die(unsigned int cpu)
 {
 	int i;
-- 
1.7.1

^ permalink raw reply related

* [PATCH 01/18] powerpc: Make decrementer interrupt robust against offlined CPUs
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

With some implementations, it is possible that a timer interrupt
occurs every few seconds on an offline CPU. In this case, just
re-arm the decrementer and return immediately

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/time.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 09d31db..ecebc7c 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -577,14 +577,21 @@ void timer_interrupt(struct pt_regs * regs)
 	struct clock_event_device *evt = &decrementer->event;
 	u64 now;
 
+	/* Ensure a positive value is written to the decrementer, or else
+	 * some CPUs will continuue to take decrementer exceptions
+	 */
+	set_dec(DECREMENTER_MAX);
+
+	/* Some implementations of hotplug will get timer interrupts while
+	 * offline, just ignore these
+	 */
+	if (!cpu_online(smp_processor_id()))
+		return;
+
 	trace_timer_interrupt_entry(regs);
 
 	__get_cpu_var(irq_stat).timer_irqs++;
 
-	/* Ensure a positive value is written to the decrementer, or else
-	 * some CPUs will continuue to take decrementer exceptions */
-	set_dec(DECREMENTER_MAX);
-
 #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);
-- 
1.7.1

^ permalink raw reply related

* [PATCH 09/18] powerpc/pmac/smp: Consolidate 32-bit and 64-bit PowerMac cpu_die in one file
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powermac/pmac.h  |    1 -
 arch/powerpc/platforms/powermac/setup.c |   56 -----------------------------
 arch/powerpc/platforms/powermac/smp.c   |   58 +++++++++++++++++++++++++++++--
 3 files changed, 55 insertions(+), 60 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
index f0bc08f..20468f4 100644
--- a/arch/powerpc/platforms/powermac/pmac.h
+++ b/arch/powerpc/platforms/powermac/pmac.h
@@ -33,7 +33,6 @@ extern void pmac_setup_pci_dma(void);
 extern void pmac_check_ht_link(void);
 
 extern void pmac_setup_smp(void);
-extern void pmac32_cpu_die(void);
 extern void low_cpu_die(void) __attribute__((noreturn));
 
 extern int pmac_nvram_init(void);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index d5aceb7..aa45281 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -650,51 +650,6 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)
 		return PCI_PROBE_NORMAL;
 	return PCI_PROBE_DEVTREE;
 }
-
-#ifdef CONFIG_HOTPLUG_CPU
-/* access per cpu vars from generic smp.c */
-DECLARE_PER_CPU(int, cpu_state);
-
-static void pmac64_cpu_die(void)
-{
-	/*
-	 * turn off as much as possible, we'll be
-	 * kicked out as this will only be invoked
-	 * on core99 platforms for now ...
-	 */
-
-	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
-	__get_cpu_var(cpu_state) = CPU_DEAD;
-	smp_wmb();
-
-	/*
-	 * during the path that leads here preemption is disabled,
-	 * reenable it now so that when coming up preempt count is
-	 * zero correctly
-	 */
-	preempt_enable();
-
-	/*
-	 * hard-disable interrupts for the non-NAP case, the NAP code
-	 * needs to re-enable interrupts (but soft-disables them)
-	 */
-	hard_irq_disable();
-
-	while (1) {
-		/* let's not take timer interrupts too often ... */
-		set_dec(0x7fffffff);
-
-		/* should always be true at this point */
-		if (cpu_has_feature(CPU_FTR_CAN_NAP))
-			power4_cpu_offline_powersave();
-		else {
-			HMT_low();
-			HMT_very_low();
-		}
-	}
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
 #endif /* CONFIG_PPC64 */
 
 define_machine(powermac) {
@@ -726,15 +681,4 @@ define_machine(powermac) {
 	.pcibios_after_init	= pmac_pcibios_after_init,
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
 #endif
-#ifdef CONFIG_HOTPLUG_CPU
-#ifdef CONFIG_PPC64
-	.cpu_die		= pmac64_cpu_die,
-#endif
-#ifdef CONFIG_PPC32
-	.cpu_die		= pmac32_cpu_die,
-#endif
-#endif
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
-	.cpu_die		= generic_mach_cpu_die,
-#endif
 };
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index eda4709..50e15b4 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -865,7 +865,7 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
 }
 
 
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
+#ifdef CONFIG_HOTPLUG_CPU
 
 static int smp_core99_cpu_disable(void)
 {
@@ -878,7 +878,9 @@ static int smp_core99_cpu_disable(void)
 	return 0;
 }
 
-void pmac32_cpu_die(void)
+#ifdef CONFIG_PPC32
+
+static void pmac_cpu_die(void)
 {
 	local_irq_disable();
 	idle_task_exit();
@@ -889,7 +891,52 @@ void pmac32_cpu_die(void)
 	low_cpu_die();
 }
 
-#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
+#else /* CONFIG_PPC32 */
+
+static void pmac_cpu_die(void)
+{
+	local_irq_disable();
+	idle_task_exit();
+
+	/*
+	 * turn off as much as possible, we'll be
+	 * kicked out as this will only be invoked
+	 * on core99 platforms for now ...
+	 */
+
+	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	smp_wmb();
+
+	/*
+	 * during the path that leads here preemption is disabled,
+	 * reenable it now so that when coming up preempt count is
+	 * zero correctly
+	 */
+	preempt_enable();
+
+	/*
+	 * hard-disable interrupts for the non-NAP case, the NAP code
+	 * needs to re-enable interrupts (but soft-disables them)
+	 */
+	hard_irq_disable();
+
+	while (1) {
+		/* let's not take timer interrupts too often ... */
+		set_dec(0x7fffffff);
+
+		/* should always be true at this point */
+		if (cpu_has_feature(CPU_FTR_CAN_NAP))
+			power4_cpu_offline_powersave();
+		else {
+			HMT_low();
+			HMT_very_low();
+		}
+	}
+}
+
+#endif /* else CONFIG_PPC32 */
+#endif /* CONFIG_HOTPLUG_CPU */
 
 /* Core99 Macs (dual G4s and G5s) */
 struct smp_ops_t core99_smp_ops = {
@@ -933,5 +980,10 @@ void __init pmac_setup_smp(void)
 		smp_ops = &psurge_smp_ops;
 	}
 #endif /* CONFIG_PPC32 */
+
+#ifdef CONFIG_HOTPLUG_CPU
+	ppc_md.cpu_die = pmac_cpu_die;
+#endif
 }
 
+
-- 
1.7.1

^ permalink raw reply related

* [PATCH 06/18] powerpc/pmac/smp: Fix 32-bit PowerMac cpu_die
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Use generic cpu_state, call idle_task_exit() properly, and
remove smp_core99_cpu_die() which isn't useful, the generic
function does the job just fine.
---
 arch/powerpc/include/asm/smp.h        |    1 +
 arch/powerpc/platforms/powermac/smp.c |   25 +++++--------------------
 2 files changed, 6 insertions(+), 20 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index a629b6f..9fe5597 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -45,6 +45,7 @@ extern void fixup_irqs(const struct cpumask *map);
 int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
+DECLARE_PER_CPU(int, cpu_state);
 #endif
 
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index ebd2b7e..e0ac7bb 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -880,31 +880,17 @@ int smp_core99_cpu_disable(void)
 	return 0;
 }
 
-static int cpu_dead[NR_CPUS];
-
 void pmac32_cpu_die(void)
 {
 	local_irq_disable();
-	cpu_dead[smp_processor_id()] = 1;
+	idle_task_exit();
+	printk(KERN_DEBUG "CPU%d offline\n", smp_processor_id());
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	smp_wmb();
 	mb();
 	low_cpu_die();
 }
 
-void smp_core99_cpu_die(unsigned int cpu)
-{
-	int timeout;
-
-	timeout = 1000;
-	while (!cpu_dead[cpu]) {
-		if (--timeout == 0) {
-			printk("CPU %u refused to die!\n", cpu);
-			break;
-		}
-		msleep(1);
-	}
-	cpu_dead[cpu] = 0;
-}
-
 #endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
 
 /* Core99 Macs (dual G4s and G5s) */
@@ -918,12 +904,11 @@ struct smp_ops_t core99_smp_ops = {
 #if defined(CONFIG_HOTPLUG_CPU)
 # if defined(CONFIG_PPC32)
 	.cpu_disable	= smp_core99_cpu_disable,
-	.cpu_die	= smp_core99_cpu_die,
 # endif
 # if defined(CONFIG_PPC64)
 	.cpu_disable	= generic_cpu_disable,
-	.cpu_die	= generic_cpu_die,
 # endif
+	.cpu_die	= generic_cpu_die,
 #endif
 };
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 07/18] powerpc/pmac/smp: Rename fixup_irqs() to migrate_irqs() and use it on ppc32
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/smp.h |    2 +-
 arch/powerpc/kernel/irq.c      |    3 ++-
 arch/powerpc/kernel/smp.c      |    2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 9fe5597..7e99771 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -41,7 +41,7 @@ extern void start_secondary_resume(void);
 DECLARE_PER_CPU(unsigned int, cpu_pvr);
 
 #ifdef CONFIG_HOTPLUG_CPU
-extern void fixup_irqs(const struct cpumask *map);
+extern void migrate_irqs(void);
 int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index ce557f6..cab8654 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -303,12 +303,13 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-void fixup_irqs(const struct cpumask *map)
+void migrate_irqs(void)
 {
 	struct irq_desc *desc;
 	unsigned int irq;
 	static int warned;
 	cpumask_var_t mask;
+	const struct cpumask *map = cpu_online_mask;
 
 	alloc_cpumask_var(&mask, GFP_KERNEL);
 
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index be7d728..f6cc5c1 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -317,8 +317,8 @@ int generic_cpu_disable(void)
 	set_cpu_online(cpu, false);
 #ifdef CONFIG_PPC64
 	vdso_data->processorCount--;
-	fixup_irqs(cpu_online_mask);
 #endif
+	migrate_irqs();
 	return 0;
 }
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 02/18] powerpc/smp: soft-replugged CPUs must go back to start_secondary
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Various thing are torn down when a CPU is hot-unplugged. That CPU
is expected to go back to start_secondary when re-plugged to re
initialize everything, such as clock sources, maps, ...

Some implementations just return from cpu_die() callback
in the idle loop when the CPU is "re-plugged". This is not enough.

We fix it using a little asm trampoline which resets the stack
and calls back into start_secondary as if we were all fresh from
boot. The trampoline already existed on ppc64, but we add it for
ppc32

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/smp.h                  |    1 +
 arch/powerpc/kernel/head_32.S                   |    9 +++++++++
 arch/powerpc/kernel/smp.c                       |    9 +++++++--
 arch/powerpc/platforms/pseries/offline_states.h |    2 --
 4 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 66e237b..1de0e97 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -36,6 +36,7 @@ extern void cpu_die(void);
 
 extern void smp_send_debugger_break(int cpu);
 extern void smp_message_recv(int);
+extern void start_secondary_resume(void);
 
 DECLARE_PER_CPU(unsigned int, cpu_pvr);
 
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 98c4b29..c5c24be 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -890,6 +890,15 @@ __secondary_start:
 	mtspr	SPRN_SRR1,r4
 	SYNC
 	RFI
+
+_GLOBAL(start_secondary_resume)
+	/* Reset stack */
+	rlwinm	r1,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
+	addi	r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
+	li	r3,0
+	std	r3,0(r1)		/* Zero the stack frame pointer	*/
+	bl	start_secondary
+	b	.
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_KVM_BOOK3S_HANDLER
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 9813605..1c9956c 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -502,7 +502,7 @@ static struct device_node *cpu_to_l2cache(int cpu)
 }
 
 /* Activate a secondary processor. */
-int __devinit start_secondary(void *unused)
+void __devinit start_secondary(void *unused)
 {
 	unsigned int cpu = smp_processor_id();
 	struct device_node *l2_cache;
@@ -558,7 +558,8 @@ int __devinit start_secondary(void *unused)
 	local_irq_enable();
 
 	cpu_idle();
-	return 0;
+
+	BUG();
 }
 
 int setup_profiling_timer(unsigned int multiplier)
@@ -660,5 +661,9 @@ void cpu_die(void)
 {
 	if (ppc_md.cpu_die)
 		ppc_md.cpu_die();
+
+	/* If we return, we re-enter start_secondary */
+	start_secondary_resume();
 }
+
 #endif
diff --git a/arch/powerpc/platforms/pseries/offline_states.h b/arch/powerpc/platforms/pseries/offline_states.h
index 75a6f48..08672d9 100644
--- a/arch/powerpc/platforms/pseries/offline_states.h
+++ b/arch/powerpc/platforms/pseries/offline_states.h
@@ -34,6 +34,4 @@ static inline void set_default_offline_state(int cpu)
 #endif
 
 extern enum cpu_state_vals get_preferred_offline_state(int cpu);
-extern int start_secondary(void);
-extern void start_secondary_resume(void);
 #endif
-- 
1.7.1

^ permalink raw reply related

* [PATCH 15/18] powerpc/smp: Don't expose per-cpu "cpu_state" array
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Instead, keep it static, expose an accessor and use that from
the PowerMac code. Avoids easy namespace collisions and will
make it easier to consolidate with other implementations.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/smp.h        |    2 +-
 arch/powerpc/kernel/smp.c             |    7 ++++++-
 arch/powerpc/platforms/powermac/smp.c |   12 ++++++++----
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 7e99771..a902a0d 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -45,7 +45,7 @@ extern void migrate_irqs(void);
 int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
-DECLARE_PER_CPU(int, cpu_state);
+void generic_set_cpu_dead(unsigned int cpu);
 #endif
 
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index df37397..7beb001 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -305,7 +305,7 @@ void __devinit smp_prepare_boot_cpu(void)
 
 #ifdef CONFIG_HOTPLUG_CPU
 /* State of each CPU during hotplug phases */
-DEFINE_PER_CPU(int, cpu_state) = { 0 };
+static DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 int generic_cpu_disable(void)
 {
@@ -348,6 +348,11 @@ void generic_mach_cpu_die(void)
 	while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
 		cpu_relax();
 }
+
+void generic_set_cpu_dead(unsigned int cpu)
+{
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+}
 #endif
 
 int __cpuinit __cpu_up(unsigned int cpu)
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 74a43c6..ce5b4f5 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -920,10 +920,12 @@ static int smp_core99_cpu_disable(void)
 
 static void pmac_cpu_die(void)
 {
+	int cpu = smp_processor_id();
+
 	local_irq_disable();
 	idle_task_exit();
-	printk(KERN_DEBUG "CPU%d offline\n", smp_processor_id());
-	__get_cpu_var(cpu_state) = CPU_DEAD;
+	pr_debug("CPU%d offline\n", cpu);
+	generic_set_cpu_dead(cpu);
 	smp_wmb();
 	mb();
 	low_cpu_die();
@@ -933,6 +935,8 @@ static void pmac_cpu_die(void)
 
 static void pmac_cpu_die(void)
 {
+	int cpu = smp_processor_id();
+
 	local_irq_disable();
 	idle_task_exit();
 
@@ -942,8 +946,8 @@ static void pmac_cpu_die(void)
 	 * on core99 platforms for now ...
 	 */
 
-	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
-	__get_cpu_var(cpu_state) = CPU_DEAD;
+	printk(KERN_INFO "CPU#%d offline\n", cpu);
+	generic_set_cpu_dead(cpu);
 	smp_wmb();
 
 	/*
-- 
1.7.1

^ permalink raw reply related

* [PATCHES] powerpc: Cleanup and fix CPU hotplug
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev

This series contain a number of cleanups and fixes to our CPU hotplug
code, including fixing crashes on G5 machines, properly re-initializing
idle threads etc...

Tested on PowerMac G5 and pSeries machines.

^ permalink raw reply

* [PATCH 13/18] powerpc/smp: Add a smp_ops->bringup_up() done callback
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

This allows us to stop abusing smp_ops->setup_cpu() for cleanup
tasks that have to take place after the initial boot time CPU
bringup.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/machdep.h |    1 +
 arch/powerpc/kernel/smp.c          |    4 ++++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 578d330..e4f0191 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -35,6 +35,7 @@ struct smp_ops_t {
 	int   (*probe)(void);
 	void  (*kick_cpu)(int nr);
 	void  (*setup_cpu)(int nr);
+	void  (*bringup_done)(void);
 	void  (*take_timebase)(void);
 	void  (*give_timebase)(void);
 	int   (*cpu_disable)(void);
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index f6cc5c1..df37397 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -553,7 +553,11 @@ void __init smp_cpus_done(unsigned int max_cpus)
 
 	free_cpumask_var(old_mask);
 
+	if (smp_ops && smp_ops->bringup_done)
+		smp_ops->bringup_done();
+
 	dump_numa_cpu_topology();
+
 }
 
 int arch_sd_sibling_asym_packing(void)
-- 
1.7.1

^ permalink raw reply related

* [PATCH 10/18] powerpc/pmac/smp: Remove HMT changes for PowerMac offline code
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Those instructions do nothing on non-threaded processors such
as 970's used on those machines.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powermac/smp.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 50e15b4..53bee66 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -928,10 +928,6 @@ static void pmac_cpu_die(void)
 		/* should always be true at this point */
 		if (cpu_has_feature(CPU_FTR_CAN_NAP))
 			power4_cpu_offline_powersave();
-		else {
-			HMT_low();
-			HMT_very_low();
-		}
 	}
 }
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 18/18] powerpc/pmac/smp: Remove no-longer needed preempt workaround
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

The generic code properly re-initializes the preempt count in the
idle thread now

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powermac/smp.c |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index ce5b4f5..a830c5e 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -951,13 +951,6 @@ static void pmac_cpu_die(void)
 	smp_wmb();
 
 	/*
-	 * during the path that leads here preemption is disabled,
-	 * reenable it now so that when coming up preempt count is
-	 * zero correctly
-	 */
-	preempt_enable();
-
-	/*
 	 * Re-enable interrupts. The NAP code needs to enable them
 	 * anyways, do it now so we deal with the case where one already
 	 * happened while soft-disabled.
-- 
1.7.1

^ permalink raw reply related

* [PATCH 16/18] powerpc/smp: Create idle threads on demand and properly reset them
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Instead of creating idle threads at boot for all possible CPUs, we
create them on demand, like x86 or ARM, and we properly call init_idle
to re-initialize an idle thread when a CPU was unplugged and is now
re-plugged.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/smp.c |  100 +++++++++++++++++++++++++++++++++++----------
 1 files changed, 78 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 7beb001..e337073 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -57,6 +57,25 @@
 #define DBG(fmt...)
 #endif
 
+
+/* Store all idle threads, this can be reused instead of creating
+* a new thread. Also avoids complicated thread destroy functionality
+* for idle threads.
+*/
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is
+ * removed after init for !CONFIG_HOTPLUG_CPU.
+ */
+static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
+#define get_idle_for_cpu(x)      (per_cpu(idle_thread_array, x))
+#define set_idle_for_cpu(x, p)   (per_cpu(idle_thread_array, x) = (p))
+#else
+static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
+#define get_idle_for_cpu(x)      (idle_thread_array[(x)])
+#define set_idle_for_cpu(x, p)   (idle_thread_array[(x)] = (p))
+#endif
+
 struct thread_info *secondary_ti;
 
 DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map);
@@ -238,23 +257,6 @@ static void __devinit smp_store_cpu_info(int id)
 	per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR);
 }
 
-static void __init smp_create_idle(unsigned int cpu)
-{
-	struct task_struct *p;
-
-	/* create a process for the processor */
-	p = fork_idle(cpu);
-	if (IS_ERR(p))
-		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-#ifdef CONFIG_PPC64
-	paca[cpu].__current = p;
-	paca[cpu].kstack = (unsigned long) task_thread_info(p)
-		+ THREAD_SIZE - STACK_FRAME_OVERHEAD;
-#endif
-	current_set[cpu] = task_thread_info(p);
-	task_thread_info(p)->cpu = cpu;
-}
-
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	unsigned int cpu;
@@ -288,10 +290,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 			max_cpus = NR_CPUS;
 	else
 		max_cpus = 1;
-
-	for_each_possible_cpu(cpu)
-		if (cpu != boot_cpuid)
-			smp_create_idle(cpu);
 }
 
 void __devinit smp_prepare_boot_cpu(void)
@@ -355,9 +353,62 @@ void generic_set_cpu_dead(unsigned int cpu)
 }
 #endif
 
+struct create_idle {
+	struct work_struct work;
+	struct task_struct *idle;
+	struct completion done;
+	int cpu;
+};
+
+static void __cpuinit do_fork_idle(struct work_struct *work)
+{
+	struct create_idle *c_idle =
+		container_of(work, struct create_idle, work);
+
+	c_idle->idle = fork_idle(c_idle->cpu);
+	complete(&c_idle->done);
+}
+
+static int __cpuinit create_idle(unsigned int cpu)
+{
+	struct thread_info *ti;
+	struct create_idle c_idle = {
+		.cpu	= cpu,
+		.done	= COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
+	};
+	INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
+
+	c_idle.idle = get_idle_for_cpu(cpu);
+
+	/* We can't use kernel_thread since we must avoid to
+	 * reschedule the child. We use a workqueue because
+	 * we want to fork from a kernel thread, not whatever
+	 * userspace process happens to be trying to online us.
+	 */
+	if (!c_idle.idle) {
+		schedule_work(&c_idle.work);
+		wait_for_completion(&c_idle.done);
+	} else
+		init_idle(c_idle.idle, cpu);
+	if (IS_ERR(c_idle.idle)) {		
+		pr_err("Failed fork for CPU %u: %li", cpu, PTR_ERR(c_idle.idle));
+		return PTR_ERR(c_idle.idle);
+	}
+	ti = task_thread_info(c_idle.idle);
+
+#ifdef CONFIG_PPC64
+	paca[cpu].__current = c_idle.idle;
+	paca[cpu].kstack = (unsigned long)ti + THREAD_SIZE - STACK_FRAME_OVERHEAD;
+#endif
+	ti->cpu = cpu;
+	current_set[cpu] = ti;
+
+	return 0;
+}
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
-	int c;
+	int rc, c;
 
 	secondary_ti = current_set[cpu];
 
@@ -365,6 +416,11 @@ int __cpuinit __cpu_up(unsigned int cpu)
 	    (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
 		return -EINVAL;
 
+	/* Make sure we have an idle thread */
+	rc = create_idle(cpu);
+	if (rc)
+		return rc;
+
 	/* Make sure callin-map entry is 0 (can be leftover a CPU
 	 * hotplug
 	 */
-- 
1.7.1

^ permalink raw reply related

* [PATCH 17/18] powerpc/smp: Increase vdso_data->processorCount, not just decrease it
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/smp.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index e337073..6023395 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -551,6 +551,10 @@ void __devinit start_secondary(void *unused)
 
 	secondary_cpu_time_init();
 
+#ifdef CONFIG_PPC64
+	if (system_state == SYSTEM_RUNNING)
+		vdso_data->processorCount++;
+#endif
 	ipi_call_lock();
 	notify_cpu_starting(cpu);
 	set_cpu_online(cpu, true);
-- 
1.7.1

^ permalink raw reply related

* [PATCH 12/18] powerpc/pmac: Rename cpu_state in therm_pm72 to avoid collision
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

This collides with the cpu_state in our SMP code, use processor_state
instead.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 drivers/macintosh/therm_pm72.c |   60 ++++++++++++++++++++--------------------
 1 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index f3a29f2..02b4f13 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -153,7 +153,7 @@ static struct i2c_adapter *		u3_0;
 static struct i2c_adapter *		u3_1;
 static struct i2c_adapter *		k2;
 static struct i2c_client *		fcu;
-static struct cpu_pid_state		cpu_state[2];
+static struct cpu_pid_state		processor_state[2];
 static struct basckside_pid_params	backside_params;
 static struct backside_pid_state	backside_state;
 static struct drives_pid_state		drives_state;
@@ -664,8 +664,8 @@ static int read_eeprom(int cpu, struct mpu_data *out)
 
 static void fetch_cpu_pumps_minmax(void)
 {
-	struct cpu_pid_state *state0 = &cpu_state[0];
-	struct cpu_pid_state *state1 = &cpu_state[1];
+	struct cpu_pid_state *state0 = &processor_state[0];
+	struct cpu_pid_state *state1 = &processor_state[1];
 	u16 pump_min = 0, pump_max = 0xffff;
 	u16 tmp[4];
 
@@ -717,17 +717,17 @@ static ssize_t show_##name(struct device *dev, struct device_attribute *attr, ch
 	return sprintf(buf, "%d", data);			\
 }
 
-BUILD_SHOW_FUNC_FIX(cpu0_temperature, cpu_state[0].last_temp)
-BUILD_SHOW_FUNC_FIX(cpu0_voltage, cpu_state[0].voltage)
-BUILD_SHOW_FUNC_FIX(cpu0_current, cpu_state[0].current_a)
-BUILD_SHOW_FUNC_INT(cpu0_exhaust_fan_rpm, cpu_state[0].rpm)
-BUILD_SHOW_FUNC_INT(cpu0_intake_fan_rpm, cpu_state[0].intake_rpm)
+BUILD_SHOW_FUNC_FIX(cpu0_temperature, processor_state[0].last_temp)
+BUILD_SHOW_FUNC_FIX(cpu0_voltage, processor_state[0].voltage)
+BUILD_SHOW_FUNC_FIX(cpu0_current, processor_state[0].current_a)
+BUILD_SHOW_FUNC_INT(cpu0_exhaust_fan_rpm, processor_state[0].rpm)
+BUILD_SHOW_FUNC_INT(cpu0_intake_fan_rpm, processor_state[0].intake_rpm)
 
-BUILD_SHOW_FUNC_FIX(cpu1_temperature, cpu_state[1].last_temp)
-BUILD_SHOW_FUNC_FIX(cpu1_voltage, cpu_state[1].voltage)
-BUILD_SHOW_FUNC_FIX(cpu1_current, cpu_state[1].current_a)
-BUILD_SHOW_FUNC_INT(cpu1_exhaust_fan_rpm, cpu_state[1].rpm)
-BUILD_SHOW_FUNC_INT(cpu1_intake_fan_rpm, cpu_state[1].intake_rpm)
+BUILD_SHOW_FUNC_FIX(cpu1_temperature, processor_state[1].last_temp)
+BUILD_SHOW_FUNC_FIX(cpu1_voltage, processor_state[1].voltage)
+BUILD_SHOW_FUNC_FIX(cpu1_current, processor_state[1].current_a)
+BUILD_SHOW_FUNC_INT(cpu1_exhaust_fan_rpm, processor_state[1].rpm)
+BUILD_SHOW_FUNC_INT(cpu1_intake_fan_rpm, processor_state[1].intake_rpm)
 
 BUILD_SHOW_FUNC_FIX(backside_temperature, backside_state.last_temp)
 BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm)
@@ -919,8 +919,8 @@ static void do_cpu_pid(struct cpu_pid_state *state, s32 temp, s32 power)
 
 static void do_monitor_cpu_combined(void)
 {
-	struct cpu_pid_state *state0 = &cpu_state[0];
-	struct cpu_pid_state *state1 = &cpu_state[1];
+	struct cpu_pid_state *state0 = &processor_state[0];
+	struct cpu_pid_state *state1 = &processor_state[1];
 	s32 temp0, power0, temp1, power1;
 	s32 temp_combi, power_combi;
 	int rc, intake, pump;
@@ -1150,7 +1150,7 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state)
 /*
  * Initialize the state structure for one CPU control loop
  */
-static int init_cpu_state(struct cpu_pid_state *state, int index)
+static int init_processor_state(struct cpu_pid_state *state, int index)
 {
 	int err;
 
@@ -1205,7 +1205,7 @@ static int init_cpu_state(struct cpu_pid_state *state, int index)
 /*
  * Dispose of the state data for one CPU control loop
  */
-static void dispose_cpu_state(struct cpu_pid_state *state)
+static void dispose_processor_state(struct cpu_pid_state *state)
 {
 	if (state->monitor == NULL)
 		return;
@@ -1804,9 +1804,9 @@ static int main_control_loop(void *x)
 		set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
 
 	/* Initialize ADCs */
-	initialize_adc(&cpu_state[0]);
-	if (cpu_state[1].monitor != NULL)
-		initialize_adc(&cpu_state[1]);
+	initialize_adc(&processor_state[0]);
+	if (processor_state[1].monitor != NULL)
+		initialize_adc(&processor_state[1]);
 
 	fcu_tickle_ticks = FCU_TICKLE_TICKS;
 
@@ -1833,14 +1833,14 @@ static int main_control_loop(void *x)
 		if (cpu_pid_type == CPU_PID_TYPE_COMBINED)
 			do_monitor_cpu_combined();
 		else if (cpu_pid_type == CPU_PID_TYPE_RACKMAC) {
-			do_monitor_cpu_rack(&cpu_state[0]);
-			if (cpu_state[1].monitor != NULL)
-				do_monitor_cpu_rack(&cpu_state[1]);
+			do_monitor_cpu_rack(&processor_state[0]);
+			if (processor_state[1].monitor != NULL)
+				do_monitor_cpu_rack(&processor_state[1]);
 			// better deal with UP
 		} else {
-			do_monitor_cpu_split(&cpu_state[0]);
-			if (cpu_state[1].monitor != NULL)
-				do_monitor_cpu_split(&cpu_state[1]);
+			do_monitor_cpu_split(&processor_state[0]);
+			if (processor_state[1].monitor != NULL)
+				do_monitor_cpu_split(&processor_state[1]);
 			// better deal with UP
 		}
 		/* Then, the rest */
@@ -1885,8 +1885,8 @@ static int main_control_loop(void *x)
  */
 static void dispose_control_loops(void)
 {
-	dispose_cpu_state(&cpu_state[0]);
-	dispose_cpu_state(&cpu_state[1]);
+	dispose_processor_state(&processor_state[0]);
+	dispose_processor_state(&processor_state[1]);
 	dispose_backside_state(&backside_state);
 	dispose_drives_state(&drives_state);
 	dispose_slots_state(&slots_state);
@@ -1928,12 +1928,12 @@ static int create_control_loops(void)
 	/* Create control loops for everything. If any fail, everything
 	 * fails
 	 */
-	if (init_cpu_state(&cpu_state[0], 0))
+	if (init_processor_state(&processor_state[0], 0))
 		goto fail;
 	if (cpu_pid_type == CPU_PID_TYPE_COMBINED)
 		fetch_cpu_pumps_minmax();
 
-	if (cpu_count > 1 && init_cpu_state(&cpu_state[1], 1))
+	if (cpu_count > 1 && init_processor_state(&processor_state[1], 1))
 		goto fail;
 	if (init_backside_state(&backside_state))
 		goto fail;
-- 
1.7.1

^ permalink raw reply related

* [PATCH 14/18] powerpc/pmac/smp: Fix CPU hotplug crashes on some machines
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

On some machines that use i2c to synchronize the timebases (such
as PowerMac7,2/7,3 G5 machines), hotplug CPU would crash when
putting back a new CPU online due to the underlying i2c bus being
closed.

This uses the newly added bringup_done() callback to move the close
along with other housekeeping calls, and adds a CPU notifier to
re-open the i2c bus around subsequent hotplug operations

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powermac/smp.c |   71 +++++++++++++++++++++++++-------
 1 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 837989e..74a43c6 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -840,30 +840,68 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
 
 	/* Setup openpic */
 	mpic_setup_this_cpu();
+}
 
-	if (cpu_nr == 0) {
-#ifdef CONFIG_PPC64
-		extern void g5_phy_disable_cpu1(void);
+#ifdef CONFIG_HOTPLUG_CPU
+static int smp_core99_cpu_notify(struct notifier_block *self,
+				 unsigned long action, void *hcpu)
+{
+	int rc;
 
-		/* Close i2c bus if it was used for tb sync */
+	switch(action) {
+	case CPU_UP_PREPARE:
+	case CPU_UP_PREPARE_FROZEN:
+		/* Open i2c bus if it was used for tb sync */
 		if (pmac_tb_clock_chip_host) {
-			pmac_i2c_close(pmac_tb_clock_chip_host);
-			pmac_tb_clock_chip_host	= NULL;
+			rc = pmac_i2c_open(pmac_tb_clock_chip_host, 1);
+			if (rc) {
+				pr_err("Failed to open i2c bus for time sync\n");
+				return notifier_from_errno(rc);
+			}
 		}
+		break;
+	case CPU_ONLINE:
+	case CPU_UP_CANCELED:
+		/* Close i2c bus if it was used for tb sync */
+		if (pmac_tb_clock_chip_host)
+			pmac_i2c_close(pmac_tb_clock_chip_host);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
 
-		/* If we didn't start the second CPU, we must take
-		 * it off the bus
-		 */
-		if (of_machine_is_compatible("MacRISC4") &&
-		    num_online_cpus() < 2)		
-			g5_phy_disable_cpu1();
-#endif /* CONFIG_PPC64 */
+static struct notifier_block __cpuinitdata smp_core99_cpu_nb = {
+	.notifier_call	= smp_core99_cpu_notify,
+};
+#endif /* CONFIG_HOTPLUG_CPU */
 
-		if (ppc_md.progress)
-			ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+static void __init smp_core99_bringup_done(void)
+{
+#ifdef CONFIG_PPC64
+	extern void g5_phy_disable_cpu1(void);
+
+	/* Close i2c bus if it was used for tb sync */
+	if (pmac_tb_clock_chip_host)
+		pmac_i2c_close(pmac_tb_clock_chip_host);
+
+	/* If we didn't start the second CPU, we must take
+	 * it off the bus.
+	 */
+	if (of_machine_is_compatible("MacRISC4") &&
+	    num_online_cpus() < 2) {
+		set_cpu_present(1, false);
+		g5_phy_disable_cpu1();
 	}
-}
+#endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_HOTPLUG_CPU
+	register_cpu_notifier(&smp_core99_cpu_nb);
+#endif
+	if (ppc_md.progress)
+		ppc_md.progress("smp_core99_bringup_done", 0x349);
+}
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -940,6 +978,7 @@ static void pmac_cpu_die(void)
 struct smp_ops_t core99_smp_ops = {
 	.message_pass	= smp_mpic_message_pass,
 	.probe		= smp_core99_probe,
+	.bringup_done	= smp_core99_bringup_done,
 	.kick_cpu	= smp_core99_kick_cpu,
 	.setup_cpu	= smp_core99_setup_cpu,
 	.give_timebase	= smp_core99_give_timebase,
-- 
1.7.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox