LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
From: Milton Miller @ 2007-09-26 16:19 UTC (permalink / raw)
  To: David Gibson; +Cc: ppcdev, Paul Mackerras
In-Reply-To: <20070925034616.GB2525@localhost.localdomain>

On Sep 24, 2007, at 10:46 PM, David Gibson wrote:
> On Mon, Sep 24, 2007 at 01:54:32AM -0500, Milton Miller wrote:
>> On Sep 23, 2007, at 10:36 PM, David Gibson wrote:
>>> On Fri, Sep 21, 2007 at 06:05:06PM -0500, Milton Miller wrote:
> [snip]
>>>> +#define MIN_VERSION 2
>>>> +#define OUT_VERSION 16
>>>
>>> Should output version 17.  In any case, don't try to be so general -
>>> just convert v123 (all basically the same) to latest (i.e. v17)
>>> without all the #if nonsense.
>>
>> Outputing v17 instead of 16 requires more words to be added to the
>> header, and the library does fine with v16.
>
> For now.  libfdt will want v17.  Although it will (eventually) have
> it's own v16->v17 conversion code.

If libfdt gets merged without supporting v16 input, then that will be a  
regression.  This code isn't pretending to address that.   The current  
flat tree code works with v16.

>>  Actually the v1 trees has
>> some other differences such as initrd addresses were kernel linear not
>> real, cpus were assigned logical numbers  ... so while the structure
>> didn't change except for the header field, the contents did.
>
> !? what's your source for this.  v2 and v3 were absolutely supposed to
> be backwards compatible with v1 which would not be the case with
> silent semantic changes such as this.

What's your souce for saying the were supposed to be backwards  
compatable?  That dtc fills out the struct header so?

My source is my involvment when v2 was defined (they were discovered  
while writing my device tree generation code):

The actual binary structure is compatable, just not the contents of the  
properties nor how any slave cpus wait (for some trees it doesn't  
matter).

http://git.kernel.org/?p=linux/kernel/git/horms/kexec-tools- 
testing.git;a=blob;f=kexec/arch/ppc64/fs2dt.c; 
hb=b84b87747a16f0afbef6f6802bb794a94f4961d9

And some more changes just before that:

http://git.kernel.org/?p=linux/kernel/git/torvalds/old-2.6-bkcvs.git; 
a=history;f=arch/ppc64/kernel/prom_init.c; 
h=e570799a84cc5328e9f0fd44592cb0b828d8c13a; 
hb=4ae24c4e8a8f68950a7774ca1cdfe69bfe4e2ffc

So its mostly when the kernel generated and required v1 trees, it was  
ppc64 only and had these other content and handoff semantics.  If it  
were to get a v1 tree, it only copes for the boot cpu determination    
I'm not aware of any code other than the kernel that would actually  
generate a v1 tree (other than dtc, which always supporteed v2, and  
doesn't care about these differences).


>>  Actually,
>> when converting v3 to v16 some of the code issn't needed, the ifs  
>> allow
>> the code size to be reduced.
>
> Yes, but it never will be, because the only reason we'd include this
> file is for converting old kexec-tools device trees which are v2 not
> v3.
>
>>>> +#define OUT_COMPAT 16
>>>> +
>>>> +#ifdef NO_CHECK
>>>> +static int check_v123_tree(u32 *start, u32 *limit)
>>>> +{
>>>> +	return 0;
>>>> +}
>>>> +#else
>>>> +/**
>>>> + * check_v123_tree - check integrety of a version 1, 2, or 3 tree
>>>> + * @start: the start of the device tree struct
>>>> + * @limit: the end of the region for the struct
>>>> + * structural checks on device_tree
>>>> + */
>>>> +static int check_v123_tree(u32 *start, u32 *limit)
>>>
>>> What is the point of this check?  If the device tree is corrupt,  
>>> we're
>>> stuffed anyway, so why bother?
>>
>> Hence the ifdef NO_CHECK.   When developing, sometimes its nice to  
>> know
>> if its your input or your program.  These functions are destructive to
>> an improperlly formed tree, and in non-obvious ways.  When debugging,
>> it's not hard to hardcode console write or read the printf string
>> buffer with a hardware debugger to see error messages.  That said, it
>> could be removed.
>
> Right.  Debugging code shouldn't pollute final patches.

There debug code, and validation code.   I call this the later.  It  
validates that the information that should be redundant is in fact  
redundant before its removed.  The response of the kernel to the tree  
may be different if this check fails..

> [snip]
>>>> +#if MIN_VERSION < 3 || OUT_VERSION > 16
>>>> +/**
>>>> + * move_nops_fwd - move nops in a v16 dt_struct to the beginning
>>>> + * @start - device tree starting address
>>>> + * @count - number of %OF_DT_NOP cells to move
>>>> + */
>>>> +static void move_nops_fwd(u32 *start, int count)
>>>
>>> What on earth is the point of this.  The NOPs are perfectly valid
>>> scattered within the tree, why go to all this trouble to shuffle them
>>> about.
>>
>> And if you notice, there is a "how many to move" argument.  The point
>> of moving them to the front of the tree is the v17 device tree header
>> takes more space than the v3 one, and the v2 header is smaller than
>> both v17 and v16 header.  Since I am converting the tree in place, the
>> space has to come from somewhere.  Since we are pretty much guaranteed
>> to get several nops, this function moves them forward so they can be
>> overwritten.  In practice we move 1-3 NOPS from the early properties >
>> 8 bytes and early grandchild nodes (eg /cpus/PowerPC,xxx).
>
> This is a hell of a lot of bother to go to for a few bytes.
> Allocating a big-enough buffer for any reasonable devtree in BSS and
> memmove()ing into there would be far simpler.

How big is enough?  Who is going to do the research for the various  
firmware levels of the big machines to find out how big the tree is?

Sure there are other ways to get the tree to version 16, one way is to  
change what is generated.  We could update kexec-tools fs2dt to  
geneerate a v16 tree to support zImages.

A question for the list: does anyone else have firmware/environment  
that supplies a tree < v16?


> [snip]
>>>> +	if (tree->last_comp_version > 3)
>>>> +		return;			/* don't know what to do */
>>>
>>> Rather, don't need to do anything.
>>
>> If the tree is >= 16 then we don't presently need to do anything.   If
>> there is a theoritical v4 tree we don't know what to do.  And if  
>> output
>> version is 17 but input is 16 we don't know what to do either, because
>> there likely aren't nops in the tree to consume.  I suppose we could
>> preceed it with a check for version == OUTPUT_VERSION, but then I'm
>> sure I'd get pointless differentation :-).
>
> There will never be a v4.  Or anything between v3 and v16.

I could see a v4 defined as v3 + the extra header in v17, not that I am  
proposing that.  Someone decided to skip to v16 for a reason.   If we  
knew there would never be v4-v15, why did we skip them?

[too general]
> [snip]
>>>> +	/*
>>>> +	 * move mem_rsvmap and dt_strings if they are before dt_struct
>>>> +	 * onto our nops .  Adjust start addresses for the 3 sections.
>>>> +	 */
>>>
>>> Hrm.  Do we really need to worry about this case.  You may be
>>> producing v2 trees in kexec-tools, but do they actually have the
>>> blocks out of order?  dtc certainly never produced them that way.
>>
>> Out of order?  There has never been a spec as to the order of the
>> blocks, only the implicit assumption that they follow the device tree
>> header in a reasonably packed sequence.  booting-without-of says it
>> must be in ram,; the offsets are unsigned 32 bit quantities.
>
>> As to the order, used, the first implemntation was the kernel which
>> writes memreserve, strings, then struct (both the openfirmware client
>> in prom_init and the iSeries procedural library in dt.c).  The second
>> implentation written is a procedural based library (similar to  
>> iseries,
>> never published, but still used internally) that starts with a
>> pre-built header and string table, builds the dt_struct as the
>> functions are called, and when finished copies the memreserve table  
>> and
>> fills in the dt_size, total size, and memreserve offset.
>
> Hrm.  Yes, well, the iSeries tree is weird in a bunch of ways.

My point is its the same as the client interface code, and proves the  
point the order is not specified nor need it be.  And since the order  
is the same in platforms/iseries/dt.c and kernel/prom_init.c, I fail to  
see your point of calling the iseries code wierd.  It's building a  
device tree via the structured programming methods of calling  
functions, each of which creates a node and the properties for that  
node.  Doesn't sound that much different than how a ieee bytecode  
program would create the device tree and fill out properties, and I  
would expect any firmware who created the device tree from scratch (as  
oposed to editing a paritially built tree like the fixup hooks  
presently in the wrapper) would be structured similarly.   Since it  
doesn't ahve a dynamic insertion library, it must fill in all the  
properties of a node completely before its children, and must travel  
some depth first order when creating the tree.  I don't see any reason  
to call it wierd.

>
>> fs2dt writes memreserve, struct, then strings.  Aparently the same as
>> dtc.  But yes, the strings can be before the struct, and the mem
>> reserve may or may not be when the strings are before the struct.
>
> Again.  We don't need to deal with the general case here - just the
> real case of trees produced by old kexec-tools.

This function isn't conver_kexec_tree_inplacee.  While my justification  
for merging this code is it can be used as the target for kexec with  
kexec-tools, its not my only use.  I also have my internal library that  
generates a v3 tree with the pieces ordered differently.  If the code  
is changed from its general support to support only the tree generated  
by kexec-tools, then merging has little benifit to me and in fact it is  
harder (I have to maintain a diff to a changing target vs adding a file  
to the makefile).

I'll write a later reply that talks about what subsets of this series  
make sense to merge.

milton

^ permalink raw reply

* git files from secret lab
From: Mead, Joseph @ 2007-09-26 14:53 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <4e5a3720709260725x6d2e9faemc6a6053379610df8@mail.gmail.com>

Hi,=20

I'm trying to download the xilinx patches from  Grant's git repository,
but don't quite understand what I am doing.

I cloned the tree from Linus' tree

git clone
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
(this worked fine)

cd linux-2.6

git fetch git://git.secretlab.ca/git/linux-2.6.git virtex-dev:virtex-dev

I get the error message:
Fatal: unexpected EOF
Fetch failure: git://git.secretlab.ca/git/linux-2.6.git



Thanks,
Joe

^ permalink raw reply

* Re: [PATCH 2/2]: PCI Error Recovery: Symbios SCSI First Failure
From: Matthew Wilcox @ 2007-09-26 15:02 UTC (permalink / raw)
  To: Linas Vepstas; +Cc: linuxppc-dev, linux-pci, linux-kernel, linux-scsi
In-Reply-To: <20070420204720.GM31947@austin.ibm.com>

On Fri, Apr 20, 2007 at 03:47:20PM -0500, Linas Vepstas wrote:
> Implement the so-called "first failure data capture" (FFDC) for the
> symbios PCI error recovery.  After a PCI error event is reported,
> the driver requests that MMIO be enabled. Once enabled, it 
> then reads and dumps assorted status registers, and concludes
> by requesting the usual reset sequence.

> +	/* Request that MMIO be enabled, so register dump can be taken. */
> +	return PCI_ERS_RESULT_CAN_RECOVER;
> +}

