Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
0002 /* Copyright (c) 2020 Mellanox Technologies */
0003 
0004 #include <net/page_pool.h>
0005 #include "en/txrx.h"
0006 #include "en/params.h"
0007 #include "en/trap.h"
0008 
0009 static int mlx5e_trap_napi_poll(struct napi_struct *napi, int budget)
0010 {
0011     struct mlx5e_trap *trap_ctx = container_of(napi, struct mlx5e_trap, napi);
0012     struct mlx5e_ch_stats *ch_stats = trap_ctx->stats;
0013     struct mlx5e_rq *rq = &trap_ctx->rq;
0014     bool busy = false;
0015     int work_done = 0;
0016 
0017     rcu_read_lock();
0018 
0019     ch_stats->poll++;
0020 
0021     work_done = mlx5e_poll_rx_cq(&rq->cq, budget);
0022     busy |= work_done == budget;
0023     busy |= rq->post_wqes(rq);
0024 
0025     if (busy) {
0026         work_done = budget;
0027         goto out;
0028     }
0029 
0030     if (unlikely(!napi_complete_done(napi, work_done)))
0031         goto out;
0032 
0033     mlx5e_cq_arm(&rq->cq);
0034 
0035 out:
0036     rcu_read_unlock();
0037     return work_done;
0038 }
0039 
0040 static void mlx5e_init_trap_rq(struct mlx5e_trap *t, struct mlx5e_params *params,
0041                    struct mlx5e_rq *rq)
0042 {
0043     struct mlx5_core_dev *mdev = t->mdev;
0044     struct mlx5e_priv *priv = t->priv;
0045 
0046     rq->wq_type      = params->rq_wq_type;
0047     rq->pdev         = t->pdev;
0048     rq->netdev       = priv->netdev;
0049     rq->priv         = priv;
0050     rq->clock        = &mdev->clock;
0051     rq->tstamp       = &priv->tstamp;
0052     rq->mdev         = mdev;
0053     rq->hw_mtu       = MLX5E_SW2HW_MTU(params, params->sw_mtu);
0054     rq->stats        = &priv->trap_stats.rq;
0055     rq->ptp_cyc2time = mlx5_rq_ts_translator(mdev);
0056     xdp_rxq_info_unused(&rq->xdp_rxq);
0057     mlx5e_rq_set_trap_handlers(rq, params);
0058 }
0059 
0060 static int mlx5e_open_trap_rq(struct mlx5e_priv *priv, struct mlx5e_trap *t)
0061 {
0062     struct mlx5e_rq_param *rq_param = &t->rq_param;
0063     struct mlx5_core_dev *mdev = priv->mdev;
0064     struct mlx5e_create_cq_param ccp = {};
0065     struct dim_cq_moder trap_moder = {};
0066     struct mlx5e_rq *rq = &t->rq;
0067     int node;
0068     int err;
0069 
0070     node = dev_to_node(mdev->device);
0071 
0072     ccp.node     = node;
0073     ccp.ch_stats = t->stats;
0074     ccp.napi     = &t->napi;
0075     ccp.ix       = 0;
0076     err = mlx5e_open_cq(priv, trap_moder, &rq_param->cqp, &ccp, &rq->cq);
0077     if (err)
0078         return err;
0079 
0080     mlx5e_init_trap_rq(t, &t->params, rq);
0081     err = mlx5e_open_rq(&t->params, rq_param, NULL, node, rq);
0082     if (err)
0083         goto err_destroy_cq;
0084 
0085     return 0;
0086 
0087 err_destroy_cq:
0088     mlx5e_close_cq(&rq->cq);
0089 
0090     return err;
0091 }
0092 
0093 static void mlx5e_close_trap_rq(struct mlx5e_rq *rq)
0094 {
0095     mlx5e_close_rq(rq);
0096     mlx5e_close_cq(&rq->cq);
0097 }
0098 
0099 static int mlx5e_create_trap_direct_rq_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir,
0100                        u32 rqn)
0101 {
0102     struct mlx5e_tir_builder *builder;
0103     int err;
0104 
0105     builder = mlx5e_tir_builder_alloc(false);
0106     if (!builder)
0107         return -ENOMEM;
0108 
0109     mlx5e_tir_builder_build_inline(builder, mdev->mlx5e_res.hw_objs.td.tdn, rqn);
0110     err = mlx5e_tir_init(tir, builder, mdev, true);
0111 
0112     mlx5e_tir_builder_free(builder);
0113 
0114     return err;
0115 }
0116 
0117 static void mlx5e_build_trap_params(struct mlx5_core_dev *mdev,
0118                     int max_mtu, u16 q_counter,
0119                     struct mlx5e_trap *t)
0120 {
0121     struct mlx5e_params *params = &t->params;
0122 
0123     params->rq_wq_type = MLX5_WQ_TYPE_CYCLIC;
0124     mlx5e_init_rq_type_params(mdev, params);
0125     params->sw_mtu = max_mtu;
0126     mlx5e_build_rq_param(mdev, params, NULL, q_counter, &t->rq_param);
0127 }
0128 
0129 static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_priv *priv)
0130 {
0131     int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(priv->mdev, 0));
0132     struct net_device *netdev = priv->netdev;
0133     struct mlx5e_trap *t;
0134     int err;
0135 
0136     t = kvzalloc_node(sizeof(*t), GFP_KERNEL, cpu_to_node(cpu));
0137     if (!t)
0138         return ERR_PTR(-ENOMEM);
0139 
0140     mlx5e_build_trap_params(priv->mdev, netdev->max_mtu, priv->q_counter, t);
0141 
0142     t->priv     = priv;
0143     t->mdev     = priv->mdev;
0144     t->tstamp   = &priv->tstamp;
0145     t->pdev     = mlx5_core_dma_dev(priv->mdev);
0146     t->netdev   = priv->netdev;
0147     t->mkey_be  = cpu_to_be32(priv->mdev->mlx5e_res.hw_objs.mkey);
0148     t->stats    = &priv->trap_stats.ch;
0149 
0150     netif_napi_add(netdev, &t->napi, mlx5e_trap_napi_poll, 64);
0151 
0152     err = mlx5e_open_trap_rq(priv, t);
0153     if (unlikely(err))
0154         goto err_napi_del;
0155 
0156     err = mlx5e_create_trap_direct_rq_tir(t->mdev, &t->tir, t->rq.rqn);
0157     if (err)
0158         goto err_close_trap_rq;
0159 
0160     return t;
0161 
0162 err_close_trap_rq:
0163     mlx5e_close_trap_rq(&t->rq);
0164 err_napi_del:
0165     netif_napi_del(&t->napi);
0166     kvfree(t);
0167     return ERR_PTR(err);
0168 }
0169 
0170 void mlx5e_close_trap(struct mlx5e_trap *trap)
0171 {
0172     mlx5e_tir_destroy(&trap->tir);
0173     mlx5e_close_trap_rq(&trap->rq);
0174     netif_napi_del(&trap->napi);
0175     kvfree(trap);
0176 }
0177 
0178 static void mlx5e_activate_trap(struct mlx5e_trap *trap)
0179 {
0180     napi_enable(&trap->napi);
0181     mlx5e_activate_rq(&trap->rq);
0182     mlx5e_trigger_napi_sched(&trap->napi);
0183 }
0184 
0185 void mlx5e_deactivate_trap(struct mlx5e_priv *priv)
0186 {
0187     struct mlx5e_trap *trap = priv->en_trap;
0188 
0189     mlx5e_deactivate_rq(&trap->rq);
0190     napi_disable(&trap->napi);
0191 }
0192 
0193 static struct mlx5e_trap *mlx5e_add_trap_queue(struct mlx5e_priv *priv)
0194 {
0195     struct mlx5e_trap *trap;
0196 
0197     trap = mlx5e_open_trap(priv);
0198     if (IS_ERR(trap))
0199         goto out;
0200 
0201     mlx5e_activate_trap(trap);
0202 out:
0203     return trap;
0204 }
0205 
0206 static void mlx5e_del_trap_queue(struct mlx5e_priv *priv)
0207 {
0208     mlx5e_deactivate_trap(priv);
0209     mlx5e_close_trap(priv->en_trap);
0210     priv->en_trap = NULL;
0211 }
0212 
0213 static int mlx5e_trap_get_tirn(struct mlx5e_trap *en_trap)
0214 {
0215     return en_trap->tir.tirn;
0216 }
0217 
0218 static int mlx5e_handle_action_trap(struct mlx5e_priv *priv, int trap_id)
0219 {
0220     bool open_queue = !priv->en_trap;
0221     struct mlx5e_trap *trap;
0222     int err;
0223 
0224     if (open_queue) {
0225         trap = mlx5e_add_trap_queue(priv);
0226         if (IS_ERR(trap))
0227             return PTR_ERR(trap);
0228         priv->en_trap = trap;
0229     }
0230 
0231     switch (trap_id) {
0232     case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER:
0233         err = mlx5e_add_vlan_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
0234         if (err)
0235             goto err_out;
0236         break;
0237     case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER:
0238         err = mlx5e_add_mac_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
0239         if (err)
0240             goto err_out;
0241         break;
0242     default:
0243         netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id);
0244         err = -EINVAL;
0245         goto err_out;
0246     }
0247     return 0;
0248 
0249 err_out:
0250     if (open_queue)
0251         mlx5e_del_trap_queue(priv);
0252     return err;
0253 }
0254 
0255 static int mlx5e_handle_action_drop(struct mlx5e_priv *priv, int trap_id)
0256 {
0257     switch (trap_id) {
0258     case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER:
0259         mlx5e_remove_vlan_trap(priv);
0260         break;
0261     case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER:
0262         mlx5e_remove_mac_trap(priv);
0263         break;
0264     default:
0265         netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id);
0266         return -EINVAL;
0267     }
0268     if (priv->en_trap && !mlx5_devlink_trap_get_num_active(priv->mdev))
0269         mlx5e_del_trap_queue(priv);
0270 
0271     return 0;
0272 }
0273 
0274 int mlx5e_handle_trap_event(struct mlx5e_priv *priv, struct mlx5_trap_ctx *trap_ctx)
0275 {
0276     int err = 0;
0277 
0278     /* Traps are unarmed when interface is down, no need to update
0279      * them. The configuration is saved in the core driver,
0280      * queried and applied upon interface up operation in
0281      * mlx5e_open_locked().
0282      */
0283     if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
0284         return 0;
0285 
0286     switch (trap_ctx->action) {
0287     case DEVLINK_TRAP_ACTION_TRAP:
0288         err = mlx5e_handle_action_trap(priv, trap_ctx->id);
0289         break;
0290     case DEVLINK_TRAP_ACTION_DROP:
0291         err = mlx5e_handle_action_drop(priv, trap_ctx->id);
0292         break;
0293     default:
0294         netdev_warn(priv->netdev, "%s: Unsupported action %d\n", __func__,
0295                 trap_ctx->action);
0296         err = -EINVAL;
0297     }
0298     return err;
0299 }
0300 
0301 static int mlx5e_apply_trap(struct mlx5e_priv *priv, int trap_id, bool enable)
0302 {
0303     enum devlink_trap_action action;
0304     int err;
0305 
0306     err = mlx5_devlink_traps_get_action(priv->mdev, trap_id, &action);
0307     if (err)
0308         return err;
0309     if (action == DEVLINK_TRAP_ACTION_TRAP)
0310         err = enable ? mlx5e_handle_action_trap(priv, trap_id) :
0311                    mlx5e_handle_action_drop(priv, trap_id);
0312     return err;
0313 }
0314 
0315 static const int mlx5e_traps_arr[] = {
0316     DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER,
0317     DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER,
0318 };
0319 
0320 int mlx5e_apply_traps(struct mlx5e_priv *priv, bool enable)
0321 {
0322     int err;
0323     int i;
0324 
0325     for (i = 0; i < ARRAY_SIZE(mlx5e_traps_arr); i++) {
0326         err = mlx5e_apply_trap(priv, mlx5e_traps_arr[i], enable);
0327         if (err)
0328             return err;
0329     }
0330     return 0;
0331 }