1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2020 Mellanox Technologies */
4 #include <net/page_pool.h>
9 static int mlx5e_trap_napi_poll(struct napi_struct *napi, int budget)
11 struct mlx5e_trap *trap_ctx = container_of(napi, struct mlx5e_trap, napi);
12 struct mlx5e_ch_stats *ch_stats = trap_ctx->stats;
13 struct mlx5e_rq *rq = &trap_ctx->rq;
19 work_done = mlx5e_poll_rx_cq(&rq->cq, budget);
20 busy |= work_done == budget;
21 busy |= rq->post_wqes(rq);
26 if (unlikely(!napi_complete_done(napi, work_done)))
29 mlx5e_cq_arm(&rq->cq);
33 static void mlx5e_init_trap_rq(struct mlx5e_trap *t, struct mlx5e_params *params,
36 struct mlx5_core_dev *mdev = t->mdev;
37 struct mlx5e_priv *priv = t->priv;
39 rq->wq_type = params->rq_wq_type;
40 rq->pdev = mdev->device;
41 rq->netdev = priv->netdev;
43 rq->clock = &mdev->clock;
44 rq->tstamp = &priv->tstamp;
46 rq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
47 rq->stats = &priv->trap_stats.rq;
48 rq->ptp_cyc2time = mlx5_rq_ts_translator(mdev);
49 xdp_rxq_info_unused(&rq->xdp_rxq);
50 mlx5e_rq_set_trap_handlers(rq, params);
53 static int mlx5e_open_trap_rq(struct mlx5e_priv *priv, struct mlx5e_trap *t)
55 struct mlx5e_rq_param *rq_param = &t->rq_param;
56 struct mlx5_core_dev *mdev = priv->mdev;
57 struct mlx5e_create_cq_param ccp = {};
58 struct dim_cq_moder trap_moder = {};
59 struct mlx5e_rq *rq = &t->rq;
63 node = dev_to_node(mdev->device);
66 ccp.ch_stats = t->stats;
69 err = mlx5e_open_cq(priv, trap_moder, &rq_param->cqp, &ccp, &rq->cq);
73 mlx5e_init_trap_rq(t, &t->params, rq);
74 err = mlx5e_open_rq(&t->params, rq_param, NULL, node, rq);
81 mlx5e_close_cq(&rq->cq);
86 static void mlx5e_close_trap_rq(struct mlx5e_rq *rq)
89 mlx5e_close_cq(&rq->cq);
92 static int mlx5e_create_trap_direct_rq_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir,
100 inlen = MLX5_ST_SZ_BYTES(create_tir_in);
101 in = kvzalloc(inlen, GFP_KERNEL);
105 tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
106 MLX5_SET(tirc, tirc, transport_domain, mdev->mlx5e_res.hw_objs.td.tdn);
107 MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_NONE);
108 MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT);
109 MLX5_SET(tirc, tirc, inline_rqn, rqn);
110 err = mlx5e_create_tir(mdev, tir, in);
116 static void mlx5e_destroy_trap_direct_rq_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir)
118 mlx5e_destroy_tir(mdev, tir);
121 static void mlx5e_build_trap_params(struct mlx5_core_dev *mdev,
122 int max_mtu, u16 q_counter,
123 struct mlx5e_trap *t)
125 struct mlx5e_params *params = &t->params;
127 params->rq_wq_type = MLX5_WQ_TYPE_CYCLIC;
128 mlx5e_init_rq_type_params(mdev, params);
129 params->sw_mtu = max_mtu;
130 mlx5e_build_rq_param(mdev, params, NULL, q_counter, &t->rq_param);
133 static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_priv *priv)
135 int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(priv->mdev, 0));
136 struct net_device *netdev = priv->netdev;
137 struct mlx5e_trap *t;
140 t = kvzalloc_node(sizeof(*t), GFP_KERNEL, cpu_to_node(cpu));
142 return ERR_PTR(-ENOMEM);
144 mlx5e_build_trap_params(priv->mdev, netdev->max_mtu, priv->q_counter, t);
147 t->mdev = priv->mdev;
148 t->tstamp = &priv->tstamp;
149 t->pdev = mlx5_core_dma_dev(priv->mdev);
150 t->netdev = priv->netdev;
151 t->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.hw_objs.mkey.key);
152 t->stats = &priv->trap_stats.ch;
154 netif_napi_add(netdev, &t->napi, mlx5e_trap_napi_poll, 64);
156 err = mlx5e_open_trap_rq(priv, t);
160 err = mlx5e_create_trap_direct_rq_tir(t->mdev, &t->tir, t->rq.rqn);
162 goto err_close_trap_rq;
167 mlx5e_close_trap_rq(&t->rq);
169 netif_napi_del(&t->napi);
174 void mlx5e_close_trap(struct mlx5e_trap *trap)
176 mlx5e_destroy_trap_direct_rq_tir(trap->mdev, &trap->tir);
177 mlx5e_close_trap_rq(&trap->rq);
178 netif_napi_del(&trap->napi);
182 static void mlx5e_activate_trap(struct mlx5e_trap *trap)
184 napi_enable(&trap->napi);
185 mlx5e_activate_rq(&trap->rq);
188 void mlx5e_deactivate_trap(struct mlx5e_priv *priv)
190 struct mlx5e_trap *trap = priv->en_trap;
192 mlx5e_deactivate_rq(&trap->rq);
193 napi_disable(&trap->napi);
196 static struct mlx5e_trap *mlx5e_add_trap_queue(struct mlx5e_priv *priv)
198 struct mlx5e_trap *trap;
200 trap = mlx5e_open_trap(priv);
204 mlx5e_activate_trap(trap);
209 static void mlx5e_del_trap_queue(struct mlx5e_priv *priv)
211 mlx5e_deactivate_trap(priv);
212 mlx5e_close_trap(priv->en_trap);
213 priv->en_trap = NULL;
216 static int mlx5e_trap_get_tirn(struct mlx5e_trap *en_trap)
218 return en_trap->tir.tirn;
221 static int mlx5e_handle_action_trap(struct mlx5e_priv *priv, int trap_id)
223 bool open_queue = !priv->en_trap;
224 struct mlx5e_trap *trap;
228 trap = mlx5e_add_trap_queue(priv);
230 return PTR_ERR(trap);
231 priv->en_trap = trap;
235 case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER:
236 err = mlx5e_add_vlan_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
240 case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER:
241 err = mlx5e_add_mac_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
246 netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id);
254 mlx5e_del_trap_queue(priv);
258 static int mlx5e_handle_action_drop(struct mlx5e_priv *priv, int trap_id)
261 case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER:
262 mlx5e_remove_vlan_trap(priv);
264 case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER:
265 mlx5e_remove_mac_trap(priv);
268 netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id);
271 if (priv->en_trap && !mlx5_devlink_trap_get_num_active(priv->mdev))
272 mlx5e_del_trap_queue(priv);
277 int mlx5e_handle_trap_event(struct mlx5e_priv *priv, struct mlx5_trap_ctx *trap_ctx)
281 /* Traps are unarmed when interface is down, no need to update
282 * them. The configuration is saved in the core driver,
283 * queried and applied upon interface up operation in
284 * mlx5e_open_locked().
286 if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
289 switch (trap_ctx->action) {
290 case DEVLINK_TRAP_ACTION_TRAP:
291 err = mlx5e_handle_action_trap(priv, trap_ctx->id);
293 case DEVLINK_TRAP_ACTION_DROP:
294 err = mlx5e_handle_action_drop(priv, trap_ctx->id);
297 netdev_warn(priv->netdev, "%s: Unsupported action %d\n", __func__,
304 static int mlx5e_apply_trap(struct mlx5e_priv *priv, int trap_id, bool enable)
306 enum devlink_trap_action action;
309 err = mlx5_devlink_traps_get_action(priv->mdev, trap_id, &action);
312 if (action == DEVLINK_TRAP_ACTION_TRAP)
313 err = enable ? mlx5e_handle_action_trap(priv, trap_id) :
314 mlx5e_handle_action_drop(priv, trap_id);
318 static const int mlx5e_traps_arr[] = {
319 DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER,
320 DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER,
323 int mlx5e_apply_traps(struct mlx5e_priv *priv, bool enable)
328 for (i = 0; i < ARRAY_SIZE(mlx5e_traps_arr); i++) {
329 err = mlx5e_apply_trap(priv, mlx5e_traps_arr[i], enable);