]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
wifi: rtw89: add HE radiotap for monitor mode
authorPing-Ke Shih <pkshih@realtek.com>
Fri, 25 Nov 2022 07:24:15 +0000 (15:24 +0800)
committerKalle Valo <kvalo@kernel.org>
Thu, 1 Dec 2022 11:02:31 +0000 (13:02 +0200)
With basic HE radiotap, we can check data rate in sniffer data. To store
the radiotap data, we reserve headroom of aligned 64 bytes, and then
update HE radiotap in monitor mode, so it doesn't affect performance in
normal mode.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20221125072416.94752-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/pci.c

index af8daa101f457ba56103487761a3e6d89b5ce436..190d72df800f9f3ee43a67cc2ba1536a646e39f6 100644 (file)
@@ -1480,6 +1480,27 @@ static void rtw89_core_hw_to_sband_rate(struct ieee80211_rx_status *rx_status)
        rx_status->rate_idx -= 4;
 }
 
+static void rtw89_core_update_radiotap(struct rtw89_dev *rtwdev,
+                                      struct sk_buff *skb,
+                                      struct ieee80211_rx_status *rx_status)
+{
+       static const struct ieee80211_radiotap_he known_he = {
+               .data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
+                                    IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN),
+               .data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN),
+       };
+       struct ieee80211_radiotap_he *he;
+
+       if (!(rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR))
+               return;
+
+       if (rx_status->encoding == RX_ENC_HE) {
+               rx_status->flag |= RX_FLAG_RADIOTAP_HE;
+               he = skb_push(skb, sizeof(*he));
+               *he = known_he;
+       }
+}
+
 static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev,
                                      struct rtw89_rx_phy_ppdu *phy_ppdu,
                                      struct rtw89_rx_desc_info *desc_info,
@@ -1494,6 +1515,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_radiotap(rtwdev, skb_ppdu, rx_status);
        /* In low power mode, it does RX in thread context. */
        local_bh_disable();
        ieee80211_rx_napi(rtwdev->hw, NULL, skb_ppdu, napi);
index 1b0acb1c5450ef462cde961b1686fff5076a8cc5..0be8f7bd3ca2df3037dae14a8370e2107d0e51f4 100644 (file)
@@ -35,6 +35,7 @@ extern const struct ieee80211_ops rtw89_ops;
 #define RSSI_FACTOR 1
 #define RTW89_RSSI_RAW_TO_DBM(rssi) ((s8)((rssi) >> RSSI_FACTOR) - MAX_RSSI)
 #define RTW89_TX_DIV_RSSI_RAW_TH (2 << RSSI_FACTOR)
+#define RTW89_RADIOTAP_ROOM ALIGN(sizeof(struct ieee80211_radiotap_he), 64)
 
 #define RTW89_HTC_MASK_VARIANT GENMASK(1, 0)
 #define RTW89_HTC_VARIANT_HE 3
@@ -4383,6 +4384,23 @@ static inline struct rtw89_fw_suit *rtw89_fw_suit_get(struct rtw89_dev *rtwdev,
        return &fw_info->normal;
 }
 
+static inline struct sk_buff *rtw89_alloc_skb_for_rx(struct rtw89_dev *rtwdev,
+                                                    unsigned int length)
+{
+       struct sk_buff *skb;
+
+       if (rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR) {
+               skb = dev_alloc_skb(length + RTW89_RADIOTAP_ROOM);
+               if (!skb)
+                       return NULL;
+
+               skb_reserve(skb, RTW89_RADIOTAP_ROOM);
+               return skb;
+       }
+
+       return dev_alloc_skb(length);
+}
+
 int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
                        struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel);
 int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
index 7aa0af18cdd5029b54130d53e2e246063aa0ff54..1c4500ba777c657bc409bea43d26ed0e691c52df 100644 (file)
@@ -267,7 +267,7 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev,
 
                rtw89_core_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size);
 
-               new = dev_alloc_skb(desc_info->pkt_size);
+               new = rtw89_alloc_skb_for_rx(rtwdev, desc_info->pkt_size);
                if (!new)
                        goto err_sync_device;