Skip to content

Commit

Permalink
mac80211: support drivers reporting VHT RX
Browse files Browse the repository at this point in the history
Add support to mac80211 for having drivers report
received VHT MCS information.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Johannes Berg committed Nov 26, 2012
1 parent db9c64c commit 5614618
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 10 deletions.
12 changes: 11 additions & 1 deletion include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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),
};

/**
Expand All @@ -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
Expand All @@ -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;
Expand Down
26 changes: 23 additions & 3 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
20 changes: 15 additions & 5 deletions net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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)) {
Expand All @@ -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;
}
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion net/mac80211/sta_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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];

/*
Expand Down
14 changes: 14 additions & 0 deletions net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 5614618

Please sign in to comment.