mac80211: support drivers reporting VHT RX
Add support to mac80211 for having drivers report received VHT MCS information. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
db9c64cf8d
commit
5614618ec4
|
@ -717,7 +717,11 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
|
|||
* (including FCS) was received.
|
||||
* @RX_FLAG_SHORTPRE: Short preamble was used for this frame
|
||||
* @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
|
||||
* @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index
|
||||
* @RX_FLAG_40MHZ: HT40 (40 MHz) was used
|
||||
* @RX_FLAG_80MHZ: 80 MHz was used
|
||||
* @RX_FLAG_80P80MHZ: 80+80 MHz was used
|
||||
* @RX_FLAG_160MHZ: 160 MHz was used
|
||||
* @RX_FLAG_SHORT_GI: Short guard interval was used
|
||||
* @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
|
||||
* Valid only for data frames (mainly A-MPDU)
|
||||
|
@ -760,6 +764,10 @@ enum mac80211_rx_flags {
|
|||
RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19),
|
||||
RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20),
|
||||
RX_FLAG_MACTIME_END = BIT(21),
|
||||
RX_FLAG_VHT = BIT(22),
|
||||
RX_FLAG_80MHZ = BIT(23),
|
||||
RX_FLAG_80P80MHZ = BIT(24),
|
||||
RX_FLAG_160MHZ = BIT(25),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -780,7 +788,8 @@ enum mac80211_rx_flags {
|
|||
* @IEEE80211_HW_SIGNAL_*
|
||||
* @antenna: antenna used
|
||||
* @rate_idx: index of data rate into band's supported rates or MCS index if
|
||||
* HT rates are use (RX_FLAG_HT)
|
||||
* HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
|
||||
* @vht_nss: number of streams (VHT only)
|
||||
* @flag: %RX_FLAG_*
|
||||
* @rx_flags: internal RX flags for mac80211
|
||||
* @ampdu_reference: A-MPDU reference number, must be a different value for
|
||||
|
@ -803,6 +812,7 @@ struct ieee80211_rx_status {
|
|||
u16 vendor_radiotap_len;
|
||||
u16 freq;
|
||||
u8 rate_idx;
|
||||
u8 vht_nss;
|
||||
u8 rx_flags;
|
||||
u8 band;
|
||||
u8 antenna;
|
||||
|
|
|
@ -374,7 +374,8 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in
|
|||
{
|
||||
enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata);
|
||||
|
||||
if (!(rate->flags & RATE_INFO_FLAGS_MCS)) {
|
||||
if (!(rate->flags & RATE_INFO_FLAGS_MCS) &&
|
||||
!(rate->flags & RATE_INFO_FLAGS_VHT_MCS)) {
|
||||
struct ieee80211_supported_band *sband;
|
||||
sband = sta->local->hw.wiphy->bands[band];
|
||||
rate->legacy = sband->bitrates[idx].bitrate;
|
||||
|
@ -444,13 +445,32 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
|
||||
|
||||
sinfo->rxrate.flags = 0;
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_HT)
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_HT) {
|
||||
sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS;
|
||||
sinfo->rxrate.mcs = sta->last_rx_rate_idx;
|
||||
} else if (sta->last_rx_rate_flag & RX_FLAG_VHT) {
|
||||
sinfo->rxrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
sinfo->rxrate.nss = sta->last_rx_rate_vht_nss;
|
||||
sinfo->rxrate.mcs = sta->last_rx_rate_idx;
|
||||
} else {
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
sband = sta->local->hw.wiphy->bands[
|
||||
ieee80211_get_sdata_band(sta->sdata)];
|
||||
sinfo->rxrate.legacy =
|
||||
sband->bitrates[sta->last_rx_rate_idx].bitrate;
|
||||
}
|
||||
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
|
||||
sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
|
||||
sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx);
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_80MHZ)
|
||||
sinfo->rxrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ)
|
||||
sinfo->rxrate.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
|
||||
if (sta->last_rx_rate_flag & RX_FLAG_160MHZ)
|
||||
sinfo->rxrate.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
|
|
|
@ -193,7 +193,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
pos++;
|
||||
|
||||
/* IEEE80211_RADIOTAP_RATE */
|
||||
if (!rate || status->flag & RX_FLAG_HT) {
|
||||
if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) {
|
||||
/*
|
||||
* Without rate information don't add it. If we have,
|
||||
* MCS information is a separate field in radiotap,
|
||||
|
@ -213,7 +213,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
if (status->band == IEEE80211_BAND_5GHZ)
|
||||
put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
|
||||
pos);
|
||||
else if (status->flag & RX_FLAG_HT)
|
||||
else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
|
||||
put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
|
||||
pos);
|
||||
else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
|
||||
|
@ -1356,6 +1356,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||
if (ieee80211_is_data(hdr->frame_control)) {
|
||||
sta->last_rx_rate_idx = status->rate_idx;
|
||||
sta->last_rx_rate_flag = status->flag;
|
||||
sta->last_rx_rate_vht_nss = status->vht_nss;
|
||||
}
|
||||
}
|
||||
} else if (!is_multicast_ether_addr(hdr->addr1)) {
|
||||
|
@ -1367,6 +1368,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||
if (ieee80211_is_data(hdr->frame_control)) {
|
||||
sta->last_rx_rate_idx = status->rate_idx;
|
||||
sta->last_rx_rate_flag = status->flag;
|
||||
sta->last_rx_rate_vht_nss = status->vht_nss;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2710,7 +2712,8 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
|
|||
status = IEEE80211_SKB_RXCB((rx->skb));
|
||||
|
||||
sband = rx->local->hw.wiphy->bands[status->band];
|
||||
if (!(status->flag & RX_FLAG_HT))
|
||||
if (!(status->flag & RX_FLAG_HT) &&
|
||||
!(status->flag & RX_FLAG_VHT))
|
||||
rate = &sband->bitrates[status->rate_idx];
|
||||
|
||||
ieee80211_rx_cooked_monitor(rx, rate);
|
||||
|
@ -2877,8 +2880,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|||
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
||||
} else if (!rx->sta) {
|
||||
int rate_idx;
|
||||
if (status->flag & RX_FLAG_HT)
|
||||
rate_idx = 0; /* TODO: HT rates */
|
||||
if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
|
||||
rate_idx = 0; /* TODO: HT/VHT rates */
|
||||
else
|
||||
rate_idx = status->rate_idx;
|
||||
ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
|
||||
|
@ -3154,6 +3157,13 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
status->rate_idx,
|
||||
status->rate_idx))
|
||||
goto drop;
|
||||
} else if (status->flag & RX_FLAG_VHT) {
|
||||
if (WARN_ONCE(status->rate_idx > 9 ||
|
||||
!status->vht_nss ||
|
||||
status->vht_nss > 8,
|
||||
"Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n",
|
||||
status->rate_idx, status->vht_nss))
|
||||
goto drop;
|
||||
} else {
|
||||
if (WARN_ON(status->rate_idx >= sband->n_bitrates))
|
||||
goto drop;
|
||||
|
|
|
@ -227,6 +227,7 @@ struct sta_ampdu_mlme {
|
|||
* "the" transmit rate
|
||||
* @last_rx_rate_idx: rx status rate index of the last data packet
|
||||
* @last_rx_rate_flag: rx status flag of the last data packet
|
||||
* @last_rx_rate_vht_nss: rx status nss of last data packet
|
||||
* @lock: used for locking all fields that require locking, see comments
|
||||
* in the header file.
|
||||
* @drv_unblock_wk: used for driver PS unblocking
|
||||
|
@ -343,7 +344,8 @@ struct sta_info {
|
|||
unsigned long tx_fragments;
|
||||
struct ieee80211_tx_rate last_tx_rate;
|
||||
int last_rx_rate_idx;
|
||||
int last_rx_rate_flag;
|
||||
u32 last_rx_rate_flag;
|
||||
u8 last_rx_rate_vht_nss;
|
||||
u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
|
||||
|
||||
/*
|
||||
|
|
|
@ -2069,6 +2069,20 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
|||
ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
|
||||
if (status->flag & RX_FLAG_SHORT_GI)
|
||||
ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
} else if (status->flag & RX_FLAG_VHT) {
|
||||
ri.flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
ri.mcs = status->rate_idx;
|
||||
ri.nss = status->vht_nss;
|
||||
if (status->flag & RX_FLAG_40MHZ)
|
||||
ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
|
||||
if (status->flag & RX_FLAG_80MHZ)
|
||||
ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
|
||||
if (status->flag & RX_FLAG_80P80MHZ)
|
||||
ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
|
||||
if (status->flag & RX_FLAG_160MHZ)
|
||||
ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
|
||||
if (status->flag & RX_FLAG_SHORT_GI)
|
||||
ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
} else {
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
|
|
Loading…
Reference in a new issue