remove extra parentheses in return statement
[dpdk.git] / drivers / net / ixgbe / ixgbe_ethdev.c
index 19ddb52..3e6fe86 100644 (file)
 #define IXGBE_HKEY_MAX_INDEX 10
 
 /* Additional timesync values. */
-#define IXGBE_TIMINCA_16NS_SHIFT 24
-#define IXGBE_TIMINCA_INCVALUE   16000000
-#define IXGBE_TIMINCA_INIT       ((0x02 << IXGBE_TIMINCA_16NS_SHIFT) \
-                                 | IXGBE_TIMINCA_INCVALUE)
+#define NSEC_PER_SEC             1000000000L
+#define IXGBE_INCVAL_10GB        0x66666666
+#define IXGBE_INCVAL_1GB         0x40000000
+#define IXGBE_INCVAL_100         0x50000000
+#define IXGBE_INCVAL_SHIFT_10GB  28
+#define IXGBE_INCVAL_SHIFT_1GB   24
+#define IXGBE_INCVAL_SHIFT_100   21
+#define IXGBE_INCVAL_SHIFT_82599 7
+#define IXGBE_INCPER_SHIFT_82599 24
+
+#define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -325,6 +332,11 @@ static int ixgbe_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
                                            uint32_t flags);
 static int ixgbe_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
                                            struct timespec *timestamp);
+static int ixgbe_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta);
+static int ixgbe_timesync_read_time(struct rte_eth_dev *dev,
+                                  struct timespec *timestamp);
+static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
+                                  const struct timespec *timestamp);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -480,6 +492,9 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
        .get_eeprom           = ixgbe_get_eeprom,
        .set_eeprom           = ixgbe_set_eeprom,
        .get_dcb_info         = ixgbe_dev_get_dcb_info,
+       .timesync_adjust_time = ixgbe_timesync_adjust_time,
+       .timesync_read_time   = ixgbe_timesync_read_time,
+       .timesync_write_time  = ixgbe_timesync_write_time,
 };
 
 /*
@@ -1308,7 +1323,7 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
         */
        if ((diag != IXGBE_SUCCESS) && (diag != IXGBE_ERR_INVALID_MAC_ADDR)) {
                PMD_INIT_LOG(ERR, "VF Initialization Failure: %d", diag);
-               return (diag);
+               return diag;
        }
 
        /* negotiate mailbox API version to use with the PF. */
@@ -1359,7 +1374,7 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
 
                default:
                        PMD_INIT_LOG(ERR, "VF Initialization Failure: %d", diag);
-                       return (-EIO);
+                       return -EIO;
        }
 
        PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x mac.type=%s",
@@ -1463,7 +1478,7 @@ rte_ixgbevf_pmd_init(const char *name __rte_unused, const char *param __rte_unus
        PMD_INIT_FUNC_TRACE();
 
        rte_eth_driver_register(&rte_ixgbevf_pmd);
-       return (0);
+       return 0;
 }
 
 static int
@@ -1976,6 +1991,9 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
                return -EINVAL;
        }
 
+       /* disable uio/vfio intr/eventfd mapping */
+       rte_intr_disable(intr_handle);
+
        /* stop adapter */
        hw->adapter_stopped = 0;
        ixgbe_stop_adapter(hw);
@@ -2144,7 +2162,7 @@ skip_link_setup:
 
        ixgbe_restore_statistics_mapping(dev);
 
-       return (0);
+       return 0;
 
 error:
        PMD_INIT_LOG(ERR, "failure in ixgbe_dev_start(): %d", err);
@@ -2316,13 +2334,20 @@ ixgbe_dev_close(struct rte_eth_dev *dev)
 }
 
 static void
