linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library
@ 2007-11-29  2:54 Olof Johansson
  2007-11-29  2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
                   ` (12 more replies)
  0 siblings, 13 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:54 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

Hi,

The following series contains driver updates for 2.6.25, together with a
couple of patches that introduces a library for abstracting DMA channel
allocation and access.

While the DMA stuff (patches 5 and 6) isn't really netdev material, the
driver updates depend on them, and it'd just be easier to merge them up
the netdev path.

The patches are:

1/12: pasemi_mac: RX/TX ring management cleanup
2/12: pasemi_mac: Remove SKB copy/recycle logic
3/12: pasemi_mac: Print warning when not attaching to a PHY
4/12: pasemi_mac: Don't enable RX/TX without a link (if possible)
5/12: pasemi_mac: Move register definitions to include/asm-powerpc
6/12: pasemi: DMA engine management library
7/12: pasemi_mac: Convert to new dma library
8/12: pasemi_mac: performance tweaks
9/12: pasemi_mac: Fix TX cleaning
10/12: pasemi_mac: Improve RX interrupt mitigation
l1/12: pasemi_mac: Software-based LRO support
12/12: pasemi_mac: SKB unmap optimization



-Olof

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
@ 2007-11-29  2:54 ` Olof Johansson
  2007-12-01 21:54   ` Jeff Garzik
  2007-11-29  2:56 ` [PATCH] [2/12] pasemi_mac: Move register definitions to include/asm-powerpc Olof Johansson
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:54 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: RX/TX ring management cleanup

Prepare a bit for supporting multiple TX queues by cleaning up some
of the ring management and shuffle things around a bit.

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


---
 drivers/net/pasemi_mac.c |  277 ++++++++++++++++++++++++-----------------------
 drivers/net/pasemi_mac.h |   19 +--
 2 files changed, 157 insertions(+), 139 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -68,11 +68,11 @@
 	 NETIF_MSG_RX_ERR	| \
 	 NETIF_MSG_TX_ERR)
 
-#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 TX_DESC(tx, num)	((tx)->ring[(num) & (TX_RING_SIZE-1)])
+#define TX_DESC_INFO(tx, num)	((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
+#define RX_DESC(rx, num)	((rx)->ring[(num) & (RX_RING_SIZE-1)])
+#define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
+#define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
 
 #define RING_USED(ring)		(((ring)->next_to_fill - (ring)->next_to_clean) \
 				 & ((ring)->size - 1))
@@ -127,6 +127,16 @@ static void write_dma_reg(struct pasemi_
 	out_le32(mac->dma_regs+reg, val);
 }
 
+static struct pasemi_mac_rxring *rx_ring(struct pasemi_mac *mac)
+{
+	return mac->rx;
+}
+
+static struct pasemi_mac_txring *tx_ring(struct pasemi_mac *mac)
+{
+	return mac->tx;
+}
+
 static int pasemi_get_mac_addr(struct pasemi_mac *mac)
 {
 	struct pci_dev *pdev = mac->pdev;
@@ -269,8 +279,8 @@ static int pasemi_mac_setup_rx_resources
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
 
-	snprintf(ring->irq_name, sizeof(ring->irq_name),
-		 "%s rx", dev->name);
+	ring->status = &dma_status->rx_sta[mac->dma_rxch];
+	ring->mac = mac;
 	mac->rx = ring;
 
 	return 0;
@@ -278,7 +288,7 @@ static int pasemi_mac_setup_rx_resources
 out_buffers:
 	dma_free_coherent(&mac->dma_pdev->dev,
 			  RX_RING_SIZE * sizeof(u64),
-			  mac->rx->ring, mac->rx->dma);
+			  rx_ring(mac)->ring, rx_ring(mac)->dma);
 out_ring_desc:
 	kfree(ring->ring_info);
 out_ring_info:
@@ -287,12 +297,11 @@ out_ring:
 	return -ENOMEM;
 }
 
-
-static int pasemi_mac_setup_tx_resources(struct net_device *dev)
+static struct pasemi_mac_txring *
+pasemi_mac_setup_tx_resources(struct net_device *dev, int txch)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	u32 val;
-	int chan_id = mac->dma_txch;
 	struct pasemi_mac_txring *ring;
 	unsigned int cfg;
 
@@ -317,12 +326,12 @@ static int pasemi_mac_setup_tx_resources
 
 	memset(ring->ring, 0, TX_RING_SIZE * sizeof(u64));
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEL(chan_id),
+	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEL(txch),
 			   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 >> 3);
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val);
+	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(txch), val);
 
 	cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
 	      PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
@@ -332,71 +341,70 @@ static int pasemi_mac_setup_tx_resources
 	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);
+	write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(txch), cfg);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
+	ring->status = &dma_status->tx_sta[txch];
+	ring->chan = txch;
+	ring->mac = mac;
 
-	snprintf(ring->irq_name, sizeof(ring->irq_name),
-		 "%s tx", dev->name);
-	mac->tx = ring;
-
-	return 0;
+	return ring;
 
 out_ring_desc:
 	kfree(ring->ring_info);
 out_ring_info:
 	kfree(ring);
 out_ring:
-	return -ENOMEM;
+	return NULL;
 }
 
-static void pasemi_mac_free_tx_resources(struct net_device *dev)
+static void pasemi_mac_free_tx_resources(struct pasemi_mac *mac)
 {
-	struct pasemi_mac *mac = netdev_priv(dev);
+	struct pasemi_mac_txring *txring = tx_ring(mac);
 	unsigned int i, j;
 	struct pasemi_mac_buffer *info;
 	dma_addr_t dmas[MAX_SKB_FRAGS+1];
 	int freed;
 	int start, limit;
 
-	start = mac->tx->next_to_clean;
-	limit = mac->tx->next_to_fill;
+	start = txring->next_to_clean;
+	limit = txring->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);
+		info = &txring->ring_info[(i+1) & (TX_RING_SIZE-1)];
 		if (info->dma && info->skb) {
 			for (j = 0; j <= skb_shinfo(info->skb)->nr_frags; j++)
-				dmas[j] = TX_RING_INFO(mac, i+1+j).dma;
+				dmas[j] = txring->ring_info[(i+1+j) &
+						(TX_RING_SIZE-1)].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;
+		txring->ring[i] = 0;
 
 	dma_free_coherent(&mac->dma_pdev->dev,
 			  TX_RING_SIZE * sizeof(u64),
-			  mac->tx->ring, mac->tx->dma);
+			  txring->ring, txring->dma);
 
-	kfree(mac->tx->ring_info);
-	kfree(mac->tx);
-	mac->tx = NULL;
+	kfree(txring->ring_info);
+	kfree(txring);
 }
 
-static void pasemi_mac_free_rx_resources(struct net_device *dev)
+static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
 {
-	struct pasemi_mac *mac = netdev_priv(dev);
+	struct pasemi_mac_rxring *rx = rx_ring(mac);
 	unsigned int i;
 	struct pasemi_mac_buffer *info;
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		info = &RX_RING_INFO(mac, i);
+		info = &RX_DESC_INFO(rx, i);
 		if (info->skb && info->dma) {
 			pci_unmap_single(mac->dma_pdev,
 					 info->dma,
@@ -409,32 +417,33 @@ static void pasemi_mac_free_rx_resources
 	}
 
 	for (i = 0; i < RX_RING_SIZE; i++)
-		RX_RING(mac, i) = 0;
+		RX_DESC(rx, i) = 0;
 
 	dma_free_coherent(&mac->dma_pdev->dev,
 			  RX_RING_SIZE * sizeof(u64),
-			  mac->rx->ring, mac->rx->dma);
+			  rx_ring(mac)->ring, rx_ring(mac)->dma);
 
 	dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
-			  mac->rx->buffers, mac->rx->buf_dma);
+			  rx_ring(mac)->buffers, rx_ring(mac)->buf_dma);
 
-	kfree(mac->rx->ring_info);
-	kfree(mac->rx);
+	kfree(rx_ring(mac)->ring_info);
+	kfree(rx_ring(mac));
 	mac->rx = NULL;
 }
 
 static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
+	struct pasemi_mac_rxring *rx = rx_ring(mac);
 	int fill, count;
 
 	if (limit <= 0)
 		return;
 
-	fill = mac->rx->next_to_fill;
+	fill = rx_ring(mac)->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);
+		struct pasemi_mac_buffer *info = &RX_DESC_INFO(rx, fill);
+		u64 *buff = &RX_BUFF(rx, fill);
 		struct sk_buff *skb;
 		dma_addr_t dma;
 
@@ -471,7 +480,7 @@ static void pasemi_mac_replenish_rx_ring
 
 	write_dma_reg(mac, PAS_DMA_RXINT_INCR(mac->dma_if), count);
 
-	mac->rx->next_to_fill = (mac->rx->next_to_fill + count) &
+	rx_ring(mac)->next_to_fill = (rx_ring(mac)->next_to_fill + count) &
 				(RX_RING_SIZE - 1);
 }
 
@@ -482,7 +491,7 @@ static void pasemi_mac_restart_rx_intr(s
 	 * ack the packet count interrupt we got in rx_intr.
 	 */
 
-	pcnt = *mac->rx_status & PAS_STATUS_PCNT_M;
+	pcnt = *rx_ring(mac)->status & PAS_STATUS_PCNT_M;
 
 	reg = PAS_IOB_DMA_RXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_RXCH_RESET_PINTC;
 
@@ -494,11 +503,11 @@ static void pasemi_mac_restart_tx_intr(s
 	unsigned int reg, pcnt;
 
 	/* Re-enable packet count interrupts */
-	pcnt = *mac->tx_status & PAS_STATUS_PCNT_M;
+	pcnt = *tx_ring(mac)->status & PAS_STATUS_PCNT_M;
 
 	reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
 
-	write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
+	write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(tx_ring(mac)->chan), reg);
 }
 
 
@@ -513,7 +522,7 @@ static inline void pasemi_mac_rx_error(s
 	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);
+		macrx, *rx_ring(mac)->status);
 
 	printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n",
 		rcmdsta, ccmdsta);
@@ -529,13 +538,14 @@ static inline void pasemi_mac_tx_error(s
 	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);
+		"tx status 0x%016lx\n", mactx, *tx_ring(mac)->status);
 
 	printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta);
 }
 
-static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
+static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx, int limit)
 {
+	struct pasemi_mac *mac = rx->mac;
 	unsigned int n;
 	int count;
 	struct pasemi_mac_buffer *info;
@@ -546,17 +556,17 @@ static int pasemi_mac_clean_rx(struct pa
 	int buf_index;
 	u64 eval;
 
-	spin_lock(&mac->rx->lock);
+	spin_lock(&rx->lock);
 
-	n = mac->rx->next_to_clean;
+	n = rx->next_to_clean;
 
-	prefetch(&RX_RING(mac, n));
+	prefetch(&RX_DESC(rx, n));
 
 	for (count = 0; count < limit; count++) {
-		macrx = RX_RING(mac, n);
+		macrx = RX_DESC(rx, n);
 
 		if ((macrx & XCT_MACRX_E) ||
-		    (*mac->rx_status & PAS_STATUS_ERROR))
+		    (*rx_ring(mac)->status & PAS_STATUS_ERROR))
 			pasemi_mac_rx_error(mac, macrx);
 
 		if (!(macrx & XCT_MACRX_O))
@@ -566,12 +576,12 @@ static int pasemi_mac_clean_rx(struct pa
 
 		BUG_ON(!(macrx & XCT_MACRX_RR_8BRES));
 
-		eval = (RX_RING(mac, n+1) & XCT_RXRES_8B_EVAL_M) >>
+		eval = (RX_DESC(rx, 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);
+		dma = (RX_DESC(rx, n+2) & XCT_PTR_ADDR_M);
+		info = &RX_DESC_INFO(rx, buf_index);
 
 		skb = info->skb;
 
@@ -624,13 +634,13 @@ static int pasemi_mac_clean_rx(struct pa
 		netif_receive_skb(skb);
 
 next:
-		RX_RING(mac, n) = 0;
-		RX_RING(mac, n+1) = 0;
+		RX_DESC(rx, n) = 0;
+		RX_DESC(rx, 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, buf_index) = 0;
+		RX_BUFF(rx, buf_index) = 0;
 
 		n += 4;
 	}
@@ -641,7 +651,7 @@ next:
 		n &= (RX_RING_SIZE-1);
 	}
 
-	mac->rx->next_to_clean = n;
+	rx_ring(mac)->next_to_clean = n;
 
 	/* Increase is in number of 16-byte entries, and since each descriptor
 	 * with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with
@@ -651,7 +661,7 @@ next:
 
 	pasemi_mac_replenish_rx_ring(mac->netdev, count);
 
-	spin_unlock(&mac->rx->lock);
+	spin_unlock(&rx_ring(mac)->lock);
 
 	return count;
 }
@@ -659,8 +669,9 @@ next:
 /* 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)
+static int pasemi_mac_clean_tx(struct pasemi_mac_txring *txring)
 {
+	struct pasemi_mac *mac = txring->mac;
 	int i, j;
 	unsigned int start, descr_count, buf_count, batch_limit;
 	unsigned int ring_limit;
@@ -672,10 +683,10 @@ static int pasemi_mac_clean_tx(struct pa
 	total_count = 0;
 	batch_limit = TX_CLEAN_BATCHSIZE;
 restart:
-	spin_lock_irqsave(&mac->tx->lock, flags);
+	spin_lock_irqsave(&txring->lock, flags);
 
-	start = mac->tx->next_to_clean;
-	ring_limit = mac->tx->next_to_fill;
+	start = txring->next_to_clean;
+	ring_limit = txring->next_to_fill;
 
 	/* Compensate for when fill has wrapped but clean has not */
 	if (start > ring_limit)
@@ -687,26 +698,26 @@ restart:
 	for (i = start;
 	     descr_count < batch_limit && i < ring_limit;
 	     i += buf_count) {
-		u64 mactx = TX_RING(mac, i);
+		u64 mactx = TX_DESC(txring, i);
 		struct sk_buff *skb;
 
 		if ((mactx  & XCT_MACTX_E) ||
-		    (*mac->tx_status & PAS_STATUS_ERROR))
+		    (*tx_ring(mac)->status & PAS_STATUS_ERROR))
 			pasemi_mac_tx_error(mac, mactx);
 
 		if (unlikely(mactx & XCT_MACTX_O))
 			/* Not yet transmitted */
 			break;
 
-		skb = TX_RING_INFO(mac, i+1).skb;
+		skb = TX_DESC_INFO(txring, i+1).skb;
 		skbs[descr_count] = skb;
 
 		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;
+			dmas[descr_count][j] = TX_DESC_INFO(txring, i+1+j).dma;
 
-		TX_RING(mac, i) = 0;
-		TX_RING(mac, i+1) = 0;
+		TX_DESC(txring, i) = 0;
+		TX_DESC(txring, i+1) = 0;
 
 		/* Since we always fill with an even number of entries, make
 		 * sure we skip any unused one at the end as well.
@@ -715,9 +726,9 @@ restart:
 			buf_count++;
 		descr_count++;
 	}
-	mac->tx->next_to_clean = i & (TX_RING_SIZE-1);
+	txring->next_to_clean = i & (TX_RING_SIZE-1);
 
-	spin_unlock_irqrestore(&mac->tx->lock, flags);
+	spin_unlock_irqrestore(&txring->lock, flags);
 	netif_wake_queue(mac->netdev);
 
 	for (i = 0; i < descr_count; i++)
@@ -739,7 +750,7 @@ static irqreturn_t pasemi_mac_rx_intr(in
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int reg;
 
-	if (!(*mac->rx_status & PAS_STATUS_CAUSE_M))
+	if (!(*rx_ring(mac)->status & PAS_STATUS_CAUSE_M))
 		return IRQ_NONE;
 
 	/* Don't reset packet count so it won't fire again but clear
@@ -747,11 +758,11 @@ static irqreturn_t pasemi_mac_rx_intr(in
 	 */
 
 	reg = 0;
-	if (*mac->rx_status & PAS_STATUS_SOFT)
+	if (*rx_ring(mac)->status & PAS_STATUS_SOFT)
 		reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
-	if (*mac->rx_status & PAS_STATUS_ERROR)
+	if (*rx_ring(mac)->status & PAS_STATUS_ERROR)
 		reg |= PAS_IOB_DMA_RXCH_RESET_DINTC;
-	if (*mac->rx_status & PAS_STATUS_TIMER)
+	if (*rx_ring(mac)->status & PAS_STATUS_TIMER)
 		reg |= PAS_IOB_DMA_RXCH_RESET_TINTC;
 
 	netif_rx_schedule(dev, &mac->napi);
@@ -763,25 +774,25 @@ static irqreturn_t pasemi_mac_rx_intr(in
 
 static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
 {
-	struct net_device *dev = data;
-	struct pasemi_mac *mac = netdev_priv(dev);
+	struct pasemi_mac_txring *txring = data;
+	struct pasemi_mac *mac = txring->mac;
 	unsigned int reg, pcnt;
 
-	if (!(*mac->tx_status & PAS_STATUS_CAUSE_M))
+	if (!(*txring->status & PAS_STATUS_CAUSE_M))
 		return IRQ_NONE;
 
-	pasemi_mac_clean_tx(mac);
+	pasemi_mac_clean_tx(txring);
 
-	pcnt = *mac->tx_status & PAS_STATUS_PCNT_M;
+	pcnt = *txring->status & PAS_STATUS_PCNT_M;
 
 	reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
 
-	if (*mac->tx_status & PAS_STATUS_SOFT)
+	if (*txring->status & PAS_STATUS_SOFT)
 		reg |= PAS_IOB_DMA_TXCH_RESET_SINTC;
-	if (*mac->tx_status & PAS_STATUS_ERROR)
+	if (*txring->status & PAS_STATUS_ERROR)
 		reg |= PAS_IOB_DMA_TXCH_RESET_DINTC;
 
-	write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
+	write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(txring->chan), reg);
 
 	return IRQ_HANDLED;
 }
@@ -919,10 +930,6 @@ static int pasemi_mac_open(struct net_de
 	write_iob_reg(mac, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
 			   PAS_IOB_DMA_TXCH_CFG_CNTTH(128));
 
-	/* Clear out any residual packet count state from firmware */
-	pasemi_mac_restart_rx_intr(mac);
-	pasemi_mac_restart_tx_intr(mac);
-
 	/* 0xffffff is max value, about 16ms */
 	write_iob_reg(mac, PAS_IOB_DMA_COM_TIMEOUTCFG,
 			   PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
@@ -931,9 +938,10 @@ static int pasemi_mac_open(struct net_de
 	if (ret)
 		goto out_rx_resources;
 
-	ret = pasemi_mac_setup_tx_resources(dev);
-	if (ret)
-		goto out_tx_resources;
+	mac->tx = pasemi_mac_setup_tx_resources(dev, mac->dma_txch);
+
+	if (!mac->tx)
+		goto out_tx_ring;
 
 	write_mac_reg(mac, PAS_MAC_IPC_CHNL,
 			   PAS_MAC_IPC_CHNL_DCHNO(mac->dma_rxch) |
@@ -967,6 +975,10 @@ static int pasemi_mac_open(struct net_de
 
 	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), RX_RING_SIZE>>1);
 
+	/* Clear out any residual packet count state from firmware */
+	pasemi_mac_restart_rx_intr(mac);
+	pasemi_mac_restart_tx_intr(mac);
+
 	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
 		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
 
@@ -997,18 +1009,25 @@ static int pasemi_mac_open(struct net_de
 	base_irq = virq_to_hw(mac->dma_pdev->irq);
 
 	mac->tx_irq = irq_create_mapping(NULL, base_irq + mac->dma_txch);
-	mac->rx_irq = irq_create_mapping(NULL, base_irq + 20 + mac->dma_txch);
+
+	snprintf(mac->tx_irq_name, sizeof(mac->tx_irq_name), "%s tx",
+		 dev->name);
 
 	ret = request_irq(mac->tx_irq, &pasemi_mac_tx_intr, IRQF_DISABLED,
-			  mac->tx->irq_name, dev);
+			  mac->tx_irq_name, mac->tx);
 	if (ret) {
 		dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
 			base_irq + mac->dma_txch, ret);
 		goto out_tx_int;
 	}
 
+	mac->rx_irq = irq_create_mapping(NULL, base_irq + 20 + mac->dma_rxch);
+
+	snprintf(mac->rx_irq_name, sizeof(mac->rx_irq_name), "%s rx",
+		 dev->name);
+
 	ret = request_irq(mac->rx_irq, &pasemi_mac_rx_intr, IRQF_DISABLED,
-			  mac->rx->irq_name, dev);
+			  mac->rx_irq_name, dev);
 	if (ret) {
 		dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
 			base_irq + 20 + mac->dma_rxch, ret);
@@ -1021,13 +1040,14 @@ static int pasemi_mac_open(struct net_de
 	return 0;
 
 out_rx_int:
-	free_irq(mac->tx_irq, dev);
+	free_irq(mac->tx_irq, mac->tx);
 out_tx_int:
 	napi_disable(&mac->napi);
 	netif_stop_queue(dev);
-	pasemi_mac_free_tx_resources(dev);
-out_tx_resources:
-	pasemi_mac_free_rx_resources(dev);
+out_tx_ring:
+	if (mac->tx)
+		pasemi_mac_free_tx_resources(mac);
+	pasemi_mac_free_rx_resources(mac);
 out_rx_resources:
 
 	return ret;
@@ -1063,20 +1083,21 @@ static int pasemi_mac_close(struct net_d
 		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))
+	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);
+	pasemi_mac_clean_tx(tx_ring(mac));
+	pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
 
 	/* Disable interface */
-	write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), PAS_DMA_TXCHAN_TCMDSTA_ST);
-	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), PAS_DMA_RXINT_RCMDSTA_ST);
-	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), PAS_DMA_RXCHAN_CCMDSTA_ST);
+	write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
+		      PAS_DMA_TXCHAN_TCMDSTA_ST);
+	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
+		      PAS_DMA_RXINT_RCMDSTA_ST);
+	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
+		      PAS_DMA_RXCHAN_CCMDSTA_ST);
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
 		sta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
