Skip to content

Commit e6fb246

Browse files
committed
RDMA/mlx5: Consolidate MR destruction to mlx5_ib_dereg_mr()
Now that the SRCU stuff has been removed the entire MR destroy logic can be made a lot simpler. Currently there are many different ways to destroy a MR and it makes it really hard to do this task correctly. Route all destruction through mlx5_ib_dereg_mr() and make it work for all situations. Since it turns out all the different MR types do basically the same thing this removes a lot of knowledge of MR internals from ODP and leaves ODP just exporting an operation to clean up children. This fixes a few weird corner cases bugs and firmly uses the correct ordering of the MR destruction: - Stop parallel access to the mkey via the ODP xarray - Stop DMA - Release the umem - Clean up ODP children - Free/Recycle the MR Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent f18ec42 commit e6fb246

File tree

4 files changed

+90
-203
lines changed

4 files changed

+90
-203
lines changed

drivers/infiniband/core/umem_dmabuf.c

+4
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf)
168168
{
169169
struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf;
170170

171+
dma_resv_lock(dmabuf->resv, NULL);
172+
ib_umem_dmabuf_unmap_pages(umem_dmabuf);
173+
dma_resv_unlock(dmabuf->resv);
174+
171175
dma_buf_detach(dmabuf, umem_dmabuf->attach);
172176
dma_buf_put(dmabuf);
173177
kfree(umem_dmabuf);

drivers/infiniband/hw/mlx5/mlx5_ib.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -1285,8 +1285,7 @@ struct mlx5_ib_mr *mlx5_ib_alloc_implicit_mr(struct mlx5_ib_pd *pd,
12851285
struct ib_udata *udata,
12861286
int access_flags);
12871287
void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *mr);
1288-
void mlx5_ib_fence_odp_mr(struct mlx5_ib_mr *mr);
1289-
void mlx5_ib_fence_dmabuf_mr(struct mlx5_ib_mr *mr);
1288+
void mlx5_ib_free_odp_mr(struct mlx5_ib_mr *mr);
12901289
struct ib_mr *mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
12911290
u64 length, u64 virt_addr, int access_flags,
12921291
struct ib_pd *pd, struct ib_udata *udata);
@@ -1334,8 +1333,6 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev);
13341333

13351334
struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev,
13361335
unsigned int entry, int access_flags);
1337-
void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
1338-
int mlx5_mr_cache_invalidate(struct mlx5_ib_mr *mr);
13391336

13401337
int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
13411338
struct ib_mr_status *mr_status);

drivers/infiniband/hw/mlx5/mr.c

+62-71
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,6 @@ mlx5_ib_create_mkey_cb(struct mlx5_ib_dev *dev,
119119
create_mkey_callback, context);
120120
}
121121

122-
static void clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
123-
static void dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
124122
static int mr_cache_max_order(struct mlx5_ib_dev *dev);
125123
static void queue_adjust_cache_locked(struct mlx5_cache_ent *ent);
126124

@@ -627,30 +625,10 @@ static struct mlx5_ib_mr *get_cache_mr(struct mlx5_cache_ent *req_ent)
627625
return NULL;
628626
}
629627

