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