LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* physmap_of and partitions (mtd concat support)
From: Stefan Roese @ 2009-03-23 10:51 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss list

I just noticed that physmap_of can't handle multiple devices of different type  
described in one device node. For example the Intel P30 48F4400 (64MByte) 
consists internally of 2 non-identical NOR chips. So a "simple" 

	flash@0,0 {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "cfi-flash";
		reg = <0 0 0x04000000>;
		bank-width = <2>;
		device-width = <2>;
		partition@0 {
			label = "test-part";
			reg = <0 0x04000000>;
		};
	}

is not working. It will "detect" 2 identical 32MByte chips which is wrong. 
Adding a 2nd flash node solves this problem:

	flash@0,0 {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "cfi-flash";
		reg = <0 0 0x02000000>;
		bank-width = <2>;
		device-width = <2>;
		partition@0 {
			label = "test-part1";
			reg = <0 0x02000000>;
		};
	}
	flash@1,0 {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "cfi-flash";
		reg = <0 0x02000000 0x02000000>;
		bank-width = <2>;
		device-width = <2>;
		partition@0 {
			label = "test-part2";
			reg = <0 0x02000000>;
		};
	}

This way both chips are detected correctly.

Now the real problem: How should I describe a partition in the device tree 
spanning over both devices (concat)?. The current physmap_of driver doesn't 
handle concat at all (physmap.c does). I already have some ideas on how to 
implement this concat support in physmap_of. But ideas about a device-tree 
syntax for such partitions are very welcome.

Thanks.

Best regards,
Stefan

^ permalink raw reply

* [PATCH] powerpc/mm: Fix Respect _PAGE_COHERENT on classic ppc32 SW TLB load machines
From: Kumar Gala @ 2009-03-23 13:46 UTC (permalink / raw)
  Cc: linuxppc-dev

Grant picked up the wrong version of "Respect _PAGE_COHERENT on classic
ppc32 SW" (commit a4bd6a93c3f14691c8a29e53eb04dc734b27f0db)

It was missing the code to actually deal with the fixup of
_PAGE_COHERENT based on the CPU feature.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 arch/powerpc/kernel/head_32.S |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 7db2e42..d794a63 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -513,6 +513,9 @@ InstructionTLBMiss:
 	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
 	ori	r1,r1,0xe04		/* clear out reserved bits */
 	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
+BEGIN_FTR_SECTION
+	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
+END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
 	mtspr	SPRN_RPA,r1
 	mfspr	r3,SPRN_IMISS
 	tlbli	r3
@@ -587,6 +590,9 @@ DataLoadTLBMiss:
 	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
 	ori	r1,r1,0xe04		/* clear out reserved bits */
 	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
+BEGIN_FTR_SECTION
+	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
+END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
 	mtspr	SPRN_RPA,r1
 	mfspr	r3,SPRN_DMISS
 	tlbld	r3
@@ -655,6 +661,9 @@ DataStoreTLBMiss:
 	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
 	li	r1,0xe05		/* clear out reserved bits & PP lsb */
 	andc	r1,r3,r1		/* PP = user? 2: 0 */
+BEGIN_FTR_SECTION
+	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
+END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
 	mtspr	SPRN_RPA,r1
 	mfspr	r3,SPRN_DMISS
 	tlbld	r3
-- 
1.5.6.6

^ permalink raw reply related

* Re: [PATCH] powerpc/mm: Fix Respect _PAGE_COHERENT on classic ppc32 SW TLB load machines
From: Kumar Gala @ 2009-03-23 13:48 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: LinuxPPC Mailing List, Linus Torvalds
In-Reply-To: <1237815974-21282-1-git-send-email-galak@kernel.crashing.org>


On Mar 23, 2009, at 8:46 AM, Kumar Gala wrote:

> Grant picked up the wrong version of "Respect _PAGE_COHERENT on  
> classic
> ppc32 SW" (commit a4bd6a93c3f14691c8a29e53eb04dc734b27f0db)
>
> It was missing the code to actually deal with the fixup of
> _PAGE_COHERENT based on the CPU feature.
>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
> arch/powerpc/kernel/head_32.S |    9 +++++++++
> 1 files changed, 9 insertions(+), 0 deletions(-)

I sent a pull request.  This needs to applied for .29

- k

^ permalink raw reply

* Re: Please pull from 'merge' branch
From: Kumar Gala @ 2009-03-23 13:50 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Linus Torvalds
In-Reply-To: <Pine.LNX.4.64.0903230843310.21260@blarg.am.freescale.net>

On Mon, 23 Mar 2009, Kumar Gala wrote:

> Please pull from 'merge' branch of
>
> 	master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc.git merge
>
> to receive the following updates:
>
>  arch/powerpc/kernel/head_32.S |    9 +++++++++
>  1 file changed, 9 insertions(+)
>
> Kumar Gala (1):
>       powerpc/mm: Fix Respect _PAGE_COHERENT on classic ppc32 SW TLB load machines
>

This should be picked up for .29.  Grant picked up the wrong verson of the
patch and we need the minor fixes to get to the right code that this
patch/pull request deals with.

- k

^ permalink raw reply

* Re: physmap_of and partitions (mtd concat support)
From: Grant Likely @ 2009-03-23 15:37 UTC (permalink / raw)
  To: Stefan Roese; +Cc: linuxppc-dev, devicetree-discuss list
In-Reply-To: <200903231151.10373.sr@denx.de>

On Mon, Mar 23, 2009 at 4:51 AM, Stefan Roese <sr@denx.de> wrote:
> I just noticed that physmap_of can't handle multiple devices of different type
> described in one device node. For example the Intel P30 48F4400 (64MByte)
> consists internally of 2 non-identical NOR chips. So a "simple"
[...]
> Now the real problem: How should I describe a partition in the device tree
> spanning over both devices (concat)?. The current physmap_of driver doesn't
> handle concat at all (physmap.c does). I already have some ideas on how to
> implement this concat support in physmap_of. But ideas about a device-tree
> syntax for such partitions are very welcome.

Sounds to me like a physmap_of driver bug.  I don't think there is any
advantage in changing the partition syntax since concatenated flash
will always be used as a single device.  It doesn't make any sense to
try and span partitions over two nodes.

Do additional properties need to be added to describe the concat layout?

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH 11/11] mmc: Add OpenFirmware bindings for SDHCI driver
From: Anton Vorontsov @ 2009-03-23 16:16 UTC (permalink / raw)
  To: 山崎 精二
  Cc: justinmattock, Ben Dooks, Arnd Bergmann, yamazaki, Liu Dave,
	linux-kernel, linuxppc-dev, sdhci-devel, Pierre Ossman
In-Reply-To: <20090323152051.D2F9.YAMAZAKI.SEIJI@kk.jp.panasonic.com>

On Mon, Mar 23, 2009 at 03:34:45PM +0900, 山崎 精二 wrote:
> Hi 
> 
> I downloaded linux-2.6.29-rc8.tar.bz2,and I patched .
> I was succeeded. Thank you very match.
> But I have the other problem.
> 
> Compile was not succeeded.
> 
> Message is ...
> 
>  CALL    arch/powerpc/kernel/prom_init_check.sh
>   CC      drivers/mmc/host/sdhci-of.o
> drivers/mmc/host/sdhci-of.c:163: error: 'SDHCI_QUIRK_FORCE_BLK_SZ_2048' undeclared here (not in a function)
> drivers/mmc/host/sdhci-of.c:164: error: 'SDHCI_QUIRK_BROKEN_CARD_DETECTION' undeclared here (not in a function)
> drivers/mmc/host/sdhci-of.c:165: error: 'SDHCI_QUIRK_INVERTED_WRITE_PROTECT' undeclared here (not in a function)
> drivers/mmc/host/sdhci-of.c:167: error: 'SDHCI_QUIRK_NONSTANDARD_CLOCK' undeclared here (not in a function)
> drivers/mmc/host/sdhci-of.c:168: error: 'SDHCI_QUIRK_PIO_NEEDS_DELAY' undeclared here (not in a function)
> drivers/mmc/host/sdhci-of.c:169: error: 'SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET' undeclared here (not in a function)
[...]
> drivers/mmc/host/sdhci-of.c:181: warning: excess elements in struct initializer
> drivers/mmc/host/sdhci-of.c:181: warning: (near initialization for 'sdhci_esdhc.ops')
> make[3]: *** [drivers/mmc/host/sdhci-of.o] Error 1
> make[2]: *** [drivers/mmc/host] Error 2
> make[1]: *** [drivers/mmc] Error 2

All these errors indicate that you didn't apply all the patches.
You'll need all 11 patches from this series, not only the last
one.

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* Re: [PATCH -next] fsl_pq_mdio: Use proper address translation
From: Kumar Gala @ 2009-03-23 16:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Andy Fleming, LinuxPPC Mailing List
In-Reply-To: <20090319164808.GA17795@oksana.dev.rtsoft.ru>


On Mar 19, 2009, at 11:48 AM, Anton Vorontsov wrote:

> Currently the driver just read "reg" property for constructing MDIO
> bus IDs, but this won't work when we'll start using "ranges = <>" in
> the device tree, so this will pop up:
>
> Freescale PowerQUICC MII Bus: probed
> sysfs: duplicate filename 'mdio@520' can not be created
> ------------[ cut here ]------------
> Badness at c00cb6b8 [verbose debug info unavailable]
> NIP: c00cb6b8 LR: c00cb6b8 CTR: c001271c
> REGS: cf82fc10 TRAP: 0700   Not tainted  (2.6.29-rc7-03702-g7ccd10f)
> MSR: 00029032 <EE,ME,CE,IR,DR>  CR: 42044022  XER: 20000000
> TASK = cf81fbd0[1] 'swapper' THREAD: cf82e000
> GPR00: c00cb6b8 cf82fcc0 cf81fbd0 0000003b 00000e42 ffffffff  
> 00004000 00000e42
> GPR08: c03cb0fc c03bfbdc 00000e42 c03cac50 22044022 1006a2bc  
> 0ffcb000 00000000
> GPR16: 0ffc04b0 0ffc5a40 00000000 0ffc79a8 0f7863a8 00000004  
> 00000000 00000000
> GPR24: c033a6a8 d1014520 cf85e840 cf82fd08 cf87cf2c cf82fcd8  
> cf85dea8 ffffffef
> NIP [c00cb6b8] sysfs_add_one+0x4c/0x54
> LR [c00cb6b8] sysfs_add_one+0x4c/0x54
> Call Trace:
> [cf82fcc0] [c00cb6b8] sysfs_add_one+0x4c/0x54 (unreliable)
> [cf82fcd0] [c00cbc18] create_dir+0x58/0xc0
> [cf82fd00] [c00cbcc0] sysfs_create_dir+0x40/0x70
> [cf82fd20] [c0159388] create_dir+0x28/0x78
> [cf82fd30] [c0159824] kobject_add_internal+0x98/0x13c
> [cf82fd50] [c0159e98] kobject_add+0x60/0x98
> [cf82fd80] [c018a480] device_add+0x98/0x2ac
> [cf82fda0] [c01a2380] mdiobus_register+0xbc/0x1c0
> [cf82fdc0] [c019f31c] fsl_pq_mdio_probe+0x284/0x2a0
> [cf82fe00] [c0223814] of_platform_device_probe+0x5c/0x84
> ...
>
> This patch fixes the issue by translating the "reg" property to a full
> address, and thus avoids the duplicate names.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---

Acked-by: Kumar Gala <galak@kernel.crashing.org>

David, I'm expecting you to pick this up and put it into net-next.

thanks

- k

^ permalink raw reply

* Re: suspend-to-mem on the mpc8349e-mitx-gp?
From: Scott Wood @ 2009-03-23 16:54 UTC (permalink / raw)
  To: Li Yang-R58472; +Cc: linuxppc-dev, Soohyung Cho
In-Reply-To: <3A45394FD742FA419B760BB8D398F9ED2FA48E@zch01exm26.fsl.freescale.net>

On Sun, Mar 22, 2009 at 10:45:23PM -0700, Li Yang-R58472 wrote:
> > I don't think so, in this case.  The user is not asking for 
> > "sleep" or deep sleep"; they are asking for a power state 
> > that meets the definition of "standby" (which sleep does) or 
> > which meets the definition of "mem" 
> > (which both sleep and deep sleep do).  When the user asks for 
> > "mem", we provide the lowest power mode that qualifies.
> 
> In my understanding, "mem" which is suspend-to-ram means all CPU states
> and registers are kept in memory and the CPU is completely off during
> suspension.  I don't think the sleep mode of 8349 qualifies, does it?

Is there a difference visible to software or to the user (other than not
achieving power savings that the board does not support)?  It seems
simpler for userspace to just specify the "heaviest" sleep state it wants
deal with (though some feedback to an administrator of what actually
happens would be nice).  

