nfp: flower: add infastructure for non-repr priv data
authorJohn Hurley <john.hurley@netronome.com>
Wed, 16 Jan 2019 03:06:57 +0000 (19:06 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 Jan 2019 23:23:15 +0000 (15:23 -0800)
NFP repr netdevs contain private data that can store per port information.
In certain cases, the NFP driver offloads information from non-repr ports
(e.g. tunnel ports). As the driver does not have control over non-repr
netdevs, it cannot add/track private data directly to the netdev struct.

Add infastructure to store private information on any non-repr netdev that
is offloaded at a given time. This is used in a following patch to track
offloaded MAC addresses for non-reprs and enable correct house keeping on
address changes.

Signed-off-by: John Hurley <john.hurley@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

index c370fbc..837ef0c 100644 (file)
@@ -32,6 +32,71 @@ static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app)
        return DEVLINK_ESWITCH_MODE_SWITCHDEV;
 }
 
+static struct nfp_flower_non_repr_priv *
+nfp_flower_non_repr_priv_lookup(struct nfp_app *app, struct net_device *netdev)
+{
+       struct nfp_flower_priv *priv = app->priv;
+       struct nfp_flower_non_repr_priv *entry;
+
+       ASSERT_RTNL();
+
+       list_for_each_entry(entry, &priv->non_repr_priv, list)
+               if (entry->netdev == netdev)
+                       return entry;
+
+       return NULL;
+}
+
+void
+__nfp_flower_non_repr_priv_get(struct nfp_flower_non_repr_priv *non_repr_priv)
+{
+       non_repr_priv->ref_count++;
+}
+
+struct nfp_flower_non_repr_priv *
+nfp_flower_non_repr_priv_get(struct nfp_app *app, struct net_device *netdev)
+{
+       struct nfp_flower_priv *priv = app->priv;
+       struct nfp_flower_non_repr_priv *entry;
+
+       entry = nfp_flower_non_repr_priv_lookup(app, netdev);
+       if (entry)
+               goto inc_ref;
+
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry)
+               return NULL;
+
+       entry->netdev = netdev;
+       list_add(&entry->list, &priv->non_repr_priv);
+
+inc_ref:
+       __nfp_flower_non_repr_priv_get(entry);
+       return entry;
+}
+
+void
+__nfp_flower_non_repr_priv_put(struct nfp_flower_non_repr_priv *non_repr_priv)
+{
+       if (--non_repr_priv->ref_count)
+               return;
+
+       list_del(&non_repr_priv->list);
+       kfree(non_repr_priv);
+}
+
+void
+nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev)
+{
+       struct nfp_flower_non_repr_priv *entry;
+
+       entry = nfp_flower_non_repr_priv_lookup(app, netdev);
+       if (!entry)
+               return;
+
+       __nfp_flower_non_repr_priv_put(entry);
+}
+
 static enum nfp_repr_type
 nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port)
 {
@@ -575,6 +640,7 @@ static int nfp_flower_init(struct nfp_app *app)
        }
 
        INIT_LIST_HEAD(&app_priv->indr_block_cb_priv);
+       INIT_LIST_HEAD(&app_priv->non_repr_priv);
 
        return 0;
 
index 1b9d6fd..2ce898b 100644 (file)
@@ -145,6 +145,7 @@ 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
+ * @non_repr_priv:     List of offloaded non-repr ports and their priv data
  * @active_mem_unit:   Current active memory unit for flower rules
  * @total_mem_units:   Total number of available memory units for flower rules
  */
@@ -170,6 +171,7 @@ struct nfp_flower_priv {
        struct nfp_mtu_conf mtu_conf;
        struct nfp_fl_lag nfp_lag;
        struct list_head indr_block_cb_priv;
+       struct list_head non_repr_priv;
        unsigned int active_mem_unit;
        unsigned int total_mem_units;
 };
@@ -182,6 +184,18 @@ struct nfp_flower_repr_priv {
        unsigned long lag_port_flags;
 };
 
+/**
+ * struct nfp_flower_non_repr_priv - Priv data for non-repr offloaded ports
+ * @list:              List entry of offloaded reprs
+ * @netdev:            Pointer to non-repr net_device
+ * @ref_count:         Number of references held for this priv data
+ */
+struct nfp_flower_non_repr_priv {
+       struct list_head list;
+       struct net_device *netdev;
+       int ref_count;
+};
+
 struct nfp_fl_key_ls {
        u32 key_layer_two;
        u8 key_layer;
@@ -282,4 +296,12 @@ int nfp_flower_reg_indir_block_handler(struct nfp_app *app,
                                       struct net_device *netdev,
                                       unsigned long event);
 
+void
+__nfp_flower_non_repr_priv_get(struct nfp_flower_non_repr_priv *non_repr_priv);
+struct nfp_flower_non_repr_priv *
+nfp_flower_non_repr_priv_get(struct nfp_app *app, struct net_device *netdev);
+void
+__nfp_flower_non_repr_priv_put(struct nfp_flower_non_repr_priv *non_repr_priv);
+void
+nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev);
 #endif