EMAC driver: define MDC_CLK=2.5MHz and caculate mdc_div according to SCLK.
[safe/jmp/linux-2.6] / drivers / net / forcedeth.c
index ae4e6f9..3634223 100644 (file)
@@ -13,7 +13,7 @@
  * Copyright (C) 2004 Andrew de Quincey (wol support)
  * Copyright (C) 2004 Carl-Daniel Hailfinger (invalid MAC handling, insane
  *             IRQ rate fixes, bigendian fixes, cleanups, verification)
- * Copyright (c) 2004,5,6 NVIDIA Corporation
+ * Copyright (c) 2004,2005,2006,2007,2008 NVIDIA Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #else
 #define DRIVERNAPI
 #endif
-#define FORCEDETH_VERSION              "0.60"
+#define FORCEDETH_VERSION              "0.61"
 #define DRV_NAME                       "forcedeth"
 
 #include <linux/module.h>
 #define dprintk(x...)          do { } while (0)
 #endif
 
+#define TX_WORK_PER_LOOP  64
+#define RX_WORK_PER_LOOP  64
 
 /*
  * Hardware access:
 #define DEV_HAS_STATISTICS_V2   0x0800  /* device supports hw statistics version 2 */
 #define DEV_HAS_TEST_EXTENDED   0x1000  /* device supports extended diagnostic test */
 #define DEV_HAS_MGMT_UNIT       0x2000  /* device supports management unit */
