get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/94493/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 94493,
    "url": "http://patches.dpdk.org/api/patches/94493/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20210618134032.1922012-13-andrew.rybchenko@oktetlabs.ru/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20210618134032.1922012-13-andrew.rybchenko@oktetlabs.ru>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210618134032.1922012-13-andrew.rybchenko@oktetlabs.ru",
    "date": "2021-06-18T13:40:24",
    "name": "[v3,12/20] net/sfc: reserve RxQ for counters",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "ab2dcbbfbb6be44354dbd2f423186a43ce812f7e",
    "submitter": {
        "id": 2013,
        "url": "http://patches.dpdk.org/api/people/2013/?format=api",
        "name": "Andrew Rybchenko",
        "email": "Andrew.Rybchenko@oktetlabs.ru"
    },
    "delegate": {
        "id": 24651,
        "url": "http://patches.dpdk.org/api/users/24651/?format=api",
        "username": "dmarchand",
        "first_name": "David",
        "last_name": "Marchand",
        "email": "david.marchand@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20210618134032.1922012-13-andrew.rybchenko@oktetlabs.ru/mbox/",
    "series": [
        {
            "id": 17397,
            "url": "http://patches.dpdk.org/api/series/17397/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=17397",
            "date": "2021-06-18T13:40:12",
            "name": "net/sfc: support flow API COUNT action",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/17397/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/94493/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/94493/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 29632A0C46;\n\tFri, 18 Jun 2021 15:42:16 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 87A164115C;\n\tFri, 18 Jun 2021 15:41:10 +0200 (CEST)",
            "from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113])\n by mails.dpdk.org (Postfix) with ESMTP id 3DD3141155\n for <dev@dpdk.org>; Fri, 18 Jun 2021 15:41:09 +0200 (CEST)",
            "by shelob.oktetlabs.ru (Postfix, from userid 122)\n id 0B4D57F53C; Fri, 18 Jun 2021 16:41:09 +0300 (MSK)",
            "from aros.oktetlabs.ru (aros.oktetlabs.ru [192.168.38.17])\n by shelob.oktetlabs.ru (Postfix) with ESMTP id 5FDC37F69A;\n Fri, 18 Jun 2021 16:40:35 +0300 (MSK)"
        ],
        "X-Spam-Checker-Version": "SpamAssassin 3.4.2 (2018-09-13) on shelob.oktetlabs.ru",
        "X-Spam-Level": "",
        "X-Spam-Status": "No, score=0.8 required=5.0 tests=ALL_TRUSTED,\n DKIM_ADSP_DISCARD,\n URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2",
        "DKIM-Filter": "OpenDKIM Filter v2.11.0 shelob.oktetlabs.ru 5FDC37F69A",
        "Authentication-Results": "shelob.oktetlabs.ru/5FDC37F69A; dkim=none;\n dkim-atps=neutral",
        "From": "Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>",
        "To": "dev@dpdk.org",
        "Cc": "David Marchand <david.marchand@redhat.com>,\n Igor Romanov <igor.romanov@oktetlabs.ru>,\n Andy Moreton <amoreton@xilinx.com>, Ivan Malov <ivan.malov@oktetlabs.ru>",
        "Date": "Fri, 18 Jun 2021 16:40:24 +0300",
        "Message-Id": "<20210618134032.1922012-13-andrew.rybchenko@oktetlabs.ru>",
        "X-Mailer": "git-send-email 2.30.2",
        "In-Reply-To": "<20210618134032.1922012-1-andrew.rybchenko@oktetlabs.ru>",
        "References": "<20210527152510.1551026-1-andrew.rybchenko@oktetlabs.ru>\n <20210618134032.1922012-1-andrew.rybchenko@oktetlabs.ru>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v3 12/20] net/sfc: reserve RxQ for counters",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Igor Romanov <igor.romanov@oktetlabs.ru>\n\nMAE delivers counters data as special packets via dedicated Rx queue.\nReserve an RxQ so that it does not interfere with ethdev Rx queues.\nA routine will be added later to handle these packets.\n\nThere is no point to reserve the queue if no service cores are\navailable and counters cannot be used.\n\nSigned-off-by: Igor Romanov <igor.romanov@oktetlabs.ru>\nSigned-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>\nReviewed-by: Andy Moreton <amoreton@xilinx.com>\nReviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru>\n---\n drivers/net/sfc/meson.build       |   1 +\n drivers/net/sfc/sfc.c             |  68 ++++++++--\n drivers/net/sfc/sfc.h             |  19 +++\n drivers/net/sfc/sfc_dp.h          |   2 +\n drivers/net/sfc/sfc_ev.h          |  72 ++++++++--\n drivers/net/sfc/sfc_mae.c         |   1 +\n drivers/net/sfc/sfc_mae_counter.c | 217 ++++++++++++++++++++++++++++++\n drivers/net/sfc/sfc_mae_counter.h |  44 ++++++\n drivers/net/sfc/sfc_rx.c          |  43 ++++--\n 9 files changed, 438 insertions(+), 29 deletions(-)\n create mode 100644 drivers/net/sfc/sfc_mae_counter.c\n create mode 100644 drivers/net/sfc/sfc_mae_counter.h",
    "diff": "diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build\nindex 4ac97e8d43..f8880f740a 100644\n--- a/drivers/net/sfc/meson.build\n+++ b/drivers/net/sfc/meson.build\n@@ -55,6 +55,7 @@ sources = files(\n         'sfc_filter.c',\n         'sfc_switch.c',\n         'sfc_mae.c',\n+        'sfc_mae_counter.c',\n         'sfc_flow.c',\n         'sfc_dp.c',\n         'sfc_ef10_rx.c',\ndiff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c\nindex 3477c7530b..4097cf39de 100644\n--- a/drivers/net/sfc/sfc.c\n+++ b/drivers/net/sfc/sfc.c\n@@ -20,6 +20,7 @@\n #include \"sfc_log.h\"\n #include \"sfc_ev.h\"\n #include \"sfc_rx.h\"\n+#include \"sfc_mae_counter.h\"\n #include \"sfc_tx.h\"\n #include \"sfc_kvargs.h\"\n #include \"sfc_tweak.h\"\n@@ -174,6 +175,7 @@ static int\n sfc_estimate_resource_limits(struct sfc_adapter *sa)\n {\n \tconst efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);\n+\tstruct sfc_adapter_shared *sas = sfc_sa2shared(sa);\n \tefx_drv_limits_t limits;\n \tint rc;\n \tuint32_t evq_allocated;\n@@ -235,17 +237,53 @@ sfc_estimate_resource_limits(struct sfc_adapter *sa)\n \trxq_allocated = MIN(rxq_allocated, limits.edl_max_rxq_count);\n \ttxq_allocated = MIN(txq_allocated, limits.edl_max_txq_count);\n \n-\t/* Subtract management EVQ not used for traffic */\n-\tSFC_ASSERT(evq_allocated > 0);\n+\t/*\n+\t * Subtract management EVQ not used for traffic\n+\t * The resource allocation strategy is as follows:\n+\t * - one EVQ for management\n+\t * - one EVQ for each ethdev RXQ\n+\t * - one EVQ for each ethdev TXQ\n+\t * - one EVQ and one RXQ for optional MAE counters.\n+\t */\n+\tif (evq_allocated == 0) {\n+\t\tsfc_err(sa, \"count of allocated EvQ is 0\");\n+\t\trc = ENOMEM;\n+\t\tgoto fail_allocate_evq;\n+\t}\n \tevq_allocated--;\n \n-\t/* Right now we use separate EVQ for Rx and Tx */\n-\tsa->rxq_max = MIN(rxq_allocated, evq_allocated / 2);\n-\tsa->txq_max = MIN(txq_allocated, evq_allocated - sa->rxq_max);\n+\t/*\n+\t * Reserve absolutely required minimum.\n+\t * Right now we use separate EVQ for Rx and Tx.\n+\t */\n+\tif (rxq_allocated > 0 && evq_allocated > 0) {\n+\t\tsa->rxq_max = 1;\n+\t\trxq_allocated--;\n+\t\tevq_allocated--;\n+\t}\n+\tif (txq_allocated > 0 && evq_allocated > 0) {\n+\t\tsa->txq_max = 1;\n+\t\ttxq_allocated--;\n+\t\tevq_allocated--;\n+\t}\n+\n+\tif (sfc_mae_counter_rxq_required(sa) &&\n+\t    rxq_allocated > 0 && evq_allocated > 0) {\n+\t\trxq_allocated--;\n+\t\tevq_allocated--;\n+\t\tsas->counters_rxq_allocated = true;\n+\t} else {\n+\t\tsas->counters_rxq_allocated = false;\n+\t}\n+\n+\t/* Add remaining allocated queues */\n+\tsa->rxq_max += MIN(rxq_allocated, evq_allocated / 2);\n+\tsa->txq_max += MIN(txq_allocated, evq_allocated - sa->rxq_max);\n \n \t/* Keep NIC initialized */\n \treturn 0;\n \n+fail_allocate_evq:\n fail_get_vi_pool:\n \tefx_nic_fini(sa->nic);\n fail_nic_init:\n@@ -256,14 +294,20 @@ static int\n sfc_set_drv_limits(struct sfc_adapter *sa)\n {\n \tconst struct rte_eth_dev_data *data = sa->eth_dev->data;\n+\tuint32_t rxq_reserved = sfc_nb_reserved_rxq(sfc_sa2shared(sa));\n \tefx_drv_limits_t lim;\n \n \tmemset(&lim, 0, sizeof(lim));\n \n-\t/* Limits are strict since take into account initial estimation */\n+\t/*\n+\t * Limits are strict since take into account initial estimation.\n+\t * Resource allocation stategy is described in\n+\t * sfc_estimate_resource_limits().\n+\t */\n \tlim.edl_min_evq_count = lim.edl_max_evq_count =\n-\t\t1 + data->nb_rx_queues + data->nb_tx_queues;\n-\tlim.edl_min_rxq_count = lim.edl_max_rxq_count = data->nb_rx_queues;\n+\t\t1 + data->nb_rx_queues + data->nb_tx_queues + rxq_reserved;\n+\tlim.edl_min_rxq_count = lim.edl_max_rxq_count =\n+\t\tdata->nb_rx_queues + rxq_reserved;\n \tlim.edl_min_txq_count = lim.edl_max_txq_count = data->nb_tx_queues;\n \n \treturn efx_nic_set_drv_limits(sa->nic, &lim);\n@@ -834,6 +878,10 @@ sfc_attach(struct sfc_adapter *sa)\n \tif (rc != 0)\n \t\tgoto fail_filter_attach;\n \n+\trc = sfc_mae_counter_rxq_attach(sa);\n+\tif (rc != 0)\n+\t\tgoto fail_mae_counter_rxq_attach;\n+\n \trc = sfc_mae_attach(sa);\n \tif (rc != 0)\n \t\tgoto fail_mae_attach;\n@@ -862,6 +910,9 @@ sfc_attach(struct sfc_adapter *sa)\n \tsfc_mae_detach(sa);\n \n fail_mae_attach:\n+\tsfc_mae_counter_rxq_detach(sa);\n+\n+fail_mae_counter_rxq_attach:\n \tsfc_filter_detach(sa);\n \n fail_filter_attach:\n@@ -903,6 +954,7 @@ sfc_detach(struct sfc_adapter *sa)\n \tsfc_flow_fini(sa);\n \n \tsfc_mae_detach(sa);\n+\tsfc_mae_counter_rxq_detach(sa);\n \tsfc_filter_detach(sa);\n \tsfc_rss_detach(sa);\n \tsfc_port_detach(sa);\ndiff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h\nindex 00fc26cf0e..546739bd4a 100644\n--- a/drivers/net/sfc/sfc.h\n+++ b/drivers/net/sfc/sfc.h\n@@ -186,6 +186,8 @@ struct sfc_adapter_shared {\n \n \tchar\t\t\t\t*dp_rx_name;\n \tchar\t\t\t\t*dp_tx_name;\n+\n+\tbool\t\t\t\tcounters_rxq_allocated;\n };\n \n /* Adapter process private data */\n@@ -205,6 +207,15 @@ sfc_adapter_priv_by_eth_dev(struct rte_eth_dev *eth_dev)\n \treturn sap;\n }\n \n+/* RxQ dedicated for counters (counter only RxQ) data */\n+struct sfc_counter_rxq {\n+\tunsigned int\t\t\tstate;\n+#define SFC_COUNTER_RXQ_ATTACHED\t\t0x1\n+#define SFC_COUNTER_RXQ_INITIALIZED\t\t0x2\n+\tsfc_sw_index_t\t\t\tsw_index;\n+\tstruct rte_mempool\t\t*mp;\n+};\n+\n /* Adapter private data */\n struct sfc_adapter {\n \t/*\n@@ -283,6 +294,8 @@ struct sfc_adapter {\n \tbool\t\t\t\tmgmt_evq_running;\n \tstruct sfc_evq\t\t\t*mgmt_evq;\n \n+\tstruct sfc_counter_rxq\t\tcounter_rxq;\n+\n \tstruct sfc_rxq\t\t\t*rxq_ctrl;\n \tstruct sfc_txq\t\t\t*txq_ctrl;\n \n@@ -357,6 +370,12 @@ sfc_adapter_lock_fini(__rte_unused struct sfc_adapter *sa)\n \t/* Just for symmetry of the API */\n }\n \n+static inline unsigned int\n+sfc_nb_counter_rxq(const struct sfc_adapter_shared *sas)\n+{\n+\treturn sas->counters_rxq_allocated ? 1 : 0;\n+}\n+\n /** Get the number of milliseconds since boot from the default timer */\n static inline uint64_t\n sfc_get_system_msecs(void)\ndiff --git a/drivers/net/sfc/sfc_dp.h b/drivers/net/sfc/sfc_dp.h\nindex 76065483d4..61c1a3fbac 100644\n--- a/drivers/net/sfc/sfc_dp.h\n+++ b/drivers/net/sfc/sfc_dp.h\n@@ -97,6 +97,8 @@ struct sfc_dp {\n TAILQ_HEAD(sfc_dp_list, sfc_dp);\n \n typedef unsigned int sfc_sw_index_t;\n+#define SFC_SW_INDEX_INVALID\t((sfc_sw_index_t)(UINT_MAX))\n+\n typedef int32_t\tsfc_ethdev_qid_t;\n #define SFC_ETHDEV_QID_INVALID\t((sfc_ethdev_qid_t)(-1))\n \ndiff --git a/drivers/net/sfc/sfc_ev.h b/drivers/net/sfc/sfc_ev.h\nindex 3f3c4b5b9a..b2a0380205 100644\n--- a/drivers/net/sfc/sfc_ev.h\n+++ b/drivers/net/sfc/sfc_ev.h\n@@ -66,36 +66,87 @@ sfc_mgmt_evq_sw_index(__rte_unused const struct sfc_adapter_shared *sas)\n \treturn 0;\n }\n \n+/* Return the number of Rx queues reserved for driver's internal use */\n+static inline unsigned int\n+sfc_nb_reserved_rxq(const struct sfc_adapter_shared *sas)\n+{\n+\treturn sfc_nb_counter_rxq(sas);\n+}\n+\n+static inline unsigned int\n+sfc_nb_reserved_evq(const struct sfc_adapter_shared *sas)\n+{\n+\t/* An EvQ is required for each reserved RxQ */\n+\treturn 1 + sfc_nb_reserved_rxq(sas);\n+}\n+\n+/*\n+ * The mapping functions that return SW index of a specific reserved\n+ * queue rely on the relative order of reserved queues. Some reserved\n+ * queues are optional, and if they are disabled or not supported, then\n+ * the function for that specific reserved queue will return previous\n+ * valid index of a reserved queue in the dependency chain or\n+ * SFC_SW_INDEX_INVALID if it is the first reserved queue in the chain.\n+ * If at least one of the reserved queues in the chain is enabled, then\n+ * the corresponding function will give valid SW index, even if previous\n+ * functions in the chain returned SFC_SW_INDEX_INVALID, since this value\n+ * is one less than the first valid SW index.\n+ *\n+ * The dependency mechanism is utilized to avoid regid defines for SW indices\n+ * for reserved queues and to allow these indices to shrink and make space\n+ * for ethdev queue indices when some of the reserved queues are disabled.\n+ */\n+\n+static inline sfc_sw_index_t\n+sfc_counters_rxq_sw_index(const struct sfc_adapter_shared *sas)\n+{\n+\treturn sas->counters_rxq_allocated ? 0 : SFC_SW_INDEX_INVALID;\n+}\n+\n /*\n  * Functions below define event queue to transmit/receive queue and vice\n  * versa mapping.\n+ * SFC_ETHDEV_QID_INVALID is returned when sw_index is converted to\n+ * ethdev_qid, but sw_index represents a reserved queue for driver's\n+ * internal use.\n  * Own event queue is allocated for management, each Rx and each Tx queue.\n  * Zero event queue is used for management events.\n- * Rx event queues from 1 to RxQ number follow management event queue.\n+ * When counters are supported, one Rx event queue is reserved.\n+ * Rx event queues follow reserved event queues.\n  * Tx event queues follow Rx event queues.\n  */\n \n static inline sfc_ethdev_qid_t\n-sfc_ethdev_rx_qid_by_rxq_sw_index(__rte_unused struct sfc_adapter_shared *sas,\n+sfc_ethdev_rx_qid_by_rxq_sw_index(struct sfc_adapter_shared *sas,\n \t\t\t\t  sfc_sw_index_t rxq_sw_index)\n {\n-\t/* Only ethdev queues are present for now */\n-\treturn rxq_sw_index;\n+\tif (rxq_sw_index < sfc_nb_reserved_rxq(sas))\n+\t\treturn SFC_ETHDEV_QID_INVALID;\n+\n+\treturn rxq_sw_index - sfc_nb_reserved_rxq(sas);\n }\n \n static inline sfc_sw_index_t\n-sfc_rxq_sw_index_by_ethdev_rx_qid(__rte_unused struct sfc_adapter_shared *sas,\n+sfc_rxq_sw_index_by_ethdev_rx_qid(struct sfc_adapter_shared *sas,\n \t\t\t\t  sfc_ethdev_qid_t ethdev_qid)\n {\n-\t/* Only ethdev queues are present for now */\n-\treturn ethdev_qid;\n+\treturn sfc_nb_reserved_rxq(sas) + ethdev_qid;\n }\n \n static inline sfc_sw_index_t\n-sfc_evq_sw_index_by_rxq_sw_index(__rte_unused struct sfc_adapter *sa,\n+sfc_evq_sw_index_by_rxq_sw_index(struct sfc_adapter *sa,\n \t\t\t\t sfc_sw_index_t rxq_sw_index)\n {\n-\treturn 1 + rxq_sw_index;\n+\tstruct sfc_adapter_shared *sas = sfc_sa2shared(sa);\n+\tsfc_ethdev_qid_t ethdev_qid;\n+\n+\tethdev_qid = sfc_ethdev_rx_qid_by_rxq_sw_index(sas, rxq_sw_index);\n+\tif (ethdev_qid == SFC_ETHDEV_QID_INVALID) {\n+\t\t/* One EvQ is reserved for management */\n+\t\treturn 1 + rxq_sw_index;\n+\t}\n+\n+\treturn sfc_nb_reserved_evq(sas) + ethdev_qid;\n }\n \n static inline sfc_ethdev_qid_t\n@@ -118,7 +169,8 @@ static inline sfc_sw_index_t\n sfc_evq_sw_index_by_txq_sw_index(struct sfc_adapter *sa,\n \t\t\t\t sfc_sw_index_t txq_sw_index)\n {\n-\treturn 1 + sa->eth_dev->data->nb_rx_queues + txq_sw_index;\n+\treturn sfc_nb_reserved_evq(sfc_sa2shared(sa)) +\n+\t\tsa->eth_dev->data->nb_rx_queues + txq_sw_index;\n }\n \n int sfc_ev_attach(struct sfc_adapter *sa);\ndiff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c\nindex a2c0aa1436..8ffcf72d88 100644\n--- a/drivers/net/sfc/sfc_mae.c\n+++ b/drivers/net/sfc/sfc_mae.c\n@@ -16,6 +16,7 @@\n #include \"efx.h\"\n \n #include \"sfc.h\"\n+#include \"sfc_mae_counter.h\"\n #include \"sfc_log.h\"\n #include \"sfc_switch.h\"\n \ndiff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c\nnew file mode 100644\nindex 0000000000..c7646cf7b1\n--- /dev/null\n+++ b/drivers/net/sfc/sfc_mae_counter.c\n@@ -0,0 +1,217 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ *\n+ * Copyright(c) 2020-2021 Xilinx, Inc.\n+ */\n+\n+#include <rte_common.h>\n+\n+#include \"efx.h\"\n+\n+#include \"sfc_ev.h\"\n+#include \"sfc.h\"\n+#include \"sfc_rx.h\"\n+#include \"sfc_mae_counter.h\"\n+#include \"sfc_service.h\"\n+\n+static uint32_t\n+sfc_mae_counter_get_service_lcore(struct sfc_adapter *sa)\n+{\n+\tuint32_t cid;\n+\n+\tcid = sfc_get_service_lcore(sa->socket_id);\n+\tif (cid != RTE_MAX_LCORE)\n+\t\treturn cid;\n+\n+\tif (sa->socket_id != SOCKET_ID_ANY)\n+\t\tcid = sfc_get_service_lcore(SOCKET_ID_ANY);\n+\n+\tif (cid == RTE_MAX_LCORE) {\n+\t\tsfc_warn(sa, \"failed to get service lcore for counter service\");\n+\t} else if (sa->socket_id != SOCKET_ID_ANY) {\n+\t\tsfc_warn(sa,\n+\t\t\t\"failed to get service lcore for counter service at socket %d, but got at socket %u\",\n+\t\t\tsa->socket_id, rte_lcore_to_socket_id(cid));\n+\t}\n+\treturn cid;\n+}\n+\n+bool\n+sfc_mae_counter_rxq_required(struct sfc_adapter *sa)\n+{\n+\tconst efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);\n+\n+\tif (encp->enc_mae_supported == B_FALSE)\n+\t\treturn false;\n+\n+\tif (sfc_mae_counter_get_service_lcore(sa) == RTE_MAX_LCORE)\n+\t\treturn false;\n+\n+\treturn true;\n+}\n+\n+int\n+sfc_mae_counter_rxq_attach(struct sfc_adapter *sa)\n+{\n+\tstruct sfc_adapter_shared * const sas = sfc_sa2shared(sa);\n+\tchar name[RTE_MEMPOOL_NAMESIZE];\n+\tstruct rte_mempool *mp;\n+\tunsigned int n_elements;\n+\tunsigned int cache_size;\n+\t/* The mempool is internal and private area is not required */\n+\tconst uint16_t priv_size = 0;\n+\tconst uint16_t data_room_size = RTE_PKTMBUF_HEADROOM +\n+\t\tSFC_MAE_COUNTER_STREAM_PACKET_SIZE;\n+\tint rc;\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tif (!sas->counters_rxq_allocated) {\n+\t\tsfc_log_init(sa, \"counter queue is not supported - skip\");\n+\t\treturn 0;\n+\t}\n+\n+\t/*\n+\t * At least one element in the ring is always unused to distinguish\n+\t * between empty and full ring cases.\n+\t */\n+\tn_elements = SFC_COUNTER_RXQ_RX_DESC_COUNT - 1;\n+\n+\t/*\n+\t * The cache must have sufficient space to put received buckets\n+\t * before they're reused on refill.\n+\t */\n+\tcache_size = rte_align32pow2(SFC_COUNTER_RXQ_REFILL_LEVEL +\n+\t\t\t\t     SFC_MAE_COUNTER_RX_BURST - 1);\n+\n+\tif (snprintf(name, sizeof(name), \"counter_rxq-pool-%u\", sas->port_id) >=\n+\t    (int)sizeof(name)) {\n+\t\tsfc_err(sa, \"failed: counter RxQ mempool name is too long\");\n+\t\trc = ENAMETOOLONG;\n+\t\tgoto fail_long_name;\n+\t}\n+\n+\t/*\n+\t * It could be single-producer single-consumer ring mempool which\n+\t * requires minimal barriers. However, cache size and refill/burst\n+\t * policy are aligned, therefore it does not matter which\n+\t * mempool backend is chosen since backend is unused.\n+\t */\n+\tmp = rte_pktmbuf_pool_create(name, n_elements, cache_size,\n+\t\t\t\t     priv_size, data_room_size, sa->socket_id);\n+\tif (mp == NULL) {\n+\t\tsfc_err(sa, \"failed to create counter RxQ mempool\");\n+\t\trc = rte_errno;\n+\t\tgoto fail_mp_create;\n+\t}\n+\n+\tsa->counter_rxq.sw_index = sfc_counters_rxq_sw_index(sas);\n+\tsa->counter_rxq.mp = mp;\n+\tsa->counter_rxq.state |= SFC_COUNTER_RXQ_ATTACHED;\n+\n+\tsfc_log_init(sa, \"done\");\n+\n+\treturn 0;\n+\n+fail_mp_create:\n+fail_long_name:\n+\tsfc_log_init(sa, \"failed: %s\", rte_strerror(rc));\n+\n+\treturn rc;\n+}\n+\n+void\n+sfc_mae_counter_rxq_detach(struct sfc_adapter *sa)\n+{\n+\tstruct sfc_adapter_shared * const sas = sfc_sa2shared(sa);\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tif (!sas->counters_rxq_allocated) {\n+\t\tsfc_log_init(sa, \"counter queue is not supported - skip\");\n+\t\treturn;\n+\t}\n+\n+\tif ((sa->counter_rxq.state & SFC_COUNTER_RXQ_ATTACHED) == 0) {\n+\t\tsfc_log_init(sa, \"counter queue is not attached - skip\");\n+\t\treturn;\n+\t}\n+\n+\trte_mempool_free(sa->counter_rxq.mp);\n+\tsa->counter_rxq.mp = NULL;\n+\tsa->counter_rxq.state &= ~SFC_COUNTER_RXQ_ATTACHED;\n+\n+\tsfc_log_init(sa, \"done\");\n+}\n+\n+int\n+sfc_mae_counter_rxq_init(struct sfc_adapter *sa)\n+{\n+\tstruct sfc_adapter_shared * const sas = sfc_sa2shared(sa);\n+\tconst struct rte_eth_rxconf rxconf = {\n+\t\t.rx_free_thresh = SFC_COUNTER_RXQ_REFILL_LEVEL,\n+\t\t.rx_drop_en = 1,\n+\t};\n+\tuint16_t nb_rx_desc = SFC_COUNTER_RXQ_RX_DESC_COUNT;\n+\tint rc;\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tif (!sas->counters_rxq_allocated) {\n+\t\tsfc_log_init(sa, \"counter queue is not supported - skip\");\n+\t\treturn 0;\n+\t}\n+\n+\tif ((sa->counter_rxq.state & SFC_COUNTER_RXQ_ATTACHED) == 0) {\n+\t\tsfc_log_init(sa, \"counter queue is not attached - skip\");\n+\t\treturn 0;\n+\t}\n+\n+\tnb_rx_desc = RTE_MIN(nb_rx_desc, sa->rxq_max_entries);\n+\tnb_rx_desc = RTE_MAX(nb_rx_desc, sa->rxq_min_entries);\n+\n+\trc = sfc_rx_qinit_info(sa, sa->counter_rxq.sw_index,\n+\t\t\t       EFX_RXQ_FLAG_USER_MARK);\n+\tif (rc != 0)\n+\t\tgoto fail_counter_rxq_init_info;\n+\n+\trc = sfc_rx_qinit(sa, sa->counter_rxq.sw_index, nb_rx_desc,\n+\t\t\t  sa->socket_id, &rxconf, sa->counter_rxq.mp);\n+\tif (rc != 0) {\n+\t\tsfc_err(sa, \"failed to init counter RxQ\");\n+\t\tgoto fail_counter_rxq_init;\n+\t}\n+\n+\tsa->counter_rxq.state |= SFC_COUNTER_RXQ_INITIALIZED;\n+\n+\tsfc_log_init(sa, \"done\");\n+\n+\treturn 0;\n+\n+fail_counter_rxq_init:\n+fail_counter_rxq_init_info:\n+\tsfc_log_init(sa, \"failed: %s\", rte_strerror(rc));\n+\n+\treturn rc;\n+}\n+\n+void\n+sfc_mae_counter_rxq_fini(struct sfc_adapter *sa)\n+{\n+\tstruct sfc_adapter_shared * const sas = sfc_sa2shared(sa);\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tif (!sas->counters_rxq_allocated) {\n+\t\tsfc_log_init(sa, \"counter queue is not supported - skip\");\n+\t\treturn;\n+\t}\n+\n+\tif ((sa->counter_rxq.state & SFC_COUNTER_RXQ_INITIALIZED) == 0) {\n+\t\tsfc_log_init(sa, \"counter queue is not initialized - skip\");\n+\t\treturn;\n+\t}\n+\n+\tsfc_rx_qfini(sa, sa->counter_rxq.sw_index);\n+\n+\tsfc_log_init(sa, \"done\");\n+}\ndiff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h\nnew file mode 100644\nindex 0000000000..f16d64a999\n--- /dev/null\n+++ b/drivers/net/sfc/sfc_mae_counter.h\n@@ -0,0 +1,44 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ *\n+ * Copyright(c) 2020-2021 Xilinx, Inc.\n+ */\n+\n+#ifndef _SFC_MAE_COUNTER_H\n+#define _SFC_MAE_COUNTER_H\n+\n+#include \"sfc.h\"\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+/* Default values for a user of counter RxQ */\n+#define SFC_MAE_COUNTER_RX_BURST 32\n+#define SFC_COUNTER_RXQ_RX_DESC_COUNT 256\n+\n+/*\n+ * The refill level is chosen based on requirement to keep number\n+ * of give credits operations low.\n+ */\n+#define SFC_COUNTER_RXQ_REFILL_LEVEL (SFC_COUNTER_RXQ_RX_DESC_COUNT / 4)\n+\n+/*\n+ * SF-122415-TC states that the packetiser that generates packets for\n+ * counter stream must support 9k frames. Set it to the maximum supported\n+ * size since in case of huge flow of counters, having fewer packets in counter\n+ * updates is better.\n+ */\n+#define SFC_MAE_COUNTER_STREAM_PACKET_SIZE 9216\n+\n+bool sfc_mae_counter_rxq_required(struct sfc_adapter *sa);\n+\n+int sfc_mae_counter_rxq_attach(struct sfc_adapter *sa);\n+void sfc_mae_counter_rxq_detach(struct sfc_adapter *sa);\n+\n+int sfc_mae_counter_rxq_init(struct sfc_adapter *sa);\n+void sfc_mae_counter_rxq_fini(struct sfc_adapter *sa);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+#endif  /* _SFC_MAE_COUNTER_H */\ndiff --git a/drivers/net/sfc/sfc_rx.c b/drivers/net/sfc/sfc_rx.c\nindex c7a7bd66ef..0532f77082 100644\n--- a/drivers/net/sfc/sfc_rx.c\n+++ b/drivers/net/sfc/sfc_rx.c\n@@ -16,6 +16,7 @@\n #include \"sfc_log.h\"\n #include \"sfc_ev.h\"\n #include \"sfc_rx.h\"\n+#include \"sfc_mae_counter.h\"\n #include \"sfc_kvargs.h\"\n #include \"sfc_tweak.h\"\n \n@@ -1705,6 +1706,9 @@ sfc_rx_configure(struct sfc_adapter *sa)\n \tstruct sfc_rss *rss = &sas->rss;\n \tstruct rte_eth_conf *dev_conf = &sa->eth_dev->data->dev_conf;\n \tconst unsigned int nb_rx_queues = sa->eth_dev->data->nb_rx_queues;\n+\tconst unsigned int nb_rsrv_rx_queues = sfc_nb_reserved_rxq(sas);\n+\tconst unsigned int nb_rxq_total = nb_rx_queues + nb_rsrv_rx_queues;\n+\tbool reconfigure;\n \tint rc;\n \n \tsfc_log_init(sa, \"nb_rx_queues=%u (old %u)\",\n@@ -1714,12 +1718,15 @@ sfc_rx_configure(struct sfc_adapter *sa)\n \tif (rc != 0)\n \t\tgoto fail_check_mode;\n \n-\tif (nb_rx_queues == sas->rxq_count)\n+\tif (nb_rxq_total == sas->rxq_count) {\n+\t\treconfigure = true;\n \t\tgoto configure_rss;\n+\t}\n \n \tif (sas->rxq_info == NULL) {\n+\t\treconfigure = false;\n \t\trc = ENOMEM;\n-\t\tsas->rxq_info = rte_calloc_socket(\"sfc-rxqs\", nb_rx_queues,\n+\t\tsas->rxq_info = rte_calloc_socket(\"sfc-rxqs\", nb_rxq_total,\n \t\t\t\t\t\t  sizeof(sas->rxq_info[0]), 0,\n \t\t\t\t\t\t  sa->socket_id);\n \t\tif (sas->rxq_info == NULL)\n@@ -1730,39 +1737,42 @@ sfc_rx_configure(struct sfc_adapter *sa)\n \t\t * since it should not be shared.\n \t\t */\n \t\trc = ENOMEM;\n-\t\tsa->rxq_ctrl = calloc(nb_rx_queues, sizeof(sa->rxq_ctrl[0]));\n+\t\tsa->rxq_ctrl = calloc(nb_rxq_total, sizeof(sa->rxq_ctrl[0]));\n \t\tif (sa->rxq_ctrl == NULL)\n \t\t\tgoto fail_rxqs_ctrl_alloc;\n \t} else {\n \t\tstruct sfc_rxq_info *new_rxq_info;\n \t\tstruct sfc_rxq *new_rxq_ctrl;\n \n+\t\treconfigure = true;\n+\n+\t\t/* Do not ununitialize reserved queues */\n \t\tif (nb_rx_queues < sas->ethdev_rxq_count)\n \t\t\tsfc_rx_fini_queues(sa, nb_rx_queues);\n \n \t\trc = ENOMEM;\n \t\tnew_rxq_info =\n \t\t\trte_realloc(sas->rxq_info,\n-\t\t\t\t    nb_rx_queues * sizeof(sas->rxq_info[0]), 0);\n-\t\tif (new_rxq_info == NULL && nb_rx_queues > 0)\n+\t\t\t\t    nb_rxq_total * sizeof(sas->rxq_info[0]), 0);\n+\t\tif (new_rxq_info == NULL && nb_rxq_total > 0)\n \t\t\tgoto fail_rxqs_realloc;\n \n \t\trc = ENOMEM;\n \t\tnew_rxq_ctrl = realloc(sa->rxq_ctrl,\n-\t\t\t\t       nb_rx_queues * sizeof(sa->rxq_ctrl[0]));\n-\t\tif (new_rxq_ctrl == NULL && nb_rx_queues > 0)\n+\t\t\t\t       nb_rxq_total * sizeof(sa->rxq_ctrl[0]));\n+\t\tif (new_rxq_ctrl == NULL && nb_rxq_total > 0)\n \t\t\tgoto fail_rxqs_ctrl_realloc;\n \n \t\tsas->rxq_info = new_rxq_info;\n \t\tsa->rxq_ctrl = new_rxq_ctrl;\n-\t\tif (nb_rx_queues > sas->rxq_count) {\n+\t\tif (nb_rxq_total > sas->rxq_count) {\n \t\t\tunsigned int rxq_count = sas->rxq_count;\n \n \t\t\tmemset(&sas->rxq_info[rxq_count], 0,\n-\t\t\t       (nb_rx_queues - rxq_count) *\n+\t\t\t       (nb_rxq_total - rxq_count) *\n \t\t\t       sizeof(sas->rxq_info[0]));\n \t\t\tmemset(&sa->rxq_ctrl[rxq_count], 0,\n-\t\t\t       (nb_rx_queues - rxq_count) *\n+\t\t\t       (nb_rxq_total - rxq_count) *\n \t\t\t       sizeof(sa->rxq_ctrl[0]));\n \t\t}\n \t}\n@@ -1779,7 +1789,13 @@ sfc_rx_configure(struct sfc_adapter *sa)\n \t\tsas->ethdev_rxq_count++;\n \t}\n \n-\tsas->rxq_count = sas->ethdev_rxq_count;\n+\tsas->rxq_count = sas->ethdev_rxq_count + nb_rsrv_rx_queues;\n+\n+\tif (!reconfigure) {\n+\t\trc = sfc_mae_counter_rxq_init(sa);\n+\t\tif (rc != 0)\n+\t\t\tgoto fail_count_rxq_init;\n+\t}\n \n configure_rss:\n \trss->channels = (dev_conf->rxmode.mq_mode == ETH_MQ_RX_RSS) ?\n@@ -1801,6 +1817,10 @@ sfc_rx_configure(struct sfc_adapter *sa)\n \treturn 0;\n \n fail_rx_process_adv_conf_rss:\n+\tif (!reconfigure)\n+\t\tsfc_mae_counter_rxq_fini(sa);\n+\n+fail_count_rxq_init:\n fail_rx_qinit_info:\n fail_rxqs_ctrl_realloc:\n fail_rxqs_realloc:\n@@ -1824,6 +1844,7 @@ sfc_rx_close(struct sfc_adapter *sa)\n \tstruct sfc_rss *rss = &sfc_sa2shared(sa)->rss;\n \n \tsfc_rx_fini_queues(sa, 0);\n+\tsfc_mae_counter_rxq_fini(sa);\n \n \trss->channels = 0;\n \n",
    "prefixes": [
        "v3",
        "12/20"
    ]
}