I'm a little concerned by the mention of MMIO.  It's entirely possible
for the sym2 driver to be using ioports to access the card rather than
MMIO.  Is it simply that it can't on the platform you test on?

-- 
Intel are signing my paycheques ... these opinions are still mine
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply

* Re: git files from secret lab
From: Grant Likely @ 2007-09-26 15:00 UTC (permalink / raw)
  To: Mead, Joseph; +Cc: linuxppc-embedded
In-Reply-To: <D1AFFAE2CC4BD54CA4C1543CFF4A4FCC5972C9@exchangemb3.bnl.gov>

On 9/26/07, Mead, Joseph <mead@bnl.gov> wrote:
> Hi,
>
> I'm trying to download the xilinx patches from  Grant's git repository,
> but don't quite understand what I am doing.
>
> I cloned the tree from Linus' tree
>
> git clone
> git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
> (this worked fine)
>
> cd linux-2.6

What version of git are you running (git --version).  That tree is
using the virtual hosting feature of newer versions of git.  You need
to be running at least version 1.5.

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* changing the EDLK components
From: Murat Artun @ 2007-09-26 14:25 UTC (permalink / raw)
  To: linuxppc-embedded

Hello,

In fact I have asked a variant of this question before.

I want to learn the way of building a GNU Automake project and adding
it into ELDK. This could be needed because the current version of an
ELDK component is old to meet the requirements or a library which is
not an ELDK component is to be used in our ppc system.

Section "3.7. Rebuilding ELDK Components" gives details of rebuilding
the components whose source rpms are provided with ELDK.

As I said above I asked a variant of this question to understand how
to build a library in a clean way which is not a part of ELDK.

As now, I need to upgrade an ELDK component. Namely, I need version
0.9.8 of OpenSSL, where latest ELDK release has OpenSSL with version
0.9.7f. I want to learn if it is necessary for me to follow the same
procedure stated in documentation in section "3.7. Rebuilding ELDK
Components". If this is the case, could anyone point me to resources
about how to prepare source rpms from an Automake project to prepare
the source rpm of version 0.9.8 of OpenSSL? Of course building the new
version of the component and placing everything by hand is always a
solution, but I want to understand the clean way of doing this.

Thanks and regards...

-- 
M u r at  A r t u n, MSc.
   Design Engineer

"be conservative in what you do, be liberal in what you accept from others"

^ permalink raw reply

* [PATCH] powerpc: fix pci domain detection
From: Arnd Bergmann @ 2007-09-26 14:02 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-pci, paulus, linux-kernel

