summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGregory Greenman <gregory.greenman@intel.com>2015-12-29 04:26:35 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2016-01-26 09:03:35 -0500
commit69c7fda40921c125eeeef6a827f6270ac6aa1baa (patch)
tree4b7702dec7e27302fb085c10c560b13b495c67c3
parentca296c571f6929e42dc0ac0bb5c81cdb5323362d (diff)
iwlwifi: mvm: rs: fix TPC statistics handling
FW behaviour changed and now updates driver about the used TPC reduction in the following cases: 1. In tx response, which is used mostly for a single frame case 2. In BA notification When tx aggregation fails with the initial rate, FW will send to the driver BA notification and will try to transmit with the next rate, but this time without tx power reduction. Thus, in case of a failure with the initial rate, driver will get two BA notifications, the first one with reduced tx power as in the LQ command and the second one with 0 power reduction. This patch adapts the TPC statistics according to the description above: 1. Use BA notifications instead of Tx response 2. For TPC only, drop the optimization which considers empty BA as one MPDU. The reason is that with TPC we want to recover very quickly from a bad power reduction and, therefore we'd like the success ratio to get an immediate hit when failing to get a BA, so we'd switch back to a lower or zero power reduction Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c74
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c5
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 */
514struct iwl_mvm_ba_notif { 517struct 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
727static int rs_collect_tx_data(struct iwl_mvm *mvm, 728static 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
744static 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);