@@ -1086,7 +1107,8 @@ static int pasemi_mac_close(struct net_d
 	}
 
 	if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)
-		dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
+		dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel %d\n",
+			mac->dma_txch);
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
 		sta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
@@ -1116,12 +1138,12 @@ static int pasemi_mac_close(struct net_d
 	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), 0);
 	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
 
-	free_irq(mac->tx_irq, dev);
-	free_irq(mac->rx_irq, dev);
+	free_irq(mac->tx_irq, mac->tx);
+	free_irq(mac->rx_irq, mac->rx);
 
 	/* Free resources */
-	pasemi_mac_free_rx_resources(dev);
-	pasemi_mac_free_tx_resources(dev);
+	pasemi_mac_free_rx_resources(mac);
+	pasemi_mac_free_tx_resources(mac);
 
 	return 0;
 }
@@ -1178,7 +1200,7 @@ static int pasemi_mac_start_tx(struct sk
 
 	mactx = dflags | XCT_MACTX_LLEN(skb->len);
 
-	txring = mac->tx;
+	txring = tx_ring(mac);
 
 	spin_lock_irqsave(&txring->lock, flags);
 
@@ -1192,13 +1214,13 @@ static int pasemi_mac_start_tx(struct sk
 		goto out_err;
 	}
 
-	TX_RING(mac, txring->next_to_fill) = mactx;
+	TX_DESC(txring, txring->next_to_fill) = mactx;
 	txring->next_to_fill++;
-	TX_RING_INFO(mac, txring->next_to_fill).skb = skb;
+	TX_DESC_INFO(txring, 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];
+		TX_DESC(txring, txring->next_to_fill+i) =
+			XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
+		TX_DESC_INFO(txring, txring->next_to_fill+i).dma = map[i];
 	}
 
 	/* We have to add an even number of 8-byte entries to the ring
@@ -1216,7 +1238,7 @@ static int pasemi_mac_start_tx(struct sk
 
 	spin_unlock_irqrestore(&txring->lock, flags);
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_INCR(mac->dma_txch), (nfrags+2) >> 1);
+	write_dma_reg(mac, PAS_DMA_TXCHAN_INCR(txring->chan), (nfrags+2) >> 1);
 
 	return NETDEV_TX_OK;
 
@@ -1253,8 +1275,8 @@ static int pasemi_mac_poll(struct napi_s
 	struct net_device *dev = mac->netdev;
 	int pkts;
 
-	pasemi_mac_clean_tx(mac);
-	pkts = pasemi_mac_clean_rx(mac, budget);
+	pasemi_mac_clean_tx(tx_ring(mac));
+	pkts = pasemi_mac_clean_rx(rx_ring(mac), budget);
 	if (pkts < budget) {
 		/* all done, no more packets present */
 		netif_rx_complete(dev, napi);
@@ -1405,9 +1427,6 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 	if (err)
 		goto out;
 
-	mac->rx_status = &dma_status->rx_sta[mac->dma_rxch];
-	mac->tx_status = &dma_status->tx_sta[mac->dma_txch];
-
 	mac->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
 	/* Enable most messages by default */
@@ -1420,11 +1439,9 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 			err);
 		goto out;
 	} else if netif_msg_probe(mac)
-		printk(KERN_INFO "%s: PA Semi %s: intf %d, txch %d, rxch %d, "
-		       "hw addr %s\n",
+		printk(KERN_INFO "%s: PA Semi %s: intf %d, hw addr %s\n",
 		       dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",
-		       mac->dma_if, mac->dma_txch, mac->dma_rxch,
-		       print_mac(mac_buf, dev->dev_addr));
+		       mac->dma_if, print_mac(mac_buf, dev->dev_addr));
 
 	return err;
 
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -28,17 +28,20 @@
 
 struct pasemi_mac_txring {
 	spinlock_t	 lock;
+	u64		*status; /* Ptr to cacheable status area */
 	u64		*ring;
 	dma_addr_t	 dma;
 	unsigned int	 size;
 	unsigned int	 next_to_fill;
 	unsigned int	 next_to_clean;
 	struct pasemi_mac_buffer *ring_info;
-	char		 irq_name[10];  /* "eth%d tx" */
+	int		 chan;
+	struct pasemi_mac *mac;	/* Needed in intr handler */
 };
 
 struct pasemi_mac_rxring {
 	spinlock_t	 lock;
+	u64		*status; /* Ptr to cacheable status area */
 	u64		*ring;	/* RX channel descriptor ring */
 	dma_addr_t	 dma;
 	u64		*buffers;	/* RX interface buffer ring */
@@ -47,7 +50,7 @@ struct pasemi_mac_rxring {
 	unsigned int	 next_to_fill;
 	unsigned int	 next_to_clean;
 	struct pasemi_mac_buffer *ring_info;
-	char		 irq_name[10];  /* "eth%d rx" */
+	struct pasemi_mac *mac;	/* Needed in intr handler */
 };
 
 struct pasemi_mac {
@@ -61,16 +64,12 @@ struct pasemi_mac {
 	struct phy_device *phydev;
 	struct napi_struct napi;
 
-	/* Pointer to the cacheable per-channel status registers */
-	u64	*rx_status;
-	u64	*tx_status;
-
 	u8		type;
 #define MAC_TYPE_GMAC	1
 #define MAC_TYPE_XAUI	2
 	u32	dma_txch;
-	u32	dma_if;
 	u32	dma_rxch;
+	u32	dma_if;
 
 	u8		mac_addr[6];
 
@@ -78,8 +77,10 @@ struct pasemi_mac {
 
 	struct pasemi_mac_txring *tx;
 	struct pasemi_mac_rxring *rx;
-	unsigned long	tx_irq;
-	unsigned long	rx_irq;
+	unsigned int	tx_irq;
+	unsigned int	rx_irq;
+	char		tx_irq_name[10];		/* "eth%d tx" */
+	char		rx_irq_name[10];		/* "eth%d rx" */
 	int	link;
 	int	speed;
 	int	duplex;

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [2/12] pasemi_mac: Move register definitions to include/asm-powerpc
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
  2007-11-29  2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
@ 2007-11-29  2:56 ` Olof Johansson
  2007-11-29  2:56 ` [PATCH] [3/12] pasemi: DMA engine management library Olof Johansson
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:56 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: Move register definitions to include/asm-powerpc

Move the common register formats and descriptor layouts from
drivers/net/pasemi_mac.h to include/asm-poewrpc/pasemi_dma.h

Previously only the ethernet driver was using them, but other drivers
are coming up that will also use them, so it makes sense to share the
constants.


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

---
 drivers/net/pasemi_mac.c         |    1 
 drivers/net/pasemi_mac.h         |  336 ---------------------------------
 include/asm-powerpc/pasemi_dma.h |  391 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 394 insertions(+), 334 deletions(-)

Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- /dev/null
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2006 PA Semi, Inc
+ *
+ * Hardware register layout and descriptor formats for the on-board
+ * DMA engine on PA Semi PWRficient. Used by ethernet, function and security
+ * drivers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef ASM_PASEMI_DMA_H
+#define ASM_PASEMI_DMA_H
+
+/* status register layout in IOB region, at 0xfb800000 */
+struct pasdma_status {
+	u64 rx_sta[64];		/* RX channel status */
+	u64 tx_sta[20];		/* TX channel status */
+};
+
+
+/* All these registers live in the PCI configuration space for the DMA PCI
+ * device. Use the normal PCI config access functions for them.
+ */
+enum {
+	PAS_DMA_COM_TXCMD = 0x100,	/* Transmit Command Register  */
+	PAS_DMA_COM_TXSTA = 0x104,	/* Transmit Status Register   */
+	PAS_DMA_COM_RXCMD = 0x108,	/* Receive Command Register   */
+	PAS_DMA_COM_RXSTA = 0x10c,	/* Receive Status Register    */
+};
+#define PAS_DMA_COM_TXCMD_EN	0x00000001 /* enable */
+#define PAS_DMA_COM_TXSTA_ACT	0x00000001 /* active */
+#define PAS_DMA_COM_RXCMD_EN	0x00000001 /* enable */
+#define PAS_DMA_COM_RXSTA_ACT	0x00000001 /* active */
+
+
+/* Per-interface and per-channel registers */
+#define _PAS_DMA_RXINT_STRIDE		0x20
+#define PAS_DMA_RXINT_RCMDSTA(i)	(0x200+(i)*_PAS_DMA_RXINT_STRIDE)
+#define    PAS_DMA_RXINT_RCMDSTA_EN	0x00000001
+#define    PAS_DMA_RXINT_RCMDSTA_ST	0x00000002
+#define    PAS_DMA_RXINT_RCMDSTA_MBT	0x00000008
+#define    PAS_DMA_RXINT_RCMDSTA_MDR	0x00000010
+#define    PAS_DMA_RXINT_RCMDSTA_MOO	0x00000020
+#define    PAS_DMA_RXINT_RCMDSTA_MBP	0x00000040
+#define    PAS_DMA_RXINT_RCMDSTA_BT	0x00000800
+#define    PAS_DMA_RXINT_RCMDSTA_DR	0x00001000
+#define    PAS_DMA_RXINT_RCMDSTA_OO	0x00002000
+#define    PAS_DMA_RXINT_RCMDSTA_BP	0x00004000
+#define    PAS_DMA_RXINT_RCMDSTA_TB	0x00008000
+#define    PAS_DMA_RXINT_RCMDSTA_ACT	0x00010000
+#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_ITR	0x00400000
+#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
+
+#define PAS_DMA_RXINT_INCR(i)		(0x210+(i)*_PAS_DMA_RXINT_STRIDE)
+#define    PAS_DMA_RXINT_INCR_INCR_M	0x0000ffff
+#define    PAS_DMA_RXINT_INCR_INCR_S	0
+#define    PAS_DMA_RXINT_INCR_INCR(x)	((x) & 0x0000ffff)
+#define PAS_DMA_RXINT_BASEL(i)		(0x218+(i)*_PAS_DMA_RXINT_STRIDE)
+#define    PAS_DMA_RXINT_BASEL_BRBL(x)	((x) & ~0x3f)
+#define PAS_DMA_RXINT_BASEU(i)		(0x21c+(i)*_PAS_DMA_RXINT_STRIDE)
+#define    PAS_DMA_RXINT_BASEU_BRBH(x)	((x) & 0xfff)
+#define    PAS_DMA_RXINT_BASEU_SIZ_M	0x3fff0000	/* # of cache lines worth of buffer ring */
+#define    PAS_DMA_RXINT_BASEU_SIZ_S	16		/* 0 = 16K */
+#define    PAS_DMA_RXINT_BASEU_SIZ(x)	(((x) << PAS_DMA_RXINT_BASEU_SIZ_S) & \
+					 PAS_DMA_RXINT_BASEU_SIZ_M)
+
+
+#define _PAS_DMA_TXCHAN_STRIDE	0x20    /* Size per channel		*/
+#define _PAS_DMA_TXCHAN_TCMDSTA	0x300	/* Command / Status		*/
+#define _PAS_DMA_TXCHAN_CFG	0x304	/* Configuration		*/
+#define _PAS_DMA_TXCHAN_DSCRBU	0x308	/* Descriptor BU Allocation	*/
+#define _PAS_DMA_TXCHAN_INCR	0x310	/* Descriptor increment		*/
+#define _PAS_DMA_TXCHAN_CNT	0x314	/* Descriptor count/offset	*/
+#define _PAS_DMA_TXCHAN_BASEL	0x318	/* Descriptor ring base (low)	*/
+#define _PAS_DMA_TXCHAN_BASEU	0x31c	/*			(high)	*/
+#define PAS_DMA_TXCHAN_TCMDSTA(c) (0x300+(c)*_PAS_DMA_TXCHAN_STRIDE)
+#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
+#define    PAS_DMA_TXCHAN_CFG_TATTR_S	2
+#define    PAS_DMA_TXCHAN_CFG_TATTR(x)	(((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
+					 PAS_DMA_TXCHAN_CFG_TATTR_M)
+#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000001c0
+#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_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
+#define    PAS_DMA_TXCHAN_BASEL_BRBL_S	0
+#define    PAS_DMA_TXCHAN_BASEL_BRBL(x)	(((x) << PAS_DMA_TXCHAN_BASEL_BRBL_S) & \
+					 PAS_DMA_TXCHAN_BASEL_BRBL_M)
+#define PAS_DMA_TXCHAN_BASEU(c)   (0x31c+(c)*_PAS_DMA_TXCHAN_STRIDE)
+#define    PAS_DMA_TXCHAN_BASEU_BRBH_M	0x00000fff
+#define    PAS_DMA_TXCHAN_BASEU_BRBH_S	0
+#define    PAS_DMA_TXCHAN_BASEU_BRBH(x)	(((x) << PAS_DMA_TXCHAN_BASEU_BRBH_S) & \
+					 PAS_DMA_TXCHAN_BASEU_BRBH_M)
+/* # of cache lines worth of buffer ring */
+#define    PAS_DMA_TXCHAN_BASEU_SIZ_M	0x3fff0000
+#define    PAS_DMA_TXCHAN_BASEU_SIZ_S	16		/* 0 = 16K */
+#define    PAS_DMA_TXCHAN_BASEU_SIZ(x)	(((x) << PAS_DMA_TXCHAN_BASEU_SIZ_S) & \
+					 PAS_DMA_TXCHAN_BASEU_SIZ_M)
+
+#define _PAS_DMA_RXCHAN_STRIDE	0x20    /* Size per channel		*/
+#define _PAS_DMA_RXCHAN_CCMDSTA	0x800	/* Command / Status		*/
+#define _PAS_DMA_RXCHAN_CFG	0x804	/* Configuration		*/
+#define _PAS_DMA_RXCHAN_INCR	0x810	/* Descriptor increment		*/
+#define _PAS_DMA_RXCHAN_CNT	0x814	/* Descriptor count/offset	*/
+#define _PAS_DMA_RXCHAN_BASEL	0x818	/* Descriptor ring base (low)	*/
+#define _PAS_DMA_RXCHAN_BASEU	0x81c	/*			(high)	*/
+#define PAS_DMA_RXCHAN_CCMDSTA(c) (0x800+(c)*_PAS_DMA_RXCHAN_STRIDE)
+#define    PAS_DMA_RXCHAN_CCMDSTA_EN	0x00000001	/* Enabled */
+#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_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) & \
+					 PAS_DMA_RXCHAN_CFG_HBU_M)
+#define PAS_DMA_RXCHAN_INCR(c)    (0x810+(c)*_PAS_DMA_RXCHAN_STRIDE)
+#define PAS_DMA_RXCHAN_BASEL(c)   (0x818+(c)*_PAS_DMA_RXCHAN_STRIDE)
+#define    PAS_DMA_RXCHAN_BASEL_BRBL_M	0xffffffc0
+#define    PAS_DMA_RXCHAN_BASEL_BRBL_S	0
+#define    PAS_DMA_RXCHAN_BASEL_BRBL(x)	(((x) << PAS_DMA_RXCHAN_BASEL_BRBL_S) & \
+					 PAS_DMA_RXCHAN_BASEL_BRBL_M)
+#define PAS_DMA_RXCHAN_BASEU(c)   (0x81c+(c)*_PAS_DMA_RXCHAN_STRIDE)
+#define    PAS_DMA_RXCHAN_BASEU_BRBH_M	0x00000fff
+#define    PAS_DMA_RXCHAN_BASEU_BRBH_S	0
+#define    PAS_DMA_RXCHAN_BASEU_BRBH(x)	(((x) << PAS_DMA_RXCHAN_BASEU_BRBH_S) & \
+					 PAS_DMA_RXCHAN_BASEU_BRBH_M)
+/* # of cache lines worth of buffer ring */
+#define    PAS_DMA_RXCHAN_BASEU_SIZ_M	0x3fff0000
+#define    PAS_DMA_RXCHAN_BASEU_SIZ_S	16		/* 0 = 16K */
+#define    PAS_DMA_RXCHAN_BASEU_SIZ(x)	(((x) << PAS_DMA_RXCHAN_BASEU_SIZ_S) & \
+					 PAS_DMA_RXCHAN_BASEU_SIZ_M)
+
+#define    PAS_STATUS_PCNT_M		0x000000000000ffffull
+#define    PAS_STATUS_PCNT_S		0
+#define    PAS_STATUS_DCNT_M		0x00000000ffff0000ull
+#define    PAS_STATUS_DCNT_S		16
+#define    PAS_STATUS_BPCNT_M		0x0000ffff00000000ull
+#define    PAS_STATUS_BPCNT_S		32
+#define    PAS_STATUS_CAUSE_M		0xf000000000000000ull
+#define    PAS_STATUS_TIMER		0x1000000000000000ull
+#define    PAS_STATUS_ERROR		0x2000000000000000ull
+#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
+#define    PAS_IOB_DMA_RXCH_CFG_CNTTH(x)	(((x) << PAS_IOB_DMA_RXCH_CFG_CNTTH_S) & \
+						 PAS_IOB_DMA_RXCH_CFG_CNTTH_M)
+#define PAS_IOB_DMA_TXCH_CFG(i)		(0x1200 + (i)*4)
+#define    PAS_IOB_DMA_TXCH_CFG_CNTTH_M		0x00000fff
+#define    PAS_IOB_DMA_TXCH_CFG_CNTTH_S		0
+#define    PAS_IOB_DMA_TXCH_CFG_CNTTH(x)	(((x) << PAS_IOB_DMA_TXCH_CFG_CNTTH_S) & \
+						 PAS_IOB_DMA_TXCH_CFG_CNTTH_M)
+#define PAS_IOB_DMA_RXCH_STAT(i)	(0x1300 + (i)*4)
+#define    PAS_IOB_DMA_RXCH_STAT_INTGEN	0x00001000
+#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL_M	0x00000fff
+#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL_S	0
+#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL(x)	(((x) << PAS_IOB_DMA_RXCH_STAT_CNTDEL_S) &\
+						 PAS_IOB_DMA_RXCH_STAT_CNTDEL_M)
+#define PAS_IOB_DMA_TXCH_STAT(i)	(0x1400 + (i)*4)
+#define    PAS_IOB_DMA_TXCH_STAT_INTGEN	0x00001000
+#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL_M	0x00000fff
+#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL_S	0
+#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL(x)	(((x) << PAS_IOB_DMA_TXCH_STAT_CNTDEL_S) &\
+						 PAS_IOB_DMA_TXCH_STAT_CNTDEL_M)
+#define PAS_IOB_DMA_RXCH_RESET(i)	(0x1500 + (i)*4)
+#define    PAS_IOB_DMA_RXCH_RESET_PCNT_M	0xffff0000
+#define    PAS_IOB_DMA_RXCH_RESET_PCNT_S	16
+#define    PAS_IOB_DMA_RXCH_RESET_PCNT(x)	(((x) << PAS_IOB_DMA_RXCH_RESET_PCNT_S) & \
+						 PAS_IOB_DMA_RXCH_RESET_PCNT_M)
+#define    PAS_IOB_DMA_RXCH_RESET_PCNTRST	0x00000020
+#define    PAS_IOB_DMA_RXCH_RESET_DCNTRST	0x00000010
+#define    PAS_IOB_DMA_RXCH_RESET_TINTC		0x00000008
+#define    PAS_IOB_DMA_RXCH_RESET_DINTC		0x00000004
+#define    PAS_IOB_DMA_RXCH_RESET_SINTC		0x00000002
+#define    PAS_IOB_DMA_RXCH_RESET_PINTC		0x00000001
+#define PAS_IOB_DMA_TXCH_RESET(i)	(0x1600 + (i)*4)
+#define    PAS_IOB_DMA_TXCH_RESET_PCNT_M	0xffff0000
+#define    PAS_IOB_DMA_TXCH_RESET_PCNT_S	16
+#define    PAS_IOB_DMA_TXCH_RESET_PCNT(x)	(((x) << PAS_IOB_DMA_TXCH_RESET_PCNT_S) & \
+						 PAS_IOB_DMA_TXCH_RESET_PCNT_M)
+#define    PAS_IOB_DMA_TXCH_RESET_PCNTRST	0x00000020
+#define    PAS_IOB_DMA_TXCH_RESET_DCNTRST	0x00000010
+#define    PAS_IOB_DMA_TXCH_RESET_TINTC		0x00000008
+#define    PAS_IOB_DMA_TXCH_RESET_DINTC		0x00000004
+#define    PAS_IOB_DMA_TXCH_RESET_SINTC		0x00000002
+#define    PAS_IOB_DMA_TXCH_RESET_PINTC		0x00000001
+
+#define PAS_IOB_DMA_COM_TIMEOUTCFG		0x1700
+#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M	0x00ffffff
+#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S	0
+#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(x)	(((x) << PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S) & \
+						 PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M)
+
+/* Transmit descriptor fields */
+#define	XCT_MACTX_T		0x8000000000000000ull
+#define	XCT_MACTX_ST		0x4000000000000000ull
+#define XCT_MACTX_NORES		0x0000000000000000ull
+#define XCT_MACTX_8BRES		0x1000000000000000ull
+#define XCT_MACTX_24BRES	0x2000000000000000ull
+#define XCT_MACTX_40BRES	0x3000000000000000ull
+#define XCT_MACTX_I		0x0800000000000000ull
+#define XCT_MACTX_O		0x0400000000000000ull
+#define XCT_MACTX_E		0x0200000000000000ull
+#define XCT_MACTX_VLAN_M	0x0180000000000000ull
+#define XCT_MACTX_VLAN_NOP	0x0000000000000000ull
+#define XCT_MACTX_VLAN_REMOVE	0x0080000000000000ull
+#define XCT_MACTX_VLAN_INSERT   0x0100000000000000ull
+#define XCT_MACTX_VLAN_REPLACE  0x0180000000000000ull
+#define XCT_MACTX_CRC_M		0x0060000000000000ull
+#define XCT_MACTX_CRC_NOP	0x0000000000000000ull
+#define XCT_MACTX_CRC_INSERT	0x0020000000000000ull
+#define XCT_MACTX_CRC_PAD	0x0040000000000000ull
+#define XCT_MACTX_CRC_REPLACE	0x0060000000000000ull
+#define XCT_MACTX_SS		0x0010000000000000ull
+#define XCT_MACTX_LLEN_M	0x00007fff00000000ull
+#define XCT_MACTX_LLEN_S	32ull
+#define XCT_MACTX_LLEN(x)	((((long)(x)) << XCT_MACTX_LLEN_S) & \
+				 XCT_MACTX_LLEN_M)
+#define XCT_MACTX_IPH_M		0x00000000f8000000ull
+#define XCT_MACTX_IPH_S		27ull
+#define XCT_MACTX_IPH(x)	((((long)(x)) << XCT_MACTX_IPH_S) & \
+				 XCT_MACTX_IPH_M)
+#define XCT_MACTX_IPO_M		0x0000000007c00000ull
+#define XCT_MACTX_IPO_S		22ull
+#define XCT_MACTX_IPO(x)	((((long)(x)) << XCT_MACTX_IPO_S) & \
+				 XCT_MACTX_IPO_M)
+#define XCT_MACTX_CSUM_M	0x0000000000000060ull
+#define XCT_MACTX_CSUM_NOP	0x0000000000000000ull
+#define XCT_MACTX_CSUM_TCP	0x0000000000000040ull
+#define XCT_MACTX_CSUM_UDP	0x0000000000000060ull
+#define XCT_MACTX_V6		0x0000000000000010ull
+#define XCT_MACTX_C		0x0000000000000004ull
+#define XCT_MACTX_AL2		0x0000000000000002ull
+
+/* Receive descriptor fields */
+#define	XCT_MACRX_T		0x8000000000000000ull
+#define	XCT_MACRX_ST		0x4000000000000000ull
+#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
+#define XCT_MACRX_PF		0x0080000000000000ull
+#define XCT_MACRX_OB		0x0040000000000000ull
+#define XCT_MACRX_OD		0x0020000000000000ull
+#define XCT_MACRX_FS		0x0010000000000000ull
+#define XCT_MACRX_NB_M		0x000fc00000000000ull
+#define XCT_MACRX_NB_S		46ULL
+#define XCT_MACRX_NB(x)		((((long)(x)) << XCT_MACRX_NB_S) & \
+				 XCT_MACRX_NB_M)
+#define XCT_MACRX_LLEN_M	0x00003fff00000000ull
+#define XCT_MACRX_LLEN_S	32ULL
+#define XCT_MACRX_LLEN(x)	((((long)(x)) << XCT_MACRX_LLEN_S) & \
+				 XCT_MACRX_LLEN_M)
+#define XCT_MACRX_CRC		0x0000000080000000ull
+#define XCT_MACRX_LEN_M		0x0000000060000000ull
+#define XCT_MACRX_LEN_TOOSHORT	0x0000000020000000ull
+#define XCT_MACRX_LEN_BELOWMIN	0x0000000040000000ull
+#define XCT_MACRX_LEN_TRUNC	0x0000000060000000ull
+#define XCT_MACRX_CAST_M	0x0000000018000000ull
+#define XCT_MACRX_CAST_UNI	0x0000000000000000ull
+#define XCT_MACRX_CAST_MULTI	0x0000000008000000ull
+#define XCT_MACRX_CAST_BROAD	0x0000000010000000ull
+#define XCT_MACRX_CAST_PAUSE	0x0000000018000000ull
+#define XCT_MACRX_VLC_M		0x0000000006000000ull
+#define XCT_MACRX_FM		0x0000000001000000ull
+#define XCT_MACRX_HTY_M		0x0000000000c00000ull
+#define XCT_MACRX_HTY_IPV4_OK	0x0000000000000000ull
+#define XCT_MACRX_HTY_IPV6 	0x0000000000400000ull
+#define XCT_MACRX_HTY_IPV4_BAD	0x0000000000800000ull
+#define XCT_MACRX_HTY_NONIP	0x0000000000c00000ull
+#define XCT_MACRX_IPP_M		0x00000000003f0000ull
+#define XCT_MACRX_IPP_S		16
+#define XCT_MACRX_CSUM_M	0x000000000000ffffull
+#define XCT_MACRX_CSUM_S	0
+
+#define XCT_PTR_T		0x8000000000000000ull
+#define XCT_PTR_LEN_M		0x7ffff00000000000ull
+#define XCT_PTR_LEN_S		44
+#define XCT_PTR_LEN(x)		((((long)(x)) << XCT_PTR_LEN_S) & \
+				 XCT_PTR_LEN_M)
+#define XCT_PTR_ADDR_M		0x00000fffffffffffull
+#define XCT_PTR_ADDR_S		0
+#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
+#define XCT_RXB_LEN(x)		((((long)(x)) << XCT_RXB_LEN_S) & \
+				 XCT_RXB_LEN_M)
+#define XCT_RXB_ADDR_M		0x00000fffffffffffull
+#define XCT_RXB_ADDR_S		0
+#define XCT_RXB_ADDR(x)		((((long)(x)) << XCT_RXB_ADDR_S) & \
+				 XCT_RXB_ADDR_M)
+
+/* Copy descriptor fields */
+#define XCT_COPY_T		0x8000000000000000ull
+#define XCT_COPY_ST		0x4000000000000000ull
+#define XCT_COPY_RR_M		0x3000000000000000ull
+#define XCT_COPY_RR_NORES	0x0000000000000000ull
+#define XCT_COPY_RR_8BRES	0x1000000000000000ull
+#define XCT_COPY_RR_24BRES	0x2000000000000000ull
+#define XCT_COPY_RR_40BRES	0x3000000000000000ull
+#define XCT_COPY_I		0x0800000000000000ull
+#define XCT_COPY_O		0x0400000000000000ull
+#define XCT_COPY_E		0x0200000000000000ull
+#define XCT_COPY_STY_ZERO	0x01c0000000000000ull
+#define XCT_COPY_DTY_PREF	0x0038000000000000ull
+#define XCT_COPY_LLEN_M		0x0007ffff00000000ull
+#define XCT_COPY_LLEN_S		32
+#define XCT_COPY_LLEN(x)	((((long)(x)) << XCT_COPY_LLEN_S) & \
+				 XCT_COPY_LLEN_M)
+#define XCT_COPY_SE		0x0000000000000001ull
+
+/* Control descriptor fields */
+#define CTRL_CMD_T		0x8000000000000000ull
+#define CTRL_CMD_META_EVT	0x2000000000000000ull
+#define CTRL_CMD_O		0x0400000000000000ull
+#define CTRL_CMD_REG_M		0x000000000000000full
+#define CTRL_CMD_REG_S		0
+#define CTRL_CMD_REG(x)		((((long)(x)) << CTRL_CMD_REG_S) & \
+				 CTRL_CMD_REG_M)
+
+
+#endif /* ASM_PASEMI_DMA_H */
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -35,6 +35,7 @@
 
 #include <asm/irq.h>
 #include <asm/firmware.h>
