[rdk-b][common][bsp][Refactor and sync kernel/wifi from Openwrt]

[Description]
Refactor and sync kernel/wifi from Openwrt

[Release-log]
N/A

diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ffa8da6..d9856f0 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3895,8 +3895,22 @@
 static void mtk_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause)
 {
 	struct mtk_mac *mac = netdev_priv(dev);
+	struct mtk_eth *eth = mac->hw;
+	u32 val;
+
+	pause->autoneg = 0;
+
+	if (mac->type == MTK_GDM_TYPE) {
+		val = mtk_r32(eth, MTK_MAC_MCR(mac->id));
+
+		pause->rx_pause = !!(val & MAC_MCR_FORCE_RX_FC);
+		pause->tx_pause = !!(val & MAC_MCR_FORCE_TX_FC);
+	} else if (mac->type == MTK_XGDM_TYPE) {
+		val = mtk_r32(eth, MTK_XMAC_MCR(mac->id));
 
-	phylink_ethtool_get_pauseparam(mac->phylink, pause);
+		pause->rx_pause = !!(val & XMAC_MCR_FORCE_RX_FC);
+		pause->tx_pause = !!(val & XMAC_MCR_FORCE_TX_FC);
+	}
 }
 
 static int mtk_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
index 544bb50..805dbd5 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
@@ -17,6 +17,17 @@
 #define BASE1000T_STATUS_EXTEND		(0x11)
 #define EXTEND_CTRL_AND_STATUS		(0x16)
 
+#define PHY_AUX_CTRL_STATUS		(0x1d)
+#define   PHY_AUX_DPX_MASK		GENMASK(5, 5)
+#define   PHY_AUX_SPEED_MASK		GENMASK(4, 2)
+
+enum {
+	PHY_AUX_SPD_10 = 0,
+	PHY_AUX_SPD_100,
+	PHY_AUX_SPD_1000,
+	PHY_AUX_SPD_2500,
+};
+
 static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
 {
 	int ret;
@@ -97,33 +108,53 @@
 static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev)
 {
 	int ret;
-	u16 reg;
 
-	ret = genphy_read_status(phydev);
+	ret = genphy_update_link(phydev);
+	if (ret)
+		return ret;
 
-	reg = phy_read(phydev, BASE1000T_STATUS_EXTEND);
-	if (FIELD_GET(BIT(2), reg)) {
-		phydev->speed = SPEED_2500;
-		goto end;
-	} else if (FIELD_GET(BIT(12), reg)) {
-		phydev->speed = SPEED_1000;
-		goto end;
-	}
+	phydev->speed = SPEED_UNKNOWN;
+	phydev->duplex = DUPLEX_UNKNOWN;
+	phydev->pause = 0;
+	phydev->asym_pause = 0;
 
-	reg = phy_read(phydev, BASE100T_STATUS_EXTEND);
-	if (FIELD_GET(BIT(12), reg)) {
-		phydev->speed = SPEED_100;
-		goto end;
+	if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
+		ret = genphy_c45_read_lpa(phydev);
+		if (ret < 0)
+			return ret;
+
+		/* Read the link partner's 1G advertisement */
+		ret = phy_read(phydev, MII_STAT1000);
+		if (ret < 0)
+			return ret;
+		mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret);
+	} else if (phydev->autoneg == AUTONEG_DISABLE) {
+		linkmode_zero(phydev->lp_advertising);
 	}
 
+	ret = phy_read(phydev, PHY_AUX_CTRL_STATUS);
+	if (ret < 0)
+		return ret;
+
-	reg = phy_read(phydev, EXTEND_CTRL_AND_STATUS);
-	if (FIELD_GET(BIT(6), reg)) {
+	/* Actually this phy supports only FDX */
+	phydev->duplex = (ret & PHY_AUX_DPX_MASK) ? DUPLEX_FULL : DUPLEX_HALF;
+	switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) {
+	case PHY_AUX_SPD_10:
 		phydev->speed = SPEED_10;
-		goto end;
+		break;
+	case PHY_AUX_SPD_100:
+		phydev->speed = SPEED_100;
+		break;
+	case PHY_AUX_SPD_1000:
+		phydev->speed = SPEED_1000;
+		break;
+	case PHY_AUX_SPD_2500:
+		phydev->speed = SPEED_2500;
+		phydev->duplex = DUPLEX_FULL; /* 2.5G must be FDX */
+		break;
 	}
 
