get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 97435,
    "url": "http://patchwork.dpdk.org/api/patches/97435/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20210827065717.1838258-20-andrew.rybchenko@oktetlabs.ru/",
    "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": "<20210827065717.1838258-20-andrew.rybchenko@oktetlabs.ru>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210827065717.1838258-20-andrew.rybchenko@oktetlabs.ru",
    "date": "2021-08-27T06:56:58",
    "name": "[19/38] net/sfc: implement port representor start and stop",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "44e7a1c95c2bf6c52bb57f43225ca6a17ac333f0",
    "submitter": {
        "id": 2013,
        "url": "http://patchwork.dpdk.org/api/people/2013/?format=api",
        "name": "Andrew Rybchenko",
        "email": "Andrew.Rybchenko@oktetlabs.ru"
    },
    "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/20210827065717.1838258-20-andrew.rybchenko@oktetlabs.ru/mbox/",
    "series": [
        {
            "id": 18492,
            "url": "http://patchwork.dpdk.org/api/series/18492/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=18492",
            "date": "2021-08-27T06:56:39",
            "name": "net/sfc: support port representors",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/18492/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/97435/comments/",
    "check": "warning",
    "checks": "http://patchwork.dpdk.org/api/patches/97435/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 D5DE8A0C43;\n\tFri, 27 Aug 2021 08:59:33 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 38DAD4126D;\n\tFri, 27 Aug 2021 08:58:41 +0200 (CEST)",
            "from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113])\n by mails.dpdk.org (Postfix) with ESMTP id 9FB1341251\n for <dev@dpdk.org>; Fri, 27 Aug 2021 08:58:36 +0200 (CEST)",
            "by shelob.oktetlabs.ru (Postfix, from userid 122)\n id 67B3B7F6DB; Fri, 27 Aug 2021 09:58:36 +0300 (MSK)",
            "from aros.oktetlabs.ru (aros.oktetlabs.ru [192.168.38.17])\n by shelob.oktetlabs.ru (Postfix) with ESMTP id E07F17F6E4;\n Fri, 27 Aug 2021 09:57:34 +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 E07F17F6E4",
        "Authentication-Results": "shelob.oktetlabs.ru/E07F17F6E4; dkim=none;\n dkim-atps=neutral",
        "From": "Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>",
        "To": "dev@dpdk.org",
        "Cc": "Igor Romanov <igor.romanov@oktetlabs.ru>,\n Andy Moreton <amoreton@xilinx.com>, Ivan Malov <ivan.malov@oktetlabs.ru>",
        "Date": "Fri, 27 Aug 2021 09:56:58 +0300",
        "Message-Id": "<20210827065717.1838258-20-andrew.rybchenko@oktetlabs.ru>",
        "X-Mailer": "git-send-email 2.30.2",
        "In-Reply-To": "<20210827065717.1838258-1-andrew.rybchenko@oktetlabs.ru>",
        "References": "<20210827065717.1838258-1-andrew.rybchenko@oktetlabs.ru>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH 19/38] net/sfc: implement port representor start\n and stop",
        "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\nImplement queue start and stop operation both in port\nrepresentors and representor proxy.\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/sfc_mae.h            |   9 +-\n drivers/net/sfc/sfc_repr.c           | 181 +++++++++++\n drivers/net/sfc/sfc_repr_proxy.c     | 453 ++++++++++++++++++++++++++-\n drivers/net/sfc/sfc_repr_proxy.h     |  16 +\n drivers/net/sfc/sfc_repr_proxy_api.h |   3 +\n 5 files changed, 644 insertions(+), 18 deletions(-)",
    "diff": "diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h\nindex 684f0daf7a..d835056aef 100644\n--- a/drivers/net/sfc/sfc_mae.h\n+++ b/drivers/net/sfc/sfc_mae.h\n@@ -139,10 +139,17 @@ struct sfc_mae_counter_registry {\n \tuint32_t\t\t\tservice_id;\n };\n \n+/**\n+ * MAE rules used to capture traffic generated by VFs and direct it to\n+ * representors (one for each VF).\n+ */\n+#define SFC_MAE_NB_REPR_RULES_MAX\t(64)\n+\n /** Rules to forward traffic from PHY port to PF and from PF to PHY port */\n #define SFC_MAE_NB_SWITCHDEV_RULES\t(2)\n /** Maximum required internal MAE rules */\n-#define SFC_MAE_NB_RULES_MAX\t\t(SFC_MAE_NB_SWITCHDEV_RULES)\n+#define SFC_MAE_NB_RULES_MAX\t\t(SFC_MAE_NB_SWITCHDEV_RULES + \\\n+\t\t\t\t\t SFC_MAE_NB_REPR_RULES_MAX)\n \n struct sfc_mae_rule {\n \tefx_mae_match_spec_t\t\t*spec;\ndiff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c\nindex b3876586cc..bfe6dd4c9b 100644\n--- a/drivers/net/sfc/sfc_repr.c\n+++ b/drivers/net/sfc/sfc_repr.c\n@@ -9,6 +9,7 @@\n \n #include <stdint.h>\n \n+#include <rte_mbuf.h>\n #include <rte_ethdev.h>\n #include <rte_malloc.h>\n #include <ethdev_driver.h>\n@@ -21,6 +22,7 @@\n #include \"sfc_ethdev_state.h\"\n #include \"sfc_repr_proxy_api.h\"\n #include \"sfc_switch.h\"\n+#include \"sfc_dp_tx.h\"\n \n /** Multi-process shared representor private data */\n struct sfc_repr_shared {\n@@ -144,6 +146,179 @@ sfc_repr_lock_fini(__rte_unused struct sfc_repr *sr)\n \t/* Just for symmetry of the API */\n }\n \n+static void\n+sfc_repr_rx_queue_stop(void *queue)\n+{\n+\tstruct sfc_repr_rxq *rxq = queue;\n+\n+\tif (rxq == NULL)\n+\t\treturn;\n+\n+\trte_ring_reset(rxq->ring);\n+}\n+\n+static void\n+sfc_repr_tx_queue_stop(void *queue)\n+{\n+\tstruct sfc_repr_txq *txq = queue;\n+\n+\tif (txq == NULL)\n+\t\treturn;\n+\n+\trte_ring_reset(txq->ring);\n+}\n+\n+static int\n+sfc_repr_start(struct rte_eth_dev *dev)\n+{\n+\tstruct sfc_repr *sr = sfc_repr_by_eth_dev(dev);\n+\tstruct sfc_repr_shared *srs;\n+\tint ret;\n+\n+\tsfcr_info(sr, \"entry\");\n+\n+\tSFC_ASSERT(sfc_repr_lock_is_locked(sr));\n+\n+\tswitch (sr->state) {\n+\tcase SFC_ETHDEV_CONFIGURED:\n+\t\tbreak;\n+\tcase SFC_ETHDEV_STARTED:\n+\t\tsfcr_info(sr, \"already started\");\n+\t\treturn 0;\n+\tdefault:\n+\t\tret = -EINVAL;\n+\t\tgoto fail_bad_state;\n+\t}\n+\n+\tsr->state = SFC_ETHDEV_STARTING;\n+\n+\tsrs = sfc_repr_shared_by_eth_dev(dev);\n+\tret = sfc_repr_proxy_start_repr(srs->pf_port_id, srs->repr_id);\n+\tif (ret != 0) {\n+\t\tSFC_ASSERT(ret > 0);\n+\t\tret = -ret;\n+\t\tgoto fail_start;\n+\t}\n+\n+\tsr->state = SFC_ETHDEV_STARTED;\n+\n+\tsfcr_info(sr, \"done\");\n+\n+\treturn 0;\n+\n+fail_start:\n+\tsr->state = SFC_ETHDEV_CONFIGURED;\n+\n+fail_bad_state:\n+\tsfcr_err(sr, \"%s() failed: %s\", __func__, rte_strerror(-ret));\n+\treturn ret;\n+}\n+\n+static int\n+sfc_repr_dev_start(struct rte_eth_dev *dev)\n+{\n+\tstruct sfc_repr *sr = sfc_repr_by_eth_dev(dev);\n+\tint ret;\n+\n+\tsfcr_info(sr, \"entry\");\n+\n+\tsfc_repr_lock(sr);\n+\tret = sfc_repr_start(dev);\n+\tsfc_repr_unlock(sr);\n+\n+\tif (ret != 0)\n+\t\tgoto fail_start;\n+\n+\tsfcr_info(sr, \"done\");\n+\n+\treturn 0;\n+\n+fail_start:\n+\tsfcr_err(sr, \"%s() failed: %s\", __func__, rte_strerror(-ret));\n+\treturn ret;\n+}\n+\n+static int\n+sfc_repr_stop(struct rte_eth_dev *dev)\n+{\n+\tstruct sfc_repr *sr = sfc_repr_by_eth_dev(dev);\n+\tstruct sfc_repr_shared *srs;\n+\tunsigned int i;\n+\tint ret;\n+\n+\tsfcr_info(sr, \"entry\");\n+\n+\tSFC_ASSERT(sfc_repr_lock_is_locked(sr));\n+\n+\tswitch (sr->state) {\n+\tcase SFC_ETHDEV_STARTED:\n+\t\tbreak;\n+\tcase SFC_ETHDEV_CONFIGURED:\n+\t\tsfcr_info(sr, \"already stopped\");\n+\t\treturn 0;\n+\tdefault:\n+\t\tsfcr_err(sr, \"stop in unexpected state %u\", sr->state);\n+\t\tSFC_ASSERT(B_FALSE);\n+\t\tret = -EINVAL;\n+\t\tgoto fail_bad_state;\n+\t}\n+\n+\tsrs = sfc_repr_shared_by_eth_dev(dev);\n+\tret = sfc_repr_proxy_stop_repr(srs->pf_port_id, srs->repr_id);\n+\tif (ret != 0) {\n+\t\tSFC_ASSERT(ret > 0);\n+\t\tret = -ret;\n+\t\tgoto fail_stop;\n+\t}\n+\n+\tfor (i = 0; i < dev->data->nb_rx_queues; i++)\n+\t\tsfc_repr_rx_queue_stop(dev->data->rx_queues[i]);\n+\n+\tfor (i = 0; i < dev->data->nb_tx_queues; i++)\n+\t\tsfc_repr_tx_queue_stop(dev->data->tx_queues[i]);\n+\n+\tsr->state = SFC_ETHDEV_CONFIGURED;\n+\tsfcr_info(sr, \"done\");\n+\n+\treturn 0;\n+\n+fail_bad_state:\n+fail_stop:\n+\tsfcr_err(sr, \"%s() failed: %s\", __func__, rte_strerror(-ret));\n+\n+\treturn ret;\n+}\n+\n+static int\n+sfc_repr_dev_stop(struct rte_eth_dev *dev)\n+{\n+\tstruct sfc_repr *sr = sfc_repr_by_eth_dev(dev);\n+\tint ret;\n+\n+\tsfcr_info(sr, \"entry\");\n+\n+\tsfc_repr_lock(sr);\n+\n+\tret = sfc_repr_stop(dev);\n+\tif (ret != 0) {\n+\t\tsfcr_err(sr, \"%s() failed to stop representor\", __func__);\n+\t\tgoto fail_stop;\n+\t}\n+\n+\tsfc_repr_unlock(sr);\n+\n+\tsfcr_info(sr, \"done\");\n+\n+\treturn 0;\n+\n+fail_stop:\n+\tsfc_repr_unlock(sr);\n+\n+\tsfcr_err(sr, \"%s() failed %s\", __func__, rte_strerror(-ret));\n+\n+\treturn ret;\n+}\n+\n static int\n sfc_repr_check_conf(struct sfc_repr *sr, uint16_t nb_rx_queues,\n \t\t    const struct rte_eth_conf *conf)\n@@ -557,6 +732,10 @@ sfc_repr_dev_close(struct rte_eth_dev *dev)\n \n \tsfc_repr_lock(sr);\n \tswitch (sr->state) {\n+\tcase SFC_ETHDEV_STARTED:\n+\t\tsfc_repr_stop(dev);\n+\t\tSFC_ASSERT(sr->state == SFC_ETHDEV_CONFIGURED);\n+\t\t/* FALLTHROUGH */\n \tcase SFC_ETHDEV_CONFIGURED:\n \t\tsfc_repr_close(sr);\n \t\tSFC_ASSERT(sr->state == SFC_ETHDEV_INITIALIZED);\n@@ -599,6 +778,8 @@ sfc_repr_dev_close(struct rte_eth_dev *dev)\n \n static const struct eth_dev_ops sfc_repr_dev_ops = {\n \t.dev_configure\t\t\t= sfc_repr_dev_configure,\n+\t.dev_start\t\t\t= sfc_repr_dev_start,\n+\t.dev_stop\t\t\t= sfc_repr_dev_stop,\n \t.dev_close\t\t\t= sfc_repr_dev_close,\n \t.dev_infos_get\t\t\t= sfc_repr_dev_infos_get,\n \t.rx_queue_setup\t\t\t= sfc_repr_rx_queue_setup,\ndiff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c\nindex a5be8fa270..ea03d5afdd 100644\n--- a/drivers/net/sfc/sfc_repr_proxy.c\n+++ b/drivers/net/sfc/sfc_repr_proxy.c\n@@ -53,6 +53,19 @@ sfc_put_adapter(struct sfc_adapter *sa)\n \tsfc_adapter_unlock(sa);\n }\n \n+static struct sfc_repr_proxy_port *\n+sfc_repr_proxy_find_port(struct sfc_repr_proxy *rp, uint16_t repr_id)\n+{\n+\tstruct sfc_repr_proxy_port *port;\n+\n+\tTAILQ_FOREACH(port, &rp->ports, entries) {\n+\t\tif (port->repr_id == repr_id)\n+\t\t\treturn port;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n static int\n sfc_repr_proxy_mbox_send(struct sfc_repr_proxy_mbox *mbox,\n \t\t\t struct sfc_repr_proxy_port *port,\n@@ -117,6 +130,12 @@ sfc_repr_proxy_mbox_handle(struct sfc_repr_proxy *rp)\n \tcase SFC_REPR_PROXY_MBOX_DEL_PORT:\n \t\tTAILQ_REMOVE(&rp->ports, mbox->port, entries);\n \t\tbreak;\n+\tcase SFC_REPR_PROXY_MBOX_START_PORT:\n+\t\tmbox->port->started = true;\n+\t\tbreak;\n+\tcase SFC_REPR_PROXY_MBOX_STOP_PORT:\n+\t\tmbox->port->started = false;\n+\t\tbreak;\n \tdefault:\n \t\tSFC_ASSERT(0);\n \t\treturn;\n@@ -463,6 +482,158 @@ sfc_repr_proxy_rxq_start(struct sfc_adapter *sa)\n \treturn rc;\n }\n \n+static int\n+sfc_repr_proxy_mae_rule_insert(struct sfc_adapter *sa,\n+\t\t\t       struct sfc_repr_proxy_port *port)\n+{\n+\tstruct sfc_repr_proxy *rp = &sa->repr_proxy;\n+\tefx_mport_sel_t mport_alias_selector;\n+\tefx_mport_sel_t mport_vf_selector;\n+\tstruct sfc_mae_rule *mae_rule;\n+\tint rc;\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\trc = efx_mae_mport_by_id(&port->egress_mport,\n+\t\t\t\t &mport_vf_selector);\n+\tif (rc != 0) {\n+\t\tsfc_err(sa, \"failed to get VF mport for repr %u\",\n+\t\t\tport->repr_id);\n+\t\tgoto fail_get_vf;\n+\t}\n+\n+\trc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);\n+\tif (rc != 0) {\n+\t\tsfc_err(sa, \"failed to get mport selector for repr %u\",\n+\t\t\tport->repr_id);\n+\t\tgoto fail_get_alias;\n+\t}\n+\n+\trc = sfc_mae_rule_add_mport_match_deliver(sa, &mport_vf_selector,\n+\t\t\t\t\t\t  &mport_alias_selector, -1,\n+\t\t\t\t\t\t  &mae_rule);\n+\tif (rc != 0) {\n+\t\tsfc_err(sa, \"failed to insert MAE rule for repr %u\",\n+\t\t\tport->repr_id);\n+\t\tgoto fail_rule_add;\n+\t}\n+\n+\tport->mae_rule = mae_rule;\n+\n+\tsfc_log_init(sa, \"done\");\n+\n+\treturn 0;\n+\n+fail_rule_add:\n+fail_get_alias:\n+fail_get_vf:\n+\tsfc_log_init(sa, \"failed: %s\", rte_strerror(rc));\n+\treturn rc;\n+}\n+\n+static void\n+sfc_repr_proxy_mae_rule_remove(struct sfc_adapter *sa,\n+\t\t\t       struct sfc_repr_proxy_port *port)\n+{\n+\tstruct sfc_mae_rule *mae_rule = port->mae_rule;\n+\n+\tsfc_mae_rule_del(sa, mae_rule);\n+}\n+\n+static int\n+sfc_repr_proxy_mport_filter_insert(struct sfc_adapter *sa)\n+{\n+\tstruct sfc_adapter_shared * const sas = sfc_sa2shared(sa);\n+\tstruct sfc_repr_proxy *rp = &sa->repr_proxy;\n+\tstruct sfc_rxq *rxq_ctrl;\n+\tstruct sfc_repr_proxy_filter *filter = &rp->mport_filter;\n+\tefx_mport_sel_t mport_alias_selector;\n+\tstatic const efx_filter_match_flags_t flags[RTE_DIM(filter->specs)] = {\n+\t\tEFX_FILTER_MATCH_UNKNOWN_UCAST_DST,\n+\t\tEFX_FILTER_MATCH_UNKNOWN_MCAST_DST };\n+\tunsigned int i;\n+\tint rc;\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tif (sfc_repr_nb_rxq(sas) == 1) {\n+\t\trxq_ctrl = &sa->rxq_ctrl[rp->dp_rxq[0].sw_index];\n+\t} else {\n+\t\tsfc_err(sa, \"multiple representor proxy RxQs not supported\");\n+\t\trc = ENOTSUP;\n+\t\tgoto fail_multiple_queues;\n+\t}\n+\n+\trc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);\n+\tif (rc != 0) {\n+\t\tsfc_err(sa, \"failed to get repr proxy mport by ID\");\n+\t\tgoto fail_get_selector;\n+\t}\n+\n+\tmemset(filter->specs, 0, sizeof(filter->specs));\n+\tfor (i = 0; i < RTE_DIM(filter->specs); i++) {\n+\t\tfilter->specs[i].efs_priority = EFX_FILTER_PRI_MANUAL;\n+\t\tfilter->specs[i].efs_flags = EFX_FILTER_FLAG_RX;\n+\t\tfilter->specs[i].efs_dmaq_id = rxq_ctrl->hw_index;\n+\t\tfilter->specs[i].efs_match_flags = flags[i] |\n+\t\t\t\tEFX_FILTER_MATCH_MPORT;\n+\t\tfilter->specs[i].efs_ingress_mport = mport_alias_selector.sel;\n+\n+\t\trc = efx_filter_insert(sa->nic, &filter->specs[i]);\n+\t\tif (rc != 0) {\n+\t\t\tsfc_err(sa, \"failed to insert repr proxy filter\");\n+\t\t\tgoto fail_insert;\n+\t\t}\n+\t}\n+\n+\tsfc_log_init(sa, \"done\");\n+\n+\treturn 0;\n+\n+fail_insert:\n+\twhile (i-- > 0)\n+\t\tefx_filter_remove(sa->nic, &filter->specs[i]);\n+\n+fail_get_selector:\n+fail_multiple_queues:\n+\tsfc_log_init(sa, \"failed: %s\", rte_strerror(rc));\n+\treturn rc;\n+}\n+\n+static void\n+sfc_repr_proxy_mport_filter_remove(struct sfc_adapter *sa)\n+{\n+\tstruct sfc_repr_proxy *rp = &sa->repr_proxy;\n+\tstruct sfc_repr_proxy_filter *filter = &rp->mport_filter;\n+\tunsigned int i;\n+\n+\tfor (i = 0; i < RTE_DIM(filter->specs); i++)\n+\t\tefx_filter_remove(sa->nic, &filter->specs[i]);\n+}\n+\n+static int\n+sfc_repr_proxy_port_rule_insert(struct sfc_adapter *sa,\n+\t\t\t\tstruct sfc_repr_proxy_port *port)\n+{\n+\tint rc;\n+\n+\trc = sfc_repr_proxy_mae_rule_insert(sa, port);\n+\tif (rc != 0)\n+\t\tgoto fail_mae_rule_insert;\n+\n+\treturn 0;\n+\n+fail_mae_rule_insert:\n+\treturn rc;\n+}\n+\n+static void\n+sfc_repr_proxy_port_rule_remove(struct sfc_adapter *sa,\n+\t\t\t\tstruct sfc_repr_proxy_port *port)\n+{\n+\tsfc_repr_proxy_mae_rule_remove(sa, port);\n+}\n+\n static int\n sfc_repr_proxy_ports_init(struct sfc_adapter *sa)\n {\n@@ -644,24 +815,105 @@ sfc_repr_proxy_detach(struct sfc_adapter *sa)\n \tsfc_log_init(sa, \"done\");\n }\n \n+static int\n+sfc_repr_proxy_do_start_port(struct sfc_adapter *sa,\n+\t\t\t   struct sfc_repr_proxy_port *port)\n+{\n+\tstruct sfc_repr_proxy *rp = &sa->repr_proxy;\n+\tint rc;\n+\n+\trc = sfc_repr_proxy_port_rule_insert(sa, port);\n+\tif (rc != 0)\n+\t\tgoto fail_filter_insert;\n+\n+\tif (rp->started) {\n+\t\trc = sfc_repr_proxy_mbox_send(&rp->mbox, port,\n+\t\t\t\t\t      SFC_REPR_PROXY_MBOX_START_PORT);\n+\t\tif (rc != 0) {\n+\t\t\tsfc_err(sa, \"failed to start proxy port %u\",\n+\t\t\t\tport->repr_id);\n+\t\t\tgoto fail_port_start;\n+\t\t}\n+\t} else {\n+\t\tport->started = true;\n+\t}\n+\n+\treturn 0;\n+\n+fail_port_start:\n+\tsfc_repr_proxy_port_rule_remove(sa, port);\n+fail_filter_insert:\n+\tsfc_err(sa, \"%s() failed %s\", __func__, rte_strerror(rc));\n+\n+\treturn rc;\n+}\n+\n+static int\n+sfc_repr_proxy_do_stop_port(struct sfc_adapter *sa,\n+\t\t\t  struct sfc_repr_proxy_port *port)\n+\n+{\n+\tstruct sfc_repr_proxy *rp = &sa->repr_proxy;\n+\tint rc;\n+\n+\tif (rp->started) {\n+\t\trc = sfc_repr_proxy_mbox_send(&rp->mbox, port,\n+\t\t\t\t\t      SFC_REPR_PROXY_MBOX_STOP_PORT);\n+\t\tif (rc != 0) {\n+\t\t\tsfc_err(sa, \"failed to stop proxy port %u: %s\",\n+\t\t\t\tport->repr_id, rte_strerror(rc));\n+\t\t\treturn rc;\n+\t\t}\n+\t} else {\n+\t\tport->started = false;\n+\t}\n+\n+\tsfc_repr_proxy_port_rule_remove(sa, port);\n+\n+\treturn 0;\n+}\n+\n+static bool\n+sfc_repr_proxy_port_enabled(struct sfc_repr_proxy_port *port)\n+{\n+\treturn port->rte_port_id != RTE_MAX_ETHPORTS && port->enabled;\n+}\n+\n+static bool\n+sfc_repr_proxy_ports_disabled(struct sfc_repr_proxy *rp)\n+{\n+\tstruct sfc_repr_proxy_port *port;\n+\n+\tTAILQ_FOREACH(port, &rp->ports, entries) {\n+\t\tif (sfc_repr_proxy_port_enabled(port))\n+\t\t\treturn false;\n+\t}\n+\n+\treturn true;\n+}\n+\n int\n sfc_repr_proxy_start(struct sfc_adapter *sa)\n {\n \tstruct sfc_adapter_shared * const sas = sfc_sa2shared(sa);\n \tstruct sfc_repr_proxy *rp = &sa->repr_proxy;\n+\tstruct sfc_repr_proxy_port *last_port = NULL;\n+\tstruct sfc_repr_proxy_port *port;\n \tint rc;\n \n \tsfc_log_init(sa, \"entry\");\n \n-\t/*\n-\t * The condition to start the proxy is insufficient. It will be\n-\t * complemented with representor port start/stop support.\n-\t */\n+\t/* Representor proxy is not started when no representors are started */\n \tif (!sfc_repr_available(sas)) {\n \t\tsfc_log_init(sa, \"representors not supported - skip\");\n \t\treturn 0;\n \t}\n \n+\tif (sfc_repr_proxy_ports_disabled(rp)) {\n+\t\tsfc_log_init(sa, \"no started representor ports - skip\");\n+\t\treturn 0;\n+\t}\n+\n \trc = sfc_repr_proxy_rxq_start(sa);\n \tif (rc != 0)\n \t\tgoto fail_rxq_start;\n@@ -698,12 +950,40 @@ sfc_repr_proxy_start(struct sfc_adapter *sa)\n \t\tgoto fail_runstate_set;\n \t}\n \n+\tTAILQ_FOREACH(port, &rp->ports, entries) {\n+\t\tif (sfc_repr_proxy_port_enabled(port)) {\n+\t\t\trc = sfc_repr_proxy_do_start_port(sa, port);\n+\t\t\tif (rc != 0)\n+\t\t\t\tgoto fail_start_id;\n+\n+\t\t\tlast_port = port;\n+\t\t}\n+\t}\n+\n+\trc = sfc_repr_proxy_mport_filter_insert(sa);\n+\tif (rc != 0)\n+\t\tgoto fail_mport_filter_insert;\n+\n \trp->started = true;\n \n \tsfc_log_init(sa, \"done\");\n \n \treturn 0;\n \n+fail_mport_filter_insert:\n+fail_start_id:\n+\tif (last_port != NULL) {\n+\t\tTAILQ_FOREACH(port, &rp->ports, entries) {\n+\t\t\tif (sfc_repr_proxy_port_enabled(port)) {\n+\t\t\t\t(void)sfc_repr_proxy_do_stop_port(sa, port);\n+\t\t\t\tif (port == last_port)\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\trte_service_runstate_set(rp->service_id, 0);\n+\n fail_runstate_set:\n \trte_service_component_runstate_set(rp->service_id, 0);\n \n@@ -726,6 +1006,7 @@ sfc_repr_proxy_stop(struct sfc_adapter *sa)\n {\n \tstruct sfc_adapter_shared * const sas = sfc_sa2shared(sa);\n \tstruct sfc_repr_proxy *rp = &sa->repr_proxy;\n+\tstruct sfc_repr_proxy_port *port;\n \tint rc;\n \n \tsfc_log_init(sa, \"entry\");\n@@ -735,6 +1016,24 @@ sfc_repr_proxy_stop(struct sfc_adapter *sa)\n \t\treturn;\n \t}\n \n+\tif (sfc_repr_proxy_ports_disabled(rp)) {\n+\t\tsfc_log_init(sa, \"no started representor ports - skip\");\n+\t\treturn;\n+\t}\n+\n+\tTAILQ_FOREACH(port, &rp->ports, entries) {\n+\t\tif (sfc_repr_proxy_port_enabled(port)) {\n+\t\t\trc = sfc_repr_proxy_do_stop_port(sa, port);\n+\t\t\tif (rc != 0) {\n+\t\t\t\tsfc_err(sa,\n+\t\t\t\t\t\"failed to stop representor proxy port %u: %s\",\n+\t\t\t\t\tport->repr_id, rte_strerror(rc));\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tsfc_repr_proxy_mport_filter_remove(sa);\n+\n \trc = rte_service_runstate_set(rp->service_id, 0);\n \tif (rc < 0) {\n \t\tsfc_err(sa, \"failed to stop %s: %s\",\n@@ -759,19 +1058,6 @@ sfc_repr_proxy_stop(struct sfc_adapter *sa)\n \tsfc_log_init(sa, \"done\");\n }\n \n-static struct sfc_repr_proxy_port *\n-sfc_repr_proxy_find_port(struct sfc_repr_proxy *rp, uint16_t repr_id)\n-{\n-\tstruct sfc_repr_proxy_port *port;\n-\n-\tTAILQ_FOREACH(port, &rp->ports, entries) {\n-\t\tif (port->repr_id == repr_id)\n-\t\t\treturn port;\n-\t}\n-\n-\treturn NULL;\n-}\n-\n int\n sfc_repr_proxy_add_port(uint16_t pf_port_id, uint16_t repr_id,\n \t\t\tuint16_t rte_port_id, const efx_mport_sel_t *mport_sel)\n@@ -1020,3 +1306,136 @@ sfc_repr_proxy_del_txq(uint16_t pf_port_id, uint16_t repr_id,\n \tsfc_log_init(sa, \"done\");\n \tsfc_put_adapter(sa);\n }\n+\n+int\n+sfc_repr_proxy_start_repr(uint16_t pf_port_id, uint16_t repr_id)\n+{\n+\tbool proxy_start_required = false;\n+\tstruct sfc_repr_proxy_port *port;\n+\tstruct sfc_repr_proxy *rp;\n+\tstruct sfc_adapter *sa;\n+\tint rc;\n+\n+\tsa = sfc_get_adapter_by_pf_port_id(pf_port_id);\n+\trp = sfc_repr_proxy_by_adapter(sa);\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tport = sfc_repr_proxy_find_port(rp, repr_id);\n+\tif (port == NULL) {\n+\t\tsfc_err(sa, \"%s() failed: no such port\", __func__);\n+\t\trc = ENOENT;\n+\t\tgoto fail_not_found;\n+\t}\n+\n+\tif (port->enabled) {\n+\t\trc = EALREADY;\n+\t\tsfc_err(sa, \"failed: repr %u proxy port already started\",\n+\t\t\trepr_id);\n+\t\tgoto fail_already_started;\n+\t}\n+\n+\tif (sa->state == SFC_ETHDEV_STARTED) {\n+\t\tif (sfc_repr_proxy_ports_disabled(rp)) {\n+\t\t\tproxy_start_required = true;\n+\t\t} else {\n+\t\t\trc = sfc_repr_proxy_do_start_port(sa, port);\n+\t\t\tif (rc != 0) {\n+\t\t\t\tsfc_err(sa,\n+\t\t\t\t\t\"failed to start repr %u proxy port\",\n+\t\t\t\t\trepr_id);\n+\t\t\t\tgoto fail_start_id;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tport->enabled = true;\n+\n+\tif (proxy_start_required) {\n+\t\trc = sfc_repr_proxy_start(sa);\n+\t\tif (rc != 0) {\n+\t\t\tsfc_err(sa, \"failed to start proxy\");\n+\t\t\tgoto fail_proxy_start;\n+\t\t}\n+\t}\n+\n+\tsfc_log_init(sa, \"done\");\n+\tsfc_put_adapter(sa);\n+\n+\treturn 0;\n+\n+fail_proxy_start:\n+\tport->enabled = false;\n+\n+fail_start_id:\n+fail_already_started:\n+fail_not_found:\n+\tsfc_err(sa, \"failed to start repr %u proxy port: %s\", repr_id,\n+\t\trte_strerror(rc));\n+\tsfc_put_adapter(sa);\n+\n+\treturn rc;\n+}\n+\n+int\n+sfc_repr_proxy_stop_repr(uint16_t pf_port_id, uint16_t repr_id)\n+{\n+\tstruct sfc_repr_proxy_port *port;\n+\tstruct sfc_repr_proxy_port *p;\n+\tstruct sfc_repr_proxy *rp;\n+\tstruct sfc_adapter *sa;\n+\tint rc;\n+\n+\tsa = sfc_get_adapter_by_pf_port_id(pf_port_id);\n+\trp = sfc_repr_proxy_by_adapter(sa);\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tport = sfc_repr_proxy_find_port(rp, repr_id);\n+\tif (port == NULL) {\n+\t\tsfc_err(sa, \"%s() failed: no such port\", __func__);\n+\t\treturn ENOENT;\n+\t}\n+\n+\tif (!port->enabled) {\n+\t\tsfc_log_init(sa, \"repr %u proxy port is not started - skip\",\n+\t\t\t     repr_id);\n+\t\tsfc_put_adapter(sa);\n+\t\treturn 0;\n+\t}\n+\n+\tif (sa->state == SFC_ETHDEV_STARTED) {\n+\t\tbool last_enabled = true;\n+\n+\t\tTAILQ_FOREACH(p, &rp->ports, entries) {\n+\t\t\tif (p == port)\n+\t\t\t\tcontinue;\n+\n+\t\t\tif (sfc_repr_proxy_port_enabled(p)) {\n+\t\t\t\tlast_enabled = false;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\trc = 0;\n+\t\tif (last_enabled)\n+\t\t\tsfc_repr_proxy_stop(sa);\n+\t\telse\n+\t\t\trc = sfc_repr_proxy_do_stop_port(sa, port);\n+\n+\t\tif (rc != 0) {\n+\t\t\tsfc_err(sa,\n+\t\t\t\t\"failed to stop representor proxy TxQ %u: %s\",\n+\t\t\t\trepr_id, rte_strerror(rc));\n+\t\t\tsfc_put_adapter(sa);\n+\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\tport->enabled = false;\n+\n+\tsfc_log_init(sa, \"done\");\n+\tsfc_put_adapter(sa);\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/sfc/sfc_repr_proxy.h b/drivers/net/sfc/sfc_repr_proxy.h\nindex 1fe7ff3695..c350713a55 100644\n--- a/drivers/net/sfc/sfc_repr_proxy.h\n+++ b/drivers/net/sfc/sfc_repr_proxy.h\n@@ -19,6 +19,8 @@\n \n #include \"sfc_repr.h\"\n #include \"sfc_dp.h\"\n+#include \"sfc_flow.h\"\n+#include \"sfc_mae.h\"\n \n #ifdef __cplusplus\n extern \"C\" {\n@@ -49,6 +51,14 @@ struct sfc_repr_proxy_txq {\n \tstruct rte_ring\t\t\t*ring;\n };\n \n+struct sfc_repr_proxy_filter {\n+\t/*\n+\t * 2 filters are required to match all incoming traffic, unknown\n+\t * unicast and unknown multicast.\n+\t */\n+\tefx_filter_spec_t specs[2];\n+};\n+\n struct sfc_repr_proxy_port {\n \tTAILQ_ENTRY(sfc_repr_proxy_port)\tentries;\n \tuint16_t\t\t\t\trepr_id;\n@@ -56,6 +66,9 @@ struct sfc_repr_proxy_port {\n \tefx_mport_id_t\t\t\t\tegress_mport;\n \tstruct sfc_repr_proxy_rxq\t\trxq[SFC_REPR_RXQ_MAX];\n \tstruct sfc_repr_proxy_txq\t\ttxq[SFC_REPR_TXQ_MAX];\n+\tstruct sfc_mae_rule\t\t\t*mae_rule;\n+\tbool\t\t\t\t\tenabled;\n+\tbool\t\t\t\t\tstarted;\n };\n \n struct sfc_repr_proxy_dp_rxq {\n@@ -72,6 +85,8 @@ struct sfc_repr_proxy_dp_txq {\n enum sfc_repr_proxy_mbox_op {\n \tSFC_REPR_PROXY_MBOX_ADD_PORT,\n \tSFC_REPR_PROXY_MBOX_DEL_PORT,\n+\tSFC_REPR_PROXY_MBOX_START_PORT,\n+\tSFC_REPR_PROXY_MBOX_STOP_PORT,\n };\n \n struct sfc_repr_proxy_mbox {\n@@ -92,6 +107,7 @@ struct sfc_repr_proxy {\n \tbool\t\t\t\tstarted;\n \tstruct sfc_repr_proxy_dp_rxq\tdp_rxq[SFC_REPR_PROXY_NB_RXQ_MAX];\n \tstruct sfc_repr_proxy_dp_txq\tdp_txq[SFC_REPR_PROXY_NB_TXQ_MAX];\n+\tstruct sfc_repr_proxy_filter\tmport_filter;\n \n \tstruct sfc_repr_proxy_mbox\tmbox;\n };\ndiff --git a/drivers/net/sfc/sfc_repr_proxy_api.h b/drivers/net/sfc/sfc_repr_proxy_api.h\nindex d1c0760efa..95b065801d 100644\n--- a/drivers/net/sfc/sfc_repr_proxy_api.h\n+++ b/drivers/net/sfc/sfc_repr_proxy_api.h\n@@ -38,6 +38,9 @@ int sfc_repr_proxy_add_txq(uint16_t pf_port_id, uint16_t repr_id,\n void sfc_repr_proxy_del_txq(uint16_t pf_port_id, uint16_t repr_id,\n \t\t\t    uint16_t queue_id);\n \n+int sfc_repr_proxy_start_repr(uint16_t pf_port_id, uint16_t repr_id);\n+int sfc_repr_proxy_stop_repr(uint16_t pf_port_id, uint16_t repr_id);\n+\n #ifdef __cplusplus\n }\n #endif\n",
    "prefixes": [
        "19/38"
    ]
}