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

Jon Mason
2005-01-04T21:38:19Z

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

Hello Richard,
Sorry for the long delay in responding. I have found an error in the
patch I sent you, and I think I missed something. The error was a
function defined twice. The erro was lack of cleanup of the tx and rx
queues are the adapter reset. The patch below (and attached) should
fix both of these errors. Please apply it to the original driver.

Thanks,
Jon

--- dl2k.c,orig-save-2004.12.20 2004-12-21 09:43:19.000000000 -0600
+++ dl2k.c 2005-01-04 15:26:57.162033944 -0600
@@ -429,23 +429,16 @@ 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 = dev->priv;
+ 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);
-
+ alloc_list (dev);
+
/* DebugCtrl bit 4, 5, 9 must set */
writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);

@@ -453,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);
@@ -488,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);
@@ -505,10 +490,36 @@ 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);
+
+ 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;
}

@@ -562,9 +573,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;
@@ -1005,10 +1018,36 @@ 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);
+
+ /* Free all the skbuffs in the queue. */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ np->rx_ring[i].status = 0;
+ np->rx_ring[i].fraginfo = 0;
+ skb = np->rx_skbuff[i];
+ if (skb) {
+ pci_unmap_single (np->pdev,
np->rx_ring[i].fraginfo,
+ skb->len, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb (skb);
+ np->rx_skbuff[i] = NULL;
+ }
+ }
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ skb = np->tx_skbuff[i];
+ if (skb) {
+ pci_unmap_single (np->pdev,
np->tx_ring[i].fraginfo,
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb (skb);
+ np->tx_skbuff[i] = NULL;
+ }
+ }
+
mdelay (500);
+
+ rio_up(dev);
}
}

[-- Attachment #2: dl2k.patch3 --]
[-- Type: application/octet-stream, Size: 4015 bytes --]

--- dl2k.c,orig-save-2004.12.20 2004-12-21 09:43:19.000000000 -0600
+++ dl2k.c 2005-01-04 15:26:57.162033944 -0600
@@ -429,23 +429,16 @@ 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 = dev->priv;
+ 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);
-
+ alloc_list (dev);
+
/* DebugCtrl bit 4, 5, 9 must set */
writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);

@@ -453,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);
@@ -488,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);
@@ -505,10 +490,36 @@ 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);
+
+ 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;
}

@@ -562,9 +573,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;
@@ -1005,10 +1018,36 @@ 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);
+
+ /* Free all the skbuffs in the queue. */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ np->rx_ring[i].status = 0;
+ np->rx_ring[i].fraginfo = 0;
+ skb = np->rx_skbuff[i];
+ if (skb) {
+ pci_unmap_single (np->pdev, np->rx_ring[i].fraginfo,
+ skb->len, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb (skb);
+ np->rx_skbuff[i] = NULL;
+ }
+ }
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ skb = np->tx_skbuff[i];
+ if (skb) {
+ pci_unmap_single (np->pdev, np->tx_ring[i].fraginfo,
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb (skb);
+ np->tx_skbuff[i] = NULL;
+ }
+ }
+
mdelay (500);
+
+ rio_up(dev);
}
}