RXQ interrupts under Linux are based on the epoll mechanism. An expected order of operations is as follows: 1. Call rte_eth_dev_rx_intr_enable(), to arm the CQ for receiving events on data input. 2. Block on rte_epoll_wait() with an array of file descriptors representing the CQ events. Upon data arrival the kernel will signal an input event on the corresponding CQ fd. 3. Call rte_eth_dev_rx_intr_disable() after the event was received and continue in polling mode. The mlx5 implementation of rte_eth_dev_rx_intr_disable() is to get the CQ event and ack it.
In practice applications may wake up from rte_epoll_wait() due to timeout with no event to ack but still call rte_eth_dev_rx_intr_disable() unconditionally. In such cases the call should return EAGAIN (since the file descriptors are non-blocked), as opposed to EINVAL which indicates a real failure. In case of EAGAIN the PMD should not warn on "Unable to disable interrupt on Rx queue". Signed-off-by: Ophir Munk <ophi...@mellanox.com> Acked-by: Viacheslav Ovsiienko <viachesl...@mellanox.com> --- drivers/net/mlx5/mlx5_rxq.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index b436f06..38dfb98 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -936,7 +936,14 @@ mlx5_rx_intr_disable(struct rte_eth_dev *dev, uint16_t rx_queue_id) } ret = mlx5_glue->get_cq_event(rxq_obj->channel, &ev_cq, &ev_ctx); if (ret || ev_cq != rxq_obj->cq) { - rte_errno = EINVAL; + /** + * For non-zero 'ret' - save the errno (may be EAGAIN which + * means this function was called before receiving an event). + */ + if (ret) + rte_errno = errno; + else + rte_errno = EINVAL; goto exit; } rxq_data->cq_arm_sn++; @@ -947,8 +954,9 @@ mlx5_rx_intr_disable(struct rte_eth_dev *dev, uint16_t rx_queue_id) ret = rte_errno; /* Save rte_errno before cleanup. */ if (rxq_obj) mlx5_rxq_obj_release(rxq_obj); - DRV_LOG(WARNING, "port %u unable to disable interrupt on Rx queue %d", - dev->data->port_id, rx_queue_id); + if (ret != EAGAIN) + DRV_LOG(WARNING, "port %u unable to disable interrupt on Rx queue %d", + dev->data->port_id, rx_queue_id); rte_errno = ret; /* Restore rte_errno. */ return -rte_errno; } -- 2.8.4