diff options
Diffstat (limited to 'drivers/net/dsa/b53/b53_common.c')
-rw-r--r-- | drivers/net/dsa/b53/b53_common.c | 204 |
1 files changed, 119 insertions, 85 deletions
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 288b5a5c3e0d..ae86ded1e2a1 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -510,6 +510,39 @@ void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port) } EXPORT_SYMBOL(b53_imp_vlan_setup); +static void b53_port_set_ucast_flood(struct b53_device *dev, int port, + bool unicast) +{ + u16 uc; + + b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc); + if (unicast) + uc |= BIT(port); + else + uc &= ~BIT(port); + b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc); +} + +static void b53_port_set_mcast_flood(struct b53_device *dev, int port, + bool multicast) +{ + u16 mc; + + b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc); + if (multicast) + mc |= BIT(port); + else + mc &= ~BIT(port); + b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc); + + b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc); + if (multicast) + mc |= BIT(port); + else + mc &= ~BIT(port); + b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc); +} + int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) { struct b53_device *dev = ds->priv; @@ -522,7 +555,8 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) cpu_port = dsa_to_port(ds, port)->cpu_dp->index; - b53_br_egress_floods(ds, port, true, true); + b53_port_set_ucast_flood(dev, port, true); + b53_port_set_mcast_flood(dev, port, true); if (dev->ops->irq_enable) ret = dev->ops->irq_enable(dev, port); @@ -655,7 +689,8 @@ static void b53_enable_cpu_port(struct b53_device *dev, int port) b53_brcm_hdr_setup(dev->ds, port); - b53_br_egress_floods(dev->ds, port, true, true); + b53_port_set_ucast_flood(dev, port, true); + b53_port_set_mcast_flood(dev, port, true); } static void b53_enable_mib(struct b53_device *dev) @@ -1375,25 +1410,22 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port, EXPORT_SYMBOL(b53_phylink_mac_link_up); int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, - struct switchdev_trans *trans) + struct netlink_ext_ack *extack) { struct b53_device *dev = ds->priv; - if (switchdev_trans_ph_prepare(trans)) - return 0; - b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering); return 0; } EXPORT_SYMBOL(b53_vlan_filtering); -int b53_vlan_prepare(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan) +static int b53_vlan_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) { struct b53_device *dev = ds->priv; - if ((is5325(dev) || is5365(dev)) && vlan->vid_begin == 0) + if ((is5325(dev) || is5365(dev)) && vlan->vid == 0) return -EOPNOTSUPP; /* Port 7 on 7278 connects to the ASP's UniMAC which is not capable of @@ -1404,47 +1436,51 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port, !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)) return -EINVAL; - if (vlan->vid_end > dev->num_vlans) + if (vlan->vid >= dev->num_vlans) return -ERANGE; b53_enable_vlan(dev, true, ds->vlan_filtering); return 0; } -EXPORT_SYMBOL(b53_vlan_prepare); -void b53_vlan_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan) +int b53_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) { struct b53_device *dev = ds->priv; bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; struct b53_vlan *vl; - u16 vid; + int err; - for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { - vl = &dev->vlans[vid]; + err = b53_vlan_prepare(ds, port, vlan); + if (err) + return err; - b53_get_vlan_entry(dev, vid, vl); + vl = &dev->vlans[vlan->vid]; - if (vid == 0 && vid == b53_default_pvid(dev)) - untagged = true; + b53_get_vlan_entry(dev, vlan->vid, vl); - vl->members |= BIT(port); - if (untagged && !dsa_is_cpu_port(ds, port)) - vl->untag |= BIT(port); - else - vl->untag &= ~BIT(port); + if (vlan->vid == 0 && vlan->vid == b53_default_pvid(dev)) + untagged = true; - b53_set_vlan_entry(dev, vid, vl); - b53_fast_age_vlan(dev, vid); - } + vl->members |= BIT(port); + if (untagged && !dsa_is_cpu_port(ds, port)) + vl->untag |= BIT(port); + else + vl->untag &= ~BIT(port); + + b53_set_vlan_entry(dev, vlan->vid, vl); + b53_fast_age_vlan(dev, vlan->vid); if (pvid && !dsa_is_cpu_port(ds, port)) { b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), - vlan->vid_end); - b53_fast_age_vlan(dev, vid); + vlan->vid); + b53_fast_age_vlan(dev, vlan->vid); } + + return 0; } EXPORT_SYMBOL(b53_vlan_add); @@ -1454,27 +1490,24 @@ int b53_vlan_del(struct dsa_switch *ds, int port, struct b53_device *dev = ds->priv; bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; struct b53_vlan *vl; - u16 vid; u16 pvid; b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid); - for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { - vl = &dev->vlans[vid]; + vl = &dev->vlans[vlan->vid]; - b53_get_vlan_entry(dev, vid, vl); + b53_get_vlan_entry(dev, vlan->vid, vl); - vl->members &= ~BIT(port); + vl->members &= ~BIT(port); - if (pvid == vid) - pvid = b53_default_pvid(dev); + if (pvid == vlan->vid) + pvid = b53_default_pvid(dev); - if (untagged && !dsa_is_cpu_port(ds, port)) - vl->untag &= ~(BIT(port)); + if (untagged && !dsa_is_cpu_port(ds, port)) + vl->untag &= ~(BIT(port)); - b53_set_vlan_entry(dev, vid, vl); - b53_fast_age_vlan(dev, vid); - } + b53_set_vlan_entry(dev, vlan->vid, vl); + b53_fast_age_vlan(dev, vlan->vid); b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), pvid); b53_fast_age_vlan(dev, pvid); @@ -1751,8 +1784,8 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, } EXPORT_SYMBOL(b53_fdb_dump); -int b53_mdb_prepare(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_mdb *mdb) +int b53_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) { struct b53_device *priv = ds->priv; @@ -1762,19 +1795,7 @@ int b53_mdb_prepare(struct dsa_switch *ds, int port, if (is5325(priv) || is5365(priv)) return -EOPNOTSUPP; - return 0; -} -EXPORT_SYMBOL(b53_mdb_prepare); - -void b53_mdb_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_mdb *mdb) -{ - struct b53_device *priv = ds->priv; - int ret; - - ret = b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true); - if (ret) - dev_err(ds->dev, "failed to add MDB entry\n"); + return b53_arl_op(priv, 0, port, mdb->addr, mdb->vid, true); } EXPORT_SYMBOL(b53_mdb_add); @@ -1932,37 +1953,37 @@ void b53_br_fast_age(struct dsa_switch *ds, int port) } EXPORT_SYMBOL(b53_br_fast_age); -int b53_br_egress_floods(struct dsa_switch *ds, int port, - bool unicast, bool multicast) +static int b53_br_flags_pre(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) { - struct b53_device *dev = ds->priv; - u16 uc, mc; - - b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc); - if (unicast) - uc |= BIT(port); - else - uc &= ~BIT(port); - b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc); + if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD)) + return -EINVAL; - b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc); - if (multicast) - mc |= BIT(port); - else - mc &= ~BIT(port); - b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc); + return 0; +} - b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc); - if (multicast) - mc |= BIT(port); - else - mc &= ~BIT(port); - b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc); +static int b53_br_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + if (flags.mask & BR_FLOOD) + b53_port_set_ucast_flood(ds->priv, port, + !!(flags.val & BR_FLOOD)); + if (flags.mask & BR_MCAST_FLOOD) + b53_port_set_mcast_flood(ds->priv, port, + !!(flags.val & BR_MCAST_FLOOD)); return 0; +} + +static int b53_set_mrouter(struct dsa_switch *ds, int port, bool mrouter, + struct netlink_ext_ack *extack) +{ + b53_port_set_mcast_flood(ds->priv, port, mrouter); + return 0; } -EXPORT_SYMBOL(b53_br_egress_floods); static bool b53_possible_cpu_port(struct dsa_switch *ds, int port) { @@ -2203,11 +2224,12 @@ static const struct dsa_switch_ops b53_switch_ops = { .set_mac_eee = b53_set_mac_eee, .port_bridge_join = b53_br_join, .port_bridge_leave = b53_br_leave, + .port_pre_bridge_flags = b53_br_flags_pre, + .port_bridge_flags = b53_br_flags, + .port_set_mrouter = b53_set_mrouter, .port_stp_state_set = b53_br_set_stp_state, .port_fast_age = b53_br_fast_age, - .port_egress_floods = b53_br_egress_floods, .port_vlan_filtering = b53_vlan_filtering, - .port_vlan_prepare = b53_vlan_prepare, .port_vlan_add = b53_vlan_add, .port_vlan_del = b53_vlan_del, .port_fdb_dump = b53_fdb_dump, @@ -2215,7 +2237,6 @@ static const struct dsa_switch_ops b53_switch_ops = { .port_fdb_del = b53_fdb_del, .port_mirror_add = b53_mirror_add, .port_mirror_del = b53_mirror_del, - .port_mdb_prepare = b53_mdb_prepare, .port_mdb_add = b53_mdb_add, .port_mdb_del = b53_mdb_del, .port_max_mtu = b53_get_max_mtu, @@ -2459,6 +2480,20 @@ static const struct b53_chip_data b53_switch_chips[] = { .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, }, + /* Starfighter 2 */ + { + .chip_id = BCM4908_DEVICE_ID, + .dev_name = "BCM4908", + .vlans = 4096, + .enabled_ports = 0x1bf, + .arl_bins = 4, + .arl_buckets = 256, + .cpu_port = 8, /* TODO: ports 4, 5, 8 */ + .vta_regs = B53_VTA_REGS, + .duplex_reg = B53_DUPLEX_STAT_GE, + .jumbo_pm_reg = B53_JUMBO_PORT_MASK, + .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + }, { .chip_id = BCM7445_DEVICE_ID, .dev_name = "BCM7445", @@ -2606,9 +2641,8 @@ struct b53_device *b53_switch_alloc(struct device *base, dev->priv = priv; dev->ops = ops; ds->ops = &b53_switch_ops; - ds->configure_vlan_while_not_filtering = true; ds->untag_bridge_pvid = true; - dev->vlan_enabled = ds->configure_vlan_while_not_filtering; + dev->vlan_enabled = true; mutex_init(&dev->reg_mutex); mutex_init(&dev->stats_mutex); |