]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge tag 'rxrpc-rewrite-20160824-2' of git://git.kernel.org/pub/scm/linux/kernel...
authorDavid S. Miller <davem@davemloft.net>
Wed, 24 Aug 2016 16:43:44 +0000 (09:43 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 24 Aug 2016 16:43:44 +0000 (09:43 -0700)
David Howells says:

====================
rxrpc: Add better client conn management strategy

These two patches add a better client connection management strategy.  They
need to be applied on top of the just-posted fixes.

 (1) Duplicate the connection list and separate out procfs iteration from
     garbage collection.  This is necessary for the next patch as with that
     client connections no longer appear on a single list and may not
     appear on a list at all - and really don't want to be exposed to the
     old garbage collector.

     (Note that client conns aren't left dangling, they're also in a tree
     rooted in the local endpoint so that they can be found by a user
     wanting to make a new client call.  Service conns do not appear in
     this tree.)

 (2) Implement a better lifetime management and garbage collection strategy
     for client connections.

     In this, a client connection can be in one of five cache states
     (inactive, waiting, active, culled and idle).  Limits are set on the
     number of client conns that may be active at any one time and makes
     users wait if they want to start a new call when there isn't capacity
     available.

     To make capacity available, active and idle connections can be culled,
     after a short delay (to allow for retransmission).  The delay is
     reduced if the capacity exceeds a tunable threshold.

     If there is spare capacity, client conns are permitted to hang around
     a fair bit longer (tunable) so as to allow reuse of negotiated
     security contexts.

     After this patch, the client conn strategy is separate from that of
     service conns (which continues to use the old code for the moment).

     This difference in strategy is because the client side retains control
     over when it allows a connection to become active, whereas the service
     side has no control over when it sees a new connection or a new call
     on an old connection.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
31 files changed:
drivers/infiniband/hw/mlx5/main.c
drivers/net/ethernet/mellanox/mlx5/core/Makefile
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/lag.c [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlx5/core/port.c
drivers/net/ethernet/mellanox/mlx5/core/sriov.c
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
include/linux/mlx5/device.h
include/linux/mlx5/driver.h
include/linux/mlx5/fs.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mlx5/port.h
include/net/sock.h
net/core/sock.c
net/ipv4/udp.c
net/ipv4/udplite.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipv6/udp_impl.h
net/ipv6/udplite.c

index 6fb77d791045afd68609dc60772c580b66fcf5d7..f02a975320bd5b4efef25358c58931b4685b5077 100644 (file)
@@ -748,8 +748,7 @@ static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port,
                                     &props->active_width);
        if (err)
                goto out;
-       err = mlx5_query_port_proto_oper(mdev, &props->active_speed, MLX5_PTYS_IB,
-                                        port);
+       err = mlx5_query_port_ib_proto_oper(mdev, &props->active_speed, port);
        if (err)
                goto out;
 
index 05cc1effc13cb187730f9d131c7c6f2c88197fb3..dad326ccd4dd9868240db572c0601119aafa36b1 100644 (file)
@@ -3,7 +3,7 @@ obj-$(CONFIG_MLX5_CORE)         += mlx5_core.o
 mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
                health.o mcg.o cq.o srq.o alloc.o qp.o port.o mr.o pd.o \
                mad.o transobj.o vport.o sriov.o fs_cmd.o fs_core.o \
-               fs_counters.o rl.o
+               fs_counters.o rl.o lag.o
 
 mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \
                en_main.o en_common.o en_fs.o en_ethtool.o en_tx.o \
index e9f6afb8c19bc94b5a3e4cdaff1ea3c162fcf896..bb89f046fa275ff506903bfd774eb5acd6a42241 100644 (file)
@@ -285,6 +285,8 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
        case MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN:
        case MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT:
        case MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY:
+       case MLX5_CMD_OP_DESTROY_LAG:
+       case MLX5_CMD_OP_DESTROY_VPORT_LAG:
        case MLX5_CMD_OP_DESTROY_TIR:
        case MLX5_CMD_OP_DESTROY_SQ:
        case MLX5_CMD_OP_DESTROY_RQ:
@@ -376,6 +378,10 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
        case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
        case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
        case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
+       case MLX5_CMD_OP_CREATE_LAG:
+       case MLX5_CMD_OP_MODIFY_LAG:
+       case MLX5_CMD_OP_QUERY_LAG:
+       case MLX5_CMD_OP_CREATE_VPORT_LAG:
        case MLX5_CMD_OP_CREATE_TIR:
        case MLX5_CMD_OP_MODIFY_TIR:
        case MLX5_CMD_OP_QUERY_TIR:
@@ -514,6 +520,12 @@ const char *mlx5_command_str(int command)
        MLX5_COMMAND_STR_CASE(DELETE_L2_TABLE_ENTRY);
        MLX5_COMMAND_STR_CASE(SET_WOL_ROL);
        MLX5_COMMAND_STR_CASE(QUERY_WOL_ROL);
+       MLX5_COMMAND_STR_CASE(CREATE_LAG);
+       MLX5_COMMAND_STR_CASE(MODIFY_LAG);
+       MLX5_COMMAND_STR_CASE(QUERY_LAG);
+       MLX5_COMMAND_STR_CASE(DESTROY_LAG);
+       MLX5_COMMAND_STR_CASE(CREATE_VPORT_LAG);
+       MLX5_COMMAND_STR_CASE(DESTROY_VPORT_LAG);
        MLX5_COMMAND_STR_CASE(CREATE_TIR);
        MLX5_COMMAND_STR_CASE(MODIFY_TIR);
        MLX5_COMMAND_STR_CASE(DESTROY_TIR);
index 1b495efa7490d2d1edb9ccc3f93de4f74ad52d7f..61902b147339d4bf18d571278fd23a2ee0c8e4d1 100644 (file)
@@ -651,40 +651,6 @@ struct mlx5e_priv {
        void                      *ppriv;
 };
 
-enum mlx5e_link_mode {
-       MLX5E_1000BASE_CX_SGMII  = 0,
-       MLX5E_1000BASE_KX        = 1,
-       MLX5E_10GBASE_CX4        = 2,
-       MLX5E_10GBASE_KX4        = 3,
-       MLX5E_10GBASE_KR         = 4,
-       MLX5E_20GBASE_KR2        = 5,
-       MLX5E_40GBASE_CR4        = 6,
-       MLX5E_40GBASE_KR4        = 7,
-       MLX5E_56GBASE_R4         = 8,
-       MLX5E_10GBASE_CR         = 12,
-       MLX5E_10GBASE_SR         = 13,
-       MLX5E_10GBASE_ER         = 14,
-       MLX5E_40GBASE_SR4        = 15,
-       MLX5E_40GBASE_LR4        = 16,
-       MLX5E_50GBASE_SR2        = 18,
-       MLX5E_100GBASE_CR4       = 20,
-       MLX5E_100GBASE_SR4       = 21,
-       MLX5E_100GBASE_KR4       = 22,
-       MLX5E_100GBASE_LR4       = 23,
-       MLX5E_100BASE_TX         = 24,
-       MLX5E_1000BASE_T         = 25,
-       MLX5E_10GBASE_T          = 26,
-       MLX5E_25GBASE_CR         = 27,
-       MLX5E_25GBASE_KR         = 28,
-       MLX5E_25GBASE_SR         = 29,
-       MLX5E_50GBASE_CR2        = 30,
-       MLX5E_50GBASE_KR2        = 31,
-       MLX5E_LINK_MODES_NUMBER,
-};
-
-#define MLX5E_PROT_MASK(link_mode) (1 << link_mode)
-
-
 void mlx5e_build_ptys2ethtool_map(void);
 
 void mlx5e_send_nop(struct mlx5e_sq *sq, bool notify_hw);
index 10fa12aa063f49920c7f7118404cc328e116b818..fa404142320d84ef0a53109b0b4694df8d035d56 100644 (file)
@@ -489,7 +489,8 @@ static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd)
        rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
 
        MLX5_SET(modify_rq_in, in, rq_state, MLX5_RQC_STATE_RDY);
-       MLX5_SET64(modify_rq_in, in, modify_bitmask, MLX5_RQ_BITMASK_VSD);
+       MLX5_SET64(modify_rq_in, in, modify_bitmask,
+                  MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_VSD);
        MLX5_SET(rqc, rqc, vsd, vsd);
        MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RDY);
 
@@ -2024,6 +2025,10 @@ static int mlx5e_create_tis(struct mlx5e_priv *priv, int tc)
 
        MLX5_SET(tisc, tisc, prio, tc << 1);
        MLX5_SET(tisc, tisc, transport_domain, mdev->mlx5e_res.td.tdn);
+
+       if (mlx5_lag_is_lacp_owner(mdev))
+               MLX5_SET(tisc, tisc, strict_lag_tx_port_affinity, 1);
+
        return mlx5_core_create_tis(mdev, in, sizeof(in), &priv->tisn[tc]);
 }
 
@@ -3368,6 +3373,8 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
        struct mlx5_eswitch *esw = mdev->priv.eswitch;
        struct mlx5_eswitch_rep rep;
 
+       mlx5_lag_add(mdev, netdev);
+
        if (mlx5e_vxlan_allowed(mdev)) {
                rtnl_lock();
                udp_tunnel_get_rx_info(netdev);
@@ -3390,6 +3397,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
 {
        queue_work(priv->wq, &priv->set_rx_mode_work);
        mlx5e_disable_async_events(priv);
+       mlx5_lag_remove(priv->mdev);
 }
 
 static const struct mlx5e_profile mlx5e_nic_profile = {
index 7aaefa9aaf1cff0d450f5efebe0507cc305e6bdf..7a0415e6d33950d8043118e87b741ae2c3546653 100644 (file)
@@ -58,6 +58,7 @@ int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
 
 int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
                               u16 vport,
+                              enum fs_flow_table_op_mod op_mod,
                               enum fs_flow_table_type type, unsigned int level,
                               unsigned int log_size, struct mlx5_flow_table
                               *next_ft, unsigned int *table_id)
@@ -69,10 +70,6 @@ int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
        MLX5_SET(create_flow_table_in, in, opcode,
                 MLX5_CMD_OP_CREATE_FLOW_TABLE);
 
-       if (next_ft) {
-               MLX5_SET(create_flow_table_in, in, table_miss_mode, 1);
-               MLX5_SET(create_flow_table_in, in, table_miss_id, next_ft->id);
-       }
        MLX5_SET(create_flow_table_in, in, table_type, type);
        MLX5_SET(create_flow_table_in, in, level, level);
        MLX5_SET(create_flow_table_in, in, log_size, log_size);
@@ -81,6 +78,22 @@ int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
                MLX5_SET(create_flow_table_in, in, other_vport, 1);
        }
 
