net: use netdev_mc_count and netdev_mc_empty when appropriate
[safe/jmp/linux-2.6] / drivers / net / via-rhine.c
index be1c104..85df7ac 100644 (file)
        version. He may or may not be interested in bug reports on this
        code. You can find his versions at:
        http://www.scyld.com/network/via-rhine.html
        version. He may or may not be interested in bug reports on this
        code. You can find his versions at:
        http://www.scyld.com/network/via-rhine.html
-
-
-       Linux kernel version history:
-
-       LK1.1.0:
-       - Jeff Garzik: softnet 'n stuff
-
-       LK1.1.1:
-       - Justin Guyett: softnet and locking fixes
-       - Jeff Garzik: use PCI interface
-
-       LK1.1.2:
-       - Urban Widmark: minor cleanups, merges from Becker 1.03a/1.04 versions
-
-       LK1.1.3:
-       - Urban Widmark: use PCI DMA interface (with thanks to the eepro100.c
-                        code) update "Theory of Operation" with
-                        softnet/locking changes
-       - Dave Miller: PCI DMA and endian fixups
-       - Jeff Garzik: MOD_xxx race fixes, updated PCI resource allocation
-
-       LK1.1.4:
-       - Urban Widmark: fix gcc 2.95.2 problem and
-                        remove writel's to fixed address 0x7c
-
-       LK1.1.5:
-       - Urban Widmark: mdio locking, bounce buffer changes
-                        merges from Beckers 1.05 version
-                        added netif_running_on/off support
-
-       LK1.1.6:
-       - Urban Widmark: merges from Beckers 1.08b version (VT6102 + mdio)
-                        set netif_running_on/off on startup, del_timer_sync
-
-       LK1.1.7:
-       - Manfred Spraul: added reset into tx_timeout
-
-       LK1.1.9:
-       - Urban Widmark: merges from Beckers 1.10 version
-                        (media selection + eeprom reload)
-       - David Vrabel:  merges from D-Link "1.11" version
-                        (disable WOL and PME on startup)
-
-       LK1.1.10:
-       - Manfred Spraul: use "singlecopy" for unaligned buffers
-                         don't allocate bounce buffers for !ReqTxAlign cards
-
-       LK1.1.11:
-       - David Woodhouse: Set dev->base_addr before the first time we call
-                          wait_for_reset(). It's a lot happier that way.
-                          Free np->tx_bufs only if we actually allocated it.
-
-       LK1.1.12:
-       - Martin Eriksson: Allow Memory-Mapped IO to be enabled.
-
-       LK1.1.13 (jgarzik):
-       - Add ethtool support
-       - Replace some MII-related magic numbers with constants
-
-       LK1.1.14 (Ivan G.):
-       - fixes comments for Rhine-III
-       - removes W_MAX_TIMEOUT (unused)
-       - adds HasDavicomPhy for Rhine-I (basis: linuxfet driver; my card
-         is R-I and has Davicom chip, flag is referenced in kernel driver)
-       - sends chip_id as a parameter to wait_for_reset since np is not
-         initialized on first call
-       - changes mmio "else if (chip_id==VT6102)" to "else" so it will work
-         for Rhine-III's (documentation says same bit is correct)
-       - transmit frame queue message is off by one - fixed
-       - adds IntrNormalSummary to "Something Wicked" exclusion list
-         so normal interrupts will not trigger the message (src: Donald Becker)
-       (Roger Luethi)
-       - show confused chip where to continue after Tx error
-       - location of collision counter is chip specific
-       - allow selecting backoff algorithm (module parameter)
-
-       LK1.1.15 (jgarzik):
-       - Use new MII lib helper generic_mii_ioctl
-
-       LK1.1.16 (Roger Luethi)
-       - Etherleak fix
-       - Handle Tx buffer underrun
-       - Fix bugs in full duplex handling
-       - New reset code uses "force reset" cmd on Rhine-II
-       - Various clean ups
-
-       LK1.1.17 (Roger Luethi)
-       - Fix race in via_rhine_start_tx()
-       - On errors, wait for Tx engine to turn off before scavenging
-       - Handle Tx descriptor write-back race on Rhine-II
-       - Force flushing for PCI posted writes
-       - More reset code changes
-
-       LK1.1.18 (Roger Luethi)
-       - No filtering multicast in promisc mode (Edward Peng)
-       - Fix for Rhine-I Tx timeouts
-
-       LK1.1.19 (Roger Luethi)
-       - Increase Tx threshold for unspecified errors
-
-       LK1.2.0-2.6 (Roger Luethi)
-       - Massive clean-up
-       - Rewrite PHY, media handling (remove options, full_duplex, backoff)
-       - Fix Tx engine race for good
+       [link no longer provides useful info -jgarzik]
 
 */
 
 #define DRV_NAME       "via-rhine"
 
 */
 
 #define DRV_NAME       "via-rhine"
-#define DRV_VERSION    "1.2.0-2.6"
-#define DRV_RELDATE    "June-10-2004"
+#define DRV_VERSION    "1.4.3"
+#define DRV_RELDATE    "2007-03-06"
 
 
 /* A few user-configurable values.
 
 
 /* A few user-configurable values.
@@ -145,7 +42,17 @@ static int max_interrupt_work = 20;
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
+#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) || \
+       defined(CONFIG_SPARC) || defined(__ia64__) ||              \
+       defined(__sh__) || defined(__mips__)
+static int rx_copybreak = 1518;
+#else
 static int rx_copybreak;
 static int rx_copybreak;
+#endif
+
+/* Work-around for broken BIOSes: they are unable to get the chip back out of
+   power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */
+static int avoid_D3;
 
 /*
  * In case you are looking for 'options[]' or 'full_duplex[]', they
 
 /*
  * In case you are looking for 'options[]' or 'full_duplex[]', they
@@ -166,8 +73,7 @@ static const int multicast_filter_limit = 32;
    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. */
    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   16
-
+#define RX_RING_SIZE   64
 
 /* Operational parameters that usually are not changed. */
 
 
 /* Operational parameters that usually are not changed. */
 
@@ -196,14 +102,17 @@ static const int multicast_filter_limit = 32;
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <linux/bitops.h>
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <linux/bitops.h>
+#include <linux/workqueue.h>
 #include <asm/processor.h>     /* Processor type for cache alignment. */
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>     /* Processor type for cache alignment. */
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
+#include <linux/dmi.h>
 
 /* These identify the driver base version and may not be removed. */
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
-KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n";
+static const char version[] __devinitconst =
+       KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE
+       " Written by Donald Becker\n";
 
 /* This driver was written to use PCI memory space. Some early versions
    of the Rhine may only work correctly with I/O space accesses. */
 
 /* This driver was written to use PCI memory space. Some early versions
    of the Rhine may only work correctly with I/O space accesses. */