+#define DEV_HAS_CORRECT_MACADDR 0x4000  /* device supports correct mac address order */
 
 enum {
        NvRegIrqStatus = 0x000,
@@ -195,7 +198,7 @@ enum {
 #define NVREG_IRQ_TX_FORCED            0x0100
 #define NVREG_IRQ_RECOVER_ERROR                0x8000
 #define NVREG_IRQMASK_THROUGHPUT       0x00df
-#define NVREG_IRQMASK_CPU              0x0040
+#define NVREG_IRQMASK_CPU              0x0060
 #define NVREG_IRQ_TX_ALL               (NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED)
 #define NVREG_IRQ_RX_ALL               (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED)
 #define NVREG_IRQ_OTHER                        (NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RECOVER_ERROR)
@@ -223,7 +226,7 @@ enum {
 #define NVREG_MISC1_HD         0x02
 #define NVREG_MISC1_FORCE      0x3b0f3c
 
-       NvRegMacReset = 0x3c,
+       NvRegMacReset = 0x34,
 #define NVREG_MAC_RESET_ASSERT 0x0F3
        NvRegTransmitterControl = 0x084,
 #define NVREG_XMITCTL_START    0x01
@@ -274,7 +277,9 @@ enum {
 #define NVREG_MCASTADDRA_FORCE 0x01
        NvRegMulticastAddrB = 0xB4,
        NvRegMulticastMaskA = 0xB8,
+#define NVREG_MCASTMASKA_NONE          0xffffffff
        NvRegMulticastMaskB = 0xBC,
+#define NVREG_MCASTMASKB_NONE          0xffff
 
        NvRegPhyInterface = 0xC0,
 #define PHY_RGMII              0x10000000
@@ -313,8 +318,8 @@ enum {
        NvRegTxRingPhysAddrHigh = 0x148,
        NvRegRxRingPhysAddrHigh = 0x14C,
        NvRegTxPauseFrame = 0x170,
-#define NVREG_TX_PAUSEFRAME_DISABLE    0x1ff0080
-#define NVREG_TX_PAUSEFRAME_ENABLE     0x0c00030
+#define NVREG_TX_PAUSEFRAME_DISABLE    0x01ff0080
+#define NVREG_TX_PAUSEFRAME_ENABLE     0x01800010
        NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR            0x0001
 #define NVREG_MIISTAT_LINKCHANGE       0x0008
@@ -468,9 +473,9 @@ union ring_type {
 #define NV_RX_AVAIL            (1<<31)
 
 #define NV_RX2_CHECKSUMMASK    (0x1C000000)
-#define NV_RX2_CHECKSUMOK1     (0x10000000)
-#define NV_RX2_CHECKSUMOK2     (0x14000000)
-#define NV_RX2_CHECKSUMOK3     (0x18000000)
+#define NV_RX2_CHECKSUM_IP     (0x10000000)
+#define NV_RX2_CHECKSUM_IP_TCP (0x14000000)
+#define NV_RX2_CHECKSUM_IP_UDP (0x18000000)
 #define NV_RX2_DESCRIPTORVALID (1<<29)
 #define NV_RX2_SUBSTRACT1      (1<<25)
 #define NV_RX2_ERROR1          (1<<18)
@@ -550,6 +555,8 @@ union ring_type {
 /* PHY defines */
 #define PHY_OUI_MARVELL        0x5043
 #define PHY_OUI_CICADA 0x03f1
+#define PHY_OUI_VITESSE        0x01c1
+#define PHY_OUI_REALTEK        0x0732
 #define PHYID1_OUI_MASK        0x03ff
 #define PHYID1_OUI_SHFT        6
 #define PHYID2_OUI_MASK        0xfc00
@@ -557,12 +564,36 @@ union ring_type {
 #define PHYID2_MODEL_MASK              0x03f0
 #define PHY_MODEL_MARVELL_E3016                0x220
 #define PHY_MARVELL_E3016_INITMASK     0x0300
-#define PHY_INIT1      0x0f000
-#define PHY_INIT2      0x0e00
-#define PHY_INIT3      0x01000
-#define PHY_INIT4      0x0200
-#define PHY_INIT5      0x0004
-#define PHY_INIT6      0x02000
+#define PHY_CICADA_INIT1       0x0f000
+#define PHY_CICADA_INIT2       0x0e00
+#define PHY_CICADA_INIT3       0x01000
+#define PHY_CICADA_INIT4       0x0200
+#define PHY_CICADA_INIT5       0x0004
+#define PHY_CICADA_INIT6       0x02000
+#define PHY_VITESSE_INIT_REG1  0x1f
+#define PHY_VITESSE_INIT_REG2  0x10
+#define PHY_VITESSE_INIT_REG3  0x11
+#define PHY_VITESSE_INIT_REG4  0x12
+#define PHY_VITESSE_INIT_MSK1  0xc
+#define PHY_VITESSE_INIT_MSK2  0x0180
+#define PHY_VITESSE_INIT1      0x52b5
+#define PHY_VITESSE_INIT2      0xaf8a
+#define PHY_VITESSE_INIT3      0x8
+#define PHY_VITESSE_INIT4      0x8f8a
+#define PHY_VITESSE_INIT5      0xaf86
+#define PHY_VITESSE_INIT6      0x8f86
+#define PHY_VITESSE_INIT7      0xaf82
+#define PHY_VITESSE_INIT8      0x0100
+#define PHY_VITESSE_INIT9      0x8f82
+#define PHY_VITESSE_INIT10     0x0
+#define PHY_REALTEK_INIT_REG1  0x1f
+#define PHY_REALTEK_INIT_REG2  0x19
+#define PHY_REALTEK_INIT_REG3  0x13
+#define PHY_REALTEK_INIT1      0x0000
+#define PHY_REALTEK_INIT2      0x8e00
+#define PHY_REALTEK_INIT3      0x0001
+#define PHY_REALTEK_INIT4      0xad17
+
 #define PHY_GIGABIT    0x0100
 
 #define PHY_TIMEOUT    0x1
@@ -683,8 +714,8 @@ static const struct nv_ethtool_str nv_etests_str[] = {
 };
 
 struct register_test {
-       __le32 reg;
-       __le32 mask;
+       __u32 reg;
+       __u32 mask;
 };
 
 static const struct register_test nv_registers_test[] = {
@@ -718,9 +749,11 @@ struct nv_skb_map {
 struct fe_priv {
        spinlock_t lock;
 
+       struct net_device *dev;
+       struct napi_struct napi;
+
        /* General data:
         * Locking: spin_lock(&np->lock); */
-       struct net_device_stats stats;
        struct nv_ethtool_stats estats;
        int in_shutdown;
        u32 linkspeed;
@@ -898,6 +931,16 @@ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
 #define NV_SETUP_RX_RING 0x01
 #define NV_SETUP_TX_RING 0x02
 
+static inline u32 dma_low(dma_addr_t addr)
+{
+       return addr;
+}
+
+static inline u32 dma_high(dma_addr_t addr)
+{
+       return addr>>31>>1;     /* 0 if 32bit, shift down by 32 if 64bit */
+}
+
 static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
 {
        struct fe_priv *np = get_nvpriv(dev);
@@ -905,19 +948,19 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
 
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
                if (rxtx_flags & NV_SETUP_RX_RING) {
-                       writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);
+                       writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr);
                }
                if (rxtx_flags & NV_SETUP_TX_RING) {
-                       writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+                       writel(dma_low(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
                }
        } else {
                if (rxtx_flags & NV_SETUP_RX_RING) {
-                       writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);
-                       writel((u32) (cpu_to_le64(np->ring_addr) >> 32), base + NvRegRxRingPhysAddrHigh);
+                       writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr);
+                       writel(dma_high(np->ring_addr), base + NvRegRxRingPhysAddrHigh);
                }
                if (rxtx_flags & NV_SETUP_TX_RING) {
-                       writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
-                       writel((u32) (cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh);
+                       writel(dma_low(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+                       writel(dma_high(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddrHigh);
                }
        }
 }
@@ -961,7 +1004,7 @@ static void nv_enable_irq(struct net_device *dev)
                if (np->msi_flags & NV_MSI_X_ENABLED)
                        enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
                else
-                       enable_irq(dev->irq);
+                       enable_irq(np->pci_dev->irq);
        } else {
                enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
                enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
@@ -977,7 +1020,7 @@ static void nv_disable_irq(struct net_device *dev)
                if (np->msi_flags & NV_MSI_X_ENABLED)
                        disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
                else
-                       disable_irq(dev->irq);
+                       disable_irq(np->pci_dev->irq);
        } else {
                disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
                disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
@@ -1096,6 +1139,28 @@ static int phy_init(struct net_device *dev)
                        return PHY_ERROR;
                }
        }
+       if (np->phy_oui == PHY_OUI_REALTEK) {
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+       }
 
        /* set advertise register */
        reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
@@ -1141,14 +1206,14 @@ static int phy_init(struct net_device *dev)
        /* phy vendor specific configuration */
        if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) {
                phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);
-               phy_reserved &= ~(PHY_INIT1 | PHY_INIT2);
-               phy_reserved |= (PHY_INIT3 | PHY_INIT4);
+               phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2);
+               phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4);
                if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) {
                        printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
                        return PHY_ERROR;
                }
                phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
-               phy_reserved |= PHY_INIT5;
+               phy_reserved |= PHY_CICADA_INIT5;
                if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) {
                        printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
                        return PHY_ERROR;
@@ -1156,12 +1221,106 @@ static int phy_init(struct net_device *dev)
        }
        if (np->phy_oui == PHY_OUI_CICADA) {
                phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);
-               phy_reserved |= PHY_INIT6;
+               phy_reserved |= PHY_CICADA_INIT6;
                if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) {
                        printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
                        return PHY_ERROR;
                }
        }
+       if (np->phy_oui == PHY_OUI_VITESSE) {
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+               phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+               phy_reserved |= PHY_VITESSE_INIT3;
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+               phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
+               phy_reserved |= PHY_VITESSE_INIT3;
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
+               phy_reserved &= ~PHY_VITESSE_INIT_MSK2;
+               phy_reserved |= PHY_VITESSE_INIT8;
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+       }
+       if (np->phy_oui == PHY_OUI_REALTEK) {
+               /* reset could have cleared these out, set them back */
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+       }
+
        /* some phys clear out pause advertisment on reset, set it back */
        mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
 
@@ -1357,15 +1516,16 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
                nv_get_hw_stats(dev);
 
                /* copy to net_device stats */
-               np->stats.tx_bytes = np->estats.tx_bytes;
-               np->stats.tx_fifo_errors = np->estats.tx_fifo_errors;
-               np->stats.tx_carrier_errors = np->estats.tx_carrier_errors;
-               np->stats.rx_crc_errors = np->estats.rx_crc_errors;
-               np->stats.rx_over_errors = np->estats.rx_over_errors;
-               np->stats.rx_errors = np->estats.rx_errors_total;
-               np->stats.tx_errors = np->estats.tx_errors_total;
-       }
-       return &np->stats;
+               dev->stats.tx_bytes = np->estats.tx_bytes;
+               dev->stats.tx_fifo_errors = np->estats.tx_fifo_errors;
+               dev->stats.tx_carrier_errors = np->estats.tx_carrier_errors;
+               dev->stats.rx_crc_errors = np->estats.rx_crc_errors;
+               dev->stats.rx_over_errors = np->estats.rx_over_errors;
+               dev->stats.rx_errors = np->estats.rx_errors_total;
+               dev->stats.tx_errors = np->estats.tx_errors_total;
+       }
+
+       return &dev->stats;
 }
 
 /*
@@ -1385,11 +1545,12 @@ static int nv_alloc_rx(struct net_device *dev)
        while (np->put_rx.orig != less_rx) {
                struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD);
                if (skb) {
-                       skb->dev = dev;
                        np->put_rx_ctx->skb = skb;
-                       np->put_rx_ctx->dma = pci_map_single(np->pci_dev, skb->data,
-                                                            skb->end-skb->data, PCI_DMA_FROMDEVICE);
-                       np->put_rx_ctx->dma_len = skb->end-skb->data;
+                       np->put_rx_ctx->dma = pci_map_single(np->pci_dev,
+                                                            skb->data,
+                                                            skb_tailroom(skb),
+                                                            PCI_DMA_FROMDEVICE);
+                       np->put_rx_ctx->dma_len = skb_tailroom(skb);
                        np->put_rx.orig->buf = cpu_to_le32(np->put_rx_ctx->dma);
                        wmb();
                        np->put_rx.orig->flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL);
@@ -1416,13 +1577,14 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
        while (np->put_rx.ex != less_rx) {
                struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD);
                if (skb) {
-                       skb->dev = dev;
                        np->put_rx_ctx->skb = skb;
-                       np->put_rx_ctx->dma = pci_map_single(np->pci_dev, skb->data,
-                                                            skb->end-skb->data, PCI_DMA_FROMDEVICE);
-                       np->put_rx_ctx->dma_len = skb->end-skb->data;
-                       np->put_rx.ex->bufhigh = cpu_to_le64(np->put_rx_ctx->dma) >> 32;
-                       np->put_rx.ex->buflow = cpu_to_le64(np->put_rx_ctx->dma) & 0x0FFFFFFFF;
+                       np->put_rx_ctx->dma = pci_map_single(np->pci_dev,
+                                                            skb->data,
+                                                            skb_tailroom(skb),
+                                                            PCI_DMA_FROMDEVICE);
+                       np->put_rx_ctx->dma_len = skb_tailroom(skb);
+                       np->put_rx.ex->bufhigh = cpu_to_le32(dma_high(np->put_rx_ctx->dma));
+                       np->put_rx.ex->buflow = cpu_to_le32(dma_low(np->put_rx_ctx->dma));
                        wmb();
                        np->put_rx.ex->flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL);
                        if (unlikely(np->put_rx.ex++ == np->last_rx.ex))
@@ -1441,9 +1603,10 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
 static void nv_do_rx_refill(unsigned long data)
 {
        struct net_device *dev = (struct net_device *) data;
+       struct fe_priv *np = netdev_priv(dev);
 
        /* Just reschedule NAPI rx processing */
