mirror of https://gitee.com/openkylin/linux.git
iwlwifi: mvm: change open and close criteria of a BA session
Tx BA session should be started according to the current throughput without any dependence on the internal rate scaling state. The criteria for opening a BA session will be 10 frames per second. Sending frequent del BAs can cause inter-op issues with some APs. We'll not close a BA session until we receive an explicit del BA from the peer. Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
b823cf3bae
commit
482e48440a
|
@ -136,6 +136,7 @@
|
|||
#define IWL_MVM_RS_SR_NO_DECREASE 85 /* percent */
|
||||
#define IWL_MVM_RS_AGG_TIME_LIMIT 4000 /* 4 msecs. valid 100-8000 */
|
||||
#define IWL_MVM_RS_AGG_DISABLE_START 3
|
||||
#define IWL_MVM_RS_AGG_START_THRESHOLD 10 /* num frames per second */
|
||||
#define IWL_MVM_RS_TPC_SR_FORCE_INCREASE 75 /* percent */
|
||||
#define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */
|
||||
#define IWL_MVM_RS_TPC_TX_POWER_STEP 3
|
||||
|
|
|
@ -622,7 +622,9 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,
|
|||
|
||||
IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n",
|
||||
sta->addr, tid);
|
||||
ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
|
||||
|
||||
/* start BA session until the peer sends del BA */
|
||||
ret = ieee80211_start_tx_ba_session(sta, tid, 0);
|
||||
if (ret == -EAGAIN) {
|
||||
/*
|
||||
* driver and mac80211 is out of sync
|
||||
|
@ -636,15 +638,31 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, u8 tid,
|
||||
struct iwl_lq_sta *lq_data,
|
||||
static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
||||
u8 tid, struct iwl_lq_sta *lq_sta,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
if (tid < IWL_MAX_TID_COUNT)
|
||||
rs_tl_turn_on_agg_for_tid(mvm, lq_data, tid, sta);
|
||||
else
|
||||
struct iwl_mvm_tid_data *tid_data;
|
||||
|
||||
/*
|
||||
* In AP mode, tid can be equal to IWL_MAX_TID_COUNT
|
||||
* when the frame is not QoS
|
||||
*/
|
||||
if (WARN_ON_ONCE(tid > IWL_MAX_TID_COUNT)) {
|
||||
IWL_ERR(mvm, "tid exceeds max TID count: %d/%d\n",
|
||||
tid, IWL_MAX_TID_COUNT);
|
||||
return;
|
||||
} else if (tid == IWL_MAX_TID_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
tid_data = &mvmsta->tid_data[tid];
|
||||
if ((tid_data->state == IWL_AGG_OFF) &&
|
||||
(lq_sta->tx_agg_tid_en & BIT(tid)) &&
|
||||
(tid_data->tx_count_last >= IWL_MVM_RS_AGG_START_THRESHOLD)) {
|
||||
IWL_DEBUG_RATE(mvm, "try to aggregate tid %d\n", tid);
|
||||
rs_tl_turn_on_agg_for_tid(mvm, lq_sta, tid, sta);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
|
||||
|
@ -753,8 +771,38 @@ static int rs_collect_tpc_data(struct iwl_mvm *mvm,
|
|||
window);
|
||||
}
|
||||
|
||||
static void rs_update_tid_tpt_stats(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_sta *mvmsta,
|
||||
u8 tid, int successes)
|
||||
{
|
||||
struct iwl_mvm_tid_data *tid_data;
|
||||
|
||||
if (tid >= IWL_MAX_TID_COUNT)
|
||||
return;
|
||||
|
||||
tid_data = &mvmsta->tid_data[tid];
|
||||
|
||||
/*
|
||||
* Measure if there're enough successful transmits per second.
|
||||
* These statistics are used only to decide if we can start a
|
||||
* BA session, so it should be updated only when A-MPDU is
|
||||
* off.
|
||||
*/
|
||||
if (tid_data->state != IWL_AGG_OFF)
|
||||
return;
|
||||
|
||||
if (time_is_before_jiffies(tid_data->tpt_meas_start + HZ) ||
|
||||
(tid_data->tx_count >= IWL_MVM_RS_AGG_START_THRESHOLD)) {
|
||||
tid_data->tx_count_last = tid_data->tx_count;
|
||||
tid_data->tx_count = 0;
|
||||
tid_data->tpt_meas_start = jiffies;
|
||||
} else {
|
||||
tid_data->tx_count += successes;
|
||||
}
|
||||
}
|
||||
|
||||
static int rs_collect_tlc_data(struct iwl_mvm *mvm,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
struct iwl_mvm_sta *mvmsta, u8 tid,
|
||||
struct iwl_scale_tbl_info *tbl,
|
||||
int scale_index, int attempts, int successes)
|
||||
{
|
||||
|
@ -764,12 +812,14 @@ static int rs_collect_tlc_data(struct iwl_mvm *mvm,
|
|||
return -EINVAL;
|
||||
|
||||
if (tbl->column != RS_COLUMN_INVALID) {
|
||||
struct lq_sta_pers *pers = &lq_sta->pers;
|
||||
struct lq_sta_pers *pers = &mvmsta->lq_sta.pers;
|
||||
|
||||
pers->tx_stats[tbl->column][scale_index].total += attempts;
|
||||
pers->tx_stats[tbl->column][scale_index].success += successes;
|
||||
}
|
||||
|
||||
rs_update_tid_tpt_stats(mvm, mvmsta, tid, successes);
|
||||
|
||||
/* Select window for current tx bit rate */
|
||||
window = &(tbl->win[scale_index]);
|
||||
return _rs_collect_tx_data(mvm, tbl, scale_index, attempts, successes,
|
||||
|
@ -1211,12 +1261,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
if (time_after(jiffies,
|
||||
(unsigned long)(lq_sta->last_tx +
|
||||
(IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) {
|
||||
int t;
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
|
||||
for (t = 0; t < IWL_MAX_TID_COUNT; t++)
|
||||
ieee80211_stop_tx_ba_session(sta, t);
|
||||
|
||||
iwl_mvm_rs_rate_init(mvm, sta, info->band, false);
|
||||
return;
|
||||
}
|
||||
|
@ -1312,7 +1357,8 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
if (info->status.ampdu_ack_len == 0)
|
||||
info->status.ampdu_len = 1;
|
||||
|
||||
rs_collect_tlc_data(mvm, lq_sta, curr_tbl, lq_rate.index,
|
||||
rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl,
|
||||
lq_rate.index,
|
||||
info->status.ampdu_len,
|
||||
info->status.ampdu_ack_len);
|
||||
|
||||
|
@ -1351,7 +1397,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
lq_rate.index, 1,
|
||||
i < retries ? 0 : legacy_success,
|
||||
reduced_txp);
|
||||
rs_collect_tlc_data(mvm, lq_sta, tmp_tbl,
|
||||
rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl,
|
||||
lq_rate.index, 1,
|
||||
i < retries ? 0 : legacy_success);
|
||||
}
|
||||
|
@ -2229,7 +2275,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
|
|||
s32 sr;
|
||||
u8 prev_agg = lq_sta->is_agg;
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_mvm_tid_data *tid_data;
|
||||
struct rs_rate *rate;
|
||||
|
||||
lq_sta->is_agg = !!mvmsta->agg_tids;
|
||||
|
@ -2480,44 +2525,12 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
|
|||
}
|
||||
}
|
||||
|
||||
if (done_search && lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_ENDED) {
|
||||
/* If the "active" (non-search) mode was legacy,
|
||||
* and we've tried switching antennas,
|
||||
* but we haven't been able to try HT modes (not available),
|
||||
* stay with best antenna legacy modulation for a while
|
||||
* before next round of mode comparisons. */
|
||||
tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||
if (is_legacy(&tbl1->rate)) {
|
||||
IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n");
|
||||
if (!ndp)
|
||||
rs_tl_turn_on_agg(mvm, mvmsta, tid, lq_sta, sta);
|
||||
|
||||
if (tid != IWL_MAX_TID_COUNT) {
|
||||
tid_data = &mvmsta->tid_data[tid];
|
||||
if (tid_data->state != IWL_AGG_OFF) {
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"Stop aggregation on tid %d\n",
|
||||
tid);
|
||||
ieee80211_stop_tx_ba_session(sta, tid);
|
||||
}
|
||||
}
|
||||
rs_set_stay_in_table(mvm, 1, lq_sta);
|
||||
} else {
|
||||
/* If we're in an HT mode, and all 3 mode switch actions
|
||||
* have been tried and compared, stay in this best modulation
|
||||
* mode for a while before next round of mode comparisons. */
|
||||
if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
|
||||
(lq_sta->tx_agg_tid_en & (1 << tid)) &&
|
||||
(tid != IWL_MAX_TID_COUNT)) {
|
||||
tid_data = &mvmsta->tid_data[tid];
|
||||
if (tid_data->state == IWL_AGG_OFF && !ndp) {
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"try to aggregate tid %d\n",
|
||||
tid);
|
||||
rs_tl_turn_on_agg(mvm, tid,
|
||||
lq_sta, sta);
|
||||
}
|
||||
}
|
||||
rs_set_stay_in_table(mvm, 0, lq_sta);
|
||||
}
|
||||
if (done_search && lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_ENDED) {
|
||||
tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||
rs_set_stay_in_table(mvm, is_legacy(&tbl1->rate), lq_sta);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -316,6 +316,10 @@ enum iwl_mvm_agg_state {
|
|||
* @is_tid_active: has this TID sent traffic in the last
|
||||
* %IWL_MVM_DQA_QUEUE_TIMEOUT time period. If %txq_id is invalid, this
|
||||
* field should be ignored.
|
||||
* @tpt_meas_start: time of the throughput measurements start, is reset every HZ
|
||||
* @tx_count_last: number of frames transmitted during the last second
|
||||
* @tx_count: counts the number of frames transmitted since the last reset of
|
||||
* tpt_meas_start
|
||||
*/
|
||||
struct iwl_mvm_tid_data {
|
||||
struct sk_buff_head deferred_tx_frames;
|
||||
|
@ -330,6 +334,9 @@ struct iwl_mvm_tid_data {
|
|||
u16 ssn;
|
||||
u16 tx_time;
|
||||
bool is_tid_active;
|
||||
unsigned long tpt_meas_start;
|
||||
u32 tx_count_last;
|
||||
u32 tx_count;
|
||||
};
|
||||
|
||||
struct iwl_mvm_key_pn {
|
||||
|
|
Loading…
Reference in New Issue