@@ -219,9 +128,11 @@ MODULE_LICENSE("GPL");
 module_param(max_interrupt_work, int, 0);
 module_param(debug, int, 0);
 module_param(rx_copybreak, int, 0);
 module_param(max_interrupt_work, int, 0);
 module_param(debug, int, 0);
 module_param(rx_copybreak, int, 0);
+module_param(avoid_D3, bool, 0);
 MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
+MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
 
 /*
                Theory of Operation
 
 /*
                Theory of Operation
@@ -282,12 +193,13 @@ IIId. Synchronization
 
 The driver runs as two independent, single-threaded flows of control. One
 is the send-packet routine, which enforces single-threaded use by the
 
 The driver runs as two independent, single-threaded flows of control. One
 is the send-packet routine, which enforces single-threaded use by the
-dev->priv->lock spinlock. The other thread is the interrupt handler, which
-is single threaded by the hardware and interrupt handling software.
+netdev_priv(dev)->lock spinlock. The other thread is the interrupt handler,
+which is single threaded by the hardware and interrupt handling software.
 
 The send packet thread has partial control over the Tx ring. It locks the
 
 The send packet thread has partial control over the Tx ring. It locks the
-dev->priv->lock whenever it's queuing a Tx packet. If the next slot in the ring
-is not available it stops the transmit queue by calling netif_stop_queue.
+netdev_priv(dev)->lock whenever it's queuing a Tx packet. If the next slot in
+the ring is not available it stops the transmit queue by
+calling netif_stop_queue.
 
 The interrupt handler has exclusive control over the Rx ring and records stats
 from the Tx ring. After reaping the stats, it marks the Tx queue entry as
 
 The interrupt handler has exclusive control over the Rx ring and records stats
 from the Tx ring. After reaping the stats, it marks the Tx queue entry as
@@ -355,12 +267,11 @@ enum rhine_quirks {
 /* Beware of PCI posted writes */
 #define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0)
 
 /* Beware of PCI posted writes */
 #define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0)
 