The /proc/bus/pci/* files list PCI domain numbers only for
devices that claim to be on a multi-domain system. The check
for this is broken on powerpc, because the buid value is
truncated to 32 bits.

There is at least one machine (IBM QS21) that only uses
the high-order bits of the buid, so the return value
of pci_proc_domain() ends up being always zero, which
makes /proc/bus/pci useless.

Change the logic to always return '1' for a nonzero
buid value.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 291ffbc..9f63bdc 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -588,7 +588,7 @@ int pci_proc_domain(struct pci_bus *bus)
 		return 0;
 	else {
 		struct pci_controller *hose = pci_bus_to_host(bus);
-		return hose->buid;
+		return hose->buid != 0;
 	}
 }
 

^ permalink raw reply related

* Re: [PATCH] add Altivec/VMX state to coredumps
From: Matt Sealey @ 2007-09-26 14:00 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <997c015e13649d06e246d3d2c1369100@kernel.crashing.org>


Segher Boessenkool wrote:
>>>> Why not put the PVR in core dumps that'd make it all easier..
>>>
>>> PVR wouldn't be very useful...  What if you have altivec disabled ? Also
>>> that would mean your gdb has to know about all new processors...
>>
>> Is that such a big deal? :D
>>
>> Hypothetically it would be impossible to determine if you were running
>> on a G5 with the FPU and AltiVec turned off or an e500 core with SPE,
>> given the data saved.
> 
> And that is exactly as should be: a core dump represents the execution
> state of a user program, it has nothing to do with the machine it was
> generated on; it even is possible to restart a core dump generated on
> e.g. an e500 on a 970, as long as it doesn't use facilities (e.g., SPE)
> that the latter processor / execution environment doesn't provide.

A hypothetical question for you then..

What happens if you get a core dump for a G4 app which dynamically detects
AltiVec presence (from PVR or /proc) then crashes before AltiVec is enabled
in the kernel for that task (i.e. before any vector exception) and you run
it on your G3 and it magically carries on (maybe a race condition or so)
and causes a vector exception later?

Isn't that kind of useless? Wouldn't it?

-- 
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations

^ permalink raw reply

* Re: [PATCH] add Altivec/VMX state to coredumps
From: Segher Boessenkool @ 2007-09-26 13:38 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <AE678FA4-5ABF-4EAC-B691-CCE5D277955F@kernel.crashing.org>

>>>>> Why not put the PVR in core dumps that'd make it all easier..
>>>>
>>>> PVR wouldn't be very useful...  What if you have altivec disabled ?
>>>> Also
>>>> that would mean your gdb has to know about all new processors...
>>>
>>> Is that such a big deal? :D
>>>
>>> Hypothetically it would be impossible to determine if you were 
>>> running
>>> on a G5 with the FPU and AltiVec turned off or an e500 core with SPE,
>>> given the data saved.
>>
>> And that is exactly as should be: a core dump represents the execution
>> state of a user program, it has nothing to do with the machine it was
>> generated on; it even is possible to restart a core dump generated on
>> e.g. an e500 on a 970, as long as it doesn't use facilities (e.g., 
>> SPE)
>> that the latter processor / execution environment doesn't provide.
>>
>>> Is that a misfeature of GDB that we even have to
>>> worry about this, or some noble plus point of a unified ISA? You
>>> decide :)
>>
>> We don't have to worry about it :-)
>
> We should worry about it.  If one misinterprets the core file you will 
> get unexpected behavior.

I read this as "worry about the PVR".

> I see no reason not to do this properly and mark the sections such 
> that its clear if its AltiVec or SPE state, rather than overloading 
> the x86 XFPU type.

Yes, certainly, I thought we all agreed on that automatically :-)


Segher

^ permalink raw reply

* Re: [PATCH] add Altivec/VMX state to coredumps
From: Kumar Gala @ 2007-09-26 13:32 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <997c015e13649d06e246d3d2c1369100@kernel.crashing.org>


On Sep 26, 2007, at 8:21 AM, Segher Boessenkool wrote:

>>>> Why not put the PVR in core dumps that'd make it all easier..
>>>
>>> PVR wouldn't be very useful...  What if you have altivec disabled ?
>>> Also
>>> that would mean your gdb has to know about all new processors...
>>
>> Is that such a big deal? :D
>>
>> Hypothetically it would be impossible to determine if you were  
>> running
>> on a G5 with the FPU and AltiVec turned off or an e500 core with SPE,
>> given the data saved.
>
> And that is exactly as should be: a core dump represents the execution
> state of a user program, it has nothing to do with the machine it was
> generated on; it even is possible to restart a core dump generated on
> e.g. an e500 on a 970, as long as it doesn't use facilities (e.g.,  
> SPE)
> that the latter processor / execution environment doesn't provide.
>
>> Is that a misfeature of GDB that we even have to
>> worry about this, or some noble plus point of a unified ISA? You
>> decide :)
>
> We don't have to worry about it :-)

We should worry about it.  If one misinterprets the core file you  
will get unexpected behavior.  I see no reason not to do this  
properly and mark the sections such that its clear if its AltiVec or  
SPE state, rather than overloading the x86 XFPU type.

- k

^ permalink raw reply

* Re: [PATCH] add Altivec/VMX state to coredumps
From: Segher Boessenkool @ 2007-09-26 13:21 UTC (permalink / raw)
  To: Matt Sealey; +Cc: linuxppc-dev
In-Reply-To: <46FA3CDD.2070409@genesi-usa.com>

>>> Why not put the PVR in core dumps that'd make it all easier..
>>
>> PVR wouldn't be very useful...  What if you have altivec disabled ? 
>> Also
>> that would mean your gdb has to know about all new processors...
>
> Is that such a big deal? :D
>
> Hypothetically it would be impossible to determine if you were running
> on a G5 with the FPU and AltiVec turned off or an e500 core with SPE,
> given the data saved.

And that is exactly as should be: a core dump represents the execution
state of a user program, it has nothing to do with the machine it was
generated on; it even is possible to restart a core dump generated on
e.g. an e500 on a 970, as long as it doesn't use facilities (e.g., SPE)
that the latter processor / execution environment doesn't provide.

> Is that a misfeature of GDB that we even have to
> worry about this, or some noble plus point of a unified ISA? You 
> decide :)

We don't have to worry about it :-)


Segher

^ permalink raw reply

* [PATCH 7/7] [POWERPC][SPI] spi_mpc83xx: allow use on any processors with QUICC Engine
From: Anton Vorontsov @ 2007-09-26 13:15 UTC (permalink / raw)
  To: Kumar Gala; +Cc: David Brownell, spi-devel-general, linuxppc-dev
In-Reply-To: <7881139C-EEF1-41DC-AB0F-115632E892B8@kernel.crashing.org>

On Tue, Sep 25, 2007 at 11:00:38PM -0500, Kumar Gala wrote:
> I'm still in favor of making it PPC_83xx || QUICC_ENGINE.

Submitting... ;-)

- - - -
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Subject: [POWERPC][SPI] spi_mpc83xx: allow use on any processors with QUICC Engine

Currently, all QE SPI controllers are almost the same comparing to
MPC83xx's, thus let's use that driver for them.

Tested to work on MPC85xx in loopback mode.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 drivers/spi/Kconfig |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b915711..a77ede5 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -124,16 +124,17 @@ config SPI_MPC52xx_PSC
 	  Controller in master SPI mode.
 
 config SPI_MPC83xx
-	tristate "Freescale MPC83xx SPI controller"
-	depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL
+	tristate "Freescale MPC83xx/QUICC Engine SPI controller"
+	depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
 	select SPI_BITBANG
 	help
-	  This enables using the Freescale MPC83xx SPI controller in master
-	  mode.
+	  This enables using the Freescale MPC83xx and QUICC Engine SPI
+	  controllers in master mode.
 
 	  Note, this driver uniquely supports the SPI controller on the MPC83xx
-	  family of PowerPC processors.  The MPC83xx uses a simple set of shift
-	  registers for data (opposed to the CPM based descriptor model).
+	  family of PowerPC processors, plus processors with QUICC Engine
+	  technology. This driver uses a simple set of shift registers for data
+	  (opposed to the CPM based descriptor model).
 
 config SPI_OMAP_UWIRE
 	tristate "OMAP1 MicroWire"
-- 
1.5.0.6

^ permalink raw reply related

* Re: [PATCH 2/2] fsl/embedded6xx: don't cast the result of of_get_property
From: Segher Boessenkool @ 2007-09-26 12:55 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: linuxppc-dev, Jeremy Kerr
In-Reply-To: <20070926104419.1b92002e.sfr@canb.auug.org.au>

>> -	avr_clock = *(u32*)of_get_property(avr, "clock-frequency", &len);
>> -	phys_addr = ((u32*)of_get_property(avr, "reg", &len))[0];
>> +	phys_addr = of_get_property(avr, "reg", &len);
>> +	avr_clock_prop = of_get_property(avr, "clock-frequency", &len);
>
> If you don't use the value of the len variable, then you can pass NULL 
> to
> of_get_property.

OTOH, it is almost always an error to not use the length (missing
error check).


Segher

^ permalink raw reply

* Re: jffs2 file system on MPC8272ADS board
From: Nethra @ 2007-09-26 12:34 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20070925202257.559a78c5@ru.mvista.com>



Hello ,

>> 
>> hi everyone,
>> 
>> I m using custom board similar to MPC8272ADS board...
>> 
>> 1) For the first time it boots up properly in case if we overwrite any
>> existing binaries using nfs mounted file system on the board, after
>> rebooting it displays fallowing message...
>> 
>> Further such events for this erase block will not be printed
>> Eep. Child "null" (ino #1346) of dir ino #3 doesn't exist!
>> Eep. Child "autocomm" (ino #463) of dir ino #461 doesn't exist!
>> Eep. Child "calibration" (ino #464) of dir ino #461 doesn't exist!
>> Eep. Child "coredsp_driver.ko" (ino #939) of dir ino #336 doesn't exist!
>> Inode #1307 was a directory with children - removing those too...
>> Inode #564 was a directory with children - removing those too...
>> Inode #565 was a directory with children - removing those too...
>> Inode #1112 was a directory with children - removing those too...
>> Inode #1115 was a directory with children - removing those too...
>> Inode #1118 was a directory with children - removing those too...
>> Inode #1123 was a directory with children - removing those too...
>> 
>> after this board boots up properly....but it not be having overwritten
>> files
>> 

>Have you created jffs2 file system on flash prior to mounting it?

Yes I created jffs2 filesytem using mkfs.jffs2 prior to mounting and then I 
am over-writing some of the binaries.  In case of overwrites from NFS after
reboot
I see the above errors & the binaries/directories gets deleted from the
jffs2 partition.

>> 3) when board is running properly in between it starts printing on
>> console
>> repeatedly...
>> 

>Do the proper MTD partitions setup, erase the partition and create jffs2
filesystem on it.
>If after all those steps you're still getting output, that is prolly flakey
flash.

>> Header CRC failed on REF_PRISTINE node at 0x00638a6c: Read 0xffffffff,
>> calculated 0x44660075
>> Node totlen on flash (0xffffffff) != totlen from node ref (0x00000254)
>> Header CRC failed on REF_PRISTINE node at 0x00638cc0: Read 0xffffffff,
>> calculated 0x44660075
[...]
>>  and 
>> 
>> file system is created using fallowing command..
>> 
>> mkfs.jffs2 -r RFS_NEW/ -e 0x20000 -o /tftpboot/jffs2_img -b
>> 
>I am recalling playing with the options upper also cured the jffs2 warnings
(not as many as yours but anyway)

The other options I am wondering about,
  -c, --cleanmarker=SIZE Size of cleanmarker (default 12)
  -n, --no-cleanmarkers  Don't add a cleanmarker to every eraseblock
cleanmaker size will it help the cause?

Nethra
 
-- 
View this message in context: http://www.nabble.com/jffs2-file-system-on-MPC8272ADS-board-tf4513530.html#a12900017
Sent from the linuxppc-dev mailing list archive at Nabble.com.

^ permalink raw reply

* Re: [PATCH 1/7] PowerPC64: Not to insert EA=0 entry at initializing SLB
From: Arnd Bergmann @ 2007-09-26 12:15 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20070926.132034.-1300539325.kouish@swc.toshiba.co.jp>

On Wednesday 26 September 2007, Ishizaki Kou wrote:
> This is a workaround NOT to insert EA=0 entry at initializing SLB.
> Without this patch, you can see /sbin/init hanging at a machine
> which has less or equal than 256MB memory.

Can you elaborate? I don't understand why /sbin/init will hang
because of an incorrect SLB entry, or how that entry gets
initialized from get_paca()->kstack.

Are you still trying to find a better fix for 2.6.24, or do
you intend to have this patch go in for now?

Also, I did not get a patch 4/7 and 5/7. Did you send them to
some other mailing list, or did they get lost on the way?

	Arnd <><

^ permalink raw reply

* Re: [PATCH 7/7] Celleb: update for PCI
From: Arnd Bergmann @ 2007-09-26 12:09 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20070926.134050.1102532600.kouish@swc.toshiba.co.jp>

On Wednesday 26 September 2007, Ishizaki Kou wrote:
> This is a patch kit to support PCI bus on Celleb with new "I/O routines
> for PowerPC." External PCI on Celleb must do explicit synchronization
> with devices (Bus has no automatic synchronization feature).

It seems you are duplicating a lot of
arch/powerpc/platforms/cell/io-workarounds.c, in order to work around
the same problem:

> +static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr,
> +					      unsigned long paddr)
> +{
> +	int i, j;
> +	struct resource *res;
> +
> +	for (i = 0; i < celleb_pci_count; i++) {
> +		struct celleb_pci_bus *bus = &celleb_pci_busses[i];
> +		struct pci_controller *phb = bus->phb;
> +		if (paddr)
> +			for (j = 0; j < 3; j++) {
> +				res = &phb->mem_resources[j];
> +				if (paddr >= res->start && paddr <= res->end)
> +					return bus;
> +			}
> +		res = &phb->io_resource;
> +		if (vaddr && vaddr >= res->start && vaddr <= res->end)
> +			return bus;
> +	}
> +	return NULL;
> +}
> +
> +static void celleb_io_flush(const PCI_IO_ADDR addr)
> +{
> +	struct celleb_pci_bus *bus;
> +	int token;
> +
> +	token = PCI_GET_ADDR_TOKEN(addr);
> +
> +	if (token && token <= celleb_pci_count)
> +		bus = &celleb_pci_busses[token - 1];
> +	else {
> +		unsigned long vaddr, paddr;
> +		pte_t *ptep;
> +
> +		vaddr = (unsigned long)PCI_FIX_ADDR(addr);
> +		if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
> +			return;
> +
> +		ptep = find_linux_pte(init_mm.pgd, vaddr);
> +		if (ptep == NULL)
> +			paddr = 0;
> +		else
> +			paddr = pte_pfn(*ptep) << PAGE_SHIFT;
> +		bus = celleb_pci_find(vaddr, paddr);
> +
> +		if (bus == NULL)
> +			return;
> +	}
> +
> +	if (bus->dummy_read)
> +		bus->dummy_read(bus->phb);
> +}
> +
> +static u8 celleb_readb(const PCI_IO_ADDR addr)
> +{
> +	u8 val;
> +	val = __do_readb(addr);
> +	celleb_io_flush(addr);
> +	return val;
> +}
> +
> +static u16 celleb_readw(const PCI_IO_ADDR addr)
> +{
> +	u16 val;
> +	val = __do_readw(addr);
> +	celleb_io_flush(addr);
> +	return val;
> +}
> +
> +static u32 celleb_readl(const PCI_IO_ADDR addr)
> +{
> +	u32 val;
> +	val = __do_readl(addr);
> +	celleb_io_flush(addr);
> +	return val;
> +}
> +
> +static u64 celleb_readq(const PCI_IO_ADDR addr)
> +{
> +	u64 val;
> +	val = __do_readq(addr);
> +	celleb_io_flush(addr);
> +	return val;
> +}
> +
> +static u16 celleb_readw_be(const PCI_IO_ADDR addr)
> +{
> +	u16 val;
> +	val = __do_readw_be(addr);
> +	celleb_io_flush(addr);
> +	return val;
> +}
> +
> +static u32 celleb_readl_be(const PCI_IO_ADDR addr)
> +{
> +	u32 val;
> +	val = __do_readl_be(addr);
> +	celleb_io_flush(addr);
> +	return val;
> +}
> +
> +static u64 celleb_readq_be(const PCI_IO_ADDR addr)
> +{
> +	u64 val;
> +	val = __do_readq_be(addr);
> +	celleb_io_flush(addr);
> +	return val;
> +}
> +
> +static void celleb_readsb(const PCI_IO_ADDR addr,
> +			  void *buf, unsigned long count)
> +{
> +	__do_readsb(addr, buf, count);
> +	celleb_io_flush(addr);
> +}
> +
> +static void celleb_readsw(const PCI_IO_ADDR addr,
> +			  void *buf, unsigned long count)
> +{
> +	__do_readsw(addr, buf, count);
> +	celleb_io_flush(addr);
> +}
> +
> +static void celleb_readsl(const PCI_IO_ADDR addr,
> +			  void *buf, unsigned long count)
> +{
> +	__do_readsl(addr, buf, count);
> +	celleb_io_flush(addr);
> +}
> +
> +static void celleb_memcpy_fromio(void *dest,
> +				 const PCI_IO_ADDR src,
> +				 unsigned long n)
> +{
> +	__do_memcpy_fromio(dest, src, n);
> +	celleb_io_flush(src);
> +}
> +
> +static void __iomem *celleb_ioremap(unsigned long addr,
> +				     unsigned long size,
> +				     unsigned long flags)
> +{
> +	struct celleb_pci_bus *bus;
> +	void __iomem *res = __ioremap(addr, size, flags);
> +	int busno;
> +
> +	bus = celleb_pci_find(0, addr);
> +	if (bus != NULL) {
> +		busno = bus - celleb_pci_busses;
> +		PCI_SET_ADDR_TOKEN(res, busno + 1);
> +	}
> +	return res;
> +}

Is there a way that we can make that code common? I guess there could be a
file in arch/powerpc/sysdev that can handle this correctly for all hardware
that requires this particular workaround (currently celleb and QS20, but
potentially more).

	Arnd <><

^ permalink raw reply

* Re: [PATCH 3/7] Celleb: Support for Power/Reset buttons
From: Arnd Bergmann @ 2007-09-26 11:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20070926.132556.1723232353.kouish@swc.toshiba.co.jp>

On Wednesday 26 September 2007, Ishizaki Kou wrote:
> This is a patch to support Power/Reset buttons on Beat on Celleb.
> 
> On Beat, we have an event from Beat if Power button or Reset button
> is pressed. This patch catches the event and convert it to a signal
> to INIT process.
> 
> /sbin/inittab have no entry to turn the machine power off so we have
> to detect if power button is pressed or not internally in our driver.
> This idea is taken from PS3's event handling subsystem.
> 
> Signed-off-by: Kou Ishizaki <Kou.Ishizaki@toshiba.co.jp>

Basically looks good. At some point I want to do a similar driver
for the IBM cell blade, but I fear there is not much code we
can share.

> +static irqreturn_t beat_power_event(int virq, void *arg)
> +{
> +	printk(KERN_DEBUG "Beat: power button pressed\n");
> +	beat_pm_poweroff_flag = 1;
> +	if (kill_cad_pid(SIGINT, 1)) {
> +		/* Just in case killing init process failed */
> +		beat_power_off();
> +	}
> +	return IRQ_HANDLED;
> +}

I think this should call ctrl_alt_del() instead of doing 
kill_cad_pid() directly.

Also, I think you should better not call the low-level
beat_power_off() function, but rather a high-level function
that goes through the reboot notifiers first.

kernel_restart() seems appropriate for that.

> +static irqreturn_t beat_reset_event(int virq, void *arg)
> +{
> +	printk(KERN_DEBUG "Beat: reset button pressed\n");
> +	beat_pm_poweroff_flag = 0;
> +	if (kill_cad_pid(SIGINT, 1)) {
> +		/* Just in case killing init process failed */
> +		beat_restart(NULL);
> +	}
> +	return IRQ_HANDLED;
> +}

same here, except calling kernel_halt() in the end.

> +static int __init beat_event_init(void)
> +{
> +	if (!machine_is(celleb) || !firmware_has_feature(FW_FEATURE_BEAT))
> +		return -EINVAL;

Shouldn't one of the two be sufficent? It seems to me that you want to
probe for either celleb or BEAT, but not both, considering that celleb
implies BEAT.

	Arnd <><

^ permalink raw reply

* Re: [PATCH 2/7] Celleb: Move pause, kexec_cpu_down to beat.c
From: Arnd Bergmann @ 2007-09-26 11:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20070926.132314.-432833655.kouish@swc.toshiba.co.jp>

On Wednesday 26 September 2007, Ishizaki Kou wrote:
> This patch is an update for "Beat on Celleb"
> =A0 - Move beat_pause(), beat_kexec_cpu_down() from setup.c to beat.c
>=20
> Signed-off-by: <Kou.Ishizaki@toshiba.co.jp>

Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

The patch looks good, once you fix this one line:

> @@ -36,5 +36,9 @@ ssize_t beat_nvram_get_size(void);
> =A0ssize_t beat_nvram_read(char *, size_t, loff_t *);
> =A0ssize_t beat_nvram_write(char *, size_t, loff_t *);
> =A0int beat_set_xdabr(unsigned long);
> +void beat_power_save(void);
> +#ifdef CONFIG_KEXEC
> +void beat_kexec_cpu_down(int, int);
> +#endif

=46unction declarations in headers files should not be enclosed in #ifdef,
it only causes unnecessary rebuilds when the configuration changes, but
does not help.

	Arnd <><

^ permalink raw reply

* Re: Please pull powerpc.git merge branch
From: Paul Mackerras @ 2007-09-26 11:33 UTC (permalink / raw)
  To: torvalds; +Cc: linuxppc-dev, jk
In-Reply-To: <18168.62378.472571.655865@cargo.ozlabs.ibm.com>

I wrote:

> Linus,
> 
> Please do
> 
> git pull \
> git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git merge
> 
> to get a patch from Roland McGrath that fixes a user-triggerable oops
> on 64-bit powerpc.

I have added another commit from Jeremy Kerr fixing a mismerge that
caused a user visible ABI regression from 2.6.22.  The diffstat and
log below include both the patch from Roland and this new patch.

Thanks,
Paul.

 arch/powerpc/kernel/process.c            |    7 +++++++
 arch/powerpc/platforms/cell/spufs/file.c |    4 ++--
 2 files changed, 9 insertions(+), 2 deletions(-)

commit 603c461250b223ac42c10b8d1df653af1a361d44
Author: Jeremy Kerr <jk@ozlabs.org>
Date:   Wed Sep 26 10:53:45 2007 +1000

    [POWERPC] spufs: fix mismerge, making context signal{1,2} files readable again
    
    The commit 8b6f50ef1d5cc86b278eb42bc91630fad455fb10 seems to have
    been affected by a mismerge of a duplicate patch
    (d054b36ffd302ec65aabec16a0c60ddd9e6b5a62) - both the
    spufs_dir_contents and spufs_dir_nosched_contents have been given
    write-only signal notification files.
    
    This change reverts the spufs_dir_contents array to use the
    readable signal notification file implementation.
    
    Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
    Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
    Signed-off-by: Paul Mackerras <paulus@samba.org>

commit 474f81967217f3bec2389ae913da72641f2c40e3
Author: Roland McGrath <roland@redhat.com>
Date:   Mon Sep 24 16:52:44 2007 -0700

    [POWERPC] Ensure FULL_REGS on exec
    
    When PTRACE_O_TRACEEXEC is used, a ptrace call to fetch the registers at
    the PTRACE_EVENT_EXEC stop (PTRACE_PEEKUSR) will oops in CHECK_FULL_REGS.
    With recent versions, "gdb --args /bin/sh -c 'exec /bin/true'" and "run" at
    the (gdb) prompt is sufficient to produce this.  I also have written an
    isolated test case, see https://bugzilla.redhat.com/show_bug.cgi?id=301791#c15.
    
    This change fixes the problem by clearing the low bit of pt_regs.trap in
    start_thread so that FULL_REGS is true again.  This is correct since all of
    the GPRs that "full" refers to are cleared in start_thread.
    
    Signed-off-by: Roland McGrath <roland@redhat.com>
    Signed-off-by: Paul Mackerras <paulus@samba.org>

^ permalink raw reply

* Re: [PATCH] add Altivec/VMX state to coredumps
From: Matt Sealey @ 2007-09-26 11:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1190758712.23457.0.camel@localhost.localdomain>


Benjamin Herrenschmidt wrote:
> On Tue, 2007-09-25 at 19:00 +0100, Matt Sealey wrote:
>> Kumar Gala wrote:
>>> I'm wondering how we distinguish a core dump w/altivec state vs one  
>>> with SPE state.
>> Sheer number of registers saved?
>>
>> Why not put the PVR in core dumps that'd make it all easier..
> 
> PVR wouldn't be very useful...  What if you have altivec disabled ? Also
> that would mean your gdb has to know about all new processors...

Is that such a big deal? :D

Hypothetically it would be impossible to determine if you were running
on a G5 with the FPU and AltiVec turned off or an e500 core with SPE,
given the data saved. Is that a misfeature of GDB that we even have to
worry about this, or some noble plus point of a unified ISA? You decide :)

-- 
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations

^ permalink raw reply

* [PATCH 5/5] ibmebus: More speaking error return code in ibmebus_store_probe()
From: Joachim Fenkes @ 2007-09-26  9:46 UTC (permalink / raw)
  To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
  Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
	Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 arch/powerpc/kernel/ibmebus.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index c1e2963..0bd186c 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -268,10 +268,10 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
 		return -ENOMEM;
 
 	if (bus_find_device(&ibmebus_bus_type, NULL, path,
-			     ibmebus_match_path)) {
+			    ibmebus_match_path)) {
 		printk(KERN_WARNING "%s: %s has already been probed\n",
 		       __FUNCTION__, path);
-		rc = -EINVAL;
+		rc = -EEXIST;
 		goto out;
 	}
 
-- 
1.5.2

^ permalink raw reply related

* [PATCH 4/5] ibmebus: Move to of_device and of_platform_driver, match eHCA and eHEA drivers
From: Joachim Fenkes @ 2007-09-26  9:45 UTC (permalink / raw)
  To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
  Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
	Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>

Replace struct ibmebus_dev and struct ibmebus_driver with struct of_device
and struct of_platform_driver, respectively. Match the external ibmebus
interface and drivers using it.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 drivers/infiniband/hw/ehca/ehca_classes.h |    2 +-
 drivers/net/ehea/ehea.h                   |    2 +-
 include/asm-powerpc/ibmebus.h             |   38 +++------------
 arch/powerpc/kernel/ibmebus.c             |   28 ++++++-----
 drivers/infiniband/hw/ehca/ehca_eq.c      |    6 +-
 drivers/infiniband/hw/ehca/ehca_main.c    |   32 ++++++------
 drivers/net/ehea/ehea_main.c              |   72 ++++++++++++++--------------
 7 files changed, 79 insertions(+), 101 deletions(-)

diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index c2edd4c..8ca4dd4 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -106,7 +106,7 @@ struct ehca_sport {
 
 struct ehca_shca {
 	struct ib_device ib_device;
-	struct ibmebus_dev *ibmebus_dev;
+	struct of_device *ofdev;
 	u8 num_ports;
 	int hw_level;
 	struct list_head shca_list;
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 8d58be5..830a66a 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -382,7 +382,7 @@ struct ehea_port_res {
 #define EHEA_MAX_PORTS 16
 struct ehea_adapter {
 	u64 handle;
-	struct ibmebus_dev *ebus_dev;
+	struct of_device *ofdev;
 	struct ehea_port *port[EHEA_MAX_PORTS];
 	struct ehea_eq *neq;       /* notification event queue */
 	struct workqueue_struct *ehea_wq;
diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h
index 87d396e..1a9d9ae 100644
--- a/include/asm-powerpc/ibmebus.h
+++ b/include/asm-powerpc/ibmebus.h
@@ -43,42 +43,18 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/mod_devicetable.h>
-#include <asm/of_device.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
 
 extern struct bus_type ibmebus_bus_type;
 
-struct ibmebus_dev {
-	struct of_device ofdev;
-};
+int ibmebus_register_driver(struct of_platform_driver *drv);
+void ibmebus_unregister_driver(struct of_platform_driver *drv);
 
-struct ibmebus_driver {
-	char *name;
-	struct of_device_id *id_table;
-	int (*probe) (struct ibmebus_dev *dev, const struct of_device_id *id);
-	int (*remove) (struct ibmebus_dev *dev);
-	struct device_driver driver;
-};
-
-int ibmebus_register_driver(struct ibmebus_driver *drv);
-void ibmebus_unregister_driver(struct ibmebus_driver *drv);
-
-int ibmebus_request_irq(struct ibmebus_dev *dev,
-			u32 ist,
-			irq_handler_t handler,
-			unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+			unsigned long irq_flags, const char *devname,
 			void *dev_id);
-void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id);
-
-static inline struct ibmebus_driver *to_ibmebus_driver(struct device_driver *drv)
-{
-	return container_of(drv, struct ibmebus_driver, driver);
-}
-
-static inline struct ibmebus_dev *to_ibmebus_dev(struct device *dev)
-{
-	return container_of(dev, struct ibmebus_dev, ofdev.dev);
-}
-
+void ibmebus_free_irq(u32 ist, void *dev_id);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_IBMEBUS_H */
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 43d4764..c1e2963 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -192,21 +192,26 @@ static int ibmebus_create_devices(const struct of_device_id *matches)
 	return ret;
 }
 
-int ibmebus_register_driver(struct ibmebus_driver *drv)
+int ibmebus_register_driver(struct of_platform_driver *drv)
 {
-	return 0;
+	/* If the driver uses devices that ibmebus doesn't know, add them */
+	ibmebus_create_devices(drv->match_table);
+
+	drv->driver.name   = drv->name;
+	drv->driver.bus    = &ibmebus_bus_type;
+
+	return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_register_driver);
 
-void ibmebus_unregister_driver(struct ibmebus_driver *drv)
+void ibmebus_unregister_driver(struct of_platform_driver *drv)
 {
+	driver_unregister(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_unregister_driver);
 
-int ibmebus_request_irq(struct ibmebus_dev *dev,
-			u32 ist,
-			irq_handler_t handler,
-			unsigned long irq_flags, const char * devname,
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+			unsigned long irq_flags, const char *devname,
 			void *dev_id)
 {
 	unsigned int irq = irq_create_mapping(NULL, ist);
@@ -214,12 +219,11 @@ int ibmebus_request_irq(struct ibmebus_dev *dev,
 	if (irq == NO_IRQ)
 		return -EINVAL;
 
-	return request_irq(irq, handler,
-			   irq_flags, devname, dev_id);
+	return request_irq(irq, handler, irq_flags, devname, dev_id);
 }
 EXPORT_SYMBOL(ibmebus_request_irq);
 
-void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
+void ibmebus_free_irq(u32 ist, void *dev_id)
 {
 	unsigned int irq = irq_find_mapping(NULL, ist);
 
@@ -230,9 +234,7 @@ EXPORT_SYMBOL(ibmebus_free_irq);
 static ssize_t name_show(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
-	struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
-	const char *name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
-	return sprintf(buf, "%s\n", name);
+	return sprintf(buf, "%s\n", to_of_device(dev)->node->name);
 }
 
 static struct device_attribute ibmebus_dev_attrs[] = {
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index 1d41faa..b4ac617 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -123,7 +123,7 @@ int ehca_create_eq(struct ehca_shca *shca,
 
 	/* register interrupt handlers and initialize work queues */
 	if (type == EHCA_EQ) {
-		ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq,
+		ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
 					  IRQF_DISABLED, "ehca_eq",
 					  (void *)shca);
 		if (ret < 0)
@@ -131,7 +131,7 @@ int ehca_create_eq(struct ehca_shca *shca,
 
 		tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
 	} else if (type == EHCA_NEQ) {
-		ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq,
+		ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
 					  IRQF_DISABLED, "ehca_neq",
 					  (void *)shca);
 		if (ret < 0)
@@ -171,7 +171,7 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)
 	u64 h_ret;
 
 	spin_lock_irqsave(&eq->spinlock, flags);
-	ibmebus_free_irq(NULL, eq->ist, (void *)shca);
+	ibmebus_free_irq(eq->ist, (void *)shca);
 
 	h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
 
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index c84e310..8a038b1 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -404,7 +404,7 @@ int ehca_init_device(struct ehca_shca *shca)
 	shca->ib_device.node_type           = RDMA_NODE_IB_CA;
 	shca->ib_device.phys_port_cnt       = shca->num_ports;
 	shca->ib_device.num_comp_vectors    = 1;
-	shca->ib_device.dma_device          = &shca->ibmebus_dev->ofdev.dev;
+	shca->ib_device.dma_device          = &shca->ofdev->dev;
 	shca->ib_device.query_device        = ehca_query_device;
 	shca->ib_device.query_port          = ehca_query_port;
 	shca->ib_device.query_gid           = ehca_query_gid;
@@ -658,7 +658,7 @@ static struct attribute_group ehca_dev_attr_grp = {
 	.attrs = ehca_dev_attrs
 };
 
-static int __devinit ehca_probe(struct ibmebus_dev *dev,
+static int __devinit ehca_probe(struct of_device *dev,
 				const struct of_device_id *id)
 {
 	struct ehca_shca *shca;
@@ -666,16 +666,16 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
 	struct ib_pd *ibpd;
 	int ret;
 
-	handle = of_get_property(dev->ofdev.node, "ibm,hca-handle", NULL);
+	handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
 	if (!handle) {
 		ehca_gen_err("Cannot get eHCA handle for adapter: %s.",
-			     dev->ofdev.node->full_name);
+			     dev->node->full_name);
 		return -ENODEV;
 	}
 
 	if (!(*handle)) {
 		ehca_gen_err("Wrong eHCA handle for adapter: %s.",
-			     dev->ofdev.node->full_name);
+			     dev->node->full_name);
 		return -ENODEV;
 	}
 
@@ -686,9 +686,9 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
 	}
 	mutex_init(&shca->modify_mutex);
 
-	shca->ibmebus_dev = dev;
+	shca->ofdev = dev;
 	shca->ipz_hca_handle.handle = *handle;
-	dev->ofdev.dev.driver_data = shca;
+	dev->dev.driver_data = shca;
 
 	ret = ehca_sense_attributes(shca);
 	if (ret < 0) {
@@ -764,7 +764,7 @@ static int __devinit ehca_probe(struct ibmebus_dev *dev,
 		}
 	}
 
-	ret = sysfs_create_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
+	ret = sysfs_create_group(&dev->dev.kobj, &ehca_dev_attr_grp);
 	if (ret) /* only complain; we can live without attributes */
 		ehca_err(&shca->ib_device,
 			 "Cannot create device attributes  ret=%d", ret);
@@ -814,12 +814,12 @@ probe1:
 	return -EINVAL;
 }
 
-static int __devexit ehca_remove(struct ibmebus_dev *dev)
+static int __devexit ehca_remove(struct of_device *dev)
 {
-	struct ehca_shca *shca = dev->ofdev.dev.driver_data;
+	struct ehca_shca *shca = dev->dev.driver_data;
 	int ret;
 
-	sysfs_remove_group(&dev->ofdev.dev.kobj, &ehca_dev_attr_grp);
+	sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp);
 
 	if (ehca_open_aqp1 == 1) {
 		int i;
@@ -870,11 +870,11 @@ static struct of_device_id ehca_device_table[] =
 	{},
 };
 
-static struct ibmebus_driver ehca_driver = {
-	.name     = "ehca",
-	.id_table = ehca_device_table,
-	.probe    = ehca_probe,
-	.remove   = ehca_remove,
+static struct of_platform_driver ehca_driver = {
+	.name        = "ehca",
+	.match_table = ehca_device_table,
+	.probe       = ehca_probe,
+	.remove      = ehca_remove,
 };
 
 void ehca_poll_eqs(unsigned long data)
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 717b129..a4d4150 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -89,10 +89,10 @@ struct workqueue_struct *ehea_driver_wq;
 struct work_struct ehea_rereg_mr_task;
 
 
-static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
+static int __devinit ehea_probe_adapter(struct of_device *dev,
 					const struct of_device_id *id);
 
-static int __devexit ehea_remove(struct ibmebus_dev *dev);
+static int __devexit ehea_remove(struct of_device *dev);
 
 static struct of_device_id ehea_device_table[] = {
 	{
@@ -102,9 +102,9 @@ static struct of_device_id ehea_device_table[] = {
 	{},
 };
 
-static struct ibmebus_driver ehea_driver = {
+static struct of_platform_driver ehea_driver = {
 	.name = "ehea",
-	.id_table = ehea_device_table,
+	.match_table = ehea_device_table,
 	.probe = ehea_probe_adapter,
 	.remove = ehea_remove,
 };
@@ -968,7 +968,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
 	snprintf(port->int_aff_name, EHEA_IRQ_NAME_SIZE - 1, "%s-aff",
 		 dev->name);
 
-	ret = ibmebus_request_irq(NULL, port->qp_eq->attr.ist1,
+	ret = ibmebus_request_irq(port->qp_eq->attr.ist1,
 				  ehea_qp_aff_irq_handler,
 				  IRQF_DISABLED, port->int_aff_name, port);
 	if (ret) {
@@ -986,7 +986,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
 		pr = &port->port_res[i];
 		snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1,
 			 "%s-queue%d", dev->name, i);
-		ret = ibmebus_request_irq(NULL, pr->eq->attr.ist1,
+		ret = ibmebus_request_irq(pr->eq->attr.ist1,
 					  ehea_recv_irq_handler,
 					  IRQF_DISABLED, pr->int_send_name,
 					  pr);
@@ -1007,11 +1007,11 @@ out:
 out_free_req:
 	while (--i >= 0) {
 		u32 ist = port->port_res[i].eq->attr.ist1;
-		ibmebus_free_irq(NULL, ist, &port->port_res[i]);
+		ibmebus_free_irq(ist, &port->port_res[i]);
 	}
 
 out_free_qpeq:
-	ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port);
+	ibmebus_free_irq(port->qp_eq->attr.ist1, port);
 	i = port->num_def_qps;
 
 	goto out;
@@ -1028,14 +1028,14 @@ static void ehea_free_interrupts(struct net_device *dev)
 
 	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
 		pr = &port->port_res[i];
-		ibmebus_free_irq(NULL, pr->eq->attr.ist1, pr);
+		ibmebus_free_irq(pr->eq->attr.ist1, pr);
 		if (netif_msg_intr(port))
 			ehea_info("free send irq for res %d with handle 0x%X",
 				  i, pr->eq->attr.ist1);
 	}
 
 	/* associated events */
-	ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port);
+	ibmebus_free_irq(port->qp_eq->attr.ist1, port);
 	if (netif_msg_intr(port))
 		ehea_info("associated event interrupt for handle 0x%X freed",
 			  port->qp_eq->attr.ist1);
@@ -2548,7 +2548,7 @@ static struct device *ehea_register_port(struct ehea_port *port,
 	int ret;
 
 	port->ofdev.node = of_node_get(dn);
-	port->ofdev.dev.parent = &port->adapter->ebus_dev->ofdev.dev;
+	port->ofdev.dev.parent = &port->adapter->ofdev->dev;
 	port->ofdev.dev.bus = &ibmebus_bus_type;
 
 	sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++);
@@ -2729,7 +2729,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
 	const u32 *dn_log_port_id;
 	int i = 0;
 
-	lhea_dn = adapter->ebus_dev->ofdev.node;
+	lhea_dn = adapter->ofdev->node;
 	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
 
 		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
@@ -2769,7 +2769,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
 	struct device_node *eth_dn = NULL;
 	const u32 *dn_log_port_id;
 
-	lhea_dn = adapter->ebus_dev->ofdev.node;
+	lhea_dn = adapter->ofdev->node;
 	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
 
 		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
@@ -2875,31 +2875,31 @@ static ssize_t ehea_remove_port(struct device *dev,
 static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
 static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
 
-int ehea_create_device_sysfs(struct ibmebus_dev *dev)
+int ehea_create_device_sysfs(struct of_device *dev)
 {
-	int ret = device_create_file(&dev->ofdev.dev, &dev_attr_probe_port);
+	int ret = device_create_file(&dev->dev, &dev_attr_probe_port);
 	if (ret)
 		goto out;
 
-	ret = device_create_file(&dev->ofdev.dev, &dev_attr_remove_port);
+	ret = device_create_file(&dev->dev, &dev_attr_remove_port);
 out:
 	return ret;
 }
 
-void ehea_remove_device_sysfs(struct ibmebus_dev *dev)
+void ehea_remove_device_sysfs(struct of_device *dev)
 {
-	device_remove_file(&dev->ofdev.dev, &dev_attr_probe_port);
-	device_remove_file(&dev->ofdev.dev, &dev_attr_remove_port);
+	device_remove_file(&dev->dev, &dev_attr_probe_port);
+	device_remove_file(&dev->dev, &dev_attr_remove_port);
 }
 
-static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
+static int __devinit ehea_probe_adapter(struct of_device *dev,
 					const struct of_device_id *id)
 {
 	struct ehea_adapter *adapter;
 	const u64 *adapter_handle;
 	int ret;
 
-	if (!dev || !dev->ofdev.node) {
+	if (!dev || !dev->node) {
 		ehea_error("Invalid ibmebus device probed");
 		return -EINVAL;
 	}
@@ -2907,36 +2907,36 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
 	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
 	if (!adapter) {
 		ret = -ENOMEM;
-		dev_err(&dev->ofdev.dev, "no mem for ehea_adapter\n");
+		dev_err(&dev->dev, "no mem for ehea_adapter\n");
 		goto out;
 	}
 
 	list_add(&adapter->list, &adapter_list);
 
-	adapter->ebus_dev = dev;
+	adapter->ofdev = dev;
 
-	adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
+	adapter_handle = of_get_property(dev->node, "ibm,hea-handle",
 					 NULL);
 	if (adapter_handle)
 		adapter->handle = *adapter_handle;
 
 	if (!adapter->handle) {
-		dev_err(&dev->ofdev.dev, "failed getting handle for adapter"
-			" '%s'\n", dev->ofdev.node->full_name);
+		dev_err(&dev->dev, "failed getting handle for adapter"
+			" '%s'\n", dev->node->full_name);
 		ret = -ENODEV;
 		goto out_free_ad;
 	}
 
 	adapter->pd = EHEA_PD_ID;
 
-	dev->ofdev.dev.driver_data = adapter;
+	dev->dev.driver_data = adapter;
 
 
 	/* initialize adapter and ports */
 	/* get adapter properties */
 	ret = ehea_sense_adapter_attr(adapter);
 	if (ret) {
-		dev_err(&dev->ofdev.dev, "sense_adapter_attr failed: %d", ret);
+		dev_err(&dev->dev, "sense_adapter_attr failed: %d", ret);
 		goto out_free_ad;
 	}
 
@@ -2944,18 +2944,18 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
 				      EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1);
 	if (!adapter->neq) {
 		ret = -EIO;
-		dev_err(&dev->ofdev.dev, "NEQ creation failed");
+		dev_err(&dev->dev, "NEQ creation failed");
 		goto out_free_ad;
 	}
 
 	tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
 		     (unsigned long)adapter);
 
-	ret = ibmebus_request_irq(NULL, adapter->neq->attr.ist1,
+	ret = ibmebus_request_irq(adapter->neq->attr.ist1,
 				  ehea_interrupt_neq, IRQF_DISABLED,
 				  "ehea_neq", adapter);
 	if (ret) {
-		dev_err(&dev->ofdev.dev, "requesting NEQ IRQ failed");
+		dev_err(&dev->dev, "requesting NEQ IRQ failed");
 		goto out_kill_eq;
 	}
 
@@ -2971,7 +2971,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
 
 	ret = ehea_setup_ports(adapter);
 	if (ret) {
-		dev_err(&dev->ofdev.dev, "setup_ports failed");
+		dev_err(&dev->dev, "setup_ports failed");
 		goto out_rem_dev_sysfs;
 	}
 
@@ -2985,7 +2985,7 @@ out_kill_wq:
 	destroy_workqueue(adapter->ehea_wq);
 
 out_free_irq:
-	ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
+	ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
 
 out_kill_eq:
 	ehea_destroy_eq(adapter->neq);
@@ -2996,9 +2996,9 @@ out:
 	return ret;
 }
 
-static int __devexit ehea_remove(struct ibmebus_dev *dev)
+static int __devexit ehea_remove(struct of_device *dev)
 {
-	struct ehea_adapter *adapter = dev->ofdev.dev.driver_data;
+	struct ehea_adapter *adapter = dev->dev.driver_data;
 	int i;
 
 	for (i = 0; i < EHEA_MAX_PORTS; i++)
@@ -3011,7 +3011,7 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev)
 
 	destroy_workqueue(adapter->ehea_wq);
 
-	ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
+	ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
 	tasklet_kill(&adapter->neq_tasklet);
 
 	ehea_destroy_eq(adapter->neq);
-- 
1.5.2

^ permalink raw reply related

* [PATCH 3/5] ibmebus: Add device creation and bus probing based on of_device
From: Joachim Fenkes @ 2007-09-26  9:45 UTC (permalink / raw)
  To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
  Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
	Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>

The devtree root is now searched for devices matching a built-in whitelist
during boot, so these devices appear on the bus from the beginning. It is
still possible to manually add/remove devices to/from the bus by using the
probe/remove sysfs interface. Also, when a device driver registers itself,
the devtree is matched against its matchlist.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 arch/powerpc/kernel/ibmebus.c |  100 +++++++++++++++++++++++++++++++++-------
 1 files changed, 82 insertions(+), 18 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index cc80f84..43d4764 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -51,6 +51,13 @@ static struct device ibmebus_bus_device = { /* fake "parent" device */
 
 struct bus_type ibmebus_bus_type;
 
+/* These devices will automatically be added to the bus during init */
+static struct of_device_id builtin_matches[] = {
+	{ .compatible = "IBM,lhca" },
+	{ .compatible = "IBM,lhea" },
+	{},
+};
+
 static void *ibmebus_alloc_coherent(struct device *dev,
 				    size_t size,
 				    dma_addr_t *dma_handle,
@@ -124,6 +131,67 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
 	.dma_supported  = ibmebus_dma_supported,
 };
 
+static int ibmebus_match_path(struct device *dev, void *data)
+{
+	struct device_node *dn = to_of_device(dev)->node;
+	return (dn->full_name &&
+		(strcasecmp((char *)data, dn->full_name) == 0));
+}
+
+static int ibmebus_match_node(struct device *dev, void *data)
+{
+	return to_of_device(dev)->node == data;
+}
+
+static int ibmebus_create_device(struct device_node *dn)
+{
+	struct of_device *dev;
+	int ret;
+
+	dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->dev.bus = &ibmebus_bus_type;
+	dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
+
+	ret = of_device_register(dev);
+	if (ret) {
+		of_device_free(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ibmebus_create_devices(const struct of_device_id *matches)
+{
+	struct device_node *root, *child;
+	int ret = 0;
+
+	root = of_find_node_by_path("/");
+
+	for (child = NULL; (child = of_get_next_child(root, child)); ) {
+		if (!of_match_node(matches, child))
+			continue;
+
+		if (bus_find_device(&ibmebus_bus_type, NULL, child,
+				    ibmebus_match_node))
+			continue;
+
+		ret = ibmebus_create_device(child);
+		if (ret) {
+			printk(KERN_ERR "%s: failed to create device (%i)",
+			       __FUNCTION__, ret);
+			of_node_put(child);
+			break;
+		}
+	}
+
+	of_node_put(root);
+	return ret;
+}
+
 int ibmebus_register_driver(struct ibmebus_driver *drv)
 {
 	return 0;
@@ -172,18 +240,6 @@ static struct device_attribute ibmebus_dev_attrs[] = {
 	__ATTR_NULL
 };
 
-static int ibmebus_match_path(struct device *dev, void *data)
-{
-	int rc;
-	struct device_node *dn =
-		of_node_get(to_ibmebus_dev(dev)->ofdev.node);
-
-	rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0));
-
-	of_node_put(dn);
-	return rc;
-}
-
 static char *ibmebus_chomp(const char *in, size_t count)
 {
 	char *out = (char*)kmalloc(count + 1, GFP_KERNEL);
@@ -202,9 +258,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
 				   const char *buf, size_t count)
 {
 	struct device_node *dn = NULL;
-	struct ibmebus_dev *dev;
 	char *path;
-	ssize_t rc;
+	ssize_t rc = 0;
 
 	path = ibmebus_chomp(buf, count);
 	if (!path)
@@ -219,9 +274,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
 	}
 
 	if ((dn = of_find_node_by_path(path))) {
-/*		dev = ibmebus_register_device_node(dn); */
+		rc = ibmebus_create_device(dn);
 		of_node_put(dn);
-		rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
 	} else {
 		printk(KERN_WARNING "%s: no such device node: %s\n",
 		       __FUNCTION__, path);
@@ -230,7 +284,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
 
 out:
 	kfree(path);
-	return rc;
+	if (rc)
+		return rc;
+	return count;
 }
 
 static ssize_t ibmebus_store_remove(struct bus_type *bus,
@@ -245,7 +301,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
 
 	if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
 				   ibmebus_match_path))) {
-/*		ibmebus_unregister_device(dev); */
+		of_device_unregister(to_of_device(dev));
 
 		kfree(path);
 		return count;
@@ -265,6 +321,7 @@ static struct bus_attribute ibmebus_bus_attrs[] = {
 };
 
 struct bus_type ibmebus_bus_type = {
+	.uevent    = of_device_uevent,
 	.dev_attrs = ibmebus_dev_attrs,
 	.bus_attrs = ibmebus_bus_attrs
 };
@@ -292,6 +349,13 @@ static int __init ibmebus_bus_init(void)
 		return err;
 	}
 
+	err = ibmebus_create_devices(builtin_matches);
+	if (err) {
+		device_unregister(&ibmebus_bus_device);
+		bus_unregister(&ibmebus_bus_type);
+		return err;
+	}
+
 	return 0;
 }
 postcore_initcall(ibmebus_bus_init);
-- 
1.5.2

^ permalink raw reply related

* [PATCH 2/5] ibmebus: Remove bus match/probe/remove functions
From: Joachim Fenkes @ 2007-09-26  9:44 UTC (permalink / raw)
  To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
  Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
	Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>

Remove old code that will be replaced by rewritten and shorter functions in
the next patch. Keep struct ibmebus_dev and struct ibmebus_driver for now,
but replace ibmebus_{,un}register_driver() by dummy functions. This way, the
kernel will still compile and run during the transition and git bisect will
be happy.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 arch/powerpc/kernel/ibmebus.c |  199 ++---------------------------------------
 1 files changed, 6 insertions(+), 193 deletions(-)

diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index d6a38cd..cc80f84 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -41,6 +41,7 @@
 #include <linux/kobject.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/of_platform.h>
 #include <asm/ibmebus.h>
 #include <asm/abs_addr.h>
 
@@ -123,183 +124,14 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
 	.dma_supported  = ibmebus_dma_supported,
 };
 
-static int ibmebus_bus_probe(struct device *dev)
-{
-	struct ibmebus_dev *ibmebusdev    = to_ibmebus_dev(dev);
-	struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
-	const struct of_device_id *id;
-	int error = -ENODEV;
-
-	if (!ibmebusdrv->probe)
-		return error;
-
-	id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
-	if (id) {
-		error = ibmebusdrv->probe(ibmebusdev, id);
-	}
-
-	return error;
-}
-
-static int ibmebus_bus_remove(struct device *dev)
-{
-	struct ibmebus_dev *ibmebusdev    = to_ibmebus_dev(dev);
-	struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
-
-	if (ibmebusdrv->remove) {
-		return ibmebusdrv->remove(ibmebusdev);
-	}
-
-	return 0;
-}
-
-static void __devinit ibmebus_dev_release(struct device *dev)
-{
-	of_node_put(to_ibmebus_dev(dev)->ofdev.node);
-	kfree(to_ibmebus_dev(dev));
-}
-
-static int __devinit ibmebus_register_device_common(
-	struct ibmebus_dev *dev, const char *name)
-{
-	int err = 0;
-
-	dev->ofdev.dev.parent  = &ibmebus_bus_device;
-	dev->ofdev.dev.bus     = &ibmebus_bus_type;
-	dev->ofdev.dev.release = ibmebus_dev_release;
-
-	dev->ofdev.dev.archdata.of_node = dev->ofdev.node;
-	dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops;
-	dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node);
-
-	/* An ibmebusdev is based on a of_device. We have to change the
-	 * bus type to use our own DMA mapping operations.
-	 */
-	if ((err = of_device_register(&dev->ofdev)) != 0) {
-		printk(KERN_ERR "%s: failed to register device (%d).\n",
-		       __FUNCTION__, err);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static struct ibmebus_dev* __devinit ibmebus_register_device_node(
-	struct device_node *dn)
-{
-	struct ibmebus_dev *dev;
-	int i, len, bus_len;
-
-	dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	dev->ofdev.node = of_node_get(dn);
-
-	len = strlen(dn->full_name + 1);
-	bus_len = min(len, BUS_ID_SIZE - 1);
-	memcpy(dev->ofdev.dev.bus_id, dn->full_name + 1
-	       + (len - bus_len), bus_len);
-	for (i = 0; i < bus_len; i++)
-		if (dev->ofdev.dev.bus_id[i] == '/')
-			dev->ofdev.dev.bus_id[i] = '_';
-
-	/* Register with generic device framework. */
-	if (ibmebus_register_device_common(dev, dn->name) != 0) {
-		kfree(dev);
-		return ERR_PTR(-ENODEV);
-	}
-
-	return dev;
-}
-
-static void ibmebus_probe_of_nodes(char* name)
-{
-	struct device_node *dn = NULL;
-
-	while ((dn = of_find_node_by_name(dn, name))) {
-		if (IS_ERR(ibmebus_register_device_node(dn))) {
-			of_node_put(dn);
-			return;
-		}
-	}
-
-	of_node_put(dn);
-
-	return;
-}
-
-static void ibmebus_add_devices_by_id(struct of_device_id *idt)
-{
-	while (strlen(idt->name) > 0) {
-		ibmebus_probe_of_nodes(idt->name);
-		idt++;
-	}
-
-	return;
-}
-
-static int ibmebus_match_name(struct device *dev, void *data)
-{
-	const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
-	const char *name;
-
-	name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
-
-	if (name && (strcmp(data, name) == 0))
-		return 1;
-
-	return 0;
-}
-
-static int ibmebus_unregister_device(struct device *dev)
-{
-	of_device_unregister(to_of_device(dev));
-
-	return 0;
-}
-
-static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
-{
-	struct device *dev;
-
-	while (strlen(idt->name) > 0) {
-		while ((dev = bus_find_device(&ibmebus_bus_type, NULL,
-					      (void*)idt->name,
-					      ibmebus_match_name))) {
-			ibmebus_unregister_device(dev);
-		}
-		idt++;
-	}
-
-	return;
-}
-
 int ibmebus_register_driver(struct ibmebus_driver *drv)
 {
-	int err = 0;
-
-	drv->driver.name   = drv->name;
-	drv->driver.bus    = &ibmebus_bus_type;
-	drv->driver.probe  = ibmebus_bus_probe;
-	drv->driver.remove = ibmebus_bus_remove;
-
-	if ((err = driver_register(&drv->driver) != 0))
-		return err;
-
-	/* remove all supported devices first, in case someone
-	 * probed them manually before registering the driver */
-	ibmebus_remove_devices_by_id(drv->id_table);
-	ibmebus_add_devices_by_id(drv->id_table);
-
 	return 0;
 }
 EXPORT_SYMBOL(ibmebus_register_driver);
 
 void ibmebus_unregister_driver(struct ibmebus_driver *drv)
 {
-	driver_unregister(&drv->driver);
-	ibmebus_remove_devices_by_id(drv->id_table);
 }
 EXPORT_SYMBOL(ibmebus_unregister_driver);
 
@@ -327,23 +159,6 @@ void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
 }
 EXPORT_SYMBOL(ibmebus_free_irq);
 
-static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
-{
-	const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
-	struct ibmebus_driver *ebus_drv    = to_ibmebus_driver(drv);
-	const struct of_device_id *ids     = ebus_drv->id_table;
-	const struct of_device_id *found_id;
-
-	if (!ids)
-		return 0;
-
-	found_id = of_match_device(ids, &ebus_dev->ofdev);
-	if (found_id)
-		return 1;
-
-	return 0;
-}
-
 static ssize_t name_show(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
@@ -404,7 +219,7 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
 	}
 
 	if ((dn = of_find_node_by_path(path))) {
-		dev = ibmebus_register_device_node(dn);
+/*		dev = ibmebus_register_device_node(dn); */
 		of_node_put(dn);
 		rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
 	} else {
@@ -430,7 +245,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
 
 	if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
 				   ibmebus_match_path))) {
-		ibmebus_unregister_device(dev);
+/*		ibmebus_unregister_device(dev); */
 
 		kfree(path);
 		return count;
@@ -450,8 +265,6 @@ static struct bus_attribute ibmebus_bus_attrs[] = {
 };
 
 struct bus_type ibmebus_bus_type = {
-	.name      = "ibmebus",
-	.match     = ibmebus_bus_match,
 	.dev_attrs = ibmebus_dev_attrs,
 	.bus_attrs = ibmebus_bus_attrs
 };
@@ -463,9 +276,9 @@ static int __init ibmebus_bus_init(void)
 
 	printk(KERN_INFO "IBM eBus Device Driver\n");
 
-	err = bus_register(&ibmebus_bus_type);
+	err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
 	if (err) {
-		printk(KERN_ERR ":%s: failed to register IBM eBus.\n",
+		printk(KERN_ERR "%s: failed to register IBM eBus.\n",
 		       __FUNCTION__);
 		return err;
 	}
@@ -481,4 +294,4 @@ static int __init ibmebus_bus_init(void)
 
 	return 0;
 }
-__initcall(ibmebus_bus_init);
+postcore_initcall(ibmebus_bus_init);
-- 
1.5.2

^ permalink raw reply related

* [PATCH 1/5] PowerPC: Move of_device allocation into of_device.[ch]
From: Joachim Fenkes @ 2007-09-26  9:44 UTC (permalink / raw)
  To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
  Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
	Stefan Roscher
In-Reply-To: <200709261143.24735.fenkes@de.ibm.com>

Extract generic of_device allocation code from of_platform_device_create()
and move it into of_device.[ch], called of_device_alloc(). Also, there's now
of_device_free() which puts the device node.

This way, bus drivers that build on of_platform (like ibmebus will) can
build upon this code instead of reinventing the wheel.

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
---
 include/asm-powerpc/of_device.h   |    4 ++
 include/linux/of_device.h         |    5 ++
 arch/powerpc/kernel/of_device.c   |   80 +++++++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/of_platform.c |   70 +-------------------------------
 4 files changed, 91 insertions(+), 68 deletions(-)

diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index ec2a8a2..9ab469d 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -17,6 +17,10 @@ struct of_device
 	struct device		dev;		/* Generic device interface */
 };
 
+extern struct of_device *of_device_alloc(struct device_node *np,
+					 const char *bus_id,
+					 struct device *parent);
+
 extern ssize_t of_device_get_modalias(struct of_device *ofdev,
 					char *str, ssize_t len);
 extern int of_device_uevent(struct device *dev,
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 91bf84b..212bffb 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -22,5 +22,10 @@ extern int of_device_register(struct of_device *ofdev);
 extern void of_device_unregister(struct of_device *ofdev);
 extern void of_release_dev(struct device *dev);
 
+static inline void of_device_free(struct of_device *dev)
+{
+	of_release_dev(&dev->dev);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_OF_DEVICE_H */
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 89b911e..ecb8b0e 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -7,8 +7,88 @@
 #include <linux/slab.h>
 
 #include <asm/errno.h>
+#include <asm/dcr.h>
 #include <asm/of_device.h>
 
+static void of_device_make_bus_id(struct of_device *dev)
+{
+	static atomic_t bus_no_reg_magic;
+	struct device_node *node = dev->node;
+	char *name = dev->dev.bus_id;
+	const u32 *reg;
+	u64 addr;
+	int magic;
+
+	/*
+	 * If it's a DCR based device, use 'd' for native DCRs
+	 * and 'D' for MMIO DCRs.
+	 */
+#ifdef CONFIG_PPC_DCR
+	reg = of_get_property(node, "dcr-reg", NULL);
+	if (reg) {
+#ifdef CONFIG_PPC_DCR_NATIVE
+		snprintf(name, BUS_ID_SIZE, "d%x.%s",
+			 *reg, node->name);
+#else /* CONFIG_PPC_DCR_NATIVE */
+		addr = of_translate_dcr_address(node, *reg, NULL);
+		if (addr != OF_BAD_ADDR) {
+			snprintf(name, BUS_ID_SIZE,
+				 "D%llx.%s", (unsigned long long)addr,
+				 node->name);
+			return;
+		}
+#endif /* !CONFIG_PPC_DCR_NATIVE */
+	}
+#endif /* CONFIG_PPC_DCR */
+
+	/*
+	 * For MMIO, get the physical address
+	 */
+	reg = of_get_property(node, "reg", NULL);
+	if (reg) {
+		addr = of_translate_address(node, reg);
+		if (addr != OF_BAD_ADDR) {
+			snprintf(name, BUS_ID_SIZE,
+				 "%llx.%s", (unsigned long long)addr,
+				 node->name);
+			return;
+		}
+	}
+
+	/*
+	 * No BusID, use the node name and add a globally incremented
+	 * counter (and pray...)
+	 */
+	magic = atomic_add_return(1, &bus_no_reg_magic);
+	snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
+}
+
+struct of_device *of_device_alloc(struct device_node *np,
+				  const char *bus_id,
+				  struct device *parent)
+{
+	struct of_device *dev;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->node = of_node_get(np);
+	dev->dev.dma_mask = &dev->dma_mask;
+	dev->dev.parent = parent;
+	dev->dev.release = of_release_dev;
+	dev->dev.archdata.of_node = np;
+	dev->dev.archdata.numa_node = of_node_to_nid(np);
+
+	if (bus_id)
+		strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+	else
+		of_device_make_bus_id(dev);
+
+	return dev;
+}
+EXPORT_SYMBOL(of_device_alloc);
+
 ssize_t of_device_get_modalias(struct of_device *ofdev,
 				char *str, ssize_t len)
 {
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index f70e787..1d96b82 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -21,7 +21,6 @@
 #include <linux/pci.h>
 
 #include <asm/errno.h>
-#include <asm/dcr.h>
 #include <asm/of_device.h>
 #include <asm/of_platform.h>
 #include <asm/topology.h>
@@ -53,8 +52,6 @@ static struct of_device_id of_default_bus_ids[] = {
 	{},
 };
 
-static atomic_t bus_no_reg_magic;
-
 struct bus_type of_platform_bus_type = {
        .uevent	= of_device_uevent,
 };
@@ -84,89 +81,26 @@ void of_unregister_platform_driver(struct of_platform_driver *drv)
 }
 EXPORT_SYMBOL(of_unregister_platform_driver);
 
-static void of_platform_make_bus_id(struct of_device *dev)
-{
-	struct device_node *node = dev->node;
-	char *name = dev->dev.bus_id;
-	const u32 *reg;
-	u64 addr;
-	int magic;
-
-	/*
-	 * If it's a DCR based device, use 'd' for native DCRs
-	 * and 'D' for MMIO DCRs.
-	 */
-#ifdef CONFIG_PPC_DCR
-	reg = of_get_property(node, "dcr-reg", NULL);
-	if (reg) {
-#ifdef CONFIG_PPC_DCR_NATIVE
-		snprintf(name, BUS_ID_SIZE, "d%x.%s",
-			 *reg, node->name);
-#else /* CONFIG_PPC_DCR_NATIVE */
-		addr = of_translate_dcr_address(node, *reg, NULL);
-		if (addr != OF_BAD_ADDR) {
-			snprintf(name, BUS_ID_SIZE,
-				 "D%llx.%s", (unsigned long long)addr,
-				 node->name);
-			return;
-		}
-#endif /* !CONFIG_PPC_DCR_NATIVE */
-	}
-#endif /* CONFIG_PPC_DCR */
-
-	/*
-	 * For MMIO, get the physical address
-	 */
-	reg = of_get_property(node, "reg", NULL);
-	if (reg) {
-		addr = of_translate_address(node, reg);
-		if (addr != OF_BAD_ADDR) {
-			snprintf(name, BUS_ID_SIZE,
-				 "%llx.%s", (unsigned long long)addr,
-				 node->name);
-			return;
-		}
-	}
-
-	/*
-	 * No BusID, use the node name and add a globally incremented
-	 * counter (and pray...)
-	 */
-	magic = atomic_add_return(1, &bus_no_reg_magic);
-	snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
-}
-
 struct of_device* of_platform_device_create(struct device_node *np,
 					    const char *bus_id,
 					    struct device *parent)
 {
 	struct of_device *dev;
 
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	dev = of_device_alloc(np, bus_id, parent);
 	if (!dev)
 		return NULL;
 
-	dev->node = of_node_get(np);
 	dev->dma_mask = 0xffffffffUL;
-	dev->dev.dma_mask = &dev->dma_mask;
-	dev->dev.parent = parent;
 	dev->dev.bus = &of_platform_bus_type;
-	dev->dev.release = of_release_dev;
-	dev->dev.archdata.of_node = np;
-	dev->dev.archdata.numa_node = of_node_to_nid(np);
 
 	/* We do not fill the DMA ops for platform devices by default.
 	 * This is currently the responsibility of the platform code
 	 * to do such, possibly using a device notifier
 	 */
 
-	if (bus_id)
-		strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
-	else
-		of_platform_make_bus_id(dev);
-
 	if (of_device_register(dev) != 0) {
-		kfree(dev);
+		of_device_free(dev);
 		return NULL;
 	}
 
-- 
1.5.2

^ permalink raw reply related

* [PATCH 0/5] [REPOST] PowerPC: ibmebus refactoring and fixes
From: Joachim Fenkes @ 2007-09-26  9:43 UTC (permalink / raw)
  To: Paul Mackerras, LinuxPPC-Dev, LKML, Arnd Bergmann
  Cc: Thomas Klein, Paul Mackerras, Jan-Bernd Themann, Christoph Raisch,
	Stefan Roscher

This patchset will merge the ibmebus and of_platform bus drivers by basing a
lot of ibmebus functionality on of_platform code and adding the features
specific to ibmebus on top of that.

This is a repost of my previous patchset incorporating Arnd's comments.

I split the actual ibmebus rework into three patches (2/5-4/5) for easier
readability. The kernel will compile during the intermediate states, and
ibmebus will not crash, but not work either.

As a side-effect of patch 3/5, a problem with bus_id collisions in case of
two devices sharing the same location code is resolved -- the bus_id is now
determined differently.

[1/5] moves of_device allocation into of_device.[ch]
[2/5] removes the old bus match/probe/remove functions
[3/5] adds device creation and bus probing based on of_device
[4/5] finally moves to of_device and of_platform_driver by changing
      ibmebus.h and matching the eHCA and eHEA drivers
[5/5] just changes a nit in ibmebus_store_probe()

These patches should apply cleanly, in order, against 2.6.23-rc5 and against
Linus' git. Please review and comment them, and queue them up for 2.6.24 if
you think they're okay.

Thanks and regards,
  Joachim


 arch/powerpc/kernel/ibmebus.c             |  267 ++++++++-----------------=
=2D---
 arch/powerpc/kernel/of_device.c           |   80 +++++++++
 arch/powerpc/kernel/of_platform.c         |   70 +--------
 drivers/infiniband/hw/ehca/ehca_classes.h |    2 +-
 drivers/infiniband/hw/ehca/ehca_eq.c      |    6 +-
 drivers/infiniband/hw/ehca/ehca_main.c    |   32 ++--
 drivers/net/ehea/ehea.h                   |    2 +-
 drivers/net/ehea/ehea_main.c              |   72 ++++----
 include/asm-powerpc/ibmebus.h             |   38 +----
 include/asm-powerpc/of_device.h           |    4 +
 include/linux/of_device.h                 |    5 +
 11 files changed, 228 insertions(+), 350 deletions(-)

=2D-=20
Joachim Fenkes =A0-- =A0eHCA Linux Driver Developer and Hardware Tamer
IBM Deutschland Entwicklung GmbH =A0-- =A0Dept. 3627 (I/O Firmware Dev. 2)
Schoenaicher Strasse 220 =A0-- =A071032 Boeblingen =A0-- =A0Germany
eMail: fenkes@de.ibm.com

^ 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