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