NAPI support in various net drivers (backported from Linux 2.6).

---

 drivers/net/8139too.c           |  235 +++++++++++++++++++++
 drivers/net/Config.in           |    8 
 drivers/net/Makefile            |   13 -
 drivers/net/bonding/bond_main.c |    2 
 drivers/net/e100/e100.h         |    4 
 drivers/net/e100/e100_main.c    |  178 +++++++++-------
 drivers/net/eepro100.c          |   36 ++-
 drivers/net/gt64240eth.h        |    2 
 drivers/net/natsemi.c           |  147 +++++++++++--
 drivers/net/starfire.c          |    7 
 drivers/net/sundance.c          |    3 
 drivers/net/tulip/interrupt.c   |  432 ++++++++++++++++++++++++++++------------
 drivers/net/tulip/tulip.h       |   31 +-
 drivers/net/tulip/tulip_core.c  |  186 +++++++++++++----
 14 files changed, 983 insertions(+), 301 deletions(-)

diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 81dbd19..f7ef441 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -92,8 +92,11 @@
 */
 
 #define DRV_NAME	"8139too"
+#ifdef CONFIG_8139TOO_NAPI
+#define DRV_VERSION	"0.9.26-NAPI"
+#else
 #define DRV_VERSION	"0.9.26"
-
+#endif
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -163,8 +166,10 @@
 static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
+#ifndef CONFIG_8139TOO_NAPI
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 20;
+#endif
 
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
    The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
@@ -599,13 +604,17 @@ MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
 MODULE_LICENSE("GPL");
 
 MODULE_PARM (multicast_filter_limit, "i");
+#ifndef CONFIG_8139TOO_NAPI
 MODULE_PARM (max_interrupt_work, "i");
+#endif
 MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM (debug, "i");
 MODULE_PARM_DESC (debug, "8139too bitmapped message enable number");
 MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
+#ifndef CONFIG_8139TOO_NAPI
 MODULE_PARM_DESC (max_interrupt_work, "8139too maximum events handled per interrupt");
+#endif
 MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
 MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)");
 
@@ -628,6 +637,9 @@ static void rtl8139_set_rx_mode (struct net_device *dev);
 static void __set_rx_mode (struct net_device *dev);
 static void rtl8139_hw_start (struct net_device *dev);
 static struct ethtool_ops rtl8139_ethtool_ops;
+#ifdef CONFIG_8139TOO_NAPI
+static int rtl8139_poll(struct net_device *dev, int *budget);
+#endif
 
 #ifdef USE_IO_OPS
 
@@ -971,6 +983,10 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
 	/* The Rtl8139-specific entries in the device structure. */
 	dev->open = rtl8139_open;
 	dev->hard_start_xmit = rtl8139_start_xmit;
+#ifdef CONFIG_8139TOO_NAPI
+	dev->poll = rtl8139_poll;
+	dev->weight = 16;
+#endif
 	dev->stop = rtl8139_close;
 	dev->get_stats = rtl8139_get_stats;
 	dev->set_multicast_list = rtl8139_set_rx_mode;
@@ -1896,7 +1912,150 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
 	__set_rx_mode (dev);
 #endif
 }
