blob: 53d656d64b2eec4c57eb17768ab1075dda897221 [file] [log] [blame]
developerd0c89452024-10-11 16:53:27 +08001From 80c870cb7dc5faa9b045a1a44322fc07f5f8aed3 Mon Sep 17 00:00:00 2001
developer05f3b2b2024-08-19 19:17:34 +08002From: Howard Hsu <howard-yh.hsu@mediatek.com>
3Date: Tue, 2 Jul 2024 10:06:26 +0800
developerd0c89452024-10-11 16:53:27 +08004Subject: [PATCH 177/223] mtk: mt76: mt7996: Add Triggered Uplink Access
developer05f3b2b2024-08-19 19:17:34 +08005 Optimization support
6
7Add TUAO feature, which is a subset of SCS procedure support.
8
developerd0c89452024-10-11 16:53:27 +08009Change-Id: I7932b147d399e39e4b91f5dd97edea6f307122d3
developer05f3b2b2024-08-19 19:17:34 +080010Signed-off-by: Howard Hsu <howard-yh.hsu@mediatek.com>
11---
12 mt7996/init.c | 25 ++++++++++-----
13 mt7996/mt7996.h | 3 ++
14 mt7996/mtk_mcu.c | 49 ++++++++++++++++++++++++++++++
15 mt7996/mtk_mcu.h | 7 +++++
16 mt7996/vendor.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
17 mt7996/vendor.h | 17 +++++++++++
18 6 files changed, 173 insertions(+), 7 deletions(-)
19
20diff --git a/mt7996/init.c b/mt7996/init.c
developerd0c89452024-10-11 16:53:27 +080021index b63316b4..ae86c0eb 100644
developer05f3b2b2024-08-19 19:17:34 +080022--- a/mt7996/init.c
23+++ b/mt7996/init.c
24@@ -62,7 +62,14 @@ static const struct ieee80211_iface_combination if_comb_7992[] = {
25 }
26 };
27
28-static const u8 mt7996_if_types_ext_capa[] = {
29+static const u8 mt7996_if_types_ext_capa_ap[] = {
30+ [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
31+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
32+ [6] = WLAN_EXT_CAPA7_SCS_SUPPORT,
33+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
34+};
35+
36+static const u8 mt7996_if_types_ext_capa_sta[] = {
37 [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
38 [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
39 [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
40@@ -71,16 +78,16 @@ static const u8 mt7996_if_types_ext_capa[] = {
41 static const struct wiphy_iftype_ext_capab mt7996_iftypes_ext_capa[] = {
42 {
43 .iftype = NL80211_IFTYPE_STATION,
44- .extended_capabilities = mt7996_if_types_ext_capa,
45- .extended_capabilities_mask = mt7996_if_types_ext_capa,
46- .extended_capabilities_len = sizeof(mt7996_if_types_ext_capa),
47+ .extended_capabilities = mt7996_if_types_ext_capa_sta,
48+ .extended_capabilities_mask = mt7996_if_types_ext_capa_sta,
49+ .extended_capabilities_len = sizeof(mt7996_if_types_ext_capa_sta),
50 .mld_capa_and_ops = 2,
51 },
52 {
53 .iftype = NL80211_IFTYPE_AP,
54- .extended_capabilities = mt7996_if_types_ext_capa,
55- .extended_capabilities_mask = mt7996_if_types_ext_capa,
56- .extended_capabilities_len = sizeof(mt7996_if_types_ext_capa),
57+ .extended_capabilities = mt7996_if_types_ext_capa_ap,
58+ .extended_capabilities_mask = mt7996_if_types_ext_capa_ap,
59+ .extended_capabilities_len = sizeof(mt7996_if_types_ext_capa_ap),
60 .eml_capabilities = IEEE80211_EML_CAP_EMLSR_SUPP,
61 .mld_capa_and_ops = 2,
62 /* the max number of simultaneous links is defined as the
developerd0c89452024-10-11 16:53:27 +080063@@ -1593,6 +1600,10 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
developer05f3b2b2024-08-19 19:17:34 +080064 u8_encode_bits(IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454,
65 IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
66
67+ if (iftype == NL80211_IFTYPE_AP)
68+ eht_cap_elem->mac_cap_info[0] |=
69+ IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC;
70+
71 eht_cap_elem->phy_cap_info[0] =
72 IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
73 IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
74diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +080075index 8b7486a1..8f8cd7ae 100644
developer05f3b2b2024-08-19 19:17:34 +080076--- a/mt7996/mt7996.h
77+++ b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +080078@@ -525,6 +525,9 @@ struct csi_data {
developer05f3b2b2024-08-19 19:17:34 +080079 };
80
81 int mt7996_set_coding_type(struct ieee80211_hw *hw, u8 coding_type, u8 link_id);
82+
83+int mt7996_mcu_set_muru_qos_cfg(struct mt7996_dev *dev, u16 wlan_idx, u8 dir,
84+ u8 scs_id, u8 req_type, u8 *qos_ie, u8 qos_ie_len);
85 #endif
86
87 struct mt7996_rro_ba_session {
88diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
89index 8bacf29d..9ec4bc9a 100644
90--- a/mt7996/mtk_mcu.c
91+++ b/mt7996/mtk_mcu.c
92@@ -1429,4 +1429,53 @@ int mt7996_set_coding_type(struct ieee80211_hw *hw, u8 coding_type, u8 link_id)
93
94 return 0;
95 }
96+
97+int mt7996_mcu_set_muru_qos_cfg(struct mt7996_dev *dev, u16 wlan_idx, u8 dir,
98+ u8 scs_id, u8 req_type, u8 *qos_ie, u8 qos_ie_len)
99+{
100+#define QOS_FLAG_UPDATE 20
101+#define QOS_FLAG_DELETE 21
102+
103+ struct {
104+ u8 _rsv[4];
105+
106+ __le16 tag;
107+ __le16 len;
108+
109+ __le32 qos_flag;
110+ __le16 wlan_idx;
111+ u8 __rsv2[12];
112+ u8 dir;
113+ u8 _rsv3[4];
114+ u8 scs_id;
115+ u8 qos_ie[44];
116+ } __packed req = {
117+ .tag = cpu_to_le16(UNI_CMD_MURU_SET_QOS_CFG),
118+ .len = cpu_to_le16(sizeof(req) - 4),
119+ .wlan_idx = cpu_to_le16(wlan_idx),
120+ .scs_id = scs_id,
121+ };
122+
123+ switch (req_type) {
124+ case SCS_REQ_TYPE_ADD:
125+ case SCS_REQ_TYPE_CHANGE:
126+ req.qos_flag = cpu_to_le32(QOS_FLAG_UPDATE);
127+ req.dir = dir;
128+
129+ if (qos_ie_len > sizeof(req.qos_ie))
130+ return -EINVAL;
131+
132+ memcpy(req.qos_ie, qos_ie, qos_ie_len);
133+ break;
134+ case SCS_REQ_TYPE_REMOVE:
135+ req.qos_flag = cpu_to_le32(QOS_FLAG_DELETE);
136+ break;
137+ default:
138+ dev_err(dev->mt76.dev, "Unsupported req_type %u\n", req_type);
139+ return -EINVAL;
140+ }
141+
142+ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &req,
143+ sizeof(req), true);
144+}
145 #endif
146diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
147index 8ba261a7..711903e0 100644
148--- a/mt7996/mtk_mcu.h
149+++ b/mt7996/mtk_mcu.h
150@@ -134,6 +134,7 @@ enum {
151 UNI_CMD_MURU_PROT_FRAME_THR = 0xCC,
152 UNI_CMD_MURU_SET_CERT_MU_EDCA_OVERRIDE,
153 UNI_CMD_MURU_SET_TRIG_VARIANT = 0xD5,
154+ UNI_CMD_MURU_SET_QOS_CFG = 0xFE,
155 };
156
157 struct bf_pfmu_tag {
158@@ -1165,4 +1166,10 @@ enum {
159 VOW_DRR_DBG_PRN)
160 #endif
161
162+enum {
163+ SCS_REQ_TYPE_ADD,
164+ SCS_REQ_TYPE_REMOVE,
165+ SCS_REQ_TYPE_CHANGE,
166+};
167+
168 #endif
169diff --git a/mt7996/vendor.c b/mt7996/vendor.c
170index e75c163e..e13a148a 100644
171--- a/mt7996/vendor.c
172+++ b/mt7996/vendor.c
173@@ -132,6 +132,17 @@ eml_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EML_CTRL] = {
174 [MTK_VENDOR_ATTR_EML_CTRL_STRUCT] = { .type = NLA_BINARY },
175 };
176
177+
178+static const struct nla_policy
179+scs_ctrl_policy[NUM_MTK_VENDOR_ATTRS_SCS_CTRL] = {
180+ [MTK_VENDOR_ATTR_SCS_ID] = { .type = NLA_U8 },
181+ [MTK_VENDOR_ATTR_SCS_REQ_TYPE] = { .type = NLA_U8 },
182+ [MTK_VENDOR_ATTR_SCS_DIR] = { .type = NLA_U8 },
183+ [MTK_VENDOR_ATTR_SCS_QOS_IE] = { .type = NLA_BINARY },
184+ [MTK_VENDOR_ATTR_SCS_MAC_ADDR] = NLA_POLICY_ETH_ADDR,
185+ [MTK_VENDOR_ATTR_SCS_LINK_ID] = { .type = NLA_U8 },
186+};
187+
188 static const struct nla_policy
189 csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = {
190 [MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX] = { .type = NLA_U8 },
191@@ -1164,6 +1175,63 @@ static int mt7996_vendor_eml_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev
192
193 return err;
194 }
195+static int mt7996_vendor_scs_ctrl(struct wiphy *wiphy, struct wireless_dev *wdev,
196+ const void *data, int data_len)
197+{
198+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
199+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
200+ struct ieee80211_sta *sta;
201+ struct mt7996_sta *msta;
202+ struct mt7996_link_sta *mlink;
203+ struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_SCS_CTRL];
204+ u8 sta_addr[ETH_ALEN];
205+ u8 scs_id, req_type, dir, link_id, qos_ie_len;
206+ u8 *qos_ie = NULL;
207+ int err;
208+
209+ err = nla_parse(tb, MTK_VENDOR_ATTR_SCS_CTRL_MAX, data, data_len,
210+ scs_ctrl_policy, NULL);
211+ if (err)
212+ return err;
213+
214+ if (!tb[MTK_VENDOR_ATTR_SCS_ID] || !tb[MTK_VENDOR_ATTR_SCS_REQ_TYPE] ||
215+ !tb[MTK_VENDOR_ATTR_SCS_MAC_ADDR] || !tb[MTK_VENDOR_ATTR_SCS_LINK_ID])
216+ return -EINVAL;
217+
218+ scs_id = nla_get_u8(tb[MTK_VENDOR_ATTR_SCS_ID]);
219+ req_type = nla_get_u8(tb[MTK_VENDOR_ATTR_SCS_REQ_TYPE]);
220+ nla_memcpy(sta_addr, tb[MTK_VENDOR_ATTR_SCS_MAC_ADDR], ETH_ALEN);
221+ link_id = nla_get_u8(tb[MTK_VENDOR_ATTR_SCS_LINK_ID]);
222+
223+ sta = ieee80211_find_sta_by_ifaddr(hw, sta_addr, NULL);
224+ if (!sta)
225+ return -EINVAL;
226+
227+ msta = (struct mt7996_sta *)sta->drv_priv;
228+ mlink = mlink_dereference_protected(msta, link_id);
229+ if (!mlink)
230+ return -EINVAL;
231+
232+ if (req_type == SCS_REQ_TYPE_ADD || req_type == SCS_REQ_TYPE_CHANGE) {
233+ if (!tb[MTK_VENDOR_ATTR_SCS_DIR] || !tb[MTK_VENDOR_ATTR_SCS_QOS_IE])
234+ return -EINVAL;
235+
236+ dir = nla_get_u8(tb[MTK_VENDOR_ATTR_SCS_DIR]);
237+ qos_ie_len = nla_len(tb[MTK_VENDOR_ATTR_SCS_QOS_IE]);
238+ qos_ie = kzalloc(qos_ie_len, GFP_KERNEL);
239+ if (!qos_ie)
240+ return -ENOMEM;
241+
242+ nla_memcpy(qos_ie, tb[MTK_VENDOR_ATTR_SCS_QOS_IE], qos_ie_len);
243+ }
244+
245+ err = mt7996_mcu_set_muru_qos_cfg(dev, mlink->wcid.idx, dir, scs_id,
246+ req_type, qos_ie, qos_ie_len);
247+
248+ kfree(qos_ie);
249+
250+ return err;
251+}
252
253 static int mt7996_vendor_csi_ctrl(struct wiphy *wiphy,
254 struct wireless_dev *wdev,
255@@ -1644,6 +1712,17 @@ static const struct wiphy_vendor_command mt7996_vendor_commands[] = {
256 .policy = txpower_ctrl_policy,
257 .maxattr = MTK_VENDOR_ATTR_TXPOWER_CTRL_MAX,
258 },
259+ {
260+ .info = {
261+ .vendor_id = MTK_NL80211_VENDOR_ID,
262+ .subcmd = MTK_NL80211_VENDOR_SUBCMD_SCS_CTRL,
263+ },
264+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
265+ WIPHY_VENDOR_CMD_NEED_RUNNING,
266+ .doit = mt7996_vendor_scs_ctrl,
267+ .policy = scs_ctrl_policy,
268+ .maxattr = MTK_VENDOR_ATTR_SCS_CTRL_MAX,
269+ },
270 };
271
272 static const struct nl80211_vendor_cmd_info mt7996_vendor_events[] = {
273diff --git a/mt7996/vendor.h b/mt7996/vendor.h
274index 515f77a6..71800590 100644
275--- a/mt7996/vendor.h
276+++ b/mt7996/vendor.h
277@@ -19,6 +19,7 @@ enum mtk_nl80211_vendor_subcmds {
278 MTK_NL80211_VENDOR_SUBCMD_PP_CTRL = 0xcc,
279 MTK_NL80211_VENDOR_SUBCMD_BEACON_CTRL = 0xcd,
280 MTK_NL80211_VENDOR_SUBCMD_TXPOWER_CTRL = 0xce,
281+ MTK_NL80211_VENDOR_SUBCMD_SCS_CTRL = 0xd0,
282 MTK_NL80211_VENDOR_SUBCMD_EML_CTRL = 0xd3,
283 };
284
285@@ -262,6 +263,22 @@ enum mtk_vendor_attr_eml_ctrl {
286 NUM_MTK_VENDOR_ATTRS_EML_CTRL - 1
287 };
288
289+enum mtk_vendor_attr_scs_ctrl {
290+ MTK_VENDOR_ATTR_SCS_CTRL_UNSPEC,
291+
292+ MTK_VENDOR_ATTR_SCS_ID,
293+ MTK_VENDOR_ATTR_SCS_REQ_TYPE,
294+ MTK_VENDOR_ATTR_SCS_DIR,
295+ MTK_VENDOR_ATTR_SCS_QOS_IE,
296+ MTK_VENDOR_ATTR_SCS_MAC_ADDR,
297+ MTK_VENDOR_ATTR_SCS_LINK_ID,
298+
299+ /* keep last */
300+ NUM_MTK_VENDOR_ATTRS_SCS_CTRL,
301+ MTK_VENDOR_ATTR_SCS_CTRL_MAX =
302+ NUM_MTK_VENDOR_ATTRS_SCS_CTRL - 1
303+};
304+
305 enum mtk_vendor_attr_csi_ctrl {
306 MTK_VENDOR_ATTR_CSI_CTRL_UNSPEC,
307
308--
developerd0c89452024-10-11 16:53:27 +08003092.45.2
developer05f3b2b2024-08-19 19:17:34 +0800310