2006-10-10 20:49:50

by linas

[permalink] [raw]
Subject: [PATCH 0/21]: powerpc/cell spidernet bugfixes, etc.


Andrew, please apply/forward upstream.

The following set of 21 patches (!) are all aimed at the the
spidernet ethernet device driver. The spidernet is an etherenet
controller built into the Toshiba southbridge for the PowerPC Cell
processor. (This is the only device in existance that with this
ethernet hardware in it).

These patches re-package/re-order/re-cleanup a previous
set of patches I've previously mailed. Thus, some have
been previously Acked-by lines, most do not. Most of
these patches are tiny, and handle problems that cropped
up during testing. Sorry about there being so many of them.

The first set of 12 patches fix a large variety of mostly
minor bugs.

The important patches are 13 through 17: these overcome a
debilitating performance problem on transmit (6 megabits
per second !!) on transmit of patches 500 bytes or larger.
After applying these, I am able to get the following:

pkt sz speed (100K buffs) speed (4M buffs)
------ ----------------- ----------------
1500 700 Mbits/sec 951 Mbits/sec
1000 658 Mbits/sec 770
800 600 648
500 500 500
300 372 372
60 70 70

Above buf size refers to /proc/sys/net/core/wmem_default

----

I'm not planning on any further patches for a long while.
I tried to do som RX work, but gave up. RX performance could
be improved.

FYI, Christoph Hellwig's node-aware patches seem to make no
difference at all any more.

I tried to base these on linux-2.6.19-rc1-mm1 but hit a
kernel BUG in copy_fdtable at fs/file.c:138!
(reported earlire today by Olof)

--linas


2006-10-10 20:56:08

by linas

[permalink] [raw]
Subject: [PATCH 1/21]: powerpc/cell spidernet ethtool -i version number info.


This patch adds version information as reported by
ethtool -i to the Spidernet driver.

From: James K Lewis <[email protected]>
Signed-off-by: James K Lewis <[email protected]>
Signed-off-by: Linas Vepstas <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 3 +++
drivers/net/spider_net.h | 2 ++
drivers/net/spider_net_ethtool.c | 2 +-
3 files changed, 6 insertions(+), 1 deletion(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-05 11:12:44.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-05 11:14:33.000000000 -0500
@@ -55,6 +55,7 @@ MODULE_AUTHOR("Utz Bacher <utz.bacher@de
"<[email protected]>");
MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION);

static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT;
static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT;
@@ -2252,6 +2253,8 @@ static struct pci_driver spider_net_driv
*/
static int __init spider_net_init(void)
{
+ printk(KERN_INFO "Spidernet version %s.\n", VERSION);
+
if (rx_descriptors < SPIDER_NET_RX_DESCRIPTORS_MIN) {
rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_MIN;
pr_info("adjusting rx descriptors to %i.\n", rx_descriptors);
Index: linux-2.6.18-mm2/drivers/net/spider_net.h
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.h 2006-10-05 11:13:53.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.h 2006-10-05 11:14:33.000000000 -0500
@@ -24,6 +24,8 @@
#ifndef _SPIDER_NET_H
#define _SPIDER_NET_H

+#define VERSION "1.1 A"
+
#include "sungem_phy.h"

extern int spider_net_stop(struct net_device *netdev);
Index: linux-2.6.18-mm2/drivers/net/spider_net_ethtool.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net_ethtool.c 2006-10-05 11:12:44.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net_ethtool.c 2006-10-05 11:14:33.000000000 -0500
@@ -76,7 +76,7 @@ spider_net_ethtool_get_drvinfo(struct ne
/* clear and fill out info */
memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
strncpy(drvinfo->driver, spider_net_driver_name, 32);
- strncpy(drvinfo->version, "0.1", 32);
+ strncpy(drvinfo->version, VERSION, 32);
strcpy(drvinfo->fw_version, "no information");
strncpy(drvinfo->bus_info, pci_name(card->pdev), 32);
}

2006-10-10 20:57:38

by linas

[permalink] [raw]
Subject: [PATCH 2/21]: powerpc/cell spidernet burst alignment patch.


This patch increases the Burst Address alignment from 64 to 1024 in the
Spidernet driver. This improves transmit performance for large packets.

From: James K Lewis <[email protected]>
Signed-off-by: James K Lewis <[email protected]>
Signed-off-by: Linas Vepstas <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.h
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.h 2006-10-10 12:20:07.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.h 2006-10-10 12:20:55.000000000 -0500
@@ -211,7 +211,7 @@ extern char spider_net_driver_name[];
#define SPIDER_NET_DMA_RX_FEND_VALUE 0x00030003
/* to set TX_DMA_EN */
#define SPIDER_NET_TX_DMA_EN 0x80000000
-#define SPIDER_NET_GDTDCEIDIS 0x00000002
+#define SPIDER_NET_GDTDCEIDIS 0x00000302
#define SPIDER_NET_DMA_TX_VALUE SPIDER_NET_TX_DMA_EN | \
SPIDER_NET_GDTDCEIDIS
#define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003

2006-10-10 20:59:08

by linas

[permalink] [raw]
Subject: [PATCH 3/21]: Spidernet module parm permissions


The module param permsissions should bw read-only, not writable.

From: James K Lewis <[email protected]>
Signed-off-by: James K Lewis <[email protected]>
Signed-off-by: Linas Vepstas <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 12:20:06.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 12:21:40.000000000 -0500
@@ -60,8 +60,8 @@ MODULE_VERSION(VERSION);
static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT;
static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT;

-module_param(rx_descriptors, int, 0644);
-module_param(tx_descriptors, int, 0644);
+module_param(rx_descriptors, int, 0444);
+module_param(tx_descriptors, int, 0444);

MODULE_PARM_DESC(rx_descriptors, "number of descriptors used " \
"in rx chains");

2006-10-10 21:00:14

by linas

[permalink] [raw]
Subject: [PATCH 4/21]: powerpc/cell spidernet force-end fix


Bugfix: when cleaning up the transmit queue upon device close,
be sure to walk the entire queue.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 12:21:40.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 12:22:49.000000000 -0500
@@ -699,6 +699,8 @@ spider_net_release_tx_descr(struct spide

/* unmap the skb */
skb = descr->skb;
+ if (!skb)
+ return;
pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
PCI_DMA_TODEVICE);
dev_kfree_skb_any(skb);
@@ -751,7 +753,8 @@ spider_net_release_tx_chain(struct spide

default:
card->netdev_stats.tx_dropped++;
- return 1;
+ if (!brutal)
+ return 1;
}
spider_net_release_tx_descr(card);
}

2006-10-10 21:01:05

by linas

[permalink] [raw]
Subject: [PATCH 5/21]: powerpc/cell spidernet zlen min packet length



Polite device drivers pad short packets to 60 bytes,
so that mean-spirited users don't accidentally DOS
some other OS that can't handle short packets.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 12:22:49.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 12:43:51.000000000 -0500
@@ -648,18 +648,26 @@ spider_net_prepare_tx_descr(struct spide
{
struct spider_net_descr *descr = card->tx_chain.head;
dma_addr_t buf;
+ int length;

- buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+ length = skb->len;
+ if (length < ETH_ZLEN) {
+ if (skb_pad(skb, ETH_ZLEN-length))
+ return 0;
+ length = ETH_ZLEN;
+ }
+
+ buf = pci_map_single(card->pdev, skb->data, length, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(buf)) {
if (netif_msg_tx_err(card) && net_ratelimit())
pr_err("could not iommu-map packet (%p, %i). "
- "Dropping packet\n", skb->data, skb->len);
+ "Dropping packet\n", skb->data, length);
card->spider_stats.tx_iommu_map_error++;
return -ENOMEM;
}

descr->buf_addr = buf;
- descr->buf_size = skb->len;
+ descr->buf_size = length;
descr->next_descr_addr = 0;
descr->skb = skb;
descr->data_status = 0;
@@ -693,6 +701,7 @@ spider_net_release_tx_descr(struct spide
{
struct spider_net_descr *descr = card->tx_chain.tail;
struct sk_buff *skb;
+ unsigned int len;

card->tx_chain.tail = card->tx_chain.tail->next;
descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
@@ -701,7 +710,8 @@ spider_net_release_tx_descr(struct spide
skb = descr->skb;
if (!skb)
return;
- pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
+ len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+ pci_unmap_single(card->pdev, descr->buf_addr, len,
PCI_DMA_TODEVICE);
dev_kfree_skb_any(skb);
}

2006-10-10 21:01:20

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH 0/21]: powerpc/cell spidernet bugfixes, etc.

On Tue, 10 Oct 2006 15:49:47 -0500
[email protected] (Linas Vepstas) wrote:

>
> Andrew, please apply/forward upstream.

s/Andrew/Jeff/;)

> I tried to base these on linux-2.6.19-rc1-mm1 but hit a
> kernel BUG in copy_fdtable at fs/file.c:138!
> (reported earlire today by Olof)

yup,
ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.19-rc1/2.6.19-rc1-mm1/hot-fixes/
holds what should be a fix.

2006-10-10 21:01:56

by linas

[permalink] [raw]
Subject: [PATCH 6/21]: powerpc/cell spidernet add missing netdev watchdog


Set the netdev watchdog timer.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 1 +
1 file changed, 1 insertion(+)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 12:43:51.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 12:49:56.000000000 -0500
@@ -686,6 +686,7 @@ spider_net_prepare_tx_descr(struct spide

descr->prev->next_descr_addr = descr->bus_addr;

+ card->netdev->trans_start = jiffies; /* set netdev watchdog timer */
return 0;
}

2006-10-10 21:02:58

by linas

[permalink] [raw]
Subject: [PATCH 7/21]: Spidernet fix register field definitions


This patch fixes the names of a few fields in the DMA control
register. There is no functional change.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----

drivers/net/spider_net.c | 2 +-
drivers/net/spider_net.h | 16 +++++++++++-----
2 files changed, 12 insertions(+), 6 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 12:49:56.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 12:51:26.000000000 -0500
@@ -1614,7 +1614,7 @@ spider_net_enable_card(struct spider_net
SPIDER_NET_INT2_MASK_VALUE);

spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
- SPIDER_NET_GDTDCEIDIS);
+ SPIDER_NET_GDTBSTA | SPIDER_NET_GDTDCEIDIS);
}

