bk://gkernel.bkbits.net/netdev-2.6
jgarzik@redhat.com|ChangeSet|20040517181259|44011 jgarzik

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/05/18 14:43:15-07:00 akpm@bix.(none) 
#   Merge bk://gkernel.bkbits.net/netdev-2.6
#   into bix.(none):/usr/src/bk-netdev
# 
# drivers/net/Makefile
#   2004/05/18 14:43:12-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/05/18 14:43:12-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/8139too.c
#   2004/05/18 14:43:12-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/18 14:42:19-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev
# 
# drivers/net/Makefile
#   2004/05/18 14:42:16-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/05/18 14:42:16-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/17 14:12:59-04:00 jgarzik@redhat.com 
#   Merge redhat.com:/spare/repo/netdev-2.6/r8169
#   into redhat.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/Kconfig
#   2004/05/17 14:12:56-04:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/17 14:11:35-04:00 jgarzik@redhat.com 
#   Merge redhat.com:/spare/repo/linux-2.6
#   into redhat.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/Makefile
#   2004/05/17 14:11:31-04:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/05/17 14:11:31-04:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# drivers/net/8139too.c
#   2004/05/17 14:11:31-04:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/17 14:07:14-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: janitoring
#   
#   Spring cleanup
#   - unsigned int (u32) should be slightly faster on ppc64 (Jon D Mason);
#   - misc minor de-uglyfication.
# 
# drivers/net/r8169.c
#   2004/05/14 17:08:45-04:00 romieu@fr.zoreil.com +47 -47
#   2.6.6-mm2 - r8169 janitoring
# 
# ChangeSet
#   2004/05/17 14:07:06-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: cosmetic renaming of a register
#   
#   RxUnderrun status bit renamed to LinkChg (identical to the 8139cp driver).
# 
# drivers/net/r8169.c
#   2004/05/14 17:08:47-04:00 romieu@fr.zoreil.com +5 -5
#   2.6.6-mm2 - r8169 register rename
# 
# ChangeSet
#   2004/05/17 14:06:58-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: napi support
#   
#   Napi for r8169 (Jon D Mason <jonmason@us.ibm.com>).
#   Both Tx and Rx processing are moved to the ->poll() function.
# 
# drivers/net/r8169.c
#   2004/05/14 17:07:18-04:00 romieu@fr.zoreil.com +78 -11
#   2.6.6-mm2 - r8169 napi
# 
# drivers/net/Kconfig
#   2004/05/14 17:07:18-04:00 romieu@fr.zoreil.com +5 -0
#   2.6.6-mm2 - r8169 napi
# 
# ChangeSet
#   2004/05/14 21:37:15-07:00 akpm@bix.(none) 
#   Merge bk://gkernel.bkbits.net/netdev-2.6
#   into bix.(none):/usr/src/bk-netdev
# 
# drivers/net/Makefile
#   2004/05/14 21:37:12-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/05/14 21:37:12-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/14 21:36:21-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev
# 
# drivers/net/8139too.c
#   2004/05/14 21:36:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/11 16:49:58-07:00 akpm@bix.(none) 
#   Merge bk://gkernel.bkbits.net/netdev-2.6
#   into bix.(none):/usr/src/bk-netdev
# 
# drivers/net/8139too.c
#   2004/05/11 16:49:55-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/11 16:49:05-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev
# 
# drivers/net/8139too.c
#   2004/05/11 16:49:01-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/10 21:11:08-04:00 jgarzik@redhat.com 
#   Merge redhat.com:/spare/repo/linux-2.6
#   into redhat.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/8139too.c
#   2004/05/10 21:11:04-04:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/21 23:30:47-04:00 romieu@fr.zoreil.com 
#   [PATCH] epic100: code removal in irq handler
#   
#   The loop in the irq handler is not needed any more as the high frequency
#   events have been deferred due to napi usage.
# 
# drivers/net/epic100.c
#   2004/04/19 18:37:16-04:00 romieu@fr.zoreil.com +52 -64
#   2.6.6-rc1-mm1 - code removal in the epic100 irq handler
# 
# ChangeSet
#   2004/04/21 23:30:40-04:00 romieu@fr.zoreil.com 
#   [PATCH] epic100: spin_unlock_irqrestore avoidance
#   
#   This patch avoids to duplicate a spin_unlock:
#   - it is mostly an artifact due to wild goto;
#   - it makes the generated code smaller.
# 
# drivers/net/epic100.c
#   2004/04/19 18:37:05-04:00 romieu@fr.zoreil.com +16 -10
#   2.6.6-rc1-mm1 - spin_unlock_irqrestore avoidance in epic100
# 
# ChangeSet
#   2004/04/21 08:29:19-04:00 jgarzik@redhat.com 
#   Merge redhat.com:/spare/repo/netdev-2.6/8139too
#   into redhat.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/8139too.c
#   2004/04/21 08:29:16-04:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/21 08:24:06-04:00 jgarzik@redhat.com 
#   [netdrvr e1000] Eliminate code duplicating ethtool_op_xxx helpers
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/04/21 08:24:01-04:00 jgarzik@redhat.com +4 -33
#   [netdrvr e1000] Eliminate code duplicating ethtool_op_xxx helpers
# 
# ChangeSet
#   2004/04/21 08:19:08-04:00 jgarzik@redhat.com 
#   Manual merge of e1000 upstream changes.
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/04/21 08:19:04-04:00 jgarzik@redhat.com +0 -3
#   Manual merge of e1000 upstream changes.
# 
# ChangeSet
#   2004/04/19 12:33:23-04:00 shemminger@osdl.org 
#   [PATCH] e1000 ethtool_ops support
#   
#   Okay, here is a first cut at ethtool ops integration for e1000.
#   
#   It has been touch tested for the basic operations on a card on
#   a lab machine.  Please review before including in the 2.6.6 kernel.
# 
# drivers/net/e1000/e1000_main.c
#   2004/04/16 11:50:02-04:00 shemminger@osdl.org +7 -28
#   e1000 ethtool_ops support
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/04/16 11:50:02-04:00 shemminger@osdl.org +234 -382
#   e1000 ethtool_ops support
# 
# ChangeSet
#   2004/04/06 08:01:31-04:00 hch@lst.de 
#   [PATCH] convert acenic to pci_driver API
# 
# drivers/net/acenic.c
#   2004/04/06 04:01:26-04:00 hch@lst.de +257 -313
#   [PATCH] convert acenic to pci_driver API
# 
# ChangeSet
#   2004/04/06 08:01:18-04:00 hch@lst.de 
#   [PATCH] kill acient compat cruft from acenic
#   
#   Kills lots of really old cruft and adds a little cruft to actually
#   make the driver work with recent 2.4 again.
# 
# drivers/net/acenic.c
#   2004/04/06 03:59:41-04:00 hch@lst.de +4 -225
#   [PATCH] kill acient compat cruft from acenic
#   
#   Kills lots of really old cruft and adds a little cruft to actually
#   make the driver work with recent 2.4 again.
# 
# ChangeSet
#   2004/03/25 23:52:21-05:00 romieu@fr.zoreil.com 
#   [netdrvr epic100] napi fixes
#   
#   Multiple invocation of __netif_rx_schedule() in epic_interrupt() while
#   epic_poll loops over __netif_rx_complete() leads to serious device
#   refcount leak.
# 
# drivers/net/epic100.c
#   2004/03/25 23:52:16-05:00 romieu@fr.zoreil.com +18 -15
#   [netdrvr epic100] napi fixes
#   
#   Multiple invocation of __netif_rx_schedule() in epic_interrupt() while
#   epic_poll loops over __netif_rx_complete() leads to serious device
#   refcount leak.
# 
# ChangeSet
#   2004/03/22 19:07:18-05:00 romieu@fr.zoreil.com 
#   [netdrvr epic100] napi 3/3 - transmit path
# 
# drivers/net/epic100.c
#   2004/03/22 18:18:40-05:00 romieu@fr.zoreil.com +9 -11
#   2.6.5-rc2 - epic100 napi
# 
# ChangeSet
#   2004/03/22 19:07:11-05:00 romieu@fr.zoreil.com 
#   [netdrvr epic100] napi 2/3 - receive path
# 
# drivers/net/epic100.c
#   2004/03/22 18:18:33-05:00 romieu@fr.zoreil.com +116 -21
#   2.6.5-rc2 - epic100 napi
# 
# ChangeSet
#   2004/03/22 19:07:03-05:00 romieu@fr.zoreil.com 
#   [netdrvr epic100] napi 1/3 - just shuffle some code around
#   
#   Isolate the classical TX part of epic_interrupt. Innocent code shuffling.
# 
# drivers/net/epic100.c
#   2004/03/22 16:53:18-05:00 romieu@fr.zoreil.com +76 -61
#   2.6.5-rc2 - epic100 napi
# 
# ChangeSet
#   2004/03/22 19:06:56-05:00 romieu@fr.zoreil.com 
#   [netdrvr epic100] minor cleanups
#   
#   - extra pci_disable_device() to balance invocation of pci_enable_device()
#     in epic_init_one() (-> error path + epic_remove_one());
#   - lazy return status in epic_init_one(), tsss...;
#   - memory dedicated to Rx descriptors was not freed after failure of
#     register_netdev() in epic_init_one();
#   - use of epic_pause() in epic_close() offers a small window for a late
#     interruption just before the final free_irq(). Let's close the window to
#     avoid two epic_rx() threads racing with each other.
# 
# drivers/net/epic100.c
#   2004/03/22 16:53:16-05:00 romieu@fr.zoreil.com +40 -19
#   2.6.5-rc2 - epic100 fixup
# 
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	Tue May 18 23:54:44 2004
+++ b/drivers/net/Kconfig	Tue May 18 23:54:44 2004
@@ -1987,6 +1987,11 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called r8169.  This is recommended.
 
+config R8169_NAPI
+	bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)"
+	depends on R8169 && EXPERIMENTAL 
+
+
 config SK98LIN
 	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
 	depends on PCI
diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c
--- a/drivers/net/acenic.c	Tue May 18 23:54:44 2004
+++ b/drivers/net/acenic.c	Tue May 18 23:54:44 2004
@@ -131,7 +131,6 @@
 #define PCI_DEVICE_ID_SGI_ACENIC	0x0009
 #endif
 
