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 if (old_size < reta_size) 127 memset(&(*priv->reta_idx)[old_size], 0, 128 (reta_size - old_size) * 129 sizeof((*priv->reta_idx)[0])); 130 return 0; 131 } 132 133 /** 134 * Query RETA table. 135 * 136 * @param priv 137 * Pointer to private structure. 138 * @param[in, out] reta_conf 139 * Pointer to the first RETA configuration structure. 140 * @param reta_size 141 * Number of entries. 142 * 143 * @return 144 * 0 on success, errno value on failure. 145 */ 146 static int 147 priv_dev_rss_reta_query(struct priv *priv, 148 struct rte_eth_rss_reta_entry64 *reta_conf, 149 unsigned int reta_size) 150 { 151 unsigned int idx; 152 unsigned int i; 153 154 if (!reta_size || reta_size > priv->reta_idx_n) 155 return EINVAL; 156 /* Fill each entry of the table even if its bit is not set. */ 157 for (idx = 0, i = 0; (i != reta_size); ++i) { 158 idx = i / RTE_RETA_GROUP_SIZE; 159 reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = 160 (*priv->reta_idx)[i]; 161 } 162 return 0; 163 } 164 165 /** 166 * Update RETA table. 167 * 168 * @param priv 169 * Pointer to private structure. 170 * @param[in] reta_conf 171 * Pointer to the first RETA configuration structure. 172 * @param reta_size 173 * Number of entries. 174 * 175 * @return 176 * 0 on success, errno value on failure. 177 */ 178 static int 179 priv_dev_rss_reta_update(struct priv *priv, 180 struct rte_eth_rss_reta_entry64 *reta_conf, 181 unsigned int reta_size) 182 { 183 unsigned int idx; 184 unsigned int i; 185 unsigned int pos; 186 int ret; 187 188 if (!reta_size) 189 return EINVAL; 190 ret = priv_rss_reta_index_resize(priv, reta_size); 191 if (ret) 192 return ret; 193 for (idx = 0, i = 0; (i != reta_size); ++i) { 194 idx = i / RTE_RETA_GROUP_SIZE; 195 pos = i % RTE_RETA_GROUP_SIZE; 196 if (((reta_conf[idx].mask >> i) & 0x1) == 0) 197 continue; 198 assert(reta_conf[idx].reta[pos] < priv->rxqs_n); 199 (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; 200 } 201 return 0; 202 } 203 204 /** 205 * DPDK callback to get the RETA indirection table. 206 * 207 * @param dev 208 * Pointer to Ethernet device structure. 209 * @param reta_conf 210 * Pointer to RETA configuration structure array. 211 * @param reta_size 212 * Size of the RETA table. 213 * 214 * @return 215 * 0 on success, negative errno value on failure. 216 */ 217 int 218 mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, 219 struct rte_eth_rss_reta_entry64 *reta_conf, 220 uint16_t reta_size) 221 { 222 int ret; 223 struct priv *priv = dev->data->dev_private; 224 225 priv_lock(priv); 226 ret = priv_dev_rss_reta_query(priv, reta_conf, reta_size); 227 priv_unlock(priv); 228 return -ret; 229 } 230 231 /** 232 * DPDK callback to update the RETA indirection table. 233 * 234 * @param dev 235 * Pointer to Ethernet device structure. 236 * @param reta_conf 237 * Pointer to RETA configuration structure array. 238 * @param reta_size 239 * Size of the RETA table. 240 * 241 * @return 242 * 0 on success, negative errno value on failure. 243 */ 244 int 245 mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, 246 struct rte_eth_rss_reta_entry64 *reta_conf, 247 uint16_t reta_size) 248 { 249 int ret; 250 struct priv *priv = dev->data->dev_private; 251 252 priv_lock(priv); 253 ret = priv_dev_rss_reta_update(priv, reta_conf, reta_size); 254 priv_unlock(priv); 255 if (dev->data->dev_started) { 256 mlx5_dev_stop(dev); 257 mlx5_dev_start(dev); 258 } 259 return -ret; 260 } 261