Commit ffe9d734 authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho

iwlwifi: mvm: clean up HE radiotap RU allocation parsing

Split the code out into a separate routine, and move that to be
called inside the previously introduced iwl_mvm_decode_he_phy_data()
function.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 59b8cf0c
...@@ -923,10 +923,83 @@ static void iwl_mvm_decode_he_sigb(struct iwl_mvm *mvm, ...@@ -923,10 +923,83 @@ static void iwl_mvm_decode_he_sigb(struct iwl_mvm *mvm,
} }
} }
static void
iwl_mvm_decode_he_phy_ru_alloc(u64 he_phy_data, u32 rate_n_flags,
struct ieee80211_radiotap_he *he,
struct ieee80211_radiotap_he_mu *he_mu,
struct ieee80211_rx_status *rx_status)
{
/*
* Unfortunately, we have to leave the mac80211 data
* incorrect for the case that we receive an HE-MU
* transmission and *don't* have the HE phy data (due
* to the bits being used for TSF). This shouldn't
* happen though as management frames where we need
* the TSF/timers are not be transmitted in HE-MU.
*/
u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data);
u8 offs = 0;
rx_status->bw = RATE_INFO_BW_HE_RU;
he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
switch (ru) {
case 0 ... 36:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
offs = ru;
break;
case 37 ... 52:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
offs = ru - 37;
break;
case 53 ... 60:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
offs = ru - 53;
break;
case 61 ... 64:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
offs = ru - 61;
break;
case 65 ... 66:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
offs = ru - 65;
break;
case 67:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
break;
case 68:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
break;
}
he->data2 |= le16_encode_bits(offs,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN |
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN);
if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80)
he->data2 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
if (he_mu) {
#define CHECK_BW(bw) \
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \
RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
CHECK_BW(20);
CHECK_BW(40);
CHECK_BW(80);
CHECK_BW(160);
he_mu->flags2 |=
le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
rate_n_flags),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
}
}
static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
struct iwl_rx_mpdu_desc *desc, struct iwl_rx_mpdu_desc *desc,
struct ieee80211_radiotap_he *he, struct ieee80211_radiotap_he *he,
struct ieee80211_radiotap_he_mu *he_mu, struct ieee80211_radiotap_he_mu *he_mu,
struct ieee80211_rx_status *rx_status,
u64 he_phy_data, u32 rate_n_flags, u64 he_phy_data, u32 rate_n_flags,
int queue) int queue)
{ {
...@@ -975,6 +1048,17 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, ...@@ -975,6 +1048,17 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm,
he->data3 |= he->data3 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA3_UL_DL); cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA3_UL_DL);
} }
switch (FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data)) {
case IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO:
case IWL_RX_HE_PHY_INFO_TYPE_TB_EXT_INFO:
iwl_mvm_decode_he_phy_ru_alloc(he_phy_data, rate_n_flags,
he, he_mu, rx_status);
break;
default:
/* nothing */
break;
}
} }
static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
...@@ -1039,8 +1123,8 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -1039,8 +1123,8 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
} }
if (he_phy_data != HE_PHY_DATA_INVAL) if (he_phy_data != HE_PHY_DATA_INVAL)
iwl_mvm_decode_he_phy_data(mvm, desc, he, he_mu, he_phy_data, iwl_mvm_decode_he_phy_data(mvm, desc, he, he_mu, rx_status,
rate_n_flags, queue); he_phy_data, rate_n_flags, queue);
/* update aggregation data for monitor sake on default queue */ /* update aggregation data for monitor sake on default queue */
if (!queue && (phy_info & IWL_RX_MPDU_PHY_AMPDU)) { if (!queue && (phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
...@@ -1064,84 +1148,12 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -1064,84 +1148,12 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
} }
if (he_phy_data != HE_PHY_DATA_INVAL && /* actually data is filled in mac80211 */
(FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data) == if (he_type == RATE_MCS_HE_TYPE_SU ||
IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO || he_type == RATE_MCS_HE_TYPE_EXT_SU)
FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data) ==
IWL_RX_HE_PHY_INFO_TYPE_TB_EXT_INFO)) {
/*
* Unfortunately, we have to leave the mac80211 data
* incorrect for the case that we receive an HE-MU
* transmission and *don't* have the HE phy data (due
* to the bits being used for TSF). This shouldn't
* happen though as management frames where we need
* the TSF/timers are not be transmitted in HE-MU.
*/
u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data);
u8 offs = 0;
rx_status->bw = RATE_INFO_BW_HE_RU;
he->data1 |= he->data1 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN); cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
switch (ru) {
case 0 ... 36:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
offs = ru;
break;
case 37 ... 52:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
offs = ru - 37;
break;
case 53 ... 60:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
offs = ru - 53;
break;
case 61 ... 64:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
offs = ru - 61;
break;
case 65 ... 66:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
offs = ru - 65;
break;
case 67:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
break;
case 68:
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
break;
}
he->data2 |=
le16_encode_bits(offs,
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
he->data2 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN |
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN);
if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80)
he->data2 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
if (he_mu) {
#define CHECK_BW(bw) \
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \
RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS)
CHECK_BW(20);
CHECK_BW(40);
CHECK_BW(80);
CHECK_BW(160);
he->data2 |=
le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
rate_n_flags),
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
}
} else if (he_type == RATE_MCS_HE_TYPE_SU ||
he_type == RATE_MCS_HE_TYPE_EXT_SU) {
he->data1 |=
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
}
stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS; stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS;
rx_status->nss = rx_status->nss =
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment