LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [HOW] binutils-2.17 breaks the 2.6.26 kernel
From: Jon Smirl @ 2008-07-17  0:38 UTC (permalink / raw)
  To: Milton Miller; +Cc: ppcdev, Alan Modra
In-Reply-To: <1dce2aab6509053e60f7a59a30974749@bga.com>

On 7/16/08, Milton Miller <miltonm@bga.com> wrote:
> Hi.

Previous threads have mentioned that binutil-2.17 is broken for
building powerpc kernels. It is fixed in binutils-2.18.

I have encountered this and upgrading to 2.18 fixed my build. The
symptom is large kernel sizes and a long time in gzip. In my case it
was gziping a 2GB file.

>
>  I've been working with Debian bintuils 2.17-3 (which identifies
>  itself as 2.17) on my build box for some time.
>
>  When testing all-yes-config, I was getting warnings, but the
>  vmlinux was booting via kexec.
>
>  Since I was replicating the warnings from BFD about section lmas
>  overlapping in vmlinux.strip.$$, I was encouraged to actually try
>  booting the resulting stripped kernel.  After a false start (getting
>  the old binary) I ended up replicating the fail-to-boot some people
>  have reported on linuxppc-dev.
>
>  Digging into the failure, we were trying to copy *way* too much data
>  in copy_and_flush from after_prom.   I found the value loaded from
>  _klimit was something like 0x00002fea_00400000, not quite _end that
>  it was initialized.
>
>  I tracked this down to the .rodata and all sections following loosing
>  the inter-section alignment.
>
>
>  /DISCARD/ {
>   ....
>  }
>  text: AT( .text - LOAD_OFFSET): {
>   ....
>  }
>
>  . = ALIGN(0x1000)   /* this align directive aparently gets lost
>                        when stripping the file */
>
>  .rodata: AT (.rodata - LOAD_OFFSET): {
>   ...
>  }
>
>  the effects of that align were dropped during strip, shifting all
>  following sections up in memory and the resulting failure.
>
>  I don't know if the fault is ld or strip.
>
>  The behavior came between 2.6.24 and -next-20080710, but others
>  have suggested their kernels don't boot in the 2.6.25 to 2.6.26
>  transition, and a likely candidate is the addition of AT(x) to
>  set the lma, although we also switched form TEXT_TEXT macro in
>  include/asm-generic.h to a hand-rolled .text section.
>
>  Can we come up with a workaround?
>
>  thanks,
>  milton
>
>  _______________________________________________
>  Linuxppc-dev mailing list
>  Linuxppc-dev@ozlabs.org
>  https://ozlabs.org/mailman/listinfo/linuxppc-dev
>


-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* Re: [HOW] binutils-2.17 breaks the 2.6.26 kernel
From: Gabriel Paubert @ 2008-07-17  0:49 UTC (permalink / raw)
  To: Jon Smirl; +Cc: ppcdev, Alan Modra, Milton Miller
In-Reply-To: <9e4733910807161738g58da8bd7v78e9d50dc4d846cb@mail.gmail.com>

On Wed, Jul 16, 2008 at 08:38:14PM -0400, Jon Smirl wrote:
> On 7/16/08, Milton Miller <miltonm@bga.com> wrote:
> > Hi.
> 
> Previous threads have mentioned that binutil-2.17 is broken for
> building powerpc kernels. It is fixed in binutils-2.18.
> 
> I have encountered this and upgrading to 2.18 fixed my build. The
> symptom is large kernel sizes and a long time in gzip. In my case it
> was gziping a 2GB file.

Only? Mine was over 3GB :-)

I've not yet had time to update the binutils (the machine has
a standard Debian Etch and I have trouble when adding Lenny
sources).

I also bisected it for fun and got 366234f6 as the culprit.

	Gabriel

^ permalink raw reply

* Re: [PATCH] Add AMCC Arches 460GT eval board support to platforms/44x
From: Josh Boyer @ 2008-07-17  2:15 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, Victor Gallardo, fkan, linuxppc-embedded
In-Reply-To: <200807170058.53599.arnd@arndb.de>

On Thu, 2008-07-17 at 00:58 +0200, Arnd Bergmann wrote:
> On Wednesday 16 July 2008, Grant Likely wrote:
> > 
> > > Shouldn't it be enough to have a common compatible value in each
> > > of these boards, e.g. "amcc,generic-ppc44x" and then just ignore the
> > > specific type unless you need to do something special?
> > 
> > This is bad for the same reason that "amcc,44x-<blah>" compatible values
> > are bad in device nodes.  The definition of '*-44x-*' changes over time as
> > new parts are added.  Compatible values should always reflect an exact
> > part number.
> 
> I agree in general, but I also think that all 44x boards should be
> regarded as the same machine time, in the same way that all powermacs
> are detected as compatible with "Power Macintosh" or "MacRISC", or
> how all sorts of serial ports claim compatibility with i8250.
> 
> For classic SOCs like 4xx or 52xx, the SOC familiy more or less defines
> the platform, and all the details about peripherals can be expressed
> in the device tree elsewhere.

This is what Grant has done for 52xx and what I was talking about with
"4xx_board.c", though 4xx_soc.c is probably a better name.

My hesitation is that while it's true today that 440<chip name> defines
the SoC, it might not always be.  And the Virtex boards are craziness
with the core and FPGA setup.  So we need to be careful a bit when
chosing what do "bind" to for generics.

> If one board is so different that you need a separate board setup
> in the kernel, it should simply not claim compatibility with the
> SOC platform.

Right.  Today we only have a few "overrides" in 4xx.  Namely
Canyonlands/Glacier, and Bamboo/Yosemite (Sequoia/Rainier should also
really be that way, but they aren't).  So if we decide to go to a
different scheme, it shouldn't be a big deal to switch.

josh

^ permalink raw reply

* Re: [PATCH] Add AMCC Arches 460GT eval board support to platforms/44x
From: Segher Boessenkool @ 2008-07-17  3:15 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev, Victor Gallardo, fkan, linuxppc-embedded
In-Reply-To: <20080716103752.463e00cb@zod.rchland.ibm.com>

>>> And then you don't need this file at all.  Just add a
>>> "amcc,canyonlands" string to your root node compatible property.
>>
>> No!  Don't do this because it is not true!

If the board actually _is_ compatible to the canyonlands board (it
only _adds_ stuff, doesn't change things or takes away things), it
is perfectly valid to declare it compatible, since it _is_.

In my opinion, for the root compatible value, it is also okay to
declare a board compatible if it is only "largely" compatible,
just has some little differences -- esp. if you're declaring a
board to be compatible to some reference design.  This does of
course have downsides as well.

> Meh. You're splitting hairs.  It _is_ true from a kernel perspective.

That doesn't matter.  The device tree describes the hardware, it doesn't
matter what the Linux kernel does.  For one thing, the kernel isn't
necessarily the only OS (or other client) to run with this DTS; also,
the kernel is a moving target, while the DTS can be burned into ROM.

>> Instead, add your board name to canyonlands.c in canyonlands_probe().
>> It's not the most scalable solution, but it keeps you from lying about
>> your hardware in the .dts file.
>
> That could also be done.  Frankly though, if you look at the existing
> board.c files in there now, none of them are special.  The device tree
> really provides the differences these days, not the C code.

Yes.  It would be more scalable if the platform probe code checks
the device tree for the features it expects (certain CPU, certain
interrupt controller, certain chipsets / bridges), instead of it
checking the root "compatible" property.

> I'm this
> || close to just killing them all and doing a 4xx_board.c file that
> does the right thing based on the few boards that have differences.

Oh, the kernel code even considers these things to be different
platforms?  Insane :-)


Segher

^ permalink raw reply

* Re: [PATCH] Add AMCC Arches 460GT eval board support to platforms/44x
From: Segher Boessenkool @ 2008-07-17  3:19 UTC (permalink / raw)
  To: Grant Likely
  Cc: linuxppc-dev, Victor Gallardo, fkan, Arnd Bergmann,
	linuxppc-embedded
In-Reply-To: <20080716154646.GH24045@secretlab.ca>

>> Shouldn't it be enough to have a common compatible value in each
>> of these boards, e.g. "amcc,generic-ppc44x" and then just ignore the
>> specific type unless you need to do something special?
>
> This is bad for the same reason that "amcc,44x-<blah>" compatible 
> values
> are bad in device nodes.  The definition of '*-44x-*' changes over 
> time as
> new parts are added.  Compatible values should always reflect an exact
> part number.

Erm, no.

"compatible" entries should always contain the real part name to reduce
the chance that separate parties come up with the same "compatible"
name for two different devices.

Other than that, the name really doesn't matter, it's just _some_
string that uniquely identifies a device; and the device bindings will
document what is what.

Of course, if no binding is written, it becomes a lot more important
that names have a sane value ;-)


Segher

^ permalink raw reply

* Re: [PATCH] Add AMCC Arches 460GT eval board support to platforms/44x
From: Segher Boessenkool @ 2008-07-17  3:24 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, Victor Gallardo, fkan, linuxppc-embedded
In-Reply-To: <200807170058.53599.arnd@arndb.de>

>>> Shouldn't it be enough to have a common compatible value in each
>>> of these boards, e.g. "amcc,generic-ppc44x" and then just ignore the
>>> specific type unless you need to do something special?
>>
>> This is bad for the same reason that "amcc,44x-<blah>" compatible=20
>> values
>> are bad in device nodes. =A0The definition of '*-44x-*' changes over=20=

>> time as
>> new parts are added. =A0Compatible values should always reflect an =
exact
>> part number.
>
> I agree in general, but I also think that all 44x boards should be
> regarded as the same machine time, in the same way that all powermacs
> are detected as compatible with "Power Macintosh" or "MacRISC", or
> how all sorts of serial ports claim compatibility with i8250.

And they can do that because a binding for those "compatible" names
exists, that describes exactly what it means for a device to be "i8250"
or "MacRISC" (well, in that last case, maybe such a binding exists, or
maybe it doesn't, but we don't know about it anyway, sigh).


Segher

^ permalink raw reply

* Re: [PATCH v3] leds: implement OpenFirmare GPIO LED driver
From: Grant Likely @ 2008-07-17  4:15 UTC (permalink / raw)
  To: Trent Piepho; +Cc: Stephen Rothwell, linux-kernel, linuxppc-dev, Richard Purdie
In-Reply-To: <Pine.LNX.4.64.0807161546010.12709@t2.domain.actdsltmp>

On Wed, Jul 16, 2008 at 04:18:52PM -0700, Trent Piepho wrote:
> On Tue, 15 Jul 2008, Anton Vorontsov wrote:
> > Despite leds-gpio and leds-openfirmware-gpio similar purposes, there
> > is not much code can be shared between the two drivers (both are mostly
> > driver bindings anyway).
> 
> Why can't this driver use the existing gpio-led driver?  Basically, do
> something like this:
> 
> of_gpio_leds_probe(...)
> {
>  	gpio = of_get_gpio(np, 0);
>  	label = of_get_property(np, "label", NULL);
> 
>  	struct gpio_led led = {
>  		.name = label,
>  		.gpio = gpio,
>  	};
> 
>  	pdev = platform_device_register_simple("leds-gpio", 0, NULL, 0);
>  	platform_device_add_data(pdev, &led, sizeof(led));
> }

Ugh; that means registering *2* 'struct device' with the kernel instead of
one.  One as a platform device and one as an of_platform device.
It's bad enough that the LED scheme we're using for OF bindings has a
separate registration for every single LED.

Now that it comes to it, I worry that this driver takes the wrong
approach.  The number of resources dedicated per LED in this driver
seems pretty loony to me (one of_platform device per LED).  The fact
that the binding specifies one node per LED makes of_platform not a very
efficient solution.

I think it would be better to have a module that scans the device tree
for LED nodes and registers a single leds-gpio platform device for the
whole lot.

Thoughts?

g.

^ permalink raw reply

* [PATCH] powerpc: Use WARN_ON(1) instead of __WARN()
From: Michael Ellerman @ 2008-07-17  4:46 UTC (permalink / raw)
  To: linuxppc-dev

__WARN() is not defined for all configs, use WARN_ON(1) instead.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/lib/feature-fixups.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 4e43702..8c5a03b 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -99,7 +99,7 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
 
 	for (; fcur < fend; fcur++) {
 		if (patch_feature_section(value, fcur)) {
-			__WARN();
+			WARN_ON(1);
 			printk("Unable to patch feature section at %p - %p" \
 				" with %p - %p\n",
 				calc_addr(fcur, fcur->start_off),
-- 
1.5.5

^ permalink raw reply related

* [PATCH] fbdev: Teaches offb about palette on radeon r5xx/r6xx
From: Benjamin Herrenschmidt @ 2008-07-17  5:05 UTC (permalink / raw)
  To: Linux Fbdev development list; +Cc: linuxppc-dev list

The offb driver already has a collection of hacks to be able to set
the palette on various chips. This adds support for r5xx/r6xx radeons.

This is needed as offb is the only console solution on these currently
and the firmware in some cases sets a really bad color palette. This
fixes using some Radeon X16xx on the Powerstation for example.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

I'm happy to merge that via the powerpc tree if there is no objection
as offb is a powerpc-only driver at this stage.

Index: linux-work/drivers/video/offb.c
===================================================================
--- linux-work.orig/drivers/video/offb.c	2008-07-14 15:57:58.000000000 +1000
+++ linux-work/drivers/video/offb.c	2008-07-15 11:12:56.000000000 +1000
@@ -47,6 +47,7 @@ enum {
 	cmap_M3B,		/* ATI Rage Mobility M3 Head B */
 	cmap_radeon,		/* ATI Radeon */
 	cmap_gxt2000,		/* IBM GXT2000 */
+	cmap_avivo,		/* ATI R5xx */
 };
 
 struct offb_par {
@@ -58,26 +59,36 @@ struct offb_par {
 
 struct offb_par default_par;
 
-    /*
-     *  Interface used by the world
-     */
-
-static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			  u_int transp, struct fb_info *info);
-static int offb_blank(int blank, struct fb_info *info);
-
 #ifdef CONFIG_PPC32
 extern boot_infos_t *boot_infos;
 #endif
 
-static struct fb_ops offb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= offb_setcolreg,
-	.fb_blank	= offb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
+/* Definitions used by the Avivo palette hack */
+#define AVIVO_DC_LUT_RW_SELECT                  0x6480
+#define AVIVO_DC_LUT_RW_MODE                    0x6484
+#define AVIVO_DC_LUT_RW_INDEX                   0x6488
+#define AVIVO_DC_LUT_SEQ_COLOR                  0x648c
+#define AVIVO_DC_LUT_PWL_DATA                   0x6490
+#define AVIVO_DC_LUT_30_COLOR                   0x6494
+#define AVIVO_DC_LUT_READ_PIPE_SELECT           0x6498
+#define AVIVO_DC_LUT_WRITE_EN_MASK              0x649c
+#define AVIVO_DC_LUT_AUTOFILL                   0x64a0
+
+#define AVIVO_DC_LUTA_CONTROL                   0x64c0
+#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE         0x64c4
+#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN        0x64c8
+#define AVIVO_DC_LUTA_BLACK_OFFSET_RED          0x64cc
+#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE         0x64d0
+#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN        0x64d4
+#define AVIVO_DC_LUTA_WHITE_OFFSET_RED          0x64d8
+
+#define AVIVO_DC_LUTB_CONTROL                   0x6cc0
+#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE         0x6cc4
+#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN        0x6cc8
+#define AVIVO_DC_LUTB_BLACK_OFFSET_RED          0x6ccc
+#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE         0x6cd0
+#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN        0x6cd4
+#define AVIVO_DC_LUTB_WHITE_OFFSET_RED          0x6cd8
 
     /*
      *  Set a single color register. The values supplied are already
@@ -160,6 +171,17 @@ static int offb_setcolreg(u_int regno, u
 		out_le32(((unsigned __iomem *) par->cmap_adr) + regno,
 			 (red << 16 | green << 8 | blue));
 		break;
+	case cmap_avivo:
+		/* Write to both LUTs for now */
+		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+		break;
 	}
 
 	return 0;
@@ -216,12 +238,59 @@ static int offb_blank(int blank, struct 
 				out_le32(((unsigned __iomem *) par->cmap_adr) + i,
 					 0);
 				break;
+			case cmap_avivo:
+				writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+				writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+				break;
 			}
 	} else
 		fb_set_cmap(&info->cmap, info);
 	return 0;
 }
 
+static int offb_set_par(struct fb_info *info)
+{
+	struct offb_par *par = (struct offb_par *) info->par;
+
+	/* On avivo, initialize palette control */
+	if (par->cmap_type == cmap_avivo) {
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_CONTROL);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_BLUE);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_GREEN);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_RED);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_BLUE);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_GREEN);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_RED);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_CONTROL);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_BLUE);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_GREEN);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_RED);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_BLUE);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_GREEN);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_RED);
+		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+	}
+	return 0;
+}
+
+static struct fb_ops offb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= offb_setcolreg,
+	.fb_set_par	= offb_set_par,
+	.fb_blank	= offb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
 
 static void __iomem *offb_map_reg(struct device_node *np, int index,
 				  unsigned long offset, unsigned long size)
@@ -245,6 +314,59 @@ static void __iomem *offb_map_reg(struct
 	return ioremap(taddr + offset, size);
 }
 
+static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
+				    const char *name, unsigned long address)
+{
+	struct offb_par *par = (struct offb_par *) info->par;
+
+	if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_r128;
+	} else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
+			  || !strncmp(name, "ATY,RageM3p12A", 14))) {
+		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_M3A;
+	} else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_M3B;
+	} else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
+		par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_radeon;
+	} else if (!strncmp(name, "ATY,", 4)) {
+		unsigned long base = address & 0xff000000UL;
+		par->cmap_adr =
+			ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
+		par->cmap_data = par->cmap_adr + 1;
+		par->cmap_type = cmap_m64;
+	} else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
+			  of_device_is_compatible(dp, "pci1014,21c"))) {
+		par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_gxt2000;
+	} else if (dp && !strncmp(name, "vga,Display-", 12)) {
+		/* Look for AVIVO initialized by SLOF */
+		struct device_node *pciparent = of_get_parent(dp);
+		const u32 *vid, *did;
+		vid = of_get_property(pciparent, "vendor-id", NULL);
+		did = of_get_property(pciparent, "device-id", NULL);
+		/* This will match most R5xx */
+		if (vid && did && *vid == 0x1002 &&
+		    ((*did >= 0x7100 && *did < 0x7800) ||
+		     (*did >= 0x9400))) {
+			par->cmap_adr = offb_map_reg(pciparent, 2, 0, 0x10000);
+			if (par->cmap_adr)
+				par->cmap_type = cmap_avivo;
+		}
+		of_node_put(pciparent);
+	}
+	info->fix.visual = (par->cmap_type != cmap_unknown) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
+}
+
 static void __init offb_init_fb(const char *name, const char *full_name,
 				int width, int height, int depth,
 				int pitch, unsigned long address,
@@ -283,6 +405,7 @@ static void __init offb_init_fb(const ch
 
 	fix = &info->fix;
 	var = &info->var;
+	info->par = par;
 
 	strcpy(fix->id, "OFfb ");
 	strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb "));
@@ -298,39 +421,9 @@ static void __init offb_init_fb(const ch
 	fix->type_aux = 0;
 
 	par->cmap_type = cmap_unknown;
-	if (depth == 8) {
-		if (dp && !strncmp(name, "ATY,Rage128", 11)) {
-			par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_r128;
-		} else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
-				  || !strncmp(name, "ATY,RageM3p12A", 14))) {
-			par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_M3A;
-		} else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
-			par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_M3B;
-		} else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
-			par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_radeon;
-		} else if (!strncmp(name, "ATY,", 4)) {
-			unsigned long base = address & 0xff000000UL;
-			par->cmap_adr =
-			    ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
-			par->cmap_data = par->cmap_adr + 1;
-			par->cmap_type = cmap_m64;
-		} else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
-				  of_device_is_compatible(dp, "pci1014,21c"))) {
-			par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_gxt2000;
-		}
-		fix->visual = (par->cmap_type != cmap_unknown) ?
-			FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
-	} else
+	if (depth == 8)
+		offb_init_palette_hacks(info, dp, name, address);
+	else
 		fix->visual = FB_VISUAL_TRUECOLOR;
 
 	var->xoffset = var->yoffset = 0;
@@ -395,7 +488,6 @@ static void __init offb_init_fb(const ch
 
 	info->fbops = &offb_ops;
 	info->screen_base = ioremap(address, fix->smem_len);
-	info->par = par;
 	info->pseudo_palette = (void *) (info + 1);
 	info->flags = FBINFO_DEFAULT | foreign_endian;
 

^ permalink raw reply

* Re: [PATCH v3] leds: implement OpenFirmare GPIO LED driver
From: Trent Piepho @ 2008-07-17  5:13 UTC (permalink / raw)
  To: Grant Likely; +Cc: Stephen Rothwell, linux-kernel, linuxppc-dev, Richard Purdie
In-Reply-To: <20080717041531.GA27243@secretlab.ca>

on Wed, 16 Jul 2008, Grant Likely wrote:
> On Wed, Jul 16, 2008 at 04:18:52PM -0700, Trent Piepho wrote:
>> On Tue, 15 Jul 2008, Anton Vorontsov wrote:
>>> Despite leds-gpio and leds-openfirmware-gpio similar purposes, there
>>> is not much code can be shared between the two drivers (both are mostly
>>> driver bindings anyway).
>>
>> Why can't this driver use the existing gpio-led driver?  Basically, do
>> something like this:
>>
>
> Ugh; that means registering *2* 'struct device' with the kernel instead of
> one.  One as a platform device and one as an of_platform device.
> It's bad enough that the LED scheme we're using for OF bindings has a
> separate registration for every single LED.

Ok, how about adding code the existing leds-gpio driver so that it can creates
LEDs from of_platform devices too?

I've made a patch to do this and it works ok.  The code added to leds-gpio is
about half what was involved in Anton's new driver.  What I did was re-factor
the existing platform device probe function to use a new function that creates
a single led.  Then a new of_platform probe function can use it too.  That way
most of the probe code is shared.  remove, suspend and resume aren't shared,
but they're short.  And the existing code to actually drive the led gets
reused as is.

There is still one of_platform device per led because of how the bindings work
(but that could be changed with new bindings), but there are zero extra
platform devices created.

Here's an example patch.  It won't apply to the git kernel as is, but should
make it clear how this works.

diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index a4a2838..12e681e 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -71,11 +71,45 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
  	return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off);
  }

