wifi: iwlwifi: mvm: add primary 80 known for EHT radiotap
authorMordechay Goodstein <mordechay.goodstein@intel.com>
Sun, 5 Mar 2023 12:16:26 +0000 (14:16 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 7 Mar 2023 19:15:18 +0000 (20:15 +0100)
Calculate the position of the control channel in the wide channel
based on the chandef, this is used to obtain the value of N in
802.11be D1.5 Table 9-53a in the column PHY MU/MRU index.

To avoid the need to calculate every frame the value, do it once
monitor vif is added.

Signed-off-by: Mordechay Goodstein <mordechay.goodstein@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230305124407.fe9a5b58e241.I291ee480252d098f62d9ec39040284d3e521d88e@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c

index 5655224..51c7652 100644 (file)
@@ -1362,6 +1362,28 @@ static void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk)
        ieee80211_chswitch_done(vif, false);
 }
 
+static u8
+iwl_mvm_chandef_get_primary_80(struct cfg80211_chan_def *chandef)
+{
+       int data_start;
+       int control_start;
+       int bw;
+
+       if (chandef->width == NL80211_CHAN_WIDTH_320)
+               bw = 320;
+       else if (chandef->width == NL80211_CHAN_WIDTH_160)
+               bw = 160;
+       else
+               return 0;
+
+       /* data is bw wide so the start is half the width */
+       data_start = chandef->center_freq1 - bw / 2;
+       /* control is 20Mhz width */
+       control_start = chandef->chan->center_freq - 10;
+
+       return (control_start - data_start) / 80;
+}
+
 static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
                                     struct ieee80211_vif *vif)
 {
@@ -1478,8 +1500,11 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
        INIT_DELAYED_WORK(&mvmvif->csa_work,
                          iwl_mvm_channel_switch_disconnect_wk);
 
-       if (vif->type == NL80211_IFTYPE_MONITOR)
+       if (vif->type == NL80211_IFTYPE_MONITOR) {
                mvm->monitor_on = true;
+               mvm->monitor_p80 =
+                       iwl_mvm_chandef_get_primary_80(&vif->bss_conf.chandef);
+       }
 
        iwl_mvm_vif_dbgfs_register(mvm, vif);
 
index ce6b701..301f39d 100644 (file)
@@ -1096,6 +1096,11 @@ struct iwl_mvm {
 
        /* does a monitor vif exist (only one can exist hence bool) */
        bool monitor_on;
+       /*
+        * primary channel position relative to he whole bandwidth,
+        * in steps of 80 MHz
+        */
+       u8 monitor_p80;
 
        /* sniffer data to include in radiotap */
        __le16 cur_aid;
index 1334c96..b545673 100644 (file)
@@ -1695,6 +1695,15 @@ static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm,
 
        iwl_mvm_decode_eht_ru(mvm, rx_status, eht);
 
+       /* We only get here in case of IWL_RX_MPDU_PHY_TSF_OVERLOAD is set
+        * which is on only in case of monitor mode so no need to check monitor
+        * mode
+        */
+       eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_PRIMARY_80);
+       eht->data[1] |=
+               le32_encode_bits(mvm->monitor_p80,
+                                IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80);
+
        usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN);
        if (phy_data->with_data)
                usig->common |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_TXOP_DUR_MASK,