+#ifdef CONFIG_8139TOO_NAPI
+/**
+ * NAPI poll routine.
+ */
+static int rtl8139_poll (struct net_device *dev, int *budget)
+{
+	struct rtl8139_private *tp;
+	void *ioaddr;
+	unsigned char *rx_ring;
+	u16 cur_rx;
+	int rx, status;
+	unsigned long flags;
+
+	assert (dev != NULL);
+
+	tp = dev->priv;
+	ioaddr = tp->mmio_addr;
+
+	spin_lock_irqsave(&tp->lock, flags);
+rescan:
+	rx_ring = tp->rx_ring;
+	cur_rx = tp->cur_rx;
+	rx = 0;
+
+	DPRINTK ("%s: In rtl8139_rx_poll(), current %4.4x BufAddr %4.4x,"
+		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+		 RTL_R16 (RxBufAddr),
+		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
+
+	while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
+		int ring_offset = cur_rx % RX_BUF_LEN;
+		u32 rx_status;
+		unsigned int rx_size;
+		unsigned int pkt_size;
+		struct sk_buff *skb;
+
+		rmb();
+
+		/* read size+status of next frame from DMA ring buffer */
+		rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
+		rx_size = rx_status >> 16;
+		pkt_size = rx_size - 4;
+
+		if (netif_msg_rx_status(tp))
+			printk(KERN_DEBUG "%s:  rtl8139_rx() status %4.4x, size %4.4x,"
+				" cur %4.4x.\n", dev->name, rx_status,
+			 rx_size, cur_rx);
+#if RTL8139_DEBUG > 2
+		{
+			int i;
+			DPRINTK ("%s: Frame contents ", dev->name);
+			for (i = 0; i < 70; i++)
+				printk (" %2.2x",
+					rx_ring[ring_offset + i]);
+			printk (".\n");
+		}
+#endif
+
+		/* Packet copy from FIFO still in progress.
+		 * Theoretically, this should never happen
+		 * since EarlyRx is disabled.
+		 */
+		if (rx_size == 0xfff0) {
+			tp->xstats.early_rx++;
+			break;
+		}
+
+		/* If Rx err or invalid rx_size/rx_status received
+		 * (which happens if we get lost in the ring),
+		 * Rx process gets reset, so we abort any further
+		 * Rx processing.
+		 */
+		if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
+		    (rx_size < 8) ||
+		    (!(rx_status & RxStatusOK))) {
+			rtl8139_rx_err (rx_status, dev, tp, ioaddr);
+			goto err;
+		}
+
+		/**
+		 * Drop lock so we can copy data with interrupts enabled.
+		 */
+		spin_unlock_irqrestore(&tp->lock, flags);
 
+		/* Omit the four octet CRC from the length. */
+		skb = dev_alloc_skb (pkt_size + 2);
+		if (skb) {
+			skb->dev = dev;
+			skb_reserve (skb, 2);	/* 16 byte align the IP fields. */
+
+			eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+			skb_put (skb, pkt_size);
+
+			skb->protocol = eth_type_trans (skb, dev);
+			netif_receive_skb(skb);
+			dev->last_rx = jiffies;
+			tp->stats.rx_bytes += pkt_size;
+			tp->stats.rx_packets++;
+		} else {
+			if (net_ratelimit()) {
+				printk (KERN_WARNING
+					"%s: Memory squeeze, dropping packet.\n",
+					dev->name);
+			}
+			tp->stats.rx_dropped++;
+		}
+
+		spin_lock_irqsave(&tp->lock, flags);
+		cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
+		RTL_W16 (RxBufPtr, cur_rx - 16);
+
+		status = RTL_R16 (IntrStatus) & RxAckBits;
+
+		if (status) {
+			RTL_W16_F (IntrStatus, RxAckBits);
+		}
+		if (++rx >= dev->quota) {
+			break;
+		}
+	}
+
+	DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
+		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+		 RTL_R16 (RxBufAddr),
+		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
+
+	tp->cur_rx = cur_rx;
+err:
+	*budget -= rx;
+	if ((dev->quota -= rx) <= 0) {
+		spin_unlock_irqrestore(&tp->lock, flags);
+		return 1;
+	}
+	/* last gasp check if interrupt still pending */
+	if (RTL_R16 (IntrStatus) & RxAckBits) {
+		DPRINTK("%s: going back for more work\n", dev->name);
+		goto rescan;
+	}
+	netif_rx_complete(dev);
+	RTL_W16 (IntrMask, rtl8139_intr_mask);
+	spin_unlock_irqrestore(&tp->lock, flags);
+	return 0; /* done */
+}
+#else
 static void rtl8139_rx_interrupt (struct net_device *dev,
 				  struct rtl8139_private *tp, void *ioaddr)
 {
@@ -1929,9 +2088,8 @@ static void rtl8139_rx_interrupt (struct net_device *dev,
 		rx_size = rx_status >> 16;
 		pkt_size = rx_size - 4;
 
-		if (netif_msg_rx_status(tp))
-			printk(KERN_DEBUG "%s:  rtl8139_rx() status %4.4x, size %4.4x,"
-				" cur %4.4x.\n", dev->name, rx_status,
+		DPRINTK ("%s:  rtl8139_rx() status %4.4x, size %4.4x,"
+			 " cur %4.4x.\n", dev->name, rx_status,
 			 rx_size, cur_rx);
 #if RTL8139_DEBUG > 2
 		{
@@ -2008,7 +2166,7 @@ static void rtl8139_rx_interrupt (struct net_device *dev,
 
 	tp->cur_rx = cur_rx;
 }
-
+#endif
 
 static void rtl8139_weird_interrupt (struct net_device *dev,
 				     struct rtl8139_private *tp,
@@ -2033,8 +2191,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev,
 	}
 
 	/* XXX along with rtl8139_rx_err, are we double-counting errors? */
-	if (status &
-	    (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
+	if (status & RxUnderrun)
 		tp->stats.rx_errors++;
 
 	if (status & PCSTimeout)
@@ -2054,6 +2211,68 @@ static void rtl8139_weird_interrupt (struct net_device *dev,
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
+#ifdef CONFIG_8139TOO_NAPI
+static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
+			       struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_instance;
+	struct rtl8139_private *tp = dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	int ackstat, status;
+	int link_changed = 0; /* avoid bogus "uninit" warning */
+
+	spin_lock (&tp->lock);
+
+	status = RTL_R16 (IntrStatus);
+
+	/* h/w no longer present (hotplug?) or major error, bail */
+	if (unlikely(status == 0xFFFF)) {
+		spin_unlock(&tp->lock);
+		return IRQ_HANDLED;
+	}
+	
+	/* no interrupt source present */
+	if (unlikely((status & rtl8139_intr_mask) == 0)) {
+		spin_unlock(&tp->lock);
+		return IRQ_NONE;
+	}
+
+	/* The chip takes special action when we clear RxAckBits,
+	 * so we clear them later in poll
+	 */
+	ackstat = status & ~(RxAckBits | TxErr);
+	RTL_W16 (IntrStatus, ackstat);
+	
+	DPRINTK ("%s: interrupt  status=%#4.4x ackstat=%#4.4x new intstat=%#4.4x.\n",
+			dev->name, status, ackstat, RTL_R16 (IntrStatus));
+
+	/* If received interrupt, then disable furthur interrupts
+	 * and enable NAPI polling.
+	 */
+	if (netif_running (dev) && (status & RxAckBits)) {
+		/* disable more receive interrupts */
+		RTL_W16 (IntrMask, rtl8139_intr_mask & ~RxAckBits);
+		netif_rx_schedule(dev);
+	}
+
+	/* Check uncommon events with one test. */
+	if (unlikely(status & (PCIErr|PCSTimeout|RxUnderrun|RxOverflow))) {
+		rtl8139_weird_interrupt (dev, tp, ioaddr,
+				status, link_changed);
+	}
+	if (netif_running (dev) && (status & (TxOK | TxErr))) {
+		rtl8139_tx_interrupt (dev, tp, ioaddr);
+		if (status & TxErr)
+			RTL_W16 (IntrStatus, TxErr);
+	}
+
+	spin_unlock (&tp->lock);
+
+	DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",
+		 dev->name, RTL_R16 (IntrStatus));
+	return IRQ_HANDLED;
+}
+#else
 static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
 			       struct pt_regs *regs)
 {
@@ -2128,7 +2347,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
 		 dev->name, RTL_R16 (IntrStatus));
 	return IRQ_RETVAL(handled);
 }
-
+#endif
 
 static int rtl8139_close (struct net_device *dev)
 {
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index 188fe42..4fa79f6 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -178,6 +178,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then
          dep_bool '      New bus configuration (EXPERIMENTAL)' CONFIG_TULIP_MWI $CONFIG_EXPERIMENTAL
          bool '      Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO
+         bool '      Use NAPI' CONFIG_TULIP_NAPI
       fi
       if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then
          tristate '    Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
@@ -191,9 +192,15 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
          dep_mbool '      Use PIO instead of MMIO' CONFIG_EEPRO100_PIO $CONFIG_EEPRO100
       fi  
       dep_tristate '    EtherExpressPro/100 support (e100, Alternate Intel driver)' CONFIG_E100 $CONFIG_PCI
+      if [ "$CONFIG_E100" = "y" -o "$CONFIG_E100" = "m" ]; then
+         bool '      Use NAPI' CONFIG_E100_NAPI
+      fi
       dep_tristate '    Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL
       dep_tristate '    Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI
       dep_tristate '    National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI
+      if [ "$CONFIG_NATSEMI" = "y" -o "$CONFIG_NATSEMI" = "m" ]; then
+         bool '      Use NAPI' CONFIG_NATSEMI_NAPI
+      fi
       dep_tristate '    PCI NE2000 and clones support (see help)' CONFIG_NE2K_PCI $CONFIG_PCI
       dep_tristate '    nForce Ethernet support (EXPERIMENTAL)' CONFIG_FORCEDETH $CONFIG_PCI $CONFIG_EXPERIMENTAL
       dep_tristate '    Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
@@ -201,6 +208,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       dep_tristate '    RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_8139CP $CONFIG_PCI $CONFIG_EXPERIMENTAL
       dep_tristate '    RealTek RTL-8139 PCI Fast Ethernet Adapter support' CONFIG_8139TOO $CONFIG_PCI
       dep_mbool '      Use PIO instead of MMIO' CONFIG_8139TOO_PIO $CONFIG_8139TOO
+      dep_mbool '      Use NAPI' CONFIG_8139TOO_NAPI $CONFIG_8139TOO
       dep_mbool '      Support for uncommon RTL-8139 rev. K (automatic channel equalization)' CONFIG_8139TOO_TUNE_TWISTER $CONFIG_8139TOO
       dep_mbool '      Support for older RTL-8129/8130 boards' CONFIG_8139TOO_8129 $CONFIG_8139TOO
       dep_mbool '      Use older RX-reset method' CONFIG_8139_OLD_RX_RESET $CONFIG_8139TOO
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 82f52fe..fba8c82 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -21,10 +21,6 @@ export-objs     :=	8390.o arlan.o aironet4500_core.o aironet4500_card.o \
 list-multi	:=	rcpci.o
 rcpci-objs	:=	rcpci45.o rclanmtl.o
 
-ifeq ($(CONFIG_TULIP),y)
-  obj-y += tulip/tulip.o
-endif
-
 obj-$(CONFIG_OCP_NET) += ibm_emac/ocp.o
 
 ifeq ($(CONFIG_E1000),y)
@@ -108,6 +104,13 @@ ifeq ($(CONFIG_SKFP),y)
   obj-y += skfp/skfp.o
 endif
 
+ifeq ($(CONFIG_TULIP),y)
+  obj-y += tulip/tulip.o
+endif
+
+obj-$(CONFIG_8139CP) += 8139cp.o mii.o
+obj-$(CONFIG_8139TOO) += 8139too.o mii.o
+
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o mii.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o mii.o
 
@@ -192,8 +195,6 @@ obj-$(CONFIG_EL3) += 3c509.o
 obj-$(CONFIG_3C515) += 3c515.o
 obj-$(CONFIG_EEXPRESS) += eexpress.o
 obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_8139CP) += 8139cp.o mii.o
-obj-$(CONFIG_8139TOO) += 8139too.o mii.o
 obj-$(CONFIG_WAVELAN) += wavelan.o
 obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
 obj-$(CONFIG_ZNET) += znet.o
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index c588ea3..086aa94 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4662,7 +4662,7 @@ static int __init bonding_init(void)
 			goto out_err;
 		}
 
-		res = dev_alloc_name(bond_dev, "bond%d");
+		res = dev_alloc_name(bond_dev, "bnd%d");
 		if (res < 0) {
 			free_netdev(bond_dev);
 			goto out_err;
diff --git a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h
index 7d977da..9916c12 100644
--- a/drivers/net/e100/e100.h
+++ b/drivers/net/e100/e100.h
@@ -948,10 +948,10 @@ struct e100_private {
 #ifdef CONFIG_PM
 	u32 pci_state[16];
 #endif
-#ifdef E100_CU_DEBUG	
+#ifdef E100_CU_DEBUG
 	u8 last_cmd;
 	u8 last_sub_cmd;
-#endif	
+#endif
 };
 
 #define E100_AUTONEG        0
diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
index c9d801a..03c065b 100644
--- a/drivers/net/e100/e100_main.c
+++ b/drivers/net/e100/e100_main.c
@@ -135,14 +135,14 @@ static void e100_non_tx_background(unsigned long);
 static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
 /* Global Data structures and variables */
 char e100_copyright[] __devinitdata = "Copyright (c) 2004 Intel Corporation";
+#ifdef CONFIG_E100_NAPI
+char e100_driver_version[]="2.3.43-k1-NAPI";
+#else
 char e100_driver_version[]="2.3.43-k1";
+#endif
 const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
 char e100_short_driver_name[] = "e100";
 static int e100nics = 0;
-static void e100_vlan_rx_register(struct net_device *netdev, struct vlan_group
-		*grp);
-static void e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
-static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /* for netdump / net console */
@@ -223,7 +223,9 @@ static void e100_set_bool_option(struct e100_private *bdp, int, u32, int,
 				 char *);
 unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8);
 void e100_exec_cmplx(struct e100_private *, u32, u8);
-
+#ifdef CONFIG_E100_NAPI
+static int e100_poll(struct net_device *dev, int *budget);
+#endif
 /**
  * e100_get_rx_struct - retrieve cell to hold skb buff from the pool
  * @bdp: atapter's private data struct
@@ -343,7 +345,11 @@ e100_alloc_skbs(struct e100_private *bdp)
 }
 
 void e100_tx_srv(struct e100_private *);
+#ifdef CONFIG_E100_NAPI
+u32 e100_rx_srv(struct e100_private *bdp, int *work_done, int work_to_do);
+#else
 u32 e100_rx_srv(struct e100_private *);
+#endif
 
 void e100_watchdog(struct net_device *);
 void e100_refresh_txthld(struct e100_private *);
@@ -636,9 +642,6 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
 		bdp->rfd_size = 16;
 	}
 
-	dev->vlan_rx_register = e100_vlan_rx_register;
-	dev->vlan_rx_add_vid = e100_vlan_rx_add_vid;
-	dev->vlan_rx_kill_vid = e100_vlan_rx_kill_vid;
 	dev->irq = pcid->irq;
 	dev->open = &e100_open;
 	dev->hard_start_xmit = &e100_xmit_frame;
@@ -653,10 +656,14 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
 	dev->poll_controller = e100_netpoll;
 #endif
 
-	if (bdp->flags & USE_IPCB)
-	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM |
-			NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-		
+#ifdef CONFIG_E100_NAPI
+	dev->poll = e100_poll;
+	dev->weight = 16;
+#endif
+	if (bdp->flags & USE_IPCB) {
+		dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
+	}
+
 	if ((rc = register_netdev(dev)) != 0) {
 		goto err_dealloc;
 	}
@@ -768,20 +775,24 @@ e100_remove1(struct pci_dev *pcid)
 	--e100nics;
 }
 
+static struct pci_device_id e100_id_table_pre[] __devinitdata = {
+	{0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0,}
+};
+
 static struct pci_device_id e100_id_table[] = {
 	{0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-  	{0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },	
-	{0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 
+	{0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 
-	{0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 
+	{0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
@@ -816,20 +827,40 @@ static struct pci_driver e100_driver = {
 	.resume       = e100_resume,
 #endif
 };
+static struct pci_driver e100_driver_pre = {
+	.name         = "e100",
+	.id_table     = e100_id_table_pre,
+	.probe        = e100_found1,
+	.remove       = __devexit_p(e100_remove1),
+#ifdef CONFIG_PM
+	.suspend      = e100_suspend,
+	.resume       = e100_resume,
+#endif
+};
 
 static int __init
 e100_init_module(void)
 {
-	int ret;
-        ret = pci_module_init(&e100_driver);
+	int ret1,ret2;
+
+	ret1 = pci_module_init(&e100_driver_pre);
+	if (!ret1 || ret1 == -ENODEV) {
+		ret2 = pci_module_init(&e100_driver);
+	}
+	else {
+		return ret1;
+	}
+	if (!ret1 && ret2 == -ENODEV) {
+		ret2 = 0;
+	}
 
-	if(ret >= 0) {
+	if(ret2 >= 0) {
 #ifdef CONFIG_PM
 		register_reboot_notifier(&e100_notifier_reboot);
-#endif 
+#endif
 	}
 
-	return ret;
+	return ret2;
 }
 
 static void __exit
@@ -1453,7 +1484,6 @@ e100_sw_init(struct e100_private *bdp)
 	spin_lock_init(&(bdp->mdi_access_lock));
 	/* Initialize configuration data */
 	e100_config_init(bdp);
-
 	return 1;
 }
 
@@ -2018,20 +2048,23 @@ e100intr(int irq, void *dev_inst, struct pt_regs *regs)
 		return IRQ_NONE;
 	}
 
