Netdev List
 help / color / mirror / Atom feed
* [git patches] net driver fixes
From: Jeff Garzik @ 2007-10-03 18:40 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: netdev, LKML


sky2 is really the only important fix, the others are trivial.


Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git upstream-linus

to receive the following updates:

 drivers/net/sky2.c                          |    3 ---
 drivers/net/wireless/bcm43xx/bcm43xx_wx.c   |    2 +-
 net/ieee80211/softmac/ieee80211softmac_wx.c |    2 +-
 3 files changed, 2 insertions(+), 5 deletions(-)

Joe Perches (1):
      bcm43xx: Correct printk with PFX before KERN_

Richard Knutsson (1):
      softmac: Fix compiler-warning

Stephen Hemminger (1):
      sky2: jumbo frame regression fix

diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 162489b..ea117fc 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -2163,9 +2163,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
 	sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
 	prefetch(sky2->rx_ring + sky2->rx_next);
 
-	if (length < ETH_ZLEN || length > sky2->rx_data_size)
-		goto len_error;
-
 	/* This chip has hardware problems that generates bogus status.
 	 * So do only marginal checking and expect higher level protocols
 	 * to handle crap frames.
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index d6d9413..6acfdc4 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -444,7 +444,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
 	u16 maxpower;
 
 	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
-		printk(PFX KERN_ERR "TX power not in dBm.\n");
+		printk(KERN_ERR PFX "TX power not in dBm.\n");
 		return -EOPNOTSUPP;
 	}
 
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index 442b987..5742dc8 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -114,7 +114,7 @@ check_assoc_again:
 	sm->associnfo.associating = 1;
 	/* queue lower level code to do work (if necessary) */
 	schedule_delayed_work(&sm->associnfo.work, 0);
-out:
+
 	mutex_unlock(&sm->associnfo.mutex);
 
 	return 0;

^ permalink raw reply related

* [git patches] net driver updates
From: Jeff Garzik @ 2007-10-03 18:39 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, LKML


Normally I wait a day or two between pushes, to queue up patches and
also to avoid annoying my upstream :)  But this includes a couple fixes
I felt should be upstreamed sooner rather than later.


Please pull from 'upstream' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git upstream

to receive the following updates:

Jeff Garzik (1):
      drivers/net/qla3xxx: trim trailing whitespace

Olof Johansson (11):
      pasemi_mac: basic error checking
      pasemi_mac: fix bug in receive buffer dma mapping
      pasemi_mac: rework ring management
      pasemi_mac: implement sg support
      pasemi_mac: workaround for erratum 5971
      pasemi_mac: add local skb alignment
      pasemi_mac: further performance tweaks
      pasemi_mac: update todo list
      pasemi_mac: clear out old errors on interface open
      pasemi_mac: use buffer index pointer in clean_rx()
      pasemi_mac: enable iommu support

trem (1):
      ipg.c doesn't compile with with CONFIG_HIGHMEM64G

vbarshak@ru.mvista.com (1):
      Fix typo in new EMAC driver.

 arch/powerpc/platforms/pasemi/Kconfig |   10 
 arch/powerpc/platforms/pasemi/iommu.c |   15 
 drivers/net/ibm_newemac/core.c        |    4 
 drivers/net/ipg.c                     |   10 
 drivers/net/pasemi_mac.c              |  595 ++++++++++++++++++++++------------
 drivers/net/pasemi_mac.h              |   67 ++-
 drivers/net/qla3xxx.c                 |  128 +++----
 drivers/net/qla3xxx.h                 |    6 
 8 files changed, 527 insertions(+), 308 deletions(-)

diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 95cd90f..e95261e 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -18,6 +18,16 @@ config PPC_PASEMI_IOMMU
 	help
 	  IOMMU support for PA6T-1682M
 
+config PPC_PASEMI_IOMMU_DMA_FORCE
+	bool "Force DMA engine to use IOMMU"
+	depends on PPC_PASEMI_IOMMU
+	help
+	  This option forces the use of the IOMMU also for the
+	  DMA engine. Otherwise the kernel will use it only when
+	  running under a hypervisor.
+
+	  If in doubt, say "N".
+
 config PPC_PASEMI_MDIO
 	depends on PHYLIB
 	tristate "MDIO support via GPIO"
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index 9014d55..a1111b5 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -25,6 +25,7 @@
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
+#include <asm/firmware.h>
 
 
 #define IOBMAP_PAGE_SHIFT	12
@@ -175,13 +176,17 @@ static void pci_dma_dev_setup_pasemi(struct pci_dev *dev)
 {
 	pr_debug("pci_dma_dev_setup, dev %p (%s)\n", dev, pci_name(dev));
 
-	/* DMA device is untranslated, but all other PCI-e goes through
-	 * the IOMMU
+#if !defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
+	/* For non-LPAR environment, don't translate anything for the DMA
+	 * engine. The exception to this is if the user has enabled
+	 * CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE at build time.
 	 */
-	if (dev->vendor == 0x1959 && dev->device == 0xa007)
+	if (dev->vendor == 0x1959 && dev->device == 0xa007 &&
+	    !firmware_has_feature(FW_FEATURE_LPAR))
 		dev->dev.archdata.dma_ops = &dma_direct_ops;
-	else
-		dev->dev.archdata.dma_data = &iommu_table_iobmap;
+#endif
+
+	dev->dev.archdata.dma_data = &iommu_table_iobmap;
 }
 
 static void pci_dma_bus_setup_null(struct pci_bus *b) { }
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 653bfdc..ce127b9 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -1232,9 +1232,9 @@ static inline int emac_xmit_finish(struct emac_instance *dev, int len)
 	 * instead
 	 */
 	if (emac_has_feature(dev, EMAC_FTR_EMAC4))
-		out_be32(&p->tmr0, EMAC_TMR0_XMIT);
-	else
 		out_be32(&p->tmr0, EMAC4_TMR0_XMIT);
+	else
+		out_be32(&p->tmr0, EMAC_TMR0_XMIT);
 
 	if (unlikely(++dev->tx_cnt == NUM_TX_BUFF)) {
 		netif_stop_queue(ndev);
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index dfdc96f..59898ce 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -25,6 +25,8 @@
 #include <linux/mii.h>
 #include <linux/mutex.h>
 
+#include <asm/div64.h>
+
 #define IPG_RX_RING_BYTES	(sizeof(struct ipg_rx) * IPG_RFDLIST_LENGTH)
 #define IPG_TX_RING_BYTES	(sizeof(struct ipg_tx) * IPG_TFDLIST_LENGTH)
 #define IPG_RESET_MASK \
@@ -836,10 +838,14 @@ static void ipg_nic_txfree(struct net_device *dev)
 {
 	struct ipg_nic_private *sp = netdev_priv(dev);
 	void __iomem *ioaddr = sp->ioaddr;
-	const unsigned int curr = ipg_r32(TFD_LIST_PTR_0) -
-		(sp->txd_map / sizeof(struct ipg_tx)) - 1;
+	unsigned int curr;
+	u64 txd_map;
 	unsigned int released, pending;
 
+	txd_map = (u64)sp->txd_map;
+	curr = ipg_r32(TFD_LIST_PTR_0) -
+		do_div(txd_map, sizeof(struct ipg_tx)) - 1;
+
 	IPG_DEBUG_MSG("_nic_txfree\n");
 
 	pending = sp->tx_current - sp->tx_dirty;
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index c2d34a8..9f9a421 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -34,24 +34,29 @@
 #include <net/checksum.h>
 
 #include <asm/irq.h>
+#include <asm/firmware.h>
 
 #include "pasemi_mac.h"
 
+/* We have our own align, since ppc64 in general has it at 0 because
+ * of design flaws in some of the server bridge chips. However, for
+ * PWRficient doing the unaligned copies is more expensive than doing
+ * unaligned DMA, so make sure the data is aligned instead.
+ */
+#define LOCAL_SKB_ALIGN	2
 
 /* TODO list
  *
- * - Get rid of pci_{read,write}_config(), map registers with ioremap
- *   for performance
- * - PHY support
  * - Multicast support
  * - Large MTU support
- * - Other performance improvements
+ * - SW LRO
+ * - Multiqueue RX/TX
  */
 
 
 /* Must be a power of two */
-#define RX_RING_SIZE 512
-#define TX_RING_SIZE 512
+#define RX_RING_SIZE 4096
+#define TX_RING_SIZE 4096
 
 #define DEFAULT_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
@@ -63,10 +68,10 @@
 	 NETIF_MSG_RX_ERR	| \
 	 NETIF_MSG_TX_ERR)
 
-#define TX_DESC(mac, num)	((mac)->tx->desc[(num) & (TX_RING_SIZE-1)])
-#define TX_DESC_INFO(mac, num)	((mac)->tx->desc_info[(num) & (TX_RING_SIZE-1)])
-#define RX_DESC(mac, num)	((mac)->rx->desc[(num) & (RX_RING_SIZE-1)])
-#define RX_DESC_INFO(mac, num)	((mac)->rx->desc_info[(num) & (RX_RING_SIZE-1)])
+#define TX_RING(mac, num)	((mac)->tx->ring[(num) & (TX_RING_SIZE-1)])
+#define TX_RING_INFO(mac, num)	((mac)->tx->ring_info[(num) & (TX_RING_SIZE-1)])
+#define RX_RING(mac, num)	((mac)->rx->ring[(num) & (RX_RING_SIZE-1)])
+#define RX_RING_INFO(mac, num)	((mac)->rx->ring_info[(num) & (RX_RING_SIZE-1)])
 #define RX_BUFF(mac, num)	((mac)->rx->buffers[(num) & (RX_RING_SIZE-1)])
 
 #define RING_USED(ring)		(((ring)->next_to_fill - (ring)->next_to_clean) \
@@ -85,6 +90,15 @@ 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)
+	return 1;
+#else
+	return firmware_has_feature(FW_FEATURE_LPAR);
+#endif
+}
+
 static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg,
 			  unsigned int val)
 {
@@ -160,11 +174,36 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
 	return 0;
 }
 
+static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
+				    struct sk_buff *skb,
+				    dma_addr_t *dmas)
+{
+	int f;
+	int nfrags = skb_shinfo(skb)->nr_frags;
+
+	pci_unmap_single(mac->dma_pdev, dmas[0], skb_headlen(skb),
+			 PCI_DMA_TODEVICE);
+
+	for (f = 0; f < nfrags; f++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
+
+		pci_unmap_page(mac->dma_pdev, dmas[f+1], frag->size,
+			       PCI_DMA_TODEVICE);
+	}
+	dev_kfree_skb_irq(skb);
+
+	/* Freed descriptor slot + main SKB ptr + nfrags additional ptrs,
+	 * aligned up to a power of 2
+	 */
+	return (nfrags + 3) & ~1;
+}
+
 static int pasemi_mac_setup_rx_resources(struct net_device *dev)
 {
 	struct pasemi_mac_rxring *ring;
 	struct pasemi_mac *mac = netdev_priv(dev);
 	int chan_id = mac->dma_rxch;
+	unsigned int cfg;
 
 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 
@@ -174,22 +213,21 @@ static int pasemi_mac_setup_rx_resources(struct net_device *dev)
 	spin_lock_init(&ring->lock);
 
 	ring->size = RX_RING_SIZE;
-	ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
+	ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
 				  RX_RING_SIZE, GFP_KERNEL);
 
-	if (!ring->desc_info)
-		goto out_desc_info;
+	if (!ring->ring_info)
+		goto out_ring_info;
 
 	/* Allocate descriptors */
-	ring->desc = dma_alloc_coherent(&mac->dma_pdev->dev,
-					RX_RING_SIZE *
-					sizeof(struct pas_dma_xct_descr),
+	ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
+					RX_RING_SIZE * sizeof(u64),
 					&ring->dma, GFP_KERNEL);
 
-	if (!ring->desc)
-		goto out_desc;
+	if (!ring->ring)
+		goto out_ring_desc;
 
-	memset(ring->desc, 0, RX_RING_SIZE * sizeof(struct pas_dma_xct_descr));
+	memset(ring->ring, 0, RX_RING_SIZE * sizeof(u64));
 
 	ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
 					   RX_RING_SIZE * sizeof(u64),
@@ -203,20 +241,30 @@ static int pasemi_mac_setup_rx_resources(struct net_device *dev)
 
 	write_dma_reg(mac, PAS_DMA_RXCHAN_BASEU(chan_id),
 			   PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) |
-			   PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 2));
+			   PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-	write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id),
-			   PAS_DMA_RXCHAN_CFG_HBU(2));
+	cfg = PAS_DMA_RXCHAN_CFG_HBU(2);
+
+	if (translation_enabled())
+		cfg |= PAS_DMA_RXCHAN_CFG_CTR;
+
+	write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id), cfg);
 
 	write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if),
-			   PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers)));
+			   PAS_DMA_RXINT_BASEL_BRBL(ring->buf_dma));
 
 	write_dma_reg(mac, PAS_DMA_RXINT_BASEU(mac->dma_if),
-			   PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) |
+			   PAS_DMA_RXINT_BASEU_BRBH(ring->buf_dma >> 32) |
 			   PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-	write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if),
-			   PAS_DMA_RXINT_CFG_DHL(2));
+	cfg = PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 |
+	      PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP |
+	      PAS_DMA_RXINT_CFG_HEN;
+
+	if (translation_enabled())
+		cfg |= PAS_DMA_RXINT_CFG_ITRR | PAS_DMA_RXINT_CFG_ITR;
+
+	write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if), cfg);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
@@ -229,11 +277,11 @@ static int pasemi_mac_setup_rx_resources(struct net_device *dev)
 
 out_buffers:
 	dma_free_coherent(&mac->dma_pdev->dev,
-			  RX_RING_SIZE * sizeof(struct pas_dma_xct_descr),
-			  mac->rx->desc, mac->rx->dma);
-out_desc:
-	kfree(ring->desc_info);
-out_desc_info:
+			  RX_RING_SIZE * sizeof(u64),
+			  mac->rx->ring, mac->rx->dma);
+out_ring_desc:
+	kfree(ring->ring_info);
+out_ring_info:
 	kfree(ring);
 out_ring:
 	return -ENOMEM;
@@ -246,6 +294,7 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev)
 	u32 val;
 	int chan_id = mac->dma_txch;
 	struct pasemi_mac_txring *ring;
+	unsigned int cfg;
 
 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 	if (!ring)
@@ -254,33 +303,36 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev)
 	spin_lock_init(&ring->lock);
 
 	ring->size = TX_RING_SIZE;
-	ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
+	ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
 				  TX_RING_SIZE, GFP_KERNEL);
-	if (!ring->desc_info)
-		goto out_desc_info;
+	if (!ring->ring_info)
+		goto out_ring_info;
 
 	/* Allocate descriptors */
-	ring->desc = dma_alloc_coherent(&mac->dma_pdev->dev,
-					TX_RING_SIZE *
-					sizeof(struct pas_dma_xct_descr),
+	ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
+					TX_RING_SIZE * sizeof(u64),
 					&ring->dma, GFP_KERNEL);
-	if (!ring->desc)
-		goto out_desc;
+	if (!ring->ring)
+		goto out_ring_desc;
 
-	memset(ring->desc, 0, TX_RING_SIZE * sizeof(struct pas_dma_xct_descr));
+	memset(ring->ring, 0, TX_RING_SIZE * sizeof(u64));
 
 	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEL(chan_id),
 			   PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma));
 	val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->dma >> 32);
-	val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 2);
+	val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 3);
 
 	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val);
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id),
-			   PAS_DMA_TXCHAN_CFG_TY_IFACE |
-			   PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
-			   PAS_DMA_TXCHAN_CFG_UP |
-			   PAS_DMA_TXCHAN_CFG_WT(2));
+	cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
+	      PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
+	      PAS_DMA_TXCHAN_CFG_UP |
+	      PAS_DMA_TXCHAN_CFG_WT(2);
+
+	if (translation_enabled())
+		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
+
+	write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id), cfg);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
@@ -291,9 +343,9 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev)
 
 	return 0;
 
-out_desc:
-	kfree(ring->desc_info);
-out_desc_info:
+out_ring_desc:
+	kfree(ring->ring_info);
+out_ring_info:
 	kfree(ring);
 out_ring:
 	return -ENOMEM;
@@ -302,33 +354,37 @@ out_ring:
 static void pasemi_mac_free_tx_resources(struct net_device *dev)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
-	unsigned int i;
+	unsigned int i, j;
 	struct pasemi_mac_buffer *info;
-	struct pas_dma_xct_descr *dp;
-
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		info = &TX_DESC_INFO(mac, i);
-		dp = &TX_DESC(mac, i);
-		if (info->dma) {
-			if (info->skb) {
-				pci_unmap_single(mac->dma_pdev,
-						 info->dma,
-						 info->skb->len,
-						 PCI_DMA_TODEVICE);
-				dev_kfree_skb_any(info->skb);
-			}
-			info->dma = 0;
-			info->skb = NULL;
-			dp->mactx = 0;
-			dp->ptr = 0;
-		}
+	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;
+
+	/* Compensate for when fill has wrapped and clean has not */
+	if (start > limit)
+		limit += TX_RING_SIZE;
+
+	for (i = start; i < limit; i += freed) {
+		info = &TX_RING_INFO(mac, i+1);
+		if (info->dma && info->skb) {
+			for (j = 0; j <= skb_shinfo(info->skb)->nr_frags; j++)
+				dmas[j] = TX_RING_INFO(mac, i+1+j).dma;
+			freed = pasemi_mac_unmap_tx_skb(mac, info->skb, dmas);
+		} else
+			freed = 2;
 	}
 
+	for (i = 0; i < TX_RING_SIZE; i++)
+		TX_RING(mac, i) = 0;
+
 	dma_free_coherent(&mac->dma_pdev->dev,
-			  TX_RING_SIZE * sizeof(struct pas_dma_xct_descr),
-			  mac->tx->desc, mac->tx->dma);
+			  TX_RING_SIZE * sizeof(u64),
+			  mac->tx->ring, mac->tx->dma);
 
-	kfree(mac->tx->desc_info);
+	kfree(mac->tx->ring_info);
 	kfree(mac->tx);
 	mac->tx = NULL;
 }
@@ -338,34 +394,31 @@ static void pasemi_mac_free_rx_resources(struct net_device *dev)
 	struct pasemi_mac *mac = netdev_priv(dev);
 	unsigned int i;
 	struct pasemi_mac_buffer *info;
-	struct pas_dma_xct_descr *dp;
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		info = &RX_DESC_INFO(mac, i);
-		dp = &RX_DESC(mac, i);
-		if (info->skb) {
-			if (info->dma) {
-				pci_unmap_single(mac->dma_pdev,
-						 info->dma,
-						 info->skb->len,
-						 PCI_DMA_FROMDEVICE);
-				dev_kfree_skb_any(info->skb);
-			}
-			info->dma = 0;
-			info->skb = NULL;
-			dp->macrx = 0;
-			dp->ptr = 0;
+		info = &RX_RING_INFO(mac, i);
+		if (info->skb && info->dma) {
+			pci_unmap_single(mac->dma_pdev,
+					 info->dma,
+					 info->skb->len,
+					 PCI_DMA_FROMDEVICE);
+			dev_kfree_skb_any(info->skb);
 		}
+		info->dma = 0;
+		info->skb = NULL;
 	}
 
+	for (i = 0; i < RX_RING_SIZE; i++)
+		RX_RING(mac, i) = 0;
+
 	dma_free_coherent(&mac->dma_pdev->dev,
-			  RX_RING_SIZE * sizeof(struct pas_dma_xct_descr),
-			  mac->rx->desc, mac->rx->dma);
+			  RX_RING_SIZE * sizeof(u64),
+			  mac->rx->ring, mac->rx->dma);
 
 	dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
 			  mac->rx->buffers, mac->rx->buf_dma);
 
-	kfree(mac->rx->desc_info);
+	kfree(mac->rx->ring_info);
 	kfree(mac->rx);
 	mac->rx = NULL;
 }
@@ -373,30 +426,34 @@ static void pasemi_mac_free_rx_resources(struct net_device *dev)
 static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
-	unsigned int i;
-	int start = mac->rx->next_to_fill;
-	int count;
+	int fill, count;
 
 	if (limit <= 0)
 		return;
 
-	i = start;
+	fill = mac->rx->next_to_fill;
 	for (count = 0; count < limit; count++) {
-		struct pasemi_mac_buffer *info = &RX_DESC_INFO(mac, i);
-		u64 *buff = &RX_BUFF(mac, i);
+		struct pasemi_mac_buffer *info = &RX_RING_INFO(mac, fill);
+		u64 *buff = &RX_BUFF(mac, fill);
 		struct sk_buff *skb;
 		dma_addr_t dma;
 
+		/* Entry in use? */
+		WARN_ON(*buff);
+
 		/* skb might still be in there for recycle on short receives */
 		if (info->skb)
 			skb = info->skb;
-		else
+		else {
 			skb = dev_alloc_skb(BUF_SIZE);
+			skb_reserve(skb, LOCAL_SKB_ALIGN);
+		}
 
 		if (unlikely(!skb))
 			break;
 
-		dma = pci_map_single(mac->dma_pdev, skb->data, skb->len,
+		dma = pci_map_single(mac->dma_pdev, skb->data,
+				     BUF_SIZE - LOCAL_SKB_ALIGN,
 				     PCI_DMA_FROMDEVICE);
 
 		if (unlikely(dma_mapping_error(dma))) {
@@ -407,15 +464,15 @@ static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
 		info->skb = skb;
 		info->dma = dma;
 		*buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma);
-		i++;
+		fill++;
 	}
 
 	wmb();
 
-	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), count);
 	write_dma_reg(mac, PAS_DMA_RXINT_INCR(mac->dma_if), count);
 
-	mac->rx->next_to_fill += count;
+	mac->rx->next_to_fill = (mac->rx->next_to_fill + count) &
+				(RX_RING_SIZE - 1);
 }
 
 static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
@@ -445,64 +502,91 @@ static void pasemi_mac_restart_tx_intr(struct pasemi_mac *mac)
 }
 
 
+static inline void pasemi_mac_rx_error(struct pasemi_mac *mac, u64 macrx)
+{
+	unsigned int rcmdsta, ccmdsta;
+
+	if (!netif_msg_rx_err(mac))
+		return;
+
+	rcmdsta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+	ccmdsta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
+
+	printk(KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n",
+		macrx, *mac->rx_status);
+
+	printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n",
+		rcmdsta, ccmdsta);
+}
+
+static inline void pasemi_mac_tx_error(struct pasemi_mac *mac, u64 mactx)
+{
+	unsigned int cmdsta;
+
+	if (!netif_msg_tx_err(mac))
+		return;
+
+	cmdsta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
+
+	printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, "\
+		"tx status 0x%016lx\n", mactx, *mac->tx_status);
+
+	printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta);
+}
+
 static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
 {
 	unsigned int n;
 	int count;
-	struct pas_dma_xct_descr *dp;
 	struct pasemi_mac_buffer *info;
 	struct sk_buff *skb;
-	unsigned int i, len;
+	unsigned int len;
 	u64 macrx;
 	dma_addr_t dma;
+	int buf_index;
+	u64 eval;
 
 	spin_lock(&mac->rx->lock);
 
 	n = mac->rx->next_to_clean;
 
-	for (count = limit; count; count--) {
+	prefetch(RX_RING(mac, n));
 
-		rmb();
+	for (count = 0; count < limit; count++) {
+		macrx = RX_RING(mac, n);
 
-		dp = &RX_DESC(mac, n);
-		prefetchw(dp);
-		macrx = dp->macrx;
+		if ((macrx & XCT_MACRX_E) ||
+		    (*mac->rx_status & PAS_STATUS_ERROR))
+			pasemi_mac_rx_error(mac, macrx);
 
 		if (!(macrx & XCT_MACRX_O))
 			break;
 
-
 		info = NULL;
 
-		/* We have to scan for our skb since there's no way
-		 * to back-map them from the descriptor, and if we
-		 * have several receive channels then they might not
-		 * show up in the same order as they were put on the
-		 * interface ring.
-		 */
+		BUG_ON(!(macrx & XCT_MACRX_RR_8BRES));
 
-		dma = (dp->ptr & XCT_PTR_ADDR_M);
-		for (i = n; i < (n + RX_RING_SIZE); i++) {
-			info = &RX_DESC_INFO(mac, i);
-			if (info->dma == dma)
-				break;
-		}
-		prefetchw(info);
+		eval = (RX_RING(mac, n+1) & XCT_RXRES_8B_EVAL_M) >>
+			XCT_RXRES_8B_EVAL_S;
+		buf_index = eval-1;
+
+		dma = (RX_RING(mac, n+2) & XCT_PTR_ADDR_M);
+		info = &RX_RING_INFO(mac, buf_index);
 
 		skb = info->skb;
-		prefetchw(skb);
-		info->dma = 0;
 
-		pci_unmap_single(mac->dma_pdev, dma, skb->len,
-				 PCI_DMA_FROMDEVICE);
+		prefetch(skb);
+		prefetch(&skb->data_len);
 
 		len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
 
 		if (len < 256) {
-			struct sk_buff *new_skb =
-			    netdev_alloc_skb(mac->netdev, len + NET_IP_ALIGN);
+			struct sk_buff *new_skb;
+
+			new_skb = netdev_alloc_skb(mac->netdev,
+						   len + LOCAL_SKB_ALIGN);
 			if (new_skb) {
-				skb_reserve(new_skb, NET_IP_ALIGN);
+				skb_reserve(new_skb, LOCAL_SKB_ALIGN);
 				memcpy(new_skb->data, skb->data, len);
 				/* save the skb in buffer_info as good */
 				skb = new_skb;
@@ -511,6 +595,10 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
 		} else
 			info->skb = NULL;
 
+		pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE);
+
+		info->dma = 0;
+
 		skb_put(skb, len);
 
 		if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {
@@ -526,72 +614,109 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
 		skb->protocol = eth_type_trans(skb, mac->netdev);
 		netif_receive_skb(skb);
 
-		dp->ptr = 0;
-		dp->macrx = 0;
+		RX_RING(mac, n) = 0;
+		RX_RING(mac, n+1) = 0;
 
-		n++;
+		/* 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;
+
+		n += 4;
+	}
+
+	if (n > RX_RING_SIZE) {
+		/* Errata 5971 workaround: L2 target of headers */
+		write_iob_reg(mac, PAS_IOB_COM_PKTHDRCNT, 0);
+		n &= (RX_RING_SIZE-1);
 	}
 
-	mac->rx->next_to_clean += limit - count;
-	pasemi_mac_replenish_rx_ring(mac->netdev, limit-count);
+	mac->rx->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
+	 * count*2.
+	 */
+	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), count << 1);
+
+	pasemi_mac_replenish_rx_ring(mac->netdev, count);
 
 	spin_unlock(&mac->rx->lock);
 
 	return count;
 }
 
+/* Can't make this too large or we blow the kernel stack limits */
+#define TX_CLEAN_BATCHSIZE (128/MAX_SKB_FRAGS)
+
 static int pasemi_mac_clean_tx(struct pasemi_mac *mac)
 {
-	int i;
-	struct pasemi_mac_buffer *info;
-	struct pas_dma_xct_descr *dp;
-	unsigned int start, count, limit;
+	int i, j;
+	unsigned int start, descr_count, buf_count, batch_limit;
+	unsigned int ring_limit;
 	unsigned int total_count;
 	unsigned long flags;
-	struct sk_buff *skbs[32];
-	dma_addr_t dmas[32];
+	struct sk_buff *skbs[TX_CLEAN_BATCHSIZE];
+	dma_addr_t dmas[TX_CLEAN_BATCHSIZE][MAX_SKB_FRAGS+1];
 
 	total_count = 0;
+	batch_limit = TX_CLEAN_BATCHSIZE;
 restart:
 	spin_lock_irqsave(&mac->tx->lock, flags);
 
 	start = mac->tx->next_to_clean;
-	limit = min(mac->tx->next_to_fill, start+32);
+	ring_limit = mac->tx->next_to_fill;
 
-	count = 0;
+	/* Compensate for when fill has wrapped but clean has not */
+	if (start > ring_limit)
+		ring_limit += TX_RING_SIZE;
+
+	buf_count = 0;
+	descr_count = 0;
+
+	for (i = start;
+	     descr_count < batch_limit && i < ring_limit;
+	     i += buf_count) {
+		u64 mactx = TX_RING(mac, i);
+		struct sk_buff *skb;
 
-	for (i = start; i < limit; i++) {
-		dp = &TX_DESC(mac, i);
+		if ((mactx  & XCT_MACTX_E) ||
+		    (*mac->tx_status & PAS_STATUS_ERROR))
+			pasemi_mac_tx_error(mac, mactx);
 
-		if (unlikely(dp->mactx & XCT_MACTX_O))
+		if (unlikely(mactx & XCT_MACTX_O))
 			/* Not yet transmitted */
 			break;
 
-		info = &TX_DESC_INFO(mac, i);
-		skbs[count] = info->skb;
-		dmas[count] = info->dma;
+		skb = TX_RING_INFO(mac, i+1).skb;
+		skbs[descr_count] = skb;
 
-		info->skb = NULL;
-		info->dma = 0;
-		dp->mactx = 0;
-		dp->ptr = 0;
+		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;
+
+		TX_RING(mac, i) = 0;
+		TX_RING(mac, i+1) = 0;
 
-		count++;
+		/* Since we always fill with an even number of entries, make
+		 * sure we skip any unused one at the end as well.
+		 */
+		if (buf_count & 1)
+			buf_count++;
+		descr_count++;
 	}
-	mac->tx->next_to_clean += count;
+	mac->tx->next_to_clean = i & (TX_RING_SIZE-1);
+
 	spin_unlock_irqrestore(&mac->tx->lock, flags);
 	netif_wake_queue(mac->netdev);
 
-	for (i = 0; i < count; i++) {
-		pci_unmap_single(mac->dma_pdev, dmas[i],
-				 skbs[i]->len, PCI_DMA_TODEVICE);
-		dev_kfree_skb_irq(skbs[i]);
-	}
+	for (i = 0; i < descr_count; i++)
+		pasemi_mac_unmap_tx_skb(mac, skbs[i], dmas[i]);
 
-	total_count += count;
+	total_count += descr_count;
 
 	/* If the batch was full, try to clean more */
-	if (count == 32)
+	if (descr_count == batch_limit)
 		goto restart;
 
 	return total_count;
@@ -607,9 +732,6 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
 	if (!(*mac->rx_status & PAS_STATUS_CAUSE_M))
 		return IRQ_NONE;
 
-	if (*mac->rx_status & PAS_STATUS_ERROR)
-		printk("rx_status reported error\n");
-
 	/* Don't reset packet count so it won't fire again but clear
 	 * all others.
 	 */
@@ -809,19 +931,32 @@ static int pasemi_mac_open(struct net_device *dev)
 
 	/* enable rx if */
 	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
-			   PAS_DMA_RXINT_RCMDSTA_EN);
+			   PAS_DMA_RXINT_RCMDSTA_EN |
+			   PAS_DMA_RXINT_RCMDSTA_DROPS_M |
+			   PAS_DMA_RXINT_RCMDSTA_BP |
+			   PAS_DMA_RXINT_RCMDSTA_OO |
+			   PAS_DMA_RXINT_RCMDSTA_BT);
 
 	/* enable rx channel */
 	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
 			   PAS_DMA_RXCHAN_CCMDSTA_EN |
-			   PAS_DMA_RXCHAN_CCMDSTA_DU);
+			   PAS_DMA_RXCHAN_CCMDSTA_DU |
+			   PAS_DMA_RXCHAN_CCMDSTA_OD |
+			   PAS_DMA_RXCHAN_CCMDSTA_FD |
+			   PAS_DMA_RXCHAN_CCMDSTA_DT);
 
 	/* enable tx channel */
 	write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
-			   PAS_DMA_TXCHAN_TCMDSTA_EN);
+			   PAS_DMA_TXCHAN_TCMDSTA_EN |
+			   PAS_DMA_TXCHAN_TCMDSTA_SZ |
+			   PAS_DMA_TXCHAN_TCMDSTA_DB |
+			   PAS_DMA_TXCHAN_TCMDSTA_DE |
+			   PAS_DMA_TXCHAN_TCMDSTA_DA);
 
 	pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE);
 
+	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), RX_RING_SIZE>>1);
+
 	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
 		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
 
@@ -893,7 +1028,7 @@ out_rx_resources:
 static int pasemi_mac_close(struct net_device *dev)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
-	unsigned int stat;
+	unsigned int sta;
 	int retries;
 
 	if (mac->phydev) {
@@ -904,6 +1039,26 @@ static int pasemi_mac_close(struct net_device *dev)
 	netif_stop_queue(dev);
 	napi_disable(&mac->napi);
 
+	sta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+	if (sta & (PAS_DMA_RXINT_RCMDSTA_BP |
+		      PAS_DMA_RXINT_RCMDSTA_OO |
+		      PAS_DMA_RXINT_RCMDSTA_BT))
+		printk(KERN_DEBUG "pasemi_mac: rcmdsta error: 0x%08x\n", sta);
+
+	sta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
+	if (sta & (PAS_DMA_RXCHAN_CCMDSTA_DU |
+		     PAS_DMA_RXCHAN_CCMDSTA_OD |
+		     PAS_DMA_RXCHAN_CCMDSTA_FD |
+		     PAS_DMA_RXCHAN_CCMDSTA_DT))
+		printk(KERN_DEBUG "pasemi_mac: ccmdsta error: 0x%08x\n", sta);
+
+	sta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
+	if (sta & (PAS_DMA_TXCHAN_TCMDSTA_SZ |
+		      PAS_DMA_TXCHAN_TCMDSTA_DB |
+		      PAS_DMA_TXCHAN_TCMDSTA_DE |
+		      PAS_DMA_TXCHAN_TCMDSTA_DA))
+		printk(KERN_DEBUG "pasemi_mac: tcmdsta error: 0x%08x\n", sta);
+
 	/* Clean out any pending buffers */
 	pasemi_mac_clean_tx(mac);
 	pasemi_mac_clean_rx(mac, RX_RING_SIZE);
@@ -914,33 +1069,33 @@ static int pasemi_mac_close(struct net_device *dev)
 	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), PAS_DMA_RXCHAN_CCMDSTA_ST);
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
-		stat = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
-		if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT))
+		sta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
+		if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT))
 			break;
 		cond_resched();
 	}
 
-	if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
+	if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)
 		dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
-		stat = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
-		if (!(stat & PAS_DMA_RXCHAN_CCMDSTA_ACT))
+		sta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
+		if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT))
 			break;
 		cond_resched();
 	}
 
-	if (stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)
+	if (sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)
 		dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
 
 	for (retries = 0; retries < MAX_RETRIES; retries++) {
-		stat = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
-		if (!(stat & PAS_DMA_RXINT_RCMDSTA_ACT))
+		sta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+		if (!(sta & PAS_DMA_RXINT_RCMDSTA_ACT))
 			break;
 		cond_resched();
 	}
 
-	if (stat & PAS_DMA_RXINT_RCMDSTA_ACT)
+	if (sta & PAS_DMA_RXINT_RCMDSTA_ACT)
 		dev_err(&mac->dma_pdev->dev, "Failed to stop rx interface\n");
 
 	/* Then, disable the channel. This must be done separately from
@@ -965,11 +1120,11 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	struct pasemi_mac_txring *txring;
-	struct pasemi_mac_buffer *info;
-	struct pas_dma_xct_descr *dp;
-	u64 dflags, mactx, ptr;
-	dma_addr_t map;
+	u64 dflags, mactx;
+	dma_addr_t map[MAX_SKB_FRAGS+1];
+	unsigned int map_size[MAX_SKB_FRAGS+1];
 	unsigned long flags;
+	int i, nfrags;
 
 	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_SS | XCT_MACTX_CRC_PAD;
 
@@ -990,54 +1145,78 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
 		}
 	}
 
-	map = pci_map_single(mac->dma_pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+	nfrags = skb_shinfo(skb)->nr_frags;
+
+	map[0] = pci_map_single(mac->dma_pdev, skb->data, skb_headlen(skb),
+				PCI_DMA_TODEVICE);
+	map_size[0] = skb_headlen(skb);
+	if (dma_mapping_error(map[0]))
+		goto out_err_nolock;
 
-	if (dma_mapping_error(map))
-		return NETDEV_TX_BUSY;
+	for (i = 0; i < nfrags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+		map[i+1] = pci_map_page(mac->dma_pdev, frag->page,
+					frag->page_offset, frag->size,
+					PCI_DMA_TODEVICE);
+		map_size[i+1] = frag->size;
+		if (dma_mapping_error(map[i+1])) {
+			nfrags = i;
+			goto out_err_nolock;
+		}
+	}
 
 	mactx = dflags | XCT_MACTX_LLEN(skb->len);
-	ptr   = XCT_PTR_LEN(skb->len) | XCT_PTR_ADDR(map);
 
 	txring = mac->tx;
 
 	spin_lock_irqsave(&txring->lock, flags);
 
-	if (RING_AVAIL(txring) <= 1) {
-		spin_unlock_irqrestore(&txring->lock, flags);
-		pasemi_mac_clean_tx(mac);
-		pasemi_mac_restart_tx_intr(mac);
-		spin_lock_irqsave(&txring->lock, flags);
-
-		if (RING_AVAIL(txring) <= 1) {
-			/* Still no room -- stop the queue and wait for tx
-			 * intr when there's room.
-			 */
-			netif_stop_queue(dev);
-			goto out_err;
-		}
+	/* Avoid stepping on the same cache line that the DMA controller
+	 * is currently about to send, so leave at least 8 words available.
+	 * Total free space needed is mactx + fragments + 8
+	 */
+	if (RING_AVAIL(txring) < nfrags + 10) {
+		/* no room -- stop the queue and wait for tx intr */
+		netif_stop_queue(dev);
+		goto out_err;
+	}
+
+	TX_RING(mac, txring->next_to_fill) = mactx;
+	txring->next_to_fill++;
+	TX_RING_INFO(mac, txring->next_to_fill).skb = skb;
+	for (i = 0; i <= nfrags; i++) {
+		TX_RING(mac, txring->next_to_fill+i) =
+		XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
+		TX_RING_INFO(mac, txring->next_to_fill+i).dma = map[i];
 	}
 
-	dp = &TX_DESC(mac, txring->next_to_fill);
-	info = &TX_DESC_INFO(mac, txring->next_to_fill);
+	/* We have to add an even number of 8-byte entries to the ring
+	 * even if the last one is unused. That means always an odd number
+	 * of pointers + one mactx descriptor.
+	 */
+	if (nfrags & 1)
+		nfrags++;
 
-	dp->mactx = mactx;
-	dp->ptr   = ptr;
-	info->dma = map;
-	info->skb = skb;
+	txring->next_to_fill = (txring->next_to_fill + nfrags + 1) &
+				(TX_RING_SIZE-1);
 
-	txring->next_to_fill++;
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
 
 	spin_unlock_irqrestore(&txring->lock, flags);
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_INCR(mac->dma_txch), 1);
+	write_dma_reg(mac, PAS_DMA_TXCHAN_INCR(mac->dma_txch), (nfrags+2) >> 1);
 
 	return NETDEV_TX_OK;
 
 out_err:
 	spin_unlock_irqrestore(&txring->lock, flags);
-	pci_unmap_single(mac->dma_pdev, map, skb->len, PCI_DMA_TODEVICE);
+out_err_nolock:
+	while (nfrags--)
+		pci_unmap_single(mac->dma_pdev, map[nfrags], map_size[nfrags],
+				 PCI_DMA_TODEVICE);
+
 	return NETDEV_TX_BUSY;
 }
 
@@ -1173,7 +1352,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
 
-	dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
+	dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX | NETIF_F_SG;
 
 	/* These should come out of the device tree eventually */
 	mac->dma_txch = index;
@@ -1230,7 +1409,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev_err(&mac->pdev->dev, "register_netdev failed with error %d\n",
 			err);
 		goto out;