And if we want to be really pedantic, neither sleep nor deep sleep meet
the definitions for either "standby" or "mem", because they specify
acceptable latency ranges in seconds, and (in the absence of a disk) we
are much faster than that (it doesn't say "up to 1-2 seconds"). :-)

Are there any existing suspend drivers that suppord standby but not mem? 
I see omap1 as a counterexample that treats them both the same.

-Scott

^ permalink raw reply

* RE: Xilinx cygwin linux cross recommendations ?
From: John Linn @ 2009-03-23 17:17 UTC (permalink / raw)
  To: dhlii, linuxppc-dev
In-Reply-To: <49C2DC5D.6000701@dlasys.net>

I agree that VmWare is a reasonable solution.

Some of our field guys, that don't do Linux everyday, use the ELDK in a
VmWare appliance and this seems reasonable.  We never had great luck
with cygwin stuff in this area.

-- John

> -----Original Message-----
> From: linuxppc-dev-bounces+john.linn=3Dxilinx.com@ozlabs.org
[mailto:linuxppc-dev-
> bounces+john.linn=3Dxilinx.com@ozlabs.org] On Behalf Of David H. Lynch
Jr.
> Sent: Thursday, March 19, 2009 5:59 PM
> To: linuxppc-dev@ozlabs.org
> Subject: Xilinx cygwin linux cross recommendations ?
> =

> =

>     Does anyone have experience sugestions for building ppc/linux apps
> or even ppc kernels under windows.
> =

>     I work (and live) under Linux. I am very happy to work under
Linux.
> I only spend about 20 minutes a week in windows anymore.
> =

>     But I have coworkers, and clients that live under windows.
>     Mostly I have them working under coLinux, but even that seems to
be
> too much for many of them.
> =

>     I have been able to mangle my build environment to  work under
msys
> and use the xilinx edk cross compiler to build standalone PPC apps,
>     But the libraries do not seem to be present for linux
applications.
> =

>     I build my own uclibc crosscompiler under linux from buildroot.
>        Has anyone got experience doing that under windows ?
> =

>     Can I just copy the appropriate library binaries and use them with
> the xilinx EDK cross compiler ? Presumably I need to match versions of
GCC.
> =

>     Other suguestions ?
> =

>     Thanks.
> =

> =

> =

> =

> --
> Dave Lynch 					  	    DLA Systems
> Software Development:
Embedded Linux
> 717.627.3770 	       dhlii@dlasys.net 	  http://www.dlasys.net
> fax: 1.253.369.9244 			           Cell: 1.717.587.7774
> Over 25 years' experience in platforms, languages, and technologies
too numerous to list.
> =

> "Any intelligent fool can make things bigger and more complex... It
takes a touch of genius - and a
> lot of courage to move in the opposite direction."
> Albert Einstein
> =

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


This email and any attachments are intended for the sole use of the named r=
ecipient(s) and contain(s) confidential information that may be proprietary=
, privileged or copyrighted under applicable law. If you are not the intend=
ed recipient, do not read, copy, or forward this email message or any attac=
hments. Delete this email message and any attachments immediately.

^ permalink raw reply

* Re: Fix for __div64_32 locks when using some 64 bit numbers
From: davidastro @ 2009-03-23 17:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <18887.4715.765245.409925@drongo.ozlabs.ibm.com>


Paul,

You are correct. Since it was such a small piece of code, I didn't use diff
between the kernel I am using (2.6.14) and the newest ones (2.6.28 on the
Linux). Also, I do not know how to look in the kernel files commit history.
I guess the link you gave me might be of some help. 

Thanks for your help


Paul Mackerras wrote:
> 
> davidastro <davidastro@hotmail.com> writes:
> 
>> Basically, the numbers shown above was causing the 64 by 32 bit algorithm
>> to
>> divide by zero making the unit spin and also giving incorrect results.
>> Here is the code as it was before.
> [snip]
>>         cntlzw  r0,r5           # we are shifting the dividend right
>>         li      r10,-1          # to make it < 2^32, and shifting
>>         srw     r10,r10,r0      # the divisor right the same amount,
>>         add     r9,r4,r10       # rounding up (so the estimate cannot
>>         andc    r11,r6,r10      # ever be too large, only too small)
>>         andc    r9,r9,r10      #THIS CODE COULD STORE A ZERO IN r9
>>         or      r11,r5,r11
>>         rotlw   r9,r9,r0
>>         rotlw   r11,r11,r0
> 
> That bug was fixed in October 2005 in commit 344480b99730bfd2, and the
> fix is in v2.6.15-rc1 and all later kernels.  I fixed it a bit
> differently to your suggestion though - see
> 
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=344480b99730bfd205e306d3fd168cdcebe83425
> 
> You must be working from an old kernel tree - which kernel version are
> you using?
> 
> Paul.
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 
> 

-- 
View this message in context: http://www.nabble.com/Fix-for-__div64_32-locks-when-using-some-64-bit-numbers-tp22567864p22665081.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.

^ permalink raw reply

* Re: [PATCH] ucc_geth: Convert to net_device_ops
From: David Miller @ 2009-03-23 18:49 UTC (permalink / raw)
  To: Joakim.Tjernlund; +Cc: netdev, leoli, linuxppc-dev
In-Reply-To: <OF2EE08546.DF677136-ONC1257582.0037C87E-C1257582.00388BCE@transmode.se>

From: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
Date: Mon, 23 Mar 2009 11:17:39 +0100

> Sorry for the WS damaged patch, but my current company mailer cannot
> handle inline patches. Due to this we are setting up a new mail system
> but it will be a few days before this is ready.
> Therefore I am attaching this patch as well, use that one
> to apply instaed of the inline variant.

This patch has other problems, anyways.

> +#if 0
> +/* not yet */
> +       .ndo_set_mac_address    = ucc_geth_set_mac_address,
> +       .ndo_change_mtu         = ucc_geth_change_mtu,
> +       .ndo_do_ioctl           = ucc_geth_do_ioctl,
> +#endif

Don't do stuff like this, please.  Even the code you are
copying from doesn't have the set_mac_address method
assignment proceted by #if 0 stuff.

Just get rid of all the unused stuff completely.

^ permalink raw reply

* Re: [PATCH 04/57] microblaze_v7: Open firmware files
From: Arnd Bergmann @ 2009-03-23 18:51 UTC (permalink / raw)
  To: monstr; +Cc: linuxppc-dev, linux-kernel, john.williams
In-Reply-To: <af309ba8e95f503b7990461384d9f8453f45dbbd.1237407249.git.monstr@monstr.eu>

On Wednesday 18 March 2009, monstr@monstr.eu wrote:
> From: Michal Simek <monstr@monstr.eu>
>=20
>=20
> Signed-off-by: Michal Simek <monstr@monstr.eu>
> ---
> =A0arch/microblaze/include/asm/of_device.h =A0 | =A0 45 ++
> =A0arch/microblaze/include/asm/of_platform.h | =A0 64 ++
> =A0arch/microblaze/include/asm/prom.h =A0 =A0 =A0 =A0| =A0313 ++++++++
> =A0arch/microblaze/kernel/of_device.c =A0 =A0 =A0 =A0| =A0115 +++
> =A0arch/microblaze/kernel/of_platform.c =A0 =A0 =A0| =A0201 +++++
> =A0arch/microblaze/kernel/prom.c =A0 =A0 =A0 =A0 =A0 =A0 | 1147 +++++++++=
++++++++++++++++++++
> =A0arch/microblaze/kernel/prom_parse.c =A0 =A0 =A0 | 1025 +++++++++++++++=
+++++++++++
> =A07 files changed, 2910 insertions(+), 0 deletions(-)
> =A0create mode 100644 arch/microblaze/include/asm/of_device.h
> =A0create mode 100644 arch/microblaze/include/asm/of_platform.h
> =A0create mode 100644 arch/microblaze/include/asm/prom.h
> =A0create mode 100644 arch/microblaze/kernel/of_device.c
> =A0create mode 100644 arch/microblaze/kernel/of_platform.c
> =A0create mode 100644 arch/microblaze/kernel/prom.c
> =A0create mode 100644 arch/microblaze/kernel/prom_parse.c

Since these files are derived from the powerpc versions, what is the
plan on them? IIRC, you had them in a common directory in an earlier
version. Are you planning to merge them at some point in the future
or do you intend to maintain a fork?

	Arnd <><

^ permalink raw reply

* Re: Please pull from 'merge' branch
From: Benjamin Herrenschmidt @ 2009-03-23 20:39 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Linus Torvalds
In-Reply-To: <Pine.LNX.4.64.0903230849130.21310@blarg.am.freescale.net>

On Mon, 2009-03-23 at 08:50 -0500, Kumar Gala wrote:
> On Mon, 23 Mar 2009, Kumar Gala wrote:
> 
> > Please pull from 'merge' branch of
> >
> > 	master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc.git merge
> >
> > to receive the following updates:
> >
> >  arch/powerpc/kernel/head_32.S |    9 +++++++++
> >  1 file changed, 9 insertions(+)
> >
> > Kumar Gala (1):
> >       powerpc/mm: Fix Respect _PAGE_COHERENT on classic ppc32 SW TLB load machines
> >
> 
> This should be picked up for .29.  Grant picked up the wrong verson of the
> patch and we need the minor fixes to get to the right code that this
> patch/pull request deals with.

Oh ok, I see. Ack.

Ben.

^ permalink raw reply

* Re: [PATCH 04/57] microblaze_v7: Open firmware files
From: Anton Vorontsov @ 2009-03-23 20:53 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, monstr, linux-kernel, john.williams
In-Reply-To: <200903231951.23902.arnd@arndb.de>

On Mon, Mar 23, 2009 at 07:51:23PM +0100, Arnd Bergmann wrote:
> On Wednesday 18 March 2009, monstr@monstr.eu wrote:
> > From: Michal Simek <monstr@monstr.eu>
> > 
> > 
> > Signed-off-by: Michal Simek <monstr@monstr.eu>
> > ---
> >  arch/microblaze/include/asm/of_device.h   |   45 ++
> >  arch/microblaze/include/asm/of_platform.h |   64 ++
> >  arch/microblaze/include/asm/prom.h        |  313 ++++++++
> >  arch/microblaze/kernel/of_device.c        |  115 +++
> >  arch/microblaze/kernel/of_platform.c      |  201 +++++
> >  arch/microblaze/kernel/prom.c             | 1147 +++++++++++++++++++++++++++++
> >  arch/microblaze/kernel/prom_parse.c       | 1025 ++++++++++++++++++++++++++
> >  7 files changed, 2910 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/microblaze/include/asm/of_device.h
> >  create mode 100644 arch/microblaze/include/asm/of_platform.h
> >  create mode 100644 arch/microblaze/include/asm/prom.h
> >  create mode 100644 arch/microblaze/kernel/of_device.c
> >  create mode 100644 arch/microblaze/kernel/of_platform.c
> >  create mode 100644 arch/microblaze/kernel/prom.c
> >  create mode 100644 arch/microblaze/kernel/prom_parse.c
> 
> Since these files are derived from the powerpc versions, what is the
> plan on them? IIRC, you had them in a common directory in an earlier
> version. Are you planning to merge them at some point in the future
> or do you intend to maintain a fork?

Actually, it's trivial to factor out all the common code out of
arch/powerpc/ to drivers/of/.

It took me approx. 4 hours to factor out the code and make a
proof-of-concept FDT support for a little-endian ARM platform. ;-)
(The device tree was only describing a cpu and a nor flash, though.
No support for interrupt- and gpio-controllers. And no support for
U-Boot, I just built the dtb file into the kernel).

I never got around to clean it up and send though, but for sure,
there is absolutely no reason to duplicate the code across the
platforms.

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* Re: [PATCH 04/57] microblaze_v7: Open firmware files
From: Michal Simek @ 2009-03-23 20:44 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, linux-kernel, john.williams
In-Reply-To: <200903231951.23902.arnd@arndb.de>

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

Hi Arnd,

nice to hear you.

On Wednesday 18 March 2009, monstr@monstr.eu wrote:
> > From: Michal Simek <monstr@monstr.eu>
> >
> >
> > Signed-off-by: Michal Simek <monstr@monstr.eu>
> > ---
> >  arch/microblaze/include/asm/of_device.h   |   45 ++
> >  arch/microblaze/include/asm/of_platform.h |   64 ++
> >  arch/microblaze/include/asm/prom.h        |  313 ++++++++
> >  arch/microblaze/kernel/of_device.c        |  115 +++
> >  arch/microblaze/kernel/of_platform.c      |  201 +++++
> >  arch/microblaze/kernel/prom.c             | 1147
> +++++++++++++++++++++++++++++
> >  arch/microblaze/kernel/prom_parse.c       | 1025
> ++++++++++++++++++++++++++
> >  7 files changed, 2910 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/microblaze/include/asm/of_device.h
> >  create mode 100644 arch/microblaze/include/asm/of_platform.h
> >  create mode 100644 arch/microblaze/include/asm/prom.h
> >  create mode 100644 arch/microblaze/kernel/of_device.c
> >  create mode 100644 arch/microblaze/kernel/of_platform.c
> >  create mode 100644 arch/microblaze/kernel/prom.c
> >  create mode 100644 arch/microblaze/kernel/prom_parse.c
>
> Since these files are derived from the powerpc versions, what is the
> plan on them? IIRC, you had them in a common directory in an earlier
> version. Are you planning to merge them at some point in the future
> or do you intend to maintain a fork?


yes, these files are defived from PPC version. Yes, I added them to generic
location and in this version
are in arch folder. It is easier for me to have them in arch folder till
Microblaze will be in  linus tree.
And then create patch which will synchronize them.

I prefer to have this code in generic location as much as possible but first
stage should be add microblaze code to tree and
then add it to generic location and remove it from all archs which use it.

Thanks,
Michal





>
>
>        Arnd <><
>

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

^ permalink raw reply

* [PATCH] tracing: Fix TRACING_SUPPORT dependency for PPC32
From: Anton Vorontsov @ 2009-03-23 22:07 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linuxppc-dev, Steven Rostedt, linux-kernel, Steven Rostedt
In-Reply-To: <20090321161814.GC11183@elte.hu>

commit 40ada30f9621fbd831ac2437b9a2a399aa ("tracing: clean up menu"),
despite the "clean up" in its purpose, introduced a behavioural
change for Kconfig symbols: we no longer able to select tracing
support on PPC32 (because IRQFLAGS_SUPPORT isn't yet implemented).

The IRQFLAGS_SUPPORT is not mandatory for most tracers, tracing core
has a special case for platforms w/o irqflags (which, by the way, has
become useless as of the commit above).

Though according to Ingo Molnar, there was periodic build failures on
weird, unmaintained architectures that had no irqflags-tracing support
and hence didn't know the raw_irqs_save/restore primitives. Thus we'd
better not enable irqflags-less tracing for all architectures.

This patch restores the old behaviour for PPC32, and thus brings the
tracing back. Other architectures can either add themselves to the
exception list or (better) implement TRACE_IRQFLAGS_SUPPORT.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---

On Sat, Mar 21, 2009 at 05:18:14PM +0100, Ingo Molnar wrote:
[...]
> > > > Surely I'll look into implementing irqflags tracing, but 
> > > > considering that no one ever needed this for almost three years, 
> > > > [...]
> > > 
> > > Weird, there's no lockdep support?
> > 
> > *ashamed*: apparently no such support currently exist for PPC32. ;-)
> 
> Hm, do all the tracers even compile on ppc32 with your patch?

Following config compiles fine:

$ grep TRAC .config
CONFIG_STACKTRACE_SUPPORT=y
# CONFIG_TREE_RCU_TRACE is not set
# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_TRACEPOINTS=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_STACKTRACE=y
CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_TRACER_MAX_TRACE=y
CONFIG_TRACING=y
CONFIG_TRACING_SUPPORT=y
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
CONFIG_SCHED_TRACER=y
CONFIG_CONTEXT_SWITCH_TRACER=y
CONFIG_EVENT_TRACER=y
CONFIG_BOOT_TRACER=y
# CONFIG_TRACE_BRANCH_PROFILING is not set
CONFIG_STACK_TRACER=y
CONFIG_KMEMTRACE=y
CONFIG_WORKQUEUE_TRACER=y
# CONFIG_BLK_DEV_IO_TRACE is not set
CONFIG_DYNAMIC_FTRACE=y
CONFIG_FTRACE_MCOUNT_RECORD=y
CONFIG_FTRACE_SELFTEST=y
CONFIG_FTRACE_STARTUP_TEST=y

With CONFIG_TRACE_BRANCH_PROFILING=y the kernel builds fine too,
but vmlinux is too big to boot (we still can boot it, but we'll
need a bit modified bootloader for that).

OK, how about the patch down below?

 kernel/trace/Kconfig |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index ee70841..2246141 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -63,7 +63,11 @@ config TRACING
 #
 config TRACING_SUPPORT
 	bool
-	depends on TRACE_IRQFLAGS_SUPPORT
+	# PPC32 has no irqflags tracing support, but it can use most of the
+	# tracers anyway, they were tested to build and work. Note that new
+	# exceptions to this list aren't welcomed, better implement the
+	# irqflags tracing for your architecture.
+	depends on TRACE_IRQFLAGS_SUPPORT || PPC32
 	depends on STACKTRACE_SUPPORT
 	default y
 
-- 
1.5.6.5

^ permalink raw reply related

* Re: [PATCH -next] fsl_pq_mdio: Use proper address translation
From: David Miller @ 2009-03-23 22:48 UTC (permalink / raw)
  To: galak; +Cc: netdev, afleming, linuxppc-dev
In-Reply-To: <95190FB6-C6A3-43F7-9684-9B4BC095D480@kernel.crashing.org>

From: Kumar Gala <galak@kernel.crashing.org>
Date: Mon, 23 Mar 2009 11:49:07 -0500

> Acked-by: Kumar Gala <galak@kernel.crashing.org>
> 
> David, I'm expecting you to pick this up and put it into net-next.

Done, thanks.

^ permalink raw reply

* Re: [PATCH] tracing: Fix TRACING_SUPPORT dependency for PPC32
From: Steven Rostedt @ 2009-03-24  0:51 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linuxppc-dev, Ingo Molnar, Steven Rostedt, linux-kernel
In-Reply-To: <20090323220724.GA9851@oksana.dev.rtsoft.ru>


On Tue, 24 Mar 2009, Anton Vorontsov wrote:

