Skip to content

Commit a06bd11

Browse files
dtatuleamstsirkin
authored andcommitted
vdpa/mlx5: Introduce reference counting to mrs
Deleting the old mr during mr update (.set_map) and then modifying the vqs with the new mr is not a good flow for firmware. The firmware expects that mkeys are deleted after there are no more vqs referencing them. Introduce reference counting for mrs to fix this. It is the only way to make sure that mkeys are not in use by vqs. An mr reference is taken when the mr is associated to the mr asid table and when the mr is linked to the vq on create/modify. The reference is released when the mkey is unlinked from the vq (trough modify/destroy) and from the mr asid table. To make things consistent, get rid of mlx5_vdpa_destroy_mr and use get/put semantics everywhere. Reviewed-by: Gal Pressman <gal@nvidia.com> Acked-by: Eugenio Pérez <eperezma@redhat.com> Acked-by: Jason Wang <jasowang@redhat.com> Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com> Message-Id: <20231225151203.152687-8-dtatulea@nvidia.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
1 parent f756dd3 commit a06bd11

3 files changed

Lines changed: 78 additions & 25 deletions

File tree

drivers/vdpa/mlx5/core/mlx5_vdpa.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ struct mlx5_vdpa_mr {
3535
struct vhost_iotlb *iotlb;
3636

3737
bool user_mr;
38+
39+
refcount_t refcount;
3840
};
3941

4042
struct mlx5_vdpa_resources {
@@ -118,8 +120,10 @@ int mlx5_vdpa_destroy_mkey(struct mlx5_vdpa_dev *mvdev, u32 mkey);
118120
struct mlx5_vdpa_mr *mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
119121
struct vhost_iotlb *iotlb);
120122
void mlx5_vdpa_destroy_mr_resources(struct mlx5_vdpa_dev *mvdev);
121-
void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev,
122-
struct mlx5_vdpa_mr *mr);
123+
void mlx5_vdpa_get_mr(struct mlx5_vdpa_dev *mvdev,
124+
struct mlx5_vdpa_mr *mr);
125+
void mlx5_vdpa_put_mr(struct mlx5_vdpa_dev *mvdev,
126+
struct mlx5_vdpa_mr *mr);
123127
void mlx5_vdpa_update_mr(struct mlx5_vdpa_dev *mvdev,
124128
struct mlx5_vdpa_mr *mr,
125129
unsigned int asid);

drivers/vdpa/mlx5/core/mr.c

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -498,32 +498,52 @@ static void destroy_user_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr
498498

499499
static void _mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr)
500500
{
501+
if (WARN_ON(!mr))
502+
return;
503+
501504
if (mr->user_mr)
502505
destroy_user_mr(mvdev, mr);
503506
else
504507
destroy_dma_mr(mvdev, mr);
505508

506509
vhost_iotlb_free(mr->iotlb);
510+
511+
kfree(mr);
507512
}
508513

509-
void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev,
510-
struct mlx5_vdpa_mr *mr)
514+
static void _mlx5_vdpa_put_mr(struct mlx5_vdpa_dev *mvdev,
515+
struct mlx5_vdpa_mr *mr)
511516
{
512517
if (!mr)
513518
return;
514519

520+
if (refcount_dec_and_test(&mr->refcount))
521+
_mlx5_vdpa_destroy_mr(mvdev, mr);
522+
}
523+
524+
void mlx5_vdpa_put_mr(struct mlx5_vdpa_dev *mvdev,
525+
struct mlx5_vdpa_mr *mr)
526+
{
515527
mutex_lock(&mvdev->mr_mtx);
528+
_mlx5_vdpa_put_mr(mvdev, mr);
529+
mutex_unlock(&mvdev->mr_mtx);
530+
}
516531

517-
_mlx5_vdpa_destroy_mr(mvdev, mr);
532+
static void _mlx5_vdpa_get_mr(struct mlx5_vdpa_dev *mvdev,
533+
struct mlx5_vdpa_mr *mr)
534+
{
535+
if (!mr)
536+
return;
518537

519-
for (int i = 0; i < MLX5_VDPA_NUM_AS; i++) {
520-
if (mvdev->mr[i] == mr)
521-
mvdev->mr[i] = NULL;
522-
}
538+
refcount_inc(&mr->refcount);
539+
}
523540

