LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] Add sysdev/pci_quirks.c file into PowerPCarchitecture with ULI chip quirk functions.
From: Kumar Gala @ 2007-08-02  4:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, paulus, Zhang Wei-r63237
In-Reply-To: <1186017799.5495.546.camel@localhost.localdomain>


On Aug 1, 2007, at 8:23 PM, Benjamin Herrenschmidt wrote:

> On Thu, 2007-08-02 at 09:17 +0800, Zhang Wei-r63237 wrote:
>> Hi, Ben,
>>
>>>
>>> Are we sure that any powerpc machine that uses that ULI chip will  
>>> need
>>> the same quirk setting ?
>>>
>>
>> We can ensure current platforms (as far as we know, MPC8544DS and
>> MPC8641HPCN) using ULI chips in powerpc of kernel need the same quirk
>> setting.
>> And we hope to make them more generic. And if there are some  
>> different
>> setting in the future, we can add special codes.
>
> All right.

My feeling is this code is pretty specific to how the ULI M1575 is  
used on those boards and should only be built for those boards.

- k

^ permalink raw reply

* Re: [ PATCH ] PowerPC cascade UIC IRQ handler fix.
From: David Gibson @ 2007-08-02  3:48 UTC (permalink / raw)
  To: Valentine Barshak; +Cc: linuxppc-dev
In-Reply-To: <20070730163517.GA10087@ru.mvista.com>

On Mon, Jul 30, 2007 at 08:35:17PM +0400, Valentine Barshak wrote:
> PPC44x cascade UIC irq handler fix.
> 
> According to PPC44x UM, if an interrupt is configured as level-sensitive,
> and a clear is attempted on the UIC_SR, the UIC_SR field is not
> cleared if the incoming interrupt signal is at the asserted polarity.
> This causes us to enter a cascade handler twice, since we first ack
> parent UIC interrupt and ack child UIC one after that.
> The patch checks child UIC msr value and returns IRQ_HANDLED
> if there're no pending interrupts. Otherwise we get a kernel panic
> with a "Fatal exception in interrupt" (illegal vector).
> The patch also fixes status flags.
> 
> Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>

Hrm... This doesn't seem like the right fix to me.  Instead, I think
the cascaded IRQ handler should ack the interrupt on the child first.
I'm a little surprised it doesn't at the moment.

> ---
> 
> --- linux.orig/arch/powerpc/sysdev/uic.c	2007-07-27 20:37:11.000000000 +0400
> +++ linux/arch/powerpc/sysdev/uic.c	2007-07-30 20:26:48.000000000 +0400
> @@ -142,7 +142,7 @@
>  
>  	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
>  	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
> -	if (trigger)
> +	if (!trigger)
>  		desc->status |= IRQ_LEVEL;
>  
>  	spin_unlock_irqrestore(&uic->lock, flags);
> @@ -207,6 +207,9 @@
>  	int subvirq;
>  
>  	msr = mfdcr(uic->dcrbase + UIC_MSR);
> +	if (!msr)
> +		return IRQ_HANDLED;
> +
>  	src = 32 - ffs(msr);
>  
>  	subvirq = irq_linear_revmap(uic->irqhost, src);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

-- 
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: [U-Boot-Users] MPC83xx - previous patch to set MBAR
From: Alfred Manheim @ 2007-08-02  2:34 UTC (permalink / raw)
  To: 'Liu Dave-r63238', 'Phillips Kim-R1AAHA',
	'Keith Mund'
  Cc: linuxppc-dev, u-boot-users
In-Reply-To: <995B09A8299C2C44B59866F6391D2635AAD0C5@zch01exm21.fsl.freescale.net>

This was to the wrong group.

Thanks for the responses and the clarification. The "needed for CodeWarrior
only" part is what I suspected.

Keith Mund

-----Original Message-----
From: linuxppc-dev-bounces+alfman=austin.rr.com@ozlabs.org
[mailto:linuxppc-dev-bounces+alfman=austin.rr.com@ozlabs.org] On Behalf Of
Liu Dave-r63238
Sent: Wednesday, August 01, 2007 9:15 PM
To: Phillips Kim-R1AAHA; Keith Mund
Cc: linuxppc-dev@ozlabs.org; u-boot-users@lists.sourceforge.net
Subject: RE: [U-Boot-Users] MPC83xx - previous patch to set MBAR

> > The end result simply adds a line to set MBAR to match IMMRBAR.
> > 
> >         lis     r3, CFG_IMMRBAR@h
> >         ori     r3, r3, CFG_IMMRBAR@l
> >         stw     r3, IMMRBAR(r4)
> > +       mtspr   MBAR, r3
> > 
> > Are these patches routinely added to the mainstream u-boot code? 
> > 
> > Is there any reason why this fix is not a good idea?
> > 
> does setting MBAR really fix anything?
> 
> MBAR doesn't live up to its name.  It's a general-purpose scratch 
> register - the hardware doesn't do anything with it.  So, wrt

Kim is right.

MBAR setting is added by two years ago, it is not really fix anything.

I set the MBAR to be easier to use the CodeWarriror. The CodeWarrior must
set the MBAR first, then it will be able to access the IMMR.

Dave
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* RE: [U-Boot-Users] MPC83xx - previous patch to set MBAR
From: Liu Dave-r63238 @ 2007-08-02  2:14 UTC (permalink / raw)
  To: Phillips Kim-R1AAHA, Keith Mund; +Cc: linuxppc-dev, u-boot-users
In-Reply-To: <20070801192009.656fc2e0.kim.phillips@freescale.com>

> > The end result simply adds a line to set MBAR to match IMMRBAR.
> >=20
> >         lis     r3, CFG_IMMRBAR@h
> >         ori     r3, r3, CFG_IMMRBAR@l
> >         stw     r3, IMMRBAR(r4)
> > +       mtspr   MBAR, r3
> >=20
> > Are these patches routinely added to the mainstream u-boot code?=20
> >=20
> > Is there any reason why this fix is not a good idea?
> >=20
> does setting MBAR really fix anything?
>=20
> MBAR doesn't live up to its name.  It's a general-purpose scratch
> register - the hardware doesn't do anything with it.  So, wrt=20

Kim is right.

MBAR setting is added by two years ago, it is not really fix anything.

I set the MBAR to be easier to use the CodeWarriror. The CodeWarrior
must set the MBAR first, then it will be able to access the IMMR.

Dave

^ permalink raw reply

* RE: [PATCH 1/2] Add sysdev/pci_quirks.c file into PowerPCarchitecture with ULI chip quirk functions.
From: Benjamin Herrenschmidt @ 2007-08-02  1:23 UTC (permalink / raw)
  To: Zhang Wei-r63237; +Cc: linuxppc-dev, paulus
In-Reply-To: <46B96294322F7D458F9648B60E15112C74D58E@zch01exm26.fsl.freescale.net>

On Thu, 2007-08-02 at 09:17 +0800, Zhang Wei-r63237 wrote:
> Hi, Ben,
>  
> > 
> > Are we sure that any powerpc machine that uses that ULI chip will need
> > the same quirk setting ?
> > 
> 
> We can ensure current platforms (as far as we know, MPC8544DS and
> MPC8641HPCN) using ULI chips in powerpc of kernel need the same quirk
> setting.
> And we hope to make them more generic. And if there are some different
> setting in the future, we can add special codes.

All right.

Ben.

^ permalink raw reply

* RE: [PATCH 1/2] Add sysdev/pci_quirks.c file into PowerPCarchitecture with ULI chip quirk functions.
From: Zhang Wei-r63237 @ 2007-08-02  1:17 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, paulus
In-Reply-To: <1186005360.5495.529.camel@localhost.localdomain>

Hi, Ben,
=20
>=20
> Are we sure that any powerpc machine that uses that ULI chip will need
> the same quirk setting ?
>=20

We can ensure current platforms (as far as we know, MPC8544DS and
MPC8641HPCN) using ULI chips in powerpc of kernel need the same quirk
setting.
And we hope to make them more generic. And if there are some different
setting in the future, we can add special codes.

Thanks!
-zw

^ permalink raw reply

* Re: [PATCH] fixes for the SLB shadow buffer
From: Benjamin Herrenschmidt @ 2007-08-02  1:04 UTC (permalink / raw)
  To: Michael Neuling; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <1186013135.5495.540.camel@localhost.localdomain>


> The first block of code detects the need for a demotion and changes the
> global mmu_vmalloc_psize, along with changing the value on the local CPU
> (and flushing it's SLB). But other CPUs still have the old values.
> 
> The second block of code checks if the global value matches the per-CPU
> value and if not, proceeds to a local SLB flush. That's how the "other"
> CPUs get the new value.
> 
> If your shadow is per-CPU, it thus needs to be updated in both cases.

Hrm.. I must have been looking at older sources or lacked caffeine, we
indeed only do the paca update and the flush&rebolt once.

Ben.

^ permalink raw reply

* Re: [PATCH 2/6] PowerPC 440EPx: Sequoia DTS
From: David Gibson @ 2007-08-02  1:00 UTC (permalink / raw)
  To: Valentine Barshak; +Cc: linuxppc-dev
In-Reply-To: <46B094F0.5010401@ru.mvista.com>

On Wed, Aug 01, 2007 at 06:13:04PM +0400, Valentine Barshak wrote:
> David Gibson wrote:
> > On Mon, Jul 30, 2007 at 07:06:48PM +0400, Valentine Barshak wrote:
[snip]
> >> +	SDR0: sdr {
> > 
> > What is the SDR?
> 
> SDR are System Device Control Registers (chip ID, pin function and stuff).
> They are accessed by using the configuration address and data (CFGADDR 
> and CFGDATA) registers.

Ok.

> >> +		compatible = "ibm,sdr-440ep";
> >> +		dcr-reg = <00e 002>;
> >> +	};
> >> +
> >> +	CPR0: cpr {
> > 
> > And the CPR?
> 
> CPR are Clock/Power-On Reset configuration registers.
> They are also accessed by using the configuration address and data 
> (CFGADDR and CFGDATA) registers.

Ok, so the rough equivalent of the 440GP's CPC registers (but with an
entirely different register layout).

[snip]
> >> +			EMAC0: ethernet@ef600e00 {
> >> +				linux,network-index = <0>;
> >> +				device_type = "network";
> >> +				compatible = "ibm,emac-440spe", "ibm,emac4", "ibm,emac-axon";
> > 
> > "ibm,emac-axon" is definitely wrong, since this isn't an Axon chip.
> 
> The chip uses EMACX_STACR_STAC_READ and EMACX_STACR_STAC_WRITE bits with 
> mdio_read/mdio_write commands. These are only enabled if the chip is 
> axon-compatible.
> ---
> 	if (device_is_compatible(np, "ibm,emac-axon"))
> 		dev->features |= EMAC_FTR_HAS_AXON_STACR
> ---

Then the driver needs fixing; I'll talk to Ben and look into it.
We'll need something in the device tree to indicate this, but it
shouldn't be "emac-axon" in compatible.

-- 
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: MPC83xx - previous patch to set MBAR
From: Kim Phillips @ 2007-08-02  0:20 UTC (permalink / raw)
  To: Keith Mund; +Cc: linuxppc-dev, u-boot-users
In-Reply-To: <5EACFDEA24DADE42BF109303D305A8093120A6@MAIL.clearcube.com>

On Wed, 1 Aug 2007 15:20:22 -0500
"Keith Mund" <keith.mund@clearcube.com> wrote:

> There was a u-boot 1.1.3 patch for start.S posted on the Freescale LTIB

posts concerning u-boot should go to the u-boot-users list (cc'd).

> site:
> http://www.bitshrine.org/gpp/u-boot-1.1.3-mpc83xx-cpu-4.patch
> 
> The end result simply adds a line to set MBAR to match IMMRBAR.
> 
>         lis     r3, CFG_IMMRBAR@h
>         ori     r3, r3, CFG_IMMRBAR@l
>         stw     r3, IMMRBAR(r4)
> +       mtspr   MBAR, r3
> 
> Are these patches routinely added to the mainstream u-boot code? 
> 
> Is there any reason why this fix is not a good idea?
> 
does setting MBAR really fix anything?

MBAR doesn't live up to its name.  It's a general-purpose scratch
register - the hardware doesn't do anything with it.  So, wrt integrity
within u-boot itself, I see no point/value in setting it.  If some
piece of software needs temporary storage, it can set it and use it as
it wishes, independent of u-boot.

Kim

^ permalink raw reply

* Re: DTC 1.0.0 Release Coming?
From: David Gibson @ 2007-08-02  0:14 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, Jon Loeliger
In-Reply-To: <200708020135.03477.arnd@arndb.de>

On Thu, Aug 02, 2007 at 01:35:03AM +0200, Arnd Bergmann wrote:
> On Wednesday 25 July 2007, Jon Loeliger wrote:
> > I'd like to make an official DTC Version 1.0.0 release soon!
> > To that end, I've published a repo on jdl.com with a v1.0.0-rc1
> > tag on it.  I anticipate some updates to the Documentation before
> > a final 1.0.0 release still.  However, if you have something
> > you would like to have be in The Real 1.0.0 release, please
> > let me know soon!
> 
> A  bug has been reported in both fedora and debian about /usr/bin/ftdump
> conflicting with a file of the same name in freetype.
> 
> Can we rename the binary in dtc to avoid this? Maybe /usr/bin/dtc-ftdump
> would be better.

Better yet, just omit it, since it's really not very useful.  That
should be happening now that my "improved make install target" patch
has been merged.

-- 
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: [PATCH] fixes for the SLB shadow buffer
From: Benjamin Herrenschmidt @ 2007-08-02  0:05 UTC (permalink / raw)
  To: Michael Neuling; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <1491.1186011132@neuling.org>

On Thu, 2007-08-02 at 09:32 +1000, Michael Neuling wrote:
> > On Wed, 2007-08-01 at 16:02 +1000, Michael Neuling wrote:
> > > We sometimes change the vmalloc segment in slb_flush_and_rebolt but we
> > > never updated with slb shadow buffer.  This fixes it.  Thanks to paulus
> > > for finding this.
> > > 
> > > Also added some write barriers to ensure the shadow buffer is always
> > > valid.
> > 
> > The shadow is global or per-cpu ?
> > 
> > Because in the later case, I think you need more than that.
> 
> It's per CPU.
> 
> > > @@ -759,6 +762,9 @@ int hash_page(unsigned long ea, unsigned
> > >  		   mmu_psize_defs[mmu_vmalloc_psize].sllp) {
> > >  		get_paca()->vmalloc_sllp =
> > >  			mmu_psize_defs[mmu_vmalloc_psize].sllp;
> > > +		vflags = SLB_VSID_KERNEL |
> > > +			mmu_psize_defs[mmu_vmalloc_psize].sllp;
> > > +		slb_shadow_update(VMALLOC_START, vflags, 1);
> > >  		slb_flush_and_rebolt();
> > >  	}
> > 
> > Later on:
> > 
> >         } else if (get_paca()->vmalloc_sllp !=
> >                    mmu_psize_defs[mmu_vmalloc_psize].sllp) {
> >                 get_paca()->vmalloc_sllp =
> >                         mmu_psize_defs[mmu_vmalloc_psize].sllp;
> >                 slb_flush_and_rebolt();
> >         }
> > 
> > If your shadow is per-cpu, you need to fix that up too.
> 
> I'm confused... isn't that the same section of code?

The first block of code detects the need for a demotion and changes the
global mmu_vmalloc_psize, along with changing the value on the local CPU
(and flushing it's SLB). But other CPUs still have the old values.

The second block of code checks if the global value matches the per-CPU
value and if not, proceeds to a local SLB flush. That's how the "other"
CPUs get the new value.

If your shadow is per-CPU, it thus needs to be updated in both cases.

Ben.


Ben.

^ permalink raw reply

* Re: DTC 1.0.0 Release Coming?
From: Arnd Bergmann @ 2007-08-01 23:35 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Jon Loeliger
In-Reply-To: <E1IDjSy-0003eC-T4@jdl.com>

On Wednesday 25 July 2007, Jon Loeliger wrote:
> I'd like to make an official DTC Version 1.0.0 release soon!
> To that end, I've published a repo on jdl.com with a v1.0.0-rc1
> tag on it. =A0I anticipate some updates to the Documentation before
> a final 1.0.0 release still. =A0However, if you have something
> you would like to have be in The Real 1.0.0 release, please
> let me know soon!

A  bug has been reported in both fedora and debian about /usr/bin/ftdump
conflicting with a file of the same name in freetype.

Can we rename the binary in dtc to avoid this? Maybe /usr/bin/dtc-ftdump
would be better.

	Arnd <><

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=3D434890
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=3D249638

^ permalink raw reply

* [PATCH] 85xxCDS: Delete the PCI exclude function.
From: Randy Vinson @ 2007-08-01 23:32 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev@ozlabs.org

>From 8367fd9e98a97ba680d23bf59fa03fcd930dd9e1 Mon Sep 17 00:00:00 2001
From: Randy Vinson <rvinson@mvista.com>
Date: Wed, 1 Aug 2007 16:24:48 -0700
Subject: [PATCH] 85xxCDS: Delete the PCI exclude function.

Now that the FPGA on the 85xxCDS main board has a quirk, we no longer
need an exclude routine.

Signed-off-by: Randy Vinson <rvinson@mvista.com>
---
 arch/powerpc/platforms/85xx/mpc85xx_cds.c |   16 ----------------
 1 files changed, 0 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 6a171e9..d7ee380 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -54,21 +54,6 @@ static volatile u8 *cadmus;
 
 #ifdef CONFIG_PCI
 
-#define ARCADIA_HOST_BRIDGE_IDSEL	17
-#define ARCADIA_2ND_BRIDGE_IDSEL	3
-
-static int mpc85xx_exclude_device(struct pci_controller *hose,
-				  u_char bus, u_char devfn)
-{
-	/* We explicitly do not go past the Tundra 320 Bridge */
-	if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	else
-		return PCIBIOS_SUCCESSFUL;
-}
-
 static void mpc85xx_cds_restart(char *cmd)
 {
 	struct pci_dev *dev;
@@ -306,7 +291,6 @@ static void __init mpc85xx_cds_setup_arch(void)
 			fsl_add_bridge(np, 0);
 	}
 	ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;
-	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 }
 
-- 
1.5.3.rc2.22.g69a9b

^ permalink raw reply related

* Re: [PATCH] fixes for the SLB shadow buffer
From: Michael Neuling @ 2007-08-01 23:32 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <1186007636.5495.536.camel@localhost.localdomain>

> On Wed, 2007-08-01 at 16:02 +1000, Michael Neuling wrote:
> > We sometimes change the vmalloc segment in slb_flush_and_rebolt but we
> > never updated with slb shadow buffer.  This fixes it.  Thanks to paulus
> > for finding this.
> > 
> > Also added some write barriers to ensure the shadow buffer is always
> > valid.
> 
> The shadow is global or per-cpu ?
> 
> Because in the later case, I think you need more than that.

It's per CPU.

> > @@ -759,6 +762,9 @@ int hash_page(unsigned long ea, unsigned
> >  		   mmu_psize_defs[mmu_vmalloc_psize].sllp) {
> >  		get_paca()->vmalloc_sllp =
> >  			mmu_psize_defs[mmu_vmalloc_psize].sllp;
> > +		vflags = SLB_VSID_KERNEL |
> > +			mmu_psize_defs[mmu_vmalloc_psize].sllp;
> > +		slb_shadow_update(VMALLOC_START, vflags, 1);
> >  		slb_flush_and_rebolt();
> >  	}
> 
> Later on:
> 
>         } else if (get_paca()->vmalloc_sllp !=
>                    mmu_psize_defs[mmu_vmalloc_psize].sllp) {
>                 get_paca()->vmalloc_sllp =
>                         mmu_psize_defs[mmu_vmalloc_psize].sllp;
>                 slb_flush_and_rebolt();
>         }
> 
> If your shadow is per-cpu, you need to fix that up too.

I'm confused... isn't that the same section of code?

> I'm tempted to think you should just expose an slb_vmalloc_update()
> from slb.c that does the shadow update and calls flush_and_rebolt.
> That would also get rid of your ifdef on vflags definition (which
> wasn't necessary in the first place if you had put it inside the
> if statement anyway).

OK, I'll create an slb_vmalloc_update for the next rev.

Mikey

^ permalink raw reply

* Re: [PATCH] fixes for the SLB shadow buffer
From: Benjamin Herrenschmidt @ 2007-08-01 22:33 UTC (permalink / raw)
  To: Michael Neuling; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <31580.1185948147@neuling.org>

On Wed, 2007-08-01 at 16:02 +1000, Michael Neuling wrote:
> We sometimes change the vmalloc segment in slb_flush_and_rebolt but we
> never updated with slb shadow buffer.  This fixes it.  Thanks to paulus
> for finding this.
> 
> Also added some write barriers to ensure the shadow buffer is always
> valid.

The shadow is global or per-cpu ?

Because in the later case, I think you need more than that.

> Index: linux-2.6-ozlabs/arch/powerpc/mm/hash_utils_64.c
> ===================================================================
> --- linux-2.6-ozlabs.orig/arch/powerpc/mm/hash_utils_64.c
> +++ linux-2.6-ozlabs/arch/powerpc/mm/hash_utils_64.c
> @@ -629,6 +629,9 @@ int hash_page(unsigned long ea, unsigned
>  	cpumask_t tmp;
>  	int rc, user_region = 0, local = 0;
>  	int psize;
> +#ifdef CONFIG_PPC_64K_PAGES
> +	unsigned long vflags;
> +#endif
>  
>  	DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
>  		ea, access, trap);
> @@ -759,6 +762,9 @@ int hash_page(unsigned long ea, unsigned
>  		   mmu_psize_defs[mmu_vmalloc_psize].sllp) {
>  		get_paca()->vmalloc_sllp =
>  			mmu_psize_defs[mmu_vmalloc_psize].sllp;
> +		vflags = SLB_VSID_KERNEL |
> +			mmu_psize_defs[mmu_vmalloc_psize].sllp;
> +		slb_shadow_update(VMALLOC_START, vflags, 1);
>  		slb_flush_and_rebolt();
>  	}

Later on:

        } else if (get_paca()->vmalloc_sllp !=
                   mmu_psize_defs[mmu_vmalloc_psize].sllp) {
                get_paca()->vmalloc_sllp =
                        mmu_psize_defs[mmu_vmalloc_psize].sllp;
                slb_flush_and_rebolt();
        }

If your shadow is per-cpu, you need to fix that up too.

I'm tempted to think you should just expose an slb_vmalloc_update()
from slb.c that does the shadow update and calls flush_and_rebolt.
That would also get rid of your ifdef on vflags definition (which
wasn't necessary in the first place if you had put it inside the
if statement anyway).

Ben.

^ permalink raw reply

* [PATCH v2 2/2] powerpc: Marvell MV64x60 EDAC driver
From: Dave Jiang @ 2007-08-01 22:32 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, bluesmoke-devel, norsk5
In-Reply-To: <20070725200812.GB28059@blade.az.mvista.com>

Marvell mv64x60 SoC support for EDAC. Used on PPC and MIPS platforms.
Development and testing done on PPC Motorola prpmc2800 ATCA board.

The driver provides error reporting for the CPU error registers, the
memory controller error registers, the SRAM error registers, and the
PCI error registers. The error reporting can be done two ways, via
interrupts, or polling.

Signed-off-by: Dave Jiang <djiang@mvista.com>
Signed-off-by: Douglas Thompson <dougthompson@xmission.com>

---

Updated error cleanup path for probe routine via comments from 85xx EDAC
driver.

 drivers/edac/Kconfig        |    6 +
 drivers/edac/Makefile       |    2 +-
 drivers/edac/mv64x60_edac.c |  855 +++++++++++++++++++++++++++++++++++++++++++
 drivers/edac/mv64x60_edac.h |  114 ++++++
 4 files changed, 976 insertions(+), 1 deletions(-)

diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 1724c41..2dff779 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -131,5 +131,11 @@ config EDAC_PASEMI
 	  Support for error detection and correction on PA Semi
 	  PWRficient.
 
+config EDAC_MV64X60
+	tristate "Marvell MV64x60"
+	depends on EDAC_MM_EDAC && MV64X60
+	help
+	  Support for error detection and correction on the Marvell
+	  MV64360 and MV64460 chipsets.
 
 endif # EDAC
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 02c09f0..3cbee8c 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -28,4 +28,4 @@ obj-$(CONFIG_EDAC_I3000)		+= i3000_edac.o
 obj-$(CONFIG_EDAC_I82860)		+= i82860_edac.o
 obj-$(CONFIG_EDAC_R82600)		+= r82600_edac.o
 obj-$(CONFIG_EDAC_PASEMI)		+= pasemi_edac.o
