Commit 36cbf39b authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski

net: dsa: hide dp->bridge_dev and dp->bridge_num in the core behind helpers

The location of the bridge device pointer and number is going to change.
It is not going to be kept individually per port, but in a common
structure allocated dynamically and which will have lockdep validation.

Create helpers to access these elements so that we have a migration path
to the new organization.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 65144067
...@@ -599,6 +599,27 @@ struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp) ...@@ -599,6 +599,27 @@ struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp)
return dp->slave; return dp->slave;
} }
static inline struct net_device *
dsa_port_bridge_dev_get(const struct dsa_port *dp)
{
return dp->bridge_dev;
}
static inline unsigned int dsa_port_bridge_num_get(struct dsa_port *dp)
{
return dp->bridge_num;
}
static inline bool dsa_port_bridge_same(const struct dsa_port *a,
const struct dsa_port *b)
{
struct net_device *br_a = dsa_port_bridge_dev_get(a);
struct net_device *br_b = dsa_port_bridge_dev_get(b);
/* Standalone ports are not in the same bridge with one another */
return (!br_a || !br_b) ? false : (br_a == br_b);
}
typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid, typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
bool is_static, void *data); bool is_static, void *data);
struct dsa_switch_ops { struct dsa_switch_ops {
......
...@@ -278,7 +278,7 @@ static inline bool dsa_port_offloads_bridge(struct dsa_port *dp, ...@@ -278,7 +278,7 @@ static inline bool dsa_port_offloads_bridge(struct dsa_port *dp,
/* DSA ports connected to a bridge, and event was emitted /* DSA ports connected to a bridge, and event was emitted
* for the bridge. * for the bridge.
*/ */
return dp->bridge_dev == bridge_dev; return dsa_port_bridge_dev_get(dp) == bridge_dev;
} }
/* Returns true if any port of this tree offloads the given net_device */ /* Returns true if any port of this tree offloads the given net_device */
...@@ -345,7 +345,7 @@ dsa_slave_to_master(const struct net_device *dev) ...@@ -345,7 +345,7 @@ dsa_slave_to_master(const struct net_device *dev)
static inline struct sk_buff *dsa_untag_bridge_pvid(struct sk_buff *skb) static inline struct sk_buff *dsa_untag_bridge_pvid(struct sk_buff *skb)
{ {
struct dsa_port *dp = dsa_slave_to_port(skb->dev); struct dsa_port *dp = dsa_slave_to_port(skb->dev);
struct net_device *br = dp->bridge_dev; struct net_device *br = dsa_port_bridge_dev_get(dp);
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
struct net_device *upper_dev; struct net_device *upper_dev;
u16 vid, pvid, proto; u16 vid, pvid, proto;
......
...@@ -221,7 +221,7 @@ static int dsa_port_switchdev_sync_attrs(struct dsa_port *dp, ...@@ -221,7 +221,7 @@ static int dsa_port_switchdev_sync_attrs(struct dsa_port *dp,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct net_device *brport_dev = dsa_port_to_bridge_port(dp); struct net_device *brport_dev = dsa_port_to_bridge_port(dp);
struct net_device *br = dp->bridge_dev; struct net_device *br = dsa_port_bridge_dev_get(dp);
int err; int err;
err = dsa_port_inherit_brport_flags(dp, extack); err = dsa_port_inherit_brport_flags(dp, extack);
...@@ -372,7 +372,7 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br, ...@@ -372,7 +372,7 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br,
goto out_rollback; goto out_rollback;
tx_fwd_offload = dsa_port_bridge_tx_fwd_offload(dp, br, tx_fwd_offload = dsa_port_bridge_tx_fwd_offload(dp, br,
dp->bridge_num); dsa_port_bridge_num_get(dp));
err = switchdev_bridge_port_offload(brport_dev, dev, dp, err = switchdev_bridge_port_offload(brport_dev, dev, dp,
&dsa_slave_switchdev_notifier, &dsa_slave_switchdev_notifier,
...@@ -415,13 +415,13 @@ void dsa_port_pre_bridge_leave(struct dsa_port *dp, struct net_device *br) ...@@ -415,13 +415,13 @@ void dsa_port_pre_bridge_leave(struct dsa_port *dp, struct net_device *br)
void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
{ {
unsigned int bridge_num = dsa_port_bridge_num_get(dp);
struct dsa_notifier_bridge_info info = { struct dsa_notifier_bridge_info info = {
.tree_index = dp->ds->dst->index, .tree_index = dp->ds->dst->index,
.sw_index = dp->ds->index, .sw_index = dp->ds->index,
.port = dp->index, .port = dp->index,
.br = br, .br = br,
}; };
int bridge_num = dp->bridge_num;
int err; int err;
/* Here the port is already unbridged. Reflect the current configuration /* Here the port is already unbridged. Reflect the current configuration
...@@ -507,12 +507,15 @@ int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag, ...@@ -507,12 +507,15 @@ int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag,
void dsa_port_pre_lag_leave(struct dsa_port *dp, struct net_device *lag) void dsa_port_pre_lag_leave(struct dsa_port *dp, struct net_device *lag)
{ {
if (dp->bridge_dev) struct net_device *br = dsa_port_bridge_dev_get(dp);
dsa_port_pre_bridge_leave(dp, dp->bridge_dev);
if (br)
dsa_port_pre_bridge_leave(dp, br);
} }
void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag) void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag)
{ {
struct net_device *br = dsa_port_bridge_dev_get(dp);
struct dsa_notifier_lag_info info = { struct dsa_notifier_lag_info info = {
.sw_index = dp->ds->index, .sw_index = dp->ds->index,
.port = dp->index, .port = dp->index,
...@@ -526,8 +529,8 @@ void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag) ...@@ -526,8 +529,8 @@ void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag)
/* Port might have been part of a LAG that in turn was /* Port might have been part of a LAG that in turn was
* attached to a bridge. * attached to a bridge.
*/ */
if (dp->bridge_dev) if (br)
dsa_port_bridge_leave(dp, dp->bridge_dev); dsa_port_bridge_leave(dp, br);
dp->lag_tx_enabled = false; dp->lag_tx_enabled = false;
dp->lag_dev = NULL; dp->lag_dev = NULL;
...@@ -556,8 +559,8 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp, ...@@ -556,8 +559,8 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
* as long as we have 8021q uppers. * as long as we have 8021q uppers.
*/ */
if (vlan_filtering && dsa_port_is_user(dp)) { if (vlan_filtering && dsa_port_is_user(dp)) {
struct net_device *br = dsa_port_bridge_dev_get(dp);
struct net_device *upper_dev, *slave = dp->slave; struct net_device *upper_dev, *slave = dp->slave;
struct net_device *br = dp->bridge_dev;
struct list_head *iter; struct list_head *iter;
netdev_for_each_upper_dev_rcu(slave, upper_dev, iter) { netdev_for_each_upper_dev_rcu(slave, upper_dev, iter) {
...@@ -591,17 +594,15 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp, ...@@ -591,17 +594,15 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
* different setting than what is being requested. * different setting than what is being requested.
*/ */
dsa_switch_for_each_port(other_dp, ds) { dsa_switch_for_each_port(other_dp, ds) {
struct net_device *other_bridge; struct net_device *other_br = dsa_port_bridge_dev_get(other_dp);
other_bridge = other_dp->bridge_dev;
if (!other_bridge)
continue;
/* If it's the same bridge, it also has same /* If it's the same bridge, it also has same
* vlan_filtering setting => no need to check * vlan_filtering setting => no need to check
*/ */
if (other_bridge == dp->bridge_dev) if (!other_br || other_br == dsa_port_bridge_dev_get(dp))
continue; continue;
if (br_vlan_enabled(other_bridge) != vlan_filtering) {
if (br_vlan_enabled(other_br) != vlan_filtering) {
NL_SET_ERR_MSG_MOD(extack, NL_SET_ERR_MSG_MOD(extack,
"VLAN filtering is a global setting"); "VLAN filtering is a global setting");
return false; return false;
...@@ -685,13 +686,13 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, ...@@ -685,13 +686,13 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
*/ */
bool dsa_port_skip_vlan_configuration(struct dsa_port *dp) bool dsa_port_skip_vlan_configuration(struct dsa_port *dp)
{ {
struct net_device *br = dsa_port_bridge_dev_get(dp);
struct dsa_switch *ds = dp->ds; struct dsa_switch *ds = dp->ds;
if (!dp->bridge_dev) if (!br)
return false; return false;
return (!ds->configure_vlan_while_not_filtering && return !ds->configure_vlan_while_not_filtering && !br_vlan_enabled(br);
!br_vlan_enabled(dp->bridge_dev));
} }
int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock) int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock)
......
...@@ -363,7 +363,7 @@ static int dsa_slave_vlan_add(struct net_device *dev, ...@@ -363,7 +363,7 @@ static int dsa_slave_vlan_add(struct net_device *dev,
/* Deny adding a bridge VLAN when there is already an 802.1Q upper with /* Deny adding a bridge VLAN when there is already an 802.1Q upper with
* the same VID. * the same VID.
*/ */
if (br_vlan_enabled(dp->bridge_dev)) { if (br_vlan_enabled(dsa_port_bridge_dev_get(dp))) {
rcu_read_lock(); rcu_read_lock();
err = dsa_slave_vlan_check_for_8021q_uppers(dev, &vlan); err = dsa_slave_vlan_check_for_8021q_uppers(dev, &vlan);
rcu_read_unlock(); rcu_read_unlock();
...@@ -1580,7 +1580,7 @@ static void dsa_bridge_mtu_normalization(struct dsa_port *dp) ...@@ -1580,7 +1580,7 @@ static void dsa_bridge_mtu_normalization(struct dsa_port *dp)
if (other_dp->type != DSA_PORT_TYPE_USER) if (other_dp->type != DSA_PORT_TYPE_USER)
continue; continue;
if (other_dp->bridge_dev != dp->bridge_dev) if (!dsa_port_bridge_same(dp, other_dp))
continue; continue;
if (!other_dp->ds->mtu_enforcement_ingress) if (!other_dp->ds->mtu_enforcement_ingress)
...@@ -2220,7 +2220,7 @@ dsa_prevent_bridging_8021q_upper(struct net_device *dev, ...@@ -2220,7 +2220,7 @@ dsa_prevent_bridging_8021q_upper(struct net_device *dev,
struct netdev_notifier_changeupper_info *info) struct netdev_notifier_changeupper_info *info)
{ {
struct netlink_ext_ack *ext_ack; struct netlink_ext_ack *ext_ack;
struct net_device *slave; struct net_device *slave, *br;
struct dsa_port *dp; struct dsa_port *dp;
ext_ack = netdev_notifier_info_to_extack(&info->info); ext_ack = netdev_notifier_info_to_extack(&info->info);
...@@ -2233,11 +2233,12 @@ dsa_prevent_bridging_8021q_upper(struct net_device *dev, ...@@ -2233,11 +2233,12 @@ dsa_prevent_bridging_8021q_upper(struct net_device *dev,
return NOTIFY_DONE; return NOTIFY_DONE;
dp = dsa_slave_to_port(slave); dp = dsa_slave_to_port(slave);
if (!dp->bridge_dev) br = dsa_port_bridge_dev_get(dp);
if (!br)
return NOTIFY_DONE; return NOTIFY_DONE;
/* Deny enslaving a VLAN device into a VLAN-aware bridge */ /* Deny enslaving a VLAN device into a VLAN-aware bridge */
if (br_vlan_enabled(dp->bridge_dev) && if (br_vlan_enabled(br) &&
netif_is_bridge_master(info->upper_dev) && info->linking) { netif_is_bridge_master(info->upper_dev) && info->linking) {
NL_SET_ERR_MSG_MOD(ext_ack, NL_SET_ERR_MSG_MOD(ext_ack,
"Cannot enslave VLAN device into VLAN aware bridge"); "Cannot enslave VLAN device into VLAN aware bridge");
...@@ -2252,7 +2253,7 @@ dsa_slave_check_8021q_upper(struct net_device *dev, ...@@ -2252,7 +2253,7 @@ dsa_slave_check_8021q_upper(struct net_device *dev,
struct netdev_notifier_changeupper_info *info) struct netdev_notifier_changeupper_info *info)
{ {
struct dsa_port *dp = dsa_slave_to_port(dev); struct dsa_port *dp = dsa_slave_to_port(dev);
struct net_device *br = dp->bridge_dev; struct net_device *br = dsa_port_bridge_dev_get(dp);
struct bridge_vlan_info br_info; struct bridge_vlan_info br_info;
struct netlink_ext_ack *extack; struct netlink_ext_ack *extack;
int err = NOTIFY_DONE; int err = NOTIFY_DONE;
......
...@@ -151,11 +151,9 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, ...@@ -151,11 +151,9 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
*/ */
if (change_vlan_filtering && ds->vlan_filtering_is_global) { if (change_vlan_filtering && ds->vlan_filtering_is_global) {
dsa_switch_for_each_port(dp, ds) { dsa_switch_for_each_port(dp, ds) {
struct net_device *bridge_dev; struct net_device *br = dsa_port_bridge_dev_get(dp);
bridge_dev = dp->bridge_dev; if (br && br_vlan_enabled(br)) {
if (bridge_dev && br_vlan_enabled(bridge_dev)) {
change_vlan_filtering = false; change_vlan_filtering = false;
break; break;
} }
......
...@@ -337,7 +337,7 @@ dsa_port_tag_8021q_bridge_match(struct dsa_port *dp, ...@@ -337,7 +337,7 @@ dsa_port_tag_8021q_bridge_match(struct dsa_port *dp,
return false; return false;
if (dsa_port_is_user(dp)) if (dsa_port_is_user(dp))
return dp->bridge_dev == info->br; return dsa_port_bridge_dev_get(dp) == info->br;
return false; return false;
} }
......
...@@ -132,6 +132,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, ...@@ -132,6 +132,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
u8 *dsa_header; u8 *dsa_header;
if (skb->offload_fwd_mark) { if (skb->offload_fwd_mark) {
unsigned int bridge_num = dsa_port_bridge_num_get(dp);
struct dsa_switch_tree *dst = dp->ds->dst; struct dsa_switch_tree *dst = dp->ds->dst;
cmd = DSA_CMD_FORWARD; cmd = DSA_CMD_FORWARD;
...@@ -140,7 +141,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, ...@@ -140,7 +141,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
* packets on behalf of a virtual switch device with an index * packets on behalf of a virtual switch device with an index
* past the physical switches. * past the physical switches.
*/ */
tag_dev = dst->last_switch + dp->bridge_num; tag_dev = dst->last_switch + bridge_num;
tag_port = 0; tag_port = 0;
} else { } else {
cmd = DSA_CMD_FROM_CPU; cmd = DSA_CMD_FROM_CPU;
...@@ -165,7 +166,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev, ...@@ -165,7 +166,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
dsa_header[2] &= ~0x10; dsa_header[2] &= ~0x10;
} }
} else { } else {
struct net_device *br = dp->bridge_dev; struct net_device *br = dsa_port_bridge_dev_get(dp);
u16 vid; u16 vid;
vid = br ? MV88E6XXX_VID_BRIDGED : MV88E6XXX_VID_STANDALONE; vid = br ? MV88E6XXX_VID_BRIDGED : MV88E6XXX_VID_STANDALONE;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
static void ocelot_xmit_get_vlan_info(struct sk_buff *skb, struct dsa_port *dp, static void ocelot_xmit_get_vlan_info(struct sk_buff *skb, struct dsa_port *dp,
u64 *vlan_tci, u64 *tag_type) u64 *vlan_tci, u64 *tag_type)
{ {
struct net_device *br = READ_ONCE(dp->bridge_dev); struct net_device *br = dsa_port_bridge_dev_get(dp);
struct vlan_ethhdr *hdr; struct vlan_ethhdr *hdr;
u16 proto, tci; u16 proto, tci;
......
...@@ -159,14 +159,16 @@ static u16 sja1105_xmit_tpid(struct dsa_port *dp) ...@@ -159,14 +159,16 @@ static u16 sja1105_xmit_tpid(struct dsa_port *dp)
* need to find it. * need to find it.
*/ */
dsa_switch_for_each_port(other_dp, ds) { dsa_switch_for_each_port(other_dp, ds) {
if (!other_dp->bridge_dev) struct net_device *br = dsa_port_bridge_dev_get(other_dp);
if (!br)
continue; continue;
/* Error is returned only if CONFIG_BRIDGE_VLAN_FILTERING, /* Error is returned only if CONFIG_BRIDGE_VLAN_FILTERING,
* which seems pointless to handle, as our port cannot become * which seems pointless to handle, as our port cannot become
* VLAN-aware in that case. * VLAN-aware in that case.
*/ */
br_vlan_get_proto(other_dp->bridge_dev, &proto); br_vlan_get_proto(br, &proto);
return proto; return proto;
} }
...@@ -180,7 +182,8 @@ static struct sk_buff *sja1105_imprecise_xmit(struct sk_buff *skb, ...@@ -180,7 +182,8 @@ static struct sk_buff *sja1105_imprecise_xmit(struct sk_buff *skb,
struct net_device *netdev) struct net_device *netdev)
{ {
struct dsa_port *dp = dsa_slave_to_port(netdev); struct dsa_port *dp = dsa_slave_to_port(netdev);
struct net_device *br = dp->bridge_dev; unsigned int bridge_num = dsa_port_bridge_num_get(dp);
struct net_device *br = dsa_port_bridge_dev_get(dp);
u16 tx_vid; u16 tx_vid;
/* If the port is under a VLAN-aware bridge, just slide the /* If the port is under a VLAN-aware bridge, just slide the
...@@ -196,7 +199,7 @@ static struct sk_buff *sja1105_imprecise_xmit(struct sk_buff *skb, ...@@ -196,7 +199,7 @@ static struct sk_buff *sja1105_imprecise_xmit(struct sk_buff *skb,
* TX VLAN that targets the bridge's entire broadcast domain, * TX VLAN that targets the bridge's entire broadcast domain,
* instead of just the specific port. * instead of just the specific port.
*/ */
tx_vid = dsa_8021q_bridge_tx_fwd_offload_vid(dp->bridge_num); tx_vid = dsa_8021q_bridge_tx_fwd_offload_vid(bridge_num);
return dsa_8021q_xmit(skb, netdev, sja1105_xmit_tpid(dp), tx_vid); return dsa_8021q_xmit(skb, netdev, sja1105_xmit_tpid(dp), tx_vid);
} }
......
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