+static int create_gpio_led(struct gpio_led *cur_led,
+	struct gpio_led_data *led_dat, struct device *parent,
+	int (*blink_set)(unsigned, unsigned long *, unsigned long *))
+
+{
+	int ret;
+
+	ret = gpio_request(cur_led->gpio, cur_led->name);
+	if (ret < 0)
+		return ret;
+
+	led_dat->cdev.name = cur_led->name;
+	led_dat->cdev.default_trigger = cur_led->default_trigger;
+	led_dat->gpio = cur_led->gpio;
+	led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
+	led_dat->active_low = cur_led->active_low;
+	if (blink_set) {
+		led_dat->platform_gpio_blink_set = blink_set;
+		led_dat->cdev.blink_set = gpio_blink_set;
+	}
+	led_dat->cdev.brightness_set = gpio_led_set;
+	led_dat->cdev.brightness = cur_led->start_on ? LED_FULL : LED_OFF;
+
+	gpio_direction_output(led_dat->gpio,
+			      led_dat->active_low ^ cur_led->start_on);
+
+	INIT_WORK(&led_dat->work, gpio_led_work);
+
+	ret = led_classdev_register(parent, &led_dat->cdev);
+	if (ret < 0)
+		gpio_free(led_dat->gpio);
+
+	return ret;
+}
+
  static int gpio_led_probe(struct platform_device *pdev)
  {
  	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
-	struct gpio_led *cur_led;
-	struct gpio_led_data *leds_data, *led_dat;
+	struct gpio_led_data *leds_data;
  	int i, ret = 0;

  	if (!pdata)
@@ -87,36 +121,10 @@ static int gpio_led_probe(struct platform_device *pdev)
  		return -ENOMEM;

  	for (i = 0; i < pdata->num_leds; i++) {
-		cur_led = &pdata->leds[i];
-		led_dat = &leds_data[i];
-
-		ret = gpio_request(cur_led->gpio, cur_led->name);
+		ret = create_gpio_led(&pdata->leds[i], &leds_data[i],
+				      &pdev->dev, pdata->gpio_blink_set);
  		if (ret < 0)
  			goto err;
-
-		led_dat->cdev.name = cur_led->name;
-		led_dat->cdev.default_trigger = cur_led->default_trigger;
-		led_dat->gpio = cur_led->gpio;
-		led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
-		led_dat->active_low = cur_led->active_low;
-		if (pdata->gpio_blink_set) {
-			led_dat->platform_gpio_blink_set = pdata->gpio_blink_set;
-			led_dat->cdev.blink_set = gpio_blink_set;
-		}
-		led_dat->cdev.brightness_set = gpio_led_set;
-		led_dat->cdev.brightness =
-			cur_led->start_on ? LED_FULL : LED_OFF;
-
-		gpio_direction_output(led_dat->gpio,
-				      led_dat->active_low ^ cur_led->start_on);
-
-		INIT_WORK(&led_dat->work, gpio_led_work);
-
-		ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
-		if (ret < 0) {
-			gpio_free(led_dat->gpio);
-			goto err;
-		}
  	}

  	platform_set_drvdata(pdev, leds_data);
@@ -217,3 +225,105 @@ MODULE_AUTHOR("Raphael Assenat <raph@8d.com>");
  MODULE_DESCRIPTION("GPIO LED driver");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("platform:leds-gpio");
+
+
+/* #ifdef CONFIG_LEDS_GPIO_OF */
+/* OpenFirmware bindings */
+#include <linux/of_platform.h>
+
+/* crap for old kernel, ignore */
+static inline const char *dev_name(struct device *dev)
+{ return dev->bus_id; }
+int of_get_gpio(struct device_node *np, int index)
+{ const u32 *pp = of_get_property(np, "gpio", NULL); return pp ? *pp : -1; }
+
+static int __devinit of_gpio_leds_probe(struct of_device *ofdev,
+					const struct of_device_id *match)
+{
+	struct device_node *np = ofdev->node;
+	struct gpio_led led;
+	struct gpio_led_data *led_dat;
+	int ret;
+
+	led_dat = kzalloc(sizeof(*led_dat), GFP_KERNEL);
+	if (!led_dat)
+		return -ENOMEM;
+
+	memset(&led, 0, sizeof(led));
+	led.gpio = of_get_gpio(np, 0);
+	led.name = of_get_property(np, "label", NULL);
+	if (!led.name)
+		led.name = dev_name(&ofdev->dev);
+
+	ret = create_gpio_led(&led, led_dat, &ofdev->dev, NULL);
+	if (ret < 0) {
+		kfree(led_dat);
+		return ret;
+	}
+
+	dev_set_drvdata(&ofdev->dev, led_dat);
+
+	return 0;
+}
+
+static int __devexit of_gpio_leds_remove(struct of_device *ofdev)
+{
+	struct gpio_led_data *led = dev_get_drvdata(&ofdev->dev);
+
+	led_classdev_unregister(&led->cdev);
+	cancel_work_sync(&led->work);
+	gpio_free(led->gpio);
+	kfree(led);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int of_gpio_led_suspend(struct of_device *ofdev, pm_message_t state)
+{
+	struct gpio_led_data *led = dev_get_drvdata(&ofdev->dev);
+
+	led_classdev_suspend(&led->cdev);
+	return 0;
+}
+
+static int of_gpio_led_resume(struct of_device *ofdev)
+{
+	struct gpio_led_data *led = dev_get_drvdata(&ofdev->dev);
+
+	led_classdev_resume(&led->cdev);
+	return 0;
+}
+#else
+#define of_gpio_led_suspend NULL
+#define of_gpio_led_resume NULL
+#endif /* CONFIG_PM */
+
+static const struct of_device_id of_gpio_leds_match[] = {
+	{ .compatible = "gpio-led", },
+	{},
+};
+
+static struct of_platform_driver of_gpio_leds_driver = {
+	.driver = {
+		.name = "of_gpio_leds",
+		.owner = THIS_MODULE,
+	},
+	.match_table = of_gpio_leds_match,
+	.probe = of_gpio_leds_probe,
+	.remove = __devexit_p(of_gpio_leds_remove),
+	.suspend = of_gpio_led_suspend,
+	.resume = of_gpio_led_resume,
+};
+
+static int __init of_gpio_leds_init(void)
+{
+	return of_register_platform_driver(&of_gpio_leds_driver);
+}
+module_init(of_gpio_leds_init);
+
+static void __exit of_gpio_leds_exit(void)
+{
+	of_unregister_platform_driver(&of_gpio_leds_driver);
+}
+module_exit(of_gpio_leds_exit);

^ permalink raw reply related

* Re: [PATCH] powerpc: fix support for latencytop
From: Chris Friesen @ 2008-07-17  5:30 UTC (permalink / raw)
  To: Nathan Lynch; +Cc: linuxppc-dev, Arnd Bergmann
In-Reply-To: <20080716224208.GF9594@localdomain>

Nathan Lynch wrote:
> Arnd Bergmann wrote:
> 
>>We need to pass the kernel stack pointer instead of the user space
>>stack pointer in save_stack_trace_tsk().
> 
> 
> Thanks, this fixes it, and latencytop even seems to work. :)

Sweet.  One week from mention to working in -next...not bad.

My thanks to Arnd and Nathan for implementing and testing it out.

Chris

^ permalink raw reply

* Re: [PATCH] dtc: supply a definition for YYRHSLOC if there isn't one
From: David Gibson @ 2008-07-17  5:47 UTC (permalink / raw)
  To: Paul Gortmaker; +Cc: linuxppc-dev, jdl
In-Reply-To: <1216230837-17557-1-git-send-email-paul.gortmaker@windriver.com>

On Wed, Jul 16, 2008 at 01:53:57PM -0400, Paul Gortmaker wrote:
> It seems that some machines, like a default RHEL4 install, will
> not have a definition for YYRHSLOC, and that prevents building
> dtc.  This supplies what appears to be the standard definition
> for it in the event that the host system does not have it defined.

I'm pretty uneasy about this, since it relies on knowing the internals
of how bison manages its tokens.  What version of bison is it in RHEL4
that causes the trouble?

In fact I have a feeling that the extra 'file' field in YYLTYPE never
gets used, which means we could just ditch our custom YYLLOC_DEFAULT
definition, which would be a better idea, IMO, except that we'll
probably want the file info back at some point.

Ick.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* powerpc: Fix OF parsing of 64 bits PCI addresses
From: Benjamin Herrenschmidt @ 2008-07-17  5:53 UTC (permalink / raw)
  To: linuxppc-dev list

The OF parsing code for PCI addresses isn't always treating properly
the address space indication 0b11 (ie. 0x3) as meaning 64 bits
memory space.

This means that it fails to parse addresses for PCI BARs that have
this encoding set by the firmware, which happens on some SLOF
versions and breaks offb palette handling on Powerstation.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

Index: linux-work/arch/powerpc/kernel/pci-common.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci-common.c	2008-07-17 15:09:11.000000000 +1000
+++ linux-work/arch/powerpc/kernel/pci-common.c	2008-07-17 15:09:22.000000000 +1000
@@ -598,6 +598,7 @@ void __devinit pci_process_bridge_OF_ran
 			res->start = pci_addr;
 			break;
 		case 2:		/* PCI Memory space */
+		case 3:		/* PCI 64 bits Memory space */
 			printk(KERN_INFO
 			       " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
 			       cpu_addr, cpu_addr + size - 1, pci_addr,
Index: linux-work/arch/powerpc/kernel/prom_parse.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/prom_parse.c	2008-07-17 15:06:43.000000000 +1000
+++ linux-work/arch/powerpc/kernel/prom_parse.c	2008-07-17 15:08:16.000000000 +1000
@@ -128,12 +128,35 @@ static void of_bus_pci_count_cells(struc
 		*sizec = 2;
 }
 
+static unsigned int of_bus_pci_get_flags(const u32 *addr)
+{
+	unsigned int flags = 0;
+	u32 w = addr[0];
+
+	switch((w >> 24) & 0x03) {
+	case 0x01:
+		flags |= IORESOURCE_IO;
+		break;
+	case 0x02: /* 32 bits */
+	case 0x03: /* 64 bits */
+		flags |= IORESOURCE_MEM;
+		break;
+	}
+	if (w & 0x40000000)
+		flags |= IORESOURCE_PREFETCH;
+	return flags;
+}
+
 static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
 {
 	u64 cp, s, da;
+	unsigned int af, rf;
+
+	af = of_bus_pci_get_flags(addr);
+	rf = of_bus_pci_get_flags(range);
 
 	/* Check address type match */
-	if ((addr[0] ^ range[0]) & 0x03000000)
+	if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
 		return OF_BAD_ADDR;
 
 	/* Read address values, skipping high cell */
@@ -153,25 +176,6 @@ static int of_bus_pci_translate(u32 *add
 	return of_bus_default_translate(addr + 1, offset, na - 1);
 }
 
-static unsigned int of_bus_pci_get_flags(const u32 *addr)
-{
-	unsigned int flags = 0;
-	u32 w = addr[0];
-
-	switch((w >> 24) & 0x03) {
-	case 0x01:
-		flags |= IORESOURCE_IO;
-		break;
-	case 0x02: /* 32 bits */
-	case 0x03: /* 64 bits */
-		flags |= IORESOURCE_MEM;
-		break;
-	}
-	if (w & 0x40000000)
-		flags |= IORESOURCE_PREFETCH;
-	return flags;
-}
-
 const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
 			unsigned int *flags)
 {

^ permalink raw reply

* Re: [patch 1/9] powerpc/cell/edac: log a syndrome code in case of correctable error
From: Benjamin Herrenschmidt @ 2008-07-17  5:59 UTC (permalink / raw)
  To: arnd, Doug Thompson
  Cc: Maxim Shchetynin, linuxppc-dev, cbe-oss-dev, bluesmoke-devel
In-Reply-To: <20080715195739.006221652@arndb.de>

Arnd, Maxim, please, next time, send that patch or at least CC the
bluesmoke-devel list for EDAC related bits.

Doug, if you are ok with this patch, I'll merge it via the powerpc
tree.

Cheers,
Ben.

On Tue, 2008-07-15 at 21:51 +0200, arnd@arndb.de 

> From: Maxim Shchetynin <maxim@de.ibm.com>
> 
> If correctable error occurs the syndrome code was logged as 0. This patch
> lets EDAC to log a correct syndrome code to make problem investigation
> easier.
> 
> Signed-off-by: Maxim Shchetynin <maxim@de.ibm.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/edac/cell_edac.c |    5 +++--
>  1 files changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
> index b54112f..0e024fe 100644
> --- a/drivers/edac/cell_edac.c
> +++ b/drivers/edac/cell_edac.c
> @@ -33,7 +33,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
>  {
>  	struct cell_edac_priv		*priv = mci->pvt_info;
>  	struct csrow_info		*csrow = &mci->csrows[0];
> -	unsigned long			address, pfn, offset;
> +	unsigned long			address, pfn, offset, syndrome;
>  
>  	dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016lx\n",
>  		priv->node, chan, ar);
> @@ -44,10 +44,11 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
>  		address = (address << 1) | chan;
>  	pfn = address >> PAGE_SHIFT;
>  	offset = address & ~PAGE_MASK;
> +	syndrome = (ar & 0x000000001fe00000ul) >> 21;
>  
>  	/* TODO: Decoding of the error addresss */
>  	edac_mc_handle_ce(mci, csrow->first_page + pfn, offset,
> -			  0, 0, chan, "");
> +			  syndrome, 0, chan, "");
>  }
>  
>  static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
> -- 
> 1.5.4.3
> 

^ permalink raw reply

* Re: [PATCH] leds: implement OpenFirmare GPIO LED driver
From: Segher Boessenkool @ 2008-07-17  5:59 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linuxppc-dev, Richard Purdie, linux-kernel
In-Reply-To: <20080714164114.GA18784@polina.dev.rtsoft.ru>

> diff --git a/Documentation/powerpc/dts-bindings/gpio/led.txt 
> b/Documentation/powerpc/dts-bindings/gpio/led.txt
> new file mode 100644
> index 0000000..7e9ce81
> --- /dev/null
> +++ b/Documentation/powerpc/dts-bindings/gpio/led.txt
> @@ -0,0 +1,15 @@
> +LED connected to GPIO
> +
> +Required properties:
> +- compatible : should be "gpio-led".

This "compatible" name is a bit too generic.  No, I don't know a
better name :-(

> +- label : (optional) the label for this LED. If omitted, the label is
> +  taken from the node name (excluding the unit address).

What is a label?  It should be described here.  Also, its encoding
should be described ("a string" I guess).

> +- gpios : should specify LED GPIO.
> +
> +Example:
> +
> +led@0 {
> +	compatible = "gpio-led";
> +	label = "hdd";
> +	gpios = <&mcu_pio 0 0>;
> +};

You show a unit address but have no "reg" value.  This is
incorrect.

What would be the parent node of this, btw?


Segher

^ permalink raw reply

* Re: [alsa-devel] WRITING AN SOC DRIVER WITHOUT DMA
From: dinesh @ 2008-07-17  6:03 UTC (permalink / raw)
  To: Nobin Mathew; +Cc: linuxppc-dev, alsa-devel, liam.girdwood
In-Reply-To: <1216203206.9723.0.camel@dinesh.dua>

[-- Attachment #1: Type: text/plain, Size: 1967 bytes --]

Hi,
I think no one is able to understand my problem, let me break it to low
level.
What i want is that i have a buffer in driver code which is also handled
by some other application i want that this buffer data is to be used for
capture and playback  stream fills data to another buffer which i can
passover to my other application.
If someone can help me please.
Regards,
Dinesh


-----Original Message-----
From: dinesh <dinesh.dua@coraltele.com>
To: Nobin Mathew <nobin.mathew@gmail.com>
Cc: Grant Likely <grant.likely@secretlab.ca>, linuxppc-dev@ozlabs.org,
alsa-devel@alsa-project.org, liam.girdwood@wolfsonmicro.com
Subject: Re: [alsa-devel] WRITING AN SOC DRIVER WITHOUT DMA
Date: Wed, 16 Jul 2008 15:43:26 +0530


no i am working on powerpc.     MPC8323


-----Original Message-----
From: Nobin Mathew <nobin.mathew@gmail.com>
To: dinesh <dinesh.dua@coraltele.com>
Cc: Grant Likely <grant.likely@secretlab.ca>, linuxppc-dev@ozlabs.org,
alsa-devel@alsa-project.org, liam.girdwood@wolfsonmicro.com
Subject: Re: [alsa-devel] WRITING AN SOC DRIVER WITHOUT DMA
Date: Wed, 16 Jul 2008 15:37:54 +0530


Hi dinesh,

If you are working on ARM, see the ARM AACi code, in sound/arm/aaci.c

Thanks
Nobin Mathew.


On 7/16/08, dinesh <dinesh.dua@coraltele.com> wrote:
>
> Hi,
> I am writing a soc sound driver for MPC8323 board linux 2.6.24 in which i
> want to do data transfer to and from device myself using BUFFER DESCRIPTOR
> not with the usual DMA transfer.
> Please help me.
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

[-- Attachment #2: Type: text/html, Size: 3509 bytes --]

^ permalink raw reply

* Re: [patch 7/9] azfs: initial submit of azfs, a non-buffered filesystem
From: Benjamin Herrenschmidt @ 2008-07-17  6:13 UTC (permalink / raw)
  To: arnd; +Cc: Maxim Shchetynin, linuxppc-dev, cbe-oss-dev
In-Reply-To: <20080715195739.820365109@arndb.de>

On Tue, 2008-07-15 at 21:51 +0200, arnd@arndb.de wrote:
> plain text document attachment
> (0007-azfs-initial-submit-of-azfs-a-non-buffered-filesys.patch)
> From: Maxim Shchetynin <maxim@linux.vnet.ibm.com>
> 
> AZFS is a file system which keeps all files on memory mapped random
> access storage. It was designed to work on the axonram device driver
> for IBM QS2x blade servers, but can operate on any block device
> that exports a direct_access method.
> 
> Signed-off-by: Maxim Shchetynin <maxim@de.ibm.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---

Can I get this acked by some filesystem person like Al ?

Cheers,
Ben.

>  Documentation/filesystems/azfs.txt  |   22 +
>  arch/powerpc/configs/cell_defconfig |    1 +
>  fs/Kconfig                          |   15 +
>  fs/Makefile                         |    1 +
>  fs/azfs/Makefile                    |    7 +
>  fs/azfs/inode.c                     | 1184 +++++++++++++++++++++++++++++++++++
>  6 files changed, 1230 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/filesystems/azfs.txt
>  create mode 100644 fs/azfs/Makefile
>  create mode 100644 fs/azfs/inode.c
> 
> diff --git a/Documentation/filesystems/azfs.txt b/Documentation/filesystems/azfs.txt
> new file mode 100644
> index 0000000..c4bf659
> --- /dev/null
> +++ b/Documentation/filesystems/azfs.txt
> @@ -0,0 +1,22 @@
> +AZFS is a file system which keeps all files on memory backed random
> +access storage. It was designed to work on the axonram device driver
> +for IBM QS2x blade servers, but can operate on any block device
> +that exports a direct_access method.
> +
> +Everything in AZFS is temporary in the sense that all the data stored
> +therein is lost when you switch off or reboot a system. If you unmount
> +an AZFS instance, all the data will be kept on device as long your system
> +is not shut down or rebooted. You can later mount AZFS on from device again
> +to get access to your files.
> +
> +AZFS uses a block device only for data but not for file information.
> +All inodes (file and directory information) is kept in RAM.
> +
> +When you mount AZFS you are able to specify a file system block size with
> +'-o bs=<size in bytes>' option. There are no software limitations for
> +a block size but you would not be able to mmap files on AZFS if block size
> +is less than a system page size. If no '-o bs' option is specified on mount
> +a block size of the used block device is used as a default block size for AZFS.
> +
> +Other available mount options for AZFS are '-o uid=<id>' and '-o gid=<id>',
> +which allow you to set the owner and group of the root of the file system.
> diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
> index c420e47..235a0c8 100644
> --- a/arch/powerpc/configs/cell_defconfig
> +++ b/arch/powerpc/configs/cell_defconfig
> @@ -240,6 +240,7 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
>  # CPU Frequency drivers
>  #
>  CONFIG_AXON_RAM=m
> +CONFIG_AZ_FS=m
>  # CONFIG_FSL_ULI1575 is not set
>  
>  #
> diff --git a/fs/Kconfig b/fs/Kconfig
> index 2694648..2d4e42b 100644
> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -1017,6 +1017,21 @@ config HUGETLBFS
>  config HUGETLB_PAGE
>  	def_bool HUGETLBFS
>  
> +config AZ_FS
> +	tristate "AZFS filesystem support"
> +	help
> +	  azfs is a file system for I/O attached memory backing. It requires
> +	  a block device with direct_access capability, e.g. axonram.
> +	  Mounting such device with azfs gives memory mapped access to the
> +	  underlying memory to user space.
> +
> +	  Read <file:Documentation/filesystems/azfs.txt> for details.
> +
> +	  To compile this file system support as a module, choose M here: the
> +	  module will be called azfs.
> +
> +	  If unsure, say N.
> +
>  config CONFIGFS_FS
>  	tristate "Userspace-driven configuration filesystem"
>  	depends on SYSFS
> diff --git a/fs/Makefile b/fs/Makefile
> index 1e7a11b..20e3253 100644
> --- a/fs/Makefile
> +++ b/fs/Makefile
> @@ -119,3 +119,4 @@ obj-$(CONFIG_HPPFS)		+= hppfs/
>  obj-$(CONFIG_DEBUG_FS)		+= debugfs/
>  obj-$(CONFIG_OCFS2_FS)		+= ocfs2/
>  obj-$(CONFIG_GFS2_FS)           += gfs2/
> +obj-$(CONFIG_AZ_FS)		+= azfs/
> diff --git a/fs/azfs/Makefile b/fs/azfs/Makefile
> new file mode 100644
> index 0000000..ff04d41
> --- /dev/null
> +++ b/fs/azfs/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# Makefile for azfs routines
> +#
> +
> +obj-$(CONFIG_AZ_FS) += azfs.o
> +
> +azfs-y := inode.o
> diff --git a/fs/azfs/inode.c b/fs/azfs/inode.c
> new file mode 100644
> index 0000000..00dc2af
> --- /dev/null
> +++ b/fs/azfs/inode.c
> @@ -0,0 +1,1184 @@
> +/*
> + * (C) Copyright IBM Deutschland Entwicklung GmbH 2007
> + *
> + * Author: Maxim Shchetynin <maxim@de.ibm.com>
> + *
> + * Non-buffered filesystem driver.
> + * It registers a filesystem which may be used for all kind of block devices
> + * which have a direct_access() method in block_device_operations.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2, or (at your option)
> + * any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#include <linux/backing-dev.h>
> +#include <linux/blkdev.h>
> +#include <linux/cache.h>
> +#include <linux/dcache.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/fs.h>
> +#include <linux/genhd.h>
> +#include <linux/kernel.h>
> +#include <linux/limits.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/mount.h>
> +#include <linux/mm.h>
> +#include <linux/mm_types.h>
> +#include <linux/mutex.h>
> +#include <linux/namei.h>
> +#include <linux/pagemap.h>
> +#include <linux/parser.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/stat.h>
> +#include <linux/statfs.h>
> +#include <linux/string.h>
> +#include <linux/time.h>
> +#include <linux/types.h>
> +#include <linux/aio.h>
> +#include <linux/uio.h>
> +#include <asm/bug.h>
> +#include <asm/page.h>
> +#include <asm/pgtable.h>
> +#include <asm/string.h>
> +
> +#define AZFS_FILESYSTEM_NAME		"azfs"
> +#define AZFS_FILESYSTEM_FLAGS		FS_REQUIRES_DEV
> +
> +#define AZFS_SUPERBLOCK_MAGIC		0xABBA1972
> +#define AZFS_SUPERBLOCK_FLAGS		MS_SYNCHRONOUS | \
> +					MS_DIRSYNC | \
> +					MS_ACTIVE
> +
> +#define AZFS_BDI_CAPABILITIES		BDI_CAP_NO_ACCT_DIRTY | \
> +					BDI_CAP_NO_WRITEBACK | \
> +					BDI_CAP_MAP_COPY | \
> +					BDI_CAP_MAP_DIRECT | \
> +					BDI_CAP_VMFLAGS
> +
> +#define AZFS_CACHE_FLAGS		SLAB_HWCACHE_ALIGN | \
> +					SLAB_RECLAIM_ACCOUNT | \
> +					SLAB_MEM_SPREAD
> +
> +struct azfs_super {
> +	struct list_head		list;
> +	unsigned long			media_size;
> +	unsigned long			block_size;
> +	unsigned short			block_shift;
> +	unsigned long			sector_size;
> +	unsigned short			sector_shift;
> +	uid_t				uid;
> +	gid_t				gid;
> +	unsigned long			ph_addr;
> +	unsigned long			io_addr;
> +	struct block_device		*blkdev;
> +	struct dentry			*root;
> +	struct list_head		block_list;
> +	rwlock_t			lock;
> +};
> +
> +struct azfs_super_list {
> +	struct list_head		head;
> +	spinlock_t			lock;
> +};
> +
> +struct azfs_block {
> +	struct list_head		list;
> +	unsigned long			id;
> +	unsigned long			count;
> +};
> +
> +struct azfs_znode {
> +	struct list_head		block_list;
> +	rwlock_t			lock;
> +	loff_t				size;
> +	struct inode			vfs_inode;
> +};
> +
> +static struct azfs_super_list		super_list;
> +static struct kmem_cache		*azfs_znode_cache __read_mostly = NULL;
> +static struct kmem_cache		*azfs_block_cache __read_mostly = NULL;
> +
> +#define I2S(inode) \
> +	inode->i_sb->s_fs_info
> +#define I2Z(inode) \
> +	container_of(inode, struct azfs_znode, vfs_inode)
> +
> +#define for_each_block(block, block_list) \
> +	list_for_each_entry(block, block_list, list)
> +#define for_each_block_reverse(block, block_list) \
> +	list_for_each_entry_reverse(block, block_list, list)
> +#define for_each_block_safe(block, temp, block_list) \
> +	list_for_each_entry_safe(block, temp, block_list, list)
> +#define for_each_block_safe_reverse(block, temp, block_list) \
> +	list_for_each_entry_safe_reverse(block, temp, block_list, list)
> +
> +/**
> + * azfs_block_init - create and initialise a new block in a list
> + * @block_list: destination list
> + * @id: block id
> + * @count: size of a block
> + */
> +static inline struct azfs_block*
> +azfs_block_init(struct list_head *block_list,
> +		unsigned long id, unsigned long count)
> +{
> +	struct azfs_block *block;
> +
> +	block = kmem_cache_alloc(azfs_block_cache, GFP_KERNEL);
> +	if (!block)
> +		return NULL;
> +
> +	block->id = id;
> +	block->count = count;
> +
> +	INIT_LIST_HEAD(&block->list);
> +	list_add_tail(&block->list, block_list);
> +
> +	return block;
> +}
> +
> +/**
> + * azfs_block_free - remove block from a list and free it back in cache
> + * @block: block to be removed
> + */
> +static inline void
> +azfs_block_free(struct azfs_block *block)
> +{
> +	list_del(&block->list);
> +	kmem_cache_free(azfs_block_cache, block);
> +}
> +
> +/**
> + * azfs_block_move - move block to another list
> + * @block: block to be moved
> + * @block_list: destination list
> + */
> +static inline void
> +azfs_block_move(struct azfs_block *block, struct list_head *block_list)
> +{
> +	list_move_tail(&block->list, block_list);
> +}
> +
> +/**
> + * azfs_block_find - get a block id of a part of a file
> + * @inode: inode
> + * @from: offset for read/write operation
> + * @size: pointer to a value of the amount of data to be read/written
> + */
> +static unsigned long
> +azfs_block_find(struct inode *inode, unsigned long from, unsigned long *size)
> +{
> +	struct azfs_super *super;
> +	struct azfs_znode *znode;
> +	struct azfs_block *block;
> +	unsigned long block_id, west, east;
> +
> +	super = I2S(inode);
> +	znode = I2Z(inode);
> +
> +	read_lock(&znode->lock);
> +
> +	while (from + *size > znode->size) {
> +		read_unlock(&znode->lock);
> +		i_size_write(inode, from + *size);
> +		inode->i_op->truncate(inode);
> +		read_lock(&znode->lock);
> +	}
> +
> +	if (list_empty(&znode->block_list)) {
> +		read_unlock(&znode->lock);
> +		*size = 0;
> +		return 0;
> +	}
> +
> +	block_id = from >> super->block_shift;
> +
> +	for_each_block(block, &znode->block_list) {
> +		if (block->count > block_id)
> +			break;
> +		block_id -= block->count;
> +	}
> +
> +	west = from % super->block_size;
> +	east = ((block->count - block_id) << super->block_shift) - west;
> +
> +	if (*size > east)
> +		*size = east;
> +
> +	block_id = ((block->id + block_id) << super->block_shift) + west;
> +
> +	read_unlock(&znode->lock);
> +
> +	return block_id;
> +}
> +
> +static struct inode*
> +azfs_new_inode(struct super_block *, struct inode *, int, dev_t);
> +
> +/**
> + * azfs_mknod - mknod() method for inode_operations
> + * @dir, @dentry, @mode, @dev: see inode_operations methods
> + */
> +static int
> +azfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
> +{
> +	struct inode *inode;
> +
> +	inode = azfs_new_inode(dir->i_sb, dir, mode, dev);
> +	if (!inode)
> +		return -ENOSPC;
> +
> +	if (S_ISREG(mode))
> +		I2Z(inode)->size = 0;
> +
> +	dget(dentry);
> +	d_instantiate(dentry, inode);
> +
> +	return 0;
> +}
> +
> +/**
> + * azfs_create - create() method for inode_operations
> + * @dir, @dentry, @mode, @nd: see inode_operations methods
> + */
> +static int
> +azfs_create(struct inode *dir, struct dentry *dentry, int mode,
> +	    struct nameidata *nd)
> +{
> +	return azfs_mknod(dir, dentry, mode | S_IFREG, 0);
> +}
> +
> +/**
> + * azfs_mkdir - mkdir() method for inode_operations
> + * @dir, @dentry, @mode: see inode_operations methods
> + */
> +static int
> +azfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
> +{
> +	int rc;
> +
> +	rc = azfs_mknod(dir, dentry, mode | S_IFDIR, 0);
> +	if (!rc)
> +		inc_nlink(dir);
> +
> +	return rc;
> +}
> +
> +/**
> + * azfs_symlink - symlink() method for inode_operations
> + * @dir, @dentry, @name: see inode_operations methods
> + */
> +static int
> +azfs_symlink(struct inode *dir, struct dentry *dentry, const char *name)
> +{
> +	struct inode *inode;
> +	int rc;
> +
> +	inode = azfs_new_inode(dir->i_sb, dir, S_IFLNK | S_IRWXUGO, 0);
> +	if (!inode)
> +		return -ENOSPC;
> +
> +	rc = page_symlink(inode, name, strlen(name) + 1);
> +	if (rc) {
> +		iput(inode);
> +		return rc;
> +	}
> +
> +	dget(dentry);
> +	d_instantiate(dentry, inode);
> +
> +	return 0;
> +}
> +
> +/**
> + * azfs_aio_read - aio_read() method for file_operations
> + * @iocb, @iov, @nr_segs, @pos: see file_operations methods
> + */
> +static ssize_t
> +azfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
> +	      unsigned long nr_segs, loff_t pos)
> +{
> +	struct azfs_super *super;
> +	struct inode *inode;
> +	void *target;
> +	unsigned long pin;
> +	unsigned long size, todo, step;
> +	ssize_t rc;
> +
> +	inode = iocb->ki_filp->f_mapping->host;
> +	super = I2S(inode);
> +
> +	mutex_lock(&inode->i_mutex);
> +
> +	if (pos >= i_size_read(inode)) {
> +		rc = 0;
> +		goto out;
> +	}
> +
> +	target = iov->iov_base;
> +	todo = min((loff_t) iov->iov_len, i_size_read(inode) - pos);
> +
> +	for (step = todo; step; step -= size) {
> +		size = step;
> +		pin = azfs_block_find(inode, pos, &size);
> +		if (!size) {
> +			rc = -ENOSPC;
> +			goto out;
> +		}
> +		pin += super->io_addr;
> +		/*
> +		 * FIXME: pin is actually an __iomem pointer, is
> +		 * that safe? -arnd
> +		 */
> +		if (copy_to_user(target, (void*) pin, size)) {
> +			rc = -EFAULT;
> +			goto out;
> +		}
> +
> +		iocb->ki_pos += size;
> +		pos += size;
> +		target += size;
> +	}
> +
> +	rc = todo;
> +
> +out:
> +	mutex_unlock(&inode->i_mutex);
> +
> +	return rc;
> +}
> +
> +/**
> + * azfs_aio_write - aio_write() method for file_operations
> + * @iocb, @iov, @nr_segs, @pos: see file_operations methods
> + */
> +static ssize_t
> +azfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
> +	       unsigned long nr_segs, loff_t pos)
> +{
> +	struct azfs_super *super;
> +	struct inode *inode;
> +	void *source;
> +	unsigned long pin;
> +	unsigned long size, todo, step;
> +	ssize_t rc;
> +
> +	inode = iocb->ki_filp->f_mapping->host;
> +	super = I2S(inode);
> +
> +	source = iov->iov_base;
> +	todo = iov->iov_len;
> +
> +	mutex_lock(&inode->i_mutex);
> +
> +	for (step = todo; step; step -= size) {
> +		size = step;
> +		pin = azfs_block_find(inode, pos, &size);
> +		if (!size) {
> +			rc = -ENOSPC;
> +			goto out;
> +		}
> +		pin += super->io_addr;
> +		/*
> +		 * FIXME: pin is actually an __iomem pointer, is
> +		 * that safe? -arnd
> +		 */
> +		if (copy_from_user((void*) pin, source, size)) {
> +			rc = -EFAULT;
> +			goto out;
> +		}
> +
> +		iocb->ki_pos += size;
> +		pos += size;
> +		source += size;
> +	}
> +
> +	rc = todo;
> +
> +out:
> +	mutex_unlock(&inode->i_mutex);
> +
> +	return rc;
> +}
> +
> +/**
> + * azfs_open - open() method for file_operations
> + * @inode, @file: see file_operations methods
> + */
> +static int
> +azfs_open(struct inode *inode, struct file *file)
> +{
> +	if (file->f_flags & O_TRUNC) {
> +		i_size_write(inode, 0);
> +		inode->i_op->truncate(inode);
> +	}
> +	if (file->f_flags & O_APPEND)
> +		inode->i_fop->llseek(file, 0, SEEK_END);
> +
> +	return 0;
> +}
> +
> +/**
> + * azfs_mmap - mmap() method for file_operations
> + * @file, @vm: see file_operations methods
> + */
> +static int
> +azfs_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> +	struct azfs_super *super;
> +	struct azfs_znode *znode;
> +	struct inode *inode;
> +	unsigned long cursor, pin;
> +	unsigned long todo, size, vm_start;
> +	pgprot_t page_prot;
> +
> +	inode = file->f_dentry->d_inode;
> +	znode = I2Z(inode);
> +	super = I2S(inode);
> +
> +	if (super->block_size < PAGE_SIZE)
> +		return -EINVAL;
> +
> +	cursor = vma->vm_pgoff << super->block_shift;
> +	todo = vma->vm_end - vma->vm_start;
> +
> +	if (cursor + todo > i_size_read(inode))
> +		return -EINVAL;
> +
> +	page_prot = pgprot_val(vma->vm_page_prot);
> +#ifdef CONFIG_PPC
> +	page_prot |= (_PAGE_NO_CACHE | _PAGE_RW);
> +	page_prot &= ~_PAGE_GUARDED;
> +#else
> +	page_prot = pgprot_noncached(page_prot);
> +#endif
> +	vma->vm_page_prot = __pgprot(page_prot);
> +
> +	vm_start = vma->vm_start;
> +	for (size = todo; todo; todo -= size, size = todo) {
> +		pin = azfs_block_find(inode, cursor, &size);
> +		if (!size)
> +			return -EAGAIN;
> +		pin += super->ph_addr;
> +		pin >>= PAGE_SHIFT;
> +		if (remap_pfn_range(vma, vm_start, pin, size, vma->vm_page_prot))
> +			return -EAGAIN;
> +
> +		vm_start += size;
> +		cursor += size;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * azfs_truncate - truncate() method for inode_operations
> + * @inode: see inode_operations methods
> + */
> +static void
> +azfs_truncate(struct inode *inode)
> +{
> +	struct azfs_super *super;
> +	struct azfs_znode *znode;
> +	struct azfs_block *block, *tmp_block, *temp, *west, *east;
> +	unsigned long id, count;
> +	signed long delta;
> +
> +	super = I2S(inode);
> +	znode = I2Z(inode);
> +
> +	delta = i_size_read(inode) + (super->block_size - 1);
> +	delta >>= super->block_shift;
> +	delta -= inode->i_blocks;
> +
> +	if (delta == 0) {
> +		znode->size = i_size_read(inode);
> +		return;
> +	}
> +
> +	write_lock(&znode->lock);
> +
> +	while (delta > 0) {
> +		west = east = NULL;
> +
> +		write_lock(&super->lock);
> +
> +		if (list_empty(&super->block_list)) {
> +			write_unlock(&super->lock);
> +			break;
> +		}
> +
> +		for (count = delta; count; count--) {
> +			for_each_block(block, &super->block_list)
> +				if (block->count >= count) {
> +					east = block;
> +					break;
> +				}
> +			if (east)
> +				break;
> +		}
> +
> +		for_each_block_reverse(block, &znode->block_list) {
> +			if (block->id + block->count == east->id)
> +				west = block;
> +			break;
> +		}
> +
> +		if (east->count == count) {
> +			if (west) {
> +				west->count += east->count;
> +				azfs_block_free(east);
> +			} else {
> +				azfs_block_move(east, &znode->block_list);
> +			}
> +		} else {
> +			if (west) {
> +				west->count += count;
> +			} else {
> +				if (!azfs_block_init(&znode->block_list,
> +						east->id, count)) {
> +					write_unlock(&super->lock);
> +					break;
> +				}
> +			}
> +
> +			east->id += count;
> +			east->count -= count;
> +		}
> +
> +		write_unlock(&super->lock);
> +
> +		inode->i_blocks += count;
> +
> +		delta -= count;
> +	}
> +
> +	while (delta < 0) {
> +		for_each_block_safe_reverse(block, tmp_block, &znode->block_list) {
> +			id = block->id;
> +			count = block->count;
> +			if ((signed long) count + delta > 0) {
> +				block->count += delta;
> +				id += block->count;
> +				count -= block->count;
> +				block = NULL;
> +			}
> +
> +			west = east = NULL;
> +
> +			write_lock(&super->lock);
> +
> +			for_each_block(temp, &super->block_list) {
> +				if (!west && (temp->id + temp->count == id))
> +					west = temp;
> +				else if (!east && (id + count == temp->id))
> +					east = temp;
> +				if (west && east)
> +					break;
> +			}
> +
> +			if (west && east) {
> +				west->count += count + east->count;
> +				azfs_block_free(east);
> +				if (block)
> +					azfs_block_free(block);
> +			} else if (west) {
> +				west->count += count;
> +				if (block)
> +					azfs_block_free(block);
> +			} else if (east) {
> +				east->id -= count;
> +				east->count += count;
> +				if (block)
> +					azfs_block_free(block);
> +			} else {
> +				if (!block) {
> +					if (!azfs_block_init(&super->block_list,
> +							id, count)) {
> +						write_unlock(&super->lock);
> +						break;
> +					}
> +				} else {
> +					azfs_block_move(block, &super->block_list);
> +				}
> +			}
> +
> +			write_unlock(&super->lock);
> +
> +			inode->i_blocks -= count;
> +
> +			delta += count;
> +
> +			break;
> +		}
> +	}
> +
> +	write_unlock(&znode->lock);
> +
> +	znode->size = min(i_size_read(inode),
> +			(loff_t) inode->i_blocks << super->block_shift);
> +}
> +
> +/**
> + * azfs_getattr - getattr() method for inode_operations
> + * @mnt, @dentry, @stat: see inode_operations methods
> + */
> +static int
> +azfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
> +{
> +	struct azfs_super *super;
> +	struct inode *inode;
> +	unsigned short shift;
> +
> +	inode = dentry->d_inode;
> +	super = I2S(inode);
> +
> +	generic_fillattr(inode, stat);
> +	stat->blocks = inode->i_blocks;
> +	shift = super->block_shift - super->sector_shift;
> +	if (shift)
> +		stat->blocks <<= shift;
> +
> +	return 0;
> +}
> +
> +static const struct address_space_operations azfs_aops = {
> +	.write_begin	= simple_write_begin,
> +	.write_end	= simple_write_end
> +};
> +
> +static struct backing_dev_info azfs_bdi = {
> +	.ra_pages	= 0,
> +	.capabilities	= AZFS_BDI_CAPABILITIES
> +};
> +
> +static struct inode_operations azfs_dir_iops = {
> +	.create		= azfs_create,
> +	.lookup		= simple_lookup,
> +	.link		= simple_link,
> +	.unlink		= simple_unlink,
> +	.symlink	= azfs_symlink,
> +	.mkdir		= azfs_mkdir,
> +	.rmdir		= simple_rmdir,
> +	.mknod		= azfs_mknod,
> +	.rename		= simple_rename
> +};
> +
> +static const struct file_operations azfs_reg_fops = {
> +	.llseek		= generic_file_llseek,
> +	.aio_read	= azfs_aio_read,
> +	.aio_write	= azfs_aio_write,
> +	.open		= azfs_open,
> +	.mmap		= azfs_mmap,
> +	.fsync		= simple_sync_file,
> +};
> +
> +static struct inode_operations azfs_reg_iops = {
> +	.truncate	= azfs_truncate,
> +	.getattr	= azfs_getattr
> +};
> +
> +/**
> + * azfs_new_inode - cook a new inode
> + * @sb: super-block
> + * @dir: parent directory
> + * @mode: file mode
> + * @dev: to be forwarded to init_special_inode()
> + */
> +static struct inode*
> +azfs_new_inode(struct super_block *sb, struct inode *dir, int mode, dev_t dev)
> +{
> +	struct azfs_super *super;
> +	struct inode *inode;
> +
> +	inode = new_inode(sb);
> +	if (!inode)
> +		return NULL;
> +
> +	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
> +
> +	inode->i_mode = mode;
> +	if (dir) {
> +		dir->i_mtime = dir->i_ctime = inode->i_mtime;
> +		inode->i_uid = current->fsuid;
> +		if (dir->i_mode & S_ISGID) {
> +			if (S_ISDIR(mode))
> +				inode->i_mode |= S_ISGID;
> +			inode->i_gid = dir->i_gid;
> +		} else {
> +			inode->i_gid = current->fsgid;
> +		}
> +	} else {
> +		super = sb->s_fs_info;
> +		inode->i_uid = super->uid;
> +		inode->i_gid = super->gid;
> +	}
> +
> +	inode->i_blocks = 0;
> +	inode->i_mapping->a_ops = &azfs_aops;
> +	inode->i_mapping->backing_dev_info = &azfs_bdi;
> +
> +	switch (mode & S_IFMT) {
> +	case S_IFDIR:
> +		inode->i_op = &azfs_dir_iops;
> +		inode->i_fop = &simple_dir_operations;
> +		inc_nlink(inode);
> +		break;
> +
> +	case S_IFREG:
> +		inode->i_op = &azfs_reg_iops;
> +		inode->i_fop = &azfs_reg_fops;
> +		break;
> +
> +	case S_IFLNK:
> +		inode->i_op = &page_symlink_inode_operations;
> +		break;
> +
> +	default:
> +		init_special_inode(inode, mode, dev);
> +		break;
> +	}
> +
> +	return inode;
> +}
> +
> +/**
> + * azfs_alloc_inode - alloc_inode() method for super_operations
> + * @sb: see super_operations methods
> + */
> +static struct inode*
> +azfs_alloc_inode(struct super_block *sb)
> +{
> +	struct azfs_znode *znode;
> +
> +	znode = kmem_cache_alloc(azfs_znode_cache, GFP_KERNEL);
> +	if (znode) {
> +		INIT_LIST_HEAD(&znode->block_list);
> +		rwlock_init(&znode->lock);
> +
> +		inode_init_once(&znode->vfs_inode);
> +
> +		return &znode->vfs_inode;
> +	}
> +
> +	return NULL;
> +}
> +
> +/**
> + * azfs_destroy_inode - destroy_inode() method for super_operations
> + * @inode: see super_operations methods
> + */
> +static void
> +azfs_destroy_inode(struct inode *inode)
> +{
> +	kmem_cache_free(azfs_znode_cache, I2Z(inode));
> +}
> +
> +/**
> + * azfs_delete_inode - delete_inode() method for super_operations
> + * @inode: see super_operations methods
> + */
> +static void
> +azfs_delete_inode(struct inode *inode)
> +{
> +	if (S_ISREG(inode->i_mode)) {
> +		i_size_write(inode, 0);
> +		azfs_truncate(inode);
> +	}
> +	truncate_inode_pages(&inode->i_data, 0);
> +	clear_inode(inode);
> +}
> +
> +/**
> + * azfs_statfs - statfs() method for super_operations
> + * @dentry, @stat: see super_operations methods
> + */
> +static int
> +azfs_statfs(struct dentry *dentry, struct kstatfs *stat)
> +{
> +	struct super_block *sb;
> +	struct azfs_super *super;
> +	struct inode *inode;
> +	unsigned long inodes, blocks;
> +
> +	sb = dentry->d_sb;
> +	super = sb->s_fs_info;
> +
> +	inodes = blocks = 0;
> +	mutex_lock(&sb->s_lock);
> +	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
> +		inodes++;
> +		blocks += inode->i_blocks;
> +	}
> +	mutex_unlock(&sb->s_lock);
> +
> +	stat->f_type = AZFS_SUPERBLOCK_MAGIC;
> +	stat->f_bsize = super->block_size;
> +	stat->f_blocks = super->media_size >> super->block_shift;
> +	stat->f_bfree = stat->f_blocks - blocks;
> +	stat->f_bavail = stat->f_blocks - blocks;
> +	stat->f_files = inodes + blocks;
> +	stat->f_ffree = blocks + 1;
> +	stat->f_namelen = NAME_MAX;
> +
> +	return 0;
> +}
> +
> +static struct super_operations azfs_ops = {
> +	.alloc_inode	= azfs_alloc_inode,
> +	.destroy_inode	= azfs_destroy_inode,
> +	.drop_inode	= generic_delete_inode,
> +	.delete_inode	= azfs_delete_inode,
> +	.statfs		= azfs_statfs
> +};
> +
> +enum {
> +	Opt_blocksize_short,
> +	Opt_blocksize_long,
> +	Opt_uid,
> +	Opt_gid,
> +	Opt_err
> +};
> +
> +static match_table_t tokens = {
> +	{Opt_blocksize_short, "bs=%u"},
> +	{Opt_blocksize_long, "blocksize=%u"},
> +	{Opt_uid, "uid=%u"},
> +	{Opt_gid, "gid=%u"},
> +	{Opt_err, NULL}
> +};
> +
> +/**
> + * azfs_parse_mount_parameters - parse options given to mount with -o
> + * @super: azfs super block extension
> + * @options: comma separated options
> + */
> +static int
> +azfs_parse_mount_parameters(struct azfs_super *super, char *options)
> +{
> +	char *option;
> +	int token, value;
> +	substring_t args[MAX_OPT_ARGS];
> +
> +	if (!options)
> +		return 1;
> +
> +	while ((option = strsep(&options, ",")) != NULL) {
> +		if (!*option)
> +			continue;
> +
> +		token = match_token(option, tokens, args);
> +		switch (token) {
> +		case Opt_blocksize_short:
> +		case Opt_blocksize_long:
> +			if (match_int(&args[0], &value))
> +				goto syntax_error;
> +			super->block_size = value;
> +			break;
> +
> +		case Opt_uid:
> +			if (match_int(&args[0], &value))
> +				goto syntax_error;
> +			super->uid = value;
> +			break;
> +
> +		case Opt_gid:
> +			if (match_int(&args[0], &value))
> +				goto syntax_error;
> +			super->gid = value;
> +			break;
> +
> +		default:
> +			goto syntax_error;
> +		}
> +	}
> +
> +	return 1;
> +
> +syntax_error:
> +	printk(KERN_ERR "%s: invalid mount option\n",
> +			AZFS_FILESYSTEM_NAME);
> +
> +	return 0;
> +}
> +
> +/**
> + * azfs_fill_super - fill_super routine for get_sb
> + * @sb, @data, @silent: see file_system_type methods
> + */
> +static int
> +azfs_fill_super(struct super_block *sb, void *data, int silent)
> +{
> +	struct gendisk *disk;
> +	struct azfs_super *super = NULL, *tmp_super;
> +	struct azfs_block *block = NULL;
> +	struct inode *inode = NULL;
> +	void *kaddr;
> +	unsigned long pfn;
> +	int rc;
> +
> +	BUG_ON(!sb->s_bdev);
> +
> +	disk = sb->s_bdev->bd_disk;
> +
> +	BUG_ON(!disk || !disk->queue);
> +
> +	if (!disk->fops->direct_access) {
> +		printk(KERN_ERR "%s needs a block device with a "
> +				"direct_access() method\n",
> +				AZFS_FILESYSTEM_NAME);
> +		return -ENOSYS;
> +	}
> +
> +	get_device(disk->driverfs_dev);
> +
> +	sb->s_magic = AZFS_SUPERBLOCK_MAGIC;
> +	sb->s_flags = AZFS_SUPERBLOCK_FLAGS;
> +	sb->s_op = &azfs_ops;
> +	sb->s_maxbytes = get_capacity(disk) * disk->queue->hardsect_size;
> +	sb->s_time_gran = 1;
> +
> +	spin_lock(&super_list.lock);
> +	list_for_each_entry(tmp_super, &super_list.head, list)
> +		if (tmp_super->blkdev == sb->s_bdev) {
> +			super = tmp_super;
> +			break;
> +		}
> +	spin_unlock(&super_list.lock);
> +
> +	if (super) {
> +		if (data && strlen((char*) data))
> +			printk(KERN_WARNING "/dev/%s was already mounted with "
> +					"%s before, it will be mounted with "
> +					"mount options used last time, "
> +					"options just given would be ignored\n",
> +					disk->disk_name, AZFS_FILESYSTEM_NAME);
> +		sb->s_fs_info = super;
> +	} else {
> +		super = kzalloc(sizeof(struct azfs_super), GFP_KERNEL);
> +		if (!super) {
> +			rc = -ENOMEM;
> +			goto failed;
> +		}
> +		sb->s_fs_info = super;
> +
> +		if (!azfs_parse_mount_parameters(super, (char*) data)) {
> +			rc = -EINVAL;
> +			goto failed;
> +		}
> +
> +		inode = azfs_new_inode(sb, NULL, S_IFDIR | S_IRWXUGO, 0);
> +		if (!inode) {
> +			rc = -ENOMEM;
> +			goto failed;
> +		}
> +
> +		super->root = d_alloc_root(inode);
> +		if (!super->root) {
> +			rc = -ENOMEM;
> +			goto failed;
> +		}
> +		dget(super->root);
> +
> +		INIT_LIST_HEAD(&super->list);
> +		INIT_LIST_HEAD(&super->block_list);
> +		rwlock_init(&super->lock);
> +
> +		super->media_size = sb->s_maxbytes;
> +
> +		if (!super->block_size)
> +			super->block_size = sb->s_blocksize;
> +		super->block_shift = blksize_bits(super->block_size);
> +
> +		super->sector_size = disk->queue->hardsect_size;
> +		super->sector_shift = blksize_bits(super->sector_size);
> +
> +		super->blkdev = sb->s_bdev;
> +
> +		block = azfs_block_init(&super->block_list,
> +				0, super->media_size >> super->block_shift);
> +		if (!block) {
> +			rc = -ENOMEM;
> +			goto failed;
> +		}
> +
> +		rc = disk->fops->direct_access(super->blkdev, 0, &kaddr, &pfn);
> +		if (rc < 0) {
> +			rc = -EFAULT;
> +			goto failed;
> +		}
> +		super->ph_addr = (unsigned long) kaddr;
> +
> +		super->io_addr = (unsigned long) ioremap_flags(
> +				super->ph_addr, super->media_size, _PAGE_NO_CACHE);
> +		if (!super->io_addr) {
> +			rc = -EFAULT;
> +			goto failed;
> +		}
> +
> +		spin_lock(&super_list.lock);
> +		list_add(&super->list, &super_list.head);
> +		spin_unlock(&super_list.lock);
> +	}
> +
> +	sb->s_root = super->root;
> +	disk->driverfs_dev->driver_data = super;
> +	disk->driverfs_dev->platform_data = sb;
> +
> +	if (super->block_size < PAGE_SIZE)
> +		printk(KERN_INFO "Block size on %s is smaller then system "
> +				"page size: mmap() would not be supported\n",
> +				disk->disk_name);
> +
> +	return 0;
> +
> +failed:
> +	if (super) {
> +		sb->s_root = NULL;
> +		sb->s_fs_info = NULL;
> +		if (block)
> +			azfs_block_free(block);
> +		if (super->root)
> +			dput(super->root);
> +		if (inode)
> +			iput(inode);
> +		disk->driverfs_dev->driver_data = NULL;
> +		kfree(super);
> +		disk->driverfs_dev->platform_data = NULL;
> +		put_device(disk->driverfs_dev);
> +	}
> +
> +	return rc;
> +}
> +
> +/**
> + * azfs_get_sb - get_sb() method for file_system_type
> + * @fs_type, @flags, @dev_name, @data, @mount: see file_system_type methods
> + */
> +static int
> +azfs_get_sb(struct file_system_type *fs_type, int flags,
> +	    const char *dev_name, void *data, struct vfsmount *mount)
> +{
> +	return get_sb_bdev(fs_type, flags,
> +			dev_name, data, azfs_fill_super, mount);
> +}
> +
> +/**
> + * azfs_kill_sb - kill_sb() method for file_system_type
> + * @sb: see file_system_type methods
> + */
> +static void
> +azfs_kill_sb(struct super_block *sb)
> +{
> +	sb->s_root = NULL;
> +	kill_block_super(sb);
> +}
> +
> +static struct file_system_type azfs_fs = {
> +	.owner		= THIS_MODULE,
> +	.name		= AZFS_FILESYSTEM_NAME,
> +	.get_sb		= azfs_get_sb,
> +	.kill_sb	= azfs_kill_sb,
> +	.fs_flags	= AZFS_FILESYSTEM_FLAGS
> +};
> +
> +/**
> + * azfs_init
> + */
> +static int __init
> +azfs_init(void)
> +{
> +	int rc;
> +
> +	INIT_LIST_HEAD(&super_list.head);
> +	spin_lock_init(&super_list.lock);
> +
> +	azfs_znode_cache = kmem_cache_create("azfs_znode_cache",
> +			sizeof(struct azfs_znode), 0, AZFS_CACHE_FLAGS, NULL);
> +	if (!azfs_znode_cache) {
> +		printk(KERN_ERR "Could not allocate inode cache for %s\n",
> +				AZFS_FILESYSTEM_NAME);
> +		rc = -ENOMEM;
> +		goto failed;
> +	}
> +
> +	azfs_block_cache = kmem_cache_create("azfs_block_cache",
> +			sizeof(struct azfs_block), 0, AZFS_CACHE_FLAGS, NULL);
> +	if (!azfs_block_cache) {
> +		printk(KERN_ERR "Could not allocate block cache for %s\n",
> +				AZFS_FILESYSTEM_NAME);
> +		rc = -ENOMEM;
> +		goto failed;
> +	}
> +
> +	rc = register_filesystem(&azfs_fs);
> +	if (rc != 0) {
> +		printk(KERN_ERR "Could not register %s\n",
> +				AZFS_FILESYSTEM_NAME);
> +		goto failed;
> +	}
> +
> +	return 0;
> +
> +failed:
> +	if (azfs_block_cache)
> +		kmem_cache_destroy(azfs_block_cache);
> +
> +	if (azfs_znode_cache)
> +		kmem_cache_destroy(azfs_znode_cache);
> +
> +	return rc;
> +}
> +
> +/**
> + * azfs_exit
> + */
> +static void __exit
> +azfs_exit(void)
> +{
> +	struct azfs_super *super, *tmp_super;
> +	struct azfs_block *block, *tmp_block;
> +	struct gendisk *disk;
> +
> +	spin_lock(&super_list.lock);
> +	list_for_each_entry_safe(super, tmp_super, &super_list.head, list) {
> +		disk = super->blkdev->bd_disk;
> +		list_del(&super->list);
> +		iounmap((void*) super->io_addr);
> +		write_lock(&super->lock);
> +		for_each_block_safe(block, tmp_block, &super->block_list)
> +			azfs_block_free(block);
> +		write_unlock(&super->lock);
> +		disk->driverfs_dev->driver_data = NULL;
> +		disk->driverfs_dev->platform_data = NULL;
> +		kfree(super);
> +		put_device(disk->driverfs_dev);
> +	}
> +	spin_unlock(&super_list.lock);
> +
> +	unregister_filesystem(&azfs_fs);
> +
> +	kmem_cache_destroy(azfs_block_cache);
> +	kmem_cache_destroy(azfs_znode_cache);
> +}
> +
> +module_init(azfs_init);
> +module_exit(azfs_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Maxim Shchetynin <maxim@de.ibm.com>");
> +MODULE_DESCRIPTION("Non-buffered file system for IO devices");
> -- 
> 1.5.4.3
> 

^ permalink raw reply

* Re: [Cbe-oss-dev] [patch 9/9] powerpc/cell: Add DMA_ATTR_STRONG_ORDERING dma attribute and use in IOMMU code
From: Benjamin Herrenschmidt @ 2008-07-17  6:20 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, Roland Dreier, cbe-oss-dev
In-Reply-To: <200807160954.03633.arnd@arndb.de>

On Wed, 2008-07-16 at 09:54 +0200, Arnd Bergmann wrote:
> On Wednesday 16 July 2008, Roland Dreier wrote:
> >  > Strong ordering is only active when both the bridge and the IOMMU enable
> >  > it, but for correctly written drivers, this only results in a slowdown.
> > 
> > So when would someone use this dma attribute?  As a hack to fix drivers
> > where the real fix is too complicated?
> 
> This is used in the Axon PCIe endpoint drivers, e.g. in the Roadrunner
> machine. The reason was to improve roundtrip latency by doing only
> mmio stores, not loads, on each side of the PCIe connection, which
> turn into posted DMA operations on the other end. With relaxed ordering,
> the posted writes may be observed out of order. Strong ordering makes
> sure they arrive in-order without having to do a non-posted mmio read
> or eieio operation on the receiver side.

I don't think it's legal for writes from a given initiator to arrive to
memory out of order.

Some drivers, notably network drivers, for example, rely on the "OWN"
bit being written last in memory when writing back ring buffer status.

If the bit arrives before the actual data, then data corruption will
occur.

Ben.

^ permalink raw reply

* Re: powerpc.git merge status
From: Benjamin Herrenschmidt @ 2008-07-17  6:30 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev list
In-Reply-To: <20080715113943.GA28229@polina.dev.rtsoft.ru>

On Tue, 2008-07-15 at 15:39 +0400, Anton Vorontsov wrote:
> On Tue, Jul 15, 2008 at 04:02:09PM +1000, Benjamin Herrenschmidt wrote:
> [...]
> > If you believe I've missed something, now is time to be vocal about
> > it :-)
> 
> Yes, this one is lost:
> 
> [OF] of_gpio: should use new <linux/gpio.h> header
> http://patchwork.ozlabs.org/linuxppc/patch?id=18750

Is that supposed to go via the powerpc tree or is there a GPIO tree ? Is
there a GPIO maintainer that should ack it first ?

I know it's a trivial patch but I don't want to start maintainer clashes
right away :-)

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH] elf loader support for auxvec base platform string
From: Benjamin Herrenschmidt @ 2008-07-17  6:35 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton
  Cc: linuxppc-dev, Nathan Lynch, linux-kernel, roland
