Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 04/13] nfp: add nfp_net_pf_free_vnic() function
From: Jakub Kicinski @ 2017-05-19 22:01 UTC (permalink / raw)
  To: netdev; +Cc: kubakici, oss-drivers, Jakub Kicinski
In-Reply-To: <20170519220155.27857-1-jakub.kicinski@netronome.com>

Soon a third place will need to free a struct nfp_net.  Add a free
counterpart to nfp_net_pf_alloc_vnic().

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 532371940fd6..5f0c58a56182 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -268,16 +268,20 @@ static u8 __iomem *nfp_net_pf_map_ctrl_bar(struct nfp_pf *pf)
 	return ctrl_bar;
 }
 
+static void nfp_net_pf_free_vnic(struct nfp_pf *pf, struct nfp_net *nn)
+{
+	list_del(&nn->vnic_list);
+	pf->num_vnics--;
+	nfp_net_free(nn);
+}
+
 static void nfp_net_pf_free_vnics(struct nfp_pf *pf)
 {
 	struct nfp_net *nn;
 
 	while (!list_empty(&pf->vnics)) {
 		nn = list_first_entry(&pf->vnics, struct nfp_net, vnic_list);
-		list_del(&nn->vnic_list);
-		pf->num_vnics--;
-
-		nfp_net_free(nn);
+		nfp_net_pf_free_vnic(pf, nn);
 	}
 }
 
@@ -518,9 +522,7 @@ static void nfp_net_refresh_vnics(struct work_struct *work)
 		nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
 		nfp_net_clean(nn);
 
-		list_del(&nn->vnic_list);
-		pf->num_vnics--;
-		nfp_net_free(nn);
+		nfp_net_pf_free_vnic(pf, nn);
 	}
 
 	if (list_empty(&pf->vnics))
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 03/13] nfp: rename netdev/port to vNIC
From: Jakub Kicinski @ 2017-05-19 22:01 UTC (permalink / raw)
  To: netdev; +Cc: kubakici, oss-drivers, Jakub Kicinski
In-Reply-To: <20170519220155.27857-1-jakub.kicinski@netronome.com>

vNIC is a PCIe-side abstraction NFP firmwares supported by this
driver use.  It was initially meant to represent a device port
and therefore a netdev but today should be thought of as a way
of grouping descriptor rings and associated state.  Advanced apps
will have vNICs without netdevs and ports without a vNIC (using
representors instead).

Make sure code refers to vNICs as vNICs and not ports or netdevs.
No functional changes.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/nfp_main.c      |   2 +-
 drivers/net/ethernet/netronome/nfp/nfp_main.h      |  25 ++--
 drivers/net/ethernet/netronome/nfp/nfp_net.h       |  10 +-
 .../net/ethernet/netronome/nfp/nfp_net_debugfs.c   |   4 +-
 drivers/net/ethernet/netronome/nfp/nfp_net_main.c  | 150 ++++++++++-----------
 .../net/ethernet/netronome/nfp/nfp_netvf_main.c    |   4 +-
 6 files changed, 97 insertions(+), 98 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c
index dde35dae35c5..9fbc7eedc017 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c
@@ -340,7 +340,7 @@ static int nfp_pci_probe(struct pci_dev *pdev,
 		err = -ENOMEM;
 		goto err_rel_regions;
 	}
-	INIT_LIST_HEAD(&pf->ports);
+	INIT_LIST_HEAD(&pf->vnics);
 	pci_set_drvdata(pdev, pf);
 	pf->pdev = pdev;
 
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h
index b57de047b002..bf31913ac7a5 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.h
@@ -57,19 +57,20 @@ struct nfp_eth_table;
  * struct nfp_pf - NFP PF-specific device structure
  * @pdev:		Backpointer to PCI device
  * @cpp:		Pointer to the CPP handle
- * @ctrl_area:		Pointer to the CPP area for the control BAR
+ * @data_vnic_bar:	Pointer to the CPP area for the data vNICs' BARs
  * @tx_area:		Pointer to the CPP area for the TX queues
  * @rx_area:		Pointer to the CPP area for the FL/RX queues
- * @irq_entries:	Array of MSI-X entries for all ports
+ * @irq_entries:	Array of MSI-X entries for all vNICs
  * @limit_vfs:		Number of VFs supported by firmware (~0 for PCI limit)
  * @num_vfs:		Number of SR-IOV VFs enabled
  * @fw_loaded:		Is the firmware loaded?
- * @eth_tbl:		NSP ETH table
  * @ddir:		Per-device debugfs directory
