1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 4 #include "en_tc.h" 5 #include "post_act.h" 6 #include "mlx5_core.h" 7 #include "fs_core.h" 8 9 struct mlx5e_post_act { 10 enum mlx5_flow_namespace_type ns_type; 11 struct mlx5_fs_chains *chains; 12 struct mlx5_flow_table *ft; 13 struct mlx5e_priv *priv; 14 struct xarray ids; 15 }; 16 17 struct mlx5e_post_act_handle { 18 enum mlx5_flow_namespace_type ns_type; 19 struct mlx5_flow_attr *attr; 20 struct mlx5_flow_handle *rule; 21 u32 id; 22 }; 23 24 #define MLX5_POST_ACTION_BITS (mlx5e_tc_attr_to_reg_mappings[FTEID_TO_REG].mlen) 25 #define MLX5_POST_ACTION_MAX GENMASK(MLX5_POST_ACTION_BITS - 1, 0) 26 #define MLX5_POST_ACTION_MASK MLX5_POST_ACTION_MAX 27 28 struct mlx5e_post_act * 29 mlx5e_tc_post_act_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains, 30 enum mlx5_flow_namespace_type ns_type) 31 { 32 enum fs_flow_table_type table_type = ns_type == MLX5_FLOW_NAMESPACE_FDB ? 33 FS_FT_FDB : FS_FT_NIC_RX; 34 struct mlx5e_post_act *post_act; 35 int err; 36 37 if (!MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, ignore_flow_level, table_type)) { 38 if (priv->mdev->coredev_type != MLX5_COREDEV_VF) 39 mlx5_core_warn(priv->mdev, "firmware level support is missing\n"); 40 err = -EOPNOTSUPP; 41 goto err_check; 42 } 43 44 post_act = kzalloc(sizeof(*post_act), GFP_KERNEL); 45 if (!post_act) { 46 err = -ENOMEM; 47 goto err_check; 48 } 49 post_act->ft = mlx5_chains_create_global_table(chains); 50 if (IS_ERR(post_act->ft)) { 51 err = PTR_ERR(post_act->ft); 52 mlx5_core_warn(priv->mdev, "failed to create post action table, err: %d\n", err); 53 goto err_ft; 54 } 55 post_act->chains = chains; 56 post_act->ns_type = ns_type; 57 post_act->priv = priv; 58 xa_init_flags(&post_act->ids, XA_FLAGS_ALLOC1); 59 return post_act; 60 61 err_ft: 62 kfree(post_act); 63 err_check: 64 return ERR_PTR(err); 65 } 66 67 void 68 mlx5e_tc_post_act_destroy(struct mlx5e_post_act *post_act) 69 { 70 if (IS_ERR_OR_NULL(post_act)) 71 return; 72 73 xa_destroy(&post_act->ids); 74 mlx5_chains_destroy_global_table(post_act->chains, post_act->ft); 75 kfree(post_act); 76 } 77 78 struct mlx5e_post_act_handle * 79 mlx5e_tc_post_act_add(struct mlx5e_post_act *post_act, struct mlx5_flow_attr *attr) 80 { 81 u32 attr_sz = ns_to_attr_sz(post_act->ns_type); 82 struct mlx5e_post_act_handle *handle = NULL; 83 struct mlx5_flow_attr *post_attr = NULL; 84 struct mlx5_flow_spec *spec = NULL; 85 int err; 86 87 handle = kzalloc(sizeof(*handle), GFP_KERNEL); 88 spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 89 post_attr = mlx5_alloc_flow_attr(post_act->ns_type); 90 if (!handle || !spec || !post_attr) { 91 kfree(post_attr); 92 kvfree(spec); 93 kfree(handle); 94 return ERR_PTR(-ENOMEM); 95 } 96 97 memcpy(post_attr, attr, attr_sz); 98 post_attr->chain = 0; 99 post_attr->prio = 0; 100 post_attr->ft = post_act->ft; 101 post_attr->inner_match_level = MLX5_MATCH_NONE; 102 post_attr->outer_match_level = MLX5_MATCH_NONE; 103 post_attr->action &= ~(MLX5_FLOW_CONTEXT_ACTION_DECAP); 104 105 handle->ns_type = post_act->ns_type; 106 /* Splits were handled before post action */ 107 if (handle->ns_type == MLX5_FLOW_NAMESPACE_FDB) 108 post_attr->esw_attr->split_count = 0; 109 110 err = xa_alloc(&post_act->ids, &handle->id, post_attr, 111 XA_LIMIT(1, MLX5_POST_ACTION_MAX), GFP_KERNEL); 112 if (err) 113 goto err_xarray; 114 115 /* Post action rule matches on fte_id and executes original rule's 116 * tc rule action 117 */ 118 mlx5e_tc_match_to_reg_match(spec, FTEID_TO_REG, 119 handle->id, MLX5_POST_ACTION_MASK); 120 121 handle->rule = mlx5_tc_rule_insert(post_act->priv, spec, post_attr); 122 if (IS_ERR(handle->rule)) { 123 err = PTR_ERR(handle->rule); 124 netdev_warn(post_act->priv->netdev, "Failed to add post action rule"); 125 goto err_rule; 126 } 127 handle->attr = post_attr; 128 129 kvfree(spec); 130 return handle; 131 132 err_rule: 133 xa_erase(&post_act->ids, handle->id); 134 err_xarray: 135 kfree(post_attr); 136 kvfree(spec); 137 kfree(handle); 138 return ERR_PTR(err); 139 } 140 141 void 142 mlx5e_tc_post_act_del(struct mlx5e_post_act *post_act, struct mlx5e_post_act_handle *handle) 143 { 144 mlx5_tc_rule_delete(post_act->priv, handle->rule, handle->attr); 145 xa_erase(&post_act->ids, handle->id); 146 kfree(handle->attr); 147 kfree(handle); 148 } 149 150 struct mlx5_flow_table * 151 mlx5e_tc_post_act_get_ft(struct mlx5e_post_act *post_act) 152 { 153 return post_act->ft; 154 } 155 156 /* Allocate a header modify action to write the post action handle fte id to a register. */ 157 int 158 mlx5e_tc_post_act_set_handle(struct mlx5_core_dev *dev, 159 struct mlx5e_post_act_handle *handle, 160 struct mlx5e_tc_mod_hdr_acts *acts) 161 { 162 return mlx5e_tc_match_to_reg_set(dev, acts, handle->ns_type, FTEID_TO_REG, handle->id); 163 } 164