+       switch (op_mod) {
+       case FS_FT_OP_MOD_NORMAL:
+               if (next_ft) {
+                       MLX5_SET(create_flow_table_in, in, table_miss_mode, 1);
+                       MLX5_SET(create_flow_table_in, in, table_miss_id, next_ft->id);
+               }
+               break;
+
+       case FS_FT_OP_MOD_LAG_DEMUX:
+               MLX5_SET(create_flow_table_in, in, op_mod, 0x1);
+               if (next_ft)
+                       MLX5_SET(create_flow_table_in, in, lag_master_next_table_id,
+                                next_ft->id);
+               break;
+       }
+
        err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
        if (!err)
                *table_id = MLX5_GET(create_flow_table_out, out,
@@ -117,17 +130,32 @@ int mlx5_cmd_modify_flow_table(struct mlx5_core_dev *dev,
                 MLX5_CMD_OP_MODIFY_FLOW_TABLE);
        MLX5_SET(modify_flow_table_in, in, table_type, ft->type);
        MLX5_SET(modify_flow_table_in, in, table_id, ft->id);
-       if (ft->vport) {
-               MLX5_SET(modify_flow_table_in, in, vport_number, ft->vport);
-               MLX5_SET(modify_flow_table_in, in, other_vport, 1);
-       }
-       MLX5_SET(modify_flow_table_in, in, modify_field_select,
-                MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID);
-       if (next_ft) {
-               MLX5_SET(modify_flow_table_in, in, table_miss_mode, 1);
-               MLX5_SET(modify_flow_table_in, in, table_miss_id, next_ft->id);
+
+       if (ft->op_mod == FS_FT_OP_MOD_LAG_DEMUX) {
+               MLX5_SET(modify_flow_table_in, in, modify_field_select,
+                        MLX5_MODIFY_FLOW_TABLE_LAG_NEXT_TABLE_ID);
+               if (next_ft) {
+                       MLX5_SET(modify_flow_table_in, in,
+                                lag_master_next_table_id, next_ft->id);
+               } else {
+                       MLX5_SET(modify_flow_table_in, in,
+                                lag_master_next_table_id, 0);
+               }
        } else {
-               MLX5_SET(modify_flow_table_in, in, table_miss_mode, 0);
+               if (ft->vport) {
+                       MLX5_SET(modify_flow_table_in, in, vport_number,
+                                ft->vport);
+                       MLX5_SET(modify_flow_table_in, in, other_vport, 1);
+               }
+               MLX5_SET(modify_flow_table_in, in, modify_field_select,
+                        MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID);
+               if (next_ft) {
+                       MLX5_SET(modify_flow_table_in, in, table_miss_mode, 1);
+                       MLX5_SET(modify_flow_table_in, in, table_miss_id,
+                                next_ft->id);
+               } else {
+                       MLX5_SET(modify_flow_table_in, in, table_miss_mode, 0);
+               }
        }
 
        return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
index ac52fdfb5096f06c6448657fe218b3416cd2fec7..c5bc4686c832414c9f8307ec0745df8de36d78fa 100644 (file)
@@ -35,6 +35,7 @@
 
 int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
                               u16 vport,
+                              enum fs_flow_table_op_mod op_mod,
                               enum fs_flow_table_type type, unsigned int level,
                               unsigned int log_size, struct mlx5_flow_table
                               *next_ft, unsigned int *table_id);
index 243efc5a8bd1753c942b2eee7e225038a2952d0b..f5571a5a57c5c29f36e34de27655ae8300a06152 100644 (file)
 #define OFFLOADS_NUM_PRIOS 1
 #define OFFLOADS_MIN_LEVEL (ANCHOR_MIN_LEVEL + 1)
 
+#define LAG_PRIO_NUM_LEVELS 1
+#define LAG_NUM_PRIOS 1
+#define LAG_MIN_LEVEL (OFFLOADS_MIN_LEVEL + 1)
+
 struct node_caps {
        size_t  arr_sz;
        long    *caps;
@@ -111,12 +115,16 @@ static struct init_tree_node {
        int num_levels;
 } root_fs = {
        .type = FS_TYPE_NAMESPACE,
-       .ar_size = 6,
+       .ar_size = 7,
        .children = (struct init_tree_node[]) {
                ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0,
                         FS_CHAINING_CAPS,
                         ADD_NS(ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_PRIOS,
                                                  BY_PASS_PRIO_NUM_LEVELS))),
+               ADD_PRIO(0, LAG_MIN_LEVEL, 0,
+                        FS_CHAINING_CAPS,
+                        ADD_NS(ADD_MULTIPLE_PRIO(LAG_NUM_PRIOS,
+                                                 LAG_PRIO_NUM_LEVELS))),
                ADD_PRIO(0, OFFLOADS_MIN_LEVEL, 0, {},
                         ADD_NS(ADD_MULTIPLE_PRIO(OFFLOADS_NUM_PRIOS, OFFLOADS_MAX_FT))),
                ADD_PRIO(0, ETHTOOL_MIN_LEVEL, 0,
@@ -477,7 +485,8 @@ static struct mlx5_flow_group *alloc_flow_group(u32 *create_fg_in)
 }
 
 static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_fte,
-                                               enum fs_flow_table_type table_type)
+                                               enum fs_flow_table_type table_type,
+                                               enum fs_flow_table_op_mod op_mod)
 {
        struct mlx5_flow_table *ft;
 
@@ -487,6 +496,7 @@ static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_ft
 
        ft->level = level;
        ft->node.type = FS_TYPE_FLOW_TABLE;
+       ft->op_mod = op_mod;
        ft->type = table_type;
        ft->vport = vport;
        ft->max_fte = max_fte;
@@ -724,6 +734,7 @@ static void list_add_flow_table(struct mlx5_flow_table *ft,
 }
 
 static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
+                                                       enum fs_flow_table_op_mod op_mod,
                                                        u16 vport, int prio,
                                                        int max_fte, u32 level)
 {
@@ -756,18 +767,19 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
        level += fs_prio->start_level;
        ft = alloc_flow_table(level,
                              vport,
-                             roundup_pow_of_two(max_fte),
-                             root->table_type);
+                             max_fte ? roundup_pow_of_two(max_fte) : 0,
+                             root->table_type,
+                             op_mod);
        if (!ft) {
                err = -ENOMEM;
                goto unlock_root;
        }
 
        tree_init_node(&ft->node, 1, del_flow_table);
-       log_table_sz = ilog2(ft->max_fte);
+       log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
        next_ft = find_next_chained_ft(fs_prio);
-       err = mlx5_cmd_create_flow_table(root->dev, ft->vport, ft->type, ft->level,
-                                        log_table_sz, next_ft, &ft->id);
+       err = mlx5_cmd_create_flow_table(root->dev, ft->vport, ft->op_mod, ft->type,
+                                        ft->level, log_table_sz, next_ft, &ft->id);
        if (err)
                goto free_ft;
 
@@ -794,15 +806,26 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
                                               int prio, int max_fte,
                                               u32 level)
 {
-       return __mlx5_create_flow_table(ns, 0, prio, max_fte, level);
+       return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_NORMAL, 0, prio,
+                                       max_fte, level);
 }
 
 struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns,
                                                     int prio, int max_fte,
                                                     u32 level, u16 vport)
 {
-       return __mlx5_create_flow_table(ns, vport, prio, max_fte, level);
+       return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_NORMAL, vport, prio,
+                                       max_fte, level);
+}
+
+struct mlx5_flow_table *mlx5_create_lag_demux_flow_table(
+                                              struct mlx5_flow_namespace *ns,
+                                              int prio, u32 level)
+{
+       return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_LAG_DEMUX, 0, prio, 0,
+                                       level);
 }
+EXPORT_SYMBOL(mlx5_create_lag_demux_flow_table);
 
 struct mlx5_flow_table *mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns,
                                                            int prio,
@@ -1381,6 +1404,7 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
 
        switch (type) {
        case MLX5_FLOW_NAMESPACE_BYPASS:
+       case MLX5_FLOW_NAMESPACE_LAG:
        case MLX5_FLOW_NAMESPACE_OFFLOADS:
        case MLX5_FLOW_NAMESPACE_ETHTOOL:
        case MLX5_FLOW_NAMESPACE_KERNEL:
@@ -1403,6 +1427,16 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
                        return &steering->esw_ingress_root_ns->ns;
                else
                        return NULL;
+       case MLX5_FLOW_NAMESPACE_SNIFFER_RX:
+               if (steering->sniffer_rx_root_ns)
+                       return &steering->sniffer_rx_root_ns->ns;
+               else
+                       return NULL;
+       case MLX5_FLOW_NAMESPACE_SNIFFER_TX:
+               if (steering->sniffer_tx_root_ns)
+                       return &steering->sniffer_tx_root_ns->ns;
+               else
+                       return NULL;
        default:
                return NULL;
        }
@@ -1702,10 +1736,46 @@ void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
        cleanup_root_ns(steering->esw_egress_root_ns);
        cleanup_root_ns(steering->esw_ingress_root_ns);
        cleanup_root_ns(steering->fdb_root_ns);
+       cleanup_root_ns(steering->sniffer_rx_root_ns);
+       cleanup_root_ns(steering->sniffer_tx_root_ns);
        mlx5_cleanup_fc_stats(dev);
        kfree(steering);
 }
 
+static int init_sniffer_tx_root_ns(struct mlx5_flow_steering *steering)
+{
+       struct fs_prio *prio;
+
+       steering->sniffer_tx_root_ns = create_root_ns(steering, FS_FT_SNIFFER_TX);
+       if (!steering->sniffer_tx_root_ns)
+               return -ENOMEM;
+
+       /* Create single prio */
+       prio = fs_create_prio(&steering->sniffer_tx_root_ns->ns, 0, 1);
+       if (IS_ERR(prio)) {
+               cleanup_root_ns(steering->sniffer_tx_root_ns);
+               return PTR_ERR(prio);
+       }
+       return 0;
+}
+
+static int init_sniffer_rx_root_ns(struct mlx5_flow_steering *steering)
+{
+       struct fs_prio *prio;
+
+       steering->sniffer_rx_root_ns = create_root_ns(steering, FS_FT_SNIFFER_RX);
+       if (!steering->sniffer_rx_root_ns)
+               return -ENOMEM;
+
+       /* Create single prio */
+       prio = fs_create_prio(&steering->sniffer_rx_root_ns->ns, 0, 1);
+       if (IS_ERR(prio)) {
+               cleanup_root_ns(steering->sniffer_rx_root_ns);
+               return PTR_ERR(prio);
+       }
+       return 0;
+}
+
 static int init_fdb_root_ns(struct mlx5_flow_steering *steering)
 {
        struct fs_prio *prio;
@@ -1802,6 +1872,18 @@ int mlx5_init_fs(struct mlx5_core_dev *dev)
                }
        }
 
+       if (MLX5_CAP_FLOWTABLE_SNIFFER_RX(dev, ft_support)) {
+               err = init_sniffer_rx_root_ns(steering);
+               if (err)
+                       goto err;
+       }
+
+       if (MLX5_CAP_FLOWTABLE_SNIFFER_TX(dev, ft_support)) {
+               err = init_sniffer_tx_root_ns(steering);
+               if (err)
+                       goto err;
+       }
+
        return 0;
 err:
        mlx5_cleanup_fs(dev);
index 9cffb6aeb4e9b1853a35827872b05251257a2f19..71ff03bceabb81b3b159f4e6b5f90b7a6df7ad9e 100644 (file)
@@ -49,6 +49,13 @@ enum fs_flow_table_type {
        FS_FT_ESW_EGRESS_ACL  = 0x2,
        FS_FT_ESW_INGRESS_ACL = 0x3,
        FS_FT_FDB             = 0X4,
+       FS_FT_SNIFFER_RX        = 0X5,
+       FS_FT_SNIFFER_TX        = 0X6,
+};
+
+enum fs_flow_table_op_mod {
+       FS_FT_OP_MOD_NORMAL,
+       FS_FT_OP_MOD_LAG_DEMUX,
 };
 
 enum fs_fte_status {
@@ -61,6 +68,8 @@ struct mlx5_flow_steering {
        struct mlx5_flow_root_namespace *fdb_root_ns;
        struct mlx5_flow_root_namespace *esw_egress_root_ns;
        struct mlx5_flow_root_namespace *esw_ingress_root_ns;
+       struct mlx5_flow_root_namespace *sniffer_tx_root_ns;
+       struct mlx5_flow_root_namespace *sniffer_rx_root_ns;
 };
 
 struct fs_node {
@@ -93,6 +102,7 @@ struct mlx5_flow_table {
        unsigned int                    max_fte;
        unsigned int                    level;
        enum fs_flow_table_type         type;
+       enum fs_flow_table_op_mod       op_mod;
        struct {
                bool                    active;
                unsigned int            required_groups;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c
new file mode 100644 (file)
index 0000000..92c3e0d
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/mlx5/driver.h>
+#include <linux/mlx5/vport.h>
+#include "mlx5_core.h"
+
+enum {
+       MLX5_LAG_FLAG_BONDED = 1 << 0,
+};
+
+struct lag_func {
+       struct mlx5_core_dev *dev;
+       struct net_device    *netdev;
+};
+
+/* Used for collection of netdev event info. */
+struct lag_tracker {
+       enum   netdev_lag_tx_type           tx_type;
+       struct netdev_lag_lower_state_info  netdev_state[MLX5_MAX_PORTS];
+       bool is_bonded;
+};
+
+/* LAG data of a ConnectX card.
+ * It serves both its phys functions.
+ */
+struct mlx5_lag {
+       u8                        flags;
+       u8                        v2p_map[MLX5_MAX_PORTS];
+       struct lag_func           pf[MLX5_MAX_PORTS];
+       struct lag_tracker        tracker;
+       struct delayed_work       bond_work;
+       struct notifier_block     nb;
+};
+
+/* General purpose, use for short periods of time.
+ * Beware of lock dependencies (preferably, no locks should be acquired
+ * under it).
+ */
+static DEFINE_MUTEX(lag_mutex);
+
+static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 remap_port1,
+                              u8 remap_port2)
+{
+       u32   in[MLX5_ST_SZ_DW(create_lag_in)]   = {0};
+       u32   out[MLX5_ST_SZ_DW(create_lag_out)] = {0};
+       void *lag_ctx = MLX5_ADDR_OF(create_lag_in, in, ctx);
+
+       MLX5_SET(create_lag_in, in, opcode, MLX5_CMD_OP_CREATE_LAG);
+
+       MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, remap_port1);
+       MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, remap_port2);
+
+       return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
+static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, u8 remap_port1,
+                              u8 remap_port2)
+{
+       u32   in[MLX5_ST_SZ_DW(modify_lag_in)]   = {0};
+       u32   out[MLX5_ST_SZ_DW(modify_lag_out)] = {0};
+       void *lag_ctx = MLX5_ADDR_OF(modify_lag_in, in, ctx);
+
+       MLX5_SET(modify_lag_in, in, opcode, MLX5_CMD_OP_MODIFY_LAG);
+       MLX5_SET(modify_lag_in, in, field_select, 0x1);
+
+       MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, remap_port1);
+       MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, remap_port2);
+
+       return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
+static int mlx5_cmd_destroy_lag(struct mlx5_core_dev *dev)
+{
+       u32  in[MLX5_ST_SZ_DW(destroy_lag_in)]  = {0};
+       u32 out[MLX5_ST_SZ_DW(destroy_lag_out)] = {0};
+
+       MLX5_SET(destroy_lag_in, in, opcode, MLX5_CMD_OP_DESTROY_LAG);
+
+       return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
+int mlx5_cmd_create_vport_lag(struct mlx5_core_dev *dev)
+{
+       u32  in[MLX5_ST_SZ_DW(create_vport_lag_in)]  = {0};
+       u32 out[MLX5_ST_SZ_DW(create_vport_lag_out)] = {0};
+
+       MLX5_SET(create_vport_lag_in, in, opcode, MLX5_CMD_OP_CREATE_VPORT_LAG);
+
+       return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+EXPORT_SYMBOL(mlx5_cmd_create_vport_lag);
+
+int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev)
+{
+       u32  in[MLX5_ST_SZ_DW(destroy_vport_lag_in)]  = {0};
+       u32 out[MLX5_ST_SZ_DW(destroy_vport_lag_out)] = {0};
+
+       MLX5_SET(destroy_vport_lag_in, in, opcode, MLX5_CMD_OP_DESTROY_VPORT_LAG);
+
+       return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag);
+
+static struct mlx5_lag *mlx5_lag_dev_get(struct mlx5_core_dev *dev)
+{
+       return dev->priv.lag;
+}
+
+static int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
+                                      struct net_device *ndev)
+{
+       int i;
+
+       for (i = 0; i < MLX5_MAX_PORTS; i++)
+               if (ldev->pf[i].netdev == ndev)
+                       return i;
+
+       return -1;
+}
+
+static bool mlx5_lag_is_bonded(struct mlx5_lag *ldev)
+{
+       return !!(ldev->flags & MLX5_LAG_FLAG_BONDED);
+}
+
+static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,
+                                          u8 *port1, u8 *port2)
+{
+       if (tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
+               if (tracker->netdev_state[0].tx_enabled) {
+                       *port1 = 1;
+                       *port2 = 1;
+               } else {
+                       *port1 = 2;
+                       *port2 = 2;
+               }
+       } else {
+               *port1 = 1;
+               *port2 = 2;
+               if (!tracker->netdev_state[0].link_up)
+                       *port1 = 2;
+               else if (!tracker->netdev_state[1].link_up)
+                       *port2 = 1;
+       }
+}
+
+static void mlx5_activate_lag(struct mlx5_lag *ldev,
+                             struct lag_tracker *tracker)
+{
+       struct mlx5_core_dev *dev0 = ldev->pf[0].dev;
+       int err;
+
+       ldev->flags |= MLX5_LAG_FLAG_BONDED;
+
+       mlx5_infer_tx_affinity_mapping(tracker, &ldev->v2p_map[0],
+                                      &ldev->v2p_map[1]);
+
+       err = mlx5_cmd_create_lag(dev0, ldev->v2p_map[0], ldev->v2p_map[1]);
+       if (err)
+               mlx5_core_err(dev0,
+                             "Failed to create LAG (%d)\n",
+                             err);
+}
+
+static void mlx5_deactivate_lag(struct mlx5_lag *ldev)
+{
+       struct mlx5_core_dev *dev0 = ldev->pf[0].dev;
+       int err;
+
+       ldev->flags &= ~MLX5_LAG_FLAG_BONDED;
+
+       err = mlx5_cmd_destroy_lag(dev0);
+       if (err)
+               mlx5_core_err(dev0,
+                             "Failed to destroy LAG (%d)\n",
+                             err);
+}
+
+static void mlx5_do_bond(struct mlx5_lag *ldev)
+{
+       struct mlx5_core_dev *dev0 = ldev->pf[0].dev;
+       struct mlx5_core_dev *dev1 = ldev->pf[1].dev;
+       struct lag_tracker tracker;
+       u8 v2p_port1, v2p_port2;
+       int i, err;
+
+       if (!dev0 || !dev1)
+               return;
+
+       mutex_lock(&lag_mutex);
+       tracker = ldev->tracker;
+       mutex_unlock(&lag_mutex);
+
+       if (tracker.is_bonded && !mlx5_lag_is_bonded(ldev)) {
+               if (mlx5_sriov_is_enabled(dev0) ||
+                   mlx5_sriov_is_enabled(dev1)) {
+                       mlx5_core_warn(dev0, "LAG is not supported with SRIOV");
+                       return;
+               }
+
+               for (i = 0; i < MLX5_MAX_PORTS; i++)
+                       mlx5_remove_dev_by_protocol(ldev->pf[i].dev,
+                                                   MLX5_INTERFACE_PROTOCOL_IB);
+
+               mlx5_activate_lag(ldev, &tracker);
+
+               mlx5_add_dev_by_protocol(dev0, MLX5_INTERFACE_PROTOCOL_IB);
+               mlx5_nic_vport_enable_roce(dev1);
+       } else if (tracker.is_bonded && mlx5_lag_is_bonded(ldev)) {
+               mlx5_infer_tx_affinity_mapping(&tracker, &v2p_port1,
+                                              &v2p_port2);
+
+               if ((v2p_port1 != ldev->v2p_map[0]) ||
+                   (v2p_port2 != ldev->v2p_map[1])) {
+                       ldev->v2p_map[0] = v2p_port1;
+                       ldev->v2p_map[1] = v2p_port2;
+
+                       err = mlx5_cmd_modify_lag(dev0, v2p_port1, v2p_port2);
+                       if (err)
+                               mlx5_core_err(dev0,
+                                             "Failed to modify LAG (%d)\n",
+                                             err);
+               }
+       } else if (!tracker.is_bonded && mlx5_lag_is_bonded(ldev)) {
+               mlx5_remove_dev_by_protocol(dev0, MLX5_INTERFACE_PROTOCOL_IB);
+               mlx5_nic_vport_disable_roce(dev1);
+
+               mlx5_deactivate_lag(ldev);
+
+               for (i = 0; i < MLX5_MAX_PORTS; i++)
+                       if (ldev->pf[i].dev)
+                               mlx5_add_dev_by_protocol(ldev->pf[i].dev,
+                                                        MLX5_INTERFACE_PROTOCOL_IB);
+       }
+}
+
+static void mlx5_queue_bond_work(struct mlx5_lag *ldev, unsigned long delay)
+{
+       schedule_delayed_work(&ldev->bond_work, delay);
+}
+
+static void mlx5_do_bond_work(struct work_struct *work)
+{
+       struct delayed_work *delayed_work = to_delayed_work(work);
+       struct mlx5_lag *ldev = container_of(delayed_work, struct mlx5_lag,
+                                            bond_work);
+       int status;
+
+       status = mutex_trylock(&mlx5_intf_mutex);
+       if (!status) {
+               /* 1 sec delay. */
+               mlx5_queue_bond_work(ldev, HZ);
+               return;
+       }
+
+       mlx5_do_bond(ldev);
+       mutex_unlock(&mlx5_intf_mutex);
+}
+
+static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev,
+                                        struct lag_tracker *tracker,
+                                        struct net_device *ndev,
+                                        struct netdev_notifier_changeupper_info *info)
+{
+       struct net_device *upper = info->upper_dev, *ndev_tmp;
+       struct netdev_lag_upper_info *lag_upper_info;
+       bool is_bonded;
+       int bond_status = 0;
+       int num_slaves = 0;
+       int idx;
+
+       if (!netif_is_lag_master(upper))
+               return 0;
+
+       lag_upper_info = info->upper_info;
+
+       /* The event may still be of interest if the slave does not belong to
+        * us, but is enslaved to a master which has one or more of our netdevs
+        * as slaves (e.g., if a new slave is added to a master that bonds two
+        * of our netdevs, we should unbond).
+        */
+       rcu_read_lock();
+       for_each_netdev_in_bond_rcu(upper, ndev_tmp) {
+               idx = mlx5_lag_dev_get_netdev_idx(ldev, ndev_tmp);
+               if (idx > -1)
+                       bond_status |= (1 << idx);
+
+               num_slaves++;
+       }
+       rcu_read_unlock();
+
+       /* None of this lagdev's netdevs are slaves of this master. */
+       if (!(bond_status & 0x3))
+               return 0;
+
+       if (lag_upper_info)
+               tracker->tx_type = lag_upper_info->tx_type;
+
+       /* Determine bonding status:
+        * A device is considered bonded if both its physical ports are slaves
+        * of the same lag master, and only them.
+        * Lag mode must be activebackup or hash.
+        */
+       is_bonded = (num_slaves == MLX5_MAX_PORTS) &&
+                   (bond_status == 0x3) &&
+                   ((tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) ||
+                    (tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH));
+
+       if (tracker->is_bonded != is_bonded) {
+               tracker->is_bonded = is_bonded;
+               return 1;
+       }
+
+       return 0;
+}
+
+static int mlx5_handle_changelowerstate_event(struct mlx5_lag *ldev,
+                                             struct lag_tracker *tracker,
+                                             struct net_device *ndev,
+                                             struct netdev_notifier_changelowerstate_info *info)
+{
+       struct netdev_lag_lower_state_info *lag_lower_info;
+       int idx;
+
+       if (!netif_is_lag_port(ndev))
+               return 0;
+
+       idx = mlx5_lag_dev_get_netdev_idx(ldev, ndev);
+       if (idx == -1)
+               return 0;
+
+       /* This information is used to determine virtual to physical
+        * port mapping.
+        */
+       lag_lower_info = info->lower_state_info;
+       if (!lag_lower_info)
+               return 0;
+
+       tracker->netdev_state[idx] = *lag_lower_info;
+
+       return 1;
+}
+
+static int mlx5_lag_netdev_event(struct notifier_block *this,
+                                unsigned long event, void *ptr)
+{
+       struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
+       struct lag_tracker tracker;
+       struct mlx5_lag *ldev;
+       int changed = 0;
+
+       if (!net_eq(dev_net(ndev), &init_net))
+               return NOTIFY_DONE;
+
+       if ((event != NETDEV_CHANGEUPPER) && (event != NETDEV_CHANGELOWERSTATE))
+               return NOTIFY_DONE;
+
+       ldev    = container_of(this, struct mlx5_lag, nb);
+       tracker = ldev->tracker;
+
+       switch (event) {
+       case NETDEV_CHANGEUPPER:
+               changed = mlx5_handle_changeupper_event(ldev, &tracker, ndev,
+                                                       ptr);
+               break;
+       case NETDEV_CHANGELOWERSTATE:
+               changed = mlx5_handle_changelowerstate_event(ldev, &tracker,
+                                                            ndev, ptr);
+               break;
+       }
+
+       mutex_lock(&lag_mutex);
+       ldev->tracker = tracker;
+       mutex_unlock(&lag_mutex);
+
+       if (changed)
+               mlx5_queue_bond_work(ldev, 0);
+
+       return NOTIFY_DONE;
+}
+
+static struct mlx5_lag *mlx5_lag_dev_alloc(void)
+{
+       struct mlx5_lag *ldev;
+
+       ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
+       if (!ldev)
+               return NULL;
+
+       INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work);
+
+       return ldev;
+}
+
+static void mlx5_lag_dev_free(struct mlx5_lag *ldev)
+{
+       kfree(ldev);
+}
+
+static void mlx5_lag_dev_add_pf(struct mlx5_lag *ldev,
+                               struct mlx5_core_dev *dev,
+                               struct net_device *netdev)
+{
+       unsigned int fn = PCI_FUNC(dev->pdev->devfn);
+
+       if (fn >= MLX5_MAX_PORTS)
+               return;
+
+       mutex_lock(&lag_mutex);
+       ldev->pf[fn].dev    = dev;
+       ldev->pf[fn].netdev = netdev;
+       ldev->tracker.netdev_state[fn].link_up = 0;
+       ldev->tracker.netdev_state[fn].tx_enabled = 0;
+
+       dev->priv.lag = ldev;
+       mutex_unlock(&lag_mutex);
+}
+
+static void mlx5_lag_dev_remove_pf(struct mlx5_lag *ldev,
+                                  struct mlx5_core_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < MLX5_MAX_PORTS; i++)
+               if (ldev->pf[i].dev == dev)
+                       break;
+
+       if (i == MLX5_MAX_PORTS)
+               return;
+
+       mutex_lock(&lag_mutex);
+       memset(&ldev->pf[i], 0, sizeof(*ldev->pf));
+
+       dev->priv.lag = NULL;
+       mutex_unlock(&lag_mutex);
+}
+
+static u16 mlx5_gen_pci_id(struct mlx5_core_dev *dev)
+{
+       return (u16)((dev->pdev->bus->number << 8) |
+                    PCI_SLOT(dev->pdev->devfn));
+}
+
+/* Must be called with intf_mutex held */
+void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
+{
+       struct mlx5_lag *ldev = NULL;
+       struct mlx5_core_dev *tmp_dev;
+       struct mlx5_priv *priv;
+       u16 pci_id;
+
+       if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
+           !MLX5_CAP_GEN(dev, lag_master) ||
+           (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_MAX_PORTS))
+               return;
+
+       pci_id = mlx5_gen_pci_id(dev);
+
+       mlx5_core_for_each_priv(priv) {
+               tmp_dev = container_of(priv, struct mlx5_core_dev, priv);
+               if ((dev != tmp_dev) &&
+                   (mlx5_gen_pci_id(tmp_dev) == pci_id)) {
+                       ldev = tmp_dev->priv.lag;
+                       break;
+               }
+       }
+
+       if (!ldev) {
+               ldev = mlx5_lag_dev_alloc();
+               if (!ldev) {
+                       mlx5_core_err(dev, "Failed to alloc lag dev\n");
+                       return;
+               }
+       }
+
+       mlx5_lag_dev_add_pf(ldev, dev, netdev);
+
+       if (!ldev->nb.notifier_call) {
+               ldev->nb.notifier_call = mlx5_lag_netdev_event;
+               if (register_netdevice_notifier(&ldev->nb)) {
+                       ldev->nb.notifier_call = NULL;
+                       mlx5_core_err(dev, "Failed to register LAG netdev notifier\n");
+               }
+       }
+}
+
+/* Must be called with intf_mutex held */
+void mlx5_lag_remove(struct mlx5_core_dev *dev)
+{
+       struct mlx5_lag *ldev;
+       int i;
+
+       ldev = mlx5_lag_dev_get(dev);
+       if (!ldev)
+               return;
+
+       if (mlx5_lag_is_bonded(ldev))
+               mlx5_deactivate_lag(ldev);
+
+       mlx5_lag_dev_remove_pf(ldev, dev);
+
+       for (i = 0; i < MLX5_MAX_PORTS; i++)
+               if (ldev->pf[i].dev)
+                       break;
+
+       if (i == MLX5_MAX_PORTS) {
+               if (ldev->nb.notifier_call)
+                       unregister_netdevice_notifier(&ldev->nb);
+               cancel_delayed_work_sync(&ldev->bond_work);
+               mlx5_lag_dev_free(ldev);
+       }
+}
+
+bool mlx5_lag_is_active(struct mlx5_core_dev *dev)
+{
+       struct mlx5_lag *ldev;
+       bool res;
+
+       mutex_lock(&lag_mutex);
+       ldev = mlx5_lag_dev_get(dev);
+       res  = ldev && mlx5_lag_is_bonded(ldev);
+       mutex_unlock(&lag_mutex);
+
+       return res;
+}
+EXPORT_SYMBOL(mlx5_lag_is_active);
+
+struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev)
+{
+       struct net_device *ndev = NULL;
+       struct mlx5_lag *ldev;
+
+       mutex_lock(&lag_mutex);
+       ldev = mlx5_lag_dev_get(dev);
+
+       if (!(ldev && mlx5_lag_is_bonded(ldev)))
+               goto unlock;
+
+       if (ldev->tracker.tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) {
+               ndev = ldev->tracker.netdev_state[0].tx_enabled ?
+                      ldev->pf[0].netdev : ldev->pf[1].netdev;
+       } else {
+               ndev = ldev->pf[0].netdev;
+       }
+       if (ndev)
+               dev_hold(ndev);
+
+unlock:
+       mutex_unlock(&lag_mutex);
+
+       return ndev;
+}
+EXPORT_SYMBOL(mlx5_lag_get_roce_netdev);
+
+bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv)
+{
+       struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev,
+                                                priv);
+       struct mlx5_lag *ldev;
+
+       if (intf->protocol != MLX5_INTERFACE_PROTOCOL_IB)
+               return true;
+
+       ldev = mlx5_lag_dev_get(dev);
+       if (!ldev || !mlx5_lag_is_bonded(ldev) || ldev->pf[0].dev == dev)
+               return true;
+
+       /* If bonded, we do not add an IB device for PF1. */
+       return false;
+}
+
index d6446a3623b2b327c5861acd7253c2576e149382..28e3ce690e3f42bbfdb2fa3d6ad1dd5d623ec936 100644 (file)
@@ -73,8 +73,9 @@ module_param_named(prof_sel, prof_sel, int, 0444);
 MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
 
 static LIST_HEAD(intf_list);
