Commit 8eb41c8d authored by Vladimir Kondratiev's avatar Vladimir Kondratiev Committed by Johannes Berg

{nl,cfg}80211: support high bitrates

Until now, a u16 value was used to represent bitrate value.
With VHT bitrates this becomes too small.

Introduce a new 32-bit bitrate attribute. nl80211 will report
both the new and the old attribute, unless the bitrate doesn't
fit into the old u16 attribute in which case only the new one
will be reported.

User space tools encouraged to prefer the 32-bit attribute, if
available (since it won't be available on older kernels.)
Signed-off-by: default avatarVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
[reword commit message and comments a bit]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c5a7e582
...@@ -1638,12 +1638,20 @@ struct nl80211_sta_flag_update { ...@@ -1638,12 +1638,20 @@ struct nl80211_sta_flag_update {
* *
* These attribute types are used with %NL80211_STA_INFO_TXRATE * These attribute types are used with %NL80211_STA_INFO_TXRATE
* when getting information about the bitrate of a station. * when getting information about the bitrate of a station.
* There are 2 attributes for bitrate, a legacy one that represents
* a 16-bit value, and new one that represents a 32-bit value.
* If the rate value fits into 16 bit, both attributes are reported
* with the same value. If the rate is too high to fit into 16 bits
* (>6.5535Gbps) only 32-bit attribute is included.
* User space tools encouraged to use the 32-bit attribute and fall
* back to the 16-bit one for compatibility with older kernels.
* *
* @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
* @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
* @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
* @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
* @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
* @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s)
* @NL80211_RATE_INFO_MAX: highest rate_info number currently defined * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
* @__NL80211_RATE_INFO_AFTER_LAST: internal use * @__NL80211_RATE_INFO_AFTER_LAST: internal use
*/ */
...@@ -1653,6 +1661,7 @@ enum nl80211_rate_info { ...@@ -1653,6 +1661,7 @@ enum nl80211_rate_info {
NL80211_RATE_INFO_MCS, NL80211_RATE_INFO_MCS,
NL80211_RATE_INFO_40_MHZ_WIDTH, NL80211_RATE_INFO_40_MHZ_WIDTH,
NL80211_RATE_INFO_SHORT_GI, NL80211_RATE_INFO_SHORT_GI,
NL80211_RATE_INFO_BITRATE32,
/* keep last */ /* keep last */
__NL80211_RATE_INFO_AFTER_LAST, __NL80211_RATE_INFO_AFTER_LAST,
......
...@@ -3487,7 +3487,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq, ...@@ -3487,7 +3487,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
* *
* return 0 if MCS index >= 32 * return 0 if MCS index >= 32
*/ */
u16 cfg80211_calculate_bitrate(struct rate_info *rate); u32 cfg80211_calculate_bitrate(struct rate_info *rate);
/* Logging, debugging and troubleshooting/diagnostic helpers. */ /* Logging, debugging and troubleshooting/diagnostic helpers. */
......
...@@ -2618,7 +2618,8 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, ...@@ -2618,7 +2618,8 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
int attr) int attr)
{ {
struct nlattr *rate; struct nlattr *rate;
u16 bitrate; u32 bitrate;
u16 bitrate_compat;
rate = nla_nest_start(msg, attr); rate = nla_nest_start(msg, attr);
if (!rate) if (!rate)
...@@ -2626,8 +2627,12 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, ...@@ -2626,8 +2627,12 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
bitrate = cfg80211_calculate_bitrate(info); bitrate = cfg80211_calculate_bitrate(info);
/* report 16-bit bitrate only if we can */
bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
if ((bitrate > 0 && if ((bitrate > 0 &&
nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate)) || nla_put_u32(msg, NL80211_RATE_INFO_BITRATE32, bitrate)) ||
(bitrate_compat > 0 &&
nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) ||
((info->flags & RATE_INFO_FLAGS_MCS) && ((info->flags & RATE_INFO_FLAGS_MCS) &&
nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) || nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) ||
((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) && ((info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) &&
......
...@@ -900,7 +900,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, ...@@ -900,7 +900,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
return err; return err;
} }
u16 cfg80211_calculate_bitrate(struct rate_info *rate) u32 cfg80211_calculate_bitrate(struct rate_info *rate)
{ {
int modulation, streams, bitrate; int modulation, streams, bitrate;
......
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