Skip to content

Commit 651cdaa

Browse files
dtatuleamstsirkin
authored andcommitted
vdpa/mlx5: Allow modifying multiple vq fields in one modify command
Add a bitmask variable that tracks hw vq field changes that are supposed to be modified on next hw vq change command. This will be useful to set multiple vq fields when resuming the vq. 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-3-dtatulea@nvidia.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
1 parent ef06719 commit 651cdaa

1 file changed

Lines changed: 40 additions & 8 deletions

File tree

drivers/vdpa/mlx5/net/mlx5_vnet.c

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ struct mlx5_vdpa_virtqueue {
120120
u16 avail_idx;
121121
u16 used_idx;
122122
int fw_state;
123+
124+
u64 modified_fields;
125+
123126
struct msi_map map;
124127

125128
/* keep last in the struct */
@@ -1181,7 +1184,19 @@ static bool is_valid_state_change(int oldstate, int newstate)
11811184
}
11821185
}
11831186

1184-
static int modify_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq, int state)
1187+
static bool modifiable_virtqueue_fields(struct mlx5_vdpa_virtqueue *mvq)
1188+
{
1189+
/* Only state is always modifiable */
1190+
if (mvq->modified_fields & ~MLX5_VIRTQ_MODIFY_MASK_STATE)
1191+
return mvq->fw_state == MLX5_VIRTIO_NET_Q_OBJECT_STATE_INIT ||
1192+
mvq->fw_state == MLX5_VIRTIO_NET_Q_OBJECT_STATE_SUSPEND;
1193+
1194+
return true;
1195+
}
1196+
1197+
static int modify_virtqueue(struct mlx5_vdpa_net *ndev,
1198+
struct mlx5_vdpa_virtqueue *mvq,
1199+
int state)
11851200
{
11861201
int inlen = MLX5_ST_SZ_BYTES(modify_virtio_net_q_in);
11871202
u32 out[MLX5_ST_SZ_DW(modify_virtio_net_q_out)] = {};
@@ -1193,6 +1208,9 @@ static int modify_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque
11931208
if (mvq->fw_state == MLX5_VIRTIO_NET_Q_OBJECT_NONE)
11941209
return 0;
11951210

1211+
if (!modifiable_virtqueue_fields(mvq))
1212+
return -EINVAL;
1213+
11961214
if (!is_valid_state_change(mvq->fw_state, state))
11971215
return -EINVAL;
11981216

@@ -1208,17 +1226,28 @@ static int modify_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque
12081226
MLX5_SET(general_obj_in_cmd_hdr, cmd_hdr, uid, ndev->mvdev.res.uid);
12091227

12101228
obj_context = MLX5_ADDR_OF(modify_virtio_net_q_in, in, obj_context);
1211-
MLX5_SET64(virtio_net_q_object, obj_context, modify_field_select,
1212-
MLX5_VIRTQ_MODIFY_MASK_STATE);
1213-
MLX5_SET(virtio_net_q_object, obj_context, state, state);
1229+
if (mvq->modified_fields & MLX5_VIRTQ_MODIFY_MASK_STATE)
1230+
MLX5_SET(virtio_net_q_object, obj_context, state, state);
1231+
1232+
MLX5_SET64(virtio_net_q_object, obj_context, modify_field_select, mvq->modified_fields);
12141233
err = mlx5_cmd_exec(ndev->mvdev.mdev, in, inlen, out, sizeof(out));
12151234
kfree(in);
12161235
if (!err)
12171236
mvq->fw_state = state;
12181237

1238+
mvq->modified_fields = 0;
1239+
12191240
return err;
12201241
}
12211242

1243+
static int modify_virtqueue_state(struct mlx5_vdpa_net *ndev,
1244+
struct mlx5_vdpa_virtqueue *mvq,
1245+
unsigned int state)
1246+
{
1247+
mvq->modified_fields |= MLX5_VIRTQ_MODIFY_MASK_STATE;
1248+
return modify_virtqueue(ndev, mvq, state);
1249+
}
1250+
12221251
static int counter_set_alloc(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq)
12231252
{
12241253
u32 in[MLX5_ST_SZ_DW(create_virtio_q_counters_in)] = {};
@@ -1347,7 +1376,7 @@ static int setup_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq)
13471376
goto err_vq;
13481377

13491378
if (mvq->ready) {
1350-
err = modify_virtqueue(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY);
1379+
err = modify_virtqueue_state(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY);
13511380
if (err) {
13521381
mlx5_vdpa_warn(&ndev->mvdev, "failed to modify to ready vq idx %d(%d)\n",
13531382
idx, err);
@@ -1382,7 +1411,7 @@ static void suspend_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *m
13821411
if (mvq->fw_state != MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY)
13831412
return;
13841413

1385-
if (modify_virtqueue(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_SUSPEND))
1414+
if (modify_virtqueue_state(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_SUSPEND))
13861415
mlx5_vdpa_warn(&ndev->mvdev, "modify to suspend failed\n");
13871416

13881417
if (query_virtqueue(ndev, mvq, &attr)) {
@@ -1407,6 +1436,7 @@ static void teardown_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *
14071436
return;
14081437

14091438
suspend_vq(ndev, mvq);
1439+
mvq->modified_fields = 0;
14101440
destroy_virtqueue(ndev, mvq);
14111441
dealloc_vector(ndev, mvq);
14121442
counter_set_dealloc(ndev, mvq);
@@ -2207,7 +2237,7 @@ static void mlx5_vdpa_set_vq_ready(struct vdpa_device *vdev, u16 idx, bool ready
22072237
if (!ready) {
22082238
suspend_vq(ndev, mvq);
22092239
} else {
2210-
err = modify_virtqueue(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY);
2240+
err = modify_virtqueue_state(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY);
22112241
if (err) {
22122242
mlx5_vdpa_warn(mvdev, "modify VQ %d to ready failed (%d)\n", idx, err);
22132243
ready = false;
@@ -2804,8 +2834,10 @@ static void clear_vqs_ready(struct mlx5_vdpa_net *ndev)
28042834
{
28052835
int i;
28062836

2807-
for (i = 0; i < ndev->mvdev.max_vqs; i++)
2837+
for (i = 0; i < ndev->mvdev.max_vqs; i++) {
28082838
ndev->vqs[i].ready = false;
2839+
ndev->vqs[i].modified_fields = 0;
2840+
}
28092841

28102842
ndev->mvdev.cvq.ready = false;
28112843
}

0 commit comments

Comments
 (0)