-static struct pci_device_id rhine_pci_tbl[] =
-{
-       {0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT86C100A */
-       {0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6102 */
-       {0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* 6105{,L,LOM} */
-       {0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6105M */
+static DEFINE_PCI_DEVICE_TABLE(rhine_pci_tbl) = {
+       { 0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, },    /* VT86C100A */
+       { 0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, },    /* VT6102 */
+       { 0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, },    /* 6105{,L,LOM} */
+       { 0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, },    /* VT6105M */
        { }     /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);
        { }     /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);
@@ -422,16 +333,16 @@ enum wol_bits {
 
 /* The Rx and Tx buffer descriptors. */
 struct rx_desc {
 
 /* The Rx and Tx buffer descriptors. */
 struct rx_desc {
-       s32 rx_status;
-       u32 desc_length; /* Chain flag, Buffer/frame length */
-       u32 addr;
-       u32 next_desc;
+       __le32 rx_status;
+       __le32 desc_length; /* Chain flag, Buffer/frame length */
+       __le32 addr;
+       __le32 next_desc;
 };
 struct tx_desc {
 };
 struct tx_desc {
-       s32 tx_status;
-       u32 desc_length; /* Chain flag, Tx Config, Frame length */
-       u32 addr;
-       u32 next_desc;
+       __le32 tx_status;
+       __le32 desc_length; /* Chain flag, Tx Config, Frame length */
+       __le32 addr;
+       __le32 next_desc;
 };
 
 /* Initial value for tx_desc.desc_length, Buffer size goes to bits 0-10 */
 };
 
 /* Initial value for tx_desc.desc_length, Buffer size goes to bits 0-10 */
@@ -469,15 +380,17 @@ struct rhine_private {
        struct sk_buff *tx_skbuff[TX_RING_SIZE];
        dma_addr_t tx_skbuff_dma[TX_RING_SIZE];
 
        struct sk_buff *tx_skbuff[TX_RING_SIZE];
        dma_addr_t tx_skbuff_dma[TX_RING_SIZE];
 
-       /* Tx bounce buffers */
+       /* Tx bounce buffers (Rhine-I only) */
        unsigned char *tx_buf[TX_RING_SIZE];
        unsigned char *tx_bufs;
        dma_addr_t tx_bufs_dma;
 
        struct pci_dev *pdev;
        long pioaddr;
        unsigned char *tx_buf[TX_RING_SIZE];
        unsigned char *tx_bufs;
        dma_addr_t tx_bufs_dma;
 
        struct pci_dev *pdev;
        long pioaddr;
-       struct net_device_stats stats;
+       struct net_device *dev;
+       struct napi_struct napi;
        spinlock_t lock;
        spinlock_t lock;
+       struct work_struct reset_task;
 
        /* Frequently used values: keep some adjacent for cache effect. */
        u32 quirks;
 
        /* Frequently used values: keep some adjacent for cache effect. */
        u32 quirks;
@@ -496,18 +409,20 @@ struct rhine_private {
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  rhine_open(struct net_device *dev);
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  rhine_open(struct net_device *dev);
+static void rhine_reset_task(struct work_struct *work);
 static void rhine_tx_timeout(struct net_device *dev);
 static void rhine_tx_timeout(struct net_device *dev);
-static int  rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
+                                 struct net_device *dev);
+static irqreturn_t rhine_interrupt(int irq, void *dev_instance);
 static void rhine_tx(struct net_device *dev);
 static void rhine_tx(struct net_device *dev);
-static void rhine_rx(struct net_device *dev);
+static int rhine_rx(struct net_device *dev, int limit);
 static void rhine_error(struct net_device *dev, int intr_status);
 static void rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *rhine_get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void rhine_error(struct net_device *dev, int intr_status);
 static void rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *rhine_get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static struct ethtool_ops netdev_ethtool_ops;
+static const struct ethtool_ops netdev_ethtool_ops;
 static int  rhine_close(struct net_device *dev);
 static int  rhine_close(struct net_device *dev);
-static void rhine_shutdown (struct device *gdev);
+static void rhine_shutdown (struct pci_dev *pdev);
 
 #define RHINE_WAIT_FOR(condition) do {                                 \
        int i=1024;                                                     \
 
 #define RHINE_WAIT_FOR(condition) do {                                 \
        int i=1024;                                                     \
@@ -663,12 +578,33 @@ static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
 static void rhine_poll(struct net_device *dev)
 {
        disable_irq(dev->irq);
 static void rhine_poll(struct net_device *dev)
 {
        disable_irq(dev->irq);
-       rhine_interrupt(dev->irq, (void *)dev, NULL);
+       rhine_interrupt(dev->irq, (void *)dev);
        enable_irq(dev->irq);
 }
 #endif
 
        enable_irq(dev->irq);
 }
 #endif
 
-static void rhine_hw_init(struct net_device *dev, long pioaddr)
+static int rhine_napipoll(struct napi_struct *napi, int budget)
+{
+       struct rhine_private *rp = container_of(napi, struct rhine_private, napi);
+       struct net_device *dev = rp->dev;
+       void __iomem *ioaddr = rp->base;
+       int work_done;
+
+       work_done = rhine_rx(dev, budget);
+
+       if (work_done < budget) {
+               napi_complete(napi);
+
+               iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
+                         IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
+                         IntrTxDone | IntrTxError | IntrTxUnderrun |
+                         IntrPCIErr | IntrStatsMax | IntrLinkChange,
+                         ioaddr + IntrEnable);
+       }
+       return work_done;
+}
+
+static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr)
 {
        struct rhine_private *rp = netdev_priv(dev);
 
 {
        struct rhine_private *rp = netdev_priv(dev);
 
@@ -683,13 +619,28 @@ static void rhine_hw_init(struct net_device *dev, long pioaddr)
        rhine_reload_eeprom(pioaddr, dev);
 }
 
        rhine_reload_eeprom(pioaddr, dev);
 }
 
+static const struct net_device_ops rhine_netdev_ops = {
+       .ndo_open                = rhine_open,
+       .ndo_stop                = rhine_close,
+       .ndo_start_xmit          = rhine_start_tx,
+       .ndo_get_stats           = rhine_get_stats,
+       .ndo_set_multicast_list  = rhine_set_rx_mode,
+       .ndo_change_mtu          = eth_change_mtu,
+       .ndo_validate_addr       = eth_validate_addr,
+       .ndo_set_mac_address     = eth_mac_addr,
+       .ndo_do_ioctl            = netdev_ioctl,
+       .ndo_tx_timeout          = rhine_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller     = rhine_poll,
+#endif
+};
+
 static int __devinit rhine_init_one(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct rhine_private *rp;
        int i, rc;
 static int __devinit rhine_init_one(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct rhine_private *rp;
        int i, rc;
-       u8 pci_rev;
        u32 quirks;
        long pioaddr;
        long memaddr;
        u32 quirks;
        long pioaddr;
        long memaddr;
@@ -709,27 +660,25 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                printk(version);
 #endif
 
                printk(version);
 #endif
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
        io_size = 256;
        phy_id = 0;
        quirks = 0;
        name = "Rhine";
        io_size = 256;
        phy_id = 0;
        quirks = 0;
        name = "Rhine";
-       if (pci_rev < VTunknown0) {
+       if (pdev->revision < VTunknown0) {
                quirks = rqRhineI;
                io_size = 128;
        }
                quirks = rqRhineI;
                io_size = 128;
        }
-       else if (pci_rev >= VT6102) {
+       else if (pdev->revision >= VT6102) {
                quirks = rqWOL | rqForceReset;
                quirks = rqWOL | rqForceReset;
-               if (pci_rev < VT6105) {
+               if (pdev->revision < VT6105) {
                        name = "Rhine II";
                        quirks |= rqStatusWBRace;       /* Rhine-II exclusive */
                }
                else {
                        phy_id = 1;     /* Integrated PHY, phy_id fixed to 1 */
                        name = "Rhine II";
                        quirks |= rqStatusWBRace;       /* Rhine-II exclusive */
                }
                else {
                        phy_id = 1;     /* Integrated PHY, phy_id fixed to 1 */
-                       if (pci_rev >= VT6105_B0)
+                       if (pdev->revision >= VT6105_B0)
                                quirks |= rq6patterns;
                                quirks |= rq6patterns;
-                       if (pci_rev < VT6105M)
+                       if (pdev->revision < VT6105M)
                                name = "Rhine III";
                        else
                                name = "Rhine III (Management Adapter)";
                                name = "Rhine III";
                        else
                                name = "Rhine III (Management Adapter)";
@@ -741,7 +690,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                goto err_out;
 
        /* this should always be supported */
                goto err_out;
 
        /* this should always be supported */
-       rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if (rc) {
                printk(KERN_ERR "32-bit PCI DMA addresses not supported by "
                       "the card!?\n");
        if (rc) {
                printk(KERN_ERR "32-bit PCI DMA addresses not supported by "
                       "the card!?\n");
@@ -767,10 +716,10 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                printk(KERN_ERR "alloc_etherdev failed\n");
                goto err_out;
        }
                printk(KERN_ERR "alloc_etherdev failed\n");
                goto err_out;
        }
-       SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        rp = netdev_priv(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        rp = netdev_priv(dev);
+       rp->dev = dev;
        rp->quirks = quirks;
        rp->pioaddr = pioaddr;
        rp->pdev = pdev;
        rp->quirks = quirks;
        rp->pioaddr = pioaddr;
        rp->pdev = pdev;
@@ -814,8 +763,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 
        for (i = 0; i < 6; i++)
                dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
 
        for (i = 0; i < 6; i++)
                dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
 
-       if (!is_valid_ether_addr(dev->dev_addr)) {
+       if (!is_valid_ether_addr(dev->perm_addr)) {
                rc = -EIO;
                printk(KERN_ERR "Invalid MAC address\n");
                goto err_out_unmap;
                rc = -EIO;
                printk(KERN_ERR "Invalid MAC address\n");
                goto err_out_unmap;
@@ -828,6 +778,8 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        dev->irq = pdev->irq;
 
        spin_lock_init(&rp->lock);
        dev->irq = pdev->irq;
 
        spin_lock_init(&rp->lock);
+       INIT_WORK(&rp->reset_task, rhine_reset_task);
+
        rp->mii_if.dev = dev;
        rp->mii_if.mdio_read = mdio_read;
        rp->mii_if.mdio_write = mdio_write;
        rp->mii_if.dev = dev;
        rp->mii_if.mdio_read = mdio_read;
        rp->mii_if.mdio_write = mdio_write;
@@ -835,18 +787,12 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        rp->mii_if.reg_num_mask = 0x1f;
 
        /* The chip-specific entries in the device structure. */
        rp->mii_if.reg_num_mask = 0x1f;
 
        /* The chip-specific entries in the device structure. */
-       dev->open = rhine_open;
-       dev->hard_start_xmit = rhine_start_tx;
-       dev->stop = rhine_close;
-       dev->get_stats = rhine_get_stats;
-       dev->set_multicast_list = rhine_set_rx_mode;
-       dev->do_ioctl = netdev_ioctl;
-       dev->ethtool_ops = &netdev_ethtool_ops;
-       dev->tx_timeout = rhine_tx_timeout;
+       dev->netdev_ops = &rhine_netdev_ops;
+       dev->ethtool_ops = &netdev_ethtool_ops,
        dev->watchdog_timeo = TX_TIMEOUT;
        dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = rhine_poll;
-#endif
+
+       netif_napi_add(dev, &rp->napi, rhine_napipoll, 64);
+
        if (rp->quirks & rqRhineI)
                dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
        if (rp->quirks & rqRhineI)
                dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
@@ -855,18 +801,14 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        if (rc)
                goto err_out_unmap;
 
        if (rc)
                goto err_out_unmap;
 
-       printk(KERN_INFO "%s: VIA %s at 0x%lx, ",
+       printk(KERN_INFO "%s: VIA %s at 0x%lx, %pM, IRQ %d.\n",
               dev->name, name,
 #ifdef USE_MMIO
               dev->name, name,
 #ifdef USE_MMIO
-               memaddr
+              memaddr,
 #else
 #else
-               (long)ioaddr
+              (long)ioaddr,
 #endif
 #endif
-                );
-
-       for (i = 0; i < 5; i++)
-               printk("%2.2x:", dev->dev_addr[i]);
-       printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], pdev->irq);
+              dev->dev_addr, pdev->irq);
 
        pci_set_drvdata(pdev, dev);
 
 
        pci_set_drvdata(pdev, dev);
 
@@ -892,6 +834,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                }
        }
        rp->mii_if.phy_id = phy_id;
                }
        }
        rp->mii_if.phy_id = phy_id;
+       if (debug > 1 && avoid_D3)
+               printk(KERN_INFO "%s: No D3 power state at shutdown.\n",
+                      dev->name);
 
        return 0;
 
 
        return 0;
 
@@ -983,14 +928,14 @@ static void alloc_rbufs(struct net_device *dev)
 
        /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
        for (i = 0; i < RX_RING_SIZE; i++) {
 
        /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
        for (i = 0; i < RX_RING_SIZE; i++) {
-               struct sk_buff *skb = dev_alloc_skb(rp->rx_buf_sz);
+               struct sk_buff *skb = netdev_alloc_skb(dev, rp->rx_buf_sz);
                rp->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
                skb->dev = dev;                 /* Mark as being used by this device. */
 
                rp->rx_skbuff_dma[i] =
                rp->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
                skb->dev = dev;                 /* Mark as being used by this device. */
 
                rp->rx_skbuff_dma[i] =
-                       pci_map_single(rp->pdev, skb->tail, rp->rx_buf_sz,
+                       pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz,
                                       PCI_DMA_FROMDEVICE);
 
                rp->rx_ring[i].addr = cpu_to_le32(rp->rx_skbuff_dma[i]);
                                       PCI_DMA_FROMDEVICE);
 
                rp->rx_ring[i].addr = cpu_to_le32(rp->rx_skbuff_dma[i]);
@@ -1032,7 +977,8 @@ static void alloc_tbufs(struct net_device* dev)
                rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC);
                next += sizeof(struct tx_desc);
                rp->tx_ring[i].next_desc = cpu_to_le32(next);
                rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC);
                next += sizeof(struct tx_desc);
                rp->tx_ring[i].next_desc = cpu_to_le32(next);
-               rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
+               if (rp->quirks & rqRhineI)
+                       rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
        }
        rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma);
 
        }
        rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma);
 
@@ -1074,6 +1020,25 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
        else
            iowrite8(ioread8(ioaddr + ChipCmd1) & ~Cmd1FDuplex,
                   ioaddr + ChipCmd1);
        else
            iowrite8(ioread8(ioaddr + ChipCmd1) & ~Cmd1FDuplex,
                   ioaddr + ChipCmd1);
+       if (debug > 1)
+               printk(KERN_INFO "%s: force_media %d, carrier %d\n", dev->name,
+                       rp->mii_if.force_media, netif_carrier_ok(dev));
+}
+
+/* Called after status of force_media possibly changed */
+static void rhine_set_carrier(struct mii_if_info *mii)
+{
+       if (mii->force_media) {
+               /* autoneg is off: Link is always assumed to be up */
+               if (!netif_carrier_ok(mii->dev))
+                       netif_carrier_on(mii->dev);
+       }
+       else    /* Let MMI library update carrier status */
+               rhine_check_media(mii->dev, 0);
+       if (debug > 1)
+               printk(KERN_INFO "%s: force_media %d, carrier %d\n",
+                      mii->dev->name, mii->force_media,
+                      netif_carrier_ok(mii->dev));
 }
 
 static void init_registers(struct net_device *dev)
 }
 
 static void init_registers(struct net_device *dev)