+#include <asm/pasemi_dma.h>
 
 #include "pasemi_mac.h"
 
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -96,11 +96,8 @@ struct pasemi_mac_buffer {
 };
 
 
-/* status register layout in IOB region, at 0xfb800000 */
-struct pasdma_status {
-	u64 rx_sta[64];
-	u64 tx_sta[20];
-};
+/* PCI register offsets and formats */
+
 
 /* MAC CFG register offsets */
 enum {
@@ -174,333 +171,4 @@ enum {
 #define PAS_MAC_IPC_CHNL_BCH(x)		(((x) << PAS_MAC_IPC_CHNL_BCH_S) & \
 					 PAS_MAC_IPC_CHNL_BCH_M)
 
-/* All these registers live in the PCI configuration space for the DMA PCI
- * device. Use the normal PCI config access functions for them.
- */
-enum {
-	PAS_DMA_COM_TXCMD = 0x100,	/* Transmit Command Register  */
-	PAS_DMA_COM_TXSTA = 0x104,	/* Transmit Status Register   */
-	PAS_DMA_COM_RXCMD = 0x108,	/* Receive Command Register   */
-	PAS_DMA_COM_RXSTA = 0x10c,	/* Receive Status Register    */
-};
-#define PAS_DMA_COM_TXCMD_EN	0x00000001 /* enable */
-#define PAS_DMA_COM_TXSTA_ACT	0x00000001 /* active */
-#define PAS_DMA_COM_RXCMD_EN	0x00000001 /* enable */
-#define PAS_DMA_COM_RXSTA_ACT	0x00000001 /* active */
-
-
-/* Per-interface and per-channel registers */
-#define _PAS_DMA_RXINT_STRIDE		0x20
-#define PAS_DMA_RXINT_RCMDSTA(i)	(0x200+(i)*_PAS_DMA_RXINT_STRIDE)
-#define    PAS_DMA_RXINT_RCMDSTA_EN	0x00000001
-#define    PAS_DMA_RXINT_RCMDSTA_ST	0x00000002
-#define    PAS_DMA_RXINT_RCMDSTA_MBT	0x00000008
-#define    PAS_DMA_RXINT_RCMDSTA_MDR	0x00000010
-#define    PAS_DMA_RXINT_RCMDSTA_MOO	0x00000020
-#define    PAS_DMA_RXINT_RCMDSTA_MBP	0x00000040
-#define    PAS_DMA_RXINT_RCMDSTA_BT	0x00000800
-#define    PAS_DMA_RXINT_RCMDSTA_DR	0x00001000
-#define    PAS_DMA_RXINT_RCMDSTA_OO	0x00002000
-#define    PAS_DMA_RXINT_RCMDSTA_BP	0x00004000
-#define    PAS_DMA_RXINT_RCMDSTA_TB	0x00008000
-#define    PAS_DMA_RXINT_RCMDSTA_ACT	0x00010000
-#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_ITR	0x00400000
-#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
-
-#define PAS_DMA_RXINT_INCR(i)		(0x210+(i)*_PAS_DMA_RXINT_STRIDE)
-#define    PAS_DMA_RXINT_INCR_INCR_M	0x0000ffff
-#define    PAS_DMA_RXINT_INCR_INCR_S	0
-#define    PAS_DMA_RXINT_INCR_INCR(x)	((x) & 0x0000ffff)
-#define PAS_DMA_RXINT_BASEL(i)		(0x218+(i)*_PAS_DMA_RXINT_STRIDE)
-#define    PAS_DMA_RXINT_BASEL_BRBL(x)	((x) & ~0x3f)
-#define PAS_DMA_RXINT_BASEU(i)		(0x21c+(i)*_PAS_DMA_RXINT_STRIDE)
-#define    PAS_DMA_RXINT_BASEU_BRBH(x)	((x) & 0xfff)
-#define    PAS_DMA_RXINT_BASEU_SIZ_M	0x3fff0000	/* # of cache lines worth of buffer ring */
-#define    PAS_DMA_RXINT_BASEU_SIZ_S	16		/* 0 = 16K */
-#define    PAS_DMA_RXINT_BASEU_SIZ(x)	(((x) << PAS_DMA_RXINT_BASEU_SIZ_S) & \
-					 PAS_DMA_RXINT_BASEU_SIZ_M)
-
-
-#define _PAS_DMA_TXCHAN_STRIDE	0x20    /* Size per channel		*/
-#define _PAS_DMA_TXCHAN_TCMDSTA	0x300	/* Command / Status		*/
-#define _PAS_DMA_TXCHAN_CFG	0x304	/* Configuration		*/
-#define _PAS_DMA_TXCHAN_DSCRBU	0x308	/* Descriptor BU Allocation	*/
-#define _PAS_DMA_TXCHAN_INCR	0x310	/* Descriptor increment		*/
-#define _PAS_DMA_TXCHAN_CNT	0x314	/* Descriptor count/offset	*/
-#define _PAS_DMA_TXCHAN_BASEL	0x318	/* Descriptor ring base (low)	*/
-#define _PAS_DMA_TXCHAN_BASEU	0x31c	/*			(high)	*/
-#define PAS_DMA_TXCHAN_TCMDSTA(c) (0x300+(c)*_PAS_DMA_TXCHAN_STRIDE)
-#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
-#define    PAS_DMA_TXCHAN_CFG_TATTR_S	2
-#define    PAS_DMA_TXCHAN_CFG_TATTR(x)	(((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
-					 PAS_DMA_TXCHAN_CFG_TATTR_M)
-#define    PAS_DMA_TXCHAN_CFG_WT_M	0x000001c0
-#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_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
-#define    PAS_DMA_TXCHAN_BASEL_BRBL_S	0
-#define    PAS_DMA_TXCHAN_BASEL_BRBL(x)	(((x) << PAS_DMA_TXCHAN_BASEL_BRBL_S) & \
-					 PAS_DMA_TXCHAN_BASEL_BRBL_M)
-#define PAS_DMA_TXCHAN_BASEU(c)   (0x31c+(c)*_PAS_DMA_TXCHAN_STRIDE)
-#define    PAS_DMA_TXCHAN_BASEU_BRBH_M	0x00000fff
-#define    PAS_DMA_TXCHAN_BASEU_BRBH_S	0
-#define    PAS_DMA_TXCHAN_BASEU_BRBH(x)	(((x) << PAS_DMA_TXCHAN_BASEU_BRBH_S) & \
-					 PAS_DMA_TXCHAN_BASEU_BRBH_M)
-/* # of cache lines worth of buffer ring */
-#define    PAS_DMA_TXCHAN_BASEU_SIZ_M	0x3fff0000
-#define    PAS_DMA_TXCHAN_BASEU_SIZ_S	16		/* 0 = 16K */
-#define    PAS_DMA_TXCHAN_BASEU_SIZ(x)	(((x) << PAS_DMA_TXCHAN_BASEU_SIZ_S) & \
-					 PAS_DMA_TXCHAN_BASEU_SIZ_M)
-
-#define _PAS_DMA_RXCHAN_STRIDE	0x20    /* Size per channel		*/
-#define _PAS_DMA_RXCHAN_CCMDSTA	0x800	/* Command / Status		*/
-#define _PAS_DMA_RXCHAN_CFG	0x804	/* Configuration		*/
-#define _PAS_DMA_RXCHAN_INCR	0x810	/* Descriptor increment		*/
-#define _PAS_DMA_RXCHAN_CNT	0x814	/* Descriptor count/offset	*/
-#define _PAS_DMA_RXCHAN_BASEL	0x818	/* Descriptor ring base (low)	*/
-#define _PAS_DMA_RXCHAN_BASEU	0x81c	/*			(high)	*/
-#define PAS_DMA_RXCHAN_CCMDSTA(c) (0x800+(c)*_PAS_DMA_RXCHAN_STRIDE)
-#define    PAS_DMA_RXCHAN_CCMDSTA_EN	0x00000001	/* Enabled */
-#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_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) & \
-					 PAS_DMA_RXCHAN_CFG_HBU_M)
-#define PAS_DMA_RXCHAN_INCR(c)    (0x810+(c)*_PAS_DMA_RXCHAN_STRIDE)
-#define PAS_DMA_RXCHAN_BASEL(c)   (0x818+(c)*_PAS_DMA_RXCHAN_STRIDE)
-#define    PAS_DMA_RXCHAN_BASEL_BRBL_M	0xffffffc0
-#define    PAS_DMA_RXCHAN_BASEL_BRBL_S	0
-#define    PAS_DMA_RXCHAN_BASEL_BRBL(x)	(((x) << PAS_DMA_RXCHAN_BASEL_BRBL_S) & \
-					 PAS_DMA_RXCHAN_BASEL_BRBL_M)
-#define PAS_DMA_RXCHAN_BASEU(c)   (0x81c+(c)*_PAS_DMA_RXCHAN_STRIDE)
-#define    PAS_DMA_RXCHAN_BASEU_BRBH_M	0x00000fff
-#define    PAS_DMA_RXCHAN_BASEU_BRBH_S	0
-#define    PAS_DMA_RXCHAN_BASEU_BRBH(x)	(((x) << PAS_DMA_RXCHAN_BASEU_BRBH_S) & \
-					 PAS_DMA_RXCHAN_BASEU_BRBH_M)
-/* # of cache lines worth of buffer ring */
-#define    PAS_DMA_RXCHAN_BASEU_SIZ_M	0x3fff0000
-#define    PAS_DMA_RXCHAN_BASEU_SIZ_S	16		/* 0 = 16K */
-#define    PAS_DMA_RXCHAN_BASEU_SIZ(x)	(((x) << PAS_DMA_RXCHAN_BASEU_SIZ_S) & \
-					 PAS_DMA_RXCHAN_BASEU_SIZ_M)
-
-#define    PAS_STATUS_PCNT_M		0x000000000000ffffull
-#define    PAS_STATUS_PCNT_S		0
-#define    PAS_STATUS_DCNT_M		0x00000000ffff0000ull
-#define    PAS_STATUS_DCNT_S		16
-#define    PAS_STATUS_BPCNT_M		0x0000ffff00000000ull
-#define    PAS_STATUS_BPCNT_S		32
-#define    PAS_STATUS_CAUSE_M		0xf000000000000000ull
-#define    PAS_STATUS_TIMER		0x1000000000000000ull
-#define    PAS_STATUS_ERROR		0x2000000000000000ull
-#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
-#define    PAS_IOB_DMA_RXCH_CFG_CNTTH(x)	(((x) << PAS_IOB_DMA_RXCH_CFG_CNTTH_S) & \
-						 PAS_IOB_DMA_RXCH_CFG_CNTTH_M)
-#define PAS_IOB_DMA_TXCH_CFG(i)		(0x1200 + (i)*4)
-#define    PAS_IOB_DMA_TXCH_CFG_CNTTH_M		0x00000fff
-#define    PAS_IOB_DMA_TXCH_CFG_CNTTH_S		0
-#define    PAS_IOB_DMA_TXCH_CFG_CNTTH(x)	(((x) << PAS_IOB_DMA_TXCH_CFG_CNTTH_S) & \
-						 PAS_IOB_DMA_TXCH_CFG_CNTTH_M)
-#define PAS_IOB_DMA_RXCH_STAT(i)	(0x1300 + (i)*4)
-#define    PAS_IOB_DMA_RXCH_STAT_INTGEN	0x00001000
-#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL_M	0x00000fff
-#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL_S	0
-#define    PAS_IOB_DMA_RXCH_STAT_CNTDEL(x)	(((x) << PAS_IOB_DMA_RXCH_STAT_CNTDEL_S) &\
-						 PAS_IOB_DMA_RXCH_STAT_CNTDEL_M)
-#define PAS_IOB_DMA_TXCH_STAT(i)	(0x1400 + (i)*4)
-#define    PAS_IOB_DMA_TXCH_STAT_INTGEN	0x00001000
-#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL_M	0x00000fff
-#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL_S	0
-#define    PAS_IOB_DMA_TXCH_STAT_CNTDEL(x)	(((x) << PAS_IOB_DMA_TXCH_STAT_CNTDEL_S) &\
-						 PAS_IOB_DMA_TXCH_STAT_CNTDEL_M)
-#define PAS_IOB_DMA_RXCH_RESET(i)	(0x1500 + (i)*4)
-#define    PAS_IOB_DMA_RXCH_RESET_PCNT_M	0xffff0000
-#define    PAS_IOB_DMA_RXCH_RESET_PCNT_S	16
-#define    PAS_IOB_DMA_RXCH_RESET_PCNT(x)	(((x) << PAS_IOB_DMA_RXCH_RESET_PCNT_S) & \
-						 PAS_IOB_DMA_RXCH_RESET_PCNT_M)
-#define    PAS_IOB_DMA_RXCH_RESET_PCNTRST	0x00000020
-#define    PAS_IOB_DMA_RXCH_RESET_DCNTRST	0x00000010
-#define    PAS_IOB_DMA_RXCH_RESET_TINTC		0x00000008
-#define    PAS_IOB_DMA_RXCH_RESET_DINTC		0x00000004
-#define    PAS_IOB_DMA_RXCH_RESET_SINTC		0x00000002
-#define    PAS_IOB_DMA_RXCH_RESET_PINTC		0x00000001
-#define PAS_IOB_DMA_TXCH_RESET(i)	(0x1600 + (i)*4)
-#define    PAS_IOB_DMA_TXCH_RESET_PCNT_M	0xffff0000
-#define    PAS_IOB_DMA_TXCH_RESET_PCNT_S	16
-#define    PAS_IOB_DMA_TXCH_RESET_PCNT(x)	(((x) << PAS_IOB_DMA_TXCH_RESET_PCNT_S) & \
-						 PAS_IOB_DMA_TXCH_RESET_PCNT_M)
-#define    PAS_IOB_DMA_TXCH_RESET_PCNTRST	0x00000020
-#define    PAS_IOB_DMA_TXCH_RESET_DCNTRST	0x00000010
-#define    PAS_IOB_DMA_TXCH_RESET_TINTC		0x00000008
-#define    PAS_IOB_DMA_TXCH_RESET_DINTC		0x00000004
-#define    PAS_IOB_DMA_TXCH_RESET_SINTC		0x00000002
-#define    PAS_IOB_DMA_TXCH_RESET_PINTC		0x00000001
-
-#define PAS_IOB_DMA_COM_TIMEOUTCFG		0x1700
-#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M	0x00ffffff
-#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S	0
-#define    PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(x)	(((x) << PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S) & \
-						 PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M)
-
-/* Transmit descriptor fields */
-#define	XCT_MACTX_T		0x8000000000000000ull
-#define	XCT_MACTX_ST		0x4000000000000000ull
-#define XCT_MACTX_NORES		0x0000000000000000ull
-#define XCT_MACTX_8BRES		0x1000000000000000ull
-#define XCT_MACTX_24BRES	0x2000000000000000ull
-#define XCT_MACTX_40BRES	0x3000000000000000ull
-#define XCT_MACTX_I		0x0800000000000000ull
-#define XCT_MACTX_O		0x0400000000000000ull
-#define XCT_MACTX_E		0x0200000000000000ull
-#define XCT_MACTX_VLAN_M	0x0180000000000000ull
-#define XCT_MACTX_VLAN_NOP	0x0000000000000000ull
-#define XCT_MACTX_VLAN_REMOVE	0x0080000000000000ull
-#define XCT_MACTX_VLAN_INSERT   0x0100000000000000ull
-#define XCT_MACTX_VLAN_REPLACE  0x0180000000000000ull
-#define XCT_MACTX_CRC_M		0x0060000000000000ull
-#define XCT_MACTX_CRC_NOP	0x0000000000000000ull
-#define XCT_MACTX_CRC_INSERT	0x0020000000000000ull
-#define XCT_MACTX_CRC_PAD	0x0040000000000000ull
-#define XCT_MACTX_CRC_REPLACE	0x0060000000000000ull
-#define XCT_MACTX_SS		0x0010000000000000ull
-#define XCT_MACTX_LLEN_M	0x00007fff00000000ull
-#define XCT_MACTX_LLEN_S	32ull
-#define XCT_MACTX_LLEN(x)	((((long)(x)) << XCT_MACTX_LLEN_S) & \
-				 XCT_MACTX_LLEN_M)
-#define XCT_MACTX_IPH_M		0x00000000f8000000ull
-#define XCT_MACTX_IPH_S		27ull
-#define XCT_MACTX_IPH(x)	((((long)(x)) << XCT_MACTX_IPH_S) & \
-				 XCT_MACTX_IPH_M)
-#define XCT_MACTX_IPO_M		0x0000000007c00000ull
-#define XCT_MACTX_IPO_S		22ull
-#define XCT_MACTX_IPO(x)	((((long)(x)) << XCT_MACTX_IPO_S) & \
-				 XCT_MACTX_IPO_M)
-#define XCT_MACTX_CSUM_M	0x0000000000000060ull
-#define XCT_MACTX_CSUM_NOP	0x0000000000000000ull
-#define XCT_MACTX_CSUM_TCP	0x0000000000000040ull
-#define XCT_MACTX_CSUM_UDP	0x0000000000000060ull
-#define XCT_MACTX_V6		0x0000000000000010ull
-#define XCT_MACTX_C		0x0000000000000004ull
-#define XCT_MACTX_AL2		0x0000000000000002ull
-
-/* Receive descriptor fields */
-#define	XCT_MACRX_T		0x8000000000000000ull
-#define	XCT_MACRX_ST		0x4000000000000000ull
-#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
-#define XCT_MACRX_PF		0x0080000000000000ull
-#define XCT_MACRX_OB		0x0040000000000000ull
-#define XCT_MACRX_OD		0x0020000000000000ull
-#define XCT_MACRX_FS		0x0010000000000000ull
-#define XCT_MACRX_NB_M		0x000fc00000000000ull
-#define XCT_MACRX_NB_S		46ULL
-#define XCT_MACRX_NB(x)		((((long)(x)) << XCT_MACRX_NB_S) & \
-				 XCT_MACRX_NB_M)
-#define XCT_MACRX_LLEN_M	0x00003fff00000000ull
-#define XCT_MACRX_LLEN_S	32ULL
-#define XCT_MACRX_LLEN(x)	((((long)(x)) << XCT_MACRX_LLEN_S) & \
-				 XCT_MACRX_LLEN_M)
-#define XCT_MACRX_CRC		0x0000000080000000ull
-#define XCT_MACRX_LEN_M		0x0000000060000000ull
-#define XCT_MACRX_LEN_TOOSHORT	0x0000000020000000ull
-#define XCT_MACRX_LEN_BELOWMIN	0x0000000040000000ull
-#define XCT_MACRX_LEN_TRUNC	0x0000000060000000ull
-#define XCT_MACRX_CAST_M	0x0000000018000000ull
-#define XCT_MACRX_CAST_UNI	0x0000000000000000ull
-#define XCT_MACRX_CAST_MULTI	0x0000000008000000ull
-#define XCT_MACRX_CAST_BROAD	0x0000000010000000ull
-#define XCT_MACRX_CAST_PAUSE	0x0000000018000000ull
-#define XCT_MACRX_VLC_M		0x0000000006000000ull
-#define XCT_MACRX_FM		0x0000000001000000ull
-#define XCT_MACRX_HTY_M		0x0000000000c00000ull
-#define XCT_MACRX_HTY_IPV4_OK	0x0000000000000000ull
-#define XCT_MACRX_HTY_IPV6 	0x0000000000400000ull
-#define XCT_MACRX_HTY_IPV4_BAD	0x0000000000800000ull
-#define XCT_MACRX_HTY_NONIP	0x0000000000c00000ull
-#define XCT_MACRX_IPP_M		0x00000000003f0000ull
-#define XCT_MACRX_IPP_S		16
-#define XCT_MACRX_CSUM_M	0x000000000000ffffull
-#define XCT_MACRX_CSUM_S	0
-
-#define XCT_PTR_T		0x8000000000000000ull
-#define XCT_PTR_LEN_M		0x7ffff00000000000ull
-#define XCT_PTR_LEN_S		44
-#define XCT_PTR_LEN(x)		((((long)(x)) << XCT_PTR_LEN_S) & \
-				 XCT_PTR_LEN_M)
-#define XCT_PTR_ADDR_M		0x00000fffffffffffull
-#define XCT_PTR_ADDR_S		0
-#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
-#define XCT_RXB_LEN(x)		((((long)(x)) << XCT_PTR_LEN_S) & XCT_PTR_LEN_M)
-#define XCT_RXB_ADDR_M		0x00000fffffffffffull
-#define XCT_RXB_ADDR_S		0
-#define XCT_RXB_ADDR(x)		((((long)(x)) << XCT_PTR_ADDR_S) & XCT_PTR_ADDR_M)
-
-
 #endif /* PASEMI_MAC_H */

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [3/12] pasemi: DMA engine management library
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
  2007-11-29  2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
  2007-11-29  2:56 ` [PATCH] [2/12] pasemi_mac: Move register definitions to include/asm-powerpc Olof Johansson
@ 2007-11-29  2:56 ` Olof Johansson
  2007-11-29  2:56 ` [PATCH] [4/12] pasemi_mac: Convert to new dma library Olof Johansson
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:56 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi: DMA engine management library

Introduce a DMA management library to manage the various DMA resources
on the PA Semi SoCs. Since several drivers need to allocate these shared
resources, provide some abstractions as well as allocation/free functions
for channels, etc.


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

---
 arch/powerpc/platforms/pasemi/Makefile  |    2 
 arch/powerpc/platforms/pasemi/dma_lib.c |  487 ++++++++++++++++++++++++++++++++
 arch/powerpc/platforms/pasemi/pasemi.h  |    1 
 include/asm-powerpc/pasemi_dma.h        |   76 ++++
 4 files changed, 565 insertions(+), 1 deletion(-)

Index: k.org/arch/powerpc/platforms/pasemi/Makefile
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/Makefile
+++ k.org/arch/powerpc/platforms/pasemi/Makefile
@@ -1,4 +1,4 @@
-obj-y	+= setup.o pci.o time.o idle.o powersave.o iommu.o
+obj-y	+= setup.o pci.o time.o idle.o powersave.o iommu.o dma_lib.o
 obj-$(CONFIG_PPC_PASEMI_MDIO)	+= gpio_mdio.o
 obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
 obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
Index: k.org/arch/powerpc/platforms/pasemi/dma_lib.c
===================================================================
--- /dev/null
+++ k.org/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * Common functions for DMA access on PA Semi PWRficient
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/of.h>
+
+#include <asm/pasemi_dma.h>
+
+#define MAX_TXCH 64
+#define MAX_RXCH 64
+
+static struct pasdma_status *dma_status;
+
+static void __iomem *iob_regs;
+static void __iomem *mac_regs[6];
+static void __iomem *dma_regs;
+
+static int base_hw_irq;
+
+static int num_txch, num_rxch;
+
+static struct pci_dev *dma_pdev;
+
+/* Bitmaps to handle allocation of channels */
+
+static DECLARE_BITMAP(txch_free, MAX_TXCH);
+static DECLARE_BITMAP(rxch_free, MAX_RXCH);
+
+/* pasemi_read_iob_reg - read IOB register
+ * @reg: Register to read (offset into PCI CFG space)
+ */
+unsigned int pasemi_read_iob_reg(unsigned int reg)
+{
+	return in_le32(iob_regs+reg);
+}
+EXPORT_SYMBOL(pasemi_read_iob_reg);
+
+/* pasemi_write_iob_reg - write IOB register
+ * @reg: Register to write to (offset into PCI CFG space)
+ * @val: Value to write
+ */
+void pasemi_write_iob_reg(unsigned int reg, unsigned int val)
+{
+	out_le32(iob_regs+reg, val);
+}
+EXPORT_SYMBOL(pasemi_write_iob_reg);
+
+/* pasemi_read_mac_reg - read MAC register
+ * @intf: MAC interface
+ * @reg: Register to read (offset into PCI CFG space)
+ */
+unsigned int pasemi_read_mac_reg(int intf, unsigned int reg)
+{
+	return in_le32(mac_regs[intf]+reg);
+}
+EXPORT_SYMBOL(pasemi_read_mac_reg);
+
+/* pasemi_write_mac_reg - write MAC register
+ * @intf: MAC interface
+ * @reg: Register to write to (offset into PCI CFG space)
+ * @val: Value to write
+ */
+void pasemi_write_mac_reg(int intf, unsigned int reg, unsigned int val)
+{
+	out_le32(mac_regs[intf]+reg, val);
+}
+EXPORT_SYMBOL(pasemi_write_mac_reg);
+
+/* pasemi_read_dma_reg - read DMA register
+ * @reg: Register to read (offset into PCI CFG space)
+ */
+unsigned int pasemi_read_dma_reg(unsigned int reg)
+{
+	return in_le32(dma_regs+reg);
+}
+EXPORT_SYMBOL(pasemi_read_dma_reg);
+
+/* pasemi_write_dma_reg - write DMA register
+ * @reg: Register to write to (offset into PCI CFG space)
+ * @val: Value to write
+ */
+void pasemi_write_dma_reg(unsigned int reg, unsigned int val)
+{
+	out_le32(dma_regs+reg, val);
+}
+EXPORT_SYMBOL(pasemi_write_dma_reg);
+
+static int pasemi_alloc_tx_chan(enum pasemi_dmachan_type type)
+{
+	int bit;
+	int start, limit;
+
+	switch (type & (TXCHAN_EVT0|TXCHAN_EVT1)) {
+	case TXCHAN_EVT0:
+		start = 0;
+		limit = 10;
+		break;
+	case TXCHAN_EVT1:
+		start = 10;
+		limit = MAX_TXCH;
+		break;
+	default:
+		start = 0;
+		limit = MAX_TXCH;
+		break;
+	}
+retry:
+	bit = find_next_bit(txch_free, MAX_TXCH, start);
+	if (bit >= limit)
+		return -ENOSPC;
+	if (!test_and_clear_bit(bit, txch_free))
+		goto retry;
+
+	return bit;
+}
+
+static void pasemi_free_tx_chan(int chan)
+{
+	BUG_ON(test_bit(chan, txch_free));
+	set_bit(chan, txch_free);
+}
+
+static int pasemi_alloc_rx_chan(void)
+{
+	int bit;
+retry:
+	bit = find_first_bit(rxch_free, MAX_RXCH);
+	if (bit >= MAX_TXCH)
+		return -ENOSPC;
+	if (!test_and_clear_bit(bit, rxch_free))
+		goto retry;
+
+	return bit;
+}
+
+static void pasemi_free_rx_chan(int chan)
+{
+	BUG_ON(test_bit(chan, rxch_free));
+	set_bit(chan, rxch_free);
+}
+
+/* pasemi_dma_alloc_chan - Allocate a DMA channel
+ * @type: Type of channel to allocate
+ * @total_size: Total size of structure to allocate (to allow for more
+ *		room behind the structure to be used by the client)
+ * @offset: Offset in bytes from start of the total structure to the beginning
+ *	    of struct pasemi_dmachan. Needed when struct pasemi_dmachan is
+ *	    not the first member of the client structure.
+ *
+ * pasemi_dma_alloc_chan allocates a DMA channel for use by a client. The
+ * type argument specifies whether it's a RX or TX channel, and in the case
+ * of TX channels which group it needs to belong to (if any).
+ *
+ * Returns a pointer to the total structure allocated on success, NULL
+ * on failure.
+ */
+void *pasemi_dma_alloc_chan(enum pasemi_dmachan_type type,
+			    int total_size, int offset)
+{
+	void *buf;
+	struct pasemi_dmachan *chan;
+	int chno;
+
+	BUG_ON(total_size < sizeof(struct pasemi_dmachan));
+
+	buf = kzalloc(total_size, GFP_KERNEL);
+
+	if (!buf)
+		return NULL;
+	chan = buf + offset;
+
+	chan->priv = buf;
+
+	switch (type & (TXCHAN|RXCHAN)) {
+	case RXCHAN:
+		chno = pasemi_alloc_rx_chan();
+		chan->chno = chno;
+		chan->irq = irq_create_mapping(NULL,
+					       base_hw_irq + num_txch + chno);
+		chan->status = &dma_status->rx_sta[chno];
+		break;
+	case TXCHAN:
+		chno = pasemi_alloc_tx_chan(type);
+		chan->chno = chno;
+		chan->irq = irq_create_mapping(NULL, base_hw_irq + chno);
+		chan->status = &dma_status->tx_sta[chno];
+		break;
+	}
+
+	chan->chan_type = type;
+
+	return chan;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_chan);
+
+/* pasemi_dma_free_chan - Free a previously allocated channel
+ * @chan: Channel to free
+ *
+ * Frees a previously allocated channel. It will also deallocate any
+ * descriptor ring associated with the channel, if allocated.
+ */
+void pasemi_dma_free_chan(struct pasemi_dmachan *chan)
+{
+	if (chan->ring_virt)
+		pasemi_dma_free_ring(chan);
+
+	switch (chan->chan_type & (RXCHAN|TXCHAN)) {
+	case RXCHAN:
+		pasemi_free_rx_chan(chan->chno);
+		break;
+	case TXCHAN:
+		pasemi_free_tx_chan(chan->chno);
+		break;
+	}
+
+	kfree(chan->priv);
+}
+EXPORT_SYMBOL(pasemi_dma_free_chan);
+
+/* pasemi_dma_alloc_ring - Allocate descriptor ring for a channel
+ * @chan: Channel for which to allocate
+ * @ring_size: Ring size in 64-bit (8-byte) words
+ *
+ * Allocate a descriptor ring for a channel. Returns 0 on success, errno
+ * on failure. The passed in struct pasemi_dmachan is updated with the
+ * virtual and DMA addresses of the ring.
+ */
+int pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size)
+{
+	BUG_ON(chan->ring_virt);
+
+	chan->ring_size = ring_size;
+
+	chan->ring_virt = dma_alloc_coherent(&dma_pdev->dev,
+					     ring_size * sizeof(u64),
+					     &chan->ring_dma, GFP_KERNEL);
+
+	if (!chan->ring_virt)
+		return -ENOMEM;
+
+	memset(chan->ring_virt, 0, ring_size * sizeof(u64));
+
+	return 0;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_ring);
+
+/* pasemi_dma_free_ring - Free an allocated descriptor ring for a channel
+ * @chan: Channel for which to free the descriptor ring
+ *
+ * Frees a previously allocated descriptor ring for a channel.
+ */
+void pasemi_dma_free_ring(struct pasemi_dmachan *chan)
+{
+	BUG_ON(!chan->ring_virt);
+
+	dma_free_coherent(&dma_pdev->dev, chan->ring_size * sizeof(u64),
+			  chan->ring_virt, chan->ring_dma);
+	chan->ring_virt = NULL;
+	chan->ring_size = 0;
+	chan->ring_dma = 0;
+}
+EXPORT_SYMBOL(pasemi_dma_free_ring);
+
+/* pasemi_dma_start_chan - Start a DMA channel
+ * @chan: Channel to start
+ * @cmdsta: Additional CCMDSTA/TCMDSTA bits to write
+ *
+ * Enables (starts) a DMA channel with optional additional arguments.
+ */
+void pasemi_dma_start_chan(const struct pasemi_dmachan *chan, const u32 cmdsta)
+{
+	if (chan->chan_type == RXCHAN)
+		pasemi_write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno),
+				     cmdsta | PAS_DMA_RXCHAN_CCMDSTA_EN);
+	else
+		pasemi_write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno),
+				     cmdsta | PAS_DMA_TXCHAN_TCMDSTA_EN);
+}
+EXPORT_SYMBOL(pasemi_dma_start_chan);
+
+/* pasemi_dma_stop_chan - Stop a DMA channel
+ * @chan: Channel to stop
+ *
+ * Stops (disables) a DMA channel. This is done by setting the ST bit in the
+ * CMDSTA register and waiting on the ACT (active) bit to clear, then
+ * finally disabling the whole channel.
+ *
+ * This function will only try for a short while for the channel to stop, if
+ * it doesn't it will return failure.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+#define MAX_RETRIES 5000
+int pasemi_dma_stop_chan(const struct pasemi_dmachan *chan)
+{
+	int reg, retries;
+	u32 sta;
+
+	if (chan->chan_type == RXCHAN) {
+		reg = PAS_DMA_RXCHAN_CCMDSTA(chan->chno);
+		pasemi_write_dma_reg(reg, PAS_DMA_RXCHAN_CCMDSTA_ST);
+		for (retries = 0; retries < MAX_RETRIES; retries++) {
+			sta = pasemi_read_dma_reg(reg);
+			if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)) {
+				pasemi_write_dma_reg(reg, 0);
+				return 1;
+			}
+			cond_resched();
+		}
+	} else {
+		reg = PAS_DMA_TXCHAN_TCMDSTA(chan->chno);
+		pasemi_write_dma_reg(reg, PAS_DMA_TXCHAN_TCMDSTA_ST);
+		for (retries = 0; retries < MAX_RETRIES; retries++) {
+			sta = pasemi_read_dma_reg(reg);
+			if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)) {
+				pasemi_write_dma_reg(reg, 0);
+				return 1;
+			}
+			cond_resched();
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(pasemi_dma_stop_chan);
+
+/* pasemi_dma_alloc_buf - Allocate a buffer to use for DMA
+ * @chan: Channel to allocate for
+ * @size: Size of buffer in bytes
+ * @handle: DMA handle
+ *
+ * Allocate a buffer to be used by the DMA engine for read/write,
+ * similar to dma_alloc_coherent().
+ *
+ * Returns the virtual address of the buffer, or NULL in case of failure.
+ */
+void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
+			   dma_addr_t *handle)
+{
+	return dma_alloc_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_buf);
+
+/* pasemi_dma_free_buf - Free a buffer used for DMA
+ * @chan: Channel the buffer was allocated for
+ * @size: Size of buffer in bytes
+ * @handle: DMA handle
+ *
+ * Frees a previously allocated buffer.
+ */
+void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
+			 dma_addr_t *handle)
+{
+	dma_free_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
+}
+EXPORT_SYMBOL(pasemi_dma_free_buf);
+
+static void *map_onedev(struct pci_dev *p, int index)
+{
+	struct device_node *dn;
+	void __iomem *ret;
+
+	dn = pci_device_to_OF_node(p);
+	if (!dn)
+		goto fallback;
+
+	ret = of_iomap(dn, index);
+	if (!ret)
+		goto fallback;
+
+	return ret;
+fallback:
+	/* This is hardcoded and ugly, but we have some firmware versions
+	 * that don't provide the register space in the device tree. Luckily
+	 * they are at well-known locations so we can just do the math here.
+	 */
+	return ioremap(0xe0000000 + (p->devfn << 12), 0x2000);
+}
+
+/* pasemi_dma_init - Initialize the PA Semi DMA library
+ *
+ * This function initializes the DMA library. It must be called before
+ * any other function in the library.
+ *
+ * Returns 0 on success, errno on failure.
+ */
+int pasemi_dma_init(void)
+{
+	static spinlock_t init_lock = SPIN_LOCK_UNLOCKED;
+	struct pci_dev *iob_pdev;
+	struct pci_dev *pdev;
+	struct resource res;
+	struct device_node *dn;
+	int i, intf, err = 0;
+	u32 tmp;
+
+	if (!machine_is(pasemi))
+		return -ENODEV;
+
+	spin_lock(&init_lock);
+
+	/* Make sure we haven't already initialized */
+	if (dma_pdev)
+		goto out;
+
+	iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
+	if (!iob_pdev) {
+		BUG();
+		printk(KERN_WARNING "Can't find I/O Bridge\n");
+		err = -ENODEV;
+		goto out;
+	}
+	iob_regs = map_onedev(iob_pdev, 0);
+
+	dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
+	if (!dma_pdev) {
+		BUG();
+		printk(KERN_WARNING "Can't find DMA controller\n");
+		err = -ENODEV;
+		goto out;
+	}
+	dma_regs = map_onedev(dma_pdev, 0);
+	base_hw_irq = virq_to_hw(dma_pdev->irq);
+
+	pci_read_config_dword(dma_pdev, PAS_DMA_CAP_TXCH, &tmp);
+	num_txch = (tmp & PAS_DMA_CAP_TXCH_TCHN_M) >> PAS_DMA_CAP_TXCH_TCHN_S;
+
+	pci_read_config_dword(dma_pdev, PAS_DMA_CAP_RXCH, &tmp);
+	num_rxch = (tmp & PAS_DMA_CAP_RXCH_RCHN_M) >> PAS_DMA_CAP_RXCH_RCHN_S;
+
+	intf = 0;
+	for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, NULL);
+	     pdev;
+	     pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, pdev))
+		mac_regs[intf++] = map_onedev(pdev, 0);
+
+	pci_dev_put(pdev);
+
+	for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, NULL);
+	     pdev;
+	     pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, pdev))
+		mac_regs[intf++] = map_onedev(pdev, 0);
+
+	pci_dev_put(pdev);
+
+	dn = pci_device_to_OF_node(iob_pdev);
+	if (dn)
+		err = of_address_to_resource(dn, 1, &res);
+	if (!dn || err) {
+		/* Fallback for old firmware */
+		res.start = 0xfd800000;
+		res.end = res.start + 0x1000;
+	}
+	dma_status = __ioremap(res.start, res.end-res.start, 0);
+	pci_dev_put(iob_pdev);
+
+	for (i = 0; i < MAX_TXCH; i++)
+		__set_bit(i, txch_free);
+
+	for (i = 0; i < MAX_RXCH; i++)
+		__set_bit(i, rxch_free);
+
+	printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
+		"(%d tx, %d rx channels)\n", num_txch, num_rxch);
+
+out:
+	spin_unlock(&init_lock);
+	return err;
+}
Index: k.org/arch/powerpc/platforms/pasemi/pasemi.h
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/pasemi.h
+++ k.org/arch/powerpc/platforms/pasemi/pasemi.h
@@ -9,6 +9,7 @@ extern void __devinit pas_pci_dma_dev_se
 extern void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset);
 
 extern void __init alloc_iobmap_l2(void);
+extern void __init pasemi_map_registers(void);
 
 /* Power savings modes, implemented in asm */
 extern void idle_spin(void);
Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- k.org.orig/include/asm-powerpc/pasemi_dma.h
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -33,11 +33,27 @@ struct pasdma_status {
  * device. Use the normal PCI config access functions for them.
  */
 enum {
+	PAS_DMA_CAP_TXCH  = 0x44,	/* Transmit Channel Info      */
+	PAS_DMA_CAP_RXCH  = 0x48,	/* Transmit Channel Info      */
+	PAS_DMA_CAP_IFI	  = 0x4c,	/* Interface Info	      */
 	PAS_DMA_COM_TXCMD = 0x100,	/* Transmit Command Register  */
 	PAS_DMA_COM_TXSTA = 0x104,	/* Transmit Status Register   */
 	PAS_DMA_COM_RXCMD = 0x108,	/* Receive Command Register   */
 	PAS_DMA_COM_RXSTA = 0x10c,	/* Receive Status Register    */
 };
+
+
+#define PAS_DMA_CAP_TXCH_TCHN_M	0x00ff0000 /* # of TX channels */
+#define PAS_DMA_CAP_TXCH_TCHN_S	16
+
+#define PAS_DMA_CAP_RXCH_RCHN_M	0x00ff0000 /* # of RX channels */
+#define PAS_DMA_CAP_RXCH_RCHN_S	16
+
+#define PAS_DMA_CAP_IFI_IOFF_M	0xff000000 /* Cfg reg for intf pointers */
+#define PAS_DMA_CAP_IFI_IOFF_S	24
+#define PAS_DMA_CAP_IFI_NIN_M	0x00ff0000 /* # of interfaces */
+#define PAS_DMA_CAP_IFI_NIN_S	16
+
 #define PAS_DMA_COM_TXCMD_EN	0x00000001 /* enable */
 #define PAS_DMA_COM_TXSTA_ACT	0x00000001 /* active */
 #define PAS_DMA_COM_RXCMD_EN	0x00000001 /* enable */
@@ -388,4 +404,64 @@ enum {
 				 CTRL_CMD_REG_M)
 
 
+
+/* Prototypes for the shared DMA functions in the platform code. */
+
+/* DMA TX Channel type. Right now only limitations used are event types 0/1,
+ * for event-triggered DMA transactions.
+ */
+
+enum pasemi_dmachan_type {
+	RXCHAN = 0,		/* Any RX chan */
+	TXCHAN = 1,		/* Any TX chan */
+	TXCHAN_EVT0 = 0x1001,	/* TX chan in event class 0 (chan 0-9) */
+	TXCHAN_EVT1 = 0x2001,	/* TX chan in event class 1 (chan 10-19) */
+};
+
+struct pasemi_dmachan {
+	int		 chno;		/* Channel number */
+	enum pasemi_dmachan_type chan_type;	/* TX / RX */
+	u64		*status;	/* Ptr to cacheable status */
+	int		 irq;		/* IRQ used by channel */
+	unsigned int	 ring_size;	/* size of allocated ring */
+	dma_addr_t	 ring_dma;	/* DMA address for ring */
+	u64		*ring_virt;	/* Virt address for ring */
+	void		*priv;		/* Ptr to start of client struct */
+};
+
+/* Read/write the different registers in the I/O Bridge, Ethernet
+ * and DMA Controller
+ */
+extern unsigned int pasemi_read_iob_reg(unsigned int reg);
+extern void pasemi_write_iob_reg(unsigned int reg, unsigned int val);
+
+extern unsigned int pasemi_read_mac_reg(int intf, unsigned int reg);
+extern void pasemi_write_mac_reg(int intf, unsigned int reg, unsigned int val);
+
+extern unsigned int pasemi_read_dma_reg(unsigned int reg);
+extern void pasemi_write_dma_reg(unsigned int reg, unsigned int val);
+
+/* Channel management routines */
+
+extern void *pasemi_dma_alloc_chan(enum pasemi_dmachan_type type,
+				   int total_size, int offset);
+extern void pasemi_dma_free_chan(struct pasemi_dmachan *chan);
+
+extern void pasemi_dma_start_chan(const struct pasemi_dmachan *chan,
+				  const u32 cmdsta);
+extern int pasemi_dma_stop_chan(const struct pasemi_dmachan *chan);
+
+/* Common routines to allocate rings and buffers */
+
+extern int pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size);
+extern void pasemi_dma_free_ring(struct pasemi_dmachan *chan);
+
+extern void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
+				  dma_addr_t *handle);
+extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
+				dma_addr_t *handle);
+
+/* Initialize the library, must be called before any other functions */
+extern int pasemi_dma_init(void);
+
 #endif /* ASM_PASEMI_DMA_H */

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [4/12] pasemi_mac: Convert to new dma library
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (2 preceding siblings ...)
  2007-11-29  2:56 ` [PATCH] [3/12] pasemi: DMA engine management library Olof Johansson
