get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 806212,
    "url": "http://patchwork.ozlabs.org/api/patches/806212/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20170827110618.20599-3-saeedm@mellanox.com/",
    "project": {
        "id": 7,
        "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api",
        "name": "Linux network development",
        "link_name": "netdev",
        "list_id": "netdev.vger.kernel.org",
        "list_email": "netdev@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20170827110618.20599-3-saeedm@mellanox.com>",
    "list_archive_url": null,
    "date": "2017-08-27T11:06:16",
    "name": "[net-next,2/4] net/mlx5: Add SRIOV VGT+ support",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "a86202bc8c2389a2c6e6918fd0f9245099aa81fe",
    "submitter": {
        "id": 65299,
        "url": "http://patchwork.ozlabs.org/api/people/65299/?format=api",
        "name": "Saeed Mahameed",
        "email": "saeedm@mellanox.com"
    },
    "delegate": {
        "id": 34,
        "url": "http://patchwork.ozlabs.org/api/users/34/?format=api",
        "username": "davem",
        "first_name": "David",
        "last_name": "Miller",
        "email": "davem@davemloft.net"
    },
    "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/20170827110618.20599-3-saeedm@mellanox.com/mbox/",
    "series": [
        {
            "id": 10,
            "url": "http://patchwork.ozlabs.org/api/series/10/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=10",
            "date": "2017-08-27T11:06:14",
            "name": "SRIOV VF VGT+ and violation counters support",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/10/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/806212/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/806212/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<netdev-owner@vger.kernel.org>",
        "X-Original-To": "patchwork-incoming@ozlabs.org",
        "Delivered-To": "patchwork-incoming@ozlabs.org",
        "Authentication-Results": "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xgCCW5Td2z9s7v\n\tfor <patchwork-incoming@ozlabs.org>;\n\tSun, 27 Aug 2017 21:21:43 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751274AbdH0LVg (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tSun, 27 Aug 2017 07:21:36 -0400",
            "from mail-il-dmz.mellanox.com ([193.47.165.129]:37293 \"EHLO\n\tmellanox.co.il\" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org\n\twith ESMTP id S1751124AbdH0LVa (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Sun, 27 Aug 2017 07:21:30 -0400",
            "from Internal Mail-Server by MTLPINE2 (envelope-from\n\tsaeedm@mellanox.com)\n\twith ESMTPS (AES256-SHA encrypted); 27 Aug 2017 14:21:24 +0300",
            "from sws.mtl.labs.mlnx (reg-l-vrt-045-015.mtl.labs.mlnx\n\t[10.135.45.15])\n\tby labmailer.mlnx (8.13.8/8.13.8) with ESMTP id v7RBLOYC028221;\n\tSun, 27 Aug 2017 14:21:24 +0300"
        ],
        "From": "Saeed Mahameed <saeedm@mellanox.com>",
        "To": "\"David S. Miller\" <davem@davemloft.net>",
        "Cc": "netdev@vger.kernel.org, Eugenia Emantayev <eugenia@mellanox.com>,\n\tMohamad Haj Yahia <mohamad@mellanox.com>,\n\tSaeed Mahameed <saeedm@mellanox.com>",
        "Subject": "[PATCH net-next 2/4] net/mlx5: Add SRIOV VGT+ support",
        "Date": "Sun, 27 Aug 2017 14:06:16 +0300",
        "Message-Id": "<20170827110618.20599-3-saeedm@mellanox.com>",
        "X-Mailer": "git-send-email 2.13.0",
        "In-Reply-To": "<20170827110618.20599-1-saeedm@mellanox.com>",
        "References": "<20170827110618.20599-1-saeedm@mellanox.com>",
        "Sender": "netdev-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<netdev.vger.kernel.org>",
        "X-Mailing-List": "netdev@vger.kernel.org"
    },
    "content": "From: Mohamad Haj Yahia <mohamad@mellanox.com>\n\nImplementing the VGT+ feature via acl tables.\nThe acl tables will hold the actual needed rules which is only the\nintersection of the requested vlan-ids list and the allowed vlan-ids\nlist from the administrator.\n\nSigned-off-by: Mohamad Haj Yahia <mohamad@mellanox.com>\nSigned-off-by: Eugenia Emantayev <eugenia@mellanox.com>\nSigned-off-by: Saeed Mahameed <saeedm@mellanox.com>\n---\n drivers/net/ethernet/mellanox/mlx5/core/en_main.c |  28 ++\n drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 496 +++++++++++++++++-----\n drivers/net/ethernet/mellanox/mlx5/core/eswitch.h |  31 +-\n drivers/net/ethernet/mellanox/mlx5/core/vport.c   |  19 +-\n include/linux/mlx5/vport.h                        |   6 +-\n 5 files changed, 458 insertions(+), 122 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c\nindex fdc2b92f020b..1a2ebe0e79ae 100644\n--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c\n+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c\n@@ -3388,6 +3388,32 @@ static int mlx5e_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos,\n \t\t\t\t\t   vlan, qos);\n }\n \n+static int mlx5e_add_vf_vlan_trunk_range(struct net_device *dev, int vf,\n+\t\t\t\t\t u16 start_vid, u16 end_vid,\n+\t\t\t\t\t __be16 vlan_proto) {\n+\tstruct mlx5e_priv *priv = netdev_priv(dev);\n+\tstruct mlx5_core_dev *mdev = priv->mdev;\n+\n+\tif (vlan_proto != htons(ETH_P_8021Q))\n+\t\treturn -EPROTONOSUPPORT;\n+\n+\treturn mlx5_eswitch_add_vport_trunk_range(mdev->priv.eswitch, vf + 1,\n+\t\t\t\t\t\t  start_vid, end_vid);\n+}\n+\n+static int mlx5e_del_vf_vlan_trunk_range(struct net_device *dev, int vf,\n+\t\t\t\t\t u16 start_vid, u16 end_vid,\n+\t\t\t\t\t __be16 vlan_proto) {\n+\tstruct mlx5e_priv *priv = netdev_priv(dev);\n+\tstruct mlx5_core_dev *mdev = priv->mdev;\n+\n+\tif (vlan_proto != htons(ETH_P_8021Q))\n+\t\treturn -EPROTONOSUPPORT;\n+\n+\treturn mlx5_eswitch_del_vport_trunk_range(mdev->priv.eswitch, vf + 1,\n+\t\t\t\t\t\t  start_vid, end_vid);\n+}\n+\n static int mlx5e_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)\n {\n \tstruct mlx5e_priv *priv = netdev_priv(dev);\n@@ -3733,6 +3759,8 @@ static const struct net_device_ops mlx5e_netdev_ops = {\n \t/* SRIOV E-Switch NDOs */\n \t.ndo_set_vf_mac          = mlx5e_set_vf_mac,\n \t.ndo_set_vf_vlan         = mlx5e_set_vf_vlan,\n+\t.ndo_add_vf_vlan_trunk_range = mlx5e_add_vf_vlan_trunk_range,\n+\t.ndo_del_vf_vlan_trunk_range = mlx5e_del_vf_vlan_trunk_range,\n \t.ndo_set_vf_spoofchk     = mlx5e_set_vf_spoofchk,\n \t.ndo_set_vf_trust        = mlx5e_set_vf_trust,\n \t.ndo_set_vf_rate         = mlx5e_set_vf_rate,\ndiff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c\nindex 6b84c1113301..a8e8670c7c8d 100644\n--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c\n+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c\n@@ -60,12 +60,14 @@ struct vport_addr {\n enum {\n \tUC_ADDR_CHANGE = BIT(0),\n \tMC_ADDR_CHANGE = BIT(1),\n+\tVLAN_CHANGE    = BIT(2),\n \tPROMISC_CHANGE = BIT(3),\n };\n \n /* Vport context events */\n #define SRIOV_VPORT_EVENTS (UC_ADDR_CHANGE | \\\n \t\t\t    MC_ADDR_CHANGE | \\\n+\t\t\t    VLAN_CHANGE | \\\n \t\t\t    PROMISC_CHANGE)\n \n static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,\n@@ -681,6 +683,45 @@ static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,\n \tkfree(mac_list);\n }\n \n+static void esw_update_acl_trunk_bitmap(struct mlx5_eswitch *esw, u32 vport_num)\n+{\n+\tstruct mlx5_vport *vport = &esw->vports[vport_num];\n+\n+\tbitmap_and(vport->acl_vlan_8021q_bitmap, vport->req_vlan_bitmap,\n+\t\t   vport->info.vlan_trunk_8021q_bitmap, VLAN_N_VID);\n+}\n+\n+static int esw_vport_egress_config(struct mlx5_eswitch *esw,\n+\t\t\t\t   struct mlx5_vport *vport);\n+static int esw_vport_ingress_config(struct mlx5_eswitch *esw,\n+\t\t\t\t    struct mlx5_vport *vport);\n+\n+/* Sync vport vlan list from vport context */\n+static void esw_update_vport_vlan_list(struct mlx5_eswitch *esw, u32 vport_num)\n+{\n+\tstruct mlx5_vport *vport = &esw->vports[vport_num];\n+\tDECLARE_BITMAP(prev_vlans_bitmap, VLAN_N_VID);\n+\tint err;\n+\n+\tbitmap_copy(prev_vlans_bitmap, vport->req_vlan_bitmap, VLAN_N_VID);\n+\tbitmap_zero(vport->req_vlan_bitmap, VLAN_N_VID);\n+\n+\tif (!vport->enabled)\n+\t\treturn;\n+\n+\terr = mlx5_query_nic_vport_vlans(esw->dev, vport_num, vport->req_vlan_bitmap);\n+\tif (err)\n+\t\treturn;\n+\n+\tbitmap_xor(prev_vlans_bitmap, prev_vlans_bitmap, vport->req_vlan_bitmap, VLAN_N_VID);\n+\tif (!bitmap_weight(prev_vlans_bitmap, VLAN_N_VID))\n+\t\treturn;\n+\n+\tesw_update_acl_trunk_bitmap(esw, vport_num);\n+\tesw_vport_egress_config(esw, vport);\n+\tesw_vport_ingress_config(esw, vport);\n+}\n+\n /* Sync vport UC/MC list from vport context\n  * Must be called after esw_update_vport_addr_list\n  */\n@@ -812,6 +853,9 @@ static void esw_vport_change_handle_locked(struct mlx5_vport *vport)\n \t\t\t\t\t   MLX5_NVPRT_LIST_TYPE_MC);\n \t}\n \n+\tif (vport->enabled_events & VLAN_CHANGE)\n+\t\tesw_update_vport_vlan_list(esw, vport->vport);\n+\n \tif (vport->enabled_events & PROMISC_CHANGE) {\n \t\tesw_update_vport_rx_mode(esw, vport->vport);\n \t\tif (!IS_ERR_OR_NULL(vport->allmulti_rule))\n@@ -844,18 +888,20 @@ static int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,\n \t\t\t\t       struct mlx5_vport *vport)\n {\n \tint inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);\n+\tstruct mlx5_flow_group *untagged_grp = NULL;\n \tstruct mlx5_flow_group *vlan_grp = NULL;\n \tstruct mlx5_flow_group *drop_grp = NULL;\n \tstruct mlx5_core_dev *dev = esw->dev;\n \tstruct mlx5_flow_namespace *root_ns;\n \tstruct mlx5_flow_table *acl;\n+\t/* The egress acl table contains 3 groups:\n+\t * 1)Allow tagged traffic with vlan_tag=vst_vlan_id/vgt+_vlan_id\n+\t * 2)Allow untagged traffic\n+\t * 2)Drop all other traffic\n+\t */\n+\tint table_size = VLAN_N_VID + 2;\n \tvoid *match_criteria;\n \tu32 *flow_group_in;\n-\t/* The egress acl table contains 2 rules:\n-\t * 1)Allow traffic with vlan_tag=vst_vlan_id\n-\t * 2)Drop all other traffic.\n-\t */\n-\tint table_size = 2;\n \tint err = 0;\n \n \tif (!MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))\n@@ -887,11 +933,26 @@ static int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,\n \n \tMLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);\n \tmatch_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);\n+\n+\t/* Create flow group for allowed untagged flow rule */\n \tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);\n-\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.first_vid);\n \tMLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);\n \tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);\n \n+\tuntagged_grp = mlx5_create_flow_group(acl, flow_group_in);\n+\tif (IS_ERR(untagged_grp)) {\n+\t\terr = PTR_ERR(untagged_grp);\n+\t\tesw_warn(dev, \"Failed to create E-Switch vport[%d] egress untagged flow group, err(%d)\\n\",\n+\t\t\t vport->vport, err);\n+\t\tgoto out;\n+\t}\n+\n+\t/* Create flow group for allowed tagged flow rules */\n+\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);\n+\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.first_vid);\n+\tMLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);\n+\tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, VLAN_N_VID);\n+\n \tvlan_grp = mlx5_create_flow_group(acl, flow_group_in);\n \tif (IS_ERR(vlan_grp)) {\n \t\terr = PTR_ERR(vlan_grp);\n@@ -900,9 +961,10 @@ static int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,\n \t\tgoto out;\n \t}\n \n+\t/* Create flow group for drop rule */\n \tmemset(flow_group_in, 0, inlen);\n-\tMLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);\n-\tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);\n+\tMLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, VLAN_N_VID + 1);\n+\tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, VLAN_N_VID + 1);\n \tdrop_grp = mlx5_create_flow_group(acl, flow_group_in);\n \tif (IS_ERR(drop_grp)) {\n \t\terr = PTR_ERR(drop_grp);\n@@ -914,25 +976,45 @@ static int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,\n \tvport->egress.acl = acl;\n \tvport->egress.drop_grp = drop_grp;\n \tvport->egress.allowed_vlans_grp = vlan_grp;\n+\tvport->egress.allow_untagged_grp = untagged_grp;\n+\n out:\n+\tif (err) {\n+\t\tif (!IS_ERR_OR_NULL(vlan_grp))\n+\t\t\tmlx5_destroy_flow_group(vlan_grp);\n+\t\tif (!IS_ERR_OR_NULL(untagged_grp))\n+\t\t\tmlx5_destroy_flow_group(untagged_grp);\n+\t\tif (!IS_ERR_OR_NULL(acl))\n+\t\t\tmlx5_destroy_flow_table(acl);\n+\t}\n+\n \tkvfree(flow_group_in);\n-\tif (err && !IS_ERR_OR_NULL(vlan_grp))\n-\t\tmlx5_destroy_flow_group(vlan_grp);\n-\tif (err && !IS_ERR_OR_NULL(acl))\n-\t\tmlx5_destroy_flow_table(acl);\n \treturn err;\n }\n \n static void esw_vport_cleanup_egress_rules(struct mlx5_eswitch *esw,\n \t\t\t\t\t   struct mlx5_vport *vport)\n {\n-\tif (!IS_ERR_OR_NULL(vport->egress.allowed_vlan))\n-\t\tmlx5_del_flow_rules(vport->egress.allowed_vlan);\n+\tstruct mlx5_acl_vlan *trunk_vlan_rule, *tmp;\n+\n+\tif (!IS_ERR_OR_NULL(vport->egress.allowed_vst_vlan))\n+\t\tmlx5_del_flow_rules(vport->egress.allowed_vst_vlan);\n+\n+\tlist_for_each_entry_safe(trunk_vlan_rule, tmp,\n+\t\t\t\t &vport->egress.allowed_vlans_rules, list) {\n+\t\tmlx5_del_flow_rules(trunk_vlan_rule->acl_vlan_rule);\n+\t\tlist_del(&trunk_vlan_rule->list);\n+\t\tkfree(trunk_vlan_rule);\n+\t}\n \n \tif (!IS_ERR_OR_NULL(vport->egress.drop_rule))\n \t\tmlx5_del_flow_rules(vport->egress.drop_rule);\n \n-\tvport->egress.allowed_vlan = NULL;\n+\tif (!IS_ERR_OR_NULL(vport->egress.allow_untagged_rule))\n+\t\tmlx5_del_flow_rules(vport->egress.allow_untagged_rule);\n+\n+\tvport->egress.allow_untagged_rule = NULL;\n+\tvport->egress.allowed_vst_vlan = NULL;\n \tvport->egress.drop_rule = NULL;\n }\n \n@@ -945,9 +1027,12 @@ static void esw_vport_disable_egress_acl(struct mlx5_eswitch *esw,\n \tesw_debug(esw->dev, \"Destroy vport[%d] E-Switch egress ACL\\n\", vport->vport);\n \n \tesw_vport_cleanup_egress_rules(esw, vport);\n+\tmlx5_destroy_flow_group(vport->egress.allow_untagged_grp);\n \tmlx5_destroy_flow_group(vport->egress.allowed_vlans_grp);\n \tmlx5_destroy_flow_group(vport->egress.drop_grp);\n \tmlx5_destroy_flow_table(vport->egress.acl);\n+\n+\tvport->egress.allow_untagged_grp = NULL;\n \tvport->egress.allowed_vlans_grp = NULL;\n \tvport->egress.drop_grp = NULL;\n \tvport->egress.acl = NULL;\n@@ -956,11 +1041,15 @@ static void esw_vport_disable_egress_acl(struct mlx5_eswitch *esw,\n static int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,\n \t\t\t\t\tstruct mlx5_vport *vport)\n {\n+\tbool need_vlan_filter = !!bitmap_weight(vport->info.vlan_trunk_8021q_bitmap,\n+\t\t\t\t\t\tVLAN_N_VID);\n \tint inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);\n+\tstruct mlx5_flow_group *untagged_spoof_grp = NULL;\n+\tstruct mlx5_flow_group *tagged_spoof_grp = NULL;\n+\tstruct mlx5_flow_group *drop_grp = NULL;\n \tstruct mlx5_core_dev *dev = esw->dev;\n \tstruct mlx5_flow_namespace *root_ns;\n \tstruct mlx5_flow_table *acl;\n-\tstruct mlx5_flow_group *g;\n \tvoid *match_criteria;\n \tu32 *flow_group_in;\n \t/* The ingress acl table contains 4 groups\n@@ -969,10 +1058,11 @@ static int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,\n \t *      1 drop rule from the last group):\n \t * 1)Allow untagged traffic with smac=original mac.\n \t * 2)Allow untagged traffic.\n-\t * 3)Allow traffic with smac=original mac.\n+\t * 3)Allow tagged traffic with smac=original mac.\n \t * 4)Drop all other traffic.\n \t */\n-\tint table_size = 4;\n+\tint table_size = need_vlan_filter ? 8192 : 4;\n+\tint allow_grp_sz = 1;\n \tint err = 0;\n \n \tif (!MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))\n@@ -1006,76 +1096,71 @@ static int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,\n \tmatch_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);\n \n \tMLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);\n-\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);\n-\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);\n-\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);\n+\n+\tif (vport->info.vlan || vport->info.qos || need_vlan_filter)\n+\t\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);\n+\n+\tif (vport->info.spoofchk) {\n+\t\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);\n+\t\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);\n+\t}\n+\n \tMLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);\n \tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);\n \n-\tg = mlx5_create_flow_group(acl, flow_group_in);\n-\tif (IS_ERR(g)) {\n-\t\terr = PTR_ERR(g);\n+\tuntagged_spoof_grp = mlx5_create_flow_group(acl, flow_group_in);\n+\tif (IS_ERR(untagged_spoof_grp)) {\n+\t\terr = PTR_ERR(untagged_spoof_grp);\n \t\tesw_warn(dev, \"Failed to create E-Switch vport[%d] ingress untagged spoofchk flow group, err(%d)\\n\",\n \t\t\t vport->vport, err);\n \t\tgoto out;\n \t}\n-\tvport->ingress.allow_untagged_spoofchk_grp = g;\n+\n+\tif (!need_vlan_filter)\n+\t\tgoto drop_grp;\n \n \tmemset(flow_group_in, 0, inlen);\n \tMLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);\n+\tif (vport->info.spoofchk) {\n+\t\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);\n+\t\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);\n+\t}\n \tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);\n+\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.first_vid);\n \tMLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);\n-\tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);\n+\tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, VLAN_N_VID);\n+\tallow_grp_sz = VLAN_N_VID + 1;\n \n-\tg = mlx5_create_flow_group(acl, flow_group_in);\n-\tif (IS_ERR(g)) {\n-\t\terr = PTR_ERR(g);\n-\t\tesw_warn(dev, \"Failed to create E-Switch vport[%d] ingress untagged flow group, err(%d)\\n\",\n-\t\t\t vport->vport, err);\n-\t\tgoto out;\n-\t}\n-\tvport->ingress.allow_untagged_only_grp = g;\n-\n-\tmemset(flow_group_in, 0, inlen);\n-\tMLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);\n-\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);\n-\tMLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);\n-\tMLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 2);\n-\tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 2);\n-\n-\tg = mlx5_create_flow_group(acl, flow_group_in);\n-\tif (IS_ERR(g)) {\n-\t\terr = PTR_ERR(g);\n+\ttagged_spoof_grp = mlx5_create_flow_group(acl, flow_group_in);\n+\tif (IS_ERR(tagged_spoof_grp)) {\n+\t\terr = PTR_ERR(tagged_spoof_grp);\n \t\tesw_warn(dev, \"Failed to create E-Switch vport[%d] ingress spoofchk flow group, err(%d)\\n\",\n \t\t\t vport->vport, err);\n \t\tgoto out;\n \t}\n-\tvport->ingress.allow_spoofchk_only_grp = g;\n \n+drop_grp:\n \tmemset(flow_group_in, 0, inlen);\n-\tMLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 3);\n-\tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 3);\n+\tMLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, allow_grp_sz);\n+\tMLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, allow_grp_sz);\n \n-\tg = mlx5_create_flow_group(acl, flow_group_in);\n-\tif (IS_ERR(g)) {\n-\t\terr = PTR_ERR(g);\n+\tdrop_grp = mlx5_create_flow_group(acl, flow_group_in);\n+\tif (IS_ERR(drop_grp)) {\n+\t\terr = PTR_ERR(drop_grp);\n \t\tesw_warn(dev, \"Failed to create E-Switch vport[%d] ingress drop flow group, err(%d)\\n\",\n \t\t\t vport->vport, err);\n \t\tgoto out;\n \t}\n-\tvport->ingress.drop_grp = g;\n+\tvport->ingress.allow_untagged_spoofchk_grp = untagged_spoof_grp;\n+\tvport->ingress.allow_tagged_spoofchk_grp = tagged_spoof_grp;\n+\tvport->ingress.drop_grp = drop_grp;\n \n out:\n \tif (err) {\n-\t\tif (!IS_ERR_OR_NULL(vport->ingress.allow_spoofchk_only_grp))\n-\t\t\tmlx5_destroy_flow_group(\n-\t\t\t\t\tvport->ingress.allow_spoofchk_only_grp);\n-\t\tif (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_only_grp))\n-\t\t\tmlx5_destroy_flow_group(\n-\t\t\t\t\tvport->ingress.allow_untagged_only_grp);\n-\t\tif (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_spoofchk_grp))\n-\t\t\tmlx5_destroy_flow_group(\n-\t\t\t\tvport->ingress.allow_untagged_spoofchk_grp);\n+\t\tif (!IS_ERR_OR_NULL(tagged_spoof_grp))\n+\t\t\tmlx5_destroy_flow_group(tagged_spoof_grp);\n+\t\tif (!IS_ERR_OR_NULL(untagged_spoof_grp))\n+\t\t\tmlx5_destroy_flow_group(untagged_spoof_grp);\n \t\tif (!IS_ERR_OR_NULL(vport->ingress.acl))\n \t\t\tmlx5_destroy_flow_table(vport->ingress.acl);\n \t}\n@@ -1087,14 +1172,23 @@ static int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,\n static void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,\n \t\t\t\t\t    struct mlx5_vport *vport)\n {\n+\tstruct mlx5_acl_vlan *trunk_vlan_rule, *tmp;\n+\n \tif (!IS_ERR_OR_NULL(vport->ingress.drop_rule))\n \t\tmlx5_del_flow_rules(vport->ingress.drop_rule);\n \n-\tif (!IS_ERR_OR_NULL(vport->ingress.allow_rule))\n-\t\tmlx5_del_flow_rules(vport->ingress.allow_rule);\n+\tlist_for_each_entry_safe(trunk_vlan_rule, tmp,\n+\t\t\t\t &vport->ingress.allowed_vlans_rules, list) {\n+\t\tmlx5_del_flow_rules(trunk_vlan_rule->acl_vlan_rule);\n+\t\tlist_del(&trunk_vlan_rule->list);\n+\t\tkfree(trunk_vlan_rule);\n+\t}\n+\n+\tif (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_rule))\n+\t\tmlx5_del_flow_rules(vport->ingress.allow_untagged_rule);\n \n \tvport->ingress.drop_rule = NULL;\n-\tvport->ingress.allow_rule = NULL;\n+\tvport->ingress.allow_untagged_rule = NULL;\n }\n \n static void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw,\n@@ -1106,23 +1200,32 @@ static void esw_vport_disable_ingress_acl(struct mlx5_eswitch *esw,\n \tesw_debug(esw->dev, \"Destroy vport[%d] E-Switch ingress ACL\\n\", vport->vport);\n \n \tesw_vport_cleanup_ingress_rules(esw, vport);\n-\tmlx5_destroy_flow_group(vport->ingress.allow_spoofchk_only_grp);\n-\tmlx5_destroy_flow_group(vport->ingress.allow_untagged_only_grp);\n-\tmlx5_destroy_flow_group(vport->ingress.allow_untagged_spoofchk_grp);\n-\tmlx5_destroy_flow_group(vport->ingress.drop_grp);\n+\tif (!IS_ERR_OR_NULL(vport->ingress.allow_tagged_spoofchk_grp))\n+\t\tmlx5_destroy_flow_group(vport->ingress.allow_tagged_spoofchk_grp);\n+\n+\tif (!IS_ERR_OR_NULL(vport->ingress.allow_untagged_spoofchk_grp))\n+\t\tmlx5_destroy_flow_group(vport->ingress.allow_untagged_spoofchk_grp);\n+\n+\tif (!IS_ERR_OR_NULL(vport->ingress.drop_grp))\n+\t\tmlx5_destroy_flow_group(vport->ingress.drop_grp);\n+\n \tmlx5_destroy_flow_table(vport->ingress.acl);\n \tvport->ingress.acl = NULL;\n \tvport->ingress.drop_grp = NULL;\n-\tvport->ingress.allow_spoofchk_only_grp = NULL;\n-\tvport->ingress.allow_untagged_only_grp = NULL;\n+\tvport->ingress.allow_tagged_spoofchk_grp = NULL;\n \tvport->ingress.allow_untagged_spoofchk_grp = NULL;\n }\n \n static int esw_vport_ingress_config(struct mlx5_eswitch *esw,\n \t\t\t\t    struct mlx5_vport *vport)\n {\n+\tbool need_vlan_filter = !!bitmap_weight(vport->info.vlan_trunk_8021q_bitmap,\n+\t\t\t\t\t\tVLAN_N_VID);\n+\tstruct mlx5_acl_vlan *trunk_vlan_rule;\n \tstruct mlx5_flow_act flow_act = {0};\n \tstruct mlx5_flow_spec *spec;\n+\tbool need_acl_table = true;\n+\tu16 vlan_id = 0;\n \tint err = 0;\n \tu8 *smac_v;\n \n@@ -1133,9 +1236,19 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,\n \t\treturn -EPERM;\n \t}\n \n+\tif ((vport->info.vlan || vport->info.qos) && need_vlan_filter) {\n+\t\tmlx5_core_warn(esw->dev,\n+\t\t\t       \"vport[%d] configure ingress rules failed, Cannot enable both VGT+ and VST\\n\",\n+\t\t\t       vport->vport);\n+\t\treturn -EPERM;\n+\t}\n+\n+\tneed_acl_table = vport->info.vlan || vport->info.qos || vport->info.spoofchk\n+\t\t\t|| need_vlan_filter;\n+\n \tesw_vport_cleanup_ingress_rules(esw, vport);\n \n-\tif (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {\n+\tif (!need_acl_table) {\n \t\tesw_vport_disable_ingress_acl(esw, vport);\n \t\treturn 0;\n \t}\n@@ -1158,7 +1271,10 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,\n \t\tgoto out;\n \t}\n \n-\tif (vport->info.vlan || vport->info.qos)\n+\tspec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;\n+\tflow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;\n+\n+\tif (vport->info.vlan || vport->info.qos || need_vlan_filter)\n \t\tMLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);\n \n \tif (vport->info.spoofchk) {\n@@ -1170,20 +1286,53 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,\n \t\tether_addr_copy(smac_v, vport->info.mac);\n \t}\n \n-\tspec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;\n-\tflow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;\n-\tvport->ingress.allow_rule =\n-\t\tmlx5_add_flow_rules(vport->ingress.acl, spec,\n-\t\t\t\t    &flow_act, NULL, 0);\n-\tif (IS_ERR(vport->ingress.allow_rule)) {\n-\t\terr = PTR_ERR(vport->ingress.allow_rule);\n-\t\tesw_warn(esw->dev,\n-\t\t\t \"vport[%d] configure ingress allow rule, err(%d)\\n\",\n-\t\t\t vport->vport, err);\n-\t\tvport->ingress.allow_rule = NULL;\n-\t\tgoto out;\n+\t/* Allow untagged */\n+\tif (!need_vlan_filter ||\n+\t    (need_vlan_filter && test_bit(0, vport->info.vlan_trunk_8021q_bitmap))) {\n+\t\tvport->ingress.allow_untagged_rule =\n+\t\t\tmlx5_add_flow_rules(vport->ingress.acl, spec,\n+\t\t\t\t\t    &flow_act, NULL, 0);\n+\t\tif (IS_ERR(vport->ingress.allow_untagged_rule)) {\n+\t\t\terr = PTR_ERR(vport->ingress.allow_untagged_rule);\n+\t\t\tesw_warn(esw->dev,\n+\t\t\t\t \"vport[%d] configure ingress allow rule, err(%d)\\n\",\n+\t\t\t\t vport->vport, err);\n+\t\t\tvport->ingress.allow_untagged_rule = NULL;\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\n+\tif (!need_vlan_filter)\n+\t\tgoto drop_rule;\n+\n+\tMLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);\n+\tMLX5_SET_TO_ONES(fte_match_param, spec->match_value, outer_headers.cvlan_tag);\n+\tMLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.first_vid);\n+\n+\t/* VGT+ rules */\n+\tfor_each_set_bit(vlan_id, vport->acl_vlan_8021q_bitmap, VLAN_N_VID) {\n+\t\ttrunk_vlan_rule = kzalloc(sizeof(*trunk_vlan_rule), GFP_KERNEL);\n+\t\tif (!trunk_vlan_rule) {\n+\t\t\terr = -ENOMEM;\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tMLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid,\n+\t\t\t vlan_id);\n+\t\ttrunk_vlan_rule->acl_vlan_rule =\n+\t\t\tmlx5_add_flow_rules(vport->ingress.acl, spec, &flow_act, NULL, 0);\n+\t\tif (IS_ERR(trunk_vlan_rule->acl_vlan_rule)) {\n+\t\t\terr = PTR_ERR(trunk_vlan_rule->acl_vlan_rule);\n+\t\t\tesw_warn(esw->dev,\n+\t\t\t\t \"vport[%d] configure ingress allowed vlan rule failed, err(%d)\\n\",\n+\t\t\t\t vport->vport, err);\n+\t\t\ttrunk_vlan_rule->acl_vlan_rule = NULL;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tlist_add(&trunk_vlan_rule->list, &vport->ingress.allowed_vlans_rules);\n \t}\n \n+drop_rule:\n \tmemset(spec, 0, sizeof(*spec));\n \tflow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;\n \tvport->ingress.drop_rule =\n@@ -1208,13 +1357,19 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,\n static int esw_vport_egress_config(struct mlx5_eswitch *esw,\n \t\t\t\t   struct mlx5_vport *vport)\n {\n+\tbool need_vlan_filter = !!bitmap_weight(vport->info.vlan_trunk_8021q_bitmap,\n+\t\t\t\t\t\tVLAN_N_VID);\n+\tbool need_acl_table = vport->info.vlan || vport->info.qos ||\n+\t\t\t      need_vlan_filter;\n+\tstruct mlx5_acl_vlan *trunk_vlan_rule;\n \tstruct mlx5_flow_act flow_act = {0};\n \tstruct mlx5_flow_spec *spec;\n+\tu16 vlan_id = 0;\n \tint err = 0;\n \n \tesw_vport_cleanup_egress_rules(esw, vport);\n \n-\tif (!vport->info.vlan && !vport->info.qos) {\n+\tif (!need_acl_table) {\n \t\tesw_vport_disable_egress_acl(esw, vport);\n \t\treturn 0;\n \t}\n@@ -1237,24 +1392,66 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,\n \t\tgoto out;\n \t}\n \n-\t/* Allowed vlan rule */\n \tMLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);\n+\tspec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;\n+\tflow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;\n+\n+\t/* Allow untagged */\n+\tif (need_vlan_filter && test_bit(0, vport->info.vlan_trunk_8021q_bitmap)) {\n+\t\tvport->egress.allow_untagged_rule =\n+\t\t\tmlx5_add_flow_rules(vport->egress.acl, spec,\n+\t\t\t\t\t    &flow_act, NULL, 0);\n+\t\tif (IS_ERR(vport->egress.allow_untagged_rule)) {\n+\t\t\terr = PTR_ERR(vport->egress.allow_untagged_rule);\n+\t\t\tesw_warn(esw->dev,\n+\t\t\t\t \"vport[%d] configure egress allow rule, err(%d)\\n\",\n+\t\t\t\t vport->vport, err);\n+\t\t\tvport->egress.allow_untagged_rule = NULL;\n+\t\t}\n+\t}\n+\n+\t/* Allowed vlan rule */\n \tMLX5_SET_TO_ONES(fte_match_param, spec->match_value, outer_headers.cvlan_tag);\n \tMLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.first_vid);\n-\tMLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vport->info.vlan);\n \n-\tspec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;\n-\tflow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;\n-\tvport->egress.allowed_vlan =\n-\t\tmlx5_add_flow_rules(vport->egress.acl, spec,\n-\t\t\t\t    &flow_act, NULL, 0);\n-\tif (IS_ERR(vport->egress.allowed_vlan)) {\n-\t\terr = PTR_ERR(vport->egress.allowed_vlan);\n-\t\tesw_warn(esw->dev,\n-\t\t\t \"vport[%d] configure egress allowed vlan rule failed, err(%d)\\n\",\n-\t\t\t vport->vport, err);\n-\t\tvport->egress.allowed_vlan = NULL;\n-\t\tgoto out;\n+\t/* VST rule */\n+\tif (vport->info.vlan || vport->info.qos) {\n+\t\tMLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vport->info.vlan);\n+\n+\t\tvport->egress.allowed_vst_vlan =\n+\t\t\tmlx5_add_flow_rules(vport->egress.acl, spec,\n+\t\t\t\t\t    &flow_act, NULL, 0);\n+\t\tif (IS_ERR(vport->egress.allowed_vst_vlan)) {\n+\t\t\terr = PTR_ERR(vport->egress.allowed_vst_vlan);\n+\t\t\tesw_warn(esw->dev,\n+\t\t\t\t \"vport[%d] configure egress allowed vlan rule failed, err(%d)\\n\",\n+\t\t\t\t vport->vport, err);\n+\t\t\tvport->egress.allowed_vst_vlan = NULL;\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\n+\t/* VGT+ rules */\n+\tfor_each_set_bit(vlan_id, vport->acl_vlan_8021q_bitmap, VLAN_N_VID) {\n+\t\ttrunk_vlan_rule = kzalloc(sizeof(*trunk_vlan_rule), GFP_KERNEL);\n+\t\tif (!trunk_vlan_rule) {\n+\t\t\terr = -ENOMEM;\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tMLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid,\n+\t\t\t vlan_id);\n+\t\ttrunk_vlan_rule->acl_vlan_rule =\n+\t\t\tmlx5_add_flow_rules(vport->egress.acl, spec, &flow_act, NULL, 0);\n+\t\tif (IS_ERR(trunk_vlan_rule->acl_vlan_rule)) {\n+\t\t\terr = PTR_ERR(trunk_vlan_rule->acl_vlan_rule);\n+\t\t\tesw_warn(esw->dev,\n+\t\t\t\t \"vport[%d] configure egress allowed vlan rule failed, err(%d)\\n\",\n+\t\t\t\t vport->vport, err);\n+\t\t\ttrunk_vlan_rule->acl_vlan_rule = NULL;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tlist_add(&trunk_vlan_rule->list, &vport->egress.allowed_vlans_rules);\n \t}\n \n \t/* Drop others rule (star rule) */\n@@ -1271,6 +1468,8 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,\n \t\tvport->egress.drop_rule = NULL;\n \t}\n out:\n+\tif (err)\n+\t\tesw_vport_cleanup_egress_rules(esw, vport);\n \tkvfree(spec);\n \treturn err;\n }\n@@ -1465,6 +1664,11 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,\n \n \tesw_debug(esw->dev, \"Enabling VPORT(%d)\\n\", vport_num);\n \n+\tbitmap_zero(vport->req_vlan_bitmap, VLAN_N_VID);\n+\tbitmap_zero(vport->acl_vlan_8021q_bitmap, VLAN_N_VID);\n+\tbitmap_zero(vport->info.vlan_trunk_8021q_bitmap, VLAN_N_VID);\n+\tINIT_LIST_HEAD(&vport->egress.allowed_vlans_rules);\n+\tINIT_LIST_HEAD(&vport->ingress.allowed_vlans_rules);\n \t/* Restore old vport configuration */\n \tesw_apply_vport_conf(esw, vport);\n \n@@ -1824,6 +2028,8 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,\n \tivi->trusted = evport->info.trusted;\n \tivi->min_tx_rate = evport->info.min_rate;\n \tivi->max_tx_rate = evport->info.max_rate;\n+\tbitmap_copy((unsigned long *)ivi->trunk_8021q,\n+\t\t    evport->info.vlan_trunk_8021q_bitmap, VLAN_N_VID);\n \tmutex_unlock(&esw->state_lock);\n \n \treturn 0;\n@@ -1843,6 +2049,14 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,\n \tmutex_lock(&esw->state_lock);\n \tevport = &esw->vports[vport];\n \n+\tif (bitmap_weight(evport->info.vlan_trunk_8021q_bitmap, VLAN_N_VID)) {\n+\t\terr = -EPERM;\n+\t\tmlx5_core_warn(esw->dev,\n+\t\t\t       \"VST is not allowed when operating in VGT+ mode vport(%d)\\n\",\n+\t\t\t       vport);\n+\t\tgoto unlock;\n+\t}\n+\n \terr = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);\n \tif (err)\n \t\tgoto unlock;\n@@ -2018,6 +2232,90 @@ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,\n \treturn err;\n }\n \n+static int mlx5_eswitch_update_vport_trunk(struct mlx5_eswitch *esw,\n+\t\t\t\t\t   struct mlx5_vport *evport,\n+\t\t\t\t\t   unsigned long *old_trunk) {\n+\tDECLARE_BITMAP(diff_vlan_bm, VLAN_N_VID);\n+\tint err = 0;\n+\n+\tbitmap_xor(diff_vlan_bm, old_trunk,\n+\t\t   evport->info.vlan_trunk_8021q_bitmap, VLAN_N_VID);\n+\tif (!bitmap_weight(diff_vlan_bm, VLAN_N_VID))\n+\t\treturn err;\n+\n+\tesw_update_acl_trunk_bitmap(esw, evport->vport);\n+\tif (evport->enabled && esw->mode == SRIOV_LEGACY) {\n+\t\terr = esw_vport_egress_config(esw, evport);\n+\t\tif (!err)\n+\t\t\terr = esw_vport_ingress_config(esw, evport);\n+\t}\n+\tif (err) {\n+\t\tbitmap_copy(evport->info.vlan_trunk_8021q_bitmap, old_trunk, VLAN_N_VID);\n+\t\tesw_update_acl_trunk_bitmap(esw, evport->vport);\n+\t\tesw_vport_egress_config(esw, evport);\n+\t\tesw_vport_ingress_config(esw, evport);\n+\t}\n+\n+\treturn err;\n+}\n+\n+int mlx5_eswitch_add_vport_trunk_range(struct mlx5_eswitch *esw,\n+\t\t\t\t       int vport, u16 start_vlan, u16 end_vlan)\n+{\n+\tDECLARE_BITMAP(prev_vport_bitmap, VLAN_N_VID);\n+\tstruct mlx5_vport *evport;\n+\tint err = 0;\n+\n+\tif (!ESW_ALLOWED(esw))\n+\t\treturn -EPERM;\n+\tif (!LEGAL_VPORT(esw, vport) || end_vlan > VLAN_N_VID || start_vlan > end_vlan)\n+\t\treturn -EINVAL;\n+\n+\tmutex_lock(&esw->state_lock);\n+\tevport = &esw->vports[vport];\n+\n+\tif (evport->info.vlan || evport->info.qos) {\n+\t\terr = -EPERM;\n+\t\tmlx5_core_warn(esw->dev,\n+\t\t\t       \"VGT+ is not allowed when operating in VST mode vport(%d)\\n\",\n+\t\t\t       vport);\n+\t\tgoto unlock;\n+\t}\n+\n+\tbitmap_copy(prev_vport_bitmap, evport->info.vlan_trunk_8021q_bitmap, VLAN_N_VID);\n+\tbitmap_set(evport->info.vlan_trunk_8021q_bitmap, start_vlan,\n+\t\t   end_vlan - start_vlan + 1);\n+\terr = mlx5_eswitch_update_vport_trunk(esw, evport, prev_vport_bitmap);\n+\n+unlock:\n+\tmutex_unlock(&esw->state_lock);\n+\n+\treturn err;\n+}\n+\n+int mlx5_eswitch_del_vport_trunk_range(struct mlx5_eswitch *esw,\n+\t\t\t\t       int vport, u16 start_vlan, u16 end_vlan)\n+{\n+\tDECLARE_BITMAP(prev_vport_bitmap, VLAN_N_VID);\n+\tstruct mlx5_vport *evport;\n+\tint err = 0;\n+\n+\tif (!ESW_ALLOWED(esw))\n+\t\treturn -EPERM;\n+\tif (!LEGAL_VPORT(esw, vport) || end_vlan > VLAN_N_VID || start_vlan > end_vlan)\n+\t\treturn -EINVAL;\n+\n+\tmutex_lock(&esw->state_lock);\n+\tevport = &esw->vports[vport];\n+\tbitmap_copy(prev_vport_bitmap, evport->info.vlan_trunk_8021q_bitmap, VLAN_N_VID);\n+\tbitmap_clear(evport->info.vlan_trunk_8021q_bitmap, start_vlan,\n+\t\t     end_vlan - start_vlan + 1);\n+\terr = mlx5_eswitch_update_vport_trunk(esw, evport, prev_vport_bitmap);\n+\tmutex_unlock(&esw->state_lock);\n+\n+\treturn err;\n+}\n+\n int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,\n \t\t\t\t int vport,\n \t\t\t\t struct ifla_vf_stats *vf_stats)\ndiff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h\nindex 565c8b7a399a..39ac2037b666 100644\n--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h\n+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h\n@@ -35,6 +35,8 @@\n \n #include <linux/if_ether.h>\n #include <linux/if_link.h>\n+#include <linux/if_vlan.h>\n+#include <linux/bitmap.h>\n #include <net/devlink.h>\n #include <linux/mlx5/device.h>\n #include \"lib/mpfs.h\"\n@@ -53,6 +55,9 @@ enum {\n #define MLX5_MAX_MC_PER_VPORT(dev) \\\n \t(1 << MLX5_CAP_GEN(dev, log_max_current_mc_list))\n \n+#define MLX5_MAX_VLAN_PER_VPORT(dev) \\\n+\t(1 << MLX5_CAP_GEN(dev, log_max_vlan_list))\n+\n #define FDB_UPLINK_VPORT 0xffff\n \n #define MLX5_MIN_BW_SHARE 1\n@@ -63,19 +68,22 @@ enum {\n struct vport_ingress {\n \tstruct mlx5_flow_table *acl;\n \tstruct mlx5_flow_group *allow_untagged_spoofchk_grp;\n-\tstruct mlx5_flow_group *allow_spoofchk_only_grp;\n-\tstruct mlx5_flow_group *allow_untagged_only_grp;\n+\tstruct mlx5_flow_group *allow_tagged_spoofchk_grp;\n \tstruct mlx5_flow_group *drop_grp;\n-\tstruct mlx5_flow_handle  *allow_rule;\n+\tstruct mlx5_flow_handle  *allow_untagged_rule;\n+\tstruct list_head         allowed_vlans_rules;\n \tstruct mlx5_flow_handle  *drop_rule;\n };\n \n struct vport_egress {\n \tstruct mlx5_flow_table *acl;\n+\tstruct mlx5_flow_group *allow_untagged_grp;\n \tstruct mlx5_flow_group *allowed_vlans_grp;\n \tstruct mlx5_flow_group *drop_grp;\n-\tstruct mlx5_flow_handle  *allowed_vlan;\n+\tstruct mlx5_flow_handle  *allowed_vst_vlan;\n \tstruct mlx5_flow_handle  *drop_rule;\n+\tstruct mlx5_flow_handle  *allow_untagged_rule;\n+\tstruct list_head        allowed_vlans_rules;\n };\n \n struct mlx5_vport_info {\n@@ -88,6 +96,8 @@ struct mlx5_vport_info {\n \tu32                     max_rate;\n \tbool                    spoofchk;\n \tbool                    trusted;\n+\t/* the admin approved vlan list */\n+\tDECLARE_BITMAP(vlan_trunk_8021q_bitmap, VLAN_N_VID);\n };\n \n struct mlx5_vport {\n@@ -95,6 +105,10 @@ struct mlx5_vport {\n \tint                     vport;\n \tstruct hlist_head       uc_list[MLX5_L2_ADDR_HASH_SIZE];\n \tstruct hlist_head       mc_list[MLX5_L2_ADDR_HASH_SIZE];\n+\t/* The requested vlan list from the vport side */\n+\tDECLARE_BITMAP(req_vlan_bitmap, VLAN_N_VID);\n+\t/* Actual accepted vlans on the acl tables */\n+\tDECLARE_BITMAP(acl_vlan_8021q_bitmap, VLAN_N_VID);\n \tstruct mlx5_flow_handle *promisc_rule;\n \tstruct mlx5_flow_handle *allmulti_rule;\n \tstruct work_struct      vport_change_handler;\n@@ -133,6 +147,11 @@ struct mlx5_eswitch_fdb {\n \t};\n };\n \n+struct mlx5_acl_vlan {\n+\tstruct mlx5_flow_handle\t*acl_vlan_rule;\n+\tstruct list_head\tlist;\n+};\n+\n struct mlx5_esw_sq {\n \tstruct mlx5_flow_handle\t*send_to_vport_rule;\n \tstruct list_head\t list;\n@@ -218,6 +237,10 @@ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,\n \t\t\t\tu32 max_rate, u32 min_rate);\n int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,\n \t\t\t\t  int vport, struct ifla_vf_info *ivi);\n+int mlx5_eswitch_add_vport_trunk_range(struct mlx5_eswitch *esw,\n+\t\t\t\t       int vport, u16 start_vlan, u16 end_vlan);\n+int mlx5_eswitch_del_vport_trunk_range(struct mlx5_eswitch *esw,\n+\t\t\t\t       int vport, u16 start_vlan, u16 end_vlan);\n int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,\n \t\t\t\t int vport,\n \t\t\t\t struct ifla_vf_stats *vf_stats);\ndiff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c\nindex 5abfec1c3399..c3afc7af6280 100644\n--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c\n+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c\n@@ -381,28 +381,18 @@ int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,\n }\n EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);\n \n-int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev,\n-\t\t\t       u32 vport,\n-\t\t\t       u16 vlans[],\n-\t\t\t       int *size)\n+int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev, u32 vport,\n+\t\t\t       unsigned long *vlans)\n {\n \tu32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)];\n \tvoid *nic_vport_ctx;\n \tint req_list_size;\n-\tint max_list_size;\n \tint out_sz;\n \tvoid *out;\n \tint err;\n \tint i;\n \n-\treq_list_size = *size;\n-\tmax_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);\n-\tif (req_list_size > max_list_size) {\n-\t\tmlx5_core_warn(dev, \"Requested list size (%d) > (%d) max list size\\n\",\n-\t\t\t       req_list_size, max_list_size);\n-\t\treq_list_size = max_list_size;\n-\t}\n-\n+\treq_list_size = 1 << MLX5_CAP_GEN(dev, log_max_vlan_list);\n \tout_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +\n \t\t\treq_list_size * MLX5_ST_SZ_BYTES(vlan_layout);\n \n@@ -429,12 +419,11 @@ int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev,\n \treq_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,\n \t\t\t\t allowed_list_size);\n \n-\t*size = req_list_size;\n \tfor (i = 0; i < req_list_size; i++) {\n \t\tvoid *vlan_addr = MLX5_ADDR_OF(nic_vport_context,\n \t\t\t\t\t       nic_vport_ctx,\n \t\t\t\t\t       current_uc_mac_address[i]);\n-\t\tvlans[i] = MLX5_GET(vlan_layout, vlan_addr, vlan);\n+\t\tbitmap_set(vlans, MLX5_GET(vlan_layout, vlan_addr, vlan), 1);\n \t}\n out:\n \tkfree(out);\ndiff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h\nindex 656c70b65dd2..a285bd04eefb 100644\n--- a/include/linux/mlx5/vport.h\n+++ b/include/linux/mlx5/vport.h\n@@ -97,10 +97,8 @@ int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev,\n \t\t\t\t  int promisc_uc,\n \t\t\t\t  int promisc_mc,\n \t\t\t\t  int promisc_all);\n-int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev,\n-\t\t\t       u32 vport,\n-\t\t\t       u16 vlans[],\n-\t\t\t       int *size);\n+int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev, u32 vport,\n+\t\t\t       unsigned long *vlans);\n int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,\n \t\t\t\tu16 vlans[],\n \t\t\t\tint list_size);\n",
    "prefixes": [
        "net-next",
        "2/4"
    ]
}