OSDN Git Service

mt76: mt7915: add TxBF capabilities
authorRyder Lee <ryder.lee@mediatek.com>
Mon, 11 May 2020 16:06:35 +0000 (00:06 +0800)
committerFelix Fietkau <nbd@nbd.name>
Tue, 12 May 2020 17:52:37 +0000 (19:52 +0200)
This allows to set HE TxBF runtime stream capabilities

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Evelyn Tsai <evelyn.tsai@mediatek.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7915/init.c
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h

index 3721bd6..e2b0ea3 100644 (file)
@@ -259,6 +259,94 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
        hw->max_tx_fragments = 4;
 }
 
+void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)
+{
+       int nss = hweight8(phy->chainmask);
+       u32 *cap = &phy->mt76->sband_5g.sband.vht_cap.cap;
+
+       *cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+               IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
+               (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
+
+       *cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK |
+                 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+                 IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
+
+       if (nss < 2)
+               return;
+
+       *cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+               IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE |
+               FIELD_PREP(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,
+                          nss - 1);
+}
+
+static void
+mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
+                              int vif, int nss)
+{
+       struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
+       struct ieee80211_he_mcs_nss_supp *mcs = &he_cap->he_mcs_nss_supp;
+       u8 c;
+
+#ifdef CONFIG_MAC80211_MESH
+       if (vif == NL80211_IFTYPE_MESH_POINT)
+               return;
+#endif
+
+       elem->phy_cap_info[3] &= ~IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
+       elem->phy_cap_info[4] &= ~IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
+
+       c = IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK |
+           IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
+       elem->phy_cap_info[5] &= ~c;
+
+       c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB |
+           IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB;
+       elem->phy_cap_info[6] &= ~c;
+
+       elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;
+
+       c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
+           IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
+           IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
+       elem->phy_cap_info[2] |= c;
+
+       c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
+           IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 |
+           IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;
+       elem->phy_cap_info[4] |= c;
+
+       /* do not support NG16 due to spec D4.0 changes subcarrier idx */
+       c = IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |
+           IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU;
+
+       if (vif == NL80211_IFTYPE_STATION)
+               c |= IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
+
+       elem->phy_cap_info[6] |= c;
+
+       if (nss < 2)
+               return;
+
+       if (vif != NL80211_IFTYPE_AP)
+               return;
+
+       elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
+       elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
+
+       /* num_snd_dim */
+       c = (nss - 1) | (max_t(int, mcs->tx_mcs_160, 1) << 3);
+       elem->phy_cap_info[5] |= c;
+
+       c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB |
+           IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB;
+       elem->phy_cap_info[6] |= c;
+
+       /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */
+       elem->phy_cap_info[7] |= min_t(int, nss - 1, 2) << 3;
+}
+
 static void
 mt7915_gen_ppe_thresh(u8 *he_ppet)
 {
@@ -352,11 +440,10 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
                he_cap_elem->phy_cap_info[1] =
                        IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
                he_cap_elem->phy_cap_info[2] =
-                       IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
                        IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
                        IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
 
-               /* TODO: TxBF & MU & MESH */
+               /* TODO: OFDMA */
 
                switch (i) {
                case NL80211_IFTYPE_AP:
@@ -407,6 +494,8 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
                he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map);
                he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map);
 
+               mt7915_set_stream_he_txbf_caps(he_cap, i, nss);
+
                memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
                if (he_cap_elem->phy_cap_info[6] &
                    IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
@@ -464,6 +553,7 @@ mt7915_cap_dbdc_enable(struct mt7915_dev *dev)
        dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask;
 
        mt76_set_stream_caps(&dev->mphy, true);
+       mt7915_set_stream_vht_txbf_caps(&dev->phy);
        mt7915_set_stream_he_caps(&dev->phy);
 }
 
@@ -480,6 +570,7 @@ mt7915_cap_dbdc_disable(struct mt7915_dev *dev)
        dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask;
 
        mt76_set_stream_caps(&dev->mphy, true);
+       mt7915_set_stream_vht_txbf_caps(&dev->phy);
        mt7915_set_stream_he_caps(&dev->phy);
 }
 
index f3a373f..147ab7d 100644 (file)
@@ -745,6 +745,7 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
        phy->chainmask = tx_ant;
 
        mt76_set_stream_caps(phy->mt76, true);
+       mt7915_set_stream_vht_txbf_caps(phy);
        mt7915_set_stream_he_caps(phy);
 
        mutex_unlock(&dev->mt76.mutex);
index 0d5b448..537fc12 100644 (file)
@@ -454,6 +454,7 @@ void mt7915_txp_skb_unmap(struct mt76_dev *dev,
 int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
 int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy);
 void mt7915_set_stream_he_caps(struct mt7915_phy *phy);
+void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy);
 void mt7915_update_channel(struct mt76_dev *mdev);
 int mt7915_init_debugfs(struct mt7915_dev *dev);
 #ifdef CONFIG_MAC80211_DEBUGFS