16da67e70SIvan Malov /* SPDX-License-Identifier: BSD-3-Clause 26da67e70SIvan Malov * 36da67e70SIvan Malov * Copyright(c) 2022 Xilinx, Inc. 46da67e70SIvan Malov */ 56da67e70SIvan Malov 66da67e70SIvan Malov #include <stdbool.h> 76da67e70SIvan Malov #include <stdint.h> 86da67e70SIvan Malov 96da67e70SIvan Malov #include <rte_common.h> 106da67e70SIvan Malov #include <rte_flow.h> 116da67e70SIvan Malov #include <rte_tailq.h> 126da67e70SIvan Malov 136da67e70SIvan Malov #include "efx.h" 146da67e70SIvan Malov 156da67e70SIvan Malov #include "sfc.h" 166da67e70SIvan Malov #include "sfc_debug.h" 176da67e70SIvan Malov #include "sfc_flow_rss.h" 186da67e70SIvan Malov #include "sfc_log.h" 196da67e70SIvan Malov #include "sfc_rx.h" 206da67e70SIvan Malov 216da67e70SIvan Malov int 226da67e70SIvan Malov sfc_flow_rss_attach(struct sfc_adapter *sa) 236da67e70SIvan Malov { 24f6d23053SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 256da67e70SIvan Malov struct sfc_flow_rss *flow_rss = &sa->flow_rss; 26be5cbe47SIvan Malov int rc; 276da67e70SIvan Malov 286da67e70SIvan Malov sfc_log_init(sa, "entry"); 296da67e70SIvan Malov 30f6d23053SIvan Malov flow_rss->qid_span_max = encp->enc_rx_scale_indirection_max_nqueues; 31be5cbe47SIvan Malov flow_rss->nb_tbl_entries_min = encp->enc_rx_scale_tbl_min_nentries; 32be5cbe47SIvan Malov flow_rss->nb_tbl_entries_max = encp->enc_rx_scale_tbl_max_nentries; 33be5cbe47SIvan Malov 34be5cbe47SIvan Malov sfc_log_init(sa, "allocate the bounce buffer for indirection entries"); 35be5cbe47SIvan Malov flow_rss->bounce_tbl = rte_calloc("sfc_flow_rss_bounce_tbl", 36be5cbe47SIvan Malov flow_rss->nb_tbl_entries_max, 37be5cbe47SIvan Malov sizeof(*flow_rss->bounce_tbl), 0); 38be5cbe47SIvan Malov if (flow_rss->bounce_tbl == NULL) { 39be5cbe47SIvan Malov rc = ENOMEM; 40be5cbe47SIvan Malov goto fail; 41be5cbe47SIvan Malov } 42f6d23053SIvan Malov 436da67e70SIvan Malov TAILQ_INIT(&flow_rss->ctx_list); 446da67e70SIvan Malov 456da67e70SIvan Malov sfc_log_init(sa, "done"); 466da67e70SIvan Malov 476da67e70SIvan Malov return 0; 48be5cbe47SIvan Malov 49be5cbe47SIvan Malov fail: 50be5cbe47SIvan Malov sfc_log_init(sa, "failed %d", rc); 51be5cbe47SIvan Malov 52be5cbe47SIvan Malov return rc; 536da67e70SIvan Malov } 546da67e70SIvan Malov 556da67e70SIvan Malov void 566da67e70SIvan Malov sfc_flow_rss_detach(struct sfc_adapter *sa) 576da67e70SIvan Malov { 58be5cbe47SIvan Malov struct sfc_flow_rss *flow_rss = &sa->flow_rss; 59be5cbe47SIvan Malov 606da67e70SIvan Malov sfc_log_init(sa, "entry"); 616da67e70SIvan Malov 62be5cbe47SIvan Malov sfc_log_init(sa, "free the bounce buffer for indirection entries"); 63be5cbe47SIvan Malov rte_free(flow_rss->bounce_tbl); 64be5cbe47SIvan Malov 656da67e70SIvan Malov sfc_log_init(sa, "done"); 666da67e70SIvan Malov } 676da67e70SIvan Malov 686da67e70SIvan Malov int 696da67e70SIvan Malov sfc_flow_rss_parse_conf(struct sfc_adapter *sa, 706da67e70SIvan Malov const struct rte_flow_action_rss *in, 716da67e70SIvan Malov struct sfc_flow_rss_conf *out, uint16_t *sw_qid_minp) 726da67e70SIvan Malov { 736da67e70SIvan Malov struct sfc_adapter_shared * const sas = sfc_sa2shared(sa); 74f6d23053SIvan Malov const struct sfc_flow_rss *flow_rss = &sa->flow_rss; 756da67e70SIvan Malov const struct sfc_rss *ethdev_rss = &sas->rss; 766da67e70SIvan Malov uint16_t sw_qid_min; 776da67e70SIvan Malov uint16_t sw_qid_max; 786da67e70SIvan Malov const uint8_t *key; 796da67e70SIvan Malov unsigned int i; 806da67e70SIvan Malov int rc; 816da67e70SIvan Malov 826da67e70SIvan Malov if (in->level) { 836da67e70SIvan Malov /* 846da67e70SIvan Malov * The caller demands that RSS hash be computed 856da67e70SIvan Malov * within the given encapsulation frame / level. 866da67e70SIvan Malov * Per flow control for that is not implemented. 876da67e70SIvan Malov */ 886da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: 'level' must be 0"); 896da67e70SIvan Malov return EINVAL; 906da67e70SIvan Malov } 916da67e70SIvan Malov 926da67e70SIvan Malov if (in->types != 0) { 936da67e70SIvan Malov rc = sfc_rx_hf_rte_to_efx(sa, in->types, 946da67e70SIvan Malov &out->efx_hash_types); 956da67e70SIvan Malov if (rc != 0) { 966da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: failed to process 'types'"); 976da67e70SIvan Malov return rc; 986da67e70SIvan Malov } 996da67e70SIvan Malov } else { 1006da67e70SIvan Malov sfc_dbg(sa, "flow-rss: parse: 'types' is 0; proceeding with ethdev setting"); 1016da67e70SIvan Malov out->efx_hash_types = ethdev_rss->hash_types; 1026da67e70SIvan Malov } 1036da67e70SIvan Malov 1046da67e70SIvan Malov if (in->key_len != 0) { 1056da67e70SIvan Malov if (in->key_len != sizeof(out->key)) { 1066da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: 'key_len' must be either %zu or 0", 1076da67e70SIvan Malov sizeof(out->key)); 1086da67e70SIvan Malov return EINVAL; 1096da67e70SIvan Malov } 1106da67e70SIvan Malov 1116da67e70SIvan Malov if (in->key == NULL) { 1126da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: 'key' is NULL"); 1136da67e70SIvan Malov return EINVAL; 1146da67e70SIvan Malov } 1156da67e70SIvan Malov 1166da67e70SIvan Malov key = in->key; 1176da67e70SIvan Malov } else { 1186da67e70SIvan Malov sfc_dbg(sa, "flow-rss: parse: 'key_len' is 0; proceeding with ethdev key"); 1196da67e70SIvan Malov key = ethdev_rss->key; 1206da67e70SIvan Malov } 1216da67e70SIvan Malov 1226da67e70SIvan Malov rte_memcpy(out->key, key, sizeof(out->key)); 1236da67e70SIvan Malov 1246da67e70SIvan Malov switch (in->func) { 1256da67e70SIvan Malov case RTE_ETH_HASH_FUNCTION_DEFAULT: 1266da67e70SIvan Malov /* 1276da67e70SIvan Malov * DEFAULT means that conformance to a specific 1286da67e70SIvan Malov * hash algorithm is a don't care to the caller. 1296da67e70SIvan Malov * The driver can pick the one it deems optimal. 1306da67e70SIvan Malov */ 1316da67e70SIvan Malov break; 1326da67e70SIvan Malov case RTE_ETH_HASH_FUNCTION_TOEPLITZ: 1336da67e70SIvan Malov if (ethdev_rss->hash_alg != EFX_RX_HASHALG_TOEPLITZ) { 1346da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: 'func' TOEPLITZ is unavailable; use DEFAULT"); 1356da67e70SIvan Malov return EINVAL; 1366da67e70SIvan Malov } 1376da67e70SIvan Malov break; 1386da67e70SIvan Malov default: 1396da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: 'func' #%d is unsupported", in->func); 1406da67e70SIvan Malov return EINVAL; 1416da67e70SIvan Malov } 1426da67e70SIvan Malov 14368cde2a3SIvan Malov out->rte_hash_function = in->func; 14468cde2a3SIvan Malov 1456da67e70SIvan Malov if (in->queue_num == 0) { 1466da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: 'queue_num' is 0; MIN=1"); 1476da67e70SIvan Malov return EINVAL; 1486da67e70SIvan Malov } 1496da67e70SIvan Malov 150be5cbe47SIvan Malov if (in->queue_num > flow_rss->nb_tbl_entries_max) { 1516da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: 'queue_num' is too large; MAX=%u", 152be5cbe47SIvan Malov flow_rss->nb_tbl_entries_max); 1536da67e70SIvan Malov return EINVAL; 1546da67e70SIvan Malov } 1556da67e70SIvan Malov 1566da67e70SIvan Malov if (in->queue == NULL) { 1576da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: 'queue' is NULL"); 1586da67e70SIvan Malov return EINVAL; 1596da67e70SIvan Malov } 1606da67e70SIvan Malov 1616da67e70SIvan Malov sw_qid_min = sas->ethdev_rxq_count - 1; 1626da67e70SIvan Malov sw_qid_max = 0; 1636da67e70SIvan Malov 1646da67e70SIvan Malov out->nb_qid_offsets = 0; 1656da67e70SIvan Malov 1666da67e70SIvan Malov for (i = 0; i < in->queue_num; ++i) { 1676da67e70SIvan Malov uint16_t sw_qid = in->queue[i]; 1686da67e70SIvan Malov 1696da67e70SIvan Malov if (sw_qid >= sas->ethdev_rxq_count) { 1706da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: queue=%u does not exist", 1716da67e70SIvan Malov sw_qid); 1726da67e70SIvan Malov return EINVAL; 1736da67e70SIvan Malov } 1746da67e70SIvan Malov 1756da67e70SIvan Malov if (sw_qid < sw_qid_min) 1766da67e70SIvan Malov sw_qid_min = sw_qid; 1776da67e70SIvan Malov 1786da67e70SIvan Malov if (sw_qid > sw_qid_max) 1796da67e70SIvan Malov sw_qid_max = sw_qid; 1806da67e70SIvan Malov 1816da67e70SIvan Malov if (sw_qid != in->queue[0] + i) 1826da67e70SIvan Malov out->nb_qid_offsets = in->queue_num; 1836da67e70SIvan Malov } 1846da67e70SIvan Malov 1856da67e70SIvan Malov out->qid_span = sw_qid_max - sw_qid_min + 1; 1866da67e70SIvan Malov 187f6d23053SIvan Malov if (out->qid_span > flow_rss->qid_span_max) { 1886da67e70SIvan Malov sfc_err(sa, "flow-rss: parse: queue ID span %u is too large; MAX=%u", 189f6d23053SIvan Malov out->qid_span, flow_rss->qid_span_max); 1906da67e70SIvan Malov return EINVAL; 1916da67e70SIvan Malov } 1926da67e70SIvan Malov 1936da67e70SIvan Malov if (sw_qid_minp != NULL) 1946da67e70SIvan Malov *sw_qid_minp = sw_qid_min; 1956da67e70SIvan Malov 1966da67e70SIvan Malov return 0; 1976da67e70SIvan Malov } 1986da67e70SIvan Malov 1996da67e70SIvan Malov struct sfc_flow_rss_ctx * 2006da67e70SIvan Malov sfc_flow_rss_ctx_reuse(struct sfc_adapter *sa, 2016da67e70SIvan Malov const struct sfc_flow_rss_conf *conf, 2026da67e70SIvan Malov uint16_t sw_qid_min, const uint16_t *sw_qids) 2036da67e70SIvan Malov { 2046da67e70SIvan Malov struct sfc_flow_rss *flow_rss = &sa->flow_rss; 2056da67e70SIvan Malov static struct sfc_flow_rss_ctx *ctx; 2066da67e70SIvan Malov 2076da67e70SIvan Malov SFC_ASSERT(sfc_adapter_is_locked(sa)); 2086da67e70SIvan Malov 2096da67e70SIvan Malov TAILQ_FOREACH(ctx, &flow_rss->ctx_list, entries) { 2106da67e70SIvan Malov if (memcmp(&ctx->conf, conf, sizeof(*conf)) != 0) 2116da67e70SIvan Malov continue; 2126da67e70SIvan Malov 2136da67e70SIvan Malov if (conf->nb_qid_offsets != 0) { 2146da67e70SIvan Malov bool match_confirmed = true; 2156da67e70SIvan Malov unsigned int i; 2166da67e70SIvan Malov 2176da67e70SIvan Malov for (i = 0; i < conf->nb_qid_offsets; ++i) { 2186da67e70SIvan Malov uint16_t qid_offset = sw_qids[i] - sw_qid_min; 2196da67e70SIvan Malov 2206da67e70SIvan Malov if (ctx->qid_offsets[i] != qid_offset) { 2216da67e70SIvan Malov match_confirmed = false; 2226da67e70SIvan Malov break; 2236da67e70SIvan Malov } 2246da67e70SIvan Malov } 2256da67e70SIvan Malov 2266da67e70SIvan Malov if (!match_confirmed) 2276da67e70SIvan Malov continue; 2286da67e70SIvan Malov } 2296da67e70SIvan Malov 2306da67e70SIvan Malov sfc_dbg(sa, "flow-rss: reusing ctx=%p", ctx); 2316da67e70SIvan Malov ++(ctx->refcnt); 2326da67e70SIvan Malov return ctx; 2336da67e70SIvan Malov } 2346da67e70SIvan Malov 2356da67e70SIvan Malov return NULL; 2366da67e70SIvan Malov } 2376da67e70SIvan Malov 2386da67e70SIvan Malov int 2396da67e70SIvan Malov sfc_flow_rss_ctx_add(struct sfc_adapter *sa, 2406da67e70SIvan Malov const struct sfc_flow_rss_conf *conf, uint16_t sw_qid_min, 2416da67e70SIvan Malov const uint16_t *sw_qids, struct sfc_flow_rss_ctx **ctxp) 2426da67e70SIvan Malov { 2436da67e70SIvan Malov struct sfc_flow_rss *flow_rss = &sa->flow_rss; 2446da67e70SIvan Malov struct sfc_flow_rss_ctx *ctx; 2456da67e70SIvan Malov 2466da67e70SIvan Malov SFC_ASSERT(sfc_adapter_is_locked(sa)); 2476da67e70SIvan Malov 2486da67e70SIvan Malov ctx = rte_zmalloc("sfc_flow_rss_ctx", sizeof(*ctx), 0); 2496da67e70SIvan Malov if (ctx == NULL) 2506da67e70SIvan Malov return ENOMEM; 2516da67e70SIvan Malov 2526da67e70SIvan Malov if (conf->nb_qid_offsets != 0) { 2536da67e70SIvan Malov unsigned int i; 2546da67e70SIvan Malov 2556da67e70SIvan Malov ctx->qid_offsets = rte_calloc("sfc_flow_rss_ctx_qid_offsets", 2566da67e70SIvan Malov conf->nb_qid_offsets, 2576da67e70SIvan Malov sizeof(*ctx->qid_offsets), 0); 2586da67e70SIvan Malov if (ctx->qid_offsets == NULL) { 2596da67e70SIvan Malov rte_free(ctx); 2606da67e70SIvan Malov return ENOMEM; 2616da67e70SIvan Malov } 2626da67e70SIvan Malov 2636da67e70SIvan Malov for (i = 0; i < conf->nb_qid_offsets; ++i) 2646da67e70SIvan Malov ctx->qid_offsets[i] = sw_qids[i] - sw_qid_min; 2656da67e70SIvan Malov } 2666da67e70SIvan Malov 2676da67e70SIvan Malov ctx->conf = *conf; 2686da67e70SIvan Malov ctx->refcnt = 1; 2696da67e70SIvan Malov 2706da67e70SIvan Malov TAILQ_INSERT_TAIL(&flow_rss->ctx_list, ctx, entries); 2716da67e70SIvan Malov 2726da67e70SIvan Malov *ctxp = ctx; 2736da67e70SIvan Malov 2746da67e70SIvan Malov sfc_dbg(sa, "flow-rss: added ctx=%p", ctx); 2756da67e70SIvan Malov 2766da67e70SIvan Malov return 0; 2776da67e70SIvan Malov } 2786da67e70SIvan Malov 2796da67e70SIvan Malov void 2806da67e70SIvan Malov sfc_flow_rss_ctx_del(struct sfc_adapter *sa, struct sfc_flow_rss_ctx *ctx) 2816da67e70SIvan Malov { 2826da67e70SIvan Malov struct sfc_flow_rss *flow_rss = &sa->flow_rss; 2836da67e70SIvan Malov 2846da67e70SIvan Malov if (ctx == NULL) 2856da67e70SIvan Malov return; 2866da67e70SIvan Malov 2876da67e70SIvan Malov SFC_ASSERT(sfc_adapter_is_locked(sa)); 2886da67e70SIvan Malov 2896da67e70SIvan Malov if (ctx->dummy) 2906da67e70SIvan Malov return; 2916da67e70SIvan Malov 2926da67e70SIvan Malov SFC_ASSERT(ctx->refcnt != 0); 2936da67e70SIvan Malov 2946da67e70SIvan Malov --(ctx->refcnt); 2956da67e70SIvan Malov 2966da67e70SIvan Malov if (ctx->refcnt != 0) 2976da67e70SIvan Malov return; 2986da67e70SIvan Malov 2996da67e70SIvan Malov if (ctx->nic_handle_refcnt != 0) { 3006da67e70SIvan Malov sfc_err(sa, "flow-rss: deleting ctx=%p abandons its NIC resource: handle=0x%08x, refcnt=%u", 3016da67e70SIvan Malov ctx, ctx->nic_handle, ctx->nic_handle_refcnt); 3026da67e70SIvan Malov } 3036da67e70SIvan Malov 3046da67e70SIvan Malov TAILQ_REMOVE(&flow_rss->ctx_list, ctx, entries); 3056da67e70SIvan Malov rte_free(ctx->qid_offsets); 3066da67e70SIvan Malov sfc_dbg(sa, "flow-rss: deleted ctx=%p", ctx); 307*757b0b6fSStephen Hemminger 308*757b0b6fSStephen Hemminger rte_free(ctx); 3096da67e70SIvan Malov } 3106da67e70SIvan Malov 3116da67e70SIvan Malov static int 3126da67e70SIvan Malov sfc_flow_rss_ctx_program_tbl(struct sfc_adapter *sa, 313be5cbe47SIvan Malov unsigned int nb_tbl_entries, 3146da67e70SIvan Malov const struct sfc_flow_rss_ctx *ctx) 3156da67e70SIvan Malov { 3166da67e70SIvan Malov const struct sfc_flow_rss_conf *conf = &ctx->conf; 3176da67e70SIvan Malov unsigned int *tbl = sa->flow_rss.bounce_tbl; 3186da67e70SIvan Malov unsigned int i; 3196da67e70SIvan Malov 3206da67e70SIvan Malov SFC_ASSERT(sfc_adapter_is_locked(sa)); 3216da67e70SIvan Malov 32268cde2a3SIvan Malov if (nb_tbl_entries == 0) 32368cde2a3SIvan Malov return 0; 32468cde2a3SIvan Malov 3256da67e70SIvan Malov if (conf->nb_qid_offsets != 0) { 3266da67e70SIvan Malov SFC_ASSERT(ctx->qid_offsets != NULL); 3276da67e70SIvan Malov 328be5cbe47SIvan Malov for (i = 0; i < nb_tbl_entries; ++i) 3296da67e70SIvan Malov tbl[i] = ctx->qid_offsets[i % conf->nb_qid_offsets]; 3306da67e70SIvan Malov } else { 331be5cbe47SIvan Malov for (i = 0; i < nb_tbl_entries; ++i) 3326da67e70SIvan Malov tbl[i] = i % conf->qid_span; 3336da67e70SIvan Malov } 3346da67e70SIvan Malov 3356da67e70SIvan Malov return efx_rx_scale_tbl_set(sa->nic, ctx->nic_handle, 336be5cbe47SIvan Malov tbl, nb_tbl_entries); 3376da67e70SIvan Malov } 3386da67e70SIvan Malov 3396da67e70SIvan Malov int 3406da67e70SIvan Malov sfc_flow_rss_ctx_program(struct sfc_adapter *sa, struct sfc_flow_rss_ctx *ctx) 3416da67e70SIvan Malov { 3426da67e70SIvan Malov efx_rx_scale_context_type_t ctx_type = EFX_RX_SCALE_EXCLUSIVE; 3436da67e70SIvan Malov struct sfc_adapter_shared * const sas = sfc_sa2shared(sa); 34468cde2a3SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); 345be5cbe47SIvan Malov const struct sfc_flow_rss *flow_rss = &sa->flow_rss; 3466da67e70SIvan Malov struct sfc_rss *ethdev_rss = &sas->rss; 3476da67e70SIvan Malov struct sfc_flow_rss_conf *conf; 3486da67e70SIvan Malov bool allocation_done = B_FALSE; 349be5cbe47SIvan Malov unsigned int nb_qid_offsets; 350be5cbe47SIvan Malov unsigned int nb_tbl_entries; 3516da67e70SIvan Malov int rc; 3526da67e70SIvan Malov 3536da67e70SIvan Malov if (ctx == NULL) 3546da67e70SIvan Malov return 0; 3556da67e70SIvan Malov 3566da67e70SIvan Malov conf = &ctx->conf; 3576da67e70SIvan Malov 3586da67e70SIvan Malov SFC_ASSERT(sfc_adapter_is_locked(sa)); 3596da67e70SIvan Malov 360be5cbe47SIvan Malov if (conf->nb_qid_offsets != 0) 361be5cbe47SIvan Malov nb_qid_offsets = conf->nb_qid_offsets; 362be5cbe47SIvan Malov else 363be5cbe47SIvan Malov nb_qid_offsets = conf->qid_span; 364be5cbe47SIvan Malov 365be5cbe47SIvan Malov if (!RTE_IS_POWER_OF_2(nb_qid_offsets)) { 366be5cbe47SIvan Malov /* 367be5cbe47SIvan Malov * Most likely, it pays to enlarge the indirection 368be5cbe47SIvan Malov * table to facilitate better distribution quality. 369be5cbe47SIvan Malov */ 370be5cbe47SIvan Malov nb_qid_offsets = flow_rss->nb_tbl_entries_max; 371be5cbe47SIvan Malov } 372be5cbe47SIvan Malov 373be5cbe47SIvan Malov nb_tbl_entries = RTE_MAX(flow_rss->nb_tbl_entries_min, nb_qid_offsets); 374be5cbe47SIvan Malov 37568cde2a3SIvan Malov if (conf->rte_hash_function == RTE_ETH_HASH_FUNCTION_DEFAULT && 37668cde2a3SIvan Malov conf->nb_qid_offsets == 0 && 37768cde2a3SIvan Malov conf->qid_span <= encp->enc_rx_scale_even_spread_max_nqueues) { 37868cde2a3SIvan Malov /* 37968cde2a3SIvan Malov * Conformance to a specific hash algorithm is a don't care to 38068cde2a3SIvan Malov * the user. The queue array is contiguous and ascending. That 38168cde2a3SIvan Malov * means that the even spread context may be requested here in 38268cde2a3SIvan Malov * order to avoid wasting precious indirection table resources. 38368cde2a3SIvan Malov */ 38468cde2a3SIvan Malov ctx_type = EFX_RX_SCALE_EVEN_SPREAD; 38568cde2a3SIvan Malov nb_tbl_entries = 0; 38668cde2a3SIvan Malov } 38768cde2a3SIvan Malov 3886da67e70SIvan Malov if (ctx->nic_handle_refcnt == 0) { 389be5cbe47SIvan Malov rc = efx_rx_scale_context_alloc_v2(sa->nic, ctx_type, 3906da67e70SIvan Malov conf->qid_span, 391be5cbe47SIvan Malov nb_tbl_entries, 3926da67e70SIvan Malov &ctx->nic_handle); 3936da67e70SIvan Malov if (rc != 0) { 394be5cbe47SIvan Malov sfc_err(sa, "flow-rss: failed to allocate NIC resource for ctx=%p: type=%d, qid_span=%u, nb_tbl_entries=%u; rc=%d", 395be5cbe47SIvan Malov ctx, ctx_type, conf->qid_span, nb_tbl_entries, rc); 3966da67e70SIvan Malov goto fail; 3976da67e70SIvan Malov } 3986da67e70SIvan Malov 399be5cbe47SIvan Malov sfc_dbg(sa, "flow-rss: allocated NIC resource for ctx=%p: type=%d, qid_span=%u, nb_tbl_entries=%u; handle=0x%08x", 400be5cbe47SIvan Malov ctx, ctx_type, conf->qid_span, nb_tbl_entries, 4016da67e70SIvan Malov ctx->nic_handle); 4026da67e70SIvan Malov 4036da67e70SIvan Malov ++(ctx->nic_handle_refcnt); 4046da67e70SIvan Malov allocation_done = B_TRUE; 4056da67e70SIvan Malov } else { 4066da67e70SIvan Malov ++(ctx->nic_handle_refcnt); 4076da67e70SIvan Malov return 0; 4086da67e70SIvan Malov } 4096da67e70SIvan Malov 4106da67e70SIvan Malov rc = efx_rx_scale_mode_set(sa->nic, ctx->nic_handle, 4116da67e70SIvan Malov ethdev_rss->hash_alg, 4126da67e70SIvan Malov (ctx->dummy) ? ethdev_rss->hash_types : 4136da67e70SIvan Malov conf->efx_hash_types, 4146da67e70SIvan Malov B_TRUE); 4156da67e70SIvan Malov if (rc != 0) { 4166da67e70SIvan Malov sfc_err(sa, "flow-rss: failed to configure hash for ctx=%p: efx_hash_alg=%d, efx_hash_types=0x%08x; rc=%d", 4176da67e70SIvan Malov ctx, ethdev_rss->hash_alg, 4186da67e70SIvan Malov (ctx->dummy) ? ethdev_rss->hash_types : 4196da67e70SIvan Malov conf->efx_hash_types, 4206da67e70SIvan Malov rc); 4216da67e70SIvan Malov goto fail; 4226da67e70SIvan Malov } 4236da67e70SIvan Malov 4246da67e70SIvan Malov rc = efx_rx_scale_key_set(sa->nic, ctx->nic_handle, 4256da67e70SIvan Malov (ctx->dummy) ? ethdev_rss->key : conf->key, 4266da67e70SIvan Malov RTE_DIM(conf->key)); 4276da67e70SIvan Malov if (rc != 0) { 4286da67e70SIvan Malov sfc_err(sa, "flow-rss: failed to set key for ctx=%p; rc=%d", 4296da67e70SIvan Malov ctx, rc); 4306da67e70SIvan Malov goto fail; 4316da67e70SIvan Malov } 4326da67e70SIvan Malov 433be5cbe47SIvan Malov rc = sfc_flow_rss_ctx_program_tbl(sa, nb_tbl_entries, ctx); 4346da67e70SIvan Malov if (rc != 0) { 435be5cbe47SIvan Malov sfc_err(sa, "flow-rss: failed to program table for ctx=%p: nb_tbl_entries=%u; rc=%d", 436be5cbe47SIvan Malov ctx, nb_tbl_entries, rc); 4376da67e70SIvan Malov goto fail; 4386da67e70SIvan Malov } 4396da67e70SIvan Malov 4406da67e70SIvan Malov return 0; 4416da67e70SIvan Malov 4426da67e70SIvan Malov fail: 4436da67e70SIvan Malov if (allocation_done) 4446da67e70SIvan Malov sfc_flow_rss_ctx_terminate(sa, ctx); 4456da67e70SIvan Malov 4466da67e70SIvan Malov return rc; 4476da67e70SIvan Malov } 4486da67e70SIvan Malov 4496da67e70SIvan Malov void 4506da67e70SIvan Malov sfc_flow_rss_ctx_terminate(struct sfc_adapter *sa, struct sfc_flow_rss_ctx *ctx) 4516da67e70SIvan Malov { 4526da67e70SIvan Malov if (ctx == NULL) 4536da67e70SIvan Malov return; 4546da67e70SIvan Malov 4556da67e70SIvan Malov SFC_ASSERT(sfc_adapter_is_locked(sa)); 4566da67e70SIvan Malov 4576da67e70SIvan Malov SFC_ASSERT(ctx->nic_handle_refcnt != 0); 4586da67e70SIvan Malov --(ctx->nic_handle_refcnt); 4596da67e70SIvan Malov 4606da67e70SIvan Malov if (ctx->nic_handle_refcnt == 0) { 4616da67e70SIvan Malov int rc; 4626da67e70SIvan Malov 4636da67e70SIvan Malov rc = efx_rx_scale_context_free(sa->nic, ctx->nic_handle); 4646da67e70SIvan Malov if (rc != 0) { 4656da67e70SIvan Malov sfc_err(sa, "flow-rss: failed to release NIC resource for ctx=%p: handle=0x%08x; rc=%d", 4666da67e70SIvan Malov ctx, ctx->nic_handle, rc); 4676da67e70SIvan Malov 4686da67e70SIvan Malov sfc_warn(sa, "flow-rss: proceeding despite the prior error"); 4696da67e70SIvan Malov } 4706da67e70SIvan Malov 4716da67e70SIvan Malov sfc_dbg(sa, "flow-rss: released NIC resource for ctx=%p; rc=%d", 4726da67e70SIvan Malov ctx, rc); 4736da67e70SIvan Malov } 4746da67e70SIvan Malov } 475