-end:
-	return ret;
+	return 0;
 }
 
 static struct phy_driver mtk_gephy_driver[] = {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c
index 74b27d6..04e6b4e 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt7531.c
@@ -1038,6 +1038,7 @@
 	u32 pmcr;
 	u32 speed;
 
+	pdev = container_of(gsw->dev, struct platform_device, dev);
 	switch_node = of_find_node_by_name(NULL, "switch0");
 	if (switch_node == NULL) {
 		dev_err(&pdev->dev, "switch node invaild\n");
@@ -1050,7 +1051,6 @@
 		return -EIO;
 	}
 
-	pdev = container_of(gsw->dev, struct platform_device, dev);
 	gsw->sysctrl_base = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 							"mediatek,sysctrl");
 	if (IS_ERR(gsw->sysctrl_base)) {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_mdio.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
index 03eb5b4..cde681a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
@@ -495,7 +495,7 @@
 	struct device_node *np = gsw->dev->of_node;
 	struct reset_control *rstc;
 	int mcm;
-	int ret = -EINVAL;
+	int ret;
 
 	mcm = of_property_read_bool(np, "mediatek,mcm");
 	if (mcm) {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.c
index cee89db..fa8e595 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mtk/mt753x/mt753x_nl.c
@@ -75,8 +75,10 @@
 		len = snprintf(buf, sizeof(buf),
 			       "id: %d, model: %s, node: %s\n",
 			       gsw->id, gsw->name, gsw->dev->of_node->name);
-		strncat(buff, buf, size - total);
-		total += len;
+		if (len == strlen(buf)) {
+			strncat(buff, buf, size - total);
+			total += len;
+		}
 	}
 
 	mt753x_put_gsw();
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
index 813ccfc..d54ff5b 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9990-mt7622-backport-nf-hw-offload-framework-and-ups.patch
@@ -6120,7 +6120,7 @@
 index 000000000..ae1eb2656
 --- /dev/null
 +++ b/net/netfilter/xt_FLOWOFFLOAD.c
-@@ -0,0 +1,728 @@
+@@ -0,0 +1,776 @@
 +/*
 + * Copyright (C) 2018-2021 Felix Fietkau <nbd@nbd.name>
 + *
@@ -6574,10 +6574,51 @@
 +}
 +
 +static int
-+xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct,
-+		     const struct xt_action_param *par,
-+		     struct nf_flow_route *route, enum ip_conntrack_dir dir,
-+		     struct net_device **devs)
++xt_flowoffload_route_nat(struct sk_buff *skb, const struct nf_conn *ct,
++			 const struct xt_action_param *par,
++			 struct nf_flow_route *route, enum ip_conntrack_dir dir,
++			 struct net_device **devs)
++{
++	struct dst_entry *this_dst = skb_dst(skb);
++	struct dst_entry *other_dst = NULL;
++	struct flowi fl;
++
++	memset(&fl, 0, sizeof(fl));
++	switch (xt_family(par)) {
++	case NFPROTO_IPV4:
++		fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
++		fl.u.ip4.flowi4_oif = xt_in(par)->ifindex;
++		break;
++	case NFPROTO_IPV6:
++		fl.u.ip6.saddr = ct->tuplehash[!dir].tuple.dst.u3.in6;
++		fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
++		fl.u.ip6.flowi6_oif = xt_in(par)->ifindex;
++		break;
++	}
++
++	nf_route(xt_net(par), &other_dst, &fl, false, xt_family(par));
++	if (!other_dst)
++		return -ENOENT;
++
++	nf_default_forward_path(route, this_dst, dir, devs);
++	nf_default_forward_path(route, other_dst, !dir, devs);
++
++	if (route->tuple[dir].xmit_type	== FLOW_OFFLOAD_XMIT_NEIGH &&
++	    route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) {
++		if (nf_dev_forward_path(route, ct, dir, devs))
++			return -1;
++		if (nf_dev_forward_path(route, ct, !dir, devs))
++			return -1;
++	}
++
++	return 0;
++}
++
++static int
++xt_flowoffload_route_bridge(struct sk_buff *skb, const struct nf_conn *ct,
++			    const struct xt_action_param *par,
++			    struct nf_flow_route *route, enum ip_conntrack_dir dir,
++			    struct net_device **devs)
 +{
 +	int ret;
 +
@@ -6666,8 +6707,13 @@
 +
 +	dir = CTINFO2DIR(ctinfo);
 +
-+	if (xt_flowoffload_route(skb, ct, par, &route, dir, devs) < 0)
-+		goto err_flow_route;
++	if (ct->status & IPS_NAT_MASK) {
++		if (xt_flowoffload_route_nat(skb, ct, par, &route, dir, devs) < 0)
++			goto err_flow_route;
++	} else {
++		if (xt_flowoffload_route_bridge(skb, ct, par, &route, dir, devs) < 0)
++			goto err_flow_route;
++	}
 +
 +	flow = flow_offload_alloc(ct);
 +	if (!flow)
@@ -6693,7 +6739,8 @@
 +	xt_flowoffload_check_device(table, devs[0]);
 +	xt_flowoffload_check_device(table, devs[1]);
 +
-+	dst_release(route.tuple[dir].dst);
++	if (!(ct->status & IPS_NAT_MASK))
++		dst_release(route.tuple[dir].dst);
 +	dst_release(route.tuple[!dir].dst);
 +
 +	return XT_CONTINUE;
@@ -6701,7 +6748,8 @@
 +err_flow_add:
 +	flow_offload_free(flow);
 +err_flow_alloc:
-+	dst_release(route.tuple[dir].dst);
++	if (!(ct->status & IPS_NAT_MASK))
++		dst_release(route.tuple[dir].dst);
 +	dst_release(route.tuple[!dir].dst);
 +err_flow_route:
 +	clear_bit(IPS_OFFLOAD_BIT, &ct->status);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/753-net-mt753x-phy-coverity-scan.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/753-net-mt753x-phy-coverity-scan.patch
index bc1bf03..c4d7d4c 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/753-net-mt753x-phy-coverity-scan.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/753-net-mt753x-phy-coverity-scan.patch
@@ -1,22 +1,3 @@
-diff -Naur a/drivers/net/phy/mtk/mt753x/mt7531.c b/drivers/net/phy/mtk/mt753x/mt7531.c
---- a/drivers/net/phy/mtk/mt753x/mt7531.c	2022-11-25 14:11:51.944272549 +0800
-+++ b/drivers/net/phy/mtk/mt753x/mt7531.c	2022-11-25 14:19:49.970820719 +0800
-@@ -1062,6 +1062,7 @@
- 	u32 pmcr;
- 	u32 speed;
- 
-+	pdev = container_of(gsw->dev, struct platform_device, dev);
- 	switch_node = of_find_node_by_name(NULL, "switch0");
- 	if (switch_node == NULL) {
- 		dev_err(&pdev->dev, "switch node invaild\n");
-@@ -1074,7 +1075,6 @@
- 		return -EIO;
- 	}
- 
--	pdev = container_of(gsw->dev, struct platform_device, dev);
- 	gsw->sysctrl_base = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
- 							"mediatek,sysctrl");
- 	if (IS_ERR(gsw->sysctrl_base)) {
 diff -Naur a/drivers/net/phy/mtk/mt753x/mt753x_common.c b/drivers/net/phy/mtk/mt753x/mt753x_common.c
 --- a/drivers/net/phy/mtk/mt753x/mt753x_common.c	2022-11-25 14:12:06.308223474 +0800
 +++ b/drivers/net/phy/mtk/mt753x/mt753x_common.c	2022-11-25 14:21:52.038450276 +0800
@@ -30,34 +11,6 @@
  	}
  
  	if (pmsr & MAC_LNK_STS) {
-diff -Naur a/drivers/net/phy/mtk/mt753x/mt753x_mdio.c b/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
---- a/drivers/net/phy/mtk/mt753x/mt753x_mdio.c	2022-11-25 14:12:29.064162894 +0800
-+++ b/drivers/net/phy/mtk/mt753x/mt753x_mdio.c	2022-11-25 17:04:01.973949052 +0800
-@@ -495,7 +495,7 @@
- 	struct device_node *np = gsw->dev->of_node;
- 	struct reset_control *rstc;
- 	int mcm;
--	int ret = -EINVAL;
-+	int ret;
- 
- 	mcm = of_property_read_bool(np, "mediatek,mcm");
- 	if (mcm) {
-diff -Naur a/drivers/net/phy/mtk/mt753x/mt753x_nl.c b/drivers/net/phy/mtk/mt753x/mt753x_nl.c
---- a/drivers/net/phy/mtk/mt753x/mt753x_nl.c	2022-11-25 14:12:12.292202033 +0800
-+++ b/drivers/net/phy/mtk/mt753x/mt753x_nl.c	2022-11-25 17:01:26.881930912 +0800
-@@ -75,8 +75,10 @@
- 		len = snprintf(buf, sizeof(buf),
- 			       "id: %d, model: %s, node: %s\n",
- 			       gsw->id, gsw->name, gsw->dev->of_node->name);
--		strncat(buff, buf, size - total);
--		total += len;
-+		if (len == strlen(buf)) {
-+			strncat(buff, buf, size - total);
-+			total += len;
-+		}
- 	}
- 
- 	mt753x_put_gsw();
 diff -Naur a/drivers/net/phy/mtk/mt753x/mt753x_phy.c b/drivers/net/phy/mtk/mt753x/mt753x_phy.c
 --- a/drivers/net/phy/mtk/mt753x/mt753x_phy.c	2022-11-25 14:12:34.160149995 +0800
 +++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.c	2022-11-29 14:12:28.261884707 +0800
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/307-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/307-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch
index 857c1c8..0201eea 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/307-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/307-wifi-mac80211-fix-initialization-of-rx-link-and-rx-l.patch
@@ -20,7 +20,7 @@
 
 --- a/net/mac80211/rx.c
 +++ b/net/mac80211/rx.c
-@@ -4067,6 +4067,56 @@ static void ieee80211_invoke_rx_handlers
+@@ -4067,6 +4067,58 @@ static void ieee80211_invoke_rx_handlers
  #undef CALL_RXH
  }
  
@@ -36,11 +36,15 @@
 +static bool ieee80211_rx_data_set_link(struct ieee80211_rx_data *rx,
 +				       u8 link_id)
 +{
++	rx->link_id = link_id;
++	rx->link = rcu_dereference(rx->sdata->link[link_id]);
++
++	if (!rx->sta || !rx->sta->sta.mlo)
++		return rx->link;
++
 +	if (!ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta, link_id))
 +		return false;
 +
-+	rx->link_id = link_id;
-+	rx->link = rcu_dereference(rx->sdata->link[link_id]);
 +	rx->link_sta = rcu_dereference(rx->sta->link[link_id]);
 +
 +	return rx->link && rx->link_sta;
@@ -62,14 +66,12 @@
 +		if (!rx->sdata)
 +			rx->sdata = sta->sdata;
 +		rx->link_sta = &sta->deflink;
-+
-+		if (link_id >= 0 &&
-+		    !ieee80211_rx_data_set_link(rx, link_id))
-+			return false;
 +	}
 +
 +	if (link_id < 0)
 +		rx->link = &rx->sdata->deflink;
++	else if (!ieee80211_rx_data_set_link(rx, link_id))
++		return false;
 +
 +	return true;
 +}
@@ -77,7 +79,7 @@
  /*
   * This function makes calls into the RX path, therefore
   * it has to be invoked under RCU read lock.
-@@ -4075,16 +4125,19 @@ void ieee80211_release_reorder_timeout(s
+@@ -4075,16 +4127,19 @@ void ieee80211_release_reorder_timeout(s
  {
  	struct sk_buff_head frames;
  	struct ieee80211_rx_data rx = {
@@ -102,7 +104,7 @@
  
  	tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
  	if (!tid_agg_rx)
-@@ -4104,10 +4157,6 @@ void ieee80211_release_reorder_timeout(s
+@@ -4104,10 +4159,6 @@ void ieee80211_release_reorder_timeout(s
  		};
  		drv_event_callback(rx.local, rx.sdata, &event);
  	}
@@ -113,7 +115,7 @@
  
  	ieee80211_rx_handlers(&rx, &frames);
  }
-@@ -4123,7 +4172,6 @@ void ieee80211_mark_rx_ba_filtered_frame
+@@ -4123,7 +4174,6 @@ void ieee80211_mark_rx_ba_filtered_frame
  		/* This is OK -- must be QoS data frame */
  		.security_idx = tid,
  		.seqno_idx = tid,
@@ -121,7 +123,7 @@
  	};
  	int i, diff;
  
-@@ -4134,10 +4182,8 @@ void ieee80211_mark_rx_ba_filtered_frame
+@@ -4134,10 +4184,8 @@ void ieee80211_mark_rx_ba_filtered_frame
  
  	sta = container_of(pubsta, struct sta_info, sta);
  
@@ -134,7 +136,7 @@
  
  	rcu_read_lock();
  	tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
-@@ -4524,15 +4570,6 @@ void ieee80211_check_fast_rx_iface(struc
+@@ -4524,15 +4572,6 @@ void ieee80211_check_fast_rx_iface(struc
  	mutex_unlock(&local->sta_mtx);
  }
  
@@ -150,7 +152,7 @@
  static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
  			      struct ieee80211_fast_rx *fast_rx,
  			      int orig_len)
-@@ -4643,7 +4680,6 @@ static bool ieee80211_invoke_fast_rx(str
+@@ -4643,7 +4682,6 @@ static bool ieee80211_invoke_fast_rx(str
  	struct sk_buff *skb = rx->skb;
  	struct ieee80211_hdr *hdr = (void *)skb->data;
  	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
@@ -158,7 +160,7 @@
  	int orig_len = skb->len;
  	int hdrlen = ieee80211_hdrlen(hdr->frame_control);
  	int snap_offs = hdrlen;
-@@ -4655,7 +4691,6 @@ static bool ieee80211_invoke_fast_rx(str
+@@ -4655,7 +4693,6 @@ static bool ieee80211_invoke_fast_rx(str
  		u8 da[ETH_ALEN];
  		u8 sa[ETH_ALEN];
  	} addrs __aligned(2);
@@ -166,7 +168,7 @@
  	struct ieee80211_sta_rx_stats *stats;
  
  	/* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write
-@@ -4758,18 +4793,10 @@ static bool ieee80211_invoke_fast_rx(str
+@@ -4758,18 +4795,10 @@ static bool ieee80211_invoke_fast_rx(str
   drop:
  	dev_kfree_skb(skb);
  
@@ -187,7 +189,7 @@
  
  	stats->dropped++;
  	return true;
-@@ -4787,8 +4814,8 @@ static bool ieee80211_prepare_and_rx_han
+@@ -4787,8 +4816,8 @@ static bool ieee80211_prepare_and_rx_han
  	struct ieee80211_local *local = rx->local;
  	struct ieee80211_sub_if_data *sdata = rx->sdata;
  	struct ieee80211_hdr *hdr = (void *)skb->data;
@@ -198,7 +200,7 @@
  
  	rx->skb = skb;
  
-@@ -4810,35 +4837,6 @@ static bool ieee80211_prepare_and_rx_han
+@@ -4810,35 +4839,6 @@ static bool ieee80211_prepare_and_rx_han
  	if (!ieee80211_accept_frame(rx))
  		return false;
  
@@ -234,7 +236,7 @@
  	if (!consume) {
  		struct skb_shared_hwtstamps *shwt;
  
-@@ -4858,7 +4856,7 @@ static bool ieee80211_prepare_and_rx_han
+@@ -4858,7 +4858,7 @@ static bool ieee80211_prepare_and_rx_han
  		shwt->hwtstamp = skb_hwtstamps(skb)->hwtstamp;
  	}
  
@@ -243,7 +245,7 @@
  		/* translate to MLD addresses */
  		if (ether_addr_equal(link->conf->addr, hdr->addr1))
  			ether_addr_copy(hdr->addr1, rx->sdata->vif.addr);
-@@ -4888,6 +4886,7 @@ static void __ieee80211_rx_handle_8023(s
+@@ -4888,6 +4888,7 @@ static void __ieee80211_rx_handle_8023(s
  	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
  	struct ieee80211_fast_rx *fast_rx;
  	struct ieee80211_rx_data rx;
@@ -251,7 +253,7 @@
  
  	memset(&rx, 0, sizeof(rx));
  	rx.skb = skb;
-@@ -4904,12 +4903,8 @@ static void __ieee80211_rx_handle_8023(s
+@@ -4904,12 +4905,8 @@ static void __ieee80211_rx_handle_8023(s
  	if (!pubsta)
  		goto drop;
  
@@ -266,7 +268,7 @@
  
  	/*
  	 * TODO: Should the frame be dropped if the right link_id is not
-@@ -4918,19 +4913,8 @@ static void __ieee80211_rx_handle_8023(s
+@@ -4918,19 +4915,8 @@ static void __ieee80211_rx_handle_8023(s
  	 * link_id is used only for stats purpose and updating the stats on
  	 * the deflink is fine?
  	 */
@@ -288,7 +290,7 @@
  
  	fast_rx = rcu_dereference(rx.sta->fast_rx);
  	if (!fast_rx)
-@@ -4948,6 +4932,8 @@ static bool ieee80211_rx_for_interface(s
+@@ -4948,6 +4934,8 @@ static bool ieee80211_rx_for_interface(s
  {
  	struct link_sta_info *link_sta;
  	struct ieee80211_hdr *hdr = (void *)skb->data;
@@ -297,7 +299,7 @@
  
  	/*
  	 * Look up link station first, in case there's a
-@@ -4957,24 +4943,19 @@ static bool ieee80211_rx_for_interface(s
+@@ -4957,24 +4945,19 @@ static bool ieee80211_rx_for_interface(s
  	 */
  	link_sta = link_sta_info_get_bss(rx->sdata, hdr->addr2);
  	if (link_sta) {
@@ -330,7 +332,7 @@
  	return ieee80211_prepare_and_rx_handle(rx, skb, consume);
  }
  
-@@ -5033,19 +5014,15 @@ static void __ieee80211_rx_handle_packet
+@@ -5033,19 +5016,15 @@ static void __ieee80211_rx_handle_packet
  
  	if (ieee80211_is_data(fc)) {
  		struct sta_info *sta, *prev_sta;
@@ -355,7 +357,7 @@
  			/*
  			 * In MLO connection, fetch the link_id using addr2
  			 * when the driver does not pass link_id in status.
-@@ -5063,7 +5040,7 @@ static void __ieee80211_rx_handle_packet
+@@ -5063,7 +5042,7 @@ static void __ieee80211_rx_handle_packet
  				if (!link_sta)
  					goto out;
  
@@ -364,7 +366,7 @@
  			}
  
  			if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
-@@ -5079,30 +5056,25 @@ static void __ieee80211_rx_handle_packet
+@@ -5079,30 +5058,27 @@ static void __ieee80211_rx_handle_packet
  				continue;
  			}
  
@@ -372,6 +374,7 @@
 -			     !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
 -								link_id)) ||
 -			    (!status->link_valid && prev_sta->sta.mlo))
++			rx.sdata = prev_sta->sdata;
 +			if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
 +						       link_id))
 +				goto out;
@@ -392,6 +395,7 @@
 -			     !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
 -								link_id)) ||
 -			    (!status->link_valid && prev_sta->sta.mlo))
++			rx.sdata = prev_sta->sdata;
 +			if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
 +						       link_id))
  				goto out;
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/99902-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/99902-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi.patch
new file mode 100644
index 0000000..9be85c9
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/99902-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi.patch
@@ -0,0 +1,89 @@
+From 1ca2a807a8067e585e628e6eb4721e7fee00acd6 Mon Sep 17 00:00:00 2001
+From: Sujuan Chen <sujuan.chen@mediatek.com>
+Date: Fri, 23 Dec 2022 18:12:41 +0800
+Subject: [PATCH] mac80211: mtk: register .ndo_setup_tc to support wifi2wifi
+ offload
+
+Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
+---
+ include/net/mac80211.h |  5 +++++
+ net/mac80211/iface.c   | 26 ++++++++++++++++++++++++++
+ 2 files changed, 31 insertions(+)
+
+diff --git a/include/net/mac80211.h b/include/net/mac80211.h
+index dd9e834..d98312e 100644
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -4188,6 +4188,8 @@ struct ieee80211_prep_tx_info {
+  *	In fact, cannot change from having valid_links and not having them.
+  * @net_fill_receive_path: Called from .ndo_fill_receive_path in order to
+  *	get a path for hardware flow offloading
++  * @net_setup_tc: Called from .ndo_setup_tc in order to register flowblock
++ *	callback function
+  */
+ struct ieee80211_ops {
+ 	void (*tx)(struct ieee80211_hw *hw,
+@@ -4546,6 +4548,9 @@ struct ieee80211_ops {
+ 	int (*net_fill_receive_path)(struct ieee80211_hw *hw,
+ 				     struct net_device_path_ctx *ctx,
+ 				     struct net_device_path *path);
++	int (*net_setup_tc)(struct ieee80211_hw *hw,
++			    struct net_device *dev,
++			    int type, void *type_data);
+ };
+ 
+ /**
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 6e76b23..b80fb66 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -942,6 +942,30 @@ static int ieee80211_netdev_fill_receive_path(struct net_device_path_ctx *ctx,
+ 	return ret;
+ }
+ 
++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;
++	int ret = -ENOENT;
++
++	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	local = sdata->local;
++
++	if (!local->ops->net_setup_tc)
++		return -EOPNOTSUPP;
++
++	if (!type_data)
++		return -EINVAL;
++
++	rcu_read_lock();
++
++	ret = local->ops->net_setup_tc(&local->hw, dev, (int)type, type_data);
++
++	rcu_read_unlock();
++
++	return ret;
++}
+ 
+ static const struct net_device_ops ieee80211_dataif_8023_ops = {
+ 	.ndo_open		= ieee80211_open,
+@@ -953,6 +977,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
+ 	.ndo_get_stats64	= ieee80211_get_stats64,
+ 	.ndo_fill_forward_path	= ieee80211_netdev_fill_forward_path,
+ 	.ndo_fill_receive_path = ieee80211_netdev_fill_receive_path,
++	.ndo_setup_tc		= ieee80211_netdev_setup_tc,
+ };
+ 
+ static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
+@@ -1482,6 +1507,7 @@ static void ieee80211_if_setup(struct net_device *dev)
+ 	ether_setup(dev);
+ 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ 	dev->priv_flags |= IFF_NO_QUEUE;
++	dev->features |= NETIF_F_HW_TC;
+ 	dev->netdev_ops = &ieee80211_dataif_ops;
+ 	dev->needs_free_netdev = true;
+ 	dev->priv_destructor = ieee80211_if_free;
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
index 230697b..d3dc6b5 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
@@ -31,5 +31,6 @@
     file://909-mac80211-mtk-check-the-control-channel-before-downgr.patch \
     file://910-mac80211-mtk-fix-tx-amsdu-aggregation.patch \
     file://99900-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-i.patch \
+    file://99902-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi.patch \
     file://99999-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch \
     "
diff --git a/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-enable-red-per-band-token-drop-for-H.patch b/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-enable-red-per-band-token-drop-for-H.patch
index 5eed16f..de7a3a1 100644
--- a/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-enable-red-per-band-token-drop-for-H.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-enable-red-per-band-token-drop-for-H.patch
@@ -1,8 +1,7 @@
-From f7a5428387ab23b9c9de3a67ad1ffc5921f89b72 Mon Sep 17 00:00:00 2001
+From 2f0b6e966f10cfcdb3a325238e10966c25c1ea3b Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Fri, 2 Sep 2022 14:40:40 +0800
-Subject: [PATCH 3006/3013] mt76: mt7915: wed: enable red per-band token drop
- for HW Path
+Subject: [PATCH] mt76: mt7915: wed: enable red per-band token drop for HW Path
 
 Limit the number of token used by each band. If a band uses too many token,
 it may hurt the throughput of the other band. The SW path can solve this
@@ -10,49 +9,55 @@
 
 Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
 ---
- mt7915/mcu.c    | 56 ++++++++++++++++++++++++++++++++++++++++---------
- mt7915/mcu.h    |  1 +
- mt7915/mmio.c   |  2 +-
- mt7915/mt7915.h |  4 +++-
- 4 files changed, 51 insertions(+), 12 deletions(-)
+ mt76_connac_mcu.h |  2 +-
+ mt7915/mcu.c      | 45 ++++++++++++++++++++++++++++++++++++++-------
+ mt7915/mcu.h      |  1 +
+ mt7915/mmio.c     |  2 +-
+ mt7915/mt7915.h   |  4 +++-
+ 5 files changed, 44 insertions(+), 10 deletions(-)
 
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 98b00747..21ea55d1 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1174,13 +1174,13 @@ enum {
+ 	MCU_EXT_CMD_RXDCOC_CAL = 0x59,
+ 	MCU_EXT_CMD_GET_MIB_INFO = 0x5a,
+ #ifdef MTK_DEBUG
+-	MCU_EXT_CMD_RED_ENABLE = 0x68,
+ 	MCU_EXT_CMD_RED_SHOW_STA = 0x69,
+ 	MCU_EXT_CMD_RED_TARGET_DELAY = 0x6A,
+ 	MCU_EXT_CMD_RED_TX_RPT = 0x6B,
+ #endif
+ 	MCU_EXT_CMD_TXDPD_CAL = 0x60,
+ 	MCU_EXT_CMD_CAL_CACHE = 0x67,
++	MCU_EXT_CMD_RED_ENABLE = 0x68,
+ 	MCU_EXT_CMD_SET_RADAR_TH = 0x7c,
+ 	MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d,
+ 	MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index f494d9f..5b2ae77 100644
+index f494d9f6..116a5cc9 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -2374,8 +2374,17 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
- 						dev->mt76.mmio.wed.rev_id, 0);
- 		if (ret)
+@@ -2376,6 +2376,7 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
  			return ret;
-+
-+		ret = mt7915_mcu_set_red(dev, true);
-+		if (ret)
-+			return ret;
-+	} else {
-+		mt7915_mcu_set_red(dev, false);
-+		if (ret)
-+			return ret;
  	}
  
 +
  	ret = mt7915_mcu_set_mwds(dev, 1);
  	if (ret)
  		return ret;
-@@ -2385,12 +2394,7 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
+@@ -2389,8 +2390,7 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
  	if (ret)
  		return ret;
  
--	ret = mt7915_mcu_init_rx_airtime(dev);
--	if (ret)
--		return ret;
--
 -	return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
 -				 MCU_WA_PARAM_RED, 0, 0);
-+	return mt7915_mcu_init_rx_airtime(dev);
++	return mt7915_mcu_set_red(dev, mtk_wed_device_active(&dev->mt76.mmio.wed));
  }
  
  int mt7915_mcu_init(struct mt7915_dev *dev)
-@@ -4533,6 +4537,34 @@ int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a
+@@ -4533,27 +4533,58 @@ int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a
  
  	return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), wait_resp);
  }
@@ -72,7 +77,7 @@
 +		__le16 high_mark;
 +		__le16 low_mark;
 +		u8 __rsv2[12];
-+	} req = {
++	} __packed req = {
 +		.args[0] = cpu_to_le32(MCU_WA_PARAM_RED_SETTING),
 +		.cmd = RED_GLOBAL_TOKEN_WATERMARK,
 +		.len = cpu_to_le16(sizeof(req) - 12),
@@ -87,7 +92,10 @@
  
  int mt7915_mcu_set_red(struct mt7915_dev *dev, bool enabled)
  {
-@@ -4543,17 +4575,21 @@ int mt7915_mcu_set_red(struct mt7915_dev *dev, bool enabled)
+ #define RED_DISABLE		0
+-#define RED_BY_HOST_ENABLE	1
+ #define RED_BY_WA_ENABLE	2
+ 	int ret;
  	u32 red_type = enabled > 0 ? RED_BY_WA_ENABLE : RED_DISABLE;
  	__le32 req = cpu_to_le32(red_type);
  
@@ -114,7 +122,7 @@
  int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
  {
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index f2f88cc..572cc16 100644
+index f2f88cc4..572cc16a 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -285,6 +285,7 @@ enum {
@@ -126,7 +134,7 @@
  	MCU_WA_PARAM_RED_SHOW_STA = 0xf,
  	MCU_WA_PARAM_RED_TARGET_DELAY = 0x10,
 diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index e0761e8..b29fe7a 100644
+index e0761e89..b29fe7a4 100644
 --- a/mt7915/mmio.c
 +++ b/mt7915/mmio.c
 @@ -759,7 +759,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
@@ -139,7 +147,7 @@
  	wed->wlan.tx_tbit[1] = is_mt7915(&dev->mt76) ? 5 : 31;
  	wed->wlan.txfree_tbit = is_mt7986(&dev->mt76) ? 2 : 1;
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 89c13db..2335f78 100644
+index 89c13dbe..2335f78f 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
 @@ -56,6 +56,7 @@
@@ -167,5 +175,5 @@
  int mt7915_mcu_set_txpower_level(struct mt7915_phy *phy, u8 drop_level);
  void mt7915_packet_log_to_host(struct mt7915_dev *dev, const void *data, int len, int type, int des_len);
 -- 
-2.36.1
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch b/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch
new file mode 100644
index 0000000..092258d
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch
@@ -0,0 +1,27 @@
+From be3ce3c8e5cf171cca1a6e7c3f5ec0536fae0f81 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Fri, 30 Dec 2022 11:11:59 +0800
+Subject: [PATCH 4003/4004] mt76: revert kernel api for kernel 5.4
+
+---
+ debugfs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/debugfs.c b/debugfs.c
+index 79064a4d..4a8e1864 100644
+--- a/debugfs.c
++++ b/debugfs.c
+@@ -33,8 +33,10 @@ mt76_napi_threaded_set(void *data, u64 val)
+ 	if (!mt76_is_mmio(dev))
+ 		return -EOPNOTSUPP;
+ 
++#if 0 /* disable in backport 5.15 */
+ 	if (dev->napi_dev.threaded != val)
+ 		return dev_set_threaded(&dev->napi_dev, val);
++#endif
+ 
+ 	return 0;
+ }
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-for-backports-5.15-wireless-stack.patch b/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch
similarity index 97%
rename from recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-for-backports-5.15-wireless-stack.patch
rename to recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch
index 4d23f61..d9573b8 100644
--- a/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-for-backports-5.15-wireless-stack.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch
@@ -1,11 +1,9 @@
-From 13c942651ef9278a618507d1e4de8751e62f6105 Mon Sep 17 00:00:00 2001
+From 24e0b09a440cc5f581f01f495a76d6180bc44faf Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Mon, 12 Dec 2022 18:17:12 +0800
-Subject: [PATCH 4003/4003] mt76: revert for backports-5.15 wireless stack
+Date: Fri, 30 Dec 2022 11:12:07 +0800
+Subject: [PATCH 4004/4004] mt76: revert for backports-5.15 wireless stack
 
-Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
 ---
- debugfs.c         |   2 +
  dma.c             |   2 +-
  mac80211.c        |   4 +-
  mt7615/dma.c      |   4 +-
@@ -21,25 +19,10 @@
  mt7915/mcu.c      | 166 +++++++++++++++++++++++-----------------------
  mt7915/testmode.c |   8 +--
  tx.c              |  11 +--
- 16 files changed, 170 insertions(+), 178 deletions(-)
+ 15 files changed, 168 insertions(+), 178 deletions(-)
 
-diff --git a/debugfs.c b/debugfs.c
-index 79064a4..4a8e186 100644
---- a/debugfs.c
-+++ b/debugfs.c
-@@ -33,8 +33,10 @@ mt76_napi_threaded_set(void *data, u64 val)
- 	if (!mt76_is_mmio(dev))
- 		return -EOPNOTSUPP;
- 
-+#if 0 /* disable in backport 5.15 */
- 	if (dev->napi_dev.threaded != val)
- 		return dev_set_threaded(&dev->napi_dev, val);
-+#endif
- 
- 	return 0;
- }
 diff --git a/dma.c b/dma.c
-index 0925daf..08169ba 100644
+index 0925daf4..08169bae 100644
 --- a/dma.c
 +++ b/dma.c
 @@ -945,7 +945,7 @@ mt76_dma_init(struct mt76_dev *dev,
@@ -52,7 +35,7 @@
  		napi_enable(&dev->napi[i]);
  	}
 diff --git a/mac80211.c b/mac80211.c
-index 818f4f0..909ab25 100644
+index 818f4f0c..909ab259 100644
 --- a/mac80211.c
 +++ b/mac80211.c
 @@ -1508,7 +1508,7 @@ EXPORT_SYMBOL_GPL(mt76_get_sar_power);
@@ -74,7 +57,7 @@
  
  	dev->csa_complete |= ieee80211_beacon_cntdwn_is_complete(vif);
 diff --git a/mt7615/dma.c b/mt7615/dma.c
-index f191443..ec729db 100644
+index f1914431..ec729dbe 100644
 --- a/mt7615/dma.c
 +++ b/mt7615/dma.c
 @@ -281,8 +281,8 @@ int mt7615_dma_init(struct mt7615_dev *dev)
@@ -89,7 +72,7 @@
  
  	mt76_poll(dev, MT_WPDMA_GLO_CFG,
 diff --git a/mt7615/main.c b/mt7615/main.c
-index ab4c1b4..8fb5b25 100644
+index ab4c1b44..8fb5b256 100644
 --- a/mt7615/main.c
 +++ b/mt7615/main.c
 @@ -474,7 +474,7 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
@@ -120,7 +103,7 @@
  	mt7615_mutex_release(dev);
  }
 diff --git a/mt7615/mcu.c b/mt7615/mcu.c
-index e917d02..b2e1f38 100644
+index e917d025..b2e1f388 100644
 --- a/mt7615/mcu.c
 +++ b/mt7615/mcu.c
 @@ -353,7 +353,7 @@ out:
@@ -160,7 +143,7 @@
  		.bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int),
  	};
 diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index d406013..703ca73 100644
+index d4060136..703ca736 100644
 --- a/mt76_connac_mcu.c
 +++ b/mt76_connac_mcu.c
 @@ -197,7 +197,7 @@ int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif)
@@ -501,7 +484,7 @@
  	return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(OFFLOAD), true);
  }
 diff --git a/mt76x02_mac.c b/mt76x02_mac.c
-index d3f7447..87ea3db 100644
+index d3f74473..87ea3db1 100644
 --- a/mt76x02_mac.c
 +++ b/mt76x02_mac.c
 @@ -404,7 +404,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
@@ -526,7 +509,7 @@
  		if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
  			ba_size = 0;
 diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
-index b178036..cecc3ef 100644
+index b178036c..cecc3ef5 100644
 --- a/mt7915/debugfs.c
 +++ b/mt7915/debugfs.c
 @@ -1905,8 +1905,8 @@ static ssize_t mt7915_sta_fixed_rate_set(struct file *file,
@@ -541,7 +524,7 @@
  	field = RATE_PARAM_FIXED;
  
 diff --git a/mt7915/dma.c b/mt7915/dma.c
-index 9cbd362..5743dc5 100644
+index 9cbd3625..5743dc54 100644
 --- a/mt7915/dma.c
 +++ b/mt7915/dma.c
 @@ -553,8 +553,8 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
@@ -556,7 +539,7 @@
  
  	mt7915_dma_enable(dev);
 diff --git a/mt7915/init.c b/mt7915/init.c
-index ef752e1..9ccbc7b 100755
+index ef752e10..9ccbc7bc 100755
 --- a/mt7915/init.c
 +++ b/mt7915/init.c
 @@ -1152,8 +1152,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
@@ -570,7 +553,7 @@
  
  		if (band == NL80211_BAND_6GHZ) {
 diff --git a/mt7915/mac.c b/mt7915/mac.c
-index 0d0ae7a..d759912 100644
+index 0d0ae7ab..d759912c 100644
 --- a/mt7915/mac.c
 +++ b/mt7915/mac.c
 @@ -915,7 +915,7 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
@@ -583,7 +566,7 @@
  
  	tid = le32_get_bits(txwi[1], MT_TXD1_TID);
 diff --git a/mt7915/main.c b/mt7915/main.c
-index c87f04b..28509d9 100644
+index c281b472..ad5cd002 100644
 --- a/mt7915/main.c
 +++ b/mt7915/main.c
 @@ -523,7 +523,7 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
@@ -627,7 +610,7 @@
  
  	mutex_lock(&dev->mt76.mutex);
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 88ce44f..f2c848d 100644
+index 50cbda88..8fab4c76 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -64,7 +64,7 @@ mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,
@@ -1125,7 +1108,7 @@
  	if (!skb)
  		return -EINVAL;
  
-@@ -3308,17 +3308,17 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
+@@ -3304,17 +3304,17 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
  	if (txpower) {
  		u32 offs, len, i;
  
@@ -1147,7 +1130,7 @@
  					len = sku_len[SKU_HE_RU242] * 4;
  				}
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 70382b9..5c71116 100644
+index e4af5e1c..19dfb354 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -397,12 +397,12 @@ mt7915_tm_entry_add(struct mt7915_phy *phy, u8 aid)
@@ -1168,7 +1151,7 @@
  	sta->wme = 1;
  
 diff --git a/tx.c b/tx.c
-index a72b777..04b6f2e 100644
+index a72b7779..04b6f2e7 100644
 --- a/tx.c
 +++ b/tx.c
 @@ -60,20 +60,15 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
@@ -1196,5 +1179,5 @@
  
  		hw = mt76_tx_status_get_hw(dev, skb);
 -- 
-2.36.1
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches/patches.inc b/recipes-wifi/linux-mt76/files/patches/patches.inc
index 94d6747..6244bb0 100644
--- a/recipes-wifi/linux-mt76/files/patches/patches.inc
+++ b/recipes-wifi/linux-mt76/files/patches/patches.inc
@@ -52,5 +52,6 @@
     file://3014-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch \
     file://4001-mt76-revert-get_of_mac_addr.patch \
     file://4002-mt76-include-header-files-for-module-param.patch \
-    file://4003-mt76-revert-for-backports-5.15-wireless-stack.patch \
+    file://4003-mt76-revert-kernel-api-for-kernel-5.4.patch \
+    file://4004-mt76-revert-for-backports-5.15-wireless-stack.patch \
     "