diff options
-rw-r--r-- | target/linux/ar7/patches-2.6.24/140-cpmac_fix.patch | 186 |
1 files changed, 169 insertions, 17 deletions
diff --git a/target/linux/ar7/patches-2.6.24/140-cpmac_fix.patch b/target/linux/ar7/patches-2.6.24/140-cpmac_fix.patch index 7c51517b1e..49c6b3234b 100644 --- a/target/linux/ar7/patches-2.6.24/140-cpmac_fix.patch +++ b/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 <ejka@imfi.kspu.ru>"); + 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)); |