-       netif_rx_schedule(dev);
+       netif_rx_schedule(dev, &np->napi);
 }
 #else
 static void nv_do_rx_refill(unsigned long data)
@@ -1456,7 +1619,7 @@ static void nv_do_rx_refill(unsigned long data)
                if (np->msi_flags & NV_MSI_X_ENABLED)
                        disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
                else
-                       disable_irq(dev->irq);
+                       disable_irq(np->pci_dev->irq);
        } else {
                disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
        }
@@ -1474,7 +1637,7 @@ static void nv_do_rx_refill(unsigned long data)
                if (np->msi_flags & NV_MSI_X_ENABLED)
                        enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
                else
-                       enable_irq(dev->irq);
+                       enable_irq(np->pci_dev->irq);
        } else {
                enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
        }
@@ -1582,7 +1745,7 @@ static void nv_drain_tx(struct net_device *dev)
                        np->tx_ring.ex[i].buflow = 0;
                }
                if (nv_release_txskb(dev, &np->tx_skb[i]))
-                       np->stats.tx_dropped++;
+                       dev->stats.tx_dropped++;
        }
 }
 
@@ -1604,8 +1767,9 @@ static void nv_drain_rx(struct net_device *dev)
                wmb();
                if (np->rx_skb[i].skb) {
                        pci_unmap_single(np->pci_dev, np->rx_skb[i].dma,
-                                               np->rx_skb[i].skb->end-np->rx_skb[i].skb->data,
-                                               PCI_DMA_FROMDEVICE);
+                                        (skb_end_pointer(np->rx_skb[i].skb) -
+                                         np->rx_skb[i].skb->data),
+                                        PCI_DMA_FROMDEVICE);
                        dev_kfree_skb(np->rx_skb[i].skb);
                        np->rx_skb[i].skb = NULL;
                }
@@ -1785,8 +1949,8 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
                np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
                                                PCI_DMA_TODEVICE);
                np->put_tx_ctx->dma_len = bcnt;
-               put_tx->bufhigh = cpu_to_le64(np->put_tx_ctx->dma) >> 32;
-               put_tx->buflow = cpu_to_le64(np->put_tx_ctx->dma) & 0x0FFFFFFFF;
+               put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma));
+               put_tx->buflow = cpu_to_le32(dma_low(np->put_tx_ctx->dma));
                put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 
                tx_flags = NV_TX2_VALID;
@@ -1811,8 +1975,8 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
                        np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
                                                           PCI_DMA_TODEVICE);
                        np->put_tx_ctx->dma_len = bcnt;
-                       put_tx->bufhigh = cpu_to_le64(np->put_tx_ctx->dma) >> 32;
-                       put_tx->buflow = cpu_to_le64(np->put_tx_ctx->dma) & 0x0FFFFFFFF;
+                       put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma));
+                       put_tx->buflow = cpu_to_le32(dma_low(np->put_tx_ctx->dma));
                        put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 
                        offset += bcnt;
@@ -1897,13 +2061,13 @@ static void nv_tx_done(struct net_device *dev)
                        if (flags & NV_TX_LASTPACKET) {
                                if (flags & NV_TX_ERROR) {
                                        if (flags & NV_TX_UNDERFLOW)
-                                               np->stats.tx_fifo_errors++;
+                                               dev->stats.tx_fifo_errors++;
                                        if (flags & NV_TX_CARRIERLOST)
-                                               np->stats.tx_carrier_errors++;
-                                       np->stats.tx_errors++;
+                                               dev->stats.tx_carrier_errors++;
+                                       dev->stats.tx_errors++;
                                } else {
-                                       np->stats.tx_packets++;
-                                       np->stats.tx_bytes += np->get_tx_ctx->skb->len;
+                                       dev->stats.tx_packets++;
+                                       dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
                                }
                                dev_kfree_skb_any(np->get_tx_ctx->skb);
                                np->get_tx_ctx->skb = NULL;
@@ -1912,13 +2076,13 @@ static void nv_tx_done(struct net_device *dev)
                        if (flags & NV_TX2_LASTPACKET) {
                                if (flags & NV_TX2_ERROR) {
                                        if (flags & NV_TX2_UNDERFLOW)
-                                               np->stats.tx_fifo_errors++;
+                                               dev->stats.tx_fifo_errors++;
                                        if (flags & NV_TX2_CARRIERLOST)
-                                               np->stats.tx_carrier_errors++;
-                                       np->stats.tx_errors++;
+                                               dev->stats.tx_carrier_errors++;
+                                       dev->stats.tx_errors++;
                                } else {
-                                       np->stats.tx_packets++;
-                                       np->stats.tx_bytes += np->get_tx_ctx->skb->len;
+                                       dev->stats.tx_packets++;
+                                       dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
                                }
                                dev_kfree_skb_any(np->get_tx_ctx->skb);
                                np->get_tx_ctx->skb = NULL;
@@ -1955,7 +2119,7 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit)
 
                if (flags & NV_TX2_LASTPACKET) {
                        if (!(flags & NV_TX2_ERROR))
-                               np->stats.tx_packets++;
+                               dev->stats.tx_packets++;
                        dev_kfree_skb_any(np->get_tx_ctx->skb);
                        np->get_tx_ctx->skb = NULL;
                }
@@ -2050,9 +2214,10 @@ static void nv_tx_timeout(struct net_device *dev)
                nv_drain_tx(dev);
                nv_init_tx(dev);
                setup_hw_rings(dev, NV_SETUP_TX_RING);
-               netif_wake_queue(dev);
        }
 
+       netif_wake_queue(dev);
+
        /* 4) restart tx engine */
        nv_start_tx(dev);
        spin_unlock_irq(&np->lock);
