.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /****************************************************************************** |
---|
2 | 3 | * |
---|
3 | | - * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
---|
| 4 | + * Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. |
---|
4 | 5 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
---|
5 | 6 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
---|
6 | | - * Copyright(c) 2018 Intel Corporation |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify it |
---|
9 | | - * under the terms of version 2 of the GNU General Public License as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
13 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
14 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
15 | | - * more details. |
---|
16 | | - * |
---|
17 | | - * The full GNU General Public License is included in this distribution in the |
---|
18 | | - * file called LICENSE. |
---|
19 | 7 | * |
---|
20 | 8 | * Contact Information: |
---|
21 | 9 | * Intel Linux Wireless <linuxwifi@intel.com> |
---|
.. | .. |
---|
615 | 603 | struct iwl_lq_sta *lq_data, u8 tid, |
---|
616 | 604 | struct ieee80211_sta *sta) |
---|
617 | 605 | { |
---|
618 | | - int ret = -EAGAIN; |
---|
| 606 | + int ret; |
---|
619 | 607 | |
---|
620 | 608 | IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n", |
---|
621 | 609 | sta->addr, tid); |
---|
.. | .. |
---|
841 | 829 | ucode_rate |= RATE_MCS_CCK_MSK; |
---|
842 | 830 | return ucode_rate; |
---|
843 | 831 | } |
---|
| 832 | + |
---|
| 833 | + /* set RTS protection for all non legacy rates |
---|
| 834 | + * This helps with congested environments reducing the conflict cost to |
---|
| 835 | + * RTS retries only, instead of the entire BA packet. |
---|
| 836 | + */ |
---|
| 837 | + ucode_rate |= RATE_MCS_RTS_REQUIRED_MSK; |
---|
844 | 838 | |
---|
845 | 839 | if (is_ht(rate)) { |
---|
846 | 840 | if (index < IWL_FIRST_HT_RATE || index > IWL_LAST_HT_RATE) { |
---|
.. | .. |
---|
1208 | 1202 | return tid; |
---|
1209 | 1203 | } |
---|
1210 | 1204 | |
---|
1211 | | -void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
---|
1212 | | - int tid, struct ieee80211_tx_info *info, bool ndp) |
---|
1213 | | -{ |
---|
1214 | | - int legacy_success; |
---|
1215 | | - int retries; |
---|
1216 | | - int i; |
---|
1217 | | - struct iwl_lq_cmd *table; |
---|
1218 | | - u32 lq_hwrate; |
---|
1219 | | - struct rs_rate lq_rate, tx_resp_rate; |
---|
1220 | | - struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
---|
1221 | | - u32 tlc_info = (uintptr_t)info->status.status_driver_data[0]; |
---|
1222 | | - u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK; |
---|
1223 | | - u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info); |
---|
1224 | | - u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1]; |
---|
1225 | | - struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
---|
1226 | | - struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv; |
---|
1227 | | - |
---|
1228 | | - /* Treat uninitialized rate scaling data same as non-existing. */ |
---|
1229 | | - if (!lq_sta) { |
---|
1230 | | - IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n"); |
---|
1231 | | - return; |
---|
1232 | | - } else if (!lq_sta->pers.drv) { |
---|
1233 | | - IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n"); |
---|
1234 | | - return; |
---|
1235 | | - } |
---|
1236 | | - |
---|
1237 | | - /* This packet was aggregated but doesn't carry status info */ |
---|
1238 | | - if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
---|
1239 | | - !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
---|
1240 | | - return; |
---|
1241 | | - |
---|
1242 | | - if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, |
---|
1243 | | - &tx_resp_rate)) { |
---|
1244 | | - WARN_ON_ONCE(1); |
---|
1245 | | - return; |
---|
1246 | | - } |
---|
1247 | | - |
---|
1248 | | -#ifdef CONFIG_MAC80211_DEBUGFS |
---|
1249 | | - /* Disable last tx check if we are debugging with fixed rate but |
---|
1250 | | - * update tx stats */ |
---|
1251 | | - if (lq_sta->pers.dbg_fixed_rate) { |
---|
1252 | | - int index = tx_resp_rate.index; |
---|
1253 | | - enum rs_column column; |
---|
1254 | | - int attempts, success; |
---|
1255 | | - |
---|
1256 | | - column = rs_get_column_from_rate(&tx_resp_rate); |
---|
1257 | | - if (WARN_ONCE(column == RS_COLUMN_INVALID, |
---|
1258 | | - "Can't map rate 0x%x to column", |
---|
1259 | | - tx_resp_hwrate)) |
---|
1260 | | - return; |
---|
1261 | | - |
---|
1262 | | - if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
---|
1263 | | - attempts = info->status.ampdu_len; |
---|
1264 | | - success = info->status.ampdu_ack_len; |
---|
1265 | | - } else { |
---|
1266 | | - attempts = info->status.rates[0].count; |
---|
1267 | | - success = !!(info->flags & IEEE80211_TX_STAT_ACK); |
---|
1268 | | - } |
---|
1269 | | - |
---|
1270 | | - lq_sta->pers.tx_stats[column][index].total += attempts; |
---|
1271 | | - lq_sta->pers.tx_stats[column][index].success += success; |
---|
1272 | | - |
---|
1273 | | - IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n", |
---|
1274 | | - tx_resp_hwrate, success, attempts); |
---|
1275 | | - return; |
---|
1276 | | - } |
---|
1277 | | -#endif |
---|
1278 | | - |
---|
1279 | | - if (time_after(jiffies, |
---|
1280 | | - (unsigned long)(lq_sta->last_tx + |
---|
1281 | | - (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) { |
---|
1282 | | - IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n"); |
---|
1283 | | - iwl_mvm_rs_rate_init(mvm, sta, info->band, true); |
---|
1284 | | - return; |
---|
1285 | | - } |
---|
1286 | | - lq_sta->last_tx = jiffies; |
---|
1287 | | - |
---|
1288 | | - /* Ignore this Tx frame response if its initial rate doesn't match |
---|
1289 | | - * that of latest Link Quality command. There may be stragglers |
---|
1290 | | - * from a previous Link Quality command, but we're no longer interested |
---|
1291 | | - * in those; they're either from the "active" mode while we're trying |
---|
1292 | | - * to check "search" mode, or a prior "search" mode after we've moved |
---|
1293 | | - * to a new "search" mode (which might become the new "active" mode). |
---|
1294 | | - */ |
---|
1295 | | - table = &lq_sta->lq; |
---|
1296 | | - lq_hwrate = le32_to_cpu(table->rs_table[0]); |
---|
1297 | | - if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) { |
---|
1298 | | - WARN_ON_ONCE(1); |
---|
1299 | | - return; |
---|
1300 | | - } |
---|
1301 | | - |
---|
1302 | | - /* Here we actually compare this rate to the latest LQ command */ |
---|
1303 | | - if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) { |
---|
1304 | | - IWL_DEBUG_RATE(mvm, |
---|
1305 | | - "tx resp color 0x%x does not match 0x%x\n", |
---|
1306 | | - lq_color, LQ_FLAG_COLOR_GET(table->flags)); |
---|
1307 | | - |
---|
1308 | | - /* |
---|
1309 | | - * Since rates mis-match, the last LQ command may have failed. |
---|
1310 | | - * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with |
---|
1311 | | - * ... driver. |
---|
1312 | | - */ |
---|
1313 | | - lq_sta->missed_rate_counter++; |
---|
1314 | | - if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) { |
---|
1315 | | - lq_sta->missed_rate_counter = 0; |
---|
1316 | | - IWL_DEBUG_RATE(mvm, |
---|
1317 | | - "Too many rates mismatch. Send sync LQ. rs_state %d\n", |
---|
1318 | | - lq_sta->rs_state); |
---|
1319 | | - iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); |
---|
1320 | | - } |
---|
1321 | | - /* Regardless, ignore this status info for outdated rate */ |
---|
1322 | | - return; |
---|
1323 | | - } else |
---|
1324 | | - /* Rate did match, so reset the missed_rate_counter */ |
---|
1325 | | - lq_sta->missed_rate_counter = 0; |
---|
1326 | | - |
---|
1327 | | - if (!lq_sta->search_better_tbl) { |
---|
1328 | | - curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
---|
1329 | | - other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); |
---|
1330 | | - } else { |
---|
1331 | | - curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); |
---|
1332 | | - other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
---|
1333 | | - } |
---|
1334 | | - |
---|
1335 | | - if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) { |
---|
1336 | | - IWL_DEBUG_RATE(mvm, |
---|
1337 | | - "Neither active nor search matches tx rate\n"); |
---|
1338 | | - tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
---|
1339 | | - rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE"); |
---|
1340 | | - tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); |
---|
1341 | | - rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH"); |
---|
1342 | | - rs_dump_rate(mvm, &lq_rate, "ACTUAL"); |
---|
1343 | | - |
---|
1344 | | - /* |
---|
1345 | | - * no matching table found, let's by-pass the data collection |
---|
1346 | | - * and continue to perform rate scale to find the rate table |
---|
1347 | | - */ |
---|
1348 | | - rs_stay_in_table(lq_sta, true); |
---|
1349 | | - goto done; |
---|
1350 | | - } |
---|
1351 | | - |
---|
1352 | | - /* |
---|
1353 | | - * Updating the frame history depends on whether packets were |
---|
1354 | | - * aggregated. |
---|
1355 | | - * |
---|
1356 | | - * For aggregation, all packets were transmitted at the same rate, the |
---|
1357 | | - * first index into rate scale table. |
---|
1358 | | - */ |
---|
1359 | | - if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
---|
1360 | | - rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index, |
---|
1361 | | - info->status.ampdu_len, |
---|
1362 | | - info->status.ampdu_ack_len, |
---|
1363 | | - reduced_txp); |
---|
1364 | | - |
---|
1365 | | - /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat |
---|
1366 | | - * it as a single frame loss as we don't want the success ratio |
---|
1367 | | - * to dip too quickly because a BA wasn't received. |
---|
1368 | | - * For TPC, there's no need for this optimisation since we want |
---|
1369 | | - * to recover very quickly from a bad power reduction and, |
---|
1370 | | - * therefore we'd like the success ratio to get an immediate hit |
---|
1371 | | - * when failing to get a BA, so we'd switch back to a lower or |
---|
1372 | | - * zero power reduction. When FW transmits agg with a rate |
---|
1373 | | - * different from the initial rate, it will not use reduced txp |
---|
1374 | | - * and will send BA notification twice (one empty with reduced |
---|
1375 | | - * txp equal to the value from LQ and one with reduced txp 0). |
---|
1376 | | - * We need to update counters for each txp level accordingly. |
---|
1377 | | - */ |
---|
1378 | | - if (info->status.ampdu_ack_len == 0) |
---|
1379 | | - info->status.ampdu_len = 1; |
---|
1380 | | - |
---|
1381 | | - rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl, tx_resp_rate.index, |
---|
1382 | | - info->status.ampdu_len, |
---|
1383 | | - info->status.ampdu_ack_len); |
---|
1384 | | - |
---|
1385 | | - /* Update success/fail counts if not searching for new mode */ |
---|
1386 | | - if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { |
---|
1387 | | - lq_sta->total_success += info->status.ampdu_ack_len; |
---|
1388 | | - lq_sta->total_failed += (info->status.ampdu_len - |
---|
1389 | | - info->status.ampdu_ack_len); |
---|
1390 | | - } |
---|
1391 | | - } else { |
---|
1392 | | - /* For legacy, update frame history with for each Tx retry. */ |
---|
1393 | | - retries = info->status.rates[0].count - 1; |
---|
1394 | | - /* HW doesn't send more than 15 retries */ |
---|
1395 | | - retries = min(retries, 15); |
---|
1396 | | - |
---|
1397 | | - /* The last transmission may have been successful */ |
---|
1398 | | - legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK); |
---|
1399 | | - /* Collect data for each rate used during failed TX attempts */ |
---|
1400 | | - for (i = 0; i <= retries; ++i) { |
---|
1401 | | - lq_hwrate = le32_to_cpu(table->rs_table[i]); |
---|
1402 | | - if (rs_rate_from_ucode_rate(lq_hwrate, info->band, |
---|
1403 | | - &lq_rate)) { |
---|
1404 | | - WARN_ON_ONCE(1); |
---|
1405 | | - return; |
---|
1406 | | - } |
---|
1407 | | - |
---|
1408 | | - /* |
---|
1409 | | - * Only collect stats if retried rate is in the same RS |
---|
1410 | | - * table as active/search. |
---|
1411 | | - */ |
---|
1412 | | - if (rs_rate_column_match(&lq_rate, &curr_tbl->rate)) |
---|
1413 | | - tmp_tbl = curr_tbl; |
---|
1414 | | - else if (rs_rate_column_match(&lq_rate, |
---|
1415 | | - &other_tbl->rate)) |
---|
1416 | | - tmp_tbl = other_tbl; |
---|
1417 | | - else |
---|
1418 | | - continue; |
---|
1419 | | - |
---|
1420 | | - rs_collect_tpc_data(mvm, lq_sta, tmp_tbl, |
---|
1421 | | - tx_resp_rate.index, 1, |
---|
1422 | | - i < retries ? 0 : legacy_success, |
---|
1423 | | - reduced_txp); |
---|
1424 | | - rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl, |
---|
1425 | | - tx_resp_rate.index, 1, |
---|
1426 | | - i < retries ? 0 : legacy_success); |
---|
1427 | | - } |
---|
1428 | | - |
---|
1429 | | - /* Update success/fail counts if not searching for new mode */ |
---|
1430 | | - if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { |
---|
1431 | | - lq_sta->total_success += legacy_success; |
---|
1432 | | - lq_sta->total_failed += retries + (1 - legacy_success); |
---|
1433 | | - } |
---|
1434 | | - } |
---|
1435 | | - /* The last TX rate is cached in lq_sta; it's set in if/else above */ |
---|
1436 | | - lq_sta->last_rate_n_flags = lq_hwrate; |
---|
1437 | | - IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); |
---|
1438 | | -done: |
---|
1439 | | - /* See if there's a better rate or modulation mode to try. */ |
---|
1440 | | - if (sta->supp_rates[info->band]) |
---|
1441 | | - rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp); |
---|
1442 | | -} |
---|
1443 | | - |
---|
1444 | 1205 | /* |
---|
1445 | 1206 | * mac80211 sends us Tx status |
---|
1446 | 1207 | */ |
---|
.. | .. |
---|
1453 | 1214 | struct iwl_op_mode *op_mode = mvm_r; |
---|
1454 | 1215 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
---|
1455 | 1216 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
---|
| 1217 | + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
---|
1456 | 1218 | |
---|
1457 | | - if (!iwl_mvm_sta_from_mac80211(sta)->vif) |
---|
| 1219 | + if (!mvmsta->vif) |
---|
1458 | 1220 | return; |
---|
1459 | 1221 | |
---|
1460 | 1222 | if (!ieee80211_is_data(hdr->frame_control) || |
---|
.. | .. |
---|
1595 | 1357 | tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw); |
---|
1596 | 1358 | } |
---|
1597 | 1359 | |
---|
| 1360 | +/* rs uses two tables, one is active and the second is for searching better |
---|
| 1361 | + * configuration. This function, according to the index of the currently |
---|
| 1362 | + * active table returns the search table, which is located at the |
---|
| 1363 | + * index complementary to 1 according to the active table (active = 1, |
---|
| 1364 | + * search = 0 or active = 0, search = 1). |
---|
| 1365 | + * Since lq_info is an arary of size 2, make sure index cannot be out of bounds. |
---|
| 1366 | + */ |
---|
| 1367 | +static inline u8 rs_search_tbl(u8 active_tbl) |
---|
| 1368 | +{ |
---|
| 1369 | + return (active_tbl ^ 1) & 1; |
---|
| 1370 | +} |
---|
| 1371 | + |
---|
1598 | 1372 | static s32 rs_get_best_rate(struct iwl_mvm *mvm, |
---|
1599 | 1373 | struct iwl_lq_sta *lq_sta, |
---|
1600 | 1374 | struct iwl_scale_tbl_info *tbl, /* "search" */ |
---|
.. | .. |
---|
1643 | 1417 | |
---|
1644 | 1418 | static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) |
---|
1645 | 1419 | { |
---|
| 1420 | + struct ieee80211_sta_vht_cap *sta_vht_cap = &sta->vht_cap; |
---|
| 1421 | + struct ieee80211_vht_cap vht_cap = { |
---|
| 1422 | + .vht_cap_info = cpu_to_le32(sta_vht_cap->cap), |
---|
| 1423 | + .supp_mcs = sta_vht_cap->vht_mcs, |
---|
| 1424 | + }; |
---|
| 1425 | + |
---|
1646 | 1426 | switch (sta->bandwidth) { |
---|
1647 | 1427 | case IEEE80211_STA_RX_BW_160: |
---|
| 1428 | + /* |
---|
| 1429 | + * Don't use 160 MHz if VHT extended NSS support |
---|
| 1430 | + * says we cannot use 2 streams, we don't want to |
---|
| 1431 | + * deal with this. |
---|
| 1432 | + * We only check MCS 0 - they will support that if |
---|
| 1433 | + * we got here at all and we don't care which MCS, |
---|
| 1434 | + * we want to determine a more global state. |
---|
| 1435 | + */ |
---|
| 1436 | + if (ieee80211_get_vht_max_nss(&vht_cap, |
---|
| 1437 | + IEEE80211_VHT_CHANWIDTH_160MHZ, |
---|
| 1438 | + 0, true, |
---|
| 1439 | + sta->rx_nss) < sta->rx_nss) |
---|
| 1440 | + return RATE_MCS_CHAN_WIDTH_80; |
---|
1648 | 1441 | return RATE_MCS_CHAN_WIDTH_160; |
---|
1649 | 1442 | case IEEE80211_STA_RX_BW_80: |
---|
1650 | 1443 | return RATE_MCS_CHAN_WIDTH_80; |
---|
.. | .. |
---|
1744 | 1537 | enum rs_action scale_action) |
---|
1745 | 1538 | { |
---|
1746 | 1539 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
---|
| 1540 | + int i; |
---|
| 1541 | + |
---|
| 1542 | + sta->max_amsdu_len = rs_fw_get_max_amsdu_len(sta); |
---|
1747 | 1543 | |
---|
1748 | 1544 | /* |
---|
1749 | 1545 | * In case TLC offload is not active amsdu_enabled is either 0xFFFF |
---|
.. | .. |
---|
1756 | 1552 | else |
---|
1757 | 1553 | mvmsta->amsdu_enabled = 0xFFFF; |
---|
1758 | 1554 | |
---|
1759 | | - mvmsta->max_amsdu_len = sta->max_amsdu_len; |
---|
| 1555 | + if (mvmsta->vif->bss_conf.he_support && |
---|
| 1556 | + !iwlwifi_mod_params.disable_11ax) |
---|
| 1557 | + mvmsta->max_amsdu_len = sta->max_amsdu_len; |
---|
| 1558 | + else |
---|
| 1559 | + mvmsta->max_amsdu_len = min_t(int, sta->max_amsdu_len, 8500); |
---|
| 1560 | + |
---|
| 1561 | + sta->max_rc_amsdu_len = mvmsta->max_amsdu_len; |
---|
| 1562 | + |
---|
| 1563 | + for (i = 0; i < IWL_MAX_TID_COUNT; i++) { |
---|
| 1564 | + if (mvmsta->amsdu_enabled) |
---|
| 1565 | + sta->max_tid_amsdu_len[i] = |
---|
| 1566 | + iwl_mvm_max_amsdu_size(mvm, sta, i); |
---|
| 1567 | + else |
---|
| 1568 | + /* |
---|
| 1569 | + * Not so elegant, but this will effectively |
---|
| 1570 | + * prevent AMSDU on this TID |
---|
| 1571 | + */ |
---|
| 1572 | + sta->max_tid_amsdu_len[i] = 1; |
---|
| 1573 | + } |
---|
1760 | 1574 | } |
---|
1761 | 1575 | |
---|
1762 | 1576 | /* |
---|
.. | .. |
---|
1768 | 1582 | struct iwl_scale_tbl_info *tbl) |
---|
1769 | 1583 | { |
---|
1770 | 1584 | rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate); |
---|
1771 | | - iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); |
---|
| 1585 | + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq); |
---|
1772 | 1586 | } |
---|
1773 | 1587 | |
---|
1774 | 1588 | static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm, |
---|
.. | .. |
---|
1777 | 1591 | struct iwl_scale_tbl_info *tbl, |
---|
1778 | 1592 | enum rs_action scale_action) |
---|
1779 | 1593 | { |
---|
1780 | | - if (sta->bandwidth != IEEE80211_STA_RX_BW_80) |
---|
| 1594 | + if (rs_bw_from_sta_bw(sta) != RATE_MCS_CHAN_WIDTH_80) |
---|
1781 | 1595 | return false; |
---|
1782 | 1596 | |
---|
1783 | 1597 | if (!is_vht_siso(&tbl->rate)) |
---|
.. | .. |
---|
1905 | 1719 | struct ieee80211_sta *sta, |
---|
1906 | 1720 | enum rs_column col_id) |
---|
1907 | 1721 | { |
---|
1908 | | - struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
---|
| 1722 | + struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl]; |
---|
1909 | 1723 | struct iwl_scale_tbl_info *search_tbl = |
---|
1910 | | - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
---|
| 1724 | + &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; |
---|
1911 | 1725 | struct rs_rate *rate = &search_tbl->rate; |
---|
1912 | 1726 | const struct rs_tx_column *column = &rs_tx_columns[col_id]; |
---|
1913 | 1727 | const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column]; |
---|
.. | .. |
---|
2315 | 2129 | if (!lq_sta->search_better_tbl) |
---|
2316 | 2130 | active_tbl = lq_sta->active_tbl; |
---|
2317 | 2131 | else |
---|
2318 | | - active_tbl = 1 - lq_sta->active_tbl; |
---|
| 2132 | + active_tbl = rs_search_tbl(lq_sta->active_tbl); |
---|
2319 | 2133 | |
---|
2320 | 2134 | tbl = &(lq_sta->lq_info[active_tbl]); |
---|
2321 | 2135 | rate = &tbl->rate; |
---|
.. | .. |
---|
2539 | 2353 | /* If new "search" mode was selected, set up in uCode table */ |
---|
2540 | 2354 | if (lq_sta->search_better_tbl) { |
---|
2541 | 2355 | /* Access the "search" table, clear its history. */ |
---|
2542 | | - tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
---|
| 2356 | + tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; |
---|
2543 | 2357 | rs_rate_scale_clear_tbl_windows(mvm, tbl); |
---|
2544 | 2358 | |
---|
2545 | 2359 | /* Use new "search" start rate */ |
---|
.. | .. |
---|
2870 | 2684 | static void rs_initialize_lq(struct iwl_mvm *mvm, |
---|
2871 | 2685 | struct ieee80211_sta *sta, |
---|
2872 | 2686 | struct iwl_lq_sta *lq_sta, |
---|
2873 | | - enum nl80211_band band, bool update) |
---|
| 2687 | + enum nl80211_band band) |
---|
2874 | 2688 | { |
---|
2875 | 2689 | struct iwl_scale_tbl_info *tbl; |
---|
2876 | 2690 | struct rs_rate *rate; |
---|
.. | .. |
---|
2882 | 2696 | if (!lq_sta->search_better_tbl) |
---|
2883 | 2697 | active_tbl = lq_sta->active_tbl; |
---|
2884 | 2698 | else |
---|
2885 | | - active_tbl = 1 - lq_sta->active_tbl; |
---|
| 2699 | + active_tbl = rs_search_tbl(lq_sta->active_tbl); |
---|
2886 | 2700 | |
---|
2887 | 2701 | tbl = &(lq_sta->lq_info[active_tbl]); |
---|
2888 | 2702 | rate = &tbl->rate; |
---|
.. | .. |
---|
2900 | 2714 | rs_set_expected_tpt_table(lq_sta, tbl); |
---|
2901 | 2715 | rs_fill_lq_cmd(mvm, sta, lq_sta, rate); |
---|
2902 | 2716 | /* TODO restore station should remember the lq cmd */ |
---|
2903 | | - iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, !update); |
---|
| 2717 | + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq); |
---|
2904 | 2718 | } |
---|
2905 | 2719 | |
---|
2906 | 2720 | static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta, |
---|
.. | .. |
---|
2922 | 2736 | sta = NULL; |
---|
2923 | 2737 | mvm_sta = NULL; |
---|
2924 | 2738 | } |
---|
2925 | | - |
---|
2926 | | - /* Send management frames and NO_ACK data using lowest rate. */ |
---|
2927 | | - if (rate_control_send_low(sta, mvm_sta, txrc)) |
---|
2928 | | - return; |
---|
2929 | 2739 | |
---|
2930 | 2740 | if (!mvm_sta) |
---|
2931 | 2741 | return; |
---|
.. | .. |
---|
3153 | 2963 | * Called after adding a new station to initialize rate scaling |
---|
3154 | 2964 | */ |
---|
3155 | 2965 | static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
---|
3156 | | - enum nl80211_band band, bool update) |
---|
| 2966 | + enum nl80211_band band) |
---|
3157 | 2967 | { |
---|
3158 | 2968 | int i, j; |
---|
3159 | 2969 | struct ieee80211_hw *hw = mvm->hw; |
---|
.. | .. |
---|
3163 | 2973 | struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv; |
---|
3164 | 2974 | struct ieee80211_supported_band *sband; |
---|
3165 | 2975 | unsigned long supp; /* must be unsigned long for for_each_set_bit */ |
---|
| 2976 | + |
---|
| 2977 | + lockdep_assert_held(&mvmsta->lq_sta.rs_drv.pers.lock); |
---|
3166 | 2978 | |
---|
3167 | 2979 | /* clear all non-persistent lq data */ |
---|
3168 | 2980 | memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers)); |
---|
.. | .. |
---|
3224 | 3036 | |
---|
3225 | 3037 | /* These values will be overridden later */ |
---|
3226 | 3038 | lq_sta->lq.single_stream_ant_msk = |
---|
3227 | | - first_antenna(iwl_mvm_get_valid_tx_ant(mvm)); |
---|
| 3039 | + iwl_mvm_bt_coex_get_single_ant_msk(mvm, iwl_mvm_get_valid_tx_ant(mvm)); |
---|
3228 | 3040 | lq_sta->lq.dual_stream_ant_msk = ANT_AB; |
---|
3229 | 3041 | |
---|
3230 | 3042 | /* as default allow aggregation for all tids */ |
---|
.. | .. |
---|
3233 | 3045 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
---|
3234 | 3046 | iwl_mvm_reset_frame_stats(mvm); |
---|
3235 | 3047 | #endif |
---|
3236 | | - rs_initialize_lq(mvm, sta, lq_sta, band, update); |
---|
| 3048 | + rs_initialize_lq(mvm, sta, lq_sta, band); |
---|
3237 | 3049 | } |
---|
3238 | 3050 | |
---|
3239 | 3051 | static void rs_drv_rate_update(void *mvm_r, |
---|
.. | .. |
---|
3254 | 3066 | ieee80211_stop_tx_ba_session(sta, tid); |
---|
3255 | 3067 | |
---|
3256 | 3068 | iwl_mvm_rs_rate_init(mvm, sta, sband->band, true); |
---|
| 3069 | +} |
---|
| 3070 | + |
---|
| 3071 | +static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, |
---|
| 3072 | + struct ieee80211_sta *sta, |
---|
| 3073 | + int tid, struct ieee80211_tx_info *info, |
---|
| 3074 | + bool ndp) |
---|
| 3075 | +{ |
---|
| 3076 | + int legacy_success; |
---|
| 3077 | + int retries; |
---|
| 3078 | + int i; |
---|
| 3079 | + struct iwl_lq_cmd *table; |
---|
| 3080 | + u32 lq_hwrate; |
---|
| 3081 | + struct rs_rate lq_rate, tx_resp_rate; |
---|
| 3082 | + struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
---|
| 3083 | + u32 tlc_info = (uintptr_t)info->status.status_driver_data[0]; |
---|
| 3084 | + u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK; |
---|
| 3085 | + u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info); |
---|
| 3086 | + u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1]; |
---|
| 3087 | + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
---|
| 3088 | + struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv; |
---|
| 3089 | + |
---|
| 3090 | + if (!lq_sta->pers.drv) { |
---|
| 3091 | + IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n"); |
---|
| 3092 | + return; |
---|
| 3093 | + } |
---|
| 3094 | + |
---|
| 3095 | + /* This packet was aggregated but doesn't carry status info */ |
---|
| 3096 | + if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
---|
| 3097 | + !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
---|
| 3098 | + return; |
---|
| 3099 | + |
---|
| 3100 | + if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, |
---|
| 3101 | + &tx_resp_rate)) { |
---|
| 3102 | + WARN_ON_ONCE(1); |
---|
| 3103 | + return; |
---|
| 3104 | + } |
---|
| 3105 | + |
---|
| 3106 | +#ifdef CONFIG_MAC80211_DEBUGFS |
---|
| 3107 | + /* Disable last tx check if we are debugging with fixed rate but |
---|
| 3108 | + * update tx stats |
---|
| 3109 | + */ |
---|
| 3110 | + if (lq_sta->pers.dbg_fixed_rate) { |
---|
| 3111 | + int index = tx_resp_rate.index; |
---|
| 3112 | + enum rs_column column; |
---|
| 3113 | + int attempts, success; |
---|
| 3114 | + |
---|
| 3115 | + column = rs_get_column_from_rate(&tx_resp_rate); |
---|
| 3116 | + if (WARN_ONCE(column == RS_COLUMN_INVALID, |
---|
| 3117 | + "Can't map rate 0x%x to column", |
---|
| 3118 | + tx_resp_hwrate)) |
---|
| 3119 | + return; |
---|
| 3120 | + |
---|
| 3121 | + if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
---|
| 3122 | + attempts = info->status.ampdu_len; |
---|
| 3123 | + success = info->status.ampdu_ack_len; |
---|
| 3124 | + } else { |
---|
| 3125 | + attempts = info->status.rates[0].count; |
---|
| 3126 | + success = !!(info->flags & IEEE80211_TX_STAT_ACK); |
---|
| 3127 | + } |
---|
| 3128 | + |
---|
| 3129 | + lq_sta->pers.tx_stats[column][index].total += attempts; |
---|
| 3130 | + lq_sta->pers.tx_stats[column][index].success += success; |
---|
| 3131 | + |
---|
| 3132 | + IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n", |
---|
| 3133 | + tx_resp_hwrate, success, attempts); |
---|
| 3134 | + return; |
---|
| 3135 | + } |
---|
| 3136 | +#endif |
---|
| 3137 | + |
---|
| 3138 | + if (time_after(jiffies, |
---|
| 3139 | + (unsigned long)(lq_sta->last_tx + |
---|
| 3140 | + (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) { |
---|
| 3141 | + IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n"); |
---|
| 3142 | + /* reach here only in case of driver RS, call directly |
---|
| 3143 | + * the unlocked version |
---|
| 3144 | + */ |
---|
| 3145 | + rs_drv_rate_init(mvm, sta, info->band); |
---|
| 3146 | + return; |
---|
| 3147 | + } |
---|
| 3148 | + lq_sta->last_tx = jiffies; |
---|
| 3149 | + |
---|
| 3150 | + /* Ignore this Tx frame response if its initial rate doesn't match |
---|
| 3151 | + * that of latest Link Quality command. There may be stragglers |
---|
| 3152 | + * from a previous Link Quality command, but we're no longer interested |
---|
| 3153 | + * in those; they're either from the "active" mode while we're trying |
---|
| 3154 | + * to check "search" mode, or a prior "search" mode after we've moved |
---|
| 3155 | + * to a new "search" mode (which might become the new "active" mode). |
---|
| 3156 | + */ |
---|
| 3157 | + table = &lq_sta->lq; |
---|
| 3158 | + lq_hwrate = le32_to_cpu(table->rs_table[0]); |
---|
| 3159 | + if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) { |
---|
| 3160 | + WARN_ON_ONCE(1); |
---|
| 3161 | + return; |
---|
| 3162 | + } |
---|
| 3163 | + |
---|
| 3164 | + /* Here we actually compare this rate to the latest LQ command */ |
---|
| 3165 | + if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) { |
---|
| 3166 | + IWL_DEBUG_RATE(mvm, |
---|
| 3167 | + "tx resp color 0x%x does not match 0x%x\n", |
---|
| 3168 | + lq_color, LQ_FLAG_COLOR_GET(table->flags)); |
---|
| 3169 | + |
---|
| 3170 | + /* Since rates mis-match, the last LQ command may have failed. |
---|
| 3171 | + * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with |
---|
| 3172 | + * ... driver. |
---|
| 3173 | + */ |
---|
| 3174 | + lq_sta->missed_rate_counter++; |
---|
| 3175 | + if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) { |
---|
| 3176 | + lq_sta->missed_rate_counter = 0; |
---|
| 3177 | + IWL_DEBUG_RATE(mvm, |
---|
| 3178 | + "Too many rates mismatch. Send sync LQ. rs_state %d\n", |
---|
| 3179 | + lq_sta->rs_state); |
---|
| 3180 | + iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq); |
---|
| 3181 | + } |
---|
| 3182 | + /* Regardless, ignore this status info for outdated rate */ |
---|
| 3183 | + return; |
---|
| 3184 | + } |
---|
| 3185 | + |
---|
| 3186 | + /* Rate did match, so reset the missed_rate_counter */ |
---|
| 3187 | + lq_sta->missed_rate_counter = 0; |
---|
| 3188 | + |
---|
| 3189 | + if (!lq_sta->search_better_tbl) { |
---|
| 3190 | + curr_tbl = &lq_sta->lq_info[lq_sta->active_tbl]; |
---|
| 3191 | + other_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; |
---|
| 3192 | + } else { |
---|
| 3193 | + curr_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; |
---|
| 3194 | + other_tbl = &lq_sta->lq_info[lq_sta->active_tbl]; |
---|
| 3195 | + } |
---|
| 3196 | + |
---|
| 3197 | + if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) { |
---|
| 3198 | + IWL_DEBUG_RATE(mvm, |
---|
| 3199 | + "Neither active nor search matches tx rate\n"); |
---|
| 3200 | + tmp_tbl = &lq_sta->lq_info[lq_sta->active_tbl]; |
---|
| 3201 | + rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE"); |
---|
| 3202 | + tmp_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)]; |
---|
| 3203 | + rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH"); |
---|
| 3204 | + rs_dump_rate(mvm, &lq_rate, "ACTUAL"); |
---|
| 3205 | + |
---|
| 3206 | + /* no matching table found, let's by-pass the data collection |
---|
| 3207 | + * and continue to perform rate scale to find the rate table |
---|
| 3208 | + */ |
---|
| 3209 | + rs_stay_in_table(lq_sta, true); |
---|
| 3210 | + goto done; |
---|
| 3211 | + } |
---|
| 3212 | + |
---|
| 3213 | + /* Updating the frame history depends on whether packets were |
---|
| 3214 | + * aggregated. |
---|
| 3215 | + * |
---|
| 3216 | + * For aggregation, all packets were transmitted at the same rate, the |
---|
| 3217 | + * first index into rate scale table. |
---|
| 3218 | + */ |
---|
| 3219 | + if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
---|
| 3220 | + rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index, |
---|
| 3221 | + info->status.ampdu_len, |
---|
| 3222 | + info->status.ampdu_ack_len, |
---|
| 3223 | + reduced_txp); |
---|
| 3224 | + |
---|
| 3225 | + /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat |
---|
| 3226 | + * it as a single frame loss as we don't want the success ratio |
---|
| 3227 | + * to dip too quickly because a BA wasn't received. |
---|
| 3228 | + * For TPC, there's no need for this optimisation since we want |
---|
| 3229 | + * to recover very quickly from a bad power reduction and, |
---|
| 3230 | + * therefore we'd like the success ratio to get an immediate hit |
---|
| 3231 | + * when failing to get a BA, so we'd switch back to a lower or |
---|
| 3232 | + * zero power reduction. When FW transmits agg with a rate |
---|
| 3233 | + * different from the initial rate, it will not use reduced txp |
---|
| 3234 | + * and will send BA notification twice (one empty with reduced |
---|
| 3235 | + * txp equal to the value from LQ and one with reduced txp 0). |
---|
| 3236 | + * We need to update counters for each txp level accordingly. |
---|
| 3237 | + */ |
---|
| 3238 | + if (info->status.ampdu_ack_len == 0) |
---|
| 3239 | + info->status.ampdu_len = 1; |
---|
| 3240 | + |
---|
| 3241 | + rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl, |
---|
| 3242 | + tx_resp_rate.index, |
---|
| 3243 | + info->status.ampdu_len, |
---|
| 3244 | + info->status.ampdu_ack_len); |
---|
| 3245 | + |
---|
| 3246 | + /* Update success/fail counts if not searching for new mode */ |
---|
| 3247 | + if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { |
---|
| 3248 | + lq_sta->total_success += info->status.ampdu_ack_len; |
---|
| 3249 | + lq_sta->total_failed += (info->status.ampdu_len - |
---|
| 3250 | + info->status.ampdu_ack_len); |
---|
| 3251 | + } |
---|
| 3252 | + } else { |
---|
| 3253 | + /* For legacy, update frame history with for each Tx retry. */ |
---|
| 3254 | + retries = info->status.rates[0].count - 1; |
---|
| 3255 | + /* HW doesn't send more than 15 retries */ |
---|
| 3256 | + retries = min(retries, 15); |
---|
| 3257 | + |
---|
| 3258 | + /* The last transmission may have been successful */ |
---|
| 3259 | + legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK); |
---|
| 3260 | + /* Collect data for each rate used during failed TX attempts */ |
---|
| 3261 | + for (i = 0; i <= retries; ++i) { |
---|
| 3262 | + lq_hwrate = le32_to_cpu(table->rs_table[i]); |
---|
| 3263 | + if (rs_rate_from_ucode_rate(lq_hwrate, info->band, |
---|
| 3264 | + &lq_rate)) { |
---|
| 3265 | + WARN_ON_ONCE(1); |
---|
| 3266 | + return; |
---|
| 3267 | + } |
---|
| 3268 | + |
---|
| 3269 | + /* Only collect stats if retried rate is in the same RS |
---|
| 3270 | + * table as active/search. |
---|
| 3271 | + */ |
---|
| 3272 | + if (rs_rate_column_match(&lq_rate, &curr_tbl->rate)) |
---|
| 3273 | + tmp_tbl = curr_tbl; |
---|
| 3274 | + else if (rs_rate_column_match(&lq_rate, |
---|
| 3275 | + &other_tbl->rate)) |
---|
| 3276 | + tmp_tbl = other_tbl; |
---|
| 3277 | + else |
---|
| 3278 | + continue; |
---|
| 3279 | + |
---|
| 3280 | + rs_collect_tpc_data(mvm, lq_sta, tmp_tbl, |
---|
| 3281 | + tx_resp_rate.index, 1, |
---|
| 3282 | + i < retries ? 0 : legacy_success, |
---|
| 3283 | + reduced_txp); |
---|
| 3284 | + rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl, |
---|
| 3285 | + tx_resp_rate.index, 1, |
---|
| 3286 | + i < retries ? 0 : legacy_success); |
---|
| 3287 | + } |
---|
| 3288 | + |
---|
| 3289 | + /* Update success/fail counts if not searching for new mode */ |
---|
| 3290 | + if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { |
---|
| 3291 | + lq_sta->total_success += legacy_success; |
---|
| 3292 | + lq_sta->total_failed += retries + (1 - legacy_success); |
---|
| 3293 | + } |
---|
| 3294 | + } |
---|
| 3295 | + /* The last TX rate is cached in lq_sta; it's set in if/else above */ |
---|
| 3296 | + lq_sta->last_rate_n_flags = lq_hwrate; |
---|
| 3297 | + IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); |
---|
| 3298 | +done: |
---|
| 3299 | + /* See if there's a better rate or modulation mode to try. */ |
---|
| 3300 | + if (sta->supp_rates[info->band]) |
---|
| 3301 | + rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp); |
---|
| 3302 | +} |
---|
| 3303 | + |
---|
| 3304 | +void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
---|
| 3305 | + int tid, struct ieee80211_tx_info *info, bool ndp) |
---|
| 3306 | +{ |
---|
| 3307 | + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
---|
| 3308 | + |
---|
| 3309 | + /* If it's locked we are in middle of init flow |
---|
| 3310 | + * just wait for next tx status to update the lq_sta data |
---|
| 3311 | + */ |
---|
| 3312 | + if (!spin_trylock(&mvmsta->lq_sta.rs_drv.pers.lock)) |
---|
| 3313 | + return; |
---|
| 3314 | + |
---|
| 3315 | + __iwl_mvm_rs_tx_status(mvm, sta, tid, info, ndp); |
---|
| 3316 | + spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock); |
---|
3257 | 3317 | } |
---|
3258 | 3318 | |
---|
3259 | 3319 | #ifdef CONFIG_MAC80211_DEBUGFS |
---|
.. | .. |
---|
3286 | 3346 | if (num_of_ant(ant) == 1) |
---|
3287 | 3347 | lq_cmd->single_stream_ant_msk = ant; |
---|
3288 | 3348 | |
---|
3289 | | - if (!mvm->trans->cfg->gen2) |
---|
| 3349 | + if (!mvm->trans->trans_cfg->gen2) |
---|
3290 | 3350 | lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
---|
3291 | 3351 | else |
---|
3292 | 3352 | lq_cmd->agg_frame_cnt_limit = |
---|
.. | .. |
---|
3332 | 3392 | /* Building the rate table is non trivial. When we're in MIMO2/VHT/80Mhz/SGI |
---|
3333 | 3393 | * column the rate table should look like this: |
---|
3334 | 3394 | * |
---|
3335 | | - * rate[0] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI |
---|
3336 | | - * rate[1] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI |
---|
3337 | | - * rate[2] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI |
---|
3338 | | - * rate[3] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI |
---|
3339 | | - * rate[4] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI |
---|
3340 | | - * rate[5] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI |
---|
| 3395 | + * rate[0] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI |
---|
| 3396 | + * rate[1] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI |
---|
| 3397 | + * rate[2] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI |
---|
| 3398 | + * rate[3] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI |
---|
| 3399 | + * rate[4] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI |
---|
| 3400 | + * rate[5] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI |
---|
3341 | 3401 | * rate[6] 0x4005007 VHT | ANT: A BW: 80Mhz MCS: 7 NSS: 1 NGI |
---|
3342 | 3402 | * rate[7] 0x4009006 VHT | ANT: B BW: 80Mhz MCS: 6 NSS: 1 NGI |
---|
3343 | 3403 | * rate[8] 0x4005005 VHT | ANT: A BW: 80Mhz MCS: 5 NSS: 1 NGI |
---|
.. | .. |
---|
3547 | 3607 | |
---|
3548 | 3608 | bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED; |
---|
3549 | 3609 | bfersta_lq_cmd->ss_params = cpu_to_le32(bfersta_ss_params); |
---|
3550 | | - iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd, false); |
---|
| 3610 | + iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd); |
---|
3551 | 3611 | |
---|
3552 | 3612 | ss_params |= LQ_SS_BFER_ALLOWED; |
---|
3553 | 3613 | IWL_DEBUG_RATE(mvm, |
---|
.. | .. |
---|
3590 | 3650 | mvmsta = iwl_mvm_sta_from_mac80211(sta); |
---|
3591 | 3651 | mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); |
---|
3592 | 3652 | |
---|
3593 | | - if (num_of_ant(initial_rate->ant) == 1) |
---|
| 3653 | + if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2) && |
---|
| 3654 | + num_of_ant(initial_rate->ant) == 1) |
---|
3594 | 3655 | lq_cmd->single_stream_ant_msk = initial_rate->ant; |
---|
3595 | 3656 | |
---|
3596 | 3657 | lq_cmd->agg_frame_cnt_limit = mvmsta->max_agg_bufsize; |
---|
.. | .. |
---|
3610 | 3671 | cpu_to_le16(iwl_mvm_coex_agg_time_limit(mvm, sta)); |
---|
3611 | 3672 | } |
---|
3612 | 3673 | |
---|
3613 | | -static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
---|
| 3674 | +static void *rs_alloc(struct ieee80211_hw *hw) |
---|
3614 | 3675 | { |
---|
3615 | 3676 | return hw->priv; |
---|
3616 | 3677 | } |
---|
.. | .. |
---|
3630 | 3691 | IWL_DEBUG_RATE(mvm, "leave\n"); |
---|
3631 | 3692 | } |
---|
3632 | 3693 | |
---|
3633 | | -#ifdef CONFIG_MAC80211_DEBUGFS |
---|
3634 | 3694 | int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate) |
---|
3635 | 3695 | { |
---|
3636 | 3696 | |
---|
.. | .. |
---|
3643 | 3703 | !(rate & RATE_MCS_HE_MSK)) { |
---|
3644 | 3704 | int index = iwl_hwrate_to_plcp_idx(rate); |
---|
3645 | 3705 | |
---|
3646 | | - return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps\n", |
---|
| 3706 | + return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps", |
---|
3647 | 3707 | rs_pretty_ant(ant), |
---|
3648 | 3708 | index == IWL_RATE_INVALID ? "BAD" : |
---|
3649 | 3709 | iwl_rate_mcs[index].mbps); |
---|
.. | .. |
---|
3686 | 3746 | } |
---|
3687 | 3747 | |
---|
3688 | 3748 | return scnprintf(buf, bufsz, |
---|
3689 | | - "%s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s\n", |
---|
3690 | | - type, rs_pretty_ant(ant), bw, mcs, nss, |
---|
| 3749 | + "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s", |
---|
| 3750 | + rate, type, rs_pretty_ant(ant), bw, mcs, nss, |
---|
3691 | 3751 | (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ", |
---|
3692 | 3752 | (rate & RATE_MCS_STBC_MSK) ? "STBC " : "", |
---|
3693 | 3753 | (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", |
---|
| 3754 | + (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "", |
---|
3694 | 3755 | (rate & RATE_MCS_BF_MSK) ? "BF " : ""); |
---|
3695 | 3756 | } |
---|
3696 | 3757 | |
---|
| 3758 | +#ifdef CONFIG_MAC80211_DEBUGFS |
---|
3697 | 3759 | /** |
---|
3698 | 3760 | * Program the device to use fixed rate for frame transmit |
---|
3699 | 3761 | * This is for debugging/testing only |
---|
.. | .. |
---|
3712 | 3774 | |
---|
3713 | 3775 | if (lq_sta->pers.dbg_fixed_rate) { |
---|
3714 | 3776 | rs_fill_lq_cmd(mvm, NULL, lq_sta, NULL); |
---|
3715 | | - iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq, false); |
---|
| 3777 | + iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq); |
---|
3716 | 3778 | } |
---|
3717 | 3779 | } |
---|
3718 | 3780 | |
---|
.. | .. |
---|
3833 | 3895 | desc += scnprintf(buff + desc, bufsz - desc, |
---|
3834 | 3896 | " rate[%d] 0x%X ", i, r); |
---|
3835 | 3897 | desc += rs_pretty_print_rate(buff + desc, bufsz - desc, r); |
---|
| 3898 | + if (desc < bufsz - 1) |
---|
| 3899 | + buff[desc++] = '\n'; |
---|
3836 | 3900 | } |
---|
3837 | 3901 | |
---|
3838 | 3902 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); |
---|
.. | .. |
---|
4040 | 4104 | #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ |
---|
4041 | 4105 | _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_lq_sta) |
---|
4042 | 4106 | #define MVM_DEBUGFS_ADD_FILE_RS(name, parent, mode) do { \ |
---|
4043 | | - if (!debugfs_create_file(#name, mode, parent, lq_sta, \ |
---|
4044 | | - &iwl_dbgfs_##name##_ops)) \ |
---|
4045 | | - goto err; \ |
---|
| 4107 | + debugfs_create_file(#name, mode, parent, lq_sta, \ |
---|
| 4108 | + &iwl_dbgfs_##name##_ops); \ |
---|
4046 | 4109 | } while (0) |
---|
4047 | 4110 | |
---|
4048 | 4111 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32); |
---|
.. | .. |
---|
4070 | 4133 | &lq_sta->pers.dbg_fixed_txp_reduction); |
---|
4071 | 4134 | |
---|
4072 | 4135 | MVM_DEBUGFS_ADD_FILE_RS(ss_force, dir, 0600); |
---|
4073 | | - return; |
---|
4074 | | -err: |
---|
4075 | | - IWL_ERR((struct iwl_mvm *)mvm, "Can't create debugfs entity\n"); |
---|
4076 | | -} |
---|
4077 | | - |
---|
4078 | | -void rs_remove_sta_debugfs(void *mvm, void *mvm_sta) |
---|
4079 | | -{ |
---|
4080 | 4136 | } |
---|
4081 | 4137 | #endif |
---|
4082 | 4138 | |
---|
.. | .. |
---|
4105 | 4161 | .rate_update = rs_drv_rate_update, |
---|
4106 | 4162 | #ifdef CONFIG_MAC80211_DEBUGFS |
---|
4107 | 4163 | .add_sta_debugfs = rs_drv_add_sta_debugfs, |
---|
4108 | | - .remove_sta_debugfs = rs_remove_sta_debugfs, |
---|
4109 | 4164 | #endif |
---|
| 4165 | + .capa = RATE_CTRL_CAPA_VHT_EXT_NSS_BW, |
---|
4110 | 4166 | }; |
---|
4111 | 4167 | |
---|
4112 | 4168 | void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
---|
4113 | 4169 | enum nl80211_band band, bool update) |
---|
4114 | 4170 | { |
---|
4115 | | - if (iwl_mvm_has_tlc_offload(mvm)) |
---|
| 4171 | + if (iwl_mvm_has_tlc_offload(mvm)) { |
---|
4116 | 4172 | rs_fw_rate_init(mvm, sta, band, update); |
---|
4117 | | - else |
---|
4118 | | - rs_drv_rate_init(mvm, sta, band, update); |
---|
| 4173 | + } else { |
---|
| 4174 | + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
---|
| 4175 | + |
---|
| 4176 | + spin_lock(&mvmsta->lq_sta.rs_drv.pers.lock); |
---|
| 4177 | + rs_drv_rate_init(mvm, sta, band); |
---|
| 4178 | + spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock); |
---|
| 4179 | + } |
---|
4119 | 4180 | } |
---|
4120 | 4181 | |
---|
4121 | 4182 | int iwl_mvm_rate_control_register(void) |
---|
.. | .. |
---|
4145 | 4206 | lq->flags &= ~LQ_FLAG_USE_RTS_MSK; |
---|
4146 | 4207 | } |
---|
4147 | 4208 | |
---|
4148 | | - return iwl_mvm_send_lq_cmd(mvm, lq, false); |
---|
| 4209 | + return iwl_mvm_send_lq_cmd(mvm, lq); |
---|
4149 | 4210 | } |
---|
4150 | 4211 | |
---|
4151 | 4212 | /** |
---|