aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJakub Kicinski <jakub.kicinski@netronome.com>2017-06-05 17:01:54 -0700
committerDavid S. Miller <davem@davemloft.net>2017-06-07 12:51:41 -0400
commit6d4b0d8ed6d2f9e1741b9abd0ce64c641f890d6c (patch)
treefd52e98456a45a2c098bc8ecb7a64435809ab143 /drivers
parentnfp: don't clutter init code passing fw_ver around (diff)
downloadlinux-dev-6d4b0d8ed6d2f9e1741b9abd0ce64c641f890d6c.tar.xz
linux-dev-6d4b0d8ed6d2f9e1741b9abd0ce64c641f890d6c.zip
nfp: slice the netdev spawning function
We want to be able to create a special vNIC for control messages. This vNIC should be created before any netdev is registered to allow nfp_app logic to exchange messages with the FW app before any netdev is visible to user space. Unfortunately we can't enable IRQs until we know how many vNICs we will need to spawn. Divide the function which spawns netdevs for vNICs into three parts: - vNIC/memory allocation; - IRQ allocation; - netdev init and register. This will help us insert the initialization of the control channel after IRQ allocation but before netdev init and register. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_main.c62
1 files changed, 37 insertions, 25 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 82172665e023..98a99b199674 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -391,18 +391,10 @@ static void nfp_net_pf_clean_vnic(struct nfp_pf *pf, struct nfp_net *nn)
nfp_app_vnic_clean(pf->app, nn);
}
-static int
-nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
- void __iomem *ctrl_bar, void __iomem *qc_bar, int stride)
+static int nfp_net_pf_alloc_irqs(struct nfp_pf *pf)
{
- unsigned int id, wanted_irqs, num_irqs, vnics_left, irqs_left;
+ unsigned int wanted_irqs, num_irqs, vnics_left, irqs_left;
struct nfp_net *nn;
- int err;
-
- /* Allocate the vnics and do basic init */
- err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, qc_bar, stride);
- if (err)
- return err;
/* Get MSI-X vectors */
wanted_irqs = 0;
@@ -410,18 +402,16 @@ nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
wanted_irqs += NFP_NET_NON_Q_VECTORS + nn->dp.num_r_vecs;
pf->irq_entries = kcalloc(wanted_irqs, sizeof(*pf->irq_entries),
GFP_KERNEL);
- if (!pf->irq_entries) {
- err = -ENOMEM;
- goto err_nn_free;
- }
+ if (!pf->irq_entries)
+ return -ENOMEM;
num_irqs = nfp_net_irqs_alloc(pf->pdev, pf->irq_entries,
NFP_NET_MIN_VNIC_IRQS * pf->num_vnics,
wanted_irqs);
if (!num_irqs) {
- nn_warn(nn, "Unable to allocate MSI-X Vectors. Exiting\n");
- err = -ENOMEM;
- goto err_vec_free;
+ nfp_warn(pf->cpp, "Unable to allocate MSI-X vectors\n");
+ kfree(pf->irq_entries);
+ return -ENOMEM;
}
/* Distribute IRQs to vNICs */
@@ -437,6 +427,21 @@ nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
vnics_left--;
}
+ return 0;
+}
+
+static void nfp_net_pf_free_irqs(struct nfp_pf *pf)
+{
+ nfp_net_irqs_disable(pf->pdev);
+ kfree(pf->irq_entries);
+}
+
+static int nfp_net_pf_init_vnics(struct nfp_pf *pf)
+{
+ struct nfp_net *nn;
+ unsigned int id;
+ int err;
+
/* Finish vNIC init and register */
id = 0;
list_for_each_entry(nn, &pf->vnics, vnic_list) {
@@ -452,11 +457,6 @@ nfp_net_pf_spawn_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);
- nfp_net_irqs_disable(pf->pdev);
-err_vec_free:
- kfree(pf->irq_entries);
-err_nn_free:
- nfp_net_pf_free_vnics(pf);
return err;
}
@@ -489,8 +489,7 @@ static void nfp_net_pci_remove_finish(struct nfp_pf *pf)
{
nfp_net_debugfs_dir_clean(&pf->ddir);
- nfp_net_irqs_disable(pf->pdev);
- kfree(pf->irq_entries);
+ nfp_net_pf_free_irqs(pf);
nfp_net_pf_app_clean(pf);
@@ -691,14 +690,27 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
pf->ddir = nfp_net_debugfs_device_add(pf->pdev);
- err = nfp_net_pf_spawn_vnics(pf, ctrl_bar, qc_bar, stride);
+ /* Allocate the vnics and do basic init */
+ err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, qc_bar, stride);
if (err)
goto err_clean_ddir;
+ err = nfp_net_pf_alloc_irqs(pf);
+ if (err)
+ goto err_free_vnics;
+
+ err = nfp_net_pf_init_vnics(pf);
+ if (err)
+ goto err_free_irqs;
+
mutex_unlock(&pf->lock);
return 0;
+err_free_irqs:
+ nfp_net_pf_free_irqs(pf);
+err_free_vnics:
+ nfp_net_pf_free_vnics(pf);
err_clean_ddir:
nfp_net_debugfs_dir_clean(&pf->ddir);
nfp_net_pf_app_clean(pf);