From 7563dc64585324f443f5ac107eb6d89ee813a2d2 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Tue, 2 Sep 2008 16:50:38 +1000 Subject: powerpc: Work around gcc's -fno-omit-frame-pointer bug This bug is causing random crashes (http://bugzilla.kernel.org/show_bug.cgi?id=11414). -fno-omit-frame-pointer is only needed on powerpc when -pg is also supplied, and there is a gcc bug that causes incorrect code generation on 32-bit powerpc when -fno-omit-frame-pointer is used---it uses stack locations below the stack pointer, which is not allowed by the ABI because those locations can and sometimes do get corrupted by an interrupt. This ensures that CONFIG_FRAME_POINTER is only selected by ftrace. When CONFIG_FTRACE is enabled we also pass -mno-sched-epilog to work around the gcc codegen bug. Patch based on work by: Andreas Schwab Segher Boessenkool Signed-off-by: Tony Breeds Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/powermac/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index 58ecdd72630..be60d64be7a 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile @@ -2,7 +2,7 @@ CFLAGS_bootx_init.o += -fPIC ifdef CONFIG_FTRACE # Do not trace early boot code -CFLAGS_REMOVE_bootx_init.o = -pg +CFLAGS_REMOVE_bootx_init.o = -pg -mno-sched-epilog endif obj-y += pic.o setup.o time.o feature.o pci.o \ -- cgit v1.2.3 From 9f43e3914dceb0f8191875b3cdf4325b48d0d70a Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 2 Sep 2008 11:57:09 +1000 Subject: powerpc/spufs: Fix multiple get_spu_context() Commit 8d5636fbca202f61fdb808fc9e20c0142291d802 introduced a reference count on SPU contexts during find_victim, but this may cause a leak in the reference count if we later find a better contender for a context to unschedule. Change the reference to after we've found our victim context, so we don't do the extra get_spu_context(). Signed-off-by: Jeremy Kerr --- arch/powerpc/platforms/cell/spufs/sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 1c1b627ee84..9bb45c6b839 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -643,9 +643,10 @@ static struct spu *find_victim(struct spu_context *ctx) !(tmp->flags & SPU_CREATE_NOSCHED) && (!victim || tmp->prio > victim->prio)) { victim = spu->ctx; - get_spu_context(victim); } } + if (victim) + get_spu_context(victim); mutex_unlock(&cbe_spu_info[node].list_mutex); if (victim) { -- cgit v1.2.3 From b65fe0356b5b732d7e1e0224c6a1cf2eb5255984 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 4 Sep 2008 15:02:47 +1000 Subject: powerpc/spufs: Fix race for a free SPU We currently have a race for a free SPE. With one thread doing a spu_yield(), and another doing a spu_activate(): thread 1 thread 2 spu_yield(oldctx) spu_activate(ctx) __spu_deactivate(oldctx) spu_unschedule(oldctx, spu) spu->alloc_state = SPU_FREE spu = spu_get_idle(ctx) - searches for a SPE in state SPU_FREE, gets the context just freed by thread 1 spu_schedule(ctx, spu) spu->alloc_state = SPU_USED spu_schedule(newctx, spu) - assumes spu is still free - tries to schedule context on already-used spu This change introduces a 'free_spu' flag to spu_unschedule, to indicate whether or not the function should free the spu after descheduling the context. We only set this flag if we're not going to re-schedule another context on this SPU. Add a comment to document this behaviour. Signed-off-by: Jeremy Kerr --- arch/powerpc/platforms/cell/spufs/sched.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 9bb45c6b839..897c7406116 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -732,13 +732,28 @@ static void spu_schedule(struct spu *spu, struct spu_context *ctx) spu_release(ctx); } -static void spu_unschedule(struct spu *spu, struct spu_context *ctx) +/** + * spu_unschedule - remove a context from a spu, and possibly release it. + * @spu: The SPU to unschedule from + * @ctx: The context currently scheduled on the SPU + * @free_spu Whether to free the SPU for other contexts + * + * Unbinds the context @ctx from the SPU @spu. If @free_spu is non-zero, the + * SPU is made available for other contexts (ie, may be returned by + * spu_get_idle). If this is zero, the caller is expected to schedule another + * context to this spu. + * + * Should be called with ctx->state_mutex held. + */ +static void spu_unschedule(struct spu *spu, struct spu_context *ctx, + int free_spu) { int node = spu->node; mutex_lock(&cbe_spu_info[node].list_mutex); cbe_spu_info[node].nr_active--; - spu->alloc_state = SPU_FREE; + if (free_spu) + spu->alloc_state = SPU_FREE; spu_unbind_context(spu, ctx); ctx->stats.invol_ctx_switch++; spu->stats.invol_ctx_switch++; @@ -838,7 +853,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) if (spu) { new = grab_runnable_context(max_prio, spu->node); if (new || force) { - spu_unschedule(spu, ctx); + spu_unschedule(spu, ctx, new == NULL); if (new) { if (new->flags & SPU_CREATE_NOSCHED) wake_up(&new->stop_wq); @@ -911,7 +926,7 @@ static noinline void spusched_tick(struct spu_context *ctx) new = grab_runnable_context(ctx->prio + 1, spu->node); if (new) { - spu_unschedule(spu, ctx); + spu_unschedule(spu, ctx, 0); if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags)) spu_add_to_rq(ctx); } else { -- cgit v1.2.3 From b2e601d14deb2083e2a537b47869ab3895d23a28 Mon Sep 17 00:00:00 2001 From: Andre Detsch Date: Thu, 4 Sep 2008 21:16:27 +0000 Subject: powerpc/spufs: Fix possible scheduling of a context to multiple SPEs We currently have a race when scheduling a context to a SPE - after we have found a runnable context in spusched_tick, the same context may have been scheduled by spu_activate(). This may result in a panic if we try to unschedule a context that has been freed in the meantime. This change exits spu_schedule() if the context has already been scheduled, so we don't end up scheduling it twice. Signed-off-by: Andre Detsch Signed-off-by: Jeremy Kerr --- arch/powerpc/platforms/cell/spufs/sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 897c7406116..67595bc380d 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -728,7 +728,8 @@ static void spu_schedule(struct spu *spu, struct spu_context *ctx) /* not a candidate for interruptible because it's called either from the scheduler thread or from spu_deactivate */ mutex_lock(&ctx->state_mutex); - __spu_schedule(spu, ctx); + if (ctx->state == SPU_STATE_SAVED) + __spu_schedule(spu, ctx); spu_release(ctx); } -- cgit v1.2.3 From 1fce2d01dff65a76cd08c1b145acd9d3c20021d2 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 2 Oct 2008 00:58:49 -0500 Subject: powerpc: Fix boot hang regression on MPC8544DS Commit 00c5372d37a78990c1530184a9c792ee60a30067 caused the MPC8544DS board to hang at boot. The MPC8544DS is unique in that it doesn't use the PCI slots on the ULI (unlike the MPC8572DS or MPC8610HPCD). So the dummy read at the end of the address space causes us to hang. We can detect the situation by comparing the bridge's BARs versus the root complex. Signed-off-by: Kumar Gala --- arch/powerpc/platforms/fsl_uli1575.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c index ef74a0763ec..8c619963bec 100644 --- a/arch/powerpc/platforms/fsl_uli1575.c +++ b/arch/powerpc/platforms/fsl_uli1575.c @@ -219,11 +219,21 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev) int i; u8 *dummy; struct pci_bus *bus = dev->bus; + resource_size_t end = 0; + + for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCES+3; i++) { + unsigned long flags = pci_resource_flags(dev, i); + if ((flags & (IORESOURCE_MEM|IORESOURCE_PREFETCH)) == IORESOURCE_MEM) + end = pci_resource_end(dev, i); + } for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { if ((bus->resource[i]) && (bus->resource[i]->flags & IORESOURCE_MEM)) { - dummy = ioremap(bus->resource[i]->end - 3, 0x4); + if (bus->resource[i]->end == end) + dummy = ioremap(bus->resource[i]->start, 0x4); + else + dummy = ioremap(bus->resource[i]->end - 3, 0x4); if (dummy) { in_8(dummy); iounmap(dummy); -- cgit v1.2.3 From 18ee49ddb0d242ed1d0e273038d5e4f6de7379d3 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 1 Oct 2008 15:41:33 +0000 Subject: phylib: rename mii_bus::dev to mii_bus::parent In preparation of giving mii_bus objects a device tree presence of their own, rename struct mii_bus's ->dev argument to ->parent, since having a 'struct device *dev' that points to our parent device conflicts with introducing a 'struct device dev' representing our own device. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller Acked-by: Andy Fleming --- arch/powerpc/platforms/82xx/ep8248e.c | 2 +- arch/powerpc/platforms/pasemi/gpio_mdio.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c index d5770fdf7f0..0eb6d7f6224 100644 --- a/arch/powerpc/platforms/82xx/ep8248e.c +++ b/arch/powerpc/platforms/82xx/ep8248e.c @@ -137,7 +137,7 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev, bus->irq[i] = -1; bus->name = "ep8248e-mdio-bitbang"; - bus->dev = &ofdev->dev; + bus->parent = &ofdev->dev; snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start); return mdiobus_register(bus); diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index ab6955412ba..798c7abe160 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -272,7 +272,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, prop = of_get_property(np, "mdio-pin", NULL); priv->mdio_pin = *prop; - new_bus->dev = dev; + new_bus->parent = dev; dev_set_drvdata(dev, new_bus); err = mdiobus_register(new_bus); -- cgit v1.2.3 From ec2a5652ea53c102306f08cdf516f98e32bd4b61 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 9 Oct 2008 09:45:04 -0700 Subject: phylib: two dynamic mii_bus allocation fallout fixes 1. arch/powerpc/platforms/pasemi/gpio_mdio.c also needs to be converted over to mdiobus_{alloc,free}(). 2. drivers/net/phy/fixed.c used to embed a struct mii_bus into its struct fixed_mdio_bus and then use container_of() to go from the former to the latter. Since mii bus structures are no longer embedded, we need to do something like use the mii bus private pointer to go from mii_bus to fixed_mdio_bus instead. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- arch/powerpc/platforms/pasemi/gpio_mdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index 798c7abe160..75cc165d5be 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -230,7 +230,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, if (!priv) goto out; - new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); + new_bus = mdiobus_alloc(); if (!new_bus) goto out_free_priv; @@ -306,7 +306,7 @@ static int gpio_mdio_remove(struct of_device *dev) kfree(bus->priv); bus->priv = NULL; - kfree(bus); + mdiobus_free(bus); return 0; } -- cgit v1.2.3