diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ani.c | 744 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ani.h | 104 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ath5k.h | 313 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/attach.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 247 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.h | 38 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/caps.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/debug.c | 382 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/debug.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/desc.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/desc.h | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.h | 88 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pcu.c | 346 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/qcu.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reg.h | 38 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 38 |
19 files changed, 1801 insertions, 693 deletions
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index 090dc6d268a3..cc09595b781a 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile | |||
@@ -12,5 +12,6 @@ ath5k-y += attach.o | |||
12 | ath5k-y += base.o | 12 | ath5k-y += base.o |
13 | ath5k-y += led.o | 13 | ath5k-y += led.o |
14 | ath5k-y += rfkill.o | 14 | ath5k-y += rfkill.o |
15 | ath5k-y += ani.o | ||
15 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o | 16 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o |
16 | obj-$(CONFIG_ATH5K) += ath5k.o | 17 | obj-$(CONFIG_ATH5K) += ath5k.o |
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c new file mode 100644 index 000000000000..584a32859bdb --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -0,0 +1,744 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Bruno Randolf <br1@einfach.org> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath5k.h" | ||
18 | #include "base.h" | ||
19 | #include "reg.h" | ||
20 | #include "debug.h" | ||
21 | #include "ani.h" | ||
22 | |||
23 | /** | ||
24 | * DOC: Basic ANI Operation | ||
25 | * | ||
26 | * Adaptive Noise Immunity (ANI) controls five noise immunity parameters | ||
27 | * depending on the amount of interference in the environment, increasing | ||
28 | * or reducing sensitivity as necessary. | ||
29 | * | ||
30 | * The parameters are: | ||
31 | * - "noise immunity" | ||
32 | * - "spur immunity" | ||
33 | * - "firstep level" | ||
34 | * - "OFDM weak signal detection" | ||
35 | * - "CCK weak signal detection" | ||
36 | * | ||
37 | * Basically we look at the amount of ODFM and CCK timing errors we get and then | ||
38 | * raise or lower immunity accordingly by setting one or more of these | ||
39 | * parameters. | ||
40 | * Newer chipsets have PHY error counters in hardware which will generate a MIB | ||
41 | * interrupt when they overflow. Older hardware has too enable PHY error frames | ||
42 | * by setting a RX flag and then count every single PHY error. When a specified | ||
43 | * threshold of errors has been reached we will raise immunity. | ||
44 | * Also we regularly check the amount of errors and lower or raise immunity as | ||
45 | * necessary. | ||
46 | */ | ||
47 | |||
48 | |||
49 | /*** ANI parameter control ***/ | ||
50 | |||
51 | /** | ||
52 | * ath5k_ani_set_noise_immunity_level() - Set noise immunity level | ||
53 | * | ||
54 | * @level: level between 0 and @ATH5K_ANI_MAX_NOISE_IMM_LVL | ||
55 | */ | ||
56 | void | ||
57 | ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) | ||
58 | { | ||
59 | /* TODO: | ||
60 | * ANI documents suggest the following five levels to use, but the HAL | ||
61 | * and ath9k use only use the last two levels, making this | ||
62 | * essentially an on/off option. There *may* be a reason for this (???), | ||
63 | * so i stick with the HAL version for now... | ||
64 | */ | ||
65 | #if 0 | ||
66 | const s8 hi[] = { -18, -18, -16, -14, -12 }; | ||
67 | const s8 lo[] = { -52, -56, -60, -64, -70 }; | ||
68 | const s8 sz[] = { -34, -41, -48, -55, -62 }; | ||
69 | const s8 fr[] = { -70, -72, -75, -78, -80 }; | ||
70 | #else | ||
71 | const s8 sz[] = { -55, -62 }; | ||
72 | const s8 lo[] = { -64, -70 }; | ||
73 | const s8 hi[] = { -14, -12 }; | ||
74 | const s8 fr[] = { -78, -80 }; | ||
75 | #endif | ||
76 | if (level < 0 || level > ARRAY_SIZE(sz)) { | ||
77 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
78 | "level out of range %d", level); | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, | ||
83 | AR5K_PHY_DESIRED_SIZE_TOT, sz[level]); | ||
84 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_AGCCOARSE, | ||
85 | AR5K_PHY_AGCCOARSE_LO, lo[level]); | ||
86 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_AGCCOARSE, | ||
87 | AR5K_PHY_AGCCOARSE_HI, hi[level]); | ||
88 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, | ||
89 | AR5K_PHY_SIG_FIRPWR, fr[level]); | ||
90 | |||
91 | ah->ah_sc->ani_state.noise_imm_level = level; | ||
92 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); | ||
93 | } | ||
94 | |||
95 | |||
96 | /** | ||
97 | * ath5k_ani_set_spur_immunity_level() - Set spur immunity level | ||
98 | * | ||
99 | * @level: level between 0 and @max_spur_level (the maximum level is dependent | ||
100 | * on the chip revision). | ||
101 | */ | ||
102 | void | ||
103 | ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) | ||
104 | { | ||
105 | const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; | ||
106 | |||
107 | if (level < 0 || level > ARRAY_SIZE(val) || | ||
108 | level > ah->ah_sc->ani_state.max_spur_level) { | ||
109 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
110 | "level out of range %d", level); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, | ||
115 | AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, val[level]); | ||
116 | |||
117 | ah->ah_sc->ani_state.spur_level = level; | ||
118 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); | ||
119 | } | ||
120 | |||
121 | |||
122 | /** | ||
123 | * ath5k_ani_set_firstep_level() - Set "firstep" level | ||
124 | * | ||
125 | * @level: level between 0 and @ATH5K_ANI_MAX_FIRSTEP_LVL | ||
126 | */ | ||
127 | void | ||
128 | ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) | ||
129 | { | ||
130 | const int val[] = { 0, 4, 8 }; | ||
131 | |||
132 | if (level < 0 || level > ARRAY_SIZE(val)) { | ||
133 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
134 | "level out of range %d", level); | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, | ||
139 | AR5K_PHY_SIG_FIRSTEP, val[level]); | ||
140 | |||
141 | ah->ah_sc->ani_state.firstep_level = level; | ||
142 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); | ||
143 | } | ||
144 | |||
145 | |||
146 | /** | ||
147 | * ath5k_ani_set_ofdm_weak_signal_detection() - Control OFDM weak signal | ||
148 | * detection | ||
149 | * | ||
150 | * @on: turn on or off | ||
151 | */ | ||
152 | void | ||
153 | ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) | ||
154 | { | ||
155 | const int m1l[] = { 127, 50 }; | ||
156 | const int m2l[] = { 127, 40 }; | ||
157 | const int m1[] = { 127, 0x4d }; | ||
158 | const int m2[] = { 127, 0x40 }; | ||
159 | const int m2cnt[] = { 31, 16 }; | ||
160 | const int m2lcnt[] = { 63, 48 }; | ||
161 | |||
162 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
163 | AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]); | ||
164 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
165 | AR5K_PHY_WEAK_OFDM_LOW_THR_M2, m2l[on]); | ||
166 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, | ||
167 | AR5K_PHY_WEAK_OFDM_HIGH_THR_M1, m1[on]); | ||
168 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, | ||
169 | AR5K_PHY_WEAK_OFDM_HIGH_THR_M2, m2[on]); | ||
170 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, | ||
171 | AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT, m2cnt[on]); | ||
172 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
173 | AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT, m2lcnt[on]); | ||
174 | |||
175 | if (on) | ||
176 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
177 | AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN); | ||
178 | else | ||
179 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
180 | AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN); | ||
181 | |||
182 | ah->ah_sc->ani_state.ofdm_weak_sig = on; | ||
183 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", | ||
184 | on ? "on" : "off"); | ||
185 | } | ||
186 | |||
187 | |||
188 | /** | ||
189 | * ath5k_ani_set_cck_weak_signal_detection() - control CCK weak signal detection | ||
190 | * | ||
191 | * @on: turn on or off | ||
192 | */ | ||
193 | void | ||
194 | ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) | ||
195 | { | ||
196 | const int val[] = { 8, 6 }; | ||
197 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR, | ||
198 | AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]); | ||
199 | ah->ah_sc->ani_state.cck_weak_sig = on; | ||
200 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", | ||
201 | on ? "on" : "off"); | ||
202 | } | ||
203 | |||
204 | |||
205 | /*** ANI algorithm ***/ | ||
206 | |||
207 | /** | ||
208 | * ath5k_ani_raise_immunity() - Increase noise immunity | ||
209 | * | ||
210 | * @ofdm_trigger: If this is true we are called because of too many OFDM errors, | ||
211 | * the algorithm will tune more parameters then. | ||
212 | * | ||
213 | * Try to raise noise immunity (=decrease sensitivity) in several steps | ||
214 | * depending on the average RSSI of the beacons we received. | ||
215 | */ | ||
216 | static void | ||
217 | ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, | ||
218 | bool ofdm_trigger) | ||
219 | { | ||
220 | int rssi = ah->ah_beacon_rssi_avg.avg; | ||
221 | |||
222 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)", | ||
223 | ofdm_trigger ? "ODFM" : "CCK"); | ||
224 | |||
225 | /* first: raise noise immunity */ | ||
226 | if (as->noise_imm_level < ATH5K_ANI_MAX_NOISE_IMM_LVL) { | ||
227 | ath5k_ani_set_noise_immunity_level(ah, as->noise_imm_level + 1); | ||
228 | return; | ||
229 | } | ||
230 | |||
231 | /* only OFDM: raise spur immunity level */ | ||
232 | if (ofdm_trigger && | ||
233 | as->spur_level < ah->ah_sc->ani_state.max_spur_level) { | ||
234 | ath5k_ani_set_spur_immunity_level(ah, as->spur_level + 1); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | /* AP mode */ | ||
239 | if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { | ||
240 | if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) | ||
241 | ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); | ||
242 | return; | ||
243 | } | ||
244 | |||
245 | /* STA and IBSS mode */ | ||
246 | |||
247 | /* TODO: for IBSS mode it would be better to keep a beacon RSSI average | ||
248 | * per each neighbour node and use the minimum of these, to make sure we | ||
249 | * don't shut out a remote node by raising immunity too high. */ | ||
250 | |||
251 | if (rssi > ATH5K_ANI_RSSI_THR_HIGH) { | ||
252 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
253 | "beacon RSSI high"); | ||
254 | /* only OFDM: beacon RSSI is high, we can disable ODFM weak | ||
255 | * signal detection */ | ||
256 | if (ofdm_trigger && as->ofdm_weak_sig == true) { | ||
257 | ath5k_ani_set_ofdm_weak_signal_detection(ah, false); | ||
258 | ath5k_ani_set_spur_immunity_level(ah, 0); | ||
259 | return; | ||
260 | } | ||
261 | /* as a last resort or CCK: raise firstep level */ | ||
262 | if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) { | ||
263 | ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); | ||
264 | return; | ||
265 | } | ||
266 | } else if (rssi > ATH5K_ANI_RSSI_THR_LOW) { | ||
267 | /* beacon RSSI in mid range, we need OFDM weak signal detect, | ||
268 | * but can raise firstep level */ | ||
269 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
270 | "beacon RSSI mid"); | ||
271 | if (ofdm_trigger && as->ofdm_weak_sig == false) | ||
272 | ath5k_ani_set_ofdm_weak_signal_detection(ah, true); | ||
273 | if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) | ||
274 | ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); | ||
275 | return; | ||
276 | } else if (ah->ah_current_channel->band == IEEE80211_BAND_2GHZ) { | ||
277 | /* beacon RSSI is low. in B/G mode turn of OFDM weak signal | ||
278 | * detect and zero firstep level to maximize CCK sensitivity */ | ||
279 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
280 | "beacon RSSI low, 2GHz"); | ||
281 | if (ofdm_trigger && as->ofdm_weak_sig == true) | ||
282 | ath5k_ani_set_ofdm_weak_signal_detection(ah, false); | ||
283 | if (as->firstep_level > 0) | ||
284 | ath5k_ani_set_firstep_level(ah, 0); | ||
285 | return; | ||
286 | } | ||
287 | |||
288 | /* TODO: why not?: | ||
289 | if (as->cck_weak_sig == true) { | ||
290 | ath5k_ani_set_cck_weak_signal_detection(ah, false); | ||
291 | } | ||
292 | */ | ||
293 | } | ||
294 | |||
295 | |||
296 | /** | ||
297 | * ath5k_ani_lower_immunity() - Decrease noise immunity | ||
298 | * | ||
299 | * Try to lower noise immunity (=increase sensitivity) in several steps | ||
300 | * depending on the average RSSI of the beacons we received. | ||
301 | */ | ||
302 | static void | ||
303 | ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) | ||
304 | { | ||
305 | int rssi = ah->ah_beacon_rssi_avg.avg; | ||
306 | |||
307 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity"); | ||
308 | |||
309 | if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { | ||
310 | /* AP mode */ | ||
311 | if (as->firstep_level > 0) { | ||
312 | ath5k_ani_set_firstep_level(ah, as->firstep_level - 1); | ||
313 | return; | ||
314 | } | ||
315 | } else { | ||
316 | /* STA and IBSS mode (see TODO above) */ | ||
317 | if (rssi > ATH5K_ANI_RSSI_THR_HIGH) { | ||
318 | /* beacon signal is high, leave OFDM weak signal | ||
319 | * detection off or it may oscillate | ||
320 | * TODO: who said it's off??? */ | ||
321 | } else if (rssi > ATH5K_ANI_RSSI_THR_LOW) { | ||
322 | /* beacon RSSI is mid-range: turn on ODFM weak signal | ||
323 | * detection and next, lower firstep level */ | ||
324 | if (as->ofdm_weak_sig == false) { | ||
325 | ath5k_ani_set_ofdm_weak_signal_detection(ah, | ||
326 | true); | ||
327 | return; | ||
328 | } | ||
329 | if (as->firstep_level > 0) { | ||
330 | ath5k_ani_set_firstep_level(ah, | ||
331 | as->firstep_level - 1); | ||
332 | return; | ||
333 | } | ||
334 | } else { | ||
335 | /* beacon signal is low: only reduce firstep level */ | ||
336 | if (as->firstep_level > 0) { | ||
337 | ath5k_ani_set_firstep_level(ah, | ||
338 | as->firstep_level - 1); | ||
339 | return; | ||
340 | } | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /* all modes */ | ||
345 | if (as->spur_level > 0) { | ||
346 | ath5k_ani_set_spur_immunity_level(ah, as->spur_level - 1); | ||
347 | return; | ||
348 | } | ||
349 | |||
350 | /* finally, reduce noise immunity */ | ||
351 | if (as->noise_imm_level > 0) { | ||
352 | ath5k_ani_set_noise_immunity_level(ah, as->noise_imm_level - 1); | ||
353 | return; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | |||
358 | /** | ||
359 | * ath5k_hw_ani_get_listen_time() - Calculate time spent listening | ||
360 | * | ||
361 | * Return an approximation of the time spent "listening" in milliseconds (ms) | ||
362 | * since the last call of this function by deducting the cycles spent | ||
363 | * transmitting and receiving from the total cycle count. | ||
364 | * Save profile count values for debugging/statistics and because we might want | ||
365 | * to use them later. | ||
366 | * | ||
367 | * We assume no one else clears these registers! | ||
368 | */ | ||
369 | static int | ||
370 | ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as) | ||
371 | { | ||
372 | int listen; | ||
373 | |||
374 | /* freeze */ | ||
375 | ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC); | ||
376 | /* read */ | ||
377 | as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE); | ||
378 | as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR); | ||
379 | as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX); | ||
380 | as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX); | ||
381 | /* clear */ | ||
382 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
383 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
384 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
385 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
386 | /* un-freeze */ | ||
387 | ath5k_hw_reg_write(ah, 0, AR5K_MIBC); | ||
388 | |||
389 | /* TODO: where does 44000 come from? (11g clock rate?) */ | ||
390 | listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000; | ||
391 | |||
392 | if (as->pfc_cycles == 0 || listen < 0) | ||
393 | return 0; | ||
394 | return listen; | ||
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * ath5k_ani_save_and_clear_phy_errors() - Clear and save PHY error counters | ||
400 | * | ||
401 | * Clear the PHY error counters as soon as possible, since this might be called | ||
402 | * from a MIB interrupt and we want to make sure we don't get interrupted again. | ||
403 | * Add the count of CCK and OFDM errors to our internal state, so it can be used | ||
404 | * by the algorithm later. | ||
405 | * | ||
406 | * Will be called from interrupt and tasklet context. | ||
407 | * Returns 0 if both counters are zero. | ||
408 | */ | ||
409 | static int | ||
410 | ath5k_ani_save_and_clear_phy_errors(struct ath5k_hw *ah, | ||
411 | struct ath5k_ani_state *as) | ||
412 | { | ||
413 | unsigned int ofdm_err, cck_err; | ||
414 | |||
415 | if (!ah->ah_capabilities.cap_has_phyerr_counters) | ||
416 | return 0; | ||
417 | |||
418 | ofdm_err = ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1); | ||
419 | cck_err = ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2); | ||
420 | |||
421 | /* reset counters first, we might be in a hurry (interrupt) */ | ||
422 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_OFDM_TRIG_HIGH, | ||
423 | AR5K_PHYERR_CNT1); | ||
424 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_CCK_TRIG_HIGH, | ||
425 | AR5K_PHYERR_CNT2); | ||
426 | |||
427 | ofdm_err = ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - ofdm_err); | ||
428 | cck_err = ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - cck_err); | ||
429 | |||
430 | /* sometimes both can be zero, especially when there is a superfluous | ||
431 | * second interrupt. detect that here and return an error. */ | ||
432 | if (ofdm_err <= 0 && cck_err <= 0) | ||
433 | return 0; | ||
434 | |||
435 | /* avoid negative values should one of the registers overflow */ | ||
436 | if (ofdm_err > 0) { | ||
437 | as->ofdm_errors += ofdm_err; | ||
438 | as->sum_ofdm_errors += ofdm_err; | ||
439 | } | ||
440 | if (cck_err > 0) { | ||
441 | as->cck_errors += cck_err; | ||
442 | as->sum_cck_errors += cck_err; | ||
443 | } | ||
444 | return 1; | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * ath5k_ani_period_restart() - Restart ANI period | ||
450 | * | ||
451 | * Just reset counters, so they are clear for the next "ani period". | ||
452 | */ | ||
453 | static void | ||
454 | ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as) | ||
455 | { | ||
456 | /* keep last values for debugging */ | ||
457 | as->last_ofdm_errors = as->ofdm_errors; | ||
458 | as->last_cck_errors = as->cck_errors; | ||
459 | as->last_listen = as->listen_time; | ||
460 | |||
461 | as->ofdm_errors = 0; | ||
462 | as->cck_errors = 0; | ||
463 | as->listen_time = 0; | ||
464 | } | ||
465 | |||
466 | |||
467 | /** | ||
468 | * ath5k_ani_calibration() - The main ANI calibration function | ||
469 | * | ||
470 | * We count OFDM and CCK errors relative to the time where we did not send or | ||
471 | * receive ("listen" time) and raise or lower immunity accordingly. | ||
472 | * This is called regularly (every second) from the calibration timer, but also | ||
473 | * when an error threshold has been reached. | ||
474 | * | ||
475 | * In order to synchronize access from different contexts, this should be | ||
476 | * called only indirectly by scheduling the ANI tasklet! | ||
477 | */ | ||
478 | void | ||
479 | ath5k_ani_calibration(struct ath5k_hw *ah) | ||
480 | { | ||
481 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | ||
482 | int listen, ofdm_high, ofdm_low, cck_high, cck_low; | ||
483 | |||
484 | if (as->ani_mode != ATH5K_ANI_MODE_AUTO) | ||
485 | return; | ||
486 | |||
487 | /* get listen time since last call and add it to the counter because we | ||
488 | * might not have restarted the "ani period" last time */ | ||
489 | listen = ath5k_hw_ani_get_listen_time(ah, as); | ||
490 | as->listen_time += listen; | ||
491 | |||
492 | ath5k_ani_save_and_clear_phy_errors(ah, as); | ||
493 | |||
494 | ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000; | ||
495 | cck_high = as->listen_time * ATH5K_ANI_CCK_TRIG_HIGH / 1000; | ||
496 | ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000; | ||
497 | cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000; | ||
498 | |||
499 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
500 | "listen %d (now %d)", as->listen_time, listen); | ||
501 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
502 | "check high ofdm %d/%d cck %d/%d", | ||
503 | as->ofdm_errors, ofdm_high, as->cck_errors, cck_high); | ||
504 | |||
505 | if (as->ofdm_errors > ofdm_high || as->cck_errors > cck_high) { | ||
506 | /* too many PHY errors - we have to raise immunity */ | ||
507 | bool ofdm_flag = as->ofdm_errors > ofdm_high ? true : false; | ||
508 | ath5k_ani_raise_immunity(ah, as, ofdm_flag); | ||
509 | ath5k_ani_period_restart(ah, as); | ||
510 | |||
511 | } else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) { | ||
512 | /* If more than 5 (TODO: why 5?) periods have passed and we got | ||
513 | * relatively little errors we can try to lower immunity */ | ||
514 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
515 | "check low ofdm %d/%d cck %d/%d", | ||
516 | as->ofdm_errors, ofdm_low, as->cck_errors, cck_low); | ||
517 | |||
518 | if (as->ofdm_errors <= ofdm_low && as->cck_errors <= cck_low) | ||
519 | ath5k_ani_lower_immunity(ah, as); | ||
520 | |||
521 | ath5k_ani_period_restart(ah, as); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | |||
526 | /*** INTERRUPT HANDLER ***/ | ||
527 | |||
528 | /** | ||
529 | * ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters | ||
530 | * | ||
531 | * Just read & reset the registers quickly, so they don't generate more | ||
532 | * interrupts, save the counters and schedule the tasklet to decide whether | ||
533 | * to raise immunity or not. | ||
534 | * | ||
535 | * We just need to handle PHY error counters, ath5k_hw_update_mib_counters() | ||
536 | * should take care of all "normal" MIB interrupts. | ||
537 | */ | ||
538 | void | ||
539 | ath5k_ani_mib_intr(struct ath5k_hw *ah) | ||
540 | { | ||
541 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | ||
542 | |||
543 | /* nothing to do here if HW does not have PHY error counters - they | ||
544 | * can't be the reason for the MIB interrupt then */ | ||
545 | if (!ah->ah_capabilities.cap_has_phyerr_counters) | ||
546 | return; | ||
547 | |||
548 | /* not in use but clear anyways */ | ||
549 | ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); | ||
550 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | ||
551 | |||
552 | if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) | ||
553 | return; | ||
554 | |||
555 | /* if one of the errors triggered, we can get a superfluous second | ||
556 | * interrupt, even though we have already reset the register. the | ||
557 | * function detects that so we can return early */ | ||
558 | if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) | ||
559 | return; | ||
560 | |||
561 | if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH || | ||
562 | as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) | ||
563 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
564 | } | ||
565 | |||
566 | |||
567 | /** | ||
568 | * ath5k_ani_phy_error_report() - Used by older HW to report PHY errors | ||
569 | * | ||
570 | * This is used by hardware without PHY error counters to report PHY errors | ||
571 | * on a frame-by-frame basis, instead of the interrupt. | ||
572 | */ | ||
573 | void | ||
574 | ath5k_ani_phy_error_report(struct ath5k_hw *ah, | ||
575 | enum ath5k_phy_error_code phyerr) | ||
576 | { | ||
577 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | ||
578 | |||
579 | if (phyerr == AR5K_RX_PHY_ERROR_OFDM_TIMING) { | ||
580 | as->ofdm_errors++; | ||
581 | if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH) | ||
582 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
583 | } else if (phyerr == AR5K_RX_PHY_ERROR_CCK_TIMING) { | ||
584 | as->cck_errors++; | ||
585 | if (as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) | ||
586 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | |||
591 | /*** INIT ***/ | ||
592 | |||
593 | /** | ||
594 | * ath5k_enable_phy_err_counters() - Enable PHY error counters | ||
595 | * | ||
596 | * Enable PHY error counters for OFDM and CCK timing errors. | ||
597 | */ | ||
598 | static void | ||
599 | ath5k_enable_phy_err_counters(struct ath5k_hw *ah) | ||
600 | { | ||
601 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_OFDM_TRIG_HIGH, | ||
602 | AR5K_PHYERR_CNT1); | ||
603 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_CCK_TRIG_HIGH, | ||
604 | AR5K_PHYERR_CNT2); | ||
605 | ath5k_hw_reg_write(ah, AR5K_PHY_ERR_FIL_OFDM, AR5K_PHYERR_CNT1_MASK); | ||
606 | ath5k_hw_reg_write(ah, AR5K_PHY_ERR_FIL_CCK, AR5K_PHYERR_CNT2_MASK); | ||
607 | |||
608 | /* not in use */ | ||
609 | ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); | ||
610 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | ||
611 | } | ||
612 | |||
613 | |||
614 | /** | ||
615 | * ath5k_disable_phy_err_counters() - Disable PHY error counters | ||
616 | * | ||
617 | * Disable PHY error counters for OFDM and CCK timing errors. | ||
618 | */ | ||
619 | static void | ||
620 | ath5k_disable_phy_err_counters(struct ath5k_hw *ah) | ||
621 | { | ||
622 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT1); | ||
623 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT2); | ||
624 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT1_MASK); | ||
625 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT2_MASK); | ||
626 | |||
627 | /* not in use */ | ||
628 | ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); | ||
629 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | ||
630 | } | ||
631 | |||
632 | |||
633 | /** | ||
634 | * ath5k_ani_init() - Initialize ANI | ||
635 | * @mode: Which mode to use (auto, manual high, manual low, off) | ||
636 | * | ||
637 | * Initialize ANI according to mode. | ||
638 | */ | ||
639 | void | ||
640 | ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode) | ||
641 | { | ||
642 | /* ANI is only possible on 5212 and newer */ | ||
643 | if (ah->ah_version < AR5K_AR5212) | ||
644 | return; | ||
645 | |||
646 | /* clear old state information */ | ||
647 | memset(&ah->ah_sc->ani_state, 0, sizeof(ah->ah_sc->ani_state)); | ||
648 | |||
649 | /* older hardware has more spur levels than newer */ | ||
650 | if (ah->ah_mac_srev < AR5K_SREV_AR2414) | ||
651 | ah->ah_sc->ani_state.max_spur_level = 7; | ||
652 | else | ||
653 | ah->ah_sc->ani_state.max_spur_level = 2; | ||
654 | |||
655 | /* initial values for our ani parameters */ | ||
656 | if (mode == ATH5K_ANI_MODE_OFF) { | ||
657 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI off\n"); | ||
658 | } else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) { | ||
659 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
660 | "ANI manual low -> high sensitivity\n"); | ||
661 | ath5k_ani_set_noise_immunity_level(ah, 0); | ||
662 | ath5k_ani_set_spur_immunity_level(ah, 0); | ||
663 | ath5k_ani_set_firstep_level(ah, 0); | ||
664 | ath5k_ani_set_ofdm_weak_signal_detection(ah, true); | ||
665 | ath5k_ani_set_cck_weak_signal_detection(ah, true); | ||
666 | } else if (mode == ATH5K_ANI_MODE_MANUAL_HIGH) { | ||
667 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
668 | "ANI manual high -> low sensitivity\n"); | ||
669 | ath5k_ani_set_noise_immunity_level(ah, | ||
670 | ATH5K_ANI_MAX_NOISE_IMM_LVL); | ||
671 | ath5k_ani_set_spur_immunity_level(ah, | ||
672 | ah->ah_sc->ani_state.max_spur_level); | ||
673 | ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL); | ||
674 | ath5k_ani_set_ofdm_weak_signal_detection(ah, false); | ||
675 | ath5k_ani_set_cck_weak_signal_detection(ah, false); | ||
676 | } else if (mode == ATH5K_ANI_MODE_AUTO) { | ||
677 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI auto\n"); | ||
678 | ath5k_ani_set_noise_immunity_level(ah, 0); | ||
679 | ath5k_ani_set_spur_immunity_level(ah, 0); | ||
680 | ath5k_ani_set_firstep_level(ah, 0); | ||
681 | ath5k_ani_set_ofdm_weak_signal_detection(ah, true); | ||
682 | ath5k_ani_set_cck_weak_signal_detection(ah, false); | ||
683 | } | ||
684 | |||
685 | /* newer hardware has PHY error counter registers which we can use to | ||
686 | * get OFDM and CCK error counts. older hardware has to set rxfilter and | ||
687 | * report every single PHY error by calling ath5k_ani_phy_error_report() | ||
688 | */ | ||
689 | if (mode == ATH5K_ANI_MODE_AUTO) { | ||
690 | if (ah->ah_capabilities.cap_has_phyerr_counters) | ||
691 | ath5k_enable_phy_err_counters(ah); | ||
692 | else | ||
693 | ath5k_hw_set_rx_filter(ah, ath5k_hw_get_rx_filter(ah) | | ||
694 | AR5K_RX_FILTER_PHYERR); | ||
695 | } else { | ||
696 | if (ah->ah_capabilities.cap_has_phyerr_counters) | ||
697 | ath5k_disable_phy_err_counters(ah); | ||
698 | else | ||
699 | ath5k_hw_set_rx_filter(ah, ath5k_hw_get_rx_filter(ah) & | ||
700 | ~AR5K_RX_FILTER_PHYERR); | ||
701 | } | ||
702 | |||
703 | ah->ah_sc->ani_state.ani_mode = mode; | ||
704 | } | ||
705 | |||
706 | |||
707 | /*** DEBUG ***/ | ||
708 | |||
709 | #ifdef CONFIG_ATH5K_DEBUG | ||
710 | |||
711 | void | ||
712 | ath5k_ani_print_counters(struct ath5k_hw *ah) | ||
713 | { | ||
714 | /* clears too */ | ||
715 | printk(KERN_NOTICE "ACK fail\t%d\n", | ||
716 | ath5k_hw_reg_read(ah, AR5K_ACK_FAIL)); | ||
717 | printk(KERN_NOTICE "RTS fail\t%d\n", | ||
718 | ath5k_hw_reg_read(ah, AR5K_RTS_FAIL)); | ||
719 | printk(KERN_NOTICE "RTS success\t%d\n", | ||
720 | ath5k_hw_reg_read(ah, AR5K_RTS_OK)); | ||
721 | printk(KERN_NOTICE "FCS error\t%d\n", | ||
722 | ath5k_hw_reg_read(ah, AR5K_FCS_FAIL)); | ||
723 | |||
724 | /* no clear */ | ||
725 | printk(KERN_NOTICE "tx\t%d\n", | ||
726 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX)); | ||
727 | printk(KERN_NOTICE "rx\t%d\n", | ||
728 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX)); | ||
729 | printk(KERN_NOTICE "busy\t%d\n", | ||
730 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR)); | ||
731 | printk(KERN_NOTICE "cycles\t%d\n", | ||
732 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE)); | ||
733 | |||
734 | printk(KERN_NOTICE "AR5K_PHYERR_CNT1\t%d\n", | ||
735 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)); | ||
736 | printk(KERN_NOTICE "AR5K_PHYERR_CNT2\t%d\n", | ||
737 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)); | ||
738 | printk(KERN_NOTICE "AR5K_OFDM_FIL_CNT\t%d\n", | ||
739 | ath5k_hw_reg_read(ah, AR5K_OFDM_FIL_CNT)); | ||
740 | printk(KERN_NOTICE "AR5K_CCK_FIL_CNT\t%d\n", | ||
741 | ath5k_hw_reg_read(ah, AR5K_CCK_FIL_CNT)); | ||
742 | } | ||
743 | |||
744 | #endif | ||
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h new file mode 100644 index 000000000000..55cf26d8522c --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ani.h | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Bruno Randolf <br1@einfach.org> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | #ifndef ANI_H | ||
17 | #define ANI_H | ||
18 | |||
19 | /* these thresholds are relative to the ATH5K_ANI_LISTEN_PERIOD */ | ||
20 | #define ATH5K_ANI_LISTEN_PERIOD 100 | ||
21 | #define ATH5K_ANI_OFDM_TRIG_HIGH 500 | ||
22 | #define ATH5K_ANI_OFDM_TRIG_LOW 200 | ||
23 | #define ATH5K_ANI_CCK_TRIG_HIGH 200 | ||
24 | #define ATH5K_ANI_CCK_TRIG_LOW 100 | ||
25 | |||
26 | /* average beacon RSSI thresholds */ | ||
27 | #define ATH5K_ANI_RSSI_THR_HIGH 40 | ||
28 | #define ATH5K_ANI_RSSI_THR_LOW 7 | ||
29 | |||
30 | /* maximum availabe levels */ | ||
31 | #define ATH5K_ANI_MAX_FIRSTEP_LVL 2 | ||
32 | #define ATH5K_ANI_MAX_NOISE_IMM_LVL 1 | ||
33 | |||
34 | |||
35 | /** | ||
36 | * enum ath5k_ani_mode - mode for ANI / noise sensitivity | ||
37 | * | ||
38 | * @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI | ||
39 | * algorithm after it has been on auto mode. | ||
40 | * ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low, | ||
41 | * maximizing sensitivity. ANI will not run. | ||
42 | * ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high, | ||
43 | * minimizing sensitivity. ANI will not run. | ||
44 | * ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the | ||
45 | * amount of OFDM and CCK frame errors (default). | ||
46 | */ | ||
47 | enum ath5k_ani_mode { | ||
48 | ATH5K_ANI_MODE_OFF = 0, | ||
49 | ATH5K_ANI_MODE_MANUAL_LOW = 1, | ||
50 | ATH5K_ANI_MODE_MANUAL_HIGH = 2, | ||
51 | ATH5K_ANI_MODE_AUTO = 3 | ||
52 | }; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * struct ath5k_ani_state - ANI state and associated counters | ||
57 | * | ||
58 | * @max_spur_level: the maximum spur level is chip dependent | ||
59 | */ | ||
60 | struct ath5k_ani_state { | ||
61 | enum ath5k_ani_mode ani_mode; | ||
62 | |||
63 | /* state */ | ||
64 | int noise_imm_level; | ||
65 | int spur_level; | ||
66 | int firstep_level; | ||
67 | bool ofdm_weak_sig; | ||
68 | bool cck_weak_sig; | ||
69 | |||
70 | int max_spur_level; | ||
71 | |||
72 | /* used by the algorithm */ | ||
73 | unsigned int listen_time; | ||
74 | unsigned int ofdm_errors; | ||
75 | unsigned int cck_errors; | ||
76 | |||
77 | /* debug/statistics only: numbers from last ANI calibration */ | ||
78 | unsigned int pfc_tx; | ||
79 | unsigned int pfc_rx; | ||
80 | unsigned int pfc_busy; | ||
81 | unsigned int pfc_cycles; | ||
82 | unsigned int last_listen; | ||
83 | unsigned int last_ofdm_errors; | ||
84 | unsigned int last_cck_errors; | ||
85 | unsigned int sum_ofdm_errors; | ||
86 | unsigned int sum_cck_errors; | ||
87 | }; | ||
88 | |||
89 | void ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode); | ||
90 | void ath5k_ani_mib_intr(struct ath5k_hw *ah); | ||
91 | void ath5k_ani_calibration(struct ath5k_hw *ah); | ||
92 | void ath5k_ani_phy_error_report(struct ath5k_hw *ah, | ||
93 | enum ath5k_phy_error_code phyerr); | ||
94 | |||
95 | /* for manual control */ | ||
96 | void ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level); | ||
97 | void ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level); | ||
98 | void ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level); | ||
99 | void ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on); | ||
100 | void ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on); | ||
101 | |||
102 | void ath5k_ani_print_counters(struct ath5k_hw *ah); | ||
103 | |||
104 | #endif /* ANI_H */ | ||
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ac67f02e26d8..2785946f659a 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -202,7 +202,8 @@ | |||
202 | #define AR5K_TUNE_MAX_TXPOWER 63 | 202 | #define AR5K_TUNE_MAX_TXPOWER 63 |
203 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 | 203 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 |
204 | #define AR5K_TUNE_TPC_TXPOWER false | 204 | #define AR5K_TUNE_TPC_TXPOWER false |
205 | #define AR5K_TUNE_HWTXTRIES 4 | 205 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ |
206 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ | ||
206 | 207 | ||
207 | #define AR5K_INIT_CARR_SENSE_EN 1 | 208 | #define AR5K_INIT_CARR_SENSE_EN 1 |
208 | 209 | ||
@@ -614,28 +615,6 @@ struct ath5k_rx_status { | |||
614 | #define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/ | 615 | #define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/ |
615 | #define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/ | 616 | #define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/ |
616 | 617 | ||
617 | #if 0 | ||
618 | /** | ||
619 | * struct ath5k_beacon_state - Per-station beacon timer state. | ||
620 | * @bs_interval: in TU's, can also include the above flags | ||
621 | * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a | ||
622 | * Point Coordination Function capable AP | ||
623 | */ | ||
624 | struct ath5k_beacon_state { | ||
625 | u32 bs_next_beacon; | ||
626 | u32 bs_next_dtim; | ||
627 | u32 bs_interval; | ||
628 | u8 bs_dtim_period; | ||
629 | u8 bs_cfp_period; | ||
630 | u16 bs_cfp_max_duration; | ||
631 | u16 bs_cfp_du_remain; | ||
632 | u16 bs_tim_offset; | ||
633 | u16 bs_sleep_duration; | ||
634 | u16 bs_bmiss_threshold; | ||
635 | u32 bs_cfp_next; | ||
636 | }; | ||
637 | #endif | ||
638 | |||
639 | 618 | ||
640 | /* | 619 | /* |
641 | * TSF to TU conversion: | 620 | * TSF to TU conversion: |
@@ -822,9 +801,9 @@ struct ath5k_athchan_2ghz { | |||
822 | * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold | 801 | * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold |
823 | * We currently do increments on interrupt by | 802 | * We currently do increments on interrupt by |
824 | * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 | 803 | * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 |
825 | * @AR5K_INT_MIB: Indicates the Management Information Base counters should be | 804 | * @AR5K_INT_MIB: Indicates the either Management Information Base counters or |
826 | * checked. We should do this with ath5k_hw_update_mib_counters() but | 805 | * one of the PHY error counters reached the maximum value and should be |
827 | * it seems we should also then do some noise immunity work. | 806 | * read and cleared. |
828 | * @AR5K_INT_RXPHY: RX PHY Error | 807 | * @AR5K_INT_RXPHY: RX PHY Error |
829 | * @AR5K_INT_RXKCM: RX Key cache miss | 808 | * @AR5K_INT_RXKCM: RX Key cache miss |
830 | * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a | 809 | * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a |
@@ -912,10 +891,11 @@ enum ath5k_int { | |||
912 | AR5K_INT_NOCARD = 0xffffffff | 891 | AR5K_INT_NOCARD = 0xffffffff |
913 | }; | 892 | }; |
914 | 893 | ||
915 | /* Software interrupts used for calibration */ | 894 | /* mask which calibration is active at the moment */ |
916 | enum ath5k_software_interrupt { | 895 | enum ath5k_calibration_mask { |
917 | AR5K_SWI_FULL_CALIBRATION = 0x01, | 896 | AR5K_CALIBRATION_FULL = 0x01, |
918 | AR5K_SWI_SHORT_CALIBRATION = 0x02, | 897 | AR5K_CALIBRATION_SHORT = 0x02, |
898 | AR5K_CALIBRATION_ANI = 0x04, | ||
919 | }; | 899 | }; |
920 | 900 | ||
921 | /* | 901 | /* |
@@ -1004,6 +984,8 @@ struct ath5k_capabilities { | |||
1004 | struct { | 984 | struct { |
1005 | u8 q_tx_num; | 985 | u8 q_tx_num; |
1006 | } cap_queues; | 986 | } cap_queues; |
987 | |||
988 | bool cap_has_phyerr_counters; | ||
1007 | }; | 989 | }; |
1008 | 990 | ||
1009 | /* size of noise floor history (keep it a power of two) */ | 991 | /* size of noise floor history (keep it a power of two) */ |
@@ -1014,6 +996,15 @@ struct ath5k_nfcal_hist | |||
1014 | s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ | 996 | s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ |
1015 | }; | 997 | }; |
1016 | 998 | ||
999 | /** | ||
1000 | * struct avg_val - Helper structure for average calculation | ||
1001 | * @avg: contains the actual average value | ||
1002 | * @avg_weight: is used internally during calculation to prevent rounding errors | ||
1003 | */ | ||
1004 | struct ath5k_avg_val { | ||
1005 | int avg; | ||
1006 | int avg_weight; | ||
1007 | }; | ||
1017 | 1008 | ||
1018 | /***************************************\ | 1009 | /***************************************\ |
1019 | HARDWARE ABSTRACTION LAYER STRUCTURE | 1010 | HARDWARE ABSTRACTION LAYER STRUCTURE |
@@ -1028,7 +1019,6 @@ struct ath5k_nfcal_hist | |||
1028 | 1019 | ||
1029 | /* TODO: Clean up and merge with ath5k_softc */ | 1020 | /* TODO: Clean up and merge with ath5k_softc */ |
1030 | struct ath5k_hw { | 1021 | struct ath5k_hw { |
1031 | u32 ah_magic; | ||
1032 | struct ath_common common; | 1022 | struct ath_common common; |
1033 | 1023 | ||
1034 | struct ath5k_softc *ah_sc; | 1024 | struct ath5k_softc *ah_sc; |
@@ -1036,7 +1026,6 @@ struct ath5k_hw { | |||
1036 | 1026 | ||
1037 | enum ath5k_int ah_imr; | 1027 | enum ath5k_int ah_imr; |
1038 | 1028 | ||
1039 | enum nl80211_iftype ah_op_mode; | ||
1040 | struct ieee80211_channel *ah_current_channel; | 1029 | struct ieee80211_channel *ah_current_channel; |
1041 | bool ah_turbo; | 1030 | bool ah_turbo; |
1042 | bool ah_calibration; | 1031 | bool ah_calibration; |
@@ -1049,7 +1038,6 @@ struct ath5k_hw { | |||
1049 | u32 ah_phy; | 1038 | u32 ah_phy; |
1050 | u32 ah_mac_srev; | 1039 | u32 ah_mac_srev; |
1051 | u16 ah_mac_version; | 1040 | u16 ah_mac_version; |
1052 | u16 ah_mac_revision; | ||
1053 | u16 ah_phy_revision; | 1041 | u16 ah_phy_revision; |
1054 | u16 ah_radio_5ghz_revision; | 1042 | u16 ah_radio_5ghz_revision; |
1055 | u16 ah_radio_2ghz_revision; | 1043 | u16 ah_radio_2ghz_revision; |
@@ -1071,8 +1059,6 @@ struct ath5k_hw { | |||
1071 | u8 ah_def_ant; | 1059 | u8 ah_def_ant; |
1072 | bool ah_software_retry; | 1060 | bool ah_software_retry; |
1073 | 1061 | ||
1074 | int ah_gpio_npins; | ||
1075 | |||
1076 | struct ath5k_capabilities ah_capabilities; | 1062 | struct ath5k_capabilities ah_capabilities; |
1077 | 1063 | ||
1078 | struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; | 1064 | struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; |
@@ -1123,17 +1109,18 @@ struct ath5k_hw { | |||
1123 | 1109 | ||
1124 | struct ath5k_nfcal_hist ah_nfcal_hist; | 1110 | struct ath5k_nfcal_hist ah_nfcal_hist; |
1125 | 1111 | ||
1112 | /* average beacon RSSI in our BSS (used by ANI) */ | ||
1113 | struct ath5k_avg_val ah_beacon_rssi_avg; | ||
1114 | |||
1126 | /* noise floor from last periodic calibration */ | 1115 | /* noise floor from last periodic calibration */ |
1127 | s32 ah_noise_floor; | 1116 | s32 ah_noise_floor; |
1128 | 1117 | ||
1129 | /* Calibration timestamp */ | 1118 | /* Calibration timestamp */ |
1130 | unsigned long ah_cal_tstamp; | 1119 | unsigned long ah_cal_next_full; |
1131 | 1120 | unsigned long ah_cal_next_ani; | |
1132 | /* Calibration interval (secs) */ | ||
1133 | u8 ah_cal_intval; | ||
1134 | 1121 | ||
1135 | /* Software interrupt mask */ | 1122 | /* Calibration mask */ |
1136 | u8 ah_swi_mask; | 1123 | u8 ah_cal_mask; |
1137 | 1124 | ||
1138 | /* | 1125 | /* |
1139 | * Function pointers | 1126 | * Function pointers |
@@ -1141,9 +1128,9 @@ struct ath5k_hw { | |||
1141 | int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, | 1128 | int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, |
1142 | u32 size, unsigned int flags); | 1129 | u32 size, unsigned int flags); |
1143 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1130 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1144 | unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, | 1131 | unsigned int, unsigned int, int, enum ath5k_pkt_type, |
1145 | unsigned int, unsigned int, unsigned int, unsigned int, | 1132 | unsigned int, unsigned int, unsigned int, unsigned int, |
1146 | unsigned int, unsigned int, unsigned int); | 1133 | unsigned int, unsigned int, unsigned int, unsigned int); |
1147 | int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1134 | int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1148 | unsigned int, unsigned int, unsigned int, unsigned int, | 1135 | unsigned int, unsigned int, unsigned int, unsigned int, |
1149 | unsigned int, unsigned int); | 1136 | unsigned int, unsigned int); |
@@ -1158,158 +1145,145 @@ struct ath5k_hw { | |||
1158 | */ | 1145 | */ |
1159 | 1146 | ||
1160 | /* Attach/Detach Functions */ | 1147 | /* Attach/Detach Functions */ |
1161 | extern int ath5k_hw_attach(struct ath5k_softc *sc); | 1148 | int ath5k_hw_attach(struct ath5k_softc *sc); |
1162 | extern void ath5k_hw_detach(struct ath5k_hw *ah); | 1149 | void ath5k_hw_detach(struct ath5k_hw *ah); |
1163 | 1150 | ||
1164 | /* LED functions */ | 1151 | /* LED functions */ |
1165 | extern int ath5k_init_leds(struct ath5k_softc *sc); | 1152 | int ath5k_init_leds(struct ath5k_softc *sc); |
1166 | extern void ath5k_led_enable(struct ath5k_softc *sc); | 1153 | void ath5k_led_enable(struct ath5k_softc *sc); |
1167 | extern void ath5k_led_off(struct ath5k_softc *sc); | 1154 | void ath5k_led_off(struct ath5k_softc *sc); |
1168 | extern void ath5k_unregister_leds(struct ath5k_softc *sc); | 1155 | void ath5k_unregister_leds(struct ath5k_softc *sc); |
1169 | 1156 | ||
1170 | /* Reset Functions */ | 1157 | /* Reset Functions */ |
1171 | extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); | 1158 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); |
1172 | extern int ath5k_hw_on_hold(struct ath5k_hw *ah); | 1159 | int ath5k_hw_on_hold(struct ath5k_hw *ah); |
1173 | extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); | 1160 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
1161 | struct ieee80211_channel *channel, bool change_channel); | ||
1162 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | ||
1163 | bool is_set); | ||
1174 | /* Power management functions */ | 1164 | /* Power management functions */ |
1175 | extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); | ||
1176 | 1165 | ||
1177 | /* DMA Related Functions */ | 1166 | /* DMA Related Functions */ |
1178 | extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); | 1167 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); |
1179 | extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); | 1168 | int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); |
1180 | extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); | 1169 | u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); |
1181 | extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); | 1170 | void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); |
1182 | extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); | 1171 | int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); |
1183 | extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); | 1172 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); |
1184 | extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); | 1173 | u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); |
1185 | extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, | 1174 | int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, |
1186 | u32 phys_addr); | 1175 | u32 phys_addr); |
1187 | extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); | 1176 | int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); |
1188 | /* Interrupt handling */ | 1177 | /* Interrupt handling */ |
1189 | extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); | 1178 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); |
1190 | extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); | 1179 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); |
1191 | extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum | 1180 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); |
1192 | ath5k_int new_mask); | 1181 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); |
1193 | extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); | ||
1194 | 1182 | ||
1195 | /* EEPROM access functions */ | 1183 | /* EEPROM access functions */ |
1196 | extern int ath5k_eeprom_init(struct ath5k_hw *ah); | 1184 | int ath5k_eeprom_init(struct ath5k_hw *ah); |
1197 | extern void ath5k_eeprom_detach(struct ath5k_hw *ah); | 1185 | void ath5k_eeprom_detach(struct ath5k_hw *ah); |
1198 | extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); | 1186 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); |
1199 | extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); | ||
1200 | 1187 | ||
1201 | /* Protocol Control Unit Functions */ | 1188 | /* Protocol Control Unit Functions */ |
1202 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); | 1189 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); |
1203 | extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); | 1190 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); |
1204 | /* BSSID Functions */ | 1191 | /* BSSID Functions */ |
1205 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1192 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1206 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah); | 1193 | void ath5k_hw_set_associd(struct ath5k_hw *ah); |
1207 | extern void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | 1194 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
1208 | /* Receive start/stop functions */ | 1195 | /* Receive start/stop functions */ |
1209 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | 1196 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); |
1210 | extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | 1197 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); |
1211 | /* RX Filter functions */ | 1198 | /* RX Filter functions */ |
1212 | extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); | 1199 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); |
1213 | extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index); | 1200 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); |
1214 | extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index); | 1201 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); |
1215 | extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); | ||
1216 | extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); | ||
1217 | /* Beacon control functions */ | 1202 | /* Beacon control functions */ |
1218 | extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); | 1203 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); |
1219 | extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); | 1204 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); |
1220 | extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); | 1205 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah); |
1221 | extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); | 1206 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); |
1222 | extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); | ||
1223 | #if 0 | ||
1224 | extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state); | ||
1225 | extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); | ||
1226 | extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); | ||
1227 | #endif | ||
1228 | /* ACK bit rate */ | 1207 | /* ACK bit rate */ |
1229 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); | 1208 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); |
1230 | /* ACK/CTS Timeouts */ | ||
1231 | extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); | ||
1232 | extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); | ||
1233 | extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); | ||
1234 | extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); | ||
1235 | /* Clock rate related functions */ | 1209 | /* Clock rate related functions */ |
1236 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | 1210 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); |
1237 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | 1211 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); |
1238 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); | 1212 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); |
1239 | /* Key table (WEP) functions */ | 1213 | /* Key table (WEP) functions */ |
1240 | extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); | 1214 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); |
1241 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); | 1215 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, |
1242 | extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); | 1216 | const struct ieee80211_key_conf *key, const u8 *mac); |
1243 | extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); | 1217 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); |
1244 | 1218 | ||
1245 | /* Queue Control Unit, DFS Control Unit Functions */ | 1219 | /* Queue Control Unit, DFS Control Unit Functions */ |
1246 | extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info); | 1220 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, |
1247 | extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | 1221 | struct ath5k_txq_info *queue_info); |
1248 | const struct ath5k_txq_info *queue_info); | 1222 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, |
1249 | extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, | 1223 | const struct ath5k_txq_info *queue_info); |
1250 | enum ath5k_tx_queue queue_type, | 1224 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, |
1251 | struct ath5k_txq_info *queue_info); | 1225 | enum ath5k_tx_queue queue_type, |
1252 | extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); | 1226 | struct ath5k_txq_info *queue_info); |
1253 | extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1227 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); |
1254 | extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1228 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1255 | extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah); | 1229 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1256 | extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); | 1230 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); |
1257 | 1231 | ||
1258 | /* Hardware Descriptor Functions */ | 1232 | /* Hardware Descriptor Functions */ |
1259 | extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); | 1233 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); |
1260 | 1234 | ||
1261 | /* GPIO Functions */ | 1235 | /* GPIO Functions */ |
1262 | extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); | 1236 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); |
1263 | extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); | 1237 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); |
1264 | extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); | 1238 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); |
1265 | extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); | 1239 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); |
1266 | extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); | 1240 | int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); |
1267 | extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); | 1241 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, |
1242 | u32 interrupt_level); | ||
1268 | 1243 | ||
1269 | /* rfkill Functions */ | 1244 | /* rfkill Functions */ |
1270 | extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah); | 1245 | void ath5k_rfkill_hw_start(struct ath5k_hw *ah); |
1271 | extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); | 1246 | void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); |
1272 | 1247 | ||
1273 | /* Misc functions */ | 1248 | /* Misc functions */ |
1274 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah); | 1249 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah); |
1275 | extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); | 1250 | int ath5k_hw_get_capability(struct ath5k_hw *ah, |
1276 | extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); | 1251 | enum ath5k_capability_type cap_type, u32 capability, |
1277 | extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); | 1252 | u32 *result); |
1253 | int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); | ||
1254 | int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); | ||
1278 | 1255 | ||
1279 | /* Initial register settings functions */ | 1256 | /* Initial register settings functions */ |
1280 | extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); | 1257 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); |
1281 | 1258 | ||
1282 | /* Initialize RF */ | 1259 | /* Initialize RF */ |
1283 | extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah, | 1260 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, |
1284 | struct ieee80211_channel *channel, | 1261 | struct ieee80211_channel *channel, |
1285 | unsigned int mode); | 1262 | unsigned int mode); |
1286 | extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); | 1263 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); |
1287 | extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); | 1264 | enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); |
1288 | extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); | 1265 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); |
1289 | /* PHY/RF channel functions */ | 1266 | /* PHY/RF channel functions */ |
1290 | extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); | 1267 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); |
1291 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1268 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); |
1292 | /* PHY calibration */ | 1269 | /* PHY calibration */ |
1293 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); | 1270 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); |
1294 | extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1271 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, |
1295 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); | 1272 | struct ieee80211_channel *channel); |
1296 | extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah); | ||
1297 | extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); | ||
1298 | /* Spur mitigation */ | 1273 | /* Spur mitigation */ |
1299 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1274 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, |
1300 | struct ieee80211_channel *channel); | 1275 | struct ieee80211_channel *channel); |
1301 | void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | 1276 | void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, |
1302 | struct ieee80211_channel *channel); | 1277 | struct ieee80211_channel *channel); |
1303 | /* Misc PHY functions */ | 1278 | /* Misc PHY functions */ |
1304 | extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); | 1279 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); |
1305 | extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); | 1280 | int ath5k_hw_phy_disable(struct ath5k_hw *ah); |
1306 | /* Antenna control */ | 1281 | /* Antenna control */ |
1307 | extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); | 1282 | void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); |
1308 | extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant); | ||
1309 | extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); | ||
1310 | /* TX power setup */ | 1283 | /* TX power setup */ |
1311 | extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); | 1284 | int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
1312 | extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | 1285 | u8 ee_mode, u8 txpower); |
1286 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | ||
1313 | 1287 | ||
1314 | /* | 1288 | /* |
1315 | * Functions used internaly | 1289 | * Functions used internaly |
@@ -1335,29 +1309,6 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) | |||
1335 | iowrite32(val, ah->ah_iobase + reg); | 1309 | iowrite32(val, ah->ah_iobase + reg); |
1336 | } | 1310 | } |
1337 | 1311 | ||
1338 | #if defined(_ATH5K_RESET) || defined(_ATH5K_PHY) | ||
1339 | /* | ||
1340 | * Check if a register write has been completed | ||
1341 | */ | ||
1342 | static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, | ||
1343 | u32 val, bool is_set) | ||
1344 | { | ||
1345 | int i; | ||
1346 | u32 data; | ||
1347 | |||
1348 | for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { | ||
1349 | data = ath5k_hw_reg_read(ah, reg); | ||
1350 | if (is_set && (data & flag)) | ||
1351 | break; | ||
1352 | else if ((data & flag) == val) | ||
1353 | break; | ||
1354 | udelay(15); | ||
1355 | } | ||
1356 | |||
1357 | return (i <= 0) ? -EAGAIN : 0; | ||
1358 | } | ||
1359 | #endif | ||
1360 | |||
1361 | static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | 1312 | static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) |
1362 | { | 1313 | { |
1363 | u32 retval = 0, bit, i; | 1314 | u32 retval = 0, bit, i; |
@@ -1370,9 +1321,27 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | |||
1370 | return retval; | 1321 | return retval; |
1371 | } | 1322 | } |
1372 | 1323 | ||
1373 | static inline int ath5k_pad_size(int hdrlen) | 1324 | #define AVG_SAMPLES 8 |
1325 | #define AVG_FACTOR 1000 | ||
1326 | |||
1327 | /** | ||
1328 | * ath5k_moving_average - Exponentially weighted moving average | ||
1329 | * @avg: average structure | ||
1330 | * @val: current value | ||
1331 | * | ||
1332 | * This implementation make use of a struct ath5k_avg_val to prevent rounding | ||
1333 | * errors. | ||
1334 | */ | ||
1335 | static inline struct ath5k_avg_val | ||
1336 | ath5k_moving_average(const struct ath5k_avg_val avg, const int val) | ||
1374 | { | 1337 | { |
1375 | return (hdrlen < 24) ? 0 : hdrlen & 3; | 1338 | struct ath5k_avg_val new; |
1339 | new.avg_weight = avg.avg_weight ? | ||
1340 | (((avg.avg_weight * ((AVG_SAMPLES) - 1)) + | ||
1341 | (val * (AVG_FACTOR))) / (AVG_SAMPLES)) : | ||
1342 | (val * (AVG_FACTOR)); | ||
1343 | new.avg = new.avg_weight / (AVG_FACTOR); | ||
1344 | return new; | ||
1376 | } | 1345 | } |
1377 | 1346 | ||
1378 | #endif | 1347 | #endif |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 42284445b75e..dcf7c30f813f 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -113,7 +113,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
113 | /* | 113 | /* |
114 | * HW information | 114 | * HW information |
115 | */ | 115 | */ |
116 | ah->ah_op_mode = NL80211_IFTYPE_STATION; | ||
117 | ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; | 116 | ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; |
118 | ah->ah_turbo = false; | 117 | ah->ah_turbo = false; |
119 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | 118 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; |
@@ -123,6 +122,9 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
123 | ah->ah_cw_min = AR5K_TUNE_CWMIN; | 122 | ah->ah_cw_min = AR5K_TUNE_CWMIN; |
124 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | 123 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; |
125 | ah->ah_software_retry = false; | 124 | ah->ah_software_retry = false; |
125 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; | ||
126 | ah->ah_noise_floor = -95; /* until first NF calibration is run */ | ||
127 | sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; | ||
126 | 128 | ||
127 | /* | 129 | /* |
128 | * Find the mac version | 130 | * Find the mac version |
@@ -148,7 +150,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
148 | /* Get MAC, PHY and RADIO revisions */ | 150 | /* Get MAC, PHY and RADIO revisions */ |
149 | ah->ah_mac_srev = srev; | 151 | ah->ah_mac_srev = srev; |
150 | ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); | 152 | ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); |
151 | ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); | ||
152 | ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & | 153 | ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & |
153 | 0xffffffff; | 154 | 0xffffffff; |
154 | ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, | 155 | ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, |
@@ -327,7 +328,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
327 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 328 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
328 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); | 329 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); |
329 | ath5k_hw_set_associd(ah); | 330 | ath5k_hw_set_associd(ah); |
330 | ath5k_hw_set_opmode(ah); | 331 | ath5k_hw_set_opmode(ah, sc->opmode); |
331 | 332 | ||
332 | ath5k_hw_rfgain_opt_init(ah); | 333 | ath5k_hw_rfgain_opt_init(ah); |
333 | 334 | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 8dce0077b023..c085a06f1e05 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -58,8 +58,8 @@ | |||
58 | #include "base.h" | 58 | #include "base.h" |
59 | #include "reg.h" | 59 | #include "reg.h" |
60 | #include "debug.h" | 60 | #include "debug.h" |
61 | #include "ani.h" | ||
61 | 62 | ||
62 | static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ | ||
63 | static int modparam_nohwcrypt; | 63 | static int modparam_nohwcrypt; |
64 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 64 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
65 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 65 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
@@ -198,7 +198,7 @@ static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | |||
198 | static int ath5k_pci_suspend(struct device *dev); | 198 | static int ath5k_pci_suspend(struct device *dev); |
199 | static int ath5k_pci_resume(struct device *dev); | 199 | static int ath5k_pci_resume(struct device *dev); |
200 | 200 | ||
201 | SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | 201 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); |
202 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | 202 | #define ATH5K_PM_OPS (&ath5k_pm_ops) |
203 | #else | 203 | #else |
204 | #define ATH5K_PM_OPS NULL | 204 | #define ATH5K_PM_OPS NULL |
@@ -307,7 +307,7 @@ static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | |||
307 | struct ath5k_buf *bf); | 307 | struct ath5k_buf *bf); |
308 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | 308 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, |
309 | struct ath5k_buf *bf, | 309 | struct ath5k_buf *bf, |
310 | struct ath5k_txq *txq); | 310 | struct ath5k_txq *txq, int padsize); |
311 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | 311 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, |
312 | struct ath5k_buf *bf) | 312 | struct ath5k_buf *bf) |
313 | { | 313 | { |
@@ -364,6 +364,7 @@ static void ath5k_beacon_send(struct ath5k_softc *sc); | |||
364 | static void ath5k_beacon_config(struct ath5k_softc *sc); | 364 | static void ath5k_beacon_config(struct ath5k_softc *sc); |
365 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | 365 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); |
366 | static void ath5k_tasklet_beacon(unsigned long data); | 366 | static void ath5k_tasklet_beacon(unsigned long data); |
367 | static void ath5k_tasklet_ani(unsigned long data); | ||
367 | 368 | ||
368 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | 369 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) |
369 | { | 370 | { |
@@ -829,6 +830,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
829 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); | 830 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); |
830 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); | 831 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); |
831 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); | 832 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); |
833 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); | ||
832 | 834 | ||
833 | ret = ath5k_eeprom_read_mac(ah, mac); | 835 | ret = ath5k_eeprom_read_mac(ah, mac); |
834 | if (ret) { | 836 | if (ret) { |
@@ -1137,8 +1139,6 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
1137 | struct ath5k_hw *ah = sc->ah; | 1139 | struct ath5k_hw *ah = sc->ah; |
1138 | u32 rfilt; | 1140 | u32 rfilt; |
1139 | 1141 | ||
1140 | ah->ah_op_mode = sc->opmode; | ||
1141 | |||
1142 | /* configure rx filter */ | 1142 | /* configure rx filter */ |
1143 | rfilt = sc->filter_flags; | 1143 | rfilt = sc->filter_flags; |
1144 | ath5k_hw_set_rx_filter(ah, rfilt); | 1144 | ath5k_hw_set_rx_filter(ah, rfilt); |
@@ -1147,8 +1147,9 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
1147 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); | 1147 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); |
1148 | 1148 | ||
1149 | /* configure operational mode */ | 1149 | /* configure operational mode */ |
1150 | ath5k_hw_set_opmode(ah); | 1150 | ath5k_hw_set_opmode(ah, sc->opmode); |
1151 | 1151 | ||
1152 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode); | ||
1152 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); | 1153 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); |
1153 | } | 1154 | } |
1154 | 1155 | ||
@@ -1271,7 +1272,7 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) | |||
1271 | 1272 | ||
1272 | static int | 1273 | static int |
1273 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | 1274 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, |
1274 | struct ath5k_txq *txq) | 1275 | struct ath5k_txq *txq, int padsize) |
1275 | { | 1276 | { |
1276 | struct ath5k_hw *ah = sc->ah; | 1277 | struct ath5k_hw *ah = sc->ah; |
1277 | struct ath5k_desc *ds = bf->desc; | 1278 | struct ath5k_desc *ds = bf->desc; |
@@ -1323,7 +1324,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1323 | sc->vif, pktlen, info)); | 1324 | sc->vif, pktlen, info)); |
1324 | } | 1325 | } |
1325 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1326 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1326 | ieee80211_get_hdrlen_from_skb(skb), | 1327 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
1327 | get_hw_packet_type(skb), | 1328 | get_hw_packet_type(skb), |
1328 | (sc->power_level * 2), | 1329 | (sc->power_level * 2), |
1329 | hw_rate, | 1330 | hw_rate, |
@@ -1806,6 +1807,86 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1806 | } | 1807 | } |
1807 | 1808 | ||
1808 | static void | 1809 | static void |
1810 | ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) | ||
1811 | { | ||
1812 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | ||
1813 | struct ath5k_hw *ah = sc->ah; | ||
1814 | struct ath_common *common = ath5k_hw_common(ah); | ||
1815 | |||
1816 | /* only beacons from our BSSID */ | ||
1817 | if (!ieee80211_is_beacon(mgmt->frame_control) || | ||
1818 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) | ||
1819 | return; | ||
1820 | |||
1821 | ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg, | ||
1822 | rssi); | ||
1823 | |||
1824 | /* in IBSS mode we should keep RSSI statistics per neighbour */ | ||
1825 | /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ | ||
1826 | } | ||
1827 | |||
1828 | /* | ||
1829 | * Compute padding position. skb must contains an IEEE 802.11 frame | ||
1830 | */ | ||
1831 | static int ath5k_common_padpos(struct sk_buff *skb) | ||
1832 | { | ||
1833 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; | ||
1834 | __le16 frame_control = hdr->frame_control; | ||
1835 | int padpos = 24; | ||
1836 | |||
1837 | if (ieee80211_has_a4(frame_control)) { | ||
1838 | padpos += ETH_ALEN; | ||
1839 | } | ||
1840 | if (ieee80211_is_data_qos(frame_control)) { | ||
1841 | padpos += IEEE80211_QOS_CTL_LEN; | ||
1842 | } | ||
1843 | |||
1844 | return padpos; | ||
1845 | } | ||
1846 | |||
1847 | /* | ||
1848 | * This function expects a 802.11 frame and returns the number of | ||
1849 | * bytes added, or -1 if we don't have enought header room. | ||
1850 | */ | ||
1851 | |||
1852 | static int ath5k_add_padding(struct sk_buff *skb) | ||
1853 | { | ||
1854 | int padpos = ath5k_common_padpos(skb); | ||
1855 | int padsize = padpos & 3; | ||
1856 | |||
1857 | if (padsize && skb->len>padpos) { | ||
1858 | |||
1859 | if (skb_headroom(skb) < padsize) | ||
1860 | return -1; | ||
1861 | |||
1862 | skb_push(skb, padsize); | ||
1863 | memmove(skb->data, skb->data+padsize, padpos); | ||
1864 | return padsize; | ||
1865 | } | ||
1866 | |||
1867 | return 0; | ||
1868 | } | ||
1869 | |||
1870 | /* | ||
1871 | * This function expects a 802.11 frame and returns the number of | ||
1872 | * bytes removed | ||
1873 | */ | ||
1874 | |||
1875 | static int ath5k_remove_padding(struct sk_buff *skb) | ||
1876 | { | ||
1877 | int padpos = ath5k_common_padpos(skb); | ||
1878 | int padsize = padpos & 3; | ||
1879 | |||
1880 | if (padsize && skb->len>=padpos+padsize) { | ||
1881 | memmove(skb->data + padsize, skb->data, padpos); | ||
1882 | skb_pull(skb, padsize); | ||
1883 | return padsize; | ||
1884 | } | ||
1885 | |||
1886 | return 0; | ||
1887 | } | ||
1888 | |||
1889 | static void | ||
1809 | ath5k_tasklet_rx(unsigned long data) | 1890 | ath5k_tasklet_rx(unsigned long data) |
1810 | { | 1891 | { |
1811 | struct ieee80211_rx_status *rxs; | 1892 | struct ieee80211_rx_status *rxs; |
@@ -1818,8 +1899,6 @@ ath5k_tasklet_rx(unsigned long data) | |||
1818 | struct ath5k_buf *bf; | 1899 | struct ath5k_buf *bf; |
1819 | struct ath5k_desc *ds; | 1900 | struct ath5k_desc *ds; |
1820 | int ret; | 1901 | int ret; |
1821 | int hdrlen; | ||
1822 | int padsize; | ||
1823 | int rx_flag; | 1902 | int rx_flag; |
1824 | 1903 | ||
1825 | spin_lock(&sc->rxbuflock); | 1904 | spin_lock(&sc->rxbuflock); |
@@ -1844,18 +1923,30 @@ ath5k_tasklet_rx(unsigned long data) | |||
1844 | break; | 1923 | break; |
1845 | else if (unlikely(ret)) { | 1924 | else if (unlikely(ret)) { |
1846 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); | 1925 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); |
1926 | sc->stats.rxerr_proc++; | ||
1847 | spin_unlock(&sc->rxbuflock); | 1927 | spin_unlock(&sc->rxbuflock); |
1848 | return; | 1928 | return; |
1849 | } | 1929 | } |
1850 | 1930 | ||
1931 | sc->stats.rx_all_count++; | ||
1932 | |||
1851 | if (unlikely(rs.rs_more)) { | 1933 | if (unlikely(rs.rs_more)) { |
1852 | ATH5K_WARN(sc, "unsupported jumbo\n"); | 1934 | ATH5K_WARN(sc, "unsupported jumbo\n"); |
1935 | sc->stats.rxerr_jumbo++; | ||
1853 | goto next; | 1936 | goto next; |
1854 | } | 1937 | } |
1855 | 1938 | ||
1856 | if (unlikely(rs.rs_status)) { | 1939 | if (unlikely(rs.rs_status)) { |
1857 | if (rs.rs_status & AR5K_RXERR_PHY) | 1940 | if (rs.rs_status & AR5K_RXERR_CRC) |
1941 | sc->stats.rxerr_crc++; | ||
1942 | if (rs.rs_status & AR5K_RXERR_FIFO) | ||
1943 | sc->stats.rxerr_fifo++; | ||
1944 | if (rs.rs_status & AR5K_RXERR_PHY) { | ||
1945 | sc->stats.rxerr_phy++; | ||
1946 | if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32) | ||
1947 | sc->stats.rxerr_phy_code[rs.rs_phyerr]++; | ||
1858 | goto next; | 1948 | goto next; |
1949 | } | ||
1859 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { | 1950 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { |
1860 | /* | 1951 | /* |
1861 | * Decrypt error. If the error occurred | 1952 | * Decrypt error. If the error occurred |
@@ -1867,12 +1958,14 @@ ath5k_tasklet_rx(unsigned long data) | |||
1867 | * | 1958 | * |
1868 | * XXX do key cache faulting | 1959 | * XXX do key cache faulting |
1869 | */ | 1960 | */ |
1961 | sc->stats.rxerr_decrypt++; | ||
1870 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && | 1962 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && |
1871 | !(rs.rs_status & AR5K_RXERR_CRC)) | 1963 | !(rs.rs_status & AR5K_RXERR_CRC)) |
1872 | goto accept; | 1964 | goto accept; |
1873 | } | 1965 | } |
1874 | if (rs.rs_status & AR5K_RXERR_MIC) { | 1966 | if (rs.rs_status & AR5K_RXERR_MIC) { |
1875 | rx_flag |= RX_FLAG_MMIC_ERROR; | 1967 | rx_flag |= RX_FLAG_MMIC_ERROR; |
1968 | sc->stats.rxerr_mic++; | ||
1876 | goto accept; | 1969 | goto accept; |
1877 | } | 1970 | } |
1878 | 1971 | ||
@@ -1904,12 +1997,8 @@ accept: | |||
1904 | * bytes and we can optimize this a bit. In addition, we must | 1997 | * bytes and we can optimize this a bit. In addition, we must |
1905 | * not try to remove padding from short control frames that do | 1998 | * not try to remove padding from short control frames that do |
1906 | * not have payload. */ | 1999 | * not have payload. */ |
1907 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 2000 | ath5k_remove_padding(skb); |
1908 | padsize = ath5k_pad_size(hdrlen); | 2001 | |
1909 | if (padsize) { | ||
1910 | memmove(skb->data + padsize, skb->data, hdrlen); | ||
1911 | skb_pull(skb, padsize); | ||
1912 | } | ||
1913 | rxs = IEEE80211_SKB_RXCB(skb); | 2002 | rxs = IEEE80211_SKB_RXCB(skb); |
1914 | 2003 | ||
1915 | /* | 2004 | /* |
@@ -1942,6 +2031,12 @@ accept: | |||
1942 | rxs->signal = rxs->noise + rs.rs_rssi; | 2031 | rxs->signal = rxs->noise + rs.rs_rssi; |
1943 | 2032 | ||
1944 | rxs->antenna = rs.rs_antenna; | 2033 | rxs->antenna = rs.rs_antenna; |
2034 | |||
2035 | if (rs.rs_antenna > 0 && rs.rs_antenna < 5) | ||
2036 | sc->stats.antenna_rx[rs.rs_antenna]++; | ||
2037 | else | ||
2038 | sc->stats.antenna_rx[0]++; /* invalid */ | ||
2039 | |||
1945 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); | 2040 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); |
1946 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); | 2041 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); |
1947 | 2042 | ||
@@ -1951,6 +2046,8 @@ accept: | |||
1951 | 2046 | ||
1952 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 2047 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); |
1953 | 2048 | ||
2049 | ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi); | ||
2050 | |||
1954 | /* check beacons in IBSS mode */ | 2051 | /* check beacons in IBSS mode */ |
1955 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | 2052 | if (sc->opmode == NL80211_IFTYPE_ADHOC) |
1956 | ath5k_check_ibss_tsf(sc, skb, rxs); | 2053 | ath5k_check_ibss_tsf(sc, skb, rxs); |
@@ -1996,6 +2093,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1996 | break; | 2093 | break; |
1997 | } | 2094 | } |
1998 | 2095 | ||
2096 | sc->stats.tx_all_count++; | ||
1999 | skb = bf->skb; | 2097 | skb = bf->skb; |
2000 | info = IEEE80211_SKB_CB(skb); | 2098 | info = IEEE80211_SKB_CB(skb); |
2001 | bf->skb = NULL; | 2099 | bf->skb = NULL; |
@@ -2021,14 +2119,31 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
2021 | info->status.rates[ts.ts_final_idx].count++; | 2119 | info->status.rates[ts.ts_final_idx].count++; |
2022 | 2120 | ||
2023 | if (unlikely(ts.ts_status)) { | 2121 | if (unlikely(ts.ts_status)) { |
2024 | sc->ll_stats.dot11ACKFailureCount++; | 2122 | sc->stats.ack_fail++; |
2025 | if (ts.ts_status & AR5K_TXERR_FILT) | 2123 | if (ts.ts_status & AR5K_TXERR_FILT) { |
2026 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 2124 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
2125 | sc->stats.txerr_filt++; | ||
2126 | } | ||
2127 | if (ts.ts_status & AR5K_TXERR_XRETRY) | ||
2128 | sc->stats.txerr_retry++; | ||
2129 | if (ts.ts_status & AR5K_TXERR_FIFO) | ||
2130 | sc->stats.txerr_fifo++; | ||
2027 | } else { | 2131 | } else { |
2028 | info->flags |= IEEE80211_TX_STAT_ACK; | 2132 | info->flags |= IEEE80211_TX_STAT_ACK; |
2029 | info->status.ack_signal = ts.ts_rssi; | 2133 | info->status.ack_signal = ts.ts_rssi; |
2030 | } | 2134 | } |
2031 | 2135 | ||
2136 | /* | ||
2137 | * Remove MAC header padding before giving the frame | ||
2138 | * back to mac80211. | ||
2139 | */ | ||
2140 | ath5k_remove_padding(skb); | ||
2141 | |||
2142 | if (ts.ts_antenna > 0 && ts.ts_antenna < 5) | ||
2143 | sc->stats.antenna_tx[ts.ts_antenna]++; | ||
2144 | else | ||
2145 | sc->stats.antenna_tx[0]++; /* invalid */ | ||
2146 | |||
2032 | ieee80211_tx_status(sc->hw, skb); | 2147 | ieee80211_tx_status(sc->hw, skb); |
2033 | 2148 | ||
2034 | spin_lock(&sc->txbuflock); | 2149 | spin_lock(&sc->txbuflock); |
@@ -2072,6 +2187,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2072 | int ret = 0; | 2187 | int ret = 0; |
2073 | u8 antenna; | 2188 | u8 antenna; |
2074 | u32 flags; | 2189 | u32 flags; |
2190 | const int padsize = 0; | ||
2075 | 2191 | ||
2076 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | 2192 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, |
2077 | PCI_DMA_TODEVICE); | 2193 | PCI_DMA_TODEVICE); |
@@ -2119,7 +2235,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2119 | * from tx power (value is in dB units already) */ | 2235 | * from tx power (value is in dB units already) */ |
2120 | ds->ds_data = bf->skbaddr; | 2236 | ds->ds_data = bf->skbaddr; |
2121 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, | 2237 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, |
2122 | ieee80211_get_hdrlen_from_skb(skb), | 2238 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
2123 | AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), | 2239 | AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), |
2124 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, | 2240 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, |
2125 | 1, AR5K_TXKEYIX_INVALID, | 2241 | 1, AR5K_TXKEYIX_INVALID, |
@@ -2406,9 +2522,6 @@ ath5k_init(struct ath5k_softc *sc) | |||
2406 | */ | 2522 | */ |
2407 | ath5k_stop_locked(sc); | 2523 | ath5k_stop_locked(sc); |
2408 | 2524 | ||
2409 | /* Set PHY calibration interval */ | ||
2410 | ah->ah_cal_intval = ath5k_calinterval; | ||
2411 | |||
2412 | /* | 2525 | /* |
2413 | * The basic interface to setting the hardware in a good | 2526 | * The basic interface to setting the hardware in a good |
2414 | * state is ``reset''. On return the hardware is known to | 2527 | * state is ``reset''. On return the hardware is known to |
@@ -2420,7 +2533,8 @@ ath5k_init(struct ath5k_softc *sc) | |||
2420 | sc->curband = &sc->sbands[sc->curchan->band]; | 2533 | sc->curband = &sc->sbands[sc->curchan->band]; |
2421 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | 2534 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | |
2422 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | 2535 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | |
2423 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI; | 2536 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; |
2537 | |||
2424 | ret = ath5k_reset(sc, NULL); | 2538 | ret = ath5k_reset(sc, NULL); |
2425 | if (ret) | 2539 | if (ret) |
2426 | goto done; | 2540 | goto done; |
@@ -2532,12 +2646,33 @@ ath5k_stop_hw(struct ath5k_softc *sc) | |||
2532 | tasklet_kill(&sc->restq); | 2646 | tasklet_kill(&sc->restq); |
2533 | tasklet_kill(&sc->calib); | 2647 | tasklet_kill(&sc->calib); |
2534 | tasklet_kill(&sc->beacontq); | 2648 | tasklet_kill(&sc->beacontq); |
2649 | tasklet_kill(&sc->ani_tasklet); | ||
2535 | 2650 | ||
2536 | ath5k_rfkill_hw_stop(sc->ah); | 2651 | ath5k_rfkill_hw_stop(sc->ah); |
2537 | 2652 | ||
2538 | return ret; | 2653 | return ret; |
2539 | } | 2654 | } |
2540 | 2655 | ||
2656 | static void | ||
2657 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) | ||
2658 | { | ||
2659 | if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) && | ||
2660 | !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) { | ||
2661 | /* run ANI only when full calibration is not active */ | ||
2662 | ah->ah_cal_next_ani = jiffies + | ||
2663 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); | ||
2664 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
2665 | |||
2666 | } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { | ||
2667 | ah->ah_cal_next_full = jiffies + | ||
2668 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); | ||
2669 | tasklet_schedule(&ah->ah_sc->calib); | ||
2670 | } | ||
2671 | /* we could use SWI to generate enough interrupts to meet our | ||
2672 | * calibration interval requirements, if necessary: | ||
2673 | * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ | ||
2674 | } | ||
2675 | |||
2541 | static irqreturn_t | 2676 | static irqreturn_t |
2542 | ath5k_intr(int irq, void *dev_id) | 2677 | ath5k_intr(int irq, void *dev_id) |
2543 | { | 2678 | { |
@@ -2586,15 +2721,10 @@ ath5k_intr(int irq, void *dev_id) | |||
2586 | if (status & AR5K_INT_BMISS) { | 2721 | if (status & AR5K_INT_BMISS) { |
2587 | /* TODO */ | 2722 | /* TODO */ |
2588 | } | 2723 | } |
2589 | if (status & AR5K_INT_SWI) { | ||
2590 | tasklet_schedule(&sc->calib); | ||
2591 | } | ||
2592 | if (status & AR5K_INT_MIB) { | 2724 | if (status & AR5K_INT_MIB) { |
2593 | /* | 2725 | sc->stats.mib_intr++; |
2594 | * These stats are also used for ANI i think | 2726 | ath5k_hw_update_mib_counters(ah); |
2595 | * so how about updating them more often ? | 2727 | ath5k_ani_mib_intr(ah); |
2596 | */ | ||
2597 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | ||
2598 | } | 2728 | } |
2599 | if (status & AR5K_INT_GPIO) | 2729 | if (status & AR5K_INT_GPIO) |
2600 | tasklet_schedule(&sc->rf_kill.toggleq); | 2730 | tasklet_schedule(&sc->rf_kill.toggleq); |
@@ -2605,7 +2735,7 @@ ath5k_intr(int irq, void *dev_id) | |||
2605 | if (unlikely(!counter)) | 2735 | if (unlikely(!counter)) |
2606 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); | 2736 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); |
2607 | 2737 | ||
2608 | ath5k_hw_calibration_poll(ah); | 2738 | ath5k_intr_calibration_poll(ah); |
2609 | 2739 | ||
2610 | return IRQ_HANDLED; | 2740 | return IRQ_HANDLED; |
2611 | } | 2741 | } |
@@ -2629,8 +2759,7 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2629 | struct ath5k_hw *ah = sc->ah; | 2759 | struct ath5k_hw *ah = sc->ah; |
2630 | 2760 | ||
2631 | /* Only full calibration for now */ | 2761 | /* Only full calibration for now */ |
2632 | if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION) | 2762 | ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; |
2633 | return; | ||
2634 | 2763 | ||
2635 | /* Stop queues so that calibration | 2764 | /* Stop queues so that calibration |
2636 | * doesn't interfere with tx */ | 2765 | * doesn't interfere with tx */ |
@@ -2653,11 +2782,22 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2653 | ieee80211_frequency_to_channel( | 2782 | ieee80211_frequency_to_channel( |
2654 | sc->curchan->center_freq)); | 2783 | sc->curchan->center_freq)); |
2655 | 2784 | ||
2656 | ah->ah_swi_mask = 0; | ||
2657 | |||
2658 | /* Wake queues */ | 2785 | /* Wake queues */ |
2659 | ieee80211_wake_queues(sc->hw); | 2786 | ieee80211_wake_queues(sc->hw); |
2660 | 2787 | ||
2788 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; | ||
2789 | } | ||
2790 | |||
2791 | |||
2792 | static void | ||
2793 | ath5k_tasklet_ani(unsigned long data) | ||
2794 | { | ||
2795 | struct ath5k_softc *sc = (void *)data; | ||
2796 | struct ath5k_hw *ah = sc->ah; | ||
2797 | |||
2798 | ah->ah_cal_mask |= AR5K_CALIBRATION_ANI; | ||
2799 | ath5k_ani_calibration(ah); | ||
2800 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_ANI; | ||
2661 | } | 2801 | } |
2662 | 2802 | ||
2663 | 2803 | ||
@@ -2679,7 +2819,6 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2679 | struct ath5k_softc *sc = hw->priv; | 2819 | struct ath5k_softc *sc = hw->priv; |
2680 | struct ath5k_buf *bf; | 2820 | struct ath5k_buf *bf; |
2681 | unsigned long flags; | 2821 | unsigned long flags; |
2682 | int hdrlen; | ||
2683 | int padsize; | 2822 | int padsize; |
2684 | 2823 | ||
2685 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | 2824 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); |
@@ -2691,17 +2830,11 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2691 | * the hardware expects the header padded to 4 byte boundaries | 2830 | * the hardware expects the header padded to 4 byte boundaries |
2692 | * if this is not the case we add the padding after the header | 2831 | * if this is not the case we add the padding after the header |
2693 | */ | 2832 | */ |
2694 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 2833 | padsize = ath5k_add_padding(skb); |
2695 | padsize = ath5k_pad_size(hdrlen); | 2834 | if (padsize < 0) { |
2696 | if (padsize) { | 2835 | ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" |
2697 | 2836 | " headroom to pad"); | |
2698 | if (skb_headroom(skb) < padsize) { | 2837 | goto drop_packet; |
2699 | ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" | ||
2700 | " headroom to pad %d\n", hdrlen, padsize); | ||
2701 | goto drop_packet; | ||
2702 | } | ||
2703 | skb_push(skb, padsize); | ||
2704 | memmove(skb->data, skb->data+padsize, hdrlen); | ||
2705 | } | 2838 | } |
2706 | 2839 | ||
2707 | spin_lock_irqsave(&sc->txbuflock, flags); | 2840 | spin_lock_irqsave(&sc->txbuflock, flags); |
@@ -2720,7 +2853,7 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2720 | 2853 | ||
2721 | bf->skb = skb; | 2854 | bf->skb = skb; |
2722 | 2855 | ||
2723 | if (ath5k_txbuf_setup(sc, bf, txq)) { | 2856 | if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { |
2724 | bf->skb = NULL; | 2857 | bf->skb = NULL; |
2725 | spin_lock_irqsave(&sc->txbuflock, flags); | 2858 | spin_lock_irqsave(&sc->txbuflock, flags); |
2726 | list_add_tail(&bf->list, &sc->txbuf); | 2859 | list_add_tail(&bf->list, &sc->txbuf); |
@@ -2767,6 +2900,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
2767 | goto err; | 2900 | goto err; |
2768 | } | 2901 | } |
2769 | 2902 | ||
2903 | ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); | ||
2904 | |||
2770 | /* | 2905 | /* |
2771 | * Change channels and update the h/w rate map if we're switching; | 2906 | * Change channels and update the h/w rate map if we're switching; |
2772 | * e.g. 11a to 11b/g. | 2907 | * e.g. 11a to 11b/g. |
@@ -2835,6 +2970,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2835 | goto end; | 2970 | goto end; |
2836 | } | 2971 | } |
2837 | 2972 | ||
2973 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode); | ||
2974 | |||
2838 | ath5k_hw_set_lladdr(sc->ah, vif->addr); | 2975 | ath5k_hw_set_lladdr(sc->ah, vif->addr); |
2839 | ath5k_mode_setup(sc); | 2976 | ath5k_mode_setup(sc); |
2840 | 2977 | ||
@@ -2905,7 +3042,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) | |||
2905 | * then we must allow the user to set how many tx antennas we | 3042 | * then we must allow the user to set how many tx antennas we |
2906 | * have available | 3043 | * have available |
2907 | */ | 3044 | */ |
2908 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); | 3045 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); |
2909 | 3046 | ||
2910 | unlock: | 3047 | unlock: |
2911 | mutex_unlock(&sc->lock); | 3048 | mutex_unlock(&sc->lock); |
@@ -3123,12 +3260,14 @@ ath5k_get_stats(struct ieee80211_hw *hw, | |||
3123 | struct ieee80211_low_level_stats *stats) | 3260 | struct ieee80211_low_level_stats *stats) |
3124 | { | 3261 | { |
3125 | struct ath5k_softc *sc = hw->priv; | 3262 | struct ath5k_softc *sc = hw->priv; |
3126 | struct ath5k_hw *ah = sc->ah; | ||
3127 | 3263 | ||
3128 | /* Force update */ | 3264 | /* Force update */ |
3129 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | 3265 | ath5k_hw_update_mib_counters(sc->ah); |
3130 | 3266 | ||
3131 | memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); | 3267 | stats->dot11ACKFailureCount = sc->stats.ack_fail; |
3268 | stats->dot11RTSFailureCount = sc->stats.rts_fail; | ||
3269 | stats->dot11RTSSuccessCount = sc->stats.rts_ok; | ||
3270 | stats->dot11FCSErrorCount = sc->stats.fcs_error; | ||
3132 | 3271 | ||
3133 | return 0; | 3272 | return 0; |
3134 | } | 3273 | } |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 7e1a88a5abdb..53a5651c57a2 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -50,6 +50,7 @@ | |||
50 | 50 | ||
51 | #include "ath5k.h" | 51 | #include "ath5k.h" |
52 | #include "debug.h" | 52 | #include "debug.h" |
53 | #include "ani.h" | ||
53 | 54 | ||
54 | #include "../regd.h" | 55 | #include "../regd.h" |
55 | #include "../ath.h" | 56 | #include "../ath.h" |
@@ -105,6 +106,37 @@ struct ath5k_rfkill { | |||
105 | struct tasklet_struct toggleq; | 106 | struct tasklet_struct toggleq; |
106 | }; | 107 | }; |
107 | 108 | ||
109 | /* statistics */ | ||
110 | struct ath5k_statistics { | ||
111 | /* antenna use */ | ||
112 | unsigned int antenna_rx[5]; /* frames count per antenna RX */ | ||
113 | unsigned int antenna_tx[5]; /* frames count per antenna TX */ | ||
114 | |||
115 | /* frame errors */ | ||
116 | unsigned int rx_all_count; /* all RX frames, including errors */ | ||
117 | unsigned int tx_all_count; /* all TX frames, including errors */ | ||
118 | unsigned int rxerr_crc; | ||
119 | unsigned int rxerr_phy; | ||
120 | unsigned int rxerr_phy_code[32]; | ||
121 | unsigned int rxerr_fifo; | ||
122 | unsigned int rxerr_decrypt; | ||
123 | unsigned int rxerr_mic; | ||
124 | unsigned int rxerr_proc; | ||
125 | unsigned int rxerr_jumbo; | ||
126 | unsigned int txerr_retry; | ||
127 | unsigned int txerr_fifo; | ||
128 | unsigned int txerr_filt; | ||
129 | |||
130 | /* MIB counters */ | ||
131 | unsigned int ack_fail; | ||
132 | unsigned int rts_fail; | ||
133 | unsigned int rts_ok; | ||
134 | unsigned int fcs_error; | ||
135 | unsigned int beacons; | ||
136 | |||
137 | unsigned int mib_intr; | ||
138 | }; | ||
139 | |||
108 | #if CHAN_DEBUG | 140 | #if CHAN_DEBUG |
109 | #define ATH_CHAN_MAX (26+26+26+200+200) | 141 | #define ATH_CHAN_MAX (26+26+26+200+200) |
110 | #else | 142 | #else |
@@ -117,7 +149,6 @@ struct ath5k_softc { | |||
117 | struct pci_dev *pdev; /* for dma mapping */ | 149 | struct pci_dev *pdev; /* for dma mapping */ |
118 | void __iomem *iobase; /* address of the device */ | 150 | void __iomem *iobase; /* address of the device */ |
119 | struct mutex lock; /* dev-level lock */ | 151 | struct mutex lock; /* dev-level lock */ |
120 | struct ieee80211_low_level_stats ll_stats; | ||
121 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ | 152 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ |
122 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 153 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
123 | struct ieee80211_channel channels[ATH_CHAN_MAX]; | 154 | struct ieee80211_channel channels[ATH_CHAN_MAX]; |
@@ -191,6 +222,11 @@ struct ath5k_softc { | |||
191 | int power_level; /* Requested tx power in dbm */ | 222 | int power_level; /* Requested tx power in dbm */ |
192 | bool assoc; /* associate state */ | 223 | bool assoc; /* associate state */ |
193 | bool enable_beacon; /* true if beacons are on */ | 224 | bool enable_beacon; /* true if beacons are on */ |
225 | |||
226 | struct ath5k_statistics stats; | ||
227 | |||
228 | struct ath5k_ani_state ani_state; | ||
229 | struct tasklet_struct ani_tasklet; /* ANI calibration */ | ||
194 | }; | 230 | }; |
195 | 231 | ||
196 | #define ath5k_hw_hasbssidmask(_ah) \ | 232 | #define ath5k_hw_hasbssidmask(_ah) \ |
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index 367a6c7d3cc7..74f007126f41 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c | |||
@@ -102,9 +102,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
102 | } | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | /* GPIO */ | ||
106 | ah->ah_gpio_npins = AR5K_NUM_GPIO; | ||
107 | |||
108 | /* Set number of supported TX queues */ | 105 | /* Set number of supported TX queues */ |
109 | if (ah->ah_version == AR5K_AR5210) | 106 | if (ah->ah_version == AR5K_AR5210) |
110 | ah->ah_capabilities.cap_queues.q_tx_num = | 107 | ah->ah_capabilities.cap_queues.q_tx_num = |
@@ -112,6 +109,12 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
112 | else | 109 | else |
113 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; | 110 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; |
114 | 111 | ||
112 | /* newer hardware has PHY error counters */ | ||
113 | if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) | ||
114 | ah->ah_capabilities.cap_has_phyerr_counters = true; | ||
115 | else | ||
116 | ah->ah_capabilities.cap_has_phyerr_counters = false; | ||
117 | |||
115 | return 0; | 118 | return 0; |
116 | } | 119 | } |
117 | 120 | ||
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 747508c15d34..6fb5c5ffa5b1 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -69,6 +69,7 @@ module_param_named(debug, ath5k_debug, uint, 0); | |||
69 | 69 | ||
70 | #include <linux/seq_file.h> | 70 | #include <linux/seq_file.h> |
71 | #include "reg.h" | 71 | #include "reg.h" |
72 | #include "ani.h" | ||
72 | 73 | ||
73 | static struct dentry *ath5k_global_debugfs; | 74 | static struct dentry *ath5k_global_debugfs; |
74 | 75 | ||
@@ -307,6 +308,7 @@ static const struct { | |||
307 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, | 308 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, |
308 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, | 309 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, |
309 | { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, | 310 | { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, |
311 | { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, | ||
310 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, | 312 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, |
311 | }; | 313 | }; |
312 | 314 | ||
@@ -364,6 +366,369 @@ static const struct file_operations fops_debug = { | |||
364 | }; | 366 | }; |
365 | 367 | ||
366 | 368 | ||
369 | /* debugfs: antenna */ | ||
370 | |||
371 | static ssize_t read_file_antenna(struct file *file, char __user *user_buf, | ||
372 | size_t count, loff_t *ppos) | ||
373 | { | ||
374 | struct ath5k_softc *sc = file->private_data; | ||
375 | char buf[700]; | ||
376 | unsigned int len = 0; | ||
377 | unsigned int i; | ||
378 | unsigned int v; | ||
379 | |||
380 | len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n", | ||
381 | sc->ah->ah_ant_mode); | ||
382 | len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n", | ||
383 | sc->ah->ah_def_ant); | ||
384 | len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n", | ||
385 | sc->ah->ah_tx_ant); | ||
386 | |||
387 | len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n"); | ||
388 | for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) { | ||
389 | len += snprintf(buf+len, sizeof(buf)-len, | ||
390 | "[antenna %d]\t%d\t%d\n", | ||
391 | i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]); | ||
392 | } | ||
393 | len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n", | ||
394 | sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]); | ||
395 | |||
396 | v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA); | ||
397 | len += snprintf(buf+len, sizeof(buf)-len, | ||
398 | "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v); | ||
399 | |||
400 | v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1); | ||
401 | len += snprintf(buf+len, sizeof(buf)-len, | ||
402 | "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n", | ||
403 | (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0); | ||
404 | len += snprintf(buf+len, sizeof(buf)-len, | ||
405 | "AR5K_STA_ID1_DESC_ANTENNA\t%d\n", | ||
406 | (v & AR5K_STA_ID1_DESC_ANTENNA) != 0); | ||
407 | len += snprintf(buf+len, sizeof(buf)-len, | ||
408 | "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n", | ||
409 | (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0); | ||
410 | len += snprintf(buf+len, sizeof(buf)-len, | ||
411 | "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n", | ||
412 | (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0); | ||
413 | |||
414 | v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL); | ||
415 | len += snprintf(buf+len, sizeof(buf)-len, | ||
416 | "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n", | ||
417 | (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0); | ||
418 | |||
419 | v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART); | ||
420 | len += snprintf(buf+len, sizeof(buf)-len, | ||
421 | "AR5K_PHY_RESTART_DIV_GC\t\t%x\n", | ||
422 | (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S); | ||
423 | |||
424 | v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV); | ||
425 | len += snprintf(buf+len, sizeof(buf)-len, | ||
426 | "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n", | ||
427 | (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0); | ||
428 | |||
429 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
430 | } | ||
431 | |||
432 | static ssize_t write_file_antenna(struct file *file, | ||
433 | const char __user *userbuf, | ||
434 | size_t count, loff_t *ppos) | ||
435 | { | ||
436 | struct ath5k_softc *sc = file->private_data; | ||
437 | unsigned int i; | ||
438 | char buf[20]; | ||
439 | |||
440 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
441 | return -EFAULT; | ||
442 | |||
443 | if (strncmp(buf, "diversity", 9) == 0) { | ||
444 | ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); | ||
445 | printk(KERN_INFO "ath5k debug: enable diversity\n"); | ||
446 | } else if (strncmp(buf, "fixed-a", 7) == 0) { | ||
447 | ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); | ||
448 | printk(KERN_INFO "ath5k debugfs: fixed antenna A\n"); | ||
449 | } else if (strncmp(buf, "fixed-b", 7) == 0) { | ||
450 | ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); | ||
451 | printk(KERN_INFO "ath5k debug: fixed antenna B\n"); | ||
452 | } else if (strncmp(buf, "clear", 5) == 0) { | ||
453 | for (i = 0; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) { | ||
454 | sc->stats.antenna_rx[i] = 0; | ||
455 | sc->stats.antenna_tx[i] = 0; | ||
456 | } | ||
457 | printk(KERN_INFO "ath5k debug: cleared antenna stats\n"); | ||
458 | } | ||
459 | return count; | ||
460 | } | ||
461 | |||
462 | static const struct file_operations fops_antenna = { | ||
463 | .read = read_file_antenna, | ||
464 | .write = write_file_antenna, | ||
465 | .open = ath5k_debugfs_open, | ||
466 | .owner = THIS_MODULE, | ||
467 | }; | ||
468 | |||
469 | |||
470 | /* debugfs: frameerrors */ | ||
471 | |||
472 | static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, | ||
473 | size_t count, loff_t *ppos) | ||
474 | { | ||
475 | struct ath5k_softc *sc = file->private_data; | ||
476 | struct ath5k_statistics *st = &sc->stats; | ||
477 | char buf[700]; | ||
478 | unsigned int len = 0; | ||
479 | int i; | ||
480 | |||
481 | len += snprintf(buf+len, sizeof(buf)-len, | ||
482 | "RX\n---------------------\n"); | ||
483 | len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n", | ||
484 | st->rxerr_crc, | ||
485 | st->rx_all_count > 0 ? | ||
486 | st->rxerr_crc*100/st->rx_all_count : 0); | ||
487 | len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n", | ||
488 | st->rxerr_phy, | ||
489 | st->rx_all_count > 0 ? | ||
490 | st->rxerr_phy*100/st->rx_all_count : 0); | ||
491 | for (i = 0; i < 32; i++) { | ||
492 | if (st->rxerr_phy_code[i]) | ||
493 | len += snprintf(buf+len, sizeof(buf)-len, | ||
494 | " phy_err[%d]\t%d\n", | ||
495 | i, st->rxerr_phy_code[i]); | ||
496 | } | ||
497 | |||
498 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", | ||
499 | st->rxerr_fifo, | ||
500 | st->rx_all_count > 0 ? | ||
501 | st->rxerr_fifo*100/st->rx_all_count : 0); | ||
502 | len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n", | ||
503 | st->rxerr_decrypt, | ||
504 | st->rx_all_count > 0 ? | ||
505 | st->rxerr_decrypt*100/st->rx_all_count : 0); | ||
506 | len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n", | ||
507 | st->rxerr_mic, | ||
508 | st->rx_all_count > 0 ? | ||
509 | st->rxerr_mic*100/st->rx_all_count : 0); | ||
510 | len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n", | ||
511 | st->rxerr_proc, | ||
512 | st->rx_all_count > 0 ? | ||
513 | st->rxerr_proc*100/st->rx_all_count : 0); | ||
514 | len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n", | ||
515 | st->rxerr_jumbo, | ||
516 | st->rx_all_count > 0 ? | ||
517 | st->rxerr_jumbo*100/st->rx_all_count : 0); | ||
518 | len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n", | ||
519 | st->rx_all_count); | ||
520 | |||
521 | len += snprintf(buf+len, sizeof(buf)-len, | ||
522 | "\nTX\n---------------------\n"); | ||
523 | len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n", | ||
524 | st->txerr_retry, | ||
525 | st->tx_all_count > 0 ? | ||
526 | st->txerr_retry*100/st->tx_all_count : 0); | ||
527 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", | ||
528 | st->txerr_fifo, | ||
529 | st->tx_all_count > 0 ? | ||
530 | st->txerr_fifo*100/st->tx_all_count : 0); | ||
531 | len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n", | ||
532 | st->txerr_filt, | ||
533 | st->tx_all_count > 0 ? | ||
534 | st->txerr_filt*100/st->tx_all_count : 0); | ||
535 | len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n", | ||
536 | st->tx_all_count); | ||
537 | |||
538 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
539 | } | ||
540 | |||
541 | static ssize_t write_file_frameerrors(struct file *file, | ||
542 | const char __user *userbuf, | ||
543 | size_t count, loff_t *ppos) | ||
544 | { | ||
545 | struct ath5k_softc *sc = file->private_data; | ||
546 | struct ath5k_statistics *st = &sc->stats; | ||
547 | char buf[20]; | ||
548 | |||
549 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
550 | return -EFAULT; | ||
551 | |||
552 | if (strncmp(buf, "clear", 5) == 0) { | ||
553 | st->rxerr_crc = 0; | ||
554 | st->rxerr_phy = 0; | ||
555 | st->rxerr_fifo = 0; | ||
556 | st->rxerr_decrypt = 0; | ||
557 | st->rxerr_mic = 0; | ||
558 | st->rxerr_proc = 0; | ||
559 | st->rxerr_jumbo = 0; | ||
560 | st->rx_all_count = 0; | ||
561 | st->txerr_retry = 0; | ||
562 | st->txerr_fifo = 0; | ||
563 | st->txerr_filt = 0; | ||
564 | st->tx_all_count = 0; | ||
565 | printk(KERN_INFO "ath5k debug: cleared frameerrors stats\n"); | ||
566 | } | ||
567 | return count; | ||
568 | } | ||
569 | |||
570 | static const struct file_operations fops_frameerrors = { | ||
571 | .read = read_file_frameerrors, | ||
572 | .write = write_file_frameerrors, | ||
573 | .open = ath5k_debugfs_open, | ||
574 | .owner = THIS_MODULE, | ||
575 | }; | ||
576 | |||
577 | |||
578 | /* debugfs: ani */ | ||
579 | |||
580 | static ssize_t read_file_ani(struct file *file, char __user *user_buf, | ||
581 | size_t count, loff_t *ppos) | ||
582 | { | ||
583 | struct ath5k_softc *sc = file->private_data; | ||
584 | struct ath5k_statistics *st = &sc->stats; | ||
585 | struct ath5k_ani_state *as = &sc->ani_state; | ||
586 | |||
587 | char buf[700]; | ||
588 | unsigned int len = 0; | ||
589 | |||
590 | len += snprintf(buf+len, sizeof(buf)-len, | ||
591 | "HW has PHY error counters:\t%s\n", | ||
592 | sc->ah->ah_capabilities.cap_has_phyerr_counters ? | ||
593 | "yes" : "no"); | ||
594 | len += snprintf(buf+len, sizeof(buf)-len, | ||
595 | "HW max spur immunity level:\t%d\n", | ||
596 | as->max_spur_level); | ||
597 | len += snprintf(buf+len, sizeof(buf)-len, | ||
598 | "\nANI state\n--------------------------------------------\n"); | ||
599 | len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t"); | ||
600 | switch (as->ani_mode) { | ||
601 | case ATH5K_ANI_MODE_OFF: | ||
602 | len += snprintf(buf+len, sizeof(buf)-len, "OFF\n"); | ||
603 | break; | ||
604 | case ATH5K_ANI_MODE_MANUAL_LOW: | ||
605 | len += snprintf(buf+len, sizeof(buf)-len, | ||
606 | "MANUAL LOW\n"); | ||
607 | break; | ||
608 | case ATH5K_ANI_MODE_MANUAL_HIGH: | ||
609 | len += snprintf(buf+len, sizeof(buf)-len, | ||
610 | "MANUAL HIGH\n"); | ||
611 | break; | ||
612 | case ATH5K_ANI_MODE_AUTO: | ||
613 | len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n"); | ||
614 | break; | ||
615 | default: | ||
616 | len += snprintf(buf+len, sizeof(buf)-len, | ||
617 | "??? (not good)\n"); | ||
618 | break; | ||
619 | } | ||
620 | len += snprintf(buf+len, sizeof(buf)-len, | ||
621 | "noise immunity level:\t\t%d\n", | ||
622 | as->noise_imm_level); | ||
623 | len += snprintf(buf+len, sizeof(buf)-len, | ||
624 | "spur immunity level:\t\t%d\n", | ||
625 | as->spur_level); | ||
626 | len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n", | ||
627 | as->firstep_level); | ||
628 | len += snprintf(buf+len, sizeof(buf)-len, | ||
629 | "OFDM weak signal detection:\t%s\n", | ||
630 | as->ofdm_weak_sig ? "on" : "off"); | ||
631 | len += snprintf(buf+len, sizeof(buf)-len, | ||
632 | "CCK weak signal detection:\t%s\n", | ||
633 | as->cck_weak_sig ? "on" : "off"); | ||
634 | |||
635 | len += snprintf(buf+len, sizeof(buf)-len, | ||
636 | "\nMIB INTERRUPTS:\t\t%u\n", | ||
637 | st->mib_intr); | ||
638 | len += snprintf(buf+len, sizeof(buf)-len, | ||
639 | "beacon RSSI average:\t%d\n", | ||
640 | sc->ah->ah_beacon_rssi_avg.avg); | ||
641 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n", | ||
642 | as->pfc_tx, | ||
643 | as->pfc_cycles > 0 ? | ||
644 | as->pfc_tx*100/as->pfc_cycles : 0); | ||
645 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n", | ||
646 | as->pfc_rx, | ||
647 | as->pfc_cycles > 0 ? | ||
648 | as->pfc_rx*100/as->pfc_cycles : 0); | ||
649 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n", | ||
650 | as->pfc_busy, | ||
651 | as->pfc_cycles > 0 ? | ||
652 | as->pfc_busy*100/as->pfc_cycles : 0); | ||
653 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n", | ||
654 | as->pfc_cycles); | ||
655 | len += snprintf(buf+len, sizeof(buf)-len, | ||
656 | "listen time\t\t%d\tlast: %d\n", | ||
657 | as->listen_time, as->last_listen); | ||
658 | len += snprintf(buf+len, sizeof(buf)-len, | ||
659 | "OFDM errors\t\t%u\tlast: %u\tsum: %u\n", | ||
660 | as->ofdm_errors, as->last_ofdm_errors, | ||
661 | as->sum_ofdm_errors); | ||
662 | len += snprintf(buf+len, sizeof(buf)-len, | ||
663 | "CCK errors\t\t%u\tlast: %u\tsum: %u\n", | ||
664 | as->cck_errors, as->last_cck_errors, | ||
665 | as->sum_cck_errors); | ||
666 | len += snprintf(buf+len, sizeof(buf)-len, | ||
667 | "AR5K_PHYERR_CNT1\t%x\t(=%d)\n", | ||
668 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1), | ||
669 | ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - | ||
670 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1))); | ||
671 | len += snprintf(buf+len, sizeof(buf)-len, | ||
672 | "AR5K_PHYERR_CNT2\t%x\t(=%d)\n", | ||
673 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2), | ||
674 | ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - | ||
675 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2))); | ||
676 | |||
677 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
678 | } | ||
679 | |||
680 | static ssize_t write_file_ani(struct file *file, | ||
681 | const char __user *userbuf, | ||
682 | size_t count, loff_t *ppos) | ||
683 | { | ||
684 | struct ath5k_softc *sc = file->private_data; | ||
685 | char buf[20]; | ||
686 | |||
687 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
688 | return -EFAULT; | ||
689 | |||
690 | if (strncmp(buf, "sens-low", 8) == 0) { | ||
691 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH); | ||
692 | } else if (strncmp(buf, "sens-high", 9) == 0) { | ||
693 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW); | ||
694 | } else if (strncmp(buf, "ani-off", 7) == 0) { | ||
695 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF); | ||
696 | } else if (strncmp(buf, "ani-on", 6) == 0) { | ||
697 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO); | ||
698 | } else if (strncmp(buf, "noise-low", 9) == 0) { | ||
699 | ath5k_ani_set_noise_immunity_level(sc->ah, 0); | ||
700 | } else if (strncmp(buf, "noise-high", 10) == 0) { | ||
701 | ath5k_ani_set_noise_immunity_level(sc->ah, | ||
702 | ATH5K_ANI_MAX_NOISE_IMM_LVL); | ||
703 | } else if (strncmp(buf, "spur-low", 8) == 0) { | ||
704 | ath5k_ani_set_spur_immunity_level(sc->ah, 0); | ||
705 | } else if (strncmp(buf, "spur-high", 9) == 0) { | ||
706 | ath5k_ani_set_spur_immunity_level(sc->ah, | ||
707 | sc->ani_state.max_spur_level); | ||
708 | } else if (strncmp(buf, "fir-low", 7) == 0) { | ||
709 | ath5k_ani_set_firstep_level(sc->ah, 0); | ||
710 | } else if (strncmp(buf, "fir-high", 8) == 0) { | ||
711 | ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL); | ||
712 | } else if (strncmp(buf, "ofdm-off", 8) == 0) { | ||
713 | ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false); | ||
714 | } else if (strncmp(buf, "ofdm-on", 7) == 0) { | ||
715 | ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true); | ||
716 | } else if (strncmp(buf, "cck-off", 7) == 0) { | ||
717 | ath5k_ani_set_cck_weak_signal_detection(sc->ah, false); | ||
718 | } else if (strncmp(buf, "cck-on", 6) == 0) { | ||
719 | ath5k_ani_set_cck_weak_signal_detection(sc->ah, true); | ||
720 | } | ||
721 | return count; | ||
722 | } | ||
723 | |||
724 | static const struct file_operations fops_ani = { | ||
725 | .read = read_file_ani, | ||
726 | .write = write_file_ani, | ||
727 | .open = ath5k_debugfs_open, | ||
728 | .owner = THIS_MODULE, | ||
729 | }; | ||
730 | |||
731 | |||
367 | /* init */ | 732 | /* init */ |
368 | 733 | ||
369 | void | 734 | void |
@@ -393,6 +758,20 @@ ath5k_debug_init_device(struct ath5k_softc *sc) | |||
393 | 758 | ||
394 | sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, | 759 | sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, |
395 | sc->debug.debugfs_phydir, sc, &fops_reset); | 760 | sc->debug.debugfs_phydir, sc, &fops_reset); |
761 | |||
762 | sc->debug.debugfs_antenna = debugfs_create_file("antenna", | ||
763 | S_IWUSR | S_IRUSR, | ||
764 | sc->debug.debugfs_phydir, sc, &fops_antenna); | ||
765 | |||
766 | sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", | ||
767 | S_IWUSR | S_IRUSR, | ||
768 | sc->debug.debugfs_phydir, sc, | ||
769 | &fops_frameerrors); | ||
770 | |||
771 | sc->debug.debugfs_ani = debugfs_create_file("ani", | ||
772 | S_IWUSR | S_IRUSR, | ||
773 | sc->debug.debugfs_phydir, sc, | ||
774 | &fops_ani); | ||
396 | } | 775 | } |
397 | 776 | ||
398 | void | 777 | void |
@@ -408,6 +787,9 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) | |||
408 | debugfs_remove(sc->debug.debugfs_registers); | 787 | debugfs_remove(sc->debug.debugfs_registers); |
409 | debugfs_remove(sc->debug.debugfs_beacon); | 788 | debugfs_remove(sc->debug.debugfs_beacon); |
410 | debugfs_remove(sc->debug.debugfs_reset); | 789 | debugfs_remove(sc->debug.debugfs_reset); |
790 | debugfs_remove(sc->debug.debugfs_antenna); | ||
791 | debugfs_remove(sc->debug.debugfs_frameerrors); | ||
792 | debugfs_remove(sc->debug.debugfs_ani); | ||
411 | debugfs_remove(sc->debug.debugfs_phydir); | 793 | debugfs_remove(sc->debug.debugfs_phydir); |
412 | } | 794 | } |
413 | 795 | ||
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 66f69f04e55e..ddd5b3a99e8d 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h | |||
@@ -74,6 +74,9 @@ struct ath5k_dbg_info { | |||
74 | struct dentry *debugfs_registers; | 74 | struct dentry *debugfs_registers; |
75 | struct dentry *debugfs_beacon; | 75 | struct dentry *debugfs_beacon; |
76 | struct dentry *debugfs_reset; | 76 | struct dentry *debugfs_reset; |
77 | struct dentry *debugfs_antenna; | ||
78 | struct dentry *debugfs_frameerrors; | ||
79 | struct dentry *debugfs_ani; | ||
77 | }; | 80 | }; |
78 | 81 | ||
79 | /** | 82 | /** |
@@ -113,6 +116,7 @@ enum ath5k_debug_level { | |||
113 | ATH5K_DEBUG_DUMP_TX = 0x00000200, | 116 | ATH5K_DEBUG_DUMP_TX = 0x00000200, |
114 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, | 117 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, |
115 | ATH5K_DEBUG_TRACE = 0x00001000, | 118 | ATH5K_DEBUG_TRACE = 0x00001000, |
119 | ATH5K_DEBUG_ANI = 0x00002000, | ||
116 | ATH5K_DEBUG_ANY = 0xffffffff | 120 | ATH5K_DEBUG_ANY = 0xffffffff |
117 | }; | 121 | }; |
118 | 122 | ||
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index dc30a2b70a6b..7d7b646ab65a 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -35,7 +35,8 @@ | |||
35 | */ | 35 | */ |
36 | static int | 36 | static int |
37 | ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 37 | ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, |
38 | unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type, | 38 | unsigned int pkt_len, unsigned int hdr_len, int padsize, |
39 | enum ath5k_pkt_type type, | ||
39 | unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, | 40 | unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, |
40 | unsigned int key_index, unsigned int antenna_mode, unsigned int flags, | 41 | unsigned int key_index, unsigned int antenna_mode, unsigned int flags, |
41 | unsigned int rtscts_rate, unsigned int rtscts_duration) | 42 | unsigned int rtscts_rate, unsigned int rtscts_duration) |
@@ -71,7 +72,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
71 | /* Verify and set frame length */ | 72 | /* Verify and set frame length */ |
72 | 73 | ||
73 | /* remove padding we might have added before */ | 74 | /* remove padding we might have added before */ |
74 | frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; | 75 | frame_len = pkt_len - padsize + FCS_LEN; |
75 | 76 | ||
76 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) | 77 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) |
77 | return -EINVAL; | 78 | return -EINVAL; |
@@ -100,7 +101,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
100 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); | 101 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); |
101 | } | 102 | } |
102 | 103 | ||
103 | /*Diferences between 5210-5211*/ | 104 | /*Differences between 5210-5211*/ |
104 | if (ah->ah_version == AR5K_AR5210) { | 105 | if (ah->ah_version == AR5K_AR5210) { |
105 | switch (type) { | 106 | switch (type) { |
106 | case AR5K_PKT_TYPE_BEACON: | 107 | case AR5K_PKT_TYPE_BEACON: |
@@ -165,6 +166,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
165 | */ | 166 | */ |
166 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | 167 | static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, |
167 | struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, | 168 | struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, |
169 | int padsize, | ||
168 | enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, | 170 | enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, |
169 | unsigned int tx_tries0, unsigned int key_index, | 171 | unsigned int tx_tries0, unsigned int key_index, |
170 | unsigned int antenna_mode, unsigned int flags, | 172 | unsigned int antenna_mode, unsigned int flags, |
@@ -206,7 +208,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
206 | /* Verify and set frame length */ | 208 | /* Verify and set frame length */ |
207 | 209 | ||
208 | /* remove padding we might have added before */ | 210 | /* remove padding we might have added before */ |
209 | frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; | 211 | frame_len = pkt_len - padsize + FCS_LEN; |
210 | 212 | ||
211 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) | 213 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) |
212 | return -EINVAL; | 214 | return -EINVAL; |
@@ -229,7 +231,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
229 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); | 231 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); |
230 | tx_ctl->tx_control_1 |= AR5K_REG_SM(type, | 232 | tx_ctl->tx_control_1 |= AR5K_REG_SM(type, |
231 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); | 233 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); |
232 | tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, | 234 | tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0, |
233 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); | 235 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); |
234 | tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | 236 | tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; |
235 | 237 | ||
@@ -643,6 +645,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
643 | rs->rs_status |= AR5K_RXERR_PHY; | 645 | rs->rs_status |= AR5K_RXERR_PHY; |
644 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, | 646 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, |
645 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); | 647 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); |
648 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); | ||
646 | } | 649 | } |
647 | 650 | ||
648 | if (rx_status->rx_status_1 & | 651 | if (rx_status->rx_status_1 & |
@@ -668,12 +671,6 @@ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) | |||
668 | ah->ah_version != AR5K_AR5212) | 671 | ah->ah_version != AR5K_AR5212) |
669 | return -ENOTSUPP; | 672 | return -ENOTSUPP; |
670 | 673 | ||
671 | /* XXX: What is this magic value and where is it used ? */ | ||
672 | if (ah->ah_version == AR5K_AR5212) | ||
673 | ah->ah_magic = AR5K_EEPROM_MAGIC_5212; | ||
674 | else if (ah->ah_version == AR5K_AR5211) | ||
675 | ah->ah_magic = AR5K_EEPROM_MAGIC_5211; | ||
676 | |||
677 | if (ah->ah_version == AR5K_AR5212) { | 674 | if (ah->ah_version == AR5K_AR5212) { |
678 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; | 675 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; |
679 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; | 676 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; |
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index 56158c804e3e..64538fbe4167 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h | |||
@@ -112,15 +112,32 @@ struct ath5k_hw_rx_error { | |||
112 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 | 112 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 |
113 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 | 113 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 |
114 | 114 | ||
115 | /* PHY Error codes */ | 115 | /** |
116 | #define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 | 116 | * enum ath5k_phy_error_code - PHY Error codes |
117 | #define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 | 117 | */ |
118 | #define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 | 118 | enum ath5k_phy_error_code { |
119 | #define AR5K_DESC_RX_PHY_ERROR_RATE 0x60 | 119 | AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun */ |
120 | #define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80 | 120 | AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ |
121 | #define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0 | 121 | AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ |
122 | #define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 | 122 | AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ |
123 | #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 | 123 | AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ |
124 | AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect */ | ||
125 | AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ | ||
126 | AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ | ||
127 | /* these are specific to the 5212 */ | ||
128 | AR5K_RX_PHY_ERROR_OFDM_TIMING = 17, | ||
129 | AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18, | ||
130 | AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19, | ||
131 | AR5K_RX_PHY_ERROR_OFDM_LENGTH_ILLEGAL = 20, | ||
132 | AR5K_RX_PHY_ERROR_OFDM_POWER_DROP = 21, | ||
133 | AR5K_RX_PHY_ERROR_OFDM_SERVICE = 22, | ||
134 | AR5K_RX_PHY_ERROR_OFDM_RESTART = 23, | ||
135 | AR5K_RX_PHY_ERROR_CCK_TIMING = 25, | ||
136 | AR5K_RX_PHY_ERROR_CCK_HEADER_CRC = 26, | ||
137 | AR5K_RX_PHY_ERROR_CCK_RATE_ILLEGAL = 27, | ||
138 | AR5K_RX_PHY_ERROR_CCK_SERVICE = 30, | ||
139 | AR5K_RX_PHY_ERROR_CCK_RESTART = 31, | ||
140 | }; | ||
124 | 141 | ||
125 | /* | 142 | /* |
126 | * 5210/5211 hardware 2-word TX control descriptor | 143 | * 5210/5211 hardware 2-word TX control descriptor |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 10b52262b232..a3cbfe4fc389 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -329,7 +329,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
329 | ee->ee_x_gain[mode] = (val >> 1) & 0xf; | 329 | ee->ee_x_gain[mode] = (val >> 1) & 0xf; |
330 | ee->ee_xpd[mode] = val & 0x1; | 330 | ee->ee_xpd[mode] = val & 0x1; |
331 | 331 | ||
332 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) | 332 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && |
333 | mode != AR5K_EEPROM_MODE_11B) | ||
333 | ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; | 334 | ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; |
334 | 335 | ||
335 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { | 336 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { |
@@ -339,6 +340,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
339 | if (mode == AR5K_EEPROM_MODE_11A) | 340 | if (mode == AR5K_EEPROM_MODE_11A) |
340 | ee->ee_xr_power[mode] = val & 0x3f; | 341 | ee->ee_xr_power[mode] = val & 0x3f; |
341 | else { | 342 | else { |
343 | /* b_DB_11[bg] and b_OB_11[bg] */ | ||
342 | ee->ee_ob[mode][0] = val & 0x7; | 344 | ee->ee_ob[mode][0] = val & 0x7; |
343 | ee->ee_db[mode][0] = (val >> 3) & 0x7; | 345 | ee->ee_db[mode][0] = (val >> 3) & 0x7; |
344 | } | 346 | } |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 473a483bb9c3..c4a6d5f26af4 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h | |||
@@ -24,9 +24,6 @@ | |||
24 | * SERDES infos are present */ | 24 | * SERDES infos are present */ |
25 | #define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ | 25 | #define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ |
26 | #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ | 26 | #define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ |
27 | #define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ | ||
28 | #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ | ||
29 | #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ | ||
30 | 27 | ||
31 | #define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ | 28 | #define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ |
32 | 29 | ||
@@ -78,9 +75,9 @@ | |||
78 | #define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) | 75 | #define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) |
79 | #define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) | 76 | #define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) |
80 | #define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) | 77 | #define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) |
81 | #define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ | 78 | #define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz */ |
82 | #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ | 79 | #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for < 2W power consumption */ |
83 | #define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) | 80 | #define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) /* Device type (1 Cardbus, 2 PCI, 3 MiniPCI, 4 AP) */ |
84 | #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ | 81 | #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ |
85 | #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ | 82 | #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ |
86 | 83 | ||
@@ -101,7 +98,7 @@ | |||
101 | 98 | ||
102 | #define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) | 99 | #define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) |
103 | #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) | 100 | #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) |
104 | #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) | 101 | #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) /* has 32KHz crystal for sleep mode */ |
105 | #define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1) | 102 | #define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1) |
106 | 103 | ||
107 | #define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6) | 104 | #define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6) |
@@ -114,26 +111,27 @@ | |||
114 | 111 | ||
115 | #define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8) | 112 | #define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8) |
116 | #define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff) | 113 | #define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff) |
117 | #define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) | 114 | #define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) /* modes supported by radio 0 (bit 1: G, bit 2: A) */ |
118 | #define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) | 115 | #define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) /* modes supported by radio 1 (bit 1: G, bit 2: A) */ |
119 | 116 | ||
120 | #define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9) | 117 | #define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9) |
121 | #define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) | 118 | #define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) /* disable compression */ |
122 | #define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) | 119 | #define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) /* disable AES */ |
123 | #define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) | 120 | #define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) /* disable fast frames */ |
124 | #define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) | 121 | #define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) /* disable bursting */ |
125 | #define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) | 122 | #define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) /* max number of QCUs. defaults to 10 */ |
126 | #define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) | 123 | #define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) /* enable heayy clipping */ |
127 | #define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) | 124 | #define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) /* key cache size. defaults to 128 */ |
128 | 125 | ||
129 | #define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10) | 126 | #define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10) |
130 | #define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8) | 127 | #define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x7) /* MIMO chains disabled for TX bitmask */ |
131 | #define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8) | 128 | #define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x7) /* MIMO chains disabled for RX bitmask */ |
132 | #define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) | 129 | #define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) /* 5.47-5.7GHz supported */ |
133 | #define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) | 130 | #define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) /* Japan UNII1 band (5.15-5.25GHz) on even channels (5180, 5200, 5220, 5240) supported */ |
134 | #define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) | 131 | #define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) /* Japan UNII2 band (5.25-5.35GHz) supported */ |
135 | #define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1) | 132 | #define AR5K_EEPROM_JAP_MID_EN (((_v) >> 9) & 0x1) /* Japan band from 5.47-5.7GHz supported */ |
136 | #define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1) | 133 | #define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 10) & 0x1) /* Japan UNII2 band (5.15-5.25GHz) on odd channels (5170, 5190, 5210, 5230) supported */ |
134 | #define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 11) & 0x1) /* Japan A mode enabled (using even channels) */ | ||
137 | 135 | ||
138 | /* calibration settings */ | 136 | /* calibration settings */ |
139 | #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) | 137 | #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) |
@@ -389,7 +387,49 @@ struct ath5k_edge_power { | |||
389 | bool flag; | 387 | bool flag; |
390 | }; | 388 | }; |
391 | 389 | ||
392 | /* EEPROM calibration data */ | 390 | /** |
391 | * struct ath5k_eeprom_info - EEPROM calibration data | ||
392 | * | ||
393 | * @ee_regdomain: ath/regd.c takes care of COUNTRY_ERD and WORLDWIDE_ROAMING | ||
394 | * flags | ||
395 | * @ee_ant_gain: Antenna gain in 0.5dB steps signed [5211 only?] | ||
396 | * @ee_cck_ofdm_gain_delta: difference in gainF to output the same power for | ||
397 | * OFDM and CCK packets | ||
398 | * @ee_cck_ofdm_power_delta: power difference between OFDM (6Mbps) and CCK | ||
399 | * (11Mbps) rate in G mode. 0.1dB steps | ||
400 | * @ee_scaled_cck_delta: for Japan Channel 14: 0.1dB resolution | ||
401 | * | ||
402 | * @ee_i_cal: Initial I coefficient to correct I/Q mismatch in the receive path | ||
403 | * @ee_q_cal: Initial Q coefficient to correct I/Q mismatch in the receive path | ||
404 | * @ee_fixed_bias: use ee_ob and ee_db settings or use automatic control | ||
405 | * @ee_switch_settling: RX/TX Switch settling time | ||
406 | * @ee_atn_tx_rx: Difference in attenuation between TX and RX in 1dB steps | ||
407 | * @ee_ant_control: Antenna Control Settings | ||
408 | * @ee_ob: Bias current for Output stage of PA | ||
409 | * B/G mode: Index [0] is used for AR2112/5112, otherwise [1] | ||
410 | * A mode: [0] 5.15-5.25 [1] 5.25-5.50 [2] 5.50-5.70 [3] 5.70-5.85 GHz | ||
411 | * @ee_db: Bias current for Output stage of PA. see @ee_ob | ||
412 | * @ee_tx_end2xlna_enable: Time difference from when BB finishes sending a frame | ||
413 | * to when the external LNA is activated | ||
414 | * @ee_tx_end2xpa_disable: Time difference from when BB finishes sending a frame | ||
415 | * to when the external PA switch is deactivated | ||
416 | * @ee_tx_frm2xpa_enable: Time difference from when MAC sends frame to when | ||
417 | * external PA switch is activated | ||
418 | * @ee_thr_62: Clear Channel Assessment (CCA) sensitivity | ||
419 | * (IEEE802.11a section 17.3.10.5 ) | ||
420 | * @ee_xlna_gain: Total gain of the LNA (information only) | ||
421 | * @ee_xpd: Use external (1) or internal power detector | ||
422 | * @ee_x_gain: Gain for external power detector output (differences in EEMAP | ||
423 | * versions!) | ||
424 | * @ee_i_gain: Initial gain value after reset | ||
425 | * @ee_margin_tx_rx: Margin in dB when final attenuation stage should be used | ||
426 | * | ||
427 | * @ee_false_detect: Backoff in Sensitivity (dB) on channels with spur signals | ||
428 | * @ee_noise_floor_thr: Noise floor threshold in 1dB steps | ||
429 | * @ee_adc_desired_size: Desired amplitude for ADC, used by AGC; in 0.5 dB steps | ||
430 | * @ee_pga_desired_size: Desired output of PGA (for BB gain) in 0.5 dB steps | ||
431 | * @ee_pd_gain_overlap: PD ADC curves need to overlap in 0.5dB steps (ee_map>=2) | ||
432 | */ | ||
393 | struct ath5k_eeprom_info { | 433 | struct ath5k_eeprom_info { |
394 | 434 | ||
395 | /* Header information */ | 435 | /* Header information */ |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index aefe84f9c04b..710870ea179b 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -39,16 +39,16 @@ | |||
39 | * ath5k_hw_set_opmode - Set PCU operating mode | 39 | * ath5k_hw_set_opmode - Set PCU operating mode |
40 | * | 40 | * |
41 | * @ah: The &struct ath5k_hw | 41 | * @ah: The &struct ath5k_hw |
42 | * @op_mode: &enum nl80211_iftype operating mode | ||
42 | * | 43 | * |
43 | * Initialize PCU for the various operating modes (AP/STA etc) | 44 | * Initialize PCU for the various operating modes (AP/STA etc) |
44 | * | ||
45 | * NOTE: ah->ah_op_mode must be set before calling this. | ||
46 | */ | 45 | */ |
47 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) | 46 | int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) |
48 | { | 47 | { |
49 | struct ath_common *common = ath5k_hw_common(ah); | 48 | struct ath_common *common = ath5k_hw_common(ah); |
50 | u32 pcu_reg, beacon_reg, low_id, high_id; | 49 | u32 pcu_reg, beacon_reg, low_id, high_id; |
51 | 50 | ||
51 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); | ||
52 | 52 | ||
53 | /* Preserve rest settings */ | 53 | /* Preserve rest settings */ |
54 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | 54 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; |
@@ -61,7 +61,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) | |||
61 | 61 | ||
62 | ATH5K_TRACE(ah->ah_sc); | 62 | ATH5K_TRACE(ah->ah_sc); |
63 | 63 | ||
64 | switch (ah->ah_op_mode) { | 64 | switch (op_mode) { |
65 | case NL80211_IFTYPE_ADHOC: | 65 | case NL80211_IFTYPE_ADHOC: |
66 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; | 66 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; |
67 | beacon_reg |= AR5K_BCR_ADHOC; | 67 | beacon_reg |= AR5K_BCR_ADHOC; |
@@ -113,39 +113,26 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) | |||
113 | } | 113 | } |
114 | 114 | ||
115 | /** | 115 | /** |
116 | * ath5k_hw_update - Update mib counters (mac layer statistics) | 116 | * ath5k_hw_update - Update MIB counters (mac layer statistics) |
117 | * | 117 | * |
118 | * @ah: The &struct ath5k_hw | 118 | * @ah: The &struct ath5k_hw |
119 | * @stats: The &struct ieee80211_low_level_stats we use to track | ||
120 | * statistics on the driver | ||
121 | * | 119 | * |
122 | * Reads MIB counters from PCU and updates sw statistics. Must be | 120 | * Reads MIB counters from PCU and updates sw statistics. Is called after a |
123 | * called after a MIB interrupt. | 121 | * MIB interrupt, because one of these counters might have reached their maximum |
122 | * and triggered the MIB interrupt, to let us read and clear the counter. | ||
123 | * | ||
124 | * Is called in interrupt context! | ||
124 | */ | 125 | */ |
125 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | 126 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) |
126 | struct ieee80211_low_level_stats *stats) | ||
127 | { | 127 | { |
128 | ATH5K_TRACE(ah->ah_sc); | 128 | struct ath5k_statistics *stats = &ah->ah_sc->stats; |
129 | 129 | ||
130 | /* Read-And-Clear */ | 130 | /* Read-And-Clear */ |
131 | stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); | 131 | stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); |
132 | stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); | 132 | stats->rts_fail += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); |
133 | stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); | 133 | stats->rts_ok += ath5k_hw_reg_read(ah, AR5K_RTS_OK); |
134 | stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); | 134 | stats->fcs_error += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); |
135 | 135 | stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | |
136 | /* XXX: Should we use this to track beacon count ? | ||
137 | * -we read it anyway to clear the register */ | ||
138 | ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | ||
139 | |||
140 | /* Reset profile count registers on 5212*/ | ||
141 | if (ah->ah_version == AR5K_AR5212) { | ||
142 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
143 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
144 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
145 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
146 | } | ||
147 | |||
148 | /* TODO: Handle ANI stats */ | ||
149 | } | 136 | } |
150 | 137 | ||
151 | /** | 138 | /** |
@@ -179,25 +166,12 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | |||
179 | \******************/ | 166 | \******************/ |
180 | 167 | ||
181 | /** | 168 | /** |
182 | * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec | ||
183 | * | ||
184 | * @ah: The &struct ath5k_hw | ||
185 | */ | ||
186 | unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | ||
187 | { | ||
188 | ATH5K_TRACE(ah->ah_sc); | ||
189 | |||
190 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
191 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK)); | ||
192 | } | ||
193 | |||
194 | /** | ||
195 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU | 169 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU |
196 | * | 170 | * |
197 | * @ah: The &struct ath5k_hw | 171 | * @ah: The &struct ath5k_hw |
198 | * @timeout: Timeout in usec | 172 | * @timeout: Timeout in usec |
199 | */ | 173 | */ |
200 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | 174 | static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) |
201 | { | 175 | { |
202 | ATH5K_TRACE(ah->ah_sc); | 176 | ATH5K_TRACE(ah->ah_sc); |
203 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) | 177 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) |
@@ -211,24 +185,12 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
211 | } | 185 | } |
212 | 186 | ||
213 | /** | 187 | /** |
214 | * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec | ||
215 | * | ||
216 | * @ah: The &struct ath5k_hw | ||
217 | */ | ||
218 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | ||
219 | { | ||
220 | ATH5K_TRACE(ah->ah_sc); | ||
221 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, | ||
222 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS)); | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU | 188 | * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU |
227 | * | 189 | * |
228 | * @ah: The &struct ath5k_hw | 190 | * @ah: The &struct ath5k_hw |
229 | * @timeout: Timeout in usec | 191 | * @timeout: Timeout in usec |
230 | */ | 192 | */ |
231 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | 193 | static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) |
232 | { | 194 | { |
233 | ATH5K_TRACE(ah->ah_sc); | 195 | ATH5K_TRACE(ah->ah_sc); |
234 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) | 196 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) |
@@ -290,7 +252,7 @@ unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) | |||
290 | * | 252 | * |
291 | * @ah: The &struct ath5k_hw | 253 | * @ah: The &struct ath5k_hw |
292 | */ | 254 | */ |
293 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | 255 | static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) |
294 | { | 256 | { |
295 | struct ieee80211_channel *channel = ah->ah_current_channel; | 257 | struct ieee80211_channel *channel = ah->ah_current_channel; |
296 | 258 | ||
@@ -308,7 +270,7 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | |||
308 | * | 270 | * |
309 | * @ah: The &struct ath5k_hw | 271 | * @ah: The &struct ath5k_hw |
310 | */ | 272 | */ |
311 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | 273 | static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) |
312 | { | 274 | { |
313 | struct ieee80211_channel *channel = ah->ah_current_channel; | 275 | struct ieee80211_channel *channel = ah->ah_current_channel; |
314 | 276 | ||
@@ -417,7 +379,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | |||
417 | * (ACK etc). | 379 | * (ACK etc). |
418 | * | 380 | * |
419 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | 381 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma |
420 | * TODO: Init ANI here | ||
421 | */ | 382 | */ |
422 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | 383 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) |
423 | { | 384 | { |
@@ -451,42 +412,6 @@ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) | |||
451 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); | 412 | ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); |
452 | } | 413 | } |
453 | 414 | ||
454 | /* | ||
455 | * Set multicast filter by index | ||
456 | */ | ||
457 | int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
458 | { | ||
459 | |||
460 | ATH5K_TRACE(ah->ah_sc); | ||
461 | if (index >= 64) | ||
462 | return -EINVAL; | ||
463 | else if (index >= 32) | ||
464 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
465 | (1 << (index - 32))); | ||
466 | else | ||
467 | AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * Clear Multicast filter by index | ||
474 | */ | ||
475 | int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) | ||
476 | { | ||
477 | |||
478 | ATH5K_TRACE(ah->ah_sc); | ||
479 | if (index >= 64) | ||
480 | return -EINVAL; | ||
481 | else if (index >= 32) | ||
482 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, | ||
483 | (1 << (index - 32))); | ||
484 | else | ||
485 | AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | /** | 415 | /** |
491 | * ath5k_hw_get_rx_filter - Get current rx filter | 416 | * ath5k_hw_get_rx_filter - Get current rx filter |
492 | * | 417 | * |
@@ -572,19 +497,6 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | |||
572 | \****************/ | 497 | \****************/ |
573 | 498 | ||
574 | /** | 499 | /** |
575 | * ath5k_hw_get_tsf32 - Get a 32bit TSF | ||
576 | * | ||
577 | * @ah: The &struct ath5k_hw | ||
578 | * | ||
579 | * Returns lower 32 bits of current TSF | ||
580 | */ | ||
581 | u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) | ||
582 | { | ||
583 | ATH5K_TRACE(ah->ah_sc); | ||
584 | return ath5k_hw_reg_read(ah, AR5K_TSF_L32); | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF | 500 | * ath5k_hw_get_tsf64 - Get the full 64bit TSF |
589 | * | 501 | * |
590 | * @ah: The &struct ath5k_hw | 502 | * @ah: The &struct ath5k_hw |
@@ -651,7 +563,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
651 | /* | 563 | /* |
652 | * Set the additional timers by mode | 564 | * Set the additional timers by mode |
653 | */ | 565 | */ |
654 | switch (ah->ah_op_mode) { | 566 | switch (ah->ah_sc->opmode) { |
655 | case NL80211_IFTYPE_MONITOR: | 567 | case NL80211_IFTYPE_MONITOR: |
656 | case NL80211_IFTYPE_STATION: | 568 | case NL80211_IFTYPE_STATION: |
657 | /* In STA mode timer1 is used as next wakeup | 569 | /* In STA mode timer1 is used as next wakeup |
@@ -688,8 +600,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
688 | * Set the beacon register and enable all timers. | 600 | * Set the beacon register and enable all timers. |
689 | */ | 601 | */ |
690 | /* When in AP or Mesh Point mode zero timer0 to start TSF */ | 602 | /* When in AP or Mesh Point mode zero timer0 to start TSF */ |
691 | if (ah->ah_op_mode == NL80211_IFTYPE_AP || | 603 | if (ah->ah_sc->opmode == NL80211_IFTYPE_AP || |
692 | ah->ah_op_mode == NL80211_IFTYPE_MESH_POINT) | 604 | ah->ah_sc->opmode == NL80211_IFTYPE_MESH_POINT) |
693 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | 605 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); |
694 | 606 | ||
695 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | 607 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); |
@@ -722,203 +634,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
722 | 634 | ||
723 | } | 635 | } |
724 | 636 | ||
725 | #if 0 | ||
726 | /* | ||
727 | * Set beacon timers | ||
728 | */ | ||
729 | int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, | ||
730 | const struct ath5k_beacon_state *state) | ||
731 | { | ||
732 | u32 cfp_period, next_cfp, dtim, interval, next_beacon; | ||
733 | |||
734 | /* | ||
735 | * TODO: should be changed through *state | ||
736 | * review struct ath5k_beacon_state struct | ||
737 | * | ||
738 | * XXX: These are used for cfp period bellow, are they | ||
739 | * ok ? Is it O.K. for tsf here to be 0 or should we use | ||
740 | * get_tsf ? | ||
741 | */ | ||
742 | u32 dtim_count = 0; /* XXX */ | ||
743 | u32 cfp_count = 0; /* XXX */ | ||
744 | u32 tsf = 0; /* XXX */ | ||
745 | |||
746 | ATH5K_TRACE(ah->ah_sc); | ||
747 | /* Return on an invalid beacon state */ | ||
748 | if (state->bs_interval < 1) | ||
749 | return -EINVAL; | ||
750 | |||
751 | interval = state->bs_interval; | ||
752 | dtim = state->bs_dtim_period; | ||
753 | |||
754 | /* | ||
755 | * PCF support? | ||
756 | */ | ||
757 | if (state->bs_cfp_period > 0) { | ||
758 | /* | ||
759 | * Enable PCF mode and set the CFP | ||
760 | * (Contention Free Period) and timer registers | ||
761 | */ | ||
762 | cfp_period = state->bs_cfp_period * state->bs_dtim_period * | ||
763 | state->bs_interval; | ||
764 | next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * | ||
765 | state->bs_interval; | ||
766 | |||
767 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, | ||
768 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
769 | AR5K_STA_ID1_PCF); | ||
770 | ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); | ||
771 | ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, | ||
772 | AR5K_CFP_DUR); | ||
773 | ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : | ||
774 | next_cfp)) << 3, AR5K_TIMER2); | ||
775 | } else { | ||
776 | /* Disable PCF mode */ | ||
777 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
778 | AR5K_STA_ID1_DEFAULT_ANTENNA | | ||
779 | AR5K_STA_ID1_PCF); | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | * Enable the beacon timer register | ||
784 | */ | ||
785 | ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); | ||
786 | |||
787 | /* | ||
788 | * Start the beacon timers | ||
789 | */ | ||
790 | ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & | ||
791 | ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | | ||
792 | AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, | ||
793 | AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, | ||
794 | AR5K_BEACON_PERIOD), AR5K_BEACON); | ||
795 | |||
796 | /* | ||
797 | * Write new beacon miss threshold, if it appears to be valid | ||
798 | * XXX: Figure out right values for min <= bs_bmiss_threshold <= max | ||
799 | * and return if its not in range. We can test this by reading value and | ||
800 | * setting value to a largest value and seeing which values register. | ||
801 | */ | ||
802 | |||
803 | AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, | ||
804 | state->bs_bmiss_threshold); | ||
805 | |||
806 | /* | ||
807 | * Set sleep control register | ||
808 | * XXX: Didn't find this in 5210 code but since this register | ||
809 | * exists also in ar5k's 5210 headers i leave it as common code. | ||
810 | */ | ||
811 | AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, | ||
812 | (state->bs_sleep_duration - 3) << 3); | ||
813 | |||
814 | /* | ||
815 | * Set enhanced sleep registers on 5212 | ||
816 | */ | ||
817 | if (ah->ah_version == AR5K_AR5212) { | ||
818 | if (state->bs_sleep_duration > state->bs_interval && | ||
819 | roundup(state->bs_sleep_duration, interval) == | ||
820 | state->bs_sleep_duration) | ||
821 | interval = state->bs_sleep_duration; | ||
822 | |||
823 | if (state->bs_sleep_duration > dtim && (dtim == 0 || | ||
824 | roundup(state->bs_sleep_duration, dtim) == | ||
825 | state->bs_sleep_duration)) | ||
826 | dtim = state->bs_sleep_duration; | ||
827 | |||
828 | if (interval > dtim) | ||
829 | return -EINVAL; | ||
830 | |||
831 | next_beacon = interval == dtim ? state->bs_next_dtim : | ||
832 | state->bs_next_beacon; | ||
833 | |||
834 | ath5k_hw_reg_write(ah, | ||
835 | AR5K_REG_SM((state->bs_next_dtim - 3) << 3, | ||
836 | AR5K_SLEEP0_NEXT_DTIM) | | ||
837 | AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | | ||
838 | AR5K_SLEEP0_ENH_SLEEP_EN | | ||
839 | AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); | ||
840 | |||
841 | ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, | ||
842 | AR5K_SLEEP1_NEXT_TIM) | | ||
843 | AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); | ||
844 | |||
845 | ath5k_hw_reg_write(ah, | ||
846 | AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | | ||
847 | AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); | ||
848 | } | ||
849 | |||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | /* | ||
854 | * Reset beacon timers | ||
855 | */ | ||
856 | void ath5k_hw_reset_beacon(struct ath5k_hw *ah) | ||
857 | { | ||
858 | ATH5K_TRACE(ah->ah_sc); | ||
859 | /* | ||
860 | * Disable beacon timer | ||
861 | */ | ||
862 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | ||
863 | |||
864 | /* | ||
865 | * Disable some beacon register values | ||
866 | */ | ||
867 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, | ||
868 | AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); | ||
869 | ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); | ||
870 | } | ||
871 | |||
872 | /* | ||
873 | * Wait for beacon queue to finish | ||
874 | */ | ||
875 | int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) | ||
876 | { | ||
877 | unsigned int i; | ||
878 | int ret; | ||
879 | |||
880 | ATH5K_TRACE(ah->ah_sc); | ||
881 | |||
882 | /* 5210 doesn't have QCU*/ | ||
883 | if (ah->ah_version == AR5K_AR5210) { | ||
884 | /* | ||
885 | * Wait for beaconn queue to finish by checking | ||
886 | * Control Register and Beacon Status Register. | ||
887 | */ | ||
888 | for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { | ||
889 | if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) | ||
890 | || | ||
891 | !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) | ||
892 | break; | ||
893 | udelay(10); | ||
894 | } | ||
895 | |||
896 | /* Timeout... */ | ||
897 | if (i <= 0) { | ||
898 | /* | ||
899 | * Re-schedule the beacon queue | ||
900 | */ | ||
901 | ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); | ||
902 | ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, | ||
903 | AR5K_BCR); | ||
904 | |||
905 | return -EIO; | ||
906 | } | ||
907 | ret = 0; | ||
908 | } else { | ||
909 | /*5211/5212*/ | ||
910 | ret = ath5k_hw_register_timeout(ah, | ||
911 | AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), | ||
912 | AR5K_QCU_STS_FRMPENDCNT, 0, false); | ||
913 | |||
914 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) | ||
915 | return -EIO; | ||
916 | } | ||
917 | |||
918 | return ret; | ||
919 | } | ||
920 | #endif | ||
921 | |||
922 | 637 | ||
923 | /*********************\ | 638 | /*********************\ |
924 | * Key table functions * | 639 | * Key table functions * |
@@ -971,19 +686,6 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | |||
971 | return 0; | 686 | return 0; |
972 | } | 687 | } |
973 | 688 | ||
974 | /* | ||
975 | * Check if a table entry is valid | ||
976 | */ | ||
977 | int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) | ||
978 | { | ||
979 | ATH5K_TRACE(ah->ah_sc); | ||
980 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
981 | |||
982 | /* Check the validation flag at the end of the entry */ | ||
983 | return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & | ||
984 | AR5K_KEYTABLE_VALID; | ||
985 | } | ||
986 | |||
987 | static | 689 | static |
988 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) | 690 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) |
989 | { | 691 | { |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index eff3323efb4b..b6704c93f808 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -20,8 +20,6 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #define _ATH5K_PHY | ||
24 | |||
25 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
26 | 24 | ||
27 | #include "ath5k.h" | 25 | #include "ath5k.h" |
@@ -1104,28 +1102,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1104 | PHY calibration | 1102 | PHY calibration |
1105 | \*****************/ | 1103 | \*****************/ |
1106 | 1104 | ||
1107 | void | ||
1108 | ath5k_hw_calibration_poll(struct ath5k_hw *ah) | ||
1109 | { | ||
1110 | /* Calibration interval in jiffies */ | ||
1111 | unsigned long cal_intval; | ||
1112 | |||
1113 | cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000); | ||
1114 | |||
1115 | /* Initialize timestamp if needed */ | ||
1116 | if (!ah->ah_cal_tstamp) | ||
1117 | ah->ah_cal_tstamp = jiffies; | ||
1118 | |||
1119 | /* For now we always do full calibration | ||
1120 | * Mark software interrupt mask and fire software | ||
1121 | * interrupt (bit gets auto-cleared) */ | ||
1122 | if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) { | ||
1123 | ah->ah_cal_tstamp = jiffies; | ||
1124 | ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; | ||
1125 | AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); | ||
1126 | } | ||
1127 | } | ||
1128 | |||
1129 | static int sign_extend(int val, const int nbits) | 1105 | static int sign_extend(int val, const int nbits) |
1130 | { | 1106 | { |
1131 | int order = BIT(nbits-1); | 1107 | int order = BIT(nbits-1); |
@@ -1190,7 +1166,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) | |||
1190 | * The median of the values in the history is then loaded into the | 1166 | * The median of the values in the history is then loaded into the |
1191 | * hardware for its own use for RSSI and CCA measurements. | 1167 | * hardware for its own use for RSSI and CCA measurements. |
1192 | */ | 1168 | */ |
1193 | void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | 1169 | static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) |
1194 | { | 1170 | { |
1195 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 1171 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
1196 | u32 val; | 1172 | u32 val; |
@@ -1399,7 +1375,11 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | |||
1399 | } | 1375 | } |
1400 | 1376 | ||
1401 | i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; | 1377 | i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; |
1402 | q_coffd = q_pwr >> 7; | 1378 | |
1379 | if (ah->ah_version == AR5K_AR5211) | ||
1380 | q_coffd = q_pwr >> 6; | ||
1381 | else | ||
1382 | q_coffd = q_pwr >> 7; | ||
1403 | 1383 | ||
1404 | /* protect against divide by 0 and loss of sign bits */ | 1384 | /* protect against divide by 0 and loss of sign bits */ |
1405 | if (i_coffd == 0 || q_coffd < 2) | 1385 | if (i_coffd == 0 || q_coffd < 2) |
@@ -1768,7 +1748,7 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | |||
1768 | * Antenna control * | 1748 | * Antenna control * |
1769 | \*****************/ | 1749 | \*****************/ |
1770 | 1750 | ||
1771 | void /*TODO:Boundary check*/ | 1751 | static void /*TODO:Boundary check*/ |
1772 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) | 1752 | ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) |
1773 | { | 1753 | { |
1774 | ATH5K_TRACE(ah->ah_sc); | 1754 | ATH5K_TRACE(ah->ah_sc); |
@@ -1777,16 +1757,6 @@ ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) | |||
1777 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); | 1757 | ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); |
1778 | } | 1758 | } |
1779 | 1759 | ||
1780 | unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) | ||
1781 | { | ||
1782 | ATH5K_TRACE(ah->ah_sc); | ||
1783 | |||
1784 | if (ah->ah_version != AR5K_AR5210) | ||
1785 | return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7; | ||
1786 | |||
1787 | return false; /*XXX: What do we return for 5210 ?*/ | ||
1788 | } | ||
1789 | |||
1790 | /* | 1760 | /* |
1791 | * Enable/disable fast rx antenna diversity | 1761 | * Enable/disable fast rx antenna diversity |
1792 | */ | 1762 | */ |
@@ -1930,6 +1900,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1930 | 1900 | ||
1931 | ah->ah_tx_ant = tx_ant; | 1901 | ah->ah_tx_ant = tx_ant; |
1932 | ah->ah_ant_mode = ant_mode; | 1902 | ah->ah_ant_mode = ant_mode; |
1903 | ah->ah_def_ant = def_ant; | ||
1933 | 1904 | ||
1934 | sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; | 1905 | sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; |
1935 | sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; | 1906 | sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; |
@@ -2440,19 +2411,6 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, | |||
2440 | pcdac_tmp = pcdac_high_pwr; | 2411 | pcdac_tmp = pcdac_high_pwr; |
2441 | 2412 | ||
2442 | edge_flag = 0x40; | 2413 | edge_flag = 0x40; |
2443 | #if 0 | ||
2444 | /* If both min and max power limits are in lower | ||
2445 | * power curve's range, only use the low power curve. | ||
2446 | * TODO: min/max levels are related to target | ||
2447 | * power values requested from driver/user | ||
2448 | * XXX: Is this really needed ? */ | ||
2449 | if (min_pwr < table_max[1] && | ||
2450 | max_pwr < table_max[1]) { | ||
2451 | edge_flag = 0; | ||
2452 | pcdac_tmp = pcdac_low_pwr; | ||
2453 | max_pwr_idx = (table_max[1] - table_min[1])/2; | ||
2454 | } | ||
2455 | #endif | ||
2456 | } else { | 2414 | } else { |
2457 | pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */ | 2415 | pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */ |
2458 | pcdac_high_pwr = ah->ah_txpower.tmpL[0]; | 2416 | pcdac_high_pwr = ah->ah_txpower.tmpL[0]; |
@@ -3143,5 +3101,3 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | |||
3143 | 3101 | ||
3144 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); | 3102 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); |
3145 | } | 3103 | } |
3146 | |||
3147 | #undef _ATH5K_PHY | ||
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 9122a8556f45..f5831da33f7b 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -517,23 +517,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
517 | } | 517 | } |
518 | 518 | ||
519 | /* | 519 | /* |
520 | * Get slot time from DCU | ||
521 | */ | ||
522 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | ||
523 | { | ||
524 | unsigned int slot_time_clock; | ||
525 | |||
526 | ATH5K_TRACE(ah->ah_sc); | ||
527 | |||
528 | if (ah->ah_version == AR5K_AR5210) | ||
529 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME); | ||
530 | else | ||
531 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT); | ||
532 | |||
533 | return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff); | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Set slot time on DCU | 520 | * Set slot time on DCU |
538 | */ | 521 | */ |
539 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | 522 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 1464f89b249c..45d62e915e4c 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -212,10 +212,10 @@ | |||
212 | * MIB control register | 212 | * MIB control register |
213 | */ | 213 | */ |
214 | #define AR5K_MIBC 0x0040 /* Register Address */ | 214 | #define AR5K_MIBC 0x0040 /* Register Address */ |
215 | #define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */ | 215 | #define AR5K_MIBC_COW 0x00000001 /* Counter Overflow Warning */ |
216 | #define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ | 216 | #define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ |
217 | #define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */ | 217 | #define AR5K_MIBC_CMC 0x00000004 /* Clear MIB Counters */ |
218 | #define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */ | 218 | #define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe, increment all */ |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * Timeout prescale register | 221 | * Timeout prescale register |
@@ -1516,7 +1516,14 @@ | |||
1516 | AR5K_NAV_5210 : AR5K_NAV_5211) | 1516 | AR5K_NAV_5210 : AR5K_NAV_5211) |
1517 | 1517 | ||
1518 | /* | 1518 | /* |
1519 | * RTS success register | 1519 | * MIB counters: |
1520 | * | ||
1521 | * max value is 0xc000, if this is reached we get a MIB interrupt. | ||
1522 | * they can be controlled via AR5K_MIBC and are cleared on read. | ||
1523 | */ | ||
1524 | |||
1525 | /* | ||
1526 | * RTS success (MIB counter) | ||
1520 | */ | 1527 | */ |
1521 | #define AR5K_RTS_OK_5210 0x8090 | 1528 | #define AR5K_RTS_OK_5210 0x8090 |
1522 | #define AR5K_RTS_OK_5211 0x8088 | 1529 | #define AR5K_RTS_OK_5211 0x8088 |
@@ -1524,7 +1531,7 @@ | |||
1524 | AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) | 1531 | AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) |
1525 | 1532 | ||
1526 | /* | 1533 | /* |
1527 | * RTS failure register | 1534 | * RTS failure (MIB counter) |
1528 | */ | 1535 | */ |
1529 | #define AR5K_RTS_FAIL_5210 0x8094 | 1536 | #define AR5K_RTS_FAIL_5210 0x8094 |
1530 | #define AR5K_RTS_FAIL_5211 0x808c | 1537 | #define AR5K_RTS_FAIL_5211 0x808c |
@@ -1532,7 +1539,7 @@ | |||
1532 | AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) | 1539 | AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) |
1533 | 1540 | ||
1534 | /* | 1541 | /* |
1535 | * ACK failure register | 1542 | * ACK failure (MIB counter) |
1536 | */ | 1543 | */ |
1537 | #define AR5K_ACK_FAIL_5210 0x8098 | 1544 | #define AR5K_ACK_FAIL_5210 0x8098 |
1538 | #define AR5K_ACK_FAIL_5211 0x8090 | 1545 | #define AR5K_ACK_FAIL_5211 0x8090 |
@@ -1540,7 +1547,7 @@ | |||
1540 | AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) | 1547 | AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) |
1541 | 1548 | ||
1542 | /* | 1549 | /* |
1543 | * FCS failure register | 1550 | * FCS failure (MIB counter) |
1544 | */ | 1551 | */ |
1545 | #define AR5K_FCS_FAIL_5210 0x809c | 1552 | #define AR5K_FCS_FAIL_5210 0x809c |
1546 | #define AR5K_FCS_FAIL_5211 0x8094 | 1553 | #define AR5K_FCS_FAIL_5211 0x8094 |
@@ -1667,11 +1674,17 @@ | |||
1667 | 1674 | ||
1668 | /* | 1675 | /* |
1669 | * Profile count registers | 1676 | * Profile count registers |
1677 | * | ||
1678 | * These registers can be cleared and freezed with ATH5K_MIBC, but they do not | ||
1679 | * generate a MIB interrupt. | ||
1680 | * Instead of overflowing, they shift by one bit to the right. All registers | ||
1681 | * shift together, i.e. when one reaches the max, all shift at the same time by | ||
1682 | * one bit to the right. This way we should always get consistent values. | ||
1670 | */ | 1683 | */ |
1671 | #define AR5K_PROFCNT_TX 0x80ec /* Tx count */ | 1684 | #define AR5K_PROFCNT_TX 0x80ec /* Tx count */ |
1672 | #define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ | 1685 | #define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ |
1673 | #define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */ | 1686 | #define AR5K_PROFCNT_RXCLR 0x80f4 /* Busy count */ |
1674 | #define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */ | 1687 | #define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle counter */ |
1675 | 1688 | ||
1676 | /* | 1689 | /* |
1677 | * Quiet period control registers | 1690 | * Quiet period control registers |
@@ -1758,7 +1771,7 @@ | |||
1758 | #define AR5K_CCK_FIL_CNT 0x8128 | 1771 | #define AR5K_CCK_FIL_CNT 0x8128 |
1759 | 1772 | ||
1760 | /* | 1773 | /* |
1761 | * PHY Error Counters (?) | 1774 | * PHY Error Counters (same masks as AR5K_PHY_ERR_FIL) |
1762 | */ | 1775 | */ |
1763 | #define AR5K_PHYERR_CNT1 0x812c | 1776 | #define AR5K_PHYERR_CNT1 0x812c |
1764 | #define AR5K_PHYERR_CNT1_MASK 0x8130 | 1777 | #define AR5K_PHYERR_CNT1_MASK 0x8130 |
@@ -1766,6 +1779,9 @@ | |||
1766 | #define AR5K_PHYERR_CNT2 0x8134 | 1779 | #define AR5K_PHYERR_CNT2 0x8134 |
1767 | #define AR5K_PHYERR_CNT2_MASK 0x8138 | 1780 | #define AR5K_PHYERR_CNT2_MASK 0x8138 |
1768 | 1781 | ||
1782 | /* if the PHY Error Counters reach this maximum, we get MIB interrupts */ | ||
1783 | #define ATH5K_PHYERR_CNT_MAX 0x00c00000 | ||
1784 | |||
1769 | /* | 1785 | /* |
1770 | * TSF Threshold register (?) | 1786 | * TSF Threshold register (?) |
1771 | */ | 1787 | */ |
@@ -1974,7 +1990,7 @@ | |||
1974 | #define AR5K_PHY_SETTLING 0x9844 /* Register Address */ | 1990 | #define AR5K_PHY_SETTLING 0x9844 /* Register Address */ |
1975 | #define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ | 1991 | #define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ |
1976 | #define AR5K_PHY_SETTLING_AGC_S 0 | 1992 | #define AR5K_PHY_SETTLING_AGC_S 0 |
1977 | #define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */ | 1993 | #define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settling time */ |
1978 | #define AR5K_PHY_SETTLING_SWITCH_S 7 | 1994 | #define AR5K_PHY_SETTLING_SWITCH_S 7 |
1979 | 1995 | ||
1980 | /* | 1996 | /* |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index cbf28e379843..44bbbf2a6edd 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -19,8 +19,6 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define _ATH5K_RESET | ||
23 | |||
24 | /*****************************\ | 22 | /*****************************\ |
25 | Reset functions and helpers | 23 | Reset functions and helpers |
26 | \*****************************/ | 24 | \*****************************/ |
@@ -34,6 +32,27 @@ | |||
34 | #include "base.h" | 32 | #include "base.h" |
35 | #include "debug.h" | 33 | #include "debug.h" |
36 | 34 | ||
35 | /* | ||
36 | * Check if a register write has been completed | ||
37 | */ | ||
38 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | ||
39 | bool is_set) | ||
40 | { | ||
41 | int i; | ||
42 | u32 data; | ||
43 | |||
44 | for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { | ||
45 | data = ath5k_hw_reg_read(ah, reg); | ||
46 | if (is_set && (data & flag)) | ||
47 | break; | ||
48 | else if ((data & flag) == val) | ||
49 | break; | ||
50 | udelay(15); | ||
51 | } | ||
52 | |||
53 | return (i <= 0) ? -EAGAIN : 0; | ||
54 | } | ||
55 | |||
37 | /** | 56 | /** |
38 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | 57 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 |
39 | * | 58 | * |
@@ -221,8 +240,8 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |||
221 | /* | 240 | /* |
222 | * Sleep control | 241 | * Sleep control |
223 | */ | 242 | */ |
224 | int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | 243 | static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, |
225 | bool set_chip, u16 sleep_duration) | 244 | bool set_chip, u16 sleep_duration) |
226 | { | 245 | { |
227 | unsigned int i; | 246 | unsigned int i; |
228 | u32 staid, data; | 247 | u32 staid, data; |
@@ -1017,11 +1036,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1017 | if (ret) | 1036 | if (ret) |
1018 | return ret; | 1037 | return ret; |
1019 | 1038 | ||
1020 | /* | ||
1021 | * Initialize operating mode | ||
1022 | */ | ||
1023 | ah->ah_op_mode = op_mode; | ||
1024 | |||
1025 | /* PHY access enable */ | 1039 | /* PHY access enable */ |
1026 | if (ah->ah_mac_srev >= AR5K_SREV_AR5211) | 1040 | if (ah->ah_mac_srev >= AR5K_SREV_AR5211) |
1027 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | 1041 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); |
@@ -1192,7 +1206,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1192 | ath5k_hw_set_associd(ah); | 1206 | ath5k_hw_set_associd(ah); |
1193 | 1207 | ||
1194 | /* Set PCU config */ | 1208 | /* Set PCU config */ |
1195 | ath5k_hw_set_opmode(ah); | 1209 | ath5k_hw_set_opmode(ah, op_mode); |
1196 | 1210 | ||
1197 | /* Clear any pending interrupts | 1211 | /* Clear any pending interrupts |
1198 | * PISR/SISR Not available on 5210 */ | 1212 | * PISR/SISR Not available on 5210 */ |
@@ -1378,7 +1392,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1378 | * external 32KHz crystal when sleeping if one | 1392 | * external 32KHz crystal when sleeping if one |
1379 | * exists */ | 1393 | * exists */ |
1380 | if (ah->ah_version == AR5K_AR5212 && | 1394 | if (ah->ah_version == AR5K_AR5212 && |
1381 | ah->ah_op_mode != NL80211_IFTYPE_AP) | 1395 | op_mode != NL80211_IFTYPE_AP) |
1382 | ath5k_hw_set_sleep_clock(ah, true); | 1396 | ath5k_hw_set_sleep_clock(ah, true); |
1383 | 1397 | ||
1384 | /* | 1398 | /* |
@@ -1388,5 +1402,3 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1388 | ath5k_hw_reset_tsf(ah); | 1402 | ath5k_hw_reset_tsf(ah); |
1389 | return 0; | 1403 | return 0; |
1390 | } | 1404 | } |
1391 | |||
1392 | #undef _ATH5K_RESET | ||