]> Pileus Git - ~andy/linux/blobdiff - drivers/net/ethernet/broadcom/tg3.c
tg3: fix to append hardware time stamping flags
[~andy/linux] / drivers / net / ethernet / broadcom / tg3.c
index a7449984c7a68f01666d101e49b42a53105abd07..728d42ab2a7636e4656a28174ac2b8c9159c60f0 100644 (file)
@@ -94,10 +94,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define DRV_MODULE_NAME                "tg3"
 #define TG3_MAJ_NUM                    3
-#define TG3_MIN_NUM                    130
+#define TG3_MIN_NUM                    131
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "February 14, 2013"
+#define DRV_MODULE_RELDATE     "April 09, 2013"
 
 #define RESET_KIND_SHUTDOWN    0
 #define RESET_KIND_INIT                1
@@ -1874,6 +1874,20 @@ static void tg3_link_report(struct tg3 *tp)
        tp->link_up = netif_carrier_ok(tp->dev);
 }
 
+static u32 tg3_decode_flowctrl_1000T(u32 adv)
+{
+       u32 flowctrl = 0;
+
+       if (adv & ADVERTISE_PAUSE_CAP) {
+               flowctrl |= FLOW_CTRL_RX;
+               if (!(adv & ADVERTISE_PAUSE_ASYM))
+                       flowctrl |= FLOW_CTRL_TX;
+       } else if (adv & ADVERTISE_PAUSE_ASYM)
+               flowctrl |= FLOW_CTRL_TX;
+
+       return flowctrl;
+}
+
 static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
 {
        u16 miireg;
@@ -1890,6 +1904,20 @@ static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
        return miireg;
 }
 
+static u32 tg3_decode_flowctrl_1000X(u32 adv)
+{
+       u32 flowctrl = 0;
+
+       if (adv & ADVERTISE_1000XPAUSE) {
+               flowctrl |= FLOW_CTRL_RX;
+               if (!(adv & ADVERTISE_1000XPSE_ASYM))
+                       flowctrl |= FLOW_CTRL_TX;
+       } else if (adv & ADVERTISE_1000XPSE_ASYM)
+               flowctrl |= FLOW_CTRL_TX;
+
+       return flowctrl;
+}
+
 static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
 {
        u8 cap = 0;
@@ -2200,7 +2228,7 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable)
        tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
 }
 
-static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
+static void tg3_phy_toggle_automdix(struct tg3 *tp, bool enable)
 {
        u32 phy;
 
@@ -2292,7 +2320,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp)
        tg3_phy_toggle_auxctl_smdsp(tp, false);
 }
 
