libertas: move to uniform lbs_/LBS_ namespace
[safe/jmp/linux-2.6] / drivers / net / tg3.c
index ff157b7..a9f1640 100644 (file)
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.75"
-#define DRV_MODULE_RELDATE     "March 23, 2007"
+#define DRV_MODULE_VERSION     "3.87"
+#define DRV_MODULE_RELDATE     "December 20, 2007"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -198,6 +198,11 @@ static struct pci_device_id tg3_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)},
+       {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_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)},
@@ -312,6 +317,16 @@ static u32 tg3_read32(struct tg3 *tp, u32 off)
        return (readl(tp->regs + off));
 }
 
+static void tg3_ape_write32(struct tg3 *tp, u32 off, u32 val)
+{
+       writel(val, tp->aperegs + off);
+}
+
+static u32 tg3_ape_read32(struct tg3 *tp, u32 off)
+{
+       return (readl(tp->aperegs + off));
+}
+
 static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
 {
        unsigned long flags;
@@ -498,6 +513,73 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
        spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
+static void tg3_ape_lock_init(struct tg3 *tp)
+{
+       int i;
+
+       /* Make sure the driver hasn't any stale locks. */
+       for (i = 0; i < 8; i++)
+               tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + 4 * i,
+                               APE_LOCK_GRANT_DRIVER);
+}
+
+static int tg3_ape_lock(struct tg3 *tp, int locknum)
+{
+       int i, off;
+       int ret = 0;
+       u32 status;
+
+       if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
+               return 0;
+
+       switch (locknum) {
+               case TG3_APE_LOCK_MEM:
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       off = 4 * locknum;
+
+       tg3_ape_write32(tp, TG3_APE_LOCK_REQ + off, APE_LOCK_REQ_DRIVER);
+
+       /* Wait for up to 1 millisecond to acquire lock. */
+       for (i = 0; i < 100; i++) {
+               status = tg3_ape_read32(tp, TG3_APE_LOCK_GRANT + off);
+               if (status == APE_LOCK_GRANT_DRIVER)
+                       break;
+               udelay(10);
+       }
+
+       if (status != APE_LOCK_GRANT_DRIVER) {
+               /* Revoke the lock request. */
+               tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off,
+                               APE_LOCK_GRANT_DRIVER);
+
+               ret = -EBUSY;
+       }
+
+       return ret;
+}
+
+static void tg3_ape_unlock(struct tg3 *tp, int locknum)
+{
+       int off;
+
+       if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
+               return;
+
+       switch (locknum) {
+               case TG3_APE_LOCK_MEM:
+                       break;
+               default:
+                       return;
+       }
+
+       off = 4 * locknum;
+       tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, APE_LOCK_GRANT_DRIVER);
+}
+
 static void tg3_disable_ints(struct tg3 *tp)
 {
        tw32(TG3PCI_MISC_HOST_CTRL,
@@ -574,7 +656,7 @@ static void tg3_restart_ints(struct tg3 *tp)
 static inline void tg3_netif_stop(struct tg3 *tp)
 {
        tp->dev->trans_start = jiffies; /* prevent tx timeout */
-       netif_poll_disable(tp->dev);
+       napi_disable(&tp->napi);
        netif_tx_disable(tp->dev);
 }
 
@@ -585,7 +667,7 @@ static inline void tg3_netif_start(struct tg3 *tp)
         * so long as all callers are assured to have free tx slots
         * (such as after tg3_init_hw)
         */
-       netif_poll_enable(tp->dev);
+       napi_enable(&tp->napi);
        tp->hw_status->status |= SD_STATUS_UPDATED;
        tg3_enable_ints(tp);
 }
@@ -595,7 +677,8 @@ static void tg3_switch_clocks(struct tg3 *tp)
        u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
        u32 orig_clock_ctrl;
 
-       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+       if ((tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) ||
+           (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                return;
 
        orig_clock_ctrl = clock_ctrl;
@@ -721,6 +804,44 @@ 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;
@@ -985,6 +1106,24 @@ static int tg3_phy_reset(struct tg3 *tp)
        if (err)
                return err;
 
+       if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+               u32 val;
+
+               val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+               if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
+                   CPMU_LSPD_1000MB_MACCLK_12_5) {
+                       val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+                       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);
+       }
+
 out:
        if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
                tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
@@ -1045,23 +1184,11 @@ out:
        }
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               u32 phy_reg;
-
                /* adjust output voltage */
                tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12);
-
-               if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) {
-                       u32 phy_reg2;
-
-                       tg3_writephy(tp, MII_TG3_EPHY_TEST,
-                                    phy_reg | MII_TG3_EPHY_SHADOW_EN);
-                       /* Enable auto-MDIX */
-                       if (!tg3_readphy(tp, 0x10, &phy_reg2))
-                               tg3_writephy(tp, 0x10, phy_reg2 | 0x4000);
-                       tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg);
-               }
        }
 
+       tg3_phy_toggle_automdix(tp, 1);
        tg3_phy_set_wirespeed(tp);
        return 0;
 }
@@ -1162,6 +1289,19 @@ static void tg3_frob_aux_power(struct tg3 *tp)
        }
 }
 
+static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
+{
+       if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
+               return 1;
+       else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) {
+               if (speed != SPEED_10)
+                       return 1;
+       } else if (speed == SPEED_10)
+               return 1;
+
+       return 0;
+}
+
 static int tg3_setup_phy(struct tg3 *, int);
 
 #define RESET_KIND_SHUTDOWN    0
@@ -1175,6 +1315,8 @@ static void tg3_nvram_unlock(struct tg3 *);
 
 static void tg3_power_down_phy(struct tg3 *tp)
 {
+       u32 val;
+
        if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
                        u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
@@ -1189,8 +1331,6 @@ static void tg3_power_down_phy(struct tg3 *tp)
        }
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-               u32 val;
-
                tg3_bmcr_reset(tp);
                val = tr32(GRC_MISC_CFG);
                tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
@@ -1210,6 +1350,14 @@ static void tg3_power_down_phy(struct tg3 *tp)
            (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
             (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
                return;
+
+       if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+               val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+               val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+               val |= CPMU_LSPD_1000MB_MACCLK_12_5;
+               tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+       }
+
        tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
 }
 
@@ -1320,9 +1468,17 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                        else
                                mac_mode = MAC_MODE_PORT_MODE_MII;
 
-                       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 ||
-                           !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB))
-                               mac_mode |= MAC_MODE_LINK_POLARITY;
+                       mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY;
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+                           ASIC_REV_5700) {
+                               u32 speed = (tp->tg3_flags &
+                                            TG3_FLAG_WOL_SPEED_100MB) ?
+                                            SPEED_100 : SPEED_10;
+                               if (tg3_5700_link_polarity(tp, speed))
+                                       mac_mode |= MAC_MODE_LINK_POLARITY;
+                               else
+                                       mac_mode &= ~MAC_MODE_LINK_POLARITY;
+                       }
                } else {
                        mac_mode = MAC_MODE_PORT_MODE_TBI;
                }
@@ -1353,6 +1509,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK |
                            CLOCK_CTRL_PWRDOWN_PLL133, 40);
        } else if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
+                  (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) ||
                   (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) {
                /* do nothing */
        } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
@@ -1397,7 +1554,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
        }
 
        if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
-           !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+           !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
+           !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
                tg3_power_down_phy(tp);
 
        tg3_frob_aux_power(tp);
@@ -1444,68 +1602,113 @@ static void tg3_link_report(struct tg3 *tp)
                       (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",
+               printk(KERN_INFO PFX
+                      "%s: Flow control is %s for TX and %s for RX.\n",
                       tp->dev->name,
-                      (tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "on" : "off",
-                      (tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "on" : "off");
+                      (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) ?
+                      "on" : "off",
+                      (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) ?
+                      "on" : "off");
        }
 }
 
-static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv)
+static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
 {
-       u32 new_tg3_flags = 0;
-       u32 old_rx_mode = tp->rx_mode;
-       u32 old_tx_mode = tp->tx_mode;
+       u16 miireg;
 
-       if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
+       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;
 
-               /* Convert 1000BaseX flow control bits to 1000BaseT
-                * bits before resolving flow control.
-                */
-               if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
-                       local_adv &= ~(ADVERTISE_PAUSE_CAP |
-                                      ADVERTISE_PAUSE_ASYM);
-                       remote_adv &= ~(LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
-
-                       if (local_adv & ADVERTISE_1000XPAUSE)
-                               local_adv |= ADVERTISE_PAUSE_CAP;
-                       if (local_adv & ADVERTISE_1000XPSE_ASYM)
-                               local_adv |= ADVERTISE_PAUSE_ASYM;
-                       if (remote_adv & LPA_1000XPAUSE)
-                               remote_adv |= LPA_PAUSE_CAP;
-                       if (remote_adv & LPA_1000XPAUSE_ASYM)
-                               remote_adv |= LPA_PAUSE_ASYM;
-               }
-
-               if (local_adv & ADVERTISE_PAUSE_CAP) {
-                       if (local_adv & ADVERTISE_PAUSE_ASYM) {
-                               if (remote_adv & LPA_PAUSE_CAP)
-                                       new_tg3_flags |=
-                                               (TG3_FLAG_RX_PAUSE |
-                                               TG3_FLAG_TX_PAUSE);
-                               else if (remote_adv & LPA_PAUSE_ASYM)
-                                       new_tg3_flags |=
-                                               (TG3_FLAG_RX_PAUSE);
-                       } else {
-                               if (remote_adv & LPA_PAUSE_CAP)
-                                       new_tg3_flags |=
-                                               (TG3_FLAG_RX_PAUSE |
-                                               TG3_FLAG_TX_PAUSE);
-                       }
-               } else if (local_adv & ADVERTISE_PAUSE_ASYM) {
-                       if ((remote_adv & LPA_PAUSE_CAP) &&
-                       (remote_adv & LPA_PAUSE_ASYM))
-                               new_tg3_flags |= TG3_FLAG_TX_PAUSE;
+       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 (rmtadv & LPA_PAUSE_CAP)
+                               cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
                }
+       } else if (lcladv & ADVERTISE_PAUSE_ASYM) {
+               if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
+                       cap = TG3_FLOW_CTRL_TX;
+       }
+
+       return cap;
+}
+
+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 = 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;
+               }
+       } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+               if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
+                       cap = TG3_FLOW_CTRL_TX;
+       }
+
+       return cap;
+}
 
-               tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
-               tp->tg3_flags |= new_tg3_flags;
+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 (tp->link_config.autoneg == AUTONEG_ENABLE &&
+           (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) {
+               if (tp->tg3_flags2 & TG3_FLG2_ANY_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->tg3_flags;
+               new_tg3_flags = tp->link_config.flowctrl;
        }
 
-       if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
+       tp->link_config.active_flowctrl = new_tg3_flags;
+
+       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;
@@ -1514,7 +1717,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv
                tw32_f(MAC_RX_MODE, tp->rx_mode);
        }
 
-       if (new_tg3_flags & TG3_FLAG_TX_PAUSE)
+       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;
@@ -1594,7 +1797,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                                ~(ADVERTISED_1000baseT_Half |
                                  ADVERTISED_1000baseT_Full);
 
-               new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+               new_adv = ADVERTISE_CSMA;
                if (tp->link_config.advertising & ADVERTISED_10baseT_Half)
                        new_adv |= ADVERTISE_10HALF;
                if (tp->link_config.advertising & ADVERTISED_10baseT_Full)
@@ -1603,6 +1806,9 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                        new_adv |= ADVERTISE_100HALF;
                if (tp->link_config.advertising & ADVERTISED_100baseT_Full)
                        new_adv |= ADVERTISE_100FULL;
+
+               new_adv |= tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+
                tg3_writephy(tp, MII_ADVERTISE, new_adv);
 
                if (tp->link_config.advertising &
@@ -1622,9 +1828,11 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                        tg3_writephy(tp, MII_TG3_CTRL, 0);
                }
        } else {
+               new_adv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+               new_adv |= ADVERTISE_CSMA;
+
                /* Asking for a specific link mode. */
                if (tp->link_config.speed == SPEED_1000) {
-                       new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
                        tg3_writephy(tp, MII_ADVERTISE, new_adv);
 
                        if (tp->link_config.duplex == DUPLEX_FULL)
@@ -1635,11 +1843,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                            tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
                                new_adv |= (MII_TG3_CTRL_AS_MASTER |
                                            MII_TG3_CTRL_ENABLE_AS_MASTER);
-                       tg3_writephy(tp, MII_TG3_CTRL, new_adv);
                } else {
-                       tg3_writephy(tp, MII_TG3_CTRL, 0);
-
-                       new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
                        if (tp->link_config.speed == SPEED_100) {
                                if (tp->link_config.duplex == DUPLEX_FULL)
                                        new_adv |= ADVERTISE_100FULL;
@@ -1652,7 +1856,11 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                                        new_adv |= ADVERTISE_10HALF;
                        }
                        tg3_writephy(tp, MII_ADVERTISE, new_adv);
+
+                       new_adv = 0;
                }
+
+               tg3_writephy(tp, MII_TG3_CTRL, new_adv);
        }
 
        if (tp->link_config.autoneg == AUTONEG_DISABLE &&
@@ -1768,10 +1976,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;
@@ -1914,56 +2156,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;
-               local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
-
-               if (tg3_readphy(tp, MII_LPA, &remote_adv))
-                       remote_adv = 0;
-
-               remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
-
-               /* If we are not advertising full pause capability,
-                * something is wrong.  Bring the link down and reconfigure.
-                */
-               if (local_adv != ADVERTISE_PAUSE_CAP) {
-                       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;
@@ -1990,15 +2211,12 @@ relink:
        if (tp->link_config.active_duplex == DUPLEX_HALF)
                tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
 
-       tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
-               if ((tp->led_ctrl == LED_CTRL_MODE_PHY_2) ||
-                   (current_link_up == 1 &&
-                    tp->link_config.active_speed == SPEED_10))
-                       tp->mac_mode |= MAC_MODE_LINK_POLARITY;
-       } else {
-               if (current_link_up == 1)
+               if (current_link_up == 1 &&
+                   tg3_5700_link_polarity(tp, tp->link_config.active_speed))
                        tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+               else
+                       tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
        }
 
        /* ??? Without this setting Netgear GA302T PHY does not
@@ -2115,6 +2333,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;
@@ -2214,7 +2433,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);
@@ -2360,7 +2584,7 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
        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;
@@ -2394,7 +2618,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 |
@@ -2456,6 +2681,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;
@@ -2481,7 +2707,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
        sg_dig_ctrl = tr32(SG_DIG_CTRL);
 
        if (tp->link_config.autoneg != AUTONEG_ENABLE) {
-               if (sg_dig_ctrl & (1 << 31)) {
+               if (sg_dig_ctrl & SG_DIG_USING_HW_AUTONEG) {
                        if (workaround) {
                                u32 val = serdes_cfg;
 
@@ -2491,7 +2717,8 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
                                        val |= 0x4010000;
                                tw32_f(MAC_SERDES_CFG, val);
                        }
-                       tw32_f(SG_DIG_CTRL, 0x01388400);
+
+                       tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
                }
                if (mac_status & MAC_STATUS_PCS_SYNCED) {
                        tg3_setup_flow_control(tp, 0, 0);
@@ -2501,13 +2728,13 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
        }
 
        /* Want auto-negotiation.  */
-       expected_sg_dig_ctrl = 0x81388400;
+       expected_sg_dig_ctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_COMMON_SETUP;
 
-       /* Pause capability */
-       expected_sg_dig_ctrl |= (1 << 11);
-
-       /* Asymettric pause */
-       expected_sg_dig_ctrl |= (1 << 12);
+       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) &&
@@ -2522,7 +2749,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
 restart_autoneg:
                if (workaround)
                        tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000);
-               tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30));
+               tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | SG_DIG_SOFT_RESET);
                udelay(5);
                tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
 
@@ -2533,22 +2760,25 @@ restart_autoneg:
                sg_dig_status = tr32(SG_DIG_STATUS);
                mac_status = tr32(MAC_STATUS);
 
-               if ((sg_dig_status & (1 << 1)) &&
+               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 & (1 << 19))
-                               remote_adv |= LPA_PAUSE_CAP;
-                       if (sg_dig_status & (1 << 20))
-                               remote_adv |= LPA_PAUSE_ASYM;
+                       if (sg_dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
+                               remote_adv |= LPA_1000XPAUSE;
+                       if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
+                               remote_adv |= LPA_1000XPAUSE_ASYM;
 
                        tg3_setup_flow_control(tp, local_adv, remote_adv);
                        current_link_up = 1;
                        tp->serdes_counter = 0;
                        tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
-               } else if (!(sg_dig_status & (1 << 1))) {
+               } else if (!(sg_dig_status & SG_DIG_AUTONEG_COMPLETE)) {
                        if (tp->serdes_counter)
                                tp->serdes_counter--;
                        else {
@@ -2563,7 +2793,7 @@ restart_autoneg:
                                        tw32_f(MAC_SERDES_CFG, val);
                                }
 
-                               tw32_f(SG_DIG_CTRL, 0x01388400);
+                               tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
                                udelay(40);
 
                                /* Link parallel detection - link is up */
@@ -2599,18 +2829,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);
 
@@ -2634,11 +2867,16 @@ 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;
 
                tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
                udelay(40);
+
+               tw32_f(MAC_MODE, tp->mac_mode);
+               udelay(40);
        }
 
 out:
@@ -2654,9 +2892,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
        int current_link_up;
        int i;
 
-       orig_pause_cfg =
-               (tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
-                                 TG3_FLAG_TX_PAUSE));
+       orig_pause_cfg = tp->link_config.active_flowctrl;
        orig_active_speed = tp->link_config.active_speed;
        orig_active_duplex = tp->link_config.active_duplex;
 
@@ -2698,10 +2934,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
        else
                current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
 
-       tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
-       tw32_f(MAC_MODE, tp->mac_mode);
-       udelay(40);
-
        tp->hw_status->status =
                (SD_STATUS_UPDATED |
                 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
@@ -2749,9 +2981,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
                        netif_carrier_off(tp->dev);
                tg3_link_report(tp);
        } else {
-               u32 now_pause_cfg =
-                       tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
-                                        TG3_FLAG_TX_PAUSE);
+               u32 now_pause_cfg = tp->link_config.active_flowctrl;
                if (orig_pause_cfg != now_pause_cfg ||
                    orig_active_speed != tp->link_config.active_speed ||
                    orig_active_duplex != tp->link_config.active_duplex)
@@ -2767,6 +2997,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);
@@ -2800,7 +3031,8 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
        err |= tg3_readphy(tp, MII_BMCR, &bmcr);
 
        if ((tp->link_config.autoneg == AUTONEG_ENABLE) && !force_reset &&
-           (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) {
+           (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) &&
+            tp->link_config.flowctrl == tp->link_config.active_flowctrl) {
                /* do nothing, just check for link up at the end */
        } else if (tp->link_config.autoneg == AUTONEG_ENABLE) {
                u32 adv, new_adv;
@@ -2811,8 +3043,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                                  ADVERTISE_1000XPSE_ASYM |
                                  ADVERTISE_SLCT);
 
-               /* Always advertise symmetric PAUSE just like copper */
-               new_adv |= ADVERTISE_1000XPAUSE;
+               new_adv |= tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
 
                if (tp->link_config.advertising & ADVERTISED_1000baseT_Half)
                        new_adv |= ADVERTISE_1000XHALF;
@@ -2883,8 +3114,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);
@@ -2895,15 +3129,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;
@@ -2998,6 +3232,23 @@ 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) {
+               u32 val, scale;
+
+               val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
+               if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5)
+                       scale = 65;
+               else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25)
+                       scale = 6;
+               else
+                       scale = 12;
+
+               val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK;
+               val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT);
+               tw32(GRC_MISC_CFG, val);
+       }
+
        if (tp->link_config.active_speed == SPEED_1000 &&
            tp->link_config.active_duplex == DUPLEX_HALF)
                tw32(MAC_TX_LENGTHS,
@@ -3019,6 +3270,16 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
                }
        }
 
+       if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND) {
+               u32 val = tr32(PCIE_PWR_MGMT_THRESH);
+               if (!netif_carrier_ok(tp->dev))
+                       val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) |
+                             tp->pwrmgmt_thresh;
+               else
+                       val |= PCIE_PWR_MGMT_L1_THRESH_MSK;
+               tw32(PCIE_PWR_MGMT_THRESH, val);
+       }
+
        return err;
 }
 
@@ -3418,11 +3679,9 @@ next_pkt_nopost:
        return received;
 }
 
-static int tg3_poll(struct net_device *netdev, int *budget)
+static int tg3_poll_work(struct tg3 *tp, int work_done, int budget)
 {
-       struct tg3 *tp = netdev_priv(netdev);
        struct tg3_hw_status *sblk = tp->hw_status;
-       int done;
 
        /* handle link change and other phy events */
        if (!(tp->tg3_flags &
@@ -3440,44 +3699,59 @@ static int tg3_poll(struct net_device *netdev, int *budget)
        /* run TX completion thread */
        if (sblk->idx[0].tx_consumer != tp->tx_cons) {
                tg3_tx(tp);
-               if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) {
-                       netif_rx_complete(netdev);
-                       schedule_work(&tp->reset_task);
-                       return 0;
-               }
+               if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
+                       return work_done;
        }
 
        /* run RX thread, within the bounds set by NAPI.
         * All RX "locking" is done by ensuring outside
-        * code synchronizes with dev->poll()
+        * code synchronizes with tg3->napi.poll()
         */
-       if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
-               int orig_budget = *budget;
-               int work_done;
+       if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr)
+               work_done += tg3_rx(tp, budget - work_done);
 
-               if (orig_budget > netdev->quota)
-                       orig_budget = netdev->quota;
+       return work_done;
+}
 
-               work_done = tg3_rx(tp, orig_budget);
+static int tg3_poll(struct napi_struct *napi, int budget)
+{
+       struct tg3 *tp = container_of(napi, struct tg3, napi);
+       int work_done = 0;
+       struct tg3_hw_status *sblk = tp->hw_status;
 
-               *budget -= work_done;
-               netdev->quota -= work_done;
-       }
+       while (1) {
+               work_done = tg3_poll_work(tp, work_done, budget);
 
-       if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
-               tp->last_tag = sblk->status_tag;
-               rmb();
-       } else
-               sblk->status &= ~SD_STATUS_UPDATED;
+               if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
+                       goto tx_recovery;
+
+               if (unlikely(work_done >= budget))
+                       break;
 
-       /* if no more work, tell net stack and NIC we're done */
-       done = !tg3_has_work(tp);
-       if (done) {
-               netif_rx_complete(netdev);
-               tg3_restart_ints(tp);
+               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
+                       /* tp->last_tag is used in tg3_restart_ints() below
+                        * to tell the hw how much work has been processed,
+                        * so we must read it before checking for more work.
+                        */
+                       tp->last_tag = sblk->status_tag;
+                       rmb();
+               } else
+                       sblk->status &= ~SD_STATUS_UPDATED;
+
+               if (likely(!tg3_has_work(tp))) {
+                       netif_rx_complete(tp->dev, napi);
+                       tg3_restart_ints(tp);
+                       break;
+               }
        }
 
-       return (done ? 0 : 1);
+       return work_done;
+
+tx_recovery:
+       /* work_done is guaranteed to be less than budget. */
+       netif_rx_complete(tp->dev, napi);
+       schedule_work(&tp->reset_task);
+       return work_done;
 }
 
 static void tg3_irq_quiesce(struct tg3 *tp)
@@ -3502,9 +3776,9 @@ static inline int tg3_irq_sync(struct tg3 *tp)
  */
 static inline void tg3_full_lock(struct tg3 *tp, int irq_sync)
 {
+       spin_lock_bh(&tp->lock);
        if (irq_sync)
                tg3_irq_quiesce(tp);
-       spin_lock_bh(&tp->lock);
 }
 
 static inline void tg3_full_unlock(struct tg3 *tp)
@@ -3524,7 +3798,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);         /* schedule NAPI poll */
+               netif_rx_schedule(dev, &tp->napi);
 
        return IRQ_HANDLED;
 }
@@ -3549,7 +3823,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);         /* schedule NAPI poll */
+               netif_rx_schedule(dev, &tp->napi);
 
        return IRQ_RETVAL(1);
 }
@@ -3580,14 +3854,18 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
         * Writing non-zero to intr-mbox-0 additional tells the
         * NIC to stop sending us irqs, engaging "in-intr-handler"
         * event coalescing.
+        *
+        * Flush the mailbox to de-assert the IRQ immediately to prevent
+        * spurious interrupts.  The flush impacts performance but
+        * excessive spurious interrupts can be worse in some cases.
         */
-       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+       tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
        if (tg3_irq_sync(tp))
                goto out;
        sblk->status &= ~SD_STATUS_UPDATED;
        if (likely(tg3_has_work(tp))) {
                prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
-               netif_rx_schedule(dev);         /* schedule NAPI poll */
+               netif_rx_schedule(dev, &tp->napi);
        } else {
                /* No work, shared interrupt perhaps?  re-enable
                 * interrupts, and flush that PCI write
@@ -3625,11 +3903,15 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
         * writing non-zero to intr-mbox-0 additional tells the
         * NIC to stop sending us irqs, engaging "in-intr-handler"
         * event coalescing.
+        *
+        * Flush the mailbox to de-assert the IRQ immediately to prevent
+        * spurious interrupts.  The flush impacts performance but
+        * excessive spurious interrupts can be worse in some cases.
         */
-       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+       tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
        if (tg3_irq_sync(tp))
                goto out;
-       if (netif_rx_schedule_prep(dev)) {
+       if (netif_rx_schedule_prep(dev, &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
@@ -3637,7 +3919,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);
+               __netif_rx_schedule(dev, &tp->napi);
        }
 out:
        return IRQ_RETVAL(handled);
@@ -3676,7 +3958,7 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
                tg3_full_unlock(tp);
                del_timer_sync(&tp->timer);
                tp->irq_sync = 0;
-               netif_poll_enable(tp->dev);
+               napi_enable(&tp->napi);
                dev_close(tp->dev);
                tg3_full_lock(tp, 0);
        }
@@ -3698,10 +3980,8 @@ static void tg3_reset_task(struct work_struct *work)
        unsigned int restart_timer;
 
        tg3_full_lock(tp, 0);
-       tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK;
 
        if (!netif_running(tp->dev)) {
-               tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
                tg3_full_unlock(tp);
                return;
        }
@@ -3732,8 +4012,6 @@ static void tg3_reset_task(struct work_struct *work)
                mod_timer(&tp->timer, jiffies + 1);
 
 out:
-       tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
-
        tg3_full_unlock(tp);
 }
 
@@ -3875,7 +4153,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        len = skb_headlen(skb);
 
        /* We are running in BH disabled context with netif_tx_lock
-        * and TX reclaim runs via tp->poll inside of a software
+        * and TX reclaim runs via tp->napi.poll inside of a software
         * interrupt.  Furthermore, IRQ processing runs lockless so we have
         * no IRQ context deadlocks to worry about either.  Rejoice!
         */
@@ -4030,7 +4308,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
        len = skb_headlen(skb);
 
        /* We are running in BH disabled context with netif_tx_lock
-        * and TX reclaim runs via tp->poll inside of a software
+        * and TX reclaim runs via tp->napi.poll inside of a software
         * interrupt.  Furthermore, IRQ processing runs lockless so we have
         * no IRQ context deadlocks to worry about either.  Rejoice!
         */
@@ -4675,6 +4953,80 @@ static void tg3_disable_nvram_access(struct tg3 *tp)
        }
 }
 
+static void tg3_ape_send_event(struct tg3 *tp, u32 event)
+{
+       int i;
+       u32 apedata;
+
+       apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
+       if (apedata != APE_SEG_SIG_MAGIC)
+               return;
+
+       apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
+       if (apedata != APE_FW_STATUS_READY)
+               return;
+
+       /* Wait for up to 1 millisecond for APE to service previous event. */
+       for (i = 0; i < 10; i++) {
+               if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM))
+                       return;
+
+               apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
+
+               if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+                       tg3_ape_write32(tp, TG3_APE_EVENT_STATUS,
+                                       event | APE_EVENT_STATUS_EVENT_PENDING);
+
+               tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
+
+               if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+                       break;
+
+               udelay(100);
+       }
+
+       if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+               tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
+}
+
+static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
+{
+       u32 event;
+       u32 apedata;
+
+       if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
+               return;
+
+       switch (kind) {
+               case RESET_KIND_INIT:
+                       tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG,
+                                       APE_HOST_SEG_SIG_MAGIC);
+                       tg3_ape_write32(tp, TG3_APE_HOST_SEG_LEN,
+                                       APE_HOST_SEG_LEN_MAGIC);
+                       apedata = tg3_ape_read32(tp, TG3_APE_HOST_INIT_COUNT);
+                       tg3_ape_write32(tp, TG3_APE_HOST_INIT_COUNT, ++apedata);
+                       tg3_ape_write32(tp, TG3_APE_HOST_DRIVER_ID,
+                                       APE_HOST_DRIVER_ID_MAGIC);
+                       tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR,
+                                       APE_HOST_BEHAV_NO_PHYLOCK);
+
+                       event = APE_EVENT_STATUS_STATE_START;
+                       break;
+               case RESET_KIND_SHUTDOWN:
+                       event = APE_EVENT_STATUS_STATE_UNLOAD;
+                       break;
+               case RESET_KIND_SUSPEND:
+                       event = APE_EVENT_STATUS_STATE_SUSPEND;
+                       break;
+               default:
+                       return;
+       }
+
+       event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE;
+
+       tg3_ape_send_event(tp, event);
+}
+
 /* tp->lock is held. */
 static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
 {
@@ -4702,6 +5054,10 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
                        break;
                };
        }
+
+       if (kind == RESET_KIND_INIT ||
+           kind == RESET_KIND_SUSPEND)
+               tg3_ape_driver_state_change(tp, kind);
 }
 
 /* tp->lock is held. */
@@ -4723,6 +5079,9 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind)
                        break;
                };
        }
+
+       if (kind == RESET_KIND_SHUTDOWN)
+               tg3_ape_driver_state_change(tp, kind);
 }
 
 /* tp->lock is held. */