-	} else
+	} else if netif_msg_probe(mac)
 		printk(KERN_INFO "%s: PA Semi %s: intf %d, txch %d, rxch %d, "
 		       "hw addr %s\n",
 		       dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
index c52cfcb..60368df 100644
--- a/drivers/net/pasemi_mac.h
+++ b/drivers/net/pasemi_mac.h
@@ -28,25 +28,25 @@
 
 struct pasemi_mac_txring {
 	spinlock_t	 lock;
-	struct pas_dma_xct_descr	*desc;
+	u64		*ring;
 	dma_addr_t	 dma;
 	unsigned int	 size;
 	unsigned int	 next_to_fill;
 	unsigned int	 next_to_clean;
-	struct pasemi_mac_buffer *desc_info;
+	struct pasemi_mac_buffer *ring_info;
 	char		 irq_name[10];  /* "eth%d tx" */
 };
 
 struct pasemi_mac_rxring {
 	spinlock_t	 lock;
-	struct pas_dma_xct_descr	*desc;	/* RX channel descriptor ring */
+	u64		*ring;	/* RX channel descriptor ring */
 	dma_addr_t	 dma;
 	u64		*buffers;	/* RX interface buffer ring */
 	dma_addr_t	 buf_dma;
 	unsigned int	 size;
 	unsigned int	 next_to_fill;
 	unsigned int	 next_to_clean;
-	struct pasemi_mac_buffer *desc_info;
+	struct pasemi_mac_buffer *ring_info;
 	char		 irq_name[10];  /* "eth%d rx" */
 };
 
@@ -88,7 +88,7 @@ struct pasemi_mac {
 	char	phy_id[BUS_ID_SIZE];
 };
 
-/* Software status descriptor (desc_info) */
+/* Software status descriptor (ring_info) */
 struct pasemi_mac_buffer {
 	struct sk_buff *skb;
 	dma_addr_t	dma;
@@ -101,20 +101,7 @@ struct pasdma_status {
 	u64 tx_sta[20];
 };
 
-/* descriptor structure */
-struct pas_dma_xct_descr {
-	union {
-		u64	mactx;
-		u64	macrx;
-	};
-	union {
-		u64	ptr;
-		u64	rxb;
-	};
-};
-
 /* MAC CFG register offsets */
-
 enum {
 	PAS_MAC_CFG_PCFG = 0x80,
 	PAS_MAC_CFG_TXP = 0x98,
@@ -219,10 +206,16 @@ enum {
 #define    PAS_DMA_RXINT_RCMDSTA_DROPS_M	0xfffe0000
 #define    PAS_DMA_RXINT_RCMDSTA_DROPS_S	17
 #define PAS_DMA_RXINT_CFG(i)		(0x204+(i)*_PAS_DMA_RXINT_STRIDE)
+#define    PAS_DMA_RXINT_CFG_RBP	0x80000000
+#define    PAS_DMA_RXINT_CFG_ITRR	0x40000000
 #define    PAS_DMA_RXINT_CFG_DHL_M	0x07000000
 #define    PAS_DMA_RXINT_CFG_DHL_S	24
 #define    PAS_DMA_RXINT_CFG_DHL(x)	(((x) << PAS_DMA_RXINT_CFG_DHL_S) & \
 					 PAS_DMA_RXINT_CFG_DHL_M)
+#define    PAS_DMA_RXINT_CFG_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
 
@@ -252,6 +245,10 @@ enum {
 #define    PAS_DMA_TXCHAN_TCMDSTA_EN	0x00000001	/* Enabled */
 #define    PAS_DMA_TXCHAN_TCMDSTA_ST	0x00000002	/* Stop interface */
 #define    PAS_DMA_TXCHAN_TCMDSTA_ACT	0x00010000	/* Active */
+#define    PAS_DMA_TXCHAN_TCMDSTA_SZ	0x00000800
+#define    PAS_DMA_TXCHAN_TCMDSTA_DB	0x00000400
+#define    PAS_DMA_TXCHAN_TCMDSTA_DE	0x00000200
+#define    PAS_DMA_TXCHAN_TCMDSTA_DA	0x00000100
 #define PAS_DMA_TXCHAN_CFG(c)     (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define    PAS_DMA_TXCHAN_CFG_TY_IFACE	0x00000000	/* Type = interface */
 #define    PAS_DMA_TXCHAN_CFG_TATTR_M	0x0000003c
@@ -262,9 +259,11 @@ enum {
 #define    PAS_DMA_TXCHAN_CFG_WT_S	6
 #define    PAS_DMA_TXCHAN_CFG_WT(x)	(((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
 					 PAS_DMA_TXCHAN_CFG_WT_M)
-#define    PAS_DMA_TXCHAN_CFG_CF	0x00001000	/* Clean first line */
-#define    PAS_DMA_TXCHAN_CFG_CL	0x00002000	/* Clean last line */
+#define    PAS_DMA_TXCHAN_CFG_TRD	0x00010000	/* translate data */
+#define    PAS_DMA_TXCHAN_CFG_TRR	0x00008000	/* translate rings */
 #define    PAS_DMA_TXCHAN_CFG_UP	0x00004000	/* update tx descr when sent */
+#define    PAS_DMA_TXCHAN_CFG_CL	0x00002000	/* Clean last line */
+#define    PAS_DMA_TXCHAN_CFG_CF	0x00001000	/* Clean first line */
 #define PAS_DMA_TXCHAN_INCR(c)    (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define PAS_DMA_TXCHAN_BASEL(c)   (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define    PAS_DMA_TXCHAN_BASEL_BRBL_M	0xffffffc0
@@ -294,7 +293,11 @@ enum {
 #define    PAS_DMA_RXCHAN_CCMDSTA_ST	0x00000002	/* Stop interface */
 #define    PAS_DMA_RXCHAN_CCMDSTA_ACT	0x00010000	/* Active */
 #define    PAS_DMA_RXCHAN_CCMDSTA_DU	0x00020000
+#define    PAS_DMA_RXCHAN_CCMDSTA_OD	0x00002000
+#define    PAS_DMA_RXCHAN_CCMDSTA_FD	0x00001000
+#define    PAS_DMA_RXCHAN_CCMDSTA_DT	0x00000800
 #define PAS_DMA_RXCHAN_CFG(c)     (0x804+(c)*_PAS_DMA_RXCHAN_STRIDE)
+#define    PAS_DMA_RXCHAN_CFG_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) & \
@@ -328,6 +331,12 @@ enum {
 #define    PAS_STATUS_SOFT		0x4000000000000000ull
 #define    PAS_STATUS_INT		0x8000000000000000ull
 
+#define PAS_IOB_COM_PKTHDRCNT		0x120
+#define    PAS_IOB_COM_PKTHDRCNT_PKTHDR1_M	0x0fff0000
+#define    PAS_IOB_COM_PKTHDRCNT_PKTHDR1_S	16
+#define    PAS_IOB_COM_PKTHDRCNT_PKTHDR0_M	0x00000fff
+#define    PAS_IOB_COM_PKTHDRCNT_PKTHDR0_S	0
+
 #define PAS_IOB_DMA_RXCH_CFG(i)		(0x1100 + (i)*4)
 #define    PAS_IOB_DMA_RXCH_CFG_CNTTH_M		0x00000fff
 #define    PAS_IOB_DMA_RXCH_CFG_CNTTH_S		0
@@ -423,10 +432,9 @@ enum {
 /* Receive descriptor fields */
 #define	XCT_MACRX_T		0x8000000000000000ull
 #define	XCT_MACRX_ST		0x4000000000000000ull
-#define XCT_MACRX_NORES		0x0000000000000000ull
-#define XCT_MACRX_8BRES		0x1000000000000000ull
-#define XCT_MACRX_24BRES	0x2000000000000000ull
-#define XCT_MACRX_40BRES	0x3000000000000000ull
+#define XCT_MACRX_RR_M		0x3000000000000000ull
+#define XCT_MACRX_RR_NORES	0x0000000000000000ull
+#define XCT_MACRX_RR_8BRES	0x1000000000000000ull
 #define XCT_MACRX_O		0x0400000000000000ull
 #define XCT_MACRX_E		0x0200000000000000ull
 #define XCT_MACRX_FF		0x0100000000000000ull
@@ -474,6 +482,17 @@ enum {
 #define XCT_PTR_ADDR(x)		((((long)(x)) << XCT_PTR_ADDR_S) & \
 				 XCT_PTR_ADDR_M)
 
+/* Receive interface 8byte result fields */
+#define XCT_RXRES_8B_L4O_M	0xff00000000000000ull
+#define XCT_RXRES_8B_L4O_S	56
+#define XCT_RXRES_8B_RULE_M	0x00ffff0000000000ull
+#define XCT_RXRES_8B_RULE_S	40
+#define XCT_RXRES_8B_EVAL_M	0x000000ffff000000ull
+#define XCT_RXRES_8B_EVAL_S	24
+#define XCT_RXRES_8B_HTYPE_M	0x0000000000f00000ull
+#define XCT_RXRES_8B_HASH_M	0x00000000000fffffull
+#define XCT_RXRES_8B_HASH_S	0
+
 /* Receive interface buffer fields */
 #define XCT_RXB_LEN_M		0x0ffff00000000000ull
 #define XCT_RXB_LEN_S		44
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
old mode 100755
new mode 100644
index 7907da1..6dad20e
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -81,7 +81,7 @@ typedef enum {
 } PHY_DEVICE_et;
 
 typedef struct {
-	PHY_DEVICE_et phyDevice; 
+	PHY_DEVICE_et phyDevice;
 	u32		phyIdOUI;
 	u16		phyIdModel;
 	char 		*name;
@@ -330,7 +330,7 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
 					     PCI_DMA_FROMDEVICE);
 			err = pci_dma_mapping_error(map);
 			if(err) {
-				printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+				printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
 				       qdev->ndev->name, err);
 				dev_kfree_skb(lrg_buf_cb->skb);
 				lrg_buf_cb->skb = NULL;
@@ -884,14 +884,14 @@ static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev)
 	u16 reg;
 
 	/* Enable Auto-negotiation sense */
-	ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, &reg, 
+	ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, &reg,
 			   PHYAddr[qdev->mac_index]);
 	reg |= PETBI_TBI_AUTO_SENSE;
-	ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg, 
+	ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg,
 			    PHYAddr[qdev->mac_index]);
 
 	ql_mii_write_reg_ex(qdev, PETBI_NEG_ADVER,
-			    PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX, 
+			    PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX,
 			    PHYAddr[qdev->mac_index]);
 
 	ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG,
@@ -945,7 +945,7 @@ static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr)
 	ql_mii_write_reg_ex(qdev, 0x10, 0x2806, miiAddr);
 	/* Write new PHYAD w/bit 5 set */
 	ql_mii_write_reg_ex(qdev, 0x11, 0x0020 | (PHYAddr[qdev->mac_index] >> 8), miiAddr);
-	/* 
+	/*
 	 * Disable diagnostic mode bit 2 = 0
 	 * Power up device bit 11 = 0
 	 * Link up (on) and activity (blink)
@@ -955,18 +955,18 @@ static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr)
 	ql_mii_write_reg(qdev, 0x1c, 0xfaf0);
 }
 
-static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev, 
+static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev,
 				 u16 phyIdReg0, u16 phyIdReg1)
 {
 	PHY_DEVICE_et result = PHY_TYPE_UNKNOWN;
-	u32   oui;     
+	u32   oui;
 	u16   model;
-	int i;   
+	int i;
 
 	if (phyIdReg0 == 0xffff) {
 		return result;
 	}
-   
+
 	if (phyIdReg1 == 0xffff) {
 		return result;
 	}
@@ -984,7 +984,7 @@ static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev,
 
 			printk(KERN_INFO "%s: Phy: %s\n",
 				qdev->ndev->name, PHY_DEVICES[i].name);
-			
+
 		        break;
 		}
 	}
@@ -1033,7 +1033,7 @@ static int ql_is_full_dup(struct ql3_adapter *qdev)
 	{
 		if (ql_mii_read_reg(qdev, 0x1A, &reg))
 			return 0;
-			
+
 		return ((reg & 0x0080) && (reg & 0x1000)) != 0;
 	}
 	case PHY_VITESSE_VSC8211:
@@ -1082,19 +1082,19 @@ static int PHY_Setup(struct ql3_adapter *qdev)
 	/*  Check if we have a Agere PHY */
 	if ((reg1 == 0xffff) || (reg2 == 0xffff)) {
 
-		/* Determine which MII address we should be using 
+		/* Determine which MII address we should be using
 		   determined by the index of the card */
 		if (qdev->mac_index == 0) {
 			miiAddr = MII_AGERE_ADDR_1;
 		} else {
 			miiAddr = MII_AGERE_ADDR_2;
 		}
-      
+
 		err =ql_mii_read_reg_ex(qdev, PHY_ID_0_REG, &reg1, miiAddr);
 		if(err != 0) {
 			printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n",
 		       	       qdev->ndev->name);
-                	return err; 
+                	return err;
 		}
 
 		err = ql_mii_read_reg_ex(qdev, PHY_ID_1_REG, &reg2, miiAddr);
@@ -1103,9 +1103,9 @@ static int PHY_Setup(struct ql3_adapter *qdev)
 			       qdev->ndev->name);
         	        return err;
 		}
-   
+
 		/*  We need to remember to initialize the Agere PHY */
-         	agereAddrChangeNeeded = true; 
+         	agereAddrChangeNeeded = true;
 	}
 
 	/*  Determine the particular PHY we have on board to apply
@@ -1114,7 +1114,7 @@ static int PHY_Setup(struct ql3_adapter *qdev)
 
 	if ((qdev->phyType == PHY_AGERE_ET1011C) && agereAddrChangeNeeded) {
 		/* need this here so address gets changed */
-		phyAgereSpecificInit(qdev, miiAddr);  
+		phyAgereSpecificInit(qdev, miiAddr);
 	} else if (qdev->phyType == PHY_TYPE_UNKNOWN) {
 		printk(KERN_ERR "%s: PHY is unknown\n", qdev->ndev->name);
 		return -EIO;
@@ -1427,7 +1427,7 @@ static int ql_this_adapter_controls_port(struct ql3_adapter *qdev)
 
 static void ql_phy_reset_ex(struct ql3_adapter *qdev)
 {
-	ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET, 
+	ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET,
 			    PHYAddr[qdev->mac_index]);
 }
 
@@ -1438,7 +1438,7 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
 
 	if(qdev->phyType == PHY_AGERE_ET1011C) {
 		/* turn off external loopback */
-		ql_mii_write_reg(qdev, 0x13, 0x0000); 
+		ql_mii_write_reg(qdev, 0x13, 0x0000);
 	}
 
 	if(qdev->mac_index == 0)
@@ -1452,23 +1452,23 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
 		portConfiguration = PORT_CONFIG_DEFAULT;
 
 	/* Set the 1000 advertisements */
-	ql_mii_read_reg_ex(qdev, PHY_GIG_CONTROL, &reg, 
+	ql_mii_read_reg_ex(qdev, PHY_GIG_CONTROL, &reg,
 			   PHYAddr[qdev->mac_index]);
 	reg &= ~PHY_GIG_ALL_PARAMS;
 
-	if(portConfiguration & 
+	if(portConfiguration &
 	   PORT_CONFIG_FULL_DUPLEX_ENABLED &
 	   PORT_CONFIG_1000MB_SPEED) {
 		reg |= PHY_GIG_ADV_1000F;
 	}
-	 
-	if(portConfiguration & 
+
+	if(portConfiguration &
 	   PORT_CONFIG_HALF_DUPLEX_ENABLED &
 	   PORT_CONFIG_1000MB_SPEED) {
 		reg |= PHY_GIG_ADV_1000H;
 	}
 
-	ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg, 
+	ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg,
 			    PHYAddr[qdev->mac_index]);
 
 	/* Set the 10/100 & pause negotiation advertisements */
@@ -1482,7 +1482,7 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
 	if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) {
 		if(portConfiguration & PORT_CONFIG_100MB_SPEED)
 			reg |= PHY_NEG_ADV_100F;
-		
+
 		if(portConfiguration & PORT_CONFIG_10MB_SPEED)
 			reg |= PHY_NEG_ADV_10F;
 	}
@@ -1490,22 +1490,22 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
 	if(portConfiguration & PORT_CONFIG_HALF_DUPLEX_ENABLED) {
 		if(portConfiguration & PORT_CONFIG_100MB_SPEED)
 			reg |= PHY_NEG_ADV_100H;
-		
+
 		if(portConfiguration & PORT_CONFIG_10MB_SPEED)
 			reg |= PHY_NEG_ADV_10H;
 	}
 
 	if(portConfiguration &
 	   PORT_CONFIG_1000MB_SPEED) {
-		reg |= 1;	
+		reg |= 1;
 	}
 
-	ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, reg, 
+	ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, reg,
 			    PHYAddr[qdev->mac_index]);
 
 	ql_mii_read_reg_ex(qdev, CONTROL_REG, &reg, PHYAddr[qdev->mac_index]);
-	
-	ql_mii_write_reg_ex(qdev, CONTROL_REG, 
+
+	ql_mii_write_reg_ex(qdev, CONTROL_REG,
 			    reg | PHY_CTRL_RESTART_NEG | PHY_CTRL_AUTO_NEG,
 			    PHYAddr[qdev->mac_index]);
 }
@@ -1660,7 +1660,7 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
 			       "%s: Reset in progress, skip processing link "
 			       "state.\n", qdev->ndev->name);
 
-		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);		
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
 		return;
 	}
 
@@ -1752,7 +1752,7 @@ static int ql_mii_setup(struct ql3_adapter *qdev)
 		return -1;
 
 	if (qdev->device_id == QL3032_DEVICE_ID)
-		ql_write_page0_reg(qdev, 
+		ql_write_page0_reg(qdev,
 			&port_regs->macMIIMgmtControlReg, 0x0f00000);
 
 	/* Divide 125MHz clock by 28 to meet PHY timing requirements */
@@ -1936,7 +1936,7 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
 
 				err = pci_dma_mapping_error(map);
 				if(err) {
-					printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+					printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
 					       qdev->ndev->name, err);
 					dev_kfree_skb(lrg_buf_cb->skb);
 					lrg_buf_cb->skb = NULL;
@@ -2044,7 +2044,7 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 	if(mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
 		printk(KERN_WARNING "Frame short but, frame was padded and sent.\n");
 	}
-	
+
 	tx_cb = &qdev->tx_buf[mac_rsp->transaction_id];
 
 	/*  Check the transmit response flags for any errors */
@@ -2108,13 +2108,13 @@ static struct ql_rcv_buf_cb *ql_get_lbuf(struct ql3_adapter *qdev)
 
 /*
  * The difference between 3022 and 3032 for inbound completions:
- * 3022 uses two buffers per completion.  The first buffer contains 
- * (some) header info, the second the remainder of the headers plus 
- * the data.  For this chip we reserve some space at the top of the 
- * receive buffer so that the header info in buffer one can be 
- * prepended to the buffer two.  Buffer two is the sent up while 
+ * 3022 uses two buffers per completion.  The first buffer contains
+ * (some) header info, the second the remainder of the headers plus
+ * the data.  For this chip we reserve some space at the top of the
+ * receive buffer so that the header info in buffer one can be
+ * prepended to the buffer two.  Buffer two is the sent up while
  * buffer one is returned to the hardware to be reused.
- * 3032 receives all of it's data and headers in one buffer for a 
+ * 3032 receives all of it's data and headers in one buffer for a
  * simpler process.  3032 also supports checksum verification as
  * can be seen in ql_process_macip_rx_intr().
  */
@@ -2205,13 +2205,13 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
 						 skb_push(skb2, size), size);
 	} else {
 		u16 checksum = le16_to_cpu(ib_ip_rsp_ptr->checksum);
-		if (checksum & 
-			(IB_IP_IOCB_RSP_3032_ICE | 
-			 IB_IP_IOCB_RSP_3032_CE)) { 
+		if (checksum &
+			(IB_IP_IOCB_RSP_3032_ICE |
+			 IB_IP_IOCB_RSP_3032_CE)) {
 			printk(KERN_ERR
 			       "%s: Bad checksum for this %s packet, checksum = %x.\n",
 			       __func__,
-			       ((checksum & 
+			       ((checksum &
 				IB_IP_IOCB_RSP_3032_TCP) ? "TCP" :
 				"UDP"),checksum);
 		} else if ((checksum & IB_IP_IOCB_RSP_3032_TCP) ||
@@ -2387,12 +2387,12 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
 }
 
 /*
- * Get the total number of segments needed for the 
+ * Get the total number of segments needed for the
  * given number of fragments.  This is necessary because
  * outbound address lists (OAL) will be used when more than
- * two frags are given.  Each address list has 5 addr/len 
+ * two frags are given.  Each address list has 5 addr/len
  * pairs.  The 5th pair in each AOL is used to  point to
- * the next AOL if more frags are coming.  
+ * the next AOL if more frags are coming.
  * That is why the frags:segment count  ratio is not linear.
  */
 static int ql_get_seg_count(struct ql3_adapter *qdev,
@@ -2469,12 +2469,12 @@ static int ql_send_map(struct ql3_adapter *qdev,
 
 	err = pci_dma_mapping_error(map);
 	if(err) {
-		printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+		printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
 		       qdev->ndev->name, err);
 
 		return NETDEV_TX_BUSY;
 	}
-	
+
 	oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
 	oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
 	oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
@@ -2504,7 +2504,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
 				err = pci_dma_mapping_error(map);
 				if(err) {
 
-					printk(KERN_ERR "%s: PCI mapping outbound address list with error: %d\n", 
+					printk(KERN_ERR "%s: PCI mapping outbound address list with error: %d\n",
 					       qdev->ndev->name, err);
 					goto map_error;
 				}
@@ -2530,7 +2530,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
 
 			err = pci_dma_mapping_error(map);
 			if(err) {
-				printk(KERN_ERR "%s: PCI mapping frags failed with error: %d\n", 
+				printk(KERN_ERR "%s: PCI mapping frags failed with error: %d\n",
 				       qdev->ndev->name, err);
 				goto map_error;
 			}
@@ -2551,10 +2551,10 @@ static int ql_send_map(struct ql3_adapter *qdev,
 
 map_error:
 	/* A PCI mapping failed and now we will need to back out
-	 * We need to traverse through the oal's and associated pages which 
+	 * We need to traverse through the oal's and associated pages which
 	 * have been mapped and now we must unmap them to clean up properly
 	 */
-	
+
 	seg = 1;
 	oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
 	oal = tx_cb->oal;
@@ -2592,11 +2592,11 @@ map_error:
  * The difference between 3022 and 3032 sends:
  * 3022 only supports a simple single segment transmission.
  * 3032 supports checksumming and scatter/gather lists (fragments).
- * The 3032 supports sglists by using the 3 addr/len pairs (ALP) 
- * in the IOCB plus a chain of outbound address lists (OAL) that 
- * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th) 
- * will used to point to an OAL when more ALP entries are required.  
- * The IOCB is always the top of the chain followed by one or more 
+ * The 3032 supports sglists by using the 3 addr/len pairs (ALP)
+ * in the IOCB plus a chain of outbound address lists (OAL) that
+ * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th)
+ * will used to point to an OAL when more ALP entries are required.
+ * The IOCB is always the top of the chain followed by one or more
  * OALs (when necessary).
  */
 static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
@@ -2610,14 +2610,14 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
 	if (unlikely(atomic_read(&qdev->tx_count) < 2)) {
 		return NETDEV_TX_BUSY;
 	}
-	
+
 	tx_cb = &qdev->tx_buf[qdev->req_producer_index] ;
 	if((tx_cb->seg_count = ql_get_seg_count(qdev,
 						(skb_shinfo(skb)->nr_frags))) == -1) {
 		printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__);
 		return NETDEV_TX_OK;
 	}
-	
+
 	mac_iocb_ptr = tx_cb->queue_entry;
 	memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req));
 	mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
@@ -2629,12 +2629,12 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
 	if (qdev->device_id == QL3032_DEVICE_ID &&
 	    skb->ip_summed == CHECKSUM_PARTIAL)
 		ql_hw_csum_setup(skb, mac_iocb_ptr);
-	
+
 	if(ql_send_map(qdev,mac_iocb_ptr,tx_cb,skb) != NETDEV_TX_OK) {
 		printk(KERN_ERR PFX"%s: Could not map the segments!\n",__func__);
 		return NETDEV_TX_BUSY;
 	}
-	
+
 	wmb();
 	qdev->req_producer_index++;
 	if (qdev->req_producer_index == NUM_REQ_Q_ENTRIES)
@@ -2732,7 +2732,7 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
 		       "%s: qdev->lrg_buf alloc failed.\n", qdev->ndev->name);
 		return -ENOMEM;
 	}
-	
+
 	qdev->lrg_buf_q_alloc_virt_addr =
 	    pci_alloc_consistent(qdev->pdev,
 				 qdev->lrg_buf_q_alloc_size,
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h
old mode 100755
new mode 100644
index 483840f..fbcb0b9
--- a/drivers/net/qla3xxx.h
+++ b/drivers/net/qla3xxx.h
@@ -556,7 +556,7 @@ enum {
 	IP_ADDR_INDEX_REG_FUNC_3_SEC = 0x0007,
 	IP_ADDR_INDEX_REG_6 = 0x0008,
 	IP_ADDR_INDEX_REG_OFFSET_MASK = 0x0030,
-	IP_ADDR_INDEX_REG_E = 0x0040, 
+	IP_ADDR_INDEX_REG_E = 0x0040,
 };
 enum {
 	QL3032_PORT_CONTROL_DS = 0x0001,
@@ -1112,7 +1112,7 @@ struct ql_rcv_buf_cb {
  * OAL has 5 entries:
  * 1 thru 4 point to frags
  * fifth points to next oal.
- */ 
+ */
 #define MAX_OAL_CNT ((MAX_SKB_FRAGS-1)/4 + 1)
 
 struct oal_entry {
@@ -1137,7 +1137,7 @@ struct ql_tx_buf_cb {
 	struct ob_mac_iocb_req *queue_entry ;
 	int seg_count;
 	struct oal *oal;
-	struct map_list map[MAX_SKB_FRAGS+1]; 
+	struct map_list map[MAX_SKB_FRAGS+1];
 };
 
 /* definitions for type field */

^ permalink raw reply related

* Re: [PATCH RESEND] [11/11] pasemi_mac: enable iommu support
From: Jeff Garzik @ 2007-10-03 18:19 UTC (permalink / raw)
  To: Olof Johansson; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071003180354.GB19319@lixom.net>

Olof Johansson wrote:
> pasemi_mac: enable iommu support
> 
> Enable IOMMU support for pasemi_mac, but avoid using it on non-partitioned
> systems for performance reasons.
> 
> The user can override this by selecting the PPC_PASEMI_IOMMU_DMA_FORCE
> configuration option.
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>

applied


^ permalink raw reply

* Re: [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
From: Jeff Garzik @ 2007-10-03 18:15 UTC (permalink / raw)
  To: Olof Johansson; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071003180210.GA19319@lixom.net>

Olof Johansson wrote:
> On Wed, Oct 03, 2007 at 01:46:16PM -0400, Jeff Garzik wrote:
>> Olof Johansson wrote:
>>> pasemi_mac: clear out old errors on interface open
>>> Clear out any pending errors when an interface is brought up. Since the 
>>> bits
>>> are sticky, they might be from interface shutdown time after firmware has
>>> used it, etc.
>>> Signed-off-by: Olof Johansson <olof@lixom.net>
>> In general, interface-open should completely reset and initialize the 
>> hardware.  does pasemi_mac not do that?
> 
> There's no explicit way to reset just one interface besides disabling it
> (which we do at close, and re-enable at open). It seems that some of
> the error bits are sticky across disable/enable, which is why this was
> needed. Also, they're RW1C, so writing 0 doesn't remove them (need to
> write 1 to clear).

OK just making sure, thanks.


> The only other dependency from firmware at this time is the setting of mac
> addresses, something that will be taken care of once we allow override of
> them via ethtool, since we'd need to program them from the driver then
> no matter what. Right now we assume that firmware has programmed it.

Standard procedure for this is

* upon module-load, obtain the MAC address from <whatever canonical source>
* upon interface-up, program dev->dev_addr[] into chip's RX filter (aka 
MAC address) registers

That permits the admin to override the MAC address via ifconfig. 
(ethtool doesn't support that, but you basically had the right idea)

	Jeff



^ permalink raw reply

* Re: [PATCH v4] qe: miscellaneous code improvements and fixes to the QE library
From: Timur Tabi @ 2007-10-03 18:00 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: linuxppc-dev, netdev, galak
In-Reply-To: <20071003094449.702c4a90@freepuppy.rosehill>

Stephen Hemminger wrote:

> Separate the changes into individual patches to allow for better comment/review
> and bisection in case of regression.

That would be too difficult.  Some of the changes are single lines, and this 
patch has already been approved -- I just cross-posted to netdev because I 
made a few ucc_geth changes that can't be docoupled from the powerpc changes. 
  A series of 18 patches would just be convoluted.

-- 
Timur Tabi
Linux Kernel Developer @ Freescale

^ permalink raw reply

* [PATCH RESEND] [11/11] pasemi_mac: enable iommu support
From: Olof Johansson @ 2007-10-03 18:03 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <4703D5A5.1080204@pobox.com>

pasemi_mac: enable iommu support

Enable IOMMU support for pasemi_mac, but avoid using it on non-partitioned
systems for performance reasons.

The user can override this by selecting the PPC_PASEMI_IOMMU_DMA_FORCE
configuration option.

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

---

On Wed, Oct 03, 2007 at 01:47:17PM -0400, Jeff Garzik wrote:

> You sent patch #10 against as patch #11 :)

Oops! Here's the real copy.


-Olof


Index: k.org/arch/powerpc/platforms/pasemi/iommu.c
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/iommu.c
+++ k.org/arch/powerpc/platforms/pasemi/iommu.c
@@ -25,6 +25,7 @@
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
+#include <asm/firmware.h>
 
 
 #define IOBMAP_PAGE_SHIFT	12
@@ -175,13 +176,17 @@ static void pci_dma_dev_setup_pasemi(str
 {
 	pr_debug("pci_dma_dev_setup, dev %p (%s)\n", dev, pci_name(dev));
 
-	/* DMA device is untranslated, but all other PCI-e goes through
-	 * the IOMMU
+#if !defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
+	/* For non-LPAR environment, don't translate anything for the DMA
+	 * engine. The exception to this is if the user has enabled
+	 * CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE at build time.
 	 */
-	if (dev->vendor == 0x1959 && dev->device == 0xa007)
+	if (dev->vendor == 0x1959 && dev->device == 0xa007 &&
+	    !firmware_has_feature(FW_FEATURE_LPAR))
 		dev->dev.archdata.dma_ops = &dma_direct_ops;
-	else
-		dev->dev.archdata.dma_data = &iommu_table_iobmap;
+#endif
+
+	dev->dev.archdata.dma_data = &iommu_table_iobmap;
 }
 
 static void pci_dma_bus_setup_null(struct pci_bus *b) { }
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -34,6 +34,7 @@
 #include <net/checksum.h>
 
 #include <asm/irq.h>
+#include <asm/firmware.h>
 
 #include "pasemi_mac.h"
 
@@ -89,6 +90,15 @@ MODULE_PARM_DESC(debug, "PA Semi MAC bit
 
 static struct pasdma_status *dma_status;
 
+static int translation_enabled(void)
+{
+#if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
+	return 1;
+#else
+	return firmware_has_feature(FW_FEATURE_LPAR);
+#endif
+}
+
 static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg,
 			  unsigned int val)
 {
@@ -193,6 +203,7 @@ static int pasemi_mac_setup_rx_resources
 	struct pasemi_mac_rxring *ring;
 	struct pasemi_mac *mac = netdev_priv(dev);
 	int chan_id = mac->dma_rxch;
+	unsigned int cfg;
 
 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 
@@ -232,20 +243,28 @@ static int pasemi_mac_setup_rx_resources
 			   PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) |
 			   PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-	write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id),
-			   PAS_DMA_RXCHAN_CFG_HBU(2));
+	cfg = PAS_DMA_RXCHAN_CFG_HBU(2);
+
+	if (translation_enabled())
+		cfg |= PAS_DMA_RXCHAN_CFG_CTR;
+
+	write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id), cfg);
 
 	write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if),
-			   PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers)));
+			   PAS_DMA_RXINT_BASEL_BRBL(ring->buf_dma));
 
 	write_dma_reg(mac, PAS_DMA_RXINT_BASEU(mac->dma_if),
-			   PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) |
+			   PAS_DMA_RXINT_BASEU_BRBH(ring->buf_dma >> 32) |
 			   PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-	write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if),
