[openwrt/openwrt] realtek: drop patches of upstreamed fix and changes from 5.15

LEDE Commits lede-commits at lists.infradead.org
Thu Dec 15 12:02:30 PST 2022


svanheule pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/23881c91e584f758af52c231cd2aaac3e751535b

commit 23881c91e584f758af52c231cd2aaac3e751535b
Author: INAGAKI Hiroshi <musashino.open at gmail.com>
AuthorDate: Tue Mar 29 15:15:07 2022 +0900

    realtek: drop patches of upstreamed fix and changes from 5.15
    
    - 007-5.16-gpio-realtek...: upstreamed on 5.16 and backported to 5.15.3
    - 708-brflood-spi.patch   : upstreamed
    - 709-lag-offloading.patch: upstreamed
    - 713-v5.12-net-dsa-...   : upstreamed and some implementations are
                                replaced
    
    Signed-off-by: INAGAKI Hiroshi <musashino.open at gmail.com>
---
 ...tek-realtek-otto-fix-gpio-line-irq-offset.patch |  22 -
 .../realtek/patches-5.15/708-brflood-api.patch     | 162 -----
 .../realtek/patches-5.15/709-lag-offloading.patch  | 781 ---------------------
 ...figure-better-brport-flags-when-ports-lea.patch | 148 ----
 4 files changed, 1113 deletions(-)

diff --git a/target/linux/realtek/patches-5.15/007-5.16-gpio-realtek-realtek-otto-fix-gpio-line-irq-offset.patch b/target/linux/realtek/patches-5.15/007-5.16-gpio-realtek-realtek-otto-fix-gpio-line-irq-offset.patch
deleted file mode 100644
index 9935c57257..0000000000
--- a/target/linux/realtek/patches-5.15/007-5.16-gpio-realtek-realtek-otto-fix-gpio-line-irq-offset.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From: Sander Vanheule <sander at svanheule.net>
-Subject: gpio: realtek-otto: fix GPIO line IRQ offset
-
-The irqchip uses one domain for all GPIO lines, so th line offset should be
-determined w.r.t. the first line of the first port, not the first line of the
-triggered port.
-
-Fixes: 0d82fb1127fb ("gpio: Add Realtek Otto GPIO support")
-Signed-off-by: Sander Vanheule <sander at svanheule.net>
-Link: https://lore.kernel.org/linux-gpio/20211028085243.34360-1-sander@svanheule.net/
-
---- a/drivers/gpio/gpio-realtek-otto.c
-+++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -206,7 +206,7 @@ static void realtek_gpio_irq_handler(str
- 		status = realtek_gpio_read_isr(ctrl, lines_done / 8);
- 		port_pin_count = min(gc->ngpio - lines_done, 8U);
- 		for_each_set_bit(offset, &status, port_pin_count) {
--			irq = irq_find_mapping(gc->irq.domain, offset);
-+			irq = irq_find_mapping(gc->irq.domain, offset + lines_done);
- 			generic_handle_irq(irq);
- 		}
- 	}
diff --git a/target/linux/realtek/patches-5.15/708-brflood-api.patch b/target/linux/realtek/patches-5.15/708-brflood-api.patch
deleted file mode 100644
index 2716933ae7..0000000000
--- a/target/linux/realtek/patches-5.15/708-brflood-api.patch
+++ /dev/null
@@ -1,162 +0,0 @@
-From afa3ab54c03d5126b14651f367b38165fab5b3cc Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git at birger-koblitz.de>
-Date: Tue, 18 Jan 2022 17:18:43 +0100
-Subject: net: brflood API
-
-Adds the DSA API for bridge configuration (flooding, L2 learning,
-and aging) offload as found in Linux 5.12 so that we can implement
-it in our drivver.
-
-Submitted-by: Sebastian Gottschall <s.gottschall at dd-wrt.com>
-Submitted-by: Birger Koblitz <git at birger-koblitz.de>
----
- include/net/dsa.h                             |  6 +++++++--
- net/dsa/dsa_priv.h                            |  6 +++---
- net/dsa/port.c                                | 28 ++++++++----
- net/dsa/slave.c                               |  6 +++---
- 4 file changed, 29 insertions(+), 13 deletions(-)
-
---- a/include/net/dsa.h
-+++ b/include/net/dsa.h
-@@ -552,8 +552,14 @@ struct dsa_switch_ops {
- 	void	(*port_stp_state_set)(struct dsa_switch *ds, int port,
- 				      u8 state);
- 	void	(*port_fast_age)(struct dsa_switch *ds, int port);
--	int	(*port_egress_floods)(struct dsa_switch *ds, int port,
--				      bool unicast, bool multicast);
-+	int	(*port_pre_bridge_flags)(struct dsa_switch *ds, int port,
-+					 unsigned long flags,
-+					 struct netlink_ext_ack *extack);
-+	int	(*port_bridge_flags)(struct dsa_switch *ds, int port,
-+				     unsigned long flags,
-+				     struct netlink_ext_ack *extack);
-+	int	(*port_set_mrouter)(struct dsa_switch *ds, int port, bool mrouter,
-+				    struct netlink_ext_ack *extack);
- 
- 	/*
- 	 * VLAN support
---- a/net/dsa/dsa_priv.h
-+++ b/net/dsa/dsa_priv.h
-@@ -167,11 +167,11 @@ int dsa_port_mdb_add(const struct dsa_po
- int dsa_port_mdb_del(const struct dsa_port *dp,
- 		     const struct switchdev_obj_port_mdb *mdb);
- int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags,
--			      struct switchdev_trans *trans);
-+			      struct switchdev_trans *trans, struct netlink_ext_ack *extack);
- int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
--			  struct switchdev_trans *trans);
-+			  struct switchdev_trans *trans, struct netlink_ext_ack *extack);
- int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
--		     struct switchdev_trans *trans);
-+		     struct switchdev_trans *trans, struct netlink_ext_ack *extack);
- int dsa_port_vlan_add(struct dsa_port *dp,
- 		      const struct switchdev_obj_port_vlan *vlan,
- 		      struct switchdev_trans *trans);
---- a/net/dsa/port.c
-+++ b/net/dsa/port.c
-@@ -145,7 +145,7 @@ int dsa_port_bridge_join(struct dsa_port
- 	int err;
- 
- 	/* Set the flooding mode before joining the port in the switch */
--	err = dsa_port_bridge_flags(dp, BR_FLOOD | BR_MCAST_FLOOD, NULL);
-+	err = dsa_port_bridge_flags(dp, BR_FLOOD | BR_MCAST_FLOOD, NULL, NULL);
- 	if (err)
- 		return err;
- 
-@@ -158,7 +158,7 @@ int dsa_port_bridge_join(struct dsa_port
- 
- 	/* The bridging is rolled back on error */
- 	if (err) {
--		dsa_port_bridge_flags(dp, 0, NULL);
-+		dsa_port_bridge_flags(dp, 0, NULL, NULL);
- 		dp->bridge_dev = NULL;
- 	}
- 
-@@ -185,7 +185,7 @@ void dsa_port_bridge_leave(struct dsa_po
- 		pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
- 
- 	/* Port is leaving the bridge, disable flooding */
--	dsa_port_bridge_flags(dp, 0, NULL);
-+	dsa_port_bridge_flags(dp, 0, NULL, NULL);
- 
- 	/* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
- 	 * so allow it to be in BR_STATE_FORWARDING to be kept functional
-@@ -333,44 +333,44 @@ int dsa_port_ageing_time(struct dsa_port
- }
- 
- int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags,
--			      struct switchdev_trans *trans)
-+			      struct switchdev_trans *trans, struct netlink_ext_ack *extack)
- {
- 	struct dsa_switch *ds = dp->ds;
- 
--	if (!ds->ops->port_egress_floods ||
--	    (flags & ~(BR_FLOOD | BR_MCAST_FLOOD)))
-+	if (!ds->ops->port_pre_bridge_flags)
- 		return -EINVAL;
- 
--	return 0;
-+	return ds->ops->port_pre_bridge_flags(ds, dp->index, flags, extack);
- }
- 
- int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
--			  struct switchdev_trans *trans)
-+			  struct switchdev_trans *trans, struct netlink_ext_ack *extack)
- {
- 	struct dsa_switch *ds = dp->ds;
--	int port = dp->index;
--	int err = 0;
- 
- 	if (switchdev_trans_ph_prepare(trans))
- 		return 0;
- 
--	if (ds->ops->port_egress_floods)
--		err = ds->ops->port_egress_floods(ds, port, flags & BR_FLOOD,
--						  flags & BR_MCAST_FLOOD);
-+	if (!ds->ops->port_bridge_flags)
-+		return -EINVAL;
-+ 
-+	return ds->ops->port_bridge_flags(ds, dp->index, flags, extack);
- 
--	return err;
- }
- 
- int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
--		     struct switchdev_trans *trans)
-+		     struct switchdev_trans *trans,
-+		     struct netlink_ext_ack *extack)
- {
- 	struct dsa_switch *ds = dp->ds;
--	int port = dp->index;
- 
- 	if (switchdev_trans_ph_prepare(trans))
--		return ds->ops->port_egress_floods ? 0 : -EOPNOTSUPP;
-+		return ds->ops->port_set_mrouter ? 0 : -EOPNOTSUPP;
-+
-+	if (!ds->ops->port_set_mrouter)
-+ 		return -EOPNOTSUPP;
- 
--	return ds->ops->port_egress_floods(ds, port, true, mrouter);
-+	return ds->ops->port_set_mrouter(ds, dp->index, mrouter, extack);
- }
- 
- int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
---- a/net/dsa/slave.c
-+++ b/net/dsa/slave.c
-@@ -290,13 +290,13 @@ static int dsa_slave_port_attr_set(struc
- 		break;
- 	case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
- 		ret = dsa_port_pre_bridge_flags(dp, attr->u.brport_flags,
--						trans);
-+						trans, NULL);
- 		break;
- 	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
--		ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, trans);
-+		ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, trans, NULL);
- 		break;
- 	case SWITCHDEV_ATTR_ID_BRIDGE_MROUTER:
--		ret = dsa_port_mrouter(dp->cpu_dp, attr->u.mrouter, trans);
-+		ret = dsa_port_mrouter(dp->cpu_dp, attr->u.mrouter, trans, NULL);
- 		break;
- 	default:
- 		ret = -EOPNOTSUPP;
diff --git a/target/linux/realtek/patches-5.15/709-lag-offloading.patch b/target/linux/realtek/patches-5.15/709-lag-offloading.patch
deleted file mode 100644
index f84687ff4a..0000000000
--- a/target/linux/realtek/patches-5.15/709-lag-offloading.patch
+++ /dev/null
@@ -1,781 +0,0 @@
-From afa3ab54c03d5126b14651f367b38165fab5b3cc Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git at birger-koblitz.de>
-Date: Tue, 18 Jan 2022 17:18:43 +0100
-Subject: [PATCH] realtek: Backport bridge configuration for DSA
-
-Adds the DSA API for bridge configuration (flooding, L2 learning,
-and aging) offload as found in Linux 5.12 so that we can implement
-it in our drivver.
-
-Submitted-by: Sebastian Gottschall <s.gottschall at dd-wrt.com>
-Submitted-by: Birger Koblitz <git at birger-koblitz.de>
----
- drivers/net/bonding/bond_main.c               |  2 ++
- include/net/dsa.h                             | 79 ++++++++++++++++-
- net/dsa/dsa2.c                                | 88 +++++++++++++++++++
- net/dsa/dsa_priv.h                            | 74 ++++++++++++++
- net/dsa/port.c                                | 92 ++++++++++++++++++++
- net/dsa/slave.c                               | 88 ++++++++++++++++---
- net/dsa/switch.c                              | 49 ++++++++++
- net/sda/tag_dsa.c                             | 13 +++++-
- 8 file changed, 460 insertions(+), 25 deletions(-)
-
---- a/drivers/net/bonding/bond_main.c
-+++ b/drivers/net/bonding/bond_main.c
-@@ -2045,6 +2045,8 @@ int bond_enslave(struct net_device *bond
- 		goto err_unregister;
- 	}
- 
-+	bond_lower_state_changed(new_slave);
-+
- 	res = bond_sysfs_slave_add(new_slave);
- 	if (res) {
- 		slave_dbg(bond_dev, slave_dev, "Error %d calling bond_sysfs_slave_add\n", res);
---- a/include/net/dsa.h
-+++ b/include/net/dsa.h
-@@ -149,8 +149,41 @@ struct dsa_switch_tree {
- 
- 	/* List of DSA links composing the routing table */
- 	struct list_head rtable;
-+
-+	/* Maps offloaded LAG netdevs to a zero-based linear ID for
-+	 * drivers that need it.
-+	 */
-+	struct net_device **lags;
-+	unsigned int lags_len;
- };
- 
-+#define dsa_lags_foreach_id(_id, _dst)				\
-+	for ((_id) = 0; (_id) < (_dst)->lags_len; (_id)++)	\
-+		if ((_dst)->lags[(_id)])
-+
-+#define dsa_lag_foreach_port(_dp, _dst, _lag)			\
-+	list_for_each_entry((_dp), &(_dst)->ports, list)	\
-+		if ((_dp)->lag_dev == (_lag))
-+
-+static inline struct net_device *dsa_lag_dev(struct dsa_switch_tree *dst,
-+					     unsigned int id)
-+{
-+	return dst->lags[id];
-+}
-+
-+static inline int dsa_lag_id(struct dsa_switch_tree *dst,
-+			     struct net_device *lag)
-+{
-+	unsigned int id;
-+
-+	dsa_lags_foreach_id(id, dst) {
-+		if (dsa_lag_dev(dst, id) == lag)
-+			return id;
-+	}
-+
-+	return -ENODEV;
-+}
-+
- /* TC matchall action types */
- enum dsa_port_mall_action_type {
- 	DSA_PORT_MALL_MIRROR,
-@@ -220,6 +253,8 @@ struct dsa_port {
- 	bool			devlink_port_setup;
- 	struct phylink		*pl;
- 	struct phylink_config	pl_config;
-+	struct net_device	*lag_dev;
-+	bool			lag_tx_enabled;
- 
- 	struct list_head list;
- 
-@@ -340,6 +375,14 @@ struct dsa_switch {
- 	 */
- 	bool			mtu_enforcement_ingress;
- 
-+	/* Drivers that benefit from having an ID associated with each
-+	 * offloaded LAG should set this to the maximum number of
-+	 * supported IDs. DSA will then maintain a mapping of _at
-+	 * least_ these many IDs, accessible to drivers via
-+	 * dsa_lag_id().
-+	 */
-+	unsigned int		num_lag_ids;
-+
- 	size_t num_ports;
- };
- 
-@@ -432,6 +475,18 @@ static inline bool dsa_port_is_vlan_filt
- 		return dp->vlan_filtering;
- }
- 
-+static inline
-+struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp)
-+{
-+	if (!dp->bridge_dev)
-+		return NULL;
-+
-+	if (dp->lag_dev)
-+		return dp->lag_dev;
-+
-+	return dp->slave;
-+}
-+
- typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
- 			      bool is_static, void *data);
- struct dsa_switch_ops {
-@@ -629,6 +684,13 @@ struct dsa_switch_ops {
- 	void	(*crosschip_bridge_leave)(struct dsa_switch *ds, int tree_index,
- 					  int sw_index, int port,
- 					  struct net_device *br);
-+	int	(*crosschip_lag_change)(struct dsa_switch *ds, int sw_index,
-+					int port);
-+	int	(*crosschip_lag_join)(struct dsa_switch *ds, int sw_index,
-+				      int port, struct net_device *lag,
-+				      struct netdev_lag_upper_info *info);
-+	int	(*crosschip_lag_leave)(struct dsa_switch *ds, int sw_index,
-+				       int port, struct net_device *lag);
- 
- 	/*
- 	 * PTP functionality
-@@ -660,6 +722,16 @@ struct dsa_switch_ops {
- 	int	(*port_change_mtu)(struct dsa_switch *ds, int port,
- 				   int new_mtu);
- 	int	(*port_max_mtu)(struct dsa_switch *ds, int port);
-+
-+	/*
-+	 * LAG integration
-+	 */
-+	int	(*port_lag_change)(struct dsa_switch *ds, int port);
-+	int	(*port_lag_join)(struct dsa_switch *ds, int port,
-+				 struct net_device *lag,
-+				 struct netdev_lag_upper_info *info);
-+	int	(*port_lag_leave)(struct dsa_switch *ds, int port,
-+				  struct net_device *lag);
- };
- 
- #define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes)		\
---- a/net/dsa/dsa.c
-+++ b/net/dsa/dsa.c
-@@ -220,11 +220,21 @@ static int dsa_switch_rcv(struct sk_buff
- 	}
- 
- 	skb = nskb;
--	p = netdev_priv(skb->dev);
- 	skb_push(skb, ETH_HLEN);
- 	skb->pkt_type = PACKET_HOST;
- 	skb->protocol = eth_type_trans(skb, skb->dev);
- 
-+	if (unlikely(!dsa_slave_dev_check(skb->dev))) {
-+		/* Packet is to be injected directly on an upper
-+		 * device, e.g. a team/bond, so skip all DSA-port
-+		 * specific actions.
-+		 */
-+		netif_rx(skb);
-+		return 0;
-+	}
-+
-+	p = netdev_priv(skb->dev);
-+
- 	if (unlikely(cpu_dp->ds->untag_bridge_pvid)) {
- 		nskb = dsa_untag_bridge_pvid(skb);
- 		if (!nskb) {
---- a/net/dsa/dsa2.c
-+++ b/net/dsa/dsa2.c
-@@ -21,6 +21,65 @@
- static DEFINE_MUTEX(dsa2_mutex);
- LIST_HEAD(dsa_tree_list);
- 
-+/**
-+ * dsa_lag_map() - Map LAG netdev to a linear LAG ID
-+ * @dst: Tree in which to record the mapping.
-+ * @lag: Netdev that is to be mapped to an ID.
-+ *
-+ * dsa_lag_id/dsa_lag_dev can then be used to translate between the
-+ * two spaces. The size of the mapping space is determined by the
-+ * driver by setting ds->num_lag_ids. It is perfectly legal to leave
-+ * it unset if it is not needed, in which case these functions become
-+ * no-ops.
-+ */
-+void dsa_lag_map(struct dsa_switch_tree *dst, struct net_device *lag)
-+{
-+	unsigned int id;
-+
-+	if (dsa_lag_id(dst, lag) >= 0)
-+		/* Already mapped */
-+		return;
-+
-+	for (id = 0; id < dst->lags_len; id++) {
-+		if (!dsa_lag_dev(dst, id)) {
-+			dst->lags[id] = lag;
-+			return;
-+		}
-+	}
-+
-+	/* No IDs left, which is OK. Some drivers do not need it. The
-+	 * ones that do, e.g. mv88e6xxx, will discover that dsa_lag_id
-+	 * returns an error for this device when joining the LAG. The
-+	 * driver can then return -EOPNOTSUPP back to DSA, which will
-+	 * fall back to a software LAG.
-+	 */
-+}
-+
-+/**
-+ * dsa_lag_unmap() - Remove a LAG ID mapping
-+ * @dst: Tree in which the mapping is recorded.
-+ * @lag: Netdev that was mapped.
-+ *
-+ * As there may be multiple users of the mapping, it is only removed
-+ * if there are no other references to it.
-+ */
-+void dsa_lag_unmap(struct dsa_switch_tree *dst, struct net_device *lag)
-+{
-+	struct dsa_port *dp;
-+	unsigned int id;
-+
-+	dsa_lag_foreach_port(dp, dst, lag)
-+		/* There are remaining users of this mapping */
-+		return;
-+
-+	dsa_lags_foreach_id(id, dst) {
-+		if (dsa_lag_dev(dst, id) == lag) {
-+			dst->lags[id] = NULL;
-+			break;
-+		}
-+	}
-+}
-+
- struct dsa_switch *dsa_switch_find(int tree_index, int sw_index)
- {
- 	struct dsa_switch_tree *dst;
-@@ -597,6 +656,32 @@ static void dsa_tree_teardown_master(str
- 			dsa_master_teardown(dp->master);
- }
- 
-+static int dsa_tree_setup_lags(struct dsa_switch_tree *dst)
-+{
-+	unsigned int len = 0;
-+	struct dsa_port *dp;
-+
-+	list_for_each_entry(dp, &dst->ports, list) {
-+		if (dp->ds->num_lag_ids > len)
-+			len = dp->ds->num_lag_ids;
-+	}
-+
-+	if (!len)
-+		return 0;
-+
-+	dst->lags = kcalloc(len, sizeof(*dst->lags), GFP_KERNEL);
-+	if (!dst->lags)
-+		return -ENOMEM;
-+
-+	dst->lags_len = len;
-+	return 0;
-+}
-+
-+static void dsa_tree_teardown_lags(struct dsa_switch_tree *dst)
-+{
-+	kfree(dst->lags);
-+}
-+
- static int dsa_tree_setup(struct dsa_switch_tree *dst)
- {
- 	bool complete;
-@@ -624,12 +709,18 @@ static int dsa_tree_setup(struct dsa_swi
- 	if (err)
- 		goto teardown_switches;
- 
-+	err = dsa_tree_setup_lags(dst);
-+	if (err)
-+		goto teardown_master;
-+
- 	dst->setup = true;
- 
- 	pr_info("DSA: tree %d setup\n", dst->index);
- 
- 	return 0;
- 
-+teardown_master:
-+	dsa_tree_teardown_master(dst);
- teardown_switches:
- 	dsa_tree_teardown_switches(dst);
- teardown_default_cpu:
-@@ -645,6 +736,8 @@ static void dsa_tree_teardown(struct dsa
- 	if (!dst->setup)
- 		return;
- 
-+	dsa_tree_teardown_lags(dst);
-+
- 	dsa_tree_teardown_master(dst);
- 
- 	dsa_tree_teardown_switches(dst);
---- a/net/dsa/dsa_priv.h
-+++ b/net/dsa/dsa_priv.h
-@@ -20,6 +20,9 @@ enum {
- 	DSA_NOTIFIER_BRIDGE_LEAVE,
- 	DSA_NOTIFIER_FDB_ADD,
- 	DSA_NOTIFIER_FDB_DEL,
-+	DSA_NOTIFIER_LAG_CHANGE,
-+	DSA_NOTIFIER_LAG_JOIN,
-+	DSA_NOTIFIER_LAG_LEAVE,
- 	DSA_NOTIFIER_MDB_ADD,
- 	DSA_NOTIFIER_MDB_DEL,
- 	DSA_NOTIFIER_VLAN_ADD,
-@@ -57,6 +60,15 @@ struct dsa_notifier_mdb_info {
- 	int port;
- };
- 
-+/* DSA_NOTIFIER_LAG_* */
-+struct dsa_notifier_lag_info {
-+	struct net_device *lag;
-+	int sw_index;
-+	int port;
-+
-+	struct netdev_lag_upper_info *info;
-+};
-+
- /* DSA_NOTIFIER_VLAN_* */
- struct dsa_notifier_vlan_info {
- 	const struct switchdev_obj_port_vlan *vlan;
-@@ -149,6 +161,11 @@ void dsa_port_disable_rt(struct dsa_port
- void dsa_port_disable(struct dsa_port *dp);
- int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
- void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
-+int dsa_port_lag_change(struct dsa_port *dp,
-+			struct netdev_lag_lower_state_info *linfo);
-+int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag_dev,
-+		      struct netdev_lag_upper_info *uinfo);
-+void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag_dev);
- int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
- 			    struct switchdev_trans *trans);
- bool dsa_port_skip_vlan_configuration(struct dsa_port *dp);
-@@ -181,6 +198,71 @@ int dsa_port_link_register_of(struct dsa
- void dsa_port_link_unregister_of(struct dsa_port *dp);
- extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
- 
-+static inline bool dsa_port_offloads_netdev(struct dsa_port *dp,
-+					    struct net_device *dev)
-+{
-+	/* Switchdev offloading can be configured on: */
-+
-+	if (dev == dp->slave)
-+		/* DSA ports directly connected to a bridge, and event
-+		 * was emitted for the ports themselves.
-+		 */
-+		return true;
-+
-+	if (dp->bridge_dev == dev)
-+		/* DSA ports connected to a bridge, and event was emitted
-+		 * for the bridge.
-+		 */
-+		return true;
-+
-+	if (dp->lag_dev == dev)
-+		/* DSA ports connected to a bridge via a LAG */
-+		return true;
-+
-+	return false;
-+}
-+
-+static inline bool dsa_port_offloads_bridge_port(struct dsa_port *dp,
-+						 struct net_device *dev)
-+{
-+	return dsa_port_to_bridge_port(dp) == dev;
-+}
-+
-+static inline bool dsa_port_offloads_bridge(struct dsa_port *dp,
-+					    struct net_device *bridge_dev)
-+{
-+	/* DSA ports connected to a bridge, and event was emitted
-+	 * for the bridge.
-+	 */
-+	return dp->bridge_dev == bridge_dev;
-+}
-+
-+/* Returns true if any port of this tree offloads the given net_device */
-+static inline bool dsa_tree_offloads_bridge_port(struct dsa_switch_tree *dst,
-+						 struct net_device *dev)
-+{
-+	struct dsa_port *dp;
-+
-+	list_for_each_entry(dp, &dst->ports, list)
-+		if (dsa_port_offloads_bridge_port(dp, dev))
-+			return true;
-+
-+	return false;
-+}
-+
-+/* Returns true if any port of this tree offloads the given net_device */
-+static inline bool dsa_tree_offloads_netdev(struct dsa_switch_tree *dst,
-+					    struct net_device *dev)
-+{
-+	struct dsa_port *dp;
-+
-+	list_for_each_entry(dp, &dst->ports, list)
-+		if (dsa_port_offloads_netdev(dp, dev))
-+			return true;
-+
-+	return false;
-+}
-+
- /* slave.c */
- extern const struct dsa_device_ops notag_netdev_ops;
- void dsa_slave_mii_bus_init(struct dsa_switch *ds);
-@@ -285,6 +367,9 @@ int dsa_switch_register_notifier(struct
- void dsa_switch_unregister_notifier(struct dsa_switch *ds);
- 
- /* dsa2.c */
-+void dsa_lag_map(struct dsa_switch_tree *dst, struct net_device *lag);
-+void dsa_lag_unmap(struct dsa_switch_tree *dst, struct net_device *lag);
-+
- extern struct list_head dsa_tree_list;
- 
- #endif
---- a/net/dsa/port.c
-+++ b/net/dsa/port.c
-@@ -193,6 +193,99 @@ void dsa_port_bridge_leave(struct dsa_po
- 	dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
- }
- 
-+int dsa_port_lag_change(struct dsa_port *dp,
-+			struct netdev_lag_lower_state_info *linfo)
-+{
-+	struct dsa_notifier_lag_info info = {
-+		.sw_index = dp->ds->index,
-+		.port = dp->index,
-+	};
-+	bool tx_enabled;
-+
-+	if (!dp->lag_dev)
-+		return 0;
-+
-+	/* On statically configured aggregates (e.g. loadbalance
-+	 * without LACP) ports will always be tx_enabled, even if the
-+	 * link is down. Thus we require both link_up and tx_enabled
-+	 * in order to include it in the tx set.
-+	 */
-+	tx_enabled = linfo->link_up && linfo->tx_enabled;
-+
-+	if (tx_enabled == dp->lag_tx_enabled)
-+		return 0;
-+
-+	dp->lag_tx_enabled = tx_enabled;
-+
-+	return dsa_port_notify(dp, DSA_NOTIFIER_LAG_CHANGE, &info);
-+}
-+
-+int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag,
-+		      struct netdev_lag_upper_info *uinfo)
-+{
-+	struct dsa_notifier_lag_info info = {
-+		.sw_index = dp->ds->index,
-+		.port = dp->index,
-+		.lag = lag,
-+		.info = uinfo,
-+	};
-+	struct net_device *bridge_dev;
-+	int err;
-+
-+	dsa_lag_map(dp->ds->dst, lag);
-+	dp->lag_dev = lag;
-+
-+	err = dsa_port_notify(dp, DSA_NOTIFIER_LAG_JOIN, &info);
-+	if (err)
-+		goto err_lag_join;
-+
-+	bridge_dev = netdev_master_upper_dev_get(lag);
-+	if (!bridge_dev || !netif_is_bridge_master(bridge_dev))
-+		return 0;
-+
-+	err = dsa_port_bridge_join(dp, bridge_dev);
-+	if (err)
-+		goto err_bridge_join;
-+
-+	return 0;
-+
-+err_bridge_join:
-+	dsa_port_notify(dp, DSA_NOTIFIER_LAG_LEAVE, &info);
-+err_lag_join:
-+	dp->lag_dev = NULL;
-+	dsa_lag_unmap(dp->ds->dst, lag);
-+	return err;
-+}
-+
-+void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag)
-+{
-+	struct dsa_notifier_lag_info info = {
-+		.sw_index = dp->ds->index,
-+		.port = dp->index,
-+		.lag = lag,
-+	};
-+	int err;
-+
-+	if (!dp->lag_dev)
-+		return;
-+
-+	/* 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);
-+
-+	dp->lag_tx_enabled = false;
-+	dp->lag_dev = NULL;
-+
-+	err = dsa_port_notify(dp, DSA_NOTIFIER_LAG_LEAVE, &info);
-+	if (err)
-+		pr_err("DSA: failed to notify DSA_NOTIFIER_LAG_LEAVE: %d\n",
-+		       err);
-+
-+	dsa_lag_unmap(dp->ds->dst, lag);
-+}
-+
- /* Must be called under rcu_read_lock() */
- static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
- 					      bool vlan_filtering)
---- a/net/dsa/slave.c
-+++ b/net/dsa/slave.c
-@@ -337,9 +337,6 @@ static int dsa_slave_vlan_add(struct net
- 	struct switchdev_obj_port_vlan vlan;
- 	int vid, err;
- 
--	if (obj->orig_dev != dev)
--		return -EOPNOTSUPP;
--
- 	if (dsa_port_skip_vlan_configuration(dp))
- 		return 0;
- 
-@@ -394,11 +391,13 @@ static int dsa_slave_port_obj_add(struct
- 
- 	switch (obj->id) {
- 	case SWITCHDEV_OBJ_ID_PORT_MDB:
--		if (obj->orig_dev != dev)
-+		if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
- 			return -EOPNOTSUPP;
- 		err = dsa_port_mdb_add(dp, SWITCHDEV_OBJ_PORT_MDB(obj), trans);
- 		break;
- 	case SWITCHDEV_OBJ_ID_HOST_MDB:
-+		if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
-+			return -EOPNOTSUPP;
- 		/* DSA can directly translate this to a normal MDB add,
- 		 * but on the CPU port.
- 		 */
-@@ -406,6 +405,9 @@ static int dsa_slave_port_obj_add(struct
- 				       trans);
- 		break;
- 	case SWITCHDEV_OBJ_ID_PORT_VLAN:
-+		if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
-+			return -EOPNOTSUPP;
-+
- 		err = dsa_slave_vlan_add(dev, obj, trans);
- 		break;
- 	default:
-@@ -424,9 +426,6 @@ static int dsa_slave_vlan_del(struct net
- 	struct switchdev_obj_port_vlan *vlan;
- 	int vid, err;
- 
--	if (obj->orig_dev != dev)
--		return -EOPNOTSUPP;
--
- 	if (dsa_port_skip_vlan_configuration(dp))
- 		return 0;
- 
-@@ -453,17 +452,22 @@ static int dsa_slave_port_obj_del(struct
- 
- 	switch (obj->id) {
- 	case SWITCHDEV_OBJ_ID_PORT_MDB:
--		if (obj->orig_dev != dev)
-+		if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
- 			return -EOPNOTSUPP;
- 		err = dsa_port_mdb_del(dp, SWITCHDEV_OBJ_PORT_MDB(obj));
- 		break;
- 	case SWITCHDEV_OBJ_ID_HOST_MDB:
-+		if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
-+			return -EOPNOTSUPP;
- 		/* DSA can directly translate this to a normal MDB add,
- 		 * but on the CPU port.
- 		 */
- 		err = dsa_port_mdb_del(dp->cpu_dp, SWITCHDEV_OBJ_PORT_MDB(obj));
- 		break;
- 	case SWITCHDEV_OBJ_ID_PORT_VLAN:
-+		if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
-+			return -EOPNOTSUPP;
-+
- 		err = dsa_slave_vlan_del(dev, obj);
- 		break;
- 	default:
-@@ -1993,6 +1997,46 @@ static int dsa_slave_changeupper(struct
- 			dsa_port_bridge_leave(dp, info->upper_dev);
- 			err = NOTIFY_OK;
- 		}
-+	} else if (netif_is_lag_master(info->upper_dev)) {
-+		if (info->linking) {
-+			err = dsa_port_lag_join(dp, info->upper_dev,
-+						info->upper_info);
-+			if (err == -EOPNOTSUPP) {
-+				NL_SET_ERR_MSG_MOD(info->info.extack,
-+						   "Offloading not supported");
-+				err = 0;
-+			}
-+			err = notifier_from_errno(err);
-+		} else {
-+			dsa_port_lag_leave(dp, info->upper_dev);
-+			err = NOTIFY_OK;
-+		}
-+	}
-+
-+	return err;
-+}
-+
-+static int
-+dsa_slave_lag_changeupper(struct net_device *dev,
-+			  struct netdev_notifier_changeupper_info *info)
-+{
-+	struct net_device *lower;
-+	struct list_head *iter;
-+	int err = NOTIFY_DONE;
-+	struct dsa_port *dp;
-+
-+	netdev_for_each_lower_dev(dev, lower, iter) {
-+		if (!dsa_slave_dev_check(lower))
-+			continue;
-+
-+		dp = dsa_slave_to_port(lower);
-+		if (!dp->lag_dev)
-+			/* Software LAG */
-+			continue;
-+
-+		err = dsa_slave_changeupper(lower, info);
-+		if (notifier_to_errno(err))
-+			break;
- 	}
- 
- 	return err;
-@@ -2078,10 +2122,26 @@ static int dsa_slave_netdevice_event(str
- 		break;
- 	}
- 	case NETDEV_CHANGEUPPER:
-+		if (dsa_slave_dev_check(dev))
-+			return dsa_slave_changeupper(dev, ptr);
-+
-+		if (netif_is_lag_master(dev))
-+			return dsa_slave_lag_changeupper(dev, ptr);
-+
-+		break;
-+	case NETDEV_CHANGELOWERSTATE: {
-+		struct netdev_notifier_changelowerstate_info *info = ptr;
-+		struct dsa_port *dp;
-+		int err;
-+
- 		if (!dsa_slave_dev_check(dev))
--			return NOTIFY_DONE;
-+			break;
- 
--		return dsa_slave_changeupper(dev, ptr);
-+		dp = dsa_slave_to_port(dev);
-+
-+		err = dsa_port_lag_change(dp, info->lower_state_info);
-+		return notifier_from_errno(err);
-+	}
- 	}
- 
- 	return NOTIFY_DONE;
-@@ -2229,6 +2289,15 @@ static int dsa_slave_switchdev_event(str
- 			if (!fdb_info->added_by_user &&
- 			    !dp->ds->assisted_learning_on_cpu_port)
- 				return NOTIFY_DONE;
-+
-+			/* When the bridge learns an address on an offloaded
-+			 * LAG we don't want to send traffic to the CPU, the
-+			 * other ports bridged with the LAG should be able to
-+			 * autonomously forward towards it.
-+			 */
-+			if (dsa_tree_offloads_netdev(dp->ds->dst, dev))
-+				return NOTIFY_DONE;
-+
- 		}
- 
- 		if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del)
---- a/net/dsa/switch.c
-+++ b/net/dsa/switch.c
-@@ -193,6 +193,47 @@ static int dsa_switch_fdb_del(struct dsa
- 	return ds->ops->port_fdb_del(ds, port, info->addr, info->vid);
- }
- 
-+static int dsa_switch_lag_change(struct dsa_switch *ds,
-+				 struct dsa_notifier_lag_info *info)
-+{
-+	if (ds->index == info->sw_index && ds->ops->port_lag_change)
-+		return ds->ops->port_lag_change(ds, info->port);
-+
-+	if (ds->index != info->sw_index && ds->ops->crosschip_lag_change)
-+		return ds->ops->crosschip_lag_change(ds, info->sw_index,
-+						     info->port);
-+
-+	return 0;
-+}
-+
-+static int dsa_switch_lag_join(struct dsa_switch *ds,
-+			       struct dsa_notifier_lag_info *info)
-+{
-+	if (ds->index == info->sw_index && ds->ops->port_lag_join)
-+		return ds->ops->port_lag_join(ds, info->port, info->lag,
-+					      info->info);
-+
-+	if (ds->index != info->sw_index && ds->ops->crosschip_lag_join)
-+		return ds->ops->crosschip_lag_join(ds, info->sw_index,
-+						   info->port, info->lag,
-+						   info->info);
-+
-+	return -EOPNOTSUPP;
-+}
-+
-+static int dsa_switch_lag_leave(struct dsa_switch *ds,
-+				struct dsa_notifier_lag_info *info)
-+{
-+	if (ds->index == info->sw_index && ds->ops->port_lag_leave)
-+		return ds->ops->port_lag_leave(ds, info->port, info->lag);
-+
-+	if (ds->index != info->sw_index && ds->ops->crosschip_lag_leave)
-+		return ds->ops->crosschip_lag_leave(ds, info->sw_index,
-+						    info->port, info->lag);
-+
-+	return -EOPNOTSUPP;
-+}
-+
- static bool dsa_switch_mdb_match(struct dsa_switch *ds, int port,
- 				 struct dsa_notifier_mdb_info *info)
- {
-@@ -340,6 +381,15 @@ static int dsa_switch_event(struct notif
- 	case DSA_NOTIFIER_FDB_DEL:
- 		err = dsa_switch_fdb_del(ds, info);
- 		break;
-+	case DSA_NOTIFIER_LAG_CHANGE:
-+		err = dsa_switch_lag_change(ds, info);
-+		break;
-+	case DSA_NOTIFIER_LAG_JOIN:
-+		err = dsa_switch_lag_join(ds, info);
-+		break;
-+	case DSA_NOTIFIER_LAG_LEAVE:
-+		err = dsa_switch_lag_leave(ds, info);
-+		break;
- 	case DSA_NOTIFIER_MDB_ADD:
- 		err = dsa_switch_mdb_add(ds, info);
- 		break;
---- a/net/dsa/tag_dsa.c
-+++ b/net/dsa/tag_dsa.c
-@@ -82,7 +82,19 @@ static struct sk_buff *dsa_rcv(struct sk
- 	source_device = dsa_header[0] & 0x1f;
- 	source_port = (dsa_header[1] >> 3) & 0x1f;
- 
--	skb->dev = dsa_master_find_slave(dev, source_device, source_port);
-+	if (trunk) {
-+		struct dsa_port *cpu_dp = dev->dsa_ptr;
-+
-+		/* The exact source port is not available in the tag,
-+		 * so we inject the frame directly on the upper
-+		 * team/bond.
-+		 */
-+		skb->dev = dsa_lag_dev(cpu_dp->dst, source_port);
-+	} else {
-+		skb->dev = dsa_master_find_slave(dev, source_device,
-+						 source_port);
-+	}
-+
- 	if (!skb->dev)
- 		return NULL;
- 
diff --git a/target/linux/realtek/patches-5.15/713-v5.12-net-dsa-configure-better-brport-flags-when-ports-lea.patch b/target/linux/realtek/patches-5.15/713-v5.12-net-dsa-configure-better-brport-flags-when-ports-lea.patch
deleted file mode 100644
index a3bfec59ab..0000000000
--- a/target/linux/realtek/patches-5.15/713-v5.12-net-dsa-configure-better-brport-flags-when-ports-lea.patch
+++ /dev/null
@@ -1,148 +0,0 @@
-From: Vladimir Oltean <vladimir.oltean at nxp.com>
-Date: Fri, 12 Feb 2021 17:15:54 +0200
-Subject: [PATCH] net: dsa: configure better brport flags when ports leave the
- bridge
-
-Bugfixed version of upstream commit 5e38c15856e9 ("net: dsa: configure
-better brport flags when ports leave the bridge")
-
-For a DSA switch port operating in standalone mode, address learning
-doesn't make much sense since that is a bridge function. In fact,
-address learning even breaks setups such as this one:
-
-   +---------------------------------------------+
-   |                                             |
-   | +-------------------+                       |
-   | |        br0        |    send      receive  |
-   | +--------+-+--------+ +--------+ +--------+ |
-   | |        | |        | |        | |        | |
-   | |  swp0  | |  swp1  | |  swp2  | |  swp3  | |
-   | |        | |        | |        | |        | |
-   +-+--------+-+--------+-+--------+-+--------+-+
-          |         ^           |          ^
-          |         |           |          |
-          |         +-----------+          |
-          |                                |
-          +--------------------------------+
-
-because if the switch has a single FDB (can offload a single bridge)
-then source address learning on swp3 can "steal" the source MAC address
-of swp2 from br0's FDB, because learning frames coming from swp2 will be
-done twice: first on the swp1 ingress port, second on the swp3 ingress
-port. So the hardware FDB will become out of sync with the software
-bridge, and when swp2 tries to send one more packet towards swp1, the
-ASIC will attempt to short-circuit the forwarding path and send it
-directly to swp3 (since that's the last port it learned that address on),
-which it obviously can't, because swp3 operates in standalone mode.
-
-So DSA drivers operating in standalone mode should still configure a
-list of bridge port flags even when they are standalone. Currently DSA
-attempts to call dsa_port_bridge_flags with 0, which disables egress
-flooding of unknown unicast and multicast, something which doesn't make
-much sense. For the switches that implement .port_egress_floods - b53
-and mv88e6xxx, it probably doesn't matter too much either, since they
-can possibly inject traffic from the CPU into a standalone port,
-regardless of MAC DA, even if egress flooding is turned off for that
-port, but certainly not all DSA switches can do that - sja1105, for
-example, can't. So it makes sense to use a better common default there,
-such as "flood everything".
-
-It should also be noted that what DSA calls "dsa_port_bridge_flags()"
-is a degenerate name for just calling .port_egress_floods(), since
-nothing else is implemented - not learning, in particular. But disabling
-address learning, something that this driver is also coding up for, will
-be supported by individual drivers once .port_egress_floods is replaced
-with a more generic .port_bridge_flags.
-
-Previous attempts to code up this logic have been in the common bridge
-layer, but as pointed out by Ido Schimmel, there are corner cases that
-are missed when doing that:
-https://patchwork.kernel.org/project/netdevbpf/patch/20210209151936.97382-5-olteanv@gmail.com/
-
-So, at least for now, let's leave DSA in charge of setting port flags
-before and after the bridge join and leave.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
-Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
-Signed-off-by: David S. Miller <davem at davemloft.net>
-[ backport and bugfix: break dsa_port_bridge_flags() out of loop ]
-Signed-off-by: Bjørn Mork <bjorn at mork.no>
----
- net/dsa/port.c | 45 ++++++++++++++++++++++++++++++++++++++-------
- 1 file changed, 38 insertions(+), 7 deletions(-)
-
---- a/net/dsa/port.c
-+++ b/net/dsa/port.c
-@@ -134,6 +134,27 @@ void dsa_port_disable(struct dsa_port *d
- 	rtnl_unlock();
- }
- 
-+static void dsa_port_change_brport_flags(struct dsa_port *dp,
-+					 bool bridge_offload)
-+{
-+	unsigned long mask, flags;
-+	int flag, err;
-+
-+	mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
-+	if (bridge_offload)
-+		flags = mask;
-+	else
-+		flags = mask & ~BR_LEARNING;
-+
-+	for_each_set_bit(flag, &mask, 32) {
-+		err = dsa_port_pre_bridge_flags(dp, BIT(flag), NULL, NULL);
-+		if (err)
-+			flags &= ~BIT(flag);
-+	}
-+
-+	dsa_port_bridge_flags(dp, flags, NULL, NULL);
-+}
-+
- int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br)
- {
- 	struct dsa_notifier_bridge_info info = {
-@@ -144,10 +165,10 @@ int dsa_port_bridge_join(struct dsa_port
- 	};
- 	int err;
- 
--	/* Set the flooding mode before joining the port in the switch */
--	err = dsa_port_bridge_flags(dp, BR_FLOOD | BR_MCAST_FLOOD, NULL, NULL);
--	if (err)
--		return err;
-+	/* Notify the port driver to set its configurable flags in a way that
-+	 * matches the initial settings of a bridge port.
-+	 */
-+	dsa_port_change_brport_flags(dp, true);
- 
- 	/* Here the interface is already bridged. Reflect the current
- 	 * configuration so that drivers can program their chips accordingly.
-@@ -158,7 +179,7 @@ int dsa_port_bridge_join(struct dsa_port
- 
- 	/* The bridging is rolled back on error */
- 	if (err) {
--		dsa_port_bridge_flags(dp, 0, NULL, NULL);
-+		dsa_port_change_brport_flags(dp, false);
- 		dp->bridge_dev = NULL;
- 	}
- 
-@@ -184,8 +205,18 @@ void dsa_port_bridge_leave(struct dsa_po
- 	if (err)
- 		pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
- 
--	/* Port is leaving the bridge, disable flooding */
--	dsa_port_bridge_flags(dp, 0, NULL, NULL);
-+	/* Configure the port for standalone mode (no address learning,
-+	 * flood everything).
-+	 * The bridge only emits SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS events
-+	 * when the user requests it through netlink or sysfs, but not
-+	 * automatically at port join or leave, so we need to handle resetting
-+	 * the brport flags ourselves. But we even prefer it that way, because
-+	 * otherwise, some setups might never get the notification they need,
-+	 * for example, when a port leaves a LAG that offloads the bridge,
-+	 * it becomes standalone, but as far as the bridge is concerned, no
-+	 * port ever left.
-+	 */
-+	dsa_port_change_brport_flags(dp, false);
- 
- 	/* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
- 	 * so allow it to be in BR_STATE_FORWARDING to be kept functional




More information about the lede-commits mailing list