Commit 0215f4cf authored by John W. Linville's avatar John W. Linville
parents 08e22e19 a6bc9280
...@@ -67,8 +67,8 @@ ...@@ -67,8 +67,8 @@
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL7260_UCODE_API_MAX 8 #define IWL7260_UCODE_API_MAX 9
#define IWL3160_UCODE_API_MAX 8 #define IWL3160_UCODE_API_MAX 9
/* Oldest version we won't warn about */ /* Oldest version we won't warn about */
#define IWL7260_UCODE_API_OK 8 #define IWL7260_UCODE_API_OK 8
...@@ -244,3 +244,4 @@ const struct iwl_cfg iwl7265_n_cfg = { ...@@ -244,3 +244,4 @@ const struct iwl_cfg iwl7265_n_cfg = {
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
...@@ -190,7 +190,7 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { ...@@ -190,7 +190,7 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
cpu_to_le32(0xcc00aaaa), cpu_to_le32(0xcc00aaaa),
cpu_to_le32(0x0000aaaa), cpu_to_le32(0x0000aaaa),
cpu_to_le32(0xc0004000), cpu_to_le32(0xc0004000),
cpu_to_le32(0x00000000), cpu_to_le32(0x00004000),
cpu_to_le32(0xf0005000), cpu_to_le32(0xf0005000),
cpu_to_le32(0xf0005000), cpu_to_le32(0xf0005000),
}, },
...@@ -213,16 +213,16 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { ...@@ -213,16 +213,16 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
/* Tx Tx disabled */ /* Tx Tx disabled */
cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa),
cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa),
cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xeeaaaaaa),
cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa),
cpu_to_le32(0xcc00ff28), cpu_to_le32(0xcc00ff28),
cpu_to_le32(0x0000aaaa), cpu_to_le32(0x0000aaaa),
cpu_to_le32(0xcc00aaaa), cpu_to_le32(0xcc00aaaa),
cpu_to_le32(0x0000aaaa), cpu_to_le32(0x0000aaaa),
cpu_to_le32(0xC0004000), cpu_to_le32(0xc0004000),
cpu_to_le32(0xC0004000), cpu_to_le32(0xc0004000),
cpu_to_le32(0xF0005000), cpu_to_le32(0xf0005000),
cpu_to_le32(0xF0005000), cpu_to_le32(0xf0005000),
}, },
}; };
...@@ -1262,6 +1262,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, ...@@ -1262,6 +1262,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
u32 ant_isolation = le32_to_cpup((void *)pkt->data); u32 ant_isolation = le32_to_cpup((void *)pkt->data);
u8 __maybe_unused lower_bound, upper_bound; u8 __maybe_unused lower_bound, upper_bound;
int ret;
u8 lut; u8 lut;
struct iwl_bt_coex_cmd *bt_cmd; struct iwl_bt_coex_cmd *bt_cmd;
...@@ -1318,5 +1319,8 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, ...@@ -1318,5 +1319,8 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20, memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
sizeof(bt_cmd->bt4_corun_lut40)); sizeof(bt_cmd->bt4_corun_lut40));
return 0; ret = iwl_mvm_send_cmd(mvm, &cmd);
kfree(bt_cmd);
return ret;
} }
...@@ -1332,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, ...@@ -1332,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
*/ */
iwl_mvm_remove_time_event(mvm, mvmvif, iwl_mvm_remove_time_event(mvm, mvmvif,
&mvmvif->time_event_data); &mvmvif->time_event_data);
iwl_mvm_sf_update(mvm, vif, false);
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC));
} else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
BSS_CHANGED_QOS)) { BSS_CHANGED_QOS)) {
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
/* max allowed rate miss before sync LQ cmd */ /* max allowed rate miss before sync LQ cmd */
#define IWL_MISSED_RATE_MAX 15 #define IWL_MISSED_RATE_MAX 15
#define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ) #define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ)
#define RS_IDLE_TIMEOUT (5*HZ)
static u8 rs_ht_to_legacy[] = { static u8 rs_ht_to_legacy[] = {
[IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX,
...@@ -142,7 +142,7 @@ enum rs_column_mode { ...@@ -142,7 +142,7 @@ enum rs_column_mode {
RS_MIMO2, RS_MIMO2,
}; };
#define MAX_NEXT_COLUMNS 5 #define MAX_NEXT_COLUMNS 7
#define MAX_COLUMN_CHECKS 3 #define MAX_COLUMN_CHECKS 3
typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm, typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm,
...@@ -212,8 +212,10 @@ static const struct rs_tx_column rs_tx_columns[] = { ...@@ -212,8 +212,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_LEGACY_ANT_B, RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B, RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2, RS_COLUMN_INVALID,
RS_COLUMN_MIMO2_SGI, RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
}, },
}, },
[RS_COLUMN_LEGACY_ANT_B] = { [RS_COLUMN_LEGACY_ANT_B] = {
...@@ -223,8 +225,10 @@ static const struct rs_tx_column rs_tx_columns[] = { ...@@ -223,8 +225,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B, RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2, RS_COLUMN_INVALID,
RS_COLUMN_MIMO2_SGI, RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
}, },
}, },
[RS_COLUMN_SISO_ANT_A] = { [RS_COLUMN_SISO_ANT_A] = {
...@@ -235,7 +239,9 @@ static const struct rs_tx_column rs_tx_columns[] = { ...@@ -235,7 +239,9 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_MIMO2, RS_COLUMN_MIMO2,
RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_MIMO2_SGI, RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
}, },
.checks = { .checks = {
rs_siso_allow, rs_siso_allow,
...@@ -249,7 +255,9 @@ static const struct rs_tx_column rs_tx_columns[] = { ...@@ -249,7 +255,9 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_MIMO2, RS_COLUMN_MIMO2,
RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_MIMO2_SGI, RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
}, },
.checks = { .checks = {
rs_siso_allow, rs_siso_allow,
...@@ -265,6 +273,8 @@ static const struct rs_tx_column rs_tx_columns[] = { ...@@ -265,6 +273,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B, RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2, RS_COLUMN_MIMO2,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
}, },
.checks = { .checks = {
rs_siso_allow, rs_siso_allow,
...@@ -281,6 +291,8 @@ static const struct rs_tx_column rs_tx_columns[] = { ...@@ -281,6 +291,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_B, RS_COLUMN_SISO_ANT_B,
RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_A,
RS_COLUMN_MIMO2, RS_COLUMN_MIMO2,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
}, },
.checks = { .checks = {
rs_siso_allow, rs_siso_allow,
...@@ -296,6 +308,8 @@ static const struct rs_tx_column rs_tx_columns[] = { ...@@ -296,6 +308,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_MIMO2_SGI, RS_COLUMN_MIMO2_SGI,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
}, },
.checks = { .checks = {
rs_mimo_allow, rs_mimo_allow,
...@@ -311,6 +325,8 @@ static const struct rs_tx_column rs_tx_columns[] = { ...@@ -311,6 +325,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B, RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2, RS_COLUMN_MIMO2,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
}, },
.checks = { .checks = {
rs_mimo_allow, rs_mimo_allow,
...@@ -503,10 +519,12 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) ...@@ -503,10 +519,12 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
window->average_tpt = IWL_INVALID_VALUE; window->average_tpt = IWL_INVALID_VALUE;
} }
static void rs_rate_scale_clear_tbl_windows(struct iwl_scale_tbl_info *tbl) static void rs_rate_scale_clear_tbl_windows(struct iwl_mvm *mvm,
struct iwl_scale_tbl_info *tbl)
{ {
int i; int i;
IWL_DEBUG_RATE(mvm, "Clearing up window stats\n");
for (i = 0; i < IWL_RATE_COUNT; i++) for (i = 0; i < IWL_RATE_COUNT; i++)
rs_rate_scale_clear_window(&tbl->win[i]); rs_rate_scale_clear_window(&tbl->win[i]);
} }
...@@ -992,6 +1010,13 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, ...@@ -992,6 +1010,13 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
return; return;
} }
#ifdef CPTCFG_MAC80211_DEBUGFS
/* Disable last tx check if we are debugging with fixed rate */
if (lq_sta->dbg_fixed_rate) {
IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n");
return;
}
#endif
if (!ieee80211_is_data(hdr->frame_control) || if (!ieee80211_is_data(hdr->frame_control) ||
info->flags & IEEE80211_TX_CTL_NO_ACK) info->flags & IEEE80211_TX_CTL_NO_ACK)
return; return;
...@@ -1034,6 +1059,18 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, ...@@ -1034,6 +1059,18 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
mac_index++; mac_index++;
} }
if (time_after(jiffies,
(unsigned long)(lq_sta->last_tx + RS_IDLE_TIMEOUT))) {
int tid;
IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
ieee80211_stop_tx_ba_session(sta, tid);
iwl_mvm_rs_rate_init(mvm, sta, sband->band, false);
return;
}
lq_sta->last_tx = jiffies;
/* Here we actually compare this rate to the latest LQ command */ /* Here we actually compare this rate to the latest LQ command */
if ((mac_index < 0) || if ((mac_index < 0) ||
(rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
...@@ -1186,6 +1223,23 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy, ...@@ -1186,6 +1223,23 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy,
lq_sta->visited_columns = 0; lq_sta->visited_columns = 0;
} }
static int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta,
const struct rs_tx_column *column)
{
switch (column->mode) {
case RS_LEGACY:
return lq_sta->max_legacy_rate_idx;
case RS_SISO:
return lq_sta->max_siso_rate_idx;
case RS_MIMO2:
return lq_sta->max_mimo2_rate_idx;
default:
WARN_ON_ONCE(1);
}
return lq_sta->max_legacy_rate_idx;
}
static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta, static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta,
const struct rs_tx_column *column, const struct rs_tx_column *column,
u32 bw) u32 bw)
...@@ -1438,7 +1492,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) ...@@ -1438,7 +1492,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"LQ: stay in table clear win\n"); "LQ: stay in table clear win\n");
rs_rate_scale_clear_tbl_windows(tbl); rs_rate_scale_clear_tbl_windows(mvm, tbl);
} }
} }
...@@ -1446,8 +1500,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) ...@@ -1446,8 +1500,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
* bitmaps and stats in active table (this will become the new * bitmaps and stats in active table (this will become the new
* "search" table). */ * "search" table). */
if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) {
IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); rs_rate_scale_clear_tbl_windows(mvm, tbl);
rs_rate_scale_clear_tbl_windows(tbl);
} }
} }
} }
...@@ -1485,14 +1538,14 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, ...@@ -1485,14 +1538,14 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl) struct iwl_scale_tbl_info *tbl)
{ {
int i, j, n; int i, j, max_rate;
enum rs_column next_col_id; enum rs_column next_col_id;
const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column];
const struct rs_tx_column *next_col; const struct rs_tx_column *next_col;
allow_column_func_t allow_func; allow_column_func_t allow_func;
u8 valid_ants = mvm->fw->valid_tx_ant; u8 valid_ants = mvm->fw->valid_tx_ant;
const u16 *expected_tpt_tbl; const u16 *expected_tpt_tbl;
s32 tpt, max_expected_tpt; u16 tpt, max_expected_tpt;
for (i = 0; i < MAX_NEXT_COLUMNS; i++) { for (i = 0; i < MAX_NEXT_COLUMNS; i++) {
next_col_id = curr_col->next_columns[i]; next_col_id = curr_col->next_columns[i];
...@@ -1535,11 +1588,11 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, ...@@ -1535,11 +1588,11 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(!expected_tpt_tbl)) if (WARN_ON_ONCE(!expected_tpt_tbl))
continue; continue;
max_expected_tpt = 0; max_rate = rs_get_max_allowed_rate(lq_sta, next_col);
for (n = 0; n < IWL_RATE_COUNT; n++) if (WARN_ON_ONCE(max_rate == IWL_RATE_INVALID))
if (expected_tpt_tbl[n] > max_expected_tpt) continue;
max_expected_tpt = expected_tpt_tbl[n];
max_expected_tpt = expected_tpt_tbl[max_rate];
if (tpt >= max_expected_tpt) { if (tpt >= max_expected_tpt) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"Skip column %d: can't beat current TPT. Max expected %d current %d\n", "Skip column %d: can't beat current TPT. Max expected %d current %d\n",
...@@ -1547,14 +1600,15 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, ...@@ -1547,14 +1600,15 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
continue; continue;
} }
IWL_DEBUG_RATE(mvm,
"Found potential column %d. Max expected %d current %d\n",
next_col_id, max_expected_tpt, tpt);
break; break;
} }
if (i == MAX_NEXT_COLUMNS) if (i == MAX_NEXT_COLUMNS)
return RS_COLUMN_INVALID; return RS_COLUMN_INVALID;
IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id);
return next_col_id; return next_col_id;
} }
...@@ -1640,85 +1694,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm, ...@@ -1640,85 +1694,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm,
{ {
enum rs_action action = RS_ACTION_STAY; enum rs_action action = RS_ACTION_STAY;
/* Too many failures, decrease rate */
if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"decrease rate because of low SR\n"); "Decrease rate because of low SR\n");
action = RS_ACTION_DOWNSCALE; return RS_ACTION_DOWNSCALE;
/* No throughput measured yet for adjacent rates; try increase. */ }
} else if ((low_tpt == IWL_INVALID_VALUE) &&
(high_tpt == IWL_INVALID_VALUE)) { if ((low_tpt == IWL_INVALID_VALUE) &&
if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { (high_tpt == IWL_INVALID_VALUE) &&
(high != IWL_RATE_INVALID)) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"Good SR and no high rate measurement. " "No data about high/low rates. Increase rate\n");
"Increase rate\n"); return RS_ACTION_UPSCALE;
action = RS_ACTION_UPSCALE; }
} else if (low != IWL_RATE_INVALID) {
if ((high_tpt == IWL_INVALID_VALUE) &&
(high != IWL_RATE_INVALID) &&
(low_tpt != IWL_INVALID_VALUE) &&
(low_tpt < current_tpt)) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"Remain in current rate\n"); "No data about high rate and low rate is worse. Increase rate\n");
action = RS_ACTION_STAY; return RS_ACTION_UPSCALE;
} }
if ((high_tpt != IWL_INVALID_VALUE) &&
(high_tpt > current_tpt)) {
IWL_DEBUG_RATE(mvm,
"Higher rate is better. Increate rate\n");
return RS_ACTION_UPSCALE;
} }
/* Both adjacent throughputs are measured, but neither one has better if ((low_tpt != IWL_INVALID_VALUE) &&
* throughput; we're using the best rate, don't change it!
*/
else if ((low_tpt != IWL_INVALID_VALUE) &&
(high_tpt != IWL_INVALID_VALUE) && (high_tpt != IWL_INVALID_VALUE) &&
(low_tpt < current_tpt) && (low_tpt < current_tpt) &&
(high_tpt < current_tpt)) { (high_tpt < current_tpt)) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"Both high and low are worse. " "Both high and low are worse. Maintain rate\n");
"Maintain rate\n"); return RS_ACTION_STAY;
action = RS_ACTION_STAY;
} }
/* At least one adjacent rate's throughput is measured, if ((low_tpt != IWL_INVALID_VALUE) &&
* and may have better performance. (low_tpt > current_tpt)) {
*/
else {
/* Higher adjacent rate's throughput is measured */
if (high_tpt != IWL_INVALID_VALUE) {
/* Higher rate has better throughput */
if (high_tpt > current_tpt &&
sr >= IWL_RATE_INCREASE_TH) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"Higher rate is better and good " "Lower rate is better\n");
"SR. Increate rate\n"); action = RS_ACTION_DOWNSCALE;
action = RS_ACTION_UPSCALE; goto out;
} else {
IWL_DEBUG_RATE(mvm,
"Higher rate isn't better OR "
"no good SR. Maintain rate\n");
action = RS_ACTION_STAY;
} }
/* Lower adjacent rate's throughput is measured */ if ((low_tpt == IWL_INVALID_VALUE) &&
} else if (low_tpt != IWL_INVALID_VALUE) { (low != IWL_RATE_INVALID)) {
/* Lower rate has better throughput */
if (low_tpt > current_tpt) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"Lower rate is better. " "No data about lower rate\n");
"Decrease rate\n");
action = RS_ACTION_DOWNSCALE; action = RS_ACTION_DOWNSCALE;
} else if (sr >= IWL_RATE_INCREASE_TH) { goto out;
IWL_DEBUG_RATE(mvm,
"Lower rate isn't better and "
"good SR. Increase rate\n");
action = RS_ACTION_UPSCALE;
}
}
} }
/* Sanity check; asked for decrease, but success rate or throughput IWL_DEBUG_RATE(mvm, "Maintain rate\n");
* has been good at old rate. Don't change it.
*/ out:
if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) && if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) {
((sr > IWL_RATE_HIGH_TH) || if (sr >= RS_SR_NO_DECREASE) {
(current_tpt > (100 * tbl->expected_tpt[low])))) {
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"Sanity check failed. Maintain rate\n"); "SR is above NO DECREASE. Avoid downscale\n");
action = RS_ACTION_STAY; action = RS_ACTION_STAY;
} else if (current_tpt > (100 * tbl->expected_tpt[low])) {
IWL_DEBUG_RATE(mvm,
"Current TPT is higher than max expected in low rate. Avoid downscale\n");
action = RS_ACTION_STAY;
} else {
IWL_DEBUG_RATE(mvm, "Decrease rate\n");
}
} }
return action; return action;
...@@ -1792,6 +1837,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, ...@@ -1792,6 +1837,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
"Aggregation changed: prev %d current %d. Update expected TPT table\n", "Aggregation changed: prev %d current %d. Update expected TPT table\n",
prev_agg, lq_sta->is_agg); prev_agg, lq_sta->is_agg);
rs_set_expected_tpt_table(lq_sta, tbl); rs_set_expected_tpt_table(lq_sta, tbl);
rs_rate_scale_clear_tbl_windows(mvm, tbl);
} }
/* current tx rate */ /* current tx rate */
...@@ -2021,7 +2067,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, ...@@ -2021,7 +2067,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
if (lq_sta->search_better_tbl) { if (lq_sta->search_better_tbl) {
/* Access the "search" table, clear its history. */ /* Access the "search" table, clear its history. */
tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
rs_rate_scale_clear_tbl_windows(tbl); rs_rate_scale_clear_tbl_windows(mvm, tbl);
/* Use new "search" start rate */ /* Use new "search" start rate */
index = tbl->rate.index; index = tbl->rate.index;
...@@ -2042,8 +2088,18 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, ...@@ -2042,8 +2088,18 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
* stay with best antenna legacy modulation for a while * stay with best antenna legacy modulation for a while
* before next round of mode comparisons. */ * before next round of mode comparisons. */
tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported) { if (is_legacy(&tbl1->rate)) {
IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n"); IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n");
if (tid != IWL_MAX_TID_COUNT) {
tid_data = &sta_priv->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); rs_set_stay_in_table(mvm, 1, lq_sta);
} else { } else {
/* If we're in an HT mode, and all 3 mode switch actions /* If we're in an HT mode, and all 3 mode switch actions
...@@ -2342,9 +2398,10 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -2342,9 +2398,10 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
lq_sta->lq.sta_id = sta_priv->sta_id; lq_sta->lq.sta_id = sta_priv->sta_id;
for (j = 0; j < LQ_SIZE; j++) for (j = 0; j < LQ_SIZE; j++)
rs_rate_scale_clear_tbl_windows(&lq_sta->lq_info[j]); rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]);
lq_sta->flush_timer = 0; lq_sta->flush_timer = 0;
lq_sta->last_tx = jiffies;
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"LQ: *** rate scale station global init for station %d ***\n", "LQ: *** rate scale station global init for station %d ***\n",
...@@ -2388,11 +2445,22 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -2388,11 +2445,22 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
lq_sta->is_vht = true; lq_sta->is_vht = true;
} }
IWL_DEBUG_RATE(mvm, lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate,
"SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n", BITS_PER_LONG);
lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate,
BITS_PER_LONG);
lq_sta->max_mimo2_rate_idx = find_last_bit(&lq_sta->active_mimo2_rate,
BITS_PER_LONG);
IWL_DEBUG_RATE(mvm, "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d\n",
lq_sta->active_legacy_rate,
lq_sta->active_siso_rate, lq_sta->active_siso_rate,
lq_sta->active_mimo2_rate, lq_sta->active_mimo2_rate,
lq_sta->is_vht); lq_sta->is_vht);
IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n",
lq_sta->max_legacy_rate_idx,
lq_sta->max_siso_rate_idx,
lq_sta->max_mimo2_rate_idx);
/* These values will be overridden later */ /* These values will be overridden later */
lq_sta->lq.single_stream_ant_msk = lq_sta->lq.single_stream_ant_msk =
...@@ -2547,6 +2615,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, ...@@ -2547,6 +2615,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
if (is_siso(&rate)) { if (is_siso(&rate)) {
num_rates = RS_SECONDARY_SISO_NUM_RATES; num_rates = RS_SECONDARY_SISO_NUM_RATES;
num_retries = RS_SECONDARY_SISO_RETRIES; num_retries = RS_SECONDARY_SISO_RETRIES;
lq_cmd->mimo_delim = index;
} else if (is_legacy(&rate)) { } else if (is_legacy(&rate)) {
num_rates = RS_SECONDARY_LEGACY_NUM_RATES; num_rates = RS_SECONDARY_LEGACY_NUM_RATES;
num_retries = RS_LEGACY_RETRIES_PER_RATE; num_retries = RS_LEGACY_RETRIES_PER_RATE;
...@@ -2749,7 +2818,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, ...@@ -2749,7 +2818,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
return -ENOMEM; return -ENOMEM;
desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id);
desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", desc += sprintf(buff+desc, "failed=%d success=%d rate=0%lX\n",
lq_sta->total_failed, lq_sta->total_success, lq_sta->total_failed, lq_sta->total_success,
lq_sta->active_legacy_rate); lq_sta->active_legacy_rate);
desc += sprintf(buff+desc, "fixed rate 0x%X\n", desc += sprintf(buff+desc, "fixed rate 0x%X\n",
......
...@@ -156,6 +156,7 @@ enum { ...@@ -156,6 +156,7 @@ enum {
#define IWL_RATE_HIGH_TH 10880 /* 85% */ #define IWL_RATE_HIGH_TH 10880 /* 85% */
#define IWL_RATE_INCREASE_TH 6400 /* 50% */ #define IWL_RATE_INCREASE_TH 6400 /* 50% */
#define RS_SR_FORCE_DECREASE 1920 /* 15% */ #define RS_SR_FORCE_DECREASE 1920 /* 15% */
#define RS_SR_NO_DECREASE 10880 /* 85% */
#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */
#define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000)
...@@ -310,13 +311,20 @@ struct iwl_lq_sta { ...@@ -310,13 +311,20 @@ struct iwl_lq_sta {
u32 visited_columns; /* Bitmask marking which Tx columns were u32 visited_columns; /* Bitmask marking which Tx columns were
* explored during a search cycle * explored during a search cycle
*/ */
u64 last_tx;
bool is_vht; bool is_vht;
enum ieee80211_band band; enum ieee80211_band band;
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
u16 active_legacy_rate; unsigned long active_legacy_rate;
u16 active_siso_rate; unsigned long active_siso_rate;
u16 active_mimo2_rate; unsigned long active_mimo2_rate;
/* Highest rate per Tx mode */
u8 max_legacy_rate_idx;
u8 max_siso_rate_idx;
u8 max_mimo2_rate_idx;
s8 max_rate_idx; /* Max rate set by user */ s8 max_rate_idx; /* Max rate set by user */
u8 missed_rate_counter; u8 missed_rate_counter;
......
...@@ -274,7 +274,8 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif, ...@@ -274,7 +274,8 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
return -EINVAL; return -EINVAL;
if (changed_vif->type != NL80211_IFTYPE_STATION) { if (changed_vif->type != NL80211_IFTYPE_STATION) {
new_state = SF_UNINIT; new_state = SF_UNINIT;
} else if (changed_vif->bss_conf.assoc) { } else if (changed_vif->bss_conf.assoc &&
changed_vif->bss_conf.dtim_period) {
mvmvif = iwl_mvm_vif_from_mac80211(changed_vif); mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
sta_id = mvmvif->ap_sta_id; sta_id = mvmvif->ap_sta_id;
new_state = SF_FULL_ON; new_state = SF_FULL_ON;
......
...@@ -373,12 +373,14 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { ...@@ -373,12 +373,14 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5102, iwl7265_n_cfg)},
{IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9200, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment