nfp: slice the netdev spawning function
authorJakub Kicinski <jakub.kicinski@netronome.com>
Tue, 6 Jun 2017 00:01:54 +0000 (17:01 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 7 Jun 2017 16:51:41 +0000 (12:51 -0400)
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>
drivers/net/ethernet/netronome/nfp/nfp_net_main.c

index 82172665e02389107a3811e47234ad89f4548b8d..98a99b1996741bc68eb98d12dcd53cbdd4cf3f8b 100644 (file)
@@ -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);