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