-static LIST_HEAD(dev_list);
-static DEFINE_MUTEX(intf_mutex);
+
+LIST_HEAD(mlx5_dev_list);
+DEFINE_MUTEX(mlx5_intf_mutex);
 
 struct mlx5_device_context {
        struct list_head        list;
@@ -782,6 +783,9 @@ static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
        struct mlx5_device_context *dev_ctx;
        struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
 
+       if (!mlx5_lag_intf_add(intf, priv))
+               return;
+
        dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL);
        if (!dev_ctx)
                return;
@@ -820,11 +824,11 @@ static int mlx5_register_device(struct mlx5_core_dev *dev)
        struct mlx5_priv *priv = &dev->priv;
        struct mlx5_interface *intf;
 
-       mutex_lock(&intf_mutex);
-       list_add_tail(&priv->dev_list, &dev_list);
+       mutex_lock(&mlx5_intf_mutex);
+       list_add_tail(&priv->dev_list, &mlx5_dev_list);
        list_for_each_entry(intf, &intf_list, list)
                mlx5_add_device(intf, priv);
-       mutex_unlock(&intf_mutex);
+       mutex_unlock(&mlx5_intf_mutex);
 
        return 0;
 }
@@ -834,11 +838,11 @@ static void mlx5_unregister_device(struct mlx5_core_dev *dev)
        struct mlx5_priv *priv = &dev->priv;
        struct mlx5_interface *intf;
 
