Merge branch 'master' into upstream
Jeff Garzik [Thu, 8 Jun 2006 19:24:46 +0000 (15:24 -0400)]
108 files changed:
Documentation/networking/README.ipw2200
MAINTAINERS
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/au1000_eth.c
drivers/net/cassini.c
drivers/net/e1000/Makefile
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c
drivers/net/e1000/e1000_osdep.h
drivers/net/e1000/e1000_param.c
drivers/net/epic100.c
drivers/net/forcedeth.c
drivers/net/ibmlana.c
drivers/net/ibmlana.h
drivers/net/ibmveth.c
drivers/net/ibmveth.h
drivers/net/ixgb/Makefile
drivers/net/ixgb/ixgb.h
drivers/net/ixgb/ixgb_ee.c
drivers/net/ixgb/ixgb_ee.h
drivers/net/ixgb/ixgb_ethtool.c
drivers/net/ixgb/ixgb_hw.c
drivers/net/ixgb/ixgb_hw.h
drivers/net/ixgb/ixgb_ids.h
drivers/net/ixgb/ixgb_main.c
drivers/net/ixgb/ixgb_osdep.h
drivers/net/ixgb/ixgb_param.c
drivers/net/myri10ge/Makefile [new file with mode: 0644]
drivers/net/myri10ge/myri10ge.c [new file with mode: 0644]
drivers/net/myri10ge/myri10ge_mcp.h [new file with mode: 0644]
drivers/net/myri10ge/myri10ge_mcp_gen_header.h [new file with mode: 0644]
drivers/net/pcmcia/pcnet_cs.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/smsc.c [new file with mode: 0644]
drivers/net/r8169.c
drivers/net/s2io-regs.h
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sis900.c
drivers/net/sis900.h
drivers/net/smc911x.c [new file with mode: 0644]
drivers/net/smc911x.h [new file with mode: 0644]
drivers/net/smc91x.h
drivers/net/sungem_phy.c
drivers/net/tulip/de2104x.c
drivers/net/tulip/de4x5.c
drivers/net/tulip/de4x5.h
drivers/net/tulip/dmfe.c
drivers/net/tulip/eeprom.c
drivers/net/tulip/interrupt.c
drivers/net/tulip/media.c
drivers/net/tulip/tulip.h
drivers/net/tulip/tulip_core.c
drivers/net/tulip/uli526x.c
drivers/net/tulip/winbond-840.c
drivers/net/tulip/xircom_cb.c
drivers/net/via-velocity.h
drivers/net/wan/pci200syn.c
drivers/net/wireless/Kconfig
drivers/net/wireless/airo.c
drivers/net/wireless/bcm43xx/bcm43xx.h
drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/hermes.c
drivers/net/wireless/hermes.h
drivers/net/wireless/hostap/hostap_80211_tx.c
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_main.c
drivers/net/wireless/ipw2200.c
drivers/net/wireless/ipw2200.h
drivers/net/wireless/orinoco.c
drivers/net/wireless/orinoco.h
drivers/net/wireless/orinoco_cs.c
drivers/net/wireless/orinoco_nortel.c
drivers/net/wireless/orinoco_pci.c
drivers/net/wireless/orinoco_pci.h [new file with mode: 0644]
drivers/net/wireless/orinoco_plx.c
drivers/net/wireless/orinoco_tmd.c
drivers/net/wireless/spectrum_cs.c
drivers/pci/pci.c
drivers/s390/net/Makefile
drivers/s390/net/ctcmain.c
drivers/s390/net/ctcmain.h
drivers/s390/net/ctctty.c [deleted file]
drivers/s390/net/ctctty.h [deleted file]
include/linux/pci.h
include/linux/pci_ids.h
include/net/ieee80211.h
include/net/ieee80211softmac.h
include/net/ieee80211softmac_wx.h
net/ieee80211/ieee80211_crypt_tkip.c
net/ieee80211/ieee80211_rx.c
net/ieee80211/ieee80211_tx.c
net/ieee80211/ieee80211_wx.c
net/ieee80211/softmac/ieee80211softmac_assoc.c
net/ieee80211/softmac/ieee80211softmac_auth.c
net/ieee80211/softmac/ieee80211softmac_event.c
net/ieee80211/softmac/ieee80211softmac_module.c
net/ieee80211/softmac/ieee80211softmac_priv.h
net/ieee80211/softmac/ieee80211softmac_wx.c

index acb30c5..4f2a40f 100644 (file)
@@ -14,8 +14,8 @@ Copyright (C) 2004-2006, Intel Corporation
 
 README.ipw2200
 
-Version: 1.0.8
-Date   : October 20, 2005
+Version: 1.1.2
+Date   : March 30, 2006
 
 
 Index
@@ -103,7 +103,7 @@ file.
 
 1.1. Overview of Features
 -----------------------------------------------
-The current release (1.0.8) supports the following features:
+The current release (1.1.2) supports the following features:
 
 + BSS mode (Infrastructure, Managed)
 + IBSS mode (Ad-Hoc)
@@ -247,8 +247,8 @@ and can set the contents via echo.  For example:
 % cat /sys/bus/pci/drivers/ipw2200/debug_level
 
 Will report the current debug level of the driver's logging subsystem 
-(only available if CONFIG_IPW_DEBUG was configured when the driver was 
-built).
+(only available if CONFIG_IPW2200_DEBUG was configured when the driver
+was built).
 
 You can set the debug level via:
 
index c3c5842..1421f74 100644 (file)
@@ -1425,6 +1425,8 @@ P:        Jesse Brandeburg
 M:     jesse.brandeburg@intel.com
 P:     Jeff Kirsher
 M:     jeffrey.t.kirsher@intel.com
+P:     Auke Kok
+M:     auke-jan.h.kok@intel.com
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
@@ -1437,6 +1439,8 @@ P:        Jesse Brandeburg
 M:     jesse.brandeburg@intel.com
 P:     Jeff Kirsher
 M:     jeffrey.t.kirsher@intel.com
+P:     Auke Kok
+M:     auke-jan.h.kok@intel.com
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
@@ -1449,6 +1453,8 @@ P:        John Ronciak
 M:     john.ronciak@intel.com
 P:     Jesse Brandeburg
 M:     jesse.brandeburg@intel.com
+P:     Auke Kok
+M:     auke-jan.h.kok@intel.com
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
index 066e22b..46d8c01 100644 (file)
        See the file COPYING in this distribution for more information.
 
        Contributors:
-       
+
                Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
                PCI suspend/resume  - Felipe Damasio <felipewd@terra.com.br>
                LinkChg interrupt   - Felipe Damasio <felipewd@terra.com.br>
-                       
+
        TODO:
        * Test Tx checksumming thoroughly
        * Implement dev->tx_timeout
@@ -461,7 +461,7 @@ static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 static inline void cp_set_rxbufsize (struct cp_private *cp)
 {
        unsigned int mtu = cp->dev->mtu;
-       
+
        if (mtu > ETH_DATA_LEN)
                /* MTU + ethernet header + FCS + optional VLAN tag */
                cp->rx_buf_sz = mtu + ETH_HLEN + 8;
@@ -510,7 +510,7 @@ static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
 static inline unsigned int cp_rx_csum_ok (u32 status)
 {
        unsigned int protocol = (status >> 16) & 0x3;
-       
+
        if (likely((protocol == RxProtoTCP) && (!(status & TCPFail))))
                return 1;
        else if ((protocol == RxProtoUDP) && (!(status & UDPFail)))
@@ -1061,7 +1061,7 @@ static void cp_init_hw (struct cp_private *cp)
        cpw8(Config3, PARMEnable);
        cp->wol_enabled = 0;
 
-       cpw8(Config5, cpr8(Config5) & PMEStatus); 
+       cpw8(Config5, cpr8(Config5) & PMEStatus);
 
        cpw32_f(HiTxRingAddr, 0);
        cpw32_f(HiTxRingAddr + 4, 0);
@@ -1351,7 +1351,7 @@ static void netdev_get_wol (struct cp_private *cp,
                         WAKE_MCAST | WAKE_UCAST;
        /* We don't need to go on if WOL is disabled */
        if (!cp->wol_enabled) return;
-       
+
        options        = cpr8 (Config3);
        if (options & LinkUp)        wol->wolopts |= WAKE_PHY;
        if (options & MagicPacket)   wol->wolopts |= WAKE_MAGIC;
@@ -1919,7 +1919,7 @@ static int cp_resume (struct pci_dev *pdev)
        mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
 
        spin_unlock_irqrestore (&cp->lock, flags);
-       
+
        return 0;
 }
 #endif /* CONFIG_PM */
index feae783..abd6261 100644 (file)
@@ -165,7 +165,7 @@ static int multicast_filter_limit = 32;
 static int debug = -1;
 
 /*
- * Receive ring size 
+ * Receive ring size
  * Warning: 64K ring has hardware issues and may lock up.
  */
 #if defined(CONFIG_SH_DREAMCAST)
@@ -257,7 +257,7 @@ static struct pci_device_id rtl8139_pci_tbl[] = {
        {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
        {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
        {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-       {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, 
+       {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 
 #ifdef CONFIG_SH_SECUREEDGE5410
        /* Bogus 8139 silicon reports 8129 without external PROM :-( */
@@ -1824,7 +1824,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
        int tmp_work;
 #endif
 
-       if (netif_msg_rx_err (tp)) 
+       if (netif_msg_rx_err (tp))
                printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n",
                        dev->name, rx_status);
        tp->stats.rx_errors++;
@@ -1944,7 +1944,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
                 RTL_R16 (RxBufAddr),
                 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
 
-       while (netif_running(dev) && received < budget 
+       while (netif_running(dev) && received < budget
               && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
                u32 ring_offset = cur_rx % RX_BUF_LEN;
                u32 rx_status;
@@ -2031,7 +2031,7 @@ no_early_rx:
 
                        netif_receive_skb (skb);
                } else {
-                       if (net_ratelimit()) 
+                       if (net_ratelimit())
                                printk (KERN_WARNING
                                        "%s: Memory squeeze, dropping packet.\n",
                                        dev->name);
@@ -2158,13 +2158,13 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
        status = RTL_R16 (IntrStatus);
 
        /* shared irq? */
-       if (unlikely((status & rtl8139_intr_mask) == 0)) 
+       if (unlikely((status & rtl8139_intr_mask) == 0))
                goto out;
 
        handled = 1;
 
        /* h/w no longer present (hotplug?) or major error, bail */
-       if (unlikely(status == 0xFFFF)) 
+       if (unlikely(status == 0xFFFF))
                goto out;
 
        /* close possible race's with dev_close */
index bdaaad8..f499a3b 100644 (file)
@@ -865,6 +865,22 @@ config DM9000
          <file:Documentation/networking/net-modules.txt>.  The module will be
          called dm9000.
 
+config SMC911X
+       tristate "SMSC LAN911[5678] support"
+       select CRC32
+       select MII
+       depends on NET_ETHERNET
+       help
+         This is a driver for SMSC's LAN911x series of Ethernet chipsets
+         including the new LAN9115, LAN9116, LAN9117, and LAN9118.
+         Say Y if you want it compiled into the kernel, 
+         and read the Ethernet-HOWTO, available from
+         <http://www.linuxdoc.org/docs.html#howto>.
+
+         This driver is also available as a module. The module will be 
+         called smc911x.  If you want to compile it as a module, say M 
+         here and read <file:Documentation/modules.txt>
+
 config NET_VENDOR_RACAL
        bool "Racal-Interlan (Micom) NI cards"
        depends on NET_ETHERNET && ISA
@@ -2311,6 +2327,23 @@ config S2IO_NAPI
 
          If in doubt, say N.
 
+config MYRI10GE
+       tristate "Myricom Myri-10G Ethernet support"
+       depends on PCI
+       select FW_LOADER
+       select CRC32
+       ---help---
+         This driver supports Myricom Myri-10G Dual Protocol interface in
+         Ethernet mode. If the eeprom on your board is not recent enough,
+         you will need a newer firmware image.
+         You may get this image or more information, at:
+
+         <http://www.myri.com/Myri-10G/>
+
+         To compile this driver as a module, choose M here and read
+         <file:Documentation/networking/net-modules.txt>.  The module
+         will be called myri10ge.
+
 endmenu
 
 source "drivers/net/tokenring/Kconfig"
index b90468a..1eced32 100644 (file)
@@ -192,7 +192,9 @@ obj-$(CONFIG_R8169) += r8169.o
 obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
 obj-$(CONFIG_IBMVETH) += ibmveth.o
 obj-$(CONFIG_S2IO) += s2io.o
+obj-$(CONFIG_MYRI10GE) += myri10ge/
 obj-$(CONFIG_SMC91X) += smc91x.o
+obj-$(CONFIG_SMC911X) += smc911x.o
 obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_FEC_8XX) += fec_8xx/
 
index 14dbad1..e1fe960 100644 (file)
@@ -2,7 +2,7 @@
  *
  * Alchemy Au1x00 ethernet driver
  *
- * Copyright 2001,2002,2003 MontaVista Software Inc.
+ * Copyright 2001-2003, 2006 MontaVista Software Inc.
  * Copyright 2002 TimeSys Corp.
  * Added ethtool/mii-tool support,
  * Copyright 2004 Matt Porter <mporter@kernel.crashing.org>
@@ -68,7 +68,7 @@ static int au1000_debug = 5;
 static int au1000_debug = 3;
 #endif
 
-#define DRV_NAME       "au1000eth"
+#define DRV_NAME       "au1000_eth"
 #define DRV_VERSION    "1.5"
 #define DRV_AUTHOR     "Pete Popov <ppopov@embeddedalley.com>"
 #define DRV_DESC       "Au1xxx on-chip Ethernet driver"
@@ -80,7 +80,7 @@ MODULE_LICENSE("GPL");
 // prototypes
 static void hard_stop(struct net_device *);
 static void enable_rx_tx(struct net_device *dev);
-static struct net_device * au1000_probe(u32 ioaddr, int irq, int port_num);
+static struct net_device * au1000_probe(int port_num);
 static int au1000_init(struct net_device *);
 static int au1000_open(struct net_device *);
 static int au1000_close(struct net_device *);
@@ -1160,12 +1160,27 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base)
 }
 
 static struct {
-       int port;
        u32 base_addr;
        u32 macen_addr;
        int irq;
        struct net_device *dev;
-} iflist[2];
+} iflist[2] = {
+#ifdef CONFIG_SOC_AU1000
+       {AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT},
+       {AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT}
+#endif
+#ifdef CONFIG_SOC_AU1100
+       {AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT}
+#endif
+#ifdef CONFIG_SOC_AU1500
+       {AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT},
+       {AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT}
+#endif
+#ifdef CONFIG_SOC_AU1550
+       {AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT},
+       {AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT}
+#endif
+};
 
 static int num_ifs;
 
@@ -1176,58 +1191,14 @@ static int num_ifs;
  */
 static int __init au1000_init_module(void)
 {
-       struct cpuinfo_mips *c = &current_cpu_data;
        int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
        struct net_device *dev;
        int i, found_one = 0;
 
-       switch (c->cputype) {
-#ifdef CONFIG_SOC_AU1000
-       case CPU_AU1000:
-               num_ifs = 2 - ni;
-               iflist[0].base_addr = AU1000_ETH0_BASE;
-               iflist[1].base_addr = AU1000_ETH1_BASE;
-               iflist[0].macen_addr = AU1000_MAC0_ENABLE;
-               iflist[1].macen_addr = AU1000_MAC1_ENABLE;
-               iflist[0].irq = AU1000_MAC0_DMA_INT;
-               iflist[1].irq = AU1000_MAC1_DMA_INT;
-               break;
-#endif
-#ifdef CONFIG_SOC_AU1100
-       case CPU_AU1100:
-               num_ifs = 1 - ni;
-               iflist[0].base_addr = AU1100_ETH0_BASE;
-               iflist[0].macen_addr = AU1100_MAC0_ENABLE;
-               iflist[0].irq = AU1100_MAC0_DMA_INT;
-               break;
-#endif
-#ifdef CONFIG_SOC_AU1500
-       case CPU_AU1500:
-               num_ifs = 2 - ni;
-               iflist[0].base_addr = AU1500_ETH0_BASE;
-               iflist[1].base_addr = AU1500_ETH1_BASE;
-               iflist[0].macen_addr = AU1500_MAC0_ENABLE;
-               iflist[1].macen_addr = AU1500_MAC1_ENABLE;
-               iflist[0].irq = AU1500_MAC0_DMA_INT;
-               iflist[1].irq = AU1500_MAC1_DMA_INT;
-               break;
-#endif
-#ifdef CONFIG_SOC_AU1550
-       case CPU_AU1550:
-               num_ifs = 2 - ni;
-               iflist[0].base_addr = AU1550_ETH0_BASE;
-               iflist[1].base_addr = AU1550_ETH1_BASE;
-               iflist[0].macen_addr = AU1550_MAC0_ENABLE;
-               iflist[1].macen_addr = AU1550_MAC1_ENABLE;
-               iflist[0].irq = AU1550_MAC0_DMA_INT;
-               iflist[1].irq = AU1550_MAC1_DMA_INT;
-               break;
-#endif
-       default:
-               num_ifs = 0;
-       }
+       num_ifs = NUM_ETH_INTERFACES - ni;
+
        for(i = 0; i < num_ifs; i++) {
-               dev = au1000_probe(iflist[i].base_addr, iflist[i].irq, i);
+               dev = au1000_probe(i);
                iflist[i].dev = dev;
                if (dev)
                        found_one++;
@@ -1436,8 +1407,7 @@ static struct ethtool_ops au1000_ethtool_ops = {
        .get_link = au1000_get_link
 };
 
-static struct net_device *
-au1000_probe(u32 ioaddr, int irq, int port_num)
+static struct net_device * au1000_probe(int port_num)
 {
        static unsigned version_printed = 0;
        struct au1000_private *aup = NULL;
@@ -1445,94 +1415,95 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
        db_dest_t *pDB, *pDBfree;
        char *pmac, *argptr;
        char ethaddr[6];
-       int i, err;
+       int irq, i, err;
+       u32 base, macen;
+
+       if (port_num >= NUM_ETH_INTERFACES)
+               return NULL;
 
-       if (!request_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE, "Au1x00 ENET"))
+       base  = CPHYSADDR(iflist[port_num].base_addr );
+       macen = CPHYSADDR(iflist[port_num].macen_addr);
+       irq = iflist[port_num].irq;
+
+       if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") ||
+           !request_mem_region(macen, 4, "Au1x00 ENET"))
                return NULL;
 
-       if (version_printed++ == 0) 
+       if (version_printed++ == 0)
                printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
 
        dev = alloc_etherdev(sizeof(struct au1000_private));
        if (!dev) {
-               printk (KERN_ERR "au1000 eth: alloc_etherdev failed\n");  
+               printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
                return NULL;
        }
 
-       if ((err = register_netdev(dev))) {
-               printk(KERN_ERR "Au1x_eth Cannot register net device err %d\n",
-                               err);
+       if ((err = register_netdev(dev)) != 0) {
+               printk(KERN_ERR "%s: Cannot register net device, error %d\n",
+                               DRV_NAME, err);
                free_netdev(dev);
                return NULL;
        }
 
-       printk("%s: Au1x Ethernet found at 0x%x, irq %d\n", 
-                       dev->name, ioaddr, irq);
+       printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
+               dev->name, base, irq);
 
        aup = dev->priv;
 
        /* Allocate the data buffers */
        /* Snooping works fine with eth on all au1xxx */
-       aup->vaddr = (u32)dma_alloc_noncoherent(NULL,
-                       MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-                       &aup->dma_addr,
-                       0);
+       aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
+                                               (NUM_TX_BUFFS + NUM_RX_BUFFS),
+                                               &aup->dma_addr, 0);
        if (!aup->vaddr) {
                free_netdev(dev);
-               release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+               release_mem_region( base, MAC_IOSIZE);
+               release_mem_region(macen, 4);
                return NULL;
        }
 
        /* aup->mac is the base address of the MAC's registers */
-       aup->mac = (volatile mac_reg_t *)((unsigned long)ioaddr);
+       aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr;
+
        /* Setup some variables for quick register address access */
-       if (ioaddr == iflist[0].base_addr)
-       {
-               /* check env variables first */
-               if (!get_ethernet_addr(ethaddr)) { 
+       aup->enable = (volatile u32 *)iflist[port_num].macen_addr;
+       aup->mac_id = port_num;
+       au_macs[port_num] = aup;
+
+       if (port_num == 0) {
+               /* Check the environment variables first */
+               if (get_ethernet_addr(ethaddr) == 0)
                        memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
-               } else {
+               else {
                        /* Check command line */
                        argptr = prom_getcmdline();
-                       if ((pmac = strstr(argptr, "ethaddr=")) == NULL) {
-                               printk(KERN_INFO "%s: No mac address found\n", 
-                                               dev->name);
-                               /* use the hard coded mac addresses */
-                       } else {
+                       if ((pmac = strstr(argptr, "ethaddr=")) == NULL)
+                               printk(KERN_INFO "%s: No MAC address found\n",
+                                                dev->name);
+                               /* Use the hard coded MAC addresses */
+                       else {
                                str2eaddr(ethaddr, pmac + strlen("ethaddr="));
                                memcpy(au1000_mac_addr, ethaddr, 
-                                               sizeof(au1000_mac_addr));
+                                      sizeof(au1000_mac_addr));
                        }
                }
-                       aup->enable = (volatile u32 *) 
-                               ((unsigned long)iflist[0].macen_addr);
-               memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+
                setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
-               aup->mac_id = 0;
-               au_macs[0] = aup;
-       }
-               else
-       if (ioaddr == iflist[1].base_addr)
-       {
-                       aup->enable = (volatile u32 *) 
-                               ((unsigned long)iflist[1].macen_addr);
-               memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
-               dev->dev_addr[4] += 0x10;
+       } else if (port_num == 1)
                setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
-               aup->mac_id = 1;
-               au_macs[1] = aup;
-       }
-       else
-       {
-               printk(KERN_ERR "%s: bad ioaddr\n", dev->name);
-       }
 
-       /* bring the device out of reset, otherwise probing the mii
-        * will hang */
+       /*
+        * Assign to the Ethernet ports two consecutive MAC addresses
+        * to match those that are printed on their stickers
+        */
+       memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+       dev->dev_addr[5] += port_num;
+
+       /* Bring the device out of reset, otherwise probing the MII will hang */
        *aup->enable = MAC_EN_CLOCK_ENABLE;
        au_sync_delay(2);
-       *aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
-               MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
+       *aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2 |
+                      MAC_EN_CLOCK_ENABLE;
        au_sync_delay(2);
 
        aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL);
@@ -1581,7 +1552,7 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
        }
 
        spin_lock_init(&aup->lock);
-       dev->base_addr = ioaddr;
+       dev->base_addr = base;
        dev->irq = irq;
        dev->open = au1000_open;
        dev->hard_start_xmit = au1000_tx;
@@ -1615,13 +1586,12 @@ err_out:
                if (aup->tx_db_inuse[i])
                        ReleaseDB(aup, aup->tx_db_inuse[i]);
        }
-       dma_free_noncoherent(NULL,
-                       MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-                       (void *)aup->vaddr,
-                       aup->dma_addr);
+       dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
+                            (void *)aup->vaddr, aup->dma_addr);
        unregister_netdev(dev);
        free_netdev(dev);
-       release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+       release_mem_region( base, MAC_IOSIZE);
+       release_mem_region(macen, 4);
        return NULL;
 }
 
@@ -1806,20 +1776,18 @@ static void __exit au1000_cleanup_module(void)
                        aup = (struct au1000_private *) dev->priv;
                        unregister_netdev(dev);
                        kfree(aup->mii);
-                       for (j = 0; j < NUM_RX_DMA; j++) {
+                       for (j = 0; j < NUM_RX_DMA; j++)
                                if (aup->rx_db_inuse[j])
                                        ReleaseDB(aup, aup->rx_db_inuse[j]);
-                       }
-                       for (j = 0; j < NUM_TX_DMA; j++) {
+                       for (j = 0; j < NUM_TX_DMA; j++)
                                if (aup->tx_db_inuse[j])
                                        ReleaseDB(aup, aup->tx_db_inuse[j]);
-                       }
-                       dma_free_noncoherent(NULL,
-                                       MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-                                       (void *)aup->vaddr,
-                                       aup->dma_addr);
+                       dma_free_noncoherent(NULL, MAX_BUF_SIZE *
+                                            (NUM_TX_BUFFS + NUM_RX_BUFFS),
+                                            (void *)aup->vaddr, aup->dma_addr);
+                       release_mem_region(dev->base_addr, MAC_IOSIZE);
+                       release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4);
                        free_netdev(dev);
-                       release_mem_region(CPHYSADDR(iflist[i].base_addr), MAC_IOSIZE);
                }
        }
 }
index ac48f75..39f36aa 100644 (file)
@@ -4877,7 +4877,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
        static int cas_version_printed = 0;
-       unsigned long casreg_base, casreg_len;
+       unsigned long casreg_len;
        struct net_device *dev;
        struct cas *cp;
        int i, err, pci_using_dac;
@@ -4972,7 +4972,6 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
                pci_using_dac = 0;
        }
 
-       casreg_base = pci_resource_start(pdev, 0);
        casreg_len = pci_resource_len(pdev, 0);
 
        cp = netdev_priv(dev);
@@ -5024,7 +5023,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
        cp->timer_ticks = 0;
 
        /* give us access to cassini registers */
-       cp->regs = ioremap(casreg_base, casreg_len);
+       cp->regs = pci_iomap(pdev, 0, casreg_len);
        if (cp->regs == 0UL) {
                printk(KERN_ERR PFX "Cannot map device registers, "
                       "aborting.\n");
@@ -5123,7 +5122,7 @@ err_out_iounmap:
                cas_shutdown(cp);
        mutex_unlock(&cp->pm_mutex);
 
-       iounmap(cp->regs);
+       pci_iounmap(pdev, cp->regs);
 
 
 err_out_free_res:
@@ -5171,7 +5170,7 @@ static void __devexit cas_remove_one(struct pci_dev *pdev)
 #endif
        pci_free_consistent(pdev, sizeof(struct cas_init_block),
                            cp->init_block, cp->block_dvma);
-       iounmap(cp->regs);
+       pci_iounmap(pdev, cp->regs);
        free_netdev(dev);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
index ca9f895..5dea2b7 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # 
-# Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+# Copyright(c) 1999 - 2006 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 
@@ -22,6 +22,7 @@
 # 
 # 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
 #
 ################################################################################
index 281de41..2bc34fb 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -22,6 +22,7 @@
   
   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
 
 *******************************************************************************/
@@ -114,6 +115,8 @@ struct e1000_adapter;
 /* Supported Rx Buffer Sizes */
 #define E1000_RXBUFFER_128   128    /* Used for packet split */
 #define E1000_RXBUFFER_256   256    /* Used for packet split */
+#define E1000_RXBUFFER_512   512
+#define E1000_RXBUFFER_1024  1024
 #define E1000_RXBUFFER_2048  2048
 #define E1000_RXBUFFER_4096  4096
 #define E1000_RXBUFFER_8192  8192
@@ -334,7 +337,6 @@ struct e1000_adapter {
        boolean_t have_msi;
 #endif
        /* to not mess up cache alignment, always add to the bottom */
-       boolean_t txb2b;
 #ifdef NETIF_F_TSO
        boolean_t tso_force;
 #endif
index ecccca3..cfdf0b2 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -22,6 +22,7 @@
   
   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
 
 *******************************************************************************/
@@ -864,15 +865,15 @@ static int
 e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 {
        struct net_device *netdev = adapter->netdev;
-       uint32_t mask, i=0, shared_int = TRUE;
-       uint32_t irq = adapter->pdev->irq;
+       uint32_t mask, i=0, shared_int = TRUE;
+       uint32_t irq = adapter->pdev->irq;
 
        *data = 0;
 
        /* Hook up test interrupt handler just for this test */
-       if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
-               shared_int = FALSE;
-       } else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
+       if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
+               shared_int = FALSE;
+       } else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
                              netdev->name, netdev)){
                *data = 1;
                return -1;
@@ -888,22 +889,22 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
                /* Interrupt to test */
                mask = 1 << i;
 
-               if (!shared_int) {
-                       /* Disable the interrupt to be reported in
-                        * the cause register and then force the same
-                        * interrupt and see if one gets posted.  If
-                        * an interrupt was posted to the bus, the
-                        * test failed.
-                        */
-                       adapter->test_icr = 0;
-                       E1000_WRITE_REG(&adapter->hw, IMC, mask);
-                       E1000_WRITE_REG(&adapter->hw, ICS, mask);
-                       msec_delay(10);
-
-                       if (adapter->test_icr & mask) {
-                               *data = 3;
-                               break;
-                       }
+               if (!shared_int) {
+                       /* Disable the interrupt to be reported in
+                        * the cause register and then force the same
+                        * interrupt and see if one gets posted.  If
+                        * an interrupt was posted to the bus, the
+                        * test failed.
+                        */
+                       adapter->test_icr = 0;
+                       E1000_WRITE_REG(&adapter->hw, IMC, mask);
+                       E1000_WRITE_REG(&adapter->hw, ICS, mask);
+                       msec_delay(10);
+
+                       if (adapter->test_icr & mask) {
+                               *data = 3;
+                               break;
+                       }
                }
 
                /* Enable the interrupt to be reported in
@@ -922,7 +923,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
                        break;
                }
 
-               if (!shared_int) {
+               if (!shared_int) {
                        /* Disable the other interrupts to be reported in
                         * the cause register and then force the other
                         * interrupts and see if any get posted.  If
index 523c2c9..3959039 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -22,6 +22,7 @@
   
   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
 
 *******************************************************************************/
@@ -764,7 +765,7 @@ e1000_init_hw(struct e1000_hw *hw)
     }
 
     if (hw->mac_type == e1000_82573) {
-        e1000_enable_tx_pkt_filtering(hw); 
+        e1000_enable_tx_pkt_filtering(hw);
     }
 
     switch (hw->mac_type) {
@@ -860,7 +861,7 @@ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
 
     if(eeprom_data != EEPROM_RESERVED_WORD) {
         /* Adjust SERDES output amplitude only. */
-        eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; 
+        eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
         if(ret_val)
             return ret_val;
@@ -1227,7 +1228,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
 
     if (hw->phy_reset_disable)
         return E1000_SUCCESS;
-    
+
     ret_val = e1000_phy_reset(hw);
     if (ret_val) {
         DEBUGOUT("Error Resetting the PHY\n");
@@ -1369,7 +1370,7 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
     DEBUGFUNC("e1000_copper_link_ggp_setup");
 
     if(!hw->phy_reset_disable) {
-        
+
         /* Enable CRS on TX for half-duplex operation. */
         ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
                                      &phy_data);
@@ -1518,7 +1519,7 @@ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
 
     if(hw->phy_reset_disable)
         return E1000_SUCCESS;
-    
+
     /* Enable CRS on TX. This must be set for half-duplex operation. */
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
     if(ret_val)
@@ -1664,7 +1665,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
 *      collision distance in the Transmit Control Register.
 *   2) Set up flow control on the MAC to that established with
 *      the link partner.
-*   3) Config DSP to improve Gigabit link quality for some PHY revisions.    
+*   3) Config DSP to improve Gigabit link quality for some PHY revisions.
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
@@ -1673,7 +1674,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
 {
     int32_t ret_val;
     DEBUGFUNC("e1000_copper_link_postconfig");
-    
+
     if(hw->mac_type >= e1000_82544) {
         e1000_config_collision_dist(hw);
     } else {
@@ -1697,7 +1698,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
             return ret_val;
         }
     }
-                
+
     return E1000_SUCCESS;
 }
 
@@ -1753,11 +1754,11 @@ e1000_setup_copper_link(struct e1000_hw *hw)
     }
 
     if(hw->autoneg) {
-        /* Setup autoneg and flow control advertisement 
-          * and perform autonegotiation */   
+        /* Setup autoneg and flow control advertisement
+          * and perform autonegotiation */
         ret_val = e1000_copper_link_autoneg(hw);
         if(ret_val)
-            return ret_val;           
+            return ret_val;
     } else {
         /* PHY will be set to 10H, 10F, 100H,or 100F
           * depending on value from forced_speed_duplex. */
@@ -1785,7 +1786,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
             ret_val = e1000_copper_link_postconfig(hw);
             if(ret_val)
                 return ret_val;
-            
+
             DEBUGOUT("Valid link established!!!\n");
             return E1000_SUCCESS;
         }
@@ -1983,7 +1984,7 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
 
     DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
 
-    ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);    
+    ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
     if(ret_val)
         return ret_val;
 
@@ -2272,7 +2273,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
 
     DEBUGFUNC("e1000_config_mac_to_phy");
 
-    /* 82544 or newer MAC, Auto Speed Detection takes care of 
+    /* 82544 or newer MAC, Auto Speed Detection takes care of
     * MAC speed/duplex configuration.*/
     if (hw->mac_type >= e1000_82544)
         return E1000_SUCCESS;
@@ -2291,9 +2292,9 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
     if(ret_val)
         return ret_val;
 
-    if(phy_data & M88E1000_PSSR_DPLX) 
+    if(phy_data & M88E1000_PSSR_DPLX)
         ctrl |= E1000_CTRL_FD;
-    else 
+    else
         ctrl &= ~E1000_CTRL_FD;
 
     e1000_config_collision_dist(hw);
@@ -2492,10 +2493,10 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                  */
                 if(hw->original_fc == e1000_fc_full) {
                     hw->fc = e1000_fc_full;
-                    DEBUGOUT("Flow Control = FULL.\r\n");
+                    DEBUGOUT("Flow Control = FULL.\n");
                 } else {
                     hw->fc = e1000_fc_rx_pause;
-                    DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                    DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
                 }
             }
             /* For receiving PAUSE frames ONLY.
@@ -2511,7 +2512,7 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                     (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = e1000_fc_tx_pause;
-                DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
             }
             /* For transmitting PAUSE frames ONLY.
              *
@@ -2526,7 +2527,7 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                     !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = e1000_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
             }
             /* Per the IEEE spec, at this point flow control should be
              * disabled.  However, we want to consider that we could
@@ -2552,10 +2553,10 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                      hw->original_fc == e1000_fc_tx_pause) ||
                     hw->fc_strict_ieee) {
                 hw->fc = e1000_fc_none;
-                DEBUGOUT("Flow Control = NONE.\r\n");
+                DEBUGOUT("Flow Control = NONE.\n");
             } else {
                 hw->fc = e1000_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
             }
 
             /* Now we need to do one last check...  If we auto-
@@ -2580,7 +2581,7 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                 return ret_val;
             }
         } else {
-            DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n");
+            DEBUGOUT("Copper PHY and Auto Neg has not completed.\n");
         }
     }
     return E1000_SUCCESS;
@@ -2763,7 +2764,7 @@ e1000_check_for_link(struct e1000_hw *hw)
             hw->autoneg_failed = 1;
             return 0;
         }
-        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
+        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
 
         /* Disable auto-negotiation in the TXCW register */
         E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
@@ -2788,7 +2789,7 @@ e1000_check_for_link(struct e1000_hw *hw)
     else if(((hw->media_type == e1000_media_type_fiber) ||
              (hw->media_type == e1000_media_type_internal_serdes)) &&
             (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
+        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
         E1000_WRITE_REG(hw, TXCW, hw->txcw);
         E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
 
@@ -2851,13 +2852,13 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
 
         if(status & E1000_STATUS_FD) {
             *duplex = FULL_DUPLEX;
-            DEBUGOUT("Full Duplex\r\n");
+            DEBUGOUT("Full Duplex\n");
         } else {
             *duplex = HALF_DUPLEX;
-            DEBUGOUT(" Half Duplex\r\n");
+            DEBUGOUT(" Half Duplex\n");
         }
     } else {
-        DEBUGOUT("1000 Mbs, Full Duplex\r\n");
+        DEBUGOUT("1000 Mbs, Full Duplex\n");
         *speed = SPEED_1000;
         *duplex = FULL_DUPLEX;
     }
@@ -2883,7 +2884,7 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
         }
     }
 
