提交 5614618e 编写于 作者: J Johannes Berg

mac80211: support drivers reporting VHT RX

Add support to mac80211 for having drivers report
received VHT MCS information.
Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
上级 db9c64cf
...@@ -717,7 +717,11 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) ...@@ -717,7 +717,11 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* (including FCS) was received. * (including FCS) was received.
* @RX_FLAG_SHORTPRE: Short preamble was used for this frame * @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_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_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_SHORT_GI: Short guard interval was used
* @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present. * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
* Valid only for data frames (mainly A-MPDU) * Valid only for data frames (mainly A-MPDU)
...@@ -760,6 +764,10 @@ enum mac80211_rx_flags { ...@@ -760,6 +764,10 @@ enum mac80211_rx_flags {
RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19), RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19),
RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20), RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20),
RX_FLAG_MACTIME_END = BIT(21), 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 { ...@@ -780,7 +788,8 @@ enum mac80211_rx_flags {
* @IEEE80211_HW_SIGNAL_* * @IEEE80211_HW_SIGNAL_*
* @antenna: antenna used * @antenna: antenna used
* @rate_idx: index of data rate into band's supported rates or MCS index if * @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_* * @flag: %RX_FLAG_*
* @rx_flags: internal RX flags for mac80211 * @rx_flags: internal RX flags for mac80211
* @ampdu_reference: A-MPDU reference number, must be a different value for * @ampdu_reference: A-MPDU reference number, must be a different value for
...@@ -803,6 +812,7 @@ struct ieee80211_rx_status { ...@@ -803,6 +812,7 @@ struct ieee80211_rx_status {
u16 vendor_radiotap_len; u16 vendor_radiotap_len;
u16 freq; u16 freq;
u8 rate_idx; u8 rate_idx;
u8 vht_nss;
u8 rx_flags; u8 rx_flags;
u8 band; u8 band;
u8 antenna; u8 antenna;
......
...@@ -374,7 +374,8 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in ...@@ -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); 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; struct ieee80211_supported_band *sband;
sband = sta->local->hw.wiphy->bands[band]; sband = sta->local->hw.wiphy->bands[band];
rate->legacy = sband->bitrates[idx].bitrate; rate->legacy = sband->bitrates[idx].bitrate;
...@@ -444,13 +445,32 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) ...@@ -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); sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
sinfo->rxrate.flags = 0; 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.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) if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
sinfo->rxrate.flags |= RATE_INFO_FLAGS_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)) { if (ieee80211_vif_is_mesh(&sdata->vif)) {
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
......
...@@ -193,7 +193,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, ...@@ -193,7 +193,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
pos++; pos++;
/* IEEE80211_RADIOTAP_RATE */ /* 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, * Without rate information don't add it. If we have,
* MCS information is a separate field in radiotap, * MCS information is a separate field in radiotap,
...@@ -213,7 +213,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, ...@@ -213,7 +213,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
if (status->band == IEEE80211_BAND_5GHZ) if (status->band == IEEE80211_BAND_5GHZ)
put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
pos); 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, put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
pos); pos);
else if (rate && rate->flags & IEEE80211_RATE_ERP_G) else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
...@@ -1356,6 +1356,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ...@@ -1356,6 +1356,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (ieee80211_is_data(hdr->frame_control)) { if (ieee80211_is_data(hdr->frame_control)) {
sta->last_rx_rate_idx = status->rate_idx; sta->last_rx_rate_idx = status->rate_idx;
sta->last_rx_rate_flag = status->flag; sta->last_rx_rate_flag = status->flag;
sta->last_rx_rate_vht_nss = status->vht_nss;
} }
} }
} else if (!is_multicast_ether_addr(hdr->addr1)) { } else if (!is_multicast_ether_addr(hdr->addr1)) {
...@@ -1367,6 +1368,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ...@@ -1367,6 +1368,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (ieee80211_is_data(hdr->frame_control)) { if (ieee80211_is_data(hdr->frame_control)) {
sta->last_rx_rate_idx = status->rate_idx; sta->last_rx_rate_idx = status->rate_idx;
sta->last_rx_rate_flag = status->flag; 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, ...@@ -2710,7 +2712,8 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
status = IEEE80211_SKB_RXCB((rx->skb)); status = IEEE80211_SKB_RXCB((rx->skb));
sband = rx->local->hw.wiphy->bands[status->band]; 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]; rate = &sband->bitrates[status->rate_idx];
ieee80211_rx_cooked_monitor(rx, rate); ieee80211_rx_cooked_monitor(rx, rate);
...@@ -2877,8 +2880,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, ...@@ -2877,8 +2880,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
status->rx_flags &= ~IEEE80211_RX_RA_MATCH; status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!rx->sta) { } else if (!rx->sta) {
int rate_idx; int rate_idx;
if (status->flag & RX_FLAG_HT) if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
rate_idx = 0; /* TODO: HT rates */ rate_idx = 0; /* TODO: HT/VHT rates */
else else
rate_idx = status->rate_idx; rate_idx = status->rate_idx;
ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
...@@ -3154,6 +3157,13 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) ...@@ -3154,6 +3157,13 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
status->rate_idx, status->rate_idx,
status->rate_idx)) status->rate_idx))
goto drop; 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 { } else {
if (WARN_ON(status->rate_idx >= sband->n_bitrates)) if (WARN_ON(status->rate_idx >= sband->n_bitrates))
goto drop; goto drop;
......
...@@ -227,6 +227,7 @@ struct sta_ampdu_mlme { ...@@ -227,6 +227,7 @@ struct sta_ampdu_mlme {
* "the" transmit rate * "the" transmit rate
* @last_rx_rate_idx: rx status rate index of the last data packet * @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_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 * @lock: used for locking all fields that require locking, see comments
* in the header file. * in the header file.
* @drv_unblock_wk: used for driver PS unblocking * @drv_unblock_wk: used for driver PS unblocking
...@@ -343,7 +344,8 @@ struct sta_info { ...@@ -343,7 +344,8 @@ struct sta_info {
unsigned long tx_fragments; unsigned long tx_fragments;
struct ieee80211_tx_rate last_tx_rate; struct ieee80211_tx_rate last_tx_rate;
int last_rx_rate_idx; 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]; u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
/* /*
......
...@@ -2069,6 +2069,20 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, ...@@ -2069,6 +2069,20 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
if (status->flag & RX_FLAG_SHORT_GI) if (status->flag & RX_FLAG_SHORT_GI)
ri.flags |= RATE_INFO_FLAGS_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 { } else {
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册