@@ -4790,6 +5149,74 @@ static int tg3_poll_fw(struct tg3 *tp)
        return 0;
 }
 
+/* Save PCI command register before chip reset */
+static void tg3_save_pci_state(struct tg3 *tp)
+{
+       pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
+}
+
+/* Restore PCI state after chip reset */
+static void tg3_restore_pci_state(struct tg3 *tp)
+{
+       u32 val;
+
+       /* Re-enable indirect register accesses. */
+       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                              tp->misc_host_ctrl);
+
+       /* Set MAX PCI retry to zero. */
+       val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
+           (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
+               val |= PCISTATE_RETRY_SAME_DMA;
+       /* Allow reads and writes to the APE register and memory space. */
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+               val |= PCISTATE_ALLOW_APE_CTLSPC_WR |
+                      PCISTATE_ALLOW_APE_SHMEM_WR;
+       pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
+
+       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);
+       }
+
+       /* Make sure PCI-X relaxed ordering bit is clear. */
+       if (tp->pcix_cap) {
+               u16 pcix_cmd;
+
+               pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+                                    &pcix_cmd);
+               pcix_cmd &= ~PCI_X_CMD_ERO;
+               pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+                                     pcix_cmd);
+       }
+
+       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
+
+               /* Chip reset on 5780 will reset MSI enable bit,
+                * so need to restore it.
+                */
+               if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+                       u16 ctrl;
+
+                       pci_read_config_word(tp->pdev,
+                                            tp->msi_cap + PCI_MSI_FLAGS,
+                                            &ctrl);
+                       pci_write_config_word(tp->pdev,
+                                             tp->msi_cap + PCI_MSI_FLAGS,
+                                             ctrl | PCI_MSI_FLAGS_ENABLE);
+                       val = tr32(MSGINT_MODE);
+                       tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
+               }
+       }
+}
+
 static void tg3_stop_fw(struct tg3 *);
 
 /* tp->lock is held. */
@@ -4806,9 +5233,17 @@ static int tg3_chip_reset(struct tg3 *tp)
         */
        tp->nvram_lock_cnt = 0;
 
+       /* GRC_MISC_CFG core clock reset will clear the memory
+        * enable bit in PCI register 4 and the MSI enable bit
+        * on some chips, so we save relevant registers here.
+        */
+       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_5787 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
                tw32(GRC_FASTBOOT_PC, 0);
 
        /*
@@ -4892,62 +5327,26 @@ static int tg3_chip_reset(struct tg3 *tp)
                        int i;
                        u32 cfg_val;
 
-                       /* Wait for link training to complete.  */
-                       for (i = 0; i < 5000; i++)
-                               udelay(100);
-
-                       pci_read_config_dword(tp->pdev, 0xc4, &cfg_val);
-                       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);
-       }
-
-       /* Re-enable indirect register accesses. */
-       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
-                              tp->misc_host_ctrl);
-
-       /* Set MAX PCI retry to zero. */
-       val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
-           (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
-               val |= PCISTATE_RETRY_SAME_DMA;
-       pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
-
-       pci_restore_state(tp->pdev);
-
-       tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
-
-       /* Make sure PCI-X relaxed ordering bit is clear. */
-       pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
-       val &= ~PCIX_CAPS_RELAXED_ORDERING;
-       pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
-
-       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
-               u32 val;
-
-               /* Chip reset on 5780 will reset MSI enable bit,
-                * so need to restore it.
-                */
-               if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
-                       u16 ctrl;
+                       /* Wait for link training to complete.  */
+                       for (i = 0; i < 5000; i++)
+                               udelay(100);
 
-                       pci_read_config_word(tp->pdev,
-                                            tp->msi_cap + PCI_MSI_FLAGS,
-                                            &ctrl);
-                       pci_write_config_word(tp->pdev,
-                                             tp->msi_cap + PCI_MSI_FLAGS,
-                                             ctrl | PCI_MSI_FLAGS_ENABLE);
-                       val = tr32(MSGINT_MODE);
-                       tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
+                       pci_read_config_dword(tp->pdev, 0xc4, &cfg_val);
+                       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);
+       }
 
-               val = tr32(MEMARB_MODE);
-               tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+       tg3_restore_pci_state(tp);
 
-       } else
-               tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+       tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
+
+       val = 0;
+       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+               val = tr32(MEMARB_MODE);
+       tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
 
        if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
                tg3_stop_fw(tp);
@@ -4957,7 +5356,7 @@ static int tg3_chip_reset(struct tg3 *tp)
        tw32(GRC_MODE, tp->grc_mode);
 
        if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
-               u32 val = tr32(0xc4);
+               val = tr32(0xc4);
 
                tw32(0xc4, val | (1 << 15));
        }
@@ -4986,7 +5385,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
            tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
-               u32 val = tr32(0x7c00);
+               val = tr32(0x7c00);
 
                tw32(0x7c00, val | (1 << 25));
        }
@@ -5012,7 +5411,8 @@ static int tg3_chip_reset(struct tg3 *tp)
 /* tp->lock is held. */
 static void tg3_stop_fw(struct tg3 *tp)
 {
-       if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+       if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
+          !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
                u32 val;
                int i;
 
@@ -6069,14 +6469,38 @@ 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) {
+               val = tr32(TG3_CPMU_CTRL);
+               val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
+               tw32(TG3_CPMU_CTRL, val);
+
+               val = tr32(TG3_CPMU_LSPD_10MB_CLK);
+               val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
+               val |= CPMU_LSPD_10MB_MACCLK_6_25;
+               tw32(TG3_CPMU_LSPD_10MB_CLK, val);
+
+               val = tr32(TG3_CPMU_LNK_AWARE_PWRMD);
+               val &= ~CPMU_LNK_AWARE_MACCLK_MASK;
+               val |= CPMU_LNK_AWARE_MACCLK_6_25;
+               tw32(TG3_CPMU_LNK_AWARE_PWRMD, val);
+
+               val = tr32(TG3_CPMU_HST_ACC);
+               val &= ~CPMU_HST_ACC_MACCLK_MASK;
+               val |= CPMU_HST_ACC_MACCLK_6_25;
+               tw32(TG3_CPMU_HST_ACC, val);
+       }
+
        /* This works around an issue with Athlon chipsets on
         * B3 tigon3 silicon.  This bit has no effect on any
         * other revision.  But do not set this on PCI Express
-        * chips.
+        * chips and don't even touch the clocks if the CPMU is present.
         */
-       if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
-               tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
-       tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+       if (!(tp->tg3_flags & TG3_FLAG_CPMU_PRESENT)) {
+               if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+                       tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
+               tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+       }
 
        if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
            (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
@@ -6085,6 +6509,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                tw32(TG3PCI_PCISTATE, val);
        }
 
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+               /* Allow reads and writes to the
+                * APE register and memory space.
+                */
+               val = tr32(TG3PCI_PCISTATE);
+               val |= PCISTATE_ALLOW_APE_CTLSPC_WR |
+                      PCISTATE_ALLOW_APE_SHMEM_WR;
+               tw32(TG3PCI_PCISTATE, val);
+       }
+
        if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) {
                /* Enable some hw fixes.  */
                val = tr32(TG3PCI_MSI_DATA);
@@ -6101,10 +6535,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        if (err)
                return err;
 
-       /* This value is determined during the probe time DMA
-        * engine test, tg3_test_dma.
-        */
-       tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) {
+               /* This value is determined during the probe time DMA
+                * engine test, tg3_test_dma.
+                */
+               tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+       }
 
        tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS |
                          GRC_MODE_4X_NIC_SEND_RINGS |
@@ -6338,6 +6775,11 @@ 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)
+               rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB |
+                             RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
+                             RDMAC_MODE_MBUF_SBD_CRPT_ENAB;
+
        /* If statement applies to 5705 and 5750 PCI devices only */
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
             tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
@@ -6430,6 +6872,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 
        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) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+               tp->mac_mode |= MAC_MODE_LINK_POLARITY;
        tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
        udelay(40);
 
@@ -6495,22 +6941,28 @@ 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_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);
 
        tw32_f(WDMAC_MODE, val);
        udelay(40);
 
-       if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
-               val = tr32(TG3PCI_X_CAPS);
+       if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
+               u16 pcix_cmd;
+
+               pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+                                    &pcix_cmd);
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
-                       val &= ~PCIX_CAPS_BURST_MASK;
-                       val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
+                       pcix_cmd &= ~PCI_X_CMD_MAX_READ;
+                       pcix_cmd |= PCI_X_CMD_READ_2K;
                } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
-                       val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
-                       val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
+                       pcix_cmd &= ~(PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ);
+                       pcix_cmd |= PCI_X_CMD_READ_2K;
                }
-               tw32(TG3PCI_X_CAPS, val);
+               pci_write_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
+                                     pcix_cmd);
        }
 
        tw32_f(RDMAC_MODE, rdmac_mode);
@@ -6519,7 +6971,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
                tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
-       tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+               tw32(SNDDATAC_MODE,
+                    SNDDATAC_MODE_ENABLE | SNDDATAC_MODE_CDELAY);
+       else
+               tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+
        tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
        tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
        tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ);
@@ -6546,7 +7004,8 @@ 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)
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
                tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
 
        tw32_f(MAC_RX_MODE, tp->rx_mode);
@@ -6676,6 +7135,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                break;
        };
 
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+               /* Write our heartbeat update interval to APE. */
+               tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS,
+                               APE_HOST_HEARTBEAT_INT_DISABLE);
+
        tg3_write_sig_post_reset(tp, RESET_KIND_INIT);
 
        return 0;
@@ -7033,11 +7497,7 @@ static int tg3_open(struct net_device *dev)
        if (err)
                return err;
 
-       if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
-           (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
-           (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX) &&
-           !((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) &&
-             (tp->pdev_peer == tp->pdev))) {
+       if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) {
                /* All MSI supporting chips should support tagged
                 * status.  Assert that this is the case.
                 */
@@ -7063,6 +7523,8 @@ static int tg3_open(struct net_device *dev)
                return err;
        }
 
+       napi_enable(&tp->napi);
+
        tg3_full_lock(tp, 0);
 
        err = tg3_init_hw(tp, 1);
