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