Merge branch 'for-3.8/drivers' of git://git.kernel.dk/linux-block
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / net / ethernet / broadcom / tg3.c
index b7817cab46e98b44f3f25c75472c6876e85a6ad6..78ea90c40e1902af09272a80b09010da52ae6c6b 100644 (file)
@@ -54,6 +54,9 @@
 #include <asm/byteorder.h>
 #include <linux/uaccess.h>
 
+#include <uapi/linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
+
 #ifdef CONFIG_SPARC
 #include <asm/idprom.h>
 #include <asm/prom.h>
@@ -90,10 +93,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                    125
+#define TG3_MIN_NUM                    128
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "September 26, 2012"
+#define DRV_MODULE_RELDATE     "December 03, 2012"
 
 #define RESET_KIND_SHUTDOWN    0
 #define RESET_KIND_INIT                1
@@ -211,7 +214,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 #define FIRMWARE_TG3TSO                "tigon/tg3_tso.bin"
 #define FIRMWARE_TG3TSO5       "tigon/tg3_tso5.bin"
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
 
 MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)");
@@ -226,6 +229,9 @@ static int tg3_debug = -1;  /* -1 == use TG3_DEF_MSG_ENABLE as value */
 module_param(tg3_debug, int, 0);
 MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
 
+#define TG3_DRV_DATA_FLAG_10_100_ONLY  0x0001
+#define TG3_DRV_DATA_FLAG_5705_10_100  0x0002
+
 static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
@@ -245,20 +251,28 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+                       TG3_DRV_DATA_FLAG_5705_10_100},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+                       TG3_DRV_DATA_FLAG_5705_10_100},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+                       TG3_DRV_DATA_FLAG_5705_10_100},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
@@ -266,8 +280,13 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
+       {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5787M,
+                       PCI_VENDOR_ID_LENOVO,
+                       TG3PCI_SUBDEVICE_ID_LENOVO_5787M),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
@@ -286,9 +305,16 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)},
+       {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
+                       PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_A),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
+       {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
+                       PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_B),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717_C)},
@@ -297,8 +323,10 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)},
@@ -399,19 +427,27 @@ static const struct {
 };
 
 #define TG3_NUM_STATS  ARRAY_SIZE(ethtool_stats_keys)
+#define TG3_NVRAM_TEST         0
+#define TG3_LINK_TEST          1
+#define TG3_REGISTER_TEST      2
+#define TG3_MEMORY_TEST                3
+#define TG3_MAC_LOOPB_TEST     4
+#define TG3_PHY_LOOPB_TEST     5
+#define TG3_EXT_LOOPB_TEST     6
+#define TG3_INTERRUPT_TEST     7
 
 
 static const struct {
        const char string[ETH_GSTRING_LEN];
 } ethtool_test_keys[] = {
-       { "nvram test        (online) " },
-       { "link test         (online) " },
-       { "register test     (offline)" },
-       { "memory test       (offline)" },
-       { "mac loopback test (offline)" },
-       { "phy loopback test (offline)" },
-       { "ext loopback test (offline)" },
-       { "interrupt test    (offline)" },
+       [TG3_NVRAM_TEST]        = { "nvram test        (online) " },
+       [TG3_LINK_TEST]         = { "link test         (online) " },
+       [TG3_REGISTER_TEST]     = { "register test     (offline)" },
+       [TG3_MEMORY_TEST]       = { "memory test       (offline)" },
+       [TG3_MAC_LOOPB_TEST]    = { "mac loopback test (offline)" },
+       [TG3_PHY_LOOPB_TEST]    = { "phy loopback test (offline)" },
+       [TG3_EXT_LOOPB_TEST]    = { "ext loopback test (offline)" },
+       [TG3_INTERRUPT_TEST]    = { "interrupt test    (offline)" },
 };
 
 #define TG3_NUM_TEST   ARRAY_SIZE(ethtool_test_keys)
@@ -2448,6 +2484,18 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
        return err;
 }
 
+static void tg3_carrier_on(struct tg3 *tp)
+{
+       netif_carrier_on(tp->dev);
+       tp->link_up = true;
+}
+
+static void tg3_carrier_off(struct tg3 *tp)
+{
+       netif_carrier_off(tp->dev);
+       tp->link_up = false;
+}
+
 /* This will reset the tigon3 PHY if there is no valid
  * link unless the FORCE argument is non-zero.
  */
@@ -2466,8 +2514,8 @@ static int tg3_phy_reset(struct tg3 *tp)
        if (err != 0)
                return -EBUSY;
 
-       if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) {
-               netif_carrier_off(tp->dev);
+       if (netif_running(tp->dev) && tp->link_up) {
+               tg3_carrier_off(tp);
                tg3_link_report(tp);
        }
 
@@ -4161,6 +4209,24 @@ 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)
+{
+       if (curr_link_up != tp->link_up) {
+               if (curr_link_up) {
+                       tg3_carrier_on(tp);
+               } else {
+                       tg3_carrier_off(tp);
+                       if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+                               tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
+               }
+
+               tg3_link_report(tp);
+               return true;
+       }
+
+       return false;
+}
+
 static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
        int current_link_up;
@@ -4193,7 +4259,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
-           netif_carrier_ok(tp->dev)) {
+           tp->link_up) {
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
                    !(bmsr & BMSR_LSTATUS))
@@ -4435,13 +4501,7 @@ relink:
                                                 PCI_EXP_LNKCTL_CLKREQ_EN);
        }
 
-       if (current_link_up != netif_carrier_ok(tp->dev)) {
-               if (current_link_up)
-                       netif_carrier_on(tp->dev);
-               else
-                       netif_carrier_off(tp->dev);
-               tg3_link_report(tp);
-       }
+       tg3_test_and_report_link_chg(tp, current_link_up);
 
        return 0;
 }