@@ -2115,13 +2280,13 @@ static int nv_rx_process(struct net_device *dev, int limit)
 {
        struct fe_priv *np = netdev_priv(dev);
        u32 flags;
-       u32 rx_processed_cnt = 0;
+       int rx_work = 0;
        struct sk_buff *skb;
        int len;
 
        while((np->get_rx.orig != np->put_rx.orig) &&
              !((flags = le32_to_cpu(np->get_rx.orig->flaglen)) & NV_RX_AVAIL) &&
-               (rx_processed_cnt++ < limit)) {
+               (rx_work < limit)) {
 
                dprintk(KERN_DEBUG "%s: nv_rx_process: flags 0x%x.\n",
                                        dev->name, flags);
@@ -2155,7 +2320,7 @@ static int nv_rx_process(struct net_device *dev, int limit)
                                        if (flags & NV_RX_ERROR4) {
                                                len = nv_getlen(dev, skb->data, len);
                                                if (len < 0) {
-                                                       np->stats.rx_errors++;
+                                                       dev->stats.rx_errors++;
                                                        dev_kfree_skb(skb);
                                                        goto next_pkt;
                                                }
@@ -2169,12 +2334,12 @@ static int nv_rx_process(struct net_device *dev, int limit)
                                        /* the rest are hard errors */
                                        else {
                                                if (flags & NV_RX_MISSEDFRAME)
-                                                       np->stats.rx_missed_errors++;
+                                                       dev->stats.rx_missed_errors++;
                                                if (flags & NV_RX_CRCERR)
-                                                       np->stats.rx_crc_errors++;
+                                                       dev->stats.rx_crc_errors++;
                                                if (flags & NV_RX_OVERFLOW)
-                                                       np->stats.rx_over_errors++;
-                                               np->stats.rx_errors++;
+                                                       dev->stats.rx_over_errors++;
+                                               dev->stats.rx_errors++;
                                                dev_kfree_skb(skb);
                                                goto next_pkt;
                                        }
@@ -2190,7 +2355,7 @@ static int nv_rx_process(struct net_device *dev, int limit)
                                        if (flags & NV_RX2_ERROR4) {
                                                len = nv_getlen(dev, skb->data, len);
                                                if (len < 0) {
-                                                       np->stats.rx_errors++;
+                                                       dev->stats.rx_errors++;
                                                        dev_kfree_skb(skb);
                                                        goto next_pkt;
                                                }
@@ -2204,22 +2369,17 @@ static int nv_rx_process(struct net_device *dev, int limit)
                                        /* the rest are hard errors */
                                        else {
                                                if (flags & NV_RX2_CRCERR)
-                                                       np->stats.rx_crc_errors++;
+                                                       dev->stats.rx_crc_errors++;
                                                if (flags & NV_RX2_OVERFLOW)
-                                                       np->stats.rx_over_errors++;
-                                               np->stats.rx_errors++;
+                                                       dev->stats.rx_over_errors++;
+                                               dev->stats.rx_errors++;
                                                dev_kfree_skb(skb);
                                                goto next_pkt;
                                        }
                                }
-                               if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ {
+                               if (((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_TCP) || /*ip and tcp */
+                                   ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_UDP))   /*ip and udp */
                                        skb->ip_summed = CHECKSUM_UNNECESSARY;
-                               } else {
-                                       if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 ||
-                                           (flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) {
-                                               skb->ip_summed = CHECKSUM_UNNECESSARY;
-                                       }
-                               }
                        } else {
                                dev_kfree_skb(skb);
                                goto next_pkt;
@@ -2236,16 +2396,18 @@ static int nv_rx_process(struct net_device *dev, int limit)
                netif_rx(skb);
 #endif
                dev->last_rx = jiffies;
-               np->stats.rx_packets++;
-               np->stats.rx_bytes += len;
+               dev->stats.rx_packets++;
+               dev->stats.rx_bytes += len;
 next_pkt:
                if (unlikely(np->get_rx.orig++ == np->last_rx.orig))
                        np->get_rx.orig = np->first_rx.orig;
                if (unlikely(np->get_rx_ctx++ == np->last_rx_ctx))
                        np->get_rx_ctx = np->first_rx_ctx;
+
+               rx_work++;
        }
 
-       return rx_processed_cnt;
+       return rx_work;
 }
 
 static int nv_rx_process_optimized(struct net_device *dev, int limit)
@@ -2253,13 +2415,13 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
        struct fe_priv *np = netdev_priv(dev);
        u32 flags;
        u32 vlanflags = 0;
-       u32 rx_processed_cnt = 0;
+       int rx_work = 0;
        struct sk_buff *skb;
        int len;
 
        while((np->get_rx.ex != np->put_rx.ex) &&
              !((flags = le32_to_cpu(np->get_rx.ex->flaglen)) & NV_RX2_AVAIL) &&
-             (rx_processed_cnt++ < limit)) {
+             (rx_work < limit)) {
 
                dprintk(KERN_DEBUG "%s: nv_rx_process_optimized: flags 0x%x.\n",
                                        dev->name, flags);
@@ -2309,14 +2471,9 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
                                }
                        }
 
-                       if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ {
+                       if (((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_TCP) || /*ip and tcp */
+                           ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_UDP))   /*ip and udp */
                                skb->ip_summed = CHECKSUM_UNNECESSARY;
-                       } else {
-                               if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 ||
-                                   (flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) {
-                                       skb->ip_summed = CHECKSUM_UNNECESSARY;
-                               }
-                       }
 
                        /* got a valid packet - forward it to the network core */
                        skb_put(skb, len);
@@ -2352,8 +2509,8 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
                        }
 
                        dev->last_rx = jiffies;
-                       np->stats.rx_packets++;
-                       np->stats.rx_bytes += len;
+                       dev->stats.rx_packets++;
+                       dev->stats.rx_bytes += len;
                } else {
                        dev_kfree_skb(skb);
                }
@@ -2362,9 +2519,11 @@ next_pkt:
                        np->get_rx.ex = np->first_rx.ex;
                if (unlikely(np->get_rx_ctx++ == np->last_rx_ctx))
                        np->get_rx_ctx = np->first_rx_ctx;
+
+               rx_work++;
        }
 
-       return rx_processed_cnt;
+       return rx_work;
 }
 
 static void set_bufsize(struct net_device *dev)
@@ -2523,8 +2682,8 @@ static void nv_set_multicast(struct net_device *dev)
                                walk = dev->mc_list;
                                while (walk != NULL) {
                                        u32 a, b;
-                                       a = le32_to_cpu(*(u32 *) walk->dmi_addr);
-                                       b = le16_to_cpu(*(u16 *) (&walk->dmi_addr[4]));
+                                       a = le32_to_cpu(*(__le32 *) walk->dmi_addr);
+                                       b = le16_to_cpu(*(__le16 *) (&walk->dmi_addr[4]));
                                        alwaysOn[0] &= a;
                                        alwaysOff[0] &= ~a;
                                        alwaysOn[1] &= b;
@@ -2536,6 +2695,9 @@ static void nv_set_multicast(struct net_device *dev)
                        addr[1] = alwaysOn[1];
                        mask[0] = alwaysOn[0] | alwaysOff[0];
                        mask[1] = alwaysOn[1] | alwaysOff[1];
+               } else {
+                       mask[0] = NVREG_MCASTMASKA_NONE;
+                       mask[1] = NVREG_MCASTMASKB_NONE;
                }
        }
        addr[0] |= NVREG_MCASTADDRA_FORCE;
@@ -2850,7 +3012,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
 
 #ifdef CONFIG_FORCEDETH_NAPI
                if (events & NVREG_IRQ_RX_ALL) {
-                       netif_rx_schedule(dev);
+                       netif_rx_schedule(dev, &np->napi);
 
                        /* Disable furthur receive irq's */
                        spin_lock(&np->lock);
@@ -2863,7 +3025,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
                        spin_unlock(&np->lock);
                }
 #else
-               if (nv_rx_process(dev, dev->weight)) {
+               if (nv_rx_process(dev, RX_WORK_PER_LOOP)) {
                        if (unlikely(nv_alloc_rx(dev))) {
                                spin_lock(&np->lock);
                                if (!np->in_shutdown)
@@ -2921,8 +3083,8 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
                                np->nic_poll_irq = np->irqmask;
                                mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
                        }
-                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i);
                        spin_unlock(&np->lock);
+                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i);
                        break;
                }
 
@@ -2932,8 +3094,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
        return IRQ_RETVAL(i);
 }
 
-#define TX_WORK_PER_LOOP  64
-#define RX_WORK_PER_LOOP  64
 /**
  * All _optimized functions are used to help increase performance
  * (reduce CPU and increase throughput). They use descripter version 3,
@@ -2967,7 +3127,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
 
 #ifdef CONFIG_FORCEDETH_NAPI
                if (events & NVREG_IRQ_RX_ALL) {
-                       netif_rx_schedule(dev);
+                       netif_rx_schedule(dev, &np->napi);
 
                        /* Disable furthur receive irq's */
                        spin_lock(&np->lock);
@@ -2980,7 +3140,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
                        spin_unlock(&np->lock);
                }
 #else
-               if (nv_rx_process_optimized(dev, dev->weight)) {
+               if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) {
                        if (unlikely(nv_alloc_rx_optimized(dev))) {
                                spin_lock(&np->lock);
                                if (!np->in_shutdown)
@@ -3039,8 +3199,8 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
                                np->nic_poll_irq = np->irqmask;
                                mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
                        }
-                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i);
                        spin_unlock(&np->lock);
+                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i);
                        break;
                }
 
@@ -3086,8 +3246,8 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)
                                np->nic_poll_irq |= NVREG_IRQ_TX_ALL;
                                mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
                        }
-                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
                        spin_unlock_irqrestore(&np->lock, flags);
+                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
                        break;
                }
 
@@ -3098,19 +3258,19 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)
 }
 
 #ifdef CONFIG_FORCEDETH_NAPI
-static int nv_napi_poll(struct net_device *dev, int *budget)
+static int nv_napi_poll(struct napi_struct *napi, int budget)
 {
-       int pkts, limit = min(*budget, dev->quota);
-       struct fe_priv *np = netdev_priv(dev);
+       struct fe_priv *np = container_of(napi, struct fe_priv, napi);
+       struct net_device *dev = np->dev;
        u8 __iomem *base = get_hwbase(dev);
        unsigned long flags;
-       int retcode;
+       int pkts, retcode;
 
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-               pkts = nv_rx_process(dev, limit);
+               pkts = nv_rx_process(dev, budget);
                retcode = nv_alloc_rx(dev);
        } else {
-               pkts = nv_rx_process_optimized(dev, limit);
+               pkts = nv_rx_process_optimized(dev, budget);
                retcode = nv_alloc_rx_optimized(dev);
        }
 
@@ -3121,13 +3281,12 @@ static int nv_napi_poll(struct net_device *dev, int *budget)
                spin_unlock_irqrestore(&np->lock, flags);
        }
 
-       if (pkts < limit) {
-               /* all done, no more packets present */
-               netif_rx_complete(dev);
-
+       if (pkts < budget) {
                /* re-enable receive interrupts */
                spin_lock_irqsave(&np->lock, flags);
 
+               __netif_rx_complete(dev, napi);
+
                np->irqmask |= NVREG_IRQ_RX_ALL;
                if (np->msi_flags & NV_MSI_X_ENABLED)
                        writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
@@ -3135,13 +3294,8 @@ static int nv_napi_poll(struct net_device *dev, int *budget)
                        writel(np->irqmask, base + NvRegIrqMask);
 
                spin_unlock_irqrestore(&np->lock, flags);
-               return 0;
-       } else {
-               /* used up our quantum, so reschedule */
-               dev->quota -= pkts;
-               *budget -= pkts;
-               return 1;
        }
+       return pkts;
 }
 #endif
 
@@ -3149,6 +3303,7 @@ static int nv_napi_poll(struct net_device *dev, int *budget)
 static irqreturn_t nv_nic_irq_rx(int foo, void *data)
 {
        struct net_device *dev = (struct net_device *) data;
+       struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
        u32 events;
 
@@ -3156,7 +3311,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
        writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
 
        if (events) {
-               netif_rx_schedule(dev);
+               netif_rx_schedule(dev, &np->napi);
                /* disable receive interrupts on the nic */
                writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
                pci_push(base);
@@ -3182,7 +3337,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
                if (!(events & np->irqmask))
                        break;
 
-               if (nv_rx_process_optimized(dev, dev->weight)) {
+               if (nv_rx_process_optimized(dev, RX_WORK_PER_LOOP)) {
                        if (unlikely(nv_alloc_rx_optimized(dev))) {
                                spin_lock_irqsave(&np->lock, flags);
                                if (!np->in_shutdown)
@@ -3201,8 +3356,8 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
                                np->nic_poll_irq |= NVREG_IRQ_RX_ALL;
                                mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
                        }
-                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
                        spin_unlock_irqrestore(&np->lock, flags);
+                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
                        break;
                }
        }
@@ -3274,8 +3429,8 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data)
                                np->nic_poll_irq |= NVREG_IRQ_OTHER;
                                mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
                        }
-                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
                        spin_unlock_irqrestore(&np->lock, flags);
+                       printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
                        break;
                }
 
@@ -3410,10 +3565,12 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
        if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
                if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
                        np->msi_flags |= NV_MSI_ENABLED;
+                       dev->irq = np->pci_dev->irq;
                        if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) {
                                printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
                                pci_disable_msi(np->pci_dev);
                                np->msi_flags &= ~NV_MSI_ENABLED;
+                               dev->irq = np->pci_dev->irq;
                                goto out_err;
                        }
 
@@ -3476,7 +3633,7 @@ static void nv_do_nic_poll(unsigned long data)
                if (np->msi_flags & NV_MSI_X_ENABLED)
                        disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
                else
-                       disable_irq_lockdep(dev->irq);
+                       disable_irq_lockdep(np->pci_dev->irq);
                mask = np->irqmask;
        } else {
                if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
@@ -3494,6 +3651,8 @@ static void nv_do_nic_poll(unsigned long data)
        }
        np->nic_poll_irq = 0;
 
+       /* disable_irq() contains synchronize_irq, thus no irq handler can run now */
+
        if (np->recover_error) {
                np->recover_error = 0;
                printk(KERN_INFO "forcedeth: MAC in recoverable error state\n");
@@ -3530,7 +3689,6 @@ static void nv_do_nic_poll(unsigned long data)
                }
        }
 
-       /* FIXME: Do we need synchronize_irq(dev->irq) here? */
 
        writel(mask, base + NvRegIrqMask);
        pci_push(base);
@@ -3543,7 +3701,7 @@ static void nv_do_nic_poll(unsigned long data)
                if (np->msi_flags & NV_MSI_X_ENABLED)
                        enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
                else
