developer | 3797e1e | 2022-05-23 17:13:14 +0800 | [diff] [blame] | 1 | From 3b12e37a1c903b7f30c1515b6eec481c206abb4e Mon Sep 17 00:00:00 2001 |
| 2 | From: MeiChia Chiu <MeiChia.Chiu@mediatek.com> |
| 3 | Date: Mon, 25 Apr 2022 15:31:02 +0800 |
| 4 | Subject: [PATCH] mt76: mt7915: add support for 6G in-band discovery |
| 5 | |
| 6 | Add offloading FILS discovery and unsolicited broadcast probe response support. |
| 7 | |
| 8 | Reviewed-by: Ryder Lee <ryder.lee@mediatek.com> |
| 9 | Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com> |
| 10 | --- |
| 11 | mt7915/init.c | 2 + |
| 12 | mt7915/mac.c | 17 +++-- |
| 13 | mt7915/main.c | 8 +- |
| 14 | mt7915/mcu.c | 75 ++++++++++++++++++- |
| 15 | mt7915/mcu.h | 15 +++- |
| 16 | mt7915/mt7915.h | 4 +- |
| 17 | 6 files changed, 107 insertions(+), 14 deletions(-) |
| 18 | |
| 19 | diff --git a/mt7915/init.c b/mt7915/init.c |
| 20 | index 70baad756dd0..d123ecb9fb0c 100644 |
| 21 | --- a/mt7915/init.c |
| 22 | +++ b/mt7915/init.c |
| 23 | @@ -351,6 +351,8 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) |
| 24 | wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT); |
| 25 | wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); |
| 26 | wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); |
| 27 | + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); |
| 28 | + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY); |
| 29 | |
| 30 | if (!mdev->dev->of_node || |
| 31 | !of_property_read_bool(mdev->dev->of_node, |
| 32 | diff --git a/mt7915/mac.c b/mt7915/mac.c |
| 33 | index e353e8c44d6c..de7bf137c234 100644 |
| 34 | --- a/mt7915/mac.c |
| 35 | +++ b/mt7915/mac.c |
| 36 | @@ -1177,7 +1177,7 @@ mt7915_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif, |
| 37 | |
| 38 | void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, |
| 39 | struct sk_buff *skb, struct mt76_wcid *wcid, int pid, |
| 40 | - struct ieee80211_key_conf *key, bool beacon) |
| 41 | + struct ieee80211_key_conf *key, u32 changed) |
| 42 | { |
| 43 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 44 | struct ieee80211_vif *vif = info->control.vif; |
| 45 | @@ -1188,6 +1188,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, |
| 46 | bool mcast = false; |
| 47 | u16 tx_count = 15; |
| 48 | u32 val; |
| 49 | + bool beacon = !!(changed & (BSS_CHANGED_BEACON | |
| 50 | + BSS_CHANGED_BEACON_ENABLED)); |
| 51 | + bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | |
| 52 | + BSS_CHANGED_FILS_DISCOVERY)); |
| 53 | |
| 54 | if (vif) { |
| 55 | struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; |
| 56 | @@ -1200,7 +1204,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, |
| 57 | if (ext_phy && dev->mt76.phy2) |
| 58 | mphy = dev->mt76.phy2; |
| 59 | |
| 60 | - if (beacon) { |
| 61 | + if (inband_disc) { |
| 62 | + p_fmt = MT_TX_TYPE_FW; |
| 63 | + q_idx = MT_LMAC_ALTX0; |
| 64 | + } else if (beacon) { |
| 65 | p_fmt = MT_TX_TYPE_FW; |
| 66 | q_idx = MT_LMAC_BCN0; |
| 67 | } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) { |
| 68 | @@ -1308,8 +1315,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, |
| 69 | return id; |
| 70 | |
| 71 | pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); |
| 72 | - mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, |
| 73 | - false); |
| 74 | + mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, 0); |
| 75 | |
| 76 | txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE); |
| 77 | for (i = 0; i < nbuf; i++) { |
| 78 | @@ -1919,7 +1925,8 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) |
| 79 | case NL80211_IFTYPE_MESH_POINT: |
| 80 | case NL80211_IFTYPE_ADHOC: |
| 81 | case NL80211_IFTYPE_AP: |
| 82 | - mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); |
| 83 | + mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon, |
| 84 | + BSS_CHANGED_BEACON_ENABLED); |
| 85 | break; |
| 86 | default: |
| 87 | break; |
| 88 | diff --git a/mt7915/main.c b/mt7915/main.c |
| 89 | index 5177b19f9154..c2c615931782 100644 |
| 90 | --- a/mt7915/main.c |
| 91 | +++ b/mt7915/main.c |
| 92 | @@ -622,8 +622,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, |
| 93 | mt7915_update_bss_color(hw, vif, &info->he_bss_color); |
| 94 | |
| 95 | if (changed & (BSS_CHANGED_BEACON | |
| 96 | - BSS_CHANGED_BEACON_ENABLED)) |
| 97 | - mt7915_mcu_add_beacon(hw, vif, info->enable_beacon); |
| 98 | + BSS_CHANGED_BEACON_ENABLED | |
| 99 | + BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | |
| 100 | + BSS_CHANGED_FILS_DISCOVERY)) |
| 101 | + mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed); |
| 102 | |
| 103 | mutex_unlock(&dev->mt76.mutex); |
| 104 | } |
| 105 | @@ -636,7 +638,7 @@ mt7915_channel_switch_beacon(struct ieee80211_hw *hw, |
| 106 | struct mt7915_dev *dev = mt7915_hw_dev(hw); |
| 107 | |
| 108 | mutex_lock(&dev->mt76.mutex); |
| 109 | - mt7915_mcu_add_beacon(hw, vif, true); |
| 110 | + mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON); |
| 111 | mutex_unlock(&dev->mt76.mutex); |
| 112 | } |
| 113 | |
| 114 | diff --git a/mt7915/mcu.c b/mt7915/mcu.c |
| 115 | index 2a07a5d2a439..87e44c69d72b 100644 |
| 116 | --- a/mt7915/mcu.c |
| 117 | +++ b/mt7915/mcu.c |
| 118 | @@ -1892,6 +1892,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, |
| 119 | u8 *buf; |
| 120 | int len = sizeof(*cont) + MT_TXD_SIZE + skb->len; |
| 121 | |
| 122 | + len = (len & 0x3) ? ((len | 0x3) + 1) : len; |
| 123 | tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT, |
| 124 | len, &bcn->sub_ntlv, &bcn->len); |
| 125 | |
| 126 | @@ -1910,7 +1911,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif, |
| 127 | |
| 128 | buf = (u8 *)tlv + sizeof(*cont); |
| 129 | mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL, |
| 130 | - true); |
| 131 | + BSS_CHANGED_BEACON); |
| 132 | memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); |
| 133 | } |
| 134 | |
| 135 | @@ -1992,8 +1993,71 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif, |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | -int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, |
| 140 | - struct ieee80211_vif *vif, int en) |
| 141 | +static void |
| 142 | +mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, |
| 143 | + struct sk_buff *rskb, struct bss_info_bcn *bcn, |
| 144 | + u32 changed) |
| 145 | +{ |
| 146 | +#define OFFLOAD_TX_MODE_SU BIT(0) |
| 147 | +#define OFFLOAD_TX_MODE_MU BIT(1) |
| 148 | + struct ieee80211_hw *hw = mt76_hw(dev); |
| 149 | + struct mt7915_phy *phy = mt7915_hw_phy(hw); |
| 150 | + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; |
| 151 | + struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef; |
| 152 | + enum nl80211_band band = chandef->chan->band; |
| 153 | + struct mt76_wcid *wcid = &dev->mt76.global_wcid; |
| 154 | + struct bss_info_inband_discovery *discov; |
| 155 | + struct ieee80211_tx_info *info; |
| 156 | + struct sk_buff *skb = NULL; |
| 157 | + struct tlv *tlv; |
| 158 | + bool ext_phy = phy != &dev->phy; |
| 159 | + u8 *buf, interval; |
| 160 | + int len; |
| 161 | + |
| 162 | + if (changed & BSS_CHANGED_FILS_DISCOVERY && |
| 163 | + vif->bss_conf.fils_discovery.max_interval) { |
| 164 | + interval = vif->bss_conf.fils_discovery.max_interval; |
| 165 | + skb = ieee80211_get_fils_discovery_tmpl(hw, vif); |
| 166 | + } else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP && |
| 167 | + vif->bss_conf.unsol_bcast_probe_resp_interval) { |
| 168 | + interval = vif->bss_conf.unsol_bcast_probe_resp_interval; |
| 169 | + skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif); |
| 170 | + } |
| 171 | + |
| 172 | + if (!skb) |
| 173 | + return; |
| 174 | + |
| 175 | + info = IEEE80211_SKB_CB(skb); |
| 176 | + info->control.vif = vif; |
| 177 | + info->band = band; |
| 178 | + |
| 179 | + if (ext_phy) |
| 180 | + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; |
| 181 | + |
| 182 | + len = sizeof(*discov) + MT_TXD_SIZE + skb->len; |
| 183 | + len = (len & 0x3) ? ((len | 0x3) + 1) : len; |
| 184 | + |
| 185 | + tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV, |
| 186 | + len, &bcn->sub_ntlv, &bcn->len); |
| 187 | + discov = (struct bss_info_inband_discovery *)tlv; |
| 188 | + discov->tx_mode = OFFLOAD_TX_MODE_SU; |
| 189 | + /* 0: UNSOL PROBE RESP, 1: FILS DISCOV */ |
| 190 | + discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY); |
| 191 | + discov->tx_interval = interval; |
| 192 | + discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len); |
| 193 | + discov->enable = true; |
| 194 | + |
| 195 | + buf = (u8 *)tlv + sizeof(*discov); |
| 196 | + |
| 197 | + mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL, |
| 198 | + changed); |
| 199 | + memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); |
| 200 | + |
| 201 | + dev_kfree_skb(skb); |
| 202 | +} |
| 203 | + |
| 204 | +int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| 205 | + int en, u32 changed) |
| 206 | { |
| 207 | #define MAX_BEACON_SIZE 512 |
| 208 | struct mt7915_dev *dev = mt7915_hw_dev(hw); |
| 209 | @@ -2044,6 +2108,11 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, |
| 210 | mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs); |
| 211 | dev_kfree_skb(skb); |
| 212 | |
| 213 | + if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP || |
| 214 | + changed & BSS_CHANGED_FILS_DISCOVERY) |
| 215 | + mt7915_mcu_beacon_inband_discov(dev, vif, rskb, |
| 216 | + bcn, changed); |
| 217 | + |
| 218 | out: |
| 219 | return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, |
| 220 | MCU_EXT_CMD(BSS_INFO_UPDATE), true); |
| 221 | diff --git a/mt7915/mcu.h b/mt7915/mcu.h |
| 222 | index 064d33e33738..e1d576701fdf 100644 |
| 223 | --- a/mt7915/mcu.h |
| 224 | +++ b/mt7915/mcu.h |
| 225 | @@ -404,11 +404,23 @@ struct bss_info_bcn_cont { |
| 226 | __le16 pkt_len; |
| 227 | } __packed __aligned(4); |
| 228 | |
| 229 | +struct bss_info_inband_discovery { |
| 230 | + __le16 tag; |
| 231 | + __le16 len; |
| 232 | + u8 tx_type; |
| 233 | + u8 tx_mode; |
| 234 | + u8 tx_interval; |
| 235 | + u8 enable; |
| 236 | + __le16 rsv; |
| 237 | + __le16 prob_rsp_len; |
| 238 | +} __packed __aligned(4); |
| 239 | + |
| 240 | enum { |
| 241 | BSS_INFO_BCN_CSA, |
| 242 | BSS_INFO_BCN_BCC, |
| 243 | BSS_INFO_BCN_MBSSID, |
| 244 | BSS_INFO_BCN_CONTENT, |
| 245 | + BSS_INFO_BCN_DISCOV, |
| 246 | BSS_INFO_BCN_MAX |
| 247 | }; |
| 248 | |
| 249 | @@ -476,6 +488,7 @@ enum { |
| 250 | #define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \ |
| 251 | sizeof(struct bss_info_bcn_cntdwn) + \ |
| 252 | sizeof(struct bss_info_bcn_mbss) + \ |
| 253 | - sizeof(struct bss_info_bcn_cont)) |
| 254 | + sizeof(struct bss_info_bcn_cont) + \ |
| 255 | + sizeof(struct bss_info_inband_discovery)) |
| 256 | |
| 257 | #endif |
| 258 | diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h |
| 259 | index 6c590eff14f1..03431012b2ff 100644 |
| 260 | --- a/mt7915/mt7915.h |
| 261 | +++ b/mt7915/mt7915.h |
| 262 | @@ -464,7 +464,7 @@ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, |
| 263 | int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif, |
| 264 | struct cfg80211_he_bss_color *he_bss_color); |
| 265 | int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| 266 | - int enable); |
| 267 | + int enable, u32 changed); |
| 268 | int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, |
| 269 | bool enable); |
| 270 | int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, |
| 271 | @@ -551,7 +551,7 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy); |
| 272 | void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy); |
| 273 | void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, |
| 274 | struct sk_buff *skb, struct mt76_wcid *wcid, int pid, |
| 275 | - struct ieee80211_key_conf *key, bool beacon); |
| 276 | + struct ieee80211_key_conf *key, u32 changed); |
| 277 | void mt7915_mac_set_timing(struct mt7915_phy *phy); |
| 278 | int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, |
| 279 | struct ieee80211_sta *sta); |
| 280 | -- |
| 281 | 2.18.0 |
| 282 | |