get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 127902,
    "url": "http://patchwork.dpdk.org/api/patches/127902/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20230601195538.8265-30-ivan.malov@arknetworks.am/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20230601195538.8265-30-ivan.malov@arknetworks.am>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230601195538.8265-30-ivan.malov@arknetworks.am",
    "date": "2023-06-01T19:55:33",
    "name": "[29/34] net/sfc: rework MAE action rule counter representation in SW",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "4027a1d7831120e798b723e055cd335faaab3962",
    "submitter": {
        "id": 2962,
        "url": "http://patchwork.dpdk.org/api/people/2962/?format=api",
        "name": "Ivan Malov",
        "email": "ivan.malov@arknetworks.am"
    },
    "delegate": {
        "id": 319,
        "url": "http://patchwork.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20230601195538.8265-30-ivan.malov@arknetworks.am/mbox/",
    "series": [
        {
            "id": 28307,
            "url": "http://patchwork.dpdk.org/api/series/28307/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=28307",
            "date": "2023-06-01T19:55:04",
            "name": "net/sfc: support HW conntrack assistance",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/28307/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/127902/comments/",
    "check": "warning",
    "checks": "http://patchwork.dpdk.org/api/patches/127902/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 5D8A742C07;\n\tThu,  1 Jun 2023 21:58:53 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id D9A264300C;\n\tThu,  1 Jun 2023 21:56:17 +0200 (CEST)",
            "from agw.arknetworks.am (agw.arknetworks.am [79.141.165.80])\n by mails.dpdk.org (Postfix) with ESMTP id 1B4FC42D86\n for <dev@dpdk.org>; Thu,  1 Jun 2023 21:55:57 +0200 (CEST)",
            "from localhost.localdomain (unknown [78.109.69.146])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by agw.arknetworks.am (Postfix) with ESMTPSA id A2466E121D;\n Thu,  1 Jun 2023 23:55:56 +0400 (+04)"
        ],
        "From": "Ivan Malov <ivan.malov@arknetworks.am>",
        "To": "dev@dpdk.org",
        "Cc": "Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>,\n Ferruh Yigit <ferruh.yigit@amd.com>, Andy Moreton <amoreton@xilinx.com>",
        "Subject": "[PATCH 29/34] net/sfc: rework MAE action rule counter representation\n in SW",
        "Date": "Thu,  1 Jun 2023 23:55:33 +0400",
        "Message-Id": "<20230601195538.8265-30-ivan.malov@arknetworks.am>",
        "X-Mailer": "git-send-email 2.30.2",
        "In-Reply-To": "<20230601195538.8265-1-ivan.malov@arknetworks.am>",
        "References": "<20230601195538.8265-1-ivan.malov@arknetworks.am>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "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"
    },
    "content": "Such rework is needed to prepare for INDIRECT action support\nand in order to align with the latest HW support perspective.\n\nCurrently, the driver supports only one counter per flow. It\nwas once thought that MAE would support multiple counters in\none action set. That was partly envisaged in code and naming.\nBut HW support for the feature is no longer planned in EF100.\n\nThe code also assumes that a counter object cannot be shared.\nThis assumption is outdated. The driver may support this now\nvia action of type INDIRECT provided by generic flow library.\n\nSigned-off-by: Ivan Malov <ivan.malov@arknetworks.am>\nReviewed-by: Andy Moreton <amoreton@xilinx.com>\n---\n drivers/net/sfc/sfc_mae.c         | 342 +++++++++++++++++-------------\n drivers/net/sfc/sfc_mae.h         |  17 +-\n drivers/net/sfc/sfc_mae_counter.c |  22 +-\n 3 files changed, 211 insertions(+), 170 deletions(-)",
    "diff": "diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c\nindex 98cc60e04d..d44e066493 100644\n--- a/drivers/net/sfc/sfc_mae.c\n+++ b/drivers/net/sfc/sfc_mae.c\n@@ -205,6 +205,7 @@ sfc_mae_attach(struct sfc_adapter *sa)\n \tTAILQ_INIT(&mae->outer_rules);\n \tTAILQ_INIT(&mae->mac_addrs);\n \tTAILQ_INIT(&mae->encap_headers);\n+\tTAILQ_INIT(&mae->counters);\n \tTAILQ_INIT(&mae->action_sets);\n \tTAILQ_INIT(&mae->action_rules);\n \n@@ -816,72 +817,155 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,\n }\n \n static int\n-sfc_mae_counters_enable(struct sfc_adapter *sa,\n-\t\t\tstruct sfc_mae_counter *counters,\n-\t\t\tunsigned int n_counters,\n-\t\t\tefx_mae_actions_t *action_set_spec)\n+sfc_mae_counter_add(struct sfc_adapter *sa,\n+\t\t    const struct sfc_mae_counter *counter_tmp,\n+\t\t    struct sfc_mae_counter **counterp)\n {\n-\tint rc;\n+\tstruct sfc_mae_counter *counter;\n+\tstruct sfc_mae *mae = &sa->mae;\n \n-\tsfc_log_init(sa, \"entry\");\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n \n-\tif (n_counters == 0) {\n-\t\tsfc_log_init(sa, \"no counters - skip\");\n-\t\treturn 0;\n+\tcounter = rte_zmalloc(\"sfc_mae_counter\", sizeof(*counter), 0);\n+\tif (counter == NULL)\n+\t\treturn ENOMEM;\n+\n+\tif (counter_tmp != NULL) {\n+\t\tcounter->rte_id_valid = counter_tmp->rte_id_valid;\n+\t\tcounter->rte_id = counter_tmp->rte_id;\n \t}\n \n-\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n-\tSFC_ASSERT(n_counters == 1);\n+\tcounter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;\n+\tcounter->refcnt = 1;\n \n-\trc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);\n-\tif (rc != 0) {\n-\t\tsfc_err(sa, \"failed to enable MAE counter %u: %s\",\n-\t\t\tcounters[0].mae_id.id, rte_strerror(rc));\n-\t\tgoto fail_counter_add;\n-\t}\n+\tTAILQ_INSERT_TAIL(&mae->counters, counter, entries);\n+\t*counterp = counter;\n \n-\trc = efx_mae_action_set_fill_in_counter_id(action_set_spec,\n-\t\t\t\t\t\t   &counters[0].mae_id);\n-\tif (rc != 0) {\n-\t\tsfc_err(sa, \"failed to fill in MAE counter %u in action set: %s\",\n-\t\t\tcounters[0].mae_id.id, rte_strerror(rc));\n-\t\tgoto fail_fill_in_id;\n-\t}\n+\tsfc_dbg(sa, \"added counter=%p\", counter);\n \n \treturn 0;\n+}\n+\n+static void\n+sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)\n+{\n+\tstruct sfc_mae *mae = &sa->mae;\n \n-fail_fill_in_id:\n-\t(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);\n+\tif (counter == NULL)\n+\t\treturn;\n \n-fail_counter_add:\n-\tsfc_log_init(sa, \"failed: %s\", rte_strerror(rc));\n-\treturn rc;\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\tSFC_ASSERT(counter->refcnt != 0);\n+\n+\t--(counter->refcnt);\n+\n+\tif (counter->refcnt != 0)\n+\t\treturn;\n+\n+\tif (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||\n+\t    counter->fw_rsrc.refcnt != 0) {\n+\t\tsfc_err(sa, \"deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u\",\n+\t\t\tcounter, counter->fw_rsrc.counter_id.id,\n+\t\t\tcounter->fw_rsrc.refcnt);\n+\t}\n+\n+\tTAILQ_REMOVE(&mae->counters, counter, entries);\n+\trte_free(counter);\n+\n+\tsfc_dbg(sa, \"deleted counter=%p\", counter);\n }\n \n static int\n-sfc_mae_counters_disable(struct sfc_adapter *sa,\n-\t\t\t struct sfc_mae_counter *counters,\n-\t\t\t unsigned int n_counters)\n+sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,\n+\t\t       efx_mae_actions_t *action_set_spec)\n {\n-\tif (n_counters == 0)\n+\tstruct sfc_mae_fw_rsrc *fw_rsrc;\n+\tint rc;\n+\n+\tif (counter == NULL)\n \t\treturn 0;\n \n \tSFC_ASSERT(sfc_adapter_is_locked(sa));\n-\tSFC_ASSERT(n_counters == 1);\n \n-\tif (counters[0].mae_id.id == EFX_MAE_RSRC_ID_INVALID) {\n-\t\tsfc_err(sa, \"failed to disable: already disabled\");\n-\t\treturn EALREADY;\n+\tfw_rsrc = &counter->fw_rsrc;\n+\n+\tif (fw_rsrc->refcnt == 0) {\n+\t\tSFC_ASSERT(fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID);\n+\n+\t\trc = sfc_mae_counter_fw_rsrc_enable(sa, counter);\n+\t\tif (rc != 0) {\n+\t\t\tsfc_err(sa, \"failed to enable counter=%p: %s\",\n+\t\t\t\tcounter, rte_strerror(rc));\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\tif (action_set_spec != NULL) {\n+\t\trc = efx_mae_action_set_fill_in_counter_id(\n+\t\t\t\t\taction_set_spec, &fw_rsrc->counter_id);\n+\t\tif (rc != 0) {\n+\t\t\tif (fw_rsrc->refcnt == 0) {\n+\t\t\t\t(void)sfc_mae_counter_fw_rsrc_disable(sa, counter);\n+\t\t\t\tfw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;\n+\t\t\t}\n+\n+\t\t\tsfc_err(sa, \"cannot fill in counter ID: %s\",\n+\t\t\t\tstrerror(rc));\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\tif (fw_rsrc->refcnt == 0) {\n+\t\tsfc_dbg(sa, \"enabled counter=%p: COUNTER_ID=0x%08x\",\n+\t\t\tcounter, fw_rsrc->counter_id.id);\n+\t}\n+\n+\t++(fw_rsrc->refcnt);\n+\n+\treturn 0;\n+}\n+\n+static void\n+sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)\n+{\n+\tstruct sfc_mae_fw_rsrc *fw_rsrc;\n+\tint rc;\n+\n+\tif (counter == NULL)\n+\t\treturn;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\tfw_rsrc = &counter->fw_rsrc;\n+\n+\tif (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||\n+\t    fw_rsrc->refcnt == 0) {\n+\t\tsfc_err(sa, \"failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u\",\n+\t\t\tcounter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);\n+\t\treturn;\n+\t}\n+\n+\tif (fw_rsrc->refcnt == 1) {\n+\t\tuint32_t counter_id = fw_rsrc->counter_id.id;\n+\n+\t\trc = sfc_mae_counter_fw_rsrc_disable(sa, counter);\n+\t\tif (rc == 0) {\n+\t\t\tsfc_dbg(sa, \"disabled counter=%p with COUNTER_ID=0x%08x\",\n+\t\t\t\tcounter, counter_id);\n+\t\t} else {\n+\t\t\tsfc_err(sa, \"failed to disable counter=%p with COUNTER_ID=0x%08x: %s\",\n+\t\t\t\tcounter, counter_id, strerror(rc));\n+\t\t}\n+\n+\t\tfw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;\n \t}\n \n-\treturn sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);\n+\t--(fw_rsrc->refcnt);\n }\n \n struct sfc_mae_aset_ctx {\n-\tuint64_t\t\t\t*ft_switch_hit_counter;\n-\tstruct sfc_ft_ctx\t\t*counter_ft_ctx;\n \tstruct sfc_mae_encap_header\t*encap_header;\n-\tunsigned int\t\t\tn_counters;\n+\tstruct sfc_mae_counter\t\t*counter;\n \tstruct sfc_mae_mac_addr\t\t*dst_mac;\n \tstruct sfc_mae_mac_addr\t\t*src_mac;\n \n@@ -897,17 +981,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,\n \n \tSFC_ASSERT(sfc_adapter_is_locked(sa));\n \n-\t/*\n-\t * Shared counters are not supported, hence, action\n-\t * sets with counters are not attachable.\n-\t */\n-\tif (ctx->n_counters != 0)\n-\t\treturn NULL;\n-\n \tTAILQ_FOREACH(action_set, &mae->action_sets, entries) {\n \t\tif (action_set->encap_header == ctx->encap_header &&\n \t\t    action_set->dst_mac_addr == ctx->dst_mac &&\n \t\t    action_set->src_mac_addr == ctx->src_mac &&\n+\t\t    action_set->counter == ctx->counter &&\n \t\t    efx_mae_action_set_specs_equal(action_set->spec,\n \t\t\t\t\t\t   ctx->spec)) {\n \t\t\tsfc_dbg(sa, \"attaching to action_set=%p\", action_set);\n@@ -921,13 +999,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,\n \n static int\n sfc_mae_action_set_add(struct sfc_adapter *sa,\n-\t\t       const struct rte_flow_action actions[],\n \t\t       const struct sfc_mae_aset_ctx *ctx,\n \t\t       struct sfc_mae_action_set **action_setp)\n {\n \tstruct sfc_mae_action_set *action_set;\n \tstruct sfc_mae *mae = &sa->mae;\n-\tunsigned int i;\n \n \tSFC_ASSERT(sfc_adapter_is_locked(sa));\n \n@@ -937,49 +1013,12 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,\n \t\treturn ENOMEM;\n \t}\n \n-\tif (ctx->n_counters > 0) {\n-\t\tconst struct rte_flow_action *action;\n-\n-\t\taction_set->counters = rte_malloc(\"sfc_mae_counter_ids\",\n-\t\t\tsizeof(action_set->counters[0]) * ctx->n_counters, 0);\n-\t\tif (action_set->counters == NULL) {\n-\t\t\trte_free(action_set);\n-\t\t\tsfc_err(sa, \"failed to alloc counters\");\n-\t\t\treturn ENOMEM;\n-\t\t}\n-\n-\t\tfor (i = 0; i < ctx->n_counters; ++i) {\n-\t\t\taction_set->counters[i].rte_id_valid = B_FALSE;\n-\t\t\taction_set->counters[i].mae_id.id =\n-\t\t\t\tEFX_MAE_RSRC_ID_INVALID;\n-\n-\t\t\taction_set->counters[i].ft_ctx = ctx->counter_ft_ctx;\n-\t\t\taction_set->counters[i].ft_switch_hit_counter =\n-\t\t\t\tctx->ft_switch_hit_counter;\n-\t\t}\n-\n-\t\tfor (action = actions, i = 0;\n-\t\t     action->type != RTE_FLOW_ACTION_TYPE_END &&\n-\t\t     i < ctx->n_counters; ++action) {\n-\t\t\tconst struct rte_flow_action_count *conf;\n-\n-\t\t\tif (action->type != RTE_FLOW_ACTION_TYPE_COUNT)\n-\t\t\t\tcontinue;\n-\n-\t\t\tconf = action->conf;\n-\n-\t\t\taction_set->counters[i].rte_id_valid = B_TRUE;\n-\t\t\taction_set->counters[i].rte_id = conf->id;\n-\t\t\ti++;\n-\t\t}\n-\t\taction_set->n_counters = ctx->n_counters;\n-\t}\n-\n \taction_set->refcnt = 1;\n \taction_set->spec = ctx->spec;\n \taction_set->encap_header = ctx->encap_header;\n \taction_set->dst_mac_addr = ctx->dst_mac;\n \taction_set->src_mac_addr = ctx->src_mac;\n+\taction_set->counter = ctx->counter;\n \n \taction_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;\n \n@@ -1020,12 +1059,7 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,\n \tsfc_mae_encap_header_del(sa, action_set->encap_header);\n \tsfc_mae_mac_addr_del(sa, action_set->dst_mac_addr);\n \tsfc_mae_mac_addr_del(sa, action_set->src_mac_addr);\n-\tif (action_set->n_counters > 0) {\n-\t\tSFC_ASSERT(action_set->n_counters == 1);\n-\t\tSFC_ASSERT(action_set->counters[0].mae_id.id ==\n-\t\t\t   EFX_MAE_RSRC_ID_INVALID);\n-\t\trte_free(action_set->counters);\n-\t}\n+\tsfc_mae_counter_del(sa, action_set->counter);\n \tTAILQ_REMOVE(&mae->action_sets, action_set, entries);\n \trte_free(action_set);\n \n@@ -1039,7 +1073,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,\n \tstruct sfc_mae_encap_header *encap_header;\n \tstruct sfc_mae_mac_addr *dst_mac_addr;\n \tstruct sfc_mae_mac_addr *src_mac_addr;\n-\tstruct sfc_mae_counter *counters;\n+\tstruct sfc_mae_counter *counter;\n \tstruct sfc_mae_fw_rsrc *fw_rsrc;\n \tint rc;\n \n@@ -1051,8 +1085,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,\n \tencap_header = action_set->encap_header;\n \tdst_mac_addr = action_set->dst_mac_addr;\n \tsrc_mac_addr = action_set->src_mac_addr;\n-\tcounters = action_set->counters;\n \tfw_rsrc = &action_set->fw_rsrc;\n+\tcounter = action_set->counter;\n \n \tif (fw_rsrc->refcnt == 0) {\n \t\tSFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);\n@@ -1080,7 +1114,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,\n \t\t\treturn rc;\n \t\t}\n \n-\t\tif (action_set->n_counters > 0) {\n+\t\tif (counter != NULL) {\n \t\t\trc = sfc_mae_counter_start(sa);\n \t\t\tif (rc != 0) {\n \t\t\t\tsfc_err(sa, \"failed to start MAE counters support: %s\",\n@@ -1092,13 +1126,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,\n \t\t\t}\n \t\t}\n \n-\t\trc = sfc_mae_counters_enable(sa, counters,\n-\t\t\t\t\t     action_set->n_counters,\n-\t\t\t\t\t     action_set->spec);\n+\t\trc = sfc_mae_counter_enable(sa, counter, action_set->spec);\n \t\tif (rc != 0) {\n-\t\t\tsfc_err(sa, \"failed to enable %u MAE counters: %s\",\n-\t\t\t\taction_set->n_counters, rte_strerror(rc));\n-\n \t\t\tsfc_mae_encap_header_disable(sa, encap_header);\n \t\t\tsfc_mae_mac_addr_disable(sa, src_mac_addr);\n \t\t\tsfc_mae_mac_addr_disable(sa, dst_mac_addr);\n@@ -1111,11 +1140,10 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,\n \t\t\tsfc_err(sa, \"failed to enable action_set=%p: %s\",\n \t\t\t\taction_set, strerror(rc));\n \n-\t\t\t(void)sfc_mae_counters_disable(sa, counters,\n-\t\t\t\t\t\t       action_set->n_counters);\n \t\t\tsfc_mae_encap_header_disable(sa, encap_header);\n \t\t\tsfc_mae_mac_addr_disable(sa, src_mac_addr);\n \t\t\tsfc_mae_mac_addr_disable(sa, dst_mac_addr);\n+\t\t\tsfc_mae_counter_disable(sa, counter);\n \t\t\treturn rc;\n \t\t}\n \n@@ -1162,16 +1190,10 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,\n \t\t}\n \t\tfw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;\n \n-\t\trc = sfc_mae_counters_disable(sa, action_set->counters,\n-\t\t\t\t\t      action_set->n_counters);\n-\t\tif (rc != 0) {\n-\t\t\tsfc_err(sa, \"failed to disable %u MAE counters: %s\",\n-\t\t\t\taction_set->n_counters, rte_strerror(rc));\n-\t\t}\n-\n \t\tsfc_mae_encap_header_disable(sa, action_set->encap_header);\n \t\tsfc_mae_mac_addr_disable(sa, action_set->src_mac_addr);\n \t\tsfc_mae_mac_addr_disable(sa, action_set->dst_mac_addr);\n+\t\tsfc_mae_counter_disable(sa, action_set->counter);\n \t}\n \n \t--(fw_rsrc->refcnt);\n@@ -3931,10 +3953,11 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,\n \n static int\n sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,\n-\t\t\t\tconst struct rte_flow_action_count *conf\n-\t\t\t\t\t__rte_unused,\n+\t\t\t\tconst struct rte_flow_action_count *conf,\n+\t\t\t\tstruct sfc_mae_counter **counterp,\n \t\t\t\tefx_mae_actions_t *spec)\n {\n+\tstruct sfc_mae_counter counter_tmp = {};\n \tint rc;\n \n \tif ((sa->counter_rxq.state & SFC_COUNTER_RXQ_INITIALIZED) == 0) {\n@@ -3949,17 +3972,33 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,\n \t\tgoto fail_no_service_core;\n \t}\n \n-\trc = efx_mae_action_set_populate_count(spec);\n-\tif (rc != 0) {\n-\t\tsfc_err(sa,\n-\t\t\t\"failed to populate counters in MAE action set: %s\",\n-\t\t\trte_strerror(rc));\n-\t\tgoto fail_populate_count;\n+\tif (*counterp != NULL) {\n+\t\tsfc_err(sa, \"cannot request more than 1 action COUNT per flow\");\n+\t\trc = EINVAL;\n+\t\tgoto fail_more_than_one;\n+\t}\n+\n+\tif (spec != NULL) {\n+\t\trc = efx_mae_action_set_populate_count(spec);\n+\t\tif (rc != 0) {\n+\t\t\tsfc_err(sa,\n+\t\t\t\t\"failed to populate counters in MAE action set: %s\",\n+\t\t\t\trte_strerror(rc));\n+\t\t\tgoto fail_populate_count;\n+\t\t}\n+\t}\n+\n+\tif (conf != NULL) {\n+\t\tcounter_tmp.rte_id_valid = true;\n+\t\tcounter_tmp.rte_id = conf->id;\n \t}\n \n+\treturn sfc_mae_counter_add(sa, &counter_tmp, counterp);\n+\n \treturn 0;\n \n fail_populate_count:\n+fail_more_than_one:\n fail_no_service_core:\n fail_counter_queue_uninit:\n \n@@ -4126,7 +4165,9 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,\n \tstruct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;\n \tconst struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;\n \tconst uint64_t rx_metadata = sa->negotiated_rx_metadata;\n+\tstruct sfc_mae_counter **counterp = &ctx->counter;\n \tefx_mae_actions_t *spec = ctx->spec;\n+\tefx_mae_actions_t *spec_ptr = spec;\n \tunsigned int switch_port_type_mask;\n \tbool custom_error = B_FALSE;\n \tint rc = 0;\n@@ -4214,7 +4255,8 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,\n \tcase RTE_FLOW_ACTION_TYPE_COUNT:\n \t\tSFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,\n \t\t\t\t       bundle->actions_mask);\n-\t\trc = sfc_mae_rule_parse_action_count(sa, action->conf, spec);\n+\t\trc = sfc_mae_rule_parse_action_count(sa, action->conf,\n+\t\t\t\t\t\t     counterp, spec_ptr);\n \t\tbreak;\n \tcase RTE_FLOW_ACTION_TYPE_FLAG:\n \t\tSFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,\n@@ -4364,19 +4406,23 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \tif (rc != 0)\n \t\tgoto fail_action_set_spec_init;\n \n-\tfor (action = actions;\n-\t     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {\n-\t\tif (action->type == RTE_FLOW_ACTION_TYPE_COUNT)\n-\t\t\t++(ctx.n_counters);\n-\t}\n-\n \tif (spec_mae->ft_rule_type == SFC_FT_RULE_SWITCH) {\n+\t\tbool have_user_action_count = false;\n+\n \t\t/* TUNNEL rules don't decapsulate packets. SWITCH rules do. */\n \t\trc = efx_mae_action_set_populate_decap(ctx.spec);\n \t\tif (rc != 0)\n \t\t\tgoto fail_enforce_ft_decap;\n \n-\t\tif (ctx.n_counters == 0 &&\n+\t\tfor (action = actions;\n+\t\t     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {\n+\t\t\tif (action->type == RTE_FLOW_ACTION_TYPE_COUNT) {\n+\t\t\t\thave_user_action_count = true;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (!have_user_action_count &&\n \t\t    sfc_mae_counter_stream_enabled(sa)) {\n \t\t\t/*\n \t\t\t * The user opted not to use action COUNT in this rule,\n@@ -4388,7 +4434,9 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \t\t\tif (rc != 0)\n \t\t\t\tgoto fail_enforce_ft_count;\n \n-\t\t\tctx.n_counters = 1;\n+\t\t\trc = sfc_mae_counter_add(sa, NULL, &ctx.counter);\n+\t\t\tif (rc != 0)\n+\t\t\t\tgoto fail_enforce_ft_count;\n \t\t}\n \t}\n \n@@ -4418,13 +4466,6 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \tif (rc != 0)\n \t\tgoto fail_process_encap_header;\n \n-\tif (ctx.n_counters > 1) {\n-\t\trc = ENOTSUP;\n-\t\tsfc_err(sa, \"too many count actions requested: %u\",\n-\t\t\tctx.n_counters);\n-\t\tgoto fail_nb_count;\n-\t}\n-\n \tswitch (spec_mae->ft_rule_type) {\n \tcase SFC_FT_RULE_NONE:\n \t\tbreak;\n@@ -4434,7 +4475,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \t\tif (rc != 0)\n \t\t\tgoto fail_workaround_tunnel_delivery;\n \n-\t\tctx.counter_ft_ctx = spec_mae->ft_ctx;\n+\t\tif (ctx.counter != NULL)\n+\t\t\t(ctx.counter)->ft_ctx = spec_mae->ft_ctx;\n \t\tbreak;\n \tcase SFC_FT_RULE_SWITCH:\n \t\t/*\n@@ -4443,7 +4485,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \t\t */\n \t\tefx_mae_action_set_populate_mark_reset(ctx.spec);\n \n-\t\tctx.ft_switch_hit_counter =\n+\t\t(ctx.counter)->ft_switch_hit_counter =\n \t\t\t&spec_mae->ft_ctx->switch_hit_counter;\n \t\tbreak;\n \tdefault:\n@@ -4467,6 +4509,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \n \taction_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);\n \tif (action_rule_ctx->action_set != NULL) {\n+\t\tsfc_mae_counter_del(sa, ctx.counter);\n \t\tsfc_mae_mac_addr_del(sa, ctx.src_mac);\n \t\tsfc_mae_mac_addr_del(sa, ctx.dst_mac);\n \t\tsfc_mae_encap_header_del(sa, ctx.encap_header);\n@@ -4474,8 +4517,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \t\treturn 0;\n \t}\n \n-\trc = sfc_mae_action_set_add(sa, actions, &ctx,\n-\t\t\t\t    &action_rule_ctx->action_set);\n+\trc = sfc_mae_action_set_add(sa, &ctx, &action_rule_ctx->action_set);\n \tif (rc != 0)\n \t\tgoto fail_action_set_add;\n \n@@ -4484,11 +4526,11 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n fail_action_set_add:\n fail_check_fate_action:\n fail_workaround_tunnel_delivery:\n-fail_nb_count:\n \tsfc_mae_encap_header_del(sa, ctx.encap_header);\n \n fail_process_encap_header:\n fail_rule_parse_action:\n+\tsfc_mae_counter_del(sa, ctx.counter);\n \tsfc_mae_mac_addr_del(sa, ctx.src_mac);\n \tsfc_mae_mac_addr_del(sa, ctx.dst_mac);\n \tefx_mae_action_set_spec_fini(sa->nic, ctx.spec);\n@@ -4768,28 +4810,22 @@ sfc_mae_query_counter(struct sfc_adapter *sa,\n \tconst struct sfc_mae_action_rule *action_rule = spec->action_rule;\n \tconst struct rte_flow_action_count *conf = action->conf;\n \tstruct sfc_mae_action_set *action_set;\n-\tunsigned int i;\n+\tstruct sfc_mae_counter *counter;\n \tint rc;\n \n-\tif (action_rule == NULL || action_rule->action_set->n_counters == 0) {\n+\tif (action_rule == NULL || action_rule->action_set->counter == NULL) {\n \t\treturn rte_flow_error_set(error, EINVAL,\n \t\t\tRTE_FLOW_ERROR_TYPE_ACTION, action,\n \t\t\t\"Queried flow rule does not have count actions\");\n \t}\n \n \taction_set = action_rule->action_set;\n+\tcounter = action_set->counter;\n \n-\tfor (i = 0; i < action_set->n_counters; i++) {\n-\t\t/*\n-\t\t * Get the first available counter of the flow rule if\n-\t\t * counter ID is not specified, provided that this\n-\t\t * counter is not an automatic (implicit) one.\n-\t\t */\n-\t\tif (conf != NULL && action_set->counters[i].rte_id != conf->id)\n-\t\t\tcontinue;\n-\n+\tif (conf == NULL ||\n+\t    (counter->rte_id_valid && conf->id == counter->rte_id)) {\n \t\trc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,\n-\t\t\t\t\t &action_set->counters[i], data);\n+\t\t\t\t\t counter, data);\n \t\tif (rc != 0) {\n \t\t\treturn rte_flow_error_set(error, EINVAL,\n \t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION, action,\ndiff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h\nindex 7337fcf14d..c73ce0a5e6 100644\n--- a/drivers/net/sfc/sfc_mae.h\n+++ b/drivers/net/sfc/sfc_mae.h\n@@ -27,6 +27,7 @@ struct sfc_mae_fw_rsrc {\n \tunsigned int\t\t\trefcnt;\n \tRTE_STD_C11\n \tunion {\n+\t\tefx_counter_t\t\tcounter_id;\n \t\tefx_mae_aset_id_t\taset_id;\n \t\tefx_mae_rule_id_t\trule_id;\n \t\tefx_mae_mac_id_t\tmac_id;\n@@ -67,10 +68,11 @@ struct sfc_mae_encap_header {\n \n TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);\n \n-/* Counter ID */\n+/* Counter object registry entry */\n struct sfc_mae_counter {\n-\t/* ID of a counter in MAE */\n-\tefx_counter_t\t\t\tmae_id;\n+\tTAILQ_ENTRY(sfc_mae_counter)\tentries;\n+\tunsigned int\t\t\trefcnt;\n+\n \t/* ID of a counter in RTE */\n \tuint32_t\t\t\trte_id;\n \t/* RTE counter ID validity status */\n@@ -80,18 +82,21 @@ struct sfc_mae_counter {\n \tuint64_t\t\t\t*ft_switch_hit_counter;\n \t/* Flow Tunnel (FT) context (for TUNNEL rules; otherwise, NULL) */\n \tstruct sfc_ft_ctx\t\t*ft_ctx;\n+\n+\tstruct sfc_mae_fw_rsrc\t\tfw_rsrc;\n };\n \n+TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);\n+\n /** Action set registry entry */\n struct sfc_mae_action_set {\n \tTAILQ_ENTRY(sfc_mae_action_set)\tentries;\n \tunsigned int\t\t\trefcnt;\n-\tstruct sfc_mae_counter\t\t*counters;\n-\tuint32_t\t\t\tn_counters;\n \tefx_mae_actions_t\t\t*spec;\n \tstruct sfc_mae_encap_header\t*encap_header;\n \tstruct sfc_mae_mac_addr\t\t*dst_mac_addr;\n \tstruct sfc_mae_mac_addr\t\t*src_mac_addr;\n+\tstruct sfc_mae_counter\t\t*counter;\n \tstruct sfc_mae_fw_rsrc\t\tfw_rsrc;\n };\n \n@@ -221,6 +226,8 @@ struct sfc_mae {\n \tbool\t\t\t\tcounter_rxq_running;\n \t/** Counter record registry */\n \tstruct sfc_mae_counter_registry\tcounter_registry;\n+\t/** Counter object registry */\n+\tstruct sfc_mae_counters\t\tcounters;\n \t/**\n \t * Switchdev default rules. They forward traffic from PHY port\n \t * to PF and vice versa.\ndiff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c\nindex 8170175991..90b89e81c6 100644\n--- a/drivers/net/sfc/sfc_mae_counter.c\n+++ b/drivers/net/sfc/sfc_mae_counter.c\n@@ -110,7 +110,7 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,\n \t\tgoto fail_counter_id_range;\n \t}\n \n-\tcounterp->mae_id = mae_counter;\n+\tcounterp->fw_rsrc.counter_id.id = mae_counter.id;\n \n \tp = &counters->mae_counters[mae_counter.id];\n \n@@ -152,29 +152,27 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,\n {\n \tstruct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;\n \tstruct sfc_mae_counter_records *counters = &reg->counters;\n+\tefx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;\n \tstruct sfc_mae_counter_record *p;\n \tuint32_t unused;\n \tint rc;\n \n-\tif (counter->mae_id.id == EFX_MAE_RSRC_ID_INVALID)\n-\t\treturn 0;\n-\n-\tSFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);\n+\tSFC_ASSERT(mae_counter->id < counters->n_mae_counters);\n \t/*\n \t * The flag is set at the very end of add operation and reset\n \t * at the beginning of delete operation. Release ordering is\n \t * paired with acquire ordering on load in counter increment operation.\n \t */\n-\tp = &counters->mae_counters[counter->mae_id.id];\n+\tp = &counters->mae_counters[mae_counter->id];\n \t__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);\n \n-\trc = efx_mae_counters_free(sa->nic, 1, &unused, &counter->mae_id, NULL);\n+\trc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);\n \tif (rc != 0)\n \t\tsfc_err(sa, \"failed to free MAE counter %u: %s\",\n-\t\t\tcounter->mae_id.id, rte_strerror(rc));\n+\t\t\tmae_counter->id, rte_strerror(rc));\n \n \tsfc_info(sa, \"disabled MAE counter #%u with reset pkts=%\" PRIu64\n-\t\t \" bytes=%\" PRIu64, counter->mae_id.id,\n+\t\t \" bytes=%\" PRIu64, mae_counter->id,\n \t\t p->reset.pkts, p->reset.bytes);\n \n \t/*\n@@ -182,7 +180,7 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,\n \t * If there's some error, the resulting resource leakage is bad, but\n \t * nothing sensible can be done in this case.\n \t */\n-\tcounter->mae_id.id = EFX_MAE_RSRC_ID_INVALID;\n+\tmae_counter->id = EFX_MAE_RSRC_ID_INVALID;\n \n \treturn rc;\n }\n@@ -952,8 +950,8 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,\n \tstruct sfc_mae_counter_record *p;\n \tunion sfc_pkts_bytes value;\n \n-\tSFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);\n-\tp = &counters->mae_counters[counter->mae_id.id];\n+\tSFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);\n+\tp = &counters->mae_counters[counter->fw_rsrc.counter_id.id];\n \n \t/*\n \t * Ordering is relaxed since it is the only operation on counter value.\n",
    "prefixes": [
        "29/34"
    ]
}