aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2009-04-01 17:33:24 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:54:40 -0400
commit584a0f00636d34f71a80f5b550a305f1a1620693 (patch)
treeb53cd82f87feb0932e18c0032244c6186996dfa3 /drivers/net/wireless/iwlwifi
parent11397a656f14466421bac503f0f3aaadf9486120 (diff)
iwlwifi: adding MIMO3 support in rate scaling
Separated the MIMO tpt matrix into MIMO2 and MIMO3, adding MIMO3 support in rate scaling algorithm. If the device support 3x3, then utilize all three antenna (A/B/C) for tx to improve throughput. Adding rs_switch_to_mimo3() function to allow switch to mimo3 modulation mode from other modes(legacy/siso/mimo2). Adding rs_move_mimo3_to_other() function to allow switch from mimo3 modulation mode to either siso or mimo2; also support toggle between SGI and NGI. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c331
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.h18
2 files changed, 325 insertions, 24 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index cab7842a73a..7cdbcfe483f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -191,7 +191,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
191 * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits 191 * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
192 * "G" is the only table that supports CCK (the first 4 rates). 192 * "G" is the only table that supports CCK (the first 4 rates).
193 */ 193 */
194/*FIXME:RS:need to separate tables for MIMO2/MIMO3*/ 194
195static s32 expected_tpt_A[IWL_RATE_COUNT] = { 195static s32 expected_tpt_A[IWL_RATE_COUNT] = {
196 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 196 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186
197}; 197};
@@ -208,11 +208,11 @@ static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = {
208 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211 208 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211
209}; 209};
210 210
211static s32 expected_tpt_mimo20MHz[IWL_RATE_COUNT] = { 211static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = {
212 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251 212 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251
213}; 213};
214 214
215static s32 expected_tpt_mimo20MHzSGI[IWL_RATE_COUNT] = { 215static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = {
216 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257 216 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257
217}; 217};
218 218
@@ -224,14 +224,31 @@ static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = {
224 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 224 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264
225}; 225};
226 226
227static s32 expected_tpt_mimo40MHz[IWL_RATE_COUNT] = { 227static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = {
228 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 228 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289
229}; 229};
230 230
231static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { 231static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = {
232 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 232 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293
233}; 233};
234 234
235/* Expected throughput metric MIMO3 */
236static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = {
237 0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268
238};
239
240static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = {
241 0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273
242};
243
244static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = {
245 0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297
246};
247
248static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = {
249 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300
250};
251
235static inline u8 rs_extract_rate(u32 rate_n_flags) 252static inline u8 rs_extract_rate(u32 rate_n_flags)
236{ 253{
237 return (u8)(rate_n_flags & 0xFF); 254 return (u8)(rate_n_flags & 0xFF);
@@ -1011,17 +1028,26 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
1011 tbl->expected_tpt = expected_tpt_siso20MHzSGI; 1028 tbl->expected_tpt = expected_tpt_siso20MHzSGI;
1012 else 1029 else
1013 tbl->expected_tpt = expected_tpt_siso20MHz; 1030 tbl->expected_tpt = expected_tpt_siso20MHz;
1014 1031 } else if (is_mimo2(tbl->lq_type)) {
1015 } else if (is_mimo(tbl->lq_type)) { /* FIXME:need to separate mimo2/3 */ 1032 if (tbl->is_fat && !lq_sta->is_dup)
1033 if (tbl->is_SGI)
1034 tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI;
1035 else
1036 tbl->expected_tpt = expected_tpt_mimo2_40MHz;
1037 else if (tbl->is_SGI)
1038 tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI;
1039 else
1040 tbl->expected_tpt = expected_tpt_mimo2_20MHz;
1041 } else if (is_mimo3(tbl->lq_type)) {
1016 if (tbl->is_fat && !lq_sta->is_dup) 1042 if (tbl->is_fat && !lq_sta->is_dup)
1017 if (tbl->is_SGI) 1043 if (tbl->is_SGI)
1018 tbl->expected_tpt = expected_tpt_mimo40MHzSGI; 1044 tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI;
1019 else 1045 else
1020 tbl->expected_tpt = expected_tpt_mimo40MHz; 1046 tbl->expected_tpt = expected_tpt_mimo3_40MHz;
1021 else if (tbl->is_SGI) 1047 else if (tbl->is_SGI)
1022 tbl->expected_tpt = expected_tpt_mimo20MHzSGI; 1048 tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI;
1023 else 1049 else
1024 tbl->expected_tpt = expected_tpt_mimo20MHz; 1050 tbl->expected_tpt = expected_tpt_mimo3_20MHz;
1025 } else 1051 } else
1026 tbl->expected_tpt = expected_tpt_G; 1052 tbl->expected_tpt = expected_tpt_G;
1027} 1053}
@@ -1130,7 +1156,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
1130} 1156}
1131 1157
1132/* 1158/*
1133 * Set up search table for MIMO 1159 * Set up search table for MIMO2
1134 */ 1160 */
1135static int rs_switch_to_mimo2(struct iwl_priv *priv, 1161static int rs_switch_to_mimo2(struct iwl_priv *priv,
1136 struct iwl_lq_sta *lq_sta, 1162 struct iwl_lq_sta *lq_sta,
@@ -1183,7 +1209,73 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
1183 rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); 1209 rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
1184 1210
1185 IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask); 1211 IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask);
1212 if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
1213 IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n",
1214 rate, rate_mask);
1215 return -1;
1216 }
1217 tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green);
1218
1219 IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n",
1220 tbl->current_rate, is_green);
1221 return 0;
1222}
1223
1224/*
1225 * Set up search table for MIMO3
1226 */
1227static int rs_switch_to_mimo3(struct iwl_priv *priv,
1228 struct iwl_lq_sta *lq_sta,
1229 struct ieee80211_conf *conf,
1230 struct ieee80211_sta *sta,
1231 struct iwl_scale_tbl_info *tbl, int index)
1232{
1233 u16 rate_mask;
1234 s32 rate;
1235 s8 is_green = lq_sta->is_green;
1236
1237 if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
1238 return -1;
1239
1240 if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
1241 == WLAN_HT_CAP_SM_PS_STATIC)
1242 return -1;
1243
1244 /* Need both Tx chains/antennas to support MIMO */
1245 if (priv->hw_params.tx_chains_num < 3)
1246 return -1;
1247
1248 IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n");
1249
1250 tbl->lq_type = LQ_MIMO3;
1251 tbl->is_dup = lq_sta->is_dup;
1252 tbl->action = 0;
1253 rate_mask = lq_sta->active_mimo3_rate;
1254
1255 if (priv->current_ht_config.supported_chan_width
1256 == IWL_CHANNEL_WIDTH_40MHZ)
1257 tbl->is_fat = 1;
1258 else
1259 tbl->is_fat = 0;
1186 1260
1261 /* FIXME: - don't toggle SGI here
1262 if (tbl->is_fat) {
1263 if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
1264 tbl->is_SGI = 1;
1265 else
1266 tbl->is_SGI = 0;
1267 } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
1268 tbl->is_SGI = 1;
1269 else
1270 tbl->is_SGI = 0;
1271 */
1272
1273 rs_set_expected_tpt_table(lq_sta, tbl);
1274
1275 rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
1276
1277 IWL_DEBUG_RATE(priv, "LQ: MIMO3 best rate %d mask %X\n",
1278 rate, rate_mask);
1187 if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { 1279 if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
1188 IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n", 1280 IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n",
1189 rate, rate_mask); 1281 rate, rate_mask);
@@ -1342,9 +1434,29 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
1342 goto out; 1434 goto out;
1343 } 1435 }
1344 break; 1436 break;
1437
1438 case IWL_LEGACY_SWITCH_MIMO3_ABC:
1439 IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO3\n");
1440
1441 /* Set up search table to try MIMO3 */
1442 memcpy(search_tbl, tbl, sz);
1443 search_tbl->is_SGI = 0;
1444
1445 search_tbl->ant_type = ANT_ABC;
1446
1447 if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
1448 break;
1449
1450 ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta,
1451 search_tbl, index);
1452 if (!ret) {
1453 lq_sta->action_counter = 0;
1454 goto out;
1455 }
1456 break;
1345 } 1457 }
1346 tbl->action++; 1458 tbl->action++;
1347 if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) 1459 if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
1348 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; 1460 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
1349 1461
1350 if (tbl->action == start_action) 1462 if (tbl->action == start_action)
@@ -1357,7 +1469,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
1357out: 1469out:
1358 lq_sta->search_better_tbl = 1; 1470 lq_sta->search_better_tbl = 1;
1359 tbl->action++; 1471 tbl->action++;
1360 if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC) 1472 if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
1361 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; 1473 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
1362 return 0; 1474 return 0;
1363 1475
@@ -1457,9 +1569,23 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
1457 rate_n_flags_from_tbl(priv, search_tbl, 1569 rate_n_flags_from_tbl(priv, search_tbl,
1458 index, is_green); 1570 index, is_green);
1459 goto out; 1571 goto out;
1572 case IWL_SISO_SWITCH_MIMO3_ABC:
1573 IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO3\n");
1574 memcpy(search_tbl, tbl, sz);
1575 search_tbl->is_SGI = 0;
1576 search_tbl->ant_type = ANT_ABC;
1577
1578 if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
1579 break;
1580
1581 ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta,
1582 search_tbl, index);
1583 if (!ret)
1584 goto out;
1585 break;
1460 } 1586 }
1461 tbl->action++; 1587 tbl->action++;
1462 if (tbl->action > IWL_SISO_SWITCH_GI) 1588 if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
1463 tbl->action = IWL_SISO_SWITCH_ANTENNA1; 1589 tbl->action = IWL_SISO_SWITCH_ANTENNA1;
1464 1590
1465 if (tbl->action == start_action) 1591 if (tbl->action == start_action)
@@ -1471,15 +1597,15 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
1471 out: 1597 out:
1472 lq_sta->search_better_tbl = 1; 1598 lq_sta->search_better_tbl = 1;
1473 tbl->action++; 1599 tbl->action++;
1474 if (tbl->action > IWL_SISO_SWITCH_GI) 1600 if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC)
1475 tbl->action = IWL_SISO_SWITCH_ANTENNA1; 1601 tbl->action = IWL_SISO_SWITCH_ANTENNA1;
1476 return 0; 1602 return 0;
1477} 1603}
1478 1604
1479/* 1605/*
1480 * Try to switch to new modulation mode from MIMO 1606 * Try to switch to new modulation mode from MIMO2
1481 */ 1607 */
1482static int rs_move_mimo_to_other(struct iwl_priv *priv, 1608static int rs_move_mimo2_to_other(struct iwl_priv *priv,
1483 struct iwl_lq_sta *lq_sta, 1609 struct iwl_lq_sta *lq_sta,
1484 struct ieee80211_conf *conf, 1610 struct ieee80211_conf *conf,
1485 struct ieee80211_sta *sta, int index) 1611 struct ieee80211_sta *sta, int index)
@@ -1501,7 +1627,7 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
1501 switch (tbl->action) { 1627 switch (tbl->action) {
1502 case IWL_MIMO2_SWITCH_ANTENNA1: 1628 case IWL_MIMO2_SWITCH_ANTENNA1:
1503 case IWL_MIMO2_SWITCH_ANTENNA2: 1629 case IWL_MIMO2_SWITCH_ANTENNA2:
1504 IWL_DEBUG_RATE(priv, "LQ: MIMO toggle Antennas\n"); 1630 IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle Antennas\n");
1505 1631
1506 if (tx_chains_num <= 2) 1632 if (tx_chains_num <= 2)
1507 break; 1633 break;
@@ -1549,9 +1675,9 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
1549 HT_SHORT_GI_40MHZ)) 1675 HT_SHORT_GI_40MHZ))
1550 break; 1676 break;
1551 1677
1552 IWL_DEBUG_RATE(priv, "LQ: MIMO toggle SGI/NGI\n"); 1678 IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n");
1553 1679
1554 /* Set up new search table for MIMO */ 1680 /* Set up new search table for MIMO2 */
1555 memcpy(search_tbl, tbl, sz); 1681 memcpy(search_tbl, tbl, sz);
1556 search_tbl->is_SGI = !tbl->is_SGI; 1682 search_tbl->is_SGI = !tbl->is_SGI;
1557 rs_set_expected_tpt_table(lq_sta, search_tbl); 1683 rs_set_expected_tpt_table(lq_sta, search_tbl);
@@ -1571,9 +1697,24 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
1571 index, is_green); 1697 index, is_green);
1572 goto out; 1698 goto out;
1573 1699
1700 case IWL_MIMO2_SWITCH_MIMO3_ABC:
1701 IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to MIMO3\n");
1702 memcpy(search_tbl, tbl, sz);
1703 search_tbl->is_SGI = 0;
1704 search_tbl->ant_type = ANT_ABC;
1705
1706 if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
1707 break;
1708
1709 ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta,
1710 search_tbl, index);
1711 if (!ret)
1712 goto out;
1713
1714 break;
1574 } 1715 }
1575 tbl->action++; 1716 tbl->action++;
1576 if (tbl->action > IWL_MIMO2_SWITCH_GI) 1717 if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC)
1577 tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; 1718 tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
1578 1719
1579 if (tbl->action == start_action) 1720 if (tbl->action == start_action)
@@ -1584,13 +1725,150 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
1584 out: 1725 out:
1585 lq_sta->search_better_tbl = 1; 1726 lq_sta->search_better_tbl = 1;
1586 tbl->action++; 1727 tbl->action++;
1587 if (tbl->action > IWL_MIMO2_SWITCH_GI) 1728 if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC)
1588 tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; 1729 tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
1589 return 0; 1730 return 0;
1590 1731
1591} 1732}
1592 1733
1593/* 1734/*
1735 * Try to switch to new modulation mode from MIMO3
1736 */
1737static int rs_move_mimo3_to_other(struct iwl_priv *priv,
1738 struct iwl_lq_sta *lq_sta,
1739 struct ieee80211_conf *conf,
1740 struct ieee80211_sta *sta, int index)
1741{
1742 s8 is_green = lq_sta->is_green;
1743 struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
1744 struct iwl_scale_tbl_info *search_tbl =
1745 &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
1746 struct iwl_rate_scale_data *window = &(tbl->win[index]);
1747 u32 sz = (sizeof(struct iwl_scale_tbl_info) -
1748 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
1749 u8 start_action = tbl->action;
1750 u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
1751 u8 tx_chains_num = priv->hw_params.tx_chains_num;
1752 int ret;
1753
1754 for (;;) {
1755 lq_sta->action_counter++;
1756 switch (tbl->action) {
1757 case IWL_MIMO3_SWITCH_ANTENNA1:
1758 case IWL_MIMO3_SWITCH_ANTENNA2:
1759 IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle Antennas\n");
1760
1761 if (tx_chains_num <= 3)
1762 break;
1763
1764 if (window->success_ratio >= IWL_RS_GOOD_RATIO)
1765 break;
1766
1767 memcpy(search_tbl, tbl, sz);
1768 if (rs_toggle_antenna(valid_tx_ant,
1769 &search_tbl->current_rate, search_tbl))
1770 goto out;
1771 break;
1772 case IWL_MIMO3_SWITCH_SISO_A:
1773 case IWL_MIMO3_SWITCH_SISO_B:
1774 case IWL_MIMO3_SWITCH_SISO_C:
1775 IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to SISO\n");
1776
1777 /* Set up new search table for SISO */
1778 memcpy(search_tbl, tbl, sz);
1779
1780 if (tbl->action == IWL_MIMO3_SWITCH_SISO_A)
1781 search_tbl->ant_type = ANT_A;
1782 else if (tbl->action == IWL_MIMO3_SWITCH_SISO_B)
1783 search_tbl->ant_type = ANT_B;
1784 else
1785 search_tbl->ant_type = ANT_C;
1786
1787 if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
1788 break;
1789
1790 ret = rs_switch_to_siso(priv, lq_sta, conf, sta,
1791 search_tbl, index);
1792 if (!ret)
1793 goto out;
1794
1795 break;
1796
1797 case IWL_MIMO3_SWITCH_MIMO2_AB:
1798 case IWL_MIMO3_SWITCH_MIMO2_AC:
1799 case IWL_MIMO3_SWITCH_MIMO2_BC:
1800 IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to MIMO2\n");
1801
1802 memcpy(search_tbl, tbl, sz);
1803 search_tbl->is_SGI = 0;
1804 if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB)
1805 search_tbl->ant_type = ANT_AB;
1806 else if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC)
1807 search_tbl->ant_type = ANT_AC;
1808 else
1809 search_tbl->ant_type = ANT_BC;
1810
1811 if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
1812 break;
1813
1814 ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta,
1815 search_tbl, index);
1816 if (!ret)
1817 goto out;
1818
1819 break;
1820
1821 case IWL_MIMO3_SWITCH_GI:
1822 if (!tbl->is_fat &&
1823 !(priv->current_ht_config.sgf &
1824 HT_SHORT_GI_20MHZ))
1825 break;
1826 if (tbl->is_fat &&
1827 !(priv->current_ht_config.sgf &
1828 HT_SHORT_GI_40MHZ))
1829 break;
1830
1831 IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n");
1832
1833 /* Set up new search table for MIMO */
1834 memcpy(search_tbl, tbl, sz);
1835 search_tbl->is_SGI = !tbl->is_SGI;
1836 rs_set_expected_tpt_table(lq_sta, search_tbl);
1837 /*
1838 * If active table already uses the fastest possible
1839 * modulation (dual stream with short guard interval),
1840 * and it's working well, there's no need to look
1841 * for a better type of modulation!
1842 */
1843 if (tbl->is_SGI) {
1844 s32 tpt = lq_sta->last_tpt / 100;
1845 if (tpt >= search_tbl->expected_tpt[index])
1846 break;
1847 }
1848 search_tbl->current_rate =
1849 rate_n_flags_from_tbl(priv, search_tbl,
1850 index, is_green);
1851 goto out;
1852 }
1853 tbl->action++;
1854 if (tbl->action > IWL_MIMO3_SWITCH_GI)
1855 tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
1856
1857 if (tbl->action == start_action)
1858 break;
1859 }
1860 search_tbl->lq_type = LQ_NONE;
1861 return 0;
1862 out:
1863 lq_sta->search_better_tbl = 1;
1864 tbl->action++;
1865 if (tbl->action > IWL_MIMO3_SWITCH_GI)
1866 tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
1867 return 0;
1868
1869}
1870
1871/*
1594 * Check whether we should continue using same modulation mode, or 1872 * Check whether we should continue using same modulation mode, or
1595 * begin search for a new mode, based on: 1873 * begin search for a new mode, based on:
1596 * 1) # tx successes or failures while using this mode 1874 * 1) # tx successes or failures while using this mode
@@ -1997,8 +2275,10 @@ lq_update:
1997 rs_move_legacy_other(priv, lq_sta, conf, sta, index); 2275 rs_move_legacy_other(priv, lq_sta, conf, sta, index);
1998 else if (is_siso(tbl->lq_type)) 2276 else if (is_siso(tbl->lq_type))
1999 rs_move_siso_to_other(priv, lq_sta, conf, sta, index); 2277 rs_move_siso_to_other(priv, lq_sta, conf, sta, index);
2278 else if (is_mimo2(tbl->lq_type))
2279 rs_move_mimo2_to_other(priv, lq_sta, conf, sta, index);
2000 else 2280 else
2001 rs_move_mimo_to_other(priv, lq_sta, conf, sta, index); 2281 rs_move_mimo3_to_other(priv, lq_sta, conf, sta, index);
2002 2282
2003 /* If new "search" mode was selected, set up in uCode table */ 2283 /* If new "search" mode was selected, set up in uCode table */
2004 if (lq_sta->search_better_tbl) { 2284 if (lq_sta->search_better_tbl) {
@@ -2362,6 +2642,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
2362 } else if (num_of_ant(tbl_type.ant_type) == 2) { 2642 } else if (num_of_ant(tbl_type.ant_type) == 2) {
2363 lq_cmd->general_params.dual_stream_ant_msk = 2643 lq_cmd->general_params.dual_stream_ant_msk =
2364 tbl_type.ant_type; 2644 tbl_type.ant_type;
2645 } else if (num_of_ant(tbl_type.ant_type) == 3) {
2646 lq_cmd->general_params.dual_stream_ant_msk =
2647 tbl_type.ant_type;
2365 } /* otherwise we don't modify the existing value */ 2648 } /* otherwise we don't modify the existing value */
2366 2649
2367 index++; 2650 index++;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index ab59acc405d..9cd90ba5ef9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -241,6 +241,7 @@ enum {
241#define IWL_LEGACY_SWITCH_MIMO2_AB 3 241#define IWL_LEGACY_SWITCH_MIMO2_AB 3
242#define IWL_LEGACY_SWITCH_MIMO2_AC 4 242#define IWL_LEGACY_SWITCH_MIMO2_AC 4
243#define IWL_LEGACY_SWITCH_MIMO2_BC 5 243#define IWL_LEGACY_SWITCH_MIMO2_BC 5
244#define IWL_LEGACY_SWITCH_MIMO3_ABC 6
244 245
245/* possible actions when in siso mode */ 246/* possible actions when in siso mode */
246#define IWL_SISO_SWITCH_ANTENNA1 0 247#define IWL_SISO_SWITCH_ANTENNA1 0
@@ -249,6 +250,8 @@ enum {
249#define IWL_SISO_SWITCH_MIMO2_AC 3 250#define IWL_SISO_SWITCH_MIMO2_AC 3
250#define IWL_SISO_SWITCH_MIMO2_BC 4 251#define IWL_SISO_SWITCH_MIMO2_BC 4
251#define IWL_SISO_SWITCH_GI 5 252#define IWL_SISO_SWITCH_GI 5
253#define IWL_SISO_SWITCH_MIMO3_ABC 6
254
252 255
253/* possible actions when in mimo mode */ 256/* possible actions when in mimo mode */
254#define IWL_MIMO2_SWITCH_ANTENNA1 0 257#define IWL_MIMO2_SWITCH_ANTENNA1 0
@@ -257,6 +260,21 @@ enum {
257#define IWL_MIMO2_SWITCH_SISO_B 3 260#define IWL_MIMO2_SWITCH_SISO_B 3
258#define IWL_MIMO2_SWITCH_SISO_C 4 261#define IWL_MIMO2_SWITCH_SISO_C 4
259#define IWL_MIMO2_SWITCH_GI 5 262#define IWL_MIMO2_SWITCH_GI 5
263#define IWL_MIMO2_SWITCH_MIMO3_ABC 6
264
265
266/* possible actions when in mimo3 mode */
267#define IWL_MIMO3_SWITCH_ANTENNA1 0
268#define IWL_MIMO3_SWITCH_ANTENNA2 1
269#define IWL_MIMO3_SWITCH_SISO_A 2
270#define IWL_MIMO3_SWITCH_SISO_B 3
271#define IWL_MIMO3_SWITCH_SISO_C 4
272#define IWL_MIMO3_SWITCH_MIMO2_AB 5
273#define IWL_MIMO3_SWITCH_MIMO2_AC 6
274#define IWL_MIMO3_SWITCH_MIMO2_BC 7
275#define IWL_MIMO3_SWITCH_GI 8
276
277
260 278
261/*FIXME:RS:add possible actions for MIMO3*/ 279/*FIXME:RS:add possible actions for MIMO3*/
262 280