- * @num_ports:		Number of adapter ports app firmware supports
- * @num_netdevs:	Number of netdevs spawned
- * @ports:		Linked list of port structures (struct nfp_net)
- * @port_lock:		Protects @ports, @num_ports, @num_netdevs
+ *
+ * @lock:		Protects all fields below
+ * @eth_tbl:		NSP ETH table
+ * @max_data_vnics:	Number of data vNICs app firmware supports
+ * @num_vnics:		Number of vNICs spawned
+ * @vnics:		Linked list of vNIC structures (struct nfp_net)
  * @port_refresh_work:	Work entry for taking netdevs out
  */
 struct nfp_pf {
@@ -77,7 +78,7 @@ struct nfp_pf {
 
 	struct nfp_cpp *cpp;
 
-	struct nfp_cpp_area *ctrl_area;
+	struct nfp_cpp_area *data_vnic_bar;
 	struct nfp_cpp_area *tx_area;
 	struct nfp_cpp_area *rx_area;
 
@@ -92,12 +93,12 @@ struct nfp_pf {
 
 	struct dentry *ddir;
 
-	unsigned int num_ports;
-	unsigned int num_netdevs;
+	unsigned int max_data_vnics;
+	unsigned int num_vnics;
 
-	struct list_head ports;
+	struct list_head vnics;
 	struct work_struct port_refresh_work;
-	struct mutex port_lock;
+	struct mutex lock;
 };
 
 extern struct pci_driver nfp_netvf_pci_driver;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 04609191ca88..1d41be9b2309 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -84,7 +84,7 @@
 #define NFP_NET_NON_Q_VECTORS		2
 #define NFP_NET_IRQ_LSC_IDX		0
 #define NFP_NET_IRQ_EXN_IDX		1
-#define NFP_NET_MIN_PORT_IRQS		(NFP_NET_NON_Q_VECTORS + 1)
+#define NFP_NET_MIN_VNIC_IRQS		(NFP_NET_NON_Q_VECTORS + 1)
 
 /* Queue/Ring definitions */
 #define NFP_NET_MAX_TX_RINGS	64	/* Max. # of Tx rings per device */
@@ -555,7 +555,7 @@ struct nfp_net_dp {
  * @rx_bar:             Pointer to mapped FL/RX queues
  * @debugfs_dir:	Device directory in debugfs
  * @ethtool_dump_flag:	Ethtool dump flag
- * @port_list:		Entry on device port list
+ * @vnic_list:		Entry on device vNIC list
  * @pdev:		Backpointer to PCI device
  * @cpp:		CPP device handle if available
  * @eth_port:		Translated ETH Table port entry
@@ -625,7 +625,7 @@ struct nfp_net {
 	struct dentry *debugfs_dir;
 	u32 ethtool_dump_flag;
 
-	struct list_head port_list;
+	struct list_head vnic_list;
 
 	struct pci_dev *pdev;
 	struct nfp_cpp *cpp;
@@ -842,7 +842,7 @@ void nfp_net_refresh_port_table(struct nfp_net *nn);
 void nfp_net_debugfs_create(void);
 void nfp_net_debugfs_destroy(void);
 struct dentry *nfp_net_debugfs_device_add(struct pci_dev *pdev);
-void nfp_net_debugfs_port_add(struct nfp_net *nn, struct dentry *ddir, int id);
+void nfp_net_debugfs_vnic_add(struct nfp_net *nn, struct dentry *ddir, int id);
 void nfp_net_debugfs_dir_clean(struct dentry **dir);
 #else
 static inline void nfp_net_debugfs_create(void)
@@ -859,7 +859,7 @@ static inline struct dentry *nfp_net_debugfs_device_add(struct pci_dev *pdev)
 }
 
 static inline void
-nfp_net_debugfs_port_add(struct nfp_net *nn, struct dentry *ddir, int id)
+nfp_net_debugfs_vnic_add(struct nfp_net *nn, struct dentry *ddir, int id)
 {
 }
 
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
index 4077c59bf782..6cf1b234eecd 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
@@ -200,7 +200,7 @@ static const struct file_operations nfp_xdp_q_fops = {
 	.llseek = seq_lseek
 };
 
-void nfp_net_debugfs_port_add(struct nfp_net *nn, struct dentry *ddir, int id)
+void nfp_net_debugfs_vnic_add(struct nfp_net *nn, struct dentry *ddir, int id)
 {
 	struct dentry *queues, *tx, *rx, *xdp;
 	char name[20];
@@ -209,7 +209,7 @@ void nfp_net_debugfs_port_add(struct nfp_net *nn, struct dentry *ddir, int id)
 	if (IS_ERR_OR_NULL(nfp_dir))
 		return;
 
-	sprintf(name, "port%d", id);
+	sprintf(name, "vnic%d", id);
 	nn->debugfs_dir = debugfs_create_dir(name, ddir);
 	if (IS_ERR_OR_NULL(nn->debugfs_dir))
 		return;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 55d916cb04fe..532371940fd6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -197,10 +197,10 @@ static unsigned int nfp_net_pf_get_num_ports(struct nfp_pf *pf)
 		 nfp_cppcore_pcie_unit(pf->cpp));
 
 	val = nfp_rtsym_read_le(pf->cpp, name, &err);
-	/* Default to one port */
+	/* Default to one port/vNIC */
 	if (err) {
 		if (err != -ENOENT)
-			nfp_err(pf->cpp, "Unable to read adapter port count\n");
+			nfp_err(pf->cpp, "Unable to read adapter vNIC count\n");
 		val = 1;
 	}
 
@@ -216,7 +216,7 @@ nfp_net_pf_total_qcs(struct nfp_pf *pf, void __iomem *ctrl_bar,
 	min_qc = readl(ctrl_bar + start_off);
 	max_qc = min_qc;
 
-	for (i = 0; i < pf->num_ports; i++) {
+	for (i = 0; i < pf->max_data_vnics; i++) {
 		/* To make our lives simpler only accept configuration where
 		 * queues are allocated to PFs in order (queues of PFn all have
 		 * indexes lower than PFn+1).
@@ -248,17 +248,17 @@ static u8 __iomem *nfp_net_pf_map_ctrl_bar(struct nfp_pf *pf)
 		return NULL;
 	}
 
-	if (ctrl_sym->size < pf->num_ports * NFP_PF_CSR_SLICE_SIZE) {
+	if (ctrl_sym->size < pf->max_data_vnics * NFP_PF_CSR_SLICE_SIZE) {
 		dev_err(&pf->pdev->dev,
-			"PF BAR0 too small to contain %d ports\n",
-			pf->num_ports);
+			"PF BAR0 too small to contain %d vNICs\n",
+			pf->max_data_vnics);
 		return NULL;
 	}
 
 	ctrl_bar = nfp_net_map_area(pf->cpp, "net.ctrl",
 				    ctrl_sym->domain, ctrl_sym->target,
 				    ctrl_sym->addr, ctrl_sym->size,
-				    &pf->ctrl_area);
+				    &pf->data_vnic_bar);
 	if (IS_ERR(ctrl_bar)) {
 		dev_err(&pf->pdev->dev, "Failed to map PF BAR0: %ld\n",
 			PTR_ERR(ctrl_bar));
@@ -268,24 +268,24 @@ static u8 __iomem *nfp_net_pf_map_ctrl_bar(struct nfp_pf *pf)
 	return ctrl_bar;
 }
 
-static void nfp_net_pf_free_netdevs(struct nfp_pf *pf)
+static void nfp_net_pf_free_vnics(struct nfp_pf *pf)
 {
 	struct nfp_net *nn;
 
-	while (!list_empty(&pf->ports)) {
-		nn = list_first_entry(&pf->ports, struct nfp_net, port_list);
-		list_del(&nn->port_list);
-		pf->num_netdevs--;
+	while (!list_empty(&pf->vnics)) {
+		nn = list_first_entry(&pf->vnics, struct nfp_net, vnic_list);
+		list_del(&nn->vnic_list);
+		pf->num_vnics--;
 
 		nfp_net_free(nn);
 	}
 }
 
 static struct nfp_net *
-nfp_net_pf_alloc_port_netdev(struct nfp_pf *pf, void __iomem *ctrl_bar,
-			     void __iomem *tx_bar, void __iomem *rx_bar,
-			     int stride, struct nfp_net_fw_version *fw_ver,
-			     struct nfp_eth_table_port *eth_port)
+nfp_net_pf_alloc_vnic(struct nfp_pf *pf, void __iomem *ctrl_bar,
+		      void __iomem *tx_bar, void __iomem *rx_bar,
+		      int stride, struct nfp_net_fw_version *fw_ver,
+		      struct nfp_eth_table_port *eth_port)
 {
 	u32 n_tx_rings, n_rx_rings;
 	struct nfp_net *nn;
@@ -293,7 +293,7 @@ nfp_net_pf_alloc_port_netdev(struct nfp_pf *pf, void __iomem *ctrl_bar,
 	n_tx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_TXRINGS);
 	n_rx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_RXRINGS);
 
-	/* Allocate and initialise the netdev */
+	/* Allocate and initialise the vNIC */
 	nn = nfp_net_alloc(pf->pdev, n_tx_rings, n_rx_rings);
 	if (IS_ERR(nn))
 		return nn;
@@ -312,8 +312,7 @@ nfp_net_pf_alloc_port_netdev(struct nfp_pf *pf, void __iomem *ctrl_bar,
 }
 
 static int
-nfp_net_pf_init_port_netdev(struct nfp_pf *pf, struct nfp_net *nn,
-			    unsigned int id)
+nfp_net_pf_init_vnic(struct nfp_pf *pf, struct nfp_net *nn, unsigned int id)
 {
 	int err;
 
@@ -330,7 +329,7 @@ nfp_net_pf_init_port_netdev(struct nfp_pf *pf, struct nfp_net *nn,
 	if (err)
 		return err;
 
-	nfp_net_debugfs_port_add(nn, pf->ddir, id);
+	nfp_net_debugfs_vnic_add(nn, pf->ddir, id);
 
 	nfp_net_info(nn);
 
@@ -338,9 +337,9 @@ nfp_net_pf_init_port_netdev(struct nfp_pf *pf, struct nfp_net *nn,
 }
 
 static int
-nfp_net_pf_alloc_netdevs(struct nfp_pf *pf, void __iomem *ctrl_bar,
-			 void __iomem *tx_bar, void __iomem *rx_bar,
-			 int stride, struct nfp_net_fw_version *fw_ver)
+nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,
+		       void __iomem *tx_bar, void __iomem *rx_bar,
+		       int stride, struct nfp_net_fw_version *fw_ver)
 {
 	u32 prev_tx_base, prev_rx_base, tgt_tx_base, tgt_rx_base;
 	struct nfp_eth_table_port *eth_port;
@@ -351,7 +350,7 @@ nfp_net_pf_alloc_netdevs(struct nfp_pf *pf, void __iomem *ctrl_bar,
 	prev_tx_base = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
 	prev_rx_base = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
 
-	for (i = 0; i < pf->num_ports; i++) {
+	for (i = 0; i < pf->max_data_vnics; i++) {
 		tgt_tx_base = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
 		tgt_rx_base = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
 		tx_bar += (tgt_tx_base - prev_tx_base) * NFP_QCP_QUEUE_ADDR_SZ;
@@ -363,49 +362,48 @@ nfp_net_pf_alloc_netdevs(struct nfp_pf *pf, void __iomem *ctrl_bar,
 		if (eth_port && eth_port->override_changed) {
 			nfp_warn(pf->cpp, "Config changed for port #%d, reboot required before port will be operational\n", i);
 		} else {
-			nn = nfp_net_pf_alloc_port_netdev(pf, ctrl_bar, tx_bar,
-							  rx_bar, stride,
-							  fw_ver, eth_port);
+			nn = nfp_net_pf_alloc_vnic(pf, ctrl_bar, tx_bar, rx_bar,
+						   stride, fw_ver, eth_port);
 			if (IS_ERR(nn)) {
 				err = PTR_ERR(nn);
 				goto err_free_prev;
 			}
-			list_add_tail(&nn->port_list, &pf->ports);
-			pf->num_netdevs++;
+			list_add_tail(&nn->vnic_list, &pf->vnics);
+			pf->num_vnics++;
 		}
 
 		ctrl_bar += NFP_PF_CSR_SLICE_SIZE;
 	}
 
-	if (list_empty(&pf->ports))
+	if (list_empty(&pf->vnics))
 		return -ENODEV;
 
 	return 0;
 
 err_free_prev:
-	nfp_net_pf_free_netdevs(pf);
+	nfp_net_pf_free_vnics(pf);
 	return err;
 }
 
 static int
-nfp_net_pf_spawn_netdevs(struct nfp_pf *pf,
-			 void __iomem *ctrl_bar, void __iomem *tx_bar,
-			 void __iomem *rx_bar, int stride,
-			 struct nfp_net_fw_version *fw_ver)
+nfp_net_pf_spawn_vnics(struct nfp_pf *pf,
+		       void __iomem *ctrl_bar, void __iomem *tx_bar,
+		       void __iomem *rx_bar, int stride,
+		       struct nfp_net_fw_version *fw_ver)
 {
-	unsigned int id, wanted_irqs, num_irqs, ports_left, irqs_left;
+	unsigned int id, wanted_irqs, num_irqs, vnics_left, irqs_left;
 	struct nfp_net *nn;
 	int err;
 
-	/* Allocate the netdevs and do basic init */
-	err = nfp_net_pf_alloc_netdevs(pf, ctrl_bar, tx_bar, rx_bar,
-				       stride, fw_ver);
+	/* Allocate the vnics and do basic init */
+	err = nfp_net_pf_alloc_vnics(pf, ctrl_bar, tx_bar, rx_bar,
+				     stride, fw_ver);
 	if (err)
 		return err;
 
 	/* Get MSI-X vectors */
 	wanted_irqs = 0;
-	list_for_each_entry(nn, &pf->ports, port_list)
+	list_for_each_entry(nn, &pf->vnics, vnic_list)
 		wanted_irqs += NFP_NET_NON_Q_VECTORS + nn->dp.num_r_vecs;
 	pf->irq_entries = kcalloc(wanted_irqs, sizeof(*pf->irq_entries),
 				  GFP_KERNEL);
@@ -415,7 +413,7 @@ nfp_net_pf_spawn_netdevs(struct nfp_pf *pf,
 	}
 
 	num_irqs = nfp_net_irqs_alloc(pf->pdev, pf->irq_entries,
-				      NFP_NET_MIN_PORT_IRQS * pf->num_netdevs,
+				      NFP_NET_MIN_VNIC_IRQS * pf->num_vnics,
 				      wanted_irqs);
 	if (!num_irqs) {
 		nn_warn(nn, "Unable to allocate MSI-X Vectors. Exiting\n");
@@ -423,23 +421,23 @@ nfp_net_pf_spawn_netdevs(struct nfp_pf *pf,
 		goto err_vec_free;
 	}
 
-	/* Distribute IRQs to ports */
+	/* Distribute IRQs to vNICs */
 	irqs_left = num_irqs;
-	ports_left = pf->num_netdevs;
-	list_for_each_entry(nn, &pf->ports, port_list) {
+	vnics_left = pf->num_vnics;
+	list_for_each_entry(nn, &pf->vnics, vnic_list) {
 		unsigned int n;
 
-		n = DIV_ROUND_UP(irqs_left, ports_left);
+		n = DIV_ROUND_UP(irqs_left, vnics_left);
 		nfp_net_irqs_assign(nn, &pf->irq_entries[num_irqs - irqs_left],
 				    n);
 		irqs_left -= n;
-		ports_left--;
+		vnics_left--;
 	}
 
-	/* Finish netdev init and register */
+	/* Finish vNIC init and register */
 	id = 0;
-	list_for_each_entry(nn, &pf->ports, port_list) {
-		err = nfp_net_pf_init_port_netdev(pf, nn, id);
+	list_for_each_entry(nn, &pf->vnics, vnic_list) {
+		err = nfp_net_pf_init_vnic(pf, nn, id);
 		if (err)
 			goto err_prev_deinit;
 
@@ -449,7 +447,7 @@ nfp_net_pf_spawn_netdevs(struct nfp_pf *pf,
 	return 0;
 
 err_prev_deinit:
-	list_for_each_entry_continue_reverse(nn, &pf->ports, port_list) {
+	list_for_each_entry_continue_reverse(nn, &pf->vnics, vnic_list) {
 		nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
 		nfp_net_clean(nn);
 	}
@@ -457,7 +455,7 @@ nfp_net_pf_spawn_netdevs(struct nfp_pf *pf,
 err_vec_free:
 	kfree(pf->irq_entries);
 err_nn_free:
-	nfp_net_pf_free_netdevs(pf);
+	nfp_net_pf_free_vnics(pf);
 	return err;
 }
 
@@ -470,23 +468,23 @@ static void nfp_net_pci_remove_finish(struct nfp_pf *pf)
 
 	nfp_cpp_area_release_free(pf->rx_area);
 	nfp_cpp_area_release_free(pf->tx_area);
-	nfp_cpp_area_release_free(pf->ctrl_area);
+	nfp_cpp_area_release_free(pf->data_vnic_bar);
 }
 
-static void nfp_net_refresh_netdevs(struct work_struct *work)
+static void nfp_net_refresh_vnics(struct work_struct *work)
 {
 	struct nfp_pf *pf = container_of(work, struct nfp_pf,
 					 port_refresh_work);
 	struct nfp_eth_table *eth_table;
 	struct nfp_net *nn, *next;
 
-	mutex_lock(&pf->port_lock);
+	mutex_lock(&pf->lock);
 
 	/* Check for nfp_net_pci_remove() racing against us */
-	if (list_empty(&pf->ports))
+	if (list_empty(&pf->vnics))
 		goto out;
 
-	list_for_each_entry(nn, &pf->ports, port_list)
+	list_for_each_entry(nn, &pf->vnics, vnic_list)
 		nfp_net_link_changed_read_clear(nn);
 
 	eth_table = nfp_eth_read_ports(pf->cpp);
@@ -496,7 +494,7 @@ static void nfp_net_refresh_netdevs(struct work_struct *work)
 	}
 
 	rtnl_lock();
-	list_for_each_entry(nn, &pf->ports, port_list) {
+	list_for_each_entry(nn, &pf->vnics, vnic_list) {
 		if (!nn->eth_port)
 			continue;
 		nn->eth_port = nfp_net_find_port(eth_table,
@@ -507,7 +505,7 @@ static void nfp_net_refresh_netdevs(struct work_struct *work)
 	kfree(pf->eth_tbl);
 	pf->eth_tbl = eth_table;
 
-	list_for_each_entry_safe(nn, next, &pf->ports, port_list) {
+	list_for_each_entry_safe(nn, next, &pf->vnics, vnic_list) {
 		if (!nn->eth_port) {
 			nfp_warn(pf->cpp, "Warning: port not present after reconfig\n");
 			continue;
@@ -520,15 +518,15 @@ static void nfp_net_refresh_netdevs(struct work_struct *work)
 		nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
 		nfp_net_clean(nn);
 
-		list_del(&nn->port_list);
-		pf->num_netdevs--;
+		list_del(&nn->vnic_list);
+		pf->num_vnics--;
 		nfp_net_free(nn);
 	}
 
-	if (list_empty(&pf->ports))
+	if (list_empty(&pf->vnics))
 		nfp_net_pci_remove_finish(pf);
 out:
-	mutex_unlock(&pf->port_lock);
+	mutex_unlock(&pf->lock);
 }
 
 void nfp_net_refresh_port_table(struct nfp_net *nn)
@@ -576,8 +574,8 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
 	int stride;
 	int err;
 
-	INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_netdevs);
-	mutex_init(&pf->port_lock);
+	INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_vnics);
+	mutex_init(&pf->lock);
 
 	/* Verify that the board has completed initialization */
 	if (!nfp_is_ready(pf->cpp)) {
@@ -585,8 +583,8 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
 		return -EINVAL;
 	}
 
-	mutex_lock(&pf->port_lock);
-	pf->num_ports = nfp_net_pf_get_num_ports(pf);
+	mutex_lock(&pf->lock);
+	pf->max_data_vnics = nfp_net_pf_get_num_ports(pf);
 
 	ctrl_bar = nfp_net_pf_map_ctrl_bar(pf);
 	if (!ctrl_bar) {
@@ -661,12 +659,12 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
 
 	pf->ddir = nfp_net_debugfs_device_add(pf->pdev);
 
-	err = nfp_net_pf_spawn_netdevs(pf, ctrl_bar, tx_bar, rx_bar,
-				       stride, &fw_ver);
+	err = nfp_net_pf_spawn_vnics(pf, ctrl_bar, tx_bar, rx_bar,
+				     stride, &fw_ver);
 	if (err)
 		goto err_clean_ddir;
 
-	mutex_unlock(&pf->port_lock);
+	mutex_unlock(&pf->lock);
 
 	return 0;
 
@@ -676,9 +674,9 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
 err_unmap_tx:
 	nfp_cpp_area_release_free(pf->tx_area);
 err_ctrl_unmap:
-	nfp_cpp_area_release_free(pf->ctrl_area);
+	nfp_cpp_area_release_free(pf->data_vnic_bar);
 err_unlock:
-	mutex_unlock(&pf->port_lock);
+	mutex_unlock(&pf->lock);
 	return err;
 }
 
@@ -686,21 +684,21 @@ void nfp_net_pci_remove(struct nfp_pf *pf)
 {
 	struct nfp_net *nn;
 
-	mutex_lock(&pf->port_lock);
-	if (list_empty(&pf->ports))
+	mutex_lock(&pf->lock);
+	if (list_empty(&pf->vnics))
 		goto out;
 
-	list_for_each_entry(nn, &pf->ports, port_list) {
+	list_for_each_entry(nn, &pf->vnics, vnic_list) {
 		nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
 
 		nfp_net_clean(nn);
 	}
 
-	nfp_net_pf_free_netdevs(pf);
+	nfp_net_pf_free_vnics(pf);
 
 	nfp_net_pci_remove_finish(pf);
 out:
-	mutex_unlock(&pf->port_lock);
+	mutex_unlock(&pf->lock);
 
 	cancel_work_sync(&pf->port_refresh_work);
 }
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
index 856a76bdfc24..3f1c7f0f392e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
@@ -267,7 +267,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
 	nfp_netvf_get_mac_addr(nn);
 
 	num_irqs = nfp_net_irqs_alloc(pdev, vf->irq_entries,
-				      NFP_NET_MIN_PORT_IRQS,
+				      NFP_NET_MIN_VNIC_IRQS,
 				      NFP_NET_NON_Q_VECTORS +
 				      nn->dp.num_r_vecs);
 	if (!num_irqs) {
@@ -289,7 +289,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
 
 	nfp_net_info(nn);
 	vf->ddir = nfp_net_debugfs_device_add(pdev);
-	nfp_net_debugfs_port_add(nn, vf->ddir, 0);
+	nfp_net_debugfs_vnic_add(nn, vf->ddir, 0);
 
 	return 0;
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 02/13] nfp: make nfp_net alloc/init/cleanup/free not depend on netdevs
From: Jakub Kicinski @ 2017-05-19 22:01 UTC (permalink / raw)
  To: netdev; +Cc: kubakici, oss-drivers, Jakub Kicinski
In-Reply-To: <20170519220155.27857-1-jakub.kicinski@netronome.com>

struct nfp_net represents a vNIC, we will be moving away from the
requirement for every vNIC to have a netdev associated with it.
Remove "netdev" from some function names and prefer passing
struct nfp_net pointer as argument instead of struct net_device *.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/nfp_net.h       | 12 ++++----
 .../net/ethernet/netronome/nfp/nfp_net_common.c    | 35 ++++++++++------------
 drivers/net/ethernet/netronome/nfp/nfp_net_main.c  | 14 ++++-----
 .../net/ethernet/netronome/nfp/nfp_netvf_main.c    | 10 +++----
 4 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 7b9518cbe965..04609191ca88 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -807,11 +807,13 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver,
 			    void __iomem *ctrl_bar);
 
 struct nfp_net *
-nfp_net_netdev_alloc(struct pci_dev *pdev,
-		     unsigned int max_tx_rings, unsigned int max_rx_rings);
-void nfp_net_netdev_free(struct nfp_net *nn);
-int nfp_net_netdev_init(struct net_device *netdev);
-void nfp_net_netdev_clean(struct net_device *netdev);
+nfp_net_alloc(struct pci_dev *pdev,
+	      unsigned int max_tx_rings, unsigned int max_rx_rings);
+void nfp_net_free(struct nfp_net *nn);
+
+int nfp_net_init(struct nfp_net *nn);
+void nfp_net_clean(struct nfp_net *nn);
+
 void nfp_net_set_ethtool_ops(struct net_device *netdev);
 void nfp_net_info(struct nfp_net *nn);
 int nfp_net_reconfig(struct nfp_net *nn, u32 update);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index da83e17b8b20..b427c95c5acd 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -516,11 +516,10 @@ nfp_net_rx_ring_init(struct nfp_net_rx_ring *rx_ring,
 
 /**
  * nfp_net_vecs_init() - Assign IRQs and setup rvecs.
- * @netdev:   netdev structure
+ * @nn:		NFP Network structure
  */
-static void nfp_net_vecs_init(struct net_device *netdev)
+static void nfp_net_vecs_init(struct nfp_net *nn)
 {
-	struct nfp_net *nn = netdev_priv(netdev);
 	struct nfp_net_r_vector *r_vec;
 	int r;
 
@@ -3087,7 +3086,7 @@ void nfp_net_info(struct nfp_net *nn)
 }
 
 /**
- * nfp_net_netdev_alloc() - Allocate netdev and related structure
+ * nfp_net_alloc() - Allocate netdev and related structure
  * @pdev:         PCI device
  * @max_tx_rings: Maximum number of TX rings supported by device
  * @max_rx_rings: Maximum number of RX rings supported by device
@@ -3097,9 +3096,9 @@ void nfp_net_info(struct nfp_net *nn)
  *
  * Return: NFP Net device structure, or ERR_PTR on error.
  */
-struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
-				     unsigned int max_tx_rings,
-				     unsigned int max_rx_rings)
+struct nfp_net *nfp_net_alloc(struct pci_dev *pdev,
+			      unsigned int max_tx_rings,
+			      unsigned int max_rx_rings)
 {
 	struct net_device *netdev;
 	struct nfp_net *nn;
@@ -3144,10 +3143,10 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
 }
 
 /**
- * nfp_net_netdev_free() - Undo what @nfp_net_netdev_alloc() did
+ * nfp_net_free() - Undo what @nfp_net_alloc() did
  * @nn:      NFP Net device to reconfigure
  */
-void nfp_net_netdev_free(struct nfp_net *nn)
+void nfp_net_free(struct nfp_net *nn)
 {
 	free_netdev(nn->dp.netdev);
 }
@@ -3221,14 +3220,14 @@ static void nfp_net_irqmod_init(struct nfp_net *nn)
 }
 
 /**
- * nfp_net_netdev_init() - Initialise/finalise the netdev structure
- * @netdev:      netdev structure
+ * nfp_net_init() - Initialise/finalise the nfp_net structure
+ * @nn:		NFP Net device structure
  *
  * Return: 0 on success or negative errno on error.
  */
-int nfp_net_netdev_init(struct net_device *netdev)
+int nfp_net_init(struct nfp_net *nn)
 {
-	struct nfp_net *nn = netdev_priv(netdev);
+	struct net_device *netdev = nn->dp.netdev;
 	int err;
 
 	nn->dp.rx_dma_dir = DMA_FROM_DEVICE;
@@ -3367,19 +3366,17 @@ int nfp_net_netdev_init(struct net_device *netdev)
 	netif_carrier_off(netdev);
 
 	nfp_net_set_ethtool_ops(netdev);
-	nfp_net_vecs_init(netdev);
+	nfp_net_vecs_init(nn);
 
 	return register_netdev(netdev);
 }
 
 /**
- * nfp_net_netdev_clean() - Undo what nfp_net_netdev_init() did.
- * @netdev:      netdev structure
+ * nfp_net_clean() - Undo what nfp_net_init() did.
+ * @nn:		NFP Net device structure
  */
-void nfp_net_netdev_clean(struct net_device *netdev)
+void nfp_net_clean(struct nfp_net *nn)
 {
-	struct nfp_net *nn = netdev_priv(netdev);
-
 	unregister_netdev(nn->dp.netdev);
 
 	if (nn->dp.xdp_prog)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 16115973112c..55d916cb04fe 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -277,7 +277,7 @@ static void nfp_net_pf_free_netdevs(struct nfp_pf *pf)
 		list_del(&nn->port_list);
 		pf->num_netdevs--;
 
-		nfp_net_netdev_free(nn);
+		nfp_net_free(nn);
 	}
 }
 
@@ -294,7 +294,7 @@ nfp_net_pf_alloc_port_netdev(struct nfp_pf *pf, void __iomem *ctrl_bar,
 	n_rx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_RXRINGS);
 
 	/* Allocate and initialise the netdev */
-	nn = nfp_net_netdev_alloc(pf->pdev, n_tx_rings, n_rx_rings);
+	nn = nfp_net_alloc(pf->pdev, n_tx_rings, n_rx_rings);
 	if (IS_ERR(nn))
 		return nn;
 
@@ -326,7 +326,7 @@ nfp_net_pf_init_port_netdev(struct nfp_pf *pf, struct nfp_net *nn,
 	 */
 	nn->me_freq_mhz = 1200;
 
-	err = nfp_net_netdev_init(nn->dp.netdev);
+	err = nfp_net_init(nn);
 	if (err)
 		return err;
 
@@ -451,7 +451,7 @@ nfp_net_pf_spawn_netdevs(struct nfp_pf *pf,
 err_prev_deinit:
 	list_for_each_entry_continue_reverse(nn, &pf->ports, port_list) {
 		nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
-		nfp_net_netdev_clean(nn->dp.netdev);
+		nfp_net_clean(nn);
 	}
 	nfp_net_irqs_disable(pf->pdev);
 err_vec_free:
@@ -518,11 +518,11 @@ static void nfp_net_refresh_netdevs(struct work_struct *work)
 		nn_warn(nn, "Port config changed, unregistering. Reboot required before port will be operational again.\n");
 
 		nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
-		nfp_net_netdev_clean(nn->dp.netdev);
+		nfp_net_clean(nn);
 
 		list_del(&nn->port_list);
 		pf->num_netdevs--;
-		nfp_net_netdev_free(nn);
+		nfp_net_free(nn);
 	}
 
 	if (list_empty(&pf->ports))
@@ -693,7 +693,7 @@ void nfp_net_pci_remove(struct nfp_pf *pf)
 	list_for_each_entry(nn, &pf->ports, port_list) {
 		nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
 
-		nfp_net_netdev_clean(nn->dp.netdev);
+		nfp_net_clean(nn);
 	}
 
 	nfp_net_pf_free_netdevs(pf);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
index 86e61be6f35c..856a76bdfc24 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c
@@ -202,7 +202,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
 	rx_bar_off = NFP_PCIE_QUEUE(startq);
 
 	/* Allocate and initialise the netdev */
-	nn = nfp_net_netdev_alloc(pdev, max_tx_rings, max_rx_rings);
+	nn = nfp_net_alloc(pdev, max_tx_rings, max_rx_rings);
 	if (IS_ERR(nn)) {
 		err = PTR_ERR(nn);
 		goto err_ctrl_unmap;
@@ -283,7 +283,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
 	 */
 	nn->me_freq_mhz = 1200;
 
-	err = nfp_net_netdev_init(nn->dp.netdev);
+	err = nfp_net_init(nn);
 	if (err)
 		goto err_irqs_disable;
 
@@ -304,7 +304,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
 	else
 		iounmap(vf->q_bar);
 err_netdev_free:
-	nfp_net_netdev_free(nn);
+	nfp_net_free(nn);
 err_ctrl_unmap:
 	iounmap(ctrl_bar);
 err_pci_regions:
@@ -328,7 +328,7 @@ static void nfp_netvf_pci_remove(struct pci_dev *pdev)
 	nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
 	nfp_net_debugfs_dir_clean(&vf->ddir);
 
-	nfp_net_netdev_clean(nn->dp.netdev);
+	nfp_net_clean(nn);
 
 	nfp_net_irqs_disable(pdev);
 
@@ -340,7 +340,7 @@ static void nfp_netvf_pci_remove(struct pci_dev *pdev)
 	}
 	iounmap(nn->dp.ctrl_bar);
 
-	nfp_net_netdev_free(nn);
+	nfp_net_free(nn);
 
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 00/13] nfp: introduce nfp_port and nfp_app
From: Jakub Kicinski @ 2017-05-19 22:01 UTC (permalink / raw)
  To: netdev; +Cc: kubakici, oss-drivers, Jakub Kicinski

Hi!

This series builds foundation for upcoming development.  So far the nfp
driver was focused on delivering basic NIC-like functionality.  We want
to switch gears a bit going forward and support more advanced applications.

First few patches are naming clean ups and reshuffling.  The two main 
structures this series adds are nfp_port and nfp_app.  

nfp_port represents a device port, where port can mean external port,
VF or PF.  For now only external port/MAC/PHY port is added.  nfp_port
is supposed to make it easy to share ethtool and devlink code regardless
of netdev type (full vNIC vs representors).

nfp_app is an abstraction which should allow easier development of new
applications.  So far we have relied fully on port capabilities to detect
which offloads and features are available.  The usual development model
for NFP is that people start with one of our "core NIC" FW apps (C one, 
or a macro assembler one) and build advanced functionality on top of that.
Therefore basic netdev code is shared, but the higher-level logic is 
usually more project specific.  The higher-level logic is also per-adapter
rather than per-port, so creating per-adapter control entity makes sense.
Hopefully the separation of lower-level netdev code and application logic
will help us limit interdependencies and accelerate parallel projects
(e.g. TC flower offloads vs eBPF offload).


Jakub Kicinski (12):
  nfp: make nfp_net alloc/init/cleanup/free not depend on netdevs
  nfp: rename netdev/port to vNIC
  nfp: add nfp_net_pf_free_vnic() function
  nfp: introduce very minimal nfp_app
  nfp: disallow mixing vNICs with and without NSP port entry
  nfp: introduce nfp_port
  nfp: update port state in place
  nfp: move refresh tracking into the port structure
  nfp: provide linking on port structures
  nfp: mark port state as stale after reconfig
  nfp: mark port state as stale if update failed
  nfp: refresh port state before reporting autonegotiation

Simon Horman (1):
  nfp: add nfp_cppcore_pcie_unit() helper

 drivers/net/ethernet/netronome/nfp/Makefile        |   4 +-
 drivers/net/ethernet/netronome/nfp/nfp_app.c       |  80 +++++
 drivers/net/ethernet/netronome/nfp/nfp_app.h       |  48 +++
 drivers/net/ethernet/netronome/nfp/nfp_main.c      |   1 +
 drivers/net/ethernet/netronome/nfp/nfp_main.h      |  28 +-
 drivers/net/ethernet/netronome/nfp/nfp_net.h       |  37 +--
 .../net/ethernet/netronome/nfp/nfp_net_common.c    |  79 ++---
 .../net/ethernet/netronome/nfp/nfp_net_debugfs.c   |   4 +-
 .../net/ethernet/netronome/nfp/nfp_net_ethtool.c   |  63 ++--
 drivers/net/ethernet/netronome/nfp/nfp_net_main.c  | 346 ++++++++++++---------
 .../net/ethernet/netronome/nfp/nfp_netvf_main.c    |  14 +-
 drivers/net/ethernet/netronome/nfp/nfp_port.c      | 123 ++++++++
 drivers/net/ethernet/netronome/nfp/nfp_port.h      | 104 +++++++
 .../net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h   |  11 +
 14 files changed, 677 insertions(+), 265 deletions(-)
 create mode 100644 drivers/net/ethernet/netronome/nfp/nfp_app.c
 create mode 100644 drivers/net/ethernet/netronome/nfp/nfp_app.h
 create mode 100644 drivers/net/ethernet/netronome/nfp/nfp_port.c
 create mode 100644 drivers/net/ethernet/netronome/nfp/nfp_port.h

-- 
2.11.0

^ permalink raw reply

* [PATCH net-next 01/13] nfp: add nfp_cppcore_pcie_unit() helper
From: Jakub Kicinski @ 2017-05-19 22:01 UTC (permalink / raw)
  To: netdev; +Cc: kubakici, oss-drivers, Simon Horman
In-Reply-To: <20170519220155.27857-1-jakub.kicinski@netronome.com>

From: Simon Horman <simon.horman@netronome.com>

Add nfp_cppcore_pcie_unit() helper to retrieve the PCIE unit of a CPP
handle and use the new helper as appropriate.

Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/nfp_net_main.c    | 16 ++++------------
 drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h | 11 +++++++++++
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 8cb87cbe1120..16115973112c 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -190,15 +190,11 @@ nfp_net_find_port(struct nfp_eth_table *eth_tbl, unsigned int id)
 static unsigned int nfp_net_pf_get_num_ports(struct nfp_pf *pf)
 {
 	char name[256];
-	u16 interface;
-	int pcie_pf;
 	int err = 0;
 	u64 val;
 
-	interface = nfp_cpp_interface(pf->cpp);
-	pcie_pf = NFP_CPP_INTERFACE_UNIT_of(interface);
-
-	snprintf(name, sizeof(name), "nfd_cfg_pf%d_num_ports", pcie_pf);
+	snprintf(name, sizeof(name), "nfd_cfg_pf%u_num_ports",
+		 nfp_cppcore_pcie_unit(pf->cpp));
 
 	val = nfp_rtsym_read_le(pf->cpp, name, &err);
 	/* Default to one port */
@@ -241,13 +237,9 @@ static u8 __iomem *nfp_net_pf_map_ctrl_bar(struct nfp_pf *pf)
 	const struct nfp_rtsym *ctrl_sym;
 	u8 __iomem *ctrl_bar;
 	char pf_symbol[256];
-	u16 interface;
-	int pcie_pf;
-
-	interface = nfp_cpp_interface(pf->cpp);
-	pcie_pf = NFP_CPP_INTERFACE_UNIT_of(interface);
 
-	snprintf(pf_symbol, sizeof(pf_symbol), "_pf%d_net_bar0", pcie_pf);
+	snprintf(pf_symbol, sizeof(pf_symbol), "_pf%u_net_bar0",
+		 nfp_cppcore_pcie_unit(pf->cpp));
 
 	ctrl_sym = nfp_rtsym_lookup(pf->cpp, pf_symbol);
 	if (!ctrl_sym) {
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
index edecc0a27485..154b0b594184 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
@@ -289,6 +289,17 @@ int nfp_cpp_mutex_lock(struct nfp_cpp_mutex *mutex);
 int nfp_cpp_mutex_unlock(struct nfp_cpp_mutex *mutex);
 int nfp_cpp_mutex_trylock(struct nfp_cpp_mutex *mutex);
 
+/**
+ * nfp_cppcore_pcie_unit() - Get PCI Unit of a CPP handle
+ * @cpp:	CPP handle
+ *
+ * Return: PCI unit for the NFP CPP handle
+ */
+static inline u8 nfp_cppcore_pcie_unit(struct nfp_cpp *cpp)
+{
+	return NFP_CPP_INTERFACE_UNIT_of(nfp_cpp_interface(cpp));
+}
+
 struct nfp_cpp_explicit;
 
 struct nfp_cpp_explicit_command {
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH v2] hdlcdrv: fix divide error bug if bitrate is 0
From: David Miller @ 2017-05-19 21:41 UTC (permalink / raw)
  To: firogm; +Cc: t.sailer, wharms, andreyknvl, linux-hams, gregkh, netdev
In-Reply-To: <20170519132146.744-1-firogm@gmail.com>

From: Firo Yang <firogm@gmail.com>
Date: Fri, 19 May 2017 21:21:46 +0800

> @@ -576,6 +576,10 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
>  	case HDLCDRVCTL_CALIBRATE:
>  		if(!capable(CAP_SYS_RAWIO))
>  			return -EPERM;
> +		if (!netif_running(dev))
> +			return -ENODEV;
> +		if (!(s->par.bitrate > 0))
> +			return -EINVAL;

This test is so un-canonical and convoluted.

Please use something more straightforward.  I really think Alan
Cox's patch handled this more cleanly.  Make the test something
like "if (x <= 0) return -EINVAL;".

I also am not convinced about the netif_running() test and at
best it is a separate change from this divide by zero bug fix
so belongs in a separate patch.

Thank you.

^ permalink raw reply

* Re: [PATCH v2 1/3] bpf: Use 1<<16 as ceiling for immediate alignment in verifier.
From: Alexei Starovoitov @ 2017-05-19 21:37 UTC (permalink / raw)
  To: David Miller, ecree; +Cc: daniel, alexei.starovoitov, netdev
In-Reply-To: <20170519.164154.368589666756458942.davem@davemloft.net>

On 5/19/17 1:41 PM, David Miller wrote:
> From: Edward Cree <ecree@solarflare.com>
> Date: Fri, 19 May 2017 18:17:42 +0100
>
>> One question: is there a way to build the verifier as userland code
>>  (or at least as a module), or will I have to reboot every time I
>>  want to test a change?
>
> There currently is no such machanism, you will have to reboot every
> time.
>
> I have considered working on making the code buildable outside of the
> kernel.  It shouldn't be too hard.

it's not hard.
We did it twice and both times abandoned.
First time to have 'user space verifier' to check programs before
loading and second time for fuzzing via llvm.
Abandoned since it diverges very quickly from kernel.

^ permalink raw reply

* [PATCH net] ipv6: fix out of bound writes in __ip6_append_data()
From: Eric Dumazet @ 2017-05-19 21:17 UTC (permalink / raw)
  To: Andrey Konovalov; +Cc: Eric Dumazet, idaifish, David S. Miller, netdev
In-Reply-To: <CAAeHK+xGCjM8oDCZcNXbaZZNqenREi4DUgHM5=Ab7GKrVEmO4Q@mail.gmail.com>

From: Eric Dumazet <edumazet@google.com>

Andrey Konovalov and idaifish@gmail.com reported crashes caused by
one skb shared_info being overwritten from __ip6_append_data()

Andrey program lead to following state :

copy -4200 datalen 2000 fraglen 2040 
maxfraglen 2040 alloclen 2048 transhdrlen 0 offset 0 fraggap 6200

The skb_copy_and_csum_bits(skb_prev, maxfraglen, data + transhdrlen,
fraggap, 0); is overwriting skb->head and skb_shared_info

Since we apparently detect this rare condition too late, move the
code earlier to even avoid allocating skb and risking crashes.

Once again, many thanks to Andrey and syzkaller team.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Tested-by: Andrey Konovalov <andreyknvl@google.com>
Reported-by: <idaifish@gmail.com>
---
 net/ipv6/ip6_output.c |   15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index d4a31becbd25dda895d7391e1e65c2de237bf2a3..bf8a58a1c32d83a9605844075da5815be23a6bf1 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1466,6 +1466,11 @@ static int __ip6_append_data(struct sock *sk,
 			 */
 			alloclen += sizeof(struct frag_hdr);
 
+			copy = datalen - transhdrlen - fraggap;
+			if (copy < 0) {
+				err = -EINVAL;
+				goto error;
+			}
 			if (transhdrlen) {
 				skb = sock_alloc_send_skb(sk,
 						alloclen + hh_len,
@@ -1515,13 +1520,9 @@ static int __ip6_append_data(struct sock *sk,
 				data += fraggap;
 				pskb_trim_unique(skb_prev, maxfraglen);
 			}
-			copy = datalen - transhdrlen - fraggap;
-
-			if (copy < 0) {
-				err = -EINVAL;
-				kfree_skb(skb);
-				goto error;
-			} else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
+			if (copy > 0 &&
+			    getfrag(from, data + transhdrlen, offset,
+				    copy, fraggap, skb) < 0) {
 				err = -EFAULT;
 				kfree_skb(skb);
 				goto error;

^ permalink raw reply related

* Re: [PATCH net] bonding: fix accounting of active ports in 3ad
From: David Miller @ 2017-05-19 21:14 UTC (permalink / raw)
  To: jarod; +Cc: linux-kernel, j.vosburgh, vfalico, andy, netdev
In-Reply-To: <20170517151144.57865-1-jarod@redhat.com>

From: Jarod Wilson <jarod@redhat.com>
Date: Wed, 17 May 2017 11:11:44 -0400

> As of 7bb11dc9f59d and 0622cab0341c, bond slaves in a 3ad bond are not
> removed from the aggregator when they are down, and the active slave count
> is NOT equal to number of ports in the aggregator, but rather the number
> of ports in the aggregator that are still enabled.
 ...
> Remedy it by using the same logic introduced in
> 7bb11dc9f59d in __bond_3ad_get_active_agg_info(), so sysfs, procfs and
  ^^^^^^^^^^^^
> netlink all report the number of active ports.

I think you mean to reference commit 0622cab0341c here not 7bb11dc9f59d.

^ permalink raw reply

* RE: [PATCH v2] e1000e: Don't return uninitialized stats
From: Brown, Aaron F @ 2017-05-19 21:12 UTC (permalink / raw)
  To: Kirsher, Jeffrey T, David Miller, bpoirier@suse.com
  Cc: s.priebe@profihost.ag, intel-wired-lan@lists.osuosl.org,
	netdev@vger.kernel.org, pmenzel@molgen.mpg.de, Neftin, Sasha,
	stephen@networkplumber.org
In-Reply-To: <1495181811.2376.0.camel@intel.com>

> From: Kirsher, Jeffrey T
> Sent: Friday, May 19, 2017 1:17 AM
> To: David Miller <davem@davemloft.net>; bpoirier@suse.com
> Cc: s.priebe@profihost.ag; intel-wired-lan@lists.osuosl.org;
> netdev@vger.kernel.org; pmenzel@molgen.mpg.de; Neftin, Sasha
> <sasha.neftin@intel.com>; Brown, Aaron F <aaron.f.brown@intel.com>;
> stephen@networkplumber.org
> Subject: Re: [PATCH v2] e1000e: Don't return uninitialized stats
> 
> On Thu, 2017-05-18 at 10:46 -0400, David Miller wrote:
> > From: Benjamin Poirier <bpoirier@suse.com>
> > Date: Wed, 17 May 2017 16:24:13 -0400
> >
> > > Some statistics passed to ethtool are garbage because
> > > e1000e_get_stats64()
> > > doesn't write them, for example: tx_heartbeat_errors. This leaks kernel
> > > memory to userspace and confuses users.
> > >
> > > Do like ixgbe and use dev_get_stats() which first zeroes out
> > > rtnl_link_stats64.
> > >
> > > Fixes: 5944701df90d ("net: remove useless memset's in drivers
> > > get_stats64")
> > > Reported-by: Stefan Priebe <s.priebe@profihost.ag>
> > > Signed-off-by: Benjamin Poirier <bpoirier@suse.com>

Tested-by: Aaron Brown <aaron.f.brown@intel.com>

^ permalink raw reply

* [PATCH net-next 18/20] net: dsa: add FDB notifier
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Add two new DSA_NOTIFIER_FDB_ADD and DSA_NOTIFIER_FDB_DEL events to
notify not only a single switch, but all switches of a the fabric when
an FDB entry is added or removed.

For the moment, keep the current behavior and ignore other switches.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h | 10 ++++++++++
 net/dsa/port.c     | 31 ++++++++++++++-----------------
 net/dsa/switch.c   | 43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index becaf8a61b13..6a7d0d7d0489 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -20,6 +20,8 @@ enum {
 	DSA_NOTIFIER_AGEING_TIME,
 	DSA_NOTIFIER_BRIDGE_JOIN,
 	DSA_NOTIFIER_BRIDGE_LEAVE,
+	DSA_NOTIFIER_FDB_ADD,
+	DSA_NOTIFIER_FDB_DEL,
 };
 
 /* DSA_NOTIFIER_AGEING_TIME */
@@ -36,6 +38,14 @@ struct dsa_notifier_bridge_info {
 	int port;
 };
 
+/* DSA_NOTIFIER_FDB_* */
+struct dsa_notifier_fdb_info {
+	const struct switchdev_obj_port_fdb *fdb;
+	struct switchdev_trans *trans;
+	int sw_index;
+	int port;
+};
+
 struct dsa_device_ops {
 	struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
 	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 59328a35394d..ed88d8381642 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -151,29 +151,26 @@ int dsa_port_fdb_add(struct dsa_port *dp,
 		     const struct switchdev_obj_port_fdb *fdb,
 		     struct switchdev_trans *trans)
 {
-	struct dsa_switch *ds = dp->ds;
-
-	if (switchdev_trans_ph_prepare(trans)) {
-		if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add)
-			return -EOPNOTSUPP;
-
-		return ds->ops->port_fdb_prepare(ds, dp->index, fdb, trans);
-	}
-
-	ds->ops->port_fdb_add(ds, dp->index, fdb, trans);
-
-	return 0;
+	struct dsa_notifier_fdb_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.trans = trans,
+		.fdb = fdb,
+	};
+
+	return dsa_port_notify(dp, DSA_NOTIFIER_FDB_ADD, &info);
 }
 
 int dsa_port_fdb_del(struct dsa_port *dp,
 		     const struct switchdev_obj_port_fdb *fdb)
 {
-	struct dsa_switch *ds = dp->ds;
+	struct dsa_notifier_fdb_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.fdb = fdb,
+	};
 
-	if (ds->ops->port_fdb_del)
-		return -EOPNOTSUPP;
-
-	return ds->ops->port_fdb_del(ds, dp->index, fdb);
+	return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info);
 }
 
 int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb,
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 540770ecc8b0..e71cc860d32c 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -84,6 +84,43 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
 	return 0;
 }
 
+static int dsa_switch_fdb_add(struct dsa_switch *ds,
+			      struct dsa_notifier_fdb_info *info)
+{
+	const struct switchdev_obj_port_fdb *fdb = info->fdb;
+	struct switchdev_trans *trans = info->trans;
+
+	/* Do not care yet about other switch chips of the fabric */
+	if (ds->index != info->sw_index)
+		return 0;
+
+	if (switchdev_trans_ph_prepare(trans)) {
+		if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add)
+			return -EOPNOTSUPP;
+
+		return ds->ops->port_fdb_prepare(ds, info->port, fdb, trans);
+	}
+
+	ds->ops->port_fdb_add(ds, info->port, fdb, trans);
+
+	return 0;
+}
+
+static int dsa_switch_fdb_del(struct dsa_switch *ds,
+			      struct dsa_notifier_fdb_info *info)
+{
+	const struct switchdev_obj_port_fdb *fdb = info->fdb;
+
+	/* Do not care yet about other switch chips of the fabric */
+	if (ds->index != info->sw_index)
+		return 0;
+
+	if (!ds->ops->port_fdb_del)
+		return -EOPNOTSUPP;
+
+	return ds->ops->port_fdb_del(ds, info->port, fdb);
+}
+
 static int dsa_switch_event(struct notifier_block *nb,
 			    unsigned long event, void *info)
 {
@@ -100,6 +137,12 @@ static int dsa_switch_event(struct notifier_block *nb,
 	case DSA_NOTIFIER_BRIDGE_LEAVE:
 		err = dsa_switch_bridge_leave(ds, info);
 		break;
+	case DSA_NOTIFIER_FDB_ADD:
+		err = dsa_switch_fdb_add(ds, info);
+		break;
+	case DSA_NOTIFIER_FDB_DEL:
+		err = dsa_switch_fdb_del(ds, info);
+		break;
 	default:
 		err = -EOPNOTSUPP;
 		break;
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 12/20] net: dsa: move ageing time setter
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Move the DSA port code which sets a port ageing time in port.c, where it
belongs.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h |  2 ++
 net/dsa/port.c     | 40 ++++++++++++++++++++++++++++++++++++++++
 net/dsa/slave.c    | 40 ----------------------------------------
 3 files changed, 42 insertions(+), 40 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index c145223247c5..b0f9837bf5ed 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -68,6 +68,8 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
 void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
 int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
 			    struct switchdev_trans *trans);
+int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
+			 struct switchdev_trans *trans);
 
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
diff --git a/net/dsa/port.c b/net/dsa/port.c
index c9f95aaf25f1..3382fdc07a11 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -127,3 +127,43 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
 
 	return 0;
 }
+
+static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds,
+					    unsigned int ageing_time)
+{
+	int i;
+
+	for (i = 0; i < ds->num_ports; ++i) {
+		struct dsa_port *dp = &ds->ports[i];
+
+		if (dp->ageing_time && dp->ageing_time < ageing_time)
+			ageing_time = dp->ageing_time;
+	}
+
+	return ageing_time;
+}
+
+int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
+			 struct switchdev_trans *trans)
+{
+	unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock);
+	unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies);
+	struct dsa_switch *ds = dp->ds;
+
+	if (switchdev_trans_ph_prepare(trans)) {
+		if (ds->ageing_time_min && ageing_time < ds->ageing_time_min)
+			return -ERANGE;
+		if (ds->ageing_time_max && ageing_time > ds->ageing_time_max)
+			return -ERANGE;
+		return 0;
+	}
+
+	/* Keep the fastest ageing time in case of multiple bridges */
+	dp->ageing_time = ageing_time;
+	ageing_time = dsa_fastest_ageing_time(ds, ageing_time);
+
+	if (ds->ops->set_ageing_time)
+		return ds->ops->set_ageing_time(ds, ageing_time);
+
+	return 0;
+}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 32e7e78313ba..1b0f396c4314 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -338,46 +338,6 @@ static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	return -EOPNOTSUPP;
 }
 
-static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds,
-					    unsigned int ageing_time)
-{
-	int i;
-
-	for (i = 0; i < ds->num_ports; ++i) {
-		struct dsa_port *dp = &ds->ports[i];
-
-		if (dp->ageing_time && dp->ageing_time < ageing_time)
-			ageing_time = dp->ageing_time;
-	}
-
-	return ageing_time;
-}
-
-static int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
-				struct switchdev_trans *trans)
-{
-	unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock);
-	unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies);
-	struct dsa_switch *ds = dp->ds;
-
-	if (switchdev_trans_ph_prepare(trans)) {
-		if (ds->ageing_time_min && ageing_time < ds->ageing_time_min)
-			return -ERANGE;
-		if (ds->ageing_time_max && ageing_time > ds->ageing_time_max)
-			return -ERANGE;
-		return 0;
-	}
-
-	/* Keep the fastest ageing time in case of multiple bridges */
-	dp->ageing_time = ageing_time;
-	ageing_time = dsa_fastest_ageing_time(ds, ageing_time);
-
-	if (ds->ops->set_ageing_time)
-		return ds->ops->set_ageing_time(ds, ageing_time);
-
-	return 0;
-}
-
 static int dsa_slave_port_attr_set(struct net_device *dev,
 				   const struct switchdev_attr *attr,
 				   struct switchdev_trans *trans)
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 00/20] net: dsa: distribute switch events
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot

DSA is by nature the support for a switch fabric, which can be composed
of a single, or multiple interconnected Ethernet switch chips.

The current DSA core behavior is to identify the slave port targeted by
a request (e.g. adding a VLAN entry), and program the switch chip to
which it belongs accordingly.

This is problematic in a multi-chip environment, since all chips of a
fabric must be aware of most configuration changes. Here are some
concrete examples in a 3-chip environment:

         [CPU].................... (mdio)
    (eth0) |   :       :          :
          _|_____    _______    _______
         [__sw0__]--[__sw1__]--[__sw2__]
          |  |  |    |  |  |    |  |  |
          v  v  v    v  v  v    v  v  v
          p1 p2 p3   p4 p5 p6   p7 p8 p9

If you add a VLAN entry on p7, sw2 gets programmed, but frames won't
reach the CPU interface in a VLAN filtered setup. sw0 and sw1 also need
to be programmed. The same problem comes with MAC addresses (FDB, MDB),
or ageing time changes for instance.

This patch series uses the notification chain introduced for bridging,
to notify not only bridge, but switchdev attributes and objects events
to all switch chips of the fabric.

An ugly debug message printing the ignored event and switch info in the
code handling the switch VLAN events would give us:

    # bridge vlan add dev p7 vid 42
    sw0: ignoring DSA_NOTIFIER_VLAN_ADD for sw2 (prepare phase)
    sw1: ignoring DSA_NOTIFIER_VLAN_ADD for sw2 (prepare phase)
    sw0: ignoring DSA_NOTIFIER_VLAN_ADD for sw2 (commit phase)
    sw1: ignoring DSA_NOTIFIER_VLAN_ADD for sw2 (commit phase)

To achieve that, patches 1-8 change the scope of the bridge and
switchdev callbacks from the DSA slave device to the generic DSA port,
so that the port-wide API can be used later for switch ports not exposed
to userspace, such as CPU and DSA links.

Patches 9-15 move the DSA port specific functions in a new port.c file.

Patches 16-20 introduce new events to notify the fabric about switchdev
attributes and objects manipulation.

This patch series only adds the plumbing to support a distributed
configuration, but for the moment, each switch chip ignores events from
other chips of the fabric, to keep the current behavior.

The next patch series will add support for cross-chip configuration of
bridge ageing time, VLAN and MAC address databases operations, etc.


Vivien Didelot (20):
  net: dsa: change scope of STP state setter
  net: dsa: change scope of notifier call chain
  net: dsa: change scope of bridging code
  net: dsa: change scope of FDB handlers
  net: dsa: change scope of MDB handlers
  net: dsa: change scope of VLAN handlers
  net: dsa: change scope of VLAN filtering setter
  net: dsa: change scope of ageing time setter
  net: dsa: move port state setters
  net: dsa: move bridging routines
  net: dsa: move VLAN filtering setter
  net: dsa: move ageing time setter
  net: dsa: move FDB handlers
  net: dsa: move MDB handlers
  net: dsa: move VLAN handlers
  net: dsa: move notifier info to private header
  net: dsa: add notifier for ageing time
  net: dsa: add FDB notifier
  net: dsa: add MDB notifier
  net: dsa: add VLAN notifier

 include/net/dsa.h  |  10 --
 net/dsa/Makefile   |   2 +-
 net/dsa/dsa_priv.h |  83 +++++++++++++
 net/dsa/port.c     | 260 +++++++++++++++++++++++++++++++++++++++
 net/dsa/slave.c    | 354 +++++------------------------------------------------
 net/dsa/switch.c   | 175 ++++++++++++++++++++++++++
 6 files changed, 547 insertions(+), 337 deletions(-)
 create mode 100644 net/dsa/port.c

-- 
2.13.0

^ permalink raw reply

* [PATCH net-next 02/20] net: dsa: change scope of notifier call chain
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Change the scope of the fabric notification helper from the DSA slave to
the DSA port, since this is a DSA layer specific notion, that can be
used by non-slave ports (CPU and DSA).

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/slave.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 403d1dfe7f50..371f6d267917 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -27,10 +27,9 @@
 
 static bool dsa_slave_dev_check(struct net_device *dev);
 
-static int dsa_slave_notify(struct net_device *dev, unsigned long e, void *v)
+static int dsa_port_notify(struct dsa_port *dp, unsigned long e, void *v)
 {
-	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct raw_notifier_head *nh = &p->dp->ds->dst->nh;
+	struct raw_notifier_head *nh = &dp->ds->dst->nh;
 	int err;
 
 	err = raw_notifier_call_chain(nh, e, v);
@@ -589,7 +588,7 @@ static int dsa_slave_bridge_port_join(struct net_device *dev,
 	 */
 	p->dp->bridge_dev = br;
 
-	err = dsa_slave_notify(dev, DSA_NOTIFIER_BRIDGE_JOIN, &info);
+	err = dsa_port_notify(p->dp, DSA_NOTIFIER_BRIDGE_JOIN, &info);
 
 	/* The bridging is rolled back on error */
 	if (err)
@@ -614,7 +613,7 @@ static void dsa_slave_bridge_port_leave(struct net_device *dev,
 	 */
 	p->dp->bridge_dev = NULL;
 
-	err = dsa_slave_notify(dev, DSA_NOTIFIER_BRIDGE_LEAVE, &info);
+	err = dsa_port_notify(p->dp, DSA_NOTIFIER_BRIDGE_LEAVE, &info);
 	if (err)
 		netdev_err(dev, "failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
 
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 20/20] net: dsa: add VLAN notifier
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Add two new DSA_NOTIFIER_VLAN_ADD and DSA_NOTIFIER_VLAN_DEL events to
notify not only a single switch, but all switches of a the fabric when
an VLAN entry is added or removed.

For the moment, keep the current behavior and ignore other switches.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h | 10 ++++++++++
 net/dsa/port.c     | 31 ++++++++++++++-----------------
 net/dsa/switch.c   | 43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 2b60293b325c..1d52f9051d0e 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -24,6 +24,8 @@ enum {
 	DSA_NOTIFIER_FDB_DEL,
 	DSA_NOTIFIER_MDB_ADD,
 	DSA_NOTIFIER_MDB_DEL,
+	DSA_NOTIFIER_VLAN_ADD,
+	DSA_NOTIFIER_VLAN_DEL,
 };
 
 /* DSA_NOTIFIER_AGEING_TIME */
@@ -56,6 +58,14 @@ struct dsa_notifier_mdb_info {
 	int port;
 };
 
+/* DSA_NOTIFIER_VLAN_* */
+struct dsa_notifier_vlan_info {
+	const struct switchdev_obj_port_vlan *vlan;
+	struct switchdev_trans *trans;
+	int sw_index;
+	int port;
+};
+
 struct dsa_device_ops {
 	struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
 	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index c7c4920e7bc9..c88c0cec8454 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -225,29 +225,26 @@ int dsa_port_vlan_add(struct dsa_port *dp,
 		      const struct switchdev_obj_port_vlan *vlan,
 		      struct switchdev_trans *trans)
 {
-	struct dsa_switch *ds = dp->ds;
-
-	if (switchdev_trans_ph_prepare(trans)) {
-		if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
-			return -EOPNOTSUPP;
-
-		return ds->ops->port_vlan_prepare(ds, dp->index, vlan, trans);
-	}
-
-	ds->ops->port_vlan_add(ds, dp->index, vlan, trans);
-
-	return 0;
+	struct dsa_notifier_vlan_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.trans = trans,
+		.vlan = vlan,
+	};
+
+	return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
 }
 
 int dsa_port_vlan_del(struct dsa_port *dp,
 		      const struct switchdev_obj_port_vlan *vlan)
 {
-	struct dsa_switch *ds = dp->ds;
+	struct dsa_notifier_vlan_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.vlan = vlan,
+	};
 
-	if (!ds->ops->port_vlan_del)
-		return -EOPNOTSUPP;
-
-	return ds->ops->port_vlan_del(ds, dp->index, vlan);
+	return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
 }
 
 int dsa_port_vlan_dump(struct dsa_port *dp,
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index b7e8e45869fc..c1e4b2d5a3ae 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -158,6 +158,43 @@ static int dsa_switch_mdb_del(struct dsa_switch *ds,
 	return ds->ops->port_mdb_del(ds, info->port, mdb);
 }
 
+static int dsa_switch_vlan_add(struct dsa_switch *ds,
+			       struct dsa_notifier_vlan_info *info)
+{
+	const struct switchdev_obj_port_vlan *vlan = info->vlan;
+	struct switchdev_trans *trans = info->trans;
+
+	/* Do not care yet about other switch chips of the fabric */
+	if (ds->index != info->sw_index)
+		return 0;
+
+	if (switchdev_trans_ph_prepare(trans)) {
+		if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
+			return -EOPNOTSUPP;
+
+		return ds->ops->port_vlan_prepare(ds, info->port, vlan, trans);
+	}
+
+	ds->ops->port_vlan_add(ds, info->port, vlan, trans);
+
+	return 0;
+}
+
+static int dsa_switch_vlan_del(struct dsa_switch *ds,
+			       struct dsa_notifier_vlan_info *info)
+{
+	const struct switchdev_obj_port_vlan *vlan = info->vlan;
+
+	/* Do not care yet about other switch chips of the fabric */
+	if (ds->index != info->sw_index)
+		return 0;
+
+	if (!ds->ops->port_vlan_del)
+		return -EOPNOTSUPP;
+
+	return ds->ops->port_vlan_del(ds, info->port, vlan);
+}
+
 static int dsa_switch_event(struct notifier_block *nb,
 			    unsigned long event, void *info)
 {
@@ -186,6 +223,12 @@ static int dsa_switch_event(struct notifier_block *nb,
 	case DSA_NOTIFIER_MDB_DEL:
 		err = dsa_switch_mdb_del(ds, info);
 		break;
+	case DSA_NOTIFIER_VLAN_ADD:
+		err = dsa_switch_vlan_add(ds, info);
+		break;
+	case DSA_NOTIFIER_VLAN_DEL:
+		err = dsa_switch_vlan_del(ds, info);
+		break;
 	default:
 		err = -EOPNOTSUPP;
 		break;
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 19/20] net: dsa: add MDB notifier
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Add two new DSA_NOTIFIER_MDB_ADD and DSA_NOTIFIER_MDB_DEL events to
notify not only a single switch, but all switches of a the fabric when
an MDB entry is added or removed.

For the moment, keep the current behavior and ignore other switches.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h | 10 ++++++++++
 net/dsa/port.c     | 31 ++++++++++++++-----------------
 net/dsa/switch.c   | 43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 6a7d0d7d0489..2b60293b325c 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -22,6 +22,8 @@ enum {
 	DSA_NOTIFIER_BRIDGE_LEAVE,
 	DSA_NOTIFIER_FDB_ADD,
 	DSA_NOTIFIER_FDB_DEL,
+	DSA_NOTIFIER_MDB_ADD,
+	DSA_NOTIFIER_MDB_DEL,
 };
 
 /* DSA_NOTIFIER_AGEING_TIME */
@@ -46,6 +48,14 @@ struct dsa_notifier_fdb_info {
 	int port;
 };
 
+/* DSA_NOTIFIER_MDB_* */
+struct dsa_notifier_mdb_info {
+	const struct switchdev_obj_port_mdb *mdb;
+	struct switchdev_trans *trans;
+	int sw_index;
+	int port;
+};
+
 struct dsa_device_ops {
 	struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
 	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index ed88d8381642..c7c4920e7bc9 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -188,29 +188,26 @@ int dsa_port_mdb_add(struct dsa_port *dp,
 		     const struct switchdev_obj_port_mdb *mdb,
 		     struct switchdev_trans *trans)
 {
-	struct dsa_switch *ds = dp->ds;
-
-	if (switchdev_trans_ph_prepare(trans)) {
-		if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add)
-			return -EOPNOTSUPP;
-
-		return ds->ops->port_mdb_prepare(ds, dp->index, mdb, trans);
-	}
-
-	ds->ops->port_mdb_add(ds, dp->index, mdb, trans);
-
-	return 0;
+	struct dsa_notifier_mdb_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.trans = trans,
+		.mdb = mdb,
+	};
+
+	return dsa_port_notify(dp, DSA_NOTIFIER_MDB_ADD, &info);
 }
 
 int dsa_port_mdb_del(struct dsa_port *dp,
 		     const struct switchdev_obj_port_mdb *mdb)
 {
-	struct dsa_switch *ds = dp->ds;
+	struct dsa_notifier_mdb_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.mdb = mdb,
+	};
 
-	if (ds->ops->port_mdb_del)
-		return ds->ops->port_mdb_del(ds, dp->index, mdb);
-
-	return -EOPNOTSUPP;
+	return dsa_port_notify(dp, DSA_NOTIFIER_MDB_DEL, &info);
 }
 
 int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb,
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index e71cc860d32c..b7e8e45869fc 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -121,6 +121,43 @@ static int dsa_switch_fdb_del(struct dsa_switch *ds,
 	return ds->ops->port_fdb_del(ds, info->port, fdb);
 }
 
+static int dsa_switch_mdb_add(struct dsa_switch *ds,
+			      struct dsa_notifier_mdb_info *info)
+{
+	const struct switchdev_obj_port_mdb *mdb = info->mdb;
+	struct switchdev_trans *trans = info->trans;
+
+	/* Do not care yet about other switch chips of the fabric */
+	if (ds->index != info->sw_index)
+		return 0;
+
+	if (switchdev_trans_ph_prepare(trans)) {
+		if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add)
+			return -EOPNOTSUPP;
+
+		return ds->ops->port_mdb_prepare(ds, info->port, mdb, trans);
+	}
+
+	ds->ops->port_mdb_add(ds, info->port, mdb, trans);
+
+	return 0;
+}
+
+static int dsa_switch_mdb_del(struct dsa_switch *ds,
+			      struct dsa_notifier_mdb_info *info)
+{
+	const struct switchdev_obj_port_mdb *mdb = info->mdb;
+
+	/* Do not care yet about other switch chips of the fabric */
+	if (ds->index != info->sw_index)
+		return 0;
+
+	if (!ds->ops->port_mdb_del)
+		return -EOPNOTSUPP;
+
+	return ds->ops->port_mdb_del(ds, info->port, mdb);
+}
+
 static int dsa_switch_event(struct notifier_block *nb,
 			    unsigned long event, void *info)
 {
@@ -143,6 +180,12 @@ static int dsa_switch_event(struct notifier_block *nb,
 	case DSA_NOTIFIER_FDB_DEL:
 		err = dsa_switch_fdb_del(ds, info);
 		break;
+	case DSA_NOTIFIER_MDB_ADD:
+		err = dsa_switch_mdb_add(ds, info);
+		break;
+	case DSA_NOTIFIER_MDB_DEL:
+		err = dsa_switch_mdb_del(ds, info);
+		break;
 	default:
 		err = -EOPNOTSUPP;
 		break;
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 17/20] net: dsa: add notifier for ageing time
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

This patch keeps the port-wide ageing time handling code in
dsa_port_ageing_time, pushes the requested ageing time value in a new
switch fabric notification, and moves the switch-wide ageing time
handling code in dsa_switch_ageing_time.

This has the effect that now not only the switch that the target port
belongs to can be programmed, but all switches composing the switch
fabric. For the moment, keep the current behavior and ignore other
switches.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h |  8 ++++++++
 net/dsa/port.c     | 37 ++++++++-----------------------------
 net/dsa/switch.c   | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 29 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index c19241eb094b..becaf8a61b13 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -17,10 +17,18 @@
 #include <net/dsa.h>
 
 enum {
+	DSA_NOTIFIER_AGEING_TIME,
 	DSA_NOTIFIER_BRIDGE_JOIN,
 	DSA_NOTIFIER_BRIDGE_LEAVE,
 };
 
+/* DSA_NOTIFIER_AGEING_TIME */
+struct dsa_notifier_ageing_time_info {
+	struct switchdev_trans *trans;
+	unsigned int ageing_time;
+	int sw_index;
+};
+
 /* DSA_NOTIFIER_BRIDGE_* */
 struct dsa_notifier_bridge_info {
 	struct net_device *br;
diff --git a/net/dsa/port.c b/net/dsa/port.c
index f211b0dfb12d..59328a35394d 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -128,44 +128,23 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
 	return 0;
 }
 
-static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds,
-					    unsigned int ageing_time)
-{
-	int i;
-
-	for (i = 0; i < ds->num_ports; ++i) {
-		struct dsa_port *dp = &ds->ports[i];
-
-		if (dp->ageing_time && dp->ageing_time < ageing_time)
-			ageing_time = dp->ageing_time;
-	}
-
-	return ageing_time;
-}
-
 int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
 			 struct switchdev_trans *trans)
 {
 	unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock);
 	unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies);
-	struct dsa_switch *ds = dp->ds;
+	struct dsa_notifier_ageing_time_info info = {
+		.ageing_time = ageing_time,
+		.sw_index = dp->ds->index,
+		.trans = trans,
+	};
 
-	if (switchdev_trans_ph_prepare(trans)) {
-		if (ds->ageing_time_min && ageing_time < ds->ageing_time_min)
-			return -ERANGE;
-		if (ds->ageing_time_max && ageing_time > ds->ageing_time_max)
-			return -ERANGE;
-		return 0;
-	}
+	if (switchdev_trans_ph_prepare(trans))
+		return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info);
 
-	/* Keep the fastest ageing time in case of multiple bridges */
 	dp->ageing_time = ageing_time;
-	ageing_time = dsa_fastest_ageing_time(ds, ageing_time);
 
-	if (ds->ops->set_ageing_time)
-		return ds->ops->set_ageing_time(ds, ageing_time);
-
-	return 0;
+	return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info);
 }
 
 int dsa_port_fdb_add(struct dsa_port *dp,
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index f477053308d2..540770ecc8b0 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -12,9 +12,52 @@
 
 #include <linux/netdevice.h>
 #include <linux/notifier.h>
+#include <net/switchdev.h>
 
 #include "dsa_priv.h"
 
+static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds,
+						   unsigned int ageing_time)
+{
+	int i;
+
+	for (i = 0; i < ds->num_ports; ++i) {
+		struct dsa_port *dp = &ds->ports[i];
+
+		if (dp->ageing_time && dp->ageing_time < ageing_time)
+			ageing_time = dp->ageing_time;
+	}
+
+	return ageing_time;
+}
+
+static int dsa_switch_ageing_time(struct dsa_switch *ds,
+				  struct dsa_notifier_ageing_time_info *info)
+{
+	unsigned int ageing_time = info->ageing_time;
+	struct switchdev_trans *trans = info->trans;
+
+	/* Do not care yet about other switch chips of the fabric */
+	if (ds->index != info->sw_index)
+		return 0;
+
+	if (switchdev_trans_ph_prepare(trans)) {
+		if (ds->ageing_time_min && ageing_time < ds->ageing_time_min)
+			return -ERANGE;
+		if (ds->ageing_time_max && ageing_time > ds->ageing_time_max)
+			return -ERANGE;
+		return 0;
+	}
+
+	/* Program the fastest ageing time in case of multiple bridges */
+	ageing_time = dsa_switch_fastest_ageing_time(ds, ageing_time);
+
+	if (ds->ops->set_ageing_time)
+		return ds->ops->set_ageing_time(ds, ageing_time);
+
+	return 0;
+}
+
 static int dsa_switch_bridge_join(struct dsa_switch *ds,
 				  struct dsa_notifier_bridge_info *info)
 {
@@ -48,6 +91,9 @@ static int dsa_switch_event(struct notifier_block *nb,
 	int err;
 
 	switch (event) {
+	case DSA_NOTIFIER_AGEING_TIME:
+		err = dsa_switch_ageing_time(ds, info);
+		break;
 	case DSA_NOTIFIER_BRIDGE_JOIN:
 		err = dsa_switch_bridge_join(ds, info);
 		break;
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 16/20] net: dsa: move notifier info to private header
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

The DSA notifier events and info structure definitions are not meant for
DSA drivers and users, but only used internally by the DSA core files.

Move them from the public net/dsa.h file to the private dsa_priv.h file.

Also use this opportunity to turn the events into an anonymous enum,
because we don't care about the values, and this will prevent future
conflicts when adding (and sorting) new events.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 include/net/dsa.h  | 10 ----------
 net/dsa/dsa_priv.h | 12 ++++++++++++
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 791fed62fb16..c0e567c0c824 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -285,16 +285,6 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds)
 		return ds->rtable[dst->cpu_dp->ds->index];
 }
 
-#define DSA_NOTIFIER_BRIDGE_JOIN		1
-#define DSA_NOTIFIER_BRIDGE_LEAVE		2
-
-/* DSA_NOTIFIER_BRIDGE_* */
-struct dsa_notifier_bridge_info {
-	struct net_device *br;
-	int sw_index;
-	int port;
-};
-
 struct dsa_switch_ops {
 	/*
 	 * Legacy probing.
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 16021a891095..c19241eb094b 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -16,6 +16,18 @@
 #include <linux/netpoll.h>
 #include <net/dsa.h>
 
+enum {
+	DSA_NOTIFIER_BRIDGE_JOIN,
+	DSA_NOTIFIER_BRIDGE_LEAVE,
+};
+
+/* DSA_NOTIFIER_BRIDGE_* */
+struct dsa_notifier_bridge_info {
+	struct net_device *br;
+	int sw_index;
+	int port;
+};
+
 struct dsa_device_ops {
 	struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
 	struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 15/20] net: dsa: move VLAN handlers
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Move the DSA port code which handles VLAN objects in port.c, where it
belongs.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h |  8 ++++++++
 net/dsa/port.c     | 41 +++++++++++++++++++++++++++++++++++++++++
 net/dsa/slave.c    | 41 -----------------------------------------
 3 files changed, 49 insertions(+), 41 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index c2a595036746..16021a891095 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -84,6 +84,14 @@ int dsa_port_mdb_del(struct dsa_port *dp,
 		     const struct switchdev_obj_port_mdb *mdb);
 int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb,
 		      switchdev_obj_dump_cb_t *cb);
+int dsa_port_vlan_add(struct dsa_port *dp,
+		      const struct switchdev_obj_port_vlan *vlan,
+		      struct switchdev_trans *trans);
+int dsa_port_vlan_del(struct dsa_port *dp,
+		      const struct switchdev_obj_port_vlan *vlan);
+int dsa_port_vlan_dump(struct dsa_port *dp,
+		       struct switchdev_obj_port_vlan *vlan,
+		       switchdev_obj_dump_cb_t *cb);
 
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 4ed0124a8d4b..f211b0dfb12d 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -247,3 +247,44 @@ int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb,
 
 	return -EOPNOTSUPP;
 }
+
+int dsa_port_vlan_add(struct dsa_port *dp,
+		      const struct switchdev_obj_port_vlan *vlan,
+		      struct switchdev_trans *trans)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	if (switchdev_trans_ph_prepare(trans)) {
+		if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
+			return -EOPNOTSUPP;
+
+		return ds->ops->port_vlan_prepare(ds, dp->index, vlan, trans);
+	}
+
+	ds->ops->port_vlan_add(ds, dp->index, vlan, trans);
+
+	return 0;
+}
+
+int dsa_port_vlan_del(struct dsa_port *dp,
+		      const struct switchdev_obj_port_vlan *vlan)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	if (!ds->ops->port_vlan_del)
+		return -EOPNOTSUPP;
+
+	return ds->ops->port_vlan_del(ds, dp->index, vlan);
+}
+
+int dsa_port_vlan_dump(struct dsa_port *dp,
+		       struct switchdev_obj_port_vlan *vlan,
+		       switchdev_obj_dump_cb_t *cb)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	if (ds->ops->port_vlan_dump)
+		return ds->ops->port_vlan_dump(ds, dp->index, vlan, cb);
+
+	return -EOPNOTSUPP;
+}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 9adcb8267d9a..887e26695519 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -204,47 +204,6 @@ static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
 	return 0;
 }
 
-static int dsa_port_vlan_add(struct dsa_port *dp,
-			     const struct switchdev_obj_port_vlan *vlan,
-			     struct switchdev_trans *trans)
-{
-	struct dsa_switch *ds = dp->ds;
-
-	if (switchdev_trans_ph_prepare(trans)) {
-		if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
-			return -EOPNOTSUPP;
-
-		return ds->ops->port_vlan_prepare(ds, dp->index, vlan, trans);
-	}
-
-	ds->ops->port_vlan_add(ds, dp->index, vlan, trans);
-
-	return 0;
-}
-
-static int dsa_port_vlan_del(struct dsa_port *dp,
-			     const struct switchdev_obj_port_vlan *vlan)
-{
-	struct dsa_switch *ds = dp->ds;
-
-	if (!ds->ops->port_vlan_del)
-		return -EOPNOTSUPP;
-
-	return ds->ops->port_vlan_del(ds, dp->index, vlan);
-}
-
-static int dsa_port_vlan_dump(struct dsa_port *dp,
-			      struct switchdev_obj_port_vlan *vlan,
-			      switchdev_obj_dump_cb_t *cb)
-{
-	struct dsa_switch *ds = dp->ds;
-
-	if (ds->ops->port_vlan_dump)
-		return ds->ops->port_vlan_dump(ds, dp->index, vlan, cb);
-
-	return -EOPNOTSUPP;
-}
-
 static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 14/20] net: dsa: move MDB handlers
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Move the DSA port code which handles MDB objects in port.c, where it
belongs.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h |  7 +++++++
 net/dsa/port.c     | 40 ++++++++++++++++++++++++++++++++++++++++
 net/dsa/slave.c    | 41 -----------------------------------------
 3 files changed, 47 insertions(+), 41 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index d003a2554c7a..c2a595036746 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -77,6 +77,13 @@ int dsa_port_fdb_del(struct dsa_port *dp,
 		     const struct switchdev_obj_port_fdb *fdb);
 int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb,
 		      switchdev_obj_dump_cb_t *cb);
