aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
diff options
context:
space:
mode:
authorRon Rindjunsky <ron.rindjunsky@intel.com>2007-11-26 09:14:41 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:05:45 -0500
commit270243a50574455f593378377c0fa74284730f7d (patch)
treec93569a41c64cc5b79060a10d35c09f842a7ab16 /drivers/net/wireless/iwlwifi/iwl-4965-rs.c
parent67d620357a186adc0f4e7d1f5b095ea2c77e7072 (diff)
iwlwifi: 802.11n comply HT rate scaling flows with mac80211 framework
This patch conforms the rate scaling flows according to the new mac80211's HT framework Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965-rs.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-rs.c93
1 files changed, 57 insertions, 36 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index 503b91745167..229b34199f92 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -498,15 +498,14 @@ static inline void rs_toggle_antenna(struct iwl4965_rate *new_rate,
498 } 498 }
499} 499}
500 500
501static inline u8 rs_use_green(struct iwl4965_priv *priv) 501static inline u8 rs_use_green(struct iwl4965_priv *priv,
502 struct ieee80211_conf *conf)
502{ 503{
503#ifdef CONFIG_IWL4965_HT 504#ifdef CONFIG_IWL4965_HT
504 if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht) 505 return ((conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
505 return 0; 506 priv->current_ht_config.is_green_field &&
506 507 !priv->current_ht_config.non_GF_STA_present);
507 return ((priv->current_assoc_ht.is_green_field) && 508#endif /* CONFIG_IWL4965_HT */
508 !(priv->current_assoc_ht.operating_mode & 0x4));
509#endif /*CONFIG_IWL4965_HT */
510 return 0; 509 return 0;
511} 510}
512 511
@@ -1047,6 +1046,8 @@ static inline u8 rs_is_both_ant_supp(u8 valid_antenna)
1047 */ 1046 */
1048static int rs_switch_to_mimo(struct iwl4965_priv *priv, 1047static int rs_switch_to_mimo(struct iwl4965_priv *priv,
1049 struct iwl4965_rate_scale_priv *lq_data, 1048 struct iwl4965_rate_scale_priv *lq_data,
1049 struct ieee80211_conf *conf,
1050 struct sta_info *sta,
1050 struct iwl4965_scale_tbl_info *tbl, int index) 1051 struct iwl4965_scale_tbl_info *tbl, int index)
1051{ 1052{
1052#ifdef CONFIG_IWL4965_HT 1053#ifdef CONFIG_IWL4965_HT
@@ -1054,7 +1055,8 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv,
1054 s32 rate; 1055 s32 rate;
1055 s8 is_green = lq_data->is_green; 1056 s8 is_green = lq_data->is_green;
1056 1057
1057 if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht) 1058 if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
1059 !sta->ht_info.ht_supported)
1058 return -1; 1060 return -1;
1059 1061
1060 IWL_DEBUG_HT("LQ: try to switch to MIMO\n"); 1062 IWL_DEBUG_HT("LQ: try to switch to MIMO\n");
@@ -1062,7 +1064,7 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv,
1062 rs_get_supported_rates(lq_data, NULL, tbl->lq_type, 1064 rs_get_supported_rates(lq_data, NULL, tbl->lq_type,
1063 &rate_mask); 1065 &rate_mask);
1064 1066
1065 if (priv->current_assoc_ht.tx_mimo_ps_mode == IWL_MIMO_PS_STATIC) 1067 if (priv->current_ht_config.tx_mimo_ps_mode == IWL_MIMO_PS_STATIC)
1066 return -1; 1068 return -1;
1067 1069
1068 /* Need both Tx chains/antennas to support MIMO */ 1070 /* Need both Tx chains/antennas to support MIMO */
@@ -1071,17 +1073,18 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv,
1071 1073
1072 tbl->is_dup = lq_data->is_dup; 1074 tbl->is_dup = lq_data->is_dup;
1073 tbl->action = 0; 1075 tbl->action = 0;
1074 if (priv->current_channel_width == IWL_CHANNEL_WIDTH_40MHZ) 1076 if (priv->current_ht_config.supported_chan_width
1077 == IWL_CHANNEL_WIDTH_40MHZ)
1075 tbl->is_fat = 1; 1078 tbl->is_fat = 1;
1076 else 1079 else
1077 tbl->is_fat = 0; 1080 tbl->is_fat = 0;
1078 1081
1079 if (tbl->is_fat) { 1082 if (tbl->is_fat) {
1080 if (priv->current_assoc_ht.sgf & HT_SHORT_GI_40MHZ_ONLY) 1083 if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
1081 tbl->is_SGI = 1; 1084 tbl->is_SGI = 1;
1082 else 1085 else
1083 tbl->is_SGI = 0; 1086 tbl->is_SGI = 0;
1084 } else if (priv->current_assoc_ht.sgf & HT_SHORT_GI_20MHZ_ONLY) 1087 } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
1085 tbl->is_SGI = 1; 1088 tbl->is_SGI = 1;
1086 else 1089 else
1087 tbl->is_SGI = 0; 1090 tbl->is_SGI = 0;
@@ -1108,6 +1111,8 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv,
1108 */ 1111 */
1109static int rs_switch_to_siso(struct iwl4965_priv *priv, 1112static int rs_switch_to_siso(struct iwl4965_priv *priv,
1110 struct iwl4965_rate_scale_priv *lq_data, 1113 struct iwl4965_rate_scale_priv *lq_data,
1114 struct ieee80211_conf *conf,
1115 struct sta_info *sta,
1111 struct iwl4965_scale_tbl_info *tbl, int index) 1116 struct iwl4965_scale_tbl_info *tbl, int index)
1112{ 1117{
1113#ifdef CONFIG_IWL4965_HT 1118#ifdef CONFIG_IWL4965_HT
@@ -1116,7 +1121,8 @@ static int rs_switch_to_siso(struct iwl4965_priv *priv,
1116 s32 rate; 1121 s32 rate;
1117 1122
1118 IWL_DEBUG_HT("LQ: try to switch to SISO\n"); 1123 IWL_DEBUG_HT("LQ: try to switch to SISO\n");
1119 if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht) 1124 if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
1125 !sta->ht_info.ht_supported)
1120 return -1; 1126 return -1;
1121 1127
1122 tbl->is_dup = lq_data->is_dup; 1128 tbl->is_dup = lq_data->is_dup;
@@ -1125,17 +1131,18 @@ static int rs_switch_to_siso(struct iwl4965_priv *priv,
1125 rs_get_supported_rates(lq_data, NULL, tbl->lq_type, 1131 rs_get_supported_rates(lq_data, NULL, tbl->lq_type,
1126 &rate_mask); 1132 &rate_mask);
1127 1133
1128 if (priv->current_channel_width == IWL_CHANNEL_WIDTH_40MHZ) 1134 if (priv->current_ht_config.supported_chan_width
1135 == IWL_CHANNEL_WIDTH_40MHZ)
1129 tbl->is_fat = 1; 1136 tbl->is_fat = 1;
1130 else 1137 else
1131 tbl->is_fat = 0; 1138 tbl->is_fat = 0;
1132 1139
1133 if (tbl->is_fat) { 1140 if (tbl->is_fat) {
1134 if (priv->current_assoc_ht.sgf & HT_SHORT_GI_40MHZ_ONLY) 1141 if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
1135 tbl->is_SGI = 1; 1142 tbl->is_SGI = 1;
1136 else 1143 else
1137 tbl->is_SGI = 0; 1144 tbl->is_SGI = 0;
1138 } else if (priv->current_assoc_ht.sgf & HT_SHORT_GI_20MHZ_ONLY) 1145 } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
1139 tbl->is_SGI = 1; 1146 tbl->is_SGI = 1;
1140 else 1147 else
1141 tbl->is_SGI = 0; 1148 tbl->is_SGI = 0;
@@ -1167,6 +1174,8 @@ static int rs_switch_to_siso(struct iwl4965_priv *priv,
1167 */ 1174 */
1168static int rs_move_legacy_other(struct iwl4965_priv *priv, 1175static int rs_move_legacy_other(struct iwl4965_priv *priv,
1169 struct iwl4965_rate_scale_priv *lq_data, 1176 struct iwl4965_rate_scale_priv *lq_data,
1177 struct ieee80211_conf *conf,
1178 struct sta_info *sta,
1170 int index) 1179 int index)
1171{ 1180{
1172 int ret = 0; 1181 int ret = 0;
@@ -1213,8 +1222,8 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv,
1213 search_tbl->lq_type = LQ_SISO; 1222 search_tbl->lq_type = LQ_SISO;
1214 search_tbl->is_SGI = 0; 1223 search_tbl->is_SGI = 0;
1215 search_tbl->is_fat = 0; 1224 search_tbl->is_fat = 0;
1216 ret = rs_switch_to_siso(priv, lq_data, search_tbl, 1225 ret = rs_switch_to_siso(priv, lq_data, conf, sta,
1217 index); 1226 search_tbl, index);
1218 if (!ret) { 1227 if (!ret) {
1219 lq_data->search_better_tbl = 1; 1228 lq_data->search_better_tbl = 1;
1220 lq_data->action_counter = 0; 1229 lq_data->action_counter = 0;
@@ -1231,8 +1240,8 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv,
1231 search_tbl->is_SGI = 0; 1240 search_tbl->is_SGI = 0;
1232 search_tbl->is_fat = 0; 1241 search_tbl->is_fat = 0;
1233 search_tbl->antenna_type = ANT_BOTH; 1242 search_tbl->antenna_type = ANT_BOTH;
1234 ret = rs_switch_to_mimo(priv, lq_data, search_tbl, 1243 ret = rs_switch_to_mimo(priv, lq_data, conf, sta,
1235 index); 1244 search_tbl, index);
1236 if (!ret) { 1245 if (!ret) {
1237 lq_data->search_better_tbl = 1; 1246 lq_data->search_better_tbl = 1;
1238 lq_data->action_counter = 0; 1247 lq_data->action_counter = 0;
@@ -1263,6 +1272,8 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv,
1263 */ 1272 */
1264static int rs_move_siso_to_other(struct iwl4965_priv *priv, 1273static int rs_move_siso_to_other(struct iwl4965_priv *priv,
1265 struct iwl4965_rate_scale_priv *lq_data, 1274 struct iwl4965_rate_scale_priv *lq_data,
1275 struct ieee80211_conf *conf,
1276 struct sta_info *sta,
1266 int index) 1277 int index)
1267{ 1278{
1268 int ret; 1279 int ret;
@@ -1303,8 +1314,8 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv,
1303 search_tbl->is_SGI = 0; 1314 search_tbl->is_SGI = 0;
1304 search_tbl->is_fat = 0; 1315 search_tbl->is_fat = 0;
1305 search_tbl->antenna_type = ANT_BOTH; 1316 search_tbl->antenna_type = ANT_BOTH;
1306 ret = rs_switch_to_mimo(priv, lq_data, search_tbl, 1317 ret = rs_switch_to_mimo(priv, lq_data, conf, sta,
1307 index); 1318 search_tbl, index);
1308 if (!ret) { 1319 if (!ret) {
1309 lq_data->search_better_tbl = 1; 1320 lq_data->search_better_tbl = 1;
1310 goto out; 1321 goto out;
@@ -1356,6 +1367,8 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv,
1356 */ 1367 */
1357static int rs_move_mimo_to_other(struct iwl4965_priv *priv, 1368static int rs_move_mimo_to_other(struct iwl4965_priv *priv,
1358 struct iwl4965_rate_scale_priv *lq_data, 1369 struct iwl4965_rate_scale_priv *lq_data,
1370 struct ieee80211_conf *conf,
1371 struct sta_info *sta,
1359 int index) 1372 int index)
1360{ 1373{
1361 int ret; 1374 int ret;
@@ -1385,8 +1398,8 @@ static int rs_move_mimo_to_other(struct iwl4965_priv *priv,
1385 else 1398 else
1386 search_tbl->antenna_type = ANT_AUX; 1399 search_tbl->antenna_type = ANT_AUX;
1387 1400
1388 ret = rs_switch_to_siso(priv, lq_data, search_tbl, 1401 ret = rs_switch_to_siso(priv, lq_data, conf, sta,
1389 index); 1402 search_tbl, index);
1390 if (!ret) { 1403 if (!ret) {
1391 lq_data->search_better_tbl = 1; 1404 lq_data->search_better_tbl = 1;
1392 goto out; 1405 goto out;
@@ -1536,6 +1549,9 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
1536 struct ieee80211_hdr *hdr, 1549 struct ieee80211_hdr *hdr,
1537 struct sta_info *sta) 1550 struct sta_info *sta)
1538{ 1551{
1552 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1553 struct ieee80211_hw *hw = local_to_hw(local);
1554 struct ieee80211_conf *conf = &hw->conf;
1539 int low = IWL_RATE_INVALID; 1555 int low = IWL_RATE_INVALID;
1540 int high = IWL_RATE_INVALID; 1556 int high = IWL_RATE_INVALID;
1541 int index; 1557 int index;
@@ -1851,11 +1867,11 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
1851 /* Select a new "search" modulation mode to try. 1867 /* Select a new "search" modulation mode to try.
1852 * If one is found, set up the new "search" table. */ 1868 * If one is found, set up the new "search" table. */
1853 if (is_legacy(tbl->lq_type)) 1869 if (is_legacy(tbl->lq_type))
1854 rs_move_legacy_other(priv, lq_data, index); 1870 rs_move_legacy_other(priv, lq_data, conf, sta, index);
1855 else if (is_siso(tbl->lq_type)) 1871 else if (is_siso(tbl->lq_type))
1856 rs_move_siso_to_other(priv, lq_data, index); 1872 rs_move_siso_to_other(priv, lq_data, conf, sta, index);
1857 else 1873 else
1858 rs_move_mimo_to_other(priv, lq_data, index); 1874 rs_move_mimo_to_other(priv, lq_data, conf, sta, index);
1859 1875
1860 /* If new "search" mode was selected, set up in uCode table */ 1876 /* If new "search" mode was selected, set up in uCode table */
1861 if (lq_data->search_better_tbl) { 1877 if (lq_data->search_better_tbl) {
@@ -1883,7 +1899,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
1883 tbl1 = &(lq_data->lq_info[lq_data->active_tbl]); 1899 tbl1 = &(lq_data->lq_info[lq_data->active_tbl]);
1884 if (is_legacy(tbl1->lq_type) && 1900 if (is_legacy(tbl1->lq_type) &&
1885#ifdef CONFIG_IWL4965_HT 1901#ifdef CONFIG_IWL4965_HT
1886 !priv->current_assoc_ht.is_ht && 1902 (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) &&
1887#endif 1903#endif
1888 (lq_data->action_counter >= 1)) { 1904 (lq_data->action_counter >= 1)) {
1889 lq_data->action_counter = 0; 1905 lq_data->action_counter = 0;
@@ -1939,6 +1955,7 @@ out:
1939 1955
1940 1956
1941static void rs_initialize_lq(struct iwl4965_priv *priv, 1957static void rs_initialize_lq(struct iwl4965_priv *priv,
1958 struct ieee80211_conf *conf,
1942 struct sta_info *sta) 1959 struct sta_info *sta)
1943{ 1960{
1944 int i; 1961 int i;
@@ -1946,7 +1963,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
1946 struct iwl4965_scale_tbl_info *tbl; 1963 struct iwl4965_scale_tbl_info *tbl;
1947 u8 active_tbl = 0; 1964 u8 active_tbl = 0;
1948 int rate_idx; 1965 int rate_idx;
1949 u8 use_green = rs_use_green(priv); 1966 u8 use_green = rs_use_green(priv, conf);
1950 struct iwl4965_rate mcs_rate; 1967 struct iwl4965_rate mcs_rate;
1951 1968
1952 if (!sta || !sta->rate_ctrl_priv) 1969 if (!sta || !sta->rate_ctrl_priv)
@@ -1997,6 +2014,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
1997 2014
1998 int i; 2015 int i;
1999 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 2016 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
2017 struct ieee80211_conf *conf = &local->hw.conf;
2000 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 2018 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
2001 struct sta_info *sta; 2019 struct sta_info *sta;
2002 struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; 2020 struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
@@ -2030,7 +2048,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
2030 lq->lq.sta_id = sta_id; 2048 lq->lq.sta_id = sta_id;
2031 lq->lq.rs_table[0].rate_n_flags = 0; 2049 lq->lq.rs_table[0].rate_n_flags = 0;
2032 lq->ibss_sta_added = 1; 2050 lq->ibss_sta_added = 1;
2033 rs_initialize_lq(priv, sta); 2051 rs_initialize_lq(priv, conf, sta);
2034 } 2052 }
2035 if (!lq->ibss_sta_added) 2053 if (!lq->ibss_sta_added)
2036 goto done; 2054 goto done;
@@ -2072,6 +2090,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
2072 struct sta_info *sta) 2090 struct sta_info *sta)
2073{ 2091{
2074 int i, j; 2092 int i, j;
2093 struct ieee80211_conf *conf = &local->hw.conf;
2075 struct ieee80211_hw_mode *mode = local->oper_hw_mode; 2094 struct ieee80211_hw_mode *mode = local->oper_hw_mode;
2076 struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; 2095 struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
2077 struct iwl4965_rate_scale_priv *crl = priv_sta; 2096 struct iwl4965_rate_scale_priv *crl = priv_sta;
@@ -2126,7 +2145,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
2126 crl->is_dup = 0; 2145 crl->is_dup = 0;
2127 crl->valid_antenna = priv->valid_antenna; 2146 crl->valid_antenna = priv->valid_antenna;
2128 crl->antenna = priv->antenna; 2147 crl->antenna = priv->antenna;
2129 crl->is_green = rs_use_green(priv); 2148 crl->is_green = rs_use_green(priv, conf);
2130 crl->active_rate = priv->active_rate; 2149 crl->active_rate = priv->active_rate;
2131 crl->active_rate &= ~(0x1000); 2150 crl->active_rate &= ~(0x1000);
2132 crl->active_rate_basic = priv->active_rate_basic; 2151 crl->active_rate_basic = priv->active_rate_basic;
@@ -2136,14 +2155,16 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
2136 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), 2155 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
2137 * supp_rates[] does not; shift to convert format, force 9 MBits off. 2156 * supp_rates[] does not; shift to convert format, force 9 MBits off.
2138 */ 2157 */
2139 crl->active_siso_rate = (priv->current_assoc_ht.supp_rates[0] << 1); 2158 crl->active_siso_rate = (priv->current_ht_config.supp_mcs_set[0] << 1);
2140 crl->active_siso_rate |= (priv->current_assoc_ht.supp_rates[0] & 0x1); 2159 crl->active_siso_rate |=
2160 (priv->current_ht_config.supp_mcs_set[0] & 0x1);
2141 crl->active_siso_rate &= ~((u16)0x2); 2161 crl->active_siso_rate &= ~((u16)0x2);
2142 crl->active_siso_rate = crl->active_siso_rate << IWL_FIRST_OFDM_RATE; 2162 crl->active_siso_rate = crl->active_siso_rate << IWL_FIRST_OFDM_RATE;
2143 2163
2144 /* Same here */ 2164 /* Same here */
2145 crl->active_mimo_rate = (priv->current_assoc_ht.supp_rates[1] << 1); 2165 crl->active_mimo_rate = (priv->current_ht_config.supp_mcs_set[1] << 1);
2146 crl->active_mimo_rate |= (priv->current_assoc_ht.supp_rates[1] & 0x1); 2166 crl->active_mimo_rate |=
2167 (priv->current_ht_config.supp_mcs_set[1] & 0x1);
2147 crl->active_mimo_rate &= ~((u16)0x2); 2168 crl->active_mimo_rate &= ~((u16)0x2);
2148 crl->active_mimo_rate = crl->active_mimo_rate << IWL_FIRST_OFDM_RATE; 2169 crl->active_mimo_rate = crl->active_mimo_rate << IWL_FIRST_OFDM_RATE;
2149 IWL_DEBUG_HT("MIMO RATE 0x%X SISO MASK 0x%X\n", crl->active_siso_rate, 2170 IWL_DEBUG_HT("MIMO RATE 0x%X SISO MASK 0x%X\n", crl->active_siso_rate,
@@ -2156,7 +2177,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
2156 if (priv->assoc_station_added) 2177 if (priv->assoc_station_added)
2157 priv->lq_mngr.lq_ready = 1; 2178 priv->lq_mngr.lq_ready = 1;
2158 2179
2159 rs_initialize_lq(priv, sta); 2180 rs_initialize_lq(priv, conf, sta);
2160} 2181}
2161 2182
2162static void rs_fill_link_cmd(struct iwl4965_rate_scale_priv *lq_data, 2183static void rs_fill_link_cmd(struct iwl4965_rate_scale_priv *lq_data,