LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] Remove unnecessary memset from physmap_of driver
From: Paul Mackerras @ 2007-10-02 23:43 UTC (permalink / raw)
  To: Valentine Barshak; +Cc: linuxppc-dev
In-Reply-To: <20071002155328.GA3574@ru.mvista.com>

Valentine Barshak writes:

> No need for memset to zero memory here, since we use kzalloc.
> 
> Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
> ---
>  drivers/mtd/maps/physmap_of.c |    1 -

Please cc the mtd list (linux-mtd@lists.infradead.org) and/or David
Woodhouse on MTD patches.  Posting them to linuxppc-dev isn't going to
get them upstream.

Paul.

^ permalink raw reply

* Re: 2.6.23-rc7-mm1 -- powerpc rtas panic
From: Linas Vepstas @ 2007-10-02 23:28 UTC (permalink / raw)
  To: Andy Whitcroft; +Cc: linuxppc-dev, Andrew Morton, linux-kernel
In-Reply-To: <20070924123531.GC30855@shadowen.org>

On Mon, Sep 24, 2007 at 01:35:31PM +0100, Andy Whitcroft wrote:
> Seeing the following from an older power LPAR, pretty sure we had
> this in the previous -mm also:

I haven't forgetten about this ... and am looking at it now.
Seems that whenever I go to reserve the machine pSeries-102,
someone else is using it :-)

--linas

^ permalink raw reply

* Re: [RFC] PPC64 Exporting memory information through /proc/iomem
From: Badari Pulavarty @ 2007-10-02 23:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, anton, KAMEZAWA Hiroyuki, linux-mm
In-Reply-To: <18178.52359.953289.638736@cargo.ozlabs.ibm.com>

On Wed, 2007-10-03 at 08:56 +1000, Paul Mackerras wrote:
> Badari Pulavarty writes:
> 
> > I am trying to get hotplug memory remove working on ppc64.
> > In order to verify a given memory region, if its valid or not -
> > current hotplug-memory patches used /proc/iomem. On IA64 and
> > x86-64 /proc/iomem shows all memory regions. 
> > 
> > I am wondering, if its acceptable to do the same on ppc64 also ?
> 
> I am a bit hesitant to do that, since /proc/iomem is user visible and
> is therefore part of the user/kernel ABI.  Also it feels a bit weird
> to have system RAM in something whose name suggests it's about MMIO.

Yes. That was my first reaction. Until last week, I never realized
that /proc/iomem contains entire memory layout on i386/x86-64 :(

Since i386, x86-64 and ia64 are all doing same thing, I thought breakage
would be minimal (if any) if we do the same on ppc64.

> > Otherwise, we need to add arch-specific hooks in hotplug-remove
> > code to be able to do this.
> 
> Isn't it just a matter of abstracting the test for a valid range of
> memory?  If it's really hard to abstract that, then I guess we can put
> RAM in iomem_resource, but I'd rather not.
> 

Sure. I will work on it and see how ugly it looks.

KAME, are you okay with abstracting the find_next_system_ram() and
let arch provide whatever implementation they want ? (since current
code doesn't work for x86-64 also ?).

Thanks,
Badari

^ permalink raw reply

* Re: [RFC] PPC64 Exporting memory information through /proc/iomem
From: Paul Mackerras @ 2007-10-02 22:56 UTC (permalink / raw)
  To: Badari Pulavarty; +Cc: linuxppc-dev, anton, KAMEZAWA Hiroyuki, linux-mm
In-Reply-To: <1191346196.6106.20.camel@dyn9047017100.beaverton.ibm.com>

Badari Pulavarty writes:

> I am trying to get hotplug memory remove working on ppc64.
> In order to verify a given memory region, if its valid or not -
> current hotplug-memory patches used /proc/iomem. On IA64 and
> x86-64 /proc/iomem shows all memory regions. 
> 
> I am wondering, if its acceptable to do the same on ppc64 also ?

I am a bit hesitant to do that, since /proc/iomem is user visible and
is therefore part of the user/kernel ABI.  Also it feels a bit weird
to have system RAM in something whose name suggests it's about MMIO.

> Otherwise, we need to add arch-specific hooks in hotplug-remove
> code to be able to do this.

Isn't it just a matter of abstracting the test for a valid range of
memory?  If it's really hard to abstract that, then I guess we can put
RAM in iomem_resource, but I'd rather not.

Thanks,
Paul.

^ permalink raw reply

* Re: [PATCH 2 6/7] Uartlite: Add of-platform-bus binding
From: Benjamin Herrenschmidt @ 2007-10-02 22:43 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40710020910u3a679ea2m15b005d0ba5fb054@mail.gmail.com>


> My opinion is that since it is driver-specific code anyway, then it
> belongs with the driver.  Plus a driver writer for ARM doesn't need to
> write them.  It's the powerpc or microblaze developer who will do it.
> If the driver maintainer doesn't want the binding in the main driver
> .c file, then the binding can easily be in an additional .c file
> without needing to add a constructor.  (Kind of like how many USB host
> controllers are managed)

The main advantage is that it keeps the OF specific code localized to a
single function, whether that function lives in the driver or the arch
code, it makes it self contained and easier to deal with by the driver
author.

Having multiple device types on which the driver can attach is a pain
from a driver standpoint. It needs multiple
probe/remove/suspend/resume/shutdown hooks etc... it's a bigger
maintainance burden in the long run.

The important thing however, with the constructor approach is to try as
much as possible to keep the proper tree structure, and thus, try to
find a way to instanciate the devices with proper parent/child
relationship so that ordering for things like suspend/resume operations
is maintained.

Ben.

^ permalink raw reply

* Re: Problem with OF interrupt parsing code
From: Benjamin Herrenschmidt @ 2007-10-02 22:03 UTC (permalink / raw)
  To: Gerhard Pircher; +Cc: linuxppc-dev
In-Reply-To: <20071002123849.242670@gmx.net>


On Tue, 2007-10-02 at 14:38 +0200, Gerhard Pircher wrote:
> I know that it's ugly, but the problem is how to distinguish the
> boards.
> The only real difference I know of is the PCI interrupt mapping. The
> northbridges chip revision for example is always the same, but CPU
> type,
> amount of memory and PCI devices can appear in all possible
> combinations.
> The firmware doesn't tell me, which board the kernel is runnning on,
> so I
> would like to rely on this fall back here until I get the chance to
> update the firmware (which is beyond my control).

And how does the firmware know ? There must be a strap somewhere...

Ben.

^ permalink raw reply

* Re: [PATCH 2/7] [POWERPC] Fix QEIC->MPIC cascading
From: Benjamin Herrenschmidt @ 2007-10-02 22:02 UTC (permalink / raw)
  To: avorontsov; +Cc: linuxppc-dev
In-Reply-To: <20071002122005.GA6425@localhost.localdomain>


> 
> Exactly, this is what that patch is trying to do. QEIC cascade handler is
> calling mpic's eoi() (end() actually, as it's flow level, but end == eoi.
> Is it main objection? Ok, I can get rid of it, and use chip level eoi()
> directly).

Yes, use eoi() directly, don't add end()

> Yup, exactly. Actually, QEIC's cascade handlers do not really know
> what needs to be done, but they're good at guessing (if (chip->eoi)).
> 
> Sure, I can place board-specific QEIC handlers in the board file, but
> that will be quite big code duplication for all machines using QEIC.

Maybe you can provide a set of common ones, and then just pick the one
you want from the board file ?

Or have some board code call into a QEIC init routine specifying the
type of cascade handler to use ... or whatevre you like here.

Just don't add end() where it doesn't belong.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH 2/2]: PCI Error Recovery: Symbios SCSI First Failure
From: Linas Vepstas @ 2007-10-02 21:59 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: linuxppc-dev, linux-pci, linux-kernel, linux-scsi
In-Reply-To: <20071002012730.GO12049@parisc-linux.org>

On Mon, Oct 01, 2007 at 07:27:30PM -0600, Matthew Wilcox wrote:
> 
> Fine by me.  Do you have the ability to produce failures on a whim on
> your platforms?  

Yes, although it is very platform specific -- there are actually
transistors in the pci bridge chip, which actually short out lines,
and so, from the point of view of the rest of the chip, it did
actually see a "real" error. Its supposed to be a very realistic 
test.

> I've been vaguely musing a PCI device failure patch for
> x86, just so people can test driver failure paths.

That would be good ... I've recently agreed to accept a fedex
to test someone elses card for them, which is outside my usual
activities.

There's also supposed to be some PCI-X riser card out there, 
(never seen one) which has the ability to inject actual pci 
errors. Its the Agilent PCI BestX card; I got the impression 
they might not sell it anymore; dunno.

One guy in the lab used to brush a grounding strap across
the pins; this usually got a rise out of the audience.

--linas

^ permalink raw reply

* [PATCH] powerpc: another use of zalloc_maybe_bootmem()
From: Linas Vepstas @ 2007-10-02 21:40 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: ppc-dev, paulus
In-Reply-To: <20071002133753.662397db.sfr@canb.auug.org.au>


Use alloc_maybe_bootmem() which wraps the if(mem_init_done)
malloc clause.

Signed-off-by: Linas Vepstas <linas@austin.ibm.com>

----
On Tue, Oct 02, 2007 at 01:37:53PM +1000, Stephen Rothwell wrote:
> This patch introduces zalloc_maybe_bootmem and uses it so that we don;t
> have to mark a whole (largish) routine as __init_ref_ok.

sfr missed a spot -- may as well get rid of this one too.


 arch/powerpc/kernel/pci-common.c |    7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

Index: linux-2.6.23-rc8-mm1/arch/powerpc/kernel/pci-common.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/arch/powerpc/kernel/pci-common.c	2007-09-26 15:02:41.000000000 -0500
+++ linux-2.6.23-rc8-mm1/arch/powerpc/kernel/pci-common.c	2007-10-02 16:28:16.000000000 -0500
@@ -65,14 +65,11 @@ static void __devinit pci_setup_pci_cont
 	spin_unlock(&hose_spinlock);
 }
 
