diff options
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r-- | drivers/net/dsa/b53/b53_common.c | 90 | ||||
-rw-r--r-- | drivers/net/dsa/b53/b53_priv.h | 3 | ||||
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 10 |
3 files changed, 80 insertions, 23 deletions
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 0e4bbdcc614f..c76892ac4e69 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c | |||
@@ -344,7 +344,8 @@ static void b53_set_forwarding(struct b53_device *dev, int enable) | |||
344 | b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt); | 344 | b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt); |
345 | } | 345 | } |
346 | 346 | ||
347 | static void b53_enable_vlan(struct b53_device *dev, bool enable) | 347 | static void b53_enable_vlan(struct b53_device *dev, bool enable, |
348 | bool enable_filtering) | ||
348 | { | 349 | { |
349 | u8 mgmt, vc0, vc1, vc4 = 0, vc5; | 350 | u8 mgmt, vc0, vc1, vc4 = 0, vc5; |
350 | 351 | ||
@@ -369,8 +370,13 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable) | |||
369 | vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID; | 370 | vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID; |
370 | vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN; | 371 | vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN; |
371 | vc4 &= ~VC4_ING_VID_CHECK_MASK; | 372 | vc4 &= ~VC4_ING_VID_CHECK_MASK; |
372 | vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S; | 373 | if (enable_filtering) { |
373 | vc5 |= VC5_DROP_VTABLE_MISS; | 374 | vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S; |
375 | vc5 |= VC5_DROP_VTABLE_MISS; | ||
376 | } else { | ||
377 | vc4 |= VC4_ING_VID_VIO_FWD << VC4_ING_VID_CHECK_S; | ||
378 | vc5 &= ~VC5_DROP_VTABLE_MISS; | ||
379 | } | ||
374 | 380 | ||
375 | if (is5325(dev)) | 381 | if (is5325(dev)) |
376 | vc0 &= ~VC0_RESERVED_1; | 382 | vc0 &= ~VC0_RESERVED_1; |
@@ -420,6 +426,9 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable) | |||
420 | } | 426 | } |
421 | 427 | ||
422 | b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); | 428 | b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); |
429 | |||
430 | dev->vlan_enabled = enable; | ||
431 | dev->vlan_filtering_enabled = enable_filtering; | ||
423 | } | 432 | } |
424 | 433 | ||
425 | static int b53_set_jumbo(struct b53_device *dev, bool enable, bool allow_10_100) | 434 | static int b53_set_jumbo(struct b53_device *dev, bool enable, bool allow_10_100) |
@@ -632,25 +641,35 @@ static void b53_enable_mib(struct b53_device *dev) | |||
632 | b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc); | 641 | b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc); |
633 | } | 642 | } |
634 | 643 | ||
644 | static u16 b53_default_pvid(struct b53_device *dev) | ||
645 | { | ||
646 | if (is5325(dev) || is5365(dev)) | ||
647 | return 1; | ||
648 | else | ||
649 | return 0; | ||
650 | } | ||
651 | |||
635 | int b53_configure_vlan(struct dsa_switch *ds) | 652 | int b53_configure_vlan(struct dsa_switch *ds) |
636 | { | 653 | { |
637 | struct b53_device *dev = ds->priv; | 654 | struct b53_device *dev = ds->priv; |
638 | struct b53_vlan vl = { 0 }; | 655 | struct b53_vlan vl = { 0 }; |
639 | int i; | 656 | int i, def_vid; |
657 | |||
658 | def_vid = b53_default_pvid(dev); | ||
640 | 659 | ||
641 | /* clear all vlan entries */ | 660 | /* clear all vlan entries */ |
642 | if (is5325(dev) || is5365(dev)) { | 661 | if (is5325(dev) || is5365(dev)) { |
643 | for (i = 1; i < dev->num_vlans; i++) | 662 | for (i = def_vid; i < dev->num_vlans; i++) |
644 | b53_set_vlan_entry(dev, i, &vl); | 663 | b53_set_vlan_entry(dev, i, &vl); |
645 | } else { | 664 | } else { |
646 | b53_do_vlan_op(dev, VTA_CMD_CLEAR); | 665 | b53_do_vlan_op(dev, VTA_CMD_CLEAR); |
647 | } | 666 | } |
648 | 667 | ||
649 | b53_enable_vlan(dev, false); | 668 | b53_enable_vlan(dev, false, dev->vlan_filtering_enabled); |
650 | 669 | ||
651 | b53_for_each_port(dev, i) | 670 | b53_for_each_port(dev, i) |
652 | b53_write16(dev, B53_VLAN_PAGE, | 671 | b53_write16(dev, B53_VLAN_PAGE, |
653 | B53_VLAN_PORT_DEF_TAG(i), 1); | 672 | B53_VLAN_PORT_DEF_TAG(i), def_vid); |
654 | 673 | ||
655 | if (!is5325(dev) && !is5365(dev)) | 674 | if (!is5325(dev) && !is5365(dev)) |
656 | b53_set_jumbo(dev, dev->enable_jumbo, false); | 675 | b53_set_jumbo(dev, dev->enable_jumbo, false); |
@@ -1255,6 +1274,46 @@ EXPORT_SYMBOL(b53_phylink_mac_link_up); | |||
1255 | 1274 | ||
1256 | int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) | 1275 | int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) |
1257 | { | 1276 | { |
1277 | struct b53_device *dev = ds->priv; | ||
1278 | struct net_device *bridge_dev; | ||
1279 | unsigned int i; | ||
1280 | u16 pvid, new_pvid; | ||
1281 | |||
1282 | /* Handle the case were multiple bridges span the same switch device | ||
1283 | * and one of them has a different setting than what is being requested | ||
1284 | * which would be breaking filtering semantics for any of the other | ||
1285 | * bridge devices. | ||
1286 | */ | ||
1287 | b53_for_each_port(dev, i) { | ||
1288 | bridge_dev = dsa_to_port(ds, i)->bridge_dev; | ||
1289 | if (bridge_dev && | ||
1290 | bridge_dev != dsa_to_port(ds, port)->bridge_dev && | ||
1291 | br_vlan_enabled(bridge_dev) != vlan_filtering) { | ||
1292 | netdev_err(bridge_dev, | ||
1293 | "VLAN filtering is global to the switch!\n"); | ||
1294 | return -EINVAL; | ||
1295 | } | ||
1296 | } | ||
1297 | |||
1298 | b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid); | ||
1299 | new_pvid = pvid; | ||
1300 | if (dev->vlan_filtering_enabled && !vlan_filtering) { | ||
1301 | /* Filtering is currently enabled, use the default PVID since | ||
1302 | * the bridge does not expect tagging anymore | ||
1303 | */ | ||
1304 | dev->ports[port].pvid = pvid; | ||
1305 | new_pvid = b53_default_pvid(dev); | ||
1306 | } else if (!dev->vlan_filtering_enabled && vlan_filtering) { | ||
1307 | /* Filtering is currently disabled, restore the previous PVID */ | ||
1308 | new_pvid = dev->ports[port].pvid; | ||
1309 | } | ||
1310 | |||
1311 | if (pvid != new_pvid) | ||
1312 | b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), | ||
1313 | new_pvid); | ||
1314 | |||
1315 | b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering); | ||
1316 | |||
1258 | return 0; | 1317 | return 0; |
1259 | } | 1318 | } |
1260 | EXPORT_SYMBOL(b53_vlan_filtering); | 1319 | EXPORT_SYMBOL(b53_vlan_filtering); |
@@ -1270,7 +1329,7 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port, | |||
1270 | if (vlan->vid_end > dev->num_vlans) | 1329 | if (vlan->vid_end > dev->num_vlans) |
1271 | return -ERANGE; | 1330 | return -ERANGE; |
1272 | 1331 | ||
1273 | b53_enable_vlan(dev, true); | 1332 | b53_enable_vlan(dev, true, dev->vlan_filtering_enabled); |
1274 | 1333 | ||
1275 | return 0; | 1334 | return 0; |
1276 | } | 1335 | } |
@@ -1300,7 +1359,7 @@ void b53_vlan_add(struct dsa_switch *ds, int port, | |||
1300 | b53_fast_age_vlan(dev, vid); | 1359 | b53_fast_age_vlan(dev, vid); |
1301 | } | 1360 | } |
1302 | 1361 | ||
1303 | if (pvid) { | 1362 | if (pvid && !dsa_is_cpu_port(ds, port)) { |
1304 | b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), | 1363 | b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), |
1305 | vlan->vid_end); | 1364 | vlan->vid_end); |
1306 | b53_fast_age_vlan(dev, vid); | 1365 | b53_fast_age_vlan(dev, vid); |
@@ -1326,12 +1385,8 @@ int b53_vlan_del(struct dsa_switch *ds, int port, | |||
1326 | 1385 | ||
1327 | vl->members &= ~BIT(port); | 1386 | vl->members &= ~BIT(port); |
1328 | 1387 | ||
1329 | if (pvid == vid) { | 1388 | if (pvid == vid) |
1330 | if (is5325(dev) || is5365(dev)) | 1389 | pvid = b53_default_pvid(dev); |
1331 | pvid = 1; | ||
1332 | else | ||
1333 | pvid = 0; | ||
1334 | } | ||
1335 | 1390 | ||
1336 | if (untagged && !dsa_is_cpu_port(ds, port)) | 1391 | if (untagged && !dsa_is_cpu_port(ds, port)) |
1337 | vl->untag &= ~(BIT(port)); | 1392 | vl->untag &= ~(BIT(port)); |
@@ -1644,10 +1699,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br) | |||
1644 | b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan); | 1699 | b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan); |
1645 | dev->ports[port].vlan_ctl_mask = pvlan; | 1700 | dev->ports[port].vlan_ctl_mask = pvlan; |
1646 | 1701 | ||
1647 | if (is5325(dev) || is5365(dev)) | 1702 | pvid = b53_default_pvid(dev); |
1648 | pvid = 1; | ||
1649 | else | ||
1650 | pvid = 0; | ||
1651 | 1703 | ||
1652 | /* Make this port join all VLANs without VLAN entries */ | 1704 | /* Make this port join all VLANs without VLAN entries */ |
1653 | if (is58xx(dev)) { | 1705 | if (is58xx(dev)) { |
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index ec796482792d..4dc7ee38b258 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h | |||
@@ -91,6 +91,7 @@ enum { | |||
91 | struct b53_port { | 91 | struct b53_port { |
92 | u16 vlan_ctl_mask; | 92 | u16 vlan_ctl_mask; |
93 | struct ethtool_eee eee; | 93 | struct ethtool_eee eee; |
94 | u16 pvid; | ||
94 | }; | 95 | }; |
95 | 96 | ||
96 | struct b53_vlan { | 97 | struct b53_vlan { |
@@ -137,6 +138,8 @@ struct b53_device { | |||
137 | 138 | ||
138 | unsigned int num_vlans; | 139 | unsigned int num_vlans; |
139 | struct b53_vlan *vlans; | 140 | struct b53_vlan *vlans; |
141 | bool vlan_enabled; | ||
142 | bool vlan_filtering_enabled; | ||
140 | unsigned int num_ports; | 143 | unsigned int num_ports; |
141 | struct b53_port *ports; | 144 | struct b53_port *ports; |
142 | }; | 145 | }; |
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 98696a88fa1c..f91b8e77d543 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c | |||
@@ -726,10 +726,11 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port, | |||
726 | { | 726 | { |
727 | struct net_device *p = ds->ports[port].cpu_dp->master; | 727 | struct net_device *p = ds->ports[port].cpu_dp->master; |
728 | struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); | 728 | struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); |
729 | struct ethtool_wolinfo pwol; | 729 | struct ethtool_wolinfo pwol = { }; |
730 | 730 | ||
731 | /* Get the parent device WoL settings */ | 731 | /* Get the parent device WoL settings */ |
732 | p->ethtool_ops->get_wol(p, &pwol); | 732 | if (p->ethtool_ops->get_wol) |
733 | p->ethtool_ops->get_wol(p, &pwol); | ||
733 | 734 | ||
734 | /* Advertise the parent device supported settings */ | 735 | /* Advertise the parent device supported settings */ |
735 | wol->supported = pwol.supported; | 736 | wol->supported = pwol.supported; |
@@ -750,9 +751,10 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port, | |||
750 | struct net_device *p = ds->ports[port].cpu_dp->master; | 751 | struct net_device *p = ds->ports[port].cpu_dp->master; |
751 | struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); | 752 | struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); |
752 | s8 cpu_port = ds->ports[port].cpu_dp->index; | 753 | s8 cpu_port = ds->ports[port].cpu_dp->index; |
753 | struct ethtool_wolinfo pwol; | 754 | struct ethtool_wolinfo pwol = { }; |
754 | 755 | ||
755 | p->ethtool_ops->get_wol(p, &pwol); | 756 | if (p->ethtool_ops->get_wol) |
757 | p->ethtool_ops->get_wol(p, &pwol); | ||
756 | if (wol->wolopts & ~pwol.supported) | 758 | if (wol->wolopts & ~pwol.supported) |
757 | return -EINVAL; | 759 | return -EINVAL; |
758 | 760 | ||