Loading drivers/net/wireless/iwlwifi/iwl-7000.c +3 −2 Original line number Diff line number Diff line Loading @@ -67,8 +67,8 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ #define IWL7260_UCODE_API_MAX 8 #define IWL3160_UCODE_API_MAX 8 #define IWL7260_UCODE_API_MAX 9 #define IWL3160_UCODE_API_MAX 9 /* Oldest version we won't warn about */ #define IWL7260_UCODE_API_OK 8 Loading Loading @@ -244,3 +244,4 @@ const struct iwl_cfg iwl7265_n_cfg = { MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); drivers/net/wireless/iwlwifi/mvm/coex.c +11 −7 Original line number Diff line number Diff line Loading @@ -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(0x0000aaaa), cpu_to_le32(0xc0004000), cpu_to_le32(0x00000000), cpu_to_le32(0x00004000), cpu_to_le32(0xf0005000), cpu_to_le32(0xf0005000), }, Loading @@ -213,16 +213,16 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { /* Tx Tx disabled */ cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xeeaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xcc00ff28), cpu_to_le32(0x0000aaaa), cpu_to_le32(0xcc00aaaa), cpu_to_le32(0x0000aaaa), cpu_to_le32(0xC0004000), cpu_to_le32(0xC0004000), cpu_to_le32(0xF0005000), cpu_to_le32(0xF0005000), cpu_to_le32(0xc0004000), cpu_to_le32(0xc0004000), cpu_to_le32(0xf0005000), cpu_to_le32(0xf0005000), }, }; Loading Loading @@ -1262,6 +1262,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt = rxb_addr(rxb); u32 ant_isolation = le32_to_cpup((void *)pkt->data); u8 __maybe_unused lower_bound, upper_bound; int ret; u8 lut; struct iwl_bt_coex_cmd *bt_cmd; Loading Loading @@ -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, sizeof(bt_cmd->bt4_corun_lut40)); return 0; ret = iwl_mvm_send_cmd(mvm, &cmd); kfree(bt_cmd); return ret; } drivers/net/wireless/iwlwifi/mvm/mac80211.c +1 −0 Original line number Diff line number Diff line Loading @@ -1332,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, */ iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); iwl_mvm_sf_update(mvm, vif, false); WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS)) { Loading drivers/net/wireless/iwlwifi/mvm/rs.c +165 −96 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ /* max allowed rate miss before sync LQ cmd */ #define IWL_MISSED_RATE_MAX 15 #define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ) #define RS_IDLE_TIMEOUT (5*HZ) static u8 rs_ht_to_legacy[] = { [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, Loading Loading @@ -142,7 +142,7 @@ enum rs_column_mode { RS_MIMO2, }; #define MAX_NEXT_COLUMNS 5 #define MAX_NEXT_COLUMNS 7 #define MAX_COLUMN_CHECKS 3 typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm, Loading Loading @@ -212,8 +212,10 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_LEGACY_ANT_B, RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_MIMO2_SGI, RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, }, }, [RS_COLUMN_LEGACY_ANT_B] = { Loading @@ -223,8 +225,10 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_MIMO2_SGI, RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, }, }, [RS_COLUMN_SISO_ANT_A] = { Loading @@ -235,7 +239,9 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_MIMO2, RS_COLUMN_SISO_ANT_A_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 = { rs_siso_allow, Loading @@ -249,7 +255,9 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_MIMO2, RS_COLUMN_SISO_ANT_B_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 = { rs_siso_allow, Loading @@ -265,6 +273,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, Loading @@ -281,6 +291,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_B, RS_COLUMN_SISO_ANT_A, RS_COLUMN_MIMO2, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, Loading @@ -296,6 +308,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_MIMO2_SGI, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_mimo_allow, Loading @@ -311,6 +325,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_mimo_allow, Loading Loading @@ -503,10 +519,12 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) 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; IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&tbl->win[i]); } Loading Loading @@ -992,6 +1010,13 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, 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) || info->flags & IEEE80211_TX_CTL_NO_ACK) return; Loading Loading @@ -1034,6 +1059,18 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, 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 */ if ((mac_index < 0) || (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || Loading Loading @@ -1186,6 +1223,23 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy, 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, const struct rs_tx_column *column, u32 bw) Loading Loading @@ -1438,7 +1492,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) IWL_DEBUG_RATE(mvm, "LQ: stay in table clear win\n"); rs_rate_scale_clear_tbl_windows(tbl); rs_rate_scale_clear_tbl_windows(mvm, tbl); } } Loading @@ -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 * "search" table). */ 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(tbl); rs_rate_scale_clear_tbl_windows(mvm, tbl); } } } Loading Loading @@ -1485,14 +1538,14 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_scale_tbl_info *tbl) { int i, j, n; int i, j, max_rate; enum rs_column next_col_id; const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; const struct rs_tx_column *next_col; allow_column_func_t allow_func; u8 valid_ants = mvm->fw->valid_tx_ant; const u16 *expected_tpt_tbl; s32 tpt, max_expected_tpt; u16 tpt, max_expected_tpt; for (i = 0; i < MAX_NEXT_COLUMNS; i++) { next_col_id = curr_col->next_columns[i]; Loading Loading @@ -1535,11 +1588,11 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, if (WARN_ON_ONCE(!expected_tpt_tbl)) continue; max_expected_tpt = 0; for (n = 0; n < IWL_RATE_COUNT; n++) if (expected_tpt_tbl[n] > max_expected_tpt) max_expected_tpt = expected_tpt_tbl[n]; max_rate = rs_get_max_allowed_rate(lq_sta, next_col); if (WARN_ON_ONCE(max_rate == IWL_RATE_INVALID)) continue; max_expected_tpt = expected_tpt_tbl[max_rate]; if (tpt >= max_expected_tpt) { IWL_DEBUG_RATE(mvm, "Skip column %d: can't beat current TPT. Max expected %d current %d\n", Loading @@ -1547,14 +1600,15 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, continue; } IWL_DEBUG_RATE(mvm, "Found potential column %d. Max expected %d current %d\n", next_col_id, max_expected_tpt, tpt); break; } if (i == MAX_NEXT_COLUMNS) return RS_COLUMN_INVALID; IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id); return next_col_id; } Loading Loading @@ -1640,85 +1694,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm, { enum rs_action action = RS_ACTION_STAY; /* Too many failures, decrease rate */ if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { IWL_DEBUG_RATE(mvm, "decrease rate because of low SR\n"); action = 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 (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { "Decrease rate because of low SR\n"); return RS_ACTION_DOWNSCALE; } if ((low_tpt == IWL_INVALID_VALUE) && (high_tpt == IWL_INVALID_VALUE) && (high != IWL_RATE_INVALID)) { IWL_DEBUG_RATE(mvm, "Good SR and no high rate measurement. " "Increase rate\n"); action = RS_ACTION_UPSCALE; } else if (low != IWL_RATE_INVALID) { "No data about high/low rates. Increase rate\n"); return RS_ACTION_UPSCALE; } if ((high_tpt == IWL_INVALID_VALUE) && (high != IWL_RATE_INVALID) && (low_tpt != IWL_INVALID_VALUE) && (low_tpt < current_tpt)) { IWL_DEBUG_RATE(mvm, "Remain in current rate\n"); action = RS_ACTION_STAY; "No data about high rate and low rate is worse. Increase rate\n"); 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 * throughput; we're using the best rate, don't change it! */ else if ((low_tpt != IWL_INVALID_VALUE) && if ((low_tpt != IWL_INVALID_VALUE) && (high_tpt != IWL_INVALID_VALUE) && (low_tpt < current_tpt) && (high_tpt < current_tpt)) { IWL_DEBUG_RATE(mvm, "Both high and low are worse. " "Maintain rate\n"); action = RS_ACTION_STAY; "Both high and low are worse. Maintain rate\n"); return RS_ACTION_STAY; } /* At least one adjacent rate's throughput is measured, * and may have better performance. */ 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) { if ((low_tpt != IWL_INVALID_VALUE) && (low_tpt > current_tpt)) { IWL_DEBUG_RATE(mvm, "Higher rate is better and good " "SR. Increate rate\n"); action = RS_ACTION_UPSCALE; } else { IWL_DEBUG_RATE(mvm, "Higher rate isn't better OR " "no good SR. Maintain rate\n"); action = RS_ACTION_STAY; "Lower rate is better\n"); action = RS_ACTION_DOWNSCALE; goto out; } /* Lower adjacent rate's throughput is measured */ } else if (low_tpt != IWL_INVALID_VALUE) { /* Lower rate has better throughput */ if (low_tpt > current_tpt) { if ((low_tpt == IWL_INVALID_VALUE) && (low != IWL_RATE_INVALID)) { IWL_DEBUG_RATE(mvm, "Lower rate is better. " "Decrease rate\n"); "No data about lower rate\n"); action = RS_ACTION_DOWNSCALE; } else if (sr >= IWL_RATE_INCREASE_TH) { IWL_DEBUG_RATE(mvm, "Lower rate isn't better and " "good SR. Increase rate\n"); action = RS_ACTION_UPSCALE; } } goto out; } /* Sanity check; asked for decrease, but success rate or throughput * has been good at old rate. Don't change it. */ if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) && ((sr > IWL_RATE_HIGH_TH) || (current_tpt > (100 * tbl->expected_tpt[low])))) { IWL_DEBUG_RATE(mvm, "Maintain rate\n"); out: if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) { if (sr >= RS_SR_NO_DECREASE) { IWL_DEBUG_RATE(mvm, "Sanity check failed. Maintain rate\n"); "SR is above NO DECREASE. Avoid downscale\n"); 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; Loading Loading @@ -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", prev_agg, lq_sta->is_agg); rs_set_expected_tpt_table(lq_sta, tbl); rs_rate_scale_clear_tbl_windows(mvm, tbl); } /* current tx rate */ Loading Loading @@ -2021,7 +2067,7 @@ lq_update: if (lq_sta->search_better_tbl) { /* Access the "search" table, clear its history. */ 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 */ index = tbl->rate.index; Loading @@ -2042,8 +2088,18 @@ lq_update: * 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) && !sta->ht_cap.ht_supported) { if (is_legacy(&tbl1->rate)) { 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); } else { /* If we're in an HT mode, and all 3 mode switch actions Loading Loading @@ -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; 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->last_tx = jiffies; IWL_DEBUG_RATE(mvm, "LQ: *** rate scale station global init for station %d ***\n", Loading Loading @@ -2388,11 +2445,22 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lq_sta->is_vht = true; } IWL_DEBUG_RATE(mvm, "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n", lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, 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_mimo2_rate, 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 */ lq_sta->lq.single_stream_ant_msk = Loading Loading @@ -2547,6 +2615,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, if (is_siso(&rate)) { num_rates = RS_SECONDARY_SISO_NUM_RATES; num_retries = RS_SECONDARY_SISO_RETRIES; lq_cmd->mimo_delim = index; } else if (is_legacy(&rate)) { num_rates = RS_SECONDARY_LEGACY_NUM_RATES; num_retries = RS_LEGACY_RETRIES_PER_RATE; Loading Loading @@ -2749,7 +2818,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, return -ENOMEM; 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->active_legacy_rate); desc += sprintf(buff+desc, "fixed rate 0x%X\n", Loading drivers/net/wireless/iwlwifi/mvm/rs.h +11 −3 Original line number Diff line number Diff line Loading @@ -156,6 +156,7 @@ enum { #define IWL_RATE_HIGH_TH 10880 /* 85% */ #define IWL_RATE_INCREASE_TH 6400 /* 50% */ #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_MAX (8000) Loading Loading @@ -310,13 +311,20 @@ struct iwl_lq_sta { u32 visited_columns; /* Bitmask marking which Tx columns were * explored during a search cycle */ u64 last_tx; bool is_vht; enum ieee80211_band band; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ u16 active_legacy_rate; u16 active_siso_rate; u16 active_mimo2_rate; unsigned long active_legacy_rate; unsigned long active_siso_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 */ u8 missed_rate_counter; Loading Loading
drivers/net/wireless/iwlwifi/iwl-7000.c +3 −2 Original line number Diff line number Diff line Loading @@ -67,8 +67,8 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ #define IWL7260_UCODE_API_MAX 8 #define IWL3160_UCODE_API_MAX 8 #define IWL7260_UCODE_API_MAX 9 #define IWL3160_UCODE_API_MAX 9 /* Oldest version we won't warn about */ #define IWL7260_UCODE_API_OK 8 Loading Loading @@ -244,3 +244,4 @@ const struct iwl_cfg iwl7265_n_cfg = { MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
drivers/net/wireless/iwlwifi/mvm/coex.c +11 −7 Original line number Diff line number Diff line Loading @@ -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(0x0000aaaa), cpu_to_le32(0xc0004000), cpu_to_le32(0x00000000), cpu_to_le32(0x00004000), cpu_to_le32(0xf0005000), cpu_to_le32(0xf0005000), }, Loading @@ -213,16 +213,16 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { /* Tx Tx disabled */ cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xeeaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xcc00ff28), cpu_to_le32(0x0000aaaa), cpu_to_le32(0xcc00aaaa), cpu_to_le32(0x0000aaaa), cpu_to_le32(0xC0004000), cpu_to_le32(0xC0004000), cpu_to_le32(0xF0005000), cpu_to_le32(0xF0005000), cpu_to_le32(0xc0004000), cpu_to_le32(0xc0004000), cpu_to_le32(0xf0005000), cpu_to_le32(0xf0005000), }, }; Loading Loading @@ -1262,6 +1262,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt = rxb_addr(rxb); u32 ant_isolation = le32_to_cpup((void *)pkt->data); u8 __maybe_unused lower_bound, upper_bound; int ret; u8 lut; struct iwl_bt_coex_cmd *bt_cmd; Loading Loading @@ -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, sizeof(bt_cmd->bt4_corun_lut40)); return 0; ret = iwl_mvm_send_cmd(mvm, &cmd); kfree(bt_cmd); return ret; }
drivers/net/wireless/iwlwifi/mvm/mac80211.c +1 −0 Original line number Diff line number Diff line Loading @@ -1332,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, */ iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); iwl_mvm_sf_update(mvm, vif, false); WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS)) { Loading
drivers/net/wireless/iwlwifi/mvm/rs.c +165 −96 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ /* max allowed rate miss before sync LQ cmd */ #define IWL_MISSED_RATE_MAX 15 #define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ) #define RS_IDLE_TIMEOUT (5*HZ) static u8 rs_ht_to_legacy[] = { [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, Loading Loading @@ -142,7 +142,7 @@ enum rs_column_mode { RS_MIMO2, }; #define MAX_NEXT_COLUMNS 5 #define MAX_NEXT_COLUMNS 7 #define MAX_COLUMN_CHECKS 3 typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm, Loading Loading @@ -212,8 +212,10 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_LEGACY_ANT_B, RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_MIMO2_SGI, RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, }, }, [RS_COLUMN_LEGACY_ANT_B] = { Loading @@ -223,8 +225,10 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_MIMO2_SGI, RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, }, }, [RS_COLUMN_SISO_ANT_A] = { Loading @@ -235,7 +239,9 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_MIMO2, RS_COLUMN_SISO_ANT_A_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 = { rs_siso_allow, Loading @@ -249,7 +255,9 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_MIMO2, RS_COLUMN_SISO_ANT_B_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 = { rs_siso_allow, Loading @@ -265,6 +273,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, Loading @@ -281,6 +291,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_B, RS_COLUMN_SISO_ANT_A, RS_COLUMN_MIMO2, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, Loading @@ -296,6 +308,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_MIMO2_SGI, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_mimo_allow, Loading @@ -311,6 +325,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_mimo_allow, Loading Loading @@ -503,10 +519,12 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) 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; IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&tbl->win[i]); } Loading Loading @@ -992,6 +1010,13 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, 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) || info->flags & IEEE80211_TX_CTL_NO_ACK) return; Loading Loading @@ -1034,6 +1059,18 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, 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 */ if ((mac_index < 0) || (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || Loading Loading @@ -1186,6 +1223,23 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy, 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, const struct rs_tx_column *column, u32 bw) Loading Loading @@ -1438,7 +1492,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) IWL_DEBUG_RATE(mvm, "LQ: stay in table clear win\n"); rs_rate_scale_clear_tbl_windows(tbl); rs_rate_scale_clear_tbl_windows(mvm, tbl); } } Loading @@ -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 * "search" table). */ 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(tbl); rs_rate_scale_clear_tbl_windows(mvm, tbl); } } } Loading Loading @@ -1485,14 +1538,14 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_scale_tbl_info *tbl) { int i, j, n; int i, j, max_rate; enum rs_column next_col_id; const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; const struct rs_tx_column *next_col; allow_column_func_t allow_func; u8 valid_ants = mvm->fw->valid_tx_ant; const u16 *expected_tpt_tbl; s32 tpt, max_expected_tpt; u16 tpt, max_expected_tpt; for (i = 0; i < MAX_NEXT_COLUMNS; i++) { next_col_id = curr_col->next_columns[i]; Loading Loading @@ -1535,11 +1588,11 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, if (WARN_ON_ONCE(!expected_tpt_tbl)) continue; max_expected_tpt = 0; for (n = 0; n < IWL_RATE_COUNT; n++) if (expected_tpt_tbl[n] > max_expected_tpt) max_expected_tpt = expected_tpt_tbl[n]; max_rate = rs_get_max_allowed_rate(lq_sta, next_col); if (WARN_ON_ONCE(max_rate == IWL_RATE_INVALID)) continue; max_expected_tpt = expected_tpt_tbl[max_rate]; if (tpt >= max_expected_tpt) { IWL_DEBUG_RATE(mvm, "Skip column %d: can't beat current TPT. Max expected %d current %d\n", Loading @@ -1547,14 +1600,15 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, continue; } IWL_DEBUG_RATE(mvm, "Found potential column %d. Max expected %d current %d\n", next_col_id, max_expected_tpt, tpt); break; } if (i == MAX_NEXT_COLUMNS) return RS_COLUMN_INVALID; IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id); return next_col_id; } Loading Loading @@ -1640,85 +1694,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm, { enum rs_action action = RS_ACTION_STAY; /* Too many failures, decrease rate */ if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { IWL_DEBUG_RATE(mvm, "decrease rate because of low SR\n"); action = 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 (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { "Decrease rate because of low SR\n"); return RS_ACTION_DOWNSCALE; } if ((low_tpt == IWL_INVALID_VALUE) && (high_tpt == IWL_INVALID_VALUE) && (high != IWL_RATE_INVALID)) { IWL_DEBUG_RATE(mvm, "Good SR and no high rate measurement. " "Increase rate\n"); action = RS_ACTION_UPSCALE; } else if (low != IWL_RATE_INVALID) { "No data about high/low rates. Increase rate\n"); return RS_ACTION_UPSCALE; } if ((high_tpt == IWL_INVALID_VALUE) && (high != IWL_RATE_INVALID) && (low_tpt != IWL_INVALID_VALUE) && (low_tpt < current_tpt)) { IWL_DEBUG_RATE(mvm, "Remain in current rate\n"); action = RS_ACTION_STAY; "No data about high rate and low rate is worse. Increase rate\n"); 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 * throughput; we're using the best rate, don't change it! */ else if ((low_tpt != IWL_INVALID_VALUE) && if ((low_tpt != IWL_INVALID_VALUE) && (high_tpt != IWL_INVALID_VALUE) && (low_tpt < current_tpt) && (high_tpt < current_tpt)) { IWL_DEBUG_RATE(mvm, "Both high and low are worse. " "Maintain rate\n"); action = RS_ACTION_STAY; "Both high and low are worse. Maintain rate\n"); return RS_ACTION_STAY; } /* At least one adjacent rate's throughput is measured, * and may have better performance. */ 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) { if ((low_tpt != IWL_INVALID_VALUE) && (low_tpt > current_tpt)) { IWL_DEBUG_RATE(mvm, "Higher rate is better and good " "SR. Increate rate\n"); action = RS_ACTION_UPSCALE; } else { IWL_DEBUG_RATE(mvm, "Higher rate isn't better OR " "no good SR. Maintain rate\n"); action = RS_ACTION_STAY; "Lower rate is better\n"); action = RS_ACTION_DOWNSCALE; goto out; } /* Lower adjacent rate's throughput is measured */ } else if (low_tpt != IWL_INVALID_VALUE) { /* Lower rate has better throughput */ if (low_tpt > current_tpt) { if ((low_tpt == IWL_INVALID_VALUE) && (low != IWL_RATE_INVALID)) { IWL_DEBUG_RATE(mvm, "Lower rate is better. " "Decrease rate\n"); "No data about lower rate\n"); action = RS_ACTION_DOWNSCALE; } else if (sr >= IWL_RATE_INCREASE_TH) { IWL_DEBUG_RATE(mvm, "Lower rate isn't better and " "good SR. Increase rate\n"); action = RS_ACTION_UPSCALE; } } goto out; } /* Sanity check; asked for decrease, but success rate or throughput * has been good at old rate. Don't change it. */ if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) && ((sr > IWL_RATE_HIGH_TH) || (current_tpt > (100 * tbl->expected_tpt[low])))) { IWL_DEBUG_RATE(mvm, "Maintain rate\n"); out: if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) { if (sr >= RS_SR_NO_DECREASE) { IWL_DEBUG_RATE(mvm, "Sanity check failed. Maintain rate\n"); "SR is above NO DECREASE. Avoid downscale\n"); 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; Loading Loading @@ -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", prev_agg, lq_sta->is_agg); rs_set_expected_tpt_table(lq_sta, tbl); rs_rate_scale_clear_tbl_windows(mvm, tbl); } /* current tx rate */ Loading Loading @@ -2021,7 +2067,7 @@ lq_update: if (lq_sta->search_better_tbl) { /* Access the "search" table, clear its history. */ 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 */ index = tbl->rate.index; Loading @@ -2042,8 +2088,18 @@ lq_update: * 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) && !sta->ht_cap.ht_supported) { if (is_legacy(&tbl1->rate)) { 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); } else { /* If we're in an HT mode, and all 3 mode switch actions Loading Loading @@ -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; 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->last_tx = jiffies; IWL_DEBUG_RATE(mvm, "LQ: *** rate scale station global init for station %d ***\n", Loading Loading @@ -2388,11 +2445,22 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lq_sta->is_vht = true; } IWL_DEBUG_RATE(mvm, "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n", lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, 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_mimo2_rate, 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 */ lq_sta->lq.single_stream_ant_msk = Loading Loading @@ -2547,6 +2615,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, if (is_siso(&rate)) { num_rates = RS_SECONDARY_SISO_NUM_RATES; num_retries = RS_SECONDARY_SISO_RETRIES; lq_cmd->mimo_delim = index; } else if (is_legacy(&rate)) { num_rates = RS_SECONDARY_LEGACY_NUM_RATES; num_retries = RS_LEGACY_RETRIES_PER_RATE; Loading Loading @@ -2749,7 +2818,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, return -ENOMEM; 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->active_legacy_rate); desc += sprintf(buff+desc, "fixed rate 0x%X\n", Loading
drivers/net/wireless/iwlwifi/mvm/rs.h +11 −3 Original line number Diff line number Diff line Loading @@ -156,6 +156,7 @@ enum { #define IWL_RATE_HIGH_TH 10880 /* 85% */ #define IWL_RATE_INCREASE_TH 6400 /* 50% */ #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_MAX (8000) Loading Loading @@ -310,13 +311,20 @@ struct iwl_lq_sta { u32 visited_columns; /* Bitmask marking which Tx columns were * explored during a search cycle */ u64 last_tx; bool is_vht; enum ieee80211_band band; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ u16 active_legacy_rate; u16 active_siso_rate; u16 active_mimo2_rate; unsigned long active_legacy_rate; unsigned long active_siso_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 */ u8 missed_rate_counter; Loading