Commit 2ad66fcb authored by Gilad Itzkovitch's avatar Gilad Itzkovitch Committed by Johannes Berg

wifi: cfg80211: S1G rate information and calculations

Increase the size of S1G rate_info flags to support S1G and add
flags for new S1G MCS and the supported bandwidths. Also, include
S1G rate information to netlink STA rate message. Lastly, add
rate calculation function for S1G MCS.
Signed-off-by: default avatarGilad Itzkovitch <gilad.itzkovitch@morsemicro.com>
Link: https://lore.kernel.org/r/20230518000723.991912-1-gilad.itzkovitch@morsemicro.comSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 91ccdbb9
...@@ -1702,6 +1702,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy, ...@@ -1702,6 +1702,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
* @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode
* @RATE_INFO_FLAGS_EXTENDED_SC_DMG: 60GHz extended SC MCS * @RATE_INFO_FLAGS_EXTENDED_SC_DMG: 60GHz extended SC MCS
* @RATE_INFO_FLAGS_EHT_MCS: EHT MCS information * @RATE_INFO_FLAGS_EHT_MCS: EHT MCS information
* @RATE_INFO_FLAGS_S1G_MCS: MCS field filled with S1G MCS
*/ */
enum rate_info_flags { enum rate_info_flags {
RATE_INFO_FLAGS_MCS = BIT(0), RATE_INFO_FLAGS_MCS = BIT(0),
...@@ -1712,6 +1713,7 @@ enum rate_info_flags { ...@@ -1712,6 +1713,7 @@ enum rate_info_flags {
RATE_INFO_FLAGS_EDMG = BIT(5), RATE_INFO_FLAGS_EDMG = BIT(5),
RATE_INFO_FLAGS_EXTENDED_SC_DMG = BIT(6), RATE_INFO_FLAGS_EXTENDED_SC_DMG = BIT(6),
RATE_INFO_FLAGS_EHT_MCS = BIT(7), RATE_INFO_FLAGS_EHT_MCS = BIT(7),
RATE_INFO_FLAGS_S1G_MCS = BIT(8),
}; };
/** /**
...@@ -1728,6 +1730,11 @@ enum rate_info_flags { ...@@ -1728,6 +1730,11 @@ enum rate_info_flags {
* @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation * @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation
* @RATE_INFO_BW_320: 320 MHz bandwidth * @RATE_INFO_BW_320: 320 MHz bandwidth
* @RATE_INFO_BW_EHT_RU: bandwidth determined by EHT RU allocation * @RATE_INFO_BW_EHT_RU: bandwidth determined by EHT RU allocation
* @RATE_INFO_BW_1: 1 MHz bandwidth
* @RATE_INFO_BW_2: 2 MHz bandwidth
* @RATE_INFO_BW_4: 4 MHz bandwidth
* @RATE_INFO_BW_8: 8 MHz bandwidth
* @RATE_INFO_BW_16: 16 MHz bandwidth
*/ */
enum rate_info_bw { enum rate_info_bw {
RATE_INFO_BW_20 = 0, RATE_INFO_BW_20 = 0,
...@@ -1739,6 +1746,11 @@ enum rate_info_bw { ...@@ -1739,6 +1746,11 @@ enum rate_info_bw {
RATE_INFO_BW_HE_RU, RATE_INFO_BW_HE_RU,
RATE_INFO_BW_320, RATE_INFO_BW_320,
RATE_INFO_BW_EHT_RU, RATE_INFO_BW_EHT_RU,
RATE_INFO_BW_1,
RATE_INFO_BW_2,
RATE_INFO_BW_4,
RATE_INFO_BW_8,
RATE_INFO_BW_16,
}; };
/** /**
...@@ -1747,8 +1759,8 @@ enum rate_info_bw { ...@@ -1747,8 +1759,8 @@ enum rate_info_bw {
* Information about a receiving or transmitting bitrate * Information about a receiving or transmitting bitrate
* *
* @flags: bitflag of flags from &enum rate_info_flags * @flags: bitflag of flags from &enum rate_info_flags
* @mcs: mcs index if struct describes an HT/VHT/HE rate
* @legacy: bitrate in 100kbit/s for 802.11abg * @legacy: bitrate in 100kbit/s for 802.11abg
* @mcs: mcs index if struct describes an HT/VHT/HE/EHT/S1G rate
* @nss: number of streams (VHT & HE only) * @nss: number of streams (VHT & HE only)
* @bw: bandwidth (from &enum rate_info_bw) * @bw: bandwidth (from &enum rate_info_bw)
* @he_gi: HE guard interval (from &enum nl80211_he_gi) * @he_gi: HE guard interval (from &enum nl80211_he_gi)
...@@ -1761,9 +1773,9 @@ enum rate_info_bw { ...@@ -1761,9 +1773,9 @@ enum rate_info_bw {
* only valid if bw is %RATE_INFO_BW_EHT_RU) * only valid if bw is %RATE_INFO_BW_EHT_RU)
*/ */
struct rate_info { struct rate_info {
u8 flags; u16 flags;
u8 mcs;
u16 legacy; u16 legacy;
u8 mcs;
u8 nss; u8 nss;
u8 bw; u8 bw;
u8 he_gi; u8 he_gi;
......
...@@ -3667,6 +3667,13 @@ enum nl80211_eht_ru_alloc { ...@@ -3667,6 +3667,13 @@ enum nl80211_eht_ru_alloc {
* (u8, see &enum nl80211_eht_gi) * (u8, see &enum nl80211_eht_gi)
* @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then * @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then
* non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc) * non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc)
* @NL80211_RATE_INFO_S1G_MCS: S1G MCS index (u8, 0-10)
* @NL80211_RATE_INFO_S1G_NSS: S1G NSS value (u8, 1-4)
* @NL80211_RATE_INFO_1_MHZ_WIDTH: 1 MHz S1G rate
* @NL80211_RATE_INFO_2_MHZ_WIDTH: 2 MHz S1G rate
* @NL80211_RATE_INFO_4_MHZ_WIDTH: 4 MHz S1G rate
* @NL80211_RATE_INFO_8_MHZ_WIDTH: 8 MHz S1G rate
* @NL80211_RATE_INFO_16_MHZ_WIDTH: 16 MHz S1G rate
* @__NL80211_RATE_INFO_AFTER_LAST: internal use * @__NL80211_RATE_INFO_AFTER_LAST: internal use
*/ */
enum nl80211_rate_info { enum nl80211_rate_info {
...@@ -3693,6 +3700,13 @@ enum nl80211_rate_info { ...@@ -3693,6 +3700,13 @@ enum nl80211_rate_info {
NL80211_RATE_INFO_EHT_NSS, NL80211_RATE_INFO_EHT_NSS,
NL80211_RATE_INFO_EHT_GI, NL80211_RATE_INFO_EHT_GI,
NL80211_RATE_INFO_EHT_RU_ALLOC, NL80211_RATE_INFO_EHT_RU_ALLOC,
NL80211_RATE_INFO_S1G_MCS,
NL80211_RATE_INFO_S1G_NSS,
NL80211_RATE_INFO_1_MHZ_WIDTH,
NL80211_RATE_INFO_2_MHZ_WIDTH,
NL80211_RATE_INFO_4_MHZ_WIDTH,
NL80211_RATE_INFO_8_MHZ_WIDTH,
NL80211_RATE_INFO_16_MHZ_WIDTH,
/* keep last */ /* keep last */
__NL80211_RATE_INFO_AFTER_LAST, __NL80211_RATE_INFO_AFTER_LAST,
......
...@@ -6368,12 +6368,27 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr) ...@@ -6368,12 +6368,27 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
return false; return false;
switch (info->bw) { 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: case RATE_INFO_BW_5:
rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH; rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
break; break;
case RATE_INFO_BW_8:
rate_flg = NL80211_RATE_INFO_8_MHZ_WIDTH;
break;
case RATE_INFO_BW_10: case RATE_INFO_BW_10:
rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH; rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
break; break;
case RATE_INFO_BW_16:
rate_flg = NL80211_RATE_INFO_16_MHZ_WIDTH;
break;
default: default:
WARN_ON(1); WARN_ON(1);
fallthrough; fallthrough;
...@@ -6432,6 +6447,14 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr) ...@@ -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, nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
info->he_ru_alloc)) info->he_ru_alloc))
return false; 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) { } else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) {
if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs)) if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs))
return false; return false;
......
...@@ -1646,6 +1646,114 @@ static u32 cfg80211_calculate_bitrate_eht(struct rate_info *rate) ...@@ -1646,6 +1646,114 @@ static u32 cfg80211_calculate_bitrate_eht(struct rate_info *rate)
return result / 10000; 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) u32 cfg80211_calculate_bitrate(struct rate_info *rate)
{ {
if (rate->flags & RATE_INFO_FLAGS_MCS) if (rate->flags & RATE_INFO_FLAGS_MCS)
...@@ -1662,6 +1770,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate) ...@@ -1662,6 +1770,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
return cfg80211_calculate_bitrate_he(rate); return cfg80211_calculate_bitrate_he(rate);
if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) if (rate->flags & RATE_INFO_FLAGS_EHT_MCS)
return cfg80211_calculate_bitrate_eht(rate); return cfg80211_calculate_bitrate_eht(rate);
if (rate->flags & RATE_INFO_FLAGS_S1G_MCS)
return cfg80211_calculate_bitrate_s1g(rate);
return rate->legacy; return rate->legacy;
} }
......
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