[openwrt/openwrt] mediatek: add kernel code for supporting offloading wlan->eth and wlan->wlan flows

LEDE Commits lede-commits at lists.infradead.org
Thu Mar 23 09:54:48 PDT 2023


nbd pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/d0a06965e8ab0a92a4813fddbb8e045407897310

commit d0a06965e8ab0a92a4813fddbb8e045407897310
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Mon Mar 20 18:51:06 2023 +0100

    mediatek: add kernel code for supporting offloading wlan->eth and wlan->wlan flows
    
    Will be enabled by an upcoming mt76 update
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 ...11-add-support-for-letting-drivers-regist.patch | 149 ++++++++++++
 .../500-mac80211_configure_antenna_gain.patch      |   8 +-
 .../generic/hack-5.10/100-update-mtk_wed_h.patch   |  25 +-
 ...t-mtk_eth_soc-add-code-for-offloading-flo.patch | 266 +++++++++++++++++++++
 ...t-mediatek-mtk_ppe-prefer-newly-added-l2-.patch |  37 +++
 ...net-mtk_wed-move-dlm-a-dedicated-dts-node.patch |   4 +-
 6 files changed, 477 insertions(+), 12 deletions(-)

diff --git a/package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch b/package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch
new file mode 100644
index 0000000000..f1807bdc8a
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch
@@ -0,0 +1,149 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Mon, 20 Mar 2023 14:28:08 +0100
+Subject: [PATCH] wifi: mac80211: add support for letting drivers register tc
+ offload support
+
+On newer MediaTek SoCs (e.g. MT7986), WLAN->WLAN or WLAN->Ethernet flows can
+be offloaded by the SoC. In order to support that, the .ndo_setup_tc op is
+needed.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -4196,6 +4196,10 @@ struct ieee80211_prep_tx_info {
+  *	Note that a sta can also be inserted or removed with valid links,
+  *	i.e. passed to @sta_add/@sta_state with sta->valid_links not zero.
+  *	In fact, cannot change from having valid_links and not having them.
++ * @net_setup_tc: Called from .ndo_setup_tc in order to prepare hardware
++ *	flow offloading for flows originating from the vif.
++ *	Note that the driver must not assume that the vif driver_data is valid
++ *	at this point, since the callback can be called during netdev teardown.
+  */
+ struct ieee80211_ops {
+ 	void (*tx)(struct ieee80211_hw *hw,
+@@ -4551,6 +4555,11 @@ struct ieee80211_ops {
+ 				struct ieee80211_vif *vif,
+ 				struct ieee80211_sta *sta,
+ 				u16 old_links, u16 new_links);
++	int (*net_setup_tc)(struct ieee80211_hw *hw,
++			    struct ieee80211_vif *vif,
++			    struct net_device *dev,
++			    enum tc_setup_type type,
++			    void *type_data);
+ };
+ 
+ /**
+--- a/net/mac80211/driver-ops.h
++++ b/net/mac80211/driver-ops.h
+@@ -1470,6 +1470,23 @@ static inline int drv_net_fill_forward_p
+ 	return ret;
+ }
+ 
++static inline int drv_net_setup_tc(struct ieee80211_local *local,
++				   struct ieee80211_sub_if_data *sdata,
++				   struct net_device *dev,
++				   enum tc_setup_type type, void *type_data)
++{
++	int ret = -EOPNOTSUPP;
++
++	sdata = get_bss_sdata(sdata);
++	trace_drv_net_setup_tc(local, sdata, type);
++	if (local->ops->net_setup_tc)
++		ret = local->ops->net_setup_tc(&local->hw, &sdata->vif, dev,
++					       type, type_data);
++	trace_drv_return_int(local, ret);
++
++	return ret;
++}
++
+ int drv_change_vif_links(struct ieee80211_local *local,
+ 			 struct ieee80211_sub_if_data *sdata,
+ 			 u16 old_links, u16 new_links,
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1935,7 +1935,8 @@ void ieee80211_color_change_finalize_wor
+ /* interface handling */
+ #define MAC80211_SUPPORTED_FEATURES_TX	(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
+ 					 NETIF_F_HW_CSUM | NETIF_F_SG | \
+-					 NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE)
++					 NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE | \
++					 NETIF_F_HW_TC)
+ #define MAC80211_SUPPORTED_FEATURES_RX	(NETIF_F_RXCSUM)
+ #define MAC80211_SUPPORTED_FEATURES	(MAC80211_SUPPORTED_FEATURES_TX | \
+ 					 MAC80211_SUPPORTED_FEATURES_RX)
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -813,6 +813,21 @@ ieee80211_get_stats64(struct net_device
+ 	dev_fetch_sw_netstats(stats, dev->tstats);
+ }
+ 
++static int ieee80211_netdev_setup_tc(struct net_device *dev,
++				     enum tc_setup_type type, void *type_data)
++{
++	struct ieee80211_sub_if_data *sdata;
++	struct ieee80211_local *local;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	local = sdata->local;
++
++	if (!local->ops->net_setup_tc)
++		return -EOPNOTSUPP;
++
++	return drv_net_setup_tc(local, sdata, dev, type, type_data);
++}
++
+ static const struct net_device_ops ieee80211_dataif_ops = {
+ 	.ndo_open		= ieee80211_open,
+ 	.ndo_stop		= ieee80211_stop,
+@@ -821,6 +836,7 @@ static const struct net_device_ops ieee8
+ 	.ndo_set_rx_mode	= ieee80211_set_multicast_list,
+ 	.ndo_set_mac_address 	= ieee80211_change_mac,
+ 	.ndo_get_stats64	= ieee80211_get_stats64,
++	.ndo_setup_tc		= ieee80211_netdev_setup_tc,
+ };
+ 
+ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
+@@ -929,6 +945,7 @@ static const struct net_device_ops ieee8
+ 	.ndo_set_mac_address	= ieee80211_change_mac,
+ 	.ndo_get_stats64	= ieee80211_get_stats64,
+ 	.ndo_fill_forward_path	= ieee80211_netdev_fill_forward_path,
++	.ndo_setup_tc		= ieee80211_netdev_setup_tc,
+ };
+ 
+ static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
+--- a/net/mac80211/trace.h
++++ b/net/mac80211/trace.h
+@@ -2478,6 +2478,31 @@ DEFINE_EVENT(sta_event, drv_net_fill_for
+ 	TP_ARGS(local, sdata, sta)
+ );
+ 
++TRACE_EVENT(drv_net_setup_tc,
++	TP_PROTO(struct ieee80211_local *local,
++		 struct ieee80211_sub_if_data *sdata,
++		 u8 type),
++
++	TP_ARGS(local, sdata, type),
++
++	TP_STRUCT__entry(
++		LOCAL_ENTRY
++		VIF_ENTRY
++		__field(u8, type)
++	),
++
++	TP_fast_assign(
++		LOCAL_ASSIGN;
++		VIF_ASSIGN;
++		__entry->type = type;
++	),
++
++	TP_printk(
++		LOCAL_PR_FMT VIF_PR_FMT " type:%d\n",
++		LOCAL_PR_ARG, VIF_PR_ARG, __entry->type
++	)
++);
++
+ TRACE_EVENT(drv_change_vif_links,
+ 	TP_PROTO(struct ieee80211_local *local,
+ 		 struct ieee80211_sub_if_data *sdata,
diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
index 80ffb493b8..d7ee33bebc 100644
--- a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
+++ b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
@@ -18,7 +18,7 @@
  
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -1645,6 +1645,7 @@ enum ieee80211_smps_mode {
+@@ -1671,6 +1671,7 @@ enum ieee80211_smps_mode {
   *
   * @power_level: requested transmit power (in dBm), backward compatibility
   *	value only that is set to the minimum of all interfaces
@@ -26,7 +26,7 @@
   *
   * @chandef: the channel definition to tune to
   * @radar_enabled: whether radar detection is enabled
-@@ -1665,6 +1666,7 @@ enum ieee80211_smps_mode {
+@@ -1691,6 +1692,7 @@ enum ieee80211_smps_mode {
  struct ieee80211_conf {
  	u32 flags;
  	int power_level, dynamic_ps_timeout;
@@ -57,7 +57,7 @@
  	__NL80211_ATTR_AFTER_LAST,
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -2998,6 +2998,19 @@ static int ieee80211_get_tx_power(struct
+@@ -3028,6 +3028,19 @@ static int ieee80211_get_tx_power(struct
  	return 0;
  }
  
@@ -77,7 +77,7 @@
  static void ieee80211_rfkill_poll(struct wiphy *wiphy)
  {
  	struct ieee80211_local *local = wiphy_priv(wiphy);
-@@ -4881,6 +4894,7 @@ const struct cfg80211_ops mac80211_confi
+@@ -4911,6 +4924,7 @@ const struct cfg80211_ops mac80211_confi
  	.set_wiphy_params = ieee80211_set_wiphy_params,
  	.set_tx_power = ieee80211_set_tx_power,
  	.get_tx_power = ieee80211_get_tx_power,
diff --git a/target/linux/generic/hack-5.10/100-update-mtk_wed_h.patch b/target/linux/generic/hack-5.10/100-update-mtk_wed_h.patch
index 151f2e8054..5f05179a36 100644
--- a/target/linux/generic/hack-5.10/100-update-mtk_wed_h.patch
+++ b/target/linux/generic/hack-5.10/100-update-mtk_wed_h.patch
@@ -1,10 +1,11 @@
 --- a/include/linux/soc/mediatek/mtk_wed.h
 +++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -5,21 +5,76 @@
+@@ -5,21 +5,77 @@
  #include <linux/rcupdate.h>
  #include <linux/regmap.h>
  #include <linux/pci.h>
 +#include <linux/skbuff.h>
++#include <linux/netdevice.h>
  
  #define MTK_WED_TX_QUEUES		2
 +#define MTK_WED_RX_QUEUES		2
@@ -77,7 +78,7 @@
  struct mtk_wed_device {
  #ifdef CONFIG_NET_MEDIATEK_SOC_WED
  	const struct mtk_wed_ops *ops;
-@@ -28,30 +83,76 @@ struct mtk_wed_device {
+@@ -28,30 +84,76 @@ struct mtk_wed_device {
  	bool init_done, running;
  	int wdma_idx;
  	int irq;
@@ -156,7 +157,7 @@
  	} wlan;
  #endif
  };
-@@ -59,10 +160,16 @@ struct mtk_wed_device {
+@@ -59,10 +161,16 @@ struct mtk_wed_device {
  struct mtk_wed_ops {
  	int (*attach)(struct mtk_wed_device *dev);
  	int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring,
@@ -174,7 +175,16 @@
  
  	void (*stop)(struct mtk_wed_device *dev);
  	void (*start)(struct mtk_wed_device *dev, u32 irq_mask);
-@@ -97,12 +204,22 @@ mtk_wed_device_attach(struct mtk_wed_dev
+@@ -73,6 +181,8 @@ struct mtk_wed_ops {
+ 
+ 	u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
+ 	void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
++	int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev,
++			enum tc_setup_type type, void *type_data);
+ };
+ 
+ extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
+@@ -97,12 +207,22 @@ mtk_wed_device_attach(struct mtk_wed_dev
  	return ret;
  }
  
@@ -199,7 +209,7 @@
  #define mtk_wed_device_txfree_ring_setup(_dev, _regs) \
  	(_dev)->ops->txfree_ring_setup(_dev, _regs)
  #define mtk_wed_device_reg_read(_dev, _reg) \
-@@ -113,6 +230,14 @@ mtk_wed_device_attach(struct mtk_wed_dev
+@@ -113,6 +233,16 @@ mtk_wed_device_attach(struct mtk_wed_dev
  	(_dev)->ops->irq_get(_dev, _mask)
  #define mtk_wed_device_irq_set_mask(_dev, _mask) \
  	(_dev)->ops->irq_set_mask(_dev, _mask)
@@ -211,10 +221,12 @@
 +	(_dev)->ops->msg_update(_dev, _id, _msg, _len)
 +#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
 +#define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
++#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \
++	(_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data)
  #else
  static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
  {
-@@ -120,12 +245,17 @@ static inline bool mtk_wed_device_active
+@@ -120,12 +250,18 @@ static inline bool mtk_wed_device_active
  }
  #define mtk_wed_device_detach(_dev) do {} while (0)
  #define mtk_wed_device_start(_dev, _mask) do {} while (0)
@@ -230,6 +242,7 @@
 +#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
 +#define mtk_wed_device_stop(_dev) do {} while (0)
 +#define mtk_wed_device_dma_reset(_dev) do {} while (0)
++#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP
  #endif
  
  #endif
diff --git a/target/linux/generic/pending-5.15/736-01-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch b/target/linux/generic/pending-5.15/736-01-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch
new file mode 100644
index 0000000000..0496752f78
--- /dev/null
+++ b/target/linux/generic/pending-5.15/736-01-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch
@@ -0,0 +1,266 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Mon, 20 Mar 2023 11:44:30 +0100
+Subject: [PATCH] net: ethernet: mtk_eth_soc: add code for offloading flows
+ from wlan devices
+
+WED version 2 (on MT7986 and later) can offload flows originating from wireless
+devices. In order to make that work, ndo_setup_tc needs to be implemented on
+the netdevs. This adds the required code to offload flows coming in from WED,
+while keeping track of the incoming wed index used for selecting the correct
+PPE device.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -1319,6 +1319,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk
+ int mtk_eth_offload_init(struct mtk_eth *eth);
+ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
+ 		     void *type_data);
++int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls,
++			 int ppe_index);
++void mtk_flow_offload_cleanup(struct mtk_eth *eth, struct list_head *list);
+ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
+ 
+ 
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+@@ -235,7 +235,8 @@ out:
+ }
+ 
+ static int
+-mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
++mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
++			 int ppe_index)
+ {
+ 	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
+ 	struct flow_action_entry *act;
+@@ -452,6 +453,7 @@ mtk_flow_offload_replace(struct mtk_eth
+ 	entry->cookie = f->cookie;
+ 	memcpy(&entry->data, &foe, sizeof(entry->data));
+ 	entry->wed_index = wed_index;
++	entry->ppe_index = ppe_index;
+ 
+ 	err = mtk_foe_entry_commit(eth->ppe[entry->ppe_index], entry);
+ 	if (err < 0)
+@@ -520,25 +522,15 @@ mtk_flow_offload_stats(struct mtk_eth *e
+ 
+ static DEFINE_MUTEX(mtk_flow_offload_mutex);
+ 
+-static int
+-mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
++int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls,
++			 int ppe_index)
+ {
+-	struct flow_cls_offload *cls = type_data;
+-	struct net_device *dev = cb_priv;
+-	struct mtk_mac *mac = netdev_priv(dev);
+-	struct mtk_eth *eth = mac->hw;
+ 	int err;
+ 
+-	if (!tc_can_offload(dev))
+-		return -EOPNOTSUPP;
+-
+-	if (type != TC_SETUP_CLSFLOWER)
+-		return -EOPNOTSUPP;
+-
+ 	mutex_lock(&mtk_flow_offload_mutex);
+ 	switch (cls->command) {
+ 	case FLOW_CLS_REPLACE:
+-		err = mtk_flow_offload_replace(eth, cls);
++		err = mtk_flow_offload_replace(eth, cls, ppe_index);
+ 		break;
+ 	case FLOW_CLS_DESTROY:
+ 		err = mtk_flow_offload_destroy(eth, cls);
+@@ -556,6 +548,23 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_
+ }
+ 
+ static int
++mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
++{
++	struct flow_cls_offload *cls = type_data;
++	struct net_device *dev = cb_priv;
++	struct mtk_mac *mac = netdev_priv(dev);
++	struct mtk_eth *eth = mac->hw;
++
++	if (!tc_can_offload(dev))
++		return -EOPNOTSUPP;
++
++	if (type != TC_SETUP_CLSFLOWER)
++		return -EOPNOTSUPP;
++
++	return mtk_flow_offload_cmd(eth, cls, 0);
++}
++
++static int
+ mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f)
+ {
+ 	struct mtk_mac *mac = netdev_priv(dev);
+--- a/drivers/net/ethernet/mediatek/mtk_wed.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed.c
+@@ -13,6 +13,8 @@
+ #include <linux/mfd/syscon.h>
+ #include <linux/debugfs.h>
+ #include <linux/soc/mediatek/mtk_wed.h>
++#include <net/flow_offload.h>
++#include <net/pkt_cls.h>
+ #include "mtk_eth_soc.h"
+ #include "mtk_wed_regs.h"
+ #include "mtk_wed.h"
+@@ -41,6 +43,11 @@
+ static struct mtk_wed_hw *hw_list[2];
+ static DEFINE_MUTEX(hw_lock);
+ 
++struct mtk_wed_flow_block_priv {
++	struct mtk_wed_hw *hw;
++	struct net_device *dev;
++};
++
+ static void
+ wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val)
+ {
+@@ -1752,6 +1759,99 @@ out:
+ 	mutex_unlock(&hw_lock);
+ }
+ 
++static int
++mtk_wed_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
++{
++	struct mtk_wed_flow_block_priv *priv = cb_priv;
++	struct flow_cls_offload *cls = type_data;
++	struct mtk_wed_hw *hw = priv->hw;
++
++	if (!tc_can_offload(priv->dev))
++		return -EOPNOTSUPP;
++
++	if (type != TC_SETUP_CLSFLOWER)
++		return -EOPNOTSUPP;
++
++	return mtk_flow_offload_cmd(hw->eth, cls, hw->index);
++}
++
++static int
++mtk_wed_setup_tc_block(struct mtk_wed_hw *hw, struct net_device *dev,
++		       struct flow_block_offload *f)
++{
++	struct mtk_wed_flow_block_priv *priv;
++	static LIST_HEAD(block_cb_list);
++	struct flow_block_cb *block_cb;
++	struct mtk_eth *eth = hw->eth;
++	flow_setup_cb_t *cb;
++
++	if (!eth->soc->offload_version)
++		return -EOPNOTSUPP;
++
++	if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
++		return -EOPNOTSUPP;
++
++	cb = mtk_wed_setup_tc_block_cb;
++	f->driver_block_list = &block_cb_list;
++
++	switch (f->command) {
++	case FLOW_BLOCK_BIND:
++		block_cb = flow_block_cb_lookup(f->block, cb, dev);
++		if (block_cb) {
++			flow_block_cb_incref(block_cb);
++			return 0;
++		}
++
++		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++		if (!priv)
++			return -ENOMEM;
++
++		priv->hw = hw;
++		priv->dev = dev;
++		block_cb = flow_block_cb_alloc(cb, dev, priv, NULL);
++		if (IS_ERR(block_cb)) {
++			kfree(priv);
++			return PTR_ERR(block_cb);
++		}
++
++		flow_block_cb_incref(block_cb);
++		flow_block_cb_add(block_cb, f);
++		list_add_tail(&block_cb->driver_list, &block_cb_list);
++		return 0;
++	case FLOW_BLOCK_UNBIND:
++		block_cb = flow_block_cb_lookup(f->block, cb, dev);
++		if (!block_cb)
++			return -ENOENT;
++
++		if (!flow_block_cb_decref(block_cb)) {
++			flow_block_cb_remove(block_cb, f);
++			list_del(&block_cb->driver_list);
++			kfree(block_cb->cb_priv);
++		}
++		return 0;
++	default:
++		return -EOPNOTSUPP;
++	}
++}
++
++static int
++mtk_wed_setup_tc(struct mtk_wed_device *wed, struct net_device *dev,
++		 enum tc_setup_type type, void *type_data)
++{
++	struct mtk_wed_hw *hw = wed->hw;
++
++	if (hw->version < 2)
++		return -EOPNOTSUPP;
++
++	switch (type) {
++	case TC_SETUP_BLOCK:
++	case TC_SETUP_FT:
++		return mtk_wed_setup_tc_block(hw, dev, type_data);
++	default:
++		return -EOPNOTSUPP;
++	}
++}
++
+ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ 		    void __iomem *wdma, phys_addr_t wdma_phy,
+ 		    int index)
+@@ -1771,6 +1871,7 @@ void mtk_wed_add_hw(struct device_node *
+ 		.irq_set_mask = mtk_wed_irq_set_mask,
+ 		.detach = mtk_wed_detach,
+ 		.ppe_check = mtk_wed_ppe_check,
++		.setup_tc = mtk_wed_setup_tc,
+ 	};
+ 	struct device_node *eth_np = eth->dev->of_node;
+ 	struct platform_device *pdev;
+--- a/include/linux/soc/mediatek/mtk_wed.h
++++ b/include/linux/soc/mediatek/mtk_wed.h
+@@ -6,6 +6,7 @@
+ #include <linux/regmap.h>
+ #include <linux/pci.h>
+ #include <linux/skbuff.h>
++#include <linux/netdevice.h>
+ 
+ #define MTK_WED_TX_QUEUES		2
+ #define MTK_WED_RX_QUEUES		2
+@@ -180,6 +181,8 @@ struct mtk_wed_ops {
+ 
+ 	u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
+ 	void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
++	int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev,
++			enum tc_setup_type type, void *type_data);
+ };
+ 
+ extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
+@@ -238,6 +241,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic
+ 	(_dev)->ops->msg_update(_dev, _id, _msg, _len)
+ #define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
+ #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
++#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \
++	(_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data)
+ #else
+ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ {
+@@ -256,6 +261,7 @@ static inline bool mtk_wed_device_active
+ #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
+ #define mtk_wed_device_stop(_dev) do {} while (0)
+ #define mtk_wed_device_dma_reset(_dev) do {} while (0)
++#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP
+ #endif
+ 
+ #endif
diff --git a/target/linux/generic/pending-5.15/736-02-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch b/target/linux/generic/pending-5.15/736-02-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch
new file mode 100644
index 0000000000..6e17e4dc52
--- /dev/null
+++ b/target/linux/generic/pending-5.15/736-02-net-ethernet-mediatek-mtk_ppe-prefer-newly-added-l2-.patch
@@ -0,0 +1,37 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Mon, 20 Mar 2023 15:37:55 +0100
+Subject: [PATCH] net: ethernet: mediatek: mtk_ppe: prefer newly added l2
+ flows over existing ones
+
+When a device is roaming between interfaces and a new flow entry is created,
+we should assume that its output device is more up to date than whatever
+entry existed already.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
+@@ -639,10 +639,20 @@ void mtk_foe_entry_clear(struct mtk_ppe
+ static int
+ mtk_foe_entry_commit_l2(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
+ {
++	struct mtk_flow_entry *prev;
++
+ 	entry->type = MTK_FLOW_TYPE_L2;
+ 
+-	return rhashtable_insert_fast(&ppe->l2_flows, &entry->l2_node,
+-				      mtk_flow_l2_ht_params);
++	prev = rhashtable_lookup_get_insert_fast(&ppe->l2_flows, &entry->l2_node,
++						 mtk_flow_l2_ht_params);
++	if (likely(!prev))
++		return 0;
++
++	if (IS_ERR(prev))
++		return PTR_ERR(prev);
++
++	return rhashtable_replace_fast(&ppe->l2_flows, &prev->l2_node,
++				       &entry->l2_node, mtk_flow_l2_ht_params);
+ }
+ 
+ int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
diff --git a/target/linux/mediatek/patches-5.15/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch b/target/linux/mediatek/patches-5.15/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch
index fb3940f544..a455005504 100644
--- a/target/linux/mediatek/patches-5.15/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch
+++ b/target/linux/mediatek/patches-5.15/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch
@@ -22,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
 
 --- a/drivers/net/ethernet/mediatek/mtk_wed.c
 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -806,6 +806,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device
+@@ -813,6 +813,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device
  	struct device_node *np;
  	int index;
  
@@ -47,7 +47,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo at kernel.org>
  	index = of_property_match_string(dev->hw->node, "memory-region-names",
  					 "wo-dlm");
  	if (index < 0)
-@@ -822,6 +840,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device
+@@ -829,6 +847,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device
  		return -ENODEV;
  
  	dev->rro.miod_phys = rmem->base;




More information about the lede-commits mailing list