Skip to content

Commit f515f19

Browse files
viviendavem330
authored andcommitted
net: dsa: add switch notifier
Add a notifier block per DSA switch, registered against a notifier head in the switch fabric they belong to. This infrastructure will allow to propagate fabric-wide events such as port bridging, VLAN configuration, etc. If a DSA switch driver cares about cross-chip configuration, such events can be caught. Signed-off-by: Vivien Didelot <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c5d35cb commit f515f19

File tree

6 files changed

+77
-0
lines changed

6 files changed

+77
-0
lines changed

include/net/dsa.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <linux/if_ether.h>
1515
#include <linux/list.h>
16+
#include <linux/notifier.h>
1617
#include <linux/timer.h>
1718
#include <linux/workqueue.h>
1819
#include <linux/of.h>
@@ -92,6 +93,9 @@ struct packet_type;
9293
struct dsa_switch_tree {
9394
struct list_head list;
9495

96+
/* Notifier chain for switch-wide events */
97+
struct raw_notifier_head nh;
98+
9599
/* Tree identifier */
96100
u32 tree;
97101

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

189+
/* Listener for switch fabric events */
190+
struct notifier_block nb;
191+
185192
/*
186193
* Give the switch driver somewhere to hang its private data
187194
* structure.

net/dsa/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# the core
22
obj-$(CONFIG_NET_DSA) += dsa_core.o
33
dsa_core-y += dsa.o slave.o dsa2.o
4+
dsa_core-y += dsa.o slave.o dsa2.o switch.o
45

56
# tagging formats
67
dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o

net/dsa/dsa.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
275275
if (ret < 0)
276276
return ret;
277277

278+
ret = dsa_switch_register_notifier(ds);
279+
if (ret)
280+
return ret;
281+
278282
if (ops->set_addr) {
279283
ret = ops->set_addr(ds, dst->master_netdev->dev_addr);
280284
if (ret < 0)
@@ -400,6 +404,8 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
400404

401405
if (ds->slave_mii_bus && ds->ops->phy_read)
402406
mdiobus_unregister(ds->slave_mii_bus);
407+
408+
dsa_switch_unregister_notifier(ds);
403409
}
404410

405411
#ifdef CONFIG_PM_SLEEP

net/dsa/dsa2.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ static int dsa_ds_apply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
294294
if (err < 0)
295295
return err;
296296

297+
err = dsa_switch_register_notifier(ds);
298+
if (err)
299+
return err;
300+
297301
if (ds->ops->set_addr) {
298302
err = ds->ops->set_addr(ds, dst->master_netdev->dev_addr);
299303
if (err < 0)
@@ -364,6 +368,8 @@ static void dsa_ds_unapply(struct dsa_switch_tree *dst, struct dsa_switch *ds)
364368

365369
if (ds->slave_mii_bus && ds->ops->phy_read)
366370
mdiobus_unregister(ds->slave_mii_bus);
371+
372+
dsa_switch_unregister_notifier(ds);
367373
}
368374

369375
static int dsa_dst_apply(struct dsa_switch_tree *dst)

net/dsa/dsa_priv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ int dsa_slave_resume(struct net_device *slave_dev);
6666
int dsa_slave_register_notifier(void);
6767
void dsa_slave_unregister_notifier(void);
6868

69+
/* switch.c */
70+
int dsa_switch_register_notifier(struct dsa_switch *ds);
71+
void dsa_switch_unregister_notifier(struct dsa_switch *ds);
72+
6973
/* tag_dsa.c */
7074
extern const struct dsa_device_ops dsa_netdev_ops;
7175

net/dsa/switch.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Handling of a single switch chip, part of a switch fabric
3+
*
4+
* Copyright (c) 2017 Vivien Didelot <[email protected]>
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*/
11+
12+
#include <linux/netdevice.h>
13+
#include <linux/notifier.h>
14+
#include <net/dsa.h>
15+
16+
static int dsa_switch_event(struct notifier_block *nb,
17+
unsigned long event, void *info)
18+
{
19+
struct dsa_switch *ds = container_of(nb, struct dsa_switch, nb);
20+
int err;
21+
22+
switch (event) {
23+
default:
24+
err = -EOPNOTSUPP;
25+
break;
26+
}
27+
28+
/* Non-switchdev operations cannot be rolled back. If a DSA driver
29+
* returns an error during the chained call, switch chips may be in an
30+
* inconsistent state.
31+
*/
32+
if (err)
33+
dev_dbg(ds->dev, "breaking chain for DSA event %lu (%d)\n",
34+
event, err);
35+
36+
return notifier_from_errno(err);
37+
}
38+
39+
int dsa_switch_register_notifier(struct dsa_switch *ds)
40+
{
41+
ds->nb.notifier_call = dsa_switch_event;
42+
43+
return raw_notifier_chain_register(&ds->dst->nh, &ds->nb);
44+
}
45+
46+
void dsa_switch_unregister_notifier(struct dsa_switch *ds)
47+
{
48+
int err;
49+
50+
err = raw_notifier_chain_unregister(&ds->dst->nh, &ds->nb);
51+
if (err)
52+
dev_err(ds->dev, "failed to unregister notifier (%d)\n", err);
53+
}

0 commit comments

Comments
 (0)