diff options
Diffstat (limited to 'drivers/net/wireless/ath/carl9170')
22 files changed, 13040 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig new file mode 100644 index 000000000000..2d1b821b440d --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/Kconfig | |||
@@ -0,0 +1,41 @@ | |||
1 | config CARL9170 | ||
2 | tristate "Linux Community AR9170 802.11n USB support" | ||
3 | depends on USB && MAC80211 && EXPERIMENTAL | ||
4 | select FW_LOADER | ||
5 | select CRC32 | ||
6 | help | ||
7 | This is another driver for the Atheros "otus" 802.11n USB devices. | ||
8 | |||
9 | This driver provides more features than the original, | ||
10 | but it needs a special firmware (carl9170-1.fw) to do that. | ||
11 | |||
12 | The firmware can be downloaded from our wiki here: | ||
13 | <http://wireless.kernel.org/en/users/Drivers/carl9170> | ||
14 | |||
15 | If you choose to build a module, it'll be called carl9170. | ||
16 | |||
17 | config CARL9170_LEDS | ||
18 | bool "SoftLED Support" | ||
19 | depends on CARL9170 | ||
20 | select MAC80211_LEDS | ||
21 | select LEDS_CLASS | ||
22 | select NEW_LEDS | ||
23 | default y | ||
24 | help | ||
25 | This option is necessary, if you want your device' LEDs to blink | ||
26 | |||
27 | Say Y, unless you need the LEDs for firmware debugging. | ||
28 | |||
29 | config CARL9170_DEBUGFS | ||
30 | bool "DebugFS Support" | ||
31 | depends on CARL9170 && DEBUG_FS && MAC80211_DEBUGFS | ||
32 | default n | ||
33 | help | ||
34 | Export several driver and device internals to user space. | ||
35 | |||
36 | Say N. | ||
37 | |||
38 | config CARL9170_WPC | ||
39 | bool | ||
40 | depends on CARL9170 && (INPUT = y || INPUT = CARL9170) | ||
41 | default y | ||
diff --git a/drivers/net/wireless/ath/carl9170/Makefile b/drivers/net/wireless/ath/carl9170/Makefile new file mode 100644 index 000000000000..f64ed76af8ad --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | carl9170-objs := main.o usb.o cmd.o mac.o phy.o led.o fw.o tx.o rx.o | ||
2 | carl9170-$(CONFIG_CARL9170_DEBUGFS) += debug.o | ||
3 | |||
4 | obj-$(CONFIG_CARL9170) += carl9170.o | ||
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h new file mode 100644 index 000000000000..4da01a9f5680 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/carl9170.h | |||
@@ -0,0 +1,637 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * Driver specific definitions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | #ifndef __CARL9170_H | ||
40 | #define __CARL9170_H | ||
41 | |||
42 | #include <linux/kernel.h> | ||
43 | #include <linux/firmware.h> | ||
44 | #include <linux/completion.h> | ||
45 | #include <linux/spinlock.h> | ||
46 | #include <net/cfg80211.h> | ||
47 | #include <net/mac80211.h> | ||
48 | #include <linux/usb.h> | ||
49 | #ifdef CONFIG_CARL9170_LEDS | ||
50 | #include <linux/leds.h> | ||
51 | #endif /* CONFIG_CARL9170_LEDS */ | ||
52 | #ifdef CONFIG_CARL9170_WPC | ||
53 | #include <linux/input.h> | ||
54 | #endif /* CONFIG_CARL9170_WPC */ | ||
55 | #include "eeprom.h" | ||
56 | #include "wlan.h" | ||
57 | #include "hw.h" | ||
58 | #include "fwdesc.h" | ||
59 | #include "fwcmd.h" | ||
60 | #include "../regd.h" | ||
61 | |||
62 | #ifdef CONFIG_CARL9170_DEBUGFS | ||
63 | #include "debug.h" | ||
64 | #endif /* CONFIG_CARL9170_DEBUGFS */ | ||
65 | |||
66 | #define CARL9170FW_NAME "carl9170-1.fw" | ||
67 | |||
68 | #define PAYLOAD_MAX (CARL9170_MAX_CMD_LEN / 4 - 1) | ||
69 | |||
70 | enum carl9170_rf_init_mode { | ||
71 | CARL9170_RFI_NONE, | ||
72 | CARL9170_RFI_WARM, | ||
73 | CARL9170_RFI_COLD, | ||
74 | }; | ||
75 | |||
76 | #define CARL9170_MAX_RX_BUFFER_SIZE 8192 | ||
77 | |||
78 | enum carl9170_device_state { | ||
79 | CARL9170_UNKNOWN_STATE, | ||
80 | CARL9170_STOPPED, | ||
81 | CARL9170_IDLE, | ||
82 | CARL9170_STARTED, | ||
83 | }; | ||
84 | |||
85 | #define CARL9170_NUM_TID 16 | ||
86 | #define WME_BA_BMP_SIZE 64 | ||
87 | #define CARL9170_TX_USER_RATE_TRIES 3 | ||
88 | |||
89 | #define WME_AC_BE 2 | ||
90 | #define WME_AC_BK 3 | ||
91 | #define WME_AC_VI 1 | ||
92 | #define WME_AC_VO 0 | ||
93 | |||
94 | #define TID_TO_WME_AC(_tid) \ | ||
95 | ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ | ||
96 | (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ | ||
97 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ | ||
98 | WME_AC_VO) | ||
99 | |||
100 | #define SEQ_DIFF(_start, _seq) \ | ||
101 | (((_start) - (_seq)) & 0x0fff) | ||
102 | #define SEQ_PREV(_seq) \ | ||
103 | (((_seq) - 1) & 0x0fff) | ||
104 | #define SEQ_NEXT(_seq) \ | ||
105 | (((_seq) + 1) & 0x0fff) | ||
106 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ | ||
107 | ((((_seqno) - (_start)) & 0xfff) < (_bawsz)) | ||
108 | |||
109 | enum carl9170_tid_state { | ||
110 | CARL9170_TID_STATE_INVALID, | ||
111 | CARL9170_TID_STATE_KILLED, | ||
112 | CARL9170_TID_STATE_SHUTDOWN, | ||
113 | CARL9170_TID_STATE_SUSPEND, | ||
114 | CARL9170_TID_STATE_PROGRESS, | ||
115 | CARL9170_TID_STATE_IDLE, | ||
116 | CARL9170_TID_STATE_XMIT, | ||
117 | }; | ||
118 | |||
119 | #define CARL9170_BAW_BITS (2 * WME_BA_BMP_SIZE) | ||
120 | #define CARL9170_BAW_SIZE (BITS_TO_LONGS(CARL9170_BAW_BITS)) | ||
121 | #define CARL9170_BAW_LEN (DIV_ROUND_UP(CARL9170_BAW_BITS, BITS_PER_BYTE)) | ||
122 | |||
123 | struct carl9170_sta_tid { | ||
124 | /* must be the first entry! */ | ||
125 | struct list_head list; | ||
126 | |||
127 | /* temporary list for RCU unlink procedure */ | ||
128 | struct list_head tmp_list; | ||
129 | |||
130 | /* lock for the following data structures */ | ||
131 | spinlock_t lock; | ||
132 | |||
133 | unsigned int counter; | ||
134 | enum carl9170_tid_state state; | ||
135 | u8 tid; /* TID number ( 0 - 15 ) */ | ||
136 | u16 max; /* max. AMPDU size */ | ||
137 | |||
138 | u16 snx; /* awaiting _next_ frame */ | ||
139 | u16 hsn; /* highest _queued_ sequence */ | ||
140 | u16 bsn; /* base of the tx/agg bitmap */ | ||
141 | unsigned long bitmap[CARL9170_BAW_SIZE]; | ||
142 | |||
143 | /* Preaggregation reorder queue */ | ||
144 | struct sk_buff_head queue; | ||
145 | }; | ||
146 | |||
147 | #define CARL9170_QUEUE_TIMEOUT 256 | ||
148 | #define CARL9170_BUMP_QUEUE 1000 | ||
149 | #define CARL9170_TX_TIMEOUT 2500 | ||
150 | #define CARL9170_JANITOR_DELAY 128 | ||
151 | #define CARL9170_QUEUE_STUCK_TIMEOUT 5500 | ||
152 | |||
153 | #define CARL9170_NUM_TX_AGG_MAX 30 | ||
154 | |||
155 | /* | ||
156 | * Tradeoff between stability/latency and speed. | ||
157 | * | ||
158 | * AR9170_TXQ_DEPTH is devised by dividing the amount of available | ||
159 | * tx buffers with the size of a full ethernet frame + overhead. | ||
160 | * | ||
161 | * Naturally: The higher the limit, the faster the device CAN send. | ||
162 | * However, even a slight over-commitment at the wrong time and the | ||
163 | * hardware is doomed to send all already-queued frames at suboptimal | ||
164 | * rates. This in turn leads to an enormous amount of unsuccessful | ||
165 | * retries => Latency goes up, whereas the throughput goes down. CRASH! | ||
166 | */ | ||
167 | #define CARL9170_NUM_TX_LIMIT_HARD ((AR9170_TXQ_DEPTH * 3) / 2) | ||
168 | #define CARL9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH) | ||
169 | |||
170 | struct carl9170_tx_queue_stats { | ||
171 | unsigned int count; | ||
172 | unsigned int limit; | ||
173 | unsigned int len; | ||
174 | }; | ||
175 | |||
176 | struct carl9170_vif { | ||
177 | unsigned int id; | ||
178 | struct ieee80211_vif *vif; | ||
179 | }; | ||
180 | |||
181 | struct carl9170_vif_info { | ||
182 | struct list_head list; | ||
183 | bool active; | ||
184 | unsigned int id; | ||
185 | struct sk_buff *beacon; | ||
186 | bool enable_beacon; | ||
187 | }; | ||
188 | |||
189 | #define AR9170_NUM_RX_URBS 16 | ||
190 | #define AR9170_NUM_RX_URBS_MUL 2 | ||
191 | #define AR9170_NUM_TX_URBS 8 | ||
192 | #define AR9170_NUM_RX_URBS_POOL (AR9170_NUM_RX_URBS_MUL * AR9170_NUM_RX_URBS) | ||
193 | |||
194 | enum carl9170_device_features { | ||
195 | CARL9170_WPS_BUTTON = BIT(0), | ||
196 | CARL9170_ONE_LED = BIT(1), | ||
197 | }; | ||
198 | |||
199 | #ifdef CONFIG_CARL9170_LEDS | ||
200 | struct ar9170; | ||
201 | |||
202 | struct carl9170_led { | ||
203 | struct ar9170 *ar; | ||
204 | struct led_classdev l; | ||
205 | char name[32]; | ||
206 | unsigned int toggled; | ||
207 | bool last_state; | ||
208 | bool registered; | ||
209 | }; | ||
210 | #endif /* CONFIG_CARL9170_LEDS */ | ||
211 | |||
212 | enum carl9170_restart_reasons { | ||
213 | CARL9170_RR_NO_REASON = 0, | ||
214 | CARL9170_RR_FATAL_FIRMWARE_ERROR, | ||
215 | CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS, | ||
216 | CARL9170_RR_WATCHDOG, | ||
217 | CARL9170_RR_STUCK_TX, | ||
218 | CARL9170_RR_UNRESPONSIVE_DEVICE, | ||
219 | CARL9170_RR_COMMAND_TIMEOUT, | ||
220 | CARL9170_RR_TOO_MANY_PHY_ERRORS, | ||
221 | CARL9170_RR_LOST_RSP, | ||
222 | CARL9170_RR_INVALID_RSP, | ||
223 | CARL9170_RR_USER_REQUEST, | ||
224 | |||
225 | __CARL9170_RR_LAST, | ||
226 | }; | ||
227 | |||
228 | enum carl9170_erp_modes { | ||
229 | CARL9170_ERP_INVALID, | ||
230 | CARL9170_ERP_AUTO, | ||
231 | CARL9170_ERP_MAC80211, | ||
232 | CARL9170_ERP_OFF, | ||
233 | CARL9170_ERP_CTS, | ||
234 | CARL9170_ERP_RTS, | ||
235 | __CARL9170_ERP_NUM, | ||
236 | }; | ||
237 | |||
238 | struct ar9170 { | ||
239 | struct ath_common common; | ||
240 | struct ieee80211_hw *hw; | ||
241 | struct mutex mutex; | ||
242 | enum carl9170_device_state state; | ||
243 | spinlock_t state_lock; | ||
244 | enum carl9170_restart_reasons last_reason; | ||
245 | bool registered; | ||
246 | |||
247 | /* USB */ | ||
248 | struct usb_device *udev; | ||
249 | struct usb_interface *intf; | ||
250 | struct usb_anchor rx_anch; | ||
251 | struct usb_anchor rx_work; | ||
252 | struct usb_anchor rx_pool; | ||
253 | struct usb_anchor tx_wait; | ||
254 | struct usb_anchor tx_anch; | ||
255 | struct usb_anchor tx_cmd; | ||
256 | struct usb_anchor tx_err; | ||
257 | struct tasklet_struct usb_tasklet; | ||
258 | atomic_t tx_cmd_urbs; | ||
259 | atomic_t tx_anch_urbs; | ||
260 | atomic_t rx_anch_urbs; | ||
261 | atomic_t rx_work_urbs; | ||
262 | atomic_t rx_pool_urbs; | ||
263 | kernel_ulong_t features; | ||
264 | |||
265 | /* firmware settings */ | ||
266 | struct completion fw_load_wait; | ||
267 | struct completion fw_boot_wait; | ||
268 | struct { | ||
269 | const struct carl9170fw_desc_head *desc; | ||
270 | const struct firmware *fw; | ||
271 | unsigned int offset; | ||
272 | unsigned int address; | ||
273 | unsigned int cmd_bufs; | ||
274 | unsigned int api_version; | ||
275 | unsigned int vif_num; | ||
276 | unsigned int err_counter; | ||
277 | unsigned int bug_counter; | ||
278 | u32 beacon_addr; | ||
279 | unsigned int beacon_max_len; | ||
280 | bool rx_stream; | ||
281 | bool tx_stream; | ||
282 | bool rx_filter; | ||
283 | unsigned int mem_blocks; | ||
284 | unsigned int mem_block_size; | ||
285 | unsigned int rx_size; | ||
286 | unsigned int tx_seq_table; | ||
287 | } fw; | ||
288 | |||
289 | /* interface configuration combinations */ | ||
290 | struct ieee80211_iface_limit if_comb_limits[1]; | ||
291 | struct ieee80211_iface_combination if_combs[1]; | ||
292 | |||
293 | /* reset / stuck frames/queue detection */ | ||
294 | struct work_struct restart_work; | ||
295 | struct work_struct ping_work; | ||
296 | unsigned int restart_counter; | ||
297 | unsigned long queue_stop_timeout[__AR9170_NUM_TXQ]; | ||
298 | unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ]; | ||
299 | bool needs_full_reset; | ||
300 | atomic_t pending_restarts; | ||
301 | |||
302 | /* interface mode settings */ | ||
303 | struct list_head vif_list; | ||
304 | unsigned long vif_bitmap; | ||
305 | unsigned int vifs; | ||
306 | struct carl9170_vif vif_priv[AR9170_MAX_VIRTUAL_MAC]; | ||
307 | |||
308 | /* beaconing */ | ||
309 | spinlock_t beacon_lock; | ||
310 | unsigned int global_pretbtt; | ||
311 | unsigned int global_beacon_int; | ||
312 | struct carl9170_vif_info *beacon_iter; | ||
313 | unsigned int beacon_enabled; | ||
314 | |||
315 | /* cryptographic engine */ | ||
316 | u64 usedkeys; | ||
317 | bool rx_software_decryption; | ||
318 | bool disable_offload; | ||
319 | |||
320 | /* filter settings */ | ||
321 | u64 cur_mc_hash; | ||
322 | u32 cur_filter; | ||
323 | unsigned int filter_state; | ||
324 | unsigned int rx_filter_caps; | ||
325 | bool sniffer_enabled; | ||
326 | |||
327 | /* MAC */ | ||
328 | enum carl9170_erp_modes erp_mode; | ||
329 | |||
330 | /* PHY */ | ||
331 | struct ieee80211_channel *channel; | ||
332 | int noise[4]; | ||
333 | unsigned int chan_fail; | ||
334 | unsigned int total_chan_fail; | ||
335 | u8 heavy_clip; | ||
336 | u8 ht_settings; | ||
337 | |||
338 | /* power calibration data */ | ||
339 | u8 power_5G_leg[4]; | ||
340 | u8 power_2G_cck[4]; | ||
341 | u8 power_2G_ofdm[4]; | ||
342 | u8 power_5G_ht20[8]; | ||
343 | u8 power_5G_ht40[8]; | ||
344 | u8 power_2G_ht20[8]; | ||
345 | u8 power_2G_ht40[8]; | ||
346 | |||
347 | #ifdef CONFIG_CARL9170_LEDS | ||
348 | /* LED */ | ||
349 | struct delayed_work led_work; | ||
350 | struct carl9170_led leds[AR9170_NUM_LEDS]; | ||
351 | #endif /* CONFIG_CARL9170_LEDS */ | ||
352 | |||
353 | /* qos queue settings */ | ||
354 | spinlock_t tx_stats_lock; | ||
355 | struct carl9170_tx_queue_stats tx_stats[__AR9170_NUM_TXQ]; | ||
356 | struct ieee80211_tx_queue_params edcf[5]; | ||
357 | struct completion tx_flush; | ||
358 | |||
359 | /* CMD */ | ||
360 | int cmd_seq; | ||
361 | int readlen; | ||
362 | u8 *readbuf; | ||
363 | spinlock_t cmd_lock; | ||
364 | struct completion cmd_wait; | ||
365 | union { | ||
366 | __le32 cmd_buf[PAYLOAD_MAX + 1]; | ||
367 | struct carl9170_cmd cmd; | ||
368 | struct carl9170_rsp rsp; | ||
369 | }; | ||
370 | |||
371 | /* statistics */ | ||
372 | unsigned int tx_dropped; | ||
373 | unsigned int tx_ack_failures; | ||
374 | unsigned int tx_fcs_errors; | ||
375 | unsigned int rx_dropped; | ||
376 | |||
377 | /* EEPROM */ | ||
378 | struct ar9170_eeprom eeprom; | ||
379 | |||
380 | /* tx queuing */ | ||
381 | struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; | ||
382 | struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; | ||
383 | struct delayed_work tx_janitor; | ||
384 | unsigned long tx_janitor_last_run; | ||
385 | bool tx_schedule; | ||
386 | |||
387 | /* tx ampdu */ | ||
388 | struct work_struct ampdu_work; | ||
389 | spinlock_t tx_ampdu_list_lock; | ||
390 | struct carl9170_sta_tid *tx_ampdu_iter; | ||
391 | struct list_head tx_ampdu_list; | ||
392 | atomic_t tx_ampdu_upload; | ||
393 | atomic_t tx_ampdu_scheduler; | ||
394 | atomic_t tx_total_pending; | ||
395 | atomic_t tx_total_queued; | ||
396 | unsigned int tx_ampdu_list_len; | ||
397 | int current_density; | ||
398 | int current_factor; | ||
399 | bool tx_ampdu_schedule; | ||
400 | |||
401 | /* internal memory management */ | ||
402 | spinlock_t mem_lock; | ||
403 | unsigned long *mem_bitmap; | ||
404 | atomic_t mem_free_blocks; | ||
405 | atomic_t mem_allocs; | ||
406 | |||
407 | /* rxstream mpdu merge */ | ||
408 | struct ar9170_rx_head rx_plcp; | ||
409 | bool rx_has_plcp; | ||
410 | struct sk_buff *rx_failover; | ||
411 | int rx_failover_missing; | ||
412 | |||
413 | #ifdef CONFIG_CARL9170_WPC | ||
414 | struct { | ||
415 | bool pbc_state; | ||
416 | struct input_dev *pbc; | ||
417 | char name[32]; | ||
418 | char phys[32]; | ||
419 | } wps; | ||
420 | #endif /* CONFIG_CARL9170_WPC */ | ||
421 | |||
422 | #ifdef CONFIG_CARL9170_DEBUGFS | ||
423 | struct carl9170_debug debug; | ||
424 | struct dentry *debug_dir; | ||
425 | #endif /* CONFIG_CARL9170_DEBUGFS */ | ||
426 | |||
427 | /* PSM */ | ||
428 | struct work_struct ps_work; | ||
429 | struct { | ||
430 | unsigned int dtim_counter; | ||
431 | unsigned long last_beacon; | ||
432 | unsigned long last_action; | ||
433 | unsigned long last_slept; | ||
434 | unsigned int sleep_ms; | ||
435 | unsigned int off_override; | ||
436 | bool state; | ||
437 | } ps; | ||
438 | }; | ||
439 | |||
440 | enum carl9170_ps_off_override_reasons { | ||
441 | PS_OFF_VIF = BIT(0), | ||
442 | PS_OFF_BCN = BIT(1), | ||
443 | PS_OFF_5GHZ = BIT(2), | ||
444 | }; | ||
445 | |||
446 | struct carl9170_ba_stats { | ||
447 | u8 ampdu_len; | ||
448 | u8 ampdu_ack_len; | ||
449 | bool clear; | ||
450 | bool req; | ||
451 | }; | ||
452 | |||
453 | struct carl9170_sta_info { | ||
454 | bool ht_sta; | ||
455 | bool sleeping; | ||
456 | atomic_t pending_frames; | ||
457 | unsigned int ampdu_max_len; | ||
458 | struct carl9170_sta_tid *agg[CARL9170_NUM_TID]; | ||
459 | struct carl9170_ba_stats stats[CARL9170_NUM_TID]; | ||
460 | }; | ||
461 | |||
462 | struct carl9170_tx_info { | ||
463 | unsigned long timeout; | ||
464 | struct ar9170 *ar; | ||
465 | struct kref ref; | ||
466 | }; | ||
467 | |||
468 | #define CHK_DEV_STATE(a, s) (((struct ar9170 *)a)->state >= (s)) | ||
469 | #define IS_INITIALIZED(a) (CHK_DEV_STATE(a, CARL9170_STOPPED)) | ||
470 | #define IS_ACCEPTING_CMD(a) (CHK_DEV_STATE(a, CARL9170_IDLE)) | ||
471 | #define IS_STARTED(a) (CHK_DEV_STATE(a, CARL9170_STARTED)) | ||
472 | |||
473 | static inline void __carl9170_set_state(struct ar9170 *ar, | ||
474 | enum carl9170_device_state newstate) | ||
475 | { | ||
476 | ar->state = newstate; | ||
477 | } | ||
478 | |||
479 | static inline void carl9170_set_state(struct ar9170 *ar, | ||
480 | enum carl9170_device_state newstate) | ||
481 | { | ||
482 | unsigned long flags; | ||
483 | |||
484 | spin_lock_irqsave(&ar->state_lock, flags); | ||
485 | __carl9170_set_state(ar, newstate); | ||
486 | spin_unlock_irqrestore(&ar->state_lock, flags); | ||
487 | } | ||
488 | |||
489 | static inline void carl9170_set_state_when(struct ar9170 *ar, | ||
490 | enum carl9170_device_state min, enum carl9170_device_state newstate) | ||
491 | { | ||
492 | unsigned long flags; | ||
493 | |||
494 | spin_lock_irqsave(&ar->state_lock, flags); | ||
495 | if (CHK_DEV_STATE(ar, min)) | ||
496 | __carl9170_set_state(ar, newstate); | ||
497 | spin_unlock_irqrestore(&ar->state_lock, flags); | ||
498 | } | ||
499 | |||
500 | /* exported interface */ | ||
501 | void *carl9170_alloc(size_t priv_size); | ||
502 | int carl9170_register(struct ar9170 *ar); | ||
503 | void carl9170_unregister(struct ar9170 *ar); | ||
504 | void carl9170_free(struct ar9170 *ar); | ||
505 | void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r); | ||
506 | void carl9170_ps_check(struct ar9170 *ar); | ||
507 | |||
508 | /* USB back-end */ | ||
509 | int carl9170_usb_open(struct ar9170 *ar); | ||
510 | void carl9170_usb_stop(struct ar9170 *ar); | ||
511 | void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb); | ||
512 | void carl9170_usb_handle_tx_err(struct ar9170 *ar); | ||
513 | int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids, | ||
514 | u32 plen, void *payload, u32 rlen, void *resp); | ||
515 | int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd, | ||
516 | const bool free_buf); | ||
517 | int carl9170_usb_restart(struct ar9170 *ar); | ||
518 | void carl9170_usb_reset(struct ar9170 *ar); | ||
519 | |||
520 | /* MAC */ | ||
521 | int carl9170_init_mac(struct ar9170 *ar); | ||
522 | int carl9170_set_qos(struct ar9170 *ar); | ||
523 | int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); | ||
524 | int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id, | ||
525 | const u8 *mac); | ||
526 | int carl9170_set_operating_mode(struct ar9170 *ar); | ||
527 | int carl9170_set_beacon_timers(struct ar9170 *ar); | ||
528 | int carl9170_set_dyn_sifs_ack(struct ar9170 *ar); | ||
529 | int carl9170_set_rts_cts_rate(struct ar9170 *ar); | ||
530 | int carl9170_set_ampdu_settings(struct ar9170 *ar); | ||
531 | int carl9170_set_slot_time(struct ar9170 *ar); | ||
532 | int carl9170_set_mac_rates(struct ar9170 *ar); | ||
533 | int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry); | ||
534 | int carl9170_update_beacon(struct ar9170 *ar, const bool submit); | ||
535 | int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac, | ||
536 | const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen); | ||
537 | int carl9170_disable_key(struct ar9170 *ar, const u8 id); | ||
538 | |||
539 | /* RX */ | ||
540 | void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len); | ||
541 | void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); | ||
542 | |||
543 | /* TX */ | ||
544 | void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
545 | void carl9170_tx_janitor(struct work_struct *work); | ||
546 | void carl9170_tx_process_status(struct ar9170 *ar, | ||
547 | const struct carl9170_rsp *cmd); | ||
548 | void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, | ||
549 | const bool success); | ||
550 | void carl9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb); | ||
551 | void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb); | ||
552 | void carl9170_tx_scheduler(struct ar9170 *ar); | ||
553 | void carl9170_tx_get_skb(struct sk_buff *skb); | ||
554 | int carl9170_tx_put_skb(struct sk_buff *skb); | ||
555 | |||
556 | /* LEDs */ | ||
557 | #ifdef CONFIG_CARL9170_LEDS | ||
558 | int carl9170_led_register(struct ar9170 *ar); | ||
559 | void carl9170_led_unregister(struct ar9170 *ar); | ||
560 | #endif /* CONFIG_CARL9170_LEDS */ | ||
561 | int carl9170_led_init(struct ar9170 *ar); | ||
562 | int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state); | ||
563 | |||
564 | /* PHY / RF */ | ||
565 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | ||
566 | enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi); | ||
567 | int carl9170_get_noisefloor(struct ar9170 *ar); | ||
568 | |||
569 | /* FW */ | ||
570 | int carl9170_parse_firmware(struct ar9170 *ar); | ||
571 | int carl9170_fw_fix_eeprom(struct ar9170 *ar); | ||
572 | |||
573 | extern struct ieee80211_rate __carl9170_ratetable[]; | ||
574 | extern int modparam_noht; | ||
575 | |||
576 | static inline struct ar9170 *carl9170_get_priv(struct carl9170_vif *carl_vif) | ||
577 | { | ||
578 | return container_of(carl_vif, struct ar9170, | ||
579 | vif_priv[carl_vif->id]); | ||
580 | } | ||
581 | |||
582 | static inline struct ieee80211_hdr *carl9170_get_hdr(struct sk_buff *skb) | ||
583 | { | ||
584 | return (void *)((struct _carl9170_tx_superframe *) | ||
585 | skb->data)->frame_data; | ||
586 | } | ||
587 | |||
588 | static inline u16 get_seq_h(struct ieee80211_hdr *hdr) | ||
589 | { | ||
590 | return le16_to_cpu(hdr->seq_ctrl) >> 4; | ||
591 | } | ||
592 | |||
593 | static inline u16 carl9170_get_seq(struct sk_buff *skb) | ||
594 | { | ||
595 | return get_seq_h(carl9170_get_hdr(skb)); | ||
596 | } | ||
597 | |||
598 | static inline u16 get_tid_h(struct ieee80211_hdr *hdr) | ||
599 | { | ||
600 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
601 | } | ||
602 | |||
603 | static inline u16 carl9170_get_tid(struct sk_buff *skb) | ||
604 | { | ||
605 | return get_tid_h(carl9170_get_hdr(skb)); | ||
606 | } | ||
607 | |||
608 | static inline struct ieee80211_vif * | ||
609 | carl9170_get_vif(struct carl9170_vif_info *priv) | ||
610 | { | ||
611 | return container_of((void *)priv, struct ieee80211_vif, drv_priv); | ||
612 | } | ||
613 | |||
614 | /* Protected by ar->mutex or RCU */ | ||
615 | static inline struct ieee80211_vif *carl9170_get_main_vif(struct ar9170 *ar) | ||
616 | { | ||
617 | struct carl9170_vif_info *cvif; | ||
618 | |||
619 | list_for_each_entry_rcu(cvif, &ar->vif_list, list) { | ||
620 | if (cvif->active) | ||
621 | return carl9170_get_vif(cvif); | ||
622 | } | ||
623 | |||
624 | return NULL; | ||
625 | } | ||
626 | |||
627 | static inline bool is_main_vif(struct ar9170 *ar, struct ieee80211_vif *vif) | ||
628 | { | ||
629 | bool ret; | ||
630 | |||
631 | rcu_read_lock(); | ||
632 | ret = (carl9170_get_main_vif(ar) == vif); | ||
633 | rcu_read_unlock(); | ||
634 | return ret; | ||
635 | } | ||
636 | |||
637 | #endif /* __CARL9170_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c new file mode 100644 index 000000000000..cdfc94c371b4 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/cmd.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * Basic HW register/memory/command access functions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include "carl9170.h" | ||
40 | #include "cmd.h" | ||
41 | |||
42 | int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) | ||
43 | { | ||
44 | const __le32 buf[2] = { | ||
45 | cpu_to_le32(reg), | ||
46 | cpu_to_le32(val), | ||
47 | }; | ||
48 | int err; | ||
49 | |||
50 | err = carl9170_exec_cmd(ar, CARL9170_CMD_WREG, sizeof(buf), | ||
51 | (u8 *) buf, 0, NULL); | ||
52 | if (err) { | ||
53 | if (net_ratelimit()) { | ||
54 | wiphy_err(ar->hw->wiphy, "writing reg %#x " | ||
55 | "(val %#x) failed (%d)\n", reg, val, err); | ||
56 | } | ||
57 | } | ||
58 | return err; | ||
59 | } | ||
60 | |||
61 | int carl9170_read_mreg(struct ar9170 *ar, const int nregs, | ||
62 | const u32 *regs, u32 *out) | ||
63 | { | ||
64 | int i, err; | ||
65 | __le32 *offs, *res; | ||
66 | |||
67 | /* abuse "out" for the register offsets, must be same length */ | ||
68 | offs = (__le32 *)out; | ||
69 | for (i = 0; i < nregs; i++) | ||
70 | offs[i] = cpu_to_le32(regs[i]); | ||
71 | |||
72 | /* also use the same buffer for the input */ | ||
73 | res = (__le32 *)out; | ||
74 | |||
75 | err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG, | ||
76 | 4 * nregs, (u8 *)offs, | ||
77 | 4 * nregs, (u8 *)res); | ||
78 | if (err) { | ||
79 | if (net_ratelimit()) { | ||
80 | wiphy_err(ar->hw->wiphy, "reading regs failed (%d)\n", | ||
81 | err); | ||
82 | } | ||
83 | return err; | ||
84 | } | ||
85 | |||
86 | /* convert result to cpu endian */ | ||
87 | for (i = 0; i < nregs; i++) | ||
88 | out[i] = le32_to_cpu(res[i]); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | int carl9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) | ||
94 | { | ||
95 | return carl9170_read_mreg(ar, 1, ®, val); | ||
96 | } | ||
97 | |||
98 | int carl9170_echo_test(struct ar9170 *ar, const u32 v) | ||
99 | { | ||
100 | u32 echores; | ||
101 | int err; | ||
102 | |||
103 | err = carl9170_exec_cmd(ar, CARL9170_CMD_ECHO, | ||
104 | 4, (u8 *)&v, | ||
105 | 4, (u8 *)&echores); | ||
106 | if (err) | ||
107 | return err; | ||
108 | |||
109 | if (v != echores) { | ||
110 | wiphy_info(ar->hw->wiphy, "wrong echo %x != %x", v, echores); | ||
111 | return -EINVAL; | ||
112 | } | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, | ||
118 | const enum carl9170_cmd_oids cmd, const unsigned int len) | ||
119 | { | ||
120 | struct carl9170_cmd *tmp; | ||
121 | |||
122 | tmp = kzalloc(sizeof(struct carl9170_cmd_head) + len, GFP_ATOMIC); | ||
123 | if (tmp) { | ||
124 | tmp->hdr.cmd = cmd; | ||
125 | tmp->hdr.len = len; | ||
126 | } | ||
127 | |||
128 | return tmp; | ||
129 | } | ||
130 | |||
131 | int carl9170_reboot(struct ar9170 *ar) | ||
132 | { | ||
133 | struct carl9170_cmd *cmd; | ||
134 | int err; | ||
135 | |||
136 | cmd = carl9170_cmd_buf(ar, CARL9170_CMD_REBOOT_ASYNC, 0); | ||
137 | if (!cmd) | ||
138 | return -ENOMEM; | ||
139 | |||
140 | err = __carl9170_exec_cmd(ar, (struct carl9170_cmd *)cmd, true); | ||
141 | return err; | ||
142 | } | ||
143 | |||
144 | int carl9170_mac_reset(struct ar9170 *ar) | ||
145 | { | ||
146 | return carl9170_exec_cmd(ar, CARL9170_CMD_SWRST, | ||
147 | 0, NULL, 0, NULL); | ||
148 | } | ||
149 | |||
150 | int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, | ||
151 | const u32 mode, const u32 addr, const u32 len) | ||
152 | { | ||
153 | struct carl9170_cmd *cmd; | ||
154 | |||
155 | cmd = carl9170_cmd_buf(ar, CARL9170_CMD_BCN_CTRL_ASYNC, | ||
156 | sizeof(struct carl9170_bcn_ctrl_cmd)); | ||
157 | if (!cmd) | ||
158 | return -ENOMEM; | ||
159 | |||
160 | cmd->bcn_ctrl.vif_id = cpu_to_le32(vif_id); | ||
161 | cmd->bcn_ctrl.mode = cpu_to_le32(mode); | ||
162 | cmd->bcn_ctrl.bcn_addr = cpu_to_le32(addr); | ||
163 | cmd->bcn_ctrl.bcn_len = cpu_to_le32(len); | ||
164 | |||
165 | return __carl9170_exec_cmd(ar, cmd, true); | ||
166 | } | ||
167 | |||
168 | int carl9170_powersave(struct ar9170 *ar, const bool ps) | ||
169 | { | ||
170 | struct carl9170_cmd *cmd; | ||
171 | u32 state; | ||
172 | |||
173 | cmd = carl9170_cmd_buf(ar, CARL9170_CMD_PSM_ASYNC, | ||
174 | sizeof(struct carl9170_psm)); | ||
175 | if (!cmd) | ||
176 | return -ENOMEM; | ||
177 | |||
178 | if (ps) { | ||
179 | /* Sleep until next TBTT */ | ||
180 | state = CARL9170_PSM_SLEEP | 1; | ||
181 | } else { | ||
182 | /* wake up immediately */ | ||
183 | state = 1; | ||
184 | } | ||
185 | |||
186 | cmd->psm.state = cpu_to_le32(state); | ||
187 | return __carl9170_exec_cmd(ar, cmd, true); | ||
188 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h new file mode 100644 index 000000000000..568174c71b94 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/cmd.h | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * Basic HW register/memory/command access functions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | #ifndef __CMD_H | ||
40 | #define __CMD_H | ||
41 | |||
42 | #include "carl9170.h" | ||
43 | |||
44 | /* basic HW access */ | ||
45 | int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); | ||
46 | int carl9170_read_reg(struct ar9170 *ar, const u32 reg, u32 *val); | ||
47 | int carl9170_read_mreg(struct ar9170 *ar, const int nregs, | ||
48 | const u32 *regs, u32 *out); | ||
49 | int carl9170_echo_test(struct ar9170 *ar, u32 v); | ||
50 | int carl9170_reboot(struct ar9170 *ar); | ||
51 | int carl9170_mac_reset(struct ar9170 *ar); | ||
52 | int carl9170_powersave(struct ar9170 *ar, const bool power_on); | ||
53 | int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, | ||
54 | const u32 mode, const u32 addr, const u32 len); | ||
55 | |||
56 | static inline int carl9170_flush_cab(struct ar9170 *ar, | ||
57 | const unsigned int vif_id) | ||
58 | { | ||
59 | return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0); | ||
60 | } | ||
61 | |||
62 | static inline int carl9170_rx_filter(struct ar9170 *ar, | ||
63 | const unsigned int _rx_filter) | ||
64 | { | ||
65 | __le32 rx_filter = cpu_to_le32(_rx_filter); | ||
66 | |||
67 | return carl9170_exec_cmd(ar, CARL9170_CMD_RX_FILTER, | ||
68 | sizeof(rx_filter), (u8 *)&rx_filter, | ||
69 | 0, NULL); | ||
70 | } | ||
71 | |||
72 | struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, | ||
73 | const enum carl9170_cmd_oids cmd, const unsigned int len); | ||
74 | |||
75 | /* | ||
76 | * Macros to facilitate writing multiple registers in a single | ||
77 | * write-combining USB command. Note that when the first group | ||
78 | * fails the whole thing will fail without any others attempted, | ||
79 | * but you won't know which write in the group failed. | ||
80 | */ | ||
81 | #define carl9170_regwrite_begin(ar) \ | ||
82 | do { \ | ||
83 | int __nreg = 0, __err = 0; \ | ||
84 | struct ar9170 *__ar = ar; | ||
85 | |||
86 | #define carl9170_regwrite(r, v) do { \ | ||
87 | __ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r); \ | ||
88 | __ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v); \ | ||
89 | __nreg++; \ | ||
90 | if ((__nreg >= PAYLOAD_MAX/2)) { \ | ||
91 | if (IS_ACCEPTING_CMD(__ar)) \ | ||
92 | __err = carl9170_exec_cmd(__ar, \ | ||
93 | CARL9170_CMD_WREG, 8 * __nreg, \ | ||
94 | (u8 *) &__ar->cmd_buf[1], 0, NULL); \ | ||
95 | else \ | ||
96 | goto __regwrite_out; \ | ||
97 | \ | ||
98 | __nreg = 0; \ | ||
99 | if (__err) \ | ||
100 | goto __regwrite_out; \ | ||
101 | } \ | ||
102 | } while (0) | ||
103 | |||
104 | #define carl9170_regwrite_finish() \ | ||
105 | __regwrite_out : \ | ||
106 | if (__err == 0 && __nreg) { \ | ||
107 | if (IS_ACCEPTING_CMD(__ar)) \ | ||
108 | __err = carl9170_exec_cmd(__ar, \ | ||
109 | CARL9170_CMD_WREG, 8 * __nreg, \ | ||
110 | (u8 *) &__ar->cmd_buf[1], 0, NULL); \ | ||
111 | __nreg = 0; \ | ||
112 | } | ||
113 | |||
114 | #define carl9170_regwrite_result() \ | ||
115 | __err; \ | ||
116 | } while (0); | ||
117 | |||
118 | |||
119 | #define carl9170_async_regwrite_get_buf() \ | ||
120 | do { \ | ||
121 | __nreg = 0; \ | ||
122 | __cmd = carl9170_cmd_buf(__carl, CARL9170_CMD_WREG_ASYNC, \ | ||
123 | CARL9170_MAX_CMD_PAYLOAD_LEN); \ | ||
124 | if (__cmd == NULL) { \ | ||
125 | __err = -ENOMEM; \ | ||
126 | goto __async_regwrite_out; \ | ||
127 | } \ | ||
128 | } while (0); | ||
129 | |||
130 | #define carl9170_async_regwrite_begin(carl) \ | ||
131 | do { \ | ||
132 | struct ar9170 *__carl = carl; \ | ||
133 | struct carl9170_cmd *__cmd; \ | ||
134 | unsigned int __nreg; \ | ||
135 | int __err = 0; \ | ||
136 | carl9170_async_regwrite_get_buf(); \ | ||
137 | |||
138 | #define carl9170_async_regwrite_flush() \ | ||
139 | do { \ | ||
140 | if (__cmd == NULL || __nreg == 0) \ | ||
141 | break; \ | ||
142 | \ | ||
143 | if (IS_ACCEPTING_CMD(__carl) && __nreg) { \ | ||
144 | __cmd->hdr.len = 8 * __nreg; \ | ||
145 | __err = __carl9170_exec_cmd(__carl, __cmd, true); \ | ||
146 | __cmd = NULL; \ | ||
147 | break; \ | ||
148 | } \ | ||
149 | goto __async_regwrite_out; \ | ||
150 | } while (0) | ||
151 | |||
152 | #define carl9170_async_regwrite(r, v) do { \ | ||
153 | if (__cmd == NULL) \ | ||
154 | carl9170_async_regwrite_get_buf(); \ | ||
155 | __cmd->wreg.regs[__nreg].addr = cpu_to_le32(r); \ | ||
156 | __cmd->wreg.regs[__nreg].val = cpu_to_le32(v); \ | ||
157 | __nreg++; \ | ||
158 | if ((__nreg >= PAYLOAD_MAX / 2)) \ | ||
159 | carl9170_async_regwrite_flush(); \ | ||
160 | } while (0) | ||
161 | |||
162 | #define carl9170_async_regwrite_finish() do { \ | ||
163 | __async_regwrite_out : \ | ||
164 | if (__cmd != NULL && __err == 0) \ | ||
165 | carl9170_async_regwrite_flush(); \ | ||
166 | kfree(__cmd); \ | ||
167 | } while (0) \ | ||
168 | |||
169 | #define carl9170_async_regwrite_result() \ | ||
170 | __err; \ | ||
171 | } while (0); | ||
172 | |||
173 | #endif /* __CMD_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c new file mode 100644 index 000000000000..0ac1124c2a0b --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/debug.c | |||
@@ -0,0 +1,902 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * debug(fs) probing | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2008-2009 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/module.h> | ||
43 | #include <linux/seq_file.h> | ||
44 | #include <linux/vmalloc.h> | ||
45 | #include "carl9170.h" | ||
46 | #include "cmd.h" | ||
47 | |||
48 | #define ADD(buf, off, max, fmt, args...) \ | ||
49 | off += snprintf(&buf[off], max - off, fmt, ##args); | ||
50 | |||
51 | static int carl9170_debugfs_open(struct inode *inode, struct file *file) | ||
52 | { | ||
53 | file->private_data = inode->i_private; | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | struct carl9170_debugfs_fops { | ||
58 | unsigned int read_bufsize; | ||
59 | mode_t attr; | ||
60 | char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize, | ||
61 | ssize_t *len); | ||
62 | ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size); | ||
63 | const struct file_operations fops; | ||
64 | |||
65 | enum carl9170_device_state req_dev_state; | ||
66 | }; | ||
67 | |||
68 | static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf, | ||
69 | size_t count, loff_t *ppos) | ||
70 | { | ||
71 | struct carl9170_debugfs_fops *dfops; | ||
72 | struct ar9170 *ar; | ||
73 | char *buf = NULL, *res_buf = NULL; | ||
74 | ssize_t ret = 0; | ||
75 | int err = 0; | ||
76 | |||
77 | if (!count) | ||
78 | return 0; | ||
79 | |||
80 | ar = file->private_data; | ||
81 | |||
82 | if (!ar) | ||
83 | return -ENODEV; | ||
84 | dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops); | ||
85 | |||
86 | if (!dfops->read) | ||
87 | return -ENOSYS; | ||
88 | |||
89 | if (dfops->read_bufsize) { | ||
90 | buf = vmalloc(dfops->read_bufsize); | ||
91 | if (!buf) | ||
92 | return -ENOMEM; | ||
93 | } | ||
94 | |||
95 | mutex_lock(&ar->mutex); | ||
96 | if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) { | ||
97 | err = -ENODEV; | ||
98 | res_buf = buf; | ||
99 | goto out_free; | ||
100 | } | ||
101 | |||
102 | res_buf = dfops->read(ar, buf, dfops->read_bufsize, &ret); | ||
103 | |||
104 | if (ret > 0) | ||
105 | err = simple_read_from_buffer(userbuf, count, ppos, | ||
106 | res_buf, ret); | ||
107 | else | ||
108 | err = ret; | ||
109 | |||
110 | WARN_ON_ONCE(dfops->read_bufsize && (res_buf != buf)); | ||
111 | |||
112 | out_free: | ||
113 | vfree(res_buf); | ||
114 | mutex_unlock(&ar->mutex); | ||
115 | return err; | ||
116 | } | ||
117 | |||
118 | static ssize_t carl9170_debugfs_write(struct file *file, | ||
119 | const char __user *userbuf, size_t count, loff_t *ppos) | ||
120 | { | ||
121 | struct carl9170_debugfs_fops *dfops; | ||
122 | struct ar9170 *ar; | ||
123 | char *buf = NULL; | ||
124 | int err = 0; | ||
125 | |||
126 | if (!count) | ||
127 | return 0; | ||
128 | |||
129 | if (count > PAGE_SIZE) | ||
130 | return -E2BIG; | ||
131 | |||
132 | ar = file->private_data; | ||
133 | |||
134 | if (!ar) | ||
135 | return -ENODEV; | ||
136 | dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops); | ||
137 | |||
138 | if (!dfops->write) | ||
139 | return -ENOSYS; | ||
140 | |||
141 | buf = vmalloc(count); | ||
142 | if (!buf) | ||
143 | return -ENOMEM; | ||
144 | |||
145 | if (copy_from_user(buf, userbuf, count)) { | ||
146 | err = -EFAULT; | ||
147 | goto out_free; | ||
148 | } | ||
149 | |||
150 | if (mutex_trylock(&ar->mutex) == 0) { | ||
151 | err = -EAGAIN; | ||
152 | goto out_free; | ||
153 | } | ||
154 | |||
155 | if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) { | ||
156 | err = -ENODEV; | ||
157 | goto out_unlock; | ||
158 | } | ||
159 | |||
160 | err = dfops->write(ar, buf, count); | ||
161 | if (err) | ||
162 | goto out_unlock; | ||
163 | |||
164 | out_unlock: | ||
165 | mutex_unlock(&ar->mutex); | ||
166 | |||
167 | out_free: | ||
168 | vfree(buf); | ||
169 | return err; | ||
170 | } | ||
171 | |||
172 | #define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \ | ||
173 | _attr, _dstate) \ | ||
174 | static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\ | ||
175 | .read_bufsize = _read_bufsize, \ | ||
176 | .read = _read, \ | ||
177 | .write = _write, \ | ||
178 | .attr = _attr, \ | ||
179 | .req_dev_state = _dstate, \ | ||
180 | .fops = { \ | ||
181 | .open = carl9170_debugfs_open, \ | ||
182 | .read = carl9170_debugfs_read, \ | ||
183 | .write = carl9170_debugfs_write, \ | ||
184 | .owner = THIS_MODULE \ | ||
185 | }, \ | ||
186 | } | ||
187 | |||
188 | #define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr) \ | ||
189 | __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \ | ||
190 | _attr, CARL9170_STARTED) \ | ||
191 | |||
192 | #define DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize) \ | ||
193 | DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \ | ||
194 | NULL, _read_bufsize, S_IRUSR) | ||
195 | |||
196 | #define DEBUGFS_DECLARE_WO_FILE(name) \ | ||
197 | DEBUGFS_DECLARE_FILE(name, NULL, carl9170_debugfs_##name ##_write,\ | ||
198 | 0, S_IWUSR) | ||
199 | |||
200 | #define DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize) \ | ||
201 | DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \ | ||
202 | carl9170_debugfs_##name ##_write, \ | ||
203 | _read_bufsize, S_IRUSR | S_IWUSR) | ||
204 | |||
205 | #define __DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize, _dstate) \ | ||
206 | __DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \ | ||
207 | carl9170_debugfs_##name ##_write, \ | ||
208 | _read_bufsize, S_IRUSR | S_IWUSR, _dstate) | ||
209 | |||
210 | #define DEBUGFS_READONLY_FILE(name, _read_bufsize, fmt, value...) \ | ||
211 | static char *carl9170_debugfs_ ##name ## _read(struct ar9170 *ar, \ | ||
212 | char *buf, size_t buf_size,\ | ||
213 | ssize_t *len) \ | ||
214 | { \ | ||
215 | ADD(buf, *len, buf_size, fmt "\n", ##value); \ | ||
216 | return buf; \ | ||
217 | } \ | ||
218 | DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize) | ||
219 | |||
220 | static char *carl9170_debugfs_mem_usage_read(struct ar9170 *ar, char *buf, | ||
221 | size_t bufsize, ssize_t *len) | ||
222 | { | ||
223 | ADD(buf, *len, bufsize, "jar: ["); | ||
224 | |||
225 | spin_lock_bh(&ar->mem_lock); | ||
226 | |||
227 | *len += bitmap_scnprintf(&buf[*len], bufsize - *len, | ||
228 | ar->mem_bitmap, ar->fw.mem_blocks); | ||
229 | |||
230 | ADD(buf, *len, bufsize, "]\n"); | ||
231 | |||
232 | ADD(buf, *len, bufsize, "cookies: used:%3d / total:%3d, allocs:%d\n", | ||
233 | bitmap_weight(ar->mem_bitmap, ar->fw.mem_blocks), | ||
234 | ar->fw.mem_blocks, atomic_read(&ar->mem_allocs)); | ||
235 | |||
236 | ADD(buf, *len, bufsize, "memory: free:%3d (%3d KiB) / total:%3d KiB)\n", | ||
237 | atomic_read(&ar->mem_free_blocks), | ||
238 | (atomic_read(&ar->mem_free_blocks) * ar->fw.mem_block_size) / 1024, | ||
239 | (ar->fw.mem_blocks * ar->fw.mem_block_size) / 1024); | ||
240 | |||
241 | spin_unlock_bh(&ar->mem_lock); | ||
242 | |||
243 | return buf; | ||
244 | } | ||
245 | DEBUGFS_DECLARE_RO_FILE(mem_usage, 512); | ||
246 | |||
247 | static char *carl9170_debugfs_qos_stat_read(struct ar9170 *ar, char *buf, | ||
248 | size_t bufsize, ssize_t *len) | ||
249 | { | ||
250 | ADD(buf, *len, bufsize, "%s QoS AC\n", modparam_noht ? "Hardware" : | ||
251 | "Software"); | ||
252 | |||
253 | ADD(buf, *len, bufsize, "[ VO VI " | ||
254 | " BE BK ]\n"); | ||
255 | |||
256 | spin_lock_bh(&ar->tx_stats_lock); | ||
257 | ADD(buf, *len, bufsize, "[length/limit length/limit " | ||
258 | "length/limit length/limit ]\n" | ||
259 | "[ %3d/%3d %3d/%3d " | ||
260 | " %3d/%3d %3d/%3d ]\n\n", | ||
261 | ar->tx_stats[0].len, ar->tx_stats[0].limit, | ||
262 | ar->tx_stats[1].len, ar->tx_stats[1].limit, | ||
263 | ar->tx_stats[2].len, ar->tx_stats[2].limit, | ||
264 | ar->tx_stats[3].len, ar->tx_stats[3].limit); | ||
265 | |||
266 | ADD(buf, *len, bufsize, "[ total total " | ||
267 | " total total ]\n" | ||
268 | "[%10d %10d %10d %10d ]\n\n", | ||
269 | ar->tx_stats[0].count, ar->tx_stats[1].count, | ||
270 | ar->tx_stats[2].count, ar->tx_stats[3].count); | ||
271 | |||
272 | spin_unlock_bh(&ar->tx_stats_lock); | ||
273 | |||
274 | ADD(buf, *len, bufsize, "[ pend/waittx pend/waittx " | ||
275 | " pend/waittx pend/waittx]\n" | ||
276 | "[ %3d/%3d %3d/%3d " | ||
277 | " %3d/%3d %3d/%3d ]\n\n", | ||
278 | skb_queue_len(&ar->tx_pending[0]), | ||
279 | skb_queue_len(&ar->tx_status[0]), | ||
280 | skb_queue_len(&ar->tx_pending[1]), | ||
281 | skb_queue_len(&ar->tx_status[1]), | ||
282 | skb_queue_len(&ar->tx_pending[2]), | ||
283 | skb_queue_len(&ar->tx_status[2]), | ||
284 | skb_queue_len(&ar->tx_pending[3]), | ||
285 | skb_queue_len(&ar->tx_status[3])); | ||
286 | |||
287 | return buf; | ||
288 | } | ||
289 | DEBUGFS_DECLARE_RO_FILE(qos_stat, 512); | ||
290 | |||
291 | static void carl9170_debugfs_format_frame(struct ar9170 *ar, | ||
292 | struct sk_buff *skb, const char *prefix, char *buf, | ||
293 | ssize_t *off, ssize_t bufsize) | ||
294 | { | ||
295 | struct _carl9170_tx_superframe *txc = (void *) skb->data; | ||
296 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
297 | struct carl9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | ||
298 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | ||
299 | |||
300 | ADD(buf, *off, bufsize, "%s %p, c:%2x, DA:%pM, sq:%4d, mc:%.4x, " | ||
301 | "pc:%.8x, to:%d ms\n", prefix, skb, txc->s.cookie, | ||
302 | ieee80211_get_DA(hdr), get_seq_h(hdr), | ||
303 | le16_to_cpu(txc->f.mac_control), le32_to_cpu(txc->f.phy_control), | ||
304 | jiffies_to_msecs(jiffies - arinfo->timeout)); | ||
305 | } | ||
306 | |||
307 | |||
308 | static char *carl9170_debugfs_ampdu_state_read(struct ar9170 *ar, char *buf, | ||
309 | size_t bufsize, ssize_t *len) | ||
310 | { | ||
311 | struct carl9170_sta_tid *iter; | ||
312 | struct sk_buff *skb; | ||
313 | int cnt = 0, fc; | ||
314 | int offset; | ||
315 | |||
316 | rcu_read_lock(); | ||
317 | list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { | ||
318 | |||
319 | spin_lock_bh(&iter->lock); | ||
320 | ADD(buf, *len, bufsize, "Entry: #%2d TID:%1d, BSN:%4d, " | ||
321 | "SNX:%4d, HSN:%4d, BAW:%2d, state:%1d, toggles:%d\n", | ||
322 | cnt, iter->tid, iter->bsn, iter->snx, iter->hsn, | ||
323 | iter->max, iter->state, iter->counter); | ||
324 | |||
325 | ADD(buf, *len, bufsize, "\tWindow: ["); | ||
326 | |||
327 | *len += bitmap_scnprintf(&buf[*len], bufsize - *len, | ||
328 | iter->bitmap, CARL9170_BAW_BITS); | ||
329 | |||
330 | #define BM_STR_OFF(offset) \ | ||
331 | ((CARL9170_BAW_BITS - (offset) - 1) / 4 + \ | ||
332 | (CARL9170_BAW_BITS - (offset) - 1) / 32 + 1) | ||
333 | |||
334 | ADD(buf, *len, bufsize, ",W]\n"); | ||
335 | |||
336 | offset = BM_STR_OFF(0); | ||
337 | ADD(buf, *len, bufsize, "\tBase Seq: %*s\n", offset, "T"); | ||
338 | |||
339 | offset = BM_STR_OFF(SEQ_DIFF(iter->snx, iter->bsn)); | ||
340 | ADD(buf, *len, bufsize, "\tNext Seq: %*s\n", offset, "W"); | ||
341 | |||
342 | offset = BM_STR_OFF(((int)iter->hsn - (int)iter->bsn) % | ||
343 | CARL9170_BAW_BITS); | ||
344 | ADD(buf, *len, bufsize, "\tLast Seq: %*s\n", offset, "N"); | ||
345 | |||
346 | ADD(buf, *len, bufsize, "\tPre-Aggregation reorder buffer: " | ||
347 | " currently queued:%d\n", skb_queue_len(&iter->queue)); | ||
348 | |||
349 | fc = 0; | ||
350 | skb_queue_walk(&iter->queue, skb) { | ||
351 | char prefix[32]; | ||
352 | |||
353 | snprintf(prefix, sizeof(prefix), "\t\t%3d :", fc); | ||
354 | carl9170_debugfs_format_frame(ar, skb, prefix, buf, | ||
355 | len, bufsize); | ||
356 | |||
357 | fc++; | ||
358 | } | ||
359 | spin_unlock_bh(&iter->lock); | ||
360 | cnt++; | ||
361 | } | ||
362 | rcu_read_unlock(); | ||
363 | |||
364 | return buf; | ||
365 | } | ||
366 | DEBUGFS_DECLARE_RO_FILE(ampdu_state, 8000); | ||
367 | |||
368 | static void carl9170_debugfs_queue_dump(struct ar9170 *ar, char *buf, | ||
369 | ssize_t *len, size_t bufsize, struct sk_buff_head *queue) | ||
370 | { | ||
371 | struct sk_buff *skb; | ||
372 | char prefix[16]; | ||
373 | int fc = 0; | ||
374 | |||
375 | spin_lock_bh(&queue->lock); | ||
376 | skb_queue_walk(queue, skb) { | ||
377 | snprintf(prefix, sizeof(prefix), "%3d :", fc); | ||
378 | carl9170_debugfs_format_frame(ar, skb, prefix, buf, | ||
379 | len, bufsize); | ||
380 | fc++; | ||
381 | } | ||
382 | spin_unlock_bh(&queue->lock); | ||
383 | } | ||
384 | |||
385 | #define DEBUGFS_QUEUE_DUMP(q, qi) \ | ||
386 | static char *carl9170_debugfs_##q ##_##qi ##_read(struct ar9170 *ar, \ | ||
387 | char *buf, size_t bufsize, ssize_t *len) \ | ||
388 | { \ | ||
389 | carl9170_debugfs_queue_dump(ar, buf, len, bufsize, &ar->q[qi]); \ | ||
390 | return buf; \ | ||
391 | } \ | ||
392 | DEBUGFS_DECLARE_RO_FILE(q##_##qi, 8000); | ||
393 | |||
394 | static char *carl9170_debugfs_sta_psm_read(struct ar9170 *ar, char *buf, | ||
395 | size_t bufsize, ssize_t *len) | ||
396 | { | ||
397 | ADD(buf, *len, bufsize, "psm state: %s\n", (ar->ps.off_override ? | ||
398 | "FORCE CAM" : (ar->ps.state ? "PSM" : "CAM"))); | ||
399 | |||
400 | ADD(buf, *len, bufsize, "sleep duration: %d ms.\n", ar->ps.sleep_ms); | ||
401 | ADD(buf, *len, bufsize, "last power-state transition: %d ms ago.\n", | ||
402 | jiffies_to_msecs(jiffies - ar->ps.last_action)); | ||
403 | ADD(buf, *len, bufsize, "last CAM->PSM transition: %d ms ago.\n", | ||
404 | jiffies_to_msecs(jiffies - ar->ps.last_slept)); | ||
405 | |||
406 | return buf; | ||
407 | } | ||
408 | DEBUGFS_DECLARE_RO_FILE(sta_psm, 160); | ||
409 | |||
410 | static char *carl9170_debugfs_tx_stuck_read(struct ar9170 *ar, char *buf, | ||
411 | size_t bufsize, ssize_t *len) | ||
412 | { | ||
413 | int i; | ||
414 | |||
415 | for (i = 0; i < ar->hw->queues; i++) { | ||
416 | ADD(buf, *len, bufsize, "TX queue [%d]: %10d max:%10d ms.\n", | ||
417 | i, ieee80211_queue_stopped(ar->hw, i) ? | ||
418 | jiffies_to_msecs(jiffies - ar->queue_stop_timeout[i]) : 0, | ||
419 | jiffies_to_msecs(ar->max_queue_stop_timeout[i])); | ||
420 | |||
421 | ar->max_queue_stop_timeout[i] = 0; | ||
422 | } | ||
423 | |||
424 | return buf; | ||
425 | } | ||
426 | DEBUGFS_DECLARE_RO_FILE(tx_stuck, 180); | ||
427 | |||
428 | static char *carl9170_debugfs_phy_noise_read(struct ar9170 *ar, char *buf, | ||
429 | size_t bufsize, ssize_t *len) | ||
430 | { | ||
431 | int err; | ||
432 | |||
433 | err = carl9170_get_noisefloor(ar); | ||
434 | if (err) { | ||
435 | *len = err; | ||
436 | return buf; | ||
437 | } | ||
438 | |||
439 | ADD(buf, *len, bufsize, "Chain 0: %10d dBm, ext. chan.:%10d dBm\n", | ||
440 | ar->noise[0], ar->noise[2]); | ||
441 | ADD(buf, *len, bufsize, "Chain 2: %10d dBm, ext. chan.:%10d dBm\n", | ||
442 | ar->noise[1], ar->noise[3]); | ||
443 | |||
444 | return buf; | ||
445 | } | ||
446 | DEBUGFS_DECLARE_RO_FILE(phy_noise, 180); | ||
447 | |||
448 | static char *carl9170_debugfs_vif_dump_read(struct ar9170 *ar, char *buf, | ||
449 | size_t bufsize, ssize_t *len) | ||
450 | { | ||
451 | struct carl9170_vif_info *iter; | ||
452 | int i = 0; | ||
453 | |||
454 | ADD(buf, *len, bufsize, "registered VIFs:%d \\ %d\n", | ||
455 | ar->vifs, ar->fw.vif_num); | ||
456 | |||
457 | ADD(buf, *len, bufsize, "VIF bitmap: ["); | ||
458 | |||
459 | *len += bitmap_scnprintf(&buf[*len], bufsize - *len, | ||
460 | &ar->vif_bitmap, ar->fw.vif_num); | ||
461 | |||
462 | ADD(buf, *len, bufsize, "]\n"); | ||
463 | |||
464 | rcu_read_lock(); | ||
465 | list_for_each_entry_rcu(iter, &ar->vif_list, list) { | ||
466 | struct ieee80211_vif *vif = carl9170_get_vif(iter); | ||
467 | ADD(buf, *len, bufsize, "\t%d = [%s VIF, id:%d, type:%x " | ||
468 | " mac:%pM %s]\n", i, (carl9170_get_main_vif(ar) == vif ? | ||
469 | "Master" : " Slave"), iter->id, vif->type, vif->addr, | ||
470 | iter->enable_beacon ? "beaconing " : ""); | ||
471 | i++; | ||
472 | } | ||
473 | rcu_read_unlock(); | ||
474 | |||
475 | return buf; | ||
476 | } | ||
477 | DEBUGFS_DECLARE_RO_FILE(vif_dump, 8000); | ||
478 | |||
479 | #define UPDATE_COUNTER(ar, name) ({ \ | ||
480 | u32 __tmp[ARRAY_SIZE(name##_regs)]; \ | ||
481 | unsigned int __i, __err = -ENODEV; \ | ||
482 | \ | ||
483 | for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) { \ | ||
484 | __tmp[__i] = name##_regs[__i].reg; \ | ||
485 | ar->debug.stats.name##_counter[__i] = 0; \ | ||
486 | } \ | ||
487 | \ | ||
488 | if (IS_STARTED(ar)) \ | ||
489 | __err = carl9170_read_mreg(ar, ARRAY_SIZE(name##_regs), \ | ||
490 | __tmp, ar->debug.stats.name##_counter); \ | ||
491 | (__err); }) | ||
492 | |||
493 | #define TALLY_SUM_UP(ar, name) do { \ | ||
494 | unsigned int __i; \ | ||
495 | \ | ||
496 | for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) { \ | ||
497 | ar->debug.stats.name##_sum[__i] += \ | ||
498 | ar->debug.stats.name##_counter[__i]; \ | ||
499 | } \ | ||
500 | } while (0) | ||
501 | |||
502 | #define DEBUGFS_HW_TALLY_FILE(name, f) \ | ||
503 | static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \ | ||
504 | char *dum, size_t bufsize, ssize_t *ret) \ | ||
505 | { \ | ||
506 | char *buf; \ | ||
507 | int i, max_len, err; \ | ||
508 | \ | ||
509 | max_len = ARRAY_SIZE(name##_regs) * 80; \ | ||
510 | buf = vmalloc(max_len); \ | ||
511 | if (!buf) \ | ||
512 | return NULL; \ | ||
513 | \ | ||
514 | err = UPDATE_COUNTER(ar, name); \ | ||
515 | if (err) { \ | ||
516 | *ret = err; \ | ||
517 | return buf; \ | ||
518 | } \ | ||
519 | \ | ||
520 | TALLY_SUM_UP(ar, name); \ | ||
521 | \ | ||
522 | for (i = 0; i < ARRAY_SIZE(name##_regs); i++) { \ | ||
523 | ADD(buf, *ret, max_len, "%22s = %" f "[+%" f "]\n", \ | ||
524 | name##_regs[i].nreg, ar->debug.stats.name ##_sum[i],\ | ||
525 | ar->debug.stats.name ##_counter[i]); \ | ||
526 | } \ | ||
527 | \ | ||
528 | return buf; \ | ||
529 | } \ | ||
530 | DEBUGFS_DECLARE_RO_FILE(name, 0); | ||
531 | |||
532 | #define DEBUGFS_HW_REG_FILE(name, f) \ | ||
533 | static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \ | ||
534 | char *dum, size_t bufsize, ssize_t *ret) \ | ||
535 | { \ | ||
536 | char *buf; \ | ||
537 | int i, max_len, err; \ | ||
538 | \ | ||
539 | max_len = ARRAY_SIZE(name##_regs) * 80; \ | ||
540 | buf = vmalloc(max_len); \ | ||
541 | if (!buf) \ | ||
542 | return NULL; \ | ||
543 | \ | ||
544 | err = UPDATE_COUNTER(ar, name); \ | ||
545 | if (err) { \ | ||
546 | *ret = err; \ | ||
547 | return buf; \ | ||
548 | } \ | ||
549 | \ | ||
550 | for (i = 0; i < ARRAY_SIZE(name##_regs); i++) { \ | ||
551 | ADD(buf, *ret, max_len, "%22s = %" f "\n", \ | ||
552 | name##_regs[i].nreg, \ | ||
553 | ar->debug.stats.name##_counter[i]); \ | ||
554 | } \ | ||
555 | \ | ||
556 | return buf; \ | ||
557 | } \ | ||
558 | DEBUGFS_DECLARE_RO_FILE(name, 0); | ||
559 | |||
560 | static ssize_t carl9170_debugfs_hw_ioread32_write(struct ar9170 *ar, | ||
561 | const char *buf, size_t count) | ||
562 | { | ||
563 | int err = 0, i, n = 0, max_len = 32, res; | ||
564 | unsigned int reg, tmp; | ||
565 | |||
566 | if (!count) | ||
567 | return 0; | ||
568 | |||
569 | if (count > max_len) | ||
570 | return -E2BIG; | ||
571 | |||
572 | res = sscanf(buf, "0x%X %d", ®, &n); | ||
573 | if (res < 1) { | ||
574 | err = -EINVAL; | ||
575 | goto out; | ||
576 | } | ||
577 | |||
578 | if (res == 1) | ||
579 | n = 1; | ||
580 | |||
581 | if (n > 15) { | ||
582 | err = -EMSGSIZE; | ||
583 | goto out; | ||
584 | } | ||
585 | |||
586 | if ((reg >= 0x280000) || ((reg + (n << 2)) >= 0x280000)) { | ||
587 | err = -EADDRNOTAVAIL; | ||
588 | goto out; | ||
589 | } | ||
590 | |||
591 | if (reg & 3) { | ||
592 | err = -EINVAL; | ||
593 | goto out; | ||
594 | } | ||
595 | |||
596 | for (i = 0; i < n; i++) { | ||
597 | err = carl9170_read_reg(ar, reg + (i << 2), &tmp); | ||
598 | if (err) | ||
599 | goto out; | ||
600 | |||
601 | ar->debug.ring[ar->debug.ring_tail].reg = reg + (i << 2); | ||
602 | ar->debug.ring[ar->debug.ring_tail].value = tmp; | ||
603 | ar->debug.ring_tail++; | ||
604 | ar->debug.ring_tail %= CARL9170_DEBUG_RING_SIZE; | ||
605 | } | ||
606 | |||
607 | out: | ||
608 | return err ? err : count; | ||
609 | } | ||
610 | |||
611 | static char *carl9170_debugfs_hw_ioread32_read(struct ar9170 *ar, char *buf, | ||
612 | size_t bufsize, ssize_t *ret) | ||
613 | { | ||
614 | int i = 0; | ||
615 | |||
616 | while (ar->debug.ring_head != ar->debug.ring_tail) { | ||
617 | ADD(buf, *ret, bufsize, "%.8x = %.8x\n", | ||
618 | ar->debug.ring[ar->debug.ring_head].reg, | ||
619 | ar->debug.ring[ar->debug.ring_head].value); | ||
620 | |||
621 | ar->debug.ring_head++; | ||
622 | ar->debug.ring_head %= CARL9170_DEBUG_RING_SIZE; | ||
623 | |||
624 | if (i++ == 64) | ||
625 | break; | ||
626 | } | ||
627 | ar->debug.ring_head = ar->debug.ring_tail; | ||
628 | return buf; | ||
629 | } | ||
630 | DEBUGFS_DECLARE_RW_FILE(hw_ioread32, CARL9170_DEBUG_RING_SIZE * 40); | ||
631 | |||
632 | static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf, | ||
633 | size_t count) | ||
634 | { | ||
635 | int err; | ||
636 | |||
637 | if (count < 1) | ||
638 | return -EINVAL; | ||
639 | |||
640 | switch (buf[0]) { | ||
641 | case 'F': | ||
642 | ar->needs_full_reset = true; | ||
643 | break; | ||
644 | |||
645 | case 'R': | ||
646 | if (!IS_STARTED(ar)) { | ||
647 | err = -EAGAIN; | ||
648 | goto out; | ||
649 | } | ||
650 | |||
651 | ar->needs_full_reset = false; | ||
652 | break; | ||
653 | |||
654 | case 'M': | ||
655 | err = carl9170_mac_reset(ar); | ||
656 | if (err < 0) | ||
657 | count = err; | ||
658 | |||
659 | goto out; | ||
660 | |||
661 | case 'P': | ||
662 | err = carl9170_set_channel(ar, ar->hw->conf.channel, | ||
663 | ar->hw->conf.channel_type, CARL9170_RFI_COLD); | ||
664 | if (err < 0) | ||
665 | count = err; | ||
666 | |||
667 | goto out; | ||
668 | |||
669 | default: | ||
670 | return -EINVAL; | ||
671 | } | ||
672 | |||
673 | carl9170_restart(ar, CARL9170_RR_USER_REQUEST); | ||
674 | |||
675 | out: | ||
676 | return count; | ||
677 | } | ||
678 | |||
679 | static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf, | ||
680 | size_t bufsize, ssize_t *ret) | ||
681 | { | ||
682 | ADD(buf, *ret, bufsize, "[P]hy reinit, [R]estart, [F]ull usb reset, " | ||
683 | "[M]ac reset\n"); | ||
684 | ADD(buf, *ret, bufsize, "firmware restarts:%d, last reason:%d\n", | ||
685 | ar->restart_counter, ar->last_reason); | ||
686 | ADD(buf, *ret, bufsize, "phy reinit errors:%d (%d)\n", | ||
687 | ar->total_chan_fail, ar->chan_fail); | ||
688 | ADD(buf, *ret, bufsize, "reported firmware errors:%d\n", | ||
689 | ar->fw.err_counter); | ||
690 | ADD(buf, *ret, bufsize, "reported firmware BUGs:%d\n", | ||
691 | ar->fw.bug_counter); | ||
692 | ADD(buf, *ret, bufsize, "pending restart requests:%d\n", | ||
693 | atomic_read(&ar->pending_restarts)); | ||
694 | return buf; | ||
695 | } | ||
696 | __DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED); | ||
697 | |||
698 | static const char *erp_modes[] = { | ||
699 | [CARL9170_ERP_INVALID] = "INVALID", | ||
700 | [CARL9170_ERP_AUTO] = "Automatic", | ||
701 | [CARL9170_ERP_MAC80211] = "Set by MAC80211", | ||
702 | [CARL9170_ERP_OFF] = "Force Off", | ||
703 | [CARL9170_ERP_RTS] = "Force RTS", | ||
704 | [CARL9170_ERP_CTS] = "Force CTS" | ||
705 | }; | ||
706 | |||
707 | static char *carl9170_debugfs_erp_read(struct ar9170 *ar, char *buf, | ||
708 | size_t bufsize, ssize_t *ret) | ||
709 | { | ||
710 | ADD(buf, *ret, bufsize, "ERP Setting: (%d) -> %s\n", ar->erp_mode, | ||
711 | erp_modes[ar->erp_mode]); | ||
712 | return buf; | ||
713 | } | ||
714 | |||
715 | static ssize_t carl9170_debugfs_erp_write(struct ar9170 *ar, const char *buf, | ||
716 | size_t count) | ||
717 | { | ||
718 | int res, val; | ||
719 | |||
720 | if (count < 1) | ||
721 | return -EINVAL; | ||
722 | |||
723 | res = sscanf(buf, "%d", &val); | ||
724 | if (res != 1) | ||
725 | return -EINVAL; | ||
726 | |||
727 | if (!((val > CARL9170_ERP_INVALID) && | ||
728 | (val < __CARL9170_ERP_NUM))) | ||
729 | return -EINVAL; | ||
730 | |||
731 | ar->erp_mode = val; | ||
732 | return count; | ||
733 | } | ||
734 | |||
735 | DEBUGFS_DECLARE_RW_FILE(erp, 80); | ||
736 | |||
737 | static ssize_t carl9170_debugfs_hw_iowrite32_write(struct ar9170 *ar, | ||
738 | const char *buf, size_t count) | ||
739 | { | ||
740 | int err = 0, max_len = 22, res; | ||
741 | u32 reg, val; | ||
742 | |||
743 | if (!count) | ||
744 | return 0; | ||
745 | |||
746 | if (count > max_len) | ||
747 | return -E2BIG; | ||
748 | |||
749 | res = sscanf(buf, "0x%X 0x%X", ®, &val); | ||
750 | if (res != 2) { | ||
751 | err = -EINVAL; | ||
752 | goto out; | ||
753 | } | ||
754 | |||
755 | if (reg <= 0x100000 || reg >= 0x280000) { | ||
756 | err = -EADDRNOTAVAIL; | ||
757 | goto out; | ||
758 | } | ||
759 | |||
760 | if (reg & 3) { | ||
761 | err = -EINVAL; | ||
762 | goto out; | ||
763 | } | ||
764 | |||
765 | err = carl9170_write_reg(ar, reg, val); | ||
766 | if (err) | ||
767 | goto out; | ||
768 | |||
769 | out: | ||
770 | return err ? err : count; | ||
771 | } | ||
772 | DEBUGFS_DECLARE_WO_FILE(hw_iowrite32); | ||
773 | |||
774 | DEBUGFS_HW_TALLY_FILE(hw_tx_tally, "u"); | ||
775 | DEBUGFS_HW_TALLY_FILE(hw_rx_tally, "u"); | ||
776 | DEBUGFS_HW_TALLY_FILE(hw_phy_errors, "u"); | ||
777 | DEBUGFS_HW_REG_FILE(hw_wlan_queue, ".8x"); | ||
778 | DEBUGFS_HW_REG_FILE(hw_pta_queue, ".8x"); | ||
779 | DEBUGFS_HW_REG_FILE(hw_ampdu_info, ".8x"); | ||
780 | DEBUGFS_QUEUE_DUMP(tx_status, 0); | ||
781 | DEBUGFS_QUEUE_DUMP(tx_status, 1); | ||
782 | DEBUGFS_QUEUE_DUMP(tx_status, 2); | ||
783 | DEBUGFS_QUEUE_DUMP(tx_status, 3); | ||
784 | DEBUGFS_QUEUE_DUMP(tx_pending, 0); | ||
785 | DEBUGFS_QUEUE_DUMP(tx_pending, 1); | ||
786 | DEBUGFS_QUEUE_DUMP(tx_pending, 2); | ||
787 | DEBUGFS_QUEUE_DUMP(tx_pending, 3); | ||
788 | DEBUGFS_READONLY_FILE(usb_tx_anch_urbs, 20, "%d", | ||
789 | atomic_read(&ar->tx_anch_urbs)); | ||
790 | DEBUGFS_READONLY_FILE(usb_rx_anch_urbs, 20, "%d", | ||
791 | atomic_read(&ar->rx_anch_urbs)); | ||
792 | DEBUGFS_READONLY_FILE(usb_rx_work_urbs, 20, "%d", | ||
793 | atomic_read(&ar->rx_work_urbs)); | ||
794 | DEBUGFS_READONLY_FILE(usb_rx_pool_urbs, 20, "%d", | ||
795 | atomic_read(&ar->rx_pool_urbs)); | ||
796 | |||
797 | DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d", | ||
798 | atomic_read(&ar->tx_total_queued)); | ||
799 | DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d", | ||
800 | atomic_read(&ar->tx_ampdu_scheduler)); | ||
801 | |||
802 | DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d", | ||
803 | atomic_read(&ar->tx_total_pending)); | ||
804 | |||
805 | DEBUGFS_READONLY_FILE(tx_ampdu_list_len, 20, "%d", | ||
806 | ar->tx_ampdu_list_len); | ||
807 | |||
808 | DEBUGFS_READONLY_FILE(tx_ampdu_upload, 20, "%d", | ||
809 | atomic_read(&ar->tx_ampdu_upload)); | ||
810 | |||
811 | DEBUGFS_READONLY_FILE(tx_janitor_last_run, 64, "last run:%d ms ago", | ||
812 | jiffies_to_msecs(jiffies - ar->tx_janitor_last_run)); | ||
813 | |||
814 | DEBUGFS_READONLY_FILE(tx_dropped, 20, "%d", ar->tx_dropped); | ||
815 | |||
816 | DEBUGFS_READONLY_FILE(rx_dropped, 20, "%d", ar->rx_dropped); | ||
817 | |||
818 | DEBUGFS_READONLY_FILE(sniffer_enabled, 20, "%d", ar->sniffer_enabled); | ||
819 | DEBUGFS_READONLY_FILE(rx_software_decryption, 20, "%d", | ||
820 | ar->rx_software_decryption); | ||
821 | DEBUGFS_READONLY_FILE(ampdu_factor, 20, "%d", | ||
822 | ar->current_factor); | ||
823 | DEBUGFS_READONLY_FILE(ampdu_density, 20, "%d", | ||
824 | ar->current_density); | ||
825 | |||
826 | DEBUGFS_READONLY_FILE(beacon_int, 20, "%d TU", ar->global_beacon_int); | ||
827 | DEBUGFS_READONLY_FILE(pretbtt, 20, "%d TU", ar->global_pretbtt); | ||
828 | |||
829 | void carl9170_debugfs_register(struct ar9170 *ar) | ||
830 | { | ||
831 | ar->debug_dir = debugfs_create_dir(KBUILD_MODNAME, | ||
832 | ar->hw->wiphy->debugfsdir); | ||
833 | |||
834 | #define DEBUGFS_ADD(name) \ | ||
835 | debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr, \ | ||
836 | ar->debug_dir, ar, \ | ||
837 | &carl_debugfs_##name ## _ops.fops); | ||
838 | |||
839 | DEBUGFS_ADD(usb_tx_anch_urbs); | ||
840 | DEBUGFS_ADD(usb_rx_pool_urbs); | ||
841 | DEBUGFS_ADD(usb_rx_anch_urbs); | ||
842 | DEBUGFS_ADD(usb_rx_work_urbs); | ||
843 | |||
844 | DEBUGFS_ADD(tx_total_queued); | ||
845 | DEBUGFS_ADD(tx_total_pending); | ||
846 | DEBUGFS_ADD(tx_dropped); | ||
847 | DEBUGFS_ADD(tx_stuck); | ||
848 | DEBUGFS_ADD(tx_ampdu_upload); | ||
849 | DEBUGFS_ADD(tx_ampdu_scheduler); | ||
850 | DEBUGFS_ADD(tx_ampdu_list_len); | ||
851 | |||
852 | DEBUGFS_ADD(rx_dropped); | ||
853 | DEBUGFS_ADD(sniffer_enabled); | ||
854 | DEBUGFS_ADD(rx_software_decryption); | ||
855 | |||
856 | DEBUGFS_ADD(mem_usage); | ||
857 | DEBUGFS_ADD(qos_stat); | ||
858 | DEBUGFS_ADD(sta_psm); | ||
859 | DEBUGFS_ADD(ampdu_state); | ||
860 | |||
861 | DEBUGFS_ADD(hw_tx_tally); | ||
862 | DEBUGFS_ADD(hw_rx_tally); | ||
863 | DEBUGFS_ADD(hw_phy_errors); | ||
864 | DEBUGFS_ADD(phy_noise); | ||
865 | |||
866 | DEBUGFS_ADD(hw_wlan_queue); | ||
867 | DEBUGFS_ADD(hw_pta_queue); | ||
868 | DEBUGFS_ADD(hw_ampdu_info); | ||
869 | |||
870 | DEBUGFS_ADD(ampdu_density); | ||
871 | DEBUGFS_ADD(ampdu_factor); | ||
872 | |||
873 | DEBUGFS_ADD(tx_janitor_last_run); | ||
874 | |||
875 | DEBUGFS_ADD(tx_status_0); | ||
876 | DEBUGFS_ADD(tx_status_1); | ||
877 | DEBUGFS_ADD(tx_status_2); | ||
878 | DEBUGFS_ADD(tx_status_3); | ||
879 | |||
880 | DEBUGFS_ADD(tx_pending_0); | ||
881 | DEBUGFS_ADD(tx_pending_1); | ||
882 | DEBUGFS_ADD(tx_pending_2); | ||
883 | DEBUGFS_ADD(tx_pending_3); | ||
884 | |||
885 | DEBUGFS_ADD(hw_ioread32); | ||
886 | DEBUGFS_ADD(hw_iowrite32); | ||
887 | DEBUGFS_ADD(bug); | ||
888 | |||
889 | DEBUGFS_ADD(erp); | ||
890 | |||
891 | DEBUGFS_ADD(vif_dump); | ||
892 | |||
893 | DEBUGFS_ADD(beacon_int); | ||
894 | DEBUGFS_ADD(pretbtt); | ||
895 | |||
896 | #undef DEBUGFS_ADD | ||
897 | } | ||
898 | |||
899 | void carl9170_debugfs_unregister(struct ar9170 *ar) | ||
900 | { | ||
901 | debugfs_remove_recursive(ar->debug_dir); | ||
902 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/debug.h b/drivers/net/wireless/ath/carl9170/debug.h new file mode 100644 index 000000000000..ea4b97524122 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/debug.h | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * debug header | ||
5 | * | ||
6 | * Copyright 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | #ifndef __DEBUG_H | ||
39 | #define __DEBUG_H | ||
40 | |||
41 | #include "eeprom.h" | ||
42 | #include "wlan.h" | ||
43 | #include "hw.h" | ||
44 | #include "fwdesc.h" | ||
45 | #include "fwcmd.h" | ||
46 | #include "../regd.h" | ||
47 | |||
48 | struct hw_stat_reg_entry { | ||
49 | u32 reg; | ||
50 | char nreg[32]; | ||
51 | }; | ||
52 | |||
53 | #define STAT_MAC_REG(reg) \ | ||
54 | { (AR9170_MAC_REG_##reg), #reg } | ||
55 | |||
56 | #define STAT_PTA_REG(reg) \ | ||
57 | { (AR9170_PTA_REG_##reg), #reg } | ||
58 | |||
59 | #define STAT_USB_REG(reg) \ | ||
60 | { (AR9170_USB_REG_##reg), #reg } | ||
61 | |||
62 | static const struct hw_stat_reg_entry hw_rx_tally_regs[] = { | ||
63 | STAT_MAC_REG(RX_CRC32), STAT_MAC_REG(RX_CRC16), | ||
64 | STAT_MAC_REG(RX_TIMEOUT_COUNT), STAT_MAC_REG(RX_ERR_DECRYPTION_UNI), | ||
65 | STAT_MAC_REG(RX_ERR_DECRYPTION_MUL), STAT_MAC_REG(RX_MPDU), | ||
66 | STAT_MAC_REG(RX_DROPPED_MPDU), STAT_MAC_REG(RX_DEL_MPDU), | ||
67 | }; | ||
68 | |||
69 | static const struct hw_stat_reg_entry hw_phy_errors_regs[] = { | ||
70 | STAT_MAC_REG(RX_PHY_MISC_ERROR), STAT_MAC_REG(RX_PHY_XR_ERROR), | ||
71 | STAT_MAC_REG(RX_PHY_OFDM_ERROR), STAT_MAC_REG(RX_PHY_CCK_ERROR), | ||
72 | STAT_MAC_REG(RX_PHY_HT_ERROR), STAT_MAC_REG(RX_PHY_TOTAL), | ||
73 | }; | ||
74 | |||
75 | static const struct hw_stat_reg_entry hw_tx_tally_regs[] = { | ||
76 | STAT_MAC_REG(TX_TOTAL), STAT_MAC_REG(TX_UNDERRUN), | ||
77 | STAT_MAC_REG(TX_RETRY), | ||
78 | }; | ||
79 | |||
80 | static const struct hw_stat_reg_entry hw_wlan_queue_regs[] = { | ||
81 | STAT_MAC_REG(DMA_STATUS), STAT_MAC_REG(DMA_TRIGGER), | ||
82 | STAT_MAC_REG(DMA_TXQ0_ADDR), STAT_MAC_REG(DMA_TXQ0_CURR_ADDR), | ||
83 | STAT_MAC_REG(DMA_TXQ1_ADDR), STAT_MAC_REG(DMA_TXQ1_CURR_ADDR), | ||
84 | STAT_MAC_REG(DMA_TXQ2_ADDR), STAT_MAC_REG(DMA_TXQ2_CURR_ADDR), | ||
85 | STAT_MAC_REG(DMA_TXQ3_ADDR), STAT_MAC_REG(DMA_TXQ3_CURR_ADDR), | ||
86 | STAT_MAC_REG(DMA_RXQ_ADDR), STAT_MAC_REG(DMA_RXQ_CURR_ADDR), | ||
87 | }; | ||
88 | |||
89 | static const struct hw_stat_reg_entry hw_ampdu_info_regs[] = { | ||
90 | STAT_MAC_REG(AMPDU_DENSITY), STAT_MAC_REG(AMPDU_FACTOR), | ||
91 | }; | ||
92 | |||
93 | static const struct hw_stat_reg_entry hw_pta_queue_regs[] = { | ||
94 | STAT_PTA_REG(DN_CURR_ADDRH), STAT_PTA_REG(DN_CURR_ADDRL), | ||
95 | STAT_PTA_REG(UP_CURR_ADDRH), STAT_PTA_REG(UP_CURR_ADDRL), | ||
96 | STAT_PTA_REG(DMA_STATUS), STAT_PTA_REG(DMA_MODE_CTRL), | ||
97 | }; | ||
98 | |||
99 | #define DEFINE_TALLY(name) \ | ||
100 | u32 name##_sum[ARRAY_SIZE(name##_regs)], \ | ||
101 | name##_counter[ARRAY_SIZE(name##_regs)] \ | ||
102 | |||
103 | #define DEFINE_STAT(name) \ | ||
104 | u32 name##_counter[ARRAY_SIZE(name##_regs)] \ | ||
105 | |||
106 | struct ath_stats { | ||
107 | DEFINE_TALLY(hw_tx_tally); | ||
108 | DEFINE_TALLY(hw_rx_tally); | ||
109 | DEFINE_TALLY(hw_phy_errors); | ||
110 | DEFINE_STAT(hw_wlan_queue); | ||
111 | DEFINE_STAT(hw_pta_queue); | ||
112 | DEFINE_STAT(hw_ampdu_info); | ||
113 | }; | ||
114 | |||
115 | struct carl9170_debug_mem_rbe { | ||
116 | u32 reg; | ||
117 | u32 value; | ||
118 | }; | ||
119 | |||
120 | #define CARL9170_DEBUG_RING_SIZE 64 | ||
121 | |||
122 | struct carl9170_debug { | ||
123 | struct ath_stats stats; | ||
124 | struct carl9170_debug_mem_rbe ring[CARL9170_DEBUG_RING_SIZE]; | ||
125 | struct mutex ring_lock; | ||
126 | unsigned int ring_head, ring_tail; | ||
127 | struct delayed_work update_tally; | ||
128 | }; | ||
129 | |||
130 | struct ar9170; | ||
131 | |||
132 | void carl9170_debugfs_register(struct ar9170 *ar); | ||
133 | void carl9170_debugfs_unregister(struct ar9170 *ar); | ||
134 | #endif /* __DEBUG_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/eeprom.h b/drivers/net/wireless/ath/carl9170/eeprom.h new file mode 100644 index 000000000000..7cff40ac7759 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/eeprom.h | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * EEPROM layout | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | #ifndef __CARL9170_SHARED_EEPROM_H | ||
39 | #define __CARL9170_SHARED_EEPROM_H | ||
40 | |||
41 | #define AR9170_EEPROM_START 0x1600 | ||
42 | |||
43 | #define AR5416_MAX_CHAINS 2 | ||
44 | #define AR5416_MODAL_SPURS 5 | ||
45 | |||
46 | struct ar9170_eeprom_modal { | ||
47 | __le32 antCtrlChain[AR5416_MAX_CHAINS]; | ||
48 | __le32 antCtrlCommon; | ||
49 | s8 antennaGainCh[AR5416_MAX_CHAINS]; | ||
50 | u8 switchSettling; | ||
51 | u8 txRxAttenCh[AR5416_MAX_CHAINS]; | ||
52 | u8 rxTxMarginCh[AR5416_MAX_CHAINS]; | ||
53 | s8 adcDesiredSize; | ||
54 | s8 pgaDesiredSize; | ||
55 | u8 xlnaGainCh[AR5416_MAX_CHAINS]; | ||
56 | u8 txEndToXpaOff; | ||
57 | u8 txEndToRxOn; | ||
58 | u8 txFrameToXpaOn; | ||
59 | u8 thresh62; | ||
60 | s8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; | ||
61 | u8 xpdGain; | ||
62 | u8 xpd; | ||
63 | s8 iqCalICh[AR5416_MAX_CHAINS]; | ||
64 | s8 iqCalQCh[AR5416_MAX_CHAINS]; | ||
65 | u8 pdGainOverlap; | ||
66 | u8 ob; | ||
67 | u8 db; | ||
68 | u8 xpaBiasLvl; | ||
69 | u8 pwrDecreaseFor2Chain; | ||
70 | u8 pwrDecreaseFor3Chain; | ||
71 | u8 txFrameToDataStart; | ||
72 | u8 txFrameToPaOn; | ||
73 | u8 ht40PowerIncForPdadc; | ||
74 | u8 bswAtten[AR5416_MAX_CHAINS]; | ||
75 | u8 bswMargin[AR5416_MAX_CHAINS]; | ||
76 | u8 swSettleHt40; | ||
77 | u8 reserved[22]; | ||
78 | struct spur_channel { | ||
79 | __le16 spurChan; | ||
80 | u8 spurRangeLow; | ||
81 | u8 spurRangeHigh; | ||
82 | } __packed spur_channels[AR5416_MODAL_SPURS]; | ||
83 | } __packed; | ||
84 | |||
85 | #define AR5416_NUM_PD_GAINS 4 | ||
86 | #define AR5416_PD_GAIN_ICEPTS 5 | ||
87 | |||
88 | struct ar9170_calibration_data_per_freq { | ||
89 | u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | ||
90 | u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | ||
91 | } __packed; | ||
92 | |||
93 | #define AR5416_NUM_5G_CAL_PIERS 8 | ||
94 | #define AR5416_NUM_2G_CAL_PIERS 4 | ||
95 | |||
96 | #define AR5416_NUM_5G_TARGET_PWRS 8 | ||
97 | #define AR5416_NUM_2G_CCK_TARGET_PWRS 3 | ||
98 | #define AR5416_NUM_2G_OFDM_TARGET_PWRS 4 | ||
99 | #define AR5416_MAX_NUM_TGT_PWRS 8 | ||
100 | |||
101 | struct ar9170_calibration_target_power_legacy { | ||
102 | u8 freq; | ||
103 | u8 power[4]; | ||
104 | } __packed; | ||
105 | |||
106 | struct ar9170_calibration_target_power_ht { | ||
107 | u8 freq; | ||
108 | u8 power[8]; | ||
109 | } __packed; | ||
110 | |||
111 | #define AR5416_NUM_CTLS 24 | ||
112 | |||
113 | struct ar9170_calctl_edges { | ||
114 | u8 channel; | ||
115 | #define AR9170_CALCTL_EDGE_FLAGS 0xC0 | ||
116 | u8 power_flags; | ||
117 | } __packed; | ||
118 | |||
119 | #define AR5416_NUM_BAND_EDGES 8 | ||
120 | |||
121 | struct ar9170_calctl_data { | ||
122 | struct ar9170_calctl_edges | ||
123 | control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; | ||
124 | } __packed; | ||
125 | |||
126 | struct ar9170_eeprom { | ||
127 | __le16 length; | ||
128 | __le16 checksum; | ||
129 | __le16 version; | ||
130 | u8 operating_flags; | ||
131 | #define AR9170_OPFLAG_5GHZ 1 | ||
132 | #define AR9170_OPFLAG_2GHZ 2 | ||
133 | u8 misc; | ||
134 | __le16 reg_domain[2]; | ||
135 | u8 mac_address[6]; | ||
136 | u8 rx_mask; | ||
137 | u8 tx_mask; | ||
138 | __le16 rf_silent; | ||
139 | __le16 bluetooth_options; | ||
140 | __le16 device_capabilities; | ||
141 | __le32 build_number; | ||
142 | u8 deviceType; | ||
143 | u8 reserved[33]; | ||
144 | |||
145 | u8 customer_data[64]; | ||
146 | |||
147 | struct ar9170_eeprom_modal | ||
148 | modal_header[2]; | ||
149 | |||
150 | u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS]; | ||
151 | u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS]; | ||
152 | |||
153 | struct ar9170_calibration_data_per_freq | ||
154 | cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS], | ||
155 | cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; | ||
156 | |||
157 | /* power calibration data */ | ||
158 | struct ar9170_calibration_target_power_legacy | ||
159 | cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS]; | ||
160 | struct ar9170_calibration_target_power_ht | ||
161 | cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS], | ||
162 | cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS]; | ||
163 | |||
164 | struct ar9170_calibration_target_power_legacy | ||
165 | cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS], | ||
166 | cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS]; | ||
167 | struct ar9170_calibration_target_power_ht | ||
168 | cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS], | ||
169 | cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS]; | ||
170 | |||
171 | /* conformance testing limits */ | ||
172 | u8 ctl_index[AR5416_NUM_CTLS]; | ||
173 | struct ar9170_calctl_data | ||
174 | ctl_data[AR5416_NUM_CTLS]; | ||
175 | |||
176 | u8 pad; | ||
177 | __le16 subsystem_id; | ||
178 | } __packed; | ||
179 | |||
180 | #define AR9170_LED_MODE_POWER_ON 0x0001 | ||
181 | #define AR9170_LED_MODE_RESERVED 0x0002 | ||
182 | #define AR9170_LED_MODE_DISABLE_STATE 0x0004 | ||
183 | #define AR9170_LED_MODE_OFF_IN_PSM 0x0008 | ||
184 | |||
185 | /* AR9170_LED_MODE BIT is set */ | ||
186 | #define AR9170_LED_MODE_FREQUENCY_S 4 | ||
187 | #define AR9170_LED_MODE_FREQUENCY 0x0030 | ||
188 | #define AR9170_LED_MODE_FREQUENCY_1HZ 0x0000 | ||
189 | #define AR9170_LED_MODE_FREQUENCY_0_5HZ 0x0010 | ||
190 | #define AR9170_LED_MODE_FREQUENCY_0_25HZ 0x0020 | ||
191 | #define AR9170_LED_MODE_FREQUENCY_0_125HZ 0x0030 | ||
192 | |||
193 | /* AR9170_LED_MODE BIT is not set */ | ||
194 | #define AR9170_LED_MODE_CONN_STATE_S 4 | ||
195 | #define AR9170_LED_MODE_CONN_STATE 0x0030 | ||
196 | #define AR9170_LED_MODE_CONN_STATE_FORCE_OFF 0x0000 | ||
197 | #define AR9170_LED_MODE_CONN_STATE_FORCE_ON 0x0010 | ||
198 | /* Idle off / Active on */ | ||
199 | #define AR9170_LED_MODE_CONN_STATE_IOFF_AON 0x0020 | ||
200 | /* Idle on / Active off */ | ||
201 | #define AR9170_LED_MODE_CONN_STATE_ION_AOFF 0x0010 | ||
202 | |||
203 | #define AR9170_LED_MODE_MODE 0x0040 | ||
204 | #define AR9170_LED_MODE_RESERVED2 0x0080 | ||
205 | |||
206 | #define AR9170_LED_MODE_TON_SCAN_S 8 | ||
207 | #define AR9170_LED_MODE_TON_SCAN 0x0f00 | ||
208 | |||
209 | #define AR9170_LED_MODE_TOFF_SCAN_S 12 | ||
210 | #define AR9170_LED_MODE_TOFF_SCAN 0xf000 | ||
211 | |||
212 | struct ar9170_led_mode { | ||
213 | __le16 led; | ||
214 | }; | ||
215 | |||
216 | #endif /* __CARL9170_SHARED_EEPROM_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c new file mode 100644 index 000000000000..221957c5d373 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/fw.c | |||
@@ -0,0 +1,435 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * firmware parser | ||
5 | * | ||
6 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/firmware.h> | ||
25 | #include <linux/crc32.h> | ||
26 | #include "carl9170.h" | ||
27 | #include "fwcmd.h" | ||
28 | #include "version.h" | ||
29 | |||
30 | #define MAKE_STR(symbol) #symbol | ||
31 | #define TO_STR(symbol) MAKE_STR(symbol) | ||
32 | #define CARL9170FW_API_VER_STR TO_STR(CARL9170FW_API_MAX_VER) | ||
33 | MODULE_VERSION(CARL9170FW_API_VER_STR ":" CARL9170FW_VERSION_GIT); | ||
34 | |||
35 | static const u8 otus_magic[4] = { OTUS_MAGIC }; | ||
36 | |||
37 | static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4], | ||
38 | const unsigned int len, const u8 compatible_revision) | ||
39 | { | ||
40 | const struct carl9170fw_desc_head *iter; | ||
41 | |||
42 | carl9170fw_for_each_hdr(iter, ar->fw.desc) { | ||
43 | if (carl9170fw_desc_cmp(iter, descid, len, | ||
44 | compatible_revision)) | ||
45 | return (void *)iter; | ||
46 | } | ||
47 | |||
48 | /* needed to find the LAST desc */ | ||
49 | if (carl9170fw_desc_cmp(iter, descid, len, | ||
50 | compatible_revision)) | ||
51 | return (void *)iter; | ||
52 | |||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | static int carl9170_fw_verify_descs(struct ar9170 *ar, | ||
57 | const struct carl9170fw_desc_head *head, unsigned int max_len) | ||
58 | { | ||
59 | const struct carl9170fw_desc_head *pos; | ||
60 | unsigned long pos_addr, end_addr; | ||
61 | unsigned int pos_length; | ||
62 | |||
63 | if (max_len < sizeof(*pos)) | ||
64 | return -ENODATA; | ||
65 | |||
66 | max_len = min_t(unsigned int, CARL9170FW_DESC_MAX_LENGTH, max_len); | ||
67 | |||
68 | pos = head; | ||
69 | pos_addr = (unsigned long) pos; | ||
70 | end_addr = pos_addr + max_len; | ||
71 | |||
72 | while (pos_addr < end_addr) { | ||
73 | if (pos_addr + sizeof(*head) > end_addr) | ||
74 | return -E2BIG; | ||
75 | |||
76 | pos_length = le16_to_cpu(pos->length); | ||
77 | |||
78 | if (pos_length < sizeof(*head)) | ||
79 | return -EBADMSG; | ||
80 | |||
81 | if (pos_length > max_len) | ||
82 | return -EOVERFLOW; | ||
83 | |||
84 | if (pos_addr + pos_length > end_addr) | ||
85 | return -EMSGSIZE; | ||
86 | |||
87 | if (carl9170fw_desc_cmp(pos, LAST_MAGIC, | ||
88 | CARL9170FW_LAST_DESC_SIZE, | ||
89 | CARL9170FW_LAST_DESC_CUR_VER)) | ||
90 | return 0; | ||
91 | |||
92 | pos_addr += pos_length; | ||
93 | pos = (void *)pos_addr; | ||
94 | max_len -= pos_length; | ||
95 | } | ||
96 | return -EINVAL; | ||
97 | } | ||
98 | |||
99 | static void carl9170_fw_info(struct ar9170 *ar) | ||
100 | { | ||
101 | const struct carl9170fw_motd_desc *motd_desc; | ||
102 | unsigned int str_ver_len; | ||
103 | u32 fw_date; | ||
104 | |||
105 | dev_info(&ar->udev->dev, "driver API: %s 2%03d-%02d-%02d [%d-%d]\n", | ||
106 | CARL9170FW_VERSION_GIT, CARL9170FW_VERSION_YEAR, | ||
107 | CARL9170FW_VERSION_MONTH, CARL9170FW_VERSION_DAY, | ||
108 | CARL9170FW_API_MIN_VER, CARL9170FW_API_MAX_VER); | ||
109 | |||
110 | motd_desc = carl9170_fw_find_desc(ar, MOTD_MAGIC, | ||
111 | sizeof(*motd_desc), CARL9170FW_MOTD_DESC_CUR_VER); | ||
112 | |||
113 | if (motd_desc) { | ||
114 | str_ver_len = strnlen(motd_desc->release, | ||
115 | CARL9170FW_MOTD_RELEASE_LEN); | ||
116 | |||
117 | fw_date = le32_to_cpu(motd_desc->fw_year_month_day); | ||
118 | |||
119 | dev_info(&ar->udev->dev, "firmware API: %.*s 2%03d-%02d-%02d\n", | ||
120 | str_ver_len, motd_desc->release, | ||
121 | CARL9170FW_GET_YEAR(fw_date), | ||
122 | CARL9170FW_GET_MONTH(fw_date), | ||
123 | CARL9170FW_GET_DAY(fw_date)); | ||
124 | |||
125 | strlcpy(ar->hw->wiphy->fw_version, motd_desc->release, | ||
126 | sizeof(ar->hw->wiphy->fw_version)); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | static bool valid_dma_addr(const u32 address) | ||
131 | { | ||
132 | if (address >= AR9170_SRAM_OFFSET && | ||
133 | address < (AR9170_SRAM_OFFSET + AR9170_SRAM_SIZE)) | ||
134 | return true; | ||
135 | |||
136 | return false; | ||
137 | } | ||
138 | |||
139 | static bool valid_cpu_addr(const u32 address) | ||
140 | { | ||
141 | if (valid_dma_addr(address) || (address >= AR9170_PRAM_OFFSET && | ||
142 | address < (AR9170_PRAM_OFFSET + AR9170_PRAM_SIZE))) | ||
143 | return true; | ||
144 | |||
145 | return false; | ||
146 | } | ||
147 | |||
148 | static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | ||
149 | { | ||
150 | const struct carl9170fw_otus_desc *otus_desc; | ||
151 | const struct carl9170fw_chk_desc *chk_desc; | ||
152 | const struct carl9170fw_last_desc *last_desc; | ||
153 | const struct carl9170fw_txsq_desc *txsq_desc; | ||
154 | u16 if_comb_types; | ||
155 | |||
156 | last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC, | ||
157 | sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER); | ||
158 | if (!last_desc) | ||
159 | return -EINVAL; | ||
160 | |||
161 | otus_desc = carl9170_fw_find_desc(ar, OTUS_MAGIC, | ||
162 | sizeof(*otus_desc), CARL9170FW_OTUS_DESC_CUR_VER); | ||
163 | if (!otus_desc) { | ||
164 | dev_err(&ar->udev->dev, "failed to find compatible firmware " | ||
165 | "descriptor.\n"); | ||
166 | return -ENODATA; | ||
167 | } | ||
168 | |||
169 | chk_desc = carl9170_fw_find_desc(ar, CHK_MAGIC, | ||
170 | sizeof(*chk_desc), CARL9170FW_CHK_DESC_CUR_VER); | ||
171 | |||
172 | if (chk_desc) { | ||
173 | unsigned long fin, diff; | ||
174 | unsigned int dsc_len; | ||
175 | u32 crc32; | ||
176 | |||
177 | dsc_len = min_t(unsigned int, len, | ||
178 | (unsigned long)chk_desc - (unsigned long)otus_desc); | ||
179 | |||
180 | fin = (unsigned long) last_desc + sizeof(*last_desc); | ||
181 | diff = fin - (unsigned long) otus_desc; | ||
182 | |||
183 | if (diff < len) | ||
184 | len -= diff; | ||
185 | |||
186 | if (len < 256) | ||
187 | return -EIO; | ||
188 | |||
189 | crc32 = crc32_le(~0, data, len); | ||
190 | if (cpu_to_le32(crc32) != chk_desc->fw_crc32) { | ||
191 | dev_err(&ar->udev->dev, "fw checksum test failed.\n"); | ||
192 | return -ENOEXEC; | ||
193 | } | ||
194 | |||
195 | crc32 = crc32_le(crc32, (void *)otus_desc, dsc_len); | ||
196 | if (cpu_to_le32(crc32) != chk_desc->hdr_crc32) { | ||
197 | dev_err(&ar->udev->dev, "descriptor check failed.\n"); | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | } else { | ||
201 | dev_warn(&ar->udev->dev, "Unprotected firmware image.\n"); | ||
202 | } | ||
203 | |||
204 | #define SUPP(feat) \ | ||
205 | (carl9170fw_supports(otus_desc->feature_set, feat)) | ||
206 | |||
207 | if (!SUPP(CARL9170FW_DUMMY_FEATURE)) { | ||
208 | dev_err(&ar->udev->dev, "invalid firmware descriptor " | ||
209 | "format detected.\n"); | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | |||
213 | ar->fw.api_version = otus_desc->api_ver; | ||
214 | |||
215 | if (ar->fw.api_version < CARL9170FW_API_MIN_VER || | ||
216 | ar->fw.api_version > CARL9170FW_API_MAX_VER) { | ||
217 | dev_err(&ar->udev->dev, "unsupported firmware api version.\n"); | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
221 | if (!SUPP(CARL9170FW_COMMAND_PHY) || SUPP(CARL9170FW_UNUSABLE) || | ||
222 | !SUPP(CARL9170FW_HANDLE_BACK_REQ)) { | ||
223 | dev_err(&ar->udev->dev, "firmware does support " | ||
224 | "mandatory features.\n"); | ||
225 | return -ECANCELED; | ||
226 | } | ||
227 | |||
228 | if (ilog2(le32_to_cpu(otus_desc->feature_set)) >= | ||
229 | __CARL9170FW_FEATURE_NUM) { | ||
230 | dev_warn(&ar->udev->dev, "driver does not support all " | ||
231 | "firmware features.\n"); | ||
232 | } | ||
233 | |||
234 | if (!SUPP(CARL9170FW_COMMAND_CAM)) { | ||
235 | dev_info(&ar->udev->dev, "crypto offloading is disabled " | ||
236 | "by firmware.\n"); | ||
237 | ar->disable_offload = true; | ||
238 | } | ||
239 | |||
240 | if (SUPP(CARL9170FW_PSM)) | ||
241 | ar->hw->flags |= IEEE80211_HW_SUPPORTS_PS; | ||
242 | |||
243 | if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) { | ||
244 | dev_err(&ar->udev->dev, "firmware does not provide " | ||
245 | "mandatory interfaces.\n"); | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | if (SUPP(CARL9170FW_MINIBOOT)) | ||
250 | ar->fw.offset = le16_to_cpu(otus_desc->miniboot_size); | ||
251 | else | ||
252 | ar->fw.offset = 0; | ||
253 | |||
254 | if (SUPP(CARL9170FW_USB_DOWN_STREAM)) { | ||
255 | ar->hw->extra_tx_headroom += sizeof(struct ar9170_stream); | ||
256 | ar->fw.tx_stream = true; | ||
257 | } | ||
258 | |||
259 | if (SUPP(CARL9170FW_USB_UP_STREAM)) | ||
260 | ar->fw.rx_stream = true; | ||
261 | |||
262 | if (SUPP(CARL9170FW_RX_FILTER)) { | ||
263 | ar->fw.rx_filter = true; | ||
264 | ar->rx_filter_caps = FIF_FCSFAIL | FIF_PLCPFAIL | | ||
265 | FIF_CONTROL | FIF_PSPOLL | FIF_OTHER_BSS | | ||
266 | FIF_PROMISC_IN_BSS; | ||
267 | } | ||
268 | |||
269 | if (SUPP(CARL9170FW_WOL)) | ||
270 | device_set_wakeup_enable(&ar->udev->dev, true); | ||
271 | |||
272 | if_comb_types = BIT(NL80211_IFTYPE_STATION) | | ||
273 | BIT(NL80211_IFTYPE_P2P_CLIENT); | ||
274 | |||
275 | ar->fw.vif_num = otus_desc->vif_num; | ||
276 | ar->fw.cmd_bufs = otus_desc->cmd_bufs; | ||
277 | ar->fw.address = le32_to_cpu(otus_desc->fw_address); | ||
278 | ar->fw.rx_size = le16_to_cpu(otus_desc->rx_max_frame_len); | ||
279 | ar->fw.mem_blocks = min_t(unsigned int, otus_desc->tx_descs, 0xfe); | ||
280 | atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks); | ||
281 | ar->fw.mem_block_size = le16_to_cpu(otus_desc->tx_frag_len); | ||
282 | |||
283 | if (ar->fw.vif_num >= AR9170_MAX_VIRTUAL_MAC || !ar->fw.vif_num || | ||
284 | ar->fw.mem_blocks < 16 || !ar->fw.cmd_bufs || | ||
285 | ar->fw.mem_block_size < 64 || ar->fw.mem_block_size > 512 || | ||
286 | ar->fw.rx_size > 32768 || ar->fw.rx_size < 4096 || | ||
287 | !valid_cpu_addr(ar->fw.address)) { | ||
288 | dev_err(&ar->udev->dev, "firmware shows obvious signs of " | ||
289 | "malicious tampering.\n"); | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | |||
293 | ar->fw.beacon_addr = le32_to_cpu(otus_desc->bcn_addr); | ||
294 | ar->fw.beacon_max_len = le16_to_cpu(otus_desc->bcn_len); | ||
295 | |||
296 | if (valid_dma_addr(ar->fw.beacon_addr) && ar->fw.beacon_max_len >= | ||
297 | AR9170_MAC_BCN_LENGTH_MAX) { | ||
298 | ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); | ||
299 | |||
300 | if (SUPP(CARL9170FW_WLANTX_CAB)) { | ||
301 | if_comb_types |= | ||
302 | BIT(NL80211_IFTYPE_AP) | | ||
303 | BIT(NL80211_IFTYPE_P2P_GO); | ||
304 | } | ||
305 | } | ||
306 | |||
307 | ar->if_comb_limits[0].max = ar->fw.vif_num; | ||
308 | ar->if_comb_limits[0].types = if_comb_types; | ||
309 | |||
310 | ar->if_combs[0].num_different_channels = 1; | ||
311 | ar->if_combs[0].max_interfaces = ar->fw.vif_num; | ||
312 | ar->if_combs[0].limits = ar->if_comb_limits; | ||
313 | ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits); | ||
314 | |||
315 | ar->hw->wiphy->iface_combinations = ar->if_combs; | ||
316 | ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs); | ||
317 | |||
318 | ar->hw->wiphy->interface_modes |= if_comb_types; | ||
319 | |||
320 | txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC, | ||
321 | sizeof(*txsq_desc), CARL9170FW_TXSQ_DESC_CUR_VER); | ||
322 | |||
323 | if (txsq_desc) { | ||
324 | ar->fw.tx_seq_table = le32_to_cpu(txsq_desc->seq_table_addr); | ||
325 | if (!valid_cpu_addr(ar->fw.tx_seq_table)) | ||
326 | return -EINVAL; | ||
327 | } else { | ||
328 | ar->fw.tx_seq_table = 0; | ||
329 | } | ||
330 | |||
331 | #undef SUPPORTED | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static struct carl9170fw_desc_head * | ||
336 | carl9170_find_fw_desc(struct ar9170 *ar, const __u8 *fw_data, const size_t len) | ||
337 | |||
338 | { | ||
339 | int scan = 0, found = 0; | ||
340 | |||
341 | if (!carl9170fw_size_check(len)) { | ||
342 | dev_err(&ar->udev->dev, "firmware size is out of bound.\n"); | ||
343 | return NULL; | ||
344 | } | ||
345 | |||
346 | while (scan < len - sizeof(struct carl9170fw_desc_head)) { | ||
347 | if (fw_data[scan++] == otus_magic[found]) | ||
348 | found++; | ||
349 | else | ||
350 | found = 0; | ||
351 | |||
352 | if (scan >= len) | ||
353 | break; | ||
354 | |||
355 | if (found == sizeof(otus_magic)) | ||
356 | break; | ||
357 | } | ||
358 | |||
359 | if (found != sizeof(otus_magic)) | ||
360 | return NULL; | ||
361 | |||
362 | return (void *)&fw_data[scan - found]; | ||
363 | } | ||
364 | |||
365 | int carl9170_fw_fix_eeprom(struct ar9170 *ar) | ||
366 | { | ||
367 | const struct carl9170fw_fix_desc *fix_desc = NULL; | ||
368 | unsigned int i, n, off; | ||
369 | u32 *data = (void *)&ar->eeprom; | ||
370 | |||
371 | fix_desc = carl9170_fw_find_desc(ar, FIX_MAGIC, | ||
372 | sizeof(*fix_desc), CARL9170FW_FIX_DESC_CUR_VER); | ||
373 | |||
374 | if (!fix_desc) | ||
375 | return 0; | ||
376 | |||
377 | n = (le16_to_cpu(fix_desc->head.length) - sizeof(*fix_desc)) / | ||
378 | sizeof(struct carl9170fw_fix_entry); | ||
379 | |||
380 | for (i = 0; i < n; i++) { | ||
381 | off = le32_to_cpu(fix_desc->data[i].address) - | ||
382 | AR9170_EEPROM_START; | ||
383 | |||
384 | if (off >= sizeof(struct ar9170_eeprom) || (off & 3)) { | ||
385 | dev_err(&ar->udev->dev, "Skip invalid entry %d\n", i); | ||
386 | continue; | ||
387 | } | ||
388 | |||
389 | data[off / sizeof(*data)] &= | ||
390 | le32_to_cpu(fix_desc->data[i].mask); | ||
391 | data[off / sizeof(*data)] |= | ||
392 | le32_to_cpu(fix_desc->data[i].value); | ||
393 | } | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | int carl9170_parse_firmware(struct ar9170 *ar) | ||
399 | { | ||
400 | const struct carl9170fw_desc_head *fw_desc = NULL; | ||
401 | const struct firmware *fw = ar->fw.fw; | ||
402 | unsigned long header_offset = 0; | ||
403 | int err; | ||
404 | |||
405 | if (WARN_ON(!fw)) | ||
406 | return -EINVAL; | ||
407 | |||
408 | fw_desc = carl9170_find_fw_desc(ar, fw->data, fw->size); | ||
409 | |||
410 | if (!fw_desc) { | ||
411 | dev_err(&ar->udev->dev, "unsupported firmware.\n"); | ||
412 | return -ENODATA; | ||
413 | } | ||
414 | |||
415 | header_offset = (unsigned long)fw_desc - (unsigned long)fw->data; | ||
416 | |||
417 | err = carl9170_fw_verify_descs(ar, fw_desc, fw->size - header_offset); | ||
418 | if (err) { | ||
419 | dev_err(&ar->udev->dev, "damaged firmware (%d).\n", err); | ||
420 | return err; | ||
421 | } | ||
422 | |||
423 | ar->fw.desc = fw_desc; | ||
424 | |||
425 | carl9170_fw_info(ar); | ||
426 | |||
427 | err = carl9170_fw(ar, fw->data, fw->size); | ||
428 | if (err) { | ||
429 | dev_err(&ar->udev->dev, "failed to parse firmware (%d).\n", | ||
430 | err); | ||
431 | return err; | ||
432 | } | ||
433 | |||
434 | return 0; | ||
435 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h new file mode 100644 index 000000000000..30449d21b762 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h | |||
@@ -0,0 +1,290 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * Firmware command interface definitions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #ifndef __CARL9170_SHARED_FWCMD_H | ||
40 | #define __CARL9170_SHARED_FWCMD_H | ||
41 | |||
42 | #define CARL9170_MAX_CMD_LEN 64 | ||
43 | #define CARL9170_MAX_CMD_PAYLOAD_LEN 60 | ||
44 | |||
45 | #define CARL9170FW_API_MIN_VER 1 | ||
46 | #define CARL9170FW_API_MAX_VER 1 | ||
47 | |||
48 | enum carl9170_cmd_oids { | ||
49 | CARL9170_CMD_RREG = 0x00, | ||
50 | CARL9170_CMD_WREG = 0x01, | ||
51 | CARL9170_CMD_ECHO = 0x02, | ||
52 | CARL9170_CMD_SWRST = 0x03, | ||
53 | CARL9170_CMD_REBOOT = 0x04, | ||
54 | CARL9170_CMD_BCN_CTRL = 0x05, | ||
55 | CARL9170_CMD_READ_TSF = 0x06, | ||
56 | CARL9170_CMD_RX_FILTER = 0x07, | ||
57 | |||
58 | /* CAM */ | ||
59 | CARL9170_CMD_EKEY = 0x10, | ||
60 | CARL9170_CMD_DKEY = 0x11, | ||
61 | |||
62 | /* RF / PHY */ | ||
63 | CARL9170_CMD_FREQUENCY = 0x20, | ||
64 | CARL9170_CMD_RF_INIT = 0x21, | ||
65 | CARL9170_CMD_SYNTH = 0x22, | ||
66 | CARL9170_CMD_FREQ_START = 0x23, | ||
67 | CARL9170_CMD_PSM = 0x24, | ||
68 | |||
69 | /* Asychronous command flag */ | ||
70 | CARL9170_CMD_ASYNC_FLAG = 0x40, | ||
71 | CARL9170_CMD_WREG_ASYNC = (CARL9170_CMD_WREG | | ||
72 | CARL9170_CMD_ASYNC_FLAG), | ||
73 | CARL9170_CMD_REBOOT_ASYNC = (CARL9170_CMD_REBOOT | | ||
74 | CARL9170_CMD_ASYNC_FLAG), | ||
75 | CARL9170_CMD_BCN_CTRL_ASYNC = (CARL9170_CMD_BCN_CTRL | | ||
76 | CARL9170_CMD_ASYNC_FLAG), | ||
77 | CARL9170_CMD_PSM_ASYNC = (CARL9170_CMD_PSM | | ||
78 | CARL9170_CMD_ASYNC_FLAG), | ||
79 | |||
80 | /* responses and traps */ | ||
81 | CARL9170_RSP_FLAG = 0xc0, | ||
82 | CARL9170_RSP_PRETBTT = 0xc0, | ||
83 | CARL9170_RSP_TXCOMP = 0xc1, | ||
84 | CARL9170_RSP_BEACON_CONFIG = 0xc2, | ||
85 | CARL9170_RSP_ATIM = 0xc3, | ||
86 | CARL9170_RSP_WATCHDOG = 0xc6, | ||
87 | CARL9170_RSP_TEXT = 0xca, | ||
88 | CARL9170_RSP_HEXDUMP = 0xcc, | ||
89 | CARL9170_RSP_RADAR = 0xcd, | ||
90 | CARL9170_RSP_GPIO = 0xce, | ||
91 | CARL9170_RSP_BOOT = 0xcf, | ||
92 | }; | ||
93 | |||
94 | struct carl9170_set_key_cmd { | ||
95 | __le16 user; | ||
96 | __le16 keyId; | ||
97 | __le16 type; | ||
98 | u8 macAddr[6]; | ||
99 | u32 key[4]; | ||
100 | } __packed __aligned(4); | ||
101 | #define CARL9170_SET_KEY_CMD_SIZE 28 | ||
102 | |||
103 | struct carl9170_disable_key_cmd { | ||
104 | __le16 user; | ||
105 | __le16 padding; | ||
106 | } __packed __aligned(4); | ||
107 | #define CARL9170_DISABLE_KEY_CMD_SIZE 4 | ||
108 | |||
109 | struct carl9170_u32_list { | ||
110 | u32 vals[0]; | ||
111 | } __packed; | ||
112 | |||
113 | struct carl9170_reg_list { | ||
114 | __le32 regs[0]; | ||
115 | } __packed; | ||
116 | |||
117 | struct carl9170_write_reg { | ||
118 | struct { | ||
119 | __le32 addr; | ||
120 | __le32 val; | ||
121 | } regs[0] __packed; | ||
122 | } __packed; | ||
123 | |||
124 | #define CARL9170FW_PHY_HT_ENABLE 0x4 | ||
125 | #define CARL9170FW_PHY_HT_DYN2040 0x8 | ||
126 | #define CARL9170FW_PHY_HT_EXT_CHAN_OFF 0x3 | ||
127 | #define CARL9170FW_PHY_HT_EXT_CHAN_OFF_S 2 | ||
128 | |||
129 | struct carl9170_rf_init { | ||
130 | __le32 freq; | ||
131 | u8 ht_settings; | ||
132 | u8 padding2[3]; | ||
133 | __le32 delta_slope_coeff_exp; | ||
134 | __le32 delta_slope_coeff_man; | ||
135 | __le32 delta_slope_coeff_exp_shgi; | ||
136 | __le32 delta_slope_coeff_man_shgi; | ||
137 | __le32 finiteLoopCount; | ||
138 | } __packed; | ||
139 | #define CARL9170_RF_INIT_SIZE 28 | ||
140 | |||
141 | struct carl9170_rf_init_result { | ||
142 | __le32 ret; /* AR9170_PHY_REG_AGC_CONTROL */ | ||
143 | } __packed; | ||
144 | #define CARL9170_RF_INIT_RESULT_SIZE 4 | ||
145 | |||
146 | #define CARL9170_PSM_SLEEP 0x1000 | ||
147 | #define CARL9170_PSM_SOFTWARE 0 | ||
148 | #define CARL9170_PSM_WAKE 0 /* internally used. */ | ||
149 | #define CARL9170_PSM_COUNTER 0xfff | ||
150 | #define CARL9170_PSM_COUNTER_S 0 | ||
151 | |||
152 | struct carl9170_psm { | ||
153 | __le32 state; | ||
154 | } __packed; | ||
155 | #define CARL9170_PSM_SIZE 4 | ||
156 | |||
157 | struct carl9170_rx_filter_cmd { | ||
158 | __le32 rx_filter; | ||
159 | } __packed; | ||
160 | #define CARL9170_RX_FILTER_CMD_SIZE 4 | ||
161 | |||
162 | #define CARL9170_RX_FILTER_BAD 0x01 | ||
163 | #define CARL9170_RX_FILTER_OTHER_RA 0x02 | ||
164 | #define CARL9170_RX_FILTER_DECRY_FAIL 0x04 | ||
165 | #define CARL9170_RX_FILTER_CTL_OTHER 0x08 | ||
166 | #define CARL9170_RX_FILTER_CTL_PSPOLL 0x10 | ||
167 | #define CARL9170_RX_FILTER_CTL_BACKR 0x20 | ||
168 | #define CARL9170_RX_FILTER_MGMT 0x40 | ||
169 | #define CARL9170_RX_FILTER_DATA 0x80 | ||
170 | #define CARL9170_RX_FILTER_EVERYTHING (~0) | ||
171 | |||
172 | struct carl9170_bcn_ctrl_cmd { | ||
173 | __le32 vif_id; | ||
174 | __le32 mode; | ||
175 | __le32 bcn_addr; | ||
176 | __le32 bcn_len; | ||
177 | } __packed; | ||
178 | #define CARL9170_BCN_CTRL_CMD_SIZE 16 | ||
179 | |||
180 | #define CARL9170_BCN_CTRL_DRAIN 0 | ||
181 | #define CARL9170_BCN_CTRL_CAB_TRIGGER 1 | ||
182 | |||
183 | struct carl9170_cmd_head { | ||
184 | union { | ||
185 | struct { | ||
186 | u8 len; | ||
187 | u8 cmd; | ||
188 | u8 seq; | ||
189 | u8 ext; | ||
190 | } __packed; | ||
191 | |||
192 | u32 hdr_data; | ||
193 | } __packed; | ||
194 | } __packed; | ||
195 | |||
196 | struct carl9170_cmd { | ||
197 | struct carl9170_cmd_head hdr; | ||
198 | union { | ||
199 | struct carl9170_set_key_cmd setkey; | ||
200 | struct carl9170_disable_key_cmd disablekey; | ||
201 | struct carl9170_u32_list echo; | ||
202 | struct carl9170_reg_list rreg; | ||
203 | struct carl9170_write_reg wreg; | ||
204 | struct carl9170_rf_init rf_init; | ||
205 | struct carl9170_psm psm; | ||
206 | struct carl9170_bcn_ctrl_cmd bcn_ctrl; | ||
207 | struct carl9170_rx_filter_cmd rx_filter; | ||
208 | u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; | ||
209 | } __packed; | ||
210 | } __packed __aligned(4); | ||
211 | |||
212 | #define CARL9170_TX_STATUS_QUEUE 3 | ||
213 | #define CARL9170_TX_STATUS_QUEUE_S 0 | ||
214 | #define CARL9170_TX_STATUS_RIX_S 2 | ||
215 | #define CARL9170_TX_STATUS_RIX (3 << CARL9170_TX_STATUS_RIX_S) | ||
216 | #define CARL9170_TX_STATUS_TRIES_S 4 | ||
217 | #define CARL9170_TX_STATUS_TRIES (7 << CARL9170_TX_STATUS_TRIES_S) | ||
218 | #define CARL9170_TX_STATUS_SUCCESS 0x80 | ||
219 | |||
220 | #ifdef __CARL9170FW__ | ||
221 | /* | ||
222 | * NOTE: | ||
223 | * Both structs [carl9170_tx_status and _carl9170_tx_status] | ||
224 | * need to be "bit for bit" in sync. | ||
225 | */ | ||
226 | struct carl9170_tx_status { | ||
227 | /* | ||
228 | * Beware of compiler bugs in all gcc pre 4.4! | ||
229 | */ | ||
230 | |||
231 | u8 cookie; | ||
232 | u8 queue:2; | ||
233 | u8 rix:2; | ||
234 | u8 tries:3; | ||
235 | u8 success:1; | ||
236 | } __packed; | ||
237 | #endif /* __CARL9170FW__ */ | ||
238 | |||
239 | struct _carl9170_tx_status { | ||
240 | /* | ||
241 | * This version should be immune to all alignment bugs. | ||
242 | */ | ||
243 | |||
244 | u8 cookie; | ||
245 | u8 info; | ||
246 | } __packed; | ||
247 | #define CARL9170_TX_STATUS_SIZE 2 | ||
248 | |||
249 | #define CARL9170_RSP_TX_STATUS_NUM (CARL9170_MAX_CMD_PAYLOAD_LEN / \ | ||
250 | sizeof(struct _carl9170_tx_status)) | ||
251 | |||
252 | #define CARL9170_TX_MAX_RATE_TRIES 7 | ||
253 | |||
254 | #define CARL9170_TX_MAX_RATES 4 | ||
255 | #define CARL9170_TX_MAX_RETRY_RATES (CARL9170_TX_MAX_RATES - 1) | ||
256 | #define CARL9170_ERR_MAGIC "ERR:" | ||
257 | #define CARL9170_BUG_MAGIC "BUG:" | ||
258 | |||
259 | struct carl9170_gpio { | ||
260 | __le32 gpio; | ||
261 | } __packed; | ||
262 | #define CARL9170_GPIO_SIZE 4 | ||
263 | |||
264 | struct carl9170_tsf_rsp { | ||
265 | union { | ||
266 | __le32 tsf[2]; | ||
267 | __le64 tsf_64; | ||
268 | } __packed; | ||
269 | } __packed; | ||
270 | #define CARL9170_TSF_RSP_SIZE 8 | ||
271 | |||
272 | struct carl9170_rsp { | ||
273 | struct carl9170_cmd_head hdr; | ||
274 | |||
275 | union { | ||
276 | struct carl9170_rf_init_result rf_init_res; | ||
277 | struct carl9170_u32_list rreg_res; | ||
278 | struct carl9170_u32_list echo; | ||
279 | #ifdef __CARL9170FW__ | ||
280 | struct carl9170_tx_status tx_status[0]; | ||
281 | #endif /* __CARL9170FW__ */ | ||
282 | struct _carl9170_tx_status _tx_status[0]; | ||
283 | struct carl9170_gpio gpio; | ||
284 | struct carl9170_tsf_rsp tsf; | ||
285 | struct carl9170_psm psm; | ||
286 | u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; | ||
287 | } __packed; | ||
288 | } __packed __aligned(4); | ||
289 | |||
290 | #endif /* __CARL9170_SHARED_FWCMD_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h new file mode 100644 index 000000000000..921066822dd5 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/fwdesc.h | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * Shared CARL9170 Header | ||
3 | * | ||
4 | * Firmware descriptor format | ||
5 | * | ||
6 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; see the file COPYING. If not, see | ||
19 | * http://www.gnu.org/licenses/. | ||
20 | */ | ||
21 | |||
22 | #ifndef __CARL9170_SHARED_FWDESC_H | ||
23 | #define __CARL9170_SHARED_FWDESC_H | ||
24 | |||
25 | /* NOTE: Don't mess with the order of the flags! */ | ||
26 | enum carl9170fw_feature_list { | ||
27 | /* Always set */ | ||
28 | CARL9170FW_DUMMY_FEATURE, | ||
29 | |||
30 | /* | ||
31 | * Indicates that this image has special boot block which prevents | ||
32 | * legacy drivers to drive the firmware. | ||
33 | */ | ||
34 | CARL9170FW_MINIBOOT, | ||
35 | |||
36 | /* usb registers are initialized by the firmware */ | ||
37 | CARL9170FW_USB_INIT_FIRMWARE, | ||
38 | |||
39 | /* command traps & notifications are send through EP2 */ | ||
40 | CARL9170FW_USB_RESP_EP2, | ||
41 | |||
42 | /* usb download (app -> fw) stream */ | ||
43 | CARL9170FW_USB_DOWN_STREAM, | ||
44 | |||
45 | /* usb upload (fw -> app) stream */ | ||
46 | CARL9170FW_USB_UP_STREAM, | ||
47 | |||
48 | /* unusable - reserved to flag non-functional debug firmwares */ | ||
49 | CARL9170FW_UNUSABLE, | ||
50 | |||
51 | /* AR9170_CMD_RF_INIT, AR9170_CMD_FREQ_START, AR9170_CMD_FREQUENCY */ | ||
52 | CARL9170FW_COMMAND_PHY, | ||
53 | |||
54 | /* AR9170_CMD_EKEY, AR9170_CMD_DKEY */ | ||
55 | CARL9170FW_COMMAND_CAM, | ||
56 | |||
57 | /* Firmware has a software Content After Beacon Queueing mechanism */ | ||
58 | CARL9170FW_WLANTX_CAB, | ||
59 | |||
60 | /* The firmware is capable of responding to incoming BAR frames */ | ||
61 | CARL9170FW_HANDLE_BACK_REQ, | ||
62 | |||
63 | /* GPIO Interrupt | CARL9170_RSP_GPIO */ | ||
64 | CARL9170FW_GPIO_INTERRUPT, | ||
65 | |||
66 | /* Firmware PSM support | CARL9170_CMD_PSM */ | ||
67 | CARL9170FW_PSM, | ||
68 | |||
69 | /* Firmware RX filter | CARL9170_CMD_RX_FILTER */ | ||
70 | CARL9170FW_RX_FILTER, | ||
71 | |||
72 | /* Wake up on WLAN */ | ||
73 | CARL9170FW_WOL, | ||
74 | |||
75 | /* KEEP LAST */ | ||
76 | __CARL9170FW_FEATURE_NUM | ||
77 | }; | ||
78 | |||
79 | #define OTUS_MAGIC "OTAR" | ||
80 | #define MOTD_MAGIC "MOTD" | ||
81 | #define FIX_MAGIC "FIX\0" | ||
82 | #define DBG_MAGIC "DBG\0" | ||
83 | #define CHK_MAGIC "CHK\0" | ||
84 | #define TXSQ_MAGIC "TXSQ" | ||
85 | #define LAST_MAGIC "LAST" | ||
86 | |||
87 | #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31) | ||
88 | #define CARL9170FW_SET_MONTH(m) ((((m) - 1) % 12) * 31) | ||
89 | #define CARL9170FW_SET_YEAR(y) (((y) - 10) * 372) | ||
90 | |||
91 | #define CARL9170FW_GET_DAY(d) (((d) % 31) + 1) | ||
92 | #define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1) | ||
93 | #define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10) | ||
94 | |||
95 | #define CARL9170FW_MAGIC_SIZE 4 | ||
96 | |||
97 | struct carl9170fw_desc_head { | ||
98 | u8 magic[CARL9170FW_MAGIC_SIZE]; | ||
99 | __le16 length; | ||
100 | u8 min_ver; | ||
101 | u8 cur_ver; | ||
102 | } __packed; | ||
103 | #define CARL9170FW_DESC_HEAD_SIZE \ | ||
104 | (sizeof(struct carl9170fw_desc_head)) | ||
105 | |||
106 | #define CARL9170FW_OTUS_DESC_MIN_VER 6 | ||
107 | #define CARL9170FW_OTUS_DESC_CUR_VER 6 | ||
108 | struct carl9170fw_otus_desc { | ||
109 | struct carl9170fw_desc_head head; | ||
110 | __le32 feature_set; | ||
111 | __le32 fw_address; | ||
112 | __le32 bcn_addr; | ||
113 | __le16 bcn_len; | ||
114 | __le16 miniboot_size; | ||
115 | __le16 tx_frag_len; | ||
116 | __le16 rx_max_frame_len; | ||
117 | u8 tx_descs; | ||
118 | u8 cmd_bufs; | ||
119 | u8 api_ver; | ||
120 | u8 vif_num; | ||
121 | } __packed; | ||
122 | #define CARL9170FW_OTUS_DESC_SIZE \ | ||
123 | (sizeof(struct carl9170fw_otus_desc)) | ||
124 | |||
125 | #define CARL9170FW_MOTD_STRING_LEN 24 | ||
126 | #define CARL9170FW_MOTD_RELEASE_LEN 20 | ||
127 | #define CARL9170FW_MOTD_DESC_MIN_VER 1 | ||
128 | #define CARL9170FW_MOTD_DESC_CUR_VER 2 | ||
129 | struct carl9170fw_motd_desc { | ||
130 | struct carl9170fw_desc_head head; | ||
131 | __le32 fw_year_month_day; | ||
132 | char desc[CARL9170FW_MOTD_STRING_LEN]; | ||
133 | char release[CARL9170FW_MOTD_RELEASE_LEN]; | ||
134 | } __packed; | ||
135 | #define CARL9170FW_MOTD_DESC_SIZE \ | ||
136 | (sizeof(struct carl9170fw_motd_desc)) | ||
137 | |||
138 | #define CARL9170FW_FIX_DESC_MIN_VER 1 | ||
139 | #define CARL9170FW_FIX_DESC_CUR_VER 2 | ||
140 | struct carl9170fw_fix_entry { | ||
141 | __le32 address; | ||
142 | __le32 mask; | ||
143 | __le32 value; | ||
144 | } __packed; | ||
145 | |||
146 | struct carl9170fw_fix_desc { | ||
147 | struct carl9170fw_desc_head head; | ||
148 | struct carl9170fw_fix_entry data[0]; | ||
149 | } __packed; | ||
150 | #define CARL9170FW_FIX_DESC_SIZE \ | ||
151 | (sizeof(struct carl9170fw_fix_desc)) | ||
152 | |||
153 | #define CARL9170FW_DBG_DESC_MIN_VER 1 | ||
154 | #define CARL9170FW_DBG_DESC_CUR_VER 3 | ||
155 | struct carl9170fw_dbg_desc { | ||
156 | struct carl9170fw_desc_head head; | ||
157 | |||
158 | __le32 bogoclock_addr; | ||
159 | __le32 counter_addr; | ||
160 | __le32 rx_total_addr; | ||
161 | __le32 rx_overrun_addr; | ||
162 | __le32 rx_filter; | ||
163 | |||
164 | /* Put your debugging definitions here */ | ||
165 | } __packed; | ||
166 | #define CARL9170FW_DBG_DESC_SIZE \ | ||
167 | (sizeof(struct carl9170fw_dbg_desc)) | ||
168 | |||
169 | #define CARL9170FW_CHK_DESC_MIN_VER 1 | ||
170 | #define CARL9170FW_CHK_DESC_CUR_VER 2 | ||
171 | struct carl9170fw_chk_desc { | ||
172 | struct carl9170fw_desc_head head; | ||
173 | __le32 fw_crc32; | ||
174 | __le32 hdr_crc32; | ||
175 | } __packed; | ||
176 | #define CARL9170FW_CHK_DESC_SIZE \ | ||
177 | (sizeof(struct carl9170fw_chk_desc)) | ||
178 | |||
179 | #define CARL9170FW_TXSQ_DESC_MIN_VER 1 | ||
180 | #define CARL9170FW_TXSQ_DESC_CUR_VER 1 | ||
181 | struct carl9170fw_txsq_desc { | ||
182 | struct carl9170fw_desc_head head; | ||
183 | |||
184 | __le32 seq_table_addr; | ||
185 | } __packed; | ||
186 | #define CARL9170FW_TXSQ_DESC_SIZE \ | ||
187 | (sizeof(struct carl9170fw_txsq_desc)) | ||
188 | |||
189 | #define CARL9170FW_LAST_DESC_MIN_VER 1 | ||
190 | #define CARL9170FW_LAST_DESC_CUR_VER 2 | ||
191 | struct carl9170fw_last_desc { | ||
192 | struct carl9170fw_desc_head head; | ||
193 | } __packed; | ||
194 | #define CARL9170FW_LAST_DESC_SIZE \ | ||
195 | (sizeof(struct carl9170fw_fix_desc)) | ||
196 | |||
197 | #define CARL9170FW_DESC_MAX_LENGTH 8192 | ||
198 | |||
199 | #define CARL9170FW_FILL_DESC(_magic, _length, _min_ver, _cur_ver) \ | ||
200 | .head = { \ | ||
201 | .magic = _magic, \ | ||
202 | .length = cpu_to_le16(_length), \ | ||
203 | .min_ver = _min_ver, \ | ||
204 | .cur_ver = _cur_ver, \ | ||
205 | } | ||
206 | |||
207 | static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head, | ||
208 | u8 magic[CARL9170FW_MAGIC_SIZE], | ||
209 | __le16 length, u8 min_ver, u8 cur_ver) | ||
210 | { | ||
211 | head->magic[0] = magic[0]; | ||
212 | head->magic[1] = magic[1]; | ||
213 | head->magic[2] = magic[2]; | ||
214 | head->magic[3] = magic[3]; | ||
215 | |||
216 | head->length = length; | ||
217 | head->min_ver = min_ver; | ||
218 | head->cur_ver = cur_ver; | ||
219 | } | ||
220 | |||
221 | #define carl9170fw_for_each_hdr(desc, fw_desc) \ | ||
222 | for (desc = fw_desc; \ | ||
223 | memcmp(desc->magic, LAST_MAGIC, CARL9170FW_MAGIC_SIZE) && \ | ||
224 | le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE && \ | ||
225 | le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH; \ | ||
226 | desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length))) | ||
227 | |||
228 | #define CHECK_HDR_VERSION(head, _min_ver) \ | ||
229 | (((head)->cur_ver < _min_ver) || ((head)->min_ver > _min_ver)) \ | ||
230 | |||
231 | static inline bool carl9170fw_supports(__le32 list, u8 feature) | ||
232 | { | ||
233 | return le32_to_cpu(list) & BIT(feature); | ||
234 | } | ||
235 | |||
236 | static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head, | ||
237 | const u8 descid[CARL9170FW_MAGIC_SIZE], | ||
238 | u16 min_len, u8 compatible_revision) | ||
239 | { | ||
240 | if (descid[0] == head->magic[0] && descid[1] == head->magic[1] && | ||
241 | descid[2] == head->magic[2] && descid[3] == head->magic[3] && | ||
242 | !CHECK_HDR_VERSION(head, compatible_revision) && | ||
243 | (le16_to_cpu(head->length) >= min_len)) | ||
244 | return true; | ||
245 | |||
246 | return false; | ||
247 | } | ||
248 | |||
249 | #define CARL9170FW_MIN_SIZE 32 | ||
250 | #define CARL9170FW_MAX_SIZE 16384 | ||
251 | |||
252 | static inline bool carl9170fw_size_check(unsigned int len) | ||
253 | { | ||
254 | return (len <= CARL9170FW_MAX_SIZE && len >= CARL9170FW_MIN_SIZE); | ||
255 | } | ||
256 | |||
257 | #endif /* __CARL9170_SHARED_FWDESC_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h new file mode 100644 index 000000000000..4e30762dd903 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/hw.h | |||
@@ -0,0 +1,769 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * Register map, hardware-specific definitions | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #ifndef __CARL9170_SHARED_HW_H | ||
40 | #define __CARL9170_SHARED_HW_H | ||
41 | |||
42 | /* High Speed UART */ | ||
43 | #define AR9170_UART_REG_BASE 0x1c0000 | ||
44 | |||
45 | /* Definitions of interrupt registers */ | ||
46 | #define AR9170_UART_REG_RX_BUFFER (AR9170_UART_REG_BASE + 0x000) | ||
47 | #define AR9170_UART_REG_TX_HOLDING (AR9170_UART_REG_BASE + 0x004) | ||
48 | #define AR9170_UART_REG_FIFO_CONTROL (AR9170_UART_REG_BASE + 0x010) | ||
49 | #define AR9170_UART_FIFO_CTRL_RESET_RX_FIFO 0x02 | ||
50 | #define AR9170_UART_FIFO_CTRL_RESET_TX_FIFO 0x04 | ||
51 | |||
52 | #define AR9170_UART_REG_LINE_CONTROL (AR9170_UART_REG_BASE + 0x014) | ||
53 | #define AR9170_UART_REG_MODEM_CONTROL (AR9170_UART_REG_BASE + 0x018) | ||
54 | #define AR9170_UART_MODEM_CTRL_DTR_BIT 0x01 | ||
55 | #define AR9170_UART_MODEM_CTRL_RTS_BIT 0x02 | ||
56 | #define AR9170_UART_MODEM_CTRL_INTERNAL_LOOP_BACK 0x10 | ||
57 | #define AR9170_UART_MODEM_CTRL_AUTO_RTS 0x20 | ||
58 | #define AR9170_UART_MODEM_CTRL_AUTO_CTR 0x40 | ||
59 | |||
60 | #define AR9170_UART_REG_LINE_STATUS (AR9170_UART_REG_BASE + 0x01c) | ||
61 | #define AR9170_UART_LINE_STS_RX_DATA_READY 0x01 | ||
62 | #define AR9170_UART_LINE_STS_RX_BUFFER_OVERRUN 0x02 | ||
63 | #define AR9170_UART_LINE_STS_RX_BREAK_IND 0x10 | ||
64 | #define AR9170_UART_LINE_STS_TX_FIFO_NEAR_EMPTY 0x20 | ||
65 | #define AR9170_UART_LINE_STS_TRANSMITTER_EMPTY 0x40 | ||
66 | |||
67 | #define AR9170_UART_REG_MODEM_STATUS (AR9170_UART_REG_BASE + 0x020) | ||
68 | #define AR9170_UART_MODEM_STS_CTS_CHANGE 0x01 | ||
69 | #define AR9170_UART_MODEM_STS_DSR_CHANGE 0x02 | ||
70 | #define AR9170_UART_MODEM_STS_DCD_CHANGE 0x08 | ||
71 | #define AR9170_UART_MODEM_STS_CTS_COMPL 0x10 | ||
72 | #define AR9170_UART_MODEM_STS_DSR_COMPL 0x20 | ||
73 | #define AR9170_UART_MODEM_STS_DCD_COMPL 0x80 | ||
74 | |||
75 | #define AR9170_UART_REG_SCRATCH (AR9170_UART_REG_BASE + 0x024) | ||
76 | #define AR9170_UART_REG_DIVISOR_LSB (AR9170_UART_REG_BASE + 0x028) | ||
77 | #define AR9170_UART_REG_DIVISOR_MSB (AR9170_UART_REG_BASE + 0x02c) | ||
78 | #define AR9170_UART_REG_WORD_RX_BUFFER (AR9170_UART_REG_BASE + 0x034) | ||
79 | #define AR9170_UART_REG_WORD_TX_HOLDING (AR9170_UART_REG_BASE + 0x038) | ||
80 | #define AR9170_UART_REG_FIFO_COUNT (AR9170_UART_REG_BASE + 0x03c) | ||
81 | #define AR9170_UART_REG_REMAINDER (AR9170_UART_REG_BASE + 0x04c) | ||
82 | |||
83 | /* Timer */ | ||
84 | #define AR9170_TIMER_REG_BASE 0x1c1000 | ||
85 | |||
86 | #define AR9170_TIMER_REG_WATCH_DOG (AR9170_TIMER_REG_BASE + 0x000) | ||
87 | #define AR9170_TIMER_REG_TIMER0 (AR9170_TIMER_REG_BASE + 0x010) | ||
88 | #define AR9170_TIMER_REG_TIMER1 (AR9170_TIMER_REG_BASE + 0x014) | ||
89 | #define AR9170_TIMER_REG_TIMER2 (AR9170_TIMER_REG_BASE + 0x018) | ||
90 | #define AR9170_TIMER_REG_TIMER3 (AR9170_TIMER_REG_BASE + 0x01c) | ||
91 | #define AR9170_TIMER_REG_TIMER4 (AR9170_TIMER_REG_BASE + 0x020) | ||
92 | #define AR9170_TIMER_REG_CONTROL (AR9170_TIMER_REG_BASE + 0x024) | ||
93 | #define AR9170_TIMER_CTRL_DISABLE_CLOCK 0x100 | ||
94 | |||
95 | #define AR9170_TIMER_REG_INTERRUPT (AR9170_TIMER_REG_BASE + 0x028) | ||
96 | #define AR9170_TIMER_INT_TIMER0 0x001 | ||
97 | #define AR9170_TIMER_INT_TIMER1 0x002 | ||
98 | #define AR9170_TIMER_INT_TIMER2 0x004 | ||
99 | #define AR9170_TIMER_INT_TIMER3 0x008 | ||
100 | #define AR9170_TIMER_INT_TIMER4 0x010 | ||
101 | #define AR9170_TIMER_INT_TICK_TIMER 0x100 | ||
102 | |||
103 | #define AR9170_TIMER_REG_TICK_TIMER (AR9170_TIMER_REG_BASE + 0x030) | ||
104 | #define AR9170_TIMER_REG_CLOCK_LOW (AR9170_TIMER_REG_BASE + 0x040) | ||
105 | #define AR9170_TIMER_REG_CLOCK_HIGH (AR9170_TIMER_REG_BASE + 0x044) | ||
106 | |||
107 | #define AR9170_MAC_REG_BASE 0x1c3000 | ||
108 | |||
109 | #define AR9170_MAC_REG_POWER_STATE_CTRL (AR9170_MAC_REG_BASE + 0x500) | ||
110 | #define AR9170_MAC_POWER_STATE_CTRL_RESET 0x20 | ||
111 | |||
112 | #define AR9170_MAC_REG_MAC_POWER_STATE_CTRL (AR9170_MAC_REG_BASE + 0x50c) | ||
113 | |||
114 | #define AR9170_MAC_REG_INT_CTRL (AR9170_MAC_REG_BASE + 0x510) | ||
115 | #define AR9170_MAC_INT_TXC BIT(0) | ||
116 | #define AR9170_MAC_INT_RXC BIT(1) | ||
117 | #define AR9170_MAC_INT_RETRY_FAIL BIT(2) | ||
118 | #define AR9170_MAC_INT_WAKEUP BIT(3) | ||
119 | #define AR9170_MAC_INT_ATIM BIT(4) | ||
120 | #define AR9170_MAC_INT_DTIM BIT(5) | ||
121 | #define AR9170_MAC_INT_CFG_BCN BIT(6) | ||
122 | #define AR9170_MAC_INT_ABORT BIT(7) | ||
123 | #define AR9170_MAC_INT_QOS BIT(8) | ||
124 | #define AR9170_MAC_INT_MIMO_PS BIT(9) | ||
125 | #define AR9170_MAC_INT_KEY_GEN BIT(10) | ||
126 | #define AR9170_MAC_INT_DECRY_NOUSER BIT(11) | ||
127 | #define AR9170_MAC_INT_RADAR BIT(12) | ||
128 | #define AR9170_MAC_INT_QUIET_FRAME BIT(13) | ||
129 | #define AR9170_MAC_INT_PRETBTT BIT(14) | ||
130 | |||
131 | #define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514) | ||
132 | #define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518) | ||
133 | |||
134 | #define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51c) | ||
135 | #define AR9170_MAC_ATIM_PERIOD_S 0 | ||
136 | #define AR9170_MAC_ATIM_PERIOD 0x0000ffff | ||
137 | |||
138 | #define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) | ||
139 | #define AR9170_MAC_BCN_PERIOD_S 0 | ||
140 | #define AR9170_MAC_BCN_PERIOD 0x0000ffff | ||
141 | #define AR9170_MAC_BCN_DTIM_S 16 | ||
142 | #define AR9170_MAC_BCN_DTIM 0x00ff0000 | ||
143 | #define AR9170_MAC_BCN_AP_MODE BIT(24) | ||
144 | #define AR9170_MAC_BCN_IBSS_MODE BIT(25) | ||
145 | #define AR9170_MAC_BCN_PWR_MGT BIT(26) | ||
146 | #define AR9170_MAC_BCN_STA_PS BIT(27) | ||
147 | |||
148 | #define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) | ||
149 | #define AR9170_MAC_PRETBTT_S 0 | ||
150 | #define AR9170_MAC_PRETBTT 0x0000ffff | ||
151 | #define AR9170_MAC_PRETBTT2_S 16 | ||
152 | #define AR9170_MAC_PRETBTT2 0xffff0000 | ||
153 | |||
154 | #define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610) | ||
155 | #define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614) | ||
156 | #define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618) | ||
157 | #define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c) | ||
158 | |||
159 | #define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624) | ||
160 | #define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628) | ||
161 | |||
162 | #define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62c) | ||
163 | |||
164 | #define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630) | ||
165 | #define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634) | ||
166 | #define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638) | ||
167 | #define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c) | ||
168 | #define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640) | ||
169 | #define AR9170_MAC_REG_AFTER_PNP (AR9170_MAC_REG_BASE + 0x648) | ||
170 | #define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64c) | ||
171 | |||
172 | #define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658) | ||
173 | #define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674) | ||
174 | #define AR9170_MAC_SNIFFER_ENABLE_PROMISC BIT(0) | ||
175 | #define AR9170_MAC_SNIFFER_DEFAULTS 0x02000000 | ||
176 | #define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) | ||
177 | #define AR9170_MAC_ENCRYPTION_RX_SOFTWARE BIT(3) | ||
178 | #define AR9170_MAC_ENCRYPTION_DEFAULTS 0x70 | ||
179 | |||
180 | #define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) | ||
181 | #define AR9170_MAC_REG_MISC_684 (AR9170_MAC_REG_BASE + 0x684) | ||
182 | #define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688) | ||
183 | |||
184 | #define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c) | ||
185 | #define AR9170_MAC_FTF_ASSOC_REQ BIT(0) | ||
186 | #define AR9170_MAC_FTF_ASSOC_RESP BIT(1) | ||
187 | #define AR9170_MAC_FTF_REASSOC_REQ BIT(2) | ||
188 | #define AR9170_MAC_FTF_REASSOC_RESP BIT(3) | ||
189 | #define AR9170_MAC_FTF_PRB_REQ BIT(4) | ||
190 | #define AR9170_MAC_FTF_PRB_RESP BIT(5) | ||
191 | #define AR9170_MAC_FTF_BIT6 BIT(6) | ||
192 | #define AR9170_MAC_FTF_BIT7 BIT(7) | ||
193 | #define AR9170_MAC_FTF_BEACON BIT(8) | ||
194 | #define AR9170_MAC_FTF_ATIM BIT(9) | ||
195 | #define AR9170_MAC_FTF_DEASSOC BIT(10) | ||
196 | #define AR9170_MAC_FTF_AUTH BIT(11) | ||
197 | #define AR9170_MAC_FTF_DEAUTH BIT(12) | ||
198 | #define AR9170_MAC_FTF_BIT13 BIT(13) | ||
199 | #define AR9170_MAC_FTF_BIT14 BIT(14) | ||
200 | #define AR9170_MAC_FTF_BIT15 BIT(15) | ||
201 | #define AR9170_MAC_FTF_BAR BIT(24) | ||
202 | #define AR9170_MAC_FTF_BA BIT(25) | ||
203 | #define AR9170_MAC_FTF_PSPOLL BIT(26) | ||
204 | #define AR9170_MAC_FTF_RTS BIT(27) | ||
205 | #define AR9170_MAC_FTF_CTS BIT(28) | ||
206 | #define AR9170_MAC_FTF_ACK BIT(29) | ||
207 | #define AR9170_MAC_FTF_CFE BIT(30) | ||
208 | #define AR9170_MAC_FTF_CFE_ACK BIT(31) | ||
209 | #define AR9170_MAC_FTF_DEFAULTS 0x0500ffff | ||
210 | #define AR9170_MAC_FTF_MONITOR 0xff00ffff | ||
211 | |||
212 | #define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) | ||
213 | #define AR9170_MAC_REG_ACK_TPC (AR9170_MAC_REG_BASE + 0x694) | ||
214 | #define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) | ||
215 | #define AR9170_MAC_REG_RX_TIMEOUT_COUNT (AR9170_MAC_REG_BASE + 0x69c) | ||
216 | #define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6a0) | ||
217 | #define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6a4) | ||
218 | #define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6a8) | ||
219 | #define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6ac) | ||
220 | #define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6b0) | ||
221 | #define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6bc) | ||
222 | #define AR9170_MAC_REG_TX_BLOCKACKS (AR9170_MAC_REG_BASE + 0x6c0) | ||
223 | #define AR9170_MAC_REG_NAV_COUNT (AR9170_MAC_REG_BASE + 0x6c4) | ||
224 | #define AR9170_MAC_REG_BACKOFF_STATUS (AR9170_MAC_REG_BASE + 0x6c8) | ||
225 | #define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6cc) | ||
226 | |||
227 | #define AR9170_MAC_REG_TX_COMPLETE (AR9170_MAC_REG_BASE + 0x6d4) | ||
228 | |||
229 | #define AR9170_MAC_REG_CHANNEL_BUSY (AR9170_MAC_REG_BASE + 0x6e8) | ||
230 | #define AR9170_MAC_REG_EXT_BUSY (AR9170_MAC_REG_BASE + 0x6ec) | ||
231 | |||
232 | #define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6f0) | ||
233 | #define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6f4) | ||
234 | #define AR9170_MAC_REG_ACK_FC (AR9170_MAC_REG_BASE + 0x6f8) | ||
235 | |||
236 | #define AR9170_MAC_REG_CAM_MODE (AR9170_MAC_REG_BASE + 0x700) | ||
237 | #define AR9170_MAC_CAM_IBSS 0xe0 | ||
238 | #define AR9170_MAC_CAM_AP 0xa1 | ||
239 | #define AR9170_MAC_CAM_STA 0x2 | ||
240 | #define AR9170_MAC_CAM_AP_WDS 0x3 | ||
241 | #define AR9170_MAC_CAM_DEFAULTS (0xf << 24) | ||
242 | #define AR9170_MAC_CAM_HOST_PENDING 0x80000000 | ||
243 | |||
244 | #define AR9170_MAC_REG_CAM_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) | ||
245 | #define AR9170_MAC_REG_CAM_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) | ||
246 | |||
247 | #define AR9170_MAC_REG_CAM_ADDR (AR9170_MAC_REG_BASE + 0x70c) | ||
248 | #define AR9170_MAC_CAM_ADDR_WRITE 0x80000000 | ||
249 | #define AR9170_MAC_REG_CAM_DATA0 (AR9170_MAC_REG_BASE + 0x720) | ||
250 | #define AR9170_MAC_REG_CAM_DATA1 (AR9170_MAC_REG_BASE + 0x724) | ||
251 | #define AR9170_MAC_REG_CAM_DATA2 (AR9170_MAC_REG_BASE + 0x728) | ||
252 | #define AR9170_MAC_REG_CAM_DATA3 (AR9170_MAC_REG_BASE + 0x72c) | ||
253 | |||
254 | #define AR9170_MAC_REG_CAM_DBG0 (AR9170_MAC_REG_BASE + 0x730) | ||
255 | #define AR9170_MAC_REG_CAM_DBG1 (AR9170_MAC_REG_BASE + 0x734) | ||
256 | #define AR9170_MAC_REG_CAM_DBG2 (AR9170_MAC_REG_BASE + 0x738) | ||
257 | #define AR9170_MAC_REG_CAM_STATE (AR9170_MAC_REG_BASE + 0x73c) | ||
258 | #define AR9170_MAC_CAM_STATE_READ_PENDING 0x40000000 | ||
259 | #define AR9170_MAC_CAM_STATE_WRITE_PENDING 0x80000000 | ||
260 | |||
261 | #define AR9170_MAC_REG_CAM_TXKEY (AR9170_MAC_REG_BASE + 0x740) | ||
262 | #define AR9170_MAC_REG_CAM_RXKEY (AR9170_MAC_REG_BASE + 0x750) | ||
263 | |||
264 | #define AR9170_MAC_REG_CAM_TX_ENC_TYPE (AR9170_MAC_REG_BASE + 0x760) | ||
265 | #define AR9170_MAC_REG_CAM_RX_ENC_TYPE (AR9170_MAC_REG_BASE + 0x770) | ||
266 | #define AR9170_MAC_REG_CAM_TX_SERACH_HIT (AR9170_MAC_REG_BASE + 0x780) | ||
267 | #define AR9170_MAC_REG_CAM_RX_SERACH_HIT (AR9170_MAC_REG_BASE + 0x790) | ||
268 | |||
269 | #define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xb00) | ||
270 | #define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xb04) | ||
271 | #define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xb08) | ||
272 | #define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xb0c) | ||
273 | #define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xb10) | ||
274 | #define AR9170_MAC_REG_AC2_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xb14) | ||
275 | #define AR9170_MAC_REG_AC4_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xb18) | ||
276 | #define AR9170_MAC_REG_TXOP_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0xb1c) | ||
277 | #define AR9170_MAC_REG_TXOP_ACK_INTERVAL (AR9170_MAC_REG_BASE + 0xb20) | ||
278 | #define AR9170_MAC_REG_CONTENTION_POINT (AR9170_MAC_REG_BASE + 0xb24) | ||
279 | #define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xb28) | ||
280 | #define AR9170_MAC_REG_TID_CFACK_CFEND_RATE (AR9170_MAC_REG_BASE + 0xb2c) | ||
281 | #define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xb30) | ||
282 | #define AR9170_MAC_REG_TKIP_TSC (AR9170_MAC_REG_BASE + 0xb34) | ||
283 | #define AR9170_MAC_REG_TXOP_DURATION (AR9170_MAC_REG_BASE + 0xb38) | ||
284 | #define AR9170_MAC_REG_TX_QOS_THRESHOLD (AR9170_MAC_REG_BASE + 0xb3c) | ||
285 | #define AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA (AR9170_MAC_REG_BASE + 0xb40) | ||
286 | #define AR9170_MAC_VIRTUAL_CCA_Q0 BIT(15) | ||
287 | #define AR9170_MAC_VIRTUAL_CCA_Q1 BIT(16) | ||
288 | #define AR9170_MAC_VIRTUAL_CCA_Q2 BIT(17) | ||
289 | #define AR9170_MAC_VIRTUAL_CCA_Q3 BIT(18) | ||
290 | #define AR9170_MAC_VIRTUAL_CCA_Q4 BIT(19) | ||
291 | #define AR9170_MAC_VIRTUAL_CCA_ALL (0xf8000) | ||
292 | |||
293 | #define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xb44) | ||
294 | #define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xb48) | ||
295 | |||
296 | #define AR9170_MAC_REG_AMPDU_COUNT (AR9170_MAC_REG_BASE + 0xb88) | ||
297 | #define AR9170_MAC_REG_MPDU_COUNT (AR9170_MAC_REG_BASE + 0xb8c) | ||
298 | |||
299 | #define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xb9c) | ||
300 | #define AR9170_MAC_AMPDU_FACTOR 0x7f0000 | ||
301 | #define AR9170_MAC_AMPDU_FACTOR_S 16 | ||
302 | #define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xba0) | ||
303 | #define AR9170_MAC_AMPDU_DENSITY 0x7 | ||
304 | #define AR9170_MAC_AMPDU_DENSITY_S 0 | ||
305 | |||
306 | #define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xbb0) | ||
307 | #define AR9170_MAC_FCS_SWFCS 0x1 | ||
308 | #define AR9170_MAC_FCS_FIFO_PROT 0x4 | ||
309 | |||
310 | #define AR9170_MAC_REG_RTS_CTS_TPC (AR9170_MAC_REG_BASE + 0xbb4) | ||
311 | #define AR9170_MAC_REG_CFEND_QOSNULL_TPC (AR9170_MAC_REG_BASE + 0xbb8) | ||
312 | |||
313 | #define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xc00) | ||
314 | #define AR9170_MAC_REG_RX_CONTROL (AR9170_MAC_REG_BASE + 0xc40) | ||
315 | #define AR9170_MAC_RX_CTRL_DEAGG 0x1 | ||
316 | #define AR9170_MAC_RX_CTRL_SHORT_FILTER 0x2 | ||
317 | #define AR9170_MAC_RX_CTRL_SA_DA_SEARCH 0x20 | ||
318 | #define AR9170_MAC_RX_CTRL_PASS_TO_HOST BIT(28) | ||
319 | #define AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER BIT(30) | ||
320 | |||
321 | #define AR9170_MAC_REG_RX_CONTROL_1 (AR9170_MAC_REG_BASE + 0xc44) | ||
322 | |||
323 | #define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xc50) | ||
324 | |||
325 | #define AR9170_MAC_REG_RX_MPDU (AR9170_MAC_REG_BASE + 0xca0) | ||
326 | #define AR9170_MAC_REG_RX_DROPPED_MPDU (AR9170_MAC_REG_BASE + 0xca4) | ||
327 | #define AR9170_MAC_REG_RX_DEL_MPDU (AR9170_MAC_REG_BASE + 0xca8) | ||
328 | #define AR9170_MAC_REG_RX_PHY_MISC_ERROR (AR9170_MAC_REG_BASE + 0xcac) | ||
329 | #define AR9170_MAC_REG_RX_PHY_XR_ERROR (AR9170_MAC_REG_BASE + 0xcb0) | ||
330 | #define AR9170_MAC_REG_RX_PHY_OFDM_ERROR (AR9170_MAC_REG_BASE + 0xcb4) | ||
331 | #define AR9170_MAC_REG_RX_PHY_CCK_ERROR (AR9170_MAC_REG_BASE + 0xcb8) | ||
332 | #define AR9170_MAC_REG_RX_PHY_HT_ERROR (AR9170_MAC_REG_BASE + 0xcbc) | ||
333 | #define AR9170_MAC_REG_RX_PHY_TOTAL (AR9170_MAC_REG_BASE + 0xcc0) | ||
334 | |||
335 | #define AR9170_MAC_REG_DMA_TXQ_ADDR (AR9170_MAC_REG_BASE + 0xd00) | ||
336 | #define AR9170_MAC_REG_DMA_TXQ_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd04) | ||
337 | #define AR9170_MAC_REG_DMA_TXQ0_ADDR (AR9170_MAC_REG_BASE + 0xd00) | ||
338 | #define AR9170_MAC_REG_DMA_TXQ0_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd04) | ||
339 | #define AR9170_MAC_REG_DMA_TXQ1_ADDR (AR9170_MAC_REG_BASE + 0xd08) | ||
340 | #define AR9170_MAC_REG_DMA_TXQ1_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd0c) | ||
341 | #define AR9170_MAC_REG_DMA_TXQ2_ADDR (AR9170_MAC_REG_BASE + 0xd10) | ||
342 | #define AR9170_MAC_REG_DMA_TXQ2_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd14) | ||
343 | #define AR9170_MAC_REG_DMA_TXQ3_ADDR (AR9170_MAC_REG_BASE + 0xd18) | ||
344 | #define AR9170_MAC_REG_DMA_TXQ3_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd1c) | ||
345 | #define AR9170_MAC_REG_DMA_TXQ4_ADDR (AR9170_MAC_REG_BASE + 0xd20) | ||
346 | #define AR9170_MAC_REG_DMA_TXQ4_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd24) | ||
347 | #define AR9170_MAC_REG_DMA_RXQ_ADDR (AR9170_MAC_REG_BASE + 0xd28) | ||
348 | #define AR9170_MAC_REG_DMA_RXQ_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd2c) | ||
349 | |||
350 | #define AR9170_MAC_REG_DMA_TRIGGER (AR9170_MAC_REG_BASE + 0xd30) | ||
351 | #define AR9170_DMA_TRIGGER_TXQ0 BIT(0) | ||
352 | #define AR9170_DMA_TRIGGER_TXQ1 BIT(1) | ||
353 | #define AR9170_DMA_TRIGGER_TXQ2 BIT(2) | ||
354 | #define AR9170_DMA_TRIGGER_TXQ3 BIT(3) | ||
355 | #define AR9170_DMA_TRIGGER_TXQ4 BIT(4) | ||
356 | #define AR9170_DMA_TRIGGER_RXQ BIT(8) | ||
357 | |||
358 | #define AR9170_MAC_REG_DMA_WLAN_STATUS (AR9170_MAC_REG_BASE + 0xd38) | ||
359 | #define AR9170_MAC_REG_DMA_STATUS (AR9170_MAC_REG_BASE + 0xd3c) | ||
360 | |||
361 | #define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xd7c) | ||
362 | #define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f | ||
363 | #define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0 | ||
364 | #define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000 | ||
365 | #define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000 | ||
366 | |||
367 | #define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xd84) | ||
368 | #define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xd88) | ||
369 | #define AR9170_MAC_BCN_LENGTH_MAX 256 | ||
370 | |||
371 | #define AR9170_MAC_REG_BCN_STATUS (AR9170_MAC_REG_BASE + 0xd8c) | ||
372 | |||
373 | #define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xd90) | ||
374 | #define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xd94) | ||
375 | #define AR9170_BCN_CTRL_READY 0x01 | ||
376 | #define AR9170_BCN_CTRL_LOCK 0x02 | ||
377 | |||
378 | #define AR9170_MAC_REG_BCN_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd98) | ||
379 | #define AR9170_MAC_REG_BCN_COUNT (AR9170_MAC_REG_BASE + 0xd9c) | ||
380 | |||
381 | |||
382 | #define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xda0) | ||
383 | #define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xda4) | ||
384 | |||
385 | #define AR9170_MAC_REG_DMA_TXQX_ADDR_CURR (AR9170_MAC_REG_BASE + 0xdc0) | ||
386 | |||
387 | /* Random number generator */ | ||
388 | #define AR9170_RAND_REG_BASE 0x1d0000 | ||
389 | |||
390 | #define AR9170_RAND_REG_NUM (AR9170_RAND_REG_BASE + 0x000) | ||
391 | #define AR9170_RAND_REG_MODE (AR9170_RAND_REG_BASE + 0x004) | ||
392 | #define AR9170_RAND_MODE_MANUAL 0x000 | ||
393 | #define AR9170_RAND_MODE_FREE 0x001 | ||
394 | |||
395 | /* GPIO */ | ||
396 | #define AR9170_GPIO_REG_BASE 0x1d0100 | ||
397 | #define AR9170_GPIO_REG_PORT_TYPE (AR9170_GPIO_REG_BASE + 0x000) | ||
398 | #define AR9170_GPIO_REG_PORT_DATA (AR9170_GPIO_REG_BASE + 0x004) | ||
399 | #define AR9170_GPIO_PORT_LED_0 1 | ||
400 | #define AR9170_GPIO_PORT_LED_1 2 | ||
401 | /* WPS Button GPIO for TP-Link TL-WN821N */ | ||
402 | #define AR9170_GPIO_PORT_WPS_BUTTON_PRESSED 4 | ||
403 | |||
404 | /* Memory Controller */ | ||
405 | #define AR9170_MC_REG_BASE 0x1d1000 | ||
406 | |||
407 | #define AR9170_MC_REG_FLASH_WAIT_STATE (AR9170_MC_REG_BASE + 0x000) | ||
408 | #define AR9170_MC_REG_SEEPROM_WP0 (AR9170_MC_REG_BASE + 0x400) | ||
409 | #define AR9170_MC_REG_SEEPROM_WP1 (AR9170_MC_REG_BASE + 0x404) | ||
410 | #define AR9170_MC_REG_SEEPROM_WP2 (AR9170_MC_REG_BASE + 0x408) | ||
411 | |||
412 | /* Interrupt Controller */ | ||
413 | #define AR9170_MAX_INT_SRC 9 | ||
414 | #define AR9170_INT_REG_BASE 0x1d2000 | ||
415 | |||
416 | #define AR9170_INT_REG_FLAG (AR9170_INT_REG_BASE + 0x000) | ||
417 | #define AR9170_INT_REG_FIQ_MASK (AR9170_INT_REG_BASE + 0x004) | ||
418 | #define AR9170_INT_REG_IRQ_MASK (AR9170_INT_REG_BASE + 0x008) | ||
419 | /* INT_REG_FLAG, INT_REG_FIQ_MASK and INT_REG_IRQ_MASK */ | ||
420 | #define AR9170_INT_FLAG_WLAN 0x001 | ||
421 | #define AR9170_INT_FLAG_PTAB_BIT 0x002 | ||
422 | #define AR9170_INT_FLAG_SE_BIT 0x004 | ||
423 | #define AR9170_INT_FLAG_UART_BIT 0x008 | ||
424 | #define AR9170_INT_FLAG_TIMER_BIT 0x010 | ||
425 | #define AR9170_INT_FLAG_EXT_BIT 0x020 | ||
426 | #define AR9170_INT_FLAG_SW_BIT 0x040 | ||
427 | #define AR9170_INT_FLAG_USB_BIT 0x080 | ||
428 | #define AR9170_INT_FLAG_ETHERNET_BIT 0x100 | ||
429 | |||
430 | #define AR9170_INT_REG_PRIORITY1 (AR9170_INT_REG_BASE + 0x00c) | ||
431 | #define AR9170_INT_REG_PRIORITY2 (AR9170_INT_REG_BASE + 0x010) | ||
432 | #define AR9170_INT_REG_PRIORITY3 (AR9170_INT_REG_BASE + 0x014) | ||
433 | #define AR9170_INT_REG_EXT_INT_CONTROL (AR9170_INT_REG_BASE + 0x018) | ||
434 | #define AR9170_INT_REG_SW_INT_CONTROL (AR9170_INT_REG_BASE + 0x01c) | ||
435 | #define AR9170_INT_SW_INT_ENABLE 0x1 | ||
436 | |||
437 | #define AR9170_INT_REG_FIQ_ENCODE (AR9170_INT_REG_BASE + 0x020) | ||
438 | #define AR9170_INT_INT_IRQ_ENCODE (AR9170_INT_REG_BASE + 0x024) | ||
439 | |||
440 | /* Power Management */ | ||
441 | #define AR9170_PWR_REG_BASE 0x1d4000 | ||
442 | |||
443 | #define AR9170_PWR_REG_POWER_STATE (AR9170_PWR_REG_BASE + 0x000) | ||
444 | |||
445 | #define AR9170_PWR_REG_RESET (AR9170_PWR_REG_BASE + 0x004) | ||
446 | #define AR9170_PWR_RESET_COMMIT_RESET_MASK BIT(0) | ||
447 | #define AR9170_PWR_RESET_WLAN_MASK BIT(1) | ||
448 | #define AR9170_PWR_RESET_DMA_MASK BIT(2) | ||
449 | #define AR9170_PWR_RESET_BRIDGE_MASK BIT(3) | ||
450 | #define AR9170_PWR_RESET_AHB_MASK BIT(9) | ||
451 | #define AR9170_PWR_RESET_BB_WARM_RESET BIT(10) | ||
452 | #define AR9170_PWR_RESET_BB_COLD_RESET BIT(11) | ||
453 | #define AR9170_PWR_RESET_ADDA_CLK_COLD_RESET BIT(12) | ||
454 | #define AR9170_PWR_RESET_PLL BIT(13) | ||
455 | #define AR9170_PWR_RESET_USB_PLL BIT(14) | ||
456 | |||
457 | #define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008) | ||
458 | #define AR9170_PWR_CLK_AHB_40MHZ 0 | ||
459 | #define AR9170_PWR_CLK_AHB_20_22MHZ 1 | ||
460 | #define AR9170_PWR_CLK_AHB_40_44MHZ 2 | ||
461 | #define AR9170_PWR_CLK_AHB_80_88MHZ 3 | ||
462 | #define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70 | ||
463 | |||
464 | #define AR9170_PWR_REG_CHIP_REVISION (AR9170_PWR_REG_BASE + 0x010) | ||
465 | #define AR9170_PWR_REG_PLL_ADDAC (AR9170_PWR_REG_BASE + 0x014) | ||
466 | #define AR9170_PWR_PLL_ADDAC_DIV_S 2 | ||
467 | #define AR9170_PWR_PLL_ADDAC_DIV 0xffc | ||
468 | #define AR9170_PWR_REG_WATCH_DOG_MAGIC (AR9170_PWR_REG_BASE + 0x020) | ||
469 | |||
470 | /* Faraday USB Controller */ | ||
471 | #define AR9170_USB_REG_BASE 0x1e1000 | ||
472 | |||
473 | #define AR9170_USB_REG_MAIN_CTRL (AR9170_USB_REG_BASE + 0x000) | ||
474 | #define AR9170_USB_MAIN_CTRL_REMOTE_WAKEUP BIT(0) | ||
475 | #define AR9170_USB_MAIN_CTRL_ENABLE_GLOBAL_INT BIT(2) | ||
476 | #define AR9170_USB_MAIN_CTRL_GO_TO_SUSPEND BIT(3) | ||
477 | #define AR9170_USB_MAIN_CTRL_RESET BIT(4) | ||
478 | #define AR9170_USB_MAIN_CTRL_CHIP_ENABLE BIT(5) | ||
479 | #define AR9170_USB_MAIN_CTRL_HIGHSPEED BIT(6) | ||
480 | |||
481 | #define AR9170_USB_REG_DEVICE_ADDRESS (AR9170_USB_REG_BASE + 0x001) | ||
482 | #define AR9170_USB_DEVICE_ADDRESS_CONFIGURE BIT(7) | ||
483 | |||
484 | #define AR9170_USB_REG_TEST (AR9170_USB_REG_BASE + 0x002) | ||
485 | #define AR9170_USB_REG_PHY_TEST_SELECT (AR9170_USB_REG_BASE + 0x008) | ||
486 | #define AR9170_USB_REG_CX_CONFIG_STATUS (AR9170_USB_REG_BASE + 0x00b) | ||
487 | #define AR9170_USB_REG_EP0_DATA (AR9170_USB_REG_BASE + 0x00c) | ||
488 | #define AR9170_USB_REG_EP0_DATA1 (AR9170_USB_REG_BASE + 0x00c) | ||
489 | #define AR9170_USB_REG_EP0_DATA2 (AR9170_USB_REG_BASE + 0x00d) | ||
490 | |||
491 | #define AR9170_USB_REG_INTR_MASK_BYTE_0 (AR9170_USB_REG_BASE + 0x011) | ||
492 | #define AR9170_USB_REG_INTR_MASK_BYTE_1 (AR9170_USB_REG_BASE + 0x012) | ||
493 | #define AR9170_USB_REG_INTR_MASK_BYTE_2 (AR9170_USB_REG_BASE + 0x013) | ||
494 | #define AR9170_USB_REG_INTR_MASK_BYTE_3 (AR9170_USB_REG_BASE + 0x014) | ||
495 | #define AR9170_USB_REG_INTR_MASK_BYTE_4 (AR9170_USB_REG_BASE + 0x015) | ||
496 | #define AR9170_USB_INTR_DISABLE_OUT_INT (BIT(7) | BIT(6)) | ||
497 | |||
498 | #define AR9170_USB_REG_INTR_MASK_BYTE_5 (AR9170_USB_REG_BASE + 0x016) | ||
499 | #define AR9170_USB_REG_INTR_MASK_BYTE_6 (AR9170_USB_REG_BASE + 0x017) | ||
500 | #define AR9170_USB_INTR_DISABLE_IN_INT BIT(6) | ||
501 | |||
502 | #define AR9170_USB_REG_INTR_MASK_BYTE_7 (AR9170_USB_REG_BASE + 0x018) | ||
503 | |||
504 | #define AR9170_USB_REG_INTR_GROUP (AR9170_USB_REG_BASE + 0x020) | ||
505 | |||
506 | #define AR9170_USB_REG_INTR_SOURCE_0 (AR9170_USB_REG_BASE + 0x021) | ||
507 | #define AR9170_USB_INTR_SRC0_SETUP BIT(0) | ||
508 | #define AR9170_USB_INTR_SRC0_IN BIT(1) | ||
509 | #define AR9170_USB_INTR_SRC0_OUT BIT(2) | ||
510 | #define AR9170_USB_INTR_SRC0_FAIL BIT(3) /* ??? */ | ||
511 | #define AR9170_USB_INTR_SRC0_END BIT(4) /* ??? */ | ||
512 | #define AR9170_USB_INTR_SRC0_ABORT BIT(7) | ||
513 | |||
514 | #define AR9170_USB_REG_INTR_SOURCE_1 (AR9170_USB_REG_BASE + 0x022) | ||
515 | #define AR9170_USB_REG_INTR_SOURCE_2 (AR9170_USB_REG_BASE + 0x023) | ||
516 | #define AR9170_USB_REG_INTR_SOURCE_3 (AR9170_USB_REG_BASE + 0x024) | ||
517 | #define AR9170_USB_REG_INTR_SOURCE_4 (AR9170_USB_REG_BASE + 0x025) | ||
518 | #define AR9170_USB_REG_INTR_SOURCE_5 (AR9170_USB_REG_BASE + 0x026) | ||
519 | #define AR9170_USB_REG_INTR_SOURCE_6 (AR9170_USB_REG_BASE + 0x027) | ||
520 | #define AR9170_USB_REG_INTR_SOURCE_7 (AR9170_USB_REG_BASE + 0x028) | ||
521 | #define AR9170_USB_INTR_SRC7_USB_RESET BIT(1) | ||
522 | #define AR9170_USB_INTR_SRC7_USB_SUSPEND BIT(2) | ||
523 | #define AR9170_USB_INTR_SRC7_USB_RESUME BIT(3) | ||
524 | #define AR9170_USB_INTR_SRC7_ISO_SEQ_ERR BIT(4) | ||
525 | #define AR9170_USB_INTR_SRC7_ISO_SEQ_ABORT BIT(5) | ||
526 | #define AR9170_USB_INTR_SRC7_TX0BYTE BIT(6) | ||
527 | #define AR9170_USB_INTR_SRC7_RX0BYTE BIT(7) | ||
528 | |||
529 | #define AR9170_USB_REG_IDLE_COUNT (AR9170_USB_REG_BASE + 0x02f) | ||
530 | |||
531 | #define AR9170_USB_REG_EP_MAP (AR9170_USB_REG_BASE + 0x030) | ||
532 | #define AR9170_USB_REG_EP1_MAP (AR9170_USB_REG_BASE + 0x030) | ||
533 | #define AR9170_USB_REG_EP2_MAP (AR9170_USB_REG_BASE + 0x031) | ||
534 | #define AR9170_USB_REG_EP3_MAP (AR9170_USB_REG_BASE + 0x032) | ||
535 | #define AR9170_USB_REG_EP4_MAP (AR9170_USB_REG_BASE + 0x033) | ||
536 | #define AR9170_USB_REG_EP5_MAP (AR9170_USB_REG_BASE + 0x034) | ||
537 | #define AR9170_USB_REG_EP6_MAP (AR9170_USB_REG_BASE + 0x035) | ||
538 | #define AR9170_USB_REG_EP7_MAP (AR9170_USB_REG_BASE + 0x036) | ||
539 | #define AR9170_USB_REG_EP8_MAP (AR9170_USB_REG_BASE + 0x037) | ||
540 | #define AR9170_USB_REG_EP9_MAP (AR9170_USB_REG_BASE + 0x038) | ||
541 | #define AR9170_USB_REG_EP10_MAP (AR9170_USB_REG_BASE + 0x039) | ||
542 | |||
543 | #define AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x03f) | ||
544 | #define AR9170_USB_EP_IN_TOGGLE 0x10 | ||
545 | |||
546 | #define AR9170_USB_REG_EP_IN_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x03e) | ||
547 | |||
548 | #define AR9170_USB_REG_EP_OUT_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x05f) | ||
549 | #define AR9170_USB_EP_OUT_TOGGLE 0x10 | ||
550 | |||
551 | #define AR9170_USB_REG_EP_OUT_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x05e) | ||
552 | |||
553 | #define AR9170_USB_REG_EP3_BYTE_COUNT_HIGH (AR9170_USB_REG_BASE + 0x0ae) | ||
554 | #define AR9170_USB_REG_EP3_BYTE_COUNT_LOW (AR9170_USB_REG_BASE + 0x0be) | ||
555 | #define AR9170_USB_REG_EP4_BYTE_COUNT_HIGH (AR9170_USB_REG_BASE + 0x0af) | ||
556 | #define AR9170_USB_REG_EP4_BYTE_COUNT_LOW (AR9170_USB_REG_BASE + 0x0bf) | ||
557 | |||
558 | #define AR9170_USB_REG_FIFO_MAP (AR9170_USB_REG_BASE + 0x080) | ||
559 | #define AR9170_USB_REG_FIFO0_MAP (AR9170_USB_REG_BASE + 0x080) | ||
560 | #define AR9170_USB_REG_FIFO1_MAP (AR9170_USB_REG_BASE + 0x081) | ||
561 | #define AR9170_USB_REG_FIFO2_MAP (AR9170_USB_REG_BASE + 0x082) | ||
562 | #define AR9170_USB_REG_FIFO3_MAP (AR9170_USB_REG_BASE + 0x083) | ||
563 | #define AR9170_USB_REG_FIFO4_MAP (AR9170_USB_REG_BASE + 0x084) | ||
564 | #define AR9170_USB_REG_FIFO5_MAP (AR9170_USB_REG_BASE + 0x085) | ||
565 | #define AR9170_USB_REG_FIFO6_MAP (AR9170_USB_REG_BASE + 0x086) | ||
566 | #define AR9170_USB_REG_FIFO7_MAP (AR9170_USB_REG_BASE + 0x087) | ||
567 | #define AR9170_USB_REG_FIFO8_MAP (AR9170_USB_REG_BASE + 0x088) | ||
568 | #define AR9170_USB_REG_FIFO9_MAP (AR9170_USB_REG_BASE + 0x089) | ||
569 | |||
570 | #define AR9170_USB_REG_FIFO_CONFIG (AR9170_USB_REG_BASE + 0x090) | ||
571 | #define AR9170_USB_REG_FIFO0_CONFIG (AR9170_USB_REG_BASE + 0x090) | ||
572 | #define AR9170_USB_REG_FIFO1_CONFIG (AR9170_USB_REG_BASE + 0x091) | ||
573 | #define AR9170_USB_REG_FIFO2_CONFIG (AR9170_USB_REG_BASE + 0x092) | ||
574 | #define AR9170_USB_REG_FIFO3_CONFIG (AR9170_USB_REG_BASE + 0x093) | ||
575 | #define AR9170_USB_REG_FIFO4_CONFIG (AR9170_USB_REG_BASE + 0x094) | ||
576 | #define AR9170_USB_REG_FIFO5_CONFIG (AR9170_USB_REG_BASE + 0x095) | ||
577 | #define AR9170_USB_REG_FIFO6_CONFIG (AR9170_USB_REG_BASE + 0x096) | ||
578 | #define AR9170_USB_REG_FIFO7_CONFIG (AR9170_USB_REG_BASE + 0x097) | ||
579 | #define AR9170_USB_REG_FIFO8_CONFIG (AR9170_USB_REG_BASE + 0x098) | ||
580 | #define AR9170_USB_REG_FIFO9_CONFIG (AR9170_USB_REG_BASE + 0x099) | ||
581 | |||
582 | #define AR9170_USB_REG_EP3_DATA (AR9170_USB_REG_BASE + 0x0f8) | ||
583 | #define AR9170_USB_REG_EP4_DATA (AR9170_USB_REG_BASE + 0x0fc) | ||
584 | |||
585 | #define AR9170_USB_REG_FIFO_SIZE (AR9170_USB_REG_BASE + 0x100) | ||
586 | #define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) | ||
587 | #define AR9170_USB_DMA_CTL_ENABLE_TO_DEVICE BIT(0) | ||
588 | #define AR9170_USB_DMA_CTL_ENABLE_FROM_DEVICE BIT(1) | ||
589 | #define AR9170_USB_DMA_CTL_HIGH_SPEED BIT(2) | ||
590 | #define AR9170_USB_DMA_CTL_UP_PACKET_MODE BIT(3) | ||
591 | #define AR9170_USB_DMA_CTL_UP_STREAM_S 4 | ||
592 | #define AR9170_USB_DMA_CTL_UP_STREAM (BIT(4) | BIT(5)) | ||
593 | #define AR9170_USB_DMA_CTL_UP_STREAM_4K (0) | ||
594 | #define AR9170_USB_DMA_CTL_UP_STREAM_8K BIT(4) | ||
595 | #define AR9170_USB_DMA_CTL_UP_STREAM_16K BIT(5) | ||
596 | #define AR9170_USB_DMA_CTL_UP_STREAM_32K (BIT(4) | BIT(5)) | ||
597 | #define AR9170_USB_DMA_CTL_DOWN_STREAM BIT(6) | ||
598 | |||
599 | #define AR9170_USB_REG_DMA_STATUS (AR9170_USB_REG_BASE + 0x10c) | ||
600 | #define AR9170_USB_DMA_STATUS_UP_IDLE BIT(8) | ||
601 | #define AR9170_USB_DMA_STATUS_DN_IDLE BIT(16) | ||
602 | |||
603 | #define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) | ||
604 | #define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) | ||
605 | |||
606 | #define AR9170_USB_REG_WAKE_UP (AR9170_USB_REG_BASE + 0x120) | ||
607 | #define AR9170_USB_WAKE_UP_WAKE BIT(0) | ||
608 | |||
609 | #define AR9170_USB_REG_CBUS_CTRL (AR9170_USB_REG_BASE + 0x1f0) | ||
610 | #define AR9170_USB_CBUS_CTRL_BUFFER_END (BIT(1)) | ||
611 | |||
612 | /* PCI/USB to AHB Bridge */ | ||
613 | #define AR9170_PTA_REG_BASE 0x1e2000 | ||
614 | |||
615 | #define AR9170_PTA_REG_CMD (AR9170_PTA_REG_BASE + 0x000) | ||
616 | #define AR9170_PTA_REG_PARAM1 (AR9170_PTA_REG_BASE + 0x004) | ||
617 | #define AR9170_PTA_REG_PARAM2 (AR9170_PTA_REG_BASE + 0x008) | ||
618 | #define AR9170_PTA_REG_PARAM3 (AR9170_PTA_REG_BASE + 0x00c) | ||
619 | #define AR9170_PTA_REG_RSP (AR9170_PTA_REG_BASE + 0x010) | ||
620 | #define AR9170_PTA_REG_STATUS1 (AR9170_PTA_REG_BASE + 0x014) | ||
621 | #define AR9170_PTA_REG_STATUS2 (AR9170_PTA_REG_BASE + 0x018) | ||
622 | #define AR9170_PTA_REG_STATUS3 (AR9170_PTA_REG_BASE + 0x01c) | ||
623 | #define AR9170_PTA_REG_AHB_INT_FLAG (AR9170_PTA_REG_BASE + 0x020) | ||
624 | #define AR9170_PTA_REG_AHB_INT_MASK (AR9170_PTA_REG_BASE + 0x024) | ||
625 | #define AR9170_PTA_REG_AHB_INT_ACK (AR9170_PTA_REG_BASE + 0x028) | ||
626 | #define AR9170_PTA_REG_AHB_SCRATCH1 (AR9170_PTA_REG_BASE + 0x030) | ||
627 | #define AR9170_PTA_REG_AHB_SCRATCH2 (AR9170_PTA_REG_BASE + 0x034) | ||
628 | #define AR9170_PTA_REG_AHB_SCRATCH3 (AR9170_PTA_REG_BASE + 0x038) | ||
629 | #define AR9170_PTA_REG_AHB_SCRATCH4 (AR9170_PTA_REG_BASE + 0x03c) | ||
630 | |||
631 | #define AR9170_PTA_REG_SHARE_MEM_CTRL (AR9170_PTA_REG_BASE + 0x124) | ||
632 | |||
633 | /* | ||
634 | * PCI to AHB Bridge | ||
635 | */ | ||
636 | |||
637 | #define AR9170_PTA_REG_INT_FLAG (AR9170_PTA_REG_BASE + 0x100) | ||
638 | #define AR9170_PTA_INT_FLAG_DN 0x01 | ||
639 | #define AR9170_PTA_INT_FLAG_UP 0x02 | ||
640 | #define AR9170_PTA_INT_FLAG_CMD 0x04 | ||
641 | |||
642 | #define AR9170_PTA_REG_INT_MASK (AR9170_PTA_REG_BASE + 0x104) | ||
643 | #define AR9170_PTA_REG_DN_DMA_ADDRL (AR9170_PTA_REG_BASE + 0x108) | ||
644 | #define AR9170_PTA_REG_DN_DMA_ADDRH (AR9170_PTA_REG_BASE + 0x10c) | ||
645 | #define AR9170_PTA_REG_UP_DMA_ADDRL (AR9170_PTA_REG_BASE + 0x110) | ||
646 | #define AR9170_PTA_REG_UP_DMA_ADDRH (AR9170_PTA_REG_BASE + 0x114) | ||
647 | #define AR9170_PTA_REG_DN_PEND_TIME (AR9170_PTA_REG_BASE + 0x118) | ||
648 | #define AR9170_PTA_REG_UP_PEND_TIME (AR9170_PTA_REG_BASE + 0x11c) | ||
649 | #define AR9170_PTA_REG_CONTROL (AR9170_PTA_REG_BASE + 0x120) | ||
650 | #define AR9170_PTA_CTRL_4_BEAT_BURST 0x00 | ||
651 | #define AR9170_PTA_CTRL_8_BEAT_BURST 0x01 | ||
652 | #define AR9170_PTA_CTRL_16_BEAT_BURST 0x02 | ||
653 | #define AR9170_PTA_CTRL_LOOPBACK_MODE 0x10 | ||
654 | |||
655 | #define AR9170_PTA_REG_MEM_CTRL (AR9170_PTA_REG_BASE + 0x124) | ||
656 | #define AR9170_PTA_REG_MEM_ADDR (AR9170_PTA_REG_BASE + 0x128) | ||
657 | #define AR9170_PTA_REG_DN_DMA_TRIGGER (AR9170_PTA_REG_BASE + 0x12c) | ||
658 | #define AR9170_PTA_REG_UP_DMA_TRIGGER (AR9170_PTA_REG_BASE + 0x130) | ||
659 | #define AR9170_PTA_REG_DMA_STATUS (AR9170_PTA_REG_BASE + 0x134) | ||
660 | #define AR9170_PTA_REG_DN_CURR_ADDRL (AR9170_PTA_REG_BASE + 0x138) | ||
661 | #define AR9170_PTA_REG_DN_CURR_ADDRH (AR9170_PTA_REG_BASE + 0x13c) | ||
662 | #define AR9170_PTA_REG_UP_CURR_ADDRL (AR9170_PTA_REG_BASE + 0x140) | ||
663 | #define AR9170_PTA_REG_UP_CURR_ADDRH (AR9170_PTA_REG_BASE + 0x144) | ||
664 | #define AR9170_PTA_REG_DMA_MODE_CTRL (AR9170_PTA_REG_BASE + 0x148) | ||
665 | #define AR9170_PTA_DMA_MODE_CTRL_RESET BIT(0) | ||
666 | #define AR9170_PTA_DMA_MODE_CTRL_DISABLE_USB BIT(1) | ||
667 | |||
668 | /* Protocol Controller Module */ | ||
669 | #define AR9170_MAC_REG_PC_REG_BASE (AR9170_MAC_REG_BASE + 0xe00) | ||
670 | |||
671 | |||
672 | #define AR9170_NUM_LEDS 2 | ||
673 | |||
674 | /* CAM */ | ||
675 | #define AR9170_CAM_MAX_USER 64 | ||
676 | #define AR9170_CAM_MAX_KEY_LENGTH 16 | ||
677 | |||
678 | #define AR9170_SRAM_OFFSET 0x100000 | ||
679 | #define AR9170_SRAM_SIZE 0x18000 | ||
680 | |||
681 | #define AR9170_PRAM_OFFSET 0x200000 | ||
682 | #define AR9170_PRAM_SIZE 0x8000 | ||
683 | |||
684 | enum cpu_clock { | ||
685 | AHB_STATIC_40MHZ = 0, | ||
686 | AHB_GMODE_22MHZ = 1, | ||
687 | AHB_AMODE_20MHZ = 1, | ||
688 | AHB_GMODE_44MHZ = 2, | ||
689 | AHB_AMODE_40MHZ = 2, | ||
690 | AHB_GMODE_88MHZ = 3, | ||
691 | AHB_AMODE_80MHZ = 3 | ||
692 | }; | ||
693 | |||
694 | /* USB endpoints */ | ||
695 | enum ar9170_usb_ep { | ||
696 | /* | ||
697 | * Control EP is always EP 0 (USB SPEC) | ||
698 | * | ||
699 | * The weird thing is: the original firmware has a few | ||
700 | * comments that suggest that the actual EP numbers | ||
701 | * are in the 1 to 10 range?! | ||
702 | */ | ||
703 | AR9170_USB_EP_CTRL = 0, | ||
704 | |||
705 | AR9170_USB_EP_TX, | ||
706 | AR9170_USB_EP_RX, | ||
707 | AR9170_USB_EP_IRQ, | ||
708 | AR9170_USB_EP_CMD, | ||
709 | AR9170_USB_NUM_EXTRA_EP = 4, | ||
710 | |||
711 | __AR9170_USB_NUM_EP, | ||
712 | |||
713 | __AR9170_USB_NUM_MAX_EP = 10 | ||
714 | }; | ||
715 | |||
716 | enum ar9170_usb_fifo { | ||
717 | __AR9170_USB_NUM_MAX_FIFO = 10 | ||
718 | }; | ||
719 | |||
720 | enum ar9170_tx_queues { | ||
721 | AR9170_TXQ0 = 0, | ||
722 | AR9170_TXQ1, | ||
723 | AR9170_TXQ2, | ||
724 | AR9170_TXQ3, | ||
725 | AR9170_TXQ_SPECIAL, | ||
726 | |||
727 | /* keep last */ | ||
728 | __AR9170_NUM_TX_QUEUES = 5 | ||
729 | }; | ||
730 | |||
731 | #define AR9170_TX_STREAM_TAG 0x697e | ||
732 | #define AR9170_RX_STREAM_TAG 0x4e00 | ||
733 | #define AR9170_RX_STREAM_MAX_SIZE 0xffff | ||
734 | |||
735 | struct ar9170_stream { | ||
736 | __le16 length; | ||
737 | __le16 tag; | ||
738 | |||
739 | u8 payload[0]; | ||
740 | } __packed __aligned(4); | ||
741 | #define AR9170_STREAM_LEN 4 | ||
742 | |||
743 | #define AR9170_MAX_ACKTABLE_ENTRIES 8 | ||
744 | #define AR9170_MAX_VIRTUAL_MAC 7 | ||
745 | |||
746 | #define AR9170_USB_EP_CTRL_MAX 64 | ||
747 | #define AR9170_USB_EP_TX_MAX 512 | ||
748 | #define AR9170_USB_EP_RX_MAX 512 | ||
749 | #define AR9170_USB_EP_IRQ_MAX 64 | ||
750 | #define AR9170_USB_EP_CMD_MAX 64 | ||
751 | |||
752 | /* Trigger PRETBTT interrupt 6 Kus earlier */ | ||
753 | #define CARL9170_PRETBTT_KUS 6 | ||
754 | |||
755 | #define AR5416_MAX_RATE_POWER 63 | ||
756 | |||
757 | #define SET_VAL(reg, value, newvalue) \ | ||
758 | (value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg)) | ||
759 | |||
760 | #define SET_CONSTVAL(reg, newvalue) \ | ||
761 | (((newvalue) << reg##_S) & reg) | ||
762 | |||
763 | #define MOD_VAL(reg, value, newvalue) \ | ||
764 | (((value) & ~reg) | (((newvalue) << reg##_S) & reg)) | ||
765 | |||
766 | #define GET_VAL(reg, value) \ | ||
767 | (((value) & reg) >> reg##_S) | ||
768 | |||
769 | #endif /* __CARL9170_SHARED_HW_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/led.c b/drivers/net/wireless/ath/carl9170/led.c new file mode 100644 index 000000000000..4bb2cbd8bd9b --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/led.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * LED handling | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparer <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include "carl9170.h" | ||
41 | #include "cmd.h" | ||
42 | |||
43 | int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state) | ||
44 | { | ||
45 | return carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_DATA, led_state); | ||
46 | } | ||
47 | |||
48 | int carl9170_led_init(struct ar9170 *ar) | ||
49 | { | ||
50 | int err; | ||
51 | |||
52 | /* disable LEDs */ | ||
53 | /* GPIO [0/1 mode: output, 2/3: input] */ | ||
54 | err = carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); | ||
55 | if (err) | ||
56 | goto out; | ||
57 | |||
58 | /* GPIO 0/1 value: off */ | ||
59 | err = carl9170_led_set_state(ar, 0); | ||
60 | |||
61 | out: | ||
62 | return err; | ||
63 | } | ||
64 | |||
65 | #ifdef CONFIG_CARL9170_LEDS | ||
66 | static void carl9170_led_update(struct work_struct *work) | ||
67 | { | ||
68 | struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); | ||
69 | int i, tmp = 300, blink_delay = 1000; | ||
70 | u32 led_val = 0; | ||
71 | bool rerun = false; | ||
72 | |||
73 | if (!IS_ACCEPTING_CMD(ar)) | ||
74 | return; | ||
75 | |||
76 | mutex_lock(&ar->mutex); | ||
77 | for (i = 0; i < AR9170_NUM_LEDS; i++) { | ||
78 | if (ar->leds[i].registered) { | ||
79 | if (ar->leds[i].last_state || | ||
80 | ar->leds[i].toggled) { | ||
81 | |||
82 | if (ar->leds[i].toggled) | ||
83 | tmp = 70 + 200 / (ar->leds[i].toggled); | ||
84 | |||
85 | if (tmp < blink_delay) | ||
86 | blink_delay = tmp; | ||
87 | |||
88 | led_val |= 1 << i; | ||
89 | ar->leds[i].toggled = 0; | ||
90 | rerun = true; | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | carl9170_led_set_state(ar, led_val); | ||
96 | mutex_unlock(&ar->mutex); | ||
97 | |||
98 | if (!rerun) | ||
99 | return; | ||
100 | |||
101 | ieee80211_queue_delayed_work(ar->hw, | ||
102 | &ar->led_work, | ||
103 | msecs_to_jiffies(blink_delay)); | ||
104 | } | ||
105 | |||
106 | static void carl9170_led_set_brightness(struct led_classdev *led, | ||
107 | enum led_brightness brightness) | ||
108 | { | ||
109 | struct carl9170_led *arl = container_of(led, struct carl9170_led, l); | ||
110 | struct ar9170 *ar = arl->ar; | ||
111 | |||
112 | if (!arl->registered) | ||
113 | return; | ||
114 | |||
115 | if (arl->last_state != !!brightness) { | ||
116 | arl->toggled++; | ||
117 | arl->last_state = !!brightness; | ||
118 | } | ||
119 | |||
120 | if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) | ||
121 | ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10); | ||
122 | } | ||
123 | |||
124 | static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name, | ||
125 | char *trigger) | ||
126 | { | ||
127 | int err; | ||
128 | |||
129 | snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), | ||
130 | "carl9170-%s::%s", wiphy_name(ar->hw->wiphy), name); | ||
131 | |||
132 | ar->leds[i].ar = ar; | ||
133 | ar->leds[i].l.name = ar->leds[i].name; | ||
134 | ar->leds[i].l.brightness_set = carl9170_led_set_brightness; | ||
135 | ar->leds[i].l.brightness = 0; | ||
136 | ar->leds[i].l.default_trigger = trigger; | ||
137 | |||
138 | err = led_classdev_register(wiphy_dev(ar->hw->wiphy), | ||
139 | &ar->leds[i].l); | ||
140 | if (err) { | ||
141 | wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n", | ||
142 | ar->leds[i].name, err); | ||
143 | } else { | ||
144 | ar->leds[i].registered = true; | ||
145 | } | ||
146 | |||
147 | return err; | ||
148 | } | ||
149 | |||
150 | void carl9170_led_unregister(struct ar9170 *ar) | ||
151 | { | ||
152 | int i; | ||
153 | |||
154 | for (i = 0; i < AR9170_NUM_LEDS; i++) | ||
155 | if (ar->leds[i].registered) { | ||
156 | led_classdev_unregister(&ar->leds[i].l); | ||
157 | ar->leds[i].registered = false; | ||
158 | ar->leds[i].toggled = 0; | ||
159 | } | ||
160 | |||
161 | cancel_delayed_work_sync(&ar->led_work); | ||
162 | } | ||
163 | |||
164 | int carl9170_led_register(struct ar9170 *ar) | ||
165 | { | ||
166 | int err; | ||
167 | |||
168 | INIT_DELAYED_WORK(&ar->led_work, carl9170_led_update); | ||
169 | |||
170 | err = carl9170_led_register_led(ar, 0, "tx", | ||
171 | ieee80211_get_tx_led_name(ar->hw)); | ||
172 | if (err) | ||
173 | goto fail; | ||
174 | |||
175 | if (ar->features & CARL9170_ONE_LED) | ||
176 | return 0; | ||
177 | |||
178 | err = carl9170_led_register_led(ar, 1, "assoc", | ||
179 | ieee80211_get_assoc_led_name(ar->hw)); | ||
180 | if (err) | ||
181 | goto fail; | ||
182 | |||
183 | return 0; | ||
184 | |||
185 | fail: | ||
186 | carl9170_led_unregister(ar); | ||
187 | return err; | ||
188 | } | ||
189 | |||
190 | #endif /* CONFIG_CARL9170_LEDS */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c new file mode 100644 index 000000000000..385cf508479b --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/mac.c | |||
@@ -0,0 +1,616 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * MAC programming | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include <asm/unaligned.h> | ||
40 | |||
41 | #include "carl9170.h" | ||
42 | #include "cmd.h" | ||
43 | |||
44 | int carl9170_set_dyn_sifs_ack(struct ar9170 *ar) | ||
45 | { | ||
46 | u32 val; | ||
47 | |||
48 | if (conf_is_ht40(&ar->hw->conf)) | ||
49 | val = 0x010a; | ||
50 | else { | ||
51 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) | ||
52 | val = 0x105; | ||
53 | else | ||
54 | val = 0x104; | ||
55 | } | ||
56 | |||
57 | return carl9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val); | ||
58 | } | ||
59 | |||
60 | int carl9170_set_rts_cts_rate(struct ar9170 *ar) | ||
61 | { | ||
62 | u32 rts_rate, cts_rate; | ||
63 | |||
64 | if (conf_is_ht(&ar->hw->conf)) { | ||
65 | /* 12 mbit OFDM */ | ||
66 | rts_rate = 0x1da; | ||
67 | cts_rate = 0x10a; | ||
68 | } else { | ||
69 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { | ||
70 | /* 11 mbit CCK */ | ||
71 | rts_rate = 033; | ||
72 | cts_rate = 003; | ||
73 | } else { | ||
74 | /* 6 mbit OFDM */ | ||
75 | rts_rate = 0x1bb; | ||
76 | cts_rate = 0x10b; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | return carl9170_write_reg(ar, AR9170_MAC_REG_RTS_CTS_RATE, | ||
81 | rts_rate | (cts_rate) << 16); | ||
82 | } | ||
83 | |||
84 | int carl9170_set_slot_time(struct ar9170 *ar) | ||
85 | { | ||
86 | struct ieee80211_vif *vif; | ||
87 | u32 slottime = 20; | ||
88 | |||
89 | rcu_read_lock(); | ||
90 | vif = carl9170_get_main_vif(ar); | ||
91 | if (!vif) { | ||
92 | rcu_read_unlock(); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) || | ||
97 | vif->bss_conf.use_short_slot) | ||
98 | slottime = 9; | ||
99 | |||
100 | rcu_read_unlock(); | ||
101 | |||
102 | return carl9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, | ||
103 | slottime << 10); | ||
104 | } | ||
105 | |||
106 | int carl9170_set_mac_rates(struct ar9170 *ar) | ||
107 | { | ||
108 | struct ieee80211_vif *vif; | ||
109 | u32 basic, mandatory; | ||
110 | |||
111 | rcu_read_lock(); | ||
112 | vif = carl9170_get_main_vif(ar); | ||
113 | |||
114 | if (!vif) { | ||
115 | rcu_read_unlock(); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | basic = (vif->bss_conf.basic_rates & 0xf); | ||
120 | basic |= (vif->bss_conf.basic_rates & 0xff0) << 4; | ||
121 | rcu_read_unlock(); | ||
122 | |||
123 | if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) | ||
124 | mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */ | ||
125 | else | ||
126 | mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */ | ||
127 | |||
128 | carl9170_regwrite_begin(ar); | ||
129 | carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, basic); | ||
130 | carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, mandatory); | ||
131 | carl9170_regwrite_finish(); | ||
132 | |||
133 | return carl9170_regwrite_result(); | ||
134 | } | ||
135 | |||
136 | int carl9170_set_qos(struct ar9170 *ar) | ||
137 | { | ||
138 | carl9170_regwrite_begin(ar); | ||
139 | |||
140 | carl9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | | ||
141 | (ar->edcf[0].cw_max << 16)); | ||
142 | carl9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | | ||
143 | (ar->edcf[1].cw_max << 16)); | ||
144 | carl9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | | ||
145 | (ar->edcf[2].cw_max << 16)); | ||
146 | carl9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | | ||
147 | (ar->edcf[3].cw_max << 16)); | ||
148 | carl9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | | ||
149 | (ar->edcf[4].cw_max << 16)); | ||
150 | |||
151 | carl9170_regwrite(AR9170_MAC_REG_AC2_AC1_AC0_AIFS, | ||
152 | ((ar->edcf[0].aifs * 9 + 10)) | | ||
153 | ((ar->edcf[1].aifs * 9 + 10) << 12) | | ||
154 | ((ar->edcf[2].aifs * 9 + 10) << 24)); | ||
155 | carl9170_regwrite(AR9170_MAC_REG_AC4_AC3_AC2_AIFS, | ||
156 | ((ar->edcf[2].aifs * 9 + 10) >> 8) | | ||
157 | ((ar->edcf[3].aifs * 9 + 10) << 4) | | ||
158 | ((ar->edcf[4].aifs * 9 + 10) << 16)); | ||
159 | |||
160 | carl9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, | ||
161 | ar->edcf[0].txop | ar->edcf[1].txop << 16); | ||
162 | carl9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, | ||
163 | ar->edcf[2].txop | ar->edcf[3].txop << 16 | | ||
164 | ar->edcf[4].txop << 24); | ||
165 | |||
166 | carl9170_regwrite_finish(); | ||
167 | |||
168 | return carl9170_regwrite_result(); | ||
169 | } | ||
170 | |||
171 | int carl9170_init_mac(struct ar9170 *ar) | ||
172 | { | ||
173 | carl9170_regwrite_begin(ar); | ||
174 | |||
175 | /* switch MAC to OTUS interface */ | ||
176 | carl9170_regwrite(0x1c3600, 0x3); | ||
177 | |||
178 | carl9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); | ||
179 | |||
180 | carl9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0x0); | ||
181 | |||
182 | carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, | ||
183 | AR9170_MAC_FTF_MONITOR); | ||
184 | |||
185 | /* enable MMIC */ | ||
186 | carl9170_regwrite(AR9170_MAC_REG_SNIFFER, | ||
187 | AR9170_MAC_SNIFFER_DEFAULTS); | ||
188 | |||
189 | carl9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); | ||
190 | |||
191 | carl9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); | ||
192 | carl9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); | ||
193 | carl9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); | ||
194 | |||
195 | /* CF-END & CF-ACK rate => 24M OFDM */ | ||
196 | carl9170_regwrite(AR9170_MAC_REG_TID_CFACK_CFEND_RATE, 0x59900000); | ||
197 | |||
198 | /* NAV protects ACK only (in TXOP) */ | ||
199 | carl9170_regwrite(AR9170_MAC_REG_TXOP_DURATION, 0x201); | ||
200 | |||
201 | /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ | ||
202 | /* OTUS set AM to 0x1 */ | ||
203 | carl9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); | ||
204 | |||
205 | carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); | ||
206 | |||
207 | /* Aggregation MAX number and timeout */ | ||
208 | carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0x8000a); | ||
209 | carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a07); | ||
210 | |||
211 | carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, | ||
212 | AR9170_MAC_FTF_DEFAULTS); | ||
213 | |||
214 | carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL, | ||
215 | AR9170_MAC_RX_CTRL_DEAGG | | ||
216 | AR9170_MAC_RX_CTRL_SHORT_FILTER); | ||
217 | |||
218 | /* rate sets */ | ||
219 | carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); | ||
220 | carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); | ||
221 | carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x0030033); | ||
222 | |||
223 | /* MIMO response control */ | ||
224 | carl9170_regwrite(AR9170_MAC_REG_ACK_TPC, 0x4003c1e); | ||
225 | |||
226 | carl9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); | ||
227 | |||
228 | /* set PHY register read timeout (??) */ | ||
229 | carl9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); | ||
230 | |||
231 | /* Disable Rx TimeOut, workaround for BB. */ | ||
232 | carl9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); | ||
233 | |||
234 | /* Set WLAN DMA interrupt mode: generate int per packet */ | ||
235 | carl9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); | ||
236 | |||
237 | carl9170_regwrite(AR9170_MAC_REG_FCS_SELECT, | ||
238 | AR9170_MAC_FCS_FIFO_PROT); | ||
239 | |||
240 | /* Disables the CF_END frame, undocumented register */ | ||
241 | carl9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, | ||
242 | 0x141e0f48); | ||
243 | |||
244 | /* reset group hash table */ | ||
245 | carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, 0xffffffff); | ||
246 | carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, 0xffffffff); | ||
247 | |||
248 | /* disable PRETBTT interrupt */ | ||
249 | carl9170_regwrite(AR9170_MAC_REG_PRETBTT, 0x0); | ||
250 | carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, 0x0); | ||
251 | |||
252 | carl9170_regwrite_finish(); | ||
253 | |||
254 | return carl9170_regwrite_result(); | ||
255 | } | ||
256 | |||
257 | static int carl9170_set_mac_reg(struct ar9170 *ar, | ||
258 | const u32 reg, const u8 *mac) | ||
259 | { | ||
260 | static const u8 zero[ETH_ALEN] = { 0 }; | ||
261 | |||
262 | if (!mac) | ||
263 | mac = zero; | ||
264 | |||
265 | carl9170_regwrite_begin(ar); | ||
266 | |||
267 | carl9170_regwrite(reg, get_unaligned_le32(mac)); | ||
268 | carl9170_regwrite(reg + 4, get_unaligned_le16(mac + 4)); | ||
269 | |||
270 | carl9170_regwrite_finish(); | ||
271 | |||
272 | return carl9170_regwrite_result(); | ||
273 | } | ||
274 | |||
275 | int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id, | ||
276 | const u8 *mac) | ||
277 | { | ||
278 | if (WARN_ON(id >= ar->fw.vif_num)) | ||
279 | return -EINVAL; | ||
280 | |||
281 | return carl9170_set_mac_reg(ar, | ||
282 | AR9170_MAC_REG_ACK_TABLE + (id - 1) * 8, mac); | ||
283 | } | ||
284 | |||
285 | int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hash) | ||
286 | { | ||
287 | int err; | ||
288 | |||
289 | carl9170_regwrite_begin(ar); | ||
290 | carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32); | ||
291 | carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash); | ||
292 | carl9170_regwrite_finish(); | ||
293 | err = carl9170_regwrite_result(); | ||
294 | if (err) | ||
295 | return err; | ||
296 | |||
297 | ar->cur_mc_hash = mc_hash; | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | int carl9170_set_operating_mode(struct ar9170 *ar) | ||
302 | { | ||
303 | struct ieee80211_vif *vif; | ||
304 | struct ath_common *common = &ar->common; | ||
305 | u8 *mac_addr, *bssid; | ||
306 | u32 cam_mode = AR9170_MAC_CAM_DEFAULTS; | ||
307 | u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS; | ||
308 | u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG | | ||
309 | AR9170_MAC_RX_CTRL_SHORT_FILTER; | ||
310 | u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS; | ||
311 | int err = 0; | ||
312 | |||
313 | rcu_read_lock(); | ||
314 | vif = carl9170_get_main_vif(ar); | ||
315 | |||
316 | if (vif) { | ||
317 | mac_addr = common->macaddr; | ||
318 | bssid = common->curbssid; | ||
319 | |||
320 | switch (vif->type) { | ||
321 | case NL80211_IFTYPE_MESH_POINT: | ||
322 | case NL80211_IFTYPE_ADHOC: | ||
323 | cam_mode |= AR9170_MAC_CAM_IBSS; | ||
324 | break; | ||
325 | case NL80211_IFTYPE_AP: | ||
326 | cam_mode |= AR9170_MAC_CAM_AP; | ||
327 | |||
328 | /* iwlagn 802.11n STA Workaround */ | ||
329 | rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST; | ||
330 | break; | ||
331 | case NL80211_IFTYPE_WDS: | ||
332 | cam_mode |= AR9170_MAC_CAM_AP_WDS; | ||
333 | rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST; | ||
334 | break; | ||
335 | case NL80211_IFTYPE_STATION: | ||
336 | cam_mode |= AR9170_MAC_CAM_STA; | ||
337 | rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST; | ||
338 | break; | ||
339 | default: | ||
340 | WARN(1, "Unsupported operation mode %x\n", vif->type); | ||
341 | err = -EOPNOTSUPP; | ||
342 | break; | ||
343 | } | ||
344 | } else { | ||
345 | mac_addr = NULL; | ||
346 | bssid = NULL; | ||
347 | } | ||
348 | rcu_read_unlock(); | ||
349 | |||
350 | if (err) | ||
351 | return err; | ||
352 | |||
353 | if (ar->rx_software_decryption) | ||
354 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; | ||
355 | |||
356 | if (ar->sniffer_enabled) { | ||
357 | rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER; | ||
358 | sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC; | ||
359 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; | ||
360 | } | ||
361 | |||
362 | err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); | ||
363 | if (err) | ||
364 | return err; | ||
365 | |||
366 | err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); | ||
367 | if (err) | ||
368 | return err; | ||
369 | |||
370 | carl9170_regwrite_begin(ar); | ||
371 | carl9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); | ||
372 | carl9170_regwrite(AR9170_MAC_REG_CAM_MODE, cam_mode); | ||
373 | carl9170_regwrite(AR9170_MAC_REG_ENCRYPTION, enc_mode); | ||
374 | carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL, rx_ctrl); | ||
375 | carl9170_regwrite_finish(); | ||
376 | |||
377 | return carl9170_regwrite_result(); | ||
378 | } | ||
379 | |||
380 | int carl9170_set_hwretry_limit(struct ar9170 *ar, const unsigned int max_retry) | ||
381 | { | ||
382 | u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); | ||
383 | |||
384 | return carl9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); | ||
385 | } | ||
386 | |||
387 | int carl9170_set_beacon_timers(struct ar9170 *ar) | ||
388 | { | ||
389 | struct ieee80211_vif *vif; | ||
390 | u32 v = 0; | ||
391 | u32 pretbtt = 0; | ||
392 | |||
393 | rcu_read_lock(); | ||
394 | vif = carl9170_get_main_vif(ar); | ||
395 | |||
396 | if (vif) { | ||
397 | struct carl9170_vif_info *mvif; | ||
398 | mvif = (void *) vif->drv_priv; | ||
399 | |||
400 | if (mvif->enable_beacon && !WARN_ON(!ar->beacon_enabled)) { | ||
401 | ar->global_beacon_int = vif->bss_conf.beacon_int / | ||
402 | ar->beacon_enabled; | ||
403 | |||
404 | SET_VAL(AR9170_MAC_BCN_DTIM, v, | ||
405 | vif->bss_conf.dtim_period); | ||
406 | |||
407 | switch (vif->type) { | ||
408 | case NL80211_IFTYPE_MESH_POINT: | ||
409 | case NL80211_IFTYPE_ADHOC: | ||
410 | v |= AR9170_MAC_BCN_IBSS_MODE; | ||
411 | break; | ||
412 | case NL80211_IFTYPE_AP: | ||
413 | v |= AR9170_MAC_BCN_AP_MODE; | ||
414 | break; | ||
415 | default: | ||
416 | WARN_ON_ONCE(1); | ||
417 | break; | ||
418 | } | ||
419 | } else if (vif->type == NL80211_IFTYPE_STATION) { | ||
420 | ar->global_beacon_int = vif->bss_conf.beacon_int; | ||
421 | |||
422 | SET_VAL(AR9170_MAC_BCN_DTIM, v, | ||
423 | ar->hw->conf.ps_dtim_period); | ||
424 | |||
425 | v |= AR9170_MAC_BCN_STA_PS | | ||
426 | AR9170_MAC_BCN_PWR_MGT; | ||
427 | } | ||
428 | |||
429 | if (ar->global_beacon_int) { | ||
430 | if (ar->global_beacon_int < 15) { | ||
431 | rcu_read_unlock(); | ||
432 | return -ERANGE; | ||
433 | } | ||
434 | |||
435 | ar->global_pretbtt = ar->global_beacon_int - | ||
436 | CARL9170_PRETBTT_KUS; | ||
437 | } else { | ||
438 | ar->global_pretbtt = 0; | ||
439 | } | ||
440 | } else { | ||
441 | ar->global_beacon_int = 0; | ||
442 | ar->global_pretbtt = 0; | ||
443 | } | ||
444 | |||
445 | rcu_read_unlock(); | ||
446 | |||
447 | SET_VAL(AR9170_MAC_BCN_PERIOD, v, ar->global_beacon_int); | ||
448 | SET_VAL(AR9170_MAC_PRETBTT, pretbtt, ar->global_pretbtt); | ||
449 | SET_VAL(AR9170_MAC_PRETBTT2, pretbtt, ar->global_pretbtt); | ||
450 | |||
451 | carl9170_regwrite_begin(ar); | ||
452 | carl9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); | ||
453 | carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); | ||
454 | carl9170_regwrite_finish(); | ||
455 | return carl9170_regwrite_result(); | ||
456 | } | ||
457 | |||
458 | int carl9170_update_beacon(struct ar9170 *ar, const bool submit) | ||
459 | { | ||
460 | struct sk_buff *skb = NULL; | ||
461 | struct carl9170_vif_info *cvif; | ||
462 | struct ieee80211_tx_info *txinfo; | ||
463 | __le32 *data, *old = NULL; | ||
464 | u32 word, off, addr, len; | ||
465 | int i = 0, err = 0; | ||
466 | |||
467 | rcu_read_lock(); | ||
468 | cvif = rcu_dereference(ar->beacon_iter); | ||
469 | retry: | ||
470 | if (ar->vifs == 0 || !cvif) | ||
471 | goto out_unlock; | ||
472 | |||
473 | list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) { | ||
474 | if (cvif->active && cvif->enable_beacon) | ||
475 | goto found; | ||
476 | } | ||
477 | |||
478 | if (!ar->beacon_enabled || i++) | ||
479 | goto out_unlock; | ||
480 | |||
481 | goto retry; | ||
482 | |||
483 | found: | ||
484 | rcu_assign_pointer(ar->beacon_iter, cvif); | ||
485 | |||
486 | skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif), | ||
487 | NULL, NULL); | ||
488 | |||
489 | if (!skb) { | ||
490 | err = -ENOMEM; | ||
491 | goto err_free; | ||
492 | } | ||
493 | |||
494 | txinfo = IEEE80211_SKB_CB(skb); | ||
495 | if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) { | ||
496 | err = -EINVAL; | ||
497 | goto err_free; | ||
498 | } | ||
499 | |||
500 | spin_lock_bh(&ar->beacon_lock); | ||
501 | data = (__le32 *)skb->data; | ||
502 | if (cvif->beacon) | ||
503 | old = (__le32 *)cvif->beacon->data; | ||
504 | |||
505 | off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX; | ||
506 | addr = ar->fw.beacon_addr + off; | ||
507 | len = roundup(skb->len + FCS_LEN, 4); | ||
508 | |||
509 | if ((off + len) > ar->fw.beacon_max_len) { | ||
510 | if (net_ratelimit()) { | ||
511 | wiphy_err(ar->hw->wiphy, "beacon does not " | ||
512 | "fit into device memory!\n"); | ||
513 | } | ||
514 | err = -EINVAL; | ||
515 | goto err_unlock; | ||
516 | } | ||
517 | |||
518 | if (len > AR9170_MAC_BCN_LENGTH_MAX) { | ||
519 | if (net_ratelimit()) { | ||
520 | wiphy_err(ar->hw->wiphy, "no support for beacons " | ||
521 | "bigger than %d (yours:%d).\n", | ||
522 | AR9170_MAC_BCN_LENGTH_MAX, len); | ||
523 | } | ||
524 | |||
525 | err = -EMSGSIZE; | ||
526 | goto err_unlock; | ||
527 | } | ||
528 | |||
529 | i = txinfo->control.rates[0].idx; | ||
530 | if (txinfo->band != IEEE80211_BAND_2GHZ) | ||
531 | i += 4; | ||
532 | |||
533 | word = __carl9170_ratetable[i].hw_value & 0xf; | ||
534 | if (i < 4) | ||
535 | word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; | ||
536 | else | ||
537 | word |= ((skb->len + FCS_LEN) << 16) + 0x0010; | ||
538 | |||
539 | carl9170_async_regwrite_begin(ar); | ||
540 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word); | ||
541 | |||
542 | for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { | ||
543 | /* | ||
544 | * XXX: This accesses beyond skb data for up | ||
545 | * to the last 3 bytes!! | ||
546 | */ | ||
547 | |||
548 | if (old && (data[i] == old[i])) | ||
549 | continue; | ||
550 | |||
551 | word = le32_to_cpu(data[i]); | ||
552 | carl9170_async_regwrite(addr + 4 * i, word); | ||
553 | } | ||
554 | carl9170_async_regwrite_finish(); | ||
555 | |||
556 | dev_kfree_skb_any(cvif->beacon); | ||
557 | cvif->beacon = NULL; | ||
558 | |||
559 | err = carl9170_async_regwrite_result(); | ||
560 | if (!err) | ||
561 | cvif->beacon = skb; | ||
562 | spin_unlock_bh(&ar->beacon_lock); | ||
563 | if (err) | ||
564 | goto err_free; | ||
565 | |||
566 | if (submit) { | ||
567 | err = carl9170_bcn_ctrl(ar, cvif->id, | ||
568 | CARL9170_BCN_CTRL_CAB_TRIGGER, | ||
569 | addr, skb->len + FCS_LEN); | ||
570 | |||
571 | if (err) | ||
572 | goto err_free; | ||
573 | } | ||
574 | out_unlock: | ||
575 | rcu_read_unlock(); | ||
576 | return 0; | ||
577 | |||
578 | err_unlock: | ||
579 | spin_unlock_bh(&ar->beacon_lock); | ||
580 | |||
581 | err_free: | ||
582 | rcu_read_unlock(); | ||
583 | dev_kfree_skb_any(skb); | ||
584 | return err; | ||
585 | } | ||
586 | |||
587 | int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac, | ||
588 | const u8 ktype, const u8 keyidx, const u8 *keydata, | ||
589 | const int keylen) | ||
590 | { | ||
591 | struct carl9170_set_key_cmd key = { }; | ||
592 | static const u8 bcast[ETH_ALEN] = { | ||
593 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
594 | |||
595 | mac = mac ? : bcast; | ||
596 | |||
597 | key.user = cpu_to_le16(id); | ||
598 | key.keyId = cpu_to_le16(keyidx); | ||
599 | key.type = cpu_to_le16(ktype); | ||
600 | memcpy(&key.macAddr, mac, ETH_ALEN); | ||
601 | if (keydata) | ||
602 | memcpy(&key.key, keydata, keylen); | ||
603 | |||
604 | return carl9170_exec_cmd(ar, CARL9170_CMD_EKEY, | ||
605 | sizeof(key), (u8 *)&key, 0, NULL); | ||
606 | } | ||
607 | |||
608 | int carl9170_disable_key(struct ar9170 *ar, const u8 id) | ||
609 | { | ||
610 | struct carl9170_disable_key_cmd key = { }; | ||
611 | |||
612 | key.user = cpu_to_le16(id); | ||
613 | |||
614 | return carl9170_exec_cmd(ar, CARL9170_CMD_DKEY, | ||
615 | sizeof(key), (u8 *)&key, 0, NULL); | ||
616 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c new file mode 100644 index 000000000000..54d093c2ab44 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -0,0 +1,1831 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * mac80211 interaction code | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/module.h> | ||
43 | #include <linux/etherdevice.h> | ||
44 | #include <linux/random.h> | ||
45 | #include <net/mac80211.h> | ||
46 | #include <net/cfg80211.h> | ||
47 | #include "hw.h" | ||
48 | #include "carl9170.h" | ||
49 | #include "cmd.h" | ||
50 | |||
51 | static int modparam_nohwcrypt; | ||
52 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | ||
53 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware crypto offload."); | ||
54 | |||
55 | int modparam_noht; | ||
56 | module_param_named(noht, modparam_noht, int, S_IRUGO); | ||
57 | MODULE_PARM_DESC(noht, "Disable MPDU aggregation."); | ||
58 | |||
59 | #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ | ||
60 | .bitrate = (_bitrate), \ | ||
61 | .flags = (_flags), \ | ||
62 | .hw_value = (_hw_rate) | (_txpidx) << 4, \ | ||
63 | } | ||
64 | |||
65 | struct ieee80211_rate __carl9170_ratetable[] = { | ||
66 | RATE(10, 0, 0, 0), | ||
67 | RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), | ||
68 | RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), | ||
69 | RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), | ||
70 | RATE(60, 0xb, 0, 0), | ||
71 | RATE(90, 0xf, 0, 0), | ||
72 | RATE(120, 0xa, 0, 0), | ||
73 | RATE(180, 0xe, 0, 0), | ||
74 | RATE(240, 0x9, 0, 0), | ||
75 | RATE(360, 0xd, 1, 0), | ||
76 | RATE(480, 0x8, 2, 0), | ||
77 | RATE(540, 0xc, 3, 0), | ||
78 | }; | ||
79 | #undef RATE | ||
80 | |||
81 | #define carl9170_g_ratetable (__carl9170_ratetable + 0) | ||
82 | #define carl9170_g_ratetable_size 12 | ||
83 | #define carl9170_a_ratetable (__carl9170_ratetable + 4) | ||
84 | #define carl9170_a_ratetable_size 8 | ||
85 | |||
86 | /* | ||
87 | * NB: The hw_value is used as an index into the carl9170_phy_freq_params | ||
88 | * array in phy.c so that we don't have to do frequency lookups! | ||
89 | */ | ||
90 | #define CHAN(_freq, _idx) { \ | ||
91 | .center_freq = (_freq), \ | ||
92 | .hw_value = (_idx), \ | ||
93 | .max_power = 18, /* XXX */ \ | ||
94 | } | ||
95 | |||
96 | static struct ieee80211_channel carl9170_2ghz_chantable[] = { | ||
97 | CHAN(2412, 0), | ||
98 | CHAN(2417, 1), | ||
99 | CHAN(2422, 2), | ||
100 | CHAN(2427, 3), | ||
101 | CHAN(2432, 4), | ||
102 | CHAN(2437, 5), | ||
103 | CHAN(2442, 6), | ||
104 | CHAN(2447, 7), | ||
105 | CHAN(2452, 8), | ||
106 | CHAN(2457, 9), | ||
107 | CHAN(2462, 10), | ||
108 | CHAN(2467, 11), | ||
109 | CHAN(2472, 12), | ||
110 | CHAN(2484, 13), | ||
111 | }; | ||
112 | |||
113 | static struct ieee80211_channel carl9170_5ghz_chantable[] = { | ||
114 | CHAN(4920, 14), | ||
115 | CHAN(4940, 15), | ||
116 | CHAN(4960, 16), | ||
117 | CHAN(4980, 17), | ||
118 | CHAN(5040, 18), | ||
119 | CHAN(5060, 19), | ||
120 | CHAN(5080, 20), | ||
121 | CHAN(5180, 21), | ||
122 | CHAN(5200, 22), | ||
123 | CHAN(5220, 23), | ||
124 | CHAN(5240, 24), | ||
125 | CHAN(5260, 25), | ||
126 | CHAN(5280, 26), | ||
127 | CHAN(5300, 27), | ||
128 | CHAN(5320, 28), | ||
129 | CHAN(5500, 29), | ||
130 | CHAN(5520, 30), | ||
131 | CHAN(5540, 31), | ||
132 | CHAN(5560, 32), | ||
133 | CHAN(5580, 33), | ||
134 | CHAN(5600, 34), | ||
135 | CHAN(5620, 35), | ||
136 | CHAN(5640, 36), | ||
137 | CHAN(5660, 37), | ||
138 | CHAN(5680, 38), | ||
139 | CHAN(5700, 39), | ||
140 | CHAN(5745, 40), | ||
141 | CHAN(5765, 41), | ||
142 | CHAN(5785, 42), | ||
143 | CHAN(5805, 43), | ||
144 | CHAN(5825, 44), | ||
145 | CHAN(5170, 45), | ||
146 | CHAN(5190, 46), | ||
147 | CHAN(5210, 47), | ||
148 | CHAN(5230, 48), | ||
149 | }; | ||
150 | #undef CHAN | ||
151 | |||
152 | #define CARL9170_HT_CAP \ | ||
153 | { \ | ||
154 | .ht_supported = true, \ | ||
155 | .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ | ||
156 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ | ||
157 | IEEE80211_HT_CAP_SGI_40 | \ | ||
158 | IEEE80211_HT_CAP_DSSSCCK40 | \ | ||
159 | IEEE80211_HT_CAP_SM_PS, \ | ||
160 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ | ||
161 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ | ||
162 | .mcs = { \ | ||
163 | .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ | ||
164 | .rx_highest = cpu_to_le16(300), \ | ||
165 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ | ||
166 | }, \ | ||
167 | } | ||
168 | |||
169 | static struct ieee80211_supported_band carl9170_band_2GHz = { | ||
170 | .channels = carl9170_2ghz_chantable, | ||
171 | .n_channels = ARRAY_SIZE(carl9170_2ghz_chantable), | ||
172 | .bitrates = carl9170_g_ratetable, | ||
173 | .n_bitrates = carl9170_g_ratetable_size, | ||
174 | .ht_cap = CARL9170_HT_CAP, | ||
175 | }; | ||
176 | |||
177 | static struct ieee80211_supported_band carl9170_band_5GHz = { | ||
178 | .channels = carl9170_5ghz_chantable, | ||
179 | .n_channels = ARRAY_SIZE(carl9170_5ghz_chantable), | ||
180 | .bitrates = carl9170_a_ratetable, | ||
181 | .n_bitrates = carl9170_a_ratetable_size, | ||
182 | .ht_cap = CARL9170_HT_CAP, | ||
183 | }; | ||
184 | |||
185 | static void carl9170_ampdu_gc(struct ar9170 *ar) | ||
186 | { | ||
187 | struct carl9170_sta_tid *tid_info; | ||
188 | LIST_HEAD(tid_gc); | ||
189 | |||
190 | rcu_read_lock(); | ||
191 | list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) { | ||
192 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
193 | if (tid_info->state == CARL9170_TID_STATE_SHUTDOWN) { | ||
194 | tid_info->state = CARL9170_TID_STATE_KILLED; | ||
195 | list_del_rcu(&tid_info->list); | ||
196 | ar->tx_ampdu_list_len--; | ||
197 | list_add_tail(&tid_info->tmp_list, &tid_gc); | ||
198 | } | ||
199 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
200 | |||
201 | } | ||
202 | rcu_assign_pointer(ar->tx_ampdu_iter, tid_info); | ||
203 | rcu_read_unlock(); | ||
204 | |||
205 | synchronize_rcu(); | ||
206 | |||
207 | while (!list_empty(&tid_gc)) { | ||
208 | struct sk_buff *skb; | ||
209 | tid_info = list_first_entry(&tid_gc, struct carl9170_sta_tid, | ||
210 | tmp_list); | ||
211 | |||
212 | while ((skb = __skb_dequeue(&tid_info->queue))) | ||
213 | carl9170_tx_status(ar, skb, false); | ||
214 | |||
215 | list_del_init(&tid_info->tmp_list); | ||
216 | kfree(tid_info); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | static void carl9170_flush(struct ar9170 *ar, bool drop_queued) | ||
221 | { | ||
222 | if (drop_queued) { | ||
223 | int i; | ||
224 | |||
225 | /* | ||
226 | * We can only drop frames which have not been uploaded | ||
227 | * to the device yet. | ||
228 | */ | ||
229 | |||
230 | for (i = 0; i < ar->hw->queues; i++) { | ||
231 | struct sk_buff *skb; | ||
232 | |||
233 | while ((skb = skb_dequeue(&ar->tx_pending[i]))) { | ||
234 | struct ieee80211_tx_info *info; | ||
235 | |||
236 | info = IEEE80211_SKB_CB(skb); | ||
237 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
238 | atomic_dec(&ar->tx_ampdu_upload); | ||
239 | |||
240 | carl9170_tx_status(ar, skb, false); | ||
241 | } | ||
242 | } | ||
243 | } | ||
244 | |||
245 | /* Wait for all other outstanding frames to timeout. */ | ||
246 | if (atomic_read(&ar->tx_total_queued)) | ||
247 | WARN_ON(wait_for_completion_timeout(&ar->tx_flush, HZ) == 0); | ||
248 | } | ||
249 | |||
250 | static void carl9170_flush_ba(struct ar9170 *ar) | ||
251 | { | ||
252 | struct sk_buff_head free; | ||
253 | struct carl9170_sta_tid *tid_info; | ||
254 | struct sk_buff *skb; | ||
255 | |||
256 | __skb_queue_head_init(&free); | ||
257 | |||
258 | rcu_read_lock(); | ||
259 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
260 | list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) { | ||
261 | if (tid_info->state > CARL9170_TID_STATE_SUSPEND) { | ||
262 | tid_info->state = CARL9170_TID_STATE_SUSPEND; | ||
263 | |||
264 | spin_lock(&tid_info->lock); | ||
265 | while ((skb = __skb_dequeue(&tid_info->queue))) | ||
266 | __skb_queue_tail(&free, skb); | ||
267 | spin_unlock(&tid_info->lock); | ||
268 | } | ||
269 | } | ||
270 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
271 | rcu_read_unlock(); | ||
272 | |||
273 | while ((skb = __skb_dequeue(&free))) | ||
274 | carl9170_tx_status(ar, skb, false); | ||
275 | } | ||
276 | |||
277 | static void carl9170_zap_queues(struct ar9170 *ar) | ||
278 | { | ||
279 | struct carl9170_vif_info *cvif; | ||
280 | unsigned int i; | ||
281 | |||
282 | carl9170_ampdu_gc(ar); | ||
283 | |||
284 | carl9170_flush_ba(ar); | ||
285 | carl9170_flush(ar, true); | ||
286 | |||
287 | for (i = 0; i < ar->hw->queues; i++) { | ||
288 | spin_lock_bh(&ar->tx_status[i].lock); | ||
289 | while (!skb_queue_empty(&ar->tx_status[i])) { | ||
290 | struct sk_buff *skb; | ||
291 | |||
292 | skb = skb_peek(&ar->tx_status[i]); | ||
293 | carl9170_tx_get_skb(skb); | ||
294 | spin_unlock_bh(&ar->tx_status[i].lock); | ||
295 | carl9170_tx_drop(ar, skb); | ||
296 | spin_lock_bh(&ar->tx_status[i].lock); | ||
297 | carl9170_tx_put_skb(skb); | ||
298 | } | ||
299 | spin_unlock_bh(&ar->tx_status[i].lock); | ||
300 | } | ||
301 | |||
302 | BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_SOFT < 1); | ||
303 | BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD < CARL9170_NUM_TX_LIMIT_SOFT); | ||
304 | BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD >= CARL9170_BAW_BITS); | ||
305 | |||
306 | /* reinitialize queues statistics */ | ||
307 | memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); | ||
308 | for (i = 0; i < ar->hw->queues; i++) | ||
309 | ar->tx_stats[i].limit = CARL9170_NUM_TX_LIMIT_HARD; | ||
310 | |||
311 | for (i = 0; i < DIV_ROUND_UP(ar->fw.mem_blocks, BITS_PER_LONG); i++) | ||
312 | ar->mem_bitmap[i] = 0; | ||
313 | |||
314 | rcu_read_lock(); | ||
315 | list_for_each_entry_rcu(cvif, &ar->vif_list, list) { | ||
316 | spin_lock_bh(&ar->beacon_lock); | ||
317 | dev_kfree_skb_any(cvif->beacon); | ||
318 | cvif->beacon = NULL; | ||
319 | spin_unlock_bh(&ar->beacon_lock); | ||
320 | } | ||
321 | rcu_read_unlock(); | ||
322 | |||
323 | atomic_set(&ar->tx_ampdu_upload, 0); | ||
324 | atomic_set(&ar->tx_ampdu_scheduler, 0); | ||
325 | atomic_set(&ar->tx_total_pending, 0); | ||
326 | atomic_set(&ar->tx_total_queued, 0); | ||
327 | atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks); | ||
328 | } | ||
329 | |||
330 | #define CARL9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ | ||
331 | do { \ | ||
332 | queue.aifs = ai_fs; \ | ||
333 | queue.cw_min = cwmin; \ | ||
334 | queue.cw_max = cwmax; \ | ||
335 | queue.txop = _txop; \ | ||
336 | } while (0) | ||
337 | |||
338 | static int carl9170_op_start(struct ieee80211_hw *hw) | ||
339 | { | ||
340 | struct ar9170 *ar = hw->priv; | ||
341 | int err, i; | ||
342 | |||
343 | mutex_lock(&ar->mutex); | ||
344 | |||
345 | carl9170_zap_queues(ar); | ||
346 | |||
347 | /* reset QoS defaults */ | ||
348 | CARL9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT */ | ||
349 | CARL9170_FILL_QUEUE(ar->edcf[1], 2, 7, 15, 94); /* VIDEO */ | ||
350 | CARL9170_FILL_QUEUE(ar->edcf[2], 2, 3, 7, 47); /* VOICE */ | ||
351 | CARL9170_FILL_QUEUE(ar->edcf[3], 7, 15, 1023, 0); /* BACKGROUND */ | ||
352 | CARL9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ | ||
353 | |||
354 | ar->current_factor = ar->current_density = -1; | ||
355 | /* "The first key is unique." */ | ||
356 | ar->usedkeys = 1; | ||
357 | ar->filter_state = 0; | ||
358 | ar->ps.last_action = jiffies; | ||
359 | ar->ps.last_slept = jiffies; | ||
360 | ar->erp_mode = CARL9170_ERP_AUTO; | ||
361 | ar->rx_software_decryption = false; | ||
362 | ar->disable_offload = false; | ||
363 | |||
364 | for (i = 0; i < ar->hw->queues; i++) { | ||
365 | ar->queue_stop_timeout[i] = jiffies; | ||
366 | ar->max_queue_stop_timeout[i] = 0; | ||
367 | } | ||
368 | |||
369 | atomic_set(&ar->mem_allocs, 0); | ||
370 | |||
371 | err = carl9170_usb_open(ar); | ||
372 | if (err) | ||
373 | goto out; | ||
374 | |||
375 | err = carl9170_init_mac(ar); | ||
376 | if (err) | ||
377 | goto out; | ||
378 | |||
379 | err = carl9170_set_qos(ar); | ||
380 | if (err) | ||
381 | goto out; | ||
382 | |||
383 | if (ar->fw.rx_filter) { | ||
384 | err = carl9170_rx_filter(ar, CARL9170_RX_FILTER_OTHER_RA | | ||
385 | CARL9170_RX_FILTER_CTL_OTHER | CARL9170_RX_FILTER_BAD); | ||
386 | if (err) | ||
387 | goto out; | ||
388 | } | ||
389 | |||
390 | err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, | ||
391 | AR9170_DMA_TRIGGER_RXQ); | ||
392 | if (err) | ||
393 | goto out; | ||
394 | |||
395 | /* Clear key-cache */ | ||
396 | for (i = 0; i < AR9170_CAM_MAX_USER + 4; i++) { | ||
397 | err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE, | ||
398 | 0, NULL, 0); | ||
399 | if (err) | ||
400 | goto out; | ||
401 | |||
402 | err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE, | ||
403 | 1, NULL, 0); | ||
404 | if (err) | ||
405 | goto out; | ||
406 | |||
407 | if (i < AR9170_CAM_MAX_USER) { | ||
408 | err = carl9170_disable_key(ar, i); | ||
409 | if (err) | ||
410 | goto out; | ||
411 | } | ||
412 | } | ||
413 | |||
414 | carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED); | ||
415 | |||
416 | ieee80211_wake_queues(ar->hw); | ||
417 | err = 0; | ||
418 | |||
419 | out: | ||
420 | mutex_unlock(&ar->mutex); | ||
421 | return err; | ||
422 | } | ||
423 | |||
424 | static void carl9170_cancel_worker(struct ar9170 *ar) | ||
425 | { | ||
426 | cancel_delayed_work_sync(&ar->tx_janitor); | ||
427 | #ifdef CONFIG_CARL9170_LEDS | ||
428 | cancel_delayed_work_sync(&ar->led_work); | ||
429 | #endif /* CONFIG_CARL9170_LEDS */ | ||
430 | cancel_work_sync(&ar->ps_work); | ||
431 | cancel_work_sync(&ar->ping_work); | ||
432 | cancel_work_sync(&ar->ampdu_work); | ||
433 | } | ||
434 | |||
435 | static void carl9170_op_stop(struct ieee80211_hw *hw) | ||
436 | { | ||
437 | struct ar9170 *ar = hw->priv; | ||
438 | |||
439 | carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE); | ||
440 | |||
441 | ieee80211_stop_queues(ar->hw); | ||
442 | |||
443 | mutex_lock(&ar->mutex); | ||
444 | if (IS_ACCEPTING_CMD(ar)) { | ||
445 | rcu_assign_pointer(ar->beacon_iter, NULL); | ||
446 | |||
447 | carl9170_led_set_state(ar, 0); | ||
448 | |||
449 | /* stop DMA */ | ||
450 | carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, 0); | ||
451 | carl9170_usb_stop(ar); | ||
452 | } | ||
453 | |||
454 | carl9170_zap_queues(ar); | ||
455 | mutex_unlock(&ar->mutex); | ||
456 | |||
457 | carl9170_cancel_worker(ar); | ||
458 | } | ||
459 | |||
460 | static void carl9170_restart_work(struct work_struct *work) | ||
461 | { | ||
462 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
463 | restart_work); | ||
464 | int err; | ||
465 | |||
466 | ar->usedkeys = 0; | ||
467 | ar->filter_state = 0; | ||
468 | carl9170_cancel_worker(ar); | ||
469 | |||
470 | mutex_lock(&ar->mutex); | ||
471 | err = carl9170_usb_restart(ar); | ||
472 | if (net_ratelimit()) { | ||
473 | if (err) { | ||
474 | dev_err(&ar->udev->dev, "Failed to restart device " | ||
475 | " (%d).\n", err); | ||
476 | } else { | ||
477 | dev_info(&ar->udev->dev, "device restarted " | ||
478 | "successfully.\n"); | ||
479 | } | ||
480 | } | ||
481 | |||
482 | carl9170_zap_queues(ar); | ||
483 | mutex_unlock(&ar->mutex); | ||
484 | if (!err) { | ||
485 | ar->restart_counter++; | ||
486 | atomic_set(&ar->pending_restarts, 0); | ||
487 | |||
488 | ieee80211_restart_hw(ar->hw); | ||
489 | } else { | ||
490 | /* | ||
491 | * The reset was unsuccessful and the device seems to | ||
492 | * be dead. But there's still one option: a low-level | ||
493 | * usb subsystem reset... | ||
494 | */ | ||
495 | |||
496 | carl9170_usb_reset(ar); | ||
497 | } | ||
498 | } | ||
499 | |||
500 | void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r) | ||
501 | { | ||
502 | carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE); | ||
503 | |||
504 | /* | ||
505 | * Sometimes, an error can trigger several different reset events. | ||
506 | * By ignoring these *surplus* reset events, the device won't be | ||
507 | * killed again, right after it has recovered. | ||
508 | */ | ||
509 | if (atomic_inc_return(&ar->pending_restarts) > 1) { | ||
510 | dev_dbg(&ar->udev->dev, "ignoring restart (%d)\n", r); | ||
511 | return; | ||
512 | } | ||
513 | |||
514 | ieee80211_stop_queues(ar->hw); | ||
515 | |||
516 | dev_err(&ar->udev->dev, "restart device (%d)\n", r); | ||
517 | |||
518 | if (!WARN_ON(r == CARL9170_RR_NO_REASON) || | ||
519 | !WARN_ON(r >= __CARL9170_RR_LAST)) | ||
520 | ar->last_reason = r; | ||
521 | |||
522 | if (!ar->registered) | ||
523 | return; | ||
524 | |||
525 | if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset) | ||
526 | ieee80211_queue_work(ar->hw, &ar->restart_work); | ||
527 | else | ||
528 | carl9170_usb_reset(ar); | ||
529 | |||
530 | /* | ||
531 | * At this point, the device instance might have vanished/disabled. | ||
532 | * So, don't put any code which access the ar9170 struct | ||
533 | * without proper protection. | ||
534 | */ | ||
535 | } | ||
536 | |||
537 | static void carl9170_ping_work(struct work_struct *work) | ||
538 | { | ||
539 | struct ar9170 *ar = container_of(work, struct ar9170, ping_work); | ||
540 | int err; | ||
541 | |||
542 | if (!IS_STARTED(ar)) | ||
543 | return; | ||
544 | |||
545 | mutex_lock(&ar->mutex); | ||
546 | err = carl9170_echo_test(ar, 0xdeadbeef); | ||
547 | if (err) | ||
548 | carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE); | ||
549 | mutex_unlock(&ar->mutex); | ||
550 | } | ||
551 | |||
552 | static int carl9170_init_interface(struct ar9170 *ar, | ||
553 | struct ieee80211_vif *vif) | ||
554 | { | ||
555 | struct ath_common *common = &ar->common; | ||
556 | int err; | ||
557 | |||
558 | if (!vif) { | ||
559 | WARN_ON_ONCE(IS_STARTED(ar)); | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | memcpy(common->macaddr, vif->addr, ETH_ALEN); | ||
564 | |||
565 | if (modparam_nohwcrypt || | ||
566 | ((vif->type != NL80211_IFTYPE_STATION) && | ||
567 | (vif->type != NL80211_IFTYPE_AP))) { | ||
568 | ar->rx_software_decryption = true; | ||
569 | ar->disable_offload = true; | ||
570 | } | ||
571 | |||
572 | err = carl9170_set_operating_mode(ar); | ||
573 | return err; | ||
574 | } | ||
575 | |||
576 | static int carl9170_op_add_interface(struct ieee80211_hw *hw, | ||
577 | struct ieee80211_vif *vif) | ||
578 | { | ||
579 | struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv; | ||
580 | struct ieee80211_vif *main_vif; | ||
581 | struct ar9170 *ar = hw->priv; | ||
582 | int vif_id = -1, err = 0; | ||
583 | |||
584 | mutex_lock(&ar->mutex); | ||
585 | rcu_read_lock(); | ||
586 | if (vif_priv->active) { | ||
587 | /* | ||
588 | * Skip the interface structure initialization, | ||
589 | * if the vif survived the _restart call. | ||
590 | */ | ||
591 | vif_id = vif_priv->id; | ||
592 | vif_priv->enable_beacon = false; | ||
593 | |||
594 | spin_lock_bh(&ar->beacon_lock); | ||
595 | dev_kfree_skb_any(vif_priv->beacon); | ||
596 | vif_priv->beacon = NULL; | ||
597 | spin_unlock_bh(&ar->beacon_lock); | ||
598 | |||
599 | goto init; | ||
600 | } | ||
601 | |||
602 | main_vif = carl9170_get_main_vif(ar); | ||
603 | |||
604 | if (main_vif) { | ||
605 | switch (main_vif->type) { | ||
606 | case NL80211_IFTYPE_STATION: | ||
607 | if (vif->type == NL80211_IFTYPE_STATION) | ||
608 | break; | ||
609 | |||
610 | err = -EBUSY; | ||
611 | rcu_read_unlock(); | ||
612 | |||
613 | goto unlock; | ||
614 | |||
615 | case NL80211_IFTYPE_AP: | ||
616 | if ((vif->type == NL80211_IFTYPE_STATION) || | ||
617 | (vif->type == NL80211_IFTYPE_WDS) || | ||
618 | (vif->type == NL80211_IFTYPE_AP)) | ||
619 | break; | ||
620 | |||
621 | err = -EBUSY; | ||
622 | rcu_read_unlock(); | ||
623 | goto unlock; | ||
624 | |||
625 | default: | ||
626 | rcu_read_unlock(); | ||
627 | goto unlock; | ||
628 | } | ||
629 | } | ||
630 | |||
631 | vif_id = bitmap_find_free_region(&ar->vif_bitmap, ar->fw.vif_num, 0); | ||
632 | |||
633 | if (vif_id < 0) { | ||
634 | rcu_read_unlock(); | ||
635 | |||
636 | err = -ENOSPC; | ||
637 | goto unlock; | ||
638 | } | ||
639 | |||
640 | BUG_ON(ar->vif_priv[vif_id].id != vif_id); | ||
641 | |||
642 | vif_priv->active = true; | ||
643 | vif_priv->id = vif_id; | ||
644 | vif_priv->enable_beacon = false; | ||
645 | ar->vifs++; | ||
646 | list_add_tail_rcu(&vif_priv->list, &ar->vif_list); | ||
647 | rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif); | ||
648 | |||
649 | init: | ||
650 | if (carl9170_get_main_vif(ar) == vif) { | ||
651 | rcu_assign_pointer(ar->beacon_iter, vif_priv); | ||
652 | rcu_read_unlock(); | ||
653 | |||
654 | err = carl9170_init_interface(ar, vif); | ||
655 | if (err) | ||
656 | goto unlock; | ||
657 | } else { | ||
658 | rcu_read_unlock(); | ||
659 | err = carl9170_mod_virtual_mac(ar, vif_id, vif->addr); | ||
660 | |||
661 | if (err) | ||
662 | goto unlock; | ||
663 | } | ||
664 | |||
665 | if (ar->fw.tx_seq_table) { | ||
666 | err = carl9170_write_reg(ar, ar->fw.tx_seq_table + vif_id * 4, | ||
667 | 0); | ||
668 | if (err) | ||
669 | goto unlock; | ||
670 | } | ||
671 | |||
672 | unlock: | ||
673 | if (err && (vif_id >= 0)) { | ||
674 | vif_priv->active = false; | ||
675 | bitmap_release_region(&ar->vif_bitmap, vif_id, 0); | ||
676 | ar->vifs--; | ||
677 | rcu_assign_pointer(ar->vif_priv[vif_id].vif, NULL); | ||
678 | list_del_rcu(&vif_priv->list); | ||
679 | mutex_unlock(&ar->mutex); | ||
680 | synchronize_rcu(); | ||
681 | } else { | ||
682 | if (ar->vifs > 1) | ||
683 | ar->ps.off_override |= PS_OFF_VIF; | ||
684 | |||
685 | mutex_unlock(&ar->mutex); | ||
686 | } | ||
687 | |||
688 | return err; | ||
689 | } | ||
690 | |||
691 | static void carl9170_op_remove_interface(struct ieee80211_hw *hw, | ||
692 | struct ieee80211_vif *vif) | ||
693 | { | ||
694 | struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv; | ||
695 | struct ieee80211_vif *main_vif; | ||
696 | struct ar9170 *ar = hw->priv; | ||
697 | unsigned int id; | ||
698 | |||
699 | mutex_lock(&ar->mutex); | ||
700 | |||
701 | if (WARN_ON_ONCE(!vif_priv->active)) | ||
702 | goto unlock; | ||
703 | |||
704 | ar->vifs--; | ||
705 | |||
706 | rcu_read_lock(); | ||
707 | main_vif = carl9170_get_main_vif(ar); | ||
708 | |||
709 | id = vif_priv->id; | ||
710 | |||
711 | vif_priv->active = false; | ||
712 | WARN_ON(vif_priv->enable_beacon); | ||
713 | vif_priv->enable_beacon = false; | ||
714 | list_del_rcu(&vif_priv->list); | ||
715 | rcu_assign_pointer(ar->vif_priv[id].vif, NULL); | ||
716 | |||
717 | if (vif == main_vif) { | ||
718 | rcu_read_unlock(); | ||
719 | |||
720 | if (ar->vifs) { | ||
721 | WARN_ON(carl9170_init_interface(ar, | ||
722 | carl9170_get_main_vif(ar))); | ||
723 | } else { | ||
724 | carl9170_set_operating_mode(ar); | ||
725 | } | ||
726 | } else { | ||
727 | rcu_read_unlock(); | ||
728 | |||
729 | WARN_ON(carl9170_mod_virtual_mac(ar, id, NULL)); | ||
730 | } | ||
731 | |||
732 | carl9170_update_beacon(ar, false); | ||
733 | carl9170_flush_cab(ar, id); | ||
734 | |||
735 | spin_lock_bh(&ar->beacon_lock); | ||
736 | dev_kfree_skb_any(vif_priv->beacon); | ||
737 | vif_priv->beacon = NULL; | ||
738 | spin_unlock_bh(&ar->beacon_lock); | ||
739 | |||
740 | bitmap_release_region(&ar->vif_bitmap, id, 0); | ||
741 | |||
742 | carl9170_set_beacon_timers(ar); | ||
743 | |||
744 | if (ar->vifs == 1) | ||
745 | ar->ps.off_override &= ~PS_OFF_VIF; | ||
746 | |||
747 | unlock: | ||
748 | mutex_unlock(&ar->mutex); | ||
749 | |||
750 | synchronize_rcu(); | ||
751 | } | ||
752 | |||
753 | void carl9170_ps_check(struct ar9170 *ar) | ||
754 | { | ||
755 | ieee80211_queue_work(ar->hw, &ar->ps_work); | ||
756 | } | ||
757 | |||
758 | /* caller must hold ar->mutex */ | ||
759 | static int carl9170_ps_update(struct ar9170 *ar) | ||
760 | { | ||
761 | bool ps = false; | ||
762 | int err = 0; | ||
763 | |||
764 | if (!ar->ps.off_override) | ||
765 | ps = (ar->hw->conf.flags & IEEE80211_CONF_PS); | ||
766 | |||
767 | if (ps != ar->ps.state) { | ||
768 | err = carl9170_powersave(ar, ps); | ||
769 | if (err) | ||
770 | return err; | ||
771 | |||
772 | if (ar->ps.state && !ps) { | ||
773 | ar->ps.sleep_ms = jiffies_to_msecs(jiffies - | ||
774 | ar->ps.last_action); | ||
775 | } | ||
776 | |||
777 | if (ps) | ||
778 | ar->ps.last_slept = jiffies; | ||
779 | |||
780 | ar->ps.last_action = jiffies; | ||
781 | ar->ps.state = ps; | ||
782 | } | ||
783 | |||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | static void carl9170_ps_work(struct work_struct *work) | ||
788 | { | ||
789 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
790 | ps_work); | ||
791 | mutex_lock(&ar->mutex); | ||
792 | if (IS_STARTED(ar)) | ||
793 | WARN_ON_ONCE(carl9170_ps_update(ar) != 0); | ||
794 | mutex_unlock(&ar->mutex); | ||
795 | } | ||
796 | |||
797 | |||
798 | static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) | ||
799 | { | ||
800 | struct ar9170 *ar = hw->priv; | ||
801 | int err = 0; | ||
802 | |||
803 | mutex_lock(&ar->mutex); | ||
804 | if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { | ||
805 | /* TODO */ | ||
806 | err = 0; | ||
807 | } | ||
808 | |||
809 | if (changed & IEEE80211_CONF_CHANGE_PS) { | ||
810 | err = carl9170_ps_update(ar); | ||
811 | if (err) | ||
812 | goto out; | ||
813 | } | ||
814 | |||
815 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | ||
816 | /* TODO */ | ||
817 | err = 0; | ||
818 | } | ||
819 | |||
820 | if (changed & IEEE80211_CONF_CHANGE_SMPS) { | ||
821 | /* TODO */ | ||
822 | err = 0; | ||
823 | } | ||
824 | |||
825 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
826 | /* adjust slot time for 5 GHz */ | ||
827 | err = carl9170_set_slot_time(ar); | ||
828 | if (err) | ||
829 | goto out; | ||
830 | |||
831 | err = carl9170_set_channel(ar, hw->conf.channel, | ||
832 | hw->conf.channel_type, CARL9170_RFI_NONE); | ||
833 | if (err) | ||
834 | goto out; | ||
835 | |||
836 | err = carl9170_set_dyn_sifs_ack(ar); | ||
837 | if (err) | ||
838 | goto out; | ||
839 | |||
840 | err = carl9170_set_rts_cts_rate(ar); | ||
841 | if (err) | ||
842 | goto out; | ||
843 | } | ||
844 | |||
845 | out: | ||
846 | mutex_unlock(&ar->mutex); | ||
847 | return err; | ||
848 | } | ||
849 | |||
850 | static u64 carl9170_op_prepare_multicast(struct ieee80211_hw *hw, | ||
851 | struct netdev_hw_addr_list *mc_list) | ||
852 | { | ||
853 | struct netdev_hw_addr *ha; | ||
854 | u64 mchash; | ||
855 | |||
856 | /* always get broadcast frames */ | ||
857 | mchash = 1ULL << (0xff >> 2); | ||
858 | |||
859 | netdev_hw_addr_list_for_each(ha, mc_list) | ||
860 | mchash |= 1ULL << (ha->addr[5] >> 2); | ||
861 | |||
862 | return mchash; | ||
863 | } | ||
864 | |||
865 | static void carl9170_op_configure_filter(struct ieee80211_hw *hw, | ||
866 | unsigned int changed_flags, | ||
867 | unsigned int *new_flags, | ||
868 | u64 multicast) | ||
869 | { | ||
870 | struct ar9170 *ar = hw->priv; | ||
871 | |||
872 | /* mask supported flags */ | ||
873 | *new_flags &= FIF_ALLMULTI | ar->rx_filter_caps; | ||
874 | |||
875 | if (!IS_ACCEPTING_CMD(ar)) | ||
876 | return; | ||
877 | |||
878 | mutex_lock(&ar->mutex); | ||
879 | |||
880 | ar->filter_state = *new_flags; | ||
881 | /* | ||
882 | * We can support more by setting the sniffer bit and | ||
883 | * then checking the error flags, later. | ||
884 | */ | ||
885 | |||
886 | if (*new_flags & FIF_ALLMULTI) | ||
887 | multicast = ~0ULL; | ||
888 | |||
889 | if (multicast != ar->cur_mc_hash) | ||
890 | WARN_ON(carl9170_update_multicast(ar, multicast)); | ||
891 | |||
892 | if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { | ||
893 | ar->sniffer_enabled = !!(*new_flags & | ||
894 | (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)); | ||
895 | |||
896 | WARN_ON(carl9170_set_operating_mode(ar)); | ||
897 | } | ||
898 | |||
899 | if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) { | ||
900 | u32 rx_filter = 0; | ||
901 | |||
902 | if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))) | ||
903 | rx_filter |= CARL9170_RX_FILTER_BAD; | ||
904 | |||
905 | if (!(*new_flags & FIF_CONTROL)) | ||
906 | rx_filter |= CARL9170_RX_FILTER_CTL_OTHER; | ||
907 | |||
908 | if (!(*new_flags & FIF_PSPOLL)) | ||
909 | rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL; | ||
910 | |||
911 | if (!(*new_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))) { | ||
912 | rx_filter |= CARL9170_RX_FILTER_OTHER_RA; | ||
913 | rx_filter |= CARL9170_RX_FILTER_DECRY_FAIL; | ||
914 | } | ||
915 | |||
916 | WARN_ON(carl9170_rx_filter(ar, rx_filter)); | ||
917 | } | ||
918 | |||
919 | mutex_unlock(&ar->mutex); | ||
920 | } | ||
921 | |||
922 | |||
923 | static void carl9170_op_bss_info_changed(struct ieee80211_hw *hw, | ||
924 | struct ieee80211_vif *vif, | ||
925 | struct ieee80211_bss_conf *bss_conf, | ||
926 | u32 changed) | ||
927 | { | ||
928 | struct ar9170 *ar = hw->priv; | ||
929 | struct ath_common *common = &ar->common; | ||
930 | int err = 0; | ||
931 | struct carl9170_vif_info *vif_priv; | ||
932 | struct ieee80211_vif *main_vif; | ||
933 | |||
934 | mutex_lock(&ar->mutex); | ||
935 | vif_priv = (void *) vif->drv_priv; | ||
936 | main_vif = carl9170_get_main_vif(ar); | ||
937 | if (WARN_ON(!main_vif)) | ||
938 | goto out; | ||
939 | |||
940 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | ||
941 | struct carl9170_vif_info *iter; | ||
942 | int i = 0; | ||
943 | |||
944 | vif_priv->enable_beacon = bss_conf->enable_beacon; | ||
945 | rcu_read_lock(); | ||
946 | list_for_each_entry_rcu(iter, &ar->vif_list, list) { | ||
947 | if (iter->active && iter->enable_beacon) | ||
948 | i++; | ||
949 | |||
950 | } | ||
951 | rcu_read_unlock(); | ||
952 | |||
953 | ar->beacon_enabled = i; | ||
954 | } | ||
955 | |||
956 | if (changed & BSS_CHANGED_BEACON) { | ||
957 | err = carl9170_update_beacon(ar, false); | ||
958 | if (err) | ||
959 | goto out; | ||
960 | } | ||
961 | |||
962 | if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON | | ||
963 | BSS_CHANGED_BEACON_INT)) { | ||
964 | |||
965 | if (main_vif != vif) { | ||
966 | bss_conf->beacon_int = main_vif->bss_conf.beacon_int; | ||
967 | bss_conf->dtim_period = main_vif->bss_conf.dtim_period; | ||
968 | } | ||
969 | |||
970 | /* | ||
971 | * Therefore a hard limit for the broadcast traffic should | ||
972 | * prevent false alarms. | ||
973 | */ | ||
974 | if (vif->type != NL80211_IFTYPE_STATION && | ||
975 | (bss_conf->beacon_int * bss_conf->dtim_period >= | ||
976 | (CARL9170_QUEUE_STUCK_TIMEOUT / 2))) { | ||
977 | err = -EINVAL; | ||
978 | goto out; | ||
979 | } | ||
980 | |||
981 | err = carl9170_set_beacon_timers(ar); | ||
982 | if (err) | ||
983 | goto out; | ||
984 | } | ||
985 | |||
986 | if (changed & BSS_CHANGED_HT) { | ||
987 | /* TODO */ | ||
988 | err = 0; | ||
989 | if (err) | ||
990 | goto out; | ||
991 | } | ||
992 | |||
993 | if (main_vif != vif) | ||
994 | goto out; | ||
995 | |||
996 | /* | ||
997 | * The following settings can only be changed by the | ||
998 | * master interface. | ||
999 | */ | ||
1000 | |||
1001 | if (changed & BSS_CHANGED_BSSID) { | ||
1002 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1003 | err = carl9170_set_operating_mode(ar); | ||
1004 | if (err) | ||
1005 | goto out; | ||
1006 | } | ||
1007 | |||
1008 | if (changed & BSS_CHANGED_ASSOC) { | ||
1009 | ar->common.curaid = bss_conf->aid; | ||
1010 | err = carl9170_set_beacon_timers(ar); | ||
1011 | if (err) | ||
1012 | goto out; | ||
1013 | } | ||
1014 | |||
1015 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
1016 | err = carl9170_set_slot_time(ar); | ||
1017 | if (err) | ||
1018 | goto out; | ||
1019 | } | ||
1020 | |||
1021 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
1022 | err = carl9170_set_mac_rates(ar); | ||
1023 | if (err) | ||
1024 | goto out; | ||
1025 | } | ||
1026 | |||
1027 | out: | ||
1028 | WARN_ON_ONCE(err && IS_STARTED(ar)); | ||
1029 | mutex_unlock(&ar->mutex); | ||
1030 | } | ||
1031 | |||
1032 | static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw) | ||
1033 | { | ||
1034 | struct ar9170 *ar = hw->priv; | ||
1035 | struct carl9170_tsf_rsp tsf; | ||
1036 | int err; | ||
1037 | |||
1038 | mutex_lock(&ar->mutex); | ||
1039 | err = carl9170_exec_cmd(ar, CARL9170_CMD_READ_TSF, | ||
1040 | 0, NULL, sizeof(tsf), &tsf); | ||
1041 | mutex_unlock(&ar->mutex); | ||
1042 | if (WARN_ON(err)) | ||
1043 | return 0; | ||
1044 | |||
1045 | return le64_to_cpu(tsf.tsf_64); | ||
1046 | } | ||
1047 | |||
1048 | static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
1049 | struct ieee80211_vif *vif, | ||
1050 | struct ieee80211_sta *sta, | ||
1051 | struct ieee80211_key_conf *key) | ||
1052 | { | ||
1053 | struct ar9170 *ar = hw->priv; | ||
1054 | int err = 0, i; | ||
1055 | u8 ktype; | ||
1056 | |||
1057 | if (ar->disable_offload || !vif) | ||
1058 | return -EOPNOTSUPP; | ||
1059 | |||
1060 | /* | ||
1061 | * We have to fall back to software encryption, whenever | ||
1062 | * the user choose to participates in an IBSS or is connected | ||
1063 | * to more than one network. | ||
1064 | * | ||
1065 | * This is very unfortunate, because some machines cannot handle | ||
1066 | * the high througput speed in 802.11n networks. | ||
1067 | */ | ||
1068 | |||
1069 | if (!is_main_vif(ar, vif)) | ||
1070 | goto err_softw; | ||
1071 | |||
1072 | /* | ||
1073 | * While the hardware supports *catch-all* key, for offloading | ||
1074 | * group-key en-/de-cryption. The way of how the hardware | ||
1075 | * decides which keyId maps to which key, remains a mystery... | ||
1076 | */ | ||
1077 | if ((vif->type != NL80211_IFTYPE_STATION && | ||
1078 | vif->type != NL80211_IFTYPE_ADHOC) && | ||
1079 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
1080 | return -EOPNOTSUPP; | ||
1081 | |||
1082 | switch (key->cipher) { | ||
1083 | case WLAN_CIPHER_SUITE_WEP40: | ||
1084 | ktype = AR9170_ENC_ALG_WEP64; | ||
1085 | break; | ||
1086 | case WLAN_CIPHER_SUITE_WEP104: | ||
1087 | ktype = AR9170_ENC_ALG_WEP128; | ||
1088 | break; | ||
1089 | case WLAN_CIPHER_SUITE_TKIP: | ||
1090 | ktype = AR9170_ENC_ALG_TKIP; | ||
1091 | break; | ||
1092 | case WLAN_CIPHER_SUITE_CCMP: | ||
1093 | ktype = AR9170_ENC_ALG_AESCCMP; | ||
1094 | break; | ||
1095 | default: | ||
1096 | return -EOPNOTSUPP; | ||
1097 | } | ||
1098 | |||
1099 | mutex_lock(&ar->mutex); | ||
1100 | if (cmd == SET_KEY) { | ||
1101 | if (!IS_STARTED(ar)) { | ||
1102 | err = -EOPNOTSUPP; | ||
1103 | goto out; | ||
1104 | } | ||
1105 | |||
1106 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
1107 | sta = NULL; | ||
1108 | |||
1109 | i = 64 + key->keyidx; | ||
1110 | } else { | ||
1111 | for (i = 0; i < 64; i++) | ||
1112 | if (!(ar->usedkeys & BIT(i))) | ||
1113 | break; | ||
1114 | if (i == 64) | ||
1115 | goto err_softw; | ||
1116 | } | ||
1117 | |||
1118 | key->hw_key_idx = i; | ||
1119 | |||
1120 | err = carl9170_upload_key(ar, i, sta ? sta->addr : NULL, | ||
1121 | ktype, 0, key->key, | ||
1122 | min_t(u8, 16, key->keylen)); | ||
1123 | if (err) | ||
1124 | goto out; | ||
1125 | |||
1126 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
1127 | err = carl9170_upload_key(ar, i, sta ? sta->addr : | ||
1128 | NULL, ktype, 1, | ||
1129 | key->key + 16, 16); | ||
1130 | if (err) | ||
1131 | goto out; | ||
1132 | |||
1133 | /* | ||
1134 | * hardware is not capable generating MMIC | ||
1135 | * of fragmented frames! | ||
1136 | */ | ||
1137 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
1138 | } | ||
1139 | |||
1140 | if (i < 64) | ||
1141 | ar->usedkeys |= BIT(i); | ||
1142 | |||
1143 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
1144 | } else { | ||
1145 | if (!IS_STARTED(ar)) { | ||
1146 | /* The device is gone... together with the key ;-) */ | ||
1147 | err = 0; | ||
1148 | goto out; | ||
1149 | } | ||
1150 | |||
1151 | if (key->hw_key_idx < 64) { | ||
1152 | ar->usedkeys &= ~BIT(key->hw_key_idx); | ||
1153 | } else { | ||
1154 | err = carl9170_upload_key(ar, key->hw_key_idx, NULL, | ||
1155 | AR9170_ENC_ALG_NONE, 0, | ||
1156 | NULL, 0); | ||
1157 | if (err) | ||
1158 | goto out; | ||
1159 | |||
1160 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
1161 | err = carl9170_upload_key(ar, key->hw_key_idx, | ||
1162 | NULL, | ||
1163 | AR9170_ENC_ALG_NONE, | ||
1164 | 1, NULL, 0); | ||
1165 | if (err) | ||
1166 | goto out; | ||
1167 | } | ||
1168 | |||
1169 | } | ||
1170 | |||
1171 | err = carl9170_disable_key(ar, key->hw_key_idx); | ||
1172 | if (err) | ||
1173 | goto out; | ||
1174 | } | ||
1175 | |||
1176 | out: | ||
1177 | mutex_unlock(&ar->mutex); | ||
1178 | return err; | ||
1179 | |||
1180 | err_softw: | ||
1181 | if (!ar->rx_software_decryption) { | ||
1182 | ar->rx_software_decryption = true; | ||
1183 | carl9170_set_operating_mode(ar); | ||
1184 | } | ||
1185 | mutex_unlock(&ar->mutex); | ||
1186 | return -ENOSPC; | ||
1187 | } | ||
1188 | |||
1189 | static int carl9170_op_sta_add(struct ieee80211_hw *hw, | ||
1190 | struct ieee80211_vif *vif, | ||
1191 | struct ieee80211_sta *sta) | ||
1192 | { | ||
1193 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
1194 | unsigned int i; | ||
1195 | |||
1196 | atomic_set(&sta_info->pending_frames, 0); | ||
1197 | |||
1198 | if (sta->ht_cap.ht_supported) { | ||
1199 | if (sta->ht_cap.ampdu_density > 6) { | ||
1200 | /* | ||
1201 | * HW does support 16us AMPDU density. | ||
1202 | * No HT-Xmit for station. | ||
1203 | */ | ||
1204 | |||
1205 | return 0; | ||
1206 | } | ||
1207 | |||
1208 | for (i = 0; i < CARL9170_NUM_TID; i++) | ||
1209 | rcu_assign_pointer(sta_info->agg[i], NULL); | ||
1210 | |||
1211 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); | ||
1212 | sta_info->ht_sta = true; | ||
1213 | } | ||
1214 | |||
1215 | return 0; | ||
1216 | } | ||
1217 | |||
1218 | static int carl9170_op_sta_remove(struct ieee80211_hw *hw, | ||
1219 | struct ieee80211_vif *vif, | ||
1220 | struct ieee80211_sta *sta) | ||
1221 | { | ||
1222 | struct ar9170 *ar = hw->priv; | ||
1223 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
1224 | unsigned int i; | ||
1225 | bool cleanup = false; | ||
1226 | |||
1227 | if (sta->ht_cap.ht_supported) { | ||
1228 | |||
1229 | sta_info->ht_sta = false; | ||
1230 | |||
1231 | rcu_read_lock(); | ||
1232 | for (i = 0; i < CARL9170_NUM_TID; i++) { | ||
1233 | struct carl9170_sta_tid *tid_info; | ||
1234 | |||
1235 | tid_info = rcu_dereference(sta_info->agg[i]); | ||
1236 | rcu_assign_pointer(sta_info->agg[i], NULL); | ||
1237 | |||
1238 | if (!tid_info) | ||
1239 | continue; | ||
1240 | |||
1241 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
1242 | if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN) | ||
1243 | tid_info->state = CARL9170_TID_STATE_SHUTDOWN; | ||
1244 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
1245 | cleanup = true; | ||
1246 | } | ||
1247 | rcu_read_unlock(); | ||
1248 | |||
1249 | if (cleanup) | ||
1250 | carl9170_ampdu_gc(ar); | ||
1251 | } | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | static int carl9170_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1257 | const struct ieee80211_tx_queue_params *param) | ||
1258 | { | ||
1259 | struct ar9170 *ar = hw->priv; | ||
1260 | int ret; | ||
1261 | |||
1262 | mutex_lock(&ar->mutex); | ||
1263 | if (queue < ar->hw->queues) { | ||
1264 | memcpy(&ar->edcf[ar9170_qmap[queue]], param, sizeof(*param)); | ||
1265 | ret = carl9170_set_qos(ar); | ||
1266 | } else { | ||
1267 | ret = -EINVAL; | ||
1268 | } | ||
1269 | |||
1270 | mutex_unlock(&ar->mutex); | ||
1271 | return ret; | ||
1272 | } | ||
1273 | |||
1274 | static void carl9170_ampdu_work(struct work_struct *work) | ||
1275 | { | ||
1276 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
1277 | ampdu_work); | ||
1278 | |||
1279 | if (!IS_STARTED(ar)) | ||
1280 | return; | ||
1281 | |||
1282 | mutex_lock(&ar->mutex); | ||
1283 | carl9170_ampdu_gc(ar); | ||
1284 | mutex_unlock(&ar->mutex); | ||
1285 | } | ||
1286 | |||
1287 | static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, | ||
1288 | struct ieee80211_vif *vif, | ||
1289 | enum ieee80211_ampdu_mlme_action action, | ||
1290 | struct ieee80211_sta *sta, | ||
1291 | u16 tid, u16 *ssn, u8 buf_size) | ||
1292 | { | ||
1293 | struct ar9170 *ar = hw->priv; | ||
1294 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
1295 | struct carl9170_sta_tid *tid_info; | ||
1296 | |||
1297 | if (modparam_noht) | ||
1298 | return -EOPNOTSUPP; | ||
1299 | |||
1300 | switch (action) { | ||
1301 | case IEEE80211_AMPDU_TX_START: | ||
1302 | if (!sta_info->ht_sta) | ||
1303 | return -EOPNOTSUPP; | ||
1304 | |||
1305 | rcu_read_lock(); | ||
1306 | if (rcu_dereference(sta_info->agg[tid])) { | ||
1307 | rcu_read_unlock(); | ||
1308 | return -EBUSY; | ||
1309 | } | ||
1310 | |||
1311 | tid_info = kzalloc(sizeof(struct carl9170_sta_tid), | ||
1312 | GFP_ATOMIC); | ||
1313 | if (!tid_info) { | ||
1314 | rcu_read_unlock(); | ||
1315 | return -ENOMEM; | ||
1316 | } | ||
1317 | |||
1318 | tid_info->hsn = tid_info->bsn = tid_info->snx = (*ssn); | ||
1319 | tid_info->state = CARL9170_TID_STATE_PROGRESS; | ||
1320 | tid_info->tid = tid; | ||
1321 | tid_info->max = sta_info->ampdu_max_len; | ||
1322 | |||
1323 | INIT_LIST_HEAD(&tid_info->list); | ||
1324 | INIT_LIST_HEAD(&tid_info->tmp_list); | ||
1325 | skb_queue_head_init(&tid_info->queue); | ||
1326 | spin_lock_init(&tid_info->lock); | ||
1327 | |||
1328 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
1329 | ar->tx_ampdu_list_len++; | ||
1330 | list_add_tail_rcu(&tid_info->list, &ar->tx_ampdu_list); | ||
1331 | rcu_assign_pointer(sta_info->agg[tid], tid_info); | ||
1332 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
1333 | rcu_read_unlock(); | ||
1334 | |||
1335 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1336 | break; | ||
1337 | |||
1338 | case IEEE80211_AMPDU_TX_STOP: | ||
1339 | rcu_read_lock(); | ||
1340 | tid_info = rcu_dereference(sta_info->agg[tid]); | ||
1341 | if (tid_info) { | ||
1342 | spin_lock_bh(&ar->tx_ampdu_list_lock); | ||
1343 | if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN) | ||
1344 | tid_info->state = CARL9170_TID_STATE_SHUTDOWN; | ||
1345 | spin_unlock_bh(&ar->tx_ampdu_list_lock); | ||
1346 | } | ||
1347 | |||
1348 | rcu_assign_pointer(sta_info->agg[tid], NULL); | ||
1349 | rcu_read_unlock(); | ||
1350 | |||
1351 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1352 | ieee80211_queue_work(ar->hw, &ar->ampdu_work); | ||
1353 | break; | ||
1354 | |||
1355 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
1356 | rcu_read_lock(); | ||
1357 | tid_info = rcu_dereference(sta_info->agg[tid]); | ||
1358 | |||
1359 | sta_info->stats[tid].clear = true; | ||
1360 | sta_info->stats[tid].req = false; | ||
1361 | |||
1362 | if (tid_info) { | ||
1363 | bitmap_zero(tid_info->bitmap, CARL9170_BAW_SIZE); | ||
1364 | tid_info->state = CARL9170_TID_STATE_IDLE; | ||
1365 | } | ||
1366 | rcu_read_unlock(); | ||
1367 | |||
1368 | if (WARN_ON_ONCE(!tid_info)) | ||
1369 | return -EFAULT; | ||
1370 | |||
1371 | break; | ||
1372 | |||
1373 | case IEEE80211_AMPDU_RX_START: | ||
1374 | case IEEE80211_AMPDU_RX_STOP: | ||
1375 | /* Handled by hardware */ | ||
1376 | break; | ||
1377 | |||
1378 | default: | ||
1379 | return -EOPNOTSUPP; | ||
1380 | } | ||
1381 | |||
1382 | return 0; | ||
1383 | } | ||
1384 | |||
1385 | #ifdef CONFIG_CARL9170_WPC | ||
1386 | static int carl9170_register_wps_button(struct ar9170 *ar) | ||
1387 | { | ||
1388 | struct input_dev *input; | ||
1389 | int err; | ||
1390 | |||
1391 | if (!(ar->features & CARL9170_WPS_BUTTON)) | ||
1392 | return 0; | ||
1393 | |||
1394 | input = input_allocate_device(); | ||
1395 | if (!input) | ||
1396 | return -ENOMEM; | ||
1397 | |||
1398 | snprintf(ar->wps.name, sizeof(ar->wps.name), "%s WPS Button", | ||
1399 | wiphy_name(ar->hw->wiphy)); | ||
1400 | |||
1401 | snprintf(ar->wps.phys, sizeof(ar->wps.phys), | ||
1402 | "ieee80211/%s/input0", wiphy_name(ar->hw->wiphy)); | ||
1403 | |||
1404 | input->name = ar->wps.name; | ||
1405 | input->phys = ar->wps.phys; | ||
1406 | input->id.bustype = BUS_USB; | ||
1407 | input->dev.parent = &ar->hw->wiphy->dev; | ||
1408 | |||
1409 | input_set_capability(input, EV_KEY, KEY_WPS_BUTTON); | ||
1410 | |||
1411 | err = input_register_device(input); | ||
1412 | if (err) { | ||
1413 | input_free_device(input); | ||
1414 | return err; | ||
1415 | } | ||
1416 | |||
1417 | ar->wps.pbc = input; | ||
1418 | return 0; | ||
1419 | } | ||
1420 | #endif /* CONFIG_CARL9170_WPC */ | ||
1421 | |||
1422 | static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, | ||
1423 | struct survey_info *survey) | ||
1424 | { | ||
1425 | struct ar9170 *ar = hw->priv; | ||
1426 | int err; | ||
1427 | |||
1428 | if (idx != 0) | ||
1429 | return -ENOENT; | ||
1430 | |||
1431 | mutex_lock(&ar->mutex); | ||
1432 | err = carl9170_get_noisefloor(ar); | ||
1433 | mutex_unlock(&ar->mutex); | ||
1434 | if (err) | ||
1435 | return err; | ||
1436 | |||
1437 | survey->channel = ar->channel; | ||
1438 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
1439 | survey->noise = ar->noise[0]; | ||
1440 | return 0; | ||
1441 | } | ||
1442 | |||
1443 | static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop) | ||
1444 | { | ||
1445 | struct ar9170 *ar = hw->priv; | ||
1446 | unsigned int vid; | ||
1447 | |||
1448 | mutex_lock(&ar->mutex); | ||
1449 | for_each_set_bit(vid, &ar->vif_bitmap, ar->fw.vif_num) | ||
1450 | carl9170_flush_cab(ar, vid); | ||
1451 | |||
1452 | carl9170_flush(ar, drop); | ||
1453 | mutex_unlock(&ar->mutex); | ||
1454 | } | ||
1455 | |||
1456 | static int carl9170_op_get_stats(struct ieee80211_hw *hw, | ||
1457 | struct ieee80211_low_level_stats *stats) | ||
1458 | { | ||
1459 | struct ar9170 *ar = hw->priv; | ||
1460 | |||
1461 | memset(stats, 0, sizeof(*stats)); | ||
1462 | stats->dot11ACKFailureCount = ar->tx_ack_failures; | ||
1463 | stats->dot11FCSErrorCount = ar->tx_fcs_errors; | ||
1464 | return 0; | ||
1465 | } | ||
1466 | |||
1467 | static void carl9170_op_sta_notify(struct ieee80211_hw *hw, | ||
1468 | struct ieee80211_vif *vif, | ||
1469 | enum sta_notify_cmd cmd, | ||
1470 | struct ieee80211_sta *sta) | ||
1471 | { | ||
1472 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
1473 | |||
1474 | switch (cmd) { | ||
1475 | case STA_NOTIFY_SLEEP: | ||
1476 | sta_info->sleeping = true; | ||
1477 | if (atomic_read(&sta_info->pending_frames)) | ||
1478 | ieee80211_sta_block_awake(hw, sta, true); | ||
1479 | break; | ||
1480 | |||
1481 | case STA_NOTIFY_AWAKE: | ||
1482 | sta_info->sleeping = false; | ||
1483 | break; | ||
1484 | } | ||
1485 | } | ||
1486 | |||
1487 | static const struct ieee80211_ops carl9170_ops = { | ||
1488 | .start = carl9170_op_start, | ||
1489 | .stop = carl9170_op_stop, | ||
1490 | .tx = carl9170_op_tx, | ||
1491 | .flush = carl9170_op_flush, | ||
1492 | .add_interface = carl9170_op_add_interface, | ||
1493 | .remove_interface = carl9170_op_remove_interface, | ||
1494 | .config = carl9170_op_config, | ||
1495 | .prepare_multicast = carl9170_op_prepare_multicast, | ||
1496 | .configure_filter = carl9170_op_configure_filter, | ||
1497 | .conf_tx = carl9170_op_conf_tx, | ||
1498 | .bss_info_changed = carl9170_op_bss_info_changed, | ||
1499 | .get_tsf = carl9170_op_get_tsf, | ||
1500 | .set_key = carl9170_op_set_key, | ||
1501 | .sta_add = carl9170_op_sta_add, | ||
1502 | .sta_remove = carl9170_op_sta_remove, | ||
1503 | .sta_notify = carl9170_op_sta_notify, | ||
1504 | .get_survey = carl9170_op_get_survey, | ||
1505 | .get_stats = carl9170_op_get_stats, | ||
1506 | .ampdu_action = carl9170_op_ampdu_action, | ||
1507 | }; | ||
1508 | |||
1509 | void *carl9170_alloc(size_t priv_size) | ||
1510 | { | ||
1511 | struct ieee80211_hw *hw; | ||
1512 | struct ar9170 *ar; | ||
1513 | struct sk_buff *skb; | ||
1514 | int i; | ||
1515 | |||
1516 | /* | ||
1517 | * this buffer is used for rx stream reconstruction. | ||
1518 | * Under heavy load this device (or the transport layer?) | ||
1519 | * tends to split the streams into separate rx descriptors. | ||
1520 | */ | ||
1521 | |||
1522 | skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); | ||
1523 | if (!skb) | ||
1524 | goto err_nomem; | ||
1525 | |||
1526 | hw = ieee80211_alloc_hw(priv_size, &carl9170_ops); | ||
1527 | if (!hw) | ||
1528 | goto err_nomem; | ||
1529 | |||
1530 | ar = hw->priv; | ||
1531 | ar->hw = hw; | ||
1532 | ar->rx_failover = skb; | ||
1533 | |||
1534 | memset(&ar->rx_plcp, 0, sizeof(struct ar9170_rx_head)); | ||
1535 | ar->rx_has_plcp = false; | ||
1536 | |||
1537 | /* | ||
1538 | * Here's a hidden pitfall! | ||
1539 | * | ||
1540 | * All 4 AC queues work perfectly well under _legacy_ operation. | ||
1541 | * However as soon as aggregation is enabled, the traffic flow | ||
1542 | * gets very bumpy. Therefore we have to _switch_ to a | ||
1543 | * software AC with a single HW queue. | ||
1544 | */ | ||
1545 | hw->queues = __AR9170_NUM_TXQ; | ||
1546 | |||
1547 | mutex_init(&ar->mutex); | ||
1548 | spin_lock_init(&ar->beacon_lock); | ||
1549 | spin_lock_init(&ar->cmd_lock); | ||
1550 | spin_lock_init(&ar->tx_stats_lock); | ||
1551 | spin_lock_init(&ar->tx_ampdu_list_lock); | ||
1552 | spin_lock_init(&ar->mem_lock); | ||
1553 | spin_lock_init(&ar->state_lock); | ||
1554 | atomic_set(&ar->pending_restarts, 0); | ||
1555 | ar->vifs = 0; | ||
1556 | for (i = 0; i < ar->hw->queues; i++) { | ||
1557 | skb_queue_head_init(&ar->tx_status[i]); | ||
1558 | skb_queue_head_init(&ar->tx_pending[i]); | ||
1559 | } | ||
1560 | INIT_WORK(&ar->ps_work, carl9170_ps_work); | ||
1561 | INIT_WORK(&ar->ping_work, carl9170_ping_work); | ||
1562 | INIT_WORK(&ar->restart_work, carl9170_restart_work); | ||
1563 | INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work); | ||
1564 | INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor); | ||
1565 | INIT_LIST_HEAD(&ar->tx_ampdu_list); | ||
1566 | rcu_assign_pointer(ar->tx_ampdu_iter, | ||
1567 | (struct carl9170_sta_tid *) &ar->tx_ampdu_list); | ||
1568 | |||
1569 | bitmap_zero(&ar->vif_bitmap, ar->fw.vif_num); | ||
1570 | INIT_LIST_HEAD(&ar->vif_list); | ||
1571 | init_completion(&ar->tx_flush); | ||
1572 | |||
1573 | /* firmware decides which modes we support */ | ||
1574 | hw->wiphy->interface_modes = 0; | ||
1575 | |||
1576 | hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | | ||
1577 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | ||
1578 | IEEE80211_HW_SUPPORTS_PS | | ||
1579 | IEEE80211_HW_PS_NULLFUNC_STACK | | ||
1580 | IEEE80211_HW_SIGNAL_DBM; | ||
1581 | |||
1582 | if (!modparam_noht) { | ||
1583 | /* | ||
1584 | * see the comment above, why we allow the user | ||
1585 | * to disable HT by a module parameter. | ||
1586 | */ | ||
1587 | hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | ||
1588 | } | ||
1589 | |||
1590 | hw->extra_tx_headroom = sizeof(struct _carl9170_tx_superframe); | ||
1591 | hw->sta_data_size = sizeof(struct carl9170_sta_info); | ||
1592 | hw->vif_data_size = sizeof(struct carl9170_vif_info); | ||
1593 | |||
1594 | hw->max_rates = CARL9170_TX_MAX_RATES; | ||
1595 | hw->max_rate_tries = CARL9170_TX_USER_RATE_TRIES; | ||
1596 | |||
1597 | for (i = 0; i < ARRAY_SIZE(ar->noise); i++) | ||
1598 | ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ | ||
1599 | |||
1600 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
1601 | return ar; | ||
1602 | |||
1603 | err_nomem: | ||
1604 | kfree_skb(skb); | ||
1605 | return ERR_PTR(-ENOMEM); | ||
1606 | } | ||
1607 | |||
1608 | static int carl9170_read_eeprom(struct ar9170 *ar) | ||
1609 | { | ||
1610 | #define RW 8 /* number of words to read at once */ | ||
1611 | #define RB (sizeof(u32) * RW) | ||
1612 | u8 *eeprom = (void *)&ar->eeprom; | ||
1613 | __le32 offsets[RW]; | ||
1614 | int i, j, err; | ||
1615 | |||
1616 | BUILD_BUG_ON(sizeof(ar->eeprom) & 3); | ||
1617 | |||
1618 | BUILD_BUG_ON(RB > CARL9170_MAX_CMD_LEN - 4); | ||
1619 | #ifndef __CHECKER__ | ||
1620 | /* don't want to handle trailing remains */ | ||
1621 | BUILD_BUG_ON(sizeof(ar->eeprom) % RB); | ||
1622 | #endif | ||
1623 | |||
1624 | for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { | ||
1625 | for (j = 0; j < RW; j++) | ||
1626 | offsets[j] = cpu_to_le32(AR9170_EEPROM_START + | ||
1627 | RB * i + 4 * j); | ||
1628 | |||
1629 | err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG, | ||
1630 | RB, (u8 *) &offsets, | ||
1631 | RB, eeprom + RB * i); | ||
1632 | if (err) | ||
1633 | return err; | ||
1634 | } | ||
1635 | |||
1636 | #undef RW | ||
1637 | #undef RB | ||
1638 | return 0; | ||
1639 | } | ||
1640 | |||
1641 | static int carl9170_parse_eeprom(struct ar9170 *ar) | ||
1642 | { | ||
1643 | struct ath_regulatory *regulatory = &ar->common.regulatory; | ||
1644 | unsigned int rx_streams, tx_streams, tx_params = 0; | ||
1645 | int bands = 0; | ||
1646 | |||
1647 | if (ar->eeprom.length == cpu_to_le16(0xffff)) | ||
1648 | return -ENODATA; | ||
1649 | |||
1650 | rx_streams = hweight8(ar->eeprom.rx_mask); | ||
1651 | tx_streams = hweight8(ar->eeprom.tx_mask); | ||
1652 | |||
1653 | if (rx_streams != tx_streams) { | ||
1654 | tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; | ||
1655 | |||
1656 | WARN_ON(!(tx_streams >= 1 && tx_streams <= | ||
1657 | IEEE80211_HT_MCS_TX_MAX_STREAMS)); | ||
1658 | |||
1659 | tx_params = (tx_streams - 1) << | ||
1660 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
1661 | |||
1662 | carl9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; | ||
1663 | carl9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; | ||
1664 | } | ||
1665 | |||
1666 | if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { | ||
1667 | ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
1668 | &carl9170_band_2GHz; | ||
1669 | bands++; | ||
1670 | } | ||
1671 | if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { | ||
1672 | ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
1673 | &carl9170_band_5GHz; | ||
1674 | bands++; | ||
1675 | } | ||
1676 | |||
1677 | /* | ||
1678 | * I measured this, a bandswitch takes roughly | ||
1679 | * 135 ms and a frequency switch about 80. | ||
1680 | * | ||
1681 | * FIXME: measure these values again once EEPROM settings | ||
1682 | * are used, that will influence them! | ||
1683 | */ | ||
1684 | if (bands == 2) | ||
1685 | ar->hw->channel_change_time = 135 * 1000; | ||
1686 | else | ||
1687 | ar->hw->channel_change_time = 80 * 1000; | ||
1688 | |||
1689 | regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); | ||
1690 | regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); | ||
1691 | |||
1692 | /* second part of wiphy init */ | ||
1693 | SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address); | ||
1694 | |||
1695 | return bands ? 0 : -EINVAL; | ||
1696 | } | ||
1697 | |||
1698 | static int carl9170_reg_notifier(struct wiphy *wiphy, | ||
1699 | struct regulatory_request *request) | ||
1700 | { | ||
1701 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
1702 | struct ar9170 *ar = hw->priv; | ||
1703 | |||
1704 | return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); | ||
1705 | } | ||
1706 | |||
1707 | int carl9170_register(struct ar9170 *ar) | ||
1708 | { | ||
1709 | struct ath_regulatory *regulatory = &ar->common.regulatory; | ||
1710 | int err = 0, i; | ||
1711 | |||
1712 | if (WARN_ON(ar->mem_bitmap)) | ||
1713 | return -EINVAL; | ||
1714 | |||
1715 | ar->mem_bitmap = kzalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG) * | ||
1716 | sizeof(unsigned long), GFP_KERNEL); | ||
1717 | |||
1718 | if (!ar->mem_bitmap) | ||
1719 | return -ENOMEM; | ||
1720 | |||
1721 | /* try to read EEPROM, init MAC addr */ | ||
1722 | err = carl9170_read_eeprom(ar); | ||
1723 | if (err) | ||
1724 | return err; | ||
1725 | |||
1726 | err = carl9170_fw_fix_eeprom(ar); | ||
1727 | if (err) | ||
1728 | return err; | ||
1729 | |||
1730 | err = carl9170_parse_eeprom(ar); | ||
1731 | if (err) | ||
1732 | return err; | ||
1733 | |||
1734 | err = ath_regd_init(regulatory, ar->hw->wiphy, | ||
1735 | carl9170_reg_notifier); | ||
1736 | if (err) | ||
1737 | return err; | ||
1738 | |||
1739 | if (modparam_noht) { | ||
1740 | carl9170_band_2GHz.ht_cap.ht_supported = false; | ||
1741 | carl9170_band_5GHz.ht_cap.ht_supported = false; | ||
1742 | } | ||
1743 | |||
1744 | for (i = 0; i < ar->fw.vif_num; i++) { | ||
1745 | ar->vif_priv[i].id = i; | ||
1746 | ar->vif_priv[i].vif = NULL; | ||
1747 | } | ||
1748 | |||
1749 | err = ieee80211_register_hw(ar->hw); | ||
1750 | if (err) | ||
1751 | return err; | ||
1752 | |||
1753 | /* mac80211 interface is now registered */ | ||
1754 | ar->registered = true; | ||
1755 | |||
1756 | if (!ath_is_world_regd(regulatory)) | ||
1757 | regulatory_hint(ar->hw->wiphy, regulatory->alpha2); | ||
1758 | |||
1759 | #ifdef CONFIG_CARL9170_DEBUGFS | ||
1760 | carl9170_debugfs_register(ar); | ||
1761 | #endif /* CONFIG_CARL9170_DEBUGFS */ | ||
1762 | |||
1763 | err = carl9170_led_init(ar); | ||
1764 | if (err) | ||
1765 | goto err_unreg; | ||
1766 | |||
1767 | #ifdef CONFIG_CARL9170_LEDS | ||
1768 | err = carl9170_led_register(ar); | ||
1769 | if (err) | ||
1770 | goto err_unreg; | ||
1771 | #endif /* CONFIG_CARL9170_LEDS */ | ||
1772 | |||
1773 | #ifdef CONFIG_CARL9170_WPC | ||
1774 | err = carl9170_register_wps_button(ar); | ||
1775 | if (err) | ||
1776 | goto err_unreg; | ||
1777 | #endif /* CONFIG_CARL9170_WPC */ | ||
1778 | |||
1779 | dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n", | ||
1780 | wiphy_name(ar->hw->wiphy)); | ||
1781 | |||
1782 | return 0; | ||
1783 | |||
1784 | err_unreg: | ||
1785 | carl9170_unregister(ar); | ||
1786 | return err; | ||
1787 | } | ||
1788 | |||
1789 | void carl9170_unregister(struct ar9170 *ar) | ||
1790 | { | ||
1791 | if (!ar->registered) | ||
1792 | return; | ||
1793 | |||
1794 | ar->registered = false; | ||
1795 | |||
1796 | #ifdef CONFIG_CARL9170_LEDS | ||
1797 | carl9170_led_unregister(ar); | ||
1798 | #endif /* CONFIG_CARL9170_LEDS */ | ||
1799 | |||
1800 | #ifdef CONFIG_CARL9170_DEBUGFS | ||
1801 | carl9170_debugfs_unregister(ar); | ||
1802 | #endif /* CONFIG_CARL9170_DEBUGFS */ | ||
1803 | |||
1804 | #ifdef CONFIG_CARL9170_WPC | ||
1805 | if (ar->wps.pbc) { | ||
1806 | input_unregister_device(ar->wps.pbc); | ||
1807 | ar->wps.pbc = NULL; | ||
1808 | } | ||
1809 | #endif /* CONFIG_CARL9170_WPC */ | ||
1810 | |||
1811 | carl9170_cancel_worker(ar); | ||
1812 | cancel_work_sync(&ar->restart_work); | ||
1813 | |||
1814 | ieee80211_unregister_hw(ar->hw); | ||
1815 | } | ||
1816 | |||
1817 | void carl9170_free(struct ar9170 *ar) | ||
1818 | { | ||
1819 | WARN_ON(ar->registered); | ||
1820 | WARN_ON(IS_INITIALIZED(ar)); | ||
1821 | |||
1822 | kfree_skb(ar->rx_failover); | ||
1823 | ar->rx_failover = NULL; | ||
1824 | |||
1825 | kfree(ar->mem_bitmap); | ||
1826 | ar->mem_bitmap = NULL; | ||
1827 | |||
1828 | mutex_destroy(&ar->mutex); | ||
1829 | |||
1830 | ieee80211_free_hw(ar->hw); | ||
1831 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c new file mode 100644 index 000000000000..b6ae0e179c8d --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/phy.c | |||
@@ -0,0 +1,1795 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * PHY and RF code | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #include <linux/bitrev.h> | ||
40 | #include "carl9170.h" | ||
41 | #include "cmd.h" | ||
42 | #include "phy.h" | ||
43 | |||
44 | static int carl9170_init_power_cal(struct ar9170 *ar) | ||
45 | { | ||
46 | carl9170_regwrite_begin(ar); | ||
47 | |||
48 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE_MAX, 0x7f); | ||
49 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE1, 0x3f3f3f3f); | ||
50 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE2, 0x3f3f3f3f); | ||
51 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE3, 0x3f3f3f3f); | ||
52 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE4, 0x3f3f3f3f); | ||
53 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE5, 0x3f3f3f3f); | ||
54 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE6, 0x3f3f3f3f); | ||
55 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE7, 0x3f3f3f3f); | ||
56 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE8, 0x3f3f3f3f); | ||
57 | carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE9, 0x3f3f3f3f); | ||
58 | |||
59 | carl9170_regwrite_finish(); | ||
60 | return carl9170_regwrite_result(); | ||
61 | } | ||
62 | |||
63 | struct carl9170_phy_init { | ||
64 | u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; | ||
65 | }; | ||
66 | |||
67 | static struct carl9170_phy_init ar5416_phy_init[] = { | ||
68 | { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
69 | { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, | ||
70 | { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
71 | { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, | ||
72 | { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, | ||
73 | { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, | ||
74 | { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, | ||
75 | { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
76 | { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, | ||
77 | { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, | ||
78 | { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, | ||
79 | { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, | ||
80 | { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
81 | { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, | ||
82 | { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
83 | { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, | ||
84 | { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, | ||
85 | { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, | ||
86 | { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, | ||
87 | { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, | ||
88 | { 0x1c5850, 0x6c48b4e4, 0x6d48b4e4, 0x6d48b0e4, 0x6c48b0e4, }, | ||
89 | { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, | ||
90 | { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, | ||
91 | { 0x1c585c, 0x31395c5e, 0x3139605e, 0x3139605e, 0x31395c5e, }, | ||
92 | { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, | ||
93 | { 0x1c5864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, | ||
94 | { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, | ||
95 | { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, | ||
96 | { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
97 | { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
98 | { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
99 | { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
100 | { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, | ||
101 | { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, | ||
102 | { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, | ||
103 | { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, | ||
104 | { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, | ||
105 | { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
106 | { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, | ||
107 | { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
108 | { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
109 | { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, | ||
110 | { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, | ||
111 | { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, | ||
112 | { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, | ||
113 | { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, | ||
114 | { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, | ||
115 | { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, | ||
116 | { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, | ||
117 | { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, | ||
118 | { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
119 | { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
120 | { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
121 | { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
122 | { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
123 | { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
124 | { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
125 | { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
126 | { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
127 | { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
128 | { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
129 | { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
130 | { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
131 | { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, | ||
132 | { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, | ||
133 | { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, | ||
134 | { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, | ||
135 | { 0x1c59bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, | ||
136 | { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, | ||
137 | { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, | ||
138 | { 0x1c59c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, }, | ||
139 | { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, | ||
140 | { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, | ||
141 | { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
142 | { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
143 | { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
144 | { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, | ||
145 | { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, | ||
146 | { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, | ||
147 | { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, | ||
148 | { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
149 | { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, | ||
150 | { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
151 | { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, | ||
152 | { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, | ||
153 | { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, | ||
154 | { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, | ||
155 | { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, | ||
156 | { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, | ||
157 | { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, | ||
158 | { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, | ||
159 | { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, | ||
160 | { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, | ||
161 | { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, | ||
162 | { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, | ||
163 | { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, | ||
164 | { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, | ||
165 | { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, | ||
166 | { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, | ||
167 | { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, | ||
168 | { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, | ||
169 | { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, | ||
170 | { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, | ||
171 | { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, | ||
172 | { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, | ||
173 | { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, | ||
174 | { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, | ||
175 | { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, | ||
176 | { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, | ||
177 | { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, | ||
178 | { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, | ||
179 | { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, | ||
180 | { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, | ||
181 | { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, | ||
182 | { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, | ||
183 | { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, | ||
184 | { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, | ||
185 | { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, | ||
186 | { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, | ||
187 | { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, | ||
188 | { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, | ||
189 | { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, | ||
190 | { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
191 | { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
192 | { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
193 | { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
194 | { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
195 | { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
196 | { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
197 | { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
198 | { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
199 | { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
200 | { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
201 | { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
202 | { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
203 | { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
204 | { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
205 | { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
206 | { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
207 | { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
208 | { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
209 | { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
210 | { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
211 | { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
212 | { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
213 | { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, | ||
214 | { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
215 | { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
216 | { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, | ||
217 | { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, | ||
218 | { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, | ||
219 | { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, | ||
220 | { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, | ||
221 | { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, | ||
222 | { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, | ||
223 | { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, | ||
224 | { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, | ||
225 | { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, | ||
226 | { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, | ||
227 | { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, | ||
228 | { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, | ||
229 | { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, | ||
230 | { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, | ||
231 | { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, | ||
232 | { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, | ||
233 | { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, | ||
234 | { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, | ||
235 | { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, | ||
236 | { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, | ||
237 | { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, | ||
238 | { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, | ||
239 | { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, | ||
240 | { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, | ||
241 | { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, | ||
242 | { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, | ||
243 | { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, | ||
244 | { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, | ||
245 | { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, | ||
246 | { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, | ||
247 | { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, | ||
248 | { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, | ||
249 | { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, | ||
250 | { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, | ||
251 | { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, | ||
252 | { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, | ||
253 | { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, | ||
254 | { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, | ||
255 | { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
256 | { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
257 | { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
258 | { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
259 | { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
260 | { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
261 | { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
262 | { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
263 | { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
264 | { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
265 | { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
266 | { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
267 | { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
268 | { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
269 | { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
270 | { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
271 | { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
272 | { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
273 | { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
274 | { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
275 | { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, | ||
276 | { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, | ||
277 | { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, | ||
278 | { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
279 | { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
280 | { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
281 | { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
282 | { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
283 | { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
284 | { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
285 | { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
286 | { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
287 | { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
288 | { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
289 | { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
290 | { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
291 | { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
292 | { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
293 | { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
294 | { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
295 | { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
296 | { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, | ||
297 | { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, | ||
298 | { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, | ||
299 | { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, | ||
300 | { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, | ||
301 | { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, | ||
302 | { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, | ||
303 | { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, | ||
304 | { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, | ||
305 | { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, | ||
306 | { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, | ||
307 | { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
308 | { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, | ||
309 | { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
310 | { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
311 | { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, | ||
312 | { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, | ||
313 | { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, | ||
314 | { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, | ||
315 | { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, | ||
316 | { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, | ||
317 | { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
318 | { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, | ||
319 | { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, | ||
320 | { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, | ||
321 | { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, | ||
322 | { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
323 | { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, | ||
324 | { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, | ||
325 | { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, | ||
326 | { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, | ||
327 | { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, | ||
328 | { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, | ||
329 | { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, | ||
330 | { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, | ||
331 | { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, | ||
332 | { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, | ||
333 | { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, | ||
334 | { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, | ||
335 | { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, | ||
336 | { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, | ||
337 | { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, | ||
338 | { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
339 | { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
340 | { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
341 | { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
342 | { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
343 | { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
344 | { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
345 | { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, | ||
346 | { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, | ||
347 | { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, | ||
348 | { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, | ||
349 | { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, | ||
350 | { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, | ||
351 | { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
352 | { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
353 | { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, | ||
354 | { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, | ||
355 | { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, | ||
356 | { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
357 | { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
358 | { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
359 | { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
360 | { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
361 | { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
362 | { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
363 | { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
364 | { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
365 | { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
366 | { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
367 | { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
368 | { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
369 | { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, | ||
370 | { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, | ||
371 | { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, | ||
372 | { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, | ||
373 | { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, | ||
374 | { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, | ||
375 | { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, | ||
376 | { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, | ||
377 | { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, | ||
378 | { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, | ||
379 | { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, | ||
380 | { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, | ||
381 | { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, | ||
382 | { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, | ||
383 | /* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ | ||
384 | { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, | ||
385 | { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, | ||
386 | { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, | ||
387 | { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, | ||
388 | { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, | ||
389 | { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, | ||
390 | { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, | ||
391 | { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, | ||
392 | { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, | ||
393 | { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, | ||
394 | { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, | ||
395 | { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, | ||
396 | { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, | ||
397 | { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, | ||
398 | { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, | ||
399 | { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } | ||
400 | }; | ||
401 | |||
402 | /* | ||
403 | * look up a certain register in ar5416_phy_init[] and return the init. value | ||
404 | * for the band and bandwidth given. Return 0 if register address not found. | ||
405 | */ | ||
406 | static u32 carl9170_def_val(u32 reg, bool is_2ghz, bool is_40mhz) | ||
407 | { | ||
408 | unsigned int i; | ||
409 | for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { | ||
410 | if (ar5416_phy_init[i].reg != reg) | ||
411 | continue; | ||
412 | |||
413 | if (is_2ghz) { | ||
414 | if (is_40mhz) | ||
415 | return ar5416_phy_init[i]._2ghz_40; | ||
416 | else | ||
417 | return ar5416_phy_init[i]._2ghz_20; | ||
418 | } else { | ||
419 | if (is_40mhz) | ||
420 | return ar5416_phy_init[i]._5ghz_40; | ||
421 | else | ||
422 | return ar5416_phy_init[i]._5ghz_20; | ||
423 | } | ||
424 | } | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * initialize some phy regs from eeprom values in modal_header[] | ||
430 | * acc. to band and bandwidth | ||
431 | */ | ||
432 | static int carl9170_init_phy_from_eeprom(struct ar9170 *ar, | ||
433 | bool is_2ghz, bool is_40mhz) | ||
434 | { | ||
435 | static const u8 xpd2pd[16] = { | ||
436 | 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2, | ||
437 | 0x2, 0x3, 0x7, 0x2, 0xb, 0x2, 0x2, 0x2 | ||
438 | }; | ||
439 | /* pointer to the modal_header acc. to band */ | ||
440 | struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz]; | ||
441 | u32 val; | ||
442 | |||
443 | carl9170_regwrite_begin(ar); | ||
444 | |||
445 | /* ant common control (index 0) */ | ||
446 | carl9170_regwrite(AR9170_PHY_REG_SWITCH_COM, | ||
447 | le32_to_cpu(m->antCtrlCommon)); | ||
448 | |||
449 | /* ant control chain 0 (index 1) */ | ||
450 | carl9170_regwrite(AR9170_PHY_REG_SWITCH_CHAIN_0, | ||
451 | le32_to_cpu(m->antCtrlChain[0])); | ||
452 | |||
453 | /* ant control chain 2 (index 2) */ | ||
454 | carl9170_regwrite(AR9170_PHY_REG_SWITCH_CHAIN_2, | ||
455 | le32_to_cpu(m->antCtrlChain[1])); | ||
456 | |||
457 | /* SwSettle (index 3) */ | ||
458 | if (!is_40mhz) { | ||
459 | val = carl9170_def_val(AR9170_PHY_REG_SETTLING, | ||
460 | is_2ghz, is_40mhz); | ||
461 | SET_VAL(AR9170_PHY_SETTLING_SWITCH, val, m->switchSettling); | ||
462 | carl9170_regwrite(AR9170_PHY_REG_SETTLING, val); | ||
463 | } | ||
464 | |||
465 | /* adcDesired, pdaDesired (index 4) */ | ||
466 | val = carl9170_def_val(AR9170_PHY_REG_DESIRED_SZ, is_2ghz, is_40mhz); | ||
467 | SET_VAL(AR9170_PHY_DESIRED_SZ_PGA, val, m->pgaDesiredSize); | ||
468 | SET_VAL(AR9170_PHY_DESIRED_SZ_ADC, val, m->adcDesiredSize); | ||
469 | carl9170_regwrite(AR9170_PHY_REG_DESIRED_SZ, val); | ||
470 | |||
471 | /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */ | ||
472 | val = carl9170_def_val(AR9170_PHY_REG_RF_CTL4, is_2ghz, is_40mhz); | ||
473 | SET_VAL(AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF, val, m->txEndToXpaOff); | ||
474 | SET_VAL(AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF, val, m->txEndToXpaOff); | ||
475 | SET_VAL(AR9170_PHY_RF_CTL4_FRAME_XPAB_ON, val, m->txFrameToXpaOn); | ||
476 | SET_VAL(AR9170_PHY_RF_CTL4_FRAME_XPAA_ON, val, m->txFrameToXpaOn); | ||
477 | carl9170_regwrite(AR9170_PHY_REG_RF_CTL4, val); | ||
478 | |||
479 | /* TxEndToRxOn (index 6) */ | ||
480 | val = carl9170_def_val(AR9170_PHY_REG_RF_CTL3, is_2ghz, is_40mhz); | ||
481 | SET_VAL(AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON, val, m->txEndToRxOn); | ||
482 | carl9170_regwrite(AR9170_PHY_REG_RF_CTL3, val); | ||
483 | |||
484 | /* thresh62 (index 7) */ | ||
485 | val = carl9170_def_val(0x1c8864, is_2ghz, is_40mhz); | ||
486 | val = (val & ~0x7f000) | (m->thresh62 << 12); | ||
487 | carl9170_regwrite(0x1c8864, val); | ||
488 | |||
489 | /* tx/rx attenuation chain 0 (index 8) */ | ||
490 | val = carl9170_def_val(AR9170_PHY_REG_RXGAIN, is_2ghz, is_40mhz); | ||
491 | SET_VAL(AR9170_PHY_RXGAIN_TXRX_ATTEN, val, m->txRxAttenCh[0]); | ||
492 | carl9170_regwrite(AR9170_PHY_REG_RXGAIN, val); | ||
493 | |||
494 | /* tx/rx attenuation chain 2 (index 9) */ | ||
495 | val = carl9170_def_val(AR9170_PHY_REG_RXGAIN_CHAIN_2, | ||
496 | is_2ghz, is_40mhz); | ||
497 | SET_VAL(AR9170_PHY_RXGAIN_TXRX_ATTEN, val, m->txRxAttenCh[1]); | ||
498 | carl9170_regwrite(AR9170_PHY_REG_RXGAIN_CHAIN_2, val); | ||
499 | |||
500 | /* tx/rx margin chain 0 (index 10) */ | ||
501 | val = carl9170_def_val(AR9170_PHY_REG_GAIN_2GHZ, is_2ghz, is_40mhz); | ||
502 | SET_VAL(AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN, val, m->rxTxMarginCh[0]); | ||
503 | /* bsw margin chain 0 for 5GHz only */ | ||
504 | if (!is_2ghz) | ||
505 | SET_VAL(AR9170_PHY_GAIN_2GHZ_BSW_MARGIN, val, m->bswMargin[0]); | ||
506 | carl9170_regwrite(AR9170_PHY_REG_GAIN_2GHZ, val); | ||
507 | |||
508 | /* tx/rx margin chain 2 (index 11) */ | ||
509 | val = carl9170_def_val(AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2, | ||
510 | is_2ghz, is_40mhz); | ||
511 | SET_VAL(AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN, val, m->rxTxMarginCh[1]); | ||
512 | carl9170_regwrite(AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2, val); | ||
513 | |||
514 | /* iqCall, iqCallq chain 0 (index 12) */ | ||
515 | val = carl9170_def_val(AR9170_PHY_REG_TIMING_CTRL4(0), | ||
516 | is_2ghz, is_40mhz); | ||
517 | SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, val, m->iqCalICh[0]); | ||
518 | SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, val, m->iqCalQCh[0]); | ||
519 | carl9170_regwrite(AR9170_PHY_REG_TIMING_CTRL4(0), val); | ||
520 | |||
521 | /* iqCall, iqCallq chain 2 (index 13) */ | ||
522 | val = carl9170_def_val(AR9170_PHY_REG_TIMING_CTRL4(2), | ||
523 | is_2ghz, is_40mhz); | ||
524 | SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, val, m->iqCalICh[1]); | ||
525 | SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, val, m->iqCalQCh[1]); | ||
526 | carl9170_regwrite(AR9170_PHY_REG_TIMING_CTRL4(2), val); | ||
527 | |||
528 | /* xpd gain mask (index 14) */ | ||
529 | val = carl9170_def_val(AR9170_PHY_REG_TPCRG1, is_2ghz, is_40mhz); | ||
530 | SET_VAL(AR9170_PHY_TPCRG1_PD_GAIN_1, val, | ||
531 | xpd2pd[m->xpdGain & 0xf] & 3); | ||
532 | SET_VAL(AR9170_PHY_TPCRG1_PD_GAIN_2, val, | ||
533 | xpd2pd[m->xpdGain & 0xf] >> 2); | ||
534 | carl9170_regwrite(AR9170_PHY_REG_TPCRG1, val); | ||
535 | |||
536 | carl9170_regwrite(AR9170_PHY_REG_RX_CHAINMASK, ar->eeprom.rx_mask); | ||
537 | carl9170_regwrite(AR9170_PHY_REG_CAL_CHAINMASK, ar->eeprom.rx_mask); | ||
538 | |||
539 | carl9170_regwrite_finish(); | ||
540 | return carl9170_regwrite_result(); | ||
541 | } | ||
542 | |||
543 | static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) | ||
544 | { | ||
545 | int i, err; | ||
546 | u32 val; | ||
547 | bool is_2ghz = band == IEEE80211_BAND_2GHZ; | ||
548 | bool is_40mhz = conf_is_ht40(&ar->hw->conf); | ||
549 | |||
550 | carl9170_regwrite_begin(ar); | ||
551 | |||
552 | for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { | ||
553 | if (is_40mhz) { | ||
554 | if (is_2ghz) | ||
555 | val = ar5416_phy_init[i]._2ghz_40; | ||
556 | else | ||
557 | val = ar5416_phy_init[i]._5ghz_40; | ||
558 | } else { | ||
559 | if (is_2ghz) | ||
560 | val = ar5416_phy_init[i]._2ghz_20; | ||
561 | else | ||
562 | val = ar5416_phy_init[i]._5ghz_20; | ||
563 | } | ||
564 | |||
565 | carl9170_regwrite(ar5416_phy_init[i].reg, val); | ||
566 | } | ||
567 | |||
568 | carl9170_regwrite_finish(); | ||
569 | err = carl9170_regwrite_result(); | ||
570 | if (err) | ||
571 | return err; | ||
572 | |||
573 | err = carl9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz); | ||
574 | if (err) | ||
575 | return err; | ||
576 | |||
577 | err = carl9170_init_power_cal(ar); | ||
578 | if (err) | ||
579 | return err; | ||
580 | |||
581 | /* XXX: remove magic! */ | ||
582 | if (is_2ghz) | ||
583 | err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163); | ||
584 | else | ||
585 | err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143); | ||
586 | |||
587 | return err; | ||
588 | } | ||
589 | |||
590 | struct carl9170_rf_initvals { | ||
591 | u32 reg, _5ghz, _2ghz; | ||
592 | }; | ||
593 | |||
594 | static struct carl9170_rf_initvals carl9170_rf_initval[] = { | ||
595 | /* bank 0 */ | ||
596 | { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, | ||
597 | { 0x1c58e0, 0x02008020, 0x02008020}, | ||
598 | /* bank 1 */ | ||
599 | { 0x1c58b0, 0x02108421, 0x02108421}, | ||
600 | { 0x1c58ec, 0x00000008, 0x00000008}, | ||
601 | /* bank 2 */ | ||
602 | { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, | ||
603 | { 0x1c58e0, 0x00000420, 0x00000420}, | ||
604 | /* bank 3 */ | ||
605 | { 0x1c58f0, 0x01400018, 0x01c00018}, | ||
606 | /* bank 4 */ | ||
607 | { 0x1c58b0, 0x000001a1, 0x000001a1}, | ||
608 | { 0x1c58e8, 0x00000001, 0x00000001}, | ||
609 | /* bank 5 */ | ||
610 | { 0x1c58b0, 0x00000013, 0x00000013}, | ||
611 | { 0x1c58e4, 0x00000002, 0x00000002}, | ||
612 | /* bank 6 */ | ||
613 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
614 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
615 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
616 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
617 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
618 | { 0x1c58b0, 0x00004000, 0x00004000}, | ||
619 | { 0x1c58b0, 0x00006c00, 0x00006c00}, | ||
620 | { 0x1c58b0, 0x00002c00, 0x00002c00}, | ||
621 | { 0x1c58b0, 0x00004800, 0x00004800}, | ||
622 | { 0x1c58b0, 0x00004000, 0x00004000}, | ||
623 | { 0x1c58b0, 0x00006000, 0x00006000}, | ||
624 | { 0x1c58b0, 0x00001000, 0x00001000}, | ||
625 | { 0x1c58b0, 0x00004000, 0x00004000}, | ||
626 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
627 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
628 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
629 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
630 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
631 | { 0x1c58b0, 0x00087c00, 0x00087c00}, | ||
632 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
633 | { 0x1c58b0, 0x00005400, 0x00005400}, | ||
634 | { 0x1c58b0, 0x00000c00, 0x00000c00}, | ||
635 | { 0x1c58b0, 0x00001800, 0x00001800}, | ||
636 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
637 | { 0x1c58b0, 0x00006c00, 0x00006c00}, | ||
638 | { 0x1c58b0, 0x00006c00, 0x00006c00}, | ||
639 | { 0x1c58b0, 0x00007c00, 0x00007c00}, | ||
640 | { 0x1c58b0, 0x00002c00, 0x00002c00}, | ||
641 | { 0x1c58b0, 0x00003c00, 0x00003c00}, | ||
642 | { 0x1c58b0, 0x00003800, 0x00003800}, | ||
643 | { 0x1c58b0, 0x00001c00, 0x00001c00}, | ||
644 | { 0x1c58b0, 0x00000800, 0x00000800}, | ||
645 | { 0x1c58b0, 0x00000408, 0x00000408}, | ||
646 | { 0x1c58b0, 0x00004c15, 0x00004c15}, | ||
647 | { 0x1c58b0, 0x00004188, 0x00004188}, | ||
648 | { 0x1c58b0, 0x0000201e, 0x0000201e}, | ||
649 | { 0x1c58b0, 0x00010408, 0x00010408}, | ||
650 | { 0x1c58b0, 0x00000801, 0x00000801}, | ||
651 | { 0x1c58b0, 0x00000c08, 0x00000c08}, | ||
652 | { 0x1c58b0, 0x0000181e, 0x0000181e}, | ||
653 | { 0x1c58b0, 0x00001016, 0x00001016}, | ||
654 | { 0x1c58b0, 0x00002800, 0x00002800}, | ||
655 | { 0x1c58b0, 0x00004010, 0x00004010}, | ||
656 | { 0x1c58b0, 0x0000081c, 0x0000081c}, | ||
657 | { 0x1c58b0, 0x00000115, 0x00000115}, | ||
658 | { 0x1c58b0, 0x00000015, 0x00000015}, | ||
659 | { 0x1c58b0, 0x00000066, 0x00000066}, | ||
660 | { 0x1c58b0, 0x0000001c, 0x0000001c}, | ||
661 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
662 | { 0x1c58b0, 0x00000004, 0x00000004}, | ||
663 | { 0x1c58b0, 0x00000015, 0x00000015}, | ||
664 | { 0x1c58b0, 0x0000001f, 0x0000001f}, | ||
665 | { 0x1c58e0, 0x00000000, 0x00000400}, | ||
666 | /* bank 7 */ | ||
667 | { 0x1c58b0, 0x000000a0, 0x000000a0}, | ||
668 | { 0x1c58b0, 0x00000000, 0x00000000}, | ||
669 | { 0x1c58b0, 0x00000040, 0x00000040}, | ||
670 | { 0x1c58f0, 0x0000001c, 0x0000001c}, | ||
671 | }; | ||
672 | |||
673 | static int carl9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) | ||
674 | { | ||
675 | int err, i; | ||
676 | |||
677 | carl9170_regwrite_begin(ar); | ||
678 | |||
679 | for (i = 0; i < ARRAY_SIZE(carl9170_rf_initval); i++) | ||
680 | carl9170_regwrite(carl9170_rf_initval[i].reg, | ||
681 | band5ghz ? carl9170_rf_initval[i]._5ghz | ||
682 | : carl9170_rf_initval[i]._2ghz); | ||
683 | |||
684 | carl9170_regwrite_finish(); | ||
685 | err = carl9170_regwrite_result(); | ||
686 | if (err) | ||
687 | wiphy_err(ar->hw->wiphy, "rf init failed\n"); | ||
688 | |||
689 | return err; | ||
690 | } | ||
691 | |||
692 | struct carl9170_phy_freq_params { | ||
693 | u8 coeff_exp; | ||
694 | u16 coeff_man; | ||
695 | u8 coeff_exp_shgi; | ||
696 | u16 coeff_man_shgi; | ||
697 | }; | ||
698 | |||
699 | enum carl9170_bw { | ||
700 | CARL9170_BW_20, | ||
701 | CARL9170_BW_40_BELOW, | ||
702 | CARL9170_BW_40_ABOVE, | ||
703 | |||
704 | __CARL9170_NUM_BW, | ||
705 | }; | ||
706 | |||
707 | struct carl9170_phy_freq_entry { | ||
708 | u16 freq; | ||
709 | struct carl9170_phy_freq_params params[__CARL9170_NUM_BW]; | ||
710 | }; | ||
711 | |||
712 | /* NB: must be in sync with channel tables in main! */ | ||
713 | static const struct carl9170_phy_freq_entry carl9170_phy_freq_params[] = { | ||
714 | /* | ||
715 | * freq, | ||
716 | * 20MHz, | ||
717 | * 40MHz (below), | ||
718 | * 40Mhz (above), | ||
719 | */ | ||
720 | { 2412, { | ||
721 | { 3, 21737, 3, 19563, }, | ||
722 | { 3, 21827, 3, 19644, }, | ||
723 | { 3, 21647, 3, 19482, }, | ||
724 | } }, | ||
725 | { 2417, { | ||
726 | { 3, 21692, 3, 19523, }, | ||
727 | { 3, 21782, 3, 19604, }, | ||
728 | { 3, 21602, 3, 19442, }, | ||
729 | } }, | ||
730 | { 2422, { | ||
731 | { 3, 21647, 3, 19482, }, | ||
732 | { 3, 21737, 3, 19563, }, | ||
733 | { 3, 21558, 3, 19402, }, | ||
734 | } }, | ||
735 | { 2427, { | ||
736 | { 3, 21602, 3, 19442, }, | ||
737 | { 3, 21692, 3, 19523, }, | ||
738 | { 3, 21514, 3, 19362, }, | ||
739 | } }, | ||
740 | { 2432, { | ||
741 | { 3, 21558, 3, 19402, }, | ||
742 | { 3, 21647, 3, 19482, }, | ||
743 | { 3, 21470, 3, 19323, }, | ||
744 | } }, | ||
745 | { 2437, { | ||
746 | { 3, 21514, 3, 19362, }, | ||
747 | { 3, 21602, 3, 19442, }, | ||
748 | { 3, 21426, 3, 19283, }, | ||
749 | } }, | ||
750 | { 2442, { | ||
751 | { 3, 21470, 3, 19323, }, | ||
752 | { 3, 21558, 3, 19402, }, | ||
753 | { 3, 21382, 3, 19244, }, | ||
754 | } }, | ||
755 | { 2447, { | ||
756 | { 3, 21426, 3, 19283, }, | ||
757 | { 3, 21514, 3, 19362, }, | ||
758 | { 3, 21339, 3, 19205, }, | ||
759 | } }, | ||
760 | { 2452, { | ||
761 | { 3, 21382, 3, 19244, }, | ||
762 | { 3, 21470, 3, 19323, }, | ||
763 | { 3, 21295, 3, 19166, }, | ||
764 | } }, | ||
765 | { 2457, { | ||
766 | { 3, 21339, 3, 19205, }, | ||
767 | { 3, 21426, 3, 19283, }, | ||
768 | { 3, 21252, 3, 19127, }, | ||
769 | } }, | ||
770 | { 2462, { | ||
771 | { 3, 21295, 3, 19166, }, | ||
772 | { 3, 21382, 3, 19244, }, | ||
773 | { 3, 21209, 3, 19088, }, | ||
774 | } }, | ||
775 | { 2467, { | ||
776 | { 3, 21252, 3, 19127, }, | ||
777 | { 3, 21339, 3, 19205, }, | ||
778 | { 3, 21166, 3, 19050, }, | ||
779 | } }, | ||
780 | { 2472, { | ||
781 | { 3, 21209, 3, 19088, }, | ||
782 | { 3, 21295, 3, 19166, }, | ||
783 | { 3, 21124, 3, 19011, }, | ||
784 | } }, | ||
785 | { 2484, { | ||
786 | { 3, 21107, 3, 18996, }, | ||
787 | { 3, 21192, 3, 19073, }, | ||
788 | { 3, 21022, 3, 18920, }, | ||
789 | } }, | ||
790 | { 4920, { | ||
791 | { 4, 21313, 4, 19181, }, | ||
792 | { 4, 21356, 4, 19220, }, | ||
793 | { 4, 21269, 4, 19142, }, | ||
794 | } }, | ||
795 | { 4940, { | ||
796 | { 4, 21226, 4, 19104, }, | ||
797 | { 4, 21269, 4, 19142, }, | ||
798 | { 4, 21183, 4, 19065, }, | ||
799 | } }, | ||
800 | { 4960, { | ||
801 | { 4, 21141, 4, 19027, }, | ||
802 | { 4, 21183, 4, 19065, }, | ||
803 | { 4, 21098, 4, 18988, }, | ||
804 | } }, | ||
805 | { 4980, { | ||
806 | { 4, 21056, 4, 18950, }, | ||
807 | { 4, 21098, 4, 18988, }, | ||
808 | { 4, 21014, 4, 18912, }, | ||
809 | } }, | ||
810 | { 5040, { | ||
811 | { 4, 20805, 4, 18725, }, | ||
812 | { 4, 20846, 4, 18762, }, | ||
813 | { 4, 20764, 4, 18687, }, | ||
814 | } }, | ||
815 | { 5060, { | ||
816 | { 4, 20723, 4, 18651, }, | ||
817 | { 4, 20764, 4, 18687, }, | ||
818 | { 4, 20682, 4, 18614, }, | ||
819 | } }, | ||
820 | { 5080, { | ||
821 | { 4, 20641, 4, 18577, }, | ||
822 | { 4, 20682, 4, 18614, }, | ||
823 | { 4, 20601, 4, 18541, }, | ||
824 | } }, | ||
825 | { 5180, { | ||
826 | { 4, 20243, 4, 18219, }, | ||
827 | { 4, 20282, 4, 18254, }, | ||
828 | { 4, 20204, 4, 18183, }, | ||
829 | } }, | ||
830 | { 5200, { | ||
831 | { 4, 20165, 4, 18148, }, | ||
832 | { 4, 20204, 4, 18183, }, | ||
833 | { 4, 20126, 4, 18114, }, | ||
834 | } }, | ||
835 | { 5220, { | ||
836 | { 4, 20088, 4, 18079, }, | ||
837 | { 4, 20126, 4, 18114, }, | ||
838 | { 4, 20049, 4, 18044, }, | ||
839 | } }, | ||
840 | { 5240, { | ||
841 | { 4, 20011, 4, 18010, }, | ||
842 | { 4, 20049, 4, 18044, }, | ||
843 | { 4, 19973, 4, 17976, }, | ||
844 | } }, | ||
845 | { 5260, { | ||
846 | { 4, 19935, 4, 17941, }, | ||
847 | { 4, 19973, 4, 17976, }, | ||
848 | { 4, 19897, 4, 17907, }, | ||
849 | } }, | ||
850 | { 5280, { | ||
851 | { 4, 19859, 4, 17873, }, | ||
852 | { 4, 19897, 4, 17907, }, | ||
853 | { 4, 19822, 4, 17840, }, | ||
854 | } }, | ||
855 | { 5300, { | ||
856 | { 4, 19784, 4, 17806, }, | ||
857 | { 4, 19822, 4, 17840, }, | ||
858 | { 4, 19747, 4, 17772, }, | ||
859 | } }, | ||
860 | { 5320, { | ||
861 | { 4, 19710, 4, 17739, }, | ||
862 | { 4, 19747, 4, 17772, }, | ||
863 | { 4, 19673, 4, 17706, }, | ||
864 | } }, | ||
865 | { 5500, { | ||
866 | { 4, 19065, 4, 17159, }, | ||
867 | { 4, 19100, 4, 17190, }, | ||
868 | { 4, 19030, 4, 17127, }, | ||
869 | } }, | ||
870 | { 5520, { | ||
871 | { 4, 18996, 4, 17096, }, | ||
872 | { 4, 19030, 4, 17127, }, | ||
873 | { 4, 18962, 4, 17065, }, | ||
874 | } }, | ||
875 | { 5540, { | ||
876 | { 4, 18927, 4, 17035, }, | ||
877 | { 4, 18962, 4, 17065, }, | ||
878 | { 4, 18893, 4, 17004, }, | ||
879 | } }, | ||
880 | { 5560, { | ||
881 | { 4, 18859, 4, 16973, }, | ||
882 | { 4, 18893, 4, 17004, }, | ||
883 | { 4, 18825, 4, 16943, }, | ||
884 | } }, | ||
885 | { 5580, { | ||
886 | { 4, 18792, 4, 16913, }, | ||
887 | { 4, 18825, 4, 16943, }, | ||
888 | { 4, 18758, 4, 16882, }, | ||
889 | } }, | ||
890 | { 5600, { | ||
891 | { 4, 18725, 4, 16852, }, | ||
892 | { 4, 18758, 4, 16882, }, | ||
893 | { 4, 18691, 4, 16822, }, | ||
894 | } }, | ||
895 | { 5620, { | ||
896 | { 4, 18658, 4, 16792, }, | ||
897 | { 4, 18691, 4, 16822, }, | ||
898 | { 4, 18625, 4, 16762, }, | ||
899 | } }, | ||
900 | { 5640, { | ||
901 | { 4, 18592, 4, 16733, }, | ||
902 | { 4, 18625, 4, 16762, }, | ||
903 | { 4, 18559, 4, 16703, }, | ||
904 | } }, | ||
905 | { 5660, { | ||
906 | { 4, 18526, 4, 16673, }, | ||
907 | { 4, 18559, 4, 16703, }, | ||
908 | { 4, 18493, 4, 16644, }, | ||
909 | } }, | ||
910 | { 5680, { | ||
911 | { 4, 18461, 4, 16615, }, | ||
912 | { 4, 18493, 4, 16644, }, | ||
913 | { 4, 18428, 4, 16586, }, | ||
914 | } }, | ||
915 | { 5700, { | ||
916 | { 4, 18396, 4, 16556, }, | ||
917 | { 4, 18428, 4, 16586, }, | ||
918 | { 4, 18364, 4, 16527, }, | ||
919 | } }, | ||
920 | { 5745, { | ||
921 | { 4, 18252, 4, 16427, }, | ||
922 | { 4, 18284, 4, 16455, }, | ||
923 | { 4, 18220, 4, 16398, }, | ||
924 | } }, | ||
925 | { 5765, { | ||
926 | { 4, 18189, 5, 32740, }, | ||
927 | { 4, 18220, 4, 16398, }, | ||
928 | { 4, 18157, 5, 32683, }, | ||
929 | } }, | ||
930 | { 5785, { | ||
931 | { 4, 18126, 5, 32626, }, | ||
932 | { 4, 18157, 5, 32683, }, | ||
933 | { 4, 18094, 5, 32570, }, | ||
934 | } }, | ||
935 | { 5805, { | ||
936 | { 4, 18063, 5, 32514, }, | ||
937 | { 4, 18094, 5, 32570, }, | ||
938 | { 4, 18032, 5, 32458, }, | ||
939 | } }, | ||
940 | { 5825, { | ||
941 | { 4, 18001, 5, 32402, }, | ||
942 | { 4, 18032, 5, 32458, }, | ||
943 | { 4, 17970, 5, 32347, }, | ||
944 | } }, | ||
945 | { 5170, { | ||
946 | { 4, 20282, 4, 18254, }, | ||
947 | { 4, 20321, 4, 18289, }, | ||
948 | { 4, 20243, 4, 18219, }, | ||
949 | } }, | ||
950 | { 5190, { | ||
951 | { 4, 20204, 4, 18183, }, | ||
952 | { 4, 20243, 4, 18219, }, | ||
953 | { 4, 20165, 4, 18148, }, | ||
954 | } }, | ||
955 | { 5210, { | ||
956 | { 4, 20126, 4, 18114, }, | ||
957 | { 4, 20165, 4, 18148, }, | ||
958 | { 4, 20088, 4, 18079, }, | ||
959 | } }, | ||
960 | { 5230, { | ||
961 | { 4, 20049, 4, 18044, }, | ||
962 | { 4, 20088, 4, 18079, }, | ||
963 | { 4, 20011, 4, 18010, }, | ||
964 | } }, | ||
965 | }; | ||
966 | |||
967 | static int carl9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, | ||
968 | u32 freq, enum carl9170_bw bw) | ||
969 | { | ||
970 | int err; | ||
971 | u32 d0, d1, td0, td1, fd0, fd1; | ||
972 | u8 chansel; | ||
973 | u8 refsel0 = 1, refsel1 = 0; | ||
974 | u8 lf_synth = 0; | ||
975 | |||
976 | switch (bw) { | ||
977 | case CARL9170_BW_40_ABOVE: | ||
978 | freq += 10; | ||
979 | break; | ||
980 | case CARL9170_BW_40_BELOW: | ||
981 | freq -= 10; | ||
982 | break; | ||
983 | case CARL9170_BW_20: | ||
984 | break; | ||
985 | default: | ||
986 | BUG(); | ||
987 | return -ENOSYS; | ||
988 | } | ||
989 | |||
990 | if (band5ghz) { | ||
991 | if (freq % 10) { | ||
992 | chansel = (freq - 4800) / 5; | ||
993 | } else { | ||
994 | chansel = ((freq - 4800) / 10) * 2; | ||
995 | refsel0 = 0; | ||
996 | refsel1 = 1; | ||
997 | } | ||
998 | chansel = byte_rev_table[chansel]; | ||
999 | } else { | ||
1000 | if (freq == 2484) { | ||
1001 | chansel = 10 + (freq - 2274) / 5; | ||
1002 | lf_synth = 1; | ||
1003 | } else | ||
1004 | chansel = 16 + (freq - 2272) / 5; | ||
1005 | chansel *= 4; | ||
1006 | chansel = byte_rev_table[chansel]; | ||
1007 | } | ||
1008 | |||
1009 | d1 = chansel; | ||
1010 | d0 = 0x21 | | ||
1011 | refsel0 << 3 | | ||
1012 | refsel1 << 2 | | ||
1013 | lf_synth << 1; | ||
1014 | td0 = d0 & 0x1f; | ||
1015 | td1 = d1 & 0x1f; | ||
1016 | fd0 = td1 << 5 | td0; | ||
1017 | |||
1018 | td0 = (d0 >> 5) & 0x7; | ||
1019 | td1 = (d1 >> 5) & 0x7; | ||
1020 | fd1 = td1 << 5 | td0; | ||
1021 | |||
1022 | carl9170_regwrite_begin(ar); | ||
1023 | |||
1024 | carl9170_regwrite(0x1c58b0, fd0); | ||
1025 | carl9170_regwrite(0x1c58e8, fd1); | ||
1026 | |||
1027 | carl9170_regwrite_finish(); | ||
1028 | err = carl9170_regwrite_result(); | ||
1029 | if (err) | ||
1030 | return err; | ||
1031 | |||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | static const struct carl9170_phy_freq_params * | ||
1036 | carl9170_get_hw_dyn_params(struct ieee80211_channel *channel, | ||
1037 | enum carl9170_bw bw) | ||
1038 | { | ||
1039 | unsigned int chanidx = 0; | ||
1040 | u16 freq = 2412; | ||
1041 | |||
1042 | if (channel) { | ||
1043 | chanidx = channel->hw_value; | ||
1044 | freq = channel->center_freq; | ||
1045 | } | ||
1046 | |||
1047 | BUG_ON(chanidx >= ARRAY_SIZE(carl9170_phy_freq_params)); | ||
1048 | |||
1049 | BUILD_BUG_ON(__CARL9170_NUM_BW != 3); | ||
1050 | |||
1051 | WARN_ON(carl9170_phy_freq_params[chanidx].freq != freq); | ||
1052 | |||
1053 | return &carl9170_phy_freq_params[chanidx].params[bw]; | ||
1054 | } | ||
1055 | |||
1056 | static int carl9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) | ||
1057 | { | ||
1058 | int idx = nfreqs - 2; | ||
1059 | |||
1060 | while (idx >= 0) { | ||
1061 | if (f >= freqs[idx]) | ||
1062 | return idx; | ||
1063 | idx--; | ||
1064 | } | ||
1065 | |||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | static s32 carl9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) | ||
1070 | { | ||
1071 | /* nothing to interpolate, it's horizontal */ | ||
1072 | if (y2 == y1) | ||
1073 | return y1; | ||
1074 | |||
1075 | /* check if we hit one of the edges */ | ||
1076 | if (x == x1) | ||
1077 | return y1; | ||
1078 | if (x == x2) | ||
1079 | return y2; | ||
1080 | |||
1081 | /* x1 == x2 is bad, hopefully == x */ | ||
1082 | if (x2 == x1) | ||
1083 | return y1; | ||
1084 | |||
1085 | return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); | ||
1086 | } | ||
1087 | |||
1088 | static u8 carl9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) | ||
1089 | { | ||
1090 | #define SHIFT 8 | ||
1091 | s32 y; | ||
1092 | |||
1093 | y = carl9170_interpolate_s32(x << SHIFT, x1 << SHIFT, | ||
1094 | y1 << SHIFT, x2 << SHIFT, y2 << SHIFT); | ||
1095 | |||
1096 | /* | ||
1097 | * XXX: unwrap this expression | ||
1098 | * Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)? | ||
1099 | * Can we rely on the compiler to optimise away the div? | ||
1100 | */ | ||
1101 | return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); | ||
1102 | #undef SHIFT | ||
1103 | } | ||
1104 | |||
1105 | static u8 carl9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array) | ||
1106 | { | ||
1107 | int i; | ||
1108 | |||
1109 | for (i = 0; i < 3; i++) { | ||
1110 | if (x <= x_array[i + 1]) | ||
1111 | break; | ||
1112 | } | ||
1113 | |||
1114 | return carl9170_interpolate_u8(x, x_array[i], y_array[i], | ||
1115 | x_array[i + 1], y_array[i + 1]); | ||
1116 | } | ||
1117 | |||
1118 | static int carl9170_set_freq_cal_data(struct ar9170 *ar, | ||
1119 | struct ieee80211_channel *channel) | ||
1120 | { | ||
1121 | u8 *cal_freq_pier; | ||
1122 | u8 vpds[2][AR5416_PD_GAIN_ICEPTS]; | ||
1123 | u8 pwrs[2][AR5416_PD_GAIN_ICEPTS]; | ||
1124 | int chain, idx, i; | ||
1125 | u32 phy_data = 0; | ||
1126 | u8 f, tmp; | ||
1127 | |||
1128 | switch (channel->band) { | ||
1129 | case IEEE80211_BAND_2GHZ: | ||
1130 | f = channel->center_freq - 2300; | ||
1131 | cal_freq_pier = ar->eeprom.cal_freq_pier_2G; | ||
1132 | i = AR5416_NUM_2G_CAL_PIERS - 1; | ||
1133 | break; | ||
1134 | |||
1135 | case IEEE80211_BAND_5GHZ: | ||
1136 | f = (channel->center_freq - 4800) / 5; | ||
1137 | cal_freq_pier = ar->eeprom.cal_freq_pier_5G; | ||
1138 | i = AR5416_NUM_5G_CAL_PIERS - 1; | ||
1139 | break; | ||
1140 | |||
1141 | default: | ||
1142 | return -EINVAL; | ||
1143 | break; | ||
1144 | } | ||
1145 | |||
1146 | for (; i >= 0; i--) { | ||
1147 | if (cal_freq_pier[i] != 0xff) | ||
1148 | break; | ||
1149 | } | ||
1150 | if (i < 0) | ||
1151 | return -EINVAL; | ||
1152 | |||
1153 | idx = carl9170_find_freq_idx(i, cal_freq_pier, f); | ||
1154 | |||
1155 | carl9170_regwrite_begin(ar); | ||
1156 | |||
1157 | for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) { | ||
1158 | for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) { | ||
1159 | struct ar9170_calibration_data_per_freq *cal_pier_data; | ||
1160 | int j; | ||
1161 | |||
1162 | switch (channel->band) { | ||
1163 | case IEEE80211_BAND_2GHZ: | ||
1164 | cal_pier_data = &ar->eeprom. | ||
1165 | cal_pier_data_2G[chain][idx]; | ||
1166 | break; | ||
1167 | |||
1168 | case IEEE80211_BAND_5GHZ: | ||
1169 | cal_pier_data = &ar->eeprom. | ||
1170 | cal_pier_data_5G[chain][idx]; | ||
1171 | break; | ||
1172 | |||
1173 | default: | ||
1174 | return -EINVAL; | ||
1175 | } | ||
1176 | |||
1177 | for (j = 0; j < 2; j++) { | ||
1178 | vpds[j][i] = carl9170_interpolate_u8(f, | ||
1179 | cal_freq_pier[idx], | ||
1180 | cal_pier_data->vpd_pdg[j][i], | ||
1181 | cal_freq_pier[idx + 1], | ||
1182 | cal_pier_data[1].vpd_pdg[j][i]); | ||
1183 | |||
1184 | pwrs[j][i] = carl9170_interpolate_u8(f, | ||
1185 | cal_freq_pier[idx], | ||
1186 | cal_pier_data->pwr_pdg[j][i], | ||
1187 | cal_freq_pier[idx + 1], | ||
1188 | cal_pier_data[1].pwr_pdg[j][i]) / 2; | ||
1189 | } | ||
1190 | } | ||
1191 | |||
1192 | for (i = 0; i < 76; i++) { | ||
1193 | if (i < 25) { | ||
1194 | tmp = carl9170_interpolate_val(i, &pwrs[0][0], | ||
1195 | &vpds[0][0]); | ||
1196 | } else { | ||
1197 | tmp = carl9170_interpolate_val(i - 12, | ||
1198 | &pwrs[1][0], | ||
1199 | &vpds[1][0]); | ||
1200 | } | ||
1201 | |||
1202 | phy_data |= tmp << ((i & 3) << 3); | ||
1203 | if ((i & 3) == 3) { | ||
1204 | carl9170_regwrite(0x1c6280 + chain * 0x1000 + | ||
1205 | (i & ~3), phy_data); | ||
1206 | phy_data = 0; | ||
1207 | } | ||
1208 | } | ||
1209 | |||
1210 | for (i = 19; i < 32; i++) | ||
1211 | carl9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2), | ||
1212 | 0x0); | ||
1213 | } | ||
1214 | |||
1215 | carl9170_regwrite_finish(); | ||
1216 | return carl9170_regwrite_result(); | ||
1217 | } | ||
1218 | |||
1219 | static u8 carl9170_get_max_edge_power(struct ar9170 *ar, | ||
1220 | u32 freq, struct ar9170_calctl_edges edges[]) | ||
1221 | { | ||
1222 | int i; | ||
1223 | u8 rc = AR5416_MAX_RATE_POWER; | ||
1224 | u8 f; | ||
1225 | if (freq < 3000) | ||
1226 | f = freq - 2300; | ||
1227 | else | ||
1228 | f = (freq - 4800) / 5; | ||
1229 | |||
1230 | for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { | ||
1231 | if (edges[i].channel == 0xff) | ||
1232 | break; | ||
1233 | if (f == edges[i].channel) { | ||
1234 | /* exact freq match */ | ||
1235 | rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS; | ||
1236 | break; | ||
1237 | } | ||
1238 | if (i > 0 && f < edges[i].channel) { | ||
1239 | if (f > edges[i - 1].channel && | ||
1240 | edges[i - 1].power_flags & | ||
1241 | AR9170_CALCTL_EDGE_FLAGS) { | ||
1242 | /* lower channel has the inband flag set */ | ||
1243 | rc = edges[i - 1].power_flags & | ||
1244 | ~AR9170_CALCTL_EDGE_FLAGS; | ||
1245 | } | ||
1246 | break; | ||
1247 | } | ||
1248 | } | ||
1249 | |||
1250 | if (i == AR5416_NUM_BAND_EDGES) { | ||
1251 | if (f > edges[i - 1].channel && | ||
1252 | edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { | ||
1253 | /* lower channel has the inband flag set */ | ||
1254 | rc = edges[i - 1].power_flags & | ||
1255 | ~AR9170_CALCTL_EDGE_FLAGS; | ||
1256 | } | ||
1257 | } | ||
1258 | return rc; | ||
1259 | } | ||
1260 | |||
1261 | static u8 carl9170_get_heavy_clip(struct ar9170 *ar, u32 freq, | ||
1262 | enum carl9170_bw bw, struct ar9170_calctl_edges edges[]) | ||
1263 | { | ||
1264 | u8 f; | ||
1265 | int i; | ||
1266 | u8 rc = 0; | ||
1267 | |||
1268 | if (freq < 3000) | ||
1269 | f = freq - 2300; | ||
1270 | else | ||
1271 | f = (freq - 4800) / 5; | ||
1272 | |||
1273 | if (bw == CARL9170_BW_40_BELOW || bw == CARL9170_BW_40_ABOVE) | ||
1274 | rc |= 0xf0; | ||
1275 | |||
1276 | for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { | ||
1277 | if (edges[i].channel == 0xff) | ||
1278 | break; | ||
1279 | if (f == edges[i].channel) { | ||
1280 | if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS)) | ||
1281 | rc |= 0x0f; | ||
1282 | break; | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | return rc; | ||
1287 | } | ||
1288 | |||
1289 | /* | ||
1290 | * calculate the conformance test limits and the heavy clip parameter | ||
1291 | * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706) | ||
1292 | */ | ||
1293 | static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw) | ||
1294 | { | ||
1295 | u8 ctl_grp; /* CTL group */ | ||
1296 | u8 ctl_idx; /* CTL index */ | ||
1297 | int i, j; | ||
1298 | struct ctl_modes { | ||
1299 | u8 ctl_mode; | ||
1300 | u8 max_power; | ||
1301 | u8 *pwr_cal_data; | ||
1302 | int pwr_cal_len; | ||
1303 | } *modes; | ||
1304 | |||
1305 | /* | ||
1306 | * order is relevant in the mode_list_*: we fall back to the | ||
1307 | * lower indices if any mode is missed in the EEPROM. | ||
1308 | */ | ||
1309 | struct ctl_modes mode_list_2ghz[] = { | ||
1310 | { CTL_11B, 0, ar->power_2G_cck, 4 }, | ||
1311 | { CTL_11G, 0, ar->power_2G_ofdm, 4 }, | ||
1312 | { CTL_2GHT20, 0, ar->power_2G_ht20, 8 }, | ||
1313 | { CTL_2GHT40, 0, ar->power_2G_ht40, 8 }, | ||
1314 | }; | ||
1315 | struct ctl_modes mode_list_5ghz[] = { | ||
1316 | { CTL_11A, 0, ar->power_5G_leg, 4 }, | ||
1317 | { CTL_5GHT20, 0, ar->power_5G_ht20, 8 }, | ||
1318 | { CTL_5GHT40, 0, ar->power_5G_ht40, 8 }, | ||
1319 | }; | ||
1320 | int nr_modes; | ||
1321 | |||
1322 | #define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) | ||
1323 | |||
1324 | ar->heavy_clip = 0; | ||
1325 | |||
1326 | /* | ||
1327 | * TODO: investigate the differences between OTUS' | ||
1328 | * hpreg.c::zfHpGetRegulatoryDomain() and | ||
1329 | * ath/regd.c::ath_regd_get_band_ctl() - | ||
1330 | * e.g. for FCC3_WORLD the OTUS procedure | ||
1331 | * always returns CTL_FCC, while the one in ath/ delivers | ||
1332 | * CTL_ETSI for 2GHz and CTL_FCC for 5GHz. | ||
1333 | */ | ||
1334 | ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory, | ||
1335 | ar->hw->conf.channel->band); | ||
1336 | |||
1337 | /* ctl group not found - either invalid band (NO_CTL) or ww roaming */ | ||
1338 | if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL) | ||
1339 | ctl_grp = CTL_FCC; | ||
1340 | |||
1341 | if (ctl_grp != CTL_FCC) | ||
1342 | /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */ | ||
1343 | return; | ||
1344 | |||
1345 | if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { | ||
1346 | modes = mode_list_2ghz; | ||
1347 | nr_modes = ARRAY_SIZE(mode_list_2ghz); | ||
1348 | } else { | ||
1349 | modes = mode_list_5ghz; | ||
1350 | nr_modes = ARRAY_SIZE(mode_list_5ghz); | ||
1351 | } | ||
1352 | |||
1353 | for (i = 0; i < nr_modes; i++) { | ||
1354 | u8 c = ctl_grp | modes[i].ctl_mode; | ||
1355 | for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++) | ||
1356 | if (c == ar->eeprom.ctl_index[ctl_idx]) | ||
1357 | break; | ||
1358 | if (ctl_idx < AR5416_NUM_CTLS) { | ||
1359 | int f_off = 0; | ||
1360 | |||
1361 | /* | ||
1362 | * determine heavy clip parameter | ||
1363 | * from the 11G edges array | ||
1364 | */ | ||
1365 | if (modes[i].ctl_mode == CTL_11G) { | ||
1366 | ar->heavy_clip = | ||
1367 | carl9170_get_heavy_clip(ar, | ||
1368 | freq, bw, EDGES(ctl_idx, 1)); | ||
1369 | } | ||
1370 | |||
1371 | /* adjust freq for 40MHz */ | ||
1372 | if (modes[i].ctl_mode == CTL_2GHT40 || | ||
1373 | modes[i].ctl_mode == CTL_5GHT40) { | ||
1374 | if (bw == CARL9170_BW_40_BELOW) | ||
1375 | f_off = -10; | ||
1376 | else | ||
1377 | f_off = 10; | ||
1378 | } | ||
1379 | |||
1380 | modes[i].max_power = | ||
1381 | carl9170_get_max_edge_power(ar, | ||
1382 | freq+f_off, EDGES(ctl_idx, 1)); | ||
1383 | |||
1384 | /* | ||
1385 | * TODO: check if the regulatory max. power is | ||
1386 | * controlled by cfg80211 for DFS. | ||
1387 | * (hpmain applies it to max_power itself for DFS freq) | ||
1388 | */ | ||
1389 | |||
1390 | } else { | ||
1391 | /* | ||
1392 | * Workaround in otus driver, hpmain.c, line 3906: | ||
1393 | * if no data for 5GHT20 are found, take the | ||
1394 | * legacy 5G value. We extend this here to fallback | ||
1395 | * from any other HT* or 11G, too. | ||
1396 | */ | ||
1397 | int k = i; | ||
1398 | |||
1399 | modes[i].max_power = AR5416_MAX_RATE_POWER; | ||
1400 | while (k-- > 0) { | ||
1401 | if (modes[k].max_power != | ||
1402 | AR5416_MAX_RATE_POWER) { | ||
1403 | modes[i].max_power = modes[k].max_power; | ||
1404 | break; | ||
1405 | } | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | /* apply max power to pwr_cal_data (ar->power_*) */ | ||
1410 | for (j = 0; j < modes[i].pwr_cal_len; j++) { | ||
1411 | modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j], | ||
1412 | modes[i].max_power); | ||
1413 | } | ||
1414 | } | ||
1415 | |||
1416 | if (ar->heavy_clip & 0xf0) { | ||
1417 | ar->power_2G_ht40[0]--; | ||
1418 | ar->power_2G_ht40[1]--; | ||
1419 | ar->power_2G_ht40[2]--; | ||
1420 | } | ||
1421 | if (ar->heavy_clip & 0xf) { | ||
1422 | ar->power_2G_ht20[0]++; | ||
1423 | ar->power_2G_ht20[1]++; | ||
1424 | ar->power_2G_ht20[2]++; | ||
1425 | } | ||
1426 | |||
1427 | #undef EDGES | ||
1428 | } | ||
1429 | |||
1430 | static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq, | ||
1431 | enum carl9170_bw bw) | ||
1432 | { | ||
1433 | struct ar9170_calibration_target_power_legacy *ctpl; | ||
1434 | struct ar9170_calibration_target_power_ht *ctph; | ||
1435 | u8 *ctpres; | ||
1436 | int ntargets; | ||
1437 | int idx, i, n; | ||
1438 | u8 ackpower, ackchains, f; | ||
1439 | u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; | ||
1440 | |||
1441 | if (freq < 3000) | ||
1442 | f = freq - 2300; | ||
1443 | else | ||
1444 | f = (freq - 4800)/5; | ||
1445 | |||
1446 | /* | ||
1447 | * cycle through the various modes | ||
1448 | * | ||
1449 | * legacy modes first: 5G, 2G CCK, 2G OFDM | ||
1450 | */ | ||
1451 | for (i = 0; i < 3; i++) { | ||
1452 | switch (i) { | ||
1453 | case 0: /* 5 GHz legacy */ | ||
1454 | ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; | ||
1455 | ntargets = AR5416_NUM_5G_TARGET_PWRS; | ||
1456 | ctpres = ar->power_5G_leg; | ||
1457 | break; | ||
1458 | case 1: /* 2.4 GHz CCK */ | ||
1459 | ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; | ||
1460 | ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; | ||
1461 | ctpres = ar->power_2G_cck; | ||
1462 | break; | ||
1463 | case 2: /* 2.4 GHz OFDM */ | ||
1464 | ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; | ||
1465 | ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; | ||
1466 | ctpres = ar->power_2G_ofdm; | ||
1467 | break; | ||
1468 | default: | ||
1469 | BUG(); | ||
1470 | } | ||
1471 | |||
1472 | for (n = 0; n < ntargets; n++) { | ||
1473 | if (ctpl[n].freq == 0xff) | ||
1474 | break; | ||
1475 | pwr_freqs[n] = ctpl[n].freq; | ||
1476 | } | ||
1477 | ntargets = n; | ||
1478 | idx = carl9170_find_freq_idx(ntargets, pwr_freqs, f); | ||
1479 | for (n = 0; n < 4; n++) | ||
1480 | ctpres[n] = carl9170_interpolate_u8(f, | ||
1481 | ctpl[idx + 0].freq, ctpl[idx + 0].power[n], | ||
1482 | ctpl[idx + 1].freq, ctpl[idx + 1].power[n]); | ||
1483 | } | ||
1484 | |||
1485 | /* HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 */ | ||
1486 | for (i = 0; i < 4; i++) { | ||
1487 | switch (i) { | ||
1488 | case 0: /* 5 GHz HT 20 */ | ||
1489 | ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; | ||
1490 | ntargets = AR5416_NUM_5G_TARGET_PWRS; | ||
1491 | ctpres = ar->power_5G_ht20; | ||
1492 | break; | ||
1493 | case 1: /* 5 GHz HT 40 */ | ||
1494 | ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; | ||
1495 | ntargets = AR5416_NUM_5G_TARGET_PWRS; | ||
1496 | ctpres = ar->power_5G_ht40; | ||
1497 | break; | ||
1498 | case 2: /* 2.4 GHz HT 20 */ | ||
1499 | ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; | ||
1500 | ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; | ||
1501 | ctpres = ar->power_2G_ht20; | ||
1502 | break; | ||
1503 | case 3: /* 2.4 GHz HT 40 */ | ||
1504 | ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; | ||
1505 | ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; | ||
1506 | ctpres = ar->power_2G_ht40; | ||
1507 | break; | ||
1508 | default: | ||
1509 | BUG(); | ||
1510 | } | ||
1511 | |||
1512 | for (n = 0; n < ntargets; n++) { | ||
1513 | if (ctph[n].freq == 0xff) | ||
1514 | break; | ||
1515 | pwr_freqs[n] = ctph[n].freq; | ||
1516 | } | ||
1517 | ntargets = n; | ||
1518 | idx = carl9170_find_freq_idx(ntargets, pwr_freqs, f); | ||
1519 | for (n = 0; n < 8; n++) | ||
1520 | ctpres[n] = carl9170_interpolate_u8(f, | ||
1521 | ctph[idx + 0].freq, ctph[idx + 0].power[n], | ||
1522 | ctph[idx + 1].freq, ctph[idx + 1].power[n]); | ||
1523 | } | ||
1524 | |||
1525 | /* calc. conformance test limits and apply to ar->power*[] */ | ||
1526 | carl9170_calc_ctl(ar, freq, bw); | ||
1527 | |||
1528 | /* set ACK/CTS TX power */ | ||
1529 | carl9170_regwrite_begin(ar); | ||
1530 | |||
1531 | if (ar->eeprom.tx_mask != 1) | ||
1532 | ackchains = AR9170_TX_PHY_TXCHAIN_2; | ||
1533 | else | ||
1534 | ackchains = AR9170_TX_PHY_TXCHAIN_1; | ||
1535 | |||
1536 | if (freq < 3000) | ||
1537 | ackpower = ar->power_2G_ofdm[0] & 0x3f; | ||
1538 | else | ||
1539 | ackpower = ar->power_5G_leg[0] & 0x3f; | ||
1540 | |||
1541 | carl9170_regwrite(AR9170_MAC_REG_ACK_TPC, | ||
1542 | 0x3c1e | ackpower << 20 | ackchains << 26); | ||
1543 | carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_TPC, | ||
1544 | ackpower << 5 | ackchains << 11 | | ||
1545 | ackpower << 21 | ackchains << 27); | ||
1546 | |||
1547 | carl9170_regwrite(AR9170_MAC_REG_CFEND_QOSNULL_TPC, | ||
1548 | ackpower << 5 | ackchains << 11 | | ||
1549 | ackpower << 21 | ackchains << 27); | ||
1550 | |||
1551 | carl9170_regwrite_finish(); | ||
1552 | return carl9170_regwrite_result(); | ||
1553 | } | ||
1554 | |||
1555 | int carl9170_get_noisefloor(struct ar9170 *ar) | ||
1556 | { | ||
1557 | static const u32 phy_regs[] = { | ||
1558 | AR9170_PHY_REG_CCA, AR9170_PHY_REG_CH2_CCA, | ||
1559 | AR9170_PHY_REG_EXT_CCA, AR9170_PHY_REG_CH2_EXT_CCA }; | ||
1560 | u32 phy_res[ARRAY_SIZE(phy_regs)]; | ||
1561 | int err, i; | ||
1562 | |||
1563 | BUILD_BUG_ON(ARRAY_SIZE(phy_regs) != ARRAY_SIZE(ar->noise)); | ||
1564 | |||
1565 | err = carl9170_read_mreg(ar, ARRAY_SIZE(phy_regs), phy_regs, phy_res); | ||
1566 | if (err) | ||
1567 | return err; | ||
1568 | |||
1569 | for (i = 0; i < 2; i++) { | ||
1570 | ar->noise[i] = sign_extend32(GET_VAL( | ||
1571 | AR9170_PHY_CCA_MIN_PWR, phy_res[i]), 8); | ||
1572 | |||
1573 | ar->noise[i + 2] = sign_extend32(GET_VAL( | ||
1574 | AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8); | ||
1575 | } | ||
1576 | |||
1577 | return 0; | ||
1578 | } | ||
1579 | |||
1580 | static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type) | ||
1581 | { | ||
1582 | switch (type) { | ||
1583 | case NL80211_CHAN_NO_HT: | ||
1584 | case NL80211_CHAN_HT20: | ||
1585 | return CARL9170_BW_20; | ||
1586 | case NL80211_CHAN_HT40MINUS: | ||
1587 | return CARL9170_BW_40_BELOW; | ||
1588 | case NL80211_CHAN_HT40PLUS: | ||
1589 | return CARL9170_BW_40_ABOVE; | ||
1590 | default: | ||
1591 | BUG(); | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1595 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | ||
1596 | enum nl80211_channel_type _bw, | ||
1597 | enum carl9170_rf_init_mode rfi) | ||
1598 | { | ||
1599 | const struct carl9170_phy_freq_params *freqpar; | ||
1600 | struct carl9170_rf_init_result rf_res; | ||
1601 | struct carl9170_rf_init rf; | ||
1602 | u32 cmd, tmp, offs = 0, new_ht = 0; | ||
1603 | int err; | ||
1604 | enum carl9170_bw bw; | ||
1605 | bool warm_reset; | ||
1606 | struct ieee80211_channel *old_channel = NULL; | ||
1607 | |||
1608 | bw = nl80211_to_carl(_bw); | ||
1609 | |||
1610 | if (conf_is_ht(&ar->hw->conf)) | ||
1611 | new_ht |= CARL9170FW_PHY_HT_ENABLE; | ||
1612 | |||
1613 | if (conf_is_ht40(&ar->hw->conf)) | ||
1614 | new_ht |= CARL9170FW_PHY_HT_DYN2040; | ||
1615 | |||
1616 | /* may be NULL at first setup */ | ||
1617 | if (ar->channel) { | ||
1618 | old_channel = ar->channel; | ||
1619 | warm_reset = (old_channel->band != channel->band) || | ||
1620 | (old_channel->center_freq == | ||
1621 | channel->center_freq) || | ||
1622 | (ar->ht_settings != new_ht); | ||
1623 | |||
1624 | ar->channel = NULL; | ||
1625 | } else { | ||
1626 | warm_reset = true; | ||
1627 | } | ||
1628 | |||
1629 | /* HW workaround */ | ||
1630 | if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && | ||
1631 | channel->center_freq <= 2417) | ||
1632 | warm_reset = true; | ||
1633 | |||
1634 | if (rfi != CARL9170_RFI_NONE || warm_reset) { | ||
1635 | u32 val; | ||
1636 | |||
1637 | if (rfi == CARL9170_RFI_COLD) | ||
1638 | val = AR9170_PWR_RESET_BB_COLD_RESET; | ||
1639 | else | ||
1640 | val = AR9170_PWR_RESET_BB_WARM_RESET; | ||
1641 | |||
1642 | /* warm/cold reset BB/ADDA */ | ||
1643 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val); | ||
1644 | if (err) | ||
1645 | return err; | ||
1646 | |||
1647 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0); | ||
1648 | if (err) | ||
1649 | return err; | ||
1650 | |||
1651 | err = carl9170_init_phy(ar, channel->band); | ||
1652 | if (err) | ||
1653 | return err; | ||
1654 | |||
1655 | err = carl9170_init_rf_banks_0_7(ar, | ||
1656 | channel->band == IEEE80211_BAND_5GHZ); | ||
1657 | if (err) | ||
1658 | return err; | ||
1659 | |||
1660 | cmd = CARL9170_CMD_RF_INIT; | ||
1661 | } else { | ||
1662 | cmd = CARL9170_CMD_FREQUENCY; | ||
1663 | } | ||
1664 | |||
1665 | err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL); | ||
1666 | if (err) | ||
1667 | return err; | ||
1668 | |||
1669 | err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE, | ||
1670 | 0x200); | ||
1671 | if (err) | ||
1672 | return err; | ||
1673 | |||
1674 | err = carl9170_init_rf_bank4_pwr(ar, | ||
1675 | channel->band == IEEE80211_BAND_5GHZ, | ||
1676 | channel->center_freq, bw); | ||
1677 | if (err) | ||
1678 | return err; | ||
1679 | |||
1680 | tmp = AR9170_PHY_TURBO_FC_SINGLE_HT_LTF1 | | ||
1681 | AR9170_PHY_TURBO_FC_HT_EN; | ||
1682 | |||
1683 | switch (bw) { | ||
1684 | case CARL9170_BW_20: | ||
1685 | break; | ||
1686 | case CARL9170_BW_40_BELOW: | ||
1687 | tmp |= AR9170_PHY_TURBO_FC_DYN2040_EN | | ||
1688 | AR9170_PHY_TURBO_FC_SHORT_GI_40; | ||
1689 | offs = 3; | ||
1690 | break; | ||
1691 | case CARL9170_BW_40_ABOVE: | ||
1692 | tmp |= AR9170_PHY_TURBO_FC_DYN2040_EN | | ||
1693 | AR9170_PHY_TURBO_FC_SHORT_GI_40 | | ||
1694 | AR9170_PHY_TURBO_FC_DYN2040_PRI_CH; | ||
1695 | offs = 1; | ||
1696 | break; | ||
1697 | default: | ||
1698 | BUG(); | ||
1699 | return -ENOSYS; | ||
1700 | } | ||
1701 | |||
1702 | if (ar->eeprom.tx_mask != 1) | ||
1703 | tmp |= AR9170_PHY_TURBO_FC_WALSH; | ||
1704 | |||
1705 | err = carl9170_write_reg(ar, AR9170_PHY_REG_TURBO, tmp); | ||
1706 | if (err) | ||
1707 | return err; | ||
1708 | |||
1709 | err = carl9170_set_freq_cal_data(ar, channel); | ||
1710 | if (err) | ||
1711 | return err; | ||
1712 | |||
1713 | err = carl9170_set_power_cal(ar, channel->center_freq, bw); | ||
1714 | if (err) | ||
1715 | return err; | ||
1716 | |||
1717 | freqpar = carl9170_get_hw_dyn_params(channel, bw); | ||
1718 | |||
1719 | rf.ht_settings = new_ht; | ||
1720 | if (conf_is_ht40(&ar->hw->conf)) | ||
1721 | SET_VAL(CARL9170FW_PHY_HT_EXT_CHAN_OFF, rf.ht_settings, offs); | ||
1722 | |||
1723 | rf.freq = cpu_to_le32(channel->center_freq * 1000); | ||
1724 | rf.delta_slope_coeff_exp = cpu_to_le32(freqpar->coeff_exp); | ||
1725 | rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man); | ||
1726 | rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi); | ||
1727 | rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi); | ||
1728 | |||
1729 | if (rfi != CARL9170_RFI_NONE) | ||
1730 | rf.finiteLoopCount = cpu_to_le32(2000); | ||
1731 | else | ||
1732 | rf.finiteLoopCount = cpu_to_le32(1000); | ||
1733 | |||
1734 | err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf, | ||
1735 | sizeof(rf_res), &rf_res); | ||
1736 | if (err) | ||
1737 | return err; | ||
1738 | |||
1739 | err = le32_to_cpu(rf_res.ret); | ||
1740 | if (err != 0) { | ||
1741 | ar->chan_fail++; | ||
1742 | ar->total_chan_fail++; | ||
1743 | |||
1744 | wiphy_err(ar->hw->wiphy, "channel change: %d -> %d " | ||
1745 | "failed (%d).\n", old_channel ? | ||
1746 | old_channel->center_freq : -1, channel->center_freq, | ||
1747 | err); | ||
1748 | |||
1749 | if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) { | ||
1750 | /* | ||
1751 | * We have tried very hard to change to _another_ | ||
1752 | * channel and we've failed to do so! | ||
1753 | * Chances are that the PHY/RF is no longer | ||
1754 | * operable (due to corruptions/fatal events/bugs?) | ||
1755 | * and we need to reset at a higher level. | ||
1756 | */ | ||
1757 | carl9170_restart(ar, CARL9170_RR_TOO_MANY_PHY_ERRORS); | ||
1758 | return 0; | ||
1759 | } | ||
1760 | |||
1761 | err = carl9170_set_channel(ar, channel, _bw, | ||
1762 | CARL9170_RFI_COLD); | ||
1763 | if (err) | ||
1764 | return err; | ||
1765 | } else { | ||
1766 | ar->chan_fail = 0; | ||
1767 | } | ||
1768 | |||
1769 | err = carl9170_get_noisefloor(ar); | ||
1770 | if (err) | ||
1771 | return err; | ||
1772 | |||
1773 | if (ar->heavy_clip) { | ||
1774 | err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE, | ||
1775 | 0x200 | ar->heavy_clip); | ||
1776 | if (err) { | ||
1777 | if (net_ratelimit()) { | ||
1778 | wiphy_err(ar->hw->wiphy, "failed to set " | ||
1779 | "heavy clip\n"); | ||
1780 | } | ||
1781 | |||
1782 | return err; | ||
1783 | } | ||
1784 | } | ||
1785 | |||
1786 | /* FIXME: PSM does not work in 5GHz Band */ | ||
1787 | if (channel->band == IEEE80211_BAND_5GHZ) | ||
1788 | ar->ps.off_override |= PS_OFF_5GHZ; | ||
1789 | else | ||
1790 | ar->ps.off_override &= ~PS_OFF_5GHZ; | ||
1791 | |||
1792 | ar->channel = channel; | ||
1793 | ar->ht_settings = new_ht; | ||
1794 | return 0; | ||
1795 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h new file mode 100644 index 000000000000..024fb42bc787 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/phy.h | |||
@@ -0,0 +1,564 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * PHY register map | ||
5 | * | ||
6 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
7 | * | ||
8 | * Permission to use, copy, modify, and/or distribute this software for any | ||
9 | * purpose with or without fee is hereby granted, provided that the above | ||
10 | * copyright notice and this permission notice appear in all copies. | ||
11 | * | ||
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | */ | ||
20 | |||
21 | #ifndef __CARL9170_SHARED_PHY_H | ||
22 | #define __CARL9170_SHARED_PHY_H | ||
23 | |||
24 | #define AR9170_PHY_REG_BASE (0x1bc000 + 0x9800) | ||
25 | #define AR9170_PHY_REG(_n) (AR9170_PHY_REG_BASE + \ | ||
26 | ((_n) << 2)) | ||
27 | |||
28 | #define AR9170_PHY_REG_TEST (AR9170_PHY_REG_BASE + 0x0000) | ||
29 | #define AR9170_PHY_TEST_AGC_CLR 0x10000000 | ||
30 | #define AR9170_PHY_TEST_RFSILENT_BB 0x00002000 | ||
31 | |||
32 | #define AR9170_PHY_REG_TURBO (AR9170_PHY_REG_BASE + 0x0004) | ||
33 | #define AR9170_PHY_TURBO_FC_TURBO_MODE 0x00000001 | ||
34 | #define AR9170_PHY_TURBO_FC_TURBO_SHORT 0x00000002 | ||
35 | #define AR9170_PHY_TURBO_FC_DYN2040_EN 0x00000004 | ||
36 | #define AR9170_PHY_TURBO_FC_DYN2040_PRI_ONLY 0x00000008 | ||
37 | #define AR9170_PHY_TURBO_FC_DYN2040_PRI_CH 0x00000010 | ||
38 | /* For 25 MHz channel spacing -- not used but supported by hw */ | ||
39 | #define AR9170_PHY_TURBO_FC_DYN2040_EXT_CH 0x00000020 | ||
40 | #define AR9170_PHY_TURBO_FC_HT_EN 0x00000040 | ||
41 | #define AR9170_PHY_TURBO_FC_SHORT_GI_40 0x00000080 | ||
42 | #define AR9170_PHY_TURBO_FC_WALSH 0x00000100 | ||
43 | #define AR9170_PHY_TURBO_FC_SINGLE_HT_LTF1 0x00000200 | ||
44 | #define AR9170_PHY_TURBO_FC_ENABLE_DAC_FIFO 0x00000800 | ||
45 | |||
46 | #define AR9170_PHY_REG_TEST2 (AR9170_PHY_REG_BASE + 0x0008) | ||
47 | |||
48 | #define AR9170_PHY_REG_TIMING2 (AR9170_PHY_REG_BASE + 0x0010) | ||
49 | #define AR9170_PHY_TIMING2_USE_FORCE 0x00001000 | ||
50 | #define AR9170_PHY_TIMING2_FORCE 0x00000fff | ||
51 | #define AR9170_PHY_TIMING2_FORCE_S 0 | ||
52 | |||
53 | #define AR9170_PHY_REG_TIMING3 (AR9170_PHY_REG_BASE + 0x0014) | ||
54 | #define AR9170_PHY_TIMING3_DSC_EXP 0x0001e000 | ||
55 | #define AR9170_PHY_TIMING3_DSC_EXP_S 13 | ||
56 | #define AR9170_PHY_TIMING3_DSC_MAN 0xfffe0000 | ||
57 | #define AR9170_PHY_TIMING3_DSC_MAN_S 17 | ||
58 | |||
59 | #define AR9170_PHY_REG_CHIP_ID (AR9170_PHY_REG_BASE + 0x0018) | ||
60 | #define AR9170_PHY_CHIP_ID_REV_0 0x80 | ||
61 | #define AR9170_PHY_CHIP_ID_REV_1 0x81 | ||
62 | #define AR9170_PHY_CHIP_ID_9160_REV_0 0xb0 | ||
63 | |||
64 | #define AR9170_PHY_REG_ACTIVE (AR9170_PHY_REG_BASE + 0x001c) | ||
65 | #define AR9170_PHY_ACTIVE_EN 0x00000001 | ||
66 | #define AR9170_PHY_ACTIVE_DIS 0x00000000 | ||
67 | |||
68 | #define AR9170_PHY_REG_RF_CTL2 (AR9170_PHY_REG_BASE + 0x0024) | ||
69 | #define AR9170_PHY_RF_CTL2_TX_END_DATA_START 0x000000ff | ||
70 | #define AR9170_PHY_RF_CTL2_TX_END_DATA_START_S 0 | ||
71 | #define AR9170_PHY_RF_CTL2_TX_END_PA_ON 0x0000ff00 | ||
72 | #define AR9170_PHY_RF_CTL2_TX_END_PA_ON_S 8 | ||
73 | |||
74 | #define AR9170_PHY_REG_RF_CTL3 (AR9170_PHY_REG_BASE + 0x0028) | ||
75 | #define AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON 0x00ff0000 | ||
76 | #define AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON_S 16 | ||
77 | |||
78 | #define AR9170_PHY_REG_ADC_CTL (AR9170_PHY_REG_BASE + 0x002c) | ||
79 | #define AR9170_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 | ||
80 | #define AR9170_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 | ||
81 | #define AR9170_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 | ||
82 | #define AR9170_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 | ||
83 | #define AR9170_PHY_ADC_CTL_OFF_PWDADC 0x00008000 | ||
84 | #define AR9170_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 | ||
85 | #define AR9170_PHY_ADC_CTL_ON_INBUFGAIN_S 16 | ||
86 | |||
87 | #define AR9170_PHY_REG_ADC_SERIAL_CTL (AR9170_PHY_REG_BASE + 0x0030) | ||
88 | #define AR9170_PHY_ADC_SCTL_SEL_INTERNAL_ADDAC 0x00000000 | ||
89 | #define AR9170_PHY_ADC_SCTL_SEL_EXTERNAL_RADIO 0x00000001 | ||
90 | |||
91 | #define AR9170_PHY_REG_RF_CTL4 (AR9170_PHY_REG_BASE + 0x0034) | ||
92 | #define AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF 0xff000000 | ||
93 | #define AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 | ||
94 | #define AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00ff0000 | ||
95 | #define AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 | ||
96 | #define AR9170_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000ff00 | ||
97 | #define AR9170_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 | ||
98 | #define AR9170_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000ff | ||
99 | #define AR9170_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 | ||
100 | |||
101 | #define AR9170_PHY_REG_TSTDAC_CONST (AR9170_PHY_REG_BASE + 0x003c) | ||
102 | |||
103 | #define AR9170_PHY_REG_SETTLING (AR9170_PHY_REG_BASE + 0x0044) | ||
104 | #define AR9170_PHY_SETTLING_SWITCH 0x00003f80 | ||
105 | #define AR9170_PHY_SETTLING_SWITCH_S 7 | ||
106 | |||
107 | #define AR9170_PHY_REG_RXGAIN (AR9170_PHY_REG_BASE + 0x0048) | ||
108 | #define AR9170_PHY_REG_RXGAIN_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2048) | ||
109 | #define AR9170_PHY_RXGAIN_TXRX_ATTEN 0x0003f000 | ||
110 | #define AR9170_PHY_RXGAIN_TXRX_ATTEN_S 12 | ||
111 | #define AR9170_PHY_RXGAIN_TXRX_RF_MAX 0x007c0000 | ||
112 | #define AR9170_PHY_RXGAIN_TXRX_RF_MAX_S 18 | ||
113 | |||
114 | #define AR9170_PHY_REG_DESIRED_SZ (AR9170_PHY_REG_BASE + 0x0050) | ||
115 | #define AR9170_PHY_DESIRED_SZ_ADC 0x000000ff | ||
116 | #define AR9170_PHY_DESIRED_SZ_ADC_S 0 | ||
117 | #define AR9170_PHY_DESIRED_SZ_PGA 0x0000ff00 | ||
118 | #define AR9170_PHY_DESIRED_SZ_PGA_S 8 | ||
119 | #define AR9170_PHY_DESIRED_SZ_TOT_DES 0x0ff00000 | ||
120 | #define AR9170_PHY_DESIRED_SZ_TOT_DES_S 20 | ||
121 | |||
122 | #define AR9170_PHY_REG_FIND_SIG (AR9170_PHY_REG_BASE + 0x0058) | ||
123 | #define AR9170_PHY_FIND_SIG_FIRSTEP 0x0003f000 | ||
124 | #define AR9170_PHY_FIND_SIG_FIRSTEP_S 12 | ||
125 | #define AR9170_PHY_FIND_SIG_FIRPWR 0x03fc0000 | ||
126 | #define AR9170_PHY_FIND_SIG_FIRPWR_S 18 | ||
127 | |||
128 | #define AR9170_PHY_REG_AGC_CTL1 (AR9170_PHY_REG_BASE + 0x005c) | ||
129 | #define AR9170_PHY_AGC_CTL1_COARSE_LOW 0x00007f80 | ||
130 | #define AR9170_PHY_AGC_CTL1_COARSE_LOW_S 7 | ||
131 | #define AR9170_PHY_AGC_CTL1_COARSE_HIGH 0x003f8000 | ||
132 | #define AR9170_PHY_AGC_CTL1_COARSE_HIGH_S 15 | ||
133 | |||
134 | #define AR9170_PHY_REG_AGC_CONTROL (AR9170_PHY_REG_BASE + 0x0060) | ||
135 | #define AR9170_PHY_AGC_CONTROL_CAL 0x00000001 | ||
136 | #define AR9170_PHY_AGC_CONTROL_NF 0x00000002 | ||
137 | #define AR9170_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 | ||
138 | #define AR9170_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 | ||
139 | #define AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 | ||
140 | |||
141 | #define AR9170_PHY_REG_CCA (AR9170_PHY_REG_BASE + 0x0064) | ||
142 | #define AR9170_PHY_CCA_MIN_PWR 0x0ff80000 | ||
143 | #define AR9170_PHY_CCA_MIN_PWR_S 19 | ||
144 | #define AR9170_PHY_CCA_THRESH62 0x0007f000 | ||
145 | #define AR9170_PHY_CCA_THRESH62_S 12 | ||
146 | |||
147 | #define AR9170_PHY_REG_SFCORR (AR9170_PHY_REG_BASE + 0x0068) | ||
148 | #define AR9170_PHY_SFCORR_M2COUNT_THR 0x0000001f | ||
149 | #define AR9170_PHY_SFCORR_M2COUNT_THR_S 0 | ||
150 | #define AR9170_PHY_SFCORR_M1_THRESH 0x00fe0000 | ||
151 | #define AR9170_PHY_SFCORR_M1_THRESH_S 17 | ||
152 | #define AR9170_PHY_SFCORR_M2_THRESH 0x7f000000 | ||
153 | #define AR9170_PHY_SFCORR_M2_THRESH_S 24 | ||
154 | |||
155 | #define AR9170_PHY_REG_SFCORR_LOW (AR9170_PHY_REG_BASE + 0x006c) | ||
156 | #define AR9170_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 | ||
157 | #define AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003f00 | ||
158 | #define AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 | ||
159 | #define AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001fc000 | ||
160 | #define AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 | ||
161 | #define AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0fe00000 | ||
162 | #define AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 | ||
163 | |||
164 | #define AR9170_PHY_REG_SLEEP_CTR_CONTROL (AR9170_PHY_REG_BASE + 0x0070) | ||
165 | #define AR9170_PHY_REG_SLEEP_CTR_LIMIT (AR9170_PHY_REG_BASE + 0x0074) | ||
166 | #define AR9170_PHY_REG_SLEEP_SCAL (AR9170_PHY_REG_BASE + 0x0078) | ||
167 | |||
168 | #define AR9170_PHY_REG_PLL_CTL (AR9170_PHY_REG_BASE + 0x007c) | ||
169 | #define AR9170_PHY_PLL_CTL_40 0xaa | ||
170 | #define AR9170_PHY_PLL_CTL_40_5413 0x04 | ||
171 | #define AR9170_PHY_PLL_CTL_44 0xab | ||
172 | #define AR9170_PHY_PLL_CTL_44_2133 0xeb | ||
173 | #define AR9170_PHY_PLL_CTL_40_2133 0xea | ||
174 | |||
175 | #define AR9170_PHY_REG_BIN_MASK_1 (AR9170_PHY_REG_BASE + 0x0100) | ||
176 | #define AR9170_PHY_REG_BIN_MASK_2 (AR9170_PHY_REG_BASE + 0x0104) | ||
177 | #define AR9170_PHY_REG_BIN_MASK_3 (AR9170_PHY_REG_BASE + 0x0108) | ||
178 | #define AR9170_PHY_REG_MASK_CTL (AR9170_PHY_REG_BASE + 0x010c) | ||
179 | |||
180 | /* analogue power on time (100ns) */ | ||
181 | #define AR9170_PHY_REG_RX_DELAY (AR9170_PHY_REG_BASE + 0x0114) | ||
182 | #define AR9170_PHY_REG_SEARCH_START_DELAY (AR9170_PHY_REG_BASE + 0x0118) | ||
183 | #define AR9170_PHY_RX_DELAY_DELAY 0x00003fff | ||
184 | |||
185 | #define AR9170_PHY_REG_TIMING_CTRL4(_i) (AR9170_PHY_REG_BASE + \ | ||
186 | (0x0120 + ((_i) << 12))) | ||
187 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01f | ||
188 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 | ||
189 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7e0 | ||
190 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 | ||
191 | #define AR9170_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 | ||
192 | #define AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xf000 | ||
193 | #define AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 | ||
194 | #define AR9170_PHY_TIMING_CTRL4_DO_IQCAL 0x10000 | ||
195 | #define AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 | ||
196 | #define AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 | ||
197 | #define AR9170_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 | ||
198 | #define AR9170_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 | ||
199 | |||
200 | #define AR9170_PHY_REG_TIMING5 (AR9170_PHY_REG_BASE + 0x0124) | ||
201 | #define AR9170_PHY_TIMING5_CYCPWR_THR1 0x000000fe | ||
202 | #define AR9170_PHY_TIMING5_CYCPWR_THR1_S 1 | ||
203 | |||
204 | #define AR9170_PHY_REG_POWER_TX_RATE1 (AR9170_PHY_REG_BASE + 0x0134) | ||
205 | #define AR9170_PHY_REG_POWER_TX_RATE2 (AR9170_PHY_REG_BASE + 0x0138) | ||
206 | #define AR9170_PHY_REG_POWER_TX_RATE_MAX (AR9170_PHY_REG_BASE + 0x013c) | ||
207 | #define AR9170_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 | ||
208 | |||
209 | #define AR9170_PHY_REG_FRAME_CTL (AR9170_PHY_REG_BASE + 0x0144) | ||
210 | #define AR9170_PHY_FRAME_CTL_TX_CLIP 0x00000038 | ||
211 | #define AR9170_PHY_FRAME_CTL_TX_CLIP_S 3 | ||
212 | |||
213 | #define AR9170_PHY_REG_SPUR_REG (AR9170_PHY_REG_BASE + 0x014c) | ||
214 | #define AR9170_PHY_SPUR_REG_MASK_RATE_CNTL (0xff << 18) | ||
215 | #define AR9170_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 | ||
216 | #define AR9170_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 | ||
217 | #define AR9170_PHY_SPUR_REG_MASK_RATE_SELECT (0xff << 9) | ||
218 | #define AR9170_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 | ||
219 | #define AR9170_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 | ||
220 | #define AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7f | ||
221 | #define AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 | ||
222 | |||
223 | #define AR9170_PHY_REG_RADAR_EXT (AR9170_PHY_REG_BASE + 0x0140) | ||
224 | #define AR9170_PHY_RADAR_EXT_ENA 0x00004000 | ||
225 | |||
226 | #define AR9170_PHY_REG_RADAR_0 (AR9170_PHY_REG_BASE + 0x0154) | ||
227 | #define AR9170_PHY_RADAR_0_ENA 0x00000001 | ||
228 | #define AR9170_PHY_RADAR_0_FFT_ENA 0x80000000 | ||
229 | /* inband pulse threshold */ | ||
230 | #define AR9170_PHY_RADAR_0_INBAND 0x0000003e | ||
231 | #define AR9170_PHY_RADAR_0_INBAND_S 1 | ||
232 | /* pulse RSSI threshold */ | ||
233 | #define AR9170_PHY_RADAR_0_PRSSI 0x00000fc0 | ||
234 | #define AR9170_PHY_RADAR_0_PRSSI_S 6 | ||
235 | /* pulse height threshold */ | ||
236 | #define AR9170_PHY_RADAR_0_HEIGHT 0x0003f000 | ||
237 | #define AR9170_PHY_RADAR_0_HEIGHT_S 12 | ||
238 | /* radar RSSI threshold */ | ||
239 | #define AR9170_PHY_RADAR_0_RRSSI 0x00fc0000 | ||
240 | #define AR9170_PHY_RADAR_0_RRSSI_S 18 | ||
241 | /* radar firepower threshold */ | ||
242 | #define AR9170_PHY_RADAR_0_FIRPWR 0x7f000000 | ||
243 | #define AR9170_PHY_RADAR_0_FIRPWR_S 24 | ||
244 | |||
245 | #define AR9170_PHY_REG_RADAR_1 (AR9170_PHY_REG_BASE + 0x0158) | ||
246 | #define AR9170_PHY_RADAR_1_RELPWR_ENA 0x00800000 | ||
247 | #define AR9170_PHY_RADAR_1_USE_FIR128 0x00400000 | ||
248 | #define AR9170_PHY_RADAR_1_RELPWR_THRESH 0x003f0000 | ||
249 | #define AR9170_PHY_RADAR_1_RELPWR_THRESH_S 16 | ||
250 | #define AR9170_PHY_RADAR_1_BLOCK_CHECK 0x00008000 | ||
251 | #define AR9170_PHY_RADAR_1_MAX_RRSSI 0x00004000 | ||
252 | #define AR9170_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 | ||
253 | #define AR9170_PHY_RADAR_1_RELSTEP_THRESH 0x00001f00 | ||
254 | #define AR9170_PHY_RADAR_1_RELSTEP_THRESH_S 8 | ||
255 | #define AR9170_PHY_RADAR_1_MAXLEN 0x000000ff | ||
256 | #define AR9170_PHY_RADAR_1_MAXLEN_S 0 | ||
257 | |||
258 | #define AR9170_PHY_REG_SWITCH_CHAIN_0 (AR9170_PHY_REG_BASE + 0x0160) | ||
259 | #define AR9170_PHY_REG_SWITCH_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2160) | ||
260 | |||
261 | #define AR9170_PHY_REG_SWITCH_COM (AR9170_PHY_REG_BASE + 0x0164) | ||
262 | |||
263 | #define AR9170_PHY_REG_CCA_THRESHOLD (AR9170_PHY_REG_BASE + 0x0168) | ||
264 | |||
265 | #define AR9170_PHY_REG_SIGMA_DELTA (AR9170_PHY_REG_BASE + 0x016c) | ||
266 | #define AR9170_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 | ||
267 | #define AR9170_PHY_SIGMA_DELTA_ADC_SEL_S 0 | ||
268 | #define AR9170_PHY_SIGMA_DELTA_FILT2 0x000000f8 | ||
269 | #define AR9170_PHY_SIGMA_DELTA_FILT2_S 3 | ||
270 | #define AR9170_PHY_SIGMA_DELTA_FILT1 0x00001f00 | ||
271 | #define AR9170_PHY_SIGMA_DELTA_FILT1_S 8 | ||
272 | #define AR9170_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000 | ||
273 | #define AR9170_PHY_SIGMA_DELTA_ADC_CLIP_S 13 | ||
274 | |||
275 | #define AR9170_PHY_REG_RESTART (AR9170_PHY_REG_BASE + 0x0170) | ||
276 | #define AR9170_PHY_RESTART_DIV_GC 0x001c0000 | ||
277 | #define AR9170_PHY_RESTART_DIV_GC_S 18 | ||
278 | |||
279 | #define AR9170_PHY_REG_RFBUS_REQ (AR9170_PHY_REG_BASE + 0x017c) | ||
280 | #define AR9170_PHY_RFBUS_REQ_EN 0x00000001 | ||
281 | |||
282 | #define AR9170_PHY_REG_TIMING7 (AR9170_PHY_REG_BASE + 0x0180) | ||
283 | #define AR9170_PHY_REG_TIMING8 (AR9170_PHY_REG_BASE + 0x0184) | ||
284 | #define AR9170_PHY_TIMING8_PILOT_MASK_2 0x000fffff | ||
285 | #define AR9170_PHY_TIMING8_PILOT_MASK_2_S 0 | ||
286 | |||
287 | #define AR9170_PHY_REG_BIN_MASK2_1 (AR9170_PHY_REG_BASE + 0x0188) | ||
288 | #define AR9170_PHY_REG_BIN_MASK2_2 (AR9170_PHY_REG_BASE + 0x018c) | ||
289 | #define AR9170_PHY_REG_BIN_MASK2_3 (AR9170_PHY_REG_BASE + 0x0190) | ||
290 | #define AR9170_PHY_REG_BIN_MASK2_4 (AR9170_PHY_REG_BASE + 0x0194) | ||
291 | #define AR9170_PHY_BIN_MASK2_4_MASK_4 0x00003fff | ||
292 | #define AR9170_PHY_BIN_MASK2_4_MASK_4_S 0 | ||
293 | |||
294 | #define AR9170_PHY_REG_TIMING9 (AR9170_PHY_REG_BASE + 0x0198) | ||
295 | #define AR9170_PHY_REG_TIMING10 (AR9170_PHY_REG_BASE + 0x019c) | ||
296 | #define AR9170_PHY_TIMING10_PILOT_MASK_2 0x000fffff | ||
297 | #define AR9170_PHY_TIMING10_PILOT_MASK_2_S 0 | ||
298 | |||
299 | #define AR9170_PHY_REG_TIMING11 (AR9170_PHY_REG_BASE + 0x01a0) | ||
300 | #define AR9170_PHY_TIMING11_SPUR_DELTA_PHASE 0x000fffff | ||
301 | #define AR9170_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 | ||
302 | #define AR9170_PHY_TIMING11_SPUR_FREQ_SD 0x3ff00000 | ||
303 | #define AR9170_PHY_TIMING11_SPUR_FREQ_SD_S 20 | ||
304 | #define AR9170_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 | ||
305 | #define AR9170_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 | ||
306 | |||
307 | #define AR9170_PHY_REG_RX_CHAINMASK (AR9170_PHY_REG_BASE + 0x01a4) | ||
308 | #define AR9170_PHY_REG_NEW_ADC_DC_GAIN_CORR(_i) (AR9170_PHY_REG_BASE + \ | ||
309 | 0x01b4 + ((_i) << 12)) | ||
310 | #define AR9170_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 | ||
311 | #define AR9170_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 | ||
312 | |||
313 | #define AR9170_PHY_REG_MULTICHAIN_GAIN_CTL (AR9170_PHY_REG_BASE + 0x01ac) | ||
314 | #define AR9170_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 | ||
315 | #define AR9170_PHY_9285_ANT_DIV_CTL 0x01000000 | ||
316 | #define AR9170_PHY_9285_ANT_DIV_CTL_S 24 | ||
317 | #define AR9170_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000 | ||
318 | #define AR9170_PHY_9285_ANT_DIV_ALT_LNACONF_S 25 | ||
319 | #define AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000 | ||
320 | #define AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27 | ||
321 | #define AR9170_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000 | ||
322 | #define AR9170_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 | ||
323 | #define AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 | ||
324 | #define AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 | ||
325 | #define AR9170_PHY_9285_ANT_DIV_LNA1 2 | ||
326 | #define AR9170_PHY_9285_ANT_DIV_LNA2 1 | ||
327 | #define AR9170_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3 | ||
328 | #define AR9170_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 | ||
329 | #define AR9170_PHY_9285_ANT_DIV_GAINTB_0 0 | ||
330 | #define AR9170_PHY_9285_ANT_DIV_GAINTB_1 1 | ||
331 | |||
332 | #define AR9170_PHY_REG_EXT_CCA0 (AR9170_PHY_REG_BASE + 0x01b8) | ||
333 | #define AR9170_PHY_REG_EXT_CCA0_THRESH62 0x000000ff | ||
334 | #define AR9170_PHY_REG_EXT_CCA0_THRESH62_S 0 | ||
335 | |||
336 | #define AR9170_PHY_REG_EXT_CCA (AR9170_PHY_REG_BASE + 0x01bc) | ||
337 | #define AR9170_PHY_EXT_CCA_CYCPWR_THR1 0x0000fe00 | ||
338 | #define AR9170_PHY_EXT_CCA_CYCPWR_THR1_S 9 | ||
339 | #define AR9170_PHY_EXT_CCA_THRESH62 0x007f0000 | ||
340 | #define AR9170_PHY_EXT_CCA_THRESH62_S 16 | ||
341 | #define AR9170_PHY_EXT_CCA_MIN_PWR 0xff800000 | ||
342 | #define AR9170_PHY_EXT_CCA_MIN_PWR_S 23 | ||
343 | |||
344 | #define AR9170_PHY_REG_SFCORR_EXT (AR9170_PHY_REG_BASE + 0x01c0) | ||
345 | #define AR9170_PHY_SFCORR_EXT_M1_THRESH 0x0000007f | ||
346 | #define AR9170_PHY_SFCORR_EXT_M1_THRESH_S 0 | ||
347 | #define AR9170_PHY_SFCORR_EXT_M2_THRESH 0x00003f80 | ||
348 | #define AR9170_PHY_SFCORR_EXT_M2_THRESH_S 7 | ||
349 | #define AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001fc000 | ||
350 | #define AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 | ||
351 | #define AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0fe00000 | ||
352 | #define AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 | ||
353 | #define AR9170_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 | ||
354 | |||
355 | #define AR9170_PHY_REG_HALFGI (AR9170_PHY_REG_BASE + 0x01d0) | ||
356 | #define AR9170_PHY_HALFGI_DSC_MAN 0x0007fff0 | ||
357 | #define AR9170_PHY_HALFGI_DSC_MAN_S 4 | ||
358 | #define AR9170_PHY_HALFGI_DSC_EXP 0x0000000f | ||
359 | #define AR9170_PHY_HALFGI_DSC_EXP_S 0 | ||
360 | |||
361 | #define AR9170_PHY_REG_CHANNEL_MASK_01_30 (AR9170_PHY_REG_BASE + 0x01d4) | ||
362 | #define AR9170_PHY_REG_CHANNEL_MASK_31_60 (AR9170_PHY_REG_BASE + 0x01d8) | ||
363 | |||
364 | #define AR9170_PHY_REG_CHAN_INFO_MEMORY (AR9170_PHY_REG_BASE + 0x01dc) | ||
365 | #define AR9170_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 | ||
366 | |||
367 | #define AR9170_PHY_REG_HEAVY_CLIP_ENABLE (AR9170_PHY_REG_BASE + 0x01e0) | ||
368 | #define AR9170_PHY_REG_HEAVY_CLIP_FACTOR_RIFS (AR9170_PHY_REG_BASE + 0x01ec) | ||
369 | #define AR9170_PHY_RIFS_INIT_DELAY 0x03ff0000 | ||
370 | |||
371 | #define AR9170_PHY_REG_CALMODE (AR9170_PHY_REG_BASE + 0x01f0) | ||
372 | #define AR9170_PHY_CALMODE_IQ 0x00000000 | ||
373 | #define AR9170_PHY_CALMODE_ADC_GAIN 0x00000001 | ||
374 | #define AR9170_PHY_CALMODE_ADC_DC_PER 0x00000002 | ||
375 | #define AR9170_PHY_CALMODE_ADC_DC_INIT 0x00000003 | ||
376 | |||
377 | #define AR9170_PHY_REG_REFCLKDLY (AR9170_PHY_REG_BASE + 0x01f4) | ||
378 | #define AR9170_PHY_REG_REFCLKPD (AR9170_PHY_REG_BASE + 0x01f8) | ||
379 | |||
380 | |||
381 | #define AR9170_PHY_REG_CAL_MEAS_0(_i) (AR9170_PHY_REG_BASE + \ | ||
382 | 0x0410 + ((_i) << 12)) | ||
383 | #define AR9170_PHY_REG_CAL_MEAS_1(_i) (AR9170_PHY_REG_BASE + \ | ||
384 | 0x0414 \ + ((_i) << 12)) | ||
385 | #define AR9170_PHY_REG_CAL_MEAS_2(_i) (AR9170_PHY_REG_BASE + \ | ||
386 | 0x0418 + ((_i) << 12)) | ||
387 | #define AR9170_PHY_REG_CAL_MEAS_3(_i) (AR9170_PHY_REG_BASE + \ | ||
388 | 0x041c + ((_i) << 12)) | ||
389 | |||
390 | #define AR9170_PHY_REG_CURRENT_RSSI (AR9170_PHY_REG_BASE + 0x041c) | ||
391 | |||
392 | #define AR9170_PHY_REG_RFBUS_GRANT (AR9170_PHY_REG_BASE + 0x0420) | ||
393 | #define AR9170_PHY_RFBUS_GRANT_EN 0x00000001 | ||
394 | |||
395 | #define AR9170_PHY_REG_CHAN_INFO_GAIN_DIFF (AR9170_PHY_REG_BASE + 0x04f4) | ||
396 | #define AR9170_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 | ||
397 | |||
398 | #define AR9170_PHY_REG_CHAN_INFO_GAIN (AR9170_PHY_REG_BASE + 0x04fc) | ||
399 | |||
400 | #define AR9170_PHY_REG_MODE (AR9170_PHY_REG_BASE + 0x0a00) | ||
401 | #define AR9170_PHY_MODE_ASYNCFIFO 0x80 | ||
402 | #define AR9170_PHY_MODE_AR2133 0x08 | ||
403 | #define AR9170_PHY_MODE_AR5111 0x00 | ||
404 | #define AR9170_PHY_MODE_AR5112 0x08 | ||
405 | #define AR9170_PHY_MODE_DYNAMIC 0x04 | ||
406 | #define AR9170_PHY_MODE_RF2GHZ 0x02 | ||
407 | #define AR9170_PHY_MODE_RF5GHZ 0x00 | ||
408 | #define AR9170_PHY_MODE_CCK 0x01 | ||
409 | #define AR9170_PHY_MODE_OFDM 0x00 | ||
410 | #define AR9170_PHY_MODE_DYN_CCK_DISABLE 0x100 | ||
411 | |||
412 | #define AR9170_PHY_REG_CCK_TX_CTRL (AR9170_PHY_REG_BASE + 0x0a04) | ||
413 | #define AR9170_PHY_CCK_TX_CTRL_JAPAN 0x00000010 | ||
414 | #define AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000c | ||
415 | #define AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 | ||
416 | |||
417 | #define AR9170_PHY_REG_CCK_DETECT (AR9170_PHY_REG_BASE + 0x0a08) | ||
418 | #define AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003f | ||
419 | #define AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 | ||
420 | /* [12:6] settling time for antenna switch */ | ||
421 | #define AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001fc0 | ||
422 | #define AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 | ||
423 | #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 | ||
424 | #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 | ||
425 | |||
426 | #define AR9170_PHY_REG_GAIN_2GHZ (AR9170_PHY_REG_BASE + 0x0a0c) | ||
427 | #define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c) | ||
428 | #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00fc0000 | ||
429 | #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 | ||
430 | #define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003c00 | ||
431 | #define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 | ||
432 | #define AR9170_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001f | ||
433 | #define AR9170_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 | ||
434 | #define AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003e0000 | ||
435 | #define AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17 | ||
436 | #define AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001f000 | ||
437 | #define AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12 | ||
438 | #define AR9170_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000fc0 | ||
439 | #define AR9170_PHY_GAIN_2GHZ_XATTEN2_DB_S 6 | ||
440 | #define AR9170_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003f | ||
441 | #define AR9170_PHY_GAIN_2GHZ_XATTEN1_DB_S 0 | ||
442 | |||
443 | #define AR9170_PHY_REG_CCK_RXCTRL4 (AR9170_PHY_REG_BASE + 0x0a1c) | ||
444 | #define AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01f80000 | ||
445 | #define AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 | ||
446 | |||
447 | #define AR9170_PHY_REG_DAG_CTRLCCK (AR9170_PHY_REG_BASE + 0x0a28) | ||
448 | #define AR9170_REG_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 | ||
449 | #define AR9170_REG_DAG_CTRLCCK_RSSI_THR 0x0001fc00 | ||
450 | #define AR9170_REG_DAG_CTRLCCK_RSSI_THR_S 10 | ||
451 | |||
452 | #define AR9170_PHY_REG_FORCE_CLKEN_CCK (AR9170_PHY_REG_BASE + 0x0a2c) | ||
453 | #define AR9170_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 | ||
454 | |||
455 | #define AR9170_PHY_REG_POWER_TX_RATE3 (AR9170_PHY_REG_BASE + 0x0a34) | ||
456 | #define AR9170_PHY_REG_POWER_TX_RATE4 (AR9170_PHY_REG_BASE + 0x0a38) | ||
457 | |||
458 | #define AR9170_PHY_REG_SCRM_SEQ_XR (AR9170_PHY_REG_BASE + 0x0a3c) | ||
459 | #define AR9170_PHY_REG_HEADER_DETECT_XR (AR9170_PHY_REG_BASE + 0x0a40) | ||
460 | #define AR9170_PHY_REG_CHIRP_DETECTED_XR (AR9170_PHY_REG_BASE + 0x0a44) | ||
461 | #define AR9170_PHY_REG_BLUETOOTH (AR9170_PHY_REG_BASE + 0x0a54) | ||
462 | |||
463 | #define AR9170_PHY_REG_TPCRG1 (AR9170_PHY_REG_BASE + 0x0a58) | ||
464 | #define AR9170_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 | ||
465 | #define AR9170_PHY_TPCRG1_NUM_PD_GAIN_S 14 | ||
466 | #define AR9170_PHY_TPCRG1_PD_GAIN_1 0x00030000 | ||
467 | #define AR9170_PHY_TPCRG1_PD_GAIN_1_S 16 | ||
468 | #define AR9170_PHY_TPCRG1_PD_GAIN_2 0x000c0000 | ||
469 | #define AR9170_PHY_TPCRG1_PD_GAIN_2_S 18 | ||
470 | #define AR9170_PHY_TPCRG1_PD_GAIN_3 0x00300000 | ||
471 | #define AR9170_PHY_TPCRG1_PD_GAIN_3_S 20 | ||
472 | #define AR9170_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 | ||
473 | #define AR9170_PHY_TPCRG1_PD_CAL_ENABLE_S 22 | ||
474 | |||
475 | #define AR9170_PHY_REG_TX_PWRCTRL4 (AR9170_PHY_REG_BASE + 0x0a64) | ||
476 | #define AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 | ||
477 | #define AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 | ||
478 | #define AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001fe | ||
479 | #define AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 | ||
480 | |||
481 | #define AR9170_PHY_REG_ANALOG_SWAP (AR9170_PHY_REG_BASE + 0x0a68) | ||
482 | #define AR9170_PHY_ANALOG_SWAP_AB 0x0001 | ||
483 | #define AR9170_PHY_ANALOG_SWAP_ALT_CHAIN 0x00000040 | ||
484 | |||
485 | #define AR9170_PHY_REG_TPCRG5 (AR9170_PHY_REG_BASE + 0x0a6c) | ||
486 | #define AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000f | ||
487 | #define AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 | ||
488 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003f0 | ||
489 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 | ||
490 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000fc00 | ||
491 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 | ||
492 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003f0000 | ||
493 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 | ||
494 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0fc00000 | ||
495 | #define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 | ||
496 | |||
497 | #define AR9170_PHY_REG_TX_PWRCTRL6_0 (AR9170_PHY_REG_BASE + 0x0a70) | ||
498 | #define AR9170_PHY_REG_TX_PWRCTRL6_1 (AR9170_PHY_REG_BASE + 0x1a70) | ||
499 | #define AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 | ||
500 | #define AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 | ||
501 | |||
502 | #define AR9170_PHY_REG_TX_PWRCTRL7 (AR9170_PHY_REG_BASE + 0x0a74) | ||
503 | #define AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01f80000 | ||
504 | #define AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 | ||
505 | |||
506 | #define AR9170_PHY_REG_TX_PWRCTRL9 (AR9170_PHY_REG_BASE + 0x0a7c) | ||
507 | #define AR9170_PHY_TX_DESIRED_SCALE_CCK 0x00007c00 | ||
508 | #define AR9170_PHY_TX_DESIRED_SCALE_CCK_S 10 | ||
509 | #define AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 | ||
510 | #define AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 | ||
511 | |||
512 | #define AR9170_PHY_REG_TX_GAIN_TBL1 (AR9170_PHY_REG_BASE + 0x0b00) | ||
513 | #define AR9170_PHY_TX_GAIN 0x0007f000 | ||
514 | #define AR9170_PHY_TX_GAIN_S 12 | ||
515 | |||
516 | /* Carrier leak calibration control, do it after AGC calibration */ | ||
517 | #define AR9170_PHY_REG_CL_CAL_CTL (AR9170_PHY_REG_BASE + 0x0b58) | ||
518 | #define AR9170_PHY_CL_CAL_ENABLE 0x00000002 | ||
519 | #define AR9170_PHY_CL_CAL_PARALLEL_CAL_ENABLE 0x00000001 | ||
520 | |||
521 | #define AR9170_PHY_REG_POWER_TX_RATE5 (AR9170_PHY_REG_BASE + 0x0b8c) | ||
522 | #define AR9170_PHY_REG_POWER_TX_RATE6 (AR9170_PHY_REG_BASE + 0x0b90) | ||
523 | |||
524 | #define AR9170_PHY_REG_CH0_TX_PWRCTRL11 (AR9170_PHY_REG_BASE + 0x0b98) | ||
525 | #define AR9170_PHY_REG_CH1_TX_PWRCTRL11 (AR9170_PHY_REG_BASE + 0x1b98) | ||
526 | #define AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP 0x0000fc00 | ||
527 | #define AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP_S 10 | ||
528 | |||
529 | #define AR9170_PHY_REG_CAL_CHAINMASK (AR9170_PHY_REG_BASE + 0x0b9c) | ||
530 | #define AR9170_PHY_REG_VIT_MASK2_M_46_61 (AR9170_PHY_REG_BASE + 0x0ba0) | ||
531 | #define AR9170_PHY_REG_MASK2_M_31_45 (AR9170_PHY_REG_BASE + 0x0ba4) | ||
532 | #define AR9170_PHY_REG_MASK2_M_16_30 (AR9170_PHY_REG_BASE + 0x0ba8) | ||
533 | #define AR9170_PHY_REG_MASK2_M_00_15 (AR9170_PHY_REG_BASE + 0x0bac) | ||
534 | #define AR9170_PHY_REG_PILOT_MASK_01_30 (AR9170_PHY_REG_BASE + 0x0bb0) | ||
535 | #define AR9170_PHY_REG_PILOT_MASK_31_60 (AR9170_PHY_REG_BASE + 0x0bb4) | ||
536 | #define AR9170_PHY_REG_MASK2_P_15_01 (AR9170_PHY_REG_BASE + 0x0bb8) | ||
537 | #define AR9170_PHY_REG_MASK2_P_30_16 (AR9170_PHY_REG_BASE + 0x0bbc) | ||
538 | #define AR9170_PHY_REG_MASK2_P_45_31 (AR9170_PHY_REG_BASE + 0x0bc0) | ||
539 | #define AR9170_PHY_REG_MASK2_P_61_45 (AR9170_PHY_REG_BASE + 0x0bc4) | ||
540 | #define AR9170_PHY_REG_POWER_TX_SUB (AR9170_PHY_REG_BASE + 0x0bc8) | ||
541 | #define AR9170_PHY_REG_POWER_TX_RATE7 (AR9170_PHY_REG_BASE + 0x0bcc) | ||
542 | #define AR9170_PHY_REG_POWER_TX_RATE8 (AR9170_PHY_REG_BASE + 0x0bd0) | ||
543 | #define AR9170_PHY_REG_POWER_TX_RATE9 (AR9170_PHY_REG_BASE + 0x0bd4) | ||
544 | #define AR9170_PHY_REG_XPA_CFG (AR9170_PHY_REG_BASE + 0x0bd8) | ||
545 | #define AR9170_PHY_FORCE_XPA_CFG 0x000000001 | ||
546 | #define AR9170_PHY_FORCE_XPA_CFG_S 0 | ||
547 | |||
548 | #define AR9170_PHY_REG_CH1_CCA (AR9170_PHY_REG_BASE + 0x1064) | ||
549 | #define AR9170_PHY_CH1_CCA_MIN_PWR 0x0ff80000 | ||
550 | #define AR9170_PHY_CH1_CCA_MIN_PWR_S 19 | ||
551 | |||
552 | #define AR9170_PHY_REG_CH2_CCA (AR9170_PHY_REG_BASE + 0x2064) | ||
553 | #define AR9170_PHY_CH2_CCA_MIN_PWR 0x0ff80000 | ||
554 | #define AR9170_PHY_CH2_CCA_MIN_PWR_S 19 | ||
555 | |||
556 | #define AR9170_PHY_REG_CH1_EXT_CCA (AR9170_PHY_REG_BASE + 0x11bc) | ||
557 | #define AR9170_PHY_CH1_EXT_CCA_MIN_PWR 0xff800000 | ||
558 | #define AR9170_PHY_CH1_EXT_CCA_MIN_PWR_S 23 | ||
559 | |||
560 | #define AR9170_PHY_REG_CH2_EXT_CCA (AR9170_PHY_REG_BASE + 0x21bc) | ||
561 | #define AR9170_PHY_CH2_EXT_CCA_MIN_PWR 0xff800000 | ||
562 | #define AR9170_PHY_CH2_EXT_CCA_MIN_PWR_S 23 | ||
563 | |||
564 | #endif /* __CARL9170_SHARED_PHY_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c new file mode 100644 index 000000000000..ec21ea9fd8d5 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/rx.c | |||
@@ -0,0 +1,938 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * 802.11 & command trap routines | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/module.h> | ||
43 | #include <linux/etherdevice.h> | ||
44 | #include <linux/crc32.h> | ||
45 | #include <net/mac80211.h> | ||
46 | #include "carl9170.h" | ||
47 | #include "hw.h" | ||
48 | #include "cmd.h" | ||
49 | |||
50 | static void carl9170_dbg_message(struct ar9170 *ar, const char *buf, u32 len) | ||
51 | { | ||
52 | bool restart = false; | ||
53 | enum carl9170_restart_reasons reason = CARL9170_RR_NO_REASON; | ||
54 | |||
55 | if (len > 3) { | ||
56 | if (memcmp(buf, CARL9170_ERR_MAGIC, 3) == 0) { | ||
57 | ar->fw.err_counter++; | ||
58 | if (ar->fw.err_counter > 3) { | ||
59 | restart = true; | ||
60 | reason = CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | if (memcmp(buf, CARL9170_BUG_MAGIC, 3) == 0) { | ||
65 | ar->fw.bug_counter++; | ||
66 | restart = true; | ||
67 | reason = CARL9170_RR_FATAL_FIRMWARE_ERROR; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | wiphy_info(ar->hw->wiphy, "FW: %.*s\n", len, buf); | ||
72 | |||
73 | if (restart) | ||
74 | carl9170_restart(ar, reason); | ||
75 | } | ||
76 | |||
77 | static void carl9170_handle_ps(struct ar9170 *ar, struct carl9170_rsp *rsp) | ||
78 | { | ||
79 | u32 ps; | ||
80 | bool new_ps; | ||
81 | |||
82 | ps = le32_to_cpu(rsp->psm.state); | ||
83 | |||
84 | new_ps = (ps & CARL9170_PSM_COUNTER) != CARL9170_PSM_WAKE; | ||
85 | if (ar->ps.state != new_ps) { | ||
86 | if (!new_ps) { | ||
87 | ar->ps.sleep_ms = jiffies_to_msecs(jiffies - | ||
88 | ar->ps.last_action); | ||
89 | } | ||
90 | |||
91 | ar->ps.last_action = jiffies; | ||
92 | |||
93 | ar->ps.state = new_ps; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static int carl9170_check_sequence(struct ar9170 *ar, unsigned int seq) | ||
98 | { | ||
99 | if (ar->cmd_seq < -1) | ||
100 | return 0; | ||
101 | |||
102 | /* | ||
103 | * Initialize Counter | ||
104 | */ | ||
105 | if (ar->cmd_seq < 0) | ||
106 | ar->cmd_seq = seq; | ||
107 | |||
108 | /* | ||
109 | * The sequence is strictly monotonic increasing and it never skips! | ||
110 | * | ||
111 | * Therefore we can safely assume that whenever we received an | ||
112 | * unexpected sequence we have lost some valuable data. | ||
113 | */ | ||
114 | if (seq != ar->cmd_seq) { | ||
115 | int count; | ||
116 | |||
117 | count = (seq - ar->cmd_seq) % ar->fw.cmd_bufs; | ||
118 | |||
119 | wiphy_err(ar->hw->wiphy, "lost %d command responses/traps! " | ||
120 | "w:%d g:%d\n", count, ar->cmd_seq, seq); | ||
121 | |||
122 | carl9170_restart(ar, CARL9170_RR_LOST_RSP); | ||
123 | return -EIO; | ||
124 | } | ||
125 | |||
126 | ar->cmd_seq = (ar->cmd_seq + 1) % ar->fw.cmd_bufs; | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) | ||
131 | { | ||
132 | /* | ||
133 | * Some commands may have a variable response length | ||
134 | * and we cannot predict the correct length in advance. | ||
135 | * So we only check if we provided enough space for the data. | ||
136 | */ | ||
137 | if (unlikely(ar->readlen != (len - 4))) { | ||
138 | dev_warn(&ar->udev->dev, "received invalid command response:" | ||
139 | "got %d, instead of %d\n", len - 4, ar->readlen); | ||
140 | print_hex_dump_bytes("carl9170 cmd:", DUMP_PREFIX_OFFSET, | ||
141 | ar->cmd_buf, (ar->cmd.hdr.len + 4) & 0x3f); | ||
142 | print_hex_dump_bytes("carl9170 rsp:", DUMP_PREFIX_OFFSET, | ||
143 | buffer, len); | ||
144 | /* | ||
145 | * Do not complete. The command times out, | ||
146 | * and we get a stack trace from there. | ||
147 | */ | ||
148 | carl9170_restart(ar, CARL9170_RR_INVALID_RSP); | ||
149 | } | ||
150 | |||
151 | spin_lock(&ar->cmd_lock); | ||
152 | if (ar->readbuf) { | ||
153 | if (len >= 4) | ||
154 | memcpy(ar->readbuf, buffer + 4, len - 4); | ||
155 | |||
156 | ar->readbuf = NULL; | ||
157 | } | ||
158 | complete(&ar->cmd_wait); | ||
159 | spin_unlock(&ar->cmd_lock); | ||
160 | } | ||
161 | |||
162 | void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | ||
163 | { | ||
164 | struct carl9170_rsp *cmd = (void *) buf; | ||
165 | struct ieee80211_vif *vif; | ||
166 | |||
167 | if (carl9170_check_sequence(ar, cmd->hdr.seq)) | ||
168 | return; | ||
169 | |||
170 | if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) { | ||
171 | if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG)) | ||
172 | carl9170_cmd_callback(ar, len, buf); | ||
173 | |||
174 | return; | ||
175 | } | ||
176 | |||
177 | if (unlikely(cmd->hdr.len != (len - 4))) { | ||
178 | if (net_ratelimit()) { | ||
179 | wiphy_err(ar->hw->wiphy, "FW: received over-/under" | ||
180 | "sized event %x (%d, but should be %d).\n", | ||
181 | cmd->hdr.cmd, cmd->hdr.len, len - 4); | ||
182 | |||
183 | print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, | ||
184 | buf, len); | ||
185 | } | ||
186 | |||
187 | return; | ||
188 | } | ||
189 | |||
190 | /* hardware event handlers */ | ||
191 | switch (cmd->hdr.cmd) { | ||
192 | case CARL9170_RSP_PRETBTT: | ||
193 | /* pre-TBTT event */ | ||
194 | rcu_read_lock(); | ||
195 | vif = carl9170_get_main_vif(ar); | ||
196 | |||
197 | if (!vif) { | ||
198 | rcu_read_unlock(); | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | switch (vif->type) { | ||
203 | case NL80211_IFTYPE_STATION: | ||
204 | carl9170_handle_ps(ar, cmd); | ||
205 | break; | ||
206 | |||
207 | case NL80211_IFTYPE_AP: | ||
208 | case NL80211_IFTYPE_ADHOC: | ||
209 | carl9170_update_beacon(ar, true); | ||
210 | break; | ||
211 | |||
212 | default: | ||
213 | break; | ||
214 | } | ||
215 | rcu_read_unlock(); | ||
216 | |||
217 | break; | ||
218 | |||
219 | |||
220 | case CARL9170_RSP_TXCOMP: | ||
221 | /* TX status notification */ | ||
222 | carl9170_tx_process_status(ar, cmd); | ||
223 | break; | ||
224 | |||
225 | case CARL9170_RSP_BEACON_CONFIG: | ||
226 | /* | ||
227 | * (IBSS) beacon send notification | ||
228 | * bytes: 04 c2 XX YY B4 B3 B2 B1 | ||
229 | * | ||
230 | * XX always 80 | ||
231 | * YY always 00 | ||
232 | * B1-B4 "should" be the number of send out beacons. | ||
233 | */ | ||
234 | break; | ||
235 | |||
236 | case CARL9170_RSP_ATIM: | ||
237 | /* End of Atim Window */ | ||
238 | break; | ||
239 | |||
240 | case CARL9170_RSP_WATCHDOG: | ||
241 | /* Watchdog Interrupt */ | ||
242 | carl9170_restart(ar, CARL9170_RR_WATCHDOG); | ||
243 | break; | ||
244 | |||
245 | case CARL9170_RSP_TEXT: | ||
246 | /* firmware debug */ | ||
247 | carl9170_dbg_message(ar, (char *)buf + 4, len - 4); | ||
248 | break; | ||
249 | |||
250 | case CARL9170_RSP_HEXDUMP: | ||
251 | wiphy_dbg(ar->hw->wiphy, "FW: HD %d\n", len - 4); | ||
252 | print_hex_dump_bytes("FW:", DUMP_PREFIX_NONE, | ||
253 | (char *)buf + 4, len - 4); | ||
254 | break; | ||
255 | |||
256 | case CARL9170_RSP_RADAR: | ||
257 | if (!net_ratelimit()) | ||
258 | break; | ||
259 | |||
260 | wiphy_info(ar->hw->wiphy, "FW: RADAR! Please report this " | ||
261 | "incident to linux-wireless@vger.kernel.org !\n"); | ||
262 | break; | ||
263 | |||
264 | case CARL9170_RSP_GPIO: | ||
265 | #ifdef CONFIG_CARL9170_WPC | ||
266 | if (ar->wps.pbc) { | ||
267 | bool state = !!(cmd->gpio.gpio & cpu_to_le32( | ||
268 | AR9170_GPIO_PORT_WPS_BUTTON_PRESSED)); | ||
269 | |||
270 | if (state != ar->wps.pbc_state) { | ||
271 | ar->wps.pbc_state = state; | ||
272 | input_report_key(ar->wps.pbc, KEY_WPS_BUTTON, | ||
273 | state); | ||
274 | input_sync(ar->wps.pbc); | ||
275 | } | ||
276 | } | ||
277 | #endif /* CONFIG_CARL9170_WPC */ | ||
278 | break; | ||
279 | |||
280 | case CARL9170_RSP_BOOT: | ||
281 | complete(&ar->fw_boot_wait); | ||
282 | break; | ||
283 | |||
284 | default: | ||
285 | wiphy_err(ar->hw->wiphy, "FW: received unhandled event %x\n", | ||
286 | cmd->hdr.cmd); | ||
287 | print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); | ||
288 | break; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | static int carl9170_rx_mac_status(struct ar9170 *ar, | ||
293 | struct ar9170_rx_head *head, struct ar9170_rx_macstatus *mac, | ||
294 | struct ieee80211_rx_status *status) | ||
295 | { | ||
296 | struct ieee80211_channel *chan; | ||
297 | u8 error, decrypt; | ||
298 | |||
299 | BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); | ||
300 | BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); | ||
301 | |||
302 | error = mac->error; | ||
303 | |||
304 | if (error & AR9170_RX_ERROR_WRONG_RA) { | ||
305 | if (!ar->sniffer_enabled) | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | if (error & AR9170_RX_ERROR_PLCP) { | ||
310 | if (!(ar->filter_state & FIF_PLCPFAIL)) | ||
311 | return -EINVAL; | ||
312 | |||
313 | status->flag |= RX_FLAG_FAILED_PLCP_CRC; | ||
314 | } | ||
315 | |||
316 | if (error & AR9170_RX_ERROR_FCS) { | ||
317 | ar->tx_fcs_errors++; | ||
318 | |||
319 | if (!(ar->filter_state & FIF_FCSFAIL)) | ||
320 | return -EINVAL; | ||
321 | |||
322 | status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
323 | } | ||
324 | |||
325 | decrypt = ar9170_get_decrypt_type(mac); | ||
326 | if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && | ||
327 | decrypt != AR9170_ENC_ALG_NONE) { | ||
328 | if ((decrypt == AR9170_ENC_ALG_TKIP) && | ||
329 | (error & AR9170_RX_ERROR_MMIC)) | ||
330 | status->flag |= RX_FLAG_MMIC_ERROR; | ||
331 | |||
332 | status->flag |= RX_FLAG_DECRYPTED; | ||
333 | } | ||
334 | |||
335 | if (error & AR9170_RX_ERROR_DECRYPT && !ar->sniffer_enabled) | ||
336 | return -ENODATA; | ||
337 | |||
338 | error &= ~(AR9170_RX_ERROR_MMIC | | ||
339 | AR9170_RX_ERROR_FCS | | ||
340 | AR9170_RX_ERROR_WRONG_RA | | ||
341 | AR9170_RX_ERROR_DECRYPT | | ||
342 | AR9170_RX_ERROR_PLCP); | ||
343 | |||
344 | /* drop any other error frames */ | ||
345 | if (unlikely(error)) { | ||
346 | /* TODO: update netdevice's RX dropped/errors statistics */ | ||
347 | |||
348 | if (net_ratelimit()) | ||
349 | wiphy_dbg(ar->hw->wiphy, "received frame with " | ||
350 | "suspicious error code (%#x).\n", error); | ||
351 | |||
352 | return -EINVAL; | ||
353 | } | ||
354 | |||
355 | chan = ar->channel; | ||
356 | if (chan) { | ||
357 | status->band = chan->band; | ||
358 | status->freq = chan->center_freq; | ||
359 | } | ||
360 | |||
361 | switch (mac->status & AR9170_RX_STATUS_MODULATION) { | ||
362 | case AR9170_RX_STATUS_MODULATION_CCK: | ||
363 | if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) | ||
364 | status->flag |= RX_FLAG_SHORTPRE; | ||
365 | switch (head->plcp[0]) { | ||
366 | case AR9170_RX_PHY_RATE_CCK_1M: | ||
367 | status->rate_idx = 0; | ||
368 | break; | ||
369 | case AR9170_RX_PHY_RATE_CCK_2M: | ||
370 | status->rate_idx = 1; | ||
371 | break; | ||
372 | case AR9170_RX_PHY_RATE_CCK_5M: | ||
373 | status->rate_idx = 2; | ||
374 | break; | ||
375 | case AR9170_RX_PHY_RATE_CCK_11M: | ||
376 | status->rate_idx = 3; | ||
377 | break; | ||
378 | default: | ||
379 | if (net_ratelimit()) { | ||
380 | wiphy_err(ar->hw->wiphy, "invalid plcp cck " | ||
381 | "rate (%x).\n", head->plcp[0]); | ||
382 | } | ||
383 | |||
384 | return -EINVAL; | ||
385 | } | ||
386 | break; | ||
387 | |||
388 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | ||
389 | case AR9170_RX_STATUS_MODULATION_OFDM: | ||
390 | switch (head->plcp[0] & 0xf) { | ||
391 | case AR9170_TXRX_PHY_RATE_OFDM_6M: | ||
392 | status->rate_idx = 0; | ||
393 | break; | ||
394 | case AR9170_TXRX_PHY_RATE_OFDM_9M: | ||
395 | status->rate_idx = 1; | ||
396 | break; | ||
397 | case AR9170_TXRX_PHY_RATE_OFDM_12M: | ||
398 | status->rate_idx = 2; | ||
399 | break; | ||
400 | case AR9170_TXRX_PHY_RATE_OFDM_18M: | ||
401 | status->rate_idx = 3; | ||
402 | break; | ||
403 | case AR9170_TXRX_PHY_RATE_OFDM_24M: | ||
404 | status->rate_idx = 4; | ||
405 | break; | ||
406 | case AR9170_TXRX_PHY_RATE_OFDM_36M: | ||
407 | status->rate_idx = 5; | ||
408 | break; | ||
409 | case AR9170_TXRX_PHY_RATE_OFDM_48M: | ||
410 | status->rate_idx = 6; | ||
411 | break; | ||
412 | case AR9170_TXRX_PHY_RATE_OFDM_54M: | ||
413 | status->rate_idx = 7; | ||
414 | break; | ||
415 | default: | ||
416 | if (net_ratelimit()) { | ||
417 | wiphy_err(ar->hw->wiphy, "invalid plcp ofdm " | ||
418 | "rate (%x).\n", head->plcp[0]); | ||
419 | } | ||
420 | |||
421 | return -EINVAL; | ||
422 | } | ||
423 | if (status->band == IEEE80211_BAND_2GHZ) | ||
424 | status->rate_idx += 4; | ||
425 | break; | ||
426 | |||
427 | case AR9170_RX_STATUS_MODULATION_HT: | ||
428 | if (head->plcp[3] & 0x80) | ||
429 | status->flag |= RX_FLAG_40MHZ; | ||
430 | if (head->plcp[6] & 0x80) | ||
431 | status->flag |= RX_FLAG_SHORT_GI; | ||
432 | |||
433 | status->rate_idx = clamp(0, 75, head->plcp[3] & 0x7f); | ||
434 | status->flag |= RX_FLAG_HT; | ||
435 | break; | ||
436 | |||
437 | default: | ||
438 | BUG(); | ||
439 | return -ENOSYS; | ||
440 | } | ||
441 | |||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | static void carl9170_rx_phy_status(struct ar9170 *ar, | ||
446 | struct ar9170_rx_phystatus *phy, struct ieee80211_rx_status *status) | ||
447 | { | ||
448 | int i; | ||
449 | |||
450 | BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); | ||
451 | |||
452 | for (i = 0; i < 3; i++) | ||
453 | if (phy->rssi[i] != 0x80) | ||
454 | status->antenna |= BIT(i); | ||
455 | |||
456 | /* post-process RSSI */ | ||
457 | for (i = 0; i < 7; i++) | ||
458 | if (phy->rssi[i] & 0x80) | ||
459 | phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; | ||
460 | |||
461 | /* TODO: we could do something with phy_errors */ | ||
462 | status->signal = ar->noise[0] + phy->rssi_combined; | ||
463 | } | ||
464 | |||
465 | static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len) | ||
466 | { | ||
467 | struct sk_buff *skb; | ||
468 | int reserved = 0; | ||
469 | struct ieee80211_hdr *hdr = (void *) buf; | ||
470 | |||
471 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
472 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
473 | reserved += NET_IP_ALIGN; | ||
474 | |||
475 | if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | ||
476 | reserved += NET_IP_ALIGN; | ||
477 | } | ||
478 | |||
479 | if (ieee80211_has_a4(hdr->frame_control)) | ||
480 | reserved += NET_IP_ALIGN; | ||
481 | |||
482 | reserved = 32 + (reserved & NET_IP_ALIGN); | ||
483 | |||
484 | skb = dev_alloc_skb(len + reserved); | ||
485 | if (likely(skb)) { | ||
486 | skb_reserve(skb, reserved); | ||
487 | memcpy(skb_put(skb, len), buf, len); | ||
488 | } | ||
489 | |||
490 | return skb; | ||
491 | } | ||
492 | |||
493 | static u8 *carl9170_find_ie(u8 *data, unsigned int len, u8 ie) | ||
494 | { | ||
495 | struct ieee80211_mgmt *mgmt = (void *)data; | ||
496 | u8 *pos, *end; | ||
497 | |||
498 | pos = (u8 *)mgmt->u.beacon.variable; | ||
499 | end = data + len; | ||
500 | while (pos < end) { | ||
501 | if (pos + 2 + pos[1] > end) | ||
502 | return NULL; | ||
503 | |||
504 | if (pos[0] == ie) | ||
505 | return pos; | ||
506 | |||
507 | pos += 2 + pos[1]; | ||
508 | } | ||
509 | return NULL; | ||
510 | } | ||
511 | |||
512 | /* | ||
513 | * NOTE: | ||
514 | * | ||
515 | * The firmware is in charge of waking up the device just before | ||
516 | * the AP is expected to transmit the next beacon. | ||
517 | * | ||
518 | * This leaves the driver with the important task of deciding when | ||
519 | * to set the PHY back to bed again. | ||
520 | */ | ||
521 | static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) | ||
522 | { | ||
523 | struct ieee80211_hdr *hdr = (void *) data; | ||
524 | struct ieee80211_tim_ie *tim_ie; | ||
525 | u8 *tim; | ||
526 | u8 tim_len; | ||
527 | bool cam; | ||
528 | |||
529 | if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS))) | ||
530 | return; | ||
531 | |||
532 | /* check if this really is a beacon */ | ||
533 | if (!ieee80211_is_beacon(hdr->frame_control)) | ||
534 | return; | ||
535 | |||
536 | /* min. beacon length + FCS_LEN */ | ||
537 | if (len <= 40 + FCS_LEN) | ||
538 | return; | ||
539 | |||
540 | /* and only beacons from the associated BSSID, please */ | ||
541 | if (compare_ether_addr(hdr->addr3, ar->common.curbssid) || | ||
542 | !ar->common.curaid) | ||
543 | return; | ||
544 | |||
545 | ar->ps.last_beacon = jiffies; | ||
546 | |||
547 | tim = carl9170_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); | ||
548 | if (!tim) | ||
549 | return; | ||
550 | |||
551 | if (tim[1] < sizeof(*tim_ie)) | ||
552 | return; | ||
553 | |||
554 | tim_len = tim[1]; | ||
555 | tim_ie = (struct ieee80211_tim_ie *) &tim[2]; | ||
556 | |||
557 | if (!WARN_ON_ONCE(!ar->hw->conf.ps_dtim_period)) | ||
558 | ar->ps.dtim_counter = (tim_ie->dtim_count - 1) % | ||
559 | ar->hw->conf.ps_dtim_period; | ||
560 | |||
561 | /* Check whenever the PHY can be turned off again. */ | ||
562 | |||
563 | /* 1. What about buffered unicast traffic for our AID? */ | ||
564 | cam = ieee80211_check_tim(tim_ie, tim_len, ar->common.curaid); | ||
565 | |||
566 | /* 2. Maybe the AP wants to send multicast/broadcast data? */ | ||
567 | cam |= !!(tim_ie->bitmap_ctrl & 0x01); | ||
568 | |||
569 | if (!cam) { | ||
570 | /* back to low-power land. */ | ||
571 | ar->ps.off_override &= ~PS_OFF_BCN; | ||
572 | carl9170_ps_check(ar); | ||
573 | } else { | ||
574 | /* force CAM */ | ||
575 | ar->ps.off_override |= PS_OFF_BCN; | ||
576 | } | ||
577 | } | ||
578 | |||
579 | static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) | ||
580 | { | ||
581 | __le16 fc; | ||
582 | |||
583 | if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE) { | ||
584 | /* | ||
585 | * This frame is not part of an aMPDU. | ||
586 | * Therefore it is not subjected to any | ||
587 | * of the following content restrictions. | ||
588 | */ | ||
589 | return true; | ||
590 | } | ||
591 | |||
592 | /* | ||
593 | * "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts | ||
594 | * certain frame types can be part of an aMPDU. | ||
595 | * | ||
596 | * In order to keep the processing cost down, I opted for a | ||
597 | * stateless filter solely based on the frame control field. | ||
598 | */ | ||
599 | |||
600 | fc = ((struct ieee80211_hdr *)buf)->frame_control; | ||
601 | if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc)) | ||
602 | return true; | ||
603 | |||
604 | if (ieee80211_is_ack(fc) || ieee80211_is_back(fc) || | ||
605 | ieee80211_is_back_req(fc)) | ||
606 | return true; | ||
607 | |||
608 | if (ieee80211_is_action(fc)) | ||
609 | return true; | ||
610 | |||
611 | return false; | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | * If the frame alignment is right (or the kernel has | ||
616 | * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there | ||
617 | * is only a single MPDU in the USB frame, then we could | ||
618 | * submit to mac80211 the SKB directly. However, since | ||
619 | * there may be multiple packets in one SKB in stream | ||
620 | * mode, and we need to observe the proper ordering, | ||
621 | * this is non-trivial. | ||
622 | */ | ||
623 | |||
624 | static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) | ||
625 | { | ||
626 | struct ar9170_rx_head *head; | ||
627 | struct ar9170_rx_macstatus *mac; | ||
628 | struct ar9170_rx_phystatus *phy = NULL; | ||
629 | struct ieee80211_rx_status status; | ||
630 | struct sk_buff *skb; | ||
631 | int mpdu_len; | ||
632 | u8 mac_status; | ||
633 | |||
634 | if (!IS_STARTED(ar)) | ||
635 | return; | ||
636 | |||
637 | if (unlikely(len < sizeof(*mac))) | ||
638 | goto drop; | ||
639 | |||
640 | mpdu_len = len - sizeof(*mac); | ||
641 | |||
642 | mac = (void *)(buf + mpdu_len); | ||
643 | mac_status = mac->status; | ||
644 | switch (mac_status & AR9170_RX_STATUS_MPDU) { | ||
645 | case AR9170_RX_STATUS_MPDU_FIRST: | ||
646 | /* Aggregated MPDUs start with an PLCP header */ | ||
647 | if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { | ||
648 | head = (void *) buf; | ||
649 | |||
650 | /* | ||
651 | * The PLCP header needs to be cached for the | ||
652 | * following MIDDLE + LAST A-MPDU packets. | ||
653 | * | ||
654 | * So, if you are wondering why all frames seem | ||
655 | * to share a common RX status information, | ||
656 | * then you have the answer right here... | ||
657 | */ | ||
658 | memcpy(&ar->rx_plcp, (void *) buf, | ||
659 | sizeof(struct ar9170_rx_head)); | ||
660 | |||
661 | mpdu_len -= sizeof(struct ar9170_rx_head); | ||
662 | buf += sizeof(struct ar9170_rx_head); | ||
663 | |||
664 | ar->rx_has_plcp = true; | ||
665 | } else { | ||
666 | if (net_ratelimit()) { | ||
667 | wiphy_err(ar->hw->wiphy, "plcp info " | ||
668 | "is clipped.\n"); | ||
669 | } | ||
670 | |||
671 | goto drop; | ||
672 | } | ||
673 | break; | ||
674 | |||
675 | case AR9170_RX_STATUS_MPDU_LAST: | ||
676 | /* | ||
677 | * The last frame of an A-MPDU has an extra tail | ||
678 | * which does contain the phy status of the whole | ||
679 | * aggregate. | ||
680 | */ | ||
681 | |||
682 | if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { | ||
683 | mpdu_len -= sizeof(struct ar9170_rx_phystatus); | ||
684 | phy = (void *)(buf + mpdu_len); | ||
685 | } else { | ||
686 | if (net_ratelimit()) { | ||
687 | wiphy_err(ar->hw->wiphy, "frame tail " | ||
688 | "is clipped.\n"); | ||
689 | } | ||
690 | |||
691 | goto drop; | ||
692 | } | ||
693 | |||
694 | case AR9170_RX_STATUS_MPDU_MIDDLE: | ||
695 | /* These are just data + mac status */ | ||
696 | if (unlikely(!ar->rx_has_plcp)) { | ||
697 | if (!net_ratelimit()) | ||
698 | return; | ||
699 | |||
700 | wiphy_err(ar->hw->wiphy, "rx stream does not start " | ||
701 | "with a first_mpdu frame tag.\n"); | ||
702 | |||
703 | goto drop; | ||
704 | } | ||
705 | |||
706 | head = &ar->rx_plcp; | ||
707 | break; | ||
708 | |||
709 | case AR9170_RX_STATUS_MPDU_SINGLE: | ||
710 | /* single mpdu has both: plcp (head) and phy status (tail) */ | ||
711 | head = (void *) buf; | ||
712 | |||
713 | mpdu_len -= sizeof(struct ar9170_rx_head); | ||
714 | mpdu_len -= sizeof(struct ar9170_rx_phystatus); | ||
715 | |||
716 | buf += sizeof(struct ar9170_rx_head); | ||
717 | phy = (void *)(buf + mpdu_len); | ||
718 | break; | ||
719 | |||
720 | default: | ||
721 | BUG_ON(1); | ||
722 | break; | ||
723 | } | ||
724 | |||
725 | /* FC + DU + RA + FCS */ | ||
726 | if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN))) | ||
727 | goto drop; | ||
728 | |||
729 | memset(&status, 0, sizeof(status)); | ||
730 | if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) | ||
731 | goto drop; | ||
732 | |||
733 | if (!carl9170_ampdu_check(ar, buf, mac_status)) | ||
734 | goto drop; | ||
735 | |||
736 | if (phy) | ||
737 | carl9170_rx_phy_status(ar, phy, &status); | ||
738 | |||
739 | carl9170_ps_beacon(ar, buf, mpdu_len); | ||
740 | |||
741 | skb = carl9170_rx_copy_data(buf, mpdu_len); | ||
742 | if (!skb) | ||
743 | goto drop; | ||
744 | |||
745 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | ||
746 | ieee80211_rx(ar->hw, skb); | ||
747 | return; | ||
748 | |||
749 | drop: | ||
750 | ar->rx_dropped++; | ||
751 | } | ||
752 | |||
753 | static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf, | ||
754 | const unsigned int resplen) | ||
755 | { | ||
756 | struct carl9170_rsp *cmd; | ||
757 | int i = 0; | ||
758 | |||
759 | while (i < resplen) { | ||
760 | cmd = (void *) &respbuf[i]; | ||
761 | |||
762 | i += cmd->hdr.len + 4; | ||
763 | if (unlikely(i > resplen)) | ||
764 | break; | ||
765 | |||
766 | carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4); | ||
767 | } | ||
768 | |||
769 | if (unlikely(i != resplen)) { | ||
770 | if (!net_ratelimit()) | ||
771 | return; | ||
772 | |||
773 | wiphy_err(ar->hw->wiphy, "malformed firmware trap:\n"); | ||
774 | print_hex_dump_bytes("rxcmd:", DUMP_PREFIX_OFFSET, | ||
775 | respbuf, resplen); | ||
776 | } | ||
777 | } | ||
778 | |||
779 | static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len) | ||
780 | { | ||
781 | unsigned int i = 0; | ||
782 | |||
783 | /* weird thing, but this is the same in the original driver */ | ||
784 | while (len > 2 && i < 12 && buf[0] == 0xff && buf[1] == 0xff) { | ||
785 | i += 2; | ||
786 | len -= 2; | ||
787 | buf += 2; | ||
788 | } | ||
789 | |||
790 | if (unlikely(len < 4)) | ||
791 | return; | ||
792 | |||
793 | /* found the 6 * 0xffff marker? */ | ||
794 | if (i == 12) | ||
795 | carl9170_rx_untie_cmds(ar, buf, len); | ||
796 | else | ||
797 | carl9170_handle_mpdu(ar, buf, len); | ||
798 | } | ||
799 | |||
800 | static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) | ||
801 | { | ||
802 | unsigned int tlen, wlen = 0, clen = 0; | ||
803 | struct ar9170_stream *rx_stream; | ||
804 | u8 *tbuf; | ||
805 | |||
806 | tbuf = buf; | ||
807 | tlen = len; | ||
808 | |||
809 | while (tlen >= 4) { | ||
810 | rx_stream = (void *) tbuf; | ||
811 | clen = le16_to_cpu(rx_stream->length); | ||
812 | wlen = ALIGN(clen, 4); | ||
813 | |||
814 | /* check if this is stream has a valid tag.*/ | ||
815 | if (rx_stream->tag != cpu_to_le16(AR9170_RX_STREAM_TAG)) { | ||
816 | /* | ||
817 | * TODO: handle the highly unlikely event that the | ||
818 | * corrupted stream has the TAG at the right position. | ||
819 | */ | ||
820 | |||
821 | /* check if the frame can be repaired. */ | ||
822 | if (!ar->rx_failover_missing) { | ||
823 | |||
824 | /* this is not "short read". */ | ||
825 | if (net_ratelimit()) { | ||
826 | wiphy_err(ar->hw->wiphy, | ||
827 | "missing tag!\n"); | ||
828 | } | ||
829 | |||
830 | __carl9170_rx(ar, tbuf, tlen); | ||
831 | return; | ||
832 | } | ||
833 | |||
834 | if (ar->rx_failover_missing > tlen) { | ||
835 | if (net_ratelimit()) { | ||
836 | wiphy_err(ar->hw->wiphy, | ||
837 | "possible multi " | ||
838 | "stream corruption!\n"); | ||
839 | goto err_telluser; | ||
840 | } else { | ||
841 | goto err_silent; | ||
842 | } | ||
843 | } | ||
844 | |||
845 | memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); | ||
846 | ar->rx_failover_missing -= tlen; | ||
847 | |||
848 | if (ar->rx_failover_missing <= 0) { | ||
849 | /* | ||
850 | * nested carl9170_rx_stream call! | ||
851 | * | ||
852 | * termination is guaranteed, even when the | ||
853 | * combined frame also have an element with | ||
854 | * a bad tag. | ||
855 | */ | ||
856 | |||
857 | ar->rx_failover_missing = 0; | ||
858 | carl9170_rx_stream(ar, ar->rx_failover->data, | ||
859 | ar->rx_failover->len); | ||
860 | |||
861 | skb_reset_tail_pointer(ar->rx_failover); | ||
862 | skb_trim(ar->rx_failover, 0); | ||
863 | } | ||
864 | |||
865 | return; | ||
866 | } | ||
867 | |||
868 | /* check if stream is clipped */ | ||
869 | if (wlen > tlen - 4) { | ||
870 | if (ar->rx_failover_missing) { | ||
871 | /* TODO: handle double stream corruption. */ | ||
872 | if (net_ratelimit()) { | ||
873 | wiphy_err(ar->hw->wiphy, "double rx " | ||
874 | "stream corruption!\n"); | ||
875 | goto err_telluser; | ||
876 | } else { | ||
877 | goto err_silent; | ||
878 | } | ||
879 | } | ||
880 | |||
881 | /* | ||
882 | * save incomplete data set. | ||
883 | * the firmware will resend the missing bits when | ||
884 | * the rx - descriptor comes round again. | ||
885 | */ | ||
886 | |||
887 | memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); | ||
888 | ar->rx_failover_missing = clen - tlen; | ||
889 | return; | ||
890 | } | ||
891 | __carl9170_rx(ar, rx_stream->payload, clen); | ||
892 | |||
893 | tbuf += wlen + 4; | ||
894 | tlen -= wlen + 4; | ||
895 | } | ||
896 | |||
897 | if (tlen) { | ||
898 | if (net_ratelimit()) { | ||
899 | wiphy_err(ar->hw->wiphy, "%d bytes of unprocessed " | ||
900 | "data left in rx stream!\n", tlen); | ||
901 | } | ||
902 | |||
903 | goto err_telluser; | ||
904 | } | ||
905 | |||
906 | return; | ||
907 | |||
908 | err_telluser: | ||
909 | wiphy_err(ar->hw->wiphy, "damaged RX stream data [want:%d, " | ||
910 | "data:%d, rx:%d, pending:%d ]\n", clen, wlen, tlen, | ||
911 | ar->rx_failover_missing); | ||
912 | |||
913 | if (ar->rx_failover_missing) | ||
914 | print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, | ||
915 | ar->rx_failover->data, | ||
916 | ar->rx_failover->len); | ||
917 | |||
918 | print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, | ||
919 | buf, len); | ||
920 | |||
921 | wiphy_err(ar->hw->wiphy, "please check your hardware and cables, if " | ||
922 | "you see this message frequently.\n"); | ||
923 | |||
924 | err_silent: | ||
925 | if (ar->rx_failover_missing) { | ||
926 | skb_reset_tail_pointer(ar->rx_failover); | ||
927 | skb_trim(ar->rx_failover, 0); | ||
928 | ar->rx_failover_missing = 0; | ||
929 | } | ||
930 | } | ||
931 | |||
932 | void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len) | ||
933 | { | ||
934 | if (ar->fw.rx_stream) | ||
935 | carl9170_rx_stream(ar, buf, len); | ||
936 | else | ||
937 | __carl9170_rx(ar, buf, len); | ||
938 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c new file mode 100644 index 000000000000..e94084fcf6f5 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -0,0 +1,1440 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * 802.11 xmit & status routines | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/init.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/module.h> | ||
43 | #include <linux/etherdevice.h> | ||
44 | #include <net/mac80211.h> | ||
45 | #include "carl9170.h" | ||
46 | #include "hw.h" | ||
47 | #include "cmd.h" | ||
48 | |||
49 | static inline unsigned int __carl9170_get_queue(struct ar9170 *ar, | ||
50 | unsigned int queue) | ||
51 | { | ||
52 | if (unlikely(modparam_noht)) { | ||
53 | return queue; | ||
54 | } else { | ||
55 | /* | ||
56 | * This is just another workaround, until | ||
57 | * someone figures out how to get QoS and | ||
58 | * AMPDU to play nicely together. | ||
59 | */ | ||
60 | |||
61 | return 2; /* AC_BE */ | ||
62 | } | ||
63 | } | ||
64 | |||
65 | static inline unsigned int carl9170_get_queue(struct ar9170 *ar, | ||
66 | struct sk_buff *skb) | ||
67 | { | ||
68 | return __carl9170_get_queue(ar, skb_get_queue_mapping(skb)); | ||
69 | } | ||
70 | |||
71 | static bool is_mem_full(struct ar9170 *ar) | ||
72 | { | ||
73 | return (DIV_ROUND_UP(IEEE80211_MAX_FRAME_LEN, ar->fw.mem_block_size) > | ||
74 | atomic_read(&ar->mem_free_blocks)); | ||
75 | } | ||
76 | |||
77 | static void carl9170_tx_accounting(struct ar9170 *ar, struct sk_buff *skb) | ||
78 | { | ||
79 | int queue, i; | ||
80 | bool mem_full; | ||
81 | |||
82 | atomic_inc(&ar->tx_total_queued); | ||
83 | |||
84 | queue = skb_get_queue_mapping(skb); | ||
85 | spin_lock_bh(&ar->tx_stats_lock); | ||
86 | |||
87 | /* | ||
88 | * The driver has to accept the frame, regardless if the queue is | ||
89 | * full to the brim, or not. We have to do the queuing internally, | ||
90 | * since mac80211 assumes that a driver which can operate with | ||
91 | * aggregated frames does not reject frames for this reason. | ||
92 | */ | ||
93 | ar->tx_stats[queue].len++; | ||
94 | ar->tx_stats[queue].count++; | ||
95 | |||
96 | mem_full = is_mem_full(ar); | ||
97 | for (i = 0; i < ar->hw->queues; i++) { | ||
98 | if (mem_full || ar->tx_stats[i].len >= ar->tx_stats[i].limit) { | ||
99 | ieee80211_stop_queue(ar->hw, i); | ||
100 | ar->queue_stop_timeout[i] = jiffies; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | spin_unlock_bh(&ar->tx_stats_lock); | ||
105 | } | ||
106 | |||
107 | /* needs rcu_read_lock */ | ||
108 | static struct ieee80211_sta *__carl9170_get_tx_sta(struct ar9170 *ar, | ||
109 | struct sk_buff *skb) | ||
110 | { | ||
111 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
112 | struct ieee80211_hdr *hdr = (void *) super->frame_data; | ||
113 | struct ieee80211_vif *vif; | ||
114 | unsigned int vif_id; | ||
115 | |||
116 | vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> | ||
117 | CARL9170_TX_SUPER_MISC_VIF_ID_S; | ||
118 | |||
119 | if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) | ||
120 | return NULL; | ||
121 | |||
122 | vif = rcu_dereference(ar->vif_priv[vif_id].vif); | ||
123 | if (unlikely(!vif)) | ||
124 | return NULL; | ||
125 | |||
126 | /* | ||
127 | * Normally we should use wrappers like ieee80211_get_DA to get | ||
128 | * the correct peer ieee80211_sta. | ||
129 | * | ||
130 | * But there is a problem with indirect traffic (broadcasts, or | ||
131 | * data which is designated for other stations) in station mode. | ||
132 | * The frame will be directed to the AP for distribution and not | ||
133 | * to the actual destination. | ||
134 | */ | ||
135 | |||
136 | return ieee80211_find_sta(vif, hdr->addr1); | ||
137 | } | ||
138 | |||
139 | static void carl9170_tx_ps_unblock(struct ar9170 *ar, struct sk_buff *skb) | ||
140 | { | ||
141 | struct ieee80211_sta *sta; | ||
142 | struct carl9170_sta_info *sta_info; | ||
143 | |||
144 | rcu_read_lock(); | ||
145 | sta = __carl9170_get_tx_sta(ar, skb); | ||
146 | if (unlikely(!sta)) | ||
147 | goto out_rcu; | ||
148 | |||
149 | sta_info = (struct carl9170_sta_info *) sta->drv_priv; | ||
150 | if (atomic_dec_return(&sta_info->pending_frames) == 0) | ||
151 | ieee80211_sta_block_awake(ar->hw, sta, false); | ||
152 | |||
153 | out_rcu: | ||
154 | rcu_read_unlock(); | ||
155 | } | ||
156 | |||
157 | static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) | ||
158 | { | ||
159 | int queue; | ||
160 | |||
161 | queue = skb_get_queue_mapping(skb); | ||
162 | |||
163 | spin_lock_bh(&ar->tx_stats_lock); | ||
164 | |||
165 | ar->tx_stats[queue].len--; | ||
166 | |||
167 | if (!is_mem_full(ar)) { | ||
168 | unsigned int i; | ||
169 | for (i = 0; i < ar->hw->queues; i++) { | ||
170 | if (ar->tx_stats[i].len >= CARL9170_NUM_TX_LIMIT_SOFT) | ||
171 | continue; | ||
172 | |||
173 | if (ieee80211_queue_stopped(ar->hw, i)) { | ||
174 | unsigned long tmp; | ||
175 | |||
176 | tmp = jiffies - ar->queue_stop_timeout[i]; | ||
177 | if (tmp > ar->max_queue_stop_timeout[i]) | ||
178 | ar->max_queue_stop_timeout[i] = tmp; | ||
179 | } | ||
180 | |||
181 | ieee80211_wake_queue(ar->hw, i); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | spin_unlock_bh(&ar->tx_stats_lock); | ||
186 | |||
187 | if (atomic_dec_and_test(&ar->tx_total_queued)) | ||
188 | complete(&ar->tx_flush); | ||
189 | } | ||
190 | |||
191 | static int carl9170_alloc_dev_space(struct ar9170 *ar, struct sk_buff *skb) | ||
192 | { | ||
193 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
194 | unsigned int chunks; | ||
195 | int cookie = -1; | ||
196 | |||
197 | atomic_inc(&ar->mem_allocs); | ||
198 | |||
199 | chunks = DIV_ROUND_UP(skb->len, ar->fw.mem_block_size); | ||
200 | if (unlikely(atomic_sub_return(chunks, &ar->mem_free_blocks) < 0)) { | ||
201 | atomic_add(chunks, &ar->mem_free_blocks); | ||
202 | return -ENOSPC; | ||
203 | } | ||
204 | |||
205 | spin_lock_bh(&ar->mem_lock); | ||
206 | cookie = bitmap_find_free_region(ar->mem_bitmap, ar->fw.mem_blocks, 0); | ||
207 | spin_unlock_bh(&ar->mem_lock); | ||
208 | |||
209 | if (unlikely(cookie < 0)) { | ||
210 | atomic_add(chunks, &ar->mem_free_blocks); | ||
211 | return -ENOSPC; | ||
212 | } | ||
213 | |||
214 | super = (void *) skb->data; | ||
215 | |||
216 | /* | ||
217 | * Cookie #0 serves two special purposes: | ||
218 | * 1. The firmware might use it generate BlockACK frames | ||
219 | * in responds of an incoming BlockAckReqs. | ||
220 | * | ||
221 | * 2. Prevent double-free bugs. | ||
222 | */ | ||
223 | super->s.cookie = (u8) cookie + 1; | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static void carl9170_release_dev_space(struct ar9170 *ar, struct sk_buff *skb) | ||
228 | { | ||
229 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
230 | int cookie; | ||
231 | |||
232 | /* make a local copy of the cookie */ | ||
233 | cookie = super->s.cookie; | ||
234 | /* invalidate cookie */ | ||
235 | super->s.cookie = 0; | ||
236 | |||
237 | /* | ||
238 | * Do a out-of-bounds check on the cookie: | ||
239 | * | ||
240 | * * cookie "0" is reserved and won't be assigned to any | ||
241 | * out-going frame. Internally however, it is used to | ||
242 | * mark no longer/un-accounted frames and serves as a | ||
243 | * cheap way of preventing frames from being freed | ||
244 | * twice by _accident_. NB: There is a tiny race... | ||
245 | * | ||
246 | * * obviously, cookie number is limited by the amount | ||
247 | * of available memory blocks, so the number can | ||
248 | * never execeed the mem_blocks count. | ||
249 | */ | ||
250 | if (unlikely(WARN_ON_ONCE(cookie == 0) || | ||
251 | WARN_ON_ONCE(cookie > ar->fw.mem_blocks))) | ||
252 | return; | ||
253 | |||
254 | atomic_add(DIV_ROUND_UP(skb->len, ar->fw.mem_block_size), | ||
255 | &ar->mem_free_blocks); | ||
256 | |||
257 | spin_lock_bh(&ar->mem_lock); | ||
258 | bitmap_release_region(ar->mem_bitmap, cookie - 1, 0); | ||
259 | spin_unlock_bh(&ar->mem_lock); | ||
260 | } | ||
261 | |||
262 | /* Called from any context */ | ||
263 | static void carl9170_tx_release(struct kref *ref) | ||
264 | { | ||
265 | struct ar9170 *ar; | ||
266 | struct carl9170_tx_info *arinfo; | ||
267 | struct ieee80211_tx_info *txinfo; | ||
268 | struct sk_buff *skb; | ||
269 | |||
270 | arinfo = container_of(ref, struct carl9170_tx_info, ref); | ||
271 | txinfo = container_of((void *) arinfo, struct ieee80211_tx_info, | ||
272 | rate_driver_data); | ||
273 | skb = container_of((void *) txinfo, struct sk_buff, cb); | ||
274 | |||
275 | ar = arinfo->ar; | ||
276 | if (WARN_ON_ONCE(!ar)) | ||
277 | return; | ||
278 | |||
279 | BUILD_BUG_ON( | ||
280 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); | ||
281 | |||
282 | memset(&txinfo->status.ampdu_ack_len, 0, | ||
283 | sizeof(struct ieee80211_tx_info) - | ||
284 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); | ||
285 | |||
286 | if (atomic_read(&ar->tx_total_queued)) | ||
287 | ar->tx_schedule = true; | ||
288 | |||
289 | if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) { | ||
290 | if (!atomic_read(&ar->tx_ampdu_upload)) | ||
291 | ar->tx_ampdu_schedule = true; | ||
292 | |||
293 | if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) { | ||
294 | struct _carl9170_tx_superframe *super; | ||
295 | |||
296 | super = (void *)skb->data; | ||
297 | txinfo->status.ampdu_len = super->s.rix; | ||
298 | txinfo->status.ampdu_ack_len = super->s.cnt; | ||
299 | } else if (txinfo->flags & IEEE80211_TX_STAT_ACK) { | ||
300 | /* | ||
301 | * drop redundant tx_status reports: | ||
302 | * | ||
303 | * 1. ampdu_ack_len of the final tx_status does | ||
304 | * include the feedback of this particular frame. | ||
305 | * | ||
306 | * 2. tx_status_irqsafe only queues up to 128 | ||
307 | * tx feedback reports and discards the rest. | ||
308 | * | ||
309 | * 3. minstrel_ht is picky, it only accepts | ||
310 | * reports of frames with the TX_STATUS_AMPDU flag. | ||
311 | */ | ||
312 | |||
313 | dev_kfree_skb_any(skb); | ||
314 | return; | ||
315 | } else { | ||
316 | /* | ||
317 | * Frame has failed, but we want to keep it in | ||
318 | * case it was lost due to a power-state | ||
319 | * transition. | ||
320 | */ | ||
321 | } | ||
322 | } | ||
323 | |||
324 | skb_pull(skb, sizeof(struct _carl9170_tx_superframe)); | ||
325 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
326 | } | ||
327 | |||
328 | void carl9170_tx_get_skb(struct sk_buff *skb) | ||
329 | { | ||
330 | struct carl9170_tx_info *arinfo = (void *) | ||
331 | (IEEE80211_SKB_CB(skb))->rate_driver_data; | ||
332 | kref_get(&arinfo->ref); | ||
333 | } | ||
334 | |||
335 | int carl9170_tx_put_skb(struct sk_buff *skb) | ||
336 | { | ||
337 | struct carl9170_tx_info *arinfo = (void *) | ||
338 | (IEEE80211_SKB_CB(skb))->rate_driver_data; | ||
339 | |||
340 | return kref_put(&arinfo->ref, carl9170_tx_release); | ||
341 | } | ||
342 | |||
343 | /* Caller must hold the tid_info->lock & rcu_read_lock */ | ||
344 | static void carl9170_tx_shift_bm(struct ar9170 *ar, | ||
345 | struct carl9170_sta_tid *tid_info, u16 seq) | ||
346 | { | ||
347 | u16 off; | ||
348 | |||
349 | off = SEQ_DIFF(seq, tid_info->bsn); | ||
350 | |||
351 | if (WARN_ON_ONCE(off >= CARL9170_BAW_BITS)) | ||
352 | return; | ||
353 | |||
354 | /* | ||
355 | * Sanity check. For each MPDU we set the bit in bitmap and | ||
356 | * clear it once we received the tx_status. | ||
357 | * But if the bit is already cleared then we've been bitten | ||
358 | * by a bug. | ||
359 | */ | ||
360 | WARN_ON_ONCE(!test_and_clear_bit(off, tid_info->bitmap)); | ||
361 | |||
362 | off = SEQ_DIFF(tid_info->snx, tid_info->bsn); | ||
363 | if (WARN_ON_ONCE(off >= CARL9170_BAW_BITS)) | ||
364 | return; | ||
365 | |||
366 | if (!bitmap_empty(tid_info->bitmap, off)) | ||
367 | off = find_first_bit(tid_info->bitmap, off); | ||
368 | |||
369 | tid_info->bsn += off; | ||
370 | tid_info->bsn &= 0x0fff; | ||
371 | |||
372 | bitmap_shift_right(tid_info->bitmap, tid_info->bitmap, | ||
373 | off, CARL9170_BAW_BITS); | ||
374 | } | ||
375 | |||
376 | static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, | ||
377 | struct sk_buff *skb, struct ieee80211_tx_info *txinfo) | ||
378 | { | ||
379 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
380 | struct ieee80211_hdr *hdr = (void *) super->frame_data; | ||
381 | struct ieee80211_sta *sta; | ||
382 | struct carl9170_sta_info *sta_info; | ||
383 | struct carl9170_sta_tid *tid_info; | ||
384 | u8 tid; | ||
385 | |||
386 | if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || | ||
387 | txinfo->flags & IEEE80211_TX_CTL_INJECTED || | ||
388 | (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) | ||
389 | return; | ||
390 | |||
391 | rcu_read_lock(); | ||
392 | sta = __carl9170_get_tx_sta(ar, skb); | ||
393 | if (unlikely(!sta)) | ||
394 | goto out_rcu; | ||
395 | |||
396 | tid = get_tid_h(hdr); | ||
397 | |||
398 | sta_info = (void *) sta->drv_priv; | ||
399 | tid_info = rcu_dereference(sta_info->agg[tid]); | ||
400 | if (!tid_info) | ||
401 | goto out_rcu; | ||
402 | |||
403 | spin_lock_bh(&tid_info->lock); | ||
404 | if (likely(tid_info->state >= CARL9170_TID_STATE_IDLE)) | ||
405 | carl9170_tx_shift_bm(ar, tid_info, get_seq_h(hdr)); | ||
406 | |||
407 | if (sta_info->stats[tid].clear) { | ||
408 | sta_info->stats[tid].clear = false; | ||
409 | sta_info->stats[tid].req = false; | ||
410 | sta_info->stats[tid].ampdu_len = 0; | ||
411 | sta_info->stats[tid].ampdu_ack_len = 0; | ||
412 | } | ||
413 | |||
414 | sta_info->stats[tid].ampdu_len++; | ||
415 | if (txinfo->status.rates[0].count == 1) | ||
416 | sta_info->stats[tid].ampdu_ack_len++; | ||
417 | |||
418 | if (!(txinfo->flags & IEEE80211_TX_STAT_ACK)) | ||
419 | sta_info->stats[tid].req = true; | ||
420 | |||
421 | if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) { | ||
422 | super->s.rix = sta_info->stats[tid].ampdu_len; | ||
423 | super->s.cnt = sta_info->stats[tid].ampdu_ack_len; | ||
424 | txinfo->flags |= IEEE80211_TX_STAT_AMPDU; | ||
425 | if (sta_info->stats[tid].req) | ||
426 | txinfo->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
427 | |||
428 | sta_info->stats[tid].clear = true; | ||
429 | } | ||
430 | spin_unlock_bh(&tid_info->lock); | ||
431 | |||
432 | out_rcu: | ||
433 | rcu_read_unlock(); | ||
434 | } | ||
435 | |||
436 | void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, | ||
437 | const bool success) | ||
438 | { | ||
439 | struct ieee80211_tx_info *txinfo; | ||
440 | |||
441 | carl9170_tx_accounting_free(ar, skb); | ||
442 | |||
443 | txinfo = IEEE80211_SKB_CB(skb); | ||
444 | |||
445 | if (success) | ||
446 | txinfo->flags |= IEEE80211_TX_STAT_ACK; | ||
447 | else | ||
448 | ar->tx_ack_failures++; | ||
449 | |||
450 | if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) | ||
451 | carl9170_tx_status_process_ampdu(ar, skb, txinfo); | ||
452 | |||
453 | carl9170_tx_ps_unblock(ar, skb); | ||
454 | carl9170_tx_put_skb(skb); | ||
455 | } | ||
456 | |||
457 | /* This function may be called form any context */ | ||
458 | void carl9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | ||
459 | { | ||
460 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
461 | |||
462 | atomic_dec(&ar->tx_total_pending); | ||
463 | |||
464 | if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) | ||
465 | atomic_dec(&ar->tx_ampdu_upload); | ||
466 | |||
467 | if (carl9170_tx_put_skb(skb)) | ||
468 | tasklet_hi_schedule(&ar->usb_tasklet); | ||
469 | } | ||
470 | |||
471 | static struct sk_buff *carl9170_get_queued_skb(struct ar9170 *ar, u8 cookie, | ||
472 | struct sk_buff_head *queue) | ||
473 | { | ||
474 | struct sk_buff *skb; | ||
475 | |||
476 | spin_lock_bh(&queue->lock); | ||
477 | skb_queue_walk(queue, skb) { | ||
478 | struct _carl9170_tx_superframe *txc = (void *) skb->data; | ||
479 | |||
480 | if (txc->s.cookie != cookie) | ||
481 | continue; | ||
482 | |||
483 | __skb_unlink(skb, queue); | ||
484 | spin_unlock_bh(&queue->lock); | ||
485 | |||
486 | carl9170_release_dev_space(ar, skb); | ||
487 | return skb; | ||
488 | } | ||
489 | spin_unlock_bh(&queue->lock); | ||
490 | |||
491 | return NULL; | ||
492 | } | ||
493 | |||
494 | static void carl9170_tx_fill_rateinfo(struct ar9170 *ar, unsigned int rix, | ||
495 | unsigned int tries, struct ieee80211_tx_info *txinfo) | ||
496 | { | ||
497 | unsigned int i; | ||
498 | |||
499 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | ||
500 | if (txinfo->status.rates[i].idx < 0) | ||
501 | break; | ||
502 | |||
503 | if (i == rix) { | ||
504 | txinfo->status.rates[i].count = tries; | ||
505 | i++; | ||
506 | break; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | for (; i < IEEE80211_TX_MAX_RATES; i++) { | ||
511 | txinfo->status.rates[i].idx = -1; | ||
512 | txinfo->status.rates[i].count = 0; | ||
513 | } | ||
514 | } | ||
515 | |||
516 | static void carl9170_check_queue_stop_timeout(struct ar9170 *ar) | ||
517 | { | ||
518 | int i; | ||
519 | struct sk_buff *skb; | ||
520 | struct ieee80211_tx_info *txinfo; | ||
521 | struct carl9170_tx_info *arinfo; | ||
522 | bool restart = false; | ||
523 | |||
524 | for (i = 0; i < ar->hw->queues; i++) { | ||
525 | spin_lock_bh(&ar->tx_status[i].lock); | ||
526 | |||
527 | skb = skb_peek(&ar->tx_status[i]); | ||
528 | |||
529 | if (!skb) | ||
530 | goto next; | ||
531 | |||
532 | txinfo = IEEE80211_SKB_CB(skb); | ||
533 | arinfo = (void *) txinfo->rate_driver_data; | ||
534 | |||
535 | if (time_is_before_jiffies(arinfo->timeout + | ||
536 | msecs_to_jiffies(CARL9170_QUEUE_STUCK_TIMEOUT)) == true) | ||
537 | restart = true; | ||
538 | |||
539 | next: | ||
540 | spin_unlock_bh(&ar->tx_status[i].lock); | ||
541 | } | ||
542 | |||
543 | if (restart) { | ||
544 | /* | ||
545 | * At least one queue has been stuck for long enough. | ||
546 | * Give the device a kick and hope it gets back to | ||
547 | * work. | ||
548 | * | ||
549 | * possible reasons may include: | ||
550 | * - frames got lost/corrupted (bad connection to the device) | ||
551 | * - stalled rx processing/usb controller hiccups | ||
552 | * - firmware errors/bugs | ||
553 | * - every bug you can think of. | ||
554 | * - all bugs you can't... | ||
555 | * - ... | ||
556 | */ | ||
557 | carl9170_restart(ar, CARL9170_RR_STUCK_TX); | ||
558 | } | ||
559 | } | ||
560 | |||
561 | static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) | ||
562 | { | ||
563 | struct carl9170_sta_tid *iter; | ||
564 | struct sk_buff *skb; | ||
565 | struct ieee80211_tx_info *txinfo; | ||
566 | struct carl9170_tx_info *arinfo; | ||
567 | struct ieee80211_sta *sta; | ||
568 | |||
569 | rcu_read_lock(); | ||
570 | list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { | ||
571 | if (iter->state < CARL9170_TID_STATE_IDLE) | ||
572 | continue; | ||
573 | |||
574 | spin_lock_bh(&iter->lock); | ||
575 | skb = skb_peek(&iter->queue); | ||
576 | if (!skb) | ||
577 | goto unlock; | ||
578 | |||
579 | txinfo = IEEE80211_SKB_CB(skb); | ||
580 | arinfo = (void *)txinfo->rate_driver_data; | ||
581 | if (time_is_after_jiffies(arinfo->timeout + | ||
582 | msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) | ||
583 | goto unlock; | ||
584 | |||
585 | sta = __carl9170_get_tx_sta(ar, skb); | ||
586 | if (WARN_ON(!sta)) | ||
587 | goto unlock; | ||
588 | |||
589 | ieee80211_stop_tx_ba_session(sta, iter->tid); | ||
590 | unlock: | ||
591 | spin_unlock_bh(&iter->lock); | ||
592 | |||
593 | } | ||
594 | rcu_read_unlock(); | ||
595 | } | ||
596 | |||
597 | void carl9170_tx_janitor(struct work_struct *work) | ||
598 | { | ||
599 | struct ar9170 *ar = container_of(work, struct ar9170, | ||
600 | tx_janitor.work); | ||
601 | if (!IS_STARTED(ar)) | ||
602 | return; | ||
603 | |||
604 | ar->tx_janitor_last_run = jiffies; | ||
605 | |||
606 | carl9170_check_queue_stop_timeout(ar); | ||
607 | carl9170_tx_ampdu_timeout(ar); | ||
608 | |||
609 | if (!atomic_read(&ar->tx_total_queued)) | ||
610 | return; | ||
611 | |||
612 | ieee80211_queue_delayed_work(ar->hw, &ar->tx_janitor, | ||
613 | msecs_to_jiffies(CARL9170_TX_TIMEOUT)); | ||
614 | } | ||
615 | |||
616 | static void __carl9170_tx_process_status(struct ar9170 *ar, | ||
617 | const uint8_t cookie, const uint8_t info) | ||
618 | { | ||
619 | struct sk_buff *skb; | ||
620 | struct ieee80211_tx_info *txinfo; | ||
621 | unsigned int r, t, q; | ||
622 | bool success = true; | ||
623 | |||
624 | q = ar9170_qmap[info & CARL9170_TX_STATUS_QUEUE]; | ||
625 | |||
626 | skb = carl9170_get_queued_skb(ar, cookie, &ar->tx_status[q]); | ||
627 | if (!skb) { | ||
628 | /* | ||
629 | * We have lost the race to another thread. | ||
630 | */ | ||
631 | |||
632 | return ; | ||
633 | } | ||
634 | |||
635 | txinfo = IEEE80211_SKB_CB(skb); | ||
636 | |||
637 | if (!(info & CARL9170_TX_STATUS_SUCCESS)) | ||
638 | success = false; | ||
639 | |||
640 | r = (info & CARL9170_TX_STATUS_RIX) >> CARL9170_TX_STATUS_RIX_S; | ||
641 | t = (info & CARL9170_TX_STATUS_TRIES) >> CARL9170_TX_STATUS_TRIES_S; | ||
642 | |||
643 | carl9170_tx_fill_rateinfo(ar, r, t, txinfo); | ||
644 | carl9170_tx_status(ar, skb, success); | ||
645 | } | ||
646 | |||
647 | void carl9170_tx_process_status(struct ar9170 *ar, | ||
648 | const struct carl9170_rsp *cmd) | ||
649 | { | ||
650 | unsigned int i; | ||
651 | |||
652 | for (i = 0; i < cmd->hdr.ext; i++) { | ||
653 | if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) { | ||
654 | print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE, | ||
655 | (void *) cmd, cmd->hdr.len + 4); | ||
656 | break; | ||
657 | } | ||
658 | |||
659 | __carl9170_tx_process_status(ar, cmd->_tx_status[i].cookie, | ||
660 | cmd->_tx_status[i].info); | ||
661 | } | ||
662 | } | ||
663 | |||
664 | static __le32 carl9170_tx_physet(struct ar9170 *ar, | ||
665 | struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate) | ||
666 | { | ||
667 | struct ieee80211_rate *rate = NULL; | ||
668 | u32 power, chains; | ||
669 | __le32 tmp; | ||
670 | |||
671 | tmp = cpu_to_le32(0); | ||
672 | |||
673 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
674 | tmp |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ << | ||
675 | AR9170_TX_PHY_BW_S); | ||
676 | /* this works because 40 MHz is 2 and dup is 3 */ | ||
677 | if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) | ||
678 | tmp |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP << | ||
679 | AR9170_TX_PHY_BW_S); | ||
680 | |||
681 | if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
682 | tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); | ||
683 | |||
684 | if (txrate->flags & IEEE80211_TX_RC_MCS) { | ||
685 | u32 r = txrate->idx; | ||
686 | u8 *txpower; | ||
687 | |||
688 | /* heavy clip control */ | ||
689 | tmp |= cpu_to_le32((r & 0x7) << | ||
690 | AR9170_TX_PHY_TX_HEAVY_CLIP_S); | ||
691 | |||
692 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { | ||
693 | if (info->band == IEEE80211_BAND_5GHZ) | ||
694 | txpower = ar->power_5G_ht40; | ||
695 | else | ||
696 | txpower = ar->power_2G_ht40; | ||
697 | } else { | ||
698 | if (info->band == IEEE80211_BAND_5GHZ) | ||
699 | txpower = ar->power_5G_ht20; | ||
700 | else | ||
701 | txpower = ar->power_2G_ht20; | ||
702 | } | ||
703 | |||
704 | power = txpower[r & 7]; | ||
705 | |||
706 | /* +1 dBm for HT40 */ | ||
707 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
708 | power += 2; | ||
709 | |||
710 | r <<= AR9170_TX_PHY_MCS_S; | ||
711 | BUG_ON(r & ~AR9170_TX_PHY_MCS); | ||
712 | |||
713 | tmp |= cpu_to_le32(r & AR9170_TX_PHY_MCS); | ||
714 | tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); | ||
715 | |||
716 | /* | ||
717 | * green field preamble does not work. | ||
718 | * | ||
719 | * if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) | ||
720 | * tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); | ||
721 | */ | ||
722 | } else { | ||
723 | u8 *txpower; | ||
724 | u32 mod; | ||
725 | u32 phyrate; | ||
726 | u8 idx = txrate->idx; | ||
727 | |||
728 | if (info->band != IEEE80211_BAND_2GHZ) { | ||
729 | idx += 4; | ||
730 | txpower = ar->power_5G_leg; | ||
731 | mod = AR9170_TX_PHY_MOD_OFDM; | ||
732 | } else { | ||
733 | if (idx < 4) { | ||
734 | txpower = ar->power_2G_cck; | ||
735 | mod = AR9170_TX_PHY_MOD_CCK; | ||
736 | } else { | ||
737 | mod = AR9170_TX_PHY_MOD_OFDM; | ||
738 | txpower = ar->power_2G_ofdm; | ||
739 | } | ||
740 | } | ||
741 | |||
742 | rate = &__carl9170_ratetable[idx]; | ||
743 | |||
744 | phyrate = rate->hw_value & 0xF; | ||
745 | power = txpower[(rate->hw_value & 0x30) >> 4]; | ||
746 | phyrate <<= AR9170_TX_PHY_MCS_S; | ||
747 | |||
748 | tmp |= cpu_to_le32(mod); | ||
749 | tmp |= cpu_to_le32(phyrate); | ||
750 | |||
751 | /* | ||
752 | * short preamble seems to be broken too. | ||
753 | * | ||
754 | * if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
755 | * tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); | ||
756 | */ | ||
757 | } | ||
758 | power <<= AR9170_TX_PHY_TX_PWR_S; | ||
759 | power &= AR9170_TX_PHY_TX_PWR; | ||
760 | tmp |= cpu_to_le32(power); | ||
761 | |||
762 | /* set TX chains */ | ||
763 | if (ar->eeprom.tx_mask == 1) { | ||
764 | chains = AR9170_TX_PHY_TXCHAIN_1; | ||
765 | } else { | ||
766 | chains = AR9170_TX_PHY_TXCHAIN_2; | ||
767 | |||
768 | /* >= 36M legacy OFDM - use only one chain */ | ||
769 | if (rate && rate->bitrate >= 360 && | ||
770 | !(txrate->flags & IEEE80211_TX_RC_MCS)) | ||
771 | chains = AR9170_TX_PHY_TXCHAIN_1; | ||
772 | } | ||
773 | tmp |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_S); | ||
774 | |||
775 | return tmp; | ||
776 | } | ||
777 | |||
778 | static bool carl9170_tx_rts_check(struct ar9170 *ar, | ||
779 | struct ieee80211_tx_rate *rate, | ||
780 | bool ampdu, bool multi) | ||
781 | { | ||
782 | switch (ar->erp_mode) { | ||
783 | case CARL9170_ERP_AUTO: | ||
784 | if (ampdu) | ||
785 | break; | ||
786 | |||
787 | case CARL9170_ERP_MAC80211: | ||
788 | if (!(rate->flags & IEEE80211_TX_RC_USE_RTS_CTS)) | ||
789 | break; | ||
790 | |||
791 | case CARL9170_ERP_RTS: | ||
792 | if (likely(!multi)) | ||
793 | return true; | ||
794 | |||
795 | default: | ||
796 | break; | ||
797 | } | ||
798 | |||
799 | return false; | ||
800 | } | ||
801 | |||
802 | static bool carl9170_tx_cts_check(struct ar9170 *ar, | ||
803 | struct ieee80211_tx_rate *rate) | ||
804 | { | ||
805 | switch (ar->erp_mode) { | ||
806 | case CARL9170_ERP_AUTO: | ||
807 | case CARL9170_ERP_MAC80211: | ||
808 | if (!(rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
809 | break; | ||
810 | |||
811 | case CARL9170_ERP_CTS: | ||
812 | return true; | ||
813 | |||
814 | default: | ||
815 | break; | ||
816 | } | ||
817 | |||
818 | return false; | ||
819 | } | ||
820 | |||
821 | static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | ||
822 | { | ||
823 | struct ieee80211_hdr *hdr; | ||
824 | struct _carl9170_tx_superframe *txc; | ||
825 | struct carl9170_vif_info *cvif; | ||
826 | struct ieee80211_tx_info *info; | ||
827 | struct ieee80211_tx_rate *txrate; | ||
828 | struct ieee80211_sta *sta; | ||
829 | struct carl9170_tx_info *arinfo; | ||
830 | unsigned int hw_queue; | ||
831 | int i; | ||
832 | __le16 mac_tmp; | ||
833 | u16 len; | ||
834 | bool ampdu, no_ack; | ||
835 | |||
836 | BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); | ||
837 | BUILD_BUG_ON(sizeof(struct _carl9170_tx_superdesc) != | ||
838 | CARL9170_TX_SUPERDESC_LEN); | ||
839 | |||
840 | BUILD_BUG_ON(sizeof(struct _ar9170_tx_hwdesc) != | ||
841 | AR9170_TX_HWDESC_LEN); | ||
842 | |||
843 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES); | ||
844 | |||
845 | BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC > | ||
846 | ((CARL9170_TX_SUPER_MISC_VIF_ID >> | ||
847 | CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); | ||
848 | |||
849 | hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)]; | ||
850 | |||
851 | hdr = (void *)skb->data; | ||
852 | info = IEEE80211_SKB_CB(skb); | ||
853 | len = skb->len; | ||
854 | |||
855 | /* | ||
856 | * Note: If the frame was sent through a monitor interface, | ||
857 | * the ieee80211_vif pointer can be NULL. | ||
858 | */ | ||
859 | if (likely(info->control.vif)) | ||
860 | cvif = (void *) info->control.vif->drv_priv; | ||
861 | else | ||
862 | cvif = NULL; | ||
863 | |||
864 | sta = info->control.sta; | ||
865 | |||
866 | txc = (void *)skb_push(skb, sizeof(*txc)); | ||
867 | memset(txc, 0, sizeof(*txc)); | ||
868 | |||
869 | SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue); | ||
870 | |||
871 | if (likely(cvif)) | ||
872 | SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc, cvif->id); | ||
873 | |||
874 | if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)) | ||
875 | txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB; | ||
876 | |||
877 | if (unlikely(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) | ||
878 | txc->s.misc |= CARL9170_TX_SUPER_MISC_ASSIGN_SEQ; | ||
879 | |||
880 | if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) | ||
881 | txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF; | ||
882 | |||
883 | mac_tmp = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | | ||
884 | AR9170_TX_MAC_BACKOFF); | ||
885 | mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) & | ||
886 | AR9170_TX_MAC_QOS); | ||
887 | |||
888 | no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK); | ||
889 | if (unlikely(no_ack)) | ||
890 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); | ||
891 | |||
892 | if (info->control.hw_key) { | ||
893 | len += info->control.hw_key->icv_len; | ||
894 | |||
895 | switch (info->control.hw_key->cipher) { | ||
896 | case WLAN_CIPHER_SUITE_WEP40: | ||
897 | case WLAN_CIPHER_SUITE_WEP104: | ||
898 | case WLAN_CIPHER_SUITE_TKIP: | ||
899 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_RC4); | ||
900 | break; | ||
901 | case WLAN_CIPHER_SUITE_CCMP: | ||
902 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_AES); | ||
903 | break; | ||
904 | default: | ||
905 | WARN_ON(1); | ||
906 | goto err_out; | ||
907 | } | ||
908 | } | ||
909 | |||
910 | ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); | ||
911 | if (ampdu) { | ||
912 | unsigned int density, factor; | ||
913 | |||
914 | if (unlikely(!sta || !cvif)) | ||
915 | goto err_out; | ||
916 | |||
917 | factor = min_t(unsigned int, 1u, sta->ht_cap.ampdu_factor); | ||
918 | density = sta->ht_cap.ampdu_density; | ||
919 | |||
920 | if (density) { | ||
921 | /* | ||
922 | * Watch out! | ||
923 | * | ||
924 | * Otus uses slightly different density values than | ||
925 | * those from the 802.11n spec. | ||
926 | */ | ||
927 | |||
928 | density = max_t(unsigned int, density + 1, 7u); | ||
929 | } | ||
930 | |||
931 | SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY, | ||
932 | txc->s.ampdu_settings, density); | ||
933 | |||
934 | SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, | ||
935 | txc->s.ampdu_settings, factor); | ||
936 | |||
937 | for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { | ||
938 | txrate = &info->control.rates[i]; | ||
939 | if (txrate->idx >= 0) { | ||
940 | txc->s.ri[i] = | ||
941 | CARL9170_TX_SUPER_RI_AMPDU; | ||
942 | |||
943 | if (WARN_ON(!(txrate->flags & | ||
944 | IEEE80211_TX_RC_MCS))) { | ||
945 | /* | ||
946 | * Not sure if it's even possible | ||
947 | * to aggregate non-ht rates with | ||
948 | * this HW. | ||
949 | */ | ||
950 | goto err_out; | ||
951 | } | ||
952 | continue; | ||
953 | } | ||
954 | |||
955 | txrate->idx = 0; | ||
956 | txrate->count = ar->hw->max_rate_tries; | ||
957 | } | ||
958 | |||
959 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
960 | } | ||
961 | |||
962 | /* | ||
963 | * NOTE: For the first rate, the ERP & AMPDU flags are directly | ||
964 | * taken from mac_control. For all fallback rate, the firmware | ||
965 | * updates the mac_control flags from the rate info field. | ||
966 | */ | ||
967 | for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { | ||
968 | txrate = &info->control.rates[i]; | ||
969 | if (txrate->idx < 0) | ||
970 | break; | ||
971 | |||
972 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], | ||
973 | txrate->count); | ||
974 | |||
975 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) | ||
976 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS << | ||
977 | CARL9170_TX_SUPER_RI_ERP_PROT_S); | ||
978 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
979 | txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << | ||
980 | CARL9170_TX_SUPER_RI_ERP_PROT_S); | ||
981 | |||
982 | txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); | ||
983 | } | ||
984 | |||
985 | txrate = &info->control.rates[0]; | ||
986 | SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); | ||
987 | |||
988 | if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) | ||
989 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); | ||
990 | else if (carl9170_tx_cts_check(ar, txrate)) | ||
991 | mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); | ||
992 | |||
993 | txc->s.len = cpu_to_le16(skb->len); | ||
994 | txc->f.length = cpu_to_le16(len + FCS_LEN); | ||
995 | txc->f.mac_control = mac_tmp; | ||
996 | txc->f.phy_control = carl9170_tx_physet(ar, info, txrate); | ||
997 | |||
998 | arinfo = (void *)info->rate_driver_data; | ||
999 | arinfo->timeout = jiffies; | ||
1000 | arinfo->ar = ar; | ||
1001 | kref_init(&arinfo->ref); | ||
1002 | return 0; | ||
1003 | |||
1004 | err_out: | ||
1005 | skb_pull(skb, sizeof(*txc)); | ||
1006 | return -EINVAL; | ||
1007 | } | ||
1008 | |||
1009 | static void carl9170_set_immba(struct ar9170 *ar, struct sk_buff *skb) | ||
1010 | { | ||
1011 | struct _carl9170_tx_superframe *super; | ||
1012 | |||
1013 | super = (void *) skb->data; | ||
1014 | super->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_BA); | ||
1015 | } | ||
1016 | |||
1017 | static void carl9170_set_ampdu_params(struct ar9170 *ar, struct sk_buff *skb) | ||
1018 | { | ||
1019 | struct _carl9170_tx_superframe *super; | ||
1020 | int tmp; | ||
1021 | |||
1022 | super = (void *) skb->data; | ||
1023 | |||
1024 | tmp = (super->s.ampdu_settings & CARL9170_TX_SUPER_AMPDU_DENSITY) << | ||
1025 | CARL9170_TX_SUPER_AMPDU_DENSITY_S; | ||
1026 | |||
1027 | /* | ||
1028 | * If you haven't noticed carl9170_tx_prepare has already filled | ||
1029 | * in all ampdu spacing & factor parameters. | ||
1030 | * Now it's the time to check whenever the settings have to be | ||
1031 | * updated by the firmware, or if everything is still the same. | ||
1032 | * | ||
1033 | * There's no sane way to handle different density values with | ||
1034 | * this hardware, so we may as well just do the compare in the | ||
1035 | * driver. | ||
1036 | */ | ||
1037 | |||
1038 | if (tmp != ar->current_density) { | ||
1039 | ar->current_density = tmp; | ||
1040 | super->s.ampdu_settings |= | ||
1041 | CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY; | ||
1042 | } | ||
1043 | |||
1044 | tmp = (super->s.ampdu_settings & CARL9170_TX_SUPER_AMPDU_FACTOR) << | ||
1045 | CARL9170_TX_SUPER_AMPDU_FACTOR_S; | ||
1046 | |||
1047 | if (tmp != ar->current_factor) { | ||
1048 | ar->current_factor = tmp; | ||
1049 | super->s.ampdu_settings |= | ||
1050 | CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR; | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | static bool carl9170_tx_rate_check(struct ar9170 *ar, struct sk_buff *_dest, | ||
1055 | struct sk_buff *_src) | ||
1056 | { | ||
1057 | struct _carl9170_tx_superframe *dest, *src; | ||
1058 | |||
1059 | dest = (void *) _dest->data; | ||
1060 | src = (void *) _src->data; | ||
1061 | |||
1062 | /* | ||
1063 | * The mac80211 rate control algorithm expects that all MPDUs in | ||
1064 | * an AMPDU share the same tx vectors. | ||
1065 | * This is not really obvious right now, because the hardware | ||
1066 | * does the AMPDU setup according to its own rulebook. | ||
1067 | * Our nicely assembled, strictly monotonic increasing mpdu | ||
1068 | * chains will be broken up, mashed back together... | ||
1069 | */ | ||
1070 | |||
1071 | return (dest->f.phy_control == src->f.phy_control); | ||
1072 | } | ||
1073 | |||
1074 | static void carl9170_tx_ampdu(struct ar9170 *ar) | ||
1075 | { | ||
1076 | struct sk_buff_head agg; | ||
1077 | struct carl9170_sta_tid *tid_info; | ||
1078 | struct sk_buff *skb, *first; | ||
1079 | unsigned int i = 0, done_ampdus = 0; | ||
1080 | u16 seq, queue, tmpssn; | ||
1081 | |||
1082 | atomic_inc(&ar->tx_ampdu_scheduler); | ||
1083 | ar->tx_ampdu_schedule = false; | ||
1084 | |||
1085 | if (atomic_read(&ar->tx_ampdu_upload)) | ||
1086 | return; | ||
1087 | |||
1088 | if (!ar->tx_ampdu_list_len) | ||
1089 | return; | ||
1090 | |||
1091 | __skb_queue_head_init(&agg); | ||
1092 | |||
1093 | rcu_read_lock(); | ||
1094 | tid_info = rcu_dereference(ar->tx_ampdu_iter); | ||
1095 | if (WARN_ON_ONCE(!tid_info)) { | ||
1096 | rcu_read_unlock(); | ||
1097 | return; | ||
1098 | } | ||
1099 | |||
1100 | retry: | ||
1101 | list_for_each_entry_continue_rcu(tid_info, &ar->tx_ampdu_list, list) { | ||
1102 | i++; | ||
1103 | |||
1104 | if (tid_info->state < CARL9170_TID_STATE_PROGRESS) | ||
1105 | continue; | ||
1106 | |||
1107 | queue = TID_TO_WME_AC(tid_info->tid); | ||
1108 | |||
1109 | spin_lock_bh(&tid_info->lock); | ||
1110 | if (tid_info->state != CARL9170_TID_STATE_XMIT) | ||
1111 | goto processed; | ||
1112 | |||
1113 | tid_info->counter++; | ||
1114 | first = skb_peek(&tid_info->queue); | ||
1115 | tmpssn = carl9170_get_seq(first); | ||
1116 | seq = tid_info->snx; | ||
1117 | |||
1118 | if (unlikely(tmpssn != seq)) { | ||
1119 | tid_info->state = CARL9170_TID_STATE_IDLE; | ||
1120 | |||
1121 | goto processed; | ||
1122 | } | ||
1123 | |||
1124 | while ((skb = skb_peek(&tid_info->queue))) { | ||
1125 | /* strict 0, 1, ..., n - 1, n frame sequence order */ | ||
1126 | if (unlikely(carl9170_get_seq(skb) != seq)) | ||
1127 | break; | ||
1128 | |||
1129 | /* don't upload more than AMPDU FACTOR allows. */ | ||
1130 | if (unlikely(SEQ_DIFF(tid_info->snx, tid_info->bsn) >= | ||
1131 | (tid_info->max - 1))) | ||
1132 | break; | ||
1133 | |||
1134 | if (!carl9170_tx_rate_check(ar, skb, first)) | ||
1135 | break; | ||
1136 | |||
1137 | atomic_inc(&ar->tx_ampdu_upload); | ||
1138 | tid_info->snx = seq = SEQ_NEXT(seq); | ||
1139 | __skb_unlink(skb, &tid_info->queue); | ||
1140 | |||
1141 | __skb_queue_tail(&agg, skb); | ||
1142 | |||
1143 | if (skb_queue_len(&agg) >= CARL9170_NUM_TX_AGG_MAX) | ||
1144 | break; | ||
1145 | } | ||
1146 | |||
1147 | if (skb_queue_empty(&tid_info->queue) || | ||
1148 | carl9170_get_seq(skb_peek(&tid_info->queue)) != | ||
1149 | tid_info->snx) { | ||
1150 | /* | ||
1151 | * stop TID, if A-MPDU frames are still missing, | ||
1152 | * or whenever the queue is empty. | ||
1153 | */ | ||
1154 | |||
1155 | tid_info->state = CARL9170_TID_STATE_IDLE; | ||
1156 | } | ||
1157 | done_ampdus++; | ||
1158 | |||
1159 | processed: | ||
1160 | spin_unlock_bh(&tid_info->lock); | ||
1161 | |||
1162 | if (skb_queue_empty(&agg)) | ||
1163 | continue; | ||
1164 | |||
1165 | /* apply ampdu spacing & factor settings */ | ||
1166 | carl9170_set_ampdu_params(ar, skb_peek(&agg)); | ||
1167 | |||
1168 | /* set aggregation push bit */ | ||
1169 | carl9170_set_immba(ar, skb_peek_tail(&agg)); | ||
1170 | |||
1171 | spin_lock_bh(&ar->tx_pending[queue].lock); | ||
1172 | skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]); | ||
1173 | spin_unlock_bh(&ar->tx_pending[queue].lock); | ||
1174 | ar->tx_schedule = true; | ||
1175 | } | ||
1176 | if ((done_ampdus++ == 0) && (i++ == 0)) | ||
1177 | goto retry; | ||
1178 | |||
1179 | rcu_assign_pointer(ar->tx_ampdu_iter, tid_info); | ||
1180 | rcu_read_unlock(); | ||
1181 | } | ||
1182 | |||
1183 | static struct sk_buff *carl9170_tx_pick_skb(struct ar9170 *ar, | ||
1184 | struct sk_buff_head *queue) | ||
1185 | { | ||
1186 | struct sk_buff *skb; | ||
1187 | struct ieee80211_tx_info *info; | ||
1188 | struct carl9170_tx_info *arinfo; | ||
1189 | |||
1190 | BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); | ||
1191 | |||
1192 | spin_lock_bh(&queue->lock); | ||
1193 | skb = skb_peek(queue); | ||
1194 | if (unlikely(!skb)) | ||
1195 | goto err_unlock; | ||
1196 | |||
1197 | if (carl9170_alloc_dev_space(ar, skb)) | ||
1198 | goto err_unlock; | ||
1199 | |||
1200 | __skb_unlink(skb, queue); | ||
1201 | spin_unlock_bh(&queue->lock); | ||
1202 | |||
1203 | info = IEEE80211_SKB_CB(skb); | ||
1204 | arinfo = (void *) info->rate_driver_data; | ||
1205 | |||
1206 | arinfo->timeout = jiffies; | ||
1207 | return skb; | ||
1208 | |||
1209 | err_unlock: | ||
1210 | spin_unlock_bh(&queue->lock); | ||
1211 | return NULL; | ||
1212 | } | ||
1213 | |||
1214 | void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb) | ||
1215 | { | ||
1216 | struct _carl9170_tx_superframe *super; | ||
1217 | uint8_t q = 0; | ||
1218 | |||
1219 | ar->tx_dropped++; | ||
1220 | |||
1221 | super = (void *)skb->data; | ||
1222 | SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, q, | ||
1223 | ar9170_qmap[carl9170_get_queue(ar, skb)]); | ||
1224 | __carl9170_tx_process_status(ar, super->s.cookie, q); | ||
1225 | } | ||
1226 | |||
1227 | static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb) | ||
1228 | { | ||
1229 | struct ieee80211_sta *sta; | ||
1230 | struct carl9170_sta_info *sta_info; | ||
1231 | |||
1232 | rcu_read_lock(); | ||
1233 | sta = __carl9170_get_tx_sta(ar, skb); | ||
1234 | if (!sta) | ||
1235 | goto out_rcu; | ||
1236 | |||
1237 | sta_info = (void *) sta->drv_priv; | ||
1238 | if (unlikely(sta_info->sleeping)) { | ||
1239 | struct ieee80211_tx_info *tx_info; | ||
1240 | |||
1241 | rcu_read_unlock(); | ||
1242 | |||
1243 | tx_info = IEEE80211_SKB_CB(skb); | ||
1244 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1245 | atomic_dec(&ar->tx_ampdu_upload); | ||
1246 | |||
1247 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
1248 | carl9170_tx_status(ar, skb, false); | ||
1249 | return true; | ||
1250 | } | ||
1251 | |||
1252 | out_rcu: | ||
1253 | rcu_read_unlock(); | ||
1254 | return false; | ||
1255 | } | ||
1256 | |||
1257 | static void carl9170_tx(struct ar9170 *ar) | ||
1258 | { | ||
1259 | struct sk_buff *skb; | ||
1260 | unsigned int i, q; | ||
1261 | bool schedule_garbagecollector = false; | ||
1262 | |||
1263 | ar->tx_schedule = false; | ||
1264 | |||
1265 | if (unlikely(!IS_STARTED(ar))) | ||
1266 | return; | ||
1267 | |||
1268 | carl9170_usb_handle_tx_err(ar); | ||
1269 | |||
1270 | for (i = 0; i < ar->hw->queues; i++) { | ||
1271 | while (!skb_queue_empty(&ar->tx_pending[i])) { | ||
1272 | skb = carl9170_tx_pick_skb(ar, &ar->tx_pending[i]); | ||
1273 | if (unlikely(!skb)) | ||
1274 | break; | ||
1275 | |||
1276 | if (unlikely(carl9170_tx_ps_drop(ar, skb))) | ||
1277 | continue; | ||
1278 | |||
1279 | atomic_inc(&ar->tx_total_pending); | ||
1280 | |||
1281 | q = __carl9170_get_queue(ar, i); | ||
1282 | /* | ||
1283 | * NB: tx_status[i] vs. tx_status[q], | ||
1284 | * TODO: Move into pick_skb or alloc_dev_space. | ||
1285 | */ | ||
1286 | skb_queue_tail(&ar->tx_status[q], skb); | ||
1287 | |||
1288 | /* | ||
1289 | * increase ref count to "2". | ||
1290 | * Ref counting is the easiest way to solve the | ||
1291 | * race between the urb's completion routine: | ||
1292 | * carl9170_tx_callback | ||
1293 | * and wlan tx status functions: | ||
1294 | * carl9170_tx_status/janitor. | ||
1295 | */ | ||
1296 | carl9170_tx_get_skb(skb); | ||
1297 | |||
1298 | carl9170_usb_tx(ar, skb); | ||
1299 | schedule_garbagecollector = true; | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | if (!schedule_garbagecollector) | ||
1304 | return; | ||
1305 | |||
1306 | ieee80211_queue_delayed_work(ar->hw, &ar->tx_janitor, | ||
1307 | msecs_to_jiffies(CARL9170_TX_TIMEOUT)); | ||
1308 | } | ||
1309 | |||
1310 | static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, | ||
1311 | struct ieee80211_sta *sta, struct sk_buff *skb) | ||
1312 | { | ||
1313 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
1314 | struct carl9170_sta_info *sta_info; | ||
1315 | struct carl9170_sta_tid *agg; | ||
1316 | struct sk_buff *iter; | ||
1317 | u16 tid, seq, qseq, off; | ||
1318 | bool run = false; | ||
1319 | |||
1320 | tid = carl9170_get_tid(skb); | ||
1321 | seq = carl9170_get_seq(skb); | ||
1322 | sta_info = (void *) sta->drv_priv; | ||
1323 | |||
1324 | rcu_read_lock(); | ||
1325 | agg = rcu_dereference(sta_info->agg[tid]); | ||
1326 | |||
1327 | if (!agg) | ||
1328 | goto err_unlock_rcu; | ||
1329 | |||
1330 | spin_lock_bh(&agg->lock); | ||
1331 | if (unlikely(agg->state < CARL9170_TID_STATE_IDLE)) | ||
1332 | goto err_unlock; | ||
1333 | |||
1334 | /* check if sequence is within the BA window */ | ||
1335 | if (unlikely(!BAW_WITHIN(agg->bsn, CARL9170_BAW_BITS, seq))) | ||
1336 | goto err_unlock; | ||
1337 | |||
1338 | if (WARN_ON_ONCE(!BAW_WITHIN(agg->snx, CARL9170_BAW_BITS, seq))) | ||
1339 | goto err_unlock; | ||
1340 | |||
1341 | off = SEQ_DIFF(seq, agg->bsn); | ||
1342 | if (WARN_ON_ONCE(test_and_set_bit(off, agg->bitmap))) | ||
1343 | goto err_unlock; | ||
1344 | |||
1345 | if (likely(BAW_WITHIN(agg->hsn, CARL9170_BAW_BITS, seq))) { | ||
1346 | __skb_queue_tail(&agg->queue, skb); | ||
1347 | agg->hsn = seq; | ||
1348 | goto queued; | ||
1349 | } | ||
1350 | |||
1351 | skb_queue_reverse_walk(&agg->queue, iter) { | ||
1352 | qseq = carl9170_get_seq(iter); | ||
1353 | |||
1354 | if (BAW_WITHIN(qseq, CARL9170_BAW_BITS, seq)) { | ||
1355 | __skb_queue_after(&agg->queue, iter, skb); | ||
1356 | goto queued; | ||
1357 | } | ||
1358 | } | ||
1359 | |||
1360 | __skb_queue_head(&agg->queue, skb); | ||
1361 | queued: | ||
1362 | |||
1363 | if (unlikely(agg->state != CARL9170_TID_STATE_XMIT)) { | ||
1364 | if (agg->snx == carl9170_get_seq(skb_peek(&agg->queue))) { | ||
1365 | agg->state = CARL9170_TID_STATE_XMIT; | ||
1366 | run = true; | ||
1367 | } | ||
1368 | } | ||
1369 | |||
1370 | spin_unlock_bh(&agg->lock); | ||
1371 | rcu_read_unlock(); | ||
1372 | |||
1373 | return run; | ||
1374 | |||
1375 | err_unlock: | ||
1376 | spin_unlock_bh(&agg->lock); | ||
1377 | |||
1378 | err_unlock_rcu: | ||
1379 | rcu_read_unlock(); | ||
1380 | super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1381 | carl9170_tx_status(ar, skb, false); | ||
1382 | ar->tx_dropped++; | ||
1383 | return false; | ||
1384 | } | ||
1385 | |||
1386 | void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1387 | { | ||
1388 | struct ar9170 *ar = hw->priv; | ||
1389 | struct ieee80211_tx_info *info; | ||
1390 | struct ieee80211_sta *sta; | ||
1391 | bool run; | ||
1392 | |||
1393 | if (unlikely(!IS_STARTED(ar))) | ||
1394 | goto err_free; | ||
1395 | |||
1396 | info = IEEE80211_SKB_CB(skb); | ||
1397 | sta = info->control.sta; | ||
1398 | |||
1399 | if (unlikely(carl9170_tx_prepare(ar, skb))) | ||
1400 | goto err_free; | ||
1401 | |||
1402 | carl9170_tx_accounting(ar, skb); | ||
1403 | /* | ||
1404 | * from now on, one has to use carl9170_tx_status to free | ||
1405 | * all ressouces which are associated with the frame. | ||
1406 | */ | ||
1407 | |||
1408 | if (sta) { | ||
1409 | struct carl9170_sta_info *stai = (void *) sta->drv_priv; | ||
1410 | atomic_inc(&stai->pending_frames); | ||
1411 | } | ||
1412 | |||
1413 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
1414 | run = carl9170_tx_ampdu_queue(ar, sta, skb); | ||
1415 | if (run) | ||
1416 | carl9170_tx_ampdu(ar); | ||
1417 | |||
1418 | } else { | ||
1419 | unsigned int queue = skb_get_queue_mapping(skb); | ||
1420 | |||
1421 | skb_queue_tail(&ar->tx_pending[queue], skb); | ||
1422 | } | ||
1423 | |||
1424 | carl9170_tx(ar); | ||
1425 | return; | ||
1426 | |||
1427 | err_free: | ||
1428 | ar->tx_dropped++; | ||
1429 | dev_kfree_skb_any(skb); | ||
1430 | } | ||
1431 | |||
1432 | void carl9170_tx_scheduler(struct ar9170 *ar) | ||
1433 | { | ||
1434 | |||
1435 | if (ar->tx_ampdu_schedule) | ||
1436 | carl9170_tx_ampdu(ar); | ||
1437 | |||
1438 | if (ar->tx_schedule) | ||
1439 | carl9170_tx(ar); | ||
1440 | } | ||
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c new file mode 100644 index 000000000000..333b69ef2ae2 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/usb.c | |||
@@ -0,0 +1,1175 @@ | |||
1 | /* | ||
2 | * Atheros CARL9170 driver | ||
3 | * | ||
4 | * USB - frontend | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; see the file COPYING. If not, see | ||
21 | * http://www.gnu.org/licenses/. | ||
22 | * | ||
23 | * This file incorporates work covered by the following copyright and | ||
24 | * permission notice: | ||
25 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
26 | * | ||
27 | * Permission to use, copy, modify, and/or distribute this software for any | ||
28 | * purpose with or without fee is hereby granted, provided that the above | ||
29 | * copyright notice and this permission notice appear in all copies. | ||
30 | * | ||
31 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
32 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
33 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
34 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
35 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
36 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
37 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/module.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/usb.h> | ||
43 | #include <linux/firmware.h> | ||
44 | #include <linux/etherdevice.h> | ||
45 | #include <linux/device.h> | ||
46 | #include <net/mac80211.h> | ||
47 | #include "carl9170.h" | ||
48 | #include "cmd.h" | ||
49 | #include "hw.h" | ||
50 | #include "fwcmd.h" | ||
51 | |||
52 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
53 | MODULE_AUTHOR("Christian Lamparter <chunkeey@googlemail.com>"); | ||
54 | MODULE_LICENSE("GPL"); | ||
55 | MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); | ||
56 | MODULE_FIRMWARE(CARL9170FW_NAME); | ||
57 | MODULE_ALIAS("ar9170usb"); | ||
58 | MODULE_ALIAS("arusb_lnx"); | ||
59 | |||
60 | /* | ||
61 | * Note: | ||
62 | * | ||
63 | * Always update our wiki's device list (located at: | ||
64 | * http://wireless.kernel.org/en/users/Drivers/ar9170/devices ), | ||
65 | * whenever you add a new device. | ||
66 | */ | ||
67 | static struct usb_device_id carl9170_usb_ids[] = { | ||
68 | /* Atheros 9170 */ | ||
69 | { USB_DEVICE(0x0cf3, 0x9170) }, | ||
70 | /* Atheros TG121N */ | ||
71 | { USB_DEVICE(0x0cf3, 0x1001) }, | ||
72 | /* TP-Link TL-WN821N v2 */ | ||
73 | { USB_DEVICE(0x0cf3, 0x1002), .driver_info = CARL9170_WPS_BUTTON | | ||
74 | CARL9170_ONE_LED }, | ||
75 | /* 3Com Dual Band 802.11n USB Adapter */ | ||
76 | { USB_DEVICE(0x0cf3, 0x1010) }, | ||
77 | /* H3C Dual Band 802.11n USB Adapter */ | ||
78 | { USB_DEVICE(0x0cf3, 0x1011) }, | ||
79 | /* Cace Airpcap NX */ | ||
80 | { USB_DEVICE(0xcace, 0x0300) }, | ||
81 | /* D-Link DWA 160 A1 */ | ||
82 | { USB_DEVICE(0x07d1, 0x3c10) }, | ||
83 | /* D-Link DWA 160 A2 */ | ||
84 | { USB_DEVICE(0x07d1, 0x3a09) }, | ||
85 | /* D-Link DWA 130 D */ | ||
86 | { USB_DEVICE(0x07d1, 0x3a0f) }, | ||
87 | /* Netgear WNA1000 */ | ||
88 | { USB_DEVICE(0x0846, 0x9040) }, | ||
89 | /* Netgear WNDA3100 (v1) */ | ||
90 | { USB_DEVICE(0x0846, 0x9010) }, | ||
91 | /* Netgear WN111 v2 */ | ||
92 | { USB_DEVICE(0x0846, 0x9001), .driver_info = CARL9170_ONE_LED }, | ||
93 | /* Zydas ZD1221 */ | ||
94 | { USB_DEVICE(0x0ace, 0x1221) }, | ||
95 | /* Proxim ORiNOCO 802.11n USB */ | ||
96 | { USB_DEVICE(0x1435, 0x0804) }, | ||
97 | /* WNC Generic 11n USB Dongle */ | ||
98 | { USB_DEVICE(0x1435, 0x0326) }, | ||
99 | /* ZyXEL NWD271N */ | ||
100 | { USB_DEVICE(0x0586, 0x3417) }, | ||
101 | /* Z-Com UB81 BG */ | ||
102 | { USB_DEVICE(0x0cde, 0x0023) }, | ||
103 | /* Z-Com UB82 ABG */ | ||
104 | { USB_DEVICE(0x0cde, 0x0026) }, | ||
105 | /* Sphairon Homelink 1202 */ | ||
106 | { USB_DEVICE(0x0cde, 0x0027) }, | ||
107 | /* Arcadyan WN7512 */ | ||
108 | { USB_DEVICE(0x083a, 0xf522) }, | ||
109 | /* Planex GWUS300 */ | ||
110 | { USB_DEVICE(0x2019, 0x5304) }, | ||
111 | /* IO-Data WNGDNUS2 */ | ||
112 | { USB_DEVICE(0x04bb, 0x093f) }, | ||
113 | /* NEC WL300NU-G */ | ||
114 | { USB_DEVICE(0x0409, 0x0249) }, | ||
115 | /* NEC WL300NU-AG */ | ||
116 | { USB_DEVICE(0x0409, 0x02b4) }, | ||
117 | /* AVM FRITZ!WLAN USB Stick N */ | ||
118 | { USB_DEVICE(0x057c, 0x8401) }, | ||
119 | /* AVM FRITZ!WLAN USB Stick N 2.4 */ | ||
120 | { USB_DEVICE(0x057c, 0x8402) }, | ||
121 | /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */ | ||
122 | { USB_DEVICE(0x1668, 0x1200) }, | ||
123 | /* Airlive X.USB a/b/g/n */ | ||
124 | { USB_DEVICE(0x1b75, 0x9170) }, | ||
125 | |||
126 | /* terminate */ | ||
127 | {} | ||
128 | }; | ||
129 | MODULE_DEVICE_TABLE(usb, carl9170_usb_ids); | ||
130 | |||
131 | static void carl9170_usb_submit_data_urb(struct ar9170 *ar) | ||
132 | { | ||
133 | struct urb *urb; | ||
134 | int err; | ||
135 | |||
136 | if (atomic_inc_return(&ar->tx_anch_urbs) > AR9170_NUM_TX_URBS) | ||
137 | goto err_acc; | ||
138 | |||
139 | urb = usb_get_from_anchor(&ar->tx_wait); | ||
140 | if (!urb) | ||
141 | goto err_acc; | ||
142 | |||
143 | usb_anchor_urb(urb, &ar->tx_anch); | ||
144 | |||
145 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
146 | if (unlikely(err)) { | ||
147 | if (net_ratelimit()) { | ||
148 | dev_err(&ar->udev->dev, "tx submit failed (%d)\n", | ||
149 | urb->status); | ||
150 | } | ||
151 | |||
152 | usb_unanchor_urb(urb); | ||
153 | usb_anchor_urb(urb, &ar->tx_err); | ||
154 | } | ||
155 | |||
156 | usb_free_urb(urb); | ||
157 | |||
158 | if (likely(err == 0)) | ||
159 | return; | ||
160 | |||
161 | err_acc: | ||
162 | atomic_dec(&ar->tx_anch_urbs); | ||
163 | } | ||
164 | |||
165 | static void carl9170_usb_tx_data_complete(struct urb *urb) | ||
166 | { | ||
167 | struct ar9170 *ar = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | ||
168 | |||
169 | if (WARN_ON_ONCE(!ar)) { | ||
170 | dev_kfree_skb_irq(urb->context); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | atomic_dec(&ar->tx_anch_urbs); | ||
175 | |||
176 | switch (urb->status) { | ||
177 | /* everything is fine */ | ||
178 | case 0: | ||
179 | carl9170_tx_callback(ar, (void *)urb->context); | ||
180 | break; | ||
181 | |||
182 | /* disconnect */ | ||
183 | case -ENOENT: | ||
184 | case -ECONNRESET: | ||
185 | case -ENODEV: | ||
186 | case -ESHUTDOWN: | ||
187 | /* | ||
188 | * Defer the frame clean-up to the tasklet worker. | ||
189 | * This is necessary, because carl9170_tx_drop | ||
190 | * does not work in an irqsave context. | ||
191 | */ | ||
192 | usb_anchor_urb(urb, &ar->tx_err); | ||
193 | return; | ||
194 | |||
195 | /* a random transmission error has occurred? */ | ||
196 | default: | ||
197 | if (net_ratelimit()) { | ||
198 | dev_err(&ar->udev->dev, "tx failed (%d)\n", | ||
199 | urb->status); | ||
200 | } | ||
201 | |||
202 | usb_anchor_urb(urb, &ar->tx_err); | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | if (likely(IS_STARTED(ar))) | ||
207 | carl9170_usb_submit_data_urb(ar); | ||
208 | } | ||
209 | |||
210 | static int carl9170_usb_submit_cmd_urb(struct ar9170 *ar) | ||
211 | { | ||
212 | struct urb *urb; | ||
213 | int err; | ||
214 | |||
215 | if (atomic_inc_return(&ar->tx_cmd_urbs) != 1) { | ||
216 | atomic_dec(&ar->tx_cmd_urbs); | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | urb = usb_get_from_anchor(&ar->tx_cmd); | ||
221 | if (!urb) { | ||
222 | atomic_dec(&ar->tx_cmd_urbs); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | usb_anchor_urb(urb, &ar->tx_anch); | ||
227 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
228 | if (unlikely(err)) { | ||
229 | usb_unanchor_urb(urb); | ||
230 | atomic_dec(&ar->tx_cmd_urbs); | ||
231 | } | ||
232 | usb_free_urb(urb); | ||
233 | |||
234 | return err; | ||
235 | } | ||
236 | |||
237 | static void carl9170_usb_cmd_complete(struct urb *urb) | ||
238 | { | ||
239 | struct ar9170 *ar = urb->context; | ||
240 | int err = 0; | ||
241 | |||
242 | if (WARN_ON_ONCE(!ar)) | ||
243 | return; | ||
244 | |||
245 | atomic_dec(&ar->tx_cmd_urbs); | ||
246 | |||
247 | switch (urb->status) { | ||
248 | /* everything is fine */ | ||
249 | case 0: | ||
250 | break; | ||
251 | |||
252 | /* disconnect */ | ||
253 | case -ENOENT: | ||
254 | case -ECONNRESET: | ||
255 | case -ENODEV: | ||
256 | case -ESHUTDOWN: | ||
257 | return; | ||
258 | |||
259 | default: | ||
260 | err = urb->status; | ||
261 | break; | ||
262 | } | ||
263 | |||
264 | if (!IS_INITIALIZED(ar)) | ||
265 | return; | ||
266 | |||
267 | if (err) | ||
268 | dev_err(&ar->udev->dev, "submit cmd cb failed (%d).\n", err); | ||
269 | |||
270 | err = carl9170_usb_submit_cmd_urb(ar); | ||
271 | if (err) | ||
272 | dev_err(&ar->udev->dev, "submit cmd failed (%d).\n", err); | ||
273 | } | ||
274 | |||
275 | static void carl9170_usb_rx_irq_complete(struct urb *urb) | ||
276 | { | ||
277 | struct ar9170 *ar = urb->context; | ||
278 | |||
279 | if (WARN_ON_ONCE(!ar)) | ||
280 | return; | ||
281 | |||
282 | switch (urb->status) { | ||
283 | /* everything is fine */ | ||
284 | case 0: | ||
285 | break; | ||
286 | |||
287 | /* disconnect */ | ||
288 | case -ENOENT: | ||
289 | case -ECONNRESET: | ||
290 | case -ENODEV: | ||
291 | case -ESHUTDOWN: | ||
292 | return; | ||
293 | |||
294 | default: | ||
295 | goto resubmit; | ||
296 | } | ||
297 | |||
298 | carl9170_handle_command_response(ar, urb->transfer_buffer, | ||
299 | urb->actual_length); | ||
300 | |||
301 | resubmit: | ||
302 | usb_anchor_urb(urb, &ar->rx_anch); | ||
303 | if (unlikely(usb_submit_urb(urb, GFP_ATOMIC))) | ||
304 | usb_unanchor_urb(urb); | ||
305 | } | ||
306 | |||
307 | static int carl9170_usb_submit_rx_urb(struct ar9170 *ar, gfp_t gfp) | ||
308 | { | ||
309 | struct urb *urb; | ||
310 | int err = 0, runs = 0; | ||
311 | |||
312 | while ((atomic_read(&ar->rx_anch_urbs) < AR9170_NUM_RX_URBS) && | ||
313 | (runs++ < AR9170_NUM_RX_URBS)) { | ||
314 | err = -ENOSPC; | ||
315 | urb = usb_get_from_anchor(&ar->rx_pool); | ||
316 | if (urb) { | ||
317 | usb_anchor_urb(urb, &ar->rx_anch); | ||
318 | err = usb_submit_urb(urb, gfp); | ||
319 | if (unlikely(err)) { | ||
320 | usb_unanchor_urb(urb); | ||
321 | usb_anchor_urb(urb, &ar->rx_pool); | ||
322 | } else { | ||
323 | atomic_dec(&ar->rx_pool_urbs); | ||
324 | atomic_inc(&ar->rx_anch_urbs); | ||
325 | } | ||
326 | usb_free_urb(urb); | ||
327 | } | ||
328 | } | ||
329 | |||
330 | return err; | ||
331 | } | ||
332 | |||
333 | static void carl9170_usb_rx_work(struct ar9170 *ar) | ||
334 | { | ||
335 | struct urb *urb; | ||
336 | int i; | ||
337 | |||
338 | for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) { | ||
339 | urb = usb_get_from_anchor(&ar->rx_work); | ||
340 | if (!urb) | ||
341 | break; | ||
342 | |||
343 | atomic_dec(&ar->rx_work_urbs); | ||
344 | if (IS_INITIALIZED(ar)) { | ||
345 | carl9170_rx(ar, urb->transfer_buffer, | ||
346 | urb->actual_length); | ||
347 | } | ||
348 | |||
349 | usb_anchor_urb(urb, &ar->rx_pool); | ||
350 | atomic_inc(&ar->rx_pool_urbs); | ||
351 | |||
352 | usb_free_urb(urb); | ||
353 | |||
354 | carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | void carl9170_usb_handle_tx_err(struct ar9170 *ar) | ||
359 | { | ||
360 | struct urb *urb; | ||
361 | |||
362 | while ((urb = usb_get_from_anchor(&ar->tx_err))) { | ||
363 | struct sk_buff *skb = (void *)urb->context; | ||
364 | |||
365 | carl9170_tx_drop(ar, skb); | ||
366 | carl9170_tx_callback(ar, skb); | ||
367 | usb_free_urb(urb); | ||
368 | } | ||
369 | } | ||
370 | |||
371 | static void carl9170_usb_tasklet(unsigned long data) | ||
372 | { | ||
373 | struct ar9170 *ar = (struct ar9170 *) data; | ||
374 | |||
375 | if (!IS_INITIALIZED(ar)) | ||
376 | return; | ||
377 | |||
378 | carl9170_usb_rx_work(ar); | ||
379 | |||
380 | /* | ||
381 | * Strictly speaking: The tx scheduler is not part of the USB system. | ||
382 | * But the rx worker returns frames back to the mac80211-stack and | ||
383 | * this is the _perfect_ place to generate the next transmissions. | ||
384 | */ | ||
385 | if (IS_STARTED(ar)) | ||
386 | carl9170_tx_scheduler(ar); | ||
387 | } | ||
388 | |||
389 | static void carl9170_usb_rx_complete(struct urb *urb) | ||
390 | { | ||
391 | struct ar9170 *ar = (struct ar9170 *)urb->context; | ||
392 | int err; | ||
393 | |||
394 | if (WARN_ON_ONCE(!ar)) | ||
395 | return; | ||
396 | |||
397 | atomic_dec(&ar->rx_anch_urbs); | ||
398 | |||
399 | switch (urb->status) { | ||
400 | case 0: | ||
401 | /* rx path */ | ||
402 | usb_anchor_urb(urb, &ar->rx_work); | ||
403 | atomic_inc(&ar->rx_work_urbs); | ||
404 | break; | ||
405 | |||
406 | case -ENOENT: | ||
407 | case -ECONNRESET: | ||
408 | case -ENODEV: | ||
409 | case -ESHUTDOWN: | ||
410 | /* handle disconnect events*/ | ||
411 | return; | ||
412 | |||
413 | default: | ||
414 | /* handle all other errors */ | ||
415 | usb_anchor_urb(urb, &ar->rx_pool); | ||
416 | atomic_inc(&ar->rx_pool_urbs); | ||
417 | break; | ||
418 | } | ||
419 | |||
420 | err = carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC); | ||
421 | if (unlikely(err)) { | ||
422 | /* | ||
423 | * usb_submit_rx_urb reported a problem. | ||
424 | * In case this is due to a rx buffer shortage, | ||
425 | * elevate the tasklet worker priority to | ||
426 | * the highest available level. | ||
427 | */ | ||
428 | tasklet_hi_schedule(&ar->usb_tasklet); | ||
429 | |||
430 | if (atomic_read(&ar->rx_anch_urbs) == 0) { | ||
431 | /* | ||
432 | * The system is too slow to cope with | ||
433 | * the enormous workload. We have simply | ||
434 | * run out of active rx urbs and this | ||
435 | * unfortunately leads to an unpredictable | ||
436 | * device. | ||
437 | */ | ||
438 | |||
439 | ieee80211_queue_work(ar->hw, &ar->ping_work); | ||
440 | } | ||
441 | } else { | ||
442 | /* | ||
443 | * Using anything less than _high_ priority absolutely | ||
444 | * kills the rx performance my UP-System... | ||
445 | */ | ||
446 | tasklet_hi_schedule(&ar->usb_tasklet); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | static struct urb *carl9170_usb_alloc_rx_urb(struct ar9170 *ar, gfp_t gfp) | ||
451 | { | ||
452 | struct urb *urb; | ||
453 | void *buf; | ||
454 | |||
455 | buf = kmalloc(ar->fw.rx_size, gfp); | ||
456 | if (!buf) | ||
457 | return NULL; | ||
458 | |||
459 | urb = usb_alloc_urb(0, gfp); | ||
460 | if (!urb) { | ||
461 | kfree(buf); | ||
462 | return NULL; | ||
463 | } | ||
464 | |||
465 | usb_fill_bulk_urb(urb, ar->udev, usb_rcvbulkpipe(ar->udev, | ||
466 | AR9170_USB_EP_RX), buf, ar->fw.rx_size, | ||
467 | carl9170_usb_rx_complete, ar); | ||
468 | |||
469 | urb->transfer_flags |= URB_FREE_BUFFER; | ||
470 | |||
471 | return urb; | ||
472 | } | ||
473 | |||
474 | static int carl9170_usb_send_rx_irq_urb(struct ar9170 *ar) | ||
475 | { | ||
476 | struct urb *urb = NULL; | ||
477 | void *ibuf; | ||
478 | int err = -ENOMEM; | ||
479 | |||
480 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
481 | if (!urb) | ||
482 | goto out; | ||
483 | |||
484 | ibuf = kmalloc(AR9170_USB_EP_CTRL_MAX, GFP_KERNEL); | ||
485 | if (!ibuf) | ||
486 | goto out; | ||
487 | |||
488 | usb_fill_int_urb(urb, ar->udev, usb_rcvintpipe(ar->udev, | ||
489 | AR9170_USB_EP_IRQ), ibuf, AR9170_USB_EP_CTRL_MAX, | ||
490 | carl9170_usb_rx_irq_complete, ar, 1); | ||
491 | |||
492 | urb->transfer_flags |= URB_FREE_BUFFER; | ||
493 | |||
494 | usb_anchor_urb(urb, &ar->rx_anch); | ||
495 | err = usb_submit_urb(urb, GFP_KERNEL); | ||
496 | if (err) | ||
497 | usb_unanchor_urb(urb); | ||
498 | |||
499 | out: | ||
500 | usb_free_urb(urb); | ||
501 | return err; | ||
502 | } | ||
503 | |||
504 | static int carl9170_usb_init_rx_bulk_urbs(struct ar9170 *ar) | ||
505 | { | ||
506 | struct urb *urb; | ||
507 | int i, err = -EINVAL; | ||
508 | |||
509 | /* | ||
510 | * The driver actively maintains a second shadow | ||
511 | * pool for inactive, but fully-prepared rx urbs. | ||
512 | * | ||
513 | * The pool should help the driver to master huge | ||
514 | * workload spikes without running the risk of | ||
515 | * undersupplying the hardware or wasting time by | ||
516 | * processing rx data (streams) inside the urb | ||
517 | * completion (hardirq context). | ||
518 | */ | ||
519 | for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) { | ||
520 | urb = carl9170_usb_alloc_rx_urb(ar, GFP_KERNEL); | ||
521 | if (!urb) { | ||
522 | err = -ENOMEM; | ||
523 | goto err_out; | ||
524 | } | ||
525 | |||
526 | usb_anchor_urb(urb, &ar->rx_pool); | ||
527 | atomic_inc(&ar->rx_pool_urbs); | ||
528 | usb_free_urb(urb); | ||
529 | } | ||
530 | |||
531 | err = carl9170_usb_submit_rx_urb(ar, GFP_KERNEL); | ||
532 | if (err) | ||
533 | goto err_out; | ||
534 | |||
535 | /* the device now waiting for the firmware. */ | ||
536 | carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE); | ||
537 | return 0; | ||
538 | |||
539 | err_out: | ||
540 | |||
541 | usb_scuttle_anchored_urbs(&ar->rx_pool); | ||
542 | usb_scuttle_anchored_urbs(&ar->rx_work); | ||
543 | usb_kill_anchored_urbs(&ar->rx_anch); | ||
544 | return err; | ||
545 | } | ||
546 | |||
547 | static int carl9170_usb_flush(struct ar9170 *ar) | ||
548 | { | ||
549 | struct urb *urb; | ||
550 | int ret, err = 0; | ||
551 | |||
552 | while ((urb = usb_get_from_anchor(&ar->tx_wait))) { | ||
553 | struct sk_buff *skb = (void *)urb->context; | ||
554 | carl9170_tx_drop(ar, skb); | ||
555 | carl9170_tx_callback(ar, skb); | ||
556 | usb_free_urb(urb); | ||
557 | } | ||
558 | |||
559 | ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, 1000); | ||
560 | if (ret == 0) | ||
561 | err = -ETIMEDOUT; | ||
562 | |||
563 | /* lets wait a while until the tx - queues are dried out */ | ||
564 | ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, 1000); | ||
565 | if (ret == 0) | ||
566 | err = -ETIMEDOUT; | ||
567 | |||
568 | usb_kill_anchored_urbs(&ar->tx_anch); | ||
569 | carl9170_usb_handle_tx_err(ar); | ||
570 | |||
571 | return err; | ||
572 | } | ||
573 | |||
574 | static void carl9170_usb_cancel_urbs(struct ar9170 *ar) | ||
575 | { | ||
576 | int err; | ||
577 | |||
578 | carl9170_set_state(ar, CARL9170_UNKNOWN_STATE); | ||
579 | |||
580 | err = carl9170_usb_flush(ar); | ||
581 | if (err) | ||
582 | dev_err(&ar->udev->dev, "stuck tx urbs!\n"); | ||
583 | |||
584 | usb_poison_anchored_urbs(&ar->tx_anch); | ||
585 | carl9170_usb_handle_tx_err(ar); | ||
586 | usb_poison_anchored_urbs(&ar->rx_anch); | ||
587 | |||
588 | tasklet_kill(&ar->usb_tasklet); | ||
589 | |||
590 | usb_scuttle_anchored_urbs(&ar->rx_work); | ||
591 | usb_scuttle_anchored_urbs(&ar->rx_pool); | ||
592 | usb_scuttle_anchored_urbs(&ar->tx_cmd); | ||
593 | } | ||
594 | |||
595 | int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd, | ||
596 | const bool free_buf) | ||
597 | { | ||
598 | struct urb *urb; | ||
599 | int err = 0; | ||
600 | |||
601 | if (!IS_INITIALIZED(ar)) { | ||
602 | err = -EPERM; | ||
603 | goto err_free; | ||
604 | } | ||
605 | |||
606 | if (WARN_ON(cmd->hdr.len > CARL9170_MAX_CMD_LEN - 4)) { | ||
607 | err = -EINVAL; | ||
608 | goto err_free; | ||
609 | } | ||
610 | |||
611 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
612 | if (!urb) { | ||
613 | err = -ENOMEM; | ||
614 | goto err_free; | ||
615 | } | ||
616 | |||
617 | usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev, | ||
618 | AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4, | ||
619 | carl9170_usb_cmd_complete, ar, 1); | ||
620 | |||
621 | if (free_buf) | ||
622 | urb->transfer_flags |= URB_FREE_BUFFER; | ||
623 | |||
624 | usb_anchor_urb(urb, &ar->tx_cmd); | ||
625 | usb_free_urb(urb); | ||
626 | |||
627 | return carl9170_usb_submit_cmd_urb(ar); | ||
628 | |||
629 | err_free: | ||
630 | if (free_buf) | ||
631 | kfree(cmd); | ||
632 | |||
633 | return err; | ||
634 | } | ||
635 | |||
636 | int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd, | ||
637 | unsigned int plen, void *payload, unsigned int outlen, void *out) | ||
638 | { | ||
639 | int err = -ENOMEM; | ||
640 | |||
641 | if (!IS_ACCEPTING_CMD(ar)) | ||
642 | return -EIO; | ||
643 | |||
644 | if (!(cmd & CARL9170_CMD_ASYNC_FLAG)) | ||
645 | might_sleep(); | ||
646 | |||
647 | ar->cmd.hdr.len = plen; | ||
648 | ar->cmd.hdr.cmd = cmd; | ||
649 | /* writing multiple regs fills this buffer already */ | ||
650 | if (plen && payload != (u8 *)(ar->cmd.data)) | ||
651 | memcpy(ar->cmd.data, payload, plen); | ||
652 | |||
653 | spin_lock_bh(&ar->cmd_lock); | ||
654 | ar->readbuf = (u8 *)out; | ||
655 | ar->readlen = outlen; | ||
656 | spin_unlock_bh(&ar->cmd_lock); | ||
657 | |||
658 | err = __carl9170_exec_cmd(ar, &ar->cmd, false); | ||
659 | |||
660 | if (!(cmd & CARL9170_CMD_ASYNC_FLAG)) { | ||
661 | err = wait_for_completion_timeout(&ar->cmd_wait, HZ); | ||
662 | if (err == 0) { | ||
663 | err = -ETIMEDOUT; | ||
664 | goto err_unbuf; | ||
665 | } | ||
666 | |||
667 | if (ar->readlen != outlen) { | ||
668 | err = -EMSGSIZE; | ||
669 | goto err_unbuf; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | return 0; | ||
674 | |||
675 | err_unbuf: | ||
676 | /* Maybe the device was removed in the moment we were waiting? */ | ||
677 | if (IS_STARTED(ar)) { | ||
678 | dev_err(&ar->udev->dev, "no command feedback " | ||
679 | "received (%d).\n", err); | ||
680 | |||
681 | /* provide some maybe useful debug information */ | ||
682 | print_hex_dump_bytes("carl9170 cmd: ", DUMP_PREFIX_NONE, | ||
683 | &ar->cmd, plen + 4); | ||
684 | |||
685 | carl9170_restart(ar, CARL9170_RR_COMMAND_TIMEOUT); | ||
686 | } | ||
687 | |||
688 | /* invalidate to avoid completing the next command prematurely */ | ||
689 | spin_lock_bh(&ar->cmd_lock); | ||
690 | ar->readbuf = NULL; | ||
691 | ar->readlen = 0; | ||
692 | spin_unlock_bh(&ar->cmd_lock); | ||
693 | |||
694 | return err; | ||
695 | } | ||
696 | |||
697 | void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) | ||
698 | { | ||
699 | struct urb *urb; | ||
700 | struct ar9170_stream *tx_stream; | ||
701 | void *data; | ||
702 | unsigned int len; | ||
703 | |||
704 | if (!IS_STARTED(ar)) | ||
705 | goto err_drop; | ||
706 | |||
707 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
708 | if (!urb) | ||
709 | goto err_drop; | ||
710 | |||
711 | if (ar->fw.tx_stream) { | ||
712 | tx_stream = (void *) (skb->data - sizeof(*tx_stream)); | ||
713 | |||
714 | len = skb->len + sizeof(*tx_stream); | ||
715 | tx_stream->length = cpu_to_le16(len); | ||
716 | tx_stream->tag = cpu_to_le16(AR9170_TX_STREAM_TAG); | ||
717 | data = tx_stream; | ||
718 | } else { | ||
719 | data = skb->data; | ||
720 | len = skb->len; | ||
721 | } | ||
722 | |||
723 | usb_fill_bulk_urb(urb, ar->udev, usb_sndbulkpipe(ar->udev, | ||
724 | AR9170_USB_EP_TX), data, len, | ||
725 | carl9170_usb_tx_data_complete, skb); | ||
726 | |||
727 | urb->transfer_flags |= URB_ZERO_PACKET; | ||
728 | |||
729 | usb_anchor_urb(urb, &ar->tx_wait); | ||
730 | |||
731 | usb_free_urb(urb); | ||
732 | |||
733 | carl9170_usb_submit_data_urb(ar); | ||
734 | return; | ||
735 | |||
736 | err_drop: | ||
737 | carl9170_tx_drop(ar, skb); | ||
738 | carl9170_tx_callback(ar, skb); | ||
739 | } | ||
740 | |||
741 | static void carl9170_release_firmware(struct ar9170 *ar) | ||
742 | { | ||
743 | if (ar->fw.fw) { | ||
744 | release_firmware(ar->fw.fw); | ||
745 | memset(&ar->fw, 0, sizeof(ar->fw)); | ||
746 | } | ||
747 | } | ||
748 | |||
749 | void carl9170_usb_stop(struct ar9170 *ar) | ||
750 | { | ||
751 | int ret; | ||
752 | |||
753 | carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STOPPED); | ||
754 | |||
755 | ret = carl9170_usb_flush(ar); | ||
756 | if (ret) | ||
757 | dev_err(&ar->udev->dev, "kill pending tx urbs.\n"); | ||
758 | |||
759 | usb_poison_anchored_urbs(&ar->tx_anch); | ||
760 | carl9170_usb_handle_tx_err(ar); | ||
761 | |||
762 | /* kill any pending command */ | ||
763 | spin_lock_bh(&ar->cmd_lock); | ||
764 | ar->readlen = 0; | ||
765 | spin_unlock_bh(&ar->cmd_lock); | ||
766 | complete_all(&ar->cmd_wait); | ||
767 | |||
768 | /* This is required to prevent an early completion on _start */ | ||
769 | INIT_COMPLETION(ar->cmd_wait); | ||
770 | |||
771 | /* | ||
772 | * Note: | ||
773 | * So far we freed all tx urbs, but we won't dare to touch any rx urbs. | ||
774 | * Else we would end up with a unresponsive device... | ||
775 | */ | ||
776 | } | ||
777 | |||
778 | int carl9170_usb_open(struct ar9170 *ar) | ||
779 | { | ||
780 | usb_unpoison_anchored_urbs(&ar->tx_anch); | ||
781 | |||
782 | carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE); | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | static int carl9170_usb_load_firmware(struct ar9170 *ar) | ||
787 | { | ||
788 | const u8 *data; | ||
789 | u8 *buf; | ||
790 | unsigned int transfer; | ||
791 | size_t len; | ||
792 | u32 addr; | ||
793 | int err = 0; | ||
794 | |||
795 | buf = kmalloc(4096, GFP_KERNEL); | ||
796 | if (!buf) { | ||
797 | err = -ENOMEM; | ||
798 | goto err_out; | ||
799 | } | ||
800 | |||
801 | data = ar->fw.fw->data; | ||
802 | len = ar->fw.fw->size; | ||
803 | addr = ar->fw.address; | ||
804 | |||
805 | /* this removes the miniboot image */ | ||
806 | data += ar->fw.offset; | ||
807 | len -= ar->fw.offset; | ||
808 | |||
809 | while (len) { | ||
810 | transfer = min_t(unsigned int, len, 4096u); | ||
811 | memcpy(buf, data, transfer); | ||
812 | |||
813 | err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0), | ||
814 | 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, | ||
815 | addr >> 8, 0, buf, transfer, 100); | ||
816 | |||
817 | if (err < 0) { | ||
818 | kfree(buf); | ||
819 | goto err_out; | ||
820 | } | ||
821 | |||
822 | len -= transfer; | ||
823 | data += transfer; | ||
824 | addr += transfer; | ||
825 | } | ||
826 | kfree(buf); | ||
827 | |||
828 | err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0), | ||
829 | 0x31 /* FW DL COMPLETE */, | ||
830 | 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 200); | ||
831 | |||
832 | if (wait_for_completion_timeout(&ar->fw_boot_wait, HZ) == 0) { | ||
833 | err = -ETIMEDOUT; | ||
834 | goto err_out; | ||
835 | } | ||
836 | |||
837 | err = carl9170_echo_test(ar, 0x4a110123); | ||
838 | if (err) | ||
839 | goto err_out; | ||
840 | |||
841 | /* now, start the command response counter */ | ||
842 | ar->cmd_seq = -1; | ||
843 | |||
844 | return 0; | ||
845 | |||
846 | err_out: | ||
847 | dev_err(&ar->udev->dev, "firmware upload failed (%d).\n", err); | ||
848 | return err; | ||
849 | } | ||
850 | |||
851 | int carl9170_usb_restart(struct ar9170 *ar) | ||
852 | { | ||
853 | int err = 0; | ||
854 | |||
855 | if (ar->intf->condition != USB_INTERFACE_BOUND) | ||
856 | return 0; | ||
857 | |||
858 | /* | ||
859 | * Disable the command response sequence counter check. | ||
860 | * We already know that the device/firmware is in a bad state. | ||
861 | * So, no extra points are awarded to anyone who reminds the | ||
862 | * driver about that. | ||
863 | */ | ||
864 | ar->cmd_seq = -2; | ||
865 | |||
866 | err = carl9170_reboot(ar); | ||
867 | |||
868 | carl9170_usb_stop(ar); | ||
869 | |||
870 | if (err) | ||
871 | goto err_out; | ||
872 | |||
873 | tasklet_schedule(&ar->usb_tasklet); | ||
874 | |||
875 | /* The reboot procedure can take quite a while to complete. */ | ||
876 | msleep(1100); | ||
877 | |||
878 | err = carl9170_usb_open(ar); | ||
879 | if (err) | ||
880 | goto err_out; | ||
881 | |||
882 | err = carl9170_usb_load_firmware(ar); | ||
883 | if (err) | ||
884 | goto err_out; | ||
885 | |||
886 | return 0; | ||
887 | |||
888 | err_out: | ||
889 | carl9170_usb_cancel_urbs(ar); | ||
890 | return err; | ||
891 | } | ||
892 | |||
893 | void carl9170_usb_reset(struct ar9170 *ar) | ||
894 | { | ||
895 | /* | ||
896 | * This is the last resort to get the device going again | ||
897 | * without any *user replugging action*. | ||
898 | * | ||
899 | * But there is a catch: usb_reset really is like a physical | ||
900 | * *reconnect*. The mac80211 state will be lost in the process. | ||
901 | * Therefore a userspace application, which is monitoring | ||
902 | * the link must step in. | ||
903 | */ | ||
904 | carl9170_usb_cancel_urbs(ar); | ||
905 | |||
906 | carl9170_usb_stop(ar); | ||
907 | |||
908 | usb_queue_reset_device(ar->intf); | ||
909 | } | ||
910 | |||
911 | static int carl9170_usb_init_device(struct ar9170 *ar) | ||
912 | { | ||
913 | int err; | ||
914 | |||
915 | /* | ||
916 | * The carl9170 firmware let's the driver know when it's | ||
917 | * ready for action. But we have to be prepared to gracefully | ||
918 | * handle all spurious [flushed] messages after each (re-)boot. | ||
919 | * Thus the command response counter remains disabled until it | ||
920 | * can be safely synchronized. | ||
921 | */ | ||
922 | ar->cmd_seq = -2; | ||
923 | |||
924 | err = carl9170_usb_send_rx_irq_urb(ar); | ||
925 | if (err) | ||
926 | goto err_out; | ||
927 | |||
928 | err = carl9170_usb_init_rx_bulk_urbs(ar); | ||
929 | if (err) | ||
930 | goto err_unrx; | ||
931 | |||
932 | err = carl9170_usb_open(ar); | ||
933 | if (err) | ||
934 | goto err_unrx; | ||
935 | |||
936 | mutex_lock(&ar->mutex); | ||
937 | err = carl9170_usb_load_firmware(ar); | ||
938 | mutex_unlock(&ar->mutex); | ||
939 | if (err) | ||
940 | goto err_stop; | ||
941 | |||
942 | return 0; | ||
943 | |||
944 | err_stop: | ||
945 | carl9170_usb_stop(ar); | ||
946 | |||
947 | err_unrx: | ||
948 | carl9170_usb_cancel_urbs(ar); | ||
949 | |||
950 | err_out: | ||
951 | return err; | ||
952 | } | ||
953 | |||
954 | static void carl9170_usb_firmware_failed(struct ar9170 *ar) | ||
955 | { | ||
956 | struct device *parent = ar->udev->dev.parent; | ||
957 | struct usb_device *udev; | ||
958 | |||
959 | /* | ||
960 | * Store a copy of the usb_device pointer locally. | ||
961 | * This is because device_release_driver initiates | ||
962 | * carl9170_usb_disconnect, which in turn frees our | ||
963 | * driver context (ar). | ||
964 | */ | ||
965 | udev = ar->udev; | ||
966 | |||
967 | complete(&ar->fw_load_wait); | ||
968 | |||
969 | /* unbind anything failed */ | ||
970 | if (parent) | ||
971 | device_lock(parent); | ||
972 | |||
973 | device_release_driver(&udev->dev); | ||
974 | if (parent) | ||
975 | device_unlock(parent); | ||
976 | |||
977 | usb_put_dev(udev); | ||
978 | } | ||
979 | |||
980 | static void carl9170_usb_firmware_finish(struct ar9170 *ar) | ||
981 | { | ||
982 | int err; | ||
983 | |||
984 | err = carl9170_parse_firmware(ar); | ||
985 | if (err) | ||
986 | goto err_freefw; | ||
987 | |||
988 | err = carl9170_usb_init_device(ar); | ||
989 | if (err) | ||
990 | goto err_freefw; | ||
991 | |||
992 | err = carl9170_register(ar); | ||
993 | |||
994 | carl9170_usb_stop(ar); | ||
995 | if (err) | ||
996 | goto err_unrx; | ||
997 | |||
998 | complete(&ar->fw_load_wait); | ||
999 | usb_put_dev(ar->udev); | ||
1000 | return; | ||
1001 | |||
1002 | err_unrx: | ||
1003 | carl9170_usb_cancel_urbs(ar); | ||
1004 | |||
1005 | err_freefw: | ||
1006 | carl9170_release_firmware(ar); | ||
1007 | carl9170_usb_firmware_failed(ar); | ||
1008 | } | ||
1009 | |||
1010 | static void carl9170_usb_firmware_step2(const struct firmware *fw, | ||
1011 | void *context) | ||
1012 | { | ||
1013 | struct ar9170 *ar = context; | ||
1014 | |||
1015 | if (fw) { | ||
1016 | ar->fw.fw = fw; | ||
1017 | carl9170_usb_firmware_finish(ar); | ||
1018 | return; | ||
1019 | } | ||
1020 | |||
1021 | dev_err(&ar->udev->dev, "firmware not found.\n"); | ||
1022 | carl9170_usb_firmware_failed(ar); | ||
1023 | } | ||
1024 | |||
1025 | static int carl9170_usb_probe(struct usb_interface *intf, | ||
1026 | const struct usb_device_id *id) | ||
1027 | { | ||
1028 | struct ar9170 *ar; | ||
1029 | struct usb_device *udev; | ||
1030 | int err; | ||
1031 | |||
1032 | err = usb_reset_device(interface_to_usbdev(intf)); | ||
1033 | if (err) | ||
1034 | return err; | ||
1035 | |||
1036 | ar = carl9170_alloc(sizeof(*ar)); | ||
1037 | if (IS_ERR(ar)) | ||
1038 | return PTR_ERR(ar); | ||
1039 | |||
1040 | udev = interface_to_usbdev(intf); | ||
1041 | usb_get_dev(udev); | ||
1042 | ar->udev = udev; | ||
1043 | ar->intf = intf; | ||
1044 | ar->features = id->driver_info; | ||
1045 | |||
1046 | usb_set_intfdata(intf, ar); | ||
1047 | SET_IEEE80211_DEV(ar->hw, &intf->dev); | ||
1048 | |||
1049 | init_usb_anchor(&ar->rx_anch); | ||
1050 | init_usb_anchor(&ar->rx_pool); | ||
1051 | init_usb_anchor(&ar->rx_work); | ||
1052 | init_usb_anchor(&ar->tx_wait); | ||
1053 | init_usb_anchor(&ar->tx_anch); | ||
1054 | init_usb_anchor(&ar->tx_cmd); | ||
1055 | init_usb_anchor(&ar->tx_err); | ||
1056 | init_completion(&ar->cmd_wait); | ||
1057 | init_completion(&ar->fw_boot_wait); | ||
1058 | init_completion(&ar->fw_load_wait); | ||
1059 | tasklet_init(&ar->usb_tasklet, carl9170_usb_tasklet, | ||
1060 | (unsigned long)ar); | ||
1061 | |||
1062 | atomic_set(&ar->tx_cmd_urbs, 0); | ||
1063 | atomic_set(&ar->tx_anch_urbs, 0); | ||
1064 | atomic_set(&ar->rx_work_urbs, 0); | ||
1065 | atomic_set(&ar->rx_anch_urbs, 0); | ||
1066 | atomic_set(&ar->rx_pool_urbs, 0); | ||
1067 | |||
1068 | usb_get_dev(ar->udev); | ||
1069 | |||
1070 | carl9170_set_state(ar, CARL9170_STOPPED); | ||
1071 | |||
1072 | return request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, | ||
1073 | &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2); | ||
1074 | } | ||
1075 | |||
1076 | static void carl9170_usb_disconnect(struct usb_interface *intf) | ||
1077 | { | ||
1078 | struct ar9170 *ar = usb_get_intfdata(intf); | ||
1079 | struct usb_device *udev; | ||
1080 | |||
1081 | if (WARN_ON(!ar)) | ||
1082 | return; | ||
1083 | |||
1084 | udev = ar->udev; | ||
1085 | wait_for_completion(&ar->fw_load_wait); | ||
1086 | |||
1087 | if (IS_INITIALIZED(ar)) { | ||
1088 | carl9170_reboot(ar); | ||
1089 | carl9170_usb_stop(ar); | ||
1090 | } | ||
1091 | |||
1092 | carl9170_usb_cancel_urbs(ar); | ||
1093 | carl9170_unregister(ar); | ||
1094 | |||
1095 | usb_set_intfdata(intf, NULL); | ||
1096 | |||
1097 | carl9170_release_firmware(ar); | ||
1098 | carl9170_free(ar); | ||
1099 | usb_put_dev(udev); | ||
1100 | } | ||
1101 | |||
1102 | #ifdef CONFIG_PM | ||
1103 | static int carl9170_usb_suspend(struct usb_interface *intf, | ||
1104 | pm_message_t message) | ||
1105 | { | ||
1106 | struct ar9170 *ar = usb_get_intfdata(intf); | ||
1107 | |||
1108 | if (!ar) | ||
1109 | return -ENODEV; | ||
1110 | |||
1111 | carl9170_usb_cancel_urbs(ar); | ||
1112 | |||
1113 | return 0; | ||
1114 | } | ||
1115 | |||
1116 | static int carl9170_usb_resume(struct usb_interface *intf) | ||
1117 | { | ||
1118 | struct ar9170 *ar = usb_get_intfdata(intf); | ||
1119 | int err; | ||
1120 | |||
1121 | if (!ar) | ||
1122 | return -ENODEV; | ||
1123 | |||
1124 | usb_unpoison_anchored_urbs(&ar->rx_anch); | ||
1125 | carl9170_set_state(ar, CARL9170_STOPPED); | ||
1126 | |||
1127 | /* | ||
1128 | * The USB documentation demands that [for suspend] all traffic | ||
1129 | * to and from the device has to stop. This would be fine, but | ||
1130 | * there's a catch: the device[usb phy] does not come back. | ||
1131 | * | ||
1132 | * Upon resume the firmware will "kill" itself and the | ||
1133 | * boot-code sorts out the magic voodoo. | ||
1134 | * Not very nice, but there's not much what could go wrong. | ||
1135 | */ | ||
1136 | msleep(1100); | ||
1137 | |||
1138 | err = carl9170_usb_init_device(ar); | ||
1139 | if (err) | ||
1140 | goto err_unrx; | ||
1141 | |||
1142 | return 0; | ||
1143 | |||
1144 | err_unrx: | ||
1145 | carl9170_usb_cancel_urbs(ar); | ||
1146 | |||
1147 | return err; | ||
1148 | } | ||
1149 | #endif /* CONFIG_PM */ | ||
1150 | |||
1151 | static struct usb_driver carl9170_driver = { | ||
1152 | .name = KBUILD_MODNAME, | ||
1153 | .probe = carl9170_usb_probe, | ||
1154 | .disconnect = carl9170_usb_disconnect, | ||
1155 | .id_table = carl9170_usb_ids, | ||
1156 | .soft_unbind = 1, | ||
1157 | #ifdef CONFIG_PM | ||
1158 | .suspend = carl9170_usb_suspend, | ||
1159 | .resume = carl9170_usb_resume, | ||
1160 | .reset_resume = carl9170_usb_resume, | ||
1161 | #endif /* CONFIG_PM */ | ||
1162 | }; | ||
1163 | |||
1164 | static int __init carl9170_usb_init(void) | ||
1165 | { | ||
1166 | return usb_register(&carl9170_driver); | ||
1167 | } | ||
1168 | |||
1169 | static void __exit carl9170_usb_exit(void) | ||
1170 | { | ||
1171 | usb_deregister(&carl9170_driver); | ||
1172 | } | ||
1173 | |||
1174 | module_init(carl9170_usb_init); | ||
1175 | module_exit(carl9170_usb_exit); | ||
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h new file mode 100644 index 000000000000..15095c035169 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/version.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __CARL9170_SHARED_VERSION_H | ||
2 | #define __CARL9170_SHARED_VERSION_H | ||
3 | #define CARL9170FW_VERSION_YEAR 11 | ||
4 | #define CARL9170FW_VERSION_MONTH 1 | ||
5 | #define CARL9170FW_VERSION_DAY 22 | ||
6 | #define CARL9170FW_VERSION_GIT "1.9.2" | ||
7 | #endif /* __CARL9170_SHARED_VERSION_H */ | ||
diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h new file mode 100644 index 000000000000..9e1324b67e08 --- /dev/null +++ b/drivers/net/wireless/ath/carl9170/wlan.h | |||
@@ -0,0 +1,438 @@ | |||
1 | /* | ||
2 | * Shared Atheros AR9170 Header | ||
3 | * | ||
4 | * RX/TX meta descriptor format | ||
5 | * | ||
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; see the file COPYING. If not, see | ||
20 | * http://www.gnu.org/licenses/. | ||
21 | * | ||
22 | * This file incorporates work covered by the following copyright and | ||
23 | * permission notice: | ||
24 | * Copyright (c) 2007-2008 Atheros Communications, Inc. | ||
25 | * | ||
26 | * Permission to use, copy, modify, and/or distribute this software for any | ||
27 | * purpose with or without fee is hereby granted, provided that the above | ||
28 | * copyright notice and this permission notice appear in all copies. | ||
29 | * | ||
30 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
31 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
33 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
34 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
37 | */ | ||
38 | |||
39 | #ifndef __CARL9170_SHARED_WLAN_H | ||
40 | #define __CARL9170_SHARED_WLAN_H | ||
41 | |||
42 | #include "fwcmd.h" | ||
43 | |||
44 | #define AR9170_RX_PHY_RATE_CCK_1M 0x0a | ||
45 | #define AR9170_RX_PHY_RATE_CCK_2M 0x14 | ||
46 | #define AR9170_RX_PHY_RATE_CCK_5M 0x37 | ||
47 | #define AR9170_RX_PHY_RATE_CCK_11M 0x6e | ||
48 | |||
49 | #define AR9170_ENC_ALG_NONE 0x0 | ||
50 | #define AR9170_ENC_ALG_WEP64 0x1 | ||
51 | #define AR9170_ENC_ALG_TKIP 0x2 | ||
52 | #define AR9170_ENC_ALG_AESCCMP 0x4 | ||
53 | #define AR9170_ENC_ALG_WEP128 0x5 | ||
54 | #define AR9170_ENC_ALG_WEP256 0x6 | ||
55 | #define AR9170_ENC_ALG_CENC 0x7 | ||
56 | |||
57 | #define AR9170_RX_ENC_SOFTWARE 0x8 | ||
58 | |||
59 | #define AR9170_RX_STATUS_MODULATION 0x03 | ||
60 | #define AR9170_RX_STATUS_MODULATION_S 0 | ||
61 | #define AR9170_RX_STATUS_MODULATION_CCK 0x00 | ||
62 | #define AR9170_RX_STATUS_MODULATION_OFDM 0x01 | ||
63 | #define AR9170_RX_STATUS_MODULATION_HT 0x02 | ||
64 | #define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03 | ||
65 | |||
66 | /* depends on modulation */ | ||
67 | #define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08 | ||
68 | #define AR9170_RX_STATUS_GREENFIELD 0x08 | ||
69 | |||
70 | #define AR9170_RX_STATUS_MPDU 0x30 | ||
71 | #define AR9170_RX_STATUS_MPDU_S 4 | ||
72 | #define AR9170_RX_STATUS_MPDU_SINGLE 0x00 | ||
73 | #define AR9170_RX_STATUS_MPDU_FIRST 0x20 | ||
74 | #define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 | ||
75 | #define AR9170_RX_STATUS_MPDU_LAST 0x10 | ||
76 | |||
77 | #define AR9170_RX_STATUS_CONT_AGGR 0x40 | ||
78 | #define AR9170_RX_STATUS_TOTAL_ERROR 0x80 | ||
79 | |||
80 | #define AR9170_RX_ERROR_RXTO 0x01 | ||
81 | #define AR9170_RX_ERROR_OVERRUN 0x02 | ||
82 | #define AR9170_RX_ERROR_DECRYPT 0x04 | ||
83 | #define AR9170_RX_ERROR_FCS 0x08 | ||
84 | #define AR9170_RX_ERROR_WRONG_RA 0x10 | ||
85 | #define AR9170_RX_ERROR_PLCP 0x20 | ||
86 | #define AR9170_RX_ERROR_MMIC 0x40 | ||
87 | |||
88 | /* these are either-or */ | ||
89 | #define AR9170_TX_MAC_PROT_RTS 0x0001 | ||
90 | #define AR9170_TX_MAC_PROT_CTS 0x0002 | ||
91 | #define AR9170_TX_MAC_PROT 0x0003 | ||
92 | |||
93 | #define AR9170_TX_MAC_NO_ACK 0x0004 | ||
94 | /* if unset, MAC will only do SIFS space before frame */ | ||
95 | #define AR9170_TX_MAC_BACKOFF 0x0008 | ||
96 | #define AR9170_TX_MAC_BURST 0x0010 | ||
97 | #define AR9170_TX_MAC_AGGR 0x0020 | ||
98 | |||
99 | /* encryption is a two-bit field */ | ||
100 | #define AR9170_TX_MAC_ENCR_NONE 0x0000 | ||
101 | #define AR9170_TX_MAC_ENCR_RC4 0x0040 | ||
102 | #define AR9170_TX_MAC_ENCR_CENC 0x0080 | ||
103 | #define AR9170_TX_MAC_ENCR_AES 0x00c0 | ||
104 | |||
105 | #define AR9170_TX_MAC_MMIC 0x0100 | ||
106 | #define AR9170_TX_MAC_HW_DURATION 0x0200 | ||
107 | #define AR9170_TX_MAC_QOS_S 10 | ||
108 | #define AR9170_TX_MAC_QOS 0x0c00 | ||
109 | #define AR9170_TX_MAC_DISABLE_TXOP 0x1000 | ||
110 | #define AR9170_TX_MAC_TXOP_RIFS 0x2000 | ||
111 | #define AR9170_TX_MAC_IMM_BA 0x4000 | ||
112 | |||
113 | /* either-or */ | ||
114 | #define AR9170_TX_PHY_MOD_CCK 0x00000000 | ||
115 | #define AR9170_TX_PHY_MOD_OFDM 0x00000001 | ||
116 | #define AR9170_TX_PHY_MOD_HT 0x00000002 | ||
117 | |||
118 | /* depends on modulation */ | ||
119 | #define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004 | ||
120 | #define AR9170_TX_PHY_GREENFIELD 0x00000004 | ||
121 | |||
122 | #define AR9170_TX_PHY_BW_S 3 | ||
123 | #define AR9170_TX_PHY_BW (3 << AR9170_TX_PHY_BW_SHIFT) | ||
124 | #define AR9170_TX_PHY_BW_20MHZ 0 | ||
125 | #define AR9170_TX_PHY_BW_40MHZ 2 | ||
126 | #define AR9170_TX_PHY_BW_40MHZ_DUP 3 | ||
127 | |||
128 | #define AR9170_TX_PHY_TX_HEAVY_CLIP_S 6 | ||
129 | #define AR9170_TX_PHY_TX_HEAVY_CLIP (7 << \ | ||
130 | AR9170_TX_PHY_TX_HEAVY_CLIP_S) | ||
131 | |||
132 | #define AR9170_TX_PHY_TX_PWR_S 9 | ||
133 | #define AR9170_TX_PHY_TX_PWR (0x3f << \ | ||
134 | AR9170_TX_PHY_TX_PWR_S) | ||
135 | |||
136 | #define AR9170_TX_PHY_TXCHAIN_S 15 | ||
137 | #define AR9170_TX_PHY_TXCHAIN (7 << \ | ||
138 | AR9170_TX_PHY_TXCHAIN_S) | ||
139 | #define AR9170_TX_PHY_TXCHAIN_1 1 | ||
140 | /* use for cck, ofdm 6/9/12/18/24 and HT if capable */ | ||
141 | #define AR9170_TX_PHY_TXCHAIN_2 5 | ||
142 | |||
143 | #define AR9170_TX_PHY_MCS_S 18 | ||
144 | #define AR9170_TX_PHY_MCS (0x7f << \ | ||
145 | AR9170_TX_PHY_MCS_S) | ||
146 | |||
147 | #define AR9170_TX_PHY_RATE_CCK_1M 0x0 | ||
148 | #define AR9170_TX_PHY_RATE_CCK_2M 0x1 | ||
149 | #define AR9170_TX_PHY_RATE_CCK_5M 0x2 | ||
150 | #define AR9170_TX_PHY_RATE_CCK_11M 0x3 | ||
151 | |||
152 | /* same as AR9170_RX_PHY_RATE */ | ||
153 | #define AR9170_TXRX_PHY_RATE_OFDM_6M 0xb | ||
154 | #define AR9170_TXRX_PHY_RATE_OFDM_9M 0xf | ||
155 | #define AR9170_TXRX_PHY_RATE_OFDM_12M 0xa | ||
156 | #define AR9170_TXRX_PHY_RATE_OFDM_18M 0xe | ||
157 | #define AR9170_TXRX_PHY_RATE_OFDM_24M 0x9 | ||
158 | #define AR9170_TXRX_PHY_RATE_OFDM_36M 0xd | ||
159 | #define AR9170_TXRX_PHY_RATE_OFDM_48M 0x8 | ||
160 | #define AR9170_TXRX_PHY_RATE_OFDM_54M 0xc | ||
161 | |||
162 | #define AR9170_TXRX_PHY_RATE_HT_MCS0 0x0 | ||
163 | #define AR9170_TXRX_PHY_RATE_HT_MCS1 0x1 | ||
164 | #define AR9170_TXRX_PHY_RATE_HT_MCS2 0x2 | ||
165 | #define AR9170_TXRX_PHY_RATE_HT_MCS3 0x3 | ||
166 | #define AR9170_TXRX_PHY_RATE_HT_MCS4 0x4 | ||
167 | #define AR9170_TXRX_PHY_RATE_HT_MCS5 0x5 | ||
168 | #define AR9170_TXRX_PHY_RATE_HT_MCS6 0x6 | ||
169 | #define AR9170_TXRX_PHY_RATE_HT_MCS7 0x7 | ||
170 | #define AR9170_TXRX_PHY_RATE_HT_MCS8 0x8 | ||
171 | #define AR9170_TXRX_PHY_RATE_HT_MCS9 0x9 | ||
172 | #define AR9170_TXRX_PHY_RATE_HT_MCS10 0xa | ||
173 | #define AR9170_TXRX_PHY_RATE_HT_MCS11 0xb | ||
174 | #define AR9170_TXRX_PHY_RATE_HT_MCS12 0xc | ||
175 | #define AR9170_TXRX_PHY_RATE_HT_MCS13 0xd | ||
176 | #define AR9170_TXRX_PHY_RATE_HT_MCS14 0xe | ||
177 | #define AR9170_TXRX_PHY_RATE_HT_MCS15 0xf | ||
178 | |||
179 | #define AR9170_TX_PHY_SHORT_GI 0x80000000 | ||
180 | |||
181 | #ifdef __CARL9170FW__ | ||
182 | struct ar9170_tx_hw_mac_control { | ||
183 | union { | ||
184 | struct { | ||
185 | /* | ||
186 | * Beware of compiler bugs in all gcc pre 4.4! | ||
187 | */ | ||
188 | |||
189 | u8 erp_prot:2; | ||
190 | u8 no_ack:1; | ||
191 | u8 backoff:1; | ||
192 | u8 burst:1; | ||
193 | u8 ampdu:1; | ||
194 | |||
195 | u8 enc_mode:2; | ||
196 | |||
197 | u8 hw_mmic:1; | ||
198 | u8 hw_duration:1; | ||
199 | |||
200 | u8 qos_queue:2; | ||
201 | |||
202 | u8 disable_txop:1; | ||
203 | u8 txop_rifs:1; | ||
204 | |||
205 | u8 ba_end:1; | ||
206 | u8 probe:1; | ||
207 | } __packed; | ||
208 | |||
209 | __le16 set; | ||
210 | } __packed; | ||
211 | } __packed; | ||
212 | |||
213 | struct ar9170_tx_hw_phy_control { | ||
214 | union { | ||
215 | struct { | ||
216 | /* | ||
217 | * Beware of compiler bugs in all gcc pre 4.4! | ||
218 | */ | ||
219 | |||
220 | u8 modulation:2; | ||
221 | u8 preamble:1; | ||
222 | u8 bandwidth:2; | ||
223 | u8:1; | ||
224 | u8 heavy_clip:3; | ||
225 | u8 tx_power:6; | ||
226 | u8 chains:3; | ||
227 | u8 mcs:7; | ||
228 | u8:6; | ||
229 | u8 short_gi:1; | ||
230 | } __packed; | ||
231 | |||
232 | __le32 set; | ||
233 | } __packed; | ||
234 | } __packed; | ||
235 | |||
236 | struct ar9170_tx_rate_info { | ||
237 | u8 tries:3; | ||
238 | u8 erp_prot:2; | ||
239 | u8 ampdu:1; | ||
240 | u8 free:2; /* free for use (e.g.:RIFS/TXOP/AMPDU) */ | ||
241 | } __packed; | ||
242 | |||
243 | struct carl9170_tx_superdesc { | ||
244 | __le16 len; | ||
245 | u8 rix; | ||
246 | u8 cnt; | ||
247 | u8 cookie; | ||
248 | u8 ampdu_density:3; | ||
249 | u8 ampdu_factor:2; | ||
250 | u8 ampdu_commit_density:1; | ||
251 | u8 ampdu_commit_factor:1; | ||
252 | u8 ampdu_unused_bit:1; | ||
253 | u8 queue:2; | ||
254 | u8 assign_seq:1; | ||
255 | u8 vif_id:3; | ||
256 | u8 fill_in_tsf:1; | ||
257 | u8 cab:1; | ||
258 | u8 padding2; | ||
259 | struct ar9170_tx_rate_info ri[CARL9170_TX_MAX_RATES]; | ||
260 | struct ar9170_tx_hw_phy_control rr[CARL9170_TX_MAX_RETRY_RATES]; | ||
261 | } __packed; | ||
262 | |||
263 | struct ar9170_tx_hwdesc { | ||
264 | __le16 length; | ||
265 | struct ar9170_tx_hw_mac_control mac; | ||
266 | struct ar9170_tx_hw_phy_control phy; | ||
267 | } __packed; | ||
268 | |||
269 | struct ar9170_tx_frame { | ||
270 | struct ar9170_tx_hwdesc hdr; | ||
271 | |||
272 | union { | ||
273 | struct ieee80211_hdr i3e; | ||
274 | u8 payload[0]; | ||
275 | } data; | ||
276 | } __packed; | ||
277 | |||
278 | struct carl9170_tx_superframe { | ||
279 | struct carl9170_tx_superdesc s; | ||
280 | struct ar9170_tx_frame f; | ||
281 | } __packed; | ||
282 | |||
283 | #endif /* __CARL9170FW__ */ | ||
284 | |||
285 | struct _ar9170_tx_hwdesc { | ||
286 | __le16 length; | ||
287 | __le16 mac_control; | ||
288 | __le32 phy_control; | ||
289 | } __packed; | ||
290 | |||
291 | #define CARL9170_TX_SUPER_AMPDU_DENSITY_S 0 | ||
292 | #define CARL9170_TX_SUPER_AMPDU_DENSITY 0x7 | ||
293 | #define CARL9170_TX_SUPER_AMPDU_FACTOR 0x18 | ||
294 | #define CARL9170_TX_SUPER_AMPDU_FACTOR_S 3 | ||
295 | #define CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY 0x20 | ||
296 | #define CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY_S 5 | ||
297 | #define CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR 0x40 | ||
298 | #define CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR_S 6 | ||
299 | |||
300 | #define CARL9170_TX_SUPER_MISC_QUEUE 0x3 | ||
301 | #define CARL9170_TX_SUPER_MISC_QUEUE_S 0 | ||
302 | #define CARL9170_TX_SUPER_MISC_ASSIGN_SEQ 0x4 | ||
303 | #define CARL9170_TX_SUPER_MISC_VIF_ID 0x38 | ||
304 | #define CARL9170_TX_SUPER_MISC_VIF_ID_S 3 | ||
305 | #define CARL9170_TX_SUPER_MISC_FILL_IN_TSF 0x40 | ||
306 | #define CARL9170_TX_SUPER_MISC_CAB 0x80 | ||
307 | |||
308 | #define CARL9170_TX_SUPER_RI_TRIES 0x7 | ||
309 | #define CARL9170_TX_SUPER_RI_TRIES_S 0 | ||
310 | #define CARL9170_TX_SUPER_RI_ERP_PROT 0x18 | ||
311 | #define CARL9170_TX_SUPER_RI_ERP_PROT_S 3 | ||
312 | #define CARL9170_TX_SUPER_RI_AMPDU 0x20 | ||
313 | #define CARL9170_TX_SUPER_RI_AMPDU_S 5 | ||
314 | |||
315 | struct _carl9170_tx_superdesc { | ||
316 | __le16 len; | ||
317 | u8 rix; | ||
318 | u8 cnt; | ||
319 | u8 cookie; | ||
320 | u8 ampdu_settings; | ||
321 | u8 misc; | ||
322 | u8 padding; | ||
323 | u8 ri[CARL9170_TX_MAX_RATES]; | ||
324 | __le32 rr[CARL9170_TX_MAX_RETRY_RATES]; | ||
325 | } __packed; | ||
326 | |||
327 | struct _carl9170_tx_superframe { | ||
328 | struct _carl9170_tx_superdesc s; | ||
329 | struct _ar9170_tx_hwdesc f; | ||
330 | u8 frame_data[0]; | ||
331 | } __packed; | ||
332 | |||
333 | #define CARL9170_TX_SUPERDESC_LEN 24 | ||
334 | #define AR9170_TX_HWDESC_LEN 8 | ||
335 | #define CARL9170_TX_SUPERFRAME_LEN (CARL9170_TX_SUPERDESC_LEN + \ | ||
336 | AR9170_TX_HWDESC_LEN) | ||
337 | |||
338 | struct ar9170_rx_head { | ||
339 | u8 plcp[12]; | ||
340 | } __packed; | ||
341 | |||
342 | #define AR9170_RX_HEAD_LEN 12 | ||
343 | |||
344 | struct ar9170_rx_phystatus { | ||
345 | union { | ||
346 | struct { | ||
347 | u8 rssi_ant0, rssi_ant1, rssi_ant2, | ||
348 | rssi_ant0x, rssi_ant1x, rssi_ant2x, | ||
349 | rssi_combined; | ||
350 | } __packed; | ||
351 | u8 rssi[7]; | ||
352 | } __packed; | ||
353 | |||
354 | u8 evm_stream0[6], evm_stream1[6]; | ||
355 | u8 phy_err; | ||
356 | } __packed; | ||
357 | |||
358 | #define AR9170_RX_PHYSTATUS_LEN 20 | ||
359 | |||
360 | struct ar9170_rx_macstatus { | ||
361 | u8 SAidx, DAidx; | ||
362 | u8 error; | ||
363 | u8 status; | ||
364 | } __packed; | ||
365 | |||
366 | #define AR9170_RX_MACSTATUS_LEN 4 | ||
367 | |||
368 | struct ar9170_rx_frame_single { | ||
369 | struct ar9170_rx_head phy_head; | ||
370 | struct ieee80211_hdr i3e; | ||
371 | struct ar9170_rx_phystatus phy_tail; | ||
372 | struct ar9170_rx_macstatus macstatus; | ||
373 | } __packed; | ||
374 | |||
375 | struct ar9170_rx_frame_head { | ||
376 | struct ar9170_rx_head phy_head; | ||
377 | struct ieee80211_hdr i3e; | ||
378 | struct ar9170_rx_macstatus macstatus; | ||
379 | } __packed; | ||
380 | |||
381 | struct ar9170_rx_frame_middle { | ||
382 | struct ieee80211_hdr i3e; | ||
383 | struct ar9170_rx_macstatus macstatus; | ||
384 | } __packed; | ||
385 | |||
386 | struct ar9170_rx_frame_tail { | ||
387 | struct ieee80211_hdr i3e; | ||
388 | struct ar9170_rx_phystatus phy_tail; | ||
389 | struct ar9170_rx_macstatus macstatus; | ||
390 | } __packed; | ||
391 | |||
392 | struct ar9170_rx_frame { | ||
393 | union { | ||
394 | struct ar9170_rx_frame_single single; | ||
395 | struct ar9170_rx_frame_head head; | ||
396 | struct ar9170_rx_frame_middle middle; | ||
397 | struct ar9170_rx_frame_tail tail; | ||
398 | } __packed; | ||
399 | } __packed; | ||
400 | |||
401 | static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) | ||
402 | { | ||
403 | return (t->SAidx & 0xc0) >> 4 | | ||
404 | (t->DAidx & 0xc0) >> 6; | ||
405 | } | ||
406 | |||
407 | enum ar9170_txq { | ||
408 | AR9170_TXQ_BE, | ||
409 | |||
410 | AR9170_TXQ_VI, | ||
411 | AR9170_TXQ_VO, | ||
412 | AR9170_TXQ_BK, | ||
413 | |||
414 | __AR9170_NUM_TXQ, | ||
415 | }; | ||
416 | |||
417 | /* | ||
418 | * This is an workaround for several undocumented bugs. | ||
419 | * Don't mess with the QoS/AC <-> HW Queue map, if you don't | ||
420 | * know what you are doing. | ||
421 | * | ||
422 | * Known problems [hardware]: | ||
423 | * * The MAC does not aggregate frames on anything other | ||
424 | * than the first HW queue. | ||
425 | * * when an AMPDU is placed [in the first hw queue] and | ||
426 | * additional frames are already queued on a different | ||
427 | * hw queue, the MAC will ALWAYS freeze. | ||
428 | * | ||
429 | * In a nutshell: The hardware can either do QoS or | ||
430 | * Aggregation but not both at the same time. As a | ||
431 | * result, this makes the device pretty much useless | ||
432 | * for any serious 802.11n setup. | ||
433 | */ | ||
434 | static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 }; | ||
435 | |||
436 | #define AR9170_TXQ_DEPTH 32 | ||
437 | |||
438 | #endif /* __CARL9170_SHARED_WLAN_H */ | ||