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 != rss_hash_default_key_len) { 54 DRV_LOG(ERR, 55 "port %u RSS key len must be %zu Bytes long", 56 dev->data->port_id, rss_hash_default_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 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 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 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 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 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 return mlx5_dev_start(dev); 226 } 227 return 0; 228 } 229