-@@ -1115,11 +1159,7 @@
- rhine_set_rx_mode(dev);
-
- /* Enable interrupts by setting the interrupt mask. */
-- iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
-- IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
-- IntrTxDone | IntrTxError | IntrTxUnderrun |
-- IntrPCIErr | IntrStatsMax | IntrLinkChange,
-- ioaddr + IntrEnable);
-+ rhine_intr_enable(dev);
-
- iowrite16(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8),
- ioaddr + ChipCmd);
-@@ -1230,6 +1270,7 @@
- mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
-
- netif_start_queue(dev);
-+ netif_poll_enable(dev);
-
- return 0;
- }
-@@ -1268,8 +1309,8 @@
- /* Reinitialize the hardware. */
- rhine_chip_reset(dev);
- init_registers(dev);
--
- spin_unlock(&rp->lock);
-+
- enable_irq(rp->pdev->irq);
-
- dev->trans_start = jiffies;
-@@ -1363,69 +1404,56 @@
- struct net_device *dev = dev_instance;
- struct rhine_private *rp = netdev_priv(dev);
- void __iomem *ioaddr = rp->base;
-- u32 intr_status;
-- int boguscnt = max_interrupt_work;
- int handled = 0;
-
-- while ((intr_status = get_intr_status(dev))) {
-+ if ((rp->istat = (get_intr_status(dev) & rp->imask))) {
- handled = 1;
-
- /* Acknowledge all of the current interrupt sources ASAP. */
-- if (intr_status & IntrTxDescRace)
-+ if (rp->istat & IntrTxDescRace)
- iowrite8(0x08, ioaddr + IntrStatus2);
-- iowrite16(intr_status & 0xffff, ioaddr + IntrStatus);
-+ iowrite16(rp->istat & 0xffff, ioaddr + IntrStatus);
- IOSYNC;
-
-- if (debug > 4)
-- printk(KERN_DEBUG "%s: Interrupt, status %8.8x.\n",
-- dev->name, intr_status);
-+ if (likely(rp->istat & ((IntrRxDone | IntrRxErr | IntrRxDropped |
-+ IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf |
-+ IntrTxErrSummary | IntrTxDone)))) {
-+
-+ rhine_intr_disable(dev);
-
-- if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
-- IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf))
-- rhine_rx(dev);
--
-- if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
-- if (intr_status & IntrTxErrSummary) {
-- /* Avoid scavenging before Tx engine turned off */
-- RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn));
-- if (debug > 2 &&
-- ioread8(ioaddr+ChipCmd) & CmdTxOn)
-- printk(KERN_WARNING "%s: "
-- "rhine_interrupt() Tx engine"
-- "still on.\n", dev->name);
-- }
-- rhine_tx(dev);
-+ if (likely(netif_rx_schedule_prep(dev)))
-+ __netif_rx_schedule(dev);
- }
-
- /* Abnormal error summary/uncommon events handlers. */
-- if (intr_status & (IntrPCIErr | IntrLinkChange |
-+ if (unlikely(rp->istat & (IntrPCIErr | IntrLinkChange |
- IntrStatsMax | IntrTxError | IntrTxAborted |
-- IntrTxUnderrun | IntrTxDescRace))
-- rhine_error(dev, intr_status);
--
-- if (--boguscnt < 0) {
-- printk(KERN_WARNING "%s: Too much work at interrupt, "
-- "status=%#8.8x.\n",
-- dev->name, intr_status);
-- break;
-- }
-+ IntrTxUnderrun | IntrTxDescRace)))
-+ rhine_error(dev);
- }
-
-- if (debug > 3)
-- printk(KERN_DEBUG "%s: exiting interrupt, status=%8.8x.\n",
-- dev->name, ioread16(ioaddr + IntrStatus));
- return IRQ_RETVAL(handled);
- }
-
- /* This routine is logically part of the interrupt handler, but isolated
- for clarity. */
--static void rhine_tx(struct net_device *dev)
-+static int rhine_tx(struct net_device *dev)
- {
- struct rhine_private *rp = netdev_priv(dev);
- int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE;
-+ void __iomem *ioaddr = rp->base;
-+ int done = 0;
-
-- spin_lock(&rp->lock);
-+ /* Avoid scavenging before Tx engine turned off */
-+ RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn));
-+ if (debug > 2 &&
-+ ioread8(ioaddr+ChipCmd) & CmdTxOn)
-+ printk(KERN_WARNING "%s: "
-+ "rhine_interrupt() Tx engine"
-+ "still on.\n", dev->name);
-
-+
-+ spin_lock_irq(&rp->lock);
- /* find and cleanup dirty tx descriptors */
- while (rp->dirty_tx != rp->cur_tx) {
- txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status);
-@@ -1462,6 +1490,7 @@
- txstatus & 0xF);
- rp->stats.tx_bytes += rp->tx_skbuff[entry]->len;
- rp->stats.tx_packets++;
-+ done++;
- }
- /* Free the original skb. */
- if (rp->tx_skbuff_dma[entry]) {
-@@ -1470,23 +1499,25 @@
- rp->tx_skbuff[entry]->len,
- PCI_DMA_TODEVICE);
- }
-- dev_kfree_skb_irq(rp->tx_skbuff[entry]);
-+ dev_kfree_skb_any(rp->tx_skbuff[entry]);
- rp->tx_skbuff[entry] = NULL;
- entry = (++rp->dirty_tx) % TX_RING_SIZE;
- }
-+ spin_unlock_irq(&rp->lock);
-+
- if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4)
- netif_wake_queue(dev);
-
-- spin_unlock(&rp->lock);
-+ return done;
- }
-
- /* This routine is logically part of the interrupt handler, but isolated
- for clarity and better register allocation. */
--static void rhine_rx(struct net_device *dev)
-+static int rhine_rx(struct net_device *dev)
- {
- struct rhine_private *rp = netdev_priv(dev);
- int entry = rp->cur_rx % RX_RING_SIZE;
-- int boguscnt = rp->dirty_rx + RX_RING_SIZE - rp->cur_rx;
-+ int done = 0;
-
- if (debug > 4) {
- printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n",
-@@ -1503,8 +1534,6 @@
- if (debug > 4)
- printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n",
- desc_status);
-- if (--boguscnt < 0)
-- break;
- if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) {
- if ((desc_status & RxWholePkt) != RxWholePkt) {
- printk(KERN_WARNING "%s: Oversized Ethernet "
-@@ -1528,9 +1557,7 @@
- if (desc_status & 0x0004) rp->stats.rx_frame_errors++;
- if (desc_status & 0x0002) {
- /* this can also be updated outside the interrupt handler */
-- spin_lock(&rp->lock);
- rp->stats.rx_crc_errors++;
-- spin_unlock(&rp->lock);
- }
- }
- } else {
-@@ -1558,6 +1585,7 @@