-    if ((hw->mac_type == e1000_80003es2lan) && 
+    if ((hw->mac_type == e1000_80003es2lan) &&
         (hw->media_type == e1000_media_type_copper)) {
         if (*speed == SPEED_1000)
             ret_val = e1000_configure_kmrn_for_1000(hw);
@@ -3159,7 +3160,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
     if (e1000_swfw_sync_acquire(hw, swfw))
         return -E1000_ERR_SWFW_SYNC;
 
-    if((hw->phy_type == e1000_phy_igp || 
+    if((hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -3298,7 +3299,7 @@ e1000_write_phy_reg(struct e1000_hw *hw,
     if (e1000_swfw_sync_acquire(hw, swfw))
         return -E1000_ERR_SWFW_SYNC;
 
-    if((hw->phy_type == e1000_phy_igp || 
+    if((hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -3496,22 +3497,22 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
         }
         /* Read the device control register and assert the E1000_CTRL_PHY_RST
          * bit. Then, take it out of reset.
-         * For pre-e1000_82571 hardware, we delay for 10ms between the assert 
+         * For pre-e1000_82571 hardware, we delay for 10ms between the assert
          * and deassert.  For e1000_82571 hardware and later, we instead delay
          * for 50us between and 10ms after the deassertion.
          */
         ctrl = E1000_READ_REG(hw, CTRL);
         E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
         E1000_WRITE_FLUSH(hw);
-        
-        if (hw->mac_type < e1000_82571) 
+
+        if (hw->mac_type < e1000_82571)
             msec_delay(10);
         else
             udelay(100);
-        
+
         E1000_WRITE_REG(hw, CTRL, ctrl);
         E1000_WRITE_FLUSH(hw);
-        
+
         if (hw->mac_type >= e1000_82571)
             msec_delay(10);
         e1000_swfw_sync_release(hw, swfw);
@@ -3815,7 +3816,7 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
     /* Check polarity status */
     ret_val = e1000_check_polarity(hw, &polarity);
     if(ret_val)
-        return ret_val; 
+        return ret_val;
     phy_info->cable_polarity = polarity;
 
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
@@ -4540,14 +4541,14 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
 
         E1000_WRITE_REG(hw, EERD, eerd);
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
-        
+
         if(error) {
             break;
         }
         data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
-      
+
     }
-    
+
     return error;
 }
 
@@ -4573,24 +4574,24 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
         return -E1000_ERR_SWFW_SYNC;
 
     for (i = 0; i < words; i++) {
-        register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | 
-                         ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | 
+        register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) |
+                         ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) |
                          E1000_EEPROM_RW_REG_START;
 
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
         if(error) {
             break;
-        }       
+        }
 
         E1000_WRITE_REG(hw, EEWR, register_value);
-        
+
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
-        
+
         if(error) {
             break;
-        }       
+        }
     }
-    
+
     e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
     return error;
 }
@@ -4610,7 +4611,7 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
     for(i = 0; i < attempts; i++) {
         if(eerd == E1000_EEPROM_POLL_READ)
             reg = E1000_READ_REG(hw, EERD);
-        else 
+        else
             reg = E1000_READ_REG(hw, EEWR);
 
         if(reg & E1000_EEPROM_RW_REG_DONE) {
@@ -5135,7 +5136,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
     uint32_t i;
     uint32_t num_rar_entry;
     uint32_t num_mta_entry;
-    
+
     DEBUGFUNC("e1000_mc_addr_list_update");
 
     /* Set the new number of MC addresses that we are being requested to use. */
@@ -6240,7 +6241,7 @@ e1000_check_polarity(struct e1000_hw *hw,
  *                                1 - Downshift ocured.
  *
  * returns: - E1000_ERR_XXX
- *            E1000_SUCCESS 
+ *            E1000_SUCCESS
  *
  * For phy's older then IGP, this function reads the Downshift bit in the Phy
  * Specific Status register.  For IGP phy's, it reads the Downgrade bit in the
@@ -6255,7 +6256,7 @@ e1000_check_downshift(struct e1000_hw *hw)
 
     DEBUGFUNC("e1000_check_downshift");
 
-    if(hw->phy_type == e1000_phy_igp || 
+    if(hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) {
         ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
                                      &phy_data);
@@ -6684,8 +6685,8 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
 
 
     } else {
-            phy_data |= IGP02E1000_PM_D0_LPLU;   
+
+            phy_data |= IGP02E1000_PM_D0_LPLU;
             ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
             if (ret_val)
                 return ret_val;
@@ -6777,7 +6778,7 @@ int32_t
 e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
 {
     uint8_t i;
-    uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET; 
+    uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET;
     uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH;
 
     length = (length >> 2);
@@ -6796,7 +6797,7 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
  * and also checks whether the previous command is completed.
  * It busy waits in case of previous command is not completed.
  *
- * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or 
+ * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or
  *            timeout
  *          - E1000_SUCCESS for success.
  ****************************************************************************/
@@ -6820,7 +6821,7 @@ e1000_mng_enable_host_if(struct e1000_hw * hw)
         msec_delay_irq(1);
     }
 
-    if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { 
+    if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
         DEBUGOUT("Previous command timeout failed .\n");
         return -E1000_ERR_HOST_INTERFACE_COMMAND;
     }
index 150e45e..467c9ed 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -22,6 +22,7 @@
   
   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
 
 *******************************************************************************/
@@ -374,7 +375,7 @@ struct e1000_host_mng_dhcp_cookie{
 };
 #endif
 
-int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer, 
+int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
                                                        uint16_t length);
 boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
 boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
@@ -1801,7 +1802,7 @@ struct e1000_hw {
  *       value2 = [0..64512],    default=4096
  *       value3 = [0..64512],    default=0
  */
-    
+
 #define E1000_PSRCTL_BSIZE0_MASK   0x0000007F
 #define E1000_PSRCTL_BSIZE1_MASK   0x00003F00
 #define E1000_PSRCTL_BSIZE2_MASK   0x003F0000
index ed15fca..bd709e5 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
   
   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 "e1000.h"
 
-/* Change Log
- * 7.0.33      3-Feb-2006
- *   o Added another fix for the pass false carrier bit
- * 7.0.32      24-Jan-2006
- *   o Need to rebuild with noew version number for the pass false carrier 
- *     fix in e1000_hw.c
- * 7.0.30      18-Jan-2006
- *   o fixup for tso workaround to disable it for pci-x
- *   o fix mem leak on 82542
- *   o fixes for 10 Mb/s connections and incorrect stats
- * 7.0.28      01/06/2006
- *   o hardware workaround to only set "speed mode" bit for 1G link.
- * 7.0.26      12/23/2005
- *   o wake on lan support modified for device ID 10B5
- *   o fix dhcp + vlan issue not making it to the iAMT firmware
- * 7.0.24      12/9/2005
- *   o New hardware support for the Gigabit NIC embedded in the south bridge
- *   o Fixes to the recycling logic (skb->tail) from IBM LTC
- * 6.3.9       12/16/2005
- *   o incorporate fix for recycled skbs from IBM LTC
- * 6.3.7       11/18/2005
- *   o Honor eeprom setting for enabling/disabling Wake On Lan
- * 6.3.5       11/17/2005
- *   o Fix memory leak in rx ring handling for PCI Express adapters
- * 6.3.4       11/8/05
- *   o Patch from Jesper Juhl to remove redundant NULL checks for kfree
- * 6.3.2       9/20/05
- *   o Render logic that sets/resets DRV_LOAD as inline functions to 
- *     avoid code replication. If f/w is AMT then set DRV_LOAD only when
- *     network interface is open.
- *   o Handle DRV_LOAD set/reset in cases where AMT uses VLANs.
- *   o Adjust PBA partioning for Jumbo frames using MTU size and not
- *     rx_buffer_len
- * 6.3.1       9/19/05
- *   o Use adapter->tx_timeout_factor in Tx Hung Detect logic 
- *      (e1000_clean_tx_irq)
- *   o Support for 8086:10B5 device (Quad Port)
- */
-
 char e1000_driver_name[] = "e1000";
 static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
 #ifndef CONFIG_E1000_NAPI
@@ -74,9 +36,9 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION "7.0.33-k2"DRIVERNAPI
+#define DRV_VERSION "7.0.38-k4"DRIVERNAPI
 char e1000_driver_version[] = DRV_VERSION;
-static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
  *
@@ -208,8 +170,8 @@ static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
 static void e1000_tx_timeout(struct net_device *dev);
 static void e1000_reset_task(struct net_device *dev);
 static void e1000_smartspeed(struct e1000_adapter *adapter);
-static inline int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
-                                             struct sk_buff *skb);
+static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
+                                       struct sk_buff *skb);
 
 static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
 static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
@@ -293,7 +255,7 @@ module_exit(e1000_exit_module);
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_disable(struct e1000_adapter *adapter)
 {
        atomic_inc(&adapter->irq_sem);
@@ -307,7 +269,7 @@ e1000_irq_disable(struct e1000_adapter *adapter)
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_enable(struct e1000_adapter *adapter)
 {
        if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
@@ -348,10 +310,10 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
  * For ASF and Pass Through versions of f/w this means that the
  * driver is no longer loaded. For AMT version (only with 82573) i
  * of the f/w this means that the netowrk i/f is closed.
- * 
+ *
  **/
 
-static inline void 
+static void
 e1000_release_hw_control(struct e1000_adapter *adapter)
 {
        uint32_t ctrl_ext;
@@ -361,6 +323,7 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
        switch (adapter->hw.mac_type) {
        case e1000_82571:
        case e1000_82572:
+       case e1000_80003es2lan:
                ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
                E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
                                ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
@@ -379,13 +342,13 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
  * @adapter: address of board private structure
  *
  * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that 
- * the driver is loaded. For AMT version (only with 82573) 
+ * For ASF and Pass Through versions of f/w this means that
+ * the driver is loaded. For AMT version (only with 82573)
  * of the f/w this means that the netowrk i/f is open.
- * 
+ *
  **/
 
-static inline void 
+static void
 e1000_get_hw_control(struct e1000_adapter *adapter)
 {
        uint32_t ctrl_ext;
@@ -394,6 +357,7 @@ e1000_get_hw_control(struct e1000_adapter *adapter)
        switch (adapter->hw.mac_type) {
        case e1000_82571:
        case e1000_82572:
+       case e1000_80003es2lan:
                ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
                E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
                                ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
@@ -421,7 +385,7 @@ e1000_up(struct e1000_adapter *adapter)
                uint16_t mii_reg;
                e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
                if (mii_reg & MII_CR_POWER_DOWN)
-                       e1000_phy_reset(&adapter->hw);
+                       e1000_phy_hw_reset(&adapter->hw);
        }
 
        e1000_set_multi(netdev);
@@ -711,8 +675,8 @@ e1000_probe(struct pci_dev *pdev,
                DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
 
        /* if ksp3, indicate if it's port a being setup */
-       if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 && 
-                       e1000_ksp3_port_a == 0) 
+       if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 &&
+                       e1000_ksp3_port_a == 0)
                adapter->ksp3_port_a = 1;
        e1000_ksp3_port_a++;
        /* Reset for multiple KP3 adapters */
@@ -740,9 +704,9 @@ e1000_probe(struct pci_dev *pdev,
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
-       /* hard_start_xmit is safe against parallel locking */
-       netdev->features |= NETIF_F_LLTX; 
+       /* hard_start_xmit is safe against parallel locking */
+       netdev->features |= NETIF_F_LLTX;
+
        adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
 
        /* before reading the EEPROM, reset the controller to
@@ -972,8 +936,8 @@ e1000_sw_init(struct e1000_adapter *adapter)
 
        pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
-       adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-       adapter->rx_ps_bsize0 = E1000_RXBUFFER_256;
+       adapter->rx_buffer_len = MAXIMUM_ETHERNET_FRAME_SIZE;
+       adapter->rx_ps_bsize0 = E1000_RXBUFFER_128;
        hw->max_frame_size = netdev->mtu +
                             ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
        hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
@@ -1181,7 +1145,7 @@ e1000_close(struct net_device *netdev)
  * @start: address of beginning of memory
  * @len: length of memory
  **/
-static inline boolean_t
+static boolean_t
 e1000_check_64k_bound(struct e1000_adapter *adapter,
                      void *start, unsigned long len)
 {
@@ -1599,14 +1563,21 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
                rctl |= E1000_RCTL_LPE;
 
        /* Setup buffer sizes */
-       if (adapter->hw.mac_type >= e1000_82571) {
-               /* We can now specify buffers in 1K increments.
-                * BSIZE and BSEX are ignored in this case. */
-               rctl |= adapter->rx_buffer_len << 0x11;
-       } else {
-               rctl &= ~E1000_RCTL_SZ_4096;
-               rctl |= E1000_RCTL_BSEX; 
-               switch (adapter->rx_buffer_len) {
+       rctl &= ~E1000_RCTL_SZ_4096;
+       rctl |= E1000_RCTL_BSEX;
+       switch (adapter->rx_buffer_len) {
+               case E1000_RXBUFFER_256:
+                       rctl |= E1000_RCTL_SZ_256;
+                       rctl &= ~E1000_RCTL_BSEX;
+                       break;
+               case E1000_RXBUFFER_512:
+                       rctl |= E1000_RCTL_SZ_512;
+                       rctl &= ~E1000_RCTL_BSEX;
+                       break;
+               case E1000_RXBUFFER_1024:
+                       rctl |= E1000_RCTL_SZ_1024;
+                       rctl &= ~E1000_RCTL_BSEX;
+                       break;
                case E1000_RXBUFFER_2048:
                default:
                        rctl |= E1000_RCTL_SZ_2048;
@@ -1621,7 +1592,6 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
                case E1000_RXBUFFER_16384:
                        rctl |= E1000_RCTL_SZ_16384;
                        break;
-               }
        }
 
 #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
@@ -1715,7 +1685,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
        if (hw->mac_type >= e1000_82571) {
                ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
                /* Reset delay timers after every interrupt */
-               ctrl_ext |= E1000_CTRL_EXT_CANC;
+               ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR;
 #ifdef CONFIG_E1000_NAPI
                /* Auto-Mask interrupts upon ICR read. */
                ctrl_ext |= E1000_CTRL_EXT_IAME;
@@ -1807,7 +1777,7 @@ e1000_free_all_tx_resources(struct e1000_adapter *adapter)
                e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
 }
 
-static inline void
+static void
 e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
                        struct e1000_buffer *buffer_info)
 {
@@ -2247,6 +2217,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
 
        if (link) {
                if (!netif_carrier_ok(netdev)) {
+                       boolean_t txb2b = 1;
                        e1000_get_speed_and_duplex(&adapter->hw,
                                                   &adapter->link_speed,
                                                   &adapter->link_duplex);
@@ -2260,23 +2231,22 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
                         * and adjust the timeout factor */
                        netdev->tx_queue_len = adapter->tx_queue_len;
                        adapter->tx_timeout_factor = 1;
-                       adapter->txb2b = 1;
                        switch (adapter->link_speed) {
                        case SPEED_10:
-                               adapter->txb2b = 0;
+                               txb2b = 0;
                                netdev->tx_queue_len = 10;
                                adapter->tx_timeout_factor = 8;
                                break;
                        case SPEED_100:
-                               adapter->txb2b = 0;
+                               txb2b = 0;
                                netdev->tx_queue_len = 100;
                                /* maybe add some timeout factor ? */
                                break;
                        }
 
-                       if ((adapter->hw.mac_type == e1000_82571 || 
+                       if ((adapter->hw.mac_type == e1000_82571 ||
                             adapter->hw.mac_type == e1000_82572) &&
-                           adapter->txb2b == 0) {
+                           txb2b == 0) {
 #define SPEED_MODE_BIT (1 << 21)
                                uint32_t tarc0;
                                tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
@@ -2400,7 +2370,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
 #define E1000_TX_FLAGS_VLAN_MASK       0xffff0000
 #define E1000_TX_FLAGS_VLAN_SHIFT      16
 
-static inline int
+static int
 e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
           struct sk_buff *skb)
 {
@@ -2422,7 +2392,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
 
                hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
                mss = skb_shinfo(skb)->tso_size;
-               if (skb->protocol == ntohs(ETH_P_IP)) {
+               if (skb->protocol == htons(ETH_P_IP)) {
                        skb->nh.iph->tot_len = 0;
                        skb->nh.iph->check = 0;
                        skb->h.th->check =
@@ -2480,7 +2450,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
        return FALSE;
 }
 
-static inline boolean_t
+static boolean_t
 e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
               struct sk_buff *skb)
 {
@@ -2516,7 +2486,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
 #define E1000_MAX_TXD_PWR      12
 #define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
 
-static inline int
+static int
 e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
              struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
              unsigned int nr_frags, unsigned int mss)
@@ -2625,7 +2595,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
        return count;
 }
 
-static inline void
+static void
 e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
                int tx_flags, int count)
 {
@@ -2689,7 +2659,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
 #define E1000_FIFO_HDR                 0x10
 #define E1000_82547_PAD_LEN            0x3E0
 
-static inline int
+static int
 e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
        uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
@@ -2716,7 +2686,7 @@ no_fifo_stall_required:
 }
 
 #define MINIMUM_DHCP_PACKET_SIZE 282
-static inline int
+static int
 e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
        struct e1000_hw *hw =  &adapter->hw;
@@ -2764,7 +2734,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        unsigned int nr_frags = 0;
        unsigned int mss = 0;
        int count = 0;
-       int tso;
+       int tso;
        unsigned int f;
        len -= skb->data_len;
 
@@ -2777,7 +2747,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
 #ifdef NETIF_F_TSO
        mss = skb_shinfo(skb)->tso_size;
-       /* The controller does a simple calculation to 
+       /* The controller does a simple calculation to
         * make sure there is enough room in the FIFO before
         * initiating the DMA for each buffer.  The calc is:
         * 4 = ceil(buffer len/mss).  To make sure we don't
@@ -2800,7 +2770,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                        case e1000_82573:
                                pull_size = min((unsigned int)4, skb->data_len);
                                if (!__pskb_pull_tail(skb, pull_size)) {
-                                       printk(KERN_ERR 
+                                       printk(KERN_ERR
                                                "__pskb_pull_tail failed.\n");
                                        dev_kfree_skb_any(skb);
                                        return NETDEV_TX_OK;
@@ -2901,7 +2871,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        /* Old method was to assume IPv4 packet by default if TSO was enabled.
         * 82571 hardware supports TSO capabilities for IPv6 as well...
         * no longer assume, we must. */
-       if (likely(skb->protocol == ntohs(ETH_P_IP)))
+       if (likely(skb->protocol == htons(ETH_P_IP)))
                tx_flags |= E1000_TX_FLAGS_IPV4;
 
        e1000_tx_queue(adapter, tx_ring, tx_flags,
@@ -2982,8 +2952,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
 
        /* Adapter-specific max frame size limits. */
        switch (adapter->hw.mac_type) {
-       case e1000_82542_rev2_0:
-       case e1000_82542_rev2_1:
+       case e1000_undefined ... e1000_82542_rev2_1:
                if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
                        DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
                        return -EINVAL;
@@ -3017,27 +2986,32 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
                break;
        }
 
-
-       if (adapter->hw.mac_type > e1000_82547_rev_2) {
-               adapter->rx_buffer_len = max_frame;
-               E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
-       } else {
-               if(unlikely((adapter->hw.mac_type < e1000_82543) &&
-                  (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
-                       DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
-                                           "on 82542\n");
-                       return -EINVAL;
-               } else {
-                       if(max_frame <= E1000_RXBUFFER_2048)
-                               adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-                       else if(max_frame <= E1000_RXBUFFER_4096)
-                               adapter->rx_buffer_len = E1000_RXBUFFER_4096;
-                       else if(max_frame <= E1000_RXBUFFER_8192)
-                               adapter->rx_buffer_len = E1000_RXBUFFER_8192;
-                       else if(max_frame <= E1000_RXBUFFER_16384)
-                               adapter->rx_buffer_len = E1000_RXBUFFER_16384;
-               }
-       }
+       /* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+        * means we reserve 2 more, this pushes us to allocate from the next
+        * larger slab size
+        * i.e. RXBUFFER_2048 --> size-4096 slab */
+
+       if (max_frame <= E1000_RXBUFFER_256)
+               adapter->rx_buffer_len = E1000_RXBUFFER_256;
+       else if (max_frame <= E1000_RXBUFFER_512)
+               adapter->rx_buffer_len = E1000_RXBUFFER_512;
+       else if (max_frame <= E1000_RXBUFFER_1024)
+               adapter->rx_buffer_len = E1000_RXBUFFER_1024;
+       else if (max_frame <= E1000_RXBUFFER_2048)
+               adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+       else if (max_frame <= E1000_RXBUFFER_4096)
+               adapter->rx_buffer_len = E1000_RXBUFFER_4096;
+       else if (max_frame <= E1000_RXBUFFER_8192)
+               adapter->rx_buffer_len = E1000_RXBUFFER_8192;
+       else if (max_frame <= E1000_RXBUFFER_16384)
+               adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+
+       /* adjust allocation if LPE protects us, and we aren't using SBP */
+#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
+       if (!adapter->hw.tbi_compatibility_on &&
+           ((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
+            (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
+               adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
 
        netdev->mtu = new_mtu;
 
@@ -3165,7 +3139,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
                adapter->stats.crcerrs + adapter->stats.algnerrc +
                adapter->stats.ruc + adapter->stats.roc +
                adapter->stats.cexterr;
-       adapter->net_stats.rx_dropped = 0;
        adapter->net_stats.rx_length_errors = adapter->stats.ruc +
                                              adapter->stats.roc;
        adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
@@ -3391,13 +3364,15 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
 
        tx_ring->next_to_clean = i;
 
-       spin_lock(&tx_ring->tx_lock);
-
+#define TX_WAKE_THRESHOLD 32
        if (unlikely(cleaned && netif_queue_stopped(netdev) &&
-                   netif_carrier_ok(netdev)))
-               netif_wake_queue(netdev);
-
-       spin_unlock(&tx_ring->tx_lock);
+                    netif_carrier_ok(netdev))) {
+               spin_lock(&tx_ring->tx_lock);
+               if (netif_queue_stopped(netdev) &&
+                   (E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))
+                       netif_wake_queue(netdev);
+               spin_unlock(&tx_ring->tx_lock);
+       }
 
        if (adapter->detect_tx_hung) {
                /* Detect a transmit hang in hardware, this serializes the
@@ -3445,7 +3420,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
  * @sk_buff:     socket buffer with received data
  **/
 
-static inline void
+static void
 e1000_rx_checksum(struct e1000_adapter *adapter,
                  uint32_t status_err, uint32_t csum,
                  struct sk_buff *skb)
@@ -3569,7 +3544,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
                                                       flags);
                                length--;
                        } else {
-                               dev_kfree_skb_irq(skb);
+                               /* recycle */
+                               buffer_info->skb = skb;
                                goto next_desc;
                        }
                }
@@ -3677,6 +3653,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
        i = rx_ring->next_to_clean;
        rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
        staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+       buffer_info = &rx_ring->buffer_info[i];
 
        while (staterr & E1000_RXD_STAT_DD) {
                buffer_info = &rx_ring->buffer_info[i];
@@ -3737,9 +3714,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
 
                /* page alloc/put takes too long and effects small packet
                 * throughput, so unsplit small packets and save the alloc/put*/
-               if (l1 && ((length + l1) < E1000_CB_LENGTH)) {
+               if (l1 && ((length + l1) <= adapter->rx_ps_bsize0)) {
                        u8 *vaddr;
-                       /* there is no documentation about how to call 
+                       /* there is no documentation about how to call
                         * kmap_atomic, so we can't hold the mapping
                         * very long */
                        pci_dma_sync_single_for_cpu(pdev,
@@ -4159,7 +4136,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
                        spin_unlock_irqrestore(&adapter->stats_lock, flags);
                        return -EIO;
                }
-               if (adapter->hw.phy_type == e1000_media_type_copper) {
+               if (adapter->hw.media_type == e1000_media_type_copper) {
                        switch (data->reg_num) {
                        case PHY_CTRL:
                                if (mii_reg & MII_CR_POWER_DOWN)
@@ -4518,21 +4495,13 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
 
                E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
                E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
-               retval = pci_enable_wake(pdev, PCI_D3hot, 1);
-               if (retval)
-                       DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-               retval = pci_enable_wake(pdev, PCI_D3cold, 1);
-               if (retval)
-                       DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+               pci_enable_wake(pdev, PCI_D3hot, 1);
+               pci_enable_wake(pdev, PCI_D3cold, 1);
        } else {
                E1000_WRITE_REG(&adapter->hw, WUC, 0);
                E1000_WRITE_REG(&adapter->hw, WUFC, 0);
-               retval = pci_enable_wake(pdev, PCI_D3hot, 0);
-               if (retval)
-                       DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-               retval = pci_enable_wake(pdev, PCI_D3cold, 0);
-               if (retval)
-                       DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+               pci_enable_wake(pdev, PCI_D3hot, 0);
+               pci_enable_wake(pdev, PCI_D3cold, 0);
        }
 
        if (adapter->hw.mac_type >= e1000_82540 &&
@@ -4541,13 +4510,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
                if (manc & E1000_MANC_SMBUS_EN) {
                        manc |= E1000_MANC_ARP_EN;
                        E1000_WRITE_REG(&adapter->hw, MANC, manc);
-                       retval = pci_enable_wake(pdev, PCI_D3hot, 1);
-                       if (retval)
-                               DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-                       retval = pci_enable_wake(pdev, PCI_D3cold, 1);
-                       if (retval)
-                               DPRINTK(PROBE, ERR,
-                                       "Error enabling D3 cold wake\n");
+                       pci_enable_wake(pdev, PCI_D3hot, 1);
+                       pci_enable_wake(pdev, PCI_D3cold, 1);
                }
        }
 
@@ -4557,9 +4521,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
 
        pci_disable_device(pdev);
 
-       retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
-       if (retval)
-               DPRINTK(PROBE, ERR, "Error in setting power state\n");
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
        return 0;
 }
@@ -4570,22 +4532,15 @@ e1000_resume(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
-       int retval;
        uint32_t manc, ret_val;
 
-       retval = pci_set_power_state(pdev, PCI_D0);
-       if (retval)
-               DPRINTK(PROBE, ERR, "Error in setting power state\n");
+       pci_set_power_state(pdev, PCI_D0);
        e1000_pci_restore_state(adapter);
        ret_val = pci_enable_device(pdev);
        pci_set_master(pdev);
 
-       retval = pci_enable_wake(pdev, PCI_D3hot, 0);
-       if (retval)
-               DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-       retval = pci_enable_wake(pdev, PCI_D3cold, 0);
-       if (retval)
-               DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+       pci_enable_wake(pdev, PCI_D3cold, 0);
 
        e1000_reset(adapter);
        E1000_WRITE_REG(&adapter->hw, WUS, ~0);
index 9790db9..048d052 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -22,6 +22,7 @@
   
   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
 
 *******************************************************************************/
index e0a4d37..e55f896 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -22,6 +22,7 @@
   
   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
 
 *******************************************************************************/
index 2f7b868..8d680ce 100644 (file)
        http://www.scyld.com/network/epic100.html
 
        ---------------------------------------------------------------------
-       
+
        Linux kernel-specific changes:
-       
+
        LK1.1.2 (jgarzik):
        * Merge becker version 1.09 (4/08/2000)
 
        LK1.1.3:
        * Major bugfix to 1.09 driver (Francis Romieu)
-       
+
        LK1.1.4 (jgarzik):
        * Merge becker test version 1.09 (5/29/2000)
 
@@ -66,7 +66,7 @@
        LK1.1.14 (Kryzsztof Halasa):
        * fix spurious bad initializations
        * pound phy a la SMSC's app note on the subject
-       
+
        AC1.1.14ac
        * fix power up/down for ethtool that broke in 1.11
 
@@ -244,7 +244,7 @@ static struct pci_device_id epic_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE (pci, epic_pci_tbl);
 
-       
+
 #ifndef USE_IO_OPS
 #undef inb
 #undef inw
@@ -370,7 +370,7 @@ static int epic_close(struct net_device *dev);
 static struct net_device_stats *epic_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 
-\f
+
 
 static int __devinit epic_init_one (struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
@@ -392,9 +392,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
                printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
                        version, version2, version3);
 #endif
-       
+
        card_idx++;
-       
+
        ret = pci_enable_device(pdev);
        if (ret)
                goto out;
@@ -405,7 +405,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
                ret = -ENODEV;
                goto err_out_disable;
        }
-       
+
        pci_set_master(pdev);
 
        ret = pci_request_regions(pdev, DRV_NAME);
@@ -498,7 +498,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
        ep->pci_dev = pdev;
        ep->chip_id = chip_idx;
        ep->chip_flags = pci_id_tbl[chip_idx].drv_flags;
-       ep->irq_mask = 
+       ep->irq_mask =
                (ep->chip_flags & TYPE2_INTR ?  PCIBusErr175 : PCIBusErr170)
                 | CntFull | TxUnderrun | EpicNapiEvent;
 
@@ -587,7 +587,7 @@ err_out_disable:
        pci_disable_device(pdev);
        goto out;
 }
-\f
+
 /* Serial EEPROM section. */
 
 /*  EEPROM_Ctrl bits. */
@@ -709,7 +709,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
 
        outw(value, ioaddr + MIIData);
        outl((phy_id << 9) | (loc << 4) | MII_WRITEOP, ioaddr + MIICtrl);
-       for (i = 10000; i > 0; i--) { 
+       for (i = 10000; i > 0; i--) {
                barrier();
                if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0)
                        break;
@@ -717,7 +717,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
        return;
 }
 
-\f
+
 static int epic_open(struct net_device *dev)
 {
        struct epic_private *ep = dev->priv;
@@ -760,7 +760,7 @@ static int epic_open(struct net_device *dev)
 #endif
 
        udelay(20); /* Looks like EPII needs that if you want reliable RX init. FIXME: pci posting bug? */
-       
+
        for (i = 0; i < 3; i++)
                outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
 
@@ -803,7 +803,7 @@ static int epic_open(struct net_device *dev)
 
        /* Enable interrupts by setting the interrupt mask. */
        outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-                | CntFull | TxUnderrun 
+                | CntFull | TxUnderrun
                 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
 
        if (debug > 1)
@@ -831,7 +831,7 @@ static void epic_pause(struct net_device *dev)
        struct epic_private *ep = dev->priv;
 
        netif_stop_queue (dev);
-       
+
        /* Disable interrupts by clearing the interrupt mask. */
        outl(0x00000000, ioaddr + INTMASK);
        /* Stop the chip's Tx and Rx DMA processes. */
@@ -987,7 +987,7 @@ static void epic_init_ring(struct net_device *dev)
        for (i = 0; i < RX_RING_SIZE; i++) {
                ep->rx_ring[i].rxstatus = 0;
                ep->rx_ring[i].buflength = cpu_to_le32(ep->rx_buf_sz);
-               ep->rx_ring[i].next = ep->rx_ring_dma + 
+               ep->rx_ring[i].next = ep->rx_ring_dma +
                                      (i+1)*sizeof(struct epic_rx_desc);
                ep->rx_skbuff[i] = NULL;
        }
@@ -1002,7 +1002,7 @@ static void epic_init_ring(struct net_device *dev)
                        break;
                skb->dev = dev;                 /* Mark as being used by this device. */
                skb_reserve(skb, 2);    /* 16 byte align the IP header. */
-               ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev, 
+               ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev,
                        skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
                ep->rx_ring[i].rxstatus = cpu_to_le32(DescOwn);
        }
@@ -1013,7 +1013,7 @@ static void epic_init_ring(struct net_device *dev)
        for (i = 0; i < TX_RING_SIZE; i++) {
                ep->tx_skbuff[i] = NULL;
                ep->tx_ring[i].txstatus = 0x0000;
-               ep->tx_ring[i].next = ep->tx_ring_dma + 
+               ep->tx_ring[i].next = ep->tx_ring_dma +
                        (i+1)*sizeof(struct epic_tx_desc);
        }
        ep->tx_ring[i-1].next = ep->tx_ring_dma;
@@ -1026,7 +1026,7 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
        int entry, free_count;
        u32 ctrl_word;
        unsigned long flags;
-       
+
        if (skb->len < ETH_ZLEN) {
                skb = skb_padto(skb, ETH_ZLEN);
                if (skb == NULL)
@@ -1042,7 +1042,7 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
        entry = ep->cur_tx % TX_RING_SIZE;
 
        ep->tx_skbuff[entry] = skb;
-       ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data, 
+       ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data,
                                                    skb->len, PCI_DMA_TODEVICE);
        if (free_count < TX_QUEUE_LEN/2) {/* Typical path */
                ctrl_word = cpu_to_le32(0x100000); /* No interrupt */
@@ -1126,7 +1126,7 @@ static void epic_tx(struct net_device *dev, struct epic_private *ep)
 
                /* Free the original skb. */
                skb = ep->tx_skbuff[entry];
-               pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
+               pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr,
                                 skb->len, PCI_DMA_TODEVICE);
                dev_kfree_skb_irq(skb);
                ep->tx_skbuff[entry] = NULL;
@@ -1281,8 +1281,8 @@ static int epic_rx(struct net_device *dev, int budget)
                                                               ep->rx_buf_sz,
                                                               PCI_DMA_FROMDEVICE);
                        } else {
-                               pci_unmap_single(ep->pci_dev, 
-                                       ep->rx_ring[entry].bufaddr, 
+                               pci_unmap_single(ep->pci_dev,
+                                       ep->rx_ring[entry].bufaddr,
                                        ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
                                skb_put(skb = ep->rx_skbuff[entry], pkt_len);
                                ep->rx_skbuff[entry] = NULL;
@@ -1307,7 +1307,7 @@ static int epic_rx(struct net_device *dev, int budget)
                                break;
                        skb->dev = dev;                 /* Mark as being used by this device. */
                        skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
-                       ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, 
+                       ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev,
                                skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
                        work_done++;
                }
@@ -1403,7 +1403,7 @@ static int epic_close(struct net_device *dev)
                ep->rx_ring[i].rxstatus = 0;            /* Not owned by Epic chip. */
                ep->rx_ring[i].buflength = 0;
                if (skb) {
-                       pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr, 
+                       pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr,
                                         ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
                        dev_kfree_skb(skb);
                }
@@ -1414,7 +1414,7 @@ static int epic_close(struct net_device *dev)
                ep->tx_skbuff[i] = NULL;
                if (!skb)
                        continue;
-               pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr, 
+               pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr,
                                 skb->len, PCI_DMA_TODEVICE);
                dev_kfree_skb(skb);
        }
@@ -1607,7 +1607,7 @@ static void __devexit epic_remove_one (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct epic_private *ep = dev->priv;
-       
+
        pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
        pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
        unregister_netdev(dev);
index feb5b22..5669b95 100644 (file)
  *     0.52: 20 Jan 2006: Add MSI/MSIX support.
  *     0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
  *     0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
+ *     0.55: 22 Mar 2006: Add flow control (pause frame).
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION              "0.54"
+#define FORCEDETH_VERSION              "0.55"
 #define DRV_NAME                       "forcedeth"
 
 #include <linux/module.h>
 #define DEV_HAS_MSI             0x0040  /* device supports MSI */
 #define DEV_HAS_MSI_X           0x0080  /* device supports MSI-X */
 #define DEV_HAS_POWER_CNTRL     0x0100  /* device supports power savings */
+#define DEV_HAS_PAUSEFRAME_TX   0x0200  /* device supports tx pause frames */
 
 enum {
        NvRegIrqStatus = 0x000,
@@ -203,6 +205,7 @@ enum {
        NvRegMSIIrqMask = 0x030,
 #define NVREG_MSI_VECTOR_0_ENABLED 0x01
        NvRegMisc1 = 0x080,
+#define NVREG_MISC1_PAUSE_TX   0x01
 #define NVREG_MISC1_HD         0x02
 #define NVREG_MISC1_FORCE      0x3b0f3c
 
@@ -214,7 +217,8 @@ enum {
 #define NVREG_XMITSTAT_BUSY    0x01
 
        NvRegPacketFilterFlags = 0x8c,
-#define NVREG_PFF_ALWAYS       0x7F0008
+#define NVREG_PFF_PAUSE_RX     0x08
+#define NVREG_PFF_ALWAYS       0x7F0000
 #define NVREG_PFF_PROMISC      0x80
 #define NVREG_PFF_MYADDR       0x20
 
@@ -277,6 +281,9 @@ enum {
 #define NVREG_TXRXCTL_VLANINS  0x00080
        NvRegTxRingPhysAddrHigh = 0x148,
        NvRegRxRingPhysAddrHigh = 0x14C,
+       NvRegTxPauseFrame = 0x170,
+#define NVREG_TX_PAUSEFRAME_DISABLE    0x1ff0080
+#define NVREG_TX_PAUSEFRAME_ENABLE     0x0c00030
        NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR            0x0001
 #define NVREG_MIISTAT_LINKCHANGE       0x0008
@@ -451,7 +458,7 @@ typedef union _ring_type {
 
 #define RX_RING                128
 #define TX_RING                256
-/* 
+/*
  * If your nic mysteriously hangs then try to reduce the limits
  * to 1/0: It might be required to set NV_TX_LASTPACKET in the
  * last valid ring entry. But this would be impossible to
@@ -473,7 +480,7 @@ typedef union _ring_type {
 #define POLL_WAIT      (1+HZ/100)
 #define LINK_TIMEOUT   (3*HZ)
 
-/* 
+/*
  * desc_ver values:
  * The nic supports three different descriptor types:
  * - DESC_VER_1: Original
@@ -506,13 +513,10 @@ typedef union _ring_type {
 #define PHY_1000       0x2
 #define PHY_HALF       0x100
 
-/* FIXME: MII defines that should be added to <linux/mii.h> */
-#define MII_1000BT_CR  0x09
-#define MII_1000BT_SR  0x0a
-#define ADVERTISE_1000FULL     0x0200
-#define ADVERTISE_1000HALF     0x0100
-#define LPA_1000FULL   0x0800
-#define LPA_1000HALF   0x0400
+#define NV_PAUSEFRAME_RX_CAPABLE 0x0001
+#define NV_PAUSEFRAME_TX_CAPABLE 0x0002
+#define NV_PAUSEFRAME_RX_ENABLE  0x0004
+#define NV_PAUSEFRAME_TX_ENABLE  0x0008
 
 /* MSI/MSI-X defines */
 #define NV_MSI_X_MAX_VECTORS  8
@@ -602,6 +606,9 @@ struct fe_priv {
        /* msi/msi-x fields */
        u32 msi_flags;
        struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS];
+
+       /* flow control */
+       u32 pause_flags;
 };
 
 /*
@@ -612,7 +619,7 @@ static int max_interrupt_work = 5;
 
 /*
  * Optimization can be either throuput mode or cpu mode
- * 
+ *
  * Throughput Mode: Every tx and rx packet will generate an interrupt.
  * CPU Mode: Interrupts are controlled by a timer.
  */
@@ -860,7 +867,7 @@ static int phy_init(struct net_device *dev)
 
        /* set advertise register */
        reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-       reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|0x800|0x400);
+       reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP);
        if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) {
                printk(KERN_INFO "%s: phy write to advertise failed.\n", pci_name(np->pci_dev));
                return PHY_ERROR;
@@ -873,14 +880,14 @@ static int phy_init(struct net_device *dev)
        mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
        if (mii_status & PHY_GIGABIT) {
                np->gigabit = PHY_GIGABIT;
-               mii_control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+               mii_control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
                mii_control_1000 &= ~ADVERTISE_1000HALF;
                if (phyinterface & PHY_RGMII)
                        mii_control_1000 |= ADVERTISE_1000FULL;
                else
                        mii_control_1000 &= ~ADVERTISE_1000FULL;
 
-               if (mii_rw(dev, np->phyaddr, MII_1000BT_CR, mii_control_1000)) {
+               if (mii_rw(dev, np->phyaddr, MII_CTRL1000, mii_control_1000)) {
                        printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
                        return PHY_ERROR;
                }
@@ -918,6 +925,8 @@ static int phy_init(struct net_device *dev)
                        return PHY_ERROR;
                }
        }
+       /* some phys clear out pause advertisment on reset, set it back */
+       mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
 
        /* restart auto negotiation */
        mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
@@ -1110,7 +1119,7 @@ static void nv_do_rx_refill(unsigned long data)
        }
 }
 
-static void nv_init_rx(struct net_device *dev) 
+static void nv_init_rx(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        int i;
@@ -1174,7 +1183,7 @@ static void nv_drain_tx(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        unsigned int i;
-       
+
        for (i = 0; i < TX_RING; i++) {
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
                        np->tx_ring.orig[i].FlagLen = 0;
@@ -1320,7 +1329,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
        } else {
                np->tx_ring.ex[start_nr].TxVlan = cpu_to_le32(tx_flags_vlan);
                np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
-       }       
+       }
 
        dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n",
                dev->name, np->next_tx, entries, tx_flags_extra);
@@ -1395,7 +1404,7 @@ static void nv_tx_done(struct net_device *dev)
                                } else {
                                        np->stats.tx_packets++;
                                        np->stats.tx_bytes += skb->len;
-                               }                               
+                               }
                        }
                }
                nv_release_txskb(dev, i);
@@ -1441,7 +1450,7 @@ static void nv_tx_timeout(struct net_device *dev)
                for (i=0;i<TX_RING;i+= 4) {
                        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
                                printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
-                                      i, 
+                                      i,
                                       le32_to_cpu(np->tx_ring.orig[i].PacketBuffer),
                                       le32_to_cpu(np->tx_ring.orig[i].FlagLen),
                                       le32_to_cpu(np->tx_ring.orig[i+1].PacketBuffer),
@@ -1452,7 +1461,7 @@ static void nv_tx_timeout(struct net_device *dev)
                                       le32_to_cpu(np->tx_ring.orig[i+3].FlagLen));
                        } else {
                                printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n",
-                                      i, 
+                                      i,
                                       le32_to_cpu(np->tx_ring.ex[i].PacketBufferHigh),
                                       le32_to_cpu(np->tx_ring.ex[i].PacketBufferLow),
                                       le32_to_cpu(np->tx_ring.ex[i].FlagLen),
@@ -1550,7 +1559,6 @@ static void nv_rx_process(struct net_device *dev)
        u32 Flags;
        u32 vlanflags = 0;
 
-
        for (;;) {
                struct sk_buff *skb;
                int len;
@@ -1901,7 +1909,9 @@ static int nv_update_linkspeed(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
-       int adv, lpa;
+       int adv = 0;
+       int lpa = 0;
+       int adv_lpa, adv_pause, lpa_pause;
        int newls = np->linkspeed;
        int newdup = np->duplex;
        int mii_status;
@@ -1954,8 +1964,8 @@ static int nv_update_linkspeed(struct net_device *dev)
 
        retval = 1;
        if (np->gigabit == PHY_GIGABIT) {
-               control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
-               status_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_SR, MII_READ);
+               control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
+               status_1000 = mii_rw(dev, np->phyaddr, MII_STAT1000, MII_READ);
 
                if ((control_1000 & ADVERTISE_1000FULL) &&
                        (status_1000 & LPA_1000FULL)) {
@@ -1973,21 +1983,21 @@ static int nv_update_linkspeed(struct net_device *dev)
                                dev->name, adv, lpa);
 
        /* FIXME: handle parallel detection properly */
-       lpa = lpa & adv;
-       if (lpa & LPA_100FULL) {
+       adv_lpa = lpa & adv;
+       if (adv_lpa & LPA_100FULL) {
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
                newdup = 1;
-       } else if (lpa & LPA_100HALF) {
+       } else if (adv_lpa & LPA_100HALF) {
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
                newdup = 0;
-       } else if (lpa & LPA_10FULL) {
+       } else if (adv_lpa & LPA_10FULL) {
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
                newdup = 1;
-       } else if (lpa & LPA_10HALF) {
+       } else if (adv_lpa & LPA_10HALF) {
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
                newdup = 0;
        } else {
-               dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, lpa);
+               dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, adv_lpa);
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
                newdup = 0;
        }
@@ -2030,6 +2040,56 @@ set_speed:
        writel(np->linkspeed, base + NvRegLinkSpeed);
        pci_push(base);
 
+       /* setup pause frame based on advertisement and link partner */
+       np->pause_flags &= ~(NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE);
+
+       if (np->duplex != 0) {
+               adv_pause = adv & (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM);
+               lpa_pause = lpa & (LPA_PAUSE_CAP| LPA_PAUSE_ASYM);
+
+               switch (adv_pause) {
+               case (ADVERTISE_PAUSE_CAP):
+                       if (lpa_pause & LPA_PAUSE_CAP) {
+                               np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE;
+                       }
+                       break;
+               case (ADVERTISE_PAUSE_ASYM):
+                       if (lpa_pause == (LPA_PAUSE_CAP| LPA_PAUSE_ASYM))
+                       {
+                               np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+                       }
+                       break;
+               case (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM):
+                       if (lpa_pause & LPA_PAUSE_CAP)
+                       {
+                               np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE;
+                       }
+                       if (lpa_pause == LPA_PAUSE_ASYM)
+                       {
+                               np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+                       }
+                       break;
+               }
+       }
+
+       if (np->pause_flags & NV_PAUSEFRAME_RX_CAPABLE) {
+               u32 pff = readl(base + NvRegPacketFilterFlags) & ~NVREG_PFF_PAUSE_RX;
+               if (np->pause_flags & NV_PAUSEFRAME_RX_ENABLE)
+                       writel(pff|NVREG_PFF_PAUSE_RX, base + NvRegPacketFilterFlags);
+               else
+                       writel(pff, base + NvRegPacketFilterFlags);
+       }
+       if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE) {
+               u32 regmisc = readl(base + NvRegMisc1) & ~NVREG_MISC1_PAUSE_TX;
+               if (np->pause_flags & NV_PAUSEFRAME_TX_ENABLE) {
+                       writel(NVREG_TX_PAUSEFRAME_ENABLE,  base + NvRegTxPauseFrame);
+                       writel(regmisc|NVREG_MISC1_PAUSE_TX, base + NvRegMisc1);
+               } else {
+                       writel(NVREG_TX_PAUSEFRAME_DISABLE,  base + NvRegTxPauseFrame);
+                       writel(regmisc, base + NvRegMisc1);
+               }
+       }
+
        return retval;
 }
 
@@ -2090,7 +2150,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
                spin_lock(&np->lock);
                nv_tx_done(dev);
                spin_unlock(&np->lock);
-               
+
                nv_rx_process(dev);
                if (nv_alloc_rx(dev)) {
                        spin_lock(&np->lock);
@@ -2098,7 +2158,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
                                mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
                        spin_unlock(&np->lock);
                }
-               
+
                if (events & NVREG_IRQ_LINK) {
                        spin_lock(&np->lock);
                        nv_link_irq(dev);
@@ -2163,7 +2223,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
                spin_lock_irq(&np->lock);
                nv_tx_done(dev);
                spin_unlock_irq(&np->lock);
-               
+
                if (events & (NVREG_IRQ_TX_ERR)) {
                        dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
                                                dev->name, events);
@@ -2206,7 +2266,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
                dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events);
                if (!(events & np->irqmask))
                        break;
-               
+
                nv_rx_process(dev);
                if (nv_alloc_rx(dev)) {
                        spin_lock_irq(&np->lock);
@@ -2214,7 +2274,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
                                mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
                        spin_unlock_irq(&np->lock);
                }
-               
+
                if (i > max_interrupt_work) {
                        spin_lock_irq(&np->lock);
                        /* disable interrupts on the nic */
@@ -2253,7 +2313,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
                dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
                if (!(events & np->irqmask))
                        break;
-               
+
                if (events & NVREG_IRQ_LINK) {
                        spin_lock_irq(&np->lock);
                        nv_link_irq(dev);
@@ -2326,7 +2386,7 @@ static void nv_do_nic_poll(unsigned long data)
        np->nic_poll_irq = 0;
 
        /* FIXME: Do we need synchronize_irq(dev->irq) here? */
-       
+
        writel(mask, base + NvRegIrqMask);
        pci_push(base);
 
@@ -2441,7 +2501,7 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        if (adv & ADVERTISE_100FULL)
                ecmd->advertising |= ADVERTISED_100baseT_Full;
        if (np->autoneg && np->gigabit == PHY_GIGABIT) {
-               adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+               adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
                if (adv & ADVERTISE_1000FULL)
                        ecmd->advertising |= ADVERTISED_1000baseT_Full;
        }
@@ -2505,23 +2565,23 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 
                /* advertise only what has been requested */
                adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-               adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+               adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
                if (ecmd->advertising & ADVERTISED_10baseT_Half)
                        adv |= ADVERTISE_10HALF;
                if (ecmd->advertising & ADVERTISED_10baseT_Full)
-                       adv |= ADVERTISE_10FULL;
+                       adv |= ADVERTISE_10FULL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
                if (ecmd->advertising & ADVERTISED_100baseT_Half)
                        adv |= ADVERTISE_100HALF;
                if (ecmd->advertising & ADVERTISED_100baseT_Full)
-                       adv |= ADVERTISE_100FULL;
+                       adv |= ADVERTISE_100FULL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
                mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
 
                if (np->gigabit == PHY_GIGABIT) {
-                       adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+                       adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
                        adv &= ~ADVERTISE_1000FULL;
                        if (ecmd->advertising & ADVERTISED_1000baseT_Full)
                                adv |= ADVERTISE_1000FULL;
-                       mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv);
+                       mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
                }
 
                bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
@@ -2534,22 +2594,22 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                np->autoneg = 0;
 
                adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-               adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+               adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
                if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF)
                        adv |= ADVERTISE_10HALF;
                if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL)
-                       adv |= ADVERTISE_10FULL;
+                       adv |= ADVERTISE_10FULL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
                if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF)
                        adv |= ADVERTISE_100HALF;
                if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL)
-                       adv |= ADVERTISE_100FULL;
+                       adv |= ADVERTISE_100FULL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
                mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
                np->fixed_mode = adv;
 
                if (np->gigabit == PHY_GIGABIT) {
-                       adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+                       adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
                        adv &= ~ADVERTISE_1000FULL;
-                       mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv);
+                       mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
                }
 
                bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
@@ -2829,6 +2889,9 @@ static int nv_open(struct net_device *dev)
 
        writel(0, base + NvRegAdapterControl);
 
+       if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)
+               writel(NVREG_TX_PAUSEFRAME_DISABLE,  base + NvRegTxPauseFrame);
+
        /* 2) initialize descriptor rings */
        set_bufsize(dev);
        oom = nv_init_ring(dev);
@@ -3114,6 +3177,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                np->msi_flags |= NV_MSI_X_CAPABLE;
        }
 
+       np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE;
+       if (id->driver_data & DEV_HAS_PAUSEFRAME_TX) {
+               np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE;
+       }
+
+
        err = -ENOMEM;
        np->base = ioremap(addr, np->register_size);
        if (!np->base)
@@ -3260,7 +3329,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                       pci_name(pci_dev));
                goto out_freering;
        }
-       
+
        /* reset it */
        phy_init(dev);
 
@@ -3374,11 +3443,11 @@ static struct pci_device_id pci_tbl[] = {
        },
        {       /* MCP55 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX,
        },
        {       /* MCP55 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX,
        },
        {0,},
 };
index 01ad904..51fd516 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 net-3-driver for the IBM LAN Adapter/A
 
 This is an extension to the Linux operating system, and is covered by the
@@ -11,9 +11,9 @@ This driver is based both on the SK_MCA driver, which is itself based on the
 SK_G16 and 3C523 driver.
 
 paper sources:
-  'PC Hardware: Aufbau, Funktionsweise, Programmierung' by 
+  'PC Hardware: Aufbau, Funktionsweise, Programmierung' by
   Hans-Peter Messmer for the basic Microchannel stuff
-  
+
   'Linux Geraetetreiber' by Allesandro Rubini, Kalle Dalheimer
   for help on Ethernet driver programming
 
@@ -27,14 +27,14 @@ paper sources:
 
 special acknowledgements to:
   - Bob Eager for helping me out with documentation from IBM
-  - Jim Shorney for his endless patience with me while I was using 
+  - Jim Shorney for his endless patience with me while I was using
     him as a beta tester to trace down the address filter bug ;-)
 
   Missing things:
 
   -> set debug level via ioctl instead of compile-time switches
   -> I didn't follow the development of the 2.1.x kernels, so my
-     assumptions about which things changed with which kernel version 
+     assumptions about which things changed with which kernel version
      are probably nonsense
 
 History:
@@ -275,7 +275,7 @@ static void InitDscrs(struct net_device *dev)
        priv->rrastart = raddr = priv->txbufstart + (TXBUFCNT * PKTSIZE);
        priv->rdastart = addr = priv->rrastart + (priv->rxbufcnt * sizeof(rra_t));
        priv->rxbufstart = baddr = priv->rdastart + (priv->rxbufcnt * sizeof(rda_t));
-       
+
        for (z = 0; z < priv->rxbufcnt; z++) {
                rra.startlo = baddr;
                rra.starthi = 0;
@@ -570,7 +570,7 @@ static void irqrx_handler(struct net_device *dev)
                lrdaaddr = priv->rdastart + (priv->lastrxdescr * sizeof(rda_t));
                memcpy_fromio(&rda, priv->base + rdaaddr, sizeof(rda_t));
 
-               /* iron out upper word halves of fields we use - SONIC will duplicate 
+               /* iron out upper word halves of fields we use - SONIC will duplicate
                   bits 0..15 to 16..31 */
 
                rda.status &= 0xffff;
@@ -836,9 +836,9 @@ static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev)
        baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE);
        memcpy_toio(priv->base + baddr, skb->data, skb->len);
 
-       /* copy filler into RAM - in case we're filling up... 
+       /* copy filler into RAM - in case we're filling up...
           we're filling a bit more than necessary, but that doesn't harm
-          since the buffer is far larger... 
+          since the buffer is far larger...
           Sorry Linus for the filler string but I couldn't resist ;-) */
 
        if (tmplen > skb->len) {
@@ -952,7 +952,7 @@ static int ibmlana_probe(struct net_device *dev)
        priv->realirq = irq;
        priv->medium = medium;
        spin_lock_init(&priv->lock);
-               
+
 
        /* set base + irq for this device (irq not allocated so far) */
 
index 458ee22..6b58bab 100644 (file)
@@ -17,7 +17,7 @@
 /* media enumeration - defined in a way that it fits onto the LAN/A's
    POS registers... */
 
-typedef enum { 
+typedef enum {
        Media_10BaseT, Media_10Base5,
        Media_Unknown, Media_10Base2, Media_Count
 } ibmlana_medium;
@@ -27,7 +27,7 @@ typedef enum {
 typedef struct {
        unsigned int slot;              /* MCA-Slot-#                       */
        struct net_device_stats stat;   /* packet statistics            */
-       int realirq;                    /* memorizes actual IRQ, even when 
+       int realirq;                    /* memorizes actual IRQ, even when
                                           currently not allocated          */
        ibmlana_medium medium;          /* physical cannector               */
        u32     tdastart, txbufstart,   /* addresses                        */
@@ -41,7 +41,7 @@ typedef struct {
        spinlock_t lock;
 } ibmlana_priv;
 
-/* this card uses quite a lot of I/O ports...luckily the MCA bus decodes 
+/* this card uses quite a lot of I/O ports...luckily the MCA bus decodes
    a full 64K I/O range... */
 
 #define IBM_LANA_IORANGE 0xa0
index 52d0102..666346f 100644 (file)
@@ -24,7 +24,7 @@
 /* for use with IBM i/pSeries LPAR Linux.  It utilizes the logical LAN    */
 /* option of the RS/6000 Platform Architechture to interface with virtual */
 /* ethernet NICs that are presented to the partition by the hypervisor.   */
-/*                                                                        */ 
+/*                                                                        */
 /**************************************************************************/
 /*
   TODO:
@@ -79,7 +79,7 @@
 #else
 #define ibmveth_debug_printk_no_adapter(fmt, args...)
 #define ibmveth_debug_printk(fmt, args...)
-#define ibmveth_assert(expr) 
+#define ibmveth_assert(expr)
 #endif
 
 static int ibmveth_open(struct net_device *dev);
@@ -96,6 +96,7 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
 static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
+static struct kobj_type ktype_veth_pool;
 
 #ifdef CONFIG_PROC_FS
 #define IBMVETH_PROC_DIR "net/ibmveth"
@@ -133,12 +134,13 @@ static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter)
 }
 
 /* setup the initial settings for a buffer pool */
-static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size)
+static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active)
 {
        pool->size = pool_size;
        pool->index = pool_index;
        pool->buff_size = buff_size;
        pool->threshold = pool_size / 2;
+       pool->active = pool_active;
 }
 
 /* allocate and setup an buffer pool - called during open */
@@ -146,13 +148,13 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
 {
        int i;
 
-       pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); 
+       pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL);
 
        if(!pool->free_map) {
                return -1;
        }
 
-       pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); 
+       pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL);
        if(!pool->dma_addr) {
                kfree(pool->free_map);
                pool->free_map = NULL;
@@ -180,7 +182,6 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
        atomic_set(&pool->available, 0);
        pool->producer_index = 0;
        pool->consumer_index = 0;
-       pool->active = 0;
 
        return 0;
 }
@@ -214,7 +215,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
 
                free_index = pool->consumer_index++ % pool->size;
                index = pool->free_map[free_index];
-       
+
                ibmveth_assert(index != IBM_VETH_INVALID_MAP);
                ibmveth_assert(pool->skbuff[index] == NULL);
 
@@ -231,10 +232,10 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
                desc.desc = 0;
                desc.fields.valid = 1;
                desc.fields.length = pool->buff_size;
-               desc.fields.address = dma_addr; 
+               desc.fields.address = dma_addr;
 
                lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
-                   
+
                if(lpar_rc != H_SUCCESS) {
                        pool->free_map[free_index] = index;
                        pool->skbuff[index] = NULL;
@@ -250,13 +251,13 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
                        adapter->replenish_add_buff_success++;
                }
        }
-    
+
        mb();
        atomic_add(buffers_added, &(pool->available));
 }
 
 /* replenish routine */
-static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) 
+static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
 {
        int i;
 
@@ -264,7 +265,7 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
 
        for(i = 0; i < IbmVethNumBufferPools; i++)
                if(adapter->rx_buff_pool[i].active)
-                       ibmveth_replenish_buffer_pool(adapter, 
+                       ibmveth_replenish_buffer_pool(adapter,
                                                     &adapter->rx_buff_pool[i]);
 
        adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
@@ -301,7 +302,6 @@ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibm
                kfree(pool->skbuff);
                pool->skbuff = NULL;
        }
-       pool->active = 0;
 }
 
 /* remove a buffer from a pool */
@@ -372,7 +372,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
        desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index];
 
        lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
-                   
+
        if(lpar_rc != H_SUCCESS) {
                ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
                ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
@@ -407,7 +407,7 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
                }
                free_page((unsigned long)adapter->buffer_list_addr);
                adapter->buffer_list_addr = NULL;
-       } 
+       }
 
        if(adapter->filter_list_addr != NULL) {
                if(!dma_mapping_error(adapter->filter_list_dma)) {
@@ -433,7 +433,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
        }
 
        for(i = 0; i<IbmVethNumBufferPools; i++)
-               ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]);
+               if (adapter->rx_buff_pool[i].active)
+                       ibmveth_free_buffer_pool(adapter,
+                                                &adapter->rx_buff_pool[i]);
 }
 
 static int ibmveth_open(struct net_device *netdev)
@@ -450,10 +452,10 @@ static int ibmveth_open(struct net_device *netdev)
 
        for(i = 0; i<IbmVethNumBufferPools; i++)
                rxq_entries += adapter->rx_buff_pool[i].size;
-    
+
        adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
        adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
+
        if(!adapter->buffer_list_addr || !adapter->filter_list_addr) {
                ibmveth_error_printk("unable to allocate filter or buffer list pages\n");
                ibmveth_cleanup(adapter);
@@ -489,9 +491,6 @@ static int ibmveth_open(struct net_device *netdev)
        adapter->rx_queue.num_slots = rxq_entries;
        adapter->rx_queue.toggle = 1;
 
-       /* call change_mtu to init the buffer pools based in initial mtu */
-       ibmveth_change_mtu(netdev, netdev->mtu);
-
        memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
        mac_address = mac_address >> 16;
 
@@ -504,7 +503,7 @@ static int ibmveth_open(struct net_device *netdev)
        ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
        ibmveth_debug_printk("receive q   @ 0x%p\n", adapter->rx_queue.queue_addr);
 
-    
+
        lpar_rc = h_register_logical_lan(adapter->vdev->unit_address,
                                         adapter->buffer_list_dma,
                                         rxq_desc.desc,
@@ -519,7 +518,18 @@ static int ibmveth_open(struct net_device *netdev)
                                     rxq_desc.desc,
                                     mac_address);
                ibmveth_cleanup(adapter);
-               return -ENONET; 
+               return -ENONET;
+       }
+
+       for(i = 0; i<IbmVethNumBufferPools; i++) {
+               if(!adapter->rx_buff_pool[i].active)
+                       continue;
+               if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[i])) {
+                       ibmveth_error_printk("unable to alloc pool\n");
+                       adapter->rx_buff_pool[i].active = 0;
+                       ibmveth_cleanup(adapter);
+                       return -ENOMEM ;
+               }
        }
 
        ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq);
@@ -547,10 +557,11 @@ static int ibmveth_close(struct net_device *netdev)
 {
        struct ibmveth_adapter *adapter = netdev->priv;
        long lpar_rc;
-    
+
        ibmveth_debug_printk("close starting\n");
 
-       netif_stop_queue(netdev);
+       if (!adapter->pool_config)
+               netif_stop_queue(netdev);
 
        free_irq(netdev->irq, netdev);
 
@@ -694,7 +705,7 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                                             desc[5].desc,
                                             correlator);
        } while ((lpar_rc == H_BUSY) && (retry_count--));
-    
+
        if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
                int i;
                ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
@@ -780,7 +791,7 @@ static int ibmveth_poll(struct net_device *netdev, int *budget)
                /* more work to do - return that we are not done yet */
                netdev->quota -= frames_processed;
                *budget -= frames_processed;
-               return 1; 
+               return 1;
        }
 
        /* we think we are done - reenable interrupts, then check once more to make sure we are done */
@@ -806,7 +817,7 @@ static int ibmveth_poll(struct net_device *netdev, int *budget)
 }
 
 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
-{   
+{
        struct net_device *netdev = dev_instance;
        struct ibmveth_adapter *adapter = netdev->priv;
        unsigned long lpar_rc;
@@ -862,7 +873,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
                                ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
                        }
                }
-       
+
                /* re-enable filtering */
                lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
                                           IbmVethMcastEnableFiltering,
@@ -876,46 +887,22 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
 static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct ibmveth_adapter *adapter = dev->priv;
+       int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
        int i;
-       int prev_smaller = 1;
 
-       if ((new_mtu < 68) || 
-           (new_mtu > (pool_size[IbmVethNumBufferPools-1]) - IBMVETH_BUFF_OH))
+       if (new_mtu < IBMVETH_MAX_MTU)
                return -EINVAL;
 
+       /* Look for an active buffer pool that can hold the new MTU */
        for(i = 0; i<IbmVethNumBufferPools; i++) {
-               int activate = 0;
-               if (new_mtu > (pool_size[i]  - IBMVETH_BUFF_OH)) { 
-                       activate = 1;
-                       prev_smaller= 1;
-               } else {
-                       if (prev_smaller)
-                               activate = 1;
-                       prev_smaller= 0;
+               if (!adapter->rx_buff_pool[i].active)
+                       continue;
+               if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
+                       dev->mtu = new_mtu;
+                       return 0;
                }
-
-               if (activate && !adapter->rx_buff_pool[i].active) {
-                       struct ibmveth_buff_pool *pool = 
-                                               &adapter->rx_buff_pool[i];
-                       if(ibmveth_alloc_buffer_pool(pool)) {
-                               ibmveth_error_printk("unable to alloc pool\n");
-                               return -ENOMEM;
-                       }
-                       adapter->rx_buff_pool[i].active = 1;
-               } else if (!activate && adapter->rx_buff_pool[i].active) {
-                       adapter->rx_buff_pool[i].active = 0;
-                       h_free_logical_lan_buffer(adapter->vdev->unit_address,
-                                         (u64)pool_size[i]);
-               }
-
        }
-
-       /* kick the interrupt handler so that the new buffer pools get
-          replenished or deallocated */
-       ibmveth_interrupt(dev->irq, dev, NULL);
-
-       dev->mtu = new_mtu;
-       return 0;       
+       return -EINVAL;
 }
 
 static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
@@ -928,7 +915,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
        unsigned int *mcastFilterSize_p;
 
 
-       ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", 
+       ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n",
                                        dev->unit_address);
 
        mac_addr_p = (unsigned char *) vio_get_attribute(dev, VETH_MAC_ADDR, 0);
@@ -937,7 +924,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
                                "attribute\n", __FILE__, __LINE__);
                return 0;
        }
-       
+
        mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0);
        if(!mcastFilterSize_p) {
                printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find "
@@ -945,7 +932,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
                                __FILE__, __LINE__);
                return 0;
        }
-       
+
        netdev = alloc_etherdev(sizeof(struct ibmveth_adapter));
 
        if(!netdev)
@@ -960,13 +947,14 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
        adapter->vdev = dev;
        adapter->netdev = netdev;
        adapter->mcastFilterSize= *mcastFilterSize_p;
-       
+       adapter->pool_config = 0;
+
        /*      Some older boxes running PHYP non-natively have an OF that
-               returns a 8-byte local-mac-address field (and the first 
+               returns a 8-byte local-mac-address field (and the first
                2 bytes have to be ignored) while newer boxes' OF return
-               a 6-byte field. Note that IEEE 1275 specifies that 
+               a 6-byte field. Note that IEEE 1275 specifies that
                local-mac-address must be a 6-byte field.
-               The RPA doc specifies that the first byte must be 10b, so 
+               The RPA doc specifies that the first byte must be 10b, so
                we'll just look for it to solve this 8 vs. 6 byte field issue */
 
        if ((*mac_addr_p & 0x3) != 0x02)
@@ -976,7 +964,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
        memcpy(&adapter->mac_addr, mac_addr_p, 6);
 
        adapter->liobn = dev->iommu_table->it_index;
-       
+
        netdev->irq = dev->irq;
        netdev->open               = ibmveth_open;
        netdev->poll               = ibmveth_poll;
@@ -989,14 +977,21 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
        netdev->ethtool_ops           = &netdev_ethtool_ops;
        netdev->change_mtu         = ibmveth_change_mtu;
        SET_NETDEV_DEV(netdev, &dev->dev);
-       netdev->features |= NETIF_F_LLTX; 
+       netdev->features |= NETIF_F_LLTX;
        spin_lock_init(&adapter->stats_lock);
 
        memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
 
-       for(i = 0; i<IbmVethNumBufferPools; i++)
-               ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, 
-                                        pool_count[i], pool_size[i]);
+       for(i = 0; i<IbmVethNumBufferPools; i++) {
+               struct kobject *kobj = &adapter->rx_buff_pool[i].kobj;
+               ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i,
+                                        pool_count[i], pool_size[i],
+                                        pool_active[i]);
+               kobj->parent = &dev->dev.kobj;
+               sprintf(kobj->name, "pool%d", i);
+               kobj->ktype = &ktype_veth_pool;
+               kobject_register(kobj);
+       }
 
        ibmveth_debug_printk("adapter @ 0x%p\n", adapter);
 
@@ -1025,6 +1020,10 @@ static int __devexit ibmveth_remove(struct vio_dev *dev)
 {
        struct net_device *netdev = dev->dev.driver_data;
        struct ibmveth_adapter *adapter = netdev->priv;
+       int i;
+
+       for(i = 0; i<IbmVethNumBufferPools; i++)
+               kobject_unregister(&adapter->rx_buff_pool[i].kobj);
 
        unregister_netdev(netdev);
 
@@ -1048,7 +1047,7 @@ static void ibmveth_proc_unregister_driver(void)
        remove_proc_entry(IBMVETH_PROC_DIR, NULL);
 }
 
-static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) 
+static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos)
 {
        if (*pos == 0) {
                return (void *)1;
@@ -1063,18 +1062,18 @@ static void *ibmveth_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        return NULL;
 }
 
-static void ibmveth_seq_stop(struct seq_file *seq, void *v) 
+static void ibmveth_seq_stop(struct seq_file *seq, void *v)
 {
 }
 
-static int ibmveth_seq_show(struct seq_file *seq, void *v) 
+static int ibmveth_seq_show(struct seq_file *seq, void *v)
 {
        struct ibmveth_adapter *adapter = seq->private;
        char *current_mac = ((char*) &adapter->netdev->dev_addr);
        char *firmware_mac = ((char*) &adapter->mac_addr) ;
 
        seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
-       
+
        seq_printf(seq, "Unit Address:    0x%x\n", adapter->vdev->unit_address);
        seq_printf(seq, "LIOBN:           0x%lx\n", adapter->liobn);
        seq_printf(seq, "Current MAC:     %02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -1083,7 +1082,7 @@ static int ibmveth_seq_show(struct seq_file *seq, void *v)
        seq_printf(seq, "Firmware MAC:    %02X:%02X:%02X:%02X:%02X:%02X\n",
                   firmware_mac[0], firmware_mac[1], firmware_mac[2],
                   firmware_mac[3], firmware_mac[4], firmware_mac[5]);
-       
+
        seq_printf(seq, "\nAdapter Statistics:\n");
        seq_printf(seq, "  TX:  skbuffs linearized:          %ld\n", adapter->tx_linearized);
        seq_printf(seq, "       multi-descriptor sends:      %ld\n", adapter->tx_multidesc_send);
@@ -1095,7 +1094,7 @@ static int ibmveth_seq_show(struct seq_file *seq, void *v)
        seq_printf(seq, "       add buffer failures:         %ld\n", adapter->replenish_add_buff_failure);
        seq_printf(seq, "       invalid buffers:             %ld\n", adapter->rx_invalid_buffer);
        seq_printf(seq, "       no buffers:                  %ld\n", adapter->rx_no_buffer);
-       
+
        return 0;
 }
 static struct seq_operations ibmveth_seq_ops = {
@@ -1153,11 +1152,11 @@ static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
 }
 
 #else /* CONFIG_PROC_FS */
-static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) 
+static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
 {
 }
 
-static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) 
+static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
 {
 }
 static void ibmveth_proc_register_driver(void)
@@ -1169,6 +1168,132 @@ static void ibmveth_proc_unregister_driver(void)
 }
 #endif /* CONFIG_PROC_FS */
 
+static struct attribute veth_active_attr;
+static struct attribute veth_num_attr;
+static struct attribute veth_size_attr;
+
+static ssize_t veth_pool_show(struct kobject * kobj,
+                              struct attribute * attr, char * buf)
+{
+       struct ibmveth_buff_pool *pool = container_of(kobj,
+                                                     struct ibmveth_buff_pool,
+                                                     kobj);
+
+       if (attr == &veth_active_attr)
+               return sprintf(buf, "%d\n", pool->active);
+       else if (attr == &veth_num_attr)
+               return sprintf(buf, "%d\n", pool->size);
+       else if (attr == &veth_size_attr)
+               return sprintf(buf, "%d\n", pool->buff_size);
+       return 0;
+}
+
+static ssize_t veth_pool_store(struct kobject * kobj, struct attribute * attr,
+const char * buf, size_t count)
+{
+       struct ibmveth_buff_pool *pool = container_of(kobj,
+                                                     struct ibmveth_buff_pool,
+                                                     kobj);
+       struct net_device *netdev =
+           container_of(kobj->parent, struct device, kobj)->driver_data;
+       struct ibmveth_adapter *adapter = netdev->priv;
+       long value = simple_strtol(buf, NULL, 10);
+       long rc;
+
+       if (attr == &veth_active_attr) {
+               if (value && !pool->active) {
+                       if(ibmveth_alloc_buffer_pool(pool)) {
+                                ibmveth_error_printk("unable to alloc pool\n");
+                                return -ENOMEM;
+                        }
+                       pool->active = 1;
+                       adapter->pool_config = 1;
+                       ibmveth_close(netdev);
+                       adapter->pool_config = 0;
+                       if ((rc = ibmveth_open(netdev)))
+                               return rc;
+               } else if (!value && pool->active) {
+                       int mtu = netdev->mtu + IBMVETH_BUFF_OH;
+                       int i;
+                       /* Make sure there is a buffer pool with buffers that
+                          can hold a packet of the size of the MTU */
+                       for(i = 0; i<IbmVethNumBufferPools; i++) {
+                               if (pool == &adapter->rx_buff_pool[i])
+                                       continue;
+                               if (!adapter->rx_buff_pool[i].active)
+                                       continue;
+                               if (mtu < adapter->rx_buff_pool[i].buff_size) {
+                                       pool->active = 0;
+                                       h_free_logical_lan_buffer(adapter->
+                                                                 vdev->
+                                                                 unit_address,
+                                                                 pool->
+                                                                 buff_size);
+                               }
+                       }
+                       if (pool->active) {
+                               ibmveth_error_printk("no active pool >= MTU\n");
+                               return -EPERM;
+                       }
+               }
+       } else if (attr == &veth_num_attr) {
+               if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
+                       return -EINVAL;
+               else {
+                       adapter->pool_config = 1;
+                       ibmveth_close(netdev);
+                       adapter->pool_config = 0;
+                       pool->size = value;
+                       if ((rc = ibmveth_open(netdev)))
+                               return rc;
+               }
+       } else if (attr == &veth_size_attr) {
+               if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE)
+                       return -EINVAL;
+               else {
+                       adapter->pool_config = 1;
+                       ibmveth_close(netdev);
+                       adapter->pool_config = 0;
+                       pool->buff_size = value;
+                       if ((rc = ibmveth_open(netdev)))
+                               return rc;
+               }
+       }
+
+       /* kick the interrupt handler to allocate/deallocate pools */
+       ibmveth_interrupt(netdev->irq, netdev, NULL);
+       return count;
+}
+
+
+#define ATTR(_name, _mode)      \
+        struct attribute veth_##_name##_attr = {               \
+        .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \
+        };
+
+static ATTR(active, 0644);
+static ATTR(num, 0644);
+static ATTR(size, 0644);
+
+static struct attribute * veth_pool_attrs[] = {
+       &veth_active_attr,
+       &veth_num_attr,
+       &veth_size_attr,
+       NULL,
+};
+
+static struct sysfs_ops veth_pool_ops = {
+       .show   = veth_pool_show,
+       .store  = veth_pool_store,
+};
+
+static struct kobj_type ktype_veth_pool = {
+       .release        = NULL,
+       .sysfs_ops      = &veth_pool_ops,
+       .default_attrs  = veth_pool_attrs,
+};
+
+
 static struct vio_device_id ibmveth_device_table[] __devinitdata= {
        { "network", "IBM,l-lan"},
        { "", "" }
@@ -1198,7 +1323,7 @@ static void __exit ibmveth_module_exit(void)
 {
        vio_unregister_driver(&ibmveth_driver);
        ibmveth_proc_unregister_driver();
-}      
+}
 
 module_init(ibmveth_module_init);
 module_exit(ibmveth_module_exit);
index 46919a8..8385bf8 100644 (file)
 
 #define IbmVethNumBufferPools 5
 #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
+#define IBMVETH_MAX_MTU 68
+#define IBMVETH_MAX_POOL_COUNT 4096
+#define IBMVETH_MAX_BUF_SIZE (1024 * 128)
 
-/* pool_size should be sorted */
 static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
 static int pool_count[] = { 256, 768, 256, 256, 256 };
+static int pool_active[] = { 1, 1, 0, 0, 0};
 
 #define IBM_VETH_INVALID_MAP ((u16)0xffff)
 
@@ -94,6 +97,7 @@ struct ibmveth_buff_pool {
     dma_addr_t *dma_addr;
     struct sk_buff **skbuff;
     int active;
+    struct kobject kobj;
 };
 
 struct ibmveth_rx_q {
@@ -118,6 +122,7 @@ struct ibmveth_adapter {
     dma_addr_t filter_list_dma;
     struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
     struct ibmveth_rx_q rx_queue;
+    int pool_config;
 
     /* adapter specific stats */
     u64 replenish_task_cycles;
@@ -134,7 +139,7 @@ struct ibmveth_adapter {
     spinlock_t stats_lock;
 };
 
-struct ibmveth_buf_desc_fields {       
+struct ibmveth_buf_desc_fields {
     u32 valid : 1;
     u32 toggle : 1;
     u32 reserved : 6;
@@ -143,7 +148,7 @@ struct ibmveth_buf_desc_fields {
 };
 
 union ibmveth_buf_desc {
-    u64 desc;  
+    u64 desc;
     struct ibmveth_buf_desc_fields fields;
 };
 
index 7c7aff1..a8a2d3d 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # 
-# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
+# Copyright(c) 1999 - 2006 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 
index c83271b..a83ef28 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -84,7 +84,12 @@ struct ixgb_adapter;
 #define IXGB_DBG(args...)
 #endif
 
-#define IXGB_ERR(args...) printk(KERN_ERR "ixgb: " args)
+#define PFX "ixgb: "
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+       (void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
+       printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
+               __FUNCTION__ , ## args))
+
 
 /* TX/RX descriptor defines */
 #define DEFAULT_TXD     256
@@ -175,6 +180,7 @@ struct ixgb_adapter {
        uint64_t hw_csum_tx_good;
        uint64_t hw_csum_tx_error;
        uint32_t tx_int_delay;
+       uint32_t tx_timeout_count;
        boolean_t tx_int_delay_enable;
        boolean_t detect_tx_hung;
 
@@ -192,7 +198,9 @@ struct ixgb_adapter {
 
        /* structs defined in ixgb_hw.h */
        struct ixgb_hw hw;
+       u16 msg_enable;
        struct ixgb_hw_stats stats;
+       uint32_t alloc_rx_buff_failed;
 #ifdef CONFIG_PCI_MSI
        boolean_t have_msi;
 #endif
index 661a46b..8357c55 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
index 5190aa8..bf6fa22 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
index d38ade5..cf19b89 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -44,6 +44,8 @@ extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
 extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
 extern void ixgb_update_stats(struct ixgb_adapter *adapter);
 
+#define IXGB_ALL_RAR_ENTRIES 16
+
 struct ixgb_stats {
        char stat_string[ETH_GSTRING_LEN];
        int sizeof_stat;
@@ -76,6 +78,7 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
        {"tx_heartbeat_errors", IXGB_STAT(net_stats.tx_heartbeat_errors)},
        {"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)},
        {"tx_deferred_ok", IXGB_STAT(stats.dc)},
+       {"tx_timeout_count", IXGB_STAT(tx_timeout_count) },
        {"rx_long_length_errors", IXGB_STAT(stats.roc)},
        {"rx_short_length_errors", IXGB_STAT(stats.ruc)},
 #ifdef NETIF_F_TSO
@@ -117,6 +120,16 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
        return 0;
 }
 
+static void ixgb_set_speed_duplex(struct net_device *netdev)
+{
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       /* be optimistic about our link, since we were up before */
+       adapter->link_speed = 10000;
+       adapter->link_duplex = FULL_DUPLEX;
+       netif_carrier_on(netdev);
+       netif_wake_queue(netdev);
+}
+
 static int
 ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
@@ -130,12 +143,7 @@ ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                ixgb_down(adapter, TRUE);
                ixgb_reset(adapter);
                ixgb_up(adapter);
-               /* be optimistic about our link, since we were up before */
-               adapter->link_speed = 10000;
-               adapter->link_duplex = FULL_DUPLEX;
-               netif_carrier_on(netdev);
-               netif_wake_queue(netdev);
-               
+               ixgb_set_speed_duplex(netdev);
        } else
                ixgb_reset(adapter);
 
@@ -183,11 +191,7 @@ ixgb_set_pauseparam(struct net_device *netdev,
        if(netif_running(adapter->netdev)) {
                ixgb_down(adapter, TRUE);
                ixgb_up(adapter);
-               /* be optimistic about our link, since we were up before */
-               adapter->link_speed = 10000;
-               adapter->link_duplex = FULL_DUPLEX;
-               netif_carrier_on(netdev);
-               netif_wake_queue(netdev);
+               ixgb_set_speed_duplex(netdev);
        } else
                ixgb_reset(adapter);
                
@@ -212,11 +216,7 @@ ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
        if(netif_running(netdev)) {
                ixgb_down(adapter,TRUE);
                ixgb_up(adapter);
-               /* be optimistic about our link, since we were up before */
-               adapter->link_speed = 10000;
-               adapter->link_duplex = FULL_DUPLEX;
-               netif_carrier_on(netdev);
-               netif_wake_queue(netdev);
+               ixgb_set_speed_duplex(netdev);
        } else
                ixgb_reset(adapter);
        return 0;
@@ -251,6 +251,19 @@ ixgb_set_tso(struct net_device *netdev, uint32_t data)
 } 
 #endif /* NETIF_F_TSO */
 
+static uint32_t
+ixgb_get_msglevel(struct net_device *netdev)
+{
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       return adapter->msg_enable;
+}
+
+static void
+ixgb_set_msglevel(struct net_device *netdev, uint32_t data)
+{
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       adapter->msg_enable = data;
+}
 #define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
 
 static int 
@@ -303,7 +316,7 @@ ixgb_get_regs(struct net_device *netdev,
        *reg++ = IXGB_READ_REG(hw, RXCSUM);     /*  20 */
 
        /* there are 16 RAR entries in hardware, we only use 3 */
-       for(i = 0; i < 16; i++) {
+       for(i = 0; i < IXGB_ALL_RAR_ENTRIES; i++) {
                *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
                *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
        }
@@ -593,11 +606,7 @@ ixgb_set_ringparam(struct net_device *netdev,
                adapter->tx_ring = tx_new;
                if((err = ixgb_up(adapter)))
                        return err;
-               /* be optimistic about our link, since we were up before */
-               adapter->link_speed = 10000;
-               adapter->link_duplex = FULL_DUPLEX;
-               netif_carrier_on(netdev);
-               netif_wake_queue(netdev);
+               ixgb_set_speed_duplex(netdev);
        }
 
        return 0;
@@ -714,6 +723,8 @@ static struct ethtool_ops ixgb_ethtool_ops = {
        .set_tx_csum = ixgb_set_tx_csum,
        .get_sg = ethtool_op_get_sg,
        .set_sg = ethtool_op_set_sg,
+       .get_msglevel = ixgb_get_msglevel,
+       .set_msglevel = ixgb_set_msglevel,
 #ifdef NETIF_F_TSO
        .get_tso = ethtool_op_get_tso,
        .set_tso = ixgb_set_tso,
index 620cad4..f7fa10e 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
index 382c630..cb45689 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -57,6 +57,7 @@ typedef enum {
 typedef enum {
        ixgb_media_type_unknown = 0,
        ixgb_media_type_fiber = 1,
+       ixgb_media_type_copper = 2,
        ixgb_num_media_types
 } ixgb_media_type;
 
index aee207e..40a085f 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -43,6 +43,8 @@
 #define IXGB_SUBDEVICE_ID_A11F      0xA11F   
 #define IXGB_SUBDEVICE_ID_A01F      0xA01F   
 
-#endif /* #ifndef _IXGB_IDS_H_ */
+#define IXGB_DEVICE_ID_82597EX_CX4   0x109E
+#define IXGB_SUBDEVICE_ID_A00C  0xA00C
 
+#endif /* #ifndef _IXGB_IDS_H_ */
 /* End of File */
index cfd67d8..57006fb 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
 
 #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.100-k2"DRIVERNAPI
+#define DRV_VERSION            "1.0.109-k2"DRIVERNAPI
 char ixgb_driver_version[] = DRV_VERSION;
-static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
 /* ixgb_pci_tbl - PCI Device ID Table
  *
@@ -67,6 +51,8 @@ static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 static struct pci_device_id ixgb_pci_tbl[] = {
        {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_CX4,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_LR,  
@@ -148,6 +134,11 @@ MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+#define DEFAULT_DEBUG_LEVEL_SHIFT 3
+static int debug = DEFAULT_DEBUG_LEVEL_SHIFT;
+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
@@ -196,7 +187,7 @@ module_exit(ixgb_exit_module);
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 ixgb_irq_disable(struct ixgb_adapter *adapter)
 {
        atomic_inc(&adapter->irq_sem);
@@ -210,7 +201,7 @@ ixgb_irq_disable(struct ixgb_adapter *adapter)
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 ixgb_irq_enable(struct ixgb_adapter *adapter)
 {
        if(atomic_dec_and_test(&adapter->irq_sem)) {
@@ -231,6 +222,7 @@ ixgb_up(struct ixgb_adapter *adapter)
 
        /* hardware has been reset, we need to reload some things */
 
+       ixgb_rar_set(hw, netdev->dev_addr, 0);
        ixgb_set_multi(netdev);
 
        ixgb_restore_vlan(adapter);
@@ -240,6 +232,9 @@ ixgb_up(struct ixgb_adapter *adapter)
        ixgb_configure_rx(adapter);
        ixgb_alloc_rx_buffers(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) & 
@@ -249,7 +244,7 @@ ixgb_up(struct ixgb_adapter *adapter)
        if (!pcix)
           adapter->have_msi = FALSE;
        else if((err = pci_enable_msi(adapter->pdev))) {
-               printk (KERN_ERR
+               DPRINTK(PROBE, ERR,
                 "Unable to allocate MSI interrupt Error: %d\n", err);
                adapter->have_msi = FALSE;
                /* proceed to try to request regular interrupt */
@@ -259,11 +254,11 @@ ixgb_up(struct ixgb_adapter *adapter)
 #endif
        if((err = request_irq(adapter->pdev->irq, &ixgb_intr,
                                  SA_SHIRQ | SA_SAMPLE_RANDOM,
-                                 netdev->name, netdev)))
+                                 netdev->name, netdev))) {
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate interrupt Error: %d\n", err);
                return err;
-
-       /* disable interrupts and get the hardware into a known state */
-       IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
+       }
 
        if((hw->max_frame_size != max_frame) ||
                (hw->max_frame_size !=
@@ -285,11 +280,12 @@ ixgb_up(struct ixgb_adapter *adapter)
        }
 
        mod_timer(&adapter->watchdog_timer, jiffies);
-       ixgb_irq_enable(adapter);
 
 #ifdef CONFIG_IXGB_NAPI
        netif_poll_enable(netdev);
 #endif
+       ixgb_irq_enable(adapter);
+
        return 0;
 }
 
@@ -326,7 +322,7 @@ ixgb_reset(struct ixgb_adapter *adapter)
 
        ixgb_adapter_stop(&adapter->hw);
        if(!ixgb_init_hw(&adapter->hw))
-               IXGB_DBG("ixgb_init_hw failed.\n");
+               DPRINTK(PROBE, ERR, "ixgb_init_hw failed.\n");
 }
 
 /**
@@ -363,7 +359,8 @@ ixgb_probe(struct pci_dev *pdev,
        } else {
                if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
                   (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
-                       IXGB_ERR("No usable DMA configuration, aborting\n");
+                       printk(KERN_ERR
+                        "ixgb: No usable DMA configuration, aborting\n");
                        goto err_dma_mask;
                }
                pci_using_dac = 0;
@@ -388,6 +385,7 @@ ixgb_probe(struct pci_dev *pdev,
        adapter->netdev = netdev;
        adapter->pdev = pdev;
        adapter->hw.back = adapter;
+       adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT);
 
        mmio_start = pci_resource_start(pdev, BAR_0);
        mmio_len = pci_resource_len(pdev, BAR_0);
@@ -416,7 +414,7 @@ ixgb_probe(struct pci_dev *pdev,
        netdev->change_mtu = &ixgb_change_mtu;
        ixgb_set_ethtool_ops(netdev);
        netdev->tx_timeout = &ixgb_tx_timeout;
-       netdev->watchdog_timeo = HZ;
+       netdev->watchdog_timeo = 5 * HZ;
 #ifdef CONFIG_IXGB_NAPI
        netdev->poll = &ixgb_clean;
        netdev->weight = 64;
@@ -428,6 +426,7 @@ ixgb_probe(struct pci_dev *pdev,
        netdev->poll_controller = ixgb_netpoll;
 #endif
 
+       strcpy(netdev->name, pci_name(pdev));
        netdev->mem_start = mmio_start;
        netdev->mem_end = mmio_start + mmio_len;
        netdev->base_addr = adapter->hw.io_base;
@@ -449,6 +448,9 @@ ixgb_probe(struct pci_dev *pdev,
 #ifdef NETIF_F_TSO
        netdev->features |= NETIF_F_TSO;
 #endif
+#ifdef NETIF_F_LLTX
+       netdev->features |= NETIF_F_LLTX;
+#endif
 
        if(pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
@@ -456,7 +458,7 @@ ixgb_probe(struct pci_dev *pdev,
        /* make sure the EEPROM is good */
 
        if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
-               printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n");
+               DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
                err = -EIO;
                goto err_eeprom;
        }
@@ -465,6 +467,7 @@ ixgb_probe(struct pci_dev *pdev,
        memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
 
        if(!is_valid_ether_addr(netdev->perm_addr)) {
+               DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
                err = -EIO;
                goto err_eeprom;
        }
@@ -478,6 +481,7 @@ ixgb_probe(struct pci_dev *pdev,
        INIT_WORK(&adapter->tx_timeout_task,
                  (void (*)(void *))ixgb_tx_timeout_task, netdev);
 
+       strcpy(netdev->name, "eth%d");
        if((err = register_netdev(netdev)))
                goto err_register;
 
@@ -486,8 +490,7 @@ ixgb_probe(struct pci_dev *pdev,
        netif_carrier_off(netdev);
        netif_stop_queue(netdev);
 
-       printk(KERN_INFO "%s: Intel(R) PRO/10GbE Network Connection\n",
-                  netdev->name);
+       DPRINTK(PROBE, INFO, "Intel(R) PRO/10GbE Network Connection\n");
        ixgb_check_options(adapter);
        /* reset the hardware with the new settings */
 
@@ -557,17 +560,17 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
        hw->subsystem_vendor_id = pdev->subsystem_vendor;
        hw->subsystem_id = pdev->subsystem_device;
 
-       adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
-
        hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+       adapter->rx_buffer_len = hw->max_frame_size;
 
        if((hw->device_id == IXGB_DEVICE_ID_82597EX)
-          ||(hw->device_id == IXGB_DEVICE_ID_82597EX_LR)
-          ||(hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
+          || (hw->device_id == IXGB_DEVICE_ID_82597EX_CX4)
+          || (hw->device_id == IXGB_DEVICE_ID_82597EX_LR)
+          || (hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
                        hw->mac_type = ixgb_82597;
        else {
                /* should never have loaded on this device */
-               printk(KERN_ERR "ixgb: unsupported device id\n");
+               DPRINTK(PROBE, ERR, "unsupported device id\n");
        }
 
        /* enable flow control to be programmed */
@@ -665,6 +668,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
        size = sizeof(struct ixgb_buffer) * txdr->count;
        txdr->buffer_info = vmalloc(size);
        if(!txdr->buffer_info) {
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate transmit descriptor ring memory\n");
                return -ENOMEM;
        }
        memset(txdr->buffer_info, 0, size);
@@ -677,6 +682,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
        txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
        if(!txdr->desc) {
                vfree(txdr->buffer_info);
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate transmit descriptor memory\n");
                return -ENOMEM;
        }
        memset(txdr->desc, 0, txdr->size);
@@ -750,6 +757,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
        size = sizeof(struct ixgb_buffer) * rxdr->count;
        rxdr->buffer_info = vmalloc(size);
        if(!rxdr->buffer_info) {
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate receive descriptor ring\n");
                return -ENOMEM;
        }
        memset(rxdr->buffer_info, 0, size);
@@ -763,6 +772,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
 
        if(!rxdr->desc) {
                vfree(rxdr->buffer_info);
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate receive descriptors\n");
                return -ENOMEM;
        }
        memset(rxdr->desc, 0, rxdr->size);
@@ -794,21 +805,14 @@ ixgb_setup_rctl(struct ixgb_adapter *adapter)
 
        rctl |= IXGB_RCTL_SECRC;
 
-       switch (adapter->rx_buffer_len) {
-       case IXGB_RXBUFFER_2048:
-       default:
+       if (adapter->rx_buffer_len <= IXGB_RXBUFFER_2048)
                rctl |= IXGB_RCTL_BSIZE_2048;
-               break;
-       case IXGB_RXBUFFER_4096:
+       else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_4096)
                rctl |= IXGB_RCTL_BSIZE_4096;
-               break;
-       case IXGB_RXBUFFER_8192:
+       else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_8192)
                rctl |= IXGB_RCTL_BSIZE_8192;
-               break;
-       case IXGB_RXBUFFER_16384:
+       else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_16384)
                rctl |= IXGB_RCTL_BSIZE_16384;
-               break;
-       }
 
        IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
 }
@@ -898,22 +902,25 @@ ixgb_free_tx_resources(struct ixgb_adapter *adapter)
        adapter->tx_ring.desc = NULL;
 }
 
-static inline void
+static void
 ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter,
                                        struct ixgb_buffer *buffer_info)
 {
        struct pci_dev *pdev = adapter->pdev;
-       if(buffer_info->dma) {
-               pci_unmap_page(pdev,
-                          buffer_info->dma,
-                          buffer_info->length,
-                          PCI_DMA_TODEVICE);
-               buffer_info->dma = 0;
-       }
-       if(buffer_info->skb) {
+
+       if (buffer_info->dma)
+               pci_unmap_page(pdev, buffer_info->dma, buffer_info->length,
+                              PCI_DMA_TODEVICE);
+
+       if (buffer_info->skb)
                dev_kfree_skb_any(buffer_info->skb);
-               buffer_info->skb = NULL;
-       }
+
+       buffer_info->skb = NULL;
+       buffer_info->dma = 0;
+       buffer_info->time_stamp = 0;
+       /* these fields must always be initialized in tx
+        * buffer_info->length = 0;
+        * buffer_info->next_to_watch = 0; */
 }
 
 /**
@@ -1112,8 +1119,8 @@ ixgb_watchdog(unsigned long data)
 
        if(adapter->hw.link_up) {
                if(!netif_carrier_ok(netdev)) {
-                       printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n",
-                                  netdev->name, 10000, "Full Duplex");
+                       DPRINTK(LINK, INFO,
+                               "NIC Link is Up 10000 Mbps Full Duplex\n");
                        adapter->link_speed = 10000;
                        adapter->link_duplex = FULL_DUPLEX;
                        netif_carrier_on(netdev);
@@ -1123,9 +1130,7 @@ ixgb_watchdog(unsigned long data)
                if(netif_carrier_ok(netdev)) {
                        adapter->link_speed = 0;
                        adapter->link_duplex = 0;
-                       printk(KERN_INFO
-                                  "ixgb: %s NIC Link is Down\n",
-                                  netdev->name);
+                       DPRINTK(LINK, INFO, "NIC Link is Down\n");
                        netif_carrier_off(netdev);
                        netif_stop_queue(netdev);
 
@@ -1158,7 +1163,7 @@ ixgb_watchdog(unsigned long data)
 #define IXGB_TX_FLAGS_VLAN             0x00000002
 #define IXGB_TX_FLAGS_TSO              0x00000004
 
-static inline int
+static int
 ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
 #ifdef NETIF_F_TSO
@@ -1220,7 +1225,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
        return 0;
 }
 
-static inline boolean_t
+static boolean_t
 ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
        struct ixgb_context_desc *context_desc;
@@ -1258,7 +1263,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
 #define IXGB_MAX_TXD_PWR       14
 #define IXGB_MAX_DATA_PER_TXD  (1<<IXGB_MAX_TXD_PWR)
 
-static inline int
+static int
 ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
            unsigned int first)
 {
@@ -1284,6 +1289,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
                                size,
                                PCI_DMA_TODEVICE);
                buffer_info->time_stamp = jiffies;
+               buffer_info->next_to_watch = 0;
 
                len -= size;
                offset += size;
@@ -1309,6 +1315,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
                                        size,
                                        PCI_DMA_TODEVICE);
                        buffer_info->time_stamp = jiffies;
+                       buffer_info->next_to_watch = 0;
 
                        len -= size;
                        offset += size;
@@ -1323,7 +1330,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
        return count;
 }
 
-static inline void
+static void
 ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
 {
        struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
@@ -1395,13 +1402,26 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                return 0;
        }
 
+#ifdef NETIF_F_LLTX
+       local_irq_save(flags);
+       if (!spin_trylock(&adapter->tx_lock)) {
+               /* Collision - tell upper layer to requeue */
+               local_irq_restore(flags);
+               return NETDEV_TX_LOCKED;
+       }
+#else
        spin_lock_irqsave(&adapter->tx_lock, flags);
+#endif
+
        if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
                netif_stop_queue(netdev);
                spin_unlock_irqrestore(&adapter->tx_lock, flags);
-               return 1;
+               return NETDEV_TX_BUSY;
        }
+
+#ifndef NETIF_F_LLTX
        spin_unlock_irqrestore(&adapter->tx_lock, flags);
+#endif
 
        if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
                tx_flags |= IXGB_TX_FLAGS_VLAN;
@@ -1413,10 +1433,13 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        tso = ixgb_tso(adapter, skb);
        if (tso < 0) {
                dev_kfree_skb_any(skb);
+#ifdef NETIF_F_LLTX
+               spin_unlock_irqrestore(&adapter->tx_lock, flags);
+#endif
                return NETDEV_TX_OK;
        }
 
-       if (tso)
+       if (likely(tso))
                tx_flags |= IXGB_TX_FLAGS_TSO;
        else if(ixgb_tx_csum(adapter, skb))
                tx_flags |= IXGB_TX_FLAGS_CSUM;
@@ -1426,7 +1449,15 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
        netdev->trans_start = jiffies;
 
-       return 0;
+#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);
+
+       spin_unlock_irqrestore(&adapter->tx_lock, flags);
+
+#endif
+       return NETDEV_TX_OK;
 }
 
 /**
@@ -1448,6 +1479,7 @@ ixgb_tx_timeout_task(struct net_device *netdev)
 {
        struct ixgb_adapter *adapter = netdev_priv(netdev);
 
+       adapter->tx_timeout_count++;
        ixgb_down(adapter, TRUE);
        ixgb_up(adapter);
 }
@@ -1486,28 +1518,15 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
 
        if((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
           || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
-               IXGB_ERR("Invalid MTU setting\n");
+               DPRINTK(PROBE, ERR, "Invalid MTU setting %d\n", new_mtu);
                return -EINVAL;
        }
 
-       if((max_frame <= IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
-          || (max_frame <= IXGB_RXBUFFER_2048)) {
-               adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
-
-       } else if(max_frame <= IXGB_RXBUFFER_4096) {
-               adapter->rx_buffer_len = IXGB_RXBUFFER_4096;
-
-       } else if(max_frame <= IXGB_RXBUFFER_8192) {
-               adapter->rx_buffer_len = IXGB_RXBUFFER_8192;
-
-       } else {
-               adapter->rx_buffer_len = IXGB_RXBUFFER_16384;
-       }
+       adapter->rx_buffer_len = max_frame;
 
        netdev->mtu = new_mtu;
 
-       if(old_max_frame != max_frame && netif_running(netdev)) {
-
+       if ((old_max_frame != max_frame) && netif_running(netdev)) {
                ixgb_down(adapter, TRUE);
                ixgb_up(adapter);
        }
@@ -1765,23 +1784,43 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
 
        tx_ring->next_to_clean = i;
 
-       spin_lock(&adapter->tx_lock);
-       if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
-          (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
-
-               netif_wake_queue(netdev);
+       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))
+                       netif_wake_queue(netdev);
+               spin_unlock(&adapter->tx_lock);
        }
-       spin_unlock(&adapter->tx_lock);
 
        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;
-               if(tx_ring->buffer_info[i].dma &&
-                  time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+               if (tx_ring->buffer_info[eop].dma &&
+                  time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ)
                   && !(IXGB_READ_REG(&adapter->hw, STATUS) &
-                       IXGB_STATUS_TXOFF))
+                       IXGB_STATUS_TXOFF)) {
+                       /* detected Tx unit hang */
+                       DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+                                       "  TDH                  <%x>\n"
+                                       "  TDT                  <%x>\n"
+                                       "  next_to_use          <%x>\n"
+                                       "  next_to_clean        <%x>\n"
+                                       "buffer_info[next_to_clean]\n"
+                                       "  time_stamp           <%lx>\n"
+                                       "  next_to_watch        <%x>\n"
+                                       "  jiffies              <%lx>\n"
+                                       "  next_to_watch.status <%x>\n",
+                               IXGB_READ_REG(&adapter->hw, TDH),
+                               IXGB_READ_REG(&adapter->hw, TDT),
+                               tx_ring->next_to_use,
+                               tx_ring->next_to_clean,
+                               tx_ring->buffer_info[eop].time_stamp,
+                               eop,
+                               jiffies,
+                               eop_desc->status);
                        netif_stop_queue(netdev);
+               }
        }
 
        return cleaned;
@@ -1794,7 +1833,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
  * @sk_buff: socket buffer with received data
  **/
 
-static inline void
+static void
 ixgb_rx_checksum(struct ixgb_adapter *adapter,
                 struct ixgb_rx_desc *rx_desc,
                 struct sk_buff *skb)
@@ -1858,6 +1897,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
 #endif
                status = rx_desc->status;
                skb = buffer_info->skb;
+               buffer_info->skb = NULL;
 
                prefetch(skb->data);
 
@@ -1902,6 +1942,26 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
                        goto rxdesc_done;
                }
 
+               /* code added for copybreak, this should improve
+                * performance for small packets with large amounts
+                * of reassembly being done in the stack */
+#define IXGB_CB_LENGTH 256
+               if (length < IXGB_CB_LENGTH) {
+                       struct sk_buff *new_skb =
+                           dev_alloc_skb(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);
+                               /* save the skb in buffer_info as good */
+                               buffer_info->skb = skb;
+                               skb = new_skb;
+                       }
+               }
+               /* end copybreak code */
+
                /* Good Receive */
                skb_put(skb, length);
 
