Blob Blame History Raw
From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Mon, 5 Jun 2017 17:01:54 -0700
Subject: nfp: slice the netdev spawning function
Patch-mainline: v4.13-rc1
Git-commit: 6d4b0d8ed6d2f9e1741b9abd0ce64c641f890d6c
References: bsc#1055968

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>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/net/ethernet/netronome/nfp/nfp_net_main.c |   62 +++++++++++++---------
 1 file changed, 37 insertions(+), 25 deletions(-)

--- 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_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(st
 {
 	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);