From: Jiri Pirko <j...@mellanox.com>

Since cld_flower provides information about the filter template for
specific chain, use this information in order to prepare a region.
Use the template to find out what elements are going to be used
and pass that down to mlxsw_sp_acl_tcam_group_add(). Later on, when the
first filter is inserted, the mlxsw_sp_acl_tcam_group_use_patterns()
function would use this element usage information instead of looking
up a pattern.

Signed-off-by: Jiri Pirko <j...@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c     |  5 +++
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h     | 12 +++++-
 drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 12 ++++--
 .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c    | 25 ++++++++++--
 .../net/ethernet/mellanox/mlxsw/spectrum_flower.c  | 44 ++++++++++++++++++++--
 5 files changed, 86 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 968b88af2ef5..da19fa343d0b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1441,6 +1441,11 @@ mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_acl_block 
*acl_block,
                return 0;
        case TC_CLSFLOWER_STATS:
                return mlxsw_sp_flower_stats(mlxsw_sp, acl_block, f);
+       case TC_CLSFLOWER_TMPLT_CREATE:
+               return mlxsw_sp_flower_tmplt_create(mlxsw_sp, acl_block, f);
+       case TC_CLSFLOWER_TMPLT_DESTROY:
+               mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, acl_block, f);
+               return 0;
        default:
                return -EOPNOTSUPP;
        }
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 4a519d8edec8..b0a8e611e730 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -459,7 +459,8 @@ enum mlxsw_sp_acl_profile {
 struct mlxsw_sp_acl_profile_ops {
        size_t ruleset_priv_size;
        int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp,
-                          void *priv, void *ruleset_priv);
+                          void *priv, void *ruleset_priv,
+                          struct mlxsw_afk_element_usage *tmplt_elusage);
        void (*ruleset_del)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv);
        int (*ruleset_bind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
                            struct mlxsw_sp_port *mlxsw_sp_port,
@@ -514,7 +515,8 @@ mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp,
 struct mlxsw_sp_acl_ruleset *
 mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
                         struct mlxsw_sp_acl_block *block, u32 chain_index,
-                        enum mlxsw_sp_acl_profile profile);
+                        enum mlxsw_sp_acl_profile profile,
+                        struct mlxsw_afk_element_usage *tmplt_elusage);
 void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp,
                              struct mlxsw_sp_acl_ruleset *ruleset);
 u16 mlxsw_sp_acl_ruleset_group_id(struct mlxsw_sp_acl_ruleset *ruleset);
@@ -594,6 +596,12 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp,
 int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
                          struct mlxsw_sp_acl_block *block,
                          struct tc_cls_flower_offload *f);
+int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp,
+                                struct mlxsw_sp_acl_block *block,
+                                struct tc_cls_flower_offload *f);
+void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp,
+                                  struct mlxsw_sp_acl_block *block,
+                                  struct tc_cls_flower_offload *f);
 
 /* spectrum_qdisc.c */
 int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index 79b1fa27a9a4..ea42605c451d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -319,7 +319,8 @@ int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp,
 static struct mlxsw_sp_acl_ruleset *
 mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
                            struct mlxsw_sp_acl_block *block, u32 chain_index,
-                           const struct mlxsw_sp_acl_profile_ops *ops)
+                           const struct mlxsw_sp_acl_profile_ops *ops,
+                           struct mlxsw_afk_element_usage *tmplt_elusage)
 {
        struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
        struct mlxsw_sp_acl_ruleset *ruleset;
@@ -339,7 +340,8 @@ mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
        if (err)
                goto err_rhashtable_init;
 
-       err = ops->ruleset_add(mlxsw_sp, acl->priv, ruleset->priv);
+       err = ops->ruleset_add(mlxsw_sp, acl->priv, ruleset->priv,
+                              tmplt_elusage);
        if (err)
                goto err_ops_ruleset_add;
 
@@ -421,7 +423,8 @@ mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp,
 struct mlxsw_sp_acl_ruleset *
 mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
                         struct mlxsw_sp_acl_block *block, u32 chain_index,
-                        enum mlxsw_sp_acl_profile profile)
+                        enum mlxsw_sp_acl_profile profile,
+                        struct mlxsw_afk_element_usage *tmplt_elusage)
 {
        const struct mlxsw_sp_acl_profile_ops *ops;
        struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
@@ -436,7 +439,8 @@ mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
                mlxsw_sp_acl_ruleset_ref_inc(ruleset);
                return ruleset;
        }
-       return mlxsw_sp_acl_ruleset_create(mlxsw_sp, block, chain_index, ops);
+       return mlxsw_sp_acl_ruleset_create(mlxsw_sp, block, chain_index, ops,
+                                          tmplt_elusage);
 }
 
 void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
index ad1b548e3cac..d6e4e00dfd3d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -157,6 +157,8 @@ struct mlxsw_sp_acl_tcam_group {
        struct mlxsw_sp_acl_tcam_group_ops *ops;
        const struct mlxsw_sp_acl_tcam_pattern *patterns;
        unsigned int patterns_count;
+       bool tmplt_elusage_set;
+       struct mlxsw_afk_element_usage tmplt_elusage;
 };
 
 struct mlxsw_sp_acl_tcam_region {
@@ -216,13 +218,19 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp,
                            struct mlxsw_sp_acl_tcam *tcam,
                            struct mlxsw_sp_acl_tcam_group *group,
                            const struct mlxsw_sp_acl_tcam_pattern *patterns,
-                           unsigned int patterns_count)
+                           unsigned int patterns_count,
+                           struct mlxsw_afk_element_usage *tmplt_elusage)
 {
        int err;
 
        group->tcam = tcam;
        group->patterns = patterns;
        group->patterns_count = patterns_count;
+       if (tmplt_elusage) {
+               group->tmplt_elusage_set = true;
+               memcpy(&group->tmplt_elusage, tmplt_elusage,
+                      sizeof(group->tmplt_elusage));
+       }
        INIT_LIST_HEAD(&group->region_list);
        err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
        if (err)
@@ -431,6 +439,15 @@ mlxsw_sp_acl_tcam_group_use_patterns(struct 
mlxsw_sp_acl_tcam_group *group,
        const struct mlxsw_sp_acl_tcam_pattern *pattern;
        int i;
 
+       /* In case the template is set, we don't have to look up the pattern
+        * and just use the template.
+        */
+       if (group->tmplt_elusage_set) {
+               memcpy(out, &group->tmplt_elusage, sizeof(*out));
+               WARN_ON(!mlxsw_afk_element_usage_subset(elusage, out));
+               return;
+       }
+
        for (i = 0; i < group->patterns_count; i++) {
                pattern = &group->patterns[i];
                mlxsw_afk_element_usage_fill(out, pattern->elements,
@@ -1019,14 +1036,16 @@ struct mlxsw_sp_acl_tcam_flower_rule {
 
 static int
 mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp,
-                                    void *priv, void *ruleset_priv)
+                                    void *priv, void *ruleset_priv,
+                                    struct mlxsw_afk_element_usage 
*tmplt_elusage)
 {
        struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
        struct mlxsw_sp_acl_tcam *tcam = priv;
 
        return mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group,
                                           mlxsw_sp_acl_tcam_patterns,
-                                          MLXSW_SP_ACL_TCAM_PATTERNS_COUNT);
+                                          MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
+                                          tmplt_elusage);
 }
 
 static void
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
index 89dbf569dff5..f34b410e5048 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
@@ -401,7 +401,7 @@ int mlxsw_sp_flower_replace(struct mlxsw_sp *mlxsw_sp,
 
        ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
                                           f->common.chain_index,
-                                          MLXSW_SP_ACL_PROFILE_FLOWER);
+                                          MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
        if (IS_ERR(ruleset))
                return PTR_ERR(ruleset);
 
@@ -445,7 +445,7 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp,
 
        ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
                                           f->common.chain_index,
-                                          MLXSW_SP_ACL_PROFILE_FLOWER);
+                                          MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
        if (IS_ERR(ruleset))
                return;
 
@@ -471,7 +471,7 @@ int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
 
        ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
                                           f->common.chain_index,
-                                          MLXSW_SP_ACL_PROFILE_FLOWER);
+                                          MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
        if (WARN_ON(IS_ERR(ruleset)))
                return -EINVAL;
 
@@ -493,3 +493,41 @@ int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
        mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
        return err;
 }
+
+int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp,
+                                struct mlxsw_sp_acl_block *block,
+                                struct tc_cls_flower_offload *f)
+{
+       struct mlxsw_sp_acl_ruleset *ruleset;
+       struct mlxsw_sp_acl_rule_info rulei;
+       int err;
+
+       memset(&rulei, 0, sizeof(rulei));
+       err = mlxsw_sp_flower_parse(mlxsw_sp, block, &rulei, f);
+       if (err)
+               return err;
+       ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
+                                          f->common.chain_index,
+                                          MLXSW_SP_ACL_PROFILE_FLOWER,
+                                          &rulei.values.elusage);
+       if (IS_ERR(ruleset))
+               return PTR_ERR(ruleset);
+       /* keep the reference to the ruleset */
+       return 0;
+}
+
+void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp,
+                                  struct mlxsw_sp_acl_block *block,
+                                  struct tc_cls_flower_offload *f)
+{
+       struct mlxsw_sp_acl_ruleset *ruleset;
+
+       ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
+                                          f->common.chain_index,
+                                          MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
+       if (IS_ERR(ruleset))
+               return;
+       /* put the reference to the ruleset kept in create */
+       mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
+       mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
+}
-- 
2.14.4

Reply via email to