541+
void mlx5_vdpa_get_mr(struct mlx5_vdpa_dev *mvdev,
542+
struct mlx5_vdpa_mr *mr)
543+
{
544+
mutex_lock(&mvdev->mr_mtx);
545+
_mlx5_vdpa_get_mr(mvdev, mr);
524546
mutex_unlock(&mvdev->mr_mtx);
525-
526-
kfree(mr);
527547
}
528548

529549
void mlx5_vdpa_update_mr(struct mlx5_vdpa_dev *mvdev,
@@ -534,20 +554,16 @@ void mlx5_vdpa_update_mr(struct mlx5_vdpa_dev *mvdev,
534554

535555
mutex_lock(&mvdev->mr_mtx);
536556

557+
_mlx5_vdpa_put_mr(mvdev, old_mr);
537558
mvdev->mr[asid] = new_mr;
538-
if (old_mr) {
539-
_mlx5_vdpa_destroy_mr(mvdev, old_mr);
540-
kfree(old_mr);
541-
}
542559

543560
mutex_unlock(&mvdev->mr_mtx);
544-
545561
}
546562

547563
void mlx5_vdpa_destroy_mr_resources(struct mlx5_vdpa_dev *mvdev)
548564
{
549565
for (int i = 0; i < MLX5_VDPA_NUM_AS; i++)
550-
mlx5_vdpa_destroy_mr(mvdev, mvdev->mr[i]);
566+
mlx5_vdpa_update_mr(mvdev, NULL, i);
551567

552568
prune_iotlb(mvdev->cvq.iotlb);
553569
}
@@ -607,6 +623,8 @@ struct mlx5_vdpa_mr *mlx5_vdpa_create_mr(struct mlx5_vdpa_dev *mvdev,
607623
if (err)
608624
goto out_err;
609625

626+
refcount_set(&mr->refcount, 1);
627+
610628
return mr;
611629

612630
out_err:
@@ -651,7 +669,7 @@ int mlx5_vdpa_reset_mr(struct mlx5_vdpa_dev *mvdev, unsigned int asid)
651669
if (asid >= MLX5_VDPA_NUM_AS)
652670
return -EINVAL;
653671

654-
mlx5_vdpa_destroy_mr(mvdev, mvdev->mr[asid]);
672+
mlx5_vdpa_update_mr(mvdev, NULL, asid);
655673

656674
if (asid == 0 && MLX5_CAP_GEN(mvdev->mdev, umem_uid_0)) {
657675
if (mlx5_vdpa_create_dma_mr(mvdev))

drivers/vdpa/mlx5/net/mlx5_vnet.c

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ struct mlx5_vdpa_virtqueue {
123123

124124
u64 modified_fields;
125125

126+
struct mlx5_vdpa_mr *vq_mr;
127+
struct mlx5_vdpa_mr *desc_mr;
128+
126129
struct msi_map map;
127130

128131
/* keep last in the struct */
@@ -946,6 +949,14 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque
946949
kfree(in);
947950
mvq->virtq_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
948951

952+
mlx5_vdpa_get_mr(mvdev, vq_mr);
953+
mvq->vq_mr = vq_mr;
954+
955+
if (vq_desc_mr && MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, desc_group_mkey_supported)) {
956+
mlx5_vdpa_get_mr(mvdev, vq_desc_mr);
957+
mvq->desc_mr = vq_desc_mr;
958+
}
959+
949960
return 0;
950961

951962
err_cmd:
@@ -972,6 +983,12 @@ static void destroy_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtq
972983
}
973984
mvq->fw_state = MLX5_VIRTIO_NET_Q_OBJECT_NONE;
974985
umems_destroy(ndev, mvq);
986+
987+
mlx5_vdpa_put_mr(&ndev->mvdev, mvq->vq_mr);
988+
mvq->vq_mr = NULL;
989+
990+
mlx5_vdpa_put_mr(&ndev->mvdev, mvq->desc_mr);
991+
mvq->desc_mr = NULL;
975992
}
976993

977994
static u32 get_rqpn(struct mlx5_vdpa_virtqueue *mvq, bool fw)
@@ -1207,6 +1224,8 @@ static int modify_virtqueue(struct mlx5_vdpa_net *ndev,
12071224
int inlen = MLX5_ST_SZ_BYTES(modify_virtio_net_q_in);
12081225
u32 out[MLX5_ST_SZ_DW(modify_virtio_net_q_out)] = {};
12091226
struct mlx5_vdpa_dev *mvdev = &ndev->mvdev;
1227+
struct mlx5_vdpa_mr *desc_mr = NULL;
1228+
struct mlx5_vdpa_mr *vq_mr = NULL;
12101229
bool state_change = false;
12111230
void *obj_context;
12121231
void *cmd_hdr;
@@ -1257,19 +1276,19 @@ static int modify_virtqueue(struct mlx5_vdpa_net *ndev,
12571276
MLX5_SET(virtio_net_q_object, obj_context, hw_used_index, mvq->used_idx);
12581277

12591278
if (mvq->modified_fields & MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_MKEY) {
1260-
struct mlx5_vdpa_mr *mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]];
1279+
vq_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_GROUP]];
12611280

1262-
if (mr)
1263-
MLX5_SET(virtio_q, vq_ctx, virtio_q_mkey, mr->mkey);
1281+
if (vq_mr)
1282+
MLX5_SET(virtio_q, vq_ctx, virtio_q_mkey, vq_mr->mkey);
12641283
else
12651284
mvq->modified_fields &= ~MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_MKEY;
12661285
}
12671286

12681287
if (mvq->modified_fields & MLX5_VIRTQ_MODIFY_MASK_DESC_GROUP_MKEY) {
1269-
struct mlx5_vdpa_mr *mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_DESC_GROUP]];
1288+
desc_mr = mvdev->mr[mvdev->group2asid[MLX5_VDPA_DATAVQ_DESC_GROUP]];
12701289

1271-
if (mr && MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, desc_group_mkey_supported))
1272-
MLX5_SET(virtio_q, vq_ctx, desc_group_mkey, mr->mkey);
1290+
if (desc_mr && MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, desc_group_mkey_supported))
1291+
MLX5_SET(virtio_q, vq_ctx, desc_group_mkey, desc_mr->mkey);
12731292
else
12741293
mvq->modified_fields &= ~MLX5_VIRTQ_MODIFY_MASK_DESC_GROUP_MKEY;
12751294
}
@@ -1282,6 +1301,18 @@ static int modify_virtqueue(struct mlx5_vdpa_net *ndev,
12821301
if (state_change)
12831302
mvq->fw_state = state;
12841303

1304+
if (mvq->modified_fields & MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_MKEY) {
1305+
mlx5_vdpa_put_mr(mvdev, mvq->vq_mr);
1306+
mlx5_vdpa_get_mr(mvdev, vq_mr);
1307+
mvq->vq_mr = vq_mr;
1308+
}
1309+
1310+
if (mvq->modified_fields & MLX5_VIRTQ_MODIFY_MASK_DESC_GROUP_MKEY) {
1311+
mlx5_vdpa_put_mr(mvdev, mvq->desc_mr);
1312+
mlx5_vdpa_get_mr(mvdev, desc_mr);
1313+
mvq->desc_mr = desc_mr;
1314+
}
1315+
12851316
mvq->modified_fields = 0;
12861317

12871318
done:
@@ -3095,7 +3126,7 @@ static int set_map_data(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb,
30953126
return mlx5_vdpa_update_cvq_iotlb(mvdev, iotlb, asid);
30963127

30973128
out_err:
3098-
mlx5_vdpa_destroy_mr(mvdev, new_mr);
3129+
mlx5_vdpa_put_mr(mvdev, new_mr);
30993130
return err;
31003131
}
31013132

0 commit comments

Comments
 (0)