net/mlx5e: Use dedicated uplink vport netdev representor
authorOr Gerlitz <ogerlitz@mellanox.com>
Tue, 13 Feb 2018 13:48:30 +0000 (15:48 +0200)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 17 Dec 2018 19:03:27 +0000 (11:03 -0800)
Currently, when running in sriov switchdev mode, we are using the PF
netdevice as the uplink representor, this is problematic from few aspects:

- will break when the PF isn't eswitch manager (e.g smart NIC env)
- misalignment with other NIC switchdev drivers
- makes us have and maintain special code, hurts the driver quality/robustness
- which in turn opens the door for future bugs

As of each and all of the above, we move to have a dedicated netdev representor
for the uplink vport in a similar manner done for for the VF vports.

This includes the following:

1. have an uplink rep netdev as we have for VF reps
2. all reps use same load/unload functions
3. HW stats for uplink based on physical port counters and not vport counters
4. link state for the uplink managed through PAOS and not vport state
5. the uplink rep has sysfs link to the PF PCI function && uses the PF MAC address

Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.h

index 1c4e033b75098e0e42785b22ba27965f7151ad9f..31deafecf6799271de0945eb1ae0560dc2cb8ae1 100644 (file)
@@ -775,6 +775,7 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
                             struct mlx5e_wqe_frag_info *wi, u32 cqe_bcnt);
 
 void mlx5e_update_stats(struct mlx5e_priv *priv);
+void mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats);
 
 void mlx5e_init_l2_addr(struct mlx5e_priv *priv);
 int mlx5e_self_test_num(struct mlx5e_priv *priv);
@@ -939,7 +940,6 @@ int mlx5e_create_tis(struct mlx5_core_dev *mdev, int tc,
 void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn);
 
 int mlx5e_create_tises(struct mlx5e_priv *priv);
-void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv);
 int mlx5e_close(struct net_device *netdev);
 int mlx5e_open(struct net_device *netdev);
 void mlx5e_update_ndo_stats(struct mlx5e_priv *priv);
@@ -948,6 +948,7 @@ void mlx5e_queue_update_stats(struct mlx5e_priv *priv);
 int mlx5e_bits_invert(unsigned long a, int size);
 
 typedef int (*change_hw_mtu_cb)(struct mlx5e_priv *priv);
+int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv);
 int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
                     change_hw_mtu_cb set_mtu_cb);
 
index 59745851b5ba6ef5a28eef1d467171312961d18b..cdd8b5efd96a2c0b25fbe8368d19cf9254132343 100644 (file)
@@ -2821,7 +2821,7 @@ static void mlx5e_query_mtu(struct mlx5_core_dev *mdev,
        *mtu = MLX5E_HW2SW_MTU(params, hw_mtu);
 }
 
-static int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv)
+int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv)
 {
        struct mlx5e_params *params = &priv->channels.params;
        struct net_device *netdev = priv->netdev;
@@ -2901,7 +2901,7 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
        mlx5e_activate_channels(&priv->channels);
        netif_tx_start_all_queues(priv->netdev);
 
-       if (MLX5_ESWITCH_MANAGER(priv->mdev))
+       if (mlx5e_is_vport_rep(priv))
                mlx5e_add_sqs_fwd_rules(priv);
 
        mlx5e_wait_channels_min_rx_wqes(&priv->channels);
@@ -2912,7 +2912,7 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
 {
        mlx5e_redirect_rqts_to_drop(priv);
 
-       if (MLX5_ESWITCH_MANAGER(priv->mdev))
+       if (mlx5e_is_vport_rep(priv))
                mlx5e_remove_sqs_fwd_rules(priv);
 
        /* FIXME: This is a W/A only for tx timeout watch dog false alarm when
@@ -3164,7 +3164,7 @@ err_close_tises:
        return err;
 }
 
-void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
+static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
 {
        int tc;
 
@@ -3409,7 +3409,8 @@ static int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
 
        switch (type) {
        case TC_SETUP_CLSFLOWER:
-               return mlx5e_setup_tc_cls_flower(priv, type_data, MLX5E_TC_INGRESS);
+               return mlx5e_setup_tc_cls_flower(priv, type_data, MLX5E_TC_INGRESS |
+                                                MLX5E_TC_NIC_OFFLOAD);
        default:
                return -EOPNOTSUPP;
        }
@@ -3452,7 +3453,7 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
        }
 }
 
-static void
+void
 mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
@@ -3596,7 +3597,7 @@ static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
 
-       if (!enable && mlx5e_tc_num_filters(priv)) {
+       if (!enable && mlx5e_tc_num_filters(priv, MLX5E_TC_NIC_OFFLOAD)) {
                netdev_err(netdev,
                           "Active offloaded tc filters, can't turn hw_tc_offload off\n");
                return -EINVAL;
@@ -4607,12 +4608,6 @@ static void mlx5e_set_netdev_dev_addr(struct net_device *netdev)
        }
 }
 
-#if IS_ENABLED(CONFIG_MLX5_ESWITCH)
-static const struct switchdev_ops mlx5e_switchdev_ops = {
-       .switchdev_port_attr_get        = mlx5e_attr_get,
-};
-#endif
-
 static void mlx5e_build_nic_netdev(struct net_device *netdev)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -4722,12 +4717,6 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
        netdev->priv_flags       |= IFF_UNICAST_FLT;
 
        mlx5e_set_netdev_dev_addr(netdev);
-
-#if IS_ENABLED(CONFIG_MLX5_ESWITCH)
-       if (MLX5_ESWITCH_MANAGER(mdev))
-               netdev->switchdev_ops = &mlx5e_switchdev_ops;
-#endif
-
        mlx5e_ipsec_build_netdev(priv);
        mlx5e_tls_build_netdev(priv);
 }
@@ -4908,7 +4897,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
                mlx5e_monitor_counter_init(priv);
 
        if (MLX5_ESWITCH_MANAGER(priv->mdev))
-               mlx5e_register_vport_reps(priv);
+               mlx5e_rep_register_vport_reps(priv);
 
        if (netdev->reg_state != NETREG_REGISTERED)
                return;
@@ -4943,7 +4932,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
        queue_work(priv->wq, &priv->set_rx_mode_work);
 
        if (MLX5_ESWITCH_MANAGER(priv->mdev))
-               mlx5e_unregister_vport_reps(priv);
+               mlx5e_rep_unregister_vport_reps(priv);
 
        if (mlx5e_monitor_counter_supported(priv))
                mlx5e_monitor_counter_cleanup(priv);
index 996a03de91712a56d4ac6f7e137dae978719cdc3..b48ba3234ac5d35bf66ac2b89de9b6b5efbd3560 100644 (file)
@@ -108,7 +108,7 @@ static void mlx5e_rep_get_strings(struct net_device *dev,
        }
 }
 
-static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv)
+static void mlx5e_vf_rep_update_hw_counters(struct mlx5e_priv *priv)
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
@@ -131,6 +131,32 @@ static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv)
        vport_stats->tx_bytes   = vf_stats.rx_bytes;
 }
 
+static void mlx5e_uplink_rep_update_hw_counters(struct mlx5e_priv *priv)
+{
+       struct mlx5e_pport_stats *pstats = &priv->stats.pport;
+       struct rtnl_link_stats64 *vport_stats;
+
+       mlx5e_grp_802_3_update_stats(priv);
+
+       vport_stats = &priv->stats.vf_vport;
+
+       vport_stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok);
+       vport_stats->rx_bytes   = PPORT_802_3_GET(pstats, a_octets_received_ok);
+       vport_stats->tx_packets = PPORT_802_3_GET(pstats, a_frames_transmitted_ok);
+       vport_stats->tx_bytes   = PPORT_802_3_GET(pstats, a_octets_transmitted_ok);
+}
+
+static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv)
+{
+       struct mlx5e_rep_priv *rpriv = priv->ppriv;
+       struct mlx5_eswitch_rep *rep = rpriv->rep;
+
+       if (rep->vport == FDB_UPLINK_VPORT)
+               mlx5e_uplink_rep_update_hw_counters(priv);
+       else
+               mlx5e_vf_rep_update_hw_counters(priv);
+}
+
 static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
 {
        struct mlx5e_sw_stats *s = &priv->stats.sw;
@@ -294,7 +320,7 @@ static const struct ethtool_ops mlx5e_rep_ethtool_ops = {
        .get_rxfh_indir_size = mlx5e_rep_get_rxfh_indir_size,
 };
 
-int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr)
+static int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
@@ -576,21 +602,19 @@ mlx5e_rep_indr_offload(struct net_device *netdev,
                       struct tc_cls_flower_offload *flower,
                       struct mlx5e_rep_indr_block_priv *indr_priv)
 {
-       int err = 0;
        struct mlx5e_priv *priv = netdev_priv(indr_priv->rpriv->netdev);
+       int flags = MLX5E_TC_EGRESS | MLX5E_TC_ESW_OFFLOAD;
+       int err = 0;
 
        switch (flower->command) {
        case TC_CLSFLOWER_REPLACE:
-               err = mlx5e_configure_flower(netdev, priv,
-                                            flower, MLX5E_TC_EGRESS);
+               err = mlx5e_configure_flower(netdev, priv, flower, flags);
                break;
        case TC_CLSFLOWER_DESTROY:
-               err = mlx5e_delete_flower(netdev, priv,
-                                         flower, MLX5E_TC_EGRESS);
+               err = mlx5e_delete_flower(netdev, priv, flower, flags);
                break;
        case TC_CLSFLOWER_STATS:
-               err = mlx5e_stats_flower(netdev, priv,
-                                        flower, MLX5E_TC_EGRESS);
+               err = mlx5e_stats_flower(netdev, priv, flower, flags);
                break;
        default:
                err = -EOPNOTSUPP;
@@ -983,7 +1007,7 @@ void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv,
                mlx5e_rep_neigh_entry_destroy(priv, nhe);
 }
 
-static int mlx5e_rep_open(struct net_device *dev)
+static int mlx5e_vf_rep_open(struct net_device *dev)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
@@ -1005,7 +1029,7 @@ unlock:
        return err;
 }
 
-static int mlx5e_rep_close(struct net_device *dev)
+static int mlx5e_vf_rep_close(struct net_device *dev)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
@@ -1062,7 +1086,8 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
 
        switch (type) {
        case TC_SETUP_CLSFLOWER:
-               return mlx5e_rep_setup_tc_cls_flower(priv, type_data, MLX5E_TC_INGRESS);
+               return mlx5e_rep_setup_tc_cls_flower(priv, type_data, MLX5E_TC_INGRESS |
+                                                    MLX5E_TC_ESW_OFFLOAD);
        default:
                return -EOPNOTSUPP;
        }
@@ -1101,19 +1126,17 @@ static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
 
 bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
 {
-       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
        struct mlx5_eswitch_rep *rep;
 
        if (!MLX5_ESWITCH_MANAGER(priv->mdev))
                return false;
 
-       rep = rpriv->rep;
-       if (esw->mode == SRIOV_OFFLOADS &&
-           rep && rep->vport == FDB_UPLINK_VPORT)
-               return true;
+       if (!rpriv) /* non vport rep mlx5e instances don't use this field */
+               return false;
 
-       return false;
+       rep = rpriv->rep;
+       return (rep->vport == FDB_UPLINK_VPORT);
 }
 
 static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
@@ -1133,11 +1156,8 @@ static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
 
 bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
 {
-       struct mlx5e_priv *priv = netdev_priv(dev);
-
        switch (attr_id) {
        case IFLA_OFFLOAD_XSTATS_CPU_HIT:
-               if (mlx5e_is_vf_vport_rep(priv) || mlx5e_is_uplink_rep(priv))
                        return true;
        }
 
@@ -1175,7 +1195,7 @@ int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
 }
 
 static void
-mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
+mlx5e_vf_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
 
@@ -1184,30 +1204,59 @@ mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
        memcpy(stats, &priv->stats.vf_vport, sizeof(*stats));
 }
 
