spectrum1_acl_tcam.c (7314B)
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2/* 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 int 31mlxsw_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 void 39mlxsw_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_ops 45mlxsw_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 int 61mlxsw_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(rulei); 94err_rulei_create: 95 mlxsw_sp_acl_ctcam_chunk_fini(®ion->catchall.cchunk); 96 return err; 97} 98 99static void 100mlxsw_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(rulei); 109 mlxsw_sp_acl_ctcam_chunk_fini(®ion->catchall.cchunk); 110} 111 112static int 113mlxsw_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 void 138mlxsw_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 int 147mlxsw_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 int 197mlxsw_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 int 205mlxsw_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 int 223mlxsw_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};