]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/dpdk/drivers/net/mlx5/mlx5_rss.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / seastar / dpdk / drivers / net / mlx5 / mlx5_rss.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright 2015 6WIND S.A.
5 * Copyright 2015 Mellanox.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of 6WIND S.A. nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <stddef.h>
35 #include <stdint.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <assert.h>
39
40 /* Verbs header. */
41 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
42 #ifdef PEDANTIC
43 #pragma GCC diagnostic ignored "-Wpedantic"
44 #endif
45 #include <infiniband/verbs.h>
46 #ifdef PEDANTIC
47 #pragma GCC diagnostic error "-Wpedantic"
48 #endif
49
50 /* DPDK headers don't like -pedantic. */
51 #ifdef PEDANTIC
52 #pragma GCC diagnostic ignored "-Wpedantic"
53 #endif
54 #include <rte_malloc.h>
55 #include <rte_ethdev.h>
56 #ifdef PEDANTIC
57 #pragma GCC diagnostic error "-Wpedantic"
58 #endif
59
60 #include "mlx5.h"
61 #include "mlx5_rxtx.h"
62
63 /**
64 * Get a RSS configuration hash key.
65 *
66 * @param priv
67 * Pointer to private structure.
68 * @param rss_hf
69 * RSS hash functions configuration must be retrieved for.
70 *
71 * @return
72 * Pointer to a RSS configuration structure or NULL if rss_hf cannot
73 * be matched.
74 */
75 static struct rte_eth_rss_conf *
76 rss_hash_get(struct priv *priv, uint64_t rss_hf)
77 {
78 unsigned int i;
79
80 for (i = 0; (i != hash_rxq_init_n); ++i) {
81 uint64_t dpdk_rss_hf = hash_rxq_init[i].dpdk_rss_hf;
82
83 if (!(dpdk_rss_hf & rss_hf))
84 continue;
85 return (*priv->rss_conf)[i];
86 }
87 return NULL;
88 }
89
90 /**
91 * Register a RSS key.
92 *
93 * @param priv
94 * Pointer to private structure.
95 * @param key
96 * Hash key to register.
97 * @param key_len
98 * Hash key length in bytes.
99 * @param rss_hf
100 * RSS hash functions the provided key applies to.
101 *
102 * @return
103 * 0 on success, errno value on failure.
104 */
105 int
106 rss_hash_rss_conf_new_key(struct priv *priv, const uint8_t *key,
107 unsigned int key_len, uint64_t rss_hf)
108 {
109 unsigned int i;
110
111 for (i = 0; (i != hash_rxq_init_n); ++i) {
112 struct rte_eth_rss_conf *rss_conf;
113 uint64_t dpdk_rss_hf = hash_rxq_init[i].dpdk_rss_hf;
114
115 if (!(dpdk_rss_hf & rss_hf))
116 continue;
117 rss_conf = rte_realloc((*priv->rss_conf)[i],
118 (sizeof(*rss_conf) + key_len),
119 0);
120 if (!rss_conf)
121 return ENOMEM;
122 rss_conf->rss_key = (void *)(rss_conf + 1);
123 rss_conf->rss_key_len = key_len;
124 rss_conf->rss_hf = dpdk_rss_hf;
125 memcpy(rss_conf->rss_key, key, key_len);
126 (*priv->rss_conf)[i] = rss_conf;
127 }
128 return 0;
129 }
130
131 /**
132 * DPDK callback to update the RSS hash configuration.
133 *
134 * @param dev
135 * Pointer to Ethernet device structure.
136 * @param[in] rss_conf
137 * RSS configuration data.
138 *
139 * @return
140 * 0 on success, negative errno value on failure.
141 */
142 int
143 mlx5_rss_hash_update(struct rte_eth_dev *dev,
144 struct rte_eth_rss_conf *rss_conf)
145 {
146 struct priv *priv = dev->data->dev_private;
147 int err = 0;
148
149 priv_lock(priv);
150
151 assert(priv->rss_conf != NULL);
152
153 /* Apply configuration. */
154 if (rss_conf->rss_key)
155 err = rss_hash_rss_conf_new_key(priv,
156 rss_conf->rss_key,
157 rss_conf->rss_key_len,
158 rss_conf->rss_hf);
159 /* Store protocols for which RSS is enabled. */
160 priv->rss_hf = rss_conf->rss_hf;
161 priv_unlock(priv);
162 assert(err >= 0);
163 return -err;
164 }
165
166 /**
167 * DPDK callback to get the RSS hash configuration.
168 *
169 * @param dev
170 * Pointer to Ethernet device structure.
171 * @param[in, out] rss_conf
172 * RSS configuration data.
173 *
174 * @return
175 * 0 on success, negative errno value on failure.
176 */
177 int
178 mlx5_rss_hash_conf_get(struct rte_eth_dev *dev,
179 struct rte_eth_rss_conf *rss_conf)
180 {
181 struct priv *priv = dev->data->dev_private;
182 struct rte_eth_rss_conf *priv_rss_conf;
183
184 priv_lock(priv);
185
186 assert(priv->rss_conf != NULL);
187
188 priv_rss_conf = rss_hash_get(priv, rss_conf->rss_hf);
189 if (!priv_rss_conf) {
190 rss_conf->rss_hf = 0;
191 priv_unlock(priv);
192 return -EINVAL;
193 }
194 if (rss_conf->rss_key &&
195 rss_conf->rss_key_len >= priv_rss_conf->rss_key_len)
196 memcpy(rss_conf->rss_key,
197 priv_rss_conf->rss_key,
198 priv_rss_conf->rss_key_len);
199 rss_conf->rss_key_len = priv_rss_conf->rss_key_len;
200 rss_conf->rss_hf = priv_rss_conf->rss_hf;
201
202 priv_unlock(priv);
203 return 0;
204 }
205
206 /**
207 * Allocate/reallocate RETA index table.
208 *
209 * @param priv
210 * Pointer to private structure.
211 * @praram reta_size
212 * The size of the array to allocate.
213 *
214 * @return
215 * 0 on success, errno value on failure.
216 */
217 int
218 priv_rss_reta_index_resize(struct priv *priv, unsigned int reta_size)
219 {
220 void *mem;
221 unsigned int old_size = priv->reta_idx_n;
222
223 if (priv->reta_idx_n == reta_size)
224 return 0;
225
226 mem = rte_realloc(priv->reta_idx,
227 reta_size * sizeof((*priv->reta_idx)[0]), 0);
228 if (!mem)
229 return ENOMEM;
230 priv->reta_idx = mem;
231 priv->reta_idx_n = reta_size;
232
233 if (old_size < reta_size)
234 memset(&(*priv->reta_idx)[old_size], 0,
235 (reta_size - old_size) *
236 sizeof((*priv->reta_idx)[0]));
237 return 0;
238 }
239
240 /**
241 * Query RETA table.
242 *
243 * @param priv
244 * Pointer to private structure.
245 * @param[in, out] reta_conf
246 * Pointer to the first RETA configuration structure.
247 * @param reta_size
248 * Number of entries.
249 *
250 * @return
251 * 0 on success, errno value on failure.
252 */
253 static int
254 priv_dev_rss_reta_query(struct priv *priv,
255 struct rte_eth_rss_reta_entry64 *reta_conf,
256 unsigned int reta_size)
257 {
258 unsigned int idx;
259 unsigned int i;
260
261 if (!reta_size || reta_size > priv->reta_idx_n)
262 return EINVAL;
263 /* Fill each entry of the table even if its bit is not set. */
264 for (idx = 0, i = 0; (i != reta_size); ++i) {
265 idx = i / RTE_RETA_GROUP_SIZE;
266 reta_conf[idx].reta[i % RTE_RETA_GROUP_SIZE] =
267 (*priv->reta_idx)[i];
268 }
269 return 0;
270 }
271
272 /**
273 * Update RETA table.
274 *
275 * @param priv
276 * Pointer to private structure.
277 * @param[in] reta_conf
278 * Pointer to the first RETA configuration structure.
279 * @param reta_size
280 * Number of entries.
281 *
282 * @return
283 * 0 on success, errno value on failure.
284 */
285 static int
286 priv_dev_rss_reta_update(struct priv *priv,
287 struct rte_eth_rss_reta_entry64 *reta_conf,
288 unsigned int reta_size)
289 {
290 unsigned int idx;
291 unsigned int i;
292 unsigned int pos;
293 int ret;
294
295 if (!reta_size)
296 return EINVAL;
297 ret = priv_rss_reta_index_resize(priv, reta_size);
298 if (ret)
299 return ret;
300
301 for (idx = 0, i = 0; (i != reta_size); ++i) {
302 idx = i / RTE_RETA_GROUP_SIZE;
303 pos = i % RTE_RETA_GROUP_SIZE;
304 if (((reta_conf[idx].mask >> i) & 0x1) == 0)
305 continue;
306 assert(reta_conf[idx].reta[pos] < priv->rxqs_n);
307 (*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
308 }
309 return 0;
310 }
311
312 /**
313 * DPDK callback to get the RETA indirection table.
314 *
315 * @param dev
316 * Pointer to Ethernet device structure.
317 * @param reta_conf
318 * Pointer to RETA configuration structure array.
319 * @param reta_size
320 * Size of the RETA table.
321 *
322 * @return
323 * 0 on success, negative errno value on failure.
324 */
325 int
326 mlx5_dev_rss_reta_query(struct rte_eth_dev *dev,
327 struct rte_eth_rss_reta_entry64 *reta_conf,
328 uint16_t reta_size)
329 {
330 int ret;
331 struct priv *priv = dev->data->dev_private;
332
333 priv_lock(priv);
334 ret = priv_dev_rss_reta_query(priv, reta_conf, reta_size);
335 priv_unlock(priv);
336 return -ret;
337 }
338
339 /**
340 * DPDK callback to update the RETA indirection table.
341 *
342 * @param dev
343 * Pointer to Ethernet device structure.
344 * @param reta_conf
345 * Pointer to RETA configuration structure array.
346 * @param reta_size
347 * Size of the RETA table.
348 *
349 * @return
350 * 0 on success, negative errno value on failure.
351 */
352 int
353 mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
354 struct rte_eth_rss_reta_entry64 *reta_conf,
355 uint16_t reta_size)
356 {
357 int ret;
358 struct priv *priv = dev->data->dev_private;
359
360 mlx5_dev_stop(dev);
361 priv_lock(priv);
362 ret = priv_dev_rss_reta_update(priv, reta_conf, reta_size);
363 priv_unlock(priv);
364 if (ret)
365 return -ret;
366 return mlx5_dev_start(dev);
367 }