Skip to content

Commit 8383da3

Browse files
committed
RDMA/mlx5: Clarify what the UMR is for when creating MRs
Once a mkey is created it can be modified using UMR. This is desirable for performance reasons. However, different hardware has restrictions on what modifications are possible using UMR. Make sense of these checks: - mlx5_ib_can_reconfig_with_umr() returns true if the access flags can be altered. Most cases create MRs using 0 access flags (now made clear by consistent use of set_mkc_access_pd_addr_fields()), but the old logic here was tormented. Make it clear that this is checking if the current access_flags can be modified using UMR to different access_flags. It is always OK to use UMR to change flags that all HW supports. - mlx5_ib_can_load_pas_with_umr() returns true if UMR can be used to enable and update the PAS/XLT. Enabling requires updating the entity size, so UMR ends up completely disabled on this old hardware. Make it clear why it is disabled. FRWR, ODP and cache always requires mlx5_ib_can_load_pas_with_umr(). - mlx5_ib_pas_fits_in_mr() is used to tell if an existing MR can be resized to hold a new PAS list. This only works for cached MR's because we don't store the PAS list size in other cases. To be very clear, arrange things so any pre-created MR's in the cache check the newly requested access_flags before allowing the MR to leave the cache. If UMR cannot set the required access_flags the cache fails to create the MR. This in turn means relaxed ordering and atomic are now correctly blocked early for implicit ODP on older HW. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 0ec52f0 commit 8383da3

File tree

4 files changed

+97
-49
lines changed

4 files changed

+97
-49
lines changed

drivers/infiniband/hw/mlx5/mlx5_ib.h

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,7 +1231,7 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev);
12311231
int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev);
12321232

12331233
struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev,
1234-
unsigned int entry);
1234+
unsigned int entry, int access_flags);
12351235
void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
12361236
int mlx5_mr_cache_invalidate(struct mlx5_ib_mr *mr);
12371237

@@ -1444,25 +1444,54 @@ int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
14441444
struct mlx5_bfreg_info *bfregi, u32 bfregn,
14451445
bool dyn_bfreg);
14461446

1447-
static inline bool mlx5_ib_can_use_umr(struct mlx5_ib_dev *dev,
1448-
bool do_modify_atomic, int access_flags)
1447+
static inline bool mlx5_ib_can_load_pas_with_umr(struct mlx5_ib_dev *dev,
1448+
size_t length)
14491449
{
1450+
/*
1451+
* umr_check_mkey_mask() rejects MLX5_MKEY_MASK_PAGE_SIZE which is
1452+
* always set if MLX5_IB_SEND_UMR_UPDATE_TRANSLATION (aka
1453+
* MLX5_IB_UPD_XLT_ADDR and MLX5_IB_UPD_XLT_ENABLE) is set. Thus, a mkey
1454+
* can never be enabled without this capability. Simplify this weird
1455+
* quirky hardware by just saying it can't use PAS lists with UMR at
1456+
* all.
1457+
*/
14501458
if (MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))
14511459
return false;
14521460

1453-
if (do_modify_atomic &&
1461+
/*
1462+
* length is the size of the MR in bytes when mlx5_ib_update_xlt() is
1463+
* used.
1464+
*/
1465+
if (!MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset) &&
1466+
length >= MLX5_MAX_UMR_PAGES * PAGE_SIZE)
1467+
return false;
1468+
return true;
1469+
}
1470+
1471+
/*
1472+
* true if an existing MR can be reconfigured to new access_flags using UMR.
1473+
* Older HW cannot use UMR to update certain elements of the MKC. See
1474+
* umr_check_mkey_mask(), get_umr_update_access_mask() and umr_check_mkey_mask()
1475+
*/
1476+
static inline bool mlx5_ib_can_reconfig_with_umr(struct mlx5_ib_dev *dev,
1477+
unsigned int current_access_flags,
1478+
unsigned int target_access_flags)
1479+
{
1480+
unsigned int diffs = current_access_flags ^ target_access_flags;
1481+
1482+
if ((diffs & IB_ACCESS_REMOTE_ATOMIC) &&
14541483
MLX5_CAP_GEN(dev->mdev, atomic) &&
14551484
MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled))
14561485
return false;
14571486

1458-
if (access_flags & IB_ACCESS_RELAXED_ORDERING &&
1487+
if ((diffs & IB_ACCESS_RELAXED_ORDERING) &&
14591488
MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write) &&
14601489
!MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr))
14611490
return false;
14621491

1463-
if (access_flags & IB_ACCESS_RELAXED_ORDERING &&
1464-
MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read) &&
1465-
!MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))
1492+
if ((diffs & IB_ACCESS_RELAXED_ORDERING) &&
1493+
MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read) &&
1494+
!MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))
14661495
return false;
14671496