630-
static void detach_mr_from_cache(struct mlx5_ib_mr *mr)
628+
static void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
631629
{
632630
struct mlx5_cache_ent *ent = mr->cache_ent;
633631

634-
mr->cache_ent = NULL;
635-
spin_lock_irq(&ent->lock);
636-
ent->total_mrs--;
637-
spin_unlock_irq(&ent->lock);
638-
}
639-
640-
void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
641-
{
642-
struct mlx5_cache_ent *ent = mr->cache_ent;
643-
644-
if (!ent)
645-
return;
646-
647-
if (mlx5_mr_cache_invalidate(mr)) {
648-
detach_mr_from_cache(mr);
649-
destroy_mkey(dev, mr);
650-
kfree(mr);
651-
return;
652-
}
653-
654632
spin_lock_irq(&ent->lock);
655633
list_add_tail(&mr->list, &ent->head);
656634
ent->available_mrs++;
@@ -1503,7 +1481,7 @@ static struct ib_mr *create_real_mr(struct ib_pd *pd, struct ib_umem *umem,
15031481
*/
15041482
err = mlx5_ib_update_mr_pas(mr, MLX5_IB_UPD_XLT_ENABLE);
15051483
if (err) {
1506-
dereg_mr(dev, mr);
1484+
mlx5_ib_dereg_mr(&mr->ibmr, NULL);
15071485
return ERR_PTR(err);
15081486
}
15091487
}
@@ -1560,7 +1538,7 @@ static struct ib_mr *create_user_odp_mr(struct ib_pd *pd, u64 start, u64 length,
15601538
return &mr->ibmr;
15611539

15621540
err_dereg_mr:
1563-
dereg_mr(dev, mr);
1541+
mlx5_ib_dereg_mr(&mr->ibmr, NULL);
15641542
return ERR_PTR(err);
15651543
}
15661544

@@ -1657,7 +1635,7 @@ struct ib_mr *mlx5_ib_reg_user_mr_dmabuf(struct ib_pd *pd, u64 offset,
16571635
return &mr->ibmr;
16581636

16591637
err_dereg_mr:
1660-
dereg_mr(dev, mr);
1638+
mlx5_ib_dereg_mr(&mr->ibmr, NULL);
16611639
return ERR_PTR(err);
16621640
}
16631641

@@ -1669,7 +1647,7 @@ struct ib_mr *mlx5_ib_reg_user_mr_dmabuf(struct ib_pd *pd, u64 offset,
16691647
* and any DMA inprogress will be completed. Failure of this function
16701648
* indicates the HW has failed catastrophically.
16711649
*/
1672-
int mlx5_mr_cache_invalidate(struct mlx5_ib_mr *mr)
1650+
static int mlx5_mr_cache_invalidate(struct mlx5_ib_mr *mr)
16731651
{
16741652
struct mlx5_umr_wr umrwr = {};
16751653

@@ -1941,69 +1919,82 @@ mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
19411919
}
19421920
}
19431921

1944-
static void clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
1922+
int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
19451923
{
1946-
if (mr->ibmr.type == IB_MR_TYPE_INTEGRITY) {
1924+
struct mlx5_ib_mr *mr = to_mmr(ibmr);
1925+
struct mlx5_ib_dev *dev = to_mdev(ibmr->device);
1926+
int rc;
1927+
1928+
/*
1929+
* Any async use of the mr must hold the refcount, once the refcount
1930+
* goes to zero no other thread, such as ODP page faults, prefetch, any
1931+
* UMR activity, etc can touch the mkey. Thus it is safe to destroy it.
1932+
*/
1933+
if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING) &&
1934+
refcount_read(&mr->mmkey.usecount) != 0 &&
1935+
xa_erase(&mr_to_mdev(mr)->odp_mkeys, mlx5_base_mkey(mr->mmkey.key)))
1936+
mlx5r_deref_wait_odp_mkey(&mr->mmkey);
1937+
1938+
if (ibmr->type == IB_MR_TYPE_INTEGRITY) {
1939+
xa_cmpxchg(&dev->sig_mrs, mlx5_base_mkey(mr->mmkey.key), ibmr,
1940+
NULL, GFP_KERNEL);
1941+
1942+
if (mr->mtt_mr) {
1943+
rc = mlx5_ib_dereg_mr(&mr->mtt_mr->ibmr, NULL);
1944+
if (rc)
1945+
return rc;
1946+
mr->mtt_mr = NULL;
1947+
}
1948+
if (mr->klm_mr) {
1949+
mlx5_ib_dereg_mr(&mr->klm_mr->ibmr, NULL);
1950+
if (rc)
1951+
return rc;
1952+
mr->klm_mr = NULL;
1953+
}
1954+
19471955
if (mlx5_core_destroy_psv(dev->mdev,
19481956
mr->sig->psv_memory.psv_idx))
19491957
mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
19501958
mr->sig->psv_memory.psv_idx);
1951-
if (mlx5_core_destroy_psv(dev->mdev,
1952-
mr->sig->psv_wire.psv_idx))
1959+
if (mlx5_core_destroy_psv(dev->mdev, mr->sig->psv_wire.psv_idx))
19531960
mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
19541961
mr->sig->psv_wire.psv_idx);
1955-
xa_erase(&dev->sig_mrs, mlx5_base_mkey(mr->mmkey.key));
19561962
kfree(mr->sig);
19571963
mr->sig = NULL;
19581964
}
19591965

