LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: RFC: issues concerning the next NAPI interface
From: David Miller @ 2007-08-27 20:37 UTC (permalink / raw)
  To: ossthema
  Cc: tklein, themann, stefan.roscher, netdev, jchapman, raisch,
	linux-kernel, linuxppc-dev, akepner, meder, shemminger
In-Reply-To: <200708271147.01890.ossthema@de.ibm.com>

From: Jan-Bernd Themann <ossthema@de.ibm.com>
Date: Mon, 27 Aug 2007 11:47:01 +0200

> So the question is simply: Do we want drivers that need (benefit
> from) a timer based polling support to implement their own timers
> each, or should there be a generic support?

I'm trying to figure out how an hrtimer implementation would
even work.

Would you start the timer from the chip interrupt handler?  If so,
that's taking two steps backwards as you've already taken all of the
overhead of running the interrupt handler.

^ permalink raw reply

* Re: RFC: issues concerning the next NAPI interface
From: David Miller @ 2007-08-27 21:02 UTC (permalink / raw)
  To: jchapman
  Cc: tklein, themann, stefan.roscher, netdev, linux-kernel, raisch,
	linuxppc-dev, akepner, meder, ossthema, shemminger
In-Reply-To: <46D2F301.7050105@katalix.com>

From: James Chapman <jchapman@katalix.com>
Date: Mon, 27 Aug 2007 16:51:29 +0100

> To implement this, there's no need for timers, hrtimers or generic NAPI 
> support that others have suggested. A driver's poll() would set an 
> internal flag and record the current jiffies value when finding 
> workdone=0 rather than doing an immediate napi_complete(). Early in 
> poll() it would test this flag and if set, do a low-cost test to see if 
> it had any work to do. If no work, it would check the saved jiffies 
> value and do the napi_complete() only if no work has been done for a 
> configurable number of jiffies. This keeps interrupts disabled longer at 
> the expense of many more calls to poll() where no work is done. So 
> critical to this scheme is modifying the driver's poll() to fastpath the 
> case of having no work to do while waiting for its local jiffy count to 
> expire.
> 
> Here's an untested patch for tg3 that illustrates the idea.

It's only going to work with hrtimers, these interfaces can
process at least 100,000 per jiffies tick.

And the hrtimer granularity is going to need to be significantly low,
and futhermore you're adding a guaranteed extra interrupt (for the
hrtimer firing) in these cases where we're exactly trying to avoid is
more interrupts.

If you can make it work, fine, but it's going to need to be at a
minimum disabled when the hrtimer granularity is not sufficient.

But there are huger fish to fry for you I think.  Talk to your
platform maintainers and ask for an interface for obtaining
a flat static distribution of interrupts to cpus in order to
support multiqueue NAPI better.

In your previous postings you made arguments saying that the
automatic placement of interrupts to cpus made everything
bunch of to a single cpu and you wanted to propagate the
NAPI work to other cpu's software interrupts from there.

That logic is bogus, because it merely proves that the hardware
interrupt distribution is broken.  If it's a bad cpu to run
software interrupts on, it's also a bad cpu to run hardware
interrupts on.

^ permalink raw reply

* Re: RFC: issues concerning the next NAPI interface
From: James Chapman @ 2007-08-27 21:41 UTC (permalink / raw)
  To: David Miller
  Cc: tklein, themann, stefan.roscher, netdev, linux-kernel, raisch,
	linuxppc-dev, akepner, meder, ossthema, shemminger
In-Reply-To: <20070827.140251.95055210.davem@davemloft.net>

David Miller wrote:
> From: James Chapman <jchapman@katalix.com>
> Date: Mon, 27 Aug 2007 16:51:29 +0100
> 
>> To implement this, there's no need for timers, hrtimers or generic NAPI 
>> support that others have suggested. A driver's poll() would set an 
>> internal flag and record the current jiffies value when finding 
>> workdone=0 rather than doing an immediate napi_complete(). Early in 
>> poll() it would test this flag and if set, do a low-cost test to see if 
>> it had any work to do. If no work, it would check the saved jiffies 
>> value and do the napi_complete() only if no work has been done for a 
>> configurable number of jiffies. This keeps interrupts disabled longer at 
>> the expense of many more calls to poll() where no work is done. So 
>> critical to this scheme is modifying the driver's poll() to fastpath the 
>> case of having no work to do while waiting for its local jiffy count to 
>> expire.
>>
>> Here's an untested patch for tg3 that illustrates the idea.
> 
> It's only going to work with hrtimers, these interfaces can
> process at least 100,000 per jiffies tick.

I don't understand where hrtimers or interface speed comes in. If the 
CPU is fast enough to call poll() 100,000 times per jiffies tick, it 
means 100,000 wasted poll() calls while the netdev migrates from active 
to poll-off state. Hence the need to fastpath the "no work" case in the 
netdev's poll(). These extra poll() calls are tolerable if it avoids 
NAPI thrashing between poll-on and poll-off states for certain packet rates.

> And the hrtimer granularity is going to need to be significantly low,
> and futhermore you're adding a guaranteed extra interrupt (for the
> hrtimer firing) in these cases where we're exactly trying to avoid is
> more interrupts.
> 
> If you can make it work, fine, but it's going to need to be at a
> minimum disabled when the hrtimer granularity is not sufficient.
> 
> But there are huger fish to fry for you I think.  Talk to your
> platform maintainers and ask for an interface for obtaining
> a flat static distribution of interrupts to cpus in order to
> support multiqueue NAPI better.
> 
> In your previous postings you made arguments saying that the
> automatic placement of interrupts to cpus made everything
> bunch of to a single cpu and you wanted to propagate the
> NAPI work to other cpu's software interrupts from there.

I don't recall saying anything in previous posts about this. Are you 
confusing my posts with Jan-Bernd's? Jan-Bernd has been talking about 
using hrtimers to _reschedule_ NAPI. My posts are suggesting an 
alternative mechanism that keeps NAPI active (with interrupts disabled) 
for a jiffy or two after it would otherwise have gone idle in order to 
avoid too many interrupts when the packet rate is such that NAPI 
thrashes between poll-on and poll-off.

> That logic is bogus, because it merely proves that the hardware
> interrupt distribution is broken.  If it's a bad cpu to run
> software interrupts on, it's also a bad cpu to run hardware
> interrupts on.

-- 
James Chapman
Katalix Systems Ltd
http://www.katalix.com
Catalysts for your Embedded Linux software development

^ permalink raw reply

* Re: RFC: issues concerning the next NAPI interface
From: David Miller @ 2007-08-27 21:56 UTC (permalink / raw)
  To: jchapman
  Cc: tklein, themann, stefan.roscher, netdev, linux-kernel, raisch,
	linuxppc-dev, akepner, meder, ossthema, shemminger
In-Reply-To: <46D34517.4010505@katalix.com>

From: James Chapman <jchapman@katalix.com>
Date: Mon, 27 Aug 2007 22:41:43 +0100

> I don't recall saying anything in previous posts about this. Are you 
> confusing my posts with Jan-Bernd's?

Yes, my bad.

> Jan-Bernd has been talking about using hrtimers to _reschedule_
> NAPI. My posts are suggesting an alternative mechanism that keeps
> NAPI active (with interrupts disabled) for a jiffy or two after it
> would otherwise have gone idle in order to avoid too many interrupts
> when the packet rate is such that NAPI thrashes between poll-on and
> poll-off.

So in this scheme what runs ->poll() to process incoming packets?
The hrtimer?

^ permalink raw reply

* Re: what is ~1MB of memory allocated at fffea000-fffff000 on ppc64?
From: Chris Friesen @ 2007-08-27 22:05 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: linuxppc-dev
In-Reply-To: <20070827203157.GD13612@kryten>

Anton Blanchard wrote:
> Hi,
> 
> 
>>I've got a ppc64 box running 2.6.14.  64-bit kernel, 32-bit userspace. 
>>It has a ~86KB chunk of memory near the top of the process address 
>>space, and I'm not sure who's setting it up and what the purpose is.  In 
>>/proc/<pid>/maps it looks like this:
>>
>>fffea000-fffff000 rw-p fffea000 00:00 0
>>
>>Can anyone enlighten me as to what this is for and who is allocating it?
> 
> 
> Looks like your process stack. BTW we leave the top page
> (0xfffff000 - 0xffffffff) unmapped mostly because of test cases that
> expect
> 
> *(unsigned long *)-1UL
> 
> to fail.


Doh.  Of course, that's almost certainly it.

For some background, we're running an emulator that uses a null pointer 
value of 0xffff0000 and we want any accesses to that address to trap.

Do you anticipate any issues with the following change?

-#define TASK_SIZE_USER32 (0x0000000100000000UL - (1*PAGE_SIZE))
+#define TASK_SIZE_USER32 (0x00000000FFFF0000UL - (1*PAGE_SIZE))


Thanks,

Chris

^ permalink raw reply

* Re: what is ~1MB of memory allocated at fffea000-fffff000 on ppc64?
From: Anton Blanchard @ 2007-08-27 23:19 UTC (permalink / raw)
  To: Chris Friesen; +Cc: linuxppc-dev
In-Reply-To: <46D34A9E.7010501@nortel.com>

 
Hi,

> For some background, we're running an emulator that uses a null pointer 
> value of 0xffff0000 and we want any accesses to that address to trap.

Weird :)

> Do you anticipate any issues with the following change?
> 
> -#define TASK_SIZE_USER32 (0x0000000100000000UL - (1*PAGE_SIZE))
> +#define TASK_SIZE_USER32 (0x00000000FFFF0000UL - (1*PAGE_SIZE))

Should be OK, for a 64kB kernel we will put the stack top at 0xFFFF0000
anyway.

Anton

^ permalink raw reply

* Re: [PATCH 3/3] [POWERPC] Add PCI support for AMCC 440EPx (sequoia)
From: David Gibson @ 2007-08-28  0:21 UTC (permalink / raw)
  To: Stefan Roese; +Cc: linuxppc-dev
In-Reply-To: <200708270821.35209.sr@denx.de>

On Mon, Aug 27, 2007 at 08:21:35AM +0200, Stefan Roese wrote:
> On Monday 27 August 2007, David Gibson wrote:
> > On Sat, Aug 25, 2007 at 01:30:01PM +0400, Vitaly Bordug wrote:
[snip]
> > Unless there really is something peculiar about the EPx bridge
> > compared to say the GP, EP and other 4xx bridges, this should have a
> > more general name.
> 
> We originally started naming this file sequoia-pci.c and changed it to be 
> 440EPx specific (just by renaming). But you are right of course. We should 
> make it even more generic for 4xx PCI support. Perhaps we will overlook some 
> problems with other 4xx platforms, but those should be solved when other 
> platforms (Josh: 440ep and 405gp? ;)) will be added.
> 
> So what should it be called? arch/powerpc/syslib/ppc4xx_pci.c ?

Sounds ok, except that it's sysdev, not syslib in arch/powerpc of
course.

-- 
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

* Re: RFC: [PATCH] Copy over headers from arch/powerpc to arch/ppc to decouple them
From: David Gibson @ 2007-08-28  1:38 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0708270945580.11455@blarg.am.freescale.net>

On Mon, Aug 27, 2007 at 09:49:04AM -0500, Kumar Gala wrote:
> Move over includes files that have CONFIG_PPC_MERGE in them to decouple
> to interdepencies between ARCH=powerpc & ARCH=ppc.
> 
> Duplicate the following headers in both locations and remove CONFIG_PPC_MERGE:
> 
> <asm/dcr.h>
> <asm/i8259.h>
> <asm/ipic.h>
> <asm/irq.h>
> 
> ---
> 
> Not sure what people think about this since removing include asm-powerpc
> from ARCH=ppc builds will require a bunch of other copies beyond these
> which had a CONFIG_PPC_MERGE in them.

Seems sensible to me.

-- 
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

* Re: RFC: [PATCH] Copy over headers from arch/powerpc to arch/ppc to decouple them
From: David Gibson @ 2007-08-28  1:40 UTC (permalink / raw)
  To: Kumar Gala, linuxppc-dev
In-Reply-To: <20070828013808.GC3470@localhost.localdomain>

On Tue, Aug 28, 2007 at 11:38:08AM +1000, David Gibson wrote:
> On Mon, Aug 27, 2007 at 09:49:04AM -0500, Kumar Gala wrote:
> > Move over includes files that have CONFIG_PPC_MERGE in them to decouple
> > to interdepencies between ARCH=powerpc & ARCH=ppc.
> > 
> > Duplicate the following headers in both locations and remove CONFIG_PPC_MERGE:
> > 
> > <asm/dcr.h>
> > <asm/i8259.h>
> > <asm/ipic.h>
> > <asm/irq.h>
> > 
> > ---
> > 
> > Not sure what people think about this since removing include asm-powerpc
> > from ARCH=ppc builds will require a bunch of other copies beyond these
> > which had a CONFIG_PPC_MERGE in them.
> 
> Seems sensible to me.

Hrm... and it might be worth splitting arch/powerpc/kernel/irq.c,
too, which also has a very large #ifdef PPC_MERGE section.

-- 
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

* Document and implement an improved flash device binding for powerpc
From: David Gibson @ 2007-08-28  3:47 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev

This patch replaces the binding for flash chips in
booting-without-of.txt with an clarified and improved version.  It
also makes drivers/mtd/maps/physmap_of.c recognize this new binding.
Finally it revises the Ebony device tree source to use the new binding
as an example.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
I don't know that this is ready yet, but I thought I'd try to kick
along the rather stalled process of getting this new flash binding in
place by sending out my current draft.

Index: working-2.6/Documentation/powerpc/booting-without-of.txt
===================================================================
--- working-2.6.orig/Documentation/powerpc/booting-without-of.txt	2007-08-28 13:25:42.000000000 +1000
+++ working-2.6/Documentation/powerpc/booting-without-of.txt	2007-08-28 13:38:10.000000000 +1000
@@ -1757,45 +1757,46 @@ platforms are moved over to use the flat
 		};
 	};
 
-    j) Flash chip nodes
+   j) CFI or JEDEC memory-mapped NOR flash
 
     Flash chips (Memory Technology Devices) are often used for solid state
     file systems on embedded devices.
 
-    Required properties:
-
-     - device_type : has to be "rom"
-     - compatible : Should specify what this flash device is compatible with.
-       Currently, this is most likely to be "direct-mapped" (which
-       corresponds to the MTD physmap mapping driver).
-     - reg : Offset and length of the register set (or memory mapping) for
-       the device.
-     - bank-width : Width of the flash data bus in bytes. Required
-       for the NOR flashes (compatible == "direct-mapped" and others) ONLY.
-
-    Recommended properties :
-
-     - partitions : Several pairs of 32-bit values where the first value is
-       partition's offset from the start of the device and the second one is
-       partition size in bytes with LSB used to signify a read only
-       partition (so, the partition size should always be an even number).
-     - partition-names : The list of concatenated zero terminated strings
-       representing the partition names.
-     - probe-type : The type of probe which should be done for the chip
-       (JEDEC vs CFI actually). Valid ONLY for NOR flashes.
-
-   Example:
-
- 	flash@ff000000 {
- 		device_type = "rom";
- 		compatible = "direct-mapped";
- 		probe-type = "CFI";
- 		reg = <ff000000 01000000>;
- 		bank-width = <4>;
- 		partitions = <00000000 00f80000
- 			      00f80000 00080001>;
- 		partition-names = "fs\0firmware";
- 	};
+     - compatible : should contain the specific model of flash chip(s)
+       used, if known, followed by either "cfi-flash" or "jedec-flash"
+     - reg : Address range of the flash chip
+     - bank-width : Width (in bytes) of the flash bank.  Equal to the
+       device width times the number of interleaved chips.
+     - device-width : (optional) Width of a single flash chip.  If
+       omitted, assumed to be equal to 'bank-width'.
+     - #address-cells, #size-cells : Must be present if the flash has
+       sub-nodes representing partitions (see below).  In this case
+       both #address-cells and #size-cells must be equal to 1.
+
+    For JEDEC compatible devices, the following additional properties
+    are defined:
+
+     - vendor-id : Contains the flash chip's vendor id (1 byte).
+     - device-id : Contains the flash chip's device id (1 byte).
+
+    In addition to the information on the flash bank itself, the
+    device tree may optionally contain additional information
+    describing partitions of the flash address space.  This can be
+    used on platforms which have strong conventions about which
+    portions of the flash are used for what purposes, but which don't
+    use an on-flash partition table such as RedBoot.
+
+    Each partitions is represented as a sub-node of the flash device.
+    Each node's name represents the name of the corresponding
+    partition of the flash device.
+
+    Flash partitions
+     - reg : The partition's offset and size within the flash bank.
+     - read-only : (optional) This parameter, if present, is a hint to
+       Linux that this flash partition should only be mounted
+       read-only.  This is usually used for flash partitions
+       containing early-boot firmware images or data which should not
+       be clobbered.
 
    k) Global Utilities Block
 