-		      PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 |
-		      PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP |
-		      PAS_DMA_RXINT_CFG_HEN);
+	cfg = PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 |
+	      PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP |
+	      PAS_DMA_RXINT_CFG_HEN;
+
+	if (translation_enabled())
+		cfg |= PAS_DMA_RXINT_CFG_ITRR | PAS_DMA_RXINT_CFG_ITR;
+
+	write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if), cfg);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
@@ -275,6 +294,7 @@ static int pasemi_mac_setup_tx_resources
 	u32 val;
 	int chan_id = mac->dma_txch;
 	struct pasemi_mac_txring *ring;
+	unsigned int cfg;
 
 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 	if (!ring)
@@ -304,11 +324,15 @@ static int pasemi_mac_setup_tx_resources
 
 	write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val);
 
-	write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id),
-			   PAS_DMA_TXCHAN_CFG_TY_IFACE |
-			   PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
-			   PAS_DMA_TXCHAN_CFG_UP |
-			   PAS_DMA_TXCHAN_CFG_WT(2));
+	cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
+	      PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
+	      PAS_DMA_TXCHAN_CFG_UP |
+	      PAS_DMA_TXCHAN_CFG_WT(2);
+
+	if (translation_enabled())
+		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
+
+	write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id), cfg);
 
 	ring->next_to_fill = 0;
 	ring->next_to_clean = 0;
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -212,6 +212,7 @@ enum {
 #define    PAS_DMA_RXINT_CFG_DHL_S	24
 #define    PAS_DMA_RXINT_CFG_DHL(x)	(((x) << PAS_DMA_RXINT_CFG_DHL_S) & \
 					 PAS_DMA_RXINT_CFG_DHL_M)
+#define    PAS_DMA_RXINT_CFG_ITR	0x00400000
 #define    PAS_DMA_RXINT_CFG_LW		0x00200000
 #define    PAS_DMA_RXINT_CFG_L2		0x00100000
 #define    PAS_DMA_RXINT_CFG_HEN	0x00080000
@@ -258,9 +259,11 @@ enum {
 #define    PAS_DMA_TXCHAN_CFG_WT_S	6
 #define    PAS_DMA_TXCHAN_CFG_WT(x)	(((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
 					 PAS_DMA_TXCHAN_CFG_WT_M)
-#define    PAS_DMA_TXCHAN_CFG_CF	0x00001000	/* Clean first line */
-#define    PAS_DMA_TXCHAN_CFG_CL	0x00002000	/* Clean last line */
+#define    PAS_DMA_TXCHAN_CFG_TRD	0x00010000	/* translate data */
+#define    PAS_DMA_TXCHAN_CFG_TRR	0x00008000	/* translate rings */
 #define    PAS_DMA_TXCHAN_CFG_UP	0x00004000	/* update tx descr when sent */
+#define    PAS_DMA_TXCHAN_CFG_CL	0x00002000	/* Clean last line */
+#define    PAS_DMA_TXCHAN_CFG_CF	0x00001000	/* Clean first line */
 #define PAS_DMA_TXCHAN_INCR(c)    (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define PAS_DMA_TXCHAN_BASEL(c)   (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define    PAS_DMA_TXCHAN_BASEL_BRBL_M	0xffffffc0
@@ -294,6 +297,7 @@ enum {
 #define    PAS_DMA_RXCHAN_CCMDSTA_FD	0x00001000
 #define    PAS_DMA_RXCHAN_CCMDSTA_DT	0x00000800
 #define PAS_DMA_RXCHAN_CFG(c)     (0x804+(c)*_PAS_DMA_RXCHAN_STRIDE)
+#define    PAS_DMA_RXCHAN_CFG_CTR	0x00000400
 #define    PAS_DMA_RXCHAN_CFG_HBU_M	0x00000380
 #define    PAS_DMA_RXCHAN_CFG_HBU_S	7
 #define    PAS_DMA_RXCHAN_CFG_HBU(x)	(((x) << PAS_DMA_RXCHAN_CFG_HBU_S) & \
Index: k.org/arch/powerpc/platforms/pasemi/Kconfig
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/Kconfig
+++ k.org/arch/powerpc/platforms/pasemi/Kconfig
@@ -19,6 +19,16 @@ config PPC_PASEMI_IOMMU
 	help
 	  IOMMU support for PA6T-1682M
 
+config PPC_PASEMI_IOMMU_DMA_FORCE
+	bool "Force DMA engine to use IOMMU"
+	depends on PPC_PASEMI_IOMMU
+	help
+	  This option forces the use of the IOMMU also for the
+	  DMA engine. Otherwise the kernel will use it only when
+	  running under a hypervisor.
+
+	  If in doubt, say "N".
+
 config PPC_PASEMI_MDIO
 	depends on PHYLIB
 	tristate "MDIO support via GPIO"

^ permalink raw reply

* Re: [PATCH] sky2: jumbo frame regression fix
From: Bill Davidsen @ 2007-10-03 18:04 UTC (permalink / raw)
  To: pomac; +Cc: Stephen Hemminger, Jeff Garzik, Linux-kernel, netdev
In-Reply-To: <1191375274.26233.17.camel@localhost>

Ian Kumlien wrote:
> On tis, 2007-10-02 at 18:02 -0700, Stephen Hemminger wrote:
>> Remove unneeded check that caused problems with jumbo frame sizes.
>> The check was recently added and is wrong.
>> When using jumbo frames the sky2 driver does fragmentation, so
>> rx_data_size is less than mtu.
> 
> Confirmed working.
> 
> Now running with 9k mtu with no errors, =)

Have you verified that you are actually getting jumbo packets out of the 
NIC? I had one machine which did standard packets silently using sky2 
and jumbo using sk98lin. I was looking for something else with tcpdump 
and got one of those WTF moments when I saw all the tiny packets.

-- 
Bill Davidsen <davidsen@tmr.com>
   "We have more to fear from the bungling of the incompetent than from
the machinations of the wicked."  - from Slashdot

^ permalink raw reply

* Re: [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
From: Olof Johansson @ 2007-10-03 18:02 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <4703D568.6000000@pobox.com>

On Wed, Oct 03, 2007 at 01:46:16PM -0400, Jeff Garzik wrote:
> Olof Johansson wrote:
>> pasemi_mac: clear out old errors on interface open
>> Clear out any pending errors when an interface is brought up. Since the 
>> bits
>> are sticky, they might be from interface shutdown time after firmware has
>> used it, etc.
>> Signed-off-by: Olof Johansson <olof@lixom.net>
>
> In general, interface-open should completely reset and initialize the 
> hardware.  does pasemi_mac not do that?

There's no explicit way to reset just one interface besides disabling it
(which we do at close, and re-enable at open). It seems that some of
the error bits are sticky across disable/enable, which is why this was
needed. Also, they're RW1C, so writing 0 doesn't remove them (need to
write 1 to clear).

The only other dependency from firmware at this time is the setting of mac
addresses, something that will be taken care of once we allow override of
them via ethtool, since we'd need to program them from the driver then
no matter what. Right now we assume that firmware has programmed it.


-Olof


^ permalink raw reply

* Re: [PATCH] Fix typo in new EMAC driver.
From: Jeff Garzik @ 2007-10-03 17:51 UTC (permalink / raw)
  To: Valentine Barshak (by way of Josh Boyer <jwboyer@linux.vnet.ibm.com>)
  Cc: linuxppc-dev, Josh Boyer, netdev
In-Reply-To: <20071002120107.GA21847@ru.mvista.com>

Valentine Barshak (by way of Josh Boyer <jwboyer@linux.vnet.ibm.com>) wrote:
> Fix an obvious typo in emac_xmit_finish.
> 
> Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
> ---
>  drivers/net/ibm_newemac/core.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)

applied



^ permalink raw reply

* Re: [patch 2/3] ipg.c doesn't compile with with CONFIG_HIGHMEM64G
From: Jeff Garzik @ 2007-10-03 17:50 UTC (permalink / raw)
  To: akpm; +Cc: davem, netdev, tremyfr, jesse, sorbica
In-Reply-To: <200710022104.l92L4cIf022231@imap1.linux-foundation.org>

applied



^ permalink raw reply

* Re: [PATCH] [1/11] pasemi_mac: basic error checking
From: Jeff Garzik @ 2007-10-03 17:50 UTC (permalink / raw)
  To: Olof Johansson; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212450.GB2282@lixom.net>

Olof Johansson wrote:
> pasemi_mac: basic error checking
> 
> Add some rudimentary error checking to pasemi_mac.
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>

applied 1-10



^ permalink raw reply

* Re: [PATCH 5/7] CAN: Add virtual CAN netdevice driver
From: Oliver Hartkopp @ 2007-10-03 17:47 UTC (permalink / raw)
  To: David Miller, shemminger
  Cc: acme, urs, netdev, kaber, tglx, yoshfuji, ebiederm,
	oliver.hartkopp, urs.thuermann
In-Reply-To: <20071002.150438.78357233.davem@davemloft.net>

David Miller wrote:
> From: Stephen Hemminger <shemminger@linux-foundation.org>
> Date: Tue, 2 Oct 2007 14:52:36 -0700
>
>   
>> Please consider using netif_msg_xxx() and module parameter to set
>> default message level, like other real network drivers already do.
>>     
>
> I keep seeing this recommendation, but the two supposedly most mature
> and actively used drivers in the tree, tg3 and e1000 and e1000e, all
> do not use this scheme.
>
> In fact there are tons of drivers that even hook up the ethtool
> msg_level setting function and never even use the value.
>
> If people aren't using netif_msg_xxx() and the ethtool msg_level
> facilities properly, it's because there is a severe dearth of good
> example drivers to learn about it from.
>   

The currently available CAN netdevice drivers do not have a common debug 
concept neither any runtime control mechanism for this debugging. So 
netif_msg_xxx() is definitely worth to look at instead of creating any 
new stuff in this direction, before posting any 'real' CAN network 
driver here.

Thanks very much for that hint!

Oliver

^ permalink raw reply

* Re: [PATCH] [11/11] pasemi_mac: enable iommu support
From: Jeff Garzik @ 2007-10-03 17:47 UTC (permalink / raw)
  To: Olof Johansson; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212818.GL2282@lixom.net>

Olof Johansson wrote:
> pasemi_mac: use buffer index pointer in clean_rx()
> 
> Use the new features in B0 for buffer ring index on the receive side. This
> means we no longer have to search in the ring for where the buffer
> came from.
> 
> Also cleanup the RX cleaning side a little, while I was at it.
> 
> Note: Pre-B0 hardware is no longer supported, and needs a pile of other
> workarounds that are not being submitted for mainline inclusion. So the
> fact that this breaks old hardware is not a problem at this time.
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>

You sent patch #10 against as patch #11 :)



^ permalink raw reply