-                       enable_irq_lockdep(dev->irq);
+                       enable_irq_lockdep(np->pci_dev->irq);
        } else {
                if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
                        nv_nic_irq_rx(0, dev);
@@ -3581,7 +3739,7 @@ static void nv_do_stats_poll(unsigned long data)
 static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct fe_priv *np = netdev_priv(dev);
-       strcpy(info->driver, "forcedeth");
+       strcpy(info->driver, DRV_NAME);
        strcpy(info->version, FORCEDETH_VERSION);
        strcpy(info->bus_info, pci_name(np->pci_dev));
 }
@@ -4187,16 +4345,26 @@ static int nv_set_sg(struct net_device *dev, u32 data)
                return -EOPNOTSUPP;
 }
 
-static int nv_get_stats_count(struct net_device *dev)
+static int nv_get_sset_count(struct net_device *dev, int sset)
 {
        struct fe_priv *np = netdev_priv(dev);
 
-       if (np->driver_data & DEV_HAS_STATISTICS_V1)
-               return NV_DEV_STATISTICS_V1_COUNT;
-       else if (np->driver_data & DEV_HAS_STATISTICS_V2)
-               return NV_DEV_STATISTICS_V2_COUNT;
-       else
-               return 0;
+       switch (sset) {
+       case ETH_SS_TEST:
+               if (np->driver_data & DEV_HAS_TEST_EXTENDED)
+                       return NV_TEST_COUNT_EXTENDED;
+               else
+                       return NV_TEST_COUNT_BASE;
+       case ETH_SS_STATS:
+               if (np->driver_data & DEV_HAS_STATISTICS_V1)
+                       return NV_DEV_STATISTICS_V1_COUNT;
+               else if (np->driver_data & DEV_HAS_STATISTICS_V2)
+                       return NV_DEV_STATISTICS_V2_COUNT;
+               else
+                       return 0;
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 static void nv_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *estats, u64 *buffer)
@@ -4206,17 +4374,7 @@ static void nv_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *e
        /* update stats */
        nv_do_stats_poll((unsigned long)dev);
 
-       memcpy(buffer, &np->estats, nv_get_stats_count(dev)*sizeof(u64));
-}
-
-static int nv_self_test_count(struct net_device *dev)
-{
-       struct fe_priv *np = netdev_priv(dev);
-
-       if (np->driver_data & DEV_HAS_TEST_EXTENDED)
-               return NV_TEST_COUNT_EXTENDED;
-       else
-               return NV_TEST_COUNT_BASE;
+       memcpy(buffer, &np->estats, nv_get_sset_count(dev, ETH_SS_STATS)*sizeof(u64));
 }
 
 static int nv_link_test(struct net_device *dev)
@@ -4375,18 +4533,19 @@ static int nv_loopback_test(struct net_device *dev)
                ret = 0;
                goto out;
        }
+       test_dma_addr = pci_map_single(np->pci_dev, tx_skb->data,
+                                      skb_tailroom(tx_skb),
+                                      PCI_DMA_FROMDEVICE);
        pkt_data = skb_put(tx_skb, pkt_len);
        for (i = 0; i < pkt_len; i++)
                pkt_data[i] = (u8)(i & 0xff);
-       test_dma_addr = pci_map_single(np->pci_dev, tx_skb->data,
-                                      tx_skb->end-tx_skb->data, PCI_DMA_FROMDEVICE);
 
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
                np->tx_ring.orig[0].buf = cpu_to_le32(test_dma_addr);
                np->tx_ring.orig[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
        } else {
-               np->tx_ring.ex[0].bufhigh = cpu_to_le64(test_dma_addr) >> 32;
-               np->tx_ring.ex[0].buflow = cpu_to_le64(test_dma_addr) & 0x0FFFFFFFF;
+               np->tx_ring.ex[0].bufhigh = cpu_to_le32(dma_high(test_dma_addr));
+               np->tx_ring.ex[0].buflow = cpu_to_le32(dma_low(test_dma_addr));
                np->tx_ring.ex[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
        }
        writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
@@ -4436,7 +4595,7 @@ static int nv_loopback_test(struct net_device *dev)
        }
 
        pci_unmap_page(np->pci_dev, test_dma_addr,
-                      tx_skb->end-tx_skb->data,
+                      (skb_end_pointer(tx_skb) - tx_skb->data),
                       PCI_DMA_TODEVICE);
        dev_kfree_skb_any(tx_skb);
  out:
@@ -4462,7 +4621,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
        int result;
-       memset(buffer, 0, nv_self_test_count(dev)*sizeof(u64));
+       memset(buffer, 0, nv_get_sset_count(dev, ETH_SS_TEST)*sizeof(u64));
 
        if (!nv_link_test(dev)) {
                test->flags |= ETH_TEST_FL_FAILED;
@@ -4472,7 +4631,9 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
        if (test->flags & ETH_TEST_FL_OFFLINE) {
                if (netif_running(dev)) {
                        netif_stop_queue(dev);
-                       netif_poll_disable(dev);
+#ifdef CONFIG_FORCEDETH_NAPI
+                       napi_disable(&np->napi);
+#endif
                        netif_tx_lock_bh(dev);
                        spin_lock_irq(&np->lock);
                        nv_disable_hw_interrupts(dev, np->irqmask);
@@ -4531,7 +4692,9 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
                        nv_start_rx(dev);
                        nv_start_tx(dev);
                        netif_start_queue(dev);
-                       netif_poll_enable(dev);
+#ifdef CONFIG_FORCEDETH_NAPI
+                       napi_enable(&np->napi);
+#endif
                        nv_enable_hw_interrupts(dev, np->irqmask);
                }
        }
@@ -4541,10 +4704,10 @@ static void nv_get_strings(struct net_device *dev, u32 stringset, u8 *buffer)
 {
        switch (stringset) {
        case ETH_SS_STATS:
-               memcpy(buffer, &nv_estats_str, nv_get_stats_count(dev)*sizeof(struct nv_ethtool_str));
+               memcpy(buffer, &nv_estats_str, nv_get_sset_count(dev, ETH_SS_STATS)*sizeof(struct nv_ethtool_str));
                break;
        case ETH_SS_TEST:
-               memcpy(buffer, &nv_etests_str, nv_self_test_count(dev)*sizeof(struct nv_ethtool_str));
+               memcpy(buffer, &nv_etests_str, nv_get_sset_count(dev, ETH_SS_TEST)*sizeof(struct nv_ethtool_str));
                break;
        }
 }
@@ -4559,8 +4722,6 @@ static const struct ethtool_ops ops = {
        .get_regs_len = nv_get_regs_len,
        .get_regs = nv_get_regs,
        .nway_reset = nv_nway_reset,
-       .get_perm_addr = ethtool_op_get_perm_addr,
-       .get_tso = ethtool_op_get_tso,
        .set_tso = nv_set_tso,
        .get_ringparam = nv_get_ringparam,
        .set_ringparam = nv_set_ringparam,
@@ -4568,14 +4729,11 @@ static const struct ethtool_ops ops = {
        .set_pauseparam = nv_set_pauseparam,
        .get_rx_csum = nv_get_rx_csum,
        .set_rx_csum = nv_set_rx_csum,
-       .get_tx_csum = ethtool_op_get_tx_csum,
        .set_tx_csum = nv_set_tx_csum,
-       .get_sg = ethtool_op_get_sg,
        .set_sg = nv_set_sg,
        .get_strings = nv_get_strings,
-       .get_stats_count = nv_get_stats_count,
        .get_ethtool_stats = nv_get_ethtool_stats,
-       .self_test_count = nv_self_test_count,
+       .get_sset_count = nv_get_sset_count,
        .self_test = nv_self_test,
 };
 
@@ -4600,12 +4758,7 @@ static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
        writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
 
        spin_unlock_irq(&np->lock);
-};
-
-static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-       /* nothing to do */
-};
+}
 
 /* The mgmt unit and driver use a semaphore to access the phy during init */
 static int nv_mgmt_acquire_sema(struct net_device *dev)
