Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
0003 
0004 #include <linux/kernel.h>
0005 #include <linux/slab.h>
0006 
0007 #include "reg.h"
0008 #include "core.h"
0009 #include "spectrum.h"
0010 #include "spectrum_acl_tcam.h"
0011 
0012 struct mlxsw_sp1_acl_tcam_region {
0013     struct mlxsw_sp_acl_ctcam_region cregion;
0014     struct mlxsw_sp_acl_tcam_region *region;
0015     struct {
0016         struct mlxsw_sp_acl_ctcam_chunk cchunk;
0017         struct mlxsw_sp_acl_ctcam_entry centry;
0018         struct mlxsw_sp_acl_rule_info *rulei;
0019     } catchall;
0020 };
0021 
0022 struct mlxsw_sp1_acl_tcam_chunk {
0023     struct mlxsw_sp_acl_ctcam_chunk cchunk;
0024 };
0025 
0026 struct mlxsw_sp1_acl_tcam_entry {
0027     struct mlxsw_sp_acl_ctcam_entry centry;
0028 };
0029 
0030 static int
0031 mlxsw_sp1_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *cregion,
0032                     struct mlxsw_sp_acl_ctcam_entry *centry,
0033                     const char *mask)
0034 {
0035     return 0;
0036 }
0037 
0038 static void
0039 mlxsw_sp1_acl_ctcam_region_entry_remove(struct mlxsw_sp_acl_ctcam_region *cregion,
0040                     struct mlxsw_sp_acl_ctcam_entry *centry)
0041 {
0042 }
0043 
0044 static const struct mlxsw_sp_acl_ctcam_region_ops
0045 mlxsw_sp1_acl_ctcam_region_ops = {
0046     .entry_insert = mlxsw_sp1_acl_ctcam_region_entry_insert,
0047     .entry_remove = mlxsw_sp1_acl_ctcam_region_entry_remove,
0048 };
0049 
0050 static int mlxsw_sp1_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv,
0051                    struct mlxsw_sp_acl_tcam *tcam)
0052 {
0053     return 0;
0054 }
0055 
0056 static void mlxsw_sp1_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, void *priv)
0057 {
0058 }
0059 
0060 static int
0061 mlxsw_sp1_acl_ctcam_region_catchall_add(struct mlxsw_sp *mlxsw_sp,
0062                     struct mlxsw_sp1_acl_tcam_region *region)
0063 {
0064     struct mlxsw_sp_acl_rule_info *rulei;
0065     int err;
0066 
0067     mlxsw_sp_acl_ctcam_chunk_init(&region->cregion,
0068                       &region->catchall.cchunk,
0069                       MLXSW_SP_ACL_TCAM_CATCHALL_PRIO);
0070     rulei = mlxsw_sp_acl_rulei_create(mlxsw_sp->acl, NULL);
0071     if (IS_ERR(rulei)) {
0072         err = PTR_ERR(rulei);
0073         goto err_rulei_create;
0074     }
0075     err = mlxsw_sp_acl_rulei_act_continue(rulei);
0076     if (WARN_ON(err))
0077         goto err_rulei_act_continue;
0078     err = mlxsw_sp_acl_rulei_commit(rulei);
0079     if (err)
0080         goto err_rulei_commit;
0081     err = mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, &region->cregion,
0082                        &region->catchall.cchunk,
0083                        &region->catchall.centry,
0084                        rulei, false);
0085     if (err)
0086         goto err_entry_add;
0087     region->catchall.rulei = rulei;
0088     return 0;
0089 
0090 err_entry_add:
0091 err_rulei_commit:
0092 err_rulei_act_continue:
0093     mlxsw_sp_acl_rulei_destroy(rulei);
0094 err_rulei_create:
0095     mlxsw_sp_acl_ctcam_chunk_fini(&region->catchall.cchunk);
0096     return err;
0097 }
0098 
0099 static void
0100 mlxsw_sp1_acl_ctcam_region_catchall_del(struct mlxsw_sp *mlxsw_sp,
0101                     struct mlxsw_sp1_acl_tcam_region *region)
0102 {
0103     struct mlxsw_sp_acl_rule_info *rulei = region->catchall.rulei;
0104 
0105     mlxsw_sp_acl_ctcam_entry_del(mlxsw_sp, &region->cregion,
0106                      &region->catchall.cchunk,
0107                      &region->catchall.centry);
0108     mlxsw_sp_acl_rulei_destroy(rulei);
0109     mlxsw_sp_acl_ctcam_chunk_fini(&region->catchall.cchunk);
0110 }
0111 
0112 static int
0113 mlxsw_sp1_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv,
0114                    void *tcam_priv,
0115                    struct mlxsw_sp_acl_tcam_region *_region,
0116                    void *hints_priv)
0117 {
0118     struct mlxsw_sp1_acl_tcam_region *region = region_priv;
0119     int err;
0120 
0121     err = mlxsw_sp_acl_ctcam_region_init(mlxsw_sp, &region->cregion,
0122                          _region,
0123                          &mlxsw_sp1_acl_ctcam_region_ops);
0124     if (err)
0125         return err;
0126     err = mlxsw_sp1_acl_ctcam_region_catchall_add(mlxsw_sp, region);
0127     if (err)
0128         goto err_catchall_add;
0129     region->region = _region;
0130     return 0;
0131 
0132 err_catchall_add:
0133     mlxsw_sp_acl_ctcam_region_fini(&region->cregion);
0134     return err;
0135 }
0136 
0137 static void
0138 mlxsw_sp1_acl_tcam_region_fini(struct mlxsw_sp *mlxsw_sp, void *region_priv)
0139 {
0140     struct mlxsw_sp1_acl_tcam_region *region = region_priv;
0141 
0142     mlxsw_sp1_acl_ctcam_region_catchall_del(mlxsw_sp, region);
0143     mlxsw_sp_acl_ctcam_region_fini(&region->cregion);
0144 }
0145 
0146 static int
0147 mlxsw_sp1_acl_tcam_region_associate(struct mlxsw_sp *mlxsw_sp,
0148                     struct mlxsw_sp_acl_tcam_region *region)
0149 {
0150     return 0;
0151 }
0152 
0153 static void mlxsw_sp1_acl_tcam_chunk_init(void *region_priv, void *chunk_priv,
0154                       unsigned int priority)
0155 {
0156     struct mlxsw_sp1_acl_tcam_region *region = region_priv;
0157     struct mlxsw_sp1_acl_tcam_chunk *chunk = chunk_priv;
0158 
0159     mlxsw_sp_acl_ctcam_chunk_init(&region->cregion, &chunk->cchunk,
0160                       priority);
0161 }
0162 
0163 static void mlxsw_sp1_acl_tcam_chunk_fini(void *chunk_priv)
0164 {
0165     struct mlxsw_sp1_acl_tcam_chunk *chunk = chunk_priv;
0166 
0167     mlxsw_sp_acl_ctcam_chunk_fini(&chunk->cchunk);
0168 }
0169 
0170 static int mlxsw_sp1_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp,
0171                     void *region_priv, void *chunk_priv,
0172                     void *entry_priv,
0173                     struct mlxsw_sp_acl_rule_info *rulei)
0174 {
0175     struct mlxsw_sp1_acl_tcam_region *region = region_priv;
0176     struct mlxsw_sp1_acl_tcam_chunk *chunk = chunk_priv;
0177     struct mlxsw_sp1_acl_tcam_entry *entry = entry_priv;
0178 
0179     return mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, &region->cregion,
0180                         &chunk->cchunk, &entry->centry,
0181                         rulei, false);
0182 }
0183 
0184 static void mlxsw_sp1_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
0185                      void *region_priv, void *chunk_priv,
0186                      void *entry_priv)
0187 {
0188     struct mlxsw_sp1_acl_tcam_region *region = region_priv;
0189     struct mlxsw_sp1_acl_tcam_chunk *chunk = chunk_priv;
0190     struct mlxsw_sp1_acl_tcam_entry *entry = entry_priv;
0191 
0192     mlxsw_sp_acl_ctcam_entry_del(mlxsw_sp, &region->cregion,
0193                      &chunk->cchunk, &entry->centry);
0194 }
0195 
0196 static int
0197 mlxsw_sp1_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
0198                     void *region_priv, void *entry_priv,
0199                     struct mlxsw_sp_acl_rule_info *rulei)
0200 {
0201     return -EOPNOTSUPP;
0202 }
0203 
0204 static int
0205 mlxsw_sp1_acl_tcam_region_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
0206                          struct mlxsw_sp_acl_tcam_region *_region,
0207                          unsigned int offset,
0208                          bool *activity)
0209 {
0210     char ptce2_pl[MLXSW_REG_PTCE2_LEN];
0211     int err;
0212 
0213     mlxsw_reg_ptce2_pack(ptce2_pl, true, MLXSW_REG_PTCE2_OP_QUERY_CLEAR_ON_READ,
0214                  _region->tcam_region_info, offset, 0);
0215     err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
0216     if (err)
0217         return err;
0218     *activity = mlxsw_reg_ptce2_a_get(ptce2_pl);
0219     return 0;
0220 }
0221 
0222 static int
0223 mlxsw_sp1_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
0224                       void *region_priv, void *entry_priv,
0225                       bool *activity)
0226 {
0227     struct mlxsw_sp1_acl_tcam_region *region = region_priv;
0228     struct mlxsw_sp1_acl_tcam_entry *entry = entry_priv;
0229     unsigned int offset;
0230 
0231     offset = mlxsw_sp_acl_ctcam_entry_offset(&entry->centry);
0232     return mlxsw_sp1_acl_tcam_region_entry_activity_get(mlxsw_sp,
0233                                 region->region,
0234                                 offset, activity);
0235 }
0236 
0237 const struct mlxsw_sp_acl_tcam_ops mlxsw_sp1_acl_tcam_ops = {
0238     .key_type       = MLXSW_REG_PTAR_KEY_TYPE_FLEX,
0239     .priv_size      = 0,
0240     .init           = mlxsw_sp1_acl_tcam_init,
0241     .fini           = mlxsw_sp1_acl_tcam_fini,
0242     .region_priv_size   = sizeof(struct mlxsw_sp1_acl_tcam_region),
0243     .region_init        = mlxsw_sp1_acl_tcam_region_init,
0244     .region_fini        = mlxsw_sp1_acl_tcam_region_fini,
0245     .region_associate   = mlxsw_sp1_acl_tcam_region_associate,
0246     .chunk_priv_size    = sizeof(struct mlxsw_sp1_acl_tcam_chunk),
0247     .chunk_init     = mlxsw_sp1_acl_tcam_chunk_init,
0248     .chunk_fini     = mlxsw_sp1_acl_tcam_chunk_fini,
0249     .entry_priv_size    = sizeof(struct mlxsw_sp1_acl_tcam_entry),
0250     .entry_add      = mlxsw_sp1_acl_tcam_entry_add,
0251     .entry_del      = mlxsw_sp1_acl_tcam_entry_del,
0252     .entry_action_replace   = mlxsw_sp1_acl_tcam_entry_action_replace,
0253     .entry_activity_get = mlxsw_sp1_acl_tcam_entry_activity_get,
0254 };