1966+
/* Stop DMA */
1967+
if (mr->cache_ent) {
1968+
if (mlx5_mr_cache_invalidate(mr)) {
1969+
spin_lock_irq(&mr->cache_ent->lock);
1970+
mr->cache_ent->total_mrs--;
1971+
spin_unlock_irq(&mr->cache_ent->lock);
1972+
mr->cache_ent = NULL;
1973+
}
1974+
}
19601975
if (!mr->cache_ent) {
1961-
destroy_mkey(dev, mr);
1962-
mlx5_free_priv_descs(mr);
1976+
rc = destroy_mkey(to_mdev(mr->ibmr.device), mr);
1977+
if (rc)
1978+
return rc;
19631979
}
1964-
}
1965-
1966-
static void dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
1967-
{
1968-
struct ib_umem *umem = mr->umem;
19691980

1970-
/* Stop all DMA */
1971-
if (is_odp_mr(mr))
1972-
mlx5_ib_fence_odp_mr(mr);
1973-
else if (is_dmabuf_mr(mr))
1974-
mlx5_ib_fence_dmabuf_mr(mr);
1975-
else
1976-
clean_mr(dev, mr);
1981+
if (mr->umem) {
1982+
bool is_odp = is_odp_mr(mr);
19771983

1978-
if (umem) {
1979-
if (!is_odp_mr(mr))
1980-
atomic_sub(ib_umem_num_pages(umem),
1984+
if (!is_odp)
1985+
atomic_sub(ib_umem_num_pages(mr->umem),
19811986
&dev->mdev->priv.reg_pages);
1982-
ib_umem_release(umem);
1987+
ib_umem_release(mr->umem);
1988+
if (is_odp)
1989+
mlx5_ib_free_odp_mr(mr);
19831990
}
19841991

1985-
if (mr->cache_ent)
1992+
if (mr->cache_ent) {
19861993
mlx5_mr_cache_free(dev, mr);
1987-
else
1994+
} else {
1995+
mlx5_free_priv_descs(mr);
19881996
kfree(mr);
1989-
}
1990-
1991-
int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
1992-
{
1993-
struct mlx5_ib_mr *mmr = to_mmr(ibmr);
1994-
1995-
if (ibmr->type == IB_MR_TYPE_INTEGRITY) {
1996-
dereg_mr(to_mdev(mmr->mtt_mr->ibmr.device), mmr->mtt_mr);
1997-
dereg_mr(to_mdev(mmr->klm_mr->ibmr.device), mmr->klm_mr);
1998-
}
1999-
2000-
if (is_odp_mr(mmr) && to_ib_umem_odp(mmr->umem)->is_implicit_odp) {
2001-
mlx5_ib_free_implicit_mr(mmr);
2002-
return 0;
20031997
}
2004-
2005-
dereg_mr(to_mdev(ibmr->device), mmr);
2006-
20071998
return 0;
20081999
}
20092000

@@ -2175,10 +2166,10 @@ static int mlx5_alloc_integrity_descs(struct ib_pd *pd, struct mlx5_ib_mr *mr,
21752166
destroy_mkey(dev, mr);
21762167
mlx5_free_priv_descs(mr);
21772168
err_free_mtt_mr:
2178-
dereg_mr(to_mdev(mr->mtt_mr->ibmr.device), mr->mtt_mr);
2169+
mlx5_ib_dereg_mr(&mr->mtt_mr->ibmr, NULL);
21792170
mr->mtt_mr = NULL;
21802171
err_free_klm_mr:
2181-
dereg_mr(to_mdev(mr->klm_mr->ibmr.device), mr->klm_mr);
2172+
mlx5_ib_dereg_mr(&mr->klm_mr->ibmr, NULL);
21822173
mr->klm_mr = NULL;
21832174
err_destroy_psv:
21842175
if (mlx5_core_destroy_psv(dev->mdev, mr->sig->psv_memory.psv_idx))

0 commit comments

Comments
 (0)