-	/* disable and ack intr */
 	e100_disable_clear_intr(bdp);
 
-	/* the device is closed, don't continue or else bad things may happen. */
 	if (!netif_running(dev)) {
-		e100_set_intr_mask(bdp);
 		return IRQ_NONE;
 	}
-
 	/* SWI intr (triggered by watchdog) is signal to allocate new skb buffers */
 	if (intr_status & SCB_STATUS_ACK_SWI) {
 		e100_alloc_skbs(bdp);
 	}
-
+#ifdef CONFIG_E100_NAPI
+	if (netif_rx_schedule_prep(dev)) {
+		__netif_rx_schedule(dev);
+	}
+	else {
+		e100_set_intr_mask(bdp);
+	}
+#else
 	/* do recv work if any */
 	if (intr_status &
 	    (SCB_STATUS_ACK_FR | SCB_STATUS_ACK_RNR | SCB_STATUS_ACK_SWI)) 
@@ -2042,9 +2075,32 @@ e100intr(int irq, void *dev_inst, struct pt_regs *regs)
 		e100_tx_srv(bdp);
 
 	e100_set_intr_mask(bdp);
+#endif
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_E100_NAPI
+static int
+e100_poll(struct net_device *netdev, int *budget)
+{
+	struct e100_private *bdp = netdev->priv;
+	int work_to_do = min(*budget, netdev->quota);
+	int work_done = 0;
+
+	e100_tx_srv(bdp);
+	e100_rx_srv(bdp, &work_done, work_to_do);
+
+	*budget -= work_done;
+	netdev->quota -= work_done;
+
+	if(work_done < work_to_do) {
+		netif_rx_complete(netdev);
+		e100_set_intr_mask(bdp);
+	}
+	return (work_done >= work_to_do);
+}
+#endif
+
 /**
  * e100_tx_srv - service TX queues
  * @bdp: atapter's private data struct
@@ -2066,7 +2122,6 @@ e100_tx_srv(struct e100_private *bdp)
 		tcb += bdp->tcb_pool.head;
 
 		rmb();
-
 		/* if the buffer at 'head' is not complete, break */
 		if (!(tcb->tcb_hdr.cb_status &
 		      __constant_cpu_to_le16(CB_STATUS_COMPLETE)))
@@ -2100,7 +2155,11 @@ e100_tx_srv(struct e100_private *bdp)
  * It returns the number of serviced RFDs.
  */
 u32
+#ifdef CONFIG_E100_NAPI
+e100_rx_srv(struct e100_private *bdp, int *work_done, int work_to_do)
+#else
 e100_rx_srv(struct e100_private *bdp)
+#endif
 {
 	rfd_t *rfd;		/* new rfd, received rfd */
 	int i;
@@ -2128,7 +2187,11 @@ e100_rx_srv(struct e100_private *bdp)
 		if (list_empty(&(bdp->active_rx_list))) {
 			break;
 		}
-
+#ifdef CONFIG_E100_NAPI
+		if(*work_done >= work_to_do)
+			break;
+		(*work_done)++;
+#endif
 		rx_struct = list_entry(bdp->active_rx_list.next,
 				       struct rx_list_elem, list_elem);
 		skb = rx_struct->skb;
@@ -2192,13 +2255,13 @@ e100_rx_srv(struct e100_private *bdp)
 			skb->ip_summed = CHECKSUM_NONE;
 		}
 
-		if(bdp->vlgrp && (rfd_status & CB_STATUS_VLAN)) {
-			vlan_hwaccel_rx(skb, bdp->vlgrp, be16_to_cpu(rfd->vlanid));
-		} else {
-			netif_rx(skb);
-		}
+#ifdef CONFIG_E100_NAPI
+		netif_receive_skb(skb);
+#else
+		netif_rx(skb);
+#endif
 		dev->last_rx = jiffies;
-		
+
 		rfd_cnt++;
 	}			/* end of rfd loop */
 
@@ -4242,45 +4305,6 @@ exit:
 	spin_unlock_bh(&(bdp->bd_non_tx_lock));
 }
 
-static void
-e100_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
-	struct e100_private *bdp = netdev->priv;
-
-	e100_disable_clear_intr(bdp);
-	bdp->vlgrp = grp;
-
-	if(grp) {
-		/* enable VLAN tag insert/strip */
-		e100_config_vlan_drop(bdp, true);
-
-	} else {
-		/* disable VLAN tag insert/strip */
-		e100_config_vlan_drop(bdp, false);
-	}
-
-	e100_config(bdp);
-	e100_set_intr_mask(bdp);
-}
-
-static void
-e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
-	/* We don't do Vlan filtering */
-	return;
-}
-
-static void
-e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
-	struct e100_private *bdp = netdev->priv;
-
-	if(bdp->vlgrp)
-		bdp->vlgrp->vlan_devices[vid] = NULL;
-	/* We don't do Vlan filtering */
-	return;
-}
-
 #ifdef CONFIG_PM
 static int
 e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 0877586..6cd5269 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -2369,13 +2369,17 @@ static void __devexit eepro100_remove_one (struct pci_dev *pdev)
 	kfree(dev);
 }
 
+static struct pci_device_id eepro100_pci_tbl_pre[] __devinitdata = {
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_7,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0,}
+};
 static struct pci_device_id eepro100_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557,
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER,
 		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_7,
-		PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, },
@@ -2387,7 +2391,6 @@ static struct pci_device_id eepro100_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, },
@@ -2405,6 +2408,16 @@ static struct pci_device_id eepro100_pci_tbl[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl);
 	
