summaryrefslogtreecommitdiff
path: root/drivers/net/dsa/mv88e6xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx.c')
-rw-r--r--drivers/net/dsa/mv88e6xxx.c110
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)
{