* Re: [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
From: Jeff Garzik @ 2007-10-03 17:46 UTC (permalink / raw)
  To: Olof Johansson; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212739.GJ2282@lixom.net>

Olof Johansson wrote:
> pasemi_mac: clear out old errors on interface open
> 
> Clear out any pending errors when an interface is brought up. Since the bits
> are sticky, they might be from interface shutdown time after firmware has
> used it, etc.
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>

In general, interface-open should completely reset and initialize the 
hardware.  does pasemi_mac not do that?

	Jeff




^ permalink raw reply

* Re: [PATCH] sky2: jumbo frame regression fix
From: Jeff Garzik @ 2007-10-03 17:39 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: pomac, Linux-kernel, netdev
In-Reply-To: <20071002180209.47c350a3@freepuppy.rosehill>

Stephen Hemminger wrote:
> Remove unneeded check that caused problems with jumbo frame sizes.
> The check was recently added and is wrong.
> When using jumbo frames the sky2 driver does fragmentation, so
> rx_data_size is less than mtu.
> 
> Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>

applied

^ permalink raw reply

* Re: Please pull 'fixes-jgarzik' branch of wireless-2.6
From: Jeff Garzik @ 2007-10-03 17:39 UTC (permalink / raw)
  To: John W. Linville; +Cc: netdev, linux-wireless
In-Reply-To: <20071003012044.GD29361@tuxdriver.com>

John W. Linville wrote:
> The following changes since commit 3146b39c185f8a436d430132457e84fa1d8f8208:
>   Linus Torvalds (1):
>         Linux 2.6.23-rc9
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git fixes-jgarzik
> 
> Joe Perches (1):
>       bcm43xx: Correct printk with PFX before KERN_
> 
> Richard Knutsson (1):
>       softmac: Fix compiler-warning

pulled



^ permalink raw reply

* lockdep report from bonding.
From: Dave Jones @ 2007-10-03 17:05 UTC (permalink / raw)
  To: netdev

Reported by a Fedora user this morning.

Ethernet Channel Bonding Driver: v3.1.3 (June 13, 2007)
bonding: MII link monitoring set to 100 ms
ADDRCONF(NETDEV_UP): bond0: link is not ready
bonding: bond0: Adding slave eth0.
e100: eth0: e100_watchdog: link up, 100Mbps, full-duplex
bonding: bond0: making interface eth0 the new active one.
bonding: bond0: enslaving eth0 as an active interface with an up link.

=================================
[ INFO: inconsistent lock state ]
2.6.23-0.214.rc8.git2.fc8 #1
---------------------------------
inconsistent {softirq-on-W} -> {in-softirq-W} usage.
events/1/10 [HC0[0]:SC1[1]:HE1:SE0] takes:
 (&(bond_info->tx_hashtbl_lock)){-+..}, at: [<f8ad154c>] tlb_clear_slave+0x1d/0x9a [bonding]
{softirq-on-W} state was registered at:
  [<c0449fb0>] __lock_acquire+0x4ff/0xc67
  [<c044ab92>] lock_acquire+0x7b/0x9e
  [<c0633050>] _spin_lock+0x2e/0x58
  [<f8ad293a>] bond_alb_initialize+0x64/0x18e [bonding]
  [<f8acf25f>] bond_open+0x33/0x178 [bonding]
  [<c05ceb36>] dev_open+0x31/0x6c
  [<c05ccc8d>] dev_change_flags+0xa3/0x156
  [<c060d579>] devinet_ioctl+0x207/0x50e
  [<c060dc27>] inet_ioctl+0x86/0xa4
  [<c05c2e62>] sock_ioctl+0x1ac/0x1c9
  [<c04942a2>] do_ioctl+0x22/0x68
  [<c0494531>] vfs_ioctl+0x249/0x25c
  [<c049458d>] sys_ioctl+0x49/0x64
  [<c040522e>] syscall_call+0x7/0xb
  [<ffffffff>] 0xffffffff
irq event stamp: 40878
hardirqs last  enabled at (40878): [<c0633474>] _spin_unlock_irq+0x22/0x2f
hardirqs last disabled at (40877): [<c063339d>] _spin_lock_irq+0x19/0x67
softirqs last  enabled at (40872): [<c05e6fcf>] rt_run_flush+0x6e/0x97
softirqs last disabled at (40873): [<c04075d4>] do_softirq+0x74/0xf7

other info that might help us debug this:
3 locks held by events/1/10:
 #0:  (rtnl_mutex){--..}, at: [<c0631c31>] mutex_lock+0x21/0x24
 #1:  (&bond->lock){-.-+}, at: [<f8ad25ed>] bond_alb_monitor+0x16/0x26e [bonding]
 #2:  (&bond->curr_slave_lock){..-+}, at: [<f8ad2680>] bond_alb_monitor+0xa9/0x26e [bonding]

stack backtrace:
 [<c0406463>] show_trace_log_lvl+0x1a/0x2f
 [<c0406e4d>] show_trace+0x12/0x14
 [<c0406e65>] dump_stack+0x16/0x18
 [<c0448856>] print_usage_bug+0x141/0x14b
 [<c04490dc>] mark_lock+0x12f/0x472
 [<c0449f38>] __lock_acquire+0x487/0xc67
 [<c044ab92>] lock_acquire+0x7b/0x9e
 [<c0633050>] _spin_lock+0x2e/0x58
 [<f8ad154c>] tlb_clear_slave+0x1d/0x9a [bonding]
 [<f8ad269a>] bond_alb_monitor+0xc3/0x26e [bonding]
 [<c043541b>] run_timer_softirq+0x127/0x18f
 [<c0432a21>] __do_softirq+0x78/0xff
 [<c04075d4>] do_softirq+0x74/0xf7
 =======================
ADDRCONF(NETDEV_CHANGE): bond0: link becomes ready
bonding: bond0: Adding slave eth1.

-- 
http://www.codemonkey.org.uk

^ permalink raw reply

* Re: [PATCH v4] qe: miscellaneous code improvements and fixes to the QE library
From: Stephen Hemminger @ 2007-10-03 16:44 UTC (permalink / raw)
  To: Timur Tabi; +Cc: linuxppc-dev, netdev, galak, Timur Tabi
In-Reply-To: <1191429299378-git-send-email-timur@freescale.com>

On Wed,  3 Oct 2007 11:34:59 -0500
Timur Tabi <timur@freescale.com> wrote:

> This patch makes numerous miscellaneous code improvements to the QE library.
> 
> 1. Remove struct ucc_common and merge ucc_init_guemr() into ucc_set_type()
>    (every caller of ucc_init_guemr() also calls ucc_set_type()).  Modify all
>    callers of ucc_set_type() accordingly.
> 
> 2. Remove the unused enum ucc_pram_initial_offset.
> 
> 3. Refactor qe_setbrg(), also implement work-around for errata QE_General4.
> 
> 4. Several printk() calls were missing the terminating \n.
> 
> 5. Add __iomem where needed, and change u16 to __be16 and u32 to __be32 where
>    appropriate.
> 
> 6. In ucc_slow_init() the RBASE and TBASE registers in the PRAM were programmed
>    with the wrong value.
> 
> 7. Add the protocol type to struct us_info and updated ucc_slow_init() to
>    use it, instead of always programming QE_CR_PROTOCOL_UNSPECIFIED.
> 
> 8. Rename ucc_slow_restart_x() to ucc_slow_restart_tx()
> 
> 9. Add several macros in qe.h (mostly for slow UCC support, but also to
>    standardize some naming convention) and remove several unused macros.
> 
> 10. Update ucc_geth.c to use the new macros.
> 
> 11. Add ucc_slow_info.protocol to specify which QE_CR_PROTOCOL_xxx protcol
>     to use when initializing the UCC in ucc_slow_init().
> 
> 12. Rename ucc_slow_pram.rfcr to rbmr and ucc_slow_pram.tfcr to tbmr, since
>     these are the real names of the registers.
> 
> 13. Use the setbits, clrbits, and clrsetbits where appropriate.
> 
> 14. Refactor ucc_set_qe_mux_rxtx().
> 
> 15. Remove all instances of 'volatile'.
> 
> 16. Simplify get_cmxucr_reg();
> 
> 17. Replace qe_mux.cmxucrX with qe_mux.cmxucr[].
> 
> 18. Updated struct ucc_geth because struct ucc_fast is not padded any more.
> 
> Signed-off-by: Timur Tabi <timur@freescale.com>
> ---
> 

Separate the changes into individual patches to allow for better comment/review
and bisection in case of regression.

^ permalink raw reply

* [PATCH v4] qe: miscellaneous code improvements and fixes to the QE library
From: Timur Tabi @ 2007-10-03 16:34 UTC (permalink / raw)
  To: linuxppc-dev, netdev, galak; +Cc: Timur Tabi

This patch makes numerous miscellaneous code improvements to the QE library.

1. Remove struct ucc_common and merge ucc_init_guemr() into ucc_set_type()
   (every caller of ucc_init_guemr() also calls ucc_set_type()).  Modify all
   callers of ucc_set_type() accordingly.

2. Remove the unused enum ucc_pram_initial_offset.

3. Refactor qe_setbrg(), also implement work-around for errata QE_General4.

4. Several printk() calls were missing the terminating \n.

5. Add __iomem where needed, and change u16 to __be16 and u32 to __be32 where
   appropriate.

6. In ucc_slow_init() the RBASE and TBASE registers in the PRAM were programmed
   with the wrong value.

7. Add the protocol type to struct us_info and updated ucc_slow_init() to
   use it, instead of always programming QE_CR_PROTOCOL_UNSPECIFIED.

8. Rename ucc_slow_restart_x() to ucc_slow_restart_tx()

9. Add several macros in qe.h (mostly for slow UCC support, but also to
   standardize some naming convention) and remove several unused macros.

10. Update ucc_geth.c to use the new macros.

11. Add ucc_slow_info.protocol to specify which QE_CR_PROTOCOL_xxx protcol
    to use when initializing the UCC in ucc_slow_init().

12. Rename ucc_slow_pram.rfcr to rbmr and ucc_slow_pram.tfcr to tbmr, since
    these are the real names of the registers.

13. Use the setbits, clrbits, and clrsetbits where appropriate.

14. Refactor ucc_set_qe_mux_rxtx().

15. Remove all instances of 'volatile'.

16. Simplify get_cmxucr_reg();

17. Replace qe_mux.cmxucrX with qe_mux.cmxucr[].

18. Updated struct ucc_geth because struct ucc_fast is not padded any more.

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

Add fix 18.

 arch/powerpc/sysdev/qe_lib/qe.c       |   36 +++--
 arch/powerpc/sysdev/qe_lib/qe_ic.c    |    2 -
 arch/powerpc/sysdev/qe_lib/qe_io.c    |   35 ++---
 arch/powerpc/sysdev/qe_lib/ucc.c      |  270 ++++++++++++++-------------------
 arch/powerpc/sysdev/qe_lib/ucc_fast.c |  127 ++++++++--------
 arch/powerpc/sysdev/qe_lib/ucc_slow.c |   48 +++---
 drivers/net/ucc_geth.c                |    2 +-
 drivers/net/ucc_geth.h                |    1 +
 include/asm-powerpc/immap_qe.h        |   30 ++---
 include/asm-powerpc/qe.h              |  243 ++++++++++++++++++++---------
 include/asm-powerpc/ucc.h             |   40 ++----
 include/asm-powerpc/ucc_slow.h        |    9 +-
 12 files changed, 431 insertions(+), 412 deletions(-)

diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 90f8740..3d57d38 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -141,7 +141,7 @@ EXPORT_SYMBOL(qe_issue_cmd);
  * 16 BRGs, which can be connected to the QE channels or output
  * as clocks. The BRGs are in two different block of internal
  * memory mapped space.
- * The baud rate clock is the system clock divided by something.
+ * The BRG clock is the QE clock divided by 2.
  * It was set up long ago during the initial boot phase and is
  * is given to us.
  * Baud rate clocks are zero-based in the driver code (as that maps
@@ -165,28 +165,38 @@ unsigned int get_brg_clk(void)
 	return brg_clk;
 }
 
-/* This function is used by UARTS, or anything else that uses a 16x
- * oversampled clock.
+/* Program the BRG to the given sampling rate and multiplier
+ *
+ * @brg: the BRG, 1-16
+ * @rate: the desired sampling rate
+ * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
+ * GUMR_L[TDCR].  E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
+ * then 'multiplier' should be 8.
+ *
+ * Also note that the value programmed into the BRGC register must be even.
  */
-void qe_setbrg(u32 brg, u32 rate)
+void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
 {
-	volatile u32 *bp;
 	u32 divisor, tempval;
-	int div16 = 0;
+	u32 div16 = 0;
 
-	bp = &qe_immr->brg.brgc[brg];
+	divisor = get_brg_clk() / (rate * multiplier);
 
-	divisor = (get_brg_clk() / rate);
 	if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
-		div16 = 1;
+		div16 = QE_BRGC_DIV16;
 		divisor /= 16;
 	}
 
-	tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
-	if (div16)
-		tempval |= QE_BRGC_DIV16;
+	/* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
+	   that the BRG divisor must be even if you're not using divide-by-16
+	   mode. */
+	if (!div16 && (divisor & 1))
+		divisor++;
+
+	tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
+		QE_BRGC_ENABLE | div16;
 
-	out_be32(bp, tempval);
+	out_be32(&qe_immr->brg.brgc[brg - 1], tempval);
 }
 
 /* Initialize SNUMs (thread serial numbers) according to
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 55e6f39..9a2d1ed 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -405,8 +405,6 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags)
 		set_irq_data(qe_ic->virq_high, qe_ic);
 		set_irq_chained_handler(qe_ic->virq_high, qe_ic_cascade_high);
 	}
-
-	printk("QEIC (%d IRQ sources) at %p\n", NR_QE_IC_INTS, qe_ic->regs);
 }
 
 void qe_ic_set_highest_priority(unsigned int virq, int high)
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index e32b45b..a114cb0 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -195,29 +195,22 @@ EXPORT_SYMBOL(par_io_of_config);
 #ifdef DEBUG
 static void dump_par_io(void)
 {
-	int i;
+	unsigned int i;
 
-	printk(KERN_INFO "PAR IO registars:\n");
-	printk(KERN_INFO "Base address: 0x%08x\n", (u32) par_io);
+	printk(KERN_INFO "%s: par_io=%p\n", __FUNCTION__, par_io);
 	for (i = 0; i < num_par_io_ports; i++) {
-		printk(KERN_INFO "cpodr[%d] : addr - 0x%08x, val - 0x%08x\n",
-		       i, (u32) & par_io[i].cpodr,
-		       in_be32(&par_io[i].cpodr));
-		printk(KERN_INFO "cpdata[%d]: addr - 0x%08x, val - 0x%08x\n",
-		       i, (u32) & par_io[i].cpdata,
-		       in_be32(&par_io[i].cpdata));
-		printk(KERN_INFO "cpdir1[%d]: addr - 0x%08x, val - 0x%08x\n",
-		       i, (u32) & par_io[i].cpdir1,
-		       in_be32(&par_io[i].cpdir1));
-		printk(KERN_INFO "cpdir2[%d]: addr - 0x%08x, val - 0x%08x\n",
-		       i, (u32) & par_io[i].cpdir2,
-		       in_be32(&par_io[i].cpdir2));
-		printk(KERN_INFO "cppar1[%d]: addr - 0x%08x, val - 0x%08x\n",
-		       i, (u32) & par_io[i].cppar1,
-		       in_be32(&par_io[i].cppar1));
-		printk(KERN_INFO "cppar2[%d]: addr - 0x%08x, val - 0x%08x\n",
-		       i, (u32) & par_io[i].cppar2,
-		       in_be32(&par_io[i].cppar2));
+		printk(KERN_INFO "	cpodr[%u]=%08x\n", i,
+			in_be32(&par_io[i].cpodr));
+		printk(KERN_INFO "	cpdata[%u]=%08x\n", i,
+			in_be32(&par_io[i].cpdata));
+		printk(KERN_INFO "	cpdir1[%u]=%08x\n", i,
+			in_be32(&par_io[i].cpdir1));
+		printk(KERN_INFO "	cpdir2[%u]=%08x\n", i,
+			in_be32(&par_io[i].cpdir2));
+		printk(KERN_INFO "	cppar1[%u]=%08x\n", i,
+			in_be32(&par_io[i].cppar1));
+		printk(KERN_INFO "	cppar2[%u]=%08x\n", i,
+			in_be32(&par_io[i].cppar2));
 	}
 
 }
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index f970e54..0e348d9 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -28,228 +28,188 @@
 
 static DEFINE_SPINLOCK(ucc_lock);
 
-int ucc_set_qe_mux_mii_mng(int ucc_num)
+int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
 {
 	unsigned long flags;
 
+	if (ucc_num > UCC_MAX_NUM - 1)
+		return -EINVAL;
+
 	spin_lock_irqsave(&ucc_lock, flags);
-	out_be32(&qe_immr->qmx.cmxgcr,
-		 ((in_be32(&qe_immr->qmx.cmxgcr) &
-		   ~QE_CMXGCR_MII_ENET_MNG) |
-		  (ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT)));
+	clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
+		ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
 	spin_unlock_irqrestore(&ucc_lock, flags);
 
 	return 0;
 }
 EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
 
-int ucc_set_type(int ucc_num, struct ucc_common *regs,
-		 enum ucc_speed_type speed)
-{
-	u8 guemr = 0;
-
-	/* check if the UCC number is in range. */
-	if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
-		return -EINVAL;
-
-	guemr = regs->guemr;
-	guemr &= ~(UCC_GUEMR_MODE_MASK_RX | UCC_GUEMR_MODE_MASK_TX);
-	switch (speed) {
-	case UCC_SPEED_TYPE_SLOW:
-		guemr |= (UCC_GUEMR_MODE_SLOW_RX | UCC_GUEMR_MODE_SLOW_TX);
-		break;
-	case UCC_SPEED_TYPE_FAST:
-		guemr |= (UCC_GUEMR_MODE_FAST_RX | UCC_GUEMR_MODE_FAST_TX);
-		break;
-	default:
-		return -EINVAL;
-	}
-	regs->guemr = guemr;
-
-	return 0;
-}
-
-int ucc_init_guemr(struct ucc_common *regs)
+/* Configure the UCC to either Slow or Fast.
+ *
+ * A given UCC can be figured to support either "slow" devices (e.g. UART)
+ * or "fast" devices (e.g. Ethernet).
+ *
+ * 'ucc_num' is the UCC number, from 0 - 7.
+ *
+ * This function also sets the UCC_GUEMR_SET_RESERVED3 bit because that bit
+ * must always be set to 1.
+ */
+int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)
 {
-	u8 guemr = 0;
-
-	if (!regs)
-		return -EINVAL;
-
-	/* Set bit 3 (which is reserved in the GUEMR register) to 1 */
-	guemr = UCC_GUEMR_SET_RESERVED3;
-
-	regs->guemr = guemr;
-
-	return 0;
-}
+	u8 __iomem *guemr;
 
-static void get_cmxucr_reg(int ucc_num, volatile u32 ** p_cmxucr, u8 * reg_num,
-			   u8 * shift)
-{
+	/* The GUEMR register is at the same location for both slow and fast
+	   devices, so we just use uccX.slow.guemr. */
 	switch (ucc_num) {
-	case 0: *p_cmxucr = &(qe_immr->qmx.cmxucr1);
-		*reg_num = 1;
-		*shift = 16;
+	case 0: guemr = &qe_immr->ucc1.slow.guemr;
 		break;
-	case 2: *p_cmxucr = &(qe_immr->qmx.cmxucr1);
-		*reg_num = 1;
-		*shift = 0;
+	case 1: guemr = &qe_immr->ucc2.slow.guemr;
 		break;
-	case 4: *p_cmxucr = &(qe_immr->qmx.cmxucr2);
-		*reg_num = 2;
-		*shift = 16;
+	case 2: guemr = &qe_immr->ucc3.slow.guemr;
 		break;
-	case 6: *p_cmxucr = &(qe_immr->qmx.cmxucr2);
-		*reg_num = 2;
-		*shift = 0;
+	case 3: guemr = &qe_immr->ucc4.slow.guemr;
 		break;
-	case 1: *p_cmxucr = &(qe_immr->qmx.cmxucr3);
-		*reg_num = 3;
-		*shift = 16;
+	case 4: guemr = &qe_immr->ucc5.slow.guemr;
 		break;
-	case 3: *p_cmxucr = &(qe_immr->qmx.cmxucr3);
-		*reg_num = 3;
-		*shift = 0;
+	case 5: guemr = &qe_immr->ucc6.slow.guemr;
 		break;
-	case 5: *p_cmxucr = &(qe_immr->qmx.cmxucr4);
-		*reg_num = 4;
-		*shift = 16;
+	case 6: guemr = &qe_immr->ucc7.slow.guemr;
 		break;
-	case 7: *p_cmxucr = &(qe_immr->qmx.cmxucr4);
-		*reg_num = 4;
-		*shift = 0;
+	case 7: guemr = &qe_immr->ucc8.slow.guemr;
 		break;
 	default:
-		break;
+		return -EINVAL;
 	}
+
+	clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK,
+		UCC_GUEMR_SET_RESERVED3 | speed);
+
+	return 0;
+}
+
+static void get_cmxucr_reg(unsigned int ucc_num, __be32 **cmxucr,
+	unsigned int *reg_num, unsigned int *shift)
+{
+	unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3);
+
+	*reg_num = cmx + 1;
+	*cmxucr = &qe_immr->qmx.cmxucr[cmx];
+	*shift = 16 - 8 * (ucc_num & 2);
 }
 
-int ucc_mux_set_grant_tsa_bkpt(int ucc_num, int set, u32 mask)
+int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
 {
-	volatile u32 *p_cmxucr;
-	u8 reg_num;
-	u8 shift;
+	__be32 *cmxucr;
+	unsigned int reg_num;
+	unsigned int shift;
 
 	/* check if the UCC number is in range. */
-	if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
+	if (ucc_num > UCC_MAX_NUM - 1)
 		return -EINVAL;
 
-	get_cmxucr_reg(ucc_num, &p_cmxucr, &reg_num, &shift);
+	get_cmxucr_reg(ucc_num, &cmxucr, &reg_num, &shift);
 
 	if (set)
-		out_be32(p_cmxucr, in_be32(p_cmxucr) | (mask << shift));
+		setbits32(cmxucr, mask << shift);
 	else
-		out_be32(p_cmxucr, in_be32(p_cmxucr) & ~(mask << shift));
+		clrbits32(cmxucr, mask << shift);
 
 	return 0;
 }
 
-int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode)
+int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
+	enum comm_dir mode)
 {
-	volatile u32 *p_cmxucr;
-	u8 reg_num;
-	u8 shift;
-	u32 clock_bits;
-	u32 clock_mask;
-	int source = -1;
+	__be32 *cmxucr;
+	unsigned int reg_num;
+	unsigned int shift;
+	u32 clock_bits = 0;
 
 	/* check if the UCC number is in range. */
-	if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
+	if (ucc_num > UCC_MAX_NUM - 1)
 		return -EINVAL;
 
-	if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX))) {
-		printk(KERN_ERR
-		       "ucc_set_qe_mux_rxtx: bad comm mode type passed.");
+	/* The communications direction must be RX or TX */
+	if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))
 		return -EINVAL;
-	}
 