-static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
+static void tg3_phy_eee_adjust(struct tg3 *tp, bool current_link_up)
 {
        u32 val;
 
@@ -2302,7 +2330,7 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
        tp->setlpicnt = 0;
 
        if (tp->link_config.autoneg == AUTONEG_ENABLE &&
-           current_link_up == 1 &&
+           current_link_up &&
            tp->link_config.active_duplex == DUPLEX_FULL &&
            (tp->link_config.active_speed == SPEED_100 ||
             tp->link_config.active_speed == SPEED_1000)) {
@@ -2324,7 +2352,7 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
        }
 
        if (!tp->setlpicnt) {
-               if (current_link_up == 1 &&
+               if (current_link_up &&
                   !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
                        tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000);
                        tg3_phy_toggle_auxctl_smdsp(tp, false);
@@ -2677,7 +2705,7 @@ out:
        if (tg3_chip_rev_id(tp) == CHIPREV_ID_5762_A0)
                tg3_phydsp_write(tp, 0xffb, 0x4000);
 
-       tg3_phy_toggle_automdix(tp, 1);
+       tg3_phy_toggle_automdix(tp, true);
        tg3_phy_set_wirespeed(tp);
        return 0;
 }
@@ -2933,6 +2961,9 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
 {
        u32 val;
 
+       if (tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN)
+               return;
+
        if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
                if (tg3_asic_rev(tp) == ASIC_REV_5704) {
                        u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
@@ -3820,7 +3851,7 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
 
 
 /* tp->lock is held. */
-static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
+static void __tg3_set_mac_addr(struct tg3 *tp, bool skip_mac_1)
 {
        u32 addr_high, addr_low;
        int i;
@@ -3883,7 +3914,7 @@ static int tg3_power_up(struct tg3 *tp)
        return err;
 }
 
-static int tg3_setup_phy(struct tg3 *, int);
+static int tg3_setup_phy(struct tg3 *, bool);
 
 static int tg3_power_down_prepare(struct tg3 *tp)
 {
@@ -3955,7 +3986,7 @@ static int tg3_power_down_prepare(struct tg3 *tp)
                        tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
 
                if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
-                       tg3_setup_phy(tp, 0);
+                       tg3_setup_phy(tp, false);
        }
 
        if (tg3_asic_rev(tp) == ASIC_REV_5906) {
@@ -3996,7 +4027,13 @@ static int tg3_power_down_prepare(struct tg3 *tp)
 
                        if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
                                mac_mode = MAC_MODE_PORT_MODE_GMII;
-                       else
+                       else if (tp->phy_flags &
+                                TG3_PHYFLG_KEEP_LINK_ON_PWRDN) {
+                               if (tp->link_config.active_speed == SPEED_1000)
+                                       mac_mode = MAC_MODE_PORT_MODE_GMII;
+                               else
+                                       mac_mode = MAC_MODE_PORT_MODE_MII;
+                       } else
                                mac_mode = MAC_MODE_PORT_MODE_MII;
 
                        mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY;
@@ -4250,12 +4287,16 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
            (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
                u32 adv, fc;
 
-               if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
+               if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) &&
+                   !(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN)) {
                        adv = ADVERTISED_10baseT_Half |
                              ADVERTISED_10baseT_Full;
                        if (tg3_flag(tp, WOL_SPEED_100MB))
                                adv |= ADVERTISED_100baseT_Half |
                                       ADVERTISED_100baseT_Full;
+                       if (tp->phy_flags & TG3_PHYFLG_1G_ON_VAUX_OK)
+                               adv |= ADVERTISED_1000baseT_Half |
+                                      ADVERTISED_1000baseT_Full;
 
                        fc = FLOW_CTRL_TX | FLOW_CTRL_RX;
                } else {
@@ -4269,6 +4310,15 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
 
                tg3_phy_autoneg_cfg(tp, adv, fc);
 
+               if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) &&
+                   (tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN)) {
+                       /* Normally during power down we want to autonegotiate
+                        * the lowest possible speed for WOL. However, to avoid
+                        * link flap, we leave it untouched.
+                        */
+                       return;
+               }
+
                tg3_writephy(tp, MII_BMCR,
                             BMCR_ANENABLE | BMCR_ANRESTART);
        } else {
@@ -4325,6 +4375,103 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
        }
 }
 
+static int tg3_phy_pull_config(struct tg3 *tp)
+{
+       int err;
+       u32 val;
+
+       err = tg3_readphy(tp, MII_BMCR, &val);
+       if (err)
+               goto done;
+
+       if (!(val & BMCR_ANENABLE)) {
+               tp->link_config.autoneg = AUTONEG_DISABLE;
+               tp->link_config.advertising = 0;
+               tg3_flag_clear(tp, PAUSE_AUTONEG);
+
+               err = -EIO;
+
+               switch (val & (BMCR_SPEED1000 | BMCR_SPEED100)) {
+               case 0:
+                       if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)
+                               goto done;
+
+                       tp->link_config.speed = SPEED_10;
+                       break;
+               case BMCR_SPEED100:
+                       if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)
+                               goto done;
+
+                       tp->link_config.speed = SPEED_100;
+                       break;
+               case BMCR_SPEED1000:
+                       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
+                               tp->link_config.speed = SPEED_1000;
+                               break;
+                       }
+                       /* Fall through */
+               default:
+                       goto done;
+               }
+
+               if (val & BMCR_FULLDPLX)
+                       tp->link_config.duplex = DUPLEX_FULL;
+               else
+                       tp->link_config.duplex = DUPLEX_HALF;
+
+               tp->link_config.flowctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
+
+               err = 0;
+               goto done;
+       }
+
+       tp->link_config.autoneg = AUTONEG_ENABLE;
+       tp->link_config.advertising = ADVERTISED_Autoneg;
+       tg3_flag_set(tp, PAUSE_AUTONEG);
+
+       if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) {
+               u32 adv;
+
+               err = tg3_readphy(tp, MII_ADVERTISE, &val);
+               if (err)
+                       goto done;
+
+               adv = mii_adv_to_ethtool_adv_t(val & ADVERTISE_ALL);
+               tp->link_config.advertising |= adv | ADVERTISED_TP;
+
+               tp->link_config.flowctrl = tg3_decode_flowctrl_1000T(val);
+       } else {
+               tp->link_config.advertising |= ADVERTISED_FIBRE;
+       }
+
+       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
+               u32 adv;
+
+               if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) {
+                       err = tg3_readphy(tp, MII_CTRL1000, &val);
+                       if (err)
+                               goto done;
+
+                       adv = mii_ctrl1000_to_ethtool_adv_t(val);
+               } else {
+                       err = tg3_readphy(tp, MII_ADVERTISE, &val);
+                       if (err)
+                               goto done;
+
+                       adv = tg3_decode_flowctrl_1000X(val);
+                       tp->link_config.flowctrl = adv;
+
+                       val &= (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL);
+                       adv = mii_adv_to_ethtool_adv_x(val);
+               }
+
+               tp->link_config.advertising |= adv;
+       }
+
+done:
+       return err;
+}
+
 static int tg3_init_5401phy_dsp(struct tg3 *tp)
 {
        int err;
@@ -4344,6 +4491,32 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp)
        return err;
 }
 