@@ -1931,7 +1991,6 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
 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;
@@ -1971,12 +2030,18 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
 
        /* 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);
+               /* recycle! its good for you */
+               if (!(skb = buffer_info->skb))
+                       skb = dev_alloc_skb(adapter->rx_buffer_len
+                                           + NET_IP_ALIGN);
+               else {
+                       skb_trim(skb, 0);
+                       goto map_skb;
+               }
 
-               if(unlikely(!skb)) {
+               if (unlikely(!skb)) {
                        /* Better luck next round */
+                       adapter->alloc_rx_buff_failed++;
                        break;
                }
 
@@ -1990,33 +2055,36 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
 
                buffer_info->skb = skb;
                buffer_info->length = adapter->rx_buffer_len;
-               buffer_info->dma =
-                       pci_map_single(pdev,
-                                  skb->data,
-                                  adapter->rx_buffer_len,
-                                  PCI_DMA_FROMDEVICE);
+map_skb:
+               buffer_info->dma = pci_map_single(pdev,
+                                                 skb->data,
+                                                 adapter->rx_buffer_len,
+                                                 PCI_DMA_FROMDEVICE);
 
+               rx_desc = IXGB_RX_DESC(*rx_ring, i);
                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
-                        * know there are new descriptors to fetch.  (Only
-                        * applicable for weak-ordered memory model archs,
-                        * such as IA-64). */
-                       wmb();
-
-                       IXGB_WRITE_REG(&adapter->hw, RDT, i);
-               }
 
                if(++i == rx_ring->count) i = 0;
                buffer_info = &rx_ring->buffer_info[i];
        }
 
-       rx_ring->next_to_use = i;
+       if (likely(rx_ring->next_to_use != i)) {
+               rx_ring->next_to_use = i;
+               if (unlikely(i-- == 0))
+                       i = (rx_ring->count - 1);
+
+               /* Force memory writes to complete before letting h/w
+                * know there are new descriptors to fetch.  (Only
+                * applicable for weak-ordered memory model archs, such
+                * as IA-64). */
+               wmb();
+               IXGB_WRITE_REG(&adapter->hw, RDT, i);
+       }
 }
 
 /**
index dba2048..ee982fe 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
index 8a83dfd..39fbed2 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 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 
@@ -76,7 +76,7 @@ IXGB_PARAM(RxDescriptors, "Number of receive descriptors");
  *  - 2 - Tx only, generate PAUSE frames but ignore them on receive
  *  - 3 - Full Flow Control Support
  *
- * Default Value: Read flow control settings from the EEPROM
+ * Default Value: 2 - Tx only (silicon bug avoidance)
  */
 
 IXGB_PARAM(FlowControl, "Flow Control setting");
@@ -137,7 +137,7 @@ IXGB_PARAM(RxFCLowThresh, "Receive Flow Control Low Threshold");
  *
  * Valid Range: 1 - 65535 
  *
- * Default Value:  256 (0x100)
+ * Default Value:  65535 (0xffff) (we'll send an xon if we recover)
  */
 
 IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout");
@@ -165,8 +165,6 @@ IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
 
 #define XSUMRX_DEFAULT          OPTION_ENABLED
 
-#define FLOW_CONTROL_FULL         ixgb_fc_full
-#define FLOW_CONTROL_DEFAULT  FLOW_CONTROL_FULL
 #define DEFAULT_FCRTL                  0x28000
 #define DEFAULT_FCRTH                  0x30000
 #define MIN_FCRTL                            0
@@ -174,9 +172,9 @@ IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
 #define MIN_FCRTH                            8
 #define MAX_FCRTH                      0x3FFF0
 
-#define DEFAULT_FCPAUSE                        0x100   /* this may be too long */
 #define MIN_FCPAUSE                          1
 #define MAX_FCPAUSE                     0xffff
+#define DEFAULT_FCPAUSE                         0xFFFF /* this may be too long */
 
 struct ixgb_option {
        enum { enable_option, range_option, list_option } type;
@@ -336,7 +334,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
                        .type = list_option,
                        .name = "Flow Control",
                        .err  = "reading default settings from EEPROM",
-                       .def  = ixgb_fc_full,
+                       .def  = ixgb_fc_tx_pause,
                        .arg  = { .l = { .nr = LIST_LEN(fc_list),
                                         .p = fc_list }}
                };
@@ -365,8 +363,8 @@ ixgb_check_options(struct ixgb_adapter *adapter)
                } else {
                        adapter->hw.fc.high_water = opt.def;
                }
-               if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
-                       printk (KERN_INFO 
+               if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
+                       printk (KERN_INFO
                                "Ignoring RxFCHighThresh when no RxFC\n");
        }
        { /* Receive Flow Control Low Threshold */
@@ -385,8 +383,8 @@ ixgb_check_options(struct ixgb_adapter *adapter)
                } else {
                        adapter->hw.fc.low_water = opt.def;
                }
-               if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
-                       printk (KERN_INFO 
+               if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
+                       printk (KERN_INFO
                                "Ignoring RxFCLowThresh when no RxFC\n");
        }
        { /* Flow Control Pause Time Request*/
@@ -406,12 +404,12 @@ ixgb_check_options(struct ixgb_adapter *adapter)
                } else {
                        adapter->hw.fc.pause_time = opt.def;
                }
-               if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
-                       printk (KERN_INFO 
+               if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
+                       printk (KERN_INFO
                                "Ignoring FCReqTimeout when no RxFC\n");
        }
        /* high low and spacing check for rx flow control thresholds */