14681497
return true;

drivers/infiniband/hw/mlx5/mr.c

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
123123
return mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
124124
}
125125

126-
static bool use_umr_mtt_update(struct mlx5_ib_mr *mr, u64 start, u64 length)
126+
static inline bool mlx5_ib_pas_fits_in_mr(struct mlx5_ib_mr *mr, u64 start,
127+
u64 length)
127128
{
128129
return ((u64)1 << mr->order) * MLX5_ADAPTER_PAGE_SIZE >=
129130
length + (start & (MLX5_ADAPTER_PAGE_SIZE - 1));
@@ -557,7 +558,7 @@ static void cache_work_func(struct work_struct *work)
557558

558559
/* Allocate a special entry from the cache */
559560
struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev,
560-
unsigned int entry)
561+
unsigned int entry, int access_flags)
561562
{
562563
struct mlx5_mr_cache *cache = &dev->cache;
563564
struct mlx5_cache_ent *ent;
@@ -567,6 +568,10 @@ struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev,
567568
entry >= ARRAY_SIZE(cache->ent)))
568569
return ERR_PTR(-EINVAL);
569570

571+
/* Matches access in alloc_cache_mr() */
572+
if (!mlx5_ib_can_reconfig_with_umr(dev, 0, access_flags))
573+
return ERR_PTR(-EOPNOTSUPP);
574+
570575
ent = &cache->ent[entry];
571576
spin_lock_irq(&ent->lock);
572577
if (list_empty(&ent->head)) {
@@ -581,6 +586,7 @@ struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev,
581586
queue_adjust_cache_locked(ent);
582587
spin_unlock_irq(&ent->lock);
583588
}
589+
mr->access_flags = access_flags;
584590
return mr;
585591
}
586592

@@ -753,8 +759,8 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
753759
MLX5_IB_UMR_OCTOWORD;
754760
ent->access_mode = MLX5_MKC_ACCESS_MODE_MTT;
755761
if ((dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE) &&
756-
!dev->is_rep &&
757-
mlx5_core_is_pf(dev->mdev))
762+
!dev->is_rep && mlx5_core_is_pf(dev->mdev) &&
763+
mlx5_ib_can_load_pas_with_umr(dev, 0))
758764
ent->limit = dev->mdev->profile->mr_cache[i].limit;
759765
else
760766
ent->limit = 0;
@@ -979,6 +985,11 @@ alloc_mr_from_cache(struct ib_pd *pd, struct ib_umem *umem, u64 virt_addr,
979985

980986
if (!ent)
981987
return ERR_PTR(-E2BIG);
988+
989+
/* Matches access in alloc_cache_mr() */
990+
if (!mlx5_ib_can_reconfig_with_umr(dev, 0, access_flags))
991+
return ERR_PTR(-EOPNOTSUPP);
992+
982993
mr = get_cache_mr(ent);
983994
if (!mr) {
984995
mr = create_cache_mr(ent);
@@ -1181,9 +1192,14 @@ static struct mlx5_ib_mr *reg_create(struct ib_mr *ibmr, struct ib_pd *pd,
11811192
goto err_1;
11821193
}
11831194
pas = (__be64 *)MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt);
1184-
if (populate && !(access_flags & IB_ACCESS_ON_DEMAND))
1195+
if (populate) {
1196+
if (WARN_ON(access_flags & IB_ACCESS_ON_DEMAND)) {
1197+
err = -EINVAL;
1198+
goto err_2;
1199+
}
11851200
mlx5_ib_populate_pas(dev, umem, page_shift, pas,
11861201
pg_cap ? MLX5_IB_MTT_PRESENT : 0);
1202+
}
11871203

11881204
/* The pg_access bit allows setting the access flags
11891205
* in the page list submitted with the command. */
@@ -1341,7 +1357,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
13411357
{
13421358
struct mlx5_ib_dev *dev = to_mdev(pd->device);
13431359
struct mlx5_ib_mr *mr = NULL;
1344-
bool use_umr;
1360+
bool xlt_with_umr;
13451361
struct ib_umem *umem;
13461362
int page_shift;
13471363
int npages;
@@ -1355,6 +1371,11 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
13551371
mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx, access_flags 0x%x\n",
13561372
start, virt_addr, length, access_flags);
13571373

1374+
xlt_with_umr = mlx5_ib_can_load_pas_with_umr(dev, length);
1375+
/* ODP requires xlt update via umr to work. */
1376+
if (!xlt_with_umr && (access_flags & IB_ACCESS_ON_DEMAND))
1377+
return ERR_PTR(-EINVAL);
1378+
13581379
if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING) && !start &&
13591380
length == U64_MAX) {
13601381
if (virt_addr != start)
@@ -1375,26 +1396,17 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
13751396
if (err < 0)
13761397
return ERR_PTR(err);
13771398

1378-
use_umr = mlx5_ib_can_use_umr(dev, true, access_flags);
1379-
1380-
if (order <= mr_cache_max_order(dev) && use_umr) {
1399+
if (xlt_with_umr) {
13811400
mr = alloc_mr_from_cache(pd, umem, virt_addr, length, ncont,
13821401
page_shift, order, access_flags);
13831402
if (IS_ERR(mr))
13841403
mr = NULL;
1385-
} else if (!MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset)) {
1386-
if (access_flags & IB_ACCESS_ON_DEMAND) {
1387-
err = -EINVAL;
1388-
pr_err("Got MR registration for ODP MR > 512MB, not supported for Connect-IB\n");
1389-
goto error;
1390-
}
1391-
use_umr = false;
13921404
}
13931405

13941406
if (!mr) {
13951407
mutex_lock(&dev->slow_path_mutex);
13961408
mr = reg_create(NULL, pd, virt_addr, length, umem, ncont,
1397-
page_shift, access_flags, !use_umr);
1409+
page_shift, access_flags, !xlt_with_umr);
13981410
mutex_unlock(&dev->slow_path_mutex);
13991411
}
14001412

