forked from Minki/linux
mlxsw: spectrum_switchdev: Reduce scope of bridge struct
Some attributes in the global chip struct are only relevant for bridge operation, so encapsulate them in their own struct that isn't exposed to non-bridge code. This will also help us later, when we add more bridge-specific attributes. Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9011b677e7
commit
5f6935c6a4
@ -3312,7 +3312,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
|
||||
mlxsw_sp->bus_info = mlxsw_bus_info;
|
||||
INIT_LIST_HEAD(&mlxsw_sp->fids);
|
||||
INIT_LIST_HEAD(&mlxsw_sp->vfids.list);
|
||||
INIT_LIST_HEAD(&mlxsw_sp->br_mids.list);
|
||||
|
||||
err = mlxsw_sp_base_mac_get(mlxsw_sp);
|
||||
if (err) {
|
||||
@ -3659,21 +3658,26 @@ static void mlxsw_sp_master_bridge_gone_sync(struct mlxsw_sp *mlxsw_sp)
|
||||
static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *br_dev)
|
||||
{
|
||||
return !mlxsw_sp->master_bridge.dev ||
|
||||
mlxsw_sp->master_bridge.dev == br_dev;
|
||||
struct mlxsw_sp_upper *master_bridge = mlxsw_sp_master_bridge(mlxsw_sp);
|
||||
|
||||
return !master_bridge->dev || master_bridge->dev == br_dev;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *br_dev)
|
||||
{
|
||||
mlxsw_sp->master_bridge.dev = br_dev;
|
||||
mlxsw_sp->master_bridge.ref_count++;
|
||||
struct mlxsw_sp_upper *master_bridge = mlxsw_sp_master_bridge(mlxsw_sp);
|
||||
|
||||
master_bridge->dev = br_dev;
|
||||
master_bridge->ref_count++;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
if (--mlxsw_sp->master_bridge.ref_count == 0) {
|
||||
mlxsw_sp->master_bridge.dev = NULL;
|
||||
struct mlxsw_sp_upper *master_bridge = mlxsw_sp_master_bridge(mlxsw_sp);
|
||||
|
||||
if (--master_bridge->ref_count == 0) {
|
||||
master_bridge->dev = NULL;
|
||||
/* It's possible upper VLAN devices are still holding
|
||||
* references to underlying FIDs. Drop the reference
|
||||
* and release the resources if it was the last one.
|
||||
@ -4272,7 +4276,7 @@ static int mlxsw_sp_netdevice_bridge_event(struct net_device *br_dev,
|
||||
if (!is_vlan_dev(upper_dev))
|
||||
return -EINVAL;
|
||||
if (is_vlan_dev(upper_dev) &&
|
||||
br_dev != mlxsw_sp->master_bridge.dev)
|
||||
br_dev != mlxsw_sp_master_bridge(mlxsw_sp)->dev)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NETDEV_CHANGEUPPER:
|
||||
|
@ -149,6 +149,7 @@ struct mlxsw_sp_port_mall_tc_entry {
|
||||
};
|
||||
|
||||
struct mlxsw_sp_sb;
|
||||
struct mlxsw_sp_bridge;
|
||||
struct mlxsw_sp_router;
|
||||
struct mlxsw_sp_acl;
|
||||
struct mlxsw_sp_counter_pool;
|
||||
@ -158,29 +159,16 @@ struct mlxsw_sp {
|
||||
struct list_head list;
|
||||
DECLARE_BITMAP(mapped, MLXSW_SP_VFID_MAX);
|
||||
} vfids;
|
||||
struct {
|
||||
struct list_head list;
|
||||
DECLARE_BITMAP(mapped, MLXSW_SP_MID_MAX);
|
||||
} br_mids;
|
||||
struct list_head fids; /* VLAN-aware bridge FIDs */
|
||||
struct mlxsw_sp_rif **rifs;
|
||||
struct mlxsw_sp_port **ports;
|
||||
struct mlxsw_core *core;
|
||||
const struct mlxsw_bus_info *bus_info;
|
||||
unsigned char base_mac[ETH_ALEN];
|
||||
struct {
|
||||
struct delayed_work dw;
|
||||
#define MLXSW_SP_DEFAULT_LEARNING_INTERVAL 100
|
||||
unsigned int interval; /* ms */
|
||||
} fdb_notify;
|
||||
#define MLXSW_SP_MIN_AGEING_TIME 10
|
||||
#define MLXSW_SP_MAX_AGEING_TIME 1000000
|
||||
#define MLXSW_SP_DEFAULT_AGEING_TIME 300
|
||||
u32 ageing_time;
|
||||
struct mlxsw_sp_upper master_bridge;
|
||||
struct mlxsw_sp_upper *lags;
|
||||
u8 *port_to_module;
|
||||
struct mlxsw_sp_sb *sb;
|
||||
struct mlxsw_sp_bridge *bridge;
|
||||
struct mlxsw_sp_router *router;
|
||||
struct mlxsw_sp_acl *acl;
|
||||
struct {
|
||||
@ -425,6 +413,7 @@ int mlxsw_sp_sb_occ_tc_port_bind_get(struct mlxsw_core_port *mlxsw_core_port,
|
||||
u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells);
|
||||
u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes);
|
||||
|
||||
struct mlxsw_sp_upper *mlxsw_sp_master_bridge(const struct mlxsw_sp *mlxsw_sp);
|
||||
int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp);
|
||||
void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp);
|
||||
int mlxsw_sp_port_vlan_init(struct mlxsw_sp_port *mlxsw_sp_port);
|
||||
|
@ -3193,7 +3193,7 @@ static struct mlxsw_sp_fid *mlxsw_sp_bridge_fid_get(struct mlxsw_sp *mlxsw_sp,
|
||||
|
||||
if (is_vlan_dev(l3_dev))
|
||||
fid = vlan_dev_vlan_id(l3_dev);
|
||||
else if (mlxsw_sp->master_bridge.dev == l3_dev)
|
||||
else if (mlxsw_sp_master_bridge(mlxsw_sp)->dev == l3_dev)
|
||||
fid = 1;
|
||||
else
|
||||
return mlxsw_sp_vfid_find(mlxsw_sp, l3_dev);
|
||||
@ -3389,7 +3389,7 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
|
||||
return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
|
||||
vid);
|
||||
else if (netif_is_bridge_master(real_dev) &&
|
||||
mlxsw_sp->master_bridge.dev == real_dev)
|
||||
mlxsw_sp_master_bridge(mlxsw_sp)->dev == real_dev)
|
||||
return mlxsw_sp_inetaddr_bridge_event(vlan_dev, real_dev,
|
||||
event);
|
||||
|
||||
|
@ -52,6 +52,27 @@
|
||||
#include "core.h"
|
||||
#include "reg.h"
|
||||
|
||||
struct mlxsw_sp_bridge {
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
struct {
|
||||
struct delayed_work dw;
|
||||
#define MLXSW_SP_DEFAULT_LEARNING_INTERVAL 100
|
||||
unsigned int interval; /* ms */
|
||||
} fdb_notify;
|
||||
#define MLXSW_SP_MIN_AGEING_TIME 10
|
||||
#define MLXSW_SP_MAX_AGEING_TIME 1000000
|
||||
#define MLXSW_SP_DEFAULT_AGEING_TIME 300
|
||||
u32 ageing_time;
|
||||
struct mlxsw_sp_upper master_bridge;
|
||||
struct list_head mids_list;
|
||||
DECLARE_BITMAP(mids_bitmap, MLXSW_SP_MID_MAX);
|
||||
};
|
||||
|
||||
struct mlxsw_sp_upper *mlxsw_sp_master_bridge(const struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
return &mlxsw_sp->bridge->master_bridge;
|
||||
}
|
||||
|
||||
static u16 mlxsw_sp_port_vid_to_fid_get(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
u16 vid)
|
||||
{
|
||||
@ -397,7 +418,7 @@ static int mlxsw_sp_ageing_set(struct mlxsw_sp *mlxsw_sp, u32 ageing_time)
|
||||
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdat), sfdat_pl);
|
||||
if (err)
|
||||
return err;
|
||||
mlxsw_sp->ageing_time = ageing_time;
|
||||
mlxsw_sp->bridge->ageing_time = ageing_time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -428,7 +449,8 @@ static int mlxsw_sp_port_attr_br_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||
|
||||
/* SWITCHDEV_TRANS_PREPARE phase */
|
||||
if ((!vlan_enabled) && (mlxsw_sp->master_bridge.dev == orig_dev)) {
|
||||
if ((!vlan_enabled) &&
|
||||
(mlxsw_sp->bridge->master_bridge.dev == orig_dev)) {
|
||||
netdev_err(mlxsw_sp_port->dev, "Bridge must be vlan-aware\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1006,7 +1028,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp *mlxsw_sp,
|
||||
{
|
||||
struct mlxsw_sp_mid *mid;
|
||||
|
||||
list_for_each_entry(mid, &mlxsw_sp->br_mids.list, list) {
|
||||
list_for_each_entry(mid, &mlxsw_sp->bridge->mids_list, list) {
|
||||
if (ether_addr_equal(mid->addr, addr) && mid->fid == fid)
|
||||
return mid;
|
||||
}
|
||||
@ -1020,7 +1042,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_mid *mid;
|
||||
u16 mid_idx;
|
||||
|
||||
mid_idx = find_first_zero_bit(mlxsw_sp->br_mids.mapped,
|
||||
mid_idx = find_first_zero_bit(mlxsw_sp->bridge->mids_bitmap,
|
||||
MLXSW_SP_MID_MAX);
|
||||
if (mid_idx == MLXSW_SP_MID_MAX)
|
||||
return NULL;
|
||||
@ -1029,12 +1051,12 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
|
||||
if (!mid)
|
||||
return NULL;
|
||||
|
||||
set_bit(mid_idx, mlxsw_sp->br_mids.mapped);
|
||||
set_bit(mid_idx, mlxsw_sp->bridge->mids_bitmap);
|
||||
ether_addr_copy(mid->addr, addr);
|
||||
mid->fid = fid;
|
||||
mid->mid = mid_idx;
|
||||
mid->ref_count = 0;
|
||||
list_add_tail(&mid->list, &mlxsw_sp->br_mids.list);
|
||||
list_add_tail(&mid->list, &mlxsw_sp->bridge->mids_list);
|
||||
|
||||
return mid;
|
||||
}
|
||||
@ -1044,7 +1066,7 @@ static int __mlxsw_sp_mc_dec_ref(struct mlxsw_sp *mlxsw_sp,
|
||||
{
|
||||
if (--mid->ref_count == 0) {
|
||||
list_del(&mid->list);
|
||||
clear_bit(mid->mid, mlxsw_sp->br_mids.mapped);
|
||||
clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
|
||||
kfree(mid);
|
||||
return 1;
|
||||
}
|
||||
@ -1600,12 +1622,15 @@ static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp,
|
||||
|
||||
static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
mlxsw_core_schedule_dw(&mlxsw_sp->fdb_notify.dw,
|
||||
msecs_to_jiffies(mlxsw_sp->fdb_notify.interval));
|
||||
struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
|
||||
|
||||
mlxsw_core_schedule_dw(&bridge->fdb_notify.dw,
|
||||
msecs_to_jiffies(bridge->fdb_notify.interval));
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
|
||||
{
|
||||
struct mlxsw_sp_bridge *bridge;
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
char *sfn_pl;
|
||||
u8 num_rec;
|
||||
@ -1616,7 +1641,8 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
|
||||
if (!sfn_pl)
|
||||
return;
|
||||
|
||||
mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work);
|
||||
bridge = container_of(work, struct mlxsw_sp_bridge, fdb_notify.dw.work);
|
||||
mlxsw_sp = bridge->mlxsw_sp;
|
||||
|
||||
rtnl_lock();
|
||||
mlxsw_reg_sfn_pack(sfn_pl);
|
||||
@ -1637,6 +1663,7 @@ out:
|
||||
|
||||
static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
|
||||
int err;
|
||||
|
||||
err = mlxsw_sp_ageing_set(mlxsw_sp, MLXSW_SP_DEFAULT_AGEING_TIME);
|
||||
@ -1644,25 +1671,37 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
|
||||
dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n");
|
||||
return err;
|
||||
}
|
||||
INIT_DELAYED_WORK(&mlxsw_sp->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
|
||||
mlxsw_sp->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
|
||||
INIT_DELAYED_WORK(&bridge->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
|
||||
bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
|
||||
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
cancel_delayed_work_sync(&mlxsw_sp->fdb_notify.dw);
|
||||
cancel_delayed_work_sync(&mlxsw_sp->bridge->fdb_notify.dw);
|
||||
}
|
||||
|
||||
int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct mlxsw_sp_bridge *bridge;
|
||||
|
||||
bridge = kzalloc(sizeof(*mlxsw_sp->bridge), GFP_KERNEL);
|
||||
if (!bridge)
|
||||
return -ENOMEM;
|
||||
mlxsw_sp->bridge = bridge;
|
||||
bridge->mlxsw_sp = mlxsw_sp;
|
||||
|
||||
INIT_LIST_HEAD(&mlxsw_sp->bridge->mids_list);
|
||||
|
||||
return mlxsw_sp_fdb_init(mlxsw_sp);
|
||||
}
|
||||
|
||||
void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
mlxsw_sp_fdb_fini(mlxsw_sp);
|
||||
WARN_ON(!list_empty(&mlxsw_sp->bridge->mids_list));
|
||||
kfree(mlxsw_sp->bridge);
|
||||
}
|
||||
|
||||
void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port)
|
||||
|
Loading…
Reference in New Issue
Block a user