]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/net/ethernet/mellanox/mlx5/core/en_main.c
net/mlx5e: Extendable vport representor netdev private data
[mirror_ubuntu-bionic-kernel.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_main.c
index 1fde4e2301a4119a20ac2ca3bd87a84d15ff5784..1afaca96a30d83afa47b084ac829c86a34176a04 100644 (file)
 #include <linux/mlx5/fs.h>
 #include <net/vxlan.h>
 #include <linux/bpf.h>
+#include "eswitch.h"
 #include "en.h"
 #include "en_tc.h"
-#include "eswitch.h"
+#include "en_rep.h"
 #include "vxlan.h"
 
 struct mlx5e_rq_param {
@@ -167,7 +168,7 @@ unlock:
 
 static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
 {
-       struct mlx5e_sw_stats *s = &priv->stats.sw;
+       struct mlx5e_sw_stats temp, *s = &temp;
        struct mlx5e_rq_stats *rq_stats;
        struct mlx5e_sq_stats *sq_stats;
        u64 tx_offload_none = 0;
@@ -224,6 +225,7 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
        s->link_down_events_phy = MLX5_GET(ppcnt_reg,
                                priv->stats.pport.phy_counters,
                                counter_set.phys_layer_cntrs.link_down_events);
+       memcpy(&priv->stats.sw, s, sizeof(*s));
 }
 
 static void mlx5e_update_vport_counters(struct mlx5e_priv *priv)
@@ -238,7 +240,6 @@ static void mlx5e_update_vport_counters(struct mlx5e_priv *priv)
        MLX5_SET(query_vport_counter_in, in, op_mod, 0);
        MLX5_SET(query_vport_counter_in, in, other_vport, 0);
 
-       memset(out, 0, outlen);
        mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
 }
 
@@ -585,15 +586,17 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
 
        switch (rq->wq_type) {
        case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
-               if (mlx5e_is_vf_vport_rep(c->priv)) {
-                       err = -EINVAL;
-                       goto err_rq_wq_destroy;
-               }
 
-               rq->handle_rx_cqe = mlx5e_handle_rx_cqe_mpwrq;
                rq->alloc_wqe = mlx5e_alloc_rx_mpwqe;
                rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe;
 
+               rq->handle_rx_cqe = c->priv->profile->rx_handlers.handle_rx_cqe_mpwqe;
+               if (!rq->handle_rx_cqe) {
+                       err = -EINVAL;
+                       netdev_err(c->netdev, "RX handler of MPWQE RQ is not set, err %d\n", err);
+                       goto err_rq_wq_destroy;
+               }
+
                rq->mpwqe_stride_sz = BIT(params->mpwqe_log_stride_sz);
                rq->mpwqe_num_strides = BIT(params->mpwqe_log_num_strides);
 
@@ -616,15 +619,17 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
                        err = -ENOMEM;
                        goto err_rq_wq_destroy;
                }
-
-               if (mlx5e_is_vf_vport_rep(c->priv))
-                       rq->handle_rx_cqe = mlx5e_handle_rx_cqe_rep;
-               else
-                       rq->handle_rx_cqe = mlx5e_handle_rx_cqe;
-
                rq->alloc_wqe = mlx5e_alloc_rx_wqe;
                rq->dealloc_wqe = mlx5e_dealloc_rx_wqe;
 
+               rq->handle_rx_cqe = c->priv->profile->rx_handlers.handle_rx_cqe;
+               if (!rq->handle_rx_cqe) {
+                       kfree(rq->dma_info);
+                       err = -EINVAL;
+                       netdev_err(c->netdev, "RX handler of RQ is not set, err %d\n", err);
+                       goto err_rq_wq_destroy;
+               }
+
                rq->buff.wqe_sz = params->lro_en  ?
                                params->lro_wqe_sz :
                                MLX5E_SW2HW_MTU(c->netdev->mtu);
@@ -1042,7 +1047,6 @@ static void mlx5e_free_txqsq_db(struct mlx5e_txqsq *sq)
 {
        kfree(sq->db.wqe_info);
        kfree(sq->db.dma_fifo);
-       kfree(sq->db.skb);
 }
 
 static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
@@ -1050,13 +1054,11 @@ static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
        int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
        int df_sz = wq_sz * MLX5_SEND_WQEBB_NUM_DS;
 
-       sq->db.skb = kzalloc_node(wq_sz * sizeof(*sq->db.skb),
-                                     GFP_KERNEL, numa);
        sq->db.dma_fifo = kzalloc_node(df_sz * sizeof(*sq->db.dma_fifo),
                                           GFP_KERNEL, numa);
        sq->db.wqe_info = kzalloc_node(wq_sz * sizeof(*sq->db.wqe_info),
                                           GFP_KERNEL, numa);
-       if (!sq->db.skb || !sq->db.dma_fifo || !sq->db.wqe_info) {
+       if (!sq->db.dma_fifo || !sq->db.wqe_info) {
                mlx5e_free_txqsq_db(sq);
                return -ENOMEM;
        }
@@ -1295,7 +1297,7 @@ static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
        if (mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, 1)) {
                struct mlx5e_tx_wqe *nop;
 
-               sq->db.skb[(sq->pc & sq->wq.sz_m1)] = NULL;
+               sq->db.wqe_info[(sq->pc & sq->wq.sz_m1)].skb = NULL;
                nop = mlx5e_post_nop(&sq->wq, sq->sqn, &sq->pc);
                mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, &nop->ctrl);
        }
@@ -2547,7 +2549,13 @@ static void mlx5e_build_channels_tx_maps(struct mlx5e_priv *priv)
        }
 }
 
-static void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
+static bool mlx5e_is_eswitch_vport_mngr(struct mlx5_core_dev *mdev)
+{
+       return (MLX5_CAP_GEN(mdev, vport_group_manager) &&
+               MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH);
+}
+
+void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
 {
        int num_txqs = priv->channels.num * priv->channels.params.num_tc;
        struct net_device *netdev = priv->netdev;
@@ -2560,18 +2568,18 @@ static void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
        mlx5e_activate_channels(&priv->channels);
        netif_tx_start_all_queues(priv->netdev);
 
-       if (MLX5_CAP_GEN(priv->mdev, vport_group_manager))
+       if (mlx5e_is_eswitch_vport_mngr(priv->mdev))
                mlx5e_add_sqs_fwd_rules(priv);
 
        mlx5e_wait_channels_min_rx_wqes(&priv->channels);
        mlx5e_redirect_rqts_to_channels(priv, &priv->channels);
 }
 
-static void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
+void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
 {
        mlx5e_redirect_rqts_to_drop(priv);
 
-       if (MLX5_CAP_GEN(priv->mdev, vport_group_manager))
+       if (mlx5e_is_eswitch_vport_mngr(priv->mdev))
                mlx5e_remove_sqs_fwd_rules(priv);
 
        /* FIXME: This is a W/A only for tx timeout watch dog false alarm when
@@ -4116,48 +4124,10 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
        return 0;
 }
 
-static void mlx5e_register_vport_rep(struct mlx5_core_dev *mdev)
-{
-       struct mlx5_eswitch *esw = mdev->priv.eswitch;
-       int total_vfs = MLX5_TOTAL_VPORTS(mdev);
-       int vport;
-       u8 mac[ETH_ALEN];
-
-       if (!MLX5_CAP_GEN(mdev, vport_group_manager))
-               return;
-
-       mlx5_query_nic_vport_mac_address(mdev, 0, mac);
-
-       for (vport = 1; vport < total_vfs; vport++) {
-               struct mlx5_eswitch_rep rep;
-
-               rep.load = mlx5e_vport_rep_load;
-               rep.unload = mlx5e_vport_rep_unload;
-               rep.vport = vport;
-               ether_addr_copy(rep.hw_id, mac);
-               mlx5_eswitch_register_vport_rep(esw, vport, &rep);
-       }
-}
-
-static void mlx5e_unregister_vport_rep(struct mlx5_core_dev *mdev)
-{
-       struct mlx5_eswitch *esw = mdev->priv.eswitch;
-       int total_vfs = MLX5_TOTAL_VPORTS(mdev);
-       int vport;
-
-       if (!MLX5_CAP_GEN(mdev, vport_group_manager))
-               return;
-
-       for (vport = 1; vport < total_vfs; vport++)
-               mlx5_eswitch_unregister_vport_rep(esw, vport);
-}
-
 static void mlx5e_nic_enable(struct mlx5e_priv *priv)
 {
        struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
-       struct mlx5_eswitch *esw = mdev->priv.eswitch;
-       struct mlx5_eswitch_rep rep;
        u16 max_mtu;
 
        mlx5e_init_l2_addr(priv);
@@ -4172,16 +4142,8 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
 
        mlx5e_enable_async_events(priv);
 
-       if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
-               mlx5_query_nic_vport_mac_address(mdev, 0, rep.hw_id);
-               rep.load = mlx5e_nic_rep_load;
-               rep.unload = mlx5e_nic_rep_unload;
-               rep.vport = FDB_UPLINK_VPORT;
-               rep.netdev = netdev;
-               mlx5_eswitch_register_vport_rep(esw, 0, &rep);
-       }
-
-       mlx5e_register_vport_rep(mdev);
+       if (MLX5_CAP_GEN(mdev, vport_group_manager))
+               mlx5e_register_vport_reps(priv);
 
        if (netdev->reg_state != NETREG_REGISTERED)
                return;
@@ -4205,7 +4167,6 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
 static void mlx5e_nic_disable(struct mlx5e_priv *priv)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
-       struct mlx5_eswitch *esw = mdev->priv.eswitch;
 
        rtnl_lock();
        if (netif_running(priv->netdev))
@@ -4214,9 +4175,10 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
        rtnl_unlock();
 
        queue_work(priv->wq, &priv->set_rx_mode_work);
-       mlx5e_unregister_vport_rep(mdev);
+
        if (MLX5_CAP_GEN(mdev, vport_group_manager))
-               mlx5_eswitch_unregister_vport_rep(esw, 0);
+               mlx5e_unregister_vport_reps(priv);
+
        mlx5e_disable_async_events(priv);
        mlx5_lag_remove(mdev);
 }
@@ -4232,6 +4194,8 @@ static const struct mlx5e_profile mlx5e_nic_profile = {
        .disable           = mlx5e_nic_disable,
        .update_stats      = mlx5e_update_stats,
        .max_nch           = mlx5e_get_max_num_channels,
+       .rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe,
+       .rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
        .max_tc            = MLX5E_MAX_NUM_TC,
 };
 
@@ -4385,7 +4349,7 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev)
 {
        struct mlx5_eswitch *esw = mdev->priv.eswitch;
        int total_vfs = MLX5_TOTAL_VPORTS(mdev);
-       void *ppriv = NULL;
+       struct mlx5e_rep_priv *rpriv = NULL;
        void *priv;
        int vport;
        int err;
@@ -4395,10 +4359,17 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev)
        if (err)
                return NULL;
 
-       if (MLX5_CAP_GEN(mdev, vport_group_manager))
-               ppriv = &esw->offloads.vport_reps[0];
+       if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
+               rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
+               if (!rpriv) {
+                       mlx5_core_warn(mdev,
+                                      "Not creating net device, Failed to alloc rep priv data\n");
+                       return NULL;
+               }
+               rpriv->rep = &esw->offloads.vport_reps[0];
+       }
 
-       netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, ppriv);
+       netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, rpriv);
        if (!netdev) {
                mlx5_core_err(mdev, "mlx5e_create_netdev failed\n");
                goto err_unregister_reps;
@@ -4430,16 +4401,19 @@ err_unregister_reps:
        for (vport = 1; vport < total_vfs; vport++)
                mlx5_eswitch_unregister_vport_rep(esw, vport);
 
+       kfree(rpriv);
        return NULL;
 }
 
 static void mlx5e_remove(struct mlx5_core_dev *mdev, void *vpriv)
 {
        struct mlx5e_priv *priv = vpriv;
+       void *ppriv = priv->ppriv;
 
        unregister_netdev(priv->netdev);
        mlx5e_detach(mdev, vpriv);
        mlx5e_destroy_netdev(priv);
+       kfree(ppriv);
 }
 
 static void *mlx5e_get_netdev(void *vpriv)