diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/recv.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 215 |
1 files changed, 167 insertions, 48 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index c5b7cbe59bf..4f52e0429f9 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -28,6 +28,33 @@ static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, | |||
28 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | 28 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); |
29 | } | 29 | } |
30 | 30 | ||
31 | static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, | ||
32 | int curr_main_set, int curr_alt_set, | ||
33 | int alt_rssi_avg, int main_rssi_avg) | ||
34 | { | ||
35 | bool result = false; | ||
36 | switch (div_group) { | ||
37 | case 0: | ||
38 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
39 | result = true; | ||
40 | break; | ||
41 | case 1: | ||
42 | if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && | ||
43 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && | ||
44 | (alt_rssi_avg >= (main_rssi_avg - 5))) || | ||
45 | ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && | ||
46 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && | ||
47 | (alt_rssi_avg >= (main_rssi_avg - 2)))) && | ||
48 | (alt_rssi_avg >= 4)) | ||
49 | result = true; | ||
50 | else | ||
51 | result = false; | ||
52 | break; | ||
53 | } | ||
54 | |||
55 | return result; | ||
56 | } | ||
57 | |||
31 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 58 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) |
32 | { | 59 | { |
33 | return sc->ps_enabled && | 60 | return sc->ps_enabled && |
@@ -572,6 +599,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
572 | ath_dbg(common, ATH_DBG_PS, | 599 | ath_dbg(common, ATH_DBG_PS, |
573 | "Reconfigure Beacon timers based on timestamp from the AP\n"); | 600 | "Reconfigure Beacon timers based on timestamp from the AP\n"); |
574 | ath_set_beacon(sc); | 601 | ath_set_beacon(sc); |
602 | sc->ps_flags &= ~PS_TSFOOR_SYNC; | ||
575 | } | 603 | } |
576 | 604 | ||
577 | if (ath_beacon_dtim_pending_cab(skb)) { | 605 | if (ath_beacon_dtim_pending_cab(skb)) { |
@@ -916,7 +944,8 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
916 | int last_rssi; | 944 | int last_rssi; |
917 | __le16 fc; | 945 | __le16 fc; |
918 | 946 | ||
919 | if (ah->opmode != NL80211_IFTYPE_STATION) | 947 | if ((ah->opmode != NL80211_IFTYPE_STATION) && |
948 | (ah->opmode != NL80211_IFTYPE_ADHOC)) | ||
920 | return; | 949 | return; |
921 | 950 | ||
922 | fc = hdr->frame_control; | 951 | fc = hdr->frame_control; |
@@ -1288,49 +1317,138 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
1288 | } | 1317 | } |
1289 | } | 1318 | } |
1290 | 1319 | ||
1291 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf) | 1320 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, |
1321 | struct ath_ant_comb *antcomb, int alt_ratio) | ||
1292 | { | 1322 | { |
1293 | /* Adjust the fast_div_bias based on main and alt lna conf */ | 1323 | if (ant_conf->div_group == 0) { |
1294 | switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { | 1324 | /* Adjust the fast_div_bias based on main and alt lna conf */ |
1295 | case (0x01): /* A-B LNA2 */ | 1325 | switch ((ant_conf->main_lna_conf << 4) | |
1296 | ant_conf->fast_div_bias = 0x3b; | 1326 | ant_conf->alt_lna_conf) { |
1297 | break; | 1327 | case (0x01): /* A-B LNA2 */ |
1298 | case (0x02): /* A-B LNA1 */ | 1328 | ant_conf->fast_div_bias = 0x3b; |
1299 | ant_conf->fast_div_bias = 0x3d; | 1329 | break; |
1300 | break; | 1330 | case (0x02): /* A-B LNA1 */ |
1301 | case (0x03): /* A-B A+B */ | 1331 | ant_conf->fast_div_bias = 0x3d; |
1302 | ant_conf->fast_div_bias = 0x1; | 1332 | break; |
1303 | break; | 1333 | case (0x03): /* A-B A+B */ |
1304 | case (0x10): /* LNA2 A-B */ | 1334 | ant_conf->fast_div_bias = 0x1; |
1305 | ant_conf->fast_div_bias = 0x7; | 1335 | break; |
1306 | break; | 1336 | case (0x10): /* LNA2 A-B */ |
1307 | case (0x12): /* LNA2 LNA1 */ | 1337 | ant_conf->fast_div_bias = 0x7; |
1308 | ant_conf->fast_div_bias = 0x2; | 1338 | break; |
1309 | break; | 1339 | case (0x12): /* LNA2 LNA1 */ |
1310 | case (0x13): /* LNA2 A+B */ | 1340 | ant_conf->fast_div_bias = 0x2; |
1311 | ant_conf->fast_div_bias = 0x7; | 1341 | break; |
1312 | break; | 1342 | case (0x13): /* LNA2 A+B */ |
1313 | case (0x20): /* LNA1 A-B */ | 1343 | ant_conf->fast_div_bias = 0x7; |
1314 | ant_conf->fast_div_bias = 0x6; | 1344 | break; |
1315 | break; | 1345 | case (0x20): /* LNA1 A-B */ |
1316 | case (0x21): /* LNA1 LNA2 */ | 1346 | ant_conf->fast_div_bias = 0x6; |
1317 | ant_conf->fast_div_bias = 0x0; | 1347 | break; |
1318 | break; | 1348 | case (0x21): /* LNA1 LNA2 */ |
1319 | case (0x23): /* LNA1 A+B */ | 1349 | ant_conf->fast_div_bias = 0x0; |
1320 | ant_conf->fast_div_bias = 0x6; | 1350 | break; |
1321 | break; | 1351 | case (0x23): /* LNA1 A+B */ |
1322 | case (0x30): /* A+B A-B */ | 1352 | ant_conf->fast_div_bias = 0x6; |
1323 | ant_conf->fast_div_bias = 0x1; | 1353 | break; |
1324 | break; | 1354 | case (0x30): /* A+B A-B */ |
1325 | case (0x31): /* A+B LNA2 */ | 1355 | ant_conf->fast_div_bias = 0x1; |
1326 | ant_conf->fast_div_bias = 0x3b; | 1356 | break; |
1327 | break; | 1357 | case (0x31): /* A+B LNA2 */ |
1328 | case (0x32): /* A+B LNA1 */ | 1358 | ant_conf->fast_div_bias = 0x3b; |
1329 | ant_conf->fast_div_bias = 0x3d; | 1359 | break; |
1330 | break; | 1360 | case (0x32): /* A+B LNA1 */ |
1331 | default: | 1361 | ant_conf->fast_div_bias = 0x3d; |
1332 | break; | 1362 | break; |
1363 | default: | ||
1364 | break; | ||
1365 | } | ||
1366 | } else if (ant_conf->div_group == 2) { | ||
1367 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
1368 | switch ((ant_conf->main_lna_conf << 4) | | ||
1369 | ant_conf->alt_lna_conf) { | ||
1370 | case (0x01): /* A-B LNA2 */ | ||
1371 | ant_conf->fast_div_bias = 0x1; | ||
1372 | ant_conf->main_gaintb = 0; | ||
1373 | ant_conf->alt_gaintb = 0; | ||
1374 | break; | ||
1375 | case (0x02): /* A-B LNA1 */ | ||
1376 | ant_conf->fast_div_bias = 0x1; | ||
1377 | ant_conf->main_gaintb = 0; | ||
1378 | ant_conf->alt_gaintb = 0; | ||
1379 | break; | ||
1380 | case (0x03): /* A-B A+B */ | ||
1381 | ant_conf->fast_div_bias = 0x1; | ||
1382 | ant_conf->main_gaintb = 0; | ||
1383 | ant_conf->alt_gaintb = 0; | ||
1384 | break; | ||
1385 | case (0x10): /* LNA2 A-B */ | ||
1386 | if (!(antcomb->scan) && | ||
1387 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1388 | ant_conf->fast_div_bias = 0x1; | ||
1389 | else | ||
1390 | ant_conf->fast_div_bias = 0x2; | ||
1391 | ant_conf->main_gaintb = 0; | ||
1392 | ant_conf->alt_gaintb = 0; | ||
1393 | break; | ||
1394 | case (0x12): /* LNA2 LNA1 */ | ||
1395 | ant_conf->fast_div_bias = 0x1; | ||
1396 | ant_conf->main_gaintb = 0; | ||
1397 | ant_conf->alt_gaintb = 0; | ||
1398 | break; | ||
1399 | case (0x13): /* LNA2 A+B */ | ||
1400 | if (!(antcomb->scan) && | ||
1401 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1402 | ant_conf->fast_div_bias = 0x1; | ||
1403 | else | ||
1404 | ant_conf->fast_div_bias = 0x2; | ||
1405 | ant_conf->main_gaintb = 0; | ||
1406 | ant_conf->alt_gaintb = 0; | ||
1407 | break; | ||
1408 | case (0x20): /* LNA1 A-B */ | ||
1409 | if (!(antcomb->scan) && | ||
1410 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1411 | ant_conf->fast_div_bias = 0x1; | ||
1412 | else | ||
1413 | ant_conf->fast_div_bias = 0x2; | ||
1414 | ant_conf->main_gaintb = 0; | ||
1415 | ant_conf->alt_gaintb = 0; | ||
1416 | break; | ||
1417 | case (0x21): /* LNA1 LNA2 */ | ||
1418 | ant_conf->fast_div_bias = 0x1; | ||
1419 | ant_conf->main_gaintb = 0; | ||
1420 | ant_conf->alt_gaintb = 0; | ||
1421 | break; | ||
1422 | case (0x23): /* LNA1 A+B */ | ||
1423 | if (!(antcomb->scan) && | ||
1424 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1425 | ant_conf->fast_div_bias = 0x1; | ||
1426 | else | ||
1427 | ant_conf->fast_div_bias = 0x2; | ||
1428 | ant_conf->main_gaintb = 0; | ||
1429 | ant_conf->alt_gaintb = 0; | ||
1430 | break; | ||
1431 | case (0x30): /* A+B A-B */ | ||
1432 | ant_conf->fast_div_bias = 0x1; | ||
1433 | ant_conf->main_gaintb = 0; | ||
1434 | ant_conf->alt_gaintb = 0; | ||
1435 | break; | ||
1436 | case (0x31): /* A+B LNA2 */ | ||
1437 | ant_conf->fast_div_bias = 0x1; | ||
1438 | ant_conf->main_gaintb = 0; | ||
1439 | ant_conf->alt_gaintb = 0; | ||
1440 | break; | ||
1441 | case (0x32): /* A+B LNA1 */ | ||
1442 | ant_conf->fast_div_bias = 0x1; | ||
1443 | ant_conf->main_gaintb = 0; | ||
1444 | ant_conf->alt_gaintb = 0; | ||
1445 | break; | ||
1446 | default: | ||
1447 | break; | ||
1448 | } | ||
1449 | |||
1333 | } | 1450 | } |
1451 | |||
1334 | } | 1452 | } |
1335 | 1453 | ||
1336 | /* Antenna diversity and combining */ | 1454 | /* Antenna diversity and combining */ |
@@ -1350,8 +1468,8 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
1350 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | 1468 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & |
1351 | ATH_ANT_RX_MASK; | 1469 | ATH_ANT_RX_MASK; |
1352 | 1470 | ||
1353 | /* Record packet only when alt_rssi is positive */ | 1471 | /* Record packet only when both main_rssi and alt_rssi is positive */ |
1354 | if (alt_rssi > 0) { | 1472 | if (main_rssi > 0 && alt_rssi > 0) { |
1355 | antcomb->total_pkt_count++; | 1473 | antcomb->total_pkt_count++; |
1356 | antcomb->main_total_rssi += main_rssi; | 1474 | antcomb->main_total_rssi += main_rssi; |
1357 | antcomb->alt_total_rssi += alt_rssi; | 1475 | antcomb->alt_total_rssi += alt_rssi; |
@@ -1411,7 +1529,9 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
1411 | } | 1529 | } |
1412 | 1530 | ||
1413 | if (!antcomb->scan) { | 1531 | if (!antcomb->scan) { |
1414 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | 1532 | if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, |
1533 | alt_ratio, curr_main_set, curr_alt_set, | ||
1534 | alt_rssi_avg, main_rssi_avg)) { | ||
1415 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | 1535 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { |
1416 | /* Switch main and alt LNA */ | 1536 | /* Switch main and alt LNA */ |
1417 | div_ant_conf.main_lna_conf = | 1537 | div_ant_conf.main_lna_conf = |
@@ -1440,7 +1560,7 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
1440 | } | 1560 | } |
1441 | 1561 | ||
1442 | if ((alt_rssi_avg < (main_rssi_avg + | 1562 | if ((alt_rssi_avg < (main_rssi_avg + |
1443 | ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA))) | 1563 | div_ant_conf.lna1_lna2_delta))) |
1444 | goto div_comb_done; | 1564 | goto div_comb_done; |
1445 | } | 1565 | } |
1446 | 1566 | ||
@@ -1554,8 +1674,7 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
1554 | antcomb->quick_scan_cnt++; | 1674 | antcomb->quick_scan_cnt++; |
1555 | 1675 | ||
1556 | div_comb_done: | 1676 | div_comb_done: |
1557 | ath_ant_div_conf_fast_divbias(&div_ant_conf); | 1677 | ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); |
1558 | |||
1559 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | 1678 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); |
1560 | 1679 | ||
1561 | antcomb->scan_start_time = jiffies; | 1680 | antcomb->scan_start_time = jiffies; |