aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorGuy Cohen <guy.cohen@intel.com>2008-04-23 20:14:59 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-07 15:02:19 -0400
commitaade00cee60d8a2b1682b6804664049d7a369ac2 (patch)
tree0e51ec82699cf7bd792c73ce68858d2c496d1e3f /drivers/net/wireless
parenteecd6e5705fdea75c354559339a2b1f22ec400a0 (diff)
iwlwifi: rate scale restructure toggle_antenna functions
This patch add support for toggeling of A/B/C and AB/BC/AC antennas Signed-off-by: Guy Cohen <guy.cohen@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-rs.c172
1 files changed, 91 insertions, 81 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index 4063534b64c8..1ad62568558b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -43,7 +43,7 @@
43 43
44#define RS_NAME "iwl-4965-rs" 44#define RS_NAME "iwl-4965-rs"
45 45
46#define NUM_TRY_BEFORE_ANTENNA_TOGGLE 1 46#define NUM_TRY_BEFORE_ANT_TOGGLE 1
47#define IWL_NUMBER_TRY 1 47#define IWL_NUMBER_TRY 1
48#define IWL_HT_NUMBER_TRY 3 48#define IWL_HT_NUMBER_TRY 3
49 49
@@ -64,6 +64,17 @@ static u8 rs_ht_to_legacy[] = {
64 IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX 64 IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX
65}; 65};
66 66
67static const u8 ant_toggle_lookup[] = {
68 /*ANT_NONE -> */ ANT_NONE,
69 /*ANT_A -> */ ANT_B,
70 /*ANT_B -> */ ANT_C,
71 /*ANT_AB -> */ ANT_BC,
72 /*ANT_C -> */ ANT_A,
73 /*ANT_AC -> */ ANT_AB,
74 /*ANT_BC -> */ ANT_AC,
75 /*ANT_ABC -> */ ANT_ABC,
76};
77
67/** 78/**
68 * struct iwl4965_rate_scale_data -- tx success history for one rate 79 * struct iwl4965_rate_scale_data -- tx success history for one rate
69 */ 80 */
@@ -131,8 +142,6 @@ struct iwl4965_lq_sta {
131 u32 flush_timer; /* time staying in mode before new search */ 142 u32 flush_timer; /* time staying in mode before new search */
132 143
133 u8 action_counter; /* # mode-switch actions tried */ 144 u8 action_counter; /* # mode-switch actions tried */
134 u8 antenna;
135 u8 valid_antenna;
136 u8 is_green; 145 u8 is_green;
137 u8 is_dup; 146 u8 is_dup;
138 enum ieee80211_band band; 147 enum ieee80211_band band;
@@ -243,6 +252,11 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
243 window->stamp = 0; 252 window->stamp = 0;
244} 253}
245 254
255static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
256{
257 return ((ant_type & valid_antenna) == ant_type);
258}
259
246#ifdef CONFIG_IWL4965_HT 260#ifdef CONFIG_IWL4965_HT
247/* 261/*
248 * removes the old data from the statistics. All data that is older than 262 * removes the old data from the statistics. All data that is older than
@@ -576,12 +590,33 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
576 } 590 }
577 return 0; 591 return 0;
578} 592}
579/* FIXME:RS: need to toggle also ANT_C, and also AB,AC,BC */ 593
580static inline void rs_toggle_antenna(u32 *rate_n_flags, 594/* switch to another antenna/antennas and return 1 */
581 struct iwl4965_scale_tbl_info *tbl) 595/* if no other valid antenna found, return 0 */
596static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
597 struct iwl4965_scale_tbl_info *tbl)
582{ 598{
583 tbl->ant_type ^= ANT_AB; 599 u8 new_ant_type;
584 *rate_n_flags ^= (RATE_MCS_ANT_A_MSK|RATE_MCS_ANT_B_MSK); 600
601 if (!tbl->ant_type || tbl->ant_type > ANT_ABC)
602 return 0;
603
604 if (!rs_is_valid_ant(valid_ant, tbl->ant_type))
605 return 0;
606
607 new_ant_type = ant_toggle_lookup[tbl->ant_type];
608
609 while ((new_ant_type != tbl->ant_type) &&
610 !rs_is_valid_ant(valid_ant, new_ant_type))
611 new_ant_type = ant_toggle_lookup[new_ant_type];
612
613 if (new_ant_type == tbl->ant_type)
614 return 0;
615
616 tbl->ant_type = new_ant_type;
617 *rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK;
618 *rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS;
619 return 1;
585} 620}
586 621
587/* FIXME:RS: in 4965 we don't use greenfield at all */ 622/* FIXME:RS: in 4965 we don't use greenfield at all */
@@ -796,8 +831,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
796 table = &lq_sta->lq; 831 table = &lq_sta->lq;
797 active_index = lq_sta->active_tbl; 832 active_index = lq_sta->active_tbl;
798 833
799 lq_sta->antenna = lq_sta->valid_antenna;
800
801 curr_tbl = &(lq_sta->lq_info[active_index]); 834 curr_tbl = &(lq_sta->lq_info[active_index]);
802 search_tbl = &(lq_sta->lq_info[(1 - active_index)]); 835 search_tbl = &(lq_sta->lq_info[(1 - active_index)]);
803 window = (struct iwl4965_rate_scale_data *) 836 window = (struct iwl4965_rate_scale_data *)
@@ -946,22 +979,6 @@ out:
946 return; 979 return;
947} 980}
948 981
949static inline u8 rs_is_ant_connected(u8 valid_antenna, u8 ant_type)
950{
951 return ((ant_type & valid_antenna) == ant_type);
952}
953
954/*FIXME:RS: this function should be replaced*/
955static u8 rs_is_other_ant_connected(u8 valid_antenna, u8 ant_type)
956{
957 if (ant_type == ANT_B)
958 return rs_is_ant_connected(valid_antenna, ANT_A);
959 else
960 return rs_is_ant_connected(valid_antenna, ANT_B);
961
962 return 0;
963}
964
965/* 982/*
966 * Begin a period of staying with a selected modulation mode. 983 * Begin a period of staying with a selected modulation mode.
967 * Set "stay_in_tbl" flag to prevent any mode switches. 984 * Set "stay_in_tbl" flag to prevent any mode switches.
@@ -1128,12 +1145,6 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
1128} 1145}
1129#endif /* CONFIG_IWL4965_HT */ 1146#endif /* CONFIG_IWL4965_HT */
1130 1147
1131/*FIXME:RS:this function should be replaced*/
1132static inline u8 rs_is_both_ant_supp(u8 valid_antenna)
1133{
1134 return (rs_is_ant_connected(valid_antenna, ANT_AB));
1135}
1136
1137/* 1148/*
1138 * Set up search table for MIMO 1149 * Set up search table for MIMO
1139 */ 1150 */
@@ -1156,7 +1167,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
1156 return -1; 1167 return -1;
1157 1168
1158 /* Need both Tx chains/antennas to support MIMO */ 1169 /* Need both Tx chains/antennas to support MIMO */
1159 if (!rs_is_both_ant_supp(priv->hw_params.valid_tx_ant)) 1170 if (priv->hw_params.tx_chains_num < 2)
1160 return -1; 1171 return -1;
1161 1172
1162 IWL_DEBUG_RATE("LQ: try to switch to MIMO2\n"); 1173 IWL_DEBUG_RATE("LQ: try to switch to MIMO2\n");
@@ -1302,7 +1313,6 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
1302 case IWL_LEGACY_SWITCH_ANTENNA: 1313 case IWL_LEGACY_SWITCH_ANTENNA:
1303 IWL_DEBUG_RATE("LQ Legacy toggle Antenna\n"); 1314 IWL_DEBUG_RATE("LQ Legacy toggle Antenna\n");
1304 1315
1305 search_tbl->lq_type = LQ_NONE;
1306 lq_sta->action_counter++; 1316 lq_sta->action_counter++;
1307 1317
1308 /* Don't change antenna if success has been great */ 1318 /* Don't change antenna if success has been great */
@@ -1310,19 +1320,15 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
1310 if (window->success_ratio >= IWL_RS_GOOD_RATIO) 1320 if (window->success_ratio >= IWL_RS_GOOD_RATIO)
1311 break; 1321 break;
1312 1322
1313 /* Don't change antenna if other one is not connected */
1314 if (!rs_is_other_ant_connected(valid_tx_ant,
1315 tbl->ant_type))
1316 break;
1317
1318 /* Set up search table to try other antenna */ 1323 /* Set up search table to try other antenna */
1319 memcpy(search_tbl, tbl, sz); 1324 memcpy(search_tbl, tbl, sz);
1320 1325
1321 rs_toggle_antenna(&search_tbl->current_rate, 1326 if (rs_toggle_antenna(valid_tx_ant,
1322 search_tbl); 1327 &search_tbl->current_rate, search_tbl)) {
1323 rs_set_expected_tpt_table(lq_sta, search_tbl); 1328 rs_set_expected_tpt_table(lq_sta, search_tbl);
1324 lq_sta->search_better_tbl = 1; 1329 lq_sta->search_better_tbl = 1;
1325 goto out; 1330 goto out;
1331 }
1326 1332
1327 case IWL_LEGACY_SWITCH_SISO: 1333 case IWL_LEGACY_SWITCH_SISO:
1328 IWL_DEBUG_RATE("LQ: Legacy switch to SISO\n"); 1334 IWL_DEBUG_RATE("LQ: Legacy switch to SISO\n");
@@ -1403,16 +1409,13 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
1403 /*FIXME:RS: is this really needed for SISO?*/ 1409 /*FIXME:RS: is this really needed for SISO?*/
1404 if (window->success_ratio >= IWL_RS_GOOD_RATIO) 1410 if (window->success_ratio >= IWL_RS_GOOD_RATIO)
1405 break; 1411 break;
1406 if (!rs_is_other_ant_connected(valid_tx_ant,
1407 tbl->ant_type))
1408 break;
1409 1412
1410 memcpy(search_tbl, tbl, sz); 1413 memcpy(search_tbl, tbl, sz);
1411 rs_toggle_antenna(&search_tbl->current_rate, 1414 if (rs_toggle_antenna(valid_tx_ant,
1412 search_tbl); 1415 &search_tbl->current_rate, search_tbl)) {
1413 lq_sta->search_better_tbl = 1; 1416 lq_sta->search_better_tbl = 1;
1414 1417 goto out;
1415 goto out; 1418 }
1416 1419
1417 case IWL_SISO_SWITCH_MIMO2: 1420 case IWL_SISO_SWITCH_MIMO2:
1418 IWL_DEBUG_RATE("LQ: SISO switch to MIMO\n"); 1421 IWL_DEBUG_RATE("LQ: SISO switch to MIMO\n");
@@ -1473,7 +1476,6 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
1473 struct sta_info *sta, 1476 struct sta_info *sta,
1474 int index) 1477 int index)
1475{ 1478{
1476 int ret;
1477 s8 is_green = lq_sta->is_green; 1479 s8 is_green = lq_sta->is_green;
1478 struct iwl4965_scale_tbl_info *tbl = 1480 struct iwl4965_scale_tbl_info *tbl =
1479 &(lq_sta->lq_info[lq_sta->active_tbl]); 1481 &(lq_sta->lq_info[lq_sta->active_tbl]);
@@ -1482,6 +1484,8 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
1482 u32 sz = (sizeof(struct iwl4965_scale_tbl_info) - 1484 u32 sz = (sizeof(struct iwl4965_scale_tbl_info) -
1483 (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT)); 1485 (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT));
1484 u8 start_action = tbl->action; 1486 u8 start_action = tbl->action;
1487 /*u8 valid_tx_ant = priv->hw_params.valid_tx_ant;*/
1488 int ret;
1485 1489
1486 for (;;) { 1490 for (;;) {
1487 lq_sta->action_counter++; 1491 lq_sta->action_counter++;
@@ -2057,13 +2061,14 @@ static void rs_initialize_lq(struct iwl_priv *priv,
2057 struct ieee80211_conf *conf, 2061 struct ieee80211_conf *conf,
2058 struct sta_info *sta) 2062 struct sta_info *sta)
2059{ 2063{
2060 int i;
2061 struct iwl4965_lq_sta *lq_sta; 2064 struct iwl4965_lq_sta *lq_sta;
2062 struct iwl4965_scale_tbl_info *tbl; 2065 struct iwl4965_scale_tbl_info *tbl;
2063 u8 active_tbl = 0;
2064 int rate_idx; 2066 int rate_idx;
2065 u8 use_green = rs_use_green(priv, conf); 2067 int i;
2066 u32 rate; 2068 u32 rate;
2069 u8 use_green = rs_use_green(priv, conf);
2070 u8 active_tbl = 0;
2071 u8 valid_tx_ant;
2067 2072
2068 if (!sta || !sta->rate_ctrl_priv) 2073 if (!sta || !sta->rate_ctrl_priv)
2069 goto out; 2074 goto out;
@@ -2075,6 +2080,8 @@ static void rs_initialize_lq(struct iwl_priv *priv,
2075 (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) 2080 (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
2076 goto out; 2081 goto out;
2077 2082
2083 valid_tx_ant = priv->hw_params.valid_tx_ant;
2084
2078 if (!lq_sta->search_better_tbl) 2085 if (!lq_sta->search_better_tbl)
2079 active_tbl = lq_sta->active_tbl; 2086 active_tbl = lq_sta->active_tbl;
2080 else 2087 else
@@ -2095,8 +2102,8 @@ static void rs_initialize_lq(struct iwl_priv *priv,
2095 2102
2096 tbl->ant_type = ANT_B; 2103 tbl->ant_type = ANT_B;
2097 rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx); 2104 rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx);
2098 if (!rs_is_ant_connected(priv->hw_params.valid_tx_ant, tbl->ant_type)) 2105 if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
2099 rs_toggle_antenna(&rate, tbl); 2106 rs_toggle_antenna(valid_tx_ant, &rate, tbl);
2100 2107
2101 rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green); 2108 rate = rate_n_flags_from_tbl(tbl, rate_idx, use_green);
2102 tbl->current_rate = rate; 2109 tbl->current_rate = rate;
@@ -2307,26 +2314,29 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
2307 u32 new_rate, 2314 u32 new_rate,
2308 struct iwl_link_quality_cmd *lq_cmd) 2315 struct iwl_link_quality_cmd *lq_cmd)
2309{ 2316{
2317 struct iwl4965_scale_tbl_info tbl_type;
2310 int index = 0; 2318 int index = 0;
2311 int rate_idx; 2319 int rate_idx;
2312 int repeat_rate = 0; 2320 int repeat_rate = 0;
2313 u8 ant_toggle_count = 0; 2321 u8 ant_toggle_cnt = 0;
2314 u8 use_ht_possible = 1; 2322 u8 use_ht_possible = 1;
2315 struct iwl4965_scale_tbl_info tbl_type = { 0 }; 2323 u8 valid_tx_ant = 0;
2316 2324
2317 /* Override starting rate (index 0) if needed for debug purposes */ 2325 /* Override starting rate (index 0) if needed for debug purposes */
2318 rs_dbgfs_set_mcs(lq_sta, &new_rate, index); 2326 rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
2319 2327
2320 /* Interpret new_rate (rate_n_flags) */ 2328 /* Interpret new_rate (rate_n_flags) */
2329 memset(&tbl_type, 0, sizeof(tbl_type));
2321 rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, 2330 rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
2322 &tbl_type, &rate_idx); 2331 &tbl_type, &rate_idx);
2323 2332
2324 /* How many times should we repeat the initial rate? */ 2333 /* How many times should we repeat the initial rate? */
2325 if (is_legacy(tbl_type.lq_type)) { 2334 if (is_legacy(tbl_type.lq_type)) {
2326 ant_toggle_count = 1; 2335 ant_toggle_cnt = 1;
2327 repeat_rate = IWL_NUMBER_TRY; 2336 repeat_rate = IWL_NUMBER_TRY;
2328 } else 2337 } else {
2329 repeat_rate = IWL_HT_NUMBER_TRY; 2338 repeat_rate = IWL_HT_NUMBER_TRY;
2339 }
2330 2340
2331 lq_cmd->general_params.mimo_delimiter = 2341 lq_cmd->general_params.mimo_delimiter =
2332 is_mimo(tbl_type.lq_type) ? 1 : 0; 2342 is_mimo(tbl_type.lq_type) ? 1 : 0;
@@ -2345,6 +2355,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
2345 index++; 2355 index++;
2346 repeat_rate--; 2356 repeat_rate--;
2347 2357
2358 if (priv)
2359 valid_tx_ant = priv->hw_params.valid_tx_ant;
2360
2348 /* Fill rest of rate table */ 2361 /* Fill rest of rate table */
2349 while (index < LINK_QUAL_MAX_RETRY_NUM) { 2362 while (index < LINK_QUAL_MAX_RETRY_NUM) {
2350 /* Repeat initial/next rate. 2363 /* Repeat initial/next rate.
@@ -2352,16 +2365,13 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
2352 * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ 2365 * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
2353 while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { 2366 while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
2354 if (is_legacy(tbl_type.lq_type)) { 2367 if (is_legacy(tbl_type.lq_type)) {
2355 if (ant_toggle_count < 2368 if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
2356 NUM_TRY_BEFORE_ANTENNA_TOGGLE) 2369 ant_toggle_cnt++;
2357 ant_toggle_count++; 2370 else if (priv &&
2358 else if (priv && rs_is_other_ant_connected( 2371 rs_toggle_antenna(valid_tx_ant,
2359 priv->hw_params.valid_tx_ant, 2372 &new_rate, &tbl_type))
2360 tbl_type.ant_type)) { 2373 ant_toggle_cnt = 1;
2361 rs_toggle_antenna(&new_rate, &tbl_type); 2374}
2362 ant_toggle_count = 1;
2363 }
2364 }
2365 2375
2366 /* Override next rate if needed for debug purposes */ 2376 /* Override next rate if needed for debug purposes */
2367 rs_dbgfs_set_mcs(lq_sta, &new_rate, index); 2377 rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
@@ -2388,17 +2398,17 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
2388 2398
2389 /* How many times should we repeat the next rate? */ 2399 /* How many times should we repeat the next rate? */
2390 if (is_legacy(tbl_type.lq_type)) { 2400 if (is_legacy(tbl_type.lq_type)) {
2391 if (ant_toggle_count < NUM_TRY_BEFORE_ANTENNA_TOGGLE) 2401 if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
2392 ant_toggle_count++; 2402 ant_toggle_cnt++;
2393 else if (priv && rs_is_other_ant_connected( 2403 else if (priv &&
2394 priv->hw_params.valid_tx_ant, 2404 rs_toggle_antenna(valid_tx_ant,
2395 tbl_type.ant_type)) { 2405 &new_rate, &tbl_type))
2396 rs_toggle_antenna(&new_rate, &tbl_type); 2406 ant_toggle_cnt = 1;
2397 ant_toggle_count = 1; 2407
2398 }
2399 repeat_rate = IWL_NUMBER_TRY; 2408 repeat_rate = IWL_NUMBER_TRY;
2400 } else 2409 } else {
2401 repeat_rate = IWL_HT_NUMBER_TRY; 2410 repeat_rate = IWL_HT_NUMBER_TRY;
2411 }
2402 2412
2403 /* Don't allow HT rates after next pass. 2413 /* Don't allow HT rates after next pass.
2404 * rs_get_lower_rate() will change type to LQ_A or LQ_G. */ 2414 * rs_get_lower_rate() will change type to LQ_A or LQ_G. */