diff options
author | Sujith Manoharan <c_manoha@qca.qualcomm.com> | 2012-06-04 10:53:49 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-06-06 15:20:31 -0400 |
commit | 8da07830e10a91cbe7badf9767230aafdd520b9c (patch) | |
tree | fd71bd855f0a1f2372756622e5a3e443c09a631f /drivers/net | |
parent | af68abadac378f7a4a44fe766383e7b88c7f9c3b (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')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/antenna.c | 776 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 740 |
5 files changed, 786 insertions, 757 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 4d60fa84cbb4..9c41232b0cd0 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -4,7 +4,8 @@ ath9k-y += beacon.o \ | |||
4 | main.o \ | 4 | main.o \ |
5 | recv.o \ | 5 | recv.o \ |
6 | xmit.o \ | 6 | xmit.o \ |
7 | link.o | 7 | link.o \ |
8 | antenna.o | ||
8 | 9 | ||
9 | ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o | 10 | ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o |
10 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | 11 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o |
diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c new file mode 100644 index 000000000000..bbcfeb3b2a60 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/antenna.c | |||
@@ -0,0 +1,776 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, | ||
20 | int mindelta, int main_rssi_avg, | ||
21 | int alt_rssi_avg, int pkt_count) | ||
22 | { | ||
23 | return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
24 | (alt_rssi_avg > main_rssi_avg + maxdelta)) || | ||
25 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | ||
26 | } | ||
27 | |||
28 | static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, | ||
29 | int curr_main_set, int curr_alt_set, | ||
30 | int alt_rssi_avg, int main_rssi_avg) | ||
31 | { | ||
32 | bool result = false; | ||
33 | switch (div_group) { | ||
34 | case 0: | ||
35 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
36 | result = true; | ||
37 | break; | ||
38 | case 1: | ||
39 | case 2: | ||
40 | if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && | ||
41 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && | ||
42 | (alt_rssi_avg >= (main_rssi_avg - 5))) || | ||
43 | ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && | ||
44 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && | ||
45 | (alt_rssi_avg >= (main_rssi_avg - 2)))) && | ||
46 | (alt_rssi_avg >= 4)) | ||
47 | result = true; | ||
48 | else | ||
49 | result = false; | ||
50 | break; | ||
51 | } | ||
52 | |||
53 | return result; | ||
54 | } | ||
55 | |||
56 | static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, | ||
57 | struct ath_hw_antcomb_conf ant_conf, | ||
58 | int main_rssi_avg) | ||
59 | { | ||
60 | antcomb->quick_scan_cnt = 0; | ||
61 | |||
62 | if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
63 | antcomb->rssi_lna2 = main_rssi_avg; | ||
64 | else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) | ||
65 | antcomb->rssi_lna1 = main_rssi_avg; | ||
66 | |||
67 | switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { | ||
68 | case 0x10: /* LNA2 A-B */ | ||
69 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
70 | antcomb->first_quick_scan_conf = | ||
71 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
72 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
73 | break; | ||
74 | case 0x20: /* LNA1 A-B */ | ||
75 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
76 | antcomb->first_quick_scan_conf = | ||
77 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
78 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
79 | break; | ||
80 | case 0x21: /* LNA1 LNA2 */ | ||
81 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; | ||
82 | antcomb->first_quick_scan_conf = | ||
83 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
84 | antcomb->second_quick_scan_conf = | ||
85 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
86 | break; | ||
87 | case 0x12: /* LNA2 LNA1 */ | ||
88 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; | ||
89 | antcomb->first_quick_scan_conf = | ||
90 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
91 | antcomb->second_quick_scan_conf = | ||
92 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
93 | break; | ||
94 | case 0x13: /* LNA2 A+B */ | ||
95 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
96 | antcomb->first_quick_scan_conf = | ||
97 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
98 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
99 | break; | ||
100 | case 0x23: /* LNA1 A+B */ | ||
101 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
102 | antcomb->first_quick_scan_conf = | ||
103 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
104 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
105 | break; | ||
106 | default: | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | ||
112 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
113 | int main_rssi_avg, int alt_rssi_avg, | ||
114 | int alt_ratio) | ||
115 | { | ||
116 | /* alt_good */ | ||
117 | switch (antcomb->quick_scan_cnt) { | ||
118 | case 0: | ||
119 | /* set alt to main, and alt to first conf */ | ||
120 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
121 | div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; | ||
122 | break; | ||
123 | case 1: | ||
124 | /* set alt to main, and alt to first conf */ | ||
125 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
126 | div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; | ||
127 | antcomb->rssi_first = main_rssi_avg; | ||
128 | antcomb->rssi_second = alt_rssi_avg; | ||
129 | |||
130 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
131 | /* main is LNA1 */ | ||
132 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
133 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
134 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
135 | main_rssi_avg, alt_rssi_avg, | ||
136 | antcomb->total_pkt_count)) | ||
137 | antcomb->first_ratio = true; | ||
138 | else | ||
139 | antcomb->first_ratio = false; | ||
140 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
141 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
142 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
143 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
144 | main_rssi_avg, alt_rssi_avg, | ||
145 | antcomb->total_pkt_count)) | ||
146 | antcomb->first_ratio = true; | ||
147 | else | ||
148 | antcomb->first_ratio = false; | ||
149 | } else { | ||
150 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
151 | (alt_rssi_avg > main_rssi_avg + | ||
152 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
153 | (alt_rssi_avg > main_rssi_avg)) && | ||
154 | (antcomb->total_pkt_count > 50)) | ||
155 | antcomb->first_ratio = true; | ||
156 | else | ||
157 | antcomb->first_ratio = false; | ||
158 | } | ||
159 | break; | ||
160 | case 2: | ||
161 | antcomb->alt_good = false; | ||
162 | antcomb->scan_not_start = false; | ||
163 | antcomb->scan = false; | ||
164 | antcomb->rssi_first = main_rssi_avg; | ||
165 | antcomb->rssi_third = alt_rssi_avg; | ||
166 | |||
167 | if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) | ||
168 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
169 | else if (antcomb->second_quick_scan_conf == | ||
170 | ATH_ANT_DIV_COMB_LNA2) | ||
171 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
172 | else if (antcomb->second_quick_scan_conf == | ||
173 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { | ||
174 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) | ||
175 | antcomb->rssi_lna2 = main_rssi_avg; | ||
176 | else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) | ||
177 | antcomb->rssi_lna1 = main_rssi_avg; | ||
178 | } | ||
179 | |||
180 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + | ||
181 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) | ||
182 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
183 | else | ||
184 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
185 | |||
186 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
187 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
188 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
189 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
190 | main_rssi_avg, alt_rssi_avg, | ||
191 | antcomb->total_pkt_count)) | ||
192 | antcomb->second_ratio = true; | ||
193 | else | ||
194 | antcomb->second_ratio = false; | ||
195 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
196 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
197 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
198 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
199 | main_rssi_avg, alt_rssi_avg, | ||
200 | antcomb->total_pkt_count)) | ||
201 | antcomb->second_ratio = true; | ||
202 | else | ||
203 | antcomb->second_ratio = false; | ||
204 | } else { | ||
205 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
206 | (alt_rssi_avg > main_rssi_avg + | ||
207 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
208 | (alt_rssi_avg > main_rssi_avg)) && | ||
209 | (antcomb->total_pkt_count > 50)) | ||
210 | antcomb->second_ratio = true; | ||
211 | else | ||
212 | antcomb->second_ratio = false; | ||
213 | } | ||
214 | |||
215 | /* set alt to the conf with maximun ratio */ | ||
216 | if (antcomb->first_ratio && antcomb->second_ratio) { | ||
217 | if (antcomb->rssi_second > antcomb->rssi_third) { | ||
218 | /* first alt*/ | ||
219 | if ((antcomb->first_quick_scan_conf == | ||
220 | ATH_ANT_DIV_COMB_LNA1) || | ||
221 | (antcomb->first_quick_scan_conf == | ||
222 | ATH_ANT_DIV_COMB_LNA2)) | ||
223 | /* Set alt LNA1 or LNA2*/ | ||
224 | if (div_ant_conf->main_lna_conf == | ||
225 | ATH_ANT_DIV_COMB_LNA2) | ||
226 | div_ant_conf->alt_lna_conf = | ||
227 | ATH_ANT_DIV_COMB_LNA1; | ||
228 | else | ||
229 | div_ant_conf->alt_lna_conf = | ||
230 | ATH_ANT_DIV_COMB_LNA2; | ||
231 | else | ||
232 | /* Set alt to A+B or A-B */ | ||
233 | div_ant_conf->alt_lna_conf = | ||
234 | antcomb->first_quick_scan_conf; | ||
235 | } else if ((antcomb->second_quick_scan_conf == | ||
236 | ATH_ANT_DIV_COMB_LNA1) || | ||
237 | (antcomb->second_quick_scan_conf == | ||
238 | ATH_ANT_DIV_COMB_LNA2)) { | ||
239 | /* Set alt LNA1 or LNA2 */ | ||
240 | if (div_ant_conf->main_lna_conf == | ||
241 | ATH_ANT_DIV_COMB_LNA2) | ||
242 | div_ant_conf->alt_lna_conf = | ||
243 | ATH_ANT_DIV_COMB_LNA1; | ||
244 | else | ||
245 | div_ant_conf->alt_lna_conf = | ||
246 | ATH_ANT_DIV_COMB_LNA2; | ||
247 | } else { | ||
248 | /* Set alt to A+B or A-B */ | ||
249 | div_ant_conf->alt_lna_conf = | ||
250 | antcomb->second_quick_scan_conf; | ||
251 | } | ||
252 | } else if (antcomb->first_ratio) { | ||
253 | /* first alt */ | ||
254 | if ((antcomb->first_quick_scan_conf == | ||
255 | ATH_ANT_DIV_COMB_LNA1) || | ||
256 | (antcomb->first_quick_scan_conf == | ||
257 | ATH_ANT_DIV_COMB_LNA2)) | ||
258 | /* Set alt LNA1 or LNA2 */ | ||
259 | if (div_ant_conf->main_lna_conf == | ||
260 | ATH_ANT_DIV_COMB_LNA2) | ||
261 | div_ant_conf->alt_lna_conf = | ||
262 | ATH_ANT_DIV_COMB_LNA1; | ||
263 | else | ||
264 | div_ant_conf->alt_lna_conf = | ||
265 | ATH_ANT_DIV_COMB_LNA2; | ||
266 | else | ||
267 | /* Set alt to A+B or A-B */ | ||
268 | div_ant_conf->alt_lna_conf = | ||
269 | antcomb->first_quick_scan_conf; | ||
270 | } else if (antcomb->second_ratio) { | ||
271 | /* second alt */ | ||
272 | if ((antcomb->second_quick_scan_conf == | ||
273 | ATH_ANT_DIV_COMB_LNA1) || | ||
274 | (antcomb->second_quick_scan_conf == | ||
275 | ATH_ANT_DIV_COMB_LNA2)) | ||
276 | /* Set alt LNA1 or LNA2 */ | ||
277 | if (div_ant_conf->main_lna_conf == | ||
278 | ATH_ANT_DIV_COMB_LNA2) | ||
279 | div_ant_conf->alt_lna_conf = | ||
280 | ATH_ANT_DIV_COMB_LNA1; | ||
281 | else | ||
282 | div_ant_conf->alt_lna_conf = | ||
283 | ATH_ANT_DIV_COMB_LNA2; | ||
284 | else | ||
285 | /* Set alt to A+B or A-B */ | ||
286 | div_ant_conf->alt_lna_conf = | ||
287 | antcomb->second_quick_scan_conf; | ||
288 | } else { | ||
289 | /* main is largest */ | ||
290 | if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
291 | (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
292 | /* Set alt LNA1 or LNA2 */ | ||
293 | if (div_ant_conf->main_lna_conf == | ||
294 | ATH_ANT_DIV_COMB_LNA2) | ||
295 | div_ant_conf->alt_lna_conf = | ||
296 | ATH_ANT_DIV_COMB_LNA1; | ||
297 | else | ||
298 | div_ant_conf->alt_lna_conf = | ||
299 | ATH_ANT_DIV_COMB_LNA2; | ||
300 | else | ||
301 | /* Set alt to A+B or A-B */ | ||
302 | div_ant_conf->alt_lna_conf = antcomb->main_conf; | ||
303 | } | ||
304 | break; | ||
305 | default: | ||
306 | break; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | ||
311 | struct ath_ant_comb *antcomb, | ||
312 | int alt_ratio) | ||
313 | { | ||
314 | if (ant_conf->div_group == 0) { | ||
315 | /* Adjust the fast_div_bias based on main and alt lna conf */ | ||
316 | switch ((ant_conf->main_lna_conf << 4) | | ||
317 | ant_conf->alt_lna_conf) { | ||
318 | case 0x01: /* A-B LNA2 */ | ||
319 | ant_conf->fast_div_bias = 0x3b; | ||
320 | break; | ||
321 | case 0x02: /* A-B LNA1 */ | ||
322 | ant_conf->fast_div_bias = 0x3d; | ||
323 | break; | ||
324 | case 0x03: /* A-B A+B */ | ||
325 | ant_conf->fast_div_bias = 0x1; | ||
326 | break; | ||
327 | case 0x10: /* LNA2 A-B */ | ||
328 | ant_conf->fast_div_bias = 0x7; | ||
329 | break; | ||
330 | case 0x12: /* LNA2 LNA1 */ | ||
331 | ant_conf->fast_div_bias = 0x2; | ||
332 | break; | ||
333 | case 0x13: /* LNA2 A+B */ | ||
334 | ant_conf->fast_div_bias = 0x7; | ||
335 | break; | ||
336 | case 0x20: /* LNA1 A-B */ | ||
337 | ant_conf->fast_div_bias = 0x6; | ||
338 | break; | ||
339 | case 0x21: /* LNA1 LNA2 */ | ||
340 | ant_conf->fast_div_bias = 0x0; | ||
341 | break; | ||
342 | case 0x23: /* LNA1 A+B */ | ||
343 | ant_conf->fast_div_bias = 0x6; | ||
344 | break; | ||
345 | case 0x30: /* A+B A-B */ | ||
346 | ant_conf->fast_div_bias = 0x1; | ||
347 | break; | ||
348 | case 0x31: /* A+B LNA2 */ | ||
349 | ant_conf->fast_div_bias = 0x3b; | ||
350 | break; | ||
351 | case 0x32: /* A+B LNA1 */ | ||
352 | ant_conf->fast_div_bias = 0x3d; | ||
353 | break; | ||
354 | default: | ||
355 | break; | ||
356 | } | ||
357 | } else if (ant_conf->div_group == 1) { | ||
358 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
359 | switch ((ant_conf->main_lna_conf << 4) | | ||
360 | ant_conf->alt_lna_conf) { | ||
361 | case 0x01: /* A-B LNA2 */ | ||
362 | ant_conf->fast_div_bias = 0x1; | ||
363 | ant_conf->main_gaintb = 0; | ||
364 | ant_conf->alt_gaintb = 0; | ||
365 | break; | ||
366 | case 0x02: /* A-B LNA1 */ | ||
367 | ant_conf->fast_div_bias = 0x1; | ||
368 | ant_conf->main_gaintb = 0; | ||
369 | ant_conf->alt_gaintb = 0; | ||
370 | break; | ||
371 | case 0x03: /* A-B A+B */ | ||
372 | ant_conf->fast_div_bias = 0x1; | ||
373 | ant_conf->main_gaintb = 0; | ||
374 | ant_conf->alt_gaintb = 0; | ||
375 | break; | ||
376 | case 0x10: /* LNA2 A-B */ | ||
377 | if (!(antcomb->scan) && | ||
378 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
379 | ant_conf->fast_div_bias = 0x3f; | ||
380 | else | ||
381 | ant_conf->fast_div_bias = 0x1; | ||
382 | ant_conf->main_gaintb = 0; | ||
383 | ant_conf->alt_gaintb = 0; | ||
384 | break; | ||
385 | case 0x12: /* LNA2 LNA1 */ | ||
386 | ant_conf->fast_div_bias = 0x1; | ||
387 | ant_conf->main_gaintb = 0; | ||
388 | ant_conf->alt_gaintb = 0; | ||
389 | break; | ||
390 | case 0x13: /* LNA2 A+B */ | ||
391 | if (!(antcomb->scan) && | ||
392 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
393 | ant_conf->fast_div_bias = 0x3f; | ||
394 | else | ||
395 | ant_conf->fast_div_bias = 0x1; | ||
396 | ant_conf->main_gaintb = 0; | ||
397 | ant_conf->alt_gaintb = 0; | ||
398 | break; | ||
399 | case 0x20: /* LNA1 A-B */ | ||
400 | if (!(antcomb->scan) && | ||
401 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
402 | ant_conf->fast_div_bias = 0x3f; | ||
403 | else | ||
404 | ant_conf->fast_div_bias = 0x1; | ||
405 | ant_conf->main_gaintb = 0; | ||
406 | ant_conf->alt_gaintb = 0; | ||
407 | break; | ||
408 | case 0x21: /* LNA1 LNA2 */ | ||
409 | ant_conf->fast_div_bias = 0x1; | ||
410 | ant_conf->main_gaintb = 0; | ||
411 | ant_conf->alt_gaintb = 0; | ||
412 | break; | ||
413 | case 0x23: /* LNA1 A+B */ | ||
414 | if (!(antcomb->scan) && | ||
415 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
416 | ant_conf->fast_div_bias = 0x3f; | ||
417 | else | ||
418 | ant_conf->fast_div_bias = 0x1; | ||
419 | ant_conf->main_gaintb = 0; | ||
420 | ant_conf->alt_gaintb = 0; | ||
421 | break; | ||
422 | case 0x30: /* A+B A-B */ | ||
423 | ant_conf->fast_div_bias = 0x1; | ||
424 | ant_conf->main_gaintb = 0; | ||
425 | ant_conf->alt_gaintb = 0; | ||
426 | break; | ||
427 | case 0x31: /* A+B LNA2 */ | ||
428 | ant_conf->fast_div_bias = 0x1; | ||
429 | ant_conf->main_gaintb = 0; | ||
430 | ant_conf->alt_gaintb = 0; | ||
431 | break; | ||
432 | case 0x32: /* A+B LNA1 */ | ||
433 | ant_conf->fast_div_bias = 0x1; | ||
434 | ant_conf->main_gaintb = 0; | ||
435 | ant_conf->alt_gaintb = 0; | ||
436 | break; | ||
437 | default: | ||
438 | break; | ||
439 | } | ||
440 | } else if (ant_conf->div_group == 2) { | ||
441 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
442 | switch ((ant_conf->main_lna_conf << 4) | | ||
443 | ant_conf->alt_lna_conf) { | ||
444 | case 0x01: /* A-B LNA2 */ | ||
445 | ant_conf->fast_div_bias = 0x1; | ||
446 | ant_conf->main_gaintb = 0; | ||
447 | ant_conf->alt_gaintb = 0; | ||
448 | break; | ||
449 | case 0x02: /* A-B LNA1 */ | ||
450 | ant_conf->fast_div_bias = 0x1; | ||
451 | ant_conf->main_gaintb = 0; | ||
452 | ant_conf->alt_gaintb = 0; | ||
453 | break; | ||
454 | case 0x03: /* A-B A+B */ | ||
455 | ant_conf->fast_div_bias = 0x1; | ||
456 | ant_conf->main_gaintb = 0; | ||
457 | ant_conf->alt_gaintb = 0; | ||
458 | break; | ||
459 | case 0x10: /* LNA2 A-B */ | ||
460 | if (!(antcomb->scan) && | ||
461 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
462 | ant_conf->fast_div_bias = 0x1; | ||
463 | else | ||
464 | ant_conf->fast_div_bias = 0x2; | ||
465 | ant_conf->main_gaintb = 0; | ||
466 | ant_conf->alt_gaintb = 0; | ||
467 | break; | ||
468 | case 0x12: /* LNA2 LNA1 */ | ||
469 | ant_conf->fast_div_bias = 0x1; | ||
470 | ant_conf->main_gaintb = 0; | ||
471 | ant_conf->alt_gaintb = 0; | ||
472 | break; | ||
473 | case 0x13: /* LNA2 A+B */ | ||
474 | if (!(antcomb->scan) && | ||
475 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
476 | ant_conf->fast_div_bias = 0x1; | ||
477 | else | ||
478 | ant_conf->fast_div_bias = 0x2; | ||
479 | ant_conf->main_gaintb = 0; | ||
480 | ant_conf->alt_gaintb = 0; | ||
481 | break; | ||
482 | case 0x20: /* LNA1 A-B */ | ||
483 | if (!(antcomb->scan) && | ||
484 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
485 | ant_conf->fast_div_bias = 0x1; | ||
486 | else | ||
487 | ant_conf->fast_div_bias = 0x2; | ||
488 | ant_conf->main_gaintb = 0; | ||
489 | ant_conf->alt_gaintb = 0; | ||
490 | break; | ||
491 | case 0x21: /* LNA1 LNA2 */ | ||
492 | ant_conf->fast_div_bias = 0x1; | ||
493 | ant_conf->main_gaintb = 0; | ||
494 | ant_conf->alt_gaintb = 0; | ||
495 | break; | ||
496 | case 0x23: /* LNA1 A+B */ | ||
497 | if (!(antcomb->scan) && | ||
498 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
499 | ant_conf->fast_div_bias = 0x1; | ||
500 | else | ||
501 | ant_conf->fast_div_bias = 0x2; | ||
502 | ant_conf->main_gaintb = 0; | ||
503 | ant_conf->alt_gaintb = 0; | ||
504 | break; | ||
505 | case 0x30: /* A+B A-B */ | ||
506 | ant_conf->fast_div_bias = 0x1; | ||
507 | ant_conf->main_gaintb = 0; | ||
508 | ant_conf->alt_gaintb = 0; | ||
509 | break; | ||
510 | case 0x31: /* A+B LNA2 */ | ||
511 | ant_conf->fast_div_bias = 0x1; | ||
512 | ant_conf->main_gaintb = 0; | ||
513 | ant_conf->alt_gaintb = 0; | ||
514 | break; | ||
515 | case 0x32: /* A+B LNA1 */ | ||
516 | ant_conf->fast_div_bias = 0x1; | ||
517 | ant_conf->main_gaintb = 0; | ||
518 | ant_conf->alt_gaintb = 0; | ||
519 | break; | ||
520 | default: | ||
521 | break; | ||
522 | } | ||
523 | } | ||
524 | } | ||
525 | |||
526 | void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | ||
527 | { | ||
528 | struct ath_hw_antcomb_conf div_ant_conf; | ||
529 | struct ath_ant_comb *antcomb = &sc->ant_comb; | ||
530 | int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; | ||
531 | int curr_main_set; | ||
532 | int main_rssi = rs->rs_rssi_ctl0; | ||
533 | int alt_rssi = rs->rs_rssi_ctl1; | ||
534 | int rx_ant_conf, main_ant_conf; | ||
535 | bool short_scan = false; | ||
536 | |||
537 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & | ||
538 | ATH_ANT_RX_MASK; | ||
539 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | ||
540 | ATH_ANT_RX_MASK; | ||
541 | |||
542 | /* Record packet only when both main_rssi and alt_rssi is positive */ | ||
543 | if (main_rssi > 0 && alt_rssi > 0) { | ||
544 | antcomb->total_pkt_count++; | ||
545 | antcomb->main_total_rssi += main_rssi; | ||
546 | antcomb->alt_total_rssi += alt_rssi; | ||
547 | if (main_ant_conf == rx_ant_conf) | ||
548 | antcomb->main_recv_cnt++; | ||
549 | else | ||
550 | antcomb->alt_recv_cnt++; | ||
551 | } | ||
552 | |||
553 | /* Short scan check */ | ||
554 | if (antcomb->scan && antcomb->alt_good) { | ||
555 | if (time_after(jiffies, antcomb->scan_start_time + | ||
556 | msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) | ||
557 | short_scan = true; | ||
558 | else | ||
559 | if (antcomb->total_pkt_count == | ||
560 | ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { | ||
561 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
562 | antcomb->total_pkt_count); | ||
563 | if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
564 | short_scan = true; | ||
565 | } | ||
566 | } | ||
567 | |||
568 | if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || | ||
569 | rs->rs_moreaggr) && !short_scan) | ||
570 | return; | ||
571 | |||
572 | if (antcomb->total_pkt_count) { | ||
573 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
574 | antcomb->total_pkt_count); | ||
575 | main_rssi_avg = (antcomb->main_total_rssi / | ||
576 | antcomb->total_pkt_count); | ||
577 | alt_rssi_avg = (antcomb->alt_total_rssi / | ||
578 | antcomb->total_pkt_count); | ||
579 | } | ||
580 | |||
581 | |||
582 | ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); | ||
583 | curr_alt_set = div_ant_conf.alt_lna_conf; | ||
584 | curr_main_set = div_ant_conf.main_lna_conf; | ||
585 | |||
586 | antcomb->count++; | ||
587 | |||
588 | if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { | ||
589 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | ||
590 | ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, | ||
591 | main_rssi_avg); | ||
592 | antcomb->alt_good = true; | ||
593 | } else { | ||
594 | antcomb->alt_good = false; | ||
595 | } | ||
596 | |||
597 | antcomb->count = 0; | ||
598 | antcomb->scan = true; | ||
599 | antcomb->scan_not_start = true; | ||
600 | } | ||
601 | |||
602 | if (!antcomb->scan) { | ||
603 | if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, | ||
604 | alt_ratio, curr_main_set, curr_alt_set, | ||
605 | alt_rssi_avg, main_rssi_avg)) { | ||
606 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | ||
607 | /* Switch main and alt LNA */ | ||
608 | div_ant_conf.main_lna_conf = | ||
609 | ATH_ANT_DIV_COMB_LNA2; | ||
610 | div_ant_conf.alt_lna_conf = | ||
611 | ATH_ANT_DIV_COMB_LNA1; | ||
612 | } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { | ||
613 | div_ant_conf.main_lna_conf = | ||
614 | ATH_ANT_DIV_COMB_LNA1; | ||
615 | div_ant_conf.alt_lna_conf = | ||
616 | ATH_ANT_DIV_COMB_LNA2; | ||
617 | } | ||
618 | |||
619 | goto div_comb_done; | ||
620 | } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && | ||
621 | (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { | ||
622 | /* Set alt to another LNA */ | ||
623 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) | ||
624 | div_ant_conf.alt_lna_conf = | ||
625 | ATH_ANT_DIV_COMB_LNA1; | ||
626 | else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) | ||
627 | div_ant_conf.alt_lna_conf = | ||
628 | ATH_ANT_DIV_COMB_LNA2; | ||
629 | |||
630 | goto div_comb_done; | ||
631 | } | ||
632 | |||
633 | if ((alt_rssi_avg < (main_rssi_avg + | ||
634 | div_ant_conf.lna1_lna2_delta))) | ||
635 | goto div_comb_done; | ||
636 | } | ||
637 | |||
638 | if (!antcomb->scan_not_start) { | ||
639 | switch (curr_alt_set) { | ||
640 | case ATH_ANT_DIV_COMB_LNA2: | ||
641 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
642 | antcomb->rssi_lna1 = main_rssi_avg; | ||
643 | antcomb->scan = true; | ||
644 | /* set to A+B */ | ||
645 | div_ant_conf.main_lna_conf = | ||
646 | ATH_ANT_DIV_COMB_LNA1; | ||
647 | div_ant_conf.alt_lna_conf = | ||
648 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
649 | break; | ||
650 | case ATH_ANT_DIV_COMB_LNA1: | ||
651 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
652 | antcomb->rssi_lna2 = main_rssi_avg; | ||
653 | antcomb->scan = true; | ||
654 | /* set to A+B */ | ||
655 | div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
656 | div_ant_conf.alt_lna_conf = | ||
657 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
658 | break; | ||
659 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: | ||
660 | antcomb->rssi_add = alt_rssi_avg; | ||
661 | antcomb->scan = true; | ||
662 | /* set to A-B */ | ||
663 | div_ant_conf.alt_lna_conf = | ||
664 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
665 | break; | ||
666 | case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: | ||
667 | antcomb->rssi_sub = alt_rssi_avg; | ||
668 | antcomb->scan = false; | ||
669 | if (antcomb->rssi_lna2 > | ||
670 | (antcomb->rssi_lna1 + | ||
671 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | ||
672 | /* use LNA2 as main LNA */ | ||
673 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | ||
674 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
675 | /* set to A+B */ | ||
676 | div_ant_conf.main_lna_conf = | ||
677 | ATH_ANT_DIV_COMB_LNA2; | ||
678 | div_ant_conf.alt_lna_conf = | ||
679 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
680 | } else if (antcomb->rssi_sub > | ||
681 | antcomb->rssi_lna1) { | ||
682 | /* set to A-B */ | ||
683 | div_ant_conf.main_lna_conf = | ||
684 | ATH_ANT_DIV_COMB_LNA2; | ||
685 | div_ant_conf.alt_lna_conf = | ||
686 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
687 | } else { | ||
688 | /* set to LNA1 */ | ||
689 | div_ant_conf.main_lna_conf = | ||
690 | ATH_ANT_DIV_COMB_LNA2; | ||
691 | div_ant_conf.alt_lna_conf = | ||
692 | ATH_ANT_DIV_COMB_LNA1; | ||
693 | } | ||
694 | } else { | ||
695 | /* use LNA1 as main LNA */ | ||
696 | if ((antcomb->rssi_add > antcomb->rssi_lna2) && | ||
697 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
698 | /* set to A+B */ | ||
699 | div_ant_conf.main_lna_conf = | ||
700 | ATH_ANT_DIV_COMB_LNA1; | ||
701 | div_ant_conf.alt_lna_conf = | ||
702 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
703 | } else if (antcomb->rssi_sub > | ||
704 | antcomb->rssi_lna1) { | ||
705 | /* set to A-B */ | ||
706 | div_ant_conf.main_lna_conf = | ||
707 | ATH_ANT_DIV_COMB_LNA1; | ||
708 | div_ant_conf.alt_lna_conf = | ||
709 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
710 | } else { | ||
711 | /* set to LNA2 */ | ||
712 | div_ant_conf.main_lna_conf = | ||
713 | ATH_ANT_DIV_COMB_LNA1; | ||
714 | div_ant_conf.alt_lna_conf = | ||
715 | ATH_ANT_DIV_COMB_LNA2; | ||
716 | } | ||
717 | } | ||
718 | break; | ||
719 | default: | ||
720 | break; | ||
721 | } | ||
722 | } else { | ||
723 | if (!antcomb->alt_good) { | ||
724 | antcomb->scan_not_start = false; | ||
725 | /* Set alt to another LNA */ | ||
726 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { | ||
727 | div_ant_conf.main_lna_conf = | ||
728 | ATH_ANT_DIV_COMB_LNA2; | ||
729 | div_ant_conf.alt_lna_conf = | ||
730 | ATH_ANT_DIV_COMB_LNA1; | ||
731 | } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { | ||
732 | div_ant_conf.main_lna_conf = | ||
733 | ATH_ANT_DIV_COMB_LNA1; | ||
734 | div_ant_conf.alt_lna_conf = | ||
735 | ATH_ANT_DIV_COMB_LNA2; | ||
736 | } | ||
737 | goto div_comb_done; | ||
738 | } | ||
739 | } | ||
740 | |||
741 | ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, | ||
742 | main_rssi_avg, alt_rssi_avg, | ||
743 | alt_ratio); | ||
744 | |||
745 | antcomb->quick_scan_cnt++; | ||
746 | |||
747 | div_comb_done: | ||
748 | ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); | ||
749 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | ||
750 | |||
751 | antcomb->scan_start_time = jiffies; | ||
752 | antcomb->total_pkt_count = 0; | ||
753 | antcomb->main_total_rssi = 0; | ||
754 | antcomb->alt_total_rssi = 0; | ||
755 | antcomb->main_recv_cnt = 0; | ||
756 | antcomb->alt_recv_cnt = 0; | ||
757 | } | ||
758 | |||
759 | void ath_ant_comb_update(struct ath_softc *sc) | ||
760 | { | ||
761 | struct ath_hw *ah = sc->sc_ah; | ||
762 | struct ath_hw_antcomb_conf div_ant_conf; | ||
763 | u8 lna_conf; | ||
764 | |||
765 | ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); | ||
766 | |||
767 | if (sc->ant_rx == 1) | ||
768 | lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
769 | else | ||
770 | lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
771 | |||
772 | div_ant_conf.main_lna_conf = lna_conf; | ||
773 | div_ant_conf.alt_lna_conf = lna_conf; | ||
774 | |||
775 | ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); | ||
776 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 2faa181d8fcf..4c2ce453af22 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -528,8 +528,10 @@ static inline void ath_deinit_leds(struct ath_softc *sc) | |||
528 | } | 528 | } |
529 | #endif | 529 | #endif |
530 | 530 | ||
531 | 531 | /*******************************/ | |
532 | /* Antenna diversity/combining */ | 532 | /* Antenna diversity/combining */ |
533 | /*******************************/ | ||
534 | |||
533 | #define ATH_ANT_RX_CURRENT_SHIFT 4 | 535 | #define ATH_ANT_RX_CURRENT_SHIFT 4 |
534 | #define ATH_ANT_RX_MAIN_SHIFT 2 | 536 | #define ATH_ANT_RX_MAIN_SHIFT 2 |
535 | #define ATH_ANT_RX_MASK 0x3 | 537 | #define ATH_ANT_RX_MASK 0x3 |
@@ -582,6 +584,9 @@ struct ath_ant_comb { | |||
582 | unsigned long scan_start_time; | 584 | unsigned long scan_start_time; |
583 | }; | 585 | }; |
584 | 586 | ||
587 | void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | ||
588 | void ath_ant_comb_update(struct ath_softc *sc); | ||
589 | |||
585 | /********************/ | 590 | /********************/ |
586 | /* Main driver core */ | 591 | /* Main driver core */ |
587 | /********************/ | 592 | /********************/ |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index b228aff481e1..66f215ca9969 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -228,21 +228,8 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
228 | ath_restart_work(sc); | 228 | ath_restart_work(sc); |
229 | } | 229 | } |
230 | 230 | ||
231 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) { | 231 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) |
232 | struct ath_hw_antcomb_conf div_ant_conf; | 232 | ath_ant_comb_update(sc); |
233 | u8 lna_conf; | ||
234 | |||
235 | ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); | ||
236 | |||
237 | if (sc->ant_rx == 1) | ||
238 | lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
239 | else | ||
240 | lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
241 | div_ant_conf.main_lna_conf = lna_conf; | ||
242 | div_ant_conf.alt_lna_conf = lna_conf; | ||
243 | |||
244 | ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); | ||
245 | } | ||
246 | 233 | ||
247 | ieee80211_wake_queues(sc->hw); | 234 | ieee80211_wake_queues(sc->hw); |
248 | 235 | ||
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 | ||
23 | static 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 | |||
32 | static 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 | |||
60 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 23 | static 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 | ||
1070 | static 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 | |||
1125 | static 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 | |||
1324 | static 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 */ | ||
1540 | static 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 | |||
1761 | div_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 | |||
1773 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1033 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
1774 | { | 1034 | { |
1775 | struct ath_buf *bf; | 1035 | struct ath_buf *bf; |