root/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mlxsw_sp2_acl_ctcam_region_entry_insert
  2. mlxsw_sp2_acl_ctcam_region_entry_remove
  3. mlxsw_sp2_acl_tcam_init
  4. mlxsw_sp2_acl_tcam_fini
  5. mlxsw_sp2_acl_tcam_region_init
  6. mlxsw_sp2_acl_tcam_region_fini
  7. mlxsw_sp2_acl_tcam_region_associate
  8. mlxsw_sp2_acl_tcam_region_rehash_hints_get
  9. mlxsw_sp2_acl_tcam_region_rehash_hints_put
  10. mlxsw_sp2_acl_tcam_chunk_init
  11. mlxsw_sp2_acl_tcam_chunk_fini
  12. mlxsw_sp2_acl_tcam_entry_add
  13. mlxsw_sp2_acl_tcam_entry_del
  14. mlxsw_sp2_acl_tcam_entry_action_replace
  15. mlxsw_sp2_acl_tcam_entry_activity_get

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
   3 
   4 #include <linux/kernel.h>
   5 
   6 #include "spectrum.h"
   7 #include "spectrum_acl_tcam.h"
   8 #include "core_acl_flex_actions.h"
   9 
  10 struct mlxsw_sp2_acl_tcam {
  11         struct mlxsw_sp_acl_atcam atcam;
  12         u32 kvdl_index;
  13         unsigned int kvdl_count;
  14 };
  15 
  16 struct mlxsw_sp2_acl_tcam_region {
  17         struct mlxsw_sp_acl_atcam_region aregion;
  18         struct mlxsw_sp_acl_tcam_region *region;
  19 };
  20 
  21 struct mlxsw_sp2_acl_tcam_chunk {
  22         struct mlxsw_sp_acl_atcam_chunk achunk;
  23 };
  24 
  25 struct mlxsw_sp2_acl_tcam_entry {
  26         struct mlxsw_sp_acl_atcam_entry aentry;
  27         struct mlxsw_afa_block *act_block;
  28 };
  29 
  30 static int
  31 mlxsw_sp2_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         struct mlxsw_sp_acl_atcam_region *aregion;
  36         struct mlxsw_sp_acl_atcam_entry *aentry;
  37         struct mlxsw_sp_acl_erp_mask *erp_mask;
  38 
  39         aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion);
  40         aentry = mlxsw_sp_acl_tcam_centry_aentry(centry);
  41 
  42         erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, true);
  43         if (IS_ERR(erp_mask))
  44                 return PTR_ERR(erp_mask);
  45         aentry->erp_mask = erp_mask;
  46 
  47         return 0;
  48 }
  49 
  50 static void
  51 mlxsw_sp2_acl_ctcam_region_entry_remove(struct mlxsw_sp_acl_ctcam_region *cregion,
  52                                         struct mlxsw_sp_acl_ctcam_entry *centry)
  53 {
  54         struct mlxsw_sp_acl_atcam_region *aregion;
  55         struct mlxsw_sp_acl_atcam_entry *aentry;
  56 
  57         aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion);
  58         aentry = mlxsw_sp_acl_tcam_centry_aentry(centry);
  59 
  60         mlxsw_sp_acl_erp_mask_put(aregion, aentry->erp_mask);
  61 }
  62 
  63 static const struct mlxsw_sp_acl_ctcam_region_ops
  64 mlxsw_sp2_acl_ctcam_region_ops = {
  65         .entry_insert = mlxsw_sp2_acl_ctcam_region_entry_insert,
  66         .entry_remove = mlxsw_sp2_acl_ctcam_region_entry_remove,
  67 };
  68 
  69 static int mlxsw_sp2_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv,
  70                                    struct mlxsw_sp_acl_tcam *_tcam)
  71 {
  72         struct mlxsw_sp2_acl_tcam *tcam = priv;
  73         struct mlxsw_afa_block *afa_block;
  74         char pefa_pl[MLXSW_REG_PEFA_LEN];
  75         char pgcr_pl[MLXSW_REG_PGCR_LEN];
  76         char *enc_actions;
  77         int i;
  78         int err;
  79 
  80         tcam->kvdl_count = _tcam->max_regions;
  81         err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET,
  82                                   tcam->kvdl_count, &tcam->kvdl_index);
  83         if (err)
  84                 return err;
  85 
  86         /* Create flex action block, set default action (continue)
  87          * but don't commit. We need just the current set encoding
  88          * to be written using PEFA register to all indexes for all regions.
  89          */
  90         afa_block = mlxsw_afa_block_create(mlxsw_sp->afa);
  91         if (IS_ERR(afa_block)) {
  92                 err = PTR_ERR(afa_block);
  93                 goto err_afa_block;
  94         }
  95         err = mlxsw_afa_block_continue(afa_block);
  96         if (WARN_ON(err))
  97                 goto err_afa_block_continue;
  98         enc_actions = mlxsw_afa_block_cur_set(afa_block);
  99 
 100         for (i = 0; i < tcam->kvdl_count; i++) {
 101                 mlxsw_reg_pefa_pack(pefa_pl, tcam->kvdl_index + i,
 102                                     true, enc_actions);
 103                 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pefa), pefa_pl);
 104                 if (err)
 105                         goto err_pefa_write;
 106         }
 107         mlxsw_reg_pgcr_pack(pgcr_pl, tcam->kvdl_index);
 108         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pgcr), pgcr_pl);
 109         if (err)
 110                 goto err_pgcr_write;
 111 
 112         err = mlxsw_sp_acl_atcam_init(mlxsw_sp, &tcam->atcam);
 113         if (err)
 114                 goto err_atcam_init;
 115 
 116         mlxsw_afa_block_destroy(afa_block);
 117         return 0;
 118 
 119 err_atcam_init:
 120 err_pgcr_write:
 121 err_pefa_write:
 122 err_afa_block_continue:
 123         mlxsw_afa_block_destroy(afa_block);
 124 err_afa_block:
 125         mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET,
 126                            tcam->kvdl_count, tcam->kvdl_index);
 127         return err;
 128 }
 129 
 130 static void mlxsw_sp2_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, void *priv)
 131 {
 132         struct mlxsw_sp2_acl_tcam *tcam = priv;
 133 
 134         mlxsw_sp_acl_atcam_fini(mlxsw_sp, &tcam->atcam);
 135         mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET,
 136                            tcam->kvdl_count, tcam->kvdl_index);
 137 }
 138 
 139 static int
 140 mlxsw_sp2_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv,
 141                                void *tcam_priv,
 142                                struct mlxsw_sp_acl_tcam_region *_region,
 143                                void *hints_priv)
 144 {
 145         struct mlxsw_sp2_acl_tcam_region *region = region_priv;
 146         struct mlxsw_sp2_acl_tcam *tcam = tcam_priv;
 147 
 148         region->region = _region;
 149 
 150         return mlxsw_sp_acl_atcam_region_init(mlxsw_sp, &tcam->atcam,
 151                                               &region->aregion,
 152                                               _region, hints_priv,
 153                                               &mlxsw_sp2_acl_ctcam_region_ops);
 154 }
 155 
 156 static void
 157 mlxsw_sp2_acl_tcam_region_fini(struct mlxsw_sp *mlxsw_sp, void *region_priv)
 158 {
 159         struct mlxsw_sp2_acl_tcam_region *region = region_priv;
 160 
 161         mlxsw_sp_acl_atcam_region_fini(&region->aregion);
 162 }
 163 
 164 static int
 165 mlxsw_sp2_acl_tcam_region_associate(struct mlxsw_sp *mlxsw_sp,
 166                                     struct mlxsw_sp_acl_tcam_region *region)
 167 {
 168         return mlxsw_sp_acl_atcam_region_associate(mlxsw_sp, region->id);
 169 }
 170 
 171 static void *mlxsw_sp2_acl_tcam_region_rehash_hints_get(void *region_priv)
 172 {
 173         struct mlxsw_sp2_acl_tcam_region *region = region_priv;
 174 
 175         return mlxsw_sp_acl_atcam_rehash_hints_get(&region->aregion);
 176 }
 177 
 178 static void mlxsw_sp2_acl_tcam_region_rehash_hints_put(void *hints_priv)
 179 {
 180         mlxsw_sp_acl_atcam_rehash_hints_put(hints_priv);
 181 }
 182 
 183 static void mlxsw_sp2_acl_tcam_chunk_init(void *region_priv, void *chunk_priv,
 184                                           unsigned int priority)
 185 {
 186         struct mlxsw_sp2_acl_tcam_region *region = region_priv;
 187         struct mlxsw_sp2_acl_tcam_chunk *chunk = chunk_priv;
 188 
 189         mlxsw_sp_acl_atcam_chunk_init(&region->aregion, &chunk->achunk,
 190                                       priority);
 191 }
 192 
 193 static void mlxsw_sp2_acl_tcam_chunk_fini(void *chunk_priv)
 194 {
 195         struct mlxsw_sp2_acl_tcam_chunk *chunk = chunk_priv;
 196 
 197         mlxsw_sp_acl_atcam_chunk_fini(&chunk->achunk);
 198 }
 199 
 200 static int mlxsw_sp2_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp,
 201                                         void *region_priv, void *chunk_priv,
 202                                         void *entry_priv,
 203                                         struct mlxsw_sp_acl_rule_info *rulei)
 204 {
 205         struct mlxsw_sp2_acl_tcam_region *region = region_priv;
 206         struct mlxsw_sp2_acl_tcam_chunk *chunk = chunk_priv;
 207         struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv;
 208 
 209         entry->act_block = rulei->act_block;
 210         return mlxsw_sp_acl_atcam_entry_add(mlxsw_sp, &region->aregion,
 211                                             &chunk->achunk, &entry->aentry,
 212                                             rulei);
 213 }
 214 
 215 static void mlxsw_sp2_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
 216                                          void *region_priv, void *chunk_priv,
 217                                          void *entry_priv)
 218 {
 219         struct mlxsw_sp2_acl_tcam_region *region = region_priv;
 220         struct mlxsw_sp2_acl_tcam_chunk *chunk = chunk_priv;
 221         struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv;
 222 
 223         mlxsw_sp_acl_atcam_entry_del(mlxsw_sp, &region->aregion, &chunk->achunk,
 224                                      &entry->aentry);
 225 }
 226 
 227 static int
 228 mlxsw_sp2_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
 229                                         void *region_priv, void *entry_priv,
 230                                         struct mlxsw_sp_acl_rule_info *rulei)
 231 {
 232         struct mlxsw_sp2_acl_tcam_region *region = region_priv;
 233         struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv;
 234 
 235         entry->act_block = rulei->act_block;
 236         return mlxsw_sp_acl_atcam_entry_action_replace(mlxsw_sp,
 237                                                        &region->aregion,
 238                                                        &entry->aentry, rulei);
 239 }
 240 
 241 static int
 242 mlxsw_sp2_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
 243                                       void *region_priv, void *entry_priv,
 244                                       bool *activity)
 245 {
 246         struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv;
 247 
 248         return mlxsw_afa_block_activity_get(entry->act_block, activity);
 249 }
 250 
 251 const struct mlxsw_sp_acl_tcam_ops mlxsw_sp2_acl_tcam_ops = {
 252         .key_type               = MLXSW_REG_PTAR_KEY_TYPE_FLEX2,
 253         .priv_size              = sizeof(struct mlxsw_sp2_acl_tcam),
 254         .init                   = mlxsw_sp2_acl_tcam_init,
 255         .fini                   = mlxsw_sp2_acl_tcam_fini,
 256         .region_priv_size       = sizeof(struct mlxsw_sp2_acl_tcam_region),
 257         .region_init            = mlxsw_sp2_acl_tcam_region_init,
 258         .region_fini            = mlxsw_sp2_acl_tcam_region_fini,
 259         .region_associate       = mlxsw_sp2_acl_tcam_region_associate,
 260         .region_rehash_hints_get = mlxsw_sp2_acl_tcam_region_rehash_hints_get,
 261         .region_rehash_hints_put = mlxsw_sp2_acl_tcam_region_rehash_hints_put,
 262         .chunk_priv_size        = sizeof(struct mlxsw_sp2_acl_tcam_chunk),
 263         .chunk_init             = mlxsw_sp2_acl_tcam_chunk_init,
 264         .chunk_fini             = mlxsw_sp2_acl_tcam_chunk_fini,
 265         .entry_priv_size        = sizeof(struct mlxsw_sp2_acl_tcam_entry),
 266         .entry_add              = mlxsw_sp2_acl_tcam_entry_add,
 267         .entry_del              = mlxsw_sp2_acl_tcam_entry_del,
 268         .entry_action_replace   = mlxsw_sp2_acl_tcam_entry_action_replace,
 269         .entry_activity_get     = mlxsw_sp2_acl_tcam_entry_activity_get,
 270 };

/* [<][>][^][v][top][bottom][index][help] */