> commit 40ada30f9621fbd831ac2437b9a2a399aa ("tracing: clean up menu"),
> despite the "clean up" in its purpose, introduced a behavioural
> change for Kconfig symbols: we no longer able to select tracing
> support on PPC32 (because IRQFLAGS_SUPPORT isn't yet implemented).
> 
> The IRQFLAGS_SUPPORT is not mandatory for most tracers, tracing core
> has a special case for platforms w/o irqflags (which, by the way, has
> become useless as of the commit above).
> 
> Though according to Ingo Molnar, there was periodic build failures on
> weird, unmaintained architectures that had no irqflags-tracing support
> and hence didn't know the raw_irqs_save/restore primitives. Thus we'd
> better not enable irqflags-less tracing for all architectures.
> 
> This patch restores the old behaviour for PPC32, and thus brings the
> tracing back. Other architectures can either add themselves to the
> exception list or (better) implement TRACE_IRQFLAGS_SUPPORT.
> 
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
[..]

> diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
> index ee70841..2246141 100644
> --- a/kernel/trace/Kconfig
> +++ b/kernel/trace/Kconfig
> @@ -63,7 +63,11 @@ config TRACING
>  #
>  config TRACING_SUPPORT
>  	bool
> -	depends on TRACE_IRQFLAGS_SUPPORT
> +	# PPC32 has no irqflags tracing support, but it can use most of the
> +	# tracers anyway, they were tested to build and work. Note that new
> +	# exceptions to this list aren't welcomed, better implement the
> +	# irqflags tracing for your architecture.
> +	depends on TRACE_IRQFLAGS_SUPPORT || PPC32
>  	depends on STACKTRACE_SUPPORT
>  	default y
> 

I'm fine with this.

Acked-by: Steven Rostedt <srostedt@redhat.com>

-- Steve

^ permalink raw reply

* Re: FW: [PATCH v2 13/13] net: add Xilinx ll_temac device driver
From: Grant Likely @ 2009-03-24  1:15 UTC (permalink / raw)
  To: John Williams; +Cc: linuxppc-dev, Michal Simek, netdev
In-Reply-To: <9e6f3dfd0903231732hdc49acej50f8ff0cb895bc2f@mail.gmail.com>

(adding netdev and linuxppc mailing lists to the CC: list)

On Mon, Mar 23, 2009 at 6:32 PM, John Williams <jwilliams@itee.uq.edu.au> w=
rote:
> On Tue, Mar 24, 2009 at 4:09 AM, Stephen Neuendorffer <stephen.neuendorff=
er@xilinx.com> wrote:
>> From: Grant Likely <grant.likely@secretlab.ca>
>>>
>>> This patch adds support for the Xilinx ll_temac 10/100/1000 Ethernet
>>> device.  The ll_temac ipcore is typically used on Xilinx Virtex and
>>> Spartan designs attached to either a PowerPC 4xx or Microblaze
>>> processor.
>>>
>>> At the present moment, this driver only works with Virtex5 PowerPC
>>> designs because it assumes DCR is used to access the DMA registers.
>>> However, the low level access to DMA registers is abstracted and
>>> it should be easy to adapt for the other implementations.
>>
>> Don't know if you saw this, but 'only supports V5' is something that
>> reasonably directly affects you...
>
> Thanks for the heads up. =A0The DCR support seems reasonably easy to
> factor out for PLB accesses to SDMA regs. =A0I would probably be happy
> enough to let it get merged then we submit patches against it later.
>
> Grant, any thoughts on this? =A0Doesn't look like a great deal of work
> to support PLB SDMA control?

It really shouldn't be much work at all.  It is on my todo list, but
any help would be appreciated.

Although I'm also thinking about going a step farther and factoring
out the LL code into a separate driver entirely.

g.

>
> Cheers,
>
> John
>
>
>>
>> -----Original Message-----
>> From: linuxppc-dev-bounces+stephen.neuendorffer=3Dxilinx.com@ozlabs.org
>> [mailto:linuxppc-dev-bounces+stephen.neuendorffer=3Dxilinx.com@ozlabs.or=
g]
>> On Behalf Of Grant Likely
>> Sent: Saturday, March 21, 2009 3:29 PM
>> To: linuxppc-dev@ozlabs.org; netdev@vger.kernel.org; olof@lixom.net
>> Cc: afleming@freescale.com; davem@davemloft.net
>> Subject: [PATCH v2 13/13] net: add Xilinx ll_temac device driver
>>
>> I'm posting this driver now as an RFC. =A0There are still some things th=
at
>> need to be tightened up, but it does appear to be stable.
>>
>> Derived from driver code written by Yoshio Kashiwagi and David H. Lynch
>> Jr.
>>
>> CC: Yoshio Kashiwagi <kashiwagi@co-nss.co.jp>
>> CC: David H. Lynch Jr. <dhlii@dlasys.net>
>> CC: John Linn <john.linn@xilinx.com>
>> CC: John Bonesio <john.bonesio@xilinx.com>
>> CC: David DeBonis <ddeboni@xilinx.com>
>> CC: Wilson Yang <wyang@xilinx.com>
>> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
>> ---
>>
>> =A0drivers/net/Kconfig =A0 =A0 =A0 =A0 =A0 =A0 | =A0 =A08
>> =A0drivers/net/Makefile =A0 =A0 =A0 =A0 =A0 =A0| =A0 =A02
>> =A0drivers/net/xilinx_temac.c =A0 =A0 =A0| =A0970
>> +++++++++++++++++++++++++++++++++++++++
>> =A0drivers/net/xilinx_temac.h =A0 =A0 =A0| =A0374 +++++++++++++++
>> =A0drivers/net/xilinx_temac_mdio.c | =A0119 +++++
>> =A05 files changed, 1473 insertions(+), 0 deletions(-)
>> =A0create mode 100644 drivers/net/xilinx_temac.c
>> =A0create mode 100644 drivers/net/xilinx_temac.h
>> =A0create mode 100644 drivers/net/xilinx_temac_mdio.c
>>
>>
>> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
>> index 435e2e3..29d6c1f 100644
>> --- a/drivers/net/Kconfig
>> +++ b/drivers/net/Kconfig
>> @@ -2321,6 +2321,14 @@ config MV643XX_ETH
>> =A0 =A0 =A0 =A0 =A0Some boards that use the Discovery chipset are the Mo=
menco
>> =A0 =A0 =A0 =A0 =A0Ocelot C and Jaguar ATX and Pegasos II.
>>
>> +config XILINX_TEMAC
>> + =A0 =A0 =A0 tristate "Xilinx TEMAC 10/100/1000 Ethernet MAC driver"
>> + =A0 =A0 =A0 select PHYLIB
>> + =A0 =A0 =A0 depends on PPC
>> + =A0 =A0 =A0 help
>> + =A0 =A0 =A0 =A0 This driver supports the Xilinx 10/100/1000 LocalLink =
TEMAC
>> + =A0 =A0 =A0 =A0 device found in Virtex FPGAs
>> +
>> =A0config QLA3XXX
>> =A0 =A0 =A0 =A0tristate "QLogic QLA3XXX Network Driver Support"
>> =A0 =A0 =A0 =A0depends on PCI
>> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> index 471baaf..c7b4dd9 100644
>> --- a/drivers/net/Makefile
>> +++ b/drivers/net/Makefile
>> @@ -132,6 +132,8 @@ obj-$(CONFIG_AX88796) +=3D ax88796.o
>>
>> =A0obj-$(CONFIG_TSI108_ETH) +=3D tsi108_eth.o
>> =A0obj-$(CONFIG_MV643XX_ETH) +=3D mv643xx_eth.o
>> +xilinxtemac-objs :=3D xilinx_temac.o xilinx_temac_mdio.o
>> +obj-$(CONFIG_XILINX_TEMAC) +=3D xilinxtemac.o
>> =A0obj-$(CONFIG_QLA3XXX) +=3D qla3xxx.o
>> =A0obj-$(CONFIG_QLGE) +=3D qlge/
>>
>> diff --git a/drivers/net/xilinx_temac.c b/drivers/net/xilinx_temac.c
>> new file mode 100644
>> index 0000000..d778a55
>> --- /dev/null
>> +++ b/drivers/net/xilinx_temac.c
>> @@ -0,0 +1,970 @@
>> +/*
>> + * Driver for Xilinx TEMAC Ethernet device
>> + *
>> + * Copyright (c) 2008 Nissin Systems Co., Ltd., =A0Yoshio Kashiwagi
>> + * Copyright (c) 2005-2008 DLA Systems, =A0David H. Lynch Jr.
>> <dhlii@dlasys.net>
>> + * Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
>> + *
>> + * This is a driver for the Xilinx ll_temac ipcore which is often used
>> + * in the Virtex and Spartan series of chips.
>> + *
>> + * Notes:
>> + * - The ll_temac hardware uses indirect access for many of the TEMAC
>> + * =A0 registers, include the MDIO bus. =A0However, indirect access to =
MDIO
>> + * =A0 registers take considerably more clock cycles than to TEMAC
>> registers.
>> + * =A0 MDIO accesses are long, so threads doing them should probably
>> sleep
>> + * =A0 rather than busywait. =A0However, since only one indirect access=
 can
>> be
>> + * =A0 in progress at any given time, that means that *all* indirect
>> accesses
>> + * =A0 could end up sleeping (to wait for an MDIO access to complete).
>> + * =A0 Fortunately none of the indirect accesses are on the 'hot' path
>> for tx
>> + * =A0 or rx, so this should be okay.
>> + *
>> + * TODO:
>> + * - Fix driver to work on more than just Virtex5. =A0Right now the
>> driver
>> + * =A0 assumes that the locallink DMA registers are accessed via DCR
>> + * =A0 instructions.
>> + * - Factor out locallink DMA code into separate driver
>> + * - Fix multicast assignment.
>> + * - Fix support for hardware checksumming.
>> + * - Testing. =A0Lots and lots of testing.
>> + *
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/etherdevice.h>
>> +#include <linux/init.h>
>> +#include <linux/mii.h>
>> +#include <linux/module.h>
>> +#include <linux/mutex.h>
>> +#include <linux/netdevice.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_mdio.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/skbuff.h>
>> +#include <linux/spinlock.h>
>> +#include <linux/tcp.h> =A0 =A0 =A0/* needed for sizeof(tcphdr) */
>> +#include <linux/udp.h> =A0 =A0 =A0/* needed for sizeof(udphdr) */
>> +#include <linux/pci.h>
>> +#include <linux/phy.h>
>> +#include <linux/in.h>
>> +#include <linux/io.h>
>> +#include <linux/ip.h>
>> +
>> +#include "xilinx_temac.h"
>> +
>> +#define TX_BD_NUM =A0 64
>> +#define RX_BD_NUM =A0 128
>> +
>> +/*
>> ---------------------------------------------------------------------
>> + * Low level register access functions
>> + */
>> +
>> +u32 temac_ior(struct temac_local *lp, int offset)
>> +{
>> + =A0 =A0 =A0 return in_be32((u32 *)(lp->regs + offset));
>> +}
>> +
>> +void temac_iow(struct temac_local *lp, int offset, u32 value)
>> +{
>> + =A0 =A0 =A0 out_be32((u32 *) (lp->regs + offset), value);
>> +}
>> +
>> +int temac_indirect_busywait(struct temac_local *lp)
>> +{
>> + =A0 =A0 =A0 long end =3D jiffies + 2;
>> +
>> + =A0 =A0 =A0 while (!(temac_ior(lp, XTE_RDY0_OFFSET) &
>> XTE_RDY0_HARD_ACS_RDY_MASK)) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (end - jiffies <=3D 0) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 WARN_ON(1);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ETIMEDOUT;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 msleep(1);
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 return 0;
>> +}
>> +
>> +/**
>> + * temac_indirect_in32
>> + *
>> + * lp->indirect_mutex must be held when calling this function
>> + */
>> +u32 temac_indirect_in32(struct temac_local *lp, int reg)
>> +{
>> + =A0 =A0 =A0 u32 val;
>> +
>> + =A0 =A0 =A0 if (temac_indirect_busywait(lp))
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ETIMEDOUT;
>> + =A0 =A0 =A0 temac_iow(lp, XTE_CTL0_OFFSET, reg);
>> + =A0 =A0 =A0 if (temac_indirect_busywait(lp))
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ETIMEDOUT;
>> + =A0 =A0 =A0 val =3D temac_ior(lp, XTE_LSW0_OFFSET);
>> +
>> + =A0 =A0 =A0 return val;
>> +}
>> +
>> +/**
>> + * temac_indirect_out32
>> + *
>> + * lp->indirect_mutex must be held when calling this function
>> + */
>> +void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
>> +{
>> + =A0 =A0 =A0 if (temac_indirect_busywait(lp))
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
>> + =A0 =A0 =A0 temac_iow(lp, XTE_LSW0_OFFSET, value);
>> + =A0 =A0 =A0 temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK |=
 reg);
>> +}
>> +
>> +static u32 temac_dma_in32(struct temac_local *lp, int reg)
>> +{
>> + =A0 =A0 =A0 return dcr_read(lp->sdma_dcrs, reg);
>> +}
>> +
>> +static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
>> +{
>> + =A0 =A0 =A0 dcr_write(lp->sdma_dcrs, reg, value);
>> +}
>> +
>> +/**
>> + * temac_dma_bd_init - Setup buffer descriptor rings
>> + */
>> +static int temac_dma_bd_init(struct net_device *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 struct sk_buff *skb;
>> + =A0 =A0 =A0 int i;
>> +
>> + =A0 =A0 =A0 lp->rx_skb =3D kzalloc(sizeof(struct sk_buff)*RX_BD_NUM,
>> GFP_KERNEL);
>> + =A0 =A0 =A0 /* allocate the tx and rx ring buffer descriptors. */
>> + =A0 =A0 =A0 /* returns a virtual addres and a physical address. */
>> + =A0 =A0 =A0 lp->tx_bd_v =3D dma_alloc_coherent(NULL, sizeof(*lp->tx_bd=
_v) *
>> TX_BD_NUM,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0&lp->tx_bd_p, GFP_KERNEL);
>> + =A0 =A0 =A0 lp->rx_bd_v =3D dma_alloc_coherent(NULL, sizeof(*lp->rx_bd=
_v) *
>> RX_BD_NUM,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0&lp->rx_bd_p, GFP_KERNEL);
>> +
>> + =A0 =A0 =A0 memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
>> + =A0 =A0 =A0 for (i =3D 0; i < TX_BD_NUM; i++) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->tx_bd_v[i].next =3D lp->tx_bd_p +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sizeof(*lp=
->tx_bd_v) * ((i + 1) %
>> TX_BD_NUM);
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
>> + =A0 =A0 =A0 for (i =3D 0; i < RX_BD_NUM; i++) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->rx_bd_v[i].next =3D lp->rx_bd_p +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sizeof(*lp=
->rx_bd_v) * ((i + 1) %
>> RX_BD_NUM);
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb =3D alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 + XTE_ALIG=
N, GFP_ATOMIC);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (skb =3D=3D 0) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&ndev->dev, "alloc=
_skb error %d\n", i);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -1;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->rx_skb[i] =3D skb;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb_reserve(skb, =A0BUFFER_ALIGN(skb->data=
));
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* returns physical address of skb->data *=
/
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->rx_bd_v[i].phys =3D pci_map_single(NUL=
L, skb->data,
>> +
>> XTE_MAX_JUMBO_FRAME_SIZE,
>> +
>> PCI_DMA_FROMDEVICE);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->rx_bd_v[i].len =3D XTE_MAX_JUMBO_FRAME=
_SIZE;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->rx_bd_v[i].app0 =3D STS_CTRL_APP0_IRQO=
NEND;
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 CHNL_CTRL_IRQ_EN |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 CHNL_CTRL_IRQ_DLY_EN |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 CHNL_CTRL_IRQ_COAL_EN);
>> + =A0 =A0 =A0 /* 0x10220483 */
>> + =A0 =A0 =A0 /* 0x00100483 */
>> + =A0 =A0 =A0 temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 CHNL_CTRL_IRQ_EN |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 CHNL_CTRL_IRQ_DLY_EN |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 CHNL_CTRL_IRQ_COAL_EN |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 CHNL_CTRL_IRQ_IOE);
>> + =A0 =A0 =A0 /* 0xff010283 */
>> +
>> + =A0 =A0 =A0 temac_dma_out32(lp, RX_CURDESC_PTR, =A0lp->rx_bd_p);
>> + =A0 =A0 =A0 temac_dma_out32(lp, RX_TAILDESC_PTR,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0lp->rx_bd_p + (sizeof(*lp->=
rx_bd_v) * (RX_BD_NUM
>> - 1)));
>> + =A0 =A0 =A0 temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p);
>> +
>> + =A0 =A0 =A0 return 0;
>> +}
>> +
>> +/*
>> ---------------------------------------------------------------------
>> + * net_device_ops
>> + */
>> +
>> +static int temac_set_mac_address(struct net_device *ndev, void
>> *address)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> +
>> + =A0 =A0 =A0 if (address)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memcpy(ndev->dev_addr, address, ETH_ALEN);
>> +
>> + =A0 =A0 =A0 if (!is_valid_ether_addr(ndev->dev_addr))
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 random_ether_addr(ndev->dev_addr);
>> +
>> + =A0 =A0 =A0 /* set up unicast MAC address filter set its mac address *=
/
>> + =A0 =A0 =A0 mutex_lock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_UAW0_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(ndev->dev_addr=
[0]) |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(ndev->dev_addr=
[1] << 8) |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(ndev->dev_addr=
[2] << 16) |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(ndev->dev_addr=
[3] << 24));
>> + =A0 =A0 =A0 /* There are reserved bits in EUAW1
>> + =A0 =A0 =A0 =A0* so don't affect them Set MAC bits [47:32] in EUAW1 */
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_UAW1_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(ndev->dev_addr=
[4] & 0x000000ff) |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(ndev->dev_addr=
[5] << 8));
>> + =A0 =A0 =A0 mutex_unlock(&lp->indirect_mutex);
>> +
>> + =A0 =A0 =A0 return 0;
>> +}
>> +
>> +static void temac_set_multicast_list(struct net_device *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 u32 multi_addr_msw, multi_addr_lsw, val;
>> + =A0 =A0 =A0 int i;
>> +
>> + =A0 =A0 =A0 mutex_lock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 || ndev->mc_count > MULTIC=
AST_CAM_TABLE_NUM) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* =A0 =A0 =A0We must make the kernel re=
alise we had to move
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* =A0 =A0 =A0into promisc mode or we st=
art all out war on
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* =A0 =A0 =A0the cable. If it was a pro=
misc request the
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* =A0 =A0 =A0flag is already set. If no=
t we assert it.
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ndev->flags |=3D IFF_PROMISC;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_indirect_out32(lp, XTE_AFM_OFFSET,
>> XTE_AFM_EPPRM_MASK);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_info(&ndev->dev, "Promiscuous mode ena=
bled.\n");
>> + =A0 =A0 =A0 } else if (ndev->mc_count) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct dev_mc_list *mclist =3D ndev->mc_li=
st;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (i =3D 0; mclist && i < ndev->mc_count=
; i++) {
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (i >=3D MULTICAST_CAM_T=
ABLE_NUM)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 multi_addr_msw =3D ((mclis=
t->dmi_addr[3] << 24) |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 (mclist->dmi_addr[2] << 16) |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 (mclist->dmi_addr[1] << 8) |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 (mclist->dmi_addr[0]));
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_indirect_out32(lp, X=
TE_MAW0_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0multi_addr_msw);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 multi_addr_lsw =3D ((mclis=
t->dmi_addr[5] << 8) |
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 (mclist->dmi_addr[4]) | (i <<
>> 16));
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_indirect_out32(lp, X=
TE_MAW1_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0multi_addr_lsw);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mclist =3D mclist->next;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> + =A0 =A0 =A0 } else {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 val =3D temac_indirect_in32(lp, XTE_AFM_OF=
FSET);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_indirect_out32(lp, XTE_AFM_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0val & ~XTE_AFM_EPPRM_MASK);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_indirect_out32(lp, XTE_MAW0_OFFSET, =
0);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_indirect_out32(lp, XTE_MAW1_OFFSET, =
0);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_info(&ndev->dev, "Promiscuous mode dis=
abled.\n");
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 mutex_unlock(&lp->indirect_mutex);
>> +}
>> +
>> +struct temac_option {
>> + =A0 =A0 =A0 int flg;
>> + =A0 =A0 =A0 u32 opt;
>> + =A0 =A0 =A0 u32 reg;
>> + =A0 =A0 =A0 u32 m_or;
>> + =A0 =A0 =A0 u32 m_and;
>> +} temac_options[] =3D {
>> + =A0 =A0 =A0 /* Turn on jumbo packet support for both Rx and Tx */
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_JUMBO,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_TXC_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3D XTE_TXC_TXJMBO_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_JUMBO,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_RXC1_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_RXC1_RXJMBO_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 /* Turn on VLAN packet support for both Rx and Tx */
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_VLAN,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_TXC_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_TXC_TXVLAN_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_VLAN,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_RXC1_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_RXC1_RXVLAN_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 /* Turn on FCS stripping on receive packets */
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_FCS_STRIP,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_RXC1_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_RXC1_RXFCS_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 /* Turn on FCS insertion on transmit packets */
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_FCS_INSERT,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_TXC_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_TXC_TXFCS_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 /* Turn on length/type field checking on receive packets *=
/
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_LENTYPE_ERR,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_RXC1_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_RXC1_RXLT_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 /* Turn on flow control */
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_FLOW_CONTROL,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_FCC_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_FCC_RXFLO_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 /* Turn on flow control */
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_FLOW_CONTROL,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_FCC_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_FCC_TXFLO_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 /* Turn on promiscuous frame filtering (all frames are rec=
eived
>> ) */
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_PROMISC,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_AFM_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_AFM_EPPRM_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 /* Enable transmitter if not already enabled */
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_TXEN,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_TXC_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_TXC_TXEN_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 /* Enable receiver? */
>> + =A0 =A0 =A0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .opt =3D XTE_OPTION_RXEN,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .reg =3D XTE_RXC1_OFFSET,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .m_or =3DXTE_RXC1_RXEN_MASK,
>> + =A0 =A0 =A0 },
>> + =A0 =A0 =A0 {}
>> +};
>> +
>> +/**
>> + * temac_setoptions
>> + */
>> +static u32 temac_setoptions(struct net_device *ndev, u32 options)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 struct temac_option *tp =3D &temac_options[0];
>> + =A0 =A0 =A0 int reg;
>> +
>> + =A0 =A0 =A0 mutex_lock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 while (tp->opt) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg =3D temac_indirect_in32(lp, tp->reg) &=
 ~tp->m_or;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (options & tp->opt)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg |=3D tp->m_or;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_indirect_out32(lp, tp->reg, reg);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tp++;
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 lp->options |=3D options;
>> + =A0 =A0 =A0 mutex_unlock(&lp->indirect_mutex);
>> +
>> + =A0 =A0 =A0 return (0);
>> +}
>> +
>> +/* Initilize temac */
>> +static void temac_device_reset(struct net_device *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 u32 timeout;
>> + =A0 =A0 =A0 u32 val;
>> +
>> + =A0 =A0 =A0 /* Perform a software reset */
>> +
>> + =A0 =A0 =A0 /* 0x300 host enable bit ? */
>> + =A0 =A0 =A0 /* reset PHY through control register ?:1 */
>> +
>> + =A0 =A0 =A0 dev_dbg(&ndev->dev, "%s()\n", __func__);
>> +
>> + =A0 =A0 =A0 mutex_lock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 /* Reset the receiver and wait for it to finish reset */
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_RXC1_OFFSET, XTE_RXC1_RXRST_M=
ASK);
>> + =A0 =A0 =A0 timeout =3D 1000;
>> + =A0 =A0 =A0 while (temac_indirect_in32(lp, XTE_RXC1_OFFSET) &
>> XTE_RXC1_RXRST_MASK) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 udelay(1);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (--timeout =3D=3D 0) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&ndev->dev,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "temac_dev=
ice_reset RX reset
>> timeout!!\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 /* Reset the transmitter and wait for it to finish reset *=
/
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_TXC_OFFSET, XTE_TXC_TXRST_MAS=
K);
>> + =A0 =A0 =A0 timeout =3D 1000;
>> + =A0 =A0 =A0 while (temac_indirect_in32(lp, XTE_TXC_OFFSET) &
>> XTE_TXC_TXRST_MASK) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 udelay(1);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (--timeout =3D=3D 0) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&ndev->dev,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "temac_dev=
ice_reset TX reset
>> timeout!!\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 /* Disable the receiver */
>> + =A0 =A0 =A0 val =3D temac_indirect_in32(lp, XTE_RXC1_OFFSET);
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_RXC1_OFFSET, val &
>> ~XTE_RXC1_RXEN_MASK);
>> +
>> + =A0 =A0 =A0 /* Reset Local Link (DMA) */
>> + =A0 =A0 =A0 temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
>> + =A0 =A0 =A0 timeout =3D 1000;
>> + =A0 =A0 =A0 while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_R=
ST) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 udelay(1);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (--timeout =3D=3D 0) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&ndev->dev,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "temac_dev=
ice_reset DMA reset
>> timeout!!\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
>> +
>> + =A0 =A0 =A0 temac_dma_bd_init(ndev);
>> +
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_RXC0_OFFSET, 0);
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_RXC1_OFFSET, 0);
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_TXC_OFFSET, 0);
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_FCC_OFFSET, XTE_FCC_RXFLO_MAS=
K);
>> +
>> + =A0 =A0 =A0 mutex_unlock(&lp->indirect_mutex);
>> +
>> + =A0 =A0 =A0 /* Sync default options with HW
>> + =A0 =A0 =A0 =A0* but leave receiver and transmitter disabled. =A0*/
>> + =A0 =A0 =A0 temac_setoptions(ndev,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0lp->options & ~(XTE_OPT=
ION_TXEN |
>> XTE_OPTION_RXEN));
>> +
>> + =A0 =A0 =A0 temac_set_mac_address(ndev, NULL);
>> +
>> + =A0 =A0 =A0 /* Set address filter table */
>> + =A0 =A0 =A0 temac_set_multicast_list(ndev);
>> + =A0 =A0 =A0 if (temac_setoptions(ndev, lp->options))
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&ndev->dev, "Error setting TEMAC o=
ptions\n");
>> +
>> + =A0 =A0 =A0 /* Init Driver variable */
>> + =A0 =A0 =A0 ndev->trans_start =3D 0;
>> +}
>> +
>> +void temac_adjust_link(struct net_device *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 struct phy_device *phy =3D lp->phy_dev;
>> + =A0 =A0 =A0 u32 mii_speed;
>> + =A0 =A0 =A0 int link_state;
>> +
>> + =A0 =A0 =A0 /* hash together the state values to decide if something h=
as
>> changed */
>> + =A0 =A0 =A0 link_state =3D phy->speed | (phy->duplex << 1) | phy->link=
;
>> +
>> + =A0 =A0 =A0 mutex_lock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 if (lp->last_link !=3D link_state) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mii_speed =3D temac_indirect_in32(lp, XTE_=
EMCFG_OFFSET);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mii_speed &=3D ~XTE_EMCFG_LINKSPD_MASK;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 switch (phy->speed) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 case SPEED_1000: mii_speed |=3D XTE_EMCFG_=
LINKSPD_1000;
>> break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 case SPEED_100: mii_speed |=3D XTE_EMCFG_L=
INKSPD_100;
>> break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 case SPEED_10: mii_speed |=3D XTE_EMCFG_LI=
NKSPD_10; break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Write new speed setting out to TEMAC */
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_indirect_out32(lp, XTE_EMCFG_OFFSET,=
 mii_speed);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->last_link =3D link_state;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 phy_print_status(phy);
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 mutex_unlock(&lp->indirect_mutex);
>> +}
>> +
>> +static void temac_start_xmit_done(struct net_device *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 struct cdmac_bd *cur_p;
>> + =A0 =A0 =A0 unsigned int stat =3D 0;
>> +
>> + =A0 =A0 =A0 cur_p =3D &lp->tx_bd_v[lp->tx_bd_ci];
>> + =A0 =A0 =A0 stat =3D cur_p->app0;
>> +
>> + =A0 =A0 =A0 while (stat & STS_CTRL_APP0_CMPLT) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pci_unmap_single(NULL, (unsigned long)cur_=
p->phys,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->len=
, PCI_DMA_TODEVICE);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (cur_p->app4)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_kfree_skb_irq((struct =
sk_buff
>> *)cur_p->app4);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->app0 =3D 0;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ndev->stats.tx_packets++;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ndev->stats.tx_bytes +=3D cur_p->len;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->tx_bd_ci++;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (lp->tx_bd_ci >=3D TX_BD_NUM)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->tx_bd_ci =3D 0;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p =3D &lp->tx_bd_v[lp->tx_bd_ci];
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 stat =3D cur_p->app0;
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 netif_wake_queue(ndev);
>> +}
>> +
>> +static int temac_start_xmit(struct sk_buff *skb, struct net_device
>> *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 struct cdmac_bd *cur_p;
>> + =A0 =A0 =A0 dma_addr_t start_p, tail_p;
>> + =A0 =A0 =A0 int ii;
>> + =A0 =A0 =A0 unsigned long num_frag;
>> + =A0 =A0 =A0 skb_frag_t *frag;
>> +
>> + =A0 =A0 =A0 num_frag =3D skb_shinfo(skb)->nr_frags;
>> + =A0 =A0 =A0 frag =3D &skb_shinfo(skb)->frags[0];
>> + =A0 =A0 =A0 start_p =3D lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd=
_tail;
>> + =A0 =A0 =A0 cur_p =3D &lp->tx_bd_v[lp->tx_bd_tail];
>> +
>> + =A0 =A0 =A0 if (cur_p->app0 & STS_CTRL_APP0_CMPLT) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!netif_queue_stopped(ndev)) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 netif_stop_queue(ndev);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return NETDEV_TX_BUSY;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return NETDEV_TX_BUSY;
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 cur_p->app0 =3D 0;
>> + =A0 =A0 =A0 if (skb->ip_summed =3D=3D CHECKSUM_PARTIAL) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 const struct iphdr *ip =3D ip_hdr(skb);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 int length =3D 0, start, insert =3D 0, hea=
dlen;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 switch (ip->protocol) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 case IPPROTO_TCP:
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 start =3D sizeof(struct ip=
hdr) + ETH_HLEN;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 insert =3D sizeof(struct i=
phdr) + ETH_HLEN + 16;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 length =3D ip->tot_len - s=
izeof(struct iphdr);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 headlen =3D ETH_HLEN + siz=
eof(struct iphdr) +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sizeof=
(struct tcphdr);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 case IPPROTO_UDP:
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 start =3D sizeof(struct ip=
hdr) + ETH_HLEN;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 insert =3D sizeof(struct i=
phdr) + ETH_HLEN + 6;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 length =3D ip->tot_len - s=
izeof(struct iphdr);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 headlen =3D ETH_HLEN + siz=
eof(struct iphdr) +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sizeof=
(struct udphdr);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 default:
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->app1 =3D ((start << 16) | insert);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->app2 =3D csum_tcpudp_magic(ip->sadd=
r, ip->daddr,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 length, ip->protocol,
>> 0);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb->data[insert] =3D 0;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb->data[insert + 1] =3D 0;
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 cur_p->app0 |=3D STS_CTRL_APP0_SOP;
>> + =A0 =A0 =A0 cur_p->len =3D skb_headlen(skb);
>> + =A0 =A0 =A0 cur_p->phys =3D pci_map_single(NULL, skb->data, skb->len,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0PCI_DMA_TODEVICE);
>> + =A0 =A0 =A0 cur_p->app4 =3D (unsigned long)skb;
>> +
>> + =A0 =A0 =A0 for (ii =3D 0; ii < num_frag; ii++) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->tx_bd_tail++;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (lp->tx_bd_tail >=3D TX_BD_NUM)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->tx_bd_tail =3D 0;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p =3D &lp->tx_bd_v[lp->tx_bd_tail];
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->phys =3D pci_map_single(NULL,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (void *)pa=
ge_address(frag->page)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 + frag->pa=
ge_offset,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 frag->size=
, PCI_DMA_TODEVICE);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->len =3D frag->size;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->app0 =3D 0;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 frag++;
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 cur_p->app0 |=3D STS_CTRL_APP0_EOP;
>> +
>> + =A0 =A0 =A0 tail_p =3D lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_=
tail;
>> + =A0 =A0 =A0 lp->tx_bd_tail++;
>> + =A0 =A0 =A0 if (lp->tx_bd_tail >=3D TX_BD_NUM)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->tx_bd_tail =3D 0;
>> +
>> + =A0 =A0 =A0 /* Kick off the transfer */
>> + =A0 =A0 =A0 temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start=
 */
