mt76: mt7915: introduce 802.11ax multi-bss support
authorLorenzo Bianconi <lorenzo@kernel.org>
Tue, 15 Mar 2022 12:19:12 +0000 (13:19 +0100)
committerFelix Fietkau <nbd@nbd.name>
Wed, 16 Mar 2022 20:13:03 +0000 (21:13 +0100)
Introduce mbss mcu APIs to enable 802.11ax multi-bss AP support for
mt7915 devices

Tested-by: Money Wang <money.wang@mediatek.com>
Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Co-developed-by: Money Wang <money.wang@mediatek.com>
Signed-off-by: Money Wang <money.wang@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/init.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c

index eeb73d14552b57c7781d791b9ef7c69d7f19f827..7cb17bf40e35a5e7fdf2ac5a7a4a21220f067fb7 100644 (file)
@@ -2675,11 +2675,25 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
        struct bss_info_basic *bss;
        struct tlv *tlv;
 
+       tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss));
+       bss = (struct bss_info_basic *)tlv;
+
        switch (vif->type) {
        case NL80211_IFTYPE_MESH_POINT:
-       case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_MONITOR:
                break;
+       case NL80211_IFTYPE_AP:
+               if (ieee80211_hw_check(phy->hw, SUPPORTS_MULTI_BSSID)) {
+                       u8 bssid_id = vif->bss_conf.bssid_indicator;
+                       struct wiphy *wiphy = phy->hw->wiphy;
+
+                       if (bssid_id > ilog2(wiphy->mbssid_max_interfaces))
+                               return -EINVAL;
+
+                       bss->non_tx_bssid = vif->bss_conf.bssid_index;
+                       bss->max_bssid = bssid_id;
+               }
+               break;
        case NL80211_IFTYPE_STATION:
                if (enable) {
                        rcu_read_lock();
@@ -2704,9 +2718,6 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
                break;
        }
 
-       tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss));
-
-       bss = (struct bss_info_basic *)tlv;
        bss->network_type = cpu_to_le32(type);
        bss->bmc_wcid_lo = to_wcid_lo(wlan_idx);
        bss->bmc_wcid_hi = to_wcid_hi(wlan_idx);
index 9a8df1282f8daac429e902b72273e81e2ad7ca10..6d29366c5139b507d3ee561be940fee92b95920b 100644 (file)
@@ -343,6 +343,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
        wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
        wiphy->reg_notifier = mt7915_regd_notifier;
        wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+       wiphy->mbssid_max_interfaces = 16;
 
        wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
        wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
@@ -360,6 +361,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
        ieee80211_hw_set(hw, HAS_RATE_CONTROL);
        ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
        ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
+       ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
        ieee80211_hw_set(hw, WANT_MONITOR_VIF);
 
        hw->max_tx_fragments = 4;
index 10dc4bf5adeca360922f6c1a36e6cee907f74a63..9cd458223b00e69a4ffefca1ad2e7e5ebb8af14e 100644 (file)
@@ -1825,6 +1825,55 @@ mt7915_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
        info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
 }
 
+static void
+mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
+                      struct ieee80211_vif *vif, struct bss_info_bcn *bcn,
+                      struct ieee80211_mutable_offsets *offs)
+{
+       struct bss_info_bcn_mbss *mbss;
+       const struct element *elem;
+       struct tlv *tlv;
+
+       if (!vif->bss_conf.bssid_indicator)
+               return;
+
+       tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_MBSSID,
+                                          sizeof(*mbss), &bcn->sub_ntlv,
+                                          &bcn->len);
+
+       mbss = (struct bss_info_bcn_mbss *)tlv;
+       mbss->offset[0] = cpu_to_le16(offs->tim_offset);
+       mbss->bitmap = cpu_to_le32(1);
+
+       for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID,
+                           &skb->data[offs->mbssid_off],
+                           skb->len - offs->mbssid_off) {
+               const struct element *sub_elem;
+
+               if (elem->datalen < 2)
+                       continue;
+
+               for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
+                       const u8 *data;
+
+                       if (sub_elem->id || sub_elem->datalen < 4)
+                               continue; /* not a valid BSS profile */
+
+                       /* Find WLAN_EID_MULTI_BSSID_IDX
+                        * in the merged nontransmitted profile
+                        */
+                       data = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
+                                               sub_elem->data,
+                                               sub_elem->datalen);
+                       if (!data || data[1] < 1 || !data[2])
+                               continue;
+
+                       mbss->offset[data[2]] = cpu_to_le16(data - skb->data);
+                       mbss->bitmap |= cpu_to_le32(BIT(data[2]));
+               }
+       }
+}
+
 static void
 mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                       struct sk_buff *rskb, struct sk_buff *skb,
@@ -1952,6 +2001,9 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
        int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE;
        bool ext_phy = phy != &dev->phy;
 
+       if (vif->bss_conf.nontransmitted)
+               return 0;
+
        rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
                                               NULL, len);
        if (IS_ERR(rskb))
@@ -1981,8 +2033,8 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
 
        mt7915_mcu_beacon_check_caps(phy, vif, skb);
 
-       /* TODO: subtag - 11v MBSSID */
        mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs);
+       mt7915_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
        mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
        dev_kfree_skb(skb);