-__init_refok struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
 {
 	struct pci_controller *phb;
 
-	if (mem_init_done)
-		phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
-	else
-		phb = alloc_bootmem(sizeof (struct pci_controller));
+	phb = alloc_maybe_bootmem(sizeof(struct pci_controller), GFP_KERNEL);
 	if (phb == NULL)
 		return NULL;
 	pci_setup_pci_controller(phb);

^ permalink raw reply

* [PATCH] [POWERPC] update immap_86xx.h for the 8610
From: Timur Tabi @ 2007-10-02 21:27 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Timur Tabi

Update the definition of the global utilities structure (ccsr_guts) in
immap_86xx.h and add some related macros for the Freescale 8610 SOC.

Signed-off-by: Timur Tabi <timur@freescale.com>
---

This patch is for 2.6.24.

 include/asm-powerpc/immap_86xx.h |   86 ++++++++++++++++++++++++++++++++++----
 1 files changed, 78 insertions(+), 8 deletions(-)

diff --git a/include/asm-powerpc/immap_86xx.h b/include/asm-powerpc/immap_86xx.h
index c83d7ad..0ad4e65 100644
--- a/include/asm-powerpc/immap_86xx.h
+++ b/include/asm-powerpc/immap_86xx.h
@@ -38,7 +38,8 @@ struct ccsr_guts {
 	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
 	u8	res6[0x70 - 0x64];
 	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
-	u8	res7[0x80 - 0x74];
+	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
+	u8	res7[0x80 - 0x78];
 	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
 	u8	res8[0x90 - 0x84];
 	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
@@ -48,18 +49,87 @@ struct ccsr_guts {
 	__be32	svr;		/* 0x.00a4 - System Version Register */
 	u8	res10[0xB0 - 0xA8];
 	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */
-	u8	res11[0xB20 - 0xB4];
-	__be32	ddr1clkdr;	/* 0x.0b20 - DDRC1 Clock Disable Register */
-	__be32	ddr2clkdr;	/* 0x.0b24 - DDRC2 Clock Disable Register */
-	u8	res12[0xE00 - 0xB28];
+	u8	res11[0xC0 - 0xB4];
+	__be32	elbcvselcr;	/* 0x.00c0 - eLBC Voltage Select Ctrl Reg */
+	u8	res12[0x800 - 0xC4];
+	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
+	u8	res13[0x900 - 0x804];
+	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
+	u8	res14[0x908 - 0x904];
+	__be32	dmacr;		/* 0x.0908 - DMA Control Register */
+	u8	res15[0x914 - 0x90C];
+	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */
+	u8	res16[0xB20 - 0x918];
+	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
+	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
+	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
+	u8	res17[0xE00 - 0xB2C];
 	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
-	u8	res13[0xF04 - 0xE04];
+	u8	res18[0xE10 - 0xE04];
+	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
+	u8	res19[0xE20 - 0xE14];
+	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
+	u8	res20[0xF04 - 0xE24];
 	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
 	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
-	u8	res14[0xF40 - 0xF0C];
+	u8	res21[0xF40 - 0xF0C];
 	__be32	srds2cr0;	/* 0x.0f40 - SerDes1 Control Register 0 */
 	__be32	srds2cr1;	/* 0x.0f44 - SerDes1 Control Register 0 */
-};
+} __attribute__ ((packed));
+
+#define CCSR_GUTS_DMACR_DEV_SSI	0	/* DMA controller/channel set to SSI */
+#define CCSR_GUTS_DMACR_DEV_IR	1	/* DMA controller/channel set to IR */
+
+/*
+ * Set the DMACR register in the GUTS
+ *
+ * The DMACR register determines the source of initiated transfers for each
+ * channel on each DMA controller.  Rather than have a bunch of repetitive
+ * macros for the bit patterns, we just have a function that calculates
+ * them.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (1 or 2)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
+ */
+static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
+	unsigned int co, unsigned int ch, unsigned int device)
+{
+	unsigned int shift = 16 + (8 * (2 - co) + 2 * (3 - ch));
+
+	clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift);
+}
+
+#define CCSR_GUTS_PMUXCR_LDPSEL		0x00010000
+#define CCSR_GUTS_PMUXCR_SSI1_MASK	0x0000C000	/* Bitmask for SSI1 */
+#define CCSR_GUTS_PMUXCR_SSI1_LA	0x00000000	/* Latched address */
+#define CCSR_GUTS_PMUXCR_SSI1_HI	0x00004000	/* High impedance */
+#define CCSR_GUTS_PMUXCR_SSI1_SSI	0x00008000	/* Used for SSI1 */
+#define CCSR_GUTS_PMUXCR_SSI2_MASK	0x00003000	/* Bitmask for SSI2 */
+#define CCSR_GUTS_PMUXCR_SSI2_LA	0x00000000	/* Latched address */
+#define CCSR_GUTS_PMUXCR_SSI2_HI	0x00001000	/* High impedance */
+#define CCSR_GUTS_PMUXCR_SSI2_SSI	0x00002000	/* Used for SSI2 */
+#define CCSR_GUTS_PMUXCR_LA_22_25_LA	0x00000000	/* Latched Address */
+#define CCSR_GUTS_PMUXCR_LA_22_25_HI	0x00000400	/* High impedance */
+#define CCSR_GUTS_PMUXCR_DBGDRV		0x00000200	/* Signals not driven */
+#define CCSR_GUTS_PMUXCR_DMA2_0		0x00000008
+#define CCSR_GUTS_PMUXCR_DMA2_3		0x00000004
+#define CCSR_GUTS_PMUXCR_DMA1_0		0x00000002
+#define CCSR_GUTS_PMUXCR_DMA1_3		0x00000001
+
+#define CCSR_GUTS_CLKDVDR_PXCKEN	0x80000000
+#define CCSR_GUTS_CLKDVDR_SSICKEN	0x20000000
+#define CCSR_GUTS_CLKDVDR_PXCKINV	0x10000000
+#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25
+#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK	0x06000000
+#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \
+	(((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT)
+#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT	16
+#define CCSR_GUTS_CLKDVDR_PXCLK_MASK	0x001F0000
+#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT)
+#define CCSR_GUTS_CLKDVDR_SSICLK_MASK	0x000000FF
+#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
 
 #endif /* __ASM_POWERPC_IMMAP_86XX_H__ */
 #endif /* __KERNEL__ */
-- 
1.5.2.4

^ permalink raw reply related

* [PATCH] [11/11] pasemi_mac: enable iommu support
From: Olof Johansson @ 2007-10-02 21:28 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: use buffer index pointer in clean_rx()

Use the new features in B0 for buffer ring index on the receive side. This
means we no longer have to search in the ring for where the buffer
came from.

Also cleanup the RX cleaning side a little, while I was at it.

Note: Pre-B0 hardware is no longer supported, and needs a pile of other
workarounds that are not being submitted for mainline inclusion. So the
fact that this breaks old hardware is not a problem at this time.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -243,9 +243,9 @@ static int pasemi_mac_setup_rx_resources
 			   PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
 
 	write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if),
-			   PAS_DMA_RXINT_CFG_DHL(3) |
-			   PAS_DMA_RXINT_CFG_L2 |
-			   PAS_DMA_RXINT_CFG_LW);
+		      PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 |
+		      PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP |
+		      PAS_DMA_RXINT_CFG_HEN);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
@@ -402,13 +402,12 @@ static void pasemi_mac_free_rx_resources
 static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
-	int start = mac->rx->next_to_fill;
-	unsigned int fill, count;
+	int fill, count;
 
 	if (limit <= 0)
 		return;
 
-	fill = start;
+	fill = mac->rx->next_to_fill;
 	for (count = 0; count < limit; count++) {
 		struct pasemi_mac_buffer *info = &RX_RING_INFO(mac, fill);
 		u64 *buff = &RX_BUFF(mac, fill);
@@ -446,10 +445,10 @@ static void pasemi_mac_replenish_rx_ring
 
 	wmb();
 
-	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), count);
 	write_dma_reg(mac, PAS_DMA_RXINT_INCR(mac->dma_if), count);
 
-	mac->rx->next_to_fill += count;
+	mac->rx->next_to_fill = (mac->rx->next_to_fill + count) &
+				(RX_RING_SIZE - 1);
 }
 
 static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
@@ -517,15 +516,19 @@ static int pasemi_mac_clean_rx(struct pa
 	int count;
 	struct pasemi_mac_buffer *info;
 	struct sk_buff *skb;
-	unsigned int i, len;
+	unsigned int len;
 	u64 macrx;
 	dma_addr_t dma;
+	int buf_index;
+	u64 eval;
 
 	spin_lock(&mac->rx->lock);
 
 	n = mac->rx->next_to_clean;
 
-	for (count = limit; count; count--) {
+	prefetch(RX_RING(mac, n));
+
+	for (count = 0; count < limit; count++) {
 		macrx = RX_RING(mac, n);
 
 		if ((macrx & XCT_MACRX_E) ||
@@ -537,21 +540,14 @@ static int pasemi_mac_clean_rx(struct pa
 
 		info = NULL;
 
-		/* We have to scan for our skb since there's no way
-		 * to back-map them from the descriptor, and if we
-		 * have several receive channels then they might not
-		 * show up in the same order as they were put on the
-		 * interface ring.
-		 */
+		BUG_ON(!(macrx & XCT_MACRX_RR_8BRES));
 
-		dma = (RX_RING(mac, n+1) & XCT_PTR_ADDR_M);
-		for (i = mac->rx->next_to_fill;
-		     i < (mac->rx->next_to_fill + RX_RING_SIZE);
-		     i++) {
-			info = &RX_RING_INFO(mac, i);
-			if (info->dma == dma)
-				break;
-		}
+		eval = (RX_RING(mac, n+1) & XCT_RXRES_8B_EVAL_M) >>
+			XCT_RXRES_8B_EVAL_S;
+		buf_index = eval-1;
+
+		dma = (RX_RING(mac, n+2) & XCT_PTR_ADDR_M);
+		info = &RX_RING_INFO(mac, buf_index);
 
 		skb = info->skb;
 
@@ -600,9 +596,9 @@ static int pasemi_mac_clean_rx(struct pa
 		/* Need to zero it out since hardware doesn't, since the
 		 * replenish loop uses it to tell when it's done.
 		 */
-		RX_BUFF(mac, i) = 0;
+		RX_BUFF(mac, buf_index) = 0;
 
-		n += 2;
+		n += 4;
 	}
 
 	if (n > RX_RING_SIZE) {
@@ -610,8 +606,16 @@ static int pasemi_mac_clean_rx(struct pa
 		write_iob_reg(mac, PAS_IOB_COM_PKTHDRCNT, 0);
 		n &= (RX_RING_SIZE-1);
 	}
+
 	mac->rx->next_to_clean = n;
-	pasemi_mac_replenish_rx_ring(mac->netdev, limit-count);
+
+	/* Increase is in number of 16-byte entries, and since each descriptor
+	 * with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with
+	 * count*2.
+	 */
+	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), count << 1);
+
+	pasemi_mac_replenish_rx_ring(mac->netdev, count);
 
 	spin_unlock(&mac->rx->lock);
 
@@ -927,6 +931,8 @@ static int pasemi_mac_open(struct net_de
 
 	pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE);
 
+	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), RX_RING_SIZE>>1);
+
 	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
 		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
 
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -206,12 +206,15 @@ enum {
 #define    PAS_DMA_RXINT_RCMDSTA_DROPS_M	0xfffe0000
 #define    PAS_DMA_RXINT_RCMDSTA_DROPS_S	17
 #define PAS_DMA_RXINT_CFG(i)		(0x204+(i)*_PAS_DMA_RXINT_STRIDE)
+#define    PAS_DMA_RXINT_CFG_RBP	0x80000000
+#define    PAS_DMA_RXINT_CFG_ITRR	0x40000000
 #define    PAS_DMA_RXINT_CFG_DHL_M	0x07000000
 #define    PAS_DMA_RXINT_CFG_DHL_S	24
 #define    PAS_DMA_RXINT_CFG_DHL(x)	(((x) << PAS_DMA_RXINT_CFG_DHL_S) & \
 					 PAS_DMA_RXINT_CFG_DHL_M)
 #define    PAS_DMA_RXINT_CFG_LW		0x00200000
 #define    PAS_DMA_RXINT_CFG_L2		0x00100000
+#define    PAS_DMA_RXINT_CFG_HEN	0x00080000
 #define    PAS_DMA_RXINT_CFG_WIF	0x00000002
 #define    PAS_DMA_RXINT_CFG_WIL	0x00000001
 
@@ -425,10 +428,9 @@ enum {
 /* Receive descriptor fields */
 #define	XCT_MACRX_T		0x8000000000000000ull
 #define	XCT_MACRX_ST		0x4000000000000000ull
-#define XCT_MACRX_NORES		0x0000000000000000ull
-#define XCT_MACRX_8BRES		0x1000000000000000ull
-#define XCT_MACRX_24BRES	0x2000000000000000ull
-#define XCT_MACRX_40BRES	0x3000000000000000ull
+#define XCT_MACRX_RR_M		0x3000000000000000ull
+#define XCT_MACRX_RR_NORES	0x0000000000000000ull
+#define XCT_MACRX_RR_8BRES	0x1000000000000000ull
 #define XCT_MACRX_O		0x0400000000000000ull
 #define XCT_MACRX_E		0x0200000000000000ull
 #define XCT_MACRX_FF		0x0100000000000000ull
@@ -476,6 +478,17 @@ enum {
 #define XCT_PTR_ADDR(x)		((((long)(x)) << XCT_PTR_ADDR_S) & \
 				 XCT_PTR_ADDR_M)
 
+/* Receive interface 8byte result fields */
+#define XCT_RXRES_8B_L4O_M	0xff00000000000000ull
+#define XCT_RXRES_8B_L4O_S	56
+#define XCT_RXRES_8B_RULE_M	0x00ffff0000000000ull
+#define XCT_RXRES_8B_RULE_S	40
+#define XCT_RXRES_8B_EVAL_M	0x000000ffff000000ull
+#define XCT_RXRES_8B_EVAL_S	24
+#define XCT_RXRES_8B_HTYPE_M	0x0000000000f00000ull
+#define XCT_RXRES_8B_HASH_M	0x00000000000fffffull
+#define XCT_RXRES_8B_HASH_S	0
+
 /* Receive interface buffer fields */
 #define XCT_RXB_LEN_M		0x0ffff00000000000ull
 #define XCT_RXB_LEN_S		44

^ permalink raw reply

* [PATCH] [10/11] pasemi_mac: use buffer index pointer in clean_rx()
From: Olof Johansson @ 2007-10-02 21:27 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: use buffer index pointer in clean_rx()

Use the new features in B0 for buffer ring index on the receive side. This
means we no longer have to search in the ring for where the buffer
came from.

Also cleanup the RX cleaning side a little, while I was at it.

Note: Pre-B0 hardware is no longer supported, and needs a pile of other
workarounds that are not being submitted for mainline inclusion. So the
fact that this breaks old hardware is not a problem at this time.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -243,9 +243,9 @@ static int pasemi_mac_setup_rx_resources
 			   PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
 
 	write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if),
-			   PAS_DMA_RXINT_CFG_DHL(3) |
-			   PAS_DMA_RXINT_CFG_L2 |
-			   PAS_DMA_RXINT_CFG_LW);
+		      PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 |
+		      PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP |
+		      PAS_DMA_RXINT_CFG_HEN);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
@@ -402,13 +402,12 @@ static void pasemi_mac_free_rx_resources
 static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
-	int start = mac->rx->next_to_fill;
-	unsigned int fill, count;
+	int fill, count;
 
 	if (limit <= 0)
 		return;
 
-	fill = start;
+	fill = mac->rx->next_to_fill;
 	for (count = 0; count < limit; count++) {
 		struct pasemi_mac_buffer *info = &RX_RING_INFO(mac, fill);
 		u64 *buff = &RX_BUFF(mac, fill);
@@ -446,10 +445,10 @@ static void pasemi_mac_replenish_rx_ring
 
 	wmb();
 
-	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), count);
 	write_dma_reg(mac, PAS_DMA_RXINT_INCR(mac->dma_if), count);
 
-	mac->rx->next_to_fill += count;
+	mac->rx->next_to_fill = (mac->rx->next_to_fill + count) &
+				(RX_RING_SIZE - 1);
 }
 
 static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
@@ -517,15 +516,19 @@ static int pasemi_mac_clean_rx(struct pa
 	int count;
 	struct pasemi_mac_buffer *info;
 	struct sk_buff *skb;
-	unsigned int i, len;
+	unsigned int len;
 	u64 macrx;
 	dma_addr_t dma;
+	int buf_index;
+	u64 eval;
 
 	spin_lock(&mac->rx->lock);
 
 	n = mac->rx->next_to_clean;
 
-	for (count = limit; count; count--) {
+	prefetch(RX_RING(mac, n));
+
+	for (count = 0; count < limit; count++) {
 		macrx = RX_RING(mac, n);
 
 		if ((macrx & XCT_MACRX_E) ||
@@ -537,21 +540,14 @@ static int pasemi_mac_clean_rx(struct pa
 
 		info = NULL;
 
-		/* We have to scan for our skb since there's no way
-		 * to back-map them from the descriptor, and if we
-		 * have several receive channels then they might not
-		 * show up in the same order as they were put on the
-		 * interface ring.
-		 */
+		BUG_ON(!(macrx & XCT_MACRX_RR_8BRES));
 
-		dma = (RX_RING(mac, n+1) & XCT_PTR_ADDR_M);
-		for (i = mac->rx->next_to_fill;
-		     i < (mac->rx->next_to_fill + RX_RING_SIZE);
-		     i++) {
-			info = &RX_RING_INFO(mac, i);
-			if (info->dma == dma)
-				break;
-		}
+		eval = (RX_RING(mac, n+1) & XCT_RXRES_8B_EVAL_M) >>
+			XCT_RXRES_8B_EVAL_S;
+		buf_index = eval-1;
+
+		dma = (RX_RING(mac, n+2) & XCT_PTR_ADDR_M);
+		info = &RX_RING_INFO(mac, buf_index);
 
 		skb = info->skb;
 
@@ -600,9 +596,9 @@ static int pasemi_mac_clean_rx(struct pa
 		/* Need to zero it out since hardware doesn't, since the
 		 * replenish loop uses it to tell when it's done.
 		 */
-		RX_BUFF(mac, i) = 0;
+		RX_BUFF(mac, buf_index) = 0;
 
-		n += 2;
+		n += 4;
 	}
 
 	if (n > RX_RING_SIZE) {
@@ -610,8 +606,16 @@ static int pasemi_mac_clean_rx(struct pa
 		write_iob_reg(mac, PAS_IOB_COM_PKTHDRCNT, 0);
 		n &= (RX_RING_SIZE-1);
 	}
+
 	mac->rx->next_to_clean = n;
-	pasemi_mac_replenish_rx_ring(mac->netdev, limit-count);
+
+	/* Increase is in number of 16-byte entries, and since each descriptor
+	 * with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with
+	 * count*2.
+	 */
+	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), count << 1);
+
+	pasemi_mac_replenish_rx_ring(mac->netdev, count);
 
 	spin_unlock(&mac->rx->lock);
 
@@ -927,6 +931,8 @@ static int pasemi_mac_open(struct net_de
 
 	pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE);
 
+	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), RX_RING_SIZE>>1);
+
 	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
 		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
 
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -206,12 +206,15 @@ enum {
 #define    PAS_DMA_RXINT_RCMDSTA_DROPS_M	0xfffe0000
 #define    PAS_DMA_RXINT_RCMDSTA_DROPS_S	17
 #define PAS_DMA_RXINT_CFG(i)		(0x204+(i)*_PAS_DMA_RXINT_STRIDE)
+#define    PAS_DMA_RXINT_CFG_RBP	0x80000000
+#define    PAS_DMA_RXINT_CFG_ITRR	0x40000000
 #define    PAS_DMA_RXINT_CFG_DHL_M	0x07000000
 #define    PAS_DMA_RXINT_CFG_DHL_S	24
 #define    PAS_DMA_RXINT_CFG_DHL(x)	(((x) << PAS_DMA_RXINT_CFG_DHL_S) & \
 					 PAS_DMA_RXINT_CFG_DHL_M)
 #define    PAS_DMA_RXINT_CFG_LW		0x00200000
 #define    PAS_DMA_RXINT_CFG_L2		0x00100000
+#define    PAS_DMA_RXINT_CFG_HEN	0x00080000
 #define    PAS_DMA_RXINT_CFG_WIF	0x00000002
 #define    PAS_DMA_RXINT_CFG_WIL	0x00000001
 
@@ -425,10 +428,9 @@ enum {
 /* Receive descriptor fields */
 #define	XCT_MACRX_T		0x8000000000000000ull
 #define	XCT_MACRX_ST		0x4000000000000000ull
-#define XCT_MACRX_NORES		0x0000000000000000ull
-#define XCT_MACRX_8BRES		0x1000000000000000ull
-#define XCT_MACRX_24BRES	0x2000000000000000ull
-#define XCT_MACRX_40BRES	0x3000000000000000ull
+#define XCT_MACRX_RR_M		0x3000000000000000ull
+#define XCT_MACRX_RR_NORES	0x0000000000000000ull
+#define XCT_MACRX_RR_8BRES	0x1000000000000000ull
 #define XCT_MACRX_O		0x0400000000000000ull
 #define XCT_MACRX_E		0x0200000000000000ull
 #define XCT_MACRX_FF		0x0100000000000000ull
@@ -476,6 +478,17 @@ enum {
 #define XCT_PTR_ADDR(x)		((((long)(x)) << XCT_PTR_ADDR_S) & \
 				 XCT_PTR_ADDR_M)
 
+/* Receive interface 8byte result fields */
+#define XCT_RXRES_8B_L4O_M	0xff00000000000000ull
+#define XCT_RXRES_8B_L4O_S	56
+#define XCT_RXRES_8B_RULE_M	0x00ffff0000000000ull
+#define XCT_RXRES_8B_RULE_S	40
+#define XCT_RXRES_8B_EVAL_M	0x000000ffff000000ull
+#define XCT_RXRES_8B_EVAL_S	24
+#define XCT_RXRES_8B_HTYPE_M	0x0000000000f00000ull
+#define XCT_RXRES_8B_HASH_M	0x00000000000fffffull
+#define XCT_RXRES_8B_HASH_S	0
+
 /* Receive interface buffer fields */
 #define XCT_RXB_LEN_M		0x0ffff00000000000ull
 #define XCT_RXB_LEN_S		44

^ permalink raw reply

* [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
From: Olof Johansson @ 2007-10-02 21:27 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: clear out old errors on interface open

Clear out any pending errors when an interface is brought up. Since the bits
are sticky, they might be from interface shutdown time after firmware has
used it, etc.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -903,16 +903,27 @@ static int pasemi_mac_open(struct net_de
 
 	/* enable rx if */
 	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
-			   PAS_DMA_RXINT_RCMDSTA_EN);
+			   PAS_DMA_RXINT_RCMDSTA_EN |
+			   PAS_DMA_RXINT_RCMDSTA_DROPS_M |
+			   PAS_DMA_RXINT_RCMDSTA_BP |
+			   PAS_DMA_RXINT_RCMDSTA_OO |
+			   PAS_DMA_RXINT_RCMDSTA_BT);
 
 	/* enable rx channel */
 	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
 			   PAS_DMA_RXCHAN_CCMDSTA_EN |
-			   PAS_DMA_RXCHAN_CCMDSTA_DU);
+			   PAS_DMA_RXCHAN_CCMDSTA_DU |
+			   PAS_DMA_RXCHAN_CCMDSTA_OD |
+			   PAS_DMA_RXCHAN_CCMDSTA_FD |
+			   PAS_DMA_RXCHAN_CCMDSTA_DT);
 
 	/* enable tx channel */
 	write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
-			   PAS_DMA_TXCHAN_TCMDSTA_EN);
+			   PAS_DMA_TXCHAN_TCMDSTA_EN |
+			   PAS_DMA_TXCHAN_TCMDSTA_SZ |
+			   PAS_DMA_TXCHAN_TCMDSTA_DB |
+			   PAS_DMA_TXCHAN_TCMDSTA_DE |
+			   PAS_DMA_TXCHAN_TCMDSTA_DA);
 
 	pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE);
 