>> +
>> + =A0 =A0 =A0 return 0;
>> +}
>> +
>> +
>> +static void ll_temac_recv(struct net_device *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 struct sk_buff *skb, *new_skb;
>> + =A0 =A0 =A0 unsigned int bdstat;
>> + =A0 =A0 =A0 struct cdmac_bd *cur_p;
>> + =A0 =A0 =A0 dma_addr_t tail_p;
>> + =A0 =A0 =A0 int length;
>> + =A0 =A0 =A0 unsigned long skb_vaddr;
>> + =A0 =A0 =A0 unsigned long flags;
>> +
>> + =A0 =A0 =A0 spin_lock_irqsave(&lp->rx_lock, flags);
>> +
>> + =A0 =A0 =A0 tail_p =3D lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_=
ci;
>> + =A0 =A0 =A0 cur_p =3D &lp->rx_bd_v[lp->rx_bd_ci];
>> +
>> + =A0 =A0 =A0 bdstat =3D cur_p->app0;
>> + =A0 =A0 =A0 while ((bdstat & STS_CTRL_APP0_CMPLT)) {
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb =3D lp->rx_skb[lp->rx_bd_ci];
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 length =3D cur_p->app4;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb_vaddr =3D virt_to_bus(skb->data);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pci_unmap_single(NULL, skb_vaddr, length,
>> PCI_DMA_FROMDEVICE);
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb_put(skb, length);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb->dev =3D ndev;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb->protocol =3D eth_type_trans(skb, ndev=
);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb->ip_summed =3D CHECKSUM_NONE;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 netif_rx(skb);
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ndev->stats.rx_packets++;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ndev->stats.rx_bytes +=3D length;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 new_skb =3D alloc_skb(XTE_MAX_JUMBO_FRAME_=
SIZE +
>> XTE_ALIGN,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 GFP_ATOMIC=
);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (new_skb =3D=3D 0) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&ndev->dev, "no me=
mory for new
>> sk_buff\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 spin_unlock_irqrestore(&lp=
->rx_lock, flags);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb_reserve(new_skb, BUFFER_ALIGN(new_skb-=
>data));
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->app0 =3D STS_CTRL_APP0_IRQONEND;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->phys =3D pci_map_single(NULL, new_s=
kb->data,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0XTE_MAX_JUMBO_FRAME_SIZE,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0PCI_DMA_FROMDEVICE);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p->len =3D XTE_MAX_JUMBO_FRAME_SIZE;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->rx_skb[lp->rx_bd_ci] =3D new_skb;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->rx_bd_ci++;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (lp->rx_bd_ci >=3D RX_BD_NUM)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->rx_bd_ci =3D 0;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cur_p =3D &lp->rx_bd_v[lp->rx_bd_ci];
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 bdstat =3D cur_p->app0;
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p);
>> +
>> + =A0 =A0 =A0 spin_unlock_irqrestore(&lp->rx_lock, flags);
>> +}
>> +
>> +static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
>> +{
>> + =A0 =A0 =A0 struct net_device *ndev =3D _ndev;
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 unsigned int status;
>> +
>> + =A0 =A0 =A0 status =3D temac_dma_in32(lp, TX_IRQ_REG);
>> + =A0 =A0 =A0 temac_dma_out32(lp, TX_IRQ_REG, status);
>> +
>> + =A0 =A0 =A0 if (status & (IRQ_COAL | IRQ_DLY))
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_start_xmit_done(lp->ndev);
>> + =A0 =A0 =A0 if (status & 0x080)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&ndev->dev, "DMA error 0x%x\n", st=
atus);
>> +
>> + =A0 =A0 =A0 return IRQ_HANDLED;
>> +}
>> +
>> +static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev)
>> +{
>> + =A0 =A0 =A0 struct net_device *ndev =3D _ndev;
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 unsigned int status;
>> +
>> + =A0 =A0 =A0 /* Read and clear the status registers */
>> + =A0 =A0 =A0 status =3D temac_dma_in32(lp, RX_IRQ_REG);
>> + =A0 =A0 =A0 temac_dma_out32(lp, RX_IRQ_REG, status);
>> +
>> + =A0 =A0 =A0 if (status & (IRQ_COAL | IRQ_DLY))
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ll_temac_recv(lp->ndev);
>> +
>> + =A0 =A0 =A0 return IRQ_HANDLED;
>> +}
>> +
>> +static int temac_open(struct net_device *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 int rc;
>> +
>> + =A0 =A0 =A0 dev_dbg(&ndev->dev, "temac_open()\n");
>> +
>> + =A0 =A0 =A0 if (lp->phy_node) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 lp->phy_dev =3D of_phy_connect(lp->ndev, l=
p->phy_node,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0temac_adjust_link, 0, 0);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!lp->phy_dev) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(lp->dev, "of_phy_c=
onnect() failed\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 phy_start(lp->phy_dev);
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 rc =3D request_irq(lp->tx_irq, ll_temac_tx_irq, 0, ndev->n=
ame,
>> ndev);
>> + =A0 =A0 =A0 if (rc)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto err_tx_irq;
>> + =A0 =A0 =A0 rc =3D request_irq(lp->rx_irq, ll_temac_rx_irq, 0, ndev->n=
ame,
>> ndev);
>> + =A0 =A0 =A0 if (rc)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto err_rx_irq;
>> +
>> + =A0 =A0 =A0 temac_device_reset(ndev);
>> + =A0 =A0 =A0 return 0;
>> +
>> + err_rx_irq:
>> + =A0 =A0 =A0 free_irq(lp->tx_irq, ndev);
>> + err_tx_irq:
>> + =A0 =A0 =A0 if (lp->phy_dev)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 phy_disconnect(lp->phy_dev);
>> + =A0 =A0 =A0 lp->phy_dev =3D NULL;
>> + =A0 =A0 =A0 dev_err(lp->dev, "request_irq() failed\n");
>> + =A0 =A0 =A0 return rc;
>> +}
>> +
>> +static int temac_stop(struct net_device *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> +
>> + =A0 =A0 =A0 dev_dbg(&ndev->dev, "temac_close()\n");
>> +
>> + =A0 =A0 =A0 free_irq(lp->tx_irq, ndev);
>> + =A0 =A0 =A0 free_irq(lp->rx_irq, ndev);
>> +
>> + =A0 =A0 =A0 if (lp->phy_dev)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 phy_disconnect(lp->phy_dev);
>> + =A0 =A0 =A0 lp->phy_dev =3D NULL;
>> +
>> + =A0 =A0 =A0 return 0;
>> +}
>> +
>> +#ifdef CONFIG_NET_POLL_CONTROLLER
>> +static void
>> +temac_poll_controller(struct net_device *ndev)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> +
>> + =A0 =A0 =A0 disable_irq(lp->tx_irq);
>> + =A0 =A0 =A0 disable_irq(lp->rx_irq);
>> +
>> + =A0 =A0 =A0 ll_temac_rx_irq(lp->tx_irq, lp, 0);
>> + =A0 =A0 =A0 ll_temac_tx_irq(lp->rx_irq, lp, 0);
>> +
>> + =A0 =A0 =A0 enable_irq(lp->tx_irq);
>> + =A0 =A0 =A0 enable_irq(lp->rx_irq);
>> +}
>> +#endif
>> +
>> +static const struct net_device_ops temac_netdev_ops =3D {
>> + =A0 =A0 =A0 .ndo_open =3D temac_open,
>> + =A0 =A0 =A0 .ndo_stop =3D temac_stop,
>> + =A0 =A0 =A0 .ndo_start_xmit =3D temac_start_xmit,
>> + =A0 =A0 =A0 .ndo_set_mac_address =3D temac_set_mac_address,
>> + =A0 =A0 =A0 //.ndo_set_multicast_list =3D temac_set_multicast_list,
>> +#ifdef CONFIG_NET_POLL_CONTROLLER
>> + =A0 =A0 =A0 .ndo_poll_controller =3D temac_poll_controller,
>> +#endif
>> +};
>> +
>> +/*
>> ---------------------------------------------------------------------
>> + * SYSFS device attributes
>> + */
>> +static ssize_t temac_show_llink_regs(struct device *dev,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0struct device_attribute *attr, char
>> *buf)
>> +{
>> + =A0 =A0 =A0 struct net_device *ndev =3D dev_get_drvdata(dev);
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 int i, len =3D 0;
>> +
>> + =A0 =A0 =A0 for (i =3D 0; i < 0x11; i++)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 len +=3D sprintf(buf + len, "%.8x%s", tema=
c_dma_in32(lp,
>> i),
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(i % 8) =3D=
=3D 7 ? "\n" : " ");
>> + =A0 =A0 =A0 len +=3D sprintf(buf + len, "\n");
>> +
>> + =A0 =A0 =A0 return len;
>> +}
>> +
>> +static DEVICE_ATTR(llink_regs, 0440, temac_show_llink_regs, NULL);
>> +
>> +static struct attribute *temac_device_attrs[] =3D {
>> + =A0 =A0 =A0 &dev_attr_llink_regs.attr,
>> + =A0 =A0 =A0 NULL,
>> +};
>> +
>> +static const struct attribute_group temac_attr_group =3D {
>> + =A0 =A0 =A0 .attrs =3D temac_device_attrs,
>> +};
>> +
>> +static int __init
>> +temac_of_probe(struct of_device *op, const struct of_device_id *match)
>> +{
>> + =A0 =A0 =A0 struct device_node *np;
>> + =A0 =A0 =A0 struct temac_local *lp;
>> + =A0 =A0 =A0 struct net_device *ndev;
>> + =A0 =A0 =A0 const void *addr;
>> + =A0 =A0 =A0 int size, rc =3D 0;
>> + =A0 =A0 =A0 unsigned int dcrs;
>> +
>> + =A0 =A0 =A0 /* Init network device structure */
>> + =A0 =A0 =A0 ndev =3D alloc_etherdev(sizeof(*lp));
>> + =A0 =A0 =A0 if (!ndev) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "could not allocate devi=
ce.\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 ether_setup(ndev);
>> + =A0 =A0 =A0 dev_set_drvdata(&op->dev, ndev);
>> + =A0 =A0 =A0 SET_NETDEV_DEV(ndev, &op->dev);
>> + =A0 =A0 =A0 ndev->flags &=3D ~IFF_MULTICAST; =A0/* clear multicast */
>> + =A0 =A0 =A0 ndev->features =3D NETIF_F_SG | NETIF_F_FRAGLIST;
>> + =A0 =A0 =A0 ndev->netdev_ops =3D &temac_netdev_ops;
>> +#if 0
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_IP_CSUM; /* Can checksum TCP/U=
DP over
>> IPv4. */
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_HW_CSUM; /* Can checksum all t=
he
>> packets. */
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_IPV6_CSUM; /* Can checksum IPV=
6
>> TCP/UDP */
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_HIGHDMA; /* Can DMA to high me=
mory. */
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_HW_VLAN_TX; /* Transmit VLAN h=
w accel
>> */
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_HW_VLAN_RX; /* Receive VLAN hw
>> acceleration */
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_HW_VLAN_FILTER; /* Receive VLA=
N
>> filtering */
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_VLAN_CHALLENGED; /* cannot han=
dle VLAN
>> pkts */
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_GSO; /* Enable software GSO. *=
/
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_MULTI_QUEUE; /* Has multiple T=
X/RX
>> queues */
>> + =A0 =A0 =A0 ndev->features |=3D NETIF_F_LRO; /* large receive offload =
*/
>> +#endif
>> +
>> + =A0 =A0 =A0 /* setup temac private info structure */
>> + =A0 =A0 =A0 lp =3D netdev_priv(ndev);
>> + =A0 =A0 =A0 lp->ndev =3D ndev;
>> + =A0 =A0 =A0 lp->dev =3D &op->dev;
>> + =A0 =A0 =A0 lp->options =3D XTE_OPTION_DEFAULTS;
>> + =A0 =A0 =A0 spin_lock_init(&lp->rx_lock);
>> + =A0 =A0 =A0 mutex_init(&lp->indirect_mutex);
>> +
>> + =A0 =A0 =A0 /* map device registers */
>> + =A0 =A0 =A0 lp->regs =3D of_iomap(op->node, 0);
>> + =A0 =A0 =A0 if (!lp->regs) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "could not map temac reg=
s.\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto nodev;
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 /* Find the DMA node, map the DMA registers, and decode th=
e DMA
>> IRQs */
>> + =A0 =A0 =A0 np =3D of_parse_phandle(op->node, "llink-connected", 0);
>> + =A0 =A0 =A0 if (!np) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "could not find DMA node=
\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto nodev;
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 dcrs =3D dcr_resource_start(np, 0);
>> + =A0 =A0 =A0 if (dcrs =3D=3D 0) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "could not get DMA regis=
ter
>> address\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto nodev;;
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 lp->sdma_dcrs =3D dcr_map(np, dcrs, dcr_resource_len(np, 0=
));
>> + =A0 =A0 =A0 dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
>> +
>> + =A0 =A0 =A0 lp->rx_irq =3D irq_of_parse_and_map(np, 0);
>> + =A0 =A0 =A0 lp->tx_irq =3D irq_of_parse_and_map(np, 1);
>> + =A0 =A0 =A0 if (!lp->rx_irq || !lp->tx_irq) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "could not determine irq=
s\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rc =3D -ENOMEM;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto nodev;
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 of_node_put(np); /* Finished with the DMA node; drop the
>> reference */
>> +
>> + =A0 =A0 =A0 /* Retrieve the MAC address */
>> + =A0 =A0 =A0 addr =3D of_get_property(op->node, "local-mac-address", &s=
ize);
>> + =A0 =A0 =A0 if ((!addr) || (size !=3D 6)) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&op->dev, "could not find MAC addr=
ess\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rc =3D -ENODEV;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto nodev;
>> + =A0 =A0 =A0 }
>> + =A0 =A0 =A0 temac_set_mac_address(ndev, (void *)addr);
>> +
>> + =A0 =A0 =A0 rc =3D temac_mdio_setup(lp, op->node);
>> + =A0 =A0 =A0 if (rc)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_warn(&op->dev, "error registering MDIO=
 bus\n");
>> +
>> + =A0 =A0 =A0 lp->phy_node =3D of_parse_phandle(op->node, "phy-handle", =
0);
>> + =A0 =A0 =A0 if (lp->phy_node)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_dbg(lp->dev, "using PHY node %s (%p)\n=
",
>> np->full_name, np);
>> +
>> + =A0 =A0 =A0 /* Add the device attributes */
>> + =A0 =A0 =A0 rc =3D sysfs_create_group(&lp->dev->kobj, &temac_attr_grou=
p);
>> + =A0 =A0 =A0 if (rc) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(lp->dev, "Error creating sysfs fil=
es\n");
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto nodev;
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 rc =3D register_netdev(lp->ndev);
>> + =A0 =A0 =A0 if (rc) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(lp->dev, "register_netdev() error =
(%i)\n", rc);
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto err_register_ndev;
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 return 0;
>> +
>> + err_register_ndev:
>> + =A0 =A0 =A0 sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
>> + nodev:
>> + =A0 =A0 =A0 free_netdev(ndev);
>> + =A0 =A0 =A0 ndev =3D NULL;
>> + =A0 =A0 =A0 return rc;
>> +}
>> +
>> +static int __devexit temac_of_remove(struct of_device *op)
>> +{
>> + =A0 =A0 =A0 struct net_device *ndev =3D dev_get_drvdata(&op->dev);
>> + =A0 =A0 =A0 struct temac_local *lp =3D netdev_priv(ndev);
>> +
>> + =A0 =A0 =A0 temac_mdio_teardown(lp);
>> + =A0 =A0 =A0 unregister_netdev(ndev);
>> + =A0 =A0 =A0 sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
>> + =A0 =A0 =A0 if (lp->phy_node)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_node_put(lp->phy_node);
>> + =A0 =A0 =A0 lp->phy_node =3D NULL;
>> + =A0 =A0 =A0 dev_set_drvdata(&op->dev, NULL);
>> + =A0 =A0 =A0 free_netdev(ndev);
>> + =A0 =A0 =A0 return 0;
>> +}
>> +
>> +static struct of_device_id temac_of_match[] __devinitdata =3D {
>> + =A0 =A0 =A0 { .compatible =3D "xlnx,xps-ll-temac-1.01.b", },
>> + =A0 =A0 =A0 {},
>> +};
>> +MODULE_DEVICE_TABLE(of, temac_of_match);
>> +
>> +static struct of_platform_driver temac_of_driver =3D {
>> + =A0 =A0 =A0 .match_table =3D temac_of_match,
>> + =A0 =A0 =A0 .probe =3D temac_of_probe,
>> + =A0 =A0 =A0 .remove =3D __devexit_p(temac_of_remove),
>> + =A0 =A0 =A0 .driver =3D {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .owner =3D THIS_MODULE,
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .name =3D "xilinx_temac",
>> + =A0 =A0 =A0 },
>> +};
>> +
>> +static int __init temac_init(void)
>> +{
>> + =A0 =A0 =A0 return of_register_platform_driver(&temac_of_driver);
>> +}
>> +module_init(temac_init);
>> +
>> +static void __exit temac_exit(void)
>> +{
>> + =A0 =A0 =A0 of_unregister_platform_driver(&temac_of_driver);
>> +}
>> +module_exit(temac_exit);
>> +
>> +MODULE_DESCRIPTION("Xilinx LL_TEMAC Ethernet driver");
>> +MODULE_AUTHOR("Yoshio Kashiwagi");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/net/xilinx_temac.h b/drivers/net/xilinx_temac.h
>> new file mode 100644
>> index 0000000..4bc340c
>> --- /dev/null
>> +++ b/drivers/net/xilinx_temac.h
>> @@ -0,0 +1,374 @@
>> +
>> +#ifndef XILINX_TEMAC_H
>> +#define XILINX_TEMAC_H
>> +
>> +#include <linux/netdevice.h>
>> +#include <linux/of.h>
>> +#include <linux/spinlock.h>
>> +#include <asm/dcr.h>
>> +#include <asm/dcr-regs.h>
>> +
>> +/* packet size info */
>> +#define XTE_HDR_SIZE =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 14 =A0 =A0 =A0=
/* size of Ethernet
>> header */
>> +#define XTE_TRL_SIZE =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 4 =A0 =A0 =A0 =
/* size of Ethernet
>> trailer (FCS) */
>> +#define XTE_JUMBO_MTU =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A09000
>> +#define XTE_MAX_JUMBO_FRAME_SIZE =A0 =A0 =A0 (XTE_JUMBO_MTU + XTE_HDR_S=
IZE +
>> XTE_TRL_SIZE)
>> +
>> +/* =A0Configuration options */
>> +
>> +/* =A0Accept all incoming packets.
>> + * =A0This option defaults to disabled (cleared) */
>> +#define XTE_OPTION_PROMISC =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(=
1 << 0)
>> +/* =A0Jumbo frame support for Tx & Rx.
>> + * =A0This option defaults to disabled (cleared) */
>> +#define XTE_OPTION_JUMBO =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0(1 << 1)
>> +/* =A0VLAN Rx & Tx frame support.
>> + * =A0This option defaults to disabled (cleared) */
>> +#define XTE_OPTION_VLAN =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 (1 << 2)
>> +/* =A0Enable recognition of flow control frames on Rx
>> + * =A0This option defaults to enabled (set) */
>> +#define XTE_OPTION_FLOW_CONTROL =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 4=
)
>> +/* =A0Strip FCS and PAD from incoming frames.
>> + * =A0Note: PAD from VLAN frames is not stripped.
>> + * =A0This option defaults to disabled (set) */
>> +#define XTE_OPTION_FCS_STRIP =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 =
<< 5)
>> +/* =A0Generate FCS field and add PAD automatically for outgoing frames.
>> + * =A0This option defaults to enabled (set) */
>> +#define XTE_OPTION_FCS_INSERT =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 <<=
 6)
>> +/* =A0Enable Length/Type error checking for incoming frames. When this
>> option is
>> +set, the MAC will filter frames that have a mismatched type/length
>> field
>> +and if XTE_OPTION_REPORT_RXERR is set, the user is notified when these
>> +types of frames are encountered. When this option is cleared, the MAC
>> will
>> +allow these types of frames to be received.
>> +This option defaults to enabled (set) */
>> +#define XTE_OPTION_LENTYPE_ERR =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 <<=
 7)
>> +/* =A0Enable the transmitter.
>> + * =A0This option defaults to enabled (set) */
>> +#define XTE_OPTION_TXEN =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 (1 << 11)
>> +/* =A0Enable the receiver
>> +* =A0 This option defaults to enabled (set) */
>> +#define XTE_OPTION_RXEN =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 (1 << 12)
>> +
>> +/* =A0Default options set when device is initialized or reset */
>> +#define XTE_OPTION_DEFAULTS =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 \
>> + =A0 =A0 =A0 (XTE_OPTION_TXEN | =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0\
>> + =A0 =A0 =A0 =A0XTE_OPTION_FLOW_CONTROL | =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0\
>> + =A0 =A0 =A0 =A0XTE_OPTION_RXEN)
>> +
>> +/* XPS_LL_TEMAC SDMA registers definition */
>> +
>> +#define TX_NXTDESC_PTR =A0 =A0 =A00x00 =A0 =A0 =A0 =A0 =A0 =A0/* r */
>> +#define TX_CURBUF_ADDR =A0 =A0 =A00x01 =A0 =A0 =A0 =A0 =A0 =A0/* r */
>> +#define TX_CURBUF_LENGTH =A0 =A00x02 =A0 =A0 =A0 =A0 =A0 =A0/* r */
>> +#define TX_CURDESC_PTR =A0 =A0 =A00x03 =A0 =A0 =A0 =A0 =A0 =A0/* rw */
>> +#define TX_TAILDESC_PTR =A0 =A0 0x04 =A0 =A0 =A0 =A0 =A0 =A0/* rw */
>> +#define TX_CHNL_CTRL =A0 =A0 =A0 =A00x05 =A0 =A0 =A0 =A0 =A0 =A0/* rw *=
/
>> +/*
>> + 0:7 =A0 =A0 =A024:31 =A0 =A0 =A0 IRQTimeout
>> + 8:15 =A0 =A0 16:23 =A0 =A0 =A0 IRQCount
>> + 16:20 =A0 =A011:15 =A0 =A0 =A0 Reserved
>> + 21 =A0 =A0 =A0 10 =A0 =A0 =A0 =A0 =A00
>> + 22 =A0 =A0 =A0 9 =A0 =A0 =A0 =A0 =A0 UseIntOnEnd
>> + 23 =A0 =A0 =A0 8 =A0 =A0 =A0 =A0 =A0 LdIRQCnt
>> + 24 =A0 =A0 =A0 7 =A0 =A0 =A0 =A0 =A0 IRQEn
>> + 25:28 =A0 =A03:6 =A0 =A0 =A0 =A0 Reserved
>> + 29 =A0 =A0 =A0 2 =A0 =A0 =A0 =A0 =A0 IrqErrEn
>> + 30 =A0 =A0 =A0 1 =A0 =A0 =A0 =A0 =A0 IrqDlyEn
>> + 31 =A0 =A0 =A0 0 =A0 =A0 =A0 =A0 =A0 IrqCoalEn
>> +*/
>> +#define CHNL_CTRL_IRQ_IOE =A0 =A0 =A0 (1 << 9)
>> +#define CHNL_CTRL_IRQ_EN =A0 =A0 =A0 =A0(1 << 7)
>> +#define CHNL_CTRL_IRQ_ERR_EN =A0 =A0(1 << 2)
>> +#define CHNL_CTRL_IRQ_DLY_EN =A0 =A0(1 << 1)
>> +#define CHNL_CTRL_IRQ_COAL_EN =A0 (1 << 0)
>> +#define TX_IRQ_REG =A0 =A0 =A0 =A0 =A00x06 =A0 =A0 =A0 =A0 =A0 =A0/* rw=
 */
