]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'mlx5-updates-2017-06-11' of git://git.kernel.org/pub/scm/linux/kernel...
authorDavid S. Miller <davem@davemloft.net>
Sun, 11 Jun 2017 22:10:42 +0000 (18:10 -0400)
committerDavid S. Miller <davem@davemloft.net>
Sun, 11 Jun 2017 22:10:42 +0000 (18:10 -0400)
Saeed Mahameed says:

====================
mlx5-updates-2017-06-11

This series provides updates to mlx5 header rewrite feature, from Or Gerlitz.
and three more small updates From maor and eran.

-------
Or says:

Packets belonging to flows which are different by matching may still need
to go through the same header re-writes (e.g set the current routing hop
MACs and issue TTL decrement).  To minimize the number of modify header
IDs, we add a cache for header re-write IDs which is keyed by the binary
chain of modify header actions.

The caching is supported for both eswitch and NIC use-cases, where the
actual conversion of the code to use caching comes in separate patches,
one per use-case.

Using a per field mask field, the TC pedit action supports modifying
partial fields. The last patch enables offloading that.
-------

From Maor, update flow table commands layout to the latest HW spec.
From Eran, ethtool connector type reporting updates.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
include/linux/mlx5/mlx5_ifc.h
include/linux/mlx5/port.h

index 2fd044b238750fedc61384fda55bf25206d25b51..f4b95dbd1c7f2304a87315890259865769237799 100644 (file)
@@ -623,6 +623,8 @@ struct mlx5e_tc_table {
 
        struct rhashtable_params        ht_params;
        struct rhashtable               ht;
+
+       DECLARE_HASHTABLE(mod_hdr_tbl, 8);
 };
 
 struct mlx5e_vlan_table {
index e9e33fd682796e48322b74280c86690ecd5d6ba3..b4514f2474024dc1f73a13ecd82f6d6c64378ca5 100644 (file)
@@ -723,24 +723,81 @@ static void ptys2ethtool_adver_link(unsigned long *advertising_modes,
                          __ETHTOOL_LINK_MODE_MASK_NBITS);
 }
 
-static void ptys2ethtool_supported_port(struct ethtool_link_ksettings *link_ksettings,
-                                       u32 eth_proto_cap)
+static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings *link_ksettings,
+                                                  u32 eth_proto_cap,
+                                                  u8 connector_type)
 {
-       if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR)
-                          | MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
-                          | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4)
-                          | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4)
-                          | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4)
-                          | MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) {
-               ethtool_link_ksettings_add_link_mode(link_ksettings, supported, FIBRE);
+       if (!connector_type || connector_type >= MLX5E_CONNECTOR_TYPE_NUMBER) {
+               if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR)
+                                  | MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
+                                  | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4)
+                                  | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4)
+                                  | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4)
+                                  | MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) {
+                       ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                            supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                            advertising,
+                                                            FIBRE);
+               }
+
+               if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_100GBASE_KR4)
+                                  | MLX5E_PROT_MASK(MLX5E_40GBASE_KR4)
+                                  | MLX5E_PROT_MASK(MLX5E_10GBASE_KR)
+                                  | MLX5E_PROT_MASK(MLX5E_10GBASE_KX4)
+                                  | MLX5E_PROT_MASK(MLX5E_1000BASE_KX))) {
+                       ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                            supported,
+                                                            Backplane);
+                       ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                            advertising,
+                                                            Backplane);
+               }
+               return;
        }
 
-       if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_100GBASE_KR4)
-                          | MLX5E_PROT_MASK(MLX5E_40GBASE_KR4)
-                          | MLX5E_PROT_MASK(MLX5E_10GBASE_KR)
-                          | MLX5E_PROT_MASK(MLX5E_10GBASE_KX4)
-                          | MLX5E_PROT_MASK(MLX5E_1000BASE_KX))) {
-               ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Backplane);
+       switch (connector_type) {
+       case MLX5E_PORT_TP:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, TP);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, TP);
+               break;
+       case MLX5E_PORT_AUI:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, AUI);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, AUI);
+               break;
+       case MLX5E_PORT_BNC:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, BNC);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, BNC);
+               break;
+       case MLX5E_PORT_MII:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, MII);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, MII);
+               break;
+       case MLX5E_PORT_FIBRE:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, FIBRE);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, FIBRE);
+               break;
+       case MLX5E_PORT_DA:
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    supported, Backplane);
+               ethtool_link_ksettings_add_link_mode(link_ksettings,
+                                                    advertising, Backplane);
+               break;
+       case MLX5E_PORT_NONE:
+       case MLX5E_PORT_OTHER:
+       default:
+               break;
        }
 }
 
@@ -791,7 +848,6 @@ static void get_supported(u32 eth_proto_cap,
 {
        unsigned long *supported = link_ksettings->link_modes.supported;
 
-       ptys2ethtool_supported_port(link_ksettings, eth_proto_cap);
        ptys2ethtool_supported_link(supported, eth_proto_cap);
        ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
 }
@@ -809,8 +865,23 @@ static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
                ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause);
 }
 
-static u8 get_connector_port(u32 eth_proto)
+static int ptys2connector_type[MLX5E_CONNECTOR_TYPE_NUMBER] = {
+               [MLX5E_PORT_UNKNOWN]            = PORT_OTHER,
+               [MLX5E_PORT_NONE]               = PORT_NONE,
+               [MLX5E_PORT_TP]                 = PORT_TP,
+               [MLX5E_PORT_AUI]                = PORT_AUI,
+               [MLX5E_PORT_BNC]                = PORT_BNC,
+               [MLX5E_PORT_MII]                = PORT_MII,
+               [MLX5E_PORT_FIBRE]              = PORT_FIBRE,
+               [MLX5E_PORT_DA]                 = PORT_DA,
+               [MLX5E_PORT_OTHER]              = PORT_OTHER,
+       };
+
+static u8 get_connector_port(u32 eth_proto, u8 connector_type)
 {
+       if (connector_type && connector_type < MLX5E_CONNECTOR_TYPE_NUMBER)
+               return ptys2connector_type[connector_type];
+
        if (eth_proto & (MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
                         | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4)
                         | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4)
@@ -856,6 +927,7 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        u32 eth_proto_oper;
        u8 an_disable_admin;
        u8 an_status;
+       u8 connector_type;
        int err;
 
        err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1);
@@ -871,6 +943,7 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        eth_proto_lp     = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
        an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
        an_status        = MLX5_GET(ptys_reg, out, an_status);
+       connector_type   = MLX5_GET(ptys_reg, out, connector_type);
 
        mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);
 
@@ -883,7 +956,10 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
 
        eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
 
-       link_ksettings->base.port = get_connector_port(eth_proto_oper);
+       link_ksettings->base.port = get_connector_port(eth_proto_oper,
+                                                      connector_type);
+       ptys2ethtool_supported_advertised_port(link_ksettings, eth_proto_admin,
+                                              connector_type);
        get_lp_advertising(eth_proto_lp, link_ksettings);
 
        if (an_status == MLX5_AN_COMPLETE)
