* 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
* [PATCH 11/18] powerpc/pmac/smp: Properly NAP offlined CPU on G5
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 current code soft-disables, and then goes to NAP mode which
turns interrupts on. That means that if an interrupt occurs, we
will hit the masked interrupt code path which isn't what we want,
as it will return with EE off, which will either get us out of
NAP mode, or fail to enter it (according to spec).
Instead, let's just rely on the fact that it is safe to take
decrementer interrupts on an offline CPU and leave interrupts
enabled. We can also get rid of the special case in asm for
power4_cpu_offline_powersave() and just use power4_idle().
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/machdep.h | 1 -
arch/powerpc/kernel/head_64.S | 7 +++++++
arch/powerpc/kernel/idle_power4.S | 21 ---------------------
arch/powerpc/platforms/powermac/smp.c | 14 ++++++++------
4 files changed, 15 insertions(+), 28 deletions(-)
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index bcfc0da..578d330 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -266,7 +266,6 @@ struct machdep_calls {
extern void e500_idle(void);
extern void power4_idle(void);
-extern void power4_cpu_offline_powersave(void);
extern void ppc6xx_idle(void);
extern void book3e_idle(void);
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 782f23d..271140b 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -536,6 +536,13 @@ _GLOBAL(pmac_secondary_start)
add r13,r13,r4 /* for this processor. */
mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG*/
+ /* Mark interrupts soft and hard disabled (they might be enabled
+ * in the PACA when doing hotplug)
+ */
+ li r0,0
+ stb r0,PACASOFTIRQEN(r13)
+ stb r0,PACAHARDIRQEN(r13)
+
/* Create a temp kernel stack for use before relocation is on. */
ld r1,PACAEMERGSP(r13)
subi r1,r1,STACK_FRAME_OVERHEAD
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index 5328709..ba31954 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -53,24 +53,3 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
isync
b 1b
-_GLOBAL(power4_cpu_offline_powersave)
- /* Go to NAP now */
- mfmsr r7
- rldicl r0,r7,48,1
- rotldi r0,r0,16
- mtmsrd r0,1 /* hard-disable interrupts */
- li r0,1
- li r6,0
- stb r0,PACAHARDIRQEN(r13) /* we'll hard-enable shortly */
- stb r6,PACASOFTIRQEN(r13) /* soft-disable irqs */
-BEGIN_FTR_SECTION
- DSSALL
- sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
- ori r7,r7,MSR_EE
- oris r7,r7,MSR_POW@h
- sync
- isync
- mtmsrd r7
- isync
- blr
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 53bee66..837989e 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -916,18 +916,20 @@ static void pmac_cpu_die(void)
preempt_enable();
/*
- * hard-disable interrupts for the non-NAP case, the NAP code
- * needs to re-enable interrupts (but soft-disables them)
+ * 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.
+ * We shouldn't get any external interrupts, only decrementer, and the
+ * decrementer handler is safe for use on offline CPUs
*/
- hard_irq_disable();
+ local_irq_enable();
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();
+ /* Enter NAP mode */
+ power4_idle();
}
}
--
1.7.1
^ permalink raw reply related
* RE: [PATCH][v2] driver/FSL SATA:Fix wrong Device Error Register usage
From: David Laight @ 2011-03-08 11:39 UTC (permalink / raw)
To: Prabhakar Kushwaha, linux-ide
Cc: meet2prabhu, Ashish Kalra, jgarzik, linuxppc-dev
In-Reply-To: <1299555095-2967-1-git-send-email-prabhakar@freescale.com>
=20
> Case when ffs return will never arise.This scenario is=20
> already been discussed
> on linuxppc-dev@lists.ozlabs.org. Please see below explanation:
> sata_fsl_error_intr() is called during device error.The=20
> mentioned scenario
> will never comes. It can be observed via code:-
> if (cereg) { --> cereg is set on command error.=20
> Means there is at least 1 device present.
This all relies on the hardware working properly, and
nothing else accidentally clearing the device 'error'
bit mask.
Being slightly defensive when the out of range value
causes an array subscript error seems sensible.
It isn't as though the code size or execution time
matters here.
David
^ permalink raw reply
* Re: Mpc8315erdb openvpn segmentation fault
From: Scott Wood @ 2011-03-08 18:52 UTC (permalink / raw)
To: Vasanth Ragavendran; +Cc: linuxppc-dev
In-Reply-To: <31094242.post@talk.nabble.com>
On Mon, 7 Mar 2011 20:28:32 -0800
Vasanth Ragavendran <ragavendrapec@yahoo.co.in> wrote:
>
> 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.
Yes, you should create a filesystem (e.g. jffs2) on a flash partition.
-Scott
^ permalink raw reply
* Re: RFC: x86: kill binutils 2.16.x?
From: Kyle Moffett @ 2011-03-08 19:57 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kbuild, Kumar Gala, Linux Kernel Mailing List, Kyle Moffett,
H. Peter Anvin, Thomas Gleixner, linuxppc-dev, Andrew Morton
In-Reply-To: <20110303083035.GB14854@elte.hu>
On Thu, Mar 3, 2011 at 03:30, Ingo Molnar <mingo@elte.hu> wrote:
> This is how specific GAS functionality is tested in arch/powerpc:
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0@if ! /bin/echo dssall | $(AS) -many -o $(TOUT=
) >/dev/null 2>&1 ; then \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0echo -n '*** ${VER=
SION}.${PATCHLEVEL} kernels no longer build ' ; \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0echo 'correctly wi=
th old versions of binutils.' ; \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0echo '*** Please u=
pgrade your binutils to 2.12.1 or newer' ; \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0false ; \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0fi
>
> This would also be a 'constructive' (and safest) way of blacklisting binu=
tils: we'd
> really only exclude binutils that is truly buggy.
Hrm... well... actually...
It's funny that you brought up this particular case. While I agree
that it's good in general, it's causing problems for me building a
kernel using a recent e500 gcc/binutils (triplet
"powerpc-linux-gnuspe").
Specifically the e500 doesn't have a normal PowerPC FPU, it has a
custom FPU built using extended integer registers instead, and it
happens to borrow the AltiVec opcode range to do it.
When trying to port Debian to the platform we were getting SIGILL's
all over the place until binutils got updated to reject all of the
unsupported opcodes on this particular platform. Now of course we get
build errors, but that's a lot easier to debug and fix. :-D
Basically, binutils no longer supports "-many" (because too many
opcodes conflict), and the test itself would fail anyways (because
"dssall" is not valid on "any" PowerPC).
So while I think that it is entirely reasonable to add a similar test
for buggy x86 binutils, I'm actually about to send a patch to remove
that particular check from the powerpc Makefile. Since the "required"
binutils 2.12.1 was released in May 2002 (almost 9 years ago) it's
probably not even worth testing for anymore.
Cheers,
Kyle Moffett
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox