diff options
author | Jakub Kicinski <jakub.kicinski@netronome.com> | 2017-06-06 03:01:56 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-07 19:51:42 +0300 |
commit | 02082701b974eea3afdb4ac25ab613adabebe41a (patch) | |
tree | e5715cdd23925b7d9308fd409016db0e9ad6f6a9 /drivers/net/ethernet/netronome/nfp/nfp_net_main.c | |
parent | 2c7e41c0b2f103056f93dd5922c03d6e2021c76d (diff) | |
download | linux-02082701b974eea3afdb4ac25ab613adabebe41a.tar.xz |
nfp: create control vNICs and wire up rx/tx
When driver encounters an nfp_app which has a control message handler
defined, allocate a control vNIC. This control channel will be used
to exchange data with the application FW such as flow table programming,
statistics and global datapath control.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/netronome/nfp/nfp_net_main.c')
-rw-r--r-- | drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 121 |
1 files changed, 107 insertions, 14 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c index 362dca38223b..db12700b5afc 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c @@ -266,12 +266,11 @@ static void nfp_net_pf_free_vnic(struct nfp_pf *pf, struct nfp_net *nn) static void nfp_net_pf_free_vnics(struct nfp_pf *pf) { - struct nfp_net *nn; + struct nfp_net *nn, *next; - while (!list_empty(&pf->vnics)) { - nn = list_first_entry(&pf->vnics, struct nfp_net, vnic_list); - nfp_net_pf_free_vnic(pf, nn); - } + list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list) + if (nfp_net_is_data_vnic(nn)) + nfp_net_pf_free_vnic(pf, nn); } static struct nfp_net * @@ -302,10 +301,12 @@ nfp_net_pf_alloc_vnic(struct nfp_pf *pf, bool needs_netdev, nn->stride_rx = stride; nn->stride_tx = stride; - err = nfp_app_vnic_init(pf->app, nn, eth_id); - if (err) { - nfp_net_free(nn); - return ERR_PTR(err); + if (needs_netdev) { + err = nfp_app_vnic_init(pf->app, nn, eth_id); + if (err) { + nfp_net_free(nn); + return ERR_PTR(err); + } } pf->num_vnics++; @@ -446,6 +447,8 @@ static int nfp_net_pf_init_vnics(struct nfp_pf *pf) /* Finish vNIC init and register */ id = 0; list_for_each_entry(nn, &pf->vnics, vnic_list) { + if (!nfp_net_is_data_vnic(nn)) + continue; err = nfp_net_pf_init_vnic(pf, nn, id); if (err) goto err_prev_deinit; @@ -457,12 +460,15 @@ static int nfp_net_pf_init_vnics(struct nfp_pf *pf) err_prev_deinit: list_for_each_entry_continue_reverse(nn, &pf->vnics, vnic_list) - nfp_net_pf_clean_vnic(pf, nn); + if (nfp_net_is_data_vnic(nn)) + nfp_net_pf_clean_vnic(pf, nn); return err; } -static int nfp_net_pf_app_init(struct nfp_pf *pf) +static int +nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride) { + u8 __iomem *ctrl_bar; int err; pf->app = nfp_app_alloc(pf, nfp_net_pf_get_app_id(pf)); @@ -473,8 +479,28 @@ static int nfp_net_pf_app_init(struct nfp_pf *pf) if (err) goto err_free; + if (!nfp_app_needs_ctrl_vnic(pf->app)) + return 0; + + ctrl_bar = nfp_net_pf_map_rtsym(pf, "net.ctrl", "_pf%u_net_ctrl_bar", + NFP_PF_CSR_SLICE_SIZE, + &pf->ctrl_vnic_bar); + if (IS_ERR(ctrl_bar)) { + err = PTR_ERR(ctrl_bar); + goto err_free; + } + + pf->ctrl_vnic = nfp_net_pf_alloc_vnic(pf, false, ctrl_bar, qc_bar, + stride, 0); + if (IS_ERR(pf->ctrl_vnic)) { + err = PTR_ERR(pf->ctrl_vnic); + goto err_unmap; + } + return 0; +err_unmap: + nfp_cpp_area_release_free(pf->ctrl_vnic_bar); err_free: nfp_app_free(pf->app); return err; @@ -482,12 +508,72 @@ err_free: static void nfp_net_pf_app_clean(struct nfp_pf *pf) { + if (pf->ctrl_vnic) { + nfp_net_pf_free_vnic(pf, pf->ctrl_vnic); + nfp_cpp_area_release_free(pf->ctrl_vnic_bar); + } nfp_app_free(pf->app); pf->app = NULL; } +static int nfp_net_pf_app_start_ctrl(struct nfp_pf *pf) +{ + int err; + + if (!pf->ctrl_vnic) + return 0; + err = nfp_net_pf_init_vnic(pf, pf->ctrl_vnic, 0); + if (err) + return err; + + err = nfp_ctrl_open(pf->ctrl_vnic); + if (err) + goto err_clean_ctrl; + + return 0; + +err_clean_ctrl: + nfp_net_pf_clean_vnic(pf, pf->ctrl_vnic); + return err; +} + +static void nfp_net_pf_app_stop_ctrl(struct nfp_pf *pf) +{ + if (!pf->ctrl_vnic) + return; + nfp_ctrl_close(pf->ctrl_vnic); + nfp_net_pf_clean_vnic(pf, pf->ctrl_vnic); +} + +static int nfp_net_pf_app_start(struct nfp_pf *pf) +{ + int err; + + 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; + + return 0; + +err_ctrl_stop: + nfp_net_pf_app_stop_ctrl(pf); + return err; +} + +static void nfp_net_pf_app_stop(struct nfp_pf *pf) +{ + nfp_app_stop(pf->app); + nfp_net_pf_app_stop_ctrl(pf); +} + static void nfp_net_pci_remove_finish(struct nfp_pf *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); nfp_net_pf_free_irqs(pf); @@ -685,7 +771,7 @@ int nfp_net_pci_probe(struct nfp_pf *pf) goto err_ctrl_unmap; } - err = nfp_net_pf_app_init(pf); + err = nfp_net_pf_app_init(pf, qc_bar, stride); if (err) goto err_unmap_qc; @@ -700,14 +786,20 @@ int nfp_net_pci_probe(struct nfp_pf *pf) if (err) goto err_free_vnics; - err = nfp_net_pf_init_vnics(pf); + err = nfp_net_pf_app_start(pf); if (err) goto err_free_irqs; + err = nfp_net_pf_init_vnics(pf); + if (err) + goto err_stop_app; + mutex_unlock(&pf->lock); return 0; +err_stop_app: + nfp_net_pf_app_stop(pf); err_free_irqs: nfp_net_pf_free_irqs(pf); err_free_vnics: @@ -733,7 +825,8 @@ void nfp_net_pci_remove(struct nfp_pf *pf) goto out; list_for_each_entry(nn, &pf->vnics, vnic_list) - nfp_net_pf_clean_vnic(pf, nn); + if (nfp_net_is_data_vnic(nn)) + nfp_net_pf_clean_vnic(pf, nn); nfp_net_pf_free_vnics(pf); |