-       mutex_lock(&intf_mutex);
+       mutex_lock(&mlx5_intf_mutex);
        list_for_each_entry(intf, &intf_list, list)
                mlx5_remove_device(intf, priv);
        list_del(&priv->dev_list);
-       mutex_unlock(&intf_mutex);
+       mutex_unlock(&mlx5_intf_mutex);
 }
 
 int mlx5_register_interface(struct mlx5_interface *intf)
@@ -848,11 +852,11 @@ int mlx5_register_interface(struct mlx5_interface *intf)
        if (!intf->add || !intf->remove)
                return -EINVAL;
 
-       mutex_lock(&intf_mutex);
+       mutex_lock(&mlx5_intf_mutex);
        list_add_tail(&intf->list, &intf_list);
-       list_for_each_entry(priv, &dev_list, dev_list)
+       list_for_each_entry(priv, &mlx5_dev_list, dev_list)
                mlx5_add_device(intf, priv);
-       mutex_unlock(&intf_mutex);
+       mutex_unlock(&mlx5_intf_mutex);
 
        return 0;
 }
@@ -862,11 +866,11 @@ void mlx5_unregister_interface(struct mlx5_interface *intf)
 {
        struct mlx5_priv *priv;
 
-       mutex_lock(&intf_mutex);
-       list_for_each_entry(priv, &dev_list, dev_list)
+       mutex_lock(&mlx5_intf_mutex);
+       list_for_each_entry(priv, &mlx5_dev_list, dev_list)
                mlx5_remove_device(intf, priv);
        list_del(&intf->list);
-       mutex_unlock(&intf_mutex);
+       mutex_unlock(&mlx5_intf_mutex);
 }
 EXPORT_SYMBOL(mlx5_unregister_interface);
 
@@ -892,6 +896,30 @@ void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol)
 }
 EXPORT_SYMBOL(mlx5_get_protocol_dev);
 
+/* Must be called with intf_mutex held */
+void mlx5_add_dev_by_protocol(struct mlx5_core_dev *dev, int protocol)
+{
+       struct mlx5_interface *intf;
+
+       list_for_each_entry(intf, &intf_list, list)
+               if (intf->protocol == protocol) {
+                       mlx5_add_device(intf, &dev->priv);
+                       break;
+               }
+}
+
+/* Must be called with intf_mutex held */
+void mlx5_remove_dev_by_protocol(struct mlx5_core_dev *dev, int protocol)
+{
+       struct mlx5_interface *intf;
+
+       list_for_each_entry(intf, &intf_list, list)
+               if (intf->protocol == protocol) {
+                       mlx5_remove_device(intf, &dev->priv);
+                       break;
+               }
+}
+
 static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
 {
        struct pci_dev *pdev = dev->pdev;
index ef0eeedcceb655139dfb751a7808b19f46d14c12..714b71bed2be0a7a07798d508d27c549cc1c3c31 100644 (file)
@@ -46,6 +46,9 @@
 
 extern int mlx5_core_debug_mask;
 
+extern struct list_head mlx5_dev_list;
+extern struct mutex mlx5_intf_mutex;
+
 #define mlx5_core_dbg(__dev, format, ...)                              \
        dev_dbg(&(__dev)->pdev->dev, "%s:%s:%d:(pid %d): " format,      \
                 (__dev)->priv.name, __func__, __LINE__, current->pid,  \
@@ -70,6 +73,9 @@ do {                                                                  \
 #define mlx5_core_info(__dev, format, ...)                             \
        dev_info(&(__dev)->pdev->dev, format, ##__VA_ARGS__)
 
+#define mlx5_core_for_each_priv(__priv)                                        \
+       list_for_each_entry(__priv, &mlx5_dev_list, dev_list)
+
 enum {
        MLX5_CMD_DATA, /* print command payload only */
        MLX5_CMD_TIME, /* print command execution time */
@@ -84,6 +90,7 @@ void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
 void mlx5_enter_error_state(struct mlx5_core_dev *dev);
 void mlx5_disable_device(struct mlx5_core_dev *dev);
 int mlx5_core_sriov_configure(struct pci_dev *dev, int num_vfs);
+bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev);
 int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id);
 int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id);
 int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev);
@@ -92,7 +99,27 @@ u32 mlx5_get_msix_vec(struct mlx5_core_dev *dev, int vecidx);
 struct mlx5_eq *mlx5_eqn2eq(struct mlx5_core_dev *dev, int eqn);
 void mlx5_cq_tasklet_cb(unsigned long data);
 
+void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev);
+void mlx5_lag_remove(struct mlx5_core_dev *dev);
+
+void mlx5_add_dev_by_protocol(struct mlx5_core_dev *dev, int protocol);
+void mlx5_remove_dev_by_protocol(struct mlx5_core_dev *dev, int protocol);
+
+bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv);
+
 void mlx5e_init(void);
 void mlx5e_cleanup(void);
 
+static inline int mlx5_lag_is_lacp_owner(struct mlx5_core_dev *dev)
+{
+       /* LACP owner conditions:
+        * 1) Function is physical.
+        * 2) LAG is supported by FW.
+        * 3) LAG is managed by driver (currently the only option).
+        */
+       return  MLX5_CAP_GEN(dev, vport_group_manager) &&
+                  (MLX5_CAP_GEN(dev, num_lag_ports) > 1) &&
+                   MLX5_CAP_GEN(dev, lag_master);
+}
+
 #endif /* __MLX5_CORE_H__ */
index 2ee28ad8f918d612c59532c21ffca7bb0a8b8f94..34e7184e23c9bac44a7d06d1e4e2e85990441e2e 100644 (file)
@@ -175,25 +175,39 @@ int mlx5_query_port_link_width_oper(struct mlx5_core_dev *dev,
 }
 EXPORT_SYMBOL_GPL(mlx5_query_port_link_width_oper);
 
-int mlx5_query_port_proto_oper(struct mlx5_core_dev *dev,
-                              u8 *proto_oper, int proto_mask,
-                              u8 local_port)
+int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
+                                  u32 *proto_oper, u8 local_port)
 {
        u32 out[MLX5_ST_SZ_DW(ptys_reg)];
        int err;
 
-       err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, local_port);
+       err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN,
+                                  local_port);
        if (err)
                return err;
 
-       if (proto_mask == MLX5_PTYS_EN)
-               *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
-       else
-               *proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
+       *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
+
+       return 0;
+}
+EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper);
+
+int mlx5_query_port_ib_proto_oper(struct mlx5_core_dev *dev,
+                                 u8 *proto_oper, u8 local_port)
+{
+       u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+       int err;
+
+       err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_IB,
+                                  local_port);
+       if (err)
+               return err;
+
+       *proto_oper = MLX5_GET(ptys_reg, out, ib_proto_oper);
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(mlx5_query_port_proto_oper);
+EXPORT_SYMBOL(mlx5_query_port_ib_proto_oper);
 
 int mlx5_set_port_ptys(struct mlx5_core_dev *dev, bool an_disable,
                       u32 proto_admin, int proto_mask)
index 0680dfb4bb1eeff15b4c30a6fe3d0bb003ddaada..78e7892451831824abd5b50fe09005a02f527021 100644 (file)
 #include "eswitch.h"
 #endif
 
+bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev)
+{
+       struct mlx5_core_sriov *sriov = &dev->priv.sriov;
+
+       return !!sriov->num_vfs;
+}
+
 static void enable_vfs(struct mlx5_core_dev *dev, int num_vfs)
 {
        struct mlx5_core_sriov *sriov = &dev->priv.sriov;
@@ -144,6 +151,11 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs)
        if (!mlx5_core_is_pf(dev))
                return -EPERM;
 
+       if (num_vfs && mlx5_lag_is_active(dev)) {
+               mlx5_core_warn(dev, "can't turn sriov on while LAG is active");
+               return -EINVAL;
+       }
+
        mlx5_core_cleanup_vfs(dev);
 
        if (!num_vfs) {
index 1721098eef131773471bb99aa281f7959ff817ff..b83d0a7a0b49b2f30bea1af97eea5dc093e2b97d 100644 (file)
@@ -591,6 +591,12 @@ static const struct mlxsw_reg_info mlxsw_reg_sfn = {
  */
 MLXSW_ITEM32(reg, sfn, swid, 0x00, 24, 8);
 
+/* reg_sfn_end
+ * Forces the current session to end.
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, sfn, end, 0x04, 20, 1);
+
 /* reg_sfn_num_rec
  * Request: Number of learned notifications and aged-out notification
  * records requested.
@@ -605,6 +611,7 @@ static inline void mlxsw_reg_sfn_pack(char *payload)
 {
        MLXSW_REG_ZERO(sfn, payload);
        mlxsw_reg_sfn_swid_set(payload, 0);
+       mlxsw_reg_sfn_end_set(payload, 1);
        mlxsw_reg_sfn_num_rec_set(payload, MLXSW_REG_SFN_REC_MAX_COUNT);
 }
 
index 1f816890681109e367f8b7a8e5639e35474e2a44..2713a64eae7541c9c38041f0c2c31473a7fad1fd 100644 (file)
@@ -555,8 +555,9 @@ int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port,
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
 }
 
-static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
-                                         u16 vid, bool learn_enable)
+int __mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                    u16 vid_begin, u16 vid_end,
+                                    bool learn_enable)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        char *spvmlr_pl;
@@ -565,13 +566,20 @@ static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
        spvmlr_pl = kmalloc(MLXSW_REG_SPVMLR_LEN, GFP_KERNEL);
        if (!spvmlr_pl)
                return -ENOMEM;
-       mlxsw_reg_spvmlr_pack(spvmlr_pl, mlxsw_sp_port->local_port, vid, vid,
-                             learn_enable);
+       mlxsw_reg_spvmlr_pack(spvmlr_pl, mlxsw_sp_port->local_port, vid_begin,
+                             vid_end, learn_enable);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvmlr), spvmlr_pl);
        kfree(spvmlr_pl);
        return err;
 }
 
+static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                         u16 vid, bool learn_enable)
+{
+       return __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid,
+                                               learn_enable);
+}
+
 static int
 mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port)
 {
@@ -973,10 +981,6 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev,
                        goto err_port_vp_mode_trans;
        }
 
-       err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, false);
-       if (err)
-               goto err_port_vid_learning_set;
-
        err = mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, true, untagged);
        if (err)
                goto err_port_add_vid;
@@ -984,8 +988,6 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev,
        return 0;
 
 err_port_add_vid:
-       mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, true);
-err_port_vid_learning_set:
        if (list_is_singular(&mlxsw_sp_port->vports_list))
                mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
 err_port_vp_mode_trans:
@@ -1012,8 +1014,6 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
 
        mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, false, false);
 
-       mlxsw_sp_port_vid_learning_set(mlxsw_sp_vport, vid, true);
-
        /* Drop FID reference. If this was the last reference the
         * resources will be freed.
         */
index ab3feb81bd432fe0dae79c41c82e2c2e5789ee1a..01537d3a1c481a552fedd2d33eb703674f0c2a6d 100644 (file)
@@ -558,6 +558,9 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
 int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port,
                                  enum mlxsw_reg_qeec_hr hr, u8 index,
                                  u8 next_index, u32 maxrate);
+int __mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                    u16 vid_begin, u16 vid_end,
+                                    bool learn_enable);
 
 #ifdef CONFIG_MLXSW_SPECTRUM_DCB
 
index d1b59cdfacc13824a642f0db6ffcd4c05678d4ef..0c3fbbc6b5378477c848f97babf678e190e88d13 100644 (file)
@@ -261,12 +261,40 @@ int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 fid,
                                         false);
 }
 
+static int mlxsw_sp_port_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                     bool set)
+{
+       u16 vid;
+       int err;
+
+       if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
+               vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
+
+               return __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid,
+                                                       set);
+       }
+
+       for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
+               err = __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid,
+                                                      set);
+               if (err)
+                       goto err_port_vid_learning_set;
+       }
+
+       return 0;
+
+err_port_vid_learning_set:
+       for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
+               __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid, !set);
+       return err;
+}
+
 static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
                                           struct switchdev_trans *trans,
                                           unsigned long brport_flags)
 {
+       unsigned long learning = mlxsw_sp_port->learning ? BR_LEARNING : 0;
        unsigned long uc_flood = mlxsw_sp_port->uc_flood ? BR_FLOOD : 0;
-       bool set;
        int err;
 
        if (!mlxsw_sp_port->bridged)
@@ -276,17 +304,30 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
                return 0;
 
        if ((uc_flood ^ brport_flags) & BR_FLOOD) {
-               set = mlxsw_sp_port->uc_flood ? false : true;
-               err = mlxsw_sp_port_uc_flood_set(mlxsw_sp_port, set);
+               err = mlxsw_sp_port_uc_flood_set(mlxsw_sp_port,
+                                                !mlxsw_sp_port->uc_flood);
                if (err)
                        return err;
        }
 
+       if ((learning ^ brport_flags) & BR_LEARNING) {
+               err = mlxsw_sp_port_learning_set(mlxsw_sp_port,
+                                                !mlxsw_sp_port->learning);
+               if (err)
+                       goto err_port_learning_set;
+       }
+
        mlxsw_sp_port->uc_flood = brport_flags & BR_FLOOD ? 1 : 0;
        mlxsw_sp_port->learning = brport_flags & BR_LEARNING ? 1 : 0;
        mlxsw_sp_port->learning_sync = brport_flags & BR_LEARNING_SYNC ? 1 : 0;
 
        return 0;
+
+err_port_learning_set:
+       if ((uc_flood ^ brport_flags) & BR_FLOOD)
+               mlxsw_sp_port_uc_flood_set(mlxsw_sp_port,
+                                          mlxsw_sp_port->uc_flood);
+       return err;
 }
 
 static int mlxsw_sp_ageing_set(struct mlxsw_sp *mlxsw_sp, u32 ageing_time)
@@ -635,6 +676,27 @@ static int __mlxsw_sp_port_vlans_set(struct mlxsw_sp_port *mlxsw_sp_port,
        return 0;
 }
 
+static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                         u16 vid_begin, u16 vid_end,
+                                         bool learn_enable)
+{
+       u16 vid, vid_e;
+       int err;
+
+       for (vid = vid_begin; vid <= vid_end;
+            vid += MLXSW_REG_SPVMLR_REC_MAX_COUNT) {
+               vid_e = min((u16) (vid + MLXSW_REG_SPVMLR_REC_MAX_COUNT - 1),
+                           vid_end);
+
+               err = __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid,
+                                                      vid_e, learn_enable);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
                                     u16 vid_begin, u16 vid_end,
                                     bool flag_untagged, bool flag_pvid)
@@ -675,6 +737,14 @@ static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
                }
        }
 
+       err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid_begin, vid_end,
+                                            mlxsw_sp_port->learning);
+       if (err) {
+               netdev_err(dev, "Failed to set learning for VIDs %d-%d\n",
+                          vid_begin, vid_end);
+               goto err_port_vid_learning_set;
+       }
+
        /* Changing activity bits only if HW operation succeded */
        for (vid = vid_begin; vid <= vid_end; vid++) {
                set_bit(vid, mlxsw_sp_port->active_vlans);
@@ -697,6 +767,9 @@ static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
 err_port_stp_state_set:
        for (vid = vid_begin; vid <= vid_end; vid++)
                clear_bit(vid, mlxsw_sp_port->active_vlans);
+       mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid_begin, vid_end,
+                                      false);
+err_port_vid_learning_set:
        if (old_pvid != mlxsw_sp_port->pvid)
                mlxsw_sp_port_pvid_set(mlxsw_sp_port, old_pvid);
 err_port_pvid_set:
@@ -1001,29 +1074,20 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
 static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
                                     u16 vid_begin, u16 vid_end)
 {
-       struct net_device *dev = mlxsw_sp_port->dev;
        u16 vid, pvid;
-       int err;
 
        if (!mlxsw_sp_port->bridged)
                return -EINVAL;
 
-       err = __mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end,
-                                       false, false);
-       if (err) {
-               netdev_err(dev, "Unable to del VIDs %d-%d\n", vid_begin,
-                          vid_end);
-               return err;
-       }
+       mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid_begin, vid_end,
+                                      false);
 
        pvid = mlxsw_sp_port->pvid;
-       if (pvid >= vid_begin && pvid <= vid_end) {
-               err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
-               if (err) {
-                       netdev_err(dev, "Unable to del PVID %d\n", pvid);
-                       return err;
-               }
-       }
+       if (pvid >= vid_begin && pvid <= vid_end)
+               mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
+
+       __mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end, false,
+                                 false);
 
        mlxsw_sp_port_fid_leave(mlxsw_sp_port, vid_begin, vid_end);
 
@@ -1366,8 +1430,6 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
                vid = fid;
        }
 
-       adding = adding && mlxsw_sp_port->learning;
-
 do_fdb_op:
        err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid,
                                      adding, true);
@@ -1429,8 +1491,6 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
                vid = fid;
        }
 
-       adding = adding && mlxsw_sp_port->learning;
-
 do_fdb_op:
        err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
                                          adding, true);
@@ -1496,20 +1556,18 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
        mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work);
 
        rtnl_lock();
-       do {
-               mlxsw_reg_sfn_pack(sfn_pl);
-               err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
-               if (err) {
-                       dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
-                       break;
-               }
-               num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
-               for (i = 0; i < num_rec; i++)
-                       mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
+       mlxsw_reg_sfn_pack(sfn_pl);
+       err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
+       if (err) {
+               dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
+               goto out;
+       }
+       num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
+       for (i = 0; i < num_rec; i++)
+               mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
 
-       } while (num_rec);
+out:
        rtnl_unlock();
-
        kfree(sfn_pl);
        mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
 }
index 2575070c836e40740dca43ba1d9a6a88d3b80230..77c141797152ef80af0a9e2d0070bfc56e796f27 100644 (file)
@@ -964,6 +964,18 @@ enum mlx5_cap_type {
 #define MLX5_CAP_FLOWTABLE_NIC_RX_MAX(mdev, cap) \
        MLX5_CAP_FLOWTABLE_MAX(mdev, flow_table_properties_nic_receive.cap)
 
+#define MLX5_CAP_FLOWTABLE_SNIFFER_RX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive_sniffer.cap)
+
+#define MLX5_CAP_FLOWTABLE_SNIFFER_RX_MAX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE_MAX(mdev, flow_table_properties_nic_receive_sniffer.cap)
+
+#define MLX5_CAP_FLOWTABLE_SNIFFER_TX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_transmit_sniffer.cap)
+
+#define MLX5_CAP_FLOWTABLE_SNIFFER_TX_MAX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE_MAX(mdev, flow_table_properties_nic_transmit_sniffer.cap)
+
 #define MLX5_CAP_ESW_FLOWTABLE(mdev, cap) \
        MLX5_GET(flow_table_eswitch_cap, \
                 mdev->hca_caps_cur[MLX5_CAP_ESWITCH_FLOW_TABLE], cap)
index ebe57abf3324080343777525c6e1999bd3d208a8..5cb9fa7aec61b32d157cc8adf51ef5ea74717073 100644 (file)
 #include <linux/mlx5/doorbell.h>
 #include <linux/mlx5/srq.h>
 
-enum {
-       MLX5_RQ_BITMASK_VSD = 1 << 1,
-};
-
 enum {
        MLX5_BOARD_ID_LEN = 64,
        MLX5_MAX_NAME_LEN = 16,
@@ -481,6 +477,7 @@ struct mlx5_fc_stats {
 };
 
 struct mlx5_eswitch;
+struct mlx5_lag;
 
 struct mlx5_rl_entry {
        u32                     rate;
@@ -554,6 +551,7 @@ struct mlx5_priv {
        struct mlx5_flow_steering *steering;
        struct mlx5_eswitch     *eswitch;
        struct mlx5_core_sriov  sriov;
+       struct mlx5_lag         *lag;
        unsigned long           pci_dev_data;
        struct mlx5_fc_stats            fc_stats;
        struct mlx5_rl_table            rl_table;
@@ -946,6 +944,11 @@ int mlx5_register_interface(struct mlx5_interface *intf);
 void mlx5_unregister_interface(struct mlx5_interface *intf);
 int mlx5_core_query_vendor_id(struct mlx5_core_dev *mdev, u32 *vendor_id);
 
+int mlx5_cmd_create_vport_lag(struct mlx5_core_dev *dev);
+int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev);
+bool mlx5_lag_is_active(struct mlx5_core_dev *dev);
+struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev);
+
 struct mlx5_profile {
        u64     mask;
        u8      log_max_qp;
index e036d6030867b9b12c0cfa74a2766371a3d87944..93ebc5e213345213d33d99e6e68970711f42c6e3 100644 (file)
@@ -54,6 +54,7 @@ static inline void build_leftovers_ft_param(int *priority,
 
 enum mlx5_flow_namespace_type {
        MLX5_FLOW_NAMESPACE_BYPASS,
+       MLX5_FLOW_NAMESPACE_LAG,
        MLX5_FLOW_NAMESPACE_OFFLOADS,
        MLX5_FLOW_NAMESPACE_ETHTOOL,
        MLX5_FLOW_NAMESPACE_KERNEL,
@@ -62,6 +63,8 @@ enum mlx5_flow_namespace_type {
        MLX5_FLOW_NAMESPACE_FDB,
        MLX5_FLOW_NAMESPACE_ESW_EGRESS,
        MLX5_FLOW_NAMESPACE_ESW_INGRESS,
+       MLX5_FLOW_NAMESPACE_SNIFFER_RX,
+       MLX5_FLOW_NAMESPACE_SNIFFER_TX,
 };
 
 struct mlx5_flow_table;
@@ -106,6 +109,9 @@ mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns,
                             int prio,
                             int num_flow_table_entries,
                             u32 level, u16 vport);
+struct mlx5_flow_table *mlx5_create_lag_demux_flow_table(
+                                              struct mlx5_flow_namespace *ns,
+                                              int prio, u32 level);
 int mlx5_destroy_flow_table(struct mlx5_flow_table *ft);
 
 /* inbox should be set with the following values:
index 3766110e13ea6394603326bcaf6b489eda0c40c1..73a720f74a69a59686c88c40b760d5b5ada3d1df 100644 (file)
@@ -174,6 +174,12 @@ enum {
        MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY         = 0x82b,
        MLX5_CMD_OP_SET_WOL_ROL                   = 0x830,
        MLX5_CMD_OP_QUERY_WOL_ROL                 = 0x831,
+       MLX5_CMD_OP_CREATE_LAG                    = 0x840,
+       MLX5_CMD_OP_MODIFY_LAG                    = 0x841,
+       MLX5_CMD_OP_QUERY_LAG                     = 0x842,
+       MLX5_CMD_OP_DESTROY_LAG                   = 0x843,
+       MLX5_CMD_OP_CREATE_VPORT_LAG              = 0x844,
+       MLX5_CMD_OP_DESTROY_VPORT_LAG             = 0x845,
        MLX5_CMD_OP_CREATE_TIR                    = 0x900,
        MLX5_CMD_OP_MODIFY_TIR                    = 0x901,
        MLX5_CMD_OP_DESTROY_TIR                   = 0x902,
@@ -477,7 +483,9 @@ struct mlx5_ifc_ads_bits {
 
 struct mlx5_ifc_flow_table_nic_cap_bits {
        u8         nic_rx_multi_path_tirs[0x1];
-       u8         reserved_at_1[0x1ff];
+       u8         nic_rx_multi_path_tirs_fts[0x1];
+       u8         allow_sniffer_and_nic_rx_shared_tir[0x1];
+       u8         reserved_at_3[0x1fd];
 
        struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_receive;
 
@@ -779,7 +787,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
        u8         out_of_seq_cnt[0x1];
        u8         vport_counters[0x1];
        u8         retransmission_q_counters[0x1];
-       u8         reserved_at_183[0x3];
+       u8         reserved_at_183[0x1];
+       u8         modify_rq_counter_set_id[0x1];
+       u8         reserved_at_185[0x1];
        u8         max_qp_cnt[0xa];
        u8         pkey_table_size[0x10];
 
@@ -882,7 +892,10 @@ struct mlx5_ifc_cmd_hca_cap_bits {
        u8         pad_tx_eth_packet[0x1];
        u8         reserved_at_263[0x8];
        u8         log_bf_reg_size[0x5];
-       u8         reserved_at_270[0x10];
+
+       u8         reserved_at_270[0xb];
+       u8         lag_master[0x1];
+       u8         num_lag_ports[0x4];
 
        u8         reserved_at_280[0x10];
        u8         max_wqe_sz_sq[0x10];
@@ -1916,7 +1929,7 @@ enum {
 
 struct mlx5_ifc_qpc_bits {
        u8         state[0x4];
-       u8         reserved_at_4[0x4];
+       u8         lag_tx_port_affinity[0x4];
        u8         st[0x8];
        u8         reserved_at_10[0x3];
        u8         pm_state[0x2];
@@ -2165,7 +2178,11 @@ struct mlx5_ifc_traffic_counter_bits {
 };
 
 struct mlx5_ifc_tisc_bits {
-       u8         reserved_at_0[0xc];
+       u8         strict_lag_tx_port_affinity[0x1];
+       u8         reserved_at_1[0x3];
+       u8         lag_tx_port_affinity[0x04];
+
+       u8         reserved_at_8[0x4];
        u8         prio[0x4];
        u8         reserved_at_10[0x10];
 
@@ -2827,7 +2844,7 @@ struct mlx5_ifc_xrqc_bits {
 
        struct mlx5_ifc_tag_matching_topology_context_bits tag_matching_topology_context;
 
-       u8         reserved_at_180[0x180];
+       u8         reserved_at_180[0x200];
 
        struct mlx5_ifc_wq_bits wq;
 };
@@ -4615,7 +4632,9 @@ struct mlx5_ifc_modify_tis_out_bits {
 struct mlx5_ifc_modify_tis_bitmask_bits {
        u8         reserved_at_0[0x20];
 
-       u8         reserved_at_20[0x1f];
+       u8         reserved_at_20[0x1d];
+       u8         lag_tx_port_affinity[0x1];
+       u8         strict_lag_tx_port_affinity[0x1];
        u8         prio[0x1];
 };
 
@@ -4750,6 +4769,11 @@ struct mlx5_ifc_modify_rq_out_bits {
        u8         reserved_at_40[0x40];
 };
 
+enum {
+       MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_VSD = 1ULL << 1,
+       MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_MODIFY_RQ_COUNTER_SET_ID = 1ULL << 3,
+};
+
 struct mlx5_ifc_modify_rq_in_bits {
        u8         opcode[0x10];
        u8         reserved_at_10[0x10];
@@ -6208,7 +6232,10 @@ struct mlx5_ifc_create_flow_table_in_bits {
        u8         reserved_at_e0[0x8];
        u8         table_miss_id[0x18];
 
-       u8         reserved_at_100[0x100];
+       u8         reserved_at_100[0x8];
+       u8         lag_master_next_table_id[0x18];
+
+       u8         reserved_at_120[0x80];
 };
 
 struct mlx5_ifc_create_flow_group_out_bits {
@@ -7662,7 +7689,8 @@ struct mlx5_ifc_set_flow_table_root_in_bits {
 };
 
 enum {
-       MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID = 0x1,
+       MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID     = (1UL << 0),
+       MLX5_MODIFY_FLOW_TABLE_LAG_NEXT_TABLE_ID = (1UL << 15),
 };
 
 struct mlx5_ifc_modify_flow_table_out_bits {
@@ -7701,7 +7729,10 @@ struct mlx5_ifc_modify_flow_table_in_bits {
        u8         reserved_at_e0[0x8];
        u8         table_miss_id[0x18];
 
-       u8         reserved_at_100[0x100];
+       u8         reserved_at_100[0x8];
+       u8         lag_master_next_table_id[0x18];
+
+       u8         reserved_at_120[0x80];
 };
 
 struct mlx5_ifc_ets_tcn_config_reg_bits {
@@ -7809,4 +7840,134 @@ struct mlx5_ifc_dcbx_param_bits {
        u8         error[0x8];
        u8         reserved_at_a0[0x160];
 };
+
+struct mlx5_ifc_lagc_bits {
+       u8         reserved_at_0[0x1d];
+       u8         lag_state[0x3];
+
+       u8         reserved_at_20[0x14];
+       u8         tx_remap_affinity_2[0x4];
+       u8         reserved_at_38[0x4];
+       u8         tx_remap_affinity_1[0x4];
+};
+
+struct mlx5_ifc_create_lag_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_create_lag_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       struct mlx5_ifc_lagc_bits ctx;
+};
+
+struct mlx5_ifc_modify_lag_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_modify_lag_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         reserved_at_40[0x20];
+       u8         field_select[0x20];
+
+       struct mlx5_ifc_lagc_bits ctx;
+};
+
+struct mlx5_ifc_query_lag_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+
+       struct mlx5_ifc_lagc_bits ctx;
+};
+
+struct mlx5_ifc_query_lag_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_destroy_lag_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_destroy_lag_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_create_vport_lag_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_create_vport_lag_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_destroy_vport_lag_out_bits {
+       u8         status[0x8];
+       u8         reserved_at_8[0x18];
+
+       u8         syndrome[0x20];
+
+       u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_destroy_vport_lag_in_bits {
+       u8         opcode[0x10];
+       u8         reserved_at_10[0x10];
+
+       u8         reserved_at_20[0x10];
+       u8         op_mod[0x10];
+
+       u8         reserved_at_40[0x40];
+};
+
 #endif /* MLX5_IFC_H */
index e3012cc64b8a000fc8a9b747d0495611ed16cd24..b3065acd20b4c9f678d92c8d2e13a81a619dc006 100644 (file)
@@ -61,6 +61,39 @@ enum mlx5_an_status {
 #define MLX5_I2C_ADDR_HIGH             0x51
 #define MLX5_EEPROM_PAGE_LENGTH                256
 
+enum mlx5e_link_mode {
+       MLX5E_1000BASE_CX_SGMII  = 0,
+       MLX5E_1000BASE_KX        = 1,
+       MLX5E_10GBASE_CX4        = 2,
+       MLX5E_10GBASE_KX4        = 3,
+       MLX5E_10GBASE_KR         = 4,
+       MLX5E_20GBASE_KR2        = 5,
+       MLX5E_40GBASE_CR4        = 6,
+       MLX5E_40GBASE_KR4        = 7,
+       MLX5E_56GBASE_R4         = 8,
+       MLX5E_10GBASE_CR         = 12,
+       MLX5E_10GBASE_SR         = 13,
+       MLX5E_10GBASE_ER         = 14,
+       MLX5E_40GBASE_SR4        = 15,
+       MLX5E_40GBASE_LR4        = 16,
+       MLX5E_50GBASE_SR2        = 18,
+       MLX5E_100GBASE_CR4       = 20,
+       MLX5E_100GBASE_SR4       = 21,
+       MLX5E_100GBASE_KR4       = 22,
+       MLX5E_100GBASE_LR4       = 23,
+       MLX5E_100BASE_TX         = 24,
+       MLX5E_1000BASE_T         = 25,
+       MLX5E_10GBASE_T          = 26,
+       MLX5E_25GBASE_CR         = 27,
+       MLX5E_25GBASE_KR         = 28,
+       MLX5E_25GBASE_SR         = 29,
+       MLX5E_50GBASE_CR2        = 30,
+       MLX5E_50GBASE_KR2        = 31,
+       MLX5E_LINK_MODES_NUMBER,
+};
+
+#define MLX5E_PROT_MASK(link_mode) (1 << link_mode)
+
 int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps);
 int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
                         int ptys_size, int proto_mask, u8 local_port);
@@ -70,9 +103,10 @@ int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev,
                                u32 *proto_admin, int proto_mask);
 int mlx5_query_port_link_width_oper(struct mlx5_core_dev *dev,
                                    u8 *link_width_oper, u8 local_port);
-int mlx5_query_port_proto_oper(struct mlx5_core_dev *dev,
-                              u8 *proto_oper, int proto_mask,
-                              u8 local_port);
+int mlx5_query_port_ib_proto_oper(struct mlx5_core_dev *dev,
+                                 u8 *proto_oper, u8 local_port);
+int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev,
+                                  u32 *proto_oper, u8 local_port);
 int mlx5_set_port_ptys(struct mlx5_core_dev *dev, bool an_disable,
                       u32 proto_admin, int proto_mask);
 void mlx5_toggle_port_link(struct mlx5_core_dev *dev);
index 2aab9b63bf168dd77e8eee854c54e3dee9149615..c797c57f4d9f6b2ef6cc23f1d63210cd41c8cff4 100644 (file)
@@ -1020,7 +1020,6 @@ struct proto {
        void                    (*unhash)(struct sock *sk);
        void                    (*rehash)(struct sock *sk);
        int                     (*get_port)(struct sock *sk, unsigned short snum);
-       void                    (*clear_sk)(struct sock *sk, int size);
 
        /* Keeping track of sockets in use */
 #ifdef CONFIG_PROC_FS
@@ -1242,8 +1241,6 @@ static inline int __sk_prot_rehash(struct sock *sk)
        return sk->sk_prot->hash(sk);
 }
 
-void sk_prot_clear_portaddr_nulls(struct sock *sk, int size);
-
 /* About 10 seconds */
 #define SOCK_DESTROY_TIME (10*HZ)
 
index 25dab8b60223e25ee92dae45a226fce2a6bb5a03..51a730485649e6e2cefac6d58de3a021411a6a0f 100644 (file)
@@ -1315,24 +1315,6 @@ static void sock_copy(struct sock *nsk, const struct sock *osk)
 #endif
 }
 
