]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: add LDPC and STBC to rx_status and radiotap known fields for monitor...
authorPing-Ke Shih <pkshih@realtek.com>
Wed, 22 May 2024 02:38:30 +0000 (10:38 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Mon, 27 May 2024 08:51:42 +0000 (16:51 +0800)
Add LDPC and STBC to rx_status by hardware PPDU status, and set them as
known fields of radiotap, so we can check these capabilities in monitor
mode.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://msgid.link/20240522023830.9798-2-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/txrx.h

index 36d31608157f140ec0782ffcb1e58ff8fb2ee5ef..3e99b63a7995951556570a6162b643f517dfa26f 100644 (file)
@@ -1557,6 +1557,12 @@ static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev,
        u32 t;
 
        phy_ppdu->chan_idx = le32_get_bits(ie->w0, RTW89_PHY_STS_IE01_W0_CH_IDX);
+
+       if (rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR) {
+               phy_ppdu->ldpc = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_LDPC);
+               phy_ppdu->stbc = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_STBC);
+       }
+
        if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6)
                return;
 
@@ -1982,6 +1988,23 @@ static void rtw89_core_hw_to_sband_rate(struct ieee80211_rx_status *rx_status)
        rx_status->rate_idx -= 4;
 }
 
+static
+void rtw89_core_update_rx_status_by_ppdu(struct rtw89_dev *rtwdev,
+                                        struct ieee80211_rx_status *rx_status,
+                                        struct rtw89_rx_phy_ppdu *phy_ppdu)
+{
+       if (!(rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR))
+               return;
+
+       if (!phy_ppdu)
+               return;
+
+       if (phy_ppdu->ldpc)
+               rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
+       if (phy_ppdu->stbc)
+               rx_status->enc_flags |= u8_encode_bits(1, RX_ENC_FLAG_STBC_MASK);
+}
+
 static const u8 rx_status_bw_to_radiotap_eht_usig[] = {
        [RATE_INFO_BW_20] = IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_20MHZ,
        [RATE_INFO_BW_5] = U8_MAX,
@@ -2025,10 +2048,14 @@ static void rtw89_core_update_radiotap_eht(struct rtw89_dev *rtwdev,
 
        eht->user_info[0] =
                cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_MCS_KNOWN |
-                           IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O);
+                           IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_KNOWN_O |
+                           IEEE80211_RADIOTAP_EHT_USER_INFO_CODING_KNOWN);
        eht->user_info[0] |=
                le32_encode_bits(rx_status->rate_idx, IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) |
                le32_encode_bits(rx_status->nss, IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O);
+       if (rx_status->enc_flags & RX_ENC_FLAG_LDPC)
+               eht->user_info[0] |=
+                       cpu_to_le32(IEEE80211_RADIOTAP_EHT_USER_INFO_CODING);
 
        /* U-SIG */
        tlv = (void *)tlv + sizeof(*tlv) + ALIGN(eht_len, 4);
@@ -2054,6 +2081,8 @@ static void rtw89_core_update_radiotap(struct rtw89_dev *rtwdev,
 {
        static const struct ieee80211_radiotap_he known_he = {
                .data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
+                                    IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN |
+                                    IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN |
                                     IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN),
                .data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN),
        };
@@ -2085,6 +2114,7 @@ static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev,
 
        rtw89_core_hw_to_sband_rate(rx_status);
        rtw89_core_rx_stats(rtwdev, phy_ppdu, desc_info, skb_ppdu);
+       rtw89_core_update_rx_status_by_ppdu(rtwdev, rx_status, phy_ppdu);
        rtw89_core_update_radiotap(rtwdev, skb_ppdu, rx_status);
        /* In low power mode, it does RX in thread context. */
        local_bh_disable();
@@ -4496,6 +4526,10 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
        hw->max_tx_aggregation_subframes = RTW89_MAX_TX_AGG_NUM;
        hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL;
 
+       hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
+                                   IEEE80211_RADIOTAP_MCS_HAVE_STBC;
+       hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC;
+
        ieee80211_hw_set(hw, SIGNAL_DBM);
        ieee80211_hw_set(hw, HAS_RATE_CONTROL);
        ieee80211_hw_set(hw, MFP_CAPABLE);
index e953c99b9a471376980214a284ea2fa7cec10f1b..68221f0b156e2789b851a1bdebf1484e4996422c 100644 (file)
@@ -793,6 +793,8 @@ struct rtw89_rx_phy_ppdu {
                u8 evm_max;
                u8 evm_min;
        } ofdm;
+       bool ldpc;
+       bool stbc;
        bool to_self;
        bool valid;
 };
index 11049a50de2c97dd1372f12d27e52a0c5e845b11..3882938c089318cf3c8c66aa501bd320abafa9f9 100644 (file)
@@ -558,6 +558,8 @@ struct rtw89_phy_sts_ie0 {
 #define RTW89_PHY_STS_IE01_W2_AVG_SNR GENMASK(5, 0)
 #define RTW89_PHY_STS_IE01_W2_EVM_MAX GENMASK(15, 8)
 #define RTW89_PHY_STS_IE01_W2_EVM_MIN GENMASK(23, 16)
+#define RTW89_PHY_STS_IE01_W2_LDPC BIT(28)
+#define RTW89_PHY_STS_IE01_W2_STBC BIT(30)
 
 enum rtw89_tx_channel {
        RTW89_TXCH_ACH0 = 0,