Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / net / ixgb / ixgb_main.c
index 037b5c3..c68b182 100644 (file)
@@ -1,49 +1,33 @@
 /*******************************************************************************
 
-  
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
-  
-  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 the Free 
-  Software Foundation; either version 2 of the License, or (at your option) 
-  any later version.
-  
-  This program is distributed in the hope that it will be useful, but WITHOUT 
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  Intel PRO/10GbE Linux driver
+  Copyright(c) 1999 - 2006 Intel Corporation.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.
-  
+
   You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc., 59 
-  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-  
-  The full GNU General Public License is included in this distribution in the
-  file called LICENSE.
-  
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
 
 #include "ixgb.h"
 
-/* Change Log
- * 1.0.96 04/19/05
- * - Make needlessly global code static -- bunk@stusta.de
- * - ethtool cleanup -- shemminger@osdl.org
- * - Support for MODULE_VERSION -- linville@tuxdriver.com
- * - add skb_header_cloned check to the tso path -- herbert@apana.org.au
- * 1.0.88 01/05/05
- * - include fix to the condition that determines when to quit NAPI - Robert Olsson
- * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
- * 1.0.84 10/26/04
- * - reset buffer_info->dma in Tx resource cleanup logic
- * 1.0.83 10/12/04
- * - sparse cleanup - shemminger@osdl.org
- * - fix tx resource cleanup logic
- */
-
 char ixgb_driver_name[] = "ixgb";
 static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
 
@@ -52,9 +36,9 @@ static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION            "1.0.104-k4"DRIVERNAPI
-char ixgb_driver_version[] = DRV_VERSION;
-static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+#define DRV_VERSION            "1.0.126-k4"DRIVERNAPI
+const char ixgb_driver_version[] = DRV_VERSION;
+static const char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
 /* ixgb_pci_tbl - PCI Device ID Table
  *
@@ -83,7 +67,7 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
 /* Local Function Prototypes */
 
 int ixgb_up(struct ixgb_adapter *adapter);
-void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
+void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
 void ixgb_reset(struct ixgb_adapter *adapter);
 int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
 int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
@@ -109,20 +93,19 @@ static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
 static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
 static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
 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);
+static irqreturn_t ixgb_intr(int irq, void *data);
+static bool 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,
-                                  int *work_done, int work_to_do);
+static int ixgb_clean(struct napi_struct *napi, int budget);
+static bool ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
+                             int *work_done, int work_to_do);
 #else
-static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
+static bool ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
 #endif
 static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
-void ixgb_set_ethtool_ops(struct net_device *netdev);
 static void ixgb_tx_timeout(struct net_device *dev);
-static void ixgb_tx_timeout_task(struct net_device *dev);
+static void ixgb_tx_timeout_task(struct work_struct *work);
 static void ixgb_vlan_rx_register(struct net_device *netdev,
                                  struct vlan_group *grp);
 static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
@@ -134,15 +117,23 @@ static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
 static void ixgb_netpoll(struct net_device *dev);
 #endif
 
-/* Exported from other modules */
+static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
+                            enum pci_channel_state state);
+static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev);
+static void ixgb_io_resume (struct pci_dev *pdev);
 
-extern void ixgb_check_options(struct ixgb_adapter *adapter);
+static struct pci_error_handlers ixgb_err_handler = {
+       .error_detected = ixgb_io_error_detected,
+       .slot_reset = ixgb_io_slot_reset,
+       .resume = ixgb_io_resume,
+};
 
 static struct pci_driver ixgb_driver = {
        .name     = ixgb_driver_name,
        .id_table = ixgb_pci_tbl,
        .probe    = ixgb_probe,
        .remove   = __devexit_p(ixgb_remove),
+       .err_handler = &ixgb_err_handler
 };
 
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -156,12 +147,12 @@ module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
 /* some defines for controlling descriptor fetches in h/w */
-#define RXDCTL_WTHRESH_DEFAULT 16      /* chip writes back at this many or RXT0 */
-#define RXDCTL_PTHRESH_DEFAULT 0               /* chip considers prefech below
-                                                * this */
-#define RXDCTL_HTHRESH_DEFAULT 0               /* chip will only prefetch if tail
-                                                * is pushed this many descriptors
-                                                * from head */
+#define RXDCTL_WTHRESH_DEFAULT 15  /* chip writes back at this many or RXT0 */
+#define RXDCTL_PTHRESH_DEFAULT 0   /* chip considers prefech below
+                                    * this */
+#define RXDCTL_HTHRESH_DEFAULT 0   /* chip will only prefetch if tail
+                                    * is pushed this many descriptors
+                                    * from head */
 
 /**
  * ixgb_init_module - Driver Registration Routine
@@ -178,7 +169,7 @@ ixgb_init_module(void)
 
        printk(KERN_INFO "%s\n", ixgb_copyright);
 
-       return pci_module_init(&ixgb_driver);
+       return pci_register_driver(&ixgb_driver);
 }
 
 module_init(ixgb_init_module);
@@ -206,7 +197,6 @@ module_exit(ixgb_exit_module);
 static void
 ixgb_irq_disable(struct ixgb_adapter *adapter)
 {
-       atomic_inc(&adapter->irq_sem);
        IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
        IXGB_WRITE_FLUSH(&adapter->hw);
        synchronize_irq(adapter->pdev->irq);
@@ -220,19 +210,19 @@ ixgb_irq_disable(struct ixgb_adapter *adapter)
 static void
 ixgb_irq_enable(struct ixgb_adapter *adapter)
 {
-       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_LSC);
-               IXGB_WRITE_FLUSH(&adapter->hw);
-       }
+       u32 val = IXGB_INT_RXT0 | IXGB_INT_RXDMT0 |
+                 IXGB_INT_TXDW | IXGB_INT_LSC;
+       if (adapter->hw.subsystem_vendor_id == SUN_SUBVENDOR_ID)
+               val |= IXGB_INT_GPI0;
+       IXGB_WRITE_REG(&adapter->hw, IMS, val);
+       IXGB_WRITE_FLUSH(&adapter->hw);
 }
 
 int
 ixgb_up(struct ixgb_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
-       int err;
+       int err, irq_flags = IRQF_SHARED;
        int max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
        struct ixgb_hw *hw = &adapter->hw;
 
@@ -251,26 +241,21 @@ ixgb_up(struct ixgb_adapter *adapter)
        /* disable interrupts and get the hardware into a known state */
        IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
 
-#ifdef CONFIG_PCI_MSI
-       {
-       boolean_t pcix = (IXGB_READ_REG(&adapter->hw, STATUS) & 
-                                                 IXGB_STATUS_PCIX_MODE) ? TRUE : FALSE;
-       adapter->have_msi = TRUE;
-
-       if (!pcix)
-          adapter->have_msi = FALSE;
-       else if((err = pci_enable_msi(adapter->pdev))) {
-               DPRINTK(PROBE, ERR,
-                "Unable to allocate MSI interrupt Error: %d\n", err);
-               adapter->have_msi = FALSE;
+       /* only enable MSI if bus is in PCI-X mode */
+       if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_PCIX_MODE) {
+               err = pci_enable_msi(adapter->pdev);
+               if (!err) {
+                       adapter->have_msi = 1;
+                       irq_flags = 0;
+               }
                /* proceed to try to request regular interrupt */
        }
-       }
 
-#endif
-       if((err = request_irq(adapter->pdev->irq, &ixgb_intr,
-                                 SA_SHIRQ | SA_SAMPLE_RANDOM,
-                                 netdev->name, netdev))) {
+       err = request_irq(adapter->pdev->irq, &ixgb_intr, irq_flags,
+                         netdev->name, netdev);
+       if (err) {
+               if (adapter->have_msi)
+                       pci_disable_msi(adapter->pdev);
                DPRINTK(PROBE, ERR,
                 "Unable to allocate interrupt Error: %d\n", err);
                return err;
@@ -295,33 +280,39 @@ ixgb_up(struct ixgb_adapter *adapter)
                }
        }
 
-       mod_timer(&adapter->watchdog_timer, jiffies);
+       clear_bit(__IXGB_DOWN, &adapter->flags);
 
 #ifdef CONFIG_IXGB_NAPI
-       netif_poll_enable(netdev);
+       napi_enable(&adapter->napi);
 #endif
        ixgb_irq_enable(adapter);
 
+       mod_timer(&adapter->watchdog_timer, jiffies);
+
        return 0;
 }
 
 void
-ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
+ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog)
 {
        struct net_device *netdev = adapter->netdev;
 
+       /* prevent the interrupt handler from restarting watchdog */
+       set_bit(__IXGB_DOWN, &adapter->flags);
+
+#ifdef CONFIG_IXGB_NAPI
+       napi_disable(&adapter->napi);
+#endif
+       /* waiting for NAPI to complete can re-enable interrupts */
        ixgb_irq_disable(adapter);
        free_irq(adapter->pdev->irq, netdev);
-#ifdef CONFIG_PCI_MSI
-       if(adapter->have_msi == TRUE)
+
+       if (adapter->have_msi)
                pci_disable_msi(adapter->pdev);
 
-#endif
        if(kill_watchdog)
                del_timer_sync(&adapter->watchdog_timer);
-#ifdef CONFIG_IXGB_NAPI
-       netif_poll_disable(netdev);
-#endif
+
        adapter->link_speed = 0;
        adapter->link_duplex = 0;
        netif_carrier_off(netdev);
@@ -335,10 +326,22 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
 void
 ixgb_reset(struct ixgb_adapter *adapter)
 {
+       struct ixgb_hw *hw = &adapter->hw;
 
-       ixgb_adapter_stop(&adapter->hw);
-       if(!ixgb_init_hw(&adapter->hw))
+       ixgb_adapter_stop(hw);
+       if (!ixgb_init_hw(hw))
                DPRINTK(PROBE, ERR, "ixgb_init_hw failed.\n");
+
+       /* restore frame size information */
+       IXGB_WRITE_REG(hw, MFS, hw->max_frame_size << IXGB_MFS_SHIFT);
+       if (hw->max_frame_size >
+           IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
+               u32 ctrl0 = IXGB_READ_REG(hw, CTRL0);
+               if (!(ctrl0 & IXGB_CTRL0_JFE)) {
+                       ctrl0 |= IXGB_CTRL0_JFE;
+                       IXGB_WRITE_REG(hw, CTRL0, ctrl0);
+               }
+       }
 }
 
 /**
@@ -393,7 +396,6 @@ ixgb_probe(struct pci_dev *pdev,
                goto err_alloc_etherdev;
        }
 
-       SET_MODULE_OWNER(netdev);
        SET_NETDEV_DEV(netdev, &pdev->dev);
 
        pci_set_drvdata(pdev, netdev);
@@ -432,8 +434,7 @@ ixgb_probe(struct pci_dev *pdev,
        netdev->tx_timeout = &ixgb_tx_timeout;
        netdev->watchdog_timeo = 5 * HZ;
 #ifdef CONFIG_IXGB_NAPI
-       netdev->poll = &ixgb_clean;
-       netdev->weight = 64;
+       netif_napi_add(netdev, &adapter->napi, ixgb_clean, 64);
 #endif
        netdev->vlan_rx_register = ixgb_vlan_rx_register;
        netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid;
@@ -442,7 +443,7 @@ ixgb_probe(struct pci_dev *pdev,
        netdev->poll_controller = ixgb_netpoll;
 #endif
 
-       strcpy(netdev->name, pci_name(pdev));
+       strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
        netdev->mem_start = mmio_start;
        netdev->mem_end = mmio_start + mmio_len;
        netdev->base_addr = adapter->hw.io_base;
@@ -461,9 +462,7 @@ ixgb_probe(struct pci_dev *pdev,
                           NETIF_F_HW_VLAN_TX |
                           NETIF_F_HW_VLAN_RX |
                           NETIF_F_HW_VLAN_FILTER;
-#ifdef NETIF_F_TSO
        netdev->features |= NETIF_F_TSO;
-#endif
 #ifdef NETIF_F_LLTX
        netdev->features |= NETIF_F_LLTX;
 #endif
@@ -494,8 +493,7 @@ ixgb_probe(struct pci_dev *pdev,
        adapter->watchdog_timer.function = &ixgb_watchdog;
        adapter->watchdog_timer.data = (unsigned long)adapter;
 
-       INIT_WORK(&adapter->tx_timeout_task,
-                 (void (*)(void *))ixgb_tx_timeout_task, netdev);
+       INIT_WORK(&adapter->tx_timeout_task, ixgb_tx_timeout_task);
 
        strcpy(netdev->name, "eth%d");
        if((err = register_netdev(netdev)))
@@ -592,9 +590,9 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
        /* enable flow control to be programmed */
        hw->fc.send_xon = 1;
 
-       atomic_set(&adapter->irq_sem, 1);
        spin_lock_init(&adapter->tx_lock);
 
+       set_bit(__IXGB_DOWN, &adapter->flags);
        return 0;
 }
 
