Re: PROBLEM: Network hang: "eth0: Tx timed out (f0080), is buffer full?" (Plain)

Jon Mason
2004-12-20T20:32:23Z

[-- Attachment #1: Type: text/plain, Size: 4698 bytes --]

Dec 20 18:49:08 urutu kernel: eth1: HostError! IntStatus 0002. 202 143 8 7c2
Dec 20 18:54:15 urutu kernel: eth1: Tx timed out (d50080) 214 143 800 0
Dec 20 18:59:31 urutu kernel: eth1: Tx timed out (d30080) 212 143 800 0

With the above numbers corresponding to the current tx descriptor, the
current rx descriptor, the DMACtrl register, and the IntEnable
register.

I think we have the culprit. It appears that the adapter reset in the
function that contains HostError disables interrupts (which prevents
any rx from being serviced). I have a new patch which should
<crossing fingers> fix the problem (attached for easier patching). If
it doesn't work, it will fail the same way. Please apply it to the
original driver.

Thanks,
Jon

--- dl2k.c.orig 2004-12-20 13:59:47.123631016 -0600
+++ dl2k.c 2004-12-20 14:22:31.820165608 -0600
@@ -431,23 +431,14 @@ parse_eeprom (struct net_device *dev)
return 0;
}

-static int
-rio_open (struct net_device *dev)
+static void
+rio_up (struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
long ioaddr = dev->base_addr;
int i;
u16 macctrl;

- i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev);
- if (i)
- return i;
-
- /* Reset all logic functions */
- writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
- ioaddr + ASICCtrl + 2);
- mdelay(10);
-
/* DebugCtrl bit 4, 5, 9 must set */
writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);

@@ -455,8 +446,6 @@ rio_open (struct net_device *dev)
if (np->jumbo != 0)
writew (MAX_JUMBO+14, ioaddr + MaxFrameSize);

- alloc_list (dev);
-
/* Get station address */
for (i = 0; i < 6; i++)
writeb (dev->dev_addr[i], ioaddr + StationAddr0 + i);
@@ -490,12 +479,6 @@ rio_open (struct net_device *dev)
ioaddr + MACCtrl);
}

- init_timer (&np->timer);
- np->timer.expires = jiffies + 1*HZ;
- np->timer.data = (unsigned long) dev;
- np->timer.function = &rio_timer;
- add_timer (&np->timer);
-
/* Start Tx/Rx */
writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable,
ioaddr + MACCtrl);
@@ -507,10 +490,38 @@ rio_open (struct net_device *dev)
macctrl |= (np->rx_flow) ? RxFlowControlEnable : 0;
writew(macctrl, ioaddr + MACCtrl);

- netif_start_queue (dev);
-
/* Enable default interrupts */
EnableInt ();
+}
+
+static int
+rio_open (struct net_device *dev)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ long ioaddr = dev->base_addr;
+ int i;
+
+ i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev);
+ if (i)
+ return i;
+
+ /* Reset all logic functions */
+ writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
+ ioaddr + ASICCtrl + 2);
+ mdelay(10);
+
+ alloc_list (dev);
+
+ rio_up (dev);
+
+ init_timer (&np->timer);
+ np->timer.expires = jiffies + 1*HZ;
+ np->timer.data = (unsigned long) dev;
+ np->timer.function = &rio_timer;
+ add_timer (&np->timer);
+
+ netif_start_queue (dev);
+
return 0;
}

@@ -564,9 +575,11 @@ static void
rio_tx_timeout (struct net_device *dev)
{
long ioaddr = dev->base_addr;
+ struct netdev_private *np = dev->priv;

- printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n",
- dev->name, readl (ioaddr + TxStatus));
+ printk (KERN_INFO "%s: Tx timed out (%4.4x) %d %d %x %x\n",
+ dev->name, readl (ioaddr + TxStatus), np->cur_tx, np->cur_rx,
+ readl (ioaddr + MACCtrl), readw(ioaddr + IntEnable));
rio_free_tx(dev, 0);
dev->if_port = 0;
dev->trans_start = jiffies;
@@ -1007,10 +1020,13 @@ rio_error (struct net_device *dev, int i
/* PCI Error, a catastronphic error related to the bus interface
occurs, set GlobalReset and HostReset to reset. */
if (int_status & HostError) {
- printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n",
- dev->name, int_status);
+ printk (KERN_ERR "%s: HostError! IntStatus %4.4x. %d
%d %x %x\n",
+ dev->name, int_status, np->cur_tx, np->cur_rx,
+ readl (ioaddr + MACCtrl), readw(ioaddr + IntEnable));
writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2);
mdelay (500);
+
+ rio_up(dev);
}
}

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dl2k.patch --]
[-- Type: text/x-patch; name="dl2k.patch", Size: 3471 bytes --]