-ixgbe_read_stats_registers(struct ixgbe_hw *hw, struct ixgbe_hw_stats
-                                                  *hw_stats, uint64_t *total_missed_rx,
-                                                  uint64_t *total_qbrc, uint64_t *total_qprc,
-                                                  uint64_t *total_qprdc)
+ixgbe_read_stats_registers(struct ixgbe_hw *hw,
+                          struct ixgbe_hw_stats *hw_stats,
+                          uint64_t *total_missed_rx, uint64_t *total_qbrc,
+                          uint64_t *total_qprc, uint64_t *total_qprdc)
 {
        uint32_t bprc, lxon, lxoff, total;
+       uint32_t delta_gprc = 0;
        unsigned i;
+       /* Workaround for RX byte count not including CRC bytes when CRC
++       * strip is enabled. CRC bytes are removed from counters when crc_strip
+        * is disabled.
++       */
+       int crc_strip = (IXGBE_READ_REG(hw, IXGBE_HLREG0) &
+                       IXGBE_HLREG0_RXCRCSTRP);
 
        hw_stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
        hw_stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC);
@@ -2357,16 +2382,27 @@ ixgbe_read_stats_registers(struct ixgbe_hw *hw, struct ixgbe_hw_stats
                    IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
        }
        for (i = 0; i < IXGBE_QUEUE_STAT_COUNTERS; i++) {
-               hw_stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
-               hw_stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+               uint32_t delta_qprc = IXGBE_READ_REG(hw, IXGBE_QPRC(i));
+               uint32_t delta_qptc = IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+               uint32_t delta_qprdc = IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+
+               delta_gprc += delta_qprc;
+
+               hw_stats->qprc[i] += delta_qprc;
+               hw_stats->qptc[i] += delta_qptc;
+
                hw_stats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
                hw_stats->qbrc[i] +=
                    ((uint64_t)IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)) << 32);
+               if (crc_strip == 0)
+                       hw_stats->qbrc[i] -= delta_qprc * ETHER_CRC_LEN;
+
                hw_stats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
                hw_stats->qbtc[i] +=
                    ((uint64_t)IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)) << 32);
-               *total_qprdc += hw_stats->qprdc[i] +=
-                               IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+
+               hw_stats->qprdc[i] += delta_qprdc;
+               *total_qprdc += hw_stats->qprdc[i];
 
                *total_qprc += hw_stats->qprc[i];
                *total_qbrc += hw_stats->qbrc[i];
@@ -2375,8 +2411,11 @@ ixgbe_read_stats_registers(struct ixgbe_hw *hw, struct ixgbe_hw_stats
        hw_stats->mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC);
        hw_stats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
 
-       /* Note that gprc counts missed packets */
-       hw_stats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
+       /*
+        * An errata states that gprc actually counts good + missed packets:
+        * Workaround to set gprc to summated queue packet receives
+        */
+       hw_stats->gprc = *total_qprc;
 
        if (hw->mac.type != ixgbe_mac_82598EB) {
                hw_stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
@@ -2395,6 +2434,18 @@ ixgbe_read_stats_registers(struct ixgbe_hw *hw, struct ixgbe_hw_stats
                hw_stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
                hw_stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH);
        }
+       uint64_t old_tpr = hw_stats->tpr;
+
+       hw_stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
+       hw_stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT);
+
+       if (crc_strip == 0)
+               hw_stats->gorc -= delta_gprc * ETHER_CRC_LEN;
+
+       uint64_t delta_gptc = IXGBE_READ_REG(hw, IXGBE_GPTC);
+       hw_stats->gptc += delta_gptc;
+       hw_stats->gotc -= delta_gptc * ETHER_CRC_LEN;
+       hw_stats->tor -= (hw_stats->tpr - old_tpr) * ETHER_CRC_LEN;
 
        /*
         * Workaround: mprc hardware is incorrectly counting
@@ -2419,7 +2470,6 @@ ixgbe_read_stats_registers(struct ixgbe_hw *hw, struct ixgbe_hw_stats
        hw_stats->lxofftxc += lxoff;
        total = lxon + lxoff;
 
-       hw_stats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
        hw_stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
        hw_stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
        hw_stats->gptc -= total;
@@ -2434,8 +2484,6 @@ ixgbe_read_stats_registers(struct ixgbe_hw *hw, struct ixgbe_hw_stats
        hw_stats->mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC);
        hw_stats->mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC);
        hw_stats->mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC);
-       hw_stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
-       hw_stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT);
        hw_stats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
        hw_stats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
        hw_stats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
@@ -2498,6 +2546,7 @@ ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        }
 
        /* Rx Errors */
+       stats->imissed  = total_missed_rx;
        stats->ierrors  = hw_stats->crcerrs +
                          hw_stats->mspdc +
                          hw_stats->rlec +
@@ -3199,7 +3248,7 @@ ixgbe_dev_led_on(struct rte_eth_dev *dev)
        struct ixgbe_hw *hw;
 
        hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       return (ixgbe_led_on(hw, 0) == IXGBE_SUCCESS ? 0 : -ENOTSUP);
+       return ixgbe_led_on(hw, 0) == IXGBE_SUCCESS ? 0 : -ENOTSUP;
 }
 
 static int
@@ -3208,7 +3257,7 @@ ixgbe_dev_led_off(struct rte_eth_dev *dev)
        struct ixgbe_hw *hw;
 
        hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       return (ixgbe_led_off(hw, 0) == IXGBE_SUCCESS ? 0 : -ENOTSUP);
+       return ixgbe_led_off(hw, 0) == IXGBE_SUCCESS ? 0 : -ENOTSUP;
 }
 
 static int
@@ -3290,7 +3339,7 @@ ixgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
                (fc_conf->high_water < fc_conf->low_water)) {
                PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB");
                PMD_INIT_LOG(ERR, "High_water must <= 0x%x", max_high_water);
-               return (-EINVAL);
+               return -EINVAL;
        }
 
        hw->fc.requested_mode = rte_fcmode_2_ixgbe_fcmode[fc_conf->mode];
@@ -3512,7 +3561,7 @@ ixgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *p
            (pfc_conf->fc.high_water <= pfc_conf->fc.low_water)) {
                PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB");
                PMD_INIT_LOG(ERR, "High_water must <= 0x%x", max_high_water);
-               return (-EINVAL);
+               return -EINVAL;
        }
 
        hw->fc.requested_mode = rte_fcmode_2_ixgbe_fcmode[pfc_conf->fc.mode];
@@ -3977,7 +4026,7 @@ ixgbe_vmdq_mode_check(struct ixgbe_hw *hw)
        reg_val = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
        if (!(reg_val & IXGBE_VT_CTL_VT_ENABLE)) {
                PMD_INIT_LOG(ERR, "VMDq must be enabled for this setting");
-               return (-1);
+               return -1;
        }
 
        return 0;
