diff options
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 74 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 5 |
3 files changed, 56 insertions, 29 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h index 0036d18334af..ba3f0bbddde8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h | |||
| @@ -510,6 +510,9 @@ struct iwl_mvm_tx_resp { | |||
| 510 | * @scd_ssn: the index of the last contiguously sent packet | 510 | * @scd_ssn: the index of the last contiguously sent packet |
| 511 | * @txed: number of Txed frames in this batch | 511 | * @txed: number of Txed frames in this batch |
| 512 | * @txed_2_done: number of Acked frames in this batch | 512 | * @txed_2_done: number of Acked frames in this batch |
| 513 | * @reduced_txp: power reduced according to TPC. This is the actual value and | ||
| 514 | * not a copy from the LQ command. Thus, if not the first rate was used | ||
| 515 | * for Tx-ing then this value will be set to 0 by FW. | ||
| 513 | */ | 516 | */ |
| 514 | struct iwl_mvm_ba_notif { | 517 | struct iwl_mvm_ba_notif { |
| 515 | __le32 sta_addr_lo32; | 518 | __le32 sta_addr_lo32; |
| @@ -524,7 +527,8 @@ struct iwl_mvm_ba_notif { | |||
| 524 | __le16 scd_ssn; | 527 | __le16 scd_ssn; |
| 525 | u8 txed; | 528 | u8 txed; |
| 526 | u8 txed_2_done; | 529 | u8 txed_2_done; |
| 527 | __le16 reserved1; | 530 | u8 reduced_txp; |
| 531 | u8 reserved1; | ||
| 528 | } __packed; | 532 | } __packed; |
| 529 | 533 | ||
| 530 | /* | 534 | /* |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 7bb6fd0e4391..94caa88df442 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * | 2 | * |
| 3 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
| 4 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 4 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 5 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
| 5 | * | 6 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms of version 2 of the GNU General Public License as | 8 | * under the terms of version 2 of the GNU General Public License as |
| @@ -724,14 +725,28 @@ static int _rs_collect_tx_data(struct iwl_mvm *mvm, | |||
| 724 | return 0; | 725 | return 0; |
| 725 | } | 726 | } |
| 726 | 727 | ||
| 727 | static int rs_collect_tx_data(struct iwl_mvm *mvm, | 728 | static int rs_collect_tpc_data(struct iwl_mvm *mvm, |
| 728 | struct iwl_lq_sta *lq_sta, | 729 | struct iwl_lq_sta *lq_sta, |
| 729 | struct iwl_scale_tbl_info *tbl, | 730 | struct iwl_scale_tbl_info *tbl, |
| 730 | int scale_index, int attempts, int successes, | 731 | int scale_index, int attempts, int successes, |
| 731 | u8 reduced_txp) | 732 | u8 reduced_txp) |
| 733 | { | ||
| 734 | struct iwl_rate_scale_data *window = NULL; | ||
| 735 | |||
| 736 | if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION)) | ||
| 737 | return -EINVAL; | ||
| 738 | |||
| 739 | window = &tbl->tpc_win[reduced_txp]; | ||
| 740 | return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, | ||
| 741 | window); | ||
| 742 | } | ||
| 743 | |||
| 744 | static int rs_collect_tlc_data(struct iwl_mvm *mvm, | ||
| 745 | struct iwl_lq_sta *lq_sta, | ||
| 746 | struct iwl_scale_tbl_info *tbl, | ||
| 747 | int scale_index, int attempts, int successes) | ||
| 732 | { | 748 | { |
| 733 | struct iwl_rate_scale_data *window = NULL; | 749 | struct iwl_rate_scale_data *window = NULL; |
| 734 | int ret; | ||
| 735 | 750 | ||
| 736 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 751 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
| 737 | return -EINVAL; | 752 | return -EINVAL; |
| @@ -745,16 +760,6 @@ static int rs_collect_tx_data(struct iwl_mvm *mvm, | |||
| 745 | 760 | ||
| 746 | /* Select window for current tx bit rate */ | 761 | /* Select window for current tx bit rate */ |
| 747 | window = &(tbl->win[scale_index]); | 762 | window = &(tbl->win[scale_index]); |
| 748 | |||
| 749 | ret = _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, | ||
| 750 | window); | ||
| 751 | if (ret) | ||
| 752 | return ret; | ||
| 753 | |||
| 754 | if (WARN_ON_ONCE(reduced_txp > TPC_MAX_REDUCTION)) | ||
| 755 | return -EINVAL; | ||
| 756 | |||
| 757 | window = &tbl->tpc_win[reduced_txp]; | ||
| 758 | return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, | 763 | return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes, |
| 759 | window); | 764 | window); |
| 760 | } | 765 | } |
| @@ -1301,17 +1306,30 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 1301 | * first index into rate scale table. | 1306 | * first index into rate scale table. |
| 1302 | */ | 1307 | */ |
| 1303 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { | 1308 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
| 1304 | /* ampdu_ack_len = 0 marks no BA was received. In this case | 1309 | rs_collect_tpc_data(mvm, lq_sta, curr_tbl, lq_rate.index, |
| 1305 | * treat it as a single frame loss as we don't want the success | 1310 | info->status.ampdu_len, |
| 1306 | * ratio to dip too quickly because a BA wasn't received | 1311 | info->status.ampdu_ack_len, |
| 1312 | reduced_txp); | ||
| 1313 | |||
| 1314 | /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat | ||
| 1315 | * it as a single frame loss as we don't want the success ratio | ||
| 1316 | * to dip too quickly because a BA wasn't received. | ||
| 1317 | * For TPC, there's no need for this optimisation since we want | ||
| 1318 | * to recover very quickly from a bad power reduction and, | ||
| 1319 | * therefore we'd like the success ratio to get an immediate hit | ||
| 1320 | * when failing to get a BA, so we'd switch back to a lower or | ||
| 1321 | * zero power reduction. When FW transmits agg with a rate | ||
| 1322 | * different from the initial rate, it will not use reduced txp | ||
| 1323 | * and will send BA notification twice (one empty with reduced | ||
| 1324 | * txp equal to the value from LQ and one with reduced txp 0). | ||
| 1325 | * We need to update counters for each txp level accordingly. | ||
| 1307 | */ | 1326 | */ |
| 1308 | if (info->status.ampdu_ack_len == 0) | 1327 | if (info->status.ampdu_ack_len == 0) |
| 1309 | info->status.ampdu_len = 1; | 1328 | info->status.ampdu_len = 1; |
| 1310 | 1329 | ||
| 1311 | rs_collect_tx_data(mvm, lq_sta, curr_tbl, lq_rate.index, | 1330 | rs_collect_tlc_data(mvm, lq_sta, curr_tbl, lq_rate.index, |
| 1312 | info->status.ampdu_len, | 1331 | info->status.ampdu_len, |
| 1313 | info->status.ampdu_ack_len, | 1332 | info->status.ampdu_ack_len); |
| 1314 | reduced_txp); | ||
| 1315 | 1333 | ||
| 1316 | /* Update success/fail counts if not searching for new mode */ | 1334 | /* Update success/fail counts if not searching for new mode */ |
| 1317 | if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { | 1335 | if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) { |
| @@ -1344,9 +1362,13 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 1344 | else | 1362 | else |
| 1345 | continue; | 1363 | continue; |
| 1346 | 1364 | ||
| 1347 | rs_collect_tx_data(mvm, lq_sta, tmp_tbl, lq_rate.index, | 1365 | rs_collect_tpc_data(mvm, lq_sta, tmp_tbl, |
| 1348 | 1, i < retries ? 0 : legacy_success, | 1366 | lq_rate.index, 1, |
| 1349 | reduced_txp); | 1367 | i < retries ? 0 : legacy_success, |
| 1368 | reduced_txp); | ||
| 1369 | rs_collect_tlc_data(mvm, lq_sta, tmp_tbl, | ||
| 1370 | lq_rate.index, 1, | ||
| 1371 | i < retries ? 0 : legacy_success); | ||
| 1350 | } | 1372 | } |
| 1351 | 1373 | ||
| 1352 | /* Update success/fail counts if not searching for new mode */ | 1374 | /* Update success/fail counts if not searching for new mode */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 8bf48a7d0f4e..0914ec2fd574 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c | |||
| @@ -1029,7 +1029,6 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, | |||
| 1029 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1029 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
| 1030 | mvmsta->tid_data[tid].rate_n_flags = | 1030 | mvmsta->tid_data[tid].rate_n_flags = |
| 1031 | le32_to_cpu(tx_resp->initial_rate); | 1031 | le32_to_cpu(tx_resp->initial_rate); |
| 1032 | mvmsta->tid_data[tid].reduced_tpc = tx_resp->reduced_tpc; | ||
| 1033 | mvmsta->tid_data[tid].tx_time = | 1032 | mvmsta->tid_data[tid].tx_time = |
| 1034 | le16_to_cpu(tx_resp->wireless_media_time); | 1033 | le16_to_cpu(tx_resp->wireless_media_time); |
| 1035 | } | 1034 | } |
| @@ -1060,7 +1059,7 @@ static void iwl_mvm_tx_info_from_ba_notif(struct ieee80211_tx_info *info, | |||
| 1060 | /* TODO: not accounted if the whole A-MPDU failed */ | 1059 | /* TODO: not accounted if the whole A-MPDU failed */ |
| 1061 | info->status.tx_time = tid_data->tx_time; | 1060 | info->status.tx_time = tid_data->tx_time; |
| 1062 | info->status.status_driver_data[0] = | 1061 | info->status.status_driver_data[0] = |
| 1063 | (void *)(uintptr_t)tid_data->reduced_tpc; | 1062 | (void *)(uintptr_t)ba_notif->reduced_txp; |
| 1064 | info->status.status_driver_data[1] = | 1063 | info->status.status_driver_data[1] = |
| 1065 | (void *)(uintptr_t)tid_data->rate_n_flags; | 1064 | (void *)(uintptr_t)tid_data->rate_n_flags; |
| 1066 | } | 1065 | } |
| @@ -1133,6 +1132,8 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) | |||
| 1133 | scd_flow, ba_resp_scd_ssn, ba_notif->txed, | 1132 | scd_flow, ba_resp_scd_ssn, ba_notif->txed, |
| 1134 | ba_notif->txed_2_done); | 1133 | ba_notif->txed_2_done); |
| 1135 | 1134 | ||
| 1135 | IWL_DEBUG_TX_REPLY(mvm, "reduced txp from ba notif %d\n", | ||
| 1136 | ba_notif->reduced_txp); | ||
| 1136 | tid_data->next_reclaimed = ba_resp_scd_ssn; | 1137 | tid_data->next_reclaimed = ba_resp_scd_ssn; |
| 1137 | 1138 | ||
| 1138 | iwl_mvm_check_ratid_empty(mvm, sta, tid); | 1139 | iwl_mvm_check_ratid_empty(mvm, sta, tid); |