@@ -4655,8 +4808,8 @@ static int nv_open(struct net_device *dev)
                nv_mac_reset(dev);
        writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
        writel(0, base + NvRegMulticastAddrB);
-       writel(0, base + NvRegMulticastMaskA);
-       writel(0, base + NvRegMulticastMaskB);
+       writel(NVREG_MCASTMASKA_NONE, base + NvRegMulticastMaskA);
+       writel(NVREG_MCASTMASKB_NONE, base + NvRegMulticastMaskB);
        writel(0, base + NvRegPacketFilterFlags);
 
        writel(0, base + NvRegTransmitterControl);
@@ -4750,8 +4903,8 @@ static int nv_open(struct net_device *dev)
        spin_lock_irq(&np->lock);
        writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
        writel(0, base + NvRegMulticastAddrB);
-       writel(0, base + NvRegMulticastMaskA);
-       writel(0, base + NvRegMulticastMaskB);
+       writel(NVREG_MCASTMASKA_NONE, base + NvRegMulticastMaskA);
+       writel(NVREG_MCASTMASKB_NONE, base + NvRegMulticastMaskB);
        writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
        /* One manual link speed update: Interrupts are enabled, future link
         * speed changes cause interrupts and are handled by nv_link_irq().
@@ -4769,12 +4922,14 @@ static int nv_open(struct net_device *dev)
        nv_start_rx(dev);
        nv_start_tx(dev);
        netif_start_queue(dev);
-       netif_poll_enable(dev);
+#ifdef CONFIG_FORCEDETH_NAPI
+       napi_enable(&np->napi);
+#endif
 
        if (ret) {
                netif_carrier_on(dev);
        } else {
-               printk("%s: no link during initialization.\n", dev->name);
+               printk(KERN_INFO "%s: no link during initialization.\n", dev->name);
                netif_carrier_off(dev);
        }
        if (oom)
@@ -4800,8 +4955,10 @@ static int nv_close(struct net_device *dev)
        spin_lock_irq(&np->lock);
        np->in_shutdown = 1;
        spin_unlock_irq(&np->lock);
-       netif_poll_disable(dev);
-       synchronize_irq(dev->irq);
+#ifdef CONFIG_FORCEDETH_NAPI
+       napi_disable(&np->napi);
+#endif
+       synchronize_irq(np->pci_dev->irq);
 
        del_timer_sync(&np->oom_kick);
        del_timer_sync(&np->nic_poll);
@@ -4825,8 +4982,10 @@ static int nv_close(struct net_device *dev)
 
        drain_ring(dev);
 
-       if (np->wolenabled)
+       if (np->wolenabled) {
+               writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
                nv_start_rx(dev);
+       }
 
        /* FIXME: power down nic */
 
@@ -4843,6 +5002,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        u32 powerstate, txreg;
        u32 phystate_orig = 0, phystate;
        int phyinitialized = 0;
+       DECLARE_MAC_BUF(mac);
+       static int printed_version;
+
+       if (!printed_version++)
+               printk(KERN_INFO "%s: Reverse Engineered nForce ethernet"
+                      " driver. Version %s.\n", DRV_NAME, FORCEDETH_VERSION);
 
        dev = alloc_etherdev(sizeof(struct fe_priv));
        err = -ENOMEM;
@@ -4850,9 +5015,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                goto out;
 
        np = netdev_priv(dev);
+       np->dev = dev;
        np->pci_dev = pci_dev;
        spin_lock_init(&np->lock);
-       SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pci_dev->dev);
 
        init_timer(&np->oom_kick);
@@ -4866,11 +5031,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        np->stats_poll.function = &nv_do_stats_poll;    /* timer handler */
 
        err = pci_enable_device(pci_dev);
-       if (err) {
-               printk(KERN_INFO "forcedeth: pci_enable_dev failed (%d) for device %s\n",
-                               err, pci_name(pci_dev));
+       if (err)
                goto out_free;
-       }
 
        pci_set_master(pci_dev);
 
@@ -4899,8 +5061,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                }
        }
        if (i == DEVICE_COUNT_RESOURCE) {
-               printk(KERN_INFO "forcedeth: Couldn't find register window for device %s.\n",
-                                       pci_name(pci_dev));
+               dev_printk(KERN_INFO, &pci_dev->dev,
+                          "Couldn't find register window\n");
                goto out_relreg;
        }
 
@@ -4913,16 +5075,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                np->desc_ver = DESC_VER_3;
                np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
                if (dma_64bit) {
-                       if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
-                               printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
-                                      pci_name(pci_dev));
-                       } else {
+                       if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK))
+                               dev_printk(KERN_INFO, &pci_dev->dev,
+                                       "64-bit DMA failed, using 32-bit addressing\n");
+                       else
                                dev->features |= NETIF_F_HIGHDMA;
-                               printk(KERN_INFO "forcedeth: using HIGHDMA\n");
-                       }
                        if (pci_set_consistent_dma_mask(pci_dev, DMA_39BIT_MASK)) {
-                               printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed, using 32-bit ring buffers for device %s.\n",
-                                      pci_name(pci_dev));
+                               dev_printk(KERN_INFO, &pci_dev->dev,
+                                       "64-bit DMA (consistent) failed, using 32-bit ring buffers\n");
                        }
                }
        } else if (id->driver_data & DEV_HAS_LARGEDESC) {
@@ -4951,7 +5111,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE;
                dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
                dev->vlan_rx_register = nv_vlan_rx_register;
-               dev->vlan_rx_kill_vid = nv_vlan_rx_kill_vid;
        }
 
        np->msi_flags = 0;
@@ -4994,12 +5153,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                        goto out_unmap;
                np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size];
        }
-       np->rx_skb = kmalloc(sizeof(struct nv_skb_map) * np->rx_ring_size, GFP_KERNEL);
-       np->tx_skb = kmalloc(sizeof(struct nv_skb_map) * np->tx_ring_size, GFP_KERNEL);
+       np->rx_skb = kcalloc(np->rx_ring_size, sizeof(struct nv_skb_map), GFP_KERNEL);
+       np->tx_skb = kcalloc(np->tx_ring_size, sizeof(struct nv_skb_map), GFP_KERNEL);
        if (!np->rx_skb || !np->tx_skb)
                goto out_freering;
-       memset(np->rx_skb, 0, sizeof(struct nv_skb_map) * np->rx_ring_size);
-       memset(np->tx_skb, 0, sizeof(struct nv_skb_map) * np->tx_ring_size);
 
        dev->open = nv_open;
        dev->stop = nv_close;
@@ -5014,9 +5171,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = nv_poll_controller;
 #endif
-       dev->weight = RX_WORK_PER_LOOP;
 #ifdef CONFIG_FORCEDETH_NAPI
