nfp: flower: support multiple memory units for filter offloads
authorPieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Wed, 16 Jan 2019 03:06:52 +0000 (19:06 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 Jan 2019 23:23:14 +0000 (15:23 -0800)
Adds support for multiple memory units which are used for filter
offloads. Each filter is assigned a stats id, the MSBs of the id are
used to determine which memory unit the filter should be offloaded
to. The number of available memory units that could be used for filter
offload is obtained from HW. A simple round robin technique is used to
allocate and distribute the ids across memory units.

Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/netronome/nfp/flower/main.c
drivers/net/ethernet/netronome/nfp/flower/main.h
drivers/net/ethernet/netronome/nfp/flower/metadata.c

index 8ce20bd389659d7b540c0213d17d32f983bc6487..c370fbcbcc380028fb122c77c6304560bb083843 100644 (file)
@@ -474,8 +474,8 @@ err_clear_nn:
 
 static int nfp_flower_init(struct nfp_app *app)
 {
+       u64 version, features, ctx_count, num_mems;
        const struct nfp_pf *pf = app->pf;
-       u64 version, features, ctx_count;
        struct nfp_flower_priv *app_priv;
        int err;
 
@@ -500,6 +500,23 @@ static int nfp_flower_init(struct nfp_app *app)
                return err;
        }
 
+       num_mems = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_SPLIT",
+                                    &err);
+       if (err) {
+               nfp_warn(app->cpp,
+                        "FlowerNIC: unsupported host context memory: %d\n",
+                        err);
+               err = 0;
+               num_mems = 1;
+       }
+
+       if (!FIELD_FIT(NFP_FL_STAT_ID_MU_NUM, num_mems) || !num_mems) {
+               nfp_warn(app->cpp,
+                        "FlowerNIC: invalid host context memory: %llu\n",
+                        num_mems);
+               return -EINVAL;
+       }
+
        ctx_count = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_COUNT",
                                      &err);
        if (err) {
@@ -520,6 +537,8 @@ static int nfp_flower_init(struct nfp_app *app)
        if (!app_priv)
                return -ENOMEM;
 
+       app_priv->total_mem_units = num_mems;
+       app_priv->active_mem_unit = 0;
        app_priv->stats_ring_size = roundup_pow_of_two(ctx_count);
        app->priv = app_priv;
        app_priv->app = app;
@@ -531,7 +550,7 @@ static int nfp_flower_init(struct nfp_app *app)
        init_waitqueue_head(&app_priv->mtu_conf.wait_q);
        spin_lock_init(&app_priv->mtu_conf.lock);
 
-       err = nfp_flower_metadata_init(app, ctx_count);
+       err = nfp_flower_metadata_init(app, ctx_count, num_mems);
        if (err)
                goto err_free_app_priv;
 
index b858bac4762133dc1e50d1f0adde709814b3d9e1..324b7fe3192f668e8c16550ba1df445e4d9ada8b 100644 (file)
@@ -20,6 +20,9 @@ struct nfp_fl_pre_lag;
 struct net_device;
 struct nfp_app;
 
+#define NFP_FL_STAT_ID_MU_NUM          GENMASK(31, 22)
+#define NFP_FL_STAT_ID_STAT            GENMASK(21, 0)
+
 #define NFP_FL_STATS_ELEM_RS           FIELD_SIZEOF(struct nfp_fl_stats_id, \
                                                     init_unalloc)
 #define NFP_FLOWER_MASK_ENTRY_RS       256
@@ -130,6 +133,8 @@ struct nfp_fl_lag {
  * @mtu_conf:          Configuration of repr MTU value
  * @nfp_lag:           Link aggregation data block
  * @indr_block_cb_priv:        List of priv data passed to indirect block cbs
+ * @active_mem_unit:   Current active memory unit for flower rules
+ * @total_mem_units:   Total number of available memory units for flower rules
  */
 struct nfp_flower_priv {
        struct nfp_app *app;
@@ -163,6 +168,8 @@ struct nfp_flower_priv {
        struct nfp_mtu_conf mtu_conf;
        struct nfp_fl_lag nfp_lag;
        struct list_head indr_block_cb_priv;
+       unsigned int active_mem_unit;
+       unsigned int total_mem_units;
 };
 
 /**
@@ -217,7 +224,8 @@ struct nfp_fl_stats_frame {
        __be64 stats_cookie;
 };
 
-int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count);
+int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
+                            unsigned int host_ctx_split);
 void nfp_flower_metadata_cleanup(struct nfp_app *app);
 
 int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
index 573a4400a26ce3d5df616aa2984ba856a74419bb..492837b852b6d3652123cc187d24dbf68bed6a19 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/hash.h>
 #include <linux/hashtable.h>
 #include <linux/jhash.h>
+#include <linux/math64.h>
 #include <linux/vmalloc.h>
 #include <net/pkt_cls.h>
 
@@ -52,8 +53,17 @@ static int nfp_get_stats_entry(struct nfp_app *app, u32 *stats_context_id)
        freed_stats_id = priv->stats_ring_size;
        /* Check for unallocated entries first. */
        if (priv->stats_ids.init_unalloc > 0) {
-               *stats_context_id = priv->stats_ids.init_unalloc - 1;
-               priv->stats_ids.init_unalloc--;
+               if (priv->active_mem_unit == priv->total_mem_units) {
+                       priv->stats_ids.init_unalloc--;
+                       priv->active_mem_unit = 0;
+               }
+
+               *stats_context_id =
+                       FIELD_PREP(NFP_FL_STAT_ID_STAT,
+                                  priv->stats_ids.init_unalloc - 1) |
+                       FIELD_PREP(NFP_FL_STAT_ID_MU_NUM,
+                                  priv->active_mem_unit);
+               priv->active_mem_unit++;
                return 0;
        }
 
@@ -381,10 +391,11 @@ const struct rhashtable_params nfp_flower_table_params = {
        .automatic_shrinking    = true,
 };
 
-int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count)
+int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
+                            unsigned int host_num_mems)
 {
        struct nfp_flower_priv *priv = app->priv;
-       int err;
+       int err, stats_size;
 
        hash_init(priv->mask_table);
 
@@ -417,10 +428,12 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count)
        if (!priv->stats_ids.free_list.buf)
                goto err_free_last_used;
 
-       priv->stats_ids.init_unalloc = host_ctx_count;
+       priv->stats_ids.init_unalloc = div_u64(host_ctx_count, host_num_mems);
 
-       priv->stats = kvmalloc_array(priv->stats_ring_size,
-                                    sizeof(struct nfp_fl_stats), GFP_KERNEL);
+       stats_size = FIELD_PREP(NFP_FL_STAT_ID_STAT, host_ctx_count) |
+                    FIELD_PREP(NFP_FL_STAT_ID_MU_NUM, host_num_mems - 1);
+       priv->stats = kvmalloc_array(stats_size, sizeof(struct nfp_fl_stats),
+                                    GFP_KERNEL);
        if (!priv->stats)
                goto err_free_ring_buf;