255 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */3 4#include <linux/kernel.h>5#include <linux/slab.h>6 7#include "reg.h"8#include "core.h"9#include "spectrum.h"10#include "spectrum_acl_tcam.h"11 12struct mlxsw_sp1_acl_tcam_region {13 struct mlxsw_sp_acl_ctcam_region cregion;14 struct mlxsw_sp_acl_tcam_region *region;15 struct {16 struct mlxsw_sp_acl_ctcam_chunk cchunk;17 struct mlxsw_sp_acl_ctcam_entry centry;18 struct mlxsw_sp_acl_rule_info *rulei;19 } catchall;20};21 22struct mlxsw_sp1_acl_tcam_chunk {23 struct mlxsw_sp_acl_ctcam_chunk cchunk;24};25 26struct mlxsw_sp1_acl_tcam_entry {27 struct mlxsw_sp_acl_ctcam_entry centry;28};29 30static int31mlxsw_sp1_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *cregion,32 struct mlxsw_sp_acl_ctcam_entry *centry,33 const char *mask)34{35 return 0;36}37 38static void39mlxsw_sp1_acl_ctcam_region_entry_remove(struct mlxsw_sp_acl_ctcam_region *cregion,40 struct mlxsw_sp_acl_ctcam_entry *centry)41{42}43 44static const struct mlxsw_sp_acl_ctcam_region_ops45mlxsw_sp1_acl_ctcam_region_ops = {46 .entry_insert = mlxsw_sp1_acl_ctcam_region_entry_insert,47 .entry_remove = mlxsw_sp1_acl_ctcam_region_entry_remove,48};49 50static int mlxsw_sp1_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv,51 struct mlxsw_sp_acl_tcam *tcam)52{53 return 0;54}55 56static void mlxsw_sp1_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, void *priv)57{58}59 60static int61mlxsw_sp1_acl_ctcam_region_catchall_add(struct mlxsw_sp *mlxsw_sp,62 struct mlxsw_sp1_acl_tcam_region *region)63{64 struct mlxsw_sp_acl_rule_info *rulei;65 int err;66 67 mlxsw_sp_acl_ctcam_chunk_init(®ion->cregion,68 ®ion->catchall.cchunk,69 MLXSW_SP_ACL_TCAM_CATCHALL_PRIO);70 rulei = mlxsw_sp_acl_rulei_create(mlxsw_sp->acl, NULL);71 if (IS_ERR(rulei)) {72 err = PTR_ERR(rulei);73 goto err_rulei_create;74 }75 err = mlxsw_sp_acl_rulei_act_continue(rulei);76 if (WARN_ON(err))77 goto err_rulei_act_continue;78 err = mlxsw_sp_acl_rulei_commit(rulei);79 if (err)80 goto err_rulei_commit;81 err = mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, ®ion->cregion,82 ®ion->catchall.cchunk,83 ®ion->catchall.centry,84 rulei, false);85 if (err)86 goto err_entry_add;87 region->catchall.rulei = rulei;88 return 0;89 90err_entry_add:91err_rulei_commit:92err_rulei_act_continue:93 mlxsw_sp_acl_rulei_destroy(mlxsw_sp, rulei);94err_rulei_create:95 mlxsw_sp_acl_ctcam_chunk_fini(®ion->catchall.cchunk);96 return err;97}98 99static void100mlxsw_sp1_acl_ctcam_region_catchall_del(struct mlxsw_sp *mlxsw_sp,101 struct mlxsw_sp1_acl_tcam_region *region)102{103 struct mlxsw_sp_acl_rule_info *rulei = region->catchall.rulei;104 105 mlxsw_sp_acl_ctcam_entry_del(mlxsw_sp, ®ion->cregion,106 ®ion->catchall.cchunk,107 ®ion->catchall.centry);108 mlxsw_sp_acl_rulei_destroy(mlxsw_sp, rulei);109 mlxsw_sp_acl_ctcam_chunk_fini(®ion->catchall.cchunk);110}111 112static int113mlxsw_sp1_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv,114 void *tcam_priv,115 struct mlxsw_sp_acl_tcam_region *_region,116 void *hints_priv)117{118 struct mlxsw_sp1_acl_tcam_region *region = region_priv;119 int err;120 121 err = mlxsw_sp_acl_ctcam_region_init(mlxsw_sp, ®ion->cregion,122 _region,123 &mlxsw_sp1_acl_ctcam_region_ops);124 if (err)125 return err;126 err = mlxsw_sp1_acl_ctcam_region_catchall_add(mlxsw_sp, region);127 if (err)128 goto err_catchall_add;129 region->region = _region;130 return 0;131 132err_catchall_add:133 mlxsw_sp_acl_ctcam_region_fini(®ion->cregion);134 return err;135}136 137static void138mlxsw_sp1_acl_tcam_region_fini(struct mlxsw_sp *mlxsw_sp, void *region_priv)139{140 struct mlxsw_sp1_acl_tcam_region *region = region_priv;141 142 mlxsw_sp1_acl_ctcam_region_catchall_del(mlxsw_sp, region);143 mlxsw_sp_acl_ctcam_region_fini(®ion->cregion);144}145 146static int147mlxsw_sp1_acl_tcam_region_associate(struct mlxsw_sp *mlxsw_sp,148 struct mlxsw_sp_acl_tcam_region *region)149{150 return 0;151}152 153static void mlxsw_sp1_acl_tcam_chunk_init(void *region_priv, void *chunk_priv,154 unsigned int priority)155{156 struct mlxsw_sp1_acl_tcam_region *region = region_priv;157 struct mlxsw_sp1_acl_tcam_chunk *chunk = chunk_priv;158 159 mlxsw_sp_acl_ctcam_chunk_init(®ion->cregion, &chunk->cchunk,160 priority);161}162 163static void mlxsw_sp1_acl_tcam_chunk_fini(void *chunk_priv)164{165 struct mlxsw_sp1_acl_tcam_chunk *chunk = chunk_priv;166 167 mlxsw_sp_acl_ctcam_chunk_fini(&chunk->cchunk);168}169 170static int mlxsw_sp1_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp,171 void *region_priv, void *chunk_priv,172 void *entry_priv,173 struct mlxsw_sp_acl_rule_info *rulei)174{175 struct mlxsw_sp1_acl_tcam_region *region = region_priv;176 struct mlxsw_sp1_acl_tcam_chunk *chunk = chunk_priv;177 struct mlxsw_sp1_acl_tcam_entry *entry = entry_priv;178 179 return mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, ®ion->cregion,180 &chunk->cchunk, &entry->centry,181 rulei, false);182}183 184static void mlxsw_sp1_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,185 void *region_priv, void *chunk_priv,186 void *entry_priv)187{188 struct mlxsw_sp1_acl_tcam_region *region = region_priv;189 struct mlxsw_sp1_acl_tcam_chunk *chunk = chunk_priv;190 struct mlxsw_sp1_acl_tcam_entry *entry = entry_priv;191 192 mlxsw_sp_acl_ctcam_entry_del(mlxsw_sp, ®ion->cregion,193 &chunk->cchunk, &entry->centry);194}195 196static int197mlxsw_sp1_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,198 void *region_priv, void *entry_priv,199 struct mlxsw_sp_acl_rule_info *rulei)200{201 return -EOPNOTSUPP;202}203 204static int205mlxsw_sp1_acl_tcam_region_entry_activity_get(struct mlxsw_sp *mlxsw_sp,206 struct mlxsw_sp_acl_tcam_region *_region,207 unsigned int offset,208 bool *activity)209{210 char ptce2_pl[MLXSW_REG_PTCE2_LEN];211 int err;212 213 mlxsw_reg_ptce2_pack(ptce2_pl, true, MLXSW_REG_PTCE2_OP_QUERY_CLEAR_ON_READ,214 _region->tcam_region_info, offset, 0);215 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);216 if (err)217 return err;218 *activity = mlxsw_reg_ptce2_a_get(ptce2_pl);219 return 0;220}221 222static int223mlxsw_sp1_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp,224 void *region_priv, void *entry_priv,225 bool *activity)226{227 struct mlxsw_sp1_acl_tcam_region *region = region_priv;228 struct mlxsw_sp1_acl_tcam_entry *entry = entry_priv;229 unsigned int offset;230 231 offset = mlxsw_sp_acl_ctcam_entry_offset(&entry->centry);232 return mlxsw_sp1_acl_tcam_region_entry_activity_get(mlxsw_sp,233 region->region,234 offset, activity);235}236 237const struct mlxsw_sp_acl_tcam_ops mlxsw_sp1_acl_tcam_ops = {238 .key_type = MLXSW_REG_PTAR_KEY_TYPE_FLEX,239 .priv_size = 0,240 .init = mlxsw_sp1_acl_tcam_init,241 .fini = mlxsw_sp1_acl_tcam_fini,242 .region_priv_size = sizeof(struct mlxsw_sp1_acl_tcam_region),243 .region_init = mlxsw_sp1_acl_tcam_region_init,244 .region_fini = mlxsw_sp1_acl_tcam_region_fini,245 .region_associate = mlxsw_sp1_acl_tcam_region_associate,246 .chunk_priv_size = sizeof(struct mlxsw_sp1_acl_tcam_chunk),247 .chunk_init = mlxsw_sp1_acl_tcam_chunk_init,248 .chunk_fini = mlxsw_sp1_acl_tcam_chunk_fini,249 .entry_priv_size = sizeof(struct mlxsw_sp1_acl_tcam_entry),250 .entry_add = mlxsw_sp1_acl_tcam_entry_add,251 .entry_del = mlxsw_sp1_acl_tcam_entry_del,252 .entry_action_replace = mlxsw_sp1_acl_tcam_entry_action_replace,253 .entry_activity_get = mlxsw_sp1_acl_tcam_entry_activity_get,254};255