>> +/*
>> + =A00:7 =A0 =A0 =A024:31 =A0 =A0 =A0 DltTmrValue
>> + 8:15 =A0 =A0 16:23 =A0 =A0 =A0 ClscCntrValue
>> + 16:17 =A0 =A014:15 =A0 =A0 =A0 Reserved
>> + 18:21 =A0 =A010:13 =A0 =A0 =A0 ClscCnt
>> + 22:23 =A0 =A08:9 =A0 =A0 =A0 =A0 DlyCnt
>> + 24:28 =A0 =A03::7 =A0 =A0 =A0 =A0Reserved
>> + 29 =A0 =A0 =A0 2 =A0 =A0 =A0 =A0 =A0 ErrIrq
>> + 30 =A0 =A0 =A0 1 =A0 =A0 =A0 =A0 =A0 DlyIrq
>> + 31 =A0 =A0 =A0 0 =A0 =A0 =A0 =A0 =A0 CoalIrq
>> + */
>> +#define TX_CHNL_STS =A0 =A0 =A0 =A0 0x07 =A0 =A0 =A0 =A0 =A0 =A0/* r */
>> +/*
>> + =A0 0:9 =A0 =A0 =A022:31 =A0 Reserved
>> + 10 =A0 =A0 =A0 21 =A0 =A0 =A0TailPErr
>> + 11 =A0 =A0 =A0 20 =A0 =A0 =A0CmpErr
>> + 12 =A0 =A0 =A0 19 =A0 =A0 =A0AddrErr
>> + 13 =A0 =A0 =A0 18 =A0 =A0 =A0NxtPErr
>> + 14 =A0 =A0 =A0 17 =A0 =A0 =A0CurPErr
>> + 15 =A0 =A0 =A0 16 =A0 =A0 =A0BsyWr
>> + 16:23 =A0 =A08:15 =A0 =A0Reserved
>> + 24 =A0 =A0 =A0 7 =A0 =A0 =A0 Error
>> + 25 =A0 =A0 =A0 6 =A0 =A0 =A0 IOE
>> + 26 =A0 =A0 =A0 5 =A0 =A0 =A0 SOE
>> + 27 =A0 =A0 =A0 4 =A0 =A0 =A0 Cmplt
>> + 28 =A0 =A0 =A0 3 =A0 =A0 =A0 SOP
>> + 29 =A0 =A0 =A0 2 =A0 =A0 =A0 EOP
>> + 30 =A0 =A0 =A0 1 =A0 =A0 =A0 EngBusy
>> + 31 =A0 =A0 =A0 0 =A0 =A0 =A0 Reserved
>> +*/
>> +
>> +#define RX_NXTDESC_PTR =A0 =A0 =A00x08 =A0 =A0 =A0 =A0 =A0 =A0/* r */
>> +#define RX_CURBUF_ADDR =A0 =A0 =A00x09 =A0 =A0 =A0 =A0 =A0 =A0/* r */
>> +#define RX_CURBUF_LENGTH =A0 =A00x0a =A0 =A0 =A0 =A0 =A0 =A0/* r */
>> +#define RX_CURDESC_PTR =A0 =A0 =A00x0b =A0 =A0 =A0 =A0 =A0 =A0/* rw */
>> +#define RX_TAILDESC_PTR =A0 =A0 0x0c =A0 =A0 =A0 =A0 =A0 =A0/* rw */
>> +#define RX_CHNL_CTRL =A0 =A0 =A0 =A00x0d =A0 =A0 =A0 =A0 =A0 =A0/* rw *=
/
>> +/*
>> + 0:7 =A0 =A0 =A024:31 =A0 =A0 =A0 IRQTimeout
>> + 8:15 =A0 =A0 16:23 =A0 =A0 =A0 IRQCount
>> + 16:20 =A0 =A011:15 =A0 =A0 =A0 Reserved
>> + 21 =A0 =A0 =A0 10 =A0 =A0 =A0 =A0 =A00
>> + 22 =A0 =A0 =A0 9 =A0 =A0 =A0 =A0 =A0 UseIntOnEnd
>> + 23 =A0 =A0 =A0 8 =A0 =A0 =A0 =A0 =A0 LdIRQCnt
>> + 24 =A0 =A0 =A0 7 =A0 =A0 =A0 =A0 =A0 IRQEn
>> + 25:28 =A0 =A03:6 =A0 =A0 =A0 =A0 Reserved
>> + 29 =A0 =A0 =A0 2 =A0 =A0 =A0 =A0 =A0 IrqErrEn
>> + 30 =A0 =A0 =A0 1 =A0 =A0 =A0 =A0 =A0 IrqDlyEn
>> + 31 =A0 =A0 =A0 0 =A0 =A0 =A0 =A0 =A0 IrqCoalEn
>> + */
>> +#define RX_IRQ_REG =A0 =A0 =A0 =A0 =A00x0e =A0 =A0 =A0 =A0 =A0 =A0/* rw=
 */
>> +#define IRQ_COAL =A0 =A0 =A0 =A0(1 << 0)
>> +#define IRQ_DLY =A0 =A0 =A0 =A0 (1 << 1)
>> +#define IRQ_ERR =A0 =A0 =A0 =A0 (1 << 2)
>> +#define IRQ_DMAERR =A0 =A0 =A0(1 << 7) =A0 =A0 =A0 =A0 =A0 =A0/* this i=
s not documented
>> ??? */
>> +/*
>> + 0:7 =A0 =A0 =A024:31 =A0 =A0 =A0 DltTmrValue
>> + 8:15 =A0 =A0 16:23 =A0 =A0 =A0 ClscCntrValue
>> + 16:17 =A0 =A014:15 =A0 =A0 =A0 Reserved
>> + 18:21 =A0 =A010:13 =A0 =A0 =A0 ClscCnt
>> + 22:23 =A0 =A08:9 =A0 =A0 =A0 =A0 DlyCnt
>> + 24:28 =A0 =A03::7 =A0 =A0 =A0 =A0Reserved
>> +*/
>> +#define RX_CHNL_STS =A0 =A0 =A0 =A0 0x0f =A0 =A0 =A0 =A0/* r */
>> +#define CHNL_STS_ENGBUSY =A0 =A0(1 << 1)
>> +#define CHNL_STS_EOP =A0 =A0 =A0 =A0(1 << 2)
>> +#define CHNL_STS_SOP =A0 =A0 =A0 =A0(1 << 3)
>> +#define CHNL_STS_CMPLT =A0 =A0 =A0(1 << 4)
>> +#define CHNL_STS_SOE =A0 =A0 =A0 =A0(1 << 5)
>> +#define CHNL_STS_IOE =A0 =A0 =A0 =A0(1 << 6)
>> +#define CHNL_STS_ERR =A0 =A0 =A0 =A0(1 << 7)
>> +
>> +#define CHNL_STS_BSYWR =A0 =A0 =A0(1 << 16)
>> +#define CHNL_STS_CURPERR =A0 =A0(1 << 17)
>> +#define CHNL_STS_NXTPERR =A0 =A0(1 << 18)
>> +#define CHNL_STS_ADDRERR =A0 =A0(1 << 19)
>> +#define CHNL_STS_CMPERR =A0 =A0 (1 << 20)
>> +#define CHNL_STS_TAILERR =A0 =A0(1 << 21)
>> +/*
>> + 0:9 =A0 =A0 =A022:31 =A0 Reserved
>> + 10 =A0 =A0 =A0 21 =A0 =A0 =A0TailPErr
>> + 11 =A0 =A0 =A0 20 =A0 =A0 =A0CmpErr
>> + 12 =A0 =A0 =A0 19 =A0 =A0 =A0AddrErr
>> + 13 =A0 =A0 =A0 18 =A0 =A0 =A0NxtPErr
>> + 14 =A0 =A0 =A0 17 =A0 =A0 =A0CurPErr
>> + 15 =A0 =A0 =A0 16 =A0 =A0 =A0BsyWr
>> + 16:23 =A0 =A08:15 =A0 =A0Reserved
>> + 24 =A0 =A0 =A0 7 =A0 =A0 =A0 Error
>> + 25 =A0 =A0 =A0 6 =A0 =A0 =A0 IOE
>> + 26 =A0 =A0 =A0 5 =A0 =A0 =A0 SOE
>> + 27 =A0 =A0 =A0 4 =A0 =A0 =A0 Cmplt
>> + 28 =A0 =A0 =A0 3 =A0 =A0 =A0 SOP
>> + 29 =A0 =A0 =A0 2 =A0 =A0 =A0 EOP
>> + 30 =A0 =A0 =A0 1 =A0 =A0 =A0 EngBusy
>> + 31 =A0 =A0 =A0 0 =A0 =A0 =A0 Reserved
>> +*/
>> +
>> +#define DMA_CONTROL_REG =A0 =A0 =A0 =A0 =A0 =A0 0x10 =A0 =A0 =A0 =A0 =
=A0 =A0/* rw */
>> +#define DMA_CONTROL_RST =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 0)
>> +#define DMA_TAIL_ENABLE =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 2)
>> +
>> +/* XPS_LL_TEMAC direct registers definition */
>> +
>> +#define XTE_RAF0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x00
>> +#define RAF0_RST =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 0=
)
>> +#define RAF0_MCSTREJ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 1)
>> +#define RAF0_BCSTREJ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 2)
>> +#define XTE_TPF0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x04
>> +#define XTE_IFGP0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 0x08
>> +#define XTE_ISR0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x0c
>> +#define ISR0_HARDACSCMPLT =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 0)
>> +#define ISR0_AUTONEG =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 1)
>> +#define ISR0_RXCMPLT =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 2)
>> +#define ISR0_RXREJ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 3)
>> +#define ISR0_RXFIFOOVR =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 4)
>> +#define ISR0_TXCMPLT =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 5)
>> +#define ISR0_RXDCMLCK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 6)
>> +
>> +#define XTE_IPR0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x10
>> +#define XTE_IER0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x14
>> +
>> +#define XTE_MSW0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x20
>> +#define XTE_LSW0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x24
>> +#define XTE_CTL0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x28
>> +#define XTE_RDY0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x2c
>> +
>> +#define XTE_RSE_MIIM_RR_MASK =A0 =A0 =A00x0002
>> +#define XTE_RSE_MIIM_WR_MASK =A0 =A0 =A00x0004
>> +#define XTE_RSE_CFG_RR_MASK =A0 =A0 =A0 0x0020
>> +#define XTE_RSE_CFG_WR_MASK =A0 =A0 =A0 0x0040
>> +#define XTE_RDY0_HARD_ACS_RDY_MASK =A0(0x10000)
>> +
>> +/* XPS_LL_TEMAC indirect registers offset definition */
>> +
>> +#define =A0 =A0 =A0 =A0XTE_RXC0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
0x00000200 /* Rx
>> configuration word 0 */
>> +#define =A0 =A0 =A0 =A0XTE_RXC1_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
0x00000240 /* Rx
>> configuration word 1 */
>> +#define XTE_RXC1_RXRST_MASK =A0 =A0 =A0 =A0 =A0 =A0(1 << 31) =A0/* Rece=
iver reset */
>> +#define XTE_RXC1_RXJMBO_MASK =A0 =A0 =A0 =A0 =A0 (1 << 30) =A0/* Jumbo =
frame enable
>> */
>> +#define XTE_RXC1_RXFCS_MASK =A0 =A0 =A0 =A0 =A0 =A0(1 << 29) =A0/* FCS =
not stripped
>> */
>> +#define XTE_RXC1_RXEN_MASK =A0 =A0 =A0 =A0 =A0 =A0 (1 << 28) =A0/* Rece=
iver enable */
>> +#define XTE_RXC1_RXVLAN_MASK =A0 =A0 =A0 =A0 =A0 (1 << 27) =A0/* VLAN e=
nable */
>> +#define XTE_RXC1_RXHD_MASK =A0 =A0 =A0 =A0 =A0 =A0 (1 << 26) =A0/* Half=
 duplex */
>> +#define XTE_RXC1_RXLT_MASK =A0 =A0 =A0 =A0 =A0 =A0 (1 << 25) =A0/* Leng=
th/type check
>> disable */
>> +
>> +#define XTE_TXC_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x00000280 /* =
=A0Tx configuration
>> */
>> +#define XTE_TXC_TXRST_MASK =A0 =A0 =A0 =A0 =A0 =A0 (1 << 31) =A0/* Tran=
smitter reset
>> */
>> +#define XTE_TXC_TXJMBO_MASK =A0 =A0 =A0 =A0 =A0 =A0(1 << 30) =A0/* Jumb=
o frame enable
>> */
>> +#define XTE_TXC_TXFCS_MASK =A0 =A0 =A0 =A0 =A0 =A0 (1 << 29) =A0/* Gene=
rate FCS */
>> +#define XTE_TXC_TXEN_MASK =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 28) =A0/* Tr=
ansmitter enable
>> */
>> +#define XTE_TXC_TXVLAN_MASK =A0 =A0 =A0 =A0 =A0 =A0(1 << 27) =A0/* VLAN=
 enable */
>> +#define XTE_TXC_TXHD_MASK =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 26) =A0/* Ha=
lf duplex */
>> +
>> +#define XTE_FCC_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x000002C0 /* Fl=
ow control
>> config */
>> +#define XTE_FCC_RXFLO_MASK =A0 =A0 =A0 =A0 =A0 =A0 (1 << 29) =A0/* Rx f=
low control
>> enable */
>> +#define XTE_FCC_TXFLO_MASK =A0 =A0 =A0 =A0 =A0 =A0 (1 << 30) =A0/* Tx f=
low control
>> enable */
>> +
>> +#define XTE_EMCFG_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x00000300 /* EMAC=
 configuration
>> */
>> +#define XTE_EMCFG_LINKSPD_MASK =A0 =A0 =A0 =A0 0xC0000000 /* Link speed=
 */
>> +#define XTE_EMCFG_HOSTEN_MASK =A0 =A0 =A0 =A0 =A0(1 << 26) =A0/* Host i=
nterface
>> enable */
>> +#define XTE_EMCFG_LINKSPD_10 =A0 =A0 =A0 =A0 =A0 0x00000000 /* 10 Mbit
>> LINKSPD_MASK */
>> +#define XTE_EMCFG_LINKSPD_100 =A0 =A0 =A0 =A0 =A0(1 << 30) =A0/* 100 Mb=
it
>> LINKSPD_MASK */
>> +#define XTE_EMCFG_LINKSPD_1000 =A0 =A0 =A0 =A0 (1 << 31) =A0/* 1000 Mbi=
t
>> LINKSPD_MASK */
>> +
>> +#define XTE_GMIC_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
0x00000320 /*
>> RGMII/SGMII config */
>> +#define XTE_MC_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A00x00000340 /* =
MDIO configuration
>> */
>> +#define XTE_UAW0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
0x00000380 /* Unicast
>> address word 0 */
>> +#define XTE_UAW1_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
0x00000384 /* Unicast
>> address word 1 */
>> +
>> +#define XTE_MAW0_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
0x00000388 /* Multicast
>> addr word 0 */
>> +#define XTE_MAW1_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
0x0000038C /* Multicast
>> addr word 1 */
>> +#define XTE_AFM_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x00000390 /* Pr=
omiscuous mode
>> */
>> +#define XTE_AFM_EPPRM_MASK =A0 =A0 =A0 =A0 =A0 =A0 (1 << 31) =A0/* Prom=
iscuous mode
>> enable */
>> +
>> +/* Interrupt Request status */
>> +#define XTE_TIS_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x000003A0
>> +#define TIS_FRIS =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 0)
>> +#define TIS_MRIS =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 1)
>> +#define TIS_MWIS =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 2)
>> +#define TIS_ARIS =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 3)
>> +#define TIS_AWIS =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 4)
>> +#define TIS_CRIS =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 5)
>> +#define TIS_CWIS =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 6)
>> +
>> +#define XTE_TIE_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x000003A4 /* In=
terrupt enable
>> */
>> +
>> +/** =A0MII Mamagement Control register (MGTCR) */
>> +#define XTE_MGTDR_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x000003B0 /* MII =
data */
>> +#define XTE_MIIMAI_OFFSET =A0 =A0 =A0 =A0 =A0 =A0 =A00x000003B4 /* MII =
control */
>> +
>> +#define CNTLREG_WRITE_ENABLE_MASK =A0 0x8000
>> +#define CNTLREG_EMAC1SEL_MASK =A0 =A0 =A0 0x0400
>> +#define CNTLREG_ADDRESSCODE_MASK =A0 =A00x03ff
>> +
>> +/* CDMAC descriptor status bit definitions */
>> +
>> +#define STS_CTRL_APP0_ERR =A0 =A0 =A0 =A0 (1 << 31)
>> +#define STS_CTRL_APP0_IRQONEND =A0 =A0(1 << 30)
>> +/* undoccumented */
>> +#define STS_CTRL_APP0_STOPONEND =A0 (1 << 29)
>> +#define STS_CTRL_APP0_CMPLT =A0 =A0 =A0 (1 << 28)
>> +#define STS_CTRL_APP0_SOP =A0 =A0 =A0 =A0 (1 << 27)
>> +#define STS_CTRL_APP0_EOP =A0 =A0 =A0 =A0 (1 << 26)
>> +#define STS_CTRL_APP0_ENGBUSY =A0 =A0 (1 << 25)
>> +/* undocumented */
>> +#define STS_CTRL_APP0_ENGRST =A0 =A0 =A0(1 << 24)
>> +
>> +#define TX_CONTROL_CALC_CSUM_MASK =A0 1
>> +
>> +#define XTE_ALIGN =A0 =A0 =A0 32
>> +#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN)
>> +
>> +#define MULTICAST_CAM_TABLE_NUM 4
>> +
>> +/* TX/RX CURDESC_PTR points to first descriptor */
>> +/* TX/RX TAILDESC_PTR points to last descriptor in linked list */
>> +
>> +/**
>> + * struct cdmac_bd - LocalLink buffer descriptor format
>> + *
>> + * app0 bits:
>> + * =A0 =A0 0 =A0 =A0Error
>> + * =A0 =A0 1 =A0 =A0IrqOnEnd =A0 =A0generate an interrupt at completion=
 of DMA =A0op
>> + * =A0 =A0 2 =A0 =A0reserved
>> + * =A0 =A0 3 =A0 =A0completed =A0 Current descriptor completed
>> + * =A0 =A0 4 =A0 =A0SOP =A0 =A0 =A0 =A0 TX - marks first desc/ RX marks=
 first desct
>> + * =A0 =A0 5 =A0 =A0EOP =A0 =A0 =A0 =A0 TX marks last desc/RX marks las=
t desc
>> + * =A0 =A0 6 =A0 =A0EngBusy =A0 =A0 DMA is processing
>> + * =A0 =A0 7 =A0 =A0reserved
>> + * =A0 =A0 8:31 application specific
>> + */
>> +struct cdmac_bd {
>> + =A0 =A0 =A0 u32 next; =A0 =A0 =A0 /* Physical address of next buffer d=
escriptor */
>> + =A0 =A0 =A0 u32 phys;
>> + =A0 =A0 =A0 u32 len;
>> + =A0 =A0 =A0 u32 app0;
>> + =A0 =A0 =A0 u32 app1; =A0 =A0 =A0 /* TX start << 16 | insert */
>> + =A0 =A0 =A0 u32 app2; =A0 =A0 =A0 /* TX csum */
>> + =A0 =A0 =A0 u32 app3;
>> + =A0 =A0 =A0 u32 app4; =A0 =A0 =A0 /* skb for TX length for RX */
>> +};
>> +
>> +struct temac_local {
>> + =A0 =A0 =A0 struct net_device *ndev;
>> + =A0 =A0 =A0 struct device *dev;
>> +
>> + =A0 =A0 =A0 /* Connection to PHY device */
>> + =A0 =A0 =A0 struct phy_device *phy_dev; =A0 =A0 /* Pointer to PHY devi=
ce */
>> + =A0 =A0 =A0 struct device_node *phy_node;
>> +
>> + =A0 =A0 =A0 /* MDIO bus data */
>> + =A0 =A0 =A0 struct mii_bus *mii_bus; =A0 =A0 =A0 =A0/* MII bus referen=
ce */
>> + =A0 =A0 =A0 int mdio_irqs[PHY_MAX_ADDR]; =A0 =A0/* IRQs table for MDIO=
 bus */
>> +
>> + =A0 =A0 =A0 /* IO registers and IRQs */
>> + =A0 =A0 =A0 void __iomem *regs;
>> + =A0 =A0 =A0 dcr_host_t sdma_dcrs;
>> + =A0 =A0 =A0 int tx_irq;
>> + =A0 =A0 =A0 int rx_irq;
>> + =A0 =A0 =A0 int emac_num;
>> +
>> + =A0 =A0 =A0 struct sk_buff **rx_skb;
>> + =A0 =A0 =A0 spinlock_t rx_lock;
>> + =A0 =A0 =A0 struct mutex indirect_mutex;
>> + =A0 =A0 =A0 u32 options; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Cur=
rent options word */
>> + =A0 =A0 =A0 int last_link;
>> +
>> + =A0 =A0 =A0 /* Buffer descriptors */
>> + =A0 =A0 =A0 struct cdmac_bd *tx_bd_v;
>> + =A0 =A0 =A0 dma_addr_t tx_bd_p;
>> + =A0 =A0 =A0 struct cdmac_bd *rx_bd_v;
>> + =A0 =A0 =A0 dma_addr_t rx_bd_p;
>> + =A0 =A0 =A0 int tx_bd_ci;
>> + =A0 =A0 =A0 int tx_bd_next;
>> + =A0 =A0 =A0 int tx_bd_tail;
>> + =A0 =A0 =A0 int rx_bd_ci;
>> +};
>> +
>> +/* xilinx_temac.c */
>> +u32 temac_ior(struct temac_local *lp, int offset);
>> +void temac_iow(struct temac_local *lp, int offset, u32 value);
>> +int temac_indirect_busywait(struct temac_local *lp);
>> +u32 temac_indirect_in32(struct temac_local *lp, int reg);
>> +void temac_indirect_out32(struct temac_local *lp, int reg, u32 value);
>> +
>> +
>> +/* xilinx_temac_mdio.c */
>> +int temac_mdio_setup(struct temac_local *lp, struct device_node *np);
>> +void temac_mdio_teardown(struct temac_local *lp);
>> +
>> +#endif /* XILINX_TEMAC_H */
>> diff --git a/drivers/net/xilinx_temac_mdio.c
>> b/drivers/net/xilinx_temac_mdio.c
>> new file mode 100644
>> index 0000000..eeea61b
>> --- /dev/null
>> +++ b/drivers/net/xilinx_temac_mdio.c
>> @@ -0,0 +1,119 @@
>> +/*
>> + * MDIO bus driver for the Xilinx TEMAC device
>> + *
>> + * Copyright (c) 2009 Secret Lab Technologies, Ltd.
>> + */
>> +
>> +#include <linux/io.h>
>> +#include <linux/netdevice.h>
>> +#include <linux/mutex.h>
>> +#include <linux/phy.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_mdio.h>
>> +#include "xilinx_temac.h"
>> +
>> +/*
>> ---------------------------------------------------------------------
>> + * MDIO Bus functions
>> + */
>> +static int temac_mdio_read(struct mii_bus *bus, int phy_id, int reg)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D bus->priv;
>> + =A0 =A0 =A0 u32 rc;
>> +
>> + =A0 =A0 =A0 /* Write the PHY address to the MIIM Access Initiator regi=
ster.
>> + =A0 =A0 =A0 =A0* When the transfer completes, the PHY register value w=
ill
>> appear
>> + =A0 =A0 =A0 =A0* in the LSW0 register */
>> + =A0 =A0 =A0 mutex_lock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 temac_iow(lp, XTE_LSW0_OFFSET, (phy_id << 5) | reg);
>> + =A0 =A0 =A0 rc =3D temac_indirect_in32(lp, XTE_MIIMAI_OFFSET);
>> + =A0 =A0 =A0 mutex_unlock(&lp->indirect_mutex);
>> +
>> + =A0 =A0 =A0 dev_dbg(lp->dev, "temac_mdio_read(phy_id=3D%i, reg=3D%x) =
=3D=3D %x\n",
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 phy_id, reg, rc);
>> +
>> + =A0 =A0 =A0 return rc;
>> +}
>> +
>> +static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg,
>> u16 val)
>> +{
>> + =A0 =A0 =A0 struct temac_local *lp =3D bus->priv;
>> +
>> + =A0 =A0 =A0 dev_dbg(lp->dev, "temac_mdio_write(phy_id=3D%i, reg=3D%x,
>> val=3D%x)\n",
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 phy_id, reg, val);
>> +
>> + =A0 =A0 =A0 /* First write the desired value into the write data regis=
ter
>> + =A0 =A0 =A0 =A0* and then write the address into the access initiator =
register
>> + =A0 =A0 =A0 =A0*/
>> + =A0 =A0 =A0 mutex_lock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_MGTDR_OFFSET, val);
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_MIIMAI_OFFSET, (phy_id << 5) =
|
>> reg);
>> + =A0 =A0 =A0 mutex_unlock(&lp->indirect_mutex);
>> +
>> + =A0 =A0 =A0 return 0;
>> +}
>> +
>> +int temac_mdio_setup(struct temac_local *lp, struct device_node *np)
>> +{
>> + =A0 =A0 =A0 struct mii_bus *bus;
>> + =A0 =A0 =A0 const u32 *bus_hz;
>> + =A0 =A0 =A0 int clk_div;
>> + =A0 =A0 =A0 int rc, size;
>> + =A0 =A0 =A0 struct resource res;
>> +
>> + =A0 =A0 =A0 /* Calculate a reasonable divisor for the clock rate */
>> + =A0 =A0 =A0 clk_div =3D 0x3f; /* worst-case default setting */
>> + =A0 =A0 =A0 bus_hz =3D of_get_property(np, "clock-frequency", &size);
>> + =A0 =A0 =A0 if (bus_hz && size >=3D sizeof(*bus_hz)) {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_div =3D (*bus_hz) / (2500 * 1000 * 2) =
- 1;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (clk_div < 1)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_div =3D 1;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (clk_div > 0x3f)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_div =3D 0x3f;
>> + =A0 =A0 =A0 }
>> +
>> + =A0 =A0 =A0 /* Enable the MDIO bus by asserting the enable bit and wri=
ting
>> + =A0 =A0 =A0 =A0* in the clock config */
>> + =A0 =A0 =A0 mutex_lock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 temac_indirect_out32(lp, XTE_MC_OFFSET, 1 << 6 | clk_div);
>> + =A0 =A0 =A0 mutex_unlock(&lp->indirect_mutex);
>> +
>> + =A0 =A0 =A0 bus =3D mdiobus_alloc();
>> + =A0 =A0 =A0 if (!bus)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
>> +
>> + =A0 =A0 =A0 of_address_to_resource(np, 0, &res);
>> + =A0 =A0 =A0 snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(unsigned long long)res.start);
>> + =A0 =A0 =A0 bus->priv =3D lp;
>> + =A0 =A0 =A0 bus->name =3D "Xilinx TEMAC MDIO";
>> + =A0 =A0 =A0 bus->read =3D temac_mdio_read;
>> + =A0 =A0 =A0 bus->write =3D temac_mdio_write;
>> + =A0 =A0 =A0 bus->parent =3D lp->dev;
>> + =A0 =A0 =A0 bus->irq =3D lp->mdio_irqs; /* preallocated IRQ table */
>> +
>> + =A0 =A0 =A0 lp->mii_bus =3D bus;
>> +
>> + =A0 =A0 =A0 rc =3D of_mdiobus_register(bus, np);
>> + =A0 =A0 =A0 if (rc)
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto err_register;
>> +
>> + =A0 =A0 =A0 mutex_lock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 dev_dbg(lp->dev, "MDIO bus registered; =A0MC:%x\n",
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temac_indirect_in32(lp, XTE_MC_OFFSET));
>> + =A0 =A0 =A0 mutex_unlock(&lp->indirect_mutex);
>> + =A0 =A0 =A0 return 0;
>> +
>> + err_register:
>> + =A0 =A0 =A0 mdiobus_free(bus);
>> + =A0 =A0 =A0 return rc;
>> +}
>> +
>> +void temac_mdio_teardown(struct temac_local *lp)
>> +{
>> + =A0 =A0 =A0 mdiobus_unregister(lp->mii_bus);
>> + =A0 =A0 =A0 kfree(lp->mii_bus->irq);
>> + =A0 =A0 =A0 mdiobus_free(lp->mii_bus);
>> + =A0 =A0 =A0 lp->mii_bus =3D NULL;
>> +}
>> +
>>
>> _______________________________________________
>> Linuxppc-dev mailing list
>> Linuxppc-dev@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>>
>>
>> This email and any attachments are intended for the sole use of the name=
d recipient(s) and contain(s) confidential information that may be propriet=
ary, privileged or copyrighted under applicable law. If you are not the int=
ended recipient, do not read, copy, or forward this email message or any at=
tachments. Delete this email message and any attachments immediately.
>>
>>
>>
>



--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* [PATCH v2] powerpc: Add virtual processor dispatch trace log
From: Jeremy Kerr @ 2009-03-24  2:40 UTC (permalink / raw)
  To: Ben Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <<1236830152.729279.468331899806.3.gpush@pingu>

pseries SPLPAR machines are able to retrieve a log of dispatch and
preempt events from the hypervisor. With this information, we can
see when and why each dispatch & preempt is occuring.

This change adds a set of debugfs files allowing userspace to read this
dispatch log.

Based on initial patches from Nishanth Aravamudan <nacc@us.ibm.com>.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

---
v2: smp_wmb before enabling logging

---
 arch/powerpc/platforms/pseries/Kconfig          |   10 
 arch/powerpc/platforms/pseries/Makefile         |    1 
 arch/powerpc/platforms/pseries/dtl.c            |  278 ++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/plpar_wrappers.h |   10 
 4 files changed, 299 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index ddc2a30..730a5cd 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -63,3 +63,13 @@ config CMM
 	  makes sense for a system running in an LPAR where the unused pages
 	  will be reused for other LPARs. The interface allows firmware to
 	  balance memory across many LPARs.
+
+config DTL
+	bool "Dispatch Trace Log"
+	depends on PPC_SPLPAR && DEBUG_FS
+	help
+	  SPLPAR machines can log hypervisor preempt & dispatch events to a
+	  kernel buffer. Saying Y here will enable logging these events,
+	  which are accessible through a debugfs file.
+
+	  Say N if you are unsure.
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index dfe574a..1b388b3 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_HVCS)		+= hvcserver.o
 obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
 obj-$(CONFIG_PHYP_DUMP)	+= phyp_dump.o
 obj-$(CONFIG_CMM)		+= cmm.o
+obj-$(CONFIG_DTL)		+= dtl.o
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
new file mode 100644
index 0000000..fafcaa0
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -0,0 +1,278 @@
+/*
+ * Virtual Processor Dispatch Trace Log
+ *
+ * (C) Copyright IBM Corporation 2009
+ *
+ * Author: Jeremy Kerr <jk@ozlabs.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "plpar_wrappers.h"
+
+/*
+ * Layout of entries in the hypervisor's DTL buffer. Although we don't
+ * actually access the internals of an entry (we only need to know the size),
+ * we might as well define it here for reference.
+ */
+struct dtl_entry {
+	u8	dispatch_reason;
+	u8	preempt_reason;
+	u16	processor_id;
+	u32	enqueue_to_dispatch_time;
+	u32	ready_to_enqueue_time;
+	u32	waiting_to_ready_time;
+	u64	timebase;
+	u64	fault_addr;
+	u64	srr0;
+	u64	srr1;
+};
+
+struct dtl {
+	struct dtl_entry	*buf;
+	struct dentry		*file;
+	int			cpu;
+	int			buf_entries;
+	u64			last_idx;
+};
+static DEFINE_PER_CPU(struct dtl, dtl);
+
+/*
+ * Dispatch trace log event mask:
+ * 0x7: 0x1: voluntary virtual processor waits
+ *      0x2: time-slice preempts
+ *      0x4: virtual partition memory page faults
+ */
+static u8 dtl_event_mask = 0x7;
+
+
+/*
+ * Size of per-cpu log buffers. Default is just under 16 pages worth.
+ */
+static int dtl_buf_entries = (16 * 85);
+
+
+static int dtl_enable(struct dtl *dtl)
+{
+	unsigned long addr;
+	int ret, hwcpu;
+
+	/* only allow one reader */
+	if (dtl->buf)
+		return -EBUSY;
+
+	/* we need to store the original allocation size for use during read */
+	dtl->buf_entries = dtl_buf_entries;
+
+	dtl->buf = kmalloc_node(dtl->buf_entries * sizeof(struct dtl_entry),
+			GFP_KERNEL, cpu_to_node(dtl->cpu));
+	if (!dtl->buf) {
+		printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
+				__func__, dtl->cpu);
+		return -ENOMEM;
+	}
+
+	/* Register our dtl buffer with the hypervisor. The HV expects the
+	 * buffer size to be passed in the second word of the buffer */
+	((u32 *)dtl->buf)[1] = dtl->buf_entries * sizeof(struct dtl_entry);
+
+	hwcpu = get_hard_smp_processor_id(dtl->cpu);
+	addr = __pa(dtl->buf);
+	ret = register_dtl(hwcpu, addr);
+	if (ret) {
+		printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) "
+		       "failed with %d\n", __func__, dtl->cpu, hwcpu, ret);
+		kfree(dtl->buf);
+		return -EIO;
+	}
+
+	/* set our initial buffer indices */
+	dtl->last_idx = lppaca[dtl->cpu].dtl_idx = 0;
+
+	/* ensure that our updates to the lppaca fields have occurred before
+	 * we actually enable the logging */
+	smp_wmb();
+
+	/* enable event logging */
+	lppaca[dtl->cpu].dtl_enable_mask = dtl_event_mask;
+
+	return 0;
+}
+
+static void dtl_disable(struct dtl *dtl)
+{
+	int hwcpu = get_hard_smp_processor_id(dtl->cpu);
+
+	lppaca[dtl->cpu].dtl_enable_mask = 0x0;
+
+	unregister_dtl(hwcpu, __pa(dtl->buf));
+
+	kfree(dtl->buf);
+	dtl->buf = NULL;
+	dtl->buf_entries = 0;
+}
+
+/* file interface */
+
+static int dtl_file_open(struct inode *inode, struct file *filp)
+{
+	struct dtl *dtl = inode->i_private;
+	int rc;
+
+	rc = dtl_enable(dtl);
+	if (rc)
+		return rc;
+
+	filp->private_data = dtl;
+	return 0;
+}
+
+static int dtl_file_release(struct inode *inode, struct file *filp)
+{
+	struct dtl *dtl = inode->i_private;
+	dtl_disable(dtl);
+	return 0;
+}
+
+static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len,
+		loff_t *pos)
+{
+	int rc, cur_idx, last_idx, n_read, n_req, read_size;
+	struct dtl *dtl;
+
+	if ((len % sizeof(struct dtl_entry)) != 0)
+		return -EINVAL;
+
+	dtl = filp->private_data;
+
+	/* requested number of entries to read */
+	n_req = len / sizeof(struct dtl_entry);
+
+	/* actual number of entries read */
+	n_read = 0;
+
+	cur_idx = lppaca[dtl->cpu].dtl_idx;
+	last_idx = dtl->last_idx;
+
+	if (cur_idx - last_idx > dtl->buf_entries) {
+		pr_debug("%s: hv buffer overflow for cpu %d, samples lost\n",
+				__func__, dtl->cpu);
+	}
+
+	cur_idx  %= dtl->buf_entries;
+	last_idx %= dtl->buf_entries;
+
+	/* read the tail of the buffer if we've wrapped */
+	if (last_idx > cur_idx) {
+		read_size = min(n_req, dtl->buf_entries - last_idx);
+
+		rc = copy_to_user(buf, &dtl->buf[last_idx],
+				read_size * sizeof(struct dtl_entry));
+		if (rc)
+			return -EFAULT;
+
+		last_idx = 0;
+		n_req -= read_size;
+		n_read += read_size;
+		buf += read_size * sizeof(struct dtl_entry);
+	}
+
+	/* .. and now the head */
+	read_size = min(n_req, cur_idx - last_idx);
+	rc = copy_to_user(buf, &dtl->buf[last_idx],
+			read_size * sizeof(struct dtl_entry));
+	if (rc)
+		return -EFAULT;
+
+	n_read += read_size;
+	dtl->last_idx += n_read;
+
+	return n_read * sizeof(struct dtl_entry);
+}
+
+static struct file_operations dtl_fops = {
+	.open		= dtl_file_open,
+	.release	= dtl_file_release,
+	.read		= dtl_file_read,
+	.llseek		= no_llseek,
+};
+
+static struct dentry *dtl_dir;
+
+static int dtl_setup_file(struct dtl *dtl)
+{
+	char name[10];
+
+	sprintf(name, "cpu-%d", dtl->cpu);
+
+	dtl->file = debugfs_create_file(name, 0400, dtl_dir, dtl, &dtl_fops);
+	if (!dtl->file)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int dtl_init(void)
+{
+	struct dentry *event_mask_file, *buf_entries_file;
+	int rc, i;
+
+	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+		return -ENODEV;
+
+	/* set up common debugfs structure */
+
+	rc = -ENOMEM;
+	dtl_dir = debugfs_create_dir("dtl", powerpc_debugfs_root);
+	if (!dtl_dir) {
+		printk(KERN_WARNING "%s: can't create dtl root dir\n",
+				__func__);
+		goto err;
+	}
+
+	event_mask_file = debugfs_create_x8("dtl_event_mask", 0600,
+				dtl_dir, &dtl_event_mask);
+	buf_entries_file = debugfs_create_u32("dtl_buf_entries", 0600,
+				dtl_dir, &dtl_buf_entries);
+
+	if (!event_mask_file || !buf_entries_file) {
+		printk(KERN_WARNING "%s: can't create dtl files\n", __func__);
+		goto err_remove_dir;
+	}
+
+	/* set up the per-cpu log structures */
+	for_each_possible_cpu(i) {
+		struct dtl *dtl = &per_cpu(dtl, i);
+		dtl->cpu = i;
+
+		rc = dtl_setup_file(dtl);
+		if (rc)
+			goto err_remove_dir;
+	}
+
+	return 0;
+
+err_remove_dir:
+	debugfs_remove_recursive(dtl_dir);
+err:
+	return rc;
+}
+arch_initcall(dtl_init);
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index d967c18..a24a6b2 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -43,6 +43,16 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)
 	return vpa_call(0x3, cpu, vpa);
 }
 
+static inline long unregister_dtl(unsigned long cpu, unsigned long vpa)
+{
+	return vpa_call(0x6, cpu, vpa);
+}
+
+static inline long register_dtl(unsigned long cpu, unsigned long vpa)
+{
+	return vpa_call(0x2, cpu, vpa);
+}
+
 static inline long plpar_page_set_loaned(unsigned long vpa)
 {
 	unsigned long cmo_page_sz = cmo_get_page_size();

^ permalink raw reply related

* [PATCH] powerpc: Add write barrier before enabling DTL flags
From: Jeremy Kerr @ 2009-03-24  2:55 UTC (permalink / raw)
  To: Ben Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <<1236830152.729279.468331899806.3.gpush@pingu>

Currently, we don't enforce any ordering for updates to the lppaca
when enabling dtl logging, so we may end up enabling logging before the
index fields have been established.

This change adds a smp_wmb() before doing the actual enable.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

---
 arch/powerpc/platforms/pseries/dtl.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index dc9b0f8..fafcaa0 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -107,6 +107,10 @@ static int dtl_enable(struct dtl *dtl)
 	/* set our initial buffer indices */
 	dtl->last_idx = lppaca[dtl->cpu].dtl_idx = 0;
 
+	/* ensure that our updates to the lppaca fields have occurred before
+	 * we actually enable the logging */
+	smp_wmb();
+
 	/* enable event logging */
 	lppaca[dtl->cpu].dtl_enable_mask = dtl_event_mask;
 

^ permalink raw reply related

* Re: [PATCH] Fix RTAS watchdog driver temperature read functionality
From: Benjamin Herrenschmidt @ 2009-03-24  4:27 UTC (permalink / raw)
  To: Adrian Reber; +Cc: linuxppc-dev
In-Reply-To: <20090316123543.GG15530@lisas.de>

On Mon, 2009-03-16 at 13:35 +0100, Adrian Reber wrote:
> Using the RTAS watchdog driver to read out the temperature crashes
> on a PXCAB:
> 
> Unable to handle kernel paging request for data at address 0xfe347b50
> Faulting instruction address: 0xc00000000001af64
> Oops: Kernel access of bad area, sig: 11 [#1]
> 
> This (removing "(void *)__pa") fixes it.

Looks correct, but why not use rtas_get_sensor() instead ? (Exported by
arch/powerpc/kernel/rtas.c

Cheers,
Ben.

> Signed-off-by: Adrian Reber <adrian@lisas.de>
> ---
>  drivers/watchdog/wdrtas.c |    3 +--
>  1 files changed, 1 insertions(+), 2 deletions(-)
> 
> Fix for:
> 
> Unable to handle kernel paging request for data at address 0xfe347b50
> Faulting instruction address: 0xc00000000001af64
> Oops: Kernel access of bad area, sig: 11 [#1]
> SMP NR_CPUS=4 NUMA Cell
> Modules linked in:
> NIP: c00000000001af64 LR: c00000000001af28 CTR: c000000000281888
> REGS: c0000000fe3477a0 TRAP: 0300   Not tainted  (2.6.29-rc6-11955-g2450cf5)
> MSR: 9000000000001032 <ME,IR,DR>  CR: 22000422  XER: 00000000
> DAR: 00000000fe347b50, DSISR: 0000000042000000
> TASK = c0000000fe4886f0[1184] 'a.out' THREAD: c0000000fe344000 CPU: 1
> GPR00: 000000000000002a c0000000fe347a20 c000000000ab2160 c000000000007bc0 
> GPR04: 0000000022000422 c000000000281888 0000000000000000 00000400001e6138  
> GPR08: 0000000000000008 c000000000b23ce4 0000000000000008 00000000fe347b54 
> GPR12: 0000000082000424 c000000000b23680 c0000000003b37b0 c000000000441620 
> GPR16: c0000000004412e0 c000000000441130 000000000e154ec8 c0000000003b4580 
> GPR20: 0000000000000000 00000000100a0370 00000000100a0390 c000000000b23cc8 
> GPR24: 0000000000000001 0000000000000002 00000000fe347b50 0000000000000002 
> GPR28: 0000000000000010 c000000000b23cb0 c000000000a59588 0000000000000002 
> NIP [c00000000001af64] .rtas_call+0x1ac/0x1f8
> LR [c00000000001af28] .rtas_call+0x170/0x1f8
> Call Trace:
> [c0000000fe347a20] [c00000000001af28] .rtas_call+0x170/0x1f8 (unreliable)          
> [c0000000fe347ae0] [c0000000002812e8] .wdrtas_get_temperature+0x48/0xa8  
> [c0000000fe347b70] [c000000000281948] .wdrtas_ioctl+0xc0/0x300
> [c0000000fe347c00] [c0000000000f58a4] .vfs_ioctl+0x54/0x138
> [c0000000fe347c90] [c0000000000f5a20] .do_vfs_ioctl+0x98/0x738
> [c0000000fe347d80] [c0000000000f6114] .SyS_ioctl+0x54/0xc8
> [c0000000fe347e30] [c0000000000074b4] syscall_exit+0x0/0x40
> Instruction dump:
> 2fba0000 419e0034 3939fffe 39400004 79290020 39290002 79281764 e93d0070 
> 7d7a5214 7c09502e 394a0004 7faa4000 <900bfffc> 409effe8 e93d0070 ebe90002 
> ---[ end trace 084fb7ab3feda750 ]---
> 
> diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c
> index 5d3b1a8..30ee1f2 100644
> --- a/drivers/watchdog/wdrtas.c
> +++ b/drivers/watchdog/wdrtas.c
> @@ -218,8 +218,7 @@ static int wdrtas_get_temperature(void)
>  	int temperature = 0;
>  
>  	result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,
> -			   (void *)__pa(&temperature),
> -			   WDRTAS_THERMAL_SENSOR, 0);
> +			   &temperature, WDRTAS_THERMAL_SENSOR, 0);
>  
>  	if (result < 0)
>  		printk(KERN_WARNING "wdrtas: reading the thermal sensor "

^ permalink raw reply

* Re: [PATCH 11/11] mmc: Add OpenFirmware bindings for SDHCI driver
From: 山崎 精二 @ 2009-03-24  4:46 UTC (permalink / raw)
  To: avorontsov
  Cc: justinmattock, Ben Dooks, Arnd Bergmann, yamazaki, Liu Dave,
	linux-kernel, linuxppc-dev, sdhci-devel, Pierre Ossman
In-Reply-To: <20090323161655.GA30262@oksana.dev.rtsoft.ru>

Hi

> 
> All these errors indicate that you didn't apply all the patches.
> You'll need all 11 patches from this series, not only the last
> one.
> 

I applyed all the patches,then Compile was succeeded.

Thank you for your advice.

regards,

-- Seiji Yamazaki


On Mon, 23 Mar 2009 19:16:55 +0300
Anton Vorontsov <avorontsov@ru.mvista.com> wrote:

> On Mon, Mar 23, 2009 at 03:34:45PM +0900, 螻ア蟠弱??邊セ莠\xB7\x01wrote:
> > Hi 
> > 
> > I downloaded linux-2.6.29-rc8.tar.bz2,and I patched .
> > I was succeeded. Thank you very match.
> > But I have the other problem.
> > 
> > Compile was not succeeded.
> > 
> > Message is ...
> > 
> >  CALL    arch/powerpc/kernel/prom_init_check.sh
> >   CC      drivers/mmc/host/sdhci-of.o
> > drivers/mmc/host/sdhci-of.c:163: error: 'SDHCI_QUIRK_FORCE_BLK_SZ_2048' undeclared here (not in a function)
> > drivers/mmc/host/sdhci-of.c:164: error: 'SDHCI_QUIRK_BROKEN_CARD_DETECTION' undeclared here (not in a function)
> > drivers/mmc/host/sdhci-of.c:165: error: 'SDHCI_QUIRK_INVERTED_WRITE_PROTECT' undeclared here (not in a function)
> > drivers/mmc/host/sdhci-of.c:167: error: 'SDHCI_QUIRK_NONSTANDARD_CLOCK' undeclared here (not in a function)
> > drivers/mmc/host/sdhci-of.c:168: error: 'SDHCI_QUIRK_PIO_NEEDS_DELAY' undeclared here (not in a function)
> > drivers/mmc/host/sdhci-of.c:169: error: 'SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET' undeclared here (not in a function)
> [...]
> > drivers/mmc/host/sdhci-of.c:181: warning: excess elements in struct initializer
> > drivers/mmc/host/sdhci-of.c:181: warning: (near initialization for 'sdhci_esdhc.ops')
> > make[3]: *** [drivers/mmc/host/sdhci-of.o] Error 1
> > make[2]: *** [drivers/mmc/host] Error 2
> > make[1]: *** [drivers/mmc] Error 2
> 
> All these errors indicate that you didn't apply all the patches.
> You'll need all 11 patches from this series, not only the last
> one.
> 
> -- 
> Anton Vorontsov
> email: cbouatmailru@gmail.com
> irc://irc.freenode.net/bd2

-- 
yamazaki seiji <yamazaki.seiji@kk.jp.panasonic.com>

^ permalink raw reply

* Re: spidev.c driver on the ppc8247 (kernel 2.6.27.19)
From: Daniel Ng @ 2009-03-24  5:05 UTC (permalink / raw)
  To: linuxppc-dev@ozlabs.org
In-Reply-To: <4206182445660643B9AEB8D4E55BBD0A02B9DDEEB4@HERMES2>

The solution is in Documentation/spi/spidev:

-in the slave device spi_board_info struct, specify 'spidev' for the
'modalias' of *every* SPI slave.

I wonder what magic was involved to set this up!!?

^ permalink raw reply

* Re: [PATCH] tracing: Fix TRACING_SUPPORT dependency
From: Benjamin Herrenschmidt @ 2009-03-24  5:43 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev, Ingo Molnar, Steven Rostedt, linux-kernel
In-Reply-To: <20090320202247.GA30654@oksana.dev.rtsoft.ru>


> > Weird, there's no lockdep support?
> 
> *ashamed*: apparently no such support currently exist for PPC32. ;-)

Actually there is a patch that's been floating around (from Dale
Farnsworth) for adding irqtrace/lockdep to ppc32 but it seems to be
buggy :-) IE, it causes crashes and I haven't had a chance
to try to find out yet. I'll probably give it another go one of these
days, but if you want to play with it, I'll send it to you directly.

Cheers,
Ben.

^ 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