In-Reply-To: <1216166331-14810-2-git-send-email-ntl@pobox.com>

Hi Linus, Andrew !

Should I seek somebody's ack before merging a patch like the one below ?

I'm a bit reluctant to merge via the powerpc.git tree some changes to
generic files without at least an ack from somebody else :-)

There have been some debate on whether this AT_BASE_PLATFORM is the
right approach, though I haven't seen them reach any useful conclusion
and our toolchain people internally are screaming for it...

Cheers,
Ben.

On Tue, 2008-07-15 at 18:58 -0500, Nathan Lynch wrote:
> Some IBM POWER-based platforms have the ability to run in a
> mode which mostly appears to the OS as a different processor from the
> actual hardware.  For example, a Power6 system may appear to be a
> Power5+, which makes the AT_PLATFORM value "power5+".  This means that
> programs are restricted to the ISA supported by Power5+;
> Power6-specific instructions are treated as illegal.
> 
> However, some applications (virtual machines, optimized libraries) can
> benefit from knowledge of the underlying CPU model.  A new aux vector
> entry, AT_BASE_PLATFORM, will denote the actual hardware.  For
> example, on a Power6 system in Power5+ compatibility mode, AT_PLATFORM
> will be "power5+" and AT_BASE_PLATFORM will be "power6".  The idea is
> that AT_PLATFORM indicates the instruction set supported, while
> AT_BASE_PLATFORM indicates the underlying microarchitecture.
> 
> If the architecture has defined ELF_BASE_PLATFORM, copy that value to
> the user stack in the same manner as ELF_PLATFORM.
> 
> Signed-off-by: Nathan Lynch <ntl@pobox.com>
> ---
>  fs/binfmt_elf.c        |   23 +++++++++++++++++++++++
>  include/linux/auxvec.h |    5 ++++-
>  2 files changed, 27 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
> index d48ff5f..834c2c4 100644
> --- a/fs/binfmt_elf.c
> +++ b/fs/binfmt_elf.c
> @@ -131,6 +131,10 @@ static int padzero(unsigned long elf_bss)
>  #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; })
>  #endif
>  
> +#ifndef ELF_BASE_PLATFORM
> +#define ELF_BASE_PLATFORM NULL
> +#endif
> +
>  static int
>  create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
>  		unsigned long load_addr, unsigned long interp_load_addr)
> @@ -142,7 +146,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
>  	elf_addr_t __user *envp;
>  	elf_addr_t __user *sp;
>  	elf_addr_t __user *u_platform;
> +	elf_addr_t __user *u_base_platform;
>  	const char *k_platform = ELF_PLATFORM;
> +	const char *k_base_platform = ELF_BASE_PLATFORM;
>  	int items;
>  	elf_addr_t *elf_info;
>  	int ei_index = 0;
> @@ -172,6 +178,19 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
>  			return -EFAULT;
>  	}
>  
> +	/*
> +	 * If this architecture has a "base" platform capability
> +	 * string, copy it to userspace.
> +	 */
> +	u_base_platform = NULL;
> +	if (k_base_platform) {
> +		size_t len = strlen(k_base_platform) + 1;
> +
> +		u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
> +		if (__copy_to_user(u_base_platform, k_base_platform, len))
> +			return -EFAULT;
> +	}
> +
>  	/* Create the ELF interpreter info */
>  	elf_info = (elf_addr_t *)current->mm->saved_auxv;
>  	/* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */
> @@ -208,6 +227,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
>  		NEW_AUX_ENT(AT_PLATFORM,
>  			    (elf_addr_t)(unsigned long)u_platform);
>  	}
> +	if (k_base_platform) {
> +		NEW_AUX_ENT(AT_BASE_PLATFORM,
> +			    (elf_addr_t)(unsigned long)u_base_platform);
> +	}
>  	if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
>  		NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
>  	}
> diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h
> index ad89545..1adc61d 100644
> --- a/include/linux/auxvec.h
> +++ b/include/linux/auxvec.h
> @@ -26,8 +26,11 @@
>  
>  #define AT_SECURE 23   /* secure mode boolean */
>  
> +#define AT_BASE_PLATFORM 38	/* string identifying real platform, may
> +				 * differ from AT_PLATFORM. */
> +
>  #ifdef __KERNEL__
> -#define AT_VECTOR_SIZE_BASE (14 + 2) /* NEW_AUX_ENT entries in auxiliary table */
> +#define AT_VECTOR_SIZE_BASE (14 + 3) /* NEW_AUX_ENT entries in auxiliary table */
>  #endif
>  
>  #endif /* _LINUX_AUXVEC_H */

