diff options
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx')
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/Kconfig | 13 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/Makefile | 6 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 627 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.h | 11 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/global1.h | 4 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/global1_vtu.c | 69 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/global2.c | 8 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/global2.h | 187 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/port.c | 73 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/port.h | 24 |
10 files changed, 589 insertions, 433 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/Kconfig b/drivers/net/dsa/mv88e6xxx/Kconfig index 51185e4d7d15..05af632b0f59 100644 --- a/drivers/net/dsa/mv88e6xxx/Kconfig +++ b/drivers/net/dsa/mv88e6xxx/Kconfig @@ -9,23 +9,10 @@ config NET_DSA_MV88E6XXX This driver adds support for most of the Marvell 88E6xxx models of Ethernet switch chips, except 88E6060. -config NET_DSA_MV88E6XXX_GLOBAL2 - bool "Switch Global 2 Registers support" - default y - depends on NET_DSA_MV88E6XXX - help - This registers set at internal SMI address 0x1C provides extended - features like EEPROM interface, trunking, cross-chip setup, etc. - - It is required on most chips. If the chip you compile the support for - doesn't have such registers set, say N here. In doubt, say Y. - config NET_DSA_MV88E6XXX_PTP bool "PTP support for Marvell 88E6xxx" default n - depends on NET_DSA_MV88E6XXX_GLOBAL2 depends on PTP_1588_CLOCK - imply NETWORK_PHY_TIMESTAMPING help Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch chips that support it. diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile index 4b080b448ce7..c8eca2b6f959 100644 --- a/drivers/net/dsa/mv88e6xxx/Makefile +++ b/drivers/net/dsa/mv88e6xxx/Makefile @@ -5,9 +5,9 @@ mv88e6xxx-objs += devlink.o mv88e6xxx-objs += global1.o mv88e6xxx-objs += global1_atu.o mv88e6xxx-objs += global1_vtu.o -mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o -mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2_avb.o -mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2_scratch.o +mv88e6xxx-objs += global2.o +mv88e6xxx-objs += global2_avb.o +mv88e6xxx-objs += global2_scratch.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o mv88e6xxx-objs += phy.o mv88e6xxx-objs += port.o diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 54aa942eedaa..903d619e08ed 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1396,15 +1396,32 @@ static int mv88e6xxx_mac_setup(struct mv88e6xxx_chip *chip) static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port) { + struct dsa_switch_tree *dst = chip->ds->dst; + struct dsa_switch *ds; + struct dsa_port *dp; u16 pvlan = 0; if (!mv88e6xxx_has_pvt(chip)) return 0; /* Skip the local source device, which uses in-chip port VLAN */ - if (dev != chip->ds->index) + if (dev != chip->ds->index) { pvlan = mv88e6xxx_port_vlan(chip, dev, port); + ds = dsa_switch_find(dst->index, dev); + dp = ds ? dsa_to_port(ds, port) : NULL; + if (dp && dp->lag_dev) { + /* As the PVT is used to limit flooding of + * FORWARD frames, which use the LAG ID as the + * source port, we must translate dev/port to + * the special "LAG device" in the PVT, using + * the LAG ID as the port number. + */ + dev = MV88E6XXX_G2_PVT_ADRR_DEV_TRUNK; + port = dsa_lag_id(dst, dp->lag_dev); + } + } + return mv88e6xxx_g2_pvt_write(chip, dev, port, pvlan); } @@ -1529,72 +1546,70 @@ static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid) } static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, - u16 vid_begin, u16 vid_end) + u16 vid) { struct mv88e6xxx_chip *chip = ds->priv; struct mv88e6xxx_vtu_entry vlan; int i, err; + if (!vid) + return -EOPNOTSUPP; + /* DSA and CPU ports have to be members of multiple vlans */ if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) return 0; - if (!vid_begin) - return -EOPNOTSUPP; - - vlan.vid = vid_begin - 1; + vlan.vid = vid - 1; vlan.valid = false; - do { - err = mv88e6xxx_vtu_getnext(chip, &vlan); - if (err) - return err; + err = mv88e6xxx_vtu_getnext(chip, &vlan); + if (err) + return err; - if (!vlan.valid) - break; + if (!vlan.valid) + return 0; - if (vlan.vid > vid_end) - break; + if (vlan.vid != vid) + return 0; - for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { - if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i)) - continue; + for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { + if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i)) + continue; - if (!dsa_to_port(ds, i)->slave) - continue; + if (!dsa_to_port(ds, i)->slave) + continue; - if (vlan.member[i] == - MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) - continue; + if (vlan.member[i] == + MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER) + continue; - if (dsa_to_port(ds, i)->bridge_dev == - dsa_to_port(ds, port)->bridge_dev) - break; /* same bridge, check next VLAN */ + if (dsa_to_port(ds, i)->bridge_dev == + dsa_to_port(ds, port)->bridge_dev) + break; /* same bridge, check next VLAN */ - if (!dsa_to_port(ds, i)->bridge_dev) - continue; + if (!dsa_to_port(ds, i)->bridge_dev) + continue; - dev_err(ds->dev, "p%d: hw VLAN %d already used by port %d in %s\n", - port, vlan.vid, i, - netdev_name(dsa_to_port(ds, i)->bridge_dev)); - return -EOPNOTSUPP; - } - } while (vlan.vid < vid_end); + dev_err(ds->dev, "p%d: hw VLAN %d already used by port %d in %s\n", + port, vlan.vid, i, + netdev_name(dsa_to_port(ds, i)->bridge_dev)); + return -EOPNOTSUPP; + } return 0; } static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, - struct switchdev_trans *trans) + struct netlink_ext_ack *extack) { struct mv88e6xxx_chip *chip = ds->priv; u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE : MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED; int err; - if (switchdev_trans_ph_prepare(trans)) - return mv88e6xxx_max_vid(chip) ? 0 : -EOPNOTSUPP; + if (!mv88e6xxx_max_vid(chip)) + return -EOPNOTSUPP; mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_set_8021q_mode(chip, port, mode); @@ -1617,13 +1632,9 @@ mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, * members, do not support it (yet) and fallback to software VLAN. */ mv88e6xxx_reg_lock(chip); - err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid_begin, - vlan->vid_end); + err = mv88e6xxx_port_check_hw_vlan(ds, port, vlan->vid); mv88e6xxx_reg_unlock(chip); - /* We don't need any dynamic resource from the kernel (yet), - * so skip the prepare phase. - */ return err; } @@ -1927,9 +1938,6 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, struct mv88e6xxx_vtu_entry vlan; int i, err; - if (!vid) - return -EOPNOTSUPP; - vlan.vid = vid - 1; vlan.valid = false; @@ -1974,18 +1982,20 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, return 0; } -static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan) +static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) { struct mv88e6xxx_chip *chip = ds->priv; bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; bool warn; u8 member; - u16 vid; + int err; - if (!mv88e6xxx_max_vid(chip)) - return; + err = mv88e6xxx_port_vlan_prepare(ds, port, vlan); + if (err) + return err; if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_UNMODIFIED; @@ -2001,16 +2011,25 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, mv88e6xxx_reg_lock(chip); - for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) - if (mv88e6xxx_port_vlan_join(chip, port, vid, member, warn)) - dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port, - vid, untagged ? 'u' : 't'); - - if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end)) - dev_err(ds->dev, "p%d: failed to set PVID %d\n", port, - vlan->vid_end); + err = mv88e6xxx_port_vlan_join(chip, port, vlan->vid, member, warn); + if (err) { + dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port, + vlan->vid, untagged ? 'u' : 't'); + goto out; + } + if (pvid) { + err = mv88e6xxx_port_set_pvid(chip, port, vlan->vid); + if (err) { + dev_err(ds->dev, "p%d: failed to set PVID %d\n", + port, vlan->vid); + goto out; + } + } +out: mv88e6xxx_reg_unlock(chip); + + return err; } static int mv88e6xxx_port_vlan_leave(struct mv88e6xxx_chip *chip, @@ -2059,8 +2078,8 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { struct mv88e6xxx_chip *chip = ds->priv; - u16 pvid, vid; int err = 0; + u16 pvid; if (!mv88e6xxx_max_vid(chip)) return -EOPNOTSUPP; @@ -2071,16 +2090,14 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, if (err) goto unlock; - for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { - err = mv88e6xxx_port_vlan_leave(chip, port, vid); + err = mv88e6xxx_port_vlan_leave(chip, port, vlan->vid); + if (err) + goto unlock; + + if (vlan->vid == pvid) { + err = mv88e6xxx_port_set_pvid(chip, port, 0); if (err) goto unlock; - - if (vid == pvid) { - err = mv88e6xxx_port_set_pvid(chip, port, 0); - if (err) - goto unlock; - } } unlock: @@ -2419,12 +2436,20 @@ static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port) { struct dsa_switch *ds = chip->ds; bool flood; + int err; /* Upstream ports flood frames with unknown unicast or multicast DA */ flood = dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port); - if (chip->info->ops->port_set_egress_floods) - return chip->info->ops->port_set_egress_floods(chip, port, - flood, flood); + if (chip->info->ops->port_set_ucast_flood) { + err = chip->info->ops->port_set_ucast_flood(chip, port, flood); + if (err) + return err; + } + if (chip->info->ops->port_set_mcast_flood) { + err = chip->info->ops->port_set_mcast_flood(chip, port, flood); + if (err) + return err; + } return 0; } @@ -2864,7 +2889,6 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) chip->ds = ds; ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip); - ds->configure_vlan_while_not_filtering = true; mv88e6xxx_reg_lock(chip); @@ -3225,7 +3249,8 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, .port_pause_limit = mv88e6097_port_pause_limit, @@ -3264,7 +3289,8 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .port_sync_link = mv88e6185_port_sync_link, .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_set_frame_mode = mv88e6085_port_set_frame_mode, - .port_set_egress_floods = mv88e6185_port_set_egress_floods, + .port_set_ucast_flood = mv88e6185_port_set_forward_unknown, + .port_set_mcast_flood = mv88e6185_port_set_default_forward, .port_set_upstream_port = mv88e6095_port_set_upstream_port, .port_get_cmode = mv88e6185_port_get_cmode, .port_setup_message_port = mv88e6xxx_setup_message_port, @@ -3299,7 +3325,8 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting, .port_pause_limit = mv88e6097_port_pause_limit, @@ -3343,7 +3370,8 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .port_sync_link = mv88e6xxx_port_sync_link, .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_set_frame_mode = mv88e6085_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, .port_get_cmode = mv88e6185_port_get_cmode, @@ -3379,7 +3407,8 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6185_port_set_egress_floods, + .port_set_ucast_flood = mv88e6185_port_set_forward_unknown, + .port_set_mcast_flood = mv88e6185_port_set_default_forward, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_upstream_port = mv88e6095_port_set_upstream_port, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, @@ -3423,7 +3452,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { .port_max_speed_mode = mv88e6341_port_max_speed_mode, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -3473,7 +3503,8 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -3551,7 +3582,8 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -3595,7 +3627,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .port_tag_remap = mv88e6095_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -3646,7 +3679,8 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -3690,7 +3724,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .port_tag_remap = mv88e6095_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -3741,7 +3776,8 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .port_sync_link = mv88e6185_port_sync_link, .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_set_frame_mode = mv88e6085_port_set_frame_mode, - .port_set_egress_floods = mv88e6185_port_set_egress_floods, + .port_set_ucast_flood = mv88e6185_port_set_forward_unknown, + .port_set_mcast_flood = mv88e6185_port_set_default_forward, .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting, .port_set_upstream_port = mv88e6095_port_set_upstream_port, .port_set_pause = mv88e6185_port_set_pause, @@ -3786,7 +3822,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_pause_limit = mv88e6390_port_pause_limit, @@ -3846,7 +3883,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_pause_limit = mv88e6390_port_pause_limit, @@ -3905,7 +3943,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .port_max_speed_mode = mv88e6390_port_max_speed_mode, .port_tag_remap = mv88e6390_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_pause_limit = mv88e6390_port_pause_limit, .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, @@ -3965,7 +4004,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .port_tag_remap = mv88e6095_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -4023,7 +4063,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = { .port_set_speed_duplex = mv88e6250_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, .port_pause_limit = mv88e6097_port_pause_limit, @@ -4039,8 +4080,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = { .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, .pot_clear = mv88e6xxx_g2_pot_clear, .reset = mv88e6250_g1_reset, - .vtu_getnext = mv88e6250_g1_vtu_getnext, - .vtu_loadpurge = mv88e6250_g1_vtu_loadpurge, + .vtu_getnext = mv88e6185_g1_vtu_getnext, + .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6250_ptp_ops, .phylink_validate = mv88e6065_phylink_validate, @@ -4063,7 +4104,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_pause_limit = mv88e6390_port_pause_limit, .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, @@ -4122,7 +4164,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -4165,7 +4208,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -4208,7 +4252,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { .port_max_speed_mode = mv88e6341_port_max_speed_mode, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -4261,7 +4306,8 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -4302,7 +4348,8 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -4348,7 +4395,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .port_tag_remap = mv88e6095_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -4410,7 +4458,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -4474,7 +4523,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .port_tag_remap = mv88e6390_port_tag_remap, .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, - .port_set_egress_floods = mv88e6352_port_set_egress_floods, + .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, + .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, .port_set_ether_type = mv88e6351_port_set_ether_type, .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, @@ -5217,10 +5267,6 @@ static int mv88e6xxx_detect(struct mv88e6xxx_chip *chip) /* Update the compatible info with the probed one */ chip->info = info; - err = mv88e6xxx_g2_require(chip); - if (err) - return err; - dev_info(chip->dev, "switch 0x%x detected: %s, revision %u\n", chip->info->prod_num, chip->info->name, rev); @@ -5253,27 +5299,18 @@ static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds, return chip->info->tag_protocol; } -static int mv88e6xxx_port_mdb_prepare(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_mdb *mdb) -{ - /* We don't need any dynamic resource from the kernel (yet), - * so skip the prepare phase. - */ - - return 0; -} - -static void mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_mdb *mdb) +static int mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb) { struct mv88e6xxx_chip *chip = ds->priv; + int err; mv88e6xxx_reg_lock(chip); - if (mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, - MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC)) - dev_err(ds->dev, "p%d: failed to load multicast MAC address\n", - port); + err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, + MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC); mv88e6xxx_reg_unlock(chip); + + return err; } static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port, @@ -5363,22 +5400,346 @@ static void mv88e6xxx_port_mirror_del(struct dsa_switch *ds, int port, mutex_unlock(&chip->reg_lock); } -static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port, - bool unicast, bool multicast) +static int mv88e6xxx_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + struct mv88e6xxx_chip *chip = ds->priv; + const struct mv88e6xxx_ops *ops; + + if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD)) + return -EINVAL; + + ops = chip->info->ops; + + if ((flags.mask & BR_FLOOD) && !ops->port_set_ucast_flood) + return -EINVAL; + + if ((flags.mask & BR_MCAST_FLOOD) && !ops->port_set_mcast_flood) + return -EINVAL; + + return 0; +} + +static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) { struct mv88e6xxx_chip *chip = ds->priv; int err = -EOPNOTSUPP; mv88e6xxx_reg_lock(chip); - if (chip->info->ops->port_set_egress_floods) - err = chip->info->ops->port_set_egress_floods(chip, port, - unicast, - multicast); + + if (flags.mask & BR_FLOOD) { + bool unicast = !!(flags.val & BR_FLOOD); + + err = chip->info->ops->port_set_ucast_flood(chip, port, + unicast); + if (err) + goto out; + } + + if (flags.mask & BR_MCAST_FLOOD) { + bool multicast = !!(flags.val & BR_MCAST_FLOOD); + + err = chip->info->ops->port_set_mcast_flood(chip, port, + multicast); + if (err) + goto out; + } + +out: + mv88e6xxx_reg_unlock(chip); + + return err; +} + +static int mv88e6xxx_port_set_mrouter(struct dsa_switch *ds, int port, + bool mrouter, + struct netlink_ext_ack *extack) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err; + + if (!chip->info->ops->port_set_mcast_flood) + return -EOPNOTSUPP; + + mv88e6xxx_reg_lock(chip); + err = chip->info->ops->port_set_mcast_flood(chip, port, mrouter); + mv88e6xxx_reg_unlock(chip); + + return err; +} + +static bool mv88e6xxx_lag_can_offload(struct dsa_switch *ds, + struct net_device *lag, + struct netdev_lag_upper_info *info) +{ + struct mv88e6xxx_chip *chip = ds->priv; + struct dsa_port *dp; + int id, members = 0; + + if (!mv88e6xxx_has_lag(chip)) + return false; + + id = dsa_lag_id(ds->dst, lag); + if (id < 0 || id >= ds->num_lag_ids) + return false; + + dsa_lag_foreach_port(dp, ds->dst, lag) + /* Includes the port joining the LAG */ + members++; + + if (members > 8) + return false; + + /* We could potentially relax this to include active + * backup in the future. + */ + if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) + return false; + + /* Ideally we would also validate that the hash type matches + * the hardware. Alas, this is always set to unknown on team + * interfaces. + */ + return true; +} + +static int mv88e6xxx_lag_sync_map(struct dsa_switch *ds, struct net_device *lag) +{ + struct mv88e6xxx_chip *chip = ds->priv; + struct dsa_port *dp; + u16 map = 0; + int id; + + id = dsa_lag_id(ds->dst, lag); + + /* Build the map of all ports to distribute flows destined for + * this LAG. This can be either a local user port, or a DSA + * port if the LAG port is on a remote chip. + */ + dsa_lag_foreach_port(dp, ds->dst, lag) + map |= BIT(dsa_towards_port(ds, dp->ds->index, dp->index)); + + return mv88e6xxx_g2_trunk_mapping_write(chip, id, map); +} + +static const u8 mv88e6xxx_lag_mask_table[8][8] = { + /* Row number corresponds to the number of active members in a + * LAG. Each column states which of the eight hash buckets are + * mapped to the column:th port in the LAG. + * + * Example: In a LAG with three active ports, the second port + * ([2][1]) would be selected for traffic mapped to buckets + * 3,4,5 (0x38). + */ + { 0xff, 0, 0, 0, 0, 0, 0, 0 }, + { 0x0f, 0xf0, 0, 0, 0, 0, 0, 0 }, + { 0x07, 0x38, 0xc0, 0, 0, 0, 0, 0 }, + { 0x03, 0x0c, 0x30, 0xc0, 0, 0, 0, 0 }, + { 0x03, 0x0c, 0x30, 0x40, 0x80, 0, 0, 0 }, + { 0x03, 0x0c, 0x10, 0x20, 0x40, 0x80, 0, 0 }, + { 0x03, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0 }, + { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, +}; + +static void mv88e6xxx_lag_set_port_mask(u16 *mask, int port, + int num_tx, int nth) +{ + u8 active = 0; + int i; + + num_tx = num_tx <= 8 ? num_tx : 8; + if (nth < num_tx) + active = mv88e6xxx_lag_mask_table[num_tx - 1][nth]; + + for (i = 0; i < 8; i++) { + if (BIT(i) & active) + mask[i] |= BIT(port); + } +} + +static int mv88e6xxx_lag_sync_masks(struct dsa_switch *ds) +{ + struct mv88e6xxx_chip *chip = ds->priv; + unsigned int id, num_tx; + struct net_device *lag; + struct dsa_port *dp; + int i, err, nth; + u16 mask[8]; + u16 ivec; + + /* Assume no port is a member of any LAG. */ + ivec = BIT(mv88e6xxx_num_ports(chip)) - 1; + + /* Disable all masks for ports that _are_ members of a LAG. */ + list_for_each_entry(dp, &ds->dst->ports, list) { + if (!dp->lag_dev || dp->ds != ds) + continue; + + ivec &= ~BIT(dp->index); + } + + for (i = 0; i < 8; i++) + mask[i] = ivec; + + /* Enable the correct subset of masks for all LAG ports that + * are in the Tx set. + */ + dsa_lags_foreach_id(id, ds->dst) { + lag = dsa_lag_dev(ds->dst, id); + if (!lag) + continue; + + num_tx = 0; + dsa_lag_foreach_port(dp, ds->dst, lag) { + if (dp->lag_tx_enabled) + num_tx++; + } + + if (!num_tx) + continue; + + nth = 0; + dsa_lag_foreach_port(dp, ds->dst, lag) { + if (!dp->lag_tx_enabled) + continue; + + if (dp->ds == ds) + mv88e6xxx_lag_set_port_mask(mask, dp->index, + num_tx, nth); + + nth++; + } + } + + for (i = 0; i < 8; i++) { + err = mv88e6xxx_g2_trunk_mask_write(chip, i, true, mask[i]); + if (err) + return err; + } + + return 0; +} + +static int mv88e6xxx_lag_sync_masks_map(struct dsa_switch *ds, + struct net_device *lag) +{ + int err; + + err = mv88e6xxx_lag_sync_masks(ds); + + if (!err) + err = mv88e6xxx_lag_sync_map(ds, lag); + + return err; +} + +static int mv88e6xxx_port_lag_change(struct dsa_switch *ds, int port) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err; + + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_lag_sync_masks(ds); + mv88e6xxx_reg_unlock(chip); + return err; +} + +static int mv88e6xxx_port_lag_join(struct dsa_switch *ds, int port, + struct net_device *lag, + struct netdev_lag_upper_info *info) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err, id; + + if (!mv88e6xxx_lag_can_offload(ds, lag, info)) + return -EOPNOTSUPP; + + id = dsa_lag_id(ds->dst, lag); + + mv88e6xxx_reg_lock(chip); + + err = mv88e6xxx_port_set_trunk(chip, port, true, id); + if (err) + goto err_unlock; + + err = mv88e6xxx_lag_sync_masks_map(ds, lag); + if (err) + goto err_clear_trunk; + + mv88e6xxx_reg_unlock(chip); + return 0; + +err_clear_trunk: + mv88e6xxx_port_set_trunk(chip, port, false, 0); +err_unlock: + mv88e6xxx_reg_unlock(chip); + return err; +} + +static int mv88e6xxx_port_lag_leave(struct dsa_switch *ds, int port, + struct net_device *lag) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err_sync, err_trunk; + + mv88e6xxx_reg_lock(chip); + err_sync = mv88e6xxx_lag_sync_masks_map(ds, lag); + err_trunk = mv88e6xxx_port_set_trunk(chip, port, false, 0); mv88e6xxx_reg_unlock(chip); + return err_sync ? : err_trunk; +} + +static int mv88e6xxx_crosschip_lag_change(struct dsa_switch *ds, int sw_index, + int port) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err; + + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_lag_sync_masks(ds); + mv88e6xxx_reg_unlock(chip); + return err; +} + +static int mv88e6xxx_crosschip_lag_join(struct dsa_switch *ds, int sw_index, + int port, struct net_device *lag, + struct netdev_lag_upper_info *info) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err; + + if (!mv88e6xxx_lag_can_offload(ds, lag, info)) + return -EOPNOTSUPP; + + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_lag_sync_masks_map(ds, lag); + if (err) + goto unlock; + + err = mv88e6xxx_pvt_map(chip, sw_index, port); + +unlock: + mv88e6xxx_reg_unlock(chip); return err; } +static int mv88e6xxx_crosschip_lag_leave(struct dsa_switch *ds, int sw_index, + int port, struct net_device *lag) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err_sync, err_pvt; + + mv88e6xxx_reg_lock(chip); + err_sync = mv88e6xxx_lag_sync_masks_map(ds, lag); + err_pvt = mv88e6xxx_pvt_map(chip, sw_index, port); + mv88e6xxx_reg_unlock(chip); + return err_sync ? : err_pvt; +} + static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .get_tag_protocol = mv88e6xxx_get_tag_protocol, .setup = mv88e6xxx_setup, @@ -5408,17 +5769,17 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .set_ageing_time = mv88e6xxx_set_ageing_time, .port_bridge_join = mv88e6xxx_port_bridge_join, .port_bridge_leave = mv88e6xxx_port_bridge_leave, - .port_egress_floods = mv88e6xxx_port_egress_floods, + .port_pre_bridge_flags = mv88e6xxx_port_pre_bridge_flags, + .port_bridge_flags = mv88e6xxx_port_bridge_flags, + .port_set_mrouter = mv88e6xxx_port_set_mrouter, .port_stp_state_set = mv88e6xxx_port_stp_state_set, .port_fast_age = mv88e6xxx_port_fast_age, .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, - .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, .port_vlan_add = mv88e6xxx_port_vlan_add, .port_vlan_del = mv88e6xxx_port_vlan_del, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_dump = mv88e6xxx_port_fdb_dump, - .port_mdb_prepare = mv88e6xxx_port_mdb_prepare, .port_mdb_add = mv88e6xxx_port_mdb_add, .port_mdb_del = mv88e6xxx_port_mdb_del, .port_mirror_add = mv88e6xxx_port_mirror_add, @@ -5433,6 +5794,12 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .devlink_param_get = mv88e6xxx_devlink_param_get, .devlink_param_set = mv88e6xxx_devlink_param_set, .devlink_info_get = mv88e6xxx_devlink_info_get, + .port_lag_change = mv88e6xxx_port_lag_change, + .port_lag_join = mv88e6xxx_port_lag_join, + .port_lag_leave = mv88e6xxx_port_lag_leave, + .crosschip_lag_change = mv88e6xxx_crosschip_lag_change, + .crosschip_lag_join = mv88e6xxx_crosschip_lag_join, + .crosschip_lag_leave = mv88e6xxx_crosschip_lag_leave, }; static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip) @@ -5452,6 +5819,12 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip) ds->ageing_time_min = chip->info->age_time_coeff; ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; + /* Some chips support up to 32, but that requires enabling the + * 5-bit port mode, which we do not support. 640k^W16 ought to + * be enough for anyone. + */ + ds->num_lag_ids = mv88e6xxx_has_lag(chip) ? 16 : 0; + dev_set_drvdata(dev, ds); return dsa_register_switch(ds); diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 3543055bcb51..a57c8886f3ac 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -454,8 +454,10 @@ struct mv88e6xxx_ops { int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port, enum mv88e6xxx_frame_mode mode); - int (*port_set_egress_floods)(struct mv88e6xxx_chip *chip, int port, - bool unicast, bool multicast); + int (*port_set_ucast_flood)(struct mv88e6xxx_chip *chip, int port, + bool unicast); + int (*port_set_mcast_flood)(struct mv88e6xxx_chip *chip, int port, + bool multicast); int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port, u16 etype); int (*port_set_jumbo_size)(struct mv88e6xxx_chip *chip, int port, @@ -662,6 +664,11 @@ static inline bool mv88e6xxx_has_pvt(struct mv88e6xxx_chip *chip) return chip->info->pvt; } +static inline bool mv88e6xxx_has_lag(struct mv88e6xxx_chip *chip) +{ + return !!chip->info->global2_addr; +} + static inline unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_chip *chip) { return chip->info->num_databases; diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index 80a182c5b98a..7c396964d0b2 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -336,10 +336,6 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, struct mv88e6xxx_vtu_entry *entry); int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, struct mv88e6xxx_vtu_entry *entry); -int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry); -int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry); int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip, struct mv88e6xxx_vtu_entry *entry); int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, diff --git a/drivers/net/dsa/mv88e6xxx/global1_vtu.c b/drivers/net/dsa/mv88e6xxx/global1_vtu.c index 7b96396be609..ae12c981923e 100644 --- a/drivers/net/dsa/mv88e6xxx/global1_vtu.c +++ b/drivers/net/dsa/mv88e6xxx/global1_vtu.c @@ -336,39 +336,6 @@ int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip, return mv88e6xxx_g1_vtu_vid_read(chip, entry); } -int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) -{ - u16 val; - int err; - - err = mv88e6xxx_g1_vtu_getnext(chip, entry); - if (err) - return err; - - if (entry->valid) { - err = mv88e6185_g1_vtu_data_read(chip, entry); - if (err) - return err; - - err = mv88e6185_g1_stu_data_read(chip, entry); - if (err) - return err; - - /* VTU DBNum[3:0] are located in VTU Operation 3:0 - * VTU DBNum[5:4] are located in VTU Operation 9:8 - */ - err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val); - if (err) - return err; - - entry->fid = val & 0x000f; - entry->fid |= (val & 0x0300) >> 4; - } - - return 0; -} - int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, struct mv88e6xxx_vtu_entry *entry) { @@ -389,7 +356,7 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, return err; /* VTU DBNum[3:0] are located in VTU Operation 3:0 - * VTU DBNum[7:4] are located in VTU Operation 11:8 + * VTU DBNum[7:4] ([5:4] for 6250) are located in VTU Operation 11:8 (9:8) */ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val); if (err) @@ -397,6 +364,7 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, entry->fid = val & 0x000f; entry->fid |= (val & 0x0f00) >> 4; + entry->fid &= mv88e6xxx_num_databases(chip) - 1; } return 0; @@ -466,35 +434,6 @@ int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip, return 0; } -int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) -{ - u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE; - int err; - - err = mv88e6xxx_g1_vtu_op_wait(chip); - if (err) - return err; - - err = mv88e6xxx_g1_vtu_vid_write(chip, entry); - if (err) - return err; - - if (entry->valid) { - err = mv88e6185_g1_vtu_data_write(chip, entry); - if (err) - return err; - - /* VTU DBNum[3:0] are located in VTU Operation 3:0 - * VTU DBNum[5:4] are located in VTU Operation 9:8 - */ - op |= entry->fid & 0x000f; - op |= (entry->fid & 0x0030) << 4; - } - - return mv88e6xxx_g1_vtu_op(chip, op); -} - int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, struct mv88e6xxx_vtu_entry *entry) { @@ -516,6 +455,10 @@ int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, /* VTU DBNum[3:0] are located in VTU Operation 3:0 * VTU DBNum[7:4] are located in VTU Operation 11:8 + * + * For the 6250/6220, the latter are really [5:4] and + * 9:8, but in those cases bits 7:6 of entry->fid are + * 0 since they have num_databases = 64. */ op |= entry->fid & 0x000f; op |= (entry->fid & 0x00f0) << 4; diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index 75b227d0f73b..da8bac8813e1 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -126,8 +126,8 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, /* Offset 0x07: Trunk Mask Table register */ -static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, - bool hash, u16 mask) +int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, + bool hash, u16 mask) { u16 val = (num << 12) | (mask & mv88e6xxx_port_mask(chip)); @@ -140,8 +140,8 @@ static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, /* Offset 0x08: Trunk Mapping Table register */ -static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id, - u16 map) +int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id, + u16 map) { const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1; u16 val = (id << 11) | (map & port_mask); diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index 1f42ee656816..4127f82275ad 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -101,6 +101,7 @@ #define MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN 0x3000 #define MV88E6XXX_G2_PVT_ADDR_OP_READ 0x4000 #define MV88E6XXX_G2_PVT_ADDR_PTR_MASK 0x01ff +#define MV88E6XXX_G2_PVT_ADRR_DEV_TRUNK 0x1f /* Offset 0x0C: Cross-chip Port VLAN Data Register */ #define MV88E6XXX_G2_PVT_DATA 0x0c @@ -295,13 +296,6 @@ #define MV88E6352_G2_SCRATCH_GPIO_PCTL_TRIG 1 #define MV88E6352_G2_SCRATCH_GPIO_PCTL_EVREQ 2 -#ifdef CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 - -static inline int mv88e6xxx_g2_require(struct mv88e6xxx_chip *chip) -{ - return 0; -} - int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val); int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val); int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, int reg, @@ -345,6 +339,10 @@ int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip); +int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num, + bool hash, u16 mask); +int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id, + u16 map); int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip); int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, @@ -365,179 +363,4 @@ int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip, int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip, u16 kind, u16 bin); int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats); -#else /* !CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */ - -static inline int mv88e6xxx_g2_require(struct mv88e6xxx_chip *chip) -{ - if (chip->info->global2_addr) { - dev_err(chip->dev, "this chip requires CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 enabled\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -static inline int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_wait_bit(struct mv88e6xxx_chip *chip, - int reg, int bit, int val) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6352_g2_irl_init_all(struct mv88e6xxx_chip *chip, - int port) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6390_g2_irl_init_all(struct mv88e6xxx_chip *chip, - int port) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, - struct mii_bus *bus, - int addr, int reg, u16 *val) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, - struct mii_bus *bus, - int addr, int reg, u16 val) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, - u8 *addr) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_get_eeprom8(struct mv88e6xxx_chip *chip, - struct ethtool_eeprom *eeprom, - u8 *data) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_set_eeprom8(struct mv88e6xxx_chip *chip, - struct ethtool_eeprom *eeprom, - u8 *data) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip, - struct ethtool_eeprom *eeprom, - u8 *data) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip, - struct ethtool_eeprom *eeprom, - u8 *data) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, - int src_dev, int src_port, u16 data) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) -{ - return -EOPNOTSUPP; -} - -static inline void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip) -{ -} - -static inline int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip, - struct mii_bus *bus) -{ - return 0; -} - -static inline void mv88e6xxx_g2_irq_mdio_free(struct mv88e6xxx_chip *chip, - struct mii_bus *bus) -{ -} - -static inline int mv88e6185_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6352_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip) -{ - return -EOPNOTSUPP; -} - -static const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {}; -static const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = {}; -static const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {}; - -static const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {}; -static const struct mv88e6xxx_avb_ops mv88e6352_avb_ops = {}; -static const struct mv88e6xxx_avb_ops mv88e6390_avb_ops = {}; - -static const struct mv88e6xxx_gpio_ops mv88e6352_gpio_ops = {}; - -static inline int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip, - bool external) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, - int target, int port) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip, - u16 kind, u16 bin) -{ - return -EOPNOTSUPP; -} - -static inline int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, - u16 *stats) -{ - return -EOPNOTSUPP; -} - -#endif /* CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */ - #endif /* _MV88E6XXX_GLOBAL2_H */ diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 77a5fd1798cd..4561f289ab76 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -789,8 +789,8 @@ int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg); } -static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip, - int port, bool unicast) +int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip, + int port, bool unicast) { int err; u16 reg; @@ -807,8 +807,8 @@ static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip, return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg); } -int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port, - bool unicast, bool multicast) +int mv88e6352_port_set_ucast_flood(struct mv88e6xxx_chip *chip, int port, + bool unicast) { int err; u16 reg; @@ -817,16 +817,28 @@ int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port, if (err) return err; - reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_MASK; + if (unicast) + reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_UC; + else + reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_UC; + + return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg); +} + +int mv88e6352_port_set_mcast_flood(struct mv88e6xxx_chip *chip, int port, + bool multicast) +{ + int err; + u16 reg; - if (unicast && multicast) - reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_ALL_UNKNOWN_DA; - else if (unicast) - reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_MC_DA; - else if (multicast) - reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_UC_DA; + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, ®); + if (err) + return err; + + if (multicast) + reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_MC; else - reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_DA; + reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_MC; return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg); } @@ -851,6 +863,27 @@ int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port, return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val); } +int mv88e6xxx_port_set_trunk(struct mv88e6xxx_chip *chip, int port, + bool trunk, u8 id) +{ + u16 val; + int err; + + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1, &val); + if (err) + return err; + + val &= ~MV88E6XXX_PORT_CTL1_TRUNK_ID_MASK; + + if (trunk) + val |= MV88E6XXX_PORT_CTL1_TRUNK_PORT | + (id << MV88E6XXX_PORT_CTL1_TRUNK_ID_SHIFT); + else + val &= ~MV88E6XXX_PORT_CTL1_TRUNK_PORT; + + return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val); +} + /* Offset 0x06: Port Based VLAN Map */ int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) @@ -992,8 +1025,8 @@ static const char * const mv88e6xxx_port_8021q_mode_names[] = { [MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE] = "Secure", }; -static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip, - int port, bool multicast) +int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip, + int port, bool multicast) { int err; u16 reg; @@ -1010,18 +1043,6 @@ static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip, return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg); } -int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port, - bool unicast, bool multicast) -{ - int err; - - err = mv88e6185_port_set_forward_unknown(chip, port, unicast); - if (err) - return err; - - return mv88e6185_port_set_default_forward(chip, port, multicast); -} - int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port, int upstream_port) { diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 500e1d4896ff..e6d0eaa6aa1d 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -154,11 +154,8 @@ #define MV88E6185_PORT_CTL0_USE_IP 0x0020 #define MV88E6185_PORT_CTL0_USE_TAG 0x0010 #define MV88E6185_PORT_CTL0_FORWARD_UNKNOWN 0x0004 -#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_MASK 0x000c -#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_DA 0x0000 -#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_MC_DA 0x0004 -#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_UC_DA 0x0008 -#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_ALL_UNKNOWN_DA 0x000c +#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_UC 0x0004 +#define MV88E6352_PORT_CTL0_EGRESS_FLOODS_MC 0x0008 #define MV88E6XXX_PORT_CTL0_STATE_MASK 0x0003 #define MV88E6XXX_PORT_CTL0_STATE_DISABLED 0x0000 #define MV88E6XXX_PORT_CTL0_STATE_BLOCKING 0x0001 @@ -168,6 +165,9 @@ /* Offset 0x05: Port Control 1 */ #define MV88E6XXX_PORT_CTL1 0x05 #define MV88E6XXX_PORT_CTL1_MESSAGE_PORT 0x8000 +#define MV88E6XXX_PORT_CTL1_TRUNK_PORT 0x4000 +#define MV88E6XXX_PORT_CTL1_TRUNK_ID_MASK 0x0f00 +#define MV88E6XXX_PORT_CTL1_TRUNK_ID_SHIFT 8 #define MV88E6XXX_PORT_CTL1_FID_11_4_MASK 0x00ff /* Offset 0x06: Port Based VLAN Map */ @@ -340,10 +340,14 @@ int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, enum mv88e6xxx_frame_mode mode); int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, enum mv88e6xxx_frame_mode mode); -int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port, - bool unicast, bool multicast); -int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port, - bool unicast, bool multicast); +int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip, + int port, bool unicast); +int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip, + int port, bool multicast); +int mv88e6352_port_set_ucast_flood(struct mv88e6xxx_chip *chip, int port, + bool unicast); +int mv88e6352_port_set_mcast_flood(struct mv88e6xxx_chip *chip, int port, + bool multicast); int mv88e6352_port_set_policy(struct mv88e6xxx_chip *chip, int port, enum mv88e6xxx_policy_mapping mapping, enum mv88e6xxx_policy_action action); @@ -351,6 +355,8 @@ int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, u16 etype); int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port, bool message_port); +int mv88e6xxx_port_set_trunk(struct mv88e6xxx_chip *chip, int port, + bool trunk, u8 id); int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port, size_t size); int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port); |