-#if LINUX_VERSION_CODE >= 0x20400
 static struct pci_device_id acenic_pci_tbl[] = {
 	{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE,
 	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
@@ -156,37 +155,6 @@
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
-#endif
-
-
-#ifndef MODULE_LICENSE
-#define MODULE_LICENSE(a)
-#endif
-
-#ifndef wmb
-#define wmb()	mb()
-#endif
-
-#ifndef __exit
-#define __exit
-#endif
-
-#ifndef __devinit
-#define __devinit	__init
-#endif
-
-#ifndef SMP_CACHE_BYTES
-#define SMP_CACHE_BYTES	L1_CACHE_BYTES
-#endif
-
-#ifndef SET_MODULE_OWNER
-#define SET_MODULE_OWNER(dev)		do{} while(0)
-#define ACE_MOD_INC_USE_COUNT		MOD_INC_USE_COUNT
-#define ACE_MOD_DEC_USE_COUNT		MOD_DEC_USE_COUNT
-#else
-#define ACE_MOD_INC_USE_COUNT		do{} while(0)
-#define ACE_MOD_DEC_USE_COUNT		do{} while(0)
-#endif
 
 #ifndef SET_NETDEV_DEV
 #define SET_NETDEV_DEV(net, pdev)	do{} while(0)
@@ -198,151 +166,8 @@
 #define ace_sync_irq(irq)	synchronize_irq()
 #endif
 
-#if LINUX_VERSION_CODE < 0x2051e
-#define local_irq_save(flags)		do{__save_flags(flags) ; \
-					   __cli();} while(0)
-#define local_irq_restore(flags)	__restore_flags(flags)
-#endif
-
-#if (LINUX_VERSION_CODE < 0x02030d)
-#define pci_resource_start(dev, bar)	dev->base_address[bar]
-#elif (LINUX_VERSION_CODE < 0x02032c)
-#define pci_resource_start(dev, bar)	dev->resource[bar].start
-#endif
-
-#if (LINUX_VERSION_CODE < 0x02030e)
-#define net_device device
-#endif
-
-
-#if (LINUX_VERSION_CODE < 0x02032a)
-typedef u32 dma_addr_t;
-
-static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-					 dma_addr_t *dma_handle)
-{
-	void *virt_ptr;
-
-	virt_ptr = kmalloc(size, GFP_KERNEL);
-	if (!virt_ptr)
-		return NULL;
-	*dma_handle = virt_to_bus(virt_ptr);
-	return virt_ptr;
-}
-
-#define pci_free_consistent(cookie, size, ptr, dma_ptr)	kfree(ptr)
-#define pci_map_page(cookie, page, off, size, dir)	\
-	virt_to_bus(page_address(page)+(off))
-#define pci_unmap_page(cookie, address, size, dir)
-#define pci_set_dma_mask(dev, mask)		\
-	(((u64)(mask) & 0xffffffff00000000) == 0 ? 0 : -EIO)
-#define pci_dma_supported(dev, mask)		\
-	(((u64)(mask) & 0xffffffff00000000) == 0 ? 1 : 0)
-
-#elif (LINUX_VERSION_CODE < 0x02040d)
-
-/*
- * 2.4.13 introduced pci_map_page()/pci_unmap_page() - for 2.4.12 and prior,
- * fall back on pci_map_single()/pci_unnmap_single().
- *
- * We are guaranteed that the page is mapped at this point since
- * pci_map_page() is only used upon valid struct skb's.
- */
-static inline dma_addr_t
-pci_map_page(struct pci_dev *cookie, struct page *page, unsigned long off,
-	     size_t size, int dir)
-{
-	void *page_virt;
-
-	page_virt = page_address(page);
-	if (!page_virt)
-		BUG();
-	return pci_map_single(cookie, (page_virt + off), size, dir);
-}
-#define pci_unmap_page(cookie, dma_addr, size, dir)	\
-	pci_unmap_single(cookie, dma_addr, size, dir)
-#endif
-
-#if (LINUX_VERSION_CODE < 0x020412)
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)		0
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do{} while(0)
-#define pci_unmap_len(PTR, LEN_NAME)		0
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do{} while(0)
-#endif
-
-
-#if (LINUX_VERSION_CODE < 0x02032b)
-/*
- * SoftNet
- *
- * For pre-softnet kernels we need to tell the upper layer not to
- * re-enter start_xmit() while we are in there. However softnet
- * guarantees not to enter while we are in there so there is no need
- * to do the netif_stop_queue() dance unless the transmit queue really
- * gets stuck. This should also improve performance according to tests
- * done by Aman Singla.
- */
-#define dev_kfree_skb_irq(a)			dev_kfree_skb(a)
-#define netif_wake_queue(dev)			clear_bit(0, &dev->tbusy)
-#define netif_stop_queue(dev)			set_bit(0, &dev->tbusy)
-#define late_stop_netif_stop_queue(dev)		do{} while(0)
-#define early_stop_netif_stop_queue(dev)	test_and_set_bit(0,&dev->tbusy)
-#define early_stop_netif_wake_queue(dev)	netif_wake_queue(dev)
-
-static inline void netif_start_queue(struct net_device *dev)
-{
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-}
-
-#define ace_mark_net_bh()			mark_bh(NET_BH)
-#define netif_queue_stopped(dev)		dev->tbusy
-#define netif_running(dev)			dev->start
-#define ace_if_down(dev)			do{dev->start = 0;} while(0)
-
-#define tasklet_struct				tq_struct
-static inline void tasklet_schedule(struct tasklet_struct *tasklet)
-{
-	queue_task(tasklet, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-}
-
-static inline void tasklet_init(struct tasklet_struct *tasklet,
-				void (*func)(unsigned long),
-				unsigned long data)
-{
-	tasklet->next = NULL;
-	tasklet->sync = 0;
-	tasklet->routine = (void (*)(void *))func;
-	tasklet->data = (void *)data;
-}
-#define tasklet_kill(tasklet)			do{} while(0)
-#else
-#define late_stop_netif_stop_queue(dev)		netif_stop_queue(dev)
-#define early_stop_netif_stop_queue(dev)	0
-#define early_stop_netif_wake_queue(dev)	do{} while(0)
-#define ace_mark_net_bh()			do{} while(0)
-#define ace_if_down(dev)			do{} while(0)
-#endif
-
-#if (LINUX_VERSION_CODE >= 0x02031b)
-#define NEW_NETINIT
-#define ACE_PROBE_ARG				void
-#else
-#define ACE_PROBE_ARG				struct net_device *dev
-#endif
-
-#ifndef min_t
-#define min_t(type,a,b)	(((a)<(b))?(a):(b))
-#endif
-
-#ifndef ARCH_HAS_PREFETCHW
-#ifndef prefetchw
-#define prefetchw(x)				do{} while(0)
-#endif
+#ifndef offset_in_page
+#define offset_in_page(ptr)	((unsigned long)(ptr) & ~PAGE_MASK)
 #endif
 
 #define ACE_MAX_MOD_PARMS	8
@@ -595,407 +420,323 @@
 static int tx_ratio[ACE_MAX_MOD_PARMS];
 static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
 
+MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
+MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state");
+MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level");
+MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives");
+MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait");
+MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives");
+MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait");
+MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
+
+
 static char version[] __initdata = 
   "acenic.c: v0.92 08/05/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
-static struct net_device *root_dev;
-
-static int probed __initdata = 0;
-
-
-int __devinit acenic_probe (ACE_PROBE_ARG)
+static int __devinit acenic_probe_one(struct pci_dev *pdev,
+		const struct pci_device_id *id)
 {
-#ifdef NEW_NETINIT
 	struct net_device *dev;
-#endif
 	struct ace_private *ap;
-	struct pci_dev *pdev = NULL;
-	int boards_found = 0;
-	int version_disp;
-
-	if (probed)
-		return -ENODEV;
-	probed++;
-
-	version_disp = 0;
-
-	while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET<<8, pdev))) {
-
-		if (!((pdev->vendor == PCI_VENDOR_ID_ALTEON) &&
-		      ((pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE) ||
-		       (pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_COPPER)))&&
-		    !((pdev->vendor == PCI_VENDOR_ID_3COM) &&
-		      (pdev->device == PCI_DEVICE_ID_3COM_3C985)) &&
-		    !((pdev->vendor == PCI_VENDOR_ID_NETGEAR) &&
-		      ((pdev->device == PCI_DEVICE_ID_NETGEAR_GA620) || 
-		       (pdev->device == PCI_DEVICE_ID_NETGEAR_GA620T))) &&
-		/*
-		 * Farallon used the DEC vendor ID on their cards by
-		 * mistake for a while
-		 */
-		    !((pdev->vendor == PCI_VENDOR_ID_DEC) &&
-		      (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX)) &&
-		    !((pdev->vendor == PCI_VENDOR_ID_ALTEON) &&
-		      (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T)) &&
-		    !((pdev->vendor == PCI_VENDOR_ID_SGI) &&
-		      (pdev->device == PCI_DEVICE_ID_SGI_ACENIC)))
-			continue;
-
-		dev = alloc_etherdev(sizeof(struct ace_private));
-		if (dev == NULL) {
-			printk(KERN_ERR "acenic: Unable to allocate "
-			       "net_device structure!\n");
-			break;
-		}
+	static int boards_found;
 
-		SET_MODULE_OWNER(dev);
-		SET_NETDEV_DEV(dev, &pdev->dev);
+	dev = alloc_etherdev(sizeof(struct ace_private));
+	if (dev == NULL) {
+		printk(KERN_ERR "acenic: Unable to allocate "
+		       "net_device structure!\n");
+		return -ENOMEM;
+	}
+
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
-		ap = dev->priv;
-		ap->pdev = pdev;
+	ap = dev->priv;
+	ap->pdev = pdev;
 
-		dev->open = &ace_open;
-		dev->hard_start_xmit = &ace_start_xmit;
-		dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
 #if ACENIC_DO_VLAN
-		dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-		dev->vlan_rx_register = ace_vlan_rx_register;
-		dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid;
-#endif
-		if (1) {
-			static void ace_watchdog(struct net_device *dev);
-			dev->tx_timeout = &ace_watchdog;
-			dev->watchdog_timeo = 5*HZ;
-		}
-		dev->stop = &ace_close;
-		dev->get_stats = &ace_get_stats;
-		dev->set_multicast_list = &ace_set_multicast_list;
-		dev->do_ioctl = &ace_ioctl;
-		dev->set_mac_address = &ace_set_mac_addr;
-		dev->change_mtu = &ace_change_mtu;
+	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	dev->vlan_rx_register = ace_vlan_rx_register;
+	dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid;
+#endif
+	if (1) {
+		static void ace_watchdog(struct net_device *dev);
+		dev->tx_timeout = &ace_watchdog;
+		dev->watchdog_timeo = 5*HZ;
+	}
 
-		/* display version info if adapter is found */
-		if (!version_disp)
-		{
-			/* set display flag to TRUE so that */
-			/* we only display this string ONCE */
-			version_disp = 1;
-			printk(version);
-		}
+	dev->open = &ace_open;
+	dev->stop = &ace_close;
+	dev->hard_start_xmit = &ace_start_xmit;
+	dev->get_stats = &ace_get_stats;
+	dev->set_multicast_list = &ace_set_multicast_list;
+	dev->do_ioctl = &ace_ioctl;
+	dev->set_mac_address = &ace_set_mac_addr;
+	dev->change_mtu = &ace_change_mtu;
 
-		if (pci_enable_device(pdev)) {
-			free_netdev(dev);
-			continue;
-		}
+	/* we only display this string ONCE */
+	if (!boards_found)
+		printk(version);
 
-		/*
-		 * Enable master mode before we start playing with the
-		 * pci_command word since pci_set_master() will modify
-		 * it.
-		 */
-		pci_set_master(pdev);
+	if (pci_enable_device(pdev))
+		goto fail_free_netdev;
 
-		pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);
+	/*
+	 * Enable master mode before we start playing with the
+	 * pci_command word since pci_set_master() will modify
+	 * it.
+	 */
+	pci_set_master(pdev);
 
-		/* OpenFirmware on Mac's does not set this - DOH.. */ 
-		if (!(ap->pci_command & PCI_COMMAND_MEMORY)) {
-			printk(KERN_INFO "%s: Enabling PCI Memory Mapped "
-			       "access - was not enabled by BIOS/Firmware\n",
-			       dev->name);
-			ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY;
-			pci_write_config_word(ap->pdev, PCI_COMMAND,
-					      ap->pci_command);
-			wmb();
-		}
+	pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);
 
-		pci_read_config_byte(pdev, PCI_LATENCY_TIMER,
-				     &ap->pci_latency);
-		if (ap->pci_latency <= 0x40) {
-			ap->pci_latency = 0x40;
-			pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
-					      ap->pci_latency);
-		}
+	/* OpenFirmware on Mac's does not set this - DOH.. */ 
+	if (!(ap->pci_command & PCI_COMMAND_MEMORY)) {
+		printk(KERN_INFO "%s: Enabling PCI Memory Mapped "
+		       "access - was not enabled by BIOS/Firmware\n",
+		       dev->name);
+		ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY;
+		pci_write_config_word(ap->pdev, PCI_COMMAND,
+				      ap->pci_command);
+		wmb();
+	}
 
-		/*
-		 * Remap the regs into kernel space - this is abuse of
-		 * dev->base_addr since it was means for I/O port
-		 * addresses but who gives a damn.
-		 */
-		dev->base_addr = pci_resource_start(pdev, 0);
-		ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000);
-		if (!ap->regs) {
-			printk(KERN_ERR "%s:  Unable to map I/O register, "
-			       "AceNIC %i will be disabled.\n",
-			       dev->name, boards_found);
-			break;
-		}
+	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &ap->pci_latency);
+	if (ap->pci_latency <= 0x40) {
+		ap->pci_latency = 0x40;
+		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ap->pci_latency);
+	}
 
