git: 654cffe59dd6 - main - LinuxKPI: 802.11: implement cfg80211_calculate_bitrate()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 31 Aug 2026 21:48:44 UTC
The branch main has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=654cffe59dd6c8818241bf44eff333af28e10168
commit 654cffe59dd6c8818241bf44eff333af28e10168
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-08-29 01:56:55 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-08-31 21:42:37 +0000
LinuxKPI: 802.11: implement cfg80211_calculate_bitrate()
lkpi_cfg80211_calculate_bitrate_vht() was constantly showing up
in my debug traces as a TODO with rtw89 so I went ahead and implemented
the HT and VHT versions. Realtek seems to limit amsdu sizes based
on the value and ask for it whether needed or not.
Sponsored by: The FreeBSD Foundation
MFC after: 3 days
---
sys/compat/linuxkpi/common/src/linux_80211.c | 109 ++++++++++++++++++++++++++-
1 file changed, 105 insertions(+), 4 deletions(-)
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index f1eef91af0da..ae0c374e2ea6 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -8845,15 +8845,116 @@ linuxkpi_80211_wiphy_register(struct wiphy *wiphy)
static uint32_t
lkpi_cfg80211_calculate_bitrate_ht(struct rate_info *rate)
{
- TODO("cfg80211_calculate_bitrate_ht");
- return (rate->legacy);
+ /*
+ * IEEE Std 802.11-2024, 19.5 Parameters for HT-MCSs;
+ * Tables Table 19-27-MCS NSS=1 800ns GI, and following.
+ * We use 100Kbit/s entries, the expacted return scale.
+ * We can calulate MCS0..31 entries.
+ */
+ uint32_t r;
+ uint8_t nss, mcsidx;
+
+ if (rate->mcs > 31)
+ goto inval;
+
+ switch (rate->bw) {
+ case RATE_INFO_BW_20:
+ r = 65;
+ break;
+ case RATE_INFO_BW_40:
+ r = 135;
+ break;
+ default:
+ goto inval;
+ /* NOTREACHED */
+ }
+
+ nss = (rate->mcs >> 3) + 1;
+ mcsidx = rate->mcs & 0x07;
+
+ switch (mcsidx) {
+ case 0 ... 3:
+ r *= (mcsidx + 1);
+ break;
+ case 4:
+ r *= (mcsidx + 2);
+ break;
+ case 5 ... 7:
+ r *= (mcsidx + 3);
+ break;
+ default:
+ goto inval;
+ /* NOTREACHED */
+ }
+ r *= nss;
+ if ((rate->flags & RATE_INFO_FLAGS_SHORT_GI) != 0)
+ r = (r * 10) / 9;
+
+ return (r);
+
+inval:
+ /* Do not warn every time or we get too much spam on console! */
+ WARN_ONCE(1, "%s: rate mcs %u nss %u mcsidx %u invalid!\n", __func__,
+ rate->mcs, nss, mcsidx);
+ return (0);
}
static uint32_t
lkpi_cfg80211_calculate_bitrate_vht(struct rate_info *rate)
{
- TODO("cfg80211_calculate_bitrate_vht");
- return (rate->legacy);
+ /*
+ * IEEE Std 802.11-2024, 21.5 Parameters for VHT-MCSs;
+ * Tables 21-29 NSS=1 800ns GI, and following.
+ * We use 100Kbit/s entries, the expacted return scale.
+ */
+ static const uint16_t datarate[4][10] = {
+ /* BW20 */
+ { 65, 130, 195, 260, 390, 520, 585, 650, 780, 0 },
+ /* BW40 */
+ { 135, 270, 405, 540, 810, 1080, 1215, 1350, 1620, 1800 },
+ /* BW80 */
+ { 293, 585, 878, 1170, 1755, 2340, 2633, 2925, 3510, 3900 },
+ /* BW160 */
+ { 585, 1170, 1755, 2340, 3510, 4680, 5265, 5850, 7020, 7800 }
+ };
+ uint32_t r;
+ uint8_t bwidx;
+
+ /* Should we warn about out of bounds values? */
+ if (rate->mcs > 9 || rate->nss > 8)
+ goto inval;
+
+ switch (rate->bw) {
+ case RATE_INFO_BW_20:
+ bwidx = 0;
+ break;
+ case RATE_INFO_BW_40:
+ bwidx = 1;
+ break;
+ case RATE_INFO_BW_80:
+ bwidx = 2;
+ break;
+ case RATE_INFO_BW_160:
+ bwidx = 2;
+ break;
+ default:
+ goto inval;
+ /* NOTREACHED */
+ }
+
+ r = datarate[bwidx][rate->mcs];
+ /* Calculate the other NSS tables and the SGI column. */
+ r *= rate->nss;
+ if ((rate->flags & RATE_INFO_FLAGS_SHORT_GI) != 0)
+ r = (r * 10) / 9;
+
+ return (r);
+
+inval:
+ /* Do not warn every time or we get too much spam on console! */
+ WARN_ONCE(1, "%s: rate mcs %u nss %u bw %d (%s) invalid!\n", __func__,
+ rate->mcs, rate->nss, rate->bw, lkpi_rate_info_bw_to_str(rate->bw));
+ return (0);
}
uint32_t