On Wed, Oct 09, 2019 at 01:09:34PM -0300, Jason Gunthorpe wrote: > diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c > index 66523313c3e46c..fd2306aff78ad7 100644 > +++ b/drivers/infiniband/hw/mlx5/odp.c > @@ -144,6 +144,32 @@ void mlx5_odp_populate_klm(struct mlx5_klm *pklm, size_t idx, size_t nentries, > } > } > > +static void dma_fence_odp_mr(struct mlx5_ib_mr *mr) > +{ > + struct ib_umem_odp *odp = to_ib_umem_odp(mr->umem); > + > + /* Ensure mlx5_ib_invalidate_range() will not touch the MR any more */ > + mutex_lock(&odp->umem_mutex); > + if (odp->npages) { > + /* > + * If not cached then the caller had to do clean_mrs first to > + * fence the mkey. > + */ > + if (mr->allocated_from_cache) { > + mlx5_mr_cache_invalidate(mr); > + } else { > + /* clean_mr() */ > + mlx5_core_destroy_mkey(mr->dev->mdev, &mr->mmkey); > + WARN_ON(mr->descs); > + } > + ib_umem_odp_unmap_dma_pages(odp, ib_umem_start(odp), > + ib_umem_end(odp)); > + WARN_ON(odp->npages); > + } > + odp->private = NULL; > + mutex_unlock(&odp->umem_mutex); The new mmu notifier debugging catches that mlx5_core_destroy_mkey() allocates as GFP_KERNEL and cannot be called under umem_mutex, so this needs to be reworked. I think to rely on mlx5_mr_cache_invalidate() to fence the DMA, then destroy out of the lock: diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c index 74c45356d54007..f713eb82eeead4 100644 --- a/drivers/infiniband/hw/mlx5/odp.c +++ b/drivers/infiniband/hw/mlx5/odp.c @@ -151,23 +151,18 @@ static void dma_fence_odp_mr(struct mlx5_ib_mr *mr) /* Ensure mlx5_ib_invalidate_range() will not touch the MR any more */ mutex_lock(&odp->umem_mutex); if (odp->npages) { - /* - * If not cached then the caller had to do clean_mrs first to - * fence the mkey. - */ - if (mr->allocated_from_cache) { - mlx5_mr_cache_invalidate(mr); - } else { - /* clean_mr() */ - mlx5_core_destroy_mkey(mr->dev->mdev, &mr->mmkey); - WARN_ON(mr->descs); - } + mlx5_mr_cache_invalidate(mr); ib_umem_odp_unmap_dma_pages(odp, ib_umem_start(odp), ib_umem_end(odp)); WARN_ON(odp->npages); } odp->private = NULL; mutex_unlock(&odp->umem_mutex); + + if (!mr->allocated_from_cache) { + mlx5_core_destroy_mkey(mr->dev->mdev, &mr->mmkey); + WARN_ON(mr->descs); + } } /*