+static bool tg3_phy_eee_config_ok(struct tg3 *tp)
+{
+       u32 val;
+       u32 tgtadv = 0;
+       u32 advertising = tp->link_config.advertising;
+
+       if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+               return true;
+
+       if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &val))
+               return false;
+
+       val &= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
+
+
+       if (advertising & ADVERTISED_100baseT_Full)
+               tgtadv |= MDIO_AN_EEE_ADV_100TX;
+       if (advertising & ADVERTISED_1000baseT_Full)
+               tgtadv |= MDIO_AN_EEE_ADV_1000T;
+
+       if (val != tgtadv)
+               return false;
+
+       return true;
+}
+
 static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv)
 {
        u32 advmsk, tgtadv, advertising;
@@ -4410,7 +4583,7 @@ static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv)
        return true;
 }
 
-static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)
+static bool tg3_test_and_report_link_chg(struct tg3 *tp, bool curr_link_up)
 {
        if (curr_link_up != tp->link_up) {
                if (curr_link_up) {
@@ -4428,23 +4601,28 @@ static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)
        return false;
 }
 
-static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
+static void tg3_clear_mac_status(struct tg3 *tp)
 {
-       int current_link_up;
+       tw32(MAC_EVENT, 0);
+
+       tw32_f(MAC_STATUS,
+              MAC_STATUS_SYNC_CHANGED |
+              MAC_STATUS_CFG_CHANGED |
+              MAC_STATUS_MI_COMPLETION |
+              MAC_STATUS_LNKSTATE_CHANGED);
+       udelay(40);
+}
+
+static int tg3_setup_copper_phy(struct tg3 *tp, bool force_reset)
+{
+       bool current_link_up;
        u32 bmsr, val;
        u32 lcl_adv, rmt_adv;
        u16 current_speed;
        u8 current_duplex;
        int i, err;
 
-       tw32(MAC_EVENT, 0);
-
-       tw32_f(MAC_STATUS,
-            (MAC_STATUS_SYNC_CHANGED |
-             MAC_STATUS_CFG_CHANGED |
-             MAC_STATUS_MI_COMPLETION |
-             MAC_STATUS_LNKSTATE_CHANGED));
-       udelay(40);
+       tg3_clear_mac_status(tp);
 
        if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
                tw32_f(MAC_MI_MODE,
@@ -4464,7 +4642,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
                    !(bmsr & BMSR_LSTATUS))
-                       force_reset = 1;
+                       force_reset = true;
        }
        if (force_reset)
                tg3_phy_reset(tp);
@@ -4528,7 +4706,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
                        tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
        }
 
-       current_link_up = 0;
+       current_link_up = false;
        current_speed = SPEED_UNKNOWN;
        current_duplex = DUPLEX_UNKNOWN;
        tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE;
@@ -4587,19 +4765,31 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
                tp->link_config.active_duplex = current_duplex;
 
                if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+                       bool eee_config_ok = tg3_phy_eee_config_ok(tp);
+
                        if ((bmcr & BMCR_ANENABLE) &&
+                           eee_config_ok &&
                            tg3_phy_copper_an_config_ok(tp, &lcl_adv) &&
                            tg3_phy_copper_fetch_rmtadv(tp, &rmt_adv))
-                               current_link_up = 1;
+                               current_link_up = true;
+
+                       /* EEE settings changes take effect only after a phy
+                        * reset.  If we have skipped a reset due to Link Flap
+                        * Avoidance being enabled, do it now.
+                        */
+                       if (!eee_config_ok &&
+                           (tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) &&
+                           !force_reset)
+                               tg3_phy_reset(tp);
                } else {
                        if (!(bmcr & BMCR_ANENABLE) &&
                            tp->link_config.speed == current_speed &&
                            tp->link_config.duplex == current_duplex) {
-                               current_link_up = 1;
+                               current_link_up = true;
                        }
                }
 
-               if (current_link_up == 1 &&
+               if (current_link_up &&
                    tp->link_config.active_duplex == DUPLEX_FULL) {
                        u32 reg, bit;
 
@@ -4619,11 +4809,11 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
        }
 
 relink:
-       if (current_link_up == 0 || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
+       if (!current_link_up || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
                tg3_phy_copper_begin(tp);
 
                if (tg3_flag(tp, ROBOSWITCH)) {
-                       current_link_up = 1;
+                       current_link_up = true;
                        /* FIXME: when BCM5325 switch is used use 100 MBit/s */
                        current_speed = SPEED_1000;
                        current_duplex = DUPLEX_FULL;
@@ -4634,11 +4824,11 @@ relink:
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
                    (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
-                       current_link_up = 1;
+                       current_link_up = true;
        }
 
        tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
-       if (current_link_up == 1) {
+       if (current_link_up) {
                if (tp->link_config.active_speed == SPEED_100 ||
                    tp->link_config.active_speed == SPEED_10)
                        tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
@@ -4674,7 +4864,7 @@ relink:
                tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
 
        if (tg3_asic_rev(tp) == ASIC_REV_5700) {
-               if (current_link_up == 1 &&
+               if (current_link_up &&
                    tg3_5700_link_polarity(tp, tp->link_config.active_speed))
                        tp->mac_mode |= MAC_MODE_LINK_POLARITY;
                else
@@ -4705,7 +4895,7 @@ relink:
        udelay(40);
 
        if (tg3_asic_rev(tp) == ASIC_REV_5700 &&
-           current_link_up == 1 &&
+           current_link_up &&
            tp->link_config.active_speed == SPEED_1000 &&
            (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) {
                udelay(120);
@@ -5145,19 +5335,19 @@ static void tg3_init_bcm8002(struct tg3 *tp)
        tg3_writephy(tp, 0x10, 0x8011);
 }
 
-static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
+static bool tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
 {
        u16 flowctrl;
+       bool current_link_up;
        u32 sg_dig_ctrl, sg_dig_status;
        u32 serdes_cfg, expected_sg_dig_ctrl;
        int workaround, port_a;
-       int current_link_up;
 
        serdes_cfg = 0;
        expected_sg_dig_ctrl = 0;
        workaround = 0;
        port_a = 1;
-       current_link_up = 0;
+       current_link_up = false;
 
        if (tg3_chip_rev_id(tp) != CHIPREV_ID_5704_A0 &&
            tg3_chip_rev_id(tp) != CHIPREV_ID_5704_A1) {
@@ -5188,7 +5378,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
                }
                if (mac_status & MAC_STATUS_PCS_SYNCED) {
                        tg3_setup_flow_control(tp, 0, 0);
-                       current_link_up = 1;
+                       current_link_up = true;
                }
                goto out;
        }
@@ -5209,7 +5399,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
                                    MAC_STATUS_RCVD_CFG)) ==
                     MAC_STATUS_PCS_SYNCED)) {
                        tp->serdes_counter--;
-                       current_link_up = 1;
+                       current_link_up = true;
                        goto out;
                }
 restart_autoneg:
@@ -5244,7 +5434,7 @@ restart_autoneg:
                                           mii_adv_to_ethtool_adv_x(remote_adv);
 
                        tg3_setup_flow_control(tp, local_adv, remote_adv);
-                       current_link_up = 1;
+                       current_link_up = true;
                        tp->serdes_counter = 0;
                        tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
                } else if (!(sg_dig_status & SG_DIG_AUTONEG_COMPLETE)) {
@@ -5272,7 +5462,7 @@ restart_autoneg:
                                if ((mac_status & MAC_STATUS_PCS_SYNCED) &&
                                    !(mac_status & MAC_STATUS_RCVD_CFG)) {
                                        tg3_setup_flow_control(tp, 0, 0);
-                                       current_link_up = 1;
+                                       current_link_up = true;
                                        tp->phy_flags |=
                                                TG3_PHYFLG_PARALLEL_DETECT;
                                        tp->serdes_counter =
@@ -5290,9 +5480,9 @@ out:
        return current_link_up;
 }
 
-static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
+static bool tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
 {
-       int current_link_up = 0;
+       bool current_link_up = false;
 
        if (!(mac_status & MAC_STATUS_PCS_SYNCED))
                goto out;
@@ -5319,7 +5509,7 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
 
                        tg3_setup_flow_control(tp, local_adv, remote_adv);
 
-                       current_link_up = 1;
+                       current_link_up = true;
                }
                for (i = 0; i < 30; i++) {
                        udelay(20);
@@ -5334,15 +5524,15 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
                }
 
                mac_status = tr32(MAC_STATUS);
-               if (current_link_up == 0 &&
+               if (!current_link_up &&
                    (mac_status & MAC_STATUS_PCS_SYNCED) &&
                    !(mac_status & MAC_STATUS_RCVD_CFG))
-                       current_link_up = 1;
+                       current_link_up = true;
        } else {
                tg3_setup_flow_control(tp, 0, 0);
 
                /* Forcing 1000FD link up. */
-               current_link_up = 1;
+               current_link_up = true;
 
                tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
                udelay(40);
@@ -5355,13 +5545,13 @@ out:
        return current_link_up;
 }
 
-static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
+static int tg3_setup_fiber_phy(struct tg3 *tp, bool force_reset)
 {
        u32 orig_pause_cfg;
        u16 orig_active_speed;
        u8 orig_active_duplex;
        u32 mac_status;
-       int current_link_up;
+       bool current_link_up;
        int i;
 
        orig_pause_cfg = tp->link_config.active_flowctrl;
@@ -5398,7 +5588,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
        tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
        udelay(40);
 
-       current_link_up = 0;
+       current_link_up = false;
        tp->link_config.rmt_adv = 0;
        mac_status = tr32(MAC_STATUS);
 
@@ -5423,7 +5613,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
 
        mac_status = tr32(MAC_STATUS);
        if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
-               current_link_up = 0;
+               current_link_up = false;
                if (tp->link_config.autoneg == AUTONEG_ENABLE &&
                    tp->serdes_counter == 0) {
                        tw32_f(MAC_MODE, (tp->mac_mode |
@@ -5433,7 +5623,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
                }
        }
 
-       if (current_link_up == 1) {
+       if (current_link_up) {
                tp->link_config.active_speed = SPEED_1000;
                tp->link_config.active_duplex = DUPLEX_FULL;
                tw32(MAC_LED_CTRL, (tp->led_ctrl |
@@ -5458,33 +5648,63 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
        return 0;
 }
 
-static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
+static int tg3_setup_fiber_mii_phy(struct tg3 *tp, bool force_reset)
 {
-       int current_link_up, err = 0;
+       int err = 0;
        u32 bmsr, bmcr;
-       u16 current_speed;
-       u8 current_duplex;
-       u32 local_adv, remote_adv;
+       u16 current_speed = SPEED_UNKNOWN;
+       u8 current_duplex = DUPLEX_UNKNOWN;
+       bool current_link_up = false;
+       u32 local_adv, remote_adv, sgsr;
+
+       if ((tg3_asic_rev(tp) == ASIC_REV_5719 ||
+            tg3_asic_rev(tp) == ASIC_REV_5720) &&
+            !tg3_readphy(tp, SERDES_TG3_1000X_STATUS, &sgsr) &&
+            (sgsr & SERDES_TG3_SGMII_MODE)) {
+
+               if (force_reset)
+                       tg3_phy_reset(tp);
+
+               tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
+
+               if (!(sgsr & SERDES_TG3_LINK_UP)) {
+                       tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+               } else {
+                       current_link_up = true;
+                       if (sgsr & SERDES_TG3_SPEED_1000) {
+                               current_speed = SPEED_1000;
+                               tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
+                       } else if (sgsr & SERDES_TG3_SPEED_100) {
+                               current_speed = SPEED_100;
+                               tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+                       } else {
+                               current_speed = SPEED_10;
+                               tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
+                       }
+
+                       if (sgsr & SERDES_TG3_FULL_DUPLEX)
+                               current_duplex = DUPLEX_FULL;
+                       else
+                               current_duplex = DUPLEX_HALF;
+               }
+
+               tw32_f(MAC_MODE, tp->mac_mode);
+               udelay(40);
+
+               tg3_clear_mac_status(tp);
+
+               goto fiber_setup_done;
+       }
 
        tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
        tw32_f(MAC_MODE, tp->mac_mode);
        udelay(40);
 
-       tw32(MAC_EVENT, 0);
-
-       tw32_f(MAC_STATUS,
-            (MAC_STATUS_SYNC_CHANGED |
-             MAC_STATUS_CFG_CHANGED |
-             MAC_STATUS_MI_COMPLETION |
-             MAC_STATUS_LNKSTATE_CHANGED));
-       udelay(40);
+       tg3_clear_mac_status(tp);
 
        if (force_reset)
                tg3_phy_reset(tp);
 
-       current_link_up = 0;
-       current_speed = SPEED_UNKNOWN;
-       current_duplex = DUPLEX_UNKNOWN;
        tp->link_config.rmt_adv = 0;
 
        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -5570,7 +5790,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
 
        if (bmsr & BMSR_LSTATUS) {
                current_speed = SPEED_1000;
-               current_link_up = 1;
+               current_link_up = true;
                if (bmcr & BMCR_FULLDPLX)
                        current_duplex = DUPLEX_FULL;
                else
@@ -5597,12 +5817,13 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                        } else if (!tg3_flag(tp, 5780_CLASS)) {
                                /* Link is up via parallel detect */
                        } else {
-                               current_link_up = 0;
+                               current_link_up = false;
                        }
                }
        }
 
-       if (current_link_up == 1 && current_duplex == DUPLEX_FULL)
+fiber_setup_done:
+       if (current_link_up && current_duplex == DUPLEX_FULL)
                tg3_setup_flow_control(tp, local_adv, remote_adv);
 
        tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
@@ -5681,7 +5902,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
        }
 }
 
-static int tg3_setup_phy(struct tg3 *tp, int force_reset)
+static int tg3_setup_phy(struct tg3 *tp, bool force_reset)
 {
        u32 val;
        int err;
@@ -5771,10 +5992,13 @@ static int tg3_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
 
        info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
                                SOF_TIMESTAMPING_RX_SOFTWARE |
-                               SOF_TIMESTAMPING_SOFTWARE    |
-                               SOF_TIMESTAMPING_TX_HARDWARE |
-                               SOF_TIMESTAMPING_RX_HARDWARE |
-                               SOF_TIMESTAMPING_RAW_HARDWARE;
+                               SOF_TIMESTAMPING_SOFTWARE;
+
+       if (tg3_flag(tp, PTP_CAPABLE)) {
+               info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE |
+                                       SOF_TIMESTAMPING_RX_HARDWARE |
+                                       SOF_TIMESTAMPING_RAW_HARDWARE;
+       }
 
        if (tp->ptp_clock)
                info->phc_index = ptp_clock_index(tp->ptp_clock);
@@ -6494,7 +6718,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 
                if (desc->type_flags & RXD_FLAG_VLAN &&
                    !(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG))
-                       __vlan_hwaccel_put_tag(skb,
+                       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
                                               desc->err_vlan & RXD_VLAN_MASK);
 
                napi_gro_receive(&tnapi->napi, skb);
@@ -6582,7 +6806,7 @@ static void tg3_poll_link(struct tg3 *tp)
                                      MAC_STATUS_LNKSTATE_CHANGED));
                                udelay(40);
                        } else
-                               tg3_setup_phy(tp, 0);
+                               tg3_setup_phy(tp, false);
                        spin_unlock(&tp->lock);
                }
        }
@@ -7679,7 +7903,7 @@ static int tg3_phy_lpbk_set(struct tg3 *tp, u32 speed, bool extlpbk)
        u32 val, bmcr, mac_mode, ptest = 0;
 
        tg3_phy_toggle_apd(tp, false);
-       tg3_phy_toggle_automdix(tp, 0);
+       tg3_phy_toggle_automdix(tp, false);
 
        if (extlpbk && tg3_phy_set_extloopbk(tp))
                return -EIO;
@@ -7787,7 +8011,7 @@ static void tg3_set_loopback(struct net_device *dev, netdev_features_t features)
                spin_lock_bh(&tp->lock);
                tg3_mac_loopback(tp, false);
                /* Force link status check */
-               tg3_setup_phy(tp, 1);
+               tg3_setup_phy(tp, true);
                spin_unlock_bh(&tp->lock);
                netdev_info(dev, "Internal MAC loopback mode disabled.\n");
        }
@@ -8298,7 +8522,7 @@ err_out:
 /* To stop a block, clear the enable bit and poll till it
  * clears.  tp->lock is held.
  */
-static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int silent)
+static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, bool silent)
 {
        unsigned int i;
        u32 val;
@@ -8342,7 +8566,7 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int
 }
 
 /* tp->lock is held. */
-static int tg3_abort_hw(struct tg3 *tp, int silent)
+static int tg3_abort_hw(struct tg3 *tp, bool silent)
 {
        int i, err;
 
@@ -8702,6 +8926,9 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        /* Reprobe ASF enable state.  */
        tg3_flag_clear(tp, ENABLE_ASF);
+       tp->phy_flags &= ~(TG3_PHYFLG_1G_ON_VAUX_OK |
+                          TG3_PHYFLG_KEEP_LINK_ON_PWRDN);
+
        tg3_flag_clear(tp, ASF_NEW_HANDSHAKE);
        tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
        if (val == NIC_SRAM_DATA_SIG_MAGIC) {
@@ -8713,6 +8940,12 @@ static int tg3_chip_reset(struct tg3 *tp)
                        tp->last_event_jiffies = jiffies;
                        if (tg3_flag(tp, 5750_PLUS))
                                tg3_flag_set(tp, ASF_NEW_HANDSHAKE);
+
+                       tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &nic_cfg);
+                       if (nic_cfg & NIC_SRAM_1G_ON_VAUX_OK)
+                               tp->phy_flags |= TG3_PHYFLG_1G_ON_VAUX_OK;
+                       if (nic_cfg & NIC_SRAM_LNK_FLAP_AVOID)
+                               tp->phy_flags |= TG3_PHYFLG_KEEP_LINK_ON_PWRDN;
                }
        }
 
