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