iwl3945: use iwl_rb_status
[safe/jmp/linux-2.6] / drivers / net / tg3.c
index 6575e9b..5b3d605 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/brcmphy.h>
 #include <linux/if_vlan.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/workqueue.h>
 #include <linux/prefetch.h>
 #include <linux/dma-mapping.h>
+#include <linux/firmware.h>
 
 #include <net/checksum.h>
 #include <net/ip.h>
 #include <asm/prom.h>
 #endif
 
+#define BAR_0  0
+#define BAR_2  2
+
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #define TG3_VLAN_TAG_USED 1
 #else
 #define TG3_VLAN_TAG_USED 0
 #endif
 
-#define TG3_TSO_SUPPORT        1
-
 #include "tg3.h"
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.86"
-#define DRV_MODULE_RELDATE     "November 9, 2007"
+#define DRV_MODULE_VERSION     "3.97"
+#define DRV_MODULE_RELDATE     "December 10, 2008"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
 /* minimum number of free TX descriptors required to wake up TX process */
 #define TG3_TX_WAKEUP_THRESH(tp)               ((tp)->tx_pending / 4)
 
+#define TG3_RAW_IP_ALIGN 2
+
 /* number of ETHTOOL_GSTATS u64's */
 #define TG3_NUM_STATS          (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
 
 #define TG3_NUM_TEST           6
 
+#define FIRMWARE_TG3           "tigon/tg3.bin"
+#define FIRMWARE_TG3TSO                "tigon/tg3_tso.bin"
+#define FIRMWARE_TG3TSO5       "tigon/tg3_tso5.bin"
+
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
@@ -139,6 +149,10 @@ MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox
 MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_FIRMWARE(FIRMWARE_TG3);
+MODULE_FIRMWARE(FIRMWARE_TG3TSO);
+MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
+
 
 static int tg3_debug = -1;     /* -1 == use TG3_DEF_MSG_ENABLE as value */
 module_param(tg3_debug, int, 0);
@@ -203,6 +217,13 @@ static struct pci_device_id tg3_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761S)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5785)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57720)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -533,6 +554,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
                return 0;
 
        switch (locknum) {
+               case TG3_APE_LOCK_GRC:
                case TG3_APE_LOCK_MEM:
                        break;
                default:
@@ -570,6 +592,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
                return;
 
        switch (locknum) {
+               case TG3_APE_LOCK_GRC:
                case TG3_APE_LOCK_MEM:
                        break;
                default:
@@ -804,57 +827,6 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
        return ret;
 }
 
-static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
-{
-       u32 phy;
-
-       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
-           (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
-               return;
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               u32 ephy;
-
-               if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &ephy)) {
-                       tg3_writephy(tp, MII_TG3_EPHY_TEST,
-                                    ephy | MII_TG3_EPHY_SHADOW_EN);
-                       if (!tg3_readphy(tp, MII_TG3_EPHYTST_MISCCTRL, &phy)) {
-                               if (enable)
-                                       phy |= MII_TG3_EPHYTST_MISCCTRL_MDIX;
-                               else
-                                       phy &= ~MII_TG3_EPHYTST_MISCCTRL_MDIX;
-                               tg3_writephy(tp, MII_TG3_EPHYTST_MISCCTRL, phy);
-                       }
-                       tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy);
-               }
-       } else {
-               phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC |
-                     MII_TG3_AUXCTL_SHDWSEL_MISC;
-               if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) &&
-                   !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) {
-                       if (enable)
-                               phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
-                       else
-                               phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
-                       phy |= MII_TG3_AUXCTL_MISC_WREN;
-                       tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
-               }
-       }
-}
-
-static void tg3_phy_set_wirespeed(struct tg3 *tp)
-{
-       u32 val;
-
-       if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED)
-               return;
-
-       if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007) &&
-           !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val))
-               tg3_writephy(tp, MII_TG3_AUX_CTRL,
-                            (val | (1 << 15) | (1 << 4)));
-}
-
 static int tg3_bmcr_reset(struct tg3 *tp)
 {
        u32 phy_control;
@@ -886,206 +858,938 @@ static int tg3_bmcr_reset(struct tg3 *tp)
        return 0;
 }
 
-static int tg3_wait_macro_done(struct tg3 *tp)
+static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg)
 {
-       int limit = 100;
+       struct tg3 *tp = bp->priv;
+       u32 val;
 
-       while (limit--) {
-               u32 tmp32;
+       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED)
+               return -EAGAIN;
 
-               if (!tg3_readphy(tp, 0x16, &tmp32)) {
-                       if ((tmp32 & 0x1000) == 0)
-                               break;
-               }
-       }
-       if (limit <= 0)
-               return -EBUSY;
+       if (tg3_readphy(tp, reg, &val))
+               return -EIO;
 
-       return 0;
+       return val;
 }
 
-static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
+static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val)
 {
-       static const u32 test_pat[4][6] = {
-       { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
-       { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
-       { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
-       { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
-       };
-       int chan;
+       struct tg3 *tp = bp->priv;
 
-       for (chan = 0; chan < 4; chan++) {
-               int i;
+       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED)
+               return -EAGAIN;
 
-               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
-                            (chan * 0x2000) | 0x0200);
-               tg3_writephy(tp, 0x16, 0x0002);
+       if (tg3_writephy(tp, reg, val))
+               return -EIO;
 
-               for (i = 0; i < 6; i++)
-                       tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
-                                    test_pat[chan][i]);
+       return 0;
+}
 
-               tg3_writephy(tp, 0x16, 0x0202);
-               if (tg3_wait_macro_done(tp)) {
-                       *resetp = 1;
-                       return -EBUSY;
-               }
+static int tg3_mdio_reset(struct mii_bus *bp)
+{
+       return 0;
+}
 
-               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
-                            (chan * 0x2000) | 0x0200);
-               tg3_writephy(tp, 0x16, 0x0082);
-               if (tg3_wait_macro_done(tp)) {
-                       *resetp = 1;
-                       return -EBUSY;
-               }
+static void tg3_mdio_config_5785(struct tg3 *tp)
+{
+       u32 val;
+       struct phy_device *phydev;
 
-               tg3_writephy(tp, 0x16, 0x0802);
-               if (tg3_wait_macro_done(tp)) {
-                       *resetp = 1;
-                       return -EBUSY;
-               }
+       phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+       switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
+       case TG3_PHY_ID_BCM50610:
+               val = MAC_PHYCFG2_50610_LED_MODES;
+               break;
+       case TG3_PHY_ID_BCMAC131:
+               val = MAC_PHYCFG2_AC131_LED_MODES;
+               break;
+       case TG3_PHY_ID_RTL8211C:
+               val = MAC_PHYCFG2_RTL8211C_LED_MODES;
+               break;
+       case TG3_PHY_ID_RTL8201E:
+               val = MAC_PHYCFG2_RTL8201E_LED_MODES;
+               break;
+       default:
+               return;
+       }
 
-               for (i = 0; i < 6; i += 2) {
-                       u32 low, high;
+       if (phydev->interface != PHY_INTERFACE_MODE_RGMII) {
+               tw32(MAC_PHYCFG2, val);
 
-                       if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) ||
-                           tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) ||
-                           tg3_wait_macro_done(tp)) {
-                               *resetp = 1;
-                               return -EBUSY;
-                       }
-                       low &= 0x7fff;
-                       high &= 0x000f;
-                       if (low != test_pat[chan][i] ||
-                           high != test_pat[chan][i+1]) {
-                               tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
-                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
-                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
+               val = tr32(MAC_PHYCFG1);
+               val &= ~MAC_PHYCFG1_RGMII_INT;
+               tw32(MAC_PHYCFG1, val);
 
-                               return -EBUSY;
-                       }
-               }
+               return;
        }
 
-       return 0;
+       if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE))
+               val |= MAC_PHYCFG2_EMODE_MASK_MASK |
+                      MAC_PHYCFG2_FMODE_MASK_MASK |
+                      MAC_PHYCFG2_GMODE_MASK_MASK |
+                      MAC_PHYCFG2_ACT_MASK_MASK   |
+                      MAC_PHYCFG2_QUAL_MASK_MASK |
+                      MAC_PHYCFG2_INBAND_ENABLE;
+
+       tw32(MAC_PHYCFG2, val);
+
+       val = tr32(MAC_PHYCFG1) & ~(MAC_PHYCFG1_RGMII_EXT_RX_DEC |
+                                   MAC_PHYCFG1_RGMII_SND_STAT_EN);
+       if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) {
+               if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN)
+                       val |= MAC_PHYCFG1_RGMII_EXT_RX_DEC;
+               if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN)
+                       val |= MAC_PHYCFG1_RGMII_SND_STAT_EN;
+       }
+       tw32(MAC_PHYCFG1, val | MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_TXC_DRV);
+
+       val = tr32(MAC_EXT_RGMII_MODE);
+       val &= ~(MAC_RGMII_MODE_RX_INT_B |
+                MAC_RGMII_MODE_RX_QUALITY |
+                MAC_RGMII_MODE_RX_ACTIVITY |
+                MAC_RGMII_MODE_RX_ENG_DET |
+                MAC_RGMII_MODE_TX_ENABLE |
+                MAC_RGMII_MODE_TX_LOWPWR |
+                MAC_RGMII_MODE_TX_RESET);
+       if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)) {
+               if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN)
+                       val |= MAC_RGMII_MODE_RX_INT_B |
+                              MAC_RGMII_MODE_RX_QUALITY |
+                              MAC_RGMII_MODE_RX_ACTIVITY |
+                              MAC_RGMII_MODE_RX_ENG_DET;
+               if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN)
+                       val |= MAC_RGMII_MODE_TX_ENABLE |
+                              MAC_RGMII_MODE_TX_LOWPWR |
+                              MAC_RGMII_MODE_TX_RESET;
+       }
+       tw32(MAC_EXT_RGMII_MODE, val);
+}
+
+static void tg3_mdio_start(struct tg3 *tp)
+{
+       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
+               mutex_lock(&tp->mdio_bus->mdio_lock);
+               tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED;
+               mutex_unlock(&tp->mdio_bus->mdio_lock);
+       }
+
+       tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL;
+       tw32_f(MAC_MI_MODE, tp->mi_mode);
+       udelay(80);
+
+       if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+               tg3_mdio_config_5785(tp);
 }
 
-static int tg3_phy_reset_chanpat(struct tg3 *tp)
+static void tg3_mdio_stop(struct tg3 *tp)
 {
-       int chan;
-
-       for (chan = 0; chan < 4; chan++) {
-               int i;
-
-               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
-                            (chan * 0x2000) | 0x0200);
-               tg3_writephy(tp, 0x16, 0x0002);
-               for (i = 0; i < 6; i++)
-                       tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
-               tg3_writephy(tp, 0x16, 0x0202);
-               if (tg3_wait_macro_done(tp))
-                       return -EBUSY;
+       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
+               mutex_lock(&tp->mdio_bus->mdio_lock);
+               tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_PAUSED;
+               mutex_unlock(&tp->mdio_bus->mdio_lock);
        }
-
-       return 0;
 }
 
-static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
+static int tg3_mdio_init(struct tg3 *tp)
 {
-       u32 reg32, phy9_orig;
-       int retries, do_phy_reset, err;
-
-       retries = 10;
-       do_phy_reset = 1;
-       do {
-               if (do_phy_reset) {
-                       err = tg3_bmcr_reset(tp);
-                       if (err)
-                               return err;
-                       do_phy_reset = 0;
-               }
+       int i;
+       u32 reg;
+       struct phy_device *phydev;
 
-               /* Disable transmitter and interrupt.  */
-               if (tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32))
-                       continue;
+       tg3_mdio_start(tp);
 
-               reg32 |= 0x3000;
-               tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+       if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) ||
+           (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED))
+               return 0;
 
-               /* Set full-duplex, 1000 mbps.  */
-               tg3_writephy(tp, MII_BMCR,
-                            BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
+       tp->mdio_bus = mdiobus_alloc();
+       if (tp->mdio_bus == NULL)
+               return -ENOMEM;
 
-               /* Set to master mode.  */
-               if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
-                       continue;
+       tp->mdio_bus->name     = "tg3 mdio bus";
+       snprintf(tp->mdio_bus->id, MII_BUS_ID_SIZE, "%x",
+                (tp->pdev->bus->number << 8) | tp->pdev->devfn);
+       tp->mdio_bus->priv     = tp;
+       tp->mdio_bus->parent   = &tp->pdev->dev;
+       tp->mdio_bus->read     = &tg3_mdio_read;
+       tp->mdio_bus->write    = &tg3_mdio_write;
+       tp->mdio_bus->reset    = &tg3_mdio_reset;
+       tp->mdio_bus->phy_mask = ~(1 << PHY_ADDR);
+       tp->mdio_bus->irq      = &tp->mdio_irq[0];
+
+       for (i = 0; i < PHY_MAX_ADDR; i++)
+               tp->mdio_bus->irq[i] = PHY_POLL;
+
+       /* The bus registration will look for all the PHYs on the mdio bus.
+        * Unfortunately, it does not ensure the PHY is powered up before
+        * accessing the PHY ID registers.  A chip reset is the
+        * quickest way to bring the device back to an operational state..
+        */
+       if (tg3_readphy(tp, MII_BMCR, &reg) || (reg & BMCR_PDOWN))
+               tg3_bmcr_reset(tp);
 
-               tg3_writephy(tp, MII_TG3_CTRL,
-                            (MII_TG3_CTRL_AS_MASTER |
-                             MII_TG3_CTRL_ENABLE_AS_MASTER));
+       i = mdiobus_register(tp->mdio_bus);
+       if (i) {
+               printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n",
+                       tp->dev->name, i);
+               mdiobus_free(tp->mdio_bus);
+               return i;
+       }
 
-               /* Enable SM_DSP_CLOCK and 6dB.  */
-               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+       phydev = tp->mdio_bus->phy_map[PHY_ADDR];
 
-               /* Block the PHY control access.  */
-               tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
-               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800);
+       if (!phydev || !phydev->drv) {
+               printk(KERN_WARNING "%s: No PHY devices\n", tp->dev->name);
+               mdiobus_unregister(tp->mdio_bus);
+               mdiobus_free(tp->mdio_bus);
+               return -ENODEV;
+       }
 
-               err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
-               if (!err)
-                       break;
-       } while (--retries);
+       switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
+       case TG3_PHY_ID_BCM57780:
+               phydev->interface = PHY_INTERFACE_MODE_GMII;
+               break;
+       case TG3_PHY_ID_BCM50610:
+               if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)
+                       phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE;
+               if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN)
+                       phydev->dev_flags |= PHY_BRCM_EXT_IBND_RX_ENABLE;
+               if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN)
+                       phydev->dev_flags |= PHY_BRCM_EXT_IBND_TX_ENABLE;
+               /* fallthru */
+       case TG3_PHY_ID_RTL8211C:
+               phydev->interface = PHY_INTERFACE_MODE_RGMII;
+               break;
+       case TG3_PHY_ID_RTL8201E:
+       case TG3_PHY_ID_BCMAC131:
+               phydev->interface = PHY_INTERFACE_MODE_MII;
+               break;
+       }
 
-       err = tg3_phy_reset_chanpat(tp);
-       if (err)
-               return err;
+       tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED;
 
-       tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
-       tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+               tg3_mdio_config_5785(tp);
 
-       tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
-       tg3_writephy(tp, 0x16, 0x0000);
+       return 0;
+}
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
-               /* Set Extended packet length bit for jumbo frames */
-               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4400);
-       }
-       else {
-               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+static void tg3_mdio_fini(struct tg3 *tp)
+{
+       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
+               tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_INITED;
+               mdiobus_unregister(tp->mdio_bus);
+               mdiobus_free(tp->mdio_bus);
+               tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED;
        }
+}
 
-       tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
+/* tp->lock is held. */
+static inline void tg3_generate_fw_event(struct tg3 *tp)
+{
+       u32 val;
 
-       if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
-               reg32 &= ~0x3000;
-               tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
-       } else if (!err)
-               err = -EBUSY;
+       val = tr32(GRC_RX_CPU_EVENT);
+       val |= GRC_RX_CPU_DRIVER_EVENT;
+       tw32_f(GRC_RX_CPU_EVENT, val);
 
-       return err;
+       tp->last_event_jiffies = jiffies;
 }
 
-static void tg3_link_report(struct tg3 *);
+#define TG3_FW_EVENT_TIMEOUT_USEC 2500
 
-/* This will reset the tigon3 PHY if there is no valid
- * link unless the FORCE argument is non-zero.
- */
-static int tg3_phy_reset(struct tg3 *tp)
+/* tp->lock is held. */
+static void tg3_wait_for_event_ack(struct tg3 *tp)
 {
-       u32 phy_status;
-       int err;
+       int i;
+       unsigned int delay_cnt;
+       long time_remain;
+
+       /* If enough time has passed, no wait is necessary. */
+       time_remain = (long)(tp->last_event_jiffies + 1 +
+                     usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) -
+                     (long)jiffies;
+       if (time_remain < 0)
+               return;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               u32 val;
+       /* Check if we can shorten the wait time. */
+       delay_cnt = jiffies_to_usecs(time_remain);
+       if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC)
+               delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC;
+       delay_cnt = (delay_cnt >> 3) + 1;
 
-               val = tr32(GRC_MISC_CFG);
-               tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
-               udelay(40);
+       for (i = 0; i < delay_cnt; i++) {
+               if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
+                       break;
+               udelay(8);
        }