+int dsa_port_mdb_add(struct dsa_port *dp,
+		     const struct switchdev_obj_port_mdb *mdb,
+		     struct switchdev_trans *trans);
+int dsa_port_mdb_del(struct dsa_port *dp,
+		     const struct switchdev_obj_port_mdb *mdb);
+int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb,
+		      switchdev_obj_dump_cb_t *cb);
 
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 18ec6d432152..4ed0124a8d4b 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -207,3 +207,43 @@ int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb,
 
 	return -EOPNOTSUPP;
 }
+
+int dsa_port_mdb_add(struct dsa_port *dp,
+		     const struct switchdev_obj_port_mdb *mdb,
+		     struct switchdev_trans *trans)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	if (switchdev_trans_ph_prepare(trans)) {
+		if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add)
+			return -EOPNOTSUPP;
+
+		return ds->ops->port_mdb_prepare(ds, dp->index, mdb, trans);
+	}
+
+	ds->ops->port_mdb_add(ds, dp->index, mdb, trans);
+
+	return 0;
+}
+
+int dsa_port_mdb_del(struct dsa_port *dp,
+		     const struct switchdev_obj_port_mdb *mdb)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	if (ds->ops->port_mdb_del)
+		return ds->ops->port_mdb_del(ds, dp->index, mdb);
+
+	return -EOPNOTSUPP;
+}
+
+int dsa_port_mdb_dump(struct dsa_port *dp, struct switchdev_obj_port_mdb *mdb,
+		      switchdev_obj_dump_cb_t *cb)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	if (ds->ops->port_mdb_dump)
+		return ds->ops->port_mdb_dump(ds, dp->index, mdb, cb);
+
+	return -EOPNOTSUPP;
+}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index d9b7bf759f44..9adcb8267d9a 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -245,47 +245,6 @@ static int dsa_port_vlan_dump(struct dsa_port *dp,
 	return -EOPNOTSUPP;
 }
 
