static void el3_tx_timeout(struct net_device *dev) { unsigned int ioaddr = dev->base_addr; netdev_warn(dev, "Transmit timed out!\n"); dump_status(dev); dev->stats.tx_errors++; dev->trans_start = jiffies; /* prevent tx timeout */ /* Issue TX_RESET and TX_START commands. */ tc589_wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); netif_wake_queue(dev); }
static void el3_tx_timeout(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); kio_addr_t ioaddr = dev->base_addr; printk(KERN_WARNING "%s: Transmit timed out!\n", dev->name); dump_status(dev); lp->stats.tx_errors++; dev->trans_start = jiffies; /* Issue TX_RESET and TX_START commands. */ tc589_wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); netif_wake_queue(dev); }
static void pop_tx_status(struct net_device *dev) { unsigned int ioaddr = dev->base_addr; int i; /* Clear the Tx status stack. */ for (i = 32; i > 0; i--) { u_char tx_status = inb(ioaddr + TX_STATUS); if (!(tx_status & 0x84)) break; /* reset transmitter on jabber error or underrun */ if (tx_status & 0x30) tc589_wait_for_completion(dev, TxReset); if (tx_status & 0x38) { netdev_dbg(dev, "transmit error: status 0x%02x\n", tx_status); outw(TxEnable, ioaddr + EL3_CMD); dev->stats.tx_aborted_errors++; } outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */ } }
static void pop_tx_status(struct net_device *dev) { struct el3_private *lp = (struct el3_private *)dev->priv; ioaddr_t ioaddr = dev->base_addr; int i; /* Clear the Tx status stack. */ for (i = 32; i > 0; i--) { u_char tx_status = inb(ioaddr + TX_STATUS); if (!(tx_status & 0x84)) break; /* reset transmitter on jabber error or underrun */ if (tx_status & 0x30) tc589_wait_for_completion(dev, TxReset); if (tx_status & 0x38) { DEBUG(1, "%s: transmit error: status 0x%02x\n", dev->name, tx_status); outw(TxEnable, ioaddr + EL3_CMD); lp->stats.tx_aborted_errors++; } outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */ } }
/* The EL3 interrupt handler. */ static irqreturn_t el3_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; struct el3_private *lp = netdev_priv(dev); unsigned int ioaddr; __u16 status; int i = 0, handled = 1; if (!netif_device_present(dev)) return IRQ_NONE; ioaddr = dev->base_addr; netdev_dbg(dev, "interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS)); spin_lock(&lp->lock); while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete | StatsFull)) { if ((status & 0xe000) != 0x2000) { netdev_dbg(dev, "interrupt from dead card\n"); handled = 0; break; } if (status & RxComplete) el3_rx(dev); if (status & TxAvailable) { netdev_dbg(dev, " TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); netif_wake_queue(dev); } if (status & TxComplete) pop_tx_status(dev); if (status & (AdapterFailure | RxEarly | StatsFull)) { /* Handle all uncommon interrupts. */ if (status & StatsFull) /* Empty statistics. */ update_stats(dev); if (status & RxEarly) { /* Rx early is unused. */ el3_rx(dev); outw(AckIntr | RxEarly, ioaddr + EL3_CMD); } if (status & AdapterFailure) { u16 fifo_diag; EL3WINDOW(4); fifo_diag = inw(ioaddr + 4); EL3WINDOW(1); netdev_warn(dev, "adapter failure, FIFO diagnostic register %04x.\n", fifo_diag); if (fifo_diag & 0x0400) { /* Tx overrun */ tc589_wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); } if (fifo_diag & 0x2000) { /* Rx underrun */ tc589_wait_for_completion(dev, RxReset); set_rx_mode(dev); outw(RxEnable, ioaddr + EL3_CMD); } outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); } } if (++i > 10) { netdev_err(dev, "infinite loop in interrupt, status %4.4x.\n", status); /* Clear all interrupts */ outw(AckIntr | 0xFF, ioaddr + EL3_CMD); break; } /* Acknowledge the IRQ. */ outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); } lp->last_irq = jiffies; spin_unlock(&lp->lock); netdev_dbg(dev, "exiting interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS)); return IRQ_RETVAL(handled); }
/* The EL3 interrupt handler. */ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct el3_private *lp = dev_id; struct net_device *dev = &lp->dev; ioaddr_t ioaddr, status; int i = 0; if (!netif_device_present(dev)) return; ioaddr = dev->base_addr; DEBUG(3, "%s: interrupt, status %4.4x.\n", dev->name, inw(ioaddr + EL3_STATUS)); while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete | StatsFull)) { if (!netif_device_present(dev) || ((status & 0xe000) != 0x2000)) { DEBUG(1, "%s: interrupt from dead card\n", dev->name); break; } if (status & RxComplete) el3_rx(dev); if (status & TxAvailable) { DEBUG(3, " TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); netif_wake_queue(dev); } if (status & TxComplete) pop_tx_status(dev); if (status & (AdapterFailure | RxEarly | StatsFull)) { /* Handle all uncommon interrupts. */ if (status & StatsFull) /* Empty statistics. */ update_stats(dev); if (status & RxEarly) { /* Rx early is unused. */ el3_rx(dev); outw(AckIntr | RxEarly, ioaddr + EL3_CMD); } if (status & AdapterFailure) { u16 fifo_diag; EL3WINDOW(4); fifo_diag = inw(ioaddr + 4); EL3WINDOW(1); printk(KERN_NOTICE "%s: adapter failure, FIFO diagnostic" " register %04x.\n", dev->name, fifo_diag); if (fifo_diag & 0x0400) { /* Tx overrun */ tc589_wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); } if (fifo_diag & 0x2000) { /* Rx underrun */ tc589_wait_for_completion(dev, RxReset); set_multicast_list(dev); outw(RxEnable, ioaddr + EL3_CMD); } outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); } } if (++i > 10) { printk(KERN_NOTICE "%s: infinite loop in interrupt, " "status %4.4x.\n", dev->name, status); /* Clear all interrupts */ outw(AckIntr | 0xFF, ioaddr + EL3_CMD); break; } /* Acknowledge the IRQ. */ outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); } lp->last_irq = jiffies; DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", dev->name, inw(ioaddr + EL3_STATUS)); return; }