提交 3cfc1510 编写于 作者: J Jeff Garzik
...@@ -586,6 +586,7 @@ struct rtl8139_private { ...@@ -586,6 +586,7 @@ struct rtl8139_private {
dma_addr_t tx_bufs_dma; dma_addr_t tx_bufs_dma;
signed char phys[4]; /* MII device addresses. */ signed char phys[4]; /* MII device addresses. */
char twistie, twist_row, twist_col; /* Twister tune state. */ 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 default_port : 4; /* Last dev->if_port value. */
unsigned int have_thread : 1; unsigned int have_thread : 1;
spinlock_t lock; spinlock_t lock;
...@@ -638,6 +639,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev); ...@@ -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 __set_rx_mode (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev);
static void rtl8139_thread (void *_data); static void rtl8139_thread (void *_data);
static void rtl8139_tx_timeout_task(void *_data);
static struct ethtool_ops rtl8139_ethtool_ops; static struct ethtool_ops rtl8139_ethtool_ops;
/* write MMIO register, with flush */ /* write MMIO register, with flush */
...@@ -1598,13 +1600,14 @@ static void rtl8139_thread (void *_data) ...@@ -1598,13 +1600,14 @@ static void rtl8139_thread (void *_data)
{ {
struct net_device *dev = _data; struct net_device *dev = _data;
struct rtl8139_private *tp = netdev_priv(dev); 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); rtl8139_thread_iter (dev, tp, tp->mmio_addr);
rtnl_unlock (); rtnl_unlock ();
thr_delay = next_tick;
} else { } else {
/* unlikely race. mitigate with fast poll. */ /* unlikely race. mitigate with fast poll. */
thr_delay = HZ / 2; thr_delay = HZ / 2;
...@@ -1631,7 +1634,8 @@ static void rtl8139_stop_thread(struct rtl8139_private *tp) ...@@ -1631,7 +1634,8 @@ static void rtl8139_stop_thread(struct rtl8139_private *tp)
if (tp->have_thread) { if (tp->have_thread) {
cancel_rearming_delayed_work(&tp->thread); cancel_rearming_delayed_work(&tp->thread);
tp->have_thread = 0; tp->have_thread = 0;
} } else
flush_scheduled_work();
} }
static inline void rtl8139_tx_clear (struct rtl8139_private *tp) static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
...@@ -1642,14 +1646,13 @@ 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 */ /* XXX account for unsent Tx packets in tp->stats.tx_dropped */
} }
static void rtl8139_tx_timeout_task (void *_data)
static void rtl8139_tx_timeout (struct net_device *dev)
{ {
struct net_device *dev = _data;
struct rtl8139_private *tp = netdev_priv(dev); struct rtl8139_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
int i; int i;
u8 tmp8; u8 tmp8;
unsigned long flags;
printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x " printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x "
"media %2.2x.\n", dev->name, RTL_R8 (ChipCmd), "media %2.2x.\n", dev->name, RTL_R8 (ChipCmd),
...@@ -1670,23 +1673,34 @@ static void rtl8139_tx_timeout (struct net_device *dev) ...@@ -1670,23 +1673,34 @@ static void rtl8139_tx_timeout (struct net_device *dev)
if (tmp8 & CmdTxEnb) if (tmp8 & CmdTxEnb)
RTL_W8 (ChipCmd, CmdRxEnb); RTL_W8 (ChipCmd, CmdRxEnb);
spin_lock(&tp->rx_lock); spin_lock_bh(&tp->rx_lock);
/* Disable interrupts by clearing the interrupt mask. */ /* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0x0000); RTL_W16 (IntrMask, 0x0000);
/* Stop a shared interrupt from scavenging while we are. */ /* Stop a shared interrupt from scavenging while we are. */
spin_lock_irqsave (&tp->lock, flags); spin_lock_irq(&tp->lock);
rtl8139_tx_clear (tp); rtl8139_tx_clear (tp);
spin_unlock_irqrestore (&tp->lock, flags); spin_unlock_irq(&tp->lock);
/* ...and finally, reset everything */ /* ...and finally, reset everything */
if (netif_running(dev)) { if (netif_running(dev)) {
rtl8139_hw_start (dev); rtl8139_hw_start (dev);
netif_wake_queue (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) static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{ {
......
...@@ -484,13 +484,12 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value) ...@@ -484,13 +484,12 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
int i; int i;
RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value); 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 */ /* Check if the RTL8169 has completed writing to the specified MII register */
if (!(RTL_R32(PHYAR) & 0x80000000)) if (!(RTL_R32(PHYAR) & 0x80000000))
break; break;
udelay(100); udelay(25);
} }
} }
...@@ -499,15 +498,14 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr) ...@@ -499,15 +498,14 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr)
int i, value = -1; int i, value = -1;
RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); 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 */ /* Check if the RTL8169 has completed retrieving data from the specified MII register */
if (RTL_R32(PHYAR) & 0x80000000) { if (RTL_R32(PHYAR) & 0x80000000) {
value = (int) (RTL_R32(PHYAR) & 0xFFFF); value = (int) (RTL_R32(PHYAR) & 0xFFFF);
break; break;
} }
udelay(100); udelay(25);
} }
return value; return value;
} }
...@@ -677,6 +675,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, ...@@ -677,6 +675,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
if (duplex == DUPLEX_HALF) if (duplex == DUPLEX_HALF)
auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); 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; tp->phy_auto_nego_reg = auto_nego;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册