Browse Source

cpmac: reapply [9664]

SVN-Revision: 10424
Matteo Croce 18 years ago
parent
commit
cae0acba53
1 changed files with 169 additions and 17 deletions
  1. 169 17
      target/linux/ar7/patches-2.6.24/140-cpmac_fix.patch

+ 169 - 17
target/linux/ar7/patches-2.6.24/140-cpmac_fix.patch

@@ -1,17 +1,97 @@
---- linux-2.6.24/drivers/net/Kconfig	2008-01-25 02:20:37.000000000 +0100
-+++ linux-2.6.24/drivers/net/Kconfig	2008-02-08 18:12:02.000000000 +0100
-@@ -1709,8 +1709,6 @@
- 	tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
- 	depends on NET_ETHERNET && EXPERIMENTAL && AR7
- 	select PHYLIB
--	select FIXED_PHY
--	select FIXED_MII_100_FDX
- 	help
- 	  TI AR7 CPMAC Ethernet support
- 
 --- linux-2.6.24/drivers/net/cpmac.c	2008-01-25 02:20:37.000000000 +0100
-+++ linux-2.6.24/drivers/net/cpmac.c	2008-02-08 18:05:35.000000000 +0100
-@@ -661,9 +661,6 @@
++++ linux-2.6.24/drivers/net/cpmac.c	2008-02-08 20:04:58.000000000 +0100
+@@ -38,6 +38,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <asm/gpio.h>
++#include <asm/atomic.h>
+ 
+ MODULE_AUTHOR("Eugene Konev <[email protected]>");
+ MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
+@@ -207,6 +208,7 @@
+ 	struct work_struct reset_work;
+ 	struct platform_device *pdev;
+ 	struct napi_struct napi;
++	atomic_t reset_pending;
+ };
+ 
+ static irqreturn_t cpmac_irq(int, void *);
+@@ -455,6 +457,9 @@
+ 	struct cpmac_desc *desc;
+ 	struct cpmac_priv *priv = netdev_priv(dev);
+ 
++	if (unlikely(atomic_read(&priv->reset_pending)))
++		return NETDEV_TX_BUSY;
++
+ 	if (unlikely(skb_padto(skb, ETH_ZLEN)))
+ 		return NETDEV_TX_OK;
+ 
+@@ -634,14 +639,14 @@
+ 		priv->desc_ring[i].dataflags = 0;
+ 		if (priv->desc_ring[i].skb) {
+ 			dev_kfree_skb_any(priv->desc_ring[i].skb);
+-			if (netif_subqueue_stopped(dev, i))
+-			    netif_wake_subqueue(dev, i);
++			priv->desc_ring[i].skb = NULL;
+ 		}
+ 	}
+ }
+ 
+ static void cpmac_hw_error(struct work_struct *work)
+ {
++	int i;
+ 	struct cpmac_priv *priv =
+ 		container_of(work, struct cpmac_priv, reset_work);
+ 
+@@ -650,8 +655,46 @@
+ 	spin_unlock(&priv->rx_lock);
+ 	cpmac_clear_tx(priv->dev);
+ 	cpmac_hw_start(priv->dev);
++	barrier();
++	atomic_dec(&priv->reset_pending);
++	
++	for (i = 0; i < CPMAC_QUEUES; i++) {
++		netif_wake_subqueue(priv->dev, i);
++	}
++	netif_wake_queue(priv->dev);
++}
++
++static void cpmac_check_status(struct net_device *dev)
++{
++	struct cpmac_priv *priv = netdev_priv(dev);
++
++	u32 macstatus = cpmac_read(priv->regs, CPMAC_MAC_STATUS);
++	int rx_channel = (macstatus >> 8) & 7;
++	int rx_code = (macstatus >> 12) & 15;
++	int tx_channel = (macstatus >> 16) & 7;
++	int tx_code = (macstatus >> 20) & 15;
++
++	if (rx_code || tx_code) {
++		if (netif_msg_drv(priv) && net_ratelimit()) {
++			/* Can't find any documentation on what these error codes actually are.
++			 * So just log them and hope..
++			 */
++			if (rx_code)
++				printk(KERN_WARNING "%s: host error %d on rx channel %d (macstatus %08x), resetting\n",
++				       dev->name, rx_code, rx_channel, macstatus);
++			if (tx_code)
++				printk(KERN_WARNING "%s: host error %d on tx channel %d (macstatus %08x), resetting\n",
++				       dev->name, tx_code, tx_channel, macstatus);
++		}
++		
++		netif_stop_queue(dev);
++		cpmac_hw_stop(dev);
++		if (schedule_work(&priv->reset_work))
++			atomic_inc(&priv->reset_pending);			
++		if (unlikely(netif_msg_hw(priv)))
++			cpmac_dump_regs(dev);
++	}
+ 	napi_enable(&priv->napi);
+-	netif_start_queue(priv->dev);
+ }
+ 
+ static irqreturn_t cpmac_irq(int irq, void *dev_id)
+@@ -661,9 +704,6 @@
  	int queue;
  	u32 status;
  
