aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEyal Shapira <eyal@wizery.com>2013-12-09 06:02:56 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2013-12-17 12:39:54 -0500
commite07be6d3fe0d7e3aa53ff294a2c9f83fb8355a64 (patch)
treeb31552c733220c46991f96a8d3997a90874c3295
parentca6f38ff4b17855692a920493aca6af50a8c2ffd (diff)
iwlwifi: mvm: rs: improve rates table algo
The new logic will attempt more rates with less retries per rate. Also when starting off with MIMO it will fallback to SISO with the same MCS and only then to Legacy. Previously we fell back directly to Legacy. Signed-off-by: Eyal Shapira <eyal@wizery.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c254
1 files changed, 151 insertions, 103 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 30470d48aaa3..bc8603254219 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -42,9 +42,16 @@
42 42
43#define RS_NAME "iwl-mvm-rs" 43#define RS_NAME "iwl-mvm-rs"
44 44
45#define NUM_TRY_BEFORE_ANT_TOGGLE 1 45#define NUM_TRY_BEFORE_ANT_TOGGLE 1
46#define IWL_NUMBER_TRY 1 46#define RS_LEGACY_RETRIES_PER_RATE 1
47#define IWL_HT_NUMBER_TRY 3 47#define RS_HT_VHT_RETRIES_PER_RATE 2
48#define RS_HT_VHT_RETRIES_PER_RATE_TW 1
49#define RS_INITIAL_MIMO_NUM_RATES 3
50#define RS_INITIAL_SISO_NUM_RATES 3
51#define RS_INITIAL_LEGACY_NUM_RATES LINK_QUAL_MAX_RETRY_NUM
52#define RS_SECONDARY_LEGACY_NUM_RATES LINK_QUAL_MAX_RETRY_NUM
53#define RS_SECONDARY_SISO_NUM_RATES 3
54#define RS_SECONDARY_SISO_RETRIES 1
48 55
49#define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ 56#define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */
50#define IWL_RATE_MIN_FAILURE_TH 3 /* min failures to calc tpt */ 57#define IWL_RATE_MIN_FAILURE_TH 3 /* min failures to calc tpt */
@@ -847,54 +854,73 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask,
847 return (high << 8) | low; 854 return (high << 8) | low;
848} 855}
849 856
850static void rs_get_lower_rate(struct iwl_lq_sta *lq_sta, 857static inline bool rs_rate_supported(struct iwl_lq_sta *lq_sta,
851 struct rs_rate *rate, 858 struct rs_rate *rate)
852 u8 scale_index, u8 ht_possible)
853{ 859{
854 s32 low; 860 return BIT(rate->index) & rs_get_supported_rates(lq_sta, rate);
855 u16 rate_mask; 861}
862
863/* Get the next supported lower rate in the current column.
864 * Return true if bottom rate in the current column was reached
865 */
866static bool rs_get_lower_rate_in_column(struct iwl_lq_sta *lq_sta,
867 struct rs_rate *rate)
868{
869 u8 low;
856 u16 high_low; 870 u16 high_low;
857 u8 switch_to_legacy = 0; 871 u16 rate_mask;
872 struct iwl_mvm *mvm = lq_sta->drv;
873
874 rate_mask = rs_get_supported_rates(lq_sta, rate);
875 high_low = rs_get_adjacent_rate(mvm, rate->index, rate_mask,
876 rate->type);
877 low = high_low & 0xff;
878
879 /* Bottom rate of column reached */
880 if (low == IWL_RATE_INVALID)
881 return true;
882
883 rate->index = low;
884 return false;
885}
886
887/* Get the next rate to use following a column downgrade */
888static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
889 struct rs_rate *rate)
890{
858 struct iwl_mvm *mvm = lq_sta->drv; 891 struct iwl_mvm *mvm = lq_sta->drv;
859 892
860 /* check if we need to switch from HT to legacy rates. 893 if (is_legacy(rate)) {
861 * assumption is that mandatory rates (1Mbps or 6Mbps) 894 /* No column to downgrade from Legacy */
862 * are always supported (spec demand) */ 895 return;
863 if (!is_legacy(rate) && (!ht_possible || !scale_index)) { 896 } else if (is_siso(rate)) {
864 switch_to_legacy = 1; 897 /* Downgrade to Legacy if we were in SISO */
865 WARN_ON_ONCE(scale_index < IWL_RATE_MCS_0_INDEX &&
866 scale_index > IWL_RATE_MCS_9_INDEX);
867 scale_index = rs_ht_to_legacy[scale_index];
868 if (lq_sta->band == IEEE80211_BAND_5GHZ) 898 if (lq_sta->band == IEEE80211_BAND_5GHZ)
869 rate->type = LQ_LEGACY_A; 899 rate->type = LQ_LEGACY_A;
870 else 900 else
871 rate->type = LQ_LEGACY_G; 901 rate->type = LQ_LEGACY_G;
872 902
873 if (num_of_ant(rate->ant) > 1)
874 rate->ant =
875 first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
876
877 rate->bw = RATE_MCS_CHAN_WIDTH_20; 903 rate->bw = RATE_MCS_CHAN_WIDTH_20;
878 rate->sgi = false;
879 }
880 904
881 rate_mask = rs_get_supported_rates(lq_sta, rate); 905 WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX &&
906 rate->index > IWL_RATE_MCS_9_INDEX);
882 907
883 /* If we switched from HT to legacy, check current rate */ 908 rate->index = rs_ht_to_legacy[rate->index];
884 if (switch_to_legacy && (rate_mask & (1 << scale_index))) { 909 } else {
885 low = scale_index; 910 /* Downgrade to SISO with same MCS if in MIMO */
886 goto out; 911 rate->type = is_vht_mimo2(rate) ?
912 LQ_VHT_SISO : LQ_HT_SISO;
887 } 913 }
888 914
889 high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask,
890 rate->type);
891 low = high_low & 0xff;
892 915
893 if (low == IWL_RATE_INVALID) 916 if (num_of_ant(rate->ant) > 1)
894 low = scale_index; 917 rate->ant = first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
895 918
896out: 919 /* Relevant in both switching to SISO or Legacy */
897 rate->index = low; 920 rate->sgi = false;
921
922 if (!rs_rate_supported(lq_sta, rate))
923 rs_get_lower_rate_in_column(lq_sta, rate);
898} 924}
899 925
900/* Simple function to compare two rate scale table types */ 926/* Simple function to compare two rate scale table types */
@@ -2333,96 +2359,118 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
2333} 2359}
2334#endif /* CONFIG_MAC80211_DEBUGFS */ 2360#endif /* CONFIG_MAC80211_DEBUGFS */
2335 2361
2362static void rs_fill_rates_for_column(struct iwl_mvm *mvm,
2363 struct iwl_lq_sta *lq_sta,
2364 struct rs_rate *rate,
2365 __le32 *rs_table, int *rs_table_index,
2366 int num_rates, int num_retries,
2367 u8 valid_tx_ant, bool toggle_ant)
2368{
2369 int i, j;
2370 __le32 ucode_rate;
2371 bool bottom_reached = false;
2372 int prev_rate_idx = rate->index;
2373 int end = LINK_QUAL_MAX_RETRY_NUM;
2374 int index = *rs_table_index;
2375
2376 for (i = 0; i < num_rates && index < end; i++) {
2377 ucode_rate = cpu_to_le32(ucode_rate_from_rs_rate(mvm, rate));
2378 for (j = 0; j < num_retries && index < end; j++, index++)
2379 rs_table[index] = ucode_rate;
2380
2381 if (toggle_ant)
2382 rs_toggle_antenna(valid_tx_ant, rate);
2383
2384 prev_rate_idx = rate->index;
2385 bottom_reached = rs_get_lower_rate_in_column(lq_sta, rate);
2386 if (bottom_reached && !is_legacy(rate))
2387 break;
2388 }
2389
2390 if (!bottom_reached)
2391 rate->index = prev_rate_idx;
2392
2393 *rs_table_index = index;
2394}
2395
2396/* Building the rate table is non trivial. When we're in MIMO2/VHT/80Mhz/SGI
2397 * column the rate table should look like this:
2398 *
2399 * rate[0] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
2400 * rate[1] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
2401 * rate[2] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
2402 * rate[3] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
2403 * rate[4] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
2404 * rate[5] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
2405 * rate[6] 0x4005007 VHT | ANT: A BW: 80Mhz MCS: 7 NSS: 1 NGI
2406 * rate[7] 0x4009006 VHT | ANT: B BW: 80Mhz MCS: 6 NSS: 1 NGI
2407 * rate[8] 0x4005005 VHT | ANT: A BW: 80Mhz MCS: 5 NSS: 1 NGI
2408 * rate[9] 0x800B Legacy | ANT: B Rate: 36 Mbps
2409 * rate[10] 0x4009 Legacy | ANT: A Rate: 24 Mbps
2410 * rate[11] 0x8007 Legacy | ANT: B Rate: 18 Mbps
2411 * rate[12] 0x4005 Legacy | ANT: A Rate: 12 Mbps
2412 * rate[13] 0x800F Legacy | ANT: B Rate: 9 Mbps
2413 * rate[14] 0x400D Legacy | ANT: A Rate: 6 Mbps
2414 * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps
2415 */
2336static void rs_build_rates_table(struct iwl_mvm *mvm, 2416static void rs_build_rates_table(struct iwl_mvm *mvm,
2337 struct iwl_lq_sta *lq_sta, 2417 struct iwl_lq_sta *lq_sta,
2338 const struct rs_rate *initial_rate) 2418 const struct rs_rate *initial_rate)
2339{ 2419{
2340 struct rs_rate rate; 2420 struct rs_rate rate;
2341 int index = 0; 2421 int num_rates, num_retries, index = 0;
2342 int repeat_rate = 0;
2343 u8 ant_toggle_cnt = 0;
2344 u8 use_ht_possible = 1;
2345 u8 valid_tx_ant = 0; 2422 u8 valid_tx_ant = 0;
2346 struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; 2423 struct iwl_lq_cmd *lq_cmd = &lq_sta->lq;
2424 bool toggle_ant = false;
2347 2425
2348 memcpy(&rate, initial_rate, sizeof(struct rs_rate)); 2426 memcpy(&rate, initial_rate, sizeof(struct rs_rate));
2349 2427
2350 lq_cmd->mimo_delim = is_mimo(&rate) ? 1 : 0; 2428 if (mvm)
2351 2429 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
2352 /* Fill 1st table entry (index 0) */
2353 lq_cmd->rs_table[index] = cpu_to_le32(
2354 ucode_rate_from_rs_rate(mvm, &rate));
2355 2430
2356 /* How many times should we repeat the initial rate? */ 2431 if (is_siso(&rate)) {
2357 if (is_legacy(&rate)) { 2432 num_rates = RS_INITIAL_SISO_NUM_RATES;
2358 ant_toggle_cnt = 1; 2433 num_retries = RS_HT_VHT_RETRIES_PER_RATE;
2359 repeat_rate = IWL_NUMBER_TRY; 2434 } else if (is_mimo(&rate)) {
2435 num_rates = RS_INITIAL_MIMO_NUM_RATES;
2436 num_retries = RS_HT_VHT_RETRIES_PER_RATE;
2360 } else { 2437 } else {
2361 repeat_rate = min(IWL_HT_NUMBER_TRY, 2438 num_rates = RS_INITIAL_LEGACY_NUM_RATES;
2362 LINK_QUAL_AGG_DISABLE_START_DEF - 1); 2439 num_retries = RS_LEGACY_RETRIES_PER_RATE;
2440 toggle_ant = true;
2363 } 2441 }
2364 2442
2365 index++; 2443 rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index,
2366 repeat_rate--; 2444 num_rates, num_retries, valid_tx_ant,
2367 if (mvm) 2445 toggle_ant);
2368 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
2369 2446
2370 /* Fill rest of rate table */ 2447 rs_get_lower_rate_down_column(lq_sta, &rate);
2371 while (index < LINK_QUAL_MAX_RETRY_NUM) {
2372 /* Repeat initial/next rate.
2373 * For legacy IWL_NUMBER_TRY == 1, this loop will not execute.
2374 * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
2375 while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
2376 if (is_legacy(&rate)) {
2377 if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
2378 ant_toggle_cnt++;
2379 else if (mvm &&
2380 rs_toggle_antenna(valid_tx_ant, &rate))
2381 ant_toggle_cnt = 1;
2382 }
2383
2384 /* Fill next table entry */
2385 lq_cmd->rs_table[index] = cpu_to_le32(
2386 ucode_rate_from_rs_rate(mvm, &rate));
2387 repeat_rate--;
2388 index++;
2389 }
2390 2448
2391 /* Indicate to uCode which entries might be MIMO. 2449 if (is_siso(&rate)) {
2392 * If initial rate was MIMO, this will finally end up 2450 num_rates = RS_SECONDARY_SISO_NUM_RATES;
2393 * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ 2451 num_retries = RS_SECONDARY_SISO_RETRIES;
2394 if (is_mimo(&rate)) 2452 } else if (is_legacy(&rate)) {
2395 lq_cmd->mimo_delim = index; 2453 num_rates = RS_SECONDARY_LEGACY_NUM_RATES;
2454 num_retries = RS_LEGACY_RETRIES_PER_RATE;
2455 } else {
2456 WARN_ON_ONCE(1);
2457 }
2396 2458
2397 /* Get next rate */ 2459 toggle_ant = true;
2398 rs_get_lower_rate(lq_sta, &rate, rate.index, use_ht_possible);
2399 2460
2400 /* How many times should we repeat the next rate? */ 2461 rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index,
2401 if (is_legacy(&rate)) { 2462 num_rates, num_retries, valid_tx_ant,
2402 if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) 2463 toggle_ant);
2403 ant_toggle_cnt++;
2404 else if (mvm &&
2405 rs_toggle_antenna(valid_tx_ant, &rate))
2406 ant_toggle_cnt = 1;
2407 2464
2408 repeat_rate = IWL_NUMBER_TRY; 2465 rs_get_lower_rate_down_column(lq_sta, &rate);
2409 } else {
2410 repeat_rate = IWL_HT_NUMBER_TRY;
2411 }
2412 2466
2413 /* Don't allow HT rates after next pass. 2467 num_rates = RS_SECONDARY_LEGACY_NUM_RATES;
2414 * rs_get_lower_rate() will change type to LQ_LEGACY_A 2468 num_retries = RS_LEGACY_RETRIES_PER_RATE;
2415 * or LQ_LEGACY_G.
2416 */
2417 use_ht_possible = 0;
2418 2469
2419 /* Fill next table entry */ 2470 rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index,
2420 lq_cmd->rs_table[index] = cpu_to_le32( 2471 num_rates, num_retries, valid_tx_ant,
2421 ucode_rate_from_rs_rate(mvm, &rate)); 2472 toggle_ant);
2422 2473
2423 index++;
2424 repeat_rate--;
2425 }
2426} 2474}
2427 2475
2428static void rs_fill_lq_cmd(struct iwl_mvm *mvm, 2476static void rs_fill_lq_cmd(struct iwl_mvm *mvm,