/**
Index: linux-2.6.18-mm2/drivers/net/spider_net.h
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.h 2006-10-10 12:20:55.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.h 2006-10-10 12:51:26.000000000 -0500
@@ -191,7 +191,9 @@ extern char spider_net_driver_name[];
#define SPIDER_NET_MACMODE_VALUE 0x00000001
#define SPIDER_NET_BURSTLMT_VALUE 0x00000200 /* about 16 us */

-/* 1(0) enable r/tx dma
+/* DMAC control register GDMACCNTR
+ *
+ * 1(0) enable r/tx dma
* 0000000 fixed to 0
*
* 000000 fixed to 0
@@ -200,6 +202,7 @@ extern char spider_net_driver_name[];
*
* 000000 fixed to 0
* 00 burst alignment: 128 bytes
+ * 11 burst alignment: 1024 bytes
*
* 00000 fixed to 0
* 0 descr writeback size 32 bytes
@@ -210,10 +213,13 @@ extern char spider_net_driver_name[];
#define SPIDER_NET_DMA_RX_VALUE 0x80000000
#define SPIDER_NET_DMA_RX_FEND_VALUE 0x00030003
/* to set TX_DMA_EN */
-#define SPIDER_NET_TX_DMA_EN 0x80000000
-#define SPIDER_NET_GDTDCEIDIS 0x00000302
-#define SPIDER_NET_DMA_TX_VALUE SPIDER_NET_TX_DMA_EN | \
- SPIDER_NET_GDTDCEIDIS
+#define SPIDER_NET_TX_DMA_EN 0x80000000
+#define SPIDER_NET_GDTBSTA 0x00000300
+#define SPIDER_NET_GDTDCEIDIS 0x00000002
+#define SPIDER_NET_DMA_TX_VALUE SPIDER_NET_TX_DMA_EN | \
+ SPIDER_NET_GDTBSTA | \
+ SPIDER_NET_GDTDCEIDIS
+
#define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003

/* SPIDER_NET_UA_DESCR_VALUE is OR'ed with the unicast address */

2006-10-10 21:04:06

by linas

[permalink] [raw]
Subject: [PATCH 8/21]: Spidernet stop queue when queue is full.


This patch adds a call to netif_stop_queue() when there is
no more room for more packets on the transmit queue.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 33 ++++++++++-----------------------
1 file changed, 10 insertions(+), 23 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 12:51:26.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 12:52:42.000000000 -0500
@@ -823,39 +823,25 @@ spider_net_xmit(struct sk_buff *skb, str
struct spider_net_descr_chain *chain = &card->tx_chain;
struct spider_net_descr *descr = chain->head;
unsigned long flags;
- int result;

spin_lock_irqsave(&chain->lock, flags);

spider_net_release_tx_chain(card, 0);

- if (chain->head->next == chain->tail->prev) {
- card->netdev_stats.tx_dropped++;
- result = NETDEV_TX_LOCKED;
- goto out;
- }
+ if ((chain->head->next == chain->tail->prev) ||
+ (spider_net_get_descr_status(descr) != SPIDER_NET_DESCR_NOT_IN_USE) ||
+ (spider_net_prepare_tx_descr(card, skb) != 0)) {

- if (spider_net_get_descr_status(descr) != SPIDER_NET_DESCR_NOT_IN_USE) {
card->netdev_stats.tx_dropped++;
- result = NETDEV_TX_LOCKED;
- goto out;
+ spin_unlock_irqrestore(&chain->lock, flags);
+ netif_stop_queue(netdev);
+ return NETDEV_TX_BUSY;
}

- if (spider_net_prepare_tx_descr(card, skb) != 0) {
- card->netdev_stats.tx_dropped++;
- result = NETDEV_TX_BUSY;
- goto out;
- }
-
- result = NETDEV_TX_OK;
-
spider_net_kick_tx_dma(card);
card->tx_chain.head = card->tx_chain.head->next;
-
-out:
spin_unlock_irqrestore(&chain->lock, flags);
- netif_wake_queue(netdev);
- return result;
+ return NETDEV_TX_OK;
}

/**
@@ -874,9 +860,10 @@ spider_net_cleanup_tx_ring(struct spider
spin_lock_irqsave(&card->tx_chain.lock, flags);

if ((spider_net_release_tx_chain(card, 0) != 0) &&
- (card->netdev->flags & IFF_UP))
+ (card->netdev->flags & IFF_UP)) {
spider_net_kick_tx_dma(card);
-
+ netif_wake_queue(card->netdev);
+ }
spin_unlock_irqrestore(&card->tx_chain.lock, flags);
}

2006-10-10 21:05:09

by linas

[permalink] [raw]
Subject: [PATCH 9/21]: powerpc/cell spidernet bogus rx interrupt bit


The current receive interrupt mask sets a bogus bit that doesn't even
belong to the definition of this register. Remove it.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.h
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.h 2006-10-10 12:51:26.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.h 2006-10-10 12:54:06.000000000 -0500
@@ -332,9 +332,8 @@ enum spider_net_int2_status {
(1 << SPIDER_NET_GDTDCEINT) | \
(1 << SPIDER_NET_GDTFDCINT) )

-/* we rely on flagged descriptor interrupts*/
-#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) | \
- (1 << SPIDER_NET_GRMFLLINT) )
+/* We rely on flagged descriptor interrupts */
+#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) )

#define SPIDER_NET_ERRINT ( 0xffffffff & \
(~SPIDER_NET_TXINT) & \

2006-10-10 21:06:57

by linas

[permalink] [raw]
Subject: [PATCH 10/21]: powerpc/cell spidernet fix error interrupt print



The print message associated with the descriptor chain end interrupt
prints a bogs value. Fix that.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 12:52:42.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 12:58:08.000000000 -0500
@@ -1356,7 +1356,7 @@ spider_net_handle_error_irq(struct spide
if (netif_msg_intr(card))
pr_err("got descriptor chain end interrupt, "
"restarting DMAC %c.\n",
- 'D'+i-SPIDER_NET_GDDDCEINT);
+ 'D'-(i-SPIDER_NET_GDDDCEINT)/3);
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
show_error = 0;

2006-10-10 21:08:50

by linas

[permalink] [raw]
Subject: [PATCH 11/21]: powerpc/cell spidernet stop error printing patch.


Turn off mis-interpretation of the queue-empty interrupt
status bit as an error.

Signed-off-by: Linas Vepstas <[email protected]>
Signed-off-by: James K Lewis <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 12:58:08.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:01:06.000000000 -0500
@@ -1245,12 +1245,15 @@ spider_net_handle_error_irq(struct spide
case SPIDER_NET_PHYINT:
case SPIDER_NET_GMAC2INT:
case SPIDER_NET_GMAC1INT:
- case SPIDER_NET_GIPSINT:
case SPIDER_NET_GFIFOINT:
case SPIDER_NET_DMACINT:
case SPIDER_NET_GSYSINT:
break; */

+ case SPIDER_NET_GIPSINT:
+ show_error = 0;
+ break;
+
case SPIDER_NET_GPWOPCMPINT:
/* PHY write operation completed */
show_error = 0;
@@ -1309,9 +1312,10 @@ spider_net_handle_error_irq(struct spide
case SPIDER_NET_GDTDCEINT:
/* chain end. If a descriptor should be sent, kick off
* tx dma
- if (card->tx_chain.tail == card->tx_chain.head)
+ if (card->tx_chain.tail != card->tx_chain.head)
spider_net_kick_tx_dma(card);
- show_error = 0; */
+ */
+ show_error = 0;
break;

/* case SPIDER_NET_G1TMCNTINT: not used. print a message */
@@ -1425,8 +1429,9 @@ spider_net_handle_error_irq(struct spide
}

if ((show_error) && (netif_msg_intr(card)))
- pr_err("Got error interrupt, GHIINT0STS = 0x%08x, "
+ pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, "
"GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
+ card->netdev->name,
status_reg, error_reg1, error_reg2);

/* clear interrupt sources */

2006-10-10 21:09:47

by linas

[permalink] [raw]
Subject: [PATCH 12/21]: powerpc/cell spidernet incorrect offset


Bugfix -- the rx chain is in memory after the tx chain --
the offset being used was wrong, resulting in memory corruption
when the size of the rx and tx rings weren't exactly the same.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----

drivers/net/spider_net.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:01:06.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:03:11.000000000 -0500
@@ -1628,8 +1628,10 @@ spider_net_open(struct net_device *netde
if (spider_net_init_chain(card, &card->tx_chain, card->descr,
PCI_DMA_TODEVICE, card->tx_desc))
goto alloc_tx_failed;
+
+ /* rx_chain is after tx_chain, so offset is descr + tx_count */
if (spider_net_init_chain(card, &card->rx_chain,
- card->descr + card->rx_desc,
+ card->descr + card->tx_desc,
PCI_DMA_FROMDEVICE, card->rx_desc))
goto alloc_rx_failed;

2006-10-10 21:11:37

by linas

[permalink] [raw]
Subject: [PATCH 13/21]: powerpc/cell spidernet low watermark patch.


Implement basic low-watermark support for the transmit queue.
Hardware low-watermarks allow a properly configured kernel
to continously stream data to a device and not have to handle
any interrupts at all in doing so. Correct zero-interrupt
operation can be actually observed for this driver, when the
socket buffer is made large enough.

The basic idea of a low-watermark interrupt is as follows.
The device driver queues up a bunch of packets for the hardware
to transmit, and then kicks the hardware to get it started.
As the hardware drains the queue of pending, untransmitted
packets, the device driver will want to know when the queue
is almost empty, so that it can queue some more packets.

If the queue drains down to the low waterark, then an interrupt
will be generated. However, if the kernel/driver continues
to add enough packets to keep the queue partially filled,
no interrupt will actually be generated, and the hardware
can continue streaming packets indefinitely in this mode.

The impelmentation is done by setting the DESCR_TXDESFLG flag
in one of the packets. When the hardware sees this flag, it will
interrupt the device driver. Because this flag is on a fixed
packet, rather than at fixed location in the queue, the
code below needs to move the flag as more packets are
queued up. This implementation attempts to keep the flag
at about 1/4 from "empty".

Signed-off-by: Linas Vepstas <[email protected]>
Signed-off-by: James K Lewis <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 43 +++++++++++++++++++++++++++++++++++++++++++
drivers/net/spider_net.h | 8 ++++----
2 files changed, 47 insertions(+), 4 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:03:11.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:09:27.000000000 -0500
@@ -684,6 +684,7 @@ spider_net_prepare_tx_descr(struct spide
break;
}

+ /* Chain the bus address, so that the DMA engine finds this descr. */
descr->prev->next_descr_addr = descr->bus_addr;

card->netdev->trans_start = jiffies; /* set netdev watchdog timer */
@@ -717,6 +718,41 @@ spider_net_release_tx_descr(struct spide
dev_kfree_skb_any(skb);
}

+static void
+spider_net_set_low_watermark(struct spider_net_card *card)
+{
+ int status;
+ int cnt=0;
+ int i;
+ struct spider_net_descr *descr = card->tx_chain.tail;
+
+ /* Measure the length of the queue. */
+ while (descr != card->tx_chain.head) {
+ status = descr->dmac_cmd_status & SPIDER_NET_DESCR_NOT_IN_USE;
+ if (status == SPIDER_NET_DESCR_NOT_IN_USE)
+ break;
+ descr = descr->next;
+ cnt++;
+ }
+
+ /* If TX queue is short, don't even bother with interrupts */
+ if (cnt < card->tx_desc/4)
+ return;
+
+ /* Set low-watermark 3/4th's of the way into the queue. */
+ descr = card->tx_chain.tail;
+ cnt = (cnt*3)/4;
+ for (i=0;i<cnt; i++)
+ descr = descr->next;
+
+ /* Set the new watermark, clear the old watermark */
+ descr->dmac_cmd_status |= SPIDER_NET_DESCR_TXDESFLG;
+ if (card->low_watermark && card->low_watermark != descr)
+ card->low_watermark->dmac_cmd_status =
+ card->low_watermark->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG;
+ card->low_watermark = descr;
+}
+
/**
* spider_net_release_tx_chain - processes sent tx descriptors
* @card: adapter structure
@@ -838,6 +874,7 @@ spider_net_xmit(struct sk_buff *skb, str
return NETDEV_TX_BUSY;
}

+ spider_net_set_low_watermark(card);
spider_net_kick_tx_dma(card);
card->tx_chain.head = card->tx_chain.head->next;
spin_unlock_irqrestore(&chain->lock, flags);
@@ -1467,6 +1504,10 @@ spider_net_interrupt(int irq, void *ptr,
spider_net_rx_irq_off(card);
netif_rx_schedule(netdev);
}
+ if (status_reg & SPIDER_NET_TXINT ) {
+ spider_net_cleanup_tx_ring(card);
+ netif_wake_queue(netdev);
+ }

if (status_reg & SPIDER_NET_ERRINT )
spider_net_handle_error_irq(card, status_reg);
@@ -1629,6 +1670,8 @@ spider_net_open(struct net_device *netde
PCI_DMA_TODEVICE, card->tx_desc))
goto alloc_tx_failed;

+ card->low_watermark = NULL;
+
/* rx_chain is after tx_chain, so offset is descr + tx_count */
if (spider_net_init_chain(card, &card->rx_chain,
card->descr + card->tx_desc,
Index: linux-2.6.18-mm2/drivers/net/spider_net.h
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.h 2006-10-10 12:54:06.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.h 2006-10-10 13:09:27.000000000 -0500
@@ -49,7 +49,7 @@ extern char spider_net_driver_name[];
#define SPIDER_NET_TX_DESCRIPTORS_MIN 16
#define SPIDER_NET_TX_DESCRIPTORS_MAX 512

-#define SPIDER_NET_TX_TIMER 20
+#define SPIDER_NET_TX_TIMER (HZ/5)

#define SPIDER_NET_RX_CSUM_DEFAULT 1

@@ -328,9 +328,7 @@ enum spider_net_int2_status {
SPIDER_NET_GRISPDNGINT
};

-#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GTTEDINT) | \
- (1 << SPIDER_NET_GDTDCEINT) | \
- (1 << SPIDER_NET_GDTFDCINT) )
+#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GDTFDCINT) )

/* We rely on flagged descriptor interrupts */
#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) )
@@ -356,6 +354,7 @@ enum spider_net_int2_status {
#define SPIDER_NET_DESCR_FORCE_END 0x50000000 /* used in rx and tx */
#define SPIDER_NET_DESCR_CARDOWNED 0xA0000000 /* used in rx and tx */
#define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000
+#define SPIDER_NET_DESCR_TXDESFLG 0x00800000

struct spider_net_descr {
/* as defined by the hardware */
@@ -440,6 +439,7 @@ struct spider_net_card {

struct spider_net_descr_chain tx_chain;
struct spider_net_descr_chain rx_chain;
+ struct spider_net_descr *low_watermark;

struct net_device_stats netdev_stats;

2006-10-10 21:13:11

by linas

[permalink] [raw]
Subject: [PATCH 14/21]: powerpc/cell spidernet NAPI polling info.


This patch moves transmit queue cleanup code out of the
interrupt context, and into the NAPI polling routine.

Signed-off-by: Linas Vepstas <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Cc: James K Lewis <[email protected]>

----

drivers/net/spider_net.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:09:27.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:10:37.000000000 -0500
@@ -715,7 +715,7 @@ spider_net_release_tx_descr(struct spide
len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
pci_unmap_single(card->pdev, descr->buf_addr, len,
PCI_DMA_TODEVICE);
- dev_kfree_skb_any(skb);
+ dev_kfree_skb(skb);
}

static void
@@ -885,9 +885,10 @@ spider_net_xmit(struct sk_buff *skb, str
* spider_net_cleanup_tx_ring - cleans up the TX ring
* @card: card structure
*
- * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
- * interrupts to cleanup our TX ring) and returns sent packets to the stack
- * by freeing them
+ * spider_net_cleanup_tx_ring is called by either the tx_timer
+ * or from the NAPI polling routine.
+ * This routine releases resources associted with transmitted
+ * packets, including updating the queue tail pointer.
*/
static void
spider_net_cleanup_tx_ring(struct spider_net_card *card)
@@ -1092,6 +1093,7 @@ spider_net_poll(struct net_device *netde
int packets_to_do, packets_done = 0;
int no_more_packets = 0;

+ spider_net_cleanup_tx_ring(card);
packets_to_do = min(*budget, netdev->quota);

while (packets_to_do) {
@@ -1504,10 +1506,8 @@ spider_net_interrupt(int irq, void *ptr,
spider_net_rx_irq_off(card);
netif_rx_schedule(netdev);
}
- if (status_reg & SPIDER_NET_TXINT ) {
- spider_net_cleanup_tx_ring(card);
- netif_wake_queue(netdev);
- }
+ if (status_reg & SPIDER_NET_TXINT)
+ netif_rx_schedule(netdev);

if (status_reg & SPIDER_NET_ERRINT )
spider_net_handle_error_irq(card, status_reg);

2006-10-10 21:14:38

by linas

[permalink] [raw]
Subject: [PATCH 15/21]: powerpc/cell spidernet refine locking


The transmit side of the spider ethernet driver currently
places locks around some very large chunks of code. This
results in a fair amount of lock contention is some cases.
This patch makes the locks much more fine-grained, protecting
only the cirtical sections. One lock is used to protect
three locations: the queue head and tail pointers, and the
queue low-watermark location.


Signed-off-by: Linas Vepstas <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: James K Lewis <[email protected]>

----
drivers/net/spider_net.c | 95 +++++++++++++++++++++--------------------------
1 file changed, 43 insertions(+), 52 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:10:37.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:20:08.000000000 -0500
@@ -646,8 +646,9 @@ static int
spider_net_prepare_tx_descr(struct spider_net_card *card,
struct sk_buff *skb)
{
- struct spider_net_descr *descr = card->tx_chain.head;
+ struct spider_net_descr *descr;
dma_addr_t buf;
+ unsigned long flags;
int length;

length = skb->len;
@@ -666,6 +667,10 @@ spider_net_prepare_tx_descr(struct spide
return -ENOMEM;
}

+ spin_lock_irqsave(&card->tx_chain.lock, flags);
+ descr = card->tx_chain.head;
+ card->tx_chain.head = descr->next;
+
descr->buf_addr = buf;
descr->buf_size = length;
descr->next_descr_addr = 0;
@@ -674,6 +679,8 @@ spider_net_prepare_tx_descr(struct spide

descr->dmac_cmd_status =
SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+ spin_unlock_irqrestore(&card->tx_chain.lock, flags);
+
if (skb->protocol == htons(ETH_P_IP))
switch (skb->nh.iph->protocol) {
case IPPROTO_TCP:
@@ -691,42 +698,17 @@ spider_net_prepare_tx_descr(struct spide
return 0;
}

-/**
- * spider_net_release_tx_descr - processes a used tx descriptor
- * @card: card structure
- * @descr: descriptor to release
- *
- * releases a used tx descriptor (unmapping, freeing of skb)
- */
-static inline void
-spider_net_release_tx_descr(struct spider_net_card *card)
-{
- struct spider_net_descr *descr = card->tx_chain.tail;
- struct sk_buff *skb;
- unsigned int len;
-
- card->tx_chain.tail = card->tx_chain.tail->next;
- descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
-
- /* unmap the skb */
- skb = descr->skb;
- if (!skb)
- return;
- len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
- pci_unmap_single(card->pdev, descr->buf_addr, len,
- PCI_DMA_TODEVICE);
- dev_kfree_skb(skb);
-}
-
static void
spider_net_set_low_watermark(struct spider_net_card *card)
{
+ unsigned long flags;
int status;
int cnt=0;
int i;
struct spider_net_descr *descr = card->tx_chain.tail;

- /* Measure the length of the queue. */
+ /* Measure the length of the queue. Measurement does not
+ * need to be precise -- does not need a lock. */
while (descr != card->tx_chain.head) {
status = descr->dmac_cmd_status & SPIDER_NET_DESCR_NOT_IN_USE;
if (status == SPIDER_NET_DESCR_NOT_IN_USE)
@@ -746,11 +728,13 @@ spider_net_set_low_watermark(struct spid
descr = descr->next;

/* Set the new watermark, clear the old watermark */
+ spin_lock_irqsave(&card->tx_chain.lock, flags);
descr->dmac_cmd_status |= SPIDER_NET_DESCR_TXDESFLG;
if (card->low_watermark && card->low_watermark != descr)
card->low_watermark->dmac_cmd_status =
card->low_watermark->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG;
card->low_watermark = descr;
+ spin_unlock_irqrestore(&card->tx_chain.lock, flags);
}

/**
@@ -769,21 +753,31 @@ static int
spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
{
struct spider_net_descr_chain *chain = &card->tx_chain;
+ struct spider_net_descr *descr;
+ struct sk_buff *skb;
+ u32 buf_addr;
+ unsigned long flags;
int status;

spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR);

while (chain->tail != chain->head) {
- status = spider_net_get_descr_status(chain->tail);
+ spin_lock_irqsave(&chain->lock, flags);
+ descr = chain->tail;
+
+ status = spider_net_get_descr_status(descr);
switch (status) {
case SPIDER_NET_DESCR_COMPLETE:
card->netdev_stats.tx_packets++;
- card->netdev_stats.tx_bytes += chain->tail->skb->len;
+ card->netdev_stats.tx_bytes += descr->skb->len;
break;

case SPIDER_NET_DESCR_CARDOWNED:
- if (!brutal)
+ if (!brutal) {
+ spin_unlock_irqrestore(&chain->lock, flags);
return 1;
+ }
+
/* fallthrough, if we release the descriptors
* brutally (then we don't care about
* SPIDER_NET_DESCR_CARDOWNED) */
@@ -800,12 +794,25 @@ spider_net_release_tx_chain(struct spide

default:
card->netdev_stats.tx_dropped++;
- if (!brutal)
+ if (!brutal) {
+ spin_unlock_irqrestore(&chain->lock, flags);
return 1;
+ }
}
- spider_net_release_tx_descr(card);
- }

+ chain->tail = descr->next;
+ descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
+ skb = descr->skb;
+ buf_addr = descr->buf_addr;
+ spin_unlock_irqrestore(&chain->lock, flags);
+
+ /* unmap the skb */
+ if (skb) {
+ int len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+ pci_unmap_single(card->pdev, buf_addr, len, PCI_DMA_TODEVICE);
+ dev_kfree_skb(skb);
+ }
+ }
return 0;
}

@@ -857,27 +864,19 @@ spider_net_xmit(struct sk_buff *skb, str
{
struct spider_net_card *card = netdev_priv(netdev);
struct spider_net_descr_chain *chain = &card->tx_chain;
- struct spider_net_descr *descr = chain->head;
- unsigned long flags;
-
- spin_lock_irqsave(&chain->lock, flags);

spider_net_release_tx_chain(card, 0);

if ((chain->head->next == chain->tail->prev) ||
- (spider_net_get_descr_status(descr) != SPIDER_NET_DESCR_NOT_IN_USE) ||
(spider_net_prepare_tx_descr(card, skb) != 0)) {

card->netdev_stats.tx_dropped++;
- spin_unlock_irqrestore(&chain->lock, flags);
netif_stop_queue(netdev);
return NETDEV_TX_BUSY;
}

spider_net_set_low_watermark(card);
spider_net_kick_tx_dma(card);
- card->tx_chain.head = card->tx_chain.head->next;
- spin_unlock_irqrestore(&chain->lock, flags);
return NETDEV_TX_OK;
}

@@ -893,16 +892,11 @@ spider_net_xmit(struct sk_buff *skb, str
static void
spider_net_cleanup_tx_ring(struct spider_net_card *card)
{
- unsigned long flags;
-
- spin_lock_irqsave(&card->tx_chain.lock, flags);
-
if ((spider_net_release_tx_chain(card, 0) != 0) &&
(card->netdev->flags & IFF_UP)) {
spider_net_kick_tx_dma(card);
netif_wake_queue(card->netdev);
}
- spin_unlock_irqrestore(&card->tx_chain.lock, flags);
}

/**
@@ -1930,10 +1924,7 @@ spider_net_stop(struct net_device *netde
spider_net_disable_rxdmac(card);

/* release chains */
- if (spin_trylock(&card->tx_chain.lock)) {
- spider_net_release_tx_chain(card, 1);
- spin_unlock(&card->tx_chain.lock);
- }
+ spider_net_release_tx_chain(card, 1);

spider_net_free_chain(card, &card->tx_chain);
spider_net_free_chain(card, &card->rx_chain);

2006-10-10 21:15:33

by linas

[permalink] [raw]
Subject: [PATCH 16/21]: powerpc/cell spidernet


Remove a dummy register read that is not needed.
This reduces CPU usage notably during transmit.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: James K Lewis <[email protected]>

----
drivers/net/spider_net.c | 2 --
1 file changed, 2 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:20:08.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:21:41.000000000 -0500
@@ -759,8 +759,6 @@ spider_net_release_tx_chain(struct spide
unsigned long flags;
int status;

- spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR);
-
while (chain->tail != chain->head) {
spin_lock_irqsave(&chain->lock, flags);
descr = chain->tail;

2006-10-10 21:18:22

by linas

[permalink] [raw]
Subject: [PATCH 17/21]: powerpc/cell spidernet reduce DMA kicking


The current code attempts to start the TX dma every time a packet
is queued. This is too conservative, and wastes CPU time. This
patch changes behaviour to call the kick-dma function less often,
only when the tx queue is at risk of emptying.

This reduces cpu usage, improves performance.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:21:41.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:28:43.000000000 -0500
@@ -698,7 +698,7 @@ spider_net_prepare_tx_descr(struct spide
return 0;
}

-static void
+static int
spider_net_set_low_watermark(struct spider_net_card *card)
{
unsigned long flags;
@@ -719,7 +719,7 @@ spider_net_set_low_watermark(struct spid

/* If TX queue is short, don't even bother with interrupts */
if (cnt < card->tx_desc/4)
- return;
+ return cnt;

/* Set low-watermark 3/4th's of the way into the queue. */
descr = card->tx_chain.tail;
@@ -735,6 +735,7 @@ spider_net_set_low_watermark(struct spid
card->low_watermark->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG;
card->low_watermark = descr;
spin_unlock_irqrestore(&card->tx_chain.lock, flags);
+ return cnt;
}

/**
@@ -819,8 +820,12 @@ spider_net_release_tx_chain(struct spide
* @card: card structure
* @descr: descriptor address to enable TX processing at
*
- * spider_net_kick_tx_dma writes the current tx chain head as start address
- * of the tx descriptor chain and enables the transmission DMA engine
+ * This routine will start the transmit DMA running if
+ * it is not already running. This routine ned only be
+ * called when queueing a new packet to an empty tx queue.
+ * Writes the current tx chain head as start address
+ * of the tx descriptor chain and enables the transmission
+ * DMA engine.
*/
static inline void
spider_net_kick_tx_dma(struct spider_net_card *card)
@@ -860,6 +865,7 @@ out:
static int
spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
{
+ int cnt;
struct spider_net_card *card = netdev_priv(netdev);
struct spider_net_descr_chain *chain = &card->tx_chain;

@@ -873,8 +879,9 @@ spider_net_xmit(struct sk_buff *skb, str
return NETDEV_TX_BUSY;
}

- spider_net_set_low_watermark(card);
- spider_net_kick_tx_dma(card);
+ cnt = spider_net_set_low_watermark(card);
+ if (cnt < 5)
+ spider_net_kick_tx_dma(card);
return NETDEV_TX_OK;
}

2006-10-10 21:19:38

by linas

[permalink] [raw]
Subject: [PATCH 18/21]: powerpc/cell spidernet variable name change


Cosmetic patch: give the variable holding the numer of descriptors
a more descriptive name, so to avoid confusion.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----

drivers/net/spider_net.c | 12 ++++++------
drivers/net/spider_net.h | 4 ++--
drivers/net/spider_net_ethtool.c | 4 ++--
3 files changed, 10 insertions(+), 10 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:28:43.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:35:33.000000000 -0500
@@ -718,7 +718,7 @@ spider_net_set_low_watermark(struct spid
}

/* If TX queue is short, don't even bother with interrupts */
- if (cnt < card->tx_desc/4)
+ if (cnt < card->num_tx_desc/4)
return cnt;

/* Set low-watermark 3/4th's of the way into the queue. */
@@ -1666,15 +1666,15 @@ spider_net_open(struct net_device *netde

result = -ENOMEM;
if (spider_net_init_chain(card, &card->tx_chain, card->descr,
- PCI_DMA_TODEVICE, card->tx_desc))
+ PCI_DMA_TODEVICE, card->num_tx_desc))
goto alloc_tx_failed;

card->low_watermark = NULL;

/* rx_chain is after tx_chain, so offset is descr + tx_count */
if (spider_net_init_chain(card, &card->rx_chain,
- card->descr + card->tx_desc,
- PCI_DMA_FROMDEVICE, card->rx_desc))
+ card->descr + card->num_tx_desc,
+ PCI_DMA_FROMDEVICE, card->num_rx_desc))
goto alloc_rx_failed;

/* allocate rx skbs */
@@ -2060,8 +2060,8 @@ spider_net_setup_netdev(struct spider_ne

card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;

- card->tx_desc = tx_descriptors;
- card->rx_desc = rx_descriptors;
+ card->num_tx_desc = tx_descriptors;
+ card->num_rx_desc = rx_descriptors;

spider_net_setup_netdev_ops(netdev);

Index: linux-2.6.18-mm2/drivers/net/spider_net.h
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.h 2006-10-10 13:09:27.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.h 2006-10-10 13:35:33.000000000 -0500
@@ -455,8 +455,8 @@ struct spider_net_card {

/* for ethtool */
int msg_enable;
- int rx_desc;
- int tx_desc;
+ int num_rx_desc;
+ int num_tx_desc;
struct spider_net_extra_stats spider_stats;

struct spider_net_descr descr[0];
Index: linux-2.6.18-mm2/drivers/net/spider_net_ethtool.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net_ethtool.c 2006-10-10 12:20:05.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net_ethtool.c 2006-10-10 13:35:33.000000000 -0500
@@ -158,9 +158,9 @@ spider_net_ethtool_get_ringparam(struct
struct spider_net_card *card = netdev->priv;

ering->tx_max_pending = SPIDER_NET_TX_DESCRIPTORS_MAX;
- ering->tx_pending = card->tx_desc;
+ ering->tx_pending = card->num_tx_desc;
ering->rx_max_pending = SPIDER_NET_RX_DESCRIPTORS_MAX;
- ering->rx_pending = card->rx_desc;
+ ering->rx_pending = card->num_rx_desc;
}

static int spider_net_get_stats_count(struct net_device *netdev)

2006-10-10 21:21:15

by linas

[permalink] [raw]
Subject: [PATCH 19/21]: powerpc/cell spidernet DMA direction fix


The ring buffer descriptors are DMA-accessed bidirectionally,
but are not declared in this way. Fix this.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:35:33.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:37:40.000000000 -0500
@@ -301,7 +301,7 @@ static int
spider_net_init_chain(struct spider_net_card *card,
struct spider_net_descr_chain *chain,
struct spider_net_descr *start_descr,
- int direction, int no)
+ int no)
{
int i;
struct spider_net_descr *descr;
@@ -316,7 +316,7 @@ spider_net_init_chain(struct spider_net_

buf = pci_map_single(card->pdev, descr,
SPIDER_NET_DESCR_SIZE,
- direction);
+ PCI_DMA_BIDIRECTIONAL);

if (pci_dma_mapping_error(buf))
goto iommu_error;
@@ -330,11 +330,6 @@ spider_net_init_chain(struct spider_net_
(descr-1)->next = start_descr;
start_descr->prev = descr-1;

- descr = start_descr;
- if (direction == PCI_DMA_FROMDEVICE)
- for (i=0; i < no; i++, descr++)
- descr->next_descr_addr = descr->next->bus_addr;
-
spin_lock_init(&chain->lock);
chain->head = start_descr;
chain->tail = start_descr;
@@ -347,7 +342,7 @@ iommu_error:
if (descr->bus_addr)
pci_unmap_single(card->pdev, descr->bus_addr,
SPIDER_NET_DESCR_SIZE,
- direction);
+ PCI_DMA_BIDIRECTIONAL);
return -ENOMEM;
}

@@ -368,7 +363,7 @@ spider_net_free_rx_chain_contents(struct
dev_kfree_skb(descr->skb);
pci_unmap_single(card->pdev, descr->buf_addr,
SPIDER_NET_MAX_FRAME,
- PCI_DMA_FROMDEVICE);
+ PCI_DMA_BIDIRECTIONAL);
}
descr = descr->next;
}
@@ -1662,21 +1657,26 @@ int
spider_net_open(struct net_device *netdev)
{
struct spider_net_card *card = netdev_priv(netdev);
- int result;
+ struct spider_net_descr *descr;
+ int i, result;

result = -ENOMEM;
if (spider_net_init_chain(card, &card->tx_chain, card->descr,
- PCI_DMA_TODEVICE, card->num_tx_desc))
+ card->num_tx_desc))
goto alloc_tx_failed;

card->low_watermark = NULL;

/* rx_chain is after tx_chain, so offset is descr + tx_count */
if (spider_net_init_chain(card, &card->rx_chain,
- card->descr + card->num_tx_desc,
- PCI_DMA_FROMDEVICE, card->num_rx_desc))
+ card->descr + card->num_tx_desc,
+ card->num_rx_desc))
goto alloc_rx_failed;

+ descr = card->rx_chain.head;
+ for (i=0; i < card->num_rx_desc; i++, descr++)
+ descr->next_descr_addr = descr->next->bus_addr;
+
/* allocate rx skbs */
if (spider_net_alloc_rx_skbs(card))
goto alloc_skbs_failed;

2006-10-10 21:22:36

by linas

[permalink] [raw]
Subject: [PATCH 20/21]: powerpc/cell spidernet release all descrs


Bugfix: rx descriptor release function fails to visit
the last entry while walking receive descriptor ring.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:37:40.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:40:56.000000000 -0500
@@ -358,7 +358,7 @@ spider_net_free_rx_chain_contents(struct
struct spider_net_descr *descr;

descr = card->rx_chain.head;
- while (descr->next != card->rx_chain.head) {
+ do {
if (descr->skb) {
dev_kfree_skb(descr->skb);
pci_unmap_single(card->pdev, descr->buf_addr,
@@ -366,7 +366,7 @@ spider_net_free_rx_chain_contents(struct
PCI_DMA_BIDIRECTIONAL);
}
descr = descr->next;
- }
+ } while (descr != card->rx_chain.head);
}

/**

2006-10-10 21:23:29

by linas

[permalink] [raw]
Subject: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing


The current driver code performs 512 DMA mappns of a bunch of
32-byte structures. This is silly, as they are all in contiguous
memory. Ths patch changes the code to DMA map the entie area
with just one call.

Signed-off-by: Linas Vepstas <[email protected]>
Cc: James K Lewis <[email protected]>
Cc: Arnd Bergmann <[email protected]>

----
drivers/net/spider_net.c | 107 +++++++++++++++++++++++------------------------
drivers/net/spider_net.h | 16 ++-----
2 files changed, 59 insertions(+), 64 deletions(-)

Index: linux-2.6.18-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.c 2006-10-10 13:40:56.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.c 2006-10-10 13:42:12.000000000 -0500
@@ -267,25 +267,6 @@ spider_net_get_descr_status(struct spide
}

/**
- * spider_net_free_chain - free descriptor chain
- * @card: card structure
- * @chain: address of chain
- *
- */
-static void
-spider_net_free_chain(struct spider_net_card *card,
- struct spider_net_descr_chain *chain)
-{
- struct spider_net_descr *descr;
-
- for (descr = chain->tail; !descr->bus_addr; descr = descr->next) {
- pci_unmap_single(card->pdev, descr->bus_addr,
- SPIDER_NET_DESCR_SIZE, PCI_DMA_BIDIRECTIONAL);
- descr->bus_addr = 0;
- }
-}
-
-/**
* spider_net_init_chain - links descriptor chain
* @card: card structure
* @chain: address of chain
@@ -297,15 +278,15 @@ spider_net_free_chain(struct spider_net_
*
* returns 0 on success, <0 on failure
*/
-static int
+static void
spider_net_init_chain(struct spider_net_card *card,
struct spider_net_descr_chain *chain,
struct spider_net_descr *start_descr,
+ dma_addr_t buf,
int no)
{
int i;
struct spider_net_descr *descr;
- dma_addr_t buf;

descr = start_descr;
memset(descr, 0, sizeof(*descr) * no);
@@ -314,17 +295,12 @@ spider_net_init_chain(struct spider_net_
for (i=0; i<no; i++, descr++) {
descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;

- buf = pci_map_single(card->pdev, descr,
- SPIDER_NET_DESCR_SIZE,
- PCI_DMA_BIDIRECTIONAL);
-
- if (pci_dma_mapping_error(buf))
- goto iommu_error;
-
descr->bus_addr = buf;
+ descr->next_descr_addr = 0;
descr->next = descr + 1;
descr->prev = descr - 1;

+ buf += sizeof(struct spider_net_descr);
}
/* do actual circular list */
(descr-1)->next = start_descr;
@@ -333,17 +309,6 @@ spider_net_init_chain(struct spider_net_
spin_lock_init(&chain->lock);
chain->head = start_descr;
chain->tail = start_descr;
-
- return 0;
-
-iommu_error:
- descr = start_descr;
- for (i=0; i < no; i++, descr++)
- if (descr->bus_addr)
- pci_unmap_single(card->pdev, descr->bus_addr,
- SPIDER_NET_DESCR_SIZE,
- PCI_DMA_BIDIRECTIONAL);
- return -ENOMEM;
}

/**
@@ -1658,24 +1623,32 @@ spider_net_open(struct net_device *netde
{
struct spider_net_card *card = netdev_priv(netdev);
struct spider_net_descr *descr;
- int i, result;
+ int result = -ENOMEM;

- result = -ENOMEM;
- if (spider_net_init_chain(card, &card->tx_chain, card->descr,
- card->num_tx_desc))
- goto alloc_tx_failed;
+ card->descr_dma_addr = pci_map_single(card->pdev, card->descr,
+ (card->num_tx_desc+card->num_rx_desc)*sizeof(struct spider_net_descr),
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(card->descr_dma_addr))
+ return -ENOMEM;
+
+ spider_net_init_chain(card, &card->tx_chain, card->descr,
+ card->descr_dma_addr,
+ card->num_tx_desc);

card->low_watermark = NULL;

/* rx_chain is after tx_chain, so offset is descr + tx_count */
- if (spider_net_init_chain(card, &card->rx_chain,
+ spider_net_init_chain(card, &card->rx_chain,
card->descr + card->num_tx_desc,
- card->num_rx_desc))
- goto alloc_rx_failed;
+ card->descr_dma_addr
+ + card->num_tx_desc * sizeof(struct spider_net_descr),
+ card->num_rx_desc);

descr = card->rx_chain.head;
- for (i=0; i < card->num_rx_desc; i++, descr++)
+ do {
descr->next_descr_addr = descr->next->bus_addr;
+ descr = descr->next;
+ } while (descr != card->rx_chain.head);

/* allocate rx skbs */
if (spider_net_alloc_rx_skbs(card))
@@ -1701,10 +1674,21 @@ spider_net_open(struct net_device *netde
register_int_failed:
spider_net_free_rx_chain_contents(card);
alloc_skbs_failed:
- spider_net_free_chain(card, &card->rx_chain);
-alloc_rx_failed:
- spider_net_free_chain(card, &card->tx_chain);
-alloc_tx_failed:
+ descr = card->rx_chain.head;
+ do {
+ descr->bus_addr = 0;
+ descr = descr->next;
+ } while (descr != card->rx_chain.head);
+
+ descr = card->tx_chain.head;
+ do {
+ descr->bus_addr = 0;
+ descr = descr->next;
+ } while (descr != card->tx_chain.head);
+
+ pci_unmap_single(card->pdev, card->descr_dma_addr,
+ (card->num_tx_desc+card->num_rx_desc)*sizeof(struct spider_net_descr),
+ PCI_DMA_BIDIRECTIONAL);
return result;
}

@@ -1907,6 +1891,7 @@ int
spider_net_stop(struct net_device *netdev)
{
struct spider_net_card *card = netdev_priv(netdev);
+ struct spider_net_descr *descr;

tasklet_kill(&card->rxram_full_tl);
netif_poll_disable(netdev);
@@ -1930,9 +1915,23 @@ spider_net_stop(struct net_device *netde

/* release chains */
spider_net_release_tx_chain(card, 1);
+ spider_net_free_rx_chain_contents(card);
+
+ descr = card->rx_chain.head;
+ do {
+ descr->bus_addr = 0;
+ descr = descr->next;
+ } while (descr != card->rx_chain.head);
+
+ descr = card->tx_chain.head;
+ do {
+ descr->bus_addr = 0;
+ descr = descr->next;
+ } while (descr != card->tx_chain.head);

- spider_net_free_chain(card, &card->tx_chain);
- spider_net_free_chain(card, &card->rx_chain);
+ pci_unmap_single(card->pdev, card->descr_dma_addr,
+ (card->num_tx_desc+card->num_rx_desc)*sizeof(struct spider_net_descr),
+ PCI_DMA_BIDIRECTIONAL);

return 0;
}
Index: linux-2.6.18-mm2/drivers/net/spider_net.h
===================================================================
--- linux-2.6.18-mm2.orig/drivers/net/spider_net.h 2006-10-10 13:35:33.000000000 -0500
+++ linux-2.6.18-mm2/drivers/net/spider_net.h 2006-10-10 13:42:12.000000000 -0500
@@ -397,8 +397,6 @@ struct spider_net_descr_chain {
* 701b8000 would be correct, but every packets gets that flag */
#define SPIDER_NET_DESTROY_RX_FLAGS 0x700b8000

-#define SPIDER_NET_DESCR_SIZE 32
-
/* this will be bigger some time */
struct spider_net_options {
int rx_csum; /* for rx: if 0 ip_summed=NONE,
@@ -437,28 +435,26 @@ struct spider_net_card {

void __iomem *regs;

+ int num_rx_desc;
+ int num_tx_desc;
struct spider_net_descr_chain tx_chain;
struct spider_net_descr_chain rx_chain;
struct spider_net_descr *low_watermark;
+ dma_addr_t descr_dma_addr;

- struct net_device_stats netdev_stats;
-
- struct spider_net_options options;
-
- spinlock_t intmask_lock;
struct tasklet_struct rxram_full_tl;
struct timer_list tx_timer;
-
struct work_struct tx_timeout_task;
atomic_t tx_timeout_task_counter;
wait_queue_head_t waitq;

/* for ethtool */
int msg_enable;
- int num_rx_desc;
- int num_tx_desc;
+ struct net_device_stats netdev_stats;
struct spider_net_extra_stats spider_stats;
+ struct spider_net_options options;

+ /* Must be last element in the structure */
struct spider_net_descr descr[0];
};

2006-10-10 23:20:17

by Joel Schopp

[permalink] [raw]
Subject: Re: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing

Linas Vepstas wrote:
> The current driver code performs 512 DMA mappns of a bunch of
> 32-byte structures. This is silly, as they are all in contiguous
> memory. Ths patch changes the code to DMA map the entie area
> with just one call.
>
> Signed-off-by: Linas Vepstas <[email protected]>
> Cc: James K Lewis <[email protected]>
> Cc: Arnd Bergmann <[email protected]>

The others look good, but this one complicates the code and doesn't have any benefit. 20
for 21 isn't bad.

2006-10-11 01:46:21

by Geoff Levand

[permalink] [raw]
Subject: Re: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing

jschopp wrote:
> Linas Vepstas wrote:
>> The current driver code performs 512 DMA mappns of a bunch of
>> 32-byte structures. This is silly, as they are all in contiguous
>> memory. Ths patch changes the code to DMA map the entie area
>> with just one call.
>>
>> Signed-off-by: Linas Vepstas <[email protected]>
>> Cc: James K Lewis <[email protected]>
>> Cc: Arnd Bergmann <[email protected]>
>
> The others look good, but this one complicates the code and doesn't have any benefit. 20
> for 21 isn't bad.

Linas,

Is the motivation for this change to improve performance by reducing the overhead
of the mapping calls? If so, there may be some benefit for some systems. Could
you please elaborate?

-Geoff

2006-10-11 07:16:10

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing

On Tue, 2006-10-10 at 18:20 -0500, jschopp wrote:
> Linas Vepstas wrote:
> > The current driver code performs 512 DMA mappns of a bunch of
> > 32-byte structures. This is silly, as they are all in contiguous
> > memory. Ths patch changes the code to DMA map the entie area
> > with just one call.
> >
> > Signed-off-by: Linas Vepstas <[email protected]>
> > Cc: James K Lewis <[email protected]>
> > Cc: Arnd Bergmann <[email protected]>
>
> The others look good, but this one complicates the code and doesn't have any benefit. 20
> for 21 isn't bad.

Hi Joel !

I'm not sure what you mean here.... (especially your 20 to 21 comment).

The patch looks perfectly fine to me, and in fact removes more lines of
code than it adds :)

Cheers,
Ben.


2006-10-11 09:25:32

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing

On Wednesday 11 October 2006 03:46, Geoff Levand wrote:
> >
> > The others look good, but this one complicates the code and doesn't have any benefit.  20
> > for 21 isn't bad.
>
> Is the motivation for this change to improve performance by reducing the overhead
> of the mapping calls?  If so, there may be some benefit for some systems.  Could
> you please elaborate?
>

>From what I understand, this patch drastically reduces the number of
I/O PTEs that are needed in the iommu. With the current static IOMMU
mapping, it should only make a difference during initialization, but
any platform that uses a dynamic mapping of iommu entries will benefit
a lot from it, because:

- the card can do better prefetching of consecutive memory
- there are more I/O ptes available for other drivers.

Arnd <><

2006-10-11 15:20:22

by linas

[permalink] [raw]
Subject: Re: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing

On Tue, Oct 10, 2006 at 06:46:08PM -0700, Geoff Levand wrote:
> > Linas Vepstas wrote:
> >> The current driver code performs 512 DMA mappns of a bunch of
> >> 32-byte structures. This is silly, as they are all in contiguous
> >> memory. Ths patch changes the code to DMA map the entie area
> >> with just one call.
>
> Linas,
>
> Is the motivation for this change to improve performance by reducing the overhead
> of the mapping calls?

Yes.

> If so, there may be some benefit for some systems. Could
> you please elaborate?

I started writingthe patch thinking it will have some huge effect on
performance, based on a false assumption on how i/o was done on this
machine

*If* this were another pSeries system, then each call to
pci_map_single() chews up an actual hardware "translation
control entry" (TCE) that maps pci bus addresses into
system RAM addresses. These are somewhat limited resources,
and so one shouldn't squander them. Furthermore, I thouhght
TCE's have TLB's associated with them (similar to how virtual
memory page tables are backed by hardware page TLB's), of which
there are even less of. I was thinking that TLB thrashing would
have a big hit on performance.

Turns out that there was no difference to performance at all,
and a quick look at "cell_map_single()" in arch/powerpc/platforms/cell
made it clear why: there's no fancy i/o address mapping.

Thus, the patch has only mrginal benefit; I submit it only in the
name of "its the right thing to do anyway".

--linas

2006-10-11 15:51:45

by Geoff Levand

[permalink] [raw]
Subject: Re: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing

Linas Vepstas wrote:
> On Tue, Oct 10, 2006 at 06:46:08PM -0700, Geoff Levand wrote:
>> > Linas Vepstas wrote:
>> >> The current driver code performs 512 DMA mappns of a bunch of
>> >> 32-byte structures. This is silly, as they are all in contiguous
>> >> memory. Ths patch changes the code to DMA map the entie area
>> >> with just one call.
>>
>> Linas,
>>
>> Is the motivation for this change to improve performance by reducing the overhead
>> of the mapping calls?
>
> Yes.
>
>> If so, there may be some benefit for some systems. Could
>> you please elaborate?
>
> I started writingthe patch thinking it will have some huge effect on
> performance, based on a false assumption on how i/o was done on this
> machine
>
> *If* this were another pSeries system, then each call to
> pci_map_single() chews up an actual hardware "translation
> control entry" (TCE) that maps pci bus addresses into
> system RAM addresses. These are somewhat limited resources,
> and so one shouldn't squander them. Furthermore, I thouhght
> TCE's have TLB's associated with them (similar to how virtual
> memory page tables are backed by hardware page TLB's), of which
> there are even less of. I was thinking that TLB thrashing would
> have a big hit on performance.
>
> Turns out that there was no difference to performance at all,
> and a quick look at "cell_map_single()" in arch/powerpc/platforms/cell
> made it clear why: there's no fancy i/o address mapping.

OK, thanks for the explanation. Actually, the current cell DMA mapping
implementation uses a simple 'linear' mapping, in that, all of RAM is
mapped into the bus DMA address space at once, and in fact, it is all
just done at system startup.

There is ongoing work to implement 'dynamic' mapping, where DMA pages are
mapped into the bus DMA address space on demand. I think a key point to
understand the benefit to this is that the cell processor's I/O controller
maps pages per device, so you can map one DMA page to one device. I
currently have this working for my platform, but have not released that
work. There is some overhead to managing the mapped buffers and to request
pages be mapped by the hypervisor, etc., so I was thinking that is this work
of yours to consolidate the memory buffers prior to requesting the mapping
could be of benefit if it was in an often executed code path.

-Geoff

2006-10-11 16:03:21

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 0/21]: powerpc/cell spidernet bugfixes, etc.

On Tuesday 10 October 2006 22:49, Linas Vepstas wrote:
> Andrew, please apply/forward upstream.
>
> The following set of 21 patches (!) are all aimed at the the
> spidernet ethernet device driver. The spidernet is an etherenet
> controller built into the Toshiba southbridge for the PowerPC Cell
> processor. (This is the only device in existance that with this
> ethernet hardware in it).
>
> These patches re-package/re-order/re-cleanup a previous
> set of patches I've previously mailed. Thus, some have
> been previously Acked-by lines, most do not. Most of
> these patches are tiny, and handle problems that cropped
> up during testing. Sorry about there being so many of them.
>
> The first set of 12 patches fix a large variety of mostly
> minor bugs.
>
> The important patches are 13 through 17: these overcome a
> debilitating performance problem on transmit (6 megabits
> per second !!) on transmit of patches 500 bytes or larger.
> After applying these, I am able to get the following:
>
> pkt sz ? speed (100K buffs) ? ? ? speed (4M buffs)
> ------ ? ----------------- ? ? ? ?----------------
> 1500 ? ? 700 Mbits/sec ? ? ? ? ? ?951 Mbits/sec
> 1000 ? ? 658 Mbits/sec ? ? ? ? ? ?770
> 800 ? ? ?600 ? ? ? ? ? ? ? ? ? ? ?648
> 500 ? ? ?500 ? ? ? ? ? ? ? ? ? ? ?500
> 300 ? ? ?372 ? ? ? ? ? ? ? ? ? ? ?372
> 60 ? ? ? ?70 ? ? ? ? ? ? ? ? ? ? ? 70
>
> Above buf size refers to /proc/sys/net/core/wmem_default

Excellent work! I guess this the best tx performance we've
seen so far on this hardware.

Consider this as an Acked-by: for all the patches, I'll save
the effort of replying to each one of them separately.

Jeff, do you plan on merging these fixes for 2.6.19?

Arnd <><

2006-10-11 22:16:55

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing


> I started writingthe patch thinking it will have some huge effect on
> performance, based on a false assumption on how i/o was done on this
> machine
>
> *If* this were another pSeries system, then each call to
> pci_map_single() chews up an actual hardware "translation
> control entry" (TCE) that maps pci bus addresses into
> system RAM addresses. These are somewhat limited resources,
> and so one shouldn't squander them. Furthermore, I thouhght
> TCE's have TLB's associated with them (similar to how virtual
> memory page tables are backed by hardware page TLB's), of which
> there are even less of. I was thinking that TLB thrashing would
> have a big hit on performance.
>
> Turns out that there was no difference to performance at all,
> and a quick look at "cell_map_single()" in arch/powerpc/platforms/cell
> made it clear why: there's no fancy i/o address mapping.
>
> Thus, the patch has only mrginal benefit; I submit it only in the
> name of "its the right thing to do anyway".

Well, there is no fancy iommu mapping ... yet.

It's been implemented and is coming after we put together some
workarounds for various other spider hardware issues that trigger when
using it (bogus prefetches and bogus pci ordering).

I think the hypervisor based platforms will be happy with that patch
too.

Ben.


2006-10-14 02:12:26

by Joel Schopp

[permalink] [raw]
Subject: Re: [PATCH 21/21]: powerpc/cell spidernet DMA coalescing

Linas Vepstas wrote:
> The current driver code performs 512 DMA mappns of a bunch of
> 32-byte structures. This is silly, as they are all in contiguous
> memory. Ths patch changes the code to DMA map the entie area
> with just one call.
>
> Signed-off-by: Linas Vepstas <[email protected]>
> Cc: James K Lewis <[email protected]>
> Cc: Arnd Bergmann <[email protected]>

While this patch wasn't useful in the current cell implementation of pci_map_single
it sounds like people are going to be making changes to that sometime. In light of
that new information (new to me anyway) this should probably go in after all. Sorry
for causing trouble.

Acked-by: Joel Schopp <[email protected]>