aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-02-25 17:04:15 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-25 17:04:15 -0500
commitbb66be1c549a0760500cfad404b3d79a136d0e44 (patch)
treed0a46201df407c4719abade5cd44bcb86041b195
parent92bf200881d978bc3c6a290991ae1f9ddc7b5411 (diff)
parent12f460f23423e81d6dd3efeb78906ae634ad8fc9 (diff)
Merge branch 'sf2_hwbridge'
Florian Fainelli says: ==================== net: dsa: integration with SWITCHDEV for HW bridging This patch set provides the DSA and SWITCHDEV integration bits together and modifies the bcm_sf2 driver accordingly such that it works properly with HW bridging. Changes in v3: - add back the null pointer check in dsa_slave_br_port_mask from Guenter - slightly rework patch 1 commit message not to mention the function name we add in patch 2 Changes in v2: - avoid a race condition in how DSA network devices are created, patch from Guenter Roeck - provide a consistent and work STP state once a port leaves the bridge - retain a bridge device pointer to properly flag port/bridge membership - properly flush the ARL (Address Resolution Logic) in bcm_sf2.c - properly retain port membership when individually bringing devices up/down while they are members of a bridge We discussed on the mailing-list the possibility of standardizing a "fdb_flush" operation for DSA switch drivers, looking at the Marvell and Broadcom switches, I am not convinced this is practical or diserable as the terminologies vary here, but there is nothing preventing us from doing it later. Many thanks to Guenter and Andrew for both testing and providing feedback. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/dsa/bcm_sf2.c155
-rw-r--r--drivers/net/dsa/bcm_sf2.h2
-rw-r--r--drivers/net/dsa/bcm_sf2_regs.h15
-rw-r--r--include/net/dsa.h10
-rw-r--r--net/dsa/Kconfig1
-rw-r--r--net/dsa/dsa.c17
-rw-r--r--net/dsa/dsa_priv.h9
-rw-r--r--net/dsa/slave.c164
8 files changed, 355 insertions, 18 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 4daffb284931..cedb572bf25a 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -23,6 +23,7 @@
23#include <linux/of_address.h> 23#include <linux/of_address.h>
24#include <net/dsa.h> 24#include <net/dsa.h>
25#include <linux/ethtool.h> 25#include <linux/ethtool.h>
26#include <linux/if_bridge.h>
26 27
27#include "bcm_sf2.h" 28#include "bcm_sf2.h"
28#include "bcm_sf2_regs.h" 29#include "bcm_sf2_regs.h"
@@ -299,10 +300,14 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
299 if (port == 7) 300 if (port == 7)
300 intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF)); 301 intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF));
301 302
302 /* Set this port, and only this one to be in the default VLAN */ 303 /* Set this port, and only this one to be in the default VLAN,
304 * if member of a bridge, restore its membership prior to
305 * bringing down this port.
306 */
303 reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(port)); 307 reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(port));
304 reg &= ~PORT_VLAN_CTRL_MASK; 308 reg &= ~PORT_VLAN_CTRL_MASK;
305 reg |= (1 << port); 309 reg |= (1 << port);
310 reg |= priv->port_sts[port].vlan_ctl_mask;
306 core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(port)); 311 core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(port));
307 312
308 bcm_sf2_imp_vlan_setup(ds, cpu_port); 313 bcm_sf2_imp_vlan_setup(ds, cpu_port);
@@ -400,6 +405,151 @@ static int bcm_sf2_sw_set_eee(struct dsa_switch *ds, int port,
400 return 0; 405 return 0;
401} 406}
402 407
408/* Fast-ageing of ARL entries for a given port, equivalent to an ARL
409 * flush for that port.
410 */
411static int bcm_sf2_sw_fast_age_port(struct dsa_switch *ds, int port)
412{
413 struct bcm_sf2_priv *priv = ds_to_priv(ds);
414 unsigned int timeout = 1000;
415 u32 reg;
416
417 core_writel(priv, port, CORE_FAST_AGE_PORT);
418
419 reg = core_readl(priv, CORE_FAST_AGE_CTRL);
420 reg |= EN_AGE_PORT | FAST_AGE_STR_DONE;
421 core_writel(priv, reg, CORE_FAST_AGE_CTRL);
422
423 do {
424 reg = core_readl(priv, CORE_FAST_AGE_CTRL);
425 if (!(reg & FAST_AGE_STR_DONE))
426 break;
427
428 cpu_relax();
429 } while (timeout--);
430
431 if (!timeout)
432 return -ETIMEDOUT;
433
434 return 0;
435}
436
437static int bcm_sf2_sw_br_join(struct dsa_switch *ds, int port,
438 u32 br_port_mask)
439{
440 struct bcm_sf2_priv *priv = ds_to_priv(ds);
441 unsigned int i;
442 u32 reg, p_ctl;
443
444 p_ctl = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(port));
445
446 for (i = 0; i < priv->hw_params.num_ports; i++) {
447 if (!((1 << i) & br_port_mask))
448 continue;
449
450 /* Add this local port to the remote port VLAN control
451 * membership and update the remote port bitmask
452 */
453 reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i));
454 reg |= 1 << port;
455 core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(i));
456 priv->port_sts[i].vlan_ctl_mask = reg;
457
458 p_ctl |= 1 << i;
459 }
460
461 /* Configure the local port VLAN control membership to include
462 * remote ports and update the local port bitmask
463 */
464 core_writel(priv, p_ctl, CORE_PORT_VLAN_CTL_PORT(port));
465 priv->port_sts[port].vlan_ctl_mask = p_ctl;
466
467 return 0;
468}
469
470static int bcm_sf2_sw_br_leave(struct dsa_switch *ds, int port,
471 u32 br_port_mask)
472{
473 struct bcm_sf2_priv *priv = ds_to_priv(ds);
474 unsigned int i;
475 u32 reg, p_ctl;
476
477 p_ctl = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(port));
478
479 for (i = 0; i < priv->hw_params.num_ports; i++) {
480 /* Don't touch the remaining ports */
481 if (!((1 << i) & br_port_mask))
482 continue;
483
484 reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i));
485 reg &= ~(1 << port);
486 core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(i));
487 priv->port_sts[port].vlan_ctl_mask = reg;
488
489 /* Prevent self removal to preserve isolation */
490 if (port != i)
491 p_ctl &= ~(1 << i);
492 }
493
494 core_writel(priv, p_ctl, CORE_PORT_VLAN_CTL_PORT(port));
495 priv->port_sts[port].vlan_ctl_mask = p_ctl;
496
497 return 0;
498}
499
500static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port,
501 u8 state)
502{
503 struct bcm_sf2_priv *priv = ds_to_priv(ds);
504 u8 hw_state, cur_hw_state;
505 int ret = 0;
506 u32 reg;
507
508 reg = core_readl(priv, CORE_G_PCTL_PORT(port));
509 cur_hw_state = reg >> G_MISTP_STATE_SHIFT;
510
511 switch (state) {
512 case BR_STATE_DISABLED:
513 hw_state = G_MISTP_DIS_STATE;
514 break;
515 case BR_STATE_LISTENING:
516 hw_state = G_MISTP_LISTEN_STATE;
517 break;
518 case BR_STATE_LEARNING:
519 hw_state = G_MISTP_LEARN_STATE;
520 break;
521 case BR_STATE_FORWARDING:
522 hw_state = G_MISTP_FWD_STATE;
523 break;
524 case BR_STATE_BLOCKING:
525 hw_state = G_MISTP_BLOCK_STATE;
526 break;
527 default:
528 pr_err("%s: invalid STP state: %d\n", __func__, state);
529 return -EINVAL;
530 }
531
532 /* Fast-age ARL entries if we are moving a port from Learning or
533 * Forwarding state to Disabled, Blocking or Listening state
534 */
535 if (cur_hw_state != hw_state) {
536 if (cur_hw_state & 4 && !(hw_state & 4)) {
537 ret = bcm_sf2_sw_fast_age_port(ds, port);
538 if (ret) {
539 pr_err("%s: fast-ageing failed\n", __func__);
540 return ret;
541 }
542 }
543 }
544
545 reg = core_readl(priv, CORE_G_PCTL_PORT(port));
546 reg &= ~(G_MISTP_STATE_MASK << G_MISTP_STATE_SHIFT);
547 reg |= hw_state;
548 core_writel(priv, reg, CORE_G_PCTL_PORT(port));
549
550 return 0;
551}
552
403static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id) 553static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id)
404{ 554{
405 struct bcm_sf2_priv *priv = dev_id; 555 struct bcm_sf2_priv *priv = dev_id;
@@ -916,6 +1066,9 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = {
916 .port_disable = bcm_sf2_port_disable, 1066 .port_disable = bcm_sf2_port_disable,
917 .get_eee = bcm_sf2_sw_get_eee, 1067 .get_eee = bcm_sf2_sw_get_eee,
918 .set_eee = bcm_sf2_sw_set_eee, 1068 .set_eee = bcm_sf2_sw_set_eee,
1069 .port_join_bridge = bcm_sf2_sw_br_join,
1070 .port_leave_bridge = bcm_sf2_sw_br_leave,
1071 .port_stp_update = bcm_sf2_sw_br_set_stp_state,
919}; 1072};
920 1073
921static int __init bcm_sf2_init(void) 1074static int __init bcm_sf2_init(void)
diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h
index ee9f650d5026..0f217e99904f 100644
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -46,6 +46,8 @@ struct bcm_sf2_port_status {
46 unsigned int link; 46 unsigned int link;
47 47
48 struct ethtool_eee eee; 48 struct ethtool_eee eee;
49
50 u32 vlan_ctl_mask;
49}; 51};
50 52
51struct bcm_sf2_priv { 53struct bcm_sf2_priv {
diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h
index cabdfa5e217a..fa4e6e78c9ea 100644
--- a/drivers/net/dsa/bcm_sf2_regs.h
+++ b/drivers/net/dsa/bcm_sf2_regs.h
@@ -163,6 +163,21 @@
163#define EN_CHIP_RST (1 << 6) 163#define EN_CHIP_RST (1 << 6)
164#define EN_SW_RESET (1 << 4) 164#define EN_SW_RESET (1 << 4)
165 165
166#define CORE_FAST_AGE_CTRL 0x00220
167#define EN_FAST_AGE_STATIC (1 << 0)
168#define EN_AGE_DYNAMIC (1 << 1)
169#define EN_AGE_PORT (1 << 2)
170#define EN_AGE_VLAN (1 << 3)
171#define EN_AGE_SPT (1 << 4)
172#define EN_AGE_MCAST (1 << 5)
173#define FAST_AGE_STR_DONE (1 << 7)
174
175#define CORE_FAST_AGE_PORT 0x00224
176#define AGE_PORT_MASK 0xf
177
178#define CORE_FAST_AGE_VID 0x00228
179#define AGE_VID_MASK 0x3fff
180
166#define CORE_LNKSTS 0x00400 181#define CORE_LNKSTS 0x00400
167#define LNK_STS_MASK 0x1ff 182#define LNK_STS_MASK 0x1ff
168 183
diff --git a/include/net/dsa.h b/include/net/dsa.h
index ed3c34bbb67a..92be34791963 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -275,6 +275,16 @@ struct dsa_switch_driver {
275 int (*get_regs_len)(struct dsa_switch *ds, int port); 275 int (*get_regs_len)(struct dsa_switch *ds, int port);
276 void (*get_regs)(struct dsa_switch *ds, int port, 276 void (*get_regs)(struct dsa_switch *ds, int port,
277 struct ethtool_regs *regs, void *p); 277 struct ethtool_regs *regs, void *p);
278
279 /*
280 * Bridge integration
281 */
282 int (*port_join_bridge)(struct dsa_switch *ds, int port,
283 u32 br_port_mask);
284 int (*port_leave_bridge)(struct dsa_switch *ds, int port,
285 u32 br_port_mask);
286 int (*port_stp_update)(struct dsa_switch *ds, int port,
287 u8 state);
278}; 288};
279 289
280void register_switch_driver(struct dsa_switch_driver *type); 290void register_switch_driver(struct dsa_switch_driver *type);
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 5f8ac404535b..b45206e8dd3e 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -8,6 +8,7 @@ config NET_DSA
8 tristate 8 tristate
9 depends on HAVE_NET_DSA 9 depends on HAVE_NET_DSA
10 select PHYLIB 10 select PHYLIB
11 select NET_SWITCHDEV
11 12
12if NET_DSA 13if NET_DSA
13 14
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 2173402d87e0..9c208f0dab08 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -314,19 +314,15 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
314 * Create network devices for physical switch ports. 314 * Create network devices for physical switch ports.
315 */ 315 */
316 for (i = 0; i < DSA_MAX_PORTS; i++) { 316 for (i = 0; i < DSA_MAX_PORTS; i++) {
317 struct net_device *slave_dev;
318
319 if (!(ds->phys_port_mask & (1 << i))) 317 if (!(ds->phys_port_mask & (1 << i)))
320 continue; 318 continue;
321 319
322 slave_dev = dsa_slave_create(ds, parent, i, pd->port_names[i]); 320 ret = dsa_slave_create(ds, parent, i, pd->port_names[i]);
323 if (slave_dev == NULL) { 321 if (ret < 0) {
324 netdev_err(dst->master_netdev, "[%d]: can't create dsa slave device for port %d(%s)\n", 322 netdev_err(dst->master_netdev, "[%d]: can't create dsa slave device for port %d(%s)\n",
325 index, i, pd->port_names[i]); 323 index, i, pd->port_names[i]);
326 continue; 324 ret = 0;
327 } 325 }
328
329 ds->ports[i] = slave_dev;
330 } 326 }
331 327
332#ifdef CONFIG_NET_DSA_HWMON 328#ifdef CONFIG_NET_DSA_HWMON
@@ -830,6 +826,10 @@ static struct packet_type dsa_pack_type __read_mostly = {
830 .func = dsa_switch_rcv, 826 .func = dsa_switch_rcv,
831}; 827};
832 828
829static struct notifier_block dsa_netdevice_nb __read_mostly = {
830 .notifier_call = dsa_slave_netdevice_event,
831};
832
833#ifdef CONFIG_PM_SLEEP 833#ifdef CONFIG_PM_SLEEP
834static int dsa_suspend(struct device *d) 834static int dsa_suspend(struct device *d)
835{ 835{
@@ -888,6 +888,8 @@ static int __init dsa_init_module(void)
888{ 888{
889 int rc; 889 int rc;
890 890
891 register_netdevice_notifier(&dsa_netdevice_nb);
892
891 rc = platform_driver_register(&dsa_driver); 893 rc = platform_driver_register(&dsa_driver);
892 if (rc) 894 if (rc)
893 return rc; 895 return rc;
@@ -900,6 +902,7 @@ module_init(dsa_init_module);
900 902
901static void __exit dsa_cleanup_module(void) 903static void __exit dsa_cleanup_module(void)
902{ 904{
905 unregister_netdevice_notifier(&dsa_netdevice_nb);
903 dev_remove_pack(&dsa_pack_type); 906 dev_remove_pack(&dsa_pack_type);
904 platform_driver_unregister(&dsa_driver); 907 platform_driver_unregister(&dsa_driver);
905} 908}
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index dc9756d3154c..d5f1f9b862ea 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -45,6 +45,8 @@ struct dsa_slave_priv {
45 int old_link; 45 int old_link;
46 int old_pause; 46 int old_pause;
47 int old_duplex; 47 int old_duplex;
48
49 struct net_device *bridge_dev;
48}; 50};
49 51
50/* dsa.c */ 52/* dsa.c */
@@ -53,11 +55,12 @@ extern char dsa_driver_version[];
53/* slave.c */ 55/* slave.c */
54extern const struct dsa_device_ops notag_netdev_ops; 56extern const struct dsa_device_ops notag_netdev_ops;
55void dsa_slave_mii_bus_init(struct dsa_switch *ds); 57void dsa_slave_mii_bus_init(struct dsa_switch *ds);
56struct net_device *dsa_slave_create(struct dsa_switch *ds, 58int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
57 struct device *parent, 59 int port, char *name);
58 int port, char *name);
59int dsa_slave_suspend(struct net_device *slave_dev); 60int dsa_slave_suspend(struct net_device *slave_dev);
60int dsa_slave_resume(struct net_device *slave_dev); 61int dsa_slave_resume(struct net_device *slave_dev);
62int dsa_slave_netdevice_event(struct notifier_block *unused,
63 unsigned long event, void *ptr);
61 64
62/* tag_dsa.c */ 65/* tag_dsa.c */
63extern const struct dsa_device_ops dsa_netdev_ops; 66extern const struct dsa_device_ops dsa_netdev_ops;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index f23deadf42a0..b5a4d8974b76 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -10,10 +10,13 @@
10 10
11#include <linux/list.h> 11#include <linux/list.h>
12#include <linux/etherdevice.h> 12#include <linux/etherdevice.h>
13#include <linux/netdevice.h>
13#include <linux/phy.h> 14#include <linux/phy.h>
14#include <linux/phy_fixed.h> 15#include <linux/phy_fixed.h>
15#include <linux/of_net.h> 16#include <linux/of_net.h>
16#include <linux/of_mdio.h> 17#include <linux/of_mdio.h>
18#include <net/rtnetlink.h>
19#include <linux/if_bridge.h>
17#include "dsa_priv.h" 20#include "dsa_priv.h"
18 21
19/* slave mii_bus handling ***************************************************/ 22/* slave mii_bus handling ***************************************************/
@@ -60,11 +63,18 @@ static int dsa_slave_init(struct net_device *dev)
60 return 0; 63 return 0;
61} 64}
62 65
66static inline bool dsa_port_is_bridged(struct dsa_slave_priv *p)
67{
68 return !!p->bridge_dev;
69}
70
63static int dsa_slave_open(struct net_device *dev) 71static int dsa_slave_open(struct net_device *dev)
64{ 72{
65 struct dsa_slave_priv *p = netdev_priv(dev); 73 struct dsa_slave_priv *p = netdev_priv(dev);
66 struct net_device *master = p->parent->dst->master_netdev; 74 struct net_device *master = p->parent->dst->master_netdev;
67 struct dsa_switch *ds = p->parent; 75 struct dsa_switch *ds = p->parent;
76 u8 stp_state = dsa_port_is_bridged(p) ?
77 BR_STATE_BLOCKING : BR_STATE_FORWARDING;
68 int err; 78 int err;
69 79
70 if (!(master->flags & IFF_UP)) 80 if (!(master->flags & IFF_UP))
@@ -93,6 +103,9 @@ static int dsa_slave_open(struct net_device *dev)
93 goto clear_promisc; 103 goto clear_promisc;
94 } 104 }
95 105
106 if (ds->drv->port_stp_update)
107 ds->drv->port_stp_update(ds, p->port, stp_state);
108
96 if (p->phy) 109 if (p->phy)
97 phy_start(p->phy); 110 phy_start(p->phy);
98 111
@@ -133,6 +146,9 @@ static int dsa_slave_close(struct net_device *dev)
133 if (ds->drv->port_disable) 146 if (ds->drv->port_disable)
134 ds->drv->port_disable(ds, p->port, p->phy); 147 ds->drv->port_disable(ds, p->port, p->phy);
135 148
149 if (ds->drv->port_stp_update)
150 ds->drv->port_stp_update(ds, p->port, BR_STATE_DISABLED);
151
136 return 0; 152 return 0;
137} 153}
138 154
@@ -194,6 +210,95 @@ static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
194 return -EOPNOTSUPP; 210 return -EOPNOTSUPP;
195} 211}
196 212
213/* Return a bitmask of all ports being currently bridged within a given bridge
214 * device. Note that on leave, the mask will still return the bitmask of ports
215 * currently bridged, prior to port removal, and this is exactly what we want.
216 */
217static u32 dsa_slave_br_port_mask(struct dsa_switch *ds,
218 struct net_device *bridge)
219{
220 struct dsa_slave_priv *p;
221 unsigned int port;
222 u32 mask = 0;
223
224 for (port = 0; port < DSA_MAX_PORTS; port++) {
225 if (!((1 << port) & ds->phys_port_mask))
226 continue;
227
228 if (!ds->ports[port])
229 continue;
230
231 p = netdev_priv(ds->ports[port]);
232
233 if (ds->ports[port]->priv_flags & IFF_BRIDGE_PORT &&
234 p->bridge_dev == bridge)
235 mask |= 1 << port;
236 }
237
238 return mask;
239}
240
241static int dsa_slave_stp_update(struct net_device *dev, u8 state)
242{
243 struct dsa_slave_priv *p = netdev_priv(dev);
244 struct dsa_switch *ds = p->parent;
245 int ret = -EOPNOTSUPP;
246
247 if (ds->drv->port_stp_update)
248 ret = ds->drv->port_stp_update(ds, p->port, state);
249
250 return ret;
251}
252
253static int dsa_slave_bridge_port_join(struct net_device *dev,
254 struct net_device *br)
255{
256 struct dsa_slave_priv *p = netdev_priv(dev);
257 struct dsa_switch *ds = p->parent;
258 int ret = -EOPNOTSUPP;
259
260 p->bridge_dev = br;
261
262 if (ds->drv->port_join_bridge)
263 ret = ds->drv->port_join_bridge(ds, p->port,
264 dsa_slave_br_port_mask(ds, br));
265
266 return ret;
267}
268
269static int dsa_slave_bridge_port_leave(struct net_device *dev)
270{
271 struct dsa_slave_priv *p = netdev_priv(dev);
272 struct dsa_switch *ds = p->parent;
273 int ret = -EOPNOTSUPP;
274
275
276 if (ds->drv->port_leave_bridge)
277 ret = ds->drv->port_leave_bridge(ds, p->port,
278 dsa_slave_br_port_mask(ds, p->bridge_dev));
279
280 p->bridge_dev = NULL;
281
282 /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
283 * so allow it to be in BR_STATE_FORWARDING to be kept functional
284 */
285 dsa_slave_stp_update(dev, BR_STATE_FORWARDING);
286
287 return ret;
288}
289
290static int dsa_slave_parent_id_get(struct net_device *dev,
291 struct netdev_phys_item_id *psid)
292{
293 struct dsa_slave_priv *p = netdev_priv(dev);
294 struct dsa_switch *ds = p->parent;
295
296 psid->id_len = sizeof(ds->index);
297 memcpy(&psid->id, &ds->index, psid->id_len);
298
299 return 0;
300}
301
197static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev) 302static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
198{ 303{
199 struct dsa_slave_priv *p = netdev_priv(dev); 304 struct dsa_slave_priv *p = netdev_priv(dev);
@@ -470,6 +575,8 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
470 .ndo_set_rx_mode = dsa_slave_set_rx_mode, 575 .ndo_set_rx_mode = dsa_slave_set_rx_mode,
471 .ndo_set_mac_address = dsa_slave_set_mac_address, 576 .ndo_set_mac_address = dsa_slave_set_mac_address,
472 .ndo_do_ioctl = dsa_slave_ioctl, 577 .ndo_do_ioctl = dsa_slave_ioctl,
578 .ndo_switch_parent_id_get = dsa_slave_parent_id_get,
579 .ndo_switch_port_stp_update = dsa_slave_stp_update,
473}; 580};
474 581
475static void dsa_slave_adjust_link(struct net_device *dev) 582static void dsa_slave_adjust_link(struct net_device *dev)
@@ -605,9 +712,8 @@ int dsa_slave_resume(struct net_device *slave_dev)
605 return 0; 712 return 0;
606} 713}
607 714
608struct net_device * 715int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
609dsa_slave_create(struct dsa_switch *ds, struct device *parent, 716 int port, char *name)
610 int port, char *name)
611{ 717{
612 struct net_device *master = ds->dst->master_netdev; 718 struct net_device *master = ds->dst->master_netdev;
613 struct net_device *slave_dev; 719 struct net_device *slave_dev;
@@ -617,7 +723,7 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
617 slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name, 723 slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name,
618 NET_NAME_UNKNOWN, ether_setup); 724 NET_NAME_UNKNOWN, ether_setup);
619 if (slave_dev == NULL) 725 if (slave_dev == NULL)
620 return slave_dev; 726 return -ENOMEM;
621 727
622 slave_dev->features = master->vlan_features; 728 slave_dev->features = master->vlan_features;
623 slave_dev->ethtool_ops = &dsa_slave_ethtool_ops; 729 slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
@@ -667,19 +773,63 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
667 ret = dsa_slave_phy_setup(p, slave_dev); 773 ret = dsa_slave_phy_setup(p, slave_dev);
668 if (ret) { 774 if (ret) {
669 free_netdev(slave_dev); 775 free_netdev(slave_dev);
670 return NULL; 776 return ret;
671 } 777 }
672 778
779 ds->ports[port] = slave_dev;
673 ret = register_netdev(slave_dev); 780 ret = register_netdev(slave_dev);
674 if (ret) { 781 if (ret) {
675 netdev_err(master, "error %d registering interface %s\n", 782 netdev_err(master, "error %d registering interface %s\n",
676 ret, slave_dev->name); 783 ret, slave_dev->name);
677 phy_disconnect(p->phy); 784 phy_disconnect(p->phy);
785 ds->ports[port] = NULL;
678 free_netdev(slave_dev); 786 free_netdev(slave_dev);
679 return NULL; 787 return ret;
680 } 788 }
681 789
682 netif_carrier_off(slave_dev); 790 netif_carrier_off(slave_dev);
683 791
684 return slave_dev; 792 return 0;
793}
794
795static bool dsa_slave_dev_check(struct net_device *dev)
796{
797 return dev->netdev_ops == &dsa_slave_netdev_ops;
798}
799
800static int dsa_slave_master_changed(struct net_device *dev)
801{
802 struct net_device *master = netdev_master_upper_dev_get(dev);
803 int err = 0;
804
805 if (master && master->rtnl_link_ops &&
806 !strcmp(master->rtnl_link_ops->kind, "bridge"))
807 err = dsa_slave_bridge_port_join(dev, master);
808 else
809 err = dsa_slave_bridge_port_leave(dev);
810
811 return err;
812}
813
814int dsa_slave_netdevice_event(struct notifier_block *unused,
815 unsigned long event, void *ptr)
816{
817 struct net_device *dev;
818 int err = 0;
819
820 switch (event) {
821 case NETDEV_CHANGEUPPER:
822 dev = netdev_notifier_info_to_dev(ptr);
823 if (!dsa_slave_dev_check(dev))
824 goto out;
825
826 err = dsa_slave_master_changed(dev);
827 if (err)
828 netdev_warn(dev, "failed to reflect master change\n");
829
830 break;
831 }
832
833out:
834 return NOTIFY_DONE;
685} 835}