index 8ec13f9be66014098332db1b76198f9fa3bd5508..f5afacfbe914c98fada5833f3471681420c5ea4f 100644 (file)
@@ -69,7 +69,8 @@ struct mlx5e_tc_flow {
        u64                     cookie;
        u8                      flags;
        struct mlx5_flow_handle *rule;
-       struct list_head        encap; /* flows sharing the same encap */
+       struct list_head        encap;   /* flows sharing the same encap ID */
+       struct list_head        mod_hdr; /* flows sharing the same mod hdr ID */
        union {
                struct mlx5_esw_flow_attr esw_attr[0];
                struct mlx5_nic_flow_attr nic_attr[0];
@@ -90,6 +91,135 @@ enum {
 #define MLX5E_TC_TABLE_NUM_ENTRIES 1024
 #define MLX5E_TC_TABLE_NUM_GROUPS 4
 
+struct mod_hdr_key {
+       int num_actions;
+       void *actions;
+};
+
+struct mlx5e_mod_hdr_entry {
+       /* a node of a hash table which keeps all the mod_hdr entries */
+       struct hlist_node mod_hdr_hlist;
+
+       /* flows sharing the same mod_hdr entry */
+       struct list_head flows;
+
+       struct mod_hdr_key key;
+
+       u32 mod_hdr_id;
+};
+
+#define MLX5_MH_ACT_SZ MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto)
+
+static inline u32 hash_mod_hdr_info(struct mod_hdr_key *key)
+{
+       return jhash(key->actions,
+                    key->num_actions * MLX5_MH_ACT_SZ, 0);
+}
+
+static inline int cmp_mod_hdr_info(struct mod_hdr_key *a,
+                                  struct mod_hdr_key *b)
+{
+       if (a->num_actions != b->num_actions)
+               return 1;
+
+       return memcmp(a->actions, b->actions, a->num_actions * MLX5_MH_ACT_SZ);
+}
+
+static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
+                               struct mlx5e_tc_flow *flow,
+                               struct mlx5e_tc_flow_parse_attr *parse_attr)
+{
+       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+       int num_actions, actions_size, namespace, err;
+       struct mlx5e_mod_hdr_entry *mh;
+       struct mod_hdr_key key;
+       bool found = false;
+       u32 hash_key;
+
+       num_actions  = parse_attr->num_mod_hdr_actions;
+       actions_size = MLX5_MH_ACT_SZ * num_actions;
+
+       key.actions = parse_attr->mod_hdr_actions;
+       key.num_actions = num_actions;
+
+       hash_key = hash_mod_hdr_info(&key);
+
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
+               namespace = MLX5_FLOW_NAMESPACE_FDB;
+               hash_for_each_possible(esw->offloads.mod_hdr_tbl, mh,
+                                      mod_hdr_hlist, hash_key) {
+                       if (!cmp_mod_hdr_info(&mh->key, &key)) {
+                               found = true;
+                               break;
+                       }
+               }
+       } else {
+               namespace = MLX5_FLOW_NAMESPACE_KERNEL;
+               hash_for_each_possible(priv->fs.tc.mod_hdr_tbl, mh,
+                                      mod_hdr_hlist, hash_key) {
+                       if (!cmp_mod_hdr_info(&mh->key, &key)) {
+                               found = true;
+                               break;
+                       }
+               }
+       }
+
+       if (found)
+               goto attach_flow;
+
+       mh = kzalloc(sizeof(*mh) + actions_size, GFP_KERNEL);
+       if (!mh)
+               return -ENOMEM;
+
+       mh->key.actions = (void *)mh + sizeof(*mh);
+       memcpy(mh->key.actions, key.actions, actions_size);
+       mh->key.num_actions = num_actions;
+       INIT_LIST_HEAD(&mh->flows);
+
+       err = mlx5_modify_header_alloc(priv->mdev, namespace,
+                                      mh->key.num_actions,
+                                      mh->key.actions,
+                                      &mh->mod_hdr_id);
+       if (err)
+               goto out_err;
+
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+               hash_add(esw->offloads.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key);
+       else
+               hash_add(priv->fs.tc.mod_hdr_tbl, &mh->mod_hdr_hlist, hash_key);
+
+attach_flow:
+       list_add(&flow->mod_hdr, &mh->flows);
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+               flow->esw_attr->mod_hdr_id = mh->mod_hdr_id;
+       else
+               flow->nic_attr->mod_hdr_id = mh->mod_hdr_id;
+
+       return 0;
+
+out_err:
+       kfree(mh);
+       return err;
+}
+
+static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
+                                struct mlx5e_tc_flow *flow)
+{
+       struct list_head *next = flow->mod_hdr.next;
+
+       list_del(&flow->mod_hdr);
+
+       if (list_empty(next)) {
+               struct mlx5e_mod_hdr_entry *mh;
+
+               mh = list_entry(next, struct mlx5e_mod_hdr_entry, flows);
+
+               mlx5_modify_header_dealloc(priv->mdev, mh->mod_hdr_id);
+               hash_del(&mh->mod_hdr_hlist);
+               kfree(mh);
+       }
+}
+
 static struct mlx5_flow_handle *
 mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
                      struct mlx5e_tc_flow_parse_attr *parse_attr,
