Commit 194fea7b authored by Vivien Didelot's avatar Vivien Didelot Committed by David S. Miller

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: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a08df0f0
...@@ -1091,7 +1091,7 @@ int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) ...@@ -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; ps->bridge_mask[fid] = br_port_mask;
if (fid != ps->fid[port]) { if (fid != ps->fid[port]) {
ps->fid_mask |= 1 << ps->fid[port]; clear_bit(ps->fid[port], ps->fid_bitmap);
ps->fid[port] = fid; ps->fid[port] = fid;
ret = _mv88e6xxx_update_bridge_config(ds, 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) ...@@ -1125,9 +1125,16 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
mutex_lock(&ps->smi_mutex); 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[port] = newfid;
ps->fid_mask &= ~(1 << newfid); set_bit(newfid, ps->fid_bitmap);
ps->bridge_mask[fid] &= ~(1 << port); ps->bridge_mask[fid] &= ~(1 << port);
ps->bridge_mask[newfid] = 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) ...@@ -1135,6 +1142,7 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
if (!ret) if (!ret)
ret = _mv88e6xxx_update_bridge_config(ds, newfid); ret = _mv88e6xxx_update_bridge_config(ds, newfid);
unlock:
mutex_unlock(&ps->smi_mutex); mutex_unlock(&ps->smi_mutex);
return ret; return ret;
...@@ -1552,9 +1560,9 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) ...@@ -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 * ports, and allow each of the 'real' ports to only talk to
* the upstream port. * the upstream port.
*/ */
fid = __ffs(ps->fid_mask); fid = port + 1;
ps->fid[port] = fid; ps->fid[port] = fid;
ps->fid_mask &= ~(1 << fid); set_bit(fid, ps->fid_bitmap);
if (!dsa_is_cpu_port(ds, port)) if (!dsa_is_cpu_port(ds, port))
ps->bridge_mask[fid] = 1 << port; ps->bridge_mask[fid] = 1 << port;
...@@ -1853,8 +1861,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) ...@@ -1853,8 +1861,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; 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); INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
name = kasprintf(GFP_KERNEL, "dsa%d", ds->index); name = kasprintf(GFP_KERNEL, "dsa%d", ds->index);
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#ifndef __MV88E6XXX_H #ifndef __MV88E6XXX_H
#define __MV88E6XXX_H #define __MV88E6XXX_H
#include <linux/if_vlan.h>
#ifndef UINT64_MAX #ifndef UINT64_MAX
#define UINT64_MAX (u64)(~((u64)0)) #define UINT64_MAX (u64)(~((u64)0))
#endif #endif
...@@ -352,9 +354,9 @@ struct mv88e6xxx_priv_state { ...@@ -352,9 +354,9 @@ struct mv88e6xxx_priv_state {
/* hw bridging */ /* hw bridging */
u32 fid_mask; DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */
u8 fid[DSA_MAX_PORTS]; u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */
u16 bridge_mask[DSA_MAX_PORTS]; u16 bridge_mask[DSA_MAX_PORTS]; /* br groups (indexed by FID) */
unsigned long port_state_update_mask; unsigned long port_state_update_mask;
u8 port_state[DSA_MAX_PORTS]; u8 port_state[DSA_MAX_PORTS];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment