]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'for-jeff' of git://electric-eye.fr.zoreil.com/home/romieu/linux-2.6
authorJeff Garzik <jgarzik@pobox.com>
Tue, 7 Feb 2006 07:05:17 +0000 (02:05 -0500)
committerJeff Garzik <jgarzik@pobox.com>
Tue, 7 Feb 2006 07:05:17 +0000 (02:05 -0500)
drivers/net/8139too.c
drivers/net/r8169.c

index adfba44dac5a009a484894fc3d36c71ae9dd6502..2beac55b57d605ec57213c52f418ae3a0ca2cc55 100644 (file)
@@ -586,6 +586,7 @@ struct rtl8139_private {
        dma_addr_t tx_bufs_dma;
        signed char phys[4];            /* MII device addresses. */
        char twistie, twist_row, twist_col;     /* Twister tune state. */
+       unsigned int watchdog_fired : 1;
        unsigned int default_port : 4;  /* Last dev->if_port value. */
        unsigned int have_thread : 1;
        spinlock_t lock;
@@ -638,6 +639,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev);
 static void __set_rx_mode (struct net_device *dev);
 static void rtl8139_hw_start (struct net_device *dev);
 static void rtl8139_thread (void *_data);
+static void rtl8139_tx_timeout_task(void *_data);
 static struct ethtool_ops rtl8139_ethtool_ops;
 
 /* write MMIO register, with flush */
@@ -1598,13 +1600,14 @@ static void rtl8139_thread (void *_data)
 {
        struct net_device *dev = _data;
        struct rtl8139_private *tp = netdev_priv(dev);
-       unsigned long thr_delay;
+       unsigned long thr_delay = next_tick;
 
-       if (rtnl_shlock_nowait() == 0) {
+       if (tp->watchdog_fired) {
+               tp->watchdog_fired = 0;
+               rtl8139_tx_timeout_task(_data);
+       } else if (rtnl_shlock_nowait() == 0) {
                rtl8139_thread_iter (dev, tp, tp->mmio_addr);
                rtnl_unlock ();
-
-               thr_delay = next_tick;
        } else {
                /* unlikely race.  mitigate with fast poll. */
                thr_delay = HZ / 2;
@@ -1631,7 +1634,8 @@ static void rtl8139_stop_thread(struct rtl8139_private *tp)
        if (tp->have_thread) {
                cancel_rearming_delayed_work(&tp->thread);
                tp->have_thread = 0;
-       }
+       } else
+               flush_scheduled_work();
 }
 
 static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
@@ -1642,14 +1646,13 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
        /* XXX account for unsent Tx packets in tp->stats.tx_dropped */
 }
 
-
-static void rtl8139_tx_timeout (struct net_device *dev)
+static void rtl8139_tx_timeout_task (void *_data)
 {
+       struct net_device *dev = _data;
        struct rtl8139_private *tp = netdev_priv(dev);
        void __iomem *ioaddr = tp->mmio_addr;
        int i;
        u8 tmp8;
-       unsigned long flags;
 
        printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x "
                "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd),
@@ -1670,23 +1673,34 @@ static void rtl8139_tx_timeout (struct net_device *dev)
        if (tmp8 & CmdTxEnb)
                RTL_W8 (ChipCmd, CmdRxEnb);
 
-       spin_lock(&tp->rx_lock);
+       spin_lock_bh(&tp->rx_lock);
        /* Disable interrupts by clearing the interrupt mask. */
        RTL_W16 (IntrMask, 0x0000);
 
        /* Stop a shared interrupt from scavenging while we are. */
-       spin_lock_irqsave (&tp->lock, flags);
+       spin_lock_irq(&tp->lock);
        rtl8139_tx_clear (tp);
-       spin_unlock_irqrestore (&tp->lock, flags);
+       spin_unlock_irq(&tp->lock);
 
        /* ...and finally, reset everything */
        if (netif_running(dev)) {
                rtl8139_hw_start (dev);
                netif_wake_queue (dev);
        }
-       spin_unlock(&tp->rx_lock);
+       spin_unlock_bh(&tp->rx_lock);
 }
 
+static void rtl8139_tx_timeout (struct net_device *dev)
+{
+       struct rtl8139_private *tp = netdev_priv(dev);
+
+       if (!tp->have_thread) {
+               INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev);
+               schedule_delayed_work(&tp->thread, next_tick);
+       } else
+               tp->watchdog_fired = 1;
+
+}
 
 static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
index 2e1bed153c39c00827e2ef986bca3db3129c807d..6e1018448eea9b00a21215d3b284933ffab836a1 100644 (file)
@@ -484,13 +484,12 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
        int i;
 
        RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
-       udelay(1000);
 
-       for (i = 2000; i > 0; i--) {
+       for (i = 20; i > 0; i--) {
                /* Check if the RTL8169 has completed writing to the specified MII register */
                if (!(RTL_R32(PHYAR) & 0x80000000)) 
                        break;
-               udelay(100);
+               udelay(25);
        }
 }
 
@@ -499,15 +498,14 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr)
        int i, value = -1;
 
        RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
-       udelay(1000);
 
-       for (i = 2000; i > 0; i--) {
+       for (i = 20; i > 0; i--) {
                /* Check if the RTL8169 has completed retrieving data from the specified MII register */
                if (RTL_R32(PHYAR) & 0x80000000) {
                        value = (int) (RTL_R32(PHYAR) & 0xFFFF);
                        break;
                }
-               udelay(100);
+               udelay(25);
        }
        return value;
 }
@@ -677,6 +675,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
 
                if (duplex == DUPLEX_HALF)
                        auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);
+
+               if (duplex == DUPLEX_FULL)
+                       auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half);
        }
 
        tp->phy_auto_nego_reg = auto_nego;