@@ -1097,6 +1062,8 @@ static void init_registers(struct net_device *dev)
 
        rhine_set_rx_mode(dev);
 
 
        rhine_set_rx_mode(dev);
 
+       napi_enable(&rp->napi);
+
        /* Enable interrupts by setting the interrupt mask. */
        iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
               IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
        /* Enable interrupts by setting the interrupt mask. */
        iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
               IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
@@ -1188,7 +1155,7 @@ static int rhine_open(struct net_device *dev)
        void __iomem *ioaddr = rp->base;
        int rc;
 
        void __iomem *ioaddr = rp->base;
        int rc;
 
-       rc = request_irq(rp->pdev->irq, &rhine_interrupt, SA_SHIRQ, dev->name,
+       rc = request_irq(rp->pdev->irq, rhine_interrupt, IRQF_SHARED, dev->name,
                        dev);
        if (rc)
                return rc;
                        dev);
        if (rc)
                return rc;
@@ -1217,20 +1184,18 @@ static int rhine_open(struct net_device *dev)
        return 0;
 }
 
        return 0;
 }
 
-static void rhine_tx_timeout(struct net_device *dev)
+static void rhine_reset_task(struct work_struct *work)
 {
 {
-       struct rhine_private *rp = netdev_priv(dev);
-       void __iomem *ioaddr = rp->base;
-
-       printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
-              "%4.4x, resetting...\n",
-              dev->name, ioread16(ioaddr + IntrStatus),
-              mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
+       struct rhine_private *rp = container_of(work, struct rhine_private,
+                                               reset_task);
+       struct net_device *dev = rp->dev;
 
        /* protect against concurrent rx interrupts */
        disable_irq(rp->pdev->irq);
 
 
        /* protect against concurrent rx interrupts */
        disable_irq(rp->pdev->irq);
 
-       spin_lock(&rp->lock);
+       napi_disable(&rp->napi);
+
+       spin_lock_bh(&rp->lock);
 
        /* clear all descriptors */
        free_tbufs(dev);
 
        /* clear all descriptors */
        free_tbufs(dev);
@@ -1242,19 +1207,34 @@ static void rhine_tx_timeout(struct net_device *dev)
        rhine_chip_reset(dev);
        init_registers(dev);
 
        rhine_chip_reset(dev);
        init_registers(dev);
 
-       spin_unlock(&rp->lock);
+       spin_unlock_bh(&rp->lock);
        enable_irq(rp->pdev->irq);
 
        dev->trans_start = jiffies;
        enable_irq(rp->pdev->irq);
 
        dev->trans_start = jiffies;
-       rp->stats.tx_errors++;
+       dev->stats.tx_errors++;
        netif_wake_queue(dev);
 }
 
        netif_wake_queue(dev);
 }
 
-static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
+static void rhine_tx_timeout(struct net_device *dev)
+{
+       struct rhine_private *rp = netdev_priv(dev);
+       void __iomem *ioaddr = rp->base;
+
+       printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
+              "%4.4x, resetting...\n",
+              dev->name, ioread16(ioaddr + IntrStatus),
+              mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
+
+       schedule_work(&rp->reset_task);
+}
+
+static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
+                                 struct net_device *dev)
 {
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
        unsigned entry;
 {
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
        unsigned entry;
+       unsigned long flags;
 
        /* Caution: the write order is important here, set the field
           with the "ownership" bits last. */
 
        /* Caution: the write order is important here, set the field
           with the "ownership" bits last. */
@@ -1262,25 +1242,27 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
        /* Calculate the next Tx descriptor entry. */
        entry = rp->cur_tx % TX_RING_SIZE;
 
        /* Calculate the next Tx descriptor entry. */
        entry = rp->cur_tx % TX_RING_SIZE;
 
-       if (skb->len < ETH_ZLEN) {
-               skb = skb_padto(skb, ETH_ZLEN);
-               if (skb == NULL)
-                       return 0;
-       }
+       if (skb_padto(skb, ETH_ZLEN))
+               return NETDEV_TX_OK;
 
        rp->tx_skbuff[entry] = skb;
 
        if ((rp->quirks & rqRhineI) &&
 
        rp->tx_skbuff[entry] = skb;
 
        if ((rp->quirks & rqRhineI) &&
-           (((unsigned long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW)) {
+           (((unsigned long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_PARTIAL)) {
                /* Must use alignment buffer. */
                if (skb->len > PKT_BUF_SZ) {
                        /* packet too long, drop it */
                        dev_kfree_skb(skb);
                        rp->tx_skbuff[entry] = NULL;
                /* Must use alignment buffer. */
                if (skb->len > PKT_BUF_SZ) {
                        /* packet too long, drop it */
                        dev_kfree_skb(skb);
                        rp->tx_skbuff[entry] = NULL;
-                       rp->stats.tx_dropped++;
-                       return 0;
+                       dev->stats.tx_dropped++;
+                       return NETDEV_TX_OK;
                }
                }
+
+               /* Padding is not copied and so must be redone. */
                skb_copy_and_csum_dev(skb, rp->tx_buf[entry]);
                skb_copy_and_csum_dev(skb, rp->tx_buf[entry]);
+               if (skb->len < ETH_ZLEN)
+                       memset(rp->tx_buf[entry] + skb->len, 0,
+                              ETH_ZLEN - skb->len);
                rp->tx_skbuff_dma[entry] = 0;
                rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_bufs_dma +
                                                      (rp->tx_buf[entry] -
                rp->tx_skbuff_dma[entry] = 0;
                rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_bufs_dma +
                                                      (rp->tx_buf[entry] -
@@ -1296,7 +1278,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
                cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
        /* lock eth irq */
                cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
        /* lock eth irq */
-       spin_lock_irq(&rp->lock);
+       spin_lock_irqsave(&rp->lock, flags);
        wmb();
        rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
        wmb();
        wmb();
        rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
        wmb();
@@ -1315,18 +1297,18 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
 
        dev->trans_start = jiffies;
 
 
        dev->trans_start = jiffies;
 
-       spin_unlock_irq(&rp->lock);
+       spin_unlock_irqrestore(&rp->lock, flags);
 
        if (debug > 4) {
                printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
                       dev->name, rp->cur_tx-1, entry);
        }
 
        if (debug > 4) {
                printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
                       dev->name, rp->cur_tx-1, entry);
        }
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
 {
        struct net_device *dev = dev_instance;
        struct rhine_private *rp = netdev_priv(dev);
 {
        struct net_device *dev = dev_instance;
        struct rhine_private *rp = netdev_priv(dev);
@@ -1349,8 +1331,14 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *
                               dev->name, intr_status);
 
                if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
                               dev->name, intr_status);
 
                if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
-                   IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf))
-                       rhine_rx(dev);
+                                  IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
+                       iowrite16(IntrTxAborted |
+                                 IntrTxDone | IntrTxError | IntrTxUnderrun |
+                                 IntrPCIErr | IntrStatsMax | IntrLinkChange,
+                                 ioaddr + IntrEnable);
+
+                       napi_schedule(&rp->napi);
+               }
 
                if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
                        if (intr_status & IntrTxErrSummary) {
 
                if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
                        if (intr_status & IntrTxErrSummary) {
@@ -1359,7 +1347,7 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *
                                if (debug > 2 &&
                                    ioread8(ioaddr+ChipCmd) & CmdTxOn)
                                        printk(KERN_WARNING "%s: "
                                if (debug > 2 &&
                                    ioread8(ioaddr+ChipCmd) & CmdTxOn)
                                        printk(KERN_WARNING "%s: "
-                                              "rhine_interrupt() Tx engine"
+                                              "rhine_interrupt() Tx engine "
                                               "still on.\n", dev->name);
                        }
                        rhine_tx(dev);
                                               "still on.\n", dev->name);
                        }
                        rhine_tx(dev);
@@ -1407,29 +1395,33 @@ static void rhine_tx(struct net_device *dev)
                                printk(KERN_DEBUG "%s: Transmit error, "
                                       "Tx status %8.8x.\n",
                                       dev->name, txstatus);
                                printk(KERN_DEBUG "%s: Transmit error, "
                                       "Tx status %8.8x.\n",
                                       dev->name, txstatus);
-                       rp->stats.tx_errors++;
-                       if (txstatus & 0x0400) rp->stats.tx_carrier_errors++;
-                       if (txstatus & 0x0200) rp->stats.tx_window_errors++;
-                       if (txstatus & 0x0100) rp->stats.tx_aborted_errors++;
-                       if (txstatus & 0x0080) rp->stats.tx_heartbeat_errors++;
+                       dev->stats.tx_errors++;
+                       if (txstatus & 0x0400)
+                               dev->stats.tx_carrier_errors++;
+                       if (txstatus & 0x0200)
+                               dev->stats.tx_window_errors++;
+                       if (txstatus & 0x0100)
+                               dev->stats.tx_aborted_errors++;
+                       if (txstatus & 0x0080)
+                               dev->stats.tx_heartbeat_errors++;
                        if (((rp->quirks & rqRhineI) && txstatus & 0x0002) ||
                            (txstatus & 0x0800) || (txstatus & 0x1000)) {
                        if (((rp->quirks & rqRhineI) && txstatus & 0x0002) ||
                            (txstatus & 0x0800) || (txstatus & 0x1000)) {
-                               rp->stats.tx_fifo_errors++;
+                               dev->stats.tx_fifo_errors++;
                                rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
                                break; /* Keep the skb - we try again */
                        }
                        /* Transmitter restarted in 'abnormal' handler. */
                } else {
                        if (rp->quirks & rqRhineI)
                                rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
                                break; /* Keep the skb - we try again */
                        }
                        /* Transmitter restarted in 'abnormal' handler. */
                } else {
                        if (rp->quirks & rqRhineI)
-                               rp->stats.collisions += (txstatus >> 3) & 0x0F;
+                               dev->stats.collisions += (txstatus >> 3) & 0x0F;
                        else
                        else
-                               rp->stats.collisions += txstatus & 0x0F;
+                               dev->stats.collisions += txstatus & 0x0F;
                        if (debug > 6)
                                printk(KERN_DEBUG "collisions: %1.1x:%1.1x\n",
                                       (txstatus >> 3) & 0xF,
                                       txstatus & 0xF);
                        if (debug > 6)
                                printk(KERN_DEBUG "collisions: %1.1x:%1.1x\n",
                                       (txstatus >> 3) & 0xF,
                                       txstatus & 0xF);
-                       rp->stats.tx_bytes += rp->tx_skbuff[entry]->len;
-                       rp->stats.tx_packets++;
+                       dev->stats.tx_bytes += rp->tx_skbuff[entry]->len;
+                       dev->stats.tx_packets++;
                }
                /* Free the original skb. */
                if (rp->tx_skbuff_dma[entry]) {
                }
                /* Free the original skb. */
                if (rp->tx_skbuff_dma[entry]) {
@@ -1448,13 +1440,12 @@ static void rhine_tx(struct net_device *dev)
        spin_unlock(&rp->lock);
 }
 
        spin_unlock(&rp->lock);
 }
 
-/* This routine is logically part of the interrupt handler, but isolated
-   for clarity and better register allocation. */
-static void rhine_rx(struct net_device *dev)
+/* Process up to limit frames from receive ring */
+static int rhine_rx(struct net_device *dev, int limit)
 {
        struct rhine_private *rp = netdev_priv(dev);
 {
        struct rhine_private *rp = netdev_priv(dev);
+       int count;
        int entry = rp->cur_rx % RX_RING_SIZE;
        int entry = rp->cur_rx % RX_RING_SIZE;
-       int boguscnt = rp->dirty_rx + RX_RING_SIZE - rp->cur_rx;
 
        if (debug > 4) {
                printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n",
 
        if (debug > 4) {
                printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n",
@@ -1463,16 +1454,18 @@ static void rhine_rx(struct net_device *dev)
        }
 
        /* If EOP is set on the next entry, it's a new packet. Send it up. */
        }
 
        /* If EOP is set on the next entry, it's a new packet. Send it up. */
-       while (!(rp->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) {
+       for (count = 0; count < limit; ++count) {
                struct rx_desc *desc = rp->rx_head_desc;
                u32 desc_status = le32_to_cpu(desc->rx_status);
                int data_size = desc_status >> 16;
 
                struct rx_desc *desc = rp->rx_head_desc;
                u32 desc_status = le32_to_cpu(desc->rx_status);
                int data_size = desc_status >> 16;
 
+               if (desc_status & DescOwn)
+                       break;
+
                if (debug > 4)
                        printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n",
                               desc_status);
                if (debug > 4)
                        printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n",
                               desc_status);
-               if (--boguscnt < 0)
-                       break;
+
                if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) {
                        if ((desc_status & RxWholePkt) != RxWholePkt) {
                                printk(KERN_WARNING "%s: Oversized Ethernet "
                if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) {
                        if ((desc_status & RxWholePkt) != RxWholePkt) {
                                printk(KERN_WARNING "%s: Oversized Ethernet "
@@ -1483,43 +1476,45 @@ static void rhine_rx(struct net_device *dev)
                                printk(KERN_WARNING "%s: Oversized Ethernet "
                                       "frame %p vs %p.\n", dev->name,
                                       rp->rx_head_desc, &rp->rx_ring[entry]);
                                printk(KERN_WARNING "%s: Oversized Ethernet "
                                       "frame %p vs %p.\n", dev->name,
                                       rp->rx_head_desc, &rp->rx_ring[entry]);
-                               rp->stats.rx_length_errors++;
+                               dev->stats.rx_length_errors++;
                        } else if (desc_status & RxErr) {
                                /* There was a error. */
                                if (debug > 2)
                                        printk(KERN_DEBUG "rhine_rx() Rx "
                                               "error was %8.8x.\n",
                                               desc_status);
                        } else if (desc_status & RxErr) {
                                /* There was a error. */
                                if (debug > 2)
                                        printk(KERN_DEBUG "rhine_rx() Rx "
                                               "error was %8.8x.\n",
                                               desc_status);
-                               rp->stats.rx_errors++;
-                               if (desc_status & 0x0030) rp->stats.rx_length_errors++;
-                               if (desc_status & 0x0048) rp->stats.rx_fifo_errors++;
-                               if (desc_status & 0x0004) rp->stats.rx_frame_errors++;
+                               dev->stats.rx_errors++;
+                               if (desc_status & 0x0030)
+                                       dev->stats.rx_length_errors++;
+                               if (desc_status & 0x0048)
+                                       dev->stats.rx_fifo_errors++;
+                               if (desc_status & 0x0004)
+                                       dev->stats.rx_frame_errors++;
                                if (desc_status & 0x0002) {
                                        /* this can also be updated outside the interrupt handler */
                                        spin_lock(&rp->lock);
                                if (desc_status & 0x0002) {
                                        /* this can also be updated outside the interrupt handler */
                                        spin_lock(&rp->lock);
-                                       rp->stats.rx_crc_errors++;
+                                       dev->stats.rx_crc_errors++;
                                        spin_unlock(&rp->lock);
                                }
                        }
                } else {
                                        spin_unlock(&rp->lock);
                                }
                        }
                } else {
-                       struct sk_buff *skb;
+                       struct sk_buff *skb = NULL;
                        /* Length should omit the CRC */
                        int pkt_len = data_size - 4;
 
                        /* Check if the packet is long enough to accept without
                           copying to a minimally-sized skbuff. */
                        /* Length should omit the CRC */
                        int pkt_len = data_size - 4;
 
                        /* Check if the packet is long enough to accept without
                           copying to a minimally-sized skbuff. */
-                       if (pkt_len < rx_copybreak &&
-                               (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
-                               skb->dev = dev;
-                               skb_reserve(skb, 2);    /* 16 byte align the IP header */
+                       if (pkt_len < rx_copybreak)
+                               skb = netdev_alloc_skb_ip_align(dev, pkt_len);
+                       if (skb) {
                                pci_dma_sync_single_for_cpu(rp->pdev,
                                                            rp->rx_skbuff_dma[entry],
                                                            rp->rx_buf_sz,
                                                            PCI_DMA_FROMDEVICE);
 
                                pci_dma_sync_single_for_cpu(rp->pdev,
                                                            rp->rx_skbuff_dma[entry],
                                                            rp->rx_buf_sz,
                                                            PCI_DMA_FROMDEVICE);
 
-                               eth_copy_and_sum(skb,
-                                                rp->rx_skbuff[entry]->tail,
-                                                pkt_len, 0);
+                               skb_copy_to_linear_data(skb,
+                                                rp->rx_skbuff[entry]->data,
+                                                pkt_len);
                                skb_put(skb, pkt_len);
                                pci_dma_sync_single_for_device(rp->pdev,
                                                               rp->rx_skbuff_dma[entry],
                                skb_put(skb, pkt_len);
                                pci_dma_sync_single_for_device(rp->pdev,
                                                               rp->rx_skbuff_dma[entry],
@@ -1541,10 +1536,9 @@ static void rhine_rx(struct net_device *dev)
                                                 PCI_DMA_FROMDEVICE);
                        }
                        skb->protocol = eth_type_trans(skb, dev);
                                                 PCI_DMA_FROMDEVICE);
                        }
                        skb->protocol = eth_type_trans(skb, dev);
-                       netif_rx(skb);
-                       dev->last_rx = jiffies;
-                       rp->stats.rx_bytes += pkt_len;
-                       rp->stats.rx_packets++;
+                       netif_receive_skb(skb);
+                       dev->stats.rx_bytes += pkt_len;
+                       dev->stats.rx_packets++;
                }
                entry = (++rp->cur_rx) % RX_RING_SIZE;
                rp->rx_head_desc = &rp->rx_ring[entry];
                }
                entry = (++rp->cur_rx) % RX_RING_SIZE;
                rp->rx_head_desc = &rp->rx_ring[entry];
@@ -1555,19 +1549,21 @@ static void rhine_rx(struct net_device *dev)
                struct sk_buff *skb;
                entry = rp->dirty_rx % RX_RING_SIZE;
                if (rp->rx_skbuff[entry] == NULL) {
                struct sk_buff *skb;
                entry = rp->dirty_rx % RX_RING_SIZE;
                if (rp->rx_skbuff[entry] == NULL) {
-                       skb = dev_alloc_skb(rp->rx_buf_sz);
+                       skb = netdev_alloc_skb(dev, rp->rx_buf_sz);
                        rp->rx_skbuff[entry] = skb;
                        if (skb == NULL)
                                break;  /* Better luck next round. */
                        skb->dev = dev; /* Mark as being used by this device. */
                        rp->rx_skbuff_dma[entry] =
                        rp->rx_skbuff[entry] = skb;
                        if (skb == NULL)
                                break;  /* Better luck next round. */
                        skb->dev = dev; /* Mark as being used by this device. */
                        rp->rx_skbuff_dma[entry] =
-                               pci_map_single(rp->pdev, skb->tail,
+                               pci_map_single(rp->pdev, skb->data,
                                               rp->rx_buf_sz,
                                               PCI_DMA_FROMDEVICE);
                        rp->rx_ring[entry].addr = cpu_to_le32(rp->rx_skbuff_dma[entry]);
                }
                rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
        }
                                               rp->rx_buf_sz,
                                               PCI_DMA_FROMDEVICE);
                        rp->rx_ring[entry].addr = cpu_to_le32(rp->rx_skbuff_dma[entry]);
                }
                rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
        }
+
+       return count;
 }
 
 /*
 }
 
 /*
@@ -1627,8 +1623,8 @@ static void rhine_error(struct net_device *dev, int intr_status)
        if (intr_status & IntrLinkChange)
                rhine_check_media(dev, 0);
        if (intr_status & IntrStatsMax) {
        if (intr_status & IntrLinkChange)
                rhine_check_media(dev, 0);
        if (intr_status & IntrStatsMax) {
-               rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
-               rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
+               dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
+               dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
                clear_tally_counters(ioaddr);
        }
        if (intr_status & IntrTxAborted) {
                clear_tally_counters(ioaddr);
        }
        if (intr_status & IntrTxAborted) {
@@ -1682,12 +1678,12 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev)
        unsigned long flags;
 
        spin_lock_irqsave(&rp->lock, flags);
        unsigned long flags;
 
        spin_lock_irqsave(&rp->lock, flags);
-       rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
-       rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
+       dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
+       dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
        clear_tally_counters(ioaddr);
        spin_unlock_irqrestore(&rp->lock, flags);
 
        clear_tally_counters(ioaddr);
        spin_unlock_irqrestore(&rp->lock, flags);
 
-       return &rp->stats;
+       return &dev->stats;
 }
 
 static void rhine_set_rx_mode(struct net_device *dev)
 }
 
 static void rhine_set_rx_mode(struct net_device *dev)
@@ -1698,14 +1694,11 @@ static void rhine_set_rx_mode(struct net_device *dev)
        u8 rx_mode;             /* Note: 0x02=accept runt, 0x01=accept errs */
 
        if (dev->flags & IFF_PROMISC) {         /* Set promiscuous. */
        u8 rx_mode;             /* Note: 0x02=accept runt, 0x01=accept errs */
 
        if (dev->flags & IFF_PROMISC) {         /* Set promiscuous. */
-               /* Unconditionally log net taps. */
-               printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-                      dev->name);
                rx_mode = 0x1C;
                iowrite32(0xffffffff, ioaddr + MulticastFilter0);
                iowrite32(0xffffffff, ioaddr + MulticastFilter1);
                rx_mode = 0x1C;
                iowrite32(0xffffffff, ioaddr + MulticastFilter0);
                iowrite32(0xffffffff, ioaddr + MulticastFilter1);
-       } else if ((dev->mc_count > multicast_filter_limit)
-                  || (dev->flags & IFF_ALLMULTI)) {
+       } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
+                  (dev->flags & IFF_ALLMULTI)) {
                /* Too many to match, or accept all multicasts. */
                iowrite32(0xffffffff, ioaddr + MulticastFilter0);
                iowrite32(0xffffffff, ioaddr + MulticastFilter1);
                /* Too many to match, or accept all multicasts. */
                iowrite32(0xffffffff, ioaddr + MulticastFilter0);
                iowrite32(0xffffffff, ioaddr + MulticastFilter1);
@@ -1714,7 +1707,8 @@ static void rhine_set_rx_mode(struct net_device *dev)
                struct dev_mc_list *mclist;
                int i;
                memset(mc_filter, 0, sizeof(mc_filter));
                struct dev_mc_list *mclist;
                int i;
                memset(mc_filter, 0, sizeof(mc_filter));
-               for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+               for (i = 0, mclist = dev->mc_list;
+                    mclist && i < netdev_mc_count(dev);
                     i++, mclist = mclist->next) {
                        int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
 
                     i++, mclist = mclist->next) {
                        int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
 
@@ -1756,6 +1750,7 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        spin_lock_irq(&rp->lock);
        rc = mii_ethtool_sset(&rp->mii_if, cmd);
        spin_unlock_irq(&rp->lock);
        spin_lock_irq(&rp->lock);
        rc = mii_ethtool_sset(&rp->mii_if, cmd);
        spin_unlock_irq(&rp->lock);
+       rhine_set_carrier(&rp->mii_if);
 
        return rc;
 }
 
        return rc;
 }
@@ -1817,7 +1812,7 @@ static int rhine_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        return 0;
 }
 
        return 0;
 }
 
-static struct ethtool_ops netdev_ethtool_ops = {
+static const struct ethtool_ops netdev_ethtool_ops = {
        .get_drvinfo            = netdev_get_drvinfo,
        .get_settings           = netdev_get_settings,
        .set_settings           = netdev_set_settings,
        .get_drvinfo            = netdev_get_drvinfo,
        .get_settings           = netdev_get_settings,
        .set_settings           = netdev_set_settings,
@@ -1827,8 +1822,6 @@ static struct ethtool_ops netdev_ethtool_ops = {
        .set_msglevel           = netdev_set_msglevel,
        .get_wol                = rhine_get_wol,
        .set_wol                = rhine_set_wol,
        .set_msglevel           = netdev_set_msglevel,
        .get_wol                = rhine_get_wol,
        .set_wol                = rhine_set_wol,
-       .get_sg                 = ethtool_op_get_sg,
-       .get_tx_csum            = ethtool_op_get_tx_csum,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1842,6 +1835,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        spin_lock_irq(&rp->lock);
        rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL);
        spin_unlock_irq(&rp->lock);
        spin_lock_irq(&rp->lock);
        rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL);
        spin_unlock_irq(&rp->lock);
+       rhine_set_carrier(&rp->mii_if);
 
        return rc;
 }
 
        return rc;
 }
