blob: 63f5b88eb60f92e2fea631a4d45c02a4369eadcc [file] [log] [blame]
developerd243af02023-12-21 14:49:33 +08001From 651d207a15f2bc281edf3c92236b88853fc41006 Mon Sep 17 00:00:00 2001
2From: Peter Chiu <chui-hao.chiu@mediatek.com>
3Date: Wed, 8 Nov 2023 10:17:10 +0800
developer8935fc12024-01-11 14:08:37 +08004Subject: [PATCH 05/25] mtk: wifi: mt76: mt7996: fix some twt issues
developerd243af02023-12-21 14:49:33 +08005
61. Reject twt flows with the same parameters to prevent potential issues
7causing by duplicated establishment.
82. mt7996 can support 16 twt stations so modify the table_mask to u16.
93. The minimum twt duration supported by mt7996 is 64 according to hardware
10design. Reply station with TWT_SETUP_CMD_DICTATE if the min_twt_dur smaller
11than 64.
124. Fix possible unaligned pointer.
135. Remove TWT_CONTROL_WAKE_DUR_UNIT flag because mt7996 does not support it.
14
15---
16 mt7996/mac.c | 53 +++++++++++++++++++++++++++++++++++++++++--------
17 mt7996/mt7996.h | 3 ++-
18 2 files changed, 47 insertions(+), 9 deletions(-)
19
20diff --git a/mt7996/mac.c b/mt7996/mac.c
21index ff7e0753..e6583427 100644
22--- a/mt7996/mac.c
23+++ b/mt7996/mac.c
24@@ -2534,6 +2534,34 @@ static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt)
25 return 0;
26 }
27
28+static bool
29+mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
30+ struct ieee80211_twt_params *twt_agrt)
31+{
32+ u16 type = le16_to_cpu(twt_agrt->req_type);
33+ u8 exp;
34+ int i;
35+
36+ exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type);
37+ for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) {
38+ struct mt7996_twt_flow *f;
39+
40+ if (!(msta->twt.flowid_mask & BIT(i)))
41+ continue;
42+
43+ f = &msta->twt.flow[i];
44+ if (f->duration == twt_agrt->min_twt_dur &&
45+ f->mantissa == twt_agrt->mantissa &&
46+ f->exp == exp &&
47+ f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) &&
48+ f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) &&
49+ f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER))
50+ return true;
51+ }
52+
53+ return false;
54+}
55+
56 void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
57 struct ieee80211_sta *sta,
58 struct ieee80211_twt_setup *twt)
59@@ -2545,8 +2573,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
60 enum ieee80211_twt_setup_cmd sta_setup_cmd;
61 struct mt7996_dev *dev = mt7996_hw_dev(hw);
62 struct mt7996_twt_flow *flow;
63- int flowid, table_id;
64- u8 exp;
65+ u8 flowid, table_id, exp;
66
67 if (mt7996_mac_check_twt_req(twt))
68 goto out;
69@@ -2559,9 +2586,19 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
70 if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
71 goto unlock;
72
73+ if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) {
74+ setup_cmd = TWT_SETUP_CMD_DICTATE;
75+ twt_agrt->min_twt_dur = MT7996_MIN_TWT_DUR;
76+ goto unlock;
77+ }
78+
79+ if (mt7996_mac_twt_param_equal(msta, twt_agrt))
80+ goto unlock;
81+
82 flowid = ffs(~msta->twt.flowid_mask) - 1;
83- le16p_replace_bits(&twt_agrt->req_type, flowid,
84- IEEE80211_TWT_REQTYPE_FLOWID);
85+ twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID);
86+ twt_agrt->req_type |= le16_encode_bits(flowid,
87+ IEEE80211_TWT_REQTYPE_FLOWID);
88
89 table_id = ffs(~dev->twt.table_mask) - 1;
90 exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type);
91@@ -2608,10 +2645,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
92 unlock:
93 mutex_unlock(&dev->mt76.mutex);
94 out:
95- le16p_replace_bits(&twt_agrt->req_type, setup_cmd,
96- IEEE80211_TWT_REQTYPE_SETUP_CMD);
97- twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) |
98- (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED);
99+ twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD);
100+ twt_agrt->req_type |=
101+ le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD);
102+ twt->control = twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED;
103 }
104
105 void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
106diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
107index bc73bcb4..8154ad37 100644
108--- a/mt7996/mt7996.h
109+++ b/mt7996/mt7996.h
110@@ -53,6 +53,7 @@
111
112 #define MT7996_MAX_TWT_AGRT 16
113 #define MT7996_MAX_STA_TWT_AGRT 8
114+#define MT7996_MIN_TWT_DUR 64
115 #define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
116
117 /* NOTE: used to map mt76_rates. idx may change if firmware expands table */
118@@ -320,7 +321,7 @@ struct mt7996_dev {
119 struct rchan *relay_fwlog;
120
121 struct {
122- u8 table_mask;
123+ u16 table_mask;
124 u8 n_agrt;
125 } twt;
126
127--
1282.18.0
129