-       err  = tg3_readphy(tp, MII_BMSR, &phy_status);
-       err |= tg3_readphy(tp, MII_BMSR, &phy_status);
-       if (err != 0)
+}
+
+/* tp->lock is held. */
+static void tg3_ump_link_report(struct tg3 *tp)
+{
+       u32 reg;
+       u32 val;
+
+       if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
+           !(tp->tg3_flags  & TG3_FLAG_ENABLE_ASF))
+               return;
+
+       tg3_wait_for_event_ack(tp);
+
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
+
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
+
+       val = 0;
+       if (!tg3_readphy(tp, MII_BMCR, &reg))
+               val = reg << 16;
+       if (!tg3_readphy(tp, MII_BMSR, &reg))
+               val |= (reg & 0xffff);
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
+
+       val = 0;
+       if (!tg3_readphy(tp, MII_ADVERTISE, &reg))
+               val = reg << 16;
+       if (!tg3_readphy(tp, MII_LPA, &reg))
+               val |= (reg & 0xffff);
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
+
+       val = 0;
+       if (!(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) {
+               if (!tg3_readphy(tp, MII_CTRL1000, &reg))
+                       val = reg << 16;
+               if (!tg3_readphy(tp, MII_STAT1000, &reg))
+                       val |= (reg & 0xffff);
+       }
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
+
+       if (!tg3_readphy(tp, MII_PHYADDR, &reg))
+               val = reg << 16;
+       else
+               val = 0;
+       tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
+
+       tg3_generate_fw_event(tp);
+}
+
+static void tg3_link_report(struct tg3 *tp)
+{
+       if (!netif_carrier_ok(tp->dev)) {
+               if (netif_msg_link(tp))
+                       printk(KERN_INFO PFX "%s: Link is down.\n",
+                              tp->dev->name);
+               tg3_ump_link_report(tp);
+       } else if (netif_msg_link(tp)) {
+               printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n",
+                      tp->dev->name,
+                      (tp->link_config.active_speed == SPEED_1000 ?
+                       1000 :
+                       (tp->link_config.active_speed == SPEED_100 ?
+                        100 : 10)),
+                      (tp->link_config.active_duplex == DUPLEX_FULL ?
+                       "full" : "half"));
+
+               printk(KERN_INFO PFX
+                      "%s: Flow control is %s for TX and %s for RX.\n",
+                      tp->dev->name,
+                      (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ?
+                      "on" : "off",
+                      (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ?
+                      "on" : "off");
+               tg3_ump_link_report(tp);
+       }
+}
+
+static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
+{
+       u16 miireg;
+
+       if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
+               miireg = ADVERTISE_PAUSE_CAP;
+       else if (flow_ctrl & FLOW_CTRL_TX)
+               miireg = ADVERTISE_PAUSE_ASYM;
+       else if (flow_ctrl & FLOW_CTRL_RX)
+               miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+       else
+               miireg = 0;
+
+       return miireg;
+}
+
+static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
+{
+       u16 miireg;
+
+       if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
+               miireg = ADVERTISE_1000XPAUSE;
+       else if (flow_ctrl & FLOW_CTRL_TX)
+               miireg = ADVERTISE_1000XPSE_ASYM;
+       else if (flow_ctrl & FLOW_CTRL_RX)
+               miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+       else
+               miireg = 0;
+
+       return miireg;
+}
+
+static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
+{
+       u8 cap = 0;
+
+       if (lcladv & ADVERTISE_1000XPAUSE) {
+               if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+                       if (rmtadv & LPA_1000XPAUSE)
+                               cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+                       else if (rmtadv & LPA_1000XPAUSE_ASYM)
+                               cap = FLOW_CTRL_RX;
+               } else {
+                       if (rmtadv & LPA_1000XPAUSE)
+                               cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
+               }
+       } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+               if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
+                       cap = FLOW_CTRL_TX;
+       }
+
+       return cap;
+}
+
+static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
+{
+       u8 autoneg;
+       u8 flowctrl = 0;
+       u32 old_rx_mode = tp->rx_mode;
+       u32 old_tx_mode = tp->tx_mode;
+
+       if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)
+               autoneg = tp->mdio_bus->phy_map[PHY_ADDR]->autoneg;
+       else
+               autoneg = tp->link_config.autoneg;
+
+       if (autoneg == AUTONEG_ENABLE &&
+           (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) {
+               if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
+                       flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv);
+               else
+                       flowctrl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+       } else
+               flowctrl = tp->link_config.flowctrl;
+
+       tp->link_config.active_flowctrl = flowctrl;
+
+       if (flowctrl & FLOW_CTRL_RX)
+               tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
+       else
+               tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
+
+       if (old_rx_mode != tp->rx_mode)
+               tw32_f(MAC_RX_MODE, tp->rx_mode);
+
+       if (flowctrl & FLOW_CTRL_TX)
+               tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
+       else
+               tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
+
+       if (old_tx_mode != tp->tx_mode)
+               tw32_f(MAC_TX_MODE, tp->tx_mode);
+}
+
+static void tg3_adjust_link(struct net_device *dev)
+{
+       u8 oldflowctrl, linkmesg = 0;
+       u32 mac_mode, lcl_adv, rmt_adv;
+       struct tg3 *tp = netdev_priv(dev);
+       struct phy_device *phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+
+       spin_lock(&tp->lock);
+
+       mac_mode = tp->mac_mode & ~(MAC_MODE_PORT_MODE_MASK |
+                                   MAC_MODE_HALF_DUPLEX);
+
+       oldflowctrl = tp->link_config.active_flowctrl;
+
+       if (phydev->link) {
+               lcl_adv = 0;
+               rmt_adv = 0;
+
+               if (phydev->speed == SPEED_100 || phydev->speed == SPEED_10)
+                       mac_mode |= MAC_MODE_PORT_MODE_MII;
+               else
+                       mac_mode |= MAC_MODE_PORT_MODE_GMII;
+
+               if (phydev->duplex == DUPLEX_HALF)
+                       mac_mode |= MAC_MODE_HALF_DUPLEX;
+               else {
+                       lcl_adv = tg3_advert_flowctrl_1000T(
+                                 tp->link_config.flowctrl);
+
+                       if (phydev->pause)
+                               rmt_adv = LPA_PAUSE_CAP;
+                       if (phydev->asym_pause)
+                               rmt_adv |= LPA_PAUSE_ASYM;
+               }
+
+               tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
+       } else
+               mac_mode |= MAC_MODE_PORT_MODE_GMII;
+
+       if (mac_mode != tp->mac_mode) {
+               tp->mac_mode = mac_mode;
+               tw32_f(MAC_MODE, tp->mac_mode);
+               udelay(40);
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+               if (phydev->speed == SPEED_10)
+                       tw32(MAC_MI_STAT,
+                            MAC_MI_STAT_10MBPS_MODE |
+                            MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+               else
+                       tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+       }
+
+       if (phydev->speed == SPEED_1000 && phydev->duplex == DUPLEX_HALF)
+               tw32(MAC_TX_LENGTHS,
+                    ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+                     (6 << TX_LENGTHS_IPG_SHIFT) |
+                     (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)));
+       else
+               tw32(MAC_TX_LENGTHS,
+                    ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
+                     (6 << TX_LENGTHS_IPG_SHIFT) |
+                     (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
+
+       if ((phydev->link && tp->link_config.active_speed == SPEED_INVALID) ||
+           (!phydev->link && tp->link_config.active_speed != SPEED_INVALID) ||
+           phydev->speed != tp->link_config.active_speed ||
+           phydev->duplex != tp->link_config.active_duplex ||
+           oldflowctrl != tp->link_config.active_flowctrl)
+           linkmesg = 1;
+
+       tp->link_config.active_speed = phydev->speed;
+       tp->link_config.active_duplex = phydev->duplex;
+
+       spin_unlock(&tp->lock);
+
+       if (linkmesg)
+               tg3_link_report(tp);
+}
+
+static int tg3_phy_init(struct tg3 *tp)
+{
+       struct phy_device *phydev;
+
+       if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)
+               return 0;
+
+       /* Bring the PHY back to a known state. */
+       tg3_bmcr_reset(tp);
+
+       phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+
+       /* Attach the MAC to the PHY. */
+       phydev = phy_connect(tp->dev, dev_name(&phydev->dev), tg3_adjust_link,
+                            phydev->dev_flags, phydev->interface);
+       if (IS_ERR(phydev)) {
+               printk(KERN_ERR "%s: Could not attach to PHY\n", tp->dev->name);
+               return PTR_ERR(phydev);
+       }
+
+       /* Mask with MAC supported features. */
+       switch (phydev->interface) {
+       case PHY_INTERFACE_MODE_GMII:
+       case PHY_INTERFACE_MODE_RGMII:
+               if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
+                       phydev->supported &= (PHY_GBIT_FEATURES |
+                                             SUPPORTED_Pause |
+                                             SUPPORTED_Asym_Pause);
+                       break;
+               }
+               /* fallthru */
+       case PHY_INTERFACE_MODE_MII:
+               phydev->supported &= (PHY_BASIC_FEATURES |
+                                     SUPPORTED_Pause |
+                                     SUPPORTED_Asym_Pause);
+               break;
+       default:
+               phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]);
+               return -EINVAL;
+       }
+
+       tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED;
+
+       phydev->advertising = phydev->supported;
+
+       return 0;
+}
+
+static void tg3_phy_start(struct tg3 *tp)
+{
+       struct phy_device *phydev;
+
+       if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
+               return;
+
+       phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+
+       if (tp->link_config.phy_is_low_power) {
+               tp->link_config.phy_is_low_power = 0;
+               phydev->speed = tp->link_config.orig_speed;
+               phydev->duplex = tp->link_config.orig_duplex;
+               phydev->autoneg = tp->link_config.orig_autoneg;
+               phydev->advertising = tp->link_config.orig_advertising;
+       }
+
+       phy_start(phydev);
+
+       phy_start_aneg(phydev);
+}
+
+static void tg3_phy_stop(struct tg3 *tp)
+{
+       if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
+               return;
+
+       phy_stop(tp->mdio_bus->phy_map[PHY_ADDR]);
+}
+
+static void tg3_phy_fini(struct tg3 *tp)
+{
+       if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) {
+               phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]);
+               tp->tg3_flags3 &= ~TG3_FLG3_PHY_CONNECTED;
+       }
+}
+
+static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
+{
+       tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
+       tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
+}
+
+static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable)
+{
+       u32 reg;
+
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+               return;
+
+       reg = MII_TG3_MISC_SHDW_WREN |
+             MII_TG3_MISC_SHDW_SCR5_SEL |
+             MII_TG3_MISC_SHDW_SCR5_LPED |
+             MII_TG3_MISC_SHDW_SCR5_DLPTLM |
+             MII_TG3_MISC_SHDW_SCR5_SDTL |
+             MII_TG3_MISC_SHDW_SCR5_C125OE;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 || !enable)
+               reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD;
+
+       tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+
+
+       reg = MII_TG3_MISC_SHDW_WREN |
+             MII_TG3_MISC_SHDW_APD_SEL |
+             MII_TG3_MISC_SHDW_APD_WKTM_84MS;
+       if (enable)
+               reg |= MII_TG3_MISC_SHDW_APD_ENABLE;
+
+       tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+}
+
+static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
+{
+       u32 phy;
+
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+           (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
+               return;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               u32 ephy;
+
+               if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &ephy)) {
+                       tg3_writephy(tp, MII_TG3_EPHY_TEST,
+                                    ephy | MII_TG3_EPHY_SHADOW_EN);
+                       if (!tg3_readphy(tp, MII_TG3_EPHYTST_MISCCTRL, &phy)) {
+                               if (enable)
+                                       phy |= MII_TG3_EPHYTST_MISCCTRL_MDIX;
+                               else
+                                       phy &= ~MII_TG3_EPHYTST_MISCCTRL_MDIX;
+                               tg3_writephy(tp, MII_TG3_EPHYTST_MISCCTRL, phy);
+                       }
+                       tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy);
+               }
+       } else {
+               phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC |
+                     MII_TG3_AUXCTL_SHDWSEL_MISC;
+               if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) &&
+                   !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) {
+                       if (enable)
+                               phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+                       else
+                               phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+                       phy |= MII_TG3_AUXCTL_MISC_WREN;
+                       tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
+               }
+       }
+}
+
+static void tg3_phy_set_wirespeed(struct tg3 *tp)
+{
+       u32 val;
+
+       if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED)
+               return;
+
+       if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007) &&
+           !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val))
+               tg3_writephy(tp, MII_TG3_AUX_CTRL,
+                            (val | (1 << 15) | (1 << 4)));
+}
+
+static void tg3_phy_apply_otp(struct tg3 *tp)
+{
+       u32 otp, phy;
+
+       if (!tp->phy_otp)
+               return;
+
+       otp = tp->phy_otp;
+
+       /* Enable SM_DSP clock and tx 6dB coding. */
+       phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+             MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
+             MII_TG3_AUXCTL_ACTL_TX_6DB;
+       tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
+
+       phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT);
+       phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT;
+       tg3_phydsp_write(tp, MII_TG3_DSP_TAP1, phy);
+
+       phy = ((otp & TG3_OTP_HPFFLTR_MASK) >> TG3_OTP_HPFFLTR_SHIFT) |
+             ((otp & TG3_OTP_HPFOVER_MASK) >> TG3_OTP_HPFOVER_SHIFT);
+       tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH0, phy);
+
+       phy = ((otp & TG3_OTP_LPFDIS_MASK) >> TG3_OTP_LPFDIS_SHIFT);
+       phy |= MII_TG3_DSP_AADJ1CH3_ADCCKADJ;
+       tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH3, phy);
+
+       phy = ((otp & TG3_OTP_VDAC_MASK) >> TG3_OTP_VDAC_SHIFT);
+       tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, phy);
+
+       phy = ((otp & TG3_OTP_10BTAMP_MASK) >> TG3_OTP_10BTAMP_SHIFT);
+       tg3_phydsp_write(tp, MII_TG3_DSP_EXP96, phy);
+
+       phy = ((otp & TG3_OTP_ROFF_MASK) >> TG3_OTP_ROFF_SHIFT) |
+             ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);
+       tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy);
+
+       /* Turn off SM_DSP clock. */
+       phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+             MII_TG3_AUXCTL_ACTL_TX_6DB;
+       tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
+}
+
+static int tg3_wait_macro_done(struct tg3 *tp)
+{
+       int limit = 100;
+
+       while (limit--) {
+               u32 tmp32;
+
+               if (!tg3_readphy(tp, 0x16, &tmp32)) {
+                       if ((tmp32 & 0x1000) == 0)
+                               break;
+               }
+       }
+       if (limit <= 0)
+               return -EBUSY;
+
+       return 0;
+}
+
+static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
+{
+       static const u32 test_pat[4][6] = {
+       { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
+       { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
+       { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
+       { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
+       };
+       int chan;
+
+       for (chan = 0; chan < 4; chan++) {
+               int i;
+
+               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+                            (chan * 0x2000) | 0x0200);
+               tg3_writephy(tp, 0x16, 0x0002);
+
+               for (i = 0; i < 6; i++)
+                       tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
+                                    test_pat[chan][i]);
+
+               tg3_writephy(tp, 0x16, 0x0202);
+               if (tg3_wait_macro_done(tp)) {
+                       *resetp = 1;
+                       return -EBUSY;
+               }
+
+               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+                            (chan * 0x2000) | 0x0200);
+               tg3_writephy(tp, 0x16, 0x0082);
+               if (tg3_wait_macro_done(tp)) {
+                       *resetp = 1;
+                       return -EBUSY;
+               }
+
+               tg3_writephy(tp, 0x16, 0x0802);
+               if (tg3_wait_macro_done(tp)) {
+                       *resetp = 1;
+                       return -EBUSY;
+               }
+
+               for (i = 0; i < 6; i += 2) {
+                       u32 low, high;
+
+                       if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) ||
+                           tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) ||
+                           tg3_wait_macro_done(tp)) {
+                               *resetp = 1;
+                               return -EBUSY;
+                       }
+                       low &= 0x7fff;
+                       high &= 0x000f;
+                       if (low != test_pat[chan][i] ||
+                           high != test_pat[chan][i+1]) {
+                               tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
+                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
+                               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
+
+                               return -EBUSY;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int tg3_phy_reset_chanpat(struct tg3 *tp)
+{
+       int chan;
+
+       for (chan = 0; chan < 4; chan++) {
+               int i;
+
+               tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
+                            (chan * 0x2000) | 0x0200);
+               tg3_writephy(tp, 0x16, 0x0002);
+               for (i = 0; i < 6; i++)
+                       tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
+               tg3_writephy(tp, 0x16, 0x0202);
+               if (tg3_wait_macro_done(tp))
+                       return -EBUSY;
+       }
+
+       return 0;
+}
+
+static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
+{
+       u32 reg32, phy9_orig;
+       int retries, do_phy_reset, err;
+
+       retries = 10;
+       do_phy_reset = 1;
+       do {
+               if (do_phy_reset) {
+                       err = tg3_bmcr_reset(tp);
+                       if (err)
+                               return err;
+                       do_phy_reset = 0;
+               }
+
+               /* Disable transmitter and interrupt.  */
+               if (tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32))
+                       continue;
+
+               reg32 |= 0x3000;
+               tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+
+               /* Set full-duplex, 1000 mbps.  */
+               tg3_writephy(tp, MII_BMCR,
+                            BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
+
+               /* Set to master mode.  */
+               if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
+                       continue;
+
+               tg3_writephy(tp, MII_TG3_CTRL,
+                            (MII_TG3_CTRL_AS_MASTER |
+                             MII_TG3_CTRL_ENABLE_AS_MASTER));
+
+               /* Enable SM_DSP_CLOCK and 6dB.  */
+               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+
+               /* Block the PHY control access.  */
+               tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
+               tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800);
+
+               err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
+               if (!err)
+                       break;
+       } while (--retries);
+
+       err = tg3_phy_reset_chanpat(tp);
+       if (err)
+               return err;
+
+       tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
+       tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000);
+
+       tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
+       tg3_writephy(tp, 0x16, 0x0000);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+               /* Set Extended packet length bit for jumbo frames */
+               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4400);
+       }
+       else {
+               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+       }
+
+       tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
+
+       if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
+               reg32 &= ~0x3000;
+               tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+       } else if (!err)
+               err = -EBUSY;
+
+       return err;
+}
+
+/* This will reset the tigon3 PHY if there is no valid
+ * link unless the FORCE argument is non-zero.
+ */
+static int tg3_phy_reset(struct tg3 *tp)
+{
+       u32 cpmuctrl;
+       u32 phy_status;
+       int err;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+               u32 val;
+
+               val = tr32(GRC_MISC_CFG);
+               tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
+               udelay(40);
+       }
+       err  = tg3_readphy(tp, MII_BMSR, &phy_status);
+       err |= tg3_readphy(tp, MII_BMSR, &phy_status);
+       if (err != 0)
                return -EBUSY;
 
        if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) {
@@ -1102,11 +1806,30 @@ static int tg3_phy_reset(struct tg3 *tp)
                goto out;
        }
 
+       cpmuctrl = 0;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+           GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
+               cpmuctrl = tr32(TG3_CPMU_CTRL);
+               if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY)
+                       tw32(TG3_CPMU_CTRL,
+                            cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY);
+       }
+
        err = tg3_bmcr_reset(tp);
        if (err)
                return err;
 
-       if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+       if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) {
+               u32 phy;
+
+               phy = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
+               tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, phy);
+
+               tw32(TG3_CPMU_CTRL, cpmuctrl);
+       }
+
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+           GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
                u32 val;
 
                val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
@@ -1116,14 +1839,15 @@ static int tg3_phy_reset(struct tg3 *tp)
                        udelay(40);
                        tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
                }
-
-               /* Disable GPHY autopowerdown. */
-               tg3_writephy(tp, MII_TG3_MISC_SHDW,
-                            MII_TG3_MISC_SHDW_WREN |
-                            MII_TG3_MISC_SHDW_APD_SEL |
-                            MII_TG3_MISC_SHDW_APD_WKTM_84MS);
        }
 
+       tg3_phy_apply_otp(tp);
+
+       if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
+               tg3_phy_toggle_apd(tp, true);
+       else
+               tg3_phy_toggle_apd(tp, false);
+
 out:
        if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
                tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
@@ -1225,6 +1949,21 @@ static void tg3_frob_aux_power(struct tg3 *tp)
                                     GRC_LCLCTRL_GPIO_OUTPUT0 |
                                     GRC_LCLCTRL_GPIO_OUTPUT1),
                                    100);
+               } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) {
+                       /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */
+                       u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
+                                            GRC_LCLCTRL_GPIO_OE1 |
+                                            GRC_LCLCTRL_GPIO_OE2 |
+                                            GRC_LCLCTRL_GPIO_OUTPUT0 |
+                                            GRC_LCLCTRL_GPIO_OUTPUT1 |
+                                            tp->grc_local_ctrl;
+                       tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
+
+                       grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2;
+                       tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
+
+                       grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0;
+                       tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100);
                } else {
                        u32 no_gpio2;
                        u32 grc_local_ctrl = 0;
@@ -1313,7 +2052,7 @@ static int tg3_halt_cpu(struct tg3 *, u32);
 static int tg3_nvram_lock(struct tg3 *);
 static void tg3_nvram_unlock(struct tg3 *);
 
-static void tg3_power_down_phy(struct tg3 *tp)
+static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
 {
        u32 val;
 
@@ -1336,10 +2075,15 @@ static void tg3_power_down_phy(struct tg3 *tp)
                tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
                udelay(40);
                return;
-       } else {
+       } else if (do_low_power) {
                tg3_writephy(tp, MII_TG3_EXT_CTRL,
                             MII_TG3_EXT_CTRL_FORCE_LED_OFF);
-               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
+
+               tg3_writephy(tp, MII_TG3_AUX_CTRL,
+                            MII_TG3_AUXCTL_SHDWSEL_PWRCTL |
+                            MII_TG3_AUXCTL_PCTL_100TX_LPWR |
+                            MII_TG3_AUXCTL_PCTL_SPR_ISOLATE |
+                            MII_TG3_AUXCTL_PCTL_VREG_11V);
        }
 
        /* The PHY should not be powered down on some chips because
@@ -1351,7 +2095,8 @@ static void tg3_power_down_phy(struct tg3 *tp)
             (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
                return;
 
-       if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+           GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
                val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
                val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
                val |= CPMU_LSPD_1000MB_MACCLK_12_5;
@@ -1361,11 +2106,47 @@ static void tg3_power_down_phy(struct tg3 *tp)
        tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
 }
 
+/* tp->lock is held. */
+static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
+{
+       u32 addr_high, addr_low;
+       int i;
+
+       addr_high = ((tp->dev->dev_addr[0] << 8) |
+                    tp->dev->dev_addr[1]);
+       addr_low = ((tp->dev->dev_addr[2] << 24) |
+                   (tp->dev->dev_addr[3] << 16) |
+                   (tp->dev->dev_addr[4] <<  8) |
+                   (tp->dev->dev_addr[5] <<  0));
+       for (i = 0; i < 4; i++) {
+               if (i == 1 && skip_mac_1)
+                       continue;
+               tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
+               tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+               for (i = 0; i < 12; i++) {
+                       tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
+                       tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
+               }
+       }
+
+       addr_high = (tp->dev->dev_addr[0] +
+                    tp->dev->dev_addr[1] +
+                    tp->dev->dev_addr[2] +
+                    tp->dev->dev_addr[3] +
+                    tp->dev->dev_addr[4] +
+                    tp->dev->dev_addr[5]) &
+               TX_BACKOFF_SEED_MASK;
+       tw32(MAC_TX_BACKOFF_SEED, addr_high);
+}
+
 static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
 {
        u32 misc_host_ctrl;
-       u16 power_control, power_caps;
-       int pm = tp->pm_cap;
+       bool device_should_wake, do_low_power;
 
        /* Make sure register accesses (indirect or otherwise)
         * will function correctly.
@@ -1374,18 +2155,10 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                               TG3PCI_MISC_HOST_CTRL,
                               tp->misc_host_ctrl);
 
-       pci_read_config_word(tp->pdev,
-                            pm + PCI_PM_CTRL,
-                            &power_control);
-       power_control |= PCI_PM_CTRL_PME_STATUS;
-       power_control &= ~(PCI_PM_CTRL_STATE_MASK);
        switch (state) {
        case PCI_D0:
-               power_control |= 0;
-               pci_write_config_word(tp->pdev,
-                                     pm + PCI_PM_CTRL,
-                                     power_control);
-               udelay(100);    /* Delay after power state change */
+               pci_enable_wake(tp->pdev, state, false);
+               pci_set_power_state(tp->pdev, PCI_D0);
 
                /* Switch out of Vaux if it is a NIC */
                if (tp->tg3_flags2 & TG3_FLG2_IS_NIC)
@@ -1394,44 +2167,102 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                return 0;
 
        case PCI_D1:
-               power_control |= 1;
-               break;
-
        case PCI_D2:
-               power_control |= 2;
-               break;
-
        case PCI_D3hot:
-               power_control |= 3;
                break;
 
        default:
-               printk(KERN_WARNING PFX "%s: Invalid power state (%d) "
-                      "requested.\n",
-                      tp->dev->name, state);
+               printk(KERN_ERR PFX "%s: Invalid power state (D%d) requested\n",
+                       tp->dev->name, state);
                return -EINVAL;
-       };
+       }
 
-       power_control |= PCI_PM_CTRL_PME_ENABLE;
+       /* Restore the CLKREQ setting. */
+       if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
+               u16 lnkctl;
+
+               pci_read_config_word(tp->pdev,
+                                    tp->pcie_cap + PCI_EXP_LNKCTL,
+                                    &lnkctl);
+               lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
+               pci_write_config_word(tp->pdev,
+                                     tp->pcie_cap + PCI_EXP_LNKCTL,
+                                     lnkctl);
+       }
 
        misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
        tw32(TG3PCI_MISC_HOST_CTRL,
             misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
 
-       if (tp->link_config.phy_is_low_power == 0) {
-               tp->link_config.phy_is_low_power = 1;
-               tp->link_config.orig_speed = tp->link_config.speed;
-               tp->link_config.orig_duplex = tp->link_config.duplex;
-               tp->link_config.orig_autoneg = tp->link_config.autoneg;
-       }
+       device_should_wake = pci_pme_capable(tp->pdev, state) &&
+                            device_may_wakeup(&tp->pdev->dev) &&
+                            (tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
+
+       if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+               do_low_power = false;
+               if ((tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) &&
+                   !tp->link_config.phy_is_low_power) {
+                       struct phy_device *phydev;
+                       u32 phyid, advertising;
+
+                       phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+
+                       tp->link_config.phy_is_low_power = 1;
+
+                       tp->link_config.orig_speed = phydev->speed;
+                       tp->link_config.orig_duplex = phydev->duplex;
+                       tp->link_config.orig_autoneg = phydev->autoneg;
+                       tp->link_config.orig_advertising = phydev->advertising;
+
+                       advertising = ADVERTISED_TP |
+                                     ADVERTISED_Pause |
+                                     ADVERTISED_Autoneg |
+                                     ADVERTISED_10baseT_Half;
+
+                       if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+                           device_should_wake) {
+                               if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB)
+                                       advertising |=
+                                               ADVERTISED_100baseT_Half |
+                                               ADVERTISED_100baseT_Full |
+                                               ADVERTISED_10baseT_Full;
+                               else
+                                       advertising |= ADVERTISED_10baseT_Full;
+                       }
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) {
-               tp->link_config.speed = SPEED_10;
-               tp->link_config.duplex = DUPLEX_HALF;
-               tp->link_config.autoneg = AUTONEG_ENABLE;
-               tg3_setup_phy(tp, 0);
+                       phydev->advertising = advertising;
+
+                       phy_start_aneg(phydev);
+
+                       phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
+                       if (phyid != TG3_PHY_ID_BCMAC131) {
+                               phyid &= TG3_PHY_OUI_MASK;
+                               if (phyid == TG3_PHY_OUI_1 &&
+                                   phyid == TG3_PHY_OUI_2 &&
+                                   phyid == TG3_PHY_OUI_3)
+                                       do_low_power = true;
+                       }
+               }
+       } else {
+               do_low_power = true;
+
+               if (tp->link_config.phy_is_low_power == 0) {
+                       tp->link_config.phy_is_low_power = 1;
+                       tp->link_config.orig_speed = tp->link_config.speed;
+                       tp->link_config.orig_duplex = tp->link_config.duplex;
+                       tp->link_config.orig_autoneg = tp->link_config.autoneg;
+               }
+
+               if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) {
+                       tp->link_config.speed = SPEED_10;
+                       tp->link_config.duplex = DUPLEX_HALF;
+                       tp->link_config.autoneg = AUTONEG_ENABLE;
+                       tg3_setup_phy(tp, 0);
+               }
        }
 
+       __tg3_set_mac_addr(tp, 0);
+
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                u32 val;
 
@@ -1454,14 +2285,14 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                                                     WOL_DRV_WOL |
                                                     WOL_SET_MAGIC_PKT);
 
-       pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
-
-       if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
+       if (device_should_wake) {
                u32 mac_mode;
 
                if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
-                       tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
-                       udelay(40);
+                       if (do_low_power) {
+                               tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
+                               udelay(40);
+                       }
 
                        if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
                                mac_mode = MAC_MODE_PORT_MODE_GMII;
@@ -1486,9 +2317,19 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
                        tw32(MAC_LED_CTRL, tp->led_ctrl);
 
-               if (((power_caps & PCI_PM_CAP_PME_D3cold) &&
-                    (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)))
-                       mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
+               mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
+               if (((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+                   !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) &&
+                   ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+                    (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)))
+                       mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL;
+
+               if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+                       mac_mode |= tp->mac_mode &
+                                   (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
+                       if (mac_mode & MAC_MODE_APE_TX_EN)
+                               mac_mode |= MAC_MODE_TDE_ENABLE;
+               }
 
                tw32_f(MAC_MODE, mac_mode);
                udelay(100);
@@ -1522,208 +2363,69 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                                    CLOCK_CTRL_TXCLK_DISABLE |
                                    CLOCK_CTRL_ALTCLK);
                        newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
-               } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
-                       newbits1 = CLOCK_CTRL_625_CORE;
-                       newbits2 = newbits1 | CLOCK_CTRL_ALTCLK;
-               } else {
-                       newbits1 = CLOCK_CTRL_ALTCLK;
-                       newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
-               }
-
-               tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1,
-                           40);
-
-               tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2,
-                           40);
-
-               if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
-                       u32 newbits3;
-
-                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
-                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
-                               newbits3 = (CLOCK_CTRL_RXCLK_DISABLE |
-                                           CLOCK_CTRL_TXCLK_DISABLE |
-                                           CLOCK_CTRL_44MHZ_CORE);
-                       } else {
-                               newbits3 = CLOCK_CTRL_44MHZ_CORE;
-                       }
-
-                       tw32_wait_f(TG3PCI_CLOCK_CTRL,
-                                   tp->pci_clock_ctrl | newbits3, 40);
-               }
-       }
-
-       if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
-           !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
-           !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
-               tg3_power_down_phy(tp);
-
-       tg3_frob_aux_power(tp);
-
-       /* Workaround for unstable PLL clock */
-       if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
-           (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) {
-               u32 val = tr32(0x7d00);
-
-               val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
-               tw32(0x7d00, val);
-               if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
-                       int err;
-
-                       err = tg3_nvram_lock(tp);
-                       tg3_halt_cpu(tp, RX_CPU_BASE);
-                       if (!err)
-                               tg3_nvram_unlock(tp);
-               }
-       }
-
-       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
-
-       /* Finally, set the new power state. */
-       pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
-       udelay(100);    /* Delay after power state change */
-
-       return 0;
-}
-
-static void tg3_link_report(struct tg3 *tp)
-{
-       if (!netif_carrier_ok(tp->dev)) {
-               if (netif_msg_link(tp))
-                       printk(KERN_INFO PFX "%s: Link is down.\n",
-                              tp->dev->name);
-       } else if (netif_msg_link(tp)) {
-               printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n",
-                      tp->dev->name,
-                      (tp->link_config.active_speed == SPEED_1000 ?
-                       1000 :
-                       (tp->link_config.active_speed == SPEED_100 ?
-                        100 : 10)),
-                      (tp->link_config.active_duplex == DUPLEX_FULL ?
-                       "full" : "half"));
-
-               printk(KERN_INFO PFX
-                      "%s: Flow control is %s for TX and %s for RX.\n",
-                      tp->dev->name,
-                      (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) ?
-                      "on" : "off",
-                      (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) ?
-                      "on" : "off");
-       }
-}
-
-static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
-{
-       u16 miireg;
-
-       if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
-               miireg = ADVERTISE_PAUSE_CAP;
-       else if (flow_ctrl & TG3_FLOW_CTRL_TX)
-               miireg = ADVERTISE_PAUSE_ASYM;
-       else if (flow_ctrl & TG3_FLOW_CTRL_RX)
-               miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
-       else
-               miireg = 0;
-
-       return miireg;
-}
-
-static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
-{
-       u16 miireg;
-
-       if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
-               miireg = ADVERTISE_1000XPAUSE;
-       else if (flow_ctrl & TG3_FLOW_CTRL_TX)
-               miireg = ADVERTISE_1000XPSE_ASYM;
-       else if (flow_ctrl & TG3_FLOW_CTRL_RX)
-               miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
-       else
-               miireg = 0;
-
-       return miireg;
-}
-
-static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv)
-{
-       u8 cap = 0;
-
-       if (lcladv & ADVERTISE_PAUSE_CAP) {
-               if (lcladv & ADVERTISE_PAUSE_ASYM) {
-                       if (rmtadv & LPA_PAUSE_CAP)
-                               cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
-                       else if (rmtadv & LPA_PAUSE_ASYM)
-                               cap = TG3_FLOW_CTRL_RX;
+               } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
+                       newbits1 = CLOCK_CTRL_625_CORE;
+                       newbits2 = newbits1 | CLOCK_CTRL_ALTCLK;
                } else {
-                       if (rmtadv & LPA_PAUSE_CAP)
-                               cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+                       newbits1 = CLOCK_CTRL_ALTCLK;
+                       newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
                }
-       } else if (lcladv & ADVERTISE_PAUSE_ASYM) {
-               if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
-                       cap = TG3_FLOW_CTRL_TX;
-       }
 
-       return cap;
-}
+               tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1,
+                           40);
 
-static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
-{
-       u8 cap = 0;
+               tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2,
+                           40);
 
-       if (lcladv & ADVERTISE_1000XPAUSE) {
-               if (lcladv & ADVERTISE_1000XPSE_ASYM) {
-                       if (rmtadv & LPA_1000XPAUSE)
-                               cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
-                       else if (rmtadv & LPA_1000XPAUSE_ASYM)
-                               cap = TG3_FLOW_CTRL_RX;
-               } else {
-                       if (rmtadv & LPA_1000XPAUSE)
-                               cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+               if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+                       u32 newbits3;
+
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+                               newbits3 = (CLOCK_CTRL_RXCLK_DISABLE |
+                                           CLOCK_CTRL_TXCLK_DISABLE |
+                                           CLOCK_CTRL_44MHZ_CORE);
+                       } else {
+                               newbits3 = CLOCK_CTRL_44MHZ_CORE;
+                       }
+
+                       tw32_wait_f(TG3PCI_CLOCK_CTRL,
+                                   tp->pci_clock_ctrl | newbits3, 40);
                }
-       } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
-               if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
-                       cap = TG3_FLOW_CTRL_TX;
        }
 
-       return cap;
-}
-
-static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv)
-{
-       u8 new_tg3_flags = 0;
-       u32 old_rx_mode = tp->rx_mode;
-       u32 old_tx_mode = tp->tx_mode;
+       if (!(device_should_wake) &&
+           !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+               tg3_power_down_phy(tp, do_low_power);
 
-       if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
-               if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
-                       new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv,
-                                                                  remote_adv);
-               else
-                       new_tg3_flags = tg3_resolve_flowctrl_1000T(local_adv,
-                                                                  remote_adv);
-       } else {
-               new_tg3_flags = tp->link_config.flowctrl;
-       }
+       tg3_frob_aux_power(tp);
 
-       tp->link_config.active_flowctrl = new_tg3_flags;
+       /* Workaround for unstable PLL clock */
+       if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
+           (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) {
+               u32 val = tr32(0x7d00);
 
-       if (new_tg3_flags & TG3_FLOW_CTRL_RX)
-               tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
-       else
-               tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
+               val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
+               tw32(0x7d00, val);
+               if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
+                       int err;
 
-       if (old_rx_mode != tp->rx_mode) {
-               tw32_f(MAC_RX_MODE, tp->rx_mode);
+                       err = tg3_nvram_lock(tp);
+                       tg3_halt_cpu(tp, RX_CPU_BASE);
+                       if (!err)
+                               tg3_nvram_unlock(tp);
+               }
        }
 
-       if (new_tg3_flags & TG3_FLOW_CTRL_TX)
-               tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
-       else
-               tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
+       tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
 
-       if (old_tx_mode != tp->tx_mode) {
-               tw32_f(MAC_TX_MODE, tp->tx_mode);
-       }
+       if (device_should_wake)
+               pci_enable_wake(tp->pdev, state, true);
+
+       /* Finally, set the new power state. */
+       pci_set_power_state(tp->pdev, state);
+
+       return 0;
 }
 
 static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
@@ -1770,7 +2472,7 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8
                *speed = SPEED_INVALID;
                *duplex = DUPLEX_INVALID;
                break;
-       };
+       }
 }
 
 static void tg3_phy_copper_begin(struct tg3 *tp)
@@ -1882,7 +2584,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                case SPEED_1000:
                        bmcr |= TG3_BMCR_SPEED1000;
                        break;
-               };
+               }
 
                if (tp->link_config.duplex == DUPLEX_FULL)
                        bmcr |= BMCR_FULLDPLX;
@@ -1975,10 +2677,44 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
        return 1;
 }
 
+static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv)
+{
+       u32 curadv, reqadv;
+
+       if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
+               return 1;
+
+       curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+       reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+
+       if (tp->link_config.active_duplex == DUPLEX_FULL) {
+               if (curadv != reqadv)
+                       return 0;
+
+               if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)
+                       tg3_readphy(tp, MII_LPA, rmtadv);
+       } else {
+               /* Reprogram the advertisement register, even if it
+                * does not affect the current link.  If the link
+                * gets renegotiated in the future, we can save an
+                * additional renegotiation cycle by advertising
+                * it correctly in the first place.
+                */
+               if (curadv != reqadv) {
+                       *lcladv &= ~(ADVERTISE_PAUSE_CAP |
+                                    ADVERTISE_PAUSE_ASYM);
+                       tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv);
+               }
+       }
+
+       return 1;
+}
+
 static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
        int current_link_up;
        u32 bmsr, dummy;
+       u32 lcl_adv, rmt_adv;
        u16 current_speed;
        u8 current_duplex;
        int i, err;
@@ -1992,9 +2728,11 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
              MAC_STATUS_LNKSTATE_CHANGED));
        udelay(40);
 
-       tp->mi_mode = MAC_MI_MODE_BASE;
-       tw32_f(MAC_MI_MODE, tp->mi_mode);
-       udelay(80);
+       if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
+               tw32_f(MAC_MI_MODE,
+                    (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
+               udelay(80);
+       }
 
        tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
 
@@ -2121,54 +2859,35 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
                        udelay(10);
                }
 
-               if (tp->link_config.autoneg == AUTONEG_ENABLE) {
-                       if (bmcr & BMCR_ANENABLE) {
-                               current_link_up = 1;
+               lcl_adv = 0;
+               rmt_adv = 0;
 
-                               /* Force autoneg restart if we are exiting
-                                * low power mode.
-                                */
-                               if (!tg3_copper_is_advertising_all(tp,
-                                               tp->link_config.advertising))
-                                       current_link_up = 0;
-                       } else {
-                               current_link_up = 0;
+               tp->link_config.active_speed = current_speed;
+               tp->link_config.active_duplex = current_duplex;
+
+               if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+                       if ((bmcr & BMCR_ANENABLE) &&
+                           tg3_copper_is_advertising_all(tp,
+                                               tp->link_config.advertising)) {
+                               if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv,
+                                                                 &rmt_adv))
+                                       current_link_up = 1;
                        }
                } else {
                        if (!(bmcr & BMCR_ANENABLE) &&
                            tp->link_config.speed == current_speed &&
-                           tp->link_config.duplex == current_duplex) {
+                           tp->link_config.duplex == current_duplex &&
+                           tp->link_config.flowctrl ==
+                           tp->link_config.active_flowctrl) {
                                current_link_up = 1;
-                       } else {
-                               current_link_up = 0;
                        }
                }
 
-               tp->link_config.active_speed = current_speed;
-               tp->link_config.active_duplex = current_duplex;
+               if (current_link_up == 1 &&
+                   tp->link_config.active_duplex == DUPLEX_FULL)
+                       tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
        }
 
-       if (current_link_up == 1 &&
-           (tp->link_config.active_duplex == DUPLEX_FULL) &&
-           (tp->link_config.autoneg == AUTONEG_ENABLE)) {
-               u32 local_adv, remote_adv;
-
-               if (tg3_readphy(tp, MII_ADVERTISE, &local_adv))
-                       local_adv = 0;
-
-               if (tg3_readphy(tp, MII_LPA, &remote_adv))
-                       remote_adv = 0;
-
-               /* If we are not advertising what has been requested,
-                * bring the link down and reconfigure.
-                */
-               if (local_adv !=
-                   tg3_advert_flowctrl_1000T(tp->link_config.flowctrl)) {
-                       current_link_up = 0;
-               } else {
-                       tg3_setup_flow_control(tp, local_adv, remote_adv);
-               }
-       }
 relink:
        if (current_link_up == 0 || tp->link_config.phy_is_low_power) {
                u32 tmp;
@@ -2239,6 +2958,24 @@ relink:
                              NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
        }
 
+       /* Prevent send BD corruption. */
+       if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
+               u16 oldlnkctl, newlnkctl;
+
+               pci_read_config_word(tp->pdev,
+                                    tp->pcie_cap + PCI_EXP_LNKCTL,
+                                    &oldlnkctl);
+               if (tp->link_config.active_speed == SPEED_100 ||
+                   tp->link_config.active_speed == SPEED_10)
+                       newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
+               else
+                       newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
+               if (newlnkctl != oldlnkctl)
+                       pci_write_config_word(tp->pdev,
+                                             tp->pcie_cap + PCI_EXP_LNKCTL,
+                                             newlnkctl);
+       }
+
        if (current_link_up != netif_carrier_ok(tp->dev)) {
                if (current_link_up)
                        netif_carrier_on(tp->dev);
@@ -2317,6 +3054,7 @@ struct tg3_fiber_aneginfo {
 static int tg3_fiber_aneg_smachine(struct tg3 *tp,
                                   struct tg3_fiber_aneginfo *ap)
 {
+       u16 flowctrl;
        unsigned long delta;
        u32 rx_cfg_reg;
        int ret;
@@ -2416,7 +3154,12 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
 
        case ANEG_STATE_ABILITY_DETECT_INIT:
                ap->flags &= ~(MR_TOGGLE_TX);
-               ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);
+               ap->txconfig = ANEG_CFG_FD;
+               flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
+               if (flowctrl & ADVERTISE_1000XPAUSE)
+                       ap->txconfig |= ANEG_CFG_PS1;
+               if (flowctrl & ADVERTISE_1000XPSE_ASYM)
+                       ap->txconfig |= ANEG_CFG_PS2;
                tw32(MAC_TX_AUTO_NEG, ap->txconfig);
                tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
                tw32_f(MAC_MODE, tp->mac_mode);
@@ -2557,12 +3300,12 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
        default:
                ret = ANEG_FAILED;
                break;
-       };
+       }
 
        return ret;
 }
 
-static int fiber_autoneg(struct tg3 *tp, u32 *flags)
+static int fiber_autoneg(struct tg3 *tp, u32 *txflags, u32 *rxflags)
 {
        int res = 0;
        struct tg3_fiber_aneginfo aninfo;
@@ -2596,7 +3339,8 @@ static int fiber_autoneg(struct tg3 *tp, u32 *flags)
        tw32_f(MAC_MODE, tp->mac_mode);
        udelay(40);
 
-       *flags = aninfo.flags;
+       *txflags = aninfo.txconfig;
+       *rxflags = aninfo.flags;
 
        if (status == ANEG_DONE &&
            (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
@@ -2658,6 +3402,7 @@ static void tg3_init_bcm8002(struct tg3 *tp)
 
 static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
 {
+       u16 flowctrl;
        u32 sg_dig_ctrl, sg_dig_status;
        u32 serdes_cfg, expected_sg_dig_ctrl;
        int workaround, port_a;
@@ -2706,11 +3451,11 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
        /* Want auto-negotiation.  */
        expected_sg_dig_ctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_COMMON_SETUP;
 
-       /* Pause capability */
-       expected_sg_dig_ctrl |= SG_DIG_PAUSE_CAP;
-
-       /* Asymettric pause */
-       expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE;
+       flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
+       if (flowctrl & ADVERTISE_1000XPAUSE)
+               expected_sg_dig_ctrl |= SG_DIG_PAUSE_CAP;
+       if (flowctrl & ADVERTISE_1000XPSE_ASYM)
+               expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE;
 
        if (sg_dig_ctrl != expected_sg_dig_ctrl) {
                if ((tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) &&
@@ -2738,14 +3483,17 @@ restart_autoneg:
 
                if ((sg_dig_status & SG_DIG_AUTONEG_COMPLETE) &&
                    (mac_status & MAC_STATUS_PCS_SYNCED)) {
-                       u32 local_adv, remote_adv;
+                       u32 local_adv = 0, remote_adv = 0;
+
+                       if (sg_dig_ctrl & SG_DIG_PAUSE_CAP)
+                               local_adv |= ADVERTISE_1000XPAUSE;
+                       if (sg_dig_ctrl & SG_DIG_ASYM_PAUSE)
+                               local_adv |= ADVERTISE_1000XPSE_ASYM;
 
-                       local_adv = ADVERTISE_PAUSE_CAP;
-                       remote_adv = 0;
                        if (sg_dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
-                               remote_adv |= LPA_PAUSE_CAP;
+                               remote_adv |= LPA_1000XPAUSE;
                        if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
-                               remote_adv |= LPA_PAUSE_ASYM;
+                               remote_adv |= LPA_1000XPAUSE_ASYM;
 
                        tg3_setup_flow_control(tp, local_adv, remote_adv);
                        current_link_up = 1;
@@ -2802,18 +3550,21 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
                goto out;
 
        if (tp->link_config.autoneg == AUTONEG_ENABLE) {
-               u32 flags;
+               u32 txflags, rxflags;
                int i;
 
-               if (fiber_autoneg(tp, &flags)) {
-                       u32 local_adv, remote_adv;
+               if (fiber_autoneg(tp, &txflags, &rxflags)) {
+                       u32 local_adv = 0, remote_adv = 0;
+
+                       if (txflags & ANEG_CFG_PS1)
+                               local_adv |= ADVERTISE_1000XPAUSE;
+                       if (txflags & ANEG_CFG_PS2)
+                               local_adv |= ADVERTISE_1000XPSE_ASYM;
 
-                       local_adv = ADVERTISE_PAUSE_CAP;
-                       remote_adv = 0;
-                       if (flags & MR_LP_ADV_SYM_PAUSE)
-                               remote_adv |= LPA_PAUSE_CAP;
-                       if (flags & MR_LP_ADV_ASYM_PAUSE)
-                               remote_adv |= LPA_PAUSE_ASYM;
+                       if (rxflags & MR_LP_ADV_SYM_PAUSE)
+                               remote_adv |= LPA_1000XPAUSE;
+                       if (rxflags & MR_LP_ADV_ASYM_PAUSE)
+                               remote_adv |= LPA_1000XPAUSE_ASYM;
 
                        tg3_setup_flow_control(tp, local_adv, remote_adv);
 
@@ -2837,6 +3588,8 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
                    !(mac_status & MAC_STATUS_RCVD_CFG))
                        current_link_up = 1;
        } else {
+               tg3_setup_flow_control(tp, 0, 0);
+
                /* Forcing 1000FD link up. */
                current_link_up = 1;
 
@@ -2965,6 +3718,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
        u32 bmsr, bmcr;
        u16 current_speed;
        u8 current_duplex;
+       u32 local_adv, remote_adv;
 
        tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
        tw32_f(MAC_MODE, tp->mac_mode);
@@ -3080,8 +3834,11 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                else
                        current_duplex = DUPLEX_HALF;
 
+               local_adv = 0;
+               remote_adv = 0;
+
                if (bmcr & BMCR_ANENABLE) {
-                       u32 local_adv, remote_adv, common;
+                       u32 common;
 
                        err |= tg3_readphy(tp, MII_ADVERTISE, &local_adv);
                        err |= tg3_readphy(tp, MII_LPA, &remote_adv);
@@ -3092,15 +3849,15 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                                        current_duplex = DUPLEX_FULL;
                                else
                                        current_duplex = DUPLEX_HALF;
-
-                               tg3_setup_flow_control(tp, local_adv,
-                                                      remote_adv);
                        }
                        else
                                current_link_up = 0;
                }
        }
 
+       if (current_link_up == 1 && current_duplex == DUPLEX_FULL)
+               tg3_setup_flow_control(tp, local_adv, remote_adv);
+
        tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
        if (tp->link_config.active_duplex == DUPLEX_HALF)
                tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
@@ -3195,8 +3952,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
                err = tg3_setup_copper_phy(tp, force_reset);
        }
 
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-           tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) {
                u32 val, scale;
 
                val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
@@ -3293,10 +4049,7 @@ static void tg3_tx(struct tg3 *tp)
                        return;
                }
 
-               pci_unmap_single(tp->pdev,
-                                pci_unmap_addr(ri, mapping),
-                                skb_headlen(skb),
-                                PCI_DMA_TODEVICE);
+               skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
 
                ri->skb = NULL;
 
@@ -3306,12 +4059,6 @@ static void tg3_tx(struct tg3 *tp)
                        ri = &tp->tx_buffers[sw_idx];
                        if (unlikely(ri->skb != NULL || sw_idx == hw_idx))
                                tx_bug = 1;
-
-                       pci_unmap_page(tp->pdev,
-                                      pci_unmap_addr(ri, mapping),
-                                      skb_shinfo(skb)->frags[i].size,
-                                      PCI_DMA_TODEVICE);
-
                        sw_idx = NEXT_TX(sw_idx);
                }
 
@@ -3384,7 +4131,7 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key,
 
        default:
                return -EINVAL;
-       };
+       }
 
        /* Do not overwrite any of the map or rp information
         * until we are sure we can commit to a new buffer.
@@ -3444,7 +4191,7 @@ static void tg3_recycle_rx(struct tg3 *tp, u32 opaque_key,
 
        default:
                return;
-       };
+       }
 
        dest_map->skb = src_map->skb;
        pci_unmap_addr_set(dest_map, mapping,
@@ -3539,12 +4286,15 @@ static int tg3_rx(struct tg3 *tp, int budget)
                        goto next_pkt;
                }
 
-               len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */
+               len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) -
+                     ETH_FCS_LEN;
 
                if (len > RX_COPY_THRESHOLD
-                       && tp->rx_offset == 2
-                       /* rx_offset != 2 iff this is a 5701 card running
-                        * in PCI-X mode [see tg3_get_invariants()] */
+                       && tp->rx_offset == NET_IP_ALIGN
+                       /* rx_offset will likely not equal NET_IP_ALIGN
+                        * if this is a 5701 card running in PCI-X mode
+                        * [see tg3_get_invariants()]
+                        */
                ) {
                        int skb_size;
 
@@ -3564,11 +4314,12 @@ static int tg3_rx(struct tg3 *tp, int budget)
                        tg3_recycle_rx(tp, opaque_key,
                                       desc_idx, *post_ptr);
 
-                       copy_skb = netdev_alloc_skb(tp->dev, len + 2);
+                       copy_skb = netdev_alloc_skb(tp->dev,
+                                                   len + TG3_RAW_IP_ALIGN);
                        if (copy_skb == NULL)
                                goto drop_it_no_recycle;
 
-                       skb_reserve(copy_skb, 2);
+                       skb_reserve(copy_skb, TG3_RAW_IP_ALIGN);
                        skb_put(copy_skb, len);
                        pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
                        skb_copy_from_linear_data(skb, copy_skb->data, len);
@@ -3596,7 +4347,6 @@ static int tg3_rx(struct tg3 *tp, int budget)
 #endif
                        netif_receive_skb(skb);
 
-               tp->dev->last_rx = jiffies;
                received++;
                budget--;
 
@@ -3654,7 +4404,15 @@ static int tg3_poll_work(struct tg3 *tp, int work_done, int budget)
                        sblk->status = SD_STATUS_UPDATED |
                                (sblk->status & ~SD_STATUS_LINK_CHG);
                        spin_lock(&tp->lock);
-                       tg3_setup_phy(tp, 0);
+                       if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+                               tw32_f(MAC_STATUS,
+                                    (MAC_STATUS_SYNC_CHANGED |
+                                     MAC_STATUS_CFG_CHANGED |
+                                     MAC_STATUS_MI_COMPLETION |
+                                     MAC_STATUS_LNKSTATE_CHANGED));
+                               udelay(40);
+                       } else
+                               tg3_setup_phy(tp, 0);
                        spin_unlock(&tp->lock);
                }
        }
@@ -3702,7 +4460,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
                        sblk->status &= ~SD_STATUS_UPDATED;
 
                if (likely(!tg3_has_work(tp))) {
-                       netif_rx_complete(tp->dev, napi);
+                       napi_complete(napi);
                        tg3_restart_ints(tp);
                        break;
                }
@@ -3712,7 +4470,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
 
 tx_recovery:
        /* work_done is guaranteed to be less than budget. */
-       netif_rx_complete(tp->dev, napi);
+       napi_complete(napi);
        schedule_work(&tp->reset_task);
        return work_done;
 }
@@ -3761,7 +4519,7 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id)
        prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
 
        if (likely(!tg3_irq_sync(tp)))
-               netif_rx_schedule(dev, &tp->napi);
+               napi_schedule(&tp->napi);
 
        return IRQ_HANDLED;
 }
@@ -3786,7 +4544,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id)
         */
        tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
        if (likely(!tg3_irq_sync(tp)))
-               netif_rx_schedule(dev, &tp->napi);
+               napi_schedule(&tp->napi);
 
        return IRQ_RETVAL(1);
 }
@@ -3828,7 +4586,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
        sblk->status &= ~SD_STATUS_UPDATED;
        if (likely(tg3_has_work(tp))) {
                prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
-               netif_rx_schedule(dev, &tp->napi);
+               napi_schedule(&tp->napi);
        } else {
                /* No work, shared interrupt perhaps?  re-enable
                 * interrupts, and flush that PCI write
@@ -3874,7 +4632,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
        tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
        if (tg3_irq_sync(tp))
                goto out;
-       if (netif_rx_schedule_prep(dev, &tp->napi)) {
+       if (napi_schedule_prep(&tp->napi)) {
                prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
                /* Update last_tag to mark that this status has been
                 * seen. Because interrupt may be shared, we may be
@@ -3882,7 +4640,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
                 * if tg3_poll() is not scheduled.
                 */
                tp->last_tag = sblk->status_tag;
-               __netif_rx_schedule(dev, &tp->napi);
+               __napi_schedule(&tp->napi);
        }
 out:
        return IRQ_RETVAL(handled);
@@ -3910,6 +4668,8 @@ static int tg3_halt(struct tg3 *, int, int);
  * Invoked with tp->lock held.
  */
 static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
+       __releases(tp->lock)
+       __acquires(tp->lock)
 {
        int err;
 
@@ -3940,6 +4700,7 @@ static void tg3_poll_controller(struct net_device *dev)
 static void tg3_reset_task(struct work_struct *work)
 {
        struct tg3 *tp = container_of(work, struct tg3, reset_task);
+       int err;
        unsigned int restart_timer;
 
        tg3_full_lock(tp, 0);
@@ -3951,6 +4712,8 @@ static void tg3_reset_task(struct work_struct *work)
 
        tg3_full_unlock(tp);
 
+       tg3_phy_stop(tp);
+
        tg3_netif_stop(tp);
 
        tg3_full_lock(tp, 1);
@@ -3966,7 +4729,8 @@ static void tg3_reset_task(struct work_struct *work)
        }
 
        tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
-       if (tg3_init_hw(tp, 1))
+       err = tg3_init_hw(tp, 1);
+       if (err)
                goto out;
 
        tg3_netif_start(tp);
@@ -3976,6 +4740,9 @@ static void tg3_reset_task(struct work_struct *work)
 
 out:
        tg3_full_unlock(tp);
+
+       if (!err)
+               tg3_phy_start(tp);
 }
 
 static void tg3_dump_short_state(struct tg3 *tp)
@@ -4028,22 +4795,36 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
                                       u32 last_plus_one, u32 *start,
                                       u32 base_flags, u32 mss)
 {
-       struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
+       struct sk_buff *new_skb;
        dma_addr_t new_addr = 0;
        u32 entry = *start;
        int i, ret = 0;
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
+               new_skb = skb_copy(skb, GFP_ATOMIC);
+       else {
+               int more_headroom = 4 - ((unsigned long)skb->data & 3);
+
+               new_skb = skb_copy_expand(skb,
+                                         skb_headroom(skb) + more_headroom,
+                                         skb_tailroom(skb), GFP_ATOMIC);
+       }
+
        if (!new_skb) {
                ret = -1;
        } else {
                /* New SKB is guaranteed to be linear. */
                entry = *start;
-               new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
-                                         PCI_DMA_TODEVICE);
+               ret = skb_dma_map(&tp->pdev->dev, new_skb, DMA_TO_DEVICE);
+               new_addr = skb_shinfo(new_skb)->dma_maps[0];
+
                /* Make sure new skb does not cross any 4G boundaries.
                 * Drop the packet if it does.
                 */
-               if (tg3_4g_overflow_test(new_addr, new_skb->len)) {
+               if (ret || tg3_4g_overflow_test(new_addr, new_skb->len)) {
+                       if (!ret)
+                               skb_dma_unmap(&tp->pdev->dev, new_skb,
+                                             DMA_TO_DEVICE);
                        ret = -1;
                        dev_kfree_skb(new_skb);
                        new_skb = NULL;
@@ -4057,18 +4838,8 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
        /* Now clean up the sw ring entries. */
        i = 0;
        while (entry != last_plus_one) {
-               int len;
-
-               if (i == 0)
-                       len = skb_headlen(skb);
-               else
-                       len = skb_shinfo(skb)->frags[i-1].size;
-               pci_unmap_single(tp->pdev,
-                                pci_unmap_addr(&tp->tx_buffers[entry], mapping),
-                                len, PCI_DMA_TODEVICE);
                if (i == 0) {
                        tp->tx_buffers[entry].skb = new_skb;
-                       pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, new_addr);
                } else {
                        tp->tx_buffers[entry].skb = NULL;
                }
@@ -4076,6 +4847,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
                i++;
        }
 
+       skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
        dev_kfree_skb(skb);
 
        return ret;
@@ -4110,8 +4882,9 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
 static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
-       dma_addr_t mapping;
        u32 len, entry, base_flags, mss;
+       struct skb_shared_info *sp;
+       dma_addr_t mapping;
 
        len = skb_headlen(skb);
 
@@ -4170,11 +4943,16 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                               (vlan_tx_tag_get(skb) << 16));
 #endif
 
-       /* Queue skb data, a.k.a. the main skb fragment. */
-       mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+       if (skb_dma_map(&tp->pdev->dev, skb, DMA_TO_DEVICE)) {
+               dev_kfree_skb(skb);
+               goto out_unlock;
+       }
+
+       sp = skb_shinfo(skb);
+
+       mapping = sp->dma_maps[0];
 
        tp->tx_buffers[entry].skb = skb;
-       pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
 
        tg3_set_txd(tp, entry, mapping, len, base_flags,
                    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
@@ -4190,13 +4968,8 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
                        len = frag->size;
-                       mapping = pci_map_page(tp->pdev,
-                                              frag->page,
-                                              frag->page_offset,
-                                              len, PCI_DMA_TODEVICE);
-
+                       mapping = sp->dma_maps[i + 1];
                        tp->tx_buffers[entry].skb = NULL;
-                       pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
 
                        tg3_set_txd(tp, entry, mapping, len,
                                    base_flags, (i == last) | (mss << 1));
@@ -4242,7 +5015,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
        }
 
        segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO);
-       if (unlikely(IS_ERR(segs)))
+       if (IS_ERR(segs))
                goto tg3_tso_bug_end;
 
        do {
@@ -4264,9 +5037,10 @@ tg3_tso_bug_end:
 static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
-       dma_addr_t mapping;
        u32 len, entry, base_flags, mss;
+       struct skb_shared_info *sp;
        int would_hit_hwbug;
+       dma_addr_t mapping;
 
        len = skb_headlen(skb);
 
@@ -4347,15 +5121,22 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
                               (vlan_tx_tag_get(skb) << 16));
 #endif
 
-       /* Queue skb data, a.k.a. the main skb fragment. */
-       mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+       if (skb_dma_map(&tp->pdev->dev, skb, DMA_TO_DEVICE)) {
+               dev_kfree_skb(skb);
+               goto out_unlock;
+       }
+
+       sp = skb_shinfo(skb);
+
+       mapping = sp->dma_maps[0];
 
        tp->tx_buffers[entry].skb = skb;
-       pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
 
        would_hit_hwbug = 0;
 
-       if (tg3_4g_overflow_test(mapping, len))
+       if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG)
+               would_hit_hwbug = 1;
+       else if (tg3_4g_overflow_test(mapping, len))
                would_hit_hwbug = 1;
 
        tg3_set_txd(tp, entry, mapping, len, base_flags,
@@ -4372,13 +5153,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
                        len = frag->size;
-                       mapping = pci_map_page(tp->pdev,
-                                              frag->page,
-                                              frag->page_offset,
-                                              len, PCI_DMA_TODEVICE);
+                       mapping = sp->dma_maps[i + 1];
 
                        tp->tx_buffers[entry].skb = NULL;
-                       pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
 
                        if (tg3_4g_overflow_test(mapping, len))
                                would_hit_hwbug = 1;
@@ -4467,6 +5244,8 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
                return 0;
        }
 
+       tg3_phy_stop(tp);
+
        tg3_netif_stop(tp);
 
        tg3_full_lock(tp, 1);
@@ -4482,6 +5261,9 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
 
        tg3_full_unlock(tp);
 
+       if (!err)
+               tg3_phy_start(tp);
+
        return err;
 }
 
@@ -4526,7 +5308,6 @@ static void tg3_free_rings(struct tg3 *tp)
        for (i = 0; i < TG3_TX_RING_SIZE; ) {
                struct tx_ring_info *txp;
                struct sk_buff *skb;
-               int j;
 
                txp = &tp->tx_buffers[i];
                skb = txp->skb;
@@ -4536,22 +5317,11 @@ static void tg3_free_rings(struct tg3 *tp)
                        continue;
                }
 
-               pci_unmap_single(tp->pdev,
-                                pci_unmap_addr(txp, mapping),
-                                skb_headlen(skb),
-                                PCI_DMA_TODEVICE);
-               txp->skb = NULL;
+               skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
 
-               i++;
+               txp->skb = NULL;
 
-               for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) {
-                       txp = &tp->tx_buffers[i & (TG3_TX_RING_SIZE - 1)];
-                       pci_unmap_page(tp->pdev,
-                                      pci_unmap_addr(txp, mapping),
-                                      skb_shinfo(skb)->frags[j].size,
-                                      PCI_DMA_TODEVICE);
-                       i++;
-               }
+               i += skb_shinfo(skb)->nr_frags + 1;
 
                dev_kfree_skb_any(skb);
        }
@@ -4773,7 +5543,7 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int
 
                default:
                        break;
-               };
+               }
        }
 
        val = tr32(ofs);
@@ -4926,7 +5696,7 @@ static void tg3_ape_send_event(struct tg3 *tp, u32 event)
                return;
 
        apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
-       if (apedata != APE_FW_STATUS_READY)
+       if (!(apedata & APE_FW_STATUS_READY))
                return;
 
        /* Wait for up to 1 millisecond for APE to service previous event. */
@@ -4976,6 +5746,13 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
                        event = APE_EVENT_STATUS_STATE_START;
                        break;
                case RESET_KIND_SHUTDOWN:
+                       /* With the interface we are currently using,
+                        * APE does not track driver state.  Wiping
+                        * out the HOST SEGMENT SIGNATURE forces
+                        * the APE to assume OS absent status.
+                        */
+                       tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);
+
                        event = APE_EVENT_STATUS_STATE_UNLOAD;
                        break;
                case RESET_KIND_SUSPEND:
@@ -5015,7 +5792,7 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
 
                default:
                        break;
-               };
+               }
        }
 
        if (kind == RESET_KIND_INIT ||
@@ -5040,7 +5817,7 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind)
 
                default:
                        break;
-               };
+               }
        }
 
        if (kind == RESET_KIND_SHUTDOWN)
@@ -5069,7 +5846,7 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind)
 
                default:
                        break;
-               };
+               }
        }
 }
 
@@ -5140,17 +5917,19 @@ static void tg3_restore_pci_state(struct tg3 *tp)
 
        pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
 
-       if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
-               pcie_set_readrq(tp->pdev, 4096);
-       else {
-               pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
-                                     tp->pci_cacheline_sz);
-               pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
-                                     tp->pci_lat_timer);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
+               if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+                       pcie_set_readrq(tp->pdev, 4096);
+               else {
+                       pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+                                             tp->pci_cacheline_sz);
+                       pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+                                             tp->pci_lat_timer);
+               }
        }
 
        /* Make sure PCI-X relaxed ordering bit is clear. */
-       if (tp->pcix_cap) {
+       if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
                u16 pcix_cmd;
 
                pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
@@ -5191,6 +5970,10 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        tg3_nvram_lock(tp);
 
+       tg3_mdio_stop(tp);
+
+       tg3_ape_lock(tp, TG3_APE_LOCK_GRC);
+
        /* No matching tg3_nvram_unlock() after this because
         * chip reset below will undo the nvram lock.
         */
@@ -5203,10 +5986,7 @@ static int tg3_chip_reset(struct tg3 *tp)
        tg3_save_pci_state(tp);
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+           (tp->tg3_flags3 & TG3_FLG3_5755_PLUS))
                tw32(GRC_FASTBOOT_PC, 0);
 
        /*
@@ -5285,7 +6065,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        udelay(120);
 
-       if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+       if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pcie_cap) {
                if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
                        int i;
                        u32 cfg_val;
@@ -5298,8 +6078,23 @@ static int tg3_chip_reset(struct tg3 *tp)
                        pci_write_config_dword(tp->pdev, 0xc4,
                                               cfg_val | (1 << 15));
                }
-               /* Set PCIE max payload size and clear error status.  */
-               pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
+
+               /* Set PCIE max payload size to 128 bytes and
+                * clear the "no snoop" and "relaxed ordering" bits.
+                */
+               pci_write_config_word(tp->pdev,
+                                     tp->pcie_cap + PCI_EXP_DEVCTL,
+                                     0);
+
+               pcie_set_readrq(tp->pdev, 4096);
+
+               /* Clear error status */
+               pci_write_config_word(tp->pdev,
+                                     tp->pcie_cap + PCI_EXP_DEVSTA,
+                                     PCI_EXP_DEVSTA_CED |
+                                     PCI_EXP_DEVSTA_NFED |
+                                     PCI_EXP_DEVSTA_FED |
+                                     PCI_EXP_DEVSTA_URD);
        }
 
        tg3_restore_pci_state(tp);
@@ -5338,10 +6133,19 @@ static int tg3_chip_reset(struct tg3 *tp)
        } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
                tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
                tw32_f(MAC_MODE, tp->mac_mode);
+       } else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+               tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN);
+               if (tp->mac_mode & MAC_MODE_APE_TX_EN)
+                       tp->mac_mode |= MAC_MODE_TDE_ENABLE;
+               tw32_f(MAC_MODE, tp->mac_mode);
        } else
                tw32_f(MAC_MODE, 0);
        udelay(40);
 
+       tg3_mdio_start(tp);
+
+       tg3_ape_unlock(tp, TG3_APE_LOCK_GRC);
+
        err = tg3_poll_fw(tp);
        if (err)
                return err;
@@ -5363,6 +6167,7 @@ static int tg3_chip_reset(struct tg3 *tp)
                tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
                if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
                        tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
+                       tp->last_event_jiffies = jiffies;
                        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
                                tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
                }
@@ -5376,20 +6181,15 @@ static void tg3_stop_fw(struct tg3 *tp)
 {
        if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
           !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
-               u32 val;
-               int i;
+               /* Wait for RX cpu to ACK the previous event. */
+               tg3_wait_for_event_ack(tp);
 
                tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
-               val = tr32(GRC_RX_CPU_EVENT);
-               val |= (1 << 14);
-               tw32(GRC_RX_CPU_EVENT, val);
 
-               /* Wait for RX cpu to ACK the event.  */
-               for (i = 0; i < 100; i++) {
-                       if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14)))
-                               break;
-                       udelay(1);
-               }
+               tg3_generate_fw_event(tp);
+
+               /* Wait for RX cpu to ACK this event. */
+               tg3_wait_for_event_ack(tp);
        }
 }
 
@@ -5414,130 +6214,6 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent)
        return 0;
 }
 
-#define TG3_FW_RELEASE_MAJOR   0x0
-#define TG3_FW_RELASE_MINOR    0x0
-#define TG3_FW_RELEASE_FIX     0x0
-#define TG3_FW_START_ADDR      0x08000000
-#define TG3_FW_TEXT_ADDR       0x08000000
-#define TG3_FW_TEXT_LEN                0x9c0
-#define TG3_FW_RODATA_ADDR     0x080009c0
-#define TG3_FW_RODATA_LEN      0x60
-#define TG3_FW_DATA_ADDR       0x08000a40
-#define TG3_FW_DATA_LEN                0x20
-#define TG3_FW_SBSS_ADDR       0x08000a60
-#define TG3_FW_SBSS_LEN                0xc
-#define TG3_FW_BSS_ADDR                0x08000a70
-#define TG3_FW_BSS_LEN         0x10
-
-static const u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = {
-       0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800,
-       0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000,
-       0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034,
-       0x0e00021c, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, 0x00000000,
-       0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xaf80680c, 0x0e00004c, 0x241b2105,
-       0x97850000, 0x97870002, 0x9782002c, 0x9783002e, 0x3c040800, 0x248409c0,
-       0xafa00014, 0x00021400, 0x00621825, 0x00052c00, 0xafa30010, 0x8f860010,
-       0x00e52825, 0x0e000060, 0x24070102, 0x3c02ac00, 0x34420100, 0x3c03ac01,
-       0x34630100, 0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498, 0xaf82049c,
-       0x24020001, 0xaf825ce0, 0x0e00003f, 0xaf825d00, 0x0e000140, 0x00000000,
-       0x8fbf0018, 0x03e00008, 0x27bd0020, 0x2402ffff, 0xaf825404, 0x8f835400,
-       0x34630400, 0xaf835400, 0xaf825404, 0x3c020800, 0x24420034, 0xaf82541c,
-       0x03e00008, 0xaf805400, 0x00000000, 0x00000000, 0x3c020800, 0x34423000,
-       0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac220a64,
-       0x24020040, 0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60, 0xac600000,
-       0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000,
-       0x00804821, 0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800, 0x8c840a68,
-       0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac230a60, 0x14400003,
-       0x00004021, 0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60, 0x3c030800,
-       0x8c630a64, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001,
-       0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c420a60,
-       0x3c030800, 0x8c630a64, 0x8f84680c, 0x00021140, 0x00431021, 0xac440008,
-       0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0,
-       0x02000008, 0x00000000, 0x0a0001e3, 0x3c0a0001, 0x0a0001e3, 0x3c0a0002,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x3c0a0007, 0x0a0001e3, 0x3c0a0008, 0x0a0001e3, 0x3c0a0009,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000b,
-       0x0a0001e3, 0x3c0a000c, 0x0a0001e3, 0x3c0a000d, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000e, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a0013, 0x0a0001e3, 0x3c0a0014,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0x27bdffe0, 0x00001821, 0x00001021, 0xafbf0018, 0xafb10014, 0xafb00010,
-       0x3c010800, 0x00220821, 0xac200a70, 0x3c010800, 0x00220821, 0xac200a74,
-       0x3c010800, 0x00220821, 0xac200a78, 0x24630001, 0x1860fff5, 0x2442000c,
-       0x24110001, 0x8f906810, 0x32020004, 0x14400005, 0x24040001, 0x3c020800,
-       0x8c420a78, 0x18400003, 0x00002021, 0x0e000182, 0x00000000, 0x32020001,
-       0x10400003, 0x00000000, 0x0e000169, 0x00000000, 0x0a000153, 0xaf915028,
-       0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c050800,
-       0x8ca50a70, 0x3c060800, 0x8cc60a80, 0x3c070800, 0x8ce70a78, 0x27bdffe0,
-       0x3c040800, 0x248409d0, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014,
-       0x0e00017b, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x24020001,
-       0x8f836810, 0x00821004, 0x00021027, 0x00621824, 0x03e00008, 0xaf836810,
-       0x27bdffd8, 0xafbf0024, 0x1080002e, 0xafb00020, 0x8f825cec, 0xafa20018,
-       0x8f825cec, 0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000, 0xaf825cec,
-       0x8e020000, 0x18400016, 0x00000000, 0x3c020800, 0x94420a74, 0x8fa3001c,
-       0x000221c0, 0xac830004, 0x8fa2001c, 0x3c010800, 0x0e000201, 0xac220a74,
-       0x10400005, 0x00000000, 0x8e020000, 0x24420001, 0x0a0001df, 0xae020000,
-       0x3c020800, 0x8c420a70, 0x00021c02, 0x000321c0, 0x0a0001c5, 0xafa2001c,
-       0x0e000201, 0x00000000, 0x1040001f, 0x00000000, 0x8e020000, 0x8fa3001c,
-       0x24420001, 0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74, 0x0a0001df,
-       0xae020000, 0x3c100800, 0x26100a78, 0x8e020000, 0x18400028, 0x00000000,
-       0x0e000201, 0x00000000, 0x14400024, 0x00000000, 0x8e020000, 0x3c030800,
-       0x8c630a70, 0x2442ffff, 0xafa3001c, 0x18400006, 0xae020000, 0x00031402,
-       0x000221c0, 0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e, 0x2442ff00,
-       0x2c420300, 0x1440000b, 0x24024000, 0x3c040800, 0x248409dc, 0xafa00010,
-       0xafa00014, 0x8fa6001c, 0x24050008, 0x0e000060, 0x00003821, 0x0a0001df,
-       0x00000000, 0xaf825cf8, 0x3c020800, 0x8c420a40, 0x8fa3001c, 0x24420001,
-       0xaf835cf8, 0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020, 0x03e00008,
-       0x27bd0028, 0x27bdffe0, 0x3c040800, 0x248409e8, 0x00002821, 0x00003021,
-       0x00003821, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x8fbf0018,
-       0x03e00008, 0x27bd0020, 0x8f82680c, 0x8f85680c, 0x00021827, 0x0003182b,
-       0x00031823, 0x00431024, 0x00441021, 0x00a2282b, 0x10a00006, 0x00000000,
-       0x00401821, 0x8f82680c, 0x0043102b, 0x1440fffd, 0x00000000, 0x03e00008,
-       0x00000000, 0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40, 0x0064102b,
-       0x54400002, 0x00831023, 0x00641023, 0x2c420008, 0x03e00008, 0x38420001,
-       0x27bdffe0, 0x00802821, 0x3c040800, 0x24840a00, 0x00003021, 0x00003821,
-       0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x0a000216, 0x00000000,
-       0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000, 0x27bdffe0, 0x3c1cc000,
-       0xafbf0018, 0x0e00004c, 0xaf80680c, 0x3c040800, 0x24840a10, 0x03802821,
-       0x00003021, 0x00003821, 0xafa00010, 0x0e000060, 0xafa00014, 0x2402ffff,
-       0xaf825404, 0x3c0200aa, 0x0e000234, 0xaf825434, 0x8fbf0018, 0x03e00008,
-       0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe8, 0xafb00010,
-       0x24100001, 0xafbf0014, 0x3c01c003, 0xac200000, 0x8f826810, 0x30422000,
-       0x10400003, 0x00000000, 0x0e000246, 0x00000000, 0x0a00023a, 0xaf905428,
-       0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdfff8, 0x8f845d0c,
-       0x3c0200ff, 0x3c030800, 0x8c630a50, 0x3442fff8, 0x00821024, 0x1043001e,
-       0x3c0500ff, 0x34a5fff8, 0x3c06c003, 0x3c074000, 0x00851824, 0x8c620010,
-       0x3c010800, 0xac230a50, 0x30420008, 0x10400005, 0x00871025, 0x8cc20000,
-       0x24420001, 0xacc20000, 0x00871025, 0xaf825d0c, 0x8fa20000, 0x24420001,
-       0xafa20000, 0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000, 0x8fa20000,
-       0x8f845d0c, 0x3c030800, 0x8c630a50, 0x00851024, 0x1443ffe8, 0x00851824,
-       0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000
-};
-
-static const u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = {
-       0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430,
-       0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
-       0x00000000, 0x00000000, 0x4d61696e, 0x43707542, 0x00000000, 0x00000000,
-       0x00000000
-};
-
-#if 0 /* All zeros, don't eat up space with it. */
-u32 tg3FwData[(TG3_FW_DATA_LEN / sizeof(u32)) + 1] = {
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000
-};
-#endif
-
 #define RX_CPU_SCRATCH_BASE    0x30000
 #define RX_CPU_SCRATCH_SIZE    0x04000
 #define TX_CPU_SCRATCH_BASE    0x34000
@@ -5592,15 +6268,9 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
 }
 
 struct fw_info {
-       unsigned int text_base;
-       unsigned int text_len;
-       const u32 *text_data;
-       unsigned int rodata_base;
-       unsigned int rodata_len;
-       const u32 *rodata_data;
-       unsigned int data_base;
-       unsigned int data_len;
-       const u32 *data_data;
+       unsigned int fw_base;
+       unsigned int fw_len;
+       const __be32 *fw_data;
 };
 
 /* tp->lock is held. */
@@ -5637,24 +6307,11 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
                write_op(tp, cpu_scratch_base + i, 0);
        tw32(cpu_base + CPU_STATE, 0xffffffff);
        tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
-       for (i = 0; i < (info->text_len / sizeof(u32)); i++)
-               write_op(tp, (cpu_scratch_base +
-                             (info->text_base & 0xffff) +
-                             (i * sizeof(u32))),
-                        (info->text_data ?
-                         info->text_data[i] : 0));
-       for (i = 0; i < (info->rodata_len / sizeof(u32)); i++)
-               write_op(tp, (cpu_scratch_base +
-                             (info->rodata_base & 0xffff) +
-                             (i * sizeof(u32))),
-                        (info->rodata_data ?
-                         info->rodata_data[i] : 0));
-       for (i = 0; i < (info->data_len / sizeof(u32)); i++)
+       for (i = 0; i < (info->fw_len / sizeof(u32)); i++)
                write_op(tp, (cpu_scratch_base +
-                             (info->data_base & 0xffff) +
+                             (info->fw_base & 0xffff) +
                              (i * sizeof(u32))),
-                        (info->data_data ?
-                         info->data_data[i] : 0));
+                             be32_to_cpu(info->fw_data[i]));
 
        err = 0;
 
@@ -5666,17 +6323,20 @@ out:
 static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
 {
        struct fw_info info;
+       const __be32 *fw_data;
        int err, i;
 
-       info.text_base = TG3_FW_TEXT_ADDR;
-       info.text_len = TG3_FW_TEXT_LEN;
-       info.text_data = &tg3FwText[0];
-       info.rodata_base = TG3_FW_RODATA_ADDR;
-       info.rodata_len = TG3_FW_RODATA_LEN;
-       info.rodata_data = &tg3FwRodata[0];
-       info.data_base = TG3_FW_DATA_ADDR;
-       info.data_len = TG3_FW_DATA_LEN;
-       info.data_data = NULL;
+       fw_data = (void *)tp->fw->data;
+
+       /* Firmware blob starts with version numbers, followed by
+          start address and length. We are setting complete length.
+          length = end_address_of_bss - start_address_of_text.
+          Remainder is the blob to be loaded contiguously
+          from start address. */
+
+       info.fw_base = be32_to_cpu(fw_data[1]);
+       info.fw_len = tp->fw->size - 12;
+       info.fw_data = &fw_data[3];
 
        err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
                                    RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
@@ -5692,570 +6352,59 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
 
        /* Now startup only the RX cpu. */
        tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-       tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
+       tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
 
        for (i = 0; i < 5; i++) {
-               if (tr32(RX_CPU_BASE + CPU_PC) == TG3_FW_TEXT_ADDR)
+               if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base)
                        break;
                tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
                tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
-               tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
+               tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
                udelay(1000);
        }
        if (i >= 5) {
                printk(KERN_ERR PFX "tg3_load_firmware fails for %s "
                       "to set RX CPU PC, is %08x should be %08x\n",
                       tp->dev->name, tr32(RX_CPU_BASE + CPU_PC),
-                      TG3_FW_TEXT_ADDR);
+                      info.fw_base);
                return -ENODEV;
        }
        tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
        tw32_f(RX_CPU_BASE + CPU_MODE,  0x00000000);
 
-       return 0;
-}
-
-
-#define TG3_TSO_FW_RELEASE_MAJOR       0x1
-#define TG3_TSO_FW_RELASE_MINOR                0x6
-#define TG3_TSO_FW_RELEASE_FIX         0x0
-#define TG3_TSO_FW_START_ADDR          0x08000000
-#define TG3_TSO_FW_TEXT_ADDR           0x08000000
-#define TG3_TSO_FW_TEXT_LEN            0x1aa0
-#define TG3_TSO_FW_RODATA_ADDR         0x08001aa0
-#define TG3_TSO_FW_RODATA_LEN          0x60
-#define TG3_TSO_FW_DATA_ADDR           0x08001b20
-#define TG3_TSO_FW_DATA_LEN            0x30
-#define TG3_TSO_FW_SBSS_ADDR           0x08001b50
-#define TG3_TSO_FW_SBSS_LEN            0x2c
-#define TG3_TSO_FW_BSS_ADDR            0x08001b80
-#define TG3_TSO_FW_BSS_LEN             0x894
-
-static const u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = {
-       0x0e000003, 0x00000000, 0x08001b24, 0x00000000, 0x10000003, 0x00000000,
-       0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800,
-       0x26100000, 0x0e000010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
-       0xafbf0018, 0x0e0005d8, 0x34840002, 0x0e000668, 0x00000000, 0x3c030800,
-       0x90631b68, 0x24020002, 0x3c040800, 0x24841aac, 0x14620003, 0x24050001,
-       0x3c040800, 0x24841aa0, 0x24060006, 0x00003821, 0xafa00010, 0x0e00067c,
-       0xafa00014, 0x8f625c50, 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001,
-       0xaf625c90, 0x2402ffff, 0x0e000034, 0xaf625404, 0x8fbf0018, 0x03e00008,
-       0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c,
-       0xafb20018, 0xafb10014, 0x0e00005b, 0xafb00010, 0x24120002, 0x24110001,
-       0x8f706820, 0x32020100, 0x10400003, 0x00000000, 0x0e0000bb, 0x00000000,
-       0x8f706820, 0x32022000, 0x10400004, 0x32020001, 0x0e0001f0, 0x24040001,
-       0x32020001, 0x10400003, 0x00000000, 0x0e0000a3, 0x00000000, 0x3c020800,
-       0x90421b98, 0x14520003, 0x00000000, 0x0e0004c0, 0x00000000, 0x0a00003c,
-       0xaf715028, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008,
-       0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ac0, 0x00002821, 0x00003021,
-       0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x3c040800,
-       0x248423d8, 0xa4800000, 0x3c010800, 0xa0201b98, 0x3c010800, 0xac201b9c,
-       0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac,
-       0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bbc, 0x8f624434, 0x3c010800,
-       0xac221b88, 0x8f624438, 0x3c010800, 0xac221b8c, 0x8f624410, 0xac80f7a8,
-       0x3c010800, 0xac201b84, 0x3c010800, 0xac2023e0, 0x3c010800, 0xac2023c8,
-       0x3c010800, 0xac2023cc, 0x3c010800, 0xac202400, 0x3c010800, 0xac221b90,
-       0x8f620068, 0x24030007, 0x00021702, 0x10430005, 0x00000000, 0x8f620068,
-       0x00021702, 0x14400004, 0x24020001, 0x3c010800, 0x0a000097, 0xac20240c,
-       0xac820034, 0x3c040800, 0x24841acc, 0x3c050800, 0x8ca5240c, 0x00003021,
-       0x00003821, 0xafa00010, 0x0e00067c, 0xafa00014, 0x8fbf0018, 0x03e00008,
-       0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ad8, 0x00002821, 0x00003021,
-       0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x0e00005b,
-       0x00000000, 0x0e0000b4, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020,
-       0x24020001, 0x8f636820, 0x00821004, 0x00021027, 0x00621824, 0x03e00008,
-       0xaf636820, 0x27bdffd0, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020,
-       0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f675c5c, 0x3c030800,
-       0x24631bbc, 0x8c620000, 0x14470005, 0x3c0200ff, 0x3c020800, 0x90421b98,
-       0x14400119, 0x3c0200ff, 0x3442fff8, 0x00e28824, 0xac670000, 0x00111902,
-       0x306300ff, 0x30e20003, 0x000211c0, 0x00622825, 0x00a04021, 0x00071602,
-       0x3c030800, 0x90631b98, 0x3044000f, 0x14600036, 0x00804821, 0x24020001,
-       0x3c010800, 0xa0221b98, 0x00051100, 0x00821025, 0x3c010800, 0xac201b9c,
-       0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac,
-       0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bb0, 0x3c010800, 0xac201bb4,
-       0x3c010800, 0xa42223d8, 0x9622000c, 0x30437fff, 0x3c010800, 0xa4222410,
-       0x30428000, 0x3c010800, 0xa4231bc6, 0x10400005, 0x24020001, 0x3c010800,
-       0xac2223f4, 0x0a000102, 0x2406003e, 0x24060036, 0x3c010800, 0xac2023f4,
-       0x9622000a, 0x3c030800, 0x94631bc6, 0x3c010800, 0xac2023f0, 0x3c010800,
-       0xac2023f8, 0x00021302, 0x00021080, 0x00c21021, 0x00621821, 0x3c010800,
-       0xa42223d0, 0x3c010800, 0x0a000115, 0xa4231b96, 0x9622000c, 0x3c010800,
-       0xa42223ec, 0x3c040800, 0x24841b9c, 0x8c820000, 0x00021100, 0x3c010800,
-       0x00220821, 0xac311bc8, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
-       0xac271bcc, 0x8c820000, 0x25030001, 0x306601ff, 0x00021100, 0x3c010800,
-       0x00220821, 0xac261bd0, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
-       0xac291bd4, 0x96230008, 0x3c020800, 0x8c421bac, 0x00432821, 0x3c010800,
-       0xac251bac, 0x9622000a, 0x30420004, 0x14400018, 0x00061100, 0x8f630c14,
-       0x3063000f, 0x2c620002, 0x1440000b, 0x3c02c000, 0x8f630c14, 0x3c020800,
-       0x8c421b40, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002,
-       0x1040fff7, 0x3c02c000, 0x00e21825, 0xaf635c5c, 0x8f625c50, 0x30420002,
-       0x10400014, 0x00000000, 0x0a000147, 0x00000000, 0x3c030800, 0x8c631b80,
-       0x3c040800, 0x94841b94, 0x01221025, 0x3c010800, 0xa42223da, 0x24020001,
-       0x3c010800, 0xac221bb8, 0x24630001, 0x0085202a, 0x3c010800, 0x10800003,
-       0xac231b80, 0x3c010800, 0xa4251b94, 0x3c060800, 0x24c61b9c, 0x8cc20000,
-       0x24420001, 0xacc20000, 0x28420080, 0x14400005, 0x00000000, 0x0e000656,
-       0x24040002, 0x0a0001e6, 0x00000000, 0x3c020800, 0x8c421bb8, 0x10400078,
-       0x24020001, 0x3c050800, 0x90a51b98, 0x14a20072, 0x00000000, 0x3c150800,
-       0x96b51b96, 0x3c040800, 0x8c841bac, 0x32a3ffff, 0x0083102a, 0x1440006c,
-       0x00000000, 0x14830003, 0x00000000, 0x3c010800, 0xac2523f0, 0x1060005c,
-       0x00009021, 0x24d60004, 0x0060a021, 0x24d30014, 0x8ec20000, 0x00028100,
-       0x3c110800, 0x02308821, 0x0e000625, 0x8e311bc8, 0x00402821, 0x10a00054,
-       0x00000000, 0x9628000a, 0x31020040, 0x10400005, 0x2407180c, 0x8e22000c,
-       0x2407188c, 0x00021400, 0xaca20018, 0x3c030800, 0x00701821, 0x8c631bd0,
-       0x3c020800, 0x00501021, 0x8c421bd4, 0x00031d00, 0x00021400, 0x00621825,
-       0xaca30014, 0x8ec30004, 0x96220008, 0x00432023, 0x3242ffff, 0x3083ffff,
-       0x00431021, 0x0282102a, 0x14400002, 0x02b23023, 0x00803021, 0x8e620000,
-       0x30c4ffff, 0x00441021, 0xae620000, 0x8e220000, 0xaca20000, 0x8e220004,
-       0x8e63fff4, 0x00431021, 0xaca20004, 0xa4a6000e, 0x8e62fff4, 0x00441021,
-       0xae62fff4, 0x96230008, 0x0043102a, 0x14400005, 0x02469021, 0x8e62fff0,
-       0xae60fff4, 0x24420001, 0xae62fff0, 0xaca00008, 0x3242ffff, 0x14540008,
-       0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x24020905, 0xa4a2000c,
-       0x0a0001cb, 0x34e70020, 0xa4a2000c, 0x3c020800, 0x8c4223f0, 0x10400003,
-       0x3c024b65, 0x0a0001d3, 0x34427654, 0x3c02b49a, 0x344289ab, 0xaca2001c,
-       0x30e2ffff, 0xaca20010, 0x0e0005a2, 0x00a02021, 0x3242ffff, 0x0054102b,
-       0x1440ffa9, 0x00000000, 0x24020002, 0x3c010800, 0x0a0001e6, 0xa0221b98,
-       0x8ec2083c, 0x24420001, 0x0a0001e6, 0xaec2083c, 0x0e0004c0, 0x00000000,
-       0x8fbf002c, 0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
-       0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0030, 0x27bdffd0, 0xafbf0028,
-       0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff,
-       0x3442fff8, 0x3c070800, 0x24e71bb4, 0x02428824, 0x9623000e, 0x8ce20000,
-       0x00431021, 0xace20000, 0x8e220010, 0x30420020, 0x14400011, 0x00809821,
-       0x0e00063b, 0x02202021, 0x3c02c000, 0x02421825, 0xaf635c9c, 0x8f625c90,
-       0x30420002, 0x1040011e, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002,
-       0x10400119, 0x00000000, 0x0a00020d, 0x00000000, 0x8e240008, 0x8e230014,
-       0x00041402, 0x000231c0, 0x00031502, 0x304201ff, 0x2442ffff, 0x3042007f,
-       0x00031942, 0x30637800, 0x00021100, 0x24424000, 0x00624821, 0x9522000a,
-       0x3084ffff, 0x30420008, 0x104000b0, 0x000429c0, 0x3c020800, 0x8c422400,
-       0x14400024, 0x24c50008, 0x94c20014, 0x3c010800, 0xa42223d0, 0x8cc40010,
-       0x00041402, 0x3c010800, 0xa42223d2, 0x3c010800, 0xa42423d4, 0x94c2000e,
-       0x3083ffff, 0x00431023, 0x3c010800, 0xac222408, 0x94c2001a, 0x3c010800,
-       0xac262400, 0x3c010800, 0xac322404, 0x3c010800, 0xac2223fc, 0x3c02c000,
-       0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e5, 0x00000000,
-       0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e0, 0x00000000, 0x0a000246,
-       0x00000000, 0x94c2000e, 0x3c030800, 0x946323d4, 0x00434023, 0x3103ffff,
-       0x2c620008, 0x1040001c, 0x00000000, 0x94c20014, 0x24420028, 0x00a22821,
-       0x00031042, 0x1840000b, 0x00002021, 0x24e60848, 0x00403821, 0x94a30000,
-       0x8cc20000, 0x24840001, 0x00431021, 0xacc20000, 0x0087102a, 0x1440fff9,
-       0x24a50002, 0x31020001, 0x1040001f, 0x3c024000, 0x3c040800, 0x248423fc,
-       0xa0a00001, 0x94a30000, 0x8c820000, 0x00431021, 0x0a000285, 0xac820000,
-       0x8f626800, 0x3c030010, 0x00431024, 0x10400009, 0x00000000, 0x94c2001a,
-       0x3c030800, 0x8c6323fc, 0x00431021, 0x3c010800, 0xac2223fc, 0x0a000286,
-       0x3c024000, 0x94c2001a, 0x94c4001c, 0x3c030800, 0x8c6323fc, 0x00441023,
-       0x00621821, 0x3c010800, 0xac2323fc, 0x3c024000, 0x02421825, 0xaf635c9c,
-       0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, 0x9522000a, 0x30420010,
-       0x1040009b, 0x00000000, 0x3c030800, 0x946323d4, 0x3c070800, 0x24e72400,
-       0x8ce40000, 0x8f626800, 0x24630030, 0x00832821, 0x3c030010, 0x00431024,
-       0x1440000a, 0x00000000, 0x94a20004, 0x3c040800, 0x8c842408, 0x3c030800,
-       0x8c6323fc, 0x00441023, 0x00621821, 0x3c010800, 0xac2323fc, 0x3c040800,
-       0x8c8423fc, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, 0x00822021,
-       0x00041027, 0xa4a20006, 0x3c030800, 0x8c632404, 0x3c0200ff, 0x3442fff8,
-       0x00628824, 0x96220008, 0x24050001, 0x24034000, 0x000231c0, 0x00801021,
-       0xa4c2001a, 0xa4c0001c, 0xace00000, 0x3c010800, 0xac251b60, 0xaf635cb8,
-       0x8f625cb0, 0x30420002, 0x10400003, 0x00000000, 0x3c010800, 0xac201b60,
-       0x8e220008, 0xaf625cb8, 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000,
-       0x3c010800, 0xac201b60, 0x3c020800, 0x8c421b60, 0x1040ffec, 0x00000000,
-       0x3c040800, 0x0e00063b, 0x8c842404, 0x0a00032a, 0x00000000, 0x3c030800,
-       0x90631b98, 0x24020002, 0x14620003, 0x3c034b65, 0x0a0002e1, 0x00008021,
-       0x8e22001c, 0x34637654, 0x10430002, 0x24100002, 0x24100001, 0x00c02021,
-       0x0e000350, 0x02003021, 0x24020003, 0x3c010800, 0xa0221b98, 0x24020002,
-       0x1202000a, 0x24020001, 0x3c030800, 0x8c6323f0, 0x10620006, 0x00000000,
-       0x3c020800, 0x944223d8, 0x00021400, 0x0a00031f, 0xae220014, 0x3c040800,
-       0x248423da, 0x94820000, 0x00021400, 0xae220014, 0x3c020800, 0x8c421bbc,
-       0x3c03c000, 0x3c010800, 0xa0201b98, 0x00431025, 0xaf625c5c, 0x8f625c50,
-       0x30420002, 0x10400009, 0x00000000, 0x2484f7e2, 0x8c820000, 0x00431025,
-       0xaf625c5c, 0x8f625c50, 0x30420002, 0x1440fffa, 0x00000000, 0x3c020800,
-       0x24421b84, 0x8c430000, 0x24630001, 0xac430000, 0x8f630c14, 0x3063000f,
-       0x2c620002, 0x1440000c, 0x3c024000, 0x8f630c14, 0x3c020800, 0x8c421b40,
-       0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7,
-       0x00000000, 0x3c024000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002,
-       0x1440fffc, 0x00000000, 0x12600003, 0x00000000, 0x0e0004c0, 0x00000000,
-       0x8fbf0028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x03e00008,
-       0x27bd0030, 0x8f634450, 0x3c040800, 0x24841b88, 0x8c820000, 0x00031c02,
-       0x0043102b, 0x14400007, 0x3c038000, 0x8c840004, 0x8f624450, 0x00021c02,
-       0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024,
-       0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3c024000,
-       0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00000000,
-       0x03e00008, 0x00000000, 0x27bdffe0, 0x00805821, 0x14c00011, 0x256e0008,
-       0x3c020800, 0x8c4223f4, 0x10400007, 0x24020016, 0x3c010800, 0xa42223d2,
-       0x2402002a, 0x3c010800, 0x0a000364, 0xa42223d4, 0x8d670010, 0x00071402,
-       0x3c010800, 0xa42223d2, 0x3c010800, 0xa42723d4, 0x3c040800, 0x948423d4,
-       0x3c030800, 0x946323d2, 0x95cf0006, 0x3c020800, 0x944223d0, 0x00832023,
-       0x01e2c023, 0x3065ffff, 0x24a20028, 0x01c24821, 0x3082ffff, 0x14c0001a,
-       0x01226021, 0x9582000c, 0x3042003f, 0x3c010800, 0xa42223d6, 0x95820004,
-       0x95830006, 0x3c010800, 0xac2023e4, 0x3c010800, 0xac2023e8, 0x00021400,
-       0x00431025, 0x3c010800, 0xac221bc0, 0x95220004, 0x3c010800, 0xa4221bc4,
-       0x95230002, 0x01e51023, 0x0043102a, 0x10400010, 0x24020001, 0x3c010800,
-       0x0a000398, 0xac2223f8, 0x3c030800, 0x8c6323e8, 0x3c020800, 0x94421bc4,
-       0x00431021, 0xa5220004, 0x3c020800, 0x94421bc0, 0xa5820004, 0x3c020800,
-       0x8c421bc0, 0xa5820006, 0x3c020800, 0x8c4223f0, 0x3c0d0800, 0x8dad23e4,
-       0x3c0a0800, 0x144000e5, 0x8d4a23e8, 0x3c020800, 0x94421bc4, 0x004a1821,
-       0x3063ffff, 0x0062182b, 0x24020002, 0x10c2000d, 0x01435023, 0x3c020800,
-       0x944223d6, 0x30420009, 0x10400008, 0x00000000, 0x9582000c, 0x3042fff6,
-       0xa582000c, 0x3c020800, 0x944223d6, 0x30420009, 0x01a26823, 0x3c020800,
-       0x8c4223f8, 0x1040004a, 0x01203821, 0x3c020800, 0x944223d2, 0x00004021,
-       0xa520000a, 0x01e21023, 0xa5220002, 0x3082ffff, 0x00021042, 0x18400008,
-       0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021, 0x0103102a,
-       0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061402,
-       0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021, 0x2527000c,
-       0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004, 0x1440fffb,
-       0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023, 0x01803821,
-       0x3082ffff, 0xa4e00010, 0x00621821, 0x00021042, 0x18400010, 0x00c33021,
-       0x00404821, 0x94e20000, 0x24e70002, 0x00c23021, 0x30e2007f, 0x14400006,
-       0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80, 0x00625824, 0x25670008,
-       0x0109102a, 0x1440fff3, 0x00000000, 0x30820001, 0x10400005, 0x00061c02,
-       0xa0e00001, 0x94e20000, 0x00c23021, 0x00061c02, 0x30c2ffff, 0x00623021,
-       0x00061402, 0x00c23021, 0x0a00047d, 0x30c6ffff, 0x24020002, 0x14c20081,
-       0x00000000, 0x3c020800, 0x8c42240c, 0x14400007, 0x00000000, 0x3c020800,
-       0x944223d2, 0x95230002, 0x01e21023, 0x10620077, 0x00000000, 0x3c020800,
-       0x944223d2, 0x01e21023, 0xa5220002, 0x3c020800, 0x8c42240c, 0x1040001a,
-       0x31e3ffff, 0x8dc70010, 0x3c020800, 0x94421b96, 0x00e04021, 0x00072c02,
-       0x00aa2021, 0x00431023, 0x00823823, 0x00072402, 0x30e2ffff, 0x00823821,
-       0x00071027, 0xa522000a, 0x3102ffff, 0x3c040800, 0x948423d4, 0x00453023,
-       0x00e02821, 0x00641823, 0x006d1821, 0x00c33021, 0x00061c02, 0x30c2ffff,
-       0x0a00047d, 0x00623021, 0x01203821, 0x00004021, 0x3082ffff, 0x00021042,
-       0x18400008, 0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021,
-       0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021,
-       0x00061402, 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021,
-       0x2527000c, 0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004,
-       0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023,
-       0x01803821, 0x3082ffff, 0xa4e00010, 0x3c040800, 0x948423d4, 0x00621821,
-       0x00c33021, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061c02, 0x3c020800,
-       0x944223d0, 0x00c34821, 0x00441023, 0x00021fc2, 0x00431021, 0x00021043,
-       0x18400010, 0x00003021, 0x00402021, 0x94e20000, 0x24e70002, 0x00c23021,
-       0x30e2007f, 0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80,
-       0x00625824, 0x25670008, 0x0104102a, 0x1440fff3, 0x00000000, 0x3c020800,
-       0x944223ec, 0x00c23021, 0x3122ffff, 0x00c23021, 0x00061c02, 0x30c2ffff,
-       0x00623021, 0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010,
-       0xadc00014, 0x0a00049d, 0xadc00000, 0x8dc70010, 0x00e04021, 0x11400007,
-       0x00072c02, 0x00aa3021, 0x00061402, 0x30c3ffff, 0x00433021, 0x00061402,
-       0x00c22821, 0x00051027, 0xa522000a, 0x3c030800, 0x946323d4, 0x3102ffff,
-       0x01e21021, 0x00433023, 0x00cd3021, 0x00061c02, 0x30c2ffff, 0x00623021,
-       0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010, 0x3102ffff,
-       0x00051c00, 0x00431025, 0xadc20010, 0x3c020800, 0x8c4223f4, 0x10400005,
-       0x2de205eb, 0x14400002, 0x25e2fff2, 0x34028870, 0xa5c20034, 0x3c030800,
-       0x246323e8, 0x8c620000, 0x24420001, 0xac620000, 0x3c040800, 0x8c8423e4,
-       0x3c020800, 0x8c421bc0, 0x3303ffff, 0x00832021, 0x00431821, 0x0062102b,
-       0x3c010800, 0xac2423e4, 0x10400003, 0x2482ffff, 0x3c010800, 0xac2223e4,
-       0x3c010800, 0xac231bc0, 0x03e00008, 0x27bd0020, 0x27bdffb8, 0x3c050800,
-       0x24a51b96, 0xafbf0044, 0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034,
-       0xafb40030, 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x94a90000,
-       0x3c020800, 0x944223d0, 0x3c030800, 0x8c631bb0, 0x3c040800, 0x8c841bac,
-       0x01221023, 0x0064182a, 0xa7a9001e, 0x106000be, 0xa7a20016, 0x24be0022,
-       0x97b6001e, 0x24b3001a, 0x24b70016, 0x8fc20000, 0x14400008, 0x00000000,
-       0x8fc2fff8, 0x97a30016, 0x8fc4fff4, 0x00431021, 0x0082202a, 0x148000b0,
-       0x00000000, 0x97d50818, 0x32a2ffff, 0x104000a3, 0x00009021, 0x0040a021,
-       0x00008821, 0x0e000625, 0x00000000, 0x00403021, 0x14c00007, 0x00000000,
-       0x3c020800, 0x8c4223dc, 0x24420001, 0x3c010800, 0x0a000596, 0xac2223dc,
-       0x3c100800, 0x02118021, 0x8e101bc8, 0x9608000a, 0x31020040, 0x10400005,
-       0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x31020080,
-       0x54400001, 0x34e70010, 0x3c020800, 0x00511021, 0x8c421bd0, 0x3c030800,
-       0x00711821, 0x8c631bd4, 0x00021500, 0x00031c00, 0x00431025, 0xacc20014,
-       0x96040008, 0x3242ffff, 0x00821021, 0x0282102a, 0x14400002, 0x02b22823,
-       0x00802821, 0x8e020000, 0x02459021, 0xacc20000, 0x8e020004, 0x00c02021,
-       0x26310010, 0xac820004, 0x30e2ffff, 0xac800008, 0xa485000e, 0xac820010,
-       0x24020305, 0x0e0005a2, 0xa482000c, 0x3242ffff, 0x0054102b, 0x1440ffc5,
-       0x3242ffff, 0x0a00058e, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a,
-       0x10400067, 0x00000000, 0x8e62fff0, 0x00028900, 0x3c100800, 0x02118021,
-       0x0e000625, 0x8e101bc8, 0x00403021, 0x14c00005, 0x00000000, 0x8e62082c,
-       0x24420001, 0x0a000596, 0xae62082c, 0x9608000a, 0x31020040, 0x10400005,
-       0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x3c020800,
-       0x00511021, 0x8c421bd0, 0x3c030800, 0x00711821, 0x8c631bd4, 0x00021500,
-       0x00031c00, 0x00431025, 0xacc20014, 0x8e63fff4, 0x96020008, 0x00432023,
-       0x3242ffff, 0x3083ffff, 0x00431021, 0x02c2102a, 0x10400003, 0x00802821,
-       0x97a9001e, 0x01322823, 0x8e620000, 0x30a4ffff, 0x00441021, 0xae620000,
-       0xa4c5000e, 0x8e020000, 0xacc20000, 0x8e020004, 0x8e63fff4, 0x00431021,
-       0xacc20004, 0x8e63fff4, 0x96020008, 0x00641821, 0x0062102a, 0x14400006,
-       0x02459021, 0x8e62fff0, 0xae60fff4, 0x24420001, 0x0a000571, 0xae62fff0,
-       0xae63fff4, 0xacc00008, 0x3242ffff, 0x10560003, 0x31020004, 0x10400006,
-       0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x34e70020, 0x24020905,
-       0xa4c2000c, 0x8ee30000, 0x8ee20004, 0x14620007, 0x3c02b49a, 0x8ee20860,
-       0x54400001, 0x34e70400, 0x3c024b65, 0x0a000588, 0x34427654, 0x344289ab,
-       0xacc2001c, 0x30e2ffff, 0xacc20010, 0x0e0005a2, 0x00c02021, 0x3242ffff,
-       0x0056102b, 0x1440ff9b, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a,
-       0x1440ff48, 0x00000000, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038,
-       0x8fb50034, 0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
-       0x03e00008, 0x27bd0048, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f624450,
-       0x8f634410, 0x0a0005b1, 0x00808021, 0x8f626820, 0x30422000, 0x10400003,
-       0x00000000, 0x0e0001f0, 0x00002021, 0x8f624450, 0x8f634410, 0x3042ffff,
-       0x0043102b, 0x1440fff5, 0x00000000, 0x8f630c14, 0x3063000f, 0x2c620002,
-       0x1440000b, 0x00000000, 0x8f630c14, 0x3c020800, 0x8c421b40, 0x3063000f,
-       0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7, 0x00000000,
-       0xaf705c18, 0x8f625c10, 0x30420002, 0x10400009, 0x00000000, 0x8f626820,
-       0x30422000, 0x1040fff8, 0x00000000, 0x0e0001f0, 0x00002021, 0x0a0005c4,
-       0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000,
-       0x00000000, 0x00000000, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010,
-       0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50,
-       0x3c010800, 0xac221b54, 0x24020b78, 0x3c010800, 0xac221b64, 0x34630002,
-       0xaf634000, 0x0e000605, 0x00808021, 0x3c010800, 0xa0221b68, 0x304200ff,
-       0x24030002, 0x14430005, 0x00000000, 0x3c020800, 0x8c421b54, 0x0a0005f8,
-       0xac5000c0, 0x3c020800, 0x8c421b54, 0xac5000bc, 0x8f624434, 0x8f634438,
-       0x8f644410, 0x3c010800, 0xac221b5c, 0x3c010800, 0xac231b6c, 0x3c010800,
-       0xac241b58, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c040800,
-       0x8c870000, 0x3c03aa55, 0x3463aa55, 0x3c06c003, 0xac830000, 0x8cc20000,
-       0x14430007, 0x24050002, 0x3c0355aa, 0x346355aa, 0xac830000, 0x8cc20000,
-       0x50430001, 0x24050001, 0x3c020800, 0xac470000, 0x03e00008, 0x00a01021,
-       0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe,
-       0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008,
-       0x27bd0008, 0x8f634450, 0x3c020800, 0x8c421b5c, 0x00031c02, 0x0043102b,
-       0x14400008, 0x3c038000, 0x3c040800, 0x8c841b6c, 0x8f624450, 0x00021c02,
-       0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024,
-       0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff,
-       0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 0x0a000648, 0x2402ffff,
-       0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021,
-       0x03e00008, 0x00000000, 0x8f624450, 0x3c030800, 0x8c631b58, 0x0a000651,
-       0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000,
-       0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040800, 0x24841af0,
-       0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014,
-       0x0a000660, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000,
-       0x00000000, 0x00000000, 0x3c020800, 0x34423000, 0x3c030800, 0x34633000,
-       0x3c040800, 0x348437ff, 0x3c010800, 0xac221b74, 0x24020040, 0x3c010800,
-       0xac221b78, 0x3c010800, 0xac201b70, 0xac600000, 0x24630004, 0x0083102b,
-       0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, 0x00804821, 0x8faa0010,
-       0x3c020800, 0x8c421b70, 0x3c040800, 0x8c841b78, 0x8fab0014, 0x24430001,
-       0x0044102b, 0x3c010800, 0xac231b70, 0x14400003, 0x00004021, 0x3c010800,
-       0xac201b70, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74, 0x91240000,
-       0x00021140, 0x00431021, 0x00481021, 0x25080001, 0xa0440000, 0x29020008,
-       0x1440fff4, 0x25290001, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74,
-       0x8f64680c, 0x00021140, 0x00431021, 0xac440008, 0xac45000c, 0xac460010,
-       0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000,
-};
-
-static const u32 tg3TsoFwRodata[] = {
-       0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
-       0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f,
-       0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000,
-       0x00000000,
-};
-
-static const u32 tg3TsoFwData[] = {
-       0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000,
-};
-
-/* 5705 needs a special version of the TSO firmware.  */
-#define TG3_TSO5_FW_RELEASE_MAJOR      0x1
-#define TG3_TSO5_FW_RELASE_MINOR       0x2
-#define TG3_TSO5_FW_RELEASE_FIX                0x0
-#define TG3_TSO5_FW_START_ADDR         0x00010000
-#define TG3_TSO5_FW_TEXT_ADDR          0x00010000
-#define TG3_TSO5_FW_TEXT_LEN           0xe90
-#define TG3_TSO5_FW_RODATA_ADDR                0x00010e90
-#define TG3_TSO5_FW_RODATA_LEN         0x50
-#define TG3_TSO5_FW_DATA_ADDR          0x00010f00
-#define TG3_TSO5_FW_DATA_LEN           0x20
-#define TG3_TSO5_FW_SBSS_ADDR          0x00010f20
-#define TG3_TSO5_FW_SBSS_LEN           0x28
-#define TG3_TSO5_FW_BSS_ADDR           0x00010f50
-#define TG3_TSO5_FW_BSS_LEN            0x88
-
-static const u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = {
-       0x0c004003, 0x00000000, 0x00010f04, 0x00000000, 0x10000003, 0x00000000,
-       0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001,
-       0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
-       0xafbf0018, 0x0c0042e8, 0x34840002, 0x0c004364, 0x00000000, 0x3c030001,
-       0x90630f34, 0x24020002, 0x3c040001, 0x24840e9c, 0x14620003, 0x24050001,
-       0x3c040001, 0x24840e90, 0x24060002, 0x00003821, 0xafa00010, 0x0c004378,
-       0xafa00014, 0x0c00402c, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020,
-       0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c, 0xafb20018, 0xafb10014,
-       0x0c0042d4, 0xafb00010, 0x3c128000, 0x24110001, 0x8f706810, 0x32020400,
-       0x10400007, 0x00000000, 0x8f641008, 0x00921024, 0x14400003, 0x00000000,
-       0x0c004064, 0x00000000, 0x3c020001, 0x90420f56, 0x10510003, 0x32020200,
-       0x1040fff1, 0x00000000, 0x0c0041b4, 0x00000000, 0x08004034, 0x00000000,
-       0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-       0x27bdffe0, 0x3c040001, 0x24840eb0, 0x00002821, 0x00003021, 0x00003821,
-       0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0000d021, 0x24020130,
-       0xaf625000, 0x3c010001, 0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018,
-       0x03e00008, 0x27bd0020, 0x00000000, 0x00000000, 0x3c030001, 0x24630f60,
-       0x90620000, 0x27bdfff0, 0x14400003, 0x0080c021, 0x08004073, 0x00004821,
-       0x3c022000, 0x03021024, 0x10400003, 0x24090002, 0x08004073, 0xa0600000,
-       0x24090001, 0x00181040, 0x30431f80, 0x346f8008, 0x1520004b, 0x25eb0028,
-       0x3c040001, 0x00832021, 0x8c848010, 0x3c050001, 0x24a50f7a, 0x00041402,
-       0xa0a20000, 0x3c010001, 0xa0240f7b, 0x3c020001, 0x00431021, 0x94428014,
-       0x3c010001, 0xa0220f7c, 0x3c0c0001, 0x01836021, 0x8d8c8018, 0x304200ff,
-       0x24420008, 0x000220c3, 0x24020001, 0x3c010001, 0xa0220f60, 0x0124102b,
-       0x1040000c, 0x00003821, 0x24a6000e, 0x01602821, 0x8ca20000, 0x8ca30004,
-       0x24a50008, 0x24e70001, 0xacc20000, 0xacc30004, 0x00e4102b, 0x1440fff8,
-       0x24c60008, 0x00003821, 0x3c080001, 0x25080f7b, 0x91060000, 0x3c020001,
-       0x90420f7c, 0x2503000d, 0x00c32821, 0x00461023, 0x00021fc2, 0x00431021,
-       0x00021043, 0x1840000c, 0x00002021, 0x91020001, 0x00461023, 0x00021fc2,
-       0x00431021, 0x00021843, 0x94a20000, 0x24e70001, 0x00822021, 0x00e3102a,
-       0x1440fffb, 0x24a50002, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402,
-       0x00822021, 0x3c02ffff, 0x01821024, 0x3083ffff, 0x00431025, 0x3c010001,
-       0x080040fa, 0xac220f80, 0x3c050001, 0x24a50f7c, 0x90a20000, 0x3c0c0001,
-       0x01836021, 0x8d8c8018, 0x000220c2, 0x1080000e, 0x00003821, 0x01603021,
-       0x24a5000c, 0x8ca20000, 0x8ca30004, 0x24a50008, 0x24e70001, 0xacc20000,
-       0xacc30004, 0x00e4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 0x24a50f7c,
-       0x90a20000, 0x30430007, 0x24020004, 0x10620011, 0x28620005, 0x10400005,
-       0x24020002, 0x10620008, 0x000710c0, 0x080040fa, 0x00000000, 0x24020006,
-       0x1062000e, 0x000710c0, 0x080040fa, 0x00000000, 0x00a21821, 0x9463000c,
-       0x004b1021, 0x080040fa, 0xa4430000, 0x000710c0, 0x00a21821, 0x8c63000c,
-       0x004b1021, 0x080040fa, 0xac430000, 0x00a21821, 0x8c63000c, 0x004b2021,
-       0x00a21021, 0xac830000, 0x94420010, 0xa4820004, 0x95e70006, 0x3c020001,
-       0x90420f7c, 0x3c030001, 0x90630f7a, 0x00e2c823, 0x3c020001, 0x90420f7b,
-       0x24630028, 0x01e34021, 0x24420028, 0x15200012, 0x01e23021, 0x94c2000c,
-       0x3c010001, 0xa4220f78, 0x94c20004, 0x94c30006, 0x3c010001, 0xa4200f76,
-       0x3c010001, 0xa4200f72, 0x00021400, 0x00431025, 0x3c010001, 0xac220f6c,
-       0x95020004, 0x3c010001, 0x08004124, 0xa4220f70, 0x3c020001, 0x94420f70,
-       0x3c030001, 0x94630f72, 0x00431021, 0xa5020004, 0x3c020001, 0x94420f6c,
-       0xa4c20004, 0x3c020001, 0x8c420f6c, 0xa4c20006, 0x3c040001, 0x94840f72,
-       0x3c020001, 0x94420f70, 0x3c0a0001, 0x954a0f76, 0x00441821, 0x3063ffff,
-       0x0062182a, 0x24020002, 0x1122000b, 0x00832023, 0x3c030001, 0x94630f78,
-       0x30620009, 0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 0x94420f78,
-       0x30420009, 0x01425023, 0x24020001, 0x1122001b, 0x29220002, 0x50400005,
-       0x24020002, 0x11200007, 0x31a2ffff, 0x08004197, 0x00000000, 0x1122001d,
-       0x24020016, 0x08004197, 0x31a2ffff, 0x3c0e0001, 0x95ce0f80, 0x10800005,
-       0x01806821, 0x01c42021, 0x00041c02, 0x3082ffff, 0x00627021, 0x000e1027,
-       0xa502000a, 0x3c030001, 0x90630f7b, 0x31a2ffff, 0x00e21021, 0x0800418d,
-       0x00432023, 0x3c020001, 0x94420f80, 0x00442021, 0x00041c02, 0x3082ffff,
-       0x00622021, 0x00807021, 0x00041027, 0x08004185, 0xa502000a, 0x3c050001,
-       0x24a50f7a, 0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 0x90a20000,
-       0x00e21023, 0xa5020002, 0x3c030001, 0x94630f80, 0x3c020001, 0x94420f5a,
-       0x30e5ffff, 0x00641821, 0x00451023, 0x00622023, 0x00041c02, 0x3082ffff,
-       0x00622021, 0x00041027, 0xa502000a, 0x3c030001, 0x90630f7c, 0x24620001,
-       0x14a20005, 0x00807021, 0x01631021, 0x90420000, 0x08004185, 0x00026200,
-       0x24620002, 0x14a20003, 0x306200fe, 0x004b1021, 0x944c0000, 0x3c020001,
-       0x94420f82, 0x3183ffff, 0x3c040001, 0x90840f7b, 0x00431021, 0x00e21021,
-       0x00442023, 0x008a2021, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402,
-       0x00822021, 0x00806821, 0x00041027, 0xa4c20010, 0x31a2ffff, 0x000e1c00,
-       0x00431025, 0x3c040001, 0x24840f72, 0xade20010, 0x94820000, 0x3c050001,
-       0x94a50f76, 0x3c030001, 0x8c630f6c, 0x24420001, 0x00b92821, 0xa4820000,
-       0x3322ffff, 0x00622021, 0x0083182b, 0x3c010001, 0xa4250f76, 0x10600003,
-       0x24a2ffff, 0x3c010001, 0xa4220f76, 0x3c024000, 0x03021025, 0x3c010001,
-       0xac240f6c, 0xaf621008, 0x03e00008, 0x27bd0010, 0x3c030001, 0x90630f56,
-       0x27bdffe8, 0x24020001, 0xafbf0014, 0x10620026, 0xafb00010, 0x8f620cf4,
-       0x2442ffff, 0x3042007f, 0x00021100, 0x8c434000, 0x3c010001, 0xac230f64,
-       0x8c434008, 0x24444000, 0x8c5c4004, 0x30620040, 0x14400002, 0x24020088,
-       0x24020008, 0x3c010001, 0xa4220f68, 0x30620004, 0x10400005, 0x24020001,
-       0x3c010001, 0xa0220f57, 0x080041d5, 0x00031402, 0x3c010001, 0xa0200f57,
-       0x00031402, 0x3c010001, 0xa4220f54, 0x9483000c, 0x24020001, 0x3c010001,
-       0xa4200f50, 0x3c010001, 0xa0220f56, 0x3c010001, 0xa4230f62, 0x24020001,
-       0x1342001e, 0x00000000, 0x13400005, 0x24020003, 0x13420067, 0x00000000,
-       0x080042cf, 0x00000000, 0x3c020001, 0x94420f62, 0x241a0001, 0x3c010001,
-       0xa4200f5e, 0x3c010001, 0xa4200f52, 0x304407ff, 0x00021bc2, 0x00031823,
-       0x3063003e, 0x34630036, 0x00021242, 0x3042003c, 0x00621821, 0x3c010001,
-       0xa4240f58, 0x00832021, 0x24630030, 0x3c010001, 0xa4240f5a, 0x3c010001,
-       0xa4230f5c, 0x3c060001, 0x24c60f52, 0x94c50000, 0x94c30002, 0x3c040001,
-       0x94840f5a, 0x00651021, 0x0044102a, 0x10400013, 0x3c108000, 0x00a31021,
-       0xa4c20000, 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008,
-       0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4,
-       0x00501024, 0x104000b7, 0x00000000, 0x0800420f, 0x00000000, 0x3c030001,
-       0x94630f50, 0x00851023, 0xa4c40000, 0x00621821, 0x3042ffff, 0x3c010001,
-       0xa4230f50, 0xaf620ce8, 0x3c020001, 0x94420f68, 0x34420024, 0xaf620cec,
-       0x94c30002, 0x3c020001, 0x94420f50, 0x14620012, 0x3c028000, 0x3c108000,
-       0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008, 0x00901024,
-       0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024,
-       0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, 0xaf620cf4, 0x3c108000,
-       0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000,
-       0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003,
-       0x3c070001, 0x24e70f50, 0x94e20000, 0x03821021, 0xaf620ce0, 0x3c020001,
-       0x8c420f64, 0xaf620ce4, 0x3c050001, 0x94a50f54, 0x94e30000, 0x3c040001,
-       0x94840f58, 0x3c020001, 0x94420f5e, 0x00a32823, 0x00822023, 0x30a6ffff,
-       0x3083ffff, 0x00c3102b, 0x14400043, 0x00000000, 0x3c020001, 0x94420f5c,
-       0x00021400, 0x00621025, 0xaf620ce8, 0x94e20000, 0x3c030001, 0x94630f54,
-       0x00441021, 0xa4e20000, 0x3042ffff, 0x14430021, 0x3c020008, 0x3c020001,
-       0x90420f57, 0x10400006, 0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624,
-       0x0800427c, 0x0000d021, 0x3c020001, 0x94420f68, 0x3c030008, 0x34630624,
-       0x00431025, 0xaf620cec, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001,
-       0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
-       0x00000000, 0x8f620cf4, 0x00501024, 0x10400015, 0x00000000, 0x08004283,
-       0x00000000, 0x3c030001, 0x94630f68, 0x34420624, 0x3c108000, 0x00621825,
-       0x3c028000, 0xaf630cec, 0xaf620cf4, 0x8f641008, 0x00901024, 0x14400003,
-       0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7,
-       0x00000000, 0x3c010001, 0x080042cf, 0xa4200f5e, 0x3c020001, 0x94420f5c,
-       0x00021400, 0x00c21025, 0xaf620ce8, 0x3c020001, 0x90420f57, 0x10400009,
-       0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624, 0x0000d021, 0x00431025,
-       0xaf620cec, 0x080042c1, 0x3c108000, 0x3c020001, 0x94420f68, 0x3c030008,
-       0x34630604, 0x00431025, 0xaf620cec, 0x3c020001, 0x94420f5e, 0x00451021,
-       0x3c010001, 0xa4220f5e, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001,
-       0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
-       0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x8fbf0014,
-       0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000, 0x27bdffe0, 0x3c040001,
-       0x24840ec0, 0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010,
-       0x0c004378, 0xafa00014, 0x0000d021, 0x24020130, 0xaf625000, 0x3c010001,
-       0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018, 0x03e00008, 0x27bd0020,
-       0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010, 0xaf60680c, 0x8f626804,
-       0x34420082, 0xaf626804, 0x8f634000, 0x24020b50, 0x3c010001, 0xac220f20,
-       0x24020b78, 0x3c010001, 0xac220f30, 0x34630002, 0xaf634000, 0x0c004315,
-       0x00808021, 0x3c010001, 0xa0220f34, 0x304200ff, 0x24030002, 0x14430005,
-       0x00000000, 0x3c020001, 0x8c420f20, 0x08004308, 0xac5000c0, 0x3c020001,
-       0x8c420f20, 0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, 0x3c010001,
-       0xac220f28, 0x3c010001, 0xac230f38, 0x3c010001, 0xac240f24, 0x8fbf0014,
-       0x8fb00010, 0x03e00008, 0x27bd0018, 0x03e00008, 0x24020001, 0x27bdfff8,
-       0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe, 0x00000000,
-       0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008, 0x27bd0008,
-       0x8f634450, 0x3c020001, 0x8c420f28, 0x00031c02, 0x0043102b, 0x14400008,
-       0x3c038000, 0x3c040001, 0x8c840f38, 0x8f624450, 0x00021c02, 0x0083102b,
-       0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024, 0x1440fffd,
-       0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff, 0x2442e000,
-       0x2c422001, 0x14400003, 0x3c024000, 0x08004347, 0x2402ffff, 0x00822025,
-       0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021, 0x03e00008,
-       0x00000000, 0x8f624450, 0x3c030001, 0x8c630f24, 0x08004350, 0x3042ffff,
-       0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000, 0x03e00008,
-       0x00000000, 0x27bdffe0, 0x00802821, 0x3c040001, 0x24840ed0, 0x00003021,
-       0x00003821, 0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0800435f,
-       0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x3c020001, 0x3442d600,
-       0x3c030001, 0x3463d600, 0x3c040001, 0x3484ddff, 0x3c010001, 0xac220f40,
-       0x24020040, 0x3c010001, 0xac220f44, 0x3c010001, 0xac200f3c, 0xac600000,
-       0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000,
-       0x00804821, 0x8faa0010, 0x3c020001, 0x8c420f3c, 0x3c040001, 0x8c840f44,
-       0x8fab0014, 0x24430001, 0x0044102b, 0x3c010001, 0xac230f3c, 0x14400003,
-       0x00004021, 0x3c010001, 0xac200f3c, 0x3c020001, 0x8c420f3c, 0x3c030001,
-       0x8c630f40, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001,
-       0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020001, 0x8c420f3c,
-       0x3c030001, 0x8c630f40, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008,
-       0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c,
-       0x00000000, 0x00000000, 0x00000000,
-};
-
-static const u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = {
-       0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
-       0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000,
-       0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
-       0x00000000, 0x00000000, 0x00000000,
-};
+       return 0;
+}
 
-static const u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = {
-       0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000,
-};
+/* 5705 needs a special version of the TSO firmware.  */
 
 /* tp->lock is held. */
 static int tg3_load_tso_firmware(struct tg3 *tp)
 {
        struct fw_info info;
+       const __be32 *fw_data;
        unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
        int err, i;
 
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
                return 0;
 
+       fw_data = (void *)tp->fw->data;
+
+       /* Firmware blob starts with version numbers, followed by
+          start address and length. We are setting complete length.
+          length = end_address_of_bss - start_address_of_text.
+          Remainder is the blob to be loaded contiguously
+          from start address. */
+
+       info.fw_base = be32_to_cpu(fw_data[1]);
+       cpu_scratch_size = tp->fw_len;
+       info.fw_len = tp->fw->size - 12;
+       info.fw_data = &fw_data[3];
+
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-               info.text_base = TG3_TSO5_FW_TEXT_ADDR;
-               info.text_len = TG3_TSO5_FW_TEXT_LEN;
-               info.text_data = &tg3Tso5FwText[0];
-               info.rodata_base = TG3_TSO5_FW_RODATA_ADDR;
-               info.rodata_len = TG3_TSO5_FW_RODATA_LEN;
-               info.rodata_data = &tg3Tso5FwRodata[0];
-               info.data_base = TG3_TSO5_FW_DATA_ADDR;
-               info.data_len = TG3_TSO5_FW_DATA_LEN;
-               info.data_data = &tg3Tso5FwData[0];
                cpu_base = RX_CPU_BASE;
                cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705;
-               cpu_scratch_size = (info.text_len +
-                                   info.rodata_len +
-                                   info.data_len +
-                                   TG3_TSO5_FW_SBSS_LEN +
-                                   TG3_TSO5_FW_BSS_LEN);
        } else {
-               info.text_base = TG3_TSO_FW_TEXT_ADDR;
-               info.text_len = TG3_TSO_FW_TEXT_LEN;
-               info.text_data = &tg3TsoFwText[0];
-               info.rodata_base = TG3_TSO_FW_RODATA_ADDR;
-               info.rodata_len = TG3_TSO_FW_RODATA_LEN;
-               info.rodata_data = &tg3TsoFwRodata[0];
-               info.data_base = TG3_TSO_FW_DATA_ADDR;
-               info.data_len = TG3_TSO_FW_DATA_LEN;
-               info.data_data = &tg3TsoFwData[0];
                cpu_base = TX_CPU_BASE;
                cpu_scratch_base = TX_CPU_SCRATCH_BASE;
                cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
@@ -6269,21 +6418,21 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
 
        /* Now startup the cpu. */
        tw32(cpu_base + CPU_STATE, 0xffffffff);
-       tw32_f(cpu_base + CPU_PC,    info.text_base);
+       tw32_f(cpu_base + CPU_PC, info.fw_base);
 
        for (i = 0; i < 5; i++) {
-               if (tr32(cpu_base + CPU_PC) == info.text_base)
+               if (tr32(cpu_base + CPU_PC) == info.fw_base)
                        break;
                tw32(cpu_base + CPU_STATE, 0xffffffff);
                tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
-               tw32_f(cpu_base + CPU_PC,    info.text_base);
+               tw32_f(cpu_base + CPU_PC, info.fw_base);
                udelay(1000);
        }
        if (i >= 5) {
                printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s "
                       "to set CPU PC, is %08x should be %08x\n",
                       tp->dev->name, tr32(cpu_base + CPU_PC),
-                      info.text_base);
+                      info.fw_base);
                return -ENODEV;
        }
        tw32(cpu_base + CPU_STATE, 0xffffffff);
@@ -6292,43 +6441,6 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
 }
 
 
-/* tp->lock is held. */
-static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
-{
-       u32 addr_high, addr_low;
-       int i;
-
-       addr_high = ((tp->dev->dev_addr[0] << 8) |
-                    tp->dev->dev_addr[1]);
-       addr_low = ((tp->dev->dev_addr[2] << 24) |
-                   (tp->dev->dev_addr[3] << 16) |
-                   (tp->dev->dev_addr[4] <<  8) |
-                   (tp->dev->dev_addr[5] <<  0));
-       for (i = 0; i < 4; i++) {
-               if (i == 1 && skip_mac_1)
-                       continue;
-               tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
-               tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
-       }
-
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
-               for (i = 0; i < 12; i++) {
-                       tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
-                       tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
-               }
-       }
-
-       addr_high = (tp->dev->dev_addr[0] +
-                    tp->dev->dev_addr[1] +
-                    tp->dev->dev_addr[2] +
-                    tp->dev->dev_addr[3] +
-                    tp->dev->dev_addr[4] +
-                    tp->dev->dev_addr[5]) &
-               TX_BACKOFF_SEED_MASK;
-       tw32(MAC_TX_BACKOFF_SEED, addr_high);
-}
-
 static int tg3_set_mac_addr(struct net_device *dev, void *p)
 {
        struct tg3 *tp = netdev_priv(dev);
@@ -6423,7 +6535,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                tg3_abort_hw(tp, 1);
        }
 
-       if (reset_phy)
+       if (reset_phy &&
+           !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB))
                tg3_phy_reset(tp);
 
        err = tg3_chip_reset(tp);
@@ -6432,8 +6545,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 
        tg3_write_sig_legacy(tp, RESET_KIND_INIT);
 
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-           tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) {
                val = tr32(TG3_CPMU_CTRL);
                val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
                tw32(TG3_CPMU_CTRL, val);
@@ -6545,11 +6657,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) {
                int fw_len;
 
-               fw_len = (TG3_TSO5_FW_TEXT_LEN +
-                         TG3_TSO5_FW_RODATA_LEN +
-                         TG3_TSO5_FW_DATA_LEN +
-                         TG3_TSO5_FW_SBSS_LEN +
-                         TG3_TSO5_FW_BSS_LEN);
+               fw_len = tp->fw_len;
                fw_len = (fw_len + (0x80 - 1)) & ~(0x80 - 1);
                tw32(BUFMGR_MB_POOL_ADDR,
                     NIC_SRAM_MBUF_POOL_BASE5705 + fw_len);
@@ -6738,7 +6846,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                      RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
                      RDMAC_MODE_LNGREAD_ENAB);
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
                rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB |
                              RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
                              RDMAC_MODE_MBUF_SBD_CRPT_ENAB;
@@ -6760,7 +6870,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
 
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
-               rdmac_mode |= (1 << 27);
+               rdmac_mode |= RDMAC_MODE_IPV4_LSO_EN;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+               rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN;
 
        /* Receive/send statistics. */
        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
@@ -6833,7 +6947,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                udelay(10);
        }
 
-       tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+               tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+       else
+               tp->mac_mode = 0;
+       tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
                MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
            !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
@@ -6903,11 +7021,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        }
 
        /* Enable host coalescing bug fix */
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761))
-               val |= (1 << 29);
+       if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
+               val |= WDMAC_MODE_STATUS_TAG_FIX;
 
        tw32_f(WDMAC_MODE, val);
        udelay(40);
@@ -6967,24 +7082,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        udelay(100);
 
        tp->rx_mode = RX_MODE_ENABLE;
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+       if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
                tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
 
        tw32_f(MAC_RX_MODE, tp->rx_mode);
        udelay(10);
 
-       if (tp->link_config.phy_is_low_power) {
-               tp->link_config.phy_is_low_power = 0;
-               tp->link_config.speed = tp->link_config.orig_speed;
-               tp->link_config.duplex = tp->link_config.orig_duplex;
-               tp->link_config.autoneg = tp->link_config.orig_autoneg;
-       }
-
-       tp->mi_mode = MAC_MI_MODE_BASE;
-       tw32_f(MAC_MI_MODE, tp->mi_mode);
-       udelay(80);
-
        tw32(MAC_LED_CTRL, tp->led_ctrl);
 
        tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
@@ -7031,19 +7134,28 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
        }
 
-       err = tg3_setup_phy(tp, 0);
-       if (err)
-               return err;
+       if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) {
+               if (tp->link_config.phy_is_low_power) {
+                       tp->link_config.phy_is_low_power = 0;
+                       tp->link_config.speed = tp->link_config.orig_speed;
+                       tp->link_config.duplex = tp->link_config.orig_duplex;
+                       tp->link_config.autoneg = tp->link_config.orig_autoneg;
+               }
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
-               u32 tmp;
+               err = tg3_setup_phy(tp, 0);
+               if (err)
+                       return err;
 
-               /* Clear CRC stats. */
-               if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) {
-                       tg3_writephy(tp, MII_TG3_TEST1,
-                                    tmp | MII_TG3_TEST1_CRC_EN);
-                       tg3_readphy(tp, 0x14, &tmp);
+               if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+                   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
+                       u32 tmp;
+
+                       /* Clear CRC stats. */
+                       if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) {
+                               tg3_writephy(tp, MII_TG3_TEST1,
+                                            tmp | MII_TG3_TEST1_CRC_EN);
+                               tg3_readphy(tp, 0x14, &tmp);
+                       }
                }
        }
 
@@ -7096,7 +7208,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 
        default:
                break;
-       };
+       }
 
        if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
                /* Write our heartbeat update interval to APE. */
@@ -7113,21 +7225,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
  */
 static int tg3_init_hw(struct tg3 *tp, int reset_phy)
 {
-       int err;
-
-       /* Force the chip into D0. */
-       err = tg3_set_power_state(tp, PCI_D0);
-       if (err)
-               goto out;
-
        tg3_switch_clocks(tp);
 
        tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 
-       err = tg3_reset_hw(tp, reset_phy);
-
-out:
-       return err;
+       return tg3_reset_hw(tp, reset_phy);
 }
 
 #define TG3_STAT_ADD32(PSTAT, REG) \
@@ -7276,17 +7378,17 @@ static void tg3_timer(unsigned long __opaque)
         * resets.
         */
        if (!--tp->asf_counter) {
-               if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
-                       u32 val;
+               if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
+                   !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
+                       tg3_wait_for_event_ack(tp);
 
                        tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
                                      FWCMD_NICDRV_ALIVE3);
                        tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
                        /* 5 seconds timeout */
                        tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
-                       val = tr32(GRC_RX_CPU_EVENT);
-                       val |= (1 << 14);
-                       tw32(GRC_RX_CPU_EVENT, val);
+
+                       tg3_generate_fw_event(tp);
                }
                tp->asf_counter = tp->asf_multiplier;
        }
@@ -7433,20 +7535,65 @@ static int tg3_test_msi(struct tg3 *tp)
        return err;
 }
 
+static int tg3_request_firmware(struct tg3 *tp)
+{
+       const __be32 *fw_data;
+
+       if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) {
+               printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
+                      tp->dev->name, tp->fw_needed);
+               return -ENOENT;
+       }
+
+       fw_data = (void *)tp->fw->data;
+
+       /* Firmware blob starts with version numbers, followed by
+        * start address and _full_ length including BSS sections
+        * (which must be longer than the actual data, of course
+        */
+
+       tp->fw_len = be32_to_cpu(fw_data[2]);   /* includes bss */
+       if (tp->fw_len < (tp->fw->size - 12)) {
+               printk(KERN_ERR "%s: bogus length %d in \"%s\"\n",
+                      tp->dev->name, tp->fw_len, tp->fw_needed);
+               release_firmware(tp->fw);
+               tp->fw = NULL;
+               return -EINVAL;
+       }
+
+       /* We no longer need firmware; we have it. */
+       tp->fw_needed = NULL;
+       return 0;
+}
+
 static int tg3_open(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
        int err;
 
-       netif_carrier_off(tp->dev);
+       if (tp->fw_needed) {
+               err = tg3_request_firmware(tp);
+               if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
+                       if (err)
+                               return err;
+               } else if (err) {
+                       printk(KERN_WARNING "%s: TSO capability disabled.\n",
+                              tp->dev->name);
+                       tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
+               } else if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
+                       printk(KERN_NOTICE "%s: TSO capability restored.\n",
+                              tp->dev->name);
+                       tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
+               }
+       }
 
-       tg3_full_lock(tp, 0);
+       netif_carrier_off(tp->dev);
 
        err = tg3_set_power_state(tp, PCI_D0);
-       if (err) {
-               tg3_full_unlock(tp);
+       if (err)
                return err;
-       }
+
+       tg3_full_lock(tp, 0);
 
        tg3_disable_ints(tp);
        tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
@@ -7556,6 +7703,8 @@ static int tg3_open(struct net_device *dev)
                }
        }
 
+       tg3_phy_start(tp);
+
        tg3_full_lock(tp, 0);
 
        add_timer(&tp->timer);
@@ -7856,6 +8005,11 @@ static inline unsigned long get_stat64(tg3_stat64_t *val)
        return ret;
 }
 
+static inline u64 get_estat64(tg3_stat64_t *val)
+{
+       return ((u64)val->high << 32) | ((u64)val->low);
+}
+
 static unsigned long calc_crc_errors(struct tg3 *tp)
 {
        struct tg3_hw_stats *hw_stats = tp->hw_stats;
@@ -7884,7 +8038,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
 
 #define ESTAT_ADD(member) \
        estats->member =        old_estats->member + \
-                               get_stat64(&hw_stats->member)
+                               get_estat64(&hw_stats->member)
 
 static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
 {
@@ -8357,7 +8511,13 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 
 static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-       struct tg3 *tp = netdev_priv(dev);
+       struct tg3 *tp = netdev_priv(dev);
+
+       if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+               if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
+                       return -EAGAIN;
+               return phy_ethtool_gset(tp->mdio_bus->phy_map[PHY_ADDR], cmd);
+       }
 
        cmd->supported = (SUPPORTED_Autoneg);
 
@@ -8394,6 +8554,12 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct tg3 *tp = netdev_priv(dev);
 
+       if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+               if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
+                       return -EAGAIN;
+               return phy_ethtool_sset(tp->mdio_bus->phy_map[PHY_ADDR], cmd);
+       }
+
        if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) {
                /* These are the only valid advertisement bits allowed.  */
                if (cmd->autoneg == AUTONEG_ENABLE &&
@@ -8411,7 +8577,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                   (cmd->speed == SPEED_1000))
                return -EINVAL;
        else if ((cmd->speed == SPEED_1000) &&
-                (tp->tg3_flags2 & TG3_FLAG_10_100_ONLY))
+                (tp->tg3_flags & TG3_FLAG_10_100_ONLY))
                return -EINVAL;
 
        tg3_full_lock(tp, 0);
@@ -8426,7 +8592,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                tp->link_config.advertising = 0;
                tp->link_config.speed = cmd->speed;
                tp->link_config.duplex = cmd->duplex;
-       }
+       }
 
        tp->link_config.orig_speed = tp->link_config.speed;
        tp->link_config.orig_duplex = tp->link_config.duplex;
@@ -8454,12 +8620,14 @@ static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+       if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) &&
+           device_can_wakeup(&tp->pdev->dev))
                wol->supported = WAKE_MAGIC;
        else
                wol->supported = 0;
        wol->wolopts = 0;
-       if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
+       if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
+           device_can_wakeup(&tp->pdev->dev))
                wol->wolopts = WAKE_MAGIC;
        memset(&wol->sopass, 0, sizeof(wol->sopass));
 }
@@ -8467,18 +8635,22 @@ static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct tg3 *tp = netdev_priv(dev);
+       struct device *dp = &tp->pdev->dev;
 
        if (wol->wolopts & ~WAKE_MAGIC)
                return -EINVAL;
        if ((wol->wolopts & WAKE_MAGIC) &&
-           !(tp->tg3_flags & TG3_FLAG_WOL_CAP))
+           !((tp->tg3_flags & TG3_FLAG_WOL_CAP) && device_can_wakeup(dp)))
                return -EINVAL;
 
        spin_lock_bh(&tp->lock);
-       if (wol->wolopts & WAKE_MAGIC)
+       if (wol->wolopts & WAKE_MAGIC) {
                tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
-       else
+               device_set_wakeup_enable(dp, true);
+       } else {
                tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
+               device_set_wakeup_enable(dp, false);
+       }
        spin_unlock_bh(&tp->lock);
 
        return 0;
@@ -8505,11 +8677,15 @@ static int tg3_set_tso(struct net_device *dev, u32 value)
                        return -EINVAL;
                return 0;
        }
-       if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
-           (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) {
+       if ((dev->features & NETIF_F_IPV6_CSUM) &&
+           (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2)) {
                if (value) {
                        dev->features |= NETIF_F_TSO6;
-                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+                           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+                            GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
                                dev->features |= NETIF_F_TSO_ECN;
                } else
                        dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
@@ -8520,7 +8696,6 @@ static int tg3_set_tso(struct net_device *dev, u32 value)
 static int tg3_nway_reset(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
-       u32 bmcr;
        int r;
 
        if (!netif_running(dev))
@@ -8529,17 +8704,25 @@ static int tg3_nway_reset(struct net_device *dev)
        if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
                return -EINVAL;
 
-       spin_lock_bh(&tp->lock);
-       r = -EINVAL;
-       tg3_readphy(tp, MII_BMCR, &bmcr);
-       if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
-           ((bmcr & BMCR_ANENABLE) ||
-            (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) {
-               tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART |
-                                          BMCR_ANENABLE);
-               r = 0;
+       if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+               if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
+                       return -EAGAIN;
+               r = phy_start_aneg(tp->mdio_bus->phy_map[PHY_ADDR]);
+       } else {
+               u32 bmcr;
+
+               spin_lock_bh(&tp->lock);
+               r = -EINVAL;
+               tg3_readphy(tp, MII_BMCR, &bmcr);
+               if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
+                   ((bmcr & BMCR_ANENABLE) ||
+                    (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) {
+                       tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART |
+                                                  BMCR_ANENABLE);
+                       r = 0;
+               }
+               spin_unlock_bh(&tp->lock);
        }
-       spin_unlock_bh(&tp->lock);
 
        return r;
 }
@@ -8581,6 +8764,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
                return -EINVAL;
 
        if (netif_running(dev)) {
+               tg3_phy_stop(tp);
                tg3_netif_stop(tp);
                irq_sync = 1;
        }
@@ -8604,6 +8788,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 
        tg3_full_unlock(tp);
 
+       if (irq_sync && !err)
+               tg3_phy_start(tp);
+
        return err;
 }
 
@@ -8613,12 +8800,12 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam
 
        epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0;
 
-       if (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX)
+       if (tp->link_config.active_flowctrl & FLOW_CTRL_RX)
                epause->rx_pause = 1;
        else
                epause->rx_pause = 0;
 
-       if (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX)
+       if (tp->link_config.active_flowctrl & FLOW_CTRL_TX)
                epause->tx_pause = 1;
        else
                epause->tx_pause = 0;
@@ -8627,36 +8814,92 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam
 static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
 {
        struct tg3 *tp = netdev_priv(dev);
-       int irq_sync = 0, err = 0;
+       int err = 0;
 
-       if (netif_running(dev)) {
-               tg3_netif_stop(tp);
-               irq_sync = 1;
-       }
+       if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+               if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
+                       return -EAGAIN;
 
-       tg3_full_lock(tp, irq_sync);
+               if (epause->autoneg) {
+                       u32 newadv;
+                       struct phy_device *phydev;
 
-       if (epause->autoneg)
-               tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
-       else
-               tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
-       if (epause->rx_pause)
-               tp->link_config.flowctrl |= TG3_FLOW_CTRL_RX;
-       else
-               tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_RX;
-       if (epause->tx_pause)
-               tp->link_config.flowctrl |= TG3_FLOW_CTRL_TX;
-       else
-               tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_TX;
+                       phydev = tp->mdio_bus->phy_map[PHY_ADDR];
 
-       if (netif_running(dev)) {
-               tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-               err = tg3_restart_hw(tp, 1);
-               if (!err)
-                       tg3_netif_start(tp);
-       }
+                       if (epause->rx_pause) {
+                               if (epause->tx_pause)
+                                       newadv = ADVERTISED_Pause;
+                               else
+                                       newadv = ADVERTISED_Pause |
+                                                ADVERTISED_Asym_Pause;
+                       } else if (epause->tx_pause) {
+                               newadv = ADVERTISED_Asym_Pause;
+                       } else
+                               newadv = 0;
+
+                       if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) {
+                               u32 oldadv = phydev->advertising &
+                                            (ADVERTISED_Pause |
+                                             ADVERTISED_Asym_Pause);
+                               if (oldadv != newadv) {
+                                       phydev->advertising &=
+                                               ~(ADVERTISED_Pause |
+                                                 ADVERTISED_Asym_Pause);
+                                       phydev->advertising |= newadv;
+                                       err = phy_start_aneg(phydev);
+                               }
+                       } else {
+                               tp->link_config.advertising &=
+                                               ~(ADVERTISED_Pause |
+                                                 ADVERTISED_Asym_Pause);
+                               tp->link_config.advertising |= newadv;
+                       }
+               } else {
+                       if (epause->rx_pause)
+                               tp->link_config.flowctrl |= FLOW_CTRL_RX;
+                       else
+                               tp->link_config.flowctrl &= ~FLOW_CTRL_RX;
 
-       tg3_full_unlock(tp);
+                       if (epause->tx_pause)
+                               tp->link_config.flowctrl |= FLOW_CTRL_TX;
+                       else
+                               tp->link_config.flowctrl &= ~FLOW_CTRL_TX;
+
+                       if (netif_running(dev))
+                               tg3_setup_flow_control(tp, 0, 0);
+               }
+       } else {
+               int irq_sync = 0;
+
+               if (netif_running(dev)) {
+                       tg3_netif_stop(tp);
+                       irq_sync = 1;
+               }
+
+               tg3_full_lock(tp, irq_sync);
+
+               if (epause->autoneg)
+                       tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+               else
+                       tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
+               if (epause->rx_pause)
+                       tp->link_config.flowctrl |= FLOW_CTRL_RX;
+               else
+                       tp->link_config.flowctrl &= ~FLOW_CTRL_RX;
+               if (epause->tx_pause)
+                       tp->link_config.flowctrl |= FLOW_CTRL_TX;
+               else
+                       tp->link_config.flowctrl &= ~FLOW_CTRL_TX;
+
+               if (netif_running(dev)) {
+                       tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+                       err = tg3_restart_hw(tp, 1);
+                       if (!err)
+                               tg3_netif_start(tp);
+               }
+
+               tg3_full_unlock(tp);
+       }
 
        return err;
 }
@@ -8697,10 +8940,7 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data)
                return 0;
        }
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+       if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
                ethtool_op_set_tx_ipv6_csum(dev, data);
        else
                ethtool_op_set_tx_csum(dev, data);
@@ -8744,7 +8984,7 @@ static int tg3_phys_id(struct net_device *dev, u32 data)
                return -EAGAIN;
 
        if (data == 0)
-               data = 2;
+               data = UINT_MAX / 2;
 
        for (i = 0; i < (data * 2); i++) {
                if ((i % 2) == 0)
@@ -9217,17 +9457,13 @@ static int tg3_test_memory(struct tg3 *tp)
        int err = 0;
        int i;
 
-       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
-                       mem_tbl = mem_tbl_5755;
-               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
-                       mem_tbl = mem_tbl_5906;
-               else
-                       mem_tbl = mem_tbl_5705;
-       } else
+       if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
+               mem_tbl = mem_tbl_5755;
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+               mem_tbl = mem_tbl_5906;
+       else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+               mem_tbl = mem_tbl_5705;
+       else
                mem_tbl = mem_tbl_570x;
 
        for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
@@ -9427,7 +9663,11 @@ static int tg3_test_loopback(struct tg3 *tp)
        if (err)
                return TG3_LOOPBACK_FAILED;
 
-       if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+       /* Turn off gphy autopowerdown. */
+       if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
+               tg3_phy_toggle_apd(tp, false);
+
+       if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
                int i;
                u32 status;
 
@@ -9444,7 +9684,7 @@ static int tg3_test_loopback(struct tg3 *tp)
                if (status != CPMU_MUTEX_GNT_DRIVER)
                        return TG3_LOOPBACK_FAILED;
 
-               /* Turn off power management based on link speed. */
+               /* Turn off link-based power management. */
                cpmuctrl = tr32(TG3_CPMU_CTRL);
                tw32(TG3_CPMU_CTRL,
                     cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE |
@@ -9454,18 +9694,23 @@ static int tg3_test_loopback(struct tg3 *tp)
        if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
                err |= TG3_MAC_LOOPBACK_FAILED;
 
-       if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+       if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
                tw32(TG3_CPMU_CTRL, cpmuctrl);
 
                /* Release the mutex */
                tw32(TG3_CPMU_MUTEX_GNT, CPMU_MUTEX_GNT_DRIVER);
        }
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+       if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+           !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) {
                if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK))
                        err |= TG3_PHY_LOOPBACK_FAILED;
        }
 
+       /* Re-enable gphy autopowerdown. */
+       if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
+               tg3_phy_toggle_apd(tp, true);
+
        return err;
 }
 
@@ -9488,9 +9733,10 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                data[1] = 1;
        }
        if (etest->flags & ETH_TEST_FL_OFFLINE) {
-               int err, irq_sync = 0;
+               int err, err2 = 0, irq_sync = 0;
 
                if (netif_running(dev)) {
+                       tg3_phy_stop(tp);
                        tg3_netif_stop(tp);
                        irq_sync = 1;
                }
@@ -9531,11 +9777,15 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
                if (netif_running(dev)) {
                        tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
-                       if (!tg3_restart_hw(tp, 1))
+                       err2 = tg3_restart_hw(tp, 1);
+                       if (!err2)
                                tg3_netif_start(tp);
                }
 
                tg3_full_unlock(tp);
+
+               if (irq_sync && !err2)
+                       tg3_phy_start(tp);
        }
        if (tp->link_config.phy_is_low_power)
                tg3_set_power_state(tp, PCI_D3hot);
@@ -9548,6 +9798,12 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        struct tg3 *tp = netdev_priv(dev);
        int err;
 
+       if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+               if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED))
+                       return -EAGAIN;
+               return phy_mii_ioctl(tp->mdio_bus->phy_map[PHY_ADDR], data, cmd);
+       }
+
        switch(cmd) {
        case SIOCGMIIPHY:
                data->phy_id = PHY_ADDR;
@@ -9764,7 +10020,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp)
                        return;
                }
        }
-       tp->nvram_size = 0x80000;
+       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
 }
 
 static void __devinit tg3_get_nvram_info(struct tg3 *tp)
@@ -9905,11 +10161,14 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
                        tp->nvram_pagesize = 264;
                        if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 ||
                            nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5)
-                               tp->nvram_size = (protect ? 0x3e200 : 0x80000);
+                               tp->nvram_size = (protect ? 0x3e200 :
+                                                 TG3_NVRAM_SIZE_512KB);
                        else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
-                               tp->nvram_size = (protect ? 0x1f200 : 0x40000);
+                               tp->nvram_size = (protect ? 0x1f200 :
+                                                 TG3_NVRAM_SIZE_256KB);
                        else
-                               tp->nvram_size = (protect ? 0x1f200 : 0x20000);
+                               tp->nvram_size = (protect ? 0x1f200 :
+                                                 TG3_NVRAM_SIZE_128KB);
                        break;
                case FLASH_5752VENDOR_ST_M45PE10:
                case FLASH_5752VENDOR_ST_M45PE20:
@@ -9919,11 +10178,17 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
                        tp->tg3_flags2 |= TG3_FLG2_FLASH;
                        tp->nvram_pagesize = 256;
                        if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10)
-                               tp->nvram_size = (protect ? 0x10000 : 0x20000);
+                               tp->nvram_size = (protect ?
+                                                 TG3_NVRAM_SIZE_64KB :
+                                                 TG3_NVRAM_SIZE_128KB);
                        else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20)
-                               tp->nvram_size = (protect ? 0x10000 : 0x40000);
+                               tp->nvram_size = (protect ?
+                                                 TG3_NVRAM_SIZE_64KB :
+                                                 TG3_NVRAM_SIZE_256KB);
                        else
-                               tp->nvram_size = (protect ? 0x20000 : 0x80000);
+                               tp->nvram_size = (protect ?
+                                                 TG3_NVRAM_SIZE_128KB :
+                                                 TG3_NVRAM_SIZE_512KB);
                        break;
        }
 }
@@ -10017,37 +10282,133 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
                        case FLASH_5761VENDOR_ATMEL_MDB161D:
                        case FLASH_5761VENDOR_ST_A_M45PE16:
                        case FLASH_5761VENDOR_ST_M_M45PE16:
-                               tp->nvram_size = 0x100000;
+                               tp->nvram_size = TG3_NVRAM_SIZE_2MB;
                                break;
                        case FLASH_5761VENDOR_ATMEL_ADB081D:
                        case FLASH_5761VENDOR_ATMEL_MDB081D:
                        case FLASH_5761VENDOR_ST_A_M45PE80:
                        case FLASH_5761VENDOR_ST_M_M45PE80:
-                               tp->nvram_size = 0x80000;
+                               tp->nvram_size = TG3_NVRAM_SIZE_1MB;
                                break;
                        case FLASH_5761VENDOR_ATMEL_ADB041D:
                        case FLASH_5761VENDOR_ATMEL_MDB041D:
                        case FLASH_5761VENDOR_ST_A_M45PE40:
                        case FLASH_5761VENDOR_ST_M_M45PE40:
-                               tp->nvram_size = 0x40000;
+                               tp->nvram_size = TG3_NVRAM_SIZE_512KB;
                                break;
                        case FLASH_5761VENDOR_ATMEL_ADB021D:
                        case FLASH_5761VENDOR_ATMEL_MDB021D:
                        case FLASH_5761VENDOR_ST_A_M45PE20:
                        case FLASH_5761VENDOR_ST_M_M45PE20:
-                               tp->nvram_size = 0x20000;
+                               tp->nvram_size = TG3_NVRAM_SIZE_256KB;
                                break;
                }
        }
 }
 
-static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
-{
-       tp->nvram_jedecnum = JEDEC_ATMEL;
-       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
-       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
-}
-
+static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
+{
+       tp->nvram_jedecnum = JEDEC_ATMEL;
+       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+}
+
+static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
+{
+       u32 nvcfg1;
+
+       nvcfg1 = tr32(NVRAM_CFG1);
+
+       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+       case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ:
+       case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+
+               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+               tw32(NVRAM_CFG1, nvcfg1);
+               return;
+       case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+       case FLASH_57780VENDOR_ATMEL_AT45DB011D:
+       case FLASH_57780VENDOR_ATMEL_AT45DB011B:
+       case FLASH_57780VENDOR_ATMEL_AT45DB021D:
+       case FLASH_57780VENDOR_ATMEL_AT45DB021B:
+       case FLASH_57780VENDOR_ATMEL_AT45DB041D:
+       case FLASH_57780VENDOR_ATMEL_AT45DB041B:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+               tp->tg3_flags2 |= TG3_FLG2_FLASH;
+
+               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+               case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+               case FLASH_57780VENDOR_ATMEL_AT45DB011D:
+               case FLASH_57780VENDOR_ATMEL_AT45DB011B:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+                       break;
+               case FLASH_57780VENDOR_ATMEL_AT45DB021D:
+               case FLASH_57780VENDOR_ATMEL_AT45DB021B:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+                       break;
+               case FLASH_57780VENDOR_ATMEL_AT45DB041D:
+               case FLASH_57780VENDOR_ATMEL_AT45DB041B:
+                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+                       break;
+               }
+               break;
+       case FLASH_5752VENDOR_ST_M45PE10:
+       case FLASH_5752VENDOR_ST_M45PE20:
+       case FLASH_5752VENDOR_ST_M45PE40:
+               tp->nvram_jedecnum = JEDEC_ST;
+               tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+               tp->tg3_flags2 |= TG3_FLG2_FLASH;
+
+               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+               case FLASH_5752VENDOR_ST_M45PE10:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+                       break;
+               case FLASH_5752VENDOR_ST_M45PE20:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+                       break;
+               case FLASH_5752VENDOR_ST_M45PE40:
+                       tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+                       break;
+               }
+               break;
+       default:
+               return;
+       }
+
+       switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
+       case FLASH_5752PAGE_SIZE_256:
+               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+               tp->nvram_pagesize = 256;
+               break;
+       case FLASH_5752PAGE_SIZE_512:
+               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+               tp->nvram_pagesize = 512;
+               break;
+       case FLASH_5752PAGE_SIZE_1K:
+               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+               tp->nvram_pagesize = 1024;
+               break;
+       case FLASH_5752PAGE_SIZE_2K:
+               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+               tp->nvram_pagesize = 2048;
+               break;
+       case FLASH_5752PAGE_SIZE_4K:
+               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+               tp->nvram_pagesize = 4096;
+               break;
+       case FLASH_5752PAGE_SIZE_264:
+               tp->nvram_pagesize = 264;
+               break;
+       case FLASH_5752PAGE_SIZE_528:
+               tp->nvram_pagesize = 528;
+               break;
+       }
+}
+
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
 static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
@@ -10081,12 +10442,15 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
                else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
                        tg3_get_5755_nvram_info(tp);
                else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
                        tg3_get_5787_nvram_info(tp);
                else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
                        tg3_get_5761_nvram_info(tp);
                else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                        tg3_get_5906_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+                       tg3_get_57780_nvram_info(tp);
                else
                        tg3_get_nvram_info(tp);
 
@@ -10407,11 +10771,8 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
                if (i == (len - 4))
                        nvram_cmd |= NVRAM_CMD_LAST;
 
-               if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
-                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) &&
-                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) &&
-                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784) &&
-                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) &&
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
+                   !(tp->tg3_flags3 & TG3_FLG3_5755_PLUS) &&
                    (tp->nvram_jedecnum == JEDEC_ST) &&
                    (nvram_cmd & NVRAM_CMD_FIRST)) {
 
@@ -10588,13 +10949,13 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                if ((val & VCPU_CFGSHDW_WOL_ENABLE) &&
                    (val & VCPU_CFGSHDW_WOL_MAGPKT))
                        tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
-               return;
+               goto done;
        }
 
        tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
        if (val == NIC_SRAM_DATA_SIG_MAGIC) {
                u32 nic_cfg, led_cfg;
-               u32 nic_phy_id, ver, cfg2 = 0, eeprom_phy_id;
+               u32 nic_phy_id, ver, cfg2 = 0, cfg4 = 0, eeprom_phy_id;
                int eeprom_phy_serdes = 0;
 
                tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
@@ -10608,6 +10969,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                    (ver > 0) && (ver < 0x100))
                        tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2);
 
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+                       tg3_read_mem(tp, NIC_SRAM_DATA_CFG_4, &cfg4);
+
                if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
                    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
                        eeprom_phy_serdes = 1;
@@ -10680,16 +11044,15 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                                                 LED_CTRL_MODE_PHY_2);
                        break;
 
-               };
+               }
 
                if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
                     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) &&
                    tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
                        tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 
-               if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-                   tp->pci_chip_rev_id == CHIPREV_ID_5784_A1)
-                       tp->led_ctrl = LED_CTRL_MODE_MAC;
+               if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX)
+                       tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
                if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
                        tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
@@ -10708,14 +11071,17 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
                                tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
                }
-               if (nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE)
+
+               if ((nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) &&
+                       (tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
                        tp->tg3_flags3 |= TG3_FLG3_ENABLE_APE;
+
                if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
                    !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL))
                        tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
 
-               if (tp->tg3_flags & TG3_FLAG_WOL_CAP &&
-                   nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE)
+               if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) &&
+                   (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE))
                        tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
 
                if (cfg2 & (1 << 17))
@@ -10726,6 +11092,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                if (cfg2 & (1 << 18))
                        tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS;
 
+               if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+                     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) &&
+                   (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN))
+                       tp->tg3_flags3 |= TG3_FLG3_PHY_ENABLE_APD;
+
                if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
                        u32 cfg3;
 
@@ -10733,7 +11104,67 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                        if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE)
                                tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
                }
+
+               if (cfg4 & NIC_SRAM_RGMII_STD_IBND_DISABLE)
+                       tp->tg3_flags3 |= TG3_FLG3_RGMII_STD_IBND_DISABLE;
+               if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_RX_EN)
+                       tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_RX_EN;
+               if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN)
+                       tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_TX_EN;
+       }
+done:
+       device_init_wakeup(&tp->pdev->dev, tp->tg3_flags & TG3_FLAG_WOL_CAP);
+       device_set_wakeup_enable(&tp->pdev->dev,
+                                tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
+}
+
+static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+{
+       int i;
+       u32 val;
+
+       tw32(OTP_CTRL, cmd | OTP_CTRL_OTP_CMD_START);
+       tw32(OTP_CTRL, cmd);
+
+       /* Wait for up to 1 ms for command to execute. */
+       for (i = 0; i < 100; i++) {
+               val = tr32(OTP_STATUS);
+               if (val & OTP_STATUS_CMD_DONE)
+                       break;
+               udelay(10);
        }
+
+       return (val & OTP_STATUS_CMD_DONE) ? 0 : -EBUSY;
+}
+
+/* Read the gphy configuration from the OTP region of the chip.  The gphy
+ * configuration is a 32-bit value that straddles the alignment boundary.
+ * We do two 32-bit reads and then shift and merge the results.
+ */
+static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
+{
+       u32 bhalf_otp, thalf_otp;
+
+       tw32(OTP_MODE, OTP_MODE_OTP_THRU_GRC);
+
+       if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_INIT))
+               return 0;
+
+       tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC1);
+
+       if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+               return 0;
+
+       thalf_otp = tr32(OTP_READ_DATA);
+
+       tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC2);
+
+       if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
+               return 0;
+
+       bhalf_otp = tr32(OTP_READ_DATA);
+
+       return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
 }
 
 static int __devinit tg3_phy_probe(struct tg3 *tp)
@@ -10742,6 +11173,9 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
        u32 hw_phy_id, hw_phy_id_masked;
        int err;
 
+       if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)
+               return tg3_phy_init(tp);
+
        /* Reading the PHY ID register can conflict with ASF
         * firwmare access to the PHY hardware.
         */
@@ -10978,6 +11412,51 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
        return 1;
 }
 
+static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
+{
+       u32 offset, major, minor, build;
+
+       tp->fw_ver[0] = 's';
+       tp->fw_ver[1] = 'b';
+       tp->fw_ver[2] = '\0';
+
+       if ((val & TG3_EEPROM_SB_FORMAT_MASK) != TG3_EEPROM_SB_FORMAT_1)
+               return;
+
+       switch (val & TG3_EEPROM_SB_REVISION_MASK) {
+       case TG3_EEPROM_SB_REVISION_0:
+               offset = TG3_EEPROM_SB_F1R0_EDH_OFF;
+               break;
+       case TG3_EEPROM_SB_REVISION_2:
+               offset = TG3_EEPROM_SB_F1R2_EDH_OFF;
+               break;
+       case TG3_EEPROM_SB_REVISION_3:
+               offset = TG3_EEPROM_SB_F1R3_EDH_OFF;
+               break;
+       default:
+               return;
+       }
+
+       if (tg3_nvram_read_swab(tp, offset, &val))
+               return;
+
+       build = (val & TG3_EEPROM_SB_EDH_BLD_MASK) >>
+               TG3_EEPROM_SB_EDH_BLD_SHFT;
+       major = (val & TG3_EEPROM_SB_EDH_MAJ_MASK) >>
+               TG3_EEPROM_SB_EDH_MAJ_SHFT;
+       minor =  val & TG3_EEPROM_SB_EDH_MIN_MASK;
+
+       if (minor > 99 || build > 26)
+               return;
+
+       snprintf(&tp->fw_ver[2], 30, " v%d.%02d", major, minor);
+
+       if (build > 0) {
+               tp->fw_ver[8] = 'a' + build - 1;
+               tp->fw_ver[9] = '\0';
+       }
+}
+
 static void __devinit tg3_read_fw_ver(struct tg3 *tp)
 {
        u32 val, offset, start;
@@ -10987,8 +11466,12 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
        if (tg3_nvram_read_swab(tp, 0, &val))
                return;
 
-       if (val != TG3_EEPROM_MAGIC)
+       if (val != TG3_EEPROM_MAGIC) {
+               if ((val & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW)
+                       tg3_read_sb_ver(tp, val);
+
                return;
+       }
 
        if (tg3_nvram_read_swab(tp, 0xc, &offset) ||
            tg3_nvram_read_swab(tp, 0x4, &start))
@@ -11076,11 +11559,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                { },
        };
        u32 misc_ctrl_reg;
-       u32 cacheline_sz_reg;
        u32 pci_state_reg, grc_misc_cfg;
        u32 val;
        u16 pci_cmd;
-       int err, pcie_cap;
+       int err;
 
        /* Force memory write invalidate off.  If we leave it on,
         * then on 5700_BX chips we have to enable a workaround.
@@ -11109,7 +11591,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
                pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
                                      &prod_id_asic_rev);
-               tp->pci_chip_rev_id = prod_id_asic_rev & PROD_ID_ASIC_REV_MASK;
+               tp->pci_chip_rev_id = prod_id_asic_rev;
        }
 
        /* Wrong chip ID in 5752 A0. This code can be removed later
@@ -11177,6 +11659,38 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                }
        }
 
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
+               static struct tg3_dev_id {
+                       u32     vendor;
+                       u32     device;
+               } bridge_chipsets[] = {
+                       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0 },
+                       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1 },
+                       { },
+               };
+               struct tg3_dev_id *pci_id = &bridge_chipsets[0];
+               struct pci_dev *bridge = NULL;
+
+               while (pci_id->vendor != 0) {
+                       bridge = pci_get_device(pci_id->vendor,
+                                               pci_id->device,
+                                               bridge);
+                       if (!bridge) {
+                               pci_id++;
+                               continue;
+                       }
+                       if (bridge->subordinate &&
+                           (bridge->subordinate->number <=
+                            tp->pdev->bus->number) &&
+                           (bridge->subordinate->subordinate >=
+                            tp->pdev->bus->number)) {
+                               tp->tg3_flags3 |= TG3_FLG3_5701_DMA_BUG;
+                               pci_dev_put(bridge);
+                               break;
+                       }
+               }
+       }
+
        /* The EPB bridge inside 5714, 5715, and 5780 cannot support
         * DMA addresses > 40-bit. This bridge may have other additional
         * 57xx devices behind it in some 4-port NIC designs for example.
@@ -11214,25 +11728,23 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
                               tp->misc_host_ctrl);
 
-       pci_read_config_dword(tp->pdev, TG3PCI_CACHELINESZ,
-                             &cacheline_sz_reg);
-
-       tp->pci_cacheline_sz = (cacheline_sz_reg >>  0) & 0xff;
-       tp->pci_lat_timer    = (cacheline_sz_reg >>  8) & 0xff;
-       tp->pci_hdr_type     = (cacheline_sz_reg >> 16) & 0xff;
-       tp->pci_bist         = (cacheline_sz_reg >> 24) & 0xff;
-
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
            (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
                tp->pdev_peer = tg3_find_peer(tp);
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+       /* Intentionally exclude ASIC_REV_5906 */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+               tp->tg3_flags3 |= TG3_FLG3_5755_PLUS;
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
+           (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
            (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
 
@@ -11240,6 +11752,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            (tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
                tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
 
+       /* 5700 B0 chips do not support checksumming correctly due
+        * to hardware bugs.
+        */
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
+               tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
+       else {
+               tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
+               tp->dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+               if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
+                       tp->dev->features |= NETIF_F_IPV6_CSUM;
+       }
+
        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
                tp->tg3_flags |= TG3_FLAG_SUPPORT_MSI;
                if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX ||
@@ -11249,10 +11773,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                     tp->pdev_peer == tp->pdev))
                        tp->tg3_flags &= ~TG3_FLAG_SUPPORT_MSI;
 
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+               if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                        tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
                        tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
@@ -11265,31 +11786,45 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                }
        }
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+            (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
 
-       pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
-       if (pcie_cap != 0) {
+       pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
+                             &pci_state_reg);
+
+       tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
+       if (tp->pcie_cap != 0) {
+               u16 lnkctl;
+
                tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 
                pcie_set_readrq(tp->pdev, 4096);
 
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-                       u16 lnkctl;
-
-                       pci_read_config_word(tp->pdev,
-                                            pcie_cap + PCI_EXP_LNKCTL,
-                                            &lnkctl);
-                       if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN)
+               pci_read_config_word(tp->pdev,
+                                    tp->pcie_cap + PCI_EXP_LNKCTL,
+                                    &lnkctl);
+               if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                                tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2;
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+                               tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG;
                }
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+               tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+       } else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+                  (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+               tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
+               if (!tp->pcix_cap) {
+                       printk(KERN_ERR PFX "Cannot find PCI-X "
+                                           "capability, aborting.\n");
+                       return -EIO;
+               }
+
+               if (!(pci_state_reg & PCISTATE_CONV_PCI_MODE))
+                       tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
        }
 
        /* If we have an AMD 762 or VIA K8T800 chipset, write
@@ -11302,42 +11837,29 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
                tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
 
+       pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+                            &tp->pci_cacheline_sz);
+       pci_read_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+                            &tp->pci_lat_timer);
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
            tp->pci_lat_timer < 64) {
                tp->pci_lat_timer = 64;
-
-               cacheline_sz_reg  = ((tp->pci_cacheline_sz & 0xff) <<  0);
-               cacheline_sz_reg |= ((tp->pci_lat_timer    & 0xff) <<  8);
-               cacheline_sz_reg |= ((tp->pci_hdr_type     & 0xff) << 16);
-               cacheline_sz_reg |= ((tp->pci_bist         & 0xff) << 24);
-
-               pci_write_config_dword(tp->pdev, TG3PCI_CACHELINESZ,
-                                      cacheline_sz_reg);
-       }
-
-       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
-           (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
-               tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
-               if (!tp->pcix_cap) {
-                       printk(KERN_ERR PFX "Cannot find PCI-X "
-                                           "capability, aborting.\n");
-                       return -EIO;
-               }
+               pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+                                     tp->pci_lat_timer);
        }
 
-       pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
-                             &pci_state_reg);
-
-       if (tp->pcix_cap && (pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
-               tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
+       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
+               /* 5700 BX chips need to have their TX producer index
+                * mailboxes written twice to workaround a bug.
+                */
+               tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
 
-               /* If this is a 5700 BX chipset, and we are in PCI-X
-                * mode, enable register write workaround.
+               /* If we are in PCI-X mode, enable register write workaround.
                 *
                 * The workaround is to use indirect register accesses
                 * for all chip writes not to mailbox registers.
                 */
-               if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
+               if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
                        u32 pm_reg;
 
                        tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
@@ -11362,12 +11884,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                }
        }
 
-       /* 5700 BX chips need to have their TX producer index mailboxes
-        * written twice to workaround a bug.
-        */
-       if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
-               tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
-
        if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
                tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
        if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
@@ -11461,16 +11977,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        }
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
                tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
 
-               if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-                   tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 ||
-                   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 ||
-                   tp->pci_chip_rev_id == CHIPREV_ID_5761_A1)
-                       tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES;
-       }
-
        /* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
         * GPIO1 driven high will bring 5700's external PHY out of reset.
         * It is also used as eeprom write protect on LOMs.
@@ -11486,8 +11997,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
                tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+               tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+
+       if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) {
+               /* Turn off the debug UART. */
                tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
+               if (tp->tg3_flags2 & TG3_FLG2_IS_NIC)
+                       /* Keep VMain power. */
+                       tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
+                                             GRC_LCLCTRL_GPIO_OUTPUT0;
+       }
 
        /* Force the chip into D0. */
        err = tg3_set_power_state(tp, PCI_D0);
@@ -11497,12 +12018,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                return err;
        }
 
-       /* 5700 B0 chips do not support checksumming correctly due
-        * to hardware bugs.
-        */
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
-               tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
-
        /* Derive initial jumbo mode from MTU assigned in
         * ether_setup() via the alloc_etherdev() call
         */
@@ -11535,7 +12050,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
                tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
 
-       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
+       if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780) {
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
@@ -11545,18 +12063,34 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                                tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
                        if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
                                tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM;
-               } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
+               } else
                        tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
        }
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+           GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
+               tp->phy_otp = tg3_read_otp_phycfg(tp);
+               if (tp->phy_otp == 0)
+                       tp->phy_otp = TG3_OTP_DEFAULT;
+       }
+
+       if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)
+               tp->mi_mode = MAC_MI_MODE_500KHZ_CONST;
+       else
+               tp->mi_mode = MAC_MI_MODE_BASE;
+
        tp->coalesce_mode = 0;
        if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
            GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
                tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
 
-       /* Initialize MAC MI mode, polling disabled. */
-       tw32_f(MAC_MI_MODE, tp->mi_mode);
-       udelay(80);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+               tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB;
+
+       err = tg3_mdio_init(tp);
+       if (err)
+               return err;
 
        /* Initialize data/descriptor byte/word swapping. */
        val = tr32(GRC_MODE);
@@ -11617,6 +12151,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                                       tp->misc_host_ctrl);
        }
 
+       /* Preserve the APE MAC_MODE bits */
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+               tp->mac_mode = tr32(MAC_MODE) |
+                              MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+       else
+               tp->mac_mode = TG3_DEF_MAC_MODE;
+
        /* these are limited to 10/100 only */
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
             (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
@@ -11629,6 +12170,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
             (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
              tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
              tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
+           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
 
@@ -11637,6 +12179,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                printk(KERN_ERR PFX "(%s) phy probe failed, err %d\n",
                       pci_name(tp->pdev), err);
                /* ... but do not return immediately ... */
+               tg3_mdio_fini(tp);
        }
 
        tg3_read_partno(tp);
@@ -11677,19 +12220,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        else
                tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
 
-       /* All chips before 5787 can get confused if TX buffers
-        * straddle the 4GB address boundary in some cases.
-        */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
-               tp->dev->hard_start_xmit = tg3_start_xmit;
-       else
-               tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug;
-
-       tp->rx_offset = 2;
+       tp->rx_offset = NET_IP_ALIGN;
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
            (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
                tp->rx_offset = 0;
@@ -11804,7 +12335,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
        }
 
        if (!is_valid_ether_addr(&dev->dev_addr[0])) {
-#ifdef CONFIG_SPARC64
+#ifdef CONFIG_SPARC
                if (!tg3_get_default_macaddr_sparc(tp))
                        return 0;
 #endif
@@ -11886,7 +12417,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
                        val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX |
                                DMA_RWCTRL_WRITE_BNDRY_384_PCIX);
                        break;
-               };
+               }
        } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
                switch (cacheline_size) {
                case 16:
@@ -11903,7 +12434,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
                        val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
                        val |= DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
                        break;
-               };
+               }
        } else {
                switch (cacheline_size) {
                case 16:
@@ -11947,7 +12478,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
                        val |= (DMA_RWCTRL_READ_BNDRY_1024 |
                                DMA_RWCTRL_WRITE_BNDRY_1024);
                        break;
-               };
+               }
        }
 
 out:
@@ -12307,7 +12838,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        case PHY_ID_BCM8002:    return "8002/serdes";
        case 0:                 return "serdes";
        default:                return "unknown";
-       };
+       }
 }
 
 static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
@@ -12405,17 +12936,53 @@ static void __devinit tg3_init_coal(struct tg3 *tp)
        }
 }
 
+static const struct net_device_ops tg3_netdev_ops = {
+       .ndo_open               = tg3_open,
+       .ndo_stop               = tg3_close,
+       .ndo_start_xmit         = tg3_start_xmit,
+       .ndo_get_stats          = tg3_get_stats,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_multicast_list = tg3_set_rx_mode,
+       .ndo_set_mac_address    = tg3_set_mac_addr,
+       .ndo_do_ioctl           = tg3_ioctl,
+       .ndo_tx_timeout         = tg3_tx_timeout,
+       .ndo_change_mtu         = tg3_change_mtu,
+#if TG3_VLAN_TAG_USED
+       .ndo_vlan_rx_register   = tg3_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = tg3_poll_controller,
+#endif
+};
+
+static const struct net_device_ops tg3_netdev_ops_dma_bug = {
+       .ndo_open               = tg3_open,
+       .ndo_stop               = tg3_close,
+       .ndo_start_xmit         = tg3_start_xmit_dma_bug,
+       .ndo_get_stats          = tg3_get_stats,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_multicast_list = tg3_set_rx_mode,
+       .ndo_set_mac_address    = tg3_set_mac_addr,
+       .ndo_do_ioctl           = tg3_ioctl,
+       .ndo_tx_timeout         = tg3_tx_timeout,
+       .ndo_change_mtu         = tg3_change_mtu,
+#if TG3_VLAN_TAG_USED
+       .ndo_vlan_rx_register   = tg3_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = tg3_poll_controller,
+#endif
+};
+
 static int __devinit tg3_init_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
        static int tg3_version_printed = 0;
-       unsigned long tg3reg_base, tg3reg_len;
        struct net_device *dev;
        struct tg3 *tp;
        int err, pm_cap;
        char str[40];
        u64 dma_mask, persist_dma_mask;
-       DECLARE_MAC_BUF(mac);
 
        if (tg3_version_printed++ == 0)
                printk(KERN_INFO "%s", version);
@@ -12427,13 +12994,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                return err;
        }
 
-       if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-               printk(KERN_ERR PFX "Cannot find proper PCI device "
-                      "base address, aborting.\n");
-               err = -ENODEV;
-               goto err_out_disable_pdev;
-       }
-
        err = pci_request_regions(pdev, DRV_MODULE_NAME);
        if (err) {
                printk(KERN_ERR PFX "Cannot obtain PCI resources, "
@@ -12452,9 +13012,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                goto err_out_free_res;
        }
 
-       tg3reg_base = pci_resource_start(pdev, 0);
-       tg3reg_len = pci_resource_len(pdev, 0);
-
        dev = alloc_etherdev(sizeof(*tp));
        if (!dev) {
                printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
@@ -12466,17 +13023,15 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
 #if TG3_VLAN_TAG_USED
        dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-       dev->vlan_rx_register = tg3_vlan_rx_register;
 #endif
 
        tp = netdev_priv(dev);
        tp->pdev = pdev;
        tp->dev = dev;
        tp->pm_cap = pm_cap;
-       tp->mac_mode = TG3_DEF_MAC_MODE;
        tp->rx_mode = TG3_DEF_RX_MODE;
        tp->tx_mode = TG3_DEF_TX_MODE;
-       tp->mi_mode = MAC_MI_MODE_BASE;
+
        if (tg3_debug > 0)
                tp->msg_enable = tg3_debug;
        else
@@ -12507,7 +13062,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        spin_lock_init(&tp->indirect_lock);
        INIT_WORK(&tp->reset_task, tg3_reset_task);
 
-       tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len);
+       tp->regs = pci_ioremap_bar(pdev, BAR_0);
        if (!tp->regs) {
                printk(KERN_ERR PFX "Cannot map device registers, "
                       "aborting.\n");
@@ -12521,21 +13076,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
        tp->tx_pending = TG3_DEF_TX_RING_PENDING;
 
-       dev->open = tg3_open;
-       dev->stop = tg3_close;
-       dev->get_stats = tg3_get_stats;
-       dev->set_multicast_list = tg3_set_rx_mode;
-       dev->set_mac_address = tg3_set_mac_addr;
-       dev->do_ioctl = tg3_ioctl;
-       dev->tx_timeout = tg3_tx_timeout;
        netif_napi_add(dev, &tp->napi, tg3_poll, 64);
        dev->ethtool_ops = &tg3_ethtool_ops;
        dev->watchdog_timeo = TG3_TX_TIMEOUT;
-       dev->change_mtu = tg3_change_mtu;
        dev->irq = pdev->irq;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = tg3_poll_controller;
-#endif
 
        err = tg3_get_invariants(tp);
        if (err) {
@@ -12544,6 +13088,13 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                goto err_out_iounmap;
        }
 
+       if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+               dev->netdev_ops = &tg3_netdev_ops;
+       else
+               dev->netdev_ops = &tg3_netdev_ops_dma_bug;
+
+
        /* The EPB bridge inside 5714, 5715, and 5780 and any
         * device behind the EPB cannot support DMA addresses > 40-bit.
         * On 64-bit systems with IOMMU, use 40-bit dma_mask.
@@ -12585,6 +13136,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        tg3_init_bufmgr_config(tp);
 
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0)
+               tp->fw_needed = FIRMWARE_TG3;
+
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
                tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
        }
@@ -12596,6 +13150,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
        } else {
                tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+                       tp->fw_needed = FIRMWARE_TG3TSO5;
+               else
+                       tp->fw_needed = FIRMWARE_TG3TSO;
        }
 
        /* TSO is on by default on chips that support hardware TSO.
@@ -12603,11 +13161,16 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
         * is off by default, but can be enabled using ethtool.
         */
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
-               dev->features |= NETIF_F_TSO;
-               if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
-                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906))
+               if (dev->features & NETIF_F_IP_CSUM)
+                       dev->features |= NETIF_F_TSO;
+               if ((dev->features & NETIF_F_IPV6_CSUM) &&
+                   (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2))
                        dev->features |= NETIF_F_TSO6;
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+                   (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+                    GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
+                       GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
                        dev->features |= NETIF_F_TSO_ECN;
        }
 
@@ -12623,26 +13186,16 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        if (err) {
                printk(KERN_ERR PFX "Could not obtain valid ethernet address, "
                       "aborting.\n");
-               goto err_out_iounmap;
+               goto err_out_fw;
        }
 
        if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
-               if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
-                       printk(KERN_ERR PFX "Cannot find proper PCI device "
-                              "base address for APE, aborting.\n");
-                       err = -ENODEV;
-                       goto err_out_iounmap;
-               }
-
-               tg3reg_base = pci_resource_start(pdev, 2);
-               tg3reg_len = pci_resource_len(pdev, 2);
-
-               tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
-               if (tp->aperegs == 0UL) {
+               tp->aperegs = pci_ioremap_bar(pdev, BAR_2);
+               if (!tp->aperegs) {
                        printk(KERN_ERR PFX "Cannot map APE registers, "
                               "aborting.\n");
                        err = -ENOMEM;
-                       goto err_out_iounmap;
+                       goto err_out_fw;
                }
 
                tg3_ape_lock_init(tp);
@@ -12665,24 +13218,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                goto err_out_apeunmap;
        }
 
-       /* Tigon3 can do ipv4 only... and some chips have buggy
-        * checksumming.
-        */
-       if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
-               dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
-                       dev->features |= NETIF_F_IPV6_CSUM;
-
-               tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
-       } else
-               tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
-
        /* flow control autonegotiation is default behavior */
        tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
-       tp->link_config.flowctrl = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+       tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
 
        tg3_init_coal(tp);
 
@@ -12695,26 +13233,34 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                goto err_out_apeunmap;
        }
 
-       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] "
-              "(%s) %s Ethernet %s\n",
+       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x] (%s) MAC address %pM\n",
               dev->name,
               tp->board_part_number,
               tp->pci_chip_rev_id,
-              tg3_phy_string(tp),
               tg3_bus_string(tp, str),
-              ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
-               ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
-                "10/100/1000Base-T")),
-              print_mac(mac, dev->dev_addr));
+              dev->dev_addr);
 
-       printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
-              "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n",
+       if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)
+               printk(KERN_INFO
+                      "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
+                      tp->dev->name,
+                      tp->mdio_bus->phy_map[PHY_ADDR]->drv->name,
+                      dev_name(&tp->mdio_bus->phy_map[PHY_ADDR]->dev));
+       else
+               printk(KERN_INFO
+                      "%s: attached PHY is %s (%s Ethernet) (WireSpeed[%d])\n",
+                      tp->dev->name, tg3_phy_string(tp),
+                      ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
+                       ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
+                        "10/100/1000Base-T")),
+                      (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0);
+
+       printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n",
               dev->name,
               (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
               (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
               (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
               (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
-              (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
               (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
        printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
               dev->name, tp->dma_rwctrl,
@@ -12729,6 +13275,10 @@ err_out_apeunmap:
                tp->aperegs = NULL;
        }
 
+err_out_fw:
+       if (tp->fw)
+               release_firmware(tp->fw);
+
 err_out_iounmap:
        if (tp->regs) {
                iounmap(tp->regs);
@@ -12754,7 +13304,16 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
        if (dev) {
                struct tg3 *tp = netdev_priv(dev);
 
+               if (tp->fw)
+                       release_firmware(tp->fw);
+
                flush_scheduled_work();
+
+               if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+                       tg3_phy_fini(tp);
+                       tg3_mdio_fini(tp);
+               }
+
                unregister_netdev(dev);
                if (tp->aperegs) {
                        iounmap(tp->aperegs);
@@ -12775,6 +13334,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tg3 *tp = netdev_priv(dev);
+       pci_power_t target_state;
        int err;
 
        /* PCI register 4 needs to be saved whether netif_running() or not.
@@ -12787,6 +13347,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
                return 0;
 
        flush_scheduled_work();
+       tg3_phy_stop(tp);
        tg3_netif_stop(tp);
 
        del_timer_sync(&tp->timer);
@@ -12802,12 +13363,17 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
        tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
        tg3_full_unlock(tp);
 
-       err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
+       target_state = pdev->pm_cap ? pci_target_state(pdev) : PCI_D3hot;
+
+       err = tg3_set_power_state(tp, target_state);
        if (err) {
+               int err2;
+
                tg3_full_lock(tp, 0);
 
                tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
-               if (tg3_restart_hw(tp, 1))
+               err2 = tg3_restart_hw(tp, 1);
+               if (err2)
                        goto out;
 
                tp->timer.expires = jiffies + tp->timer_offset;
@@ -12818,6 +13384,9 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
 
 out:
                tg3_full_unlock(tp);
+
+               if (!err2)
+                       tg3_phy_start(tp);
        }
 
        return err;
@@ -12855,6 +13424,9 @@ static int tg3_resume(struct pci_dev *pdev)
 out:
        tg3_full_unlock(tp);
 
+       if (!err)
+               tg3_phy_start(tp);
+
        return err;
 }