-		switch(pdev->vendor) {
-		case PCI_VENDOR_ID_ALTEON:
-			if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {
-				strncpy(ap->name, "Farallon PN9100-T "
-					"Gigabit Ethernet", sizeof (ap->name));
-				printk(KERN_INFO "%s: Farallon PN9100-T ",
-				       dev->name);
-			} else {
-				strncpy(ap->name, "AceNIC Gigabit Ethernet",
-					sizeof (ap->name));
-				printk(KERN_INFO "%s: Alteon AceNIC ",
-				       dev->name);
-			}
-			break;
-		case PCI_VENDOR_ID_3COM:
-			strncpy(ap->name, "3Com 3C985 Gigabit Ethernet",
-				sizeof (ap->name));
-			printk(KERN_INFO "%s: 3Com 3C985 ", dev->name);
-			break;
-		case PCI_VENDOR_ID_NETGEAR:
-			strncpy(ap->name, "NetGear GA620 Gigabit Ethernet",
-				sizeof (ap->name));
-			printk(KERN_INFO "%s: NetGear GA620 ", dev->name);
-			break;
-		case PCI_VENDOR_ID_DEC:
-			if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) {
-				strncpy(ap->name, "Farallon PN9000-SX "
-					"Gigabit Ethernet", sizeof (ap->name));
-				printk(KERN_INFO "%s: Farallon PN9000-SX ",
-				       dev->name);
-				break;
-			}
-		case PCI_VENDOR_ID_SGI:
-			strncpy(ap->name, "SGI AceNIC Gigabit Ethernet",
+	/*
+	 * Remap the regs into kernel space - this is abuse of
+	 * dev->base_addr since it was means for I/O port
+	 * addresses but who gives a damn.
+	 */
+	dev->base_addr = pci_resource_start(pdev, 0);
+	ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000);
+	if (!ap->regs) {
+		printk(KERN_ERR "%s:  Unable to map I/O register, "
+		       "AceNIC %i will be disabled.\n",
+		       dev->name, boards_found);
+		goto fail_free_netdev;
+	}
+
+	switch(pdev->vendor) {
+	case PCI_VENDOR_ID_ALTEON:
+		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {
+			strncpy(ap->name, "Farallon PN9100-T "
+				"Gigabit Ethernet", sizeof (ap->name));
+			printk(KERN_INFO "%s: Farallon PN9100-T ",
+			       dev->name);
+		} else {
+			strncpy(ap->name, "AceNIC Gigabit Ethernet",
 				sizeof (ap->name));
-			printk(KERN_INFO "%s: SGI AceNIC ", dev->name);
-			break;
-		default:
- 			strncpy(ap->name, "Unknown AceNIC based Gigabit "
-				"Ethernet", sizeof (ap->name));
-			printk(KERN_INFO "%s: Unknown AceNIC ", dev->name);
+			printk(KERN_INFO "%s: Alteon AceNIC ",
+			       dev->name);
+		}
+		break;
+	case PCI_VENDOR_ID_3COM:
+		strncpy(ap->name, "3Com 3C985 Gigabit Ethernet",
+			sizeof (ap->name));
+		printk(KERN_INFO "%s: 3Com 3C985 ", dev->name);
+		break;
+	case PCI_VENDOR_ID_NETGEAR:
+		strncpy(ap->name, "NetGear GA620 Gigabit Ethernet",
+			sizeof (ap->name));
+		printk(KERN_INFO "%s: NetGear GA620 ", dev->name);
+		break;
+	case PCI_VENDOR_ID_DEC:
+		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) {
+			strncpy(ap->name, "Farallon PN9000-SX "
+				"Gigabit Ethernet", sizeof (ap->name));
+			printk(KERN_INFO "%s: Farallon PN9000-SX ",
+			       dev->name);
 			break;
 		}
-		ap->name [sizeof (ap->name) - 1] = '\0';
-		printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);
+	case PCI_VENDOR_ID_SGI:
+		strncpy(ap->name, "SGI AceNIC Gigabit Ethernet",
+			sizeof (ap->name));
+		printk(KERN_INFO "%s: SGI AceNIC ", dev->name);
+		break;
+	default:
+ 		strncpy(ap->name, "Unknown AceNIC based Gigabit "
+			"Ethernet", sizeof (ap->name));
+		printk(KERN_INFO "%s: Unknown AceNIC ", dev->name);
+		break;
+	}
+
+	ap->name [sizeof (ap->name) - 1] = '\0';
+	printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);
 #ifdef __sparc__
-		printk("irq %s\n", __irq_itoa(pdev->irq));
+	printk("irq %s\n", __irq_itoa(pdev->irq));
 #else
-		printk("irq %i\n", pdev->irq);
+	printk("irq %i\n", pdev->irq);
 #endif
 
 #ifdef CONFIG_ACENIC_OMIT_TIGON_I
-		if ((readl(&ap->regs->HostCtrl) >> 28) == 4) {
-			printk(KERN_ERR "%s: Driver compiled without Tigon I"
-			       " support - NIC disabled\n", dev->name);
-			ace_init_cleanup(dev);
-			free_netdev(dev);
-			continue;
-		}
+	if ((readl(&ap->regs->HostCtrl) >> 28) == 4) {
+		printk(KERN_ERR "%s: Driver compiled without Tigon I"
+		       " support - NIC disabled\n", dev->name);
+		goto fail_uninit;
+	}
 #endif
 
-		if (ace_allocate_descriptors(dev)) {
-			/*
-			 * ace_allocate_descriptors() calls
-			 * ace_init_cleanup() on error.
-			 */
-			free_netdev(dev);
-			continue;
-		}
+	if (ace_allocate_descriptors(dev))
+		goto fail_free_netdev;
 
 #ifdef MODULE
-		if (boards_found >= ACE_MAX_MOD_PARMS)
-			ap->board_idx = BOARD_IDX_OVERFLOW;
-		else
-			ap->board_idx = boards_found;
+	if (boards_found >= ACE_MAX_MOD_PARMS)
+		ap->board_idx = BOARD_IDX_OVERFLOW;
+	else
+		ap->board_idx = boards_found;
 #else
-		ap->board_idx = BOARD_IDX_STATIC;
+	ap->board_idx = BOARD_IDX_STATIC;
 #endif
 
-		if (ace_init(dev)) {
-			/*
-			 * ace_init() calls ace_init_cleanup() on error.
-			 */
-			free_netdev(dev);
-			continue;
-		}
+	if (ace_init(dev))
+		goto fail_free_netdev;
 
-		if (register_netdev(dev)) {
-			printk(KERN_ERR "acenic: device registration failed\n");
-			ace_init_cleanup(dev);
-			free_netdev(dev);
-			continue;
-		}
-
-		if (ap->pci_using_dac)
-			dev->features |= NETIF_F_HIGHDMA;
-
-		boards_found++;
+	if (register_netdev(dev)) {
+		printk(KERN_ERR "acenic: device registration failed\n");
+		goto fail_uninit;
 	}
 
-	/*
-	 * If we're at this point we're going through ace_probe() for
-	 * the first time.  Return success (0) if we've initialized 1
-	 * or more boards. Otherwise, return failure (-ENODEV).
-	 */
-
-	if (boards_found > 0)
-		return 0;
-	else
-		return -ENODEV;
-}
+	if (ap->pci_using_dac)
+		dev->features |= NETIF_F_HIGHDMA;
 
+	pci_set_drvdata(pdev, dev);
 
-#ifdef MODULE
-MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
-MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state");
-MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level");
-MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives");
-MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait");
-MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives");
-MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait");
-MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
-#endif
+	boards_found++;
+	return 0;
 
+ fail_uninit:
+	ace_init_cleanup(dev);
+ fail_free_netdev:
+	free_netdev(dev);
+	return -ENODEV;
+}
 
-static void __exit ace_module_cleanup(void)
+static void __devexit acenic_remove_one(struct pci_dev *pdev)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
-	struct net_device *next;
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct ace_private *ap = dev->priv;
+	struct ace_regs *regs = ap->regs;
 	short i;
 
-	while (root_dev) {
-		ap = root_dev->priv;
-		next = ap->next;
-		unregister_netdev(root_dev);
-
-		regs = ap->regs;
+	unregister_netdev(dev);
 
-		writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
-		if (ap->version >= 2)
-			writel(readl(&regs->CpuBCtrl) | CPU_HALT,
-			       &regs->CpuBCtrl);
-		/*
-		 * This clears any pending interrupts
-		 */
-		writel(1, &regs->Mb0Lo);
-		readl(&regs->CpuCtrl);	/* flush */
+	writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
+	if (ap->version >= 2)
+		writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
+	
+	/*
+	 * This clears any pending interrupts
+	 */
+	writel(1, &regs->Mb0Lo);
+	readl(&regs->CpuCtrl);	/* flush */
 
-		/*
-		 * Make sure no other CPUs are processing interrupts
-		 * on the card before the buffers are being released.
-		 * Otherwise one might experience some `interesting'
-		 * effects.
-		 *
-		 * Then release the RX buffers - jumbo buffers were
-		 * already released in ace_close().
-		 */
-		ace_sync_irq(root_dev->irq);
+	/*
+	 * Make sure no other CPUs are processing interrupts
+	 * on the card before the buffers are being released.
+	 * Otherwise one might experience some `interesting'
+	 * effects.
+	 *
+	 * Then release the RX buffers - jumbo buffers were
+	 * already released in ace_close().
+	 */
+	ace_sync_irq(dev->irq);
 
-		for (i = 0; i < RX_STD_RING_ENTRIES; i++) {
-			struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb;
+	for (i = 0; i < RX_STD_RING_ENTRIES; i++) {
+		struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb;
 
-			if (skb) {
-				struct ring_info *ringp;
-				dma_addr_t mapping;
+		if (skb) {
+			struct ring_info *ringp;
+			dma_addr_t mapping;
 
-				ringp = &ap->skb->rx_std_skbuff[i];
-				mapping = pci_unmap_addr(ringp, mapping);
-				pci_unmap_page(ap->pdev, mapping,
-					       ACE_STD_BUFSIZE - (2 + 16),
-					       PCI_DMA_FROMDEVICE);
+			ringp = &ap->skb->rx_std_skbuff[i];
+			mapping = pci_unmap_addr(ringp, mapping);
+			pci_unmap_page(ap->pdev, mapping,
+				       ACE_STD_BUFSIZE - (2 + 16),
+				       PCI_DMA_FROMDEVICE);
 
-				ap->rx_std_ring[i].size = 0;
-				ap->skb->rx_std_skbuff[i].skb = NULL;
-				dev_kfree_skb(skb);
-			}
-		}
-		if (ap->version >= 2) {
-			for (i = 0; i < RX_MINI_RING_ENTRIES; i++) {
-				struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb;
-
-				if (skb) {
-					struct ring_info *ringp;
-					dma_addr_t mapping;
-
-					ringp = &ap->skb->rx_mini_skbuff[i];
-					mapping = pci_unmap_addr(ringp,mapping);
-					pci_unmap_page(ap->pdev, mapping,
-						       ACE_MINI_BUFSIZE - (2 + 16),
-						       PCI_DMA_FROMDEVICE);
-
-					ap->rx_mini_ring[i].size = 0;
-					ap->skb->rx_mini_skbuff[i].skb = NULL;
-					dev_kfree_skb(skb);
-				}
-			}
+			ap->rx_std_ring[i].size = 0;
+			ap->skb->rx_std_skbuff[i].skb = NULL;
+			dev_kfree_skb(skb);
 		}
-		for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
-			struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb;
+	}
+
+	if (ap->version >= 2) {
+		for (i = 0; i < RX_MINI_RING_ENTRIES; i++) {
+			struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb;
+
 			if (skb) {
 				struct ring_info *ringp;
 				dma_addr_t mapping;
 
-				ringp = &ap->skb->rx_jumbo_skbuff[i];
-				mapping = pci_unmap_addr(ringp, mapping);
+				ringp = &ap->skb->rx_mini_skbuff[i];
+				mapping = pci_unmap_addr(ringp,mapping);
 				pci_unmap_page(ap->pdev, mapping,
-					       ACE_JUMBO_BUFSIZE - (2 + 16),
+					       ACE_MINI_BUFSIZE - (2 + 16),
 					       PCI_DMA_FROMDEVICE);
 
-				ap->rx_jumbo_ring[i].size = 0;
-				ap->skb->rx_jumbo_skbuff[i].skb = NULL;
+				ap->rx_mini_ring[i].size = 0;
+				ap->skb->rx_mini_skbuff[i].skb = NULL;
 				dev_kfree_skb(skb);
 			}
 		}
-
-		ace_init_cleanup(root_dev);
-		free_netdev(root_dev);
-		root_dev = next;
 	}
-}
 
+	for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
+		struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb;
+		if (skb) {
+			struct ring_info *ringp;
+			dma_addr_t mapping;
 
-int __init ace_module_init(void)
-{
-	int status;
+			ringp = &ap->skb->rx_jumbo_skbuff[i];
+			mapping = pci_unmap_addr(ringp, mapping);
+			pci_unmap_page(ap->pdev, mapping,
+				       ACE_JUMBO_BUFSIZE - (2 + 16),
+				       PCI_DMA_FROMDEVICE);
 
-	root_dev = NULL;
+			ap->rx_jumbo_ring[i].size = 0;
+			ap->skb->rx_jumbo_skbuff[i].skb = NULL;
+			dev_kfree_skb(skb);
+		}
+	}
 
-#ifdef NEW_NETINIT
-	status = acenic_probe();
-#else
-	status = acenic_probe(NULL);
-#endif
-	return status;
+	ace_init_cleanup(dev);
+	free_netdev(dev);
 }
 
+static struct pci_driver acenic_pci_driver = {
+	.name		= "acenic",
+	.id_table	= acenic_pci_tbl,
+	.probe		= acenic_probe_one,
+	.remove		= __devexit_p(acenic_remove_one),
+};
 
-#if (LINUX_VERSION_CODE < 0x02032a)
-#ifdef MODULE
-int init_module(void)
+static int __init acenic_init(void)
 {
-	return ace_module_init();
+	return pci_module_init(&acenic_pci_driver);
 }
 
-
-void cleanup_module(void)
+static void __exit acenic_exit(void)
 {
-	ace_module_cleanup();
+	pci_unregister_driver(&acenic_pci_driver);
 }
-#endif
-#else
-module_init(ace_module_init);
-module_exit(ace_module_cleanup);
-#endif
 
+module_init(acenic_init);
+module_exit(acenic_exit);
 
 static void ace_free_descriptors(struct net_device *dev)
 {
@@ -1462,13 +1203,6 @@
 	} else
 		dev->irq = pdev->irq;
 
-	/*
-	 * Register the device here to be able to catch allocated
-	 * interrupt handlers in case the firmware doesn't come up.
-	 */
-	ap->next = root_dev;
-	root_dev = dev;
-
 #ifdef INDEX_DEBUG
 	spin_lock_init(&ap->debug_lock);
 	ap->last_tx = ACE_TX_RING_ENTRIES(ap) - 1;
@@ -2642,8 +2376,6 @@
 
 	netif_start_queue(dev);
 
-	ACE_MOD_INC_USE_COUNT;
-
 	/*
 	 * Setup the bottom half rx ring refill handler
 	 */
@@ -2660,8 +2392,6 @@
 	unsigned long flags;
 	short i;
 
-	ace_if_down(dev);
-
 	/*
 	 * Without (or before) releasing irq and stopping hardware, this
 	 * is an absolute non-sense, by the way. It will be reset instantly
@@ -2733,7 +2463,6 @@
 	ace_unmask_irq(dev);
 	local_irq_restore(flags);
 
-	ACE_MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -2789,12 +2518,6 @@
 	struct ace_regs *regs = ap->regs;
 	struct tx_desc *desc;
 	u32 idx, flagsize;
-
- 	/*
-	 * This only happens with pre-softnet, ie. 2.2.x kernels.
- 	 */
-	if (early_stop_netif_stop_queue(dev))
- 		return 1;
 
 restart:
 	idx = ap->tx_prd;
diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- a/drivers/net/e1000/e1000_ethtool.c	Tue May 18 23:54:44 2004
+++ b/drivers/net/e1000/e1000_ethtool.c	Tue May 18 23:54:44 2004
@@ -53,7 +53,7 @@
 
 #define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \
 		      offsetof(struct e1000_adapter, m)
-static struct e1000_stats e1000_gstrings_stats[] = {
+static const struct e1000_stats e1000_gstrings_stats[] = {
 	{ "rx_packets", E1000_STAT(net_stats.rx_packets) },
 	{ "tx_packets", E1000_STAT(net_stats.tx_packets) },
 	{ "rx_bytes", E1000_STAT(net_stats.rx_bytes) },
@@ -100,9 +100,10 @@
 };
 #define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN
 
-static void
-e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
+static int
+e1000_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
+	struct e1000_adapter *adapter = netdev_priv(dev);
 	struct e1000_hw *hw = &adapter->hw;
 
 	if(hw->media_type == e1000_media_type_copper) {
@@ -169,11 +170,13 @@
 	}
 
 	ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+	return 0;
 }
 
 static int
-e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
+e1000_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
+	struct e1000_adapter *adapter = netdev_priv(dev);
 	struct e1000_hw *hw = &adapter->hw;
 
 	if(ecmd->autoneg == AUTONEG_ENABLE) {
@@ -195,10 +198,11 @@
 	return 0;
 }
 
-static int
-e1000_ethtool_gpause(struct e1000_adapter *adapter,
+static void
+e1000_get_pauseparam(struct net_device *netdev,
                      struct ethtool_pauseparam *epause)
 {
+	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	
 	epause->autoneg = 
@@ -212,14 +216,13 @@
 		epause->rx_pause = 1;
 		epause->tx_pause = 1;
 	}
-	
-	return 0;
 }
 
 static int
-e1000_ethtool_spause(struct e1000_adapter *adapter,
+e1000_set_pauseparam(struct net_device *netdev,
                      struct ethtool_pauseparam *epause)
 {
+	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	
 	adapter->fc_autoneg = epause->autoneg;
@@ -248,28 +251,95 @@
 	return 0;
 }
 
+static u32
+e1000_get_rx_csum(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	return adapter->rx_csum;
+}
+
+static int
+e1000_set_rx_csum(struct net_device *netdev, u32 data)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
+	adapter->rx_csum = data;
+	if(netif_running(netdev)) {
+		e1000_down(adapter);
+		e1000_up(adapter);
+	} else
+		e1000_reset(adapter);
+	return 0;
+}
+
+static u32
+e1000_get_tx_csum(struct net_device *netdev)
+{
+	return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static int
+e1000_set_tx_csum(struct net_device *netdev, u32 data)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
+	if(adapter->hw.mac_type < e1000_82543)
+		return data ? -EINVAL : 0;
+
+	if (data)
+		netdev->features |= NETIF_F_HW_CSUM;
+	else
+		netdev->features &= ~NETIF_F_HW_CSUM;
+	return 0;
+}
+
+static int
+e1000_set_tso(struct net_device *netdev, u32 data)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
+	if (adapter->hw.mac_type < e1000_82544 ||
+	     adapter->hw.mac_type == e1000_82547)
+		return data ? -EINVAL : 0;
+		
+	if (data)
+		netdev->features |= NETIF_F_TSO;
+	else
+		netdev->features &= ~NETIF_F_TSO;
+	return 0;
+}
+
+
 static void
-e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
-                       struct ethtool_drvinfo *drvinfo)
+e1000_get_drvinfo(struct net_device *dev, 
+		  struct ethtool_drvinfo *drvinfo)
 {
+	struct e1000_adapter *adapter = netdev_priv(dev);
+
 	strncpy(drvinfo->driver,  e1000_driver_name, 32);
 	strncpy(drvinfo->version, e1000_driver_version, 32);
 	strncpy(drvinfo->fw_version, "N/A", 32);
 	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
-	drvinfo->n_stats = E1000_STATS_LEN;
-	drvinfo->testinfo_len = E1000_TEST_LEN;
+}
+
+static int
+e1000_get_regs_len(struct net_device *dev)
+{
 #define E1000_REGS_LEN 32
-	drvinfo->regdump_len  = E1000_REGS_LEN * sizeof(uint32_t);
-	drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2;
+	return E1000_REGS_LEN * sizeof(uint32_t);
 }
 
 static void
-e1000_ethtool_gregs(struct e1000_adapter *adapter,
-                    struct ethtool_regs *regs, uint32_t *regs_buff)
+e1000_get_regs(struct net_device *dev,
+	       struct ethtool_regs *regs, void *p)
 {
+	struct e1000_adapter *adapter = netdev_priv(dev);
 	struct e1000_hw *hw = &adapter->hw;
+	u32 *regs_buff = p;
 	uint16_t phy_data;
 
+	memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t));
+
 	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
 
 	regs_buff[0]  = E1000_READ_REG(hw, CTRL);
@@ -342,30 +412,36 @@
 	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
 	regs_buff[24] = (uint32_t)phy_data;  /* phy local receiver status */
 	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
+}
 
-	return;
+static int
+e1000_get_eeprom_len(struct net_device *dev)
+{
+	struct e1000_adapter *adapter = netdev_priv(dev);
+
+	return adapter->hw.eeprom.word_size * 2;
 }
 
 static int
-e1000_ethtool_geeprom(struct e1000_adapter *adapter,
-                      struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
+e1000_get_eeprom(struct net_device *dev,
+		 struct ethtool_eeprom *eeprom, u8 *bytes)
 {
+	struct e1000_adapter *adapter = netdev_priv(dev);
 	struct e1000_hw *hw = &adapter->hw;
+	uint16_t *eeprom_buff = (uint16_t *) bytes;
 	int first_word, last_word;
 	int ret_val = 0;
 	uint16_t i;
 
-	if(eeprom->len == 0) {
-		ret_val = -EINVAL;
-		goto geeprom_error;
-	}
+	if(eeprom->len == 0) 
+		return  -EINVAL;
 
 	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
 
-	if(eeprom->offset > eeprom->offset + eeprom->len) {
-		ret_val = -EINVAL;
-		goto geeprom_error;
-	}
+	if(eeprom->offset > eeprom->offset + eeprom->len) 
+		return -EINVAL;
+
+	memset(bytes, 0, adapter->hw.eeprom.word_size*2);
 
 	if((eeprom->offset + eeprom->len) > (hw->eeprom.word_size * 2))
 		eeprom->len = ((hw->eeprom.word_size * 2) - eeprom->offset);
@@ -388,14 +464,14 @@
 	for (i = 0; i < last_word - first_word + 1; i++)
 		le16_to_cpus(&eeprom_buff[i]);
 
-geeprom_error:
 	return ret_val;
 }
 
 static int
-e1000_ethtool_seeprom(struct e1000_adapter *adapter,
-                      struct ethtool_eeprom *eeprom, void *user_data)
+e1000_set_eeprom(struct net_device *netdev,
+		 struct ethtool_eeprom *eeprom, u8 *bytes)
 {
+	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	uint16_t *eeprom_buff;
 	void *ptr;
@@ -439,11 +515,7 @@
 	for (i = 0; i < last_word - first_word + 1; i++)
 		le16_to_cpus(&eeprom_buff[i]);
 
-	if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) {
-		ret_val = -EFAULT;
-		goto seeprom_error;
-	}
-
+	memcpy(ptr, bytes, eeprom->len);
 	for (i = 0; i < last_word - first_word + 1; i++)
 		eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
 
@@ -454,15 +526,15 @@
 	if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
 		e1000_update_eeprom_checksum(hw);
 
-seeprom_error:
 	kfree(eeprom_buff);
 	return ret_val;
 }
 
-static int
-e1000_ethtool_gring(struct e1000_adapter *adapter,
+static void
+e1000_get_ringparam(struct net_device *netdev,
                     struct ethtool_ringparam *ring)
 {
+	struct e1000_adapter *adapter = netdev_priv(netdev);
 	e1000_mac_type mac_type = adapter->hw.mac_type;
 	struct e1000_desc_ring *txdr = &adapter->tx_ring;
 	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
@@ -477,13 +549,12 @@
 	ring->tx_pending = txdr->count;
 	ring->rx_mini_pending = 0;
 	ring->rx_jumbo_pending = 0;
-
-	return 0;
 }
+
 static int 
-e1000_ethtool_sring(struct e1000_adapter *adapter,
-                    struct ethtool_ringparam *ring)
+e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
 {
+	struct e1000_adapter *adapter = netdev_priv(netdev);
 	int err;
 	e1000_mac_type mac_type = adapter->hw.mac_type;
 	struct e1000_desc_ring *txdr = &adapter->tx_ring;
@@ -806,8 +877,6 @@
 		kfree(txdr->buffer_info);
 	if(rxdr->buffer_info)
 		kfree(rxdr->buffer_info);
-
-	return;
 }
 
 static int
@@ -939,8 +1008,6 @@
 	e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC);
 	e1000_write_phy_reg(&adapter->hw, 29, 0x001A);
 	e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0);
-
-	return;
 }
 
 static void
@@ -1257,11 +1324,19 @@
 	return *data;
 }
 
+
 static int
-e1000_ethtool_test(struct e1000_adapter *adapter,
-		   struct ethtool_test *eth_test, uint64_t *data)
+e1000_diag_test_count(struct net_device *dev)
 {
-	boolean_t if_running = netif_running(adapter->netdev);
+	return E1000_TEST_LEN;
+}
+
+static void 
+e1000_diag_test(struct net_device *netdev,
+		struct ethtool_test *eth_test, u64 *data)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	boolean_t if_running = netif_running(netdev);
 
 	if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
 		/* Offline tests */
@@ -1305,12 +1380,12 @@
 		data[2] = 0;
 		data[3] = 0;
 	}
-	return 0;
 }
 
 static void
-e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
+e1000_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
+	struct e1000_adapter *adapter = netdev_priv(dev);
 	struct e1000_hw *hw = &adapter->hw;
 
 	switch(adapter->hw.device_id) {
@@ -1348,10 +1423,10 @@
 		return;
 	}
 }
-
 static int
-e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
+e1000_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
+	struct e1000_adapter *adapter = netdev_priv(dev);
 	struct e1000_hw *hw = &adapter->hw;
 
 	switch(adapter->hw.device_id) {
@@ -1408,8 +1483,13 @@
 }
 
 static int
