[][MAC80211][wifi7][Misc][Sync Internal patches to External Release Folder]

[Description]
Add 20231011 MT7996 firmware and sync patches to External Release Folder

[Release-log]
N/A

Change-Id: I8971c21f494c3947f2ac7f19b8c398488356ca59
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/8101977
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
new file mode 100644
index 0000000..d9fe625
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/kernel/mt76/patches/2004-wifi-mt76-mt7996-reset-addr_elem-when-delete-ba.patch
@@ -0,0 +1,425 @@
+From d663fd304a7bd5701b2b3ac42b4743dabb252750 Mon Sep 17 00:00:00 2001
+From: "sujuan.chen" <sujuan.chen@mediatek.com>
+Date: Thu, 18 May 2023 15:01:47 +0800
+Subject: [PATCH 68/98] wifi: mt76: mt7996: reset addr_elem when delete ba
+
+The old addr element info may be used when the signature is not equel to
+0xff, and sta will find error SDP cause the SDP/SDL=0 issue.
+
+Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
+---
+ mt76.h            |  1 +
+ mt76_connac_mcu.h |  1 +
+ mt7996/init.c     |  3 ++
+ mt7996/mac.c      | 97 +++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.c      | 77 +++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h      | 46 ++++++++++++++++++++++
+ mt7996/mt7996.h   | 27 +++++++++++++
+ mt7996/regs.h     |  6 +++
+ 8 files changed, 258 insertions(+)
+
+diff --git a/mt76.h b/mt76.h
+index b960f3d..bea58ff 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -434,6 +434,7 @@ struct mt76_rx_tid {
+ 	u16 nframes;
+ 
+ 	u8 num;
++	u16 session_id;
+ 
+ 	u8 started:1, stopped:1, timer_pending:1;
+ 
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index e904ebc..f659d2e 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1038,6 +1038,7 @@ enum {
+ 	MCU_UNI_EVENT_THERMAL = 0x35,
+ 	MCU_UNI_EVENT_NIC_CAPAB = 0x43,
+ 	MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
++	MCU_UNI_EVENT_RRO = 0x57,
+ 	MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
+ 	MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
+ };
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 4503482..1f01f24 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -779,6 +779,9 @@ static int mt7996_wed_rro_init(struct mt7996_dev *dev)
+ 	mt76_wr(dev, MT_RRO_HOST_INT_ENA,
+ 		MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
+ 
++	INIT_WORK(&dev->wed_rro.rro_del_work, mt7996_rro_delete_sessions);
++	INIT_LIST_HEAD(&dev->wed_rro.rro_poll_list);
++
+ 	/* rro ind cmd queue init */
+ 	return mt7996_dma_rro_init(dev);
+ #else
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index b24f237..60ca23b 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1450,6 +1450,96 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 	}
+ }
+ 
++static struct mt7996_wed_rro_addr *
++mt7996_rro_get_addr_elem(struct mt7996_dev *dev, u16 seid, u16 sn)
++{
++	u32 idx;
++	void *addr;
++
++	if (seid == MT7996_RRO_MAX_SESSION) {
++		addr = dev->wed_rro.session.ptr;
++		idx = sn % MT7996_RRO_WINDOW_MAX_LEN;
++	} else {
++		addr = dev->wed_rro.addr_elem[seid / MT7996_RRO_BA_BITMAP_SESSION_SIZE].ptr;
++		idx = (seid % MT7996_RRO_BA_BITMAP_SESSION_SIZE) * MT7996_RRO_WINDOW_MAX_LEN
++			+ (sn % MT7996_RRO_WINDOW_MAX_LEN);
++	}
++	return addr + idx * sizeof(struct mt7996_wed_rro_addr);
++}
++
++static bool mt7996_rro_reset_sessions(struct mt7996_dev *dev, u16 session_id)
++{
++	struct  mt7996_wed_rro_addr *elem;
++	int i;
++
++	for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
++		elem = mt7996_rro_get_addr_elem(dev, session_id, i);
++		elem->signature = 0xff;
++	}
++	return true;
++
++}
++
++void  mt7996_rro_delete_sessions(struct work_struct *work)
++{
++	struct mt7996_dev *dev;
++	struct mt7996_rro_ba_session_elem *e;
++	int elem_nums;
++	LIST_HEAD(rro_poll_list);
++
++	dev = (struct mt7996_dev *)container_of(work, struct mt7996_dev,
++					       wed_rro.rro_del_work);
++	elem_nums = dev->wed_rro.elem_nums;
++
++	spin_lock_bh(&dev->wed_rro.rro_stbl_lock);
++	list_splice_init(&dev->wed_rro.rro_poll_list, &rro_poll_list);
++	spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++
++	do {
++		spin_lock_bh(&dev->wed_rro.rro_stbl_lock);
++		if (list_empty(&rro_poll_list)) {
++			spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++			break;
++		}
++
++		e = list_first_entry(&rro_poll_list,
++				     struct mt7996_rro_ba_session_elem,
++				     poll_list);
++		if (!e) {
++			spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++			break;
++		}
++		list_del_init(&e->poll_list);
++		spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++
++		if (mt7996_rro_reset_sessions(dev, e->session_id)) {
++			mt7996_mcu_reset_rro_sessions(dev, e->session_id);
++			kfree(e);
++			dev->wed_rro.elem_nums--;
++		}
++		elem_nums--;
++	} while (elem_nums);
++}
++
++int mt7996_rro_add_delete_elem(struct mt7996_dev *dev, u16 seid)
++{
++	struct mt7996_rro_ba_session_elem *e;
++
++	e = kzalloc(sizeof(*e), GFP_ATOMIC);
++	if (!e)
++		return -ENOMEM;
++
++	e->session_id = seid;
++
++	spin_lock_bh(&dev->wed_rro.rro_stbl_lock);
++	list_add_tail(&e->poll_list, &dev->wed_rro.rro_poll_list);
++	spin_unlock_bh(&dev->wed_rro.rro_stbl_lock);
++	dev->wed_rro.elem_nums++;
++
++	ieee80211_queue_work(mt76_hw(dev), &dev->wed_rro.rro_del_work);
++	return 0;
++}
++
+ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+@@ -1774,6 +1864,9 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
+ 	if (phy3)
+ 		ieee80211_stop_queues(phy3->mt76->hw);
+ 
++	if (dev->has_rro)
++		cancel_work_sync(&dev->wed_rro.rro_del_work);
++
+ 	cancel_delayed_work_sync(&dev->mphy.mac_work);
+ 	if (phy2)
+ 		cancel_delayed_work_sync(&phy2->mt76->mac_work);
+@@ -1865,6 +1958,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	set_bit(MT76_RESET, &dev->mphy.state);
+ 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
+ 	wake_up(&dev->mt76.mcu.wait);
++
++	if (dev->has_rro)
++		cancel_work_sync(&dev->wed_rro.rro_del_work);
++
+ 	cancel_delayed_work_sync(&dev->mphy.mac_work);
+ 	if (phy2) {
+ 		set_bit(MT76_RESET, &phy2->mt76->state);
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 6589610..ce38a5e 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -538,6 +538,60 @@ mt7996_mcu_update_tx_gi(struct rate_info *rate, struct all_sta_trx_rate *mcu_rat
+ 	return 0;
+ }
+ 
++static void mt7996_mcu_rx_rro(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++	struct mt7996_mcu_rro_event *event;
++	struct mt7996_mcu_rro_ba *rro;
++	struct mt7996_mcu_rro_ba_del_chk_done *delba;
++	u16 len;
++
++	if (!dev->has_rro)
++		return;
++
++	event = (struct mt7996_mcu_rro_event *)skb->data;
++	skb_pull(skb, sizeof(struct mt7996_mcu_rxd) + 4);
++
++	switch (event->tag) {
++	case UNI_RRO_BA_SESSION_STATUS: {
++		len = sizeof(struct mt7996_mcu_rro_ba);
++		while (unlikely(len > skb->len) ? NULL : true) {
++			rro = (struct mt7996_mcu_rro_ba *)skb->data;
++			u16 idx = cpu_to_le16(rro->wlan_id);
++			struct mt76_rx_tid *tid;
++			struct mt76_wcid *wcid;
++
++			wcid = rcu_dereference(dev->mt76.wcid[idx]);
++			if (!wcid || !wcid->sta)
++				return;
++
++			tid = rcu_dereference(wcid->aggr[rro->tid]);
++			if (!tid)
++				return;
++			tid->session_id = cpu_to_le16(rro->session_id);
++			skb_pull(skb, len);
++		}
++		break;
++	}
++	case UNI_RRO_BA_SESSION_DEL_CHK_DONE: {
++		len = sizeof(struct mt7996_mcu_rro_ba_del_chk_done);
++		while (unlikely(len > skb->len) ? NULL : true) {
++			delba = (struct mt7996_mcu_rro_ba_del_chk_done *)skb->data;
++			u16 session_id = cpu_to_le16(delba->session_id);
++
++			mt7996_rro_add_delete_elem(dev, session_id);
++			skb_pull(skb, len);
++		}
++		break;
++	}
++
++	default:
++		dev_info(dev->mt76.dev, "%s: unknown rro event tag %d\n",
++			 __func__, event->tag);
++		break;
++	}
++
++}
++
+ static void
+ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+@@ -663,6 +717,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 		mt7996_tm_rf_test_event(dev, skb);
+ 		break;
+ #endif
++	case MCU_UNI_EVENT_RRO:
++		mt7996_mcu_rx_rro(dev, skb);
++		break;
+ 	default:
+ 		break;
+ 	}
+@@ -4615,6 +4672,26 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
+ 				 sizeof(req), true);
+ }
+ 
++int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev, u16 seid)
++{
++	struct {
++		/* fixed field */
++		u8 __rsv[4];
++
++		__le16 tag;
++		__le16 len;
++		__le16 session_id;
++		u8 pad[4];
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_RRO_DEL_BA_SESSION),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.session_id = cpu_to_le16(seid),
++	};
++
++	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO),
++				 &req, sizeof(req), true);
++}
++
+ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
+ {
+ 	struct mt7996_dev *dev = phy->dev;
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index 666216a..0aa68f7 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -239,6 +239,50 @@ struct mt7996_mcu_all_sta_info_event {
+ 	};
+ } __packed;
+ 
++struct mt7996_mcu_rro_event {
++	struct mt7996_mcu_rxd rxd;
++
++	u8 __rsv1[4];
++
++	__le16 tag;
++	__le16 len;
++} __packed;
++
++struct mt7996_mcu_rro_ba {
++	__le16 tag;
++	__le16 len;
++
++	__le16 wlan_id;
++	u8 tid;
++	u8 __rsv1;
++	__le32 status;
++	__le16 session_id;
++	u8 __rsv2[2];
++} __packed;
++
++struct mt7996_mcu_rro_ba_del_chk_done {
++	__le16 tag;
++	__le16 len;
++
++	__le16 session_id;
++	u8 __rsv2[2];
++} __packed;
++
++enum  {
++	UNI_RRO_BA_SESSION_STATUS = 0,
++	UNI_RRO_BA_SESSION_TBL	= 1,
++	UNI_RRO_BA_SESSION_DEL_CHK_DONE = 2,
++	UNI_RRO_BA_SESSION_MAX_NUM
++};
++
++struct mt7996_mcu_rro_del_ba {
++	struct mt7996_mcu_rro_event event;
++
++	u8  wlan_idx;
++	u8  tid;
++	u8 __rsv2[2];
++};
++
+ enum mt7996_chan_mib_offs {
+ 	UNI_MIB_OBSS_AIRTIME = 26,
+ 	UNI_MIB_NON_WIFI_TIME = 27,
+@@ -840,6 +884,8 @@ enum {
+ 	UNI_RRO_GET_BA_SESSION_TABLE,
+ 	UNI_RRO_SET_BYPASS_MODE,
+ 	UNI_RRO_SET_TXFREE_PATH,
++	UNI_RRO_DEL_BA_SESSION,
++	UNI_RRO_SET_FLUSH_TIMEOUT
+ };
+ 
+ enum{
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index bba1364..af67c59 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -282,6 +282,26 @@ struct mt7996_wed_rro_addr {
+ 	u32 signature : 8;
+ };
+ 
++struct mt7996_rro_ba_session {
++	u32 ack_sn         :12;
++	u32 win_sz         :3;
++	u32 bn             :1;
++	u32 last_in_sn     :12;
++	u32 bc             :1;
++	u32 bd             :1;
++	u32 sat            :1;
++	u32 cn             :1;
++	u32 within_cnt     :12;
++	u32 to_sel         :3;
++	u32 rsv            :1;
++	u32 last_in_rxtime :12;
++};
++
++struct mt7996_rro_ba_session_elem {
++	struct list_head poll_list;
++	u16 session_id;
++};
++
+ struct mt7996_phy {
+ 	struct mt76_phy *mt76;
+ 	struct mt7996_dev *dev;
+@@ -418,6 +438,10 @@ struct mt7996_dev {
+ 			void *ptr;
+ 			dma_addr_t phy_addr;
+ 		} session;
++		struct work_struct rro_del_work;
++		spinlock_t rro_stbl_lock;
++		struct list_head rro_poll_list;
++		u16 elem_nums;
+ 	} wed_rro;
+ 
+ 	bool testmode_enable;
+@@ -653,6 +677,7 @@ int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
+ int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
+ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
+ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
++int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev, u16 seid);
+ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
+ int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable);
+ int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
+@@ -757,6 +782,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 			  struct ieee80211_sta *sta,
+ 			  struct mt76_tx_info *tx_info);
+ void mt7996_tx_token_put(struct mt7996_dev *dev);
++void  mt7996_rro_delete_sessions(struct work_struct *work);
++int mt7996_rro_add_delete_elem(struct mt7996_dev *dev, u16 seid);
+ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+ 			 struct sk_buff *skb, u32 *info);
+ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index d305c25..38467d9 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -101,6 +101,12 @@ enum offs_rev {
+ #define MT_RRO_ACK_SN_CTRL_SN_MASK		GENMASK(27, 16)
+ #define MT_RRO_ACK_SN_CTRL_SESSION_MASK		GENMASK(11, 0)
+ 
++#define MT_RRO_DBG_RD_CTRL			MT_RRO_TOP(0xe0)
++#define MT_RRO_DBG_RD_ADDR			GENMASK(15, 0)
++#define MT_RRO_DBG_RD_EXEC			BIT(31)
++
++#define MT_RRO_DBG_RDAT_DW(_n)			MT_RRO_TOP(0xf0 + _n * 0x4)
++
+ #define MT_MCU_INT_EVENT			0x2108
+ #define MT_MCU_INT_EVENT_DMA_STOPPED		BIT(0)
+ #define MT_MCU_INT_EVENT_DMA_INIT		BIT(1)
+-- 
+2.18.0
+