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