diff options
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx.c')
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.c | 110 |
1 files changed, 51 insertions, 59 deletions
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 685dcb047979..d98dc635b00b 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1151,19 +1151,6 @@ static int _mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid) return 0; } -int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid) -{ - int ret; - - ret = mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_DEFAULT_VLAN); - if (ret < 0) - return ret; - - *pvid = ret & PORT_DEFAULT_VLAN_MASK; - - return 0; -} - static int _mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 pvid) { return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN, @@ -1306,6 +1293,57 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, return 0; } +int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, + struct switchdev_obj_port_vlan *vlan, + int (*cb)(struct switchdev_obj *obj)) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + struct mv88e6xxx_vtu_stu_entry next; + u16 pvid; + int err; + + mutex_lock(&ps->smi_mutex); + + err = _mv88e6xxx_port_pvid_get(ds, port, &pvid); + if (err) + goto unlock; + + err = _mv88e6xxx_vtu_vid_write(ds, GLOBAL_VTU_VID_MASK); + if (err) + goto unlock; + + do { + err = _mv88e6xxx_vtu_getnext(ds, &next); + if (err) + break; + + if (!next.valid) + break; + + if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) + continue; + + /* reinit and dump this VLAN obj */ + vlan->vid_begin = vlan->vid_end = next.vid; + vlan->flags = 0; + + if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED) + vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED; + + if (next.vid == pvid) + vlan->flags |= BRIDGE_VLAN_INFO_PVID; + + err = cb(&vlan->obj); + if (err) + break; + } while (next.vid < GLOBAL_VTU_VID_MASK); + +unlock: + mutex_unlock(&ps->smi_mutex); + + return err; +} + static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, struct mv88e6xxx_vtu_stu_entry *entry) { @@ -1675,52 +1713,6 @@ unlock: return err; } -int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid, - unsigned long *ports, unsigned long *untagged) -{ - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - struct mv88e6xxx_vtu_stu_entry next; - int port; - int err; - - if (*vid == 4095) - return -ENOENT; - - mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_vtu_vid_write(ds, *vid); - if (err) - goto unlock; - - err = _mv88e6xxx_vtu_getnext(ds, &next); -unlock: - mutex_unlock(&ps->smi_mutex); - - if (err) - return err; - - if (!next.valid) - return -ENOENT; - - *vid = next.vid; - - for (port = 0; port < ps->num_ports; ++port) { - clear_bit(port, ports); - clear_bit(port, untagged); - - if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) - continue; - - if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED || - next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED) - set_bit(port, ports); - - if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED) - set_bit(port, untagged); - } - - return 0; -} - static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, const unsigned char *addr) { |