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 <viachesl...@mellanox.com> Acked-by: Matan Azrad <ma...@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(+) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index e599bbb..a61394c 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -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. */ }; /* diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h index 974a847..d082cd7 100644 --- a/drivers/net/mlx5/mlx5_rxtx.h +++ b/drivers/net/mlx5/mlx5_rxtx.h @@ -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_ */ diff --git a/drivers/net/mlx5/mlx5_txpp.c b/drivers/net/mlx5/mlx5_txpp.c index 17d64ff..799b20a 100644 --- a/drivers/net/mlx5/mlx5_txpp.c +++ b/drivers/net/mlx5/mlx5_txpp.c @@ -858,6 +858,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); -- 1.8.3.1