Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2020 Amazon.com, Inc. or its affiliates.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "ena_ethdev.h"
7 : : #include "ena_logs.h"
8 : :
9 : : #include <ena_admin_defs.h>
10 : :
11 : : #define TEST_BIT(val, bit_shift) ((val) & (1UL << (bit_shift)))
12 : :
13 : : #define ENA_HF_RSS_ALL_L2 (ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA)
14 : : #define ENA_HF_RSS_ALL_L3 (ENA_ADMIN_RSS_L3_SA | ENA_ADMIN_RSS_L3_DA)
15 : : #define ENA_HF_RSS_ALL_L4 (ENA_ADMIN_RSS_L4_SP | ENA_ADMIN_RSS_L4_DP)
16 : : #define ENA_HF_RSS_ALL_L3_L4 (ENA_HF_RSS_ALL_L3 | ENA_HF_RSS_ALL_L4)
17 : : #define ENA_HF_RSS_ALL_L2_L3_L4 (ENA_HF_RSS_ALL_L2 | ENA_HF_RSS_ALL_L3_L4)
18 : :
19 : : enum ena_rss_hash_fields {
20 : : ENA_HF_RSS_TCP4 = ENA_HF_RSS_ALL_L3_L4,
21 : : ENA_HF_RSS_UDP4 = ENA_HF_RSS_ALL_L3_L4,
22 : : ENA_HF_RSS_TCP6 = ENA_HF_RSS_ALL_L3_L4,
23 : : ENA_HF_RSS_UDP6 = ENA_HF_RSS_ALL_L3_L4,
24 : : ENA_HF_RSS_IP4 = ENA_HF_RSS_ALL_L3,
25 : : ENA_HF_RSS_IP6 = ENA_HF_RSS_ALL_L3,
26 : : ENA_HF_RSS_IP4_FRAG = ENA_HF_RSS_ALL_L3,
27 : : ENA_HF_RSS_NOT_IP = ENA_HF_RSS_ALL_L2,
28 : : ENA_HF_RSS_TCP6_EX = ENA_HF_RSS_ALL_L3_L4,
29 : : ENA_HF_RSS_IP6_EX = ENA_HF_RSS_ALL_L3,
30 : : };
31 : :
32 : : static int ena_fill_indirect_table_default(struct ena_com_dev *ena_dev,
33 : : size_t tbl_size,
34 : : size_t queue_num);
35 : : static uint64_t ena_admin_hf_to_eth_hf(enum ena_admin_flow_hash_proto proto,
36 : : uint16_t field);
37 : : static uint16_t ena_eth_hf_to_admin_hf(enum ena_admin_flow_hash_proto proto,
38 : : uint64_t rss_hf);
39 : : static int ena_set_hash_fields(struct ena_com_dev *ena_dev, uint64_t rss_hf);
40 : : static int ena_rss_hash_set(struct ena_com_dev *ena_dev,
41 : : struct rte_eth_rss_conf *rss_conf,
42 : : bool default_allowed);
43 : : static void ena_reorder_rss_hash_key(uint8_t *reordered_key,
44 : : uint8_t *key,
45 : : size_t key_size);
46 : : static int ena_get_rss_hash_key(struct ena_com_dev *ena_dev, uint8_t *rss_key);
47 : :
48 : 0 : size_t ena_rss_get_indirection_table_size(struct ena_adapter *adapter)
49 : : {
50 : 0 : struct ena_com_dev *ena_dev = &adapter->ena_dev;
51 [ # # ]: 0 : if (!ena_com_indirection_table_config_supported(ena_dev)) {
52 : 0 : PMD_DRV_LOG_LINE(WARNING,
53 : : "Indirection table is not supported by the device.");
54 : 0 : return 0;
55 : : }
56 : 0 : adapter->indirect_table_size = (1UL << ena_dev->rss.tbl_log_size);
57 : 0 : return adapter->indirect_table_size;
58 : : }
59 : 0 : void ena_rss_key_fill(void *key, size_t size)
60 : : {
61 : : static bool key_generated;
62 : : static uint8_t default_key[ENA_HASH_KEY_SIZE];
63 : : size_t i;
64 : :
65 [ # # ]: 0 : if (!key_generated) {
66 [ # # ]: 0 : for (i = 0; i < RTE_DIM(default_key); ++i)
67 : 0 : default_key[i] = rte_rand() & 0xff;
68 : 0 : key_generated = true;
69 : : }
70 : :
71 : : RTE_ASSERT(size <= sizeof(default_key));
72 [ # # ]: 0 : rte_memcpy(key, default_key, RTE_MIN(size, sizeof(default_key)));
73 : 0 : }
74 : :
75 : 0 : int ena_rss_reta_update(struct rte_eth_dev *dev,
76 : : struct rte_eth_rss_reta_entry64 *reta_conf,
77 : : uint16_t reta_size)
78 : : {
79 : 0 : struct ena_adapter *adapter = dev->data->dev_private;
80 : 0 : struct ena_com_dev *ena_dev = &adapter->ena_dev;
81 : : int rc, i;
82 : : u16 entry_value;
83 : : int conf_idx;
84 : : int idx;
85 : : size_t tbl_size;
86 : :
87 [ # # ]: 0 : if (reta_size == 0 || reta_conf == NULL)
88 : : return -EINVAL;
89 : :
90 [ # # ]: 0 : if (!(dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH)) {
91 : 0 : PMD_DRV_LOG_LINE(ERR,
92 : : "RSS was not configured for the PMD");
93 : 0 : return -ENOTSUP;
94 : : }
95 : :
96 : 0 : tbl_size = ena_rss_get_indirection_table_size(adapter);
97 [ # # ]: 0 : if (reta_size != tbl_size) {
98 : 0 : PMD_DRV_LOG_LINE(ERR,
99 : : "Requested indirection table size (%" PRIu16 ") isn't supported (expected: %zu)",
100 : : reta_size, tbl_size);
101 : 0 : return -EINVAL;
102 : : }
103 : :
104 : : /* Prevent RETA table structure update races */
105 : 0 : rte_spinlock_lock(&adapter->admin_lock);
106 [ # # ]: 0 : for (i = 0 ; i < reta_size ; i++) {
107 : : /* Each reta_conf is for 64 entries.
108 : : * To support 128 we use 2 conf of 64.
109 : : */
110 : 0 : conf_idx = i / RTE_ETH_RETA_GROUP_SIZE;
111 : 0 : idx = i % RTE_ETH_RETA_GROUP_SIZE;
112 [ # # ]: 0 : if (TEST_BIT(reta_conf[conf_idx].mask, idx)) {
113 : 0 : entry_value =
114 : 0 : ENA_IO_RXQ_IDX(reta_conf[conf_idx].reta[idx]);
115 : :
116 : 0 : rc = ena_com_indirect_table_fill_entry(ena_dev, i,
117 : : entry_value);
118 [ # # ]: 0 : if (unlikely(rc != 0)) {
119 : 0 : PMD_DRV_LOG_LINE(ERR,
120 : : "Cannot fill indirection table");
121 : : rte_spinlock_unlock(&adapter->admin_lock);
122 : 0 : return rc;
123 : : }
124 : : }
125 : : }
126 : :
127 : 0 : rc = ena_mp_indirect_table_set(adapter);
128 : : rte_spinlock_unlock(&adapter->admin_lock);
129 [ # # ]: 0 : if (unlikely(rc != 0)) {
130 : 0 : PMD_DRV_LOG_LINE(ERR, "Cannot set the indirection table");
131 : 0 : return rc;
132 : : }
133 : :
134 : 0 : PMD_DRV_LOG_LINE(DEBUG, "RSS configured %d entries for port %d",
135 : : reta_size, dev->data->port_id);
136 : :
137 : 0 : return 0;
138 : : }
139 : :
140 : : /* Query redirection table. */
141 : 0 : int ena_rss_reta_query(struct rte_eth_dev *dev,
142 : : struct rte_eth_rss_reta_entry64 *reta_conf,
143 : : uint16_t reta_size)
144 : : {
145 : 0 : struct ena_adapter *adapter = dev->data->dev_private;
146 : : int rc;
147 : : int i;
148 : : int reta_conf_idx;
149 : : int reta_idx;
150 : : size_t tbl_size;
151 : :
152 [ # # ]: 0 : if (reta_size == 0 || reta_conf == NULL)
153 : : return -EINVAL;
154 : :
155 [ # # ]: 0 : if (!(dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH)) {
156 : 0 : PMD_DRV_LOG_LINE(ERR,
157 : : "RSS was not configured for the PMD");
158 : 0 : return -ENOTSUP;
159 : : }
160 : :
161 : 0 : tbl_size = ena_rss_get_indirection_table_size(adapter);
162 [ # # ]: 0 : if (reta_size != tbl_size) {
163 : 0 : PMD_DRV_LOG_LINE(ERR,
164 : : "Cannot get indirection table: size (%" PRIu16 ") mismatch (expected: %zu)",
165 : : reta_size, tbl_size);
166 : 0 : return -EINVAL;
167 : : }
168 [ # # ]: 0 : if (!adapter->indirect_table) {
169 : 0 : PMD_DRV_LOG_LINE(ERR,
170 : : "Cannot get indirection table: local table not allocated");
171 : 0 : return -EINVAL;
172 : : }
173 : 0 : rte_spinlock_lock(&adapter->admin_lock);
174 : 0 : rc = ena_mp_indirect_table_get(adapter, adapter->indirect_table);
175 [ # # ]: 0 : if (unlikely(rc != 0)) {
176 : : rte_spinlock_unlock(&adapter->admin_lock);
177 : 0 : PMD_DRV_LOG_LINE(ERR, "Cannot get indirection table");
178 : 0 : return rc;
179 : : }
180 : :
181 [ # # ]: 0 : for (i = 0 ; i < reta_size ; i++) {
182 : 0 : reta_conf_idx = i / RTE_ETH_RETA_GROUP_SIZE;
183 : 0 : reta_idx = i % RTE_ETH_RETA_GROUP_SIZE;
184 [ # # ]: 0 : if (TEST_BIT(reta_conf[reta_conf_idx].mask, reta_idx))
185 : 0 : reta_conf[reta_conf_idx].reta[reta_idx] =
186 : 0 : ENA_IO_RXQ_IDX_REV(adapter->indirect_table[i]);
187 : : }
188 : : rte_spinlock_unlock(&adapter->admin_lock);
189 : :
190 : 0 : return 0;
191 : : }
192 : :
193 : 0 : static int ena_fill_indirect_table_default(struct ena_com_dev *ena_dev,
194 : : size_t tbl_size,
195 : : size_t queue_num)
196 : : {
197 : : size_t i;
198 : : int rc;
199 : : uint16_t val;
200 : :
201 [ # # ]: 0 : for (i = 0; i < tbl_size; ++i) {
202 : 0 : val = i % queue_num;
203 : 0 : rc = ena_com_indirect_table_fill_entry(ena_dev, i,
204 : 0 : ENA_IO_RXQ_IDX(val));
205 [ # # ]: 0 : if (unlikely(rc != 0)) {
206 : 0 : PMD_DRV_LOG_LINE(DEBUG,
207 : : "Failed to set %zu indirection table entry with val %" PRIu16 "",
208 : : i, val);
209 : 0 : return rc;
210 : : }
211 : : }
212 : :
213 : : return 0;
214 : : }
215 : :
216 : 0 : static uint64_t ena_admin_hf_to_eth_hf(enum ena_admin_flow_hash_proto proto,
217 : : uint16_t fields)
218 : : {
219 : : uint64_t rss_hf = 0;
220 : :
221 : : /* If no fields are activated, then RSS is disabled for this proto */
222 [ # # ]: 0 : if ((fields & ENA_HF_RSS_ALL_L2_L3_L4) == 0)
223 : : return 0;
224 : :
225 : : /* Convert proto to ETH flag */
226 : : switch (proto) {
227 : : case ENA_ADMIN_RSS_TCP4:
228 : : rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
229 : : break;
230 : : case ENA_ADMIN_RSS_UDP4:
231 : : rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
232 : : break;
233 : : case ENA_ADMIN_RSS_TCP6:
234 : : rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP;
235 : : break;
236 : : case ENA_ADMIN_RSS_UDP6:
237 : : rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP;
238 : : break;
239 : : case ENA_ADMIN_RSS_IP4:
240 : : rss_hf |= RTE_ETH_RSS_IPV4;
241 : : break;
242 : : case ENA_ADMIN_RSS_IP6:
243 : : rss_hf |= RTE_ETH_RSS_IPV6;
244 : : break;
245 : : case ENA_ADMIN_RSS_IP4_FRAG:
246 : : rss_hf |= RTE_ETH_RSS_FRAG_IPV4;
247 : : break;
248 : : case ENA_ADMIN_RSS_NOT_IP:
249 : : rss_hf |= RTE_ETH_RSS_L2_PAYLOAD;
250 : : break;
251 : : case ENA_ADMIN_RSS_TCP6_EX:
252 : : rss_hf |= RTE_ETH_RSS_IPV6_TCP_EX;
253 : : break;
254 : : case ENA_ADMIN_RSS_IP6_EX:
255 : : rss_hf |= RTE_ETH_RSS_IPV6_EX;
256 : : break;
257 : : default:
258 : : break;
259 : : };
260 : :
261 : : /* Check if only DA or SA is being used for L3. */
262 [ # # # ]: 0 : switch (fields & ENA_HF_RSS_ALL_L3) {
263 : 0 : case ENA_ADMIN_RSS_L3_SA:
264 : 0 : rss_hf |= RTE_ETH_RSS_L3_SRC_ONLY;
265 : 0 : break;
266 : 0 : case ENA_ADMIN_RSS_L3_DA:
267 : 0 : rss_hf |= RTE_ETH_RSS_L3_DST_ONLY;
268 : 0 : break;
269 : : default:
270 : : break;
271 : : };
272 : :
273 : : /* Check if only DA or SA is being used for L4. */
274 [ # # # ]: 0 : switch (fields & ENA_HF_RSS_ALL_L4) {
275 : 0 : case ENA_ADMIN_RSS_L4_SP:
276 : 0 : rss_hf |= RTE_ETH_RSS_L4_SRC_ONLY;
277 : 0 : break;
278 : 0 : case ENA_ADMIN_RSS_L4_DP:
279 : 0 : rss_hf |= RTE_ETH_RSS_L4_DST_ONLY;
280 : 0 : break;
281 : : default:
282 : : break;
283 : : };
284 : :
285 : : return rss_hf;
286 : : }
287 : :
288 : : static uint16_t ena_eth_hf_to_admin_hf(enum ena_admin_flow_hash_proto proto,
289 : : uint64_t rss_hf)
290 : : {
291 : : uint16_t fields_mask = 0;
292 : :
293 : : /* L2 always uses source and destination addresses. */
294 : : fields_mask = ENA_ADMIN_RSS_L2_DA | ENA_ADMIN_RSS_L2_SA;
295 : :
296 : : /* Determine which fields of L3 should be used. */
297 [ # # # # : 0 : switch (rss_hf & (RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY)) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
298 : : case RTE_ETH_RSS_L3_DST_ONLY:
299 : : fields_mask |= ENA_ADMIN_RSS_L3_DA;
300 : : break;
301 : 0 : case RTE_ETH_RSS_L3_SRC_ONLY:
302 : : fields_mask |= ENA_ADMIN_RSS_L3_SA;
303 : 0 : break;
304 : 0 : default:
305 : : /*
306 : : * If SRC nor DST aren't set, it means both of them should be
307 : : * used.
308 : : */
309 : : fields_mask |= ENA_HF_RSS_ALL_L3;
310 : : }
311 : :
312 : : /* Determine which fields of L4 should be used. */
313 [ # # # # : 0 : switch (rss_hf & (RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY)) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
314 : 0 : case RTE_ETH_RSS_L4_DST_ONLY:
315 : 0 : fields_mask |= ENA_ADMIN_RSS_L4_DP;
316 : 0 : break;
317 : 0 : case RTE_ETH_RSS_L4_SRC_ONLY:
318 : 0 : fields_mask |= ENA_ADMIN_RSS_L4_SP;
319 : 0 : break;
320 : 0 : default:
321 : : /*
322 : : * If SRC nor DST aren't set, it means both of them should be
323 : : * used.
324 : : */
325 : 0 : fields_mask |= ENA_HF_RSS_ALL_L4;
326 : : }
327 : :
328 : : /* Return appropriate hash fields. */
329 : : switch (proto) {
330 : : case ENA_ADMIN_RSS_TCP4:
331 : 0 : return ENA_HF_RSS_TCP4 & fields_mask;
332 : : case ENA_ADMIN_RSS_UDP4:
333 : 0 : return ENA_HF_RSS_UDP4 & fields_mask;
334 : : case ENA_ADMIN_RSS_TCP6:
335 : 0 : return ENA_HF_RSS_TCP6 & fields_mask;
336 : : case ENA_ADMIN_RSS_UDP6:
337 : 0 : return ENA_HF_RSS_UDP6 & fields_mask;
338 : : case ENA_ADMIN_RSS_IP4:
339 : 0 : return ENA_HF_RSS_IP4 & fields_mask;
340 : : case ENA_ADMIN_RSS_IP6:
341 : 0 : return ENA_HF_RSS_IP6 & fields_mask;
342 : : case ENA_ADMIN_RSS_IP4_FRAG:
343 : 0 : return ENA_HF_RSS_IP4_FRAG & fields_mask;
344 : : case ENA_ADMIN_RSS_NOT_IP:
345 : 0 : return ENA_HF_RSS_NOT_IP & fields_mask;
346 : : case ENA_ADMIN_RSS_TCP6_EX:
347 : 0 : return ENA_HF_RSS_TCP6_EX & fields_mask;
348 : : case ENA_ADMIN_RSS_IP6_EX:
349 : 0 : return ENA_HF_RSS_IP6_EX & fields_mask;
350 : : default:
351 : : break;
352 : : }
353 : :
354 : : return 0;
355 : : }
356 : :
357 : 0 : static int ena_set_hash_fields(struct ena_com_dev *ena_dev, uint64_t rss_hf)
358 : : {
359 : 0 : struct ena_admin_proto_input selected_fields[ENA_ADMIN_RSS_PROTO_NUM] = {};
360 : : int rc, i;
361 : :
362 : : /* Turn on appropriate fields for each requested packet type */
363 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) != 0)
364 : 0 : selected_fields[ENA_ADMIN_RSS_TCP4].fields =
365 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_TCP4, rss_hf);
366 : :
367 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) != 0)
368 : 0 : selected_fields[ENA_ADMIN_RSS_UDP4].fields =
369 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_UDP4, rss_hf);
370 : :
371 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) != 0)
372 : 0 : selected_fields[ENA_ADMIN_RSS_TCP6].fields =
373 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_TCP6, rss_hf);
374 : :
375 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) != 0)
376 : 0 : selected_fields[ENA_ADMIN_RSS_UDP6].fields =
377 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_UDP6, rss_hf);
378 : :
379 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_IPV4) != 0)
380 : 0 : selected_fields[ENA_ADMIN_RSS_IP4].fields =
381 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_IP4, rss_hf);
382 : :
383 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_IPV6) != 0)
384 : 0 : selected_fields[ENA_ADMIN_RSS_IP6].fields =
385 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_IP6, rss_hf);
386 : :
387 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_FRAG_IPV4) != 0)
388 : 0 : selected_fields[ENA_ADMIN_RSS_IP4_FRAG].fields =
389 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_IP4_FRAG, rss_hf);
390 : :
391 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_L2_PAYLOAD) != 0)
392 : 0 : selected_fields[ENA_ADMIN_RSS_NOT_IP].fields =
393 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_NOT_IP, rss_hf);
394 : :
395 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) != 0)
396 : 0 : selected_fields[ENA_ADMIN_RSS_TCP6_EX].fields =
397 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_TCP6_EX, rss_hf);
398 : :
399 [ # # ]: 0 : if ((rss_hf & RTE_ETH_RSS_IPV6_EX) != 0)
400 : 0 : selected_fields[ENA_ADMIN_RSS_IP6_EX].fields =
401 : : ena_eth_hf_to_admin_hf(ENA_ADMIN_RSS_IP6_EX, rss_hf);
402 : :
403 : : /* Try to write them to the device */
404 [ # # ]: 0 : for (i = 0; i < ENA_ADMIN_RSS_PROTO_NUM; i++) {
405 : 0 : rc = ena_com_fill_hash_ctrl(ena_dev,
406 : : (enum ena_admin_flow_hash_proto)i,
407 : 0 : selected_fields[i].fields);
408 [ # # ]: 0 : if (unlikely(rc != 0)) {
409 : 0 : PMD_DRV_LOG_LINE(DEBUG,
410 : : "Failed to set ENA HF %d with fields %" PRIu16 "",
411 : : i, selected_fields[i].fields);
412 : 0 : return rc;
413 : : }
414 : : }
415 : :
416 : : return 0;
417 : : }
418 : :
419 : 0 : static int ena_rss_hash_set(struct ena_com_dev *ena_dev,
420 : : struct rte_eth_rss_conf *rss_conf,
421 : : bool default_allowed)
422 : : {
423 : : uint8_t hw_rss_key[ENA_HASH_KEY_SIZE];
424 : : uint8_t *rss_key;
425 : : int rc;
426 : :
427 [ # # ]: 0 : if (rss_conf->rss_key != NULL) {
428 : : /* Reorder the RSS key bytes for the hardware requirements. */
429 : : ena_reorder_rss_hash_key(hw_rss_key, rss_conf->rss_key,
430 : : ENA_HASH_KEY_SIZE);
431 : : rss_key = hw_rss_key;
432 : : } else {
433 : : rss_key = NULL;
434 : : }
435 : :
436 : : /* If the rss_key is NULL, then the randomized key will be used. */
437 : 0 : rc = ena_com_fill_hash_function(ena_dev, ENA_ADMIN_TOEPLITZ,
438 : : rss_key, ENA_HASH_KEY_SIZE, 0);
439 [ # # # # ]: 0 : if (rc != 0 && !(default_allowed && rc == ENA_COM_UNSUPPORTED)) {
440 : 0 : PMD_DRV_LOG_LINE(ERR,
441 : : "Failed to set RSS hash function in the device");
442 : 0 : return rc;
443 : : }
444 : :
445 : 0 : rc = ena_set_hash_fields(ena_dev, rss_conf->rss_hf);
446 [ # # ]: 0 : if (rc == ENA_COM_UNSUPPORTED) {
447 [ # # # # ]: 0 : if (rss_conf->rss_key == NULL && !default_allowed) {
448 : 0 : PMD_DRV_LOG_LINE(ERR,
449 : : "Setting RSS hash fields is not supported");
450 : 0 : return -ENOTSUP;
451 : : }
452 : 0 : PMD_DRV_LOG_LINE(WARNING,
453 : : "Setting RSS hash fields is not supported. Using default values: 0x%"PRIx64,
454 : : (uint64_t)(ENA_ALL_RSS_HF));
455 [ # # ]: 0 : } else if (rc != 0) {
456 : 0 : PMD_DRV_LOG_LINE(ERR, "Failed to set RSS hash fields");
457 : 0 : return rc;
458 : : }
459 : :
460 : : return 0;
461 : : }
462 : :
463 : : /* ENA HW interprets the RSS key in reverse bytes order. Because of that, the
464 : : * key must be processed upon interaction with ena_com layer.
465 : : */
466 : : static void ena_reorder_rss_hash_key(uint8_t *reordered_key,
467 : : uint8_t *key,
468 : : size_t key_size)
469 : : {
470 : : size_t i, rev_i;
471 : :
472 [ # # # # ]: 0 : for (i = 0, rev_i = key_size - 1; i < key_size; ++i, --rev_i)
473 : 0 : reordered_key[i] = key[rev_i];
474 : : }
475 : :
476 : 0 : static int ena_get_rss_hash_key(struct ena_com_dev *ena_dev, uint8_t *rss_key)
477 : : {
478 : : uint8_t hw_rss_key[ENA_HASH_KEY_SIZE];
479 : : int rc;
480 : :
481 : : /* The default RSS hash key cannot be retrieved from the HW. Unless it's
482 : : * explicitly set, this operation shouldn't be supported.
483 : : */
484 [ # # ]: 0 : if (ena_dev->rss.hash_key == NULL) {
485 : 0 : PMD_DRV_LOG_LINE(WARNING,
486 : : "Retrieving default RSS hash key is not supported");
487 : 0 : return -ENOTSUP;
488 : : }
489 : :
490 : 0 : rc = ena_com_get_hash_key(ena_dev, hw_rss_key);
491 [ # # ]: 0 : if (rc != 0)
492 : : return rc;
493 : :
494 : : ena_reorder_rss_hash_key(rss_key, hw_rss_key, ENA_HASH_KEY_SIZE);
495 : :
496 : : return 0;
497 : : }
498 : :
499 : 0 : int ena_rss_configure(struct ena_adapter *adapter)
500 : : {
501 : : struct rte_eth_rss_conf *rss_conf;
502 : : struct ena_com_dev *ena_dev;
503 : : int rc;
504 : : size_t tbl_size;
505 : :
506 : 0 : ena_dev = &adapter->ena_dev;
507 : 0 : rss_conf = &adapter->edev_data->dev_conf.rx_adv_conf.rss_conf;
508 : :
509 [ # # ]: 0 : if (adapter->edev_data->nb_rx_queues == 0)
510 : : return 0;
511 : :
512 : 0 : tbl_size = ena_rss_get_indirection_table_size(adapter);
513 [ # # ]: 0 : if (!tbl_size)
514 : : return 0;
515 : : /* Restart the indirection table. The number of queues could change
516 : : * between start/stop calls, so it must be reinitialized with default
517 : : * values.
518 : : */
519 : 0 : rc = ena_fill_indirect_table_default(ena_dev, tbl_size,
520 : 0 : adapter->edev_data->nb_rx_queues);
521 [ # # ]: 0 : if (unlikely(rc != 0)) {
522 : 0 : PMD_DRV_LOG_LINE(ERR,
523 : : "Failed to fill indirection table with default values");
524 : 0 : return rc;
525 : : }
526 : :
527 : 0 : rc = ena_com_indirect_table_set(ena_dev);
528 [ # # ]: 0 : if (unlikely(rc != 0 && rc != ENA_COM_UNSUPPORTED)) {
529 : 0 : PMD_DRV_LOG_LINE(ERR,
530 : : "Failed to set indirection table in the device");
531 : 0 : return rc;
532 : : }
533 : :
534 : 0 : rc = ena_rss_hash_set(ena_dev, rss_conf, true);
535 [ # # ]: 0 : if (unlikely(rc != 0)) {
536 : 0 : PMD_DRV_LOG_LINE(ERR, "Failed to set RSS hash");
537 : 0 : return rc;
538 : : }
539 : :
540 : 0 : PMD_DRV_LOG_LINE(DEBUG, "RSS configured for port %d",
541 : : adapter->edev_data->port_id);
542 : :
543 : 0 : return 0;
544 : : }
545 : :
546 : 0 : int ena_rss_hash_update(struct rte_eth_dev *dev,
547 : : struct rte_eth_rss_conf *rss_conf)
548 : : {
549 : 0 : struct ena_adapter *adapter = dev->data->dev_private;
550 : : int rc;
551 : :
552 : 0 : rte_spinlock_lock(&adapter->admin_lock);
553 : 0 : rc = ena_rss_hash_set(&adapter->ena_dev, rss_conf, false);
554 : : rte_spinlock_unlock(&adapter->admin_lock);
555 [ # # ]: 0 : if (unlikely(rc != 0)) {
556 : 0 : PMD_DRV_LOG_LINE(ERR, "Failed to set RSS hash");
557 : 0 : return rc;
558 : : }
559 : :
560 : : return 0;
561 : : }
562 : :
563 : 0 : int ena_rss_hash_conf_get(struct rte_eth_dev *dev,
564 : : struct rte_eth_rss_conf *rss_conf)
565 : : {
566 : 0 : struct ena_adapter *adapter = dev->data->dev_private;
567 : 0 : struct ena_com_dev *ena_dev = &adapter->ena_dev;
568 : : enum ena_admin_flow_hash_proto proto;
569 : : uint64_t rss_hf = 0;
570 : : int rc, i;
571 : : uint16_t admin_hf;
572 : : static bool warn_once;
573 : :
574 [ # # ]: 0 : if (!(dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH)) {
575 : 0 : PMD_DRV_LOG_LINE(ERR, "RSS was not configured for the PMD");
576 : 0 : return -ENOTSUP;
577 : : }
578 : :
579 [ # # ]: 0 : if (rss_conf->rss_key != NULL) {
580 : 0 : rc = ena_get_rss_hash_key(ena_dev, rss_conf->rss_key);
581 [ # # ]: 0 : if (unlikely(rc != 0)) {
582 : 0 : PMD_DRV_LOG_LINE(ERR,
583 : : "Cannot retrieve RSS hash key, err: %d",
584 : : rc);
585 : 0 : return rc;
586 : : }
587 : : }
588 : :
589 [ # # ]: 0 : for (i = 0; i < ENA_ADMIN_RSS_PROTO_NUM; ++i) {
590 : 0 : proto = (enum ena_admin_flow_hash_proto)i;
591 : 0 : rte_spinlock_lock(&adapter->admin_lock);
592 : 0 : rc = ena_com_get_hash_ctrl(ena_dev, proto, &admin_hf);
593 : : rte_spinlock_unlock(&adapter->admin_lock);
594 [ # # ]: 0 : if (rc == ENA_COM_UNSUPPORTED) {
595 : : /* As some devices may support only reading rss hash
596 : : * key and not the hash ctrl, we want to notify the
597 : : * caller that this feature is only partially supported
598 : : * and do not return an error - the caller could be
599 : : * interested only in the key value.
600 : : */
601 [ # # ]: 0 : if (!warn_once) {
602 : 0 : PMD_DRV_LOG_LINE(WARNING,
603 : : "Reading hash control from the device is not supported. .rss_hf will contain a default value.");
604 : 0 : warn_once = true;
605 : : }
606 : : rss_hf = ENA_ALL_RSS_HF;
607 : : break;
608 [ # # ]: 0 : } else if (rc != 0) {
609 : 0 : PMD_DRV_LOG_LINE(ERR,
610 : : "Failed to retrieve hash ctrl for proto: %d with err: %d",
611 : : i, rc);
612 : 0 : return rc;
613 : : }
614 : :
615 : 0 : rss_hf |= ena_admin_hf_to_eth_hf(proto, admin_hf);
616 : : }
617 : :
618 : 0 : rss_conf->rss_hf = rss_hf;
619 : 0 : return 0;
620 : : }
|