^ permalink raw reply

* Re: PS3 patches for 2.6.27
From: Benjamin Herrenschmidt @ 2008-07-17  6:43 UTC (permalink / raw)
  To: Geoff Levand; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <487E6683.9000001@am.sony.com>

On Wed, 2008-07-16 at 14:22 -0700, Geoff Levand wrote:
> Hi Ben,
> 
> Here are two more PS3 patches for 2.6.27.  Please apply.

Thanks, they'll be in my next batch (hopefully tomorrow).

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH] powerpc: Introduce local (non-broadcast) forms of tlb invalidates
From: Benjamin Herrenschmidt @ 2008-07-17  6:48 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0807151627020.29665@blarg.am.freescale.net>

On Tue, 2008-07-15 at 16:27 -0500, Kumar Gala wrote:
> Introduced a new set of low level tlb invalidate functions that do not
> broadcast invalidates on the bus:
> 
> _tlbil_all - invalidate all
> _tlbil_pid - invalidate based on process id (or mm context)
> _tlbil_va  - invalidate based on virtual address (ea + pid)
> 
> On non-SMP configs _tlbil_all should be functionally equivalent to _tlbia and
> _tlbil_va should be functionally equivalent to _tlbie.
> 
> The intent of this change is to handle SMP based invalidates via IPIs instead
> of broadcasts as the mechanism scales better for larger number of cores.
> 
> On e500 (fsl-booke mmu) based cores move to using MMUCSR for invalidate alls
> and tlbsx/tlbwe for invalidate virtual address.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

Any reason why we have to continue doing those in asm .S files ?

mfspr/mtspr in C work fine and inline asm statements for the
tlbilx instructions proper too :-)

Cheers,
Ben.

> ---
>  arch/powerpc/kernel/misc_32.S   |   53 +++++++++++++++++++++++++++++++++++++++
>  arch/powerpc/kernel/ppc_ksyms.c |    1 +
>  include/asm-powerpc/reg_booke.h |    7 +++++
>  include/asm-powerpc/tlbflush.h  |   13 ++++++---
>  4 files changed, 69 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
> index 6321ae3..9245b75 100644
> --- a/arch/powerpc/kernel/misc_32.S
> +++ b/arch/powerpc/kernel/misc_32.S
> @@ -274,6 +274,9 @@ _GLOBAL(real_writeb)
>  /*
>   * Flush MMU TLB
>   */
> +#ifndef CONFIG_FSL_BOOKE
> +_GLOBAL(_tlbil_all)
> +#endif
>  _GLOBAL(_tlbia)
>  #if defined(CONFIG_40x)
>  	sync			/* Flush to memory before changing mapping */
> @@ -344,6 +347,9 @@ _GLOBAL(_tlbia)
>  /*
>   * Flush MMU TLB for a particular address
>   */
> +#ifndef CONFIG_FSL_BOOKE
> +_GLOBAL(_tlbil_va)
> +#endif
>  _GLOBAL(_tlbie)
>  #if defined(CONFIG_40x)
>  	/* We run the search with interrupts disabled because we have to change
> @@ -436,6 +442,53 @@ _GLOBAL(_tlbie)
>  #endif /* ! CONFIG_40x */
>  	blr
> 
> +#if defined(CONFIG_FSL_BOOKE)
> +/*
> + * Flush MMU TLB, but only on the local processor (no broadcast)
> + */
> +_GLOBAL(_tlbil_all)
> +#define MMUCSR0_TLBFI	(MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \
> +			 MMUCSR0_TLB2FI | MMUCSR0_TLB3FI)
> +	li	r3,(MMUCSR0_TLBFI)@l
> +	mtspr	SPRN_MMUCSR0, r3
> +1:
> +	mfspr	r3,SPRN_MMUCSR0
> +	andi.	r3,r3,MMUCSR0_TLBFI@l
> +	bne	1b
> +	blr
> +
> +/*
> + * Flush MMU TLB for a particular process id, but only on the local processor
> + * (no broadcast)
> + */
> +_GLOBAL(_tlbil_pid)
> +	li	r3,(MMUCSR0_TLBFI)@l
> +	mtspr	SPRN_MMUCSR0, r3
> +1:
> +	mfspr	r3,SPRN_MMUCSR0
> +	andi.	r1,r2,MMUCSR0_TLBFI@l
> +	bne	1b
> +	blr
> +
> +/*
> + * Flush MMU TLB for a particular address, but only on the local processor
> + * (no broadcast)
> + */
> +_GLOBAL(_tlbil_va)
> +	slwi	r4,r4,16
> +	mtspr	SPRN_MAS6,r4		/* assume AS=0 for now */
> +	tlbsx	0,r3
> +	mfspr	r4,SPRN_MAS1		/* check valid */
> +	andis.	r3,r4,MAS1_VALID@h
> +	beq	1f
> +	rlwinm	r4,r4,0,1,31
> +	mtspr	SPRN_MAS1,r4
> +	tlbwe
> +1:
> +	blr
> +#endif /* CONFIG_FSL_BOOKE */
> +
> +
>  /*
>   * Flush instruction cache.
>   * This is a no-op on the 601.
> diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
> index 958ecb9..b7e4ff0 100644
> --- a/arch/powerpc/kernel/ppc_ksyms.c
> +++ b/arch/powerpc/kernel/ppc_ksyms.c
> @@ -114,6 +114,7 @@ EXPORT_SYMBOL(flush_instruction_cache);
>  EXPORT_SYMBOL(flush_tlb_kernel_range);
>  EXPORT_SYMBOL(flush_tlb_page);
>  EXPORT_SYMBOL(_tlbie);
> +EXPORT_SYMBOL(_tlbil_va);
>  #endif
>  EXPORT_SYMBOL(__flush_icache_range);
>  EXPORT_SYMBOL(flush_dcache_range);
> diff --git a/include/asm-powerpc/reg_booke.h b/include/asm-powerpc/reg_booke.h
> index be980f4..6745376 100644
> --- a/include/asm-powerpc/reg_booke.h
> +++ b/include/asm-powerpc/reg_booke.h
> @@ -109,6 +109,7 @@
>  #define SPRN_EVPR	0x3D6	/* Exception Vector Prefix Register */
>  #define SPRN_L1CSR0	0x3F2	/* L1 Cache Control and Status Register 0 */
>  #define SPRN_L1CSR1	0x3F3	/* L1 Cache Control and Status Register 1 */
> +#define SPRN_MMUCSR0	0x3F4	/* MMU Control and Status Register 0 */
>  #define SPRN_PIT	0x3DB	/* Programmable Interval Timer */
>  #define SPRN_BUCSR	0x3F5	/* Branch Unit Control and Status */
>  #define SPRN_L2CSR0	0x3F9	/* L2 Data Cache Control and Status Register 0 */
> @@ -410,6 +411,12 @@
>  #define L2CSR0_L2LOA	0x00000080	/* L2 Cache Lock Overflow Allocate */
>  #define L2CSR0_L2LO	0x00000020	/* L2 Cache Lock Overflow */
> 
> +/* Bit definitions for MMUCSR0 */
> +#define MMUCSR0_TLB1FI	0x00000002	/* TLB1 Flash invalidate */
> +#define MMUCSR0_TLB0FI	0x00000004	/* TLB0 Flash invalidate */
> +#define MMUCSR0_TLB2FI	0x00000040	/* TLB2 Flash invalidate */
> +#define MMUCSR0_TLB3FI	0x00000020	/* TLB3 Flash invalidate */
> +
>  /* Bit definitions for SGR. */
>  #define SGR_NORMAL	0		/* Speculative fetching allowed. */
>  #define SGR_GUARDED	1		/* Speculative fetching disallowed. */
> diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h
> index 5c91081..29da561 100644
> --- a/include/asm-powerpc/tlbflush.h
> +++ b/include/asm-powerpc/tlbflush.h
> @@ -29,6 +29,9 @@
>  #include <linux/mm.h>
> 
>  extern void _tlbie(unsigned long address, unsigned int pid);
> +extern void _tlbil_all(void);
> +extern void _tlbil_pid(unsigned int pid);
> +extern void _tlbil_va(unsigned long address, unsigned int pid);
> 
>  #if defined(CONFIG_40x) || defined(CONFIG_8xx)
>  #define _tlbia()	asm volatile ("tlbia; sync" : : : "memory")
> @@ -38,31 +41,31 @@ extern void _tlbia(void);
> 
>  static inline void flush_tlb_mm(struct mm_struct *mm)
>  {
> -	_tlbia();
> +	_tlbil_all();
>  }
> 
>  static inline void flush_tlb_page(struct vm_area_struct *vma,
>  				  unsigned long vmaddr)
>  {
> -	_tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);
> +	_tlbil_va(vmaddr, vma ? vma->vm_mm->context.id : 0);
>  }
> 
>  static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
>  					 unsigned long vmaddr)
>  {
> -	_tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);
> +	flush_tlb_page(vma, vmaddr);
>  }
> 
>  static inline void flush_tlb_range(struct vm_area_struct *vma,
>  				   unsigned long start, unsigned long end)
>  {
> -	_tlbia();
> +	_tlbil_all();
>  }
> 
>  static inline void flush_tlb_kernel_range(unsigned long start,
>  					  unsigned long end)
>  {
> -	_tlbia();
> +	_tlbil_all();
>  }
> 
>  #elif defined(CONFIG_PPC32)