@ 2007-11-29  2:56 ` Olof Johansson
  2007-11-29  2:56 ` [PATCH] [5/12] pasemi_mac: performance tweaks Olof Johansson
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:56 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: Convert to new dma library

Convert the pasemi_mac driver to the new platform global DMA manaagement
library. This also does a couple of other minor cleanups w.r.t. channel
management.

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

---
 drivers/net/pasemi_mac.c |  480 ++++++++++++++++++++---------------------------
 drivers/net/pasemi_mac.h |   16 -
 2 files changed, 210 insertions(+), 286 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -69,9 +69,9 @@
 	 NETIF_MSG_RX_ERR	| \
 	 NETIF_MSG_TX_ERR)
 
-#define TX_DESC(tx, num)	((tx)->ring[(num) & (TX_RING_SIZE-1)])
+#define TX_DESC(tx, num)	((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
 #define TX_DESC_INFO(tx, num)	((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
-#define RX_DESC(rx, num)	((rx)->ring[(num) & (RX_RING_SIZE-1)])
+#define RX_DESC(rx, num)	((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
 #define RX_DESC_INFO(rx, num)	((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
 #define RX_BUFF(rx, num)	((rx)->buffers[(num) & (RX_RING_SIZE-1)])
 
@@ -89,8 +89,6 @@ static int debug = -1;	/* -1 == use DEFA
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
 
-static struct pasdma_status *dma_status;
-
 static int translation_enabled(void)
 {
 #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
@@ -100,32 +98,30 @@ static int translation_enabled(void)
 #endif
 }
 
-static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg,
-			  unsigned int val)
+static void write_iob_reg(unsigned int reg, unsigned int val)
 {
-	out_le32(mac->iob_regs+reg, val);
+	pasemi_write_iob_reg(reg, val);
 }
 
 static unsigned int read_mac_reg(struct pasemi_mac *mac, unsigned int reg)
 {
-	return in_le32(mac->regs+reg);
+	return pasemi_read_mac_reg(mac->dma_if, reg);
 }
 
 static void write_mac_reg(struct pasemi_mac *mac, unsigned int reg,
 			  unsigned int val)
 {
-	out_le32(mac->regs+reg, val);
+	pasemi_write_mac_reg(mac->dma_if, reg, val);
 }
 
-static unsigned int read_dma_reg(struct pasemi_mac *mac, unsigned int reg)
+static unsigned int read_dma_reg(unsigned int reg)
 {
-	return in_le32(mac->dma_regs+reg);
+	return pasemi_read_dma_reg(reg);
 }
 
-static void write_dma_reg(struct pasemi_mac *mac, unsigned int reg,
-			  unsigned int val)
+static void write_dma_reg(unsigned int reg, unsigned int val)
 {
-	out_le32(mac->dma_regs+reg, val);
+	pasemi_write_dma_reg(reg, val);
 }
 
 static struct pasemi_mac_rxring *rx_ring(struct pasemi_mac *mac)
@@ -138,6 +134,34 @@ static struct pasemi_mac_txring *tx_ring
 	return mac->tx;
 }
 
+static int mac_to_intf(struct pasemi_mac *mac)
+{
+	struct pci_dev *pdev = mac->pdev;
+	u32 tmp;
+	int nintf, off, i, j;
+	int devfn = pdev->devfn;
+
+	tmp = read_dma_reg(PAS_DMA_CAP_IFI);
+	nintf = (tmp & PAS_DMA_CAP_IFI_NIN_M) >> PAS_DMA_CAP_IFI_NIN_S;
+	off = (tmp & PAS_DMA_CAP_IFI_IOFF_M) >> PAS_DMA_CAP_IFI_IOFF_S;
+
+	/* IOFF contains the offset to the registers containing the
+	 * DMA interface-to-MAC-pci-id mappings, and NIN contains number
+	 * of total interfaces. Each register contains 4 devfns.
+	 * Just do a linear search until we find the devfn of the MAC
+	 * we're trying to look up.
+	 */
+
+	for (i = 0; i < (nintf+3)/4; i++) {
+		tmp = read_dma_reg(off+4*i);
+		for (j = 0; j < 4; j++) {
+			if (((tmp >> (8*j)) & 0xff) == devfn)
+				return i*4 + j;
+		}
+	}
+	return -1;
+}
+
 static int pasemi_get_mac_addr(struct pasemi_mac *mac)
 {
 	struct pci_dev *pdev = mac->pdev;
@@ -213,13 +237,17 @@ 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;
+	int chno;
 	unsigned int cfg;
 
-	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+	ring = pasemi_dma_alloc_chan(RXCHAN, sizeof(struct pasemi_mac_rxring),
+				     offsetof(struct pasemi_mac_rxring, chan));
 
-	if (!ring)
-		goto out_ring;
+	if (!ring) {
+		dev_err(&mac->pdev->dev, "Can't allocate RX channel\n");
+		goto out_chan;
+	}
+	chno = ring->chan.chno;
 
 	spin_lock_init(&ring->lock);
 
@@ -231,84 +259,80 @@ static int pasemi_mac_setup_rx_resources
 		goto out_ring_info;
 
 	/* Allocate descriptors */
-	ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
-					RX_RING_SIZE * sizeof(u64),
-					&ring->dma, GFP_KERNEL);
-
-	if (!ring->ring)
+	if (pasemi_dma_alloc_ring(&ring->chan, RX_RING_SIZE))
 		goto out_ring_desc;
 
-	memset(ring->ring, 0, RX_RING_SIZE * sizeof(u64));
-
 	ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
 					   RX_RING_SIZE * sizeof(u64),
 					   &ring->buf_dma, GFP_KERNEL);
 	if (!ring->buffers)
-		goto out_buffers;
+		goto out_ring_desc;
 
 	memset(ring->buffers, 0, RX_RING_SIZE * sizeof(u64));
 
-	write_dma_reg(mac, PAS_DMA_RXCHAN_BASEL(chan_id), PAS_DMA_RXCHAN_BASEL_BRBL(ring->dma));
+	write_dma_reg(PAS_DMA_RXCHAN_BASEL(chno),
+		      PAS_DMA_RXCHAN_BASEL_BRBL(ring->chan.ring_dma));
 
-	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 >> 3));
+	write_dma_reg(PAS_DMA_RXCHAN_BASEU(chno),
+		      PAS_DMA_RXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32) |
+		      PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-	cfg = PAS_DMA_RXCHAN_CFG_HBU(2);
+	cfg = PAS_DMA_RXCHAN_CFG_HBU(1);
 
 	if (translation_enabled())
 		cfg |= PAS_DMA_RXCHAN_CFG_CTR;
 
-	write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id), cfg);
+	write_dma_reg(PAS_DMA_RXCHAN_CFG(chno), cfg);
 
-	write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if),
-			   PAS_DMA_RXINT_BASEL_BRBL(ring->buf_dma));
+	write_dma_reg(PAS_DMA_RXINT_BASEL(mac->dma_if),
+		      PAS_DMA_RXINT_BASEL_BRBL(ring->buf_dma));
 
-	write_dma_reg(mac, PAS_DMA_RXINT_BASEU(mac->dma_if),
-			   PAS_DMA_RXINT_BASEU_BRBH(ring->buf_dma >> 32) |
-			   PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
+	write_dma_reg(PAS_DMA_RXINT_BASEU(mac->dma_if),
+		      PAS_DMA_RXINT_BASEU_BRBH(ring->buf_dma >> 32) |
+		      PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-	cfg = PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 |
+	cfg = PAS_DMA_RXINT_CFG_DHL(1) | 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);
+	write_dma_reg(PAS_DMA_RXINT_CFG(mac->dma_if), cfg);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
-
-	ring->status = &dma_status->rx_sta[mac->dma_rxch];
 	ring->mac = mac;
 	mac->rx = ring;
 
 	return 0;
 
-out_buffers:
-	dma_free_coherent(&mac->dma_pdev->dev,
-			  RX_RING_SIZE * sizeof(u64),
-			  rx_ring(mac)->ring, rx_ring(mac)->dma);
 out_ring_desc:
 	kfree(ring->ring_info);
 out_ring_info:
-	kfree(ring);
-out_ring:
+	pasemi_dma_free_chan(&ring->chan);
+out_chan:
 	return -ENOMEM;
 }
 
 static struct pasemi_mac_txring *
-pasemi_mac_setup_tx_resources(struct net_device *dev, int txch)
+pasemi_mac_setup_tx_resources(struct net_device *dev)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	u32 val;
 	struct pasemi_mac_txring *ring;
 	unsigned int cfg;
+	int chno;
 
-	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
-	if (!ring)
-		goto out_ring;
+	ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_txring),
+				     offsetof(struct pasemi_mac_txring, chan));
+
+	if (!ring) {
+		dev_err(&mac->pdev->dev, "Can't allocate TX channel\n");
+		goto out_chan;
+	}
+
+	chno = ring->chan.chno;
 
 	spin_lock_init(&ring->lock);
 
@@ -319,20 +343,15 @@ pasemi_mac_setup_tx_resources(struct net
 		goto out_ring_info;
 
 	/* Allocate descriptors */
-	ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
-					TX_RING_SIZE * sizeof(u64),
-					&ring->dma, GFP_KERNEL);
-	if (!ring->ring)
+	if (pasemi_dma_alloc_ring(&ring->chan, TX_RING_SIZE))
 		goto out_ring_desc;
 
-	memset(ring->ring, 0, TX_RING_SIZE * sizeof(u64));
-
-	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEL(txch),
-			   PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma));
-	val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->dma >> 32);
+	write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno),
+		      PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma));
+	val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32);
 	val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 3);
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(txch), val);
+	write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val);
 
 	cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
 	      PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
@@ -342,12 +361,10 @@ pasemi_mac_setup_tx_resources(struct net
 	if (translation_enabled())
 		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(txch), cfg);
+	write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
-	ring->status = &dma_status->tx_sta[txch];
-	ring->chan = txch;
 	ring->mac = mac;
 
 	return ring;
@@ -355,8 +372,8 @@ pasemi_mac_setup_tx_resources(struct net
 out_ring_desc:
 	kfree(ring->ring_info);
 out_ring_info:
-	kfree(ring);
-out_ring:
+	pasemi_dma_free_chan(&ring->chan);
+out_chan:
 	return NULL;
 }
 
@@ -387,15 +404,9 @@ static void pasemi_mac_free_tx_resources
 			freed = 2;
 	}
 
-	for (i = 0; i < TX_RING_SIZE; i++)
-		txring->ring[i] = 0;
-
-	dma_free_coherent(&mac->dma_pdev->dev,
-			  TX_RING_SIZE * sizeof(u64),
-			  txring->ring, txring->dma);
-
 	kfree(txring->ring_info);
-	kfree(txring);
+	pasemi_dma_free_chan(&txring->chan);
+
 }
 
 static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
@@ -420,15 +431,11 @@ static void pasemi_mac_free_rx_resources
 	for (i = 0; i < RX_RING_SIZE; i++)
 		RX_DESC(rx, i) = 0;
 
-	dma_free_coherent(&mac->dma_pdev->dev,
-			  RX_RING_SIZE * sizeof(u64),
-			  rx_ring(mac)->ring, rx_ring(mac)->dma);
-
 	dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
 			  rx_ring(mac)->buffers, rx_ring(mac)->buf_dma);
 
 	kfree(rx_ring(mac)->ring_info);
-	kfree(rx_ring(mac));
+	pasemi_dma_free_chan(&rx_ring(mac)->chan);
 	mac->rx = NULL;
 }
 
@@ -479,7 +486,7 @@ static void pasemi_mac_replenish_rx_ring
 
 	wmb();
 
-	write_dma_reg(mac, PAS_DMA_RXINT_INCR(mac->dma_if), count);
+	write_dma_reg(PAS_DMA_RXINT_INCR(mac->dma_if), count);
 
 	rx_ring(mac)->next_to_fill = (rx_ring(mac)->next_to_fill + count) &
 				(RX_RING_SIZE - 1);