@@ -7090,6 +7552,7 @@ static int tg3_open(struct net_device *dev)
        tg3_full_unlock(tp);
 
        if (err) {
+               napi_disable(&tp->napi);
                free_irq(tp->pdev->irq, dev);
                if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
                        pci_disable_msi(tp->pdev);
@@ -7115,6 +7578,8 @@ static int tg3_open(struct net_device *dev)
 
                        tg3_full_unlock(tp);
 
+                       napi_disable(&tp->napi);
+
                        return err;
                }
 
@@ -7376,12 +7841,8 @@ static int tg3_close(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       /* Calling flush_scheduled_work() may deadlock because
-        * linkwatch_event() may be on the workqueue and it will try to get
-        * the rtnl_lock which we are holding.
-        */
-       while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK)
-               msleep(1);
+       napi_disable(&tp->napi);
+       cancel_work_sync(&tp->reset_task);
 
        netif_stop_queue(dev);
 
@@ -7808,6 +8269,7 @@ static int tg3_get_eeprom_len(struct net_device *dev)
 }
 
 static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val);
+static int tg3_nvram_read_le(struct tg3 *tp, u32 offset, __le32 *val);
 static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val);
 
 static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
@@ -7815,7 +8277,8 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
        struct tg3 *tp = netdev_priv(dev);
        int ret;
        u8  *pd;
-       u32 i, offset, len, val, b_offset, b_count;
+       u32 i, offset, len, b_offset, b_count;
+       __le32 val;
 
        if (tp->link_config.phy_is_low_power)
                return -EAGAIN;
@@ -7834,10 +8297,9 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
                        /* i.e. offset=1 len=2 */
                        b_count = len;
                }
-               ret = tg3_nvram_read(tp, offset-b_offset, &val);
+               ret = tg3_nvram_read_le(tp, offset-b_offset, &val);
                if (ret)
                        return ret;
-               val = cpu_to_le32(val);
                memcpy(data, ((char*)&val) + b_offset, b_count);
                len -= b_count;
                offset += b_count;
@@ -7847,12 +8309,11 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
        /* read bytes upto the last 4 byte boundary */
        pd = &data[eeprom->len];
        for (i = 0; i < (len - (len & 3)); i += 4) {
-               ret = tg3_nvram_read(tp, offset + i, &val);
+               ret = tg3_nvram_read_le(tp, offset + i, &val);
                if (ret) {
                        eeprom->len += i;
                        return ret;
                }
-               val = cpu_to_le32(val);
                memcpy(pd + i, &val, 4);
        }
        eeprom->len += i;
@@ -7862,11 +8323,10 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
                pd = &data[eeprom->len];
                b_count = len & 3;
                b_offset = offset + len - b_count;
-               ret = tg3_nvram_read(tp, b_offset, &val);
+               ret = tg3_nvram_read_le(tp, b_offset, &val);
                if (ret)
                        return ret;
-               val = cpu_to_le32(val);
-               memcpy(pd, ((char*)&val), b_count);
+               memcpy(pd, &val, b_count);
                eeprom->len += b_count;
        }
        return 0;
@@ -7878,8 +8338,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 {
        struct tg3 *tp = netdev_priv(dev);
        int ret;
-       u32 offset, len, b_offset, odd_len, start, end;
+       u32 offset, len, b_offset, odd_len;
        u8 *buf;
+       __le32 start, end;
 
        if (tp->link_config.phy_is_low_power)
                return -EAGAIN;
@@ -7892,10 +8353,9 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 
        if ((b_offset = (offset & 3))) {
                /* adjustments to start on required 4 byte boundary */
-               ret = tg3_nvram_read(tp, offset-b_offset, &start);
+               ret = tg3_nvram_read_le(tp, offset-b_offset, &start);
                if (ret)
                        return ret;
-               start = cpu_to_le32(start);
                len += b_offset;
                offset &= ~3;
                if (len < 4)
@@ -7907,16 +8367,15 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
                /* adjustments to end on required 4 byte boundary */
                odd_len = 1;
                len = (len + 3) & ~3;
-               ret = tg3_nvram_read(tp, offset+len-4, &end);
+               ret = tg3_nvram_read_le(tp, offset+len-4, &end);
                if (ret)
                        return ret;
-               end = cpu_to_le32(end);
        }
 
        buf = data;
        if (b_offset || odd_len) {
                buf = kmalloc(len, GFP_KERNEL);
-               if (buf == 0)
+               if (!buf)
                        return -ENOMEM;
                if (b_offset)
                        memcpy(buf, &start, 4);
@@ -7948,7 +8407,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                                  SUPPORTED_100baseT_Full |
                                  SUPPORTED_10baseT_Half |
                                  SUPPORTED_10baseT_Full |
-                                 SUPPORTED_MII);
+                                 SUPPORTED_TP);
                cmd->port = PORT_TP;
        } else {
                cmd->supported |= SUPPORTED_FIBRE;
@@ -7996,7 +8455,8 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
        tp->link_config.autoneg = cmd->autoneg;
        if (cmd->autoneg == AUTONEG_ENABLE) {
-               tp->link_config.advertising = cmd->advertising;
+               tp->link_config.advertising = (cmd->advertising |
+                                             ADVERTISED_Autoneg);
                tp->link_config.speed = SPEED_INVALID;
                tp->link_config.duplex = DUPLEX_INVALID;
        } else {
@@ -8084,10 +8544,12 @@ static int tg3_set_tso(struct net_device *dev, u32 value)
        }
        if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
            (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) {
-               if (value)
+               if (value) {
                        dev->features |= NETIF_F_TSO6;
-               else
-                       dev->features &= ~NETIF_F_TSO6;
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+                               dev->features |= NETIF_F_TSO_ECN;
+               } else
+                       dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
        }
        return ethtool_op_set_tso(dev, value);
 }
@@ -8187,8 +8649,16 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam
        struct tg3 *tp = netdev_priv(dev);
 
        epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0;
-       epause->rx_pause = (tp->tg3_flags & TG3_FLAG_RX_PAUSE) != 0;
-       epause->tx_pause = (tp->tg3_flags & TG3_FLAG_TX_PAUSE) != 0;
+
+       if (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX)
+               epause->rx_pause = 1;
+       else
+               epause->rx_pause = 0;
+
+       if (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX)
+               epause->tx_pause = 1;
+       else
+               epause->tx_pause = 0;
 }
 
 static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
@@ -8208,13 +8678,13 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
        else
                tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
        if (epause->rx_pause)
-               tp->tg3_flags |= TG3_FLAG_RX_PAUSE;
+               tp->link_config.flowctrl |= TG3_FLOW_CTRL_RX;
        else
-               tp->tg3_flags &= ~TG3_FLAG_RX_PAUSE;
+               tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_RX;
        if (epause->tx_pause)
-               tp->tg3_flags |= TG3_FLAG_TX_PAUSE;
+               tp->link_config.flowctrl |= TG3_FLOW_CTRL_TX;
        else
-               tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE;
+               tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_TX;
 
        if (netif_running(dev)) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
@@ -8265,22 +8735,26 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data)
        }
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
-               ethtool_op_set_tx_hw_csum(dev, data);
+           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)
+               ethtool_op_set_tx_ipv6_csum(dev, data);
        else
                ethtool_op_set_tx_csum(dev, data);
 
        return 0;
 }
 
-static int tg3_get_stats_count (struct net_device *dev)
-{
-       return TG3_NUM_STATS;
-}
-
-static int tg3_get_test_count (struct net_device *dev)
+static int tg3_get_sset_count (struct net_device *dev, int sset)
 {
-       return TG3_NUM_TEST;
+       switch (sset) {
+       case ETH_SS_TEST:
+               return TG3_NUM_TEST;
+       case ETH_SS_STATS:
+               return TG3_NUM_STATS;
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
@@ -8338,14 +8812,17 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
 }
 
 #define NVRAM_TEST_SIZE 0x100
-#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_0_SIZE  0x14
+#define NVRAM_SELFBOOT_FORMAT1_2_SIZE  0x18
+#define NVRAM_SELFBOOT_FORMAT1_3_SIZE  0x1c
 #define NVRAM_SELFBOOT_HW_SIZE 0x20
 #define NVRAM_SELFBOOT_DATA_SIZE 0x1c
 
 static int tg3_test_nvram(struct tg3 *tp)
 {
-       u32 *buf, csum, magic;
-       int i, j, err = 0, size;
+       u32 csum, magic;
+       __le32 *buf;
+       int i, j, k, err = 0, size;
 
        if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
                return -EIO;
@@ -8353,9 +8830,22 @@ static int tg3_test_nvram(struct tg3 *tp)
        if (magic == TG3_EEPROM_MAGIC)
                size = NVRAM_TEST_SIZE;
        else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
-               if ((magic & 0xe00000) == 0x200000)
-                       size = NVRAM_SELFBOOT_FORMAT1_SIZE;
-               else
+               if ((magic & TG3_EEPROM_SB_FORMAT_MASK) ==
+                   TG3_EEPROM_SB_FORMAT_1) {
+                       switch (magic & TG3_EEPROM_SB_REVISION_MASK) {
+                       case TG3_EEPROM_SB_REVISION_0:
+                               size = NVRAM_SELFBOOT_FORMAT1_0_SIZE;
+                               break;
+                       case TG3_EEPROM_SB_REVISION_2:
+                               size = NVRAM_SELFBOOT_FORMAT1_2_SIZE;
+                               break;
+                       case TG3_EEPROM_SB_REVISION_3:
+                               size = NVRAM_SELFBOOT_FORMAT1_3_SIZE;
+                               break;
+                       default:
+                               return 0;
+                       }
+               } else
                        return 0;
        } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
                size = NVRAM_SELFBOOT_HW_SIZE;
@@ -8368,22 +8858,29 @@ static int tg3_test_nvram(struct tg3 *tp)
 
        err = -EIO;
        for (i = 0, j = 0; i < size; i += 4, j++) {
-               u32 val;
-
-               if ((err = tg3_nvram_read(tp, i, &val)) != 0)
+               if ((err = tg3_nvram_read_le(tp, i, &buf[j])) != 0)
                        break;
-               buf[j] = cpu_to_le32(val);
        }
        if (i < size)
                goto out;
 
        /* Selfboot format */
-       if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_FW_MSK) ==
+       magic = swab32(le32_to_cpu(buf[0]));
+       if ((magic & TG3_EEPROM_MAGIC_FW_MSK) ==
            TG3_EEPROM_MAGIC_FW) {
                u8 *buf8 = (u8 *) buf, csum8 = 0;
 
-               for (i = 0; i < size; i++)
-                       csum8 += buf8[i];
+               if ((magic & TG3_EEPROM_SB_REVISION_MASK) ==
+                   TG3_EEPROM_SB_REVISION_2) {
+                       /* For rev 2, the csum doesn't include the MBA. */
+                       for (i = 0; i < TG3_EEPROM_SB_F1R2_MBA_OFF; i++)
+                               csum8 += buf8[i];
+                       for (i = TG3_EEPROM_SB_F1R2_MBA_OFF + 4; i < size; i++)
+                               csum8 += buf8[i];
+               } else {
+                       for (i = 0; i < size; i++)
+                               csum8 += buf8[i];
+               }
 
                if (csum8 == 0) {
                        err = 0;
@@ -8394,12 +8891,11 @@ static int tg3_test_nvram(struct tg3 *tp)
                goto out;
        }
 
-       if ((cpu_to_be32(buf[0]) & TG3_EEPROM_MAGIC_HW_MSK) ==
+       if ((magic & TG3_EEPROM_MAGIC_HW_MSK) ==
            TG3_EEPROM_MAGIC_HW) {
                u8 data[NVRAM_SELFBOOT_DATA_SIZE];
                u8 parity[NVRAM_SELFBOOT_DATA_SIZE];
                u8 *buf8 = (u8 *) buf;
-               int j, k;
 
                /* Separate the parity bits and the data bytes.  */
                for (i = 0, j = 0, k = 0; i < NVRAM_SELFBOOT_HW_SIZE; i++) {
@@ -8441,12 +8937,12 @@ static int tg3_test_nvram(struct tg3 *tp)
 
        /* Bootstrap checksum at offset 0x10 */
        csum = calc_crc((unsigned char *) buf, 0x10);
-       if(csum != cpu_to_le32(buf[0x10/4]))
+       if(csum != le32_to_cpu(buf[0x10/4]))
                goto out;
 
        /* Manufacturing block starts at offset 0x74, checksum at 0xfc */
        csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88);
-       if (csum != cpu_to_le32(buf[0xfc/4]))
+       if (csum != le32_to_cpu(buf[0xfc/4]))
                 goto out;
 
        err = 0;
@@ -8709,7 +9205,7 @@ static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len)
        int i;
        u32 j;
 
-       for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) {
+       for (i = 0; i < ARRAY_SIZE(test_pattern); i++) {
                for (j = 0; j < len; j += 4) {
                        u32 val;
 
@@ -8760,7 +9256,9 @@ static int tg3_test_memory(struct tg3 *tp)
 
        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_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;
@@ -8800,7 +9298,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                        return 0;
 
                mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-                          MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY;
+                          MAC_MODE_PORT_INT_LPBACK;
+               if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+                       mac_mode |= MAC_MODE_LINK_POLARITY;
                if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
                        mac_mode |= MAC_MODE_PORT_MODE_MII;
                else
@@ -8819,19 +9319,18 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                                             phytest | MII_TG3_EPHY_SHADOW_EN);
                                if (!tg3_readphy(tp, 0x1b, &phy))
                                        tg3_writephy(tp, 0x1b, phy & ~0x20);
-                               if (!tg3_readphy(tp, 0x10, &phy))
-                                       tg3_writephy(tp, 0x10, phy & ~0x4000);
                                tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
                        }
                        val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100;
                } else
                        val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
 
+               tg3_phy_toggle_automdix(tp, 0);
+
                tg3_writephy(tp, MII_BMCR, val);
                udelay(40);
 
-               mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-                          MAC_MODE_LINK_POLARITY;
+               mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                        tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800);
                        mac_mode |= MAC_MODE_PORT_MODE_MII;
@@ -8844,8 +9343,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
                        udelay(10);
                        tw32_f(MAC_RX_MODE, tp->rx_mode);
                }
-               if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
-                       mac_mode &= ~MAC_MODE_LINK_POLARITY;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+                       if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+                               mac_mode &= ~MAC_MODE_LINK_POLARITY;
+                       else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411)
+                               mac_mode |= MAC_MODE_LINK_POLARITY;
                        tg3_writephy(tp, MII_TG3_EXT_CTRL,
                                     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
                }
@@ -8953,6 +9455,7 @@ out:
 static int tg3_test_loopback(struct tg3 *tp)
 {
        int err = 0;
+       u32 cpmuctrl = 0;
 
        if (!netif_running(tp->dev))
                return TG3_LOOPBACK_FAILED;
@@ -8961,8 +9464,40 @@ static int tg3_test_loopback(struct tg3 *tp)
        if (err)
                return TG3_LOOPBACK_FAILED;
 
+       if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+               int i;
+               u32 status;
+
+               tw32(TG3_CPMU_MUTEX_REQ, CPMU_MUTEX_REQ_DRIVER);
+
+               /* Wait for up to 40 microseconds to acquire lock. */
+               for (i = 0; i < 4; i++) {
+                       status = tr32(TG3_CPMU_MUTEX_GNT);
+                       if (status == CPMU_MUTEX_GNT_DRIVER)
+                               break;
+                       udelay(10);
+               }
+
+               if (status != CPMU_MUTEX_GNT_DRIVER)
+                       return TG3_LOOPBACK_FAILED;
+
+               /* Turn off power management based on link speed. */
+               cpmuctrl = tr32(TG3_CPMU_CTRL);
+               tw32(TG3_CPMU_CTRL,
+                    cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE |
+                                 CPMU_CTRL_LINK_AWARE_MODE));
+       }
+
        if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
                err |= TG3_MAC_LOOPBACK_FAILED;
+
+       if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+               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 (tg3_run_loopback(tp, TG3_PHY_LOOPBACK))
                        err |= TG3_PHY_LOOPBACK_FAILED;
@@ -9111,25 +9646,10 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
        /* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
        __tg3_set_rx_mode(dev);
 
-       tg3_full_unlock(tp);
-
        if (netif_running(dev))
                tg3_netif_start(tp);
-}
-
-static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-       struct tg3 *tp = netdev_priv(dev);
-
-       if (netif_running(dev))
-               tg3_netif_stop(tp);
 
-       tg3_full_lock(tp, 0);
-       vlan_group_set_device(tp->vlgrp, vid, NULL);
        tg3_full_unlock(tp);
-
-       if (netif_running(dev))
-               tg3_netif_start(tp);
 }
 #endif
 
@@ -9216,21 +9736,16 @@ static const struct ethtool_ops tg3_ethtool_ops = {
        .set_pauseparam         = tg3_set_pauseparam,
        .get_rx_csum            = tg3_get_rx_csum,
        .set_rx_csum            = tg3_set_rx_csum,
-       .get_tx_csum            = ethtool_op_get_tx_csum,
        .set_tx_csum            = tg3_set_tx_csum,
-       .get_sg                 = ethtool_op_get_sg,
        .set_sg                 = ethtool_op_set_sg,
-       .get_tso                = ethtool_op_get_tso,
        .set_tso                = tg3_set_tso,
-       .self_test_count        = tg3_get_test_count,
        .self_test              = tg3_self_test,
        .get_strings            = tg3_get_strings,
        .phys_id                = tg3_phys_id,
-       .get_stats_count        = tg3_get_stats_count,
        .get_ethtool_stats      = tg3_get_ethtool_stats,
        .get_coalesce           = tg3_get_coalesce,
        .set_coalesce           = tg3_set_coalesce,
-       .get_perm_addr          = ethtool_op_get_perm_addr,
+       .get_sset_count         = tg3_get_sset_count,
 };
 
 static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
@@ -9420,11 +9935,13 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
                case FLASH_5755VENDOR_ATMEL_FLASH_1:
                case FLASH_5755VENDOR_ATMEL_FLASH_2:
                case FLASH_5755VENDOR_ATMEL_FLASH_3:
+               case FLASH_5755VENDOR_ATMEL_FLASH_5:
                        tp->nvram_jedecnum = JEDEC_ATMEL;
                        tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
                        tp->tg3_flags2 |= TG3_FLG2_FLASH;
                        tp->nvram_pagesize = 264;
-                       if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1)
+                       if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 ||
+                           nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5)
                                tp->nvram_size = (protect ? 0x3e200 : 0x80000);
                        else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
                                tp->nvram_size = (protect ? 0x1f200 : 0x40000);
@@ -9486,6 +10003,81 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
        }
 }
 
+static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
+{
+       u32 nvcfg1, protect = 0;
+
+       nvcfg1 = tr32(NVRAM_CFG1);
+
+       /* NVRAM protection for TPM */
+       if (nvcfg1 & (1 << 27)) {
+               tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
+               protect = 1;
+       }
+
+       nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
+       switch (nvcfg1) {
+               case FLASH_5761VENDOR_ATMEL_ADB021D:
+               case FLASH_5761VENDOR_ATMEL_ADB041D:
+               case FLASH_5761VENDOR_ATMEL_ADB081D:
+               case FLASH_5761VENDOR_ATMEL_ADB161D:
+               case FLASH_5761VENDOR_ATMEL_MDB021D:
+               case FLASH_5761VENDOR_ATMEL_MDB041D:
+               case FLASH_5761VENDOR_ATMEL_MDB081D:
+               case FLASH_5761VENDOR_ATMEL_MDB161D:
+                       tp->nvram_jedecnum = JEDEC_ATMEL;
+                       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+                       tp->tg3_flags2 |= TG3_FLG2_FLASH;
+                       tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+                       tp->nvram_pagesize = 256;
+                       break;
+               case FLASH_5761VENDOR_ST_A_M45PE20:
+               case FLASH_5761VENDOR_ST_A_M45PE40:
+               case FLASH_5761VENDOR_ST_A_M45PE80:
+               case FLASH_5761VENDOR_ST_A_M45PE16:
+               case FLASH_5761VENDOR_ST_M_M45PE20:
+               case FLASH_5761VENDOR_ST_M_M45PE40:
+               case FLASH_5761VENDOR_ST_M_M45PE80:
+               case FLASH_5761VENDOR_ST_M_M45PE16:
+                       tp->nvram_jedecnum = JEDEC_ST;
+                       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+                       tp->tg3_flags2 |= TG3_FLG2_FLASH;
+                       tp->nvram_pagesize = 256;
+                       break;
+       }
+
+       if (protect) {
+               tp->nvram_size = tr32(NVRAM_ADDR_LOCKOUT);
+       } else {
+               switch (nvcfg1) {
+                       case FLASH_5761VENDOR_ATMEL_ADB161D:
+                       case FLASH_5761VENDOR_ATMEL_MDB161D:
+                       case FLASH_5761VENDOR_ST_A_M45PE16:
+                       case FLASH_5761VENDOR_ST_M_M45PE16:
+                               tp->nvram_size = 0x100000;
+                               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;
+                               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;
+                               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;
+                               break;
+               }
+       }
+}
+
 static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
 {
        tp->nvram_jedecnum = JEDEC_ATMEL;
@@ -9525,8 +10117,11 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
                        tg3_get_5752_nvram_info(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)
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
                        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
@@ -9604,6 +10199,7 @@ static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr)
        if ((tp->tg3_flags & TG3_FLAG_NVRAM) &&
            (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
            (tp->tg3_flags2 & TG3_FLG2_FLASH) &&
+          !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) &&
            (tp->nvram_jedecnum == JEDEC_ATMEL))
 
                addr = ((addr / tp->nvram_pagesize) <<
@@ -9618,6 +10214,7 @@ static u32 tg3_nvram_logical_addr(struct tg3 *tp, u32 addr)
        if ((tp->tg3_flags & TG3_FLAG_NVRAM) &&
            (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
            (tp->tg3_flags2 & TG3_FLG2_FLASH) &&
+          !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) &&
            (tp->nvram_jedecnum == JEDEC_ATMEL))
 
                addr = ((addr >> ATMEL_AT45DB0X1B_PAGE_POS) *
@@ -9659,6 +10256,15 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
        return ret;
 }
 
+static int tg3_nvram_read_le(struct tg3 *tp, u32 offset, __le32 *val)
+{
+       u32 v;
+       int res = tg3_nvram_read(tp, offset, &v);
+       if (!res)
+               *val = cpu_to_le32(v);
+       return res;
+}
+
 static int tg3_nvram_read_swab(struct tg3 *tp, u32 offset, u32 *val)
 {
        int err;
@@ -9676,13 +10282,14 @@ static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
        u32 val;
 
        for (i = 0; i < len; i += 4) {
-               u32 addr, data;
+               u32 addr;
+               __le32 data;
 
                addr = offset + i;
 
                memcpy(&data, buf + i, 4);
 
-               tw32(GRC_EEPROM_DATA, cpu_to_le32(data));
+               tw32(GRC_EEPROM_DATA, le32_to_cpu(data));
 
                val = tr32(GRC_EEPROM_ADDR);
                tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE);
@@ -9732,8 +10339,8 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
                phy_addr = offset & ~pagemask;
 
                for (j = 0; j < pagesize; j += 4) {
-                       if ((ret = tg3_nvram_read(tp, phy_addr + j,
-                                               (u32 *) (tmp + j))))
+                       if ((ret = tg3_nvram_read_le(tp, phy_addr + j,
+                                               (__le32 *) (tmp + j))))
                                break;
                }
                if (ret)
@@ -9777,10 +10384,11 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
                        break;
 
                for (j = 0; j < pagesize; j += 4) {
-                       u32 data;
+                       __be32 data;
 
-                       data = *((u32 *) (tmp + j));
-                       tw32(NVRAM_WRDATA, cpu_to_be32(data));
+                       data = *((__be32 *) (tmp + j));
+                       /* swab32(le32_to_cpu(data)), actually */
+                       tw32(NVRAM_WRDATA, be32_to_cpu(data));
 
                        tw32(NVRAM_ADDR, phy_addr + j);
 
@@ -9814,10 +10422,11 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
        int i, ret = 0;
 
        for (i = 0; i < len; i += 4, offset += 4) {
-               u32 data, page_off, phy_addr, nvram_cmd;
+               u32 page_off, phy_addr, nvram_cmd;
+               __be32 data;
 
                memcpy(&data, buf + i, 4);
-               tw32(NVRAM_WRDATA, cpu_to_be32(data));
+               tw32(NVRAM_WRDATA, be32_to_cpu(data));
 
                page_off = offset % tp->nvram_pagesize;
 
@@ -9838,6 +10447,8 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
                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->nvram_jedecnum == JEDEC_ST) &&
                    (nvram_cmd & NVRAM_CMD_FIRST)) {
 
@@ -10008,6 +10619,12 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                        tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
                        tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
                }
+               val = tr32(VCPU_CFGSHDW);
+               if (val & VCPU_CFGSHDW_ASPM_DBNC)
+                       tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
+               if ((val & VCPU_CFGSHDW_WOL_ENABLE) &&
+                   (val & VCPU_CFGSHDW_WOL_MAGPKT))
+                       tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
                return;
        }
 
@@ -10107,6 +10724,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                    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 (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
                        tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
                        if ((tp->pdev->subsystem_vendor ==
@@ -10124,10 +10745,16 @@ 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)
+                       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)
+                       tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
+
                if (cfg2 & (1 << 17))
                        tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
 
@@ -10135,6 +10762,14 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                /* bootcode if bit 18 is set */
                if (cfg2 & (1 << 18))
                        tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS;
+
+               if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+                       u32 cfg3;
+
+                       tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3);
+                       if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE)
+                               tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
+               }
        }
 }
 
@@ -10148,7 +10783,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
         * firwmare access to the PHY hardware.
         */
        err = 0;
-       if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+       if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+           (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
                hw_phy_id = hw_phy_id_masked = PHY_ID_INVALID;
        } else {
                /* Now read the physical PHY_ID from the chip and verify
@@ -10195,6 +10831,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
        }
 
        if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) &&
+           !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) &&
            !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
                u32 bmsr, adv_reg, tg3_ctrl, mask;
 
@@ -10291,6 +10928,7 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
                vpd_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_VPD);
                for (i = 0; i < 256; i += 4) {
                        u32 tmp, j = 0;
+                       __le32 v;
                        u16 tmp16;
 
                        pci_write_config_word(tp->pdev, vpd_cap + PCI_VPD_ADDR,
@@ -10307,8 +10945,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 
                        pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA,
                                              &tmp);
-                       tmp = cpu_to_le32(tmp);
-                       memcpy(&vpd_data[i], &tmp, 4);
+                       v = cpu_to_le32(tmp);
+                       memcpy(&vpd_data[i], &v, 4);
                }
        }
 
@@ -10364,9 +11002,24 @@ out_not_found:
                strcpy(tp->board_part_number, "none");
 }
 
+static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
+{
+       u32 val;
+
+       if (tg3_nvram_read_swab(tp, offset, &val) ||
+           (val & 0xfc000000) != 0x0c000000 ||
+           tg3_nvram_read_swab(tp, offset + 4, &val) ||
+           val != 0)
+               return 0;
+
+       return 1;
+}
+
 static void __devinit tg3_read_fw_ver(struct tg3 *tp)
 {
        u32 val, offset, start;
+       u32 ver_offset;
+       int i, bcnt;
 
        if (tg3_nvram_read_swab(tp, 0, &val))
                return;
@@ -10379,31 +11032,75 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
                return;
 
        offset = tg3_nvram_logical_addr(tp, offset);
-       if (tg3_nvram_read_swab(tp, offset, &val))
+
+       if (!tg3_fw_img_is_valid(tp, offset) ||
+           tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
                return;
 
-       if ((val & 0xfc000000) == 0x0c000000) {
-               u32 ver_offset, addr;
-               int i;
+       offset = offset + ver_offset - start;
+       for (i = 0; i < 16; i += 4) {
+               __le32 v;
+               if (tg3_nvram_read_le(tp, offset + i, &v))
+                       return;
+
+               memcpy(tp->fw_ver + i, &v, 4);
+       }
+
+       if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+            (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
+               return;
 
-               if (tg3_nvram_read_swab(tp, offset + 4, &val) ||
-                   tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
+       for (offset = TG3_NVM_DIR_START;
+            offset < TG3_NVM_DIR_END;
+            offset += TG3_NVM_DIRENT_SIZE) {
+               if (tg3_nvram_read_swab(tp, offset, &val))
                        return;
 
-               if (val != 0)
+               if ((val >> TG3_NVM_DIRTYPE_SHIFT) == TG3_NVM_DIRTYPE_ASFINI)
+                       break;
+       }
+
+       if (offset == TG3_NVM_DIR_END)
+               return;
+
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+               start = 0x08000000;
+       else if (tg3_nvram_read_swab(tp, offset - 4, &start))
+               return;
+
+       if (tg3_nvram_read_swab(tp, offset + 4, &offset) ||
+           !tg3_fw_img_is_valid(tp, offset) ||
+           tg3_nvram_read_swab(tp, offset + 8, &val))
+               return;
+
+       offset += val - start;
+
+       bcnt = strlen(tp->fw_ver);
+
+       tp->fw_ver[bcnt++] = ',';
+       tp->fw_ver[bcnt++] = ' ';
+
+       for (i = 0; i < 4; i++) {
+               __le32 v;
+               if (tg3_nvram_read_le(tp, offset, &v))
                        return;
 
-               addr = offset + ver_offset - start;
-               for (i = 0; i < 16; i += 4) {
-                       if (tg3_nvram_read(tp, addr + i, &val))
-                               return;
+               offset += sizeof(v);
 
-                       val = cpu_to_le32(val);
-                       memcpy(tp->fw_ver + i, &val, 4);
+               if (bcnt > TG3_VER_SIZE - sizeof(v)) {
+                       memcpy(&tp->fw_ver[bcnt], &v, TG3_VER_SIZE - bcnt);
+                       break;
                }
+
+               memcpy(&tp->fw_ver[bcnt], &v, sizeof(v));
+               bcnt += sizeof(v);
        }
+
+       tp->fw_ver[TG3_VER_SIZE - 1] = 0;
 }
 
+static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
+
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
        static struct pci_device_id write_reorder_chipsets[] = {
@@ -10444,6 +11141,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
        tp->pci_chip_rev_id = (misc_ctrl_reg >>
                               MISC_HOST_CTRL_CHIPREV_SHIFT);
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
+               u32 prod_id_asic_rev;
+
+               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;
+       }
 
        /* Wrong chip ID in 5752 A0. This code can be removed later
         * as A0 is not in production.
@@ -10496,11 +11200,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                                continue;
                        }
                        if (pci_id->rev != PCI_ANY_ID) {
-                               u8 rev;
-
-                               pci_read_config_byte(bridge, PCI_REVISION_ID,
-                                                    &rev);
-                               if (rev > pci_id->rev)
+                               if (bridge->revision > pci_id->rev)
                                        continue;
                        }
                        if (bridge->subordinate &&
@@ -10559,10 +11259,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        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 ||
            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->tg3_flags2 & TG3_FLG2_5780_CLASS))
                tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
@@ -10572,8 +11278,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
 
        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 ||
+                   GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX ||
+                   (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 &&
+                    tp->pci_chip_rev_id <= CHIPREV_ID_5714_A2 &&
+                    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 ||
                    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;
@@ -10591,12 +11307,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            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)
                tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
 
        pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
        if (pcie_cap != 0) {
                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;
 
@@ -10631,10 +11352,20 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                                       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_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
                              &pci_state_reg);
 
-       if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
+       if (tp->pcix_cap && (pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
                tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
 
                /* If this is a 5700 BX chipset, and we are in PCI-X
@@ -10645,7 +11376,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                 */
                if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
                        u32 pm_reg;
-                       u16 pci_cmd;
 
                        tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
 
@@ -10653,11 +11383,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                         * space registers clobbered due to this bug.
                         * So explicitly force the chip into D0 here.
                         */
-                       pci_read_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT,
+                       pci_read_config_dword(tp->pdev,
+                                             tp->pm_cap + PCI_PM_CTRL,
                                              &pm_reg);
                        pm_reg &= ~PCI_PM_CTRL_STATE_MASK;
                        pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */;
-                       pci_write_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT,
+                       pci_write_config_dword(tp->pdev,
+                                              tp->pm_cap + PCI_PM_CTRL,
                                               pm_reg);
 
                        /* Also, force SERR#/PERR# in PCI command. */
@@ -10673,17 +11405,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
                tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
 
-       /* Back to back register writes can cause problems on this chip,
-        * the workaround is to read back all reg writes except those to
-        * mailbox regs.  See tg3_write_indirect_reg32().
-        *
-        * PCI Express 5750_A0 rev chips need this workaround too.
-        */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
-           ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
-            tp->pci_chip_rev_id == CHIPREV_ID_5750_A0))
-               tp->tg3_flags |= TG3_FLAG_5701_REG_WRITE_BUG;
-
        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)
@@ -10707,8 +11428,19 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        /* Various workaround register access methods */
        if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG)
                tp->write32 = tg3_write_indirect_reg32;
-       else if (tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG)
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
+                ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
+                 tp->pci_chip_rev_id == CHIPREV_ID_5750_A0)) {
+               /*
+                * Back to back register writes can cause problems on these
+                * chips, the workaround is to read back all reg writes
+                * except those to mailbox regs.
+                *
+                * See tg3_write_indirect_reg32().
+                */
                tp->write32 = tg3_write_flush_reg32;
+       }
+
 
        if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
            (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
@@ -10755,6 +11487,27 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
         */
        tg3_get_eeprom_hw_cfg(tp);
 
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+               /* Allow reads and writes to the
+                * APE register and memory space.
+                */
+               pci_state_reg |= PCISTATE_ALLOW_APE_CTLSPC_WR |
+                                PCISTATE_ALLOW_APE_SHMEM_WR;
+               pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE,
+                                      pci_state_reg);
+       }
+
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
+               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.
@@ -10821,7 +11574,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
        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_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->pdev->device != PCI_DEVICE_ID_TIGON3_5756 &&
                            tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722)
                                tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
@@ -10947,6 +11702,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
         * upon subsystem IDs.
         */
        if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
            !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
                tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
                                  TG3_FLAG_USE_LINKCHG_REG);
@@ -10963,6 +11719,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
         */
        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
@@ -10983,10 +11741,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
                tp->rx_std_max_post = 8;
 
-       /* By default, disable wake-on-lan.  User can change this
-        * using ETHTOOL_SWOL.
-        */
-       tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
+       if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND)
+               tp->pwrmgmt_thresh = tr32(PCIE_PWR_MGMT_THRESH) &
+                                    PCIE_PWR_MGMT_L1_THRESH_MSK;
 
        return err;
 }
@@ -11580,8 +12337,10 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        case PHY_ID_BCM5780:    return "5780";
        case PHY_ID_BCM5755:    return "5755";
        case PHY_ID_BCM5787:    return "5787";
+       case PHY_ID_BCM5784:    return "5784";
        case PHY_ID_BCM5756:    return "5722/5756";
        case PHY_ID_BCM5906:    return "5906";
+       case PHY_ID_BCM5761:    return "5761";
        case PHY_ID_BCM8002:    return "8002/serdes";
        case 0:                 return "serdes";
        default:                return "unknown";
@@ -11690,9 +12449,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        unsigned long tg3reg_base, tg3reg_len;
        struct net_device *dev;
        struct tg3 *tp;
-       int i, err, pm_cap;
+       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);
@@ -11739,13 +12499,11 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                goto err_out_free_res;
        }
 
-       SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
 #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;
-       dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid;
 #endif
 
        tp = netdev_priv(dev);
@@ -11787,7 +12545,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        INIT_WORK(&tp->reset_task, tg3_reset_task);
 
        tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len);
-       if (tp->regs == 0UL) {
+       if (!tp->regs) {
                printk(KERN_ERR PFX "Cannot map device registers, "
                       "aborting.\n");
                err = -ENOMEM;
@@ -11807,9 +12565,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        dev->set_mac_address = tg3_set_mac_addr;
        dev->do_ioctl = tg3_ioctl;
        dev->tx_timeout = tg3_tx_timeout;
-       dev->poll = tg3_poll;
+       netif_napi_add(dev, &tp->napi, tg3_poll, 64);
        dev->ethtool_ops = &tg3_ethtool_ops;
-       dev->weight = 64;
        dev->watchdog_timeo = TG3_TX_TIMEOUT;
        dev->change_mtu = tg3_change_mtu;
        dev->irq = pdev->irq;
@@ -11887,6 +12644,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
                    (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906))
                        dev->features |= NETIF_F_TSO6;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+                       dev->features |= NETIF_F_TSO_ECN;
        }
 
 
@@ -11897,10 +12656,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                tp->rx_pending = 63;
        }
 
-       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);
-
        err = tg3_get_device_address(tp);
        if (err) {
                printk(KERN_ERR PFX "Could not obtain valid ethernet address, "
@@ -11908,6 +12663,28 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                goto err_out_iounmap;
        }
 
+       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) {
+                       printk(KERN_ERR PFX "Cannot map APE registers, "
+                              "aborting.\n");
+                       err = -ENOMEM;
+                       goto err_out_iounmap;
+               }
+
+               tg3_ape_lock_init(tp);
+       }
+
        /*
         * Reset chip in case UNDI or EFI driver did not shutdown
         * DMA self test will enable WDMAC and we'll see (spurious)
@@ -11915,7 +12692,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
         */
        if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
            (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
-               pci_save_state(tp->pdev);
                tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
        }
@@ -11923,44 +12699,41 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        err = tg3_test_dma(tp);
        if (err) {
                printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
-               goto err_out_iounmap;
+               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)
-                       dev->features |= NETIF_F_HW_CSUM;
-               else
-                       dev->features |= NETIF_F_IP_CSUM;
-               dev->features |= NETIF_F_SG;
+                   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;
 
        tg3_init_coal(tp);
 
-       /* Now that we have fully setup the chip, save away a snapshot
-        * of the PCI config space.  We need to restore this after
-        * GRC_MISC_CFG core clock resets and some resume events.
-        */
-       pci_save_state(tp->pdev);
-
        pci_set_drvdata(pdev, dev);
 
        err = register_netdev(dev);
        if (err) {
                printk(KERN_ERR PFX "Cannot register net device, "
                       "aborting.\n");
-               goto err_out_iounmap;
+               goto err_out_apeunmap;
        }
 
-       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ",
+       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] "
+              "(%s) %s Ethernet %s\n",
               dev->name,
               tp->board_part_number,
               tp->pci_chip_rev_id,
@@ -11968,11 +12741,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
               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")));
-
-       for (i = 0; i < 6; i++)
-               printk("%2.2x%c", dev->dev_addr[i],
-                      i == 5 ? '\n' : ':');
+                "10/100/1000Base-T")),
+              print_mac(mac, dev->dev_addr));
 
        printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
               "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n",
@@ -11990,6 +12760,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        return 0;
 
+err_out_apeunmap:
+       if (tp->aperegs) {
+               iounmap(tp->aperegs);
+               tp->aperegs = NULL;
+       }
+
 err_out_iounmap:
        if (tp->regs) {
                iounmap(tp->regs);
@@ -12017,6 +12793,10 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
 
                flush_scheduled_work();
                unregister_netdev(dev);
+               if (tp->aperegs) {
+                       iounmap(tp->aperegs);
+                       tp->aperegs = NULL;
+               }
                if (tp->regs) {
                        iounmap(tp->regs);
                        tp->regs = NULL;
@@ -12034,6 +12814,12 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
        struct tg3 *tp = netdev_priv(dev);
        int err;
 
+       /* PCI register 4 needs to be saved whether netif_running() or not.
+        * MSI address and data need to be saved if using MSI and
+        * netif_running().
+        */
+       pci_save_state(pdev);
+
        if (!netif_running(dev))
                return 0;
 
@@ -12053,9 +12839,6 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
        tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
        tg3_full_unlock(tp);
 
-       /* Save MSI address and data for resume.  */
-       pci_save_state(pdev);
-
        err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
        if (err) {
                tg3_full_lock(tp, 0);
@@ -12083,11 +12866,11 @@ static int tg3_resume(struct pci_dev *pdev)
        struct tg3 *tp = netdev_priv(dev);
        int err;
 
+       pci_restore_state(tp->pdev);
+
        if (!netif_running(dev))
                return 0;
 
-       pci_restore_state(tp->pdev);
-
        err = tg3_set_power_state(tp, PCI_D0);
        if (err)
                return err;