diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rs.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 294 |
1 files changed, 259 insertions, 35 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index a4563389bad..57629fba3a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -82,7 +82,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
82 | struct iwl_lq_sta *lq_sta); | 82 | struct iwl_lq_sta *lq_sta); |
83 | static void rs_fill_link_cmd(struct iwl_priv *priv, | 83 | static void rs_fill_link_cmd(struct iwl_priv *priv, |
84 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); | 84 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); |
85 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta); | 85 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); |
86 | 86 | ||
87 | 87 | ||
88 | #ifdef CONFIG_MAC80211_DEBUGFS | 88 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -301,7 +301,19 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
301 | struct ieee80211_sta *sta) | 301 | struct ieee80211_sta *sta) |
302 | { | 302 | { |
303 | int ret = -EAGAIN; | 303 | int ret = -EAGAIN; |
304 | u32 load = rs_tl_get_load(lq_data, tid); | 304 | u32 load; |
305 | |||
306 | /* | ||
307 | * Don't create TX aggregation sessions when in high | ||
308 | * BT traffic, as they would just be disrupted by BT. | ||
309 | */ | ||
310 | if (priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) { | ||
311 | IWL_ERR(priv, "BT traffic (%d), no aggregation allowed\n", | ||
312 | priv->bt_traffic_load); | ||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | load = rs_tl_get_load(lq_data, tid); | ||
305 | 317 | ||
306 | if (load > IWL_AGG_LOAD_THRESHOLD) { | 318 | if (load > IWL_AGG_LOAD_THRESHOLD) { |
307 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", | 319 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", |
@@ -590,11 +602,13 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
590 | * Green-field mode is valid if the station supports it and | 602 | * Green-field mode is valid if the station supports it and |
591 | * there are no non-GF stations present in the BSS. | 603 | * there are no non-GF stations present in the BSS. |
592 | */ | 604 | */ |
593 | static inline u8 rs_use_green(struct ieee80211_sta *sta, | 605 | static bool rs_use_green(struct ieee80211_sta *sta) |
594 | struct iwl_ht_config *ht_conf) | ||
595 | { | 606 | { |
607 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
608 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | ||
609 | |||
596 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && | 610 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && |
597 | !(ht_conf->non_GF_STA_present); | 611 | !(ctx->ht.non_gf_sta_present); |
598 | } | 612 | } |
599 | 613 | ||
600 | /** | 614 | /** |
@@ -746,6 +760,32 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a, | |||
746 | (a->is_SGI == b->is_SGI); | 760 | (a->is_SGI == b->is_SGI); |
747 | } | 761 | } |
748 | 762 | ||
763 | static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | ||
764 | struct iwl_lq_sta *lq_sta) | ||
765 | { | ||
766 | struct iwl_scale_tbl_info *tbl; | ||
767 | bool full_concurrent; | ||
768 | unsigned long flags; | ||
769 | |||
770 | spin_lock_irqsave(&priv->lock, flags); | ||
771 | if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) | ||
772 | full_concurrent = true; | ||
773 | else | ||
774 | full_concurrent = false; | ||
775 | spin_unlock_irqrestore(&priv->lock, flags); | ||
776 | |||
777 | if (priv->bt_full_concurrent != full_concurrent) { | ||
778 | priv->bt_full_concurrent = full_concurrent; | ||
779 | |||
780 | /* Update uCode's rate table. */ | ||
781 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | ||
782 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); | ||
783 | iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); | ||
784 | |||
785 | queue_work(priv->workqueue, &priv->bt_full_concurrency); | ||
786 | } | ||
787 | } | ||
788 | |||
749 | /* | 789 | /* |
750 | * mac80211 sends us Tx status | 790 | * mac80211 sends us Tx status |
751 | */ | 791 | */ |
@@ -765,6 +805,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
765 | u32 tx_rate; | 805 | u32 tx_rate; |
766 | struct iwl_scale_tbl_info tbl_type; | 806 | struct iwl_scale_tbl_info tbl_type; |
767 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; | 807 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
808 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
809 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | ||
768 | 810 | ||
769 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 811 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
770 | 812 | ||
@@ -831,7 +873,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
831 | lq_sta->missed_rate_counter++; | 873 | lq_sta->missed_rate_counter++; |
832 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { | 874 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { |
833 | lq_sta->missed_rate_counter = 0; | 875 | lq_sta->missed_rate_counter = 0; |
834 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); | 876 | iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); |
835 | } | 877 | } |
836 | /* Regardless, ignore this status info for outdated rate */ | 878 | /* Regardless, ignore this status info for outdated rate */ |
837 | return; | 879 | return; |
@@ -862,7 +904,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
862 | * no matching table found, let's by-pass the data collection | 904 | * no matching table found, let's by-pass the data collection |
863 | * and continue to perform rate scale to find the rate table | 905 | * and continue to perform rate scale to find the rate table |
864 | */ | 906 | */ |
865 | rs_stay_in_table(lq_sta); | 907 | rs_stay_in_table(lq_sta, true); |
866 | goto done; | 908 | goto done; |
867 | } | 909 | } |
868 | 910 | ||
@@ -928,6 +970,10 @@ done: | |||
928 | /* See if there's a better rate or modulation mode to try. */ | 970 | /* See if there's a better rate or modulation mode to try. */ |
929 | if (sta && sta->supp_rates[sband->band]) | 971 | if (sta && sta->supp_rates[sband->band]) |
930 | rs_rate_scale_perform(priv, skb, sta, lq_sta); | 972 | rs_rate_scale_perform(priv, skb, sta, lq_sta); |
973 | |||
974 | /* Is there a need to switch between full concurrency and 3-wire? */ | ||
975 | if (priv->bt_ant_couple_ok) | ||
976 | rs_bt_update_lq(priv, ctx, lq_sta); | ||
931 | } | 977 | } |
932 | 978 | ||
933 | /* | 979 | /* |
@@ -1121,6 +1167,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, | |||
1121 | u16 rate_mask; | 1167 | u16 rate_mask; |
1122 | s32 rate; | 1168 | s32 rate; |
1123 | s8 is_green = lq_sta->is_green; | 1169 | s8 is_green = lq_sta->is_green; |
1170 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
1171 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | ||
1124 | 1172 | ||
1125 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) | 1173 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) |
1126 | return -1; | 1174 | return -1; |
@@ -1141,7 +1189,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, | |||
1141 | tbl->max_search = IWL_MAX_SEARCH; | 1189 | tbl->max_search = IWL_MAX_SEARCH; |
1142 | rate_mask = lq_sta->active_mimo2_rate; | 1190 | rate_mask = lq_sta->active_mimo2_rate; |
1143 | 1191 | ||
1144 | if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap)) | 1192 | if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) |
1145 | tbl->is_ht40 = 1; | 1193 | tbl->is_ht40 = 1; |
1146 | else | 1194 | else |
1147 | tbl->is_ht40 = 0; | 1195 | tbl->is_ht40 = 0; |
@@ -1175,6 +1223,8 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, | |||
1175 | u16 rate_mask; | 1223 | u16 rate_mask; |
1176 | s32 rate; | 1224 | s32 rate; |
1177 | s8 is_green = lq_sta->is_green; | 1225 | s8 is_green = lq_sta->is_green; |
1226 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
1227 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | ||
1178 | 1228 | ||
1179 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) | 1229 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) |
1180 | return -1; | 1230 | return -1; |
@@ -1195,7 +1245,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, | |||
1195 | tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; | 1245 | tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; |
1196 | rate_mask = lq_sta->active_mimo3_rate; | 1246 | rate_mask = lq_sta->active_mimo3_rate; |
1197 | 1247 | ||
1198 | if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap)) | 1248 | if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) |
1199 | tbl->is_ht40 = 1; | 1249 | tbl->is_ht40 = 1; |
1200 | else | 1250 | else |
1201 | tbl->is_ht40 = 0; | 1251 | tbl->is_ht40 = 0; |
@@ -1230,6 +1280,8 @@ static int rs_switch_to_siso(struct iwl_priv *priv, | |||
1230 | u16 rate_mask; | 1280 | u16 rate_mask; |
1231 | u8 is_green = lq_sta->is_green; | 1281 | u8 is_green = lq_sta->is_green; |
1232 | s32 rate; | 1282 | s32 rate; |
1283 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
1284 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | ||
1233 | 1285 | ||
1234 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) | 1286 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) |
1235 | return -1; | 1287 | return -1; |
@@ -1242,7 +1294,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, | |||
1242 | tbl->max_search = IWL_MAX_SEARCH; | 1294 | tbl->max_search = IWL_MAX_SEARCH; |
1243 | rate_mask = lq_sta->active_siso_rate; | 1295 | rate_mask = lq_sta->active_siso_rate; |
1244 | 1296 | ||
1245 | if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap)) | 1297 | if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) |
1246 | tbl->is_ht40 = 1; | 1298 | tbl->is_ht40 = 1; |
1247 | else | 1299 | else |
1248 | tbl->is_ht40 = 0; | 1300 | tbl->is_ht40 = 0; |
@@ -1286,12 +1338,45 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1286 | int ret = 0; | 1338 | int ret = 0; |
1287 | u8 update_search_tbl_counter = 0; | 1339 | u8 update_search_tbl_counter = 0; |
1288 | 1340 | ||
1341 | switch (priv->bt_traffic_load) { | ||
1342 | case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | ||
1343 | /* nothing */ | ||
1344 | break; | ||
1345 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | ||
1346 | /* avoid antenna B unless MIMO */ | ||
1347 | valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); | ||
1348 | if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2) | ||
1349 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | ||
1350 | break; | ||
1351 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | ||
1352 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||
1353 | /* avoid antenna B and MIMO */ | ||
1354 | valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); | ||
1355 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && | ||
1356 | tbl->action != IWL_LEGACY_SWITCH_SISO) | ||
1357 | tbl->action = IWL_LEGACY_SWITCH_SISO; | ||
1358 | break; | ||
1359 | default: | ||
1360 | IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); | ||
1361 | break; | ||
1362 | } | ||
1363 | |||
1289 | if (!iwl_ht_enabled(priv)) | 1364 | if (!iwl_ht_enabled(priv)) |
1290 | /* stay in Legacy */ | 1365 | /* stay in Legacy */ |
1291 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | 1366 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; |
1292 | else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && | 1367 | else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && |
1293 | tbl->action > IWL_LEGACY_SWITCH_SISO) | 1368 | tbl->action > IWL_LEGACY_SWITCH_SISO) |
1294 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1369 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
1370 | |||
1371 | /* configure as 1x1 if bt full concurrency */ | ||
1372 | if (priv->bt_full_concurrent) { | ||
1373 | if (!iwl_ht_enabled(priv)) | ||
1374 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | ||
1375 | else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | ||
1376 | tbl->action = IWL_LEGACY_SWITCH_SISO; | ||
1377 | valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); | ||
1378 | } | ||
1379 | |||
1295 | start_action = tbl->action; | 1380 | start_action = tbl->action; |
1296 | for (; ;) { | 1381 | for (; ;) { |
1297 | lq_sta->action_counter++; | 1382 | lq_sta->action_counter++; |
@@ -1307,7 +1392,10 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1307 | break; | 1392 | break; |
1308 | 1393 | ||
1309 | /* Don't change antenna if success has been great */ | 1394 | /* Don't change antenna if success has been great */ |
1310 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) | 1395 | if (window->success_ratio >= IWL_RS_GOOD_RATIO && |
1396 | !priv->bt_full_concurrent && | ||
1397 | priv->bt_traffic_load == | ||
1398 | IWL_BT_COEX_TRAFFIC_LOAD_NONE) | ||
1311 | break; | 1399 | break; |
1312 | 1400 | ||
1313 | /* Set up search table to try other antenna */ | 1401 | /* Set up search table to try other antenna */ |
@@ -1425,11 +1513,41 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1425 | u8 update_search_tbl_counter = 0; | 1513 | u8 update_search_tbl_counter = 0; |
1426 | int ret; | 1514 | int ret; |
1427 | 1515 | ||
1516 | switch (priv->bt_traffic_load) { | ||
1517 | case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | ||
1518 | /* nothing */ | ||
1519 | break; | ||
1520 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | ||
1521 | /* avoid antenna B unless MIMO */ | ||
1522 | valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); | ||
1523 | if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) | ||
1524 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||
1525 | break; | ||
1526 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | ||
1527 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||
1528 | /* avoid antenna B and MIMO */ | ||
1529 | valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); | ||
1530 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) | ||
1531 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||
1532 | break; | ||
1533 | default: | ||
1534 | IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); | ||
1535 | break; | ||
1536 | } | ||
1537 | |||
1428 | if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && | 1538 | if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && |
1429 | tbl->action > IWL_SISO_SWITCH_ANTENNA2) { | 1539 | tbl->action > IWL_SISO_SWITCH_ANTENNA2) { |
1430 | /* stay in SISO */ | 1540 | /* stay in SISO */ |
1431 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1541 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1432 | } | 1542 | } |
1543 | |||
1544 | /* configure as 1x1 if bt full concurrency */ | ||
1545 | if (priv->bt_full_concurrent) { | ||
1546 | valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); | ||
1547 | if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | ||
1548 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||
1549 | } | ||
1550 | |||
1433 | start_action = tbl->action; | 1551 | start_action = tbl->action; |
1434 | for (;;) { | 1552 | for (;;) { |
1435 | lq_sta->action_counter++; | 1553 | lq_sta->action_counter++; |
@@ -1437,14 +1555,16 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1437 | case IWL_SISO_SWITCH_ANTENNA1: | 1555 | case IWL_SISO_SWITCH_ANTENNA1: |
1438 | case IWL_SISO_SWITCH_ANTENNA2: | 1556 | case IWL_SISO_SWITCH_ANTENNA2: |
1439 | IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n"); | 1557 | IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n"); |
1440 | |||
1441 | if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && | 1558 | if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && |
1442 | tx_chains_num <= 1) || | 1559 | tx_chains_num <= 1) || |
1443 | (tbl->action == IWL_SISO_SWITCH_ANTENNA2 && | 1560 | (tbl->action == IWL_SISO_SWITCH_ANTENNA2 && |
1444 | tx_chains_num <= 2)) | 1561 | tx_chains_num <= 2)) |
1445 | break; | 1562 | break; |
1446 | 1563 | ||
1447 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) | 1564 | if (window->success_ratio >= IWL_RS_GOOD_RATIO && |
1565 | !priv->bt_full_concurrent && | ||
1566 | priv->bt_traffic_load == | ||
1567 | IWL_BT_COEX_TRAFFIC_LOAD_NONE) | ||
1448 | break; | 1568 | break; |
1449 | 1569 | ||
1450 | memcpy(search_tbl, tbl, sz); | 1570 | memcpy(search_tbl, tbl, sz); |
@@ -1564,12 +1684,40 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1564 | u8 update_search_tbl_counter = 0; | 1684 | u8 update_search_tbl_counter = 0; |
1565 | int ret; | 1685 | int ret; |
1566 | 1686 | ||
1687 | switch (priv->bt_traffic_load) { | ||
1688 | case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | ||
1689 | /* nothing */ | ||
1690 | break; | ||
1691 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | ||
1692 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||
1693 | /* avoid antenna B and MIMO */ | ||
1694 | if (tbl->action != IWL_MIMO2_SWITCH_SISO_A) | ||
1695 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | ||
1696 | break; | ||
1697 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | ||
1698 | /* avoid antenna B unless MIMO */ | ||
1699 | if (tbl->action == IWL_MIMO2_SWITCH_SISO_B || | ||
1700 | tbl->action == IWL_MIMO2_SWITCH_SISO_C) | ||
1701 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | ||
1702 | break; | ||
1703 | default: | ||
1704 | IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); | ||
1705 | break; | ||
1706 | } | ||
1707 | |||
1567 | if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) && | 1708 | if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) && |
1568 | (tbl->action < IWL_MIMO2_SWITCH_SISO_A || | 1709 | (tbl->action < IWL_MIMO2_SWITCH_SISO_A || |
1569 | tbl->action > IWL_MIMO2_SWITCH_SISO_C)) { | 1710 | tbl->action > IWL_MIMO2_SWITCH_SISO_C)) { |
1570 | /* switch in SISO */ | 1711 | /* switch in SISO */ |
1571 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | 1712 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; |
1572 | } | 1713 | } |
1714 | |||
1715 | /* configure as 1x1 if bt full concurrency */ | ||
1716 | if (priv->bt_full_concurrent && | ||
1717 | (tbl->action < IWL_MIMO2_SWITCH_SISO_A || | ||
1718 | tbl->action > IWL_MIMO2_SWITCH_SISO_C)) | ||
1719 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | ||
1720 | |||
1573 | start_action = tbl->action; | 1721 | start_action = tbl->action; |
1574 | for (;;) { | 1722 | for (;;) { |
1575 | lq_sta->action_counter++; | 1723 | lq_sta->action_counter++; |
@@ -1706,12 +1854,40 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1706 | int ret; | 1854 | int ret; |
1707 | u8 update_search_tbl_counter = 0; | 1855 | u8 update_search_tbl_counter = 0; |
1708 | 1856 | ||
1857 | switch (priv->bt_traffic_load) { | ||
1858 | case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | ||
1859 | /* nothing */ | ||
1860 | break; | ||
1861 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | ||
1862 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||
1863 | /* avoid antenna B and MIMO */ | ||
1864 | if (tbl->action != IWL_MIMO3_SWITCH_SISO_A) | ||
1865 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; | ||
1866 | break; | ||
1867 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | ||
1868 | /* avoid antenna B unless MIMO */ | ||
1869 | if (tbl->action == IWL_MIMO3_SWITCH_SISO_B || | ||
1870 | tbl->action == IWL_MIMO3_SWITCH_SISO_C) | ||
1871 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; | ||
1872 | break; | ||
1873 | default: | ||
1874 | IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); | ||
1875 | break; | ||
1876 | } | ||
1877 | |||
1709 | if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) && | 1878 | if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) && |
1710 | (tbl->action < IWL_MIMO3_SWITCH_SISO_A || | 1879 | (tbl->action < IWL_MIMO3_SWITCH_SISO_A || |
1711 | tbl->action > IWL_MIMO3_SWITCH_SISO_C)) { | 1880 | tbl->action > IWL_MIMO3_SWITCH_SISO_C)) { |
1712 | /* switch in SISO */ | 1881 | /* switch in SISO */ |
1713 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; | 1882 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; |
1714 | } | 1883 | } |
1884 | |||
1885 | /* configure as 1x1 if bt full concurrency */ | ||
1886 | if (priv->bt_full_concurrent && | ||
1887 | (tbl->action < IWL_MIMO3_SWITCH_SISO_A || | ||
1888 | tbl->action > IWL_MIMO3_SWITCH_SISO_C)) | ||
1889 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; | ||
1890 | |||
1715 | start_action = tbl->action; | 1891 | start_action = tbl->action; |
1716 | for (;;) { | 1892 | for (;;) { |
1717 | lq_sta->action_counter++; | 1893 | lq_sta->action_counter++; |
@@ -1839,7 +2015,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1839 | * 2) # times calling this function | 2015 | * 2) # times calling this function |
1840 | * 3) elapsed time in this mode (not used, for now) | 2016 | * 3) elapsed time in this mode (not used, for now) |
1841 | */ | 2017 | */ |
1842 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) | 2018 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) |
1843 | { | 2019 | { |
1844 | struct iwl_scale_tbl_info *tbl; | 2020 | struct iwl_scale_tbl_info *tbl; |
1845 | int i; | 2021 | int i; |
@@ -1870,7 +2046,8 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) | |||
1870 | * allow a new search. Also (below) reset all bitmaps and | 2046 | * allow a new search. Also (below) reset all bitmaps and |
1871 | * stats in active history. | 2047 | * stats in active history. |
1872 | */ | 2048 | */ |
1873 | if ((lq_sta->total_failed > lq_sta->max_failure_limit) || | 2049 | if (force_search || |
2050 | (lq_sta->total_failed > lq_sta->max_failure_limit) || | ||
1874 | (lq_sta->total_success > lq_sta->max_success_limit) || | 2051 | (lq_sta->total_success > lq_sta->max_success_limit) || |
1875 | ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer) | 2052 | ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer) |
1876 | && (flush_interval_passed))) { | 2053 | && (flush_interval_passed))) { |
@@ -1919,6 +2096,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) | |||
1919 | * return rate_n_flags as used in the table | 2096 | * return rate_n_flags as used in the table |
1920 | */ | 2097 | */ |
1921 | static u32 rs_update_rate_tbl(struct iwl_priv *priv, | 2098 | static u32 rs_update_rate_tbl(struct iwl_priv *priv, |
2099 | struct iwl_rxon_context *ctx, | ||
1922 | struct iwl_lq_sta *lq_sta, | 2100 | struct iwl_lq_sta *lq_sta, |
1923 | struct iwl_scale_tbl_info *tbl, | 2101 | struct iwl_scale_tbl_info *tbl, |
1924 | int index, u8 is_green) | 2102 | int index, u8 is_green) |
@@ -1928,7 +2106,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, | |||
1928 | /* Update uCode's rate table. */ | 2106 | /* Update uCode's rate table. */ |
1929 | rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); | 2107 | rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); |
1930 | rs_fill_link_cmd(priv, lq_sta, rate); | 2108 | rs_fill_link_cmd(priv, lq_sta, rate); |
1931 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); | 2109 | iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); |
1932 | 2110 | ||
1933 | return rate; | 2111 | return rate; |
1934 | } | 2112 | } |
@@ -1967,6 +2145,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1967 | s32 sr; | 2145 | s32 sr; |
1968 | u8 tid = MAX_TID_COUNT; | 2146 | u8 tid = MAX_TID_COUNT; |
1969 | struct iwl_tid_data *tid_data; | 2147 | struct iwl_tid_data *tid_data; |
2148 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
2149 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | ||
1970 | 2150 | ||
1971 | IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); | 2151 | IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); |
1972 | 2152 | ||
@@ -2005,7 +2185,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2005 | if (is_legacy(tbl->lq_type)) | 2185 | if (is_legacy(tbl->lq_type)) |
2006 | lq_sta->is_green = 0; | 2186 | lq_sta->is_green = 0; |
2007 | else | 2187 | else |
2008 | lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); | 2188 | lq_sta->is_green = rs_use_green(sta); |
2009 | is_green = lq_sta->is_green; | 2189 | is_green = lq_sta->is_green; |
2010 | 2190 | ||
2011 | /* current tx rate */ | 2191 | /* current tx rate */ |
@@ -2044,7 +2224,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2044 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 2224 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
2045 | /* get "active" rate info */ | 2225 | /* get "active" rate info */ |
2046 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); | 2226 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); |
2047 | rate = rs_update_rate_tbl(priv, lq_sta, | 2227 | rate = rs_update_rate_tbl(priv, ctx, lq_sta, |
2048 | tbl, index, is_green); | 2228 | tbl, index, is_green); |
2049 | } | 2229 | } |
2050 | return; | 2230 | return; |
@@ -2086,7 +2266,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2086 | 2266 | ||
2087 | /* Should we stay with this modulation mode, | 2267 | /* Should we stay with this modulation mode, |
2088 | * or search for a new one? */ | 2268 | * or search for a new one? */ |
2089 | rs_stay_in_table(lq_sta); | 2269 | rs_stay_in_table(lq_sta, false); |
2090 | 2270 | ||
2091 | goto out; | 2271 | goto out; |
2092 | } | 2272 | } |
@@ -2234,6 +2414,28 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2234 | if (iwl_tx_ant_restriction(priv) != IWL_ANT_OK_MULTI && | 2414 | if (iwl_tx_ant_restriction(priv) != IWL_ANT_OK_MULTI && |
2235 | (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) | 2415 | (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) |
2236 | scale_action = -1; | 2416 | scale_action = -1; |
2417 | |||
2418 | if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && | ||
2419 | (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) { | ||
2420 | if (lq_sta->last_bt_traffic > priv->bt_traffic_load) { | ||
2421 | /* | ||
2422 | * don't set scale_action, don't want to scale up if | ||
2423 | * the rate scale doesn't otherwise think that is a | ||
2424 | * good idea. | ||
2425 | */ | ||
2426 | } else if (lq_sta->last_bt_traffic <= priv->bt_traffic_load) { | ||
2427 | scale_action = -1; | ||
2428 | } | ||
2429 | } | ||
2430 | lq_sta->last_bt_traffic = priv->bt_traffic_load; | ||
2431 | |||
2432 | if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && | ||
2433 | (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) { | ||
2434 | /* search for a new modulation */ | ||
2435 | rs_stay_in_table(lq_sta, true); | ||
2436 | goto lq_update; | ||
2437 | } | ||
2438 | |||
2237 | switch (scale_action) { | 2439 | switch (scale_action) { |
2238 | case -1: | 2440 | case -1: |
2239 | /* Decrease starting rate, update uCode's rate table */ | 2441 | /* Decrease starting rate, update uCode's rate table */ |
@@ -2264,13 +2466,13 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2264 | lq_update: | 2466 | lq_update: |
2265 | /* Replace uCode's rate table for the destination station. */ | 2467 | /* Replace uCode's rate table for the destination station. */ |
2266 | if (update_lq) | 2468 | if (update_lq) |
2267 | rate = rs_update_rate_tbl(priv, lq_sta, | 2469 | rate = rs_update_rate_tbl(priv, ctx, lq_sta, |
2268 | tbl, index, is_green); | 2470 | tbl, index, is_green); |
2269 | 2471 | ||
2270 | if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) { | 2472 | if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) { |
2271 | /* Should we stay with this modulation mode, | 2473 | /* Should we stay with this modulation mode, |
2272 | * or search for a new one? */ | 2474 | * or search for a new one? */ |
2273 | rs_stay_in_table(lq_sta); | 2475 | rs_stay_in_table(lq_sta, false); |
2274 | } | 2476 | } |
2275 | /* | 2477 | /* |
2276 | * Search for new modulation mode if we're: | 2478 | * Search for new modulation mode if we're: |
@@ -2306,7 +2508,7 @@ lq_update: | |||
2306 | IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", | 2508 | IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", |
2307 | tbl->current_rate, index); | 2509 | tbl->current_rate, index); |
2308 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); | 2510 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); |
2309 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); | 2511 | iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); |
2310 | } else | 2512 | } else |
2311 | done_search = 1; | 2513 | done_search = 1; |
2312 | } | 2514 | } |
@@ -2376,12 +2578,17 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2376 | int rate_idx; | 2578 | int rate_idx; |
2377 | int i; | 2579 | int i; |
2378 | u32 rate; | 2580 | u32 rate; |
2379 | u8 use_green = rs_use_green(sta, &priv->current_ht_config); | 2581 | u8 use_green = rs_use_green(sta); |
2380 | u8 active_tbl = 0; | 2582 | u8 active_tbl = 0; |
2381 | u8 valid_tx_ant; | 2583 | u8 valid_tx_ant; |
2584 | struct iwl_station_priv *sta_priv; | ||
2585 | struct iwl_rxon_context *ctx; | ||
2382 | 2586 | ||
2383 | if (!sta || !lq_sta) | 2587 | if (!sta || !lq_sta) |
2384 | goto out; | 2588 | return; |
2589 | |||
2590 | sta_priv = (void *)sta->drv_priv; | ||
2591 | ctx = sta_priv->common.ctx; | ||
2385 | 2592 | ||
2386 | i = lq_sta->last_txrate_idx; | 2593 | i = lq_sta->last_txrate_idx; |
2387 | 2594 | ||
@@ -2413,9 +2620,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2413 | rs_set_expected_tpt_table(lq_sta, tbl); | 2620 | rs_set_expected_tpt_table(lq_sta, tbl); |
2414 | rs_fill_link_cmd(NULL, lq_sta, rate); | 2621 | rs_fill_link_cmd(NULL, lq_sta, rate); |
2415 | priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; | 2622 | priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; |
2416 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true); | 2623 | iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true); |
2417 | out: | ||
2418 | return; | ||
2419 | } | 2624 | } |
2420 | 2625 | ||
2421 | static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | 2626 | static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, |
@@ -2543,7 +2748,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | |||
2543 | lq_sta->is_dup = 0; | 2748 | lq_sta->is_dup = 0; |
2544 | lq_sta->max_rate_idx = -1; | 2749 | lq_sta->max_rate_idx = -1; |
2545 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; | 2750 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; |
2546 | lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); | 2751 | lq_sta->is_green = rs_use_green(sta); |
2547 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); | 2752 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); |
2548 | lq_sta->band = priv->band; | 2753 | lq_sta->band = priv->band; |
2549 | /* | 2754 | /* |
@@ -2616,6 +2821,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2616 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, | 2821 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, |
2617 | &tbl_type, &rate_idx); | 2822 | &tbl_type, &rate_idx); |
2618 | 2823 | ||
2824 | if (priv && priv->bt_full_concurrent) { | ||
2825 | /* 1x1 only */ | ||
2826 | tbl_type.ant_type = | ||
2827 | first_antenna(priv->hw_params.valid_tx_ant); | ||
2828 | } | ||
2829 | |||
2619 | /* How many times should we repeat the initial rate? */ | 2830 | /* How many times should we repeat the initial rate? */ |
2620 | if (is_legacy(tbl_type.lq_type)) { | 2831 | if (is_legacy(tbl_type.lq_type)) { |
2621 | ant_toggle_cnt = 1; | 2832 | ant_toggle_cnt = 1; |
@@ -2640,9 +2851,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2640 | 2851 | ||
2641 | index++; | 2852 | index++; |
2642 | repeat_rate--; | 2853 | repeat_rate--; |
2643 | 2854 | if (priv) { | |
2644 | if (priv) | 2855 | if (priv->bt_full_concurrent) |
2645 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2856 | valid_tx_ant = ANT_A; |
2857 | else | ||
2858 | valid_tx_ant = priv->hw_params.valid_tx_ant; | ||
2859 | } | ||
2646 | 2860 | ||
2647 | /* Fill rest of rate table */ | 2861 | /* Fill rest of rate table */ |
2648 | while (index < LINK_QUAL_MAX_RETRY_NUM) { | 2862 | while (index < LINK_QUAL_MAX_RETRY_NUM) { |
@@ -2657,7 +2871,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2657 | rs_toggle_antenna(valid_tx_ant, | 2871 | rs_toggle_antenna(valid_tx_ant, |
2658 | &new_rate, &tbl_type)) | 2872 | &new_rate, &tbl_type)) |
2659 | ant_toggle_cnt = 1; | 2873 | ant_toggle_cnt = 1; |
2660 | } | 2874 | } |
2661 | 2875 | ||
2662 | /* Override next rate if needed for debug purposes */ | 2876 | /* Override next rate if needed for debug purposes */ |
2663 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); | 2877 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); |
@@ -2672,6 +2886,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2672 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, | 2886 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, |
2673 | &rate_idx); | 2887 | &rate_idx); |
2674 | 2888 | ||
2889 | if (priv && priv->bt_full_concurrent) { | ||
2890 | /* 1x1 only */ | ||
2891 | tbl_type.ant_type = | ||
2892 | first_antenna(priv->hw_params.valid_tx_ant); | ||
2893 | } | ||
2894 | |||
2675 | /* Indicate to uCode which entries might be MIMO. | 2895 | /* Indicate to uCode which entries might be MIMO. |
2676 | * If initial rate was MIMO, this will finally end up | 2896 | * If initial rate was MIMO, this will finally end up |
2677 | * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ | 2897 | * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ |
@@ -2788,6 +3008,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2788 | char buf[64]; | 3008 | char buf[64]; |
2789 | int buf_size; | 3009 | int buf_size; |
2790 | u32 parsed_rate; | 3010 | u32 parsed_rate; |
3011 | struct iwl_station_priv *sta_priv = | ||
3012 | container_of(lq_sta, struct iwl_station_priv, lq_sta); | ||
3013 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | ||
2791 | 3014 | ||
2792 | priv = lq_sta->drv; | 3015 | priv = lq_sta->drv; |
2793 | memset(buf, 0, sizeof(buf)); | 3016 | memset(buf, 0, sizeof(buf)); |
@@ -2810,7 +3033,8 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2810 | 3033 | ||
2811 | if (lq_sta->dbg_fixed_rate) { | 3034 | if (lq_sta->dbg_fixed_rate) { |
2812 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); | 3035 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); |
2813 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); | 3036 | iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, |
3037 | false); | ||
2814 | } | 3038 | } |
2815 | 3039 | ||
2816 | return count; | 3040 | return count; |