@@ -987,7 +998,7 @@ out_rx_resources:
 static int pasemi_mac_close(struct net_device *dev)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
-	unsigned int stat;
+	unsigned int sta;
 	int retries;
 
 	if (mac->phydev) {
@@ -998,6 +1009,26 @@ static int pasemi_mac_close(struct net_d
 	netif_stop_queue(dev);
 	napi_disable(&mac->napi);
 
+	sta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+	if (sta & (PAS_DMA_RXINT_RCMDSTA_BP |
+		      PAS_DMA_RXINT_RCMDSTA_OO |
+		      PAS_DMA_RXINT_RCMDSTA_BT))
+		printk(KERN_DEBUG "pasemi_mac: rcmdsta error: 0x%08x\n", sta);
+
+	sta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
+	if (sta & (PAS_DMA_RXCHAN_CCMDSTA_DU |
+		     PAS_DMA_RXCHAN_CCMDSTA_OD |
+		     PAS_DMA_RXCHAN_CCMDSTA_FD |
+		     PAS_DMA_RXCHAN_CCMDSTA_DT))
+		printk(KERN_DEBUG "pasemi_mac: ccmdsta error: 0x%08x\n", sta);
+
+	sta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
+	if (sta & (PAS_DMA_TXCHAN_TCMDSTA_SZ |
+		      PAS_DMA_TXCHAN_TCMDSTA_DB |
+		      PAS_DMA_TXCHAN_TCMDSTA_DE |
+		      PAS_DMA_TXCHAN_TCMDSTA_DA))
+		printk(KERN_DEBUG "pasemi_mac: tcmdsta error: 0x%08x\n", sta);
+
 	/* Clean out any pending buffers */
 	pasemi_mac_clean_tx(mac);
 	pasemi_mac_clean_rx(mac, RX_RING_SIZE);
@@ -1008,33 +1039,33 @@ static int pasemi_mac_close(struct net_d
 	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), PAS_DMA_RXCHAN_CCMDSTA_ST);
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
-		stat = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
-		if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT))
+		sta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
+		if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT))
 			break;
 		cond_resched();
 	}
 
-	if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
+	if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)
 		dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
-		stat = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
-		if (!(stat & PAS_DMA_RXCHAN_CCMDSTA_ACT))
+		sta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
+		if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT))
 			break;
 		cond_resched();
 	}
 
-	if (stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)
+	if (sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)
 		dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
-		stat = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
-		if (!(stat & PAS_DMA_RXINT_RCMDSTA_ACT))
+		sta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+		if (!(sta & PAS_DMA_RXINT_RCMDSTA_ACT))
 			break;
 		cond_resched();
 	}
 
-	if (stat & PAS_DMA_RXINT_RCMDSTA_ACT)
+	if (sta & PAS_DMA_RXINT_RCMDSTA_ACT)
 		dev_err(&mac->dma_pdev->dev, "Failed to stop rx interface\n");
 
 	/* Then, disable the channel. This must be done separately from
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -241,6 +241,10 @@ enum {
 #define    PAS_DMA_TXCHAN_TCMDSTA_EN	0x00000001	/* Enabled */
 #define    PAS_DMA_TXCHAN_TCMDSTA_ST	0x00000002	/* Stop interface */
 #define    PAS_DMA_TXCHAN_TCMDSTA_ACT	0x00010000	/* Active */
+#define    PAS_DMA_TXCHAN_TCMDSTA_SZ	0x00000800
+#define    PAS_DMA_TXCHAN_TCMDSTA_DB	0x00000400
+#define    PAS_DMA_TXCHAN_TCMDSTA_DE	0x00000200
+#define    PAS_DMA_TXCHAN_TCMDSTA_DA	0x00000100
 #define PAS_DMA_TXCHAN_CFG(c)     (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define    PAS_DMA_TXCHAN_CFG_TY_IFACE	0x00000000	/* Type = interface */
 #define    PAS_DMA_TXCHAN_CFG_TATTR_M	0x0000003c
