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