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 if (rss_conf->rss_hf & MLX5_RSS_HF_MASK) { 48 ret = -EINVAL; 49 goto out; 50 } 51 if (rss_conf->rss_key && rss_conf->rss_key_len) { 52 priv->rss_conf.rss_key = rte_realloc(priv->rss_conf.rss_key, 53 rss_conf->rss_key_len, 0); 54 if (!priv->rss_conf.rss_key) { 55 ret = -ENOMEM; 56 goto out; 57 } 58 memcpy(priv->rss_conf.rss_key, rss_conf->rss_key, 59 rss_conf->rss_key_len); 60 priv->rss_conf.rss_key_len = rss_conf->rss_key_len; 61 } 62 priv->rss_conf.rss_hf = rss_conf->rss_hf; 63 out: 64 return ret; 65 } 66 67 /** 68 * DPDK callback to get the RSS hash configuration. 69 * 70 * @param dev 71 * Pointer to Ethernet device structure. 72 * @param[in, out] rss_conf 73 * RSS configuration data. 74 * 75 * @return 76 * 0 on success, negative errno value on failure. 77 */ 78 int 79 mlx5_rss_hash_conf_get(struct rte_eth_dev *dev, 80 struct rte_eth_rss_conf *rss_conf) 81 { 82 struct priv *priv = dev->data->dev_private; 83 84 if (!rss_conf) 85 return -EINVAL; 86 if (rss_conf->rss_key && 87 (rss_conf->rss_key_len >= priv->rss_conf.rss_key_len)) { 88 memcpy(rss_conf->rss_key, priv->rss_conf.rss_key, 89 priv->rss_conf.rss_key_len); 90 } 91 rss_conf->rss_key_len = priv->rss_conf.rss_key_len; 92 rss_conf->rss_hf = priv->rss_conf.rss_hf; 93 return 0; 94 } 95 96 /** 97 * Allocate/reallocate RETA index table. 98 * 99 * @param priv 100 * Pointer to private structure. 101 * @praram reta_size 102 * The size of the array to allocate. 103 * 104 * @return 105 * 0 on success, errno value on failure. 106 */ 107 int 108 priv_rss_reta_index_resize(struct priv *priv, unsigned int reta_size) 109 { 110 void *mem; 111 unsigned int old_size = priv->reta_idx_n; 112 113 if (priv->reta_idx_n == reta_size) 114 return 0; 115 116 mem = rte_realloc(priv->reta_idx, 117 reta_size * sizeof((*priv->reta_idx)[0]), 0); 118 if (!mem) 119 return ENOMEM; 120 priv->reta_idx = mem; 121 priv->reta_idx_n = reta_size; 122 if (old_size < reta_size) 123 memset(&(*priv->reta_idx)[old_size], 0, 124 (reta_size - old_size) * 125 sizeof((*priv->reta_idx)[0])); 126 return 0; 127 } 128 129 /** 130 * Query RETA table. 131 * 132 * @param priv 133 * Pointer to private structure. 134 * @param[in, out] reta_conf 135 * Pointer to the first RETA configuration structure. 136 * @param reta_size 137 * Number of entries. 138 * 139 * @return 140 * 0 on success, errno value on failure. 141 */ 142 static int 143 priv_dev_rss_reta_query(struct priv *priv, 144 struct rte_eth_rss_reta_entry64 *reta_conf, 145 unsigned int reta_size) 146 { 147 unsigned int idx; 148 unsigned int i; 149 150 if (!reta_size || reta_size > priv->reta_idx_n) 151 return EINVAL; 152 /* Fill each entry of the table even if its bit is not set. */ 153 for (idx = 0, i = 0; (i != reta_size); ++i) { 154 idx = i / RTE_RETA_GROUP_SIZE; 155 reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] = 156 (*priv->reta_idx)[i]; 157 } 158 return 0; 159 } 160 161 /** 162 * Update RETA table. 163 * 164 * @param priv 165 * Pointer to private structure. 166 * @param[in] reta_conf 167 * Pointer to the first RETA configuration structure. 168 * @param reta_size 169 * Number of entries. 170 * 171 * @return 172 * 0 on success, errno value on failure. 173 */ 174 static int 175 priv_dev_rss_reta_update(struct priv *priv, 176 struct rte_eth_rss_reta_entry64 *reta_conf, 177 unsigned int reta_size) 178 { 179 unsigned int idx; 180 unsigned int i; 181 unsigned int pos; 182 int ret; 183 184 if (!reta_size) 185 return EINVAL; 186 ret = priv_rss_reta_index_resize(priv, reta_size); 187 if (ret) 188 return ret; 189 for (idx = 0, i = 0; (i != reta_size); ++i) { 190 idx = i / RTE_RETA_GROUP_SIZE; 191 pos = i % RTE_RETA_GROUP_SIZE; 192 if (((reta_conf[idx].mask >> i) & 0x1) == 0) 193 continue; 194 assert(reta_conf[idx].reta[pos] < priv->rxqs_n); 195 (*priv->reta_idx)[i] = reta_conf[idx].reta[pos]; 196 } 197 return 0; 198 } 199 200 /** 201 * DPDK callback to get the RETA indirection table. 202 * 203 * @param dev 204 * Pointer to Ethernet device structure. 205 * @param reta_conf 206 * Pointer to RETA configuration structure array. 207 * @param reta_size 208 * Size of the RETA table. 209 * 210 * @return 211 * 0 on success, negative errno value on failure. 212 */ 213 int 214 mlx5_dev_rss_reta_query(struct rte_eth_dev *dev, 215 struct rte_eth_rss_reta_entry64 *reta_conf, 216 uint16_t reta_size) 217 { 218 int ret; 219 struct priv *priv = dev->data->dev_private; 220 221 ret = priv_dev_rss_reta_query(priv, reta_conf, reta_size); 222 return -ret; 223 } 224 225 /** 226 * DPDK callback to update the RETA indirection table. 227 * 228 * @param dev 229 * Pointer to Ethernet device structure. 230 * @param reta_conf 231 * Pointer to RETA configuration structure array. 232 * @param reta_size 233 * Size of the RETA table. 234 * 235 * @return 236 * 0 on success, negative errno value on failure. 237 */ 238 int 239 mlx5_dev_rss_reta_update(struct rte_eth_dev *dev, 240 struct rte_eth_rss_reta_entry64 *reta_conf, 241 uint16_t reta_size) 242 { 243 int ret; 244 struct priv *priv = dev->data->dev_private; 245 246 ret = priv_dev_rss_reta_update(priv, reta_conf, reta_size); 247 if (dev->data->dev_started) { 248 mlx5_dev_stop(dev); 249 mlx5_dev_start(dev); 250 } 251 return -ret; 252 } 253