Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9172d2a0 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dsa-add-fabric-notifier'



Vivien Didelot says:

====================
net: dsa: add fabric notifier

When a switch fabric is composed of multiple switch chips, these chips
must be programmed accordingly when an event occurred on one of them.

Examples of such event include hardware bridging: when a Linux bridge
spans interconnected chips, they must be programmed to allow external
ports to ingress frames on their internal ports.

Another example is cross-chip hardware VLANs. Switch chips in-between
interconnected bridge ports must also configure a given VLAN to allow
packets to pass through them.

In order to support that, this patchset introduces a non-intrusive
notifier mechanism. It adds a notifier head in every DSA switch tree
(the said fabric), and a notifier block in every DSA switch chip.

When an even occurs, it is chained to all notifiers of the fabric.
Switch chips can react accordingly if they are cross-chip capable.

On a dynamic debug enabled system, bridging a port in a multi-chip
fabric will print something like this (ZII Rev B board):

    # brctl addif br0 lan3
    mv88e6085 0.1:00: crosschip DSA port 1.0 bridged to br0
    mv88e6085 0.4:00: crosschip DSA port 1.0 bridged to br0
    # brctl delif br0 lan3
    mv88e6085 0.1:00: crosschip DSA port 1.0 unbridged from br0
    mv88e6085 0.4:00: crosschip DSA port 1.0 unbridged from br0

Currently only bridging events are added. A patchset introducing support
for cross-chip hardware bridging configuration in mv88e6xxx will follow
right after. Then events for switchdev operations are next on the line.

We should note that non-switchdev events do not support rolling-back
switch-wide operations. We'll have to work on closer integration with
switchdev for that, like introducing new attributes or objects, to
benefit from the prepare and commit phases.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 321fa4ff 04d3a4c6
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@

#include <linux/if_ether.h>
#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/of.h>
@@ -92,6 +93,9 @@ struct packet_type;
struct dsa_switch_tree {
	struct list_head	list;

	/* Notifier chain for switch-wide events */
	struct raw_notifier_head	nh;

	/* Tree identifier */
	u32 tree;

@@ -182,6 +186,9 @@ struct dsa_switch {
	struct dsa_switch_tree	*dst;
	int			index;

	/* Listener for switch fabric events */
	struct notifier_block	nb;

	/*
	 * Give the switch driver somewhere to hang its private data
	 * structure.
@@ -261,6 +268,16 @@ struct switchdev_obj_port_fdb;
struct switchdev_obj_port_mdb;
struct switchdev_obj_port_vlan;

#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 {
	/*
	 * Probing and setup.
+1 −0
Original line number Diff line number Diff line
# the core
obj-$(CONFIG_NET_DSA) += dsa_core.o
dsa_core-y += dsa.o slave.o dsa2.o
dsa_core-y += dsa.o slave.o dsa2.o switch.o

# tagging formats
dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
+10 −6
Original line number Diff line number Diff line
@@ -275,6 +275,10 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
	if (ret < 0)
		return ret;

	ret = dsa_switch_register_notifier(ds);
	if (ret)
		return ret;

	if (ops->set_addr) {
		ret = ops->set_addr(ds, dst->master_netdev->dev_addr);
		if (ret < 0)
@@ -400,6 +404,8 @@ static void dsa_switch_destroy(struct dsa_switch *ds)

	if (ds->slave_mii_bus && ds->ops->phy_read)
		mdiobus_unregister(ds->slave_mii_bus);

	dsa_switch_unregister_notifier(ds);
}

#ifdef CONFIG_PM_SLEEP
@@ -903,10 +909,6 @@ static struct packet_type dsa_pack_type __read_mostly = {
	.func	= dsa_switch_rcv,
};

static struct notifier_block dsa_netdevice_nb __read_mostly = {
	.notifier_call	= dsa_slave_netdevice_event,
};

#ifdef CONFIG_PM_SLEEP
static int dsa_suspend(struct device *d)
{
@@ -964,7 +966,9 @@ static int __init dsa_init_module(void)
{
	int rc;

	register_netdevice_notifier(&dsa_netdevice_nb);
	rc = dsa_slave_register_notifier();
	if (rc)
		return rc;

	rc = platform_driver_register(&dsa_driver);
	if (rc)
@@ -978,7 +982,7 @@ module_init(dsa_init_module);

static void __exit dsa_cleanup_module(void)
{
	unregister_netdevice_notifier(&dsa_netdevice_nb);
	dsa_slave_unregister_notifier();
	dev_remove_pack(&dsa_pack_type);
	platform_driver_unregister(&dsa_driver);
}
+6 −0
Original line number Diff line number Diff line
@@ -294,6 +294,10 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
	if (err < 0)
		return err;

	err = dsa_switch_register_notifier(ds);
	if (err)
		return err;

	if (ds->ops->set_addr) {
		err = ds->ops->set_addr(ds, dst->master_netdev->dev_addr);
		if (err < 0)
@@ -364,6 +368,8 @@ static void dsa_ds_unapply(struct dsa_switch_tree *dst, struct dsa_switch *ds)

	if (ds->slave_mii_bus && ds->ops->phy_read)
		mdiobus_unregister(ds->slave_mii_bus);

	dsa_switch_unregister_notifier(ds);
}

static int dsa_dst_apply(struct dsa_switch_tree *dst)
+6 −2
Original line number Diff line number Diff line
@@ -63,8 +63,12 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
void dsa_slave_destroy(struct net_device *slave_dev);
int dsa_slave_suspend(struct net_device *slave_dev);
int dsa_slave_resume(struct net_device *slave_dev);
int dsa_slave_netdevice_event(struct notifier_block *unused,
			      unsigned long event, void *ptr);
int dsa_slave_register_notifier(void);
void dsa_slave_unregister_notifier(void);

/* switch.c */
int dsa_switch_register_notifier(struct dsa_switch *ds);
void dsa_switch_unregister_notifier(struct dsa_switch *ds);

/* tag_dsa.c */
extern const struct dsa_device_ops dsa_netdev_ops;
Loading