Commit b80888a9 authored by Nogah Frankel's avatar Nogah Frankel Committed by David S. Miller

mlxsw: spectrum_switchdev: Save mids list per bridge device

Instead of saving all the mids in the same list, save them per vlan
device. This change allows a more efficient mid find.
Also, in the next patches, there will be added a lot of loops over all the
mids in bridge device for multicast disable, mrouter change and ndb flush.
Signed-off-by: default avatarNogah Frankel <nogahf@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0161b950
...@@ -67,7 +67,6 @@ struct mlxsw_sp_bridge { ...@@ -67,7 +67,6 @@ struct mlxsw_sp_bridge {
u32 ageing_time; u32 ageing_time;
bool vlan_enabled_exists; bool vlan_enabled_exists;
struct list_head bridges_list; struct list_head bridges_list;
struct list_head mids_list;
DECLARE_BITMAP(mids_bitmap, MLXSW_SP_MID_MAX); DECLARE_BITMAP(mids_bitmap, MLXSW_SP_MID_MAX);
const struct mlxsw_sp_bridge_ops *bridge_8021q_ops; const struct mlxsw_sp_bridge_ops *bridge_8021q_ops;
const struct mlxsw_sp_bridge_ops *bridge_8021d_ops; const struct mlxsw_sp_bridge_ops *bridge_8021d_ops;
...@@ -77,6 +76,7 @@ struct mlxsw_sp_bridge_device { ...@@ -77,6 +76,7 @@ struct mlxsw_sp_bridge_device {
struct net_device *dev; struct net_device *dev;
struct list_head list; struct list_head list;
struct list_head ports_list; struct list_head ports_list;
struct list_head mids_list;
u8 vlan_enabled:1, u8 vlan_enabled:1,
multicast_enabled:1; multicast_enabled:1;
const struct mlxsw_sp_bridge_ops *ops; const struct mlxsw_sp_bridge_ops *ops;
...@@ -161,6 +161,7 @@ mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge, ...@@ -161,6 +161,7 @@ mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge,
} else { } else {
bridge_device->ops = bridge->bridge_8021d_ops; bridge_device->ops = bridge->bridge_8021d_ops;
} }
INIT_LIST_HEAD(&bridge_device->mids_list);
list_add(&bridge_device->list, &bridge->bridges_list); list_add(&bridge_device->list, &bridge->bridges_list);
return bridge_device; return bridge_device;
...@@ -170,10 +171,17 @@ static void ...@@ -170,10 +171,17 @@ static void
mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge, mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge,
struct mlxsw_sp_bridge_device *bridge_device) struct mlxsw_sp_bridge_device *bridge_device)
{ {
struct mlxsw_sp_mid *mid, *tmp;
list_del(&bridge_device->list); list_del(&bridge_device->list);
if (bridge_device->vlan_enabled) if (bridge_device->vlan_enabled)
bridge->vlan_enabled_exists = false; bridge->vlan_enabled_exists = false;
WARN_ON(!list_empty(&bridge_device->ports_list)); WARN_ON(!list_empty(&bridge_device->ports_list));
list_for_each_entry_safe(mid, tmp, &bridge_device->mids_list, list) {
list_del(&mid->list);
clear_bit(mid->mid, bridge->mids_bitmap);
kfree(mid);
}
kfree(bridge_device); kfree(bridge_device);
} }
...@@ -1221,20 +1229,23 @@ static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mid, ...@@ -1221,20 +1229,23 @@ static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mid,
return err; return err;
} }
static struct mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp *mlxsw_sp, static struct
mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
const unsigned char *addr, const unsigned char *addr,
u16 fid) u16 fid)
{ {
struct mlxsw_sp_mid *mid; struct mlxsw_sp_mid *mid;
list_for_each_entry(mid, &mlxsw_sp->bridge->mids_list, list) { list_for_each_entry(mid, &bridge_device->mids_list, list) {
if (ether_addr_equal(mid->addr, addr) && mid->fid == fid) if (ether_addr_equal(mid->addr, addr) && mid->fid == fid)
return mid; return mid;
} }
return NULL; return NULL;
} }
static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp, static struct
mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_bridge_device *bridge_device,
const unsigned char *addr, const unsigned char *addr,
u16 fid) u16 fid)
{ {
...@@ -1263,7 +1274,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp, ...@@ -1263,7 +1274,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
ether_addr_copy(mid->addr, addr); ether_addr_copy(mid->addr, addr);
mid->fid = fid; mid->fid = fid;
mid->mid = mid_idx; mid->mid = mid_idx;
list_add_tail(&mid->list, &mlxsw_sp->bridge->mids_list); list_add_tail(&mid->list, &bridge_device->mids_list);
return mid; return mid;
} }
...@@ -1316,9 +1327,10 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1316,9 +1327,10 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid); fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
mid = __mlxsw_sp_mc_get(mlxsw_sp, mdb->addr, fid_index); mid = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
if (!mid) { if (!mid) {
mid = __mlxsw_sp_mc_alloc(mlxsw_sp, mdb->addr, fid_index); mid = __mlxsw_sp_mc_alloc(mlxsw_sp, bridge_device, mdb->addr,
fid_index);
if (!mid) { if (!mid) {
netdev_err(dev, "Unable to allocate MC group\n"); netdev_err(dev, "Unable to allocate MC group\n");
return -ENOMEM; return -ENOMEM;
...@@ -1440,7 +1452,7 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1440,7 +1452,7 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid); fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
mid = __mlxsw_sp_mc_get(mlxsw_sp, mdb->addr, fid_index); mid = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
if (!mid) { if (!mid) {
netdev_err(dev, "Unable to remove port from MC DB\n"); netdev_err(dev, "Unable to remove port from MC DB\n");
return -EINVAL; return -EINVAL;
...@@ -1995,17 +2007,6 @@ static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp) ...@@ -1995,17 +2007,6 @@ static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
} }
static void mlxsw_sp_mids_fini(struct mlxsw_sp *mlxsw_sp)
{
struct mlxsw_sp_mid *mid, *tmp;
list_for_each_entry_safe(mid, tmp, &mlxsw_sp->bridge->mids_list, list) {
list_del(&mid->list);
clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
kfree(mid);
}
}
int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp) int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
{ {
struct mlxsw_sp_bridge *bridge; struct mlxsw_sp_bridge *bridge;
...@@ -2017,7 +2018,6 @@ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp) ...@@ -2017,7 +2018,6 @@ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
bridge->mlxsw_sp = mlxsw_sp; bridge->mlxsw_sp = mlxsw_sp;
INIT_LIST_HEAD(&mlxsw_sp->bridge->bridges_list); INIT_LIST_HEAD(&mlxsw_sp->bridge->bridges_list);
INIT_LIST_HEAD(&mlxsw_sp->bridge->mids_list);
bridge->bridge_8021q_ops = &mlxsw_sp_bridge_8021q_ops; bridge->bridge_8021q_ops = &mlxsw_sp_bridge_8021q_ops;
bridge->bridge_8021d_ops = &mlxsw_sp_bridge_8021d_ops; bridge->bridge_8021d_ops = &mlxsw_sp_bridge_8021d_ops;
...@@ -2028,7 +2028,6 @@ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp) ...@@ -2028,7 +2028,6 @@ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp) void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp)
{ {
mlxsw_sp_fdb_fini(mlxsw_sp); mlxsw_sp_fdb_fini(mlxsw_sp);
mlxsw_sp_mids_fini(mlxsw_sp);
WARN_ON(!list_empty(&mlxsw_sp->bridge->bridges_list)); WARN_ON(!list_empty(&mlxsw_sp->bridge->bridges_list));
kfree(mlxsw_sp->bridge); kfree(mlxsw_sp->bridge);
} }
......
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