From c23f92244cdb69c98b49a7441118464ceba74340 Mon Sep 17 00:00:00 2001
From: John Crispin <john@openwrt.org>
Date: Sun, 25 Oct 2009 00:11:08 +0000
Subject: [PATCH] fixes dma hangups in eth

SVN-Revision: 18139
---
 .../arch/mips/include/asm/mach-ralink/eth.h   | 14 +++++-----
 .../linux/ramips/files/drivers/net/ramips.c   | 27 ++++++++++---------
 .../ramips/files/drivers/net/ramips_esw.c     |  3 +++
 3 files changed, 25 insertions(+), 19 deletions(-)

diff --git a/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/eth.h b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/eth.h
index 27cf6dffff..efacc5d1ec 100644
--- a/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/eth.h
+++ b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/eth.h
@@ -199,15 +199,17 @@ struct ramips_eth_platform_data
 struct raeth_priv
 {
 	unsigned int			phy_rx;
-    struct tasklet_struct	rx_tasklet;
-    struct ramips_rx_dma	*rx;
+	struct tasklet_struct	rx_tasklet;
+	struct ramips_rx_dma	*rx;
+	struct sk_buff			*rx_skb[NUM_RX_DESC];
 
 	unsigned int			phy_tx;
-    struct tasklet_struct	tx_housekeeping_tasklet;
-    struct ramips_tx_dma	*tx;
+	struct tasklet_struct	tx_housekeeping_tasklet;
+	struct ramips_tx_dma	*tx;
+	struct sk_buff			*tx_skb[NUM_RX_DESC];
 
-    unsigned int			skb_free_idx;
-    struct net_device_stats	stat;
+	unsigned int			skb_free_idx;
+	struct net_device_stats	stat;
 
 	struct ramips_eth_platform_data *plat;
 };
diff --git a/target/linux/ramips/files/drivers/net/ramips.c b/target/linux/ramips/files/drivers/net/ramips.c
index 42d38ccda2..4ea81db744 100644
--- a/target/linux/ramips/files/drivers/net/ramips.c
+++ b/target/linux/ramips/files/drivers/net/ramips.c
@@ -91,7 +91,7 @@ ramips_alloc_dma(struct net_device *dev)
 			dma_map_single(NULL, skb_put(new_skb, 2), MAX_RX_LENGTH + 2,
 				PCI_DMA_FROMDEVICE);
 		priv->rx[i].rxd2 |= RX_DMA_LSO;
-		priv->rx[i].rxd3 = (unsigned int)new_skb;
+		priv->rx_skb[i] = new_skb;
 	}
 	dma_cache_wback_inv((unsigned long)priv->rx,
 		NUM_RX_DESC * (sizeof(struct ramips_rx_dma)));
@@ -131,7 +131,7 @@ ramips_eth_hard_start_xmit(struct sk_buff* skb, struct net_device *dev)
 		tx_next = 0;
 	else
 		tx_next = tx + 1;
