From: Patrisious Haddad <phaddad@xxxxxxxxxx> Prior to this patch in the case that destroy_unmap_eq() failed and was called again, it triggered an additional call of mlx5_debug_eq_remove() which causes a kernel crash, since eq->dbg was not nullified in previous call. Fix it by nullifying eq->dbg pointer after removal. As for the qp->dbg the change is a preparation for the next patches from the series in which mlx5_core_destroy_qp() could actually fail, and have the same outcome. Signed-off-by: Patrisious Haddad <phaddad@xxxxxxxxxx> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxx> --- .../net/ethernet/mellanox/mlx5/core/debugfs.c | 12 ++++++------ drivers/net/ethernet/mellanox/mlx5/core/eq.c | 19 +++++++++++++------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index 3d3e55a5cb11..9b96a1ca0779 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -486,11 +486,11 @@ EXPORT_SYMBOL(mlx5_debug_qp_add); void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp) { - if (!mlx5_debugfs_root) + if (!mlx5_debugfs_root || !qp->dbg) return; - if (qp->dbg) - rem_res_tree(qp->dbg); + rem_res_tree(qp->dbg); + qp->dbg = NULL; } EXPORT_SYMBOL(mlx5_debug_qp_remove); @@ -512,11 +512,11 @@ int mlx5_debug_eq_add(struct mlx5_core_dev *dev, struct mlx5_eq *eq) void mlx5_debug_eq_remove(struct mlx5_core_dev *dev, struct mlx5_eq *eq) { - if (!mlx5_debugfs_root) + if (!mlx5_debugfs_root || !eq->dbg) return; - if (eq->dbg) - rem_res_tree(eq->dbg); + rem_res_tree(eq->dbg); + eq->dbg = NULL; } int mlx5_debug_cq_add(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 229728c80233..3c61f355cdac 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -386,16 +386,20 @@ void mlx5_eq_disable(struct mlx5_core_dev *dev, struct mlx5_eq *eq, } EXPORT_SYMBOL(mlx5_eq_disable); -static int destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq) +static int destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, + bool reentry) { int err; mlx5_debug_eq_remove(dev, eq); err = mlx5_cmd_destroy_eq(dev, eq->eqn); - if (err) + if (err) { mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n", eq->eqn); + if (reentry) + return err; + } mlx5_frag_buf_free(dev, &eq->frag_buf); return err; @@ -481,7 +485,7 @@ static int destroy_async_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq) int err; mutex_lock(&eq_table->lock); - err = destroy_unmap_eq(dev, eq); + err = destroy_unmap_eq(dev, eq, false); mutex_unlock(&eq_table->lock); return err; } @@ -748,12 +752,15 @@ EXPORT_SYMBOL(mlx5_eq_create_generic); int mlx5_eq_destroy_generic(struct mlx5_core_dev *dev, struct mlx5_eq *eq) { + struct mlx5_eq_table *eq_table = dev->priv.eq_table; int err; if (IS_ERR(eq)) return -EINVAL; - err = destroy_async_eq(dev, eq); + mutex_lock(&eq_table->lock); + err = destroy_unmap_eq(dev, eq, true); + mutex_unlock(&eq_table->lock); if (err) goto out; @@ -851,7 +858,7 @@ static void destroy_comp_eqs(struct mlx5_core_dev *dev) list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) { list_del(&eq->list); mlx5_eq_disable(dev, &eq->core, &eq->irq_nb); - if (destroy_unmap_eq(dev, &eq->core)) + if (destroy_unmap_eq(dev, &eq->core, false)) mlx5_core_warn(dev, "failed to destroy comp EQ 0x%x\n", eq->core.eqn); tasklet_disable(&eq->tasklet_ctx.task); @@ -915,7 +922,7 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) goto clean_eq; err = mlx5_eq_enable(dev, &eq->core, &eq->irq_nb); if (err) { - destroy_unmap_eq(dev, &eq->core); + destroy_unmap_eq(dev, &eq->core, false); goto clean_eq; } -- 2.35.1