developer | d0c8945 | 2024-10-11 16:53:27 +0800 | [diff] [blame^] | 1 | From 80c870cb7dc5faa9b045a1a44322fc07f5f8aed3 Mon Sep 17 00:00:00 2001 |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame] | 2 | From: Howard Hsu <howard-yh.hsu@mediatek.com> |
| 3 | Date: Tue, 2 Jul 2024 10:06:26 +0800 |
developer | d0c8945 | 2024-10-11 16:53:27 +0800 | [diff] [blame^] | 4 | Subject: [PATCH 177/223] mtk: mt76: mt7996: Add Triggered Uplink Access |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame] | 5 | Optimization support |
| 6 | |
| 7 | Add TUAO feature, which is a subset of SCS procedure support. |
| 8 | |
developer | d0c8945 | 2024-10-11 16:53:27 +0800 | [diff] [blame^] | 9 | Change-Id: I7932b147d399e39e4b91f5dd97edea6f307122d3 |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame] | 10 | Signed-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 | |
| 20 | diff --git a/mt7996/init.c b/mt7996/init.c |
developer | d0c8945 | 2024-10-11 16:53:27 +0800 | [diff] [blame^] | 21 | index b63316b4..ae86c0eb 100644 |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame] | 22 | --- 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 |
developer | d0c8945 | 2024-10-11 16:53:27 +0800 | [diff] [blame^] | 63 | @@ -1593,6 +1600,10 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band, |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame] | 64 | 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 | |
| 74 | diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h |
developer | d0c8945 | 2024-10-11 16:53:27 +0800 | [diff] [blame^] | 75 | index 8b7486a1..8f8cd7ae 100644 |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame] | 76 | --- a/mt7996/mt7996.h |
| 77 | +++ b/mt7996/mt7996.h |
developer | d0c8945 | 2024-10-11 16:53:27 +0800 | [diff] [blame^] | 78 | @@ -525,6 +525,9 @@ struct csi_data { |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame] | 79 | }; |
| 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 { |
| 88 | diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c |
| 89 | index 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 |
| 146 | diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h |
| 147 | index 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 |
| 169 | diff --git a/mt7996/vendor.c b/mt7996/vendor.c |
| 170 | index 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[] = { |
| 273 | diff --git a/mt7996/vendor.h b/mt7996/vendor.h |
| 274 | index 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 | -- |
developer | d0c8945 | 2024-10-11 16:53:27 +0800 | [diff] [blame^] | 309 | 2.45.2 |
developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame] | 310 | |