@@ -121,10 +251,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
        }
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
-               err = mlx5_modify_header_alloc(dev, MLX5_FLOW_NAMESPACE_KERNEL,
-                                              parse_attr->num_mod_hdr_actions,
-                                              parse_attr->mod_hdr_actions,
-                                              &attr->mod_hdr_id);
+               err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
                flow_act.modify_id = attr->mod_hdr_id;
                kfree(parse_attr->mod_hdr_actions);
                if (err) {
@@ -166,8 +293,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
        }
 err_create_ft:
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
-               mlx5_modify_header_dealloc(priv->mdev,
-                                          attr->mod_hdr_id);
+               mlx5e_detach_mod_hdr(priv, flow);
 err_create_mod_hdr_id:
        mlx5_fc_destroy(dev, counter);
 
@@ -177,6 +303,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
 static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
                                  struct mlx5e_tc_flow *flow)
 {
+       struct mlx5_nic_flow_attr *attr = flow->nic_attr;
        struct mlx5_fc *counter = NULL;
 
        counter = mlx5_flow_rule_counter(flow->rule);
@@ -188,9 +315,8 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
                priv->fs.tc.t = NULL;
        }
 
-       if (flow->nic_attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
-               mlx5_modify_header_dealloc(priv->mdev,
-                                          flow->nic_attr->mod_hdr_id);
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
+               mlx5e_detach_mod_hdr(priv, flow);
 }
 
 static void mlx5e_detach_encap(struct mlx5e_priv *priv,
@@ -213,10 +339,7 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
        }
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
-               err = mlx5_modify_header_alloc(priv->mdev, MLX5_FLOW_NAMESPACE_FDB,
-                                              parse_attr->num_mod_hdr_actions,
-                                              parse_attr->mod_hdr_actions,
-                                              &attr->mod_hdr_id);
+               err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
                kfree(parse_attr->mod_hdr_actions);
                if (err) {
                        rule = ERR_PTR(err);
@@ -231,9 +354,8 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
        return rule;
 
 err_add_rule:
-       if (flow->esw_attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
-               mlx5_modify_header_dealloc(priv->mdev,
-                                          attr->mod_hdr_id);
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
+               mlx5e_detach_mod_hdr(priv, flow);
 err_mod_hdr:
        mlx5_eswitch_del_vlan_action(esw, attr);
 err_add_vlan:
@@ -250,19 +372,18 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
 
        if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
                flow->flags &= ~MLX5E_TC_FLOW_OFFLOADED;
-               mlx5_eswitch_del_offloaded_rule(esw, flow->rule, flow->esw_attr);
+               mlx5_eswitch_del_offloaded_rule(esw, flow->rule, attr);
        }
 
-       mlx5_eswitch_del_vlan_action(esw, flow->esw_attr);
+       mlx5_eswitch_del_vlan_action(esw, attr);
 
-       if (flow->esw_attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) {
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) {
                mlx5e_detach_encap(priv, flow);
-               kvfree(flow->esw_attr->parse_attr);
+               kvfree(attr->parse_attr);
        }
 
-       if (flow->esw_attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
-               mlx5_modify_header_dealloc(priv->mdev,
-                                          attr->mod_hdr_id);
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
+               mlx5e_detach_mod_hdr(priv, flow);
 }
 
 void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
@@ -970,12 +1091,14 @@ static int offload_pedit_fields(struct pedit_headers *masks,
                                struct mlx5e_tc_flow_parse_attr *parse_attr)
 {
        struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
-       int i, action_size, nactions, max_actions, first, last, first_z;
+       int i, action_size, nactions, max_actions, first, last, next_z;
        void *s_masks_p, *a_masks_p, *vals_p;
        struct mlx5_fields *f;
        u8 cmd, field_bsize;
        u32 s_mask, a_mask;
        unsigned long mask;
+       __be32 mask_be32;
+       __be16 mask_be16;
        void *action;
 
        set_masks = &masks[TCA_PEDIT_KEY_EX_CMD_SET];
@@ -1029,11 +1152,19 @@ static int offload_pedit_fields(struct pedit_headers *masks,
 
                field_bsize = f->size * BITS_PER_BYTE;
 
-               first_z = find_first_zero_bit(&mask, field_bsize);
+               if (field_bsize == 32) {
+                       mask_be32 = *(__be32 *)&mask;
+                       mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
+               } else if (field_bsize == 16) {
+                       mask_be16 = *(__be16 *)&mask;
+                       mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
+               }
+
                first = find_first_bit(&mask, field_bsize);
+               next_z = find_next_zero_bit(&mask, field_bsize, first);
                last  = find_last_bit(&mask, field_bsize);
-               if (first > 0 || last != (field_bsize - 1) || first_z < last) {
-                       printk(KERN_WARNING "mlx5: partial rewrite (mask %lx) is currently not offloaded\n",
+               if (first < next_z && next_z < last) {
+                       printk(KERN_WARNING "mlx5: rewrite of few sub-fields (mask %lx) isn't offloaded\n",
                               mask);
                        return -EOPNOTSUPP;
                }
@@ -1042,17 +1173,17 @@ static int offload_pedit_fields(struct pedit_headers *masks,
                MLX5_SET(set_action_in, action, field, f->field);
 
                if (cmd == MLX5_ACTION_TYPE_SET) {
-                       MLX5_SET(set_action_in, action, offset, 0);
+                       MLX5_SET(set_action_in, action, offset, first);
                        /* length is num of bits to be written, zero means length of 32 */
-                       MLX5_SET(set_action_in, action, length, field_bsize);
+                       MLX5_SET(set_action_in, action, length, (last - first + 1));
                }
 
                if (field_bsize == 32)
-                       MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p));
+                       MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p) >> first);
                else if (field_bsize == 16)
-                       MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p));
+                       MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p) >> first);
                else if (field_bsize == 8)
-                       MLX5_SET(set_action_in, action, data, *(u8 *)vals_p);
+                       MLX5_SET(set_action_in, action, data, *(u8 *)vals_p >> first);
 
                action += action_size;
                nactions++;
@@ -1194,10 +1325,6 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
 
        tcf_exts_to_list(exts, &actions);
        list_for_each_entry(a, &actions, list) {
-               /* Only support a single action per rule */
-               if (attr->action)
-                       return -EINVAL;
-
                if (is_tcf_gact_shot(a)) {
                        attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
                        if (MLX5_CAP_FLOWTABLE(priv->mdev,
@@ -1942,6 +2069,8 @@ int mlx5e_tc_init(struct mlx5e_priv *priv)
 {
        struct mlx5e_tc_table *tc = &priv->fs.tc;
 
+       hash_init(tc->mod_hdr_tbl);
+
        tc->ht_params = mlx5e_tc_flow_ht_params;
        return rhashtable_init(&tc->ht, &tc->ht_params);
 }
index 81dfcd90b1f54b5430518080040801a63c63278e..37927156f258cb50cb29f0ea4d23a559b4f8a81f 100644 (file)
@@ -1769,6 +1769,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
        }
 
        hash_init(esw->offloads.encap_tbl);
+       hash_init(esw->offloads.mod_hdr_tbl);
        mutex_init(&esw->state_lock);
 
        for (vport_num = 0; vport_num < total_vports; vport_num++) {
index b746f62c8c79b17a64c0923665917170a075092a..834a33050969719ca6e13b27c11b6eb895c02257 100644 (file)
@@ -207,6 +207,7 @@ struct mlx5_esw_offload {
        struct mlx5_flow_group *vport_rx_group;
        struct mlx5_eswitch_rep *vport_reps;
        DECLARE_HASHTABLE(encap_tbl, 8);
+       DECLARE_HASHTABLE(mod_hdr_tbl, 8);
        u8 inline_mode;
        u64 num_flows;
        u8 encap;
index abb44a268563e4b12577278e62b34e7c553d594e..e750f07793b829de4b0383f93770f301e20eb196 100644 (file)
@@ -78,28 +78,33 @@ int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
                 MLX5_CMD_OP_CREATE_FLOW_TABLE);
 
        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);
+       MLX5_SET(create_flow_table_in, in, flow_table_context.level, level);
+       MLX5_SET(create_flow_table_in, in, flow_table_context.log_size, log_size);
        if (vport) {
                MLX5_SET(create_flow_table_in, in, vport_number, vport);
                MLX5_SET(create_flow_table_in, in, other_vport, 1);
        }
 
-       MLX5_SET(create_flow_table_in, in, decap_en, en_encap_decap);
-       MLX5_SET(create_flow_table_in, in, encap_en, en_encap_decap);
+       MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en,
+                en_encap_decap);
+       MLX5_SET(create_flow_table_in, in, flow_table_context.encap_en,
+                en_encap_decap);
 
        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);
+                       MLX5_SET(create_flow_table_in, in,
+                                flow_table_context.table_miss_action, 1);
+                       MLX5_SET(create_flow_table_in, in,
+                                flow_table_context.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,
+                       MLX5_SET(create_flow_table_in, in,
+                                flow_table_context.lag_master_next_table_id,
                                 next_ft->id);
                break;
        }
@@ -146,10 +151,10 @@ int mlx5_cmd_modify_flow_table(struct mlx5_core_dev *dev,
                         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);
+                                flow_table_context.lag_master_next_table_id, next_ft->id);
                } else {
                        MLX5_SET(modify_flow_table_in, in,
-                                lag_master_next_table_id, 0);
+                                flow_table_context.lag_master_next_table_id, 0);
                }
        } else {
                if (ft->vport) {
@@ -160,11 +165,14 @@ int mlx5_cmd_modify_flow_table(struct mlx5_core_dev *dev,
                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,
+                       MLX5_SET(modify_flow_table_in, in,
+                                flow_table_context.table_miss_action, 1);
+                       MLX5_SET(modify_flow_table_in, in,
+                                flow_table_context.table_miss_id,
                                 next_ft->id);
                } else {
-                       MLX5_SET(modify_flow_table_in, in, table_miss_mode, 0);
+                       MLX5_SET(modify_flow_table_in, in,
+                                flow_table_context.table_miss_action, 0);
                }
        }
 
index 56e96f6a0a45143afc69f5c71a2a9b852e4a91a5..32b044e953d22ae5ddbc2ffaa1f73ca4273db83d 100644 (file)
@@ -6627,6 +6627,24 @@ struct mlx5_ifc_create_flow_table_out_bits {
        u8         reserved_at_60[0x20];
 };
 
+struct mlx5_ifc_flow_table_context_bits {
+       u8         encap_en[0x1];
+       u8         decap_en[0x1];
+       u8         reserved_at_2[0x2];
+       u8         table_miss_action[0x4];
+       u8         level[0x8];
+       u8         reserved_at_10[0x8];
+       u8         log_size[0x8];
+
+       u8         reserved_at_20[0x8];
+       u8         table_miss_id[0x18];
+
+       u8         reserved_at_40[0x8];
+       u8         lag_master_next_table_id[0x18];
+
+       u8         reserved_at_60[0xe0];
+};
+
 struct mlx5_ifc_create_flow_table_in_bits {
        u8         opcode[0x10];
        u8         reserved_at_10[0x10];
@@ -6645,21 +6663,7 @@ struct mlx5_ifc_create_flow_table_in_bits {
 
        u8         reserved_at_a0[0x20];
 
-       u8         encap_en[0x1];
-       u8         decap_en[0x1];
-       u8         reserved_at_c2[0x2];
-       u8         table_miss_mode[0x4];
-       u8         level[0x8];
-       u8         reserved_at_d0[0x8];
-       u8         log_size[0x8];
-
-       u8         reserved_at_e0[0x8];
-       u8         table_miss_id[0x18];
-
-       u8         reserved_at_100[0x8];
-       u8         lag_master_next_table_id[0x18];
-
-       u8         reserved_at_120[0x80];
+       struct mlx5_ifc_flow_table_context_bits flow_table_context;
 };
 
 struct mlx5_ifc_create_flow_group_out_bits {
@@ -7291,7 +7295,8 @@ struct mlx5_ifc_ptys_reg_bits {
        u8         ib_link_width_oper[0x10];
        u8         ib_proto_oper[0x10];
 
-       u8         reserved_at_160[0x20];
+       u8         reserved_at_160[0x1c];
+       u8         connector_type[0x4];
 
        u8         eth_proto_lp_advertise[0x20];
 
@@ -7694,8 +7699,10 @@ struct mlx5_ifc_peir_reg_bits {
 };
 
 struct mlx5_ifc_pcam_enhanced_features_bits {
-       u8         reserved_at_0[0x7e];
+       u8         reserved_at_0[0x7c];
 
+       u8         ptys_connector_type[0x1];
+       u8         reserved_at_7d[0x1];
        u8         ppcnt_discard_group[0x1];
        u8         ppcnt_statistical_group[0x1];
 };
@@ -8277,17 +8284,7 @@ struct mlx5_ifc_modify_flow_table_in_bits {
        u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_at_c0[0x4];
-       u8         table_miss_mode[0x4];
-       u8         reserved_at_c8[0x18];
-
-       u8         reserved_at_e0[0x8];
-       u8         table_miss_id[0x18];
-
-       u8         reserved_at_100[0x8];
-       u8         lag_master_next_table_id[0x18];
-
-       u8         reserved_at_120[0x80];
+       struct mlx5_ifc_flow_table_context_bits flow_table_context;
 };
 
 struct mlx5_ifc_ets_tcn_config_reg_bits {
index e527732fb31bcc16791a93f1d45f5de2dd5d7649..c57d4b7de3a80203719f36319d17fb4794dd40b7 100644 (file)
@@ -92,6 +92,19 @@ enum mlx5e_link_mode {
        MLX5E_LINK_MODES_NUMBER,
 };
 
+enum mlx5e_connector_type {
+       MLX5E_PORT_UNKNOWN      = 0,
+       MLX5E_PORT_NONE                 = 1,
+       MLX5E_PORT_TP                   = 2,
+       MLX5E_PORT_AUI                  = 3,
+       MLX5E_PORT_BNC                  = 4,
+       MLX5E_PORT_MII                  = 5,
+       MLX5E_PORT_FIBRE                = 6,
+       MLX5E_PORT_DA                   = 7,
+       MLX5E_PORT_OTHER                = 8,
+       MLX5E_CONNECTOR_TYPE_NUMBER,
+};
+
 #define MLX5E_PROT_MASK(link_mode) (1 << link_mode)
 
 #define PORT_MODULE_EVENT_MODULE_STATUS_MASK 0xF