[NET]: Make NAPI polling independent of struct net_device objects.
[linux-3.10.git] / drivers / net / via-rhine.c
index eb0e7bd..7a58990 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
-
-
-       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_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.
@@ -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. */
+#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;
+#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
@@ -166,7 +73,11 @@ 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. */
+#ifdef CONFIG_VIA_RHINE_NAPI
+#define RX_RING_SIZE   64
+#else
 #define RX_RING_SIZE   16
+#endif
 
 
 /* Operational parameters that usually are not changed. */
@@ -200,6 +111,7 @@ static const int multicast_filter_limit = 32;
 #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. */
 static char version[] __devinitdata =
@@ -219,9 +131,11 @@ MODULE_LICENSE("GPL");
 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(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
 
 /*
                Theory of Operation
@@ -355,12 +269,11 @@ enum rhine_quirks {
 /* 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 const struct pci_device_id 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);
@@ -469,13 +382,15 @@ struct rhine_private {
        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;
+       struct net_device *dev;
+       struct napi_struct napi;
        struct net_device_stats stats;
        spinlock_t lock;
 
@@ -498,14 +413,14 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
 static int  rhine_open(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 irqreturn_t rhine_interrupt(int irq, void *dev_instance);
 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 struct ethtool_ops netdev_ethtool_ops;
+static const struct ethtool_ops netdev_ethtool_ops;
 static int  rhine_close(struct net_device *dev);
 static void rhine_shutdown (struct pci_dev *pdev);
 
@@ -663,11 +578,34 @@ static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
 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
 
+#ifdef CONFIG_VIA_RHINE_NAPI
+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) {
+               netif_rx_complete(dev, napi);
+
+               iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
+                         IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
+                         IntrTxDone | IntrTxError | IntrTxUnderrun |
+                         IntrPCIErr | IntrStatsMax | IntrLinkChange,
+                         ioaddr + IntrEnable);
+       }
+       return work_done;
+}
+#endif
+
 static void rhine_hw_init(struct net_device *dev, long pioaddr)
 {
        struct rhine_private *rp = netdev_priv(dev);
@@ -689,7 +627,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        struct net_device *dev;
        struct rhine_private *rp;
        int i, rc;
-       u8 pci_rev;
        u32 quirks;
        long pioaddr;
        long memaddr;
@@ -709,27 +646,25 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                printk(version);
 #endif
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
        io_size = 256;
        phy_id = 0;
        quirks = 0;
        name = "Rhine";
-       if (pci_rev < VTunknown0) {
+       if (pdev->revision < VTunknown0) {
                quirks = rqRhineI;
                io_size = 128;
        }
-       else if (pci_rev >= VT6102) {
+       else if (pdev->revision >= VT6102) {
                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 */
-                       if (pci_rev >= VT6105_B0)
+                       if (pdev->revision >= VT6105_B0)
                                quirks |= rq6patterns;
-                       if (pci_rev < VT6105M)
+                       if (pdev->revision < VT6105M)
                                name = "Rhine III";
                        else
                                name = "Rhine III (Management Adapter)";
@@ -771,6 +706,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        rp = netdev_priv(dev);
+       rp->dev = dev;
        rp->quirks = quirks;
        rp->pioaddr = pioaddr;
        rp->pdev = pdev;
@@ -814,8 +750,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);
+       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;
@@ -847,6 +784,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        dev->poll_controller = rhine_poll;
 #endif
+#ifdef CONFIG_VIA_RHINE_NAPI
+       netif_napi_add(dev, &rp->napi, rhine_napipoll, 64);
+#endif
        if (rp->quirks & rqRhineI)
                dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
@@ -892,6 +832,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                }
        }
        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;
 
@@ -990,7 +933,7 @@ static void alloc_rbufs(struct net_device *dev)
                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]);
@@ -1032,7 +975,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_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);
 
@@ -1074,6 +1018,25 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
        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)
@@ -1097,6 +1060,10 @@ static void init_registers(struct net_device *dev)
 
        rhine_set_rx_mode(dev);
 
+#ifdef CONFIG_VIA_RHINE_NAPI
+       napi_enable(&rp->napi);
+#endif
+
        /* 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;
 
-       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;
@@ -1230,6 +1197,10 @@ static void rhine_tx_timeout(struct net_device *dev)
        /* protect against concurrent rx interrupts */
        disable_irq(rp->pdev->irq);
 
