aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-02-03 15:41:58 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-03 15:41:58 -0500
commit1725d409caba16ea5fc694bd50e95e79e8ced11a (patch)
tree688fe26dd4ceda5364692f0ce307aadb6f04f331 /drivers/net/wireless/iwlwifi/iwl-agn-rs.c
parentb3ff29d2ccfe3af065a9b393699a8fbf2abd1b15 (diff)
parentb8abde45d7d6ab9e8ceced9b5990eeb1149d0b97 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rs.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c106
1 files changed, 76 insertions, 30 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 27f50471aed8..13039a024473 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -1,6 +1,6 @@
1/****************************************************************************** 1/******************************************************************************
2 * 2 *
3 * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. 3 * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as 6 * under the terms of version 2 of the GNU General Public License as
@@ -49,6 +49,8 @@
49#define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */ 49#define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */
50#define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */ 50#define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */
51 51
52/* max allowed rate miss before sync LQ cmd */
53#define IWL_MISSED_RATE_MAX 15
52/* max time to accum history 2 seconds */ 54/* max time to accum history 2 seconds */
53#define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ) 55#define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ)
54 56
@@ -148,6 +150,8 @@ struct iwl_lq_sta {
148 u16 active_mimo2_rate; 150 u16 active_mimo2_rate;
149 u16 active_mimo3_rate; 151 u16 active_mimo3_rate;
150 u16 active_rate_basic; 152 u16 active_rate_basic;
153 s8 max_rate_idx; /* Max rate set by user */
154 u8 missed_rate_counter;
151 155
152 struct iwl_link_quality_cmd lq; 156 struct iwl_link_quality_cmd lq;
153 struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ 157 struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
@@ -463,8 +467,9 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
463 * Fill uCode API rate_n_flags field, based on "search" or "active" table. 467 * Fill uCode API rate_n_flags field, based on "search" or "active" table.
464 */ 468 */
465/* FIXME:RS:remove this function and put the flags statically in the table */ 469/* FIXME:RS:remove this function and put the flags statically in the table */
466static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, 470static u32 rate_n_flags_from_tbl(struct iwl_priv *priv,
467 int index, u8 use_green) 471 struct iwl_scale_tbl_info *tbl,
472 int index, u8 use_green)
468{ 473{
469 u32 rate_n_flags = 0; 474 u32 rate_n_flags = 0;
470 475
@@ -475,7 +480,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl,
475 480
476 } else if (is_Ht(tbl->lq_type)) { 481 } else if (is_Ht(tbl->lq_type)) {
477 if (index > IWL_LAST_OFDM_RATE) { 482 if (index > IWL_LAST_OFDM_RATE) {
478 IWL_ERROR("invalid HT rate index %d\n", index); 483 IWL_ERR(priv, "Invalid HT rate index %d\n", index);
479 index = IWL_LAST_OFDM_RATE; 484 index = IWL_LAST_OFDM_RATE;
480 } 485 }
481 rate_n_flags = RATE_MCS_HT_MSK; 486 rate_n_flags = RATE_MCS_HT_MSK;
@@ -487,7 +492,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl,
487 else 492 else
488 rate_n_flags |= iwl_rates[index].plcp_mimo3; 493 rate_n_flags |= iwl_rates[index].plcp_mimo3;
489 } else { 494 } else {
490 IWL_ERROR("Invalid tbl->lq_type %d\n", tbl->lq_type); 495 IWL_ERR(priv, "Invalid tbl->lq_type %d\n", tbl->lq_type);
491 } 496 }
492 497
493 rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & 498 rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) &
@@ -507,7 +512,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl,
507 rate_n_flags |= RATE_MCS_GF_MSK; 512 rate_n_flags |= RATE_MCS_GF_MSK;
508 if (is_siso(tbl->lq_type) && tbl->is_SGI) { 513 if (is_siso(tbl->lq_type) && tbl->is_SGI) {
509 rate_n_flags &= ~RATE_MCS_SGI_MSK; 514 rate_n_flags &= ~RATE_MCS_SGI_MSK;
510 IWL_ERROR("GF was set with SGI:SISO\n"); 515 IWL_ERR(priv, "GF was set with SGI:SISO\n");
511 } 516 }
512 } 517 }
513 } 518 }
@@ -758,7 +763,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
758 low = scale_index; 763 low = scale_index;
759 764
760out: 765out:
761 return rate_n_flags_from_tbl(tbl, low, is_green); 766 return rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green);
762} 767}
763 768
764/* 769/*
@@ -839,10 +844,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
839 /* the last LQ command could failed so the LQ in ucode not 844 /* the last LQ command could failed so the LQ in ucode not
840 * the same in driver sync up 845 * the same in driver sync up
841 */ 846 */
842 iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); 847 lq_sta->missed_rate_counter++;
848 if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
849 lq_sta->missed_rate_counter = 0;
850 iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
851 }
843 goto out; 852 goto out;
844 } 853 }
845 854
855 lq_sta->missed_rate_counter = 0;
846 /* Update frame history window with "failure" for each Tx retry. */ 856 /* Update frame history window with "failure" for each Tx retry. */
847 while (retries) { 857 while (retries) {
848 /* Look up the rate and other info used for each tx attempt. 858 /* Look up the rate and other info used for each tx attempt.
@@ -1129,7 +1139,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
1129 s32 rate; 1139 s32 rate;
1130 s8 is_green = lq_sta->is_green; 1140 s8 is_green = lq_sta->is_green;
1131 1141
1132 if (!conf->ht.enabled || !sta->ht_cap.ht_supported) 1142 if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
1133 return -1; 1143 return -1;
1134 1144
1135 if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) 1145 if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
@@ -1176,7 +1186,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
1176 rate, rate_mask); 1186 rate, rate_mask);
1177 return -1; 1187 return -1;
1178 } 1188 }
1179 tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green); 1189 tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green);
1180 1190
1181 IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", 1191 IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n",
1182 tbl->current_rate, is_green); 1192 tbl->current_rate, is_green);
@@ -1196,7 +1206,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
1196 u8 is_green = lq_sta->is_green; 1206 u8 is_green = lq_sta->is_green;
1197 s32 rate; 1207 s32 rate;
1198 1208
1199 if (!conf->ht.enabled || !sta->ht_cap.ht_supported) 1209 if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
1200 return -1; 1210 return -1;
1201 1211
1202 IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); 1212 IWL_DEBUG_RATE("LQ: try to switch to SISO\n");
@@ -1236,7 +1246,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
1236 rate, rate_mask); 1246 rate, rate_mask);
1237 return -1; 1247 return -1;
1238 } 1248 }
1239 tbl->current_rate = rate_n_flags_from_tbl(tbl, rate, is_green); 1249 tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green);
1240 IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n", 1250 IWL_DEBUG_RATE("LQ: Switch to new mcs %X index is green %X\n",
1241 tbl->current_rate, is_green); 1251 tbl->current_rate, is_green);
1242 return 0; 1252 return 0;
@@ -1430,7 +1440,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
1430 if (!tbl->is_SGI) 1440 if (!tbl->is_SGI)
1431 break; 1441 break;
1432 else 1442 else
1433 IWL_ERROR("SGI was set in GF+SISO\n"); 1443 IWL_ERR(priv,
1444 "SGI was set in GF+SISO\n");
1434 } 1445 }
1435 search_tbl->is_SGI = !tbl->is_SGI; 1446 search_tbl->is_SGI = !tbl->is_SGI;
1436 rs_set_expected_tpt_table(lq_sta, search_tbl); 1447 rs_set_expected_tpt_table(lq_sta, search_tbl);
@@ -1439,8 +1450,9 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
1439 if (tpt >= search_tbl->expected_tpt[index]) 1450 if (tpt >= search_tbl->expected_tpt[index])
1440 break; 1451 break;
1441 } 1452 }
1442 search_tbl->current_rate = rate_n_flags_from_tbl( 1453 search_tbl->current_rate =
1443 search_tbl, index, is_green); 1454 rate_n_flags_from_tbl(priv, search_tbl,
1455 index, is_green);
1444 goto out; 1456 goto out;
1445 } 1457 }
1446 tbl->action++; 1458 tbl->action++;
@@ -1551,8 +1563,9 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
1551 if (tpt >= search_tbl->expected_tpt[index]) 1563 if (tpt >= search_tbl->expected_tpt[index])
1552 break; 1564 break;
1553 } 1565 }
1554 search_tbl->current_rate = rate_n_flags_from_tbl( 1566 search_tbl->current_rate =
1555 search_tbl, index, is_green); 1567 rate_n_flags_from_tbl(priv, search_tbl,
1568 index, is_green);
1556 goto out; 1569 goto out;
1557 1570
1558 } 1571 }
@@ -1745,16 +1758,25 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
1745 rate_scale_index_msk = rate_mask; 1758 rate_scale_index_msk = rate_mask;
1746 1759
1747 if (!((1 << index) & rate_scale_index_msk)) { 1760 if (!((1 << index) & rate_scale_index_msk)) {
1748 IWL_ERROR("Current Rate is not valid\n"); 1761 IWL_ERR(priv, "Current Rate is not valid\n");
1749 return; 1762 return;
1750 } 1763 }
1751 1764
1752 /* Get expected throughput table and history window for current rate */ 1765 /* Get expected throughput table and history window for current rate */
1753 if (!tbl->expected_tpt) { 1766 if (!tbl->expected_tpt) {
1754 IWL_ERROR("tbl->expected_tpt is NULL\n"); 1767 IWL_ERR(priv, "tbl->expected_tpt is NULL\n");
1755 return; 1768 return;
1756 } 1769 }
1757 1770
1771 /* force user max rate if set by user */
1772 if ((lq_sta->max_rate_idx != -1) &&
1773 (lq_sta->max_rate_idx < index)) {
1774 index = lq_sta->max_rate_idx;
1775 update_lq = 1;
1776 window = &(tbl->win[index]);
1777 goto lq_update;
1778 }
1779
1758 window = &(tbl->win[index]); 1780 window = &(tbl->win[index]);
1759 1781
1760 /* 1782 /*
@@ -1846,6 +1868,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
1846 low = high_low & 0xff; 1868 low = high_low & 0xff;
1847 high = (high_low >> 8) & 0xff; 1869 high = (high_low >> 8) & 0xff;
1848 1870
1871 /* If user set max rate, dont allow higher than user constrain */
1872 if ((lq_sta->max_rate_idx != -1) &&
1873 (lq_sta->max_rate_idx < high))
1874 high = IWL_RATE_INVALID;
1875
1849 sr = window->success_ratio; 1876 sr = window->success_ratio;
1850 1877
1851 /* Collect measured throughputs for current and adjacent rates */ 1878 /* Collect measured throughputs for current and adjacent rates */
@@ -1944,7 +1971,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
1944lq_update: 1971lq_update:
1945 /* Replace uCode's rate table for the destination station. */ 1972 /* Replace uCode's rate table for the destination station. */
1946 if (update_lq) { 1973 if (update_lq) {
1947 rate = rate_n_flags_from_tbl(tbl, index, is_green); 1974 rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
1948 rs_fill_link_cmd(priv, lq_sta, rate); 1975 rs_fill_link_cmd(priv, lq_sta, rate);
1949 iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); 1976 iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
1950 } 1977 }
@@ -1993,7 +2020,7 @@ lq_update:
1993 * stay with best antenna legacy modulation for a while 2020 * stay with best antenna legacy modulation for a while
1994 * before next round of mode comparisons. */ 2021 * before next round of mode comparisons. */
1995 tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); 2022 tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
1996 if (is_legacy(tbl1->lq_type) && !conf->ht.enabled && 2023 if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) &&
1997 lq_sta->action_counter >= 1) { 2024 lq_sta->action_counter >= 1) {
1998 lq_sta->action_counter = 0; 2025 lq_sta->action_counter = 0;
1999 IWL_DEBUG_RATE("LQ: STAY in legacy table\n"); 2026 IWL_DEBUG_RATE("LQ: STAY in legacy table\n");
@@ -2028,7 +2055,7 @@ lq_update:
2028 } 2055 }
2029 2056
2030out: 2057out:
2031 tbl->current_rate = rate_n_flags_from_tbl(tbl, index, is_green); 2058 tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
2032 i = index; 2059 i = index;
2033 lq_sta->last_txrate_idx = i; 2060 lq_sta->last_txrate_idx = i;
2034 2061
@@ -2081,7 +2108,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
2081 if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) 2108 if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
2082 rs_toggle_antenna(valid_tx_ant, &rate, tbl); 2109 rs_toggle_antenna(valid_tx_ant, &rate, tbl);
2083 2110
2084 rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green); 2111 rate = rate_n_flags_from_tbl(priv, tbl, rate_idx, use_green);
2085 tbl->current_rate = rate; 2112 tbl->current_rate = rate;
2086 rs_set_expected_tpt_table(lq_sta, tbl); 2113 rs_set_expected_tpt_table(lq_sta, tbl);
2087 rs_fill_link_cmd(NULL, lq_sta, rate); 2114 rs_fill_link_cmd(NULL, lq_sta, rate);
@@ -2106,6 +2133,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
2106 2133
2107 IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); 2134 IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
2108 2135
2136 /* Get max rate if user set max rate */
2137 if (lq_sta) {
2138 lq_sta->max_rate_idx = txrc->max_rate_idx;
2139 if ((sband->band == IEEE80211_BAND_5GHZ) &&
2140 (lq_sta->max_rate_idx != -1))
2141 lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE;
2142 if ((lq_sta->max_rate_idx < 0) ||
2143 (lq_sta->max_rate_idx >= IWL_RATE_COUNT))
2144 lq_sta->max_rate_idx = -1;
2145 }
2146
2109 if (sta) 2147 if (sta)
2110 mask_bit = sta->supp_rates[sband->band]; 2148 mask_bit = sta->supp_rates[sband->band];
2111 2149
@@ -2182,6 +2220,8 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
2182 struct ieee80211_conf *conf = &priv->hw->conf; 2220 struct ieee80211_conf *conf = &priv->hw->conf;
2183 struct iwl_lq_sta *lq_sta = priv_sta; 2221 struct iwl_lq_sta *lq_sta = priv_sta;
2184 u16 mask_bit = 0; 2222 u16 mask_bit = 0;
2223 int count;
2224 int start_rate = 0;
2185 2225
2186 lq_sta->flush_timer = 0; 2226 lq_sta->flush_timer = 0;
2187 lq_sta->supp_rates = sta->supp_rates[sband->band]; 2227 lq_sta->supp_rates = sta->supp_rates[sband->band];
@@ -2216,6 +2256,8 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
2216 } 2256 }
2217 2257
2218 lq_sta->is_dup = 0; 2258 lq_sta->is_dup = 0;
2259 lq_sta->max_rate_idx = -1;
2260 lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
2219 lq_sta->is_green = rs_use_green(priv, conf); 2261 lq_sta->is_green = rs_use_green(priv, conf);
2220 lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); 2262 lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
2221 lq_sta->active_rate_basic = priv->active_rate_basic; 2263 lq_sta->active_rate_basic = priv->active_rate_basic;
@@ -2254,16 +2296,20 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
2254 lq_sta->drv = priv; 2296 lq_sta->drv = priv;
2255 2297
2256 /* Find highest tx rate supported by hardware and destination station */ 2298 /* Find highest tx rate supported by hardware and destination station */
2257 mask_bit = sta->supp_rates[sband->band] & lq_sta->active_legacy_rate; 2299 mask_bit = sta->supp_rates[sband->band];
2258 lq_sta->last_txrate_idx = 3; 2300 count = sband->n_bitrates;
2259 for (i = 0; i < sband->n_bitrates; i++) 2301 if (sband->band == IEEE80211_BAND_5GHZ) {
2302 count += IWL_FIRST_OFDM_RATE;
2303 start_rate = IWL_FIRST_OFDM_RATE;
2304 mask_bit <<= IWL_FIRST_OFDM_RATE;
2305 }
2306
2307 mask_bit = mask_bit & lq_sta->active_legacy_rate;
2308 lq_sta->last_txrate_idx = 4;
2309 for (i = start_rate; i < count; i++)
2260 if (mask_bit & BIT(i)) 2310 if (mask_bit & BIT(i))
2261 lq_sta->last_txrate_idx = i; 2311 lq_sta->last_txrate_idx = i;
2262 2312
2263 /* For MODE_IEEE80211A, skip over cck rates in global rate table */
2264 if (sband->band == IEEE80211_BAND_5GHZ)
2265 lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
2266
2267 rs_initialize_lq(priv, conf, sta, lq_sta); 2313 rs_initialize_lq(priv, conf, sta, lq_sta);
2268} 2314}
2269 2315