@@ -1851,10 +1845,12 @@ static int rhine_close(struct net_device *dev)
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
 
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
 
-       spin_lock_irq(&rp->lock);
-
+       napi_disable(&rp->napi);
+       cancel_work_sync(&rp->reset_task);
        netif_stop_queue(dev);
 
        netif_stop_queue(dev);
 
+       spin_lock_irq(&rp->lock);
+
        if (debug > 1)
                printk(KERN_DEBUG "%s: Shutting down ethercard, "
                       "status was %4.4x.\n",
        if (debug > 1)
                printk(KERN_DEBUG "%s: Shutting down ethercard, "
                       "status was %4.4x.\n",
@@ -1895,9 +1891,8 @@ static void __devexit rhine_remove_one(struct pci_dev *pdev)
        pci_set_drvdata(pdev, NULL);
 }
 
        pci_set_drvdata(pdev, NULL);
 }
 
-static void rhine_shutdown (struct device *gendev)
+static void rhine_shutdown (struct pci_dev *pdev)
 {
 {
-       struct pci_dev *pdev = to_pci_dev(gendev);
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
@@ -1909,7 +1904,7 @@ static void rhine_shutdown (struct device *gendev)
 
        /* Make sure we use pattern 0, 1 and not 4, 5 */
        if (rp->quirks & rq6patterns)
 
        /* Make sure we use pattern 0, 1 and not 4, 5 */
        if (rp->quirks & rq6patterns)
-               iowrite8(0x04, ioaddr + 0xA7);
+               iowrite8(0x04, ioaddr + WOLcgClr);
 
        if (rp->wolopts & WAKE_MAGIC) {
                iowrite8(WOLmagic, ioaddr + WOLcrSet);
 
        if (rp->wolopts & WAKE_MAGIC) {
                iowrite8(WOLmagic, ioaddr + WOLcrSet);
@@ -1936,7 +1931,8 @@ static void rhine_shutdown (struct device *gendev)
        }
 
        /* Hit power state D3 (sleep) */
        }
 
        /* Hit power state D3 (sleep) */
-       iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
+       if (!avoid_D3)
+               iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
 
        /* TODO: Check use of pci_enable_wake() */
 
 
        /* TODO: Check use of pci_enable_wake() */
 
@@ -1952,11 +1948,13 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
        if (!netif_running(dev))
                return 0;
 
        if (!netif_running(dev))
                return 0;
 
+       napi_disable(&rp->napi);
+
        netif_device_detach(dev);
        pci_save_state(pdev);
 
        spin_lock_irqsave(&rp->lock, flags);
        netif_device_detach(dev);
        pci_save_state(pdev);
 
        spin_lock_irqsave(&rp->lock, flags);
-       rhine_shutdown(&pdev->dev);
+       rhine_shutdown(pdev);
        spin_unlock_irqrestore(&rp->lock, flags);
 
        free_irq(dev->irq, dev);
        spin_unlock_irqrestore(&rp->lock, flags);
 
        free_irq(dev->irq, dev);
@@ -1973,7 +1971,7 @@ static int rhine_resume(struct pci_dev *pdev)
        if (!netif_running(dev))
                return 0;
 
        if (!netif_running(dev))
                return 0;
 
-        if (request_irq(dev->irq, rhine_interrupt, SA_SHIRQ, dev->name, dev))
+        if (request_irq(dev->irq, rhine_interrupt, IRQF_SHARED, dev->name, dev))
                printk(KERN_ERR "via-rhine %s: request_irq failed\n", dev->name);
 
        ret = pci_set_power_state(pdev, PCI_D0);
                printk(KERN_ERR "via-rhine %s: request_irq failed\n", dev->name);
 
        ret = pci_set_power_state(pdev, PCI_D0);
@@ -2010,11 +2008,26 @@ static struct pci_driver rhine_driver = {
        .suspend        = rhine_suspend,
        .resume         = rhine_resume,
 #endif /* CONFIG_PM */
        .suspend        = rhine_suspend,
        .resume         = rhine_resume,
 #endif /* CONFIG_PM */
-       .driver = {
-               .shutdown = rhine_shutdown,
-       }
+       .shutdown =     rhine_shutdown,
 };
 
 };
 
+static struct dmi_system_id __initdata rhine_dmi_table[] = {
+       {
+               .ident = "EPIA-M",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
+                       DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+               },
+       },
+       {
+               .ident = "KV7",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+               },
+       },
+       { NULL }
+};
 
 static int __init rhine_init(void)
 {
 
 static int __init rhine_init(void)
 {
@@ -2022,7 +2035,17 @@ static int __init rhine_init(void)
 #ifdef MODULE
        printk(version);
 #endif
 #ifdef MODULE
        printk(version);
 #endif
-       return pci_module_init(&rhine_driver);
+       if (dmi_check_system(rhine_dmi_table)) {
+               /* these BIOSes fail at PXE boot if chip is in D3 */
+               avoid_D3 = 1;
+               printk(KERN_WARNING "%s: Broken BIOS detected, avoid_D3 "
+                                   "enabled.\n",
+                      DRV_NAME);
+       }
+       else if (avoid_D3)
+               printk(KERN_INFO "%s: avoid_D3 set.\n", DRV_NAME);
+
+       return pci_register_driver(&rhine_driver);
 }
 
 
 }