diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
37 files changed, 1926 insertions, 1182 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index d491a3178986..7944c25c9a43 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -56,7 +56,7 @@ config ATH9K_AHB | |||
56 | 56 | ||
57 | config ATH9K_DEBUGFS | 57 | config ATH9K_DEBUGFS |
58 | bool "Atheros ath9k debugging" | 58 | bool "Atheros ath9k debugging" |
59 | depends on ATH9K | 59 | depends on ATH9K && DEBUG_FS |
60 | select MAC80211_DEBUGFS | 60 | select MAC80211_DEBUGFS |
61 | select RELAY | 61 | select RELAY |
62 | ---help--- | 62 | ---help--- |
@@ -96,6 +96,16 @@ config ATH9K_LEGACY_RATE_CONTROL | |||
96 | has to be passed to mac80211 using the module parameter, | 96 | has to be passed to mac80211 using the module parameter, |
97 | ieee80211_default_rc_algo. | 97 | ieee80211_default_rc_algo. |
98 | 98 | ||
99 | config ATH9K_RFKILL | ||
100 | bool "Atheros ath9k rfkill support" if EXPERT | ||
101 | depends on ATH9K | ||
102 | depends on RFKILL=y || RFKILL=ATH9K | ||
103 | default y | ||
104 | help | ||
105 | Say Y to have ath9k poll the RF-Kill GPIO every couple of | ||
106 | seconds. Turn off to save power, but enable it if you have | ||
107 | a platform that can toggle the RF-Kill GPIO. | ||
108 | |||
99 | config ATH9K_HTC | 109 | config ATH9K_HTC |
100 | tristate "Atheros HTC based wireless cards support" | 110 | tristate "Atheros HTC based wireless cards support" |
101 | depends on USB && MAC80211 | 111 | depends on USB && MAC80211 |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 4994bea809eb..be466b0ef7a7 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -319,9 +319,6 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
319 | ah->ani_function = 0; | 319 | ah->ani_function = 0; |
320 | } | 320 | } |
321 | 321 | ||
322 | /* always allow mode (on/off) to be controlled */ | ||
323 | ah->ani_function |= ATH9K_ANI_MODE; | ||
324 | |||
325 | ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL, | 322 | ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL, |
326 | aniState->ofdmNoiseImmunityLevel); | 323 | aniState->ofdmNoiseImmunityLevel); |
327 | cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL, | 324 | cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL, |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index b54a3fb01883..21e7b83c3f6a 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -48,15 +48,10 @@ | |||
48 | /* values here are relative to the INI */ | 48 | /* values here are relative to the INI */ |
49 | 49 | ||
50 | enum ath9k_ani_cmd { | 50 | enum ath9k_ani_cmd { |
51 | ATH9K_ANI_PRESENT = 0x1, | 51 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x1, |
52 | ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, | 52 | ATH9K_ANI_FIRSTEP_LEVEL = 0x2, |
53 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4, | 53 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x4, |
54 | ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8, | 54 | ATH9K_ANI_MRC_CCK = 0x8, |
55 | ATH9K_ANI_FIRSTEP_LEVEL = 0x10, | ||
56 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, | ||
57 | ATH9K_ANI_MODE = 0x40, | ||
58 | ATH9K_ANI_PHYERR_RESET = 0x80, | ||
59 | ATH9K_ANI_MRC_CCK = 0x100, | ||
60 | ATH9K_ANI_ALL = 0xfff | 55 | ATH9K_ANI_ALL = 0xfff |
61 | }; | 56 | }; |
62 | 57 | ||
diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c index 664844c5d3d5..dd1cc73d7946 100644 --- a/drivers/net/wireless/ath/ath9k/antenna.c +++ b/drivers/net/wireless/ath/ath9k/antenna.c | |||
@@ -16,37 +16,119 @@ | |||
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "ath9k.h" |
18 | 18 | ||
19 | static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, | 19 | /* |
20 | * AR9285 | ||
21 | * ====== | ||
22 | * | ||
23 | * EEPROM has 2 4-bit fields containing the card configuration. | ||
24 | * | ||
25 | * antdiv_ctl1: | ||
26 | * ------------ | ||
27 | * bb_enable_ant_div_lnadiv : 1 | ||
28 | * bb_ant_div_alt_gaintb : 1 | ||
29 | * bb_ant_div_main_gaintb : 1 | ||
30 | * bb_enable_ant_fast_div : 1 | ||
31 | * | ||
32 | * antdiv_ctl2: | ||
33 | * ----------- | ||
34 | * bb_ant_div_alt_lnaconf : 2 | ||
35 | * bb_ant_div_main_lnaconf : 2 | ||
36 | * | ||
37 | * The EEPROM bits are used as follows: | ||
38 | * ------------------------------------ | ||
39 | * | ||
40 | * bb_enable_ant_div_lnadiv - Enable LNA path rx antenna diversity/combining. | ||
41 | * Set in AR_PHY_MULTICHAIN_GAIN_CTL. | ||
42 | * | ||
43 | * bb_ant_div_[alt/main]_gaintb - 0 -> Antenna config Alt/Main uses gaintable 0 | ||
44 | * 1 -> Antenna config Alt/Main uses gaintable 1 | ||
45 | * Set in AR_PHY_MULTICHAIN_GAIN_CTL. | ||
46 | * | ||
47 | * bb_enable_ant_fast_div - Enable fast antenna diversity. | ||
48 | * Set in AR_PHY_CCK_DETECT. | ||
49 | * | ||
50 | * bb_ant_div_[alt/main]_lnaconf - Alt/Main LNA diversity/combining input config. | ||
51 | * Set in AR_PHY_MULTICHAIN_GAIN_CTL. | ||
52 | * 10=LNA1 | ||
53 | * 01=LNA2 | ||
54 | * 11=LNA1+LNA2 | ||
55 | * 00=LNA1-LNA2 | ||
56 | * | ||
57 | * AR9485 / AR9565 / AR9331 | ||
58 | * ======================== | ||
59 | * | ||
60 | * The same bits are present in the EEPROM, but the location in the | ||
61 | * EEPROM is different (ant_div_control in ar9300_BaseExtension_1). | ||
62 | * | ||
63 | * ant_div_alt_lnaconf ==> bit 0~1 | ||
64 | * ant_div_main_lnaconf ==> bit 2~3 | ||
65 | * ant_div_alt_gaintb ==> bit 4 | ||
66 | * ant_div_main_gaintb ==> bit 5 | ||
67 | * enable_ant_div_lnadiv ==> bit 6 | ||
68 | * enable_ant_fast_div ==> bit 7 | ||
69 | */ | ||
70 | |||
71 | static inline bool ath_is_alt_ant_ratio_better(struct ath_ant_comb *antcomb, | ||
72 | int alt_ratio, int maxdelta, | ||
20 | int mindelta, int main_rssi_avg, | 73 | int mindelta, int main_rssi_avg, |
21 | int alt_rssi_avg, int pkt_count) | 74 | int alt_rssi_avg, int pkt_count) |
22 | { | 75 | { |
23 | return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | 76 | if (pkt_count <= 50) |
24 | (alt_rssi_avg > main_rssi_avg + maxdelta)) || | 77 | return false; |
25 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | 78 | |
79 | if (alt_rssi_avg > main_rssi_avg + mindelta) | ||
80 | return true; | ||
81 | |||
82 | if (alt_ratio >= antcomb->ant_ratio2 && | ||
83 | alt_rssi_avg >= antcomb->low_rssi_thresh && | ||
84 | (alt_rssi_avg > main_rssi_avg + maxdelta)) | ||
85 | return true; | ||
86 | |||
87 | return false; | ||
26 | } | 88 | } |
27 | 89 | ||
28 | static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, | 90 | static inline bool ath_ant_div_comb_alt_check(struct ath_hw_antcomb_conf *conf, |
29 | int curr_main_set, int curr_alt_set, | 91 | struct ath_ant_comb *antcomb, |
30 | int alt_rssi_avg, int main_rssi_avg) | 92 | int alt_ratio, int alt_rssi_avg, |
93 | int main_rssi_avg) | ||
31 | { | 94 | { |
32 | bool result = false; | 95 | bool result, set1, set2; |
33 | switch (div_group) { | 96 | |
97 | result = set1 = set2 = false; | ||
98 | |||
99 | if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2 && | ||
100 | conf->alt_lna_conf == ATH_ANT_DIV_COMB_LNA1) | ||
101 | set1 = true; | ||
102 | |||
103 | if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA1 && | ||
104 | conf->alt_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
105 | set2 = true; | ||
106 | |||
107 | switch (conf->div_group) { | ||
34 | case 0: | 108 | case 0: |
35 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | 109 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) |
36 | result = true; | 110 | result = true; |
37 | break; | 111 | break; |
38 | case 1: | 112 | case 1: |
39 | case 2: | 113 | case 2: |
40 | if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && | 114 | if (alt_rssi_avg < 4 || alt_rssi_avg < antcomb->low_rssi_thresh) |
41 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && | 115 | break; |
42 | (alt_rssi_avg >= (main_rssi_avg - 5))) || | 116 | |
43 | ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && | 117 | if ((set1 && (alt_rssi_avg >= (main_rssi_avg - 5))) || |
44 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && | 118 | (set2 && (alt_rssi_avg >= (main_rssi_avg - 2))) || |
45 | (alt_rssi_avg >= (main_rssi_avg - 2)))) && | 119 | (alt_ratio > antcomb->ant_ratio)) |
46 | (alt_rssi_avg >= 4)) | ||
47 | result = true; | 120 | result = true; |
48 | else | 121 | |
49 | result = false; | 122 | break; |
123 | case 3: | ||
124 | if (alt_rssi_avg < 4 || alt_rssi_avg < antcomb->low_rssi_thresh) | ||
125 | break; | ||
126 | |||
127 | if ((set1 && (alt_rssi_avg >= (main_rssi_avg - 3))) || | ||
128 | (set2 && (alt_rssi_avg >= (main_rssi_avg + 3))) || | ||
129 | (alt_ratio > antcomb->ant_ratio)) | ||
130 | result = true; | ||
131 | |||
50 | break; | 132 | break; |
51 | } | 133 | } |
52 | 134 | ||
@@ -108,6 +190,74 @@ static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, | |||
108 | } | 190 | } |
109 | } | 191 | } |
110 | 192 | ||
193 | static void ath_ant_set_alt_ratio(struct ath_ant_comb *antcomb, | ||
194 | struct ath_hw_antcomb_conf *conf) | ||
195 | { | ||
196 | /* set alt to the conf with maximun ratio */ | ||
197 | if (antcomb->first_ratio && antcomb->second_ratio) { | ||
198 | if (antcomb->rssi_second > antcomb->rssi_third) { | ||
199 | /* first alt*/ | ||
200 | if ((antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
201 | (antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
202 | /* Set alt LNA1 or LNA2*/ | ||
203 | if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
204 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
205 | else | ||
206 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
207 | else | ||
208 | /* Set alt to A+B or A-B */ | ||
209 | conf->alt_lna_conf = | ||
210 | antcomb->first_quick_scan_conf; | ||
211 | } else if ((antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
212 | (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2)) { | ||
213 | /* Set alt LNA1 or LNA2 */ | ||
214 | if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
215 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
216 | else | ||
217 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
218 | } else { | ||
219 | /* Set alt to A+B or A-B */ | ||
220 | conf->alt_lna_conf = antcomb->second_quick_scan_conf; | ||
221 | } | ||
222 | } else if (antcomb->first_ratio) { | ||
223 | /* first alt */ | ||
224 | if ((antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
225 | (antcomb->first_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
226 | /* Set alt LNA1 or LNA2 */ | ||
227 | if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
228 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
229 | else | ||
230 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
231 | else | ||
232 | /* Set alt to A+B or A-B */ | ||
233 | conf->alt_lna_conf = antcomb->first_quick_scan_conf; | ||
234 | } else if (antcomb->second_ratio) { | ||
235 | /* second alt */ | ||
236 | if ((antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
237 | (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
238 | /* Set alt LNA1 or LNA2 */ | ||
239 | if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
240 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
241 | else | ||
242 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
243 | else | ||
244 | /* Set alt to A+B or A-B */ | ||
245 | conf->alt_lna_conf = antcomb->second_quick_scan_conf; | ||
246 | } else { | ||
247 | /* main is largest */ | ||
248 | if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
249 | (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
250 | /* Set alt LNA1 or LNA2 */ | ||
251 | if (conf->main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
252 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
253 | else | ||
254 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
255 | else | ||
256 | /* Set alt to A+B or A-B */ | ||
257 | conf->alt_lna_conf = antcomb->main_conf; | ||
258 | } | ||
259 | } | ||
260 | |||
111 | static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | 261 | static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, |
112 | struct ath_hw_antcomb_conf *div_ant_conf, | 262 | struct ath_hw_antcomb_conf *div_ant_conf, |
113 | int main_rssi_avg, int alt_rssi_avg, | 263 | int main_rssi_avg, int alt_rssi_avg, |
@@ -129,7 +279,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
129 | 279 | ||
130 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | 280 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { |
131 | /* main is LNA1 */ | 281 | /* main is LNA1 */ |
132 | if (ath_is_alt_ant_ratio_better(alt_ratio, | 282 | if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio, |
133 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | 283 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, |
134 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | 284 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, |
135 | main_rssi_avg, alt_rssi_avg, | 285 | main_rssi_avg, alt_rssi_avg, |
@@ -138,7 +288,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
138 | else | 288 | else |
139 | antcomb->first_ratio = false; | 289 | antcomb->first_ratio = false; |
140 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | 290 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { |
141 | if (ath_is_alt_ant_ratio_better(alt_ratio, | 291 | if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio, |
142 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | 292 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, |
143 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | 293 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, |
144 | main_rssi_avg, alt_rssi_avg, | 294 | main_rssi_avg, alt_rssi_avg, |
@@ -147,11 +297,11 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
147 | else | 297 | else |
148 | antcomb->first_ratio = false; | 298 | antcomb->first_ratio = false; |
149 | } else { | 299 | } else { |
150 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | 300 | if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio, |
151 | (alt_rssi_avg > main_rssi_avg + | 301 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, |
152 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | 302 | 0, |
153 | (alt_rssi_avg > main_rssi_avg)) && | 303 | main_rssi_avg, alt_rssi_avg, |
154 | (antcomb->total_pkt_count > 50)) | 304 | antcomb->total_pkt_count)) |
155 | antcomb->first_ratio = true; | 305 | antcomb->first_ratio = true; |
156 | else | 306 | else |
157 | antcomb->first_ratio = false; | 307 | antcomb->first_ratio = false; |
@@ -164,17 +314,21 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
164 | antcomb->rssi_first = main_rssi_avg; | 314 | antcomb->rssi_first = main_rssi_avg; |
165 | antcomb->rssi_third = alt_rssi_avg; | 315 | antcomb->rssi_third = alt_rssi_avg; |
166 | 316 | ||
167 | if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) | 317 | switch(antcomb->second_quick_scan_conf) { |
318 | case ATH_ANT_DIV_COMB_LNA1: | ||
168 | antcomb->rssi_lna1 = alt_rssi_avg; | 319 | antcomb->rssi_lna1 = alt_rssi_avg; |
169 | else if (antcomb->second_quick_scan_conf == | 320 | break; |
170 | ATH_ANT_DIV_COMB_LNA2) | 321 | case ATH_ANT_DIV_COMB_LNA2: |
171 | antcomb->rssi_lna2 = alt_rssi_avg; | 322 | antcomb->rssi_lna2 = alt_rssi_avg; |
172 | else if (antcomb->second_quick_scan_conf == | 323 | break; |
173 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { | 324 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: |
174 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) | 325 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) |
175 | antcomb->rssi_lna2 = main_rssi_avg; | 326 | antcomb->rssi_lna2 = main_rssi_avg; |
176 | else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) | 327 | else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) |
177 | antcomb->rssi_lna1 = main_rssi_avg; | 328 | antcomb->rssi_lna1 = main_rssi_avg; |
329 | break; | ||
330 | default: | ||
331 | break; | ||
178 | } | 332 | } |
179 | 333 | ||
180 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + | 334 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + |
@@ -184,7 +338,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
184 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | 338 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; |
185 | 339 | ||
186 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | 340 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { |
187 | if (ath_is_alt_ant_ratio_better(alt_ratio, | 341 | if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio, |
188 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | 342 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, |
189 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | 343 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, |
190 | main_rssi_avg, alt_rssi_avg, | 344 | main_rssi_avg, alt_rssi_avg, |
@@ -193,7 +347,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
193 | else | 347 | else |
194 | antcomb->second_ratio = false; | 348 | antcomb->second_ratio = false; |
195 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | 349 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { |
196 | if (ath_is_alt_ant_ratio_better(alt_ratio, | 350 | if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio, |
197 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | 351 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, |
198 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | 352 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, |
199 | main_rssi_avg, alt_rssi_avg, | 353 | main_rssi_avg, alt_rssi_avg, |
@@ -202,105 +356,18 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
202 | else | 356 | else |
203 | antcomb->second_ratio = false; | 357 | antcomb->second_ratio = false; |
204 | } else { | 358 | } else { |
205 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | 359 | if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio, |
206 | (alt_rssi_avg > main_rssi_avg + | 360 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, |
207 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | 361 | 0, |
208 | (alt_rssi_avg > main_rssi_avg)) && | 362 | main_rssi_avg, alt_rssi_avg, |
209 | (antcomb->total_pkt_count > 50)) | 363 | antcomb->total_pkt_count)) |
210 | antcomb->second_ratio = true; | 364 | antcomb->second_ratio = true; |
211 | else | 365 | else |
212 | antcomb->second_ratio = false; | 366 | antcomb->second_ratio = false; |
213 | } | 367 | } |
214 | 368 | ||
215 | /* set alt to the conf with maximun ratio */ | 369 | ath_ant_set_alt_ratio(antcomb, div_ant_conf); |
216 | if (antcomb->first_ratio && antcomb->second_ratio) { | 370 | |
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; | 371 | break; |
305 | default: | 372 | default: |
306 | break; | 373 | break; |
@@ -430,8 +497,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
430 | ant_conf->fast_div_bias = 0x1; | 497 | ant_conf->fast_div_bias = 0x1; |
431 | break; | 498 | break; |
432 | case 0x10: /* LNA2 A-B */ | 499 | case 0x10: /* LNA2 A-B */ |
433 | if (!(antcomb->scan) && | 500 | if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio)) |
434 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
435 | ant_conf->fast_div_bias = 0x1; | 501 | ant_conf->fast_div_bias = 0x1; |
436 | else | 502 | else |
437 | ant_conf->fast_div_bias = 0x2; | 503 | ant_conf->fast_div_bias = 0x2; |
@@ -440,15 +506,13 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
440 | ant_conf->fast_div_bias = 0x1; | 506 | ant_conf->fast_div_bias = 0x1; |
441 | break; | 507 | break; |
442 | case 0x13: /* LNA2 A+B */ | 508 | case 0x13: /* LNA2 A+B */ |
443 | if (!(antcomb->scan) && | 509 | if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio)) |
444 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
445 | ant_conf->fast_div_bias = 0x1; | 510 | ant_conf->fast_div_bias = 0x1; |
446 | else | 511 | else |
447 | ant_conf->fast_div_bias = 0x2; | 512 | ant_conf->fast_div_bias = 0x2; |
448 | break; | 513 | break; |
449 | case 0x20: /* LNA1 A-B */ | 514 | case 0x20: /* LNA1 A-B */ |
450 | if (!(antcomb->scan) && | 515 | if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio)) |
451 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
452 | ant_conf->fast_div_bias = 0x1; | 516 | ant_conf->fast_div_bias = 0x1; |
453 | else | 517 | else |
454 | ant_conf->fast_div_bias = 0x2; | 518 | ant_conf->fast_div_bias = 0x2; |
@@ -457,8 +521,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
457 | ant_conf->fast_div_bias = 0x1; | 521 | ant_conf->fast_div_bias = 0x1; |
458 | break; | 522 | break; |
459 | case 0x23: /* LNA1 A+B */ | 523 | case 0x23: /* LNA1 A+B */ |
460 | if (!(antcomb->scan) && | 524 | if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio)) |
461 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
462 | ant_conf->fast_div_bias = 0x1; | 525 | ant_conf->fast_div_bias = 0x1; |
463 | else | 526 | else |
464 | ant_conf->fast_div_bias = 0x2; | 527 | ant_conf->fast_div_bias = 0x2; |
@@ -475,6 +538,9 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
475 | default: | 538 | default: |
476 | break; | 539 | break; |
477 | } | 540 | } |
541 | |||
542 | if (antcomb->fast_div_bias) | ||
543 | ant_conf->fast_div_bias = antcomb->fast_div_bias; | ||
478 | } else if (ant_conf->div_group == 3) { | 544 | } else if (ant_conf->div_group == 3) { |
479 | switch ((ant_conf->main_lna_conf << 4) | | 545 | switch ((ant_conf->main_lna_conf << 4) | |
480 | ant_conf->alt_lna_conf) { | 546 | ant_conf->alt_lna_conf) { |
@@ -540,6 +606,138 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
540 | } | 606 | } |
541 | } | 607 | } |
542 | 608 | ||
609 | static void ath_ant_try_scan(struct ath_ant_comb *antcomb, | ||
610 | struct ath_hw_antcomb_conf *conf, | ||
611 | int curr_alt_set, int alt_rssi_avg, | ||
612 | int main_rssi_avg) | ||
613 | { | ||
614 | switch (curr_alt_set) { | ||
615 | case ATH_ANT_DIV_COMB_LNA2: | ||
616 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
617 | antcomb->rssi_lna1 = main_rssi_avg; | ||
618 | antcomb->scan = true; | ||
619 | /* set to A+B */ | ||
620 | conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
621 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
622 | break; | ||
623 | case ATH_ANT_DIV_COMB_LNA1: | ||
624 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
625 | antcomb->rssi_lna2 = main_rssi_avg; | ||
626 | antcomb->scan = true; | ||
627 | /* set to A+B */ | ||
628 | conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
629 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
630 | break; | ||
631 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: | ||
632 | antcomb->rssi_add = alt_rssi_avg; | ||
633 | antcomb->scan = true; | ||
634 | /* set to A-B */ | ||
635 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
636 | break; | ||
637 | case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: | ||
638 | antcomb->rssi_sub = alt_rssi_avg; | ||
639 | antcomb->scan = false; | ||
640 | if (antcomb->rssi_lna2 > | ||
641 | (antcomb->rssi_lna1 + ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | ||
642 | /* use LNA2 as main LNA */ | ||
643 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | ||
644 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
645 | /* set to A+B */ | ||
646 | conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
647 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
648 | } else if (antcomb->rssi_sub > | ||
649 | antcomb->rssi_lna1) { | ||
650 | /* set to A-B */ | ||
651 | conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
652 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
653 | } else { | ||
654 | /* set to LNA1 */ | ||
655 | conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
656 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
657 | } | ||
658 | } else { | ||
659 | /* use LNA1 as main LNA */ | ||
660 | if ((antcomb->rssi_add > antcomb->rssi_lna2) && | ||
661 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
662 | /* set to A+B */ | ||
663 | conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
664 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
665 | } else if (antcomb->rssi_sub > | ||
666 | antcomb->rssi_lna1) { | ||
667 | /* set to A-B */ | ||
668 | conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
669 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
670 | } else { | ||
671 | /* set to LNA2 */ | ||
672 | conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
673 | conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
674 | } | ||
675 | } | ||
676 | break; | ||
677 | default: | ||
678 | break; | ||
679 | } | ||
680 | } | ||
681 | |||
682 | static bool ath_ant_try_switch(struct ath_hw_antcomb_conf *div_ant_conf, | ||
683 | struct ath_ant_comb *antcomb, | ||
684 | int alt_ratio, int alt_rssi_avg, | ||
685 | int main_rssi_avg, int curr_main_set, | ||
686 | int curr_alt_set) | ||
687 | { | ||
688 | bool ret = false; | ||
689 | |||
690 | if (ath_ant_div_comb_alt_check(div_ant_conf, antcomb, alt_ratio, | ||
691 | alt_rssi_avg, main_rssi_avg)) { | ||
692 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | ||
693 | /* | ||
694 | * Switch main and alt LNA. | ||
695 | */ | ||
696 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
697 | div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
698 | } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { | ||
699 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
700 | div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
701 | } | ||
702 | |||
703 | ret = true; | ||
704 | } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && | ||
705 | (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { | ||
706 | /* | ||
707 | Set alt to another LNA. | ||
708 | */ | ||
709 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) | ||
710 | div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
711 | else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) | ||
712 | div_ant_conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
713 | |||
714 | ret = true; | ||
715 | } | ||
716 | |||
717 | return ret; | ||
718 | } | ||
719 | |||
720 | static bool ath_ant_short_scan_check(struct ath_ant_comb *antcomb) | ||
721 | { | ||
722 | int alt_ratio; | ||
723 | |||
724 | if (!antcomb->scan || !antcomb->alt_good) | ||
725 | return false; | ||
726 | |||
727 | if (time_after(jiffies, antcomb->scan_start_time + | ||
728 | msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) | ||
729 | return true; | ||
730 | |||
731 | if (antcomb->total_pkt_count == ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { | ||
732 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
733 | antcomb->total_pkt_count); | ||
734 | if (alt_ratio < antcomb->ant_ratio) | ||
735 | return true; | ||
736 | } | ||
737 | |||
738 | return false; | ||
739 | } | ||
740 | |||
543 | void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | 741 | void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) |
544 | { | 742 | { |
545 | struct ath_hw_antcomb_conf div_ant_conf; | 743 | struct ath_hw_antcomb_conf div_ant_conf; |
@@ -549,41 +747,46 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
549 | int main_rssi = rs->rs_rssi_ctl0; | 747 | int main_rssi = rs->rs_rssi_ctl0; |
550 | int alt_rssi = rs->rs_rssi_ctl1; | 748 | int alt_rssi = rs->rs_rssi_ctl1; |
551 | int rx_ant_conf, main_ant_conf; | 749 | int rx_ant_conf, main_ant_conf; |
552 | bool short_scan = false; | 750 | bool short_scan = false, ret; |
553 | 751 | ||
554 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & | 752 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & |
555 | ATH_ANT_RX_MASK; | 753 | ATH_ANT_RX_MASK; |
556 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | 754 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & |
557 | ATH_ANT_RX_MASK; | 755 | ATH_ANT_RX_MASK; |
558 | 756 | ||
757 | if (alt_rssi >= antcomb->low_rssi_thresh) { | ||
758 | antcomb->ant_ratio = ATH_ANT_DIV_COMB_ALT_ANT_RATIO; | ||
759 | antcomb->ant_ratio2 = ATH_ANT_DIV_COMB_ALT_ANT_RATIO2; | ||
760 | } else { | ||
761 | antcomb->ant_ratio = ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI; | ||
762 | antcomb->ant_ratio2 = ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI; | ||
763 | } | ||
764 | |||
559 | /* Record packet only when both main_rssi and alt_rssi is positive */ | 765 | /* Record packet only when both main_rssi and alt_rssi is positive */ |
560 | if (main_rssi > 0 && alt_rssi > 0) { | 766 | if (main_rssi > 0 && alt_rssi > 0) { |
561 | antcomb->total_pkt_count++; | 767 | antcomb->total_pkt_count++; |
562 | antcomb->main_total_rssi += main_rssi; | 768 | antcomb->main_total_rssi += main_rssi; |
563 | antcomb->alt_total_rssi += alt_rssi; | 769 | antcomb->alt_total_rssi += alt_rssi; |
770 | |||
564 | if (main_ant_conf == rx_ant_conf) | 771 | if (main_ant_conf == rx_ant_conf) |
565 | antcomb->main_recv_cnt++; | 772 | antcomb->main_recv_cnt++; |
566 | else | 773 | else |
567 | antcomb->alt_recv_cnt++; | 774 | antcomb->alt_recv_cnt++; |
568 | } | 775 | } |
569 | 776 | ||
570 | /* Short scan check */ | 777 | if (main_ant_conf == rx_ant_conf) { |
571 | if (antcomb->scan && antcomb->alt_good) { | 778 | ANT_STAT_INC(ANT_MAIN, recv_cnt); |
572 | if (time_after(jiffies, antcomb->scan_start_time + | 779 | ANT_LNA_INC(ANT_MAIN, rx_ant_conf); |
573 | msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) | 780 | } else { |
574 | short_scan = true; | 781 | ANT_STAT_INC(ANT_ALT, recv_cnt); |
575 | else | 782 | ANT_LNA_INC(ANT_ALT, rx_ant_conf); |
576 | if (antcomb->total_pkt_count == | ||
577 | ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { | ||
578 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
579 | antcomb->total_pkt_count); | ||
580 | if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
581 | short_scan = true; | ||
582 | } | ||
583 | } | 783 | } |
584 | 784 | ||
785 | /* Short scan check */ | ||
786 | short_scan = ath_ant_short_scan_check(antcomb); | ||
787 | |||
585 | if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || | 788 | if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || |
586 | rs->rs_moreaggr) && !short_scan) | 789 | rs->rs_moreaggr) && !short_scan) |
587 | return; | 790 | return; |
588 | 791 | ||
589 | if (antcomb->total_pkt_count) { | 792 | if (antcomb->total_pkt_count) { |
@@ -595,15 +798,13 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
595 | antcomb->total_pkt_count); | 798 | antcomb->total_pkt_count); |
596 | } | 799 | } |
597 | 800 | ||
598 | |||
599 | ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); | 801 | ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); |
600 | curr_alt_set = div_ant_conf.alt_lna_conf; | 802 | curr_alt_set = div_ant_conf.alt_lna_conf; |
601 | curr_main_set = div_ant_conf.main_lna_conf; | 803 | curr_main_set = div_ant_conf.main_lna_conf; |
602 | |||
603 | antcomb->count++; | 804 | antcomb->count++; |
604 | 805 | ||
605 | if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { | 806 | if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { |
606 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | 807 | if (alt_ratio > antcomb->ant_ratio) { |
607 | ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, | 808 | ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, |
608 | main_rssi_avg); | 809 | main_rssi_avg); |
609 | antcomb->alt_good = true; | 810 | antcomb->alt_good = true; |
@@ -617,153 +818,47 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
617 | } | 818 | } |
618 | 819 | ||
619 | if (!antcomb->scan) { | 820 | if (!antcomb->scan) { |
620 | if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, | 821 | ret = ath_ant_try_switch(&div_ant_conf, antcomb, alt_ratio, |
621 | alt_ratio, curr_main_set, curr_alt_set, | 822 | alt_rssi_avg, main_rssi_avg, |
622 | alt_rssi_avg, main_rssi_avg)) { | 823 | curr_main_set, curr_alt_set); |
623 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | 824 | if (ret) |
624 | /* Switch main and alt LNA */ | ||
625 | div_ant_conf.main_lna_conf = | ||
626 | ATH_ANT_DIV_COMB_LNA2; | ||
627 | div_ant_conf.alt_lna_conf = | ||
628 | ATH_ANT_DIV_COMB_LNA1; | ||
629 | } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { | ||
630 | div_ant_conf.main_lna_conf = | ||
631 | ATH_ANT_DIV_COMB_LNA1; | ||
632 | div_ant_conf.alt_lna_conf = | ||
633 | ATH_ANT_DIV_COMB_LNA2; | ||
634 | } | ||
635 | |||
636 | goto div_comb_done; | ||
637 | } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && | ||
638 | (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { | ||
639 | /* Set alt to another LNA */ | ||
640 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) | ||
641 | div_ant_conf.alt_lna_conf = | ||
642 | ATH_ANT_DIV_COMB_LNA1; | ||
643 | else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) | ||
644 | div_ant_conf.alt_lna_conf = | ||
645 | ATH_ANT_DIV_COMB_LNA2; | ||
646 | |||
647 | goto div_comb_done; | ||
648 | } | ||
649 | |||
650 | if ((alt_rssi_avg < (main_rssi_avg + | ||
651 | div_ant_conf.lna1_lna2_delta))) | ||
652 | goto div_comb_done; | 825 | goto div_comb_done; |
653 | } | 826 | } |
654 | 827 | ||
828 | if (!antcomb->scan && | ||
829 | (alt_rssi_avg < (main_rssi_avg + div_ant_conf.lna1_lna2_delta))) | ||
830 | goto div_comb_done; | ||
831 | |||
655 | if (!antcomb->scan_not_start) { | 832 | if (!antcomb->scan_not_start) { |
656 | switch (curr_alt_set) { | 833 | ath_ant_try_scan(antcomb, &div_ant_conf, curr_alt_set, |
657 | case ATH_ANT_DIV_COMB_LNA2: | 834 | alt_rssi_avg, main_rssi_avg); |
658 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
659 | antcomb->rssi_lna1 = main_rssi_avg; | ||
660 | antcomb->scan = true; | ||
661 | /* set to A+B */ | ||
662 | div_ant_conf.main_lna_conf = | ||
663 | ATH_ANT_DIV_COMB_LNA1; | ||
664 | div_ant_conf.alt_lna_conf = | ||
665 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
666 | break; | ||
667 | case ATH_ANT_DIV_COMB_LNA1: | ||
668 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
669 | antcomb->rssi_lna2 = main_rssi_avg; | ||
670 | antcomb->scan = true; | ||
671 | /* set to A+B */ | ||
672 | div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
673 | div_ant_conf.alt_lna_conf = | ||
674 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
675 | break; | ||
676 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: | ||
677 | antcomb->rssi_add = alt_rssi_avg; | ||
678 | antcomb->scan = true; | ||
679 | /* set to A-B */ | ||
680 | div_ant_conf.alt_lna_conf = | ||
681 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
682 | break; | ||
683 | case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: | ||
684 | antcomb->rssi_sub = alt_rssi_avg; | ||
685 | antcomb->scan = false; | ||
686 | if (antcomb->rssi_lna2 > | ||
687 | (antcomb->rssi_lna1 + | ||
688 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | ||
689 | /* use LNA2 as main LNA */ | ||
690 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | ||
691 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
692 | /* set to A+B */ | ||
693 | div_ant_conf.main_lna_conf = | ||
694 | ATH_ANT_DIV_COMB_LNA2; | ||
695 | div_ant_conf.alt_lna_conf = | ||
696 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
697 | } else if (antcomb->rssi_sub > | ||
698 | antcomb->rssi_lna1) { | ||
699 | /* set to A-B */ | ||
700 | div_ant_conf.main_lna_conf = | ||
701 | ATH_ANT_DIV_COMB_LNA2; | ||
702 | div_ant_conf.alt_lna_conf = | ||
703 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
704 | } else { | ||
705 | /* set to LNA1 */ | ||
706 | div_ant_conf.main_lna_conf = | ||
707 | ATH_ANT_DIV_COMB_LNA2; | ||
708 | div_ant_conf.alt_lna_conf = | ||
709 | ATH_ANT_DIV_COMB_LNA1; | ||
710 | } | ||
711 | } else { | ||
712 | /* use LNA1 as main LNA */ | ||
713 | if ((antcomb->rssi_add > antcomb->rssi_lna2) && | ||
714 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
715 | /* set to A+B */ | ||
716 | div_ant_conf.main_lna_conf = | ||
717 | ATH_ANT_DIV_COMB_LNA1; | ||
718 | div_ant_conf.alt_lna_conf = | ||
719 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
720 | } else if (antcomb->rssi_sub > | ||
721 | antcomb->rssi_lna1) { | ||
722 | /* set to A-B */ | ||
723 | div_ant_conf.main_lna_conf = | ||
724 | ATH_ANT_DIV_COMB_LNA1; | ||
725 | div_ant_conf.alt_lna_conf = | ||
726 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
727 | } else { | ||
728 | /* set to LNA2 */ | ||
729 | div_ant_conf.main_lna_conf = | ||
730 | ATH_ANT_DIV_COMB_LNA1; | ||
731 | div_ant_conf.alt_lna_conf = | ||
732 | ATH_ANT_DIV_COMB_LNA2; | ||
733 | } | ||
734 | } | ||
735 | break; | ||
736 | default: | ||
737 | break; | ||
738 | } | ||
739 | } else { | 835 | } else { |
740 | if (!antcomb->alt_good) { | 836 | if (!antcomb->alt_good) { |
741 | antcomb->scan_not_start = false; | 837 | antcomb->scan_not_start = false; |
742 | /* Set alt to another LNA */ | 838 | /* Set alt to another LNA */ |
743 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { | 839 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { |
744 | div_ant_conf.main_lna_conf = | 840 | div_ant_conf.main_lna_conf = |
745 | ATH_ANT_DIV_COMB_LNA2; | 841 | ATH_ANT_DIV_COMB_LNA2; |
746 | div_ant_conf.alt_lna_conf = | 842 | div_ant_conf.alt_lna_conf = |
747 | ATH_ANT_DIV_COMB_LNA1; | 843 | ATH_ANT_DIV_COMB_LNA1; |
748 | } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { | 844 | } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { |
749 | div_ant_conf.main_lna_conf = | 845 | div_ant_conf.main_lna_conf = |
750 | ATH_ANT_DIV_COMB_LNA1; | 846 | ATH_ANT_DIV_COMB_LNA1; |
751 | div_ant_conf.alt_lna_conf = | 847 | div_ant_conf.alt_lna_conf = |
752 | ATH_ANT_DIV_COMB_LNA2; | 848 | ATH_ANT_DIV_COMB_LNA2; |
753 | } | 849 | } |
754 | goto div_comb_done; | 850 | goto div_comb_done; |
755 | } | 851 | } |
852 | ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, | ||
853 | main_rssi_avg, alt_rssi_avg, | ||
854 | alt_ratio); | ||
855 | antcomb->quick_scan_cnt++; | ||
756 | } | 856 | } |
757 | 857 | ||
758 | ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, | ||
759 | main_rssi_avg, alt_rssi_avg, | ||
760 | alt_ratio); | ||
761 | |||
762 | antcomb->quick_scan_cnt++; | ||
763 | |||
764 | div_comb_done: | 858 | div_comb_done: |
765 | ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); | 859 | ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); |
766 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | 860 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); |
861 | ath9k_debug_stat_ant(sc, &div_ant_conf, main_rssi_avg, alt_rssi_avg); | ||
767 | 862 | ||
768 | antcomb->scan_start_time = jiffies; | 863 | antcomb->scan_start_time = jiffies; |
769 | antcomb->total_pkt_count = 0; | 864 | antcomb->total_pkt_count = 0; |
@@ -772,26 +867,3 @@ div_comb_done: | |||
772 | antcomb->main_recv_cnt = 0; | 867 | antcomb->main_recv_cnt = 0; |
773 | antcomb->alt_recv_cnt = 0; | 868 | antcomb->alt_recv_cnt = 0; |
774 | } | 869 | } |
775 | |||
776 | void ath_ant_comb_update(struct ath_softc *sc) | ||
777 | { | ||
778 | struct ath_hw *ah = sc->sc_ah; | ||
779 | struct ath_common *common = ath9k_hw_common(ah); | ||
780 | struct ath_hw_antcomb_conf div_ant_conf; | ||
781 | u8 lna_conf; | ||
782 | |||
783 | ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); | ||
784 | |||
785 | if (sc->ant_rx == 1) | ||
786 | lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
787 | else | ||
788 | lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
789 | |||
790 | div_ant_conf.main_lna_conf = lna_conf; | ||
791 | div_ant_conf.alt_lna_conf = lna_conf; | ||
792 | |||
793 | ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); | ||
794 | |||
795 | if (common->antenna_diversity) | ||
796 | ath9k_hw_antctrl_shared_chain_lnadiv(ah, true); | ||
797 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 1576d58291d4..08656473c63e 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -1160,8 +1160,6 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1160 | */ | 1160 | */ |
1161 | WARN_ON(1); | 1161 | WARN_ON(1); |
1162 | break; | 1162 | break; |
1163 | case ATH9K_ANI_PRESENT: | ||
1164 | break; | ||
1165 | default: | 1163 | default: |
1166 | ath_dbg(common, ANI, "invalid cmd %u\n", cmd); | 1164 | ath_dbg(common, ANI, "invalid cmd %u\n", cmd); |
1167 | return false; | 1165 | return false; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 8dc2d089cdef..fb61b081d172 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -269,13 +269,12 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |||
269 | if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) | 269 | if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) |
270 | val |= AR_WA_D3_L1_DISABLE; | 270 | val |= AR_WA_D3_L1_DISABLE; |
271 | } else { | 271 | } else { |
272 | if (((AR_SREV_9285(ah) || | 272 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) { |
273 | AR_SREV_9271(ah) || | 273 | if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE) |
274 | AR_SREV_9287(ah)) && | 274 | val |= AR_WA_D3_L1_DISABLE; |
275 | (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || | 275 | } else if (AR_SREV_9280(ah)) { |
276 | (AR_SREV_9280(ah) && | 276 | if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE) |
277 | (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { | 277 | val |= AR_WA_D3_L1_DISABLE; |
278 | val |= AR_WA_D3_L1_DISABLE; | ||
279 | } | 278 | } |
280 | } | 279 | } |
281 | 280 | ||
@@ -297,24 +296,18 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |||
297 | } else { | 296 | } else { |
298 | if (ah->config.pcie_waen) { | 297 | if (ah->config.pcie_waen) { |
299 | val = ah->config.pcie_waen; | 298 | val = ah->config.pcie_waen; |
300 | if (!power_off) | 299 | val &= (~AR_WA_D3_L1_DISABLE); |
301 | val &= (~AR_WA_D3_L1_DISABLE); | ||
302 | } else { | 300 | } else { |
303 | if (AR_SREV_9285(ah) || | 301 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) { |
304 | AR_SREV_9271(ah) || | ||
305 | AR_SREV_9287(ah)) { | ||
306 | val = AR9285_WA_DEFAULT; | 302 | val = AR9285_WA_DEFAULT; |
307 | if (!power_off) | 303 | val &= (~AR_WA_D3_L1_DISABLE); |
308 | val &= (~AR_WA_D3_L1_DISABLE); | 304 | } else if (AR_SREV_9280(ah)) { |
309 | } | ||
310 | else if (AR_SREV_9280(ah)) { | ||
311 | /* | 305 | /* |
312 | * For AR9280 chips, bit 22 of 0x4004 | 306 | * For AR9280 chips, bit 22 of 0x4004 |
313 | * needs to be set. | 307 | * needs to be set. |
314 | */ | 308 | */ |
315 | val = AR9280_WA_DEFAULT; | 309 | val = AR9280_WA_DEFAULT; |
316 | if (!power_off) | 310 | val &= (~AR_WA_D3_L1_DISABLE); |
317 | val &= (~AR_WA_D3_L1_DISABLE); | ||
318 | } else { | 311 | } else { |
319 | val = AR_WA_DEFAULT; | 312 | val = AR_WA_DEFAULT; |
320 | } | 313 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index f4003512d8d5..1fc1fa955d44 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -555,6 +555,69 @@ static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah, | |||
555 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); | 555 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); |
556 | } | 556 | } |
557 | 557 | ||
558 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | ||
559 | |||
560 | static void ar9002_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) | ||
561 | { | ||
562 | struct ath_btcoex_hw *btcoex = &ah->btcoex_hw; | ||
563 | u8 antdiv_ctrl1, antdiv_ctrl2; | ||
564 | u32 regval; | ||
565 | |||
566 | if (enable) { | ||
567 | antdiv_ctrl1 = ATH_BT_COEX_ANTDIV_CONTROL1_ENABLE; | ||
568 | antdiv_ctrl2 = ATH_BT_COEX_ANTDIV_CONTROL2_ENABLE; | ||
569 | |||
570 | /* | ||
571 | * Don't disable BT ant to allow BB to control SWCOM. | ||
572 | */ | ||
573 | btcoex->bt_coex_mode2 &= (~(AR_BT_DISABLE_BT_ANT)); | ||
574 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2); | ||
575 | |||
576 | REG_WRITE(ah, AR_PHY_SWITCH_COM, ATH_BT_COEX_ANT_DIV_SWITCH_COM); | ||
577 | REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); | ||
578 | } else { | ||
579 | /* | ||
580 | * Disable antenna diversity, use LNA1 only. | ||
581 | */ | ||
582 | antdiv_ctrl1 = ATH_BT_COEX_ANTDIV_CONTROL1_FIXED_A; | ||
583 | antdiv_ctrl2 = ATH_BT_COEX_ANTDIV_CONTROL2_FIXED_A; | ||
584 | |||
585 | /* | ||
586 | * Disable BT Ant. to allow concurrent BT and WLAN receive. | ||
587 | */ | ||
588 | btcoex->bt_coex_mode2 |= AR_BT_DISABLE_BT_ANT; | ||
589 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2); | ||
590 | |||
591 | /* | ||
592 | * Program SWCOM table to make sure RF switch always parks | ||
593 | * at BT side. | ||
594 | */ | ||
595 | REG_WRITE(ah, AR_PHY_SWITCH_COM, 0); | ||
596 | REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); | ||
597 | } | ||
598 | |||
599 | regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
600 | regval &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); | ||
601 | /* | ||
602 | * Clear ant_fast_div_bias [14:9] since for WB195, | ||
603 | * the main LNA is always LNA1. | ||
604 | */ | ||
605 | regval &= (~(AR_PHY_9285_FAST_DIV_BIAS)); | ||
606 | regval |= SM(antdiv_ctrl1, AR_PHY_9285_ANT_DIV_CTL); | ||
607 | regval |= SM(antdiv_ctrl2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); | ||
608 | regval |= SM((antdiv_ctrl2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF); | ||
609 | regval |= SM((antdiv_ctrl1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB); | ||
610 | regval |= SM((antdiv_ctrl1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB); | ||
611 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); | ||
612 | |||
613 | regval = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
614 | regval &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); | ||
615 | regval |= SM((antdiv_ctrl1 >> 3), AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); | ||
616 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); | ||
617 | } | ||
618 | |||
619 | #endif | ||
620 | |||
558 | static void ar9002_hw_spectral_scan_config(struct ath_hw *ah, | 621 | static void ar9002_hw_spectral_scan_config(struct ath_hw *ah, |
559 | struct ath_spec_scan *param) | 622 | struct ath_spec_scan *param) |
560 | { | 623 | { |
@@ -634,5 +697,9 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | |||
634 | ops->spectral_scan_trigger = ar9002_hw_spectral_scan_trigger; | 697 | ops->spectral_scan_trigger = ar9002_hw_spectral_scan_trigger; |
635 | ops->spectral_scan_wait = ar9002_hw_spectral_scan_wait; | 698 | ops->spectral_scan_wait = ar9002_hw_spectral_scan_wait; |
636 | 699 | ||
700 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | ||
701 | ops->set_bt_ant_diversity = ar9002_hw_set_bt_ant_diversity; | ||
702 | #endif | ||
703 | |||
637 | ar9002_hw_set_nf_limits(ah); | 704 | ar9002_hw_set_nf_limits(ah); |
638 | } | 705 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index f9eb2c357169..6314ae2e93e3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h | |||
@@ -317,13 +317,15 @@ | |||
317 | #define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 | 317 | #define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 |
318 | #define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 | 318 | #define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 |
319 | #define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 | 319 | #define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 |
320 | #define AR_PHY_9285_ANT_DIV_LNA1 2 | ||
321 | #define AR_PHY_9285_ANT_DIV_LNA2 1 | ||
322 | #define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3 | ||
323 | #define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 | ||
324 | #define AR_PHY_9285_ANT_DIV_GAINTB_0 0 | 320 | #define AR_PHY_9285_ANT_DIV_GAINTB_0 0 |
325 | #define AR_PHY_9285_ANT_DIV_GAINTB_1 1 | 321 | #define AR_PHY_9285_ANT_DIV_GAINTB_1 1 |
326 | 322 | ||
323 | #define ATH_BT_COEX_ANTDIV_CONTROL1_ENABLE 0x0b | ||
324 | #define ATH_BT_COEX_ANTDIV_CONTROL2_ENABLE 0x09 | ||
325 | #define ATH_BT_COEX_ANTDIV_CONTROL1_FIXED_A 0x04 | ||
326 | #define ATH_BT_COEX_ANTDIV_CONTROL2_FIXED_A 0x09 | ||
327 | #define ATH_BT_COEX_ANT_DIV_SWITCH_COM 0x66666666 | ||
328 | |||
327 | #define AR_PHY_EXT_CCA0 0x99b8 | 329 | #define AR_PHY_EXT_CCA0 0x99b8 |
328 | #define AR_PHY_EXT_CCA0_THRESH62 0x000000FF | 330 | #define AR_PHY_EXT_CCA0_THRESH62 0x000000FF |
329 | #define AR_PHY_EXT_CCA0_THRESH62_S 0 | 331 | #define AR_PHY_EXT_CCA0_THRESH62_S 0 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index d105e43d22e1..f4864807e15b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -3541,13 +3541,12 @@ static u16 ar9003_switch_com_spdt_get(struct ath_hw *ah, bool is2ghz) | |||
3541 | return le16_to_cpu(ar9003_modal_header(ah, is2ghz)->switchcomspdt); | 3541 | return le16_to_cpu(ar9003_modal_header(ah, is2ghz)->switchcomspdt); |
3542 | } | 3542 | } |
3543 | 3543 | ||
3544 | 3544 | u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) | |
3545 | static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) | ||
3546 | { | 3545 | { |
3547 | return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->antCtrlCommon); | 3546 | return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->antCtrlCommon); |
3548 | } | 3547 | } |
3549 | 3548 | ||
3550 | static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz) | 3549 | u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz) |
3551 | { | 3550 | { |
3552 | return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->antCtrlCommon2); | 3551 | return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->antCtrlCommon2); |
3553 | } | 3552 | } |
@@ -3561,6 +3560,7 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, int chain, | |||
3561 | 3560 | ||
3562 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | 3561 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) |
3563 | { | 3562 | { |
3563 | struct ath_common *common = ath9k_hw_common(ah); | ||
3564 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 3564 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
3565 | int chain; | 3565 | int chain; |
3566 | u32 regval, value, gpio; | 3566 | u32 regval, value, gpio; |
@@ -3614,6 +3614,11 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3614 | } | 3614 | } |
3615 | 3615 | ||
3616 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); | 3616 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); |
3617 | if (AR_SREV_9485(ah) && common->bt_ant_diversity) { | ||
3618 | value &= ~AR_SWITCH_TABLE_COM2_ALL; | ||
3619 | value |= ah->config.ant_ctrl_comm2g_switch_enable; | ||
3620 | |||
3621 | } | ||
3617 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); | 3622 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); |
3618 | 3623 | ||
3619 | if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { | 3624 | if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { |
@@ -3645,8 +3650,11 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3645 | regval &= (~AR_PHY_ANT_DIV_LNADIV); | 3650 | regval &= (~AR_PHY_ANT_DIV_LNADIV); |
3646 | regval |= ((value >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S; | 3651 | regval |= ((value >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S; |
3647 | 3652 | ||
3653 | if (AR_SREV_9485(ah) && common->bt_ant_diversity) | ||
3654 | regval |= AR_ANT_DIV_ENABLE; | ||
3655 | |||
3648 | if (AR_SREV_9565(ah)) { | 3656 | if (AR_SREV_9565(ah)) { |
3649 | if (ah->shared_chain_lnadiv) { | 3657 | if (common->bt_ant_diversity) { |
3650 | regval |= (1 << AR_PHY_ANT_SW_RX_PROT_S); | 3658 | regval |= (1 << AR_PHY_ANT_SW_RX_PROT_S); |
3651 | } else { | 3659 | } else { |
3652 | regval &= ~(1 << AR_PHY_ANT_DIV_LNADIV_S); | 3660 | regval &= ~(1 << AR_PHY_ANT_DIV_LNADIV_S); |
@@ -3656,10 +3664,14 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3656 | 3664 | ||
3657 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | 3665 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); |
3658 | 3666 | ||
3659 | /*enable fast_div */ | 3667 | /* enable fast_div */ |
3660 | regval = REG_READ(ah, AR_PHY_CCK_DETECT); | 3668 | regval = REG_READ(ah, AR_PHY_CCK_DETECT); |
3661 | regval &= (~AR_FAST_DIV_ENABLE); | 3669 | regval &= (~AR_FAST_DIV_ENABLE); |
3662 | regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; | 3670 | regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; |
3671 | |||
3672 | if (AR_SREV_9485(ah) && common->bt_ant_diversity) | ||
3673 | regval |= AR_FAST_DIV_ENABLE; | ||
3674 | |||
3663 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); | 3675 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); |
3664 | 3676 | ||
3665 | if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) { | 3677 | if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) { |
@@ -3673,9 +3685,9 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3673 | AR_PHY_ANT_DIV_ALT_GAINTB | | 3685 | AR_PHY_ANT_DIV_ALT_GAINTB | |
3674 | AR_PHY_ANT_DIV_MAIN_GAINTB)); | 3686 | AR_PHY_ANT_DIV_MAIN_GAINTB)); |
3675 | /* by default use LNA1 for the main antenna */ | 3687 | /* by default use LNA1 for the main antenna */ |
3676 | regval |= (AR_PHY_ANT_DIV_LNA1 << | 3688 | regval |= (ATH_ANT_DIV_COMB_LNA1 << |
3677 | AR_PHY_ANT_DIV_MAIN_LNACONF_S); | 3689 | AR_PHY_ANT_DIV_MAIN_LNACONF_S); |
3678 | regval |= (AR_PHY_ANT_DIV_LNA2 << | 3690 | regval |= (ATH_ANT_DIV_COMB_LNA2 << |
3679 | AR_PHY_ANT_DIV_ALT_LNACONF_S); | 3691 | AR_PHY_ANT_DIV_ALT_LNACONF_S); |
3680 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | 3692 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); |
3681 | } | 3693 | } |
@@ -3813,6 +3825,11 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) | |||
3813 | else | 3825 | else |
3814 | value = ar9003_hw_atten_chain_get_margin(ah, i, chan); | 3826 | value = ar9003_hw_atten_chain_get_margin(ah, i, chan); |
3815 | 3827 | ||
3828 | if (ah->config.alt_mingainidx) | ||
3829 | REG_RMW_FIELD(ah, AR_PHY_EXT_ATTEN_CTL_0, | ||
3830 | AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, | ||
3831 | value); | ||
3832 | |||
3816 | REG_RMW_FIELD(ah, ext_atten_reg[i], | 3833 | REG_RMW_FIELD(ah, ext_atten_reg[i], |
3817 | AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, | 3834 | AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, |
3818 | value); | 3835 | value); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 874f6570bd1c..75d4fb41962f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | |||
@@ -334,6 +334,8 @@ struct ar9300_eeprom { | |||
334 | 334 | ||
335 | s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah); | 335 | s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah); |
336 | s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah); | 336 | s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah); |
337 | u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz); | ||
338 | u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz); | ||
337 | 339 | ||
338 | u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz); | 340 | u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz); |
339 | 341 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index d402cb32283f..608bb4824e2a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -153,7 +153,7 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
153 | if (!ah->is_clk_25mhz) | 153 | if (!ah->is_clk_25mhz) |
154 | INIT_INI_ARRAY(&ah->iniAdditional, | 154 | INIT_INI_ARRAY(&ah->iniAdditional, |
155 | ar9340_1p0_radio_core_40M); | 155 | ar9340_1p0_radio_core_40M); |
156 | } else if (AR_SREV_9485_11(ah)) { | 156 | } else if (AR_SREV_9485_11_OR_LATER(ah)) { |
157 | /* mac */ | 157 | /* mac */ |
158 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | 158 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], |
159 | ar9485_1_1_mac_core); | 159 | ar9485_1_1_mac_core); |
@@ -424,7 +424,7 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) | |||
424 | else if (AR_SREV_9340(ah)) | 424 | else if (AR_SREV_9340(ah)) |
425 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 425 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
426 | ar9340Modes_lowest_ob_db_tx_gain_table_1p0); | 426 | ar9340Modes_lowest_ob_db_tx_gain_table_1p0); |
427 | else if (AR_SREV_9485_11(ah)) | 427 | else if (AR_SREV_9485_11_OR_LATER(ah)) |
428 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 428 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
429 | ar9485_modes_lowest_ob_db_tx_gain_1_1); | 429 | ar9485_modes_lowest_ob_db_tx_gain_1_1); |
430 | else if (AR_SREV_9550(ah)) | 430 | else if (AR_SREV_9550(ah)) |
@@ -458,7 +458,7 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) | |||
458 | else if (AR_SREV_9340(ah)) | 458 | else if (AR_SREV_9340(ah)) |
459 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 459 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
460 | ar9340Modes_high_ob_db_tx_gain_table_1p0); | 460 | ar9340Modes_high_ob_db_tx_gain_table_1p0); |
461 | else if (AR_SREV_9485_11(ah)) | 461 | else if (AR_SREV_9485_11_OR_LATER(ah)) |
462 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 462 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
463 | ar9485Modes_high_ob_db_tx_gain_1_1); | 463 | ar9485Modes_high_ob_db_tx_gain_1_1); |
464 | else if (AR_SREV_9580(ah)) | 464 | else if (AR_SREV_9580(ah)) |
@@ -492,7 +492,7 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah) | |||
492 | else if (AR_SREV_9340(ah)) | 492 | else if (AR_SREV_9340(ah)) |
493 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 493 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
494 | ar9340Modes_low_ob_db_tx_gain_table_1p0); | 494 | ar9340Modes_low_ob_db_tx_gain_table_1p0); |
495 | else if (AR_SREV_9485_11(ah)) | 495 | else if (AR_SREV_9485_11_OR_LATER(ah)) |
496 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 496 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
497 | ar9485Modes_low_ob_db_tx_gain_1_1); | 497 | ar9485Modes_low_ob_db_tx_gain_1_1); |
498 | else if (AR_SREV_9580(ah)) | 498 | else if (AR_SREV_9580(ah)) |
@@ -517,7 +517,7 @@ static void ar9003_tx_gain_table_mode3(struct ath_hw *ah) | |||
517 | else if (AR_SREV_9340(ah)) | 517 | else if (AR_SREV_9340(ah)) |
518 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 518 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
519 | ar9340Modes_high_power_tx_gain_table_1p0); | 519 | ar9340Modes_high_power_tx_gain_table_1p0); |
520 | else if (AR_SREV_9485_11(ah)) | 520 | else if (AR_SREV_9485_11_OR_LATER(ah)) |
521 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 521 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
522 | ar9485Modes_high_power_tx_gain_1_1); | 522 | ar9485Modes_high_power_tx_gain_1_1); |
523 | else if (AR_SREV_9580(ah)) | 523 | else if (AR_SREV_9580(ah)) |
@@ -552,7 +552,7 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah) | |||
552 | 552 | ||
553 | static void ar9003_tx_gain_table_mode5(struct ath_hw *ah) | 553 | static void ar9003_tx_gain_table_mode5(struct ath_hw *ah) |
554 | { | 554 | { |
555 | if (AR_SREV_9485_11(ah)) | 555 | if (AR_SREV_9485_11_OR_LATER(ah)) |
556 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 556 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
557 | ar9485Modes_green_ob_db_tx_gain_1_1); | 557 | ar9485Modes_green_ob_db_tx_gain_1_1); |
558 | else if (AR_SREV_9340(ah)) | 558 | else if (AR_SREV_9340(ah)) |
@@ -571,7 +571,7 @@ static void ar9003_tx_gain_table_mode6(struct ath_hw *ah) | |||
571 | if (AR_SREV_9340(ah)) | 571 | if (AR_SREV_9340(ah)) |
572 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 572 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
573 | ar9340Modes_low_ob_db_and_spur_tx_gain_table_1p0); | 573 | ar9340Modes_low_ob_db_and_spur_tx_gain_table_1p0); |
574 | else if (AR_SREV_9485_11(ah)) | 574 | else if (AR_SREV_9485_11_OR_LATER(ah)) |
575 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 575 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
576 | ar9485Modes_green_spur_ob_db_tx_gain_1_1); | 576 | ar9485Modes_green_spur_ob_db_tx_gain_1_1); |
577 | else if (AR_SREV_9580(ah)) | 577 | else if (AR_SREV_9580(ah)) |
@@ -611,7 +611,7 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) | |||
611 | else if (AR_SREV_9340(ah)) | 611 | else if (AR_SREV_9340(ah)) |
612 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 612 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
613 | ar9340Common_rx_gain_table_1p0); | 613 | ar9340Common_rx_gain_table_1p0); |
614 | else if (AR_SREV_9485_11(ah)) | 614 | else if (AR_SREV_9485_11_OR_LATER(ah)) |
615 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 615 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
616 | ar9485_common_rx_gain_1_1); | 616 | ar9485_common_rx_gain_1_1); |
617 | else if (AR_SREV_9550(ah)) { | 617 | else if (AR_SREV_9550(ah)) { |
@@ -644,7 +644,7 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) | |||
644 | else if (AR_SREV_9340(ah)) | 644 | else if (AR_SREV_9340(ah)) |
645 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 645 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
646 | ar9340Common_wo_xlna_rx_gain_table_1p0); | 646 | ar9340Common_wo_xlna_rx_gain_table_1p0); |
647 | else if (AR_SREV_9485_11(ah)) | 647 | else if (AR_SREV_9485_11_OR_LATER(ah)) |
648 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 648 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
649 | ar9485Common_wo_xlna_rx_gain_1_1); | 649 | ar9485Common_wo_xlna_rx_gain_1_1); |
650 | else if (AR_SREV_9462_21(ah)) | 650 | else if (AR_SREV_9462_21(ah)) |
@@ -745,16 +745,25 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah) | |||
745 | static void ar9003_hw_configpcipowersave(struct ath_hw *ah, | 745 | static void ar9003_hw_configpcipowersave(struct ath_hw *ah, |
746 | bool power_off) | 746 | bool power_off) |
747 | { | 747 | { |
748 | /* | ||
749 | * Increase L1 Entry Latency. Some WB222 boards don't have | ||
750 | * this change in eeprom/OTP. | ||
751 | * | ||
752 | */ | ||
753 | if (AR_SREV_9462(ah)) { | ||
754 | u32 val = ah->config.aspm_l1_fix; | ||
755 | if ((val & 0xff000000) == 0x17000000) { | ||
756 | val &= 0x00ffffff; | ||
757 | val |= 0x27000000; | ||
758 | REG_WRITE(ah, 0x570c, val); | ||
759 | } | ||
760 | } | ||
761 | |||
748 | /* Nothing to do on restore for 11N */ | 762 | /* Nothing to do on restore for 11N */ |
749 | if (!power_off /* !restore */) { | 763 | if (!power_off /* !restore */) { |
750 | /* set bit 19 to allow forcing of pcie core into L1 state */ | 764 | /* set bit 19 to allow forcing of pcie core into L1 state */ |
751 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | 765 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); |
752 | 766 | REG_WRITE(ah, AR_WA, ah->WARegVal); | |
753 | /* Several PCIe massages to ensure proper behaviour */ | ||
754 | if (ah->config.pcie_waen) | ||
755 | REG_WRITE(ah, AR_WA, ah->config.pcie_waen); | ||
756 | else | ||
757 | REG_WRITE(ah, AR_WA, ah->WARegVal); | ||
758 | } | 767 | } |
759 | 768 | ||
760 | /* | 769 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 5163abd3937c..f6c5c1b50471 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -491,6 +491,7 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, | |||
491 | rxs->rs_rate = MS(rxsp->status1, AR_RxRate); | 491 | rxs->rs_rate = MS(rxsp->status1, AR_RxRate); |
492 | rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0; | 492 | rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0; |
493 | 493 | ||
494 | rxs->rs_firstaggr = (rxsp->status11 & AR_RxFirstAggr) ? 1 : 0; | ||
494 | rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0; | 495 | rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0; |
495 | rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0; | 496 | rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0; |
496 | rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7); | 497 | rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 1f694ab3cc78..e897648d3233 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -632,6 +632,22 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) | |||
632 | 632 | ||
633 | REG_SET_BIT(ah, AR_PHY_CCK_DETECT, | 633 | REG_SET_BIT(ah, AR_PHY_CCK_DETECT, |
634 | AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); | 634 | AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); |
635 | |||
636 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | ||
637 | REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE, | ||
638 | AR_GLB_SWREG_DISCONT_EN_BT_WLAN); | ||
639 | |||
640 | if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0, | ||
641 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) | ||
642 | ah->enabled_cals |= TX_IQ_CAL; | ||
643 | else | ||
644 | ah->enabled_cals &= ~TX_IQ_CAL; | ||
645 | |||
646 | if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) | ||
647 | ah->enabled_cals |= TX_CL_CAL; | ||
648 | else | ||
649 | ah->enabled_cals &= ~TX_CL_CAL; | ||
650 | } | ||
635 | } | 651 | } |
636 | 652 | ||
637 | static void ar9003_hw_prog_ini(struct ath_hw *ah, | 653 | static void ar9003_hw_prog_ini(struct ath_hw *ah, |
@@ -814,29 +830,12 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
814 | if (chan->channel == 2484) | 830 | if (chan->channel == 2484) |
815 | ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1); | 831 | ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1); |
816 | 832 | ||
817 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) | ||
818 | REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE, | ||
819 | AR_GLB_SWREG_DISCONT_EN_BT_WLAN); | ||
820 | |||
821 | ah->modes_index = modesIndex; | 833 | ah->modes_index = modesIndex; |
822 | ar9003_hw_override_ini(ah); | 834 | ar9003_hw_override_ini(ah); |
823 | ar9003_hw_set_channel_regs(ah, chan); | 835 | ar9003_hw_set_channel_regs(ah, chan); |
824 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | 836 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); |
825 | ath9k_hw_apply_txpower(ah, chan, false); | 837 | ath9k_hw_apply_txpower(ah, chan, false); |
826 | 838 | ||
827 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | ||
828 | if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0, | ||
829 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) | ||
830 | ah->enabled_cals |= TX_IQ_CAL; | ||
831 | else | ||
832 | ah->enabled_cals &= ~TX_IQ_CAL; | ||
833 | |||
834 | if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) | ||
835 | ah->enabled_cals |= TX_CL_CAL; | ||
836 | else | ||
837 | ah->enabled_cals &= ~TX_CL_CAL; | ||
838 | } | ||
839 | |||
840 | return 0; | 839 | return 0; |
841 | } | 840 | } |
842 | 841 | ||
@@ -1173,6 +1172,10 @@ skip_ws_det: | |||
1173 | * is_on == 0 means MRC CCK is OFF (more noise imm) | 1172 | * is_on == 0 means MRC CCK is OFF (more noise imm) |
1174 | */ | 1173 | */ |
1175 | bool is_on = param ? 1 : 0; | 1174 | bool is_on = param ? 1 : 0; |
1175 | |||
1176 | if (ah->caps.rx_chainmask == 1) | ||
1177 | break; | ||
1178 | |||
1176 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, | 1179 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, |
1177 | AR_PHY_MRC_CCK_ENABLE, is_on); | 1180 | AR_PHY_MRC_CCK_ENABLE, is_on); |
1178 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, | 1181 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, |
@@ -1190,8 +1193,6 @@ skip_ws_det: | |||
1190 | } | 1193 | } |
1191 | break; | 1194 | break; |
1192 | } | 1195 | } |
1193 | case ATH9K_ANI_PRESENT: | ||
1194 | break; | ||
1195 | default: | 1196 | default: |
1196 | ath_dbg(common, ANI, "invalid cmd %u\n", cmd); | 1197 | ath_dbg(common, ANI, "invalid cmd %u\n", cmd); |
1197 | return false; | 1198 | return false; |
@@ -1413,65 +1414,111 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah, | |||
1413 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | 1414 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); |
1414 | } | 1415 | } |
1415 | 1416 | ||
1416 | static void ar9003_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah, | 1417 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
1417 | bool enable) | 1418 | |
1419 | static void ar9003_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) | ||
1418 | { | 1420 | { |
1421 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1419 | u8 ant_div_ctl1; | 1422 | u8 ant_div_ctl1; |
1420 | u32 regval; | 1423 | u32 regval; |
1421 | 1424 | ||
1422 | if (!AR_SREV_9565(ah)) | 1425 | if (!AR_SREV_9485(ah) && !AR_SREV_9565(ah)) |
1423 | return; | 1426 | return; |
1424 | 1427 | ||
1425 | ah->shared_chain_lnadiv = enable; | 1428 | if (AR_SREV_9485(ah)) { |
1429 | regval = ar9003_hw_ant_ctrl_common_2_get(ah, | ||
1430 | IS_CHAN_2GHZ(ah->curchan)); | ||
1431 | if (enable) { | ||
1432 | regval &= ~AR_SWITCH_TABLE_COM2_ALL; | ||
1433 | regval |= ah->config.ant_ctrl_comm2g_switch_enable; | ||
1434 | } | ||
1435 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, | ||
1436 | AR_SWITCH_TABLE_COM2_ALL, regval); | ||
1437 | } | ||
1438 | |||
1426 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | 1439 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); |
1427 | 1440 | ||
1441 | /* | ||
1442 | * Set MAIN/ALT LNA conf. | ||
1443 | * Set MAIN/ALT gain_tb. | ||
1444 | */ | ||
1428 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | 1445 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); |
1429 | regval &= (~AR_ANT_DIV_CTRL_ALL); | 1446 | regval &= (~AR_ANT_DIV_CTRL_ALL); |
1430 | regval |= (ant_div_ctl1 & 0x3f) << AR_ANT_DIV_CTRL_ALL_S; | 1447 | regval |= (ant_div_ctl1 & 0x3f) << AR_ANT_DIV_CTRL_ALL_S; |
1431 | regval &= ~AR_PHY_ANT_DIV_LNADIV; | ||
1432 | regval |= ((ant_div_ctl1 >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S; | ||
1433 | |||
1434 | if (enable) | ||
1435 | regval |= AR_ANT_DIV_ENABLE; | ||
1436 | |||
1437 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | 1448 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); |
1438 | 1449 | ||
1439 | regval = REG_READ(ah, AR_PHY_CCK_DETECT); | 1450 | if (AR_SREV_9485_11_OR_LATER(ah)) { |
1440 | regval &= ~AR_FAST_DIV_ENABLE; | 1451 | /* |
1441 | regval |= ((ant_div_ctl1 >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; | 1452 | * Enable LNA diversity. |
1442 | 1453 | */ | |
1443 | if (enable) | ||
1444 | regval |= AR_FAST_DIV_ENABLE; | ||
1445 | |||
1446 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); | ||
1447 | |||
1448 | if (enable) { | ||
1449 | REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, | ||
1450 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); | ||
1451 | if (ah->curchan && IS_CHAN_2GHZ(ah->curchan)) | ||
1452 | REG_SET_BIT(ah, AR_PHY_RESTART, | ||
1453 | AR_PHY_RESTART_ENABLE_DIV_M2FLAG); | ||
1454 | REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, | ||
1455 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | ||
1456 | } else { | ||
1457 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE); | ||
1458 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, | ||
1459 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); | ||
1460 | REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE); | ||
1461 | REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV, | ||
1462 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | ||
1463 | |||
1464 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | 1454 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); |
1465 | regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF | | 1455 | regval &= ~AR_PHY_ANT_DIV_LNADIV; |
1466 | AR_PHY_ANT_DIV_ALT_LNACONF | | 1456 | regval |= ((ant_div_ctl1 >> 6) & 0x1) << AR_PHY_ANT_DIV_LNADIV_S; |
1467 | AR_PHY_ANT_DIV_MAIN_GAINTB | | 1457 | if (enable) |
1468 | AR_PHY_ANT_DIV_ALT_GAINTB); | 1458 | regval |= AR_ANT_DIV_ENABLE; |
1469 | regval |= (AR_PHY_ANT_DIV_LNA1 << AR_PHY_ANT_DIV_MAIN_LNACONF_S); | 1459 | |
1470 | regval |= (AR_PHY_ANT_DIV_LNA2 << AR_PHY_ANT_DIV_ALT_LNACONF_S); | ||
1471 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | 1460 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); |
1461 | |||
1462 | /* | ||
1463 | * Enable fast antenna diversity. | ||
1464 | */ | ||
1465 | regval = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
1466 | regval &= ~AR_FAST_DIV_ENABLE; | ||
1467 | regval |= ((ant_div_ctl1 >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; | ||
1468 | if (enable) | ||
1469 | regval |= AR_FAST_DIV_ENABLE; | ||
1470 | |||
1471 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); | ||
1472 | |||
1473 | if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) { | ||
1474 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
1475 | regval &= (~(AR_PHY_ANT_DIV_MAIN_LNACONF | | ||
1476 | AR_PHY_ANT_DIV_ALT_LNACONF | | ||
1477 | AR_PHY_ANT_DIV_ALT_GAINTB | | ||
1478 | AR_PHY_ANT_DIV_MAIN_GAINTB)); | ||
1479 | /* | ||
1480 | * Set MAIN to LNA1 and ALT to LNA2 at the | ||
1481 | * beginning. | ||
1482 | */ | ||
1483 | regval |= (ATH_ANT_DIV_COMB_LNA1 << | ||
1484 | AR_PHY_ANT_DIV_MAIN_LNACONF_S); | ||
1485 | regval |= (ATH_ANT_DIV_COMB_LNA2 << | ||
1486 | AR_PHY_ANT_DIV_ALT_LNACONF_S); | ||
1487 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
1488 | } | ||
1489 | } else if (AR_SREV_9565(ah)) { | ||
1490 | if (enable) { | ||
1491 | REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, | ||
1492 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); | ||
1493 | if (ah->curchan && IS_CHAN_2GHZ(ah->curchan)) | ||
1494 | REG_SET_BIT(ah, AR_PHY_RESTART, | ||
1495 | AR_PHY_RESTART_ENABLE_DIV_M2FLAG); | ||
1496 | REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, | ||
1497 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | ||
1498 | } else { | ||
1499 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE); | ||
1500 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, | ||
1501 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); | ||
1502 | REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE); | ||
1503 | REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV, | ||
1504 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | ||
1505 | |||
1506 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
1507 | regval &= ~(AR_PHY_ANT_DIV_MAIN_LNACONF | | ||
1508 | AR_PHY_ANT_DIV_ALT_LNACONF | | ||
1509 | AR_PHY_ANT_DIV_MAIN_GAINTB | | ||
1510 | AR_PHY_ANT_DIV_ALT_GAINTB); | ||
1511 | regval |= (ATH_ANT_DIV_COMB_LNA1 << | ||
1512 | AR_PHY_ANT_DIV_MAIN_LNACONF_S); | ||
1513 | regval |= (ATH_ANT_DIV_COMB_LNA2 << | ||
1514 | AR_PHY_ANT_DIV_ALT_LNACONF_S); | ||
1515 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
1516 | } | ||
1472 | } | 1517 | } |
1473 | } | 1518 | } |
1474 | 1519 | ||
1520 | #endif | ||
1521 | |||
1475 | static int ar9003_hw_fast_chan_change(struct ath_hw *ah, | 1522 | static int ar9003_hw_fast_chan_change(struct ath_hw *ah, |
1476 | struct ath9k_channel *chan, | 1523 | struct ath9k_channel *chan, |
1477 | u8 *ini_reloaded) | 1524 | u8 *ini_reloaded) |
@@ -1518,6 +1565,18 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah, | |||
1518 | 1565 | ||
1519 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); | 1566 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); |
1520 | 1567 | ||
1568 | if (AR_SREV_9462_20_OR_LATER(ah)) { | ||
1569 | /* | ||
1570 | * CUS217 mix LNA mode. | ||
1571 | */ | ||
1572 | if (ar9003_hw_get_rx_gain_idx(ah) == 2) { | ||
1573 | REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_core, | ||
1574 | 1, regWrites); | ||
1575 | REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_postamble, | ||
1576 | modesIndex, regWrites); | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1521 | /* | 1580 | /* |
1522 | * For 5GHz channels requiring Fast Clock, apply | 1581 | * For 5GHz channels requiring Fast Clock, apply |
1523 | * different modal values. | 1582 | * different modal values. |
@@ -1528,7 +1587,11 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah, | |||
1528 | if (AR_SREV_9565(ah)) | 1587 | if (AR_SREV_9565(ah)) |
1529 | REG_WRITE_ARRAY(&ah->iniModesFastClock, 1, regWrites); | 1588 | REG_WRITE_ARRAY(&ah->iniModesFastClock, 1, regWrites); |
1530 | 1589 | ||
1531 | REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites); | 1590 | /* |
1591 | * JAPAN regulatory. | ||
1592 | */ | ||
1593 | if (chan->channel == 2484) | ||
1594 | ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1); | ||
1532 | 1595 | ||
1533 | ah->modes_index = modesIndex; | 1596 | ah->modes_index = modesIndex; |
1534 | *ini_reloaded = true; | 1597 | *ini_reloaded = true; |
@@ -1631,11 +1694,14 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
1631 | 1694 | ||
1632 | ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; | 1695 | ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; |
1633 | ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; | 1696 | ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; |
1634 | ops->antctrl_shared_chain_lnadiv = ar9003_hw_antctrl_shared_chain_lnadiv; | ||
1635 | ops->spectral_scan_config = ar9003_hw_spectral_scan_config; | 1697 | ops->spectral_scan_config = ar9003_hw_spectral_scan_config; |
1636 | ops->spectral_scan_trigger = ar9003_hw_spectral_scan_trigger; | 1698 | ops->spectral_scan_trigger = ar9003_hw_spectral_scan_trigger; |
1637 | ops->spectral_scan_wait = ar9003_hw_spectral_scan_wait; | 1699 | ops->spectral_scan_wait = ar9003_hw_spectral_scan_wait; |
1638 | 1700 | ||
1701 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | ||
1702 | ops->set_bt_ant_diversity = ar9003_hw_set_bt_ant_diversity; | ||
1703 | #endif | ||
1704 | |||
1639 | ar9003_hw_set_nf_limits(ah); | 1705 | ar9003_hw_set_nf_limits(ah); |
1640 | ar9003_hw_set_radar_conf(ah); | 1706 | ar9003_hw_set_radar_conf(ah); |
1641 | memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); | 1707 | memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index d4d39f305a0b..6fd752321e36 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -148,6 +148,8 @@ | |||
148 | #define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 | 148 | #define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 |
149 | #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 | 149 | #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 |
150 | #define AR_PHY_EXT_CCA_THRESH62_S 16 | 150 | #define AR_PHY_EXT_CCA_THRESH62_S 16 |
151 | #define AR_PHY_EXTCHN_PWRTHR1_ANT_DIV_ALT_ANT_MINGAINIDX 0x0000FF00 | ||
152 | #define AR_PHY_EXTCHN_PWRTHR1_ANT_DIV_ALT_ANT_MINGAINIDX_S 8 | ||
151 | #define AR_PHY_EXT_MINCCA_PWR 0x01FF0000 | 153 | #define AR_PHY_EXT_MINCCA_PWR 0x01FF0000 |
152 | #define AR_PHY_EXT_MINCCA_PWR_S 16 | 154 | #define AR_PHY_EXT_MINCCA_PWR_S 16 |
153 | #define AR_PHY_EXT_CYCPWR_THR1 0x0000FE00L | 155 | #define AR_PHY_EXT_CYCPWR_THR1 0x0000FE00L |
@@ -296,11 +298,6 @@ | |||
296 | #define AR_PHY_ANT_DIV_MAIN_GAINTB 0x40000000 | 298 | #define AR_PHY_ANT_DIV_MAIN_GAINTB 0x40000000 |
297 | #define AR_PHY_ANT_DIV_MAIN_GAINTB_S 30 | 299 | #define AR_PHY_ANT_DIV_MAIN_GAINTB_S 30 |
298 | 300 | ||
299 | #define AR_PHY_ANT_DIV_LNA1_MINUS_LNA2 0x0 | ||
300 | #define AR_PHY_ANT_DIV_LNA2 0x1 | ||
301 | #define AR_PHY_ANT_DIV_LNA1 0x2 | ||
302 | #define AR_PHY_ANT_DIV_LNA1_PLUS_LNA2 0x3 | ||
303 | |||
304 | #define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) | 301 | #define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) |
305 | #define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) | 302 | #define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) |
306 | #define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34) | 303 | #define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34) |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index c1224b5a257b..2ee35f677c0e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -72,17 +72,12 @@ struct ath_config { | |||
72 | /*************************/ | 72 | /*************************/ |
73 | 73 | ||
74 | #define ATH_TXBUF_RESET(_bf) do { \ | 74 | #define ATH_TXBUF_RESET(_bf) do { \ |
75 | (_bf)->bf_stale = false; \ | ||
76 | (_bf)->bf_lastbf = NULL; \ | 75 | (_bf)->bf_lastbf = NULL; \ |
77 | (_bf)->bf_next = NULL; \ | 76 | (_bf)->bf_next = NULL; \ |
78 | memset(&((_bf)->bf_state), 0, \ | 77 | memset(&((_bf)->bf_state), 0, \ |
79 | sizeof(struct ath_buf_state)); \ | 78 | sizeof(struct ath_buf_state)); \ |
80 | } while (0) | 79 | } while (0) |
81 | 80 | ||
82 | #define ATH_RXBUF_RESET(_bf) do { \ | ||
83 | (_bf)->bf_stale = false; \ | ||
84 | } while (0) | ||
85 | |||
86 | /** | 81 | /** |
87 | * enum buffer_type - Buffer type flags | 82 | * enum buffer_type - Buffer type flags |
88 | * | 83 | * |
@@ -137,7 +132,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
137 | #define ATH_AGGR_ENCRYPTDELIM 10 | 132 | #define ATH_AGGR_ENCRYPTDELIM 10 |
138 | /* minimum h/w qdepth to be sustained to maximize aggregation */ | 133 | /* minimum h/w qdepth to be sustained to maximize aggregation */ |
139 | #define ATH_AGGR_MIN_QDEPTH 2 | 134 | #define ATH_AGGR_MIN_QDEPTH 2 |
140 | #define ATH_AMPDU_SUBFRAME_DEFAULT 32 | 135 | /* minimum h/w qdepth for non-aggregated traffic */ |
136 | #define ATH_NON_AGGR_MIN_QDEPTH 8 | ||
141 | 137 | ||
142 | #define IEEE80211_SEQ_SEQ_SHIFT 4 | 138 | #define IEEE80211_SEQ_SEQ_SHIFT 4 |
143 | #define IEEE80211_SEQ_MAX 4096 | 139 | #define IEEE80211_SEQ_MAX 4096 |
@@ -174,12 +170,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
174 | 170 | ||
175 | #define ATH_TX_COMPLETE_POLL_INT 1000 | 171 | #define ATH_TX_COMPLETE_POLL_INT 1000 |
176 | 172 | ||
177 | enum ATH_AGGR_STATUS { | ||
178 | ATH_AGGR_DONE, | ||
179 | ATH_AGGR_BAW_CLOSED, | ||
180 | ATH_AGGR_LIMITED, | ||
181 | }; | ||
182 | |||
183 | #define ATH_TXFIFO_DEPTH 8 | 173 | #define ATH_TXFIFO_DEPTH 8 |
184 | struct ath_txq { | 174 | struct ath_txq { |
185 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ | 175 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ |
@@ -201,10 +191,10 @@ struct ath_txq { | |||
201 | 191 | ||
202 | struct ath_atx_ac { | 192 | struct ath_atx_ac { |
203 | struct ath_txq *txq; | 193 | struct ath_txq *txq; |
204 | int sched; | ||
205 | struct list_head list; | 194 | struct list_head list; |
206 | struct list_head tid_q; | 195 | struct list_head tid_q; |
207 | bool clear_ps_filter; | 196 | bool clear_ps_filter; |
197 | bool sched; | ||
208 | }; | 198 | }; |
209 | 199 | ||
210 | struct ath_frame_info { | 200 | struct ath_frame_info { |
@@ -212,14 +202,16 @@ struct ath_frame_info { | |||
212 | int framelen; | 202 | int framelen; |
213 | enum ath9k_key_type keytype; | 203 | enum ath9k_key_type keytype; |
214 | u8 keyix; | 204 | u8 keyix; |
215 | u8 retries; | ||
216 | u8 rtscts_rate; | 205 | u8 rtscts_rate; |
206 | u8 retries : 7; | ||
207 | u8 baw_tracked : 1; | ||
217 | }; | 208 | }; |
218 | 209 | ||
219 | struct ath_buf_state { | 210 | struct ath_buf_state { |
220 | u8 bf_type; | 211 | u8 bf_type; |
221 | u8 bfs_paprd; | 212 | u8 bfs_paprd; |
222 | u8 ndelim; | 213 | u8 ndelim; |
214 | bool stale; | ||
223 | u16 seqno; | 215 | u16 seqno; |
224 | unsigned long bfs_paprd_timestamp; | 216 | unsigned long bfs_paprd_timestamp; |
225 | }; | 217 | }; |
@@ -233,7 +225,6 @@ struct ath_buf { | |||
233 | void *bf_desc; /* virtual addr of desc */ | 225 | void *bf_desc; /* virtual addr of desc */ |
234 | dma_addr_t bf_daddr; /* physical addr of desc */ | 226 | dma_addr_t bf_daddr; /* physical addr of desc */ |
235 | dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */ | 227 | dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */ |
236 | bool bf_stale; | ||
237 | struct ieee80211_tx_rate rates[4]; | 228 | struct ieee80211_tx_rate rates[4]; |
238 | struct ath_buf_state bf_state; | 229 | struct ath_buf_state bf_state; |
239 | }; | 230 | }; |
@@ -241,16 +232,18 @@ struct ath_buf { | |||
241 | struct ath_atx_tid { | 232 | struct ath_atx_tid { |
242 | struct list_head list; | 233 | struct list_head list; |
243 | struct sk_buff_head buf_q; | 234 | struct sk_buff_head buf_q; |
235 | struct sk_buff_head retry_q; | ||
244 | struct ath_node *an; | 236 | struct ath_node *an; |
245 | struct ath_atx_ac *ac; | 237 | struct ath_atx_ac *ac; |
246 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; | 238 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; |
247 | int bar_index; | ||
248 | u16 seq_start; | 239 | u16 seq_start; |
249 | u16 seq_next; | 240 | u16 seq_next; |
250 | u16 baw_size; | 241 | u16 baw_size; |
251 | int tidno; | 242 | u8 tidno; |
252 | int baw_head; /* first un-acked tx buffer */ | 243 | int baw_head; /* first un-acked tx buffer */ |
253 | int baw_tail; /* next unused tx buffer slot */ | 244 | int baw_tail; /* next unused tx buffer slot */ |
245 | |||
246 | s8 bar_index; | ||
254 | bool sched; | 247 | bool sched; |
255 | bool paused; | 248 | bool paused; |
256 | bool active; | 249 | bool active; |
@@ -262,16 +255,13 @@ struct ath_node { | |||
262 | struct ieee80211_vif *vif; /* interface with which we're associated */ | 255 | struct ieee80211_vif *vif; /* interface with which we're associated */ |
263 | struct ath_atx_tid tid[IEEE80211_NUM_TIDS]; | 256 | struct ath_atx_tid tid[IEEE80211_NUM_TIDS]; |
264 | struct ath_atx_ac ac[IEEE80211_NUM_ACS]; | 257 | struct ath_atx_ac ac[IEEE80211_NUM_ACS]; |
265 | int ps_key; | ||
266 | 258 | ||
267 | u16 maxampdu; | 259 | u16 maxampdu; |
268 | u8 mpdudensity; | 260 | u8 mpdudensity; |
261 | s8 ps_key; | ||
269 | 262 | ||
270 | bool sleeping; | 263 | bool sleeping; |
271 | 264 | bool no_ps_filter; | |
272 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) | ||
273 | struct dentry *node_stat; | ||
274 | #endif | ||
275 | }; | 265 | }; |
276 | 266 | ||
277 | struct ath_tx_control { | 267 | struct ath_tx_control { |
@@ -317,6 +307,7 @@ struct ath_rx { | |||
317 | struct ath_descdma rxdma; | 307 | struct ath_descdma rxdma; |
318 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; | 308 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; |
319 | 309 | ||
310 | struct ath_buf *buf_hold; | ||
320 | struct sk_buff *frag; | 311 | struct sk_buff *frag; |
321 | 312 | ||
322 | u32 ampdu_ref; | 313 | u32 ampdu_ref; |
@@ -367,6 +358,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
367 | /********/ | 358 | /********/ |
368 | 359 | ||
369 | struct ath_vif { | 360 | struct ath_vif { |
361 | struct ath_node mcast_node; | ||
370 | int av_bslot; | 362 | int av_bslot; |
371 | bool primary_sta_vif; | 363 | bool primary_sta_vif; |
372 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ | 364 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ |
@@ -428,6 +420,7 @@ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif); | |||
428 | void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif); | 420 | void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif); |
429 | void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif); | 421 | void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif); |
430 | void ath9k_set_beacon(struct ath_softc *sc); | 422 | void ath9k_set_beacon(struct ath_softc *sc); |
423 | bool ath9k_csa_is_finished(struct ath_softc *sc); | ||
431 | 424 | ||
432 | /*******************/ | 425 | /*******************/ |
433 | /* Link Monitoring */ | 426 | /* Link Monitoring */ |
@@ -585,19 +578,14 @@ static inline void ath_fill_led_pin(struct ath_softc *sc) | |||
585 | #define ATH_ANT_DIV_COMB_MAX_COUNT 100 | 578 | #define ATH_ANT_DIV_COMB_MAX_COUNT 100 |
586 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 | 579 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 |
587 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 | 580 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 |
581 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI 50 | ||
582 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI 50 | ||
588 | 583 | ||
589 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 | 584 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 |
590 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 | 585 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 |
591 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 | 586 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 |
592 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2 | 587 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2 |
593 | 588 | ||
594 | enum ath9k_ant_div_comb_lna_conf { | ||
595 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, | ||
596 | ATH_ANT_DIV_COMB_LNA2, | ||
597 | ATH_ANT_DIV_COMB_LNA1, | ||
598 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2, | ||
599 | }; | ||
600 | |||
601 | struct ath_ant_comb { | 589 | struct ath_ant_comb { |
602 | u16 count; | 590 | u16 count; |
603 | u16 total_pkt_count; | 591 | u16 total_pkt_count; |
@@ -614,27 +602,36 @@ struct ath_ant_comb { | |||
614 | int rssi_first; | 602 | int rssi_first; |
615 | int rssi_second; | 603 | int rssi_second; |
616 | int rssi_third; | 604 | int rssi_third; |
605 | int ant_ratio; | ||
606 | int ant_ratio2; | ||
617 | bool alt_good; | 607 | bool alt_good; |
618 | int quick_scan_cnt; | 608 | int quick_scan_cnt; |
619 | int main_conf; | 609 | enum ath9k_ant_div_comb_lna_conf main_conf; |
620 | enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf; | 610 | enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf; |
621 | enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf; | 611 | enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf; |
622 | bool first_ratio; | 612 | bool first_ratio; |
623 | bool second_ratio; | 613 | bool second_ratio; |
624 | unsigned long scan_start_time; | 614 | unsigned long scan_start_time; |
615 | |||
616 | /* | ||
617 | * Card-specific config values. | ||
618 | */ | ||
619 | int low_rssi_thresh; | ||
620 | int fast_div_bias; | ||
625 | }; | 621 | }; |
626 | 622 | ||
627 | void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | 623 | void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); |
628 | void ath_ant_comb_update(struct ath_softc *sc); | ||
629 | 624 | ||
630 | /********************/ | 625 | /********************/ |
631 | /* Main driver core */ | 626 | /* Main driver core */ |
632 | /********************/ | 627 | /********************/ |
633 | 628 | ||
634 | #define ATH9K_PCI_CUS198 0x0001 | 629 | #define ATH9K_PCI_CUS198 0x0001 |
635 | #define ATH9K_PCI_CUS230 0x0002 | 630 | #define ATH9K_PCI_CUS230 0x0002 |
636 | #define ATH9K_PCI_CUS217 0x0004 | 631 | #define ATH9K_PCI_CUS217 0x0004 |
637 | #define ATH9K_PCI_WOW 0x0008 | 632 | #define ATH9K_PCI_WOW 0x0008 |
633 | #define ATH9K_PCI_BT_ANT_DIV 0x0010 | ||
634 | #define ATH9K_PCI_D3_L1_WAR 0x0020 | ||
638 | 635 | ||
639 | /* | 636 | /* |
640 | * Default cache line size, in bytes. | 637 | * Default cache line size, in bytes. |
@@ -761,6 +758,7 @@ struct ath_softc { | |||
761 | #endif | 758 | #endif |
762 | 759 | ||
763 | struct ath_descdma txsdma; | 760 | struct ath_descdma txsdma; |
761 | struct ieee80211_vif *csa_vif; | ||
764 | 762 | ||
765 | struct ath_ant_comb ant_comb; | 763 | struct ath_ant_comb ant_comb; |
766 | u8 ant_tx, ant_rx; | 764 | u8 ant_tx, ant_rx; |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 1a17732bb089..b5c16b3a37b9 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -291,6 +291,23 @@ void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
291 | (unsigned long long)tsfadjust, avp->av_bslot); | 291 | (unsigned long long)tsfadjust, avp->av_bslot); |
292 | } | 292 | } |
293 | 293 | ||
294 | bool ath9k_csa_is_finished(struct ath_softc *sc) | ||
295 | { | ||
296 | struct ieee80211_vif *vif; | ||
297 | |||
298 | vif = sc->csa_vif; | ||
299 | if (!vif || !vif->csa_active) | ||
300 | return false; | ||
301 | |||
302 | if (!ieee80211_csa_is_complete(vif)) | ||
303 | return false; | ||
304 | |||
305 | ieee80211_csa_finish(vif); | ||
306 | |||
307 | sc->csa_vif = NULL; | ||
308 | return true; | ||
309 | } | ||
310 | |||
294 | void ath9k_beacon_tasklet(unsigned long data) | 311 | void ath9k_beacon_tasklet(unsigned long data) |
295 | { | 312 | { |
296 | struct ath_softc *sc = (struct ath_softc *)data; | 313 | struct ath_softc *sc = (struct ath_softc *)data; |
@@ -336,6 +353,10 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
336 | return; | 353 | return; |
337 | } | 354 | } |
338 | 355 | ||
356 | /* EDMA devices check that in the tx completion function. */ | ||
357 | if (!edma && ath9k_csa_is_finished(sc)) | ||
358 | return; | ||
359 | |||
339 | slot = ath9k_beacon_choose_slot(sc); | 360 | slot = ath9k_beacon_choose_slot(sc); |
340 | vif = sc->beacon.bslot[slot]; | 361 | vif = sc->beacon.bslot[slot]; |
341 | 362 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 344fdde1d7a3..d3063c21e16c 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -49,37 +49,40 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) | |||
49 | } | 49 | } |
50 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); | 50 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); |
51 | 51 | ||
52 | static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, | 52 | static u32 ath9k_get_extchanmode(struct cfg80211_chan_def *chandef) |
53 | enum nl80211_channel_type channel_type) | ||
54 | { | 53 | { |
55 | u32 chanmode = 0; | 54 | u32 chanmode = 0; |
56 | 55 | ||
57 | switch (chan->band) { | 56 | switch (chandef->chan->band) { |
58 | case IEEE80211_BAND_2GHZ: | 57 | case IEEE80211_BAND_2GHZ: |
59 | switch (channel_type) { | 58 | switch (chandef->width) { |
60 | case NL80211_CHAN_NO_HT: | 59 | case NL80211_CHAN_WIDTH_20_NOHT: |
61 | case NL80211_CHAN_HT20: | 60 | case NL80211_CHAN_WIDTH_20: |
62 | chanmode = CHANNEL_G_HT20; | 61 | chanmode = CHANNEL_G_HT20; |
63 | break; | 62 | break; |
64 | case NL80211_CHAN_HT40PLUS: | 63 | case NL80211_CHAN_WIDTH_40: |
65 | chanmode = CHANNEL_G_HT40PLUS; | 64 | if (chandef->center_freq1 > chandef->chan->center_freq) |
65 | chanmode = CHANNEL_G_HT40PLUS; | ||
66 | else | ||
67 | chanmode = CHANNEL_G_HT40MINUS; | ||
66 | break; | 68 | break; |
67 | case NL80211_CHAN_HT40MINUS: | 69 | default: |
68 | chanmode = CHANNEL_G_HT40MINUS; | ||
69 | break; | 70 | break; |
70 | } | 71 | } |
71 | break; | 72 | break; |
72 | case IEEE80211_BAND_5GHZ: | 73 | case IEEE80211_BAND_5GHZ: |
73 | switch (channel_type) { | 74 | switch (chandef->width) { |
74 | case NL80211_CHAN_NO_HT: | 75 | case NL80211_CHAN_WIDTH_20_NOHT: |
75 | case NL80211_CHAN_HT20: | 76 | case NL80211_CHAN_WIDTH_20: |
76 | chanmode = CHANNEL_A_HT20; | 77 | chanmode = CHANNEL_A_HT20; |
77 | break; | 78 | break; |
78 | case NL80211_CHAN_HT40PLUS: | 79 | case NL80211_CHAN_WIDTH_40: |
79 | chanmode = CHANNEL_A_HT40PLUS; | 80 | if (chandef->center_freq1 > chandef->chan->center_freq) |
81 | chanmode = CHANNEL_A_HT40PLUS; | ||
82 | else | ||
83 | chanmode = CHANNEL_A_HT40MINUS; | ||
80 | break; | 84 | break; |
81 | case NL80211_CHAN_HT40MINUS: | 85 | default: |
82 | chanmode = CHANNEL_A_HT40MINUS; | ||
83 | break; | 86 | break; |
84 | } | 87 | } |
85 | break; | 88 | break; |
@@ -94,13 +97,12 @@ static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, | |||
94 | * Update internal channel flags. | 97 | * Update internal channel flags. |
95 | */ | 98 | */ |
96 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, | 99 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, |
97 | struct ieee80211_channel *chan, | 100 | struct cfg80211_chan_def *chandef) |
98 | enum nl80211_channel_type channel_type) | ||
99 | { | 101 | { |
100 | ichan->channel = chan->center_freq; | 102 | ichan->channel = chandef->chan->center_freq; |
101 | ichan->chan = chan; | 103 | ichan->chan = chandef->chan; |
102 | 104 | ||
103 | if (chan->band == IEEE80211_BAND_2GHZ) { | 105 | if (chandef->chan->band == IEEE80211_BAND_2GHZ) { |
104 | ichan->chanmode = CHANNEL_G; | 106 | ichan->chanmode = CHANNEL_G; |
105 | ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; | 107 | ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; |
106 | } else { | 108 | } else { |
@@ -108,8 +110,22 @@ void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, | |||
108 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; | 110 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; |
109 | } | 111 | } |
110 | 112 | ||
111 | if (channel_type != NL80211_CHAN_NO_HT) | 113 | switch (chandef->width) { |
112 | ichan->chanmode = ath9k_get_extchanmode(chan, channel_type); | 114 | case NL80211_CHAN_WIDTH_5: |
115 | ichan->channelFlags |= CHANNEL_QUARTER; | ||
116 | break; | ||
117 | case NL80211_CHAN_WIDTH_10: | ||
118 | ichan->channelFlags |= CHANNEL_HALF; | ||
119 | break; | ||
120 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
121 | break; | ||
122 | case NL80211_CHAN_WIDTH_20: | ||
123 | case NL80211_CHAN_WIDTH_40: | ||
124 | ichan->chanmode = ath9k_get_extchanmode(chandef); | ||
125 | break; | ||
126 | default: | ||
127 | WARN_ON(1); | ||
128 | } | ||
113 | } | 129 | } |
114 | EXPORT_SYMBOL(ath9k_cmn_update_ichannel); | 130 | EXPORT_SYMBOL(ath9k_cmn_update_ichannel); |
115 | 131 | ||
@@ -125,8 +141,7 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | |||
125 | 141 | ||
126 | chan_idx = curchan->hw_value; | 142 | chan_idx = curchan->hw_value; |
127 | channel = &ah->channels[chan_idx]; | 143 | channel = &ah->channels[chan_idx]; |
128 | ath9k_cmn_update_ichannel(channel, curchan, | 144 | ath9k_cmn_update_ichannel(channel, &hw->conf.chandef); |
129 | cfg80211_get_chandef_type(&hw->conf.chandef)); | ||
130 | 145 | ||
131 | return channel; | 146 | return channel; |
132 | } | 147 | } |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 207d06995b15..e039bcbfbd79 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -44,8 +44,7 @@ | |||
44 | 44 | ||
45 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 45 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
46 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, | 46 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, |
47 | struct ieee80211_channel *chan, | 47 | struct cfg80211_chan_def *chandef); |
48 | enum nl80211_channel_type channel_type); | ||
49 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | 48 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, |
50 | struct ath_hw *ah); | 49 | struct ath_hw *ah); |
51 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | 50 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 87454f6c7b4f..c088744a6bfb 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -88,90 +88,6 @@ static const struct file_operations fops_debug = { | |||
88 | 88 | ||
89 | #define DMA_BUF_LEN 1024 | 89 | #define DMA_BUF_LEN 1024 |
90 | 90 | ||
91 | static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf, | ||
92 | size_t count, loff_t *ppos) | ||
93 | { | ||
94 | struct ath_softc *sc = file->private_data; | ||
95 | struct ath_hw *ah = sc->sc_ah; | ||
96 | char buf[32]; | ||
97 | unsigned int len; | ||
98 | |||
99 | len = sprintf(buf, "0x%08x\n", ah->txchainmask); | ||
100 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
101 | } | ||
102 | |||
103 | static ssize_t write_file_tx_chainmask(struct file *file, const char __user *user_buf, | ||
104 | size_t count, loff_t *ppos) | ||
105 | { | ||
106 | struct ath_softc *sc = file->private_data; | ||
107 | struct ath_hw *ah = sc->sc_ah; | ||
108 | unsigned long mask; | ||
109 | char buf[32]; | ||
110 | ssize_t len; | ||
111 | |||
112 | len = min(count, sizeof(buf) - 1); | ||
113 | if (copy_from_user(buf, user_buf, len)) | ||
114 | return -EFAULT; | ||
115 | |||
116 | buf[len] = '\0'; | ||
117 | if (kstrtoul(buf, 0, &mask)) | ||
118 | return -EINVAL; | ||
119 | |||
120 | ah->txchainmask = mask; | ||
121 | ah->caps.tx_chainmask = mask; | ||
122 | return count; | ||
123 | } | ||
124 | |||
125 | static const struct file_operations fops_tx_chainmask = { | ||
126 | .read = read_file_tx_chainmask, | ||
127 | .write = write_file_tx_chainmask, | ||
128 | .open = simple_open, | ||
129 | .owner = THIS_MODULE, | ||
130 | .llseek = default_llseek, | ||
131 | }; | ||
132 | |||
133 | |||
134 | static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf, | ||
135 | size_t count, loff_t *ppos) | ||
136 | { | ||
137 | struct ath_softc *sc = file->private_data; | ||
138 | struct ath_hw *ah = sc->sc_ah; | ||
139 | char buf[32]; | ||
140 | unsigned int len; | ||
141 | |||
142 | len = sprintf(buf, "0x%08x\n", ah->rxchainmask); | ||
143 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
144 | } | ||
145 | |||
146 | static ssize_t write_file_rx_chainmask(struct file *file, const char __user *user_buf, | ||
147 | size_t count, loff_t *ppos) | ||
148 | { | ||
149 | struct ath_softc *sc = file->private_data; | ||
150 | struct ath_hw *ah = sc->sc_ah; | ||
151 | unsigned long mask; | ||
152 | char buf[32]; | ||
153 | ssize_t len; | ||
154 | |||
155 | len = min(count, sizeof(buf) - 1); | ||
156 | if (copy_from_user(buf, user_buf, len)) | ||
157 | return -EFAULT; | ||
158 | |||
159 | buf[len] = '\0'; | ||
160 | if (kstrtoul(buf, 0, &mask)) | ||
161 | return -EINVAL; | ||
162 | |||
163 | ah->rxchainmask = mask; | ||
164 | ah->caps.rx_chainmask = mask; | ||
165 | return count; | ||
166 | } | ||
167 | |||
168 | static const struct file_operations fops_rx_chainmask = { | ||
169 | .read = read_file_rx_chainmask, | ||
170 | .write = write_file_rx_chainmask, | ||
171 | .open = simple_open, | ||
172 | .owner = THIS_MODULE, | ||
173 | .llseek = default_llseek, | ||
174 | }; | ||
175 | 91 | ||
176 | static ssize_t read_file_ani(struct file *file, char __user *user_buf, | 92 | static ssize_t read_file_ani(struct file *file, char __user *user_buf, |
177 | size_t count, loff_t *ppos) | 93 | size_t count, loff_t *ppos) |
@@ -270,25 +186,29 @@ static const struct file_operations fops_ani = { | |||
270 | .llseek = default_llseek, | 186 | .llseek = default_llseek, |
271 | }; | 187 | }; |
272 | 188 | ||
273 | static ssize_t read_file_ant_diversity(struct file *file, char __user *user_buf, | 189 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
274 | size_t count, loff_t *ppos) | 190 | |
191 | static ssize_t read_file_bt_ant_diversity(struct file *file, | ||
192 | char __user *user_buf, | ||
193 | size_t count, loff_t *ppos) | ||
275 | { | 194 | { |
276 | struct ath_softc *sc = file->private_data; | 195 | struct ath_softc *sc = file->private_data; |
277 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 196 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
278 | char buf[32]; | 197 | char buf[32]; |
279 | unsigned int len; | 198 | unsigned int len; |
280 | 199 | ||
281 | len = sprintf(buf, "%d\n", common->antenna_diversity); | 200 | len = sprintf(buf, "%d\n", common->bt_ant_diversity); |
282 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 201 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
283 | } | 202 | } |
284 | 203 | ||
285 | static ssize_t write_file_ant_diversity(struct file *file, | 204 | static ssize_t write_file_bt_ant_diversity(struct file *file, |
286 | const char __user *user_buf, | 205 | const char __user *user_buf, |
287 | size_t count, loff_t *ppos) | 206 | size_t count, loff_t *ppos) |
288 | { | 207 | { |
289 | struct ath_softc *sc = file->private_data; | 208 | struct ath_softc *sc = file->private_data; |
290 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 209 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
291 | unsigned long antenna_diversity; | 210 | struct ath9k_hw_capabilities *pCap = &sc->sc_ah->caps; |
211 | unsigned long bt_ant_diversity; | ||
292 | char buf[32]; | 212 | char buf[32]; |
293 | ssize_t len; | 213 | ssize_t len; |
294 | 214 | ||
@@ -296,26 +216,147 @@ static ssize_t write_file_ant_diversity(struct file *file, | |||
296 | if (copy_from_user(buf, user_buf, len)) | 216 | if (copy_from_user(buf, user_buf, len)) |
297 | return -EFAULT; | 217 | return -EFAULT; |
298 | 218 | ||
299 | if (!AR_SREV_9565(sc->sc_ah)) | 219 | if (!(pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV)) |
300 | goto exit; | 220 | goto exit; |
301 | 221 | ||
302 | buf[len] = '\0'; | 222 | buf[len] = '\0'; |
303 | if (kstrtoul(buf, 0, &antenna_diversity)) | 223 | if (kstrtoul(buf, 0, &bt_ant_diversity)) |
304 | return -EINVAL; | 224 | return -EINVAL; |
305 | 225 | ||
306 | common->antenna_diversity = !!antenna_diversity; | 226 | common->bt_ant_diversity = !!bt_ant_diversity; |
307 | ath9k_ps_wakeup(sc); | 227 | ath9k_ps_wakeup(sc); |
308 | ath_ant_comb_update(sc); | 228 | ath9k_hw_set_bt_ant_diversity(sc->sc_ah, common->bt_ant_diversity); |
309 | ath_dbg(common, CONFIG, "Antenna diversity: %d\n", | 229 | ath_dbg(common, CONFIG, "Enable WLAN/BT RX Antenna diversity: %d\n", |
310 | common->antenna_diversity); | 230 | common->bt_ant_diversity); |
311 | ath9k_ps_restore(sc); | 231 | ath9k_ps_restore(sc); |
312 | exit: | 232 | exit: |
313 | return count; | 233 | return count; |
314 | } | 234 | } |
315 | 235 | ||
316 | static const struct file_operations fops_ant_diversity = { | 236 | static const struct file_operations fops_bt_ant_diversity = { |
317 | .read = read_file_ant_diversity, | 237 | .read = read_file_bt_ant_diversity, |
318 | .write = write_file_ant_diversity, | 238 | .write = write_file_bt_ant_diversity, |
239 | .open = simple_open, | ||
240 | .owner = THIS_MODULE, | ||
241 | .llseek = default_llseek, | ||
242 | }; | ||
243 | |||
244 | #endif | ||
245 | |||
246 | void ath9k_debug_stat_ant(struct ath_softc *sc, | ||
247 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
248 | int main_rssi_avg, int alt_rssi_avg) | ||
249 | { | ||
250 | struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN]; | ||
251 | struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT]; | ||
252 | |||
253 | as_main->lna_attempt_cnt[div_ant_conf->main_lna_conf]++; | ||
254 | as_alt->lna_attempt_cnt[div_ant_conf->alt_lna_conf]++; | ||
255 | |||
256 | as_main->rssi_avg = main_rssi_avg; | ||
257 | as_alt->rssi_avg = alt_rssi_avg; | ||
258 | } | ||
259 | |||
260 | static ssize_t read_file_antenna_diversity(struct file *file, | ||
261 | char __user *user_buf, | ||
262 | size_t count, loff_t *ppos) | ||
263 | { | ||
264 | struct ath_softc *sc = file->private_data; | ||
265 | struct ath_hw *ah = sc->sc_ah; | ||
266 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
267 | struct ath_antenna_stats *as_main = &sc->debug.stats.ant_stats[ANT_MAIN]; | ||
268 | struct ath_antenna_stats *as_alt = &sc->debug.stats.ant_stats[ANT_ALT]; | ||
269 | struct ath_hw_antcomb_conf div_ant_conf; | ||
270 | unsigned int len = 0, size = 1024; | ||
271 | ssize_t retval = 0; | ||
272 | char *buf; | ||
273 | char *lna_conf_str[4] = {"LNA1_MINUS_LNA2", | ||
274 | "LNA2", | ||
275 | "LNA1", | ||
276 | "LNA1_PLUS_LNA2"}; | ||
277 | |||
278 | buf = kzalloc(size, GFP_KERNEL); | ||
279 | if (buf == NULL) | ||
280 | return -ENOMEM; | ||
281 | |||
282 | if (!(pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)) { | ||
283 | len += snprintf(buf + len, size - len, "%s\n", | ||
284 | "Antenna Diversity Combining is disabled"); | ||
285 | goto exit; | ||
286 | } | ||
287 | |||
288 | ath9k_ps_wakeup(sc); | ||
289 | ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); | ||
290 | len += snprintf(buf + len, size - len, "Current MAIN config : %s\n", | ||
291 | lna_conf_str[div_ant_conf.main_lna_conf]); | ||
292 | len += snprintf(buf + len, size - len, "Current ALT config : %s\n", | ||
293 | lna_conf_str[div_ant_conf.alt_lna_conf]); | ||
294 | len += snprintf(buf + len, size - len, "Average MAIN RSSI : %d\n", | ||
295 | as_main->rssi_avg); | ||
296 | len += snprintf(buf + len, size - len, "Average ALT RSSI : %d\n\n", | ||
297 | as_alt->rssi_avg); | ||
298 | ath9k_ps_restore(sc); | ||
299 | |||
300 | len += snprintf(buf + len, size - len, "Packet Receive Cnt:\n"); | ||
301 | len += snprintf(buf + len, size - len, "-------------------\n"); | ||
302 | |||
303 | len += snprintf(buf + len, size - len, "%30s%15s\n", | ||
304 | "MAIN", "ALT"); | ||
305 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | ||
306 | "TOTAL COUNT", | ||
307 | as_main->recv_cnt, | ||
308 | as_alt->recv_cnt); | ||
309 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | ||
310 | "LNA1", | ||
311 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1], | ||
312 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1]); | ||
313 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | ||
314 | "LNA2", | ||
315 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2], | ||
316 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2]); | ||
317 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | ||
318 | "LNA1 + LNA2", | ||
319 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2], | ||
320 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]); | ||
321 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | ||
322 | "LNA1 - LNA2", | ||
323 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2], | ||
324 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]); | ||
325 | |||
326 | len += snprintf(buf + len, size - len, "\nLNA Config Attempts:\n"); | ||
327 | len += snprintf(buf + len, size - len, "--------------------\n"); | ||
328 | |||
329 | len += snprintf(buf + len, size - len, "%30s%15s\n", | ||
330 | "MAIN", "ALT"); | ||
331 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | ||
332 | "LNA1", | ||
333 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1], | ||
334 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1]); | ||
335 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | ||
336 | "LNA2", | ||
337 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2], | ||
338 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2]); | ||
339 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | ||
340 | "LNA1 + LNA2", | ||
341 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2], | ||
342 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]); | ||
343 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | ||
344 | "LNA1 - LNA2", | ||
345 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2], | ||
346 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]); | ||
347 | |||
348 | exit: | ||
349 | if (len > size) | ||
350 | len = size; | ||
351 | |||
352 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
353 | kfree(buf); | ||
354 | |||
355 | return retval; | ||
356 | } | ||
357 | |||
358 | static const struct file_operations fops_antenna_diversity = { | ||
359 | .read = read_file_antenna_diversity, | ||
319 | .open = simple_open, | 360 | .open = simple_open, |
320 | .owner = THIS_MODULE, | 361 | .owner = THIS_MODULE, |
321 | .llseek = default_llseek, | 362 | .llseek = default_llseek, |
@@ -607,6 +648,28 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
607 | return retval; | 648 | return retval; |
608 | } | 649 | } |
609 | 650 | ||
651 | static ssize_t print_queue(struct ath_softc *sc, struct ath_txq *txq, | ||
652 | char *buf, ssize_t size) | ||
653 | { | ||
654 | ssize_t len = 0; | ||
655 | |||
656 | ath_txq_lock(sc, txq); | ||
657 | |||
658 | len += snprintf(buf + len, size - len, "%s: %d ", | ||
659 | "qnum", txq->axq_qnum); | ||
660 | len += snprintf(buf + len, size - len, "%s: %2d ", | ||
661 | "qdepth", txq->axq_depth); | ||
662 | len += snprintf(buf + len, size - len, "%s: %2d ", | ||
663 | "ampdu-depth", txq->axq_ampdu_depth); | ||
664 | len += snprintf(buf + len, size - len, "%s: %3d ", | ||
665 | "pending", txq->pending_frames); | ||
666 | len += snprintf(buf + len, size - len, "%s: %d\n", | ||
667 | "stopped", txq->stopped); | ||
668 | |||
669 | ath_txq_unlock(sc, txq); | ||
670 | return len; | ||
671 | } | ||
672 | |||
610 | static ssize_t read_file_queues(struct file *file, char __user *user_buf, | 673 | static ssize_t read_file_queues(struct file *file, char __user *user_buf, |
611 | size_t count, loff_t *ppos) | 674 | size_t count, loff_t *ppos) |
612 | { | 675 | { |
@@ -624,24 +687,13 @@ static ssize_t read_file_queues(struct file *file, char __user *user_buf, | |||
624 | 687 | ||
625 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | 688 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
626 | txq = sc->tx.txq_map[i]; | 689 | txq = sc->tx.txq_map[i]; |
627 | len += snprintf(buf + len, size - len, "(%s): ", qname[i]); | 690 | len += snprintf(buf + len, size - len, "(%s): ", qname[i]); |
628 | 691 | len += print_queue(sc, txq, buf + len, size - len); | |
629 | ath_txq_lock(sc, txq); | ||
630 | |||
631 | len += snprintf(buf + len, size - len, "%s: %d ", | ||
632 | "qnum", txq->axq_qnum); | ||
633 | len += snprintf(buf + len, size - len, "%s: %2d ", | ||
634 | "qdepth", txq->axq_depth); | ||
635 | len += snprintf(buf + len, size - len, "%s: %2d ", | ||
636 | "ampdu-depth", txq->axq_ampdu_depth); | ||
637 | len += snprintf(buf + len, size - len, "%s: %3d ", | ||
638 | "pending", txq->pending_frames); | ||
639 | len += snprintf(buf + len, size - len, "%s: %d\n", | ||
640 | "stopped", txq->stopped); | ||
641 | |||
642 | ath_txq_unlock(sc, txq); | ||
643 | } | 692 | } |
644 | 693 | ||
694 | len += snprintf(buf + len, size - len, "(CAB): "); | ||
695 | len += print_queue(sc, sc->beacon.cabq, buf + len, size - len); | ||
696 | |||
645 | if (len > size) | 697 | if (len > size) |
646 | len = size; | 698 | len = size; |
647 | 699 | ||
@@ -1589,17 +1641,7 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, | |||
1589 | struct dentry *dir) | 1641 | struct dentry *dir) |
1590 | { | 1642 | { |
1591 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 1643 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
1592 | an->node_stat = debugfs_create_file("node_stat", S_IRUGO, | 1644 | debugfs_create_file("node_stat", S_IRUGO, dir, an, &fops_node_stat); |
1593 | dir, an, &fops_node_stat); | ||
1594 | } | ||
1595 | |||
1596 | void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw, | ||
1597 | struct ieee80211_vif *vif, | ||
1598 | struct ieee80211_sta *sta, | ||
1599 | struct dentry *dir) | ||
1600 | { | ||
1601 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | ||
1602 | debugfs_remove(an->node_stat); | ||
1603 | } | 1645 | } |
1604 | 1646 | ||
1605 | /* Ethtool support for get-stats */ | 1647 | /* Ethtool support for get-stats */ |
@@ -1770,10 +1812,10 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1770 | &fops_reset); | 1812 | &fops_reset); |
1771 | debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc, | 1813 | debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc, |
1772 | &fops_recv); | 1814 | &fops_recv); |
1773 | debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, | 1815 | debugfs_create_u8("rx_chainmask", S_IRUSR, sc->debug.debugfs_phy, |
1774 | sc->debug.debugfs_phy, sc, &fops_rx_chainmask); | 1816 | &ah->rxchainmask); |
1775 | debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, | 1817 | debugfs_create_u8("tx_chainmask", S_IRUSR, sc->debug.debugfs_phy, |
1776 | sc->debug.debugfs_phy, sc, &fops_tx_chainmask); | 1818 | &ah->txchainmask); |
1777 | debugfs_create_file("ani", S_IRUSR | S_IWUSR, | 1819 | debugfs_create_file("ani", S_IRUSR | S_IWUSR, |
1778 | sc->debug.debugfs_phy, sc, &fops_ani); | 1820 | sc->debug.debugfs_phy, sc, &fops_ani); |
1779 | debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | 1821 | debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
@@ -1814,9 +1856,11 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1814 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); | 1856 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); |
1815 | debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, | 1857 | debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, |
1816 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); | 1858 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); |
1817 | debugfs_create_file("diversity", S_IRUSR | S_IWUSR, | 1859 | debugfs_create_file("antenna_diversity", S_IRUSR, |
1818 | sc->debug.debugfs_phy, sc, &fops_ant_diversity); | 1860 | sc->debug.debugfs_phy, sc, &fops_antenna_diversity); |
1819 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 1861 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
1862 | debugfs_create_file("bt_ant_diversity", S_IRUSR | S_IWUSR, | ||
1863 | sc->debug.debugfs_phy, sc, &fops_bt_ant_diversity); | ||
1820 | debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, | 1864 | debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, |
1821 | &fops_btcoex); | 1865 | &fops_btcoex); |
1822 | #endif | 1866 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index fc679198a0f3..6e1556fa2f3e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -28,9 +28,13 @@ struct fft_sample_tlv; | |||
28 | #ifdef CONFIG_ATH9K_DEBUGFS | 28 | #ifdef CONFIG_ATH9K_DEBUGFS |
29 | #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ | 29 | #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ |
30 | #define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++ | 30 | #define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++ |
31 | #define ANT_STAT_INC(i, c) sc->debug.stats.ant_stats[i].c++ | ||
32 | #define ANT_LNA_INC(i, c) sc->debug.stats.ant_stats[i].lna_recv_cnt[c]++; | ||
31 | #else | 33 | #else |
32 | #define TX_STAT_INC(q, c) do { } while (0) | 34 | #define TX_STAT_INC(q, c) do { } while (0) |
33 | #define RESET_STAT_INC(sc, type) do { } while (0) | 35 | #define RESET_STAT_INC(sc, type) do { } while (0) |
36 | #define ANT_STAT_INC(i, c) do { } while (0) | ||
37 | #define ANT_LNA_INC(i, c) do { } while (0) | ||
34 | #endif | 38 | #endif |
35 | 39 | ||
36 | enum ath_reset_type { | 40 | enum ath_reset_type { |
@@ -243,11 +247,22 @@ struct ath_rx_stats { | |||
243 | u32 rx_spectral; | 247 | u32 rx_spectral; |
244 | }; | 248 | }; |
245 | 249 | ||
250 | #define ANT_MAIN 0 | ||
251 | #define ANT_ALT 1 | ||
252 | |||
253 | struct ath_antenna_stats { | ||
254 | u32 recv_cnt; | ||
255 | u32 rssi_avg; | ||
256 | u32 lna_recv_cnt[4]; | ||
257 | u32 lna_attempt_cnt[4]; | ||
258 | }; | ||
259 | |||
246 | struct ath_stats { | 260 | struct ath_stats { |
247 | struct ath_interrupt_stats istats; | 261 | struct ath_interrupt_stats istats; |
248 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; | 262 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; |
249 | struct ath_rx_stats rxstats; | 263 | struct ath_rx_stats rxstats; |
250 | struct ath_dfs_stats dfs_stats; | 264 | struct ath_dfs_stats dfs_stats; |
265 | struct ath_antenna_stats ant_stats[2]; | ||
251 | u32 reset[__RESET_TYPE_MAX]; | 266 | u32 reset[__RESET_TYPE_MAX]; |
252 | }; | 267 | }; |
253 | 268 | ||
@@ -277,14 +292,11 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, | |||
277 | struct ieee80211_vif *vif, | 292 | struct ieee80211_vif *vif, |
278 | struct ieee80211_sta *sta, | 293 | struct ieee80211_sta *sta, |
279 | struct dentry *dir); | 294 | struct dentry *dir); |
280 | void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw, | ||
281 | struct ieee80211_vif *vif, | ||
282 | struct ieee80211_sta *sta, | ||
283 | struct dentry *dir); | ||
284 | |||
285 | void ath_debug_send_fft_sample(struct ath_softc *sc, | 295 | void ath_debug_send_fft_sample(struct ath_softc *sc, |
286 | struct fft_sample_tlv *fft_sample); | 296 | struct fft_sample_tlv *fft_sample); |
287 | 297 | void ath9k_debug_stat_ant(struct ath_softc *sc, | |
298 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
299 | int main_rssi_avg, int alt_rssi_avg); | ||
288 | #else | 300 | #else |
289 | 301 | ||
290 | #define RX_STAT_INC(c) /* NOP */ | 302 | #define RX_STAT_INC(c) /* NOP */ |
@@ -297,12 +309,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah) | |||
297 | static inline void ath9k_deinit_debug(struct ath_softc *sc) | 309 | static inline void ath9k_deinit_debug(struct ath_softc *sc) |
298 | { | 310 | { |
299 | } | 311 | } |
300 | |||
301 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, | 312 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, |
302 | enum ath9k_int status) | 313 | enum ath9k_int status) |
303 | { | 314 | { |
304 | } | 315 | } |
305 | |||
306 | static inline void ath_debug_stat_tx(struct ath_softc *sc, | 316 | static inline void ath_debug_stat_tx(struct ath_softc *sc, |
307 | struct ath_buf *bf, | 317 | struct ath_buf *bf, |
308 | struct ath_tx_status *ts, | 318 | struct ath_tx_status *ts, |
@@ -310,11 +320,16 @@ static inline void ath_debug_stat_tx(struct ath_softc *sc, | |||
310 | unsigned int flags) | 320 | unsigned int flags) |
311 | { | 321 | { |
312 | } | 322 | } |
313 | |||
314 | static inline void ath_debug_stat_rx(struct ath_softc *sc, | 323 | static inline void ath_debug_stat_rx(struct ath_softc *sc, |
315 | struct ath_rx_status *rs) | 324 | struct ath_rx_status *rs) |
316 | { | 325 | { |
317 | } | 326 | } |
327 | static inline void ath9k_debug_stat_ant(struct ath_softc *sc, | ||
328 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
329 | int main_rssi_avg, int alt_rssi_avg) | ||
330 | { | ||
331 | |||
332 | } | ||
318 | 333 | ||
319 | #endif /* CONFIG_ATH9K_DEBUGFS */ | 334 | #endif /* CONFIG_ATH9K_DEBUGFS */ |
320 | 335 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index c2bfd748eed8..9ea8e4b779c9 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -812,6 +812,7 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | |||
812 | static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | 812 | static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, |
813 | struct ath9k_channel *chan) | 813 | struct ath9k_channel *chan) |
814 | { | 814 | { |
815 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
815 | struct modal_eep_4k_header *pModal; | 816 | struct modal_eep_4k_header *pModal; |
816 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | 817 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; |
817 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; | 818 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; |
@@ -858,6 +859,24 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
858 | 859 | ||
859 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); | 860 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); |
860 | regVal = REG_READ(ah, AR_PHY_CCK_DETECT); | 861 | regVal = REG_READ(ah, AR_PHY_CCK_DETECT); |
862 | |||
863 | if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) { | ||
864 | /* | ||
865 | * If diversity combining is enabled, | ||
866 | * set MAIN to LNA1 and ALT to LNA2 initially. | ||
867 | */ | ||
868 | regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
869 | regVal &= (~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | | ||
870 | AR_PHY_9285_ANT_DIV_ALT_LNACONF)); | ||
871 | |||
872 | regVal |= (ATH_ANT_DIV_COMB_LNA1 << | ||
873 | AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S); | ||
874 | regVal |= (ATH_ANT_DIV_COMB_LNA2 << | ||
875 | AR_PHY_9285_ANT_DIV_ALT_LNACONF_S); | ||
876 | regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS)); | ||
877 | regVal |= (0 << AR_PHY_9285_FAST_DIV_BIAS_S); | ||
878 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); | ||
879 | } | ||
861 | } | 880 | } |
862 | 881 | ||
863 | if (pModal->version >= 2) { | 882 | if (pModal->version >= 2) { |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 5205a3625e84..6d5d716adc1b 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -115,10 +115,10 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | |||
115 | cmd->skb = skb; | 115 | cmd->skb = skb; |
116 | cmd->hif_dev = hif_dev; | 116 | cmd->hif_dev = hif_dev; |
117 | 117 | ||
118 | usb_fill_bulk_urb(urb, hif_dev->udev, | 118 | usb_fill_int_urb(urb, hif_dev->udev, |
119 | usb_sndbulkpipe(hif_dev->udev, USB_REG_OUT_PIPE), | 119 | usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE), |
120 | skb->data, skb->len, | 120 | skb->data, skb->len, |
121 | hif_usb_regout_cb, cmd); | 121 | hif_usb_regout_cb, cmd, 1); |
122 | 122 | ||
123 | usb_anchor_urb(urb, &hif_dev->regout_submitted); | 123 | usb_anchor_urb(urb, &hif_dev->regout_submitted); |
124 | ret = usb_submit_urb(urb, GFP_KERNEL); | 124 | ret = usb_submit_urb(urb, GFP_KERNEL); |
@@ -723,11 +723,11 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
723 | return; | 723 | return; |
724 | } | 724 | } |
725 | 725 | ||
726 | usb_fill_bulk_urb(urb, hif_dev->udev, | 726 | usb_fill_int_urb(urb, hif_dev->udev, |
727 | usb_rcvbulkpipe(hif_dev->udev, | 727 | usb_rcvintpipe(hif_dev->udev, |
728 | USB_REG_IN_PIPE), | 728 | USB_REG_IN_PIPE), |
729 | nskb->data, MAX_REG_IN_BUF_SIZE, | 729 | nskb->data, MAX_REG_IN_BUF_SIZE, |
730 | ath9k_hif_usb_reg_in_cb, nskb); | 730 | ath9k_hif_usb_reg_in_cb, nskb, 1); |
731 | } | 731 | } |
732 | 732 | ||
733 | resubmit: | 733 | resubmit: |
@@ -909,11 +909,11 @@ static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev) | |||
909 | goto err_skb; | 909 | goto err_skb; |
910 | } | 910 | } |
911 | 911 | ||
912 | usb_fill_bulk_urb(urb, hif_dev->udev, | 912 | usb_fill_int_urb(urb, hif_dev->udev, |
913 | usb_rcvbulkpipe(hif_dev->udev, | 913 | usb_rcvintpipe(hif_dev->udev, |
914 | USB_REG_IN_PIPE), | 914 | USB_REG_IN_PIPE), |
915 | skb->data, MAX_REG_IN_BUF_SIZE, | 915 | skb->data, MAX_REG_IN_BUF_SIZE, |
916 | ath9k_hif_usb_reg_in_cb, skb); | 916 | ath9k_hif_usb_reg_in_cb, skb, 1); |
917 | 917 | ||
918 | /* Anchor URB */ | 918 | /* Anchor URB */ |
919 | usb_anchor_urb(urb, &hif_dev->reg_in_submitted); | 919 | usb_anchor_urb(urb, &hif_dev->reg_in_submitted); |
@@ -1031,9 +1031,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
1031 | 1031 | ||
1032 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) | 1032 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) |
1033 | { | 1033 | { |
1034 | struct usb_host_interface *alt = &hif_dev->interface->altsetting[0]; | 1034 | int ret; |
1035 | struct usb_endpoint_descriptor *endp; | ||
1036 | int ret, idx; | ||
1037 | 1035 | ||
1038 | ret = ath9k_hif_usb_download_fw(hif_dev); | 1036 | ret = ath9k_hif_usb_download_fw(hif_dev); |
1039 | if (ret) { | 1037 | if (ret) { |
@@ -1043,20 +1041,6 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) | |||
1043 | return ret; | 1041 | return ret; |
1044 | } | 1042 | } |
1045 | 1043 | ||
1046 | /* On downloading the firmware to the target, the USB descriptor of EP4 | ||
1047 | * is 'patched' to change the type of the endpoint to Bulk. This will | ||
1048 | * bring down CPU usage during the scan period. | ||
1049 | */ | ||
1050 | for (idx = 0; idx < alt->desc.bNumEndpoints; idx++) { | ||
1051 | endp = &alt->endpoint[idx].desc; | ||
1052 | if ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
1053 | == USB_ENDPOINT_XFER_INT) { | ||
1054 | endp->bmAttributes &= ~USB_ENDPOINT_XFERTYPE_MASK; | ||
1055 | endp->bmAttributes |= USB_ENDPOINT_XFER_BULK; | ||
1056 | endp->bInterval = 0; | ||
1057 | } | ||
1058 | } | ||
1059 | |||
1060 | /* Alloc URBs */ | 1044 | /* Alloc URBs */ |
1061 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); | 1045 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); |
1062 | if (ret) { | 1046 | if (ret) { |
@@ -1268,7 +1252,7 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev) | |||
1268 | if (!buf) | 1252 | if (!buf) |
1269 | return; | 1253 | return; |
1270 | 1254 | ||
1271 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE), | 1255 | ret = usb_interrupt_msg(udev, usb_sndintpipe(udev, USB_REG_OUT_PIPE), |
1272 | buf, 4, NULL, HZ); | 1256 | buf, 4, NULL, HZ); |
1273 | if (ret) | 1257 | if (ret) |
1274 | dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n"); | 1258 | dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 5c1bec18c9e3..d44258172c0f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1203,16 +1203,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1203 | 1203 | ||
1204 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) { | 1204 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) { |
1205 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; | 1205 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; |
1206 | enum nl80211_channel_type channel_type = | ||
1207 | cfg80211_get_chandef_type(&hw->conf.chandef); | ||
1208 | int pos = curchan->hw_value; | 1206 | int pos = curchan->hw_value; |
1209 | 1207 | ||
1210 | ath_dbg(common, CONFIG, "Set channel: %d MHz\n", | 1208 | ath_dbg(common, CONFIG, "Set channel: %d MHz\n", |
1211 | curchan->center_freq); | 1209 | curchan->center_freq); |
1212 | 1210 | ||
1213 | ath9k_cmn_update_ichannel(&priv->ah->channels[pos], | 1211 | ath9k_cmn_update_ichannel(&priv->ah->channels[pos], |
1214 | hw->conf.chandef.chan, | 1212 | &hw->conf.chandef); |
1215 | channel_type); | ||
1216 | 1213 | ||
1217 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { | 1214 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { |
1218 | ath_err(common, "Unable to set channel\n"); | 1215 | ath_err(common, "Unable to set channel\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 14b701140b49..83f4927aeaca 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -78,13 +78,16 @@ static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | |||
78 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); | 78 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); |
79 | } | 79 | } |
80 | 80 | ||
81 | static inline void ath9k_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah, | 81 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
82 | bool enable) | 82 | |
83 | static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) | ||
83 | { | 84 | { |
84 | if (ath9k_hw_ops(ah)->antctrl_shared_chain_lnadiv) | 85 | if (ath9k_hw_ops(ah)->set_bt_ant_diversity) |
85 | ath9k_hw_ops(ah)->antctrl_shared_chain_lnadiv(ah, enable); | 86 | ath9k_hw_ops(ah)->set_bt_ant_diversity(ah, enable); |
86 | } | 87 | } |
87 | 88 | ||
89 | #endif | ||
90 | |||
88 | /* Private hardware call ops */ | 91 | /* Private hardware call ops */ |
89 | 92 | ||
90 | /* PHY ops */ | 93 | /* PHY ops */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4ca0cb060106..ecc6ec4a1edb 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -450,7 +450,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
450 | ah->config.ack_6mb = 0x0; | 450 | ah->config.ack_6mb = 0x0; |
451 | ah->config.cwm_ignore_extcca = 0; | 451 | ah->config.cwm_ignore_extcca = 0; |
452 | ah->config.pcie_clock_req = 0; | 452 | ah->config.pcie_clock_req = 0; |
453 | ah->config.pcie_waen = 0; | ||
454 | ah->config.analog_shiftreg = 1; | 453 | ah->config.analog_shiftreg = 1; |
455 | 454 | ||
456 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | 455 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
@@ -575,18 +574,17 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
575 | * We need to do this to avoid RMW of this register. We cannot | 574 | * We need to do this to avoid RMW of this register. We cannot |
576 | * read the reg when chip is asleep. | 575 | * read the reg when chip is asleep. |
577 | */ | 576 | */ |
578 | ah->WARegVal = REG_READ(ah, AR_WA); | 577 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
579 | ah->WARegVal |= (AR_WA_D3_L1_DISABLE | | 578 | ah->WARegVal = REG_READ(ah, AR_WA); |
580 | AR_WA_ASPM_TIMER_BASED_DISABLE); | 579 | ah->WARegVal |= (AR_WA_D3_L1_DISABLE | |
580 | AR_WA_ASPM_TIMER_BASED_DISABLE); | ||
581 | } | ||
581 | 582 | ||
582 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { | 583 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { |
583 | ath_err(common, "Couldn't reset chip\n"); | 584 | ath_err(common, "Couldn't reset chip\n"); |
584 | return -EIO; | 585 | return -EIO; |
585 | } | 586 | } |
586 | 587 | ||
587 | if (AR_SREV_9462(ah)) | ||
588 | ah->WARegVal &= ~AR_WA_D3_L1_DISABLE; | ||
589 | |||
590 | if (AR_SREV_9565(ah)) { | 588 | if (AR_SREV_9565(ah)) { |
591 | ah->WARegVal |= AR_WA_BIT22; | 589 | ah->WARegVal |= AR_WA_BIT22; |
592 | REG_WRITE(ah, AR_WA, ah->WARegVal); | 590 | REG_WRITE(ah, AR_WA, ah->WARegVal); |
@@ -656,8 +654,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
656 | ath9k_hw_init_cal_settings(ah); | 654 | ath9k_hw_init_cal_settings(ah); |
657 | 655 | ||
658 | ah->ani_function = ATH9K_ANI_ALL; | 656 | ah->ani_function = ATH9K_ANI_ALL; |
659 | if (AR_SREV_9280_20_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) | ||
660 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | ||
661 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 657 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
662 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; | 658 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; |
663 | 659 | ||
@@ -1069,7 +1065,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
1069 | if (IS_CHAN_A_FAST_CLOCK(ah, chan)) | 1065 | if (IS_CHAN_A_FAST_CLOCK(ah, chan)) |
1070 | tx_lat += 11; | 1066 | tx_lat += 11; |
1071 | 1067 | ||
1072 | sifstime *= 2; | 1068 | sifstime = 32; |
1073 | ack_offset = 16; | 1069 | ack_offset = 16; |
1074 | slottime = 13; | 1070 | slottime = 13; |
1075 | } else if (IS_CHAN_QUARTER_RATE(chan)) { | 1071 | } else if (IS_CHAN_QUARTER_RATE(chan)) { |
@@ -1079,7 +1075,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
1079 | if (IS_CHAN_A_FAST_CLOCK(ah, chan)) | 1075 | if (IS_CHAN_A_FAST_CLOCK(ah, chan)) |
1080 | tx_lat += 22; | 1076 | tx_lat += 22; |
1081 | 1077 | ||
1082 | sifstime *= 4; | 1078 | sifstime = 64; |
1083 | ack_offset = 32; | 1079 | ack_offset = 32; |
1084 | slottime = 21; | 1080 | slottime = 21; |
1085 | } else { | 1081 | } else { |
@@ -1116,7 +1112,6 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
1116 | ctstimeout += 48 - sifstime - ah->slottime; | 1112 | ctstimeout += 48 - sifstime - ah->slottime; |
1117 | } | 1113 | } |
1118 | 1114 | ||
1119 | |||
1120 | ath9k_hw_set_sifs_time(ah, sifstime); | 1115 | ath9k_hw_set_sifs_time(ah, sifstime); |
1121 | ath9k_hw_setslottime(ah, slottime); | 1116 | ath9k_hw_setslottime(ah, slottime); |
1122 | ath9k_hw_set_ack_timeout(ah, acktimeout); | 1117 | ath9k_hw_set_ack_timeout(ah, acktimeout); |
@@ -1496,16 +1491,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1496 | struct ath9k_channel *chan) | 1491 | struct ath9k_channel *chan) |
1497 | { | 1492 | { |
1498 | struct ath_common *common = ath9k_hw_common(ah); | 1493 | struct ath_common *common = ath9k_hw_common(ah); |
1494 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1495 | bool band_switch = false, mode_diff = false; | ||
1496 | u8 ini_reloaded = 0; | ||
1499 | u32 qnum; | 1497 | u32 qnum; |
1500 | int r; | 1498 | int r; |
1501 | bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); | ||
1502 | bool band_switch, mode_diff; | ||
1503 | u8 ini_reloaded; | ||
1504 | 1499 | ||
1505 | band_switch = (chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ)) != | 1500 | if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { |
1506 | (ah->curchan->channelFlags & (CHANNEL_2GHZ | | 1501 | u32 cur = ah->curchan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ); |
1507 | CHANNEL_5GHZ)); | 1502 | u32 new = chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ); |
1508 | mode_diff = (chan->chanmode != ah->curchan->chanmode); | 1503 | band_switch = (cur != new); |
1504 | mode_diff = (chan->chanmode != ah->curchan->chanmode); | ||
1505 | } | ||
1509 | 1506 | ||
1510 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { | 1507 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { |
1511 | if (ath9k_hw_numtxpending(ah, qnum)) { | 1508 | if (ath9k_hw_numtxpending(ah, qnum)) { |
@@ -1520,11 +1517,12 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1520 | return false; | 1517 | return false; |
1521 | } | 1518 | } |
1522 | 1519 | ||
1523 | if (edma && (band_switch || mode_diff)) { | 1520 | if (band_switch || mode_diff) { |
1524 | ath9k_hw_mark_phy_inactive(ah); | 1521 | ath9k_hw_mark_phy_inactive(ah); |
1525 | udelay(5); | 1522 | udelay(5); |
1526 | 1523 | ||
1527 | ath9k_hw_init_pll(ah, NULL); | 1524 | if (band_switch) |
1525 | ath9k_hw_init_pll(ah, chan); | ||
1528 | 1526 | ||
1529 | if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) { | 1527 | if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) { |
1530 | ath_err(common, "Failed to do fast channel change\n"); | 1528 | ath_err(common, "Failed to do fast channel change\n"); |
@@ -1541,22 +1539,21 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1541 | } | 1539 | } |
1542 | ath9k_hw_set_clockrate(ah); | 1540 | ath9k_hw_set_clockrate(ah); |
1543 | ath9k_hw_apply_txpower(ah, chan, false); | 1541 | ath9k_hw_apply_txpower(ah, chan, false); |
1544 | ath9k_hw_rfbus_done(ah); | ||
1545 | 1542 | ||
1546 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | 1543 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) |
1547 | ath9k_hw_set_delta_slope(ah, chan); | 1544 | ath9k_hw_set_delta_slope(ah, chan); |
1548 | 1545 | ||
1549 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1546 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1550 | 1547 | ||
1551 | if (edma && (band_switch || mode_diff)) { | 1548 | if (band_switch || ini_reloaded) |
1552 | ah->ah_flags |= AH_FASTCC; | 1549 | ah->eep_ops->set_board_values(ah, chan); |
1553 | if (band_switch || ini_reloaded) | ||
1554 | ah->eep_ops->set_board_values(ah, chan); | ||
1555 | 1550 | ||
1556 | ath9k_hw_init_bb(ah, chan); | 1551 | ath9k_hw_init_bb(ah, chan); |
1552 | ath9k_hw_rfbus_done(ah); | ||
1557 | 1553 | ||
1558 | if (band_switch || ini_reloaded) | 1554 | if (band_switch || ini_reloaded) { |
1559 | ath9k_hw_init_cal(ah, chan); | 1555 | ah->ah_flags |= AH_FASTCC; |
1556 | ath9k_hw_init_cal(ah, chan); | ||
1560 | ah->ah_flags &= ~AH_FASTCC; | 1557 | ah->ah_flags &= ~AH_FASTCC; |
1561 | } | 1558 | } |
1562 | 1559 | ||
@@ -1778,16 +1775,11 @@ static void ath9k_hw_init_desc(struct ath_hw *ah) | |||
1778 | /* | 1775 | /* |
1779 | * Fast channel change: | 1776 | * Fast channel change: |
1780 | * (Change synthesizer based on channel freq without resetting chip) | 1777 | * (Change synthesizer based on channel freq without resetting chip) |
1781 | * | ||
1782 | * Don't do FCC when | ||
1783 | * - Flag is not set | ||
1784 | * - Chip is just coming out of full sleep | ||
1785 | * - Channel to be set is same as current channel | ||
1786 | * - Channel flags are different, (eg.,moving from 2GHz to 5GHz channel) | ||
1787 | */ | 1778 | */ |
1788 | static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | 1779 | static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) |
1789 | { | 1780 | { |
1790 | struct ath_common *common = ath9k_hw_common(ah); | 1781 | struct ath_common *common = ath9k_hw_common(ah); |
1782 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1791 | int ret; | 1783 | int ret; |
1792 | 1784 | ||
1793 | if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) | 1785 | if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) |
@@ -1806,9 +1798,21 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1806 | (CHANNEL_HALF | CHANNEL_QUARTER)) | 1798 | (CHANNEL_HALF | CHANNEL_QUARTER)) |
1807 | goto fail; | 1799 | goto fail; |
1808 | 1800 | ||
1809 | if ((chan->channelFlags & CHANNEL_ALL) != | 1801 | /* |
1810 | (ah->curchan->channelFlags & CHANNEL_ALL)) | 1802 | * If cross-band fcc is not supoprted, bail out if |
1811 | goto fail; | 1803 | * either channelFlags or chanmode differ. |
1804 | * | ||
1805 | * chanmode will be different if the HT operating mode | ||
1806 | * changes because of CSA. | ||
1807 | */ | ||
1808 | if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH)) { | ||
1809 | if ((chan->channelFlags & CHANNEL_ALL) != | ||
1810 | (ah->curchan->channelFlags & CHANNEL_ALL)) | ||
1811 | goto fail; | ||
1812 | |||
1813 | if (chan->chanmode != ah->curchan->chanmode) | ||
1814 | goto fail; | ||
1815 | } | ||
1812 | 1816 | ||
1813 | if (!ath9k_hw_check_alive(ah)) | 1817 | if (!ath9k_hw_check_alive(ah)) |
1814 | goto fail; | 1818 | goto fail; |
@@ -2047,7 +2051,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2047 | 2051 | ||
2048 | ath9k_hw_apply_gpio_override(ah); | 2052 | ath9k_hw_apply_gpio_override(ah); |
2049 | 2053 | ||
2050 | if (AR_SREV_9565(ah) && ah->shared_chain_lnadiv) | 2054 | if (AR_SREV_9565(ah) && common->bt_ant_diversity) |
2051 | REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); | 2055 | REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); |
2052 | 2056 | ||
2053 | return 0; | 2057 | return 0; |
@@ -2504,7 +2508,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2504 | else | 2508 | else |
2505 | pCap->rts_aggr_limit = (8 * 1024); | 2509 | pCap->rts_aggr_limit = (8 * 1024); |
2506 | 2510 | ||
2507 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | 2511 | #ifdef CONFIG_ATH9K_RFKILL |
2508 | ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); | 2512 | ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); |
2509 | if (ah->rfsilent & EEP_RFSILENT_ENABLED) { | 2513 | if (ah->rfsilent & EEP_RFSILENT_ENABLED) { |
2510 | ah->rfkill_gpio = | 2514 | ah->rfkill_gpio = |
@@ -2550,34 +2554,28 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2550 | if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) | 2554 | if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) |
2551 | pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; | 2555 | pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; |
2552 | 2556 | ||
2553 | if (AR_SREV_9285(ah)) | 2557 | if (AR_SREV_9285(ah)) { |
2554 | if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) { | 2558 | if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) { |
2555 | ant_div_ctl1 = | 2559 | ant_div_ctl1 = |
2556 | ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | 2560 | ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); |
2557 | if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) | 2561 | if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) { |
2558 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; | 2562 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; |
2563 | ath_info(common, "Enable LNA combining\n"); | ||
2564 | } | ||
2559 | } | 2565 | } |
2566 | } | ||
2567 | |||
2560 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 2568 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
2561 | if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE)) | 2569 | if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE)) |
2562 | pCap->hw_caps |= ATH9K_HW_CAP_APM; | 2570 | pCap->hw_caps |= ATH9K_HW_CAP_APM; |
2563 | } | 2571 | } |
2564 | 2572 | ||
2565 | |||
2566 | if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) { | 2573 | if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) { |
2567 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | 2574 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); |
2568 | /* | 2575 | if ((ant_div_ctl1 >> 0x6) == 0x3) { |
2569 | * enable the diversity-combining algorithm only when | ||
2570 | * both enable_lna_div and enable_fast_div are set | ||
2571 | * Table for Diversity | ||
2572 | * ant_div_alt_lnaconf bit 0-1 | ||
2573 | * ant_div_main_lnaconf bit 2-3 | ||
2574 | * ant_div_alt_gaintb bit 4 | ||
2575 | * ant_div_main_gaintb bit 5 | ||
2576 | * enable_ant_div_lnadiv bit 6 | ||
2577 | * enable_ant_fast_div bit 7 | ||
2578 | */ | ||
2579 | if ((ant_div_ctl1 >> 0x6) == 0x3) | ||
2580 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; | 2576 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; |
2577 | ath_info(common, "Enable LNA combining\n"); | ||
2578 | } | ||
2581 | } | 2579 | } |
2582 | 2580 | ||
2583 | if (ath9k_hw_dfs_tested(ah)) | 2581 | if (ath9k_hw_dfs_tested(ah)) |
@@ -2610,6 +2608,13 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2610 | ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) | 2608 | ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) |
2611 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; | 2609 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; |
2612 | 2610 | ||
2611 | /* | ||
2612 | * Fast channel change across bands is available | ||
2613 | * only for AR9462 and AR9565. | ||
2614 | */ | ||
2615 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) | ||
2616 | pCap->hw_caps |= ATH9K_HW_CAP_FCC_BAND_SWITCH; | ||
2617 | |||
2613 | return 0; | 2618 | return 0; |
2614 | } | 2619 | } |
2615 | 2620 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index cd74b3afef7d..69a907b55a73 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -247,6 +247,8 @@ enum ath9k_hw_caps { | |||
247 | ATH9K_HW_CAP_DFS = BIT(16), | 247 | ATH9K_HW_CAP_DFS = BIT(16), |
248 | ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17), | 248 | ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17), |
249 | ATH9K_HW_CAP_PAPRD = BIT(18), | 249 | ATH9K_HW_CAP_PAPRD = BIT(18), |
250 | ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(19), | ||
251 | ATH9K_HW_CAP_BT_ANT_DIV = BIT(20), | ||
250 | }; | 252 | }; |
251 | 253 | ||
252 | /* | 254 | /* |
@@ -309,8 +311,11 @@ struct ath9k_ops_config { | |||
309 | u16 ani_poll_interval; /* ANI poll interval in ms */ | 311 | u16 ani_poll_interval; /* ANI poll interval in ms */ |
310 | 312 | ||
311 | /* Platform specific config */ | 313 | /* Platform specific config */ |
314 | u32 aspm_l1_fix; | ||
312 | u32 xlna_gpio; | 315 | u32 xlna_gpio; |
316 | u32 ant_ctrl_comm2g_switch_enable; | ||
313 | bool xatten_margin_cfg; | 317 | bool xatten_margin_cfg; |
318 | bool alt_mingainidx; | ||
314 | }; | 319 | }; |
315 | 320 | ||
316 | enum ath9k_int { | 321 | enum ath9k_int { |
@@ -716,11 +721,14 @@ struct ath_hw_ops { | |||
716 | struct ath_hw_antcomb_conf *antconf); | 721 | struct ath_hw_antcomb_conf *antconf); |
717 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, | 722 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, |
718 | struct ath_hw_antcomb_conf *antconf); | 723 | struct ath_hw_antcomb_conf *antconf); |
719 | void (*antctrl_shared_chain_lnadiv)(struct ath_hw *hw, bool enable); | ||
720 | void (*spectral_scan_config)(struct ath_hw *ah, | 724 | void (*spectral_scan_config)(struct ath_hw *ah, |
721 | struct ath_spec_scan *param); | 725 | struct ath_spec_scan *param); |
722 | void (*spectral_scan_trigger)(struct ath_hw *ah); | 726 | void (*spectral_scan_trigger)(struct ath_hw *ah); |
723 | void (*spectral_scan_wait)(struct ath_hw *ah); | 727 | void (*spectral_scan_wait)(struct ath_hw *ah); |
728 | |||
729 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | ||
730 | void (*set_bt_ant_diversity)(struct ath_hw *hw, bool enable); | ||
731 | #endif | ||
724 | }; | 732 | }; |
725 | 733 | ||
726 | struct ath_nf_limits { | 734 | struct ath_nf_limits { |
@@ -765,7 +773,6 @@ struct ath_hw { | |||
765 | bool aspm_enabled; | 773 | bool aspm_enabled; |
766 | bool is_monitoring; | 774 | bool is_monitoring; |
767 | bool need_an_top2_fixup; | 775 | bool need_an_top2_fixup; |
768 | bool shared_chain_lnadiv; | ||
769 | u16 tx_trig_level; | 776 | u16 tx_trig_level; |
770 | 777 | ||
771 | u32 nf_regs[6]; | 778 | u32 nf_regs[6]; |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 026a2a067b46..9a1f349f9260 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -53,9 +53,9 @@ static int ath9k_btcoex_enable; | |||
53 | module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); | 53 | module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); |
54 | MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); | 54 | MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); |
55 | 55 | ||
56 | static int ath9k_enable_diversity; | 56 | static int ath9k_bt_ant_diversity; |
57 | module_param_named(enable_diversity, ath9k_enable_diversity, int, 0444); | 57 | module_param_named(bt_ant_diversity, ath9k_bt_ant_diversity, int, 0444); |
58 | MODULE_PARM_DESC(enable_diversity, "Enable Antenna diversity for AR9565"); | 58 | MODULE_PARM_DESC(bt_ant_diversity, "Enable WLAN/BT RX antenna diversity"); |
59 | 59 | ||
60 | bool is_ath9k_unloaded; | 60 | bool is_ath9k_unloaded; |
61 | /* We use the hw_value as an index into our private channel structure */ | 61 | /* We use the hw_value as an index into our private channel structure */ |
@@ -146,14 +146,22 @@ static struct ieee80211_rate ath9k_legacy_rates[] = { | |||
146 | RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), | 146 | RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), |
147 | RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), | 147 | RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), |
148 | RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), | 148 | RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), |
149 | RATE(60, 0x0b, 0), | 149 | RATE(60, 0x0b, (IEEE80211_RATE_SUPPORTS_5MHZ | |
150 | RATE(90, 0x0f, 0), | 150 | IEEE80211_RATE_SUPPORTS_10MHZ)), |
151 | RATE(120, 0x0a, 0), | 151 | RATE(90, 0x0f, (IEEE80211_RATE_SUPPORTS_5MHZ | |
152 | RATE(180, 0x0e, 0), | 152 | IEEE80211_RATE_SUPPORTS_10MHZ)), |
153 | RATE(240, 0x09, 0), | 153 | RATE(120, 0x0a, (IEEE80211_RATE_SUPPORTS_5MHZ | |
154 | RATE(360, 0x0d, 0), | 154 | IEEE80211_RATE_SUPPORTS_10MHZ)), |
155 | RATE(480, 0x08, 0), | 155 | RATE(180, 0x0e, (IEEE80211_RATE_SUPPORTS_5MHZ | |
156 | RATE(540, 0x0c, 0), | 156 | IEEE80211_RATE_SUPPORTS_10MHZ)), |
157 | RATE(240, 0x09, (IEEE80211_RATE_SUPPORTS_5MHZ | | ||
158 | IEEE80211_RATE_SUPPORTS_10MHZ)), | ||
159 | RATE(360, 0x0d, (IEEE80211_RATE_SUPPORTS_5MHZ | | ||
160 | IEEE80211_RATE_SUPPORTS_10MHZ)), | ||
161 | RATE(480, 0x08, (IEEE80211_RATE_SUPPORTS_5MHZ | | ||
162 | IEEE80211_RATE_SUPPORTS_10MHZ)), | ||
163 | RATE(540, 0x0c, (IEEE80211_RATE_SUPPORTS_5MHZ | | ||
164 | IEEE80211_RATE_SUPPORTS_10MHZ)), | ||
157 | }; | 165 | }; |
158 | 166 | ||
159 | #ifdef CONFIG_MAC80211_LEDS | 167 | #ifdef CONFIG_MAC80211_LEDS |
@@ -516,6 +524,7 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
516 | static void ath9k_init_platform(struct ath_softc *sc) | 524 | static void ath9k_init_platform(struct ath_softc *sc) |
517 | { | 525 | { |
518 | struct ath_hw *ah = sc->sc_ah; | 526 | struct ath_hw *ah = sc->sc_ah; |
527 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
519 | struct ath_common *common = ath9k_hw_common(ah); | 528 | struct ath_common *common = ath9k_hw_common(ah); |
520 | 529 | ||
521 | if (common->bus_ops->ath_bus_type != ATH_PCI) | 530 | if (common->bus_ops->ath_bus_type != ATH_PCI) |
@@ -525,12 +534,27 @@ static void ath9k_init_platform(struct ath_softc *sc) | |||
525 | ATH9K_PCI_CUS230)) { | 534 | ATH9K_PCI_CUS230)) { |
526 | ah->config.xlna_gpio = 9; | 535 | ah->config.xlna_gpio = 9; |
527 | ah->config.xatten_margin_cfg = true; | 536 | ah->config.xatten_margin_cfg = true; |
537 | ah->config.alt_mingainidx = true; | ||
538 | ah->config.ant_ctrl_comm2g_switch_enable = 0x000BBB88; | ||
539 | sc->ant_comb.low_rssi_thresh = 20; | ||
540 | sc->ant_comb.fast_div_bias = 3; | ||
528 | 541 | ||
529 | ath_info(common, "Set parameters for %s\n", | 542 | ath_info(common, "Set parameters for %s\n", |
530 | (sc->driver_data & ATH9K_PCI_CUS198) ? | 543 | (sc->driver_data & ATH9K_PCI_CUS198) ? |
531 | "CUS198" : "CUS230"); | 544 | "CUS198" : "CUS230"); |
532 | } else if (sc->driver_data & ATH9K_PCI_CUS217) { | 545 | } |
546 | |||
547 | if (sc->driver_data & ATH9K_PCI_CUS217) | ||
533 | ath_info(common, "CUS217 card detected\n"); | 548 | ath_info(common, "CUS217 card detected\n"); |
549 | |||
550 | if (sc->driver_data & ATH9K_PCI_BT_ANT_DIV) { | ||
551 | pCap->hw_caps |= ATH9K_HW_CAP_BT_ANT_DIV; | ||
552 | ath_info(common, "Set BT/WLAN RX diversity capability\n"); | ||
553 | } | ||
554 | |||
555 | if (sc->driver_data & ATH9K_PCI_D3_L1_WAR) { | ||
556 | ah->config.pcie_waen = 0x0040473b; | ||
557 | ath_info(common, "Enable WAR for ASPM D3/L1\n"); | ||
534 | } | 558 | } |
535 | } | 559 | } |
536 | 560 | ||
@@ -584,6 +608,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
584 | { | 608 | { |
585 | struct ath9k_platform_data *pdata = sc->dev->platform_data; | 609 | struct ath9k_platform_data *pdata = sc->dev->platform_data; |
586 | struct ath_hw *ah = NULL; | 610 | struct ath_hw *ah = NULL; |
611 | struct ath9k_hw_capabilities *pCap; | ||
587 | struct ath_common *common; | 612 | struct ath_common *common; |
588 | int ret = 0, i; | 613 | int ret = 0, i; |
589 | int csz = 0; | 614 | int csz = 0; |
@@ -600,6 +625,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
600 | ah->reg_ops.rmw = ath9k_reg_rmw; | 625 | ah->reg_ops.rmw = ath9k_reg_rmw; |
601 | atomic_set(&ah->intr_ref_cnt, -1); | 626 | atomic_set(&ah->intr_ref_cnt, -1); |
602 | sc->sc_ah = ah; | 627 | sc->sc_ah = ah; |
628 | pCap = &ah->caps; | ||
603 | 629 | ||
604 | sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET); | 630 | sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET); |
605 | 631 | ||
@@ -631,11 +657,15 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
631 | ath9k_init_platform(sc); | 657 | ath9k_init_platform(sc); |
632 | 658 | ||
633 | /* | 659 | /* |
634 | * Enable Antenna diversity only when BTCOEX is disabled | 660 | * Enable WLAN/BT RX Antenna diversity only when: |
635 | * and the user manually requests the feature. | 661 | * |
662 | * - BTCOEX is disabled. | ||
663 | * - the user manually requests the feature. | ||
664 | * - the HW cap is set using the platform data. | ||
636 | */ | 665 | */ |
637 | if (!common->btcoex_enabled && ath9k_enable_diversity) | 666 | if (!common->btcoex_enabled && ath9k_bt_ant_diversity && |
638 | common->antenna_diversity = 1; | 667 | (pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV)) |
668 | common->bt_ant_diversity = 1; | ||
639 | 669 | ||
640 | spin_lock_init(&common->cc_lock); | 670 | spin_lock_init(&common->cc_lock); |
641 | 671 | ||
@@ -710,13 +740,15 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band) | |||
710 | struct ieee80211_supported_band *sband; | 740 | struct ieee80211_supported_band *sband; |
711 | struct ieee80211_channel *chan; | 741 | struct ieee80211_channel *chan; |
712 | struct ath_hw *ah = sc->sc_ah; | 742 | struct ath_hw *ah = sc->sc_ah; |
743 | struct cfg80211_chan_def chandef; | ||
713 | int i; | 744 | int i; |
714 | 745 | ||
715 | sband = &sc->sbands[band]; | 746 | sband = &sc->sbands[band]; |
716 | for (i = 0; i < sband->n_channels; i++) { | 747 | for (i = 0; i < sband->n_channels; i++) { |
717 | chan = &sband->channels[i]; | 748 | chan = &sband->channels[i]; |
718 | ah->curchan = &ah->channels[chan->hw_value]; | 749 | ah->curchan = &ah->channels[chan->hw_value]; |
719 | ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20); | 750 | cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); |
751 | ath9k_cmn_update_ichannel(ah->curchan, &chandef); | ||
720 | ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); | 752 | ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); |
721 | } | 753 | } |
722 | } | 754 | } |
@@ -835,6 +867,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
835 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 867 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
836 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; | 868 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; |
837 | hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 869 | hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
870 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; | ||
871 | hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; | ||
838 | 872 | ||
839 | #ifdef CONFIG_PM_SLEEP | 873 | #ifdef CONFIG_PM_SLEEP |
840 | if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && | 874 | if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && |
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index fff5d3ccc663..2f831db396ac 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
@@ -41,7 +41,7 @@ void ath_tx_complete_poll_work(struct work_struct *work) | |||
41 | txq->axq_tx_inprogress = true; | 41 | txq->axq_tx_inprogress = true; |
42 | } | 42 | } |
43 | } | 43 | } |
44 | ath_txq_unlock_complete(sc, txq); | 44 | ath_txq_unlock(sc, txq); |
45 | } | 45 | } |
46 | 46 | ||
47 | if (needreset) { | 47 | if (needreset) { |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 2ef05ebffbcf..a3eff0986a3f 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -583,9 +583,9 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
583 | rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate); | 583 | rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate); |
584 | rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; | 584 | rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; |
585 | 585 | ||
586 | rs->rs_firstaggr = (ads.ds_rxstatus8 & AR_RxFirstAggr) ? 1 : 0; | ||
586 | rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; | 587 | rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; |
587 | rs->rs_moreaggr = | 588 | rs->rs_moreaggr = (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; |
588 | (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; | ||
589 | rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); | 589 | rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); |
590 | 590 | ||
591 | /* directly mapped flags for ieee80211_rx_status */ | 591 | /* directly mapped flags for ieee80211_rx_status */ |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index b02dfce964b4..bfccaceed44e 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -140,6 +140,7 @@ struct ath_rx_status { | |||
140 | int8_t rs_rssi_ext1; | 140 | int8_t rs_rssi_ext1; |
141 | int8_t rs_rssi_ext2; | 141 | int8_t rs_rssi_ext2; |
142 | u8 rs_isaggr; | 142 | u8 rs_isaggr; |
143 | u8 rs_firstaggr; | ||
143 | u8 rs_moreaggr; | 144 | u8 rs_moreaggr; |
144 | u8 rs_num_delims; | 145 | u8 rs_num_delims; |
145 | u8 rs_flags; | 146 | u8 rs_flags; |
@@ -569,6 +570,7 @@ struct ar5416_desc { | |||
569 | #define AR_RxAggr 0x00020000 | 570 | #define AR_RxAggr 0x00020000 |
570 | #define AR_PostDelimCRCErr 0x00040000 | 571 | #define AR_PostDelimCRCErr 0x00040000 |
571 | #define AR_RxStatusRsvd71 0x3ff80000 | 572 | #define AR_RxStatusRsvd71 0x3ff80000 |
573 | #define AR_RxFirstAggr 0x20000000 | ||
572 | #define AR_DecryptBusyErr 0x40000000 | 574 | #define AR_DecryptBusyErr 0x40000000 |
573 | #define AR_KeyMiss 0x80000000 | 575 | #define AR_KeyMiss 0x80000000 |
574 | 576 | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index cb5a65553ac7..e4f65900132d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -237,9 +237,6 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
237 | ath_restart_work(sc); | 237 | ath_restart_work(sc); |
238 | } | 238 | } |
239 | 239 | ||
240 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) | ||
241 | ath_ant_comb_update(sc); | ||
242 | |||
243 | ieee80211_wake_queues(sc->hw); | 240 | ieee80211_wake_queues(sc->hw); |
244 | 241 | ||
245 | return true; | 242 | return true; |
@@ -965,6 +962,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
965 | struct ath_softc *sc = hw->priv; | 962 | struct ath_softc *sc = hw->priv; |
966 | struct ath_hw *ah = sc->sc_ah; | 963 | struct ath_hw *ah = sc->sc_ah; |
967 | struct ath_common *common = ath9k_hw_common(ah); | 964 | struct ath_common *common = ath9k_hw_common(ah); |
965 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
966 | struct ath_node *an = &avp->mcast_node; | ||
968 | 967 | ||
969 | mutex_lock(&sc->mutex); | 968 | mutex_lock(&sc->mutex); |
970 | 969 | ||
@@ -978,6 +977,12 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
978 | if (ath9k_uses_beacons(vif->type)) | 977 | if (ath9k_uses_beacons(vif->type)) |
979 | ath9k_beacon_assign_slot(sc, vif); | 978 | ath9k_beacon_assign_slot(sc, vif); |
980 | 979 | ||
980 | an->sc = sc; | ||
981 | an->sta = NULL; | ||
982 | an->vif = vif; | ||
983 | an->no_ps_filter = true; | ||
984 | ath_tx_node_init(sc, an); | ||
985 | |||
981 | mutex_unlock(&sc->mutex); | 986 | mutex_unlock(&sc->mutex); |
982 | return 0; | 987 | return 0; |
983 | } | 988 | } |
@@ -1015,6 +1020,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1015 | { | 1020 | { |
1016 | struct ath_softc *sc = hw->priv; | 1021 | struct ath_softc *sc = hw->priv; |
1017 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1022 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1023 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
1018 | 1024 | ||
1019 | ath_dbg(common, CONFIG, "Detach Interface\n"); | 1025 | ath_dbg(common, CONFIG, "Detach Interface\n"); |
1020 | 1026 | ||
@@ -1025,10 +1031,15 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1025 | if (ath9k_uses_beacons(vif->type)) | 1031 | if (ath9k_uses_beacons(vif->type)) |
1026 | ath9k_beacon_remove_slot(sc, vif); | 1032 | ath9k_beacon_remove_slot(sc, vif); |
1027 | 1033 | ||
1034 | if (sc->csa_vif == vif) | ||
1035 | sc->csa_vif = NULL; | ||
1036 | |||
1028 | ath9k_ps_wakeup(sc); | 1037 | ath9k_ps_wakeup(sc); |
1029 | ath9k_calculate_summary_state(hw, NULL); | 1038 | ath9k_calculate_summary_state(hw, NULL); |
1030 | ath9k_ps_restore(sc); | 1039 | ath9k_ps_restore(sc); |
1031 | 1040 | ||
1041 | ath_tx_node_cleanup(sc, &avp->mcast_node); | ||
1042 | |||
1032 | mutex_unlock(&sc->mutex); | 1043 | mutex_unlock(&sc->mutex); |
1033 | } | 1044 | } |
1034 | 1045 | ||
@@ -1192,8 +1203,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1192 | 1203 | ||
1193 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { | 1204 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { |
1194 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; | 1205 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; |
1195 | enum nl80211_channel_type channel_type = | ||
1196 | cfg80211_get_chandef_type(&conf->chandef); | ||
1197 | int pos = curchan->hw_value; | 1206 | int pos = curchan->hw_value; |
1198 | int old_pos = -1; | 1207 | int old_pos = -1; |
1199 | unsigned long flags; | 1208 | unsigned long flags; |
@@ -1201,8 +1210,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1201 | if (ah->curchan) | 1210 | if (ah->curchan) |
1202 | old_pos = ah->curchan - &ah->channels[0]; | 1211 | old_pos = ah->curchan - &ah->channels[0]; |
1203 | 1212 | ||
1204 | ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n", | 1213 | ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", |
1205 | curchan->center_freq, channel_type); | 1214 | curchan->center_freq, hw->conf.chandef.width); |
1206 | 1215 | ||
1207 | /* update survey stats for the old channel before switching */ | 1216 | /* update survey stats for the old channel before switching */ |
1208 | spin_lock_irqsave(&common->cc_lock, flags); | 1217 | spin_lock_irqsave(&common->cc_lock, flags); |
@@ -1210,7 +1219,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1210 | spin_unlock_irqrestore(&common->cc_lock, flags); | 1219 | spin_unlock_irqrestore(&common->cc_lock, flags); |
1211 | 1220 | ||
1212 | ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], | 1221 | ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], |
1213 | curchan, channel_type); | 1222 | &conf->chandef); |
1214 | 1223 | ||
1215 | /* | 1224 | /* |
1216 | * If the operating channel changes, change the survey in-use flags | 1225 | * If the operating channel changes, change the survey in-use flags |
@@ -1373,9 +1382,6 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, | |||
1373 | struct ath_softc *sc = hw->priv; | 1382 | struct ath_softc *sc = hw->priv; |
1374 | struct ath_node *an = (struct ath_node *) sta->drv_priv; | 1383 | struct ath_node *an = (struct ath_node *) sta->drv_priv; |
1375 | 1384 | ||
1376 | if (!sta->ht_cap.ht_supported) | ||
1377 | return; | ||
1378 | |||
1379 | switch (cmd) { | 1385 | switch (cmd) { |
1380 | case STA_NOTIFY_SLEEP: | 1386 | case STA_NOTIFY_SLEEP: |
1381 | an->sleeping = true; | 1387 | an->sleeping = true; |
@@ -2093,7 +2099,7 @@ static void ath9k_wow_add_pattern(struct ath_softc *sc, | |||
2093 | { | 2099 | { |
2094 | struct ath_hw *ah = sc->sc_ah; | 2100 | struct ath_hw *ah = sc->sc_ah; |
2095 | struct ath9k_wow_pattern *wow_pattern = NULL; | 2101 | struct ath9k_wow_pattern *wow_pattern = NULL; |
2096 | struct cfg80211_wowlan_trig_pkt_pattern *patterns = wowlan->patterns; | 2102 | struct cfg80211_pkt_pattern *patterns = wowlan->patterns; |
2097 | int mask_len; | 2103 | int mask_len; |
2098 | s8 i = 0; | 2104 | s8 i = 0; |
2099 | 2105 | ||
@@ -2314,6 +2320,19 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
2314 | clear_bit(SC_OP_SCANNING, &sc->sc_flags); | 2320 | clear_bit(SC_OP_SCANNING, &sc->sc_flags); |
2315 | } | 2321 | } |
2316 | 2322 | ||
2323 | static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw, | ||
2324 | struct ieee80211_vif *vif, | ||
2325 | struct cfg80211_chan_def *chandef) | ||
2326 | { | ||
2327 | struct ath_softc *sc = hw->priv; | ||
2328 | |||
2329 | /* mac80211 does not support CSA in multi-if cases (yet) */ | ||
2330 | if (WARN_ON(sc->csa_vif)) | ||
2331 | return; | ||
2332 | |||
2333 | sc->csa_vif = vif; | ||
2334 | } | ||
2335 | |||
2317 | struct ieee80211_ops ath9k_ops = { | 2336 | struct ieee80211_ops ath9k_ops = { |
2318 | .tx = ath9k_tx, | 2337 | .tx = ath9k_tx, |
2319 | .start = ath9k_start, | 2338 | .start = ath9k_start, |
@@ -2358,8 +2377,8 @@ struct ieee80211_ops ath9k_ops = { | |||
2358 | 2377 | ||
2359 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) | 2378 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) |
2360 | .sta_add_debugfs = ath9k_sta_add_debugfs, | 2379 | .sta_add_debugfs = ath9k_sta_add_debugfs, |
2361 | .sta_remove_debugfs = ath9k_sta_remove_debugfs, | ||
2362 | #endif | 2380 | #endif |
2363 | .sw_scan_start = ath9k_sw_scan_start, | 2381 | .sw_scan_start = ath9k_sw_scan_start, |
2364 | .sw_scan_complete = ath9k_sw_scan_complete, | 2382 | .sw_scan_complete = ath9k_sw_scan_complete, |
2383 | .channel_switch_beacon = ath9k_channel_switch_beacon, | ||
2365 | }; | 2384 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index c585c9b35973..d089a7cf01c4 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -29,6 +29,60 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
29 | { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ | 29 | { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ |
30 | { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ | 30 | { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ |
31 | { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ | 31 | { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ |
32 | |||
33 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
34 | 0x002A, | ||
35 | PCI_VENDOR_ID_AZWAVE, | ||
36 | 0x1C71), | ||
37 | .driver_data = ATH9K_PCI_D3_L1_WAR }, | ||
38 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
39 | 0x002A, | ||
40 | PCI_VENDOR_ID_FOXCONN, | ||
41 | 0xE01F), | ||
42 | .driver_data = ATH9K_PCI_D3_L1_WAR }, | ||
43 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
44 | 0x002A, | ||
45 | 0x11AD, /* LITEON */ | ||
46 | 0x6632), | ||
47 | .driver_data = ATH9K_PCI_D3_L1_WAR }, | ||
48 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
49 | 0x002A, | ||
50 | 0x11AD, /* LITEON */ | ||
51 | 0x6642), | ||
52 | .driver_data = ATH9K_PCI_D3_L1_WAR }, | ||
53 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
54 | 0x002A, | ||
55 | PCI_VENDOR_ID_QMI, | ||
56 | 0x0306), | ||
57 | .driver_data = ATH9K_PCI_D3_L1_WAR }, | ||
58 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
59 | 0x002A, | ||
60 | 0x185F, /* WNC */ | ||
61 | 0x309D), | ||
62 | .driver_data = ATH9K_PCI_D3_L1_WAR }, | ||
63 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
64 | 0x002A, | ||
65 | 0x10CF, /* Fujitsu */ | ||
66 | 0x147C), | ||
67 | .driver_data = ATH9K_PCI_D3_L1_WAR }, | ||
68 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
69 | 0x002A, | ||
70 | 0x10CF, /* Fujitsu */ | ||
71 | 0x147D), | ||
72 | .driver_data = ATH9K_PCI_D3_L1_WAR }, | ||
73 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
74 | 0x002A, | ||
75 | 0x10CF, /* Fujitsu */ | ||
76 | 0x1536), | ||
77 | .driver_data = ATH9K_PCI_D3_L1_WAR }, | ||
78 | |||
79 | /* AR9285 card for Asus */ | ||
80 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
81 | 0x002B, | ||
82 | PCI_VENDOR_ID_AZWAVE, | ||
83 | 0x2C37), | ||
84 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
85 | |||
32 | { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ | 86 | { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ |
33 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ | 87 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ |
34 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ | 88 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ |
@@ -40,29 +94,106 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
40 | 0x0032, | 94 | 0x0032, |
41 | PCI_VENDOR_ID_AZWAVE, | 95 | PCI_VENDOR_ID_AZWAVE, |
42 | 0x2086), | 96 | 0x2086), |
43 | .driver_data = ATH9K_PCI_CUS198 }, | 97 | .driver_data = ATH9K_PCI_CUS198 | ATH9K_PCI_BT_ANT_DIV }, |
44 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 98 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
45 | 0x0032, | 99 | 0x0032, |
46 | PCI_VENDOR_ID_AZWAVE, | 100 | PCI_VENDOR_ID_AZWAVE, |
47 | 0x1237), | 101 | 0x1237), |
48 | .driver_data = ATH9K_PCI_CUS198 }, | 102 | .driver_data = ATH9K_PCI_CUS198 | ATH9K_PCI_BT_ANT_DIV }, |
49 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 103 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
50 | 0x0032, | 104 | 0x0032, |
51 | PCI_VENDOR_ID_AZWAVE, | 105 | PCI_VENDOR_ID_AZWAVE, |
52 | 0x2126), | 106 | 0x2126), |
53 | .driver_data = ATH9K_PCI_CUS198 }, | 107 | .driver_data = ATH9K_PCI_CUS198 | ATH9K_PCI_BT_ANT_DIV }, |
108 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
109 | 0x0032, | ||
110 | PCI_VENDOR_ID_AZWAVE, | ||
111 | 0x126A), | ||
112 | .driver_data = ATH9K_PCI_CUS198 | ATH9K_PCI_BT_ANT_DIV }, | ||
54 | 113 | ||
55 | /* PCI-E CUS230 */ | 114 | /* PCI-E CUS230 */ |
56 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 115 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
57 | 0x0032, | 116 | 0x0032, |
58 | PCI_VENDOR_ID_AZWAVE, | 117 | PCI_VENDOR_ID_AZWAVE, |
59 | 0x2152), | 118 | 0x2152), |
60 | .driver_data = ATH9K_PCI_CUS230 }, | 119 | .driver_data = ATH9K_PCI_CUS230 | ATH9K_PCI_BT_ANT_DIV }, |
61 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 120 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
62 | 0x0032, | 121 | 0x0032, |
63 | PCI_VENDOR_ID_FOXCONN, | 122 | PCI_VENDOR_ID_FOXCONN, |
64 | 0xE075), | 123 | 0xE075), |
65 | .driver_data = ATH9K_PCI_CUS230 }, | 124 | .driver_data = ATH9K_PCI_CUS230 | ATH9K_PCI_BT_ANT_DIV }, |
125 | |||
126 | /* WB225 */ | ||
127 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
128 | 0x0032, | ||
129 | PCI_VENDOR_ID_ATHEROS, | ||
130 | 0x3119), | ||
131 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
132 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
133 | 0x0032, | ||
134 | PCI_VENDOR_ID_ATHEROS, | ||
135 | 0x3122), | ||
136 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
137 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
138 | 0x0032, | ||
139 | 0x185F, /* WNC */ | ||
140 | 0x3119), | ||
141 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
142 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
143 | 0x0032, | ||
144 | 0x185F, /* WNC */ | ||
145 | 0x3027), | ||
146 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
147 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
148 | 0x0032, | ||
149 | PCI_VENDOR_ID_SAMSUNG, | ||
150 | 0x4105), | ||
151 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
152 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
153 | 0x0032, | ||
154 | PCI_VENDOR_ID_SAMSUNG, | ||
155 | 0x4106), | ||
156 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
157 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
158 | 0x0032, | ||
159 | PCI_VENDOR_ID_SAMSUNG, | ||
160 | 0x410D), | ||
161 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
162 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
163 | 0x0032, | ||
164 | PCI_VENDOR_ID_SAMSUNG, | ||
165 | 0x410E), | ||
166 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
167 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
168 | 0x0032, | ||
169 | PCI_VENDOR_ID_SAMSUNG, | ||
170 | 0x410F), | ||
171 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
172 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
173 | 0x0032, | ||
174 | PCI_VENDOR_ID_SAMSUNG, | ||
175 | 0xC706), | ||
176 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
177 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
178 | 0x0032, | ||
179 | PCI_VENDOR_ID_SAMSUNG, | ||
180 | 0xC680), | ||
181 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
182 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
183 | 0x0032, | ||
184 | PCI_VENDOR_ID_SAMSUNG, | ||
185 | 0xC708), | ||
186 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
187 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
188 | 0x0032, | ||
189 | PCI_VENDOR_ID_LENOVO, | ||
190 | 0x3218), | ||
191 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
192 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
193 | 0x0032, | ||
194 | PCI_VENDOR_ID_LENOVO, | ||
195 | 0x3219), | ||
196 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
66 | 197 | ||
67 | { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ | 198 | { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ |
68 | { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ | 199 | { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ |
@@ -229,6 +360,22 @@ static void ath_pci_aspm_init(struct ath_common *common) | |||
229 | return; | 360 | return; |
230 | } | 361 | } |
231 | 362 | ||
363 | /* | ||
364 | * 0x70c - Ack Frequency Register. | ||
365 | * | ||
366 | * Bits 27:29 - DEFAULT_L1_ENTRANCE_LATENCY. | ||
367 | * | ||
368 | * 000 : 1 us | ||
369 | * 001 : 2 us | ||
370 | * 010 : 4 us | ||
371 | * 011 : 8 us | ||
372 | * 100 : 16 us | ||
373 | * 101 : 32 us | ||
374 | * 110/111 : 64 us | ||
375 | */ | ||
376 | if (AR_SREV_9462(ah)) | ||
377 | pci_read_config_dword(pdev, 0x70c, &ah->config.aspm_l1_fix); | ||
378 | |||
232 | pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm); | 379 | pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm); |
233 | if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) { | 380 | if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) { |
234 | ah->aspm_enabled = true; | 381 | ah->aspm_enabled = true; |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 8b380305b0fc..4a1b99238ec2 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -48,4 +48,11 @@ | |||
48 | #define AR_PHY_PLL_CONTROL 0x16180 | 48 | #define AR_PHY_PLL_CONTROL 0x16180 |
49 | #define AR_PHY_PLL_MODE 0x16184 | 49 | #define AR_PHY_PLL_MODE 0x16184 |
50 | 50 | ||
51 | enum ath9k_ant_div_comb_lna_conf { | ||
52 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, | ||
53 | ATH_ANT_DIV_COMB_LNA2, | ||
54 | ATH_ANT_DIV_COMB_LNA1, | ||
55 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2, | ||
56 | }; | ||
57 | |||
51 | #endif | 58 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 7eb1f4b458e4..d3d7c51fa6c8 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1275,15 +1275,21 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1275 | } | 1275 | } |
1276 | 1276 | ||
1277 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | 1277 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, |
1278 | struct cfg80211_chan_def *chandef, | ||
1278 | struct ieee80211_sta *sta, void *priv_sta) | 1279 | struct ieee80211_sta *sta, void *priv_sta) |
1279 | { | 1280 | { |
1280 | struct ath_softc *sc = priv; | 1281 | struct ath_softc *sc = priv; |
1281 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1282 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1282 | struct ath_rate_priv *ath_rc_priv = priv_sta; | 1283 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
1283 | int i, j = 0; | 1284 | int i, j = 0; |
1285 | u32 rate_flags = ieee80211_chandef_rate_flags(&sc->hw->conf.chandef); | ||
1284 | 1286 | ||
1285 | for (i = 0; i < sband->n_bitrates; i++) { | 1287 | for (i = 0; i < sband->n_bitrates; i++) { |
1286 | if (sta->supp_rates[sband->band] & BIT(i)) { | 1288 | if (sta->supp_rates[sband->band] & BIT(i)) { |
1289 | if ((rate_flags & sband->bitrates[i].flags) | ||
1290 | != rate_flags) | ||
1291 | continue; | ||
1292 | |||
1287 | ath_rc_priv->neg_rates.rs_rates[j] | 1293 | ath_rc_priv->neg_rates.rs_rates[j] |
1288 | = (sband->bitrates[i].bitrate * 2) / 10; | 1294 | = (sband->bitrates[i].bitrate * 2) / 10; |
1289 | j++; | 1295 | j++; |
@@ -1313,6 +1319,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1313 | } | 1319 | } |
1314 | 1320 | ||
1315 | static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | 1321 | static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, |
1322 | struct cfg80211_chan_def *chandef, | ||
1316 | struct ieee80211_sta *sta, void *priv_sta, | 1323 | struct ieee80211_sta *sta, void *priv_sta, |
1317 | u32 changed) | 1324 | u32 changed) |
1318 | { | 1325 | { |
@@ -1324,8 +1331,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | |||
1324 | ath_rc_init(sc, priv_sta); | 1331 | ath_rc_init(sc, priv_sta); |
1325 | 1332 | ||
1326 | ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, | 1333 | ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, |
1327 | "Operating HT Bandwidth changed to: %d\n", | 1334 | "Operating Bandwidth changed to: %d\n", |
1328 | cfg80211_get_chandef_type(&sc->hw->conf.chandef)); | 1335 | sc->hw->conf.chandef.width); |
1329 | } | 1336 | } |
1330 | } | 1337 | } |
1331 | 1338 | ||
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 865e043e8aa6..4ee472a5a4e4 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -42,8 +42,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
42 | struct ath_desc *ds; | 42 | struct ath_desc *ds; |
43 | struct sk_buff *skb; | 43 | struct sk_buff *skb; |
44 | 44 | ||
45 | ATH_RXBUF_RESET(bf); | ||
46 | |||
47 | ds = bf->bf_desc; | 45 | ds = bf->bf_desc; |
48 | ds->ds_link = 0; /* link to null */ | 46 | ds->ds_link = 0; /* link to null */ |
49 | ds->ds_data = bf->bf_buf_addr; | 47 | ds->ds_data = bf->bf_buf_addr; |
@@ -70,6 +68,14 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
70 | sc->rx.rxlink = &ds->ds_link; | 68 | sc->rx.rxlink = &ds->ds_link; |
71 | } | 69 | } |
72 | 70 | ||
71 | static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf) | ||
72 | { | ||
73 | if (sc->rx.buf_hold) | ||
74 | ath_rx_buf_link(sc, sc->rx.buf_hold); | ||
75 | |||
76 | sc->rx.buf_hold = bf; | ||
77 | } | ||
78 | |||
73 | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) | 79 | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) |
74 | { | 80 | { |
75 | /* XXX block beacon interrupts */ | 81 | /* XXX block beacon interrupts */ |
@@ -117,7 +123,6 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc, | |||
117 | 123 | ||
118 | skb = bf->bf_mpdu; | 124 | skb = bf->bf_mpdu; |
119 | 125 | ||
120 | ATH_RXBUF_RESET(bf); | ||
121 | memset(skb->data, 0, ah->caps.rx_status_len); | 126 | memset(skb->data, 0, ah->caps.rx_status_len); |
122 | dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, | 127 | dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, |
123 | ah->caps.rx_status_len, DMA_TO_DEVICE); | 128 | ah->caps.rx_status_len, DMA_TO_DEVICE); |
@@ -185,7 +190,7 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc) | |||
185 | 190 | ||
186 | static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size) | 191 | static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size) |
187 | { | 192 | { |
188 | skb_queue_head_init(&rx_edma->rx_fifo); | 193 | __skb_queue_head_init(&rx_edma->rx_fifo); |
189 | rx_edma->rx_fifo_hwsize = size; | 194 | rx_edma->rx_fifo_hwsize = size; |
190 | } | 195 | } |
191 | 196 | ||
@@ -432,6 +437,7 @@ int ath_startrecv(struct ath_softc *sc) | |||
432 | if (list_empty(&sc->rx.rxbuf)) | 437 | if (list_empty(&sc->rx.rxbuf)) |
433 | goto start_recv; | 438 | goto start_recv; |
434 | 439 | ||
440 | sc->rx.buf_hold = NULL; | ||
435 | sc->rx.rxlink = NULL; | 441 | sc->rx.rxlink = NULL; |
436 | list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) { | 442 | list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) { |
437 | ath_rx_buf_link(sc, bf); | 443 | ath_rx_buf_link(sc, bf); |
@@ -677,6 +683,9 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
677 | } | 683 | } |
678 | 684 | ||
679 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); | 685 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); |
686 | if (bf == sc->rx.buf_hold) | ||
687 | return NULL; | ||
688 | |||
680 | ds = bf->bf_desc; | 689 | ds = bf->bf_desc; |
681 | 690 | ||
682 | /* | 691 | /* |
@@ -755,7 +764,6 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
755 | bool is_mc, is_valid_tkip, strip_mic, mic_error; | 764 | bool is_mc, is_valid_tkip, strip_mic, mic_error; |
756 | struct ath_hw *ah = common->ah; | 765 | struct ath_hw *ah = common->ah; |
757 | __le16 fc; | 766 | __le16 fc; |
758 | u8 rx_status_len = ah->caps.rx_status_len; | ||
759 | 767 | ||
760 | fc = hdr->frame_control; | 768 | fc = hdr->frame_control; |
761 | 769 | ||
@@ -777,25 +785,6 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
777 | !test_bit(rx_stats->rs_keyix, common->ccmp_keymap)) | 785 | !test_bit(rx_stats->rs_keyix, common->ccmp_keymap)) |
778 | rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; | 786 | rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; |
779 | 787 | ||
780 | if (!rx_stats->rs_datalen) { | ||
781 | RX_STAT_INC(rx_len_err); | ||
782 | return false; | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * rs_status follows rs_datalen so if rs_datalen is too large | ||
787 | * we can take a hint that hardware corrupted it, so ignore | ||
788 | * those frames. | ||
789 | */ | ||
790 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) { | ||
791 | RX_STAT_INC(rx_len_err); | ||
792 | return false; | ||
793 | } | ||
794 | |||
795 | /* Only use error bits from the last fragment */ | ||
796 | if (rx_stats->rs_more) | ||
797 | return true; | ||
798 | |||
799 | mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) && | 788 | mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) && |
800 | !ieee80211_has_morefrags(fc) && | 789 | !ieee80211_has_morefrags(fc) && |
801 | !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && | 790 | !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && |
@@ -814,8 +803,6 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
814 | rxs->flag |= RX_FLAG_FAILED_FCS_CRC; | 803 | rxs->flag |= RX_FLAG_FAILED_FCS_CRC; |
815 | mic_error = false; | 804 | mic_error = false; |
816 | } | 805 | } |
817 | if (rx_stats->rs_status & ATH9K_RXERR_PHY) | ||
818 | return false; | ||
819 | 806 | ||
820 | if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) || | 807 | if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) || |
821 | (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) { | 808 | (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) { |
@@ -865,6 +852,17 @@ static int ath9k_process_rate(struct ath_common *common, | |||
865 | band = hw->conf.chandef.chan->band; | 852 | band = hw->conf.chandef.chan->band; |
866 | sband = hw->wiphy->bands[band]; | 853 | sband = hw->wiphy->bands[band]; |
867 | 854 | ||
855 | switch (hw->conf.chandef.width) { | ||
856 | case NL80211_CHAN_WIDTH_5: | ||
857 | rxs->flag |= RX_FLAG_5MHZ; | ||
858 | break; | ||
859 | case NL80211_CHAN_WIDTH_10: | ||
860 | rxs->flag |= RX_FLAG_10MHZ; | ||
861 | break; | ||
862 | default: | ||
863 | break; | ||
864 | } | ||
865 | |||
868 | if (rx_stats->rs_rate & 0x80) { | 866 | if (rx_stats->rs_rate & 0x80) { |
869 | /* HT rate */ | 867 | /* HT rate */ |
870 | rxs->flag |= RX_FLAG_HT; | 868 | rxs->flag |= RX_FLAG_HT; |
@@ -898,129 +896,65 @@ static int ath9k_process_rate(struct ath_common *common, | |||
898 | 896 | ||
899 | static void ath9k_process_rssi(struct ath_common *common, | 897 | static void ath9k_process_rssi(struct ath_common *common, |
900 | struct ieee80211_hw *hw, | 898 | struct ieee80211_hw *hw, |
901 | struct ieee80211_hdr *hdr, | 899 | struct ath_rx_status *rx_stats, |
902 | struct ath_rx_status *rx_stats) | 900 | struct ieee80211_rx_status *rxs) |
903 | { | 901 | { |
904 | struct ath_softc *sc = hw->priv; | 902 | struct ath_softc *sc = hw->priv; |
905 | struct ath_hw *ah = common->ah; | 903 | struct ath_hw *ah = common->ah; |
906 | int last_rssi; | 904 | int last_rssi; |
907 | int rssi = rx_stats->rs_rssi; | 905 | int rssi = rx_stats->rs_rssi; |
908 | 906 | ||
909 | if (!rx_stats->is_mybeacon || | 907 | /* |
910 | ((ah->opmode != NL80211_IFTYPE_STATION) && | 908 | * RSSI is not available for subframes in an A-MPDU. |
911 | (ah->opmode != NL80211_IFTYPE_ADHOC))) | 909 | */ |
910 | if (rx_stats->rs_moreaggr) { | ||
911 | rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; | ||
912 | return; | 912 | return; |
913 | 913 | } | |
914 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) | ||
915 | ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); | ||
916 | |||
917 | last_rssi = sc->last_rssi; | ||
918 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | ||
919 | rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); | ||
920 | if (rssi < 0) | ||
921 | rssi = 0; | ||
922 | |||
923 | /* Update Beacon RSSI, this is used by ANI. */ | ||
924 | ah->stats.avgbrssi = rssi; | ||
925 | } | ||
926 | |||
927 | /* | ||
928 | * For Decrypt or Demic errors, we only mark packet status here and always push | ||
929 | * up the frame up to let mac80211 handle the actual error case, be it no | ||
930 | * decryption key or real decryption error. This let us keep statistics there. | ||
931 | */ | ||
932 | static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | ||
933 | struct ieee80211_hdr *hdr, | ||
934 | struct ath_rx_status *rx_stats, | ||
935 | struct ieee80211_rx_status *rx_status, | ||
936 | bool *decrypt_error) | ||
937 | { | ||
938 | struct ieee80211_hw *hw = sc->hw; | ||
939 | struct ath_hw *ah = sc->sc_ah; | ||
940 | struct ath_common *common = ath9k_hw_common(ah); | ||
941 | bool discard_current = sc->rx.discard_next; | ||
942 | |||
943 | sc->rx.discard_next = rx_stats->rs_more; | ||
944 | if (discard_current) | ||
945 | return -EINVAL; | ||
946 | 914 | ||
947 | /* | 915 | /* |
948 | * everything but the rate is checked here, the rate check is done | 916 | * Check if the RSSI for the last subframe in an A-MPDU |
949 | * separately to avoid doing two lookups for a rate for each frame. | 917 | * or an unaggregated frame is valid. |
950 | */ | 918 | */ |
951 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) | 919 | if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) { |
952 | return -EINVAL; | 920 | rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; |
953 | 921 | return; | |
954 | /* Only use status info from the last fragment */ | 922 | } |
955 | if (rx_stats->rs_more) | ||
956 | return 0; | ||
957 | 923 | ||
958 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) | 924 | /* |
959 | return -EINVAL; | 925 | * Update Beacon RSSI, this is used by ANI. |
926 | */ | ||
927 | if (rx_stats->is_mybeacon && | ||
928 | ((ah->opmode == NL80211_IFTYPE_STATION) || | ||
929 | (ah->opmode == NL80211_IFTYPE_ADHOC))) { | ||
930 | ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); | ||
931 | last_rssi = sc->last_rssi; | ||
960 | 932 | ||
961 | ath9k_process_rssi(common, hw, hdr, rx_stats); | 933 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
934 | rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); | ||
935 | if (rssi < 0) | ||
936 | rssi = 0; | ||
962 | 937 | ||
963 | rx_status->band = hw->conf.chandef.chan->band; | 938 | ah->stats.avgbrssi = rssi; |
964 | rx_status->freq = hw->conf.chandef.chan->center_freq; | 939 | } |
965 | rx_status->signal = ah->noise + rx_stats->rs_rssi; | ||
966 | rx_status->antenna = rx_stats->rs_antenna; | ||
967 | rx_status->flag |= RX_FLAG_MACTIME_END; | ||
968 | if (rx_stats->rs_moreaggr) | ||
969 | rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; | ||
970 | 940 | ||
971 | sc->rx.discard_next = false; | 941 | rxs->signal = ah->noise + rx_stats->rs_rssi; |
972 | return 0; | ||
973 | } | 942 | } |
974 | 943 | ||
975 | static void ath9k_rx_skb_postprocess(struct ath_common *common, | 944 | static void ath9k_process_tsf(struct ath_rx_status *rs, |
976 | struct sk_buff *skb, | 945 | struct ieee80211_rx_status *rxs, |
977 | struct ath_rx_status *rx_stats, | 946 | u64 tsf) |
978 | struct ieee80211_rx_status *rxs, | ||
979 | bool decrypt_error) | ||
980 | { | 947 | { |
981 | struct ath_hw *ah = common->ah; | 948 | u32 tsf_lower = tsf & 0xffffffff; |
982 | struct ieee80211_hdr *hdr; | ||
983 | int hdrlen, padpos, padsize; | ||
984 | u8 keyix; | ||
985 | __le16 fc; | ||
986 | |||
987 | /* see if any padding is done by the hw and remove it */ | ||
988 | hdr = (struct ieee80211_hdr *) skb->data; | ||
989 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
990 | fc = hdr->frame_control; | ||
991 | padpos = ieee80211_hdrlen(fc); | ||
992 | |||
993 | /* The MAC header is padded to have 32-bit boundary if the | ||
994 | * packet payload is non-zero. The general calculation for | ||
995 | * padsize would take into account odd header lengths: | ||
996 | * padsize = (4 - padpos % 4) % 4; However, since only | ||
997 | * even-length headers are used, padding can only be 0 or 2 | ||
998 | * bytes and we can optimize this a bit. In addition, we must | ||
999 | * not try to remove padding from short control frames that do | ||
1000 | * not have payload. */ | ||
1001 | padsize = padpos & 3; | ||
1002 | if (padsize && skb->len>=padpos+padsize+FCS_LEN) { | ||
1003 | memmove(skb->data + padsize, skb->data, padpos); | ||
1004 | skb_pull(skb, padsize); | ||
1005 | } | ||
1006 | 949 | ||
1007 | keyix = rx_stats->rs_keyix; | 950 | rxs->mactime = (tsf & ~0xffffffffULL) | rs->rs_tstamp; |
951 | if (rs->rs_tstamp > tsf_lower && | ||
952 | unlikely(rs->rs_tstamp - tsf_lower > 0x10000000)) | ||
953 | rxs->mactime -= 0x100000000ULL; | ||
1008 | 954 | ||
1009 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && | 955 | if (rs->rs_tstamp < tsf_lower && |
1010 | ieee80211_has_protected(fc)) { | 956 | unlikely(tsf_lower - rs->rs_tstamp > 0x10000000)) |
1011 | rxs->flag |= RX_FLAG_DECRYPTED; | 957 | rxs->mactime += 0x100000000ULL; |
1012 | } else if (ieee80211_has_protected(fc) | ||
1013 | && !decrypt_error && skb->len >= hdrlen + 4) { | ||
1014 | keyix = skb->data[hdrlen + 3] >> 6; | ||
1015 | |||
1016 | if (test_bit(keyix, common->keymap)) | ||
1017 | rxs->flag |= RX_FLAG_DECRYPTED; | ||
1018 | } | ||
1019 | if (ah->sw_mgmt_crypto && | ||
1020 | (rxs->flag & RX_FLAG_DECRYPTED) && | ||
1021 | ieee80211_is_mgmt(fc)) | ||
1022 | /* Use software decrypt for management frames. */ | ||
1023 | rxs->flag &= ~RX_FLAG_DECRYPTED; | ||
1024 | } | 958 | } |
1025 | 959 | ||
1026 | #ifdef CONFIG_ATH9K_DEBUGFS | 960 | #ifdef CONFIG_ATH9K_DEBUGFS |
@@ -1133,6 +1067,234 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
1133 | #endif | 1067 | #endif |
1134 | } | 1068 | } |
1135 | 1069 | ||
1070 | static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr) | ||
1071 | { | ||
1072 | struct ath_hw *ah = sc->sc_ah; | ||
1073 | struct ath_common *common = ath9k_hw_common(ah); | ||
1074 | |||
1075 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
1076 | RX_STAT_INC(rx_beacons); | ||
1077 | if (!is_zero_ether_addr(common->curbssid) && | ||
1078 | ether_addr_equal(hdr->addr3, common->curbssid)) | ||
1079 | return true; | ||
1080 | } | ||
1081 | |||
1082 | return false; | ||
1083 | } | ||
1084 | |||
1085 | /* | ||
1086 | * For Decrypt or Demic errors, we only mark packet status here and always push | ||
1087 | * up the frame up to let mac80211 handle the actual error case, be it no | ||
1088 | * decryption key or real decryption error. This let us keep statistics there. | ||
1089 | */ | ||
1090 | static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | ||
1091 | struct sk_buff *skb, | ||
1092 | struct ath_rx_status *rx_stats, | ||
1093 | struct ieee80211_rx_status *rx_status, | ||
1094 | bool *decrypt_error, u64 tsf) | ||
1095 | { | ||
1096 | struct ieee80211_hw *hw = sc->hw; | ||
1097 | struct ath_hw *ah = sc->sc_ah; | ||
1098 | struct ath_common *common = ath9k_hw_common(ah); | ||
1099 | struct ieee80211_hdr *hdr; | ||
1100 | bool discard_current = sc->rx.discard_next; | ||
1101 | int ret = 0; | ||
1102 | |||
1103 | /* | ||
1104 | * Discard corrupt descriptors which are marked in | ||
1105 | * ath_get_next_rx_buf(). | ||
1106 | */ | ||
1107 | sc->rx.discard_next = rx_stats->rs_more; | ||
1108 | if (discard_current) | ||
1109 | return -EINVAL; | ||
1110 | |||
1111 | /* | ||
1112 | * Discard zero-length packets. | ||
1113 | */ | ||
1114 | if (!rx_stats->rs_datalen) { | ||
1115 | RX_STAT_INC(rx_len_err); | ||
1116 | return -EINVAL; | ||
1117 | } | ||
1118 | |||
1119 | /* | ||
1120 | * rs_status follows rs_datalen so if rs_datalen is too large | ||
1121 | * we can take a hint that hardware corrupted it, so ignore | ||
1122 | * those frames. | ||
1123 | */ | ||
1124 | if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) { | ||
1125 | RX_STAT_INC(rx_len_err); | ||
1126 | return -EINVAL; | ||
1127 | } | ||
1128 | |||
1129 | /* Only use status info from the last fragment */ | ||
1130 | if (rx_stats->rs_more) | ||
1131 | return 0; | ||
1132 | |||
1133 | /* | ||
1134 | * Return immediately if the RX descriptor has been marked | ||
1135 | * as corrupt based on the various error bits. | ||
1136 | * | ||
1137 | * This is different from the other corrupt descriptor | ||
1138 | * condition handled above. | ||
1139 | */ | ||
1140 | if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) { | ||
1141 | ret = -EINVAL; | ||
1142 | goto exit; | ||
1143 | } | ||
1144 | |||
1145 | hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len); | ||
1146 | |||
1147 | ath9k_process_tsf(rx_stats, rx_status, tsf); | ||
1148 | ath_debug_stat_rx(sc, rx_stats); | ||
1149 | |||
1150 | /* | ||
1151 | * Process PHY errors and return so that the packet | ||
1152 | * can be dropped. | ||
1153 | */ | ||
1154 | if (rx_stats->rs_status & ATH9K_RXERR_PHY) { | ||
1155 | ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime); | ||
1156 | if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime)) | ||
1157 | RX_STAT_INC(rx_spectral); | ||
1158 | |||
1159 | ret = -EINVAL; | ||
1160 | goto exit; | ||
1161 | } | ||
1162 | |||
1163 | /* | ||
1164 | * everything but the rate is checked here, the rate check is done | ||
1165 | * separately to avoid doing two lookups for a rate for each frame. | ||
1166 | */ | ||
1167 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) { | ||
1168 | ret = -EINVAL; | ||
1169 | goto exit; | ||
1170 | } | ||
1171 | |||
1172 | rx_stats->is_mybeacon = ath9k_is_mybeacon(sc, hdr); | ||
1173 | if (rx_stats->is_mybeacon) { | ||
1174 | sc->hw_busy_count = 0; | ||
1175 | ath_start_rx_poll(sc, 3); | ||
1176 | } | ||
1177 | |||
1178 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) { | ||
1179 | ret =-EINVAL; | ||
1180 | goto exit; | ||
1181 | } | ||
1182 | |||
1183 | ath9k_process_rssi(common, hw, rx_stats, rx_status); | ||
1184 | |||
1185 | rx_status->band = hw->conf.chandef.chan->band; | ||
1186 | rx_status->freq = hw->conf.chandef.chan->center_freq; | ||
1187 | rx_status->antenna = rx_stats->rs_antenna; | ||
1188 | rx_status->flag |= RX_FLAG_MACTIME_END; | ||
1189 | |||
1190 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | ||
1191 | if (ieee80211_is_data_present(hdr->frame_control) && | ||
1192 | !ieee80211_is_qos_nullfunc(hdr->frame_control)) | ||
1193 | sc->rx.num_pkts++; | ||
1194 | #endif | ||
1195 | |||
1196 | exit: | ||
1197 | sc->rx.discard_next = false; | ||
1198 | return ret; | ||
1199 | } | ||
1200 | |||
1201 | static void ath9k_rx_skb_postprocess(struct ath_common *common, | ||
1202 | struct sk_buff *skb, | ||
1203 | struct ath_rx_status *rx_stats, | ||
1204 | struct ieee80211_rx_status *rxs, | ||
1205 | bool decrypt_error) | ||
1206 | { | ||
1207 | struct ath_hw *ah = common->ah; | ||
1208 | struct ieee80211_hdr *hdr; | ||
1209 | int hdrlen, padpos, padsize; | ||
1210 | u8 keyix; | ||
1211 | __le16 fc; | ||
1212 | |||
1213 | /* see if any padding is done by the hw and remove it */ | ||
1214 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1215 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
1216 | fc = hdr->frame_control; | ||
1217 | padpos = ieee80211_hdrlen(fc); | ||
1218 | |||
1219 | /* The MAC header is padded to have 32-bit boundary if the | ||
1220 | * packet payload is non-zero. The general calculation for | ||
1221 | * padsize would take into account odd header lengths: | ||
1222 | * padsize = (4 - padpos % 4) % 4; However, since only | ||
1223 | * even-length headers are used, padding can only be 0 or 2 | ||
1224 | * bytes and we can optimize this a bit. In addition, we must | ||
1225 | * not try to remove padding from short control frames that do | ||
1226 | * not have payload. */ | ||
1227 | padsize = padpos & 3; | ||
1228 | if (padsize && skb->len>=padpos+padsize+FCS_LEN) { | ||
1229 | memmove(skb->data + padsize, skb->data, padpos); | ||
1230 | skb_pull(skb, padsize); | ||
1231 | } | ||
1232 | |||
1233 | keyix = rx_stats->rs_keyix; | ||
1234 | |||
1235 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && | ||
1236 | ieee80211_has_protected(fc)) { | ||
1237 | rxs->flag |= RX_FLAG_DECRYPTED; | ||
1238 | } else if (ieee80211_has_protected(fc) | ||
1239 | && !decrypt_error && skb->len >= hdrlen + 4) { | ||
1240 | keyix = skb->data[hdrlen + 3] >> 6; | ||
1241 | |||
1242 | if (test_bit(keyix, common->keymap)) | ||
1243 | rxs->flag |= RX_FLAG_DECRYPTED; | ||
1244 | } | ||
1245 | if (ah->sw_mgmt_crypto && | ||
1246 | (rxs->flag & RX_FLAG_DECRYPTED) && | ||
1247 | ieee80211_is_mgmt(fc)) | ||
1248 | /* Use software decrypt for management frames. */ | ||
1249 | rxs->flag &= ~RX_FLAG_DECRYPTED; | ||
1250 | } | ||
1251 | |||
1252 | /* | ||
1253 | * Run the LNA combining algorithm only in these cases: | ||
1254 | * | ||
1255 | * Standalone WLAN cards with both LNA/Antenna diversity | ||
1256 | * enabled in the EEPROM. | ||
1257 | * | ||
1258 | * WLAN+BT cards which are in the supported card list | ||
1259 | * in ath_pci_id_table and the user has loaded the | ||
1260 | * driver with "bt_ant_diversity" set to true. | ||
1261 | */ | ||
1262 | static void ath9k_antenna_check(struct ath_softc *sc, | ||
1263 | struct ath_rx_status *rs) | ||
1264 | { | ||
1265 | struct ath_hw *ah = sc->sc_ah; | ||
1266 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1267 | struct ath_common *common = ath9k_hw_common(ah); | ||
1268 | |||
1269 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)) | ||
1270 | return; | ||
1271 | |||
1272 | /* | ||
1273 | * All MPDUs in an aggregate will use the same LNA | ||
1274 | * as the first MPDU. | ||
1275 | */ | ||
1276 | if (rs->rs_isaggr && !rs->rs_firstaggr) | ||
1277 | return; | ||
1278 | |||
1279 | /* | ||
1280 | * Change the default rx antenna if rx diversity | ||
1281 | * chooses the other antenna 3 times in a row. | ||
1282 | */ | ||
1283 | if (sc->rx.defant != rs->rs_antenna) { | ||
1284 | if (++sc->rx.rxotherant >= 3) | ||
1285 | ath_setdefantenna(sc, rs->rs_antenna); | ||
1286 | } else { | ||
1287 | sc->rx.rxotherant = 0; | ||
1288 | } | ||
1289 | |||
1290 | if (pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV) { | ||
1291 | if (common->bt_ant_diversity) | ||
1292 | ath_ant_comb_scan(sc, rs); | ||
1293 | } else { | ||
1294 | ath_ant_comb_scan(sc, rs); | ||
1295 | } | ||
1296 | } | ||
1297 | |||
1136 | static void ath9k_apply_ampdu_details(struct ath_softc *sc, | 1298 | static void ath9k_apply_ampdu_details(struct ath_softc *sc, |
1137 | struct ath_rx_status *rs, struct ieee80211_rx_status *rxs) | 1299 | struct ath_rx_status *rs, struct ieee80211_rx_status *rxs) |
1138 | { | 1300 | { |
@@ -1159,15 +1321,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1159 | struct ath_hw *ah = sc->sc_ah; | 1321 | struct ath_hw *ah = sc->sc_ah; |
1160 | struct ath_common *common = ath9k_hw_common(ah); | 1322 | struct ath_common *common = ath9k_hw_common(ah); |
1161 | struct ieee80211_hw *hw = sc->hw; | 1323 | struct ieee80211_hw *hw = sc->hw; |
1162 | struct ieee80211_hdr *hdr; | ||
1163 | int retval; | 1324 | int retval; |
1164 | struct ath_rx_status rs; | 1325 | struct ath_rx_status rs; |
1165 | enum ath9k_rx_qtype qtype; | 1326 | enum ath9k_rx_qtype qtype; |
1166 | bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); | 1327 | bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); |
1167 | int dma_type; | 1328 | int dma_type; |
1168 | u8 rx_status_len = ah->caps.rx_status_len; | ||
1169 | u64 tsf = 0; | 1329 | u64 tsf = 0; |
1170 | u32 tsf_lower = 0; | ||
1171 | unsigned long flags; | 1330 | unsigned long flags; |
1172 | dma_addr_t new_buf_addr; | 1331 | dma_addr_t new_buf_addr; |
1173 | 1332 | ||
@@ -1179,7 +1338,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1179 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; | 1338 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; |
1180 | 1339 | ||
1181 | tsf = ath9k_hw_gettsf64(ah); | 1340 | tsf = ath9k_hw_gettsf64(ah); |
1182 | tsf_lower = tsf & 0xffffffff; | ||
1183 | 1341 | ||
1184 | do { | 1342 | do { |
1185 | bool decrypt_error = false; | 1343 | bool decrypt_error = false; |
@@ -1206,55 +1364,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1206 | else | 1364 | else |
1207 | hdr_skb = skb; | 1365 | hdr_skb = skb; |
1208 | 1366 | ||
1209 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); | ||
1210 | rxs = IEEE80211_SKB_RXCB(hdr_skb); | 1367 | rxs = IEEE80211_SKB_RXCB(hdr_skb); |
1211 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
1212 | RX_STAT_INC(rx_beacons); | ||
1213 | if (!is_zero_ether_addr(common->curbssid) && | ||
1214 | ether_addr_equal(hdr->addr3, common->curbssid)) | ||
1215 | rs.is_mybeacon = true; | ||
1216 | else | ||
1217 | rs.is_mybeacon = false; | ||
1218 | } | ||
1219 | else | ||
1220 | rs.is_mybeacon = false; | ||
1221 | |||
1222 | if (ieee80211_is_data_present(hdr->frame_control) && | ||
1223 | !ieee80211_is_qos_nullfunc(hdr->frame_control)) | ||
1224 | sc->rx.num_pkts++; | ||
1225 | |||
1226 | ath_debug_stat_rx(sc, &rs); | ||
1227 | |||
1228 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); | 1368 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); |
1229 | 1369 | ||
1230 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | 1370 | retval = ath9k_rx_skb_preprocess(sc, hdr_skb, &rs, rxs, |
1231 | if (rs.rs_tstamp > tsf_lower && | 1371 | &decrypt_error, tsf); |
1232 | unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) | ||
1233 | rxs->mactime -= 0x100000000ULL; | ||
1234 | |||
1235 | if (rs.rs_tstamp < tsf_lower && | ||
1236 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) | ||
1237 | rxs->mactime += 0x100000000ULL; | ||
1238 | |||
1239 | if (rs.rs_phyerr == ATH9K_PHYERR_RADAR) | ||
1240 | ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime); | ||
1241 | |||
1242 | if (rs.rs_status & ATH9K_RXERR_PHY) { | ||
1243 | if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) { | ||
1244 | RX_STAT_INC(rx_spectral); | ||
1245 | goto requeue_drop_frag; | ||
1246 | } | ||
1247 | } | ||
1248 | |||
1249 | retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs, | ||
1250 | &decrypt_error); | ||
1251 | if (retval) | 1372 | if (retval) |
1252 | goto requeue_drop_frag; | 1373 | goto requeue_drop_frag; |
1253 | 1374 | ||
1254 | if (rs.is_mybeacon) { | ||
1255 | sc->hw_busy_count = 0; | ||
1256 | ath_start_rx_poll(sc, 3); | ||
1257 | } | ||
1258 | /* Ensure we always have an skb to requeue once we are done | 1375 | /* Ensure we always have an skb to requeue once we are done |
1259 | * processing the current buffer's skb */ | 1376 | * processing the current buffer's skb */ |
1260 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); | 1377 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); |
@@ -1308,8 +1425,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1308 | sc->rx.frag = skb; | 1425 | sc->rx.frag = skb; |
1309 | goto requeue; | 1426 | goto requeue; |
1310 | } | 1427 | } |
1311 | if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC) | ||
1312 | goto requeue_drop_frag; | ||
1313 | 1428 | ||
1314 | if (sc->rx.frag) { | 1429 | if (sc->rx.frag) { |
1315 | int space = skb->len - skb_tailroom(hdr_skb); | 1430 | int space = skb->len - skb_tailroom(hdr_skb); |
@@ -1328,22 +1443,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1328 | skb = hdr_skb; | 1443 | skb = hdr_skb; |
1329 | } | 1444 | } |
1330 | 1445 | ||
1331 | |||
1332 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) { | ||
1333 | |||
1334 | /* | ||
1335 | * change the default rx antenna if rx diversity | ||
1336 | * chooses the other antenna 3 times in a row. | ||
1337 | */ | ||
1338 | if (sc->rx.defant != rs.rs_antenna) { | ||
1339 | if (++sc->rx.rxotherant >= 3) | ||
1340 | ath_setdefantenna(sc, rs.rs_antenna); | ||
1341 | } else { | ||
1342 | sc->rx.rxotherant = 0; | ||
1343 | } | ||
1344 | |||
1345 | } | ||
1346 | |||
1347 | if (rxs->flag & RX_FLAG_MMIC_STRIPPED) | 1446 | if (rxs->flag & RX_FLAG_MMIC_STRIPPED) |
1348 | skb_trim(skb, skb->len - 8); | 1447 | skb_trim(skb, skb->len - 8); |
1349 | 1448 | ||
@@ -1355,8 +1454,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1355 | ath_rx_ps(sc, skb, rs.is_mybeacon); | 1454 | ath_rx_ps(sc, skb, rs.is_mybeacon); |
1356 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 1455 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
1357 | 1456 | ||
1358 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3) | 1457 | ath9k_antenna_check(sc, &rs); |
1359 | ath_ant_comb_scan(sc, &rs); | ||
1360 | 1458 | ||
1361 | ath9k_apply_ampdu_details(sc, &rs, rxs); | 1459 | ath9k_apply_ampdu_details(sc, &rs, rxs); |
1362 | 1460 | ||
@@ -1375,7 +1473,7 @@ requeue: | |||
1375 | if (edma) { | 1473 | if (edma) { |
1376 | ath_rx_edma_buf_link(sc, qtype); | 1474 | ath_rx_edma_buf_link(sc, qtype); |
1377 | } else { | 1475 | } else { |
1378 | ath_rx_buf_link(sc, bf); | 1476 | ath_rx_buf_relink(sc, bf); |
1379 | ath9k_hw_rxena(ah); | 1477 | ath9k_hw_rxena(ah); |
1380 | } | 1478 | } |
1381 | } while (1); | 1479 | } while (1); |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 5af97442ac37..a13b2d143d9e 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -893,9 +893,9 @@ | |||
893 | 893 | ||
894 | #define AR_SREV_9485(_ah) \ | 894 | #define AR_SREV_9485(_ah) \ |
895 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) | 895 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) |
896 | #define AR_SREV_9485_11(_ah) \ | 896 | #define AR_SREV_9485_11_OR_LATER(_ah) \ |
897 | (AR_SREV_9485(_ah) && \ | 897 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485) && \ |
898 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) | 898 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9485_11)) |
899 | #define AR_SREV_9485_OR_LATER(_ah) \ | 899 | #define AR_SREV_9485_OR_LATER(_ah) \ |
900 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) | 900 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) |
901 | 901 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 927992732620..35b515fe3ffa 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -135,6 +135,9 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) | |||
135 | 135 | ||
136 | static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) | 136 | static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) |
137 | { | 137 | { |
138 | if (!tid->an->sta) | ||
139 | return; | ||
140 | |||
138 | ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno, | 141 | ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno, |
139 | seqno << IEEE80211_SEQ_SEQ_SHIFT); | 142 | seqno << IEEE80211_SEQ_SEQ_SHIFT); |
140 | } | 143 | } |
@@ -168,6 +171,71 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, | |||
168 | } | 171 | } |
169 | } | 172 | } |
170 | 173 | ||
174 | static struct ath_atx_tid * | ||
175 | ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb) | ||
176 | { | ||
177 | struct ieee80211_hdr *hdr; | ||
178 | u8 tidno = 0; | ||
179 | |||
180 | hdr = (struct ieee80211_hdr *) skb->data; | ||
181 | if (ieee80211_is_data_qos(hdr->frame_control)) | ||
182 | tidno = ieee80211_get_qos_ctl(hdr)[0]; | ||
183 | |||
184 | tidno &= IEEE80211_QOS_CTL_TID_MASK; | ||
185 | return ATH_AN_2_TID(an, tidno); | ||
186 | } | ||
187 | |||
188 | static bool ath_tid_has_buffered(struct ath_atx_tid *tid) | ||
189 | { | ||
190 | return !skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q); | ||
191 | } | ||
192 | |||
193 | static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid) | ||
194 | { | ||
195 | struct sk_buff *skb; | ||
196 | |||
197 | skb = __skb_dequeue(&tid->retry_q); | ||
198 | if (!skb) | ||
199 | skb = __skb_dequeue(&tid->buf_q); | ||
200 | |||
201 | return skb; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * ath_tx_tid_change_state: | ||
206 | * - clears a-mpdu flag of previous session | ||
207 | * - force sequence number allocation to fix next BlockAck Window | ||
208 | */ | ||
209 | static void | ||
210 | ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid) | ||
211 | { | ||
212 | struct ath_txq *txq = tid->ac->txq; | ||
213 | struct ieee80211_tx_info *tx_info; | ||
214 | struct sk_buff *skb, *tskb; | ||
215 | struct ath_buf *bf; | ||
216 | struct ath_frame_info *fi; | ||
217 | |||
218 | skb_queue_walk_safe(&tid->buf_q, skb, tskb) { | ||
219 | fi = get_frame_info(skb); | ||
220 | bf = fi->bf; | ||
221 | |||
222 | tx_info = IEEE80211_SKB_CB(skb); | ||
223 | tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
224 | |||
225 | if (bf) | ||
226 | continue; | ||
227 | |||
228 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | ||
229 | if (!bf) { | ||
230 | __skb_unlink(skb, &tid->buf_q); | ||
231 | ath_txq_skb_done(sc, txq, skb); | ||
232 | ieee80211_free_txskb(sc->hw, skb); | ||
233 | continue; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | } | ||
238 | |||
171 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 239 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
172 | { | 240 | { |
173 | struct ath_txq *txq = tid->ac->txq; | 241 | struct ath_txq *txq = tid->ac->txq; |
@@ -182,28 +250,22 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
182 | 250 | ||
183 | memset(&ts, 0, sizeof(ts)); | 251 | memset(&ts, 0, sizeof(ts)); |
184 | 252 | ||
185 | while ((skb = __skb_dequeue(&tid->buf_q))) { | 253 | while ((skb = __skb_dequeue(&tid->retry_q))) { |
186 | fi = get_frame_info(skb); | 254 | fi = get_frame_info(skb); |
187 | bf = fi->bf; | 255 | bf = fi->bf; |
188 | |||
189 | if (!bf) { | 256 | if (!bf) { |
190 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | 257 | ath_txq_skb_done(sc, txq, skb); |
191 | if (!bf) { | 258 | ieee80211_free_txskb(sc->hw, skb); |
192 | ath_txq_skb_done(sc, txq, skb); | 259 | continue; |
193 | ieee80211_free_txskb(sc->hw, skb); | ||
194 | continue; | ||
195 | } | ||
196 | } | 260 | } |
197 | 261 | ||
198 | if (fi->retries) { | 262 | if (fi->baw_tracked) { |
199 | list_add_tail(&bf->list, &bf_head); | ||
200 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | 263 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); |
201 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | ||
202 | sendbar = true; | 264 | sendbar = true; |
203 | } else { | ||
204 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | ||
205 | ath_tx_send_normal(sc, txq, NULL, skb); | ||
206 | } | 265 | } |
266 | |||
267 | list_add_tail(&bf->list, &bf_head); | ||
268 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | ||
207 | } | 269 | } |
208 | 270 | ||
209 | if (sendbar) { | 271 | if (sendbar) { |
@@ -232,13 +294,16 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
232 | } | 294 | } |
233 | 295 | ||
234 | static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | 296 | static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, |
235 | u16 seqno) | 297 | struct ath_buf *bf) |
236 | { | 298 | { |
299 | struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); | ||
300 | u16 seqno = bf->bf_state.seqno; | ||
237 | int index, cindex; | 301 | int index, cindex; |
238 | 302 | ||
239 | index = ATH_BA_INDEX(tid->seq_start, seqno); | 303 | index = ATH_BA_INDEX(tid->seq_start, seqno); |
240 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 304 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
241 | __set_bit(cindex, tid->tx_buf); | 305 | __set_bit(cindex, tid->tx_buf); |
306 | fi->baw_tracked = 1; | ||
242 | 307 | ||
243 | if (index >= ((tid->baw_tail - tid->baw_head) & | 308 | if (index >= ((tid->baw_tail - tid->baw_head) & |
244 | (ATH_TID_MAX_BUFS - 1))) { | 309 | (ATH_TID_MAX_BUFS - 1))) { |
@@ -247,12 +312,6 @@ static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
247 | } | 312 | } |
248 | } | 313 | } |
249 | 314 | ||
250 | /* | ||
251 | * TODO: For frame(s) that are in the retry state, we will reuse the | ||
252 | * sequence number(s) without setting the retry bit. The | ||
253 | * alternative is to give up on these and BAR the receiver's window | ||
254 | * forward. | ||
255 | */ | ||
256 | static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | 315 | static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, |
257 | struct ath_atx_tid *tid) | 316 | struct ath_atx_tid *tid) |
258 | 317 | ||
@@ -266,7 +325,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
266 | memset(&ts, 0, sizeof(ts)); | 325 | memset(&ts, 0, sizeof(ts)); |
267 | INIT_LIST_HEAD(&bf_head); | 326 | INIT_LIST_HEAD(&bf_head); |
268 | 327 | ||
269 | while ((skb = __skb_dequeue(&tid->buf_q))) { | 328 | while ((skb = ath_tid_dequeue(tid))) { |
270 | fi = get_frame_info(skb); | 329 | fi = get_frame_info(skb); |
271 | bf = fi->bf; | 330 | bf = fi->bf; |
272 | 331 | ||
@@ -276,14 +335,8 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
276 | } | 335 | } |
277 | 336 | ||
278 | list_add_tail(&bf->list, &bf_head); | 337 | list_add_tail(&bf->list, &bf_head); |
279 | |||
280 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | ||
281 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | 338 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
282 | } | 339 | } |
283 | |||
284 | tid->seq_next = tid->seq_start; | ||
285 | tid->baw_tail = tid->baw_head; | ||
286 | tid->bar_index = -1; | ||
287 | } | 340 | } |
288 | 341 | ||
289 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, | 342 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, |
@@ -403,7 +456,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
403 | struct ieee80211_tx_rate rates[4]; | 456 | struct ieee80211_tx_rate rates[4]; |
404 | struct ath_frame_info *fi; | 457 | struct ath_frame_info *fi; |
405 | int nframes; | 458 | int nframes; |
406 | u8 tidno; | ||
407 | bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH); | 459 | bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH); |
408 | int i, retries; | 460 | int i, retries; |
409 | int bar_index = -1; | 461 | int bar_index = -1; |
@@ -429,7 +481,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
429 | while (bf) { | 481 | while (bf) { |
430 | bf_next = bf->bf_next; | 482 | bf_next = bf->bf_next; |
431 | 483 | ||
432 | if (!bf->bf_stale || bf_next != NULL) | 484 | if (!bf->bf_state.stale || bf_next != NULL) |
433 | list_move_tail(&bf->list, &bf_head); | 485 | list_move_tail(&bf->list, &bf_head); |
434 | 486 | ||
435 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0); | 487 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0); |
@@ -440,8 +492,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
440 | } | 492 | } |
441 | 493 | ||
442 | an = (struct ath_node *)sta->drv_priv; | 494 | an = (struct ath_node *)sta->drv_priv; |
443 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; | 495 | tid = ath_get_skb_tid(sc, an, skb); |
444 | tid = ATH_AN_2_TID(an, tidno); | ||
445 | seq_first = tid->seq_start; | 496 | seq_first = tid->seq_start; |
446 | isba = ts->ts_flags & ATH9K_TX_BA; | 497 | isba = ts->ts_flags & ATH9K_TX_BA; |
447 | 498 | ||
@@ -453,7 +504,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
453 | * Only BlockAcks have a TID and therefore normal Acks cannot be | 504 | * Only BlockAcks have a TID and therefore normal Acks cannot be |
454 | * checked | 505 | * checked |
455 | */ | 506 | */ |
456 | if (isba && tidno != ts->tid) | 507 | if (isba && tid->tidno != ts->tid) |
457 | txok = false; | 508 | txok = false; |
458 | 509 | ||
459 | isaggr = bf_isaggr(bf); | 510 | isaggr = bf_isaggr(bf); |
@@ -489,7 +540,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
489 | tx_info = IEEE80211_SKB_CB(skb); | 540 | tx_info = IEEE80211_SKB_CB(skb); |
490 | fi = get_frame_info(skb); | 541 | fi = get_frame_info(skb); |
491 | 542 | ||
492 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { | 543 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) || |
544 | !tid->active) { | ||
493 | /* | 545 | /* |
494 | * Outside of the current BlockAck window, | 546 | * Outside of the current BlockAck window, |
495 | * maybe part of a previous session | 547 | * maybe part of a previous session |
@@ -522,7 +574,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
522 | * not a holding desc. | 574 | * not a holding desc. |
523 | */ | 575 | */ |
524 | INIT_LIST_HEAD(&bf_head); | 576 | INIT_LIST_HEAD(&bf_head); |
525 | if (bf_next != NULL || !bf_last->bf_stale) | 577 | if (bf_next != NULL || !bf_last->bf_state.stale) |
526 | list_move_tail(&bf->list, &bf_head); | 578 | list_move_tail(&bf->list, &bf_head); |
527 | 579 | ||
528 | if (!txpending) { | 580 | if (!txpending) { |
@@ -546,7 +598,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
546 | ieee80211_sta_eosp(sta); | 598 | ieee80211_sta_eosp(sta); |
547 | } | 599 | } |
548 | /* retry the un-acked ones */ | 600 | /* retry the un-acked ones */ |
549 | if (bf->bf_next == NULL && bf_last->bf_stale) { | 601 | if (bf->bf_next == NULL && bf_last->bf_state.stale) { |
550 | struct ath_buf *tbf; | 602 | struct ath_buf *tbf; |
551 | 603 | ||
552 | tbf = ath_clone_txbuf(sc, bf_last); | 604 | tbf = ath_clone_txbuf(sc, bf_last); |
@@ -583,7 +635,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
583 | if (an->sleeping) | 635 | if (an->sleeping) |
584 | ieee80211_sta_set_buffered(sta, tid->tidno, true); | 636 | ieee80211_sta_set_buffered(sta, tid->tidno, true); |
585 | 637 | ||
586 | skb_queue_splice(&bf_pending, &tid->buf_q); | 638 | skb_queue_splice_tail(&bf_pending, &tid->retry_q); |
587 | if (!an->sleeping) { | 639 | if (!an->sleeping) { |
588 | ath_tx_queue_tid(txq, tid); | 640 | ath_tx_queue_tid(txq, tid); |
589 | 641 | ||
@@ -641,7 +693,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | |||
641 | } else | 693 | } else |
642 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok); | 694 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok); |
643 | 695 | ||
644 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !flush) | 696 | if (!flush) |
645 | ath_txq_schedule(sc, txq); | 697 | ath_txq_schedule(sc, txq); |
646 | } | 698 | } |
647 | 699 | ||
@@ -815,15 +867,20 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
815 | 867 | ||
816 | static struct ath_buf * | 868 | static struct ath_buf * |
817 | ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, | 869 | ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, |
818 | struct ath_atx_tid *tid) | 870 | struct ath_atx_tid *tid, struct sk_buff_head **q) |
819 | { | 871 | { |
872 | struct ieee80211_tx_info *tx_info; | ||
820 | struct ath_frame_info *fi; | 873 | struct ath_frame_info *fi; |
821 | struct sk_buff *skb; | 874 | struct sk_buff *skb; |
822 | struct ath_buf *bf; | 875 | struct ath_buf *bf; |
823 | u16 seqno; | 876 | u16 seqno; |
824 | 877 | ||
825 | while (1) { | 878 | while (1) { |
826 | skb = skb_peek(&tid->buf_q); | 879 | *q = &tid->retry_q; |
880 | if (skb_queue_empty(*q)) | ||
881 | *q = &tid->buf_q; | ||
882 | |||
883 | skb = skb_peek(*q); | ||
827 | if (!skb) | 884 | if (!skb) |
828 | break; | 885 | break; |
829 | 886 | ||
@@ -831,14 +888,26 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, | |||
831 | bf = fi->bf; | 888 | bf = fi->bf; |
832 | if (!fi->bf) | 889 | if (!fi->bf) |
833 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | 890 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); |
891 | else | ||
892 | bf->bf_state.stale = false; | ||
834 | 893 | ||
835 | if (!bf) { | 894 | if (!bf) { |
836 | __skb_unlink(skb, &tid->buf_q); | 895 | __skb_unlink(skb, *q); |
837 | ath_txq_skb_done(sc, txq, skb); | 896 | ath_txq_skb_done(sc, txq, skb); |
838 | ieee80211_free_txskb(sc->hw, skb); | 897 | ieee80211_free_txskb(sc->hw, skb); |
839 | continue; | 898 | continue; |
840 | } | 899 | } |
841 | 900 | ||
901 | bf->bf_next = NULL; | ||
902 | bf->bf_lastbf = bf; | ||
903 | |||
904 | tx_info = IEEE80211_SKB_CB(skb); | ||
905 | tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
906 | if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { | ||
907 | bf->bf_state.bf_type = 0; | ||
908 | return bf; | ||
909 | } | ||
910 | |||
842 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; | 911 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; |
843 | seqno = bf->bf_state.seqno; | 912 | seqno = bf->bf_state.seqno; |
844 | 913 | ||
@@ -852,73 +921,52 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, | |||
852 | 921 | ||
853 | INIT_LIST_HEAD(&bf_head); | 922 | INIT_LIST_HEAD(&bf_head); |
854 | list_add(&bf->list, &bf_head); | 923 | list_add(&bf->list, &bf_head); |
855 | __skb_unlink(skb, &tid->buf_q); | 924 | __skb_unlink(skb, *q); |
856 | ath_tx_update_baw(sc, tid, seqno); | 925 | ath_tx_update_baw(sc, tid, seqno); |
857 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | 926 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
858 | continue; | 927 | continue; |
859 | } | 928 | } |
860 | 929 | ||
861 | bf->bf_next = NULL; | ||
862 | bf->bf_lastbf = bf; | ||
863 | return bf; | 930 | return bf; |
864 | } | 931 | } |
865 | 932 | ||
866 | return NULL; | 933 | return NULL; |
867 | } | 934 | } |
868 | 935 | ||
869 | static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | 936 | static bool |
870 | struct ath_txq *txq, | 937 | ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, |
871 | struct ath_atx_tid *tid, | 938 | struct ath_atx_tid *tid, struct list_head *bf_q, |
872 | struct list_head *bf_q, | 939 | struct ath_buf *bf_first, struct sk_buff_head *tid_q, |
873 | int *aggr_len) | 940 | int *aggr_len) |
874 | { | 941 | { |
875 | #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) | 942 | #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) |
876 | struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; | 943 | struct ath_buf *bf = bf_first, *bf_prev = NULL; |
877 | int rl = 0, nframes = 0, ndelim, prev_al = 0; | 944 | int nframes = 0, ndelim; |
878 | u16 aggr_limit = 0, al = 0, bpad = 0, | 945 | u16 aggr_limit = 0, al = 0, bpad = 0, |
879 | al_delta, h_baw = tid->baw_size / 2; | 946 | al_delta, h_baw = tid->baw_size / 2; |
880 | enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; | ||
881 | struct ieee80211_tx_info *tx_info; | 947 | struct ieee80211_tx_info *tx_info; |
882 | struct ath_frame_info *fi; | 948 | struct ath_frame_info *fi; |
883 | struct sk_buff *skb; | 949 | struct sk_buff *skb; |
950 | bool closed = false; | ||
884 | 951 | ||
885 | do { | 952 | bf = bf_first; |
886 | bf = ath_tx_get_tid_subframe(sc, txq, tid); | 953 | aggr_limit = ath_lookup_rate(sc, bf, tid); |
887 | if (!bf) { | ||
888 | status = ATH_AGGR_BAW_CLOSED; | ||
889 | break; | ||
890 | } | ||
891 | 954 | ||
955 | do { | ||
892 | skb = bf->bf_mpdu; | 956 | skb = bf->bf_mpdu; |
893 | fi = get_frame_info(skb); | 957 | fi = get_frame_info(skb); |
894 | 958 | ||
895 | if (!bf_first) | ||
896 | bf_first = bf; | ||
897 | |||
898 | if (!rl) { | ||
899 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | ||
900 | aggr_limit = ath_lookup_rate(sc, bf, tid); | ||
901 | rl = 1; | ||
902 | } | ||
903 | |||
904 | /* do not exceed aggregation limit */ | 959 | /* do not exceed aggregation limit */ |
905 | al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; | 960 | al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; |
961 | if (nframes) { | ||
962 | if (aggr_limit < al + bpad + al_delta || | ||
963 | ath_lookup_legacy(bf) || nframes >= h_baw) | ||
964 | break; | ||
906 | 965 | ||
907 | if (nframes && | 966 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); |
908 | ((aggr_limit < (al + bpad + al_delta + prev_al)) || | 967 | if ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) || |
909 | ath_lookup_legacy(bf))) { | 968 | !(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) |
910 | status = ATH_AGGR_LIMITED; | 969 | break; |
911 | break; | ||
912 | } | ||
913 | |||
914 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
915 | if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) | ||
916 | break; | ||
917 | |||
918 | /* do not exceed subframe limit */ | ||
919 | if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { | ||
920 | status = ATH_AGGR_LIMITED; | ||
921 | break; | ||
922 | } | 970 | } |
923 | 971 | ||
924 | /* add padding for previous frame to aggregation length */ | 972 | /* add padding for previous frame to aggregation length */ |
@@ -936,22 +984,37 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
936 | bf->bf_next = NULL; | 984 | bf->bf_next = NULL; |
937 | 985 | ||
938 | /* link buffers of this frame to the aggregate */ | 986 | /* link buffers of this frame to the aggregate */ |
939 | if (!fi->retries) | 987 | if (!fi->baw_tracked) |
940 | ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); | 988 | ath_tx_addto_baw(sc, tid, bf); |
941 | bf->bf_state.ndelim = ndelim; | 989 | bf->bf_state.ndelim = ndelim; |
942 | 990 | ||
943 | __skb_unlink(skb, &tid->buf_q); | 991 | __skb_unlink(skb, tid_q); |
944 | list_add_tail(&bf->list, bf_q); | 992 | list_add_tail(&bf->list, bf_q); |
945 | if (bf_prev) | 993 | if (bf_prev) |
946 | bf_prev->bf_next = bf; | 994 | bf_prev->bf_next = bf; |
947 | 995 | ||
948 | bf_prev = bf; | 996 | bf_prev = bf; |
949 | 997 | ||
950 | } while (!skb_queue_empty(&tid->buf_q)); | 998 | bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); |
999 | if (!bf) { | ||
1000 | closed = true; | ||
1001 | break; | ||
1002 | } | ||
1003 | } while (ath_tid_has_buffered(tid)); | ||
1004 | |||
1005 | bf = bf_first; | ||
1006 | bf->bf_lastbf = bf_prev; | ||
1007 | |||
1008 | if (bf == bf_prev) { | ||
1009 | al = get_frame_info(bf->bf_mpdu)->framelen; | ||
1010 | bf->bf_state.bf_type = BUF_AMPDU; | ||
1011 | } else { | ||
1012 | TX_STAT_INC(txq->axq_qnum, a_aggr); | ||
1013 | } | ||
951 | 1014 | ||
952 | *aggr_len = al; | 1015 | *aggr_len = al; |
953 | 1016 | ||
954 | return status; | 1017 | return closed; |
955 | #undef PADBYTES | 1018 | #undef PADBYTES |
956 | } | 1019 | } |
957 | 1020 | ||
@@ -1023,7 +1086,7 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop) | |||
1023 | } | 1086 | } |
1024 | 1087 | ||
1025 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | 1088 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, |
1026 | struct ath_tx_info *info, int len) | 1089 | struct ath_tx_info *info, int len, bool rts) |
1027 | { | 1090 | { |
1028 | struct ath_hw *ah = sc->sc_ah; | 1091 | struct ath_hw *ah = sc->sc_ah; |
1029 | struct sk_buff *skb; | 1092 | struct sk_buff *skb; |
@@ -1032,6 +1095,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
1032 | const struct ieee80211_rate *rate; | 1095 | const struct ieee80211_rate *rate; |
1033 | struct ieee80211_hdr *hdr; | 1096 | struct ieee80211_hdr *hdr; |
1034 | struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); | 1097 | struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); |
1098 | u32 rts_thresh = sc->hw->wiphy->rts_threshold; | ||
1035 | int i; | 1099 | int i; |
1036 | u8 rix = 0; | 1100 | u8 rix = 0; |
1037 | 1101 | ||
@@ -1054,7 +1118,17 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
1054 | rix = rates[i].idx; | 1118 | rix = rates[i].idx; |
1055 | info->rates[i].Tries = rates[i].count; | 1119 | info->rates[i].Tries = rates[i].count; |
1056 | 1120 | ||
1057 | if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | 1121 | /* |
1122 | * Handle RTS threshold for unaggregated HT frames. | ||
1123 | */ | ||
1124 | if (bf_isampdu(bf) && !bf_isaggr(bf) && | ||
1125 | (rates[i].flags & IEEE80211_TX_RC_MCS) && | ||
1126 | unlikely(rts_thresh != (u32) -1)) { | ||
1127 | if (!rts_thresh || (len > rts_thresh)) | ||
1128 | rts = true; | ||
1129 | } | ||
1130 | |||
1131 | if (rts || rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
1058 | info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; | 1132 | info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; |
1059 | info->flags |= ATH9K_TXDESC_RTSENA; | 1133 | info->flags |= ATH9K_TXDESC_RTSENA; |
1060 | } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 1134 | } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
@@ -1147,6 +1221,8 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
1147 | struct ath_hw *ah = sc->sc_ah; | 1221 | struct ath_hw *ah = sc->sc_ah; |
1148 | struct ath_buf *bf_first = NULL; | 1222 | struct ath_buf *bf_first = NULL; |
1149 | struct ath_tx_info info; | 1223 | struct ath_tx_info info; |
1224 | u32 rts_thresh = sc->hw->wiphy->rts_threshold; | ||
1225 | bool rts = false; | ||
1150 | 1226 | ||
1151 | memset(&info, 0, sizeof(info)); | 1227 | memset(&info, 0, sizeof(info)); |
1152 | info.is_first = true; | 1228 | info.is_first = true; |
@@ -1183,7 +1259,22 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
1183 | info.flags |= (u32) bf->bf_state.bfs_paprd << | 1259 | info.flags |= (u32) bf->bf_state.bfs_paprd << |
1184 | ATH9K_TXDESC_PAPRD_S; | 1260 | ATH9K_TXDESC_PAPRD_S; |
1185 | 1261 | ||
1186 | ath_buf_set_rate(sc, bf, &info, len); | 1262 | /* |
1263 | * mac80211 doesn't handle RTS threshold for HT because | ||
1264 | * the decision has to be taken based on AMPDU length | ||
1265 | * and aggregation is done entirely inside ath9k. | ||
1266 | * Set the RTS/CTS flag for the first subframe based | ||
1267 | * on the threshold. | ||
1268 | */ | ||
1269 | if (aggr && (bf == bf_first) && | ||
1270 | unlikely(rts_thresh != (u32) -1)) { | ||
1271 | /* | ||
1272 | * "len" is the size of the entire AMPDU. | ||
1273 | */ | ||
1274 | if (!rts_thresh || (len > rts_thresh)) | ||
1275 | rts = true; | ||
1276 | } | ||
1277 | ath_buf_set_rate(sc, bf, &info, len, rts); | ||
1187 | } | 1278 | } |
1188 | 1279 | ||
1189 | info.buf_addr[0] = bf->bf_buf_addr; | 1280 | info.buf_addr[0] = bf->bf_buf_addr; |
@@ -1212,53 +1303,86 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
1212 | } | 1303 | } |
1213 | } | 1304 | } |
1214 | 1305 | ||
1215 | static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | 1306 | static void |
1216 | struct ath_atx_tid *tid) | 1307 | ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, |
1308 | struct ath_atx_tid *tid, struct list_head *bf_q, | ||
1309 | struct ath_buf *bf_first, struct sk_buff_head *tid_q) | ||
1217 | { | 1310 | { |
1218 | struct ath_buf *bf; | 1311 | struct ath_buf *bf = bf_first, *bf_prev = NULL; |
1219 | enum ATH_AGGR_STATUS status; | 1312 | struct sk_buff *skb; |
1220 | struct ieee80211_tx_info *tx_info; | 1313 | int nframes = 0; |
1221 | struct list_head bf_q; | ||
1222 | int aggr_len; | ||
1223 | 1314 | ||
1224 | do { | 1315 | do { |
1225 | if (skb_queue_empty(&tid->buf_q)) | 1316 | struct ieee80211_tx_info *tx_info; |
1226 | return; | 1317 | skb = bf->bf_mpdu; |
1227 | 1318 | ||
1228 | INIT_LIST_HEAD(&bf_q); | 1319 | nframes++; |
1320 | __skb_unlink(skb, tid_q); | ||
1321 | list_add_tail(&bf->list, bf_q); | ||
1322 | if (bf_prev) | ||
1323 | bf_prev->bf_next = bf; | ||
1324 | bf_prev = bf; | ||
1229 | 1325 | ||
1230 | status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len); | 1326 | if (nframes >= 2) |
1327 | break; | ||
1231 | 1328 | ||
1232 | /* | 1329 | bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); |
1233 | * no frames picked up to be aggregated; | 1330 | if (!bf) |
1234 | * block-ack window is not open. | ||
1235 | */ | ||
1236 | if (list_empty(&bf_q)) | ||
1237 | break; | 1331 | break; |
1238 | 1332 | ||
1239 | bf = list_first_entry(&bf_q, struct ath_buf, list); | ||
1240 | bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); | ||
1241 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); | 1333 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); |
1334 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1335 | break; | ||
1242 | 1336 | ||
1243 | if (tid->ac->clear_ps_filter) { | 1337 | ath_set_rates(tid->an->vif, tid->an->sta, bf); |
1244 | tid->ac->clear_ps_filter = false; | 1338 | } while (1); |
1245 | tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1339 | } |
1246 | } else { | ||
1247 | tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
1248 | } | ||
1249 | 1340 | ||
1250 | /* if only one frame, send as non-aggregate */ | 1341 | static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, |
1251 | if (bf == bf->bf_lastbf) { | 1342 | struct ath_atx_tid *tid, bool *stop) |
1252 | aggr_len = get_frame_info(bf->bf_mpdu)->framelen; | 1343 | { |
1253 | bf->bf_state.bf_type = BUF_AMPDU; | 1344 | struct ath_buf *bf; |
1254 | } else { | 1345 | struct ieee80211_tx_info *tx_info; |
1255 | TX_STAT_INC(txq->axq_qnum, a_aggr); | 1346 | struct sk_buff_head *tid_q; |
1256 | } | 1347 | struct list_head bf_q; |
1348 | int aggr_len = 0; | ||
1349 | bool aggr, last = true; | ||
1350 | |||
1351 | if (!ath_tid_has_buffered(tid)) | ||
1352 | return false; | ||
1353 | |||
1354 | INIT_LIST_HEAD(&bf_q); | ||
1355 | |||
1356 | bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); | ||
1357 | if (!bf) | ||
1358 | return false; | ||
1359 | |||
1360 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
1361 | aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); | ||
1362 | if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) || | ||
1363 | (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) { | ||
1364 | *stop = true; | ||
1365 | return false; | ||
1366 | } | ||
1257 | 1367 | ||
1258 | ath_tx_fill_desc(sc, bf, txq, aggr_len); | 1368 | ath_set_rates(tid->an->vif, tid->an->sta, bf); |
1259 | ath_tx_txqaddbuf(sc, txq, &bf_q, false); | 1369 | if (aggr) |
1260 | } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH && | 1370 | last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf, |
1261 | status != ATH_AGGR_BAW_CLOSED); | 1371 | tid_q, &aggr_len); |
1372 | else | ||
1373 | ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q); | ||
1374 | |||
1375 | if (list_empty(&bf_q)) | ||
1376 | return false; | ||
1377 | |||
1378 | if (tid->ac->clear_ps_filter || tid->an->no_ps_filter) { | ||
1379 | tid->ac->clear_ps_filter = false; | ||
1380 | tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
1381 | } | ||
1382 | |||
1383 | ath_tx_fill_desc(sc, bf, txq, aggr_len); | ||
1384 | ath_tx_txqaddbuf(sc, txq, &bf_q, false); | ||
1385 | return true; | ||
1262 | } | 1386 | } |
1263 | 1387 | ||
1264 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 1388 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
@@ -1282,6 +1406,9 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1282 | an->mpdudensity = density; | 1406 | an->mpdudensity = density; |
1283 | } | 1407 | } |
1284 | 1408 | ||
1409 | /* force sequence number allocation for pending frames */ | ||
1410 | ath_tx_tid_change_state(sc, txtid); | ||
1411 | |||
1285 | txtid->active = true; | 1412 | txtid->active = true; |
1286 | txtid->paused = true; | 1413 | txtid->paused = true; |
1287 | *ssn = txtid->seq_start = txtid->seq_next; | 1414 | *ssn = txtid->seq_start = txtid->seq_next; |
@@ -1301,8 +1428,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
1301 | 1428 | ||
1302 | ath_txq_lock(sc, txq); | 1429 | ath_txq_lock(sc, txq); |
1303 | txtid->active = false; | 1430 | txtid->active = false; |
1304 | txtid->paused = true; | 1431 | txtid->paused = false; |
1305 | ath_tx_flush_tid(sc, txtid); | 1432 | ath_tx_flush_tid(sc, txtid); |
1433 | ath_tx_tid_change_state(sc, txtid); | ||
1306 | ath_txq_unlock_complete(sc, txq); | 1434 | ath_txq_unlock_complete(sc, txq); |
1307 | } | 1435 | } |
1308 | 1436 | ||
@@ -1326,7 +1454,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, | |||
1326 | 1454 | ||
1327 | ath_txq_lock(sc, txq); | 1455 | ath_txq_lock(sc, txq); |
1328 | 1456 | ||
1329 | buffered = !skb_queue_empty(&tid->buf_q); | 1457 | buffered = ath_tid_has_buffered(tid); |
1330 | 1458 | ||
1331 | tid->sched = false; | 1459 | tid->sched = false; |
1332 | list_del(&tid->list); | 1460 | list_del(&tid->list); |
@@ -1358,7 +1486,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | |||
1358 | ath_txq_lock(sc, txq); | 1486 | ath_txq_lock(sc, txq); |
1359 | ac->clear_ps_filter = true; | 1487 | ac->clear_ps_filter = true; |
1360 | 1488 | ||
1361 | if (!skb_queue_empty(&tid->buf_q) && !tid->paused) { | 1489 | if (!tid->paused && ath_tid_has_buffered(tid)) { |
1362 | ath_tx_queue_tid(txq, tid); | 1490 | ath_tx_queue_tid(txq, tid); |
1363 | ath_txq_schedule(sc, txq); | 1491 | ath_txq_schedule(sc, txq); |
1364 | } | 1492 | } |
@@ -1383,7 +1511,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1383 | tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; | 1511 | tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; |
1384 | tid->paused = false; | 1512 | tid->paused = false; |
1385 | 1513 | ||
1386 | if (!skb_queue_empty(&tid->buf_q)) { | 1514 | if (ath_tid_has_buffered(tid)) { |
1387 | ath_tx_queue_tid(txq, tid); | 1515 | ath_tx_queue_tid(txq, tid); |
1388 | ath_txq_schedule(sc, txq); | 1516 | ath_txq_schedule(sc, txq); |
1389 | } | 1517 | } |
@@ -1403,6 +1531,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
1403 | struct ieee80211_tx_info *info; | 1531 | struct ieee80211_tx_info *info; |
1404 | struct list_head bf_q; | 1532 | struct list_head bf_q; |
1405 | struct ath_buf *bf_tail = NULL, *bf; | 1533 | struct ath_buf *bf_tail = NULL, *bf; |
1534 | struct sk_buff_head *tid_q; | ||
1406 | int sent = 0; | 1535 | int sent = 0; |
1407 | int i; | 1536 | int i; |
1408 | 1537 | ||
@@ -1418,15 +1547,15 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
1418 | continue; | 1547 | continue; |
1419 | 1548 | ||
1420 | ath_txq_lock(sc, tid->ac->txq); | 1549 | ath_txq_lock(sc, tid->ac->txq); |
1421 | while (!skb_queue_empty(&tid->buf_q) && nframes > 0) { | 1550 | while (nframes > 0) { |
1422 | bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid); | 1551 | bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q); |
1423 | if (!bf) | 1552 | if (!bf) |
1424 | break; | 1553 | break; |
1425 | 1554 | ||
1426 | __skb_unlink(bf->bf_mpdu, &tid->buf_q); | 1555 | __skb_unlink(bf->bf_mpdu, tid_q); |
1427 | list_add_tail(&bf->list, &bf_q); | 1556 | list_add_tail(&bf->list, &bf_q); |
1428 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | 1557 | ath_set_rates(tid->an->vif, tid->an->sta, bf); |
1429 | ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); | 1558 | ath_tx_addto_baw(sc, tid, bf); |
1430 | bf->bf_state.bf_type &= ~BUF_AGGR; | 1559 | bf->bf_state.bf_type &= ~BUF_AGGR; |
1431 | if (bf_tail) | 1560 | if (bf_tail) |
1432 | bf_tail->bf_next = bf; | 1561 | bf_tail->bf_next = bf; |
@@ -1436,7 +1565,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
1436 | sent++; | 1565 | sent++; |
1437 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); | 1566 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); |
1438 | 1567 | ||
1439 | if (skb_queue_empty(&tid->buf_q)) | 1568 | if (an->sta && !ath_tid_has_buffered(tid)) |
1440 | ieee80211_sta_set_buffered(an->sta, i, false); | 1569 | ieee80211_sta_set_buffered(an->sta, i, false); |
1441 | } | 1570 | } |
1442 | ath_txq_unlock_complete(sc, tid->ac->txq); | 1571 | ath_txq_unlock_complete(sc, tid->ac->txq); |
@@ -1595,7 +1724,7 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, | |||
1595 | while (!list_empty(list)) { | 1724 | while (!list_empty(list)) { |
1596 | bf = list_first_entry(list, struct ath_buf, list); | 1725 | bf = list_first_entry(list, struct ath_buf, list); |
1597 | 1726 | ||
1598 | if (bf->bf_stale) { | 1727 | if (bf->bf_state.stale) { |
1599 | list_del(&bf->list); | 1728 | list_del(&bf->list); |
1600 | 1729 | ||
1601 | ath_tx_return_buffer(sc, bf); | 1730 | ath_tx_return_buffer(sc, bf); |
@@ -1689,25 +1818,27 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) | |||
1689 | */ | 1818 | */ |
1690 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | 1819 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) |
1691 | { | 1820 | { |
1692 | struct ath_atx_ac *ac, *ac_tmp, *last_ac; | 1821 | struct ath_atx_ac *ac, *last_ac; |
1693 | struct ath_atx_tid *tid, *last_tid; | 1822 | struct ath_atx_tid *tid, *last_tid; |
1823 | bool sent = false; | ||
1694 | 1824 | ||
1695 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) || | 1825 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) || |
1696 | list_empty(&txq->axq_acq) || | 1826 | list_empty(&txq->axq_acq)) |
1697 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) | ||
1698 | return; | 1827 | return; |
1699 | 1828 | ||
1700 | rcu_read_lock(); | 1829 | rcu_read_lock(); |
1701 | 1830 | ||
1702 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); | ||
1703 | last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list); | 1831 | last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list); |
1832 | while (!list_empty(&txq->axq_acq)) { | ||
1833 | bool stop = false; | ||
1704 | 1834 | ||
1705 | list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { | 1835 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); |
1706 | last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); | 1836 | last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); |
1707 | list_del(&ac->list); | 1837 | list_del(&ac->list); |
1708 | ac->sched = false; | 1838 | ac->sched = false; |
1709 | 1839 | ||
1710 | while (!list_empty(&ac->tid_q)) { | 1840 | while (!list_empty(&ac->tid_q)) { |
1841 | |||
1711 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, | 1842 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, |
1712 | list); | 1843 | list); |
1713 | list_del(&tid->list); | 1844 | list_del(&tid->list); |
@@ -1716,17 +1847,17 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1716 | if (tid->paused) | 1847 | if (tid->paused) |
1717 | continue; | 1848 | continue; |
1718 | 1849 | ||
1719 | ath_tx_sched_aggr(sc, txq, tid); | 1850 | if (ath_tx_sched_aggr(sc, txq, tid, &stop)) |
1851 | sent = true; | ||
1720 | 1852 | ||
1721 | /* | 1853 | /* |
1722 | * add tid to round-robin queue if more frames | 1854 | * add tid to round-robin queue if more frames |
1723 | * are pending for the tid | 1855 | * are pending for the tid |
1724 | */ | 1856 | */ |
1725 | if (!skb_queue_empty(&tid->buf_q)) | 1857 | if (ath_tid_has_buffered(tid)) |
1726 | ath_tx_queue_tid(txq, tid); | 1858 | ath_tx_queue_tid(txq, tid); |
1727 | 1859 | ||
1728 | if (tid == last_tid || | 1860 | if (stop || tid == last_tid) |
1729 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) | ||
1730 | break; | 1861 | break; |
1731 | } | 1862 | } |
1732 | 1863 | ||
@@ -1735,9 +1866,17 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1735 | list_add_tail(&ac->list, &txq->axq_acq); | 1866 | list_add_tail(&ac->list, &txq->axq_acq); |
1736 | } | 1867 | } |
1737 | 1868 | ||
1738 | if (ac == last_ac || | 1869 | if (stop) |
1739 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) | ||
1740 | break; | 1870 | break; |
1871 | |||
1872 | if (ac == last_ac) { | ||
1873 | if (!sent) | ||
1874 | break; | ||
1875 | |||
1876 | sent = false; | ||
1877 | last_ac = list_entry(txq->axq_acq.prev, | ||
1878 | struct ath_atx_ac, list); | ||
1879 | } | ||
1741 | } | 1880 | } |
1742 | 1881 | ||
1743 | rcu_read_unlock(); | 1882 | rcu_read_unlock(); |
@@ -1816,58 +1955,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1816 | } | 1955 | } |
1817 | } | 1956 | } |
1818 | 1957 | ||
1819 | static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_txq *txq, | ||
1820 | struct ath_atx_tid *tid, struct sk_buff *skb, | ||
1821 | struct ath_tx_control *txctl) | ||
1822 | { | ||
1823 | struct ath_frame_info *fi = get_frame_info(skb); | ||
1824 | struct list_head bf_head; | ||
1825 | struct ath_buf *bf; | ||
1826 | |||
1827 | /* | ||
1828 | * Do not queue to h/w when any of the following conditions is true: | ||
1829 | * - there are pending frames in software queue | ||
1830 | * - the TID is currently paused for ADDBA/BAR request | ||
1831 | * - seqno is not within block-ack window | ||
1832 | * - h/w queue depth exceeds low water mark | ||
1833 | */ | ||
1834 | if ((!skb_queue_empty(&tid->buf_q) || tid->paused || | ||
1835 | !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) || | ||
1836 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) && | ||
1837 | txq != sc->tx.uapsdq) { | ||
1838 | /* | ||
1839 | * Add this frame to software queue for scheduling later | ||
1840 | * for aggregation. | ||
1841 | */ | ||
1842 | TX_STAT_INC(txq->axq_qnum, a_queued_sw); | ||
1843 | __skb_queue_tail(&tid->buf_q, skb); | ||
1844 | if (!txctl->an || !txctl->an->sleeping) | ||
1845 | ath_tx_queue_tid(txq, tid); | ||
1846 | return; | ||
1847 | } | ||
1848 | |||
1849 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | ||
1850 | if (!bf) { | ||
1851 | ath_txq_skb_done(sc, txq, skb); | ||
1852 | ieee80211_free_txskb(sc->hw, skb); | ||
1853 | return; | ||
1854 | } | ||
1855 | |||
1856 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | ||
1857 | bf->bf_state.bf_type = BUF_AMPDU; | ||
1858 | INIT_LIST_HEAD(&bf_head); | ||
1859 | list_add(&bf->list, &bf_head); | ||
1860 | |||
1861 | /* Add sub-frame to BAW */ | ||
1862 | ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); | ||
1863 | |||
1864 | /* Queue to h/w without aggregation */ | ||
1865 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); | ||
1866 | bf->bf_lastbf = bf; | ||
1867 | ath_tx_fill_desc(sc, bf, txq, fi->framelen); | ||
1868 | ath_tx_txqaddbuf(sc, txq, &bf_head, false); | ||
1869 | } | ||
1870 | |||
1871 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | 1958 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, |
1872 | struct ath_atx_tid *tid, struct sk_buff *skb) | 1959 | struct ath_atx_tid *tid, struct sk_buff *skb) |
1873 | { | 1960 | { |
@@ -2010,6 +2097,7 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2010 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2097 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2011 | struct ieee80211_sta *sta = txctl->sta; | 2098 | struct ieee80211_sta *sta = txctl->sta; |
2012 | struct ieee80211_vif *vif = info->control.vif; | 2099 | struct ieee80211_vif *vif = info->control.vif; |
2100 | struct ath_vif *avp; | ||
2013 | struct ath_softc *sc = hw->priv; | 2101 | struct ath_softc *sc = hw->priv; |
2014 | int frmlen = skb->len + FCS_LEN; | 2102 | int frmlen = skb->len + FCS_LEN; |
2015 | int padpos, padsize; | 2103 | int padpos, padsize; |
@@ -2017,6 +2105,10 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2017 | /* NOTE: sta can be NULL according to net/mac80211.h */ | 2105 | /* NOTE: sta can be NULL according to net/mac80211.h */ |
2018 | if (sta) | 2106 | if (sta) |
2019 | txctl->an = (struct ath_node *)sta->drv_priv; | 2107 | txctl->an = (struct ath_node *)sta->drv_priv; |
2108 | else if (vif && ieee80211_is_data(hdr->frame_control)) { | ||
2109 | avp = (void *)vif->drv_priv; | ||
2110 | txctl->an = &avp->mcast_node; | ||
2111 | } | ||
2020 | 2112 | ||
2021 | if (info->control.hw_key) | 2113 | if (info->control.hw_key) |
2022 | frmlen += info->control.hw_key->icv_len; | 2114 | frmlen += info->control.hw_key->icv_len; |
@@ -2066,7 +2158,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2066 | struct ath_txq *txq = txctl->txq; | 2158 | struct ath_txq *txq = txctl->txq; |
2067 | struct ath_atx_tid *tid = NULL; | 2159 | struct ath_atx_tid *tid = NULL; |
2068 | struct ath_buf *bf; | 2160 | struct ath_buf *bf; |
2069 | u8 tidno; | ||
2070 | int q; | 2161 | int q; |
2071 | int ret; | 2162 | int ret; |
2072 | 2163 | ||
@@ -2094,22 +2185,25 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2094 | ath_txq_unlock(sc, txq); | 2185 | ath_txq_unlock(sc, txq); |
2095 | txq = sc->tx.uapsdq; | 2186 | txq = sc->tx.uapsdq; |
2096 | ath_txq_lock(sc, txq); | 2187 | ath_txq_lock(sc, txq); |
2097 | } | 2188 | } else if (txctl->an && |
2098 | 2189 | ieee80211_is_data_present(hdr->frame_control)) { | |
2099 | if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) { | 2190 | tid = ath_get_skb_tid(sc, txctl->an, skb); |
2100 | tidno = ieee80211_get_qos_ctl(hdr)[0] & | ||
2101 | IEEE80211_QOS_CTL_TID_MASK; | ||
2102 | tid = ATH_AN_2_TID(txctl->an, tidno); | ||
2103 | 2191 | ||
2104 | WARN_ON(tid->ac->txq != txctl->txq); | 2192 | WARN_ON(tid->ac->txq != txctl->txq); |
2105 | } | ||
2106 | 2193 | ||
2107 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) { | 2194 | if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) |
2195 | tid->ac->clear_ps_filter = true; | ||
2196 | |||
2108 | /* | 2197 | /* |
2109 | * Try aggregation if it's a unicast data frame | 2198 | * Add this frame to software queue for scheduling later |
2110 | * and the destination is HT capable. | 2199 | * for aggregation. |
2111 | */ | 2200 | */ |
2112 | ath_tx_send_ampdu(sc, txq, tid, skb, txctl); | 2201 | TX_STAT_INC(txq->axq_qnum, a_queued_sw); |
2202 | __skb_queue_tail(&tid->buf_q, skb); | ||
2203 | if (!txctl->an->sleeping) | ||
2204 | ath_tx_queue_tid(txq, tid); | ||
2205 | |||
2206 | ath_txq_schedule(sc, txq); | ||
2113 | goto out; | 2207 | goto out; |
2114 | } | 2208 | } |
2115 | 2209 | ||
@@ -2168,7 +2262,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
2168 | 2262 | ||
2169 | bf->bf_lastbf = bf; | 2263 | bf->bf_lastbf = bf; |
2170 | ath_set_rates(vif, NULL, bf); | 2264 | ath_set_rates(vif, NULL, bf); |
2171 | ath_buf_set_rate(sc, bf, &info, fi->framelen); | 2265 | ath_buf_set_rate(sc, bf, &info, fi->framelen, false); |
2172 | duration += info.rates[0].PktDuration; | 2266 | duration += info.rates[0].PktDuration; |
2173 | if (bf_tail) | 2267 | if (bf_tail) |
2174 | bf_tail->bf_next = bf; | 2268 | bf_tail->bf_next = bf; |
@@ -2372,8 +2466,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2372 | 2466 | ||
2373 | if (list_empty(&txq->axq_q)) { | 2467 | if (list_empty(&txq->axq_q)) { |
2374 | txq->axq_link = NULL; | 2468 | txq->axq_link = NULL; |
2375 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 2469 | ath_txq_schedule(sc, txq); |
2376 | ath_txq_schedule(sc, txq); | ||
2377 | break; | 2470 | break; |
2378 | } | 2471 | } |
2379 | bf = list_first_entry(&txq->axq_q, struct ath_buf, list); | 2472 | bf = list_first_entry(&txq->axq_q, struct ath_buf, list); |
@@ -2387,7 +2480,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2387 | * it with the STALE flag. | 2480 | * it with the STALE flag. |
2388 | */ | 2481 | */ |
2389 | bf_held = NULL; | 2482 | bf_held = NULL; |
2390 | if (bf->bf_stale) { | 2483 | if (bf->bf_state.stale) { |
2391 | bf_held = bf; | 2484 | bf_held = bf; |
2392 | if (list_is_last(&bf_held->list, &txq->axq_q)) | 2485 | if (list_is_last(&bf_held->list, &txq->axq_q)) |
2393 | break; | 2486 | break; |
@@ -2411,7 +2504,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2411 | * however leave the last descriptor back as the holding | 2504 | * however leave the last descriptor back as the holding |
2412 | * descriptor for hw. | 2505 | * descriptor for hw. |
2413 | */ | 2506 | */ |
2414 | lastbf->bf_stale = true; | 2507 | lastbf->bf_state.stale = true; |
2415 | INIT_LIST_HEAD(&bf_head); | 2508 | INIT_LIST_HEAD(&bf_head); |
2416 | if (!list_is_singular(&lastbf->list)) | 2509 | if (!list_is_singular(&lastbf->list)) |
2417 | list_cut_position(&bf_head, | 2510 | list_cut_position(&bf_head, |
@@ -2466,6 +2559,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2466 | if (ts.qid == sc->beacon.beaconq) { | 2559 | if (ts.qid == sc->beacon.beaconq) { |
2467 | sc->beacon.tx_processed = true; | 2560 | sc->beacon.tx_processed = true; |
2468 | sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); | 2561 | sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); |
2562 | |||
2563 | ath9k_csa_is_finished(sc); | ||
2469 | continue; | 2564 | continue; |
2470 | } | 2565 | } |
2471 | 2566 | ||
@@ -2482,7 +2577,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2482 | } | 2577 | } |
2483 | 2578 | ||
2484 | bf = list_first_entry(fifo_list, struct ath_buf, list); | 2579 | bf = list_first_entry(fifo_list, struct ath_buf, list); |
2485 | if (bf->bf_stale) { | 2580 | if (bf->bf_state.stale) { |
2486 | list_del(&bf->list); | 2581 | list_del(&bf->list); |
2487 | ath_tx_return_buffer(sc, bf); | 2582 | ath_tx_return_buffer(sc, bf); |
2488 | bf = list_first_entry(fifo_list, struct ath_buf, list); | 2583 | bf = list_first_entry(fifo_list, struct ath_buf, list); |
@@ -2504,7 +2599,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2504 | ath_tx_txqaddbuf(sc, txq, &bf_q, true); | 2599 | ath_tx_txqaddbuf(sc, txq, &bf_q, true); |
2505 | } | 2600 | } |
2506 | } else { | 2601 | } else { |
2507 | lastbf->bf_stale = true; | 2602 | lastbf->bf_state.stale = true; |
2508 | if (bf != lastbf) | 2603 | if (bf != lastbf) |
2509 | list_cut_position(&bf_head, fifo_list, | 2604 | list_cut_position(&bf_head, fifo_list, |
2510 | lastbf->list.prev); | 2605 | lastbf->list.prev); |
@@ -2595,6 +2690,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
2595 | tid->paused = false; | 2690 | tid->paused = false; |
2596 | tid->active = false; | 2691 | tid->active = false; |
2597 | __skb_queue_head_init(&tid->buf_q); | 2692 | __skb_queue_head_init(&tid->buf_q); |
2693 | __skb_queue_head_init(&tid->retry_q); | ||
2598 | acno = TID_TO_WME_AC(tidno); | 2694 | acno = TID_TO_WME_AC(tidno); |
2599 | tid->ac = &an->ac[acno]; | 2695 | tid->ac = &an->ac[acno]; |
2600 | } | 2696 | } |
@@ -2602,6 +2698,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
2602 | for (acno = 0, ac = &an->ac[acno]; | 2698 | for (acno = 0, ac = &an->ac[acno]; |
2603 | acno < IEEE80211_NUM_ACS; acno++, ac++) { | 2699 | acno < IEEE80211_NUM_ACS; acno++, ac++) { |
2604 | ac->sched = false; | 2700 | ac->sched = false; |
2701 | ac->clear_ps_filter = true; | ||
2605 | ac->txq = sc->tx.txq_map[acno]; | 2702 | ac->txq = sc->tx.txq_map[acno]; |
2606 | INIT_LIST_HEAD(&ac->tid_q); | 2703 | INIT_LIST_HEAD(&ac->tid_q); |
2607 | } | 2704 | } |