+static struct pci_driver eepro100_driver_pre = {
+	name:		"eepro100",
+	id_table:	eepro100_pci_tbl_pre,
+	probe:		eepro100_init_one,
+	remove:		__devexit_p(eepro100_remove_one),
+#ifdef CONFIG_PM
+	suspend:	eepro100_suspend,
+	resume:		eepro100_resume,
+#endif /* CONFIG_PM */
+};
 static struct pci_driver eepro100_driver = {
 	name:		"eepro100",
 	id_table:	eepro100_pci_tbl,
@@ -2434,15 +2447,30 @@ static int pci_module_init(struct pci_driver *pdev)
 
 static int __init eepro100_init_module(void)
 {
+	int r1,r2;
 #ifdef MODULE
 	printk(version);
 #endif
-	return pci_module_init(&eepro100_driver);
+
+	r1 =  pci_module_init(&eepro100_driver_pre);
+	if ((r1==0) || (r1==-ENODEV)) {
+		r2 =  pci_module_init(&eepro100_driver);
+	}
+	else {	
+		return r1;
+	}
+
+	if ((r1==0) && (r2==-ENODEV)) {
+		r2 = 0;
+	}
+
+	return r2;
 }
 
 static void __exit eepro100_cleanup_module(void)
 {
 	pci_unregister_driver(&eepro100_driver);
+	pci_unregister_driver(&eepro100_driver_pre);
 }
 
 module_init(eepro100_init_module);
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 215473a..d51b50e 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -136,7 +136,6 @@
 	TODO:
 	* big endian support with CFG:BEM instead of cpu_to_le32
 	* support for an external PHY
-	* NAPI
 */
 
 #if !defined(__OPTIMIZE__)
@@ -172,7 +171,11 @@
 #include <asm/uaccess.h>
 
 #define DRV_NAME	"natsemi"
+#ifdef CONFIG_NATSEMI_NAPI
+#define DRV_VERSION	"1.07+LK1.0.17-NAPI"
+#else
 #define DRV_VERSION	"1.07+LK1.0.17"
+#endif
 #define DRV_RELDATE	"Sep 27, 2002"
 
 #define RX_OFFSET	2
@@ -188,9 +191,10 @@
 				 NETIF_MSG_RX_ERR	| \
 				 NETIF_MSG_TX_ERR)
 static int debug = -1;
-
+#ifndef CONFIG_NATSEMI_NAPI
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 20;
+#endif
 static int mtu;
 
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
@@ -249,15 +253,16 @@ static char version[] __devinitdata =
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver");
 MODULE_LICENSE("GPL");
-
+#ifndef CONFIG_NATSEMI_NAPI
 MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM_DESC(max_interrupt_work,
+	"DP8381x maximum events handled per interrupt");
+#endif
 MODULE_PARM(mtu, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM_DESC(max_interrupt_work, 
-	"DP8381x maximum events handled per interrupt");
 MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)");
 MODULE_PARM_DESC(debug, "DP8381x default debug level");
 MODULE_PARM_DESC(rx_copybreak, 
@@ -674,6 +679,9 @@ struct netdev_private {
 	unsigned int iosize;
 	spinlock_t lock;
 	u32 msg_enable;
+#ifdef CONFIG_NATSEMI_NAPI
+	atomic_t irq_sem;
+#endif
 };
 
 static int eeprom_read(long ioaddr, int location);
@@ -699,8 +707,12 @@ static void reinit_ring(struct net_device *dev);
 static void init_registers(struct net_device *dev);
 static int start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
-static void netdev_error(struct net_device *dev, int intr_status);
+#ifdef CONFIG_NATSEMI_NAPI
+static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do);
+#else
 static void netdev_rx(struct net_device *dev);
+#endif
+static void netdev_error(struct net_device *dev, int intr_status);
 static void netdev_tx_done(struct net_device *dev);
 static void __set_rx_mode(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
@@ -717,7 +729,39 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr);
 static int netdev_close(struct net_device *dev);
 static int netdev_get_regs(struct net_device *dev, u8 *buf);
 static int netdev_get_eeprom(struct net_device *dev, u8 *buf);
+#ifdef CONFIG_NATSEMI_NAPI
+static int netdev_poll(struct net_device *dev, int *budget);
+#endif
 
+static void intr_enable(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+#ifdef CONFIG_NATSEMI_NAPI
+	if(atomic_dec_and_test(&np->irq_sem)) {
+		writel(DEFAULT_INTR, dev->base_addr + IntrMask);
+		writel(1, dev->base_addr + IntrEnable);
+		readl(dev->base_addr + IntrEnable); // read safe
+		mb();
+	}
+#else
+	writel(DEFAULT_INTR, dev->base_addr + IntrMask);
+	writel(1, dev->base_addr + IntrEnable);
+	readl(dev->base_addr + IntrEnable); // read safe
+	mb();
+#endif
+
+}
+
+static void intr_disable(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+#ifdef CONFIG_NATSEMI_NAPI
+	atomic_inc(&np->irq_sem);
+#endif
+	writel(0, dev->base_addr + IntrEnable);
+	readl(dev->base_addr + IntrEnable); // read safe
+	mb();
+}
 
 static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	const struct pci_device_id *ent)
@@ -793,6 +837,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	pci_set_drvdata(pdev, dev);
 	np->iosize = iosize;
 	spin_lock_init(&np->lock);
+#ifdef CONFIG_NATSEMI_NAPI
+	atomic_set(&np->irq_sem, 1);
+#endif
 	np->msg_enable = (debug >= 0) ? (1<<debug)-1 : NATSEMI_DEF_MSG;
 	np->hands_off = 0;
 
@@ -825,6 +872,10 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	dev->do_ioctl = &netdev_ioctl;
 	dev->tx_timeout = &tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NATSEMI_NAPI
+	dev->poll = netdev_poll;
+	dev->weight = 16;
+#endif
 
 	if (mtu)
 		dev->mtu = mtu;
@@ -1294,7 +1345,7 @@ static void init_registers(struct net_device *dev)
 	/* DRTH 0x10: start copying to memory if 128 bytes are in the fifo
 	 * MXDMA 0: up to 256 byte bursts
 	 */
-	np->rx_config = RxMxdma_256 | 0x20;
+	np->rx_config = RxMxdma_256 | 0x20 | RxAcceptLong;
 	writel(np->rx_config, ioaddr + RxConfig);
 
 	/* Disable PME:
@@ -1314,8 +1365,10 @@ static void init_registers(struct net_device *dev)
 	__set_rx_mode(dev);
 
 	/* Enable interrupts by setting the interrupt mask. */
-	writel(DEFAULT_INTR, ioaddr + IntrMask);
-	writel(1, ioaddr + IntrEnable);
+/*	writel(DEFAULT_INTR, ioaddr + IntrMask);
+	writel(1, ioaddr + IntrEnable);*/
+	printk(KERN_INFO "Set Interrupt enable in init_registers\n");
+	intr_enable(dev);
 
 	writel(RxOn | TxOn, ioaddr + ChipCmd);
 	writel(StatsClear, ioaddr + StatsCtrl); /* Clear Stats */
@@ -1626,7 +1679,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
 		/* Wake the potentially-idle transmit channel. */
 		writel(TxOn, dev->base_addr + ChipCmd);
 	} else {
-		dev_kfree_skb_irq(skb);
+		dev_kfree_skb_any(skb);
 		np->stats.tx_dropped++;
 	}
 	spin_unlock_irq(&np->lock);
@@ -1673,7 +1726,7 @@ static void netdev_tx_done(struct net_device *dev)
 					np->tx_skbuff[entry]->len,
 					PCI_DMA_TODEVICE);
 		/* Free the original skb. */
