linux/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c
<<
>>
Prefs
   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(&region->cregion,
  68                                      &region->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, &region->cregion,
  82                                           &region->catchall.cchunk,
  83                                           &region->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(&region->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, &region->cregion,
 106                                     &region->catchall.cchunk,
 107                                     &region->catchall.centry);
 108        mlxsw_sp_acl_rulei_destroy(rulei);
 109        mlxsw_sp_acl_ctcam_chunk_fini(&region->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, &region->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(&region->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(&region->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(&region->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, &region->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, &region->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};
 255