@@ -659,7 +657,7 @@ ixgb_close(struct net_device *netdev)
 {
        struct ixgb_adapter *adapter = netdev_priv(netdev);
 
-       ixgb_down(adapter, TRUE);
+       ixgb_down(adapter, true);
 
        ixgb_free_tx_resources(adapter);
        ixgb_free_rx_resources(adapter);
@@ -693,7 +691,7 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
        /* round up to nearest 4K */
 
        txdr->size = txdr->count * sizeof(struct ixgb_tx_desc);
-       IXGB_ROUNDUP(txdr->size, 4096);
+       txdr->size = ALIGN(txdr->size, 4096);
 
        txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
        if(!txdr->desc) {
@@ -782,7 +780,7 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
        /* Round up to nearest 4K */
 
        rxdr->size = rxdr->count * sizeof(struct ixgb_rx_desc);
-       IXGB_ROUNDUP(rxdr->size, 4096);
+       rxdr->size = ALIGN(rxdr->size, 4096);
 
        rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
 
@@ -884,7 +882,7 @@ ixgb_configure_rx(struct ixgb_adapter *adapter)
        IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
 
        /* Enable Receive Checksum Offload for TCP and UDP */
-       if(adapter->rx_csum == TRUE) {
+       if (adapter->rx_csum) {
                rxcsum = IXGB_READ_REG(hw, RXCSUM);
                rxcsum |= IXGB_RXCSUM_TUOFL;
                IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
@@ -1101,7 +1099,8 @@ ixgb_set_multi(struct net_device *netdev)
                rctl |= IXGB_RCTL_MPE;
                IXGB_WRITE_REG(hw, RCTL, rctl);
        } else {
-               uint8_t mta[netdev->mc_count * IXGB_ETH_LENGTH_OF_ADDRESS];
+               uint8_t mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES *
+                           IXGB_ETH_LENGTH_OF_ADDRESS];
 
                IXGB_WRITE_REG(hw, RCTL, rctl);
 
@@ -1166,7 +1165,7 @@ ixgb_watchdog(unsigned long data)
        }
 
        /* Force detection of hung controller every watchdog period */
-       adapter->detect_tx_hung = TRUE;
+       adapter->detect_tx_hung = true;
 
        /* generate an interrupt to force clean up of any stragglers */
        IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);
@@ -1182,36 +1181,41 @@ ixgb_watchdog(unsigned long data)
 static int
 ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
-#ifdef NETIF_F_TSO
        struct ixgb_context_desc *context_desc;
        unsigned int i;
        uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
        uint16_t ipcse, tucse, mss;
        int err;
 
-       if(likely(skb_shinfo(skb)->tso_size)) {
+       if (likely(skb_is_gso(skb))) {
+               struct ixgb_buffer *buffer_info;
+               struct iphdr *iph;
+
                if (skb_header_cloned(skb)) {
                        err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
                        if (err)
                                return err;
                }
 
-               hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
-               mss = skb_shinfo(skb)->tso_size;
-               skb->nh.iph->tot_len = 0;
-               skb->nh.iph->check = 0;
-               skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
-                                                     skb->nh.iph->daddr,
-                                                     0, IPPROTO_TCP, 0);
-               ipcss = skb->nh.raw - skb->data;
-               ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;
-               ipcse = skb->h.raw - skb->data - 1;
-               tucss = skb->h.raw - skb->data;
-               tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
+               hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+               mss = skb_shinfo(skb)->gso_size;
+               iph = ip_hdr(skb);
+               iph->tot_len = 0;
+               iph->check = 0;
+               tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+                                                        iph->daddr, 0,
+                                                        IPPROTO_TCP, 0);
+               ipcss = skb_network_offset(skb);
+               ipcso = (void *)&(iph->check) - (void *)skb->data;
+               ipcse = skb_transport_offset(skb) - 1;
+               tucss = skb_transport_offset(skb);
+               tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
                tucse = 0;
 
                i = adapter->tx_ring.next_to_use;
                context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
+               buffer_info = &adapter->tx_ring.buffer_info[i];
+               WARN_ON(buffer_info->dma != 0);
 
                context_desc->ipcss = ipcss;
                context_desc->ipcso = ipcso;
@@ -1236,24 +1240,26 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
 
                return 1;
        }
-#endif
 
        return 0;
 }
 
-static boolean_t
+static bool
 ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
        struct ixgb_context_desc *context_desc;
        unsigned int i;
        uint8_t css, cso;
 
