aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>2017-02-03 13:20:21 -0500
committerDavid S. Miller <davem@davemloft.net>2017-02-06 16:53:29 -0500
commit04d3a4c6af52a58370795bc9f70dc15f51f8bb84 (patch)
tree07ed46ceedeb980d62da34ae26e3aac5f8af7dfb
parentf515f192ab4f45bb695146b82432d63d98775787 (diff)
net: dsa: introduce bridge notifier
A slave device will now notify the switch fabric once its port is bridged or unbridged, instead of calling directly its switch operations. This code allows propagating cross-chip bridging events in the fabric. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/dsa.h10
-rw-r--r--net/dsa/slave.c40
-rw-r--r--net/dsa/switch.c32
3 files changed, 71 insertions, 11 deletions
diff --git a/include/net/dsa.h b/include/net/dsa.h
index ac4ea7c3a102..e9c940c8936f 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -268,6 +268,16 @@ struct switchdev_obj_port_fdb;
268struct switchdev_obj_port_mdb; 268struct switchdev_obj_port_mdb;
269struct switchdev_obj_port_vlan; 269struct switchdev_obj_port_vlan;
270 270
271#define DSA_NOTIFIER_BRIDGE_JOIN 1
272#define DSA_NOTIFIER_BRIDGE_LEAVE 2
273
274/* DSA_NOTIFIER_BRIDGE_* */
275struct dsa_notifier_bridge_info {
276 struct net_device *br;
277 int sw_index;
278 int port;
279};
280
271struct dsa_switch_ops { 281struct dsa_switch_ops {
272 /* 282 /*
273 * Probing and setup. 283 * Probing and setup.
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index d8c3c0f00cf3..061a49c29cef 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -27,6 +27,17 @@
27 27
28static bool dsa_slave_dev_check(struct net_device *dev); 28static bool dsa_slave_dev_check(struct net_device *dev);
29 29
30static int dsa_slave_notify(struct net_device *dev, unsigned long e, void *v)
31{
32 struct dsa_slave_priv *p = netdev_priv(dev);
33 struct raw_notifier_head *nh = &p->dp->ds->dst->nh;
34 int err;
35
36 err = raw_notifier_call_chain(nh, e, v);
37
38 return notifier_to_errno(err);
39}
40
30/* slave mii_bus handling ***************************************************/ 41/* slave mii_bus handling ***************************************************/
31static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg) 42static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
32{ 43{
@@ -562,39 +573,46 @@ static int dsa_slave_bridge_port_join(struct net_device *dev,
562 struct net_device *br) 573 struct net_device *br)
563{ 574{
564 struct dsa_slave_priv *p = netdev_priv(dev); 575 struct dsa_slave_priv *p = netdev_priv(dev);
565 struct dsa_switch *ds = p->dp->ds; 576 struct dsa_notifier_bridge_info info = {
566 int ret = -EOPNOTSUPP; 577 .sw_index = p->dp->ds->index,
578 .port = p->dp->index,
579 .br = br,
580 };
581 int err;
567 582
568 /* Here the port is already bridged. Reflect the current configuration 583 /* Here the port is already bridged. Reflect the current configuration
569 * so that drivers can program their chips accordingly. 584 * so that drivers can program their chips accordingly.
570 */ 585 */
571 p->dp->bridge_dev = br; 586 p->dp->bridge_dev = br;
572 587
573 if (ds->ops->port_bridge_join) 588 err = dsa_slave_notify(dev, DSA_NOTIFIER_BRIDGE_JOIN, &info);
574 ret = ds->ops->port_bridge_join(ds, p->dp->index, br);
575 589
576 /* The bridging is rolled back on error */ 590 /* The bridging is rolled back on error */
577 if (ret && ret != -EOPNOTSUPP) { 591 if (err)
578 p->dp->bridge_dev = NULL; 592 p->dp->bridge_dev = NULL;
579 return ret;
580 }
581 593
582 return 0; 594 return err;
583} 595}
584 596
585static void dsa_slave_bridge_port_leave(struct net_device *dev, 597static void dsa_slave_bridge_port_leave(struct net_device *dev,
586 struct net_device *br) 598 struct net_device *br)
587{ 599{
588 struct dsa_slave_priv *p = netdev_priv(dev); 600 struct dsa_slave_priv *p = netdev_priv(dev);
589 struct dsa_switch *ds = p->dp->ds; 601 struct dsa_notifier_bridge_info info = {
602 .sw_index = p->dp->ds->index,
603 .port = p->dp->index,
604 .br = br,
605 };
606 int err;
590 607
591 /* Here the port is already unbridged. Reflect the current configuration 608 /* Here the port is already unbridged. Reflect the current configuration
592 * so that drivers can program their chips accordingly. 609 * so that drivers can program their chips accordingly.
593 */ 610 */
594 p->dp->bridge_dev = NULL; 611 p->dp->bridge_dev = NULL;
595 612
596 if (ds->ops->port_bridge_leave) 613 err = dsa_slave_notify(dev, DSA_NOTIFIER_BRIDGE_LEAVE, &info);
597 ds->ops->port_bridge_leave(ds, p->dp->index, br); 614 if (err)
615 netdev_err(dev, "failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
598 616
599 /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer, 617 /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
600 * so allow it to be in BR_STATE_FORWARDING to be kept functional 618 * so allow it to be in BR_STATE_FORWARDING to be kept functional
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index e22fa7633d03..6456dacf9ae9 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -13,6 +13,32 @@
13#include <linux/notifier.h> 13#include <linux/notifier.h>
14#include <net/dsa.h> 14#include <net/dsa.h>
15 15
16static int dsa_switch_bridge_join(struct dsa_switch *ds,
17 struct dsa_notifier_bridge_info *info)
18{
19 if (ds->index == info->sw_index && ds->ops->port_bridge_join)
20 return ds->ops->port_bridge_join(ds, info->port, info->br);
21
22 if (ds->index != info->sw_index)
23 dev_dbg(ds->dev, "crosschip DSA port %d.%d bridged to %s\n",
24 info->sw_index, info->port, netdev_name(info->br));
25
26 return 0;
27}
28
29static int dsa_switch_bridge_leave(struct dsa_switch *ds,
30 struct dsa_notifier_bridge_info *info)
31{
32 if (ds->index == info->sw_index && ds->ops->port_bridge_leave)
33 ds->ops->port_bridge_leave(ds, info->port, info->br);
34
35 if (ds->index != info->sw_index)
36 dev_dbg(ds->dev, "crosschip DSA port %d.%d unbridged from %s\n",
37 info->sw_index, info->port, netdev_name(info->br));
38
39 return 0;
40}
41
16static int dsa_switch_event(struct notifier_block *nb, 42static int dsa_switch_event(struct notifier_block *nb,
17 unsigned long event, void *info) 43 unsigned long event, void *info)
18{ 44{
@@ -20,6 +46,12 @@ static int dsa_switch_event(struct notifier_block *nb,
20 int err; 46 int err;
21 47
22 switch (event) { 48 switch (event) {
49 case DSA_NOTIFIER_BRIDGE_JOIN:
50 err = dsa_switch_bridge_join(ds, info);
51 break;
52 case DSA_NOTIFIER_BRIDGE_LEAVE:
53 err = dsa_switch_bridge_leave(ds, info);
54 break;
23 default: 55 default:
24 err = -EOPNOTSUPP; 56 err = -EOPNOTSUPP;
25 break; 57 break;