-       dev->poll = nv_napi_poll;
+       netif_napi_add(dev, &np->napi, nv_napi_poll, RX_WORK_PER_LOOP);
 #endif
        SET_ETHTOOL_OPS(dev, &ops);
        dev->tx_timeout = nv_tx_timeout;
@@ -5031,7 +5187,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 
        /* check the workaround bit for correct mac address order */
        txreg = readl(base + NvRegTransmitPoll);
-       if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) {
+       if ((txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) ||
+           (id->driver_data & DEV_HAS_CORRECT_MACADDR)) {
                /* mac address is already in correct order */
                dev->dev_addr[0] = (np->orig_mac[0] >>  0) & 0xff;
                dev->dev_addr[1] = (np->orig_mac[0] >>  8) & 0xff;
@@ -5047,10 +5204,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
                dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
                dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
-               /* set permanent address to be correct aswell */
-               np->orig_mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
-                       (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
-               np->orig_mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
                writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
        }
        memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
@@ -5060,20 +5213,19 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                 * Bad mac address. At least one bios sets the mac address
                 * to 01:23:45:67:89:ab
                 */
-               printk(KERN_ERR "%s: Invalid Mac address detected: %02x:%02x:%02x:%02x:%02x:%02x\n",
-                       pci_name(pci_dev),
-                       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-                       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-               printk(KERN_ERR "Please complain to your hardware vendor. Switching to a random MAC.\n");
+               dev_printk(KERN_ERR, &pci_dev->dev,
+                       "Invalid Mac address detected: %s\n",
+                       print_mac(mac, dev->dev_addr));
+               dev_printk(KERN_ERR, &pci_dev->dev,
+                       "Please complain to your hardware vendor. Switching to a random MAC.\n");
                dev->dev_addr[0] = 0x00;
                dev->dev_addr[1] = 0x00;
                dev->dev_addr[2] = 0x6c;
                get_random_bytes(&dev->dev_addr[3], 3);
        }
 
-       dprintk(KERN_DEBUG "%s: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", pci_name(pci_dev),
-                       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-                       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+       dprintk(KERN_DEBUG "%s: MAC Address %s\n",
+               pci_name(pci_dev), print_mac(mac, dev->dev_addr));
 
        /* set mac address */
        nv_copy_mac_to_hw(dev);
@@ -5083,15 +5235,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        np->wolenabled = 0;
 
        if (id->driver_data & DEV_HAS_POWER_CNTRL) {
-               u8 revision_id;
-               pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id);
 
                /* take phy and nic out of low power mode */
                powerstate = readl(base + NvRegPowerState2);
                powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
                if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
                     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) &&
-                   revision_id >= 0xA3)
+                   pci_dev->revision >= 0xA3)
                        powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
                writel(powerstate, base + NvRegPowerState2);
        }
@@ -5137,19 +5287,15 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) {
                        np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST;
                        dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use);
-                       for (i = 0; i < 5000; i++) {
-                               msleep(1);
-                               if (nv_mgmt_acquire_sema(dev)) {
-                                       /* management unit setup the phy already? */
-                                       if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
-                                           NVREG_XMITCTL_SYNC_PHY_INIT) {
-                                               /* phy is inited by mgmt unit */
-                                               phyinitialized = 1;
-                                               dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev));
-                                       } else {
-                                               /* we need to init the phy */
-                                       }
-                                       break;
+                       if (nv_mgmt_acquire_sema(dev)) {
+                               /* management unit setup the phy already? */
+                               if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
+                                   NVREG_XMITCTL_SYNC_PHY_INIT) {
+                                       /* phy is inited by mgmt unit */
+                                       phyinitialized = 1;
+                                       dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev));
+                               } else {
+                                       /* we need to init the phy */
                                }
                        }
                }
@@ -5181,8 +5327,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                break;
        }
        if (i == 33) {
-               printk(KERN_INFO "%s: open: Could not find a valid PHY.\n",
-                      pci_name(pci_dev));
+               dev_printk(KERN_INFO, &pci_dev->dev,
+                       "open: Could not find a valid PHY.\n");
                goto out_error;
        }
 
@@ -5204,12 +5350,37 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 
        err = register_netdev(dev);
        if (err) {
-               printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err);
+               dev_printk(KERN_INFO, &pci_dev->dev,
+                          "unable to register netdev: %d\n", err);
                goto out_error;
        }
-       printk(KERN_INFO "%s: forcedeth.c: subsystem: %05x:%04x bound to %s\n",
-                       dev->name, pci_dev->subsystem_vendor, pci_dev->subsystem_device,
-                       pci_name(pci_dev));
+
+       dev_printk(KERN_INFO, &pci_dev->dev, "ifname %s, PHY OUI 0x%x @ %d, "
+                  "addr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
+                  dev->name,
+                  np->phy_oui,
+                  np->phyaddr,
+                  dev->dev_addr[0],
+                  dev->dev_addr[1],
+                  dev->dev_addr[2],
+                  dev->dev_addr[3],
+                  dev->dev_addr[4],
+                  dev->dev_addr[5]);
+
+       dev_printk(KERN_INFO, &pci_dev->dev, "%s%s%s%s%s%s%s%s%s%sdesc-v%u\n",
+                  dev->features & NETIF_F_HIGHDMA ? "highdma " : "",
+                  dev->features & (NETIF_F_HW_CSUM | NETIF_F_SG) ?
+                       "csum " : "",
+                  dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX) ?
+                       "vlan " : "",
+                  id->driver_data & DEV_HAS_POWER_CNTRL ? "pwrctl " : "",
+                  id->driver_data & DEV_HAS_MGMT_UNIT ? "mgmt " : "",
+                  id->driver_data & DEV_NEED_TIMERIRQ ? "timirq " : "",
+                  np->gigabit == PHY_GIGABIT ? "gbit " : "",
+                  np->need_linktimer ? "lnktim " : "",
+                  np->msi_flags & NV_MSI_CAPABLE ? "msi " : "",
+                  np->msi_flags & NV_MSI_X_CAPABLE ? "msi-x " : "",
+                  np->desc_ver);
 
        return 0;
 
@@ -5244,6 +5415,8 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
         */
        writel(np->orig_mac[0], base + NvRegMacAddrA);
        writel(np->orig_mac[1], base + NvRegMacAddrB);
+       writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV,
+              base + NvRegTransmitPoll);
 
        /* free all structures */
        free_rings(dev);
@@ -5361,67 +5534,114 @@ static struct pci_device_id pci_tbl[] = {
        },
        {       /* MCP61 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP61 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP61 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP61 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP73 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP73 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP73 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP73 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP77 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP77 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP77 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP77 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP79 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP79 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP79 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+       },
+       {       /* MCP79 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
        },
        {0,},
 };
 
 static struct pci_driver driver = {
-       .name = "forcedeth",
-       .id_table = pci_tbl,
-       .probe = nv_probe,
-       .remove = __devexit_p(nv_remove),
-       .suspend = nv_suspend,
-       .resume = nv_resume,
+       .name           = DRV_NAME,
+       .id_table       = pci_tbl,
+       .probe          = nv_probe,
+       .remove         = __devexit_p(nv_remove),
+       .suspend        = nv_suspend,
+       .resume         = nv_resume,
 };
 
 static int __init init_nic(void)
 {
-       printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION);
        return pci_register_driver(&driver);
 }