+static int mlx5e_vf_rep_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       return mlx5e_change_mtu(netdev, new_mtu, NULL);
+}
+
+static int mlx5e_uplink_rep_open(struct net_device *dev)
+{
+       int err;
+
+       err = mlx5e_open(dev);
+       if (!err)
+               netif_carrier_on(dev);
+       return err;
+}
+
+static int mlx5e_uplink_rep_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       return mlx5e_change_mtu(netdev, new_mtu, mlx5e_set_dev_port_mtu);
+}
+
 static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
        .switchdev_port_attr_get        = mlx5e_attr_get,
 };
 
-static int mlx5e_change_rep_mtu(struct net_device *netdev, int new_mtu)
-{
-       return mlx5e_change_mtu(netdev, new_mtu, NULL);
-}
+static const struct net_device_ops mlx5e_netdev_ops_vf_rep = {
+       .ndo_open                = mlx5e_vf_rep_open,
+       .ndo_stop                = mlx5e_vf_rep_close,
+       .ndo_start_xmit          = mlx5e_xmit,
+       .ndo_get_phys_port_name  = mlx5e_rep_get_phys_port_name,
+       .ndo_setup_tc            = mlx5e_rep_setup_tc,
+       .ndo_get_stats64         = mlx5e_vf_rep_get_stats,
+       .ndo_has_offload_stats   = mlx5e_has_offload_stats,
+       .ndo_get_offload_stats   = mlx5e_get_offload_stats,
+       .ndo_change_mtu          = mlx5e_vf_rep_change_mtu,
+};
 
