From: xiongweimin In mlx5_vdpa_change_map(), mlx5_vdpa_update_mr() is called before setup_vq_resources(), which releases the old MR and updates mres.mr[asid] to point to new_mr. If setup_vq_resources() then fails, the function returns an error but the MR pointer is already updated, leaving mres.mr[asid] pointing to a potentially invalid state. Fix by calling setup_vq_resources() before updating the MR pointer. On failure, the old MR is still intact and can be restored by the caller. Signed-off-by: xiongweimin --- drivers/vdpa/mlx5/net/mlx5_vnet.c | 24 ++++++++++++++++---------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index ad0d5fbbb..8a6ddc00b 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -3067,24 +3067,28 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, teardown_vq_resources(ndev); } - mlx5_vdpa_update_mr(mvdev, new_mr, asid); - for (int i = 0; i < mvdev->max_vqs; i++) ndev->vqs[i].modified_fields |= MLX5_VIRTQ_MODIFY_MASK_VIRTIO_Q_MKEY | MLX5_VIRTQ_MODIFY_MASK_DESC_GROUP_MKEY; if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK) || mvdev->suspended) - return 0; + goto done; if (teardown) { restore_channels_info(ndev); err = setup_vq_resources(ndev, true); if (err) - return err; + goto out_err; } resume_vqs(ndev, 0, ndev->cur_num_vqs); + goto done; +out_err: + return err; + +done: + mlx5_vdpa_update_mr(mvdev, new_mr, asid); return 0; } -- 2.39.3