OSDN Git Service

net: dsa: hide dp->bridge_dev and dp->bridge_num in the core behind helpers
authorVladimir Oltean <vladimir.oltean@nxp.com>
Mon, 6 Dec 2021 16:57:52 +0000 (18:57 +0200)
committerJakub Kicinski <kuba@kernel.org>
Wed, 8 Dec 2021 22:31:15 +0000 (14:31 -0800)
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: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/dsa.h
net/dsa/dsa_priv.h
net/dsa/port.c
net/dsa/slave.c
net/dsa/switch.c
net/dsa/tag_8021q.c
net/dsa/tag_dsa.c
net/dsa/tag_ocelot.c
net/dsa/tag_sja1105.c

index 00fbd87..18bce03 100644 (file)
@@ -599,6 +599,27 @@ struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp)
        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,
                              bool is_static, void *data);
 struct dsa_switch_ops {
index 70c4a5b..46a0adf 100644 (file)
@@ -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
         * 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 */
@@ -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)
 {
        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 *upper_dev;
        u16 vid, pvid, proto;
index 199a56f..f6ea41c 100644 (file)
@@ -221,7 +221,7 @@ static int dsa_port_switchdev_sync_attrs(struct dsa_port *dp,
                                         struct netlink_ext_ack *extack)
 {
        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;
 
        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,
                goto out_rollback;
 
        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,
                                            &dsa_slave_switchdev_notifier,
@@ -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)
 {
+       unsigned int bridge_num = dsa_port_bridge_num_get(dp);
        struct dsa_notifier_bridge_info info = {
                .tree_index = dp->ds->dst->index,
                .sw_index = dp->ds->index,
                .port = dp->index,
                .br = br,
        };
-       int bridge_num = dp->bridge_num;
        int err;
 
        /* Here the port is already unbridged. Reflect the current configuration
@@ -507,12 +507,15 @@ err_lag_join:
 
 void dsa_port_pre_lag_leave(struct dsa_port *dp, struct net_device *lag)
 {
-       if (dp->bridge_dev)
-               dsa_port_pre_bridge_leave(dp, dp->bridge_dev);
+       struct net_device *br = dsa_port_bridge_dev_get(dp);
+
+       if (br)
+               dsa_port_pre_bridge_leave(dp, br);
 }
 
 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 = {
                .sw_index = dp->ds->index,
                .port = dp->index,
@@ -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
         * attached to a bridge.
         */
-       if (dp->bridge_dev)
-               dsa_port_bridge_leave(dp, dp->bridge_dev);
+       if (br)
+               dsa_port_bridge_leave(dp, br);
 
        dp->lag_tx_enabled = false;
        dp->lag_dev = NULL;
@@ -556,8 +559,8 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
         * as long as we have 8021q uppers.
         */
        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 *br = dp->bridge_dev;
                struct list_head *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,
         * different setting than what is being requested.
         */
        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
                 * 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;
-               if (br_vlan_enabled(other_bridge) != vlan_filtering) {
+
+               if (br_vlan_enabled(other_br) != vlan_filtering) {
                        NL_SET_ERR_MSG_MOD(extack,
                                           "VLAN filtering is a global setting");
                        return false;
@@ -685,13 +686,13 @@ restore:
  */
 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;
 
-       if (!dp->bridge_dev)
+       if (!br)
                return false;
 
-       return (!ds->configure_vlan_while_not_filtering &&
-               !br_vlan_enabled(dp->bridge_dev));
+       return !ds->configure_vlan_while_not_filtering && !br_vlan_enabled(br);
 }
 
 int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock)
index 33b54ea..99068ce 100644 (file)
@@ -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
         * the same VID.
         */
-       if (br_vlan_enabled(dp->bridge_dev)) {
+       if (br_vlan_enabled(dsa_port_bridge_dev_get(dp))) {
                rcu_read_lock();
                err = dsa_slave_vlan_check_for_8021q_uppers(dev, &vlan);
                rcu_read_unlock();
@@ -1580,7 +1580,7 @@ static void dsa_bridge_mtu_normalization(struct dsa_port *dp)
                        if (other_dp->type != DSA_PORT_TYPE_USER)
                                continue;
 
-                       if (other_dp->bridge_dev != dp->bridge_dev)
+                       if (!dsa_port_bridge_same(dp, other_dp))
                                continue;
 
                        if (!other_dp->ds->mtu_enforcement_ingress)
@@ -2220,7 +2220,7 @@ dsa_prevent_bridging_8021q_upper(struct net_device *dev,
                                 struct netdev_notifier_changeupper_info *info)
 {
        struct netlink_ext_ack *ext_ack;
-       struct net_device *slave;
+       struct net_device *slave, *br;
        struct dsa_port *dp;
 
        ext_ack = netdev_notifier_info_to_extack(&info->info);
@@ -2233,11 +2233,12 @@ dsa_prevent_bridging_8021q_upper(struct net_device *dev,
                return NOTIFY_DONE;
 
        dp = dsa_slave_to_port(slave);
-       if (!dp->bridge_dev)
+       br = dsa_port_bridge_dev_get(dp);
+       if (!br)
                return NOTIFY_DONE;
 
        /* 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) {
                NL_SET_ERR_MSG_MOD(ext_ack,
                                   "Cannot enslave VLAN device into VLAN aware bridge");
@@ -2252,7 +2253,7 @@ dsa_slave_check_8021q_upper(struct net_device *dev,
                            struct netdev_notifier_changeupper_info *info)
 {
        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 netlink_ext_ack *extack;
        int err = NOTIFY_DONE;
index bb155a1..7993192 100644 (file)
@@ -151,11 +151,9 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
         */
        if (change_vlan_filtering && ds->vlan_filtering_is_global) {
                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 (bridge_dev && br_vlan_enabled(bridge_dev)) {
+                       if (br && br_vlan_enabled(br)) {
                                change_vlan_filtering = false;
                                break;
                        }
index df59f16..e9d5e56 100644 (file)
@@ -337,7 +337,7 @@ dsa_port_tag_8021q_bridge_match(struct dsa_port *dp,
                return false;
 
        if (dsa_port_is_user(dp))
-               return dp->bridge_dev == info->br;
+               return dsa_port_bridge_dev_get(dp) == info->br;
 
        return false;
 }
index a7d70ae..8abf39d 100644 (file)
@@ -132,6 +132,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
        u8 *dsa_header;
 
        if (skb->offload_fwd_mark) {
+               unsigned int bridge_num = dsa_port_bridge_num_get(dp);
                struct dsa_switch_tree *dst = dp->ds->dst;
 
                cmd = DSA_CMD_FORWARD;
@@ -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
                 * past the physical switches.
                 */
-               tag_dev = dst->last_switch + dp->bridge_num;
+               tag_dev = dst->last_switch + bridge_num;
                tag_port = 0;
        } else {
                cmd = DSA_CMD_FROM_CPU;
@@ -165,7 +166,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
                        dsa_header[2] &= ~0x10;
                }
        } else {
-               struct net_device *br = dp->bridge_dev;
+               struct net_device *br = dsa_port_bridge_dev_get(dp);
                u16 vid;
 
                vid = br ? MV88E6XXX_VID_BRIDGED : MV88E6XXX_VID_STANDALONE;
index de1c849..4ba460c 100644 (file)
@@ -12,7 +12,7 @@
 static void ocelot_xmit_get_vlan_info(struct sk_buff *skb, struct dsa_port *dp,
                                      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;
        u16 proto, tci;
 
index 262c883..6c293c2 100644 (file)
@@ -159,14 +159,16 @@ static u16 sja1105_xmit_tpid(struct dsa_port *dp)
         * need to find it.
         */
        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;
 
                /* Error is returned only if CONFIG_BRIDGE_VLAN_FILTERING,
                 * which seems pointless to handle, as our port cannot become
                 * VLAN-aware in that case.
                 */
-               br_vlan_get_proto(other_dp->bridge_dev, &proto);
+               br_vlan_get_proto(br, &proto);
 
                return proto;
        }
@@ -180,7 +182,8 @@ static struct sk_buff *sja1105_imprecise_xmit(struct sk_buff *skb,
                                              struct net_device *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;
 
        /* 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,
         * TX VLAN that targets the bridge's entire broadcast domain,
         * 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);
 }