mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
wifi: iwlwifi: mld: decode VHT information for sniffer
The available VHT information may be useful, so decode it and include it in the generated radiotap headers. Signed-off-by: Benjamin Berg <benjamin.berg@intel.com> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20251110150012.6751d1d0b31d.I927cb0767667f2c03ee41f2ba417f3b94bba6d91@changeid
This commit is contained in:
parent
b47b3d0d8b
commit
4bfdbd5d1e
|
|
@ -1062,7 +1062,29 @@ struct iwl_vht_sigs {
|
|||
#define OFDM_RX_FRAME_VHT_NUM_OF_DATA_SYM 0x000007ff
|
||||
#define OFDM_RX_FRAME_VHT_NUM_OF_DATA_SYM_VALID 0x80000000
|
||||
__le32 a0;
|
||||
__le32 a1, a2;
|
||||
#define OFDM_RX_FRAME_VHT_BANDWIDTH 0x00000003
|
||||
#define OFDM_RX_FRAME_VHT_STBC 0x00000008
|
||||
#define OFDM_RX_FRAME_VHT_GRP_ID 0x000003f0
|
||||
#define OFDM_RX_FRAME_VHT_STS_USER0 0x00001c00
|
||||
#define OFDM_RX_FRAME_VHT_MU_STS_USER1 0x0000e000
|
||||
#define OFDM_RX_FRAME_VHT_MU_STS_USER2 0x00070000
|
||||
#define OFDM_RX_FRAME_VHT_MU_STS_USER3 0x00380000
|
||||
#define OFDM_RX_FRAME_VHT_PARTIAL_AID_OR_MU_STS 0x003fe000
|
||||
#define OFDM_RX_FRAME_VHT_MU_MIMO_USER_POSITION 0x03000000
|
||||
#define OFDM_RX_FRAME_VHT_NO_STREAMS 0x04000000
|
||||
#define OFDM_RX_FRAME_VHT_STS 0x38000000
|
||||
__le32 a1;
|
||||
#define OFDM_RX_FRAME_VHT_SHORT_GI 0x00000001
|
||||
#define OFDM_RX_FRAME_VHT_SHORT_GI_AMBIG 0x00000002
|
||||
#define OFDM_RX_FRAME_VHT_CODING 0x00000004
|
||||
#define OFDM_RX_FRAME_VHT_CODING_EXTRA_SYM 0x00000008
|
||||
#define OFDM_RX_FRAME_VHT_MCS_OR_MU_CODING 0x000000f0
|
||||
#define OFDM_RX_FRAME_VHT_BF_OR_MU_RESERVED 0x00000100
|
||||
#define OFDM_RX_FRAME_VHT_CRC 0x0003fc00
|
||||
#define OFDM_RX_FRAME_VHT_CRC_OK_BIT 0x00040000
|
||||
#define OFDM_RX_FRAME_VHT_CUR_USER_CODING 0x00080000
|
||||
#define OFDM_RX_FRAME_VHT_CUR_USER_STS 0x00700000
|
||||
__le32 a2;
|
||||
};
|
||||
|
||||
struct iwl_he_sigs {
|
||||
|
|
|
|||
|
|
@ -207,6 +207,134 @@ static void iwl_mld_fill_signal(struct iwl_mld *mld, int link_id,
|
|||
rx_status->chain_signal[1] = energy_b;
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mld_decode_vht_phy_data(struct iwl_mld_rx_phy_data *phy_data,
|
||||
struct ieee80211_radiotap_vht *vht,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
bool stbc;
|
||||
|
||||
vht->known = cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH |
|
||||
IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID |
|
||||
IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
|
||||
IEEE80211_RADIOTAP_VHT_KNOWN_GI |
|
||||
IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS |
|
||||
IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM |
|
||||
IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED);
|
||||
|
||||
switch (le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_BANDWIDTH)) {
|
||||
case 0:
|
||||
vht->bandwidth = IEEE80211_RADIOTAP_VHT_BW_20;
|
||||
break;
|
||||
case 1:
|
||||
vht->bandwidth = IEEE80211_RADIOTAP_VHT_BW_40;
|
||||
break;
|
||||
case 2:
|
||||
vht->bandwidth = IEEE80211_RADIOTAP_VHT_BW_80;
|
||||
break;
|
||||
case 3:
|
||||
vht->bandwidth = IEEE80211_RADIOTAP_VHT_BW_160;
|
||||
break;
|
||||
}
|
||||
|
||||
vht->group_id = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_GRP_ID);
|
||||
|
||||
stbc = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_STBC);
|
||||
if (stbc)
|
||||
vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
|
||||
|
||||
if (le32_get_bits(phy_data->ntfy->sigs.vht.a2,
|
||||
OFDM_RX_FRAME_VHT_SHORT_GI))
|
||||
vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
|
||||
|
||||
if (le32_get_bits(phy_data->ntfy->sigs.vht.a2,
|
||||
OFDM_RX_FRAME_VHT_SHORT_GI_AMBIG))
|
||||
vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9;
|
||||
|
||||
if (le32_get_bits(phy_data->ntfy->sigs.vht.a2,
|
||||
OFDM_RX_FRAME_VHT_CODING_EXTRA_SYM))
|
||||
vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM;
|
||||
|
||||
if (vht->group_id != 0 && vht->group_id != 63) {
|
||||
/* MU frame */
|
||||
int user = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_MU_MIMO_USER_POSITION);
|
||||
int nsts;
|
||||
|
||||
/* Always beamformed */
|
||||
vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
|
||||
|
||||
/* No MCS information in the a1/a2 data for MU frames */
|
||||
nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_STS_USER0);
|
||||
vht->mcs_nss[0] = (stbc ? nsts / 2 : nsts) | 0xf0;
|
||||
|
||||
nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_MU_STS_USER1);
|
||||
vht->mcs_nss[1] = (stbc ? nsts / 2 : nsts) | 0xf0;
|
||||
|
||||
nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_MU_STS_USER2);
|
||||
vht->mcs_nss[2] = (stbc ? nsts / 2 : nsts) | 0xf0;
|
||||
|
||||
nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_MU_STS_USER3);
|
||||
vht->mcs_nss[3] = (stbc ? nsts / 2 : nsts) | 0xf0;
|
||||
|
||||
/* Report current user MCS from rate_n_flags via rx_status */
|
||||
vht->mcs_nss[user] &= 0x0f;
|
||||
vht->mcs_nss[user] |= rx_status->rate_idx << 4;
|
||||
|
||||
/* Report LDPC for current user */
|
||||
if (rx_status->enc_flags & RX_ENC_FLAG_LDPC)
|
||||
vht->coding = 0x1 << user;
|
||||
} else {
|
||||
int nsts;
|
||||
|
||||
/* SU frame */
|
||||
vht->known |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID);
|
||||
|
||||
if (le32_get_bits(phy_data->ntfy->sigs.vht.a2,
|
||||
OFDM_RX_FRAME_VHT_BF_OR_MU_RESERVED))
|
||||
vht->flags |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
|
||||
|
||||
vht->partial_aid =
|
||||
cpu_to_le16(le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_PARTIAL_AID_OR_MU_STS));
|
||||
|
||||
nsts = le32_get_bits(phy_data->ntfy->sigs.vht.a1,
|
||||
OFDM_RX_FRAME_VHT_STS) + 1;
|
||||
vht->mcs_nss[0] =
|
||||
(stbc ? nsts / 2 : nsts) |
|
||||
le32_get_bits(phy_data->ntfy->sigs.vht.a2,
|
||||
OFDM_RX_FRAME_VHT_MCS_OR_MU_CODING) << 4;
|
||||
vht->mcs_nss[1] = 0;
|
||||
vht->mcs_nss[2] = 0;
|
||||
vht->mcs_nss[3] = 0;
|
||||
|
||||
if (rx_status->enc_flags & RX_ENC_FLAG_LDPC)
|
||||
vht->coding = 0x1;
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mld_rx_vht(struct sk_buff *skb,
|
||||
struct iwl_mld_rx_phy_data *phy_data)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_radiotap_vht *vht;
|
||||
|
||||
if (likely(!phy_data->ntfy))
|
||||
return;
|
||||
|
||||
vht = skb_put_zero(skb, sizeof(*vht));
|
||||
rx_status->flag |= RX_FLAG_RADIOTAP_VHT;
|
||||
|
||||
iwl_mld_decode_vht_phy_data(phy_data, vht, rx_status);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mld_he_set_ru_alloc(struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_radiotap_he *he,
|
||||
|
|
@ -1377,6 +1505,10 @@ static void iwl_mld_rx_fill_status(struct iwl_mld *mld, int link_id,
|
|||
|
||||
iwl_mld_set_rx_rate(mld, phy_data, rx_status);
|
||||
|
||||
/* must be before HE data (radiotap field order) */
|
||||
if (format == RATE_MCS_MOD_TYPE_VHT)
|
||||
iwl_mld_rx_vht(skb, phy_data);
|
||||
|
||||
/* must be before L-SIG data (radiotap field order) */
|
||||
if (format == RATE_MCS_MOD_TYPE_HE)
|
||||
iwl_mld_rx_he(skb, phy_data);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user