-e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id)
+e1000_phys_id(struct net_device *netdev, u32 data)
 {
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
+	if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+
 	if(!adapter->blink_timer.function) {
 		init_timer(&adapter->blink_timer);
 		adapter->blink_timer.function = e1000_led_blink_callback;
@@ -1420,11 +1500,7 @@
 	mod_timer(&adapter->blink_timer, jiffies);
 
 	set_current_state(TASK_INTERRUPTIBLE);
-	if(id->data)
-		schedule_timeout(id->data * HZ);
-	else
-		schedule_timeout(MAX_SCHEDULE_TIMEOUT);
-
+	schedule_timeout(data * HZ);
 	del_timer_sync(&adapter->blink_timer);
 	e1000_led_off(&adapter->hw);
 	clear_bit(E1000_LED_ON, &adapter->led_status);
@@ -1433,345 +1509,89 @@
 	return 0;
 }
 
-int
-e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
+static int
+e1000_nway_reset(struct net_device *netdev)
 {
-	struct e1000_adapter *adapter = netdev->priv;
-	void *addr = ifr->ifr_data;
-	uint32_t cmd;
-
-	if(get_user(cmd, (uint32_t *) addr))
-		return -EFAULT;
-
-	switch(cmd) {
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = {ETHTOOL_GSET};
-		e1000_ethtool_gset(adapter, &ecmd);
-		if(copy_to_user(addr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SSET: {
-		struct ethtool_cmd ecmd;
-		if(copy_from_user(&ecmd, addr, sizeof(ecmd)))
-			return -EFAULT;
-		return e1000_ethtool_sset(adapter, &ecmd);
-	}
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo drvinfo = {ETHTOOL_GDRVINFO};
-		e1000_ethtool_gdrvinfo(adapter, &drvinfo);
-		if(copy_to_user(addr, &drvinfo, sizeof(drvinfo)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GSTRINGS: {
-		struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS };
-		char *strings = NULL;
-		int err = 0;
-
-		if(copy_from_user(&gstrings, addr, sizeof(gstrings)))
-			return -EFAULT;
-		switch(gstrings.string_set) {
-		case ETH_SS_TEST:
-			gstrings.len = E1000_TEST_LEN;
-			strings = kmalloc(E1000_TEST_LEN * ETH_GSTRING_LEN,
-					  GFP_KERNEL);
-			if(!strings)
-				return -ENOMEM;
-			memcpy(strings, e1000_gstrings_test, E1000_TEST_LEN *
-			       ETH_GSTRING_LEN);
-			break;
-		case ETH_SS_STATS: {
-			int i;
-			gstrings.len = E1000_STATS_LEN;
-			strings = kmalloc(E1000_STATS_LEN * ETH_GSTRING_LEN,
-					  GFP_KERNEL);
-			if(!strings)
-				return -ENOMEM;
-			for(i=0; i < E1000_STATS_LEN; i++) {
-				memcpy(&strings[i * ETH_GSTRING_LEN],
-				       e1000_gstrings_stats[i].stat_string,
-				       ETH_GSTRING_LEN);
-			}
-			break;
-		}
-		default:
-			return -EOPNOTSUPP;
-		}
-		if(copy_to_user(addr, &gstrings, sizeof(gstrings)))
-			err = -EFAULT;
-		addr += offsetof(struct ethtool_gstrings, data);
-		if(!err && copy_to_user(addr, strings,
-		   gstrings.len * ETH_GSTRING_LEN))
-			err = -EFAULT;
-
-		kfree(strings);
-		return err;
-	}
-	case ETHTOOL_GREGS: {
-		struct ethtool_regs regs = {ETHTOOL_GREGS};
-		uint32_t regs_buff[E1000_REGS_LEN];
-
-		if(copy_from_user(&regs, addr, sizeof(regs)))
-			return -EFAULT;
-		memset(regs_buff, 0, sizeof(regs_buff));
-		if (regs.len > E1000_REGS_LEN)
-			regs.len = E1000_REGS_LEN;
-		e1000_ethtool_gregs(adapter, &regs, regs_buff);
-		if(copy_to_user(addr, &regs, sizeof(regs)))
-			return -EFAULT;
-
-		addr += offsetof(struct ethtool_regs, data);
-		if(copy_to_user(addr, regs_buff, regs.len))
-			return -EFAULT;
-
-		return 0;
-	}
-	case ETHTOOL_NWAY_RST: {
-		if(netif_running(netdev)) {
-			e1000_down(adapter);
-			e1000_up(adapter);
-		}
-		return 0;
-	}
-	case ETHTOOL_PHYS_ID: {
-		struct ethtool_value id;
-		if(copy_from_user(&id, addr, sizeof(id)))
-			return -EFAULT;
-		return e1000_ethtool_led_blink(adapter, &id);
-	}
-	case ETHTOOL_GLINK: {
-		struct ethtool_value link = {ETHTOOL_GLINK};
-		link.data = netif_carrier_ok(netdev);
-		if(copy_to_user(addr, &link, sizeof(link)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GWOL: {
-		struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
-		e1000_ethtool_gwol(adapter, &wol);
-		if(copy_to_user(addr, &wol, sizeof(wol)) != 0)
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SWOL: {
-		struct ethtool_wolinfo wol;
-		if(copy_from_user(&wol, addr, sizeof(wol)) != 0)
-			return -EFAULT;
-		return e1000_ethtool_swol(adapter, &wol);
-	}
-	case ETHTOOL_GEEPROM: {
-		struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM};
-		struct e1000_hw *hw = &adapter->hw;
-		uint16_t *eeprom_buff;
-		void *ptr;
-		int err = 0;
-
-		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
-			return -EFAULT;
-
-		eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL);
-
-		if(!eeprom_buff)
-			return -ENOMEM;
-
-		if((err = e1000_ethtool_geeprom(adapter, &eeprom,
-						eeprom_buff)))
-			goto err_geeprom_ioctl;
-
-		if(copy_to_user(addr, &eeprom, sizeof(eeprom))) {
-			err = -EFAULT;
-			goto err_geeprom_ioctl;
-		}
-
-		addr += offsetof(struct ethtool_eeprom, data);
-		ptr = ((void *)eeprom_buff) + (eeprom.offset & 1);
-
-		if(copy_to_user(addr, ptr, eeprom.len))
-			err = -EFAULT;
-
-err_geeprom_ioctl:
-		kfree(eeprom_buff);
-		return err;
-	}
-	case ETHTOOL_SEEPROM: {
-		struct ethtool_eeprom eeprom;
-
-		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
-			return -EFAULT;
-
-		addr += offsetof(struct ethtool_eeprom, data);
-		return e1000_ethtool_seeprom(adapter, &eeprom, addr);
-	}
-	case ETHTOOL_GRINGPARAM: {
-		struct ethtool_ringparam ering = {ETHTOOL_GRINGPARAM};
-		e1000_ethtool_gring(adapter, &ering);
-		if(copy_to_user(addr, &ering, sizeof(ering)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SRINGPARAM: {
-		struct ethtool_ringparam ering;
-		if(copy_from_user(&ering, addr, sizeof(ering)))
-			return -EFAULT;
-		return e1000_ethtool_sring(adapter, &ering);
-	}
-	case ETHTOOL_GPAUSEPARAM: {
-		struct ethtool_pauseparam epause = {ETHTOOL_GPAUSEPARAM};
-		e1000_ethtool_gpause(adapter, &epause);
-		if(copy_to_user(addr, &epause, sizeof(epause)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SPAUSEPARAM: {
-		struct ethtool_pauseparam epause;
-		if(copy_from_user(&epause, addr, sizeof(epause)))
-			return -EFAULT;
-		return e1000_ethtool_spause(adapter, &epause);
-	}
-	case ETHTOOL_GSTATS: {
-		struct {
-			struct ethtool_stats eth_stats;
-			uint64_t data[E1000_STATS_LEN];
-		} stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} };
-		int i;
-
-		e1000_update_stats(adapter);
-		for(i = 0; i < E1000_STATS_LEN; i++)
-			stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
-					sizeof(uint64_t)) ?
-				*(uint64_t *)((char *)adapter +
-					e1000_gstrings_stats[i].stat_offset) :
-				*(uint32_t *)((char *)adapter +
-					e1000_gstrings_stats[i].stat_offset);
-		if(copy_to_user(addr, &stats, sizeof(stats)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_TEST: {
-		struct {
-			struct ethtool_test eth_test;
-			uint64_t data[E1000_TEST_LEN];
-		} test = { {ETHTOOL_TEST} };
-		int err;
-
-		if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test)))
-			return -EFAULT;
-
-		test.eth_test.len = E1000_TEST_LEN;
-
-		if((err = e1000_ethtool_test(adapter, &test.eth_test,
-					     test.data)))
-			return err;
-
-		if(copy_to_user(addr, &test, sizeof(test)) != 0)
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GRXCSUM: {
-		struct ethtool_value edata = { ETHTOOL_GRXCSUM };
-
-		edata.data = adapter->rx_csum;
-		if (copy_to_user(addr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SRXCSUM: {
-		struct ethtool_value edata;
-
-		if (copy_from_user(&edata, addr, sizeof(edata)))
-			return -EFAULT;
-		adapter->rx_csum = edata.data;
-		if(netif_running(netdev)) {
-			e1000_down(adapter);
-			e1000_up(adapter);
-		} else
-			e1000_reset(adapter);
-		return 0;
-	}
-	case ETHTOOL_GTXCSUM: {
-		struct ethtool_value edata = { ETHTOOL_GTXCSUM };
+	struct e1000_adapter *adapter = netdev_priv(netdev);
 
-		edata.data =
-			(netdev->features & NETIF_F_HW_CSUM) != 0;
-		if (copy_to_user(addr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
+	if(netif_running(netdev)) {
+		e1000_down(adapter);
+		e1000_up(adapter);
 	}
-	case ETHTOOL_STXCSUM: {
-		struct ethtool_value edata;
-
-		if (copy_from_user(&edata, addr, sizeof(edata)))
-			return -EFAULT;
-
-		if(adapter->hw.mac_type < e1000_82543) {
-			if (edata.data != 0)
-				return -EINVAL;
-			return 0;
-		}
+	return 0;
+}
 
-		if (edata.data)
-			netdev->features |= NETIF_F_HW_CSUM;
-		else
-			netdev->features &= ~NETIF_F_HW_CSUM;
+static int
+e1000_get_stats_count(struct net_device *dev)
+{
+	return E1000_STATS_LEN;
+}
 
-		return 0;
-	}
-	case ETHTOOL_GSG: {
-		struct ethtool_value edata = { ETHTOOL_GSG };
+static void
+e1000_get_ethtool_stats(struct net_device *netdev,
+			struct ethtool_stats *stats, u64 *data)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	int i;
 
-		edata.data =
-			(netdev->features & NETIF_F_SG) != 0;
-		if (copy_to_user(addr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
+	e1000_update_stats(adapter);
+	for(i = 0; i < E1000_STATS_LEN; i++) {
+		char *p = (char *) adapter + e1000_gstrings_stats[i].stat_offset;
+		data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) 
+			? *(uint64_t *)p : *(uint32_t *)p;
 	}
-	case ETHTOOL_SSG: {
-		struct ethtool_value edata;
-
-		if (copy_from_user(&edata, addr, sizeof(edata)))
-			return -EFAULT;
-
-		if (edata.data)
-			netdev->features |= NETIF_F_SG;
-		else
-			netdev->features &= ~NETIF_F_SG;
+}
 
-		return 0;
-	}
-#ifdef NETIF_F_TSO
-	case ETHTOOL_GTSO: {
-		struct ethtool_value edata = { ETHTOOL_GTSO };
-
-		edata.data = (netdev->features & NETIF_F_TSO) != 0;
-		if (copy_to_user(addr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_STSO: {
-		struct ethtool_value edata;
+static void
+e1000_get_strings(struct net_device *netdev, u32 string_set, u8 *data)
+{
+	int i;
 
-		if (copy_from_user(&edata, addr, sizeof(edata)))
-			return -EFAULT;
+	switch(string_set) {
+	case ETH_SS_TEST:
+		memcpy(data, e1000_gstrings_test, E1000_TEST_LEN * ETH_GSTRING_LEN);
+		break;
 
-		if ((adapter->hw.mac_type < e1000_82544) ||
-		    (adapter->hw.mac_type == e1000_82547)) {
-			if (edata.data != 0)
-				return -EINVAL;
-			return 0;
+	case ETH_SS_STATS:
+		for(i=0; i < E1000_STATS_LEN; i++) {
+			memcpy(data + i * ETH_GSTRING_LEN,
+			       e1000_gstrings_stats[i].stat_string,
+			       ETH_GSTRING_LEN);
 		}
-
-		if (edata.data)
-			netdev->features |= NETIF_F_TSO;
-		else
-			netdev->features &= ~NETIF_F_TSO;
-
-		return 0;
-	}
-#endif
-	default:
-		return -EOPNOTSUPP;
+		break;
 	}
 }
 
 
+struct ethtool_ops e1000_ethtool_ops = {
+	.get_settings		= e1000_get_settings,
+	.set_settings		= e1000_set_settings,
+	.get_drvinfo		= e1000_get_drvinfo,
+	.get_regs_len		= e1000_get_regs_len,
+	.get_regs		= e1000_get_regs,
+	.get_wol		= e1000_get_wol,
+	.set_wol		= e1000_set_wol,
+	.nway_reset		= e1000_nway_reset,
+	.get_link		= ethtool_op_get_link,
+	.get_eeprom_len		= e1000_get_eeprom_len,
+	.get_eeprom		= e1000_get_eeprom,
+	.set_eeprom		= e1000_set_eeprom,
+	.get_ringparam		= e1000_get_ringparam,
+	.set_ringparam		= e1000_set_ringparam,
+	.get_pauseparam		= e1000_get_pauseparam,
+	.set_pauseparam		= e1000_set_pauseparam,
+	.get_rx_csum		= e1000_get_rx_csum,
+	.set_rx_csum		= e1000_set_rx_csum,
+	.get_tx_csum		= e1000_get_tx_csum,
+	.set_tx_csum		= e1000_set_tx_csum,
+	.get_sg			= ethtool_op_get_sg,
+	.set_sg			= ethtool_op_set_sg,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= e1000_set_tso,
+	.self_test_count	= e1000_diag_test_count,
+	.self_test		= e1000_diag_test,
+	.get_strings		= e1000_get_strings,
+	.phys_id		= e1000_phys_id,
+	.get_stats_count	= e1000_get_stats_count,
+	.get_ethtool_stats	= e1000_get_ethtool_stats,
+};
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	Tue May 18 23:54:44 2004
+++ b/drivers/net/e1000/e1000_main.c	Tue May 18 23:54:44 2004
@@ -167,9 +167,9 @@
 static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
 #endif
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
-static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
-static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
-			   int cmd);
+
+static int e1000_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
+extern struct ethtool_ops e1000_ethtool_ops;
 static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
 static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
 static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
@@ -206,7 +206,6 @@
 /* Exported from other modules */
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
-extern int e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr);
 
 static struct pci_driver e1000_driver = {
 	.name     = e1000_driver_name,
@@ -445,7 +444,8 @@
 	netdev->set_multicast_list = &e1000_set_multi;
 	netdev->set_mac_address = &e1000_set_mac;
 	netdev->change_mtu = &e1000_change_mtu;
-	netdev->do_ioctl = &e1000_ioctl;
+	netdev->do_ioctl = &e1000_do_ioctl;
+	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
 	netdev->tx_timeout = &e1000_tx_timeout;
 	netdev->watchdog_timeo = 5 * HZ;
 #ifdef CONFIG_E1000_NAPI
@@ -2498,37 +2498,16 @@
 		adapter->smartspeed = 0;
 }
 
-/**
- * e1000_ioctl -
- * @netdev:
- * @ifreq:
- * @cmd:
- **/
-
-static int
-e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCGMIIPHY:
-	case SIOCGMIIREG:
-	case SIOCSMIIREG:
-		return e1000_mii_ioctl(netdev, ifr, cmd);
-	case SIOCETHTOOL:
-		return e1000_ethtool_ioctl(netdev, ifr);
-	default:
-		return -EOPNOTSUPP;
-	}
-}
 
 /**
- * e1000_mii_ioctl -
+ * e1000_do_ioctl -
  * @netdev:
  * @ifreq:
  * @cmd:
  **/
 
 static int
-e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+e1000_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c
--- a/drivers/net/epic100.c	Tue May 18 23:54:44 2004
+++ b/drivers/net/epic100.c	Tue May 18 23:54:44 2004
@@ -77,8 +77,6 @@
    These may be modified when a driver module is loaded.*/
 
 static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 32;
 
 /* Used to pass the full-duplex flag, etc. */
 #define MAX_UNITS 8		/* More are supported, limit only on options */
@@ -96,9 +94,9 @@
    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 TX_QUEUE_LEN	10		/* Limit ring entries actually used.  */
-#define RX_RING_SIZE	32
+#define TX_RING_SIZE	256
+#define TX_QUEUE_LEN	240		/* Limit ring entries actually used.  */
+#define RX_RING_SIZE	256
 #define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct epic_tx_desc)
 #define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct epic_rx_desc)
 
@@ -155,12 +153,10 @@
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(debug, "i");
-MODULE_PARM(max_interrupt_work, "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(debug, "EPIC/100 debug level (0-5)");
-MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt");
 MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex");
 MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)");
@@ -292,6 +288,12 @@
 	StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80,
 };
 
+#define EpicRemoved	0xffffffff	/* Chip failed or removed (CardBus) */
+
+#define EpicNapiEvent	(TxEmpty | TxDone | \
+			 RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull)
+#define EpicNormalEvent	(0x0000ffff & ~EpicNapiEvent)
+
 static u16 media2miictl[16] = {
 	0, 0x0C00, 0x0C00, 0x2000,  0x0100, 0x2100, 0, 0,
 	0, 0, 0, 0,  0, 0, 0, 0 };
@@ -330,9 +332,12 @@
 
 	/* Ring pointers. */
 	spinlock_t lock;				/* Group with Tx control cache line. */
+	spinlock_t napi_lock;
+	unsigned int reschedule_in_poll;
 	unsigned int cur_tx, dirty_tx;
 
 	unsigned int cur_rx, dirty_rx;
+	u32 irq_mask;
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
 
 	struct pci_dev *pci_dev;			/* PCI bus location. */
@@ -359,7 +364,8 @@
 static void epic_tx_timeout(struct net_device *dev);
 static void epic_init_ring(struct net_device *dev);
 static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int epic_rx(struct net_device *dev);
+static int epic_rx(struct net_device *dev, int budget);
+static int epic_poll(struct net_device *dev, int *budget);
 static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
@@ -378,7 +384,7 @@
 	int irq;
 	struct net_device *dev;
 	struct epic_private *ep;
-	int i, option = 0, duplex = 0;
+	int i, ret, option = 0, duplex = 0;
 	void *ring_space;
 	dma_addr_t ring_dma;
 
@@ -392,29 +398,33 @@
 	
 	card_idx++;
 	
-	i = pci_enable_device(pdev);
-	if (i)
-		return i;
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto out;
 	irq = pdev->irq;
 
 	if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) {
 		printk (KERN_ERR "card %d: no PCI region space\n", card_idx);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_out_disable;
 	}
 	
 	pci_set_master(pdev);
 
+	ret = pci_request_regions(pdev, DRV_NAME);
+	if (ret < 0)
+		goto err_out_disable;
+
+	ret = -ENOMEM;
+
 	dev = alloc_etherdev(sizeof (*ep));
 	if (!dev) {
 		printk (KERN_ERR "card %d: no memory for eth device\n", card_idx);
-		return -ENOMEM;
+		goto err_out_free_res;
 	}
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	if (pci_request_regions(pdev, DRV_NAME))
-		goto err_out_free_netdev;
-
 #ifdef USE_IO_OPS
 	ioaddr = pci_resource_start (pdev, 0);
 #else
@@ -422,7 +432,7 @@
 	ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
 	if (!ioaddr) {
 		printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx);
-		goto err_out_free_res;
+		goto err_out_free_netdev;
 	}
 #endif
 
@@ -459,7 +469,9 @@
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 
-	spin_lock_init (&ep->lock);
+	spin_lock_init(&ep->lock);
+	spin_lock_init(&ep->napi_lock);
+	ep->reschedule_in_poll = 0;
 
 	/* Bring the chip out of low-power mode. */
 	outl(0x4200, ioaddr + GENCTL);
@@ -489,6 +501,9 @@
 	ep->pci_dev = pdev;
 	ep->chip_id = chip_idx;
 	ep->chip_flags = pci_id_tbl[chip_idx].drv_flags;
+	ep->irq_mask = 
+		(ep->chip_flags & TYPE2_INTR ?  PCIBusErr175 : PCIBusErr170)
+		 | CntFull | TxUnderrun | EpicNapiEvent;
 
 	/* Find the connected MII xcvrs.
 	   Doing this in open() would allow detecting external xcvrs later, but
@@ -543,10 +558,12 @@
 	dev->ethtool_ops = &netdev_ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->tx_timeout = &epic_tx_timeout;
+	dev->poll = epic_poll;
+	dev->weight = 64;
 
-	i = register_netdev(dev);
-	if (i)
-		goto err_out_unmap_tx;
+	ret = register_netdev(dev);
+	if (ret < 0)
+		goto err_out_unmap_rx;
 
 	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
 		   dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq);
@@ -554,19 +571,24 @@
 		printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x.\n", dev->dev_addr[i]);
 
-	return 0;
+out:
+	return ret;
 
+err_out_unmap_rx:
+	pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
 err_out_unmap_tx:
 	pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
 err_out_iounmap:
 #ifndef USE_IO_OPS
 	iounmap(ioaddr);
-err_out_free_res:
-#endif
-	pci_release_regions(pdev);
 err_out_free_netdev:
+#endif
 	free_netdev(dev);
-	return -ENODEV;
+err_out_free_res:
+	pci_release_regions(pdev);
+err_out_disable:
+	pci_disable_device(pdev);
+	goto out;
 }
 
 /* Serial EEPROM section. */
@@ -592,6 +614,38 @@
 #define EE_READ256_CMD	(6 << 8)
 #define EE_ERASE_CMD	(7 << 6)
 
+static void epic_disable_int(struct net_device *dev, struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+
+	outl(0x00000000, ioaddr + INTMASK);
+}
+
+static inline void __epic_pci_commit(long ioaddr)
+{
+#ifndef USE_IO_OPS
+	inl(ioaddr + INTMASK);
+#endif
+}
+
+static inline void epic_napi_irq_off(struct net_device *dev,
+				     struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+
+	outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK);
+	__epic_pci_commit(ioaddr);
+}
+
+static inline void epic_napi_irq_on(struct net_device *dev,
+				    struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+
+	/* No need to commit possible posted write */
+	outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK);
+}
+
 static int __devinit read_eeprom(long ioaddr, int location)
 {
 	int i;
@@ -752,9 +806,8 @@
 
 	/* Enable interrupts by setting the interrupt mask. */
 	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone | TxEmpty
-		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
-		 ioaddr + INTMASK);
+		 | CntFull | TxUnderrun 
+		 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
@@ -795,7 +848,7 @@
 	}
 
 	/* Remove the packets on the Rx queue. */
-	epic_rx(dev);
+	epic_rx(dev, RX_RING_SIZE);
 }
 
 static void epic_restart(struct net_device *dev)
@@ -841,9 +894,9 @@
 
 	/* Enable interrupts by setting the interrupt mask. */
 	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone | TxEmpty
-		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
-		 ioaddr + INTMASK);
+		 | CntFull | TxUnderrun
+		 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
+
 	printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
 		   " interrupt %4.4x.\n",
 		   dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL),
@@ -929,7 +982,6 @@
 	int i;
 
 	ep->tx_full = 0;
-	ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 	ep->dirty_tx = ep->cur_tx = 0;
 	ep->cur_rx = ep->dirty_rx = 0;
 	ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
@@ -1029,6 +1081,76 @@
 	return 0;
 }
 
+static void epic_tx_error(struct net_device *dev, struct epic_private *ep,
+			  int status)
+{
+	struct net_device_stats *stats = &ep->stats;
+
+#ifndef final_version
+	/* There was an major error, log it. */
+	if (debug > 1)
+		printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
+		       dev->name, status);
+#endif
+	stats->tx_errors++;
+	if (status & 0x1050)
+		stats->tx_aborted_errors++;
+	if (status & 0x0008)
+		stats->tx_carrier_errors++;
+	if (status & 0x0040)
+		stats->tx_window_errors++;
+	if (status & 0x0010)
+		stats->tx_fifo_errors++;
+}
+
+static void epic_tx(struct net_device *dev, struct epic_private *ep)
+{
+	unsigned int dirty_tx, cur_tx;
+
+	/*
+	 * Note: if this lock becomes a problem we can narrow the locked
+	 * region at the cost of occasionally grabbing the lock more times.
+	 */
+	cur_tx = ep->cur_tx;
+	for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) {
+		struct sk_buff *skb;
+		int entry = dirty_tx % TX_RING_SIZE;
+		int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus);
+
+		if (txstatus & DescOwn)
+			break;	/* It still hasn't been Txed */
+
+		if (likely(txstatus & 0x0001)) {
+			ep->stats.collisions += (txstatus >> 8) & 15;
+			ep->stats.tx_packets++;
+			ep->stats.tx_bytes += ep->tx_skbuff[entry]->len;
+		} else
+			epic_tx_error(dev, ep, txstatus);
+
+		/* Free the original skb. */
+		skb = ep->tx_skbuff[entry];
+		pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
+				 skb->len, PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq(skb);
+		ep->tx_skbuff[entry] = 0;
+	}
+
+#ifndef final_version
+	if (cur_tx - dirty_tx > TX_RING_SIZE) {
+		printk(KERN_WARNING
+		       "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+		       dev->name, dirty_tx, cur_tx, ep->tx_full);
+		dirty_tx += TX_RING_SIZE;
+	}
+#endif
+	ep->dirty_tx = dirty_tx;
+	if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) {
+		/* The ring is no longer full, allow new TX entries. */
+		ep->tx_full = 0;
+		netif_wake_queue(dev);
+	}
+}
+
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
@@ -1036,135 +1158,71 @@
 	struct net_device *dev = dev_instance;
 	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
-	int status, boguscnt = max_interrupt_work;
 	unsigned int handled = 0;
+	int status;
 
-	do {
-		status = inl(ioaddr + INTSTAT);
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		outl(status & 0x00007fff, ioaddr + INTSTAT);
-
-		if (debug > 4)
-			printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new "
-				   "intstat=%#8.8x.\n",
-				   dev->name, status, (int)inl(ioaddr + INTSTAT));
-
-		if ((status & IntrSummary) == 0)
-			break;
-		handled = 1;
+	status = inl(ioaddr + INTSTAT);
+	/* Acknowledge all of the current interrupt sources ASAP. */
+	outl(status & EpicNormalEvent, ioaddr + INTSTAT);
 
-		if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow))
-			epic_rx(dev);
+	if (debug > 4) {
+		printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new "
+				   "intstat=%#8.8x.\n", dev->name, status,
+				   (int)inl(ioaddr + INTSTAT));
+	}
 
-		if (status & (TxEmpty | TxDone)) {
-			unsigned int dirty_tx, cur_tx;
+	if ((status & IntrSummary) == 0)
+		goto out;
 
-			/* Note: if this lock becomes a problem we can narrow the locked
-			   region at the cost of occasionally grabbing the lock more
-			   times. */
-			spin_lock(&ep->lock);
-			cur_tx = ep->cur_tx;
-			dirty_tx = ep->dirty_tx;
-			for (; cur_tx - dirty_tx > 0; dirty_tx++) {
-				struct sk_buff *skb;
-				int entry = dirty_tx % TX_RING_SIZE;
-				int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus);
+	handled = 1;
 
-				if (txstatus & DescOwn)
-					break;			/* It still hasn't been Txed */
+	if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) {
+		spin_lock(&ep->napi_lock);
+		if (netif_rx_schedule_prep(dev)) {
+			epic_napi_irq_off(dev, ep);
+			__netif_rx_schedule(dev);
+		} else
+			ep->reschedule_in_poll++;
+		spin_unlock(&ep->napi_lock);
+	}
+	status &= ~EpicNapiEvent;
 
-				if ( ! (txstatus & 0x0001)) {
-					/* There was an major error, log it. */
-#ifndef final_version
-					if (debug > 1)
-						printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
-							   dev->name, txstatus);
-#endif
-					ep->stats.tx_errors++;
-					if (txstatus & 0x1050) ep->stats.tx_aborted_errors++;
-					if (txstatus & 0x0008) ep->stats.tx_carrier_errors++;
-					if (txstatus & 0x0040) ep->stats.tx_window_errors++;
-					if (txstatus & 0x0010) ep->stats.tx_fifo_errors++;
-				} else {
-					ep->stats.collisions += (txstatus >> 8) & 15;
-					ep->stats.tx_packets++;
-					ep->stats.tx_bytes += ep->tx_skbuff[entry]->len;
-				}
-
-				/* Free the original skb. */
-				skb = ep->tx_skbuff[entry];
-				pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
-						 skb->len, PCI_DMA_TODEVICE);
-				dev_kfree_skb_irq(skb);
-				ep->tx_skbuff[entry] = 0;
-			}
+	/* Check uncommon events all at once. */
+	if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) {
+		if (status == EpicRemoved)
+			goto out;
 
-#ifndef final_version
-			if (cur_tx - dirty_tx > TX_RING_SIZE) {
-				printk(KERN_WARNING "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-					   dev->name, dirty_tx, cur_tx, ep->tx_full);
-				dirty_tx += TX_RING_SIZE;
-			}
-#endif
-			ep->dirty_tx = dirty_tx;
-			if (ep->tx_full
-				&& cur_tx - dirty_tx < TX_QUEUE_LEN - 4) {
-				/* The ring is no longer full, allow new TX entries. */
-				ep->tx_full = 0;
-				spin_unlock(&ep->lock);
-				netif_wake_queue(dev);
-			} else
-				spin_unlock(&ep->lock);
-		}
+		/* Always update the error counts to avoid overhead later. */
+		ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+		ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+		ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
 
-		/* Check uncommon events all at once. */
-		if (status & (CntFull | TxUnderrun | RxOverflow | RxFull |
-					  PCIBusErr170 | PCIBusErr175)) {
-			if (status == 0xffffffff) /* Chip failed or removed (CardBus). */
-				break;
-			/* Always update the error counts to avoid overhead later. */
-			ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-			ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-			ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
-
-			if (status & TxUnderrun) { /* Tx FIFO underflow. */
-				ep->stats.tx_fifo_errors++;
-				outl(ep->tx_threshold += 128, ioaddr + TxThresh);
-				/* Restart the transmit process. */
-				outl(RestartTx, ioaddr + COMMAND);
-			}
-			if (status & RxOverflow) {		/* Missed a Rx frame. */
-				ep->stats.rx_errors++;
-			}
-			if (status & (RxOverflow | RxFull))
-				outw(RxQueued, ioaddr + COMMAND);
-			if (status & PCIBusErr170) {
-				printk(KERN_ERR "%s: PCI Bus Error!  EPIC status %4.4x.\n",
-					   dev->name, status);
-				epic_pause(dev);
-				epic_restart(dev);
-			}
-			/* Clear all error sources. */
-			outl(status & 0x7f18, ioaddr + INTSTAT);
+		if (status & TxUnderrun) { /* Tx FIFO underflow. */
+			ep->stats.tx_fifo_errors++;
+			outl(ep->tx_threshold += 128, ioaddr + TxThresh);
+			/* Restart the transmit process. */
+			outl(RestartTx, ioaddr + COMMAND);
 		}
-		if (--boguscnt < 0) {
-			printk(KERN_ERR "%s: Too much work at interrupt, "
-				   "IntrStatus=0x%8.8x.\n",
-				   dev->name, status);
-			/* Clear all interrupt sources. */
-			outl(0x0001ffff, ioaddr + INTSTAT);
-			break;
+		if (status & PCIBusErr170) {
+			printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n",
+					 dev->name, status);
+			epic_pause(dev);
+			epic_restart(dev);
 		}
-	} while (1);
+		/* Clear all error sources. */
+		outl(status & 0x7f18, ioaddr + INTSTAT);
+	}
 
