X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/7ec87f23ff1626dd235c62f6a1c87c14f14b775b..741b8902a746ca42d99f39bb688924e1f93e6790:/target/linux/ar7/patches-2.6.24/140-cpmac_fix.patch 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 4957d85a6..020197a1b 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,20 +1,99 @@ ---- linux-2.6.24/drivers/net/Kconfig 2008-02-07 02:29:04.000000000 +0100 -+++ linux-2.6.24/drivers/net/Kconfig 2008-02-07 02:29:35.000000000 +0100 -@@ -1830,10 +1830,8 @@ - - config CPMAC - tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)" -- depends on NET_ETHERNET && EXPERIMENTAL && AR7 -+ depends on NET_ETHERNET && EXPERIMENTAL && AR7 && BROKEN - 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-24 23:58:37.000000000 +0100 -+++ linux-2.6.24/drivers/net/cpmac.c 2008-02-07 02:32:57.000000000 +0100 -@@ -661,9 +661,6 @@ +--- 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-04-06 21:30:03.000000000 +0200 +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + MODULE_AUTHOR("Eugene Konev "); + 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,47 @@ + spin_unlock(&priv->rx_lock); + cpmac_clear_tx(priv->dev); + cpmac_hw_start(priv->dev); +- napi_enable(&priv->napi); +- netif_start_queue(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); ++ cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3); ++} ++ ++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); ++ } ++ cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); + } + + static irqreturn_t cpmac_irq(int irq, void *dev_id) +@@ -661,9 +705,6 @@ int queue; u32 status; @@ -24,7 +103,71 @@ priv = netdev_priv(dev); status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR); -@@ -848,15 +845,6 @@ +@@ -685,49 +726,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 +873,6 @@ spin_unlock(&priv->lock); } @@ -40,7 +183,15 @@ static int cpmac_open(struct net_device *dev) { int i, size, res; -@@ -999,11 +987,11 @@ +@@ -923,6 +939,7 @@ + goto fail_irq; + } + ++ atomic_set(&priv->reset_pending, 0); + INIT_WORK(&priv->reset_work, cpmac_hw_error); + cpmac_hw_start(dev); + +@@ -999,11 +1016,11 @@ static int __devinit cpmac_probe(struct platform_device *pdev) { int rc, phy_id, i; @@ -53,7 +204,7 @@ DECLARE_MAC_BUF(mac); pdata = pdev->dev.platform_data; -@@ -1017,9 +1005,23 @@ +@@ -1017,9 +1034,23 @@ } if (phy_id == PHY_MAX_ADDR) { @@ -79,7 +230,7 @@ printk(KERN_ERR "cpmac: no PHY present\n"); return -ENODEV; } -@@ -1063,32 +1065,8 @@ +@@ -1063,32 +1094,8 @@ priv->msg_enable = netif_msg_init(debug_level, 0xff); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));