^ permalink raw reply

* Re: [PATCH] elf loader support for auxvec base platform string
From: Andrew Morton @ 2008-07-17  7:09 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, Nathan Lynch, Linus Torvalds, linux-kernel, roland
In-Reply-To: <1216276539.7740.309.camel@pasglop>

On Thu, 17 Jul 2008 16:35:39 +1000 Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> Hi Linus, Andrew !
> 
> Should I seek somebody's ack before merging a patch like the one below ?

I think it's good to do so.

> I'm a bit reluctant to merge via the powerpc.git tree some changes to
> generic files without at least an ack from somebody else :-)

It tends to happen.  People often don't notice unless it a) crashes or
b) spits warnings or c) screws up my tree or d) all the above plus
more.

> There have been some debate on whether this AT_BASE_PLATFORM is the
> right approach, though I haven't seen them reach any useful conclusion
> and our toolchain people internally are screaming for it...
> 
> Cheers,
> Ben.
> 
> On Tue, 2008-07-15 at 18:58 -0500, Nathan Lynch wrote:
> > Some IBM POWER-based platforms have the ability to run in a
> > mode which mostly appears to the OS as a different processor from the
> > actual hardware.  For example, a Power6 system may appear to be a
> > Power5+, which makes the AT_PLATFORM value "power5+".  This means that
> > programs are restricted to the ISA supported by Power5+;
> > Power6-specific instructions are treated as illegal.
> > 
> > However, some applications (virtual machines, optimized libraries) can
> > benefit from knowledge of the underlying CPU model.  A new aux vector
> > entry, AT_BASE_PLATFORM, will denote the actual hardware.  For
> > example, on a Power6 system in Power5+ compatibility mode, AT_PLATFORM
> > will be "power5+" and AT_BASE_PLATFORM will be "power6".  The idea is
> > that AT_PLATFORM indicates the instruction set supported, while
> > AT_BASE_PLATFORM indicates the underlying microarchitecture.
> > 
> > If the architecture has defined ELF_BASE_PLATFORM, copy that value to
> > the user stack in the same manner as ELF_PLATFORM.
> > 
> > Signed-off-by: Nathan Lynch <ntl@pobox.com>
> > ---
> >  fs/binfmt_elf.c        |   23 +++++++++++++++++++++++
> >  include/linux/auxvec.h |    5 ++++-
> >  2 files changed, 27 insertions(+), 1 deletions(-)
> > 
> > diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
> > index d48ff5f..834c2c4 100644
> > --- a/fs/binfmt_elf.c
> > +++ b/fs/binfmt_elf.c
> > @@ -131,6 +131,10 @@ static int padzero(unsigned long elf_bss)
> >  #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; })
> >  #endif
> >  
> > +#ifndef ELF_BASE_PLATFORM
> > +#define ELF_BASE_PLATFORM NULL
> > +#endif

Please add a comment which explains what this is.

Please also add a comment telling the world in which header file the
architecture *must* define this macro and then ensure that that header is
included into this file by reliable means.  asm/elf.h looks OK.

> >  static int
> >  create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
> >  		unsigned long load_addr, unsigned long interp_load_addr)
> > @@ -142,7 +146,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
> >  	elf_addr_t __user *envp;
> >  	elf_addr_t __user *sp;
> >  	elf_addr_t __user *u_platform;
> > +	elf_addr_t __user *u_base_platform;
> >  	const char *k_platform = ELF_PLATFORM;
> > +	const char *k_base_platform = ELF_BASE_PLATFORM;
> >  	int items;
> >  	elf_addr_t *elf_info;
> >  	int ei_index = 0;
> > @@ -172,6 +178,19 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
> >  			return -EFAULT;
> >  	}
> >  
> > +	/*
> > +	 * If this architecture has a "base" platform capability
> > +	 * string, copy it to userspace.
> > +	 */
> > +	u_base_platform = NULL;
> > +	if (k_base_platform) {
> > +		size_t len = strlen(k_base_platform) + 1;
> > +
> > +		u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
> > +		if (__copy_to_user(u_base_platform, k_base_platform, len))
> > +			return -EFAULT;
> > +	}

>From my reading, this change will result in no additional code
generation on non-powerpc architectures.  This is good.  If poss, could
you please verify that theory and perhaps drop a note in the changelog
about that?


Apart from that - acked-by-me

^ permalink raw reply

* Re: Videomode 800x480
From: Alex_SYS @ 2008-07-17  7:15 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <18482586.post@talk.nabble.com>



Alex_SYS wrote:
>=20
> <Here is the Kernel Bootup message that it gives when it crashes!
>=20
> U-Boot 1.2.0-mpc5200b-tiny-3 (Dec 11 2007 - 11:25:01)
>=20
> CPU:   MPC5200 v2.2, Core v1.4 at 399.999 MHz
>        Bus 133 MHz, IPB 133 MHz, PCI 33 MHz
> Board: phyCORE-MPC5200B-tiny
> I2C:   ready
> DRAM:  64 MB
> SP:    0x03f73768
> FLASH: 16 MB
> Using pcm030 machine description
> Linux version 2.6.23.1-rt5-pcm030-1trunk (aschmid@LINUX) (gcc version
> 4.1.2) #39
> 4 PREEMPT RT Tue Dec 11 17:58:48 CET 2007
> Zone PFN ranges:
>   DMA             0 ->    16384
>   Normal      16384 ->    16384
> Movable zone start PFN for each node
> early_node_map[1] active PFN ranges
>     0:        0 ->    16384
> Real-Time Preemption Support (C) 2004-2007 Ingo Molnar
> Built 1 zonelists in Zone order.  Total pages: 16256
> Kernel command line: video=3D0x0-16@60 , console=3DttyPSC0,115200
> mtdparts=3Dphysmap-f
> lash.0:256k(ubootl),1792k(kernel),13312k(jffs2),256k(uboot)ro,256k(oftree=
),-(spa
> ce) rw root=3D/dev/mtdblock2 rootfstype=3Djffs2
> WARNING: experimental RCU implementation.
> MPC52xx PIC is up and running!
> PID hash table entries: 256 (order: 8, 1024 bytes)
> Console: colour dummy device 80x25
> console [ttyPSC0] enabled
> Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
> Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
> Memory: 61960k/65536k available (2624k kernel code, 3508k reserved, 144k
> data, 1
> 06k bss, 124k init)
> Mount-cache hash table entries: 512
> NET: Registered protocol family 16
> PCI: Probing PCI hardware
> DMA: MPC52xx BestComm driver
> DMA: MPC52xx BestComm engine @f0001200 ok !
> Generic PHY: Registered new driver
> usbcore: registered new interface driver usbfs
> usbcore: registered new interface driver hub
> usbcore: registered new device driver usb
> NET: Registered protocol family 2
> IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
> TCP established hash table entries: 2048 (order: 4, 73728 bytes)
> TCP bind hash table entries: 2048 (order: 3, 57344 bytes)
> TCP: Hash tables configured (established 2048 bind 2048)
> TCP reno registered
> JFFS2 version 2.2. (NAND) =C3=82=C2=A9 2001-2006 Red Hat, Inc.
> io scheduler noop registered (default)
> No Options from U-Boot
> Lime Driver PROBE
> No Mode
> Name des Strings 0x0-16@60 with L=C3=83=C2=A4nge 9
> Schleife mode Options
> Schleife @
> Schleife -
> Schleife x
> DONE vor CVT xres=3D 0 , yres=3D0 , cvt=3D
> 0******************************************
> ************CVT Mode: Trying specified video mode 0x0
> Trying mode 800x480-16@60 800x600-16@20
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 640x400-16@70
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 640x480-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 800x600-16@56
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1024x768-16@87
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 640x400-16@85
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 640x480-16@72
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 640x480-16@75
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 800x600-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 640x480-16@85
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1152x864-16@69
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 800x600-16@72
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1024x768-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 640x480-16@100
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1152x864-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 800x600-16@85
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1024x768-16@70
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1280x1024-16@87
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 800x600-16@100
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1024x768-16@76
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1152x864-16@70
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1280x1024-16@61
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1400x1050-16@68
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1400x1050-16@75
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1400x1050-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1024x768-16@85
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1152x864-16@78
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1280x1024-16@70
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1600x1200-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1152x864-16@84
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1280x1024-16@74
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1024x768-16@100
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1280x1024-16@76
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1600x1200-16@70
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1152x864-16@100
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1280x1024-16@85
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1600x1200-16@75
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1680x1050-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1600x1200-16@85
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1280x1024-16@100
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1800x1440-16@64
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1800x1440-16@70
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 512x384-16@78
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 512x384-16@85
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 320x200-16@70
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 320x240-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 320x240-16@72
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 400x300-16@56
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 400x300-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 400x300-16@72
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 480x300-16@56
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 480x300-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 480x300-16@63
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 480x300-16@72
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1920x1200-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1152x768-16@60
> Error=3D
> 0********************************************************************Tryi
> ng mode noname 1366x768-16@60
> Error=3D
> 0********************************************************************Tryi
> ng default video mode
> Trying mode noname 800x480-16@60
> Error=3D
> 0********************************************************************Tryi
> ng default mode
> Console: switching to colour frame buffer device 114x34
> stopped custom tracer.
> Oops: Exception in kernel mode, sig: 4 [#1]
> PREEMPT pcm030
> Modules linked in:
> NIP: 00000900 LR: c011d94c CTR: c011daf4
> REGS: c3fe7a30 TRAP: 0700   Not tainted  (2.6.23.1-rt5-pcm030-1trunk)
> MSR: 00081000 <ME>  CR: 42042022  XER: 00000000
> TASK =3D c3fe5c00[1] 'swapper' THREAD: c3fe6000
> GPR00: ffffffff c3fe7ae0 c3fe5c00 c5128bfc 00000000 00010001 00000020
> 00000020
> GPR08: 00000000 00010001 ffffffff 00000020 c3f5f800 fffffffb 03fcb000
> ffffffff
> GPR16: 00000001 00000000 c3fe7f78 c024a748 00000000 00000000 00000002
> 000001e0
> GPR24: 00010001 c011daf4 00000020 c3f5f800 c5128bfc 00000000 00000005
> 000001b0
> NIP [00000900] 0x900
> LR [c011d94c] cfb_fillrect+0x144/0x2ec
> Call Trace:
> [c3fe7ae0] [c00fd90c] number+0x354/0x374 (unreliable)
> [c3fe7b20] [c011c9c4] bit_clear_margins+0x100/0x104
> [c3fe7b60] [c0116254] fbcon_clear_margins+0x7c/0x80
> [c3fe7b70] [c011ba34] fbcon_switch+0x45c/0x630
> [c3fe7c40] [c01350cc] redraw_screen+0x158/0x200
> [c3fe7c60] [c0137878] bind_con_driver+0x2ec/0x428
> [c3fe7ca0] [c01379f4] take_over_console+0x40/0x58
> [c3fe7cc0] [c01199d0] fbcon_takeover+0x88/0xf8
> [c3fe7cd0] [c011a694] fbcon_event_notify+0x8e4/0x908
> [c3fe7da0] [c002e5a4] notifier_call_chain+0x60/0xb0
> [c3fe7dc0] [c002f2bc] __blocking_notifier_call_chain+0x50/0x74
> [c3fe7de0] [c011165c] fb_notifier_call_chain+0x24/0x34
> [c3fe7df0] [c0112600] register_framebuffer+0x120/0x1d0
> [c3fe7e50] [c0283380] vfb_probe+0x164/0x220
> [c3fe7e70] [c0142284] platform_drv_probe+0x20/0x30
> [c3fe7e80] [c01408e0] driver_probe_device+0xb8/0x1ec
> [c3fe7ea0] [c0140a98] __driver_attach+0x84/0x88
> [c3fe7ec0] [c013fbbc] bus_for_each_dev+0x58/0x94
> [c3fe7ef0] [c01406f0] driver_attach+0x24/0x34
> [c3fe7f00] [c0140018] bus_add_driver+0x98/0x1d8
> [c3fe7f20] [c0140c40] driver_register+0x58/0xa0
> [c3fe7f30] [c0142618] platform_driver_register+0x98/0xa8
> [c3fe7f40] [c0283534] vfb_init+0xf8/0x120
> [c3fe7f70] [c02711c4] kernel_init+0xa8/0x2bc
> [c3fe7ff0] [c000fd2c] kernel_thread+0x44/0x60
> Instruction dump:
> Unable to handle kernel paging request for data at address 0xffff83bc
> Faulting instruction address: 0xc00fd970
> Oops: Kernel access of bad area, sig: 11 [#2]
> PREEMPT pcm030
> Modules linked in:
> NIP: c00fd970 LR: c00fe29c CTR: 00000000
> REGS: c3fe7790 TRAP: 0300   Not tainted  (2.6.23.1-rt5-pcm030-1trunk)
> MSR: 00001032 <ME,IR,DR>  CR: 28044088  XER: 00000000
> DAR: ffff83bc, DSISR: 20000000
> TASK =3D c3fe5c00[1] 'swapper' THREAD: c3fe6000
> GPR00: c00fe29c c3fe7840 c3fe5c00 00000000 00000400 ffff83bc c3fe78f8
> 00004000
> GPR08: 00000000 00000002 ffff83bc c0296cc8 28042088 fffffffb 03fcb000
> ffffffff
> GPR16: 00000001 00000000 c3fe7f78 c024a748 00000000 00000000 c0290000
> c0290000
> GPR24: 00001032 c02bd934 c3fe78f8 c0250000 ffff83bc c02c0000 c02bdd34
> c02bd934
> NIP [c00fd970] vsnprintf+0x44/0x80c
> LR [c00fe29c] vscnprintf+0x18/0x1ac
> Call Trace:
> [c3fe7840] [c0045948] rt_down_trylock+0x20/0x70 (unreliable)
> [c3fe7870] [c00fe29c] vscnprintf+0x18/0x1ac
> [c3fe7880] [c001fb88] vprintk+0x94/0x3c4
> [c3fe78f0] [c001ff08] printk+0x50/0x60
> [c3fe7930] [c0008890] show_regs+0x2c4/0x2e8
> [c3fe7960] [c000d3bc] die+0xe8/0x198
> [c3fe7980] [c000d5e8] _exception+0x38/0x104
> [c3fe7a20] [c000f534] ret_from_except_full+0x0/0x4c
> --- Exception: 700 at 0x900
>     LR =3D cfb_fillrect+0x144/0x2ec
> [c3fe7ae0] [c00fd90c] number+0x354/0x374 (unreliable)
> [c3fe7b20] [c011c9c4] bit_clear_margins+0x100/0x104
> [c3fe7b60] [c0116254] fbcon_clear_margins+0x7c/0x80
> [c3fe7b70] [c011ba34] fbcon_switch+0x45c/0x630
> [c3fe7c40] [c01350cc] redraw_screen+0x158/0x200
> [c3fe7c60] [c0137878] bind_con_driver+0x2ec/0x428
> [c3fe7ca0] [c01379f4] take_over_console+0x40/0x58
> [c3fe7cc0] [c01199d0] fbcon_takeover+0x88/0xf8
> [c3fe7cd0] [c011a694] fbcon_event_notify+0x8e4/0x908
> [c3fe7da0] [c002e5a4] notifier_call_chain+0x60/0xb0
> [c3fe7dc0] [c002f2bc] __blocking_notifier_call_chain+0x50/0x74
> [c3fe7de0] [c011165c] fb_notifier_call_chain+0x24/0x34
> [c3fe7df0] [c0112600] register_framebuffer+0x120/0x1d0
> [c3fe7e50] [c0283380] vfb_probe+0x164/0x220
> [c3fe7e70] [c0142284] platform_drv_probe+0x20/0x30
> [c3fe7e80] [c01408e0] driver_probe_device+0xb8/0x1ec
> [c3fe7ea0] [c0140a98] __driver_attach+0x84/0x88
> [c3fe7ec0] [c013fbbc] bus_for_each_dev+0x58/0x94
> [c3fe7ef0] [c01406f0] driver_attach+0x24/0x34
> [c3fe7f00] [c0140018] bus_add_driver+0x98/0x1d8
> [c3fe7f20] [c0140c40] driver_register+0x58/0xa0
> [c3fe7f30] [c0142618] platform_driver_register+0x98/0xa8
> [c3fe7f40] [c0283534] vfb_init+0xf8/0x120
> [c3fe7f70] [c02711c4] kernel_init+0xa8/0x2bc
> [c3fe7ff0] [c000fd2c] kernel_thread+0x44/0x60
> Instruction dump:
> 7c791b78 7cda3378 90010034 91810010 90a10008 419007bc 7fc32214 7f83f040
> 419d0260 81410008 7f3fcb78 38600000 <880a0000> 2f800000 419e0044 7f3fcb78
> Kernel panic - not syncing: Attempted to kill init!
> Call Trace:
> [c3fe7690] [c0007dfc] show_stack+0x3c/0x194 (unreliable)
> [c3fe76c0] [c001f004] panic+0x9c/0x174
> [c3fe7710] [c0023214] do_exit+0x6ec/0x884
> [c3fe7750] [c000d46c] kernel_bad_stack+0x0/0x4c
> [c3fe7770] [c00120ac] bad_page_fault+0x90/0xd8
> [c3fe7780] [c000f388] handle_page_fault+0x7c/0x80
> --- Exception: 300 at vsnprintf+0x44/0x80c
>     LR =3D vscnprintf+0x18/0x1ac
> [c3fe7840] [c0045948] rt_down_trylock+0x20/0x70 (unreliable)
> [c3fe7870] [c00fe29c] vscnprintf+0x18/0x1ac
> [c3fe7880] [c001fb88] vprintk+0x94/0x3c4
> [c3fe78f0] [c001ff08] printk+0x50/0x60
> [c3fe7930] [c0008890] show_regs+0x2c4/0x2e8
> [c3fe7960] [c000d3bc] die+0xe8/0x198
> [c3fe7980] [c000d5e8] _exception+0x38/0x104
> [c3fe7a20] [c000f534] ret_from_except_full+0x0/0x4c
> --- Exception: 700 at 0x900
>     LR =3D cfb_fillrect+0x144/0x2ec
> [c3fe7ae0] [c00fd90c] number+0x354/0x374 (unreliable)
> [c3fe7b20] [c011c9c4] bit_clear_margins+0x100/0x104
> [c3fe7b60] [c0116254] fbcon_clear_margins+0x7c/0x80
> [c3fe7b70] [c011ba34] fbcon_switch+0x45c/0x630
> [c3fe7c40] [c01350cc] redraw_screen+0x158/0x200
> [c3fe7c60] [c0137878] bind_con_driver+0x2ec/0x428
> [c3fe7ca0] [c01379f4] take_over_console+0x40/0x58
> [c3fe7cc0] [c01199d0] fbcon_takeover+0x88/0xf8
> [c3fe7cd0] [c011a694] fbcon_event_notify+0x8e4/0x908
> [c3fe7da0] [c002e5a4] notifier_call_chain+0x60/0xb0
> [c3fe7dc0] [c002f2bc] __blocking_notifier_call_chain+0x50/0x74
> [c3fe7de0] [c011165c] fb_notifier_call_chain+0x24/0x34
> [c3fe7df0] [c0112600] register_framebuffer+0x120/0x1d0
> [c3fe7e50] [c0283380] vfb_probe+0x164/0x220
> [c3fe7e70] [c0142284] platform_drv_probe+0x20/0x30
> [c3fe7e80] [c01408e0] driver_probe_device+0xb8/0x1ec
> [c3fe7ea0] [c0140a98] __driver_attach+0x84/0x88
> [c3fe7ec0] [c013fbbc] bus_for_each_dev+0x58/0x94
> [c3fe7ef0] [c01406f0] driver_attach+0x24/0x34
> [c3fe7f00] [c0140018] bus_add_driver+0x98/0x1d8
> [c3fe7f20] [c0140c40] driver_register+0x58/0xa0
> [c3fe7f30] [c0142618] platform_driver_register+0x98/0xa8
> [c3fe7f40] [c0283534] vfb_init+0xf8/0x120
> [c3fe7f70] [c02711c4] kernel_init+0xa8/0x2bc
> [c3fe7ff0] [c000fd2c] kernel_thread+0x44/0x60
> Rebooting in 180 seconds..
> =20
> Hello,
>=20
> Alex_SYS wrote:
>> Hello, I have the problem that I need a Framebuffer resolution 800x480!
>> Since now I have filled the fb_info, var and fix Structs!
>> But there was the problem with the resolution!
>> I have found out that the problem is the videomode!
>> In modedb there is unfortunately no 800x480 Videomode, and I have tried
>> my
>> own 800x480 Struct, but the Kernel does`t want my settings (I tried to
>> change an 800x600 to 800x480 only by changing yres to 480).
>> Can someone tell me please a working fb_videomode struct for 800x480?
>=20
> Values for 800x480 fb_videomode depend on the TFT-panel that
> you are using. Without the spec of this panel it is hard to guess.
> It is also hard to guess the value for .pixclock as we do not know
> if internal or external clock is used as the source for display
> reference clock. What is the value of GDC DCM0 register (at
> offset 0x1fd0000 or 0x1fd0100 from the GDC base)?
>=20
> Try something like this:
> .xres =3D 800
> .yres =3D 480
> .pixclock =3D 40000
> .left_margin =3D 86
> .right_margin =3D 42
> .upper_margin =3D 33
> .lower_margin =3D 10
> .hsync_len =3D 128
> .vsync_len =3D 2
>=20
>> The syncs are setted up by U-Boot .
>=20
>>then you probably should retrieve proper values for fb_videomode
>>from display controller registers set up by U-Boot. If you do not
>>have the spec for your panel, it is the way to go. Consult the
>>GDC manual (Display control registers section) and
>>Documentation/fb/framebuffer.txt in the linux source tree.
>=20
> Hello, the physical settings for sync are made by U-Boot and working!
> But in Lunux when I use 800x480, the screen is well, but the Kernel
> crashes at Bootup!
> Using 800x600 works!
> Now I need only "Dummy" settings, that I can tell Linux I would like
> 800x480 and the Kernel doesn`t crash!
> I don`t know exactly why the Kernel crashes, I know only that the modedB
> 800x600 and so on work!
> I will try your settings immediately!
> Thanks
>=20
> Alex
>=20
> Best regards,
> Anatolij
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>=20
>=20
>=20

--=20
View this message in context: http://www.nabble.com/Videomode-800x480-tp184=
70632p18502863.html
Sent from the linuxppc-embedded mailing list archive at Nabble.com.

^ permalink raw reply

* [PATCH 1/3] powerpc: Add a #define for aligning to a long-sized boundary
From: Michael Ellerman @ 2008-07-17  7:17 UTC (permalink / raw)
  To: linuxppc-dev

Add a #define for aligning to a long-sized boundary. It would be nice
to use sizeof(long) for this, but that requires generating the value
with asm-offsets.c, and asm-offsets.c includes asm-compat.h and we
descend into some sort of recursive include hell.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 include/asm-powerpc/asm-compat.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/asm-powerpc/asm-compat.h b/include/asm-powerpc/asm-compat.h
index 8ec2e1d..8f0fe79 100644
--- a/include/asm-powerpc/asm-compat.h
+++ b/include/asm-powerpc/asm-compat.h
@@ -22,6 +22,7 @@
 #define PPC_STL		stringify_in_c(std)
 #define PPC_LCMPI	stringify_in_c(cmpdi)
 #define PPC_LONG	stringify_in_c(.llong)
+#define PPC_LONG_ALIGN	stringify_in_c(.balign 8)
 #define PPC_TLNEI	stringify_in_c(tdnei)
 #define PPC_LLARX	stringify_in_c(ldarx)
 #define PPC_STLCX	stringify_in_c(stdcx.)
@@ -43,6 +44,7 @@
 #define PPC_STL		stringify_in_c(stw)
 #define PPC_LCMPI	stringify_in_c(cmpwi)
 #define PPC_LONG	stringify_in_c(.long)
+#define PPC_LONG_ALIGN	stringify_in_c(.balign 4)
 #define PPC_TLNEI	stringify_in_c(twnei)
 #define PPC_LLARX	stringify_in_c(lwarx)
 #define PPC_STLCX	stringify_in_c(stwcx.)
-- 
1.5.5

^ 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