-static const struct net_device_ops mlx5e_netdev_ops_rep = {
-       .ndo_open                = mlx5e_rep_open,
-       .ndo_stop                = mlx5e_rep_close,
+static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
+       .ndo_open                = mlx5e_uplink_rep_open,
+       .ndo_stop                = mlx5e_close,
        .ndo_start_xmit          = mlx5e_xmit,
        .ndo_get_phys_port_name  = mlx5e_rep_get_phys_port_name,
        .ndo_setup_tc            = mlx5e_rep_setup_tc,
-       .ndo_get_stats64         = mlx5e_rep_get_stats,
+       .ndo_get_stats64         = mlx5e_get_stats,
        .ndo_has_offload_stats   = mlx5e_has_offload_stats,
        .ndo_get_offload_stats   = mlx5e_get_offload_stats,
-       .ndo_change_mtu          = mlx5e_change_rep_mtu,
+       .ndo_change_mtu          = mlx5e_uplink_rep_change_mtu,
 };
 
 static void mlx5e_build_rep_params(struct net_device *netdev)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
+       struct mlx5e_rep_priv *rpriv = priv->ppriv;
+       struct mlx5_eswitch_rep *rep = rpriv->rep;
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5e_params *params;
 
@@ -1218,7 +1267,12 @@ static void mlx5e_build_rep_params(struct net_device *netdev)
        params = &priv->channels.params;
        params->hard_mtu    = MLX5E_ETH_HARD_MTU;
        params->sw_mtu      = netdev->mtu;
-       params->log_sq_size = MLX5E_REP_PARAMS_LOG_SQ_SIZE;
+
+       /* SQ */
+       if (rep->vport == FDB_UPLINK_VPORT)
+               params->log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
+       else
+               params->log_sq_size = MLX5E_REP_PARAMS_LOG_SQ_SIZE;
 
        /* RQ */
        mlx5e_build_rq_params(mdev, params);
@@ -1238,10 +1292,20 @@ static void mlx5e_build_rep_params(struct net_device *netdev)
 static void mlx5e_build_rep_netdev(struct net_device *netdev)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
+       struct mlx5e_rep_priv *rpriv = priv->ppriv;
+       struct mlx5_eswitch_rep *rep = rpriv->rep;
        struct mlx5_core_dev *mdev = priv->mdev;
        u16 max_mtu;
 
-       netdev->netdev_ops = &mlx5e_netdev_ops_rep;
+       if (rep->vport == FDB_UPLINK_VPORT) {
+               SET_NETDEV_DEV(netdev, &priv->mdev->pdev->dev);
+               netdev->netdev_ops = &mlx5e_netdev_ops_uplink_rep;
+               /* we want a persistent mac for the uplink rep */
+               mlx5_query_nic_vport_mac_address(mdev, 0, netdev->dev_addr);
+       } else {
+               netdev->netdev_ops = &mlx5e_netdev_ops_vf_rep;
+               eth_hw_addr_random(netdev);
+       }
 
        netdev->watchdog_timeo    = 15 * HZ;
 
@@ -1262,28 +1326,35 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
 
        netdev->features |= netdev->hw_features;
 
-       eth_hw_addr_random(netdev);
-
        netdev->min_mtu = ETH_MIN_MTU;
        mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
        netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu);
 }
 
+static int mlx5e_rep_get_default_num_channels(struct mlx5_eswitch_rep *rep,
+                                             struct net_device *netdev)
+{
+       if (rep->vport == FDB_UPLINK_VPORT)
+               return mlx5e_get_netdev_max_channels(netdev);
+       else
+               return 1;
+}
+
 static int mlx5e_init_rep(struct mlx5_core_dev *mdev,
                          struct net_device *netdev,
                          const struct mlx5e_profile *profile,
                          void *ppriv)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
+       struct mlx5e_rep_priv *rpriv = ppriv;
        int err;
 
        err = mlx5e_netdev_init(netdev, priv, mdev, profile, ppriv);
        if (err)
                return err;
 
-
        priv->channels.params.num_channels =
-                               mlx5e_get_netdev_max_channels(netdev);
+                       mlx5e_rep_get_default_num_channels(rpriv->rep, netdev);
 
        mlx5e_build_rep_params(netdev);
        mlx5e_build_rep_netdev(netdev);
@@ -1408,14 +1479,60 @@ static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
 
 static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
 {
-       int err;
+       struct mlx5e_rep_priv *rpriv = priv->ppriv;
+       struct mlx5_rep_uplink_priv *uplink_priv;
+       int tc, err;
 
        err = mlx5e_create_tises(priv);
        if (err) {
                mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err);
                return err;
        }
+
+       if (rpriv->rep->vport == FDB_UPLINK_VPORT) {
+               uplink_priv = &rpriv->uplink_priv;
+
+               /* init shared tc flow table */
+               err = mlx5e_tc_esw_init(&uplink_priv->tc_ht);
+               if (err)
+                       goto destroy_tises;
+
+               /* init indirect block notifications */
+               INIT_LIST_HEAD(&uplink_priv->tc_indr_block_priv_list);
+               uplink_priv->netdevice_nb.notifier_call = mlx5e_nic_rep_netdevice_event;
+               err = register_netdevice_notifier(&uplink_priv->netdevice_nb);
+               if (err) {
+                       mlx5_core_err(priv->mdev, "Failed to register netdev notifier\n");
+                       goto tc_esw_cleanup;
+               }
+       }
+
        return 0;
+
+tc_esw_cleanup:
+       mlx5e_tc_esw_cleanup(&uplink_priv->tc_ht);
+destroy_tises:
+       for (tc = 0; tc < priv->profile->max_tc; tc++)
+               mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]);
+       return err;
+}
+
+static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv)
+{
+       struct mlx5e_rep_priv *rpriv = priv->ppriv;
+       int tc;
+
+       for (tc = 0; tc < priv->profile->max_tc; tc++)
+               mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]);
+
+       if (rpriv->rep->vport == FDB_UPLINK_VPORT) {
+               /* clean indirect TC block notifications */
+               unregister_netdevice_notifier(&rpriv->uplink_priv.netdevice_nb);
+               mlx5e_rep_indr_clean_block_privs(rpriv);
+
+               /* delete shared tc flow table */
+               mlx5e_tc_esw_cleanup(&rpriv->uplink_priv.tc_ht);
+       }
 }
 
 static const struct mlx5e_profile mlx5e_rep_profile = {
@@ -1424,7 +1541,7 @@ static const struct mlx5e_profile mlx5e_rep_profile = {
        .init_rx                = mlx5e_init_rep_rx,
        .cleanup_rx             = mlx5e_cleanup_rep_rx,
        .init_tx                = mlx5e_init_rep_tx,
-       .cleanup_tx             = mlx5e_cleanup_nic_tx,
+       .cleanup_tx             = mlx5e_cleanup_rep_tx,
        .update_stats           = mlx5e_rep_update_hw_counters,
        .update_carrier         = NULL,
        .rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe_rep,
@@ -1507,6 +1624,9 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
        if (!rpriv)
                return -ENOMEM;
 
+       /* rpriv->rep to be looked up when profile->init() is called */
+       rpriv->rep = rep;
+
        nch = mlx5e_get_max_num_channels(dev);
        netdev = mlx5e_create_netdev(dev, &mlx5e_rep_profile, nch, rpriv);
        if (!netdev) {
@@ -1517,7 +1637,6 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
        }
 
        rpriv->netdev = netdev;
-       rpriv->rep = rep;
        rep->rep_if[REP_ETH].priv = rpriv;
        INIT_LIST_HEAD(&rpriv->vport_sqs_list);
 
@@ -1580,14 +1699,14 @@ static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
        return rpriv->netdev;
 }
 
-static void mlx5e_rep_register_vf_vports(struct mlx5e_priv *priv)
+void mlx5e_rep_register_vport_reps(struct mlx5e_priv *priv)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5_eswitch *esw   = mdev->priv.eswitch;
        int total_vfs = MLX5_TOTAL_VPORTS(mdev);
        int vport;
 
-       for (vport = 1; vport < total_vfs; vport++) {
+       for (vport = 0; vport < total_vfs; vport++) {
                struct mlx5_eswitch_rep_if rep_if = {};
 
                rep_if.load = mlx5e_vport_rep_load;
@@ -1597,46 +1716,17 @@ static void mlx5e_rep_register_vf_vports(struct mlx5e_priv *priv)
        }
 }
 
-static void mlx5e_rep_unregister_vf_vports(struct mlx5e_priv *priv)
+void mlx5e_rep_unregister_vport_reps(struct mlx5e_priv *priv)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5_eswitch *esw = mdev->priv.eswitch;
        int total_vfs = MLX5_TOTAL_VPORTS(mdev);
        int vport;
 
-       for (vport = 1; vport < total_vfs; vport++)
+       for (vport = total_vfs - 1; vport >= 0; vport--)
                mlx5_eswitch_unregister_vport_rep(esw, vport, REP_ETH);
 }
 
-void mlx5e_register_vport_reps(struct mlx5e_priv *priv)
-{
-       struct mlx5_core_dev *mdev = priv->mdev;
-       struct mlx5_eswitch *esw   = mdev->priv.eswitch;
-       struct mlx5_eswitch_rep_if rep_if;
-       struct mlx5e_rep_priv *rpriv;
-
-       rpriv = priv->ppriv;
-       rpriv->netdev = priv->netdev;
-
-       rep_if.load = mlx5e_nic_rep_load;
-       rep_if.unload = mlx5e_nic_rep_unload;
-       rep_if.get_proto_dev = mlx5e_vport_rep_get_proto_dev;
-       rep_if.priv = rpriv;
-       INIT_LIST_HEAD(&rpriv->vport_sqs_list);
-       mlx5_eswitch_register_vport_rep(esw, 0, &rep_if, REP_ETH); /* UPLINK PF vport*/
-
-       mlx5e_rep_register_vf_vports(priv); /* VFs vports */
-}
-
-void mlx5e_unregister_vport_reps(struct mlx5e_priv *priv)
-{
-       struct mlx5_core_dev *mdev = priv->mdev;
-       struct mlx5_eswitch *esw   = mdev->priv.eswitch;
-
-       mlx5e_rep_unregister_vf_vports(priv); /* VFs vports */
-       mlx5_eswitch_unregister_vport_rep(esw, 0, REP_ETH); /* UPLINK PF*/
-}
-
 void *mlx5e_alloc_nic_rep_priv(struct mlx5_core_dev *mdev)
 {
        struct mlx5_eswitch *esw = mdev->priv.eswitch;
index 2c8798332c32b3b820db5097318a1544fed05cc6..07d5964356f1b3854e261b5f11c632099cee8395 100644 (file)
@@ -162,8 +162,8 @@ struct mlx5e_rep_sq {
 };
 
 void *mlx5e_alloc_nic_rep_priv(struct mlx5_core_dev *mdev);
-void mlx5e_register_vport_reps(struct mlx5e_priv *priv);
-void mlx5e_unregister_vport_reps(struct mlx5e_priv *priv);
+void mlx5e_rep_register_vport_reps(struct mlx5e_priv *priv);
+void mlx5e_rep_unregister_vport_reps(struct mlx5e_priv *priv);
 bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv);
 int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv);
 void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv);
@@ -171,7 +171,6 @@ void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv);
 int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev, void *sp);
 bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id);
 
-int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr);
 void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe);
 
 int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv,
@@ -181,11 +180,15 @@ void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv,
 
 void mlx5e_rep_queue_neigh_stats_work(struct mlx5e_priv *priv);
 #else /* CONFIG_MLX5_ESWITCH */
-static inline void mlx5e_register_vport_reps(struct mlx5e_priv *priv) {}
-static inline void mlx5e_unregister_vport_reps(struct mlx5e_priv *priv) {}
+static inline void mlx5e_rep_register_vport_reps(struct mlx5e_priv *priv) {}
+static inline void mlx5e_rep_unregister_vport_reps(struct mlx5e_priv *priv) {}
 static inline bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) { return false; }
 static inline int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv) { return 0; }
 static inline void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv) {}
 #endif
 
+static inline bool mlx5e_is_vport_rep(struct mlx5e_priv *priv)
+{
+       return (MLX5_ESWITCH_MANAGER(priv->mdev) && priv->ppriv);
+}
 #endif /* __MLX5E_REP_H__ */
index 8224f1e062a8ce4e3bc19eb5782a0ad6eb1e4cfc..3071a44e2f3021303c2d420bf01070adce4b85db 100644 (file)
@@ -486,7 +486,7 @@ static int mlx5e_grp_802_3_fill_stats(struct mlx5e_priv *priv, u64 *data,
 #define MLX5_BASIC_PPCNT_SUPPORTED(mdev) \
        (MLX5_CAP_GEN(mdev, pcam_reg) ? MLX5_CAP_PCAM_REG(mdev, ppcnt) : 1)
 
-static void mlx5e_grp_802_3_update_stats(struct mlx5e_priv *priv)
+void mlx5e_grp_802_3_update_stats(struct mlx5e_priv *priv)
 {
        struct mlx5e_pport_stats *pstats = &priv->stats.pport;
        struct mlx5_core_dev *mdev = priv->mdev;
index 3f8e870ef4c903bbca01e894bc2608bbb8ead182..807e60582a6bf074853ce6bc6d770354c4055b28 100644 (file)
@@ -280,5 +280,6 @@ extern const struct mlx5e_stats_grp mlx5e_stats_grps[];
 extern const int mlx5e_num_stats_grps;
 
 void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv);
+void mlx5e_grp_802_3_update_stats(struct mlx5e_priv *priv);
 
 #endif /* __MLX5_EN_STATS_H__ */
index 53ebb5a48018ae37387093e30095dfd03042e38b..c1a9120412b8cc3a943a2fb1b315a1409062c231 100644 (file)
@@ -69,13 +69,13 @@ struct mlx5_nic_flow_attr {
 enum {
        MLX5E_TC_FLOW_INGRESS   = MLX5E_TC_INGRESS,
        MLX5E_TC_FLOW_EGRESS    = MLX5E_TC_EGRESS,
-       MLX5E_TC_FLOW_ESWITCH   = BIT(MLX5E_TC_FLOW_BASE),
-       MLX5E_TC_FLOW_NIC       = BIT(MLX5E_TC_FLOW_BASE + 1),
-       MLX5E_TC_FLOW_OFFLOADED = BIT(MLX5E_TC_FLOW_BASE + 2),
-       MLX5E_TC_FLOW_HAIRPIN   = BIT(MLX5E_TC_FLOW_BASE + 3),
-       MLX5E_TC_FLOW_HAIRPIN_RSS = BIT(MLX5E_TC_FLOW_BASE + 4),
-       MLX5E_TC_FLOW_SLOW        = BIT(MLX5E_TC_FLOW_BASE + 5),
-       MLX5E_TC_FLOW_DUP         = BIT(MLX5E_TC_FLOW_BASE + 6),
+       MLX5E_TC_FLOW_ESWITCH   = MLX5E_TC_ESW_OFFLOAD,
+       MLX5E_TC_FLOW_NIC       = MLX5E_TC_NIC_OFFLOAD,
+       MLX5E_TC_FLOW_OFFLOADED = BIT(MLX5E_TC_FLOW_BASE),
+       MLX5E_TC_FLOW_HAIRPIN   = BIT(MLX5E_TC_FLOW_BASE + 1),
+       MLX5E_TC_FLOW_HAIRPIN_RSS = BIT(MLX5E_TC_FLOW_BASE + 2),
+       MLX5E_TC_FLOW_SLOW        = BIT(MLX5E_TC_FLOW_BASE + 3),
+       MLX5E_TC_FLOW_DUP         = BIT(MLX5E_TC_FLOW_BASE + 4),
 };
 
 #define MLX5E_TC_MAX_SPLITS 1
@@ -834,7 +834,7 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
        mlx5_del_flow_rules(flow->rule[0]);
        mlx5_fc_destroy(priv->mdev, counter);
 
-       if (!mlx5e_tc_num_filters(priv) && priv->fs.tc.t) {
+       if (!mlx5e_tc_num_filters(priv, MLX5E_TC_NIC_OFFLOAD)  && priv->fs.tc.t) {
                mlx5_destroy_flow_table(priv->fs.tc.t);
                priv->fs.tc.t = NULL;
        }
@@ -2686,6 +2686,11 @@ static void get_flags(int flags, u16 *flow_flags)
        if (flags & MLX5E_TC_EGRESS)
                __flow_flags |= MLX5E_TC_FLOW_EGRESS;
 
+       if (flags & MLX5E_TC_ESW_OFFLOAD)
+               __flow_flags |= MLX5E_TC_FLOW_ESWITCH;
+       if (flags & MLX5E_TC_NIC_OFFLOAD)
+               __flow_flags |= MLX5E_TC_FLOW_NIC;
+
        *flow_flags = __flow_flags;
 }
 
@@ -2696,15 +2701,15 @@ static const struct rhashtable_params tc_ht_params = {
        .automatic_shrinking = true,
 };
 
-static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv)
+static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv, int flags)
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5e_rep_priv *uplink_rpriv;
 
-       if (MLX5_VPORT_MANAGER(priv->mdev) && esw->mode == SRIOV_OFFLOADS) {
+       if (flags & MLX5E_TC_ESW_OFFLOAD) {
                uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
                return &uplink_rpriv->uplink_priv.tc_ht;
-       } else
+       } else /* NIC offload */
                return &priv->fs.tc.ht;
 }
 
@@ -2973,7 +2978,7 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv,
                           struct tc_cls_flower_offload *f, int flags)
 {
        struct netlink_ext_ack *extack = f->common.extack;
-       struct rhashtable *tc_ht = get_tc_ht(priv);
+       struct rhashtable *tc_ht = get_tc_ht(priv, flags);
        struct mlx5e_tc_flow *flow;
        int err = 0;
 
@@ -3018,7 +3023,7 @@ static bool same_flow_direction(struct mlx5e_tc_flow *flow, int flags)
 int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv,
                        struct tc_cls_flower_offload *f, int flags)
 {
-       struct rhashtable *tc_ht = get_tc_ht(priv);
+       struct rhashtable *tc_ht = get_tc_ht(priv, flags);
        struct mlx5e_tc_flow *flow;
 
        flow = rhashtable_lookup_fast(tc_ht, &f->cookie, tc_ht_params);
@@ -3038,7 +3043,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
                       struct tc_cls_flower_offload *f, int flags)
 {
        struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
-       struct rhashtable *tc_ht = get_tc_ht(priv);
+       struct rhashtable *tc_ht = get_tc_ht(priv, flags);
        struct mlx5_eswitch *peer_esw;
        struct mlx5e_tc_flow *flow;
        struct mlx5_fc *counter;
@@ -3168,7 +3173,7 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv)
        if (tc->netdevice_nb.notifier_call)
                unregister_netdevice_notifier(&tc->netdevice_nb);
 
-       rhashtable_free_and_destroy(&tc->ht, _mlx5e_tc_del_flow, NULL);
+       rhashtable_destroy(&tc->ht);
 
        if (!IS_ERR_OR_NULL(tc->t)) {
                mlx5_destroy_flow_table(tc->t);
@@ -3186,9 +3191,9 @@ void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht)
        rhashtable_free_and_destroy(tc_ht, _mlx5e_tc_del_flow, NULL);
 }
 
-int mlx5e_tc_num_filters(struct mlx5e_priv *priv)
+int mlx5e_tc_num_filters(struct mlx5e_priv *priv, int flags)
 {
-       struct rhashtable *tc_ht = get_tc_ht(priv);
+       struct rhashtable *tc_ht = get_tc_ht(priv, flags);
 
        return atomic_read(&tc_ht->nelems);
 }
index a15c08a350549583b25d5cd758bb08cc6666b6df..d2d87f978c060b73a8d05abbfbc6629f0dfa08aa 100644 (file)
@@ -42,7 +42,9 @@
 enum {
        MLX5E_TC_INGRESS = BIT(0),
        MLX5E_TC_EGRESS  = BIT(1),
-       MLX5E_TC_LAST_EXPORTED_BIT = 1,
+       MLX5E_TC_NIC_OFFLOAD = BIT(2),
+       MLX5E_TC_ESW_OFFLOAD = BIT(3),
+       MLX5E_TC_LAST_EXPORTED_BIT = 3,
 };
 
 int mlx5e_tc_nic_init(struct mlx5e_priv *priv);
@@ -68,13 +70,13 @@ 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);
 
-int mlx5e_tc_num_filters(struct mlx5e_priv *priv);
+int mlx5e_tc_num_filters(struct mlx5e_priv *priv, int flags);
 
 
 #else /* CONFIG_MLX5_ESWITCH */
 static inline int  mlx5e_tc_nic_init(struct mlx5e_priv *priv) { return 0; }
 static inline void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) {}
-static inline int  mlx5e_tc_num_filters(struct mlx5e_priv *priv) { return 0; }
+static inline int  mlx5e_tc_num_filters(struct mlx5e_priv *priv, int flags) { return 0; }
 #endif
 
 #endif /* __MLX5_EN_TC_H__ */