drivers/infiniband/hw/mlx5/mlx5_ib.h | 2 +
drivers/infiniband/hw/mlx5/mr.c | 12 +
drivers/net/ethernet/mellanox/mlx5/core/en.h | 31 ++
- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 235 +++++++++-
+ .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 235 ++++++++-
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c | 2 +
- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 519 ++++++++++++++++++++-
- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 128 ++++-
- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 92 ++++
+ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 533 ++++++++++++++++++++-
+ drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 150 +++++-
+ drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 108 +++++
.../net/ethernet/mellanox/mlx5/core/en_selftest.c | 8 +-
- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 205 ++++++++
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 287 +++++++++++
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.h | 2 +
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c | 32 ++
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 17 +
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 6 +
+ drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 2 +
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/health.c | 18 +
drivers/net/ethernet/mellanox/mlx5/core/lag.c | 47 ++
drivers/net/ethernet/mellanox/mlx5/core/main.c | 67 +++
.../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 3 +
include/linux/mlx5/driver.h | 3 +
- 23 files changed, 1462 insertions(+), 13 deletions(-)
+ 25 files changed, 1600 insertions(+), 13 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/ib_virt.c b/drivers/infiniband/hw/mlx5/ib_virt.c
index xxxxxxx..xxxxxxx xxxxxx
mlx5e_build_icosq_param(priv, icosq_log_wq_sz, &cparam->icosq);
mlx5e_build_rx_cq_param(priv, params, &cparam->rx_cq);
mlx5e_build_tx_cq_param(priv, params, &cparam->tx_cq);
-@@ -2765,8 +2840,10 @@ static int mlx5e_alloc_drop_rq(struct mlx5_core_dev *mdev,
+@@ -2709,8 +2784,14 @@ int mlx5e_open(struct net_device *netdev)
+ mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_UP);
+ mutex_unlock(&priv->state_lock);
+
++#ifdef HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON
+ if (mlx5e_vxlan_allowed(priv->mdev))
++#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_NDO_UDP_TUNNEL_ADD_EXTENDED)
+ udp_tunnel_get_rx_info(netdev);
++#elif defined(HAVE_NDO_ADD_VXLAN_PORT)
++ vxlan_get_rx_port(netdev);
++#endif
++#endif /* HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON */
+
+ return err;
+ }
+@@ -2765,8 +2846,10 @@ static int mlx5e_alloc_drop_rq(struct mlx5_core_dev *mdev,
if (err)
return err;
rq->mdev = mdev;
-@@ -3030,6 +3107,7 @@ void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv)
+@@ -3030,6 +3113,7 @@ void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv)
mlx5e_destroy_tir(priv->mdev, &priv->direct_tir[i]);
}
static int mlx5e_modify_channels_scatter_fcs(struct mlx5e_channels *chs, bool enable)
{
int err = 0;
-@@ -3043,6 +3121,7 @@ static int mlx5e_modify_channels_scatter_fcs(struct mlx5e_channels *chs, bool en
+@@ -3043,6 +3127,7 @@ static int mlx5e_modify_channels_scatter_fcs(struct mlx5e_channels *chs, bool en
return 0;
}
static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd)
{
-@@ -3058,15 +3137,23 @@ static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd)
+@@ -3058,15 +3143,23 @@ static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd)
return 0;
}
if (tc && tc != MLX5E_MAX_NUM_TC)
return -EINVAL;
-@@ -3091,10 +3178,25 @@ out:
+@@ -3091,10 +3184,25 @@ out:
return err;
}
switch (cls_flower->command) {
case TC_CLSFLOWER_REPLACE:
return mlx5e_configure_flower(priv, cls_flower);
-@@ -3107,6 +3209,7 @@ static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv,
+@@ -3107,6 +3215,7 @@ static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv,
}
}
int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
void *cb_priv)
{
-@@ -3144,14 +3247,25 @@ static int mlx5e_setup_tc_block(struct net_device *dev,
+@@ -3144,14 +3253,25 @@ static int mlx5e_setup_tc_block(struct net_device *dev,
}
}
#endif
#endif
case TC_SETUP_QDISC_MQPRIO:
return mlx5e_setup_tc_mqprio(dev, type_data);
-@@ -3159,15 +3273,79 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
+@@ -3159,15 +3279,79 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
return -EOPNOTSUPP;
}
}
if (mlx5e_is_uplink_rep(priv)) {
stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok);
stats->rx_bytes = PPORT_802_3_GET(pstats, a_octets_received_ok);
-@@ -3200,6 +3378,10 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
+@@ -3200,6 +3384,10 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
*/
stats->multicast =
VPORT_COUNTER_GET(vstats, received_eth_multicast.packets);
}
static void mlx5e_set_rx_mode(struct net_device *dev)
-@@ -3236,7 +3418,11 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
+@@ -3236,7 +3424,11 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
typedef int (*mlx5e_feature_handler)(struct net_device *netdev, bool enable);
{
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5_core_dev *mdev = priv->mdev;
-@@ -3245,7 +3431,9 @@ static int set_feature_lro(struct net_device *netdev, bool enable)
+@@ -3245,7 +3437,9 @@ static int set_feature_lro(struct net_device *netdev, bool enable)
int err = 0;
bool reset;
old_params = &priv->channels.params;
reset = test_bit(MLX5E_STATE_OPENED, &priv->state);
-@@ -3271,10 +3459,13 @@ static int set_feature_lro(struct net_device *netdev, bool enable)
+@@ -3271,10 +3465,13 @@ static int set_feature_lro(struct net_device *netdev, bool enable)
mlx5e_switch_priv_channels(priv, &new_channels, mlx5e_modify_tirs_lro);
out:
static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3286,7 +3477,9 @@ static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)
+@@ -3286,7 +3483,9 @@ static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)
return 0;
}
static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3299,7 +3492,9 @@ static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
+@@ -3299,7 +3498,9 @@ static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
return 0;
}
static int set_feature_rx_all(struct net_device *netdev, bool enable)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3307,7 +3502,9 @@ static int set_feature_rx_all(struct net_device *netdev, bool enable)
+@@ -3307,7 +3508,9 @@ static int set_feature_rx_all(struct net_device *netdev, bool enable)
return mlx5_set_port_fcs(mdev, !enable);
}
static int set_feature_rx_fcs(struct net_device *netdev, bool enable)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3324,7 +3521,9 @@ static int set_feature_rx_fcs(struct net_device *netdev, bool enable)
+@@ -3324,7 +3527,9 @@ static int set_feature_rx_fcs(struct net_device *netdev, bool enable)
return err;
}
static int set_feature_rx_vlan(struct net_device *netdev, bool enable)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3345,6 +3544,7 @@ unlock:
+@@ -3345,6 +3550,7 @@ unlock:
return err;
}
#ifdef CONFIG_RFS_ACCEL
static int set_feature_arfs(struct net_device *netdev, bool enable)
-@@ -3361,13 +3561,23 @@ static int set_feature_arfs(struct net_device *netdev, bool enable)
+@@ -3361,13 +3567,23 @@ static int set_feature_arfs(struct net_device *netdev, bool enable)
}
#endif
bool enable = !!(wanted_features & feature);
int err;
-@@ -3376,17 +3586,28 @@ static int mlx5e_handle_feature(struct net_device *netdev,
+@@ -3376,17 +3592,28 @@ static int mlx5e_handle_feature(struct net_device *netdev,
err = feature_handler(netdev, enable);
if (err) {
{
netdev_features_t oper_features = netdev->features;
int err = 0;
-@@ -3412,7 +3633,9 @@ static int mlx5e_set_features(struct net_device *netdev,
+@@ -3412,7 +3639,9 @@ static int mlx5e_set_features(struct net_device *netdev,
return 0;
}
static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
netdev_features_t features)
{
-@@ -3431,6 +3654,7 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
+@@ -3431,6 +3660,7 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
return features;
}
static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
{
-@@ -3476,8 +3700,14 @@ out:
+@@ -3476,8 +3706,14 @@ out:
return err;
}
struct hwtstamp_config config;
int err;
-@@ -3540,6 +3770,7 @@ int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr)
+@@ -3540,6 +3776,7 @@ int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr)
sizeof(config)) ? -EFAULT : 0;
}
int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr)
{
struct hwtstamp_config *cfg = &priv->tstamp;
-@@ -3549,6 +3780,7 @@ int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr)
+@@ -3549,6 +3786,7 @@ int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr)
return copy_to_user(ifr->ifr_data, cfg, sizeof(*cfg)) ? -EFAULT : 0;
}
static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
-@@ -3556,14 +3788,19 @@ static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+@@ -3556,14 +3794,19 @@ static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
switch (cmd) {
case SIOCSHWTSTAMP:
#ifdef CONFIG_MLX5_ESWITCH
static int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
{
-@@ -3572,20 +3809,31 @@ static int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
+@@ -3572,20 +3815,31 @@ static int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
return mlx5_eswitch_set_vport_mac(mdev->priv.eswitch, vf + 1, mac);
}
static int mlx5e_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
{
struct mlx5e_priv *priv = netdev_priv(dev);
-@@ -3593,7 +3841,9 @@ static int mlx5e_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
+@@ -3593,7 +3847,9 @@ static int mlx5e_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
return mlx5_eswitch_set_vport_spoofchk(mdev->priv.eswitch, vf + 1, setting);
}
static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting)
{
struct mlx5e_priv *priv = netdev_priv(dev);
-@@ -3601,17 +3851,40 @@ static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting)
+@@ -3601,17 +3857,40 @@ static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting)
return mlx5_eswitch_set_vport_trust(mdev->priv.eswitch, vf + 1, setting);
}
static int mlx5_vport_link2ifla(u8 esw_link)
{
switch (esw_link) {
-@@ -3633,7 +3906,9 @@ static int mlx5_ifla_link2vport(u8 ifla_link)
+@@ -3633,7 +3912,9 @@ static int mlx5_ifla_link2vport(u8 ifla_link)
}
return MLX5_ESW_VPORT_ADMIN_STATE_AUTO;
}
static int mlx5e_set_vf_link_state(struct net_device *dev, int vf,
int link_state)
{
-@@ -3643,7 +3918,9 @@ static int mlx5e_set_vf_link_state(struct net_device *dev, int vf,
+@@ -3643,7 +3924,9 @@ static int mlx5e_set_vf_link_state(struct net_device *dev, int vf,
return mlx5_eswitch_set_vport_state(mdev->priv.eswitch, vf + 1,
mlx5_ifla_link2vport(link_state));
}
static int mlx5e_get_vf_config(struct net_device *dev,
int vf, struct ifla_vf_info *ivi)
{
-@@ -3654,10 +3931,14 @@ static int mlx5e_get_vf_config(struct net_device *dev,
+@@ -3654,10 +3937,14 @@ static int mlx5e_get_vf_config(struct net_device *dev,
err = mlx5_eswitch_get_vport_config(mdev->priv.eswitch, vf + 1, ivi);
if (err)
return err;
static int mlx5e_get_vf_stats(struct net_device *dev,
int vf, struct ifla_vf_stats *vf_stats)
{
-@@ -3669,6 +3950,8 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
+@@ -3669,6 +3956,8 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
}
#endif
static void mlx5e_add_vxlan_port(struct net_device *netdev,
struct udp_tunnel_info *ti)
{
-@@ -3696,15 +3979,44 @@ static void mlx5e_del_vxlan_port(struct net_device *netdev,
+@@ -3696,15 +3985,44 @@ static void mlx5e_del_vxlan_port(struct net_device *netdev,
mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 0);
}
+
+ mlx5e_vxlan_queue_work(priv, sa_family, be16_to_cpu(port), 1);
+}
-
++
+static void mlx5e_del_vxlan_port(struct net_device *netdev,
+ sa_family_t sa_family, __be16 port)
+{
+}
+#endif
+#endif /* HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON */
-+
+
+#ifdef HAVE_NETDEV_FEATURES_T
static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
struct sk_buff *skb,
switch (vlan_get_protocol(skb)) {
case htons(ETH_P_IP):
-@@ -3720,6 +4032,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
+@@ -3720,6 +4038,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
switch (proto) {
case IPPROTO_GRE:
return features;
case IPPROTO_UDP:
udph = udp_hdr(skb);
port = be16_to_cpu(udph->dest);
-@@ -3727,6 +4040,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
+@@ -3727,6 +4046,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
/* Verify if UDP port is being offloaded by HW */
if (mlx5e_vxlan_lookup_port(priv, port))
return features;
}
out:
-@@ -3740,8 +4054,14 @@ static netdev_features_t mlx5e_features_check(struct sk_buff *skb,
+@@ -3740,8 +4060,14 @@ static netdev_features_t mlx5e_features_check(struct sk_buff *skb,
{
struct mlx5e_priv *priv = netdev_priv(netdev);
#ifdef CONFIG_MLX5_EN_IPSEC
if (mlx5e_ipsec_feature_check(skb, netdev, features))
-@@ -3756,6 +4076,31 @@ static netdev_features_t mlx5e_features_check(struct sk_buff *skb,
+@@ -3756,6 +4082,31 @@ static netdev_features_t mlx5e_features_check(struct sk_buff *skb,
return features;
}
static bool mlx5e_tx_timeout_eq_recover(struct net_device *dev,
struct mlx5e_txqsq *sq)
{
-@@ -3832,6 +4177,7 @@ static void mlx5e_tx_timeout(struct net_device *dev)
+@@ -3832,6 +4183,7 @@ static void mlx5e_tx_timeout(struct net_device *dev)
queue_work(priv->wq, &priv->tx_timeout_work);
}
static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3848,11 +4194,13 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
+@@ -3848,11 +4200,13 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
goto unlock;
}
was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
/* no need for full reset when exchanging programs */
-@@ -3901,6 +4249,9 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
+@@ -3901,6 +4255,9 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
set_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state);
/* napi_schedule in case we have missed anything */
napi_schedule(&c->napi);
if (old_prog)
-@@ -3912,6 +4263,7 @@ unlock:
+@@ -3912,6 +4269,7 @@ unlock:
return err;
}
static u32 mlx5e_xdp_query(struct net_device *dev)
{
struct mlx5e_priv *priv = netdev_priv(dev);
-@@ -3926,6 +4278,14 @@ static u32 mlx5e_xdp_query(struct net_device *dev)
+@@ -3926,6 +4284,14 @@ static u32 mlx5e_xdp_query(struct net_device *dev)
return prog_id;
}
static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
{
-@@ -3933,13 +4293,18 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
+@@ -3933,13 +4299,18 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
case XDP_SETUP_PROG:
return mlx5e_xdp_set(dev, xdp->prog);
case XDP_QUERY_PROG:
#ifdef CONFIG_NET_POLL_CONTROLLER
/* Fake "interrupt" called by netpoll (eg netconsole) to send skbs without
-@@ -3961,44 +4326,143 @@ static const struct net_device_ops mlx5e_netdev_ops = {
+@@ -3961,43 +4332,142 @@ static const struct net_device_ops mlx5e_netdev_ops = {
.ndo_open = mlx5e_open,
.ndo_stop = mlx5e_close,
.ndo_start_xmit = mlx5e_xmit,
.ndo_get_offload_stats = mlx5e_get_offload_stats,
+#elif defined(HAVE_NDO_GET_OFFLOAD_STATS_EXTENDED)
+ .extended.ndo_get_offload_stats = mlx5e_get_offload_stats,
- #endif
++#endif
+#endif /* CONFIG_MLX5_ESWITCH */
- };
-
++};
++
+#ifdef HAVE_NET_DEVICE_OPS_EXT
+static const struct net_device_ops_ext mlx5e_netdev_ops_ext= {
+ .size = sizeof(struct net_device_ops_ext),
+#endif
+#ifdef HAVE_NETDEV_OPS_EXT_NDO_SET_VF_LINK_STATE
+ .ndo_set_vf_link_state = mlx5e_set_vf_link_state,
-+#endif
-+};
+ #endif
+ };
+#endif /* HAVE_NET_DEVICE_OPS_EXT */
-+
+
static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
{
- if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
-@@ -4033,13 +4497,49 @@ void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
+@@ -4033,13 +4503,49 @@ void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
indirection_rqt[i] = i % num_channels;
}
mlx5_core_dbg_once(mdev, "Max link speed = %d, PCI BW = %d\n",
link_speed, pci_bw);
-@@ -4238,7 +4738,9 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
+@@ -4238,7 +4744,9 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
netdev->vlan_features |= NETIF_F_TSO;
netdev->vlan_features |= NETIF_F_TSO6;
netdev->vlan_features |= NETIF_F_RXCSUM;
netdev->hw_enc_features |= NETIF_F_HW_VLAN_CTAG_TX;
netdev->hw_enc_features |= NETIF_F_HW_VLAN_CTAG_RX;
-@@ -4447,7 +4949,9 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
+@@ -4253,12 +4761,16 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
+ netdev->hw_features |= NETIF_F_HW_VLAN_STAG_TX;
+
+ if (mlx5e_vxlan_allowed(mdev) || MLX5_CAP_ETH(mdev, tunnel_stateless_gre)) {
++#ifdef HAVE_NETIF_F_GSO_PARTIAL
+ netdev->hw_features |= NETIF_F_GSO_PARTIAL;
++#endif
+ netdev->hw_enc_features |= NETIF_F_IP_CSUM;
+ netdev->hw_enc_features |= NETIF_F_IPV6_CSUM;
+ netdev->hw_enc_features |= NETIF_F_TSO;
+ netdev->hw_enc_features |= NETIF_F_TSO6;
++#ifdef HAVE_NETIF_F_GSO_PARTIAL
+ netdev->hw_enc_features |= NETIF_F_GSO_PARTIAL;
++#endif
+ }
+
+ if (mlx5e_vxlan_allowed(mdev)) {
+@@ -4266,7 +4778,9 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
+ NETIF_F_GSO_UDP_TUNNEL_CSUM;
+ netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL |
+ NETIF_F_GSO_UDP_TUNNEL_CSUM;
++#ifdef HAVE_NETIF_F_GSO_PARTIAL
+ netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
++#endif
+ }
+
+ if (MLX5_CAP_ETH(mdev, tunnel_stateless_gre)) {
+@@ -4274,8 +4788,10 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
+ NETIF_F_GSO_GRE_CSUM;
+ netdev->hw_enc_features |= NETIF_F_GSO_GRE |
+ NETIF_F_GSO_GRE_CSUM;
++#ifdef HAVE_NETIF_F_GSO_PARTIAL
+ netdev->gso_partial_features |= NETIF_F_GSO_GRE |
+ NETIF_F_GSO_GRE_CSUM;
++#endif
+ }
+
+ mlx5_query_port_fcs(mdev, &fcs_supported, &fcs_enabled);
+@@ -4447,7 +4963,9 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
{
struct net_device *netdev = priv->netdev;
struct mlx5_core_dev *mdev = priv->mdev;
mlx5e_init_l2_addr(priv);
-@@ -4455,10 +4959,17 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
+@@ -4455,10 +4973,17 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
if (!netif_running(netdev))
mlx5_set_port_admin_status(mdev, MLX5_PORT_DOWN);
index xxxxxxx..xxxxxxx xxxxxx
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
-@@ -706,6 +706,7 @@ static int mlx5e_rep_close(struct net_device *dev)
+@@ -290,6 +290,7 @@ void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
+ mlx5e_sqs2vport_stop(esw, rep);
+ }
+
++#ifdef HAVE_TCF_TUNNEL_INFO
+ static void mlx5e_rep_neigh_update_init_interval(struct mlx5e_rep_priv *rpriv)
+ {
+ #if IS_ENABLED(CONFIG_IPV6)
+@@ -421,9 +422,13 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_neigh_hash_entry *nhe = NULL;
+ struct mlx5e_neigh m_neigh = {};
++#ifdef NETEVENT_DELAY_PROBE_TIME_UPDATE
+ struct neigh_parms *p;
++#endif
+ struct neighbour *n;
++#ifdef NETEVENT_DELAY_PROBE_TIME_UPDATE
+ bool found = false;
++#endif
+
+ switch (event) {
+ case NETEVENT_NEIGH_UPDATE:
+@@ -436,7 +441,9 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+ return NOTIFY_DONE;
+
+ m_neigh.dev = n->dev;
++#ifdef HAVE_TCF_TUNNEL_INFO
+ m_neigh.family = n->ops->family;
++#endif
+ memcpy(&m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
+
+ /* We are in atomic context and can't take RTNL mutex, so use
+@@ -469,6 +476,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+ spin_unlock_bh(&neigh_update->encap_lock);
+ break;
+
++#ifdef NETEVENT_DELAY_PROBE_TIME_UPDATE
+ case NETEVENT_DELAY_PROBE_TIME_UPDATE:
+ p = ptr;
+
+@@ -505,9 +513,11 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+ mlx5_fc_update_sampling_interval(priv->mdev,
+ neigh_update->min_interval);
+ break;
++#endif
+ }
+ return NOTIFY_DONE;
+ }
++#endif /* HAVE_TCF_TUNNEL_INFO */
+
+ static const struct rhashtable_params mlx5e_neigh_ht_params = {
+ .head_offset = offsetof(struct mlx5e_neigh_hash_entry, rhash_node),
+@@ -526,6 +536,7 @@ static int mlx5e_rep_neigh_init(struct mlx5e_rep_priv *rpriv)
+ return err;
+
+ INIT_LIST_HEAD(&neigh_update->neigh_list);
++#ifdef HAVE_TCF_TUNNEL_INFO
+ spin_lock_init(&neigh_update->encap_lock);
+ INIT_DELAYED_WORK(&neigh_update->neigh_stats_work,
+ mlx5e_rep_neigh_stats_work);
+@@ -539,12 +550,14 @@ static int mlx5e_rep_neigh_init(struct mlx5e_rep_priv *rpriv)
+
+ out_err:
+ rhashtable_destroy(&neigh_update->neigh_ht);
++#endif
+ return err;
+ }
+
+ static void mlx5e_rep_neigh_cleanup(struct mlx5e_rep_priv *rpriv)
+ {
+ struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
++#ifdef HAVE_TCF_TUNNEL_INFO
+ struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
+
+ unregister_netevent_notifier(&neigh_update->netevent_nb);
+@@ -552,10 +565,12 @@ static void mlx5e_rep_neigh_cleanup(struct mlx5e_rep_priv *rpriv)
+ flush_workqueue(priv->wq); /* flush neigh update works */
+
+ cancel_delayed_work_sync(&rpriv->neigh_update.neigh_stats_work);
++#endif
+
+ rhashtable_destroy(&neigh_update->neigh_ht);
+ }
+
++#ifdef HAVE_TCF_TUNNEL_INFO
+ static int mlx5e_rep_neigh_entry_insert(struct mlx5e_priv *priv,
+ struct mlx5e_neigh_hash_entry *nhe)
+ {
+@@ -578,14 +593,18 @@ static void mlx5e_rep_neigh_entry_remove(struct mlx5e_priv *priv,
+ {
+ struct mlx5e_rep_priv *rpriv = priv->ppriv;
+
++#ifdef HAVE_TCF_TUNNEL_INFO
+ spin_lock_bh(&rpriv->neigh_update.encap_lock);
++#endif
+
+ list_del(&nhe->neigh_list);
+
+ rhashtable_remove_fast(&rpriv->neigh_update.neigh_ht,
+ &nhe->rhash_node,
+ mlx5e_neigh_ht_params);
++#ifdef HAVE_TCF_TUNNEL_INFO
+ spin_unlock_bh(&rpriv->neigh_update.encap_lock);
++#endif
+ }
+
+ /* This function must only be called under RTNL lock or under the
+@@ -667,6 +686,7 @@ void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv,
+ if (list_empty(&nhe->encap_list))
+ mlx5e_rep_neigh_entry_destroy(priv, nhe);
+ }
++#endif /* HAVE_TCF_TUNNEL_INFO */
+
+ static int mlx5e_rep_open(struct net_device *dev)
+ {
+@@ -706,6 +726,7 @@ static int mlx5e_rep_close(struct net_device *dev)
return ret;
}
static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
char *buf, size_t len)
{
-@@ -720,11 +721,35 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
+@@ -720,11 +741,35 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
return 0;
}
switch (cls_flower->command) {
case TC_CLSFLOWER_REPLACE:
return mlx5e_configure_flower(priv, cls_flower);
-@@ -736,7 +761,9 @@ mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
+@@ -736,7 +781,9 @@ mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
return -EOPNOTSUPP;
}
}
static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
void *cb_priv)
{
-@@ -772,17 +799,47 @@ static int mlx5e_rep_setup_tc_block(struct net_device *dev,
+@@ -772,17 +819,47 @@ static int mlx5e_rep_setup_tc_block(struct net_device *dev,
return -EOPNOTSUPP;
}
}
bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
{
-@@ -801,6 +858,7 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
+@@ -801,6 +878,7 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
return false;
}
static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
{
struct mlx5e_rep_priv *rpriv = priv->ppriv;
-@@ -824,6 +882,7 @@ bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
+@@ -824,7 +902,9 @@ bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
return false;
}
+#endif
++#if defined(HAVE_NDO_GET_OFFLOAD_STATS) || defined(HAVE_NDO_GET_OFFLOAD_STATS_EXTENDED)
static int
mlx5e_get_sw_stats64(const struct net_device *dev,
-@@ -853,12 +912,25 @@ int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+@@ -852,13 +932,27 @@ int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
+
return -EINVAL;
}
++#endif
-static void
-mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
}
static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
-@@ -869,11 +941,36 @@ static const struct net_device_ops mlx5e_netdev_ops_rep = {
+@@ -869,11 +963,36 @@ static const struct net_device_ops mlx5e_netdev_ops_rep = {
.ndo_open = mlx5e_rep_open,
.ndo_stop = mlx5e_rep_close,
.ndo_start_xmit = mlx5e_xmit,
};
static void mlx5e_build_rep_params(struct mlx5_core_dev *mdev,
-@@ -906,7 +1003,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
+@@ -906,7 +1025,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
netdev->ethtool_ops = &mlx5e_rep_ethtool_ops;
netdev->features |= NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
netdev->hw_features |= NETIF_F_HW_TC;
-@@ -1071,7 +1170,9 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
+@@ -1071,7 +1192,9 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
struct mlx5e_rep_priv *uplink_rpriv;
struct mlx5e_rep_priv *rpriv;
struct net_device *netdev;
int err;
rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
-@@ -1106,11 +1207,18 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
+@@ -1106,11 +1229,18 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
}
uplink_rpriv = mlx5_eswitch_get_uplink_priv(dev->priv.eswitch, REP_ETH);
err = register_netdev(netdev);
if (err) {
-@@ -1122,10 +1230,17 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
+@@ -1122,10 +1252,17 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
return 0;
err_egdev_cleanup:
mlx5e_rep_neigh_cleanup(rpriv);
err_detach_netdev:
-@@ -1145,14 +1260,23 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
+@@ -1145,14 +1282,23 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_rep_priv *uplink_rpriv;
void *ppriv = priv->ppriv;
index xxxxxxx..xxxxxxx xxxxxx
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
-@@ -758,6 +758,7 @@ static inline void mlx5e_complete_rx_cqe(struct mlx5e_rq *rq,
+@@ -200,7 +200,11 @@ static inline bool mlx5e_rx_cache_get(struct mlx5e_rq *rq,
+ return false;
+ }
+
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
+ if (page_ref_count(cache->page_cache[cache->head].page) != 1) {
++#else
++ if (atomic_read(&cache->page_cache[cache->head].page->_count) != 1) {
++#endif
+ rq->stats.cache_busy++;
+ return false;
+ }
+@@ -306,7 +310,11 @@ static inline void mlx5e_add_skb_frag_mpwqe(struct mlx5e_rq *rq,
+ dma_sync_single_for_cpu(rq->pdev,
+ di->addr + frag_offset,
+ len, DMA_FROM_DEVICE);
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
+ page_ref_inc(di->page);
++#else
++ atomic_inc(&di->page->_count);
++#endif
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+ di->page, frag_offset, len, truesize);
+ }
+@@ -758,6 +766,7 @@ static inline void mlx5e_complete_rx_cqe(struct mlx5e_rq *rq,
mlx5e_build_rx_skb(cqe, cqe_bcnt, rq, skb);
}
static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
{
struct mlx5_wq_cyc *wq = &sq->wq;
-@@ -771,7 +772,12 @@ static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
+@@ -771,7 +780,12 @@ static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
struct mlx5e_dma_info *di,
{
struct mlx5e_xdpsq *sq = &rq->xdpsq;
struct mlx5_wq_cyc *wq = &sq->wq;
-@@ -782,8 +788,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
+@@ -782,8 +796,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
struct mlx5_wqe_eth_seg *eseg = &wqe->eth;
struct mlx5_wqe_data_seg *dseg;
unsigned int dma_len = xdp->data_end - xdp->data;
prefetchw(wqe);
-@@ -792,6 +801,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
+@@ -792,6 +809,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
rq->stats.xdp_drop++;
return false;
}
if (unlikely(!mlx5e_wqc_has_room_for(wq, sq->cc, sq->pc, 1))) {
if (sq->db.doorbell) {
-@@ -811,7 +825,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
+@@ -811,7 +833,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
/* copy the inline part if required */
if (sq->min_inline_mode != MLX5_INLINE_MODE_NONE) {
eseg->inline_hdr.sz = cpu_to_be16(MLX5E_XDP_MIN_INLINE);
dma_len -= MLX5E_XDP_MIN_INLINE;
dma_addr += MLX5E_XDP_MIN_INLINE;
-@@ -838,43 +856,75 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
+@@ -838,43 +864,75 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
}
/* returns true if packet was consumed by xdp */
static inline
struct sk_buff *mlx5e_build_linear_skb(struct mlx5e_rq *rq, void *va,
u32 frag_size, u16 headroom,
-@@ -892,6 +942,7 @@ struct sk_buff *mlx5e_build_linear_skb(struct mlx5e_rq *rq, void *va,
+@@ -892,6 +950,7 @@ struct sk_buff *mlx5e_build_linear_skb(struct mlx5e_rq *rq, void *va,
return skb;
}
static inline
struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
-@@ -901,7 +952,9 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
+@@ -901,7 +960,9 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
u16 rx_headroom = rq->buff.headroom;
struct sk_buff *skb;
void *va, *data;
u32 frag_size;
va = page_address(di->page) + wi->offset;
-@@ -918,19 +971,34 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
+@@ -918,19 +979,38 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
return NULL;
}
return NULL;
/* queue up for recycling/reuse */
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
page_ref_inc(di->page);
++#else
++ atomic_inc(&di->page->_count);
++#endif
+#ifdef HAVE_BUILD_SKB
+ skb_reserve(skb, rx_headroom);
return skb;
}
-@@ -1072,7 +1140,9 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
+@@ -1072,7 +1152,9 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
struct sk_buff *skb;
void *va, *data;
u32 frag_size;
va = page_address(di->page) + head_offset;
data = va + rx_headroom;
-@@ -1082,22 +1152,38 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
+@@ -1082,21 +1164,41 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
frag_size, DMA_FROM_DEVICE);
prefetch(data);
return NULL;
/* queue up for recycling/reuse */
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
page_ref_inc(di->page);
-
++#else
++ atomic_inc(&di->page->_count);
++#endif
++
+#ifdef HAVE_BUILD_SKB
+ skb_reserve(skb, rx_headroom);
+ skb_put(skb, cqe_bcnt);
+#endif
-+
+
return skb;
}
-
-@@ -1148,7 +1234,9 @@ mpwrq_cqe_out:
+@@ -1148,7 +1250,9 @@ mpwrq_cqe_out:
int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
{
struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq);
struct mlx5_cqe64 *cqe;
int work_done = 0;
-@@ -1162,7 +1250,9 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
+@@ -1162,7 +1266,9 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
if (!cqe)
return 0;
do {
if (mlx5_get_cqe_format(cqe) == MLX5_COMPRESSED) {
-@@ -1177,10 +1267,12 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
+@@ -1177,10 +1283,12 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
rq->handle_rx_cqe(rq, cqe);
} while ((++work_done < budget) && (cqe = mlx5_cqwq_get_cqe(&cq->wq)));
#include <net/arp.h>
#include "en.h"
#include "en_rep.h"
-@@ -56,7 +65,9 @@
+@@ -53,11 +62,19 @@
+ #include "vxlan.h"
+ #include "fs_core.h"
+
++#ifdef HAVE_TCF_TUNNEL_INFO
++#define MLNX_HAIRPIN_SUPPORT
++#endif
++
struct mlx5_nic_flow_attr {
u32 action;
u32 flow_tag;
+#ifdef HAVE_TCF_PEDIT_TCFP_KEYS_EX
u32 mod_hdr_id;
+#endif
++#ifdef MLNX_HAIRPIN_SUPPORT
u32 hairpin_tirn;
++#endif
struct mlx5_flow_table *hairpin_ft;
};
-@@ -74,8 +85,12 @@ struct mlx5e_tc_flow {
+
+@@ -65,8 +82,10 @@ enum {
+ MLX5E_TC_FLOW_ESWITCH = BIT(0),
+ MLX5E_TC_FLOW_NIC = BIT(1),
+ MLX5E_TC_FLOW_OFFLOADED = BIT(2),
++#ifdef MLNX_HAIRPIN_SUPPORT
+ MLX5E_TC_FLOW_HAIRPIN = BIT(3),
+ MLX5E_TC_FLOW_HAIRPIN_RSS = BIT(4),
++#endif
+ };
+
+ struct mlx5e_tc_flow {
+@@ -74,9 +93,15 @@ struct mlx5e_tc_flow {
u64 cookie;
u8 flags;
struct mlx5_flow_handle *rule;
+#ifdef HAVE_TCF_PEDIT_TCFP_KEYS_EX
struct list_head mod_hdr; /* flows sharing the same mod hdr ID */
+#endif
++#ifdef MLNX_HAIRPIN_SUPPORT
struct list_head hairpin; /* flows sharing the same hairpin */
++#endif
union {
struct mlx5_esw_flow_attr esw_attr[0];
-@@ -84,17 +99,25 @@ struct mlx5e_tc_flow {
+ struct mlx5_nic_flow_attr nic_attr[0];
+@@ -84,21 +109,30 @@ struct mlx5e_tc_flow {
};
struct mlx5e_tc_flow_parse_attr {
#define MLX5E_TC_TABLE_NUM_GROUPS 4
#define MLX5E_TC_TABLE_MAX_GROUP_SIZE (1 << 16)
-@@ -125,6 +148,7 @@ struct mlx5e_hairpin_entry {
+
++#ifdef MLNX_HAIRPIN_SUPPORT
+ struct mlx5e_hairpin {
+ struct mlx5_hairpin *pair;
+
+@@ -124,7 +158,9 @@ struct mlx5e_hairpin_entry {
+ u8 prio;
struct mlx5e_hairpin *hp;
};
++#endif
+#ifdef HAVE_TCF_PEDIT_TCFP_KEYS_EX
struct mod_hdr_key {
int num_actions;
void *actions;
-@@ -253,6 +277,7 @@ static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
+@@ -253,7 +289,9 @@ static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
kfree(mh);
}
}
+#endif /* HAVE_TCF_PEDIT_TCFP_KEYS_EX */
++#ifdef MLNX_HAIRPIN_SUPPORT
static
struct mlx5_core_dev *mlx5e_hairpin_get_mdev(struct net *net, int ifindex)
-@@ -715,6 +740,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+ {
+@@ -664,8 +702,13 @@ static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv,
+ kfree(hpe);
+ }
+ }
++#endif /* MLNX_HAIRPIN_SUPPORT */
+
++#ifdef HAVE_TCF_TUNNEL_INFO
+ static struct mlx5_flow_handle *
++#else
++static int
++#endif
+ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+ struct mlx5e_tc_flow_parse_attr *parse_attr,
+ struct mlx5e_tc_flow *flow)
+@@ -684,6 +727,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+ bool table_created = false;
+ int err, dest_ix = 0;
+
++#ifdef MLNX_HAIRPIN_SUPPORT
+ if (flow->flags & MLX5E_TC_FLOW_HAIRPIN) {
+ err = mlx5e_hairpin_flow_add(priv, flow, parse_attr);
+ if (err) {
+@@ -703,18 +747,30 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+ dest[dest_ix].ft = priv->fs.vlan.ft.t;
+ dest_ix++;
+ }
++#else
++ if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
++ dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
++ dest[dest_ix].ft = priv->fs.vlan.ft.t;
++ dest_ix++;
++ }
++#endif
+
+ if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+ counter = mlx5_fc_create(dev, true);
+ if (IS_ERR(counter)) {
++#ifdef MLNX_HAIRPIN_SUPPORT
+ rule = ERR_CAST(counter);
+ goto err_fc_create;
++#else
++ return PTR_ERR(counter);
++#endif
+ }
+ dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+ dest[dest_ix].counter = counter;
dest_ix++;
}
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
flow_act.modify_id = attr->mod_hdr_id;
-@@ -724,6 +750,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+@@ -724,6 +780,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
goto err_create_mod_hdr_id;
}
}
if (IS_ERR_OR_NULL(priv->fs.tc.t)) {
int tc_grp_size, tc_tbl_size;
-@@ -768,9 +795,11 @@ err_add_rule:
+@@ -760,7 +817,11 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+ if (IS_ERR(rule))
+ goto err_add_rule;
+
++#ifdef HAVE_TCF_TUNNEL_INFO
+ return rule;
++#else
++ return 0;
++#endif
+
+ err_add_rule:
+ if (table_created) {
+@@ -768,21 +829,31 @@ err_add_rule:
priv->fs.tc.t = NULL;
}
err_create_ft:
err_create_mod_hdr_id:
+#endif
mlx5_fc_destroy(dev, counter);
++#ifdef MLNX_HAIRPIN_SUPPORT
err_fc_create:
if (flow->flags & MLX5E_TC_FLOW_HAIRPIN)
-@@ -782,7 +811,9 @@ err_add_hairpin_flow:
+ mlx5e_hairpin_flow_del(priv, flow);
+ err_add_hairpin_flow:
++#endif
++#ifdef HAVE_TCF_TUNNEL_INFO
+ return rule;
++#else
++ return err;
++#endif
+ }
+
static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
struct mlx5e_tc_flow *flow)
{
struct mlx5_fc *counter = NULL;
counter = mlx5_flow_rule_counter(flow->rule);
-@@ -794,13 +825,16 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
+@@ -794,13 +865,18 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
priv->fs.tc.t = NULL;
}
mlx5e_detach_mod_hdr(priv, flow);
+#endif
++#ifdef MLNX_HAIRPIN_SUPPORT
if (flow->flags & MLX5E_TC_FLOW_HAIRPIN)
mlx5e_hairpin_flow_del(priv, flow);
++#endif
}
+#ifdef HAVE_TCF_TUNNEL_INFO
static void mlx5e_detach_encap(struct mlx5e_priv *priv,
struct mlx5e_tc_flow *flow);
-@@ -809,6 +843,7 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
+@@ -809,27 +885,37 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
struct net_device *mirred_dev,
struct net_device **encap_dev,
struct mlx5e_tc_flow *flow);
+#endif
++#ifdef HAVE_TCF_TUNNEL_INFO
static struct mlx5_flow_handle *
++#else
++static int
++#endif
mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
-@@ -817,12 +852,15 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+ struct mlx5e_tc_flow_parse_attr *parse_attr,
+ struct mlx5e_tc_flow *flow)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5_esw_flow_attr *attr = flow->esw_attr;
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) {
out_dev = __dev_get_by_index(dev_net(priv->netdev),
attr->parse_attr->mirred_ifindex);
-@@ -837,6 +875,7 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+ err = mlx5e_attach_encap(priv, &parse_attr->tun_info,
+ out_dev, &encap_dev, flow);
+ if (err) {
++#ifdef HAVE_TCF_TUNNEL_INFO
+ rule = ERR_PTR(err);
++#endif
+ if (err != -EAGAIN)
+ goto err_attach_encap;
+ }
+@@ -837,22 +923,30 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
rpriv = out_priv->ppriv;
attr->out_rep = rpriv->rep;
}
err = mlx5_eswitch_add_vlan_action(esw, attr);
if (err) {
-@@ -844,6 +883,7 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
++#ifdef HAVE_TCF_TUNNEL_INFO
+ rule = ERR_PTR(err);
++#endif
goto err_add_vlan;
}
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
kfree(parse_attr->mod_hdr_actions);
-@@ -852,7 +892,9 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+ if (err) {
++#ifdef HAVE_TCF_TUNNEL_INFO
+ rule = ERR_PTR(err);
++#endif
goto err_mod_hdr;
}
}
/* we get here if (1) there's no error (rule being null) or when
* (2) there's an encap action and we're on -EAGAIN (no valid neigh)
*/
-@@ -864,14 +906,19 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+@@ -864,15 +958,22 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
return rule;
err_add_rule:
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
mlx5e_detach_encap(priv, flow);
err_attach_encap:
-+#endif
return rule;
++#else
++ return err;
++#endif
}
-@@ -882,21 +929,28 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
+ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
+@@ -882,21 +983,28 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
struct mlx5_esw_flow_attr *attr = flow->esw_attr;
if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
struct mlx5e_encap_entry *e)
{
-@@ -1021,6 +1075,7 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,
+@@ -1021,6 +1129,7 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,
kfree(e);
}
}
static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
struct mlx5e_tc_flow *flow)
-@@ -1031,6 +1086,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
+@@ -1031,6 +1140,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
mlx5e_tc_del_nic_flow(priv, flow);
}
static void parse_vxlan_attr(struct mlx5_flow_spec *spec,
struct tc_cls_flower_offload *f)
{
-@@ -1186,6 +1242,7 @@ vxlan_match_offload_err:
+@@ -1186,6 +1296,7 @@ vxlan_match_offload_err:
return 0;
}
static int __parse_cls_flower(struct mlx5e_priv *priv,
struct mlx5_flow_spec *spec,
-@@ -1205,22 +1262,37 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1205,22 +1316,37 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
if ((dissector_uses_key(f->dissector,
FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) ||
dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID) ||
-@@ -1248,6 +1320,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1248,6 +1374,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
inner_headers);
}
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
struct flow_dissector_key_control *key =
-@@ -1326,6 +1399,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1326,6 +1453,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
key->src);
}
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
struct flow_dissector_key_vlan *key =
skb_flow_dissector_target(f->dissector,
-@@ -1345,6 +1419,23 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1345,6 +1473,23 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, mask->vlan_priority);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, key->vlan_priority);
}
}
if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
-@@ -1403,6 +1494,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1403,6 +1548,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
*min_inline = MLX5_INLINE_MODE_IP;
}
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) {
struct flow_dissector_key_ip *key =
skb_flow_dissector_target(f->dissector,
-@@ -1430,6 +1522,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1430,6 +1576,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
if (mask->tos || mask->ttl)
*min_inline = MLX5_INLINE_MODE_IP;
}
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
struct flow_dissector_key_ports *key =
-@@ -1474,6 +1567,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1474,6 +1621,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
*min_inline = MLX5_INLINE_MODE_TCP_UDP;
}
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) {
struct flow_dissector_key_tcp *key =
skb_flow_dissector_target(f->dissector,
-@@ -1492,6 +1586,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1492,6 +1640,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
if (mask->flags)
*min_inline = MLX5_INLINE_MODE_TCP_UDP;
}
return 0;
}
-@@ -1525,6 +1620,7 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1525,6 +1674,7 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
return err;
}
struct pedit_headers {
struct ethhdr eth;
struct iphdr ip4;
-@@ -1810,6 +1906,7 @@ out_err:
+@@ -1810,6 +1960,7 @@ out_err:
return err;
}
static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 update_flags)
{
u32 prot_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR | TCA_CSUM_UPDATE_FLAG_TCP |
-@@ -1831,6 +1928,7 @@ static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 upda
+@@ -1831,6 +1982,7 @@ static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 upda
return true;
}
static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
struct tcf_exts *exts)
-@@ -1895,6 +1993,7 @@ static bool actions_match_supported(struct mlx5e_priv *priv,
+@@ -1895,7 +2047,9 @@ static bool actions_match_supported(struct mlx5e_priv *priv,
return true;
}
+#endif /* HAVE_TCF_PEDIT_TCFP_KEYS_EX */
++#ifdef MLNX_HAIRPIN_SUPPORT
static bool same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv)
{
-@@ -1917,16 +2016,26 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+ struct mlx5_core_dev *fmdev, *pmdev;
+@@ -1909,6 +2063,7 @@ static bool same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv)
+
+ return (func_id == peer_id);
+ }
++#endif
+
+ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+ struct mlx5e_tc_flow_parse_attr *parse_attr,
+@@ -1917,16 +2072,26 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
struct mlx5_nic_flow_attr *attr = flow->nic_attr;
const struct tc_action *a;
LIST_HEAD(actions);
if (is_tcf_gact_shot(a)) {
attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
if (MLX5_CAP_FLOWTABLE(priv->mdev,
-@@ -1935,6 +2044,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -1935,6 +2100,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
continue;
}
if (is_tcf_pedit(a)) {
err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_KERNEL,
parse_attr);
-@@ -1945,7 +2055,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -1945,7 +2111,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
continue;
}
if (is_tcf_csum(a)) {
if (csum_offload_supported(priv, attr->action,
tcf_csum_update_flags(a)))
-@@ -1953,9 +2065,16 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -1953,13 +2121,23 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
return -EOPNOTSUPP;
}
+#endif
++#ifdef MLNX_HAIRPIN_SUPPORT
if (is_tcf_mirred_egress_redirect(a)) {
+#ifndef HAVE_TCF_MIRRED_DEV
+ int ifindex = tcf_mirred_ifindex(a);
if (priv->netdev->netdev_ops == peer_dev->netdev_ops &&
same_hw_devs(priv, netdev_priv(peer_dev))) {
-@@ -1988,12 +2107,15 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
++#ifdef HAVE_TCF_TUNNEL_INFO
+ parse_attr->mirred_ifindex = peer_dev->ifindex;
++#endif
+ flow->flags |= MLX5E_TC_FLOW_HAIRPIN;
+ attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+ MLX5_FLOW_CONTEXT_ACTION_COUNT;
+@@ -1970,6 +2148,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+ }
+ continue;
+ }
++#endif
+
+ if (is_tcf_skbedit_mark(a)) {
+ u32 mark = tcf_skbedit_mark(a);
+@@ -1988,12 +2167,15 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
return -EINVAL;
}
static inline int cmp_encap_info(struct ip_tunnel_key *a,
struct ip_tunnel_key *b)
{
-@@ -2448,33 +2570,53 @@ out_err:
+@@ -2448,33 +2630,53 @@ out_err:
kfree(e);
return err;
}
if (is_tcf_pedit(a)) {
err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_FDB,
parse_attr);
-@@ -2484,7 +2626,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2484,7 +2686,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
continue;
}
if (is_tcf_csum(a)) {
if (csum_offload_supported(priv, attr->action,
tcf_csum_update_flags(a)))
-@@ -2492,12 +2636,19 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2492,12 +2696,19 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
return -EOPNOTSUPP;
}
if (switchdev_port_same_parent_id(priv->netdev,
out_dev)) {
-@@ -2506,8 +2657,13 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2506,8 +2717,13 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
out_priv = netdev_priv(out_dev);
rpriv = out_priv->ppriv;
attr->out_rep = rpriv->rep;
parse_attr->tun_info = *info;
attr->parse_attr = parse_attr;
attr->action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP |
-@@ -2531,6 +2687,20 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2531,6 +2747,19 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
continue;
}
+ attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+ MLX5_FLOW_CONTEXT_ACTION_COUNT;
+ out_priv = netdev_priv(out_dev);
-+ attr->out_rep[attr->out_count++] = out_priv->ppriv;
+ continue;
+ }
+#endif /* HAVE_TCF_TUNNEL_INFO */
if (is_tcf_vlan(a)) {
if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
-@@ -2552,16 +2722,20 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2552,16 +2781,20 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
continue;
}
return err;
}
-@@ -2664,6 +2838,10 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
+@@ -2599,24 +2832,45 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv,
+ goto err_free;
+
+ if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
++#ifdef HAVE_TCF_TUNNEL_INFO
+ err = parse_tc_fdb_actions(priv, f->exts, parse_attr, flow);
++#else
++ err = parse_tc_fdb_actions(priv, f->exts, parse_attr, flow->esw_attr);
++#endif
+ if (err < 0)
+ goto err_free;
++#ifdef HAVE_TCF_TUNNEL_INFO
+ flow->rule = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow);
++#else
++ err = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow);
++#endif
+ } else {
+ err = parse_tc_nic_actions(priv, f->exts, parse_attr, flow);
+ if (err < 0)
+ goto err_free;
++#ifdef HAVE_TCF_TUNNEL_INFO
+ flow->rule = mlx5e_tc_add_nic_flow(priv, parse_attr, flow);
++#else
++ err = mlx5e_tc_add_nic_flow(priv, parse_attr, flow);
++#endif
+ }
+
++#ifdef HAVE_TCF_TUNNEL_INFO
+ if (IS_ERR(flow->rule)) {
+ err = PTR_ERR(flow->rule);
+ if (err != -EAGAIN)
+ goto err_free;
+ }
++#else
++ if (err && err != -EAGAIN)
++ goto err_free;
++#endif
+
++#ifdef HAVE_TCF_TUNNEL_INFO
+ if (err != -EAGAIN)
++#else
++ if (!err)
++#endif
+ flow->flags |= MLX5E_TC_FLOW_OFFLOADED;
+
+ if (!(flow->flags & MLX5E_TC_FLOW_ESWITCH) ||
+@@ -2664,6 +2918,10 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
struct mlx5e_tc_table *tc = &priv->fs.tc;
struct mlx5e_tc_flow *flow;
struct mlx5_fc *counter;
u64 bytes;
u64 packets;
u64 lastuse;
-@@ -2682,7 +2860,32 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
+@@ -2682,7 +2940,32 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
return 0;
}
-@@ -2698,7 +2901,9 @@ int mlx5e_tc_init(struct mlx5e_priv *priv)
+@@ -2698,8 +2981,12 @@ int mlx5e_tc_init(struct mlx5e_priv *priv)
{
struct mlx5e_tc_table *tc = &priv->fs.tc;
+#ifdef HAVE_TCF_PEDIT_TCFP_KEYS_EX
hash_init(tc->mod_hdr_tbl);
+#endif
++#ifdef MLNX_HAIRPIN_SUPPORT
hash_init(tc->hairpin_tbl);
++#endif
tc->ht_params = mlx5e_tc_flow_ht_params;
+ return rhashtable_init(&tc->ht, &tc->ht_params);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
+@@ -49,6 +49,7 @@ int mlx5e_delete_flower(struct mlx5e_priv *priv,
+ int mlx5e_stats_flower(struct mlx5e_priv *priv,
+ struct tc_cls_flower_offload *f);
+
++#ifdef HAVE_TCF_TUNNEL_INFO
+ struct mlx5e_encap_entry;
+ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
+ struct mlx5e_encap_entry *e);
+@@ -57,6 +58,7 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv,
+
+ struct mlx5e_neigh_hash_entry;
+ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe);
++#endif
+
+ static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv)
+ {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
index xxxxxxx..xxxxxxx xxxxxx
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
free_out:
kvfree(out);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+@@ -238,7 +238,9 @@ struct mlx5_esw_flow_attr {
+ bool vlan_handled;
+ u32 encap_id;
+ u32 mod_hdr_id;
++#ifdef HAVE_TCF_TUNNEL_INFO
+ struct mlx5e_tc_flow_parse_attr *parse_attr;
++#endif
+ };
+
+ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index xxxxxxx..xxxxxxx xxxxxx
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
From: Vladimir Sokolovsky <vlad@mellanox.com>
-Subject: [PATCH] mlx4
+Subject: [PATCH] BACKPORT: mlx4
Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx4/catas.c | 17 +
drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c | 29 ++
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 8 +
- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 378 ++++++++++++++++++++++-
- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 66 +++-
+ drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 426 ++++++++++++++++++++++-
+ drivers/net/ethernet/mellanox/mlx4/en_rx.c | 70 +++-
drivers/net/ethernet/mellanox/mlx4/en_selftest.c | 4 +-
drivers/net/ethernet/mellanox/mlx4/main.c | 2 +
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 12 +
- 8 files changed, 508 insertions(+), 8 deletions(-)
+ 8 files changed, 560 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c
index xxxxxxx..xxxxxxx xxxxxx
ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port,
VXLAN_STEER_BY_OUTER_MAC, 0);
-@@ -2741,12 +2904,19 @@ static void mlx4_en_del_vxlan_port(struct net_device *dev,
+@@ -2689,6 +2852,8 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
+ priv->vxlan_port = 0;
+ }
+
++#ifdef HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON
++#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_NDO_UDP_TUNNEL_ADD_EXTENDED)
+ static void mlx4_en_add_vxlan_port(struct net_device *dev,
+ struct udp_tunnel_info *ti)
+ {
+@@ -2740,13 +2905,66 @@ static void mlx4_en_del_vxlan_port(struct net_device *dev,
+
queue_work(priv->mdev->workqueue, &priv->vxlan_del_task);
}
++#elif defined(HAVE_NDO_ADD_VXLAN_PORT)
++static void mlx4_en_add_vxlan_port(struct net_device *dev,
++ sa_family_t sa_family, __be16 port)
++{
++ struct mlx4_en_priv *priv = netdev_priv(dev);
++ __be16 current_port;
++
++ if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
++ return;
++
++ if (sa_family == AF_INET6)
++ return;
++
++ current_port = priv->vxlan_port;
++ if (current_port && current_port != port) {
++ en_warn(priv, "vxlan port %d configured, can't add port %d\n",
++ ntohs(current_port), ntohs(port));
++ return;
++ }
++
++ priv->vxlan_port = port;
++ queue_work(priv->mdev->workqueue, &priv->vxlan_add_task);
++}
++
++static void mlx4_en_del_vxlan_port(struct net_device *dev,
++ sa_family_t sa_family, __be16 port)
++{
++ struct mlx4_en_priv *priv = netdev_priv(dev);
++ __be16 current_port;
++
++ if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
++ return;
++
++ if (sa_family == AF_INET6)
++ return;
++
++ current_port = priv->vxlan_port;
++ if (current_port != port) {
++ en_dbg(DRV, priv, "vxlan port %d isn't configured, ignoring\n", ntohs(port));
++ return;
++ }
++
++ queue_work(priv->mdev->workqueue, &priv->vxlan_del_task);
++}
++#endif
++#endif /* HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON */
+#ifdef HAVE_NETDEV_FEATURES_T
static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
/* The ConnectX-3 doesn't support outer IPv6 checksums but it does
* support inner IPv6 checksums and segmentation so we need to
-@@ -2765,6 +2935,7 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
+@@ -2765,6 +2983,7 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
return features;
}
static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 maxrate)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
-@@ -2791,7 +2962,9 @@ static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 m
+@@ -2791,7 +3010,9 @@ static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 m
¶ms);
return err;
}
static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
-@@ -2855,7 +3028,11 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
+@@ -2855,7 +3076,11 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
en_warn(priv, "Reducing the number of TX rings, to not exceed the max total rings number.\n");
}
if (err) {
if (prog)
bpf_prog_sub(prog, priv->rx_ring_num - 1);
-@@ -2896,6 +3073,7 @@ out:
+@@ -2896,6 +3121,7 @@ out:
return err;
}
static u32 mlx4_xdp_query(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
-@@ -2916,6 +3094,14 @@ static u32 mlx4_xdp_query(struct net_device *dev)
+@@ -2916,6 +3142,14 @@ static u32 mlx4_xdp_query(struct net_device *dev)
return prog_id;
}
static int mlx4_xdp(struct net_device *dev, struct netdev_bpf *xdp)
{
-@@ -2923,24 +3109,40 @@ static int mlx4_xdp(struct net_device *dev, struct netdev_bpf *xdp)
+@@ -2923,24 +3157,40 @@ static int mlx4_xdp(struct net_device *dev, struct netdev_bpf *xdp)
case XDP_SETUP_PROG:
return mlx4_xdp_set(dev, xdp->prog);
case XDP_QUERY_PROG:
.ndo_do_ioctl = mlx4_en_ioctl,
.ndo_tx_timeout = mlx4_en_tx_timeout,
.ndo_vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid,
-@@ -2948,21 +3150,73 @@ static const struct net_device_ops mlx4_netdev_ops = {
+@@ -2948,21 +3198,73 @@ static const struct net_device_ops mlx4_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = mlx4_en_netpoll,
#endif
.ndo_open = mlx4_en_open,
.ndo_stop = mlx4_en_close,
.ndo_start_xmit = mlx4_en_xmit,
-@@ -2971,12 +3225,20 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
+@@ -2971,12 +3273,20 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
.ndo_set_rx_mode = mlx4_en_set_rx_mode,
.ndo_set_mac_address = mlx4_en_set_mac,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_vf_rate = mlx4_en_set_vf_rate,
.ndo_set_vf_spoofchk = mlx4_en_set_vf_spoofchk,
.ndo_set_vf_link_state = mlx4_en_set_vf_link_state,
-@@ -2987,16 +3249,47 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
+@@ -2987,16 +3297,47 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
#endif
.ndo_set_features = mlx4_en_set_features,
.ndo_fix_features = mlx4_en_fix_features,
};
struct mlx4_en_bond {
-@@ -3424,24 +3717,35 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+@@ -3424,24 +3765,35 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN)) {
dev->features |= NETIF_F_HW_VLAN_STAG_RX |
NETIF_F_HW_VLAN_STAG_FILTER;
-@@ -3475,45 +3779,93 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+@@ -3475,45 +3827,93 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN))
dev->hw_features |= NETIF_F_HW_VLAN_STAG_TX;
}
mdev->pndev[port] = dev;
mdev->upper[port] = NULL;
-@@ -3599,8 +3951,12 @@ int mlx4_en_reset_config(struct net_device *dev,
+@@ -3599,8 +3999,12 @@ int mlx4_en_reset_config(struct net_device *dev,
if (priv->hwtstamp_config.tx_type == ts_config.tx_type &&
priv->hwtstamp_config.rx_filter == ts_config.rx_filter &&
return 0; /* Nothing to change */
if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX) &&
-@@ -3619,7 +3975,11 @@ int mlx4_en_reset_config(struct net_device *dev,
+@@ -3619,7 +4023,11 @@ int mlx4_en_reset_config(struct net_device *dev,
memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
memcpy(&new_prof.hwtstamp_config, &ts_config, sizeof(ts_config));
if (err)
goto out;
-@@ -3639,18 +3999,26 @@ int mlx4_en_reset_config(struct net_device *dev,
+@@ -3639,18 +4047,26 @@ int mlx4_en_reset_config(struct net_device *dev,
/* RX time-stamping is OFF, update the RX vlan offload
* to the latest wanted state
*/
mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);
kvfree(ring->rx_info);
ring->rx_info = NULL;
-@@ -657,11 +671,17 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -510,7 +524,11 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
+ dma_unmap_page(priv->ddev, dma, PAGE_SIZE, priv->dma_dir);
+ frags->page = NULL;
+ } else {
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
+ page_ref_inc(page);
++#else
++ atomic_inc(&frags->page->_count);
++#endif
+ }
+
+ nr++;
+@@ -657,11 +675,17 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
struct mlx4_en_priv *priv = netdev_priv(dev);
int factor = priv->cqe_factor;
struct mlx4_en_rx_ring *ring;
int polled = 0;
int index;
-@@ -670,11 +690,15 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -670,11 +694,15 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
ring = priv->rx_ring[cq_ring];
/* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
* descriptor offset can be deduced from the CQE index instead of
-@@ -757,9 +781,12 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -757,9 +785,12 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
/* A bpf program gets first chance to drop the packet. It may
* read bytes but not past the end of the frag.
*/
u32 act;
dma = frags[0].dma + frags[0].page_offset;
-@@ -767,20 +794,29 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -767,20 +798,29 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
priv->frag_info[0].frag_size,
DMA_FROM_DEVICE);
switch (act) {
case XDP_PASS:
-@@ -792,18 +828,23 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -792,18 +832,23 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
frags[0].page = NULL;
goto next;
}
ring->bytes += length;
ring->packets++;
-@@ -885,13 +926,17 @@ next:
+@@ -885,13 +930,17 @@ next:
break;
}
mlx4_cq_set_ci(&cq->mcq);
wmb(); /* ensure HW sees CQ consumer before we post new buffers */
-@@ -940,7 +985,9 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
+@@ -940,7 +989,9 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
/* If we used up all the quota - we're probably not done yet... */
if (done == budget || !clean_complete) {
const struct cpumask *aff;
int cpu_curr;
/* in case we got here because of !clean_complete */
-@@ -949,8 +996,12 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
+@@ -949,8 +1000,12 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
INC_PERF_COUNTER(priv->pstats.napi_quota);
cpu_curr = smp_processor_id();
if (likely(cpumask_test_cpu(cpu_curr, aff)))
return budget;
-@@ -965,8 +1016,18 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
+@@ -965,8 +1020,18 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
done--;
}
/* Done for now */
return done;
}
-@@ -976,6 +1037,7 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
+@@ -976,6 +1041,7 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
int eff_mtu = MLX4_EN_EFF_MTU(dev->mtu);
int i = 0;
/* bpf requires buffers to be set up as 1 packet per page.
* This only works when num_frags == 1.
*/
-@@ -988,7 +1050,9 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
+@@ -988,7 +1054,9 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
priv->dma_dir = PCI_DMA_BIDIRECTIONAL;
priv->rx_headroom = XDP_PACKET_HEADROOM;
i = 1;