-		dev_kfree_skb_irq(np->tx_skbuff[entry]);
+		dev_kfree_skb_any(np->tx_skbuff[entry]);
 		np->tx_skbuff[entry] = NULL;
 	}
 	if (netif_queue_stopped(dev)
@@ -1689,15 +1742,31 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
 {
 	struct net_device *dev = dev_instance;
 	struct netdev_private *np = dev->priv;
-	long ioaddr = dev->base_addr;
+	u32 intr_status;
+#ifndef CONFIG_NATSEMI_NAPI
 	int boguscnt = max_interrupt_work;
-	unsigned int handled = 0;
+	long ioaddr = dev->base_addr;
+#endif
 
-	if (np->hands_off)
+	if (np->hands_off) {
 		return IRQ_NONE;
+	}
+#ifdef CONFIG_NATSEMI_NAPI
+	intr_status = readl(dev->base_addr + IntrStatus);
+	/* Abnormal error summary/uncommon events handlers. */
+	if (intr_status & IntrAbnormalSummary)
+		netdev_error(dev, intr_status);
+
+	if (netif_rx_schedule_prep(dev)) {
+		intr_disable(dev);
+		__netif_rx_schedule(dev);
+	}
+	return IRQ_HANDLED;
+#else
+
 	do {
 		/* Reading automatically acknowledges all int sources. */
-		u32 intr_status = readl(ioaddr + IntrStatus);
+		intr_status = readl(ioaddr + IntrStatus);
 
 		if (netif_msg_intr(np))
 			printk(KERN_DEBUG
@@ -1740,11 +1809,44 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
 		printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name);
 
 	return IRQ_RETVAL(handled);
+#endif
+}
+
+#ifdef CONFIG_NATSEMI_NAPI
+static int netdev_poll(struct net_device *dev, int *budget)
+{
+	struct netdev_private *np = dev->priv;
+	int work_to_do = min(*budget, dev->quota);
+	int work_done = 0;
+
+	spin_lock(&np->lock);
+	netdev_tx_done(dev);
+	spin_unlock(&np->lock);
+
+	netdev_rx(dev, &work_done, work_to_do);
+
+	*budget -= work_done;
+	dev->quota -= work_done;
+
+	if (work_done < work_to_do) {
+		netif_rx_complete(dev);
+		/**
+		 * Enable Irq
+		 */
+		intr_enable(dev);
+	}
+	return (work_done >= work_to_do);
 }
+#endif
+
 
 /* This routine is logically part of the interrupt handler, but separated
    for clarity and better register allocation. */
+#ifdef CONFIG_NATSEMI_NAPI
+static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do)
+#else
 static void netdev_rx(struct net_device *dev)
+#endif
 {
 	struct netdev_private *np = dev->priv;
 	int entry = np->cur_rx % RX_RING_SIZE;
@@ -1760,6 +1862,11 @@ static void netdev_rx(struct net_device *dev)
 				entry, desc_status);
 		if (--boguscnt < 0)
 			break;
+#ifdef CONFIG_NATSEMI_NAPI
+		if (*work_done >= work_to_do)
+			break;
+		(*work_done)++;
+#endif
 		if ((desc_status&(DescMore|DescPktOK|DescRxLong)) != DescPktOK){
 			if (desc_status & DescMore) {
 				if (netif_msg_rx_err(np))
@@ -1812,7 +1919,11 @@ static void netdev_rx(struct net_device *dev)
 				np->rx_skbuff[entry] = NULL;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
+#ifdef CONFIG_NATSEMI_NAPI
+			netif_receive_skb(skb);
+#else
 			netif_rx(skb);
+#endif
 			dev->last_rx = jiffies;
 			np->stats.rx_packets++;
 			np->stats.rx_bytes += pkt_len;
@@ -2468,6 +2579,7 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr)
 		/* enable the WOL interrupt.
 		 * Could be used to send a netlink message.
 		 */
+		printk(KERN_INFO "Enable WOL Interrupt\n");
 		writel(WOLPkt | LinkChange, ioaddr + IntrMask);
 		writel(1, ioaddr + IntrEnable);
 	}
@@ -2499,8 +2611,7 @@ static int netdev_close(struct net_device *dev)
 	disable_irq(dev->irq);
 	spin_lock_irq(&np->lock);
 	/* Disable interrupts, and flush posted writes */
-	writel(0, ioaddr + IntrEnable);
-	readl(ioaddr + IntrEnable);
+	intr_disable(dev);
 	np->hands_off = 1;
 	spin_unlock_irq(&np->lock);
 	enable_irq(dev->irq);
@@ -2598,7 +2709,7 @@ static int natsemi_suspend (struct pci_dev *pdev, u32 state)
 		disable_irq(dev->irq);
 		spin_lock_irq(&np->lock);
 
-		writel(0, ioaddr + IntrEnable);
+		intr_disable(dev);
 		np->hands_off = 1;
 		natsemi_stop_rxtx(dev);
 		netif_stop_queue(dev);
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 14a25a4..77b6d38 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -171,10 +171,6 @@ TODO:
 #include "starfire_firmware.h"
 #endif /* HAS_FIRMWARE */
 
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define VLAN_SUPPORT
-#endif
-
 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
 
@@ -1977,9 +1973,6 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
 	int rc;
 
-	if (!netif_running(dev))
-		return -EINVAL;
-
 	if (cmd == SIOCETHTOOL)
 		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index aba75be..c44f9af 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -1654,9 +1654,6 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	int i;
 	long ioaddr = dev->base_addr;
 
-	if (!netif_running(dev))
-		return -EINVAL;
-
 	if (cmd == SIOCETHTOOL)
 		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index 802004b..a3003ff 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -23,9 +23,11 @@
 int tulip_rx_copybreak;
 unsigned int tulip_max_interrupt_work;
 
-#ifdef CONFIG_NET_HW_FLOWCONTROL
+#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
 
 #define MIT_SIZE 15
+#define MIT_TABLE 15 /* We use 0 or max */
+
 unsigned int mit_table[MIT_SIZE+1] =
 {
         /*  CRS11 21143 hardware Mitigation Control Interrupt
@@ -100,16 +102,27 @@ int tulip_refill_rx(struct net_device *dev)
 }
 
 
-static int tulip_rx(struct net_device *dev)
+#ifdef CONFIG_TULIP_NAPI
+void oom_timer(unsigned long data)
+{
+struct net_device *dev = (struct net_device *)data;
+	netif_rx_schedule(dev);
+}
+
+int tulip_poll(struct net_device *dev, int *budget)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int entry = tp->cur_rx % RX_RING_SIZE;
-	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
+	int rx_work_limit = *budget;
 	int received = 0;
 
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-        int drop = 0, mit_sel = 0;
+	if (!netif_running(dev))
+		goto done;
+
+	if (rx_work_limit > dev->quota)
+		rx_work_limit = dev->quota;
 
+#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
 /* that one buffer is needed for mit activation; or might be a
    bug in the ring buffer code; check later -- JHS*/
 
@@ -119,6 +132,237 @@ static int tulip_rx(struct net_device *dev)
 	if (tulip_debug > 4)
 		printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
 			   tp->rx_ring[entry].status);
+
+	do {
+		if (inl(dev->base_addr + CSR5) == 0xffffffff) {
+			printk(KERN_DEBUG " In tulip_poll(), hardware disappeared.\n");
+			break;
+		}
+		/* Acknowledge current RX interrupt sources. */
+		outl((RxIntr | RxNoBuf), dev->base_addr + CSR5);
+
+
+		/* If we own the next entry, it is a new packet. Send it up. */
+		while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
+			s32 status = le32_to_cpu(tp->rx_ring[entry].status);
+
+
+			if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx)
+				break;
+
+			if (tulip_debug > 5)
+				printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
+					dev->name, entry, status);
+			if (--rx_work_limit < 0)
+				goto not_done;
+
+		if ((status & (0x38000000 | RxDescFatalErr | RxWholePkt)) != RxWholePkt) {
+			if ((status & (0x38000000 | RxWholePkt)) != RxWholePkt) {
+					/* Ingore earlier buffers. */
+					if ((status & 0xffff) != 0x7fff) {
+						if (tulip_debug > 1)
+							printk(KERN_WARNING "%s: Oversized Ethernet frame "
+								"spanned multiple buffers, status %8.8x!\n",
+								dev->name, status);
+						tp->stats.rx_length_errors++;
+					}
+				}
+				else if (status & RxDescFatalErr) {
+					/* There was a fatal error. */
+					if (tulip_debug > 2)
+						printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
+							dev->name, status);
+					tp->stats.rx_errors++; /* end of a packet.*/
+					if (status & 0x0890) tp->stats.rx_length_errors++;
+					if (status & 0x0004) tp->stats.rx_frame_errors++;
+					if (status & 0x0002) tp->stats.rx_crc_errors++;
+					if (status & 0x0001) tp->stats.rx_fifo_errors++;
+				}
+			}
+			else {
+				/* Omit the four octet CRC from the length. */
+				short pkt_len = ((status >> 16) & 0x7ff) - 4;
+				struct sk_buff *skb;
+
+#ifndef final_version
+				if (pkt_len > 1522) {
+					printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
+						dev->name, pkt_len, pkt_len);
+					pkt_len = 1522;
+					tp->stats.rx_length_errors++;
+				}
+#endif
+				/* Check if the packet is long enough to accept without copying
+				   to a minimally-sized skbuff. */
+				if (pkt_len < tulip_rx_copybreak
+					&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+					skb->dev = dev;
+					skb_reserve(skb, 2);    /* 16 byte align the IP header */
+#if ! defined(__alpha__)
+					eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->tail,
+						pkt_len, 0);
+					skb_put(skb, pkt_len);
+#else
+					memcpy(skb_put(skb, pkt_len),
+						tp->rx_buffers[entry].skb->tail,
+						pkt_len);
+#endif
+				}
+				else {        /* Pass up the skb already on the Rx ring. */
+					char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
+							pkt_len);
+
+#ifndef final_version
+					if (tp->rx_buffers[entry].mapping !=
+						le32_to_cpu(tp->rx_ring[entry].buffer1)) {
+						printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
+							"do not match in tulip_rx: %08x vs. %08llx %p / %p.\n",
+							dev->name,
+							le32_to_cpu(tp->rx_ring[entry].buffer1),
+							(unsigned long long)tp->rx_buffers[entry].mapping,
+							skb->head, temp);
+					}
+#endif
+
+					tp->rx_buffers[entry].skb = NULL;
+					tp->rx_buffers[entry].mapping = 0;
+				}
+				skb->protocol = eth_type_trans(skb, dev);
+
+				netif_receive_skb(skb);
+
+				dev->last_rx = jiffies;
+				tp->stats.rx_packets++;
+				tp->stats.rx_bytes += pkt_len;
+				}
+			received++;
+
+			entry = (++tp->cur_rx) % RX_RING_SIZE;
+			if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4)
+				tulip_refill_rx(dev);
+
+		}
+
+		/* New ack strategy... irq does not ack Rx any longer
+			hopefully this helps */
+
+		/* Really bad things can happen here... If new packet arrives
+		 * and an irq arrives (tx or just due to occasionally unset
+		 * mask), it will be acked by irq handler, but new thread
+		 * is not scheduled. It is major hole in design.
+		 * No idea how to fix this if "playing with fire" will fail
+		 * tomorrow (night 011029). If it will not fail, we won
+		 * finally: amount of IO did not increase at all. */
+	} while ((inl(dev->base_addr + CSR5) & RxIntr));
+
+done:
+
+#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
+
+	/* We use this simplistic scheme for IM. It's proven by
+	   real life installations. We can have IM enabled
+	   continuesly but this would cause unnecessary latency. 
+	   Unfortunely we can't use all the NET_RX_* feedback here. 
+	   This would turn on IM for devices that is not contributing 
+	   to backlog congestion with unnecessary latency. 
+
+	   We monitor the the device RX-ring and have:
+
+	   HW Interrupt Mitigation either ON or OFF.
+
+	   ON:  More then 1 pkt received (per intr.) OR we are dropping 
+	   OFF: Only 1 pkt received
+
+	   Note. We only use min and max (0, 15) settings from mit_table */
+
+
+	if( tp->flags &  HAS_INTR_MITIGATION) {
+		if( received > 1 ) {
+			if( ! tp->mit_on ) {
+				tp->mit_on = 1;
+				outl(mit_table[MIT_TABLE], dev->base_addr + CSR11);
+			}
+		}
+		else {
+			if( tp->mit_on ) {
+				tp->mit_on = 0;
+				outl(0, dev->base_addr + CSR11);
+			}
+		}
+	}
+
+#endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */
+
+	dev->quota -= received;
+	*budget -= received;
+
+	tulip_refill_rx(dev);
+
+	/* If RX ring is not full we are out of memory. */
+	if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
+
+	/* Remove us from polling list and enable RX intr. */
+
+	netif_rx_complete(dev);
+	outl(tulip_tbl[tp->chip_id].valid_intrs, dev->base_addr+CSR7);
+
+	/* The last op happens after poll completion. Which means the following:
+	 * 1. it can race with disabling irqs in irq handler
+	 * 2. it can race with dise/enabling irqs in other poll threads
+	 * 3. if an irq raised after beginning loop, it will be immediately
+	 *    triggered here.
+	 *
+	 * Summarizing: the logic results in some redundant irqs both
+	 * due to races in masking and due to too late acking of already
+	 * processed irqs. But it must not result in losing events.
+	 */
+
+	return 0;
+
+not_done:
+	if (!received) {
+
+		received = dev->quota; /* Not to happen */
+	}
+	dev->quota -= received;
+	*budget -= received;
+
+	if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 ||
+	tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
+	tulip_refill_rx(dev);
+
+	if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
+
+	return 1;
+
+
+oom:    /* Executed with RX ints disabled */
+
+	/* Start timer, stop polling, but do not enable rx interrupts. */
+	mod_timer(&tp->oom_timer, jiffies+1);
+
+	/* Think: timer_pending() was an explicit signature of bug.
+	 * Timer can be pending now but fired and completed
+	 * before we did netif_rx_complete(). See? We would lose it. */
+
+	/* remove ourselves from the polling list */
+	netif_rx_complete(dev);
+
+	return 0;
+}
+
+#else /* CONFIG_TULIP_NAPI */
+
+static int tulip_rx(struct net_device *dev)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	int entry = tp->cur_rx % RX_RING_SIZE;
+	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
+	int received = 0;
+
+	if (tulip_debug > 4)
+		printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
+			   tp->rx_ring[entry].status);
 	/* If we own the next entry, it is a new packet. Send it up. */
 	while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
 		s32 status = le32_to_cpu(tp->rx_ring[entry].status);