@@ -8723,7 +8956,7 @@ static void tg3_get_nstats(struct tg3 *, struct rtnl_link_stats64 *);
 static void tg3_get_estats(struct tg3 *, struct tg3_ethtool_stats *);
 
 /* tp->lock is held. */
-static int tg3_halt(struct tg3 *tp, int kind, int silent)
+static int tg3_halt(struct tg3 *tp, int kind, bool silent)
 {
        int err;
 
@@ -8734,7 +8967,7 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent)
        tg3_abort_hw(tp, silent);
        err = tg3_chip_reset(tp);
 
-       __tg3_set_mac_addr(tp, 0);
+       __tg3_set_mac_addr(tp, false);
 
        tg3_write_sig_legacy(tp, kind);
        tg3_write_sig_post_reset(tp, kind);
@@ -8758,7 +8991,8 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
 {
        struct tg3 *tp = netdev_priv(dev);
        struct sockaddr *addr = p;
-       int err = 0, skip_mac_1 = 0;
+       int err = 0;
+       bool skip_mac_1 = false;
 
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
@@ -8779,7 +9013,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
                /* Skip MAC addr 1 if ASF is using it. */
                if ((addr0_high != addr1_high || addr0_low != addr1_low) &&
                    !(addr1_high == 0 && addr1_low == 0))
-                       skip_mac_1 = 1;
+                       skip_mac_1 = true;
        }
        spin_lock_bh(&tp->lock);
        __tg3_set_mac_addr(tp, skip_mac_1);
@@ -9198,7 +9432,7 @@ static void tg3_rss_write_indir_tbl(struct tg3 *tp)
 }
 
 /* tp->lock is held. */
-static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
+static int tg3_reset_hw(struct tg3 *tp, bool reset_phy)
 {
        u32 val, rdmac_mode;
        int i, err, limit;
@@ -9247,6 +9481,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                       TG3_CPMU_DBTMR2_TXIDXEQ_2047US);
        }
 
+       if ((tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) &&
+           !(tp->phy_flags & TG3_PHYFLG_USER_CONFIGURED)) {
+               tg3_phy_pull_config(tp);
+               tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED;
+       }
+
        if (reset_phy)
                tg3_phy_reset(tp);
 
@@ -9585,7 +9825,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        tg3_rings_reset(tp);
 
        /* Initialize MAC address and backoff seed. */
