summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/wireless/nl80211.c23
-rw-r--r--net/wireless/util.c110
2 files changed, 133 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 772671b9bc42..f962765f7e0f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6368,12 +6368,27 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
return false;
switch (info->bw) {
+ case RATE_INFO_BW_1:
+ rate_flg = NL80211_RATE_INFO_1_MHZ_WIDTH;
+ break;
+ case RATE_INFO_BW_2:
+ rate_flg = NL80211_RATE_INFO_2_MHZ_WIDTH;
+ break;
+ case RATE_INFO_BW_4:
+ rate_flg = NL80211_RATE_INFO_4_MHZ_WIDTH;
+ break;
case RATE_INFO_BW_5:
rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
break;
+ case RATE_INFO_BW_8:
+ rate_flg = NL80211_RATE_INFO_8_MHZ_WIDTH;
+ break;
case RATE_INFO_BW_10:
rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
break;
+ case RATE_INFO_BW_16:
+ rate_flg = NL80211_RATE_INFO_16_MHZ_WIDTH;
+ break;
default:
WARN_ON(1);
fallthrough;
@@ -6432,6 +6447,14 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
info->he_ru_alloc))
return false;
+ } else if (info->flags & RATE_INFO_FLAGS_S1G_MCS) {
+ if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_MCS, info->mcs))
+ return false;
+ if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_NSS, info->nss))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
+ nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
+ return false;
} else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) {
if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs))
return false;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 3bc0c3072e78..610a867c14f7 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1646,6 +1646,114 @@ static u32 cfg80211_calculate_bitrate_eht(struct rate_info *rate)
return result / 10000;
}
+static u32 cfg80211_calculate_bitrate_s1g(struct rate_info *rate)
+{
+ /* For 1, 2, 4, 8 and 16 MHz channels */
+ static const u32 base[5][11] = {
+ { 300000,
+ 600000,
+ 900000,
+ 1200000,
+ 1800000,
+ 2400000,
+ 2700000,
+ 3000000,
+ 3600000,
+ 4000000,
+ /* MCS 10 supported in 1 MHz only */
+ 150000,
+ },
+ { 650000,
+ 1300000,
+ 1950000,
+ 2600000,
+ 3900000,
+ 5200000,
+ 5850000,
+ 6500000,
+ 7800000,
+ /* MCS 9 not valid */
+ },
+ { 1350000,
+ 2700000,
+ 4050000,
+ 5400000,
+ 8100000,
+ 10800000,
+ 12150000,
+ 13500000,
+ 16200000,
+ 18000000,
+ },
+ { 2925000,
+ 5850000,
+ 8775000,
+ 11700000,
+ 17550000,
+ 23400000,
+ 26325000,
+ 29250000,
+ 35100000,
+ 39000000,
+ },
+ { 8580000,
+ 11700000,
+ 17550000,
+ 23400000,
+ 35100000,
+ 46800000,
+ 52650000,
+ 58500000,
+ 70200000,
+ 78000000,
+ },
+ };
+ u32 bitrate;
+ /* default is 1 MHz index */
+ int idx = 0;
+
+ if (rate->mcs >= 11)
+ goto warn;
+
+ switch (rate->bw) {
+ case RATE_INFO_BW_16:
+ idx = 4;
+ break;
+ case RATE_INFO_BW_8:
+ idx = 3;
+ break;
+ case RATE_INFO_BW_4:
+ idx = 2;
+ break;
+ case RATE_INFO_BW_2:
+ idx = 1;
+ break;
+ case RATE_INFO_BW_1:
+ idx = 0;
+ break;
+ case RATE_INFO_BW_5:
+ case RATE_INFO_BW_10:
+ case RATE_INFO_BW_20:
+ case RATE_INFO_BW_40:
+ case RATE_INFO_BW_80:
+ case RATE_INFO_BW_160:
+ default:
+ goto warn;
+ }
+
+ bitrate = base[idx][rate->mcs];
+ bitrate *= rate->nss;
+
+ if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+ bitrate = (bitrate / 9) * 10;
+ /* do NOT round down here */
+ return (bitrate + 50000) / 100000;
+warn:
+ WARN_ONCE(1, "invalid rate bw=%d, mcs=%d, nss=%d\n",
+ rate->bw, rate->mcs, rate->nss);
+ return 0;
+}
+
u32 cfg80211_calculate_bitrate(struct rate_info *rate)
{
if (rate->flags & RATE_INFO_FLAGS_MCS)
@@ -1662,6 +1770,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
return cfg80211_calculate_bitrate_he(rate);
if (rate->flags & RATE_INFO_FLAGS_EHT_MCS)
return cfg80211_calculate_bitrate_eht(rate);
+ if (rate->flags & RATE_INFO_FLAGS_S1G_MCS)
+ return cfg80211_calculate_bitrate_s1g(rate);
return rate->legacy;
}