static void tx_error (struct net_device *dev, int tx_status) { struct netdev_private *np = netdev_priv(dev); void __iomem *ioaddr = np->ioaddr; int frame_id; int i; frame_id = (tx_status & 0xffff0000); printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n", dev->name, tx_status, frame_id); np->stats.tx_errors++; /* Ttransmit Underrun */ if (tx_status & 0x10) { np->stats.tx_fifo_errors++; dw16(TxStartThresh, dr16(TxStartThresh) + 0x10); /* Transmit Underrun need to set TxReset, DMARest, FIFOReset */ dw16(ASICCtrl + 2, TxReset | DMAReset | FIFOReset | NetworkReset); /* Wait for ResetBusy bit clear */ for (i = 50; i > 0; i--) { if (!(dr16(ASICCtrl + 2) & ResetBusy)) break; mdelay (1); } rio_set_led_mode(dev); rio_free_tx (dev, 1); /* Reset TFDListPtr */ dw32(TFDListPtr0, np->tx_ring_dma + np->old_tx * sizeof (struct netdev_desc)); dw32(TFDListPtr1, 0); /* Let TxStartThresh stay default value */ } /* Late Collision */ if (tx_status & 0x04) { np->stats.tx_fifo_errors++; /* TxReset and clear FIFO */ dw16(ASICCtrl + 2, TxReset | FIFOReset); /* Wait reset done */ for (i = 50; i > 0; i--) { if (!(dr16(ASICCtrl + 2) & ResetBusy)) break; mdelay (1); } rio_set_led_mode(dev); /* Let TxStartThresh stay default value */ } /* Maximum Collisions */ #ifdef ETHER_STATS if (tx_status & 0x08) np->stats.collisions16++; #else if (tx_status & 0x08) np->stats.collisions++; #endif /* Restart the Tx */ dw32(MACCtrl, dr16(MACCtrl) | TxEnable); }
static void rio_tx_timeout (struct net_device *dev) { long ioaddr = dev->base_addr; printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n", dev->name, readl (ioaddr + TxStatus)); rio_free_tx(dev, 0); dev->if_port = 0; dev->trans_start = jiffies; /* prevent tx timeout */ }
static void rio_tx_timeout (struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); void __iomem *ioaddr = np->ioaddr; printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n", dev->name, dr32(TxStatus)); rio_free_tx(dev, 0); dev->if_port = 0; dev->trans_start = jiffies; /* prevent tx timeout */ }
static irqreturn_t rio_interrupt (int irq, void *dev_instance) { struct net_device *dev = dev_instance; struct netdev_private *np; unsigned int_status; long ioaddr; int cnt = max_intrloop; int handled = 0; ioaddr = dev->base_addr; np = netdev_priv(dev); while (1) { int_status = readw (ioaddr + IntStatus); writew (int_status, ioaddr + IntStatus); int_status &= DEFAULT_INTR; if (int_status == 0 || --cnt < 0) break; handled = 1; /* Processing received packets */ if (int_status & RxDMAComplete) receive_packet (dev); /* TxDMAComplete interrupt */ if ((int_status & (TxDMAComplete|IntRequested))) { int tx_status; tx_status = readl (ioaddr + TxStatus); if (tx_status & 0x01) tx_error (dev, tx_status); /* Free used tx skbuffs */ rio_free_tx (dev, 1); } /* Handle uncommon events */ if (int_status & (HostError | LinkEvent | UpdateStats)) rio_error (dev, int_status); } if (np->cur_tx != np->old_tx) writel (100, ioaddr + CountDown); return IRQ_RETVAL(handled); }
static void tx_error (struct net_device *dev, int tx_status) { struct netdev_private *np; long ioaddr = dev->base_addr; int frame_id; int i; np = netdev_priv(dev); frame_id = (tx_status & 0xffff0000); printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n", dev->name, tx_status, frame_id); np->stats.tx_errors++; /* Ttransmit Underrun */ if (tx_status & 0x10) { np->stats.tx_fifo_errors++; writew (readw (ioaddr + TxStartThresh) + 0x10, ioaddr + TxStartThresh); /* Transmit Underrun need to set TxReset, DMARest, FIFOReset */ writew (TxReset | DMAReset | FIFOReset | NetworkReset, ioaddr + ASICCtrl + 2); /* Wait for ResetBusy bit clear */ for (i = 50; i > 0; i--) { if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0) break; mdelay (1); } rio_free_tx (dev, 1); /* Reset TFDListPtr */ writel (np->tx_ring_dma + np->old_tx * sizeof (struct netdev_desc), dev->base_addr + TFDListPtr0); writel (0, dev->base_addr + TFDListPtr1); /* Let TxStartThresh stay default value */ } /* Late Collision */ if (tx_status & 0x04) { np->stats.tx_fifo_errors++; /* TxReset and clear FIFO */ writew (TxReset | FIFOReset, ioaddr + ASICCtrl + 2); /* Wait reset done */ for (i = 50; i > 0; i--) { if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0) break; mdelay (1); } /* Let TxStartThresh stay default value */ } /* Maximum Collisions */ #ifdef ETHER_STATS if (tx_status & 0x08) np->stats.collisions16++; #else if (tx_status & 0x08) np->stats.collisions++; #endif /* Restart the Tx */ writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl); }