-static int dsa_port_mdb_add(struct dsa_port *dp,
-			    const struct switchdev_obj_port_mdb *mdb,
-			    struct switchdev_trans *trans)
-{
-	struct dsa_switch *ds = dp->ds;
-
-	if (switchdev_trans_ph_prepare(trans)) {
-		if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add)
-			return -EOPNOTSUPP;
-
-		return ds->ops->port_mdb_prepare(ds, dp->index, mdb, trans);
-	}
-
-	ds->ops->port_mdb_add(ds, dp->index, mdb, trans);
-
-	return 0;
-}
-
-static int dsa_port_mdb_del(struct dsa_port *dp,
-			    const struct switchdev_obj_port_mdb *mdb)
-{
-	struct dsa_switch *ds = dp->ds;
-
-	if (ds->ops->port_mdb_del)
-		return ds->ops->port_mdb_del(ds, dp->index, mdb);
-
-	return -EOPNOTSUPP;
-}
-
-static int dsa_port_mdb_dump(struct dsa_port *dp,
-			     struct switchdev_obj_port_mdb *mdb,
-			     switchdev_obj_dump_cb_t *cb)
-{
-	struct dsa_switch *ds = dp->ds;
-
-	if (ds->ops->port_mdb_dump)
-		return ds->ops->port_mdb_dump(ds, dp->index, mdb, cb);
-
-	return -EOPNOTSUPP;
-}
-
 static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 13/20] net: dsa: move FDB handlers
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Move the DSA port code which handles FDB objects in port.c, where it
belongs.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h |  7 +++++++
 net/dsa/port.c     | 40 ++++++++++++++++++++++++++++++++++++++++
 net/dsa/slave.c    | 42 ------------------------------------------
 3 files changed, 47 insertions(+), 42 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index b0f9837bf5ed..d003a2554c7a 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -70,6 +70,13 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
 			    struct switchdev_trans *trans);
 int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
 			 struct switchdev_trans *trans);