@@ -492,11 +499,11 @@ static void pasemi_mac_restart_rx_intr(s
 	 * ack the packet count interrupt we got in rx_intr.
 	 */
 
-	pcnt = *rx_ring(mac)->status & PAS_STATUS_PCNT_M;
+	pcnt = *rx_ring(mac)->chan.status & PAS_STATUS_PCNT_M;
 
 	reg = PAS_IOB_DMA_RXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_RXCH_RESET_PINTC;
 
-	write_iob_reg(mac, PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
+	write_iob_reg(PAS_IOB_DMA_RXCH_RESET(mac->rx->chan.chno), reg);
 }
 
 static void pasemi_mac_restart_tx_intr(struct pasemi_mac *mac)
@@ -504,26 +511,27 @@ static void pasemi_mac_restart_tx_intr(s
 	unsigned int reg, pcnt;
 
 	/* Re-enable packet count interrupts */
-	pcnt = *tx_ring(mac)->status & PAS_STATUS_PCNT_M;
+	pcnt = *tx_ring(mac)->chan.status & PAS_STATUS_PCNT_M;
 
 	reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
 
-	write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(tx_ring(mac)->chan), reg);
+	write_iob_reg(PAS_IOB_DMA_TXCH_RESET(tx_ring(mac)->chan.chno), reg);
 }
 
 
 static inline void pasemi_mac_rx_error(struct pasemi_mac *mac, u64 macrx)
 {
 	unsigned int rcmdsta, ccmdsta;
+	struct pasemi_dmachan *chan = &rx_ring(mac)->chan;
 
 	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));
+	rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+	ccmdsta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno));
 
 	printk(KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n",
-		macrx, *rx_ring(mac)->status);
+		macrx, *chan->status);
 
 	printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n",
 		rcmdsta, ccmdsta);
@@ -532,20 +540,22 @@ static inline void pasemi_mac_rx_error(s
 static inline void pasemi_mac_tx_error(struct pasemi_mac *mac, u64 mactx)
 {
 	unsigned int cmdsta;
+	struct pasemi_dmachan *chan = &tx_ring(mac)->chan;
 
 	if (!netif_msg_tx_err(mac))
 		return;
 
-	cmdsta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
+	cmdsta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno));
 
 	printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, "\
-		"tx status 0x%016lx\n", mactx, *tx_ring(mac)->status);
+		"tx status 0x%016lx\n", mactx, *chan->status);
 
 	printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta);
 }
 
 static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx, int limit)
 {
+	struct pasemi_dmachan *chan = &rx->chan;
 	struct pasemi_mac *mac = rx->mac;
 	unsigned int n;
 	int count;
@@ -567,7 +577,7 @@ static int pasemi_mac_clean_rx(struct pa
 		macrx = RX_DESC(rx, n);
 
 		if ((macrx & XCT_MACRX_E) ||
-		    (*rx_ring(mac)->status & PAS_STATUS_ERROR))
+		    (*chan->status & PAS_STATUS_ERROR))
 			pasemi_mac_rx_error(mac, macrx);
 
 		if (!(macrx & XCT_MACRX_O))
@@ -648,7 +658,7 @@ next:
 
 	if (n > RX_RING_SIZE) {
 		/* Errata 5971 workaround: L2 target of headers */
-		write_iob_reg(mac, PAS_IOB_COM_PKTHDRCNT, 0);
+		write_iob_reg(PAS_IOB_COM_PKTHDRCNT, 0);
 		n &= (RX_RING_SIZE-1);
 	}
 
@@ -658,7 +668,7 @@ next:
 	 * 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);
+	write_dma_reg(PAS_DMA_RXCHAN_INCR(mac->rx->chan.chno), count << 1);
 
 	pasemi_mac_replenish_rx_ring(mac->netdev, count);
 
@@ -672,6 +682,7 @@ next:
 
 static int pasemi_mac_clean_tx(struct pasemi_mac_txring *txring)
 {
+	struct pasemi_dmachan *chan = &txring->chan;
 	struct pasemi_mac *mac = txring->mac;
 	int i, j;
 	unsigned int start, descr_count, buf_count, batch_limit;
@@ -703,7 +714,7 @@ restart:
 		struct sk_buff *skb;
 
 		if ((mactx  & XCT_MACTX_E) ||
-		    (*tx_ring(mac)->status & PAS_STATUS_ERROR))
+		    (*chan->status & PAS_STATUS_ERROR))
 			pasemi_mac_tx_error(mac, mactx);
 
 		if (unlikely(mactx & XCT_MACTX_O))
@@ -747,11 +758,13 @@ restart:
 
 static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
 {
-	struct net_device *dev = data;
-	struct pasemi_mac *mac = netdev_priv(dev);
+	struct pasemi_mac_rxring *rxring = data;
+	struct pasemi_mac *mac = rxring->mac;
+	struct net_device *dev = mac->netdev;
+	struct pasemi_dmachan *chan = &rxring->chan;
 	unsigned int reg;
 
-	if (!(*rx_ring(mac)->status & PAS_STATUS_CAUSE_M))
+	if (!(*chan->status & PAS_STATUS_CAUSE_M))
 		return IRQ_NONE;
 
 	/* Don't reset packet count so it won't fire again but clear
@@ -759,16 +772,16 @@ static irqreturn_t pasemi_mac_rx_intr(in
 	 */
 
 	reg = 0;
-	if (*rx_ring(mac)->status & PAS_STATUS_SOFT)
+	if (*chan->status & PAS_STATUS_SOFT)
 		reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
-	if (*rx_ring(mac)->status & PAS_STATUS_ERROR)
+	if (*chan->status & PAS_STATUS_ERROR)
 		reg |= PAS_IOB_DMA_RXCH_RESET_DINTC;
-	if (*rx_ring(mac)->status & PAS_STATUS_TIMER)
+	if (*chan->status & PAS_STATUS_TIMER)
 		reg |= PAS_IOB_DMA_RXCH_RESET_TINTC;
 
 	netif_rx_schedule(dev, &mac->napi);
 
-	write_iob_reg(mac, PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
+	write_iob_reg(PAS_IOB_DMA_RXCH_RESET(chan->chno), reg);
 
 	return IRQ_HANDLED;
 }
@@ -776,24 +789,24 @@ static irqreturn_t pasemi_mac_rx_intr(in
 static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
 {
 	struct pasemi_mac_txring *txring = data;
-	struct pasemi_mac *mac = txring->mac;
+	struct pasemi_dmachan *chan = &txring->chan;
 	unsigned int reg, pcnt;
 
-	if (!(*txring->status & PAS_STATUS_CAUSE_M))
+	if (!(*chan->status & PAS_STATUS_CAUSE_M))
 		return IRQ_NONE;
 
 	pasemi_mac_clean_tx(txring);
 
-	pcnt = *txring->status & PAS_STATUS_PCNT_M;
+	pcnt = *chan->status & PAS_STATUS_PCNT_M;
 
 	reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
 
-	if (*txring->status & PAS_STATUS_SOFT)
+	if (*chan->status & PAS_STATUS_SOFT)
 		reg |= PAS_IOB_DMA_TXCH_RESET_SINTC;
-	if (*txring->status & PAS_STATUS_ERROR)
+	if (*chan->status & PAS_STATUS_ERROR)
 		reg |= PAS_IOB_DMA_TXCH_RESET_DINTC;
 
-	write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(txring->chan), reg);
+	write_iob_reg(PAS_IOB_DMA_TXCH_RESET(chan->chno), reg);
 
 	return IRQ_HANDLED;
 }
@@ -909,15 +922,14 @@ err:
 static int pasemi_mac_open(struct net_device *dev)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
-	int base_irq;
 	unsigned int flags;
 	int ret;
 
 	/* enable rx section */
-	write_dma_reg(mac, PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
+	write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
 
 	/* enable tx section */
-	write_dma_reg(mac, PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
+	write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
 
 	flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
 		PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
@@ -925,56 +937,53 @@ static int pasemi_mac_open(struct net_de
 
 	write_mac_reg(mac, PAS_MAC_CFG_TXP, flags);
 
-	write_iob_reg(mac, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
-			   PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
-
-	write_iob_reg(mac, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
-			   PAS_IOB_DMA_TXCH_CFG_CNTTH(128));
-
 	/* 0xffffff is max value, about 16ms */
-	write_iob_reg(mac, PAS_IOB_DMA_COM_TIMEOUTCFG,
-			   PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
+	write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
+		      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
 
 	ret = pasemi_mac_setup_rx_resources(dev);
 	if (ret)
 		goto out_rx_resources;
 
-	mac->tx = pasemi_mac_setup_tx_resources(dev, mac->dma_txch);
+	mac->tx = pasemi_mac_setup_tx_resources(dev);
 
 	if (!mac->tx)
 		goto out_tx_ring;
 
+	write_iob_reg(PAS_IOB_DMA_RXCH_CFG(mac->rx->chan.chno),
+		      PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
+
+	write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno),
+		      PAS_IOB_DMA_TXCH_CFG_CNTTH(128));
+
 	write_mac_reg(mac, PAS_MAC_IPC_CHNL,
-			   PAS_MAC_IPC_CHNL_DCHNO(mac->dma_rxch) |
-			   PAS_MAC_IPC_CHNL_BCH(mac->dma_rxch));
+		      PAS_MAC_IPC_CHNL_DCHNO(mac->rx->chan.chno) |
+		      PAS_MAC_IPC_CHNL_BCH(mac->rx->chan.chno));
 
 	/* enable rx if */
-	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
-			   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);
+	write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
+		      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_OD |
-			   PAS_DMA_RXCHAN_CCMDSTA_FD |
-			   PAS_DMA_RXCHAN_CCMDSTA_DT);
+	pasemi_dma_start_chan(&rx_ring(mac)->chan, 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_SZ |
-			   PAS_DMA_TXCHAN_TCMDSTA_DB |
-			   PAS_DMA_TXCHAN_TCMDSTA_DE |
-			   PAS_DMA_TXCHAN_TCMDSTA_DA);
+	pasemi_dma_start_chan(&tx_ring(mac)->chan, 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);
 
-	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), RX_RING_SIZE>>1);
+	write_dma_reg(PAS_DMA_RXCHAN_INCR(rx_ring(mac)->chan.chno),
+		      RX_RING_SIZE>>1);
 
 	/* Clear out any residual packet count state from firmware */
 	pasemi_mac_restart_rx_intr(mac);
@@ -1001,37 +1010,25 @@ static int pasemi_mac_open(struct net_de
 	netif_start_queue(dev);
 	napi_enable(&mac->napi);
 
-	/* Interrupts are a bit different for our DMA controller: While
-	 * it's got one a regular PCI device header, the interrupt there
-	 * is really the base of the range it's using. Each tx and rx
-	 * channel has it's own interrupt source.
-	 */
-
-	base_irq = virq_to_hw(mac->dma_pdev->irq);
-
-	mac->tx_irq = irq_create_mapping(NULL, base_irq + mac->dma_txch);
-
 	snprintf(mac->tx_irq_name, sizeof(mac->tx_irq_name), "%s tx",
 		 dev->name);
 
-	ret = request_irq(mac->tx_irq, &pasemi_mac_tx_intr, IRQF_DISABLED,
+	ret = request_irq(mac->tx->chan.irq, &pasemi_mac_tx_intr, IRQF_DISABLED,
 			  mac->tx_irq_name, mac->tx);
 	if (ret) {
 		dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
-			base_irq + mac->dma_txch, ret);
+			mac->tx->chan.irq, ret);
 		goto out_tx_int;
 	}
 
-	mac->rx_irq = irq_create_mapping(NULL, base_irq + 20 + mac->dma_rxch);
-
 	snprintf(mac->rx_irq_name, sizeof(mac->rx_irq_name), "%s rx",
 		 dev->name);
 
-	ret = request_irq(mac->rx_irq, &pasemi_mac_rx_intr, IRQF_DISABLED,
-			  mac->rx_irq_name, dev);
+	ret = request_irq(mac->rx->chan.irq, &pasemi_mac_rx_intr, IRQF_DISABLED,
+			  mac->rx_irq_name, mac->rx);
 	if (ret) {
 		dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
-			base_irq + 20 + mac->dma_rxch, ret);
+			mac->rx->chan.irq, ret);
 		goto out_rx_int;
 	}
 
@@ -1041,7 +1038,7 @@ static int pasemi_mac_open(struct net_de
 	return 0;
 
 out_rx_int:
-	free_irq(mac->tx_irq, mac->tx);
+	free_irq(mac->tx->chan.irq, mac->tx);
 out_tx_int:
 	napi_disable(&mac->napi);
 	netif_stop_queue(dev);
@@ -1061,6 +1058,10 @@ static int pasemi_mac_close(struct net_d
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int sta;
 	int retries;
+	int rxch, txch;
+
+	rxch = rx_ring(mac)->chan.chno;
+	txch = tx_ring(mac)->chan.chno;
 
 	if (mac->phydev) {
 		phy_stop(mac->phydev);
@@ -1070,20 +1071,20 @@ 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));
+	sta = read_dma_reg(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));
+	sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(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));
+	sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(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);
@@ -1093,26 +1094,25 @@ static int pasemi_mac_close(struct net_d
 	pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
 
 	/* Disable interface */
-	write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
+	write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch),
 		      PAS_DMA_TXCHAN_TCMDSTA_ST);
-	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
+	write_dma_reg( PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
 		      PAS_DMA_RXINT_RCMDSTA_ST);
-	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
+	write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch),
 		      PAS_DMA_RXCHAN_CCMDSTA_ST);
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
-		sta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
+		sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(rxch));
 		if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT))
 			break;
 		cond_resched();
 	}
 
 	if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)
-		dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel %d\n",
-			mac->dma_txch);
+		dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
-		sta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
+		sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch));
 		if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT))
 			break;
 		cond_resched();
@@ -1122,7 +1122,7 @@ static int pasemi_mac_close(struct net_d
 		dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
-		sta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+		sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
 		if (!(sta & PAS_DMA_RXINT_RCMDSTA_ACT))
 			break;
 		cond_resched();
@@ -1135,12 +1135,12 @@ static int pasemi_mac_close(struct net_d
 	 * stopping, since you can't disable when active.
 	 */
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), 0);
-	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), 0);
-	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
+	write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 0);
+	write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch), 0);
+	write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
 
-	free_irq(mac->tx_irq, mac->tx);
-	free_irq(mac->rx_irq, mac->rx);
+	free_irq(mac->tx->chan.irq, mac->tx);
+	free_irq(mac->rx->chan.irq, mac->rx);
 
 	/* Free resources */
 	pasemi_mac_free_rx_resources(mac);
@@ -1239,7 +1239,7 @@ static int pasemi_mac_start_tx(struct sk
 
 	spin_unlock_irqrestore(&txring->lock, flags);
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_INCR(txring->chan), (nfrags+2) >> 1);
+	write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), (nfrags+2) >> 1);
 
 	return NETDEV_TX_OK;
 
@@ -1287,77 +1287,9 @@ static int pasemi_mac_poll(struct napi_s
 	return pkts;
 }
 
-static void __iomem * __devinit map_onedev(struct pci_dev *p, int index)
-{
-	struct device_node *dn;
-	void __iomem *ret;
-
-	dn = pci_device_to_OF_node(p);
-	if (!dn)
-		goto fallback;
-
-	ret = of_iomap(dn, index);
-	if (!ret)
-		goto fallback;
-
-	return ret;
-fallback:
-	/* This is hardcoded and ugly, but we have some firmware versions
-	 * that don't provide the register space in the device tree. Luckily
-	 * they are at well-known locations so we can just do the math here.
-	 */
-	return ioremap(0xe0000000 + (p->devfn << 12), 0x2000);
-}
-
-static int __devinit pasemi_mac_map_regs(struct pasemi_mac *mac)
-{
-	struct resource res;
-	struct device_node *dn;
-	int err;
-
-	mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
-	if (!mac->dma_pdev) {
-		dev_err(&mac->pdev->dev, "Can't find DMA Controller\n");
-		return -ENODEV;
-	}
-
-	mac->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
-	if (!mac->iob_pdev) {
-		dev_err(&mac->pdev->dev, "Can't find I/O Bridge\n");
-		return -ENODEV;
-	}
-
-	mac->regs = map_onedev(mac->pdev, 0);
-	mac->dma_regs = map_onedev(mac->dma_pdev, 0);
-	mac->iob_regs = map_onedev(mac->iob_pdev, 0);
-
-	if (!mac->regs || !mac->dma_regs || !mac->iob_regs) {
-		dev_err(&mac->pdev->dev, "Can't map registers\n");
-		return -ENODEV;
-	}
-
-	/* The dma status structure is located in the I/O bridge, and
-	 * is cache coherent.
-	 */
-	if (!dma_status) {
-		dn = pci_device_to_OF_node(mac->iob_pdev);
-		if (dn)
-			err = of_address_to_resource(dn, 1, &res);
-		if (!dn || err) {
-			/* Fallback for old firmware */
-			res.start = 0xfd800000;
-			res.end = res.start + 0x1000;
-		}
-		dma_status = __ioremap(res.start, res.end-res.start, 0);
-	}
-
-	return 0;
-}
-
 static int __devinit
 pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	static int index = 0;
 	struct net_device *dev;
 	struct pasemi_mac *mac;
 	int err;
@@ -1387,18 +1319,33 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 
 	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;
-	mac->dma_rxch = index;
+	mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
+	if (!mac->dma_pdev) {
+		dev_err(&mac->pdev->dev, "Can't find DMA Controller\n");
+		err = -ENODEV;
+		goto out;
+	}
 
-	/* We probe GMAC before XAUI, but the DMA interfaces are
-	 * in XAUI, GMAC order.
-	 */
-	if (index < 4)
-		mac->dma_if = index + 2;
-	else
-		mac->dma_if = index - 4;
-	index++;
+	mac->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
+	if (!mac->iob_pdev) {
+		dev_err(&mac->pdev->dev, "Can't find I/O Bridge\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	/* get mac addr from device tree */
+	if (pasemi_get_mac_addr(mac) || !is_valid_ether_addr(mac->mac_addr)) {
+		err = -ENODEV;
+		goto out;
+	}
+	memcpy(dev->dev_addr, mac->mac_addr, sizeof(mac->mac_addr));
+
+	mac->dma_if = mac_to_intf(mac);
+	if (mac->dma_if < 0) {
+		dev_err(&mac->pdev->dev, "Can't map DMA interface\n");
+		err = -ENODEV;
+		goto out;
+	}
 
 	switch (pdev->device) {
 	case 0xa005:
@@ -1412,19 +1359,11 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 		goto out;
 	}
 
-	/* get mac addr from device tree */
-	if (pasemi_get_mac_addr(mac) || !is_valid_ether_addr(mac->mac_addr)) {
-		err = -ENODEV;
-		goto out;
-	}
-	memcpy(dev->dev_addr, mac->mac_addr, sizeof(mac->mac_addr));
-
 	dev->open = pasemi_mac_open;
 	dev->stop = pasemi_mac_close;
 	dev->hard_start_xmit = pasemi_mac_start_tx;
 	dev->set_multicast_list = pasemi_mac_set_rx_mode;
 
-	err = pasemi_mac_map_regs(mac);
 	if (err)
 		goto out;
 
@@ -1451,12 +1390,6 @@ out:
 		pci_dev_put(mac->iob_pdev);
 	if (mac->dma_pdev)
 		pci_dev_put(mac->dma_pdev);
-	if (mac->dma_regs)
-		iounmap(mac->dma_regs);
-	if (mac->iob_regs)
-		iounmap(mac->iob_regs);
-	if (mac->regs)
-		iounmap(mac->regs);
 
 	free_netdev(dev);
 out_disable_device:
@@ -1481,9 +1414,8 @@ static void __devexit pasemi_mac_remove(
 	pci_dev_put(mac->dma_pdev);
 	pci_dev_put(mac->iob_pdev);
 
-	iounmap(mac->regs);
-	iounmap(mac->dma_regs);
-	iounmap(mac->iob_regs);
+	pasemi_dma_free_chan(&mac->tx->chan);
+	pasemi_dma_free_chan(&mac->rx->chan);
 
 	pci_set_drvdata(pdev, NULL);
 	free_netdev(netdev);
@@ -1507,12 +1439,16 @@ static struct pci_driver pasemi_mac_driv
 static void __exit pasemi_mac_cleanup_module(void)
 {
 	pci_unregister_driver(&pasemi_mac_driver);
-	__iounmap(dma_status);
-	dma_status = NULL;
 }
 
 int pasemi_mac_init_module(void)
 {
+	int err;
+
+	err = pasemi_dma_init();
+	if (err)
+		return err;
+
 	return pci_register_driver(&pasemi_mac_driver);
 }
 
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -27,23 +27,18 @@
 #include <linux/phy.h>
 
 struct pasemi_mac_txring {
+	struct pasemi_dmachan chan; /* Must be first */
 	spinlock_t	 lock;
-	u64		*status; /* Ptr to cacheable status area */
-	u64		*ring;
-	dma_addr_t	 dma;
 	unsigned int	 size;
 	unsigned int	 next_to_fill;
 	unsigned int	 next_to_clean;
 	struct pasemi_mac_buffer *ring_info;
-	int		 chan;
 	struct pasemi_mac *mac;	/* Needed in intr handler */
 };
 
 struct pasemi_mac_rxring {
+	struct pasemi_dmachan chan; /* Must be first */
 	spinlock_t	 lock;
-	u64		*status; /* Ptr to cacheable status area */
-	u64		*ring;	/* RX channel descriptor ring */
-	dma_addr_t	 dma;
 	u64		*buffers;	/* RX interface buffer ring */
 	dma_addr_t	 buf_dma;
 	unsigned int	 size;
@@ -55,9 +50,6 @@ struct pasemi_mac_rxring {
 
 struct pasemi_mac {
 	struct net_device *netdev;
-	void __iomem *regs;
-	void __iomem *dma_regs;
-	void __iomem *iob_regs;
 	struct pci_dev *pdev;
 	struct pci_dev *dma_pdev;
 	struct pci_dev *iob_pdev;
@@ -67,8 +59,6 @@ struct pasemi_mac {
 	u8		type;
 #define MAC_TYPE_GMAC	1
 #define MAC_TYPE_XAUI	2
-	u32	dma_txch;
-	u32	dma_rxch;
 	u32	dma_if;
 
 	u8		mac_addr[6];
@@ -77,8 +67,6 @@ struct pasemi_mac {
 
 	struct pasemi_mac_txring *tx;
 	struct pasemi_mac_rxring *rx;
-	unsigned int	tx_irq;
-	unsigned int	rx_irq;
 	char		tx_irq_name[10];		/* "eth%d tx" */
 	char		rx_irq_name[10];		/* "eth%d rx" */
 	int	link;

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [5/12] pasemi_mac: performance tweaks
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (3 preceding siblings ...)
  2007-11-29  2:56 ` [PATCH] [4/12] pasemi_mac: Convert to new dma library Olof Johansson
@ 2007-11-29  2:56 ` Olof Johansson
  2007-11-29  2:56 ` [PATCH] [6/12] pasemi_mac: Fix TX cleaning Olof Johansson
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:56 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: performance tweaks

* Seems like we do better with a smaller RX ring, probably because chances of
  still having the SKB cached are better
* Const-ify variables to get better code generation and fewer reloads
* Move prefetching around a little, and try to prefetch the whole SKB
* Set NETIF_F_HIGHDMA
* Misc other minor tweaks


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

---
 drivers/net/pasemi_mac.c |  114 ++++++++++++++++++++++++++++-------------------
 1 file changed, 68 insertions(+), 46 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -56,7 +56,7 @@
 
 
 /* Must be a power of two */
-#define RX_RING_SIZE 4096
+#define RX_RING_SIZE 1024
 #define TX_RING_SIZE 4096
 
 #define DEFAULT_MSG_ENABLE	  \
@@ -103,12 +103,12 @@ static void write_iob_reg(unsigned int r
 	pasemi_write_iob_reg(reg, val);
 }
 
-static unsigned int read_mac_reg(struct pasemi_mac *mac, unsigned int reg)
+static unsigned int read_mac_reg(const struct pasemi_mac *mac, unsigned int reg)
 {
 	return pasemi_read_mac_reg(mac->dma_if, reg);
 }
 
-static void write_mac_reg(struct pasemi_mac *mac, unsigned int reg,
+static void write_mac_reg(const struct pasemi_mac *mac, unsigned int reg,
 			  unsigned int val)
 {
 	pasemi_write_mac_reg(mac->dma_if, reg, val);
@@ -124,16 +124,26 @@ static void write_dma_reg(unsigned int r
 	pasemi_write_dma_reg(reg, val);
 }
 
-static struct pasemi_mac_rxring *rx_ring(struct pasemi_mac *mac)
+static struct pasemi_mac_rxring *rx_ring(const struct pasemi_mac *mac)
 {
 	return mac->rx;
 }
 
-static struct pasemi_mac_txring *tx_ring(struct pasemi_mac *mac)
+static struct pasemi_mac_txring *tx_ring(const struct pasemi_mac *mac)
 {
 	return mac->tx;
 }
 
+static inline void prefetch_skb(const struct sk_buff *skb)
+{
+	const void *d = skb;
+
+	prefetch(d);
+	prefetch(d+64);
+	prefetch(d+128);
+	prefetch(d+192);
+}
+
 static int mac_to_intf(struct pasemi_mac *mac)
 {
 	struct pci_dev *pdev = mac->pdev;
@@ -211,19 +221,18 @@ static int pasemi_get_mac_addr(struct pa
 
 static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
 				    struct sk_buff *skb,
-				    dma_addr_t *dmas)
+				    const dma_addr_t *dmas)
 {
 	int f;
 	int nfrags = skb_shinfo(skb)->nr_frags;
+	struct pci_dev *pdev = mac->dma_pdev;
 
-	pci_unmap_single(mac->dma_pdev, dmas[0], skb_headlen(skb),
-			 PCI_DMA_TODEVICE);
+	pci_unmap_single(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);
+		pci_unmap_page(pdev, dmas[f+1], frag->size, PCI_DMA_TODEVICE);
 	}
 	dev_kfree_skb_irq(skb);
 
@@ -233,7 +242,7 @@ static int pasemi_mac_unmap_tx_skb(struc
 	return (nfrags + 3) & ~1;
 }
 
-static int pasemi_mac_setup_rx_resources(struct net_device *dev)
+static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
 {
 	struct pasemi_mac_rxring *ring;
 	struct pasemi_mac *mac = netdev_priv(dev);
@@ -277,7 +286,7 @@ static int pasemi_mac_setup_rx_resources
 		      PAS_DMA_RXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32) |
 		      PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-	cfg = PAS_DMA_RXCHAN_CFG_HBU(1);
+	cfg = PAS_DMA_RXCHAN_CFG_HBU(2);
 
 	if (translation_enabled())
 		cfg |= PAS_DMA_RXCHAN_CFG_CTR;
@@ -291,7 +300,7 @@ static int pasemi_mac_setup_rx_resources
 		      PAS_DMA_RXINT_BASEU_BRBH(ring->buf_dma >> 32) |
 		      PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-	cfg = PAS_DMA_RXINT_CFG_DHL(1) | PAS_DMA_RXINT_CFG_L2 |
+	cfg = PAS_DMA_RXINT_CFG_DHL(2) | PAS_DMA_RXINT_CFG_L2 |
 	      PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP |
 	      PAS_DMA_RXINT_CFG_HEN;
 
@@ -316,7 +325,7 @@ out_chan:
 }
 
 static struct pasemi_mac_txring *
-pasemi_mac_setup_tx_resources(struct net_device *dev)
+pasemi_mac_setup_tx_resources(const struct net_device *dev)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	u32 val;
@@ -439,9 +448,10 @@ static void pasemi_mac_free_rx_resources
 	mac->rx = NULL;
 }
 
-static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
+static void pasemi_mac_replenish_rx_ring(const struct net_device *dev,
+					 const int limit)
 {
-	struct pasemi_mac *mac = netdev_priv(dev);
+	const struct pasemi_mac *mac = netdev_priv(dev);
 	struct pasemi_mac_rxring *rx = rx_ring(mac);
 	int fill, count;
 
@@ -492,7 +502,7 @@ static void pasemi_mac_replenish_rx_ring
 				(RX_RING_SIZE - 1);
 }
 
-static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
+static void pasemi_mac_restart_rx_intr(const struct pasemi_mac *mac)
 {
 	unsigned int reg, pcnt;
 	/* Re-enable packet count interrupts: finally
@@ -506,7 +516,7 @@ static void pasemi_mac_restart_rx_intr(s
 	write_iob_reg(PAS_IOB_DMA_RXCH_RESET(mac->rx->chan.chno), reg);
 }
 
-static void pasemi_mac_restart_tx_intr(struct pasemi_mac *mac)
+static void pasemi_mac_restart_tx_intr(const struct pasemi_mac *mac)
 {
 	unsigned int reg, pcnt;
 
@@ -519,7 +529,8 @@ static void pasemi_mac_restart_tx_intr(s
 }
 
 
-static inline void pasemi_mac_rx_error(struct pasemi_mac *mac, u64 macrx)
+static inline void pasemi_mac_rx_error(const struct pasemi_mac *mac,
+				       const u64 macrx)
 {
 	unsigned int rcmdsta, ccmdsta;
 	struct pasemi_dmachan *chan = &rx_ring(mac)->chan;
@@ -537,7 +548,8 @@ static inline void pasemi_mac_rx_error(s
 		rcmdsta, ccmdsta);
 }
 
-static inline void pasemi_mac_tx_error(struct pasemi_mac *mac, u64 mactx)
+static inline void pasemi_mac_tx_error(const struct pasemi_mac *mac,
+				       const u64 mactx)
 {
 	unsigned int cmdsta;
 	struct pasemi_dmachan *chan = &tx_ring(mac)->chan;
@@ -553,19 +565,22 @@ static inline void pasemi_mac_tx_error(s
 	printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta);
 }
 
-static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx, int limit)
+static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx,
+			       const int limit)
 {
-	struct pasemi_dmachan *chan = &rx->chan;
+	const struct pasemi_dmachan *chan = &rx->chan;
 	struct pasemi_mac *mac = rx->mac;
+	struct pci_dev *pdev = mac->dma_pdev;
 	unsigned int n;
-	int count;
+	int count, buf_index, tot_bytes, packets;
 	struct pasemi_mac_buffer *info;
 	struct sk_buff *skb;
 	unsigned int len;
-	u64 macrx;
+	u64 macrx, eval;
 	dma_addr_t dma;
-	int buf_index;
-	u64 eval;
+
+	tot_bytes = 0;
+	packets = 0;
 
 	spin_lock(&rx->lock);
 
@@ -575,6 +590,7 @@ static int pasemi_mac_clean_rx(struct pa
 
 	for (count = 0; count < limit; count++) {
 		macrx = RX_DESC(rx, n);
+		prefetch(&RX_DESC(rx, n+4));
 
 		if ((macrx & XCT_MACRX_E) ||
 		    (*chan->status & PAS_STATUS_ERROR))
@@ -596,12 +612,12 @@ static int pasemi_mac_clean_rx(struct pa
 
 		skb = info->skb;
 
-		prefetch(skb);
-		prefetch(&skb->data_len);
+		prefetch_skb(skb);
 
 		len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
 
-		pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE);
+		pci_unmap_single(pdev, dma, BUF_SIZE-LOCAL_SKB_ALIGN,
+				 PCI_DMA_FROMDEVICE);
 
 		if (macrx & XCT_MACRX_CRC) {
 			/* CRC error flagged */
@@ -628,9 +644,6 @@ static int pasemi_mac_clean_rx(struct pa
 
 		info->dma = 0;
 
-		/* Don't include CRC */
-		skb_put(skb, len-4);
-
 		if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			skb->csum = (macrx & XCT_MACRX_CSUM_M) >>
@@ -638,8 +651,11 @@ static int pasemi_mac_clean_rx(struct pa
 		} else
 			skb->ip_summed = CHECKSUM_NONE;
 
-		mac->netdev->stats.rx_bytes += len;
-		mac->netdev->stats.rx_packets++;
+		packets++;
+		tot_bytes += len;
+
+		/* Don't include CRC */
+		skb_put(skb, len-4);
 
 		skb->protocol = eth_type_trans(skb, mac->netdev);
 		netif_receive_skb(skb);
@@ -672,6 +688,9 @@ next:
 
 	pasemi_mac_replenish_rx_ring(mac->netdev, count);
 
+	mac->netdev->stats.rx_bytes += tot_bytes;
+	mac->netdev->stats.rx_packets += packets;
+
 	spin_unlock(&rx_ring(mac)->lock);
 
 	return count;
@@ -758,10 +777,10 @@ restart:
 
 static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
 {
-	struct pasemi_mac_rxring *rxring = data;
+	const struct pasemi_mac_rxring *rxring = data;
 	struct pasemi_mac *mac = rxring->mac;
 	struct net_device *dev = mac->netdev;
-	struct pasemi_dmachan *chan = &rxring->chan;
+	const struct pasemi_dmachan *chan = &rxring->chan;
 	unsigned int reg;
 
 	if (!(*chan->status & PAS_STATUS_CAUSE_M))
@@ -789,7 +808,7 @@ static irqreturn_t pasemi_mac_rx_intr(in
 static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
 {
 	struct pasemi_mac_txring *txring = data;
-	struct pasemi_dmachan *chan = &txring->chan;
+	const struct pasemi_dmachan *chan = &txring->chan;
 	unsigned int reg, pcnt;
 
 	if (!(*chan->status & PAS_STATUS_CAUSE_M))
@@ -1158,6 +1177,7 @@ static int pasemi_mac_start_tx(struct sk
 	unsigned int map_size[MAX_SKB_FRAGS+1];
 	unsigned long flags;
 	int i, nfrags;
+	int fill;
 
 	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
 
@@ -1205,6 +1225,8 @@ static int pasemi_mac_start_tx(struct sk
 
 	spin_lock_irqsave(&txring->lock, flags);
 
+	fill = txring->next_to_fill;
+
 	/* 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
@@ -1215,13 +1237,13 @@ static int pasemi_mac_start_tx(struct sk
 		goto out_err;
 	}
 
-	TX_DESC(txring, txring->next_to_fill) = mactx;
-	txring->next_to_fill++;
-	TX_DESC_INFO(txring, txring->next_to_fill).skb = skb;
+	TX_DESC(txring, fill) = mactx;
+	fill++;
+	TX_DESC_INFO(txring, fill).skb = skb;
 	for (i = 0; i <= nfrags; i++) {
-		TX_DESC(txring, txring->next_to_fill+i) =
+		TX_DESC(txring, fill+i) =
 			XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
-		TX_DESC_INFO(txring, txring->next_to_fill+i).dma = map[i];
+		TX_DESC_INFO(txring, fill+i).dma = map[i];
 	}
 
 	/* We have to add an even number of 8-byte entries to the ring
@@ -1231,8 +1253,7 @@ static int pasemi_mac_start_tx(struct sk
 	if (nfrags & 1)
 		nfrags++;
 
-	txring->next_to_fill = (txring->next_to_fill + nfrags + 1) &
-				(TX_RING_SIZE-1);
+	txring->next_to_fill = (fill + nfrags + 1) & (TX_RING_SIZE-1);
 
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
@@ -1255,7 +1276,7 @@ out_err_nolock:
 
 static void pasemi_mac_set_rx_mode(struct net_device *dev)
 {
-	struct pasemi_mac *mac = netdev_priv(dev);
+	const struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int flags;
 
 	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
@@ -1317,7 +1338,8 @@ 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 | NETIF_F_SG;
+	dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX | NETIF_F_SG |
+			NETIF_F_HIGHDMA;
 
 	mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
 	if (!mac->dma_pdev) {

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [6/12] pasemi_mac: Fix TX cleaning
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (4 preceding siblings ...)
  2007-11-29  2:56 ` [PATCH] [5/12] pasemi_mac: performance tweaks Olof Johansson
@ 2007-11-29  2:56 ` Olof Johansson
  2007-11-29  2:57 ` [PATCH] [7/12] pasemi_mac: Improve RX interrupt mitigation Olof Johansson
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:56 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: Fix TX cleaning

This is a bit awkward. We don't have a timer-delayed interrupt on TX
complete, but we have a count threshold. So set that reasonably high
(32 packets), and schedule the NAPI poll when it goes off. Also bump a
regular timer that will take care of rotting packets for the last 1..31
ones in case we don't trigger a TX interrupt (and there's no RX activity
that would otherwise trigger the poll).

The longer-term fix is to separate TX from RX NAPI and do two separate
poll loops.

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

---
 drivers/net/pasemi_mac.c |   41 +++++++++++++++++++++++++++++++++--------
 drivers/net/pasemi_mac.h |    1 +
 2 files changed, 34 insertions(+), 8 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -805,27 +805,43 @@ static irqreturn_t pasemi_mac_rx_intr(in
 	return IRQ_HANDLED;
 }
 
+#define TX_CLEAN_INTERVAL HZ
+
+static void pasemi_mac_tx_timer(unsigned long data)
+{
+	struct pasemi_mac_txring *txring = (struct pasemi_mac_txring *)data;
+	struct pasemi_mac *mac = txring->mac;
+
+	pasemi_mac_clean_tx(txring);
+
+	mod_timer(&txring->clean_timer, jiffies + TX_CLEAN_INTERVAL);
+
+	pasemi_mac_restart_tx_intr(mac);
+}
+
 static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
 {
 	struct pasemi_mac_txring *txring = data;
 	const struct pasemi_dmachan *chan = &txring->chan;
-	unsigned int reg, pcnt;
+	struct pasemi_mac *mac = txring->mac;
+	unsigned int reg;
 
 	if (!(*chan->status & PAS_STATUS_CAUSE_M))
 		return IRQ_NONE;
 
-	pasemi_mac_clean_tx(txring);
-
-	pcnt = *chan->status & PAS_STATUS_PCNT_M;
-
-	reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
+	reg = 0;
 
 	if (*chan->status & PAS_STATUS_SOFT)
 		reg |= PAS_IOB_DMA_TXCH_RESET_SINTC;
 	if (*chan->status & PAS_STATUS_ERROR)
 		reg |= PAS_IOB_DMA_TXCH_RESET_DINTC;
 
-	write_iob_reg(PAS_IOB_DMA_TXCH_RESET(chan->chno), reg);
+	mod_timer(&txring->clean_timer, jiffies + (TX_CLEAN_INTERVAL)*2);
+
+	netif_rx_schedule(mac->netdev, &mac->napi);
+
+	if (reg)
+		write_iob_reg(PAS_IOB_DMA_TXCH_RESET(chan->chno), reg);
 
 	return IRQ_HANDLED;
 }
@@ -973,7 +989,7 @@ static int pasemi_mac_open(struct net_de
 		      PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
 
 	write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno),
-		      PAS_IOB_DMA_TXCH_CFG_CNTTH(128));
+		      PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
 
 	write_mac_reg(mac, PAS_MAC_IPC_CHNL,
 		      PAS_MAC_IPC_CHNL_DCHNO(mac->rx->chan.chno) |
@@ -1054,6 +1070,12 @@ static int pasemi_mac_open(struct net_de
 	if (mac->phydev)
 		phy_start(mac->phydev);
 
+	init_timer(&mac->tx->clean_timer);
+	mac->tx->clean_timer.function = pasemi_mac_tx_timer;
+	mac->tx->clean_timer.data = (unsigned long)mac->tx;
+	mac->tx->clean_timer.expires = jiffies+HZ;
+	add_timer(&mac->tx->clean_timer);
+
 	return 0;
 
 out_rx_int:
@@ -1087,6 +1109,8 @@ static int pasemi_mac_close(struct net_d
 		phy_disconnect(mac->phydev);
 	}
 
+	del_timer_sync(&mac->tx->clean_timer);
+
 	netif_stop_queue(dev);
 	napi_disable(&mac->napi);
 
@@ -1304,6 +1328,7 @@ static int pasemi_mac_poll(struct napi_s
 		netif_rx_complete(dev, napi);
 
 		pasemi_mac_restart_rx_intr(mac);
+		pasemi_mac_restart_tx_intr(mac);
 	}
 	return pkts;
 }
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -34,6 +34,7 @@ struct pasemi_mac_txring {
 	unsigned int	 next_to_clean;
 	struct pasemi_mac_buffer *ring_info;
 	struct pasemi_mac *mac;	/* Needed in intr handler */
+	struct timer_list clean_timer;
 };
 
 struct pasemi_mac_rxring {

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [7/12] pasemi_mac: Improve RX interrupt mitigation
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (5 preceding siblings ...)
  2007-11-29  2:56 ` [PATCH] [6/12] pasemi_mac: Fix TX cleaning Olof Johansson
@ 2007-11-29  2:57 ` Olof Johansson
  2007-11-29  2:57 ` [PATCH] [8/12] pasemi_mac: Software-based LRO support Olof Johansson
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: Improve RX interrupt mitigation

Currently the receive side interrupts will go off on the reception of
a packet, NAPI will poll the ring and keep polling as long as there's
a decent amount of packets to receive.

This is less than optimal, especially for LRO where it's better if we
have a more substantial amount of packets to process at once, to get
the real LRO benefits.

So, set the count threshold to a higher value and use the timeout feature
that will give us an interrupt even if not enough packets have come in
to set off the count threshold.

FIXME: It'd be real nice to have ethtool support for users to tune this
at runtime.


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


---
 drivers/net/pasemi_mac.c |   18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -504,15 +504,19 @@ static void pasemi_mac_replenish_rx_ring
 
 static void pasemi_mac_restart_rx_intr(const struct pasemi_mac *mac)
 {
+	struct pasemi_mac_rxring *rx = rx_ring(mac);
 	unsigned int reg, pcnt;
 	/* Re-enable packet count interrupts: finally
 	 * ack the packet count interrupt we got in rx_intr.
 	 */
 
-	pcnt = *rx_ring(mac)->chan.status & PAS_STATUS_PCNT_M;
+	pcnt = *rx->chan.status & PAS_STATUS_PCNT_M;
 
 	reg = PAS_IOB_DMA_RXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_RXCH_RESET_PINTC;
 
+	if (*rx->chan.status & PAS_STATUS_TIMER)
+		reg |= PAS_IOB_DMA_RXCH_RESET_TINTC;
+
 	write_iob_reg(PAS_IOB_DMA_RXCH_RESET(mac->rx->chan.chno), reg);
 }
 
@@ -795,8 +799,6 @@ static irqreturn_t pasemi_mac_rx_intr(in
 		reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
 	if (*chan->status & PAS_STATUS_ERROR)
 		reg |= PAS_IOB_DMA_RXCH_RESET_DINTC;
-	if (*chan->status & PAS_STATUS_TIMER)
-		reg |= PAS_IOB_DMA_RXCH_RESET_TINTC;
 
 	netif_rx_schedule(dev, &mac->napi);
 
@@ -972,10 +974,6 @@ static int pasemi_mac_open(struct net_de
 
 	write_mac_reg(mac, PAS_MAC_CFG_TXP, flags);
 
-	/* 0xffffff is max value, about 16ms */
-	write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
-		      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
-
 	ret = pasemi_mac_setup_rx_resources(dev);
 	if (ret)
 		goto out_rx_resources;
@@ -985,8 +983,12 @@ static int pasemi_mac_open(struct net_de
 	if (!mac->tx)
 		goto out_tx_ring;
 
+	/* 0x3ff with 33MHz clock is about 31us */
+	write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
+		      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
+
 	write_iob_reg(PAS_IOB_DMA_RXCH_CFG(mac->rx->chan.chno),
-		      PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
+		      PAS_IOB_DMA_RXCH_CFG_CNTTH(128));
 
 	write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno),
 		      PAS_IOB_DMA_TXCH_CFG_CNTTH(32));

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [8/12] pasemi_mac: Software-based LRO support
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (6 preceding siblings ...)
  2007-11-29  2:57 ` [PATCH] [7/12] pasemi_mac: Improve RX interrupt mitigation Olof Johansson
@ 2007-11-29  2:57 ` Olof Johansson
  2007-11-29  2:57 ` [PATCH] [9/12] pasemi_mac: SKB unmap optimization Olof Johansson
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: Software-based LRO support

Implement LRO for pasemi_mac. Pretty straightforward.


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

---
 drivers/net/Kconfig      |    1 
 drivers/net/pasemi_mac.c |   53 +++++++++++++++++++++++++++++++++++++++++++----
 drivers/net/pasemi_mac.h |    5 ++++
 3 files changed, 55 insertions(+), 4 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -32,6 +32,7 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <net/checksum.h>
+#include <linux/inet_lro.h>
 
 #include <asm/irq.h>
 #include <asm/firmware.h>
@@ -56,9 +57,11 @@
 
 
 /* Must be a power of two */
-#define RX_RING_SIZE 1024
+#define RX_RING_SIZE 2048
 #define TX_RING_SIZE 4096
 
+#define LRO_MAX_AGGR 64
+
 #define DEFAULT_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
 	 NETIF_MSG_PROBE	| \
@@ -206,7 +209,6 @@ static int pasemi_get_mac_addr(struct pa
 		return -ENOENT;
 	}
 
-
 	if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0],
 		   &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) {
 		dev_warn(&pdev->dev,
@@ -219,6 +221,37 @@ static int pasemi_get_mac_addr(struct pa
 	return 0;
 }
 
+static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
+		       void **tcph, u64 *hdr_flags, void *data)
+{
+	u64 macrx = (u64) data;
+	unsigned int ip_len;
+	struct iphdr *iph;
+
+	/* IPv4 header checksum failed */
+	if ((macrx & XCT_MACRX_HTY_M) != XCT_MACRX_HTY_IPV4_OK)
+		return -1;
+
+	/* non tcp packet */
+	skb_reset_network_header(skb);
+	iph = ip_hdr(skb);
+	if (iph->protocol != IPPROTO_TCP)
+		return -1;
+
+	ip_len = ip_hdrlen(skb);
+	skb_set_transport_header(skb, ip_len);
+	*tcph = tcp_hdr(skb);
+
+	/* check if ip header and tcp header are complete */
+	if (iph->tot_len < ip_len + tcp_hdrlen(skb))
+		return -1;
+
+	*hdr_flags = LRO_IPV4 | LRO_TCP;
+	*iphdr = iph;
+
+	return 0;
+}
+
 static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
 				    struct sk_buff *skb,
 				    const dma_addr_t *dmas)
@@ -662,7 +695,7 @@ static int pasemi_mac_clean_rx(struct pa
 		skb_put(skb, len-4);
 
 		skb->protocol = eth_type_trans(skb, mac->netdev);
-		netif_receive_skb(skb);
+		lro_receive_skb(&mac->lro_mgr, skb, (void *)macrx);
 
 next:
 		RX_DESC(rx, n) = 0;
@@ -684,6 +717,8 @@ next:
 
 	rx_ring(mac)->next_to_clean = n;
 
+	lro_flush_all(&mac->lro_mgr);
+
 	/* 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.
@@ -988,7 +1023,7 @@ static int pasemi_mac_open(struct net_de
 		      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
 
 	write_iob_reg(PAS_IOB_DMA_RXCH_CFG(mac->rx->chan.chno),
-		      PAS_IOB_DMA_RXCH_CFG_CNTTH(128));
+		      PAS_IOB_DMA_RXCH_CFG_CNTTH(256));
 
 	write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno),
 		      PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
@@ -1368,6 +1403,16 @@ pasemi_mac_probe(struct pci_dev *pdev, c
 	dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX | NETIF_F_SG |
 			NETIF_F_HIGHDMA;
 
+	mac->lro_mgr.max_aggr = LRO_MAX_AGGR;
+	mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
+	mac->lro_mgr.lro_arr = mac->lro_desc;
+	mac->lro_mgr.get_skb_header = get_skb_hdr;
+	mac->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
+	mac->lro_mgr.dev = mac->netdev;
+	mac->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
+	mac->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+
+
 	mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
 	if (!mac->dma_pdev) {
 		dev_err(&mac->pdev->dev, "Can't find DMA Controller\n");
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -26,6 +26,8 @@
 #include <linux/spinlock.h>
 #include <linux/phy.h>
 
+#define MAX_LRO_DESCRIPTORS 8
+
 struct pasemi_mac_txring {
 	struct pasemi_dmachan chan; /* Must be first */
 	spinlock_t	 lock;
@@ -64,7 +66,10 @@ struct pasemi_mac {
 
 	u8		mac_addr[6];
 
+	struct net_lro_mgr	lro_mgr;
+	struct net_lro_desc	lro_desc[MAX_LRO_DESCRIPTORS];
 	struct timer_list	rxtimer;
+	unsigned int		lro_max_aggr;
 
 	struct pasemi_mac_txring *tx;
 	struct pasemi_mac_rxring *rx;
Index: k.org/drivers/net/Kconfig
===================================================================
--- k.org.orig/drivers/net/Kconfig
+++ k.org/drivers/net/Kconfig
@@ -2566,6 +2566,7 @@ config PASEMI_MAC
 	tristate "PA Semi 1/10Gbit MAC"
 	depends on PPC64 && PCI
 	select PHYLIB
+	select INET_LRO
 	help
 	  This driver supports the on-chip 1/10Gbit Ethernet controller on
 	  PA Semi's PWRficient line of chips.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [9/12] pasemi_mac: SKB unmap optimization
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (7 preceding siblings ...)
  2007-11-29  2:57 ` [PATCH] [8/12] pasemi_mac: Software-based LRO support Olof Johansson
@ 2007-11-29  2:57 ` Olof Johansson
  2007-11-29  2:57 ` [PATCH] [10/12] pasemi_mac: Remove SKB copy/recycle logic Olof Johansson
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: SKB unmap optimization

Avoid touching skb_shinfo() in the unmap path, since it turns out to
normally cause cache misses and delays. instead, save number of fragments
in the TX_RING_INFO structures since that's all that's needed anyway.


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

---
 drivers/net/pasemi_mac.c |   39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -253,11 +253,11 @@ static int get_skb_hdr(struct sk_buff *s
 }
 
 static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
+				    const int nfrags,
 				    struct sk_buff *skb,
 				    const dma_addr_t *dmas)
 {
 	int f;
-	int nfrags = skb_shinfo(skb)->nr_frags;
 	struct pci_dev *pdev = mac->dma_pdev;
 
 	pci_unmap_single(pdev, dmas[0], skb_headlen(skb), PCI_DMA_TODEVICE);
@@ -425,7 +425,7 @@ static void pasemi_mac_free_tx_resources
 	unsigned int i, j;
 	struct pasemi_mac_buffer *info;
 	dma_addr_t dmas[MAX_SKB_FRAGS+1];
-	int freed;
+	int freed, nfrags;
 	int start, limit;
 
 	start = txring->next_to_clean;
@@ -438,10 +438,12 @@ static void pasemi_mac_free_tx_resources
 	for (i = start; i < limit; i += freed) {
 		info = &txring->ring_info[(i+1) & (TX_RING_SIZE-1)];
 		if (info->dma && info->skb) {
-			for (j = 0; j <= skb_shinfo(info->skb)->nr_frags; j++)
+			nfrags = skb_shinfo(info->skb)->nr_frags;
+			for (j = 0; j <= nfrags; j++)
 				dmas[j] = txring->ring_info[(i+1+j) &
 						(TX_RING_SIZE-1)].dma;
-			freed = pasemi_mac_unmap_tx_skb(mac, info->skb, dmas);
+			freed = pasemi_mac_unmap_tx_skb(mac, nfrags,
+							info->skb, dmas);
 		} else
 			freed = 2;
 	}
@@ -749,6 +751,8 @@ static int pasemi_mac_clean_tx(struct pa
 	unsigned long flags;
 	struct sk_buff *skbs[TX_CLEAN_BATCHSIZE];
 	dma_addr_t dmas[TX_CLEAN_BATCHSIZE][MAX_SKB_FRAGS+1];
+	int nf[TX_CLEAN_BATCHSIZE];
+	int nr_frags;
 
 	total_count = 0;
 	batch_limit = TX_CLEAN_BATCHSIZE;
@@ -758,6 +762,8 @@ restart:
 	start = txring->next_to_clean;
 	ring_limit = txring->next_to_fill;
 
+	prefetch(&TX_DESC_INFO(txring, start+1).skb);
+
 	/* Compensate for when fill has wrapped but clean has not */
 	if (start > ring_limit)
 		ring_limit += TX_RING_SIZE;
@@ -771,6 +777,9 @@ restart:
 		u64 mactx = TX_DESC(txring, i);
 		struct sk_buff *skb;
 
+		skb = TX_DESC_INFO(txring, i+1).skb;
+		nr_frags = TX_DESC_INFO(txring, i).dma;
+
 		if ((mactx  & XCT_MACTX_E) ||
 		    (*chan->status & PAS_STATUS_ERROR))
 			pasemi_mac_tx_error(mac, mactx);
@@ -779,21 +788,22 @@ restart:
 			/* Not yet transmitted */
 			break;
 
-		skb = TX_DESC_INFO(txring, i+1).skb;
-		skbs[descr_count] = skb;
+		buf_count = 2 + nr_frags;
+		/* 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++;
 
-		buf_count = 2 + skb_shinfo(skb)->nr_frags;
-		for (j = 0; j <= skb_shinfo(skb)->nr_frags; j++)
+		for (j = 0; j <= nr_frags; j++)
 			dmas[descr_count][j] = TX_DESC_INFO(txring, i+1+j).dma;
 
+		skbs[descr_count] = skb;
+		nf[descr_count] = nr_frags;
+
 		TX_DESC(txring, i) = 0;
 		TX_DESC(txring, i+1) = 0;
 
-		/* 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++;
 	}
 	txring->next_to_clean = i & (TX_RING_SIZE-1);
@@ -802,7 +812,7 @@ restart:
 	netif_wake_queue(mac->netdev);
 
 	for (i = 0; i < descr_count; i++)
-		pasemi_mac_unmap_tx_skb(mac, skbs[i], dmas[i]);
+		pasemi_mac_unmap_tx_skb(mac, nf[i], skbs[i], dmas[i]);
 
 	total_count += descr_count;
 
@@ -1299,6 +1309,7 @@ static int pasemi_mac_start_tx(struct sk
 	}
 
 	TX_DESC(txring, fill) = mactx;
+	TX_DESC_INFO(txring, fill).dma = nfrags;
 	fill++;
 	TX_DESC_INFO(txring, fill).skb = skb;
 	for (i = 0; i <= nfrags; i++) {

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [10/12] pasemi_mac: Remove SKB copy/recycle logic
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (8 preceding siblings ...)
  2007-11-29  2:57 ` [PATCH] [9/12] pasemi_mac: SKB unmap optimization Olof Johansson
@ 2007-11-29  2:57 ` Olof Johansson
  2007-11-29  2:58 ` [PATCH] [11/12] pasemi_mac: Print warning when not attaching to a PHY Olof Johansson
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:57 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: Remove SKB copy/recycle logic

It doesn't really buy us much, since copying is about as expensive
as the allocation in the first place. Just remove it for now.


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


---
 drivers/net/pasemi_mac.c |   25 +++----------------------
 1 file changed, 3 insertions(+), 22 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -503,13 +503,8 @@ static void pasemi_mac_replenish_rx_ring
 		/* Entry in use? */
 		WARN_ON(*buff);
 
-		/* skb might still be in there for recycle on short receives */
-		if (info->skb)
-			skb = info->skb;
-		else {
-			skb = dev_alloc_skb(BUF_SIZE);
-			skb_reserve(skb, LOCAL_SKB_ALIGN);
-		}
+		skb = dev_alloc_skb(BUF_SIZE);
+		skb_reserve(skb, LOCAL_SKB_ALIGN);
 
 		if (unlikely(!skb))
 			break;
@@ -666,21 +661,7 @@ static int pasemi_mac_clean_rx(struct pa
 			goto next;
 		}
 
-		if (len < 256) {
-			struct sk_buff *new_skb;
-
-			new_skb = netdev_alloc_skb(mac->netdev,
-						   len + LOCAL_SKB_ALIGN);
-			if (new_skb) {
-				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;
-			}
-			/* else just continue with the old one */
-		} else
-			info->skb = NULL;
-
+		info->skb = NULL;
 		info->dma = 0;
 
 		if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [11/12] pasemi_mac: Print warning when not attaching to a PHY
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (9 preceding siblings ...)
  2007-11-29  2:57 ` [PATCH] [10/12] pasemi_mac: Remove SKB copy/recycle logic Olof Johansson
@ 2007-11-29  2:58 ` Olof Johansson
  2007-11-29  2:58 ` [PATCH] [12/12] pasemi_mac: Don't enable RX/TX without a link (if possible) Olof Johansson
  2007-11-29  2:59 ` [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:58 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: Print warning when not attaching to a PHY

Print a warning on the console when not connecting to a phy for an interface.
It turns out to be a pretty common problem when someone gets the MDIO info
wrong in their device tree, resulting in the macs running at a fixed 1Gbit FD.

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


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

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -1064,11 +1064,12 @@ static int pasemi_mac_open(struct net_de
 	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
 
 	ret = pasemi_mac_phy_init(dev);
-	/* Some configs don't have PHYs (XAUI etc), so don't complain about
-	 * failed init due to -ENODEV.
+	/* Warn for missing PHY on SGMII (1Gig) ports.
 	 */
-	if (ret && ret != -ENODEV)
-		dev_warn(&mac->pdev->dev, "phy init failed: %d\n", ret);
+	if (ret && mac->type == MAC_TYPE_GMAC) {
+		dev_warn(&mac->pdev->dev, "PHY init failed: %d.\n", ret);
+		dev_warn(&mac->pdev->dev, "Defaulting to 1Gbit full duplex\n");
+	}
 
 	netif_start_queue(dev);
 	napi_enable(&mac->napi);

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] [12/12] pasemi_mac: Don't enable RX/TX without a link (if possible)
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (10 preceding siblings ...)
  2007-11-29  2:58 ` [PATCH] [11/12] pasemi_mac: Print warning when not attaching to a PHY Olof Johansson
@ 2007-11-29  2:58 ` Olof Johansson
  2007-11-29  2:59 ` [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:58 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

pasemi_mac: Don't enable RX/TX without a link (if possible)

Don't enable RX/TX of packets until we have a link, since there's a chance
we'll just get RX frame errors, etc.

The case where we don't have a PHY we can't do much about: Just enable
it and deal with errors as they come in.


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


---
 drivers/net/pasemi_mac.c |   41 +++++++++++++++++++++++++++++++++--------
 1 file changed, 33 insertions(+), 8 deletions(-)

Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -874,6 +874,24 @@ static irqreturn_t pasemi_mac_tx_intr(in
 	return IRQ_HANDLED;
 }
 
+static void pasemi_mac_intf_disable(struct pasemi_mac *mac)
+{
+	unsigned int flags;
+
+	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
+	flags &= ~PAS_MAC_CFG_PCFG_PE;
+	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
+}
+
+static void pasemi_mac_intf_enable(struct pasemi_mac *mac)
+{
+	unsigned int flags;
+
+	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
+	flags |= PAS_MAC_CFG_PCFG_PE;
+	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
+}
+
 static void pasemi_adjust_link(struct net_device *dev)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
@@ -889,11 +907,14 @@ static void pasemi_adjust_link(struct ne
 			printk(KERN_INFO "%s: Link is down.\n", dev->name);
 
 		netif_carrier_off(dev);
+		pasemi_mac_intf_disable(mac);
 		mac->link = 0;
 
 		return;
-	} else
+	} else {
+		pasemi_mac_intf_enable(mac);
 		netif_carrier_on(dev);
+	}
 
 	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
 	new_flags = flags & ~(PAS_MAC_CFG_PCFG_HD | PAS_MAC_CFG_PCFG_SPD_M |
@@ -1052,8 +1073,7 @@ static int pasemi_mac_open(struct net_de
 	pasemi_mac_restart_rx_intr(mac);
 	pasemi_mac_restart_tx_intr(mac);
 
-	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
-		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
+	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
 
 	if (mac->type == MAC_TYPE_GMAC)
 		flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
@@ -1064,11 +1084,16 @@ static int pasemi_mac_open(struct net_de
 	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
 
 	ret = pasemi_mac_phy_init(dev);
-	/* Warn for missing PHY on SGMII (1Gig) ports.
-	 */
-	if (ret && mac->type == MAC_TYPE_GMAC) {
-		dev_warn(&mac->pdev->dev, "PHY init failed: %d.\n", ret);
-		dev_warn(&mac->pdev->dev, "Defaulting to 1Gbit full duplex\n");
+	if (ret) {
+		/* Since we won't get link notification, just enable RX */
+		pasemi_mac_intf_enable(mac);
+		if (mac->type == MAC_TYPE_GMAC) {
+			/* Warn for missing PHY on SGMII (1Gig) ports */
+			dev_warn(&mac->pdev->dev,
+				 "PHY init failed: %d.\n", ret);
+			dev_warn(&mac->pdev->dev,
+				 "Defaulting to 1Gbit full duplex\n");
+		}
 	}
 
 	netif_start_queue(dev);

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library
  2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
                   ` (11 preceding siblings ...)
  2007-11-29  2:58 ` [PATCH] [12/12] pasemi_mac: Don't enable RX/TX without a link (if possible) Olof Johansson
@ 2007-11-29  2:59 ` Olof Johansson
  12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29  2:59 UTC (permalink / raw)
  To: jgarzik; +Cc: linuxppc-dev, netdev

On Wed, Nov 28, 2007 at 08:54:10PM -0600, Olof Johansson wrote:

> The patches are:
[...]

I got the order wrong above, the actual one is:

1/12 pasemi_mac: RX/TX ring management cleanup
2/12 pasemi_mac: Move register definitions to include/asm-powerpc
3/12 pasemi: DMA engine management library
4/12 pasemi_mac: Convert to new dma library
5/12 pasemi_mac: performance tweaks
6/12 pasemi_mac: Fix TX cleaning
7/12 pasemi_mac: Improve RX interrupt mitigation
8/12 pasemi_mac: Software-based LRO support
9/12 pasemi_mac: SKB unmap optimization
10/12 pasemi_mac: Remove SKB copy/recycle logic
11/12 pasemi_mac: Print warning when not attaching to a PHY
12/12 pasemi_mac: Don't enable RX/TX without a link (if possible)

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup
  2007-11-29  2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
@ 2007-12-01 21:54   ` Jeff Garzik
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2007-12-01 21:54 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev, netdev

Olof Johansson wrote:
> pasemi_mac: RX/TX ring management cleanup
> 
> Prepare a bit for supporting multiple TX queues by cleaning up some
> of the ring management and shuffle things around a bit.
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>

applied 1-12

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2007-12-01 21:54 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-29  2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
2007-11-29  2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
2007-12-01 21:54   ` Jeff Garzik
2007-11-29  2:56 ` [PATCH] [2/12] pasemi_mac: Move register definitions to include/asm-powerpc Olof Johansson
2007-11-29  2:56 ` [PATCH] [3/12] pasemi: DMA engine management library Olof Johansson
2007-11-29  2:56 ` [PATCH] [4/12] pasemi_mac: Convert to new dma library Olof Johansson
2007-11-29  2:56 ` [PATCH] [5/12] pasemi_mac: performance tweaks Olof Johansson
2007-11-29  2:56 ` [PATCH] [6/12] pasemi_mac: Fix TX cleaning Olof Johansson
2007-11-29  2:57 ` [PATCH] [7/12] pasemi_mac: Improve RX interrupt mitigation Olof Johansson
2007-11-29  2:57 ` [PATCH] [8/12] pasemi_mac: Software-based LRO support Olof Johansson
2007-11-29  2:57 ` [PATCH] [9/12] pasemi_mac: SKB unmap optimization Olof Johansson
2007-11-29  2:57 ` [PATCH] [10/12] pasemi_mac: Remove SKB copy/recycle logic Olof Johansson
2007-11-29  2:58 ` [PATCH] [11/12] pasemi_mac: Print warning when not attaching to a PHY Olof Johansson
2007-11-29  2:58 ` [PATCH] [12/12] pasemi_mac: Don't enable RX/TX without a link (if possible) Olof Johansson
2007-11-29  2:59 ` [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson

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).