-	get_cmxucr_reg(ucc_num, &p_cmxucr, &reg_num, &shift);
+	get_cmxucr_reg(ucc_num, &cmxucr, &reg_num, &shift);
 
 	switch (reg_num) {
 	case 1:
 		switch (clock) {
-		case QE_BRG1:	source = 1; break;
-		case QE_BRG2:	source = 2; break;
-		case QE_BRG7:	source = 3; break;
-		case QE_BRG8:	source = 4; break;
-		case QE_CLK9:	source = 5; break;
-		case QE_CLK10:	source = 6; break;
-		case QE_CLK11:	source = 7; break;
-		case QE_CLK12:	source = 8; break;
-		case QE_CLK15:	source = 9; break;
-		case QE_CLK16:	source = 10; break;
-		default: 	source = -1; break;
+		case QE_BRG1:	clock_bits = 1; break;
+		case QE_BRG2:	clock_bits = 2; break;
+		case QE_BRG7:	clock_bits = 3; break;
+		case QE_BRG8:	clock_bits = 4; break;
+		case QE_CLK9:	clock_bits = 5; break;
+		case QE_CLK10:	clock_bits = 6; break;
+		case QE_CLK11:	clock_bits = 7; break;
+		case QE_CLK12:	clock_bits = 8; break;
+		case QE_CLK15:	clock_bits = 9; break;
+		case QE_CLK16:	clock_bits = 10; break;
+		default: break;
 		}
 		break;
 	case 2:
 		switch (clock) {
-		case QE_BRG5:	source = 1; break;
-		case QE_BRG6:	source = 2; break;
-		case QE_BRG7:	source = 3; break;
-		case QE_BRG8:	source = 4; break;
-		case QE_CLK13:	source = 5; break;
-		case QE_CLK14:	source = 6; break;
-		case QE_CLK19:	source = 7; break;
-		case QE_CLK20:	source = 8; break;
-		case QE_CLK15:	source = 9; break;
-		case QE_CLK16:	source = 10; break;
-		default: 	source = -1; break;
+		case QE_BRG5:	clock_bits = 1; break;
+		case QE_BRG6:	clock_bits = 2; break;
+		case QE_BRG7:	clock_bits = 3; break;
+		case QE_BRG8:	clock_bits = 4; break;
+		case QE_CLK13:	clock_bits = 5; break;
+		case QE_CLK14:	clock_bits = 6; break;
+		case QE_CLK19:	clock_bits = 7; break;
+		case QE_CLK20:	clock_bits = 8; break;
+		case QE_CLK15:	clock_bits = 9; break;
+		case QE_CLK16:	clock_bits = 10; break;
+		default: break;
 		}
 		break;
 	case 3:
 		switch (clock) {
-		case QE_BRG9:	source = 1; break;
-		case QE_BRG10:	source = 2; break;
-		case QE_BRG15:	source = 3; break;
-		case QE_BRG16:	source = 4; break;
-		case QE_CLK3:	source = 5; break;
-		case QE_CLK4:	source = 6; break;
-		case QE_CLK17:	source = 7; break;
-		case QE_CLK18:	source = 8; break;
-		case QE_CLK7:	source = 9; break;
-		case QE_CLK8:	source = 10; break;
-		case QE_CLK16:	source = 11; break;
-		default:	source = -1; break;
+		case QE_BRG9:	clock_bits = 1; break;
+		case QE_BRG10:	clock_bits = 2; break;
+		case QE_BRG15:	clock_bits = 3; break;
+		case QE_BRG16:	clock_bits = 4; break;
+		case QE_CLK3:	clock_bits = 5; break;
+		case QE_CLK4:	clock_bits = 6; break;
+		case QE_CLK17:	clock_bits = 7; break;
+		case QE_CLK18:	clock_bits = 8; break;
+		case QE_CLK7:	clock_bits = 9; break;
+		case QE_CLK8:	clock_bits = 10; break;
+		case QE_CLK16:	clock_bits = 11; break;
+		default: break;
 		}
 		break;
 	case 4:
 		switch (clock) {
-		case QE_BRG13:	source = 1; break;
-		case QE_BRG14:	source = 2; break;
-		case QE_BRG15:	source = 3; break;
-		case QE_BRG16:	source = 4; break;
-		case QE_CLK5:	source = 5; break;
-		case QE_CLK6:	source = 6; break;
-		case QE_CLK21:	source = 7; break;
-		case QE_CLK22:	source = 8; break;
-		case QE_CLK7:	source = 9; break;
-		case QE_CLK8:	source = 10; break;
-		case QE_CLK16:	source = 11; break;
-		default: 	source = -1; break;
+		case QE_BRG13:	clock_bits = 1; break;
+		case QE_BRG14:	clock_bits = 2; break;
+		case QE_BRG15:	clock_bits = 3; break;
+		case QE_BRG16:	clock_bits = 4; break;
+		case QE_CLK5:	clock_bits = 5; break;
+		case QE_CLK6:	clock_bits = 6; break;
+		case QE_CLK21:	clock_bits = 7; break;
+		case QE_CLK22:	clock_bits = 8; break;
+		case QE_CLK7:	clock_bits = 9; break;
+		case QE_CLK8:	clock_bits = 10; break;
+		case QE_CLK16:	clock_bits = 11; break;
+		default: break;
 		}
 		break;
-	default:
-		source = -1;
-		break;
+	default: break;
 	}
 
-	if (source == -1) {
-		printk(KERN_ERR
-		     "ucc_set_qe_mux_rxtx: Bad combination of clock and UCC.");
+	/* Check for invalid combination of clock and UCC number */
+	if (!clock_bits)
 		return -ENOENT;
-	}
 
-	clock_bits = (u32) source;
-	clock_mask = QE_CMXUCR_TX_CLK_SRC_MASK;
-	if (mode == COMM_DIR_RX) {
-		clock_bits <<= 4;  /* Rx field is 4 bits to left of Tx field */
-		clock_mask <<= 4;  /* Rx field is 4 bits to left of Tx field */
-	}
-	clock_bits <<= shift;
-	clock_mask <<= shift;
+	if (mode == COMM_DIR_RX)
+		shift += 4;
 