Index: working-2.6/drivers/mtd/maps/physmap_of.c
===================================================================
--- working-2.6.orig/drivers/mtd/maps/physmap_of.c	2007-08-28 13:25:42.000000000 +1000
+++ working-2.6/drivers/mtd/maps/physmap_of.c	2007-08-28 13:26:43.000000000 +1000
@@ -4,6 +4,9 @@
  * Copyright (C) 2006 MontaVista Software Inc.
  * Author: Vitaly Wool <vwool@ru.mvista.com>
  *
+ * Revised to handle newer style flash binding by:
+ *   Copyright (C) 2007 David Gibson, IBM Corporation.
+ *
  * 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 of the  License, or (at your
@@ -30,56 +33,129 @@ struct physmap_flash_info {
 	struct map_info		map;
 	struct resource		*res;
 #ifdef CONFIG_MTD_PARTITIONS
-	int			nr_parts;
 	struct mtd_partition	*parts;
 #endif
 };
 
-static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
-#ifdef CONFIG_MTD_PARTITIONS
-static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
-#endif
-
 #ifdef CONFIG_MTD_PARTITIONS
-static int parse_flash_partitions(struct device_node *node,
-		struct mtd_partition **parts)
+static int parse_obsolete_partitions(struct physmap_flash_info *info,
+				     struct device_node *dp)
 {
-	int i, plen, retval = -ENOMEM;
-	const  u32  *part;
-	const  char *name;
-
-	part = of_get_property(node, "partitions", &plen);
-	if (part == NULL)
-		goto err;
-
-	retval = plen / (2 * sizeof(u32));
-	*parts = kzalloc(retval * sizeof(struct mtd_partition), GFP_KERNEL);
-	if (*parts == NULL) {
+	int i, plen, nr_parts;
+	const struct {
+		u32 offset, len;
+	} *part;
+	const char *names;
+
+	part = of_get_property(dp, "partitions", &plen);
+	if (!part)
+		return -ENOENT;
+
+	nr_parts = plen / sizeof(part[0]);
+
+	info->parts = kzalloc(nr_parts * sizeof(struct mtd_partition), GFP_KERNEL);
+	if (!info->parts) {
 		printk(KERN_ERR "Can't allocate the flash partition data!\n");
-		goto err;
+		return -ENOMEM;
 	}
 
-	name = of_get_property(node, "partition-names", &plen);
+	names = of_get_property(dp, "partition-names", &plen);
 
-	for (i = 0; i < retval; i++) {
-		(*parts)[i].offset = *part++;
-		(*parts)[i].size   = *part & ~1;
-		if (*part++ & 1) /* bit 0 set signifies read only partition */
-			(*parts)[i].mask_flags = MTD_WRITEABLE;
+	for (i = 0; i < nr_parts; i++) {
+		info->parts[i].offset = part->offset;
+		info->parts[i].size   = part->len & ~1;
+		if (part->len & 1) /* bit 0 set signifies read only partition */
+			info->parts[i].mask_flags = MTD_WRITEABLE;
 
-		if (name != NULL && plen > 0) {
-			int len = strlen(name) + 1;
+		if (names && (plen > 0)) {
+			int len = strlen(names) + 1;
 
-			(*parts)[i].name = (char *)name;
+			info->parts[i].name = (char *)names;
 			plen -= len;
-			name += len;
-		} else
-			(*parts)[i].name = "unnamed";
+			names += len;
+		} else {
+			info->parts[i].name = "unnamed";
+		}
+
+		part++;
 	}
-err:
-	return retval;
+
+	return nr_parts;
 }
-#endif
+
+static int __devinit process_partitions(struct physmap_flash_info *info,
+					struct of_device *dev)
+{
+	static const char *part_probe_types[]
+		= { "cmdlinepart", "RedBoot", NULL };
+	struct device_node *dp = dev->node, *pp;
+	int nr_parts, i, err;
+
+	/* First look for RedBoot table or partitions on the command
+	 * line, these take precedence over device tree information */
+	nr_parts = parse_mtd_partitions(info->mtd, part_probe_types,
+					&info->parts, 0);
+	if (nr_parts > 0) {
+		add_mtd_partitions(info->mtd, info->parts, err);
+		return 0;
+	}
+
+	/* First count the subnodes */
+	nr_parts = 0;
+	for (pp = dp->child; pp; pp = pp->sibling)
+		nr_parts++;
+
+	if (nr_parts) {
+		info->parts = kzalloc(nr_parts * sizeof(struct mtd_partition),
+				      GFP_KERNEL);
+		if (!info->parts) {
+			printk(KERN_ERR "Can't allocate the flash partition data!\n");
+			return -ENOMEM;
+		}
+
+		for (pp = dp->child, i = 0 ; pp; pp = pp->sibling, i++) {
+			const u32 *reg;
+			int len;
+
+			reg = of_get_property(pp, "reg", &len);
+			if (!reg || (len != 2*sizeof(u32))) {
+				dev_err(&dev->dev, "Invalid 'reg' on %s\n",
+					dp->full_name);
+				kfree(info->parts);
+				info->parts = NULL;
+				return -EINVAL;
+			}
+			info->parts[i].offset = reg[0];
+			info->parts[i].size = reg[1];
+
+			info->parts[i].name =
+				(char *)of_get_property(pp, "name", &len);
+
+			if (of_get_property(pp, "read-only", &len))
+				info->parts[i].mask_flags = MTD_WRITEABLE;
+		}
+	} else {
+		nr_parts = parse_obsolete_partitions(info, dp);
+	}
+
+	if (nr_parts < 0)
+		return nr_parts;
+
+	if (nr_parts > 0)
+		add_mtd_partitions(info->mtd, info->parts, nr_parts);
+	else
+		add_mtd_device(info->mtd);
+
+	return 0;
+}
+#else /* MTD_PARTITIONS */
+static int __devinit process_partitions(struct physmap_flash_info *info,
+					struct device_node *dev)
+{
+	add_mtd_device(info->mtd);
+	return 0;
+}
+#endif /* MTD_PARTITIONS */
 
 static int of_physmap_remove(struct of_device *dev)
 {
@@ -92,7 +168,7 @@ static int of_physmap_remove(struct of_d
 
 	if (info->mtd != NULL) {
 #ifdef CONFIG_MTD_PARTITIONS
-		if (info->nr_parts) {
+		if (info->parts) {
 			del_mtd_partitions(info->mtd);
 			kfree(info->parts);
 		} else {
@@ -115,13 +191,45 @@ static int of_physmap_remove(struct of_d
 	return 0;
 }
 
+/* Helper function to handle probing of the obsolete "direct-mapped"
+ * compatible binding, which has an extra "probe-type" property
+ * describing the type of flash probe necessary. */
+static struct mtd_info * __devinit obsolete_probe(struct of_device *dev,
+						  struct map_info *map)
+{
+	struct device_node *dp = dev->node;
+	const char *of_probe;
+	struct mtd_info *mtd;
+	static const char *rom_probe_types[]
+		= { "cfi_probe", "jedec_probe", "map_rom"};
+	int i;
+
+	of_probe = of_get_property(dp, "probe-type", NULL);
+	if (!of_probe) {
+		for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
+			mtd = do_map_probe(rom_probe_types[i], map);
+			if (mtd)
+				return mtd;
+		}
+		return NULL;
+	} else if (strcmp(of_probe, "CFI") == 0) {
+		return do_map_probe("cfi_probe", map);
+	} else if (strcmp(of_probe, "JEDEC") == 0) {
+		return do_map_probe("jedec_probe", map);
+	} else {
+ 		if (strcmp(of_probe, "ROM") != 0)
+			dev_dbg(&dev->dev, "obsolete_probe: don't know probe type "
+				"'%s', mapping as rom\n", of_probe);
+		return do_map_probe("mtd_rom", map);
+	}
+}
+
 static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match)
 {
 	struct device_node *dp = dev->node;
 	struct resource res;
 	struct physmap_flash_info *info;
-	const char **probe_type;
-	const char *of_probe;
+	const char *probe_type = (const char *)match->data;
 	const u32 *width;
 	int err;
 
@@ -174,21 +282,11 @@ static int __devinit of_physmap_probe(st
 
 	simple_map_init(&info->map);
 
-	of_probe = of_get_property(dp, "probe-type", NULL);
-	if (of_probe == NULL) {
-		probe_type = rom_probe_types;
-		for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
-			info->mtd = do_map_probe(*probe_type, &info->map);
-	} else if (!strcmp(of_probe, "CFI"))
-		info->mtd = do_map_probe("cfi_probe", &info->map);
-	else if (!strcmp(of_probe, "JEDEC"))
-		info->mtd = do_map_probe("jedec_probe", &info->map);
-	else {
- 		if (strcmp(of_probe, "ROM"))
-			dev_dbg(&dev->dev, "map_probe: don't know probe type "
-			"'%s', mapping as rom\n", of_probe);
-		info->mtd = do_map_probe("mtd_rom", &info->map);
-	}
+	if (probe_type)
+		info->mtd = do_map_probe(probe_type, &info->map);
+	else
+		info->mtd = obsolete_probe(dev, &info->map);
+
 	if (info->mtd == NULL) {
 		dev_err(&dev->dev, "map_probe failed\n");
 		err = -ENXIO;
@@ -196,19 +294,7 @@ static int __devinit of_physmap_probe(st
 	}
 	info->mtd->owner = THIS_MODULE;
 
-#ifdef CONFIG_MTD_PARTITIONS
-	err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
-	if (err > 0) {
-		add_mtd_partitions(info->mtd, info->parts, err);
-	} else if ((err = parse_flash_partitions(dp, &info->parts)) > 0) {
-		dev_info(&dev->dev, "Using OF partition information\n");
-		add_mtd_partitions(info->mtd, info->parts, err);
-		info->nr_parts = err;
-	} else
-#endif
-
-	add_mtd_device(info->mtd);
-	return 0;
+	return process_partitions(info, dev);
 
 err_out:
 	of_physmap_remove(dev);
@@ -221,6 +307,14 @@ err_out:
 
 static struct of_device_id of_physmap_match[] = {
 	{
+		.compatible	= "cfi-flash",
+		.data		= (void *)"cfi_probe",
+	},
+	{
+		.compatible	= "jedec-flash",
+		.data		= (void *)"jedec_probe",
+	},
+	{
 		.type		= "rom",
 		.compatible	= "direct-mapped"
 	},
Index: working-2.6/arch/powerpc/boot/dts/ebony.dts
===================================================================
--- working-2.6.orig/arch/powerpc/boot/dts/ebony.dts	2007-08-28 13:25:42.000000000 +1000
+++ working-2.6/arch/powerpc/boot/dts/ebony.dts	2007-08-28 13:41:00.000000000 +1000
@@ -142,13 +142,15 @@
 				interrupt-parent = <&UIC1>;
 
 				small-flash@0,80000 {
-					device_type = "rom";
-					compatible = "direct-mapped";
-					probe-type = "JEDEC";
+					compatible = "jedec-flash";
 					bank-width = <1>;
-					partitions = <0 80000>;
-					partition-names = "OpenBIOS";
 					reg = <0 80000 80000>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					OpenBIOS@0 {
+						reg = <0 80000>;
+						read-only;
+					};
 				};
 
 				ds1743@1,0 {
@@ -158,14 +160,17 @@
 				};
 
 				large-flash@2,0 {
-					device_type = "rom";
-					compatible = "direct-mapped";
-					probe-type = "JEDEC";
+					compatible = "jedec-flash";
 					bank-width = <1>;
-					partitions = <0 380000
-						      380000 80000>;
-					partition-names = "fs", "firmware";
 					reg = <2 0 400000>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					fs@0 {
+						reg = <0 380000>;
+					};
+					firmware@380000 {
+						reg = <380000 80000>;
+					};
 				};
 
 				ir@3,0 {

-- 
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

* [PATCH] qemu-system-ppc -prep initial port
From: Milton Miller @ 2007-08-28  4:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: firmware

Hi.

Some people have been asking about booting powerpc kernels on qemu.

Based on some comments about the existing rom for qemu, I looked
at OpenHackWare enough to discern how qemu started its execution
and how it gets its config.   

I then proceeded to write a wrapper patch to use as the rom and then
proceeded with a minimal platform (based on David Gibson's prep patch)
to boot a ARCH=powerpc kernel.

These patches are being posted early to allow others to use them,
they are not ready to be merged.

What works:
	-prep  (not default pmac, or core99 in later qemu)
	serial console in bootwrapper
	serial console in kernel (console=ttyS0)
	kernel must be loaded with --kernel=
		vmlinux, or vmlinuz (gzip'ed elf).
		zImage.qemu, zImage.initrd.qemu (with compiler assumptions)
	-initrd (optional)
	-append (optional)
	ide-disk and cdrom appear to work
	floppy is untested, and needs io port added.

What doesn't work:
	boot from disk
	vga (needs bios post, maybe pci)
	pci (config cycles are not working, at least on 0.6.3)

How it works:
	wrapper is compiled to run as rom
		copied from rom to ram (linked address)
		supplies initial device tree blob (because dtb = NULL)
		reads nvram for memory size, kernel, initrd, command line
	if invoked with device tree, then it only uses attached kernel
		initrd either attached or from kernel

what you need:
	2.6.23-rc3 + [ from powerpc.git for-2.6.24 branch ]
	commit 0602801c22ea1767cd0298b11da140bd5cb764d2
	    [POWERPC] bootwrapper: dt_xlate_range() bugfixes
	commit a73ac50c4787b1b28d5c94bb18c60352f5dd7d6f
	    [POWERPC] bootwrapper: Add dt_is_compatible()
	commit 6e913c67b3eb93e2b8bc1dc0ff854f00a760f41b
	    [POWERPC] bootwrapper: Add 16-bit I/O, sync(), eieio(), and barrier()
	commit dc4f397d6e385c4ea0fe9732df911a86f1a78c9a
	    [POWERPC] bootwrapper: serial_console_init() fixes
	commit 2f1d4899321be87bc5f0c4ee0e62c9d9ced05f80
	    [POWERPC] bootwrapper: Move linker symbols into ops.h

	tell wrapper where initrd is, so it can move it if needed
		http://patchwork.ozlabs.org/linuxppc/patch?id=12168

	tell code where vmlinuz is
		http://patchwork.ozlabs.org/linuxppc/patch?id=12178

	build rom without vmlinuz
		http://patchwork.ozlabs.org/linuxppc/patch?id=12180

	Subject: Move serial_dev_init to device_initcall()
		http://patchwork.ozlabs.org/linuxppc/patch?id=13097


To run:
	build ppc_rom.bin using CONFIG_DEVICE_TREE=prep.dts with the
	dtc installed.  This will be based on zBoot.qemu and will not
	have a kernel attached.  Put this in a directory and invoke
	qemu-system-ppc -prep -L <dir-with-rom> -kernel <kernel>
	where kernel is either zImage.qemu or a (possibly compressed)
	vmlinux elf , add ide drives, -append, and -initrd as desired.

My tree has all patches in for-2.6.24 that touch arch/powerpc/boot plus
ojn's patch plus my kexec series plus the prep patch, so there will be
some rejects, especially to makefiles etc.

The first hunk to main.c to check loader_info for a command line after
the fixup callback should be a seperate patch.

The boot/Makefile has a hack to avoid ovewriting qemu.dtb.

Index: kernel/arch/powerpc/boot/main.c
===================================================================
--- kernel.orig/arch/powerpc/boot/main.c	2007-08-24 03:49:35.000000000 -0500
+++ kernel/arch/powerpc/boot/main.c	2007-08-24 03:50:21.000000000 -0500
@@ -181,6 +181,11 @@ void start(void)
 	if (platform_ops.fixups)
 		platform_ops.fixups();
 
+	/* check again, in case fixups told us about it */
+	if ((loader_info.cmdline_len > 0) && (cmdline[0] == '\0'))
+		memmove(cmdline, loader_info.cmdline,
+			min(loader_info.cmdline_len, COMMAND_LINE_SIZE-1));
+
 	printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
 	       _start, get_sp());
 
Index: kernel/arch/powerpc/boot/qemu.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/qemu.c	2007-08-27 20:46:10.000000000 -0500
@@ -0,0 +1,237 @@
+/*
+ * QEMU PReP-specific stuff for the zImage boot wrapper.
+ *
+ * Copyright (C) 2007 Milton Miller, IBM Corp. <miltonm@bga.com>
+ * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License.
+ *
+ * nvram format obtained from OpenHackWare 0.4
+ * Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr)
+ *
+ */
+
+asm(
+/*
+ * gcc 4.1.2 seems to place this first, even with the block at the end of
+ * the file.  Put it first for good measure.  If the branch ends up at the
+ * beginning of the image then it can be started like a kernel.
+ */
+"	b	_zimage_start\n"	/* gcc 4.1.2 places this first */
+
+/*
+ * This code will be loaded by qemu as a rom at the end of memory, and
+ * execution will start at address -4.  Since the rom is read only, we
+ * and the zImage code wants to run where loaded, we must copy it to ram.
+ *
+ * move to linked place
+ * end with a branch to this code
+ * this code will be copied with dd to the end of the rom image
+ */
+
+"	.globl	copy_rom_start\n"
+"copy_rom_start:\n"
+"	bl	1f\n"
+"1:	mflr	4\n"
+"	clrrwi	4,4,19\n"		/* ROM_BITS -- get beginning of rom */
+"	lis	5,_end@ha\n"
+"	addi	5,5,_end@l\n"
+"	lis	3,_start@ha\n"
+"	addi	3,3,_start@l\n"
+"	subf	5,3,5\n"
+"	addi	5,5,0x1f\n"
+"	srwi	5,5,5\n"
+"	mtctr	5\n"
+"2:	lwz	24,0(4)\n"		/* copy to linked addresss */
+"	lwz	25,4(4)\n"
+"	lwz	26,8(4)\n"
+"	lwz	27,12(4)\n"
+"	lwz	28,16(4)\n"
+"	lwz	29,20(4)\n"
+"	lwz	30,24(4)\n"
+"	lwz	31,28(4)\n"
+"	stw	24,0(3)\n"
+"	stw	25,4(3)\n"
+"	stw	26,8(3)\n"
+"	stw	27,12(3)\n"
+"	stw	28,16(3)\n"
+"	stw	29,20(3)\n"
+"	stw	30,24(3)\n"
+"	stw	31,28(3)\n"
+"	dcbf	0,3\n"
+"	sync\n"
+"	icbi	0,3\n"
+"	addi	3,3,32\n"
+"	addi	4,4,32\n"
+"	bdnz	2b\n"
+"	sync\n"
+"	isync\n"
+
+	/*
+	 * Put a branch to self on a few vectors in case we get an unexpected
+	 * interrupt.  At least you can dump regs in the qemu monitor.
+	 */
+"	lis	0,0x48000000@h\n"
+"	stw	0,0x700(0)\n"
+"	stw	0,0x300(0)\n"
+"	stw	0,0x400(0)\n"
+"	stw	0,0x900(0)\n"
+"	stw	0,0x800(0)\n"
+"	stw	0,0x200(0)\n"
+
+	/* branch to linked address */
+"	lis	0,_zimage_start@h\n"
+"	ori	0,0,_zimage_start@l\n"
+"	mtctr	0\n"
+"	li	3,0\n"
+"	bctrl\n"
+
+	/* must be last word before copy_rom_end */
+"	b	copy_rom_start\n"
+"	.globl	copy_rom_end\n"
+"copy_rom_end:\n"
+);
+
+
+#include <stddef.h>
+#include "string.h"
+#include "stdio.h"
+#include "ops.h"
+#include "page.h"
+#include "io.h"
+#include "gunzip_util.h"
+#include "flatdevtree.h"
+
+BSS_STACK(16*1024);
+
+unsigned char *nvram = (void *)0x80000074;	/* address of nvram on PReP */
+
+static void qemu_nvram_write(unsigned short addr, char data)
+{
+	out_8(nvram + 0, addr & 0xff);
+	out_8(nvram + 1, addr >> 8);
+	out_8(nvram + 3, data);
+}
+
+static char qemu_nvram_read(unsigned short addr)
+{
+	char data;
+	out_8(nvram + 0, addr & 0xff);
+	out_8(nvram + 1, addr >> 8);
+	data = in_8(nvram + 3);
+
+	return data;
+}
+
+static void qemu_nvram_fetch(unsigned short addr, unsigned short len, void *p)
+{
+	char *buf = p;
+	int i;
+
+	for (i = 0; i < len; i ++)
+		buf[i] = qemu_nvram_read(addr + i);	/* big endian */
+}
+
+static char arch[17];
+static void * image_start;
+static unsigned int image_len;
+
+void qemu_find_vmlinuz(struct gunzip_state *state, void **srcp,
+	unsigned long *lenp)
+{
+	*srcp = image_start;
+	*lenp = image_len;
+	gunzip_start(state, image_start, image_len);
+}
+
+/* if no device tree, read the nvram to find out about our system */
+/* based on openhackware 0.4 nvram.c get_nvram_config */
+static void qemu_fixups(void)
+{
+	char buf[32];
+	int word;
+
+	printf("qemu_fixups\n\r");
+
+	qemu_nvram_fetch(0, 16, buf);
+	printf("sig: %s", buf);
+	if (strcmp(buf, "QEMU_BIOS"))
+		fatal("no qemu sig found");
+	qemu_nvram_fetch(0x10, 16, &word);
+	if (word != 2)
+		fatal("wrong qemu nvram version");
+	/* compute crc over 0-0xfc, compare to crc in 0xfc */
+	/* size at 0x14, mult 256 0x400-0x2000 */
+	qemu_nvram_fetch(0x20, 16, buf);
+	strncpy(arch, buf, sizeof(arch)-1);
+	if (strcmp(arch,"PREP"))
+		fatal("don't understand arch %s", arch);
+
+	/* XXX: put the model in the device tree */
+
+	qemu_nvram_fetch(0x30, 16, &word);
+	printf("memory: %x\n\r", word);
+	dt_fixup_memory(0, word);
+	printf("boot device %c\n\r", qemu_nvram_read(0x34));
+	qemu_nvram_fetch(0x38, 16, &word);
+	image_start = (void *)word;
+	qemu_nvram_fetch(0x3c, 16, &word);
+	image_len = word;
+	printf("kernel %p %x\n\r", image_start, image_len);
+	qemu_nvram_fetch(0x40, 16, &word);
+	loader_info.cmdline = (void *)word;
+	qemu_nvram_fetch(0x44, 16, &word);
+	loader_info.cmdline_len = word;
+	printf("cmdline %p %x\n\r", loader_info.cmdline,
+		loader_info.cmdline_len);
+	printf("cmdline is %s\n\r", loader_info.cmdline);
+	qemu_nvram_fetch(0x48, 16, &word);
+	loader_info.initrd_addr = word;
+	qemu_nvram_fetch(0x4c, 16, &word);
+	loader_info.initrd_size = word;
+	printf("initrd %lx %lx\n\r", loader_info.initrd_addr,
+		loader_info.initrd_size);
+	/* XXX: nvram image addr at 50 */
+	/* XXX: vga width, height, depth = shorts at 54, 56, 58 */
+}
+
+/* if loaded with a device tree, then just read the tree */
+static void tree_fixups(void)
+{
+	/* get initrd from tree */
+	dt_find_initrd();
+
+	/* we must have an attached image for device-tree boot */
+}
+
+static void *heap_end;	/* set in platform_init */
+
+static void *qemu_vmlinux_alloc(unsigned long size)
+{
+	if (size < (unsigned long)_start)
+		return 0;
+
+	return (void *)_ALIGN_UP((unsigned long) heap_end, 4096);
+}
+
+void platform_init(void *r3)
+{
+	struct boot_param_header *bph = r3;
+
+	heap_end = simple_alloc_init(_end, 4096*1024, 4096, 512);
+
+	if (bph)  {
+		ft_init(bph, bph->totalsize, 128);
+		platform_ops.fixups = tree_fixups;
+	} else {
+		ft_init(_dtb_start, _dtb_end - _dtb_start, 128);
+		platform_ops.fixups = qemu_fixups;
+		platform_ops.find_vmlinuz = qemu_find_vmlinuz;
+	}
+	platform_ops.vmlinux_alloc = qemu_vmlinux_alloc;
+
+	serial_console_init();
+
+	// platform_ops.vmlinux_alloc = of_vmlinux_alloc;
+}
Index: kernel/arch/powerpc/boot/Makefile
===================================================================
--- kernel.orig/arch/powerpc/boot/Makefile	2007-08-24 05:46:36.000000000 -0500
+++ kernel/arch/powerpc/boot/Makefile	2007-08-27 22:49:03.000000000 -0500
@@ -49,7 +49,7 @@ src-wlib := string.S crt0.S stdio.c main
 		cpm-serial.c
 src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c crt0_kexec.S \
 		cuboot-ebony.c treeboot-ebony.c prpmc2800.c crt0_bml.S bml.c \
-		ps3-head.S ps3-hvcall.S ps3.c prep.c \
+		ps3-head.S ps3-hvcall.S ps3.c prep.c qemu.c \
 		treeboot-bamboo.c cuboot-8xx.c cuboot-pq2.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
@@ -144,6 +144,7 @@ image-$(CONFIG_PPC_HOLLY)		+= zImage.hol
 image-$(CONFIG_PPC_PRPMC2800)		+= zImage.prpmc2800
 image-$(CONFIG_PPC_ISERIES)		+= zImage.iseries
 image-$(CONFIG_PPC_PREP)		+= zImage.prep
+image-$(CONFIG_PPC_QEMU)		+= zImage.qemu zBoot.qemu
 image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage
 image-$(CONFIG_KEXEC)			+= $(kexec-y)
 image-$(CONFIG_KEXEC)			+= $(patsubst zImage%,zBoot%,$(kexec-y))
@@ -201,6 +202,9 @@ $(obj)/zImage.iseries: vmlinux
 $(obj)/zBoot.%: $(wrapperbits) $(dts)
 	$(call if_changed,wrap,$*,$(dts),,,$(obj)/empty.o)
 
+# horrible hack to avoid overlapping calls to wrapper script clobbering dtb.
+$(obj)/zImage.qemu: $(obj)/zBoot.qemu
+
 $(obj)/zImage.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
 	$(STRIP) -s -R .comment $< -o vmlinux.strip
 	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
@@ -234,8 +238,8 @@ install: $(CONFIGURE) $(addprefix $(obj)
 	sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
 
 # anything not in $(targets)
-clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
-	otheros.bld $(kexec-)
+clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.*
+clean-files += otheros.bld ppc_rom.bin $(kexec-)
 
 # clean up files cached by wrapper
 clean-kernel := vmlinux.strip vmlinux.bin empty.o.bin
Index: kernel/arch/powerpc/boot/dts/qemu.dts
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/boot/dts/qemu.dts	2007-08-27 20:48:34.000000000 -0500
@@ -0,0 +1,100 @@
+/*
+ * QEMU PReP skeleton device tree
+ * from PReP skeleton device tree
+ *
+ * Milton Miller
+ */
+
+/ {
+	device_type = "qemu";
+	model = "QEMU,PReP";
+	compatible = "qemu-prep";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			reg = <0>;
+			clock-frequency =<d#200000000>;
+			bus-frequency = <d#100000000>;
+			timebase-frequency = <d#25000000>;	/* correct? */
+			i-cache-line-size = <d#32>;
+			d-cache-line-size = <d#32>;
+			d-cache-size = <0>;
+			i-cache-size = <0>;
+
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		// dummy range here, zImage wrapper will fill in the actual
+		// amount of memory from the nvram
+		reg = <00000000 01000000>;
+	};
+
+	pci@80000000 {
+		device_type = "pci";
+		compatible = "prep-pci";
+		clock-frequency = <01fca055>;
+		reg = <80000000 7ffff>;
+		/* 8259-interrupt-acknowledge = <bffffff0>; */
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges=<01000000 00000000 00000000 80000000 00000000 00800000
+			02000000 00000000 00000000 c0000000 00000000 01000000>;
+		interrupt-map-mask = <f800 0 0 7>;
+		interrupt-map = <6000 0 0 1	&PIC8259 6 0
+				 8000 0 0 1	&PIC8259 7 0
+				 9000 0 0 1	&PIC8259 2 0
+				 b000 0 0 1	&PIC8259 1 0>;
+
+		isa {
+			device_type = "isa";
+			#address-cells = <2>;
+			#size-cells = <1>;
+			#interrupt-cells = <2>;
+			ranges = <00000001 00000000
+				  01005800 00000000 00000000  00010000
+				  00000000 00000000
+				  02005800 00000000 00000000  01000000>;
+
+			parallel {
+				device_type = "parallel";
+				compatible = "pnpPNP,401", "pnpPNP,400";
+				reg =  <00000001 000003bc  00000008
+					00000001 000007bc  00000006>;
+				interrupts = <00000007 00000003>;
+				interrupt-parent = <&PIC8259>;
+			};
+
+			serial@3f8 {
+				device_type = "serial";
+				compatible = "pnpPNP,501", "pnpPNP,500",
+						"ns16550";
+				virtual-reg = <800003f8>;
+				clock-frequency = <001c2000>;
+				reg =  <00000001 000003f8  00000008>;
+				interrupts = <00000004 00000003>;
+				interrupt-parent = <&PIC8259>;
+			};
+			PIC8259: interrupt-controller {
+				device_type = "i8259";
+				compatible = "prep,iic";
+				interrupt-controller;
+				reg = <	00000001 00000020  00000002
+					00000001 000000a0  00000002
+					00000001 000004d0  00000002>;
+			};
+		};
+	};
+
+	chosen {
+		linux,stdout-path = "/pci/isa/serial@3f8";
+	};
+};
+
Index: kernel/arch/powerpc/platforms/Kconfig
===================================================================
--- kernel.orig/arch/powerpc/platforms/Kconfig	2007-08-24 05:46:36.000000000 -0500
+++ kernel/arch/powerpc/platforms/Kconfig	2007-08-24 05:46:58.000000000 -0500
@@ -47,6 +47,7 @@ source "arch/powerpc/platforms/chrp/Kcon
 source "arch/powerpc/platforms/52xx/Kconfig"
 source "arch/powerpc/platforms/powermac/Kconfig"
 source "arch/powerpc/platforms/prep/Kconfig"
+source "arch/powerpc/platforms/qemu/Kconfig"
 source "arch/powerpc/platforms/maple/Kconfig"
 source "arch/powerpc/platforms/pasemi/Kconfig"
 source "arch/powerpc/platforms/celleb/Kconfig"
Index: kernel/arch/powerpc/boot/wrapper
===================================================================
--- kernel.orig/arch/powerpc/boot/wrapper	2007-08-24 05:46:36.000000000 -0500
+++ kernel/arch/powerpc/boot/wrapper	2007-08-27 22:49:09.000000000 -0500
@@ -320,4 +320,53 @@ ps3)
 
     gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
     ;;
+qemu)
+    # this part makes the zBoot.qemu a bootrom for qemu.
+    #
+    # the qemu bootrom is 512k , located at the top of the 32 bit address
+    # space.   The fixed entrypoint is address -4.
+
+    copy_rom_start=0x`${CROSS}nm "$ofile" \
+        | grep ' copy_rom_start$'       \
+        | cut -d' ' -f1`
+    copy_rom_start=`printf "%d" $copy_rom_start`
+    copy_rom_end=0x`${CROSS}nm "$ofile" \
+        | grep ' copy_rom_end$'       \
+        | cut -d' ' -f1`
+    copy_rom_end=`printf "%d" $copy_rom_end`
+    rom_start=0x`${CROSS}nm "$ofile" \
+        | grep ' _start$'       \
+        | cut -d' ' -f1`
+
+    rom_start=`printf "%d" $rom_start`
+    rom_size=$((1<<19))
+    copy_rom_len=$(($copy_rom_end-$copy_rom_start))
+    copy_rom_dst=$(($rom_size-$copy_rom_len))
+    copy_rom_src=$(($copy_rom_start-$rom_start))
+
+    img_size=`${CROSS}size "$ofile" | tail -n1 | cut -f4`
+    if [ $img_size -gt $copy_rom_dst ]
+    then
+	echo Image "${ofile##*/}" too big to fit in rom, skipping rom build.
+    else
+	romfile="$object/ppc_rom.bin"
+	tmpfile="$object/ppc_rom.$$"
+
+	rm -f "$tmpfile"
+	${CROSS}objcopy -O binary --pad-to=$(($rom_size+$rom_start)) \
+	    --gap-fill=0xff  "$ofile" "$tmpfile"
+
+	msg=$(dd if="$tmpfile" of="$tmpfile" conv=notrunc \
+	    skip=$copy_rom_src seek=$copy_rom_dst      \
+	    count=$copy_rom_len bs=1 2>&1)
+
+	if [ $? -ne "0" ]; then
+	    echo $msg
+	    rm -f "$tmpfile"
+	    exit 2
+	fi
+
+	mv "$tmpfile" "$romfile"
+    fi
+    ;;
 esac
Index: kernel/arch/powerpc/platforms/qemu/Kconfig
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/platforms/qemu/Kconfig	2007-08-24 05:46:58.000000000 -0500
@@ -0,0 +1,10 @@
+config PPC_QEMU
+	bool "PowerPC Reference Platform (PReP) based QEMU emulated systems"
+	depends on PPC_MULTIPLATFORM && PPC32
+	select PPC_I8259
+	select PPC_INDIRECT_PCI
+	select PPC_UDBG_16550
+	select PPC_NATIVE
+	select WANT_DEVICE_TREE
+	default n
+
Index: kernel/arch/powerpc/platforms/qemu/Makefile
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/platforms/qemu/Makefile	2007-08-24 05:46:58.000000000 -0500
@@ -0,0 +1,2 @@
+obj-y			+= setup.o
+obj-$(CONFIG_PCI)	+= pci.o
Index: kernel/arch/powerpc/platforms/qemu/pci.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/platforms/qemu/pci.c	2007-08-27 20:14:37.000000000 -0500
@@ -0,0 +1,133 @@
+/*
+ * Port to arch/powerpc:
+ * Copyright 2007 David Gibson, IBM Corporation.
+ *
+ * Port to qemu:
+ * Copyright 2007 Milton Miller, IBM Corporation.
+ *
+ * Based on OpenHackware 0.4
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ *
+ * pci config based on arch/powerpc/platforms/chrp/pci.c GoldenGate code
+ *
+ */
+
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/udbg.h>
+
+static volatile void __iomem *qemu_config_addr(struct pci_bus *bus,
+	unsigned int devfn, int off)
+{
+	int dev, fn;
+	struct pci_controller *hose = bus->sysdata;
+
+	if (!hose->cfg_data)
+		return NULL;
+
+	if (bus->number != 0)
+		return NULL;
+
+	dev = devfn >> 3;
+	fn = devfn & 7;
+
+	if (dev < 11 || dev > 21)
+		return NULL;
+
+	return hose->cfg_data + ((1 << dev) | (fn << 8) | off);
+}
+
+int qemu_read_config(struct pci_bus *bus, unsigned int devfn, int off,
+			   int len, u32 *val)
+{
+	volatile void __iomem *cfg_data = qemu_config_addr(bus, devfn, off);
+
+	/* check, should this be 0? */
+	if (cfg_data == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that off is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		*val =  in_8(cfg_data);
+		break;
+	case 2:
+		*val = in_le16(cfg_data);
+		break;
+	default:
+		*val = in_le32(cfg_data);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int qemu_write_config(struct pci_bus *bus, unsigned int devfn, int off,
+			    int len, u32 val)
+{
+	volatile void __iomem *cfg_data = qemu_config_addr(bus, devfn, off);
+
+	if (cfg_data == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/*
+	 * Note: the caller has already checked that off is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		out_8(cfg_data, val);
+		break;
+	case 2:
+		out_le16(cfg_data, val);
+		break;
+	default:
+		out_le32(cfg_data, val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops qemu_pci_ops =
+{
+	qemu_read_config,
+	qemu_write_config
+};
+
+void __init qemu_find_bridges(void)
+{
+	struct device_node *phb;
+	struct pci_controller *hose;
+
+	phb = of_find_node_by_type(NULL, "pci");
+	if (!phb) {
+		printk(KERN_ERR "PReP: Cannot find PCI bridge OF node\n");
+		return;
+	}
+
+	hose = pcibios_alloc_controller(phb);
+	if (!hose)
+		return;
+
+	pci_process_bridge_OF_ranges(hose, phb, 1);
+
+#define PREP_PCI_DRAM_OFFSET 	0x80000000
+
+	pci_dram_offset = PREP_PCI_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	hose->cfg_data = ioremap(0x80000000, 1 << 22);
+
+	hose->ops = &qemu_pci_ops;
+
+	udbg_init_uart(hose->io_base_virt + 0x3f8, 0, 0);
+	register_early_udbg_console();
+	printk(KERN_INFO "qemu_find_bridges: config at %p\n", hose->cfg_data);
+}
+
Index: kernel/arch/powerpc/platforms/qemu/setup.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kernel/arch/powerpc/platforms/qemu/setup.c	2007-08-27 20:24:59.000000000 -0500
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 1995  Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * Support for PReP (Motorola MTX/MVME)
+ * by Troy Benjegerdes (hozer@drgw.net)
+ *
+ * Port to arch/powerpc:
+ * Copyright 2007 David Gibson, IBM Corporation.
+ *
+ * Port to qemu:
+ * Copyright 2007 Milton Miller, IBM Corporation.
+ *
+ * Based on OpenHackware 0.4
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <linux/initrd.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+/* #include <asm/mpic.h> */
+#include <asm/i8259.h>
+#include <asm/time.h>
+#include <asm/udbg.h>
+
+static const char *qemu_model = "(unknown)";
+
+extern void qemu_find_bridges(void);
+
+#if 0
+
+/* useful ISA ports */
+#define PREP_SYSCTL	0x81c
+/* present in the IBM reference design; possibly identical in Mot boxes: */
+#define PREP_IBM_PM1	0x82a	/* power management register 1 */
+#define PREP_IBM_PLANAR	0x852	/* planar ID - identifies the motherboard */
+#define PREP_IBM_DISP	0x8c0	/* 4-digit LED display */
+
+
+
+
+/* Used by all Motorola PReP */
+static void prep_restart(char *cmd)
+{
+	local_irq_disable(); /* no interrupts */
+
+	/* set exception prefix high - to the prom */
+	mtmsr(mfmsr() | MSR_IP);
+
+	/* make sure bit 0 (reset) is a 0 */
+	outb(inb(0x92) & ~1L, 0x92);
+	/* signal a reset to system control port A - soft reset */
+	outb(inb(0x92) | 1, 0x92);
+
+	for (;;)
+		;
+	/* not reached */
+}
+
+static void prep_halt(void)
+{
+	local_irq_disable(); /* no interrupts */
+
+	/* set exception prefix high - to the prom */
+	mtmsr(mfmsr() | MSR_IP);
+
+	for (;;)
+		;
+	/* not reached */
+}
+
+/*
+ * On most IBM PReP's, power management is handled by a Signetics 87c750
+ * behind the Utah component on the ISA bus. To access the 750 you must write
+ * a series of nibbles to port 0x82a (decoded by the Utah). This is described
+ * somewhat in the IBM Carolina Technical Specification.
+ * -Hollis
+ */
+static void
+utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value)
+{
+	/*
+	 * byte1: 0 0 0 1 0  d  a5 a4
+	 * byte2: 0 0 0 1 a3 a2 a1 a0
+	 *
+	 * d = the bit's value, enabled or disabled
+	 * (a5 a4 a3) = the byte number, minus 20
+	 * (a2 a1 a0) = the bit number
+	 *
+	 * example: set the 5th bit of byte 21 (21.5)
+	 *     a5 a4 a3 = 001 (byte 1)
+	 *     a2 a1 a0 = 101 (bit 5)
+	 *
+	 *     byte1 = 0001 0100 (0x14)
+	 *     byte2 = 0001 1101 (0x1d)
+	 */
+	unsigned char byte1=0x10, byte2=0x10;
+
+	/* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */
+	bytenum -= 20;
+
+	byte1 |= (!!value) << 2;		/* set d */
+	byte1 |= (bytenum >> 1) & 0x3;	/* set a5, a4 */
+
+	byte2 |= (bytenum & 0x1) << 3;	/* set a3 */
+	byte2 |= bitnum & 0x7;			/* set a2, a1, a0 */
+
+	outb(byte1, PREP_IBM_PM1);	/* first nibble */
+	mb();
+	udelay(100);				/* important: let controller recover */
+
+	outb(byte2, PREP_IBM_PM1);	/* second nibble */
+	mb();
+	udelay(100);				/* important: let controller recover */
+}
+
+static void prep_sig750_poweroff(void)
+{
+	/* tweak the power manager found in most IBM PRePs (except Thinkpads) */
+
+	local_irq_disable();
+	/* set exception prefix high - to the prom */
+	mtmsr(mfmsr() | MSR_IP);
+
+	utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */
+
+	for (;;)
+		;
+	/* not reached */
+}
+
+#endif
+
+/* cpuinfo code common to all IBM PReP */
+static void qemu_ibm_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "machine\t\t: PReP %s\n", qemu_model);
+}
+
+#define NVRAM_AS0 0x74
+#define NVRAM_AS1 0x75
+#define NVRAM_DAT 0x77
+
+static unsigned char qemu_nvram_read_val(int addr)
+{
+	outb(NVRAM_AS0, addr & 0xff);
+	outb(NVRAM_AS1, (addr >> 8) & 0xff);
+	return inb(NVRAM_DAT);
+}
+
+
+static void qemu_nvram_write_val(int addr, unsigned char val)
+{
+	outb(NVRAM_AS0, addr & 0xff);
+	outb(NVRAM_AS1, (addr >> 8) & 0xff);
+	outb(NVRAM_DAT, val);
+}
+
+
+static void __init qemu_setup_arch(void)
+{
+	struct device_node *root;
+	const char *model;
+
+	root = of_find_node_by_path("/");
+	model = of_get_property(root, "model", NULL);
+	of_node_put(root);
+	if (model)
+		qemu_model = model;
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	/* loops_per_jiffy = 50000000; */
+
+	/* Lookup PCI host bridges */
+	qemu_find_bridges();
+
+	/* Read in NVRAM data */
+/* 	init_qemu_nvram(); */
+}
+
+static void __init qemu_find_8259(void)
+{
+	struct device_node *pic = NULL;
+	unsigned long int_ack = 0;
+
+	pic = of_find_node_by_type(NULL, "i8259");
+	if (!pic) {
+		printk(KERN_ERR "No interrupt controller found!\n");
+		return;
+	}
+
+	/* polling */
+	i8259_init(pic, int_ack);
+	ppc_md.get_irq = i8259_irq;
+
+	/* hack: set default host until interrupt map and pci fixed */
+	irq_set_default_host(i8259_get_host());
+}
+
+static void __init qemu_init_IRQ(void)
+{
+	qemu_find_8259();
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+static int qemu_ide_default_irq(unsigned long base)
+{
+	switch (base) {
+	case 0x1f0: return 13;
+	case 0x170: return 13;
+	case 0x1e8: return 11;
+	case 0x168: return 10;
+	case 0xfff0: return 14;		/* MCP(N)750 ide0 */
+	case 0xffe0: return 15;		/* MCP(N)750 ide1 */
+	default: return 0;
+	}
+}
+
+static unsigned long qemu_ide_default_io_base(int index)
+{
+	switch (index) {
+	case 0: return 0x1f0;
+	case 1: return 0x170;
+	case 2: return 0x1e8;
+	case 3: return 0x168;
+	default:
+		return 0;
+	}
+}
+#endif
+
+#if 0
+static int __init prep_request_io(void)
+{
+#ifdef CONFIG_NVRAM
+	request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+#endif
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
+
+	return 0;
+}
+device_initcall(prep_request_io);
+#endif
+
+
+static int __init qemu_probe(void)
+{
+	if (! of_flat_dt_is_compatible(of_get_flat_dt_root(), "qemu-prep"))
+		return 0;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+	ppc_ide_md.default_irq = qemu_ide_default_irq;
+	ppc_ide_md.default_io_base = qemu_ide_default_io_base;
+#endif
+
+	return 1;
+}
+
+define_machine(qemu) {
+	.name			= "QEMU",
+	.probe			= qemu_probe,
+	.setup_arch		= qemu_setup_arch,
+	.progress		= udbg_progress,
+	.show_cpuinfo		= qemu_ibm_cpuinfo,
+	.init_IRQ		= qemu_init_IRQ,
+/* 	.pcibios_fixup		= qemu_pcibios_fixup, */
+/*	.restart		= qemu_restart, */
+/*	.power_off		= qemu_halt, */
+/*	.halt			= qemu_halt, */
+/* 	.time_init		= todc_time_init, */
+/* 	.set_rtc_time		= todc_set_rtc_time, */
+/* 	.get_rtc_time		= todc_get_rtc_time, */
+	.calibrate_decr		= generic_calibrate_decr,
+ 	.nvram_read_val		= qemu_nvram_read_val,
+ 	.nvram_write_val	= qemu_nvram_write_val,
+	.phys_mem_access_prot	= pci_phys_mem_access_prot,
+};
Index: kernel/arch/powerpc/platforms/Makefile
===================================================================
--- kernel.orig/arch/powerpc/platforms/Makefile	2007-08-24 05:46:36.000000000 -0500
+++ kernel/arch/powerpc/platforms/Makefile	2007-08-24 05:46:58.000000000 -0500
@@ -7,6 +7,7 @@ endif
 endif
 obj-$(CONFIG_PPC_CHRP)		+= chrp/
 obj-$(CONFIG_PPC_PREP)		+= prep/
+obj-$(CONFIG_PPC_QEMU)		+= qemu/
 #obj-$(CONFIG_4xx)		+= 4xx/
 obj-$(CONFIG_44x)		+= 44x/
 obj-$(CONFIG_PPC_MPC52xx)	+= 52xx/
Index: kernel/arch/powerpc/boot/.gitignore
===================================================================
--- kernel.orig/arch/powerpc/boot/.gitignore	2007-08-27 21:10:42.000000000 -0500
+++ kernel/arch/powerpc/boot/.gitignore	2007-08-27 21:11:02.000000000 -0500
@@ -17,6 +17,7 @@ infutil.h
 kernel-vmlinux.strip.c
 kernel-vmlinux.strip.gz
 mktree
+ppc_rom.bin
 uImage
 cuImage.*
 zImage

^ permalink raw reply

* Move bootwrapper's strchr() and strncmp() from .h to string.S
From: David Gibson @ 2007-08-28  4:52 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

Currently the bootwrapper has implementations of strchr() and
strncmp(), but they're inlines in flatdevtree_env.h, rather than in
string.S with all the rest of the string functions.  This patch moves
them to string.S.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---

Paul, please apply to the for-2.6.24 branch.

Index: working-2.6/arch/powerpc/boot/string.S
===================================================================
--- working-2.6.orig/arch/powerpc/boot/string.S	2006-12-08 10:42:48.000000000 +1100
+++ working-2.6/arch/powerpc/boot/string.S	2007-08-28 14:48:52.000000000 +1000
@@ -49,6 +49,17 @@ strcat:
 	bne	1b
 	blr
 
+	.globl	strchr
+strchr:
+	addi	r3,r3,-1
+1:	lbzu	r0,1(r3)
+	cmpw	0,r0,r4
+	beqlr
+	cmpwi	0,r0,0
+	bne	1b
+	li	r3,0
+	blr
+
 	.globl	strcmp
 strcmp:
 	addi	r5,r3,-1
@@ -61,6 +72,19 @@ strcmp:
 	beq	1b
 	blr
 
+	.globl	strncmp
+strncmp:
+	mtctr	r5
+	addi	r5,r3,-1
+	addi	r4,r4,-1
+1:	lbzu	r3,1(r5)
+	cmpwi	1,r3,0
+	lbzu	r0,1(r4)
+	subf.	r3,r0,r3
+	beqlr	1
+	bdnzt	eq,1b
+	blr
+
 	.globl	strlen
 strlen:
 	addi	r4,r3,-1
Index: working-2.6/arch/powerpc/boot/string.h
===================================================================
--- working-2.6.orig/arch/powerpc/boot/string.h	2006-12-08 10:42:48.000000000 +1100
+++ working-2.6/arch/powerpc/boot/string.h	2007-08-28 14:49:14.000000000 +1000
@@ -5,7 +5,9 @@
 extern char *strcpy(char *dest, const char *src);
 extern char *strncpy(char *dest, const char *src, size_t n);
 extern char *strcat(char *dest, const char *src);
+extern char *strchr(const char *s, int c);
 extern int strcmp(const char *s1, const char *s2);
+extern int strncmp(const char *s1, const char *s2, size_t n);
 extern size_t strlen(const char *s);
 extern size_t strnlen(const char *s, size_t count);
 
Index: working-2.6/arch/powerpc/boot/flatdevtree_env.h
===================================================================
--- working-2.6.orig/arch/powerpc/boot/flatdevtree_env.h	2007-08-15 16:56:30.000000000 +1000
+++ working-2.6/arch/powerpc/boot/flatdevtree_env.h	2007-08-28 14:38:29.000000000 +1000
@@ -24,24 +24,4 @@
 #define be64_to_cpu(x)		(x)
 #define cpu_to_be64(x)		(x)
 
-static inline int strncmp(const char *cs, const char *ct, size_t count)
-{
-	signed char __res = 0;
-
-	while (count) {
-		if ((__res = *cs - *ct++) != 0 || !*cs++)
-			break;
-		count--;
-	}
-	return __res;
-}
-
-static inline char *strchr(const char *s, int c)
-{
-	for (; *s != (char)c; ++s)
-		if (*s == '\0')
-			return NULL;
-	return (char *)s;
-}
-
 #endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */

-- 
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

* Re: what is ~1MB of memory allocated at fffea000-fffff000 on ppc64?
From: Paul Mackerras @ 2007-08-28  5:19 UTC (permalink / raw)
  To: Chris Friesen; +Cc: linuxppc-dev, Anton Blanchard
In-Reply-To: <46D34A9E.7010501@nortel.com>

Chris Friesen writes:

> For some background, we're running an emulator that uses a null pointer 
> value of 0xffff0000 and we want any accesses to that address to trap.
> 
> Do you anticipate any issues with the following change?
> 
> -#define TASK_SIZE_USER32 (0x0000000100000000UL - (1*PAGE_SIZE))
> +#define TASK_SIZE_USER32 (0x00000000FFFF0000UL - (1*PAGE_SIZE))

Can you fix this in userspace instead by moving the stack down below
0xffff0000 and then doing munmap(0xffff0000, 0x1000) ?

Paul.

^ permalink raw reply

* Re: Newbie and linux on virtex-II ppc
From: schardt @ 2007-08-28  6:51 UTC (permalink / raw)
  Cc: linuxppc-embedded
In-Reply-To: <fa686aa40708270609x453092eye6eaf83b65ac2dee@mail.gmail.com>

Good morning,

last night i got a 2.6. kernel ready and ive got a "Now booting the
kernel" message on the serial port *yeah* :)

... but nothing more :(

the __log_buffer says something like "Linux version ..."
is there a more useable way to read out the buffer ?  i use the xmd
debugger and the mrd command

Regards
Georg

Grant Likely wrote:
> On 8/27/07, schardt <g.schardt@fz-juelich.de> wrote:
>   
>> im a student from germany and i try to run linux on a virtex-II with
>> integrated powerpc.
>> i use the developer board DS-DB-2VP4/7-FG456 from Memec ( i think its
>> now avnet)
>>
>> what is running :
>>
>>   - Xilinx EDK project (standalone program running fine, and BSP files
>> are generated)
>>     the project has only one UARTLITE, 82MB SDRAM and a few kByte
>> blockram, and the systemace interface
>>
>>   - crosscompiler toolchain works
>>
>>   - after modified some defines in the xparameters.h i got a linux 2.4.
>> kernel (linuxppc) without compiler errors
>>     
>
> I strongly recommend trying to bring up a 2.6 kernel, it's much easier.
>
>   
>>     and yes, the uartlite driver is enabled :)
>>     
>
> Don't modify xparams by hand; it's not worth the trouble.  Go into
> software setting in your EDK project and select 'linux-2.6' as the OS.
>  Generate the libraries and copy the generated xparameters_ml40x.h
> into your kernel tree.
>
>   
>> but, when downloading the zImage.elf via XMD to the SDRAM and starting
>> it with the run command nothing happens , or  i think that nothings
>> happens because the serial port is quiet.
>>     
>
> You can always use System.map in the kernel tree to find out where
> __log_buf was linked to.  Look at that location with the debugger to
> see if there is a crash message that didn't get printed out.
>
>   
>> is it possible to run a kernel that way ? or need i some kind of
>> bootloader ?
>> or is this complete the wrong way ?
>>     
>
> Yes, I use this same method to bring up a kernel on Virtex boards
> which don't have a bootloader.
>
>   



-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
Forschungszentrum Jülich GmbH
52425 Jülich

Sitz der Gesellschaft: Jülich
Eingetragen im Handelsregister des Amtsgerichts Düren Nr. HR B 3498
Vorsitzende des Aufsichtsrats: MinDirig'in Bärbel Brumme-Bothe
Vorstand: Prof. Dr. Achim Bachem (Vorsitzender), Dr. Ulrich Krafft (stellv. 
Vorsitzender)
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------

^ permalink raw reply

* Re: Move bootwrapper's strchr() and strncmp() from .h to string.S
From: Geert Uytterhoeven @ 2007-08-28  7:33 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20070828045257.GE6811@localhost.localdomain>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2784 bytes --]

On Tue, 28 Aug 2007, David Gibson wrote:
> Currently the bootwrapper has implementations of strchr() and
> strncmp(), but they're inlines in flatdevtree_env.h, rather than in
> string.S with all the rest of the string functions.  This patch moves
                                                                  ^^^^^
Nice move ;-)

... replaces them by assembler versions?

> them to string.S.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> 
> Paul, please apply to the for-2.6.24 branch.
> 
> Index: working-2.6/arch/powerpc/boot/string.S
> ===================================================================
> --- working-2.6.orig/arch/powerpc/boot/string.S	2006-12-08 10:42:48.000000000 +1100
> +++ working-2.6/arch/powerpc/boot/string.S	2007-08-28 14:48:52.000000000 +1000
> @@ -49,6 +49,17 @@ strcat:
>  	bne	1b
>  	blr
>  
> +	.globl	strchr
> +strchr:
> +	addi	r3,r3,-1
> +1:	lbzu	r0,1(r3)
> +	cmpw	0,r0,r4
> +	beqlr
> +	cmpwi	0,r0,0
> +	bne	1b
> +	li	r3,0
> +	blr
> +
>  	.globl	strcmp
>  strcmp:
>  	addi	r5,r3,-1
> @@ -61,6 +72,19 @@ strcmp:
>  	beq	1b
>  	blr
>  
> +	.globl	strncmp
> +strncmp:
> +	mtctr	r5
> +	addi	r5,r3,-1
> +	addi	r4,r4,-1
> +1:	lbzu	r3,1(r5)
> +	cmpwi	1,r3,0
> +	lbzu	r0,1(r4)
> +	subf.	r3,r0,r3
> +	beqlr	1
> +	bdnzt	eq,1b
> +	blr
> +
>  	.globl	strlen
>  strlen:
>  	addi	r4,r3,-1
> Index: working-2.6/arch/powerpc/boot/flatdevtree_env.h
> ===================================================================
> --- working-2.6.orig/arch/powerpc/boot/flatdevtree_env.h	2007-08-15 16:56:30.000000000 +1000
> +++ working-2.6/arch/powerpc/boot/flatdevtree_env.h	2007-08-28 14:38:29.000000000 +1000
> @@ -24,24 +24,4 @@
>  #define be64_to_cpu(x)		(x)
>  #define cpu_to_be64(x)		(x)
>  
> -static inline int strncmp(const char *cs, const char *ct, size_t count)
> -{
> -	signed char __res = 0;
> -
> -	while (count) {
> -		if ((__res = *cs - *ct++) != 0 || !*cs++)
> -			break;
> -		count--;
> -	}
> -	return __res;
> -}
> -
> -static inline char *strchr(const char *s, int c)
> -{
> -	for (; *s != (char)c; ++s)
> -		if (*s == '\0')
> -			return NULL;
> -	return (char *)s;
> -}
> -
>  #endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */

With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium	
VAT BE 0413.825.160 · RPR Brussels	
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619

^ permalink raw reply

* [PATCH 1/5] Add an optional device_node pointer to the irq_host
From: Michael Ellerman @ 2007-08-28  8:47 UTC (permalink / raw)
  To: linuxppc-dev

The majority of irq_host implementations (3 out of 4) are associated
with a device_node, and need to stash it somewhere. Rather than having
it somewhere different for each host, add an optional device_node pointer
to the irq_host structure.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/kernel/irq.c                 |   10 ++++++----
 arch/powerpc/platforms/52xx/mpc52xx_pic.c |    5 ++---
 arch/powerpc/platforms/82xx/mpc82xx_ads.c |    7 ++-----
 arch/powerpc/platforms/cell/axon_msi.c    |   14 +++++---------
 arch/powerpc/platforms/cell/interrupt.c   |    2 +-
 arch/powerpc/platforms/cell/spider-pic.c  |   18 +++++++-----------
 arch/powerpc/platforms/celleb/interrupt.c |    2 +-
 arch/powerpc/platforms/iseries/irq.c      |    3 ++-
 arch/powerpc/platforms/powermac/pic.c     |    2 +-
 arch/powerpc/platforms/ps3/interrupt.c    |    2 +-
 arch/powerpc/platforms/pseries/xics.c     |    2 +-
 arch/powerpc/sysdev/commproc.c            |    8 +++-----
 arch/powerpc/sysdev/cpm2_pic.c            |    7 +++----
 arch/powerpc/sysdev/i8259.c               |    8 +++-----
 arch/powerpc/sysdev/ipic.c                |    7 ++-----
 arch/powerpc/sysdev/ipic.h                |    3 ---
 arch/powerpc/sysdev/mpc8xx_pic.c          |   19 ++++++++++---------
 arch/powerpc/sysdev/mpic.c                |   11 ++++-------
 arch/powerpc/sysdev/mpic_msi.c            |    7 ++++---
 arch/powerpc/sysdev/mv64x60_pic.c         |    8 +++-----
 arch/powerpc/sysdev/qe_lib/qe_ic.c        |    7 ++-----
 arch/powerpc/sysdev/qe_lib/qe_ic.h        |    3 ---
 arch/powerpc/sysdev/tsi108_pci.c          |    8 ++++----
 arch/powerpc/sysdev/uic.c                 |   11 +++--------
 include/asm-powerpc/irq.h                 |    8 ++++++--
 include/asm-powerpc/mpic.h                |    3 ---
 26 files changed, 76 insertions(+), 109 deletions(-)

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index dfad0e4..79b4512 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -418,10 +418,11 @@ irq_hw_number_t virq_to_hw(unsigned int virq)
 }
 EXPORT_SYMBOL_GPL(virq_to_hw);
 
-__init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type,
-						unsigned int revmap_arg,
-						struct irq_host_ops *ops,
-						irq_hw_number_t inval_irq)
+__init_refok struct irq_host *irq_alloc_host(struct device_node *of_node,
+				unsigned int revmap_type,
+				unsigned int revmap_arg,
+				struct irq_host_ops *ops,
+				irq_hw_number_t inval_irq)
 {
 	struct irq_host *host;
 	unsigned int size = sizeof(struct irq_host);
@@ -446,6 +447,7 @@ __init_refok struct irq_host *irq_alloc_host(unsigned int revmap_type,
 	host->revmap_type = revmap_type;
 	host->inval_irq = inval_irq;
 	host->ops = ops;
+	host->of_node = of_node;
 
 	spin_lock_irqsave(&irq_big_lock, flags);
 
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 8c464c5..1d793e4 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -244,7 +244,7 @@ static struct irq_chip mpc52xx_sdma_irqchip = {
 static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
 {
 	pr_debug("%s: node=%p\n", __func__, node);
-	return mpc52xx_irqhost->host_data == node;
+	return h->of_node == node;
 }
 
 static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
@@ -419,14 +419,13 @@ void __init mpc52xx_init_irq(void)
 	 * hw irq information provided by the ofw to linux virq
 	 */
 
-	mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
+	mpc52xx_irqhost = irq_alloc_host(picnode, IRQ_HOST_MAP_LINEAR,
 	                                 MPC52xx_IRQ_HIGHTESTHWIRQ,
 	                                 &mpc52xx_irqhost_ops, -1);
 
 	if (!mpc52xx_irqhost)
 		panic(__FILE__ ": Cannot allocate the IRQ host\n");
 
-	mpc52xx_irqhost->host_data = picnode;
 	printk(KERN_INFO "MPC52xx PIC is up and running!\n");
 }
 
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
index c0a0c56..91ddbd2 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
@@ -61,7 +61,6 @@ static struct {
 
 static unsigned long pci_int_base;
 static struct irq_host *pci_pic_host;
-static struct device_node *pci_pic_node;
 #endif
 
 static void __init mpc82xx_ads_pic_init(void)
@@ -401,7 +400,7 @@ m82xx_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
 
 static int pci_pic_host_match(struct irq_host *h, struct device_node *node)
 {
-	return node == pci_pic_node;
+	return h->of_node == node;
 }
 
 static int pci_pic_host_map(struct irq_host *h, unsigned int virq,
@@ -478,7 +477,6 @@ void m82xx_pci_init_irq(void)
 		iounmap(immap);
 		return;
 	}
-	pci_pic_node = of_node_get(np);
 	/* PCI interrupt controller registers: status and mask */
 	regs = of_get_property(np, "reg", &size);
 	if ((!regs) || (size <= 2)) {
@@ -490,7 +488,6 @@ void m82xx_pci_init_irq(void)
 	    ioremap(regs[0], sizeof(*pci_regs.pci_int_stat_reg));
 	pci_regs.pci_int_mask_reg =
 	    ioremap(regs[1], sizeof(*pci_regs.pci_int_mask_reg));
-	of_node_put(np);
 	/* configure chip select for PCI interrupt controller */
 	immap->im_memctl.memc_br3 = regs[0] | 0x00001801;
 	immap->im_memctl.memc_or3 = 0xffff8010;
@@ -501,7 +498,7 @@ void m82xx_pci_init_irq(void)
 	*pci_regs.pci_int_mask_reg |= 0xfff00000;
 	iounmap(immap);
 	pci_pic_host =
-	    irq_alloc_host(IRQ_HOST_MAP_LINEAR, irq_max - irq_min + 1,
+	    irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, irq_max - irq_min + 1,
 			   &pci_pic_host_ops, irq_max + 1);
 	return;
 }
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 4c9ab5b..bdd97bb 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -64,7 +64,6 @@
 
 
 struct axon_msic {
-	struct device_node *dn;
 	struct irq_host *irq_host;
 	__le32 *fifo;
 	dcr_host_t dcr_host;
@@ -297,9 +296,7 @@ static int msic_host_map(struct irq_host *h, unsigned int virq,
 
 static int msic_host_match(struct irq_host *host, struct device_node *dn)
 {
-	struct axon_msic *msic = host->host_data;
-
-	return msic->dn == dn;
+	return host->of_node == dn;
 }
 
 static struct irq_host_ops msic_host_ops = {
@@ -314,7 +311,8 @@ static int axon_msi_notify_reboot(struct notifier_block *nb,
 	u32 tmp;
 
 	list_for_each_entry(msic, &axon_msic_list, list) {
-		pr_debug("axon_msi: disabling %s\n", msic->dn->full_name);
+		pr_debug("axon_msi: disabling %s\n",
+			  msic->irq_host->of_node->full_name);
 		tmp  = msic_dcr_read(msic, MSIC_CTRL_REG);
 		tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
 		msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
@@ -370,8 +368,8 @@ static int axon_msi_setup_one(struct device_node *dn)
 
 	msic->fifo = page_address(page);
 
-	msic->irq_host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, NR_IRQS,
-					&msic_host_ops, 0);
+	msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP,
+					NR_IRQS, &msic_host_ops, 0);
 	if (!msic->irq_host) {
 		printk(KERN_ERR "axon_msi: couldn't allocate irq_host for %s\n",
 		       dn->full_name);
@@ -387,8 +385,6 @@ static int axon_msi_setup_one(struct device_node *dn)
 		goto out_free_host;
 	}
 
-	msic->dn = of_node_get(dn);
-
 	set_irq_data(virq, msic);
 	set_irq_chained_handler(virq, axon_msi_cascade);
 	pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq);
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 47264e7..c29e634 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -381,7 +381,7 @@ static int __init setup_iic(void)
 void __init iic_init_IRQ(void)
 {
 	/* Setup an irq host data structure */
-	iic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT,
+	iic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT,
 				  &iic_host_ops, IIC_IRQ_INVALID);
 	BUG_ON(iic_host == NULL);
 	irq_set_default_host(iic_host);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 05f4b3d..4309c2c 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -63,7 +63,6 @@ enum {
 
 struct spider_pic {
 	struct irq_host		*host;
-	struct device_node	*of_node;
 	void __iomem		*regs;
 	unsigned int		node_id;
 };
@@ -178,8 +177,7 @@ static struct irq_chip spider_pic = {
 
 static int spider_host_match(struct irq_host *h, struct device_node *node)
 {
-	struct spider_pic *pic = h->host_data;
-	return node == pic->of_node;
+	return h->of_node == node;
 }
 
 static int spider_host_map(struct irq_host *h, unsigned int virq,
@@ -247,18 +245,18 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
 	 * tree in case the device-tree is ever fixed
 	 */
 	struct of_irq oirq;
-	if (of_irq_map_one(pic->of_node, 0, &oirq) == 0) {
+	if (of_irq_map_one(pic->host->of_node, 0, &oirq) == 0) {
 		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
 					     oirq.size);
 		return virq;
 	}
 
 	/* Now do the horrible hacks */
-	tmp = of_get_property(pic->of_node, "#interrupt-cells", NULL);
+	tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL);
 	if (tmp == NULL)
 		return NO_IRQ;
 	intsize = *tmp;
-	imap = of_get_property(pic->of_node, "interrupt-map", &imaplen);
+	imap = of_get_property(pic->host->of_node, "interrupt-map", &imaplen);
 	if (imap == NULL || imaplen < (intsize + 1))
 		return NO_IRQ;
 	iic = of_find_node_by_phandle(imap[intsize]);
@@ -308,15 +306,13 @@ static void __init spider_init_one(struct device_node *of_node, int chip,
 		panic("spider_pic: can't map registers !");
 
 	/* Allocate a host */
-	pic->host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, SPIDER_SRC_COUNT,
-				   &spider_host_ops, SPIDER_IRQ_INVALID);
+	pic->host = irq_alloc_host(of_node_get(of_node), IRQ_HOST_MAP_LINEAR,
+				   SPIDER_SRC_COUNT, &spider_host_ops,
+				   SPIDER_IRQ_INVALID);
 	if (pic->host == NULL)
 		panic("spider_pic: can't allocate irq host !");
 	pic->host->host_data = pic;
 
-	/* Fill out other bits */
-	pic->of_node = of_node_get(of_node);
-
 	/* Go through all sources and disable them */
 	for (i = 0; i < SPIDER_SRC_COUNT; i++) {
 		void __iomem *cfg = pic->regs + TIR_CFGA + 8 * i;
diff --git a/arch/powerpc/platforms/celleb/interrupt.c b/arch/powerpc/platforms/celleb/interrupt.c
index 98e6665..4ecdf06 100644
--- a/arch/powerpc/platforms/celleb/interrupt.c
+++ b/arch/powerpc/platforms/celleb/interrupt.c
@@ -242,7 +242,7 @@ void __init beatic_init_IRQ(void)
 	ppc_md.get_irq = beatic_get_irq;
 
 	/* Allocate an irq host */
-	beatic_host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0,
+	beatic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0,
 					 &beatic_pic_host_ops,
 					 0);
 	BUG_ON(beatic_host == NULL);
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 63b3367..3666746 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -369,7 +369,8 @@ void __init iSeries_init_IRQ(void)
 	/* Create irq host. No need for a revmap since HV will give us
 	 * back our virtual irq number
 	 */
-	host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &iseries_irq_host_ops, 0);
+	host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0,
+			      &iseries_irq_host_ops, 0);
 	BUG_ON(host == NULL);
 	irq_set_default_host(host);
 
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 87cd680..999f5e1 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -384,7 +384,7 @@ static void __init pmac_pic_probe_oldstyle(void)
 	/*
 	 * Allocate an irq host
 	 */
-	pmac_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, max_irqs,
+	pmac_pic_host = irq_alloc_host(master, IRQ_HOST_MAP_LINEAR, max_irqs,
 				       &pmac_pic_host_ops,
 				       max_irqs);
 	BUG_ON(pmac_pic_host == NULL);
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 67e32ec..30b9f4c 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -726,7 +726,7 @@ void __init ps3_init_IRQ(void)
 	unsigned cpu;
 	struct irq_host *host;
 
-	host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops,
+	host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops,
 		PS3_INVALID_OUTLET);
 	irq_set_default_host(host);
 	irq_set_virq_count(PS3_PLUG_MAX + 1);
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 5bd90a7..5ddb025 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -540,7 +540,7 @@ static void __init xics_init_host(void)
 		ops = &xics_host_lpar_ops;
 	else
 		ops = &xics_host_direct_ops;
-	xics_host = irq_alloc_host(IRQ_HOST_MAP_TREE, 0, ops,
+	xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, ops,
 				   XICS_IRQ_SPURIOUS);
 	BUG_ON(xics_host == NULL);
 	irq_set_default_host(xics_host);
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
index e8e79f8..05dc30b 100644
--- a/arch/powerpc/sysdev/commproc.c
+++ b/arch/powerpc/sysdev/commproc.c
@@ -50,7 +50,6 @@ static uint host_end;    /* end + 1 */
 cpm8xx_t *cpmp;          /* Pointer to comm processor space */
 cpic8xx_t *cpic_reg;
 
-static struct device_node *cpm_pic_node;
 static struct irq_host *cpm_pic_host;
 
 static void cpm_mask_irq(unsigned int irq)
@@ -97,7 +96,7 @@ int cpm_get_irq(void)
 
 static int cpm_pic_host_match(struct irq_host *h, struct device_node *node)
 {
-	return cpm_pic_node == node;
+	return h->of_node == node;
 }
 
 static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
@@ -165,9 +164,8 @@ unsigned int cpm_pic_init(void)
 
 	out_be32(&cpic_reg->cpic_cimr, 0);
 
-	cpm_pic_node = of_node_get(np);
-
-	cpm_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm_pic_host_ops, 64);
+	cpm_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR,
+				      64, &cpm_pic_host_ops, 64);
 	if (cpm_pic_host == NULL) {
 		printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
 		sirq = NO_IRQ;
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index eabfe06..d9ab30c 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -50,7 +50,6 @@
 
 static intctl_cpm2_t *cpm2_intctl;
 
-static struct device_node *cpm2_pic_node;
 static struct irq_host *cpm2_pic_host;
 #define NR_MASK_WORDS   ((NR_IRQS + 31) / 32)
 static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
@@ -208,7 +207,7 @@ unsigned int cpm2_get_irq(void)
 
 static int cpm2_pic_host_match(struct irq_host *h, struct device_node *node)
 {
-	return cpm2_pic_node == node;
+	return h->of_node == node;
 }
 
 static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,
@@ -273,8 +272,8 @@ void cpm2_pic_init(struct device_node *node)
 	out_be32(&cpm2_intctl->ic_scprrl, 0x05309770);
 
 	/* create a legacy host */
-	cpm2_pic_node = of_node_get(node);
-	cpm2_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm2_pic_host_ops, 64);
+	cpm2_pic_host = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
+				       64, &cpm2_pic_host_ops, 64);
 	if (cpm2_pic_host == NULL) {
 		printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
 		return;
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index ad87adc..7c1b27a 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -25,7 +25,6 @@ static unsigned char cached_8259[2] = { 0xff, 0xff };
 
 static DEFINE_SPINLOCK(i8259_lock);
 
-static struct device_node *i8259_node;
 static struct irq_host *i8259_host;
 
 /*
@@ -165,7 +164,7 @@ static struct resource pic_edgectrl_iores = {
 
 static int i8259_host_match(struct irq_host *h, struct device_node *node)
 {
-	return i8259_node == NULL || i8259_node == node;
+	return h->of_node == NULL || h->of_node == node;
 }
 
 static int i8259_host_map(struct irq_host *h, unsigned int virq,
@@ -276,9 +275,8 @@ void i8259_init(struct device_node *node, unsigned long intack_addr)
 	spin_unlock_irqrestore(&i8259_lock, flags);
 
 	/* create a legacy host */
-	if (node)
-		i8259_node = of_node_get(node);
-	i8259_host = irq_alloc_host(IRQ_HOST_MAP_LEGACY, 0, &i8259_host_ops, 0);
+	i8259_host = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LEGACY,
+				    0, &i8259_host_ops, 0);
 	if (i8259_host == NULL) {
 		printk(KERN_ERR "i8259: failed to allocate irq host !\n");
 		return;
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 473c415..05a56e5 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -511,10 +511,8 @@ static struct irq_chip ipic_irq_chip = {
 
 static int ipic_host_match(struct irq_host *h, struct device_node *node)
 {
-	struct ipic *ipic = h->host_data;
-
 	/* Exact match, unless ipic node is NULL */
-	return ipic->of_node == NULL || ipic->of_node == node;
+	return h->of_node == NULL || h->of_node == node;
 }
 
 static int ipic_host_map(struct irq_host *h, unsigned int virq,
@@ -568,9 +566,8 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
 		return NULL;
 
 	memset(ipic, 0, sizeof(struct ipic));
-	ipic->of_node = of_node_get(node);
 
-	ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
+	ipic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
 				       NR_IPIC_INTS,
 				       &ipic_host_ops, 0);
 	if (ipic->irqhost == NULL) {
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index c28e589..bb309a5 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -48,9 +48,6 @@ struct ipic {
 
 	/* The "linux" controller struct */
 	struct irq_chip		hc_irq;
-
-	/* The device node of the interrupt controller */
-	struct device_node	*of_node;
 };
 
 struct ipic_info {
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index 2fc2bcd..f20a4d4 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -19,7 +19,6 @@
 
 extern int cpm_get_irq(struct pt_regs *regs);
 
-static struct device_node *mpc8xx_pic_node;
 static struct irq_host *mpc8xx_pic_host;
 #define NR_MASK_WORDS   ((NR_IRQS + 31) / 32)
 static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
@@ -122,7 +121,7 @@ unsigned int mpc8xx_get_irq(void)
 
 static int mpc8xx_pic_host_match(struct irq_host *h, struct device_node *node)
 {
-	return mpc8xx_pic_node == node;
+	return h->of_node == node;
 }
 
 static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq,
@@ -176,22 +175,24 @@ int mpc8xx_pic_init(void)
 		return -ENOMEM;
 	}
 
-	mpc8xx_pic_node = of_node_get(np);
-
 	ret = of_address_to_resource(np, 0, &res);
-	of_node_put(np);
 	if (ret)
-		return ret;
+		goto out;
 
 	siu_reg = (void *)ioremap(res.start, res.end - res.start + 1);
-	if (siu_reg == NULL)
-		return -EINVAL;
+	if (siu_reg == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
 
-	mpc8xx_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &mpc8xx_pic_host_ops, 64);
+	mpc8xx_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR,
+					 64, &mpc8xx_pic_host_ops, 64);
 	if (mpc8xx_pic_host == NULL) {
 		printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
 		ret = -ENOMEM;
 	}
 
+out:
+	of_node_put(np);
 	return ret;
 }
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 74c64c0..25a81f7 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -271,7 +271,7 @@ static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb,
 {
 	rb->dbase = mpic->dcr_base;
 	rb->doff = offset;
-	rb->dhost = dcr_map(mpic->of_node, rb->dbase + rb->doff, size);
+	rb->dhost = dcr_map(mpic->irqhost->of_node, rb->dbase + rb->doff, size);
 	BUG_ON(!DCR_MAP_OK(rb->dhost));
 }
 
@@ -861,10 +861,8 @@ static struct irq_chip mpic_irq_ht_chip = {
 
 static int mpic_host_match(struct irq_host *h, struct device_node *node)
 {
-	struct mpic *mpic = h->host_data;
-
 	/* Exact match, unless mpic node is NULL */
-	return mpic->of_node == NULL || mpic->of_node == node;
+	return h->of_node == NULL || h->of_node == node;
 }
 
 static int mpic_host_map(struct irq_host *h, unsigned int virq,
@@ -985,10 +983,9 @@ struct mpic * __init mpic_alloc(struct device_node *node,
 	
 	memset(mpic, 0, sizeof(struct mpic));
 	mpic->name = name;
-	mpic->of_node = of_node_get(node);
 
-	mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, isu_size,
-				       &mpic_host_ops,
+	mpic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
+				       isu_size, &mpic_host_ops,
 				       flags & MPIC_LARGE_VECTORS ? 2048 : 256);
 	if (mpic->irqhost == NULL) {
 		of_node_put(node);
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index b076793..9ca4d8f 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -117,16 +117,17 @@ static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
 	int i, len;
 	const u32 *p;
 
-	p = of_get_property(mpic->of_node, "msi-available-ranges", &len);
+	p = of_get_property(mpic->irqhost->of_node,
+			    "msi-available-ranges", &len);
 	if (!p) {
 		pr_debug("mpic: no msi-available-ranges property found on %s\n",
-			  mpic->of_node->full_name);
+			  mpic->irqhost->of_node->full_name);
 		return -ENODEV;
 	}
 
 	if (len % 8 != 0) {
 		printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
-		       "property on %s\n", mpic->of_node->full_name);
+		       "property on %s\n", mpic->irqhost->of_node->full_name);
 		return -EINVAL;
 	}
 
diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c
index 01d3162..a145bfd 100644
--- a/arch/powerpc/sysdev/mv64x60_pic.c
+++ b/arch/powerpc/sysdev/mv64x60_pic.c
@@ -204,7 +204,7 @@ static struct irq_chip mv64x60_chip_gpp = {
 
 static int mv64x60_host_match(struct irq_host *h, struct device_node *np)
 {
-	return mv64x60_irq_host->host_data == np;
+	return h->of_node == np;
 }
 
 static struct irq_chip *mv64x60_chips[] = {
@@ -253,14 +253,12 @@ void __init mv64x60_init_irq(void)
 	np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-pic");
 	reg = of_get_property(np, "reg", &size);
 	paddr = of_translate_address(np, reg);
-	of_node_put(np);
 	mv64x60_irq_reg_base = ioremap(paddr, reg[1]);
 
-	mv64x60_irq_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, MV64x60_NUM_IRQS,
+	mv64x60_irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
+					  MV64x60_NUM_IRQS,
 					  &mv64x60_host_ops, MV64x60_NUM_IRQS);
 
-	mv64x60_irq_host->host_data = np;
-
 	spin_lock_irqsave(&mv64x60_lock, flags);
 	out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK,
 		 mv64x60_cached_gpp_mask);
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 4d1dcb4..55e6f39 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -245,10 +245,8 @@ static struct irq_chip qe_ic_irq_chip = {
 
 static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
 {
-	struct qe_ic *qe_ic = h->host_data;
-
 	/* Exact match, unless qe_ic node is NULL */
-	return qe_ic->of_node == NULL || qe_ic->of_node == node;
+	return h->of_node == NULL || h->of_node == node;
 }
 
 static int qe_ic_host_map(struct irq_host *h, unsigned int virq,
@@ -352,9 +350,8 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags)
 		return;
 
 	memset(qe_ic, 0, sizeof(struct qe_ic));
-	qe_ic->of_node = of_node_get(node);
 
-	qe_ic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
+	qe_ic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
 					NR_QE_IC_INTS, &qe_ic_host_ops, 0);
 	if (qe_ic->irqhost == NULL) {
 		of_node_put(node);
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.h b/arch/powerpc/sysdev/qe_lib/qe_ic.h
index 9a631ad..c1361d0 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.h
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.h
@@ -84,9 +84,6 @@ struct qe_ic {
 	/* The "linux" controller struct */
 	struct irq_chip hc_irq;
 
-	/* The device node of the interrupt controller */
-	struct device_node *of_node;
-
 	/* VIRQ numbers of QE high/low irqs */
 	unsigned int virq_high;
 	unsigned int virq_low;
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index cf0bfbd..b41492a 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -52,7 +52,6 @@
 u32 tsi108_pci_cfg_base;
 static u32 tsi108_pci_cfg_phys;
 u32 tsi108_csr_vir_base;
-static struct device_node *pci_irq_node;
 static struct irq_host *pci_irq_host;
 
 extern u32 get_vir_csrbase(void);
@@ -407,7 +406,7 @@ static int pci_irq_host_map(struct irq_host *h, unsigned int virq,
 
 static int pci_irq_host_match(struct irq_host *h, struct device_node *node)
 {
-	return pci_irq_node == node;
+	return h->of_node == node;
 }
 
 static struct irq_host_ops pci_irq_host_ops = {
@@ -433,10 +432,11 @@ void __init tsi108_pci_int_init(struct device_node *node)
 {
 	DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
 
-	pci_irq_node = of_node_get(node);
-	pci_irq_host = irq_alloc_host(IRQ_HOST_MAP_LEGACY, 0, &pci_irq_host_ops, 0);
+	pci_irq_host = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LEGACY,
+				      0, &pci_irq_host_ops, 0);
 	if (pci_irq_host == NULL) {
 		printk(KERN_ERR "pci_irq_host: failed to allocate irq host !\n");
+		of_node_put(node);
 		return;
 	}
 
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 47180b3..bf37667 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -56,9 +56,6 @@ struct uic {
 
 	/* For secondary UICs, the cascade interrupt's irqaction */
 	struct irqaction cascade;
-
-	/* The device node of the interrupt controller */
-	struct device_node *of_node;
 };
 
 static void uic_unmask_irq(unsigned int virq)
@@ -220,8 +217,7 @@ out_unlock:
 
 static int uic_host_match(struct irq_host *h, struct device_node *node)
 {
-	struct uic *uic = h->host_data;
-	return uic->of_node == node;
+	return h->of_node == node;
 }
 
 static int uic_host_map(struct irq_host *h, unsigned int virq,
@@ -291,7 +287,6 @@ static struct uic * __init uic_init_one(struct device_node *node)
 
 	memset(uic, 0, sizeof(*uic));
 	spin_lock_init(&uic->lock);
-	uic->of_node = of_node_get(node);
 	indexp = of_get_property(node, "cell-index", &len);
 	if (!indexp || (len != sizeof(u32))) {
 		printk(KERN_ERR "uic: Device node %s has missing or invalid "
@@ -308,8 +303,8 @@ static struct uic * __init uic_init_one(struct device_node *node)
 	}
 	uic->dcrbase = *dcrreg;
 
-	uic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_UIC_INTS,
-				      &uic_host_ops, -1);
+	uic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
+				      NR_UIC_INTS, &uic_host_ops, -1);
 	if (! uic->irqhost) {
 		of_node_put(node);
 		return NULL; /* FIXME: panic? */
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 0485c53..1392db4 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -124,6 +124,9 @@ struct irq_host {
 	struct irq_host_ops	*ops;
 	void			*host_data;
 	irq_hw_number_t		inval_irq;
+
+	/* Optional device node pointer */
+	struct device_node	*of_node;
 };
 
 /* The main irq map itself is an array of NR_IRQ entries containing the
@@ -142,7 +145,7 @@ extern irq_hw_number_t virq_to_hw(unsigned int virq);
 
 /**
  * irq_alloc_host - Allocate a new irq_host data structure
- * @node: device-tree node of the interrupt controller
+ * @of_node: optional device-tree node of the interrupt controller
  * @revmap_type: type of reverse mapping to use
  * @revmap_arg: for IRQ_HOST_MAP_LINEAR linear only: size of the map
  * @ops: map/unmap host callbacks
@@ -156,7 +159,8 @@ extern irq_hw_number_t virq_to_hw(unsigned int virq);
  * later during boot automatically (the reverse mapping will use the slow path
  * until that happens).
  */
-extern struct irq_host *irq_alloc_host(unsigned int revmap_type,
+extern struct irq_host *irq_alloc_host(struct device_node *of_node,
+				       unsigned int revmap_type,
 				       unsigned int revmap_arg,
 				       struct irq_host_ops *ops,
 				       irq_hw_number_t inval_irq);
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index 262db6b..0eb3ab9 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -240,9 +240,6 @@ struct mpic_irq_save {
 /* The instance data of a given MPIC */
 struct mpic
 {
-	/* The device node of the interrupt controller */
-	struct device_node	*of_node;
-
 	/* The remapper for this MPIC */
 	struct irq_host		*irqhost;
 
-- 
1.5.1.3.g7a33b

^ permalink raw reply related

* [PATCH 2/5] Invert null match behaviour for irq_hosts
From: Michael Ellerman @ 2007-08-28  8:47 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <460e86e8b5a08c23dcbedb5d4bd484a519246dd3.1188290811.git.michael@ellerman.id.au>

Currently if you don't specify a match callback for your irq_host it's
assumed you match everything. This is a kind of opt-out approach, and
turns out to be the exception rather than the rule.

So change the semantics to be opt-in, ie. you don't match anything unless
you provide a match callback. This in itself isn't very useful, but will
allow us to provide a default match implementation in a subsequent patch.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/kernel/irq.c                 |    2 +-
 arch/powerpc/platforms/celleb/interrupt.c |    7 +++++++
 arch/powerpc/platforms/iseries/irq.c      |    7 +++++++
 arch/powerpc/platforms/ps3/interrupt.c    |    7 +++++++
 4 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 79b4512..30fb8e2 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -523,7 +523,7 @@ struct irq_host *irq_find_host(struct device_node *node)
 	 */
 	spin_lock_irqsave(&irq_big_lock, flags);
 	list_for_each_entry(h, &irq_hosts, link)
-		if (h->ops->match == NULL || h->ops->match(h, node)) {
+		if (h->ops->match != NULL && h->ops->match(h, node)) {
 			found = h;
 			break;
 		}
diff --git a/arch/powerpc/platforms/celleb/interrupt.c b/arch/powerpc/platforms/celleb/interrupt.c
index 4ecdf06..c7c68ca 100644
--- a/arch/powerpc/platforms/celleb/interrupt.c
+++ b/arch/powerpc/platforms/celleb/interrupt.c
@@ -175,11 +175,18 @@ static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct,
 	return 0;
 }
 
+static int beatic_pic_host_match(struct irq_host *h, struct device_node *np)
+{
+	/* Match all */
+	return 1;
+}
+
 static struct irq_host_ops beatic_pic_host_ops = {
 	.map = beatic_pic_host_map,
 	.remap = beatic_pic_host_remap,
 	.unmap = beatic_pic_host_unmap,
 	.xlate = beatic_pic_host_xlate,
+	.match = beatic_pic_host_match,
 };
 
 /*
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 3666746..701d929 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -346,8 +346,15 @@ static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
 	return 0;
 }
 
+static int iseries_irq_host_match(struct irq_host *h, struct device_node *np)
+{
+	/* Match all */
+	return 1;
+}
+
 static struct irq_host_ops iseries_irq_host_ops = {
 	.map = iseries_irq_host_map,
+	.match = iseries_irq_host_match,
 };
 
 /*
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 30b9f4c..3a6db04 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -673,9 +673,16 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq,
 	return 0;
 }
 
+static int ps3_host_match(struct irq_host *h, struct device_node *np)
+{
+	/* Match all */
+	return 1;
+}
+
 static struct irq_host_ops ps3_host_ops = {
 	.map = ps3_host_map,
 	.unmap = ps3_host_unmap,
+	.match = ps3_host_match,
 };
 
 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
-- 
1.5.1.3.g7a33b

^ permalink raw reply related

* [PATCH 3/5] Provide a default irq_host match, which matches on an exact of_node
From: Michael Ellerman @ 2007-08-28  8:47 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <460e86e8b5a08c23dcbedb5d4bd484a519246dd3.1188290811.git.michael@ellerman.id.au>

The most common match semantic is an exact match based on the device node.
So provide a default implementation that does this, and hook it up if no
match routine is specified.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/kernel/irq.c                 |   10 +++++++++-
 arch/powerpc/platforms/52xx/mpc52xx_pic.c |    7 -------
 arch/powerpc/platforms/82xx/mpc82xx_ads.c |    6 ------
 arch/powerpc/platforms/cell/axon_msi.c    |    6 ------
 arch/powerpc/platforms/cell/spider-pic.c  |    6 ------
 arch/powerpc/sysdev/commproc.c            |    6 ------
 arch/powerpc/sysdev/cpm2_pic.c            |    6 ------
 arch/powerpc/sysdev/mpc8xx_pic.c          |    6 ------
 arch/powerpc/sysdev/mv64x60_pic.c         |    6 ------
 arch/powerpc/sysdev/tsi108_pci.c          |    6 ------
 arch/powerpc/sysdev/uic.c                 |    6 ------
 11 files changed, 9 insertions(+), 62 deletions(-)

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 30fb8e2..d5c7e4c 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -418,6 +418,11 @@ irq_hw_number_t virq_to_hw(unsigned int virq)
 }
 EXPORT_SYMBOL_GPL(virq_to_hw);
 
+static int default_irq_host_match(struct irq_host *h, struct device_node *np)
+{
+	return h->of_node != NULL && h->of_node == np;
+}
+
 __init_refok struct irq_host *irq_alloc_host(struct device_node *of_node,
 				unsigned int revmap_type,
 				unsigned int revmap_arg,
@@ -449,6 +454,9 @@ __init_refok struct irq_host *irq_alloc_host(struct device_node *of_node,
 	host->ops = ops;
 	host->of_node = of_node;
 
+	if (host->ops->match == NULL)
+		host->ops->match = default_irq_host_match;
+
 	spin_lock_irqsave(&irq_big_lock, flags);
 
 	/* If it's a legacy controller, check for duplicates and
@@ -523,7 +531,7 @@ struct irq_host *irq_find_host(struct device_node *node)
 	 */
 	spin_lock_irqsave(&irq_big_lock, flags);
 	list_for_each_entry(h, &irq_hosts, link)
-		if (h->ops->match != NULL && h->ops->match(h, node)) {
+		if (h->ops->match(h, node)) {
 			found = h;
 			break;
 		}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 1d793e4..0f4ca8a 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -241,12 +241,6 @@ static struct irq_chip mpc52xx_sdma_irqchip = {
  * irq_host
 */
 
-static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
-{
-	pr_debug("%s: node=%p\n", __func__, node);
-	return h->of_node == node;
-}
-
 static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
 				 u32 * intspec, unsigned int intsize,
 				 irq_hw_number_t * out_hwirq,
@@ -367,7 +361,6 @@ static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
 }
 
 static struct irq_host_ops mpc52xx_irqhost_ops = {
-	.match = mpc52xx_irqhost_match,
 	.xlate = mpc52xx_irqhost_xlate,
 	.map = mpc52xx_irqhost_map,
 };
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
index 91ddbd2..4008795 100644
--- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
@@ -398,11 +398,6 @@ m82xx_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
 	}
 }
 
-static int pci_pic_host_match(struct irq_host *h, struct device_node *node)
-{
-	return h->of_node == node;
-}
-
 static int pci_pic_host_map(struct irq_host *h, unsigned int virq,
 			    irq_hw_number_t hw)
 {
@@ -418,7 +413,6 @@ static void pci_host_unmap(struct irq_host *h, unsigned int virq)
 }
 
 static struct irq_host_ops pci_pic_host_ops = {
-	.match = pci_pic_host_match,
 	.map = pci_pic_host_map,
 	.unmap = pci_host_unmap,
 };
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index bdd97bb..74407af 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -294,13 +294,7 @@ static int msic_host_map(struct irq_host *h, unsigned int virq,
 	return 0;
 }
 
-static int msic_host_match(struct irq_host *host, struct device_node *dn)
-{
-	return host->of_node == dn;
-}
-
 static struct irq_host_ops msic_host_ops = {
-	.match	= msic_host_match,
 	.map	= msic_host_map,
 };
 
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 4309c2c..3f4b4ae 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -175,11 +175,6 @@ static struct irq_chip spider_pic = {
 	.set_type = spider_set_irq_type,
 };
 
-static int spider_host_match(struct irq_host *h, struct device_node *node)
-{
-	return h->of_node == node;
-}
-
 static int spider_host_map(struct irq_host *h, unsigned int virq,
 			irq_hw_number_t hw)
 {
@@ -206,7 +201,6 @@ static int spider_host_xlate(struct irq_host *h, struct device_node *ct,
 }
 
 static struct irq_host_ops spider_host_ops = {
-	.match = spider_host_match,
 	.map = spider_host_map,
 	.xlate = spider_host_xlate,
 };
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
index 05dc30b..b562afc 100644
--- a/arch/powerpc/sysdev/commproc.c
+++ b/arch/powerpc/sysdev/commproc.c
@@ -94,11 +94,6 @@ int cpm_get_irq(void)
 	return irq_linear_revmap(cpm_pic_host, cpm_vec);
 }
 
-static int cpm_pic_host_match(struct irq_host *h, struct device_node *node)
-{
-	return h->of_node == node;
-}
-
 static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
 			  irq_hw_number_t hw)
 {
@@ -126,7 +121,6 @@ static struct irqaction cpm_error_irqaction = {
 };
 
 static struct irq_host_ops cpm_pic_host_ops = {
-	.match = cpm_pic_host_match,
 	.map = cpm_pic_host_map,
 };
 
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index d9ab30c..d5b36e0 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -205,11 +205,6 @@ unsigned int cpm2_get_irq(void)
 	return irq_linear_revmap(cpm2_pic_host, irq);
 }
 
-static int cpm2_pic_host_match(struct irq_host *h, struct device_node *node)
-{
-	return h->of_node == node;
-}
-
 static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,
 			  irq_hw_number_t hw)
 {
@@ -233,7 +228,6 @@ static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct,
 }
 
 static struct irq_host_ops cpm2_pic_host_ops = {
-	.match = cpm2_pic_host_match,
 	.map = cpm2_pic_host_map,
 	.xlate = cpm2_pic_host_xlate,
 };
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index f20a4d4..565156a 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -119,11 +119,6 @@ unsigned int mpc8xx_get_irq(void)
 
 }
 
-static int mpc8xx_pic_host_match(struct irq_host *h, struct device_node *node)
-{
-	return h->of_node == node;
-}
-
 static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq,
 			  irq_hw_number_t hw)
 {
@@ -157,7 +152,6 @@ static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct,
 
 
 static struct irq_host_ops mpc8xx_pic_host_ops = {
-	.match = mpc8xx_pic_host_match,
 	.map = mpc8xx_pic_host_map,
 	.xlate = mpc8xx_pic_host_xlate,
 };
diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c
index a145bfd..19e6ef2 100644
--- a/arch/powerpc/sysdev/mv64x60_pic.c
+++ b/arch/powerpc/sysdev/mv64x60_pic.c
@@ -202,11 +202,6 @@ static struct irq_chip mv64x60_chip_gpp = {
  * mv64x60_host_ops functions
  */
 
-static int mv64x60_host_match(struct irq_host *h, struct device_node *np)
-{
-	return h->of_node == np;
-}
-
 static struct irq_chip *mv64x60_chips[] = {
 	[MV64x60_LEVEL1_LOW]  = &mv64x60_chip_low,
 	[MV64x60_LEVEL1_HIGH] = &mv64x60_chip_high,
@@ -228,7 +223,6 @@ static int mv64x60_host_map(struct irq_host *h, unsigned int virq,
 }
 
 static struct irq_host_ops mv64x60_host_ops = {
-	.match = mv64x60_host_match,
 	.map   = mv64x60_host_map,
 };
 
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index b41492a..31d3d33 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -404,13 +404,7 @@ static int pci_irq_host_map(struct irq_host *h, unsigned int virq,
 	return 0;
 }
 
-static int pci_irq_host_match(struct irq_host *h, struct device_node *node)
-{
-	return h->of_node == node;
-}
-
 static struct irq_host_ops pci_irq_host_ops = {
-	.match = pci_irq_host_match,
 	.map = pci_irq_host_map,
 	.xlate = pci_irq_host_xlate,
 };
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index bf37667..5149716 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -215,11 +215,6 @@ out_unlock:
 	spin_unlock(&desc->lock);
 }
 
-static int uic_host_match(struct irq_host *h, struct device_node *node)
-{
-	return h->of_node == node;
-}
-
 static int uic_host_map(struct irq_host *h, unsigned int virq,
 			irq_hw_number_t hw)
 {
@@ -249,7 +244,6 @@ static int uic_host_xlate(struct irq_host *h, struct device_node *ct,
 }
 
 static struct irq_host_ops uic_host_ops = {
-	.match	= uic_host_match,
 	.map	= uic_host_map,
 	.xlate	= uic_host_xlate,
 };
-- 
1.5.1.3.g7a33b

^ permalink raw reply related

* [PATCH 4/5] Initialise hwirq for legacy irqs
From: Michael Ellerman @ 2007-08-28  8:47 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <460e86e8b5a08c23dcbedb5d4bd484a519246dd3.1188290811.git.michael@ellerman.id.au>

Although no one uses the hwirq value for legacy irqs at the moment, we
should really setup the correct value in the irq_map.

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

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index d5c7e4c..1339f32 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -487,7 +487,7 @@ __init_refok struct irq_host *irq_alloc_host(struct device_node *of_node,
 		host->inval_irq = 0;
 		/* setup us as the host for all legacy interrupts */
 		for (i = 1; i < NUM_ISA_INTERRUPTS; i++) {
-			irq_map[i].hwirq = 0;
+			irq_map[i].hwirq = i;
 			smp_wmb();
 			irq_map[i].host = host;
 			smp_wmb();
-- 
1.5.1.3.g7a33b

^ permalink raw reply related

* [PATCH 5/5] Export virq mapping via debugfs
From: Michael Ellerman @ 2007-08-28  8:47 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <460e86e8b5a08c23dcbedb5d4bd484a519246dd3.1188290811.git.michael@ellerman.id.au>

This patch adds a debugfs file "powerpc/virq_mapping", which shows the virtual
to real mapping of irq numbers. Enable it with CONFIG_VIRQ_DEBUG.

Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Chen Gong <G.Chen@freescale.com>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/Kconfig.debug |   10 +++++++
 arch/powerpc/kernel/irq.c  |   63 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 22acece..c38bc22 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -124,6 +124,16 @@ config IRQSTACKS
 	  for handling hard and soft interrupts.  This can help avoid
 	  overflowing the process kernel stacks.
 
+config VIRQ_DEBUG
+	bool "Expose hardware/virtual IRQ mapping via debugfs"
+	depends on DEBUG_FS && PPC_MERGE
+	help
+	  This option will show the mapping relationship between hardware irq
+	  numbers and virtual irq numbers. The mapping is exposed via debugfs
+	  in the file powerpc/virq_mapping.
+
+	  If you don't know what this means you don't need it.
+
 config BDI_SWITCH
 	bool "Include BDI-2000 user context switcher"
 	depends on DEBUG_KERNEL && PPC32
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 1339f32..0e47c8c 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -52,6 +52,7 @@
 #include <linux/mutex.h>
 #include <linux/bootmem.h>
 #include <linux/pci.h>
+#include <linux/debugfs.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -1006,6 +1007,68 @@ static int irq_late_init(void)
 }
 arch_initcall(irq_late_init);
 
+#ifdef CONFIG_VIRQ_DEBUG
+static int virq_debug_show(struct seq_file *m, void *private)
+{
+	unsigned long flags;
+	irq_desc_t *desc;
+	const char *p;
+	char none[] = "none";
+	int i;
+
+	seq_printf(m, "%-5s  %-7s  %-15s  %s\n", "virq", "hwirq",
+		      "chip name", "host name");
+
+	for (i = 1; i < NR_IRQS; i++) {
+		desc = get_irq_desc(i);
+		spin_lock_irqsave(&desc->lock, flags);
+
+		if (desc->action && desc->action->handler) {
+			seq_printf(m, "%5d  ", i);
+			seq_printf(m, "0x%05lx  ", virq_to_hw(i));
+
+			if (desc->chip && desc->chip->typename)
+				p = desc->chip->typename;
+			else
+				p = none;
+			seq_printf(m, "%-15s  ", p);
+
+			if (irq_map[i].host && irq_map[i].host->of_node)
+				p = irq_map[i].host->of_node->full_name;
+			else
+				p = none;
+			seq_printf(m, "%s\n", p);
+		}
+
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
+
+	return 0;
+}
+
+static int virq_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, virq_debug_show, inode->i_private);
+}
+
+static const struct file_operations virq_debug_fops = {
+	.open = virq_debug_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int __init irq_debugfs_init(void)
+{
+	if (debugfs_create_file("virq_mapping", S_IRUGO, powerpc_debugfs_root,
+				 NULL, &virq_debug_fops))
+		return -ENOMEM;
+
+	return 0;
+}
+__initcall(irq_debugfs_init);
+#endif /* CONFIG_VIRQ_DEBUG */
+
 #endif /* CONFIG_PPC_MERGE */
 
 #ifdef CONFIG_PPC64
-- 
1.5.1.3.g7a33b

^ permalink raw reply related

* Re: [PATCH 1/5] Add an optional device_node pointer to the irq_host
From: Michael Ellerman @ 2007-08-28  8:50 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <460e86e8b5a08c23dcbedb5d4bd484a519246dd3.1188290811.git.michael@ellerman.id.au>

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

On Tue, 2007-08-28 at 18:47 +1000, Michael Ellerman wrote:
> The majority of irq_host implementations (3 out of 4) are associated
> with a device_node, and need to stash it somewhere. Rather than having
> it somewhere different for each host, add an optional device_node pointer
> to the irq_host structure.
> 
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>

This series is basically unchanged since I last sent it, but applies
cleanly now onto the powerpc-for-2.6.24 branch.

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* RE: STK5200 pci_enable_device problem
From: Mustafa Cayir @ 2007-08-28  8:51 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: linuxppc-embedded
In-Reply-To: <20070827191419.9A9CE24044@gemini.denx.de>

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

Hi,

i build Linux-2.6.22-gbcfc8d37 kernel lastest kernel from denx git for the board (STK5200 with TQM5200-AB).
ELDK 4.1 version is used.

make mrproper
export ARCH=powerpc
make tqm5200_defconfig
make uImage

It hangs on after  following line
  Uncompressing Kernel Image ... OK

Our u-boot version : U-Boot 1.1.3 (Apr  7 2005 - 14:42:37)

Any idea will be appreciated.

Regards.

done
Bytes transferred = 1454056 (162fe8 hex)
## Booting image at 00200000 ...
   Image Name:   Linux-2.6.22-gbcfc8d37
   Created:      2007-08-28  19:41:27 UTC
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    1453992 Bytes =  1.4 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK




-----Original Message-----
From: Wolfgang Denk [mailto:wd@denx.de]
Sent: Mon 8/27/2007 10:14 PM
To: Mustafa Cayir
Cc: Oliver Rutsch; linuxppc-embedded@ozlabs.org
Subject: Re: STK5200 pci_enable_device problem
 
In message <7B9A8FF57DBB524190E98CABF6E56F070B927E@itri.bte.mam.gov.tr> you wrote:
> 
> i use 2.4.25 kernel and eldk 3.1.1 on TQM5200 board. i tried denx 2.6.19
> kernel to port on TQM5200 but i couldn't.
> Did you port 2.6 kernel on TQM5200? Did pci device start working
> succesfully after porting 2.6 kernel to TQM5200 board.

Current top-of-tree in our git repo has been tested with a Intel
EEPRO100 network card in the ST5200's PCI slot. It's working.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Unsichtbar macht sich die Dummheit, indem sie immer  größere  Ausmaße
annimmt.                             -- Bertold Brecht: Der Tui-Roman


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

^ permalink raw reply

* Re: RFC: issues concerning the next NAPI interface
From: James Chapman @ 2007-08-28  9:22 UTC (permalink / raw)
  To: David Miller
  Cc: tklein, themann, stefan.roscher, netdev, linux-kernel, raisch,
	linuxppc-dev, akepner, meder, ossthema, shemminger
In-Reply-To: <20070827.145600.102570576.davem@davemloft.net>

David Miller wrote:
> From: James Chapman <jchapman@katalix.com>
> Date: Mon, 27 Aug 2007 22:41:43 +0100
> 
>> I don't recall saying anything in previous posts about this. Are you 
>> confusing my posts with Jan-Bernd's?
> 
> Yes, my bad.
> 
>> Jan-Bernd has been talking about using hrtimers to _reschedule_
>> NAPI. My posts are suggesting an alternative mechanism that keeps
>> NAPI active (with interrupts disabled) for a jiffy or two after it
>> would otherwise have gone idle in order to avoid too many interrupts
>> when the packet rate is such that NAPI thrashes between poll-on and
>> poll-off.
> 
> So in this scheme what runs ->poll() to process incoming packets?
> The hrtimer?

No, the regular NAPI networking core calls ->poll() as usual; no timers 
are involved. This scheme simply delays the napi_complete() from the 
driver so the device stays in the poll list longer. It means that its 
->poll() will be called when there is no work to do for 1-2 jiffies, 
hence the optimization at the top of ->poll() to efficiently handle that 
case. The device's ->poll() is called by the NAPI core until it has 
continuously done no work for 1-2 jiffies, at which point it finally 
does the netif_rx_complete() and re-enables its interrupts.

If people feel that holding the device in the poll list for 1-2 jiffies 
is too long (because there are too many wasted polls), a counter could 
be used to to delay the netif_rx_complete() by N polls instead. N would 
be a value depending on CPU speed. I use the jiffy sampling method 
because it results in some natural randomization of the actual delay 
depending on when the jiffy value was sampled in relation to the jiffy tick.

Here is the tg3 patch again that illustrates the idea. The patch changes 
only the ->poll() routine; note how the netif_rx_complete() call is delayed.

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 710dccc..59e151b 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3473,6 +3473,24 @@ static int tg3_poll(struct napi_struct *napi,
      struct tg3_hw_status *sblk = tp->hw_status;
      int work_done = 0;

+    /* fastpath having no work while we're holding ourself in
+     * polled mode
+     */
+    if ((tp->exit_poll_time) && (!tg3_has_work(tp))) {
+        if (time_after(jiffies, tp->exit_poll_time)) {
+            tp->exit_poll_time = 0;
+            /* tell net stack and NIC we're done */
+            netif_rx_complete(netdev, napi);
+            tg3_restart_ints(tp);
+        }
+        return 0;
+    }
+
+    /* if we get here, there might be work to do so disable the
+     * poll hold fastpath above
+     */
+    tp->exit_poll_time = 0;
+
      /* handle link change and other phy events */
      if (!(tp->tg3_flags &
            (TG3_FLAG_USE_LINKCHG_REG |
@@ -3511,11 +3529,11 @@ static int tg3_poll(struct napi_struct *napi,
      } else
          sblk->status &= ~SD_STATUS_UPDATED;

-    /* if no more work, tell net stack and NIC we're done */
-    if (!tg3_has_work(tp)) {
-        netif_rx_complete(netdev, napi);
-        tg3_restart_ints(tp);
-    }
+    /* if no more work, set the time in jiffies when we should
+     * exit polled mode
+     */
+    if (!tg3_has_work(tp))
+        tp->exit_poll_time = jiffies + 2;

      return work_done;
  }
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index a6a23bb..a0d24d3 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2163,6 +2163,7 @@ struct tg3 {
      u32                last_tag;

      u32                msg_enable;
+    unsigned long            exit_poll_time;

      /* begin "tx thread" cacheline section */
      void                (*write32_tx_mbox) (struct tg3 *, u32,


-- 
James Chapman
Katalix Systems Ltd
http://www.katalix.com
Catalysts for your Embedded Linux software development

^ permalink raw reply related

* ppc/powerpc, remote debugging (ptrace), floating point variables
From: Visser, Udo RD-IS-E23 @ 2007-08-28  9:40 UTC (permalink / raw)
  To: linuxppc-embedded


Hello world, ;-)

when stepping through my own software, which is using floating point =
variables, gdb showed weird results (mostly NAN=B4s) for these =
variables. Running the software without gdb did not show any problems. =
The software is compiled with floating point instructions and the =
results (without gdb) are OK.

My setup:

MPC8349 target, "home grown", much like the MPC8349EMDS, running 2.6.16 =
(ppc)
GDB, gdbserver 6.3 connected via ethernet with my Linux Host.


What I did to get rid of the described problem:

In module:     arch/powerpc/kernel/process.c
In function:   void flush_fp_to_thread(struct tast_struct *tsk)

I changed the line:  giveup_fpu(current);
to:                  giveup_fpu(tsk);


Now my questions: Has anybody else had such problems?
                  Have I found a bug, or will I encounter any yet =
unknown problems in the near future?

I would appreciate any comment on my changes, especially from the =
maintainers.

Thank you very much

Udo Visser

Heidelberger Druckmaschinen AG
RD IMAGING SYSTEMS    RD-IS-E23


Confidentiality note:
The information in this email and any attachment may contain =
confidential and proprietary information of Heidelberger Druckmaschinen =
AG and/or its affiliates and may be privileged or otherwise protected =
from disclosure. If you are not the intended recipient, you are hereby =
notified that any review, reliance or distribution by others or =
forwarding without express permission is strictly prohibited and may =
cause liability. In case you have received this message due to an error =
in transmission, we kindly ask you to notify the sender immediately and =
to delete this email and any attachment from your system.

^ permalink raw reply

* Re: Linux doesn not boot from u-boot on ML403
From: Miroslaw Dach @ 2007-08-28 11:18 UTC (permalink / raw)
  To: Grant Likely, Leonid; +Cc: linuxppc-embedded
In-Reply-To: <fa686aa40708270753u1411796fv698d3b39ee908599@mail.gmail.com>

I have done additional test with my u-boot and linux kernel.

I have downloaded u-boot(.elf) and zImage.elf via jtag to SDRAM:

The SDRAM has 32 MB: 
Address Map for Processor ppc405_0
  (0x00000000-0x01ffffff) DDR_SDRAM_1   plb

The steps I have doe are as following:

1. XMD% dow -data zImage.elf 0xe00000
2. XMD% dow u-boot.elf
        section, .text: 0x00800000-0x0081513c
        section, .resetvec: 0x0081513c-0x00815140
        section, .rodata: 0x00815140-0x00817ce0
        section, .reloc: 0x00817d00-0x00818674
        section, .data: 0x00818674-0x00818b08
        section, .data.rel: 0x00818b08-0x00818b34
        section, .data.rel.local: 0x00818b34-0x00818f6c
        section, .u_boot_cmd: 0x00818f6c-0x008191dc
        section, .bss: 0x00819200-0x0081dd04
Downloaded Program u-boot.elf
Setting PC with program start addr = 0x00800100
PC reset to 0x00800100, Clearing MSR Register

3. XMD% run

------------------------------------------------------------------
                output on the serial port
------------------------------------------------------------------
 
U-Boot 1.2.0 (Aug 28 2007 - 11:56:19)


U-Boot: checkboard
DRAM:  U-Boot: initdram
32 MB
Using default environment

In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0 
=> 

U-Boot 1.2.0 (Aug 27 2007 - 14:23:15)


U-Boot: checkboard
DRAM:  U-Boot: initdram
32 MB
Using default environment

In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0 
=> bootelf 0xe00000
Loading .text @ 0x00400000 (14028 bytes)
Loading .data @ 0x00404000 (995328 bytes)
Clearing .bss @ 0x004f7000 (8504 bytes)
## Starting application at 0x00400000 ...

loaded at:     00400000 004F9138
board data at: 004F7120 004F7138
relocated to:  004040B4 004040CC
zimage at:     00404E59 004F6EE8
avail ram:     004FA000 01FFFFFF

Linux/PPC load: console=ttyUL0,9600 root=/dev/nfs rw 
nfsroot=129.117.144.113:/opt/eldk41/ppc_4xx,tcp  
ip=::::virtex4-mirek:eth0:dhcp panic=1
Uncompressing Linux...


After that system just hangs.

I do not understand why it is possible to run zImage.elf straight from jtag
but it hangs when started from u-boot.

Is it any fundamental problem with running Linux from u-boot on ML403 
(Virtex-4) boards?

Best Regards

Mirek

^ permalink raw reply


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