ag71xx driver: handle TX timout
authorGabor Juhos <juhosg@openwrt.org>
Sun, 7 Dec 2008 06:43:02 +0000 (06:43 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Sun, 7 Dec 2008 06:43:02 +0000 (06:43 +0000)
SVN-Revision: 13537

target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h
target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c

index 7e3da8178e124456e297daf0edc5e87249cce245..d5f7743d4ca0508e633279a02e16841ae3481772 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/phy.h>
 #include <linux/skbuff.h>
 #include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
 
 #include <linux/bitops.h>
 
@@ -37,7 +38,7 @@
 #define ETH_FCS_LEN    4
 
 #define AG71XX_DRV_NAME                "ag71xx"
-#define AG71XX_DRV_VERSION     "0.5.10"
+#define AG71XX_DRV_VERSION     "0.5.11"
 
 #define AG71XX_NAPI_WEIGHT     64
 
@@ -124,6 +125,8 @@ struct ag71xx {
        unsigned int            link;
        unsigned int            speed;
        int                     duplex;
+
+       struct work_struct      restart_work;
 };
 
 extern struct ethtool_ops ag71xx_ethtool_ops;
index 87f83d0cd123d03d61f38cd857e531bff2cf6097..78189693553a20350872125018a8118452e207d7 100644 (file)
@@ -551,6 +551,24 @@ static int ag71xx_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        return -EOPNOTSUPP;
 }
 
+static void ag71xx_tx_timeout(struct net_device *dev)
+{
+       struct ag71xx *ag = netdev_priv(dev);
+
+       if (netif_msg_tx_err(ag))
+               printk(KERN_DEBUG "%s: tx timeout\n", ag->dev->name);
+
+       schedule_work(&ag->restart_work);
+}
+
+static void ag71xx_restart_work_func(struct work_struct *work)
+{
+       struct ag71xx *ag = container_of(work, struct ag71xx, restart_work);
+
+       ag71xx_stop(ag->dev);
+       ag71xx_open(ag->dev);
+}
+
 static void ag71xx_tx_packets(struct ag71xx *ag)
 {
        struct ag71xx_ring *ring = &ag->tx_ring;
@@ -824,6 +842,9 @@ static int __init ag71xx_probe(struct platform_device *pdev)
        dev->do_ioctl = ag71xx_do_ioctl;
        dev->ethtool_ops = &ag71xx_ethtool_ops;
 
+       dev->tx_timeout = ag71xx_tx_timeout;
+       INIT_WORK(&ag->restart_work, ag71xx_restart_work_func);
+
        netif_napi_add(dev, &ag->napi, ag71xx_poll, AG71XX_NAPI_WEIGHT);
 
        if (is_valid_ether_addr(pdata->mac_addr))