Commit 8bc83c24 authored by Johannes Berg's avatar Johannes Berg

mac80211: support VHT rates in TX info

To achieve this, limit the number of retries to
31 (instead of 255) and use the three bits that
are then free for VHT flags.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 5614618e
...@@ -499,9 +499,14 @@ enum mac80211_tx_control_flags { ...@@ -499,9 +499,14 @@ enum mac80211_tx_control_flags {
* This is set if the current BSS requires ERP protection. * This is set if the current BSS requires ERP protection.
* @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble. * @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
* @IEEE80211_TX_RC_MCS: HT rate. * @IEEE80211_TX_RC_MCS: HT rate.
* @IEEE80211_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is split
* into a higher 4 bits (Nss) and lower 4 bits (MCS number)
* @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in * @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in
* Greenfield mode. * Greenfield mode.
* @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz. * @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz.
* @IEEE80211_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission
* @IEEE80211_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission
* (80+80 isn't supported yet)
* @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the * @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the
* adjacent 20 MHz channels, if the current channel type is * adjacent 20 MHz channels, if the current channel type is
* NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS. * NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
...@@ -512,12 +517,15 @@ enum mac80211_rate_control_flags { ...@@ -512,12 +517,15 @@ enum mac80211_rate_control_flags {
IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1),
IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
/* rate index is an MCS rate number instead of an index */ /* rate index is an HT/VHT MCS instead of an index */
IEEE80211_TX_RC_MCS = BIT(3), IEEE80211_TX_RC_MCS = BIT(3),
IEEE80211_TX_RC_GREEN_FIELD = BIT(4), IEEE80211_TX_RC_GREEN_FIELD = BIT(4),
IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5),
IEEE80211_TX_RC_DUP_DATA = BIT(6), IEEE80211_TX_RC_DUP_DATA = BIT(6),
IEEE80211_TX_RC_SHORT_GI = BIT(7), IEEE80211_TX_RC_SHORT_GI = BIT(7),
IEEE80211_TX_RC_VHT_MCS = BIT(8),
IEEE80211_TX_RC_80_MHZ_WIDTH = BIT(9),
IEEE80211_TX_RC_160_MHZ_WIDTH = BIT(10),
}; };
...@@ -560,10 +568,32 @@ enum mac80211_rate_control_flags { ...@@ -560,10 +568,32 @@ enum mac80211_rate_control_flags {
*/ */
struct ieee80211_tx_rate { struct ieee80211_tx_rate {
s8 idx; s8 idx;
u8 count; u16 count:5,
u8 flags; flags:11;
} __packed; } __packed;
#define IEEE80211_MAX_TX_RETRY 31
static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,
u8 mcs, u8 nss)
{
WARN_ON(mcs & ~0xF);
WARN_ON(nss & ~0x7);
rate->idx = (nss << 4) | mcs;
}
static inline u8
ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate)
{
return rate->idx & 0xF;
}
static inline u8
ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
{
return rate->idx >> 4;
}
/** /**
* struct ieee80211_tx_info - skb transmit information * struct ieee80211_tx_info - skb transmit information
* *
......
...@@ -370,31 +370,32 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, ...@@ -370,31 +370,32 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
return 0; return 0;
} }
static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx)
{
enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata);
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;
} else
rate->mcs = idx;
}
void sta_set_rate_info_tx(struct sta_info *sta, void sta_set_rate_info_tx(struct sta_info *sta,
const struct ieee80211_tx_rate *rate, const struct ieee80211_tx_rate *rate,
struct rate_info *rinfo) struct rate_info *rinfo)
{ {
rinfo->flags = 0; rinfo->flags = 0;
if (rate->flags & IEEE80211_TX_RC_MCS) if (rate->flags & IEEE80211_TX_RC_MCS) {
rinfo->flags |= RATE_INFO_FLAGS_MCS; rinfo->flags |= RATE_INFO_FLAGS_MCS;
rinfo->mcs = rate->idx;
} else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
rinfo->mcs = ieee80211_rate_get_vht_mcs(rate);
rinfo->nss = ieee80211_rate_get_vht_nss(rate);
} else {
struct ieee80211_supported_band *sband;
sband = sta->local->hw.wiphy->bands[
ieee80211_get_sdata_band(sta->sdata)];
rinfo->legacy = sband->bitrates[rate->idx].bitrate;
}
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
if (rate->flags & IEEE80211_TX_RC_SHORT_GI) if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
rate_idx_to_bitrate(rinfo, sta, rate->idx);
} }
static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
...@@ -2003,10 +2004,16 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ...@@ -2003,10 +2004,16 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return err; return err;
} }
if (changed & WIPHY_PARAM_RETRY_SHORT) if (changed & WIPHY_PARAM_RETRY_SHORT) {
if (wiphy->retry_short > IEEE80211_MAX_TX_RETRY)
return -EINVAL;
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
if (changed & WIPHY_PARAM_RETRY_LONG) }
if (changed & WIPHY_PARAM_RETRY_LONG) {
if (wiphy->retry_long > IEEE80211_MAX_TX_RETRY)
return -EINVAL;
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
}
if (changed & if (changed &
(WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
......
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