FILE
trap.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2020 Mellanox Technologies */ 3 4#include "en/txrx.h" 5#include "en/params.h" 6#include "en/trap.h" 7 8static int mlx5e_trap_napi_poll(struct napi_struct *napi, int budget) 9{ 10 struct mlx5e_trap *trap_ctx = container_of(napi, struct mlx5e_trap, napi); 11 struct mlx5e_ch_stats *ch_stats = trap_ctx->stats; 12 struct mlx5e_rq *rq = &trap_ctx->rq; 13 bool busy = false; 14 int work_done = 0; 15 16 rcu_read_lock(); 17 18 ch_stats->poll++; 19 20 work_done = mlx5e_poll_rx_cq(&rq->cq, budget); 21 busy |= work_done == budget; 22 busy |= rq->post_wqes(rq); 23 24 if (busy) { 25 work_done = budget; 26 goto out; 27 } 28 29 if (unlikely(!napi_complete_done(napi, work_done))) 30 goto out; 31 32 mlx5e_cq_arm(&rq->cq); 33 34out: 35 rcu_read_unlock(); 36 return work_done; 37} 38 39static void mlx5e_init_trap_rq(struct mlx5e_trap *t, struct mlx5e_params *params, 40 struct mlx5e_rq *rq) 41{ 42 struct mlx5_core_dev *mdev = t->mdev; 43 struct mlx5e_priv *priv = t->priv; 44 45 rq->wq_type = params->rq_wq_type; 46 rq->pdev = t->pdev; 47 rq->netdev = priv->netdev; 48 rq->priv = priv; 49 rq->clock = mdev->clock; 50 rq->hwtstamp_config = &priv->hwtstamp_config; 51 rq->mdev = mdev; 52 rq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); 53 rq->stats = &priv->trap_stats.rq; 54 rq->ptp_cyc2time = mlx5_rq_ts_translator(mdev); 55 xdp_rxq_info_unused(&rq->xdp_rxq); 56 mlx5e_rq_set_trap_handlers(rq, params); 57} 58 59static int mlx5e_open_trap_rq(struct mlx5e_priv *priv, struct mlx5e_trap *t) 60{ 61 struct mlx5e_rq_param *rq_param = &t->rq_param; 62 struct mlx5_core_dev *mdev = priv->mdev; 63 struct mlx5e_create_cq_param ccp = {}; 64 struct dim_cq_moder trap_moder = {}; 65 struct mlx5e_rq *rq = &t->rq; 66 u16 q_counter; 67 int node; 68 int err; 69 70 node = dev_to_node(mdev->device); 71 q_counter = priv->q_counter[0]; 72 73 ccp.netdev = priv->netdev; 74 ccp.wq = priv->wq; 75 ccp.node = node; 76 ccp.ch_stats = t->stats; 77 ccp.napi = &t->napi; 78 ccp.ix = 0; 79 ccp.uar = mdev->priv.bfreg.up; 80 err = mlx5e_open_cq(priv->mdev, trap_moder, &rq_param->cqp, &ccp, &rq->cq); 81 if (err) 82 return err; 83 84 mlx5e_init_trap_rq(t, &t->params, rq); 85 err = mlx5e_open_rq(&t->params, rq_param, NULL, node, q_counter, rq); 86 if (err) 87 goto err_destroy_cq; 88 89 return 0; 90 91err_destroy_cq: 92 mlx5e_close_cq(&rq->cq); 93 94 return err; 95} 96 97static void mlx5e_close_trap_rq(struct mlx5e_rq *rq) 98{ 99 mlx5e_close_rq(rq); 100 mlx5e_close_cq(&rq->cq); 101} 102 103static int mlx5e_create_trap_direct_rq_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir, 104 u32 rqn) 105{ 106 struct mlx5e_tir_builder *builder; 107 int err; 108 109 builder = mlx5e_tir_builder_alloc(false); 110 if (!builder) 111 return -ENOMEM; 112 113 mlx5e_tir_builder_build_inline(builder, mdev->mlx5e_res.hw_objs.td.tdn, rqn); 114 err = mlx5e_tir_init(tir, builder, mdev, true); 115 116 mlx5e_tir_builder_free(builder); 117 118 return err; 119} 120 121static void mlx5e_build_trap_params(struct mlx5_core_dev *mdev, 122 int max_mtu, struct mlx5e_trap *t) 123{ 124 struct mlx5e_params *params = &t->params; 125 126 params->rq_wq_type = MLX5_WQ_TYPE_CYCLIC; 127 mlx5e_init_rq_type_params(mdev, params); 128 params->sw_mtu = max_mtu; 129 mlx5e_build_rq_param(mdev, params, NULL, &t->rq_param); 130} 131 132static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_priv *priv) 133{ 134 int cpu = mlx5_comp_vector_get_cpu(priv->mdev, 0); 135 struct net_device *netdev = priv->netdev; 136 struct mlx5e_trap *t; 137 int err; 138 139 t = kvzalloc_node(sizeof(*t), GFP_KERNEL, cpu_to_node(cpu)); 140 if (!t) 141 return ERR_PTR(-ENOMEM); 142 143 mlx5e_build_trap_params(priv->mdev, netdev->max_mtu, t); 144 145 t->priv = priv; 146 t->mdev = priv->mdev; 147 t->pdev = mlx5_core_dma_dev(priv->mdev); 148 t->netdev = priv->netdev; 149 t->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.hw_objs.mkey); 150 t->stats = &priv->trap_stats.ch; 151 152 netif_napi_add_locked(netdev, &t->napi, mlx5e_trap_napi_poll); 153 154 err = mlx5e_open_trap_rq(priv, t); 155 if (unlikely(err)) 156 goto err_napi_del; 157 158 err = mlx5e_create_trap_direct_rq_tir(t->mdev, &t->tir, t->rq.rqn); 159 if (err) 160 goto err_close_trap_rq; 161 162 return t; 163 164err_close_trap_rq: 165 mlx5e_close_trap_rq(&t->rq); 166err_napi_del: 167 netif_napi_del_locked(&t->napi); 168 kvfree(t); 169 return ERR_PTR(err); 170} 171 172void mlx5e_close_trap(struct mlx5e_trap *trap) 173{ 174 mlx5e_tir_destroy(&trap->tir); 175 mlx5e_close_trap_rq(&trap->rq); 176 netif_napi_del_locked(&trap->napi); 177 kvfree(trap); 178} 179 180static void mlx5e_activate_trap(struct mlx5e_trap *trap) 181{ 182 napi_enable_locked(&trap->napi); 183 mlx5e_activate_rq(&trap->rq); 184 mlx5e_trigger_napi_sched(&trap->napi); 185} 186 187void mlx5e_deactivate_trap(struct mlx5e_priv *priv) 188{ 189 struct mlx5e_trap *trap = priv->en_trap; 190 191 mlx5e_deactivate_rq(&trap->rq); 192 napi_disable_locked(&trap->napi); 193} 194 195static struct mlx5e_trap *mlx5e_add_trap_queue(struct mlx5e_priv *priv) 196{ 197 struct mlx5e_trap *trap; 198 199 trap = mlx5e_open_trap(priv); 200 if (IS_ERR(trap)) 201 goto out; 202 203 mlx5e_activate_trap(trap); 204out: 205 return trap; 206} 207 208static void mlx5e_del_trap_queue(struct mlx5e_priv *priv) 209{ 210 mlx5e_deactivate_trap(priv); 211 mlx5e_close_trap(priv->en_trap); 212 priv->en_trap = NULL; 213} 214 215static int mlx5e_trap_get_tirn(struct mlx5e_trap *en_trap) 216{ 217 return en_trap->tir.tirn; 218} 219 220static int mlx5e_handle_action_trap(struct mlx5e_priv *priv, int trap_id) 221{ 222 bool open_queue = !priv->en_trap; 223 struct mlx5e_trap *trap; 224 int err; 225 226 if (open_queue) { 227 trap = mlx5e_add_trap_queue(priv); 228 if (IS_ERR(trap)) 229 return PTR_ERR(trap); 230 priv->en_trap = trap; 231 } 232 233 switch (trap_id) { 234 case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER: 235 err = mlx5e_add_vlan_trap(priv->fs, trap_id, mlx5e_trap_get_tirn(priv->en_trap)); 236 if (err) 237 goto err_out; 238 break; 239 case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER: 240 err = mlx5e_add_mac_trap(priv->fs, trap_id, mlx5e_trap_get_tirn(priv->en_trap)); 241 if (err) 242 goto err_out; 243 break; 244 default: 245 netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id); 246 err = -EINVAL; 247 goto err_out; 248 } 249 return 0; 250 251err_out: 252 if (open_queue) 253 mlx5e_del_trap_queue(priv); 254 return err; 255} 256 257static int mlx5e_handle_action_drop(struct mlx5e_priv *priv, int trap_id) 258{ 259 switch (trap_id) { 260 case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER: 261 mlx5e_remove_vlan_trap(priv->fs); 262 break; 263 case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER: 264 mlx5e_remove_mac_trap(priv->fs); 265 break; 266 default: 267 netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id); 268 return -EINVAL; 269 } 270 if (priv->en_trap && !mlx5_devlink_trap_get_num_active(priv->mdev)) 271 mlx5e_del_trap_queue(priv); 272 273 return 0; 274} 275 276int mlx5e_handle_trap_event(struct mlx5e_priv *priv, struct mlx5_trap_ctx *trap_ctx) 277{ 278 int err = 0; 279 280 /* Traps are unarmed when interface is down, no need to update 281 * them. The configuration is saved in the core driver, 282 * queried and applied upon interface up operation in 283 * mlx5e_open_locked(). 284 */ 285 if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) 286 return 0; 287 288 netdev_lock(priv->netdev); 289 switch (trap_ctx->action) { 290 case DEVLINK_TRAP_ACTION_TRAP: 291 err = mlx5e_handle_action_trap(priv, trap_ctx->id); 292 break; 293 case DEVLINK_TRAP_ACTION_DROP: 294 err = mlx5e_handle_action_drop(priv, trap_ctx->id); 295 break; 296 default: 297 netdev_warn(priv->netdev, "%s: Unsupported action %d\n", __func__, 298 trap_ctx->action); 299 err = -EINVAL; 300 } 301 netdev_unlock(priv->netdev); 302 return err; 303} 304 305static int mlx5e_apply_trap(struct mlx5e_priv *priv, int trap_id, bool enable) 306{ 307 enum devlink_trap_action action; 308 int err; 309 310 err = mlx5_devlink_traps_get_action(priv->mdev, trap_id, &action); 311 if (err) 312 return err; 313 if (action == DEVLINK_TRAP_ACTION_TRAP) 314 err = enable ? mlx5e_handle_action_trap(priv, trap_id) : 315 mlx5e_handle_action_drop(priv, trap_id); 316 return err; 317} 318 319static const int mlx5e_traps_arr[] = { 320 DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER, 321 DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER, 322}; 323 324int mlx5e_apply_traps(struct mlx5e_priv *priv, bool enable) 325{ 326 int err; 327 int i; 328 329 for (i = 0; i < ARRAY_SIZE(mlx5e_traps_arr); i++) { 330 err = mlx5e_apply_trap(priv, mlx5e_traps_arr[i], enable); 331 if (err) 332 return err; 333 } 334 return 0; 335}
~/
Read-only file preview.