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/errno.h>
0006 #include <linux/parman.h>
0007 
0008 #include "reg.h"
0009 #include "core.h"
0010 #include "spectrum.h"
0011 #include "spectrum_acl_tcam.h"
0012 
0013 static int
0014 mlxsw_sp_acl_ctcam_region_resize(struct mlxsw_sp *mlxsw_sp,
0015                  struct mlxsw_sp_acl_tcam_region *region,
0016                  u16 new_size)
0017 {
0018     char ptar_pl[MLXSW_REG_PTAR_LEN];
0019 
0020     mlxsw_reg_ptar_pack(ptar_pl, MLXSW_REG_PTAR_OP_RESIZE,
0021                 region->key_type, new_size, region->id,
0022                 region->tcam_region_info);
0023     return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptar), ptar_pl);
0024 }
0025 
0026 static void
0027 mlxsw_sp_acl_ctcam_region_move(struct mlxsw_sp *mlxsw_sp,
0028                    struct mlxsw_sp_acl_tcam_region *region,
0029                    u16 src_offset, u16 dst_offset, u16 size)
0030 {
0031     char prcr_pl[MLXSW_REG_PRCR_LEN];
0032 
0033     mlxsw_reg_prcr_pack(prcr_pl, MLXSW_REG_PRCR_OP_MOVE,
0034                 region->tcam_region_info, src_offset,
0035                 region->tcam_region_info, dst_offset, size);
0036     mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(prcr), prcr_pl);
0037 }
0038 
0039 static int
0040 mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
0041                        struct mlxsw_sp_acl_ctcam_region *cregion,
0042                        struct mlxsw_sp_acl_ctcam_entry *centry,
0043                        struct mlxsw_sp_acl_rule_info *rulei,
0044                        bool fillup_priority)
0045 {
0046     struct mlxsw_sp_acl_tcam_region *region = cregion->region;
0047     struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
0048     char ptce2_pl[MLXSW_REG_PTCE2_LEN];
0049     char *act_set;
0050     u32 priority;
0051     char *mask;
0052     char *key;
0053     int err;
0054 
0055     err = mlxsw_sp_acl_tcam_priority_get(mlxsw_sp, rulei, &priority,
0056                          fillup_priority);
0057     if (err)
0058         return err;
0059 
0060     mlxsw_reg_ptce2_pack(ptce2_pl, true, MLXSW_REG_PTCE2_OP_WRITE_WRITE,
0061                  region->tcam_region_info,
0062                  centry->parman_item.index, priority);
0063     key = mlxsw_reg_ptce2_flex_key_blocks_data(ptce2_pl);
0064     mask = mlxsw_reg_ptce2_mask_data(ptce2_pl);
0065     mlxsw_afk_encode(afk, region->key_info, &rulei->values, key, mask);
0066 
0067     err = cregion->ops->entry_insert(cregion, centry, mask);
0068     if (err)
0069         return err;
0070 
0071     /* Only the first action set belongs here, the rest is in KVD */
0072     act_set = mlxsw_afa_block_first_set(rulei->act_block);
0073     mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set);
0074 
0075     err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
0076     if (err)
0077         goto err_ptce2_write;
0078 
0079     return 0;
0080 
0081 err_ptce2_write:
0082     cregion->ops->entry_remove(cregion, centry);
0083     return err;
0084 }
0085 
0086 static void
0087 mlxsw_sp_acl_ctcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp,
0088                        struct mlxsw_sp_acl_ctcam_region *cregion,
0089                        struct mlxsw_sp_acl_ctcam_entry *centry)
0090 {
0091     char ptce2_pl[MLXSW_REG_PTCE2_LEN];
0092 
0093     mlxsw_reg_ptce2_pack(ptce2_pl, false, MLXSW_REG_PTCE2_OP_WRITE_WRITE,
0094                  cregion->region->tcam_region_info,
0095                  centry->parman_item.index, 0);
0096     mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
0097     cregion->ops->entry_remove(cregion, centry);
0098 }
0099 
0100 static int
0101 mlxsw_sp_acl_ctcam_region_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
0102                            struct mlxsw_sp_acl_ctcam_region *cregion,
0103                            struct mlxsw_sp_acl_ctcam_entry *centry,
0104                            struct mlxsw_afa_block *afa_block,
0105                            unsigned int priority)
0106 {
0107     char ptce2_pl[MLXSW_REG_PTCE2_LEN];
0108     char *act_set;
0109 
0110     mlxsw_reg_ptce2_pack(ptce2_pl, true, MLXSW_REG_PTCE2_OP_WRITE_UPDATE,
0111                  cregion->region->tcam_region_info,
0112                  centry->parman_item.index, priority);
0113 
0114     act_set = mlxsw_afa_block_first_set(afa_block);
0115     mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set);
0116 
0117     return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
0118 }
0119 
0120 
0121 static int mlxsw_sp_acl_ctcam_region_parman_resize(void *priv,
0122                            unsigned long new_count)
0123 {
0124     struct mlxsw_sp_acl_ctcam_region *cregion = priv;
0125     struct mlxsw_sp_acl_tcam_region *region = cregion->region;
0126     struct mlxsw_sp *mlxsw_sp = region->mlxsw_sp;
0127     u64 max_tcam_rules;
0128 
0129     max_tcam_rules = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_TCAM_RULES);
0130     if (new_count > max_tcam_rules)
0131         return -EINVAL;
0132     return mlxsw_sp_acl_ctcam_region_resize(mlxsw_sp, region, new_count);
0133 }
0134 
0135 static void mlxsw_sp_acl_ctcam_region_parman_move(void *priv,
0136                           unsigned long from_index,
0137                           unsigned long to_index,
0138                           unsigned long count)
0139 {
0140     struct mlxsw_sp_acl_ctcam_region *cregion = priv;
0141     struct mlxsw_sp_acl_tcam_region *region = cregion->region;
0142     struct mlxsw_sp *mlxsw_sp = region->mlxsw_sp;
0143 
0144     mlxsw_sp_acl_ctcam_region_move(mlxsw_sp, region,
0145                        from_index, to_index, count);
0146 }
0147 
0148 static const struct parman_ops mlxsw_sp_acl_ctcam_region_parman_ops = {
0149     .base_count = MLXSW_SP_ACL_TCAM_REGION_BASE_COUNT,
0150     .resize_step    = MLXSW_SP_ACL_TCAM_REGION_RESIZE_STEP,
0151     .resize     = mlxsw_sp_acl_ctcam_region_parman_resize,
0152     .move       = mlxsw_sp_acl_ctcam_region_parman_move,
0153     .algo       = PARMAN_ALGO_TYPE_LSORT,
0154 };
0155 
0156 int
0157 mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp,
0158                    struct mlxsw_sp_acl_ctcam_region *cregion,
0159                    struct mlxsw_sp_acl_tcam_region *region,
0160                    const struct mlxsw_sp_acl_ctcam_region_ops *ops)
0161 {
0162     cregion->region = region;
0163     cregion->ops = ops;
0164     cregion->parman = parman_create(&mlxsw_sp_acl_ctcam_region_parman_ops,
0165                     cregion);
0166     if (!cregion->parman)
0167         return -ENOMEM;
0168     return 0;
0169 }
0170 
0171 void mlxsw_sp_acl_ctcam_region_fini(struct mlxsw_sp_acl_ctcam_region *cregion)
0172 {
0173     parman_destroy(cregion->parman);
0174 }
0175 
0176 void mlxsw_sp_acl_ctcam_chunk_init(struct mlxsw_sp_acl_ctcam_region *cregion,
0177                    struct mlxsw_sp_acl_ctcam_chunk *cchunk,
0178                    unsigned int priority)
0179 {
0180     parman_prio_init(cregion->parman, &cchunk->parman_prio, priority);
0181 }
0182 
0183 void mlxsw_sp_acl_ctcam_chunk_fini(struct mlxsw_sp_acl_ctcam_chunk *cchunk)
0184 {
0185     parman_prio_fini(&cchunk->parman_prio);
0186 }
0187 
0188 int mlxsw_sp_acl_ctcam_entry_add(struct mlxsw_sp *mlxsw_sp,
0189                  struct mlxsw_sp_acl_ctcam_region *cregion,
0190                  struct mlxsw_sp_acl_ctcam_chunk *cchunk,
0191                  struct mlxsw_sp_acl_ctcam_entry *centry,
0192                  struct mlxsw_sp_acl_rule_info *rulei,
0193                  bool fillup_priority)
0194 {
0195     int err;
0196 
0197     err = parman_item_add(cregion->parman, &cchunk->parman_prio,
0198                   &centry->parman_item);
0199     if (err)
0200         return err;
0201 
0202     err = mlxsw_sp_acl_ctcam_region_entry_insert(mlxsw_sp, cregion, centry,
0203                              rulei, fillup_priority);
0204     if (err)
0205         goto err_rule_insert;
0206     return 0;
0207 
0208 err_rule_insert:
0209     parman_item_remove(cregion->parman, &cchunk->parman_prio,
0210                &centry->parman_item);
0211     return err;
0212 }
0213 
0214 void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp,
0215                   struct mlxsw_sp_acl_ctcam_region *cregion,
0216                   struct mlxsw_sp_acl_ctcam_chunk *cchunk,
0217                   struct mlxsw_sp_acl_ctcam_entry *centry)
0218 {
0219     mlxsw_sp_acl_ctcam_region_entry_remove(mlxsw_sp, cregion, centry);
0220     parman_item_remove(cregion->parman, &cchunk->parman_prio,
0221                &centry->parman_item);
0222 }
0223 
0224 int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
0225                         struct mlxsw_sp_acl_ctcam_region *cregion,
0226                         struct mlxsw_sp_acl_ctcam_entry *centry,
0227                         struct mlxsw_sp_acl_rule_info *rulei)
0228 {
0229     return mlxsw_sp_acl_ctcam_region_entry_action_replace(mlxsw_sp, cregion,
0230                                   centry,
0231                                   rulei->act_block,
0232                                   rulei->priority);
0233 }