-	if((priv->tx[tx].txd3 == 0) && (priv->tx[tx_next].txd3 == 0))
+	if((priv->tx_skb[tx]== 0) && (priv->tx_skb[tx_next] == 0))
 	{
 		if(!(priv->tx[tx].txd2 & TX_DMA_DONE))
 		{
@@ -146,7 +146,7 @@ ramips_eth_hard_start_xmit(struct sk_buff* skb, struct net_device *dev)
 		ramips_fe_wr((tx + 1) % NUM_TX_DESC, RAMIPS_TX_CTX_IDX0);
 		priv->stat.tx_packets++;
 		priv->stat.tx_bytes += skb->len;
-		priv->tx[tx].txd3 = (unsigned int)skb;
+		priv->tx_skb[tx] = skb;
 		ramips_fe_wr((tx + 1) % NUM_TX_DESC, RAMIPS_TX_CTX_IDX0);
 	} else {
 		priv->stat.tx_dropped++;
@@ -172,7 +172,7 @@ ramips_eth_rx_hw(unsigned long ptr)
 			break;
 		max_rx--;
 
-		rx_skb = (struct sk_buff*)priv->rx[rx].rxd3;
+		rx_skb = priv->rx_skb[rx];
 		rx_skb->len = RX_DMA_PLEN0(priv->rx[rx].rxd2);
 		rx_skb->tail = rx_skb->data + rx_skb->len;
 		rx_skb->dev = dev;
@@ -183,7 +183,7 @@ ramips_eth_rx_hw(unsigned long ptr)
 		netif_rx(rx_skb);
 
 		new_skb = __dev_alloc_skb(MAX_RX_LENGTH + 2, GFP_DMA | GFP_ATOMIC);
-		priv->rx[rx].rxd3 = (unsigned int)new_skb;
+		priv->rx_skb[rx] = new_skb;
 		BUG_ON(!new_skb);
 		skb_reserve(new_skb, 2);
 		priv->rx[rx].rxd1 =
@@ -208,10 +208,10 @@ ramips_eth_tx_housekeeping(unsigned long ptr)
 	struct raeth_priv *priv = (struct raeth_priv*)netdev_priv(dev);
 
 	while((priv->tx[priv->skb_free_idx].txd2 & TX_DMA_DONE) &&
-		(priv->tx[priv->skb_free_idx].txd3))
+		(priv->tx_skb[priv->skb_free_idx]))
 	{
-		dev_kfree_skb_irq((struct sk_buff*)priv->tx[priv->skb_free_idx].txd3);
-		priv->tx[priv->skb_free_idx].txd3 = 0;
+		dev_kfree_skb_irq((struct sk_buff*)priv->tx_skb[priv->skb_free_idx]);
+		priv->tx_skb[priv->skb_free_idx] = 0;
 		priv->skb_free_idx++;
 		if(priv->skb_free_idx >= NUM_TX_DESC)
 			priv->skb_free_idx = 0;
@@ -323,7 +323,7 @@ ramips_eth_probe(struct net_device *dev)
 	struct raeth_priv *priv = (struct raeth_priv*)netdev_priv(dev);
 	struct sockaddr addr;
 
-	BUG(!priv->plat->reset_fe);
+	BUG_ON(!priv->plat->reset_fe);
 	priv->plat->reset_fe();
 	net_srandom(jiffies);
 	memcpy(addr.sa_data, priv->plat->mac, 6);
@@ -345,20 +345,21 @@ static int
 ramips_eth_plat_probe(struct platform_device *plat)
 {
 	struct raeth_priv *priv;
-
-	ramips_fe_base = ioremap_nocache(plat->base_addr, PAGE_SIZE);
+	struct ramips_eth_platform_data *data =
+		(struct ramips_eth_platform_data*)plat->dev.platform_data;
+	ramips_fe_base = ioremap_nocache(data->base_addr, PAGE_SIZE);
 	if(!ramips_fe_base)
 		return -ENOMEM;
 	ramips_dev = alloc_etherdev(sizeof(struct raeth_priv));
 	if(!ramips_dev)
 		return -ENOMEM;
 	strcpy(ramips_dev->name, "eth%d");
-	ramips_dev->irq = plat->irq;
+	ramips_dev->irq = data->irq;
 	ramips_dev->addr_len = ETH_ALEN;
 	ramips_dev->base_addr = (unsigned long)ramips_fe_base;
 	ramips_dev->init = ramips_eth_probe;
 	priv = (struct raeth_priv*)netdev_priv(ramips_dev);
-	priv->plat = (struct ramips_eth_platform_data*)plat->dev.platform_data;
+	priv->plat = data;
 	if(register_netdev(ramips_dev))
 	{
 		printk(KERN_ERR "ramips_eth: error bringing up device\n");
diff --git a/target/linux/ramips/files/drivers/net/ramips_esw.c b/target/linux/ramips/files/drivers/net/ramips_esw.c
index a77060075b..f9d31c2fb4 100644
--- a/target/linux/ramips/files/drivers/net/ramips_esw.c
+++ b/target/linux/ramips/files/drivers/net/ramips_esw.c
@@ -1,3 +1,6 @@
+#include <rt305x.h>
+#include <rt305x_regs.h>
+
 #define GPIO_PRUPOSE           0x60
 #define GPIO_MDIO_BIT          (1<<7)
 #define RT305X_ESW_PHY_WRITE		(1 << 13)