--- dl2k.c.orig 2004-12-20 13:59:47.123631016 -0600
+++ dl2k.c 2004-12-20 14:22:31.820165608 -0600
@@ -431,23 +431,14 @@ parse_eeprom (struct net_device *dev)
return 0;
}

-static int
-rio_open (struct net_device *dev)
+static void
+rio_up (struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
long ioaddr = dev->base_addr;
int i;
u16 macctrl;

- i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev);
- if (i)
- return i;
-
- /* Reset all logic functions */
- writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
- ioaddr + ASICCtrl + 2);
- mdelay(10);
-
/* DebugCtrl bit 4, 5, 9 must set */
writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);

@@ -455,8 +446,6 @@ rio_open (struct net_device *dev)
if (np->jumbo != 0)
writew (MAX_JUMBO+14, ioaddr + MaxFrameSize);

- alloc_list (dev);
-
/* Get station address */
for (i = 0; i < 6; i++)
writeb (dev->dev_addr[i], ioaddr + StationAddr0 + i);
@@ -490,12 +479,6 @@ rio_open (struct net_device *dev)
ioaddr + MACCtrl);
}

- init_timer (&np->timer);
- np->timer.expires = jiffies + 1*HZ;
- np->timer.data = (unsigned long) dev;
- np->timer.function = &rio_timer;
- add_timer (&np->timer);
-
/* Start Tx/Rx */
writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable,
ioaddr + MACCtrl);
@@ -507,10 +490,38 @@ rio_open (struct net_device *dev)
macctrl |= (np->rx_flow) ? RxFlowControlEnable : 0;
writew(macctrl, ioaddr + MACCtrl);

- netif_start_queue (dev);
-
/* Enable default interrupts */
EnableInt ();
+}
+
+static int
+rio_open (struct net_device *dev)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ long ioaddr = dev->base_addr;
+ int i;
+
+ i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev);
+ if (i)
+ return i;
+
+ /* Reset all logic functions */
+ writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
+ ioaddr + ASICCtrl + 2);
+ mdelay(10);
+
+ alloc_list (dev);
+
+ rio_up (dev);
+
+ init_timer (&np->timer);
+ np->timer.expires = jiffies + 1*HZ;
+ np->timer.data = (unsigned long) dev;
+ np->timer.function = &rio_timer;
+ add_timer (&np->timer);
+
+ netif_start_queue (dev);
+
return 0;
}

@@ -564,9 +575,11 @@ static void
rio_tx_timeout (struct net_device *dev)
{
long ioaddr = dev->base_addr;
+ struct netdev_private *np = dev->priv;

- printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n",
- dev->name, readl (ioaddr + TxStatus));
+ printk (KERN_INFO "%s: Tx timed out (%4.4x) %d %d %x %x\n",
+ dev->name, readl (ioaddr + TxStatus), np->cur_tx, np->cur_rx,
+ readl (ioaddr + MACCtrl), readw(ioaddr + IntEnable));
rio_free_tx(dev, 0);
dev->if_port = 0;
dev->trans_start = jiffies;
@@ -1007,10 +1020,13 @@ rio_error (struct net_device *dev, int i
/* PCI Error, a catastronphic error related to the bus interface
occurs, set GlobalReset and HostReset to reset. */
if (int_status & HostError) {
- printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n",
- dev->name, int_status);
+ printk (KERN_ERR "%s: HostError! IntStatus %4.4x. %d %d %x %x\n",
+ dev->name, int_status, np->cur_tx, np->cur_rx,
+ readl (ioaddr + MACCtrl), readw(ioaddr + IntEnable));
writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2);
mdelay (500);
+
+ rio_up(dev);
}
}