nfp: separate app vNIC init/clean from alloc/free
authorJakub Kicinski <jakub.kicinski@netronome.com>
Sun, 3 Sep 2017 01:26:00 +0000 (18:26 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 4 Sep 2017 04:22:04 +0000 (21:22 -0700)
We currently only have one app callback for vNIC creation
and destruction.  This is insufficient, because some actions
have to be taken before netdev is registered, after it's
registered and after it's unregistered.  Old callbacks
were really corresponding to alloc/free actions.  Rename
them and add proper init/clean.  Apps using representors
will be able to use new callbacks to manage lifetime of
upper devices.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/netronome/nfp/bpf/main.c
drivers/net/ethernet/netronome/nfp/flower/cmsg.c
drivers/net/ethernet/netronome/nfp/flower/main.c
drivers/net/ethernet/netronome/nfp/flower/main.h
drivers/net/ethernet/netronome/nfp/nfp_app.c
drivers/net/ethernet/netronome/nfp/nfp_app.h
drivers/net/ethernet/netronome/nfp/nfp_app_nic.c
drivers/net/ethernet/netronome/nfp/nfp_net_main.c
drivers/net/ethernet/netronome/nfp/nic/main.c

index f4de3a7377b0d953053a16e2fa65763c01b0d054..be2cf10a2cd7a507caae5e2e9f983f142455de2a 100644 (file)
@@ -84,7 +84,7 @@ static const char *nfp_bpf_extra_cap(struct nfp_app *app, struct nfp_net *nn)
 }
 
 static int
-nfp_bpf_vnic_init(struct nfp_app *app, struct nfp_net *nn, unsigned int id)
+nfp_bpf_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, unsigned int id)
 {
        struct nfp_net_bpf_priv *priv;
        int ret;
@@ -106,14 +106,14 @@ nfp_bpf_vnic_init(struct nfp_app *app, struct nfp_net *nn, unsigned int id)
        setup_timer(&priv->rx_filter_stats_timer,
                    nfp_net_filter_stats_timer, (unsigned long)nn);
 
-       ret = nfp_app_nic_vnic_init(app, nn, id);
+       ret = nfp_app_nic_vnic_alloc(app, nn, id);
        if (ret)
                kfree(priv);
 
        return ret;
 }
 
-static void nfp_bpf_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
+static void nfp_bpf_vnic_free(struct nfp_app *app, struct nfp_net *nn)
 {
        if (nn->dp.bpf_offload_xdp)
                nfp_bpf_xdp_offload(app, nn, NULL);
@@ -149,8 +149,8 @@ const struct nfp_app_type app_bpf = {
 
        .extra_cap      = nfp_bpf_extra_cap,
 
-       .vnic_init      = nfp_bpf_vnic_init,
-       .vnic_clean     = nfp_bpf_vnic_clean,
+       .vnic_alloc     = nfp_bpf_vnic_alloc,
+       .vnic_free      = nfp_bpf_vnic_free,
 
        .setup_tc       = nfp_bpf_setup_tc,
        .tc_busy        = nfp_bpf_tc_busy,
index 806924b82adca42384d53490ff0f6851cac8da78..d82d9888d676899a95cf30fe0c50f4d0bcab97f9 100644 (file)
@@ -203,7 +203,7 @@ void nfp_flower_cmsg_process_rx(struct work_struct *work)
        priv = container_of(work, struct nfp_flower_priv, cmsg_work);
 
        while ((skb = skb_dequeue(&priv->cmsg_skbs)))
-               nfp_flower_cmsg_process_one_rx(priv->nn->app, skb);
+               nfp_flower_cmsg_process_one_rx(priv->app, skb);
 }
 
 void nfp_flower_cmsg_rx(struct nfp_app *app, struct sk_buff *skb)
index 126a6b5233bfafc6cd34aaf35cf528aaec254124..db59858c0f198ca62c058b3fbb122a27ad49abfb 100644 (file)
@@ -313,18 +313,14 @@ static int nfp_flower_start(struct nfp_app *app)
                                           NFP_REPR_TYPE_PF, 1);
 }
 
-static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn,
-                               unsigned int id)
+static int nfp_flower_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
+                                unsigned int id)
 {
-       struct nfp_flower_priv *priv = app->priv;
-
        if (id > 0) {
                nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n");
                goto err_invalid_port;
        }
 
-       priv->nn = nn;
-
        eth_hw_addr_random(nn->dp.netdev);
        netif_keep_dst(nn->dp.netdev);
 
@@ -335,6 +331,22 @@ err_invalid_port:
        return PTR_ERR_OR_ZERO(nn->port);
 }
 
+static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
+{
+       struct nfp_flower_priv *priv = app->priv;
+
+       priv->nn = NULL;
+}
+
+static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn)
+{
+       struct nfp_flower_priv *priv = app->priv;
+
+       priv->nn = nn;
+
+       return 0;
+}
+
 static int nfp_flower_init(struct nfp_app *app)
 {
        const struct nfp_pf *pf = app->pf;
@@ -374,6 +386,7 @@ static int nfp_flower_init(struct nfp_app *app)
                return -ENOMEM;
 
        app->priv = app_priv;
+       app_priv->app = app;
        skb_queue_head_init(&app_priv->cmsg_skbs);
        INIT_WORK(&app_priv->cmsg_work, nfp_flower_cmsg_process_rx);
 
@@ -410,7 +423,9 @@ const struct nfp_app_type app_flower = {
        .init           = nfp_flower_init,
        .clean          = nfp_flower_clean,
 
+       .vnic_alloc     = nfp_flower_vnic_alloc,
        .vnic_init      = nfp_flower_vnic_init,
+       .vnic_clean     = nfp_flower_vnic_clean,
 
        .repr_open      = nfp_flower_repr_netdev_open,
        .repr_stop      = nfp_flower_repr_netdev_stop,
index b7043ca9b9fc3052d6e8dd74250afb0b2205fa82..c20dd00a1caeca3412c0e2cbb9d62ac5a87d550a 100644 (file)
@@ -72,6 +72,7 @@ struct nfp_fl_stats_id {
 
 /**
  * struct nfp_flower_priv - Flower APP per-vNIC priv data
+ * @app:               Back pointer to app
  * @nn:                        Pointer to vNIC
  * @mask_id_seed:      Seed used for mask hash table
  * @flower_version:    HW version of flower
@@ -83,6 +84,7 @@ struct nfp_fl_stats_id {
  * @cmsg_skbs:         List of skbs for control message processing
  */
 struct nfp_flower_priv {
+       struct nfp_app *app;
        struct nfp_net *nn;
        u32 mask_id_seed;
        u64 flower_version;
index 505e63f47419116ae9033c5df1cac5c72efbc3d8..82c290763529e628a2c4b4c153d231ee33e6a477 100644 (file)
@@ -125,7 +125,7 @@ struct nfp_app *nfp_app_alloc(struct nfp_pf *pf, enum nfp_app_id id)
                return ERR_PTR(-EINVAL);
        }
 
-       if (WARN_ON(!apps[i]->name || !apps[i]->vnic_init))
+       if (WARN_ON(!apps[i]->name || !apps[i]->vnic_alloc))
                return ERR_PTR(-EINVAL);
 
        app = kzalloc(sizeof(*app), GFP_KERNEL);
index c13b9bbe7e6258589d209921378fd1c4c25d40e7..af640b5c2108f387cb90a4ccd37dd9f662ac5742 100644 (file)
@@ -69,8 +69,10 @@ extern const struct nfp_app_type app_flower;
  * @init:      perform basic app checks and init
  * @clean:     clean app state
  * @extra_cap: extra capabilities string
- * @vnic_init: init vNICs (assign port types, etc.)
- * @vnic_clean:        clean up app's vNIC state
+ * @vnic_alloc:        allocate vNICs (assign port types, etc.)
+ * @vnic_free: free up app's vNIC state
+ * @vnic_init: vNIC netdev was registered
+ * @vnic_clean:        vNIC netdev about to be unregistered
  * @repr_open: representor netdev open callback
  * @repr_stop: representor netdev stop callback
  * @start:     start application logic
@@ -95,8 +97,10 @@ struct nfp_app_type {
 
        const char *(*extra_cap)(struct nfp_app *app, struct nfp_net *nn);
 
-       int (*vnic_init)(struct nfp_app *app, struct nfp_net *nn,
-                        unsigned int id);
+       int (*vnic_alloc)(struct nfp_app *app, struct nfp_net *nn,
+                         unsigned int id);
+       void (*vnic_free)(struct nfp_app *app, struct nfp_net *nn);
+       int (*vnic_init)(struct nfp_app *app, struct nfp_net *nn);
        void (*vnic_clean)(struct nfp_app *app, struct nfp_net *nn);
 
        int (*repr_open)(struct nfp_app *app, struct nfp_repr *repr);
@@ -157,10 +161,23 @@ static inline void nfp_app_clean(struct nfp_app *app)
                app->type->clean(app);
 }
 
-static inline int nfp_app_vnic_init(struct nfp_app *app, struct nfp_net *nn,
-                                   unsigned int id)
+static inline int nfp_app_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
+                                    unsigned int id)
 {
-       return app->type->vnic_init(app, nn, id);
+       return app->type->vnic_alloc(app, nn, id);
+}
+
+static inline void nfp_app_vnic_free(struct nfp_app *app, struct nfp_net *nn)
+{
+       if (app->type->vnic_free)
+               app->type->vnic_free(app, nn);
+}
+
+static inline int nfp_app_vnic_init(struct nfp_app *app, struct nfp_net *nn)
+{
+       if (!app->type->vnic_init)
+               return 0;
+       return app->type->vnic_init(app, nn);
 }
 
 static inline void nfp_app_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
@@ -308,7 +325,7 @@ void nfp_app_free(struct nfp_app *app);
 
 /* Callbacks shared between apps */
 
-int nfp_app_nic_vnic_init(struct nfp_app *app, struct nfp_net *nn,
-                         unsigned int id);
+int nfp_app_nic_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
+                          unsigned int id);
 
 #endif
index 4e37c81f9eaf0702645cbd607e00b63d5237b707..2a2f2fbc8850df6a04e620ae0db1a989eec30a88 100644 (file)
@@ -60,8 +60,8 @@ nfp_app_nic_vnic_init_phy_port(struct nfp_pf *pf, struct nfp_app *app,
        return nn->port->type == NFP_PORT_INVALID;
 }
 
-int nfp_app_nic_vnic_init(struct nfp_app *app, struct nfp_net *nn,
-                         unsigned int id)
+int nfp_app_nic_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
+                          unsigned int id)
 {
        int err;
 
index 7c22cc4654b74867338c9e087f6f2af7e7d63a2f..f2a1a4e2ce8bf4154d66ee5556385d1e8985c0ed 100644 (file)
@@ -161,6 +161,8 @@ nfp_net_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
 
 static void nfp_net_pf_free_vnic(struct nfp_pf *pf, struct nfp_net *nn)
 {
+       if (nfp_net_is_data_vnic(nn))
+               nfp_app_vnic_free(pf->app, nn);
        nfp_port_free(nn->port);
        list_del(&nn->vnic_list);
        pf->num_vnics--;
@@ -205,7 +207,7 @@ nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev,
        nn->stride_tx = stride;
 
        if (needs_netdev) {
-               err = nfp_app_vnic_init(pf->app, nn, id);
+               err = nfp_app_vnic_alloc(pf->app, nn, id);
                if (err) {
                        nfp_net_free(nn);
                        return ERR_PTR(err);
@@ -243,8 +245,17 @@ nfp_net_pf_init_vnic(struct nfp_pf *pf, struct nfp_net *nn, unsigned int id)
 
        nfp_net_info(nn);
 
+       if (nfp_net_is_data_vnic(nn)) {
+               err = nfp_app_vnic_init(pf->app, nn);
+               if (err)
+                       goto err_devlink_port_clean;
+       }
+
        return 0;
 
+err_devlink_port_clean:
+       if (nn->port)
+               nfp_devlink_port_unregister(nn->port);
 err_dfs_clean:
        nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
        nfp_net_clean(nn);
@@ -288,11 +299,12 @@ err_free_prev:
 
 static void nfp_net_pf_clean_vnic(struct nfp_pf *pf, struct nfp_net *nn)
 {
+       if (nfp_net_is_data_vnic(nn))
+               nfp_app_vnic_clean(pf->app, nn);
        if (nn->port)
                nfp_devlink_port_unregister(nn->port);
        nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
        nfp_net_clean(nn);
-       nfp_app_vnic_clean(pf->app, nn);
 }
 
 static int nfp_net_pf_alloc_irqs(struct nfp_pf *pf)
index 8287a85d22c1445e8065f23f3f8ae89be452e5c8..d5b587fccaa30917e86edf45df0a15071366acdd 100644 (file)
@@ -63,7 +63,7 @@ const struct nfp_app_type app_nic = {
        .name           = "nic",
 
        .init           = nfp_nic_init,
-       .vnic_init      = nfp_app_nic_vnic_init,
+       .vnic_alloc     = nfp_app_nic_vnic_alloc,
 
        .sriov_enable   = nfp_nic_sriov_enable,
        .sriov_disable  = nfp_nic_sriov_disable,