From c496291c5a414bd55bae76880137947d2e8decbe Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 2 Sep 2017 18:26:00 -0700 Subject: [PATCH 1/6] nfp: separate app vNIC init/clean from alloc/free 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 Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/bpf/main.c | 10 +++--- .../net/ethernet/netronome/nfp/flower/cmsg.c | 2 +- .../net/ethernet/netronome/nfp/flower/main.c | 27 ++++++++++---- .../net/ethernet/netronome/nfp/flower/main.h | 2 ++ drivers/net/ethernet/netronome/nfp/nfp_app.c | 2 +- drivers/net/ethernet/netronome/nfp/nfp_app.h | 35 ++++++++++++++----- .../net/ethernet/netronome/nfp/nfp_app_nic.c | 4 +-- .../net/ethernet/netronome/nfp/nfp_net_main.c | 16 +++++++-- drivers/net/ethernet/netronome/nfp/nic/main.c | 2 +- 9 files changed, 73 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c index f4de3a7377b0d..be2cf10a2cd7a 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c @@ -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, diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c index 806924b82adca..d82d9888d6768 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c @@ -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) diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index 126a6b5233bfa..db59858c0f198 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -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 @@ static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn, 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, diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index b7043ca9b9fc3..c20dd00a1caec 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -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; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.c b/drivers/net/ethernet/netronome/nfp/nfp_app.c index 505e63f474191..82c290763529e 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_app.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_app.c @@ -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); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h index c13b9bbe7e625..af640b5c2108f 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_app.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h @@ -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 diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app_nic.c b/drivers/net/ethernet/netronome/nfp/nfp_app_nic.c index 4e37c81f9eaf0..2a2f2fbc8850d 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_app_nic.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_app_nic.c @@ -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; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c index 7c22cc4654b74..f2a1a4e2ce8bf 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c @@ -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 @@ nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar, 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) diff --git a/drivers/net/ethernet/netronome/nfp/nic/main.c b/drivers/net/ethernet/netronome/nfp/nic/main.c index 8287a85d22c14..d5b587fccaa30 100644 --- a/drivers/net/ethernet/netronome/nfp/nic/main.c +++ b/drivers/net/ethernet/netronome/nfp/nic/main.c @@ -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, From 192e685105097c48ad9f3665af643e1d97bcd2d4 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 2 Sep 2017 18:26:01 -0700 Subject: [PATCH 2/6] nfp: flower: base lifetime of representors on existence of lower vNIC Create representors after lower vNIC is registered and destroy them before it is destroyed. Move the code out of start/stop callbacks directly into vnic_init/clean callbacks. Make sure SR-IOV callbacks don't try to create representors when lower device does not exist. Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/flower/main.c | 66 ++++++++++++------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index db59858c0f198..91fe036171065 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -127,6 +127,11 @@ nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr) static void nfp_flower_sriov_disable(struct nfp_app *app) { + struct nfp_flower_priv *priv = app->priv; + + if (!priv->nn) + return; + nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF); } @@ -203,18 +208,16 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app, static int nfp_flower_sriov_enable(struct nfp_app *app, int num_vfs) { + struct nfp_flower_priv *priv = app->priv; + + if (!priv->nn) + return 0; + return nfp_flower_spawn_vnic_reprs(app, NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF, NFP_REPR_TYPE_VF, num_vfs); } -static void nfp_flower_stop(struct nfp_app *app) -{ - nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF); - nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT); - -} - static int nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv) { @@ -300,19 +303,6 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv) return err; } -static int nfp_flower_start(struct nfp_app *app) -{ - int err; - - err = nfp_flower_spawn_phy_reprs(app, app->priv); - if (err) - return err; - - return nfp_flower_spawn_vnic_reprs(app, - NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF, - NFP_REPR_TYPE_PF, 1); -} - static int nfp_flower_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, unsigned int id) { @@ -335,16 +325,49 @@ static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn) { struct nfp_flower_priv *priv = app->priv; + if (app->pf->num_vfs) + nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF); + nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF); + nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT); + priv->nn = NULL; } static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn) { struct nfp_flower_priv *priv = app->priv; + int err; priv->nn = nn; + err = nfp_flower_spawn_phy_reprs(app, app->priv); + if (err) + goto err_clear_nn; + + err = nfp_flower_spawn_vnic_reprs(app, + NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF, + NFP_REPR_TYPE_PF, 1); + if (err) + goto err_destroy_reprs_phy; + + if (app->pf->num_vfs) { + err = nfp_flower_spawn_vnic_reprs(app, + NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF, + NFP_REPR_TYPE_VF, + app->pf->num_vfs); + if (err) + goto err_destroy_reprs_pf; + } + return 0; + +err_destroy_reprs_pf: + nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF); +err_destroy_reprs_phy: + nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT); +err_clear_nn: + priv->nn = NULL; + return err; } static int nfp_flower_init(struct nfp_app *app) @@ -430,9 +453,6 @@ const struct nfp_app_type app_flower = { .repr_open = nfp_flower_repr_netdev_open, .repr_stop = nfp_flower_repr_netdev_stop, - .start = nfp_flower_start, - .stop = nfp_flower_stop, - .ctrl_msg_rx = nfp_flower_cmsg_rx, .sriov_enable = nfp_flower_sriov_enable, From 9d8b17bed757a3c5edbd6c1d09e52cbff6f2cc78 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 2 Sep 2017 18:26:02 -0700 Subject: [PATCH 3/6] nfp: move the start/stop app callbacks back Since representors are now created with a separate callback start/stop app callbacks can be moved again to their original location. They are intended to app-specific init/clean up over the control channel. Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_main.c | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c index f2a1a4e2ce8bf..5abb9ba31e7d2 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c @@ -469,10 +469,14 @@ static int nfp_net_pf_app_start(struct nfp_pf *pf) { int err; - err = nfp_app_start(pf->app, pf->ctrl_vnic); + err = nfp_net_pf_app_start_ctrl(pf); if (err) return err; + err = nfp_app_start(pf->app, pf->ctrl_vnic); + if (err) + goto err_ctrl_stop; + if (pf->num_vfs) { err = nfp_app_sriov_enable(pf->app, pf->num_vfs); if (err) @@ -483,6 +487,8 @@ static int nfp_net_pf_app_start(struct nfp_pf *pf) err_app_stop: nfp_app_stop(pf->app); +err_ctrl_stop: + nfp_net_pf_app_stop_ctrl(pf); return err; } @@ -491,6 +497,7 @@ static void nfp_net_pf_app_stop(struct nfp_pf *pf) if (pf->num_vfs) nfp_app_sriov_disable(pf->app); nfp_app_stop(pf->app); + nfp_net_pf_app_stop_ctrl(pf); } static void nfp_net_pci_unmap_mem(struct nfp_pf *pf) @@ -582,7 +589,7 @@ static int nfp_net_pci_map_mem(struct nfp_pf *pf) static void nfp_net_pci_remove_finish(struct nfp_pf *pf) { - nfp_net_pf_app_stop_ctrl(pf); + nfp_net_pf_app_stop(pf); /* stop app first, to avoid double free of ctrl vNIC's ddir */ nfp_net_debugfs_dir_clean(&pf->ddir); @@ -713,7 +720,6 @@ int nfp_net_pci_probe(struct nfp_pf *pf) { struct nfp_net_fw_version fw_ver; u8 __iomem *ctrl_bar, *qc_bar; - struct nfp_net *nn; int stride; int err; @@ -790,7 +796,7 @@ int nfp_net_pci_probe(struct nfp_pf *pf) if (err) goto err_free_vnics; - err = nfp_net_pf_app_start_ctrl(pf); + err = nfp_net_pf_app_start(pf); if (err) goto err_free_irqs; @@ -798,20 +804,12 @@ int nfp_net_pci_probe(struct nfp_pf *pf) if (err) goto err_stop_app; - err = nfp_net_pf_app_start(pf); - if (err) - goto err_clean_vnics; - mutex_unlock(&pf->lock); return 0; -err_clean_vnics: - list_for_each_entry(nn, &pf->vnics, vnic_list) - if (nfp_net_is_data_vnic(nn)) - nfp_net_pf_clean_vnic(pf, nn); err_stop_app: - nfp_net_pf_app_stop_ctrl(pf); + nfp_net_pf_app_stop(pf); err_free_irqs: nfp_net_pf_free_irqs(pf); err_free_vnics: @@ -835,8 +833,6 @@ void nfp_net_pci_remove(struct nfp_pf *pf) if (list_empty(&pf->vnics)) goto out; - nfp_net_pf_app_stop(pf); - list_for_each_entry(nn, &pf->vnics, vnic_list) if (nfp_net_is_data_vnic(nn)) nfp_net_pf_clean_vnic(pf, nn); From 023a928461e9370e73de2d5ef1a7e44a8033d2a6 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 2 Sep 2017 18:26:03 -0700 Subject: [PATCH 4/6] nfp: be drop monitor friendly Use dev_consume_skb_any() in place of dev_kfree_skb_any() when control frame has been successfully processed in flower and on the driver's main TX completion path. Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 3 +++ drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c index d82d9888d6768..e014d862b9b6e 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c @@ -189,8 +189,11 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb) default: nfp_flower_cmsg_warn(app, "Cannot handle invalid repr control type %u\n", type); + goto out; } + dev_consume_skb_any(skb); + return; out: dev_kfree_skb_any(skb); } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 2920889fa6d61..1c0187f0af51f 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -991,7 +991,7 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring) /* check for last gather fragment */ if (fidx == nr_frags - 1) - dev_kfree_skb_any(skb); + dev_consume_skb_any(skb); tx_ring->txbufs[idx].dma_addr = 0; tx_ring->txbufs[idx].skb = NULL; From 7c8a2d8b366d2dc9e386b96e4555cc5c6932c43d Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 2 Sep 2017 18:26:04 -0700 Subject: [PATCH 5/6] nfp: build the flower offload by default It's reasonable to assume that if user selects to build the NFP driver all offload capabilities will be enabled by default. Change the CONFIG_NFP_APP_FLOWER to default to enabled. Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/netronome/Kconfig b/drivers/net/ethernet/netronome/Kconfig index 0e331e2f685ad..ae0c46ba7546d 100644 --- a/drivers/net/ethernet/netronome/Kconfig +++ b/drivers/net/ethernet/netronome/Kconfig @@ -29,6 +29,7 @@ config NFP_APP_FLOWER bool "NFP4000/NFP6000 TC Flower offload support" depends on NFP depends on NET_SWITCHDEV + default y ---help--- Enable driver support for TC Flower offload on NFP4000 and NFP6000. Say Y, if you are planning to make use of TC Flower offload From 9ce4fa548313f585c637aa846f7fc904b676bf43 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sat, 2 Sep 2017 18:26:05 -0700 Subject: [PATCH 6/6] nfp: flower: restore RTNL locking around representor updates When we moved to updating representors from a workqueue grabbing the RTNL somehow got lost in the process. Restore it, and make sure RCU lock is not held while we are grabbing the RTNL. RCU protects the representor table, so since we will be under RTNL we can drop RCU lock as soon as we find the netdev pointer. RTNL is needed for the dev_set_mtu() call. Fixes: 2dff19622421 ("nfp: process MTU updates from firmware flower app") Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c index e014d862b9b6e..c3ca05d10fe10 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c @@ -141,12 +141,14 @@ nfp_flower_cmsg_portmod_rx(struct nfp_app *app, struct sk_buff *skb) msg = nfp_flower_cmsg_get_data(skb); link = msg->info & NFP_FLOWER_CMSG_PORTMOD_INFO_LINK; + rtnl_lock(); rcu_read_lock(); netdev = nfp_app_repr_get(app, be32_to_cpu(msg->portnum)); + rcu_read_unlock(); if (!netdev) { nfp_flower_cmsg_warn(app, "ctrl msg for unknown port 0x%08x\n", be32_to_cpu(msg->portnum)); - rcu_read_unlock(); + rtnl_unlock(); return; } @@ -161,7 +163,7 @@ nfp_flower_cmsg_portmod_rx(struct nfp_app *app, struct sk_buff *skb) } else { netif_carrier_off(netdev); } - rcu_read_unlock(); + rtnl_unlock(); } static void