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