@@ -5081,7 +5141,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
        orig_active_duplex = tp->link_config.active_duplex;
 
        if (!tg3_flag(tp, HW_AUTONEG) &&
-           netif_carrier_ok(tp->dev) &&
+           tp->link_up &&
            tg3_flag(tp, INIT_COMPLETE)) {
                mac_status = tr32(MAC_STATUS);
                mac_status &= (MAC_STATUS_PCS_SYNCED |
@@ -5159,13 +5219,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
                                    LED_CTRL_TRAFFIC_OVERRIDE));
        }
 
-       if (current_link_up != netif_carrier_ok(tp->dev)) {
-               if (current_link_up)
-                       netif_carrier_on(tp->dev);
-               else
-                       netif_carrier_off(tp->dev);
-               tg3_link_report(tp);
-       } else {
+       if (!tg3_test_and_report_link_chg(tp, current_link_up)) {
                u32 now_pause_cfg = tp->link_config.active_flowctrl;
                if (orig_pause_cfg != now_pause_cfg ||
                    orig_active_speed != tp->link_config.active_speed ||
@@ -5258,7 +5312,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                        new_bmcr |= BMCR_SPEED1000;
 
                        /* Force a linkdown */
-                       if (netif_carrier_ok(tp->dev)) {
+                       if (tp->link_up) {
                                u32 adv;
 
                                err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
@@ -5270,7 +5324,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                                                           BMCR_ANRESTART |
                                                           BMCR_ANENABLE);
                                udelay(10);
-                               netif_carrier_off(tp->dev);
+                               tg3_carrier_off(tp);
                        }
                        tg3_writephy(tp, MII_BMCR, new_bmcr);
                        bmcr = new_bmcr;
@@ -5336,15 +5390,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
        tp->link_config.active_speed = current_speed;
        tp->link_config.active_duplex = current_duplex;
 
-       if (current_link_up != netif_carrier_ok(tp->dev)) {
-               if (current_link_up)
-                       netif_carrier_on(tp->dev);
-               else {
-                       netif_carrier_off(tp->dev);
-                       tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
-               }
-               tg3_link_report(tp);
-       }
+       tg3_test_and_report_link_chg(tp, current_link_up);
        return err;
 }
 
@@ -5356,7 +5402,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
                return;
        }
 
-       if (!netif_carrier_ok(tp->dev) &&
+       if (!tp->link_up &&
            (tp->link_config.autoneg == AUTONEG_ENABLE)) {
                u32 bmcr;
 
@@ -5386,7 +5432,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
                                tp->phy_flags |= TG3_PHYFLG_PARALLEL_DETECT;
                        }
                }
-       } else if (netif_carrier_ok(tp->dev) &&
+       } else if (tp->link_up &&
                   (tp->link_config.autoneg == AUTONEG_ENABLE) &&
                   (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) {
                u32 phy2;
@@ -5452,7 +5498,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
                     (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
 
        if (!tg3_flag(tp, 5705_PLUS)) {
-               if (netif_carrier_ok(tp->dev)) {
+               if (tp->link_up) {
                        tw32(HOSTCC_STAT_COAL_TICKS,
                             tp->coal.stats_block_coalesce_usecs);
                } else {
@@ -5462,7 +5508,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
 
        if (tg3_flag(tp, ASPM_WORKAROUND)) {
                val = tr32(PCIE_PWR_MGMT_THRESH);
-               if (!netif_carrier_ok(tp->dev))
+               if (!tp->link_up)
                        val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) |
                              tp->pwrmgmt_thresh;
                else
@@ -5473,6 +5519,190 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
        return err;
 }
 
+/* tp->lock must be held */
+static u64 tg3_refclk_read(struct tg3 *tp)
+{
+       u64 stamp = tr32(TG3_EAV_REF_CLCK_LSB);
+       return stamp | (u64)tr32(TG3_EAV_REF_CLCK_MSB) << 32;
+}
+
+/* tp->lock must be held */
+static void tg3_refclk_write(struct tg3 *tp, u64 newval)
+{
+       tw32(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_STOP);
+       tw32(TG3_EAV_REF_CLCK_LSB, newval & 0xffffffff);
+       tw32(TG3_EAV_REF_CLCK_MSB, newval >> 32);
+       tw32_f(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_RESUME);
+}
+
+static inline void tg3_full_lock(struct tg3 *tp, int irq_sync);
+static inline void tg3_full_unlock(struct tg3 *tp);
+static int tg3_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
+{
+       struct tg3 *tp = netdev_priv(dev);
+
+       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;
+
+       if (tp->ptp_clock)
+               info->phc_index = ptp_clock_index(tp->ptp_clock);
+       else
+               info->phc_index = -1;
+
+       info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+
+       info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+                          (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
+       return 0;
+}
+
+static int tg3_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+       struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+       bool neg_adj = false;
+       u32 correction = 0;
+
+       if (ppb < 0) {
+               neg_adj = true;
+               ppb = -ppb;
+       }
+
+       /* Frequency adjustment is performed using hardware with a 24 bit
+        * accumulator and a programmable correction value. On each clk, the
+        * correction value gets added to the accumulator and when it
+        * overflows, the time counter is incremented/decremented.
+        *
+        * So conversion from ppb to correction value is
+        *              ppb * (1 << 24) / 1000000000
+        */
+       correction = div_u64((u64)ppb * (1 << 24), 1000000000ULL) &
+                    TG3_EAV_REF_CLK_CORRECT_MASK;
+
+       tg3_full_lock(tp, 0);
+
+       if (correction)
+               tw32(TG3_EAV_REF_CLK_CORRECT_CTL,
+                    TG3_EAV_REF_CLK_CORRECT_EN |
+                    (neg_adj ? TG3_EAV_REF_CLK_CORRECT_NEG : 0) | correction);
+       else
+               tw32(TG3_EAV_REF_CLK_CORRECT_CTL, 0);
+
+       tg3_full_unlock(tp);
+
+       return 0;
+}
+
+static int tg3_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+       struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+
+       tg3_full_lock(tp, 0);
+       tp->ptp_adjust += delta;
+       tg3_full_unlock(tp);
+
+       return 0;
+}
+
+static int tg3_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+       u64 ns;
+       u32 remainder;
+       struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+
+       tg3_full_lock(tp, 0);
+       ns = tg3_refclk_read(tp);
+       ns += tp->ptp_adjust;
+       tg3_full_unlock(tp);
+
+       ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+       ts->tv_nsec = remainder;
+
+       return 0;
+}
+
+static int tg3_ptp_settime(struct ptp_clock_info *ptp,
+                          const struct timespec *ts)
+{
+       u64 ns;
+       struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+
+       ns = timespec_to_ns(ts);
+
+       tg3_full_lock(tp, 0);
+       tg3_refclk_write(tp, ns);
+       tp->ptp_adjust = 0;
+       tg3_full_unlock(tp);
+
+       return 0;
+}
+
+static int tg3_ptp_enable(struct ptp_clock_info *ptp,
+                         struct ptp_clock_request *rq, int on)
+{
+       return -EOPNOTSUPP;
+}
+
+static const struct ptp_clock_info tg3_ptp_caps = {
+       .owner          = THIS_MODULE,
+       .name           = "tg3 clock",
+       .max_adj        = 250000000,
+       .n_alarm        = 0,
+       .n_ext_ts       = 0,
+       .n_per_out      = 0,
+       .pps            = 0,
+       .adjfreq        = tg3_ptp_adjfreq,
+       .adjtime        = tg3_ptp_adjtime,
+       .gettime        = tg3_ptp_gettime,
+       .settime        = tg3_ptp_settime,
+       .enable         = tg3_ptp_enable,
+};
+
+static void tg3_hwclock_to_timestamp(struct tg3 *tp, u64 hwclock,
+                                    struct skb_shared_hwtstamps *timestamp)
+{
+       memset(timestamp, 0, sizeof(struct skb_shared_hwtstamps));
+       timestamp->hwtstamp  = ns_to_ktime((hwclock & TG3_TSTAMP_MASK) +
+                                          tp->ptp_adjust);
+}
+
+/* tp->lock must be held */
+static void tg3_ptp_init(struct tg3 *tp)
+{
+       if (!tg3_flag(tp, PTP_CAPABLE))
+               return;
+
+       /* Initialize the hardware clock to the system time. */
+       tg3_refclk_write(tp, ktime_to_ns(ktime_get_real()));
+       tp->ptp_adjust = 0;
+       tp->ptp_info = tg3_ptp_caps;
+}
+
+/* tp->lock must be held */
+static void tg3_ptp_resume(struct tg3 *tp)
+{
+       if (!tg3_flag(tp, PTP_CAPABLE))
+               return;
+
+       tg3_refclk_write(tp, ktime_to_ns(ktime_get_real()) + tp->ptp_adjust);
+       tp->ptp_adjust = 0;
+}
+
+static void tg3_ptp_fini(struct tg3 *tp)
+{
+       if (!tg3_flag(tp, PTP_CAPABLE) || !tp->ptp_clock)
+               return;
+
+       ptp_clock_unregister(tp->ptp_clock);
+       tp->ptp_clock = NULL;
+       tp->ptp_adjust = 0;
+}
+
 static inline int tg3_irq_sync(struct tg3 *tp)
 {
        return tp->irq_sync;
@@ -5653,6 +5883,16 @@ static void tg3_tx(struct tg3_napi *tnapi)
                        return;
                }
 
+               if (tnapi->tx_ring[sw_idx].len_flags & TXD_FLAG_HWTSTAMP) {
+                       struct skb_shared_hwtstamps timestamp;
+                       u64 hwclock = tr32(TG3_TX_TSTAMP_LSB);
+                       hwclock |= (u64)tr32(TG3_TX_TSTAMP_MSB) << 32;
+
+                       tg3_hwclock_to_timestamp(tp, hwclock, &timestamp);
+
+                       skb_tstamp_tx(skb, &timestamp);
+               }
+
                pci_unmap_single(tp->pdev,
                                 dma_unmap_addr(ri, mapping),
                                 skb_headlen(skb),
@@ -5920,6 +6160,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                dma_addr_t dma_addr;
                u32 opaque_key, desc_idx, *post_ptr;
                u8 *data;
+               u64 tstamp = 0;
 
                desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
                opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
@@ -5954,6 +6195,14 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) -
                      ETH_FCS_LEN;
 
+               if ((desc->type_flags & RXD_FLAG_PTPSTAT_MASK) ==
+                    RXD_FLAG_PTPSTAT_PTPV1 ||
+                   (desc->type_flags & RXD_FLAG_PTPSTAT_MASK) ==
+                    RXD_FLAG_PTPSTAT_PTPV2) {
+                       tstamp = tr32(TG3_RX_TSTAMP_LSB);
+                       tstamp |= (u64)tr32(TG3_RX_TSTAMP_MSB) << 32;
+               }
+
                if (len > TG3_RX_COPY_THRESH(tp)) {
                        int skb_size;
                        unsigned int frag_size;
@@ -5997,6 +6246,10 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                }
 
                skb_put(skb, len);
+               if (tstamp)
+                       tg3_hwclock_to_timestamp(tp, tstamp,
+                                                skb_hwtstamps(skb));
+
                if ((tp->dev->features & NETIF_F_RXCSUM) &&
                    (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) &&
                    (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK)
@@ -6478,17 +6731,24 @@ static inline void tg3_netif_stop(struct tg3 *tp)
 {
        tp->dev->trans_start = jiffies; /* prevent tx timeout */
        tg3_napi_disable(tp);
+       netif_carrier_off(tp->dev);
        netif_tx_disable(tp->dev);
 }
 
+/* tp->lock must be held */
 static inline void tg3_netif_start(struct tg3 *tp)
 {
+       tg3_ptp_resume(tp);
+
        /* NOTE: unconditional netif_tx_wake_all_queues is only
         * appropriate so long as all callers are assured to
         * have free tx slots (such as after tg3_init_hw)
         */
        netif_tx_wake_all_queues(tp->dev);
 
+       if (tp->link_up)
+               netif_carrier_on(tp->dev);
+
        tg3_napi_enable(tp);
        tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
        tg3_enable_ints(tp);
@@ -7047,6 +7307,12 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                vlan = vlan_tx_tag_get(skb);
        }
 
+       if ((unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) &&
+           tg3_flag(tp, TX_TSTAMP_EN)) {
+               skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+               base_flags |= TXD_FLAG_HWTSTAMP;
+       }
+
        len = skb_headlen(skb);
 
        mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
@@ -8387,7 +8653,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
                tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
                tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
 
-               if (!netif_carrier_ok(tp->dev))
+               if (!tp->link_up)
                        val = 0;
 
                tw32(HOSTCC_STAT_COAL_TICKS, val);
@@ -8663,14 +8929,14 @@ static void tg3_rss_check_indir_tbl(struct tg3 *tp)
        if (!tg3_flag(tp, SUPPORT_MSIX))
                return;
 
-       if (tp->irq_cnt <= 2) {
+       if (tp->rxq_cnt == 1) {
                memset(&tp->rss_ind_tbl[0], 0, sizeof(tp->rss_ind_tbl));
                return;
        }
 
        /* Validate table against current IRQ count */
        for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) {
-               if (tp->rss_ind_tbl[i] >= tp->irq_cnt - 1)
+               if (tp->rss_ind_tbl[i] >= tp->rxq_cnt)
                        break;
        }
 
@@ -8915,9 +9181,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
         */
        tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
 
-       tw32(GRC_MODE,
-            tp->grc_mode |
-            (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
+       val = GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP;
+       if (tp->rxptpctl)
+               tw32(TG3_RX_PTP_CTL,
+                    tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK);
+
+       if (tg3_flag(tp, PTP_CAPABLE))
+               val |= GRC_MODE_TIME_SYNC_ENABLE;
+
+       tw32(GRC_MODE, tp->grc_mode | val);
 
        /* Setup the timer prescalar register.  Clock is always 66Mhz. */
        val = tr32(GRC_MISC_CFG);
@@ -9680,7 +9952,7 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
 {
        struct tg3_hw_stats *sp = tp->hw_stats;
 
-       if (!netif_carrier_ok(tp->dev))
+       if (!tp->link_up)
                return;
 
        TG3_STAT_ADD32(&sp->tx_octets, MAC_TX_STATS_OCTETS);
@@ -9824,11 +10096,11 @@ static void tg3_timer(unsigned long __opaque)
                        u32 mac_stat = tr32(MAC_STATUS);
                        int need_setup = 0;
 
-                       if (netif_carrier_ok(tp->dev) &&
+                       if (tp->link_up &&
                            (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)) {
                                need_setup = 1;
                        }
-                       if (!netif_carrier_ok(tp->dev) &&
+                       if (!tp->link_up &&
                            (mac_stat & (MAC_STATUS_PCS_SYNCED |
                                         MAC_STATUS_SIGNAL_DET))) {
                                need_setup = 1;
@@ -9891,7 +10163,7 @@ restart_timer:
        add_timer(&tp->timer);
 }
 
-static void __devinit tg3_timer_init(struct tg3 *tp)
+static void tg3_timer_init(struct tg3 *tp)
 {
        if (tg3_flag(tp, TAGGED_STATUS) &&
            GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
@@ -10317,7 +10589,8 @@ static void tg3_ints_fini(struct tg3 *tp)
        tg3_flag_clear(tp, ENABLE_TSS);
 }
 
-static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq)
+static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
+                    bool init)
 {
        struct net_device *dev = tp->dev;
        int i, err;
@@ -10396,6 +10669,12 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq)
        tg3_flag_set(tp, INIT_COMPLETE);
        tg3_enable_ints(tp);
 
+       if (init)
+               tg3_ptp_init(tp);
+       else
+               tg3_ptp_resume(tp);
+
+
        tg3_full_unlock(tp);
 
        netif_tx_start_all_queues(dev);
@@ -10430,10 +10709,8 @@ static void tg3_stop(struct tg3 *tp)
 {
        int i;
 
-       tg3_napi_disable(tp);
        tg3_reset_task_cancel(tp);
-
-       netif_tx_disable(tp->dev);
+       tg3_netif_stop(tp);
 
        tg3_timer_stop(tp);
 
@@ -10482,7 +10759,7 @@ static int tg3_open(struct net_device *dev)
                }
        }
 
-       netif_carrier_off(tp->dev);
+       tg3_carrier_off(tp);
 
        err = tg3_power_up(tp);
        if (err)
@@ -10495,11 +10772,19 @@ static int tg3_open(struct net_device *dev)
 
        tg3_full_unlock(tp);
 
-       err = tg3_start(tp, true, true);
+       err = tg3_start(tp, true, true, true);
        if (err) {
                tg3_frob_aux_power(tp, false);
                pci_set_power_state(tp->pdev, PCI_D3hot);
        }
+
+       if (tg3_flag(tp, PTP_CAPABLE)) {
+               tp->ptp_clock = ptp_clock_register(&tp->ptp_info,
+                                                  &tp->pdev->dev);
+               if (IS_ERR(tp->ptp_clock))
+                       tp->ptp_clock = NULL;
+       }
+
        return err;
 }
 
@@ -10507,6 +10792,8 @@ static int tg3_close(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
+       tg3_ptp_fini(tp);
+
        tg3_stop(tp);
 
        /* Clear stats across close / open calls */
@@ -10515,7 +10802,7 @@ static int tg3_close(struct net_device *dev)
 
        tg3_power_down(tp);
 
-       netif_carrier_off(tp->dev);
+       tg3_carrier_off(tp);
 
        return 0;
 }
@@ -10889,7 +11176,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                        cmd->advertising |= ADVERTISED_Asym_Pause;
                }
        }
-       if (netif_running(dev) && netif_carrier_ok(dev)) {
+       if (netif_running(dev) && tp->link_up) {
                ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
                cmd->duplex = tp->link_config.active_duplex;
                cmd->lp_advertising = tp->link_config.rmt_adv;
@@ -11407,9 +11694,9 @@ static int tg3_set_channels(struct net_device *dev,
 
        tg3_stop(tp);
 
-       netif_carrier_off(dev);
+       tg3_carrier_off(tp);
 
-       tg3_start(tp, true, false);
+       tg3_start(tp, true, false, false);
 
        return 0;
 }
@@ -11756,7 +12043,7 @@ static int tg3_test_link(struct tg3 *tp)
                max = TG3_COPPER_TIMEOUT_SEC;
 
        for (i = 0; i < max; i++) {
-               if (netif_carrier_ok(tp->dev))
+               if (tp->link_up)
                        return 0;
 
                if (msleep_interruptible(1000))
@@ -12327,19 +12614,19 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
        tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
 
        if (!netif_running(tp->dev)) {
-               data[0] = TG3_LOOPBACK_FAILED;
-               data[1] = TG3_LOOPBACK_FAILED;
+               data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
+               data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
                if (do_extlpbk)
-                       data[2] = TG3_LOOPBACK_FAILED;
+                       data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
                goto done;
        }
 
        err = tg3_reset_hw(tp, 1);
        if (err) {
-               data[0] = TG3_LOOPBACK_FAILED;
-               data[1] = TG3_LOOPBACK_FAILED;
+               data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
+               data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
                if (do_extlpbk)
-                       data[2] = TG3_LOOPBACK_FAILED;
+                       data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
                goto done;
        }
 
@@ -12362,11 +12649,11 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                tg3_mac_loopback(tp, true);
 
                if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
-                       data[0] |= TG3_STD_LOOPBACK_FAILED;
+                       data[TG3_MAC_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED;
 
                if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
                    tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
-                       data[0] |= TG3_JMB_LOOPBACK_FAILED;
+                       data[TG3_MAC_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED;
 
                tg3_mac_loopback(tp, false);
        }
@@ -12385,13 +12672,13 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                }
 
                if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
-                       data[1] |= TG3_STD_LOOPBACK_FAILED;
+                       data[TG3_PHY_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED;
                if (tg3_flag(tp, TSO_CAPABLE) &&
                    tg3_run_loopback(tp, ETH_FRAME_LEN, true))
-                       data[1] |= TG3_TSO_LOOPBACK_FAILED;
+                       data[TG3_PHY_LOOPB_TEST] |= TG3_TSO_LOOPBACK_FAILED;
                if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
                    tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
-                       data[1] |= TG3_JMB_LOOPBACK_FAILED;
+                       data[TG3_PHY_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED;
 
                if (do_extlpbk) {
                        tg3_phy_lpbk_set(tp, 0, true);
@@ -12403,13 +12690,16 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                        mdelay(40);
 
                        if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
-                               data[2] |= TG3_STD_LOOPBACK_FAILED;
+                               data[TG3_EXT_LOOPB_TEST] |=
+                                                       TG3_STD_LOOPBACK_FAILED;
                        if (tg3_flag(tp, TSO_CAPABLE) &&
                            tg3_run_loopback(tp, ETH_FRAME_LEN, true))
-                               data[2] |= TG3_TSO_LOOPBACK_FAILED;
+                               data[TG3_EXT_LOOPB_TEST] |=
+                                                       TG3_TSO_LOOPBACK_FAILED;
                        if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
                            tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
-                               data[2] |= TG3_JMB_LOOPBACK_FAILED;
+                               data[TG3_EXT_LOOPB_TEST] |=
+                                                       TG3_JMB_LOOPBACK_FAILED;
                }
 
                /* Re-enable gphy autopowerdown. */
@@ -12417,7 +12707,8 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                        tg3_phy_toggle_apd(tp, true);
        }
 
-       err = (data[0] | data[1] | data[2]) ? -EIO : 0;
+       err = (data[TG3_MAC_LOOPB_TEST] | data[TG3_PHY_LOOPB_TEST] |
+              data[TG3_EXT_LOOPB_TEST]) ? -EIO : 0;
 
 done:
        tp->phy_flags |= eee_cap;
@@ -12442,11 +12733,11 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 
        if (tg3_test_nvram(tp) != 0) {
                etest->flags |= ETH_TEST_FL_FAILED;
-               data[0] = 1;
+               data[TG3_NVRAM_TEST] = 1;
        }
        if (!doextlpbk && tg3_test_link(tp)) {
                etest->flags |= ETH_TEST_FL_FAILED;
-               data[1] = 1;
+               data[TG3_LINK_TEST] = 1;
        }
        if (etest->flags & ETH_TEST_FL_OFFLINE) {
                int err, err2 = 0, irq_sync = 0;
@@ -12458,7 +12749,6 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                }
 
                tg3_full_lock(tp, irq_sync);
-
                tg3_halt(tp, RESET_KIND_SUSPEND, 1);
                err = tg3_nvram_lock(tp);
                tg3_halt_cpu(tp, RX_CPU_BASE);
@@ -12472,25 +12762,25 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 
                if (tg3_test_registers(tp) != 0) {
                        etest->flags |= ETH_TEST_FL_FAILED;
-                       data[2] = 1;
+                       data[TG3_REGISTER_TEST] = 1;
                }
 
                if (tg3_test_memory(tp) != 0) {
                        etest->flags |= ETH_TEST_FL_FAILED;
-                       data[3] = 1;
+                       data[TG3_MEMORY_TEST] = 1;
                }
 
                if (doextlpbk)
                        etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
 
-               if (tg3_test_loopback(tp, &data[4], doextlpbk))
+               if (tg3_test_loopback(tp, data, doextlpbk))
                        etest->flags |= ETH_TEST_FL_FAILED;
 
                tg3_full_unlock(tp);
 
                if (tg3_test_interrupt(tp) != 0) {
                        etest->flags |= ETH_TEST_FL_FAILED;
-                       data[7] = 1;
+                       data[TG3_INTERRUPT_TEST] = 1;
                }
 
                tg3_full_lock(tp, 0);
@@ -12513,6 +12803,96 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 
 }
 
+static int tg3_hwtstamp_ioctl(struct net_device *dev,
+                             struct ifreq *ifr, int cmd)
+{
+       struct tg3 *tp = netdev_priv(dev);
+       struct hwtstamp_config stmpconf;
+
+       if (!tg3_flag(tp, PTP_CAPABLE))
+               return -EINVAL;
+
+       if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf)))
+               return -EFAULT;
+
+       if (stmpconf.flags)
+               return -EINVAL;
+
+       switch (stmpconf.tx_type) {
+       case HWTSTAMP_TX_ON:
+               tg3_flag_set(tp, TX_TSTAMP_EN);
+               break;
+       case HWTSTAMP_TX_OFF:
+               tg3_flag_clear(tp, TX_TSTAMP_EN);
+               break;
+       default:
+               return -ERANGE;
+       }
+
+       switch (stmpconf.rx_filter) {
+       case HWTSTAMP_FILTER_NONE:
+               tp->rxptpctl = 0;
+               break;
+       case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
+                              TG3_RX_PTP_CTL_ALL_V1_EVENTS;
+               break;
+       case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
+                              TG3_RX_PTP_CTL_SYNC_EVNT;
+               break;
+       case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
+                              TG3_RX_PTP_CTL_DELAY_REQ;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_EVENT:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
+                              TG3_RX_PTP_CTL_ALL_V2_EVENTS;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
+                              TG3_RX_PTP_CTL_ALL_V2_EVENTS;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
+                              TG3_RX_PTP_CTL_ALL_V2_EVENTS;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_SYNC:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
+                              TG3_RX_PTP_CTL_SYNC_EVNT;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
+                              TG3_RX_PTP_CTL_SYNC_EVNT;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
+                              TG3_RX_PTP_CTL_SYNC_EVNT;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
+                              TG3_RX_PTP_CTL_DELAY_REQ;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
+                              TG3_RX_PTP_CTL_DELAY_REQ;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
+                              TG3_RX_PTP_CTL_DELAY_REQ;
+               break;
+       default:
+               return -ERANGE;
+       }
+
+       if (netif_running(dev) && tp->rxptpctl)
+               tw32(TG3_RX_PTP_CTL,
+                    tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK);
+
+       return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ?
+               -EFAULT : 0;
+}
+
 static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        struct mii_ioctl_data *data = if_mii(ifr);
@@ -12563,6 +12943,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
                return err;
 
+       case SIOCSHWTSTAMP:
+               return tg3_hwtstamp_ioctl(dev, ifr, cmd);
+
        default:
                /* do nothing */
                break;
@@ -12664,7 +13047,7 @@ static const struct ethtool_ops tg3_ethtool_ops = {
        .set_rxfh_indir         = tg3_set_rxfh_indir,
        .get_channels           = tg3_get_channels,
        .set_channels           = tg3_set_channels,
-       .get_ts_info            = ethtool_op_get_ts_info,
+       .get_ts_info            = tg3_get_ts_info,
 };
 
 static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
@@ -12780,7 +13163,7 @@ static const struct net_device_ops tg3_netdev_ops = {
 #endif
 };
 
-static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
+static void tg3_get_eeprom_size(struct tg3 *tp)
 {
        u32 cursize, val, magic;
 
@@ -12814,7 +13197,7 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
        tp->nvram_size = cursize;
 }
 
-static void __devinit tg3_get_nvram_size(struct tg3 *tp)
+static void tg3_get_nvram_size(struct tg3 *tp)
 {
        u32 val;
 
@@ -12847,7 +13230,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp)
        tp->nvram_size = TG3_NVRAM_SIZE_512KB;
 }
 
-static void __devinit tg3_get_nvram_info(struct tg3 *tp)
+static void tg3_get_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -12898,7 +13281,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
+static void tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
 {
        switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
        case FLASH_5752PAGE_SIZE_256:
@@ -12925,7 +13308,7 @@ static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
        }
 }
 
-static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
+static void tg3_get_5752_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -12966,7 +13349,7 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
+static void tg3_get_5755_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1, protect = 0;
 
@@ -13022,7 +13405,7 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
+static void tg3_get_5787_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -13060,7 +13443,7 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
+static void tg3_get_5761_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1, protect = 0;
 
@@ -13135,14 +13518,14 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
+static void tg3_get_5906_nvram_info(struct tg3 *tp)
 {
        tp->nvram_jedecnum = JEDEC_ATMEL;
        tg3_flag_set(tp, NVRAM_BUFFERED);
        tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
 }
 
-static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
+static void tg3_get_57780_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -13215,7 +13598,7 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
 }
 
 
-static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
+static void tg3_get_5717_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -13293,7 +13676,7 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
                tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
 }
 
-static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
+static void tg3_get_5720_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1, nvmpinstrp;
 
@@ -13406,7 +13789,7 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
 }
 
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
-static void __devinit tg3_nvram_init(struct tg3 *tp)
+static void tg3_nvram_init(struct tg3 *tp)
 {
        tw32_f(GRC_EEPROM_ADDR,
             (EEPROM_ADDR_FSM_RESET |
@@ -13476,7 +13859,7 @@ struct subsys_tbl_ent {
        u32 phy_id;
 };
 
-static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = {
+static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
        /* Broadcom boards. */
        { TG3PCI_SUBVENDOR_ID_BROADCOM,
          TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 },
@@ -13540,7 +13923,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = {
          TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 }
 };
 
-static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
+static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp)
 {
        int i;
 
@@ -13554,7 +13937,7 @@ static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
        return NULL;
 }
 
-static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
+static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 {
        u32 val;
 
@@ -13754,7 +14137,7 @@ done:
                device_set_wakeup_capable(&tp->pdev->dev, false);
 }
 
-static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
 {
        int i;
        u32 val;
@@ -13777,7 +14160,7 @@ static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
  * configuration is a 32-bit value that straddles the alignment boundary.
  * We do two 32-bit reads and then shift and merge the results.
  */
-static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
+static u32 tg3_read_otp_phycfg(struct tg3 *tp)
 {
        u32 bhalf_otp, thalf_otp;
 
@@ -13803,7 +14186,7 @@ static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
        return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
 }
 
-static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
+static void tg3_phy_init_link_config(struct tg3 *tp)
 {
        u32 adv = ADVERTISED_Autoneg;
 
@@ -13830,7 +14213,7 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
        tp->old_link = -1;
 }
 
-static int __devinit tg3_phy_probe(struct tg3 *tp)
+static int tg3_phy_probe(struct tg3 *tp)
 {
        u32 hw_phy_id_1, hw_phy_id_2;
        u32 hw_phy_id, hw_phy_id_masked;
@@ -13958,7 +14341,7 @@ skip_phy_reset:
        return err;
 }
 
-static void __devinit tg3_read_vpd(struct tg3 *tp)
+static void tg3_read_vpd(struct tg3 *tp)
 {
        u8 *vpd_data;
        unsigned int block_end, rosize, len;
@@ -14079,7 +14462,7 @@ nomatch:
        }
 }
 
-static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
+static int tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
 {
        u32 val;
 
@@ -14092,7 +14475,7 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
        return 1;
 }
 
-static void __devinit tg3_read_bc_ver(struct tg3 *tp)
+static void tg3_read_bc_ver(struct tg3 *tp)
 {
        u32 val, offset, start, ver_offset;
        int i, dst_off;
@@ -14144,7 +14527,7 @@ static void __devinit tg3_read_bc_ver(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_read_hwsb_ver(struct tg3 *tp)
+static void tg3_read_hwsb_ver(struct tg3 *tp)
 {
        u32 val, major, minor;
 
@@ -14160,7 +14543,7 @@ static void __devinit tg3_read_hwsb_ver(struct tg3 *tp)
        snprintf(&tp->fw_ver[0], 32, "sb v%d.%02d", major, minor);
 }
 
-static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
+static void tg3_read_sb_ver(struct tg3 *tp, u32 val)
 {
        u32 offset, major, minor, build;
 
@@ -14215,7 +14598,7 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
        }
 }
 
-static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp)
+static void tg3_read_mgmtfw_ver(struct tg3 *tp)
 {
        u32 val, offset, start;
        int i, vlen;
@@ -14267,7 +14650,7 @@ static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_probe_ncsi(struct tg3 *tp)
+static void tg3_probe_ncsi(struct tg3 *tp)
 {
        u32 apedata;
 
@@ -14283,7 +14666,7 @@ static void __devinit tg3_probe_ncsi(struct tg3 *tp)
                tg3_flag_set(tp, APE_HAS_NCSI);
 }
 
-static void __devinit tg3_read_dash_ver(struct tg3 *tp)
+static void tg3_read_dash_ver(struct tg3 *tp)
 {
        int vlen;
        u32 apedata;
@@ -14306,7 +14689,7 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp)
                 (apedata & APE_FW_VERSION_BLDMSK));
 }
 
-static void __devinit tg3_read_fw_ver(struct tg3 *tp)
+static void tg3_read_fw_ver(struct tg3 *tp)
 {
        u32 val;
        bool vpd_vers = false;
@@ -14359,7 +14742,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
        { },
 };
 
-static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
+static struct pci_dev *tg3_find_peer(struct tg3 *tp)
 {
        struct pci_dev *peer;
        unsigned int func, devnr = tp->pdev->devfn & ~7;
@@ -14387,7 +14770,7 @@ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
        return peer;
 }
 
-static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
+static void tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
 {
        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) {
@@ -14468,7 +14851,29 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
                tg3_flag_set(tp, 5705_PLUS);
 }
 
-static int __devinit tg3_get_invariants(struct tg3 *tp)
+static bool tg3_10_100_only_device(struct tg3 *tp,
+                                  const struct pci_device_id *ent)
+{
+       u32 grc_misc_cfg = tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK;
+
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+           (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
+           (tp->phy_flags & TG3_PHYFLG_IS_FET))
+               return true;
+
+       if (ent->driver_data & TG3_DRV_DATA_FLAG_10_100_ONLY) {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+                       if (ent->driver_data & TG3_DRV_DATA_FLAG_5705_10_100)
+                               return true;
+               } else {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
 {
        u32 misc_ctrl_reg;
        u32 pci_state_reg, grc_misc_cfg;
@@ -15147,22 +15552,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        else
                tp->mac_mode = 0;
 
-       /* these are limited to 10/100 only */
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
-            (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
-            tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
-            (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
-           (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
-            (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
-           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 ||
-           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
-           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 ||
-           (tp->phy_flags & TG3_PHYFLG_IS_FET))
+       if (tg3_10_100_only_device(tp, ent))
                tp->phy_flags |= TG3_PHYFLG_10_100_ONLY;
 
        err = tg3_phy_probe(tp);
@@ -15242,7 +15632,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 }
 
 #ifdef CONFIG_SPARC
-static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
+static int tg3_get_macaddr_sparc(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
        struct pci_dev *pdev = tp->pdev;
@@ -15259,7 +15649,7 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
        return -ENODEV;
 }
 
-static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
+static int tg3_get_default_macaddr_sparc(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
 
@@ -15269,7 +15659,7 @@ static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
 }
 #endif
 
-static int __devinit tg3_get_device_address(struct tg3 *tp)
+static int tg3_get_device_address(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
        u32 hi, lo, mac_offset;
@@ -15348,7 +15738,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 #define BOUNDARY_SINGLE_CACHELINE      1
 #define BOUNDARY_MULTI_CACHELINE       2
 
-static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+static u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
 {
        int cacheline_size;
        u8 byte;
@@ -15489,7 +15879,8 @@ out:
        return val;
 }
 
-static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device)
+static int tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma,
+                          int size, int to_device)
 {
        struct tg3_internal_buffer_desc test_desc;
        u32 sram_dma_descs;
@@ -15576,7 +15967,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = {
        { },
 };
 
-static int __devinit tg3_test_dma(struct tg3 *tp)
+static int tg3_test_dma(struct tg3 *tp)
 {
        dma_addr_t buf_dma;
        u32 *buf, saved_dma_rwctrl;
@@ -15766,7 +16157,7 @@ out_nofree:
        return ret;
 }
 
-static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
+static void tg3_init_bufmgr_config(struct tg3 *tp)
 {
        if (tg3_flag(tp, 57765_PLUS)) {
                tp->bufmgr_config.mbuf_read_dma_low_water =
@@ -15822,7 +16213,7 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
        tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER;
 }
 
-static char * __devinit tg3_phy_string(struct tg3 *tp)
+static char *tg3_phy_string(struct tg3 *tp)
 {
        switch (tp->phy_id & TG3_PHY_ID_MASK) {
        case TG3_PHY_ID_BCM5400:        return "5400";
@@ -15853,7 +16244,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        }
 }
 
-static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
+static char *tg3_bus_string(struct tg3 *tp, char *str)
 {
        if (tg3_flag(tp, PCI_EXPRESS)) {
                strcpy(str, "PCI Express");
@@ -15889,7 +16280,7 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
        return str;
 }
 
-static void __devinit tg3_init_coal(struct tg3 *tp)
+static void tg3_init_coal(struct tg3 *tp)
 {
        struct ethtool_coalesce *ec = &tp->coal;
 
@@ -15920,7 +16311,7 @@ static void __devinit tg3_init_coal(struct tg3 *tp)
        }
 }
 
-static int __devinit tg3_init_one(struct pci_dev *pdev,
+static int tg3_init_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
        struct net_device *dev;
@@ -16041,7 +16432,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        dev->netdev_ops = &tg3_netdev_ops;
        dev->irq = pdev->irq;
 
-       err = tg3_get_invariants(tp);
+       err = tg3_get_invariants(tp, ent);
        if (err) {
                dev_err(&pdev->dev,
                        "Problem fetching invariants of chip, aborting\n");
@@ -16216,6 +16607,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        pci_set_drvdata(pdev, dev);
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               tg3_flag_set(tp, PTP_CAPABLE);
+
        if (tg3_flag(tp, 5717_PLUS)) {
                /* Resume a low-power mode */
                tg3_frob_aux_power(tp, false);
@@ -16300,7 +16695,7 @@ err_out_disable_pdev:
        return err;
 }
 
-static void __devexit tg3_remove_one(struct pci_dev *pdev)
+static void tg3_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -16541,8 +16936,8 @@ 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);
-       tg3_full_unlock(tp);
        if (err) {
+               tg3_full_unlock(tp);
                netdev_err(netdev, "Cannot restart hardware after reset.\n");
                goto done;
        }
@@ -16553,6 +16948,8 @@ static void tg3_io_resume(struct pci_dev *pdev)
 
        tg3_netif_start(tp);
 
+       tg3_full_unlock(tp);
+
        tg3_phy_start(tp);
 
 done:
@@ -16569,7 +16966,7 @@ static struct pci_driver tg3_driver = {
        .name           = DRV_MODULE_NAME,
        .id_table       = tg3_pci_tbl,
        .probe          = tg3_init_one,
-       .remove         = __devexit_p(tg3_remove_one),
+       .remove         = tg3_remove_one,
        .err_handler    = &tg3_err_handler,
        .driver.pm      = TG3_PM_OPS,
 };