-       if(likely(skb->ip_summed == CHECKSUM_HW)) {
-               css = skb->h.raw - skb->data;
-               cso = (skb->h.raw + skb->csum) - skb->data;
+       if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+               struct ixgb_buffer *buffer_info;
+               css = skb_transport_offset(skb);
+               cso = css + skb->csum_offset;
 
                i = adapter->tx_ring.next_to_use;
                context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
+               buffer_info = &adapter->tx_ring.buffer_info[i];
+               WARN_ON(buffer_info->dma != 0);
 
                context_desc->tucss = css;
                context_desc->tucso = cso;
@@ -1270,10 +1276,10 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
                if(++i == adapter->tx_ring.count) i = 0;
                adapter->tx_ring.next_to_use = i;
 
-               return TRUE;
+               return true;
        }
 
-       return FALSE;
+       return false;
 }
 
 #define IXGB_MAX_TXD_PWR       14
@@ -1287,6 +1293,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
        struct ixgb_buffer *buffer_info;
        int len = skb->len;
        unsigned int offset = 0, size, count = 0, i;
+       unsigned int mss = skb_shinfo(skb)->gso_size;
 
        unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
        unsigned int f;
@@ -1297,8 +1304,14 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
 
        while(len) {
                buffer_info = &tx_ring->buffer_info[i];
-               size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);
+               size = min(len, IXGB_MAX_DATA_PER_TXD);
+               /* Workaround for premature desc write-backs
+                * in TSO mode.  Append 4-byte sentinel desc */
+               if (unlikely(mss && !nr_frags && size == len && size > 8))
+                       size -= 4;
+
                buffer_info->length = size;
