]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge upstream (approx. 2.6.12-git8) into 'janitor' branch of netdev-2.6.
authorJeff Garzik <jgarzik@pretzel.yyz.us>
Sun, 26 Jun 2005 21:11:03 +0000 (17:11 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Sun, 26 Jun 2005 21:11:03 +0000 (17:11 -0400)
1  2 
drivers/net/8139cp.c
drivers/net/ixgb/ixgb_main.c

diff --combined drivers/net/8139cp.c
index ca4c9ac7e11550689f37bfa990ad9fead086dec1,72cdf19e1be1fd6358c39718ea534e73e5531b87..ca7746dd164f1e1a1b32c67b25d2dce82f9ab50c
  
  #include <linux/config.h>
  #include <linux/module.h>
+ #include <linux/moduleparam.h>
  #include <linux/kernel.h>
  #include <linux/compiler.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/init.h>
  #include <linux/pci.h>
 +#include <linux/dma-mapping.h>
  #include <linux/delay.h>
  #include <linux/ethtool.h>
  #include <linux/mii.h>
@@@ -92,16 -92,17 +93,17 @@@ KERN_INFO DRV_NAME ": 10/100 PCI Ethern
  
  MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
  MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
+ MODULE_VERSION(DRV_VERSION);
  MODULE_LICENSE("GPL");
  
  static int debug = -1;
MODULE_PARM (debug, "i");
module_param(debug, int, 0);
  MODULE_PARM_DESC (debug, "8139cp: bitmapped message enable number");
  
  /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
     The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
  static int multicast_filter_limit = 32;
MODULE_PARM (multicast_filter_limit, "i");
module_param(multicast_filter_limit, int, 0);
  MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered multicast addresses");
  
  #define PFX                   DRV_NAME ": "
@@@ -187,6 -188,9 +189,9 @@@ enum 
        RingEnd         = (1 << 30), /* End of descriptor ring */
        FirstFrag       = (1 << 29), /* First segment of a packet */
        LastFrag        = (1 << 28), /* Final segment of a packet */
+       LargeSend       = (1 << 27), /* TCP Large Send Offload (TSO) */
+       MSSShift        = 16,        /* MSS value position */
+       MSSMask         = 0xfff,     /* MSS value: 11 bits */
        TxError         = (1 << 23), /* Tx error summary */
        RxError         = (1 << 20), /* Rx error summary */
        IPCS            = (1 << 18), /* Calculate IP checksum */
@@@ -313,7 -317,7 +318,7 @@@ struct cp_desc 
  struct ring_info {
        struct sk_buff          *skb;
        dma_addr_t              mapping;
-       unsigned                frag;
+       u32                     len;
  };
  
  struct cp_dma_stats {
@@@ -395,6 -399,9 +400,9 @@@ struct cp_private 
  static void __cp_set_rx_mode (struct net_device *dev);
  static void cp_tx (struct cp_private *cp);
  static void cp_clean_rings (struct cp_private *cp);
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void cp_poll_controller(struct net_device *dev);
+ #endif
  
  static struct pci_device_id cp_pci_tbl[] = {
        { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
@@@ -689,6 -696,19 +697,19 @@@ cp_interrupt (int irq, void *dev_instan
        return IRQ_HANDLED;
  }
  
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ /*
+  * Polling receive - used by netconsole and other diagnostic tools
+  * to allow network i/o with interrupts disabled.
+  */
+ static void cp_poll_controller(struct net_device *dev)
+ {
+       disable_irq(dev->irq);
+       cp_interrupt(dev->irq, dev, NULL);
+       enable_irq(dev->irq);
+ }
+ #endif
  static void cp_tx (struct cp_private *cp)
  {
        unsigned tx_head = cp->tx_head;
                        BUG();
  
                pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
-                                       skb->len, PCI_DMA_TODEVICE);
+                                cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
  
                if (status & LastFrag) {
                        if (status & (TxError | TxFIFOUnder)) {
@@@ -750,10 -770,11 +771,11 @@@ static int cp_start_xmit (struct sk_buf
  {
        struct cp_private *cp = netdev_priv(dev);
        unsigned entry;
-       u32 eor;
+       u32 eor, flags;
  #if CP_VLAN_TAG_USED
        u32 vlan_tag = 0;
  #endif
+       int mss = 0;
  
        spin_lock_irq(&cp->lock);
  
  
        entry = cp->tx_head;
        eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
+       if (dev->features & NETIF_F_TSO)
+               mss = skb_shinfo(skb)->tso_size;
        if (skb_shinfo(skb)->nr_frags == 0) {
                struct cp_desc *txd = &cp->tx_ring[entry];
                u32 len;
                txd->addr = cpu_to_le64(mapping);
                wmb();
  
-               if (skb->ip_summed == CHECKSUM_HW) {
+               flags = eor | len | DescOwn | FirstFrag | LastFrag;
+               if (mss)
+                       flags |= LargeSend | ((mss & MSSMask) << MSSShift);
+               else if (skb->ip_summed == CHECKSUM_HW) {
                        const struct iphdr *ip = skb->nh.iph;
                        if (ip->protocol == IPPROTO_TCP)
-                               txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-                                                        FirstFrag | LastFrag |
-                                                        IPCS | TCPCS);
+                               flags |= IPCS | TCPCS;
                        else if (ip->protocol == IPPROTO_UDP)
-                               txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-                                                        FirstFrag | LastFrag |
-                                                        IPCS | UDPCS);
+                               flags |= IPCS | UDPCS;
                        else
-                               BUG();
-               } else
-                       txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-                                                FirstFrag | LastFrag);
+                               WARN_ON(1);     /* we need a WARN() */
+               }
+               txd->opts1 = cpu_to_le32(flags);
                wmb();
  
                cp->tx_skb[entry].skb = skb;
                cp->tx_skb[entry].mapping = mapping;
-               cp->tx_skb[entry].frag = 0;
+               cp->tx_skb[entry].len = len;
                entry = NEXT_TX(entry);
        } else {
                struct cp_desc *txd;
                                               first_len, PCI_DMA_TODEVICE);
                cp->tx_skb[entry].skb = skb;
                cp->tx_skb[entry].mapping = first_mapping;
-               cp->tx_skb[entry].frag = 1;
+               cp->tx_skb[entry].len = first_len;
                entry = NEXT_TX(entry);
  
                for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
                                                 len, PCI_DMA_TODEVICE);
                        eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
  
-                       if (skb->ip_summed == CHECKSUM_HW) {
-                               ctrl = eor | len | DescOwn | IPCS;
+                       ctrl = eor | len | DescOwn;
+                       if (mss)
+                               ctrl |= LargeSend |
+                                       ((mss & MSSMask) << MSSShift);
+                       else if (skb->ip_summed == CHECKSUM_HW) {
                                if (ip->protocol == IPPROTO_TCP)
-                                       ctrl |= TCPCS;
+                                       ctrl |= IPCS | TCPCS;
                                else if (ip->protocol == IPPROTO_UDP)
-                                       ctrl |= UDPCS;
+                                       ctrl |= IPCS | UDPCS;
                                else
                                        BUG();
-                       } else
-                               ctrl = eor | len | DescOwn;
+                       }
  
                        if (frag == skb_shinfo(skb)->nr_frags - 1)
                                ctrl |= LastFrag;
  
                        cp->tx_skb[entry].skb = skb;
                        cp->tx_skb[entry].mapping = mapping;
-                       cp->tx_skb[entry].frag = frag + 2;
+                       cp->tx_skb[entry].len = len;
                        entry = NEXT_TX(entry);
                }
  
@@@ -1075,7 -1102,6 +1103,6 @@@ static int cp_refill_rx (struct cp_priv
                cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
                        skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
                cp->rx_skb[i].skb = skb;
-               cp->rx_skb[i].frag = 0;
  
                cp->rx_ring[i].opts2 = 0;
                cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
@@@ -1127,9 -1153,6 +1154,6 @@@ static void cp_clean_rings (struct cp_p
  {
        unsigned i;
  
-       memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
-       memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
        for (i = 0; i < CP_RX_RING_SIZE; i++) {
                if (cp->rx_skb[i].skb) {
                        pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
        for (i = 0; i < CP_TX_RING_SIZE; i++) {
                if (cp->tx_skb[i].skb) {
                        struct sk_buff *skb = cp->tx_skb[i].skb;
                        pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
-                                        skb->len, PCI_DMA_TODEVICE);
-                       dev_kfree_skb(skb);
+                                        cp->tx_skb[i].len, PCI_DMA_TODEVICE);
+                       if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+                               dev_kfree_skb(skb);
                        cp->net_stats.tx_dropped++;
                }
        }
  
+       memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
+       memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
        memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
        memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
  }
@@@ -1539,6 -1567,8 +1568,8 @@@ static struct ethtool_ops cp_ethtool_op
        .set_tx_csum            = ethtool_op_set_tx_csum, /* local! */
        .get_sg                 = ethtool_op_get_sg,
        .set_sg                 = ethtool_op_set_sg,
+       .get_tso                = ethtool_op_get_tso,
+       .set_tso                = ethtool_op_set_tso,
        .get_regs               = cp_get_regs,
        .get_wol                = cp_get_wol,
        .set_wol                = cp_set_wol,
@@@ -1702,19 -1732,19 +1733,19 @@@ static int cp_init_one (struct pci_dev 
  
        /* Configure DMA attributes. */
        if ((sizeof(dma_addr_t) > 4) &&
 -          !pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) &&
 -          !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
 +          !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) &&
 +          !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
                pci_using_dac = 1;
        } else {
                pci_using_dac = 0;
  
 -              rc = pci_set_dma_mask(pdev, 0xffffffffULL);
 +              rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
                if (rc) {
                        printk(KERN_ERR PFX "No usable DMA configuration, "
                               "aborting.\n");
                        goto err_out_res;
                }
 -              rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL);
 +              rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
                if (rc) {
                        printk(KERN_ERR PFX "No usable consistent DMA configuration, "
                               "aborting.\n");
        dev->get_stats = cp_get_stats;
        dev->do_ioctl = cp_ioctl;
        dev->poll = cp_rx_poll;
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller = cp_poll_controller;
+ #endif
        dev->weight = 16;       /* arbitrary? from NAPI_HOWTO.txt. */
  #ifdef BROKEN
        dev->change_mtu = cp_change_mtu;
        if (pci_using_dac)
                dev->features |= NETIF_F_HIGHDMA;
  
+ #if 0 /* disabled by default until verified */
+       dev->features |= NETIF_F_TSO;
+ #endif
        dev->irq = pdev->irq;
  
        rc = register_netdev(dev);
index a6af9d9e340865278cfe4b607efed9e56c087538,35f6a7c271a2be3a1f749716cbe27b1bffc66b98..097b90ccf575b2d17e8f6f67458bcd6003dba96c
@@@ -47,8 -47,7 +47,9 @@@ char ixgb_driver_string[] = "Intel(R) P
  #else
  #define DRIVERNAPI "-NAPI"
  #endif
- #define DRV_VERSION "1.0.90-k2"DRIVERNAPI
 -char ixgb_driver_version[] = "1.0.95-k2"DRIVERNAPI;
++
++#define DRV_VERSION "1.0.95-k2"DRIVERNAPI
 +char ixgb_driver_version[] = DRV_VERSION;
  char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
  
  /* ixgb_pci_tbl - PCI Device ID Table
@@@ -104,6 -103,7 +105,7 @@@ static int ixgb_change_mtu(struct net_d
  static int ixgb_set_mac(struct net_device *netdev, void *p);
  static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);
  static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
  #ifdef CONFIG_IXGB_NAPI
  static int ixgb_clean(struct net_device *netdev, int *budget);
  static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
@@@ -121,39 -121,25 +123,26 @@@ static void ixgb_vlan_rx_add_vid(struc
  static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
  static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
  
- static int ixgb_notify_reboot(struct notifier_block *, unsigned long event,
-                             void *ptr);
- static int ixgb_suspend(struct pci_dev *pdev, uint32_t state);
  #ifdef CONFIG_NET_POLL_CONTROLLER
  /* for netdump / net console */
  static void ixgb_netpoll(struct net_device *dev);
  #endif
  
- struct notifier_block ixgb_notifier_reboot = {
-       .notifier_call = ixgb_notify_reboot,
-       .next = NULL,
-       .priority = 0
- };
  /* Exported from other modules */
  
  extern void ixgb_check_options(struct ixgb_adapter *adapter);
  
  static struct pci_driver ixgb_driver = {
-       .name = ixgb_driver_name,
+       .name     = ixgb_driver_name,
        .id_table = ixgb_pci_tbl,
-       .probe = ixgb_probe,
-       .remove = __devexit_p(ixgb_remove),
-       /* Power Managment Hooks */
-       .suspend = NULL,
-       .resume = NULL
+       .probe    = ixgb_probe,
+       .remove   = __devexit_p(ixgb_remove),
  };
  
  MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
  MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");
  MODULE_LICENSE("GPL");
 +MODULE_VERSION(DRV_VERSION);
  
  /* some defines for controlling descriptor fetches in h/w */
  #define RXDCTL_PTHRESH_DEFAULT 128    /* chip considers prefech below this */
  static int __init
  ixgb_init_module(void)
  {
-       int ret;
        printk(KERN_INFO "%s - version %s\n",
               ixgb_driver_string, ixgb_driver_version);
  
        printk(KERN_INFO "%s\n", ixgb_copyright);
  
-       ret = pci_module_init(&ixgb_driver);
-       if(ret >= 0) {
-               register_reboot_notifier(&ixgb_notifier_reboot);
-       }
-       return ret;
+       return pci_module_init(&ixgb_driver);
  }
  
  module_init(ixgb_init_module);
  static void __exit
  ixgb_exit_module(void)
  {
-       unregister_reboot_notifier(&ixgb_notifier_reboot);
        pci_unregister_driver(&ixgb_driver);
  }
  
@@@ -226,8 -206,8 +209,8 @@@ ixgb_irq_enable(struct ixgb_adapter *ad
  {
        if(atomic_dec_and_test(&adapter->irq_sem)) {
                IXGB_WRITE_REG(&adapter->hw, IMS,
-                          IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
-                          IXGB_INT_RXO | IXGB_INT_LSC);
+                              IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
+                              IXGB_INT_LSC);
                IXGB_WRITE_FLUSH(&adapter->hw);
        }
  }
@@@ -1211,10 -1191,10 +1194,10 @@@ ixgb_tso(struct ixgb_adapter *adapter, 
                                                | IXGB_CONTEXT_DESC_CMD_TSE
                                                | IXGB_CONTEXT_DESC_CMD_IP
                                                | IXGB_CONTEXT_DESC_CMD_TCP
-                                               | IXGB_CONTEXT_DESC_CMD_RS
                                                | IXGB_CONTEXT_DESC_CMD_IDE
                                                | (skb->len - (hdr_len)));
  
                if(++i == adapter->tx_ring.count) i = 0;
                adapter->tx_ring.next_to_use = i;
  
@@@ -1249,8 -1229,7 +1232,7 @@@ ixgb_tx_csum(struct ixgb_adapter *adapt
                context_desc->mss = 0;
                context_desc->cmd_type_len =
                        cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
-                                       | IXGB_TX_DESC_CMD_RS 
-                                       | IXGB_TX_DESC_CMD_IDE);
+                                   | IXGB_TX_DESC_CMD_IDE);
  
                if(++i == adapter->tx_ring.count) i = 0;
                adapter->tx_ring.next_to_use = i;
@@@ -1275,6 -1254,7 +1257,7 @@@ ixgb_tx_map(struct ixgb_adapter *adapte
  
        unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
        unsigned int f;
        len -= skb->data_len;
  
        i = tx_ring->next_to_use;
@@@ -1528,14 -1508,33 +1511,33 @@@ ixgb_change_mtu(struct net_device *netd
  void
  ixgb_update_stats(struct ixgb_adapter *adapter)
  {
+       struct net_device *netdev = adapter->netdev;
+       if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) ||
+          (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) {
+               u64 multi = IXGB_READ_REG(&adapter->hw, MPRCL);
+               u32 bcast_l = IXGB_READ_REG(&adapter->hw, BPRCL);
+               u32 bcast_h = IXGB_READ_REG(&adapter->hw, BPRCH);
+               u64 bcast = ((u64)bcast_h << 32) | bcast_l; 
+               multi |= ((u64)IXGB_READ_REG(&adapter->hw, MPRCH) << 32);
+               /* fix up multicast stats by removing broadcasts */
+               multi -= bcast;
+               
+               adapter->stats.mprcl += (multi & 0xFFFFFFFF);
+               adapter->stats.mprch += (multi >> 32);
+               adapter->stats.bprcl += bcast_l; 
+               adapter->stats.bprch += bcast_h;
+       } else {
+               adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
+               adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
+               adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
+               adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
+       }
        adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
        adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
        adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);
        adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);
-       adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
-       adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
-       adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
-       adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
        adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);
        adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);
        adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);
@@@ -1825,7 -1824,6 +1827,6 @@@ ixgb_clean_rx_irq(struct ixgb_adapter *
        struct pci_dev *pdev = adapter->pdev;
        struct ixgb_rx_desc *rx_desc, *next_rxd;
        struct ixgb_buffer *buffer_info, *next_buffer, *next2_buffer;
-       struct sk_buff *skb, *next_skb;
        uint32_t length;
        unsigned int i, j;
        boolean_t cleaned = FALSE;
        buffer_info = &rx_ring->buffer_info[i];
  
        while(rx_desc->status & IXGB_RX_DESC_STATUS_DD) {
+               struct sk_buff *skb, *next_skb;
+               u8 status;
  
  #ifdef CONFIG_IXGB_NAPI
                if(*work_done >= work_to_do)
  
                (*work_done)++;
  #endif
+               status = rx_desc->status;
                skb = buffer_info->skb;
                prefetch(skb->data);
  
                if(++i == rx_ring->count) i = 0;
                next_skb = next_buffer->skb;
                prefetch(next_skb);
  
                cleaned = TRUE;
  
                pci_unmap_single(pdev,
  
                length = le16_to_cpu(rx_desc->length);
  
-               if(unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) {
+               if(unlikely(!(status & IXGB_RX_DESC_STATUS_EOP))) {
  
                        /* All receives must fit into a single buffer */
  
                                         "length<%x>\n", length);
  
                        dev_kfree_skb_irq(skb);
-                       rx_desc->status = 0;
-                       buffer_info->skb = NULL;
-                       rx_desc = next_rxd;
-                       buffer_info = next_buffer;
-                       continue;
+                       goto rxdesc_done;
                }
  
                if (unlikely(rx_desc->errors
                                IXGB_RX_DESC_ERRORS_RXE))) {
  
                        dev_kfree_skb_irq(skb);
-                       rx_desc->status = 0;
-                       buffer_info->skb = NULL;
-                       rx_desc = next_rxd;
-                       buffer_info = next_buffer;
-                       continue;
+                       goto rxdesc_done;
                }
  
                /* Good Receive */
  
                skb->protocol = eth_type_trans(skb, netdev);
  #ifdef CONFIG_IXGB_NAPI
-               if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+               if(adapter->vlgrp && (status & IXGB_RX_DESC_STATUS_VP)) {
                        vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
                                le16_to_cpu(rx_desc->special) &
                                        IXGB_RX_DESC_SPECIAL_VLAN_MASK);
                        netif_receive_skb(skb);
                }
  #else /* CONFIG_IXGB_NAPI */
-               if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+               if(adapter->vlgrp && (status & IXGB_RX_DESC_STATUS_VP)) {
                        vlan_hwaccel_rx(skb, adapter->vlgrp,
                                le16_to_cpu(rx_desc->special) &
                                        IXGB_RX_DESC_SPECIAL_VLAN_MASK);
  #endif /* CONFIG_IXGB_NAPI */
                netdev->last_rx = jiffies;
  
+ rxdesc_done:
+               /* clean up descriptor, might be written over by hw */
                rx_desc->status = 0;
                buffer_info->skb = NULL;
  
+               /* use prefetched values */
                rx_desc = next_rxd;
                buffer_info = next_buffer;
        }
@@@ -1961,8 -1955,8 +1958,8 @@@ ixgb_alloc_rx_buffers(struct ixgb_adapt
  
        num_group_tail_writes = IXGB_RX_BUFFER_WRITE;
  
-       /* leave one descriptor unused */
-       while(--cleancount > 0) {
+       /* leave three descriptors unused */
+       while(--cleancount > 2) {
                rx_desc = IXGB_RX_DESC(*rx_ring, i);
  
                skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
                                   PCI_DMA_FROMDEVICE);
  
                rx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
+               /* guarantee DD bit not set now before h/w gets descriptor
+                * this is the rest of the workaround for h/w double 
+                * writeback. */
+               rx_desc->status = 0;
  
                if((i & ~(num_group_tail_writes- 1)) == i) {
                        /* Force memory writes to complete before letting h/w
@@@ -2101,54 -2099,6 +2102,6 @@@ ixgb_restore_vlan(struct ixgb_adapter *
        }
  }
  
- /**
-  * ixgb_notify_reboot - handles OS notification of reboot event.
-  * @param nb notifier block, unused
-  * @param event Event being passed to driver to act upon
-  * @param p A pointer to our net device
-  **/
- static int
- ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
- {
-       struct pci_dev *pdev = NULL;
-       switch(event) {
-       case SYS_DOWN:
-       case SYS_HALT:
-       case SYS_POWER_OFF:
-               while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
-                       if (pci_dev_driver(pdev) == &ixgb_driver)
-                               ixgb_suspend(pdev, 3);
-               }
-       }
-       return NOTIFY_DONE;
- }
- /**
-  * ixgb_suspend - driver suspend function called from notify.
-  * @param pdev pci driver structure used for passing to
-  * @param state power state to enter 
-  **/
- static int
- ixgb_suspend(struct pci_dev *pdev, uint32_t state)
- {
-       struct net_device *netdev = pci_get_drvdata(pdev);
-       struct ixgb_adapter *adapter = netdev->priv;
-       netif_device_detach(netdev);
-       if(netif_running(netdev))
-               ixgb_down(adapter, TRUE);
-       pci_save_state(pdev);
-       state = (state > 0) ? 3 : 0;
-       pci_set_power_state(pdev, state);
-       msec_delay(200);
-       return 0;
- }
  #ifdef CONFIG_NET_POLL_CONTROLLER
  /*
   * Polling 'interrupt' - used by things like netconsole to send skbs
  static void ixgb_netpoll(struct net_device *dev)
  {
        struct ixgb_adapter *adapter = dev->priv;
        disable_irq(adapter->pdev->irq);
        ixgb_intr(adapter->pdev->irq, dev, NULL);
        enable_irq(adapter->pdev->irq);