@@ -1408,15 +1420,19 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
14081420
mr->umem = umem;
14091421
set_mr_fields(dev, mr, npages, length, access_flags);
14101422

1411-
if (use_umr) {
1423+
if (xlt_with_umr) {
1424+
/*
1425+
* If the MR was created with reg_create then it will be
1426+
* configured properly but left disabled. It is safe to go ahead
1427+
* and configure it again via UMR while enabling it.
1428+
*/
14121429
int update_xlt_flags = MLX5_IB_UPD_XLT_ENABLE;
14131430

14141431
if (access_flags & IB_ACCESS_ON_DEMAND)
14151432
update_xlt_flags |= MLX5_IB_UPD_XLT_ZAP;
14161433

14171434
err = mlx5_ib_update_xlt(mr, 0, ncont, page_shift,
14181435
update_xlt_flags);
1419-
14201436
if (err) {
14211437
dereg_mr(dev, mr);
14221438
return ERR_PTR(err);
@@ -1541,8 +1557,11 @@ int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
15411557
goto err;
15421558
}
15431559

1544-
if (!mlx5_ib_can_use_umr(dev, true, access_flags) ||
1545-
(flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len))) {
1560+
if (!mlx5_ib_can_reconfig_with_umr(dev, mr->access_flags,
1561+
access_flags) ||
1562+
!mlx5_ib_can_load_pas_with_umr(dev, len) ||
1563+
(flags & IB_MR_REREG_TRANS &&
1564+
!mlx5_ib_pas_fits_in_mr(mr, addr, len))) {
15461565
/*
15471566
* UMR can't be used - MKey needs to be replaced.
15481567
*/
@@ -1713,9 +1732,9 @@ static void mlx5_set_umr_free_mkey(struct ib_pd *pd, u32 *in, int ndescs,
17131732

17141733
mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
17151734

1735+
/* This is only used from the kernel, so setting the PD is OK. */
1736+
set_mkc_access_pd_addr_fields(mkc, 0, 0, pd);
17161737
MLX5_SET(mkc, mkc, free, 1);
1717-
MLX5_SET(mkc, mkc, qpn, 0xffffff);
1718-
MLX5_SET(mkc, mkc, pd, to_mpd(pd)->pdn);
17191738
MLX5_SET(mkc, mkc, translations_octword_size, ndescs);
17201739
MLX5_SET(mkc, mkc, access_mode_1_0, access_mode & 0x3);
17211740
MLX5_SET(mkc, mkc, access_mode_4_2, (access_mode >> 2) & 0x7);

drivers/infiniband/hw/mlx5/odp.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
382382
memset(caps, 0, sizeof(*caps));
383383

384384
if (!MLX5_CAP_GEN(dev->mdev, pg) ||
385-
!mlx5_ib_can_use_umr(dev, true, 0))
385+
!mlx5_ib_can_load_pas_with_umr(dev, 0))
386386
return;
387387

388388
caps->general_caps = IB_ODP_SUPPORT;
@@ -476,12 +476,12 @@ static struct mlx5_ib_mr *implicit_get_child_mr(struct mlx5_ib_mr *imr,
476476
if (IS_ERR(odp))
477477
return ERR_CAST(odp);
478478

479-
ret = mr = mlx5_mr_cache_alloc(imr->dev, MLX5_IMR_MTT_CACHE_ENTRY);
479+
ret = mr = mlx5_mr_cache_alloc(imr->dev, MLX5_IMR_MTT_CACHE_ENTRY,
480+
imr->access_flags);
480481
if (IS_ERR(mr))
481482
goto out_umem;
482483

483484
mr->ibmr.pd = imr->ibmr.pd;
484-
mr->access_flags = imr->access_flags;
485485
mr->umem = &odp->umem;
486486
mr->ibmr.lkey = mr->mmkey.key;
487487
mr->ibmr.rkey = mr->mmkey.key;
@@ -540,14 +540,13 @@ struct mlx5_ib_mr *mlx5_ib_alloc_implicit_mr(struct mlx5_ib_pd *pd,
540540
if (IS_ERR(umem_odp))
541541
return ERR_CAST(umem_odp);
542542

543-
imr = mlx5_mr_cache_alloc(dev, MLX5_IMR_KSM_CACHE_ENTRY);
543+
imr = mlx5_mr_cache_alloc(dev, MLX5_IMR_KSM_CACHE_ENTRY, access_flags);
544544
if (IS_ERR(imr)) {
545545
err = PTR_ERR(imr);
546546
goto out_umem;
547547
}
548548

549549
imr->ibmr.pd = &pd->ibpd;
550-
imr->access_flags = access_flags;
551550
imr->mmkey.iova = 0;
552551
imr->umem = &umem_odp->umem;
553552
imr->ibmr.lkey = imr->mmkey.key;

drivers/infiniband/hw/mlx5/wr.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,8 @@ static void set_linv_mkey_seg(struct mlx5_mkey_seg *seg)
398398
seg->status = MLX5_MKEY_STATUS_FREE;
399399
}
400400

401-
static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg,
401+
static void set_reg_mkey_segment(struct mlx5_ib_dev *dev,
402+
struct mlx5_mkey_seg *seg,
402403
const struct ib_send_wr *wr)
403404
{
404405
const struct mlx5_umr_wr *umrwr = umr_wr(wr);
@@ -414,10 +415,12 @@ static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg,
414415
MLX5_SET(mkc, seg, rr, !!(umrwr->access_flags & IB_ACCESS_REMOTE_READ));
415416
MLX5_SET(mkc, seg, lw, !!(umrwr->access_flags & IB_ACCESS_LOCAL_WRITE));
416417
MLX5_SET(mkc, seg, lr, 1);
417-
MLX5_SET(mkc, seg, relaxed_ordering_write,
418-
!!(umrwr->access_flags & IB_ACCESS_RELAXED_ORDERING));
419-
MLX5_SET(mkc, seg, relaxed_ordering_read,
420-
!!(umrwr->access_flags & IB_ACCESS_RELAXED_ORDERING));
418+
if (MLX5_CAP_GEN(dev->mdev, relaxed_ordering_write_umr))
419+
MLX5_SET(mkc, seg, relaxed_ordering_write,
420+
!!(umrwr->access_flags & IB_ACCESS_RELAXED_ORDERING));
421+
if (MLX5_CAP_GEN(dev->mdev, relaxed_ordering_read_umr))
422+
MLX5_SET(mkc, seg, relaxed_ordering_read,
423+
!!(umrwr->access_flags & IB_ACCESS_RELAXED_ORDERING));
421424

422425
if (umrwr->pd)
423426
MLX5_SET(mkc, seg, pd, to_mpd(umrwr->pd)->pdn);
@@ -863,13 +866,11 @@ static int set_reg_wr(struct mlx5_ib_qp *qp,
863866
bool atomic = wr->access & IB_ACCESS_REMOTE_ATOMIC;
864867
u8 flags = 0;
865868

866-
if (!mlx5_ib_can_use_umr(dev, atomic, wr->access)) {
867-
mlx5_ib_warn(to_mdev(qp->ibqp.device),
868-
"Fast update of %s for MR is disabled\n",
869-
(MLX5_CAP_GEN(dev->mdev,
870-
umr_modify_entity_size_disabled)) ?
871-
"entity size" :
872-
"atomic access");
869+
/* Matches access in mlx5_set_umr_free_mkey() */
870+
if (!mlx5_ib_can_reconfig_with_umr(dev, 0, wr->access)) {
871+
mlx5_ib_warn(
872+
to_mdev(qp->ibqp.device),
873+
"Fast update for MR access flags is not possible\n");
873874
return -EINVAL;
874875
}
875876

@@ -1263,7 +1264,7 @@ static int handle_qpt_reg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
12631264
*seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
12641265
*size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
12651266
handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
1266-
set_reg_mkey_segment(*seg, wr);
1267+
set_reg_mkey_segment(dev, *seg, wr);
12671268
*seg += sizeof(struct mlx5_mkey_seg);
12681269
*size += sizeof(struct mlx5_mkey_seg) / 16;
12691270
handle_post_send_edge(&qp->sq, seg, *size, cur_edge);

0 commit comments

Comments
 (0)