app/testpmd: fix use of indirect action after port close
[dpdk.git] / drivers / net / sfc / sfc_flow_rss.c
index 17876f1..e28c943 100644 (file)
 int
 sfc_flow_rss_attach(struct sfc_adapter *sa)
 {
+       const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
        struct sfc_flow_rss *flow_rss = &sa->flow_rss;
+       int rc;
 
        sfc_log_init(sa, "entry");
 
+       flow_rss->qid_span_max = encp->enc_rx_scale_indirection_max_nqueues;
+       flow_rss->nb_tbl_entries_min = encp->enc_rx_scale_tbl_min_nentries;
+       flow_rss->nb_tbl_entries_max = encp->enc_rx_scale_tbl_max_nentries;
+
+       sfc_log_init(sa, "allocate the bounce buffer for indirection entries");
+       flow_rss->bounce_tbl = rte_calloc("sfc_flow_rss_bounce_tbl",
+                                         flow_rss->nb_tbl_entries_max,
+                                         sizeof(*flow_rss->bounce_tbl), 0);
+       if (flow_rss->bounce_tbl == NULL) {
+               rc = ENOMEM;
+               goto fail;
+       }
+
        TAILQ_INIT(&flow_rss->ctx_list);
 
        sfc_log_init(sa, "done");
 
        return 0;
+
+fail:
+       sfc_log_init(sa, "failed %d", rc);
+
+       return rc;
 }
 
 void
 sfc_flow_rss_detach(struct sfc_adapter *sa)
 {
+       struct sfc_flow_rss *flow_rss = &sa->flow_rss;
+
        sfc_log_init(sa, "entry");
 
+       sfc_log_init(sa, "free the bounce buffer for indirection entries");
+       rte_free(flow_rss->bounce_tbl);
+
        sfc_log_init(sa, "done");
 }
 
