1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2015 6WIND S.A. 3 * Copyright 2015 Mellanox. 4 */ 5 6 #include <stddef.h> 7 #include <stdint.h> 8 #include <errno.h> 9 #include <string.h> 10 #include <assert.h> 11 12 /* Verbs header. */ 13 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 14 #ifdef PEDANTIC 15 #pragma GCC diagnostic ignored "-Wpedantic" 16 #endif 17 #include <infiniband/verbs.h> 18 #ifdef PEDANTIC 19 #pragma GCC diagnostic error "-Wpedantic" 20 #endif 21 22 #include <rte_malloc.h> 23 #include <rte_ethdev_driver.h> 24 25 #include "mlx5.h" 26 #include "mlx5_defs.h" 27 #include "mlx5_rxtx.h" 28 29 /** 30 * DPDK callback to update the RSS hash configuration. 31 * 32 * @param dev 33 * Pointer to Ethernet device structure. 34 * @param[in] rss_conf 35 * RSS configuration data. 36 * 37 * @return 38 * 0 on success, negative errno value on failure. 39 */ 40 int 41 mlx5_rss_hash_update(struct rte_eth_dev *dev, 42 struct rte_eth_rss_conf *rss_conf) 43 { 44 struct priv *priv = dev->data->dev_private; 45 int ret = 0; 46 47 priv_lock(priv); 48 if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) { 49 ret = -EINVAL; 50 goto out; 51 } 52 if (rss_conf->rss_key && rss_conf->rss_key_len) { 53 priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key, 54 rss_conf->rss_key_len, 0); 55 if (!priv->rss_conf.rss_key) { 56 ret = -ENOMEM; 57 goto out; 58 } 59 memcpy(priv->rss_conf.rss_key, rss_conf->rss_key, 60 rss_conf->rss_key_len); 61 priv->rss_conf.rss_key_len = rss_conf->rss_key_len; 62 } 63 priv->rss_conf.rss_hf = rss_conf->rss_hf; 64 out: 65 priv_unlock(priv); 66 return ret; 67 } 68 69 /** 70 * DPDK callback to get the RSS hash configuration. 71 * 72 * @param dev 73 * Pointer to Ethernet device structure. 74 * @param[in, out] rss_conf 75 * RSS configuration data. 76 * 77 * @return 78 * 0 on success, negative errno value on failure. 79 */ 80 int 81 mlx5_rss_hash_conf_get(struct rte_eth_dev *dev, 82 struct rte_eth_rss_conf *rss_conf) 83 { 84 struct priv *priv = dev->data->dev_private; 85 86 if (!rss_conf) 87 return -EINVAL; 88 priv_lock(priv); 89 if (rss_conf->rss_key && 90 (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) { 91 memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, 92 priv->rss_conf.rss_key_len); 93 } 94 rss_conf->rss_key_len = priv->rss_conf.rss_key_len; 95 rss_conf->rss_hf = priv->rss_conf.rss_hf; 96 priv_unlock(priv); 97 return 0; 98 } 99 100 /** 101 * Allocate/reallocate RETA index table. 102 * 103 * @param priv 104 * Pointer to private structure. 105 * @praram reta_size 106 * The size of the array to allocate. 107 * 108 * @return 109 * 0 on success, errno value on failure. 110 */ 111 int 112 priv_rss_reta_index_resize(struct priv *priv, unsigned int reta_size) 113 { 114 void *mem; 115 unsigned int old_size = priv->reta_idx_n; 116 117 if (priv->reta_idx_n == reta_size) 118 return 0; 119 120 mem = rte_realloc(priv->reta_idx, 121 reta_size * sizeof((*priv->reta_idx)[0]), 0); 122 if (!mem) 123 return ENOMEM; 124 priv->reta_idx = mem; 125 priv->reta_idx_n = reta_size; 126 127 if (old_size < reta_size) 128 memset(&(*priv->reta_idx)[old_size], 0, 129 (reta_size - old_size) * 130 sizeof((*priv->reta_idx)[0])); 131 return 0; 132 } 133 134 /** 135 * Query RETA table. 136 * 137 * @param priv 138 * Pointer to private structure. 139 * @param[in, out] reta_conf 140 * Pointer to the first RETA configuration structure. 141 * @param reta_size 142 * Number of entries. 143 * 144 * @return 145 * 0 on success, errno value on failure. 146 */ 147 static int 148 priv_dev_rss_reta_query(struct priv *priv, 149 struct rte_eth_rss_reta_entry64 *reta_conf, 150 unsigned int reta_size) 151 { 152 unsigned int idx; 153 unsigned int i; 154 155 if (!reta_size || reta_size > priv->reta_idx_n) 156 return EINVAL; 157 /* Fill each entry of the table even if its bit is not set. */ 158 for (idx = 0, i = 0; (i != reta_size); ++i) { 159 idx = i / RTE_RETA_GROUP_SIZE; 160 reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = 161 (*priv->reta_idx)[i]; 162 } 163 return 0; 164 } 165 166 /** 167 * Update RETA table. 168 * 169 * @param priv 170 * Pointer to private structure. 171 * @param[in] reta_conf 172 * Pointer to the first RETA configuration structure. 173 * @param reta_size 174 * Number of entries. 175 * 176 * @return 177 * 0 on success, errno value on failure. 178 */ 179 static int 180 priv_dev_rss_reta_update(struct priv *priv, 181 struct rte_eth_rss_reta_entry64 *reta_conf, 182 unsigned int reta_size) 183 { 184 unsigned int idx; 185 unsigned int i; 186 unsigned int pos; 187 int ret; 188 189 if (!reta_size) 190 return EINVAL; 191 ret = priv_rss_reta_index_resize(priv, reta_size); 192 if (ret) 193 return ret; 194 195 for (idx = 0, i = 0; (i != reta_size); ++i) { 196 idx = i / RTE_RETA_GROUP_SIZE; 197 pos = i % RTE_RETA_GROUP_SIZE; 198 if (((reta_conf[idx].mask >> i) & 0x1) == 0) 199 continue; 200 assert(reta_conf[idx].reta[pos] < priv->rxqs_n); 201 (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; 202 } 203 return 0; 204 } 205 206 /** 207 * DPDK callback to get the RETA indirection table. 208 * 209 * @param dev 210 * Pointer to Ethernet device structure. 211 * @param reta_conf 212 * Pointer to RETA configuration structure array. 213 * @param reta_size 214 * Size of the RETA table. 215 * 216 * @return 217 * 0 on success, negative errno value on failure. 218 */ 219 int 220 mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, 221 struct rte_eth_rss_reta_entry64 *reta_conf, 222 uint16_t reta_size) 223 { 224 int ret; 225 struct priv *priv = dev->data->dev_private; 226 227 priv_lock(priv); 228 ret = priv_dev_rss_reta_query(priv, reta_conf, reta_size); 229 priv_unlock(priv); 230 return -ret; 231 } 232 233 /** 234 * DPDK callback to update the RETA indirection table. 235 * 236 * @param dev 237 * Pointer to Ethernet device structure. 238 * @param reta_conf 239 * Pointer to RETA configuration structure array. 240 * @param reta_size 241 * Size of the RETA table. 242 * 243 * @return 244 * 0 on success, negative errno value on failure. 245 */ 246 int 247 mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, 248 struct rte_eth_rss_reta_entry64 *reta_conf, 249 uint16_t reta_size) 250 { 251 int ret; 252 struct priv *priv = dev->data->dev_private; 253 254 priv_lock(priv); 255 ret = priv_dev_rss_reta_update(priv, reta_conf, reta_size); 256 priv_unlock(priv); 257 if (dev->data->dev_started) { 258 mlx5_dev_stop(dev); 259 mlx5_dev_start(dev); 260 } 261 return -ret; 262 } 263