blob: 5897422c32fb297cd3cbff9ec9a8e8ce3cbd8c7d [file] [log] [blame]
developer064da3c2023-06-13 15:57:26 +08001From cc7283ecc1da9d4f62803062466fb5420d2ea766 Mon Sep 17 00:00:00 2001
2From: "sujuan.chen" <sujuan.chen@mediatek.com>
3Date: Thu, 18 May 2023 15:01:47 +0800
4Subject: [PATCH 2007/2008] wifi: mt76: mt7996: reset addr_elem when delete ba
5
6The old addr element info may be used when the signature is not equel to
70xff, and sta will find error SDP cause the SDP/SDL=0 issue.
8
9Signed-off-by: sujuan.chen <sujuan.chen@mediatek.com>
10---
11 mt76.h | 1 +
12 mt76_connac_mcu.h | 1 +
13 mt7996/init.c | 3 +
14 mt7996/mac.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++
15 mt7996/main.c | 7 +++
16 mt7996/mcu.c | 64 +++++++++++++++++++++
17 mt7996/mcu.h | 34 +++++++++++
18 mt7996/mt7996.h | 32 +++++++++++
19 mt7996/regs.h | 5 ++
20 9 files changed, 287 insertions(+)
21
22diff --git a/mt76.h b/mt76.h
23index e4351338..7ebcf432 100644
24--- a/mt76.h
25+++ b/mt76.h
26@@ -436,6 +436,7 @@ struct mt76_rx_tid {
27 u16 nframes;
28
29 u8 num;
30+ u8 partial_id;
31
32 u8 started:1, stopped:1, timer_pending:1;
33
34diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
35index a53fa138..d74fd2dd 100644
36--- a/mt76_connac_mcu.h
37+++ b/mt76_connac_mcu.h
38@@ -1023,6 +1023,7 @@ enum {
39 MCU_UNI_EVENT_THERMAL = 0x35,
40 MCU_UNI_EVENT_BF = 0x33,
41 MCU_UNI_EVENT_TESTMODE_CTRL = 0x46,
42+ MCU_UNI_EVENT_RRO = 0x57,
43 };
44
45 #define MCU_UNI_CMD_EVENT BIT(1)
46diff --git a/mt7996/init.c b/mt7996/init.c
47index d70dcf9f..93262297 100644
48--- a/mt7996/init.c
49+++ b/mt7996/init.c
50@@ -759,6 +759,9 @@ static int mt7996_rro_init(struct mt7996_dev *dev)
51 mt76_wr(dev, MT_RRO_HOST_INT_ENA,
52 MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
53
54+ INIT_DELAYED_WORK(&dev->rro.rro_del_work, mt7996_rro_delete_sessions);
55+ INIT_LIST_HEAD(&dev->rro.rro_poll_list);
56+
57 /* rro ind cmd queue init */
58 return mt7996_dma_rro_init(dev);
59 }
60diff --git a/mt7996/mac.c b/mt7996/mac.c
61index 4fbbc077..3a89013c 100644
62--- a/mt7996/mac.c
63+++ b/mt7996/mac.c
64@@ -1647,6 +1647,139 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
65 }
66 }
67
68+static struct mt7996_rro_addr *
69+mt7996_rro_get_addr_elem(struct mt7996_dev *dev, u16 seid, u16 sn)
70+{
71+ struct mt7996_rro_cfg *rro = &dev->rro;
72+ u32 idx;
73+ void *addr;
74+
75+ if (seid == rro->particular_se_id) {
76+ addr = rro->particular_session_va;
77+ idx = sn % rro->win_sz;
78+ } else {
79+ addr = rro->addr_elem_alloc_va[seid / MT7996_RRO_SESSION_PER_CR];
80+ idx = (seid % MT7996_RRO_SESSION_PER_CR) * rro->win_sz
81+ + (sn % rro->win_sz);
82+ }
83+ return addr + idx * sizeof(struct mt7996_rro_addr);
84+}
85+
86+static bool mt7996_rro_reset_sessions(struct mt7996_dev *dev,
87+ u16 wcid, u8 partial_id)
88+{
89+ u32 sid = ((wcid & 0x7F) << 3) + partial_id;
90+ u32 value[2];
91+ struct mt7996_rro_ba_session *s;
92+ struct mt7996_rro_addr *elem;
93+ int i;
94+
95+ mt76_wr(dev, MT_RRO_DBG_RD_CTRL, MT_RRO_DBG_RD_EXEC |
96+ sid >> 1 | 0x200);
97+
98+ if (sid & 0x1) {
99+ value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(2));
100+ value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(2));
101+ } else {
102+ value[0] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(0));
103+ value[1] = mt76_rr(dev, MT_RRO_DBG_RDAT_DW(1));
104+ }
105+
106+ s = (struct mt7996_rro_ba_session *)&value[0];
107+ if (!s->cn && s->ack_sn == s->last_in_sn) {
108+ for (i = 0; i < MT7996_RRO_WIN_SIZE_MAX; i++) {
109+ elem = mt7996_rro_get_addr_elem(dev, sid, i);
110+ elem->signature = 0xff;
111+ }
112+ return true;
113+ }
114+
115+ return false;
116+}
117+
118+void mt7996_rro_delete_sessions(struct work_struct *work)
119+{
120+ struct mt7996_dev *dev;
121+ struct mt7996_rro_ba_session_elem *e;
122+ int elem_nums;
123+ LIST_HEAD(rro_poll_list);
124+
125+ dev = (struct mt7996_dev *)container_of(work, struct mt7996_dev,
126+ rro.rro_del_work.work);
127+ elem_nums = dev->rro.elem_nums;
128+
129+ spin_lock_bh(&dev->rro.rro_stbl_lock);
130+ list_splice_init(&dev->rro.rro_poll_list, &rro_poll_list);
131+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
132+
133+ do {
134+ spin_lock_bh(&dev->rro.rro_stbl_lock);
135+ if (list_empty(&rro_poll_list)) {
136+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
137+ break;
138+ }
139+
140+ e = list_first_entry(&rro_poll_list,
141+ struct mt7996_rro_ba_session_elem,
142+ poll_list);
143+ if (!e) {
144+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
145+ break;
146+ }
147+ list_del_init(&e->poll_list);
148+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
149+
150+ if (mt7996_rro_reset_sessions(dev, e->wlan_idx,
151+ e->partial_id)) {
152+ mt7996_mcu_reset_rro_sessions(dev, e->wlan_idx,
153+ e->tid, e->partial_id);
154+ kfree(e);
155+ dev->rro.elem_nums--;
156+ } else {
157+ spin_lock_bh(&dev->rro.rro_stbl_lock);
158+ list_add_tail(&e->poll_list, &dev->rro.rro_poll_list);
159+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
160+ }
161+ elem_nums--;
162+ } while (elem_nums);
163+
164+ if (list_empty(&rro_poll_list))
165+ ieee80211_queue_delayed_work(mt76_hw(dev),
166+ &dev->rro.rro_del_work,
167+ MT7996_WATCHDOG_TIME);
168+}
169+
170+int mt7996_rro_add_delete_elem(struct mt7996_dev *dev,
171+ struct mt7996_sta *msta, u8 tidno)
172+{
173+ struct mt76_rx_tid *tid = NULL;
174+ struct mt76_wcid *wcid = &msta->wcid;
175+ struct mt7996_rro_ba_session_elem *e;
176+ u16 idx = msta->wcid.idx;
177+
178+ tid = rcu_dereference(wcid->aggr[tidno]);
179+ if (!tid)
180+ return 0;
181+
182+ e = kzalloc(sizeof(*e), GFP_ATOMIC);
183+ if (!e)
184+ return -ENOMEM;
185+
186+ e->wlan_idx = idx;
187+ e->tid = tidno;
188+ e->partial_id = tid->partial_id;
189+
190+ spin_lock_bh(&dev->rro.rro_stbl_lock);
191+ list_add_tail(&e->poll_list, &dev->rro.rro_poll_list);
192+ spin_unlock_bh(&dev->rro.rro_stbl_lock);
193+ dev->rro.elem_nums++;
194+
195+ ieee80211_queue_delayed_work(mt76_hw(dev),
196+ &dev->rro.rro_del_work,
197+ MT7996_WATCHDOG_TIME);
198+ return 0;
199+}
200+
201 void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy)
202 {
203 struct mt7996_dev *dev = phy->dev;
204@@ -1971,6 +2104,9 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
205 if (phy3)
206 ieee80211_stop_queues(phy3->mt76->hw);
207
208+ if (dev->rro_support)
209+ cancel_delayed_work_sync(&dev->rro.rro_del_work);
210+
211 cancel_delayed_work_sync(&dev->mphy.mac_work);
212 if (phy2)
213 cancel_delayed_work_sync(&phy2->mt76->mac_work);
214@@ -2062,6 +2198,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
215 set_bit(MT76_RESET, &dev->mphy.state);
216 set_bit(MT76_MCU_RESET, &dev->mphy.state);
217 wake_up(&dev->mt76.mcu.wait);
218+
219+ if (dev->rro_support)
220+ cancel_delayed_work_sync(&dev->rro.rro_del_work);
221+
222 cancel_delayed_work_sync(&dev->mphy.mac_work);
223 if (phy2) {
224 set_bit(MT76_RESET, &phy2->mt76->state);
225diff --git a/mt7996/main.c b/mt7996/main.c
226index cebac4ab..4cb72220 100644
227--- a/mt7996/main.c
228+++ b/mt7996/main.c
229@@ -119,6 +119,9 @@ static void mt7996_stop(struct ieee80211_hw *hw)
230 struct mt7996_dev *dev = mt7996_hw_dev(hw);
231 struct mt7996_phy *phy = mt7996_hw_phy(hw);
232
233+ if (dev->rro_support)
234+ cancel_delayed_work_sync(&dev->rro.rro_del_work);
235+
236 cancel_delayed_work_sync(&phy->mt76->mac_work);
237 cancel_delayed_work_sync(&dev->scs_work);
238
239@@ -797,6 +800,10 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
240 ret = mt7996_mcu_add_rx_ba(dev, params, true);
241 break;
242 case IEEE80211_AMPDU_RX_STOP:
243+ if (dev->rro_support) {
244+ ret = mt7996_rro_add_delete_elem(dev, msta,
245+ params->tid);
246+ }
247 mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
248 ret = mt7996_mcu_add_rx_ba(dev, params, false);
249 break;
250diff --git a/mt7996/mcu.c b/mt7996/mcu.c
251index 0c01e90b..094f3656 100644
252--- a/mt7996/mcu.c
253+++ b/mt7996/mcu.c
254@@ -476,6 +476,41 @@ mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
255 phy->throttle_state = n->duty_percent;
256 }
257
258+static void mt7996_mcu_rx_rro(struct mt7996_dev *dev, struct sk_buff *skb)
259+{
260+ struct mt7996_mcu_rro_event *event;
261+
262+ if (!dev->rro_support)
263+ return;
264+
265+ event = (struct mt7996_mcu_rro_event*)skb->data;
266+
267+ switch (event->tag) {
268+ case UNI_RRO_BA_SESSION_STATUS: {
269+ struct mt7996_mcu_rro_ba *rro = (struct mt7996_mcu_rro_ba *)skb->data;
270+ u16 idx = rro->wlan_id;
271+ struct mt76_rx_tid *tid;
272+ struct mt76_wcid *wcid;
273+
274+ wcid = rcu_dereference(dev->mt76.wcid[idx]);
275+ if (!wcid || !wcid->sta)
276+ return;
277+
278+ tid = rcu_dereference(wcid->aggr[rro->tid]);
279+ if (!tid)
280+ return;
281+ tid->partial_id = rro->partial_id;
282+
283+ break;
284+ }
285+ default:
286+ dev_info(dev->mt76.dev, "%s: unknown rro event tag %d\n",
287+ __func__, event->tag);
288+ break;
289+ }
290+
291+}
292+
293 static void
294 mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
295 {
296@@ -528,6 +563,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
297 mt7996_tm_rf_test_event(dev, skb);
298 break;
299 #endif
300+ case MCU_UNI_EVENT_RRO:
301+ mt7996_mcu_rx_rro(dev, skb);
302+ break;
303 default:
304 break;
305 }
306@@ -4533,6 +4571,32 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
307 sizeof(req), true);
308 }
309
310+int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev,
311+ u16 wcid, u8 tid, u8 pid)
312+{
313+ struct {
314+ /* fixed field */
315+ u8 __rsv[4];
316+
317+ __le16 tag;
318+ __le16 len;
319+ u16 wcid;
320+ u8 tid;
321+ u8 partial_id;
322+ u8 pad[4];
323+ } __packed req = {
324+ .tag = cpu_to_le16(UNI_RRO_DEL_BA_SESSION),
325+ .len = cpu_to_le16(sizeof(req) - 4),
326+ .wcid = wcid,
327+ .tid = tid,
328+ .partial_id = pid,
329+ };
330+
331+ return mt76_mcu_send_msg(&dev->mt76, MCU_WMWA_UNI_CMD(RRO),
332+ &req, sizeof(req), true);
333+}
334+
335+
336 int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 data)
337 {
338 struct mt7996_dev *dev = phy->dev;
339diff --git a/mt7996/mcu.h b/mt7996/mcu.h
340index ec074bc6..10e3799f 100644
341--- a/mt7996/mcu.h
342+++ b/mt7996/mcu.h
343@@ -191,6 +191,38 @@ struct mt7996_mcu_thermal_notify {
344 u8 __rsv2[4];
345 } __packed;
346
347+struct mt7996_mcu_rro_event {
348+ struct mt7996_mcu_rxd rxd;
349+
350+ u8 __rsv1[4];
351+
352+ __le16 tag;
353+ __le16 len;
354+} __packed;
355+
356+struct mt7996_mcu_rro_ba {
357+ struct mt7996_mcu_rro_event event;
358+
359+ u16 wlan_id;
360+ u8 tid;
361+ u8 partial_id;
362+ __le32 status;
363+}__packed;
364+
365+enum {
366+ UNI_RRO_BA_SESSION_STATUS = 0,
367+ UNI_RRO_BA_SESSION_TBL = 1,
368+ UNI_RRO_BA_SESSION_MAX_NUM
369+};
370+
371+struct mt7996_mcu_rro_del_ba {
372+ struct mt7996_mcu_rro_event event;
373+
374+ u8 wlan_idx;
375+ u8 tid;
376+ u8 __rsv2[2];
377+};
378+
379 enum mt7996_chan_mib_offs {
380 UNI_MIB_OBSS_AIRTIME = 26,
381 UNI_MIB_NON_WIFI_TIME = 27,
382@@ -718,6 +750,8 @@ enum {
383 UNI_RRO_GET_BA_SESSION_TABLE,
384 UNI_RRO_SET_BYPASS_MODE,
385 UNI_RRO_SET_TXFREE_PATH,
386+ UNI_RRO_DEL_BA_SESSION,
387+ UNI_RRO_SET_FLUSH_TIMEOUT
388 };
389
390 enum{
391diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
392index b239c44c..88d42c3a 100644
393--- a/mt7996/mt7996.h
394+++ b/mt7996/mt7996.h
395@@ -310,6 +310,28 @@ struct mt7996_rro_addr {
396 u32 signature : 8;
397 };
398
399+struct mt7996_rro_ba_session {
400+ u32 ack_sn :12;
401+ u32 win_sz :3;
402+ u32 bn :1;
403+ u32 last_in_sn :12;
404+ u32 bc :1;
405+ u32 bd :1;
406+ u32 sat :1;
407+ u32 cn :1;
408+ u32 within_cnt :12;
409+ u32 to_sel :3;
410+ u32 rsv :1;
411+ u32 last_in_rxtime :12;
412+};
413+
414+struct mt7996_rro_ba_session_elem {
415+ struct list_head poll_list;
416+ u16 wlan_idx;
417+ u8 tid;
418+ u8 partial_id;
419+};
420+
421 struct mt7996_rro_cfg {
422 u32 ind_signature;
423 void *ba_bitmap_cache_va[MT7996_RRO_BA_BITMAP_CR_CNT];
424@@ -324,6 +346,11 @@ struct mt7996_rro_cfg {
425 spinlock_t lock;
426 struct list_head pg_addr_cache;
427 struct list_head pg_hash_head[MT7996_RRO_MSDU_PG_HASH_SIZE];
428+
429+ struct delayed_work rro_del_work;
430+ spinlock_t rro_stbl_lock;
431+ struct list_head rro_poll_list;
432+ u16 elem_nums;
433 };
434
435 struct mt7996_phy {
436@@ -670,6 +697,8 @@ int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
437 int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
438 int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
439 int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
440+int mt7996_mcu_reset_rro_sessions(struct mt7996_dev *dev,
441+ u16 wcid, u8 tid, u8 pid);
442 int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
443 int mt7996_mcu_red_config(struct mt7996_dev *dev, bool enable);
444 int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
445@@ -768,6 +797,9 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
446 struct mt76_tx_info *tx_info);
447 void mt7996_tx_token_put(struct mt7996_dev *dev);
448 int mt7996_dma_rro_init(struct mt7996_dev *dev);
449+void mt7996_rro_delete_sessions(struct work_struct *work);
450+int mt7996_rro_add_delete_elem(struct mt7996_dev *dev,
451+ struct mt7996_sta *msta, u8 tid);
452 void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
453 struct sk_buff *skb, u32 *info);
454 bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
455diff --git a/mt7996/regs.h b/mt7996/regs.h
456index 6624685e..f97c87c9 100644
457--- a/mt7996/regs.h
458+++ b/mt7996/regs.h
459@@ -72,6 +72,11 @@ enum base_rev {
460 #define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
461 #define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
462
463+#define MT_RRO_DBG_RD_CTRL MT_RRO_TOP(0xe0)
464+#define MT_RRO_DBG_RD_ADDR GENMASK(15, 0)
465+#define MT_RRO_DBG_RD_EXEC BIT(31)
466+
467+#define MT_RRO_DBG_RDAT_DW(_n) MT_RRO_TOP(0xf0 + _n * 0x4)
468
469 #define MT_MCU_INT_EVENT 0x2108
470 #define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
471--
4722.39.2
473