summaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa/mv88e6xxx.c
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>2015-08-06 01:44:05 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-09 22:48:09 -0700
commit368b1d9c10acf99a855961ae6a1430591ee55f03 (patch)
tree1f0b44291e134fbe05ae318a4bfe5206327fa94f /drivers/net/dsa/mv88e6xxx.c
parent55045ddded0f39d84c2ca019508973be8c595a78 (diff)
downloadtalos-op-linux-368b1d9c10acf99a855961ae6a1430591ee55f03.tar.gz
talos-op-linux-368b1d9c10acf99a855961ae6a1430591ee55f03.zip
net: dsa: mv88e6xxx: extend fid mask
The driver currently manages one FID per port (or bridge group), with a mask of DSA_MAX_PORTS bits, where 0 means that the FID is in use. The Marvell 88E6xxx switches support up to 4094 FIDs (from 1 to 0xfff; FID 0 means that multiple address databases are not being used). This patch changes the fid_mask for an fid_bitmap of 4096 bits. >From now on, FIDs 1 to num_ports are reserved for non-bridged ports and bridge groups (a bridge group gets the FID of its first member). The remaining bits will be reserved for VLAN entries. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx.c')
-rw-r--r--drivers/net/dsa/mv88e6xxx.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 109452056eff..982151e64f43 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1091,7 +1091,7 @@ int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
ps->bridge_mask[fid] = br_port_mask;
if (fid != ps->fid[port]) {
- ps->fid_mask |= 1 << ps->fid[port];
+ clear_bit(ps->fid[port], ps->fid_bitmap);
ps->fid[port] = fid;
ret = _mv88e6xxx_update_bridge_config(ds, fid);
}
@@ -1125,9 +1125,16 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
mutex_lock(&ps->smi_mutex);
- newfid = __ffs(ps->fid_mask);
+ newfid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID, 1);
+ if (unlikely(newfid > ps->num_ports)) {
+ netdev_err(ds->ports[port], "all first %d FIDs are used\n",
+ ps->num_ports);
+ ret = -ENOSPC;
+ goto unlock;
+ }
+
ps->fid[port] = newfid;
- ps->fid_mask &= ~(1 << newfid);
+ set_bit(newfid, ps->fid_bitmap);
ps->bridge_mask[fid] &= ~(1 << port);
ps->bridge_mask[newfid] = 1 << port;
@@ -1135,6 +1142,7 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
if (!ret)
ret = _mv88e6xxx_update_bridge_config(ds, newfid);
+unlock:
mutex_unlock(&ps->smi_mutex);
return ret;
@@ -1552,9 +1560,9 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
* ports, and allow each of the 'real' ports to only talk to
* the upstream port.
*/
- fid = __ffs(ps->fid_mask);
+ fid = port + 1;
ps->fid[port] = fid;
- ps->fid_mask &= ~(1 << fid);
+ set_bit(fid, ps->fid_bitmap);
if (!dsa_is_cpu_port(ds, port))
ps->bridge_mask[fid] = 1 << port;
@@ -1853,8 +1861,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
- ps->fid_mask = (1 << DSA_MAX_PORTS) - 1;
-
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
name = kasprintf(GFP_KERNEL, "dsa%d", ds->index);
OpenPOWER on IntegriCloud