-	if (debug > 3)
-		printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n",
-			   dev->name, status);
+out:
+	if (debug > 3) {
+		printk(KERN_DEBUG "%s: exit interrupt, intr_status=%#4.4x.\n",
+				   dev->name, status);
+	}
 
 	return IRQ_RETVAL(handled);
 }
 
-static int epic_rx(struct net_device *dev)
+static int epic_rx(struct net_device *dev, int budget)
 {
 	struct epic_private *ep = dev->priv;
 	int entry = ep->cur_rx % RX_RING_SIZE;
@@ -1174,6 +1232,10 @@
 	if (debug > 4)
 		printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
 			   ep->rx_ring[entry].rxstatus);
+
+	if (rx_work_limit > budget)
+		rx_work_limit = budget;
+
 	/* If we own the next entry, it's a new packet. Send it up. */
 	while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) {
 		int status = le32_to_cpu(ep->rx_ring[entry].rxstatus);
@@ -1234,7 +1296,7 @@
 				ep->rx_skbuff[entry] = NULL;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
+			netif_receive_skb(skb);
 			dev->last_rx = jiffies;
 			ep->stats.rx_packets++;
 			ep->stats.rx_bytes += pkt_len;
@@ -1262,6 +1324,65 @@
 	return work_done;
 }
 