@@ -21,7 +101,71 @@
  	priv = netdev_priv(dev);
  
  	status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR);
-@@ -848,15 +845,6 @@
+@@ -685,49 +725,33 @@
+ 
+ 	cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0);
+ 
+-	if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) {
+-		if (netif_msg_drv(priv) && net_ratelimit())
+-			printk(KERN_ERR "%s: hw error, resetting...\n",
+-			       dev->name);
+-		netif_stop_queue(dev);
+-		napi_disable(&priv->napi);
+-		cpmac_hw_stop(dev);
+-		schedule_work(&priv->reset_work);
+-		if (unlikely(netif_msg_hw(priv)))
+-			cpmac_dump_regs(dev);
+-	}
++	if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS)))
++		cpmac_check_status(dev);
+ 
+ 	return IRQ_HANDLED;
+ }
+ 
+ static void cpmac_tx_timeout(struct net_device *dev)
+ {
+-	struct cpmac_priv *priv = netdev_priv(dev);
+ 	int i;
++	struct cpmac_priv *priv = netdev_priv(dev);
+ 
+ 	spin_lock(&priv->lock);
+ 	dev->stats.tx_errors++;
+ 	spin_unlock(&priv->lock);
+ 	if (netif_msg_tx_err(priv) && net_ratelimit())
+ 		printk(KERN_WARNING "%s: transmit timeout\n", dev->name);
+-	/* 
+-	 * FIXME: waking up random queue is not the best thing to
+-	 * do... on the other hand why we got here at all?
+-	 */
+-#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+-	for (i = 0; i < CPMAC_QUEUES; i++)
+-		if (priv->desc_ring[i].skb) {
+-			priv->desc_ring[i].dataflags = 0;
+-			dev_kfree_skb_any(priv->desc_ring[i].skb);
+-			netif_wake_subqueue(dev, i);
+-			break;
+-		}
+-#else
+-	priv->desc_ring[0].dataflags = 0;
+-	if (priv->desc_ring[0].skb)
+-		dev_kfree_skb_any(priv->desc_ring[0].skb);
+-	netif_wake_queue(dev);
+-#endif
++
++	atomic_inc(&priv->reset_pending);
++	barrier();
++	cpmac_clear_tx(dev);
++	barrier();
++	atomic_dec(&priv->reset_pending);
++
++	netif_wake_queue(priv->dev);
++	for (i = 0; i < CPMAC_QUEUES; i++) {
++		netif_wake_subqueue(dev, i);
++	}
+ }
+ 
+ static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+@@ -848,15 +872,6 @@
  	spin_unlock(&priv->lock);
  }
  
@@ -37,7 +181,15 @@
  static int cpmac_open(struct net_device *dev)
  {
  	int i, size, res;
-@@ -999,11 +987,11 @@
+@@ -923,6 +938,7 @@
+ 		goto fail_irq;
+ 	}
+ 
++	atomic_set(&priv->reset_pending, 0);
+ 	INIT_WORK(&priv->reset_work, cpmac_hw_error);
+ 	cpmac_hw_start(dev);
+ 
+@@ -999,11 +1015,11 @@
  static int __devinit cpmac_probe(struct platform_device *pdev)
  {
  	int rc, phy_id, i;
@@ -50,7 +202,7 @@
  	DECLARE_MAC_BUF(mac);
  
  	pdata = pdev->dev.platform_data;
-@@ -1017,9 +1005,23 @@
+@@ -1017,9 +1033,23 @@
  	}
  
  	if (phy_id == PHY_MAX_ADDR) {
@@ -76,7 +228,7 @@
  			printk(KERN_ERR "cpmac: no PHY present\n");
  			return -ENODEV;
  		}
-@@ -1063,32 +1065,8 @@
+@@ -1063,32 +1093,8 @@
  	priv->msg_enable = netif_msg_init(debug_level, 0xff);
  	memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));