-
+obj-$(CONFIG_EDAC_MV64X60)		+= mv64x60_edac.o
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
index a2134df..cbc419c 100644
--- a/drivers/edac/edac_module.h
diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c
new file mode 100644
index 0000000..aa35f10
--- /dev/null
+++ b/drivers/edac/mv64x60_edac.c
@@ -0,0 +1,855 @@
+/*
+ * Marvell MV64x60 Memory Controller kernel module for PPC platforms
+ *
+ * Author: Dave Jiang <djiang@mvista.com>
+ *
+ * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+#include "mv64x60_edac.h"
+
+const char *mv64x60_ctl_name = "MV64x60";
+static int edac_dev_idx;
+static int edac_pci_idx;
+static int edac_mc_idx;
+
+/*********************** PCI err device **********************************/
+#ifdef CONFIG_PCI
+static void mv64x60_pci_check(struct edac_pci_ctl_info *pci)
+{
+	struct mv64x60_pci_pdata *pdata = pci->pvt_info;
+	u32 cause;
+
+	cause = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
+	if (!cause)
+		return;
+
+	printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose);
+	printk(KERN_ERR "Cause register: 0x%08x\n", cause);
+	printk(KERN_ERR "Address Low: 0x%08x\n",
+	       in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO));
+	printk(KERN_ERR "Address High: 0x%08x\n",
+	       in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI));
+	printk(KERN_ERR "Attribute: 0x%08x\n",
+	       in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR));
+	printk(KERN_ERR "Command: 0x%08x\n",
+	       in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD));
+	out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, ~cause);
+
+	if (cause & MV64X60_PCI_PE_MASK)
+		edac_pci_handle_pe(pci, pci->ctl_name);
+
+	if (!(cause & MV64X60_PCI_PE_MASK))
+		edac_pci_handle_npe(pci, pci->ctl_name);
+}
+
+static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id)
+{
+	struct edac_pci_ctl_info *pci = dev_id;
+	struct mv64x60_pci_pdata *pdata = pci->pvt_info;
+	u32 val;
+
+	val = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
+	if (!val)
+		return IRQ_NONE;
+
+	mv64x60_pci_check(pci);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev)
+{
+	struct edac_pci_ctl_info *pci;
+	struct mv64x60_pci_pdata *pdata;
+	struct resource *r;
+	int res = 0;
+
+	if (!devres_open_group(&pdev->dev, mv64x60_pci_err_probe, GFP_KERNEL))
+		return -ENOMEM;
+
+	pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mv64x60_pci_err");
+	if (!pci)
+		return -ENOMEM;
+
+	pdata = pci->pvt_info;
+
+	pdata->pci_hose = pdev->id;
+	pdata->name = "mpc85xx_pci_err";
+	pdata->irq = NO_IRQ;
+	platform_set_drvdata(pdev, pci);
+	pci->dev = &pdev->dev;
+	pci->dev_name = pdev->dev.bus_id;
+	pci->mod_name = EDAC_MOD_STR;
+	pci->ctl_name = pdata->name;
+
+	if (edac_op_state == EDAC_OPSTATE_POLL)
+		pci->edac_check = mv64x60_pci_check;
+
+	pdata->edac_idx = edac_pci_idx++;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		printk(KERN_ERR "%s: Unable to get resource for "
+		       "PCI err regs\n", __func__);
+		res = -ENOENT;
+		goto err;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev,
+				     r->start,
+				     r->end - r->start + 1,
+				     pdata->name)) {
+		printk(KERN_ERR "%s: Error while requesting mem region\n",
+		       __func__);
+		res = -EBUSY;
+		goto err;
+	}
+
+	pdata->pci_vbase = devm_ioremap(&pdev->dev,
+					r->start,
+					r->end - r->start + 1);
+	if (!pdata->pci_vbase) {
+		printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
+		res = -ENOMEM;
+		goto err;
+	}
+
+	out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0);
+	out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0);
+	out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK,
+		 MV64X60_PCIx_ERR_MASK_VAL);
+
+	if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
+		debugf3("%s(): failed edac_pci_add_device()\n", __func__);
+		goto err;
+	}
+
+	if (edac_op_state == EDAC_OPSTATE_INT) {
+		pdata->irq = platform_get_irq(pdev, 0);
+		res = devm_request_irq(&pdev->dev,
+				       pdata->irq,
+				       mv64x60_pci_isr,
+				       IRQF_DISABLED,
+				       "[EDAC] PCI err",
+				       pci);
+		if (res < 0) {
+			printk(KERN_ERR "%s: Unable to request irq %d for "
+			       "MV64x60 PCI ERR\n", __func__, pdata->irq);
+			res = -ENODEV;
+			goto err2;
+		}
+		printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n",
+		       pdata->irq);
+	}
+
+	devres_remove_group(&pdev->dev, mv64x60_pci_err_probe);
+
+	/* get this far and it's successful */
+	debugf3("%s(): success\n", __func__);
+
+	return 0;
+
+err2:
+	edac_pci_del_device(&pdev->dev);
+err:
+	edac_pci_free_ctl_info(pci);
+	devres_release_group(&pdev->dev, mv64x60_pci_err_probe);
+	return res;
+}
+
+static int mv64x60_pci_err_remove(struct platform_device *pdev)
+{
+	struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
+
+	debugf0("%s()\n", __func__);
+
+	edac_pci_del_device(&pdev->dev);
+
+	edac_pci_free_ctl_info(pci);
+
+	return 0;
+}
+
+static struct platform_driver mv64x60_pci_err_driver = {
+	.probe = mv64x60_pci_err_probe,
+	.remove = __devexit_p(mv64x60_pci_err_remove),
+	.driver = {
+		   .name = "mv64x60_pci_err",
+	}
+};
+
+#endif /* CONFIG_PCI */
+
+/*********************** SRAM err device **********************************/
+static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev)
+{
+	struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
+	u32 cause;
+
+	cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
+	if (!cause)
+		return;
+
+	printk(KERN_ERR "Error in internal SRAM\n");
+	printk(KERN_ERR "Cause register: 0x%08x\n", cause);
+	printk(KERN_ERR "Address Low: 0x%08x\n",
+	       in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO));
+	printk(KERN_ERR "Address High: 0x%08x\n",
+	       in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI));
+	printk(KERN_ERR "Data Low: 0x%08x\n",
+	       in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO));
+	printk(KERN_ERR "Data High: 0x%08x\n",
+	       in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI));
+	printk(KERN_ERR "Parity: 0x%08x\n",
+	       in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY));
+	out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0);
+
+	edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
+}
+
+static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id)
+{
+	struct edac_device_ctl_info *edac_dev = dev_id;
+	struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
+	u32 cause;
+
+	cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
+	if (!cause)
+		return IRQ_NONE;
+
+	mv64x60_sram_check(edac_dev);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *edac_dev;
+	struct mv64x60_sram_pdata *pdata;
+	struct resource *r;
+	int res = 0;
+
+	if (!devres_open_group(&pdev->dev, mv64x60_sram_err_probe, GFP_KERNEL))
+		return -ENOMEM;
+
+	edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
+					      "sram", 1, NULL, 0, 0, NULL, 0,
+					      edac_dev_idx);
+	if (!edac_dev) {
+		devres_release_group(&pdev->dev, mv64x60_sram_err_probe);
+		return -ENOMEM;
+	}
+
+	pdata = edac_dev->pvt_info;
+	pdata->name = "mv64x60_sram_err";
+	pdata->irq = NO_IRQ;
+	edac_dev->dev = &pdev->dev;
+	platform_set_drvdata(pdev, edac_dev);
+	edac_dev->dev_name = pdev->dev.bus_id;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		printk(KERN_ERR "%s: Unable to get resource for "
+		       "SRAM err regs\n", __func__);
+		res = -ENOENT;
+		goto err;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev,
+				     r->start,
+				     r->end - r->start + 1,
+				     pdata->name)) {
+		printk(KERN_ERR "%s: Error while request mem region\n",
+		       __func__);
+		res = -EBUSY;
+		goto err;
+	}
+
+	pdata->sram_vbase = devm_ioremap(&pdev->dev,
+					 r->start,
+					 r->end - r->start + 1);
+	if (!pdata->sram_vbase) {
+		printk(KERN_ERR "%s: Unable to setup SRAM err regs\n",
+		       __func__);
+		res = -ENOMEM;
+		goto err;
+	}
+
+	/* setup SRAM err registers */
+	out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0);
+
+	edac_dev->mod_name = EDAC_MOD_STR;
+	edac_dev->ctl_name = pdata->name;
+
+	if (edac_op_state == EDAC_OPSTATE_POLL)
+		edac_dev->edac_check = mv64x60_sram_check;
+
+	pdata->edac_idx = edac_dev_idx++;
+
+	if (edac_device_add_device(edac_dev) > 0) {
+		debugf3("%s(): failed edac_device_add_device()\n", __func__);
+		goto err;
+	}
+
+	if (edac_op_state == EDAC_OPSTATE_INT) {
+		pdata->irq = platform_get_irq(pdev, 0);
+		res = devm_request_irq(&pdev->dev,
+				       pdata->irq,
+				       mv64x60_sram_isr,
+				       IRQF_DISABLED,
+				       "[EDAC] SRAM err",
+				       edac_dev);
+		if (res < 0) {
+			printk(KERN_ERR
+			       "%s: Unable to request irq %d for "
+			       "MV64x60 SRAM ERR\n", __func__, pdata->irq);
+			res = -ENODEV;
+			goto err2;
+		}
+
+		printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for SRAM Err\n",
+		       pdata->irq);
+	}
+
+	devres_remove_group(&pdev->dev, mv64x60_sram_err_probe);
+
+	/* get this far and it's successful */
+	debugf3("%s(): success\n", __func__);
+
+	return 0;
+
+err2:
+	edac_device_del_device(&pdev->dev);
+err:
+	devres_release_group(&pdev->dev, mv64x60_sram_err_probe);
+	edac_device_free_ctl_info(edac_dev);
+	return res;
+}
+
+static int mv64x60_sram_err_remove(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev);
+
+	debugf0("%s()\n", __func__);
+
+	edac_device_del_device(&pdev->dev);
+	edac_device_free_ctl_info(edac_dev);
+
+	return 0;
+}
+
+static struct platform_driver mv64x60_sram_err_driver = {
+	.probe = mv64x60_sram_err_probe,
+	.remove = mv64x60_sram_err_remove,
+	.driver = {
+		   .name = "mv64x60_sram_err",
+	}
+};
+
+/*********************** CPU err device **********************************/
+static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev)
+{
+	struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
+	u32 cause;
+
+	cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
+	    MV64x60_CPU_CAUSE_MASK;
+	if (!cause)
+		return;
+
+	printk(KERN_ERR "Error on CPU interface\n");
+	printk(KERN_ERR "Cause register: 0x%08x\n", cause);
+	printk(KERN_ERR "Address Low: 0x%08x\n",
+	       in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO));
+	printk(KERN_ERR "Address High: 0x%08x\n",
+	       in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI));
+	printk(KERN_ERR "Data Low: 0x%08x\n",
+	       in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO));
+	printk(KERN_ERR "Data High: 0x%08x\n",
+	       in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI));
+	printk(KERN_ERR "Parity: 0x%08x\n",
+	       in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY));
+	out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0);
+
+	edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
+}
+
+static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id)
+{
+	struct edac_device_ctl_info *edac_dev = dev_id;
+	struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
+	u32 cause;
+
+	cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
+	    MV64x60_CPU_CAUSE_MASK;
+	if (!cause)
+		return IRQ_NONE;
+
+	mv64x60_cpu_check(edac_dev);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *edac_dev;
+	struct resource *r;
+	struct mv64x60_cpu_pdata *pdata;
+	int res = 0;
+
+	if (!devres_open_group(&pdev->dev, mv64x60_cpu_err_probe, GFP_KERNEL))
+		return -ENOMEM;
+
+	edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
+					      "cpu", 1, NULL, 0, 0, NULL, 0,
+					      edac_dev_idx);
+	if (!edac_dev) {
+		devres_release_group(&pdev->dev, mv64x60_cpu_err_probe);
+		return -ENOMEM;
+	}
+
+	pdata = edac_dev->pvt_info;
+	pdata->name = "mv64x60_cpu_err";
+	pdata->irq = NO_IRQ;
+	edac_dev->dev = &pdev->dev;
+	platform_set_drvdata(pdev, edac_dev);
+	edac_dev->dev_name = pdev->dev.bus_id;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		printk(KERN_ERR "%s: Unable to get resource for "
+		       "CPU err regs\n", __func__);
+		res = -ENOENT;
+		goto err;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev,
+				     r->start,
+				     r->end - r->start + 1,
+				     pdata->name)) {
+		printk(KERN_ERR "%s: Error while requesting mem region\n",
+		       __func__);
+		res = -EBUSY;
+		goto err;
+	}
+
+	pdata->cpu_vbase[0] = devm_ioremap(&pdev->dev,
+					   r->start,
+					   r->end - r->start + 1);
+	if (!pdata->cpu_vbase[0]) {
+		printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__);
+		res = -ENOMEM;
+		goto err;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r) {
+		printk(KERN_ERR "%s: Unable to get resource for "
+		       "CPU err regs\n", __func__);
+		res = -ENOENT;
+		goto err;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev,
+				     r->start,
+				     r->end - r->start + 1,
+				     pdata->name)) {
+		printk(KERN_ERR "%s: Error while requesting mem region\n",
+		       __func__);
+		res = -EBUSY;
+		goto err;
+	}
+
+	pdata->cpu_vbase[1] = devm_ioremap(&pdev->dev,
+					   r->start,
+					   r->end - r->start + 1);
+	if (!pdata->cpu_vbase[1]) {
+		printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__);
+		res = -ENOMEM;
+		goto err;
+	}
+
+	/* setup CPU err registers */
+	out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0);
+	out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0);
+	out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0x000000ff);
+
+	edac_dev->mod_name = EDAC_MOD_STR;
+	edac_dev->ctl_name = pdata->name;
+	if (edac_op_state == EDAC_OPSTATE_POLL)
+		edac_dev->edac_check = mv64x60_cpu_check;
+
+	pdata->edac_idx = edac_dev_idx++;
+
+	if (edac_device_add_device(edac_dev) > 0) {
+		debugf3("%s(): failed edac_device_add_device()\n", __func__);
+		goto err;
+	}
+
+	if (edac_op_state == EDAC_OPSTATE_INT) {
+		pdata->irq = platform_get_irq(pdev, 0);
+		res = devm_request_irq(&pdev->dev,
+				       pdata->irq,
+				       mv64x60_cpu_isr,
+				       IRQF_DISABLED,
+				       "[EDAC] CPU err",
+				       edac_dev);
+		if (res < 0) {
+			printk(KERN_ERR
+			       "%s: Unable to request irq %d for MV64x60 "
+			       "CPU ERR\n", __func__, pdata->irq);
+			res = -ENODEV;
+			goto err2;
+		}
+
+		printk(KERN_INFO EDAC_MOD_STR
+		       " acquired irq %d for CPU Err\n", pdata->irq);
+	}
+
+	devres_remove_group(&pdev->dev, mv64x60_cpu_err_probe);
+
+	/* get this far and it's successful */
+	debugf3("%s(): success\n", __func__);
+
+	return 0;
+
+err2:
+	edac_device_del_device(&pdev->dev);
+err:
+	devres_release_group(&pdev->dev, mv64x60_cpu_err_probe);
+	edac_device_free_ctl_info(edac_dev);
+	return res;
+}
+
+static int mv64x60_cpu_err_remove(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev);
+
+	debugf0("%s()\n", __func__);
+
+	edac_device_del_device(&pdev->dev);
+	edac_device_free_ctl_info(edac_dev);
+	return 0;
+}
+
+static struct platform_driver mv64x60_cpu_err_driver = {
+	.probe = mv64x60_cpu_err_probe,
+	.remove = mv64x60_cpu_err_remove,
+	.driver = {
+		   .name = "mv64x60_cpu_err",
+	}
+};
+
+/*********************** DRAM err device **********************************/
+
+static void mv64x60_mc_check(struct mem_ctl_info *mci)
+{
+	struct mv64x60_mc_pdata *pdata = mci->pvt_info;
+	u32 reg;
+	u32 err_addr;
+	u32 sdram_ecc;
+	u32 comp_ecc;
+	u32 syndrome;
+
+	reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
+	if (!reg)
+		return;
+
+	err_addr = reg & ~0x3;
+	sdram_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD);
+	comp_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC);
+	syndrome = sdram_ecc ^ comp_ecc;
+
+	/* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */
+	if (!(reg & 0x1))
+		edac_mc_handle_ce(mci, err_addr >> PAGE_SHIFT,
+				  err_addr & PAGE_MASK, syndrome, 0, 0,
+				  mci->ctl_name);
+	else	/* 2 bit error, UE */
+		edac_mc_handle_ue(mci, err_addr >> PAGE_SHIFT,
+				  err_addr & PAGE_MASK, 0, mci->ctl_name);
+
+	/* clear the error */
+	out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
+}
+
+static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id)
+{
+	struct mem_ctl_info *mci = dev_id;
+	struct mv64x60_mc_pdata *pdata = mci->pvt_info;
+	u32 reg;
+
+	reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
+	if (!reg)
+		return IRQ_NONE;
+
+	/* writing 0's to the ECC err addr in check function clears irq */
+	mv64x60_mc_check(mci);
+
+	return IRQ_HANDLED;
+}
+
+static void get_total_mem(struct mv64x60_mc_pdata *pdata)
+{
+	struct device_node *np = NULL;
+	const unsigned int *reg;
+
+	np = of_find_node_by_type(NULL, "memory");
+	if (!np)
+		return;
+
+	reg = get_property(np, "reg", NULL);
+
+	pdata->total_mem = reg[1];
+}
+
+static void mv64x60_init_csrows(struct mem_ctl_info *mci,
+				struct mv64x60_mc_pdata *pdata)
+{
+	struct csrow_info *csrow;
+	u32 devtype;
+	u32 ctl;
+
+	get_total_mem(pdata);
+
+	ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
+
+	csrow = &mci->csrows[0];
+	csrow->first_page = 0;
+	csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT;
+	csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+	csrow->grain = 8;
+
+	csrow->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR;
+
+	devtype = (ctl >> 20) & 0x3;
+	switch (devtype) {
+	case 0x0:
+		csrow->dtype = DEV_X32;
+		break;
+	case 0x2:		/* could be X8 too, but no way to tell */
+		csrow->dtype = DEV_X16;
+		break;
+	case 0x3:
+		csrow->dtype = DEV_X4;
+		break;
+	default:
+		csrow->dtype = DEV_UNKNOWN;
+		break;
+	}
+
+	csrow->edac_mode = EDAC_SECDED;
+}
+
+static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev)
+{
+	struct mem_ctl_info *mci;
+	struct mv64x60_mc_pdata *pdata;
+	struct resource *r;
+	u32 ctl;
+	int res = 0;
+
+	if (!devres_open_group(&pdev->dev, mv64x60_mc_err_probe, GFP_KERNEL))
+		return -ENOMEM;
+
+	mci = edac_mc_alloc(sizeof(struct mv64x60_mc_pdata), 1, 1, edac_mc_idx);
+	if (!mci) {
+		printk(KERN_ERR "%s: No memory for CPU err\n", __func__);
+		devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
+		return -ENOMEM;
+	}
+
+	pdata = mci->pvt_info;
+	mci->dev = &pdev->dev;
+	platform_set_drvdata(pdev, mci);
+	pdata->name = "mv64x60_mc_err";
+	pdata->irq = NO_IRQ;
+	mci->dev_name = pdev->dev.bus_id;
+	pdata->edac_idx = edac_mc_idx++;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		printk(KERN_ERR "%s: Unable to get resource for "
+		       "MC err regs\n", __func__);
+		res = -ENOENT;
+		goto err;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev,
+				     r->start,
+				     r->end - r->start + 1,
+				     pdata->name)) {
+		printk(KERN_ERR "%s: Error while requesting mem region\n",
+		       __func__);
+		res = -EBUSY;
+		goto err;
+	}
+
+	pdata->mc_vbase = devm_ioremap(&pdev->dev,
+				       r->start,
+				       r->end - r->start + 1);
+	if (!pdata->mc_vbase) {
+		printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__);
+		res = -ENOMEM;
+		goto err;
+	}
+
+	ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
+	if (!(ctl & MV64X60_SDRAM_ECC)) {
+		/* Non-ECC RAM? */
+		printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__);
+		res = -ENODEV;
+		goto err2;
+	}
+
+	debugf3("%s(): init mci\n", __func__);
+	mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
+	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+	mci->edac_cap = EDAC_FLAG_SECDED;
+	mci->mod_name = EDAC_MOD_STR;
+	mci->mod_ver = MV64x60_REVISION;
+	mci->ctl_name = mv64x60_ctl_name;
+
+	if (edac_op_state == EDAC_OPSTATE_POLL)
+		mci->edac_check = mv64x60_mc_check;
+
+	mci->ctl_page_to_phys = NULL;
+
+	mci->scrub_mode = SCRUB_SW_SRC;
+
+	mv64x60_init_csrows(mci, pdata);
+
+	/* setup MC registers */
+	out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
+	ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
+	ctl = (ctl & 0xff00ffff) | 0x10000;
+	out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl);
+
+	if (edac_mc_add_mc(mci)) {
+		debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
+		goto err;
+	}
+
+	if (edac_op_state == EDAC_OPSTATE_INT) {
+		/* acquire interrupt that reports errors */
+		pdata->irq = platform_get_irq(pdev, 0);
+		res = devm_request_irq(&pdev->dev,
+				       pdata->irq,
+				       mv64x60_mc_isr,
+				       IRQF_DISABLED,
+				       "[EDAC] MC err",
+				       mci);
+		if (res < 0) {
+			printk(KERN_ERR "%s: Unable to request irq %d for "
+			       "MV64x60 DRAM ERR\n", __func__, pdata->irq);
+			res = -ENODEV;
+			goto err2;
+		}
+
+		printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC Err\n",
+		       pdata->irq);
+	}
+
+	/* get this far and it's successful */
+	debugf3("%s(): success\n", __func__);
+
+	return 0;
+
+err2:
+	edac_mc_del_mc(&pdev->dev);
+err:
+	devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
+	edac_mc_free(mci);
+	return res;
+}
+
+static int mv64x60_mc_err_remove(struct platform_device *pdev)
+{
+	struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+
+	debugf0("%s()\n", __func__);
+
+	edac_mc_del_mc(&pdev->dev);
+	edac_mc_free(mci);
+	return 0;
+}
+
+static struct platform_driver mv64x60_mc_err_driver = {
+	.probe = mv64x60_mc_err_probe,
+	.remove = mv64x60_mc_err_remove,
+	.driver = {
+		   .name = "mv64x60_mc_err",
+	}
+};
+
+static int __init mv64x60_edac_init(void)
+{
+	int ret = 0;
+
+	printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n");
+	printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n");
+	/* make sure error reporting method is sane */
+	switch (edac_op_state) {
+	case EDAC_OPSTATE_POLL:
+	case EDAC_OPSTATE_INT:
+		break;
+	default:
+		edac_op_state = EDAC_OPSTATE_INT;
+		break;
+	}
+
+	ret = platform_driver_register(&mv64x60_mc_err_driver);
+	if (ret)
+		printk(KERN_WARNING EDAC_MOD_STR "MC err failed to register\n");
+
+	ret = platform_driver_register(&mv64x60_cpu_err_driver);
+	if (ret)
+		printk(KERN_WARNING EDAC_MOD_STR
+			"CPU err failed to register\n");
+
+	ret = platform_driver_register(&mv64x60_sram_err_driver);
+	if (ret)
+		printk(KERN_WARNING EDAC_MOD_STR
+			"SRAM err failed to register\n");
+
+#ifdef CONFIG_PCI
+	ret = platform_driver_register(&mv64x60_pci_err_driver);
+	if (ret)
+		printk(KERN_WARNING EDAC_MOD_STR
+			"PCI err failed to register\n");
+#endif
+
+	return ret;
+}
+module_init(mv64x60_edac_init);
+
+static void __exit mv64x60_edac_exit(void)
+{
+#ifdef CONFIG_PCI
+	platform_driver_unregister(&mv64x60_pci_err_driver);
+#endif
+	platform_driver_unregister(&mv64x60_sram_err_driver);
+	platform_driver_unregister(&mv64x60_cpu_err_driver);
+	platform_driver_unregister(&mv64x60_mc_err_driver);
+}
+module_exit(mv64x60_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Montavista Software, Inc.");
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state,
+		 "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
diff --git a/drivers/edac/mv64x60_edac.h b/drivers/edac/mv64x60_edac.h
new file mode 100644
index 0000000..e042e2d
--- /dev/null
+++ b/drivers/edac/mv64x60_edac.h
@@ -0,0 +1,114 @@
+/*
+ * EDAC defs for Marvell MV64x60 bridge chip
+ *
+ * Author: Dave Jiang <djiang@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ */
+#ifndef _MV64X60_EDAC_H_
+#define _MV64X60_EDAC_H_
+
+#define MV64x60_REVISION " Ver: 2.0.0 " __DATE__
+#define EDAC_MOD_STR	"MV64x60_edac"
+
+#define mv64x60_printk(level, fmt, arg...) \
+	edac_printk(level, "MV64x60", fmt, ##arg)
+
+#define mv64x60_mc_printk(mci, level, fmt, arg...) \
+	edac_mc_chipset_printk(mci, level, "MV64x60", fmt, ##arg)
+
+/* CPU Error Report Registers */
+#define MV64x60_CPU_ERR_ADDR_LO		0x00	/* 0x0070 */
+#define MV64x60_CPU_ERR_ADDR_HI		0x08	/* 0x0078 */
+#define MV64x60_CPU_ERR_DATA_LO		0x00	/* 0x0128 */
+#define MV64x60_CPU_ERR_DATA_HI		0x08	/* 0x0130 */
+#define MV64x60_CPU_ERR_PARITY		0x10	/* 0x0138 */
+#define MV64x60_CPU_ERR_CAUSE		0x18	/* 0x0140 */
+#define MV64x60_CPU_ERR_MASK		0x20	/* 0x0148 */
+
+#define MV64x60_CPU_CAUSE_MASK		0x07ffffff
+
+/* SRAM Error Report Registers */
+#define MV64X60_SRAM_ERR_CAUSE		0x08	/* 0x0388 */
+#define MV64X60_SRAM_ERR_ADDR_LO	0x10	/* 0x0390 */
+#define MV64X60_SRAM_ERR_ADDR_HI	0x78	/* 0x03f8 */
+#define MV64X60_SRAM_ERR_DATA_LO	0x18	/* 0x0398 */
+#define MV64X60_SRAM_ERR_DATA_HI	0x20	/* 0x03a0 */
+#define MV64X60_SRAM_ERR_PARITY		0x28	/* 0x03a8 */
+
+/* SDRAM Controller Registers */
+#define MV64X60_SDRAM_CONFIG		0x00	/* 0x1400 */
+#define MV64X60_SDRAM_ERR_DATA_HI	0x40	/* 0x1440 */
+#define MV64X60_SDRAM_ERR_DATA_LO	0x44	/* 0x1444 */
+#define MV64X60_SDRAM_ERR_ECC_RCVD	0x48	/* 0x1448 */
+#define MV64X60_SDRAM_ERR_ECC_CALC	0x4c	/* 0x144c */
+#define MV64X60_SDRAM_ERR_ADDR		0x50	/* 0x1450 */
+#define MV64X60_SDRAM_ERR_ECC_CNTL	0x54	/* 0x1454 */
+#define MV64X60_SDRAM_ERR_ECC_ERR_CNT	0x58	/* 0x1458 */
+
+#define MV64X60_SDRAM_REGISTERED	0x20000
+#define MV64X60_SDRAM_ECC		0x40000
+
+#ifdef CONFIG_PCI
+/*
+ * Bit 0 of MV64x60_PCIx_ERR_MASK does not exist on the 64360 and because of
+ * errata FEr-#11 and FEr-##16 for the 64460, it should be 0 on that chip as
+ * well.  IOW, don't set bit 0.
+ */
+#define MV64X60_PCIx_ERR_MASK_VAL	0x00a50c24
+
+/* Register offsets from PCIx error address low register */
+#define MV64X60_PCI_ERROR_ADDR_LO	0x00
+#define MV64X60_PCI_ERROR_ADDR_HI	0x04
+#define MV64X60_PCI_ERROR_ATTR		0x08
+#define MV64X60_PCI_ERROR_CMD		0x10
+#define MV64X60_PCI_ERROR_CAUSE		0x18
+#define MV64X60_PCI_ERROR_MASK		0x1c
+
+#define MV64X60_PCI_ERR_SWrPerr		0x0002
+#define MV64X60_PCI_ERR_SRdPerr		0x0004
+#define	MV64X60_PCI_ERR_MWrPerr		0x0020
+#define MV64X60_PCI_ERR_MRdPerr		0x0040
+
+#define MV64X60_PCI_PE_MASK	(MV64X60_PCI_ERR_SWrPerr | \
+				MV64X60_PCI_ERR_SRdPerr | \
+				MV64X60_PCI_ERR_MWrPerr | \
+				MV64X60_PCI_ERR_MRdPerr)
+
+struct mv64x60_pci_pdata {
+	int pci_hose;
+	void __iomem *pci_vbase;
+	char *name;
+	int irq;
+	int edac_idx;
+};
+
+#endif				/* CONFIG_PCI */
+
+struct mv64x60_mc_pdata {
+	void __iomem *mc_vbase;
+	int total_mem;
+	char *name;
+	int irq;
+	int edac_idx;
+};
+
+struct mv64x60_cpu_pdata {
+	void __iomem *cpu_vbase[2];
+	char *name;
+	int irq;
+	int edac_idx;
+};
+
+struct mv64x60_sram_pdata {
+	void __iomem *sram_vbase;
+	char *name;
+	int irq;
+	int edac_idx;
+};
+
+#endif

^ permalink raw reply related

* Re: [PATCH 1/2] Add sysdev/pci_quirks.c file into PowerPC architecture with ULI chip quirk functions.
From: Benjamin Herrenschmidt @ 2007-08-01 21:56 UTC (permalink / raw)
  To: Zhang Wei; +Cc: linuxppc-dev, paulus
In-Reply-To: <11859560694083-git-send-email-wei.zhang@freescale.com>

On Wed, 2007-08-01 at 16:14 +0800, Zhang Wei wrote:
> Add sysdev/pci_quirks.c file into PowerPC architecture with
> ULI chip quirk functions.
> We add generic quirk functions for ULI chips
> from individual platform into arch/powerpc/sysdev/pci_quirks.c file.
> 

Are we sure that any powerpc machine that uses that ULI chip will need
the same quirk setting ?

Ben.

^ permalink raw reply

* Re: [PATCH] fixes for the SLB shadow buffer
From: Will Schmidt @ 2007-08-01 21:48 UTC (permalink / raw)
  To: Michael Neuling; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <31580.1185948147@neuling.org>

On Wed, 2007-08-01 at 16:02 +1000, Michael Neuling wrote:
> --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/entry_64.S
> +++ linux-2.6-ozlabs/arch/powerpc/kernel/entry_64.S
> @@ -389,7 +389,9 @@ BEGIN_FTR_SECTION
>  	ld	r9,PACA_SLBSHADOWPTR(r13)
>  	li	r12,0
>  	std	r12,SLBSHADOW_STACKESID(r9) /* Clear ESID */
> +	eieio
>  	std	r7,SLBSHADOW_STACKVSID(r9)  /* Save VSID */
> +	eieio
>  	std	r0,SLBSHADOW_STACKESID(r9)  /* Save ESID */
> 
Hi Michael, 

I was going to ask if we really needed both of them, but think I
convinced myself that we do.
 
Do we also want/need an eieio after the /* Save ESID */ statement, or is
that somehow handled by the slbie following?

-Will 

^ permalink raw reply

* Re: ipv6 in yaboot
From: Doug Maxey @ 2007-08-01 21:01 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Linux PowerPC List, Paul Mackerras, Paul Nasrat, yaboot-devel
In-Reply-To: <5682bc7e60187e64d80fd99b4ad573df@kernel.crashing.org>


On Wed, 01 Aug 2007 07:12:15 +0200, Segher Boessenkool wrote:
>>>> I just got asked about ipv6 support in yaboot and a quick
>>>> investigation
>>>> showed _no_ knowledge of the address formats in the code.
>>>>
>>>> Should I be submitting an RFC for a full parser that can pick that
>>>> apart?  Or does has someone have code lurking in the shadows, that
>>>> just needed some prompting?  :)
>>>
>>> I would have thought that yaboot would just be passing any network
>>> addresses in text form to some OF method, so it's up to OF to
>>> understand ipv6 address formats.  No?
>>
>> Yes, yaboot _should_ just pass the text representation around.
>> However, there are places that the context determination, for
>> disklabels, is a simple check for the presence of ':'.
>
>The network address is passed to OF as (part of) the device
>argument for the network device; and colons aren't legal
>characters in a device argument,

yeah, pretty thoughtless of the IETF for not consulting the 1275WG. :)

> so any OF implementation that
>would use colons in IPv6 addresses is terminally broken.

Ok.  What is your proposed resolution that does not violate the rfcs?
Namely RFCs 3986, 4038, and especially 4291.

>This
>is completely analogous to the fact that filesystem paths cannot
>use forward slashes.  (The third disallowed character is the
>at-sign, for completeness).

Not really.  I don't expect to the the "device path" contain any ipv6
info.  Just the parameters that follow on the end, e.g., not a real
example, just an extrapolation from current usage using the existing
addresses from a client and a server:

> boot network1:ipv6,fe80::202:55ff:fed3:9e20/64,KERNEL-NAME,fe80::21a:64ff:fe44:1713/64,GWADDR,...

The above addrs after the first colon is the part that yaboot would
have to deal with, if only to treat it as opaque token.

There is no ppc64 OFW that supports this yet, but a version is
expected soon.

BTW, I don't really have any real input into how the OFW is designed,
just try to adapt to what is implemented.

++doug

^ permalink raw reply

* Re: [PATCH] powerpc: Add of_register_i2c_devices()
From: Scott Wood @ 2007-08-01 20:42 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <Pine.LNX.4.60.0708012053240.7394@poirot.grange>

Guennadi Liakhovetski wrote:
> And the only safe way is 
> 
> 	strncpy(z.c, c, 3);
> 	z.c[3] = '\0';
> 
> with compilers < 4.2?...