@@ -46,6 +71,7 @@ sfc_flow_rss_parse_conf(struct sfc_adapter *sa,
                        struct sfc_flow_rss_conf *out, uint16_t *sw_qid_minp)
 {
        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+       const struct sfc_flow_rss *flow_rss = &sa->flow_rss;
        const struct sfc_rss *ethdev_rss = &sas->rss;
        uint16_t sw_qid_min;
        uint16_t sw_qid_max;
@@ -114,14 +140,16 @@ sfc_flow_rss_parse_conf(struct sfc_adapter *sa,
                return EINVAL;
        }
 
+       out->rte_hash_function = in->func;
+
        if (in->queue_num == 0) {
                sfc_err(sa, "flow-rss: parse: 'queue_num' is 0; MIN=1");
                return EINVAL;
        }
 
-       if (in->queue_num > EFX_RSS_TBL_SIZE) {
+       if (in->queue_num > flow_rss->nb_tbl_entries_max) {
                sfc_err(sa, "flow-rss: parse: 'queue_num' is too large; MAX=%u",
-                       EFX_RSS_TBL_SIZE);
+                       flow_rss->nb_tbl_entries_max);
                return EINVAL;
        }
 
@@ -156,9 +184,9 @@ sfc_flow_rss_parse_conf(struct sfc_adapter *sa,
 
        out->qid_span = sw_qid_max - sw_qid_min + 1;
 
-       if (out->qid_span > EFX_MAXRSS) {
+       if (out->qid_span > flow_rss->qid_span_max) {
                sfc_err(sa, "flow-rss: parse: queue ID span %u is too large; MAX=%u",
-                       out->qid_span, EFX_MAXRSS);
+                       out->qid_span, flow_rss->qid_span_max);
                return EINVAL;
        }
 
@@ -282,6 +310,7 @@ sfc_flow_rss_ctx_del(struct sfc_adapter *sa, struct sfc_flow_rss_ctx *ctx)
 
 static int
 sfc_flow_rss_ctx_program_tbl(struct sfc_adapter *sa,
+                            unsigned int nb_tbl_entries,
                             const struct sfc_flow_rss_ctx *ctx)
 {
        const struct sfc_flow_rss_conf *conf = &ctx->conf;
@@ -290,18 +319,21 @@ sfc_flow_rss_ctx_program_tbl(struct sfc_adapter *sa,
 
        SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+       if (nb_tbl_entries == 0)
+               return 0;
+
        if (conf->nb_qid_offsets != 0) {
                SFC_ASSERT(ctx->qid_offsets != NULL);
 
-               for (i = 0; i < EFX_RSS_TBL_SIZE; ++i)
+               for (i = 0; i < nb_tbl_entries; ++i)
                        tbl[i] = ctx->qid_offsets[i % conf->nb_qid_offsets];
        } else {
-               for (i = 0; i < EFX_RSS_TBL_SIZE; ++i)
+               for (i = 0; i < nb_tbl_entries; ++i)
                        tbl[i] = i % conf->qid_span;
        }
 
        return efx_rx_scale_tbl_set(sa->nic, ctx->nic_handle,
-                                   tbl, EFX_RSS_TBL_SIZE);
+                                   tbl, nb_tbl_entries);
 }
 
 int
@@ -309,9 +341,13 @@ sfc_flow_rss_ctx_program(struct sfc_adapter *sa, struct sfc_flow_rss_ctx *ctx)
 {
        efx_rx_scale_context_type_t ctx_type = EFX_RX_SCALE_EXCLUSIVE;
        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+       const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+       const struct sfc_flow_rss *flow_rss = &sa->flow_rss;
        struct sfc_rss *ethdev_rss = &sas->rss;
        struct sfc_flow_rss_conf *conf;
        bool allocation_done = B_FALSE;
+       unsigned int nb_qid_offsets;
+       unsigned int nb_tbl_entries;
        int rc;
 
        if (ctx == NULL)
@@ -321,18 +357,47 @@ sfc_flow_rss_ctx_program(struct sfc_adapter *sa, struct sfc_flow_rss_ctx *ctx)
 
        SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+       if (conf->nb_qid_offsets != 0)
+               nb_qid_offsets = conf->nb_qid_offsets;
+       else
+               nb_qid_offsets = conf->qid_span;
+
+       if (!RTE_IS_POWER_OF_2(nb_qid_offsets)) {
+               /*
+                * Most likely, it pays to enlarge the indirection
+                * table to facilitate better distribution quality.
+                */
+               nb_qid_offsets = flow_rss->nb_tbl_entries_max;
+       }
+
+       nb_tbl_entries = RTE_MAX(flow_rss->nb_tbl_entries_min, nb_qid_offsets);
+
+       if (conf->rte_hash_function == RTE_ETH_HASH_FUNCTION_DEFAULT &&
+           conf->nb_qid_offsets == 0 &&
+           conf->qid_span <= encp->enc_rx_scale_even_spread_max_nqueues) {
+               /*
+                * Conformance to a specific hash algorithm is a don't care to
+                * the user. The queue array is contiguous and ascending. That
+                * means that the even spread context may be requested here in
+                * order to avoid wasting precious indirection table resources.
+                */
+               ctx_type = EFX_RX_SCALE_EVEN_SPREAD;
+               nb_tbl_entries = 0;
+       }
+
        if (ctx->nic_handle_refcnt == 0) {
-               rc = efx_rx_scale_context_alloc(sa->nic, ctx_type,
-                                               conf->qid_span,
-                                               &ctx->nic_handle);
+               rc = efx_rx_scale_context_alloc_v2(sa->nic, ctx_type,
+                                                  conf->qid_span,
+                                                  nb_tbl_entries,
+                                                  &ctx->nic_handle);
                if (rc != 0) {
-                       sfc_err(sa, "flow-rss: failed to allocate NIC resource for ctx=%p: type=%d, qid_span=%u, rc=%d",
-                               ctx, ctx_type, conf->qid_span, rc);
+                       sfc_err(sa, "flow-rss: failed to allocate NIC resource for ctx=%p: type=%d, qid_span=%u, nb_tbl_entries=%u; rc=%d",
+                               ctx, ctx_type, conf->qid_span, nb_tbl_entries, rc);
                        goto fail;
                }
 
-               sfc_dbg(sa, "flow-rss: allocated NIC resource for ctx=%p: type=%d, qid_span=%u; handle=0x%08x",
-                       ctx, ctx_type, conf->qid_span,
+               sfc_dbg(sa, "flow-rss: allocated NIC resource for ctx=%p: type=%d, qid_span=%u, nb_tbl_entries=%u; handle=0x%08x",
+                       ctx, ctx_type, conf->qid_span, nb_tbl_entries,
                        ctx->nic_handle);
 
                ++(ctx->nic_handle_refcnt);
@@ -365,10 +430,10 @@ sfc_flow_rss_ctx_program(struct sfc_adapter *sa, struct sfc_flow_rss_ctx *ctx)
                goto fail;
        }
 
-       rc = sfc_flow_rss_ctx_program_tbl(sa, ctx);
+       rc = sfc_flow_rss_ctx_program_tbl(sa, nb_tbl_entries, ctx);
        if (rc != 0) {
-               sfc_err(sa, "flow-rss: failed to program table for ctx=%p; rc=%d",
-                       ctx, rc);
+               sfc_err(sa, "flow-rss: failed to program table for ctx=%p: nb_tbl_entries=%u; rc=%d",
+                       ctx, nb_tbl_entries, rc);
                goto fail;
        }