-       if (adapter->hw.fc.type & ixgb_fc_rx_pause) {
+       if (adapter->hw.fc.type & ixgb_fc_tx_pause) {
                /* high must be greater than low */
                if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
                        /* set defaults */
diff --git a/drivers/net/myri10ge/Makefile b/drivers/net/myri10ge/Makefile
new file mode 100644 (file)
index 0000000..5df8916
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Myricom Myri-10G ethernet driver
+#
+
+obj-$(CONFIG_MYRI10GE) += myri10ge.o
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
new file mode 100644 (file)
index 0000000..87933cb
--- /dev/null
@@ -0,0 +1,2851 @@
+/*************************************************************************
+ * myri10ge.c: Myricom Myri-10G Ethernet driver.
+ *
+ * Copyright (C) 2005, 2006 Myricom, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Myricom, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * If the eeprom on your board is not recent enough, you will need to get a
+ * newer firmware image at:
+ *   http://www.myri.com/scs/download-Myri10GE.html
+ *
+ * Contact Information:
+ *   <help@myri.com>
+ *   Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006
+ *************************************************************************/
+
+#include <linux/tcp.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/inet.h>
+#include <linux/in.h>
+#include <linux/ethtool.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/timer.h>
+#include <linux/vmalloc.h>
+#include <linux/crc32.h>
+#include <linux/moduleparam.h>
+#include <linux/io.h>
+#include <net/checksum.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "myri10ge_mcp.h"
+#include "myri10ge_mcp_gen_header.h"
+
+#define MYRI10GE_VERSION_STR "0.9.0"
+
+MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
+MODULE_AUTHOR("Maintainer: help@myri.com");
+MODULE_VERSION(MYRI10GE_VERSION_STR);
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define MYRI10GE_MAX_ETHER_MTU 9014
+
+#define MYRI10GE_ETH_STOPPED 0
+#define MYRI10GE_ETH_STOPPING 1
+#define MYRI10GE_ETH_STARTING 2
+#define MYRI10GE_ETH_RUNNING 3
+#define MYRI10GE_ETH_OPEN_FAILED 4
+
+#define MYRI10GE_EEPROM_STRINGS_SIZE 256
+#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
+
+#define MYRI10GE_NO_CONFIRM_DATA 0xffffffff
+#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
+
+struct myri10ge_rx_buffer_state {
+       struct sk_buff *skb;
+        DECLARE_PCI_UNMAP_ADDR(bus)
+        DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_tx_buffer_state {
+       struct sk_buff *skb;
+       int last;
+        DECLARE_PCI_UNMAP_ADDR(bus)
+        DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_cmd {
+       u32 data0;
+       u32 data1;
+       u32 data2;
+};
+
+struct myri10ge_rx_buf {
+       struct mcp_kreq_ether_recv __iomem *lanai;      /* lanai ptr for recv ring */
+       u8 __iomem *wc_fifo;    /* w/c rx dma addr fifo address */
+       struct mcp_kreq_ether_recv *shadow;     /* host shadow of recv ring */
+       struct myri10ge_rx_buffer_state *info;
+       int cnt;
+       int alloc_fail;
+       int mask;               /* number of rx slots -1 */
+};
+
+struct myri10ge_tx_buf {
+       struct mcp_kreq_ether_send __iomem *lanai;      /* lanai ptr for sendq */
+       u8 __iomem *wc_fifo;    /* w/c send fifo address */
+       struct mcp_kreq_ether_send *req_list;   /* host shadow of sendq */
+       char *req_bytes;
+       struct myri10ge_tx_buffer_state *info;
+       int mask;               /* number of transmit slots -1  */
+       int boundary;           /* boundary transmits cannot cross */
+       int req ____cacheline_aligned;  /* transmit slots submitted     */
+       int pkt_start;          /* packets started */
+       int done ____cacheline_aligned; /* transmit slots completed     */
+       int pkt_done;           /* packets completed */
+};
+
+struct myri10ge_rx_done {
+       struct mcp_slot *entry;
+       dma_addr_t bus;
+       int cnt;
+       int idx;
+};
+
+struct myri10ge_priv {
+       int running;            /* running?             */
+       int csum_flag;          /* rx_csums?            */
+       struct myri10ge_tx_buf tx;      /* transmit ring        */
+       struct myri10ge_rx_buf rx_small;
+       struct myri10ge_rx_buf rx_big;
+       struct myri10ge_rx_done rx_done;
+       int small_bytes;
+       struct net_device *dev;
+       struct net_device_stats stats;
+       u8 __iomem *sram;
+       int sram_size;
+       unsigned long board_span;
+       unsigned long iomem_base;
+       u32 __iomem *irq_claim;
+       u32 __iomem *irq_deassert;
+       char *mac_addr_string;
+       struct mcp_cmd_response *cmd;
+       dma_addr_t cmd_bus;
+       struct mcp_irq_data *fw_stats;
+       dma_addr_t fw_stats_bus;
+       struct pci_dev *pdev;
+       int msi_enabled;
+       unsigned int link_state;
+       unsigned int rdma_tags_available;
+       int intr_coal_delay;
+       u32 __iomem *intr_coal_delay_ptr;
+       int mtrr;
+       int wake_queue;
+       int stop_queue;
+       int down_cnt;
+       wait_queue_head_t down_wq;
+       struct work_struct watchdog_work;
+       struct timer_list watchdog_timer;
+       int watchdog_tx_done;
+       int watchdog_resets;
+       int tx_linearized;
+       int pause;
+       char *fw_name;
+       char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE];
+       char fw_version[128];
+       u8 mac_addr[6];         /* eeprom mac address */
+       unsigned long serial_number;
+       int vendor_specific_offset;
+       u32 devctl;
+       u16 msi_flags;
+       u32 pm_state[16];
+       u32 read_dma;
+       u32 write_dma;
+       u32 read_write_dma;
+};
+
+static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
+static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat";
+
+static char *myri10ge_fw_name = NULL;
+module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name\n");
+
+static int myri10ge_ecrc_enable = 1;
+module_param(myri10ge_ecrc_enable, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E\n");
+
+static int myri10ge_max_intr_slots = 1024;
+module_param(myri10ge_max_intr_slots, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots\n");
+
+static int myri10ge_small_bytes = -1;  /* -1 == auto */
+module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets\n");
+
+static int myri10ge_msi = 1;   /* enable msi by default */
+module_param(myri10ge_msi, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n");
+
+static int myri10ge_intr_coal_delay = 25;
+module_param(myri10ge_intr_coal_delay, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n");
+
+static int myri10ge_flow_control = 1;
+module_param(myri10ge_flow_control, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_flow_control, "Pause parameter\n");
+
+static int myri10ge_deassert_wait = 1;
+module_param(myri10ge_deassert_wait, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_deassert_wait,
+                "Wait when deasserting legacy interrupts\n");
+
+static int myri10ge_force_firmware = 0;
+module_param(myri10ge_force_firmware, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_force_firmware,
+                "Force firmware to assume aligned completions\n");
+
+static int myri10ge_skb_cross_4k = 0;
+module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_skb_cross_4k,
+                "Can a small skb cross a 4KB boundary?\n");
+
+static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
+module_param(myri10ge_initial_mtu, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n");
+
+static int myri10ge_napi_weight = 64;
+module_param(myri10ge_napi_weight, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_napi_weight, "Set NAPI weight\n");
+
+static int myri10ge_watchdog_timeout = 1;
+module_param(myri10ge_watchdog_timeout, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_watchdog_timeout, "Set watchdog timeout\n");
+
+static int myri10ge_max_irq_loops = 1048576;
+module_param(myri10ge_max_irq_loops, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_max_irq_loops,
+                "Set stuck legacy IRQ detection threshold\n");
+
+#define MYRI10GE_FW_OFFSET 1024*1024
+#define MYRI10GE_HIGHPART_TO_U32(X) \
+(sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
+#define MYRI10GE_LOWPART_TO_U32(X) ((u32)(X))
+
+#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
+
+static int
+myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
+                 struct myri10ge_cmd *data, int atomic)
+{
+       struct mcp_cmd *buf;
+       char buf_bytes[sizeof(*buf) + 8];
+       struct mcp_cmd_response *response = mgp->cmd;
+       char __iomem *cmd_addr = mgp->sram + MXGEFW_CMD_OFFSET;
+       u32 dma_low, dma_high, result, value;
+       int sleep_total = 0;
+
+       /* ensure buf is aligned to 8 bytes */
+       buf = (struct mcp_cmd *)ALIGN((unsigned long)buf_bytes, 8);
+
+       buf->data0 = htonl(data->data0);
+       buf->data1 = htonl(data->data1);
+       buf->data2 = htonl(data->data2);
+       buf->cmd = htonl(cmd);
+       dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+       dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+       buf->response_addr.low = htonl(dma_low);
+       buf->response_addr.high = htonl(dma_high);
+       response->result = MYRI10GE_NO_RESPONSE_RESULT;
+       mb();
+       myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf));
+
+       /* wait up to 15ms. Longest command is the DMA benchmark,
+        * which is capped at 5ms, but runs from a timeout handler
+        * that runs every 7.8ms. So a 15ms timeout leaves us with
+        * a 2.2ms margin
+        */
+       if (atomic) {
+               /* if atomic is set, do not sleep,
+                * and try to get the completion quickly
+                * (1ms will be enough for those commands) */
+               for (sleep_total = 0;
+                    sleep_total < 1000
+                    && response->result == MYRI10GE_NO_RESPONSE_RESULT;
+                    sleep_total += 10)
+                       udelay(10);
+       } else {
+               /* use msleep for most command */
+               for (sleep_total = 0;
+                    sleep_total < 15
+                    && response->result == MYRI10GE_NO_RESPONSE_RESULT;
+                    sleep_total++)
+                       msleep(1);
+       }
+
+       result = ntohl(response->result);
+       value = ntohl(response->data);
+       if (result != MYRI10GE_NO_RESPONSE_RESULT) {
+               if (result == 0) {
+                       data->data0 = value;
+                       return 0;
+               } else {
+                       dev_err(&mgp->pdev->dev,
+                               "command %d failed, result = %d\n",
+                               cmd, result);
+                       return -ENXIO;
+               }
+       }
+
+       dev_err(&mgp->pdev->dev, "command %d timed out, result = %d\n",
+               cmd, result);
+       return -EAGAIN;
+}
+
+/*
+ * The eeprom strings on the lanaiX have the format
+ * SN=x\0
+ * MAC=x:x:x:x:x:x\0
+ * PT:ddd mmm xx xx:xx:xx xx\0
+ * PV:ddd mmm xx xx:xx:xx xx\0
+ */
+static int myri10ge_read_mac_addr(struct myri10ge_priv *mgp)
+{
+       char *ptr, *limit;
+       int i;
+
+       ptr = mgp->eeprom_strings;
+       limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE;
+
+       while (*ptr != '\0' && ptr < limit) {
+               if (memcmp(ptr, "MAC=", 4) == 0) {
+                       ptr += 4;
+                       mgp->mac_addr_string = ptr;
+                       for (i = 0; i < 6; i++) {
+                               if ((ptr + 2) > limit)
+                                       goto abort;
+                               mgp->mac_addr[i] =
+                                   simple_strtoul(ptr, &ptr, 16);
+                               ptr += 1;
+                       }
+               }
+               if (memcmp((const void *)ptr, "SN=", 3) == 0) {
+                       ptr += 3;
+                       mgp->serial_number = simple_strtoul(ptr, &ptr, 10);
+               }
+               while (ptr < limit && *ptr++) ;
+       }
+
+       return 0;
+
+abort:
+       dev_err(&mgp->pdev->dev, "failed to parse eeprom_strings\n");
+       return -ENXIO;
+}
+
+/*
+ * Enable or disable periodic RDMAs from the host to make certain
+ * chipsets resend dropped PCIe messages
+ */
+
+static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
+{
+       char __iomem *submit;
+       u32 buf[16];
+       u32 dma_low, dma_high;
+       int i;
+
+       /* clear confirmation addr */
+       mgp->cmd->data = 0;
+       mb();
+
+       /* send a rdma command to the PCIe engine, and wait for the
+        * response in the confirmation address.  The firmware should
+        * write a -1 there to indicate it is alive and well
+        */
+       dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+       dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+       buf[0] = htonl(dma_high);       /* confirm addr MSW */
+       buf[1] = htonl(dma_low);        /* confirm addr LSW */
+       buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);       /* confirm data */
+       buf[3] = htonl(dma_high);       /* dummy addr MSW */
+       buf[4] = htonl(dma_low);        /* dummy addr LSW */
+       buf[5] = htonl(enable); /* enable? */
+
+       submit = mgp->sram + 0xfc01c0;
+
+       myri10ge_pio_copy(submit, &buf, sizeof(buf));
+       for (i = 0; mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20; i++)
+               msleep(1);
+       if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA)
+               dev_err(&mgp->pdev->dev, "dummy rdma %s failed\n",
+                       (enable ? "enable" : "disable"));
+}
+
+static int
+myri10ge_validate_firmware(struct myri10ge_priv *mgp,
+                          struct mcp_gen_header *hdr)
+{
+       struct device *dev = &mgp->pdev->dev;
+       int major, minor;
+
+       /* check firmware type */
+       if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) {
+               dev_err(dev, "Bad firmware type: 0x%x\n", ntohl(hdr->mcp_type));
+               return -EINVAL;
+       }
+
+       /* save firmware version for ethtool */
+       strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
+
+       sscanf(mgp->fw_version, "%d.%d", &major, &minor);
+
+       if (!(major == MXGEFW_VERSION_MAJOR && minor == MXGEFW_VERSION_MINOR)) {
+               dev_err(dev, "Found firmware version %s\n", mgp->fw_version);
+               dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR,
+                       MXGEFW_VERSION_MINOR);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size)
+{
+       unsigned crc, reread_crc;
+       const struct firmware *fw;
+       struct device *dev = &mgp->pdev->dev;
+       struct mcp_gen_header *hdr;
+       size_t hdr_offset;
+       int status;
+
+       if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) {
+               dev_err(dev, "Unable to load %s firmware image via hotplug\n",
+                       mgp->fw_name);
+               status = -EINVAL;
+               goto abort_with_nothing;
+       }
+
+       /* check size */
+
+       if (fw->size >= mgp->sram_size - MYRI10GE_FW_OFFSET ||
+           fw->size < MCP_HEADER_PTR_OFFSET + 4) {
+               dev_err(dev, "Firmware size invalid:%d\n", (int)fw->size);
+               status = -EINVAL;
+               goto abort_with_fw;
+       }
+
+       /* check id */
+       hdr_offset = ntohl(*(u32 *) (fw->data + MCP_HEADER_PTR_OFFSET));
+       if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) {
+               dev_err(dev, "Bad firmware file\n");
+               status = -EINVAL;
+               goto abort_with_fw;
+       }
+       hdr = (void *)(fw->data + hdr_offset);
+
+       status = myri10ge_validate_firmware(mgp, hdr);
+       if (status != 0)
+               goto abort_with_fw;
+
+       crc = crc32(~0, fw->data, fw->size);
+       memcpy_toio(mgp->sram + MYRI10GE_FW_OFFSET, fw->data, fw->size);
+       /* corruption checking is good for parity recovery and buggy chipset */
+       memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
+       reread_crc = crc32(~0, fw->data, fw->size);
+       if (crc != reread_crc) {
+               dev_err(dev, "CRC failed(fw-len=%u), got 0x%x (expect 0x%x)\n",
+                       (unsigned)fw->size, reread_crc, crc);
+               status = -EIO;
+               goto abort_with_fw;
+       }
+       *size = (u32) fw->size;
+
+abort_with_fw:
+       release_firmware(fw);
+
+abort_with_nothing:
+       return status;
+}
+
+static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
+{
+       struct mcp_gen_header *hdr;
+       struct device *dev = &mgp->pdev->dev;
+       const size_t bytes = sizeof(struct mcp_gen_header);
+       size_t hdr_offset;
+       int status;
+
+       /* find running firmware header */
+       hdr_offset = ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET));
+
+       if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > mgp->sram_size) {
+               dev_err(dev, "Running firmware has bad header offset (%d)\n",
+                       (int)hdr_offset);
+               return -EIO;
+       }
+
+       /* copy header of running firmware from SRAM to host memory to
+        * validate firmware */
+       hdr = kmalloc(bytes, GFP_KERNEL);
+       if (hdr == NULL) {
+               dev_err(dev, "could not malloc firmware hdr\n");
+               return -ENOMEM;
+       }
+       memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes);
+       status = myri10ge_validate_firmware(mgp, hdr);
+       kfree(hdr);
+       return status;
+}
+
+static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
+{
+       char __iomem *submit;
+       u32 buf[16];
+       u32 dma_low, dma_high, size;
+       int status, i;
+
+       status = myri10ge_load_hotplug_firmware(mgp, &size);
+       if (status) {
+               dev_warn(&mgp->pdev->dev, "hotplug firmware loading failed\n");
+
+               /* Do not attempt to adopt firmware if there
+                * was a bad crc */
+               if (status == -EIO)
+                       return status;
+
+               status = myri10ge_adopt_running_firmware(mgp);
+               if (status != 0) {
+                       dev_err(&mgp->pdev->dev,
+                               "failed to adopt running firmware\n");
+                       return status;
+               }
+               dev_info(&mgp->pdev->dev,
+                        "Successfully adopted running firmware\n");
+               if (mgp->tx.boundary == 4096) {
+                       dev_warn(&mgp->pdev->dev,
+                                "Using firmware currently running on NIC"
+                                ".  For optimal\n");
+                       dev_warn(&mgp->pdev->dev,
+                                "performance consider loading optimized "
+                                "firmware\n");
+                       dev_warn(&mgp->pdev->dev, "via hotplug\n");
+               }
+
+               mgp->fw_name = "adopted";
+               mgp->tx.boundary = 2048;
+               return status;
+       }
+
+       /* clear confirmation addr */
+       mgp->cmd->data = 0;
+       mb();
+
+       /* send a reload command to the bootstrap MCP, and wait for the
+        *  response in the confirmation address.  The firmware should
+        * write a -1 there to indicate it is alive and well
+        */
+       dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+       dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+       buf[0] = htonl(dma_high);       /* confirm addr MSW */
+       buf[1] = htonl(dma_low);        /* confirm addr LSW */
+       buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);       /* confirm data */
+
+       /* FIX: All newest firmware should un-protect the bottom of
+        * the sram before handoff. However, the very first interfaces
+        * do not. Therefore the handoff copy must skip the first 8 bytes
+        */
+       buf[3] = htonl(MYRI10GE_FW_OFFSET + 8); /* where the code starts */
+       buf[4] = htonl(size - 8);       /* length of code */
+       buf[5] = htonl(8);      /* where to copy to */
+       buf[6] = htonl(0);      /* where to jump to */
+
+       submit = mgp->sram + 0xfc0000;
+
+       myri10ge_pio_copy(submit, &buf, sizeof(buf));
+       mb();
+       msleep(1);
+       mb();
+       i = 0;
+       while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20) {
+               msleep(1);
+               i++;
+       }
+       if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) {
+               dev_err(&mgp->pdev->dev, "handoff failed\n");
+               return -ENXIO;
+       }
+       dev_info(&mgp->pdev->dev, "handoff confirmed\n");
+       myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096);
+
+       return 0;
+}
+
+static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr)
+{
+       struct myri10ge_cmd cmd;
+       int status;
+
+       cmd.data0 = ((addr[0] << 24) | (addr[1] << 16)
+                    | (addr[2] << 8) | addr[3]);
+
+       cmd.data1 = ((addr[4] << 8) | (addr[5]));
+
+       status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd, 0);
+       return status;
+}
+
+static int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause)
+{
+       struct myri10ge_cmd cmd;
+       int status, ctl;
+
+       ctl = pause ? MXGEFW_ENABLE_FLOW_CONTROL : MXGEFW_DISABLE_FLOW_CONTROL;
+       status = myri10ge_send_cmd(mgp, ctl, &cmd, 0);
+
+       if (status) {
+               printk(KERN_ERR
+                      "myri10ge: %s: Failed to set flow control mode\n",
+                      mgp->dev->name);
+               return status;
+       }
+       mgp->pause = pause;
+       return 0;
+}
+
+static void
+myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc, int atomic)
+{
+       struct myri10ge_cmd cmd;
+       int status, ctl;
+
+       ctl = promisc ? MXGEFW_ENABLE_PROMISC : MXGEFW_DISABLE_PROMISC;
+       status = myri10ge_send_cmd(mgp, ctl, &cmd, atomic);
+       if (status)
+               printk(KERN_ERR "myri10ge: %s: Failed to set promisc mode\n",
+                      mgp->dev->name);
+}
+
+static int myri10ge_reset(struct myri10ge_priv *mgp)
+{
+       struct myri10ge_cmd cmd;
+       int status;
+       size_t bytes;
+       u32 len;
+
+       /* try to send a reset command to the card to see if it
+        * is alive */
+       memset(&cmd, 0, sizeof(cmd));
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd, 0);
+       if (status != 0) {
+               dev_err(&mgp->pdev->dev, "failed reset\n");
+               return -ENXIO;
+       }
+
+       /* Now exchange information about interrupts  */
+
+       bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+       memset(mgp->rx_done.entry, 0, bytes);
+       cmd.data0 = (u32) bytes;
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, &cmd, 0);
+
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
+       mgp->irq_claim = (__iomem u32 *) (mgp->sram + cmd.data0);
+       if (!mgp->msi_enabled) {
+               status |= myri10ge_send_cmd
+                   (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0);
+               mgp->irq_deassert = (__iomem u32 *) (mgp->sram + cmd.data0);
+
+       }
+       status |= myri10ge_send_cmd
+           (mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0);
+       mgp->intr_coal_delay_ptr = (__iomem u32 *) (mgp->sram + cmd.data0);
+       if (status != 0) {
+               dev_err(&mgp->pdev->dev, "failed set interrupt parameters\n");
+               return status;
+       }
+       __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
+
+       /* Run a small DMA test.
+        * The magic multipliers to the length tell the firmware
+        * to do DMA read, write, or read+write tests.  The
+        * results are returned in cmd.data0.  The upper 16
+        * bits or the return is the number of transfers completed.
+        * The lower 16 bits is the time in 0.5us ticks that the
+        * transfers took to complete.
+        */
+
+       len = mgp->tx.boundary;
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data2 = len * 0x10000;
+       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+       if (status == 0)
+               mgp->read_dma = ((cmd.data0 >> 16) * len * 2) /
+                   (cmd.data0 & 0xffff);
+       else
+               dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n",
+                        status);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data2 = len * 0x1;
+       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+       if (status == 0)
+               mgp->write_dma = ((cmd.data0 >> 16) * len * 2) /
+                   (cmd.data0 & 0xffff);
+       else
+               dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n",
+                        status);
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data2 = len * 0x10001;
+       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+       if (status == 0)
+               mgp->read_write_dma = ((cmd.data0 >> 16) * len * 2 * 2) /
+                   (cmd.data0 & 0xffff);
+       else
+               dev_warn(&mgp->pdev->dev,
+                        "DMA read/write benchmark failed: %d\n", status);
+
+       memset(mgp->rx_done.entry, 0, bytes);
+
+       /* reset mcp/driver shared state back to 0 */
+       mgp->tx.req = 0;
+       mgp->tx.done = 0;
+       mgp->tx.pkt_start = 0;
+       mgp->tx.pkt_done = 0;
+       mgp->rx_big.cnt = 0;
+       mgp->rx_small.cnt = 0;
+       mgp->rx_done.idx = 0;
+       mgp->rx_done.cnt = 0;
+       status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr);
+       myri10ge_change_promisc(mgp, 0, 0);
+       myri10ge_change_pause(mgp, mgp->pause);
+       return status;
+}
+
+static inline void
+myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
+                   struct mcp_kreq_ether_recv *src)
+{
+       u32 low;
+
+       low = src->addr_low;
+       src->addr_low = DMA_32BIT_MASK;
+       myri10ge_pio_copy(dst, src, 8 * sizeof(*src));
+       mb();
+       src->addr_low = low;
+       __raw_writel(low, &dst->addr_low);
+       mb();
+}
+
+/*
+ * Set of routunes to get a new receive buffer.  Any buffer which
+ * crosses a 4KB boundary must start on a 4KB boundary due to PCIe
+ * wdma restrictions. We also try to align any smaller allocation to
+ * at least a 16 byte boundary for efficiency.  We assume the linux
+ * memory allocator works by powers of 2, and will not return memory
+ * smaller than 2KB which crosses a 4KB boundary.  If it does, we fall
+ * back to allocating 2x as much space as required.
+ *
+ * We intend to replace large (>4KB) skb allocations by using
+ * pages directly and building a fraglist in the near future.
+ */
+
+static inline struct sk_buff *myri10ge_alloc_big(int bytes)
+{
+       struct sk_buff *skb;
+       unsigned long data, roundup;
+
+       skb = dev_alloc_skb(bytes + 4096 + MXGEFW_PAD);
+       if (skb == NULL)
+               return NULL;
+
+       /* Correct skb->truesize so that socket buffer
+        * accounting is not confused the rounding we must
+        * do to satisfy alignment constraints.
+        */
+       skb->truesize -= 4096;
+
+       data = (unsigned long)(skb->data);
+       roundup = (-data) & (4095);
+       skb_reserve(skb, roundup);
+       return skb;
+}
+
+/* Allocate 2x as much space as required and use whichever portion
+ * does not cross a 4KB boundary */
+static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes)
+{
+       struct sk_buff *skb;
+       unsigned long data, boundary;
+
+       skb = dev_alloc_skb(2 * (bytes + MXGEFW_PAD) - 1);
+       if (unlikely(skb == NULL))
+               return NULL;
+
+       /* Correct skb->truesize so that socket buffer
+        * accounting is not confused the rounding we must
+        * do to satisfy alignment constraints.
+        */
+       skb->truesize -= bytes + MXGEFW_PAD;
+
+       data = (unsigned long)(skb->data);
+       boundary = (data + 4095UL) & ~4095UL;
+       if ((boundary - data) >= (bytes + MXGEFW_PAD))
+               return skb;
+
+       skb_reserve(skb, boundary - data);
+       return skb;
+}
+
+/* Allocate just enough space, and verify that the allocated
+ * space does not cross a 4KB boundary */
+static inline struct sk_buff *myri10ge_alloc_small(int bytes)
+{
+       struct sk_buff *skb;
+       unsigned long roundup, data, end;
+
+       skb = dev_alloc_skb(bytes + 16 + MXGEFW_PAD);
+       if (unlikely(skb == NULL))
+               return NULL;
+
+       /* Round allocated buffer to 16 byte boundary */
+       data = (unsigned long)(skb->data);
+       roundup = (-data) & 15UL;
+       skb_reserve(skb, roundup);
+       /* Verify that the data buffer does not cross a page boundary */
+       data = (unsigned long)(skb->data);
+       end = data + bytes + MXGEFW_PAD - 1;
+       if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) {
+               printk(KERN_NOTICE
+                      "myri10ge_alloc_small: small skb crossed 4KB boundary\n");
+               myri10ge_skb_cross_4k = 1;
+               dev_kfree_skb_any(skb);
+               skb = myri10ge_alloc_small_safe(bytes);
+       }
+       return skb;
+}
+
+static inline int
+myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes,
+               int idx)
+{
+       struct sk_buff *skb;
+       dma_addr_t bus;
+       int len, retval = 0;
+
+       bytes += VLAN_HLEN;     /* account for 802.1q vlan tag */
+
+       if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ )
+               skb = myri10ge_alloc_big(bytes);
+       else if (myri10ge_skb_cross_4k)
+               skb = myri10ge_alloc_small_safe(bytes);
+       else
+               skb = myri10ge_alloc_small(bytes);
+
+       if (unlikely(skb == NULL)) {
+               rx->alloc_fail++;
+               retval = -ENOBUFS;
+               goto done;
+       }
+
+       /* set len so that it only covers the area we
+        * need mapped for DMA */
+       len = bytes + MXGEFW_PAD;
+
+       bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE);
+       rx->info[idx].skb = skb;
+       pci_unmap_addr_set(&rx->info[idx], bus, bus);
+       pci_unmap_len_set(&rx->info[idx], len, len);
+       rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus));
+       rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus));
+
+done:
+       /* copy 8 descriptors (64-bytes) to the mcp at a time */
+       if ((idx & 7) == 7) {
+               if (rx->wc_fifo == NULL)
+                       myri10ge_submit_8rx(&rx->lanai[idx - 7],
+                                           &rx->shadow[idx - 7]);
+               else {
+                       mb();
+                       myri10ge_pio_copy(rx->wc_fifo,
+                                         &rx->shadow[idx - 7], 64);
+               }
+       }
+       return retval;
+}
+
+static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum)
+{
+       struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data);
+
+       if ((skb->protocol == ntohs(ETH_P_8021Q)) &&
+           (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) ||
+            vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) {
+               skb->csum = hw_csum;
+               skb->ip_summed = CHECKSUM_HW;
+       }
+}
+
+static inline unsigned long
+myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
+                int bytes, int len, int csum)
+{
+       dma_addr_t bus;
+       struct sk_buff *skb;
+       int idx, unmap_len;
+
+       idx = rx->cnt & rx->mask;
+       rx->cnt++;
+
+       /* save a pointer to the received skb */
+       skb = rx->info[idx].skb;
+       bus = pci_unmap_addr(&rx->info[idx], bus);
+       unmap_len = pci_unmap_len(&rx->info[idx], len);
+
+       /* try to replace the received skb */
+       if (myri10ge_getbuf(rx, mgp->pdev, bytes, idx)) {
+               /* drop the frame -- the old skbuf is re-cycled */
+               mgp->stats.rx_dropped += 1;
+               return 0;
+       }
+
+       /* unmap the recvd skb */
+       pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE);
+
+       /* mcp implicitly skips 1st bytes so that packet is properly
+        * aligned */
+       skb_reserve(skb, MXGEFW_PAD);
+
+       /* set the length of the frame */
+       skb_put(skb, len);
+
+       skb->protocol = eth_type_trans(skb, mgp->dev);
+       skb->dev = mgp->dev;
+       if (mgp->csum_flag) {
+               if ((skb->protocol == ntohs(ETH_P_IP)) ||
+                   (skb->protocol == ntohs(ETH_P_IPV6))) {
+                       skb->csum = ntohs((u16) csum);
+                       skb->ip_summed = CHECKSUM_HW;
+               } else
+                       myri10ge_vlan_ip_csum(skb, ntohs((u16) csum));
+       }
+
+       netif_receive_skb(skb);
+       mgp->dev->last_rx = jiffies;
+       return 1;
+}
+
+static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
+{
+       struct pci_dev *pdev = mgp->pdev;
+       struct myri10ge_tx_buf *tx = &mgp->tx;
+       struct sk_buff *skb;
+       int idx, len;
+       int limit = 0;
+
+       while (tx->pkt_done != mcp_index) {
+               idx = tx->done & tx->mask;
+               skb = tx->info[idx].skb;
+
+               /* Mark as free */
+               tx->info[idx].skb = NULL;
+               if (tx->info[idx].last) {
+                       tx->pkt_done++;
+                       tx->info[idx].last = 0;
+               }
+               tx->done++;
+               len = pci_unmap_len(&tx->info[idx], len);
+               pci_unmap_len_set(&tx->info[idx], len, 0);
+               if (skb) {
+                       mgp->stats.tx_bytes += skb->len;
+                       mgp->stats.tx_packets++;
+                       dev_kfree_skb_irq(skb);
+                       if (len)
+                               pci_unmap_single(pdev,
+                                                pci_unmap_addr(&tx->info[idx],
+                                                               bus), len,
+                                                PCI_DMA_TODEVICE);
+               } else {
+                       if (len)
+                               pci_unmap_page(pdev,
+                                              pci_unmap_addr(&tx->info[idx],
+                                                             bus), len,
+                                              PCI_DMA_TODEVICE);
+               }
+
+               /* limit potential for livelock by only handling
+                * 2 full tx rings per call */
+               if (unlikely(++limit > 2 * tx->mask))
+                       break;
+       }
+       /* start the queue if we've stopped it */
+       if (netif_queue_stopped(mgp->dev)
+           && tx->req - tx->done < (tx->mask >> 1)) {
+               mgp->wake_queue++;
+               netif_wake_queue(mgp->dev);
+       }
+}
+
+static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
+{
+       struct myri10ge_rx_done *rx_done = &mgp->rx_done;
+       unsigned long rx_bytes = 0;
+       unsigned long rx_packets = 0;
+       unsigned long rx_ok;
+
+       int idx = rx_done->idx;
+       int cnt = rx_done->cnt;
+       u16 length;
+       u16 checksum;
+
+       while (rx_done->entry[idx].length != 0 && *limit != 0) {
+               length = ntohs(rx_done->entry[idx].length);
+               rx_done->entry[idx].length = 0;
+               checksum = ntohs(rx_done->entry[idx].checksum);
+               if (length <= mgp->small_bytes)
+                       rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small,
+                                                mgp->small_bytes,
+                                                length, checksum);
+               else
+                       rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big,
+                                                mgp->dev->mtu + ETH_HLEN,
+                                                length, checksum);
+               rx_packets += rx_ok;
+               rx_bytes += rx_ok * (unsigned long)length;
+               cnt++;
+               idx = cnt & (myri10ge_max_intr_slots - 1);
+
+               /* limit potential for livelock by only handling a
+                * limited number of frames. */
+               (*limit)--;
+       }
+       rx_done->idx = idx;
+       rx_done->cnt = cnt;
+       mgp->stats.rx_packets += rx_packets;
+       mgp->stats.rx_bytes += rx_bytes;
+}
+
+static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
+{
+       struct mcp_irq_data *stats = mgp->fw_stats;
+
+       if (unlikely(stats->stats_updated)) {
+               if (mgp->link_state != stats->link_up) {
+                       mgp->link_state = stats->link_up;
+                       if (mgp->link_state) {
+                               printk(KERN_INFO "myri10ge: %s: link up\n",
+                                      mgp->dev->name);
+                               netif_carrier_on(mgp->dev);
+                       } else {
+                               printk(KERN_INFO "myri10ge: %s: link down\n",
+                                      mgp->dev->name);
+                               netif_carrier_off(mgp->dev);
+                       }
+               }
+               if (mgp->rdma_tags_available !=
+                   ntohl(mgp->fw_stats->rdma_tags_available)) {
+                       mgp->rdma_tags_available =
+                           ntohl(mgp->fw_stats->rdma_tags_available);
+                       printk(KERN_WARNING "myri10ge: %s: RDMA timed out! "
+                              "%d tags left\n", mgp->dev->name,
+                              mgp->rdma_tags_available);
+               }
+               mgp->down_cnt += stats->link_down;
+               if (stats->link_down)
+                       wake_up(&mgp->down_wq);
+       }
+}
+
+static int myri10ge_poll(struct net_device *netdev, int *budget)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       struct myri10ge_rx_done *rx_done = &mgp->rx_done;
+       int limit, orig_limit, work_done;
+
+       /* process as many rx events as NAPI will allow */
+       limit = min(*budget, netdev->quota);
+       orig_limit = limit;
+       myri10ge_clean_rx_done(mgp, &limit);
+       work_done = orig_limit - limit;
+       *budget -= work_done;
+       netdev->quota -= work_done;
+
+       if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
+               netif_rx_complete(netdev);
+               __raw_writel(htonl(3), mgp->irq_claim);
+               return 0;
+       }
+       return 1;
+}
+
+static irqreturn_t myri10ge_intr(int irq, void *arg, struct pt_regs *regs)
+{
+       struct myri10ge_priv *mgp = arg;
+       struct mcp_irq_data *stats = mgp->fw_stats;
+       struct myri10ge_tx_buf *tx = &mgp->tx;
+       u32 send_done_count;
+       int i;
+
+       /* make sure it is our IRQ, and that the DMA has finished */
+       if (unlikely(!stats->valid))
+               return (IRQ_NONE);
+
+       /* low bit indicates receives are present, so schedule
+        * napi poll handler */
+       if (stats->valid & 1)
+               netif_rx_schedule(mgp->dev);
+
+       if (!mgp->msi_enabled) {
+               __raw_writel(0, mgp->irq_deassert);
+               if (!myri10ge_deassert_wait)
+                       stats->valid = 0;
+               mb();
+       } else
+               stats->valid = 0;
+
+       /* Wait for IRQ line to go low, if using INTx */
+       i = 0;
+       while (1) {
+               i++;
+               /* check for transmit completes and receives */
+               send_done_count = ntohl(stats->send_done_count);
+               if (send_done_count != tx->pkt_done)
+                       myri10ge_tx_done(mgp, (int)send_done_count);
+               if (unlikely(i > myri10ge_max_irq_loops)) {
+                       printk(KERN_WARNING "myri10ge: %s: irq stuck?\n",
+                              mgp->dev->name);
+                       stats->valid = 0;
+                       schedule_work(&mgp->watchdog_work);
+               }
+               if (likely(stats->valid == 0))
+                       break;
+               cpu_relax();
+               barrier();
+       }
+
+       myri10ge_check_statblock(mgp);
+
+       __raw_writel(htonl(3), mgp->irq_claim + 1);
+       return (IRQ_HANDLED);
+}
+
+static int
+myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+       cmd->autoneg = AUTONEG_DISABLE;
+       cmd->speed = SPEED_10000;
+       cmd->duplex = DUPLEX_FULL;
+       return 0;
+}
+
+static void
+myri10ge_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       strlcpy(info->driver, "myri10ge", sizeof(info->driver));
+       strlcpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version));
+       strlcpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version));
+       strlcpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info));
+}
+
+static int
+myri10ge_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       coal->rx_coalesce_usecs = mgp->intr_coal_delay;
+       return 0;
+}
+
+static int
+myri10ge_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       mgp->intr_coal_delay = coal->rx_coalesce_usecs;
+       __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
+       return 0;
+}
+
+static void
+myri10ge_get_pauseparam(struct net_device *netdev,
+                       struct ethtool_pauseparam *pause)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       pause->autoneg = 0;
+       pause->rx_pause = mgp->pause;
+       pause->tx_pause = mgp->pause;
+}
+
+static int
+myri10ge_set_pauseparam(struct net_device *netdev,
+                       struct ethtool_pauseparam *pause)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       if (pause->tx_pause != mgp->pause)
+               return myri10ge_change_pause(mgp, pause->tx_pause);
+       if (pause->rx_pause != mgp->pause)
+               return myri10ge_change_pause(mgp, pause->tx_pause);
+       if (pause->autoneg != 0)
+               return -EINVAL;
+       return 0;
+}
+
+static void
+myri10ge_get_ringparam(struct net_device *netdev,
+                      struct ethtool_ringparam *ring)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       ring->rx_mini_max_pending = mgp->rx_small.mask + 1;
+       ring->rx_max_pending = mgp->rx_big.mask + 1;
+       ring->rx_jumbo_max_pending = 0;
+       ring->tx_max_pending = mgp->rx_small.mask + 1;
+       ring->rx_mini_pending = ring->rx_mini_max_pending;
+       ring->rx_pending = ring->rx_max_pending;
+       ring->rx_jumbo_pending = ring->rx_jumbo_max_pending;
+       ring->tx_pending = ring->tx_max_pending;
+}
+
+static u32 myri10ge_get_rx_csum(struct net_device *netdev)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       if (mgp->csum_flag)
+               return 1;
+       else
+               return 0;
+}
+
+static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       if (csum_enabled)
+               mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
+       else
+               mgp->csum_flag = 0;
+       return 0;
+}
+
+static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
+       "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
+       "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
+       "rx_length_errors", "rx_over_errors", "rx_crc_errors",
+       "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
+       "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
+       "tx_heartbeat_errors", "tx_window_errors",
+       /* device-specific stats */
+       "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
+       "serial_number", "tx_pkt_start", "tx_pkt_done",
+       "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt",
+       "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized",
+       "link_up", "dropped_link_overflow", "dropped_link_error_or_filtered",
+       "dropped_runt", "dropped_overrun", "dropped_no_small_buffer",
+       "dropped_no_big_buffer"
+};
+
+#define MYRI10GE_NET_STATS_LEN      21
+#define MYRI10GE_STATS_LEN  sizeof(myri10ge_gstrings_stats) / ETH_GSTRING_LEN
+
+static void
+myri10ge_get_strings(struct net_device *netdev, u32 stringset, u8 * data)
+{
+       switch (stringset) {
+       case ETH_SS_STATS:
+               memcpy(data, *myri10ge_gstrings_stats,
+                      sizeof(myri10ge_gstrings_stats));
+               break;
+       }
+}
+
+static int myri10ge_get_stats_count(struct net_device *netdev)
+{
+       return MYRI10GE_STATS_LEN;
+}
+
+static void
+myri10ge_get_ethtool_stats(struct net_device *netdev,
+                          struct ethtool_stats *stats, u64 * data)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       int i;
+
+       for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
+               data[i] = ((unsigned long *)&mgp->stats)[i];
+
+       data[i++] = (unsigned int)mgp->read_dma;
+       data[i++] = (unsigned int)mgp->write_dma;
+       data[i++] = (unsigned int)mgp->read_write_dma;
+       data[i++] = (unsigned int)mgp->serial_number;
+       data[i++] = (unsigned int)mgp->tx.pkt_start;
+       data[i++] = (unsigned int)mgp->tx.pkt_done;
+       data[i++] = (unsigned int)mgp->tx.req;
+       data[i++] = (unsigned int)mgp->tx.done;
+       data[i++] = (unsigned int)mgp->rx_small.cnt;
+       data[i++] = (unsigned int)mgp->rx_big.cnt;
+       data[i++] = (unsigned int)mgp->wake_queue;
+       data[i++] = (unsigned int)mgp->stop_queue;
+       data[i++] = (unsigned int)mgp->watchdog_resets;
+       data[i++] = (unsigned int)mgp->tx_linearized;
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow);
+       data[i++] =
+           (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer);
+}
+
+static struct ethtool_ops myri10ge_ethtool_ops = {
+       .get_settings = myri10ge_get_settings,
+       .get_drvinfo = myri10ge_get_drvinfo,
+       .get_coalesce = myri10ge_get_coalesce,
+       .set_coalesce = myri10ge_set_coalesce,
+       .get_pauseparam = myri10ge_get_pauseparam,
+       .set_pauseparam = myri10ge_set_pauseparam,
+       .get_ringparam = myri10ge_get_ringparam,
+       .get_rx_csum = myri10ge_get_rx_csum,
+       .set_rx_csum = myri10ge_set_rx_csum,
+       .get_tx_csum = ethtool_op_get_tx_csum,
+       .set_tx_csum = ethtool_op_set_tx_csum,
+       .get_sg = ethtool_op_get_sg,
+       .set_sg = ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+       .get_tso = ethtool_op_get_tso,
+       .set_tso = ethtool_op_set_tso,
+#endif
+       .get_strings = myri10ge_get_strings,
+       .get_stats_count = myri10ge_get_stats_count,
+       .get_ethtool_stats = myri10ge_get_ethtool_stats
+};
+
+static int myri10ge_allocate_rings(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct myri10ge_cmd cmd;
+       int tx_ring_size, rx_ring_size;
+       int tx_ring_entries, rx_ring_entries;
+       int i, status;
+       size_t bytes;
+
+       mgp = netdev_priv(dev);
+
+       /* get ring sizes */
+
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0);
+       tx_ring_size = cmd.data0;
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0);
+       rx_ring_size = cmd.data0;
+
+       tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send);
+       rx_ring_entries = rx_ring_size / sizeof(struct mcp_dma_addr);
+       mgp->tx.mask = tx_ring_entries - 1;
+       mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1;
+
+       /* allocate the host shadow rings */
+
+       bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4)
+           * sizeof(*mgp->tx.req_list);
+       mgp->tx.req_bytes = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->tx.req_bytes == NULL)
+               goto abort_with_nothing;
+
+       /* ensure req_list entries are aligned to 8 bytes */
+       mgp->tx.req_list = (struct mcp_kreq_ether_send *)
+           ALIGN((unsigned long)mgp->tx.req_bytes, 8);
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_small.shadow);
+       mgp->rx_small.shadow = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_small.shadow == NULL)
+               goto abort_with_tx_req_bytes;
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_big.shadow);
+       mgp->rx_big.shadow = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_big.shadow == NULL)
+               goto abort_with_rx_small_shadow;
+
+       /* allocate the host info rings */
+
+       bytes = tx_ring_entries * sizeof(*mgp->tx.info);
+       mgp->tx.info = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->tx.info == NULL)
+               goto abort_with_rx_big_shadow;
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_small.info);
+       mgp->rx_small.info = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_small.info == NULL)
+               goto abort_with_tx_info;
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_big.info);
+       mgp->rx_big.info = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_big.info == NULL)
+               goto abort_with_rx_small_info;
+
+       /* Fill the receive rings */
+
+       for (i = 0; i <= mgp->rx_small.mask; i++) {
+               status = myri10ge_getbuf(&mgp->rx_small, mgp->pdev,
+                                        mgp->small_bytes, i);
+               if (status) {
+                       printk(KERN_ERR
+                              "myri10ge: %s: alloced only %d small bufs\n",
+                              dev->name, i);
+                       goto abort_with_rx_small_ring;
+               }
+       }
+
+       for (i = 0; i <= mgp->rx_big.mask; i++) {
+               status =
+                   myri10ge_getbuf(&mgp->rx_big, mgp->pdev,
+                                   dev->mtu + ETH_HLEN, i);
+               if (status) {
+                       printk(KERN_ERR
+                              "myri10ge: %s: alloced only %d big bufs\n",
+                              dev->name, i);
+                       goto abort_with_rx_big_ring;
+               }
+       }
+
+       return 0;
+
+abort_with_rx_big_ring:
+       for (i = 0; i <= mgp->rx_big.mask; i++) {
+               if (mgp->rx_big.info[i].skb != NULL)
+                       dev_kfree_skb_any(mgp->rx_big.info[i].skb);
+               if (pci_unmap_len(&mgp->rx_big.info[i], len))
+                       pci_unmap_single(mgp->pdev,
+                                        pci_unmap_addr(&mgp->rx_big.info[i],
+                                                       bus),
+                                        pci_unmap_len(&mgp->rx_big.info[i],
+                                                      len),
+                                        PCI_DMA_FROMDEVICE);
+       }
+
+abort_with_rx_small_ring:
+       for (i = 0; i <= mgp->rx_small.mask; i++) {
+               if (mgp->rx_small.info[i].skb != NULL)
+                       dev_kfree_skb_any(mgp->rx_small.info[i].skb);
+               if (pci_unmap_len(&mgp->rx_small.info[i], len))
+                       pci_unmap_single(mgp->pdev,
+                                        pci_unmap_addr(&mgp->rx_small.info[i],
+                                                       bus),
+                                        pci_unmap_len(&mgp->rx_small.info[i],
+                                                      len),
+                                        PCI_DMA_FROMDEVICE);
+       }
+       kfree(mgp->rx_big.info);
+
+abort_with_rx_small_info:
+       kfree(mgp->rx_small.info);
+
+abort_with_tx_info:
+       kfree(mgp->tx.info);
+
+abort_with_rx_big_shadow:
+       kfree(mgp->rx_big.shadow);
+
+abort_with_rx_small_shadow:
+       kfree(mgp->rx_small.shadow);
+
+abort_with_tx_req_bytes:
+       kfree(mgp->tx.req_bytes);
+       mgp->tx.req_bytes = NULL;
+       mgp->tx.req_list = NULL;
+
+abort_with_nothing:
+       return status;
+}
+
+static void myri10ge_free_rings(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct sk_buff *skb;
+       struct myri10ge_tx_buf *tx;
+       int i, len, idx;
+
+       mgp = netdev_priv(dev);
+
+       for (i = 0; i <= mgp->rx_big.mask; i++) {
+               if (mgp->rx_big.info[i].skb != NULL)
+                       dev_kfree_skb_any(mgp->rx_big.info[i].skb);
+               if (pci_unmap_len(&mgp->rx_big.info[i], len))
+                       pci_unmap_single(mgp->pdev,
+                                        pci_unmap_addr(&mgp->rx_big.info[i],
+                                                       bus),
+                                        pci_unmap_len(&mgp->rx_big.info[i],
+                                                      len),
+                                        PCI_DMA_FROMDEVICE);
+       }
+
+       for (i = 0; i <= mgp->rx_small.mask; i++) {
+               if (mgp->rx_small.info[i].skb != NULL)
+                       dev_kfree_skb_any(mgp->rx_small.info[i].skb);
+               if (pci_unmap_len(&mgp->rx_small.info[i], len))
+                       pci_unmap_single(mgp->pdev,
+                                        pci_unmap_addr(&mgp->rx_small.info[i],
+                                                       bus),
+                                        pci_unmap_len(&mgp->rx_small.info[i],
+                                                      len),
+                                        PCI_DMA_FROMDEVICE);
+       }
+
+       tx = &mgp->tx;
+       while (tx->done != tx->req) {
+               idx = tx->done & tx->mask;
+               skb = tx->info[idx].skb;
+
+               /* Mark as free */
+               tx->info[idx].skb = NULL;
+               tx->done++;
+               len = pci_unmap_len(&tx->info[idx], len);
+               pci_unmap_len_set(&tx->info[idx], len, 0);
+               if (skb) {
+                       mgp->stats.tx_dropped++;
+                       dev_kfree_skb_any(skb);
+                       if (len)
+                               pci_unmap_single(mgp->pdev,
+                                                pci_unmap_addr(&tx->info[idx],
+                                                               bus), len,
+                                                PCI_DMA_TODEVICE);
+               } else {
+                       if (len)
+                               pci_unmap_page(mgp->pdev,
+                                              pci_unmap_addr(&tx->info[idx],
+                                                             bus), len,
+                                              PCI_DMA_TODEVICE);
+               }
+       }
+       kfree(mgp->rx_big.info);
+
+       kfree(mgp->rx_small.info);
+
+       kfree(mgp->tx.info);
+
+       kfree(mgp->rx_big.shadow);
+
+       kfree(mgp->rx_small.shadow);
+
+       kfree(mgp->tx.req_bytes);
+       mgp->tx.req_bytes = NULL;
+       mgp->tx.req_list = NULL;
+}
+
+static int myri10ge_open(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct myri10ge_cmd cmd;
+       int status, big_pow2;
+
+       mgp = netdev_priv(dev);
+
+       if (mgp->running != MYRI10GE_ETH_STOPPED)
+               return -EBUSY;
+
+       mgp->running = MYRI10GE_ETH_STARTING;
+       status = myri10ge_reset(mgp);
+       if (status != 0) {
+               printk(KERN_ERR "myri10ge: %s: failed reset\n", dev->name);
+               mgp->running = MYRI10GE_ETH_STOPPED;
+               return -ENXIO;
+       }
+
+       /* decide what small buffer size to use.  For good TCP rx
+        * performance, it is important to not receive 1514 byte
+        * frames into jumbo buffers, as it confuses the socket buffer
+        * accounting code, leading to drops and erratic performance.
+        */
+
+       if (dev->mtu <= ETH_DATA_LEN)
+               mgp->small_bytes = 128; /* enough for a TCP header */
+       else
+               mgp->small_bytes = ETH_FRAME_LEN;       /* enough for an ETH_DATA_LEN frame */
+
+       /* Override the small buffer size? */
+       if (myri10ge_small_bytes > 0)
+               mgp->small_bytes = myri10ge_small_bytes;
+
+       /* If the user sets an obscenely small MTU, adjust the small
+        * bytes down to nearly nothing */
+       if (mgp->small_bytes >= (dev->mtu + ETH_HLEN))
+               mgp->small_bytes = 64;
+
+       /* get the lanai pointers to the send and receive rings */
+
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
+       mgp->tx.lanai =
+           (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0);
+
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd, 0);
+       mgp->rx_small.lanai =
+           (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
+
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd, 0);
+       mgp->rx_big.lanai =
+           (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
+
+       if (status != 0) {
+               printk(KERN_ERR
+                      "myri10ge: %s: failed to get ring sizes or locations\n",
+                      dev->name);
+               mgp->running = MYRI10GE_ETH_STOPPED;
+               return -ENXIO;
+       }
+
+       if (mgp->mtrr >= 0) {
+               mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + 0x200000;
+               mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + 0x300000;
+               mgp->rx_big.wc_fifo = (u8 __iomem *) mgp->sram + 0x340000;
+       } else {
+               mgp->tx.wc_fifo = NULL;
+               mgp->rx_small.wc_fifo = NULL;
+               mgp->rx_big.wc_fifo = NULL;
+       }
+
+       status = myri10ge_allocate_rings(dev);
+       if (status != 0)
+               goto abort_with_nothing;
+
+       /* Firmware needs the big buff size as a power of 2.  Lie and
+        * tell him the buffer is larger, because we only use 1
+        * buffer/pkt, and the mtu will prevent overruns.
+        */
+       big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD;
+       while ((big_pow2 & (big_pow2 - 1)) != 0)
+               big_pow2++;
+
+       /* now give firmware buffers sizes, and MTU */
+       cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN;
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd, 0);
+       cmd.data0 = mgp->small_bytes;
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, &cmd, 0);
+       cmd.data0 = big_pow2;
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd, 0);
+       if (status) {
+               printk(KERN_ERR "myri10ge: %s: Couldn't set buffer sizes\n",
+                      dev->name);
+               goto abort_with_rings;
+       }
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus);
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA, &cmd, 0);
+       if (status) {
+               printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n",
+                      dev->name);
+               goto abort_with_rings;
+       }
+
+       mgp->link_state = -1;
+       mgp->rdma_tags_available = 15;
+
+       netif_poll_enable(mgp->dev);    /* must happen prior to any irq */
+
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0);
+       if (status) {
+               printk(KERN_ERR "myri10ge: %s: Couldn't bring up link\n",
+                      dev->name);
+               goto abort_with_rings;
+       }
+
+       mgp->wake_queue = 0;
+       mgp->stop_queue = 0;
+       mgp->running = MYRI10GE_ETH_RUNNING;
+       mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ;
+       add_timer(&mgp->watchdog_timer);
+       netif_wake_queue(dev);
+       return 0;
+
+abort_with_rings:
+       myri10ge_free_rings(dev);
+
+abort_with_nothing:
+       mgp->running = MYRI10GE_ETH_STOPPED;
+       return -ENOMEM;
+}
+
+static int myri10ge_close(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct myri10ge_cmd cmd;
+       int status, old_down_cnt;
+
+       mgp = netdev_priv(dev);
+
+       if (mgp->running != MYRI10GE_ETH_RUNNING)
+               return 0;
+
+       if (mgp->tx.req_bytes == NULL)
+               return 0;
+
+       del_timer_sync(&mgp->watchdog_timer);
+       mgp->running = MYRI10GE_ETH_STOPPING;
+       netif_poll_disable(mgp->dev);
+       netif_carrier_off(dev);
+       netif_stop_queue(dev);
+       old_down_cnt = mgp->down_cnt;
+       mb();
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
+       if (status)
+               printk(KERN_ERR "myri10ge: %s: Couldn't bring down link\n",
+                      dev->name);
+
+       wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ);
+       if (old_down_cnt == mgp->down_cnt)
+               printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name);
+
+       netif_tx_disable(dev);
+
+       myri10ge_free_rings(dev);
+
+       mgp->running = MYRI10GE_ETH_STOPPED;
+       return 0;
+}
+
+/* copy an array of struct mcp_kreq_ether_send's to the mcp.  Copy
+ * backwards one at a time and handle ring wraps */
+
+static inline void
+myri10ge_submit_req_backwards(struct myri10ge_tx_buf *tx,
+                             struct mcp_kreq_ether_send *src, int cnt)
+{
+       int idx, starting_slot;
+       starting_slot = tx->req;
+       while (cnt > 1) {
+               cnt--;
+               idx = (starting_slot + cnt) & tx->mask;
+               myri10ge_pio_copy(&tx->lanai[idx], &src[cnt], sizeof(*src));
+               mb();
+       }
+}
+
+/*
+ * copy an array of struct mcp_kreq_ether_send's to the mcp.  Copy
+ * at most 32 bytes at a time, so as to avoid involving the software
+ * pio handler in the nic.   We re-write the first segment's flags
+ * to mark them valid only after writing the entire chain.
+ */
+
+static inline void
+myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
+                   int cnt)
+{
+       int idx, i;
+       struct mcp_kreq_ether_send __iomem *dstp, *dst;
+       struct mcp_kreq_ether_send *srcp;
+       u8 last_flags;
+
+       idx = tx->req & tx->mask;
+
+       last_flags = src->flags;
+       src->flags = 0;
+       mb();
+       dst = dstp = &tx->lanai[idx];
+       srcp = src;
+
+       if ((idx + cnt) < tx->mask) {
+               for (i = 0; i < (cnt - 1); i += 2) {
+                       myri10ge_pio_copy(dstp, srcp, 2 * sizeof(*src));
+                       mb();   /* force write every 32 bytes */
+                       srcp += 2;
+                       dstp += 2;
+               }
+       } else {
+               /* submit all but the first request, and ensure
+                * that it is submitted below */
+               myri10ge_submit_req_backwards(tx, src, cnt);
+               i = 0;
+       }
+       if (i < cnt) {
+               /* submit the first request */
+               myri10ge_pio_copy(dstp, srcp, sizeof(*src));
+               mb();           /* barrier before setting valid flag */
+       }
+
+       /* re-write the last 32-bits with the valid flags */
+       src->flags = last_flags;
+       __raw_writel(*((u32 *) src + 3), (u32 __iomem *) dst + 3);
+       tx->req += cnt;
+       mb();
+}
+
+static inline void
+myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx,
+                      struct mcp_kreq_ether_send *src, int cnt)
+{
+       tx->req += cnt;
+       mb();
+       while (cnt >= 4) {
+               myri10ge_pio_copy(tx->wc_fifo, src, 64);
+               mb();
+               src += 4;
+               cnt -= 4;
+       }
+       if (cnt > 0) {
+               /* pad it to 64 bytes.  The src is 64 bytes bigger than it
+                * needs to be so that we don't overrun it */
+               myri10ge_pio_copy(tx->wc_fifo + (cnt << 18), src, 64);
+               mb();
+       }
+}
+
+/*
+ * Transmit a packet.  We need to split the packet so that a single
+ * segment does not cross myri10ge->tx.boundary, so this makes segment
+ * counting tricky.  So rather than try to count segments up front, we
+ * just give up if there are too few segments to hold a reasonably
+ * fragmented packet currently available.  If we run
+ * out of segments while preparing a packet for DMA, we just linearize
+ * it and try again.
+ */
+
+static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct myri10ge_priv *mgp = netdev_priv(dev);
+       struct mcp_kreq_ether_send *req;
+       struct myri10ge_tx_buf *tx = &mgp->tx;
+       struct skb_frag_struct *frag;
+       dma_addr_t bus;
+       u32 low, high_swapped;
+       unsigned int len;
+       int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
+       u16 pseudo_hdr_offset, cksum_offset;
+       int cum_len, seglen, boundary, rdma_count;
+       u8 flags, odd_flag;
+
+again:
+       req = tx->req_list;
+       avail = tx->mask - 1 - (tx->req - tx->done);
+
+       mss = 0;
+       max_segments = MXGEFW_MAX_SEND_DESC;
+
+#ifdef NETIF_F_TSO
+       if (skb->len > (dev->mtu + ETH_HLEN)) {
+               mss = skb_shinfo(skb)->tso_size;
+               if (mss != 0)
+                       max_segments = MYRI10GE_MAX_SEND_DESC_TSO;
+       }
+#endif                         /*NETIF_F_TSO */
+
+       if ((unlikely(avail < max_segments))) {
+               /* we are out of transmit resources */
+               mgp->stop_queue++;
+               netif_stop_queue(dev);
+               return 1;
+       }
+
+       /* Setup checksum offloading, if needed */
+       cksum_offset = 0;
+       pseudo_hdr_offset = 0;
+       odd_flag = 0;
+       flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST);
+       if (likely(skb->ip_summed == CHECKSUM_HW)) {
+               cksum_offset = (skb->h.raw - skb->data);
+               pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data;
+               /* If the headers are excessively large, then we must
+                * fall back to a software checksum */
+               if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) {
+                       if (skb_checksum_help(skb, 0))
+                               goto drop;
+                       cksum_offset = 0;
+                       pseudo_hdr_offset = 0;
+               } else {
+                       pseudo_hdr_offset = htons(pseudo_hdr_offset);
+                       odd_flag = MXGEFW_FLAGS_ALIGN_ODD;
+                       flags |= MXGEFW_FLAGS_CKSUM;
+               }
+       }
+
+       cum_len = 0;
+
+#ifdef NETIF_F_TSO
+       if (mss) {              /* TSO */
+               /* this removes any CKSUM flag from before */
+               flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST);
+
+               /* negative cum_len signifies to the
+                * send loop that we are still in the
+                * hea