-	out_be32(p_cmxucr, (in_be32(p_cmxucr) & ~clock_mask) | clock_bits);
+	clrsetbits_be32(cmxucr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,
+		clock_bits << shift);
 
 	return 0;
 }
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index 3df202e..3223acb 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -30,46 +30,45 @@
 
 void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
 {
-	printk(KERN_INFO "UCC%d Fast registers:", uccf->uf_info->ucc_num);
-	printk(KERN_INFO "Base address: 0x%08x", (u32) uccf->uf_regs);
-
-	printk(KERN_INFO "gumr  : addr - 0x%08x, val - 0x%08x",
-		  (u32) & uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
-	printk(KERN_INFO "upsmr : addr - 0x%08x, val - 0x%08x",
-		  (u32) & uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
-	printk(KERN_INFO "utodr : addr - 0x%08x, val - 0x%04x",
-		  (u32) & uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
-	printk(KERN_INFO "udsr  : addr - 0x%08x, val - 0x%04x",
-		  (u32) & uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
-	printk(KERN_INFO "ucce  : addr - 0x%08x, val - 0x%08x",
-		  (u32) & uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
-	printk(KERN_INFO "uccm  : addr - 0x%08x, val - 0x%08x",
-		  (u32) & uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
-	printk(KERN_INFO "uccs  : addr - 0x%08x, val - 0x%02x",
-		  (u32) & uccf->uf_regs->uccs, uccf->uf_regs->uccs);
-	printk(KERN_INFO "urfb  : addr - 0x%08x, val - 0x%08x",
-		  (u32) & uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
-	printk(KERN_INFO "urfs  : addr - 0x%08x, val - 0x%04x",
-		  (u32) & uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
-	printk(KERN_INFO "urfet : addr - 0x%08x, val - 0x%04x",
-		  (u32) & uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
-	printk(KERN_INFO "urfset: addr - 0x%08x, val - 0x%04x",
-		  (u32) & uccf->uf_regs->urfset,
-		  in_be16(&uccf->uf_regs->urfset));
-	printk(KERN_INFO "utfb  : addr - 0x%08x, val - 0x%08x",
-		  (u32) & uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
-	printk(KERN_INFO "utfs  : addr - 0x%08x, val - 0x%04x",
-		  (u32) & uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
-	printk(KERN_INFO "utfet : addr - 0x%08x, val - 0x%04x",
-		  (u32) & uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
-	printk(KERN_INFO "utftt : addr - 0x%08x, val - 0x%04x",
-		  (u32) & uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
-	printk(KERN_INFO "utpt  : addr - 0x%08x, val - 0x%04x",
-		  (u32) & uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
-	printk(KERN_INFO "urtry : addr - 0x%08x, val - 0x%08x",
-		  (u32) & uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
-	printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x",
-		  (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
+	printk(KERN_INFO "UCC%u Fast registers:\n", uccf->uf_info->ucc_num);
+	printk(KERN_INFO "Base address: 0x%p\n", uccf->uf_regs);
+
+	printk(KERN_INFO "gumr  : addr=0x%p, val=0x%08x\n",
+		  &uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
+	printk(KERN_INFO "upsmr : addr=0x%p, val=0x%08x\n",
+		  &uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
+	printk(KERN_INFO "utodr : addr=0x%p, val=0x%04x\n",
+		  &uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
+	printk(KERN_INFO "udsr  : addr=0x%p, val=0x%04x\n",
+		  &uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
+	printk(KERN_INFO "ucce  : addr=0x%p, val=0x%08x\n",
+		  &uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
+	printk(KERN_INFO "uccm  : addr=0x%p, val=0x%08x\n",
+		  &uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
+	printk(KERN_INFO "uccs  : addr=0x%p, val=0x%02x\n",
+		  &uccf->uf_regs->uccs, uccf->uf_regs->uccs);
+	printk(KERN_INFO "urfb  : addr=0x%p, val=0x%08x\n",
+		  &uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
+	printk(KERN_INFO "urfs  : addr=0x%p, val=0x%04x\n",
+		  &uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
+	printk(KERN_INFO "urfet : addr=0x%p, val=0x%04x\n",
+		  &uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
+	printk(KERN_INFO "urfset: addr=0x%p, val=0x%04x\n",
+		  &uccf->uf_regs->urfset, in_be16(&uccf->uf_regs->urfset));
+	printk(KERN_INFO "utfb  : addr=0x%p, val=0x%08x\n",
+		  &uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
+	printk(KERN_INFO "utfs  : addr=0x%p, val=0x%04x\n",
+		  &uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
+	printk(KERN_INFO "utfet : addr=0x%p, val=0x%04x\n",
+		  &uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
+	printk(KERN_INFO "utftt : addr=0x%p, val=0x%04x\n",
+		  &uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
+	printk(KERN_INFO "utpt  : addr=0x%p, val=0x%04x\n",
+		  &uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
+	printk(KERN_INFO "urtry : addr=0x%p, val=0x%08x\n",
+		  &uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
+	printk(KERN_INFO "guemr : addr=0x%p, val=0x%02x\n",
+		  &uccf->uf_regs->guemr, uccf->uf_regs->guemr);
 }
 EXPORT_SYMBOL(ucc_fast_dump_regs);
 
@@ -149,55 +148,57 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 
 	/* check if the UCC port number is in range. */
 	if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
-		printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__);
+		printk(KERN_ERR "%s: illegal UCC number\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	/* Check that 'max_rx_buf_length' is properly aligned (4). */
 	if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
-		printk(KERN_ERR "%s: max_rx_buf_length not aligned", __FUNCTION__);
+		printk(KERN_ERR "%s: max_rx_buf_length not aligned\n",
+			__FUNCTION__);
 		return -EINVAL;
 	}
 
 	/* Validate Virtual Fifo register values */
 	if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
-		printk(KERN_ERR "%s: urfs is too small", __FUNCTION__);
+		printk(KERN_ERR "%s: urfs is too small\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		printk(KERN_ERR "%s: urfs is not aligned", __FUNCTION__);
+		printk(KERN_ERR "%s: urfs is not aligned\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		printk(KERN_ERR "%s: urfet is not aligned.", __FUNCTION__);
+		printk(KERN_ERR "%s: urfet is not aligned.\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		printk(KERN_ERR "%s: urfset is not aligned", __FUNCTION__);
+		printk(KERN_ERR "%s: urfset is not aligned\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		printk(KERN_ERR "%s: utfs is not aligned", __FUNCTION__);
+		printk(KERN_ERR "%s: utfs is not aligned\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		printk(KERN_ERR "%s: utfet is not aligned", __FUNCTION__);
+		printk(KERN_ERR "%s: utfet is not aligned\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
-		printk(KERN_ERR "%s: utftt is not aligned", __FUNCTION__);
+		printk(KERN_ERR "%s: utftt is not aligned\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
 	uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
 	if (!uccf) {
-		printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__);
+		printk(KERN_ERR "%s: Cannot allocate private data\n",
+			__FUNCTION__);
 		return -ENOMEM;
 	}
 
@@ -206,7 +207,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 	/* Set the PHY base address */
 	uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast));
 	if (uccf->uf_regs == NULL) {
-		printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__);
+		printk(KERN_ERR "%s: Cannot map UCC registers\n", __FUNCTION__);
 		return -ENOMEM;
 	}
 
@@ -226,18 +227,10 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 	uccf->rx_discarded = 0;
 #endif				/* STATISTICS */
 
-	/* Init Guemr register */
-	if ((ret = ucc_init_guemr((struct ucc_common *) (uf_regs)))) {
-		printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
-		ucc_fast_free(uccf);
-		return ret;
-	}
-
 	/* Set UCC to fast type */
-	if ((ret = ucc_set_type(uf_info->ucc_num,
-				(struct ucc_common *) (uf_regs),
-				UCC_SPEED_TYPE_FAST))) {
-		printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
+	ret = ucc_set_type(uf_info->ucc_num, UCC_SPEED_TYPE_FAST);
+	if (ret) {
+		printk(KERN_ERR "%s: cannot set UCC type\n", __FUNCTION__);
 		ucc_fast_free(uccf);
 		return ret;
 	}
@@ -276,7 +269,8 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 	uccf->ucc_fast_tx_virtual_fifo_base_offset =
 	    qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 	if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
-		printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO", __FUNCTION__);
+		printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n",
+			__FUNCTION__);
 		uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
 		ucc_fast_free(uccf);
 		return -ENOMEM;
@@ -288,7 +282,8 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 			   UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
 			   UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 	if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
-		printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO", __FUNCTION__);
+		printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO\n",
+			__FUNCTION__);
 		uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
 		ucc_fast_free(uccf);
 		return -ENOMEM;
@@ -318,7 +313,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 		if ((uf_info->rx_clock != QE_CLK_NONE) &&
 		    ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock,
 					COMM_DIR_RX)) {
-			printk(KERN_ERR "%s: illegal value for RX clock",
+			printk(KERN_ERR "%s: illegal value for RX clock\n",
 			       __FUNCTION__);
 			ucc_fast_free(uccf);
 			return -EINVAL;
@@ -327,7 +322,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 		if ((uf_info->tx_clock != QE_CLK_NONE) &&
 		    ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock,
 					COMM_DIR_TX)) {
-			printk(KERN_ERR "%s: illegal value for TX clock",
+			printk(KERN_ERR "%s: illegal value for TX clock\n",
 			       __FUNCTION__);
 			ucc_fast_free(uccf);
 			return -EINVAL;
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index 1f65c26..0174b3a 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -115,11 +115,15 @@ void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
 	out_be32(&us_regs->gumr_l, gumr_l);
 }
 
+/* Initialize the UCC for Slow operations
+ *
+ * The caller should initialize the following us_info
+ */
 int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret)
 {
 	struct ucc_slow_private *uccs;
 	u32 i;
-	struct ucc_slow *us_regs;
+	struct ucc_slow __iomem *us_regs;
 	u32 gumr;
 	struct qe_bd *bd;
 	u32 id;
@@ -131,7 +135,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 
 	/* check if the UCC port number is in range. */
 	if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
-		printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__);
+		printk(KERN_ERR "%s: illegal UCC number\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
@@ -143,13 +147,14 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 	 */
 	if ((!us_info->rfw) &&
 		(us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) {
-		printk(KERN_ERR "max_rx_buf_length not aligned.");
+		printk(KERN_ERR "max_rx_buf_length not aligned.\n");
 		return -EINVAL;
 	}
 
 	uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
 	if (!uccs) {
-		printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__);
+		printk(KERN_ERR "%s: Cannot allocate private data\n",
+			__FUNCTION__);
 		return -ENOMEM;
 	}
 
@@ -158,7 +163,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 	/* Set the PHY base address */
 	uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow));
 	if (uccs->us_regs == NULL) {
-		printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__);
+		printk(KERN_ERR "%s: Cannot map UCC registers\n", __FUNCTION__);
 		return -ENOMEM;
 	}
 
@@ -182,22 +187,14 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 		return -ENOMEM;
 	}
 	id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
-	qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, QE_CR_PROTOCOL_UNSPECIFIED,
+	qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, us_info->protocol,
 		     uccs->us_pram_offset);
 
 	uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
 
-	/* Init Guemr register */
-	if ((ret = ucc_init_guemr((struct ucc_common *) us_regs))) {
-		printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
-		ucc_slow_free(uccs);
-		return ret;
-	}
-
 	/* Set UCC to slow type */
-	if ((ret = ucc_set_type(us_info->ucc_num,
-				(struct ucc_common *) us_regs,
-				UCC_SPEED_TYPE_SLOW))) {
+	ret = ucc_set_type(us_info->ucc_num, UCC_SPEED_TYPE_SLOW);
+	if (ret) {
 		printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
 		ucc_slow_free(uccs);
 		return ret;
@@ -212,7 +209,8 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 		qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
 				QE_ALIGNMENT_OF_BD);
 	if (IS_ERR_VALUE(uccs->rx_base_offset)) {
-		printk(KERN_ERR "%s: cannot allocate RX BDs", __FUNCTION__);
+		printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __FUNCTION__,
+			us_info->rx_bd_ring_len);
 		uccs->rx_base_offset = 0;
 		ucc_slow_free(uccs);
 		return -ENOMEM;
@@ -292,12 +290,12 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 
 	/* if the data is in cachable memory, the 'global' */
 	/* in the function code should be set. */
-	uccs->us_pram->tfcr = uccs->us_pram->rfcr =
-		us_info->data_mem_part | QE_BMR_BYTE_ORDER_BO_MOT;
+	uccs->us_pram->tbmr = UCC_BMR_BO_BE;
+	uccs->us_pram->rbmr = UCC_BMR_BO_BE;
 
 	/* rbase, tbase are offsets from MURAM base */
-	out_be16(&uccs->us_pram->rbase, uccs->us_pram_offset);
-	out_be16(&uccs->us_pram->tbase, uccs->us_pram_offset);
+	out_be16(&uccs->us_pram->rbase, uccs->rx_base_offset);
+	out_be16(&uccs->us_pram->tbase, uccs->tx_base_offset);
 
 	/* Mux clocking */
 	/* Grant Support */
@@ -311,7 +309,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 		/* Rx clock routing */
 		if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock,
 					COMM_DIR_RX)) {
-			printk(KERN_ERR "%s: illegal value for RX clock",
+			printk(KERN_ERR "%s: illegal value for RX clock\n",
 			       __FUNCTION__);
 			ucc_slow_free(uccs);
 			return -EINVAL;
@@ -319,7 +317,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 		/* Tx clock routing */
 		if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock,
 					COMM_DIR_TX)) {
-			printk(KERN_ERR "%s: illegal value for TX clock",
+			printk(KERN_ERR "%s: illegal value for TX clock\n",
 			       __FUNCTION__);
 			ucc_slow_free(uccs);
 			return -EINVAL;
@@ -343,8 +341,8 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 		command = QE_INIT_TX;
 	else
 		command = QE_INIT_RX;	/* We know at least one is TRUE */
-	id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
-	qe_issue_cmd(command, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+	qe_issue_cmd(command, id, us_info->protocol, 0);
 
 	*uccs_ret = uccs;
 	return 0;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 9a38dfe..7dedc96 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -2919,7 +2919,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
 	test = in_be16(&ugeth->p_tx_glbl_pram->temoder);
 
 	/* Function code register value to be used later */
-	function_code = QE_BMR_BYTE_ORDER_BO_MOT | UCC_FAST_FUNCTION_CODE_GBL;
+	function_code = UCC_BMR_BO_BE | UCC_BMR_GBL;
 	/* Required for QE */
 
 	/* function code register */
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index bb4dac8..1aa6902 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -44,6 +44,7 @@
 
 struct ucc_geth {
 	struct ucc_fast uccf;
+	u8 res0[0x100 - sizeof(struct ucc_fast)];
 
 	u32 maccfg1;		/* mac configuration reg. 1 */
 	u32 maccfg2;		/* mac configuration reg. 2 */
diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
index 1020b7f..e1db782 100644
--- a/include/asm-powerpc/immap_qe.h
+++ b/include/asm-powerpc/immap_qe.h
@@ -96,10 +96,7 @@ struct qe_mux {
 	__be32	cmxsi1cr_l;	/* CMX SI1 clock route low register */
 	__be32	cmxsi1cr_h;	/* CMX SI1 clock route high register */
 	__be32	cmxsi1syr;	/* CMX SI1 SYNC route register */
-	__be32	cmxucr1;	/* CMX UCC1, UCC3 clock route register */
-	__be32	cmxucr2;	/* CMX UCC5, UCC7 clock route register */
-	__be32	cmxucr3;	/* CMX UCC2, UCC4 clock route register */
-	__be32	cmxucr4;	/* CMX UCC6, UCC8 clock route register */
+	__be32	cmxucr[4];	/* CMX UCCx clock route registers */
 	__be32	cmxupcr;	/* CMX UPC clock route register */
 	u8	res0[0x1C];
 } __attribute__ ((packed));
@@ -260,7 +257,6 @@ struct ucc_slow {
 	__be16	utpt;
 	u8	res4[0x52];
 	u8	guemr;		/* UCC general extended mode register */
-	u8	res5[0x200 - 0x091];
 } __attribute__ ((packed));
 
 /* QE UCC Fast */
@@ -293,21 +289,13 @@ struct ucc_fast {
 	__be32	urtry;		/* UCC retry counter register */
 	u8	res8[0x4C];
 	u8	guemr;		/* UCC general extended mode register */
-	u8	res9[0x100 - 0x091];
-} __attribute__ ((packed));
-
-/* QE UCC */
-struct ucc_common {
-	u8	res1[0x90];
-	u8	guemr;
-	u8	res2[0x200 - 0x091];
 } __attribute__ ((packed));
 
 struct ucc {
 	union {
 		struct	ucc_slow slow;
 		struct	ucc_fast fast;
-		struct	ucc_common common;
+		u8	res[0x200];	/* UCC blocks are 512 bytes each */
 	};
 } __attribute__ ((packed));
 
@@ -406,7 +394,7 @@ struct dbg {
 
 /* RISC Special Registers (Trap and Breakpoint) */
 struct rsp {
-	u8	fixme[0x100];
+	u32	reg[0x40];	/* 64 32-bit registers */
 } __attribute__ ((packed));
 
 struct qe_immap {
@@ -435,11 +423,13 @@ struct qe_immap {
 	u8			res13[0x600];
 	struct upc		upc2;		/* MultiPHY UTOPIA POS Ctrlr 2*/
 	struct sdma		sdma;		/* SDMA */
-	struct dbg		dbg;		/* Debug Space */
-	struct rsp		rsp[0x2];	/* RISC Special Registers
+	struct dbg		dbg;		/* 0x104080 - 0x1040FF
+						   Debug Space */
+	struct rsp		rsp[0x2];	/* 0x104100 - 0x1042FF
+						   RISC Special Registers
 						   (Trap and Breakpoint) */
-	u8			res14[0x300];
-	u8			res15[0x3A00];
+	u8			res14[0x300];	/* 0x104300 - 0x1045FF */
+	u8			res15[0x3A00];	/* 0x104600 - 0x107FFF */
 	u8			res16[0x8000];	/* 0x108000 - 0x110000 */
 	u8			muram[0xC000];	/* 0x110000 - 0x11C000
 						   Multi-user RAM */
@@ -450,7 +440,7 @@ struct qe_immap {
 extern struct qe_immap *qe_immr;
 extern phys_addr_t get_qe_base(void);
 
-static inline unsigned long immrbar_virt_to_phys(volatile void * address)
+static inline unsigned long immrbar_virt_to_phys(void *address)
 {
 	if ( ((u32)address >= (u32)qe_immr) &&
 			((u32)address < ((u32)qe_immr + QE_IMMAP_SIZE)) )
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index ad23c58..0dabe46 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -38,7 +38,7 @@ extern int par_io_data_set(u8 port, u8 pin, u8 val);
 
 /* QE internal API */
 int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
-void qe_setbrg(u32 brg, u32 rate);
+void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier);
 int qe_get_snum(void);
 void qe_put_snum(u8 snum);
 unsigned long qe_muram_alloc(int size, int align);
@@ -49,14 +49,28 @@ void *qe_muram_addr(unsigned long offset);
 
 /* Buffer descriptors */
 struct qe_bd {
-	u16 status;
-	u16 length;
-	u32 buf;
+	__be16 status;
+	__be16 length;
+	__be32 buf;
 } __attribute__ ((packed));
 
 #define BD_STATUS_MASK	0xffff0000
 #define BD_LENGTH_MASK	0x0000ffff
 
+#define BD_SC_EMPTY	0x8000	/* Receive is empty */
+#define BD_SC_READY	0x8000	/* Transmit is ready */
+#define BD_SC_WRAP	0x2000	/* Last buffer descriptor */
+#define BD_SC_INTRPT	0x1000	/* Interrupt on change */
+#define BD_SC_LAST	0x0800	/* Last buffer in frame */
+#define BD_SC_CM	0x0200	/* Continous mode */
+#define BD_SC_ID	0x0100	/* Rec'd too many idles */
+#define BD_SC_P		0x0100	/* xmt preamble */
+#define BD_SC_BR	0x0020	/* Break received */
+#define BD_SC_FR	0x0010	/* Framing error */
+#define BD_SC_PR	0x0008	/* Parity error */
+#define BD_SC_OV	0x0002	/* Overrun */
+#define BD_SC_CD	0x0001	/* ?? */
+
 /* Alignment */
 #define QE_INTR_TABLE_ALIGN	16	/* ??? */
 #define QE_ALIGNMENT_OF_BD	8
@@ -269,15 +283,12 @@ enum qe_clock {
 /* QE CECR Protocol - For non-MCC, specifies mode for QE CECR command */
 #define QE_CR_PROTOCOL_UNSPECIFIED	0x00	/* For all other protocols */
 #define QE_CR_PROTOCOL_HDLC_TRANSPARENT	0x00
+#define QE_CR_PROTOCOL_QMC		0x02
+#define QE_CR_PROTOCOL_UART		0x04
 #define QE_CR_PROTOCOL_ATM_POS		0x0A
 #define QE_CR_PROTOCOL_ETHERNET		0x0C
 #define QE_CR_PROTOCOL_L2_SWITCH	0x0D
 
-/* BMR byte order */
-#define QE_BMR_BYTE_ORDER_BO_PPC	0x08	/* powerpc little endian */
-#define QE_BMR_BYTE_ORDER_BO_MOT	0x10	/* motorola big endian */
-#define QE_BMR_BYTE_ORDER_BO_MAX	0x18
-
 /* BRG configuration register */
 #define QE_BRGC_ENABLE		0x00010000
 #define QE_BRGC_DIVISOR_SHIFT	1
@@ -324,41 +335,41 @@ enum qe_clock {
 #define UPGCR_ADDR	0x10000000	/* Master MPHY Addr multiplexing */
 #define UPGCR_DIAG	0x01000000	/* Diagnostic mode */
 
-/* UCC */
+/* UCC GUEMR register */
 #define UCC_GUEMR_MODE_MASK_RX	0x02
-#define UCC_GUEMR_MODE_MASK_TX	0x01
 #define UCC_GUEMR_MODE_FAST_RX	0x02
-#define UCC_GUEMR_MODE_FAST_TX	0x01
 #define UCC_GUEMR_MODE_SLOW_RX	0x00
+#define UCC_GUEMR_MODE_MASK_TX	0x01
+#define UCC_GUEMR_MODE_FAST_TX	0x01
 #define UCC_GUEMR_MODE_SLOW_TX	0x00
+#define UCC_GUEMR_MODE_MASK (UCC_GUEMR_MODE_MASK_RX | UCC_GUEMR_MODE_MASK_TX)
 #define UCC_GUEMR_SET_RESERVED3	0x10	/* Bit 3 in the guemr is reserved but
 					   must be set 1 */
 
 /* structure representing UCC SLOW parameter RAM */
 struct ucc_slow_pram {
-	u16 rbase;		/* RX BD base address */
-	u16 tbase;		/* TX BD base address */
-	u8 rfcr;		/* Rx function code */
-	u8 tfcr;		/* Tx function code */
-	u16 mrblr;		/* Rx buffer length */
-	u32 rstate;		/* Rx internal state */
-	u32 rptr;		/* Rx internal data pointer */
-	u16 rbptr;		/* rb BD Pointer */
-	u16 rcount;		/* Rx internal byte count */
-	u32 rtemp;		/* Rx temp */
-	u32 tstate;		/* Tx internal state */
-	u32 tptr;		/* Tx internal data pointer */
-	u16 tbptr;		/* Tx BD pointer */
-	u16 tcount;		/* Tx byte count */
-	u32 ttemp;		/* Tx temp */
-	u32 rcrc;		/* temp receive CRC */
-	u32 tcrc;		/* temp transmit CRC */
+	__be16 rbase;		/* RX BD base address */
+	__be16 tbase;		/* TX BD base address */
+	u8 rbmr;		/* RX bus mode register (same as CPM's RFCR) */
+	u8 tbmr;		/* TX bus mode register (same as CPM's TFCR) */
+	__be16 mrblr;		/* Rx buffer length */
+	__be32 rstate;		/* Rx internal state */
+	__be32 rptr;		/* Rx internal data pointer */
+	__be16 rbptr;		/* rb BD Pointer */
+	__be16 rcount;		/* Rx internal byte count */
+	__be32 rtemp;		/* Rx temp */
+	__be32 tstate;		/* Tx internal state */
+	__be32 tptr;		/* Tx internal data pointer */
+	__be16 tbptr;		/* Tx BD pointer */
+	__be16 tcount;		/* Tx byte count */
+	__be32 ttemp;		/* Tx temp */
+	__be32 rcrc;		/* temp receive CRC */
+	__be32 tcrc;		/* temp transmit CRC */
 } __attribute__ ((packed));
 
 /* General UCC SLOW Mode Register (GUMRH & GUMRL) */
-#define UCC_SLOW_GUMR_H_CRC16		0x00004000
-#define UCC_SLOW_GUMR_H_CRC16CCITT	0x00000000
-#define UCC_SLOW_GUMR_H_CRC32CCITT	0x00008000
+#define UCC_SLOW_GUMR_H_SAM_QMC		0x00000000
+#define UCC_SLOW_GUMR_H_SAM_SATM	0x00008000
 #define UCC_SLOW_GUMR_H_REVD		0x00002000
 #define UCC_SLOW_GUMR_H_TRX		0x00001000
 #define UCC_SLOW_GUMR_H_TTX		0x00000800
@@ -378,9 +389,33 @@ struct ucc_slow_pram {
 #define UCC_SLOW_GUMR_L_TCI		0x10000000
 #define UCC_SLOW_GUMR_L_RINV		0x02000000
 #define UCC_SLOW_GUMR_L_TINV		0x01000000
-#define UCC_SLOW_GUMR_L_TEND		0x00020000
+#define UCC_SLOW_GUMR_L_TEND		0x00040000
+#define UCC_SLOW_GUMR_L_TDCR_MASK	0x00030000
+#define UCC_SLOW_GUMR_L_TDCR_32	        0x00030000
+#define UCC_SLOW_GUMR_L_TDCR_16	        0x00020000
+#define UCC_SLOW_GUMR_L_TDCR_8	        0x00010000
+#define UCC_SLOW_GUMR_L_TDCR_1	        0x00000000
+#define UCC_SLOW_GUMR_L_RDCR_MASK	0x0000c000
+#define UCC_SLOW_GUMR_L_RDCR_32		0x0000c000
+#define UCC_SLOW_GUMR_L_RDCR_16	        0x00008000
+#define UCC_SLOW_GUMR_L_RDCR_8	        0x00004000
+#define UCC_SLOW_GUMR_L_RDCR_1		0x00000000
+#define UCC_SLOW_GUMR_L_RENC_NRZI	0x00000800
+#define UCC_SLOW_GUMR_L_RENC_NRZ	0x00000000
+#define UCC_SLOW_GUMR_L_TENC_NRZI	0x00000100
+#define UCC_SLOW_GUMR_L_TENC_NRZ	0x00000000
+#define UCC_SLOW_GUMR_L_DIAG_MASK	0x000000c0
+#define UCC_SLOW_GUMR_L_DIAG_LE	        0x000000c0
+#define UCC_SLOW_GUMR_L_DIAG_ECHO	0x00000080
+#define UCC_SLOW_GUMR_L_DIAG_LOOP	0x00000040
+#define UCC_SLOW_GUMR_L_DIAG_NORM	0x00000000
 #define UCC_SLOW_GUMR_L_ENR		0x00000020
 #define UCC_SLOW_GUMR_L_ENT		0x00000010
+#define UCC_SLOW_GUMR_L_MODE_MASK	0x0000000F
+#define UCC_SLOW_GUMR_L_MODE_BISYNC	0x00000008
+#define UCC_SLOW_GUMR_L_MODE_AHDLC	0x00000006
+#define UCC_SLOW_GUMR_L_MODE_UART	0x00000004
+#define UCC_SLOW_GUMR_L_MODE_QMC	0x00000002
 
 /* General UCC FAST Mode Register */
 #define UCC_FAST_GUMR_TCI	0x20000000
@@ -397,53 +432,111 @@ struct ucc_slow_pram {
 #define UCC_FAST_GUMR_ENR	0x00000020
 #define UCC_FAST_GUMR_ENT	0x00000010
 
-/* Slow UCC Event Register (UCCE) */
-#define UCC_SLOW_UCCE_GLR	0x1000
-#define UCC_SLOW_UCCE_GLT	0x0800
-#define UCC_SLOW_UCCE_DCC	0x0400
-#define UCC_SLOW_UCCE_FLG	0x0200
-#define UCC_SLOW_UCCE_AB	0x0200
-#define UCC_SLOW_UCCE_IDLE	0x0100
-#define UCC_SLOW_UCCE_GRA	0x0080
-#define UCC_SLOW_UCCE_TXE	0x0010
-#define UCC_SLOW_UCCE_RXF	0x0008
-#define UCC_SLOW_UCCE_CCR	0x0008
-#define UCC_SLOW_UCCE_RCH	0x0008
-#define UCC_SLOW_UCCE_BSY	0x0004
-#define UCC_SLOW_UCCE_TXB	0x0002
-#define UCC_SLOW_UCCE_TX	0x0002
-#define UCC_SLOW_UCCE_RX	0x0001
-#define UCC_SLOW_UCCE_GOV	0x0001
-#define UCC_SLOW_UCCE_GUN	0x0002
-#define UCC_SLOW_UCCE_GINT	0x0004
-#define UCC_SLOW_UCCE_IQOV	0x0008
-
-#define UCC_SLOW_UCCE_HDLC_SET	(UCC_SLOW_UCCE_TXE | UCC_SLOW_UCCE_BSY | \
-		UCC_SLOW_UCCE_GRA | UCC_SLOW_UCCE_TXB | UCC_SLOW_UCCE_RXF | \
-		UCC_SLOW_UCCE_DCC | UCC_SLOW_UCCE_GLT | UCC_SLOW_UCCE_GLR)
-#define UCC_SLOW_UCCE_ENET_SET	(UCC_SLOW_UCCE_TXE | UCC_SLOW_UCCE_BSY | \
-		UCC_SLOW_UCCE_GRA | UCC_SLOW_UCCE_TXB | UCC_SLOW_UCCE_RXF)
-#define UCC_SLOW_UCCE_TRANS_SET	(UCC_SLOW_UCCE_TXE | UCC_SLOW_UCCE_BSY | \
-		UCC_SLOW_UCCE_GRA | UCC_SLOW_UCCE_TX | UCC_SLOW_UCCE_RX | \
-		UCC_SLOW_UCCE_DCC | UCC_SLOW_UCCE_GLT | UCC_SLOW_UCCE_GLR)
-#define UCC_SLOW_UCCE_UART_SET	(UCC_SLOW_UCCE_BSY | UCC_SLOW_UCCE_GRA | \
-		UCC_SLOW_UCCE_TXB | UCC_SLOW_UCCE_TX | UCC_SLOW_UCCE_RX | \
-		UCC_SLOW_UCCE_GLT | UCC_SLOW_UCCE_GLR)
-#define UCC_SLOW_UCCE_QMC_SET	(UCC_SLOW_UCCE_IQOV | UCC_SLOW_UCCE_GINT | \
-		UCC_SLOW_UCCE_GUN | UCC_SLOW_UCCE_GOV)
-
-#define UCC_SLOW_UCCE_OTHER	(UCC_SLOW_UCCE_TXE | UCC_SLOW_UCCE_BSY | \
-		UCC_SLOW_UCCE_GRA | UCC_SLOW_UCCE_DCC | UCC_SLOW_UCCE_GLT | \
-		UCC_SLOW_UCCE_GLR)
-
-#define UCC_SLOW_INTR_TX	UCC_SLOW_UCCE_TXB
-#define UCC_SLOW_INTR_RX	(UCC_SLOW_UCCE_RXF | UCC_SLOW_UCCE_RX)
-#define UCC_SLOW_INTR		(UCC_SLOW_INTR_TX | UCC_SLOW_INTR_RX)
+/* UART Slow UCC Event Register (UCCE) */
+#define UCC_UART_UCCE_AB	0x0200
+#define UCC_UART_UCCE_IDLE	0x0100
+#define UCC_UART_UCCE_GRA	0x0080
+#define UCC_UART_UCCE_BRKE	0x0040
+#define UCC_UART_UCCE_BRKS	0x0020
+#define UCC_UART_UCCE_CCR	0x0008
+#define UCC_UART_UCCE_BSY	0x0004
+#define UCC_UART_UCCE_TX	0x0002
+#define UCC_UART_UCCE_RX	0x0001
+
+/* HDLC Slow UCC Event Register (UCCE) */
+#define UCC_HDLC_UCCE_GLR	0x1000
+#define UCC_HDLC_UCCE_GLT	0x0800
+#define UCC_HDLC_UCCE_IDLE	0x0100
+#define UCC_HDLC_UCCE_BRKE	0x0040
+#define UCC_HDLC_UCCE_BRKS	0x0020
+#define UCC_HDLC_UCCE_TXE	0x0010
+#define UCC_HDLC_UCCE_RXF	0x0008
+#define UCC_HDLC_UCCE_BSY	0x0004
+#define UCC_HDLC_UCCE_TXB	0x0002
+#define UCC_HDLC_UCCE_RXB	0x0001
+
+/* BISYNC Slow UCC Event Register (UCCE) */
+#define UCC_BISYNC_UCCE_GRA	0x0080
+#define UCC_BISYNC_UCCE_TXE	0x0010
+#define UCC_BISYNC_UCCE_RCH	0x0008
+#define UCC_BISYNC_UCCE_BSY	0x0004
+#define UCC_BISYNC_UCCE_TXB	0x0002
+#define UCC_BISYNC_UCCE_RXB	0x0001
+
+/* Gigabit Ethernet Fast UCC Event Register (UCCE) */
+#define UCC_GETH_UCCE_MPD       0x80000000
+#define UCC_GETH_UCCE_SCAR      0x40000000
+#define UCC_GETH_UCCE_GRA       0x20000000
+#define UCC_GETH_UCCE_CBPR      0x10000000
+#define UCC_GETH_UCCE_BSY       0x08000000
+#define UCC_GETH_UCCE_RXC       0x04000000
+#define UCC_GETH_UCCE_TXC       0x02000000
+#define UCC_GETH_UCCE_TXE       0x01000000
+#define UCC_GETH_UCCE_TXB7      0x00800000
+#define UCC_GETH_UCCE_TXB6      0x00400000
+#define UCC_GETH_UCCE_TXB5      0x00200000
+#define UCC_GETH_UCCE_TXB4      0x00100000
+#define UCC_GETH_UCCE_TXB3      0x00080000
+#define UCC_GETH_UCCE_TXB2      0x00040000
+#define UCC_GETH_UCCE_TXB1      0x00020000
+#define UCC_GETH_UCCE_TXB0      0x00010000
+#define UCC_GETH_UCCE_RXB7      0x00008000
+#define UCC_GETH_UCCE_RXB6      0x00004000
+#define UCC_GETH_UCCE_RXB5      0x00002000
+#define UCC_GETH_UCCE_RXB4      0x00001000
+#define UCC_GETH_UCCE_RXB3      0x00000800
+#define UCC_GETH_UCCE_RXB2      0x00000400
+#define UCC_GETH_UCCE_RXB1      0x00000200
+#define UCC_GETH_UCCE_RXB0      0x00000100
+#define UCC_GETH_UCCE_RXF7      0x00000080
+#define UCC_GETH_UCCE_RXF6      0x00000040
+#define UCC_GETH_UCCE_RXF5      0x00000020
+#define UCC_GETH_UCCE_RXF4      0x00000010
+#define UCC_GETH_UCCE_RXF3      0x00000008
+#define UCC_GETH_UCCE_RXF2      0x00000004
+#define UCC_GETH_UCCE_RXF1      0x00000002
+#define UCC_GETH_UCCE_RXF0      0x00000001
+
+/* UPSMR, when used as a UART */
+#define UCC_UART_UPSMR_FLC		0x8000
+#define UCC_UART_UPSMR_SL		0x4000
+#define UCC_UART_UPSMR_CL_MASK		0x3000
+#define UCC_UART_UPSMR_CL_8		0x3000
+#define UCC_UART_UPSMR_CL_7		0x2000
+#define UCC_UART_UPSMR_CL_6		0x1000
+#define UCC_UART_UPSMR_CL_5		0x0000
+#define UCC_UART_UPSMR_UM_MASK		0x0c00
+#define UCC_UART_UPSMR_UM_NORMAL	0x0000
+#define UCC_UART_UPSMR_UM_MAN_MULTI	0x0400
+#define UCC_UART_UPSMR_UM_AUTO_MULTI	0x0c00
+#define UCC_UART_UPSMR_FRZ		0x0200
+#define UCC_UART_UPSMR_RZS		0x0100
+#define UCC_UART_UPSMR_SYN		0x0080
+#define UCC_UART_UPSMR_DRT		0x0040
+#define UCC_UART_UPSMR_PEN		0x0010
+#define UCC_UART_UPSMR_RPM_MASK		0x000c
+#define UCC_UART_UPSMR_RPM_ODD		0x0000
+#define UCC_UART_UPSMR_RPM_LOW		0x0004
+#define UCC_UART_UPSMR_RPM_EVEN		0x0008
+#define UCC_UART_UPSMR_RPM_HIGH		0x000C
+#define UCC_UART_UPSMR_TPM_MASK		0x0003
+#define UCC_UART_UPSMR_TPM_ODD		0x0000
+#define UCC_UART_UPSMR_TPM_LOW		0x0001
+#define UCC_UART_UPSMR_TPM_EVEN		0x0002
+#define UCC_UART_UPSMR_TPM_HIGH		0x0003
 
 /* UCC Transmit On Demand Register (UTODR) */
 #define UCC_SLOW_TOD	0x8000
 #define UCC_FAST_TOD	0x8000
 
+/* UCC Bus Mode Register masks */
+/* Not to be confused with the Bundle Mode Register */
+#define UCC_BMR_GBL		0x20
+#define UCC_BMR_BO_BE		0x10
+#define UCC_BMR_CETM		0x04
+#define UCC_BMR_DTB		0x02
+#define UCC_BMR_BDB		0x01
+
 /* Function code masks */
 #define FC_GBL				0x20
 #define FC_DTB_LCL			0x02
diff --git a/include/asm-powerpc/ucc.h b/include/asm-powerpc/ucc.h
index afe3076..46b09ba 100644
--- a/include/asm-powerpc/ucc.h
+++ b/include/asm-powerpc/ucc.h
@@ -25,58 +25,38 @@
 /* Slow or fast type for UCCs.
 */
 enum ucc_speed_type {
-	UCC_SPEED_TYPE_FAST, UCC_SPEED_TYPE_SLOW
-};
-
-/* Initial UCCs Parameter RAM address relative to: MEM_MAP_BASE (IMMR).
-*/
-enum ucc_pram_initial_offset {
-	UCC_PRAM_OFFSET_UCC1 = 0x8400,
-	UCC_PRAM_OFFSET_UCC2 = 0x8500,
-	UCC_PRAM_OFFSET_UCC3 = 0x8600,
-	UCC_PRAM_OFFSET_UCC4 = 0x9000,
-	UCC_PRAM_OFFSET_UCC5 = 0x8000,
-	UCC_PRAM_OFFSET_UCC6 = 0x8100,
-	UCC_PRAM_OFFSET_UCC7 = 0x8200,
-	UCC_PRAM_OFFSET_UCC8 = 0x8300
+	UCC_SPEED_TYPE_FAST = UCC_GUEMR_MODE_FAST_RX | UCC_GUEMR_MODE_FAST_TX,
+	UCC_SPEED_TYPE_SLOW = UCC_GUEMR_MODE_SLOW_RX | UCC_GUEMR_MODE_SLOW_TX
 };
 
 /* ucc_set_type
  * Sets UCC to slow or fast mode.
  *
  * ucc_num - (In) number of UCC (0-7).
- * regs    - (In) pointer to registers base for the UCC.
  * speed   - (In) slow or fast mode for UCC.
  */
-int ucc_set_type(int ucc_num, struct ucc_common *regs,
-		 enum ucc_speed_type speed);
-
-/* ucc_init_guemr
- * Init the Guemr register.
- *
- * regs - (In) pointer to registers base for the UCC.
- */
-int ucc_init_guemr(struct ucc_common *regs);
+int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed);
 
-int ucc_set_qe_mux_mii_mng(int ucc_num);
+int ucc_set_qe_mux_mii_mng(unsigned int ucc_num);
 
-int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode);
+int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
+	enum comm_dir mode);
 
-int ucc_mux_set_grant_tsa_bkpt(int ucc_num, int set, u32 mask);
+int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask);
 
 /* QE MUX clock routing for UCC
 */
-static inline int ucc_set_qe_mux_grant(int ucc_num, int set)
+static inline int ucc_set_qe_mux_grant(unsigned int ucc_num, int set)
 {
 	return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_GRANT);
 }
 
-static inline int ucc_set_qe_mux_tsa(int ucc_num, int set)
+static inline int ucc_set_qe_mux_tsa(unsigned int ucc_num, int set)
 {
 	return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_TSA);
 }
 
-static inline int ucc_set_qe_mux_bkpt(int ucc_num, int set)
+static inline int ucc_set_qe_mux_bkpt(unsigned int ucc_num, int set)
 {
 	return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_BKPT);
 }
diff --git a/include/asm-powerpc/ucc_slow.h b/include/asm-powerpc/ucc_slow.h
index fdaac9d..0980e6a 100644
--- a/include/asm-powerpc/ucc_slow.h
+++ b/include/asm-powerpc/ucc_slow.h
@@ -148,9 +148,10 @@ enum ucc_slow_diag_mode {
 
 struct ucc_slow_info {
 	int ucc_num;
+	int protocol;			/* QE_CR_PROTOCOL_xxx */
 	enum qe_clock rx_clock;
 	enum qe_clock tx_clock;
-	u32 regs;
+	phys_addr_t regs;
 	int irq;
 	u16 uccm_mask;
 	int data_mem_part;
@@ -186,7 +187,7 @@ struct ucc_slow_info {
 
 struct ucc_slow_private {
 	struct ucc_slow_info *us_info;
-	struct ucc_slow *us_regs;	/* a pointer to memory map of UCC regs */
+	struct ucc_slow __iomem *us_regs; /* Ptr to memory map of UCC regs */
 	struct ucc_slow_pram *us_pram;	/* a pointer to the parameter RAM */
 	u32 us_pram_offset;
 	int enabled_tx;		/* Whether channel is enabled for Tx (ENT) */
@@ -277,12 +278,12 @@ void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs);
  */
 void ucc_slow_stop_tx(struct ucc_slow_private * uccs);
 
-/* ucc_slow_restart_x
+/* ucc_slow_restart_tx
  * Restarts transmitting on a specified slow UCC.
  *
  * uccs - (In) pointer to the slow UCC structure.
  */
-void ucc_slow_restart_x(struct ucc_slow_private * uccs);
+void ucc_slow_restart_tx(struct ucc_slow_private *uccs);
 
 u32 ucc_slow_get_qe_cr_subblock(int uccs_num);
 
-- 
1.5.2.4


^ permalink raw reply related

* Re: [PATCH] net: fix race in process_backlog
From: Stephen Hemminger @ 2007-10-03 16:15 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: linux-kernel, netdev, Jeff Dike, David Miller
In-Reply-To: <1191426293.5599.27.camel@lappy>

On Wed, 03 Oct 2007 17:44:53 +0200
Peter Zijlstra <a.p.zijlstra@chello.nl> wrote:

> Subject: net: fix race in process_backlog
> 
> The recent NAPI rework (4fa57c9ea9f36f9ca852f3a88ca5d2f1aebbc960)
> introduced a race between netif_rx() and process_backlog() which
> resulted in softirq processing to drop dead.
> 
> netif_rx()		process_backlog()
> 
> 			irq_disable();
> 			skb = __skb_dequeue();
> 			irq_enable();
> 
> irq_disable();
> __skb_queue_tail();
> napi_schedule();
> irq_enable();
> 
> 			if (!skb)
> 			  napi_complete();  <-- oops!
> 
> we cleared the napi bit, even though there is data to process.
> 
> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>

Acked-by: Stephen Hemminger <shemminger@linux-foundation.org>


-- 
Stephen Hemminger <shemminger@linux-foundation.org>

^ permalink raw reply

* [PATCH] net: fix race in process_backlog
From: Peter Zijlstra @ 2007-10-03 15:44 UTC (permalink / raw)
  To: linux-kernel, netdev; +Cc: Stephen Hemminger, Jeff Dike, David Miller

Subject: net: fix race in process_backlog

The recent NAPI rework (4fa57c9ea9f36f9ca852f3a88ca5d2f1aebbc960)
introduced a race between netif_rx() and process_backlog() which
resulted in softirq processing to drop dead.

netif_rx()		process_backlog()

			irq_disable();
			skb = __skb_dequeue();
			irq_enable();

irq_disable();
__skb_queue_tail();
napi_schedule();
irq_enable();

			if (!skb)
			  napi_complete();  <-- oops!

we cleared the napi bit, even though there is data to process.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 net/core/dev.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: linux-2.6/net/core/dev.c
===================================================================
--- linux-2.6.orig/net/core/dev.c
+++ linux-2.6/net/core/dev.c
@@ -2095,11 +2095,11 @@ static int process_backlog(struct napi_s
 
 		local_irq_disable();
 		skb = __skb_dequeue(&queue->input_pkt_queue);
-		local_irq_enable();
 		if (!skb) {
-			napi_complete(napi);
+			__napi_complete(napi);
 			break;
 		}
+		local_irq_enable();
 
 		dev = skb->dev;
 

^ permalink raw reply

* Re: [PATCH net-2.6.24 0/3]: More TCP fixes
From: Cedric Le Goater @ 2007-10-03 15:12 UTC (permalink / raw)
  To: Cedric Le Goater; +Cc: Ilpo Järvinen, David Miller, Netdev
In-Reply-To: <4703AE04.5090009@free.fr>

Cedric Le Goater wrote:
> Ilpo Järvinen wrote:
>> On Wed, 3 Oct 2007, Cedric Le Goater wrote:
>>
>>> Ilpo Järvinen wrote:
>>>> Ah, that's path 1) then... Since you seem to have enough time, I would say 
>>>> that the path 1 is good as well and bugs unrelated to the fix will show up 
>>>> there too...
>>> arg. yes. sorry for the confusion.
>>>
>>>> I should have stated it explicitly that with path 2 those 3 patches should 
>>>> not be applied because the aim is not a fix but reproducal. Path 2 was 
>>>> intentionally left without the potentional fix as then nice backtrace 
>>>> informs when we can stop trying (which would hopefully occurred 
>>>> pretty soon) :-).  But lets discard that path 2...
>>> I have 2 spare nodes so i'll run both. 1) is on already without any issues
>>> i'm just compiling 2)
> 
> Below are the messages I got on 2) right after running ketchup (which does 
> a wget www.kernel.org) 
> 
> not a warning on 1) with your extra verbose patch.

bummer, I got this one on 1) :(

C.

WARNING: at /home/legoater/linux/net-2.6.24.git/net/ipv4/tcp_input.c:2325 tcp_fastretrans_alert()

Call Trace:
 <IRQ>  [<ffffffff8022ddb6>] __wake_up+0x1f/0x4c
 [<ffffffff803fd9d3>] tcp_ack+0xcee/0x18ac
 [<ffffffff80400764>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8024e8d8>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8040795b>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff804082d5>] tcp_v4_rcv+0x624/0x9b1
 [<ffffffff803ecfa3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff803ed900>] ip_rcv+0x57c/0x5c4
 [<ffffffff8045ae53>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803ce78e>] netif_receive_skb+0x2ba/0x2de
 [<ffffffff88044505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803ce958>] net_rx_action+0xb8/0x191
 [<ffffffff802385cb>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c97c>] call_softirq+0x1c/0x28
 [<ffffffff8020e672>] do_softirq+0x3b/0xb9
 [<ffffffff802386c2>] irq_exit+0x4e/0x50
 [<ffffffff8020e48e>] do_IRQ+0xbe/0xd8
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bcc6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80464e10>] __sched_text_start+0x5f0/0x62b
 [<ffffffff80464e10>] __sched_text_start+0x5f0/0x62b
 [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80464513>] rest_init+0x57/0x59
 [<ffffffff8060c82a>] start_kernel+0x2d1/0x2dd
 [<ffffffff8060c14e>] _sinittext+0x14e/0x155

WARNING: at /home/legoater/linux/net-2.6.24.git/net/ipv4/tcp_input.c:2325 tcp_fastretrans_alert()

Call Trace:
 <IRQ>  [<ffffffff8022ddb6>] __wake_up+0x1f/0x4c
 [<ffffffff803fd9d3>] tcp_ack+0xcee/0x18ac
 [<ffffffff80400764>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8024e8d8>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8040795b>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff804082d5>] tcp_v4_rcv+0x624/0x9b1
 [<ffffffff803ecfa3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff803ed900>] ip_rcv+0x57c/0x5c4
 [<ffffffff8045ae53>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803ce78e>] netif_receive_skb+0x2ba/0x2de
 [<ffffffff88044505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803ce958>] net_rx_action+0xb8/0x191
 [<ffffffff802385cb>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c97c>] call_softirq+0x1c/0x28
 [<ffffffff8020e672>] do_softirq+0x3b/0xb9
 [<ffffffff802386c2>] irq_exit+0x4e/0x50
 [<ffffffff8020e48e>] do_IRQ+0xbe/0xd8
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bcc6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80464e10>] __sched_text_start+0x5f0/0x62b
 [<ffffffff80464e10>] __sched_text_start+0x5f0/0x62b
 [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80464513>] rest_init+0x57/0x59
 [<ffffffff8060c82a>] start_kernel+0x2d1/0x2dd



^ permalink raw reply

* Re: [PATCH net-2.6.24 0/3]: More TCP fixes
From: Cedric Le Goater @ 2007-10-03 14:59 UTC (permalink / raw)
  To: Cedric Le Goater; +Cc: Ilpo Järvinen, David Miller, Netdev
In-Reply-To: <4703AE04.5090009@free.fr>

Cedric Le Goater wrote:
> Ilpo Järvinen wrote:
>> On Wed, 3 Oct 2007, Cedric Le Goater wrote:
>>
>>> Ilpo Järvinen wrote:
>>>> Ah, that's path 1) then... Since you seem to have enough time, I would say 
>>>> that the path 1 is good as well and bugs unrelated to the fix will show up 
>>>> there too...
>>> arg. yes. sorry for the confusion.
>>>
>>>> I should have stated it explicitly that with path 2 those 3 patches should 
>>>> not be applied because the aim is not a fix but reproducal. Path 2 was 
>>>> intentionally left without the potentional fix as then nice backtrace 
>>>> informs when we can stop trying (which would hopefully occurred 
>>>> pretty soon) :-).  But lets discard that path 2...
>>> I have 2 spare nodes so i'll run both. 1) is on already without any issues
>>> i'm just compiling 2)
> 
> Below are the messages I got on 2) right after running ketchup (which does 
> a wget www.kernel.org) 

and a second run of ketchup gave the following.

cheers,

C.

WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:193 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff8041aa86>] tcp_verify_fackets+0x119/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

TCP wq(s) --S------<
TCP wq(i)   h      <
s1 f5 (14) p6 seq: su110259658 hs110265450 sn110278722 (0)
WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:193 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff803250aa>] vgacon_scroll+0x188/0x1dd
 [<ffffffff8041aa86>] tcp_verify_fackets+0x119/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:198 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff803250aa>] vgacon_scroll+0x188/0x1dd
 [<ffffffff8041aad0>] tcp_verify_fackets+0x163/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

TCP wq(s) ---SSS-----<
TCP wq(i)      hf    <
s3 f7 (14) p7 seq: su110259658 hs110268346 sn110278722 (110269794)




C.

^ permalink raw reply

* Re: [PATCH net-2.6.24 0/3]: More TCP fixes
From: Cedric Le Goater @ 2007-10-03 14:58 UTC (permalink / raw)
  To: Ilpo Järvinen; +Cc: David Miller, Netdev
In-Reply-To: <Pine.LNX.4.64.0710031709450.27745@kivilampi-30.cs.helsinki.fi>

Ilpo Järvinen wrote:
> On Wed, 3 Oct 2007, Cedric Le Goater wrote:
> 
>> Ilpo Järvinen wrote:
>>> Ah, that's path 1) then... Since you seem to have enough time, I would say 
>>> that the path 1 is good as well and bugs unrelated to the fix will show up 
>>> there too...
>> arg. yes. sorry for the confusion.
>>
>>> I should have stated it explicitly that with path 2 those 3 patches should 
>>> not be applied because the aim is not a fix but reproducal. Path 2 was 
>>> intentionally left without the potentional fix as then nice backtrace 
>>> informs when we can stop trying (which would hopefully occurred 
>>> pretty soon) :-).  But lets discard that path 2...
>> I have 2 spare nodes so i'll run both. 1) is on already without any issues
>> i'm just compiling 2)

Below are the messages I got on 2) right after running ketchup (which does 
a wget www.kernel.org) 

not a warning on 1) with your extra verbose patch.

>> I usually work on -mm, so what would be interesting for me is to have what you 
>> need in net-2.6.24 which is getting pulled in -mm by andrew. then, if 
>> you need an extra patch for verbosity, that's fine, i'll include it in 
>> my usual patchset.
> 
> Ah, I'm sorry about the subject and the extra work it caused, 

no problem, that was a comment for the futur patchset.
 
> it was meant for DaveM only, didn't realize at that time it would be 
> meaningful to you as well, thus couldn't warn you back then... Testing on 
> top of mm would be (/ have been) fine as well... From my point of view 
> both mm and net-2.6.24 are pretty much the same (I even verified that 
> those patches apply fine on top of rc8-mm2 since I thought that you might 
> want to use that one).

He, you might have solved it with 1). If not, I'm keeping the hardware for
you.

Cheers,

C.

WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:193 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff8041aa86>] tcp_verify_fackets+0x119/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:198 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff80323bf6>] vgacon_set_cursor_size+0x39/0xd5
 [<ffffffff8041aad0>] tcp_verify_fackets+0x163/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

TCP wq(s) -S--SSS--------------------<
TCP wq(i)       hf                   <
s4 f9 (47) p9 seq: su3460595874 hs3460607374 sn3460659962 (3460608822)
WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:193 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff80323bf6>] vgacon_set_cursor_size+0x39/0xd5
 [<ffffffff8041aa86>] tcp_verify_fackets+0x119/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:198 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff80323bf6>] vgacon_set_cursor_size+0x39/0xd5
 [<ffffffff8041aad0>] tcp_verify_fackets+0x163/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

TCP wq(s) -S---SSSSSS------------------<
TCP wq(i)           hf                 <
s7 f12 (47) p12 seq: su3460595874 hs3460611718 sn3460659962 (3460613166)
WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:193 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff8041aa86>] tcp_verify_fackets+0x119/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

TCP wq(s) --S--------<
TCP wq(i)   h        <
s1 f7 (19) p8 seq: su3633343602 hs3633352290 sn3633370354 (0)
WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:193 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff80323bf6>] vgacon_set_cursor_size+0x39/0xd5
 [<ffffffff8041aa86>] tcp_verify_fackets+0x119/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:198 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff80323bf6>] vgacon_set_cursor_size+0x39/0xd5
 [<ffffffff8041aad0>] tcp_verify_fackets+0x163/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

TCP wq(s) ---S-S-------<
TCP wq(i)      hf      <
s2 f9 (19) p9 seq: su3633343602 hs3633355102 sn3633370354 (3633356550)
WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:193 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff80323bf6>] vgacon_set_cursor_size+0x39/0xd5
 [<ffffffff8041aa86>] tcp_verify_fackets+0x119/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:198 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff80323bf6>] vgacon_set_cursor_size+0x39/0xd5
 [<ffffffff8041aad0>] tcp_verify_fackets+0x163/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

TCP wq(s) ----S-SSS-----<
TCP wq(i)         hf    <
s4 f11 (19) p11 seq: su3633343602 hs3633357998 sn3633370354 (3633359446)
WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:193 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff80323bf6>] vgacon_set_cursor_size+0x39/0xd5
 [<ffffffff8041aa86>] tcp_verify_fackets+0x119/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

WARNING: at /home/legoater/linux/2.6.23-rc8-mm2-tcp_fastretrans/net/ipv4/tcp_ipv4.c:198 tcp_verify_fackets()

Call Trace:
 <IRQ>  [<ffffffff80323bf6>] vgacon_set_cursor_size+0x39/0xd5
 [<ffffffff8041aad0>] tcp_verify_fackets+0x163/0x237
 [<ffffffff80416e57>] tcp_fragment+0x468/0x4b8
 [<ffffffff804184a5>] tcp_retransmit_skb+0xcf/0x2f4
 [<ffffffff8041878d>] tcp_xmit_retransmit_queue+0xc3/0x31e
 [<ffffffff8041220a>] tcp_fastretrans_alert+0xb36/0xb43
 [<ffffffff80412f0f>] tcp_ack+0x5d3/0x71b
 [<ffffffff80415229>] tcp_rcv_established+0x61f/0x6df
 [<ffffffff8025419a>] __lock_acquire+0x8a1/0xf1b
 [<ffffffff8041c7ff>] tcp_v4_do_rcv+0x3e/0x394
 [<ffffffff8041d171>] tcp_v4_rcv+0x61c/0x9a9
 [<ffffffff804017e3>] ip_local_deliver+0x1da/0x2a4
 [<ffffffff8040214e>] ip_rcv+0x583/0x5c9
 [<ffffffff8046fe43>] packet_rcv_spkt+0x19a/0x1a8
 [<ffffffff803e2e1c>] netif_receive_skb+0x2cf/0x2f5
 [<ffffffff88042505>] :tg3:tg3_poll+0x65d/0x8a4
 [<ffffffff803e2fe8>] net_rx_action+0xb8/0x191
 [<ffffffff8023a9b7>] __do_softirq+0x5f/0xe0
 [<ffffffff8020c98c>] call_softirq+0x1c/0x28
 [<ffffffff8020e9c3>] do_softirq+0x3b/0xb8
 [<ffffffff8023aaae>] irq_exit+0x4e/0x50
 [<ffffffff8020e7df>] do_IRQ+0xbd/0xd7
 [<ffffffff80209cb9>] mwait_idle+0x0/0x4d
 [<ffffffff8020bce6>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff80209cfc>] mwait_idle+0x43/0x4d
 [<ffffffff802099fb>] enter_idle+0x22/0x24
 [<ffffffff80209c4f>] cpu_idle+0x9d/0xc0
 [<ffffffff80479591>] rest_init+0x55/0x57
 [<ffffffff8063681f>] start_kernel+0x2e0/0x2ec
 [<ffffffff80636134>] _sinittext+0x134/0x13b

TCP wq(s) -----S-SSSS-----<
TCP wq(i)           hf    <
s5 f12 (19) p12 seq: su3633343602 hs3633359446 sn3633370354 (3633360894)



^ permalink raw reply

* [IPv6] Fix ICMPv6 redirect handling with target multicast address, try 3
From: Brian Haley @ 2007-10-03 14:44 UTC (permalink / raw)
  To: David Miller, YOSHIFUJI Hideaki; +Cc: netdev@vger.kernel.org, David Stevens
In-Reply-To: <4702997D.6020208@hp.com>

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

When the ICMPv6 Target address is multicast, Linux processes the 
redirect instead of dropping it.  The problem is in this code in 
ndisc_redirect_rcv():

         if (ipv6_addr_equal(dest, target)) {
                 on_link = 1;
         } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
                 ND_PRINTK2(KERN_WARNING
                            "ICMPv6 Redirect: target address is not 
link-local.\n");
                 return;
         }

This second check will succeed if the Target address is, for example, 
FF02::1 because it has link-local scope.  Instead, it should be checking 
if it's a unicast link-local address, as stated in RFC 2461/4861 Section 
8.1:

       - The ICMP Target Address is either a link-local address (when
         redirected to a router) or the same as the ICMP Destination
         Address (when redirected to the on-link destination).

I know this doesn't explicitly say unicast link-local address, but it's 
implied.

This bug is preventing Linux kernels from achieving IPv6 Logo Phase II 
certification because of a recent error that was found in the TAHI test 
suite - Neighbor Disovery suite test 206 (v6LC.2.3.6_G) had the 
multicast address in the Destination field instead of Target field, so 
we were passing the test.  This won't be the case anymore.

The patch below fixes this problem, and also fixes ndisc_send_redirect() 
to not send an invalid redirect with a multicast address in the Target 
field.  I re-ran the TAHI Neighbor Discovery section to make sure Linux 
passes all 245 tests now.

-Brian


Signed-off-by: Brian Haley <brian.haley@hp.com>
Acked-by: David L Stevens <dlstevens@us.ibm.com>

[-- Attachment #2: ipv6.redirect.patch --]
[-- Type: text/x-patch, Size: 1051 bytes --]

diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 74c4d8d..b761dbe 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1267,9 +1267,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
 
 	if (ipv6_addr_equal(dest, target)) {
 		on_link = 1;
-	} else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
+	} else if (ipv6_addr_type(target) !=
+		   (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
 		ND_PRINTK2(KERN_WARNING
-			   "ICMPv6 Redirect: target address is not link-local.\n");
+			   "ICMPv6 Redirect: target address is not link-local unicast.\n");
 		return;
 	}
 
@@ -1343,9 +1344,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 	}
 
 	if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) &&
-	    !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
+	    ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
 		ND_PRINTK2(KERN_WARNING
-			"ICMPv6 Redirect: target address is not link-local.\n");
+			"ICMPv6 Redirect: target address is not link-local unicast.\n");
 		return;
 	}
 

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox