* [PATCH] [0/11] pasemi_mac: Patches for 2.6.24
@ 2007-10-02 21:24 Olof Johansson
2007-10-02 21:24 ` [PATCH] [1/11] pasemi_mac: basic error checking Olof Johansson
` (10 more replies)
0 siblings, 11 replies; 19+ messages in thread
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 [flat|nested] 19+ messages in thread
* [PATCH] [1/11] pasemi_mac: basic error checking
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
@ 2007-10-02 21:24 ` Olof Johansson
2007-10-03 17:50 ` Jeff Garzik
2007-10-02 21:25 ` [PATCH] [2/11] pasemi_mac: fix bug in receive buffer dma mapping Olof Johansson
` (9 subsequent siblings)
10 siblings, 1 reply; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:24 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [2/11] pasemi_mac: fix bug in receive buffer dma mapping
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
2007-10-02 21:24 ` [PATCH] [1/11] pasemi_mac: basic error checking Olof Johansson
@ 2007-10-02 21:25 ` Olof Johansson
2007-10-02 21:25 ` [PATCH] [3/11] pasemi_mac: rework ring management Olof Johansson
` (8 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:25 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [3/11] pasemi_mac: rework ring management
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
2007-10-02 21:24 ` [PATCH] [1/11] pasemi_mac: basic error checking Olof Johansson
2007-10-02 21:25 ` [PATCH] [2/11] pasemi_mac: fix bug in receive buffer dma mapping Olof Johansson
@ 2007-10-02 21:25 ` Olof Johansson
2007-10-02 21:26 ` [PATCH] [4/11] pasemi_mac: implement sg support Olof Johansson
` (7 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:25 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [4/11] pasemi_mac: implement sg support
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
` (2 preceding siblings ...)
2007-10-02 21:25 ` [PATCH] [3/11] pasemi_mac: rework ring management Olof Johansson
@ 2007-10-02 21:26 ` Olof Johansson
2007-10-02 21:26 ` [PATCH] [5/11] pasemi_mac: workaround for erratum 5971 Olof Johansson
` (6 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:26 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [5/11] pasemi_mac: workaround for erratum 5971
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
` (3 preceding siblings ...)
2007-10-02 21:26 ` [PATCH] [4/11] pasemi_mac: implement sg support Olof Johansson
@ 2007-10-02 21:26 ` Olof Johansson
2007-10-02 21:26 ` [PATCH] [6/11] pasemi_mac: add local skb alignment Olof Johansson
` (5 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:26 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [6/11] pasemi_mac: add local skb alignment
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
` (4 preceding siblings ...)
2007-10-02 21:26 ` [PATCH] [5/11] pasemi_mac: workaround for erratum 5971 Olof Johansson
@ 2007-10-02 21:26 ` Olof Johansson
2007-10-02 21:27 ` [PATCH] [7/11] pasemi_mac: further performance tweaks Olof Johansson
` (4 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:26 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [7/11] pasemi_mac: further performance tweaks
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
` (5 preceding siblings ...)
2007-10-02 21:26 ` [PATCH] [6/11] pasemi_mac: add local skb alignment Olof Johansson
@ 2007-10-02 21:27 ` Olof Johansson
2007-10-02 21:27 ` [PATCH] [8/11] pasemi_mac: update todo list Olof Johansson
` (3 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:27 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [8/11] pasemi_mac: update todo list
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
` (6 preceding siblings ...)
2007-10-02 21:27 ` [PATCH] [7/11] pasemi_mac: further performance tweaks Olof Johansson
@ 2007-10-02 21:27 ` Olof Johansson
2007-10-02 21:27 ` [PATCH] [9/11] pasemi_mac: clear out old errors on interface open Olof Johansson
` (2 subsequent siblings)
10 siblings, 0 replies; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:27 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
` (7 preceding siblings ...)
2007-10-02 21:27 ` [PATCH] [8/11] pasemi_mac: update todo list Olof Johansson
@ 2007-10-02 21:27 ` Olof Johansson
2007-10-03 17:46 ` Jeff Garzik
2007-10-02 21:27 ` [PATCH] [10/11] pasemi_mac: use buffer index pointer in clean_rx() Olof Johansson
2007-10-02 21:28 ` [PATCH] [11/11] pasemi_mac: enable iommu support Olof Johansson
10 siblings, 1 reply; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:27 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [10/11] pasemi_mac: use buffer index pointer in clean_rx()
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
` (8 preceding siblings ...)
2007-10-02 21:27 ` [PATCH] [9/11] pasemi_mac: clear out old errors on interface open Olof Johansson
@ 2007-10-02 21:27 ` Olof Johansson
2007-10-02 21:28 ` [PATCH] [11/11] pasemi_mac: enable iommu support Olof Johansson
10 siblings, 0 replies; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:27 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* [PATCH] [11/11] pasemi_mac: enable iommu support
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
` (9 preceding siblings ...)
2007-10-02 21:27 ` [PATCH] [10/11] pasemi_mac: use buffer index pointer in clean_rx() Olof Johansson
@ 2007-10-02 21:28 ` Olof Johansson
2007-10-03 17:47 ` Jeff Garzik
10 siblings, 1 reply; 19+ messages in thread
From: Olof Johansson @ 2007-10-02 21:28 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
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 [flat|nested] 19+ messages in thread
* Re: [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
2007-10-02 21:27 ` [PATCH] [9/11] pasemi_mac: clear out old errors on interface open Olof Johansson
@ 2007-10-03 17:46 ` Jeff Garzik
2007-10-03 18:02 ` Olof Johansson
0 siblings, 1 reply; 19+ messages in thread
From: Jeff Garzik @ 2007-10-03 17:46 UTC (permalink / raw)
To: Olof Johansson; +Cc: netdev, linuxppc-dev
Olof Johansson wrote:
> 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>
In general, interface-open should completely reset and initialize the
hardware. does pasemi_mac not do that?
Jeff
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] [11/11] pasemi_mac: enable iommu support
2007-10-02 21:28 ` [PATCH] [11/11] pasemi_mac: enable iommu support Olof Johansson
@ 2007-10-03 17:47 ` Jeff Garzik
2007-10-03 18:03 ` [PATCH RESEND] " Olof Johansson
0 siblings, 1 reply; 19+ messages in thread
From: Jeff Garzik @ 2007-10-03 17:47 UTC (permalink / raw)
To: Olof Johansson; +Cc: netdev, linuxppc-dev
Olof Johansson wrote:
> 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>
You sent patch #10 against as patch #11 :)
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] [1/11] pasemi_mac: basic error checking
2007-10-02 21:24 ` [PATCH] [1/11] pasemi_mac: basic error checking Olof Johansson
@ 2007-10-03 17:50 ` Jeff Garzik
0 siblings, 0 replies; 19+ messages in thread
From: Jeff Garzik @ 2007-10-03 17:50 UTC (permalink / raw)
To: Olof Johansson; +Cc: netdev, linuxppc-dev
Olof Johansson wrote:
> pasemi_mac: basic error checking
>
> Add some rudimentary error checking to pasemi_mac.
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
applied 1-10
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
2007-10-03 17:46 ` Jeff Garzik
@ 2007-10-03 18:02 ` Olof Johansson
2007-10-03 18:15 ` Jeff Garzik
0 siblings, 1 reply; 19+ messages in thread
From: Olof Johansson @ 2007-10-03 18:02 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, linuxppc-dev
On Wed, Oct 03, 2007 at 01:46:16PM -0400, Jeff Garzik wrote:
> Olof Johansson wrote:
>> 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>
>
> In general, interface-open should completely reset and initialize the
> hardware. does pasemi_mac not do that?
There's no explicit way to reset just one interface besides disabling it
(which we do at close, and re-enable at open). It seems that some of
the error bits are sticky across disable/enable, which is why this was
needed. Also, they're RW1C, so writing 0 doesn't remove them (need to
write 1 to clear).
The only other dependency from firmware at this time is the setting of mac
addresses, something that will be taken care of once we allow override of
them via ethtool, since we'd need to program them from the driver then
no matter what. Right now we assume that firmware has programmed it.
-Olof
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH RESEND] [11/11] pasemi_mac: enable iommu support
2007-10-03 17:47 ` Jeff Garzik
@ 2007-10-03 18:03 ` Olof Johansson
2007-10-03 18:19 ` Jeff Garzik
0 siblings, 1 reply; 19+ messages in thread
From: Olof Johansson @ 2007-10-03 18:03 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, linuxppc-dev
pasemi_mac: enable iommu support
Enable IOMMU support for pasemi_mac, but avoid using it on non-partitioned
systems for performance reasons.
The user can override this by selecting the PPC_PASEMI_IOMMU_DMA_FORCE
configuration option.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
On Wed, Oct 03, 2007 at 01:47:17PM -0400, Jeff Garzik wrote:
> You sent patch #10 against as patch #11 :)
Oops! Here's the real copy.
-Olof
Index: k.org/arch/powerpc/platforms/pasemi/iommu.c
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/iommu.c
+++ k.org/arch/powerpc/platforms/pasemi/iommu.c
@@ -25,6 +25,7 @@
#include <asm/iommu.h>
#include <asm/machdep.h>
#include <asm/abs_addr.h>
+#include <asm/firmware.h>
#define IOBMAP_PAGE_SHIFT 12
@@ -175,13 +176,17 @@ static void pci_dma_dev_setup_pasemi(str
{
pr_debug("pci_dma_dev_setup, dev %p (%s)\n", dev, pci_name(dev));
- /* DMA device is untranslated, but all other PCI-e goes through
- * the IOMMU
+#if !defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
+ /* For non-LPAR environment, don't translate anything for the DMA
+ * engine. The exception to this is if the user has enabled
+ * CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE at build time.
*/
- if (dev->vendor == 0x1959 && dev->device == 0xa007)
+ if (dev->vendor == 0x1959 && dev->device == 0xa007 &&
+ !firmware_has_feature(FW_FEATURE_LPAR))
dev->dev.archdata.dma_ops = &dma_direct_ops;
- else
- dev->dev.archdata.dma_data = &iommu_table_iobmap;
+#endif
+
+ dev->dev.archdata.dma_data = &iommu_table_iobmap;
}
static void pci_dma_bus_setup_null(struct pci_bus *b) { }
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -34,6 +34,7 @@
#include <net/checksum.h>
#include <asm/irq.h>
+#include <asm/firmware.h>
#include "pasemi_mac.h"
@@ -89,6 +90,15 @@ MODULE_PARM_DESC(debug, "PA Semi MAC bit
static struct pasdma_status *dma_status;
+static int translation_enabled(void)
+{
+#if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
+ return 1;
+#else
+ return firmware_has_feature(FW_FEATURE_LPAR);
+#endif
+}
+
static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg,
unsigned int val)
{
@@ -193,6 +203,7 @@ static int pasemi_mac_setup_rx_resources
struct pasemi_mac_rxring *ring;
struct pasemi_mac *mac = netdev_priv(dev);
int chan_id = mac->dma_rxch;
+ unsigned int cfg;
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
@@ -232,20 +243,28 @@ static int pasemi_mac_setup_rx_resources
PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) |
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));
+ cfg = PAS_DMA_RXCHAN_CFG_HBU(2);
+
+ if (translation_enabled())
+ cfg |= PAS_DMA_RXCHAN_CFG_CTR;
+
+ write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id), cfg);
write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if),
- PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers)));
+ PAS_DMA_RXINT_BASEL_BRBL(ring->buf_dma));
write_dma_reg(mac, PAS_DMA_RXINT_BASEU(mac->dma_if),
- PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) |
+ PAS_DMA_RXINT_BASEU_BRBH(ring->buf_dma >> 32) |
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_RBP |
- PAS_DMA_RXINT_CFG_HEN);
+ cfg = 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;
+
+ if (translation_enabled())
+ cfg |= PAS_DMA_RXINT_CFG_ITRR | PAS_DMA_RXINT_CFG_ITR;
+
+ write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if), cfg);
ring->next_to_fill = 0;
ring->next_to_clean = 0;
@@ -275,6 +294,7 @@ static int pasemi_mac_setup_tx_resources
u32 val;
int chan_id = mac->dma_txch;
struct pasemi_mac_txring *ring;
+ unsigned int cfg;
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
if (!ring)
@@ -304,11 +324,15 @@ static int pasemi_mac_setup_tx_resources
write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val);
- write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id),
- PAS_DMA_TXCHAN_CFG_TY_IFACE |
- PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
- PAS_DMA_TXCHAN_CFG_UP |
- PAS_DMA_TXCHAN_CFG_WT(2));
+ cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
+ PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
+ PAS_DMA_TXCHAN_CFG_UP |
+ PAS_DMA_TXCHAN_CFG_WT(2);
+
+ if (translation_enabled())
+ cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
+
+ write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id), cfg);
ring->next_to_fill = 0;
ring->next_to_clean = 0;
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -212,6 +212,7 @@ 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_ITR 0x00400000
#define PAS_DMA_RXINT_CFG_LW 0x00200000
#define PAS_DMA_RXINT_CFG_L2 0x00100000
#define PAS_DMA_RXINT_CFG_HEN 0x00080000
@@ -258,9 +259,11 @@ enum {
#define PAS_DMA_TXCHAN_CFG_WT_S 6
#define PAS_DMA_TXCHAN_CFG_WT(x) (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
PAS_DMA_TXCHAN_CFG_WT_M)
-#define PAS_DMA_TXCHAN_CFG_CF 0x00001000 /* Clean first line */
-#define PAS_DMA_TXCHAN_CFG_CL 0x00002000 /* Clean last line */
+#define PAS_DMA_TXCHAN_CFG_TRD 0x00010000 /* translate data */
+#define PAS_DMA_TXCHAN_CFG_TRR 0x00008000 /* translate rings */
#define PAS_DMA_TXCHAN_CFG_UP 0x00004000 /* update tx descr when sent */
+#define PAS_DMA_TXCHAN_CFG_CL 0x00002000 /* Clean last line */
+#define PAS_DMA_TXCHAN_CFG_CF 0x00001000 /* Clean first line */
#define PAS_DMA_TXCHAN_INCR(c) (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE)
#define PAS_DMA_TXCHAN_BASEL(c) (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE)
#define PAS_DMA_TXCHAN_BASEL_BRBL_M 0xffffffc0
@@ -294,6 +297,7 @@ enum {
#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_CTR 0x00000400
#define PAS_DMA_RXCHAN_CFG_HBU_M 0x00000380
#define PAS_DMA_RXCHAN_CFG_HBU_S 7
#define PAS_DMA_RXCHAN_CFG_HBU(x) (((x) << PAS_DMA_RXCHAN_CFG_HBU_S) & \
Index: k.org/arch/powerpc/platforms/pasemi/Kconfig
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/Kconfig
+++ k.org/arch/powerpc/platforms/pasemi/Kconfig
@@ -19,6 +19,16 @@ config PPC_PASEMI_IOMMU
help
IOMMU support for PA6T-1682M
+config PPC_PASEMI_IOMMU_DMA_FORCE
+ bool "Force DMA engine to use IOMMU"
+ depends on PPC_PASEMI_IOMMU
+ help
+ This option forces the use of the IOMMU also for the
+ DMA engine. Otherwise the kernel will use it only when
+ running under a hypervisor.
+
+ If in doubt, say "N".
+
config PPC_PASEMI_MDIO
depends on PHYLIB
tristate "MDIO support via GPIO"
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
2007-10-03 18:02 ` Olof Johansson
@ 2007-10-03 18:15 ` Jeff Garzik
0 siblings, 0 replies; 19+ messages in thread
From: Jeff Garzik @ 2007-10-03 18:15 UTC (permalink / raw)
To: Olof Johansson; +Cc: netdev, linuxppc-dev
Olof Johansson wrote:
> On Wed, Oct 03, 2007 at 01:46:16PM -0400, Jeff Garzik wrote:
>> Olof Johansson wrote:
>>> 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>
>> In general, interface-open should completely reset and initialize the
>> hardware. does pasemi_mac not do that?
>
> There's no explicit way to reset just one interface besides disabling it
> (which we do at close, and re-enable at open). It seems that some of
> the error bits are sticky across disable/enable, which is why this was
> needed. Also, they're RW1C, so writing 0 doesn't remove them (need to
> write 1 to clear).
OK just making sure, thanks.
> The only other dependency from firmware at this time is the setting of mac
> addresses, something that will be taken care of once we allow override of
> them via ethtool, since we'd need to program them from the driver then
> no matter what. Right now we assume that firmware has programmed it.
Standard procedure for this is
* upon module-load, obtain the MAC address from <whatever canonical source>
* upon interface-up, program dev->dev_addr[] into chip's RX filter (aka
MAC address) registers
That permits the admin to override the MAC address via ifconfig.
(ethtool doesn't support that, but you basically had the right idea)
Jeff
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH RESEND] [11/11] pasemi_mac: enable iommu support
2007-10-03 18:03 ` [PATCH RESEND] " Olof Johansson
@ 2007-10-03 18:19 ` Jeff Garzik
0 siblings, 0 replies; 19+ messages in thread
From: Jeff Garzik @ 2007-10-03 18:19 UTC (permalink / raw)
To: Olof Johansson; +Cc: netdev, linuxppc-dev
Olof Johansson wrote:
> pasemi_mac: enable iommu support
>
> Enable IOMMU support for pasemi_mac, but avoid using it on non-partitioned
> systems for performance reasons.
>
> The user can override this by selecting the PPC_PASEMI_IOMMU_DMA_FORCE
> configuration option.
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
applied
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2007-10-03 18:19 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-02 21:24 [PATCH] [0/11] pasemi_mac: Patches for 2.6.24 Olof Johansson
2007-10-02 21:24 ` [PATCH] [1/11] pasemi_mac: basic error checking Olof Johansson
2007-10-03 17:50 ` Jeff Garzik
2007-10-02 21:25 ` [PATCH] [2/11] pasemi_mac: fix bug in receive buffer dma mapping Olof Johansson
2007-10-02 21:25 ` [PATCH] [3/11] pasemi_mac: rework ring management Olof Johansson
2007-10-02 21:26 ` [PATCH] [4/11] pasemi_mac: implement sg support Olof Johansson
2007-10-02 21:26 ` [PATCH] [5/11] pasemi_mac: workaround for erratum 5971 Olof Johansson
2007-10-02 21:26 ` [PATCH] [6/11] pasemi_mac: add local skb alignment Olof Johansson
2007-10-02 21:27 ` [PATCH] [7/11] pasemi_mac: further performance tweaks Olof Johansson
2007-10-02 21:27 ` [PATCH] [8/11] pasemi_mac: update todo list Olof Johansson
2007-10-02 21:27 ` [PATCH] [9/11] pasemi_mac: clear out old errors on interface open Olof Johansson
2007-10-03 17:46 ` Jeff Garzik
2007-10-03 18:02 ` Olof Johansson
2007-10-03 18:15 ` Jeff Garzik
2007-10-02 21:27 ` [PATCH] [10/11] pasemi_mac: use buffer index pointer in clean_rx() Olof Johansson
2007-10-02 21:28 ` [PATCH] [11/11] pasemi_mac: enable iommu support Olof Johansson
2007-10-03 17:47 ` Jeff Garzik
2007-10-03 18:03 ` [PATCH RESEND] " Olof Johansson
2007-10-03 18:19 ` Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).