+               WARN_ON(buffer_info->dma != 0);
                buffer_info->dma =
                        pci_map_single(adapter->pdev,
                                skb->data + offset,
@@ -1322,7 +1335,14 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
 
                while(len) {
                        buffer_info = &tx_ring->buffer_info[i];
-                       size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);
+                       size = min(len, IXGB_MAX_DATA_PER_TXD);
+
+                       /* Workaround for premature desc write-backs
+                        * in TSO mode.  Append 4-byte sentinel desc */
+                       if (unlikely(mss && (f == (nr_frags - 1))
+                                    && size == len && size > 8))
+                               size -= 4;
+
                        buffer_info->length = size;
                        buffer_info->dma =
                                pci_map_page(adapter->pdev,
@@ -1397,11 +1417,43 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
        IXGB_WRITE_REG(&adapter->hw, TDT, i);
 }
 
+static int __ixgb_maybe_stop_tx(struct net_device *netdev, int size)
+{
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+
+       netif_stop_queue(netdev);
+       /* Herbert's original patch had:
+        *  smp_mb__after_netif_stop_queue();
+        * but since that doesn't exist yet, just open code it. */
+       smp_mb();
+
+       /* We need to check again in a case another CPU has just
+        * made room available. */
+       if (likely(IXGB_DESC_UNUSED(tx_ring) < size))
+               return -EBUSY;
+
+       /* A reprieve! */
+       netif_start_queue(netdev);
+       ++adapter->restart_queue;
+       return 0;
+}
+
+static int ixgb_maybe_stop_tx(struct net_device *netdev,
+                              struct ixgb_desc_ring *tx_ring, int size)
+{
+       if (likely(IXGB_DESC_UNUSED(tx_ring) >= size))
+               return 0;
+       return __ixgb_maybe_stop_tx(netdev, size);
+}
+
+
 /* Tx Descriptors needed, worst case */
 #define TXD_USE_COUNT(S) (((S) >> IXGB_MAX_TXD_PWR) + \
                         (((S) & (IXGB_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
-#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) + \
-       MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1
+#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) /* skb->date */ + \
+       MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1 /* for context */ \
+       + 1 /* one more needed for sentinel TSO workaround */
 
 static int
 ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -1413,14 +1465,18 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        int vlan_id = 0;
        int tso;
 
+       if (test_bit(__IXGB_DOWN, &adapter->flags)) {
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+
        if(skb->len <= 0) {
                dev_kfree_skb_any(skb);
                return 0;
        }
 
 #ifdef NETIF_F_LLTX
-       local_irq_save(flags);
-       if (!spin_trylock(&adapter->tx_lock)) {
+       if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
                /* Collision - tell upper layer to requeue */
                local_irq_restore(flags);
                return NETDEV_TX_LOCKED;
@@ -1429,7 +1485,8 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        spin_lock_irqsave(&adapter->tx_lock, flags);
 #endif
 
-       if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
+       if (unlikely(ixgb_maybe_stop_tx(netdev, &adapter->tx_ring,
+                     DESC_NEEDED))) {
                netif_stop_queue(netdev);
                spin_unlock_irqrestore(&adapter->tx_lock, flags);
                return NETDEV_TX_BUSY;
@@ -1467,8 +1524,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
 #ifdef NETIF_F_LLTX
        /* Make sure there is space in the ring for the next send. */
-       if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED))
-               netif_stop_queue(netdev);
+       ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED);
 
        spin_unlock_irqrestore(&adapter->tx_lock, flags);
 
@@ -1491,12 +1547,13 @@ ixgb_tx_timeout(struct net_device *netdev)
 }
 
 static void
-ixgb_tx_timeout_task(struct net_device *netdev)
+ixgb_tx_timeout_task(struct work_struct *work)
 {
-       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       struct ixgb_adapter *adapter =
+               container_of(work, struct ixgb_adapter, tx_timeout_task);
 
        adapter->tx_timeout_count++;
-       ixgb_down(adapter, TRUE);
+       ixgb_down(adapter, true);
        ixgb_up(adapter);
 }
 
@@ -1543,7 +1600,7 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
        netdev->mtu = new_mtu;
 
        if ((old_max_frame != max_frame) && netif_running(netdev)) {
-               ixgb_down(adapter, TRUE);
+               ixgb_down(adapter, true);
                ixgb_up(adapter);
        }
 
@@ -1559,6 +1616,11 @@ void
 ixgb_update_stats(struct ixgb_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
+       struct pci_dev *pdev = adapter->pdev;
+
+       /* Prevent stats update while adapter is being reset */
+       if (pci_channel_offline(pdev))
+               return;
 
        if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) ||
           (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) {
@@ -1680,11 +1742,10 @@ ixgb_update_stats(struct ixgb_adapter *adapter)
  * ixgb_intr - Interrupt Handler
  * @irq: interrupt number
  * @data: pointer to a network interface device structure
- * @pt_regs: CPU registers structure
  **/
 
 static irqreturn_t
-ixgb_intr(int irq, void *data, struct pt_regs *regs)
+ixgb_intr(int irq, void *data)
 {
        struct net_device *netdev = data;
        struct ixgb_adapter *adapter = netdev_priv(netdev);
@@ -1697,20 +1758,19 @@ ixgb_intr(int irq, void *data, struct pt_regs *regs)
        if(unlikely(!icr))
                return IRQ_NONE;  /* Not our interrupt */
 
-       if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
-               mod_timer(&adapter->watchdog_timer, jiffies);
-       }
+       if (unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)))
+               if (!test_bit(__IXGB_DOWN, &adapter->flags))
+                       mod_timer(&adapter->watchdog_timer, jiffies);
 
 #ifdef CONFIG_IXGB_NAPI
-       if(netif_rx_schedule_prep(netdev)) {
+       if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
 
                /* Disable interrupts and register for poll. The flush 
                  of the posted write is intentionally left out.
                */
 
-               atomic_inc(&adapter->irq_sem);
                IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
-               __netif_rx_schedule(netdev);
+               __netif_rx_schedule(netdev, &adapter->napi);
        }
 #else
        /* yes, that is actually a & and it is meant to make sure that
@@ -1732,27 +1792,22 @@ ixgb_intr(int irq, void *data, struct pt_regs *regs)
  **/
 
 static int
-ixgb_clean(struct net_device *netdev, int *budget)
+ixgb_clean(struct napi_struct *napi, int budget)
 {
-       struct ixgb_adapter *adapter = netdev_priv(netdev);
-       int work_to_do = min(*budget, netdev->quota);
-       int tx_cleaned;
+       struct ixgb_adapter *adapter = container_of(napi, struct ixgb_adapter, napi);
+       struct net_device *netdev = adapter->netdev;
        int work_done = 0;
 
-       tx_cleaned = ixgb_clean_tx_irq(adapter);
-       ixgb_clean_rx_irq(adapter, &work_done, work_to_do);
+       ixgb_clean_tx_irq(adapter);
+       ixgb_clean_rx_irq(adapter, &work_done, budget);
 
-       *budget -= work_done;
-       netdev->quota -= work_done;
-
-       /* if no Tx and not enough Rx work done, exit the polling mode */
-       if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
-               netif_rx_complete(netdev);
+       /* If budget not fully consumed, exit the polling mode */
+       if (work_done < budget) {
+               netif_rx_complete(netdev, napi);
                ixgb_irq_enable(adapter);
-               return 0;
        }
 
-       return 1;
+       return work_done;
 }
 #endif
 
@@ -1761,7 +1816,7 @@ ixgb_clean(struct net_device *netdev, int *budget)
  * @adapter: board private structure
  **/
 
-static boolean_t
+static bool
 ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
 {
        struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
@@ -1769,7 +1824,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
        struct ixgb_tx_desc *tx_desc, *eop_desc;
        struct ixgb_buffer *buffer_info;
        unsigned int i, eop;
-       boolean_t cleaned = FALSE;
+       bool cleaned = false;
 
        i = tx_ring->next_to_clean;
        eop = tx_ring->buffer_info[i].next_to_watch;
@@ -1777,7 +1832,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
 
        while(eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
 
-               for(cleaned = FALSE; !cleaned; ) {
+               for (cleaned = false; !cleaned; ) {
                        tx_desc = IXGB_TX_DESC(*tx_ring, i);
                        buffer_info = &tx_ring->buffer_info[i];
 
@@ -1803,7 +1858,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
        if (unlikely(netif_queue_stopped(netdev))) {
                spin_lock(&adapter->tx_lock);
                if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
-                   (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE))
+                   (IXGB_DESC_UNUSED(tx_ring) >= DESC_NEEDED))
                        netif_wake_queue(netdev);
                spin_unlock(&adapter->tx_lock);
        }
@@ -1811,7 +1866,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
        if(adapter->detect_tx_hung) {
                /* detect a transmit hang in hardware, this serializes the
                 * check with the clearing of time_stamp and movement of i */
-               adapter->detect_tx_hung = FALSE;
+               adapter->detect_tx_hung = false;
                if (tx_ring->buffer_info[eop].dma &&
                   time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ)
                   && !(IXGB_READ_REG(&adapter->hw, STATUS) &
@@ -1881,7 +1936,7 @@ ixgb_rx_checksum(struct ixgb_adapter *adapter,
  * @adapter: board private structure
  **/
 
-static boolean_t
+static bool
 #ifdef CONFIG_IXGB_NAPI
 ixgb_clean_rx_irq(struct ixgb_adapter *adapter, int *work_done, int work_to_do)
 #else
@@ -1895,7 +1950,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
        struct ixgb_buffer *buffer_info, *next_buffer, *next2_buffer;
        uint32_t length;
        unsigned int i, j;
-       boolean_t cleaned = FALSE;
+       bool cleaned = false;
 
        i = rx_ring->next_to_clean;
        rx_desc = IXGB_RX_DESC(*rx_ring, i);
@@ -1929,7 +1984,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
                next_skb = next_buffer->skb;
                prefetch(next_skb);
 
-               cleaned = TRUE;
+               cleaned = true;
 
                pci_unmap_single(pdev,
                                 buffer_info->dma,
@@ -1964,13 +2019,15 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
 #define IXGB_CB_LENGTH 256
                if (length < IXGB_CB_LENGTH) {
                        struct sk_buff *new_skb =
-                           dev_alloc_skb(length + NET_IP_ALIGN);
+                           netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
                        if (new_skb) {
                                skb_reserve(new_skb, NET_IP_ALIGN);
-                               new_skb->dev = netdev;
-                               memcpy(new_skb->data - NET_IP_ALIGN,
-                                      skb->data - NET_IP_ALIGN,
-                                      length + NET_IP_ALIGN);
+                               skb_copy_to_linear_data_offset(new_skb,
+                                                              -NET_IP_ALIGN,
+                                                              (skb->data -
+                                                               NET_IP_ALIGN),
+                                                              (length +
+                                                               NET_IP_ALIGN));
                                /* save the skb in buffer_info as good */
                                buffer_info->skb = skb;
                                skb = new_skb;
@@ -2035,26 +2092,24 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
        struct ixgb_buffer *buffer_info;
        struct sk_buff *skb;
        unsigned int i;
-       int num_group_tail_writes;
        long cleancount;
 
        i = rx_ring->next_to_use;
        buffer_info = &rx_ring->buffer_info[i];
        cleancount = IXGB_DESC_UNUSED(rx_ring);
 
-       num_group_tail_writes = IXGB_RX_BUFFER_WRITE;
 
        /* leave three descriptors unused */
        while(--cleancount > 2) {
                /* recycle! its good for you */
-               if (!(skb = buffer_info->skb))
-                       skb = dev_alloc_skb(adapter->rx_buffer_len
-                                           + NET_IP_ALIGN);
-               else {
+               skb = buffer_info->skb;
+               if (skb) {
                        skb_trim(skb, 0);
                        goto map_skb;
                }
 
+               skb = netdev_alloc_skb(netdev, adapter->rx_buffer_len
+                                      + NET_IP_ALIGN);
                if (unlikely(!skb)) {
                        /* Better luck next round */
                        adapter->alloc_rx_buff_failed++;
@@ -2067,8 +2122,6 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
                 */
                skb_reserve(skb, NET_IP_ALIGN);
 
-               skb->dev = netdev;
-
                buffer_info->skb = skb;
                buffer_info->length = adapter->rx_buffer_len;
 map_skb:
@@ -2144,7 +2197,9 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
                IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
        }
 
-       ixgb_irq_enable(adapter);
+       /* don't enable interrupts unless we are UP */
+       if (adapter->netdev->flags & IFF_UP)
+               ixgb_irq_enable(adapter);
 }
 
 static void
@@ -2169,12 +2224,13 @@ ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
 
        ixgb_irq_disable(adapter);
 
-       if(adapter->vlgrp)
-               adapter->vlgrp->vlan_devices[vid] = NULL;
+       vlan_group_set_device(adapter->vlgrp, vid, NULL);
 
-       ixgb_irq_enable(adapter);
+       /* don't enable interrupts unless we are UP */
+       if (adapter->netdev->flags & IFF_UP)
+               ixgb_irq_enable(adapter);
 
-       /* remove VID from filter table*/
+       /* remove VID from filter table */
 
        index = (vid >> 5) & 0x7F;
        vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
@@ -2190,7 +2246,7 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter)
        if(adapter->vlgrp) {
                uint16_t vid;
                for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
-                       if(!adapter->vlgrp->vlan_devices[vid])
+                       if(!vlan_group_get_device(adapter->vlgrp, vid))
                                continue;
                        ixgb_vlan_rx_add_vid(adapter->netdev, vid);
                }
@@ -2206,12 +2262,106 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter)
 
 static void ixgb_netpoll(struct net_device *dev)
 {
-       struct ixgb_adapter *adapter = dev->priv;
+       struct ixgb_adapter *adapter = netdev_priv(dev);
 
        disable_irq(adapter->pdev->irq);
-       ixgb_intr(adapter->pdev->irq, dev, NULL);
+       ixgb_intr(adapter->pdev->irq, dev);
        enable_irq(adapter->pdev->irq);
 }
 #endif
 
+/**
+ * ixgb_io_error_detected() - called when PCI error is detected
+ * @pdev    pointer to pci device with error
+ * @state   pci channel state after error
+ *
+ * This callback is called by the PCI subsystem whenever
+ * a PCI bus error is detected.
+ */
+static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
+                                    enum pci_channel_state state)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+
+       if(netif_running(netdev))
+               ixgb_down(adapter, true);
+
+       pci_disable_device(pdev);
+
+       /* Request a slot reset. */
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * ixgb_io_slot_reset - called after the pci bus has been reset.
+ * @pdev    pointer to pci device with error
+ *
+ * This callback is called after the PCI buss has been reset.
+ * Basically, this tries to restart the card from scratch.
+ * This is a shortened version of the device probe/discovery code,
+ * it resembles the first-half of the ixgb_probe() routine.
+ */
+static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+
+       if(pci_enable_device(pdev)) {
+               DPRINTK(PROBE, ERR, "Cannot re-enable PCI device after reset.\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+
+       /* Perform card reset only on one instance of the card */
+       if (0 != PCI_FUNC (pdev->devfn))
+               return PCI_ERS_RESULT_RECOVERED;
+
+       pci_set_master(pdev);
+
+       netif_carrier_off(netdev);
+       netif_stop_queue(netdev);
+       ixgb_reset(adapter);
+
+       /* Make sure the EEPROM is good */
+       if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
+               DPRINTK(PROBE, ERR, "After reset, the EEPROM checksum is not valid.\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+       ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
+       memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
+
+       if(!is_valid_ether_addr(netdev->perm_addr)) {
+               DPRINTK(PROBE, ERR, "After reset, invalid MAC address.\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+
+       return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * ixgb_io_resume - called when its OK to resume normal operations
+ * @pdev    pointer to pci device with error
+ *
+ * The error recovery driver tells us that its OK to resume
+ * normal operation. Implementation resembles the second-half
+ * of the ixgb_probe() routine.
+ */
+static void ixgb_io_resume (struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+
+       pci_set_master(pdev);
+
+       if(netif_running(netdev)) {
+               if(ixgb_up(adapter)) {
+                       printk ("ixgb: can't bring device back up after reset\n");
+                       return;
+               }
+       }
+
+       netif_device_attach(netdev);
+       mod_timer(&adapter->watchdog_timer, jiffies);
+}
+
 /* ixgb_main.c */