+static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+	int status;
+
+	status = inl(ioaddr + INTSTAT);
+
+	if (status == EpicRemoved)
+		return;
+	if (status & RxOverflow) 	/* Missed a Rx frame. */
+		ep->stats.rx_errors++;
+	if (status & (RxOverflow | RxFull))
+		outw(RxQueued, ioaddr + COMMAND);
+}
+
+static int epic_poll(struct net_device *dev, int *budget)
+{
+	struct epic_private *ep = dev->priv;
+	int work_done, orig_budget;
+	long ioaddr = dev->base_addr;
+
+	orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
+
+rx_action:
+
+	epic_tx(dev, ep);
+
+	work_done = epic_rx(dev, *budget);
+
+	epic_rx_err(dev, ep);
+
+	*budget -= work_done;
+	dev->quota -= work_done;
+
+	if (netif_running(dev) && (work_done < orig_budget)) {
+		unsigned long flags;
+		int more;
+
+		/* A bit baroque but it avoids a (space hungry) spin_unlock */
+
+		spin_lock_irqsave(&ep->napi_lock, flags);
+
+		more = ep->reschedule_in_poll;
+		if (!more) {
+			__netif_rx_complete(dev);
+			outl(EpicNapiEvent, ioaddr + INTSTAT);
+			epic_napi_irq_on(dev, ep);
+		} else
+			ep->reschedule_in_poll--;
+
+		spin_unlock_irqrestore(&ep->napi_lock, flags);
+
+		if (more)
+			goto rx_action;
+	}
+
+	return (work_done >= orig_budget);
+}
+
 static int epic_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
@@ -1276,9 +1397,13 @@
 			   dev->name, (int)inl(ioaddr + INTSTAT));
 
 	del_timer_sync(&ep->timer);
-	epic_pause(dev);
+
+	epic_disable_int(dev, ep);
+
 	free_irq(dev->irq, dev);
 
+	epic_pause(dev);
+
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		skb = ep->rx_skbuff[i];
@@ -1476,6 +1601,7 @@
 #endif
 	pci_release_regions(pdev);
 	free_netdev(dev);
+	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 	/* pci_power_off(pdev, -1); */
 }
diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c
--- a/drivers/net/r8169.c	Tue May 18 23:54:44 2004
+++ b/drivers/net/r8169.c	Tue May 18 23:54:44 2004
@@ -64,6 +64,14 @@
 #define dprintk(fmt, args...)	do {} while (0)
 #endif /* RTL8169_DEBUG */
 
+#ifdef CONFIG_R8169_NAPI
+#define rtl8169_rx_skb			netif_receive_skb
+#define rtl8169_rx_quota(count, quota)	min(count, quota)
+#else
+#define rtl8169_rx_skb			netif_rx
+#define rtl8169_rx_quota(count, quota)	count
+#endif
+
 /* media options */
 #define MAX_UNITS 8
 static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
@@ -90,8 +98,9 @@
 #define RxPacketMaxSize	0x0800	/* Maximum size supported is 16K-1 */
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
 
+#define R8169_NAPI_WEIGHT	64
 #define NUM_TX_DESC	64	/* Number of Tx descriptor registers */
-#define NUM_RX_DESC	64	/* Number of Rx descriptor registers */
+#define NUM_RX_DESC	256	/* Number of Rx descriptor registers */
 #define RX_BUF_SIZE	1536	/* Rx Buffer size */
 #define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
 #define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
@@ -194,7 +203,7 @@
 	SWInt = 0x0100,
 	TxDescUnavail = 0x80,
 	RxFIFOOver = 0x40,
-	RxUnderrun = 0x20,
+	LinkChg = 0x20,
 	RxOverflow = 0x10,
 	TxErr = 0x08,
 	TxOK = 0x04,
@@ -306,10 +315,10 @@
 };
 
 struct rtl8169_private {
-	void *mmio_addr;	/* memory map physical address */
+	void *mmio_addr;		/* memory map physical address */
 	struct pci_dev *pci_dev;	/* Index of PCI device  */
 	struct net_device_stats stats;	/* statistics of net device */
-	spinlock_t lock;	/* spin lock flag */
+	spinlock_t lock;		/* spin lock flag */
 	int chipset;
 	int mac_version;
 	int phy_version;
@@ -317,15 +326,16 @@
 	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
 	u32 dirty_rx;
 	u32 dirty_tx;
-	struct TxDesc *TxDescArray;	/* Index of 256-alignment Tx Descriptor buffer */
-	struct RxDesc *RxDescArray;	/* Index of 256-alignment Rx Descriptor buffer */
+	struct TxDesc *TxDescArray;	/* 256-aligned Tx descriptor ring */
+	struct RxDesc *RxDescArray;	/* 256-aligned Rx descriptor ring */
 	dma_addr_t TxPhyAddr;
 	dma_addr_t RxPhyAddr;
 	struct sk_buff *Rx_skbuff[NUM_RX_DESC];	/* Rx data buffers */
-	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Index of Transmit data buffer */
+	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Tx data buffers */
 	struct timer_list timer;
 	unsigned long phy_link_down_cnt;
 	u16 cp_cmd;
+	u16 intr_mask;
 };
 
 MODULE_AUTHOR("Realtek");
