Commit c496291c authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

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: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarSimon Horman <simon.horman@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 18a4ded9
......@@ -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,
......
......@@ -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)
......
......@@ -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,
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,
......
......@@ -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;
......
......@@ -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);
......
......@@ -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,
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,
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,
int nfp_app_nic_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
unsigned int id);
#endif
......@@ -60,7 +60,7 @@ 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,
int nfp_app_nic_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
unsigned int id)
{
int err;
......
......@@ -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)
......
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment