[v3,11/17] net/mlx5: convert timestamp to completion index
Checks
Commit Message
The application provides timestamps in Tx mbuf as clocks,
the hardware performs scheduling on Clock Queue completion index
match. This patch introduces the timestamp-to-completion-index
inline routine.
Signed-off-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
Acked-by: Matan Azrad <matan@mellanox.com>
---
drivers/net/mlx5/mlx5.h | 2 ++
drivers/net/mlx5/mlx5_rxtx.h | 55 ++++++++++++++++++++++++++++++++++++++++++++
drivers/net/mlx5/mlx5_txpp.c | 5 ++++
3 files changed, 62 insertions(+)
@@ -585,6 +585,8 @@ struct mlx5_dev_txpp {
rte_atomic32_t err_miss_int; /* Missed service interrupt. */
rte_atomic32_t err_rearm_queue; /* Rearm Queue errors. */
rte_atomic32_t err_clock_queue; /* Clock Queue errors. */
+ rte_atomic32_t err_ts_past; /* Timestamp in the past. */
+ rte_atomic32_t err_ts_future; /* Timestamp in the distant future. */
};
/*
@@ -719,4 +719,59 @@ int mlx5_dma_unmap(struct rte_pci_device *pdev, void *addr, uint64_t iova,
return (ts & UINT32_MAX) + (ts >> 32) * NS_PER_S;
}
+/**
+ * Convert timestamp from mbuf format to linear counter
+ * of Clock Queue completions (24 bits)
+ *
+ * @param sh
+ * Pointer to the device shared context to fetch Tx
+ * packet pacing timestamp and parameters.
+ * @param ts
+ * Timestamp from mbuf to convert.
+ * @return
+ * positive or zero value - completion ID to wait
+ * negative value - conversion error
+ */
+static __rte_always_inline int32_t
+mlx5_txpp_convert_tx_ts(struct mlx5_dev_ctx_shared *sh, uint64_t mts)
+{
+ uint64_t ts, ci;
+ uint32_t tick;
+
+ do {
+ /*
+ * Read atomically two uint64_t fields and compare lsb bits.
+ * It there is no match - the timestamp was updated in
+ * the service thread, data should be re-read.
+ */
+ rte_compiler_barrier();
+ ci = rte_atomic64_read(&sh->txpp.ts.ci_ts);
+ ts = rte_atomic64_read(&sh->txpp.ts.ts);
+ rte_compiler_barrier();
+ if (!((ts ^ ci) << (64 - MLX5_CQ_INDEX_WIDTH)))
+ break;
+ } while (true);
+ /* Perform the skew correction, positive value to send earlier. */
+ mts -= sh->txpp.skew;
+ mts -= ts;
+ if (unlikely(mts >= UINT64_MAX / 2)) {
+ /* We have negative integer, mts is in the past. */
+ rte_atomic32_inc(&sh->txpp.err_ts_past);
+ return -1;
+ }
+ tick = sh->txpp.tick;
+ MLX5_ASSERT(tick);
+ /* Convert delta to completions, round up. */
+ mts = (mts + tick - 1) / tick;
+ if (unlikely(mts >= (1 << MLX5_CQ_INDEX_WIDTH) / 2 - 1)) {
+ /* We have mts is too distant future. */
+ rte_atomic32_inc(&sh->txpp.err_ts_future);
+ return -1;
+ }
+ mts <<= 64 - MLX5_CQ_INDEX_WIDTH;
+ ci += mts;
+ ci >>= 64 - MLX5_CQ_INDEX_WIDTH;
+ return ci;
+}
+
#endif /* RTE_PMD_MLX5_RXTX_H_ */
@@ -860,6 +860,11 @@
int flags;
int ret;
+ rte_atomic32_set(&sh->txpp.err_miss_int, 0);
+ rte_atomic32_set(&sh->txpp.err_rearm_queue, 0);
+ rte_atomic32_set(&sh->txpp.err_clock_queue, 0);
+ rte_atomic32_set(&sh->txpp.err_ts_past, 0);
+ rte_atomic32_set(&sh->txpp.err_ts_future, 0);
/* Attach interrupt handler to process Rearm Queue completions. */
flags = fcntl(sh->txpp.echan->fd, F_GETFL);
ret = fcntl(sh->txpp.echan->fd, F_SETFL, flags | O_NONBLOCK);