@@ -344,9 +354,14 @@
 static void rtl8169_set_rx_mode(struct net_device *dev);
 static void rtl8169_tx_timeout(struct net_device *dev);
 static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
+#ifdef CONFIG_R8169_NAPI
+static int rtl8169_poll(struct net_device *dev, int *budget);
+#endif
 
 static const u16 rtl8169_intr_mask =
-    RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
+	LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
+static const u16 rtl8169_napi_event =
+	RxOK | LinkChg | RxOverflow | RxFIFOOver | TxOK | TxErr;
 static const unsigned int rtl8169_rx_config =
     (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
@@ -364,11 +379,9 @@
 
 	for (i = 2000; i > 0; i--) {
 		// Check if the RTL8169 has completed writing to the specified MII register
-		if (!(RTL_R32(PHYAR) & 0x80000000)) {
+		if (!(RTL_R32(PHYAR) & 0x80000000)) 
 			break;
-		} else {
-			udelay(100);
-		}
+		udelay(100);
 	}
 }
 
@@ -393,7 +406,7 @@
 static void rtl8169_get_drvinfo(struct net_device *dev,
 				struct ethtool_drvinfo *info)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 
 	strcpy(info->driver, RTL8169_DRIVER_NAME);
 	strcpy(info->version, RTL8169_VERSION );
@@ -500,7 +513,7 @@
 
 static void rtl8169_hw_phy_config(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	struct {
 		u16 regs[5]; /* Beware of bit-sign propagation */
@@ -568,7 +581,7 @@
 
 static void rtl8169_hw_phy_reset(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	int i, val;
 
@@ -592,7 +605,7 @@
 static void rtl8169_phy_timer(unsigned long __opaque)
 {
 	struct net_device *dev = (struct net_device *)__opaque;
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct timer_list *timer = &tp->timer;
 	void *ioaddr = tp->mmio_addr;
 
@@ -620,7 +633,7 @@
 
 static inline void rtl8169_delete_timer(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct timer_list *timer = &tp->timer;
 
 	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
@@ -634,7 +647,7 @@
 
 static inline void rtl8169_request_timer(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct timer_list *timer = &tp->timer;
 
 	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
@@ -681,7 +694,7 @@
 	// enable device (incl. PCI PM wakeup and hotplug setup)
 	rc = pci_enable_device(pdev);
 	if (rc) {
-		printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name);
+		printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name);
 		goto err_out;
 	}
 
@@ -693,7 +706,8 @@
 		pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
 		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
 	} else {
-		printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n");
+		printk(KERN_ERR PFX
+		       "Cannot find PowerManagement capability, aborting.\n");
 		goto err_out_free_res;
 	}
 
@@ -718,7 +732,8 @@
 
 	rc = pci_request_regions(pdev, dev->name);
 	if (rc) {
-		printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name);
+		printk(KERN_ERR PFX "%s: could not request regions.\n",
+		       pdev->slot_name);
 		goto err_out_disable;
 	}
 
@@ -836,9 +851,12 @@
 	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 	dev->irq = pdev->irq;
 	dev->base_addr = (unsigned long) ioaddr;
-//      dev->do_ioctl           = mii_ioctl;
-
-	tp = dev->priv;		// private data //
+#ifdef CONFIG_R8169_NAPI
+	dev->poll = rtl8169_poll;
+	dev->weight = R8169_NAPI_WEIGHT;
+	printk(KERN_INFO PFX "NAPI enabled\n");
+#endif
+	tp->intr_mask = 0xffff;
 	tp->pci_dev = pdev;
 	tp->mmio_addr = ioaddr;
 
@@ -919,13 +937,16 @@
 			default:
 				break;
 			}
-			mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F));	//leave PHY_AUTO_NEGO_REG bit4:0 unchanged
+			// leave PHY_AUTO_NEGO_REG bit4:0 unchanged
+			mdio_write(ioaddr, PHY_AUTO_NEGO_REG,
+				   Cap10_100 | (val & 0x1F));
 			mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000);
 		} else {
 			printk(KERN_INFO "%s: Auto-negotiation Enabled.\n",
 			       dev->name);
 
-			// enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
+			// enable 10/100 Full/Half Mode
+			// leave PHY_AUTO_NEGO_REG bit4:0 unchanged
 			mdio_write(ioaddr, PHY_AUTO_NEGO_REG,
 				   PHY_Cap_100_Full_Or_Less | (val & 0x1f));
 
@@ -964,7 +985,7 @@
 			} else {
 				udelay(100);
 			}
-		}		// end for-loop to wait for auto-negotiation process
+		}	// end for-loop to wait for auto-negotiation process
 
 	} else {
 		udelay(100);
@@ -972,7 +993,6 @@
 		       "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n",
 		       dev->name,
 		       (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed");
-
 	}
 
 	return 0;
@@ -982,7 +1002,7 @@
 rtl8169_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -1001,7 +1021,7 @@
 static int rtl8169_suspend(struct pci_dev *pdev, u32 state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
@@ -1042,7 +1062,7 @@
 static int
 rtl8169_open(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct pci_dev *pdev = tp->pci_dev;
 	int retval;
 
@@ -1091,7 +1111,7 @@
 static void
 rtl8169_hw_start(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	u32 i;
 
@@ -1102,8 +1122,7 @@
 	for (i = 1000; i > 0; i--) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
-		else
-			udelay(10);
+		udelay(10);
 	}
 
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -1114,8 +1133,8 @@
 	RTL_W16(RxMaxSize, RxPacketMaxSize);
 
 	// Set Rx Config register
-	i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].
-				 RxConfigMask);
+	i = rtl8169_rx_config |
+		(RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
 	RTL_W32(RxConfig, i);
 
 	/* Set DMA burst size and Interframe Gap Time */
@@ -1126,7 +1145,8 @@
 	RTL_W16(CPlusCmd, tp->cp_cmd);
 
 	if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
-		dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n");
+		dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. "
+			"Bit-3 and bit-14 MUST be 1\n");
 		tp->cp_cmd |= (1 << 14) | PCIMulRW;
 		RTL_W16(CPlusCmd, tp->cp_cmd);
 	}
@@ -1151,7 +1171,6 @@
 	RTL_W16(IntrMask, rtl8169_intr_mask);
 
 	netif_start_queue(dev);
-
 }
 
 static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
@@ -1248,7 +1267,7 @@
 
 static int rtl8169_init_ring(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 
 	tp->cur_rx = tp->dirty_rx = 0;
 	tp->cur_tx = tp->dirty_tx = 0;
@@ -1302,10 +1321,11 @@
 static void
 rtl8169_tx_timeout(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	u8 tmp8;
 
+	printk(KERN_INFO "%s: TX Timeout\n", dev->name);
 	/* disable Tx, if not already */
 	tmp8 = RTL_R8(ChipCmd);
 	if (tmp8 & CmdTxEnb)
@@ -1328,9 +1348,9 @@
 static int
 rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
-	int entry = tp->cur_tx % NUM_TX_DESC;
+	unsigned int entry = tp->cur_tx % NUM_TX_DESC;
 	u32 len = skb->len;
 
 	if (unlikely(skb->len < ETH_ZLEN)) {
@@ -1382,7 +1402,7 @@
 rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	unsigned long dirty_tx, tx_left;
+	unsigned int dirty_tx, tx_left;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -1392,7 +1412,7 @@
 	tx_left = tp->cur_tx - dirty_tx;
 
 	while (tx_left > 0) {
-		int entry = dirty_tx % NUM_TX_DESC;
+		unsigned int entry = dirty_tx % NUM_TX_DESC;
 		struct sk_buff *skb = tp->Tx_skbuff[entry];
 		u32 status;
 
@@ -1442,11 +1462,11 @@
 	return ret;
 }
 
-static void
+static int
 rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	unsigned long cur_rx, rx_left;
+	unsigned int cur_rx, rx_left, count;
 	int delta;
 
 	assert(dev != NULL);
@@ -1455,9 +1475,10 @@
 
 	cur_rx = tp->cur_rx;
 	rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
+	rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
 
 	while (rx_left > 0) {
-		int entry = cur_rx % NUM_RX_DESC;
+		unsigned int entry = cur_rx % NUM_RX_DESC;
 		u32 status;
 
 		rmb();
@@ -1494,7 +1515,7 @@
 
 			skb_put(skb, pkt_size);
 			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
+			rtl8169_rx_skb(skb);
 
 			dev->last_rx = jiffies;
 			tp->stats.rx_bytes += pkt_size;
@@ -1505,13 +1526,15 @@
 		rx_left--;
 	}
 
+	count = cur_rx - tp->cur_rx;
 	tp->cur_rx = cur_rx;
 
 	delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
-	if (delta > 0)
-		tp->dirty_rx += delta;
-	else if (delta < 0)
+	if (delta < 0) {
 		printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
+		delta = 0;
+	}
+	tp->dirty_rx += delta;
 
 	/*
 	 * FIXME: until there is periodic timer to try and refill the ring,
@@ -1522,6 +1545,8 @@
 	 */
 	if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
 		printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
+
+	return count;
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
@@ -1529,7 +1554,7 @@
 rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	int boguscnt = max_interrupt_work;
 	void *ioaddr = tp->mmio_addr;
 	int status = 0;
@@ -1544,17 +1569,30 @@
 
 		handled = 1;
 /*
-		if (status & RxUnderrun)
+		if (status & LinkChg)
 			link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;
 */
+		status &= tp->intr_mask;
 		RTL_W16(IntrStatus,
 			(status & RxFIFOOver) ? (status | RxOverflow) : status);
 
 		if (!(status & rtl8169_intr_mask))
 			break;
 
+#ifdef CONFIG_R8169_NAPI
+		RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
+		tp->intr_mask = ~rtl8169_napi_event;
+
+		if (likely(netif_rx_schedule_prep(dev)))
+			__netif_rx_schedule(dev);
+		else {
+			printk(KERN_INFO "%s: interrupt %x taken in poll\n",
+			       dev->name, status);	
+		}
+		break;
+#else
 		// Rx interrupt 
-		if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) {
+		if (status & (RxOK | LinkChg | RxOverflow | RxFIFOOver)) {
 			rtl8169_rx_interrupt(dev, tp, ioaddr);
 		}
 		// Tx interrupt
@@ -1563,6 +1601,7 @@
 			rtl8169_tx_interrupt(dev, tp, ioaddr);
 			spin_unlock(&tp->lock);
 		}
+#endif
 
 		boguscnt--;
 	} while (boguscnt > 0);
@@ -1576,10 +1615,40 @@
 	return IRQ_RETVAL(handled);
 }
 
+#ifdef CONFIG_R8169_NAPI
+static int rtl8169_poll(struct net_device *dev, int *budget)
+{
+	unsigned int work_done, work_to_do = min(*budget, dev->quota);
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+
+	work_done = rtl8169_rx_interrupt(dev, tp, ioaddr);
+	rtl8169_tx_interrupt(dev, tp, ioaddr);
+
+	*budget -= work_done;
+	dev->quota -= work_done;
+
+	if ((work_done < work_to_do) || !netif_running(dev)) {
+		netif_rx_complete(dev);
+		tp->intr_mask = 0xffff;
+		/*
+		 * 20040426: the barrier is not strictly required but the
+		 * behavior of the irq handler could be less predictable
+		 * without it. Btw, the lack of flush for the posted pci
+		 * write is safe - FR
+		 */
+		smp_wmb();
+		RTL_W16(IntrMask, rtl8169_intr_mask);
+	}
+
+	return (work_done >= work_to_do);
+}
+#endif
+
 static int
 rtl8169_close(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct pci_dev *pdev = tp->pci_dev;
 	void *ioaddr = tp->mmio_addr;
 
@@ -1621,7 +1690,7 @@
 static void
 rtl8169_set_rx_mode(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 	u32 mc_filter[2];	/* Multicast hash filter */
@@ -1655,10 +1724,8 @@
 
 	spin_lock_irqsave(&tp->lock, flags);
 
-	tmp =
-	    rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) &
-					   rtl_chip_info[tp->chipset].
-					   RxConfigMask);
+	tmp = rtl8169_rx_config | rx_mode |
+	      (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
 
 	RTL_W32(RxConfig, tmp);
 	RTL_W32(MAR0 + 0, mc_filter[0]);
@@ -1675,7 +1742,7 @@
  */
 static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;