@@ -2868,7 +2868,6 @@ static inline void mlxsw_reg_percr_pack(char *payload, u16 region_id)
mlxsw_reg_percr_atcam_ignore_prune_set(payload, false);
mlxsw_reg_percr_ctcam_ignore_prune_set(payload, false);
mlxsw_reg_percr_bf_bypass_set(payload, true);
- memset(payload + 0x20, 0xff, 96);
}
/* PERERP - Policy-Engine Region eRP Register
@@ -58,6 +58,28 @@ struct mlxsw_sp1_acl_tcam_entry {
struct mlxsw_sp_acl_ctcam_entry centry;
};
+static int
+mlxsw_sp1_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *
+ cregion,
+ struct mlxsw_sp_acl_ctcam_entry *centry,
+ const char *mask)
+{
+ return 0;
+}
+
+static void
+mlxsw_sp1_acl_ctcam_region_entry_remove(struct mlxsw_sp_acl_ctcam_region *
+ cregion,
+ struct mlxsw_sp_acl_ctcam_entry *centry)
+{
+}
+
+static const struct mlxsw_sp_acl_ctcam_region_ops
+mlxsw_sp1_acl_ctcam_region_ops = {
+ .entry_insert = mlxsw_sp1_acl_ctcam_region_entry_insert,
+ .entry_remove = mlxsw_sp1_acl_ctcam_region_entry_remove,
+};
+
static int mlxsw_sp1_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv,
struct mlxsw_sp_acl_tcam *tcam)
{
@@ -129,7 +151,8 @@ mlxsw_sp1_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv,
int err;
err = mlxsw_sp_acl_ctcam_region_init(mlxsw_sp, ®ion->cregion,
- _region);
+ _region,
+ &mlxsw_sp1_acl_ctcam_region_ops);
if (err)
return err;
err = mlxsw_sp1_acl_ctcam_region_catchall_add(mlxsw_sp, region);
@@ -54,8 +54,53 @@ struct mlxsw_sp2_acl_tcam_chunk {
};
struct mlxsw_sp2_acl_tcam_entry {
- struct mlxsw_sp_acl_ctcam_entry centry;
+ struct mlxsw_sp_acl_atcam_entry aentry;
struct mlxsw_afa_block *act_block;
+ void (*destructor)(struct mlxsw_sp2_acl_tcam_entry *entry,
+ struct mlxsw_sp2_acl_tcam_region *region,
+ struct mlxsw_sp2_acl_tcam_chunk *chunk);
+};
+
+static int
+mlxsw_sp2_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *
+ cregion,
+ struct mlxsw_sp_acl_ctcam_entry *
+ centry,
+ const char *mask)
+{
+ struct mlxsw_sp_acl_atcam_region *aregion;
+ struct mlxsw_sp_acl_atcam_entry *aentry;
+ struct mlxsw_sp_acl_erp *erp;
+
+ aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion);
+ aentry = mlxsw_sp_acl_tcam_centry_aentry(centry);
+
+ erp = mlxsw_sp_acl_erp_get(aregion, mask, true);
+ if (IS_ERR(erp))
+ return PTR_ERR(erp);
+ aentry->erp = erp;
+
+ return 0;
+}
+
+static void
+mlxsw_sp2_acl_ctcam_region_entry_remove(struct mlxsw_sp_acl_ctcam_region *
+ cregion,
+ struct mlxsw_sp_acl_ctcam_entry *centry)
+{
+ struct mlxsw_sp_acl_atcam_region *aregion;
+ struct mlxsw_sp_acl_atcam_entry *aentry;
+
+ aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion);
+ aentry = mlxsw_sp_acl_tcam_centry_aentry(centry);
+
+ mlxsw_sp_acl_erp_put(aregion, aentry->erp);
+}
+
+static const struct mlxsw_sp_acl_ctcam_region_ops
+mlxsw_sp2_acl_ctcam_region_ops = {
+ .entry_insert = mlxsw_sp2_acl_ctcam_region_entry_insert,
+ .entry_remove = mlxsw_sp2_acl_ctcam_region_entry_remove,
};
static int mlxsw_sp2_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv,
@@ -145,7 +190,8 @@ mlxsw_sp2_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv,
return err;
err = mlxsw_sp_acl_ctcam_region_init(mlxsw_sp, ®ion->aregion.cregion,
- _region);
+ _region,
+ &mlxsw_sp2_acl_ctcam_region_ops);
if (err)
goto err_ctcam_region_init;
@@ -189,6 +235,30 @@ static void mlxsw_sp2_acl_tcam_chunk_fini(void *chunk_priv)
mlxsw_sp_acl_ctcam_chunk_fini(&chunk->cchunk);
}
+static void
+mlxsw_sp2_acl_atcam_entry_del(struct mlxsw_sp2_acl_tcam_entry *entry,
+ struct mlxsw_sp2_acl_tcam_region *region,
+ struct mlxsw_sp2_acl_tcam_chunk *chunk)
+{
+ struct mlxsw_sp_acl_tcam_region *_region = region->region;
+ struct mlxsw_sp *mlxsw_sp = _region->mlxsw_sp;
+
+ mlxsw_sp_acl_atcam_entry_del(mlxsw_sp, ®ion->aregion,
+ &entry->aentry);
+}
+
+static void
+mlxsw_sp2_acl_ctcam_entry_del(struct mlxsw_sp2_acl_tcam_entry *entry,
+ struct mlxsw_sp2_acl_tcam_region *region,
+ struct mlxsw_sp2_acl_tcam_chunk *chunk)
+{
+ struct mlxsw_sp_acl_tcam_region *_region = region->region;
+ struct mlxsw_sp *mlxsw_sp = _region->mlxsw_sp;
+
+ mlxsw_sp_acl_ctcam_entry_del(mlxsw_sp, ®ion->aregion.cregion,
+ &chunk->cchunk, &entry->aentry.centry);
+}
+
static int mlxsw_sp2_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp,
void *region_priv, void *chunk_priv,
void *entry_priv,
@@ -197,11 +267,29 @@ static int mlxsw_sp2_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp2_acl_tcam_region *region = region_priv;
struct mlxsw_sp2_acl_tcam_chunk *chunk = chunk_priv;
struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv;
+ int err;
entry->act_block = rulei->act_block;
- return mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, ®ion->aregion.cregion,
- &chunk->cchunk, &entry->centry,
- rulei, true);
+
+ err = mlxsw_sp_acl_atcam_entry_add(mlxsw_sp, ®ion->aregion,
+ &entry->aentry, rulei);
+ if (!err) {
+ entry->destructor = mlxsw_sp2_acl_atcam_entry_del;
+ return 0;
+ }
+
+ /* It is possible we failed to add the rule to the A-TCAM due to
+ * exceeded number of masks. Try to spill into C-TCAM.
+ */
+ err = mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, ®ion->aregion.cregion,
+ &chunk->cchunk,
+ &entry->aentry.centry, rulei, true);
+ if (!err) {
+ entry->destructor = mlxsw_sp2_acl_ctcam_entry_del;
+ return 0;
+ }
+
+ return err;
}
static void mlxsw_sp2_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
@@ -212,8 +300,7 @@ static void mlxsw_sp2_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp2_acl_tcam_chunk *chunk = chunk_priv;
struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv;
- mlxsw_sp_acl_ctcam_entry_del(mlxsw_sp, ®ion->aregion.cregion,
- &chunk->cchunk, &entry->centry);
+ entry->destructor(entry, region, chunk);
}
static int
@@ -96,6 +96,10 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
mask = mlxsw_reg_ptce2_mask_data(ptce2_pl);
mlxsw_afk_encode(afk, region->key_info, &rulei->values, key, mask);
+ err = cregion->ops->entry_insert(cregion, centry, mask);
+ if (err)
+ return err;
+
/* Only the first action set belongs here, the rest is in KVD */
act_set = mlxsw_afa_block_first_set(rulei->act_block);
mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set);
@@ -115,6 +119,7 @@ mlxsw_sp_acl_ctcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp,
cregion->region->tcam_region_info,
centry->parman_item.index, 0);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+ cregion->ops->entry_remove(cregion, centry);
}
static int mlxsw_sp_acl_ctcam_region_parman_resize(void *priv,
@@ -152,11 +157,14 @@ static const struct parman_ops mlxsw_sp_acl_ctcam_region_parman_ops = {
.algo = PARMAN_ALGO_TYPE_LSORT,
};
-int mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_ctcam_region *cregion,
- struct mlxsw_sp_acl_tcam_region *region)
+int
+mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_ctcam_region *cregion,
+ struct mlxsw_sp_acl_tcam_region *region,
+ const struct mlxsw_sp_acl_ctcam_region_ops *ops)
{
cregion->region = region;
+ cregion->ops = ops;
cregion->parman = parman_create(&mlxsw_sp_acl_ctcam_region_parman_ops,
cregion);
if (!cregion->parman)
@@ -1035,11 +1035,8 @@ mlxsw_sp_acl_erp_master_mask_init(struct mlxsw_sp_acl_atcam_region *aregion)
{
struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp;
char percr_pl[MLXSW_REG_PERCR_LEN];
- char *master_mask;
mlxsw_reg_percr_pack(percr_pl, aregion->region->id);
- master_mask = mlxsw_reg_percr_master_mask_data(percr_pl);
- memset(master_mask, 0, MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(percr), percr_pl);
}
@@ -1049,7 +1046,7 @@ mlxsw_sp_acl_erp_region_param_init(struct mlxsw_sp_acl_atcam_region *aregion)
struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp;
char pererp_pl[MLXSW_REG_PERERP_LEN];
- mlxsw_reg_pererp_pack(pererp_pl, aregion->region->id, true, true, 0,
+ mlxsw_reg_pererp_pack(pererp_pl, aregion->region->id, false, false, 0,
0, 0);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pererp), pererp_pl);
}
@@ -1064,16 +1061,12 @@ int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion)
return PTR_ERR(erp_table);
aregion->erp_table = erp_table;
- /* Initialize the region's master mask to all ones for C-TCAM
- * only mode
- */
+ /* Initialize the region's master mask to all zeroes */
err = mlxsw_sp_acl_erp_master_mask_init(aregion);
if (err)
goto err_erp_master_mask_init;
- /* Initialize the region to use the eRP table and enable C-TCAM
- * lookup
- */
+ /* Initialize the region to not use the eRP table */
err = mlxsw_sp_acl_erp_region_param_init(aregion);
if (err)
goto err_erp_region_param_init;
@@ -111,6 +111,7 @@ struct mlxsw_sp_acl_tcam_region {
struct mlxsw_sp_acl_ctcam_region {
struct parman *parman;
+ const struct mlxsw_sp_acl_ctcam_region_ops *ops;
struct mlxsw_sp_acl_tcam_region *region;
};
@@ -122,9 +123,19 @@ struct mlxsw_sp_acl_ctcam_entry {
struct parman_item parman_item;
};
-int mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_acl_ctcam_region *cregion,
- struct mlxsw_sp_acl_tcam_region *region);
+struct mlxsw_sp_acl_ctcam_region_ops {
+ int (*entry_insert)(struct mlxsw_sp_acl_ctcam_region *cregion,
+ struct mlxsw_sp_acl_ctcam_entry *centry,
+ const char *mask);
+ void (*entry_remove)(struct mlxsw_sp_acl_ctcam_region *cregion,
+ struct mlxsw_sp_acl_ctcam_entry *centry);
+};
+
+int
+mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_ctcam_region *cregion,
+ struct mlxsw_sp_acl_tcam_region *region,
+ const struct mlxsw_sp_acl_ctcam_region_ops *ops);
void mlxsw_sp_acl_ctcam_region_fini(struct mlxsw_sp_acl_ctcam_region *cregion);
void mlxsw_sp_acl_ctcam_chunk_init(struct mlxsw_sp_acl_ctcam_region *cregion,
struct mlxsw_sp_acl_ctcam_chunk *cchunk,
@@ -180,10 +191,23 @@ struct mlxsw_sp_acl_atcam_entry_ht_key {
struct mlxsw_sp_acl_atcam_entry {
struct rhash_head ht_node;
struct mlxsw_sp_acl_atcam_entry_ht_key ht_key;
+ struct mlxsw_sp_acl_ctcam_entry centry;
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
struct mlxsw_sp_acl_erp *erp;
};
+static inline struct mlxsw_sp_acl_atcam_region *
+mlxsw_sp_acl_tcam_cregion_aregion(struct mlxsw_sp_acl_ctcam_region *cregion)
+{
+ return container_of(cregion, struct mlxsw_sp_acl_atcam_region, cregion);
+}
+
+static inline struct mlxsw_sp_acl_atcam_entry *
+mlxsw_sp_acl_tcam_centry_aentry(struct mlxsw_sp_acl_ctcam_entry *centry)
+{
+ return container_of(centry, struct mlxsw_sp_acl_atcam_entry, centry);
+}
+
int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp,
u16 region_id);
int mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp,
Now that all the pieces are in place we can start using the A-TCAM instead of only using the C-TCAM. This allows for much higher scale and better performance (to be improved further by follow-up patch sets). Perform the integration with the A-TCAM and the eRP core by reverting the changes introduced by "mlxsw: spectrum_acl: Enable C-TCAM only mode in eRP core" and add calls from the C-TCAM code into the eRP core. Signed-off-by: Ido Schimmel <idosch@mellanox.com> --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 1 - .../ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c | 25 ++++- .../ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c | 101 +++++++++++++++++++-- .../ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c | 14 ++- .../net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c | 13 +-- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 30 +++++- 6 files changed, 159 insertions(+), 25 deletions(-)