From 0f08479143854257a8e7b38f296b1fd17bc91091 Mon Sep 17 00:00:00 2001 From: Dirk van der Merwe Date: Tue, 2 Jan 2018 19:19:00 -0800 Subject: [PATCH] nfp: add repr_preclean callback Just before a repr is cleaned up, we give the app a chance to perform some preclean configuration while the reprs pointer is still configured for the app. Signed-off-by: Dirk van der Merwe Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_app.h | 10 ++++++++++ .../net/ethernet/netronome/nfp/nfp_net_repr.c | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h index 0e5e0305ad1c..3af1943a8521 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_app.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h @@ -77,6 +77,8 @@ extern const struct nfp_app_type app_flower; * @vnic_init: vNIC netdev was registered * @vnic_clean: vNIC netdev about to be unregistered * @repr_init: representor about to be registered + * @repr_preclean: representor about to unregistered, executed before app + * reference to the it is removed * @repr_clean: representor about to be unregistered * @repr_open: representor netdev open callback * @repr_stop: representor netdev stop callback @@ -112,6 +114,7 @@ struct nfp_app_type { void (*vnic_clean)(struct nfp_app *app, struct nfp_net *nn); int (*repr_init)(struct nfp_app *app, struct net_device *netdev); + void (*repr_preclean)(struct nfp_app *app, struct net_device *netdev); void (*repr_clean)(struct nfp_app *app, struct net_device *netdev); int (*repr_open)(struct nfp_app *app, struct nfp_repr *repr); @@ -225,6 +228,13 @@ nfp_app_repr_init(struct nfp_app *app, struct net_device *netdev) return app->type->repr_init(app, netdev); } +static inline void +nfp_app_repr_preclean(struct nfp_app *app, struct net_device *netdev) +{ + if (app->type->repr_preclean) + app->type->repr_preclean(app, netdev); +} + static inline void nfp_app_repr_clean(struct nfp_app *app, struct net_device *netdev) { diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c index 3c6cb381385d..f50aa119570a 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c @@ -377,11 +377,22 @@ nfp_reprs_clean_and_free_by_type(struct nfp_app *app, enum nfp_repr_type type) { struct nfp_reprs *reprs; + int i; - reprs = nfp_app_reprs_set(app, type, NULL); + reprs = rcu_dereference_protected(app->reprs[type], + lockdep_is_held(&app->pf->lock)); if (!reprs) return; + /* Preclean must happen before we remove the reprs reference from the + * app below. + */ + for (i = 0; i < reprs->num_reprs; i++) + if (reprs->reprs[i]) + nfp_app_repr_preclean(app, reprs->reprs[i]); + + reprs = nfp_app_reprs_set(app, type, NULL); + synchronize_rcu(); nfp_reprs_clean_and_free(reprs); } @@ -420,8 +431,10 @@ int nfp_reprs_resync_phys_ports(struct nfp_app *app) continue; repr = netdev_priv(old_reprs->reprs[i]); - if (repr->port->type == NFP_PORT_INVALID) + if (repr->port->type == NFP_PORT_INVALID) { + nfp_app_repr_preclean(app, old_reprs->reprs[i]); continue; + } reprs->reprs[i] = old_reprs->reprs[i]; } @@ -438,7 +451,6 @@ int nfp_reprs_resync_phys_ports(struct nfp_app *app) if (repr->port->type != NFP_PORT_INVALID) continue; - nfp_app_repr_stop(app, repr); nfp_repr_clean(repr); } -- 2.30.2