developer | 05f3b2b | 2024-08-19 19:17:34 +0800 | [diff] [blame^] | 1 | From 06c0ba03cc9ed39bee42b10a1e22f9aceeb57ecd Mon Sep 17 00:00:00 2001 |
| 2 | From: Benjamin Lin <benjamin-jw.lin@mediatek.com> |
| 3 | Date: Fri, 7 Jun 2024 10:44:45 +0800 |
| 4 | Subject: [PATCH 153/199] mtk: mt76: mt7996: update TX/RX rates via MCU command |
| 5 | |
| 6 | Update TX/RX rates via MCU command to address following issues: |
| 7 | 1. TX rate was originally updated via TXS. However in MLO connection, WCID from TXS may not represent the actually used link. |
| 8 | 2. RX rate was originally updated via RXD. However, there is no RXD when HW path is taken. |
| 9 | |
| 10 | Original TX-rate update via TXS is removed. |
| 11 | Still, RX-rate update via RXD is not removed, because mac80211 requires driver to provide such information for each received frame. |
| 12 | |
| 13 | Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com> |
| 14 | --- |
| 15 | mt76.h | 1 + |
| 16 | mt7996/mac.c | 117 ++++++---------------------------------- |
| 17 | mt7996/main.c | 28 ++++------ |
| 18 | mt7996/mcu.c | 146 +++++++++++++++++++++++++++++++++++++++++++++----- |
| 19 | 4 files changed, 161 insertions(+), 131 deletions(-) |
| 20 | |
| 21 | diff --git a/mt76.h b/mt76.h |
| 22 | index f544814e..a0fc8b1a 100644 |
| 23 | --- a/mt76.h |
| 24 | +++ b/mt76.h |
| 25 | @@ -370,6 +370,7 @@ struct mt76_wcid { |
| 26 | int inactive_count; |
| 27 | |
| 28 | struct rate_info rate; |
| 29 | + struct rate_info rx_rate; |
| 30 | unsigned long ampdu_state; |
| 31 | |
| 32 | u16 idx; |
| 33 | diff --git a/mt7996/mac.c b/mt7996/mac.c |
| 34 | index 020203ec..484b679b 100644 |
| 35 | --- a/mt7996/mac.c |
| 36 | +++ b/mt7996/mac.c |
| 37 | @@ -1242,15 +1242,12 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, |
| 38 | int pid, __le32 *txs_data) |
| 39 | { |
| 40 | struct mt76_sta_stats *stats = &wcid->stats; |
| 41 | - struct ieee80211_supported_band *sband; |
| 42 | struct mt76_dev *mdev = &dev->mt76; |
| 43 | - struct mt76_phy *mphy; |
| 44 | struct ieee80211_tx_info *info; |
| 45 | struct sk_buff_head list; |
| 46 | - struct rate_info rate = {}; |
| 47 | struct sk_buff *skb = NULL; |
| 48 | - bool cck = false; |
| 49 | - u32 txrate, txs, mode, stbc; |
| 50 | + u32 txrate, txs; |
| 51 | + u8 mode, bw, mcs, nss; |
| 52 | |
| 53 | txs = le32_to_cpu(txs_data[0]); |
| 54 | |
| 55 | @@ -1298,105 +1295,23 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, |
| 56 | } |
| 57 | |
| 58 | txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); |
| 59 | - |
| 60 | - rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); |
| 61 | - rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; |
| 62 | - stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC); |
| 63 | - |
| 64 | - if (stbc && rate.nss > 1) |
| 65 | - rate.nss >>= 1; |
| 66 | - |
| 67 | - if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) |
| 68 | - stats->tx_nss[rate.nss - 1]++; |
| 69 | - if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) |
| 70 | - stats->tx_mcs[rate.mcs]++; |
| 71 | + bw = FIELD_GET(MT_TXS0_BW, txs); |
| 72 | |
| 73 | mode = FIELD_GET(MT_TX_RATE_MODE, txrate); |
| 74 | - switch (mode) { |
| 75 | - case MT_PHY_TYPE_CCK: |
| 76 | - cck = true; |
| 77 | - fallthrough; |
| 78 | - case MT_PHY_TYPE_OFDM: |
| 79 | - mphy = mt76_dev_phy(mdev, wcid->phy_idx); |
| 80 | - |
| 81 | - if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) |
| 82 | - sband = &mphy->sband_5g.sband; |
| 83 | - else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) |
| 84 | - sband = &mphy->sband_6g.sband; |
| 85 | - else |
| 86 | - sband = &mphy->sband_2g.sband; |
| 87 | - |
| 88 | - rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck); |
| 89 | - rate.legacy = sband->bitrates[rate.mcs].bitrate; |
| 90 | - break; |
| 91 | - case MT_PHY_TYPE_HT: |
| 92 | - case MT_PHY_TYPE_HT_GF: |
| 93 | - if (rate.mcs > 31) |
| 94 | - goto out; |
| 95 | - |
| 96 | - rate.flags = RATE_INFO_FLAGS_MCS; |
| 97 | - if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) |
| 98 | - rate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 99 | - break; |
| 100 | - case MT_PHY_TYPE_VHT: |
| 101 | - if (rate.mcs > 9) |
| 102 | - goto out; |
| 103 | - |
| 104 | - rate.flags = RATE_INFO_FLAGS_VHT_MCS; |
| 105 | - if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) |
| 106 | - rate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 107 | - break; |
| 108 | - case MT_PHY_TYPE_HE_SU: |
| 109 | - case MT_PHY_TYPE_HE_EXT_SU: |
| 110 | - case MT_PHY_TYPE_HE_TB: |
| 111 | - case MT_PHY_TYPE_HE_MU: |
| 112 | - if (rate.mcs > 11) |
| 113 | - goto out; |
| 114 | - |
| 115 | - rate.he_gi = wcid->rate.he_gi; |
| 116 | - rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); |
| 117 | - rate.flags = RATE_INFO_FLAGS_HE_MCS; |
| 118 | - break; |
| 119 | - case MT_PHY_TYPE_EHT_SU: |
| 120 | - case MT_PHY_TYPE_EHT_TRIG: |
| 121 | - case MT_PHY_TYPE_EHT_MU: |
| 122 | - if (rate.mcs > 13) |
| 123 | - goto out; |
| 124 | - |
| 125 | - rate.eht_gi = wcid->rate.eht_gi; |
| 126 | - rate.flags = RATE_INFO_FLAGS_EHT_MCS; |
| 127 | - break; |
| 128 | - default: |
| 129 | - goto out; |
| 130 | - } |
| 131 | - |
| 132 | - stats->tx_mode[mode]++; |
| 133 | + mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); |
| 134 | + nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; |
| 135 | + if (le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC) && nss > 1) |
| 136 | + nss >>= 1; |
| 137 | + |
| 138 | + if (nss - 1 < ARRAY_SIZE(stats->tx_nss)) |
| 139 | + stats->tx_nss[nss - 1]++; |
| 140 | + if (mcs < ARRAY_SIZE(stats->tx_mcs)) |
| 141 | + stats->tx_mcs[mcs]++; |
| 142 | + if (mode < ARRAY_SIZE(stats->tx_mode)) |
| 143 | + stats->tx_mode[mode]++; |
| 144 | + if (bw < ARRAY_SIZE(stats->tx_bw)) |
| 145 | + stats->tx_bw[bw]++; |
| 146 | |
| 147 | - switch (FIELD_GET(MT_TXS0_BW, txs)) { |
| 148 | - case IEEE80211_STA_RX_BW_320: |
| 149 | - rate.bw = RATE_INFO_BW_320; |
| 150 | - stats->tx_bw[4]++; |
| 151 | - break; |
| 152 | - case IEEE80211_STA_RX_BW_160: |
| 153 | - rate.bw = RATE_INFO_BW_160; |
| 154 | - stats->tx_bw[3]++; |
| 155 | - break; |
| 156 | - case IEEE80211_STA_RX_BW_80: |
| 157 | - rate.bw = RATE_INFO_BW_80; |
| 158 | - stats->tx_bw[2]++; |
| 159 | - break; |
| 160 | - case IEEE80211_STA_RX_BW_40: |
| 161 | - rate.bw = RATE_INFO_BW_40; |
| 162 | - stats->tx_bw[1]++; |
| 163 | - break; |
| 164 | - default: |
| 165 | - rate.bw = RATE_INFO_BW_20; |
| 166 | - stats->tx_bw[0]++; |
| 167 | - break; |
| 168 | - } |
| 169 | - wcid->rate = rate; |
| 170 | - |
| 171 | -out: |
| 172 | if (skb) |
| 173 | mt76_tx_status_skb_done(mdev, skb, &list); |
| 174 | mt76_tx_status_unlock(mdev, &list); |
| 175 | diff --git a/mt7996/main.c b/mt7996/main.c |
| 176 | index 19a1c7b3..fa60b889 100644 |
| 177 | --- a/mt7996/main.c |
| 178 | +++ b/mt7996/main.c |
| 179 | @@ -1765,32 +1765,24 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw, |
| 180 | struct mt7996_phy *phy = mt7996_hw_phy(hw); |
| 181 | struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; |
| 182 | struct mt7996_link_sta *mlink; |
| 183 | - struct rate_info *txrate; |
| 184 | + struct rate_info *rate; |
| 185 | |
| 186 | - /* TODO: support per-link rate report */ |
| 187 | mutex_lock(&dev->mt76.mutex); |
| 188 | mlink = mlink_dereference_protected(msta, msta->pri_link); |
| 189 | if (!mlink) |
| 190 | goto out; |
| 191 | |
| 192 | - txrate = &mlink->wcid.rate; |
| 193 | - if (txrate->legacy || txrate->flags) { |
| 194 | - if (txrate->legacy) { |
| 195 | - sinfo->txrate.legacy = txrate->legacy; |
| 196 | - } else { |
| 197 | - sinfo->txrate.mcs = txrate->mcs; |
| 198 | - sinfo->txrate.nss = txrate->nss; |
| 199 | - sinfo->txrate.bw = txrate->bw; |
| 200 | - sinfo->txrate.he_gi = txrate->he_gi; |
| 201 | - sinfo->txrate.he_dcm = txrate->he_dcm; |
| 202 | - sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; |
| 203 | - sinfo->txrate.eht_gi = txrate->eht_gi; |
| 204 | - } |
| 205 | - sinfo->txrate.flags = txrate->flags; |
| 206 | + rate = &mlink->wcid.rate; |
| 207 | + if (rate->legacy || rate->flags) { |
| 208 | + sinfo->txrate = *rate; |
| 209 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); |
| 210 | } |
| 211 | - sinfo->txrate.flags = txrate->flags; |
| 212 | - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); |
| 213 | + |
| 214 | + rate = &mlink->wcid.rx_rate; |
| 215 | + if (rate->legacy || rate->flags) { |
| 216 | + sinfo->rxrate = *rate; |
| 217 | + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); |
| 218 | + } |
| 219 | |
| 220 | sinfo->tx_failed = mlink->wcid.stats.tx_failed; |
| 221 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); |
| 222 | diff --git a/mt7996/mcu.c b/mt7996/mcu.c |
| 223 | index 51f15928..8fd9d450 100644 |
| 224 | --- a/mt7996/mcu.c |
| 225 | +++ b/mt7996/mcu.c |
| 226 | @@ -532,42 +532,164 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb) |
| 227 | } |
| 228 | |
| 229 | static int |
| 230 | -mt7996_mcu_update_tx_gi(struct rate_info *rate, struct all_sta_trx_rate *mcu_rate) |
| 231 | +mt7996_mcu_update_rate(struct rate_info *rate, struct ieee80211_supported_band *sband, |
| 232 | + u8 mode, u8 bw, u8 mcs, u8 nss, u8 stbc, u8 gi) |
| 233 | { |
| 234 | - switch (mcu_rate->tx_mode) { |
| 235 | + struct rate_info tmp_rate = {}; |
| 236 | + |
| 237 | + tmp_rate.mcs = mcs; |
| 238 | + tmp_rate.nss = (stbc && nss > 1) ? nss / 2 : nss; |
| 239 | + |
| 240 | + switch (mode) { |
| 241 | case MT_PHY_TYPE_CCK: |
| 242 | case MT_PHY_TYPE_OFDM: |
| 243 | + if (mcs >= sband->n_bitrates) |
| 244 | + return -EINVAL; |
| 245 | + |
| 246 | + tmp_rate.legacy = sband->bitrates[mcs].bitrate; |
| 247 | break; |
| 248 | case MT_PHY_TYPE_HT: |
| 249 | case MT_PHY_TYPE_HT_GF: |
| 250 | + if (mcs > 31) |
| 251 | + return -EINVAL; |
| 252 | + |
| 253 | + tmp_rate.flags |= RATE_INFO_FLAGS_MCS; |
| 254 | + if (gi) |
| 255 | + tmp_rate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 256 | + break; |
| 257 | case MT_PHY_TYPE_VHT: |
| 258 | - if (mcu_rate->tx_gi) |
| 259 | - rate->flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 260 | - else |
| 261 | - rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI; |
| 262 | + if (mcs > 9) |
| 263 | + return -EINVAL; |
| 264 | + |
| 265 | + tmp_rate.flags |= RATE_INFO_FLAGS_VHT_MCS; |
| 266 | + if (gi) |
| 267 | + tmp_rate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 268 | break; |
| 269 | case MT_PHY_TYPE_HE_SU: |
| 270 | case MT_PHY_TYPE_HE_EXT_SU: |
| 271 | case MT_PHY_TYPE_HE_TB: |
| 272 | case MT_PHY_TYPE_HE_MU: |
| 273 | - if (mcu_rate->tx_gi > NL80211_RATE_INFO_HE_GI_3_2) |
| 274 | + tmp_rate.mcs = mcs & GENMASK(3, 0); |
| 275 | + if (tmp_rate.mcs > 11 || gi > NL80211_RATE_INFO_HE_GI_3_2) |
| 276 | return -EINVAL; |
| 277 | - rate->he_gi = mcu_rate->tx_gi; |
| 278 | + |
| 279 | + tmp_rate.flags |= RATE_INFO_FLAGS_HE_MCS; |
| 280 | + tmp_rate.he_gi = gi; |
| 281 | + tmp_rate.he_dcm = mcs & MT_PRXV_TX_DCM; |
| 282 | break; |
| 283 | case MT_PHY_TYPE_EHT_SU: |
| 284 | case MT_PHY_TYPE_EHT_TRIG: |
| 285 | case MT_PHY_TYPE_EHT_MU: |
| 286 | - if (mcu_rate->tx_gi > NL80211_RATE_INFO_EHT_GI_3_2) |
| 287 | + tmp_rate.mcs = mcs & GENMASK(3, 0); |
| 288 | + if (tmp_rate.mcs > 13 || gi > NL80211_RATE_INFO_EHT_GI_3_2) |
| 289 | return -EINVAL; |
| 290 | - rate->eht_gi = mcu_rate->tx_gi; |
| 291 | + |
| 292 | + tmp_rate.flags |= RATE_INFO_FLAGS_EHT_MCS; |
| 293 | + tmp_rate.eht_gi = gi; |
| 294 | break; |
| 295 | default: |
| 296 | return -EINVAL; |
| 297 | } |
| 298 | |
| 299 | + switch (bw) { |
| 300 | + case IEEE80211_STA_RX_BW_20: |
| 301 | + tmp_rate.bw = RATE_INFO_BW_20; |
| 302 | + break; |
| 303 | + case IEEE80211_STA_RX_BW_40: |
| 304 | + tmp_rate.bw = RATE_INFO_BW_40; |
| 305 | + break; |
| 306 | + case IEEE80211_STA_RX_BW_80: |
| 307 | + tmp_rate.bw = RATE_INFO_BW_80; |
| 308 | + break; |
| 309 | + case IEEE80211_STA_RX_BW_160: |
| 310 | + tmp_rate.bw = RATE_INFO_BW_160; |
| 311 | + break; |
| 312 | + case IEEE80211_STA_RX_BW_320: |
| 313 | + tmp_rate.bw = RATE_INFO_BW_320; |
| 314 | + break; |
| 315 | + default: |
| 316 | + return -EINVAL; |
| 317 | + } |
| 318 | + |
| 319 | + if (mode == MT_PHY_TYPE_HE_EXT_SU && mcs & MT_PRXV_TX_ER_SU_106T) { |
| 320 | + tmp_rate.bw = RATE_INFO_BW_HE_RU; |
| 321 | + tmp_rate.he_ru_alloc = NL80211_RATE_INFO_HE_RU_ALLOC_106; |
| 322 | + } |
| 323 | + *rate = tmp_rate; |
| 324 | + |
| 325 | return 0; |
| 326 | } |
| 327 | |
| 328 | +static int |
| 329 | +mt7996_mcu_update_trx_rates(struct mt76_wcid *wcid, struct all_sta_trx_rate *mcu_rate) |
| 330 | +{ |
| 331 | + struct mt7996_link_sta *mlink = container_of(wcid, struct mt7996_link_sta, wcid); |
| 332 | + struct mt76_dev *dev = &mlink->sta->vif->dev->mt76; |
| 333 | + struct mt76_phy *phy = mt76_dev_phy(dev, wcid->phy_idx); |
| 334 | + struct ieee80211_supported_band *sband = NULL; |
| 335 | + bool cck; |
| 336 | + int ret; |
| 337 | + |
| 338 | + /* TX rate */ |
| 339 | + cck = false; |
| 340 | + |
| 341 | + switch (mcu_rate->tx_mode) { |
| 342 | + case MT_PHY_TYPE_CCK: |
| 343 | + cck = true; |
| 344 | + fallthrough; |
| 345 | + case MT_PHY_TYPE_OFDM: |
| 346 | + if (phy->chandef.chan->band == NL80211_BAND_2GHZ) { |
| 347 | + sband = &phy->sband_2g.sband; |
| 348 | + if (!cck) |
| 349 | + mcu_rate->tx_mcs += 4; |
| 350 | + } else if (phy->chandef.chan->band == NL80211_BAND_5GHZ) |
| 351 | + sband = &phy->sband_5g.sband; |
| 352 | + else |
| 353 | + sband = &phy->sband_6g.sband; |
| 354 | + break; |
| 355 | + case MT_PHY_TYPE_HT: |
| 356 | + case MT_PHY_TYPE_HT_GF: |
| 357 | + mcu_rate->tx_mcs += ((mcu_rate->tx_nss - 1) << 3); |
| 358 | + break; |
| 359 | + default: |
| 360 | + break; |
| 361 | + } |
| 362 | + |
| 363 | + ret = mt7996_mcu_update_rate(&wcid->rate, sband, mcu_rate->tx_mode, |
| 364 | + mcu_rate->tx_bw, mcu_rate->tx_mcs, |
| 365 | + mcu_rate->tx_nss, mcu_rate->tx_stbc, |
| 366 | + mcu_rate->tx_gi); |
| 367 | + if (ret) |
| 368 | + return ret; |
| 369 | + |
| 370 | + /* RX rate */ |
| 371 | + cck = false; |
| 372 | + |
| 373 | + switch (mcu_rate->rx_mode) { |
| 374 | + case MT_PHY_TYPE_CCK: |
| 375 | + cck = true; |
| 376 | + fallthrough; |
| 377 | + case MT_PHY_TYPE_OFDM: |
| 378 | + if (phy->chandef.chan->band == NL80211_BAND_2GHZ) |
| 379 | + sband = &phy->sband_2g.sband; |
| 380 | + else if (phy->chandef.chan->band == NL80211_BAND_5GHZ) |
| 381 | + sband = &phy->sband_5g.sband; |
| 382 | + else |
| 383 | + sband = &phy->sband_6g.sband; |
| 384 | + |
| 385 | + mcu_rate->rx_rate = mt76_get_rate(dev, sband, mcu_rate->rx_rate, cck); |
| 386 | + break; |
| 387 | + default: |
| 388 | + break; |
| 389 | + } |
| 390 | + |
| 391 | + ret = mt7996_mcu_update_rate(&wcid->rx_rate, sband, mcu_rate->rx_mode, |
| 392 | + mcu_rate->rx_bw, mcu_rate->rx_rate, |
| 393 | + mcu_rate->rx_nsts + 1, mcu_rate->rx_stbc, |
| 394 | + mcu_rate->rx_gi); |
| 395 | + return ret; |
| 396 | +} |
| 397 | + |
| 398 | static inline void __mt7996_stat_to_netdev(struct mt76_phy *mphy, |
| 399 | struct mt76_wcid *wcid, |
| 400 | u32 tx_bytes, u32 rx_bytes, |
| 401 | @@ -618,8 +740,8 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb) |
| 402 | if (!wcid) |
| 403 | break; |
| 404 | |
| 405 | - if (mt7996_mcu_update_tx_gi(&wcid->rate, &res->rate[i])) |
| 406 | - dev_err(dev->mt76.dev, "Failed to update TX GI\n"); |
| 407 | + if (mt7996_mcu_update_trx_rates(wcid, &res->rate[i])) |
| 408 | + dev_err(dev->mt76.dev, "Failed to update TX/RX rates.\n"); |
| 409 | break; |
| 410 | case UNI_ALL_STA_TXRX_ADM_STAT: |
| 411 | wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx); |
| 412 | -- |
| 413 | 2.18.0 |
| 414 | |