-void sk_prot_clear_portaddr_nulls(struct sock *sk, int size)
-{
-       unsigned long nulls1, nulls2;
-
-       nulls1 = offsetof(struct sock, __sk_common.skc_node.next);
-       nulls2 = offsetof(struct sock, __sk_common.skc_portaddr_node.next);
-       if (nulls1 > nulls2)
-               swap(nulls1, nulls2);
-
-       if (nulls1 != 0)
-               memset((char *)sk, 0, nulls1);
-       memset((char *)sk + nulls1 + sizeof(void *), 0,
-              nulls2 - nulls1 - sizeof(void *));
-       memset((char *)sk + nulls2 + sizeof(void *), 0,
-              size - nulls2 - sizeof(void *));
-}
-EXPORT_SYMBOL(sk_prot_clear_portaddr_nulls);
-
 static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
                int family)
 {
@@ -1344,12 +1326,8 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
                sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO);
                if (!sk)
                        return sk;
-               if (priority & __GFP_ZERO) {
-                       if (prot->clear_sk)
-                               prot->clear_sk(sk, prot->obj_size);
-                       else
-                               sk_prot_clear_nulls(sk, prot->obj_size);
-               }
+               if (priority & __GFP_ZERO)
+                       sk_prot_clear_nulls(sk, prot->obj_size);
        } else
                sk = kmalloc(prot->obj_size, priority);
 
index e9ffc27b23d0e739deb39bbadc56a5f5f4083bbc..f0ebb0bd1e11afc344445458b22c58cd8cb5b8f8 100644 (file)
@@ -2237,7 +2237,6 @@ struct proto udp_prot = {
        .compat_setsockopt = compat_udp_setsockopt,
        .compat_getsockopt = compat_udp_getsockopt,
 #endif
-       .clear_sk          = sk_prot_clear_portaddr_nulls,
        .diag_destroy      = udp_abort,
 };
 EXPORT_SYMBOL(udp_prot);
index 3b3efbda48e13941b35388238508706844c043aa..67fc9d96e67dae76af5d9abe6ee2c7baad08bbe4 100644 (file)
@@ -61,7 +61,6 @@ struct proto  udplite_prot = {
        .compat_setsockopt = compat_udp_setsockopt,
        .compat_getsockopt = compat_udp_getsockopt,
 #endif
-       .clear_sk          = sk_prot_clear_portaddr_nulls,
 };
 EXPORT_SYMBOL(udplite_prot);
 
index 33df8b8575cceb6f4bf50d9a50ab5a6afa79cd86..e0f46439e391f2a8b2fac2e13b6f61a11c082715 100644 (file)
@@ -1862,17 +1862,6 @@ void tcp6_proc_exit(struct net *net)
 }
 #endif
 
-static void tcp_v6_clear_sk(struct sock *sk, int size)
-{
-       struct inet_sock *inet = inet_sk(sk);
-
-       /* we do not want to clear pinet6 field, because of RCU lookups */
-       sk_prot_clear_nulls(sk, offsetof(struct inet_sock, pinet6));
-
-       size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6);
-       memset(&inet->pinet6 + 1, 0, size);
-}
-
 struct proto tcpv6_prot = {
        .name                   = "TCPv6",
        .owner                  = THIS_MODULE,
@@ -1914,7 +1903,6 @@ struct proto tcpv6_prot = {
        .compat_setsockopt      = compat_tcp_setsockopt,
        .compat_getsockopt      = compat_tcp_getsockopt,
 #endif
-       .clear_sk               = tcp_v6_clear_sk,
        .diag_destroy           = tcp_abort,
 };
 
index 16512cf06e733ad8004b18cdb2cfcbcffacec605..9efe740ff6ddd6bbfc95cf598e4c09a25262ca88 100644 (file)
@@ -1424,17 +1424,6 @@ void udp6_proc_exit(struct net *net)
 }
 #endif /* CONFIG_PROC_FS */
 
-void udp_v6_clear_sk(struct sock *sk, int size)
-{
-       struct inet_sock *inet = inet_sk(sk);
-
-       /* we do not want to clear pinet6 field, because of RCU lookups */
-       sk_prot_clear_portaddr_nulls(sk, offsetof(struct inet_sock, pinet6));
-
-       size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6);
-       memset(&inet->pinet6 + 1, 0, size);
-}
-
 /* ------------------------------------------------------------------------ */
 
 struct proto udpv6_prot = {
@@ -1466,7 +1455,6 @@ struct proto udpv6_prot = {
        .compat_setsockopt = compat_udpv6_setsockopt,
        .compat_getsockopt = compat_udpv6_getsockopt,
 #endif
-       .clear_sk          = udp_v6_clear_sk,
        .diag_destroy      = udp_abort,
 };
 
index 0682c031ccdc77da801c46851d7ad2163921fe19..f6eb1ab34f4bc50e321e74f129feee4118f03807 100644 (file)
@@ -29,8 +29,6 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
 int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 void udpv6_destroy_sock(struct sock *sk);
 
-void udp_v6_clear_sk(struct sock *sk, int size);
-
 #ifdef CONFIG_PROC_FS
 int udp6_seq_show(struct seq_file *seq, void *v);
 #endif
index 9cf097e206e931c6e3c184f22b8adcabedc4c03a..5cf0099b86f71c2f74f813b17230f80149665b8e 100644 (file)
@@ -56,7 +56,6 @@ struct proto udplitev6_prot = {
        .compat_setsockopt = compat_udpv6_setsockopt,
        .compat_getsockopt = compat_udpv6_getsockopt,
 #endif
-       .clear_sk          = udp_v6_clear_sk,
 };
 
 static struct inet_protosw udplite6_protosw = {