diff options
Diffstat (limited to 'drivers/net/dsa/b53')
| -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/b53/b53_srab.c | 3 |
3 files changed, 74 insertions, 22 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/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c index 90f514252987..d9c56a779c08 100644 --- a/drivers/net/dsa/b53/b53_srab.c +++ b/drivers/net/dsa/b53/b53_srab.c | |||
| @@ -511,9 +511,6 @@ static void b53_srab_prepare_irq(struct platform_device *pdev) | |||
| 511 | /* Clear all pending interrupts */ | 511 | /* Clear all pending interrupts */ |
| 512 | writel(0xffffffff, priv->regs + B53_SRAB_INTR); | 512 | writel(0xffffffff, priv->regs + B53_SRAB_INTR); |
| 513 | 513 | ||
| 514 | if (dev->pdata && dev->pdata->chip_id != BCM58XX_DEVICE_ID) | ||
| 515 | return; | ||
| 516 | |||
| 517 | for (i = 0; i < B53_N_PORTS; i++) { | 514 | for (i = 0; i < B53_N_PORTS; i++) { |
| 518 | port = &priv->port_intrs[i]; | 515 | port = &priv->port_intrs[i]; |
| 519 | 516 | ||