You could use strlcpy() instead, which always leaves a zero terminator.

-Scott

^ permalink raw reply

* Re: [PATCH] powerpc: Add of_register_i2c_devices()
From: Guennadi Liakhovetski @ 2007-08-01 20:36 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <19a13f8700d078abc4cab0064a7d0183@kernel.crashing.org>

On Wed, 1 Aug 2007, Segher Boessenkool wrote:

> > > > > > +		strncpy(info->driver_name, i2c_devices[i].i2c_driver,
> > > > > > KOBJ_NAME_LEN);
> > > > > > +		strncpy(info->type, i2c_devices[i].i2c_type,
> > > > > > I2C_NAME_SIZE);
> > > > > 
> > > > > Why not just strcpy(), btw?
> > > > 
> > > > Because target strings are finite length, and sources are just pointers
> > > > to
> > > > some constant strings, which one might make arbitrarily long.
> > > 
> > > So it's no problem if the name or type string gets cut short?
> > > Just checking :-)
> > 
> > Then it just won't match.
> 
> strncpy() won't put a terminating zero on there, is everything
> that uses the resulting string okay with that?

Ok, this might be a problem, I guess. E.g., in 
drivers/i2c/i2c-core.c::i2c_device_uevent():

	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
			"MODALIAS=%s", client->driver_name))

and in a couple more places.

> Also, if the
> name gets cut short, it might match some _other_ expected name.

Don't think this could happen. At least the generic strcmp compares the 
'\0' too.

Now, the bad news (for me at least, as well as for some on #mklinux). To 
fix the bug I wrote the patch below. Yes, it is lacking a "Signed-..." - 
on purpose. Here's why. Having written it, I verified, that

	c[4] = "01234";

causes a nice compiler warning like:

warning: initializer-string for array of chars is too long

Then I asked myself what happens if you do

	c[4] = "0123";

? To my surprise, there was no warning. So, for example, declaring a 
struct like

struct t {
	char c[4];
	int i;
} z;

and doing

	strcpy(z.c, c);

silently corrupts z.i. Verified with gcc 3.3.x, 3.4.5, 4.1.2. 4.2 Does 
emit a warning... Now, am I right that there are lots of places in 
the kernel where we just initialize arrays of chars like above and then 
use ctrcpy to copy it to another equally-long string? Which means, if the 
initialization string is exactly the array length - without the '\0' - we 
get random memory corruption... And the only safe way is 

	strncpy(z.c, c, 3);
	z.c[3] = '\0';

with compilers < 4.2?...

Thanks
Guennadi
---

Fix a bug introduced by my earlier patch, whereby strncpy of too long a 
line could leave the result unterminated. Instead, just use fixed-size 
arrays and let the compiler verify the length for us. No need to try to 
save a few bytes of __initdata anyway. Thanks to Segher Boessenkool for 
pointing out.

diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 727453d..1e567d5 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -309,8 +309,8 @@ arch_initcall(gfar_of_init);
 #include <linux/i2c.h>
 struct i2c_driver_device {
 	char	*of_device;
-	char	*i2c_driver;
-	char	*i2c_type;
+	char	i2c_driver[KOBJ_NAME_LEN];
+	char	i2c_type[I2C_NAME_SIZE];
 };
 
 static struct i2c_driver_device i2c_devices[] __initdata = {
@@ -327,8 +327,8 @@ static int __init of_find_i2c_driver(struct device_node *node, struct i2c_board_
 	for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
 		if (!of_device_is_compatible(node, i2c_devices[i].of_device))
 			continue;
-		strncpy(info->driver_name, i2c_devices[i].i2c_driver, KOBJ_NAME_LEN);
-		strncpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE);
+		strcpy(info->driver_name, i2c_devices[i].i2c_driver);
+		strcpy(info->type, i2c_devices[i].i2c_type);
 		return 0;
 	}
 	return -ENODEV;

^ permalink raw reply related

* Re: EDAC stats & PCI error recovery (was Re: [PATCH 2/2] powerpc: MPC85xx EDAC device driver)
From: Doug Thompson @ 2007-08-01 20:34 UTC (permalink / raw)
  To: Linas Vepstas
  Cc: amitkale, linux-scsi, Arnd Bergmann, halr, openib-general,
	munsone, linuxppc-dev, mpt_linux_developer, norsk5, Eric.Moore,
	bluesmoke-devel
In-Reply-To: <20070801194857.GL4884@austin.ibm.com>


--- Linas Vepstas <linas@austin.ibm.com> wrote:

> On Mon, Jul 30, 2007 at 03:47:05PM -0700, Doug Thompson wrote:
> > 
> > --- Linas Vepstas <linas@austin.ibm.com> wrote:
> > > Also: please note that the linux kernel has a pci error recovery
> > > mechanism built in; its used by pseries and PCI-E. I'm not clear
> > > on what any of this has to do with EDAC, which I thought was supposed 
> > > to be for RAM only. (The EDAC project once talked about doing pci error 
> > > recovery, but that was years ago, and there is a separate system for
> > > that, now.)
> > 
> > no, edac can/does harvest PCI bus errors, via polling and other hardware error detectors.
> 
> Ehh! I had no idea. A few years ago, when I was working on the PCI error
> recovery, I sent a number of emails to the various EDAC people and mailing 
> lists that I could find, and never got a response.  I assumed the
> project was dead. I guess its not ... 

No its not, just some company lay offs stirred the pot, at least for me, for awhile.
I did see the ibm patches go by, but didn't have the time to check up at that time. I actually,
didn't know the recovery interface had gotten into the kernel (My failure to watch for them), so I
was pleasantly surprised at this last OLS to attend the presentation.

> 
> > But at the current time, few PCI device drivers initialize those callback functions and
> > thus errors are lost and some IO transactions fail.
> 
> There are patches for 6 drivers in mainline (e100, e1000, ixgb, s2io,
> ipr, lpfc), and two more pending (sym53cxxx, tg3).  So far, I've written 
> all of them. 

Great.
EDAC does nothing for recovery, just logging and stats gathering and presentation.

> 
> > Over time, as drivers get updated (might take some time) then drivers
> > can take some sort of action FOR THEMSELVES
> 
> I think I need to do more to raise awareness and interest.

good point

> 
> > Yet, there is no tracking of errors - except for a log message in the log file.
> > 
> > There is NO meter on frequency of errors, etc. One must grep the log file and that is not a
> very
> > cycle friendly mechanism.
> 
> Yeah, there was low interest in stats. There's a core set of stats in
> /proc/pp64/eeh, but these are clearly arch-specific. I'd ike to move
> away from those.  Some recent patches added stats to the /sys tree,
> under the individual pci bridge and device nodes.  Again, these are
> arch-specific; I'd like to move to some geeral/standardized presentation.

the memory error consumers really like the stats of EDAC. Allows them to track trends.
Cluster types, with thousands of nodes, like the monitoring for both memory and PCI, as well as
some newer hardware detector harvesting.

> 
> > The reason I added PCI parity/error device scanning, was that when I was at Linux Networx, we
> had
> > parity errors on the PCI-X bus, but didn't know the cause.  After we discovered that a simple
> > PCI-X riser card had manufacturing problems (quality) and didn't drive lines properly, it
> caused
> > parity errors. 
> 
> Heh. Not unusual. I've seen/heard of cases with voltages being low,
> and/or ground-bounce in slots near the end. There's a whole zoo of
> hardware/firmware bugs that we've had to painfully crawl through and
> fix. That's why the IBM boxes cost big $$$; here's to hoping that 
> customers understand why.

I understand


> 
> > This feature allowed us to track nodes that were having parity problems, but we had
> > no METER to know it.
> > 
> > Recovery is a good thing, BUT how do you know you having LOTS of errors/recovery events? You
> need
> > a meter. EDAC provides that METER
> 
> I'm lazy. What source code should I be looking at?  I'm concerned about
> duplication of function and proliferation of interfaces. I've got my 
> metering data under (for example)
> /sys/bus/pci/devices/0001:c0:01.0/eeh_*, mostly very arch specific.
> The code for this is in arch/powerpc/platforms/pseries/eeh_sysfs.c

http://bluesmoke.sourceforge.net/

is the SF project zone (bluesmoke was the out-of-tree name, changed to EDAC when it came into
tree, and source forge doesn't allow renaming)

EDAC info is under:

/sys/devices/system/edac/....

mc for memory controllers
pci for pci info.

very basic, just counters and some controls


> 
> > I met with Yanmin Zhang of Intel at OLS after his paper presentation on PCI Express Advanced
> Error
> > Reporting in the Kernel, and we talked about this same thing. I am talking with him on having
> the
> > recovery code present information into EDAC sysfs area. (hopefully, anyway)
> 
> Hmm. OK, where's that?  Back when, I'd talked to Yamin about coming up 
> with a generic, arch-indep way of driving the recovery routines. But
> this wasn't exactly easy, and we were still grappling with just getting
> things working.  Now that things are working, its time to broaden
> horizons.

Not very far, but I see the potential.
When EDAC was received, it was placed where it was in the sysfs from various kernel developers as
a good spot on its own.

> 
> Can you point me to the current edac code?
> find . -print |grep edac is not particuarly revealing at the moment.

drivers/edac

latest is in 2.6.23-rc1.   

-rc2 will have a few vital bug fixes. This release is fairly large since 2.6.26 when it first was
in the tree.

> 
> > The recovery generates log messages BUT having to periodically 'grep' the log file looking for
> > errors is not a good use of CPU cycles. grep once for a count and then grep later for a count
> and
> > then compare the counts for a delta count per unit time. ugly.
> 
> Yep. Maybe send events up to udev?

That is a possibility, yet EDAC consumers like the stats being available as well.

> 
> > The EDAC solution is to be able to have a Listener thread in user space that can be notified
> (via
> > poll()) that an event has occurred.
> 
> Hmm. OK, I'm alarmingly nave about udev, but my initial gut instinct is
> to pipe all such events to udev. Most of user-space has already been
> given the marching orders to use udev and/or hal for this kind of stuff.
> So this makes sense to me.

I need a learning process as well on udev.
It being the unified highway of event notification from kernel to user space. Although, when
memory errors fires, sometimes they can generate MASSIVE Number of events on every memory access.
PCI being different might have different constraints. Each needs investigation and classification
of timing, etc.

> 
> > There are more than one consumer (error recover) of error events:
> > 1) driver recovery after a transaction (which is the recovery consumer above)
> 
> I had to argue loudly for recovery in the kernel. The problem was that
> it was impossible to recover erros on scsi devics from userspace (since
> the block device and filesystems would go bonkers).

I hear you. It took the cluster consumers to demand ROBUST "meters" to for their machines to give
'validation' (so to speak) of their calculations. Bluesmoke/EDAC became that in our sandbox.

> 
> > 2) Management agents for health of a node
> > 3) Maintainance agents for predictive component replacement
> 
> Yes, agreed. Care to ask your management agent friends for where they'd
> like to get these events from (i.e. udev, or somewhere else?)

They are in a learning curve as well.
Error event processing is still so "young" under linux. Getting people aware of it is the current
push.

> 
> > We have MEMORY (edac_mc) devices for chipsets now, but via the new edac_device class, such
> things
> > as ECC error tracking on DMA error checkers, FABRIC switchs, L1 and L2 cache ECC events, core
> CPU
> > data ECC checkers, etc can be done. I have an out of kernel tree MIPS driver do just this.
> Other
> > types of harvesters can be generated as well for other and/or new hardware error detectors.
> 
> Ohh. I've got hardware tha does this, but its not currently usng EDAC.
> There must be some edac mailing list I'm not subscribed to??

the new edac_device class  rolled out in 2.6.23-rc1
No in tree drivers, but I have a test_device_edac module that uses it and it is in the svn repos.

I need to update the edac tarball to contain this stuff.

for mailing list, goto 

http://bluesmoke.sourceforge.net/

find the subscribe to mailing list action item. Fairly low bandwidth, but has notices, and some
discussion on things now and then.

bluesmoke-devel@lists.sourceforge.net is the development email


doug t

> 
> --linas
> 
> 

^ permalink raw reply

* MPC83xx - previous patch to set MBAR
From: Keith Mund @ 2007-08-01 20:20 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <fa686aa40708010653v7e1fb909gb03eb1d4754359bf@mail.gmail.com>

There was a u-boot 1.1.3 patch for start.S posted on the Freescale LTIB
site:
http://www.bitshrine.org/gpp/u-boot-1.1.3-mpc83xx-cpu-4.patch

The end result simply adds a line to set MBAR to match IMMRBAR.

        lis     r3, CFG_IMMRBAR@h
        ori     r3, r3, CFG_IMMRBAR@l
        stw     r3, IMMRBAR(r4)
+       mtspr   MBAR, r3

Are these patches routinely added to the mainstream u-boot code?=20

Is there any reason why this fix is not a good idea?

^ permalink raw reply

* [PATCH 1/1] ibmveth: Fix rx pool deactivate oops
From: Brian King @ 2007-08-01 20:26 UTC (permalink / raw)
  To: santil; +Cc: linuxppc-dev, rcjenn, brking, netdev


This fixes the following oops which can occur when trying to deallocate
receive buffer pools using sysfs with the ibmveth driver.

NIP: d00000000024f954 LR: d00000000024fa58 CTR: c0000000000d7478
REGS: c00000000ffef9f0 TRAP: 0300   Not tainted  (2.6.22-ppc64)
MSR: 8000000000009032 <EE,ME,IR,DR>  CR: 24242442  XER: 00000010
DAR: 00000000000007f0, DSISR: 0000000042000000
TASK = c000000002f91360[2967] 'bash' THREAD: c00000001398c000 CPU: 2
GPR00: 0000000000000000 c00000000ffefc70 d000000000262d30 c00000001c4087a0 
GPR04: 00000003000000fe 0000000000000000 000000000000000f c000000000579d80 
GPR08: 0000000000365688 c00000001c408998 00000000000007f0 0000000000000000 
GPR12: d000000000251e88 c000000000579d80 00000000200957ec 0000000000000000 
GPR16: 00000000100b8808 00000000100feb30 0000000000000000 0000000010084828 
GPR20: 0000000000000000 000000001014d4d0 0000000000000010 c00000000ffefeb0 
GPR24: c00000001c408000 0000000000000000 c00000001c408000 00000000ffffb054 
GPR28: 00000000000000fe 0000000000000003 d000000000262700 c00000001c4087a0 
NIP [d00000000024f954] .ibmveth_remove_buffer_from_pool+0x38/0x108 [ibmveth]
LR [d00000000024fa58] .ibmveth_rxq_harvest_buffer+0x34/0x78 [ibmveth]
Call Trace:
[c00000000ffefc70] [c0000000000280a8] .dma_iommu_unmap_single+0x14/0x28 (unreliable)
[c00000000ffefd00] [d00000000024fa58] .ibmveth_rxq_harvest_buffer+0x34/0x78 [ibmveth]
[c00000000ffefd80] [d000000000250e40] .ibmveth_poll+0xd8/0x434 [ibmveth]
[c00000000ffefe40] [c00000000032da8c] .net_rx_action+0xdc/0x248
[c00000000ffefef0] [c000000000068b4c] .__do_softirq+0xa8/0x164
[c00000000ffeff90] [c00000000002789c] .call_do_softirq+0x14/0x24
[c00000001398f6f0] [c00000000000c04c] .do_softirq+0x68/0xac
[c00000001398f780] [c000000000068ca0] .irq_exit+0x54/0x6c
[c00000001398f800] [c00000000000c8e4] .do_IRQ+0x170/0x1ac
[c00000001398f890] [c000000000004790] hardware_interrupt_entry+0x18/0x1c
   Exception: 501 at .plpar_hcall_norets+0x24/0x94
    LR = .veth_pool_store+0x15c/0x298 [ibmveth]
[c00000001398fb80] [d000000000250b2c] .veth_pool_store+0x5c/0x298 [ibmveth] (unreliable)
[c00000001398fc30] [c000000000145530] .sysfs_write_file+0x140/0x1d8
[c00000001398fcf0] [c0000000000de89c] .vfs_write+0x120/0x208
[c00000001398fd90] [c0000000000df2c8] .sys_write+0x4c/0x8c
[c00000001398fe30] [c0000000000086ac] syscall_exit+0x0/0x40
Instruction dump:
fba1ffe8 fbe1fff8 789d0022 f8010010 f821ff71 789c0020 1d3d00a8 7b8a1f24 
38000000 7c7f1b78 7d291a14 e9690128 <7c0a592a> e8030000 e9690120 80a90100 

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 linux-2.6-bjking1/drivers/net/ibmveth.c |   24 ++++++++++++++----------
 linux-2.6-bjking1/drivers/net/ibmveth.h |    3 ---
 2 files changed, 14 insertions(+), 13 deletions(-)

diff -puN drivers/net/ibmveth.c~ibmveth_fixup_pool_deactivate drivers/net/ibmveth.c
--- linux-2.6/drivers/net/ibmveth.c~ibmveth_fixup_pool_deactivate	2007-08-01 10:22:37.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.c	2007-08-01 10:23:20.000000000 -0500
@@ -1280,24 +1280,28 @@ const char * buf, size_t count)
 			int i;
 			/* Make sure there is a buffer pool with buffers that
 			   can hold a packet of the size of the MTU */
-			for(i = 0; i<IbmVethNumBufferPools; i++) {
+			for (i = 0; i < IbmVethNumBufferPools; i++) {
 				if (pool == &adapter->rx_buff_pool[i])
 					continue;
 				if (!adapter->rx_buff_pool[i].active)
 					continue;
-				if (mtu < adapter->rx_buff_pool[i].buff_size) {
-					pool->active = 0;
-					h_free_logical_lan_buffer(adapter->
-								  vdev->
-								  unit_address,
-								  pool->
-								  buff_size);
-				}
+				if (mtu <= adapter->rx_buff_pool[i].buff_size)
+					break;
 			}
-			if (pool->active) {
+
+			if (i == IbmVethNumBufferPools) {
 				ibmveth_error_printk("no active pool >= MTU\n");
 				return -EPERM;
 			}
+
+			pool->active = 0;
+			if (netif_running(netdev)) {
+				adapter->pool_config = 1;
+				ibmveth_close(netdev);
+				adapter->pool_config = 0;
+				if ((rc = ibmveth_open(netdev)))
+					return rc;
+			}
 		}
 	} else if (attr == &veth_num_attr) {
 		if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
diff -puN drivers/net/ibmveth.h~ibmveth_fixup_pool_deactivate drivers/net/ibmveth.h
--- linux-2.6/drivers/net/ibmveth.h~ibmveth_fixup_pool_deactivate	2007-08-01 14:45:09.000000000 -0500
+++ linux-2.6-bjking1/drivers/net/ibmveth.h	2007-08-01 14:45:21.000000000 -0500
@@ -73,9 +73,6 @@ static inline long h_send_logical_lan(un
 #define h_change_logical_lan_mac(ua, mac) \
   plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
 
-#define h_free_logical_lan_buffer(ua, bufsize) \
-  plpar_hcall_norets(H_FREE_LOGICAL_LAN_BUFFER, ua, bufsize)
-
 #define IbmVethNumBufferPools 5
 #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
 #define IBMVETH_MAX_MTU 68
_

^ permalink raw reply

* FEC driver not working after upgrade
From: Mit Matelske @ 2007-08-01 19:47 UTC (permalink / raw)
  To: linuxppc-dev


I upgraded from an old 2.4.25 kernel to the latest Denx snapshot and cannot
get the ethernet to work.  I was previously running the FEC driver that used
the sdma interface.  I get a couple of interrupts and that is it.

Output when initializing:

mpc5xxx_fec_init
fec_priv c3f83160
MPC5200 I2S driver (16 BDs x 16 bytes).
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 4096 bind 8192)
mpc5xxx_fec_open
mpc5xxx_fec_restart
eth0: duplex set to 1
mii_queue: 600a0000 c0130bb0 00000000
mpc5xxx_fec_interrupt:
mpc5xxx_fec_mii 60080141 c0130bb0 00000000
mii_discover_phy
mii_queue: 600e0000 c0130abc 00000000
mpc5xxx_fec_interrupt:
mpc5xxx_fec_mii 600e0c87 c0130abc 00000000
eth0: Phy @ 0x0, type 88E6060 (0x01410c87)

Whenever I try to transmit anything I get:

mpc5xxx_fec_hard_start_xmit:
dev c3f83000, priv c3f83160, skb c3bcc860

The phy code works in the old fec driver fine, but I have tried the generic
phy driver also and it acts exactly the same.  

The major change was done by this patch back on Sept 4, 2005:

Modifications to the MPC5200 ATA and FEC drivers based on the
linuxppc_2_4_devel-fec+ata.patch and linux.habanero.fifo_cntrl.patch
patches from Freescale.

I am running a 5200B.  Thanks for any help.

Mit
-- 
View this message in context: http://www.nabble.com/FEC-driver-not-working-after-upgrade-tf4202285.html#a11952546
Sent from the linuxppc-dev mailing list archive at Nabble.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