+#ifdef CONFIG_VIA_RHINE_NAPI
+       napi_disable(&rp->napi);
+#endif
+
        spin_lock(&rp->lock);
 
        /* clear all descriptors */
@@ -1262,16 +1233,13 @@ 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;
 
-       if (skb->len < ETH_ZLEN) {
-               skb = skb_padto(skb, ETH_ZLEN);
-               if (skb == NULL)
-                       return 0;
-       }
+       if (skb_padto(skb, ETH_ZLEN))
+               return 0;
 
        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 */
@@ -1280,7 +1248,12 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
                        rp->stats.tx_dropped++;
                        return 0;
                }
+
+               /* Padding is not copied and so must be redone. */
                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] -
@@ -1326,7 +1299,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
 
 /* 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);
@@ -1349,8 +1322,18 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *
                               dev->name, intr_status);
 
                if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
-                   IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf))
-                       rhine_rx(dev);
+                                  IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
+#ifdef CONFIG_VIA_RHINE_NAPI
+                       iowrite16(IntrTxAborted |
+                                 IntrTxDone | IntrTxError | IntrTxUnderrun |
+                                 IntrPCIErr | IntrStatsMax | IntrLinkChange,
+                                 ioaddr + IntrEnable);
+
+                       netif_rx_schedule(dev, &rp->napi);
+#else
+                       rhine_rx(dev, RX_RING_SIZE);
+#endif
+               }
 
                if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
                        if (intr_status & IntrTxErrSummary) {
@@ -1448,13 +1431,12 @@ static void rhine_tx(struct net_device *dev)
        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);
+       int count;
        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",
@@ -1463,16 +1445,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. */
-       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;
 
+               if (desc_status & DescOwn)
+                       break;
+
                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 "
@@ -1510,16 +1494,15 @@ static void rhine_rx(struct net_device *dev)
                           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 */
                                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],
@@ -1541,7 +1524,11 @@ static void rhine_rx(struct net_device *dev)
                                                 PCI_DMA_FROMDEVICE);
                        }
                        skb->protocol = eth_type_trans(skb, dev);
+#ifdef CONFIG_VIA_RHINE_NAPI
+                       netif_receive_skb(skb);
+#else
                        netif_rx(skb);
+#endif
                        dev->last_rx = jiffies;
                        rp->stats.rx_bytes += pkt_len;
                        rp->stats.rx_packets++;
@@ -1561,13 +1548,15 @@ static void rhine_rx(struct net_device *dev)
                                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);
        }
+
+       return count;
 }
 
 /*
@@ -1698,9 +1687,6 @@ 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. */
-               /* 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);
@@ -1756,6 +1742,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);
+       rhine_set_carrier(&rp->mii_if);
 
        return rc;
 }
@@ -1817,7 +1804,7 @@ static int rhine_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        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,
@@ -1842,6 +1829,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);
+       rhine_set_carrier(&rp->mii_if);
 
        return rc;
 }
@@ -1854,6 +1842,9 @@ static int rhine_close(struct net_device *dev)
        spin_lock_irq(&rp->lock);
 
        netif_stop_queue(dev);
+#ifdef CONFIG_VIA_RHINE_NAPI
+       napi_disable(&rp->napi);
+#endif
 
        if (debug > 1)
                printk(KERN_DEBUG "%s: Shutting down ethercard, "
@@ -1935,7 +1926,8 @@ static void rhine_shutdown (struct pci_dev *pdev)
        }
 
        /* 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() */
 
@@ -1951,6 +1943,9 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
        if (!netif_running(dev))
                return 0;
 
+#ifdef CONFIG_VIA_RHINE_NAPI
+       napi_disable(&rp->napi);
+#endif
        netif_device_detach(dev);
        pci_save_state(pdev);
 
@@ -1972,7 +1967,7 @@ static int rhine_resume(struct pci_dev *pdev)
        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);
@@ -2012,6 +2007,23 @@ static struct pci_driver rhine_driver = {
        .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)
 {
@@ -2019,7 +2031,17 @@ static int __init rhine_init(void)
 #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);
 }