#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);
/* For Virtual Function support */
static int eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev);
static int eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev);
-static int ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev);
-static int ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev);
static int ixgbevf_dev_configure(struct rte_eth_dev *dev);
static int ixgbevf_dev_start(struct rte_eth_dev *dev);
static void ixgbevf_dev_stop(struct rte_eth_dev *dev);
uint16_t queue, int on);
static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on);
-static void ixgbevf_dev_interrupt_handler(struct rte_intr_handle *handle,
- void *param);
static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
uint16_t queue_id);
static int ixgbevf_dev_rx_queue_intr_disable(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
.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,
};
/*
sizeof(rte_ixgbe_stats_strings[0]))
/* Per-queue statistics */
-#define IXBGE_NB_8_PER_Q_STATS (8 * 7)
-#define IXBGE_NB_16_PER_Q_STATS (16 * 5)
-#define IXGBE_NB_Q_STATS (IXBGE_NB_8_PER_Q_STATS + IXBGE_NB_16_PER_Q_STATS)
+static const struct rte_ixgbe_xstats_name_off rte_ixgbe_rxq_strings[] = {
+ {"mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats, rnbc)},
+ {"dropped", offsetof(struct ixgbe_hw_stats, mpc)},
+ {"xon_packets", offsetof(struct ixgbe_hw_stats, pxonrxc)},
+ {"xoff_packets", offsetof(struct ixgbe_hw_stats, pxoffrxc)},
+};
+
+#define IXGBE_NB_RXQ_PRIO_STATS (sizeof(rte_ixgbe_rxq_strings) / \
+ sizeof(rte_ixgbe_rxq_strings[0]))
+
+static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
+ {"xon_packets", offsetof(struct ixgbe_hw_stats, pxontxc)},
+ {"xoff_packets", offsetof(struct ixgbe_hw_stats, pxofftxc)},
+ {"xon_to_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc)},
+};
-#define IXGBE_NB_XSTATS (IXGBE_NB_HW_STATS + IXGBE_NB_Q_STATS)
+#define IXGBE_NB_TXQ_PRIO_STATS (sizeof(rte_ixgbe_txq_strings) / \
+ sizeof(rte_ixgbe_txq_strings[0]))
static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
{"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
eth_dev->data->port_id, pci_dev->id.vendor_id,
pci_dev->id.device_id);
+ rte_intr_callback_register(&pci_dev->intr_handle,
+ ixgbe_dev_interrupt_handler,
+ (void *)eth_dev);
+
+ /* enable uio/vfio intr/eventfd mapping */
+ rte_intr_enable(&pci_dev->intr_handle);
+
/* enable support intr */
ixgbe_enable_intr(eth_dev);
ixgbe_pf_host_configure(dev);
/* check and configure queue intr-vector mapping */
- if (dev->data->dev_conf.intr_conf.rxq != 0) {
+ if ((rte_intr_cap_multiple(intr_handle) ||
+ !RTE_ETH_DEV_SRIOV(dev).active) &&
+ dev->data->dev_conf.intr_conf.rxq != 0) {
intr_vector = dev->data->nb_rx_queues;
if (rte_intr_efd_enable(intr_handle, intr_vector))
return -1;
if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
intr_handle->intr_vec =
rte_zmalloc("intr_vec",
- dev->data->nb_rx_queues * sizeof(int),
- 0);
+ dev->data->nb_rx_queues * sizeof(int), 0);
if (intr_handle->intr_vec == NULL) {
PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
" intr_vec\n", dev->data->nb_rx_queues);
skip_link_setup:
- /* check if lsc interrupt is enabled */
- if (dev->data->dev_conf.intr_conf.lsc != 0) {
- if (rte_intr_allow_others(intr_handle)) {
- rte_intr_callback_register(intr_handle,
- ixgbe_dev_interrupt_handler,
- (void *)dev);
+ if (rte_intr_allow_others(intr_handle)) {
+ /* check if lsc interrupt is enabled */
+ if (dev->data->dev_conf.intr_conf.lsc != 0)
ixgbe_dev_lsc_interrupt_setup(dev);
- } else
+ } else {
+ rte_intr_callback_unregister(intr_handle,
+ ixgbe_dev_interrupt_handler,
+ (void *)dev);
+ if (dev->data->dev_conf.intr_conf.lsc != 0)
PMD_INIT_LOG(INFO, "lsc won't enable because of"
" no intr multiplex\n");
}
/* check if rxq interrupt is enabled */
- if (dev->data->dev_conf.intr_conf.rxq != 0)
+ if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+ rte_intr_dp_is_en(intr_handle))
ixgbe_dev_rxq_interrupt_setup(dev);
/* enable uio/vfio intr/eventfd mapping */
memset(filter_info->fivetuple_mask, 0,
sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
+ if (!rte_intr_allow_others(intr_handle))
+ /* resume to the default handler */
+ rte_intr_callback_register(intr_handle,
+ ixgbe_dev_interrupt_handler,
+ (void *)dev);
+
/* Clean datapath event and queue/vec mapping */
rte_intr_efd_disable(intr_handle);
if (intr_handle->intr_vec != NULL) {
total_missed_rx +
hw_stats->illerrc +
hw_stats->errbc +
- hw_stats->xec +
hw_stats->rfc +
hw_stats->fccrc +
hw_stats->fclast;
memset(stats, 0, sizeof(*stats));
}
+/* This function calculates the number of xstats based on the current config */
+static unsigned
+ixgbe_xstats_calc_num(void) {
+ return IXGBE_NB_HW_STATS + (IXGBE_NB_RXQ_PRIO_STATS * 8) +
+ (IXGBE_NB_TXQ_PRIO_STATS * 8);
+}
+
static int
ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
unsigned n)
struct ixgbe_hw_stats *hw_stats =
IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
uint64_t total_missed_rx, total_qbrc, total_qprc, total_qprdc;
- unsigned i, count = IXGBE_NB_XSTATS;
+ unsigned i, stat, count = 0;
+
+ count = ixgbe_xstats_calc_num();
if (n < count)
return count;
count++;
}
- /* Per-Q stats, with 8 queues available */
- for (i = 0; i < 8; i++) {
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_q%u_mbuf_allocation_errors", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, rnbc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_q%u_missed_packets", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, mpc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_q%u_xon_priority_packets", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, pxonrxc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "tx_q%u_xon_priority_packets", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, pxontxc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_q%u_xoff_priority_packets", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, pxoffrxc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "tx_q%u_xoff_priority_packets", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, pxofftxc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "xx_q%u_xon_to_xoff_priority_packets", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, pxon2offc[i]));
- count++;
+ /* RX Priority Stats */
+ for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
+ for (i = 0; i < 8; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_priority%u_%s", i,
+ rte_ixgbe_rxq_strings[stat].name);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_ixgbe_rxq_strings[stat].offset +
+ (sizeof(uint64_t) * i));
+ count++;
+ }
}
- for (i = 0; i < 16; i++) {
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_q%u_packets", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, qprc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_q%u_bytes", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, qbrc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "tx_q%u_packets", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, qptc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "tx_q%u_bytes", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, qbtc[i]));
- count++;
-
- snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_q%u_dropped", i);
- xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
- offsetof(struct ixgbe_hw_stats, qprdc[i]));
- count++;
+ /* TX Priority Stats */
+ for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
+ for (i = 0; i < 8; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_priority%u_%s", i,
+ rte_ixgbe_txq_strings[stat].name);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_ixgbe_txq_strings[stat].offset +
+ (sizeof(uint64_t) * i));
+ count++;
+ }
}
return count;
struct ixgbe_hw_stats *stats =
IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned count = ixgbe_xstats_calc_num();
+
/* HW registers are cleared on read */
- ixgbe_dev_xstats_get(dev, NULL, IXGBE_NB_XSTATS);
+ ixgbe_dev_xstats_get(dev, NULL, count);
/* Reset software totals */
memset(stats, 0, sizeof(*stats));
return 0;
}
-static int
-ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev)
-{
- uint32_t eicr;
- struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct ixgbe_interrupt *intr =
- IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-
- /* clear all cause mask */
- ixgbevf_intr_disable(hw);
-
- /* read-on-clear nic registers here */
- eicr = IXGBE_READ_REG(hw, IXGBE_VTEICR);
- PMD_DRV_LOG(INFO, "eicr %x", eicr);
-
- intr->flags = 0;
-
- /* set flag for async link update */
- if (eicr & IXGBE_EICR_LSC)
- intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
-
- return 0;
-}
-
/**
* It gets and then prints the link status.
*
return 0;
}
-static int
-ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev)
-{
- struct ixgbe_hw *hw =
- IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
- PMD_DRV_LOG(DEBUG, "enable intr immediately");
- ixgbevf_intr_enable(hw);
- rte_intr_enable(&dev->pci_dev->intr_handle);
- return 0;
-}
-
/**
* Interrupt handler which shall be registered for alarm callback for delayed
* handling specific interrupt to wait for the stable nic state. As the
ixgbe_dev_interrupt_action(dev);
}
-static void
-ixgbevf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
- void *param)
-{
- struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
-
- ixgbevf_dev_interrupt_get_status(dev);
- ixgbevf_dev_interrupt_action(dev);
-}
-
static int
ixgbe_dev_led_on(struct rte_eth_dev *dev)
{
}
ixgbevf_configure_msix(dev);
- if (dev->data->dev_conf.intr_conf.lsc != 0) {
- if (rte_intr_allow_others(intr_handle))
- rte_intr_callback_register(intr_handle,
- ixgbevf_dev_interrupt_handler,
- (void *)dev);
- else
- PMD_INIT_LOG(INFO, "lsc won't enable because of"
- " no intr multiplex\n");
- }
-
rte_intr_enable(intr_handle);
/* Re-enable interrupt for VF */
ixgbevf_dev_close(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct rte_pci_device *pci_dev;
PMD_INIT_FUNC_TRACE();
/* reprogram the RAR[0] in case user changed it. */
ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
-
- pci_dev = dev->pci_dev;
- if (pci_dev->intr_handle.intr_vec) {
- rte_free(pci_dev->intr_handle.intr_vec);
- pci_dev->intr_handle.intr_vec = NULL;
- }
}
static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on)
intr_handle->intr_vec[q_idx] = vector_idx;
}
- /* Configure VF Rx queue ivar */
+ /* Configure VF other cause ivar */
ixgbevf_set_ivar_map(hw, -1, 1, vector_idx);
}
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)
{
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),
tsync_ctl |= IXGBE_TSYNCTXCTL_ENABLED;
IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, tsync_ctl);
+ IXGBE_WRITE_FLUSH(hw);
+
return 0;
}
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;
}
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);
+ 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);
- timestamp->tv_sec = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl);
- timestamp->tv_nsec = 0;
-
- return 0;
+ return 0;
}
static int