@@ -283,6 +287,9 @@ enum {
 #define    PAS_DMA_RXCHAN_CCMDSTA_ST	0x00000002	/* Stop interface */
 #define    PAS_DMA_RXCHAN_CCMDSTA_ACT	0x00010000	/* Active */
 #define    PAS_DMA_RXCHAN_CCMDSTA_DU	0x00020000
+#define    PAS_DMA_RXCHAN_CCMDSTA_OD	0x00002000
+#define    PAS_DMA_RXCHAN_CCMDSTA_FD	0x00001000
+#define    PAS_DMA_RXCHAN_CCMDSTA_DT	0x00000800
 #define PAS_DMA_RXCHAN_CFG(c)     (0x804+(c)*_PAS_DMA_RXCHAN_STRIDE)
 #define    PAS_DMA_RXCHAN_CFG_HBU_M	0x00000380
 #define    PAS_DMA_RXCHAN_CFG_HBU_S	7

^ permalink raw reply

* [PATCH] [8/11] pasemi_mac: update todo list
From: Olof Johansson @ 2007-10-02 21:27 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: update todo list

Remove some stale todo items that have been taken care of. Add a couple
of upcoming ones.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: 2.6.23/drivers/net/pasemi_mac.c
===================================================================
--- 2.6.23.orig/drivers/net/pasemi_mac.c
+++ 2.6.23/drivers/net/pasemi_mac.c
@@ -46,12 +46,10 @@
 
 /* TODO list
  *
- * - Get rid of pci_{read,write}_config(), map registers with ioremap
- *   for performance
- * - PHY support
  * - Multicast support
  * - Large MTU support
- * - Other performance improvements
+ * - SW LRO
+ * - Multiqueue RX/TX
  */
 
 

^ permalink raw reply

* [PATCH] [7/11] pasemi_mac: further performance tweaks
From: Olof Johansson @ 2007-10-02 21:27 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: further performance tweaks

Misc driver tweaks for pasemi_mac:
	* Increase ring size (really needed mostly on 10G)
	* Take out an unneeded barrier
	* Move around a few prefetches and reorder a few calls
	* Don't try to clean on full tx buffer, just let things
	  take their course and stop the queue directly
	* Avoid filling on the same line as the interface is
	  working on to reduce cache line bouncing
	* Avoid unneeded clearing of software state (and make the
	  interface shutdown code handle it)
	* Fix up some of the tx ring wrap logic.


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -56,8 +56,8 @@
 
 
 /* Must be a power of two */
-#define RX_RING_SIZE 512
-#define TX_RING_SIZE 512
+#define RX_RING_SIZE 4096
+#define TX_RING_SIZE 4096
 
 #define DEFAULT_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
@@ -336,8 +336,16 @@ static void pasemi_mac_free_tx_resources
 	struct pasemi_mac_buffer *info;
 	dma_addr_t dmas[MAX_SKB_FRAGS+1];
 	int freed;
+	int start, limit;
 
-	for (i = 0; i < TX_RING_SIZE; i += freed) {
+	start = mac->tx->next_to_clean;
+	limit = mac->tx->next_to_fill;
+
+	/* Compensate for when fill has wrapped and clean has not */
+	if (start > limit)
+		limit += TX_RING_SIZE;
+
+	for (i = start; i < limit; i += freed) {
 		info = &TX_RING_INFO(mac, i+1);
 		if (info->dma && info->skb) {
 			for (j = 0; j <= skb_shinfo(info->skb)->nr_frags; j++)
@@ -520,9 +528,6 @@ static int pasemi_mac_clean_rx(struct pa
 	n = mac->rx->next_to_clean;
 
 	for (count = limit; count; count--) {
-
-		rmb();
-
 		macrx = RX_RING(mac, n);
 
 		if ((macrx & XCT_MACRX_E) ||
@@ -550,14 +555,10 @@ static int pasemi_mac_clean_rx(struct pa
 				break;
 		}
 
-		prefetchw(info);
-
 		skb = info->skb;
-		prefetchw(skb);
-		info->dma = 0;
 
-		pci_unmap_single(mac->dma_pdev, dma, skb->len,
-				 PCI_DMA_FROMDEVICE);
+		prefetch(skb);
+		prefetch(&skb->data_len);
 
 		len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
 
@@ -576,10 +577,9 @@ static int pasemi_mac_clean_rx(struct pa
 		} else
 			info->skb = NULL;
 
-		/* Need to zero it out since hardware doesn't, since the
-		 * replenish loop uses it to tell when it's done.
-		 */
-		RX_BUFF(mac, i) = 0;
+		pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE);
+
+		info->dma = 0;
 
 		skb_put(skb, len);
 
@@ -599,6 +599,11 @@ static int pasemi_mac_clean_rx(struct pa
 		RX_RING(mac, n) = 0;
 		RX_RING(mac, n+1) = 0;
 
+		/* Need to zero it out since hardware doesn't, since the
+		 * replenish loop uses it to tell when it's done.
+		 */
+		RX_BUFF(mac, i) = 0;
+
 		n += 2;
 	}
 
@@ -621,27 +626,33 @@ static int pasemi_mac_clean_rx(struct pa
 static int pasemi_mac_clean_tx(struct pasemi_mac *mac)
 {
 	int i, j;
-	struct pasemi_mac_buffer *info;
-	unsigned int start, descr_count, buf_count, limit;
+	unsigned int start, descr_count, buf_count, batch_limit;
+	unsigned int ring_limit;
 	unsigned int total_count;
 	unsigned long flags;
 	struct sk_buff *skbs[TX_CLEAN_BATCHSIZE];
 	dma_addr_t dmas[TX_CLEAN_BATCHSIZE][MAX_SKB_FRAGS+1];
 
 	total_count = 0;
-	limit = TX_CLEAN_BATCHSIZE;
+	batch_limit = TX_CLEAN_BATCHSIZE;
 restart:
 	spin_lock_irqsave(&mac->tx->lock, flags);
 
 	start = mac->tx->next_to_clean;
+	ring_limit = mac->tx->next_to_fill;
+
+	/* Compensate for when fill has wrapped but clean has not */
+	if (start > ring_limit)
+		ring_limit += TX_RING_SIZE;
 
 	buf_count = 0;
 	descr_count = 0;
 
 	for (i = start;
-	     descr_count < limit && i < mac->tx->next_to_fill;
+	     descr_count < batch_limit && i < ring_limit;
 	     i += buf_count) {
 		u64 mactx = TX_RING(mac, i);
+		struct sk_buff *skb;
 
 		if ((mactx  & XCT_MACTX_E) ||
 		    (*mac->tx_status & PAS_STATUS_ERROR))
@@ -651,19 +662,15 @@ restart:
 			/* Not yet transmitted */
 			break;
 
-		info = &TX_RING_INFO(mac, i+1);
-		skbs[descr_count] = info->skb;
+		skb = TX_RING_INFO(mac, i+1).skb;
+		skbs[descr_count] = skb;
 
-		buf_count = 2 + skb_shinfo(info->skb)->nr_frags;
-		for (j = 0; j <= skb_shinfo(info->skb)->nr_frags; j++)
+		buf_count = 2 + skb_shinfo(skb)->nr_frags;
+		for (j = 0; j <= skb_shinfo(skb)->nr_frags; j++)
 			dmas[descr_count][j] = TX_RING_INFO(mac, i+1+j).dma;
 
-
-		info->dma = 0;
 		TX_RING(mac, i) = 0;
 		TX_RING(mac, i+1) = 0;
-		TX_RING_INFO(mac, i+1).skb = 0;
-		TX_RING_INFO(mac, i+1).dma = 0;
 
 		/* Since we always fill with an even number of entries, make
 		 * sure we skip any unused one at the end as well.
@@ -672,7 +679,7 @@ restart:
 			buf_count++;
 		descr_count++;
 	}
-	mac->tx->next_to_clean = i;
+	mac->tx->next_to_clean = i & (TX_RING_SIZE-1);
 
 	spin_unlock_irqrestore(&mac->tx->lock, flags);
 	netif_wake_queue(mac->netdev);
@@ -683,7 +690,7 @@ restart:
 	total_count += descr_count;
 
 	/* If the batch was full, try to clean more */
-	if (descr_count == limit)
+	if (descr_count == batch_limit)
 		goto restart;
 
 	return total_count;
@@ -1106,19 +1113,14 @@ static int pasemi_mac_start_tx(struct sk
 
 	spin_lock_irqsave(&txring->lock, flags);
 
-	if (RING_AVAIL(txring) <= nfrags+3) {
-		spin_unlock_irqrestore(&txring->lock, flags);
-		pasemi_mac_clean_tx(mac);
-		pasemi_mac_restart_tx_intr(mac);
-		spin_lock_irqsave(&txring->lock, flags);
-
-		if (RING_AVAIL(txring) <= nfrags+3) {
-			/* Still no room -- stop the queue and wait for tx
-			 * intr when there's room.
-			 */
-			netif_stop_queue(dev);
-			goto out_err;
-		}
+	/* Avoid stepping on the same cache line that the DMA controller
+	 * is currently about to send, so leave at least 8 words available.
+	 * Total free space needed is mactx + fragments + 8
+	 */
+	if (RING_AVAIL(txring) < nfrags + 10) {
+		/* no room -- stop the queue and wait for tx intr */
+		netif_stop_queue(dev);
+		goto out_err;
 	}
 
 	TX_RING(mac, txring->next_to_fill) = mactx;
@@ -1137,8 +1139,8 @@ static int pasemi_mac_start_tx(struct sk
 	if (nfrags & 1)
 		nfrags++;
 
-	txring->next_to_fill += nfrags + 1;
-
+	txring->next_to_fill = (txring->next_to_fill + nfrags + 1) &
+				(TX_RING_SIZE-1);
 
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;

^ permalink raw reply

* [PATCH] [6/11] pasemi_mac: add local skb alignment
From: Olof Johansson @ 2007-10-02 21:26 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: add local skb alignment

Add local SKB alignment to pasemi_mac, since ppc64 in general has it at 0
because of design flaws in some of the IBM server bridge chips. However,
for PWRficient doing the unaligned copies is more expensive than doing
unaligned DMA so make sure the data is aligned instead.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -37,6 +37,12 @@
 
 #include "pasemi_mac.h"
 
+/* We have our own align, since ppc64 in general has it at 0 because
+ * of design flaws in some of the server bridge chips. However, for
+ * PWRficient doing the unaligned copies is more expensive than doing
+ * unaligned DMA, so make sure the data is aligned instead.
+ */
+#define LOCAL_SKB_ALIGN	2
 
 /* TODO list
  *
@@ -409,13 +415,16 @@ static void pasemi_mac_replenish_rx_ring
 		/* skb might still be in there for recycle on short receives */
 		if (info->skb)
 			skb = info->skb;
-		else
+		else {
 			skb = dev_alloc_skb(BUF_SIZE);
+			skb_reserve(skb, LOCAL_SKB_ALIGN);
+		}
 
 		if (unlikely(!skb))
 			break;
 
-		dma = pci_map_single(mac->dma_pdev, skb->data, BUF_SIZE,
+		dma = pci_map_single(mac->dma_pdev, skb->data,
+				     BUF_SIZE - LOCAL_SKB_ALIGN,
 				     PCI_DMA_FROMDEVICE);
 
 		if (unlikely(dma_mapping_error(dma))) {
@@ -553,10 +562,12 @@ static int pasemi_mac_clean_rx(struct pa
 		len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
 
 		if (len < 256) {
-			struct sk_buff *new_skb =
-			    netdev_alloc_skb(mac->netdev, len + NET_IP_ALIGN);
+			struct sk_buff *new_skb;
+
+			new_skb = netdev_alloc_skb(mac->netdev,
+						   len + LOCAL_SKB_ALIGN);
 			if (new_skb) {
-				skb_reserve(new_skb, NET_IP_ALIGN);
+				skb_reserve(new_skb, LOCAL_SKB_ALIGN);
 				memcpy(new_skb->data, skb->data, len);
 				/* save the skb in buffer_info as good */
 				skb = new_skb;

^ permalink raw reply

* [PATCH] [5/11] pasemi_mac: workaround for erratum 5971
From: Olof Johansson @ 2007-10-02 21:26 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: workaround for erratum 5971

Implement workarounds for erratum 5971, where L2 hints aren't considered
properly unless the way hint is enabled on the interface. Since L2 isn't
setup to dedicate a way to headers, we need to reset the packet count
by hand so it won't run out of credits.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -239,7 +239,9 @@ static int pasemi_mac_setup_rx_resources
 			   PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
 
 	write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if),
-			   PAS_DMA_RXINT_CFG_DHL(2));
+			   PAS_DMA_RXINT_CFG_DHL(3) |
+			   PAS_DMA_RXINT_CFG_L2 |
+			   PAS_DMA_RXINT_CFG_LW);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
@@ -589,6 +591,11 @@ static int pasemi_mac_clean_rx(struct pa
 		n += 2;
 	}
 
+	if (n > RX_RING_SIZE) {
+		/* Errata 5971 workaround: L2 target of headers */
+		write_iob_reg(mac, PAS_IOB_COM_PKTHDRCNT, 0);
+		n &= (RX_RING_SIZE-1);
+	}
 	mac->rx->next_to_clean = n;
 	pasemi_mac_replenish_rx_ring(mac->netdev, limit-count);
 
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -210,6 +210,8 @@ enum {
 #define    PAS_DMA_RXINT_CFG_DHL_S	24
 #define    PAS_DMA_RXINT_CFG_DHL(x)	(((x) << PAS_DMA_RXINT_CFG_DHL_S) & \
 					 PAS_DMA_RXINT_CFG_DHL_M)
+#define    PAS_DMA_RXINT_CFG_LW		0x00200000
+#define    PAS_DMA_RXINT_CFG_L2		0x00100000
 #define    PAS_DMA_RXINT_CFG_WIF	0x00000002
 #define    PAS_DMA_RXINT_CFG_WIL	0x00000001
 
@@ -315,6 +317,12 @@ enum {
 #define    PAS_STATUS_SOFT		0x4000000000000000ull
 #define    PAS_STATUS_INT		0x8000000000000000ull
 
+#define PAS_IOB_COM_PKTHDRCNT		0x120
+#define    PAS_IOB_COM_PKTHDRCNT_PKTHDR1_M	0x0fff0000
+#define    PAS_IOB_COM_PKTHDRCNT_PKTHDR1_S	16
+#define    PAS_IOB_COM_PKTHDRCNT_PKTHDR0_M	0x00000fff
+#define    PAS_IOB_COM_PKTHDRCNT_PKTHDR0_S	0
+
 #define PAS_IOB_DMA_RXCH_CFG(i)		(0x1100 + (i)*4)
 #define    PAS_IOB_DMA_RXCH_CFG_CNTTH_M		0x00000fff
 #define    PAS_IOB_DMA_RXCH_CFG_CNTTH_S		0

^ permalink raw reply

* [PATCH] [4/11] pasemi_mac: implement sg support
From: Olof Johansson @ 2007-10-02 21:26 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: implement sg support

Implement SG support for pasemi_mac

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -160,6 +160,30 @@ static int pasemi_get_mac_addr(struct pa
 	return 0;
 }
 
+static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
+				    struct sk_buff *skb,
+				    dma_addr_t *dmas)
+{
+	int f;
+	int nfrags = skb_shinfo(skb)->nr_frags;
+
+	pci_unmap_single(mac->dma_pdev, dmas[0], skb_headlen(skb),
+			 PCI_DMA_TODEVICE);
+
+	for (f = 0; f < nfrags; f++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
+
+		pci_unmap_page(mac->dma_pdev, dmas[f+1], frag->size,
+			       PCI_DMA_TODEVICE);
+	}
+	dev_kfree_skb_irq(skb);
+
+	/* Freed descriptor slot + main SKB ptr + nfrags additional ptrs,
+	 * aligned up to a power of 2
+	 */
+	return (nfrags + 3) & ~1;
+}
+
 static int pasemi_mac_setup_rx_resources(struct net_device *dev)
 {
 	struct pasemi_mac_rxring *ring;
@@ -300,24 +324,24 @@ out_ring:
 static void pasemi_mac_free_tx_resources(struct net_device *dev)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
-	unsigned int i;
+	unsigned int i, j;
 	struct pasemi_mac_buffer *info;
+	dma_addr_t dmas[MAX_SKB_FRAGS+1];
+	int freed;
 
-	for (i = 0; i < TX_RING_SIZE; i += 2) {
+	for (i = 0; i < TX_RING_SIZE; i += freed) {
 		info = &TX_RING_INFO(mac, i+1);
 		if (info->dma && info->skb) {
-			pci_unmap_single(mac->dma_pdev,
-					 info->dma,
-					 info->skb->len,
-					 PCI_DMA_TODEVICE);
-			dev_kfree_skb_any(info->skb);
-		}
-		TX_RING(mac, i) = 0;
-		TX_RING(mac, i+1) = 0;
-		info->dma = 0;
-		info->skb = NULL;
+			for (j = 0; j <= skb_shinfo(info->skb)->nr_frags; j++)
+				dmas[j] = TX_RING_INFO(mac, i+1+j).dma;
+			freed = pasemi_mac_unmap_tx_skb(mac, info->skb, dmas);
+		} else
+			freed = 2;
 	}
 
+	for (i = 0; i < TX_RING_SIZE; i++)
+		TX_RING(mac, i) = 0;
+
 	dma_free_coherent(&mac->dma_pdev->dev,
 			  TX_RING_SIZE * sizeof(u64),
 			  mac->tx->ring, mac->tx->dma);
@@ -573,27 +597,34 @@ static int pasemi_mac_clean_rx(struct pa
 	return count;
 }
 
+/* Can't make this too large or we blow the kernel stack limits */
+#define TX_CLEAN_BATCHSIZE (128/MAX_SKB_FRAGS)
+
 static int pasemi_mac_clean_tx(struct pasemi_mac *mac)
 {
-	int i;
+	int i, j;
 	struct pasemi_mac_buffer *info;
-	unsigned int start, count, limit;
+	unsigned int start, descr_count, buf_count, limit;
 	unsigned int total_count;
 	unsigned long flags;
-	struct sk_buff *skbs[32];
-	dma_addr_t dmas[32];
+	struct sk_buff *skbs[TX_CLEAN_BATCHSIZE];
+	dma_addr_t dmas[TX_CLEAN_BATCHSIZE][MAX_SKB_FRAGS+1];
 
 	total_count = 0;
+	limit = TX_CLEAN_BATCHSIZE;
 restart:
 	spin_lock_irqsave(&mac->tx->lock, flags);
 
 	start = mac->tx->next_to_clean;
-	limit = min(mac->tx->next_to_fill, start+32);
 
-	count = 0;
+	buf_count = 0;
+	descr_count = 0;
 
-	for (i = start; i < limit; i += 2) {
+	for (i = start;
+	     descr_count < limit && i < mac->tx->next_to_fill;
+	     i += buf_count) {
 		u64 mactx = TX_RING(mac, i);
+
 		if ((mactx  & XCT_MACTX_E) ||
 		    (*mac->tx_status & PAS_STATUS_ERROR))
 			pasemi_mac_tx_error(mac, mactx);
@@ -603,30 +634,38 @@ restart:
 			break;
 
 		info = &TX_RING_INFO(mac, i+1);
-		skbs[count] = info->skb;
-		dmas[count] = info->dma;
+		skbs[descr_count] = info->skb;
+
+		buf_count = 2 + skb_shinfo(info->skb)->nr_frags;
+		for (j = 0; j <= skb_shinfo(info->skb)->nr_frags; j++)
+			dmas[descr_count][j] = TX_RING_INFO(mac, i+1+j).dma;
+
 
 		info->dma = 0;
 		TX_RING(mac, i) = 0;
 		TX_RING(mac, i+1) = 0;
+		TX_RING_INFO(mac, i+1).skb = 0;
+		TX_RING_INFO(mac, i+1).dma = 0;
 
-
-		count++;
+		/* Since we always fill with an even number of entries, make
+		 * sure we skip any unused one at the end as well.
+		 */
+		if (buf_count & 1)
+			buf_count++;
+		descr_count++;
 	}
-	mac->tx->next_to_clean += count * 2;
+	mac->tx->next_to_clean = i;
+
 	spin_unlock_irqrestore(&mac->tx->lock, flags);
 	netif_wake_queue(mac->netdev);
 
-	for (i = 0; i < count; i++) {
-		pci_unmap_single(mac->dma_pdev, dmas[i],
-				 skbs[i]->len, PCI_DMA_TODEVICE);
-		dev_kfree_skb_irq(skbs[i]);
-	}
+	for (i = 0; i < descr_count; i++)
+		pasemi_mac_unmap_tx_skb(mac, skbs[i], dmas[i]);
 
-	total_count += count;
+	total_count += descr_count;
 
 	/* If the batch was full, try to clean more */
-	if (count == 32)
+	if (descr_count == limit)
 		goto restart;
 
 	return total_count;
@@ -997,9 +1036,11 @@ static int pasemi_mac_start_tx(struct sk
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	struct pasemi_mac_txring *txring;
-	u64 dflags, mactx, ptr;
-	dma_addr_t map;
+	u64 dflags, mactx;
+	dma_addr_t map[MAX_SKB_FRAGS+1];
+	unsigned int map_size[MAX_SKB_FRAGS+1];
 	unsigned long flags;
+	int i, nfrags;
 
 	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_SS | XCT_MACTX_CRC_PAD;
 
@@ -1020,25 +1061,40 @@ static int pasemi_mac_start_tx(struct sk
 		}
 	}
 
-	map = pci_map_single(mac->dma_pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+	nfrags = skb_shinfo(skb)->nr_frags;
 
-	if (dma_mapping_error(map))
-		return NETDEV_TX_BUSY;
+	map[0] = pci_map_single(mac->dma_pdev, skb->data, skb_headlen(skb),
+				PCI_DMA_TODEVICE);
+	map_size[0] = skb_headlen(skb);
+	if (dma_mapping_error(map[0]))
+		goto out_err_nolock;
+
+	for (i = 0; i < nfrags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+		map[i+1] = pci_map_page(mac->dma_pdev, frag->page,
+					frag->page_offset, frag->size,
+					PCI_DMA_TODEVICE);
+		map_size[i+1] = frag->size;
+		if (dma_mapping_error(map[i+1])) {
+			nfrags = i;
+			goto out_err_nolock;
+		}
+	}
 
 	mactx = dflags | XCT_MACTX_LLEN(skb->len);
-	ptr   = XCT_PTR_LEN(skb->len) | XCT_PTR_ADDR(map);
 
 	txring = mac->tx;
 
 	spin_lock_irqsave(&txring->lock, flags);
 
-	if (RING_AVAIL(txring) <= 2) {
+	if (RING_AVAIL(txring) <= nfrags+3) {
 		spin_unlock_irqrestore(&txring->lock, flags);
 		pasemi_mac_clean_tx(mac);
 		pasemi_mac_restart_tx_intr(mac);
 		spin_lock_irqsave(&txring->lock, flags);
 
-		if (RING_AVAIL(txring) <= 2) {
+		if (RING_AVAIL(txring) <= nfrags+3) {
 			/* Still no room -- stop the queue and wait for tx
 			 * intr when there's room.
 			 */
@@ -1048,25 +1104,40 @@ static int pasemi_mac_start_tx(struct sk
 	}
 
 	TX_RING(mac, txring->next_to_fill) = mactx;
-	TX_RING(mac, txring->next_to_fill+1) = ptr;
+	txring->next_to_fill++;
+	TX_RING_INFO(mac, txring->next_to_fill).skb = skb;
+	for (i = 0; i <= nfrags; i++) {
+		TX_RING(mac, txring->next_to_fill+i) =
+		XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
+		TX_RING_INFO(mac, txring->next_to_fill+i).dma = map[i];
+	}
+
+	/* We have to add an even number of 8-byte entries to the ring
+	 * even if the last one is unused. That means always an odd number
+	 * of pointers + one mactx descriptor.
+	 */
+	if (nfrags & 1)
+		nfrags++;
 
-	TX_RING_INFO(mac, txring->next_to_fill+1).dma = map;
-	TX_RING_INFO(mac, txring->next_to_fill+1).skb = skb;
+	txring->next_to_fill += nfrags + 1;
 
-	txring->next_to_fill += 2;
 
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
 
 	spin_unlock_irqrestore(&txring->lock, flags);
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_INCR(mac->dma_txch), 1);
+	write_dma_reg(mac, PAS_DMA_TXCHAN_INCR(mac->dma_txch), (nfrags+2) >> 1);
 
 	return NETDEV_TX_OK;
 
 out_err:
 	spin_unlock_irqrestore(&txring->lock, flags);
-	pci_unmap_single(mac->dma_pdev, map, skb->len, PCI_DMA_TODEVICE);
+out_err_nolock:
+	while (nfrags--)
+		pci_unmap_single(mac->dma_pdev, map[nfrags], map_size[nfrags],
+				 PCI_DMA_TODEVICE);
+
 	return NETDEV_TX_BUSY;
 }
 
@@ -1202,7 +1273,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 
 	netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
 
-	dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
+	dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX | NETIF_F_SG;
 
 	/* These should come out of the device tree eventually */
 	mac->dma_txch = index;

^ permalink raw reply

* [PATCH] [3/11] pasemi_mac: rework ring management
From: Olof Johansson @ 2007-10-02 21:25 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: rework ring management

Rework ring management, switching to an opaque ring format instead of
the struct-based descriptor+pointer setup, since it will be needed for
SG support.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -63,10 +63,10 @@
 	 NETIF_MSG_RX_ERR	| \
 	 NETIF_MSG_TX_ERR)
 
-#define TX_DESC(mac, num)	((mac)->tx->desc[(num) & (TX_RING_SIZE-1)])
-#define TX_DESC_INFO(mac, num)	((mac)->tx->desc_info[(num) & (TX_RING_SIZE-1)])
-#define RX_DESC(mac, num)	((mac)->rx->desc[(num) & (RX_RING_SIZE-1)])
-#define RX_DESC_INFO(mac, num)	((mac)->rx->desc_info[(num) & (RX_RING_SIZE-1)])
+#define TX_RING(mac, num)	((mac)->tx->ring[(num) & (TX_RING_SIZE-1)])
+#define TX_RING_INFO(mac, num)	((mac)->tx->ring_info[(num) & (TX_RING_SIZE-1)])
+#define RX_RING(mac, num)	((mac)->rx->ring[(num) & (RX_RING_SIZE-1)])
+#define RX_RING_INFO(mac, num)	((mac)->rx->ring_info[(num) & (RX_RING_SIZE-1)])
 #define RX_BUFF(mac, num)	((mac)->rx->buffers[(num) & (RX_RING_SIZE-1)])
 
 #define RING_USED(ring)		(((ring)->next_to_fill - (ring)->next_to_clean) \
@@ -174,22 +174,21 @@ static int pasemi_mac_setup_rx_resources
 	spin_lock_init(&ring->lock);
 
 	ring->size = RX_RING_SIZE;
-	ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
+	ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
 				  RX_RING_SIZE, GFP_KERNEL);
 
-	if (!ring->desc_info)
-		goto out_desc_info;
+	if (!ring->ring_info)
+		goto out_ring_info;
 
 	/* Allocate descriptors */
-	ring->desc = dma_alloc_coherent(&mac->dma_pdev->dev,
-					RX_RING_SIZE *
-					sizeof(struct pas_dma_xct_descr),
+	ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
+					RX_RING_SIZE * sizeof(u64),
 					&ring->dma, GFP_KERNEL);
 
-	if (!ring->desc)
-		goto out_desc;
+	if (!ring->ring)
+		goto out_ring_desc;
 
-	memset(ring->desc, 0, RX_RING_SIZE * sizeof(struct pas_dma_xct_descr));
+	memset(ring->ring, 0, RX_RING_SIZE * sizeof(u64));
 
 	ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
 					   RX_RING_SIZE * sizeof(u64),
@@ -203,7 +202,7 @@ static int pasemi_mac_setup_rx_resources
 
 	write_dma_reg(mac, PAS_DMA_RXCHAN_BASEU(chan_id),
 			   PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) |
-			   PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 2));
+			   PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3));
 
 	write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id),
 			   PAS_DMA_RXCHAN_CFG_HBU(2));
@@ -229,11 +228,11 @@ static int pasemi_mac_setup_rx_resources
 
 out_buffers:
 	dma_free_coherent(&mac->dma_pdev->dev,
-			  RX_RING_SIZE * sizeof(struct pas_dma_xct_descr),
-			  mac->rx->desc, mac->rx->dma);
-out_desc:
-	kfree(ring->desc_info);
-out_desc_info:
+			  RX_RING_SIZE * sizeof(u64),
+			  mac->rx->ring, mac->rx->dma);
+out_ring_desc:
+	kfree(ring->ring_info);
+out_ring_info:
 	kfree(ring);
 out_ring:
 	return -ENOMEM;
@@ -254,25 +253,24 @@ static int pasemi_mac_setup_tx_resources
 	spin_lock_init(&ring->lock);
 
 	ring->size = TX_RING_SIZE;
-	ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
+	ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
 				  TX_RING_SIZE, GFP_KERNEL);
-	if (!ring->desc_info)
-		goto out_desc_info;
+	if (!ring->ring_info)
+		goto out_ring_info;
 
 	/* Allocate descriptors */
-	ring->desc = dma_alloc_coherent(&mac->dma_pdev->dev,
-					TX_RING_SIZE *
-					sizeof(struct pas_dma_xct_descr),
+	ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
+					TX_RING_SIZE * sizeof(u64),
 					&ring->dma, GFP_KERNEL);
-	if (!ring->desc)
-		goto out_desc;
+	if (!ring->ring)
+		goto out_ring_desc;
 
-	memset(ring->desc, 0, TX_RING_SIZE * sizeof(struct pas_dma_xct_descr));
+	memset(ring->ring, 0, TX_RING_SIZE * sizeof(u64));
 
 	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEL(chan_id),
 			   PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma));
 	val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->dma >> 32);
-	val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 2);
+	val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 3);
 
 	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val);
 
@@ -291,9 +289,9 @@ static int pasemi_mac_setup_tx_resources
 
 	return 0;
 
-out_desc:
-	kfree(ring->desc_info);
-out_desc_info:
+out_ring_desc:
+	kfree(ring->ring_info);
+out_ring_info:
 	kfree(ring);
 out_ring:
 	return -ENOMEM;
@@ -304,31 +302,27 @@ static void pasemi_mac_free_tx_resources
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int i;
 	struct pasemi_mac_buffer *info;
-	struct pas_dma_xct_descr *dp;
 
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		info = &TX_DESC_INFO(mac, i);
-		dp = &TX_DESC(mac, i);
-		if (info->dma) {
-			if (info->skb) {
-				pci_unmap_single(mac->dma_pdev,
-						 info->dma,
-						 info->skb->len,
-						 PCI_DMA_TODEVICE);
-				dev_kfree_skb_any(info->skb);
-			}
-			info->dma = 0;
-			info->skb = NULL;
-			dp->mactx = 0;
-			dp->ptr = 0;
+	for (i = 0; i < TX_RING_SIZE; i += 2) {
+		info = &TX_RING_INFO(mac, i+1);
+		if (info->dma && info->skb) {
+			pci_unmap_single(mac->dma_pdev,
+					 info->dma,
+					 info->skb->len,
+					 PCI_DMA_TODEVICE);
+			dev_kfree_skb_any(info->skb);
 		}
+		TX_RING(mac, i) = 0;
+		TX_RING(mac, i+1) = 0;
+		info->dma = 0;
+		info->skb = NULL;
 	}
 
 	dma_free_coherent(&mac->dma_pdev->dev,
-			  TX_RING_SIZE * sizeof(struct pas_dma_xct_descr),
-			  mac->tx->desc, mac->tx->dma);
+			  TX_RING_SIZE * sizeof(u64),
+			  mac->tx->ring, mac->tx->dma);
 
-	kfree(mac->tx->desc_info);
+	kfree(mac->tx->ring_info);
 	kfree(mac->tx);
 	mac->tx = NULL;
 }
@@ -338,34 +332,31 @@ static void pasemi_mac_free_rx_resources
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int i;
 	struct pasemi_mac_buffer *info;
-	struct pas_dma_xct_descr *dp;
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		info = &RX_DESC_INFO(mac, i);
-		dp = &RX_DESC(mac, i);
-		if (info->skb) {
-			if (info->dma) {
-				pci_unmap_single(mac->dma_pdev,
-						 info->dma,
-						 info->skb->len,
-						 PCI_DMA_FROMDEVICE);
-				dev_kfree_skb_any(info->skb);
-			}
-			info->dma = 0;
-			info->skb = NULL;
-			dp->macrx = 0;
-			dp->ptr = 0;
+		info = &RX_RING_INFO(mac, i);
+		if (info->skb && info->dma) {
+			pci_unmap_single(mac->dma_pdev,
+					 info->dma,
+					 info->skb->len,
+					 PCI_DMA_FROMDEVICE);
+			dev_kfree_skb_any(info->skb);
 		}
+		info->dma = 0;
+		info->skb = NULL;
 	}
 
+	for (i = 0; i < RX_RING_SIZE; i++)
+		RX_RING(mac, i) = 0;
+
 	dma_free_coherent(&mac->dma_pdev->dev,
-			  RX_RING_SIZE * sizeof(struct pas_dma_xct_descr),
-			  mac->rx->desc, mac->rx->dma);
+			  RX_RING_SIZE * sizeof(u64),
+			  mac->rx->ring, mac->rx->dma);
 
 	dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
 			  mac->rx->buffers, mac->rx->buf_dma);
 
-	kfree(mac->rx->desc_info);
+	kfree(mac->rx->ring_info);
 	kfree(mac->rx);
 	mac->rx = NULL;
 }
@@ -373,20 +364,22 @@ static void pasemi_mac_free_rx_resources
 static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
-	unsigned int i;
 	int start = mac->rx->next_to_fill;
-	int count;
+	unsigned int fill, count;
 
 	if (limit <= 0)
 		return;
 
-	i = start;
+	fill = start;
 	for (count = 0; count < limit; count++) {
-		struct pasemi_mac_buffer *info = &RX_DESC_INFO(mac, i);
-		u64 *buff = &RX_BUFF(mac, i);
+		struct pasemi_mac_buffer *info = &RX_RING_INFO(mac, fill);
+		u64 *buff = &RX_BUFF(mac, fill);
 		struct sk_buff *skb;
 		dma_addr_t dma;
 
+		/* Entry in use? */
+		WARN_ON(*buff);
+
 		/* skb might still be in there for recycle on short receives */
 		if (info->skb)
 			skb = info->skb;
@@ -407,7 +400,7 @@ static void pasemi_mac_replenish_rx_ring
 		info->skb = skb;
 		info->dma = dma;
 		*buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma);
-		i++;
+		fill++;
 	}
 
 	wmb();
@@ -481,7 +474,6 @@ static int pasemi_mac_clean_rx(struct pa
 {
 	unsigned int n;
 	int count;
-	struct pas_dma_xct_descr *dp;
 	struct pasemi_mac_buffer *info;
 	struct sk_buff *skb;
 	unsigned int i, len;
@@ -496,9 +488,7 @@ static int pasemi_mac_clean_rx(struct pa
 
 		rmb();
 
-		dp = &RX_DESC(mac, n);
-		prefetchw(dp);
-		macrx = dp->macrx;
+		macrx = RX_RING(mac, n);
 
 		if ((macrx & XCT_MACRX_E) ||
 		    (*mac->rx_status & PAS_STATUS_ERROR))
@@ -516,12 +506,15 @@ static int pasemi_mac_clean_rx(struct pa
 		 * interface ring.
 		 */
 
-		dma = (dp->ptr & XCT_PTR_ADDR_M);
-		for (i = n; i < (n + RX_RING_SIZE); i++) {
-			info = &RX_DESC_INFO(mac, i);
+		dma = (RX_RING(mac, n+1) & XCT_PTR_ADDR_M);
+		for (i = mac->rx->next_to_fill;
+		     i < (mac->rx->next_to_fill + RX_RING_SIZE);
+		     i++) {
+			info = &RX_RING_INFO(mac, i);
 			if (info->dma == dma)
 				break;
 		}
+
 		prefetchw(info);
 
 		skb = info->skb;
@@ -546,6 +539,11 @@ static int pasemi_mac_clean_rx(struct pa
 		} else
 			info->skb = NULL;
 
+		/* Need to zero it out since hardware doesn't, since the
+		 * replenish loop uses it to tell when it's done.
+		 */
+		RX_BUFF(mac, i) = 0;
+
 		skb_put(skb, len);
 
 		if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {
@@ -561,13 +559,13 @@ static int pasemi_mac_clean_rx(struct pa
 		skb->protocol = eth_type_trans(skb, mac->netdev);
 		netif_receive_skb(skb);
 
-		dp->ptr = 0;
-		dp->macrx = 0;
+		RX_RING(mac, n) = 0;
+		RX_RING(mac, n+1) = 0;
 
-		n++;
+		n += 2;
 	}
 
-	mac->rx->next_to_clean += limit - count;
+	mac->rx->next_to_clean = n;
 	pasemi_mac_replenish_rx_ring(mac->netdev, limit-count);
 
 	spin_unlock(&mac->rx->lock);
@@ -579,7 +577,6 @@ static int pasemi_mac_clean_tx(struct pa
 {
 	int i;
 	struct pasemi_mac_buffer *info;
-	struct pas_dma_xct_descr *dp;
 	unsigned int start, count, limit;
 	unsigned int total_count;
 	unsigned long flags;
@@ -595,29 +592,28 @@ restart:
 
 	count = 0;
 
-	for (i = start; i < limit; i++) {
-		dp = &TX_DESC(mac, i);
-
-		if ((dp->mactx & XCT_MACTX_E) ||
+	for (i = start; i < limit; i += 2) {
+		u64 mactx = TX_RING(mac, i);
+		if ((mactx  & XCT_MACTX_E) ||
 		    (*mac->tx_status & PAS_STATUS_ERROR))
-			pasemi_mac_tx_error(mac, dp->mactx);
+			pasemi_mac_tx_error(mac, mactx);
 
-		if (unlikely(dp->mactx & XCT_MACTX_O))
+		if (unlikely(mactx & XCT_MACTX_O))
 			/* Not yet transmitted */
 			break;
 
-		info = &TX_DESC_INFO(mac, i);
+		info = &TX_RING_INFO(mac, i+1);
 		skbs[count] = info->skb;
 		dmas[count] = info->dma;
 
-		info->skb = NULL;
 		info->dma = 0;
-		dp->mactx = 0;
-		dp->ptr = 0;
+		TX_RING(mac, i) = 0;
+		TX_RING(mac, i+1) = 0;
+
 
 		count++;
 	}
-	mac->tx->next_to_clean += count;
+	mac->tx->next_to_clean += count * 2;
 	spin_unlock_irqrestore(&mac->tx->lock, flags);
 	netif_wake_queue(mac->netdev);
 
@@ -1001,8 +997,6 @@ static int pasemi_mac_start_tx(struct sk
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	struct pasemi_mac_txring *txring;
-	struct pasemi_mac_buffer *info;
-	struct pas_dma_xct_descr *dp;
 	u64 dflags, mactx, ptr;
 	dma_addr_t map;
 	unsigned long flags;
@@ -1038,13 +1032,13 @@ static int pasemi_mac_start_tx(struct sk
 
 	spin_lock_irqsave(&txring->lock, flags);
 
-	if (RING_AVAIL(txring) <= 1) {
+	if (RING_AVAIL(txring) <= 2) {
 		spin_unlock_irqrestore(&txring->lock, flags);
 		pasemi_mac_clean_tx(mac);
 		pasemi_mac_restart_tx_intr(mac);
 		spin_lock_irqsave(&txring->lock, flags);
 
-		if (RING_AVAIL(txring) <= 1) {
+		if (RING_AVAIL(txring) <= 2) {
 			/* Still no room -- stop the queue and wait for tx
 			 * intr when there's room.
 			 */
@@ -1053,15 +1047,14 @@ static int pasemi_mac_start_tx(struct sk
 		}
 	}
 
-	dp = &TX_DESC(mac, txring->next_to_fill);
-	info = &TX_DESC_INFO(mac, txring->next_to_fill);
+	TX_RING(mac, txring->next_to_fill) = mactx;
+	TX_RING(mac, txring->next_to_fill+1) = ptr;
+
+	TX_RING_INFO(mac, txring->next_to_fill+1).dma = map;
+	TX_RING_INFO(mac, txring->next_to_fill+1).skb = skb;
 
-	dp->mactx = mactx;
-	dp->ptr   = ptr;
-	info->dma = map;
-	info->skb = skb;
+	txring->next_to_fill += 2;
 
-	txring->next_to_fill++;
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
 
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -28,25 +28,25 @@
 
 struct pasemi_mac_txring {
 	spinlock_t	 lock;
-	struct pas_dma_xct_descr	*desc;
+	u64		*ring;
 	dma_addr_t	 dma;
 	unsigned int	 size;
 	unsigned int	 next_to_fill;
 	unsigned int	 next_to_clean;
-	struct pasemi_mac_buffer *desc_info;
+	struct pasemi_mac_buffer *ring_info;
 	char		 irq_name[10];  /* "eth%d tx" */
 };
 
 struct pasemi_mac_rxring {
 	spinlock_t	 lock;
-	struct pas_dma_xct_descr	*desc;	/* RX channel descriptor ring */
+	u64		*ring;	/* RX channel descriptor ring */
 	dma_addr_t	 dma;
 	u64		*buffers;	/* RX interface buffer ring */
 	dma_addr_t	 buf_dma;
 	unsigned int	 size;
 	unsigned int	 next_to_fill;
 	unsigned int	 next_to_clean;
-	struct pasemi_mac_buffer *desc_info;
+	struct pasemi_mac_buffer *ring_info;
 	char		 irq_name[10];  /* "eth%d rx" */
 };
 
@@ -88,7 +88,7 @@ struct pasemi_mac {
 	char	phy_id[BUS_ID_SIZE];
 };
 
-/* Software status descriptor (desc_info) */
+/* Software status descriptor (ring_info) */
 struct pasemi_mac_buffer {
 	struct sk_buff *skb;
 	dma_addr_t	dma;
@@ -101,20 +101,7 @@ struct pasdma_status {
 	u64 tx_sta[20];
 };
 
-/* descriptor structure */
-struct pas_dma_xct_descr {
-	union {
-		u64	mactx;
-		u64	macrx;
-	};
-	union {
-		u64	ptr;
-		u64	rxb;
-	};
-};
-
 /* MAC CFG register offsets */
-
 enum {
 	PAS_MAC_CFG_PCFG = 0x80,
 	PAS_MAC_CFG_TXP = 0x98,

^ permalink raw reply

* [PATCH] [2/11] pasemi_mac: fix bug in receive buffer dma mapping
From: Olof Johansson @ 2007-10-02 21:25 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: fix bug in receive buffer dma mapping

skb->len isn't actually set to the size of the allocated skb, so don't
try to use it when figuring out how much to map.

(This hasn't surfaced as a real bug because we effectively disable
translation for the interface, but it still needs fixing for the future)


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -396,7 +396,7 @@ static void pasemi_mac_replenish_rx_ring
 		if (unlikely(!skb))
 			break;
 
-		dma = pci_map_single(mac->dma_pdev, skb->data, skb->len,
+		dma = pci_map_single(mac->dma_pdev, skb->data, BUF_SIZE,
 				     PCI_DMA_FROMDEVICE);
 
 		if (unlikely(dma_mapping_error(dma))) {

^ permalink raw reply

* [PATCH] [1/11] pasemi_mac: basic error checking
From: Olof Johansson @ 2007-10-02 21:24 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>

pasemi_mac: basic error checking

Add some rudimentary error checking to pasemi_mac.

Signed-off-by: Olof Johansson <olof@lixom.net>

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -445,6 +445,38 @@ static void pasemi_mac_restart_tx_intr(s
 }
 
 
+static inline void pasemi_mac_rx_error(struct pasemi_mac *mac, u64 macrx)
+{
+	unsigned int rcmdsta, ccmdsta;
+
+	if (!netif_msg_rx_err(mac))
+		return;
+
+	rcmdsta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+	ccmdsta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
+
+	printk(KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n",
+		macrx, *mac->rx_status);
+
+	printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n",
+		rcmdsta, ccmdsta);
+}
+
+static inline void pasemi_mac_tx_error(struct pasemi_mac *mac, u64 mactx)
+{
+	unsigned int cmdsta;
+
+	if (!netif_msg_tx_err(mac))
+		return;
+
+	cmdsta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
+
+	printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, "\
+		"tx status 0x%016lx\n", mactx, *mac->tx_status);
+
+	printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta);
+}
+
 static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
 {
 	unsigned int n;
@@ -468,10 +500,13 @@ static int pasemi_mac_clean_rx(struct pa
 		prefetchw(dp);
 		macrx = dp->macrx;
 
+		if ((macrx & XCT_MACRX_E) ||
+		    (*mac->rx_status & PAS_STATUS_ERROR))
+			pasemi_mac_rx_error(mac, macrx);
+
 		if (!(macrx & XCT_MACRX_O))
 			break;
 
-
 		info = NULL;
 
 		/* We have to scan for our skb since there's no way
@@ -563,6 +598,10 @@ restart:
 	for (i = start; i < limit; i++) {
 		dp = &TX_DESC(mac, i);
 
+		if ((dp->mactx & XCT_MACTX_E) ||
+		    (*mac->tx_status & PAS_STATUS_ERROR))
+			pasemi_mac_tx_error(mac, dp->mactx);
+
 		if (unlikely(dp->mactx & XCT_MACTX_O))
 			/* Not yet transmitted */
 			break;
@@ -607,9 +646,6 @@ static irqreturn_t pasemi_mac_rx_intr(in
 	if (!(*mac->rx_status & PAS_STATUS_CAUSE_M))
 		return IRQ_NONE;
 
-	if (*mac->rx_status & PAS_STATUS_ERROR)
-		printk("rx_status reported error\n");
-
 	/* Don't reset packet count so it won't fire again but clear
 	 * all others.
 	 */
@@ -1230,7 +1266,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 		dev_err(&mac->pdev->dev, "register_netdev failed with error %d\n",
 			err);
 		goto out;
-	} else
+	} else if netif_msg_probe(mac)
 		printk(KERN_INFO "%s: PA Semi %s: intf %d, txch %d, rxch %d, "
 		       "hw addr %s\n",
 		       dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",

^ permalink raw reply

* [PATCH] [0/11] pasemi_mac: Patches for 2.6.24
From: Olof Johansson @ 2007-10-02 21:24 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev

Hi,

This series of patches go on top of the previous fixes that were sent
out and picked up.

It's a series of mostly feature-related changes, but also a couple
of bugfixes:

[1/11] pasemi_mac: basic error checking
[2/11] pasemi_mac: fix bug in receive buffer dma mapping
[3/11] pasemi_mac: rework ring management
[4/11] pasemi_mac: implement sg support
[5/11] pasemi_mac: workaround for erratum 5971
[6/11] pasemi_mac: add local skb alignment
[7/11] pasemi_mac: further performance tweaks
[8/11] pasemi_mac: update todo list
[9/11] pasemi_mac: clear out old errors on interface open
[10/11] pasemi_mac: use buffer index pointer in clean_rx()
[11/11] pasemi_mac: enable iommu support


Thanks,

-Olof

^ permalink raw reply

* Re: [RFC] PPC64 Exporting memory information through /proc/iomem
From: Geoff Levand @ 2007-10-02 20:50 UTC (permalink / raw)
  To: Badari Pulavarty; +Cc: linuxppc-dev, anton, KAMEZAWA Hiroyuki, linux-mm
In-Reply-To: <1191357435.6106.31.camel@dyn9047017100.beaverton.ibm.com>

Badari Pulavarty wrote:
> On Tue, 2007-10-02 at 13:11 -0700, Geoff Levand wrote:
>> Hi Badari,
>> 
>> Badari Pulavarty wrote:
>> > Hi Paul & Ben,
>> > 
>> > I am trying to get hotplug memory remove working on ppc64.
>> > In order to verify a given memory region, if its valid or not -
>> > current hotplug-memory patches used /proc/iomem. On IA64 and
>> > x86-64 /proc/iomem shows all memory regions. 
>> > 
>> > I am wondering, if its acceptable to do the same on ppc64 also ?
>> > Otherwise, we need to add arch-specific hooks in hotplug-remove
>> > code to be able to do this.
>> 
>> 
>> It seems the only reasonable place is in /proc/iomem, as the the 
>> generic memory hotplug routines put it in there, and if you have
>> a ppc64 system that uses add_memory() you will have mem info in
>> several places, none of which are complete.  
> 
> Well, this information exists in various places (lmb structures
> in the kernel), /proc/device-tree for various users. I want to
> find out what ppc experts think about making this available through
> /proc/iomem also since generic memory hotplug routines expect 
> it there.


Well, I can't say I am one of those experts you seek, but for PS3 we
already have the hotplug mem in /proc/iomem (I set it up to use
add_memory()), so it seems reasonable to have the bootmem there too.

-Geoff

^ permalink raw reply

* Re: [RFC] PPC64 Exporting memory information through /proc/iomem
From: Badari Pulavarty @ 2007-10-02 20:37 UTC (permalink / raw)
  To: Geoff Levand; +Cc: linuxppc-dev, anton, KAMEZAWA Hiroyuki, linux-mm
In-Reply-To: <4702A5FE.5000308@am.sony.com>

On Tue, 2007-10-02 at 13:11 -0700, Geoff Levand wrote:
> Hi Badari,
> 
> Badari Pulavarty wrote:
> > Hi Paul & Ben,
> > 
> > I am trying to get hotplug memory remove working on ppc64.
> > In order to verify a given memory region, if its valid or not -
> > current hotplug-memory patches used /proc/iomem. On IA64 and
> > x86-64 /proc/iomem shows all memory regions. 
> > 
> > I am wondering, if its acceptable to do the same on ppc64 also ?
> > Otherwise, we need to add arch-specific hooks in hotplug-remove
> > code to be able to do this.
> 
> 
> It seems the only reasonable place is in /proc/iomem, as the the 
> generic memory hotplug routines put it in there, and if you have
> a ppc64 system that uses add_memory() you will have mem info in
> several places, none of which are complete.  

Well, this information exists in various places (lmb structures
in the kernel), /proc/device-tree for various users. I want to
find out what ppc experts think about making this available through
/proc/iomem also since generic memory hotplug routines expect 
it there.

Other option would be to provide arch-specific call out. Each
arch could decide to implement whatever way they want to verify 
the range.

Thanks,
Badari

^ permalink raw reply

* Re: [RFC] PPC64 Exporting memory information through /proc/iomem
From: Geoff Levand @ 2007-10-02 20:11 UTC (permalink / raw)
  To: Badari Pulavarty; +Cc: linuxppc-dev, anton, KAMEZAWA Hiroyuki, linux-mm
In-Reply-To: <1191346196.6106.20.camel@dyn9047017100.beaverton.ibm.com>

Hi Badari,

Badari Pulavarty wrote:
> Hi Paul & Ben,
> 
> I am trying to get hotplug memory remove working on ppc64.
> In order to verify a given memory region, if its valid or not -
> current hotplug-memory patches used /proc/iomem. On IA64 and
> x86-64 /proc/iomem shows all memory regions. 
> 
> I am wondering, if its acceptable to do the same on ppc64 also ?
> Otherwise, we need to add arch-specific hooks in hotplug-remove
> code to be able to do this.


It seems the only reasonable place is in /proc/iomem, as the the 
generic memory hotplug routines put it in there, and if you have
a ppc64 system that uses add_memory() you will have mem info in
several places, none of which are complete.  


> Index: linux-2.6.23-rc8/arch/powerpc/mm/numa.c
> ===================================================================
> --- linux-2.6.23-rc8.orig/arch/powerpc/mm/numa.c	2007-10-02 10:16:42.000000000 -0700
> +++ linux-2.6.23-rc8/arch/powerpc/mm/numa.c	2007-10-02 10:17:05.000000000 -0700
> @@ -587,6 +587,22 @@ static void __init *careful_allocation(i
>  	return (void *)ret;
>  }
>  
> +static void add_regions_iomem()
> +{
> +	int i;
> +	struct resource *res;
> +
> +	for (i = 0; i < lmb.memory.cnt; i++) {
> +		res = alloc_bootmem_low(sizeof(struct resource));
> +
> +		res->name = "System RAM";
> +		res->start = lmb.memory.region[i].base;
> +		res->end = res->start + lmb.memory.region[i].size - 1;
> +		res->flags = IORESOURCE_MEM;
> +		request_resource(&iomem_resource, res);
> +	}
> +}
> +

I think this duplication of the code in register_memory_resource()
is a maintenance concern though.  I wonder if it would be better
to somehow hook your stuff into into the existing memory hotplug
routines.


-Geoff

^ 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