-       __tg3_set_mac_addr(tp, 0);
+       __tg3_set_mac_addr(tp, false);
 
        /* MTU + ethernet header + FCS + optional VLAN tag */
        tw32(MAC_RX_MTU_SIZE,
@@ -10036,7 +10276,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
                        tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER;
 
-               err = tg3_setup_phy(tp, 0);
+               err = tg3_setup_phy(tp, false);
                if (err)
                        return err;
 
@@ -10116,7 +10356,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 /* Called at device open time to get the chip ready for
  * packet processing.  Invoked with tp->lock held.
  */
-static int tg3_init_hw(struct tg3 *tp, int reset_phy)
+static int tg3_init_hw(struct tg3 *tp, bool reset_phy)
 {
        tg3_switch_clocks(tp);
 
@@ -10377,7 +10617,7 @@ static void tg3_timer(unsigned long __opaque)
                                phy_event = 1;
 
                        if (phy_event)
-                               tg3_setup_phy(tp, 0);
+                               tg3_setup_phy(tp, false);
                } else if (tg3_flag(tp, POLL_SERDES)) {
                        u32 mac_stat = tr32(MAC_STATUS);
                        int need_setup = 0;
@@ -10400,7 +10640,7 @@ static void tg3_timer(unsigned long __opaque)
                                        tw32_f(MAC_MODE, tp->mac_mode);
                                        udelay(40);
                                }
-                               tg3_setup_phy(tp, 0);
+                               tg3_setup_phy(tp, false);
                        }
                } else if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
                           tg3_flag(tp, 5780_CLASS)) {
@@ -10486,7 +10726,7 @@ static void tg3_timer_stop(struct tg3 *tp)
 /* Restart hardware after configuration changes, self-test, etc.
  * Invoked with tp->lock held.
  */
-static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
+static int tg3_restart_hw(struct tg3 *tp, bool reset_phy)
        __releases(tp->lock)
        __acquires(tp->lock)
 {
@@ -10536,7 +10776,7 @@ static void tg3_reset_task(struct work_struct *work)
        }
 
        tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
-       err = tg3_init_hw(tp, 1);
+       err = tg3_init_hw(tp, true);
        if (err)
                goto out;
 
@@ -10706,7 +10946,7 @@ static int tg3_test_msi(struct tg3 *tp)
        tg3_full_lock(tp, 1);
 
        tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-       err = tg3_init_hw(tp, 1);
+       err = tg3_init_hw(tp, true);
 
        tg3_full_unlock(tp);
 
@@ -11066,7 +11306,9 @@ static int tg3_open(struct net_device *dev)
 
        tg3_full_unlock(tp);
 
-       err = tg3_start(tp, true, true, true);
+       err = tg3_start(tp,
+                       !(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN),
+                       true, true);
        if (err) {
                tg3_frob_aux_power(tp, false);
                pci_set_power_state(tp->pdev, PCI_D3hot);
@@ -11572,10 +11814,12 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                tp->link_config.duplex = cmd->duplex;
        }
 
+       tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED;
+
        tg3_warn_mgmt_link_flap(tp);
 
        if (netif_running(dev))
-               tg3_setup_phy(tp, 1);
+               tg3_setup_phy(tp, true);
 
        tg3_full_unlock(tp);
 
@@ -11731,7 +11975,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 
        if (netif_running(dev)) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-               err = tg3_restart_hw(tp, 0);
+               err = tg3_restart_hw(tp, false);
                if (!err)
                        tg3_netif_start(tp);
        }
@@ -11855,7 +12099,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
 
                if (netif_running(dev)) {
                        tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-                       err = tg3_restart_hw(tp, 0);
+                       err = tg3_restart_hw(tp, false);
                        if (!err)
                                tg3_netif_start(tp);
                }
@@ -11863,6 +12107,8 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
                tg3_full_unlock(tp);
        }
 
+       tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED;
+
        return err;
 }
 
@@ -12923,7 +13169,7 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                goto done;
        }
 
-       err = tg3_reset_hw(tp, 1);
+       err = tg3_reset_hw(tp, true);
        if (err) {
                data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
                data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
@@ -13090,7 +13336,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
                if (netif_running(dev)) {
                        tg3_flag_set(tp, INIT_COMPLETE);
-                       err2 = tg3_restart_hw(tp, 1);
+                       err2 = tg3_restart_hw(tp, true);
                        if (!err2)
                                tg3_netif_start(tp);
                }
@@ -13407,7 +13653,8 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
 static int tg3_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct tg3 *tp = netdev_priv(dev);
-       int err, reset_phy = 0;
+       int err;
+       bool reset_phy = false;
 
        if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
                return -EINVAL;
@@ -13434,7 +13681,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
         * breaks all requests to 256 bytes.
         */
        if (tg3_asic_rev(tp) == ASIC_REV_57766)
-               reset_phy = 1;
+               reset_phy = true;
 
        err = tg3_restart_hw(tp, reset_phy);
 
@@ -14458,14 +14705,18 @@ static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                    (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN))
                        tp->phy_flags |= TG3_PHYFLG_ENABLE_APD;
 
-               if (tg3_flag(tp, PCI_EXPRESS) &&
-                   tg3_asic_rev(tp) != ASIC_REV_5785 &&
-                   !tg3_flag(tp, 57765_PLUS)) {
+               if (tg3_flag(tp, PCI_EXPRESS)) {
                        u32 cfg3;
 
                        tg3_read_mem(tp, NIC_SRAM_DATA_CFG_3, &cfg3);
-                       if (cfg3 & NIC_SRAM_ASPM_DEBOUNCE)
+                       if (tg3_asic_rev(tp) != ASIC_REV_5785 &&
+                           !tg3_flag(tp, 57765_PLUS) &&
+                           (cfg3 & NIC_SRAM_ASPM_DEBOUNCE))
                                tg3_flag_set(tp, ASPM_WORKAROUND);
+                       if (cfg3 & NIC_SRAM_LNK_FLAP_AVOID)
+                               tp->phy_flags |= TG3_PHYFLG_KEEP_LINK_ON_PWRDN;
+                       if (cfg3 & NIC_SRAM_1G_ON_VAUX_OK)
+                               tp->phy_flags |= TG3_PHYFLG_1G_ON_VAUX_OK;
                }
 
                if (cfg4 & NIC_SRAM_RGMII_INBAND_DISABLE)
@@ -14619,6 +14870,12 @@ static int tg3_phy_probe(struct tg3 *tp)
                }
        }
 
+       if (!tg3_flag(tp, ENABLE_ASF) &&
+           !(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+           !(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
+               tp->phy_flags &= ~(TG3_PHYFLG_1G_ON_VAUX_OK |
+                                  TG3_PHYFLG_KEEP_LINK_ON_PWRDN);
+
        if (tg3_flag(tp, USE_PHYLIB))
                return tg3_phy_init(tp);
 
@@ -14694,7 +14951,8 @@ static int tg3_phy_probe(struct tg3 *tp)
 
        tg3_phy_init_link_config(tp);
 
-       if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+       if (!(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) &&
+           !(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
            !tg3_flag(tp, ENABLE_APE) &&
            !tg3_flag(tp, ENABLE_ASF)) {
                u32 bmsr, dummy;
@@ -16323,7 +16581,7 @@ out:
 }
 
 static int tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma,
-                          int size, int to_device)
+                          int size, bool to_device)
 {
        struct tg3_internal_buffer_desc test_desc;
        u32 sram_dma_descs;
@@ -16523,7 +16781,7 @@ static int tg3_test_dma(struct tg3 *tp)
                        p[i] = i;
 
                /* Send the buffer to the chip. */
-               ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1);
+               ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, true);
                if (ret) {
                        dev_err(&tp->pdev->dev,
                                "%s: Buffer write failed. err = %d\n",
@@ -16546,7 +16804,7 @@ static int tg3_test_dma(struct tg3 *tp)
                }
 #endif
                /* Now read it back. */
-               ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0);
+               ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, false);
                if (ret) {
                        dev_err(&tp->pdev->dev, "%s: Buffer read failed. "
                                "err = %d\n", __func__, ret);
@@ -16942,7 +17200,7 @@ static int tg3_init_one(struct pci_dev *pdev,
 
        tg3_init_bufmgr_config(tp);
 
-       features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+       features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
 
        /* 5700 B0 chips do not support checksumming correctly due
         * to hardware bugs.
@@ -17227,7 +17485,7 @@ static int tg3_suspend(struct device *device)
                tg3_full_lock(tp, 0);
 
                tg3_flag_set(tp, INIT_COMPLETE);
-               err2 = tg3_restart_hw(tp, 1);
+               err2 = tg3_restart_hw(tp, true);
                if (err2)
                        goto out;
 
@@ -17261,7 +17519,8 @@ static int tg3_resume(struct device *device)
        tg3_full_lock(tp, 0);
 
        tg3_flag_set(tp, INIT_COMPLETE);
-       err = tg3_restart_hw(tp, 1);
+       err = tg3_restart_hw(tp,
+                            !(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN));
        if (err)
                goto out;
 
@@ -17277,15 +17536,9 @@ out:
 
        return err;
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(tg3_pm_ops, tg3_suspend, tg3_resume);
-#define TG3_PM_OPS (&tg3_pm_ops)
-
-#else
-
-#define TG3_PM_OPS NULL
-
-#endif /* CONFIG_PM_SLEEP */
 
 /**
  * tg3_io_error_detected - called when PCI error is detected
@@ -17400,7 +17653,7 @@ static void tg3_io_resume(struct pci_dev *pdev)
 
        tg3_full_lock(tp, 0);
        tg3_flag_set(tp, INIT_COMPLETE);
-       err = tg3_restart_hw(tp, 1);
+       err = tg3_restart_hw(tp, true);
        if (err) {
                tg3_full_unlock(tp);
                netdev_err(netdev, "Cannot restart hardware after reset.\n");
@@ -17433,7 +17686,7 @@ static struct pci_driver tg3_driver = {
        .probe          = tg3_init_one,
        .remove         = tg3_remove_one,
        .err_handler    = &tg3_err_handler,
-       .driver.pm      = TG3_PM_OPS,
+       .driver.pm      = &tg3_pm_ops,
 };
 
 static int __init tg3_init(void)