diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 331 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 18 |
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 cab7842a73aa..7cdbcfe483f3 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 | |
195 | static s32 expected_tpt_A[IWL_RATE_COUNT] = { | 195 | static 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 | ||
211 | static s32 expected_tpt_mimo20MHz[IWL_RATE_COUNT] = { | 211 | static 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 | ||
215 | static s32 expected_tpt_mimo20MHzSGI[IWL_RATE_COUNT] = { | 215 | static 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 | ||
227 | static s32 expected_tpt_mimo40MHz[IWL_RATE_COUNT] = { | 227 | static 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 | ||
231 | static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { | 231 | static 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 */ | ||
236 | static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = { | ||
237 | 0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268 | ||
238 | }; | ||
239 | |||
240 | static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = { | ||
241 | 0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273 | ||
242 | }; | ||
243 | |||
244 | static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = { | ||
245 | 0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297 | ||
246 | }; | ||
247 | |||
248 | static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = { | ||
249 | 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300 | ||
250 | }; | ||
251 | |||
235 | static inline u8 rs_extract_rate(u32 rate_n_flags) | 252 | static 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 | */ |
1135 | static int rs_switch_to_mimo2(struct iwl_priv *priv, | 1161 | static 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 | */ | ||
1227 | static 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, | |||
1357 | out: | 1469 | out: |
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 | */ |
1482 | static int rs_move_mimo_to_other(struct iwl_priv *priv, | 1608 | static 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 | */ | ||
1737 | static 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 ab59acc405d9..9cd90ba5ef95 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 | ||