@@ -128,8 +372,8 @@ static int tulip_rx(struct net_device *dev)
 				   dev->name, entry, status);
 		if (--rx_work_limit < 0)
 			break;
-		if ((status & 0x38008300) != 0x0300) {
-			if ((status & 0x38000300) != 0x0300) {
+		if ((status & (0x38000000 | RxDescFatalErr | RxWholePkt)) != RxWholePkt) {
+			if ((status & (0x38000000 | RxWholePkt)) != RxWholePkt) {
 				/* Ingore earlier buffers. */
 				if ((status & 0xffff) != 0x7fff) {
 					if (tulip_debug > 1)
@@ -155,19 +399,13 @@ static int tulip_rx(struct net_device *dev)
 			struct sk_buff *skb;
 
 #ifndef final_version
-			if (pkt_len > 1518) {
+			if (pkt_len > 1522) {
 				printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
 					   dev->name, pkt_len, pkt_len);
-				pkt_len = 1518;
+				pkt_len = 1522;
 				tp->stats.rx_length_errors++;
 			}
 #endif
-
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-                        drop = atomic_read(&netdev_dropping);
-                        if (drop)
-                                goto throttle;
-#endif
 			/* Check if the packet is long enough to accept without copying
 			   to a minimally-sized skbuff. */
 			if (pkt_len < tulip_rx_copybreak
@@ -209,44 +447,7 @@ static int tulip_rx(struct net_device *dev)
 				tp->rx_buffers[entry].mapping = 0;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-                        mit_sel =
-#endif
 			netif_rx(skb);
-
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-                        switch (mit_sel) {
-                        case NET_RX_SUCCESS:
-                        case NET_RX_CN_LOW:
-                        case NET_RX_CN_MOD:
-                                break;
-
-                        case NET_RX_CN_HIGH:
-                                rx_work_limit -= NET_RX_CN_HIGH; /* additional*/
-                                break;
-                        case NET_RX_DROP:
-                                rx_work_limit = -1;
-                                break;
-                        default:
-                                printk("unknown feedback return code %d\n", mit_sel);
-                                break;
-                        }
-
-                        drop = atomic_read(&netdev_dropping);
-                        if (drop) {
-throttle:
-                                rx_work_limit = -1;
-                                mit_sel = NET_RX_DROP;
-
-                                if (tp->fc_bit) {
-                                        long ioaddr = dev->base_addr;
-
-                                        /* disable Rx & RxNoBuf ints. */
-                                        outl(tulip_tbl[tp->chip_id].valid_intrs&RX_A_NBF_STOP, ioaddr + CSR7);
-                                        set_bit(tp->fc_bit, &netdev_fc_xoff);
-                                }
-                        }
-#endif
 			dev->last_rx = jiffies;
 			tp->stats.rx_packets++;
 			tp->stats.rx_bytes += pkt_len;
@@ -254,44 +455,10 @@ throttle:
 		received++;
 		entry = (++tp->cur_rx) % RX_RING_SIZE;
 	}
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-
-        /* We use this simplistic scheme for IM. It's proven by
-           real life installations. We can have IM enabled
-           continuesly but this would cause unnecessary latency.
-           Unfortunely we can't use all the NET_RX_* feedback here.
-           This would turn on IM for devices that is not contributing
-           to backlog congestion with unnecessary latency.
-
-           We monitor the device RX-ring and have:
-
-           HW Interrupt Mitigation either ON or OFF.
-
-           ON:  More then 1 pkt received (per intr.) OR we are dropping
-           OFF: Only 1 pkt received
-
-           Note. We only use min and max (0, 15) settings from mit_table */
-
-
-        if( tp->flags &  HAS_INTR_MITIGATION) {
-                if((received > 1 || mit_sel == NET_RX_DROP)
-                   && tp->mit_sel != 15 ) {
-                        tp->mit_sel = 15;
-                        tp->mit_change = 1; /* Force IM change */
-                }
-                if((received <= 1 && mit_sel != NET_RX_DROP) && tp->mit_sel != 0 ) {
-                        tp->mit_sel = 0;
-                        tp->mit_change = 1; /* Force IM change */
-                }
-        }
-
-        return RX_RING_SIZE+1; /* maxrx+1 */
-#else
 	return received;
-#endif
 }
-
-static inline void phy_interrupt (struct net_device *dev)
+#endif  /* CONFIG_TULIP_NAPI */
+static inline unsigned int phy_interrupt (struct net_device *dev)
 {
 #ifdef __hppa__
 	int csr12 = inl(dev->base_addr + CSR12) & 0xff;
@@ -307,19 +474,20 @@ static inline void phy_interrupt (struct net_device *dev)
 		spin_unlock(&tp->lock);
 		/* clear irq ack bit */
 		outl(csr12 & ~0x02, dev->base_addr + CSR12);
+		return 1;
 	}
+	return 0;
 #endif
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_instance;
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 	int csr5;
-	int entry;
 	int missed;
 	int rx = 0;
 	int tx = 0;
@@ -327,35 +495,55 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 	int maxrx = RX_RING_SIZE;
 	int maxtx = TX_RING_SIZE;
 	int maxoi = TX_RING_SIZE;
+#ifdef CONFIG_TULIP_NAPI
+	int rxd = 0;
+#else
+	int entry;
+#endif
 	unsigned int work_count = tulip_max_interrupt_work;
+	unsigned int handled = 0;
 
 	/* Let's see whether the interrupt really is for us */
 	csr5 = inl(ioaddr + CSR5);
 
         if (tp->flags & HAS_PHY_IRQ)
-	        phy_interrupt (dev);
-    
+	        handled = phy_interrupt (dev);
+
 	if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
-		return;
+		return IRQ_RETVAL(handled);
+	;
 
 	tp->nir++;
 
 	do {
+
+#ifdef CONFIG_TULIP_NAPI
+		if (!rxd && (csr5 & (RxIntr | RxNoBuf))) {
+			rxd++;
+			/* Mask RX intrs and add the device to poll list. */
+			outl(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7);
+			netif_rx_schedule(dev);
+
+			if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))
+				break;
+		}
+
+		/* Acknowledge the interrupt sources we handle here ASAP
+		   the poll function does Rx and RxNoBuf acking */
+
+		outl(csr5 & 0x0001ff3f, ioaddr + CSR5);
+#else
 		/* Acknowledge all of the current interrupt sources ASAP. */
 		outl(csr5 & 0x0001ffff, ioaddr + CSR5);
 
-		if (tulip_debug > 4)
-			printk(KERN_DEBUG "%s: interrupt  csr5=%#8.8x new csr5=%#8.8x.\n",
-				   dev->name, csr5, inl(dev->base_addr + CSR5));
-
 		if (csr5 & (RxIntr | RxNoBuf)) {
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-                        if ((!tp->fc_bit) ||
-			    (!test_bit(tp->fc_bit, &netdev_fc_xoff)))
-#endif
 				rx += tulip_rx(dev);
 			tulip_refill_rx(dev);
 		}
+#endif
+		if (tulip_debug > 4)
+			printk(KERN_DEBUG "%s: interrupt  csr5=%#8.8x new csr5=%#8.8x.\n",
+				   dev->name, csr5, inl(dev->base_addr + CSR5));
 
 		if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {
 			unsigned int dirty_tx;
@@ -457,15 +645,8 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 			}
 			if (csr5 & RxDied) {		/* Missed a Rx frame. */
                                 tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-				if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) {
-					tp->stats.rx_errors++;
-					tulip_start_rxtx(tp);
-				}
-#else
 				tp->stats.rx_errors++;
 				tulip_start_rxtx(tp);
-#endif
 			}
 			/*
 			 * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this
@@ -499,32 +680,21 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 			if (tulip_debug > 2)
 				printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n",
 					   dev->name, csr5);
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-                        if (tp->fc_bit && (test_bit(tp->fc_bit, &netdev_fc_xoff)))
-                          if (net_ratelimit()) printk("BUG!! enabling interupt when FC off (timerintr.) \n");
-#endif
 			outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
 			tp->ttimer = 0;
 			oi++;
 		}
 		if (tx > maxtx || rx > maxrx || oi > maxoi) {
-			if (tulip_debug > 1)
+		/*	if (tulip_debug > 1)*/
 				printk(KERN_WARNING "%s: Too much work during an interrupt, "
-					   "csr5=0x%8.8x. (%lu) (%d,%d,%d)\n", dev->name, csr5, tp->nir, tx, rx, oi);
+					   "csr5=0x%8.8x. (%lu) (%d>%d,%d>%d,%d>%d)\n", dev->name, csr5, tp->nir, tx, maxtx,rx,maxrx, oi,maxoi);
 
                        /* Acknowledge all interrupt sources. */
                         outl(0x8001ffff, ioaddr + CSR5);
                         if (tp->flags & HAS_INTR_MITIGATION) {
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-                                if(tp->mit_change) {
-                                        outl(mit_table[tp->mit_sel], ioaddr + CSR11);
-                                        tp->mit_change = 0;
-                                }
-#else
                      /* Josip Loncaric at ICASE did extensive experimentation
 			to develop a good interrupt mitigation setting.*/
                                 outl(0x8b240000, ioaddr + CSR11);
-#endif
                         } else if (tp->chip_id == LC82C168) {
 				/* the LC82C168 doesn't have a hw timer.*/
 				outl(0x00, ioaddr + CSR7);
@@ -532,10 +702,6 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 			} else {
                           /* Mask all interrupting sources, set timer to
 				re-enable. */
-#ifndef CONFIG_NET_HW_FLOWCONTROL
-                                outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7);
-                                outl(0x0012, ioaddr + CSR11);
-#endif
                         }
 			break;
 		}
@@ -545,6 +711,20 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 			break;
 
 		csr5 = inl(ioaddr + CSR5);
+#ifdef CONFIG_TULIP_NAPI
+		if (rxd)
+		csr5 &= ~RxPollInt;
+	} while ((csr5 & (TxNoBuf |
+			  TxDied |
+			  TxIntr |
+			  TimerInt |
+			/* Abnormal intr. */
+			  RxDied |
+			  TxFIFOUnderflow |
+			  TxJabber |
+			  TPLnkFail |
+			  SytemError )) != 0);
+#else
 	} while ((csr5 & (NormalIntr|AbnormalIntr)) != 0);
 
 	tulip_refill_rx(dev);
@@ -569,7 +749,7 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 			}
 		}
 	}
-
+#endif
 	if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) {
 		tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
 	}
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index 758ae05..5929fd8 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -38,7 +38,8 @@
 # define USE_IO_OPS 1
 #endif
 
-
+//#define CONFIG_TULIP_NAPI_HW_MITIGATION
+//#define CONFIG_TULIP_NAPI
 
 struct tulip_chip_table {
 	char *chip_name;
@@ -127,6 +128,9 @@ enum pci_cfg_driver_reg {
 };
 
 
+#define RxPollInt (RxIntr|RxNoBuf|RxDied|RxJabber)
+
+
 /* The bits in the CSR5 status registers, mostly interrupt sources. */
 enum status_bits {
 	TimerInt = 0x800,
@@ -191,7 +195,7 @@ struct tulip_tx_desc {
 
 enum desc_status_bits {
 	DescOwned = 0x80000000,
-	RxDescFatalErr = 0x8000,
+	RxDescFatalErr = 0x4842,
 	RxWholePkt = 0x0300,
 };
 
@@ -264,12 +268,12 @@ enum t21143_csr6_bits {
    Making the Tx ring too large decreases the effectiveness of channel
    bonding and packet priority.
    There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	16
-#define RX_RING_SIZE	32
+#define TX_RING_SIZE	32
+#define RX_RING_SIZE	128
 
 #define MEDIA_MASK     31
 
-#define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer. */
+#define PKT_BUF_SZ		1540	/* Size of each temporary Rx buffer. */
 
 #define TULIP_MIN_CACHE_LINE	8	/* in units of 32-bit words */
 
@@ -295,7 +299,7 @@ enum t21143_csr6_bits {
 #define DESC_RING_WRAP 0x02000000
 
 
-#define EEPROM_SIZE 128 	/* 2 << EEPROM_ADDRLEN */
+#define EEPROM_SIZE 512	/* 2 << EEPROM_ADDRLEN */
 
 
 #define RUN_AT(x) (jiffies + (x))
@@ -356,17 +360,14 @@ struct tulip_private {
 	int flags;
 	struct net_device_stats stats;
 	struct timer_list timer;	/* Media selection timer. */
+	struct timer_list oom_timer;    /* Out of memory timer. */
 	u32 mc_filter[2];
 	spinlock_t lock;
 	spinlock_t mii_lock;
 	unsigned int cur_rx, cur_tx;	/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
-
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-#define RX_A_NBF_STOP 0xffffff3f /* To disable RX and RX-NOBUF ints. */
-        int fc_bit;
-        int mit_sel;
-        int mit_change; /* Signal for Interrupt Mitigtion */
+#ifdef	CONFIG_TULIP_NAPI_HW_MITIGATION
+	int mit_on;
 #endif
 	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
 	unsigned int full_duplex_lock:1;
@@ -426,8 +427,11 @@ int tulip_read_eeprom(long ioaddr, int location, int addr_len);
 /* interrupt.c */
 extern unsigned int tulip_max_interrupt_work;
 extern int tulip_rx_copybreak;
-void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 int tulip_refill_rx(struct net_device *dev);
+#ifdef CONFIG_TULIP_NAPI
+int tulip_poll(struct net_device *dev, int *budget);
+#endif
 
 /* media.c */
 int tulip_mdio_read(struct net_device *dev, int phy_id, int location);
@@ -451,6 +455,7 @@ extern int tulip_debug;
 extern const char * const medianame[];
 extern const char tulip_media_cap[];
 extern struct tulip_chip_table tulip_tbl[];
+void oom_timer(unsigned long data);
 extern u8 t21040_csr13[];
 extern u16 t21041_csr13[];
 extern u16 t21041_csr14[];
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index d63f096..b36a7bd 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -267,8 +267,12 @@ static void tulip_down(struct net_device *dev);
 static struct net_device_stats *tulip_get_stats(struct net_device *dev);
 static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
+static int tulip_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd);
+static int tulip_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd);
 
-
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void poll_tulip(struct net_device *dev);
+#endif
 
 static void tulip_set_power_state (struct tulip_private *tp,
 				   int sleep, int snooze)
@@ -499,29 +503,17 @@ media_picked:
 	   to an alternate media type. */
 	tp->timer.expires = RUN_AT(next_tick);
 	add_timer(&tp->timer);
-}
-
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-/* Enable receiver */
-void tulip_xon(struct net_device *dev)
-{
-        struct tulip_private *tp = (struct tulip_private *)dev->priv;
-
-        clear_bit(tp->fc_bit, &netdev_fc_xoff);
-        if (netif_running(dev)){
+#ifdef CONFIG_TULIP_NAPI
+	init_timer(&tp->oom_timer);
+	tp->oom_timer.data = (unsigned long)dev;
+	tp->oom_timer.function = oom_timer;
+#endif
 
-                tulip_refill_rx(dev);
-                outl(tulip_tbl[tp->chip_id].valid_intrs,  dev->base_addr+CSR7);
-        }
 }
-#endif
 
 static int
 tulip_open(struct net_device *dev)
 {
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-        struct tulip_private *tp = (struct tulip_private *)dev->priv;
-#endif
 	int retval;
 	MOD_INC_USE_COUNT;
 
@@ -534,10 +526,6 @@ tulip_open(struct net_device *dev)
 
 	tulip_up (dev);
 
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-        tp->fc_bit = netdev_register_fc(dev, tulip_xon);
-#endif
-
 	netif_start_queue (dev);
 
 	return 0;
@@ -645,10 +633,6 @@ static void tulip_tx_timeout(struct net_device *dev)
 #endif
 
 	/* Stop and restart the chip's Tx processes . */
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-        if (tp->fc_bit && test_bit(tp->fc_bit,&netdev_fc_xoff))
-                printk("BUG tx_timeout restarting rx when fc on\n");
-#endif
 	tulip_restart_rxtx(tp);
 	/* Trigger an immediate transmit demand. */
 	outl(0, ioaddr + CSR1);
@@ -808,6 +792,10 @@ static void tulip_down (struct net_device *dev)
 
 	del_timer_sync (&tp->timer);
 
+#ifdef CONFIG_TULIP_NAPI
+	del_timer_sync (&tp->oom_timer);
+#endif
+
 	spin_lock_irqsave (&tp->lock, flags);
 
 	/* Disable interrupts by clearing the interrupt mask. */
@@ -850,13 +838,6 @@ static int tulip_close (struct net_device *dev)
 
 	netif_stop_queue (dev);
 
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-        if (tp->fc_bit) {
-                int bit = tp->fc_bit;
-                tp->fc_bit = 0;
-                netdev_unregister_fc(bit);
-        }
-#endif
 	tulip_down (dev);
 
 	if (tulip_debug > 1)
@@ -917,6 +898,111 @@ static struct net_device_stats *tulip_get_stats(struct net_device *dev)
 	return &tp->stats;
 }
 
+static int tulip_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	u32 adv, lpa, bmcr;
+
+	ecmd->supported =
+		(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+		SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+		SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
+
+
+	/* only supports twisted-pair or MII */
+	if (tulip_media_cap[dev->if_port] & MediaIsMII) {
+		 ecmd->port = PORT_MII;
+	}
+	else {
+		ecmd->port = PORT_TP;
+	}
+
+	/* only supports internal transceiver */
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
+	adv = tulip_mdio_read(dev, 1, MII_ADVERTISE);
+	if (adv & ADVERTISE_10HALF)
+		ecmd->advertising |= ADVERTISED_10baseT_Half;
+	if (adv & ADVERTISE_10FULL)
+		ecmd->advertising |= ADVERTISED_10baseT_Full;
+	if (adv & ADVERTISE_100HALF)
+		ecmd->advertising |= ADVERTISED_100baseT_Half;
+	if (adv & ADVERTISE_100FULL)
+		ecmd->advertising |= ADVERTISED_100baseT_Full;
+
+
+	bmcr = tulip_mdio_read(dev, 1, MII_BMCR);
+	lpa = tulip_mdio_read(dev, 1, MII_LPA);
+
+	if (bmcr & BMCR_ANENABLE) {
+		ecmd->advertising |= ADVERTISED_Autoneg;
+		ecmd->autoneg = AUTONEG_ENABLE;
+		if (lpa & adv & LPA_100FULL) {
+			ecmd->speed = SPEED_100;
+			ecmd->duplex = DUPLEX_FULL;
+		}
+		else if (lpa & adv & LPA_100HALF) {
+			ecmd->speed = SPEED_100;
+			ecmd->duplex = DUPLEX_HALF;
+		}
+		else if (lpa & adv & LPA_10FULL) {
+			ecmd->speed = SPEED_10;
+			ecmd->duplex = DUPLEX_FULL;
+		}
+		else if (lpa & adv & LPA_10HALF) {
+			ecmd->speed = SPEED_10;
+			ecmd->duplex = DUPLEX_HALF;
+		}
+	} else {
+		ecmd->autoneg = AUTONEG_DISABLE;
+		if (bmcr & BMCR_SPEED100) {
+			ecmd->speed = SPEED_100;
+		}
+		else {
+			ecmd->speed = SPEED_10;
+		}
+		if (bmcr & BMCR_FULLDPLX) {
+			ecmd->duplex = DUPLEX_FULL;
+		}
+		else {
+			ecmd->duplex = DUPLEX_HALF;
+		}
+	}
+	return 0;
+}
+
+static int tulip_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct tulip_private *np = dev->priv;
+	u32 tmp;
+
+	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
+		return -EINVAL;
+	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
+		return -EINVAL;
+	if (ecmd->port != PORT_TP && ecmd->port != PORT_MII)
+		return -EINVAL;
+	if (ecmd->transceiver != XCVR_INTERNAL)
+		return -EINVAL;
+	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
+		return -EINVAL;
+
+	tmp = tulip_mdio_read(dev, 1, MII_BMCR);
+	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		tmp |= BMCR_ANENABLE;
+	}
+	else {
+		tmp &= ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
+		if (ecmd->speed == SPEED_100)
+			tmp |= BMCR_SPEED100;
+		if (ecmd->duplex == DUPLEX_FULL)
+			tmp |= BMCR_FULLDPLX;
+		else
+			np->full_duplex = 0;
+	}
+	tulip_mdio_write(dev, 1, MII_BMCR, tmp);
+	return 0;
+}
 
 static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
 {
@@ -936,7 +1022,34 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
 			return -EFAULT;
 		return 0;
 	}
-
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		/* LSTATUS is latched low until a read - so read twice */
+		tulip_mdio_read(dev, 1, MII_BMSR);
+		edata.data = (tulip_mdio_read(dev, 1, MII_BMSR) & BMSR_LSTATUS)? 1:0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		tulip_get_ecmd(dev, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_SSET: {
+		struct ethtool_cmd ecmd;
+		int r;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = tulip_set_ecmd(dev, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
         }
 
 	return -EOPNOTSUPP;
@@ -1729,6 +1842,10 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
 	dev->get_stats = tulip_get_stats;
 	dev->do_ioctl = private_ioctl;
 	dev->set_multicast_list = set_rx_mode;
+#ifdef CONFIG_TULIP_NAPI
+	dev->poll = tulip_poll;
+	dev->weight = 16;
+#endif
 
 	if (register_netdev(dev))
 		goto err_out_free_ring;
@@ -1902,7 +2019,6 @@ static void __devexit tulip_remove_one (struct pci_dev *pdev)
 	/* pci_power_off (pdev, -1); */
 }
 
-
 static struct pci_driver tulip_driver = {
 	name:		DRV_NAME,
 	id_table:	tulip_pci_tbl,

