aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/recv.c
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2012-06-04 10:53:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-06 15:20:31 -0400
commit8da07830e10a91cbe7badf9767230aafdd520b9c (patch)
treefd71bd855f0a1f2372756622e5a3e443c09a631f /drivers/net/wireless/ath/ath9k/recv.c
parentaf68abadac378f7a4a44fe766383e7b88c7f9c3b (diff)
ath9k: Move LNA code to antenna.c
And use a helper function to setup antennae after a reset. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/recv.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c740
1 files changed, 0 insertions, 740 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 611be4f934e7..c2f5fd1c8b87 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -20,43 +20,6 @@
20 20
21#define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) 21#define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb))
22 22
23static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta,
24 int mindelta, int main_rssi_avg,
25 int alt_rssi_avg, int pkt_count)
26{
27 return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
28 (alt_rssi_avg > main_rssi_avg + maxdelta)) ||
29 (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50);
30}
31
32static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio,
33 int curr_main_set, int curr_alt_set,
34 int alt_rssi_avg, int main_rssi_avg)
35{
36 bool result = false;
37 switch (div_group) {
38 case 0:
39 if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
40 result = true;
41 break;
42 case 1:
43 case 2:
44 if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&
45 (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&
46 (alt_rssi_avg >= (main_rssi_avg - 5))) ||
47 ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) &&
48 (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) &&
49 (alt_rssi_avg >= (main_rssi_avg - 2)))) &&
50 (alt_rssi_avg >= 4))
51 result = true;
52 else
53 result = false;
54 break;
55 }
56
57 return result;
58}
59
60static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) 23static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
61{ 24{
62 return sc->ps_enabled && 25 return sc->ps_enabled &&
@@ -1067,709 +1030,6 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
1067 rxs->flag &= ~RX_FLAG_DECRYPTED; 1030 rxs->flag &= ~RX_FLAG_DECRYPTED;
1068} 1031}
1069 1032
1070static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
1071 struct ath_hw_antcomb_conf ant_conf,
1072 int main_rssi_avg)
1073{
1074 antcomb->quick_scan_cnt = 0;
1075
1076 if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
1077 antcomb->rssi_lna2 = main_rssi_avg;
1078 else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1)
1079 antcomb->rssi_lna1 = main_rssi_avg;
1080
1081 switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
1082 case 0x10: /* LNA2 A-B */
1083 antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
1084 antcomb->first_quick_scan_conf =
1085 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1086 antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
1087 break;
1088 case 0x20: /* LNA1 A-B */
1089 antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
1090 antcomb->first_quick_scan_conf =
1091 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1092 antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
1093 break;
1094 case 0x21: /* LNA1 LNA2 */
1095 antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
1096 antcomb->first_quick_scan_conf =
1097 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
1098 antcomb->second_quick_scan_conf =
1099 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1100 break;
1101 case 0x12: /* LNA2 LNA1 */
1102 antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
1103 antcomb->first_quick_scan_conf =
1104 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
1105 antcomb->second_quick_scan_conf =
1106 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1107 break;
1108 case 0x13: /* LNA2 A+B */
1109 antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1110 antcomb->first_quick_scan_conf =
1111 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
1112 antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
1113 break;
1114 case 0x23: /* LNA1 A+B */
1115 antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1116 antcomb->first_quick_scan_conf =
1117 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
1118 antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
1119 break;
1120 default:
1121 break;
1122 }
1123}
1124
1125static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
1126 struct ath_hw_antcomb_conf *div_ant_conf,
1127 int main_rssi_avg, int alt_rssi_avg,
1128 int alt_ratio)
1129{
1130 /* alt_good */
1131 switch (antcomb->quick_scan_cnt) {
1132 case 0:
1133 /* set alt to main, and alt to first conf */
1134 div_ant_conf->main_lna_conf = antcomb->main_conf;
1135 div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf;
1136 break;
1137 case 1:
1138 /* set alt to main, and alt to first conf */
1139 div_ant_conf->main_lna_conf = antcomb->main_conf;
1140 div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf;
1141 antcomb->rssi_first = main_rssi_avg;
1142 antcomb->rssi_second = alt_rssi_avg;
1143
1144 if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
1145 /* main is LNA1 */
1146 if (ath_is_alt_ant_ratio_better(alt_ratio,
1147 ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
1148 ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
1149 main_rssi_avg, alt_rssi_avg,
1150 antcomb->total_pkt_count))
1151 antcomb->first_ratio = true;
1152 else
1153 antcomb->first_ratio = false;
1154 } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
1155 if (ath_is_alt_ant_ratio_better(alt_ratio,
1156 ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
1157 ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
1158 main_rssi_avg, alt_rssi_avg,
1159 antcomb->total_pkt_count))
1160 antcomb->first_ratio = true;
1161 else
1162 antcomb->first_ratio = false;
1163 } else {
1164 if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
1165 (alt_rssi_avg > main_rssi_avg +
1166 ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
1167 (alt_rssi_avg > main_rssi_avg)) &&
1168 (antcomb->total_pkt_count > 50))
1169 antcomb->first_ratio = true;
1170 else
1171 antcomb->first_ratio = false;
1172 }
1173 break;
1174 case 2:
1175 antcomb->alt_good = false;
1176 antcomb->scan_not_start = false;
1177 antcomb->scan = false;
1178 antcomb->rssi_first = main_rssi_avg;
1179 antcomb->rssi_third = alt_rssi_avg;
1180
1181 if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1)
1182 antcomb->rssi_lna1 = alt_rssi_avg;
1183 else if (antcomb->second_quick_scan_conf ==
1184 ATH_ANT_DIV_COMB_LNA2)
1185 antcomb->rssi_lna2 = alt_rssi_avg;
1186 else if (antcomb->second_quick_scan_conf ==
1187 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) {
1188 if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)
1189 antcomb->rssi_lna2 = main_rssi_avg;
1190 else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1)
1191 antcomb->rssi_lna1 = main_rssi_avg;
1192 }
1193
1194 if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
1195 ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)
1196 div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
1197 else
1198 div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
1199
1200 if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
1201 if (ath_is_alt_ant_ratio_better(alt_ratio,
1202 ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
1203 ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
1204 main_rssi_avg, alt_rssi_avg,
1205 antcomb->total_pkt_count))
1206 antcomb->second_ratio = true;
1207 else
1208 antcomb->second_ratio = false;
1209 } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
1210 if (ath_is_alt_ant_ratio_better(alt_ratio,
1211 ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
1212 ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
1213 main_rssi_avg, alt_rssi_avg,
1214 antcomb->total_pkt_count))
1215 antcomb->second_ratio = true;
1216 else
1217 antcomb->second_ratio = false;
1218 } else {
1219 if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
1220 (alt_rssi_avg > main_rssi_avg +
1221 ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
1222 (alt_rssi_avg > main_rssi_avg)) &&
1223 (antcomb->total_pkt_count > 50))
1224 antcomb->second_ratio = true;
1225 else
1226 antcomb->second_ratio = false;
1227 }
1228
1229 /* set alt to the conf with maximun ratio */
1230 if (antcomb->first_ratio && antcomb->second_ratio) {
1231 if (antcomb->rssi_second > antcomb->rssi_third) {
1232 /* first alt*/
1233 if ((antcomb->first_quick_scan_conf ==
1234 ATH_ANT_DIV_COMB_LNA1) ||
1235 (antcomb->first_quick_scan_conf ==
1236 ATH_ANT_DIV_COMB_LNA2))
1237 /* Set alt LNA1 or LNA2*/
1238 if (div_ant_conf->main_lna_conf ==
1239 ATH_ANT_DIV_COMB_LNA2)
1240 div_ant_conf->alt_lna_conf =
1241 ATH_ANT_DIV_COMB_LNA1;
1242 else
1243 div_ant_conf->alt_lna_conf =
1244 ATH_ANT_DIV_COMB_LNA2;
1245 else
1246 /* Set alt to A+B or A-B */
1247 div_ant_conf->alt_lna_conf =
1248 antcomb->first_quick_scan_conf;
1249 } else if ((antcomb->second_quick_scan_conf ==
1250 ATH_ANT_DIV_COMB_LNA1) ||
1251 (antcomb->second_quick_scan_conf ==
1252 ATH_ANT_DIV_COMB_LNA2)) {
1253 /* Set alt LNA1 or LNA2 */
1254 if (div_ant_conf->main_lna_conf ==
1255 ATH_ANT_DIV_COMB_LNA2)
1256 div_ant_conf->alt_lna_conf =
1257 ATH_ANT_DIV_COMB_LNA1;
1258 else
1259 div_ant_conf->alt_lna_conf =
1260 ATH_ANT_DIV_COMB_LNA2;
1261 } else {
1262 /* Set alt to A+B or A-B */
1263 div_ant_conf->alt_lna_conf =
1264 antcomb->second_quick_scan_conf;
1265 }
1266 } else if (antcomb->first_ratio) {
1267 /* first alt */
1268 if ((antcomb->first_quick_scan_conf ==
1269 ATH_ANT_DIV_COMB_LNA1) ||
1270 (antcomb->first_quick_scan_conf ==
1271 ATH_ANT_DIV_COMB_LNA2))
1272 /* Set alt LNA1 or LNA2 */
1273 if (div_ant_conf->main_lna_conf ==
1274 ATH_ANT_DIV_COMB_LNA2)
1275 div_ant_conf->alt_lna_conf =
1276 ATH_ANT_DIV_COMB_LNA1;
1277 else
1278 div_ant_conf->alt_lna_conf =
1279 ATH_ANT_DIV_COMB_LNA2;
1280 else
1281 /* Set alt to A+B or A-B */
1282 div_ant_conf->alt_lna_conf =
1283 antcomb->first_quick_scan_conf;
1284 } else if (antcomb->second_ratio) {
1285 /* second alt */
1286 if ((antcomb->second_quick_scan_conf ==
1287 ATH_ANT_DIV_COMB_LNA1) ||
1288 (antcomb->second_quick_scan_conf ==
1289 ATH_ANT_DIV_COMB_LNA2))
1290 /* Set alt LNA1 or LNA2 */
1291 if (div_ant_conf->main_lna_conf ==
1292 ATH_ANT_DIV_COMB_LNA2)
1293 div_ant_conf->alt_lna_conf =
1294 ATH_ANT_DIV_COMB_LNA1;
1295 else
1296 div_ant_conf->alt_lna_conf =
1297 ATH_ANT_DIV_COMB_LNA2;
1298 else
1299 /* Set alt to A+B or A-B */
1300 div_ant_conf->alt_lna_conf =
1301 antcomb->second_quick_scan_conf;
1302 } else {
1303 /* main is largest */
1304 if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) ||
1305 (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2))
1306 /* Set alt LNA1 or LNA2 */
1307 if (div_ant_conf->main_lna_conf ==
1308 ATH_ANT_DIV_COMB_LNA2)
1309 div_ant_conf->alt_lna_conf =
1310 ATH_ANT_DIV_COMB_LNA1;
1311 else
1312 div_ant_conf->alt_lna_conf =
1313 ATH_ANT_DIV_COMB_LNA2;
1314 else
1315 /* Set alt to A+B or A-B */
1316 div_ant_conf->alt_lna_conf = antcomb->main_conf;
1317 }
1318 break;
1319 default:
1320 break;
1321 }
1322}
1323
1324static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
1325 struct ath_ant_comb *antcomb, int alt_ratio)
1326{
1327 if (ant_conf->div_group == 0) {
1328 /* Adjust the fast_div_bias based on main and alt lna conf */
1329 switch ((ant_conf->main_lna_conf << 4) |
1330 ant_conf->alt_lna_conf) {
1331 case 0x01: /* A-B LNA2 */
1332 ant_conf->fast_div_bias = 0x3b;
1333 break;
1334 case 0x02: /* A-B LNA1 */
1335 ant_conf->fast_div_bias = 0x3d;
1336 break;
1337 case 0x03: /* A-B A+B */
1338 ant_conf->fast_div_bias = 0x1;
1339 break;
1340 case 0x10: /* LNA2 A-B */
1341 ant_conf->fast_div_bias = 0x7;
1342 break;
1343 case 0x12: /* LNA2 LNA1 */
1344 ant_conf->fast_div_bias = 0x2;
1345 break;
1346 case 0x13: /* LNA2 A+B */
1347 ant_conf->fast_div_bias = 0x7;
1348 break;
1349 case 0x20: /* LNA1 A-B */
1350 ant_conf->fast_div_bias = 0x6;
1351 break;
1352 case 0x21: /* LNA1 LNA2 */
1353 ant_conf->fast_div_bias = 0x0;
1354 break;
1355 case 0x23: /* LNA1 A+B */
1356 ant_conf->fast_div_bias = 0x6;
1357 break;
1358 case 0x30: /* A+B A-B */
1359 ant_conf->fast_div_bias = 0x1;
1360 break;
1361 case 0x31: /* A+B LNA2 */
1362 ant_conf->fast_div_bias = 0x3b;
1363 break;
1364 case 0x32: /* A+B LNA1 */
1365 ant_conf->fast_div_bias = 0x3d;
1366 break;
1367 default:
1368 break;
1369 }
1370 } else if (ant_conf->div_group == 1) {
1371 /* Adjust the fast_div_bias based on main and alt_lna_conf */
1372 switch ((ant_conf->main_lna_conf << 4) |
1373 ant_conf->alt_lna_conf) {
1374 case 0x01: /* A-B LNA2 */
1375 ant_conf->fast_div_bias = 0x1;
1376 ant_conf->main_gaintb = 0;
1377 ant_conf->alt_gaintb = 0;
1378 break;
1379 case 0x02: /* A-B LNA1 */
1380 ant_conf->fast_div_bias = 0x1;
1381 ant_conf->main_gaintb = 0;
1382 ant_conf->alt_gaintb = 0;
1383 break;
1384 case 0x03: /* A-B A+B */
1385 ant_conf->fast_div_bias = 0x1;
1386 ant_conf->main_gaintb = 0;
1387 ant_conf->alt_gaintb = 0;
1388 break;
1389 case 0x10: /* LNA2 A-B */
1390 if (!(antcomb->scan) &&
1391 (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
1392 ant_conf->fast_div_bias = 0x3f;
1393 else
1394 ant_conf->fast_div_bias = 0x1;
1395 ant_conf->main_gaintb = 0;
1396 ant_conf->alt_gaintb = 0;
1397 break;
1398 case 0x12: /* LNA2 LNA1 */
1399 ant_conf->fast_div_bias = 0x1;
1400 ant_conf->main_gaintb = 0;
1401 ant_conf->alt_gaintb = 0;
1402 break;
1403 case 0x13: /* LNA2 A+B */
1404 if (!(antcomb->scan) &&
1405 (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
1406 ant_conf->fast_div_bias = 0x3f;
1407 else
1408 ant_conf->fast_div_bias = 0x1;
1409 ant_conf->main_gaintb = 0;
1410 ant_conf->alt_gaintb = 0;
1411 break;
1412 case 0x20: /* LNA1 A-B */
1413 if (!(antcomb->scan) &&
1414 (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
1415 ant_conf->fast_div_bias = 0x3f;
1416 else
1417 ant_conf->fast_div_bias = 0x1;
1418 ant_conf->main_gaintb = 0;
1419 ant_conf->alt_gaintb = 0;
1420 break;
1421 case 0x21: /* LNA1 LNA2 */
1422 ant_conf->fast_div_bias = 0x1;
1423 ant_conf->main_gaintb = 0;
1424 ant_conf->alt_gaintb = 0;
1425 break;
1426 case 0x23: /* LNA1 A+B */
1427 if (!(antcomb->scan) &&
1428 (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
1429 ant_conf->fast_div_bias = 0x3f;
1430 else
1431 ant_conf->fast_div_bias = 0x1;
1432 ant_conf->main_gaintb = 0;
1433 ant_conf->alt_gaintb = 0;
1434 break;
1435 case 0x30: /* A+B A-B */
1436 ant_conf->fast_div_bias = 0x1;
1437 ant_conf->main_gaintb = 0;
1438 ant_conf->alt_gaintb = 0;
1439 break;
1440 case 0x31: /* A+B LNA2 */
1441 ant_conf->fast_div_bias = 0x1;
1442 ant_conf->main_gaintb = 0;
1443 ant_conf->alt_gaintb = 0;
1444 break;
1445 case 0x32: /* A+B LNA1 */
1446 ant_conf->fast_div_bias = 0x1;
1447 ant_conf->main_gaintb = 0;
1448 ant_conf->alt_gaintb = 0;
1449 break;
1450 default:
1451 break;
1452 }
1453 } else if (ant_conf->div_group == 2) {
1454 /* Adjust the fast_div_bias based on main and alt_lna_conf */
1455 switch ((ant_conf->main_lna_conf << 4) |
1456 ant_conf->alt_lna_conf) {
1457 case 0x01: /* A-B LNA2 */
1458 ant_conf->fast_div_bias = 0x1;
1459 ant_conf->main_gaintb = 0;
1460 ant_conf->alt_gaintb = 0;
1461 break;
1462 case 0x02: /* A-B LNA1 */
1463 ant_conf->fast_div_bias = 0x1;
1464 ant_conf->main_gaintb = 0;
1465 ant_conf->alt_gaintb = 0;
1466 break;
1467 case 0x03: /* A-B A+B */
1468 ant_conf->fast_div_bias = 0x1;
1469 ant_conf->main_gaintb = 0;
1470 ant_conf->alt_gaintb = 0;
1471 break;
1472 case 0x10: /* LNA2 A-B */
1473 if (!(antcomb->scan) &&
1474 (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
1475 ant_conf->fast_div_bias = 0x1;
1476 else
1477 ant_conf->fast_div_bias = 0x2;
1478 ant_conf->main_gaintb = 0;
1479 ant_conf->alt_gaintb = 0;
1480 break;
1481 case 0x12: /* LNA2 LNA1 */
1482 ant_conf->fast_div_bias = 0x1;
1483 ant_conf->main_gaintb = 0;
1484 ant_conf->alt_gaintb = 0;
1485 break;
1486 case 0x13: /* LNA2 A+B */
1487 if (!(antcomb->scan) &&
1488 (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
1489 ant_conf->fast_div_bias = 0x1;
1490 else
1491 ant_conf->fast_div_bias = 0x2;
1492 ant_conf->main_gaintb = 0;
1493 ant_conf->alt_gaintb = 0;
1494 break;
1495 case 0x20: /* LNA1 A-B */
1496 if (!(antcomb->scan) &&
1497 (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
1498 ant_conf->fast_div_bias = 0x1;
1499 else
1500 ant_conf->fast_div_bias = 0x2;
1501 ant_conf->main_gaintb = 0;
1502 ant_conf->alt_gaintb = 0;
1503 break;
1504 case 0x21: /* LNA1 LNA2 */
1505 ant_conf->fast_div_bias = 0x1;
1506 ant_conf->main_gaintb = 0;
1507 ant_conf->alt_gaintb = 0;
1508 break;
1509 case 0x23: /* LNA1 A+B */
1510 if (!(antcomb->scan) &&
1511 (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
1512 ant_conf->fast_div_bias = 0x1;
1513 else
1514 ant_conf->fast_div_bias = 0x2;
1515 ant_conf->main_gaintb = 0;
1516 ant_conf->alt_gaintb = 0;
1517 break;
1518 case 0x30: /* A+B A-B */
1519 ant_conf->fast_div_bias = 0x1;
1520 ant_conf->main_gaintb = 0;
1521 ant_conf->alt_gaintb = 0;
1522 break;
1523 case 0x31: /* A+B LNA2 */
1524 ant_conf->fast_div_bias = 0x1;
1525 ant_conf->main_gaintb = 0;
1526 ant_conf->alt_gaintb = 0;
1527 break;
1528 case 0x32: /* A+B LNA1 */
1529 ant_conf->fast_div_bias = 0x1;
1530 ant_conf->main_gaintb = 0;
1531 ant_conf->alt_gaintb = 0;
1532 break;
1533 default:
1534 break;
1535 }
1536 }
1537}
1538
1539/* Antenna diversity and combining */
1540static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
1541{
1542 struct ath_hw_antcomb_conf div_ant_conf;
1543 struct ath_ant_comb *antcomb = &sc->ant_comb;
1544 int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
1545 int curr_main_set;
1546 int main_rssi = rs->rs_rssi_ctl0;
1547 int alt_rssi = rs->rs_rssi_ctl1;
1548 int rx_ant_conf, main_ant_conf;
1549 bool short_scan = false;
1550
1551 rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
1552 ATH_ANT_RX_MASK;
1553 main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
1554 ATH_ANT_RX_MASK;
1555
1556 /* Record packet only when both main_rssi and alt_rssi is positive */
1557 if (main_rssi > 0 && alt_rssi > 0) {
1558 antcomb->total_pkt_count++;
1559 antcomb->main_total_rssi += main_rssi;
1560 antcomb->alt_total_rssi += alt_rssi;
1561 if (main_ant_conf == rx_ant_conf)
1562 antcomb->main_recv_cnt++;
1563 else
1564 antcomb->alt_recv_cnt++;
1565 }
1566
1567 /* Short scan check */
1568 if (antcomb->scan && antcomb->alt_good) {
1569 if (time_after(jiffies, antcomb->scan_start_time +
1570 msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
1571 short_scan = true;
1572 else
1573 if (antcomb->total_pkt_count ==
1574 ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
1575 alt_ratio = ((antcomb->alt_recv_cnt * 100) /
1576 antcomb->total_pkt_count);
1577 if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
1578 short_scan = true;
1579 }
1580 }
1581
1582 if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) ||
1583 rs->rs_moreaggr) && !short_scan)
1584 return;
1585
1586 if (antcomb->total_pkt_count) {
1587 alt_ratio = ((antcomb->alt_recv_cnt * 100) /
1588 antcomb->total_pkt_count);
1589 main_rssi_avg = (antcomb->main_total_rssi /
1590 antcomb->total_pkt_count);
1591 alt_rssi_avg = (antcomb->alt_total_rssi /
1592 antcomb->total_pkt_count);
1593 }
1594
1595
1596 ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf);
1597 curr_alt_set = div_ant_conf.alt_lna_conf;
1598 curr_main_set = div_ant_conf.main_lna_conf;
1599
1600 antcomb->count++;
1601
1602 if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) {
1603 if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
1604 ath_lnaconf_alt_good_scan(antcomb, div_ant_conf,
1605 main_rssi_avg);
1606 antcomb->alt_good = true;
1607 } else {
1608 antcomb->alt_good = false;
1609 }
1610
1611 antcomb->count = 0;
1612 antcomb->scan = true;
1613 antcomb->scan_not_start = true;
1614 }
1615
1616 if (!antcomb->scan) {
1617 if (ath_ant_div_comb_alt_check(div_ant_conf.div_group,
1618 alt_ratio, curr_main_set, curr_alt_set,
1619 alt_rssi_avg, main_rssi_avg)) {
1620 if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) {
1621 /* Switch main and alt LNA */
1622 div_ant_conf.main_lna_conf =
1623 ATH_ANT_DIV_COMB_LNA2;
1624 div_ant_conf.alt_lna_conf =
1625 ATH_ANT_DIV_COMB_LNA1;
1626 } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) {
1627 div_ant_conf.main_lna_conf =
1628 ATH_ANT_DIV_COMB_LNA1;
1629 div_ant_conf.alt_lna_conf =
1630 ATH_ANT_DIV_COMB_LNA2;
1631 }
1632
1633 goto div_comb_done;
1634 } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) &&
1635 (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) {
1636 /* Set alt to another LNA */
1637 if (curr_main_set == ATH_ANT_DIV_COMB_LNA2)
1638 div_ant_conf.alt_lna_conf =
1639 ATH_ANT_DIV_COMB_LNA1;
1640 else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1)
1641 div_ant_conf.alt_lna_conf =
1642 ATH_ANT_DIV_COMB_LNA2;
1643
1644 goto div_comb_done;
1645 }
1646
1647 if ((alt_rssi_avg < (main_rssi_avg +
1648 div_ant_conf.lna1_lna2_delta)))
1649 goto div_comb_done;
1650 }
1651
1652 if (!antcomb->scan_not_start) {
1653 switch (curr_alt_set) {
1654 case ATH_ANT_DIV_COMB_LNA2:
1655 antcomb->rssi_lna2 = alt_rssi_avg;
1656 antcomb->rssi_lna1 = main_rssi_avg;
1657 antcomb->scan = true;
1658 /* set to A+B */
1659 div_ant_conf.main_lna_conf =
1660 ATH_ANT_DIV_COMB_LNA1;
1661 div_ant_conf.alt_lna_conf =
1662 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1663 break;
1664 case ATH_ANT_DIV_COMB_LNA1:
1665 antcomb->rssi_lna1 = alt_rssi_avg;
1666 antcomb->rssi_lna2 = main_rssi_avg;
1667 antcomb->scan = true;
1668 /* set to A+B */
1669 div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
1670 div_ant_conf.alt_lna_conf =
1671 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1672 break;
1673 case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2:
1674 antcomb->rssi_add = alt_rssi_avg;
1675 antcomb->scan = true;
1676 /* set to A-B */
1677 div_ant_conf.alt_lna_conf =
1678 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
1679 break;
1680 case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2:
1681 antcomb->rssi_sub = alt_rssi_avg;
1682 antcomb->scan = false;
1683 if (antcomb->rssi_lna2 >
1684 (antcomb->rssi_lna1 +
1685 ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) {
1686 /* use LNA2 as main LNA */
1687 if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
1688 (antcomb->rssi_add > antcomb->rssi_sub)) {
1689 /* set to A+B */
1690 div_ant_conf.main_lna_conf =
1691 ATH_ANT_DIV_COMB_LNA2;
1692 div_ant_conf.alt_lna_conf =
1693 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1694 } else if (antcomb->rssi_sub >
1695 antcomb->rssi_lna1) {
1696 /* set to A-B */
1697 div_ant_conf.main_lna_conf =
1698 ATH_ANT_DIV_COMB_LNA2;
1699 div_ant_conf.alt_lna_conf =
1700 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
1701 } else {
1702 /* set to LNA1 */
1703 div_ant_conf.main_lna_conf =
1704 ATH_ANT_DIV_COMB_LNA2;
1705 div_ant_conf.alt_lna_conf =
1706 ATH_ANT_DIV_COMB_LNA1;
1707 }
1708 } else {
1709 /* use LNA1 as main LNA */
1710 if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
1711 (antcomb->rssi_add > antcomb->rssi_sub)) {
1712 /* set to A+B */
1713 div_ant_conf.main_lna_conf =
1714 ATH_ANT_DIV_COMB_LNA1;
1715 div_ant_conf.alt_lna_conf =
1716 ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
1717 } else if (antcomb->rssi_sub >
1718 antcomb->rssi_lna1) {
1719 /* set to A-B */
1720 div_ant_conf.main_lna_conf =
1721 ATH_ANT_DIV_COMB_LNA1;
1722 div_ant_conf.alt_lna_conf =
1723 ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
1724 } else {
1725 /* set to LNA2 */
1726 div_ant_conf.main_lna_conf =
1727 ATH_ANT_DIV_COMB_LNA1;
1728 div_ant_conf.alt_lna_conf =
1729 ATH_ANT_DIV_COMB_LNA2;
1730 }
1731 }
1732 break;
1733 default:
1734 break;
1735 }
1736 } else {
1737 if (!antcomb->alt_good) {
1738 antcomb->scan_not_start = false;
1739 /* Set alt to another LNA */
1740 if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) {
1741 div_ant_conf.main_lna_conf =
1742 ATH_ANT_DIV_COMB_LNA2;
1743 div_ant_conf.alt_lna_conf =
1744 ATH_ANT_DIV_COMB_LNA1;
1745 } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) {
1746 div_ant_conf.main_lna_conf =
1747 ATH_ANT_DIV_COMB_LNA1;
1748 div_ant_conf.alt_lna_conf =
1749 ATH_ANT_DIV_COMB_LNA2;
1750 }
1751 goto div_comb_done;
1752 }
1753 }
1754
1755 ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
1756 main_rssi_avg, alt_rssi_avg,
1757 alt_ratio);
1758
1759 antcomb->quick_scan_cnt++;
1760
1761div_comb_done:
1762 ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio);
1763 ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf);
1764
1765 antcomb->scan_start_time = jiffies;
1766 antcomb->total_pkt_count = 0;
1767 antcomb->main_total_rssi = 0;
1768 antcomb->alt_total_rssi = 0;
1769 antcomb->main_recv_cnt = 0;
1770 antcomb->alt_recv_cnt = 0;
1771}
1772
1773int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) 1033int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
1774{ 1034{
1775 struct ath_buf *bf; 1035 struct ath_buf *bf;