From: xiongweimin <[email protected]>

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 <[email protected]>
---
 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


Reply via email to