From: Daniel Mrzyglod <danielx.t.mrzyg...@intel.com> Add additional functions to support the existing IEEE1588 functionality and to enable getting, setting and adjusting the device time.
Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod at intel.com> Signed-off-by: Pablo de Lara <pablo.de.lara.guarch at intel.com> Reviewed-by: John McNamara <john.mcnamara at intel.com> --- drivers/net/ixgbe/ixgbe_ethdev.c | 187 ++++++++++++++++++++++++++++++++++++--- drivers/net/ixgbe/ixgbe_ethdev.h | 2 + 2 files changed, 178 insertions(+), 11 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index 0b0bbcf..91a903d 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -126,10 +126,17 @@ #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 0xffffffffffffffff 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, }; /* @@ -5608,20 +5623,147 @@ ixgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev, ixgbe_dev_addr_list_itr, TRUE); } +static uint64_t +ixgbe_read_cyclecounter(void *arg) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *) arg; + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint64_t systime_cycles = 0; + + 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 void +ixgbe_start_cyclecounter(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->tc, 0, sizeof(struct rte_timecounter)); + adapter->tc.read = ixgbe_read_cyclecounter; + adapter->tc.cc_mask = IXGBE_CYCLECOUNTER_MASK; + adapter->tc.cc_shift = shift; + adapter->tc.arg = dev; +} + +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->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); + /* Reset the timecounter. */ + rte_timecounter_init(&adapter->tc, ns); + + return 0; +} + +static int +ixgbe_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts) +{ + uint64_t ns; + struct ixgbe_adapter *adapter = + (struct ixgbe_adapter *)dev->data->dev_private; + + ns = rte_timecounter_read(&adapter->tc); + *ts = rte_ns_to_timespec(ns); + + return 0; +} + static int ixgbe_timesync_enable(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; uint32_t tsync_ctl; uint32_t tsauxc; + uint64_t ns; + struct timespec zerotime = {0, 0}; /* 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); + /* Set 0.0 epoch time to initialize timecounter. */ + ns = rte_timespec_to_ns(&zerotime); + ixgbe_start_cyclecounter(dev); + rte_timecounter_init(&adapter->tc, ns); + + IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); /* Enable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */ IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), @@ -5639,6 +5781,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; } @@ -5673,9 +5817,13 @@ 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 regival = 0; tsync_rxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); if ((tsync_rxctl & IXGBE_TSYNCRXCTL_VALID) == 0) @@ -5683,9 +5831,16 @@ ixgbe_timesync_read_rx_timestamp(struct rte_eth_dev *dev, rx_stmpl = IXGBE_READ_REG(hw, IXGBE_RXSTMPL); rx_stmph = IXGBE_READ_REG(hw, IXGBE_RXSTMPH); + rte_timecounter_read(&adapter->tc); + + if (hw->mac.type == ixgbe_mac_X550) + regival = (uint64_t)((uint64_t)rx_stmph * NSEC_PER_SEC + + rx_stmpl); + else + regival = (uint64_t)(((uint64_t)rx_stmph << 32) | rx_stmpl); - timestamp->tv_sec = (uint64_t)(((uint64_t)rx_stmph << 32) | rx_stmpl); - timestamp->tv_nsec = 0; + regival = rte_timecounter_cycles_to_ns_time(&adapter->tc, regival); + *timestamp = rte_ns_to_timespec(regival); return 0; } @@ -5695,9 +5850,13 @@ 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 regival = 0; tsync_txctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); if ((tsync_txctl & IXGBE_TSYNCTXCTL_VALID) == 0) @@ -5705,9 +5864,15 @@ ixgbe_timesync_read_tx_timestamp(struct rte_eth_dev *dev, tx_stmpl = IXGBE_READ_REG(hw, IXGBE_TXSTMPL); tx_stmph = IXGBE_READ_REG(hw, IXGBE_TXSTMPH); + rte_timecounter_read(&adapter->tc); - timestamp->tv_sec = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl); - timestamp->tv_nsec = 0; + if (hw->mac.type == ixgbe_mac_X550) + regival = (uint64_t)((uint64_t)tx_stmph * NSEC_PER_SEC + + tx_stmpl); + else + regival = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl); + regival = rte_timecounter_cycles_to_ns_time(&adapter->tc, regival); + *timestamp = rte_ns_to_timespec(regival); return 0; } diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h index 1856c42..0e309a2 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.h +++ b/drivers/net/ixgbe/ixgbe_ethdev.h @@ -37,6 +37,7 @@ #include "base/ixgbe_dcb_82599.h" #include "base/ixgbe_dcb_82598.h" #include "ixgbe_bypass.h" +#include <rte_time.h> /* need update link, bit flag */ #define IXGBE_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0) @@ -282,6 +283,7 @@ struct ixgbe_adapter { bool rx_bulk_alloc_allowed; bool rx_vec_allowed; + struct rte_timecounter tc; }; #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\ -- 1.8.1.4