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