+int dsa_port_fdb_add(struct dsa_port *dp,
+		     const struct switchdev_obj_port_fdb *fdb,
+		     struct switchdev_trans *trans);
+int dsa_port_fdb_del(struct dsa_port *dp,
+		     const struct switchdev_obj_port_fdb *fdb);
+int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb,
+		      switchdev_obj_dump_cb_t *cb);
 
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 3382fdc07a11..18ec6d432152 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -167,3 +167,43 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
 
 	return 0;
 }
+
+int dsa_port_fdb_add(struct dsa_port *dp,
+		     const struct switchdev_obj_port_fdb *fdb,
+		     struct switchdev_trans *trans)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	if (switchdev_trans_ph_prepare(trans)) {
+		if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add)
+			return -EOPNOTSUPP;
+
+		return ds->ops->port_fdb_prepare(ds, dp->index, fdb, trans);
+	}
+
+	ds->ops->port_fdb_add(ds, dp->index, fdb, trans);
+
+	return 0;
+}
+
+int dsa_port_fdb_del(struct dsa_port *dp,
+		     const struct switchdev_obj_port_fdb *fdb)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	if (ds->ops->port_fdb_del)
+		return -EOPNOTSUPP;
+
+	return ds->ops->port_fdb_del(ds, dp->index, fdb);
+}
+
+int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb,
+		      switchdev_obj_dump_cb_t *cb)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	if (ds->ops->port_fdb_dump)
+		return ds->ops->port_fdb_dump(ds, dp->index, fdb, cb);
+
+	return -EOPNOTSUPP;
+}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 1b0f396c4314..d9b7bf759f44 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -245,48 +245,6 @@ static int dsa_port_vlan_dump(struct dsa_port *dp,
 	return -EOPNOTSUPP;
 }
 
-static int dsa_port_fdb_add(struct dsa_port *dp,
-			    const struct switchdev_obj_port_fdb *fdb,
-			    struct switchdev_trans *trans)
-{
-	struct dsa_switch *ds = dp->ds;
-
-	if (switchdev_trans_ph_prepare(trans)) {
-		if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add)
-			return -EOPNOTSUPP;
-
-		return ds->ops->port_fdb_prepare(ds, dp->index, fdb, trans);
-	}
-
-	ds->ops->port_fdb_add(ds, dp->index, fdb, trans);
-
-	return 0;
-}
-
-static int dsa_port_fdb_del(struct dsa_port *dp,
-			    const struct switchdev_obj_port_fdb *fdb)
-{
-	struct dsa_switch *ds = dp->ds;
-	int ret = -EOPNOTSUPP;
-
-	if (ds->ops->port_fdb_del)
-		ret = ds->ops->port_fdb_del(ds, dp->index, fdb);
-
-	return ret;
-}
-
-static int dsa_port_fdb_dump(struct dsa_port *dp,
-			     struct switchdev_obj_port_fdb *fdb,
-			     switchdev_obj_dump_cb_t *cb)
-{
-	struct dsa_switch *ds = dp->ds;
-
-	if (ds->ops->port_fdb_dump)
-		return ds->ops->port_fdb_dump(ds, dp->index, fdb, cb);
-
-	return -EOPNOTSUPP;
-}
-
 static int dsa_port_mdb_add(struct dsa_port *dp,
 			    const struct switchdev_obj_port_mdb *mdb,
 			    struct switchdev_trans *trans)
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 11/20] net: dsa: move VLAN filtering setter
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Move the DSA port code which sets VLAN filtering on a port in port.c,
where it belongs.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h |  2 ++
 net/dsa/port.c     | 16 ++++++++++++++++
 net/dsa/slave.c    | 16 ----------------
 3 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index f0b6cd3c8a65..c145223247c5 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -66,6 +66,8 @@ int dsa_port_set_state(struct dsa_port *dp, u8 state,
 void dsa_port_set_state_now(struct dsa_port *dp, u8 state);
 int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
 void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
+int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
+			    struct switchdev_trans *trans);
 
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
diff --git a/net/dsa/port.c b/net/dsa/port.c
index da8577fb3d07..c9f95aaf25f1 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -111,3 +111,19 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
 	 */
 	dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
 }
