Commit 5f6935c6 authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

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: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9011b677
...@@ -3312,7 +3312,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, ...@@ -3312,7 +3312,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->bus_info = mlxsw_bus_info; mlxsw_sp->bus_info = mlxsw_bus_info;
INIT_LIST_HEAD(&mlxsw_sp->fids); INIT_LIST_HEAD(&mlxsw_sp->fids);
INIT_LIST_HEAD(&mlxsw_sp->vfids.list); INIT_LIST_HEAD(&mlxsw_sp->vfids.list);
INIT_LIST_HEAD(&mlxsw_sp->br_mids.list);
err = mlxsw_sp_base_mac_get(mlxsw_sp); err = mlxsw_sp_base_mac_get(mlxsw_sp);
if (err) { if (err) {
...@@ -3659,21 +3658,26 @@ static void mlxsw_sp_master_bridge_gone_sync(struct mlxsw_sp *mlxsw_sp) ...@@ -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, static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
struct net_device *br_dev) struct net_device *br_dev)
{ {
return !mlxsw_sp->master_bridge.dev || struct mlxsw_sp_upper *master_bridge = mlxsw_sp_master_bridge(mlxsw_sp);
mlxsw_sp->master_bridge.dev == br_dev;
return !master_bridge->dev || master_bridge->dev == br_dev;
} }
static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp *mlxsw_sp,
struct net_device *br_dev) struct net_device *br_dev)
{ {
mlxsw_sp->master_bridge.dev = br_dev; struct mlxsw_sp_upper *master_bridge = mlxsw_sp_master_bridge(mlxsw_sp);
mlxsw_sp->master_bridge.ref_count++;
master_bridge->dev = br_dev;
master_bridge->ref_count++;
} }
static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp) static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp)
{ {
if (--mlxsw_sp->master_bridge.ref_count == 0) { struct mlxsw_sp_upper *master_bridge = mlxsw_sp_master_bridge(mlxsw_sp);
mlxsw_sp->master_bridge.dev = NULL;
if (--master_bridge->ref_count == 0) {
master_bridge->dev = NULL;
/* It's possible upper VLAN devices are still holding /* It's possible upper VLAN devices are still holding
* references to underlying FIDs. Drop the reference * references to underlying FIDs. Drop the reference
* and release the resources if it was the last one. * 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, ...@@ -4272,7 +4276,7 @@ static int mlxsw_sp_netdevice_bridge_event(struct net_device *br_dev,
if (!is_vlan_dev(upper_dev)) if (!is_vlan_dev(upper_dev))
return -EINVAL; return -EINVAL;
if (is_vlan_dev(upper_dev) && if (is_vlan_dev(upper_dev) &&
br_dev != mlxsw_sp->master_bridge.dev) br_dev != mlxsw_sp_master_bridge(mlxsw_sp)->dev)
return -EINVAL; return -EINVAL;
break; break;
case NETDEV_CHANGEUPPER: case NETDEV_CHANGEUPPER:
......
...@@ -149,6 +149,7 @@ struct mlxsw_sp_port_mall_tc_entry { ...@@ -149,6 +149,7 @@ struct mlxsw_sp_port_mall_tc_entry {
}; };
struct mlxsw_sp_sb; struct mlxsw_sp_sb;
struct mlxsw_sp_bridge;
struct mlxsw_sp_router; struct mlxsw_sp_router;
struct mlxsw_sp_acl; struct mlxsw_sp_acl;
struct mlxsw_sp_counter_pool; struct mlxsw_sp_counter_pool;
...@@ -158,29 +159,16 @@ struct mlxsw_sp { ...@@ -158,29 +159,16 @@ struct mlxsw_sp {
struct list_head list; struct list_head list;
DECLARE_BITMAP(mapped, MLXSW_SP_VFID_MAX); DECLARE_BITMAP(mapped, MLXSW_SP_VFID_MAX);
} vfids; } vfids;
struct {
struct list_head list;
DECLARE_BITMAP(mapped, MLXSW_SP_MID_MAX);
} br_mids;
struct list_head fids; /* VLAN-aware bridge FIDs */ struct list_head fids; /* VLAN-aware bridge FIDs */
struct mlxsw_sp_rif **rifs; struct mlxsw_sp_rif **rifs;
struct mlxsw_sp_port **ports; struct mlxsw_sp_port **ports;
struct mlxsw_core *core; struct mlxsw_core *core;
const struct mlxsw_bus_info *bus_info; const struct mlxsw_bus_info *bus_info;
unsigned char base_mac[ETH_ALEN]; 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; struct mlxsw_sp_upper *lags;
u8 *port_to_module; u8 *port_to_module;
struct mlxsw_sp_sb *sb; struct mlxsw_sp_sb *sb;
struct mlxsw_sp_bridge *bridge;
struct mlxsw_sp_router *router; struct mlxsw_sp_router *router;
struct mlxsw_sp_acl *acl; struct mlxsw_sp_acl *acl;
struct { struct {
...@@ -425,6 +413,7 @@ int mlxsw_sp_sb_occ_tc_port_bind_get(struct mlxsw_core_port *mlxsw_core_port, ...@@ -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_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells);
u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes); 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); 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);
int mlxsw_sp_port_vlan_init(struct mlxsw_sp_port *mlxsw_sp_port); 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, ...@@ -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)) if (is_vlan_dev(l3_dev))
fid = vlan_dev_vlan_id(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; fid = 1;
else else
return mlxsw_sp_vfid_find(mlxsw_sp, l3_dev); 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, ...@@ -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, return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
vid); vid);
else if (netif_is_bridge_master(real_dev) && 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, return mlxsw_sp_inetaddr_bridge_event(vlan_dev, real_dev,
event); event);
......
...@@ -52,6 +52,27 @@ ...@@ -52,6 +52,27 @@
#include "core.h" #include "core.h"
#include "reg.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, static u16 mlxsw_sp_port_vid_to_fid_get(struct mlxsw_sp_port *mlxsw_sp_port,
u16 vid) u16 vid)
{ {
...@@ -397,7 +418,7 @@ static int mlxsw_sp_ageing_set(struct mlxsw_sp *mlxsw_sp, u32 ageing_time) ...@@ -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); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdat), sfdat_pl);
if (err) if (err)
return err; return err;
mlxsw_sp->ageing_time = ageing_time; mlxsw_sp->bridge->ageing_time = ageing_time;
return 0; return 0;
} }
...@@ -428,7 +449,8 @@ static int mlxsw_sp_port_attr_br_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -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; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
/* SWITCHDEV_TRANS_PREPARE phase */ /* 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"); netdev_err(mlxsw_sp_port->dev, "Bridge must be vlan-aware\n");
return -EINVAL; return -EINVAL;
} }
...@@ -1006,7 +1028,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp *mlxsw_sp, ...@@ -1006,7 +1028,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp *mlxsw_sp,
{ {
struct mlxsw_sp_mid *mid; 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) if (ether_addr_equal(mid->addr, addr) && mid->fid == fid)
return mid; return mid;
} }
...@@ -1020,7 +1042,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp, ...@@ -1020,7 +1042,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mid *mid; struct mlxsw_sp_mid *mid;
u16 mid_idx; 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); MLXSW_SP_MID_MAX);
if (mid_idx == MLXSW_SP_MID_MAX) if (mid_idx == MLXSW_SP_MID_MAX)
return NULL; return NULL;
...@@ -1029,12 +1051,12 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp, ...@@ -1029,12 +1051,12 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
if (!mid) if (!mid)
return NULL; 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); ether_addr_copy(mid->addr, addr);
mid->fid = fid; mid->fid = fid;
mid->mid = mid_idx; mid->mid = mid_idx;
mid->ref_count = 0; 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; return mid;
} }
...@@ -1044,7 +1066,7 @@ static int __mlxsw_sp_mc_dec_ref(struct mlxsw_sp *mlxsw_sp, ...@@ -1044,7 +1066,7 @@ static int __mlxsw_sp_mc_dec_ref(struct mlxsw_sp *mlxsw_sp,
{ {
if (--mid->ref_count == 0) { if (--mid->ref_count == 0) {
list_del(&mid->list); list_del(&mid->list);
clear_bit(mid->mid, mlxsw_sp->br_mids.mapped); clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
kfree(mid); kfree(mid);
return 1; return 1;
} }
...@@ -1600,12 +1622,15 @@ static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp, ...@@ -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) static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp)
{ {
mlxsw_core_schedule_dw(&mlxsw_sp->fdb_notify.dw, struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
msecs_to_jiffies(mlxsw_sp->fdb_notify.interval));
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) static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
{ {
struct mlxsw_sp_bridge *bridge;
struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp *mlxsw_sp;
char *sfn_pl; char *sfn_pl;
u8 num_rec; u8 num_rec;
...@@ -1616,7 +1641,8 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work) ...@@ -1616,7 +1641,8 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
if (!sfn_pl) if (!sfn_pl)
return; 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(); rtnl_lock();
mlxsw_reg_sfn_pack(sfn_pl); mlxsw_reg_sfn_pack(sfn_pl);
...@@ -1637,6 +1663,7 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work) ...@@ -1637,6 +1663,7 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
{ {
struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
int err; int err;
err = mlxsw_sp_ageing_set(mlxsw_sp, MLXSW_SP_DEFAULT_AGEING_TIME); 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) ...@@ -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"); dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n");
return err; return err;
} }
INIT_DELAYED_WORK(&mlxsw_sp->fdb_notify.dw, mlxsw_sp_fdb_notify_work); INIT_DELAYED_WORK(&bridge->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
mlxsw_sp->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL; bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp); mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
return 0; return 0;
} }
static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp) 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) 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); return mlxsw_sp_fdb_init(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);
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) void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port)
......
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