@@ -4034,7 +4083,7 @@ ixgbe_uc_hash_table_set(struct rte_eth_dev *dev,struct ether_addr* mac_addr,
 
        /* The UTA table only exists on 82599 hardware and newer */
        if (hw->mac.type < ixgbe_mac_82599EB)
-               return (-ENOTSUP);
+               return -ENOTSUP;
 
        vector = ixgbe_uta_vector(hw,mac_addr);
        uta_idx = (vector >> ixgbe_uta_bit_shift) & ixgbe_uta_idx_mask;
@@ -4077,7 +4126,7 @@ ixgbe_uc_all_hash_table_set(struct rte_eth_dev *dev, uint8_t on)
 
        /* The UTA table only exists on 82599 hardware and newer */
        if (hw->mac.type < ixgbe_mac_82599EB)
-               return (-ENOTSUP);
+               return -ENOTSUP;
 
        if(on) {
                for (i = 0; i < ETH_VMDQ_NUM_UC_HASH_ARRAY; i++) {
@@ -4126,10 +4175,10 @@ ixgbe_set_pool_rx_mode(struct rte_eth_dev *dev, uint16_t pool,
        if (hw->mac.type == ixgbe_mac_82598EB) {
                PMD_INIT_LOG(ERR, "setting VF receive mode set should be done"
                             " on 82599 hardware and newer");
-               return (-ENOTSUP);
+               return -ENOTSUP;
        }
        if (ixgbe_vmdq_mode_check(hw) < 0)
-               return (-ENOTSUP);
+               return -ENOTSUP;
 
        val = ixgbe_convert_vm_rx_mask_to_val(rx_mask, val);
 
@@ -4154,7 +4203,7 @@ ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
        if (ixgbe_vmdq_mode_check(hw) < 0)
-               return (-ENOTSUP);
+               return -ENOTSUP;
 
        addr = IXGBE_VFRE(pool >= ETH_64_POOLS/2);
        reg = IXGBE_READ_REG(hw, addr);
@@ -4181,7 +4230,7 @@ ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on)
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
        if (ixgbe_vmdq_mode_check(hw) < 0)
-               return (-ENOTSUP);
+               return -ENOTSUP;
 
        addr = IXGBE_VFTE(pool >= ETH_64_POOLS/2);
        reg = IXGBE_READ_REG(hw, addr);
@@ -4207,7 +4256,7 @@ ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan,
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
        if (ixgbe_vmdq_mode_check(hw) < 0)
-               return (-ENOTSUP);
+               return -ENOTSUP;
        for (pool_idx = 0; pool_idx < ETH_64_POOLS; pool_idx++) {
                if (pool_mask & ((uint64_t)(1ULL << pool_idx)))
                        ret = hw->mac.ops.set_vfta(hw,vlan,pool_idx,vlan_on);
@@ -4373,7 +4422,7 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id)
                (IXGBE_DEV_PRIVATE_TO_PFDATA(dev->data->dev_private));
 
        if (ixgbe_vmdq_mode_check(hw) < 0)
-               return (-ENOTSUP);
+               return -ENOTSUP;
 
        memset(&mr_info->mr_conf[rule_id], 0,
                sizeof(struct rte_eth_mirror_conf));
@@ -5582,6 +5631,186 @@ ixgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,
                                         ixgbe_dev_addr_list_itr, TRUE);
 }
 
+static uint64_t
+ixgbe_read_systime_cyclecounter(struct rte_eth_dev *dev)
+{
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint64_t systime_cycles;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_X550:
+               /* SYSTIMEL stores ns and SYSTIMEH stores seconds. */
+               systime_cycles = (uint64_t)IXGBE_READ_REG(hw, IXGBE_SYSTIML);
+               systime_cycles += (uint64_t)IXGBE_READ_REG(hw, IXGBE_SYSTIMH)
+                               * NSEC_PER_SEC;
+               break;
+       default:
+               systime_cycles = (uint64_t)IXGBE_READ_REG(hw, IXGBE_SYSTIML);
+               systime_cycles |= (uint64_t)IXGBE_READ_REG(hw, IXGBE_SYSTIMH)
+                               << 32;
+       }
+
+       return systime_cycles;
+}
+
+static uint64_t
+ixgbe_read_rx_tstamp_cyclecounter(struct rte_eth_dev *dev)
+{
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint64_t rx_tstamp_cycles;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_X550:
+               /* RXSTMPL stores ns and RXSTMPH stores seconds. */
+               rx_tstamp_cycles = (uint64_t)IXGBE_READ_REG(hw, IXGBE_RXSTMPL);
+               rx_tstamp_cycles += (uint64_t)IXGBE_READ_REG(hw, IXGBE_RXSTMPH)
+                               * NSEC_PER_SEC;
+               break;
+       default:
+               /* RXSTMPL stores ns and RXSTMPH stores seconds. */
+               rx_tstamp_cycles = (uint64_t)IXGBE_READ_REG(hw, IXGBE_RXSTMPL);
+               rx_tstamp_cycles |= (uint64_t)IXGBE_READ_REG(hw, IXGBE_RXSTMPH)
+                               << 32;
+       }
+
+       return rx_tstamp_cycles;
+}
+
+static uint64_t
+ixgbe_read_tx_tstamp_cyclecounter(struct rte_eth_dev *dev)
+{
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint64_t tx_tstamp_cycles;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_X550:
+               /* TXSTMPL stores ns and TXSTMPH stores seconds. */
+               tx_tstamp_cycles = (uint64_t)IXGBE_READ_REG(hw, IXGBE_TXSTMPL);
+               tx_tstamp_cycles += (uint64_t)IXGBE_READ_REG(hw, IXGBE_TXSTMPH)
+                               * NSEC_PER_SEC;
+               break;
+       default:
+               /* TXSTMPL stores ns and TXSTMPH stores seconds. */
+               tx_tstamp_cycles = (uint64_t)IXGBE_READ_REG(hw, IXGBE_TXSTMPL);
+               tx_tstamp_cycles |= (uint64_t)IXGBE_READ_REG(hw, IXGBE_TXSTMPH)
+                               << 32;
+       }
+
+       return tx_tstamp_cycles;
+}
+
+static void
+ixgbe_start_timecounters(struct rte_eth_dev *dev)
+{
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct ixgbe_adapter *adapter =
+               (struct ixgbe_adapter *)dev->data->dev_private;
+       struct rte_eth_link link;
+       uint32_t incval = 0;
+       uint32_t shift = 0;
+
+       /* Get current link speed. */
+       memset(&link, 0, sizeof(link));
+       ixgbe_dev_link_update(dev, 1);
+       rte_ixgbe_dev_atomic_read_link_status(dev, &link);
+
+       switch (link.link_speed) {
+       case ETH_LINK_SPEED_100:
+               incval = IXGBE_INCVAL_100;
+               shift = IXGBE_INCVAL_SHIFT_100;
+               break;
+       case ETH_LINK_SPEED_1000:
+               incval = IXGBE_INCVAL_1GB;
+               shift = IXGBE_INCVAL_SHIFT_1GB;
+               break;
+       case ETH_LINK_SPEED_10000:
+       default:
+               incval = IXGBE_INCVAL_10GB;
+               shift = IXGBE_INCVAL_SHIFT_10GB;
+               break;
+       }
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_X550:
+               /* Independent of link speed. */
+               incval = 1;
+               /* Cycles read will be interpreted as ns. */
+               shift = 0;
+               /* Fall-through */
+       case ixgbe_mac_X540:
+               IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, incval);
+               break;
+       case ixgbe_mac_82599EB:
+               incval >>= IXGBE_INCVAL_SHIFT_82599;
+               shift -= IXGBE_INCVAL_SHIFT_82599;
+               IXGBE_WRITE_REG(hw, IXGBE_TIMINCA,
+                               (1 << IXGBE_INCPER_SHIFT_82599) | incval);
+               break;
+       default:
+               /* Not supported. */
+               return;
+       }
+
+       memset(&adapter->systime_tc, 0, sizeof(struct rte_timecounter));
+       memset(&adapter->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+       memset(&adapter->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+
+       adapter->systime_tc.cc_mask = IXGBE_CYCLECOUNTER_MASK;
+       adapter->systime_tc.cc_shift = shift;
+       adapter->systime_tc.nsec_mask = (1ULL << shift) - 1;
+
+       adapter->rx_tstamp_tc.cc_mask = IXGBE_CYCLECOUNTER_MASK;
+       adapter->rx_tstamp_tc.cc_shift = shift;
+       adapter->rx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
+
+       adapter->tx_tstamp_tc.cc_mask = IXGBE_CYCLECOUNTER_MASK;
+       adapter->tx_tstamp_tc.cc_shift = shift;
+       adapter->tx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
+}
+
+static int
+ixgbe_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
+{
+       struct ixgbe_adapter *adapter =
+                       (struct ixgbe_adapter *)dev->data->dev_private;
+
+       adapter->systime_tc.nsec += delta;
+       adapter->rx_tstamp_tc.nsec += delta;
+       adapter->tx_tstamp_tc.nsec += delta;
+
+       return 0;
+}
+
+static int
+ixgbe_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
+{
+       uint64_t ns;
+       struct ixgbe_adapter *adapter =
+                       (struct ixgbe_adapter *)dev->data->dev_private;
+
+       ns = rte_timespec_to_ns(ts);
+       /* Set the timecounters to a new value. */
+       adapter->systime_tc.nsec = ns;
+       adapter->rx_tstamp_tc.nsec = ns;
+       adapter->tx_tstamp_tc.nsec = ns;
+
+       return 0;
+}
+
+static int
+ixgbe_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
+{
+       uint64_t ns, systime_cycles;
+       struct ixgbe_adapter *adapter =
+                       (struct ixgbe_adapter *)dev->data->dev_private;
+
+       systime_cycles = ixgbe_read_systime_cyclecounter(dev);
+       ns = rte_timecounter_update(&adapter->systime_tc, systime_cycles);
+       *ts = rte_ns_to_timespec(ns);
+
+       return 0;
+}
+
 static int
 ixgbe_timesync_enable(struct rte_eth_dev *dev)
 {
@@ -5589,13 +5818,18 @@ ixgbe_timesync_enable(struct rte_eth_dev *dev)
        uint32_t tsync_ctl;
        uint32_t tsauxc;
 
+       /* Stop the timesync system time. */
+       IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, 0x0);
+       /* Reset the timesync system time value. */
+       IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x0);
+       IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x0);
+
        /* Enable system time for platforms where it isn't on by default. */
        tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC);
        tsauxc &= ~IXGBE_TSAUXC_DISABLE_SYSTIME;
        IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc);
 