+
+int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
+			    struct switchdev_trans *trans)
+{
+	struct dsa_switch *ds = dp->ds;
+
+	/* bridge skips -EOPNOTSUPP, so skip the prepare phase */
+	if (switchdev_trans_ph_prepare(trans))
+		return 0;
+
+	if (ds->ops->port_vlan_filtering)
+		return ds->ops->port_vlan_filtering(ds, dp->index,
+						    vlan_filtering);
+
+	return 0;
+}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index ab298c41b8e7..32e7e78313ba 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -338,22 +338,6 @@ static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	return -EOPNOTSUPP;
 }
 
-static int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
-				   struct switchdev_trans *trans)
-{
-	struct dsa_switch *ds = dp->ds;
-
-	/* bridge skips -EOPNOTSUPP, so skip the prepare phase */
-	if (switchdev_trans_ph_prepare(trans))
-		return 0;
-
-	if (ds->ops->port_vlan_filtering)
-		return ds->ops->port_vlan_filtering(ds, dp->index,
-						    vlan_filtering);
-
-	return 0;
-}
-
 static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds,
 					    unsigned int ageing_time)
 {
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 10/20] net: dsa: move bridging routines
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Move the DSA port code which bridges a port in port.c, where it belongs.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/dsa_priv.h |  2 ++
 net/dsa/port.c     | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 net/dsa/slave.c    | 57 -----------------------------------------------------
 3 files changed, 60 insertions(+), 57 deletions(-)

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index cda218cd9b05..f0b6cd3c8a65 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -64,6 +64,8 @@ void dsa_legacy_unregister(void);
 int dsa_port_set_state(struct dsa_port *dp, u8 state,
 		       struct switchdev_trans *trans);
 void dsa_port_set_state_now(struct dsa_port *dp, u8 state);
+int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
+void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
 
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 6cc4704190fd..da8577fb3d07 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -11,9 +11,20 @@
  */
 
 #include <linux/if_bridge.h>
+#include <linux/notifier.h>
 
 #include "dsa_priv.h"
 
+static int dsa_port_notify(struct dsa_port *dp, unsigned long e, void *v)
+{
+	struct raw_notifier_head *nh = &dp->ds->dst->nh;
+	int err;
+
+	err = raw_notifier_call_chain(nh, e, v);
+
+	return notifier_to_errno(err);
+}
+
 int dsa_port_set_state(struct dsa_port *dp, u8 state,
 		       struct switchdev_trans *trans)
 {
@@ -53,3 +64,50 @@ void dsa_port_set_state_now(struct dsa_port *dp, u8 state)
 	if (err)
 		pr_err("DSA: failed to set STP state %u (%d)\n", state, err);
 }
+
+int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br)
+{
+	struct dsa_notifier_bridge_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.br = br,
+	};
+	int err;
+
+	/* Here the port is already bridged. Reflect the current configuration
+	 * so that drivers can program their chips accordingly.
+	 */
+	dp->bridge_dev = br;
+
+	err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_JOIN, &info);
+
+	/* The bridging is rolled back on error */
+	if (err)
+		dp->bridge_dev = NULL;
+
+	return err;
+}
+
+void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
+{
+	struct dsa_notifier_bridge_info info = {
+		.sw_index = dp->ds->index,
+		.port = dp->index,
+		.br = br,
+	};
+	int err;
+
+	/* Here the port is already unbridged. Reflect the current configuration
+	 * so that drivers can program their chips accordingly.
+	 */
+	dp->bridge_dev = NULL;
+
+	err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_LEAVE, &info);
+	if (err)
+		pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
+
+	/* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
+	 * so allow it to be in BR_STATE_FORWARDING to be kept functional
+	 */
+	dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
+}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 2c57c7205aa3..ab298c41b8e7 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -27,16 +27,6 @@
 
 static bool dsa_slave_dev_check(struct net_device *dev);
 
-static int dsa_port_notify(struct dsa_port *dp, unsigned long e, void *v)
-{
-	struct raw_notifier_head *nh = &dp->ds->dst->nh;
-	int err;
-
-	err = raw_notifier_call_chain(nh, e, v);
-
-	return notifier_to_errno(err);
-}
-
 /* slave mii_bus handling ***************************************************/
 static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
 {
@@ -514,53 +504,6 @@ static int dsa_slave_port_obj_dump(struct net_device *dev,
 	return err;
 }
 
-static int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br)
-{
-	struct dsa_notifier_bridge_info info = {
-		.sw_index = dp->ds->index,
-		.port = dp->index,
-		.br = br,
-	};
-	int err;
-
-	/* Here the port is already bridged. Reflect the current configuration
-	 * so that drivers can program their chips accordingly.
-	 */
-	dp->bridge_dev = br;
-
-	err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_JOIN, &info);
-
-	/* The bridging is rolled back on error */
-	if (err)
-		dp->bridge_dev = NULL;
-
-	return err;
-}
-
-static void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
-{
-	struct dsa_notifier_bridge_info info = {
-		.sw_index = dp->ds->index,
-		.port = dp->index,
-		.br = br,
-	};
-	int err;
-
-	/* Here the port is already unbridged. Reflect the current configuration
-	 * so that drivers can program their chips accordingly.
-	 */
-	dp->bridge_dev = NULL;
-
-	err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_LEAVE, &info);
-	if (err)
-		pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
-
-	/* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
-	 * so allow it to be in BR_STATE_FORWARDING to be kept functional
-	 */
-	dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
-}
-
 static int dsa_slave_port_attr_get(struct net_device *dev,
 				   struct switchdev_attr *attr)
 {
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 09/20] net: dsa: move port state setters
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Add a new port.c file to hold all DSA port-wide logic. This patch moves
in the code which sets a port state.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/Makefile   |  2 +-
 net/dsa/dsa_priv.h |  5 +++++
 net/dsa/port.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 net/dsa/slave.c    | 40 ---------------------------------------
 4 files changed, 61 insertions(+), 41 deletions(-)
 create mode 100644 net/dsa/port.c

diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index f8c0251d1f43..90e5aa6f7d0f 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -1,6 +1,6 @@
 # the core
 obj-$(CONFIG_NET_DSA) += dsa_core.o
-dsa_core-y += dsa.o slave.o dsa2.o switch.o legacy.o
+dsa_core-y += dsa.o dsa2.o legacy.o port.o slave.o switch.o
 
 # tagging formats
 dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index c274130e3ac9..cda218cd9b05 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -60,6 +60,11 @@ void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds);
 int dsa_legacy_register(void);
 void dsa_legacy_unregister(void);
 
+/* port.c */
+int dsa_port_set_state(struct dsa_port *dp, u8 state,
+		       struct switchdev_trans *trans);
+void dsa_port_set_state_now(struct dsa_port *dp, u8 state);
+
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
 void dsa_slave_mii_bus_init(struct dsa_switch *ds);
diff --git a/net/dsa/port.c b/net/dsa/port.c
new file mode 100644
index 000000000000..6cc4704190fd
--- /dev/null
+++ b/net/dsa/port.c
@@ -0,0 +1,55 @@
+/*
+ * Handling of a single switch port
+ *
+ * Copyright (c) 2017 Savoir-faire Linux Inc.
+ *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/if_bridge.h>
+
+#include "dsa_priv.h"
+
+int dsa_port_set_state(struct dsa_port *dp, u8 state,
+		       struct switchdev_trans *trans)
+{
+	struct dsa_switch *ds = dp->ds;
+	int port = dp->index;
+
+	if (switchdev_trans_ph_prepare(trans))
+		return ds->ops->port_stp_state_set ? 0 : -EOPNOTSUPP;
+
+	if (ds->ops->port_stp_state_set)
+		ds->ops->port_stp_state_set(ds, port, state);
+
+	if (ds->ops->port_fast_age) {
+		/* Fast age FDB entries or flush appropriate forwarding database
+		 * for the given port, if we are moving it from Learning or
+		 * Forwarding state, to Disabled or Blocking or Listening state.
+		 */
+
+		if ((dp->stp_state == BR_STATE_LEARNING ||
+		     dp->stp_state == BR_STATE_FORWARDING) &&
+		    (state == BR_STATE_DISABLED ||
+		     state == BR_STATE_BLOCKING ||
+		     state == BR_STATE_LISTENING))
+			ds->ops->port_fast_age(ds, port);
+	}
+
+	dp->stp_state = state;
+
+	return 0;
+}
+
+void dsa_port_set_state_now(struct dsa_port *dp, u8 state)
+{
+	int err;
+
+	err = dsa_port_set_state(dp, state, NULL);
+	if (err)
+		pr_err("DSA: failed to set STP state %u (%d)\n", state, err);
+}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index b0150f79dcdd..2c57c7205aa3 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -84,46 +84,6 @@ static inline bool dsa_port_is_bridged(struct dsa_port *dp)
 	return !!dp->bridge_dev;
 }
 
-static int dsa_port_set_state(struct dsa_port *dp, u8 state,
-			      struct switchdev_trans *trans)
-{
-	struct dsa_switch *ds = dp->ds;
-	int port = dp->index;
-
-	if (switchdev_trans_ph_prepare(trans))
-		return ds->ops->port_stp_state_set ? 0 : -EOPNOTSUPP;
-
-	if (ds->ops->port_stp_state_set)
-		ds->ops->port_stp_state_set(ds, port, state);
-
-	if (ds->ops->port_fast_age) {
-		/* Fast age FDB entries or flush appropriate forwarding database
-		 * for the given port, if we are moving it from Learning or
-		 * Forwarding state, to Disabled or Blocking or Listening state.
-		 */
-
-		if ((dp->stp_state == BR_STATE_LEARNING ||
-		     dp->stp_state == BR_STATE_FORWARDING) &&
-		    (state == BR_STATE_DISABLED ||
-		     state == BR_STATE_BLOCKING ||
-		     state == BR_STATE_LISTENING))
-			ds->ops->port_fast_age(ds, port);
-	}
-
-	dp->stp_state = state;
-
-	return 0;
-}
-
-static void dsa_port_set_state_now(struct dsa_port *dp, u8 state)
-{
-	int err;
-
-	err = dsa_port_set_state(dp, state, NULL);
-	if (err)
-		pr_err("DSA: failed to set STP state %u (%d)\n", state, err);
-}
-
 static int dsa_slave_open(struct net_device *dev)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
-- 
2.13.0

^ permalink raw reply related

* [PATCH net-next 08/20] net: dsa: change scope of ageing time setter
From: Vivien Didelot @ 2017-05-19 21:00 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <20170519210055.9366-1-vivien.didelot@savoirfairelinux.com>

Change the scope of the switchdev bridge ageing time attribute setter
from the DSA slave device to the generic DSA port, so that the future
port-wide API can also be used for other port types, such as CPU and DSA
links.

Also ds->ports is now a contiguous array of dsa_port structures, thus
their addresses cannot be NULL. Remove the useless check in
dsa_fastest_ageing_time.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 net/dsa/slave.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 216eb38a847d..b0150f79dcdd 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -412,21 +412,19 @@ static unsigned int dsa_fastest_ageing_time(struct dsa_switch *ds,
 	for (i = 0; i < ds->num_ports; ++i) {
 		struct dsa_port *dp = &ds->ports[i];
 
-		if (dp && dp->ageing_time && dp->ageing_time < ageing_time)
+		if (dp->ageing_time && dp->ageing_time < ageing_time)
 			ageing_time = dp->ageing_time;
 	}
 
 	return ageing_time;
 }
 
-static int dsa_slave_ageing_time(struct net_device *dev,
-				 const struct switchdev_attr *attr,
-				 struct switchdev_trans *trans)
+static int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
+				struct switchdev_trans *trans)
 {
-	struct dsa_slave_priv *p = netdev_priv(dev);
-	struct dsa_switch *ds = p->dp->ds;
-	unsigned long ageing_jiffies = clock_t_to_jiffies(attr->u.ageing_time);
+	unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock);
 	unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies);
+	struct dsa_switch *ds = dp->ds;
 
 	if (switchdev_trans_ph_prepare(trans)) {
 		if (ds->ageing_time_min && ageing_time < ds->ageing_time_min)
@@ -437,7 +435,7 @@ static int dsa_slave_ageing_time(struct net_device *dev,
 	}
 
 	/* Keep the fastest ageing time in case of multiple bridges */
-	p->dp->ageing_time = ageing_time;
+	dp->ageing_time = ageing_time;
 	ageing_time = dsa_fastest_ageing_time(ds, ageing_time);
 
 	if (ds->ops->set_ageing_time)
@@ -463,7 +461,7 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
 					      trans);
 		break;
 	case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
-		ret = dsa_slave_ageing_time(dev, attr, trans);
+		ret = dsa_port_ageing_time(dp, attr->u.ageing_time, trans);
 		break;
 	default:
 		ret = -EOPNOTSUPP;
-- 
2.13.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox