linux/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2015, Mellanox Technologies. All rights reserved.
   3 *
   4 * This software is available to you under a choice of one of two
   5 * licenses.  You may choose to be licensed under the terms of the GNU
   6 * General Public License (GPL) Version 2, available from the file
   7 * COPYING in the main directory of this source tree, or the
   8 * OpenIB.org BSD license below:
   9 *
  10 *     Redistribution and use in source and binary forms, with or
  11 *     without modification, are permitted provided that the following
  12 *     conditions are met:
  13 *
  14 *      - Redistributions of source code must retain the above
  15 *        copyright notice, this list of conditions and the following
  16 *        disclaimer.
  17 *
  18 *      - Redistributions in binary form must reproduce the above
  19 *        copyright notice, this list of conditions and the following
  20 *        disclaimer in the documentation and/or other materials
  21 *        provided with the distribution.
  22 *
  23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30 * SOFTWARE.
  31 */
  32
  33#include <linux/list.h>
  34#include <linux/ip.h>
  35#include <linux/ipv6.h>
  36#include <linux/tcp.h>
  37#include <linux/mlx5/fs.h>
  38#include <linux/mlx5/mpfs.h>
  39#include "en.h"
  40#include "en_rep.h"
  41#include "lib/mpfs.h"
  42#include "en/ptp.h"
  43
  44static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
  45                                  struct mlx5e_l2_rule *ai, int type);
  46static void mlx5e_del_l2_flow_rule(struct mlx5e_priv *priv,
  47                                   struct mlx5e_l2_rule *ai);
  48
  49enum {
  50        MLX5E_FULLMATCH = 0,
  51        MLX5E_ALLMULTI  = 1,
  52};
  53
  54enum {
  55        MLX5E_UC        = 0,
  56        MLX5E_MC_IPV4   = 1,
  57        MLX5E_MC_IPV6   = 2,
  58        MLX5E_MC_OTHER  = 3,
  59};
  60
  61enum {
  62        MLX5E_ACTION_NONE = 0,
  63        MLX5E_ACTION_ADD  = 1,
  64        MLX5E_ACTION_DEL  = 2,
  65};
  66
  67struct mlx5e_l2_hash_node {
  68        struct hlist_node          hlist;
  69        u8                         action;
  70        struct mlx5e_l2_rule ai;
  71        bool   mpfs;
  72};
  73
  74static inline int mlx5e_hash_l2(u8 *addr)
  75{
  76        return addr[5];
  77}
  78
  79static void mlx5e_add_l2_to_hash(struct hlist_head *hash, u8 *addr)
  80{
  81        struct mlx5e_l2_hash_node *hn;
  82        int ix = mlx5e_hash_l2(addr);
  83        int found = 0;
  84
  85        hlist_for_each_entry(hn, &hash[ix], hlist)
  86                if (ether_addr_equal_64bits(hn->ai.addr, addr)) {
  87                        found = 1;
  88                        break;
  89                }
  90
  91        if (found) {
  92                hn->action = MLX5E_ACTION_NONE;
  93                return;
  94        }
  95
  96        hn = kzalloc(sizeof(*hn), GFP_ATOMIC);
  97        if (!hn)
  98                return;
  99
 100        ether_addr_copy(hn->ai.addr, addr);
 101        hn->action = MLX5E_ACTION_ADD;
 102
 103        hlist_add_head(&hn->hlist, &hash[ix]);
 104}
 105
 106static void mlx5e_del_l2_from_hash(struct mlx5e_l2_hash_node *hn)
 107{
 108        hlist_del(&hn->hlist);
 109        kfree(hn);
 110}
 111
 112struct mlx5e_vlan_table {
 113        struct mlx5e_flow_table         ft;
 114        DECLARE_BITMAP(active_cvlans, VLAN_N_VID);
 115        DECLARE_BITMAP(active_svlans, VLAN_N_VID);
 116        struct mlx5_flow_handle *active_cvlans_rule[VLAN_N_VID];
 117        struct mlx5_flow_handle *active_svlans_rule[VLAN_N_VID];
 118        struct mlx5_flow_handle *untagged_rule;
 119        struct mlx5_flow_handle *any_cvlan_rule;
 120        struct mlx5_flow_handle *any_svlan_rule;
 121        struct mlx5_flow_handle *trap_rule;
 122        bool                    cvlan_filter_disabled;
 123};
 124
 125unsigned long *mlx5e_vlan_get_active_svlans(struct mlx5e_vlan_table *vlan)
 126{
 127        return vlan->active_svlans;
 128}
 129
 130struct mlx5_flow_table *mlx5e_vlan_get_flowtable(struct mlx5e_vlan_table *vlan)
 131{
 132        return vlan->ft.t;
 133}
 134
 135static int mlx5e_vport_context_update_vlans(struct mlx5e_priv *priv)
 136{
 137        struct net_device *ndev = priv->netdev;
 138        int max_list_size;
 139        int list_size;
 140        u16 *vlans;
 141        int vlan;
 142        int err;
 143        int i;
 144
 145        list_size = 0;
 146        for_each_set_bit(vlan, priv->fs.vlan->active_cvlans, VLAN_N_VID)
 147                list_size++;
 148
 149        max_list_size = 1 << MLX5_CAP_GEN(priv->mdev, log_max_vlan_list);
 150
 151        if (list_size > max_list_size) {
 152                netdev_warn(ndev,
 153                            "netdev vlans list size (%d) > (%d) max vport list size, some vlans will be dropped\n",
 154                            list_size, max_list_size);
 155                list_size = max_list_size;
 156        }
 157
 158        vlans = kcalloc(list_size, sizeof(*vlans), GFP_KERNEL);
 159        if (!vlans)
 160                return -ENOMEM;
 161
 162        i = 0;
 163        for_each_set_bit(vlan, priv->fs.vlan->active_cvlans, VLAN_N_VID) {
 164                if (i >= list_size)
 165                        break;
 166                vlans[i++] = vlan;
 167        }
 168
 169        err = mlx5_modify_nic_vport_vlans(priv->mdev, vlans, list_size);
 170        if (err)
 171                netdev_err(ndev, "Failed to modify vport vlans list err(%d)\n",
 172                           err);
 173
 174        kfree(vlans);
 175        return err;
 176}
 177
 178enum mlx5e_vlan_rule_type {
 179        MLX5E_VLAN_RULE_TYPE_UNTAGGED,
 180        MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID,
 181        MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID,
 182        MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID,
 183        MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID,
 184};
 185
 186static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
 187                                 enum mlx5e_vlan_rule_type rule_type,
 188                                 u16 vid, struct mlx5_flow_spec *spec)
 189{
 190        struct mlx5_flow_table *ft = priv->fs.vlan->ft.t;
 191        struct mlx5_flow_destination dest = {};
 192        struct mlx5_flow_handle **rule_p;
 193        MLX5_DECLARE_FLOW_ACT(flow_act);
 194        int err = 0;
 195
 196        dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
 197        dest.ft = priv->fs.l2.ft.t;
 198
 199        spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
 200
 201        switch (rule_type) {
 202        case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
 203                /* cvlan_tag enabled in match criteria and
 204                 * disabled in match value means both S & C tags
 205                 * don't exist (untagged of both)
 206                 */
 207                rule_p = &priv->fs.vlan->untagged_rule;
 208                MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
 209                                 outer_headers.cvlan_tag);
 210                break;
 211        case MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID:
 212                rule_p = &priv->fs.vlan->any_cvlan_rule;
 213                MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
 214                                 outer_headers.cvlan_tag);
 215                MLX5_SET(fte_match_param, spec->match_value, outer_headers.cvlan_tag, 1);
 216                break;
 217        case MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID:
 218                rule_p = &priv->fs.vlan->any_svlan_rule;
 219                MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
 220                                 outer_headers.svlan_tag);
 221                MLX5_SET(fte_match_param, spec->match_value, outer_headers.svlan_tag, 1);
 222                break;
 223        case MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID:
 224                rule_p = &priv->fs.vlan->active_svlans_rule[vid];
 225                MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
 226                                 outer_headers.svlan_tag);
 227                MLX5_SET(fte_match_param, spec->match_value, outer_headers.svlan_tag, 1);
 228                MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
 229                                 outer_headers.first_vid);
 230                MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid,
 231                         vid);
 232                break;
 233        default: /* MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID */
 234                rule_p = &priv->fs.vlan->active_cvlans_rule[vid];
 235                MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
 236                                 outer_headers.cvlan_tag);
 237                MLX5_SET(fte_match_param, spec->match_value, outer_headers.cvlan_tag, 1);
 238                MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
 239                                 outer_headers.first_vid);
 240                MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid,
 241                         vid);
 242                break;
 243        }
 244
 245        if (WARN_ONCE(*rule_p, "VLAN rule already exists type %d", rule_type))
 246                return 0;
 247
 248        *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
 249
 250        if (IS_ERR(*rule_p)) {
 251                err = PTR_ERR(*rule_p);
 252                *rule_p = NULL;
 253                netdev_err(priv->netdev, "%s: add rule failed\n", __func__);
 254        }
 255
 256        return err;
 257}
 258
 259static int mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
 260                               enum mlx5e_vlan_rule_type rule_type, u16 vid)
 261{
 262        struct mlx5_flow_spec *spec;
 263        int err = 0;
 264
 265        spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
 266        if (!spec)
 267                return -ENOMEM;
 268
 269        if (rule_type == MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID)
 270                mlx5e_vport_context_update_vlans(priv);
 271
 272        err = __mlx5e_add_vlan_rule(priv, rule_type, vid, spec);
 273
 274        kvfree(spec);
 275
 276        return err;
 277}
 278
 279static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
 280                                enum mlx5e_vlan_rule_type rule_type, u16 vid)
 281{
 282        switch (rule_type) {
 283        case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
 284                if (priv->fs.vlan->untagged_rule) {
 285                        mlx5_del_flow_rules(priv->fs.vlan->untagged_rule);
 286                        priv->fs.vlan->untagged_rule = NULL;
 287                }
 288                break;
 289        case MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID:
 290                if (priv->fs.vlan->any_cvlan_rule) {
 291                        mlx5_del_flow_rules(priv->fs.vlan->any_cvlan_rule);
 292                        priv->fs.vlan->any_cvlan_rule = NULL;
 293                }
 294                break;
 295        case MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID:
 296                if (priv->fs.vlan->any_svlan_rule) {
 297                        mlx5_del_flow_rules(priv->fs.vlan->any_svlan_rule);
 298                        priv->fs.vlan->any_svlan_rule = NULL;
 299                }
 300                break;
 301        case MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID:
 302                if (priv->fs.vlan->active_svlans_rule[vid]) {
 303                        mlx5_del_flow_rules(priv->fs.vlan->active_svlans_rule[vid]);
 304                        priv->fs.vlan->active_svlans_rule[vid] = NULL;
 305                }
 306                break;
 307        case MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID:
 308                if (priv->fs.vlan->active_cvlans_rule[vid]) {
 309                        mlx5_del_flow_rules(priv->fs.vlan->active_cvlans_rule[vid]);
 310                        priv->fs.vlan->active_cvlans_rule[vid] = NULL;
 311                }
 312                mlx5e_vport_context_update_vlans(priv);
 313                break;
 314        }
 315}
 316
 317static void mlx5e_del_any_vid_rules(struct mlx5e_priv *priv)
 318{
 319        mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
 320        mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID, 0);
 321}
 322
 323static int mlx5e_add_any_vid_rules(struct mlx5e_priv *priv)
 324{
 325        int err;
 326
 327        err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
 328        if (err)
 329                return err;
 330
 331        return mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_STAG_VID, 0);
 332}
 333
 334static struct mlx5_flow_handle *
 335mlx5e_add_trap_rule(struct mlx5_flow_table *ft, int trap_id, int tir_num)
 336{
 337        struct mlx5_flow_destination dest = {};
 338        MLX5_DECLARE_FLOW_ACT(flow_act);
 339        struct mlx5_flow_handle *rule;
 340        struct mlx5_flow_spec *spec;
 341
 342        spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
 343        if (!spec)
 344                return ERR_PTR(-ENOMEM);
 345        spec->flow_context.flags |= FLOW_CONTEXT_HAS_TAG;
 346        spec->flow_context.flow_tag = trap_id;
 347        dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
 348        dest.tir_num = tir_num;
 349
 350        rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
 351        kvfree(spec);
 352        return rule;
 353}
 354
 355int mlx5e_add_vlan_trap(struct mlx5e_priv *priv, int trap_id, int tir_num)
 356{
 357        struct mlx5_flow_table *ft = priv->fs.vlan->ft.t;
 358        struct mlx5_flow_handle *rule;
 359        int err;
 360
 361        rule = mlx5e_add_trap_rule(ft, trap_id, tir_num);
 362        if (IS_ERR(rule)) {
 363                err = PTR_ERR(rule);
 364                priv->fs.vlan->trap_rule = NULL;
 365                netdev_err(priv->netdev, "%s: add VLAN trap rule failed, err %d\n",
 366                           __func__, err);
 367                return err;
 368        }
 369        priv->fs.vlan->trap_rule = rule;
 370        return 0;
 371}
 372
 373void mlx5e_remove_vlan_trap(struct mlx5e_priv *priv)
 374{
 375        if (priv->fs.vlan->trap_rule) {
 376                mlx5_del_flow_rules(priv->fs.vlan->trap_rule);
 377                priv->fs.vlan->trap_rule = NULL;
 378        }
 379}
 380
 381int mlx5e_add_mac_trap(struct mlx5e_priv *priv, int trap_id, int tir_num)
 382{
 383        struct mlx5_flow_table *ft = priv->fs.l2.ft.t;
 384        struct mlx5_flow_handle *rule;
 385        int err;
 386
 387        rule = mlx5e_add_trap_rule(ft, trap_id, tir_num);
 388        if (IS_ERR(rule)) {
 389                err = PTR_ERR(rule);
 390                priv->fs.l2.trap_rule = NULL;
 391                netdev_err(priv->netdev, "%s: add MAC trap rule failed, err %d\n",
 392                           __func__, err);
 393                return err;
 394        }
 395        priv->fs.l2.trap_rule = rule;
 396        return 0;
 397}
 398
 399void mlx5e_remove_mac_trap(struct mlx5e_priv *priv)
 400{
 401        if (priv->fs.l2.trap_rule) {
 402                mlx5_del_flow_rules(priv->fs.l2.trap_rule);
 403                priv->fs.l2.trap_rule = NULL;
 404        }
 405}
 406
 407void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv)
 408{
 409        if (!priv->fs.vlan->cvlan_filter_disabled)
 410                return;
 411
 412        priv->fs.vlan->cvlan_filter_disabled = false;
 413        if (priv->netdev->flags & IFF_PROMISC)
 414                return;
 415        mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
 416}
 417
 418void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv)
 419{
 420        if (priv->fs.vlan->cvlan_filter_disabled)
 421                return;
 422
 423        priv->fs.vlan->cvlan_filter_disabled = true;
 424        if (priv->netdev->flags & IFF_PROMISC)
 425                return;
 426        mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
 427}
 428
 429static int mlx5e_vlan_rx_add_cvid(struct mlx5e_priv *priv, u16 vid)
 430{
 431        int err;
 432
 433        set_bit(vid, priv->fs.vlan->active_cvlans);
 434
 435        err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, vid);
 436        if (err)
 437                clear_bit(vid, priv->fs.vlan->active_cvlans);
 438
 439        return err;
 440}
 441
 442static int mlx5e_vlan_rx_add_svid(struct mlx5e_priv *priv, u16 vid)
 443{
 444        struct net_device *netdev = priv->netdev;
 445        int err;
 446
 447        set_bit(vid, priv->fs.vlan->active_svlans);
 448
 449        err = mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, vid);
 450        if (err) {
 451                clear_bit(vid, priv->fs.vlan->active_svlans);
 452                return err;
 453        }
 454
 455        /* Need to fix some features.. */
 456        netdev_update_features(netdev);
 457        return err;
 458}
 459
 460int mlx5e_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
 461{
 462        struct mlx5e_priv *priv = netdev_priv(dev);
 463
 464        if (mlx5e_is_uplink_rep(priv))
 465                return 0; /* no vlan table for uplink rep */
 466
 467        if (be16_to_cpu(proto) == ETH_P_8021Q)
 468                return mlx5e_vlan_rx_add_cvid(priv, vid);
 469        else if (be16_to_cpu(proto) == ETH_P_8021AD)
 470                return mlx5e_vlan_rx_add_svid(priv, vid);
 471
 472        return -EOPNOTSUPP;
 473}
 474
 475int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
 476{
 477        struct mlx5e_priv *priv = netdev_priv(dev);
 478
 479        if (mlx5e_is_uplink_rep(priv))
 480                return 0; /* no vlan table for uplink rep */
 481
 482        if (be16_to_cpu(proto) == ETH_P_8021Q) {
 483                clear_bit(vid, priv->fs.vlan->active_cvlans);
 484                mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, vid);
 485        } else if (be16_to_cpu(proto) == ETH_P_8021AD) {
 486                clear_bit(vid, priv->fs.vlan->active_svlans);
 487                mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, vid);
 488                netdev_update_features(dev);
 489        }
 490
 491        return 0;
 492}
 493
 494static void mlx5e_add_vlan_rules(struct mlx5e_priv *priv)
 495{
 496        int i;
 497
 498        mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
 499
 500        for_each_set_bit(i, priv->fs.vlan->active_cvlans, VLAN_N_VID) {
 501                mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, i);
 502        }
 503
 504        for_each_set_bit(i, priv->fs.vlan->active_svlans, VLAN_N_VID)
 505                mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
 506
 507        if (priv->fs.vlan->cvlan_filter_disabled)
 508                mlx5e_add_any_vid_rules(priv);
 509}
 510
 511static void mlx5e_del_vlan_rules(struct mlx5e_priv *priv)
 512{
 513        int i;
 514
 515        mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
 516
 517        for_each_set_bit(i, priv->fs.vlan->active_cvlans, VLAN_N_VID) {
 518                mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, i);
 519        }
 520
 521        for_each_set_bit(i, priv->fs.vlan->active_svlans, VLAN_N_VID)
 522                mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
 523
 524        WARN_ON_ONCE(!(test_bit(MLX5E_STATE_DESTROYING, &priv->state)));
 525
 526        mlx5e_remove_vlan_trap(priv);
 527
 528        /* must be called after DESTROY bit is set and
 529         * set_rx_mode is called and flushed
 530         */
 531        if (priv->fs.vlan->cvlan_filter_disabled)
 532                mlx5e_del_any_vid_rules(priv);
 533}
 534
 535#define mlx5e_for_each_hash_node(hn, tmp, hash, i) \
 536        for (i = 0; i < MLX5E_L2_ADDR_HASH_SIZE; i++) \
 537                hlist_for_each_entry_safe(hn, tmp, &hash[i], hlist)
 538
 539static void mlx5e_execute_l2_action(struct mlx5e_priv *priv,
 540                                    struct mlx5e_l2_hash_node *hn)
 541{
 542        u8 action = hn->action;
 543        u8 mac_addr[ETH_ALEN];
 544        int l2_err = 0;
 545
 546        ether_addr_copy(mac_addr, hn->ai.addr);
 547
 548        switch (action) {
 549        case MLX5E_ACTION_ADD:
 550                mlx5e_add_l2_flow_rule(priv, &hn->ai, MLX5E_FULLMATCH);
 551                if (!is_multicast_ether_addr(mac_addr)) {
 552                        l2_err = mlx5_mpfs_add_mac(priv->mdev, mac_addr);
 553                        hn->mpfs = !l2_err;
 554                }
 555                hn->action = MLX5E_ACTION_NONE;
 556                break;
 557
 558        case MLX5E_ACTION_DEL:
 559                if (!is_multicast_ether_addr(mac_addr) && hn->mpfs)
 560                        l2_err = mlx5_mpfs_del_mac(priv->mdev, mac_addr);
 561                mlx5e_del_l2_flow_rule(priv, &hn->ai);
 562                mlx5e_del_l2_from_hash(hn);
 563                break;
 564        }
 565
 566        if (l2_err)
 567                netdev_warn(priv->netdev, "MPFS, failed to %s mac %pM, err(%d)\n",
 568                            action == MLX5E_ACTION_ADD ? "add" : "del", mac_addr, l2_err);
 569}
 570
 571static void mlx5e_sync_netdev_addr(struct mlx5e_priv *priv)
 572{
 573        struct net_device *netdev = priv->netdev;
 574        struct netdev_hw_addr *ha;
 575
 576        netif_addr_lock_bh(netdev);
 577
 578        mlx5e_add_l2_to_hash(priv->fs.l2.netdev_uc,
 579                             priv->netdev->dev_addr);
 580
 581        netdev_for_each_uc_addr(ha, netdev)
 582                mlx5e_add_l2_to_hash(priv->fs.l2.netdev_uc, ha->addr);
 583
 584        netdev_for_each_mc_addr(ha, netdev)
 585                mlx5e_add_l2_to_hash(priv->fs.l2.netdev_mc, ha->addr);
 586
 587        netif_addr_unlock_bh(netdev);
 588}
 589
 590static void mlx5e_fill_addr_array(struct mlx5e_priv *priv, int list_type,
 591                                  u8 addr_array[][ETH_ALEN], int size)
 592{
 593        bool is_uc = (list_type == MLX5_NVPRT_LIST_TYPE_UC);
 594        struct net_device *ndev = priv->netdev;
 595        struct mlx5e_l2_hash_node *hn;
 596        struct hlist_head *addr_list;
 597        struct hlist_node *tmp;
 598        int i = 0;
 599        int hi;
 600
 601        addr_list = is_uc ? priv->fs.l2.netdev_uc : priv->fs.l2.netdev_mc;
 602
 603        if (is_uc) /* Make sure our own address is pushed first */
 604                ether_addr_copy(addr_array[i++], ndev->dev_addr);
 605        else if (priv->fs.l2.broadcast_enabled)
 606                ether_addr_copy(addr_array[i++], ndev->broadcast);
 607
 608        mlx5e_for_each_hash_node(hn, tmp, addr_list, hi) {
 609                if (ether_addr_equal(ndev->dev_addr, hn->ai.addr))
 610                        continue;
 611                if (i >= size)
 612                        break;
 613                ether_addr_copy(addr_array[i++], hn->ai.addr);
 614        }
 615}
 616
 617static void mlx5e_vport_context_update_addr_list(struct mlx5e_priv *priv,
 618                                                 int list_type)
 619{
 620        bool is_uc = (list_type == MLX5_NVPRT_LIST_TYPE_UC);
 621        struct mlx5e_l2_hash_node *hn;
 622        u8 (*addr_array)[ETH_ALEN] = NULL;
 623        struct hlist_head *addr_list;
 624        struct hlist_node *tmp;
 625        int max_size;
 626        int size;
 627        int err;
 628        int hi;
 629
 630        size = is_uc ? 0 : (priv->fs.l2.broadcast_enabled ? 1 : 0);
 631        max_size = is_uc ?
 632                1 << MLX5_CAP_GEN(priv->mdev, log_max_current_uc_list) :
 633                1 << MLX5_CAP_GEN(priv->mdev, log_max_current_mc_list);
 634
 635        addr_list = is_uc ? priv->fs.l2.netdev_uc : priv->fs.l2.netdev_mc;
 636        mlx5e_for_each_hash_node(hn, tmp, addr_list, hi)
 637                size++;
 638
 639        if (size > max_size) {
 640                netdev_warn(priv->netdev,
 641                            "netdev %s list size (%d) > (%d) max vport list size, some addresses will be dropped\n",
 642                            is_uc ? "UC" : "MC", size, max_size);
 643                size = max_size;
 644        }
 645
 646        if (size) {
 647                addr_array = kcalloc(size, ETH_ALEN, GFP_KERNEL);
 648                if (!addr_array) {
 649                        err = -ENOMEM;
 650                        goto out;
 651                }
 652                mlx5e_fill_addr_array(priv, list_type, addr_array, size);
 653        }
 654
 655        err = mlx5_modify_nic_vport_mac_list(priv->mdev, list_type, addr_array, size);
 656out:
 657        if (err)
 658                netdev_err(priv->netdev,
 659                           "Failed to modify vport %s list err(%d)\n",
 660                           is_uc ? "UC" : "MC", err);
 661        kfree(addr_array);
 662}
 663
 664static void mlx5e_vport_context_update(struct mlx5e_priv *priv)
 665{
 666        struct mlx5e_l2_table *ea = &priv->fs.l2;
 667
 668        mlx5e_vport_context_update_addr_list(priv, MLX5_NVPRT_LIST_TYPE_UC);
 669        mlx5e_vport_context_update_addr_list(priv, MLX5_NVPRT_LIST_TYPE_MC);
 670        mlx5_modify_nic_vport_promisc(priv->mdev, 0,
 671                                      ea->allmulti_enabled,
 672                                      ea->promisc_enabled);
 673}
 674
 675static void mlx5e_apply_netdev_addr(struct mlx5e_priv *priv)
 676{
 677        struct mlx5e_l2_hash_node *hn;
 678        struct hlist_node *tmp;
 679        int i;
 680
 681        mlx5e_for_each_hash_node(hn, tmp, priv->fs.l2.netdev_uc, i)
 682                mlx5e_execute_l2_action(priv, hn);
 683
 684        mlx5e_for_each_hash_node(hn, tmp, priv->fs.l2.netdev_mc, i)
 685                mlx5e_execute_l2_action(priv, hn);
 686}
 687
 688static void mlx5e_handle_netdev_addr(struct mlx5e_priv *priv)
 689{
 690        struct mlx5e_l2_hash_node *hn;
 691        struct hlist_node *tmp;
 692        int i;
 693
 694        mlx5e_for_each_hash_node(hn, tmp, priv->fs.l2.netdev_uc, i)
 695                hn->action = MLX5E_ACTION_DEL;
 696        mlx5e_for_each_hash_node(hn, tmp, priv->fs.l2.netdev_mc, i)
 697                hn->action = MLX5E_ACTION_DEL;
 698
 699        if (!test_bit(MLX5E_STATE_DESTROYING, &priv->state))
 700                mlx5e_sync_netdev_addr(priv);
 701
 702        mlx5e_apply_netdev_addr(priv);
 703}
 704
 705#define MLX5E_PROMISC_GROUP0_SIZE BIT(0)
 706#define MLX5E_PROMISC_TABLE_SIZE MLX5E_PROMISC_GROUP0_SIZE
 707
 708static int mlx5e_add_promisc_rule(struct mlx5e_priv *priv)
 709{
 710        struct mlx5_flow_table *ft = priv->fs.promisc.ft.t;
 711        struct mlx5_flow_destination dest = {};
 712        struct mlx5_flow_handle **rule_p;
 713        MLX5_DECLARE_FLOW_ACT(flow_act);
 714        struct mlx5_flow_spec *spec;
 715        int err = 0;
 716
 717        spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
 718        if (!spec)
 719                return -ENOMEM;
 720        dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
 721        dest.ft = mlx5_get_ttc_flow_table(priv->fs.ttc);
 722
 723        rule_p = &priv->fs.promisc.rule;
 724        *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
 725        if (IS_ERR(*rule_p)) {
 726                err = PTR_ERR(*rule_p);
 727                *rule_p = NULL;
 728                netdev_err(priv->netdev, "%s: add promiscuous rule failed\n", __func__);
 729        }
 730        kvfree(spec);
 731        return err;
 732}
 733
 734static int mlx5e_create_promisc_table(struct mlx5e_priv *priv)
 735{
 736        struct mlx5e_flow_table *ft = &priv->fs.promisc.ft;
 737        struct mlx5_flow_table_attr ft_attr = {};
 738        int err;
 739
 740        ft_attr.max_fte = MLX5E_PROMISC_TABLE_SIZE;
 741        ft_attr.autogroup.max_num_groups = 1;
 742        ft_attr.level = MLX5E_PROMISC_FT_LEVEL;
 743        ft_attr.prio = MLX5E_NIC_PRIO;
 744
 745        ft->t = mlx5_create_auto_grouped_flow_table(priv->fs.ns, &ft_attr);
 746        if (IS_ERR(ft->t)) {
 747                err = PTR_ERR(ft->t);
 748                netdev_err(priv->netdev, "fail to create promisc table err=%d\n", err);
 749                return err;
 750        }
 751
 752        err = mlx5e_add_promisc_rule(priv);
 753        if (err)
 754                goto err_destroy_promisc_table;
 755
 756        return 0;
 757
 758err_destroy_promisc_table:
 759        mlx5_destroy_flow_table(ft->t);
 760        ft->t = NULL;
 761
 762        return err;
 763}
 764
 765static void mlx5e_del_promisc_rule(struct mlx5e_priv *priv)
 766{
 767        if (WARN(!priv->fs.promisc.rule, "Trying to remove non-existing promiscuous rule"))
 768                return;
 769        mlx5_del_flow_rules(priv->fs.promisc.rule);
 770        priv->fs.promisc.rule = NULL;
 771}
 772
 773static void mlx5e_destroy_promisc_table(struct mlx5e_priv *priv)
 774{
 775        if (WARN(!priv->fs.promisc.ft.t, "Trying to remove non-existing promiscuous table"))
 776                return;
 777        mlx5e_del_promisc_rule(priv);
 778        mlx5_destroy_flow_table(priv->fs.promisc.ft.t);
 779        priv->fs.promisc.ft.t = NULL;
 780}
 781
 782void mlx5e_set_rx_mode_work(struct work_struct *work)
 783{
 784        struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
 785                                               set_rx_mode_work);
 786
 787        struct mlx5e_l2_table *ea = &priv->fs.l2;
 788        struct net_device *ndev = priv->netdev;
 789
 790        bool rx_mode_enable   = !test_bit(MLX5E_STATE_DESTROYING, &priv->state);
 791        bool promisc_enabled   = rx_mode_enable && (ndev->flags & IFF_PROMISC);
 792        bool allmulti_enabled  = rx_mode_enable && (ndev->flags & IFF_ALLMULTI);
 793        bool broadcast_enabled = rx_mode_enable;
 794
 795        bool enable_promisc    = !ea->promisc_enabled   &&  promisc_enabled;
 796        bool disable_promisc   =  ea->promisc_enabled   && !promisc_enabled;
 797        bool enable_allmulti   = !ea->allmulti_enabled  &&  allmulti_enabled;
 798        bool disable_allmulti  =  ea->allmulti_enabled  && !allmulti_enabled;
 799        bool enable_broadcast  = !ea->broadcast_enabled &&  broadcast_enabled;
 800        bool disable_broadcast =  ea->broadcast_enabled && !broadcast_enabled;
 801        int err;
 802
 803        if (enable_promisc) {
 804                err = mlx5e_create_promisc_table(priv);
 805                if (err)
 806                        enable_promisc = false;
 807                if (!priv->channels.params.vlan_strip_disable && !err)
 808                        netdev_warn_once(ndev,
 809                                         "S-tagged traffic will be dropped while C-tag vlan stripping is enabled\n");
 810        }
 811        if (enable_allmulti)
 812                mlx5e_add_l2_flow_rule(priv, &ea->allmulti, MLX5E_ALLMULTI);
 813        if (enable_broadcast)
 814                mlx5e_add_l2_flow_rule(priv, &ea->broadcast, MLX5E_FULLMATCH);
 815
 816        mlx5e_handle_netdev_addr(priv);
 817
 818        if (disable_broadcast)
 819                mlx5e_del_l2_flow_rule(priv, &ea->broadcast);
 820        if (disable_allmulti)
 821                mlx5e_del_l2_flow_rule(priv, &ea->allmulti);
 822        if (disable_promisc)
 823                mlx5e_destroy_promisc_table(priv);
 824
 825        ea->promisc_enabled   = promisc_enabled;
 826        ea->allmulti_enabled  = allmulti_enabled;
 827        ea->broadcast_enabled = broadcast_enabled;
 828
 829        mlx5e_vport_context_update(priv);
 830}
 831
 832static void mlx5e_destroy_groups(struct mlx5e_flow_table *ft)
 833{
 834        int i;
 835
 836        for (i = ft->num_groups - 1; i >= 0; i--) {
 837                if (!IS_ERR_OR_NULL(ft->g[i]))
 838                        mlx5_destroy_flow_group(ft->g[i]);
 839                ft->g[i] = NULL;
 840        }
 841        ft->num_groups = 0;
 842}
 843
 844void mlx5e_init_l2_addr(struct mlx5e_priv *priv)
 845{
 846        ether_addr_copy(priv->fs.l2.broadcast.addr, priv->netdev->broadcast);
 847}
 848
 849void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft)
 850{
 851        mlx5e_destroy_groups(ft);
 852        kfree(ft->g);
 853        mlx5_destroy_flow_table(ft->t);
 854        ft->t = NULL;
 855}
 856
 857static void mlx5e_set_inner_ttc_params(struct mlx5e_priv *priv,
 858                                       struct ttc_params *ttc_params)
 859{
 860        struct mlx5_flow_table_attr *ft_attr = &ttc_params->ft_attr;
 861        int tt;
 862
 863        memset(ttc_params, 0, sizeof(*ttc_params));
 864        ttc_params->ns = mlx5_get_flow_namespace(priv->mdev,
 865                                                 MLX5_FLOW_NAMESPACE_KERNEL);
 866        ft_attr->level = MLX5E_INNER_TTC_FT_LEVEL;
 867        ft_attr->prio = MLX5E_NIC_PRIO;
 868
 869        for (tt = 0; tt < MLX5_NUM_TT; tt++) {
 870                ttc_params->dests[tt].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
 871                ttc_params->dests[tt].tir_num =
 872                        tt == MLX5_TT_ANY ?
 873                                mlx5e_rx_res_get_tirn_direct(priv->rx_res, 0) :
 874                                mlx5e_rx_res_get_tirn_rss_inner(priv->rx_res,
 875                                                                tt);
 876        }
 877}
 878
 879void mlx5e_set_ttc_params(struct mlx5e_priv *priv,
 880                          struct ttc_params *ttc_params, bool tunnel)
 881
 882{
 883        struct mlx5_flow_table_attr *ft_attr = &ttc_params->ft_attr;
 884        int tt;
 885
 886        memset(ttc_params, 0, sizeof(*ttc_params));
 887        ttc_params->ns = mlx5_get_flow_namespace(priv->mdev,
 888                                                 MLX5_FLOW_NAMESPACE_KERNEL);
 889        ft_attr->level = MLX5E_TTC_FT_LEVEL;
 890        ft_attr->prio = MLX5E_NIC_PRIO;
 891
 892        for (tt = 0; tt < MLX5_NUM_TT; tt++) {
 893                ttc_params->dests[tt].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
 894                ttc_params->dests[tt].tir_num =
 895                        tt == MLX5_TT_ANY ?
 896                                mlx5e_rx_res_get_tirn_direct(priv->rx_res, 0) :
 897                                mlx5e_rx_res_get_tirn_rss(priv->rx_res, tt);
 898        }
 899
 900        ttc_params->inner_ttc = tunnel;
 901        if (!tunnel || !mlx5_tunnel_inner_ft_supported(priv->mdev))
 902                return;
 903
 904        for (tt = 0; tt < MLX5_NUM_TUNNEL_TT; tt++) {
 905                ttc_params->tunnel_dests[tt].type =
 906                        MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
 907                ttc_params->tunnel_dests[tt].ft =
 908                        mlx5_get_ttc_flow_table(priv->fs.inner_ttc);
 909        }
 910}
 911
 912static void mlx5e_del_l2_flow_rule(struct mlx5e_priv *priv,
 913                                   struct mlx5e_l2_rule *ai)
 914{
 915        if (!IS_ERR_OR_NULL(ai->rule)) {
 916                mlx5_del_flow_rules(ai->rule);
 917                ai->rule = NULL;
 918        }
 919}
 920
 921static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
 922                                  struct mlx5e_l2_rule *ai, int type)
 923{
 924        struct mlx5_flow_table *ft = priv->fs.l2.ft.t;
 925        struct mlx5_flow_destination dest = {};
 926        MLX5_DECLARE_FLOW_ACT(flow_act);
 927        struct mlx5_flow_spec *spec;
 928        int err = 0;
 929        u8 *mc_dmac;
 930        u8 *mv_dmac;
 931
 932        spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
 933        if (!spec)
 934                return -ENOMEM;
 935
 936        mc_dmac = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
 937                               outer_headers.dmac_47_16);
 938        mv_dmac = MLX5_ADDR_OF(fte_match_param, spec->match_value,
 939                               outer_headers.dmac_47_16);
 940
 941        dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
 942        dest.ft = mlx5_get_ttc_flow_table(priv->fs.ttc);
 943
 944        switch (type) {
 945        case MLX5E_FULLMATCH:
 946                spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
 947                eth_broadcast_addr(mc_dmac);
 948                ether_addr_copy(mv_dmac, ai->addr);
 949                break;
 950
 951        case MLX5E_ALLMULTI:
 952                spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
 953                mc_dmac[0] = 0x01;
 954                mv_dmac[0] = 0x01;
 955                break;
 956        }
 957
 958        ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
 959        if (IS_ERR(ai->rule)) {
 960                netdev_err(priv->netdev, "%s: add l2 rule(mac:%pM) failed\n",
 961                           __func__, mv_dmac);
 962                err = PTR_ERR(ai->rule);
 963                ai->rule = NULL;
 964        }
 965
 966        kvfree(spec);
 967
 968        return err;
 969}
 970
 971#define MLX5E_NUM_L2_GROUPS        3
 972#define MLX5E_L2_GROUP1_SIZE       BIT(15)
 973#define MLX5E_L2_GROUP2_SIZE       BIT(0)
 974#define MLX5E_L2_GROUP_TRAP_SIZE   BIT(0) /* must be last */
 975#define MLX5E_L2_TABLE_SIZE        (MLX5E_L2_GROUP1_SIZE +\
 976                                    MLX5E_L2_GROUP2_SIZE +\
 977                                    MLX5E_L2_GROUP_TRAP_SIZE)
 978static int mlx5e_create_l2_table_groups(struct mlx5e_l2_table *l2_table)
 979{
 980        int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
 981        struct mlx5e_flow_table *ft = &l2_table->ft;
 982        int ix = 0;
 983        u8 *mc_dmac;
 984        u32 *in;
 985        int err;
 986        u8 *mc;
 987
 988        ft->g = kcalloc(MLX5E_NUM_L2_GROUPS, sizeof(*ft->g), GFP_KERNEL);
 989        if (!ft->g)
 990                return -ENOMEM;
 991        in = kvzalloc(inlen, GFP_KERNEL);
 992        if (!in) {
 993                kfree(ft->g);
 994                return -ENOMEM;
 995        }
 996
 997        mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
 998        mc_dmac = MLX5_ADDR_OF(fte_match_param, mc,
 999                               outer_headers.dmac_47_16);
1000        /* Flow Group for full match */
1001        eth_broadcast_addr(mc_dmac);
1002        MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1003        MLX5_SET_CFG(in, start_flow_index, ix);
1004        ix += MLX5E_L2_GROUP1_SIZE;
1005        MLX5_SET_CFG(in, end_flow_index, ix - 1);
1006        ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1007        if (IS_ERR(ft->g[ft->num_groups]))
1008                goto err_destroy_groups;
1009        ft->num_groups++;
1010
1011        /* Flow Group for allmulti */
1012        eth_zero_addr(mc_dmac);
1013        mc_dmac[0] = 0x01;
1014        MLX5_SET_CFG(in, start_flow_index, ix);
1015        ix += MLX5E_L2_GROUP2_SIZE;
1016        MLX5_SET_CFG(in, end_flow_index, ix - 1);
1017        ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1018        if (IS_ERR(ft->g[ft->num_groups]))
1019                goto err_destroy_groups;
1020        ft->num_groups++;
1021
1022        /* Flow Group for l2 traps */
1023        memset(in, 0, inlen);
1024        MLX5_SET_CFG(in, start_flow_index, ix);
1025        ix += MLX5E_L2_GROUP_TRAP_SIZE;
1026        MLX5_SET_CFG(in, end_flow_index, ix - 1);
1027        ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1028        if (IS_ERR(ft->g[ft->num_groups]))
1029                goto err_destroy_groups;
1030        ft->num_groups++;
1031
1032        kvfree(in);
1033        return 0;
1034
1035err_destroy_groups:
1036        err = PTR_ERR(ft->g[ft->num_groups]);
1037        ft->g[ft->num_groups] = NULL;
1038        mlx5e_destroy_groups(ft);
1039        kvfree(in);
1040        kfree(ft->g);
1041
1042        return err;
1043}
1044
1045static void mlx5e_destroy_l2_table(struct mlx5e_priv *priv)
1046{
1047        mlx5e_destroy_flow_table(&priv->fs.l2.ft);
1048}
1049
1050static int mlx5e_create_l2_table(struct mlx5e_priv *priv)
1051{
1052        struct mlx5e_l2_table *l2_table = &priv->fs.l2;
1053        struct mlx5e_flow_table *ft = &l2_table->ft;
1054        struct mlx5_flow_table_attr ft_attr = {};
1055        int err;
1056
1057        ft->num_groups = 0;
1058
1059        ft_attr.max_fte = MLX5E_L2_TABLE_SIZE;
1060        ft_attr.level = MLX5E_L2_FT_LEVEL;
1061        ft_attr.prio = MLX5E_NIC_PRIO;
1062
1063        ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr);
1064        if (IS_ERR(ft->t)) {
1065                err = PTR_ERR(ft->t);
1066                ft->t = NULL;
1067                return err;
1068        }
1069
1070        err = mlx5e_create_l2_table_groups(l2_table);
1071        if (err)
1072                goto err_destroy_flow_table;
1073
1074        return 0;
1075
1076err_destroy_flow_table:
1077        mlx5_destroy_flow_table(ft->t);
1078        ft->t = NULL;
1079
1080        return err;
1081}
1082
1083#define MLX5E_NUM_VLAN_GROUPS   5
1084#define MLX5E_VLAN_GROUP0_SIZE  BIT(12)
1085#define MLX5E_VLAN_GROUP1_SIZE  BIT(12)
1086#define MLX5E_VLAN_GROUP2_SIZE  BIT(1)
1087#define MLX5E_VLAN_GROUP3_SIZE  BIT(0)
1088#define MLX5E_VLAN_GROUP_TRAP_SIZE BIT(0) /* must be last */
1089#define MLX5E_VLAN_TABLE_SIZE   (MLX5E_VLAN_GROUP0_SIZE +\
1090                                 MLX5E_VLAN_GROUP1_SIZE +\
1091                                 MLX5E_VLAN_GROUP2_SIZE +\
1092                                 MLX5E_VLAN_GROUP3_SIZE +\
1093                                 MLX5E_VLAN_GROUP_TRAP_SIZE)
1094
1095static int __mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft, u32 *in,
1096                                            int inlen)
1097{
1098        int err;
1099        int ix = 0;
1100        u8 *mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
1101
1102        memset(in, 0, inlen);
1103        MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1104        MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
1105        MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.first_vid);
1106        MLX5_SET_CFG(in, start_flow_index, ix);
1107        ix += MLX5E_VLAN_GROUP0_SIZE;
1108        MLX5_SET_CFG(in, end_flow_index, ix - 1);
1109        ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1110        if (IS_ERR(ft->g[ft->num_groups]))
1111                goto err_destroy_groups;
1112        ft->num_groups++;
1113
1114        memset(in, 0, inlen);
1115        MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1116        MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag);
1117        MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.first_vid);
1118        MLX5_SET_CFG(in, start_flow_index, ix);
1119        ix += MLX5E_VLAN_GROUP1_SIZE;
1120        MLX5_SET_CFG(in, end_flow_index, ix - 1);
1121        ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1122        if (IS_ERR(ft->g[ft->num_groups]))
1123                goto err_destroy_groups;
1124        ft->num_groups++;
1125
1126        memset(in, 0, inlen);
1127        MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1128        MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.cvlan_tag);
1129        MLX5_SET_CFG(in, start_flow_index, ix);
1130        ix += MLX5E_VLAN_GROUP2_SIZE;
1131        MLX5_SET_CFG(in, end_flow_index, ix - 1);
1132        ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1133        if (IS_ERR(ft->g[ft->num_groups]))
1134                goto err_destroy_groups;
1135        ft->num_groups++;
1136
1137        memset(in, 0, inlen);
1138        MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1139        MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.svlan_tag);
1140        MLX5_SET_CFG(in, start_flow_index, ix);
1141        ix += MLX5E_VLAN_GROUP3_SIZE;
1142        MLX5_SET_CFG(in, end_flow_index, ix - 1);
1143        ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1144        if (IS_ERR(ft->g[ft->num_groups]))
1145                goto err_destroy_groups;
1146        ft->num_groups++;
1147
1148        memset(in, 0, inlen);
1149        MLX5_SET_CFG(in, start_flow_index, ix);
1150        ix += MLX5E_VLAN_GROUP_TRAP_SIZE;
1151        MLX5_SET_CFG(in, end_flow_index, ix - 1);
1152        ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1153        if (IS_ERR(ft->g[ft->num_groups]))
1154                goto err_destroy_groups;
1155        ft->num_groups++;
1156
1157        return 0;
1158
1159err_destroy_groups:
1160        err = PTR_ERR(ft->g[ft->num_groups]);
1161        ft->g[ft->num_groups] = NULL;
1162        mlx5e_destroy_groups(ft);
1163
1164        return err;
1165}
1166
1167static int mlx5e_create_vlan_table_groups(struct mlx5e_flow_table *ft)
1168{
1169        u32 *in;
1170        int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1171        int err;
1172
1173        in = kvzalloc(inlen, GFP_KERNEL);
1174        if (!in)
1175                return -ENOMEM;
1176
1177        err = __mlx5e_create_vlan_table_groups(ft, in, inlen);
1178
1179        kvfree(in);
1180        return err;
1181}
1182
1183static int mlx5e_create_vlan_table(struct mlx5e_priv *priv)
1184{
1185        struct mlx5_flow_table_attr ft_attr = {};
1186        struct mlx5e_flow_table *ft;
1187        int err;
1188
1189        ft = &priv->fs.vlan->ft;
1190        ft->num_groups = 0;
1191
1192        ft_attr.max_fte = MLX5E_VLAN_TABLE_SIZE;
1193        ft_attr.level = MLX5E_VLAN_FT_LEVEL;
1194        ft_attr.prio = MLX5E_NIC_PRIO;
1195
1196        ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr);
1197        if (IS_ERR(ft->t))
1198                return PTR_ERR(ft->t);
1199
1200        ft->g = kcalloc(MLX5E_NUM_VLAN_GROUPS, sizeof(*ft->g), GFP_KERNEL);
1201        if (!ft->g) {
1202                err = -ENOMEM;
1203                goto err_destroy_vlan_table;
1204        }
1205
1206        err = mlx5e_create_vlan_table_groups(ft);
1207        if (err)
1208                goto err_free_g;
1209
1210        mlx5e_add_vlan_rules(priv);
1211
1212        return 0;
1213
1214err_free_g:
1215        kfree(ft->g);
1216err_destroy_vlan_table:
1217        mlx5_destroy_flow_table(ft->t);
1218
1219        return err;
1220}
1221
1222static void mlx5e_destroy_vlan_table(struct mlx5e_priv *priv)
1223{
1224        mlx5e_del_vlan_rules(priv);
1225        mlx5e_destroy_flow_table(&priv->fs.vlan->ft);
1226}
1227
1228static void mlx5e_destroy_inner_ttc_table(struct mlx5e_priv *priv)
1229{
1230        if (!mlx5_tunnel_inner_ft_supported(priv->mdev))
1231                return;
1232        mlx5_destroy_ttc_table(priv->fs.inner_ttc);
1233}
1234
1235void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv)
1236{
1237        mlx5_destroy_ttc_table(priv->fs.ttc);
1238}
1239
1240static int mlx5e_create_inner_ttc_table(struct mlx5e_priv *priv)
1241{
1242        struct ttc_params ttc_params = {};
1243
1244        if (!mlx5_tunnel_inner_ft_supported(priv->mdev))
1245                return 0;
1246
1247        mlx5e_set_inner_ttc_params(priv, &ttc_params);
1248        priv->fs.inner_ttc = mlx5_create_inner_ttc_table(priv->mdev,
1249                                                         &ttc_params);
1250        if (IS_ERR(priv->fs.inner_ttc))
1251                return PTR_ERR(priv->fs.inner_ttc);
1252        return 0;
1253}
1254
1255int mlx5e_create_ttc_table(struct mlx5e_priv *priv)
1256{
1257        struct ttc_params ttc_params = {};
1258
1259        mlx5e_set_ttc_params(priv, &ttc_params, true);
1260        priv->fs.ttc = mlx5_create_ttc_table(priv->mdev, &ttc_params);
1261        if (IS_ERR(priv->fs.ttc))
1262                return PTR_ERR(priv->fs.ttc);
1263        return 0;
1264}
1265
1266int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
1267{
1268        int err;
1269
1270        priv->fs.ns = mlx5_get_flow_namespace(priv->mdev,
1271                                               MLX5_FLOW_NAMESPACE_KERNEL);
1272
1273        if (!priv->fs.ns)
1274                return -EOPNOTSUPP;
1275
1276        err = mlx5e_arfs_create_tables(priv);
1277        if (err) {
1278                netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n",
1279                           err);
1280                priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
1281        }
1282
1283        err = mlx5e_create_inner_ttc_table(priv);
1284        if (err) {
1285                netdev_err(priv->netdev,
1286                           "Failed to create inner ttc table, err=%d\n",
1287                           err);
1288                goto err_destroy_arfs_tables;
1289        }
1290
1291        err = mlx5e_create_ttc_table(priv);
1292        if (err) {
1293                netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
1294                           err);
1295                goto err_destroy_inner_ttc_table;
1296        }
1297
1298        err = mlx5e_create_l2_table(priv);
1299        if (err) {
1300                netdev_err(priv->netdev, "Failed to create l2 table, err=%d\n",
1301                           err);
1302                goto err_destroy_ttc_table;
1303        }
1304
1305        err = mlx5e_create_vlan_table(priv);
1306        if (err) {
1307                netdev_err(priv->netdev, "Failed to create vlan table, err=%d\n",
1308                           err);
1309                goto err_destroy_l2_table;
1310        }
1311
1312        err = mlx5e_ptp_alloc_rx_fs(priv);
1313        if (err)
1314                goto err_destory_vlan_table;
1315
1316        mlx5e_ethtool_init_steering(priv);
1317
1318        return 0;
1319
1320err_destory_vlan_table:
1321        mlx5e_destroy_vlan_table(priv);
1322err_destroy_l2_table:
1323        mlx5e_destroy_l2_table(priv);
1324err_destroy_ttc_table:
1325        mlx5e_destroy_ttc_table(priv);
1326err_destroy_inner_ttc_table:
1327        mlx5e_destroy_inner_ttc_table(priv);
1328err_destroy_arfs_tables:
1329        mlx5e_arfs_destroy_tables(priv);
1330
1331        return err;
1332}
1333
1334void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv)
1335{
1336        mlx5e_ptp_free_rx_fs(priv);
1337        mlx5e_destroy_vlan_table(priv);
1338        mlx5e_destroy_l2_table(priv);
1339        mlx5e_destroy_ttc_table(priv);
1340        mlx5e_destroy_inner_ttc_table(priv);
1341        mlx5e_arfs_destroy_tables(priv);
1342        mlx5e_ethtool_cleanup_steering(priv);
1343}
1344
1345int mlx5e_fs_init(struct mlx5e_priv *priv)
1346{
1347        priv->fs.vlan = kvzalloc(sizeof(*priv->fs.vlan), GFP_KERNEL);
1348        if (!priv->fs.vlan)
1349                return -ENOMEM;
1350        return 0;
1351}
1352
1353void mlx5e_fs_cleanup(struct mlx5e_priv *priv)
1354{
1355        kvfree(priv->fs.vlan);
1356        priv->fs.vlan = NULL;
1357}
1358