-       /* Start incrementing the register used to timestamp PTP packets. */
-       IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, IXGBE_TIMINCA_INIT);
+       ixgbe_start_timecounters(dev);
 
        /* Enable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */
        IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588),
@@ -5613,6 +5847,8 @@ ixgbe_timesync_enable(struct rte_eth_dev *dev)
        tsync_ctl |= IXGBE_TSYNCTXCTL_ENABLED;
        IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, tsync_ctl);
 
+       IXGBE_WRITE_FLUSH(hw);
+
        return 0;
 }
 
@@ -5647,19 +5883,19 @@ ixgbe_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
                                 uint32_t flags __rte_unused)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct ixgbe_adapter *adapter =
+               (struct ixgbe_adapter *)dev->data->dev_private;
        uint32_t tsync_rxctl;
-       uint32_t rx_stmpl;
-       uint32_t rx_stmph;
+       uint64_t rx_tstamp_cycles;
+       uint64_t ns;
 
        tsync_rxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL);
        if ((tsync_rxctl & IXGBE_TSYNCRXCTL_VALID) == 0)
                return -EINVAL;
 
-       rx_stmpl = IXGBE_READ_REG(hw, IXGBE_RXSTMPL);
-       rx_stmph = IXGBE_READ_REG(hw, IXGBE_RXSTMPH);
-
-       timestamp->tv_sec = (uint64_t)(((uint64_t)rx_stmph << 32) | rx_stmpl);
-       timestamp->tv_nsec = 0;
+       rx_tstamp_cycles = ixgbe_read_rx_tstamp_cyclecounter(dev);
+       ns = rte_timecounter_update(&adapter->rx_tstamp_tc, rx_tstamp_cycles);
+       *timestamp = rte_ns_to_timespec(ns);
 
        return  0;
 }
@@ -5669,21 +5905,21 @@ ixgbe_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
                                 struct timespec *timestamp)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct ixgbe_adapter *adapter =
+               (struct ixgbe_adapter *)dev->data->dev_private;
        uint32_t tsync_txctl;
-       uint32_t tx_stmpl;
-       uint32_t tx_stmph;
+       uint64_t tx_tstamp_cycles;
+       uint64_t ns;
 
        tsync_txctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL);
        if ((tsync_txctl & IXGBE_TSYNCTXCTL_VALID) == 0)
                return -EINVAL;
 
-       tx_stmpl = IXGBE_READ_REG(hw, IXGBE_TXSTMPL);
-       tx_stmph = IXGBE_READ_REG(hw, IXGBE_TXSTMPH);
-
-       timestamp->tv_sec = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl);
-       timestamp->tv_nsec = 0;
+       tx_tstamp_cycles = ixgbe_read_tx_tstamp_cyclecounter(dev);
+       ns = rte_timecounter_update(&adapter->tx_tstamp_tc, tx_tstamp_cycles);
+       *timestamp = rte_ns_to_timespec(ns);
 
-       return  0;
+       return 0;
 }
 
 static int