From 6817ad38718451849b672b0584176c14a8b55b88 Mon Sep 17 00:00:00 2001 From: Yongseok Koh Date: Wed, 10 Jan 2018 09:46:49 -0800 Subject: [PATCH] net/mlx5: fix deadlock of link status alarm If mlx5_dev_link_status_handler() is executed while canceling the alarm, deadlock can happen because rte_eal_alarm_cancel() waits for all callbackes to finish execution and both calls are protected by priv->lock. Fixes: 198a3c339a8f ("mlx5: handle link status interrupts") Cc: stable@dpdk.org Signed-off-by: Yongseok Koh Acked-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.h | 16 ++++++++++++++++ drivers/net/mlx5/mlx5_ethdev.c | 13 +++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 8ee5220698..e740a4e777 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -179,6 +179,22 @@ priv_lock(struct priv *priv) rte_spinlock_lock(&priv->lock); } +/** + * Try to lock private structure to protect it from concurrent access in the + * control path. + * + * @param priv + * Pointer to private structure. + * + * @return + * 1 if the lock is successfully taken; 0 otherwise. + */ +static inline int +priv_trylock(struct priv *priv) +{ + return rte_spinlock_trylock(&priv->lock); +} + /** * Unlock private structure. * diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index 79a0248a88..6f78adc4ab 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -1187,8 +1187,12 @@ mlx5_dev_link_status_handler(void *arg) struct priv *priv = dev->data->dev_private; int ret; - priv_lock(priv); - assert(priv->pending_alarm == 1); + while (!priv_trylock(priv)) { + /* Alarm is being canceled. */ + if (priv->pending_alarm == 0) + return; + rte_pause(); + } priv->pending_alarm = 0; ret = priv_link_status_update(priv); priv_unlock(priv); @@ -1255,9 +1259,10 @@ priv_dev_interrupt_handler_uninstall(struct priv *priv, struct rte_eth_dev *dev) if (priv->primary_socket) rte_intr_callback_unregister(&priv->intr_handle_socket, mlx5_dev_handler_socket, dev); - if (priv->pending_alarm) + if (priv->pending_alarm) { + priv->pending_alarm = 0; rte_eal_alarm_cancel(mlx5_dev_link_status_handler, dev); - priv->pending_alarm = 0; + } priv->intr_handle.fd = 0; priv->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; priv->intr_handle_socket.fd = 0; -- 2.20.1