1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2019 Mellanox Technologies, Ltd 3 */ 4 #include <rte_malloc.h> 5 #include <rte_errno.h> 6 7 #include "mlx5_vdpa_utils.h" 8 #include "mlx5_vdpa.h" 9 10 11 int 12 mlx5_vdpa_logging_enable(struct mlx5_vdpa_priv *priv, int enable) 13 { 14 struct mlx5_devx_virtq_attr attr = { 15 .type = MLX5_VIRTQ_MODIFY_TYPE_DIRTY_BITMAP_DUMP_ENABLE, 16 .dirty_bitmap_dump_enable = enable, 17 }; 18 int i; 19 20 for (i = 0; i < priv->nr_virtqs; ++i) { 21 attr.queue_index = i; 22 if (!priv->virtqs[i].virtq) { 23 DRV_LOG(DEBUG, "virtq %d is invalid for dirty bitmap " 24 "enabling.", i); 25 } else if (mlx5_devx_cmd_modify_virtq(priv->virtqs[i].virtq, 26 &attr)) { 27 DRV_LOG(ERR, "Failed to modify virtq %d for dirty " 28 "bitmap enabling.", i); 29 return -1; 30 } 31 } 32 return 0; 33 } 34 35 int 36 mlx5_vdpa_dirty_bitmap_set(struct mlx5_vdpa_priv *priv, uint64_t log_base, 37 uint64_t log_size) 38 { 39 struct mlx5_devx_mkey_attr mkey_attr = { 40 .addr = (uintptr_t)log_base, 41 .size = log_size, 42 .pd = priv->pdn, 43 .pg_access = 1, 44 .klm_array = NULL, 45 .klm_num = 0, 46 .relaxed_ordering_read = 0, 47 .relaxed_ordering_write = 0, 48 }; 49 struct mlx5_devx_virtq_attr attr = { 50 .type = MLX5_VIRTQ_MODIFY_TYPE_DIRTY_BITMAP_PARAMS, 51 .dirty_bitmap_addr = log_base, 52 .dirty_bitmap_size = log_size, 53 }; 54 struct mlx5_vdpa_query_mr *mr = rte_malloc(__func__, sizeof(*mr), 0); 55 int i; 56 57 if (!mr) { 58 DRV_LOG(ERR, "Failed to allocate mem for lm mr."); 59 return -1; 60 } 61 mr->umem = mlx5_glue->devx_umem_reg(priv->ctx, 62 (void *)(uintptr_t)log_base, 63 log_size, IBV_ACCESS_LOCAL_WRITE); 64 if (!mr->umem) { 65 DRV_LOG(ERR, "Failed to register umem for lm mr."); 66 goto err; 67 } 68 mkey_attr.umem_id = mr->umem->umem_id; 69 mr->mkey = mlx5_devx_cmd_mkey_create(priv->ctx, &mkey_attr); 70 if (!mr->mkey) { 71 DRV_LOG(ERR, "Failed to create Mkey for lm."); 72 goto err; 73 } 74 attr.dirty_bitmap_mkey = mr->mkey->id; 75 for (i = 0; i < priv->nr_virtqs; ++i) { 76 attr.queue_index = i; 77 if (!priv->virtqs[i].virtq) { 78 DRV_LOG(DEBUG, "virtq %d is invalid for LM.", i); 79 } else if (mlx5_devx_cmd_modify_virtq(priv->virtqs[i].virtq, 80 &attr)) { 81 DRV_LOG(ERR, "Failed to modify virtq %d for LM.", i); 82 goto err; 83 } 84 } 85 mr->is_indirect = 0; 86 SLIST_INSERT_HEAD(&priv->mr_list, mr, next); 87 return 0; 88 err: 89 if (mr->mkey) 90 mlx5_devx_cmd_destroy(mr->mkey); 91 if (mr->umem) 92 mlx5_glue->devx_umem_dereg(mr->umem); 93 rte_free(mr); 94 return -1; 95 } 96 97 #define MLX5_VDPA_USED_RING_LEN(size) \ 98 ((size) * sizeof(struct vring_used_elem) + sizeof(uint16_t) * 3) 99 100 int 101 mlx5_vdpa_lm_log(struct mlx5_vdpa_priv *priv) 102 { 103 uint64_t features; 104 int ret = rte_vhost_get_negotiated_features(priv->vid, &features); 105 int i; 106 107 if (ret) { 108 DRV_LOG(ERR, "Failed to get negotiated features."); 109 return -1; 110 } 111 if (!RTE_VHOST_NEED_LOG(features)) 112 return 0; 113 for (i = 0; i < priv->nr_virtqs; ++i) { 114 if (!priv->virtqs[i].virtq) { 115 DRV_LOG(DEBUG, "virtq %d is invalid for LM log.", i); 116 } else { 117 ret = mlx5_vdpa_virtq_stop(priv, i); 118 if (ret) { 119 DRV_LOG(ERR, "Failed to stop virtq %d for LM " 120 "log.", i); 121 return -1; 122 } 123 } 124 rte_vhost_log_used_vring(priv->vid, i, 0, 125 MLX5_VDPA_USED_RING_LEN(priv->virtqs[i].vq_size)); 126 } 127 return 0; 128 } 129