diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2008-08-04 03:16:41 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-07 09:49:42 -0400 |
commit | f078f209704849c86bd43c0beccfc1f410ed1c66 (patch) | |
tree | 9b965db2c86e7369002a05808f6b418c8a9aa985 | |
parent | b1a5215004130689aeee9e522585c879d3b71472 (diff) |
ath9k: Add new Atheros IEEE 802.11n driver
This adds the new mac80211 11n ath9k Atheros driver. Only STA support
is currently enabled and tested.
Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Jack Howarth <howarth@bromo.msbb.uc.edu>
Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
23 files changed, 31694 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8223a521d7c..c67a402a685 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -720,6 +720,15 @@ L: linux-wireless@vger.kernel.org | |||
720 | L: ath5k-devel@lists.ath5k.org | 720 | L: ath5k-devel@lists.ath5k.org |
721 | S: Maintained | 721 | S: Maintained |
722 | 722 | ||
723 | ATHEROS ATH9K WIRELESS DRIVER | ||
724 | P: Luis R. Rodriguez | ||
725 | M: lrodriguez@atheros.com | ||
726 | P: Jouni Malinen | ||
727 | M: jmalinen@atheros.com | ||
728 | L: linux-wireless@vger.kernel.org | ||
729 | L: ath9k-devel@lists.ath9k.org | ||
730 | S: Supported | ||
731 | |||
723 | ATI_REMOTE2 DRIVER | 732 | ATI_REMOTE2 DRIVER |
724 | P: Ville Syrjala | 733 | P: Ville Syrjala |
725 | M: syrjala@sci.fi | 734 | M: syrjala@sci.fi |
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 4c7ff61a1a9..9931b5ab59c 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -695,6 +695,7 @@ config MAC80211_HWSIM | |||
695 | 695 | ||
696 | source "drivers/net/wireless/p54/Kconfig" | 696 | source "drivers/net/wireless/p54/Kconfig" |
697 | source "drivers/net/wireless/ath5k/Kconfig" | 697 | source "drivers/net/wireless/ath5k/Kconfig" |
698 | source "drivers/net/wireless/ath9k/Kconfig" | ||
698 | source "drivers/net/wireless/iwlwifi/Kconfig" | 699 | source "drivers/net/wireless/iwlwifi/Kconfig" |
699 | source "drivers/net/wireless/hostap/Kconfig" | 700 | source "drivers/net/wireless/hostap/Kconfig" |
700 | source "drivers/net/wireless/b43/Kconfig" | 701 | source "drivers/net/wireless/b43/Kconfig" |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 54a4f6f1db6..59aa89ec6e8 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
@@ -62,5 +62,6 @@ obj-$(CONFIG_RT2X00) += rt2x00/ | |||
62 | obj-$(CONFIG_P54_COMMON) += p54/ | 62 | obj-$(CONFIG_P54_COMMON) += p54/ |
63 | 63 | ||
64 | obj-$(CONFIG_ATH5K) += ath5k/ | 64 | obj-$(CONFIG_ATH5K) += ath5k/ |
65 | obj-$(CONFIG_ATH9K) += ath9k/ | ||
65 | 66 | ||
66 | obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o | 67 | obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o |
diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig new file mode 100644 index 00000000000..9e19dcceb3a --- /dev/null +++ b/drivers/net/wireless/ath9k/Kconfig | |||
@@ -0,0 +1,8 @@ | |||
1 | config ATH9K | ||
2 | tristate "Atheros 802.11n wireless cards support" | ||
3 | depends on PCI && MAC80211 && WLAN_80211 | ||
4 | ---help--- | ||
5 | This module adds support for wireless adapters based on | ||
6 | Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets. | ||
7 | |||
8 | If you choose to build a module, it'll be called ath9k. | ||
diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath9k/Makefile new file mode 100644 index 00000000000..a6411517e5f --- /dev/null +++ b/drivers/net/wireless/ath9k/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | ath9k-y += hw.o \ | ||
2 | phy.o \ | ||
3 | regd.o \ | ||
4 | beacon.o \ | ||
5 | main.o \ | ||
6 | recv.o \ | ||
7 | xmit.o \ | ||
8 | rc.o \ | ||
9 | core.o | ||
10 | |||
11 | obj-$(CONFIG_ATH9K) += ath9k.o | ||
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h new file mode 100644 index 00000000000..dc1da64d2d7 --- /dev/null +++ b/drivers/net/wireless/ath9k/ath9k.h | |||
@@ -0,0 +1,1066 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef ATH9K_H | ||
18 | #define ATH9K_H | ||
19 | |||
20 | #include <linux/io.h> | ||
21 | |||
22 | #define ATHEROS_VENDOR_ID 0x168c | ||
23 | |||
24 | #define AR5416_DEVID_PCI 0x0023 | ||
25 | #define AR5416_DEVID_PCIE 0x0024 | ||
26 | #define AR9160_DEVID_PCI 0x0027 | ||
27 | #define AR9280_DEVID_PCI 0x0029 | ||
28 | #define AR9280_DEVID_PCIE 0x002a | ||
29 | |||
30 | #define AR5416_AR9100_DEVID 0x000b | ||
31 | |||
32 | #define AR_SUBVENDOR_ID_NOG 0x0e11 | ||
33 | #define AR_SUBVENDOR_ID_NEW_A 0x7065 | ||
34 | |||
35 | #define ATH9K_TXERR_XRETRY 0x01 | ||
36 | #define ATH9K_TXERR_FILT 0x02 | ||
37 | #define ATH9K_TXERR_FIFO 0x04 | ||
38 | #define ATH9K_TXERR_XTXOP 0x08 | ||
39 | #define ATH9K_TXERR_TIMER_EXPIRED 0x10 | ||
40 | |||
41 | #define ATH9K_TX_BA 0x01 | ||
42 | #define ATH9K_TX_PWRMGMT 0x02 | ||
43 | #define ATH9K_TX_DESC_CFG_ERR 0x04 | ||
44 | #define ATH9K_TX_DATA_UNDERRUN 0x08 | ||
45 | #define ATH9K_TX_DELIM_UNDERRUN 0x10 | ||
46 | #define ATH9K_TX_SW_ABORTED 0x40 | ||
47 | #define ATH9K_TX_SW_FILTERED 0x80 | ||
48 | |||
49 | #define NBBY 8 | ||
50 | |||
51 | struct ath_tx_status { | ||
52 | u32 ts_tstamp; | ||
53 | u16 ts_seqnum; | ||
54 | u8 ts_status; | ||
55 | u8 ts_ratecode; | ||
56 | u8 ts_rateindex; | ||
57 | int8_t ts_rssi; | ||
58 | u8 ts_shortretry; | ||
59 | u8 ts_longretry; | ||
60 | u8 ts_virtcol; | ||
61 | u8 ts_antenna; | ||
62 | u8 ts_flags; | ||
63 | int8_t ts_rssi_ctl0; | ||
64 | int8_t ts_rssi_ctl1; | ||
65 | int8_t ts_rssi_ctl2; | ||
66 | int8_t ts_rssi_ext0; | ||
67 | int8_t ts_rssi_ext1; | ||
68 | int8_t ts_rssi_ext2; | ||
69 | u8 pad[3]; | ||
70 | u32 ba_low; | ||
71 | u32 ba_high; | ||
72 | u32 evm0; | ||
73 | u32 evm1; | ||
74 | u32 evm2; | ||
75 | }; | ||
76 | |||
77 | struct ath_rx_status { | ||
78 | u32 rs_tstamp; | ||
79 | u16 rs_datalen; | ||
80 | u8 rs_status; | ||
81 | u8 rs_phyerr; | ||
82 | int8_t rs_rssi; | ||
83 | u8 rs_keyix; | ||
84 | u8 rs_rate; | ||
85 | u8 rs_antenna; | ||
86 | u8 rs_more; | ||
87 | int8_t rs_rssi_ctl0; | ||
88 | int8_t rs_rssi_ctl1; | ||
89 | int8_t rs_rssi_ctl2; | ||
90 | int8_t rs_rssi_ext0; | ||
91 | int8_t rs_rssi_ext1; | ||
92 | int8_t rs_rssi_ext2; | ||
93 | u8 rs_isaggr; | ||
94 | u8 rs_moreaggr; | ||
95 | u8 rs_num_delims; | ||
96 | u8 rs_flags; | ||
97 | u32 evm0; | ||
98 | u32 evm1; | ||
99 | u32 evm2; | ||
100 | }; | ||
101 | |||
102 | #define ATH9K_RXERR_CRC 0x01 | ||
103 | #define ATH9K_RXERR_PHY 0x02 | ||
104 | #define ATH9K_RXERR_FIFO 0x04 | ||
105 | #define ATH9K_RXERR_DECRYPT 0x08 | ||
106 | #define ATH9K_RXERR_MIC 0x10 | ||
107 | |||
108 | #define ATH9K_RX_MORE 0x01 | ||
109 | #define ATH9K_RX_MORE_AGGR 0x02 | ||
110 | #define ATH9K_RX_GI 0x04 | ||
111 | #define ATH9K_RX_2040 0x08 | ||
112 | #define ATH9K_RX_DELIM_CRC_PRE 0x10 | ||
113 | #define ATH9K_RX_DELIM_CRC_POST 0x20 | ||
114 | #define ATH9K_RX_DECRYPT_BUSY 0x40 | ||
115 | |||
116 | #define ATH9K_RXKEYIX_INVALID ((u8)-1) | ||
117 | #define ATH9K_TXKEYIX_INVALID ((u32)-1) | ||
118 | |||
119 | struct ath_desc { | ||
120 | u32 ds_link; | ||
121 | u32 ds_data; | ||
122 | u32 ds_ctl0; | ||
123 | u32 ds_ctl1; | ||
124 | u32 ds_hw[20]; | ||
125 | union { | ||
126 | struct ath_tx_status tx; | ||
127 | struct ath_rx_status rx; | ||
128 | void *stats; | ||
129 | } ds_us; | ||
130 | void *ds_vdata; | ||
131 | } __packed; | ||
132 | |||
133 | #define ds_txstat ds_us.tx | ||
134 | #define ds_rxstat ds_us.rx | ||
135 | #define ds_stat ds_us.stats | ||
136 | |||
137 | #define ATH9K_TXDESC_CLRDMASK 0x0001 | ||
138 | #define ATH9K_TXDESC_NOACK 0x0002 | ||
139 | #define ATH9K_TXDESC_RTSENA 0x0004 | ||
140 | #define ATH9K_TXDESC_CTSENA 0x0008 | ||
141 | #define ATH9K_TXDESC_INTREQ 0x0010 | ||
142 | #define ATH9K_TXDESC_VEOL 0x0020 | ||
143 | #define ATH9K_TXDESC_EXT_ONLY 0x0040 | ||
144 | #define ATH9K_TXDESC_EXT_AND_CTL 0x0080 | ||
145 | #define ATH9K_TXDESC_VMF 0x0100 | ||
146 | #define ATH9K_TXDESC_FRAG_IS_ON 0x0200 | ||
147 | |||
148 | #define ATH9K_RXDESC_INTREQ 0x0020 | ||
149 | |||
150 | enum hal_capability_type { | ||
151 | HAL_CAP_CIPHER = 0, | ||
152 | HAL_CAP_TKIP_MIC, | ||
153 | HAL_CAP_TKIP_SPLIT, | ||
154 | HAL_CAP_PHYCOUNTERS, | ||
155 | HAL_CAP_DIVERSITY, | ||
156 | HAL_CAP_PSPOLL, | ||
157 | HAL_CAP_TXPOW, | ||
158 | HAL_CAP_PHYDIAG, | ||
159 | HAL_CAP_MCAST_KEYSRCH, | ||
160 | HAL_CAP_TSF_ADJUST, | ||
161 | HAL_CAP_WME_TKIPMIC, | ||
162 | HAL_CAP_RFSILENT, | ||
163 | HAL_CAP_ANT_CFG_2GHZ, | ||
164 | HAL_CAP_ANT_CFG_5GHZ | ||
165 | }; | ||
166 | |||
167 | struct hal_capabilities { | ||
168 | u32 halChanSpreadSupport:1, | ||
169 | halChapTuningSupport:1, | ||
170 | halMicAesCcmSupport:1, | ||
171 | halMicCkipSupport:1, | ||
172 | halMicTkipSupport:1, | ||
173 | halCipherAesCcmSupport:1, | ||
174 | halCipherCkipSupport:1, | ||
175 | halCipherTkipSupport:1, | ||
176 | halVEOLSupport:1, | ||
177 | halBssIdMaskSupport:1, | ||
178 | halMcastKeySrchSupport:1, | ||
179 | halTsfAddSupport:1, | ||
180 | halChanHalfRate:1, | ||
181 | halChanQuarterRate:1, | ||
182 | halHTSupport:1, | ||
183 | halGTTSupport:1, | ||
184 | halFastCCSupport:1, | ||
185 | halRfSilentSupport:1, | ||
186 | halWowSupport:1, | ||
187 | halCSTSupport:1, | ||
188 | halEnhancedPmSupport:1, | ||
189 | halAutoSleepSupport:1, | ||
190 | hal4kbSplitTransSupport:1, | ||
191 | halWowMatchPatternExact:1; | ||
192 | u32 halWirelessModes; | ||
193 | u16 halTotalQueues; | ||
194 | u16 halKeyCacheSize; | ||
195 | u16 halLow5GhzChan, halHigh5GhzChan; | ||
196 | u16 halLow2GhzChan, halHigh2GhzChan; | ||
197 | u16 halNumMRRetries; | ||
198 | u16 halRtsAggrLimit; | ||
199 | u8 halTxChainMask; | ||
200 | u8 halRxChainMask; | ||
201 | u16 halTxTrigLevelMax; | ||
202 | u16 halRegCap; | ||
203 | u8 halNumGpioPins; | ||
204 | u8 halNumAntCfg2GHz; | ||
205 | u8 halNumAntCfg5GHz; | ||
206 | }; | ||
207 | |||
208 | struct hal_ops_config { | ||
209 | int ath_hal_dma_beacon_response_time; | ||
210 | int ath_hal_sw_beacon_response_time; | ||
211 | int ath_hal_additional_swba_backoff; | ||
212 | int ath_hal_6mb_ack; | ||
213 | int ath_hal_cwmIgnoreExtCCA; | ||
214 | u8 ath_hal_pciePowerSaveEnable; | ||
215 | u8 ath_hal_pcieL1SKPEnable; | ||
216 | u8 ath_hal_pcieClockReq; | ||
217 | u32 ath_hal_pcieWaen; | ||
218 | int ath_hal_pciePowerReset; | ||
219 | u8 ath_hal_pcieRestore; | ||
220 | u8 ath_hal_analogShiftReg; | ||
221 | u8 ath_hal_htEnable; | ||
222 | u32 ath_hal_ofdmTrigLow; | ||
223 | u32 ath_hal_ofdmTrigHigh; | ||
224 | u32 ath_hal_cckTrigHigh; | ||
225 | u32 ath_hal_cckTrigLow; | ||
226 | u32 ath_hal_enableANI; | ||
227 | u8 ath_hal_noiseImmunityLvl; | ||
228 | u32 ath_hal_ofdmWeakSigDet; | ||
229 | u32 ath_hal_cckWeakSigThr; | ||
230 | u8 ath_hal_spurImmunityLvl; | ||
231 | u8 ath_hal_firStepLvl; | ||
232 | int8_t ath_hal_rssiThrHigh; | ||
233 | int8_t ath_hal_rssiThrLow; | ||
234 | u16 ath_hal_diversityControl; | ||
235 | u16 ath_hal_antennaSwitchSwap; | ||
236 | int ath_hal_serializeRegMode; | ||
237 | int ath_hal_intrMitigation; | ||
238 | #define SPUR_DISABLE 0 | ||
239 | #define SPUR_ENABLE_IOCTL 1 | ||
240 | #define SPUR_ENABLE_EEPROM 2 | ||
241 | #define AR_EEPROM_MODAL_SPURS 5 | ||
242 | #define AR_SPUR_5413_1 1640 | ||
243 | #define AR_SPUR_5413_2 1200 | ||
244 | #define AR_NO_SPUR 0x8000 | ||
245 | #define AR_BASE_FREQ_2GHZ 2300 | ||
246 | #define AR_BASE_FREQ_5GHZ 4900 | ||
247 | #define AR_SPUR_FEEQ_BOUND_HT40 19 | ||
248 | #define AR_SPUR_FEEQ_BOUND_HT20 10 | ||
249 | int ath_hal_spurMode; | ||
250 | u16 ath_hal_spurChans[AR_EEPROM_MODAL_SPURS][2]; | ||
251 | }; | ||
252 | |||
253 | enum ath9k_tx_queue { | ||
254 | ATH9K_TX_QUEUE_INACTIVE = 0, | ||
255 | ATH9K_TX_QUEUE_DATA, | ||
256 | ATH9K_TX_QUEUE_BEACON, | ||
257 | ATH9K_TX_QUEUE_CAB, | ||
258 | ATH9K_TX_QUEUE_UAPSD, | ||
259 | ATH9K_TX_QUEUE_PSPOLL | ||
260 | }; | ||
261 | |||
262 | #define ATH9K_NUM_TX_QUEUES 10 | ||
263 | |||
264 | enum ath9k_tx_queue_subtype { | ||
265 | ATH9K_WME_AC_BK = 0, | ||
266 | ATH9K_WME_AC_BE, | ||
267 | ATH9K_WME_AC_VI, | ||
268 | ATH9K_WME_AC_VO, | ||
269 | ATH9K_WME_UPSD | ||
270 | }; | ||
271 | |||
272 | enum ath9k_tx_queue_flags { | ||
273 | TXQ_FLAG_TXOKINT_ENABLE = 0x0001, | ||
274 | TXQ_FLAG_TXERRINT_ENABLE = 0x0001, | ||
275 | TXQ_FLAG_TXDESCINT_ENABLE = 0x0002, | ||
276 | TXQ_FLAG_TXEOLINT_ENABLE = 0x0004, | ||
277 | TXQ_FLAG_TXURNINT_ENABLE = 0x0008, | ||
278 | TXQ_FLAG_BACKOFF_DISABLE = 0x0010, | ||
279 | TXQ_FLAG_COMPRESSION_ENABLE = 0x0020, | ||
280 | TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040, | ||
281 | TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080, | ||
282 | }; | ||
283 | |||
284 | struct ath9k_txq_info { | ||
285 | u32 tqi_ver; | ||
286 | enum ath9k_tx_queue_subtype tqi_subtype; | ||
287 | enum ath9k_tx_queue_flags tqi_qflags; | ||
288 | u32 tqi_priority; | ||
289 | u32 tqi_aifs; | ||
290 | u32 tqi_cwmin; | ||
291 | u32 tqi_cwmax; | ||
292 | u16 tqi_shretry; | ||
293 | u16 tqi_lgretry; | ||
294 | u32 tqi_cbrPeriod; | ||
295 | u32 tqi_cbrOverflowLimit; | ||
296 | u32 tqi_burstTime; | ||
297 | u32 tqi_readyTime; | ||
298 | u32 tqi_compBuf; | ||
299 | }; | ||
300 | |||
301 | #define ATH9K_TXQ_USEDEFAULT ((u32) -1) | ||
302 | |||
303 | #define ATH9K_DECOMP_MASK_SIZE 128 | ||
304 | #define ATH9K_READY_TIME_LO_BOUND 50 | ||
305 | #define ATH9K_READY_TIME_HI_BOUND 96 | ||
306 | |||
307 | enum ath9k_pkt_type { | ||
308 | ATH9K_PKT_TYPE_NORMAL = 0, | ||
309 | ATH9K_PKT_TYPE_ATIM, | ||
310 | ATH9K_PKT_TYPE_PSPOLL, | ||
311 | ATH9K_PKT_TYPE_BEACON, | ||
312 | ATH9K_PKT_TYPE_PROBE_RESP, | ||
313 | ATH9K_PKT_TYPE_CHIRP, | ||
314 | ATH9K_PKT_TYPE_GRP_POLL, | ||
315 | }; | ||
316 | |||
317 | struct ath9k_tx_queue_info { | ||
318 | u32 tqi_ver; | ||
319 | enum ath9k_tx_queue tqi_type; | ||
320 | enum ath9k_tx_queue_subtype tqi_subtype; | ||
321 | enum ath9k_tx_queue_flags tqi_qflags; | ||
322 | u32 tqi_priority; | ||
323 | u32 tqi_aifs; | ||
324 | u32 tqi_cwmin; | ||
325 | u32 tqi_cwmax; | ||
326 | u16 tqi_shretry; | ||
327 | u16 tqi_lgretry; | ||
328 | u32 tqi_cbrPeriod; | ||
329 | u32 tqi_cbrOverflowLimit; | ||
330 | u32 tqi_burstTime; | ||
331 | u32 tqi_readyTime; | ||
332 | u32 tqi_physCompBuf; | ||
333 | u32 tqi_intFlags; | ||
334 | }; | ||
335 | |||
336 | enum ath9k_rx_filter { | ||
337 | ATH9K_RX_FILTER_UCAST = 0x00000001, | ||
338 | ATH9K_RX_FILTER_MCAST = 0x00000002, | ||
339 | ATH9K_RX_FILTER_BCAST = 0x00000004, | ||
340 | ATH9K_RX_FILTER_CONTROL = 0x00000008, | ||
341 | ATH9K_RX_FILTER_BEACON = 0x00000010, | ||
342 | ATH9K_RX_FILTER_PROM = 0x00000020, | ||
343 | ATH9K_RX_FILTER_PROBEREQ = 0x00000080, | ||
344 | ATH9K_RX_FILTER_PSPOLL = 0x00004000, | ||
345 | ATH9K_RX_FILTER_PHYERR = 0x00000100, | ||
346 | ATH9K_RX_FILTER_PHYRADAR = 0x00002000, | ||
347 | }; | ||
348 | |||
349 | enum ath9k_int { | ||
350 | ATH9K_INT_RX = 0x00000001, | ||
351 | ATH9K_INT_RXDESC = 0x00000002, | ||
352 | ATH9K_INT_RXNOFRM = 0x00000008, | ||
353 | ATH9K_INT_RXEOL = 0x00000010, | ||
354 | ATH9K_INT_RXORN = 0x00000020, | ||
355 | ATH9K_INT_TX = 0x00000040, | ||
356 | ATH9K_INT_TXDESC = 0x00000080, | ||
357 | ATH9K_INT_TIM_TIMER = 0x00000100, | ||
358 | ATH9K_INT_TXURN = 0x00000800, | ||
359 | ATH9K_INT_MIB = 0x00001000, | ||
360 | ATH9K_INT_RXPHY = 0x00004000, | ||
361 | ATH9K_INT_RXKCM = 0x00008000, | ||
362 | ATH9K_INT_SWBA = 0x00010000, | ||
363 | ATH9K_INT_BMISS = 0x00040000, | ||
364 | ATH9K_INT_BNR = 0x00100000, | ||
365 | ATH9K_INT_TIM = 0x00200000, | ||
366 | ATH9K_INT_DTIM = 0x00400000, | ||
367 | ATH9K_INT_DTIMSYNC = 0x00800000, | ||
368 | ATH9K_INT_GPIO = 0x01000000, | ||
369 | ATH9K_INT_CABEND = 0x02000000, | ||
370 | ATH9K_INT_CST = 0x10000000, | ||
371 | ATH9K_INT_GTT = 0x20000000, | ||
372 | ATH9K_INT_FATAL = 0x40000000, | ||
373 | ATH9K_INT_GLOBAL = 0x80000000, | ||
374 | ATH9K_INT_BMISC = ATH9K_INT_TIM | | ||
375 | ATH9K_INT_DTIM | | ||
376 | ATH9K_INT_DTIMSYNC | | ||
377 | ATH9K_INT_CABEND, | ||
378 | ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM | | ||
379 | ATH9K_INT_RXDESC | | ||
380 | ATH9K_INT_RXEOL | | ||
381 | ATH9K_INT_RXORN | | ||
382 | ATH9K_INT_TXURN | | ||
383 | ATH9K_INT_TXDESC | | ||
384 | ATH9K_INT_MIB | | ||
385 | ATH9K_INT_RXPHY | | ||
386 | ATH9K_INT_RXKCM | | ||
387 | ATH9K_INT_SWBA | | ||
388 | ATH9K_INT_BMISS | | ||
389 | ATH9K_INT_GPIO, | ||
390 | ATH9K_INT_NOCARD = 0xffffffff | ||
391 | }; | ||
392 | |||
393 | struct ath9k_rate_table { | ||
394 | int rateCount; | ||
395 | u8 rateCodeToIndex[256]; | ||
396 | struct { | ||
397 | u8 valid; | ||
398 | u8 phy; | ||
399 | u32 rateKbps; | ||
400 | u8 rateCode; | ||
401 | u8 shortPreamble; | ||
402 | u8 dot11Rate; | ||
403 | u8 controlRate; | ||
404 | u16 lpAckDuration; | ||
405 | u16 spAckDuration; | ||
406 | } info[32]; | ||
407 | }; | ||
408 | |||
409 | #define ATH9K_RATESERIES_RTS_CTS 0x0001 | ||
410 | #define ATH9K_RATESERIES_2040 0x0002 | ||
411 | #define ATH9K_RATESERIES_HALFGI 0x0004 | ||
412 | |||
413 | struct ath9k_11n_rate_series { | ||
414 | u32 Tries; | ||
415 | u32 Rate; | ||
416 | u32 PktDuration; | ||
417 | u32 ChSel; | ||
418 | u32 RateFlags; | ||
419 | }; | ||
420 | |||
421 | #define CHANNEL_CW_INT 0x00002 | ||
422 | #define CHANNEL_CCK 0x00020 | ||
423 | #define CHANNEL_OFDM 0x00040 | ||
424 | #define CHANNEL_2GHZ 0x00080 | ||
425 | #define CHANNEL_5GHZ 0x00100 | ||
426 | #define CHANNEL_PASSIVE 0x00200 | ||
427 | #define CHANNEL_DYN 0x00400 | ||
428 | #define CHANNEL_HALF 0x04000 | ||
429 | #define CHANNEL_QUARTER 0x08000 | ||
430 | #define CHANNEL_HT20 0x10000 | ||
431 | #define CHANNEL_HT40PLUS 0x20000 | ||
432 | #define CHANNEL_HT40MINUS 0x40000 | ||
433 | |||
434 | #define CHANNEL_INTERFERENCE 0x01 | ||
435 | #define CHANNEL_DFS 0x02 | ||
436 | #define CHANNEL_4MS_LIMIT 0x04 | ||
437 | #define CHANNEL_DFS_CLEAR 0x08 | ||
438 | #define CHANNEL_DISALLOW_ADHOC 0x10 | ||
439 | #define CHANNEL_PER_11D_ADHOC 0x20 | ||
440 | |||
441 | #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) | ||
442 | #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) | ||
443 | #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) | ||
444 | #define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20) | ||
445 | #define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20) | ||
446 | #define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS) | ||
447 | #define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS) | ||
448 | #define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS) | ||
449 | #define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS) | ||
450 | #define CHANNEL_ALL \ | ||
451 | (CHANNEL_OFDM| \ | ||
452 | CHANNEL_CCK| \ | ||
453 | CHANNEL_2GHZ | \ | ||
454 | CHANNEL_5GHZ | \ | ||
455 | CHANNEL_HT20 | \ | ||
456 | CHANNEL_HT40PLUS | \ | ||
457 | CHANNEL_HT40MINUS) | ||
458 | |||
459 | struct ath9k_channel { | ||
460 | u16 channel; | ||
461 | u32 channelFlags; | ||
462 | u8 privFlags; | ||
463 | int8_t maxRegTxPower; | ||
464 | int8_t maxTxPower; | ||
465 | int8_t minTxPower; | ||
466 | u32 chanmode; | ||
467 | int32_t CalValid; | ||
468 | bool oneTimeCalsDone; | ||
469 | int8_t iCoff; | ||
470 | int8_t qCoff; | ||
471 | int16_t rawNoiseFloor; | ||
472 | int8_t antennaMax; | ||
473 | u32 regDmnFlags; | ||
474 | u32 conformanceTestLimit[3]; /* 0:11a, 1: 11b, 2:11g */ | ||
475 | #ifdef ATH_NF_PER_CHAN | ||
476 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | ||
477 | #endif | ||
478 | }; | ||
479 | |||
480 | #define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \ | ||
481 | (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \ | ||
482 | (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \ | ||
483 | (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS)) | ||
484 | #define IS_CHAN_B(_c) (((_c)->channelFlags & CHANNEL_B) == CHANNEL_B) | ||
485 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | ||
486 | (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ | ||
487 | (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ | ||
488 | (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) | ||
489 | #define IS_CHAN_CCK(_c) (((_c)->channelFlags & CHANNEL_CCK) != 0) | ||
490 | #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) | ||
491 | #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) | ||
492 | #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) | ||
493 | #define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0) | ||
494 | #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) | ||
495 | #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) | ||
496 | |||
497 | /* These macros check chanmode and not channelFlags */ | ||
498 | #define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ | ||
499 | ((_c)->chanmode == CHANNEL_G_HT20)) | ||
500 | #define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ | ||
501 | ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \ | ||
502 | ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \ | ||
503 | ((_c)->chanmode == CHANNEL_G_HT40MINUS)) | ||
504 | #define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c))) | ||
505 | |||
506 | #define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990) | ||
507 | #define IS_CHAN_A_5MHZ_SPACED(_c) \ | ||
508 | ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ | ||
509 | (((_c)->channel % 20) != 0) && \ | ||
510 | (((_c)->channel % 10) != 0)) | ||
511 | |||
512 | struct ath9k_keyval { | ||
513 | u8 kv_type; | ||
514 | u8 kv_pad; | ||
515 | u16 kv_len; | ||
516 | u8 kv_val[16]; | ||
517 | u8 kv_mic[8]; | ||
518 | u8 kv_txmic[8]; | ||
519 | }; | ||
520 | |||
521 | enum ath9k_key_type { | ||
522 | ATH9K_KEY_TYPE_CLEAR, | ||
523 | ATH9K_KEY_TYPE_WEP, | ||
524 | ATH9K_KEY_TYPE_AES, | ||
525 | ATH9K_KEY_TYPE_TKIP, | ||
526 | }; | ||
527 | |||
528 | enum ath9k_cipher { | ||
529 | ATH9K_CIPHER_WEP = 0, | ||
530 | ATH9K_CIPHER_AES_OCB = 1, | ||
531 | ATH9K_CIPHER_AES_CCM = 2, | ||
532 | ATH9K_CIPHER_CKIP = 3, | ||
533 | ATH9K_CIPHER_TKIP = 4, | ||
534 | ATH9K_CIPHER_CLR = 5, | ||
535 | ATH9K_CIPHER_MIC = 127 | ||
536 | }; | ||
537 | |||
538 | #define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001 | ||
539 | #define AR_EEPROM_EEPCAP_AES_DIS 0x0002 | ||
540 | #define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004 | ||
541 | #define AR_EEPROM_EEPCAP_BURST_DIS 0x0008 | ||
542 | #define AR_EEPROM_EEPCAP_MAXQCU 0x01F0 | ||
543 | #define AR_EEPROM_EEPCAP_MAXQCU_S 4 | ||
544 | #define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200 | ||
545 | #define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000 | ||
546 | #define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12 | ||
547 | |||
548 | #define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 | ||
549 | #define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 | ||
550 | #define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100 | ||
551 | #define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 | ||
552 | #define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 | ||
553 | #define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 | ||
554 | |||
555 | #define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000 | ||
556 | #define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000 | ||
557 | |||
558 | #define SD_NO_CTL 0xE0 | ||
559 | #define NO_CTL 0xff | ||
560 | #define CTL_MODE_M 7 | ||
561 | #define CTL_11A 0 | ||
562 | #define CTL_11B 1 | ||
563 | #define CTL_11G 2 | ||
564 | #define CTL_2GHT20 5 | ||
565 | #define CTL_5GHT20 6 | ||
566 | #define CTL_2GHT40 7 | ||
567 | #define CTL_5GHT40 8 | ||
568 | |||
569 | #define AR_EEPROM_MAC(i) (0x1d+(i)) | ||
570 | #define EEP_SCALE 100 | ||
571 | #define EEP_DELTA 10 | ||
572 | |||
573 | #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c | ||
574 | #define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 | ||
575 | #define AR_EEPROM_RFSILENT_POLARITY 0x0002 | ||
576 | #define AR_EEPROM_RFSILENT_POLARITY_S 1 | ||
577 | |||
578 | #define CTRY_DEBUG 0x1ff | ||
579 | #define CTRY_DEFAULT 0 | ||
580 | |||
581 | enum reg_ext_bitmap { | ||
582 | REG_EXT_JAPAN_MIDBAND = 1, | ||
583 | REG_EXT_FCC_DFS_HT40 = 2, | ||
584 | REG_EXT_JAPAN_NONDFS_HT40 = 3, | ||
585 | REG_EXT_JAPAN_DFS_HT40 = 4 | ||
586 | }; | ||
587 | |||
588 | struct ath9k_country_entry { | ||
589 | u16 countryCode; | ||
590 | u16 regDmnEnum; | ||
591 | u16 regDmn5G; | ||
592 | u16 regDmn2G; | ||
593 | u8 isMultidomain; | ||
594 | u8 iso[3]; | ||
595 | }; | ||
596 | |||
597 | #define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg) | ||
598 | #define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg) | ||
599 | |||
600 | #define SM(_v, _f) (((_v) << _f##_S) & _f) | ||
601 | #define MS(_v, _f) (((_v) & _f) >> _f##_S) | ||
602 | #define REG_RMW(_a, _r, _set, _clr) \ | ||
603 | REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set)) | ||
604 | #define REG_RMW_FIELD(_a, _r, _f, _v) \ | ||
605 | REG_WRITE(_a, _r, \ | ||
606 | (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) | ||
607 | #define REG_SET_BIT(_a, _r, _f) \ | ||
608 | REG_WRITE(_a, _r, REG_READ(_a, _r) | _f) | ||
609 | #define REG_CLR_BIT(_a, _r, _f) \ | ||
610 | REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) | ||
611 | |||
612 | #define ATH9K_COMP_BUF_MAX_SIZE 9216 | ||
613 | #define ATH9K_COMP_BUF_ALIGN_SIZE 512 | ||
614 | |||
615 | #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 | ||
616 | |||
617 | #define INIT_AIFS 2 | ||
618 | #define INIT_CWMIN 15 | ||
619 | #define INIT_CWMIN_11B 31 | ||
620 | #define INIT_CWMAX 1023 | ||
621 | #define INIT_SH_RETRY 10 | ||
622 | #define INIT_LG_RETRY 10 | ||
623 | #define INIT_SSH_RETRY 32 | ||
624 | #define INIT_SLG_RETRY 32 | ||
625 | |||
626 | #define WLAN_CTRL_FRAME_SIZE (2+2+6+4) | ||
627 | |||
628 | #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) | ||
629 | #define ATH_AMPDU_LIMIT_DEFAULT ATH_AMPDU_LIMIT_MAX | ||
630 | |||
631 | #define IEEE80211_WEP_IVLEN 3 | ||
632 | #define IEEE80211_WEP_KIDLEN 1 | ||
633 | #define IEEE80211_WEP_CRCLEN 4 | ||
634 | #define IEEE80211_MAX_MPDU_LEN (3840 + FCS_LEN + \ | ||
635 | (IEEE80211_WEP_IVLEN + \ | ||
636 | IEEE80211_WEP_KIDLEN + \ | ||
637 | IEEE80211_WEP_CRCLEN)) | ||
638 | #define IEEE80211_MAX_LEN (2300 + FCS_LEN + \ | ||
639 | (IEEE80211_WEP_IVLEN + \ | ||
640 | IEEE80211_WEP_KIDLEN + \ | ||
641 | IEEE80211_WEP_CRCLEN)) | ||
642 | |||
643 | #define MAX_REG_ADD_COUNT 129 | ||
644 | #define MAX_RATE_POWER 63 | ||
645 | |||
646 | enum ath9k_power_mode { | ||
647 | ATH9K_PM_AWAKE = 0, | ||
648 | ATH9K_PM_FULL_SLEEP, | ||
649 | ATH9K_PM_NETWORK_SLEEP, | ||
650 | ATH9K_PM_UNDEFINED | ||
651 | }; | ||
652 | |||
653 | #define HAL_ANTENNA_MIN_MODE 0 | ||
654 | #define HAL_ANTENNA_FIXED_A 1 | ||
655 | #define HAL_ANTENNA_FIXED_B 2 | ||
656 | #define HAL_ANTENNA_MAX_MODE 3 | ||
657 | |||
658 | struct ath9k_mib_stats { | ||
659 | u32 ackrcv_bad; | ||
660 | u32 rts_bad; | ||
661 | u32 rts_good; | ||
662 | u32 fcs_bad; | ||
663 | u32 beacons; | ||
664 | }; | ||
665 | |||
666 | enum ath9k_ant_setting { | ||
667 | ATH9K_ANT_VARIABLE = 0, | ||
668 | ATH9K_ANT_FIXED_A, | ||
669 | ATH9K_ANT_FIXED_B | ||
670 | }; | ||
671 | |||
672 | enum ath9k_opmode { | ||
673 | ATH9K_M_STA = 1, | ||
674 | ATH9K_M_IBSS = 0, | ||
675 | ATH9K_M_HOSTAP = 6, | ||
676 | ATH9K_M_MONITOR = 8 | ||
677 | }; | ||
678 | |||
679 | #define ATH9K_SLOT_TIME_6 6 | ||
680 | #define ATH9K_SLOT_TIME_9 9 | ||
681 | #define ATH9K_SLOT_TIME_20 20 | ||
682 | |||
683 | enum ath9k_ht_macmode { | ||
684 | ATH9K_HT_MACMODE_20 = 0, | ||
685 | ATH9K_HT_MACMODE_2040 = 1, | ||
686 | }; | ||
687 | |||
688 | enum ath9k_ht_extprotspacing { | ||
689 | ATH9K_HT_EXTPROTSPACING_20 = 0, | ||
690 | ATH9K_HT_EXTPROTSPACING_25 = 1, | ||
691 | }; | ||
692 | |||
693 | struct ath9k_ht_cwm { | ||
694 | enum ath9k_ht_macmode ht_macmode; | ||
695 | enum ath9k_ht_extprotspacing ht_extprotspacing; | ||
696 | }; | ||
697 | |||
698 | enum hal_freq_band { | ||
699 | HAL_FREQ_BAND_5GHZ = 0, | ||
700 | HAL_FREQ_BAND_2GHZ = 1, | ||
701 | }; | ||
702 | |||
703 | enum ath9k_ani_cmd { | ||
704 | ATH9K_ANI_PRESENT = 0x1, | ||
705 | ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, | ||
706 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4, | ||
707 | ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8, | ||
708 | ATH9K_ANI_FIRSTEP_LEVEL = 0x10, | ||
709 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, | ||
710 | ATH9K_ANI_MODE = 0x40, | ||
711 | ATH9K_ANI_PHYERR_RESET = 0x80, | ||
712 | ATH9K_ANI_ALL = 0xff | ||
713 | }; | ||
714 | |||
715 | enum phytype { | ||
716 | PHY_DS, | ||
717 | PHY_FH, | ||
718 | PHY_OFDM, | ||
719 | PHY_HT, | ||
720 | PHY_MAX | ||
721 | }; | ||
722 | #define PHY_CCK PHY_DS | ||
723 | |||
724 | enum start_adhoc_option { | ||
725 | START_ADHOC_NO_11A, | ||
726 | START_ADHOC_PER_11D, | ||
727 | START_ADHOC_IN_11A, | ||
728 | START_ADHOC_IN_11B, | ||
729 | }; | ||
730 | |||
731 | enum ath9k_tp_scale { | ||
732 | ATH9K_TP_SCALE_MAX = 0, | ||
733 | ATH9K_TP_SCALE_50, | ||
734 | ATH9K_TP_SCALE_25, | ||
735 | ATH9K_TP_SCALE_12, | ||
736 | ATH9K_TP_SCALE_MIN | ||
737 | }; | ||
738 | |||
739 | enum ser_reg_mode { | ||
740 | SER_REG_MODE_OFF = 0, | ||
741 | SER_REG_MODE_ON = 1, | ||
742 | SER_REG_MODE_AUTO = 2, | ||
743 | }; | ||
744 | |||
745 | #define AR_PHY_CCA_MAX_GOOD_VALUE -85 | ||
746 | #define AR_PHY_CCA_MAX_HIGH_VALUE -62 | ||
747 | #define AR_PHY_CCA_MIN_BAD_VALUE -121 | ||
748 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 | ||
749 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 | ||
750 | |||
751 | #define ATH9K_NF_CAL_HIST_MAX 5 | ||
752 | #define NUM_NF_READINGS 6 | ||
753 | |||
754 | struct ath9k_nfcal_hist { | ||
755 | int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX]; | ||
756 | u8 currIndex; | ||
757 | int16_t privNF; | ||
758 | u8 invalidNFcount; | ||
759 | }; | ||
760 | |||
761 | struct ath9k_beacon_state { | ||
762 | u32 bs_nexttbtt; | ||
763 | u32 bs_nextdtim; | ||
764 | u32 bs_intval; | ||
765 | #define ATH9K_BEACON_PERIOD 0x0000ffff | ||
766 | #define ATH9K_BEACON_ENA 0x00800000 | ||
767 | #define ATH9K_BEACON_RESET_TSF 0x01000000 | ||
768 | u32 bs_dtimperiod; | ||
769 | u16 bs_cfpperiod; | ||
770 | u16 bs_cfpmaxduration; | ||
771 | u32 bs_cfpnext; | ||
772 | u16 bs_timoffset; | ||
773 | u16 bs_bmissthreshold; | ||
774 | u32 bs_sleepduration; | ||
775 | }; | ||
776 | |||
777 | struct ath9k_node_stats { | ||
778 | u32 ns_avgbrssi; | ||
779 | u32 ns_avgrssi; | ||
780 | u32 ns_avgtxrssi; | ||
781 | u32 ns_avgtxrate; | ||
782 | }; | ||
783 | |||
784 | #define ATH9K_RSSI_EP_MULTIPLIER (1<<7) | ||
785 | |||
786 | enum ath9k_gpio_output_mux_type { | ||
787 | ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT, | ||
788 | ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, | ||
789 | ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, | ||
790 | ATH9K_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, | ||
791 | ATH9K_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, | ||
792 | ATH9K_GPIO_OUTPUT_MUX_NUM_ENTRIES | ||
793 | }; | ||
794 | |||
795 | enum { | ||
796 | ATH9K_RESET_POWER_ON, | ||
797 | ATH9K_RESET_WARM, | ||
798 | ATH9K_RESET_COLD, | ||
799 | }; | ||
800 | |||
801 | #define AH_USE_EEPROM 0x1 | ||
802 | |||
803 | struct ath_hal { | ||
804 | u32 ah_magic; | ||
805 | u16 ah_devid; | ||
806 | u16 ah_subvendorid; | ||
807 | struct ath_softc *ah_sc; | ||
808 | void __iomem *ah_sh; | ||
809 | u16 ah_countryCode; | ||
810 | u32 ah_macVersion; | ||
811 | u16 ah_macRev; | ||
812 | u16 ah_phyRev; | ||
813 | u16 ah_analog5GhzRev; | ||
814 | u16 ah_analog2GhzRev; | ||
815 | u8 ah_decompMask[ATH9K_DECOMP_MASK_SIZE]; | ||
816 | u32 ah_flags; | ||
817 | enum ath9k_opmode ah_opmode; | ||
818 | struct hal_ops_config ah_config; | ||
819 | struct hal_capabilities ah_caps; | ||
820 | int16_t ah_powerLimit; | ||
821 | u16 ah_maxPowerLevel; | ||
822 | u32 ah_tpScale; | ||
823 | u16 ah_currentRD; | ||
824 | u16 ah_currentRDExt; | ||
825 | u16 ah_currentRDInUse; | ||
826 | u16 ah_currentRD5G; | ||
827 | u16 ah_currentRD2G; | ||
828 | char ah_iso[4]; | ||
829 | enum start_adhoc_option ah_adHocMode; | ||
830 | bool ah_commonMode; | ||
831 | struct ath9k_channel ah_channels[150]; | ||
832 | u32 ah_nchan; | ||
833 | struct ath9k_channel *ah_curchan; | ||
834 | u16 ah_rfsilent; | ||
835 | bool ah_rfkillEnabled; | ||
836 | bool ah_isPciExpress; | ||
837 | u16 ah_txTrigLevel; | ||
838 | #ifndef ATH_NF_PER_CHAN | ||
839 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | ||
840 | #endif | ||
841 | }; | ||
842 | |||
843 | enum wireless_mode { | ||
844 | WIRELESS_MODE_11a = 0, | ||
845 | WIRELESS_MODE_11b = 2, | ||
846 | WIRELESS_MODE_11g = 3, | ||
847 | WIRELESS_MODE_11NA_HT20 = 6, | ||
848 | WIRELESS_MODE_11NG_HT20 = 7, | ||
849 | WIRELESS_MODE_11NA_HT40PLUS = 8, | ||
850 | WIRELESS_MODE_11NA_HT40MINUS = 9, | ||
851 | WIRELESS_MODE_11NG_HT40PLUS = 10, | ||
852 | WIRELESS_MODE_11NG_HT40MINUS = 11, | ||
853 | WIRELESS_MODE_MAX | ||
854 | }; | ||
855 | |||
856 | enum { | ||
857 | ATH9K_MODE_SEL_11A = 0x00001, | ||
858 | ATH9K_MODE_SEL_11B = 0x00002, | ||
859 | ATH9K_MODE_SEL_11G = 0x00004, | ||
860 | ATH9K_MODE_SEL_11NG_HT20 = 0x00008, | ||
861 | ATH9K_MODE_SEL_11NA_HT20 = 0x00010, | ||
862 | ATH9K_MODE_SEL_11NG_HT40PLUS = 0x00020, | ||
863 | ATH9K_MODE_SEL_11NG_HT40MINUS = 0x00040, | ||
864 | ATH9K_MODE_SEL_11NA_HT40PLUS = 0x00080, | ||
865 | ATH9K_MODE_SEL_11NA_HT40MINUS = 0x00100, | ||
866 | ATH9K_MODE_SEL_2GHZ = (ATH9K_MODE_SEL_11B | | ||
867 | ATH9K_MODE_SEL_11G | | ||
868 | ATH9K_MODE_SEL_11NG_HT20), | ||
869 | ATH9K_MODE_SEL_5GHZ = (ATH9K_MODE_SEL_11A | | ||
870 | ATH9K_MODE_SEL_11NA_HT20), | ||
871 | ATH9K_MODE_SEL_ALL = 0xffffffff | ||
872 | }; | ||
873 | |||
874 | struct chan_centers { | ||
875 | u16 synth_center; | ||
876 | u16 ctl_center; | ||
877 | u16 ext_center; | ||
878 | }; | ||
879 | |||
880 | int ath_hal_getcapability(struct ath_hal *ah, | ||
881 | enum hal_capability_type type, | ||
882 | u32 capability, | ||
883 | u32 *result); | ||
884 | const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah, | ||
885 | u32 mode); | ||
886 | void ath9k_hw_detach(struct ath_hal *ah); | ||
887 | struct ath_hal *ath9k_hw_attach(u16 devid, | ||
888 | struct ath_softc *sc, | ||
889 | void __iomem *mem, | ||
890 | int *error); | ||
891 | bool ath9k_regd_init_channels(struct ath_hal *ah, | ||
892 | u32 maxchans, u32 *nchans, | ||
893 | u8 *regclassids, | ||
894 | u32 maxregids, u32 *nregids, | ||
895 | u16 cc, u32 modeSelect, | ||
896 | bool enableOutdoor, | ||
897 | bool enableExtendedChannels); | ||
898 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); | ||
899 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, | ||
900 | enum ath9k_int ints); | ||
901 | bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | ||
902 | struct ath9k_channel *chan, | ||
903 | enum ath9k_ht_macmode macmode, | ||
904 | u8 txchainmask, u8 rxchainmask, | ||
905 | enum ath9k_ht_extprotspacing extprotspacing, | ||
906 | bool bChannelChange, | ||
907 | int *status); | ||
908 | bool ath9k_hw_phy_disable(struct ath_hal *ah); | ||
909 | void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan, | ||
910 | bool *isCalDone); | ||
911 | void ath9k_hw_ani_monitor(struct ath_hal *ah, | ||
912 | const struct ath9k_node_stats *stats, | ||
913 | struct ath9k_channel *chan); | ||
914 | bool ath9k_hw_calibrate(struct ath_hal *ah, | ||
915 | struct ath9k_channel *chan, | ||
916 | u8 rxchainmask, | ||
917 | bool longcal, | ||
918 | bool *isCalDone); | ||
919 | int16_t ath9k_hw_getchan_noise(struct ath_hal *ah, | ||
920 | struct ath9k_channel *chan); | ||
921 | void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, | ||
922 | u16 assocId); | ||
923 | void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits); | ||
924 | void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, | ||
925 | u16 assocId); | ||
926 | bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q); | ||
927 | void ath9k_hw_reset_tsf(struct ath_hal *ah); | ||
928 | bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry); | ||
929 | bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, | ||
930 | const u8 *mac); | ||
931 | bool ath9k_hw_set_keycache_entry(struct ath_hal *ah, | ||
932 | u16 entry, | ||
933 | const struct ath9k_keyval *k, | ||
934 | const u8 *mac, | ||
935 | int xorKey); | ||
936 | bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, | ||
937 | u32 setting); | ||
938 | void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore); | ||
939 | bool ath9k_hw_intrpend(struct ath_hal *ah); | ||
940 | bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked); | ||
941 | bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, | ||
942 | bool bIncTrigLevel); | ||
943 | void ath9k_hw_procmibevent(struct ath_hal *ah, | ||
944 | const struct ath9k_node_stats *stats); | ||
945 | bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set); | ||
946 | void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode); | ||
947 | bool ath9k_hw_phycounters(struct ath_hal *ah); | ||
948 | bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry); | ||
949 | bool ath9k_hw_getcapability(struct ath_hal *ah, | ||
950 | enum hal_capability_type type, | ||
951 | u32 capability, | ||
952 | u32 *result); | ||
953 | bool ath9k_hw_setcapability(struct ath_hal *ah, | ||
954 | enum hal_capability_type type, | ||
955 | u32 capability, | ||
956 | u32 setting, | ||
957 | int *status); | ||
958 | u32 ath9k_hw_getdefantenna(struct ath_hal *ah); | ||
959 | void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac); | ||
960 | void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask); | ||
961 | bool ath9k_hw_setbssidmask(struct ath_hal *ah, | ||
962 | const u8 *mask); | ||
963 | bool ath9k_hw_setpower(struct ath_hal *ah, | ||
964 | enum ath9k_power_mode mode); | ||
965 | enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah); | ||
966 | u64 ath9k_hw_gettsf64(struct ath_hal *ah); | ||
967 | u32 ath9k_hw_getdefantenna(struct ath_hal *ah); | ||
968 | bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us); | ||
969 | bool ath9k_hw_setantennaswitch(struct ath_hal *ah, | ||
970 | enum ath9k_ant_setting settings, | ||
971 | struct ath9k_channel *chan, | ||
972 | u8 *tx_chainmask, | ||
973 | u8 *rx_chainmask, | ||
974 | u8 *antenna_cfgd); | ||
975 | void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna); | ||
976 | int ath9k_hw_select_antconfig(struct ath_hal *ah, | ||
977 | u32 cfg); | ||
978 | bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, | ||
979 | u32 txdp); | ||
980 | bool ath9k_hw_txstart(struct ath_hal *ah, u32 q); | ||
981 | u16 ath9k_hw_computetxtime(struct ath_hal *ah, | ||
982 | const struct ath9k_rate_table *rates, | ||
983 | u32 frameLen, u16 rateix, | ||
984 | bool shortPreamble); | ||
985 | void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds, | ||
986 | struct ath_desc *lastds, | ||
987 | u32 durUpdateEn, u32 rtsctsRate, | ||
988 | u32 rtsctsDuration, | ||
989 | struct ath9k_11n_rate_series series[], | ||
990 | u32 nseries, u32 flags); | ||
991 | void ath9k_hw_set11n_burstduration(struct ath_hal *ah, | ||
992 | struct ath_desc *ds, | ||
993 | u32 burstDuration); | ||
994 | void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds); | ||
995 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); | ||
996 | bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q); | ||
997 | u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan); | ||
998 | u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah, | ||
999 | struct ath9k_channel *chan); | ||
1000 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); | ||
1001 | bool ath9k_hw_gettxqueueprops(struct ath_hal *ah, int q, | ||
1002 | struct ath9k_txq_info *qInfo); | ||
1003 | bool ath9k_hw_settxqueueprops(struct ath_hal *ah, int q, | ||
1004 | const struct ath9k_txq_info *qInfo); | ||
1005 | struct ath9k_channel *ath9k_regd_check_channel(struct ath_hal *ah, | ||
1006 | const struct ath9k_channel *c); | ||
1007 | void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
1008 | u32 pktLen, enum ath9k_pkt_type type, | ||
1009 | u32 txPower, u32 keyIx, | ||
1010 | enum ath9k_key_type keyType, u32 flags); | ||
1011 | bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
1012 | u32 segLen, bool firstSeg, | ||
1013 | bool lastSeg, | ||
1014 | const struct ath_desc *ds0); | ||
1015 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah, | ||
1016 | u32 *rxc_pcnt, | ||
1017 | u32 *rxf_pcnt, | ||
1018 | u32 *txf_pcnt); | ||
1019 | void ath9k_hw_dmaRegDump(struct ath_hal *ah); | ||
1020 | void ath9k_hw_beaconinit(struct ath_hal *ah, | ||
1021 | u32 next_beacon, u32 beacon_period); | ||
1022 | void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah, | ||
1023 | const struct ath9k_beacon_state *bs); | ||
1024 | bool ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
1025 | u32 size, u32 flags); | ||
1026 | void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp); | ||
1027 | void ath9k_hw_rxena(struct ath_hal *ah); | ||
1028 | void ath9k_hw_setopmode(struct ath_hal *ah); | ||
1029 | bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac); | ||
1030 | void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, | ||
1031 | u32 filter1); | ||
1032 | u32 ath9k_hw_getrxfilter(struct ath_hal *ah); | ||
1033 | void ath9k_hw_startpcureceive(struct ath_hal *ah); | ||
1034 | void ath9k_hw_stoppcurecv(struct ath_hal *ah); | ||
1035 | bool ath9k_hw_stopdmarecv(struct ath_hal *ah); | ||
1036 | int ath9k_hw_rxprocdesc(struct ath_hal *ah, | ||
1037 | struct ath_desc *ds, u32 pa, | ||
1038 | struct ath_desc *nds, u64 tsf); | ||
1039 | u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q); | ||
1040 | int ath9k_hw_txprocdesc(struct ath_hal *ah, | ||
1041 | struct ath_desc *ds); | ||
1042 | void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds, | ||
1043 | u32 numDelims); | ||
1044 | void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds, | ||
1045 | u32 aggrLen); | ||
1046 | void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds); | ||
1047 | bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q); | ||
1048 | void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs); | ||
1049 | void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds); | ||
1050 | void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, | ||
1051 | struct ath_desc *ds, u32 vmf); | ||
1052 | bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit); | ||
1053 | bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah); | ||
1054 | int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type, | ||
1055 | const struct ath9k_txq_info *qInfo); | ||
1056 | u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q); | ||
1057 | const char *ath9k_hw_probe(u16 vendorid, u16 devid); | ||
1058 | bool ath9k_hw_disable(struct ath_hal *ah); | ||
1059 | void ath9k_hw_rfdetach(struct ath_hal *ah); | ||
1060 | void ath9k_hw_get_channel_centers(struct ath_hal *ah, | ||
1061 | struct ath9k_channel *chan, | ||
1062 | struct chan_centers *centers); | ||
1063 | bool ath9k_get_channel_edges(struct ath_hal *ah, | ||
1064 | u16 flags, u16 *low, | ||
1065 | u16 *high); | ||
1066 | #endif | ||
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c new file mode 100644 index 00000000000..00993f828c5 --- /dev/null +++ b/drivers/net/wireless/ath9k/beacon.c | |||
@@ -0,0 +1,977 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* Implementation of beacon processing. */ | ||
18 | |||
19 | #include <asm/unaligned.h> | ||
20 | #include "core.h" | ||
21 | |||
22 | /* | ||
23 | * Configure parameters for the beacon queue | ||
24 | * | ||
25 | * This function will modify certain transmit queue properties depending on | ||
26 | * the operating mode of the station (AP or AdHoc). Parameters are AIFS | ||
27 | * settings and channel width min/max | ||
28 | */ | ||
29 | |||
30 | static int ath_beaconq_config(struct ath_softc *sc) | ||
31 | { | ||
32 | struct ath_hal *ah = sc->sc_ah; | ||
33 | struct ath9k_txq_info qi; | ||
34 | |||
35 | ath9k_hw_gettxqueueprops(ah, sc->sc_bhalq, &qi); | ||
36 | if (sc->sc_opmode == ATH9K_M_HOSTAP) { | ||
37 | /* Always burst out beacon and CAB traffic. */ | ||
38 | qi.tqi_aifs = 1; | ||
39 | qi.tqi_cwmin = 0; | ||
40 | qi.tqi_cwmax = 0; | ||
41 | } else { | ||
42 | /* Adhoc mode; important thing is to use 2x cwmin. */ | ||
43 | qi.tqi_aifs = sc->sc_beacon_qi.tqi_aifs; | ||
44 | qi.tqi_cwmin = 2*sc->sc_beacon_qi.tqi_cwmin; | ||
45 | qi.tqi_cwmax = sc->sc_beacon_qi.tqi_cwmax; | ||
46 | } | ||
47 | |||
48 | if (!ath9k_hw_settxqueueprops(ah, sc->sc_bhalq, &qi)) { | ||
49 | DPRINTF(sc, ATH_DBG_FATAL, | ||
50 | "%s: unable to update h/w beacon queue parameters\n", | ||
51 | __func__); | ||
52 | return 0; | ||
53 | } else { | ||
54 | ath9k_hw_resettxqueue(ah, sc->sc_bhalq); /* push to h/w */ | ||
55 | return 1; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * Setup the beacon frame for transmit. | ||
61 | * | ||
62 | * Associates the beacon frame buffer with a transmit descriptor. Will set | ||
63 | * up all required antenna switch parameters, rate codes, and channel flags. | ||
64 | * Beacons are always sent out at the lowest rate, and are not retried. | ||
65 | */ | ||
66 | |||
67 | static void ath_beacon_setup(struct ath_softc *sc, | ||
68 | struct ath_vap *avp, struct ath_buf *bf) | ||
69 | { | ||
70 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | ||
71 | struct ath_hal *ah = sc->sc_ah; | ||
72 | struct ath_desc *ds; | ||
73 | int flags, antenna; | ||
74 | const struct ath9k_rate_table *rt; | ||
75 | u8 rix, rate; | ||
76 | int ctsrate = 0; | ||
77 | int ctsduration = 0; | ||
78 | struct ath9k_11n_rate_series series[4]; | ||
79 | |||
80 | DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n", | ||
81 | __func__, skb, skb->len); | ||
82 | |||
83 | /* setup descriptors */ | ||
84 | ds = bf->bf_desc; | ||
85 | |||
86 | flags = ATH9K_TXDESC_NOACK; | ||
87 | |||
88 | if (sc->sc_opmode == ATH9K_M_IBSS && ah->ah_caps.halVEOLSupport) { | ||
89 | ds->ds_link = bf->bf_daddr; /* self-linked */ | ||
90 | flags |= ATH9K_TXDESC_VEOL; | ||
91 | /* Let hardware handle antenna switching. */ | ||
92 | antenna = 0; | ||
93 | } else { | ||
94 | ds->ds_link = 0; | ||
95 | /* | ||
96 | * Switch antenna every beacon. | ||
97 | * Should only switch every beacon period, not for every | ||
98 | * SWBA's | ||
99 | * XXX assumes two antenna | ||
100 | */ | ||
101 | antenna = ((sc->ast_be_xmit / sc->sc_nbcnvaps) & 1 ? 2 : 1); | ||
102 | } | ||
103 | |||
104 | ds->ds_data = bf->bf_buf_addr; | ||
105 | |||
106 | /* | ||
107 | * Calculate rate code. | ||
108 | * XXX everything at min xmit rate | ||
109 | */ | ||
110 | rix = sc->sc_minrateix; | ||
111 | rt = sc->sc_currates; | ||
112 | rate = rt->info[rix].rateCode; | ||
113 | if (sc->sc_flags & ATH_PREAMBLE_SHORT) | ||
114 | rate |= rt->info[rix].shortPreamble; | ||
115 | |||
116 | ath9k_hw_set11n_txdesc(ah, ds | ||
117 | , skb->len + FCS_LEN /* frame length */ | ||
118 | , ATH9K_PKT_TYPE_BEACON /* Atheros packet type */ | ||
119 | , avp->av_btxctl.txpower /* txpower XXX */ | ||
120 | , ATH9K_TXKEYIX_INVALID /* no encryption */ | ||
121 | , ATH9K_KEY_TYPE_CLEAR /* no encryption */ | ||
122 | , flags /* no ack, veol for beacons */ | ||
123 | ); | ||
124 | |||
125 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | ||
126 | ath9k_hw_filltxdesc(ah, ds | ||
127 | , roundup(skb->len, 4) /* buffer length */ | ||
128 | , true /* first segment */ | ||
129 | , true /* last segment */ | ||
130 | , ds /* first descriptor */ | ||
131 | ); | ||
132 | |||
133 | memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); | ||
134 | series[0].Tries = 1; | ||
135 | series[0].Rate = rate; | ||
136 | series[0].ChSel = sc->sc_tx_chainmask; | ||
137 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; | ||
138 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, | ||
139 | ctsrate, ctsduration, series, 4, 0); | ||
140 | } | ||
141 | |||
142 | /* Move everything from the vap's mcast queue to the hardware cab queue. | ||
143 | * Caller must hold mcasq lock and cabq lock | ||
144 | * XXX MORE_DATA bit? | ||
145 | */ | ||
146 | static void empty_mcastq_into_cabq(struct ath_hal *ah, | ||
147 | struct ath_txq *mcastq, struct ath_txq *cabq) | ||
148 | { | ||
149 | struct ath_buf *bfmcast; | ||
150 | |||
151 | BUG_ON(list_empty(&mcastq->axq_q)); | ||
152 | |||
153 | bfmcast = list_first_entry(&mcastq->axq_q, struct ath_buf, list); | ||
154 | |||
155 | /* link the descriptors */ | ||
156 | if (!cabq->axq_link) | ||
157 | ath9k_hw_puttxbuf(ah, cabq->axq_qnum, bfmcast->bf_daddr); | ||
158 | else | ||
159 | *cabq->axq_link = bfmcast->bf_daddr; | ||
160 | |||
161 | /* append the private vap mcast list to the cabq */ | ||
162 | |||
163 | cabq->axq_depth += mcastq->axq_depth; | ||
164 | cabq->axq_totalqueued += mcastq->axq_totalqueued; | ||
165 | cabq->axq_linkbuf = mcastq->axq_linkbuf; | ||
166 | cabq->axq_link = mcastq->axq_link; | ||
167 | list_splice_tail_init(&mcastq->axq_q, &cabq->axq_q); | ||
168 | mcastq->axq_depth = 0; | ||
169 | mcastq->axq_totalqueued = 0; | ||
170 | mcastq->axq_linkbuf = NULL; | ||
171 | mcastq->axq_link = NULL; | ||
172 | } | ||
173 | |||
174 | /* This is only run at DTIM. We move everything from the vap's mcast queue | ||
175 | * to the hardware cab queue. Caller must hold the mcastq lock. */ | ||
176 | static void trigger_mcastq(struct ath_hal *ah, | ||
177 | struct ath_txq *mcastq, struct ath_txq *cabq) | ||
178 | { | ||
179 | spin_lock_bh(&cabq->axq_lock); | ||
180 | |||
181 | if (!list_empty(&mcastq->axq_q)) | ||
182 | empty_mcastq_into_cabq(ah, mcastq, cabq); | ||
183 | |||
184 | /* cabq is gated by beacon so it is safe to start here */ | ||
185 | if (!list_empty(&cabq->axq_q)) | ||
186 | ath9k_hw_txstart(ah, cabq->axq_qnum); | ||
187 | |||
188 | spin_unlock_bh(&cabq->axq_lock); | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * Generate beacon frame and queue cab data for a vap. | ||
193 | * | ||
194 | * Updates the contents of the beacon frame. It is assumed that the buffer for | ||
195 | * the beacon frame has been allocated in the ATH object, and simply needs to | ||
196 | * be filled for this cycle. Also, any CAB (crap after beacon?) traffic will | ||
197 | * be added to the beacon frame at this point. | ||
198 | */ | ||
199 | static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | ||
200 | { | ||
201 | struct ath_hal *ah = sc->sc_ah; | ||
202 | struct ath_buf *bf; | ||
203 | struct ath_vap *avp; | ||
204 | struct sk_buff *skb; | ||
205 | int cabq_depth; | ||
206 | int mcastq_depth; | ||
207 | int is_beacon_dtim = 0; | ||
208 | unsigned int curlen; | ||
209 | struct ath_txq *cabq; | ||
210 | struct ath_txq *mcastq; | ||
211 | avp = sc->sc_vaps[if_id]; | ||
212 | |||
213 | mcastq = &avp->av_mcastq; | ||
214 | cabq = sc->sc_cabq; | ||
215 | |||
216 | ASSERT(avp); | ||
217 | |||
218 | if (avp->av_bcbuf == NULL) { | ||
219 | DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", | ||
220 | __func__, avp, avp->av_bcbuf); | ||
221 | return NULL; | ||
222 | } | ||
223 | bf = avp->av_bcbuf; | ||
224 | skb = (struct sk_buff *) bf->bf_mpdu; | ||
225 | |||
226 | /* | ||
227 | * Update dynamic beacon contents. If this returns | ||
228 | * non-zero then we need to remap the memory because | ||
229 | * the beacon frame changed size (probably because | ||
230 | * of the TIM bitmap). | ||
231 | */ | ||
232 | curlen = skb->len; | ||
233 | |||
234 | /* XXX: spin_lock_bh should not be used here, but sparse bitches | ||
235 | * otherwise. We should fix sparse :) */ | ||
236 | spin_lock_bh(&mcastq->axq_lock); | ||
237 | mcastq_depth = avp->av_mcastq.axq_depth; | ||
238 | |||
239 | if (ath_update_beacon(sc, if_id, &avp->av_boff, skb, mcastq_depth) == | ||
240 | 1) { | ||
241 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
242 | get_dma_mem_context(bf, bf_dmacontext)); | ||
243 | bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE, | ||
244 | get_dma_mem_context(bf, bf_dmacontext)); | ||
245 | } else { | ||
246 | pci_dma_sync_single_for_cpu(sc->pdev, | ||
247 | bf->bf_buf_addr, | ||
248 | skb_tailroom(skb), | ||
249 | PCI_DMA_TODEVICE); | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * if the CABQ traffic from previous DTIM is pending and the current | ||
254 | * beacon is also a DTIM. | ||
255 | * 1) if there is only one vap let the cab traffic continue. | ||
256 | * 2) if there are more than one vap and we are using staggered | ||
257 | * beacons, then drain the cabq by dropping all the frames in | ||
258 | * the cabq so that the current vaps cab traffic can be scheduled. | ||
259 | */ | ||
260 | spin_lock_bh(&cabq->axq_lock); | ||
261 | cabq_depth = cabq->axq_depth; | ||
262 | spin_unlock_bh(&cabq->axq_lock); | ||
263 | |||
264 | is_beacon_dtim = avp->av_boff.bo_tim[4] & 1; | ||
265 | |||
266 | if (mcastq_depth && is_beacon_dtim && cabq_depth) { | ||
267 | /* | ||
268 | * Unlock the cabq lock as ath_tx_draintxq acquires | ||
269 | * the lock again which is a common function and that | ||
270 | * acquires txq lock inside. | ||
271 | */ | ||
272 | if (sc->sc_nvaps > 1) { | ||
273 | ath_tx_draintxq(sc, cabq, false); | ||
274 | DPRINTF(sc, ATH_DBG_BEACON, | ||
275 | "%s: flush previous cabq traffic\n", __func__); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | /* Construct tx descriptor. */ | ||
280 | ath_beacon_setup(sc, avp, bf); | ||
281 | |||
282 | /* | ||
283 | * Enable the CAB queue before the beacon queue to | ||
284 | * insure cab frames are triggered by this beacon. | ||
285 | */ | ||
286 | if (is_beacon_dtim) | ||
287 | trigger_mcastq(ah, mcastq, cabq); | ||
288 | |||
289 | spin_unlock_bh(&mcastq->axq_lock); | ||
290 | return bf; | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * Startup beacon transmission for adhoc mode when they are sent entirely | ||
295 | * by the hardware using the self-linked descriptor + veol trick. | ||
296 | */ | ||
297 | |||
298 | static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) | ||
299 | { | ||
300 | struct ath_hal *ah = sc->sc_ah; | ||
301 | struct ath_buf *bf; | ||
302 | struct ath_vap *avp; | ||
303 | struct sk_buff *skb; | ||
304 | |||
305 | avp = sc->sc_vaps[if_id]; | ||
306 | ASSERT(avp); | ||
307 | |||
308 | if (avp->av_bcbuf == NULL) { | ||
309 | DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", | ||
310 | __func__, avp, avp != NULL ? avp->av_bcbuf : NULL); | ||
311 | return; | ||
312 | } | ||
313 | bf = avp->av_bcbuf; | ||
314 | skb = (struct sk_buff *) bf->bf_mpdu; | ||
315 | |||
316 | /* Construct tx descriptor. */ | ||
317 | ath_beacon_setup(sc, avp, bf); | ||
318 | |||
319 | /* NB: caller is known to have already stopped tx dma */ | ||
320 | ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr); | ||
321 | ath9k_hw_txstart(ah, sc->sc_bhalq); | ||
322 | DPRINTF(sc, ATH_DBG_BEACON, "%s: TXDP%u = %llx (%p)\n", __func__, | ||
323 | sc->sc_bhalq, ito64(bf->bf_daddr), bf->bf_desc); | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | * Setup a h/w transmit queue for beacons. | ||
328 | * | ||
329 | * This function allocates an information structure (struct ath9k_txq_info) | ||
330 | * on the stack, sets some specific parameters (zero out channel width | ||
331 | * min/max, and enable aifs). The info structure does not need to be | ||
332 | * persistant. | ||
333 | */ | ||
334 | |||
335 | int ath_beaconq_setup(struct ath_hal *ah) | ||
336 | { | ||
337 | struct ath9k_txq_info qi; | ||
338 | |||
339 | memzero(&qi, sizeof(qi)); | ||
340 | qi.tqi_aifs = 1; | ||
341 | qi.tqi_cwmin = 0; | ||
342 | qi.tqi_cwmax = 0; | ||
343 | /* NB: don't enable any interrupts */ | ||
344 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); | ||
345 | } | ||
346 | |||
347 | |||
348 | /* | ||
349 | * Allocate and setup an initial beacon frame. | ||
350 | * | ||
351 | * Allocate a beacon state variable for a specific VAP instance created on | ||
352 | * the ATH interface. This routine also calculates the beacon "slot" for | ||
353 | * staggared beacons in the mBSSID case. | ||
354 | */ | ||
355 | |||
356 | int ath_beacon_alloc(struct ath_softc *sc, int if_id) | ||
357 | { | ||
358 | struct ath_vap *avp; | ||
359 | struct ieee80211_hdr *wh; | ||
360 | struct ath_buf *bf; | ||
361 | struct sk_buff *skb; | ||
362 | |||
363 | avp = sc->sc_vaps[if_id]; | ||
364 | ASSERT(avp); | ||
365 | |||
366 | /* Allocate a beacon descriptor if we haven't done so. */ | ||
367 | if (!avp->av_bcbuf) { | ||
368 | /* | ||
369 | * Allocate beacon state for hostap/ibss. We know | ||
370 | * a buffer is available. | ||
371 | */ | ||
372 | |||
373 | avp->av_bcbuf = list_first_entry(&sc->sc_bbuf, | ||
374 | struct ath_buf, list); | ||
375 | list_del(&avp->av_bcbuf->list); | ||
376 | |||
377 | if (sc->sc_opmode == ATH9K_M_HOSTAP || | ||
378 | !sc->sc_ah->ah_caps.halVEOLSupport) { | ||
379 | int slot; | ||
380 | /* | ||
381 | * Assign the vap to a beacon xmit slot. As | ||
382 | * above, this cannot fail to find one. | ||
383 | */ | ||
384 | avp->av_bslot = 0; | ||
385 | for (slot = 0; slot < ATH_BCBUF; slot++) | ||
386 | if (sc->sc_bslot[slot] == ATH_IF_ID_ANY) { | ||
387 | /* | ||
388 | * XXX hack, space out slots to better | ||
389 | * deal with misses | ||
390 | */ | ||
391 | if (slot+1 < ATH_BCBUF && | ||
392 | sc->sc_bslot[slot+1] == | ||
393 | ATH_IF_ID_ANY) { | ||
394 | avp->av_bslot = slot+1; | ||
395 | break; | ||
396 | } | ||
397 | avp->av_bslot = slot; | ||
398 | /* NB: keep looking for a double slot */ | ||
399 | } | ||
400 | BUG_ON(sc->sc_bslot[avp->av_bslot] != ATH_IF_ID_ANY); | ||
401 | sc->sc_bslot[avp->av_bslot] = if_id; | ||
402 | sc->sc_nbcnvaps++; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | /* release the previous beacon frame , if it already exists. */ | ||
407 | bf = avp->av_bcbuf; | ||
408 | if (bf->bf_mpdu != NULL) { | ||
409 | skb = (struct sk_buff *)bf->bf_mpdu; | ||
410 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
411 | get_dma_mem_context(bf, bf_dmacontext)); | ||
412 | dev_kfree_skb_any(skb); | ||
413 | bf->bf_mpdu = NULL; | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * NB: the beacon data buffer must be 32-bit aligned; | ||
418 | * we assume the wbuf routines will return us something | ||
419 | * with this alignment (perhaps should assert). | ||
420 | * FIXME: Fill avp->av_boff.bo_tim,avp->av_btxctl.txpower and | ||
421 | * avp->av_btxctl.shortPreamble | ||
422 | */ | ||
423 | skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); | ||
424 | if (skb == NULL) { | ||
425 | DPRINTF(sc, ATH_DBG_BEACON, "%s: cannot get skb\n", | ||
426 | __func__); | ||
427 | return -ENOMEM; | ||
428 | } | ||
429 | |||
430 | /* | ||
431 | * Calculate a TSF adjustment factor required for | ||
432 | * staggered beacons. Note that we assume the format | ||
433 | * of the beacon frame leaves the tstamp field immediately | ||
434 | * following the header. | ||
435 | */ | ||
436 | if (avp->av_bslot > 0) { | ||
437 | u64 tsfadjust; | ||
438 | __le64 val; | ||
439 | int intval; | ||
440 | |||
441 | /* FIXME: Use default value for now: Sujith */ | ||
442 | |||
443 | intval = ATH_DEFAULT_BINTVAL; | ||
444 | |||
445 | /* | ||
446 | * The beacon interval is in TU's; the TSF in usecs. | ||
447 | * We figure out how many TU's to add to align the | ||
448 | * timestamp then convert to TSF units and handle | ||
449 | * byte swapping before writing it in the frame. | ||
450 | * The hardware will then add this each time a beacon | ||
451 | * frame is sent. Note that we align vap's 1..N | ||
452 | * and leave vap 0 untouched. This means vap 0 | ||
453 | * has a timestamp in one beacon interval while the | ||
454 | * others get a timestamp aligned to the next interval. | ||
455 | */ | ||
456 | tsfadjust = (intval * (ATH_BCBUF - avp->av_bslot)) / ATH_BCBUF; | ||
457 | val = cpu_to_le64(tsfadjust << 10); /* TU->TSF */ | ||
458 | |||
459 | DPRINTF(sc, ATH_DBG_BEACON, | ||
460 | "%s: %s beacons, bslot %d intval %u tsfadjust %llu\n", | ||
461 | __func__, "stagger", | ||
462 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | ||
463 | |||
464 | wh = (struct ieee80211_hdr *)skb->data; | ||
465 | memcpy(&wh[1], &val, sizeof(val)); | ||
466 | } | ||
467 | |||
468 | bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE, | ||
469 | get_dma_mem_context(bf, bf_dmacontext)); | ||
470 | bf->bf_mpdu = skb; | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | /* | ||
476 | * Reclaim beacon resources and return buffer to the pool. | ||
477 | * | ||
478 | * Checks the VAP to put the beacon frame buffer back to the ATH object | ||
479 | * queue, and de-allocates any wbuf frames that were sent as CAB traffic. | ||
480 | */ | ||
481 | |||
482 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) | ||
483 | { | ||
484 | if (avp->av_bcbuf != NULL) { | ||
485 | struct ath_buf *bf; | ||
486 | |||
487 | if (avp->av_bslot != -1) { | ||
488 | sc->sc_bslot[avp->av_bslot] = ATH_IF_ID_ANY; | ||
489 | sc->sc_nbcnvaps--; | ||
490 | } | ||
491 | |||
492 | bf = avp->av_bcbuf; | ||
493 | if (bf->bf_mpdu != NULL) { | ||
494 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | ||
495 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
496 | get_dma_mem_context(bf, bf_dmacontext)); | ||
497 | dev_kfree_skb_any(skb); | ||
498 | bf->bf_mpdu = NULL; | ||
499 | } | ||
500 | list_add_tail(&bf->list, &sc->sc_bbuf); | ||
501 | |||
502 | avp->av_bcbuf = NULL; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | /* | ||
507 | * Reclaim beacon resources and return buffer to the pool. | ||
508 | * | ||
509 | * This function will free any wbuf frames that are still attached to the | ||
510 | * beacon buffers in the ATH object. Note that this does not de-allocate | ||
511 | * any wbuf objects that are in the transmit queue and have not yet returned | ||
512 | * to the ATH object. | ||
513 | */ | ||
514 | |||
515 | void ath_beacon_free(struct ath_softc *sc) | ||
516 | { | ||
517 | struct ath_buf *bf; | ||
518 | |||
519 | list_for_each_entry(bf, &sc->sc_bbuf, list) { | ||
520 | if (bf->bf_mpdu != NULL) { | ||
521 | struct sk_buff *skb = (struct sk_buff *) bf->bf_mpdu; | ||
522 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
523 | get_dma_mem_context(bf, bf_dmacontext)); | ||
524 | dev_kfree_skb_any(skb); | ||
525 | bf->bf_mpdu = NULL; | ||
526 | } | ||
527 | } | ||
528 | } | ||
529 | |||
530 | /* | ||
531 | * Tasklet for Sending Beacons | ||
532 | * | ||
533 | * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame | ||
534 | * contents are done as needed and the slot time is also adjusted based on | ||
535 | * current state. | ||
536 | * | ||
537 | * This tasklet is not scheduled, it's called in ISR context. | ||
538 | */ | ||
539 | |||
540 | void ath9k_beacon_tasklet(unsigned long data) | ||
541 | { | ||
542 | #define TSF_TO_TU(_h,_l) \ | ||
543 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
544 | |||
545 | struct ath_softc *sc = (struct ath_softc *)data; | ||
546 | struct ath_hal *ah = sc->sc_ah; | ||
547 | struct ath_buf *bf = NULL; | ||
548 | int slot, if_id; | ||
549 | u32 bfaddr; | ||
550 | u32 rx_clear = 0, rx_frame = 0, tx_frame = 0; | ||
551 | u32 show_cycles = 0; | ||
552 | u32 bc = 0; /* beacon count */ | ||
553 | u64 tsf; | ||
554 | u32 tsftu; | ||
555 | u16 intval; | ||
556 | |||
557 | if (sc->sc_noreset) { | ||
558 | show_cycles = ath9k_hw_GetMibCycleCountsPct(ah, | ||
559 | &rx_clear, | ||
560 | &rx_frame, | ||
561 | &tx_frame); | ||
562 | } | ||
563 | |||
564 | /* | ||
565 | * Check if the previous beacon has gone out. If | ||
566 | * not don't try to post another, skip this period | ||
567 | * and wait for the next. Missed beacons indicate | ||
568 | * a problem and should not occur. If we miss too | ||
569 | * many consecutive beacons reset the device. | ||
570 | */ | ||
571 | if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) { | ||
572 | sc->sc_bmisscount++; | ||
573 | /* XXX: doth needs the chanchange IE countdown decremented. | ||
574 | * We should consider adding a mac80211 call to indicate | ||
575 | * a beacon miss so appropriate action could be taken | ||
576 | * (in that layer). | ||
577 | */ | ||
578 | if (sc->sc_bmisscount < BSTUCK_THRESH) { | ||
579 | if (sc->sc_noreset) { | ||
580 | DPRINTF(sc, ATH_DBG_BEACON, | ||
581 | "%s: missed %u consecutive beacons\n", | ||
582 | __func__, sc->sc_bmisscount); | ||
583 | if (show_cycles) { | ||
584 | /* | ||
585 | * Display cycle counter stats | ||
586 | * from HW to aide in debug of | ||
587 | * stickiness. | ||
588 | */ | ||
589 | DPRINTF(sc, | ||
590 | ATH_DBG_BEACON, | ||
591 | "%s: busy times: rx_clear=%d, " | ||
592 | "rx_frame=%d, tx_frame=%d\n", | ||
593 | __func__, rx_clear, rx_frame, | ||
594 | tx_frame); | ||
595 | } else { | ||
596 | DPRINTF(sc, | ||
597 | ATH_DBG_BEACON, | ||
598 | "%s: unable to obtain " | ||
599 | "busy times\n", __func__); | ||
600 | } | ||
601 | } else { | ||
602 | DPRINTF(sc, ATH_DBG_BEACON, | ||
603 | "%s: missed %u consecutive beacons\n", | ||
604 | __func__, sc->sc_bmisscount); | ||
605 | } | ||
606 | } else if (sc->sc_bmisscount >= BSTUCK_THRESH) { | ||
607 | if (sc->sc_noreset) { | ||
608 | if (sc->sc_bmisscount == BSTUCK_THRESH) { | ||
609 | DPRINTF(sc, | ||
610 | ATH_DBG_BEACON, | ||
611 | "%s: beacon is officially " | ||
612 | "stuck\n", __func__); | ||
613 | ath9k_hw_dmaRegDump(ah); | ||
614 | } | ||
615 | } else { | ||
616 | DPRINTF(sc, ATH_DBG_BEACON, | ||
617 | "%s: beacon is officially stuck\n", | ||
618 | __func__); | ||
619 | ath_bstuck_process(sc); | ||
620 | } | ||
621 | } | ||
622 | |||
623 | return; | ||
624 | } | ||
625 | if (sc->sc_bmisscount != 0) { | ||
626 | if (sc->sc_noreset) { | ||
627 | DPRINTF(sc, | ||
628 | ATH_DBG_BEACON, | ||
629 | "%s: resume beacon xmit after %u misses\n", | ||
630 | __func__, sc->sc_bmisscount); | ||
631 | } else { | ||
632 | DPRINTF(sc, ATH_DBG_BEACON, | ||
633 | "%s: resume beacon xmit after %u misses\n", | ||
634 | __func__, sc->sc_bmisscount); | ||
635 | } | ||
636 | sc->sc_bmisscount = 0; | ||
637 | } | ||
638 | |||
639 | /* | ||
640 | * Generate beacon frames. we are sending frames | ||
641 | * staggered so calculate the slot for this frame based | ||
642 | * on the tsf to safeguard against missing an swba. | ||
643 | */ | ||
644 | |||
645 | /* FIXME: Use default value for now - Sujith */ | ||
646 | intval = ATH_DEFAULT_BINTVAL; | ||
647 | |||
648 | tsf = ath9k_hw_gettsf64(ah); | ||
649 | tsftu = TSF_TO_TU(tsf>>32, tsf); | ||
650 | slot = ((tsftu % intval) * ATH_BCBUF) / intval; | ||
651 | if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF]; | ||
652 | DPRINTF(sc, ATH_DBG_BEACON, | ||
653 | "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", | ||
654 | __func__, slot, (unsigned long long) tsf, tsftu, | ||
655 | intval, if_id); | ||
656 | bfaddr = 0; | ||
657 | if (if_id != ATH_IF_ID_ANY) { | ||
658 | bf = ath_beacon_generate(sc, if_id); | ||
659 | if (bf != NULL) { | ||
660 | bfaddr = bf->bf_daddr; | ||
661 | bc = 1; | ||
662 | } | ||
663 | } | ||
664 | /* | ||
665 | * Handle slot time change when a non-ERP station joins/leaves | ||
666 | * an 11g network. The 802.11 layer notifies us via callback, | ||
667 | * we mark updateslot, then wait one beacon before effecting | ||
668 | * the change. This gives associated stations at least one | ||
669 | * beacon interval to note the state change. | ||
670 | * | ||
671 | * NB: The slot time change state machine is clocked according | ||
672 | * to whether we are bursting or staggering beacons. We | ||
673 | * recognize the request to update and record the current | ||
674 | * slot then don't transition until that slot is reached | ||
675 | * again. If we miss a beacon for that slot then we'll be | ||
676 | * slow to transition but we'll be sure at least one beacon | ||
677 | * interval has passed. When bursting slot is always left | ||
678 | * set to ATH_BCBUF so this check is a noop. | ||
679 | */ | ||
680 | /* XXX locking */ | ||
681 | if (sc->sc_updateslot == UPDATE) { | ||
682 | sc->sc_updateslot = COMMIT; /* commit next beacon */ | ||
683 | sc->sc_slotupdate = slot; | ||
684 | } else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot) | ||
685 | ath_setslottime(sc); /* commit change to hardware */ | ||
686 | |||
687 | if (bfaddr != 0) { | ||
688 | /* | ||
689 | * Stop any current dma and put the new frame(s) on the queue. | ||
690 | * This should never fail since we check above that no frames | ||
691 | * are still pending on the queue. | ||
692 | */ | ||
693 | if (!ath9k_hw_stoptxdma(ah, sc->sc_bhalq)) { | ||
694 | DPRINTF(sc, ATH_DBG_FATAL, | ||
695 | "%s: beacon queue %u did not stop?\n", | ||
696 | __func__, sc->sc_bhalq); | ||
697 | /* NB: the HAL still stops DMA, so proceed */ | ||
698 | } | ||
699 | |||
700 | /* NB: cabq traffic should already be queued and primed */ | ||
701 | ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bfaddr); | ||
702 | ath9k_hw_txstart(ah, sc->sc_bhalq); | ||
703 | |||
704 | sc->ast_be_xmit += bc; /* XXX per-vap? */ | ||
705 | } | ||
706 | #undef TSF_TO_TU | ||
707 | } | ||
708 | |||
709 | /* | ||
710 | * Tasklet for Beacon Stuck processing | ||
711 | * | ||
712 | * Processing for Beacon Stuck. | ||
713 | * Basically calls the ath_internal_reset function to reset the chip. | ||
714 | */ | ||
715 | |||
716 | void ath_bstuck_process(struct ath_softc *sc) | ||
717 | { | ||
718 | DPRINTF(sc, ATH_DBG_BEACON, | ||
719 | "%s: stuck beacon; resetting (bmiss count %u)\n", | ||
720 | __func__, sc->sc_bmisscount); | ||
721 | ath_internal_reset(sc); | ||
722 | } | ||
723 | |||
724 | /* | ||
725 | * Configure the beacon and sleep timers. | ||
726 | * | ||
727 | * When operating as an AP this resets the TSF and sets | ||
728 | * up the hardware to notify us when we need to issue beacons. | ||
729 | * | ||
730 | * When operating in station mode this sets up the beacon | ||
731 | * timers according to the timestamp of the last received | ||
732 | * beacon and the current TSF, configures PCF and DTIM | ||
733 | * handling, programs the sleep registers so the hardware | ||
734 | * will wakeup in time to receive beacons, and configures | ||
735 | * the beacon miss handling so we'll receive a BMISS | ||
736 | * interrupt when we stop seeing beacons from the AP | ||
737 | * we've associated with. | ||
738 | */ | ||
739 | |||
740 | void ath_beacon_config(struct ath_softc *sc, int if_id) | ||
741 | { | ||
742 | #define TSF_TO_TU(_h,_l) \ | ||
743 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
744 | struct ath_hal *ah = sc->sc_ah; | ||
745 | u32 nexttbtt, intval; | ||
746 | struct ath_beacon_config conf; | ||
747 | enum ath9k_opmode av_opmode; | ||
748 | |||
749 | if (if_id != ATH_IF_ID_ANY) | ||
750 | av_opmode = sc->sc_vaps[if_id]->av_opmode; | ||
751 | else | ||
752 | av_opmode = sc->sc_opmode; | ||
753 | |||
754 | memzero(&conf, sizeof(struct ath_beacon_config)); | ||
755 | |||
756 | /* FIXME: Use default values for now - Sujith */ | ||
757 | /* Query beacon configuration first */ | ||
758 | /* | ||
759 | * Protocol stack doesn't support dynamic beacon configuration, | ||
760 | * use default configurations. | ||
761 | */ | ||
762 | conf.beacon_interval = ATH_DEFAULT_BINTVAL; | ||
763 | conf.listen_interval = 1; | ||
764 | conf.dtim_period = conf.beacon_interval; | ||
765 | conf.dtim_count = 1; | ||
766 | conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; | ||
767 | |||
768 | /* extract tstamp from last beacon and convert to TU */ | ||
769 | nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4), | ||
770 | get_unaligned_le32(conf.u.last_tstamp)); | ||
771 | /* XXX conditionalize multi-bss support? */ | ||
772 | if (sc->sc_opmode == ATH9K_M_HOSTAP) { | ||
773 | /* | ||
774 | * For multi-bss ap support beacons are either staggered | ||
775 | * evenly over N slots or burst together. For the former | ||
776 | * arrange for the SWBA to be delivered for each slot. | ||
777 | * Slots that are not occupied will generate nothing. | ||
778 | */ | ||
779 | /* NB: the beacon interval is kept internally in TU's */ | ||
780 | intval = conf.beacon_interval & ATH9K_BEACON_PERIOD; | ||
781 | intval /= ATH_BCBUF; /* for staggered beacons */ | ||
782 | } else { | ||
783 | intval = conf.beacon_interval & ATH9K_BEACON_PERIOD; | ||
784 | } | ||
785 | |||
786 | if (nexttbtt == 0) /* e.g. for ap mode */ | ||
787 | nexttbtt = intval; | ||
788 | else if (intval) /* NB: can be 0 for monitor mode */ | ||
789 | nexttbtt = roundup(nexttbtt, intval); | ||
790 | DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", | ||
791 | __func__, nexttbtt, intval, conf.beacon_interval); | ||
792 | /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */ | ||
793 | if (sc->sc_opmode == ATH9K_M_STA) { | ||
794 | struct ath9k_beacon_state bs; | ||
795 | u64 tsf; | ||
796 | u32 tsftu; | ||
797 | int dtimperiod, dtimcount, sleepduration; | ||
798 | int cfpperiod, cfpcount; | ||
799 | |||
800 | /* | ||
801 | * Setup dtim and cfp parameters according to | ||
802 | * last beacon we received (which may be none). | ||
803 | */ | ||
804 | dtimperiod = conf.dtim_period; | ||
805 | if (dtimperiod <= 0) /* NB: 0 if not known */ | ||
806 | dtimperiod = 1; | ||
807 | dtimcount = conf.dtim_count; | ||
808 | if (dtimcount >= dtimperiod) /* NB: sanity check */ | ||
809 | dtimcount = 0; /* XXX? */ | ||
810 | cfpperiod = 1; /* NB: no PCF support yet */ | ||
811 | cfpcount = 0; | ||
812 | |||
813 | sleepduration = conf.listen_interval * intval; | ||
814 | if (sleepduration <= 0) | ||
815 | sleepduration = intval; | ||
816 | |||
817 | #define FUDGE 2 | ||
818 | /* | ||
819 | * Pull nexttbtt forward to reflect the current | ||
820 | * TSF and calculate dtim+cfp state for the result. | ||
821 | */ | ||
822 | tsf = ath9k_hw_gettsf64(ah); | ||
823 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; | ||
824 | do { | ||
825 | nexttbtt += intval; | ||
826 | if (--dtimcount < 0) { | ||
827 | dtimcount = dtimperiod - 1; | ||
828 | if (--cfpcount < 0) | ||
829 | cfpcount = cfpperiod - 1; | ||
830 | } | ||
831 | } while (nexttbtt < tsftu); | ||
832 | #undef FUDGE | ||
833 | memzero(&bs, sizeof(bs)); | ||
834 | bs.bs_intval = intval; | ||
835 | bs.bs_nexttbtt = nexttbtt; | ||
836 | bs.bs_dtimperiod = dtimperiod*intval; | ||
837 | bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; | ||
838 | bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; | ||
839 | bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; | ||
840 | bs.bs_cfpmaxduration = 0; | ||
841 | /* | ||
842 | * Calculate the number of consecutive beacons to miss | ||
843 | * before taking a BMISS interrupt. The configuration | ||
844 | * is specified in TU so we only need calculate based | ||
845 | * on the beacon interval. Note that we clamp the | ||
846 | * result to at most 15 beacons. | ||
847 | */ | ||
848 | if (sleepduration > intval) { | ||
849 | bs.bs_bmissthreshold = | ||
850 | conf.listen_interval * | ||
851 | ATH_DEFAULT_BMISS_LIMIT / 2; | ||
852 | } else { | ||
853 | bs.bs_bmissthreshold = | ||
854 | DIV_ROUND_UP(conf.bmiss_timeout, intval); | ||
855 | if (bs.bs_bmissthreshold > 15) | ||
856 | bs.bs_bmissthreshold = 15; | ||
857 | else if (bs.bs_bmissthreshold <= 0) | ||
858 | bs.bs_bmissthreshold = 1; | ||
859 | } | ||
860 | |||
861 | /* | ||
862 | * Calculate sleep duration. The configuration is | ||
863 | * given in ms. We insure a multiple of the beacon | ||
864 | * period is used. Also, if the sleep duration is | ||
865 | * greater than the DTIM period then it makes senses | ||
866 | * to make it a multiple of that. | ||
867 | * | ||
868 | * XXX fixed at 100ms | ||
869 | */ | ||
870 | |||
871 | bs.bs_sleepduration = | ||
872 | roundup(IEEE80211_MS_TO_TU(100), sleepduration); | ||
873 | if (bs.bs_sleepduration > bs.bs_dtimperiod) | ||
874 | bs.bs_sleepduration = bs.bs_dtimperiod; | ||
875 | |||
876 | DPRINTF(sc, ATH_DBG_BEACON, | ||
877 | "%s: tsf %llu " | ||
878 | "tsf:tu %u " | ||
879 | "intval %u " | ||
880 | "nexttbtt %u " | ||
881 | "dtim %u " | ||
882 | "nextdtim %u " | ||
883 | "bmiss %u " | ||
884 | "sleep %u " | ||
885 | "cfp:period %u " | ||
886 | "maxdur %u " | ||
887 | "next %u " | ||
888 | "timoffset %u\n" | ||
889 | , __func__ | ||
890 | , (unsigned long long)tsf, tsftu | ||
891 | , bs.bs_intval | ||
892 | , bs.bs_nexttbtt | ||
893 | , bs.bs_dtimperiod | ||
894 | , bs.bs_nextdtim | ||
895 | , bs.bs_bmissthreshold | ||
896 | , bs.bs_sleepduration | ||
897 | , bs.bs_cfpperiod | ||
898 | , bs.bs_cfpmaxduration | ||
899 | , bs.bs_cfpnext | ||
900 | , bs.bs_timoffset | ||
901 | ); | ||
902 | |||
903 | ath9k_hw_set_interrupts(ah, 0); | ||
904 | ath9k_hw_set_sta_beacon_timers(ah, &bs); | ||
905 | sc->sc_imask |= ATH9K_INT_BMISS; | ||
906 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
907 | } else { | ||
908 | u64 tsf; | ||
909 | u32 tsftu; | ||
910 | ath9k_hw_set_interrupts(ah, 0); | ||
911 | if (nexttbtt == intval) | ||
912 | intval |= ATH9K_BEACON_RESET_TSF; | ||
913 | if (sc->sc_opmode == ATH9K_M_IBSS) { | ||
914 | /* | ||
915 | * Pull nexttbtt forward to reflect the current | ||
916 | * TSF . | ||
917 | */ | ||
918 | #define FUDGE 2 | ||
919 | if (!(intval & ATH9K_BEACON_RESET_TSF)) { | ||
920 | tsf = ath9k_hw_gettsf64(ah); | ||
921 | tsftu = TSF_TO_TU((u32)(tsf>>32), | ||
922 | (u32)tsf) + FUDGE; | ||
923 | do { | ||
924 | nexttbtt += intval; | ||
925 | } while (nexttbtt < tsftu); | ||
926 | } | ||
927 | #undef FUDGE | ||
928 | DPRINTF(sc, ATH_DBG_BEACON, | ||
929 | "%s: IBSS nexttbtt %u intval %u (%u)\n", | ||
930 | __func__, nexttbtt, | ||
931 | intval & ~ATH9K_BEACON_RESET_TSF, | ||
932 | conf.beacon_interval); | ||
933 | |||
934 | /* | ||
935 | * In IBSS mode enable the beacon timers but only | ||
936 | * enable SWBA interrupts if we need to manually | ||
937 | * prepare beacon frames. Otherwise we use a | ||
938 | * self-linked tx descriptor and let the hardware | ||
939 | * deal with things. | ||
940 | */ | ||
941 | intval |= ATH9K_BEACON_ENA; | ||
942 | if (!ah->ah_caps.halVEOLSupport) | ||
943 | sc->sc_imask |= ATH9K_INT_SWBA; | ||
944 | ath_beaconq_config(sc); | ||
945 | } else if (sc->sc_opmode == ATH9K_M_HOSTAP) { | ||
946 | /* | ||
947 | * In AP mode we enable the beacon timers and | ||
948 | * SWBA interrupts to prepare beacon frames. | ||
949 | */ | ||
950 | intval |= ATH9K_BEACON_ENA; | ||
951 | sc->sc_imask |= ATH9K_INT_SWBA; /* beacon prepare */ | ||
952 | ath_beaconq_config(sc); | ||
953 | } | ||
954 | ath9k_hw_beaconinit(ah, nexttbtt, intval); | ||
955 | sc->sc_bmisscount = 0; | ||
956 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
957 | /* | ||
958 | * When using a self-linked beacon descriptor in | ||
959 | * ibss mode load it once here. | ||
960 | */ | ||
961 | if (sc->sc_opmode == ATH9K_M_IBSS && ah->ah_caps.halVEOLSupport) | ||
962 | ath_beacon_start_adhoc(sc, 0); | ||
963 | } | ||
964 | #undef TSF_TO_TU | ||
965 | } | ||
966 | |||
967 | /* Function to collect beacon rssi data and resync beacon if necessary */ | ||
968 | |||
969 | void ath_beacon_sync(struct ath_softc *sc, int if_id) | ||
970 | { | ||
971 | /* | ||
972 | * Resync beacon timers using the tsf of the | ||
973 | * beacon frame we just received. | ||
974 | */ | ||
975 | ath_beacon_config(sc, if_id); | ||
976 | sc->sc_beacons = 1; | ||
977 | } | ||
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c new file mode 100644 index 00000000000..e8b3f1fabb3 --- /dev/null +++ b/drivers/net/wireless/ath9k/core.c | |||
@@ -0,0 +1,1961 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008, Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* Implementation of the main "ATH" layer. */ | ||
18 | |||
19 | #include "core.h" | ||
20 | #include "regd.h" | ||
21 | |||
22 | static int ath_outdoor; /* enable outdoor use */ | ||
23 | |||
24 | static const u8 ath_bcast_mac[ETH_ALEN] = | ||
25 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
26 | |||
27 | static u32 ath_chainmask_sel_up_rssi_thres = | ||
28 | ATH_CHAINMASK_SEL_UP_RSSI_THRES; | ||
29 | static u32 ath_chainmask_sel_down_rssi_thres = | ||
30 | ATH_CHAINMASK_SEL_DOWN_RSSI_THRES; | ||
31 | static u32 ath_chainmask_sel_period = | ||
32 | ATH_CHAINMASK_SEL_TIMEOUT; | ||
33 | |||
34 | /* return bus cachesize in 4B word units */ | ||
35 | |||
36 | static void bus_read_cachesize(struct ath_softc *sc, int *csz) | ||
37 | { | ||
38 | u8 u8tmp; | ||
39 | |||
40 | pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, (u8 *)&u8tmp); | ||
41 | *csz = (int)u8tmp; | ||
42 | |||
43 | /* | ||
44 | * This check was put in to avoid "unplesant" consequences if | ||
45 | * the bootrom has not fully initialized all PCI devices. | ||
46 | * Sometimes the cache line size register is not set | ||
47 | */ | ||
48 | |||
49 | if (*csz == 0) | ||
50 | *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * Set current operating mode | ||
55 | * | ||
56 | * This function initializes and fills the rate table in the ATH object based | ||
57 | * on the operating mode. The blink rates are also set up here, although | ||
58 | * they have been superceeded by the ath_led module. | ||
59 | */ | ||
60 | |||
61 | static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) | ||
62 | { | ||
63 | const struct ath9k_rate_table *rt; | ||
64 | int i; | ||
65 | |||
66 | memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap)); | ||
67 | rt = sc->sc_rates[mode]; | ||
68 | BUG_ON(!rt); | ||
69 | |||
70 | for (i = 0; i < rt->rateCount; i++) | ||
71 | sc->sc_rixmap[rt->info[i].rateCode] = (u8) i; | ||
72 | |||
73 | memzero(sc->sc_hwmap, sizeof(sc->sc_hwmap)); | ||
74 | for (i = 0; i < 256; i++) { | ||
75 | u8 ix = rt->rateCodeToIndex[i]; | ||
76 | |||
77 | if (ix == 0xff) | ||
78 | continue; | ||
79 | |||
80 | sc->sc_hwmap[i].ieeerate = | ||
81 | rt->info[ix].dot11Rate & IEEE80211_RATE_VAL; | ||
82 | sc->sc_hwmap[i].rateKbps = rt->info[ix].rateKbps; | ||
83 | |||
84 | if (rt->info[ix].shortPreamble || | ||
85 | rt->info[ix].phy == PHY_OFDM) { | ||
86 | /* XXX: Handle this */ | ||
87 | } | ||
88 | |||
89 | /* NB: this uses the last entry if the rate isn't found */ | ||
90 | /* XXX beware of overlow */ | ||
91 | } | ||
92 | sc->sc_currates = rt; | ||
93 | sc->sc_curmode = mode; | ||
94 | /* | ||
95 | * All protection frames are transmited at 2Mb/s for | ||
96 | * 11g, otherwise at 1Mb/s. | ||
97 | * XXX select protection rate index from rate table. | ||
98 | */ | ||
99 | sc->sc_protrix = (mode == WIRELESS_MODE_11g ? 1 : 0); | ||
100 | /* rate index used to send mgt frames */ | ||
101 | sc->sc_minrateix = 0; | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * Select Rate Table | ||
106 | * | ||
107 | * Based on the wireless mode passed in, the rate table in the ATH object | ||
108 | * is set to the mode specific rate table. This also calls the callback | ||
109 | * function to set the rate in the protocol layer object. | ||
110 | */ | ||
111 | |||
112 | static int ath_rate_setup(struct ath_softc *sc, enum wireless_mode mode) | ||
113 | { | ||
114 | struct ath_hal *ah = sc->sc_ah; | ||
115 | const struct ath9k_rate_table *rt; | ||
116 | |||
117 | switch (mode) { | ||
118 | case WIRELESS_MODE_11a: | ||
119 | sc->sc_rates[mode] = | ||
120 | ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11A); | ||
121 | break; | ||
122 | case WIRELESS_MODE_11b: | ||
123 | sc->sc_rates[mode] = | ||
124 | ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11B); | ||
125 | break; | ||
126 | case WIRELESS_MODE_11g: | ||
127 | sc->sc_rates[mode] = | ||
128 | ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11G); | ||
129 | break; | ||
130 | case WIRELESS_MODE_11NA_HT20: | ||
131 | sc->sc_rates[mode] = | ||
132 | ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11NA_HT20); | ||
133 | break; | ||
134 | case WIRELESS_MODE_11NG_HT20: | ||
135 | sc->sc_rates[mode] = | ||
136 | ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11NG_HT20); | ||
137 | break; | ||
138 | case WIRELESS_MODE_11NA_HT40PLUS: | ||
139 | sc->sc_rates[mode] = | ||
140 | ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11NA_HT40PLUS); | ||
141 | break; | ||
142 | case WIRELESS_MODE_11NA_HT40MINUS: | ||
143 | sc->sc_rates[mode] = | ||
144 | ath9k_hw_getratetable(ah, | ||
145 | ATH9K_MODE_SEL_11NA_HT40MINUS); | ||
146 | break; | ||
147 | case WIRELESS_MODE_11NG_HT40PLUS: | ||
148 | sc->sc_rates[mode] = | ||
149 | ath9k_hw_getratetable(ah, ATH9K_MODE_SEL_11NG_HT40PLUS); | ||
150 | break; | ||
151 | case WIRELESS_MODE_11NG_HT40MINUS: | ||
152 | sc->sc_rates[mode] = | ||
153 | ath9k_hw_getratetable(ah, | ||
154 | ATH9K_MODE_SEL_11NG_HT40MINUS); | ||
155 | break; | ||
156 | default: | ||
157 | DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid mode %u\n", | ||
158 | __func__, mode); | ||
159 | return 0; | ||
160 | } | ||
161 | rt = sc->sc_rates[mode]; | ||
162 | if (rt == NULL) | ||
163 | return 0; | ||
164 | |||
165 | /* setup rate set in 802.11 protocol layer */ | ||
166 | ath_setup_rate(sc, mode, NORMAL_RATE, rt); | ||
167 | |||
168 | return 1; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * Set up channel list | ||
173 | */ | ||
174 | static int ath_setup_channels(struct ath_softc *sc) | ||
175 | { | ||
176 | struct ath_hal *ah = sc->sc_ah; | ||
177 | int nchan, i, a = 0, b = 0; | ||
178 | u8 regclassids[ATH_REGCLASSIDS_MAX]; | ||
179 | u32 nregclass = 0; | ||
180 | struct ieee80211_supported_band *band_2ghz; | ||
181 | struct ieee80211_supported_band *band_5ghz; | ||
182 | struct ieee80211_channel *chan_2ghz; | ||
183 | struct ieee80211_channel *chan_5ghz; | ||
184 | struct ath9k_channel *c; | ||
185 | |||
186 | /* Fill in ah->ah_channels */ | ||
187 | if (!ath9k_regd_init_channels(ah, | ||
188 | ATH_CHAN_MAX, | ||
189 | (u32 *)&nchan, | ||
190 | regclassids, | ||
191 | ATH_REGCLASSIDS_MAX, | ||
192 | &nregclass, | ||
193 | CTRY_DEFAULT, | ||
194 | ATH9K_MODE_SEL_ALL, | ||
195 | false, | ||
196 | 1)) { | ||
197 | u32 rd = ah->ah_currentRD; | ||
198 | |||
199 | DPRINTF(sc, ATH_DBG_FATAL, | ||
200 | "%s: unable to collect channel list; " | ||
201 | "regdomain likely %u country code %u\n", | ||
202 | __func__, rd, CTRY_DEFAULT); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
207 | band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
208 | chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ]; | ||
209 | chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ]; | ||
210 | |||
211 | for (i = 0; i < nchan; i++) { | ||
212 | c = &ah->ah_channels[i]; | ||
213 | if (IS_CHAN_2GHZ(c)) { | ||
214 | chan_2ghz[a].band = IEEE80211_BAND_2GHZ; | ||
215 | chan_2ghz[a].center_freq = c->channel; | ||
216 | chan_2ghz[a].max_power = c->maxTxPower; | ||
217 | |||
218 | if (c->privFlags & CHANNEL_DISALLOW_ADHOC) | ||
219 | chan_2ghz[a].flags |= | ||
220 | IEEE80211_CHAN_NO_IBSS; | ||
221 | if (c->channelFlags & CHANNEL_PASSIVE) | ||
222 | chan_2ghz[a].flags |= | ||
223 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
224 | |||
225 | band_2ghz->n_channels = ++a; | ||
226 | |||
227 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
228 | "%s: 2MHz channel: %d, " | ||
229 | "channelFlags: 0x%x\n", | ||
230 | __func__, | ||
231 | c->channel, | ||
232 | c->channelFlags); | ||
233 | } else if (IS_CHAN_5GHZ(c)) { | ||
234 | chan_5ghz[b].band = IEEE80211_BAND_5GHZ; | ||
235 | chan_5ghz[b].center_freq = c->channel; | ||
236 | chan_5ghz[b].max_power = c->maxTxPower; | ||
237 | |||
238 | if (c->privFlags & CHANNEL_DISALLOW_ADHOC) | ||
239 | chan_5ghz[b].flags |= | ||
240 | IEEE80211_CHAN_NO_IBSS; | ||
241 | if (c->channelFlags & CHANNEL_PASSIVE) | ||
242 | chan_5ghz[b].flags |= | ||
243 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
244 | |||
245 | band_5ghz->n_channels = ++b; | ||
246 | |||
247 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
248 | "%s: 5MHz channel: %d, " | ||
249 | "channelFlags: 0x%x\n", | ||
250 | __func__, | ||
251 | c->channel, | ||
252 | c->channelFlags); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * Determine mode from channel flags | ||
261 | * | ||
262 | * This routine will provide the enumerated WIRELESSS_MODE value based | ||
263 | * on the settings of the channel flags. If ho valid set of flags | ||
264 | * exist, the lowest mode (11b) is selected. | ||
265 | */ | ||
266 | |||
267 | static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan) | ||
268 | { | ||
269 | if (chan->chanmode == CHANNEL_A) | ||
270 | return WIRELESS_MODE_11a; | ||
271 | else if (chan->chanmode == CHANNEL_G) | ||
272 | return WIRELESS_MODE_11g; | ||
273 | else if (chan->chanmode == CHANNEL_B) | ||
274 | return WIRELESS_MODE_11b; | ||
275 | else if (chan->chanmode == CHANNEL_A_HT20) | ||
276 | return WIRELESS_MODE_11NA_HT20; | ||
277 | else if (chan->chanmode == CHANNEL_G_HT20) | ||
278 | return WIRELESS_MODE_11NG_HT20; | ||
279 | else if (chan->chanmode == CHANNEL_A_HT40PLUS) | ||
280 | return WIRELESS_MODE_11NA_HT40PLUS; | ||
281 | else if (chan->chanmode == CHANNEL_A_HT40MINUS) | ||
282 | return WIRELESS_MODE_11NA_HT40MINUS; | ||
283 | else if (chan->chanmode == CHANNEL_G_HT40PLUS) | ||
284 | return WIRELESS_MODE_11NG_HT40PLUS; | ||
285 | else if (chan->chanmode == CHANNEL_G_HT40MINUS) | ||
286 | return WIRELESS_MODE_11NG_HT40MINUS; | ||
287 | |||
288 | /* NB: should not get here */ | ||
289 | return WIRELESS_MODE_11b; | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * Change Channels | ||
294 | * | ||
295 | * Performs the actions to change the channel in the hardware, and set up | ||
296 | * the current operating mode for the new channel. | ||
297 | */ | ||
298 | |||
299 | static void ath_chan_change(struct ath_softc *sc, struct ath9k_channel *chan) | ||
300 | { | ||
301 | enum wireless_mode mode; | ||
302 | |||
303 | mode = ath_chan2mode(chan); | ||
304 | |||
305 | ath_rate_setup(sc, mode); | ||
306 | ath_setcurmode(sc, mode); | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * Stop the device, grabbing the top-level lock to protect | ||
311 | * against concurrent entry through ath_init (which can happen | ||
312 | * if another thread does a system call and the thread doing the | ||
313 | * stop is preempted). | ||
314 | */ | ||
315 | |||
316 | static int ath_stop(struct ath_softc *sc) | ||
317 | { | ||
318 | struct ath_hal *ah = sc->sc_ah; | ||
319 | |||
320 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %u\n", | ||
321 | __func__, sc->sc_invalid); | ||
322 | |||
323 | /* | ||
324 | * Shutdown the hardware and driver: | ||
325 | * stop output from above | ||
326 | * reset 802.11 state machine | ||
327 | * (sends station deassoc/deauth frames) | ||
328 | * turn off timers | ||
329 | * disable interrupts | ||
330 | * clear transmit machinery | ||
331 | * clear receive machinery | ||
332 | * turn off the radio | ||
333 | * reclaim beacon resources | ||
334 | * | ||
335 | * Note that some of this work is not possible if the | ||
336 | * hardware is gone (invalid). | ||
337 | */ | ||
338 | |||
339 | if (!sc->sc_invalid) | ||
340 | ath9k_hw_set_interrupts(ah, 0); | ||
341 | ath_draintxq(sc, false); | ||
342 | if (!sc->sc_invalid) { | ||
343 | ath_stoprecv(sc); | ||
344 | ath9k_hw_phy_disable(ah); | ||
345 | } else | ||
346 | sc->sc_rxlink = NULL; | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * Start Scan | ||
353 | * | ||
354 | * This function is called when starting a channel scan. It will perform | ||
355 | * power save wakeup processing, set the filter for the scan, and get the | ||
356 | * chip ready to send broadcast packets out during the scan. | ||
357 | */ | ||
358 | |||
359 | void ath_scan_start(struct ath_softc *sc) | ||
360 | { | ||
361 | struct ath_hal *ah = sc->sc_ah; | ||
362 | u32 rfilt; | ||
363 | u32 now = (u32) jiffies_to_msecs(get_timestamp()); | ||
364 | |||
365 | sc->sc_scanning = 1; | ||
366 | rfilt = ath_calcrxfilter(sc); | ||
367 | ath9k_hw_setrxfilter(ah, rfilt); | ||
368 | ath9k_hw_write_associd(ah, ath_bcast_mac, 0); | ||
369 | |||
370 | /* Restore previous power management state. */ | ||
371 | |||
372 | DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0\n", | ||
373 | now / 1000, now % 1000, __func__, rfilt); | ||
374 | } | ||
375 | |||
376 | /* | ||
377 | * Scan End | ||
378 | * | ||
379 | * This routine is called by the upper layer when the scan is completed. This | ||
380 | * will set the filters back to normal operating mode, set the BSSID to the | ||
381 | * correct value, and restore the power save state. | ||
382 | */ | ||
383 | |||
384 | void ath_scan_end(struct ath_softc *sc) | ||
385 | { | ||
386 | struct ath_hal *ah = sc->sc_ah; | ||
387 | u32 rfilt; | ||
388 | u32 now = (u32) jiffies_to_msecs(get_timestamp()); | ||
389 | |||
390 | sc->sc_scanning = 0; | ||
391 | /* Request for a full reset due to rx packet filter changes */ | ||
392 | sc->sc_full_reset = 1; | ||
393 | rfilt = ath_calcrxfilter(sc); | ||
394 | ath9k_hw_setrxfilter(ah, rfilt); | ||
395 | ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid); | ||
396 | |||
397 | DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0x%x\n", | ||
398 | now / 1000, now % 1000, __func__, rfilt, sc->sc_curaid); | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * Set the current channel | ||
403 | * | ||
404 | * Set/change channels. If the channel is really being changed, it's done | ||
405 | * by reseting the chip. To accomplish this we must first cleanup any pending | ||
406 | * DMA, then restart stuff after a la ath_init. | ||
407 | */ | ||
408 | int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) | ||
409 | { | ||
410 | struct ath_hal *ah = sc->sc_ah; | ||
411 | bool fastcc = true, stopped; | ||
412 | enum ath9k_ht_macmode ht_macmode; | ||
413 | |||
414 | if (sc->sc_invalid) /* if the device is invalid or removed */ | ||
415 | return -EIO; | ||
416 | |||
417 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
418 | "%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n", | ||
419 | __func__, | ||
420 | ath9k_hw_mhz2ieee(ah, sc->sc_curchan.channel, | ||
421 | sc->sc_curchan.channelFlags), | ||
422 | sc->sc_curchan.channel, | ||
423 | ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags), | ||
424 | hchan->channel, hchan->channelFlags); | ||
425 | |||
426 | ht_macmode = ath_cwm_macmode(sc); | ||
427 | |||
428 | if (hchan->channel != sc->sc_curchan.channel || | ||
429 | hchan->channelFlags != sc->sc_curchan.channelFlags || | ||
430 | sc->sc_update_chainmask || sc->sc_full_reset) { | ||
431 | int status; | ||
432 | /* | ||
433 | * This is only performed if the channel settings have | ||
434 | * actually changed. | ||
435 | * | ||
436 | * To switch channels clear any pending DMA operations; | ||
437 | * wait long enough for the RX fifo to drain, reset the | ||
438 | * hardware at the new frequency, and then re-enable | ||
439 | * the relevant bits of the h/w. | ||
440 | */ | ||
441 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ | ||
442 | ath_draintxq(sc, false); /* clear pending tx frames */ | ||
443 | stopped = ath_stoprecv(sc); /* turn off frame recv */ | ||
444 | |||
445 | /* XXX: do not flush receive queue here. We don't want | ||
446 | * to flush data frames already in queue because of | ||
447 | * changing channel. */ | ||
448 | |||
449 | if (!stopped || sc->sc_full_reset) | ||
450 | fastcc = false; | ||
451 | |||
452 | spin_lock_bh(&sc->sc_resetlock); | ||
453 | if (!ath9k_hw_reset(ah, sc->sc_opmode, hchan, | ||
454 | ht_macmode, sc->sc_tx_chainmask, | ||
455 | sc->sc_rx_chainmask, | ||
456 | sc->sc_ht_extprotspacing, | ||
457 | fastcc, &status)) { | ||
458 | DPRINTF(sc, ATH_DBG_FATAL, | ||
459 | "%s: unable to reset channel %u (%uMhz) " | ||
460 | "flags 0x%x hal status %u\n", __func__, | ||
461 | ath9k_hw_mhz2ieee(ah, hchan->channel, | ||
462 | hchan->channelFlags), | ||
463 | hchan->channel, hchan->channelFlags, status); | ||
464 | spin_unlock_bh(&sc->sc_resetlock); | ||
465 | return -EIO; | ||
466 | } | ||
467 | spin_unlock_bh(&sc->sc_resetlock); | ||
468 | |||
469 | sc->sc_curchan = *hchan; | ||
470 | sc->sc_update_chainmask = 0; | ||
471 | sc->sc_full_reset = 0; | ||
472 | |||
473 | /* Re-enable rx framework */ | ||
474 | if (ath_startrecv(sc) != 0) { | ||
475 | DPRINTF(sc, ATH_DBG_FATAL, | ||
476 | "%s: unable to restart recv logic\n", __func__); | ||
477 | return -EIO; | ||
478 | } | ||
479 | /* | ||
480 | * Change channels and update the h/w rate map | ||
481 | * if we're switching; e.g. 11a to 11b/g. | ||
482 | */ | ||
483 | ath_chan_change(sc, hchan); | ||
484 | ath_update_txpow(sc); /* update tx power state */ | ||
485 | /* | ||
486 | * Re-enable interrupts. | ||
487 | */ | ||
488 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
489 | } | ||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | /**********************/ | ||
494 | /* Chainmask Handling */ | ||
495 | /**********************/ | ||
496 | |||
497 | static void ath_chainmask_sel_timertimeout(unsigned long data) | ||
498 | { | ||
499 | struct ath_chainmask_sel *cm = (struct ath_chainmask_sel *)data; | ||
500 | cm->switch_allowed = 1; | ||
501 | } | ||
502 | |||
503 | /* Start chainmask select timer */ | ||
504 | static void ath_chainmask_sel_timerstart(struct ath_chainmask_sel *cm) | ||
505 | { | ||
506 | cm->switch_allowed = 0; | ||
507 | mod_timer(&cm->timer, ath_chainmask_sel_period); | ||
508 | } | ||
509 | |||
510 | /* Stop chainmask select timer */ | ||
511 | static void ath_chainmask_sel_timerstop(struct ath_chainmask_sel *cm) | ||
512 | { | ||
513 | cm->switch_allowed = 0; | ||
514 | del_timer_sync(&cm->timer); | ||
515 | } | ||
516 | |||
517 | static void ath_chainmask_sel_init(struct ath_softc *sc, struct ath_node *an) | ||
518 | { | ||
519 | struct ath_chainmask_sel *cm = &an->an_chainmask_sel; | ||
520 | |||
521 | memzero(cm, sizeof(struct ath_chainmask_sel)); | ||
522 | |||
523 | cm->cur_tx_mask = sc->sc_tx_chainmask; | ||
524 | cm->cur_rx_mask = sc->sc_rx_chainmask; | ||
525 | cm->tx_avgrssi = ATH_RSSI_DUMMY_MARKER; | ||
526 | setup_timer(&cm->timer, | ||
527 | ath_chainmask_sel_timertimeout, (unsigned long) cm); | ||
528 | } | ||
529 | |||
530 | int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an) | ||
531 | { | ||
532 | struct ath_chainmask_sel *cm = &an->an_chainmask_sel; | ||
533 | |||
534 | /* | ||
535 | * Disable auto-swtiching in one of the following if conditions. | ||
536 | * sc_chainmask_auto_sel is used for internal global auto-switching | ||
537 | * enabled/disabled setting | ||
538 | */ | ||
539 | if (sc->sc_ah->ah_caps.halTxChainMask != ATH_CHAINMASK_SEL_3X3) { | ||
540 | cm->cur_tx_mask = sc->sc_tx_chainmask; | ||
541 | return cm->cur_tx_mask; | ||
542 | } | ||
543 | |||
544 | if (cm->tx_avgrssi == ATH_RSSI_DUMMY_MARKER) | ||
545 | return cm->cur_tx_mask; | ||
546 | |||
547 | if (cm->switch_allowed) { | ||
548 | /* Switch down from tx 3 to tx 2. */ | ||
549 | if (cm->cur_tx_mask == ATH_CHAINMASK_SEL_3X3 && | ||
550 | ATH_RSSI_OUT(cm->tx_avgrssi) >= | ||
551 | ath_chainmask_sel_down_rssi_thres) { | ||
552 | cm->cur_tx_mask = sc->sc_tx_chainmask; | ||
553 | |||
554 | /* Don't let another switch happen until | ||
555 | * this timer expires */ | ||
556 | ath_chainmask_sel_timerstart(cm); | ||
557 | } | ||
558 | /* Switch up from tx 2 to 3. */ | ||
559 | else if (cm->cur_tx_mask == sc->sc_tx_chainmask && | ||
560 | ATH_RSSI_OUT(cm->tx_avgrssi) <= | ||
561 | ath_chainmask_sel_up_rssi_thres) { | ||
562 | cm->cur_tx_mask = ATH_CHAINMASK_SEL_3X3; | ||
563 | |||
564 | /* Don't let another switch happen | ||
565 | * until this timer expires */ | ||
566 | ath_chainmask_sel_timerstart(cm); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | return cm->cur_tx_mask; | ||
571 | } | ||
572 | |||
573 | /* | ||
574 | * Update tx/rx chainmask. For legacy association, | ||
575 | * hard code chainmask to 1x1, for 11n association, use | ||
576 | * the chainmask configuration. | ||
577 | */ | ||
578 | |||
579 | void ath_update_chainmask(struct ath_softc *sc, int is_ht) | ||
580 | { | ||
581 | sc->sc_update_chainmask = 1; | ||
582 | if (is_ht) { | ||
583 | sc->sc_tx_chainmask = sc->sc_ah->ah_caps.halTxChainMask; | ||
584 | sc->sc_rx_chainmask = sc->sc_ah->ah_caps.halRxChainMask; | ||
585 | } else { | ||
586 | sc->sc_tx_chainmask = 1; | ||
587 | sc->sc_rx_chainmask = 1; | ||
588 | } | ||
589 | |||
590 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: tx chmask: %d, rx chmask: %d\n", | ||
591 | __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask); | ||
592 | } | ||
593 | |||
594 | /******************/ | ||
595 | /* VAP management */ | ||
596 | /******************/ | ||
597 | |||
598 | /* | ||
599 | * VAP in Listen mode | ||
600 | * | ||
601 | * This routine brings the VAP out of the down state into a "listen" state | ||
602 | * where it waits for association requests. This is used in AP and AdHoc | ||
603 | * modes. | ||
604 | */ | ||
605 | |||
606 | int ath_vap_listen(struct ath_softc *sc, int if_id) | ||
607 | { | ||
608 | struct ath_hal *ah = sc->sc_ah; | ||
609 | struct ath_vap *avp; | ||
610 | u32 rfilt = 0; | ||
611 | DECLARE_MAC_BUF(mac); | ||
612 | |||
613 | avp = sc->sc_vaps[if_id]; | ||
614 | if (avp == NULL) { | ||
615 | DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n", | ||
616 | __func__, if_id); | ||
617 | return -EINVAL; | ||
618 | } | ||
619 | |||
620 | #ifdef CONFIG_SLOW_ANT_DIV | ||
621 | ath_slow_ant_div_stop(&sc->sc_antdiv); | ||
622 | #endif | ||
623 | |||
624 | /* update ratectrl about the new state */ | ||
625 | ath_rate_newstate(sc, avp); | ||
626 | |||
627 | rfilt = ath_calcrxfilter(sc); | ||
628 | ath9k_hw_setrxfilter(ah, rfilt); | ||
629 | |||
630 | if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS) { | ||
631 | memcpy(sc->sc_curbssid, ath_bcast_mac, ETH_ALEN); | ||
632 | ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid); | ||
633 | } else | ||
634 | sc->sc_curaid = 0; | ||
635 | |||
636 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
637 | "%s: RX filter 0x%x bssid %s aid 0x%x\n", | ||
638 | __func__, rfilt, print_mac(mac, | ||
639 | sc->sc_curbssid), sc->sc_curaid); | ||
640 | |||
641 | /* | ||
642 | * XXXX | ||
643 | * Disable BMISS interrupt when we're not associated | ||
644 | */ | ||
645 | ath9k_hw_set_interrupts(ah, | ||
646 | sc->sc_imask & ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS)); | ||
647 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | ||
648 | /* need to reconfigure the beacons when it moves to RUN */ | ||
649 | sc->sc_beacons = 0; | ||
650 | |||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | int ath_vap_attach(struct ath_softc *sc, | ||
655 | int if_id, | ||
656 | struct ieee80211_vif *if_data, | ||
657 | enum ath9k_opmode opmode) | ||
658 | { | ||
659 | struct ath_vap *avp; | ||
660 | |||
661 | if (if_id >= ATH_BCBUF || sc->sc_vaps[if_id] != NULL) { | ||
662 | DPRINTF(sc, ATH_DBG_FATAL, | ||
663 | "%s: Invalid interface id = %u\n", __func__, if_id); | ||
664 | return -EINVAL; | ||
665 | } | ||
666 | |||
667 | switch (opmode) { | ||
668 | case ATH9K_M_STA: | ||
669 | case ATH9K_M_IBSS: | ||
670 | case ATH9K_M_MONITOR: | ||
671 | break; | ||
672 | case ATH9K_M_HOSTAP: | ||
673 | /* XXX not right, beacon buffer is allocated on RUN trans */ | ||
674 | if (list_empty(&sc->sc_bbuf)) | ||
675 | return -ENOMEM; | ||
676 | break; | ||
677 | default: | ||
678 | return -EINVAL; | ||
679 | } | ||
680 | |||
681 | /* create ath_vap */ | ||
682 | avp = kmalloc(sizeof(struct ath_vap), GFP_KERNEL); | ||
683 | if (avp == NULL) | ||
684 | return -ENOMEM; | ||
685 | |||
686 | memzero(avp, sizeof(struct ath_vap)); | ||
687 | avp->av_if_data = if_data; | ||
688 | /* Set the VAP opmode */ | ||
689 | avp->av_opmode = opmode; | ||
690 | avp->av_bslot = -1; | ||
691 | INIT_LIST_HEAD(&avp->av_mcastq.axq_q); | ||
692 | INIT_LIST_HEAD(&avp->av_mcastq.axq_acq); | ||
693 | spin_lock_init(&avp->av_mcastq.axq_lock); | ||
694 | |||
695 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); | ||
696 | |||
697 | sc->sc_vaps[if_id] = avp; | ||
698 | sc->sc_nvaps++; | ||
699 | /* Set the device opmode */ | ||
700 | sc->sc_opmode = opmode; | ||
701 | |||
702 | /* default VAP configuration */ | ||
703 | avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE; | ||
704 | avp->av_config.av_fixed_retryset = 0x03030303; | ||
705 | |||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | int ath_vap_detach(struct ath_softc *sc, int if_id) | ||
710 | { | ||
711 | struct ath_hal *ah = sc->sc_ah; | ||
712 | struct ath_vap *avp; | ||
713 | |||
714 | avp = sc->sc_vaps[if_id]; | ||
715 | if (avp == NULL) { | ||
716 | DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n", | ||
717 | __func__, if_id); | ||
718 | return -EINVAL; | ||
719 | } | ||
720 | |||
721 | /* | ||
722 | * Quiesce the hardware while we remove the vap. In | ||
723 | * particular we need to reclaim all references to the | ||
724 | * vap state by any frames pending on the tx queues. | ||
725 | * | ||
726 | * XXX can we do this w/o affecting other vap's? | ||
727 | */ | ||
728 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ | ||
729 | ath_draintxq(sc, false); /* stop xmit side */ | ||
730 | ath_stoprecv(sc); /* stop recv side */ | ||
731 | ath_flushrecv(sc); /* flush recv queue */ | ||
732 | |||
733 | /* Reclaim any pending mcast bufs on the vap. */ | ||
734 | ath_tx_draintxq(sc, &avp->av_mcastq, false); | ||
735 | |||
736 | kfree(avp); | ||
737 | sc->sc_vaps[if_id] = NULL; | ||
738 | sc->sc_nvaps--; | ||
739 | |||
740 | return 0; | ||
741 | } | ||
742 | |||
743 | int ath_vap_config(struct ath_softc *sc, | ||
744 | int if_id, struct ath_vap_config *if_config) | ||
745 | { | ||
746 | struct ath_vap *avp; | ||
747 | |||
748 | if (if_id >= ATH_BCBUF) { | ||
749 | DPRINTF(sc, ATH_DBG_FATAL, | ||
750 | "%s: Invalid interface id = %u\n", __func__, if_id); | ||
751 | return -EINVAL; | ||
752 | } | ||
753 | |||
754 | avp = sc->sc_vaps[if_id]; | ||
755 | ASSERT(avp != NULL); | ||
756 | |||
757 | if (avp) | ||
758 | memcpy(&avp->av_config, if_config, sizeof(avp->av_config)); | ||
759 | |||
760 | return 0; | ||
761 | } | ||
762 | |||
763 | /********/ | ||
764 | /* Core */ | ||
765 | /********/ | ||
766 | |||
767 | int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | ||
768 | { | ||
769 | struct ath_hal *ah = sc->sc_ah; | ||
770 | int status; | ||
771 | int error = 0; | ||
772 | enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); | ||
773 | |||
774 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", __func__, sc->sc_opmode); | ||
775 | |||
776 | /* | ||
777 | * Stop anything previously setup. This is safe | ||
778 | * whether this is the first time through or not. | ||
779 | */ | ||
780 | ath_stop(sc); | ||
781 | |||
782 | /* Initialize chanmask selection */ | ||
783 | sc->sc_tx_chainmask = ah->ah_caps.halTxChainMask; | ||
784 | sc->sc_rx_chainmask = ah->ah_caps.halRxChainMask; | ||
785 | |||
786 | /* Reset SERDES registers */ | ||
787 | ath9k_hw_configpcipowersave(ah, 0); | ||
788 | |||
789 | /* | ||
790 | * The basic interface to setting the hardware in a good | ||
791 | * state is ``reset''. On return the hardware is known to | ||
792 | * be powered up and with interrupts disabled. This must | ||
793 | * be followed by initialization of the appropriate bits | ||
794 | * and then setup of the interrupt mask. | ||
795 | */ | ||
796 | sc->sc_curchan = *initial_chan; | ||
797 | |||
798 | spin_lock_bh(&sc->sc_resetlock); | ||
799 | if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, ht_macmode, | ||
800 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
801 | sc->sc_ht_extprotspacing, false, &status)) { | ||
802 | DPRINTF(sc, ATH_DBG_FATAL, | ||
803 | "%s: unable to reset hardware; hal status %u " | ||
804 | "(freq %u flags 0x%x)\n", __func__, status, | ||
805 | sc->sc_curchan.channel, sc->sc_curchan.channelFlags); | ||
806 | error = -EIO; | ||
807 | spin_unlock_bh(&sc->sc_resetlock); | ||
808 | goto done; | ||
809 | } | ||
810 | spin_unlock_bh(&sc->sc_resetlock); | ||
811 | /* | ||
812 | * This is needed only to setup initial state | ||
813 | * but it's best done after a reset. | ||
814 | */ | ||
815 | ath_update_txpow(sc); | ||
816 | |||
817 | /* | ||
818 | * Setup the hardware after reset: | ||
819 | * The receive engine is set going. | ||
820 | * Frame transmit is handled entirely | ||
821 | * in the frame output path; there's nothing to do | ||
822 | * here except setup the interrupt mask. | ||
823 | */ | ||
824 | if (ath_startrecv(sc) != 0) { | ||
825 | DPRINTF(sc, ATH_DBG_FATAL, | ||
826 | "%s: unable to start recv logic\n", __func__); | ||
827 | error = -EIO; | ||
828 | goto done; | ||
829 | } | ||
830 | /* Setup our intr mask. */ | ||
831 | sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX | ||
832 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | ||
833 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; | ||
834 | |||
835 | if (ah->ah_caps.halGTTSupport) | ||
836 | sc->sc_imask |= ATH9K_INT_GTT; | ||
837 | |||
838 | if (ah->ah_caps.halHTSupport) | ||
839 | sc->sc_imask |= ATH9K_INT_CST; | ||
840 | |||
841 | /* | ||
842 | * Enable MIB interrupts when there are hardware phy counters. | ||
843 | * Note we only do this (at the moment) for station mode. | ||
844 | */ | ||
845 | if (ath9k_hw_phycounters(ah) && | ||
846 | ((sc->sc_opmode == ATH9K_M_STA) || (sc->sc_opmode == ATH9K_M_IBSS))) | ||
847 | sc->sc_imask |= ATH9K_INT_MIB; | ||
848 | /* | ||
849 | * Some hardware processes the TIM IE and fires an | ||
850 | * interrupt when the TIM bit is set. For hardware | ||
851 | * that does, if not overridden by configuration, | ||
852 | * enable the TIM interrupt when operating as station. | ||
853 | */ | ||
854 | if (ah->ah_caps.halEnhancedPmSupport && sc->sc_opmode == ATH9K_M_STA && | ||
855 | !sc->sc_config.swBeaconProcess) | ||
856 | sc->sc_imask |= ATH9K_INT_TIM; | ||
857 | /* | ||
858 | * Don't enable interrupts here as we've not yet built our | ||
859 | * vap and node data structures, which will be needed as soon | ||
860 | * as we start receiving. | ||
861 | */ | ||
862 | ath_chan_change(sc, initial_chan); | ||
863 | |||
864 | /* XXX: we must make sure h/w is ready and clear invalid flag | ||
865 | * before turning on interrupt. */ | ||
866 | sc->sc_invalid = 0; | ||
867 | done: | ||
868 | return error; | ||
869 | } | ||
870 | |||
871 | /* | ||
872 | * Reset the hardware w/o losing operational state. This is | ||
873 | * basically a more efficient way of doing ath_stop, ath_init, | ||
874 | * followed by state transitions to the current 802.11 | ||
875 | * operational state. Used to recover from errors rx overrun | ||
876 | * and to reset the hardware when rf gain settings must be reset. | ||
877 | */ | ||
878 | |||
879 | static int ath_reset_start(struct ath_softc *sc, u32 flag) | ||
880 | { | ||
881 | struct ath_hal *ah = sc->sc_ah; | ||
882 | |||
883 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ | ||
884 | ath_draintxq(sc, flag & RESET_RETRY_TXQ); /* stop xmit side */ | ||
885 | ath_stoprecv(sc); /* stop recv side */ | ||
886 | ath_flushrecv(sc); /* flush recv queue */ | ||
887 | |||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | static int ath_reset_end(struct ath_softc *sc, u32 flag) | ||
892 | { | ||
893 | struct ath_hal *ah = sc->sc_ah; | ||
894 | |||
895 | if (ath_startrecv(sc) != 0) /* restart recv */ | ||
896 | DPRINTF(sc, ATH_DBG_FATAL, | ||
897 | "%s: unable to start recv logic\n", __func__); | ||
898 | |||
899 | /* | ||
900 | * We may be doing a reset in response to a request | ||
901 | * that changes the channel so update any state that | ||
902 | * might change as a result. | ||
903 | */ | ||
904 | ath_chan_change(sc, &sc->sc_curchan); | ||
905 | |||
906 | ath_update_txpow(sc); /* update tx power state */ | ||
907 | |||
908 | if (sc->sc_beacons) | ||
909 | ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ | ||
910 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
911 | |||
912 | /* Restart the txq */ | ||
913 | if (flag & RESET_RETRY_TXQ) { | ||
914 | int i; | ||
915 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
916 | if (ATH_TXQ_SETUP(sc, i)) { | ||
917 | spin_lock_bh(&sc->sc_txq[i].axq_lock); | ||
918 | ath_txq_schedule(sc, &sc->sc_txq[i]); | ||
919 | spin_unlock_bh(&sc->sc_txq[i].axq_lock); | ||
920 | } | ||
921 | } | ||
922 | } | ||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | int ath_reset(struct ath_softc *sc) | ||
927 | { | ||
928 | struct ath_hal *ah = sc->sc_ah; | ||
929 | int status; | ||
930 | int error = 0; | ||
931 | enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); | ||
932 | |||
933 | /* NB: indicate channel change so we do a full reset */ | ||
934 | spin_lock_bh(&sc->sc_resetlock); | ||
935 | if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, | ||
936 | ht_macmode, | ||
937 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
938 | sc->sc_ht_extprotspacing, false, &status)) { | ||
939 | DPRINTF(sc, ATH_DBG_FATAL, | ||
940 | "%s: unable to reset hardware; hal status %u\n", | ||
941 | __func__, status); | ||
942 | error = -EIO; | ||
943 | } | ||
944 | spin_unlock_bh(&sc->sc_resetlock); | ||
945 | |||
946 | return error; | ||
947 | } | ||
948 | |||
949 | int ath_suspend(struct ath_softc *sc) | ||
950 | { | ||
951 | struct ath_hal *ah = sc->sc_ah; | ||
952 | |||
953 | /* No I/O if device has been surprise removed */ | ||
954 | if (sc->sc_invalid) | ||
955 | return -EIO; | ||
956 | |||
957 | /* Shut off the interrupt before setting sc->sc_invalid to '1' */ | ||
958 | ath9k_hw_set_interrupts(ah, 0); | ||
959 | |||
960 | /* XXX: we must make sure h/w will not generate any interrupt | ||
961 | * before setting the invalid flag. */ | ||
962 | sc->sc_invalid = 1; | ||
963 | |||
964 | /* disable HAL and put h/w to sleep */ | ||
965 | ath9k_hw_disable(sc->sc_ah); | ||
966 | |||
967 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); | ||
968 | |||
969 | return 0; | ||
970 | } | ||
971 | |||
972 | /* Interrupt handler. Most of the actual processing is deferred. | ||
973 | * It's the caller's responsibility to ensure the chip is awake. */ | ||
974 | |||
975 | irqreturn_t ath_isr(int irq, void *dev) | ||
976 | { | ||
977 | struct ath_softc *sc = dev; | ||
978 | struct ath_hal *ah = sc->sc_ah; | ||
979 | enum ath9k_int status; | ||
980 | bool sched = false; | ||
981 | |||
982 | do { | ||
983 | if (sc->sc_invalid) { | ||
984 | /* | ||
985 | * The hardware is not ready/present, don't | ||
986 | * touch anything. Note this can happen early | ||
987 | * on if the IRQ is shared. | ||
988 | */ | ||
989 | return IRQ_NONE; | ||
990 | } | ||
991 | if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */ | ||
992 | return IRQ_NONE; | ||
993 | } | ||
994 | |||
995 | /* | ||
996 | * Figure out the reason(s) for the interrupt. Note | ||
997 | * that the hal returns a pseudo-ISR that may include | ||
998 | * bits we haven't explicitly enabled so we mask the | ||
999 | * value to insure we only process bits we requested. | ||
1000 | */ | ||
1001 | ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ | ||
1002 | |||
1003 | status &= sc->sc_imask; /* discard unasked-for bits */ | ||
1004 | |||
1005 | /* | ||
1006 | * If there are no status bits set, then this interrupt was not | ||
1007 | * for me (should have been caught above). | ||
1008 | */ | ||
1009 | |||
1010 | if (!status) | ||
1011 | return IRQ_NONE; | ||
1012 | |||
1013 | sc->sc_intrstatus = status; | ||
1014 | |||
1015 | if (status & ATH9K_INT_FATAL) { | ||
1016 | /* need a chip reset */ | ||
1017 | sched = true; | ||
1018 | } else if (status & ATH9K_INT_RXORN) { | ||
1019 | /* need a chip reset */ | ||
1020 | sched = true; | ||
1021 | } else { | ||
1022 | if (status & ATH9K_INT_SWBA) { | ||
1023 | /* schedule a tasklet for beacon handling */ | ||
1024 | tasklet_schedule(&sc->bcon_tasklet); | ||
1025 | } | ||
1026 | if (status & ATH9K_INT_RXEOL) { | ||
1027 | /* | ||
1028 | * NB: the hardware should re-read the link when | ||
1029 | * RXE bit is written, but it doesn't work | ||
1030 | * at least on older hardware revs. | ||
1031 | */ | ||
1032 | sched = true; | ||
1033 | } | ||
1034 | |||
1035 | if (status & ATH9K_INT_TXURN) | ||
1036 | /* bump tx trigger level */ | ||
1037 | ath9k_hw_updatetxtriglevel(ah, true); | ||
1038 | /* XXX: optimize this */ | ||
1039 | if (status & ATH9K_INT_RX) | ||
1040 | sched = true; | ||
1041 | if (status & ATH9K_INT_TX) | ||
1042 | sched = true; | ||
1043 | if (status & ATH9K_INT_BMISS) | ||
1044 | sched = true; | ||
1045 | /* carrier sense timeout */ | ||
1046 | if (status & ATH9K_INT_CST) | ||
1047 | sched = true; | ||
1048 | if (status & ATH9K_INT_MIB) { | ||
1049 | /* | ||
1050 | * Disable interrupts until we service the MIB | ||
1051 | * interrupt; otherwise it will continue to | ||
1052 | * fire. | ||
1053 | */ | ||
1054 | ath9k_hw_set_interrupts(ah, 0); | ||
1055 | /* | ||
1056 | * Let the hal handle the event. We assume | ||
1057 | * it will clear whatever condition caused | ||
1058 | * the interrupt. | ||
1059 | */ | ||
1060 | ath9k_hw_procmibevent(ah, &sc->sc_halstats); | ||
1061 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
1062 | } | ||
1063 | if (status & ATH9K_INT_TIM_TIMER) { | ||
1064 | if (!ah->ah_caps.halAutoSleepSupport) { | ||
1065 | /* Clear RxAbort bit so that we can | ||
1066 | * receive frames */ | ||
1067 | ath9k_hw_setrxabort(ah, 0); | ||
1068 | sched = true; | ||
1069 | } | ||
1070 | } | ||
1071 | } | ||
1072 | } while (0); | ||
1073 | |||
1074 | if (sched) { | ||
1075 | /* turn off every interrupt except SWBA */ | ||
1076 | ath9k_hw_set_interrupts(ah, (sc->sc_imask & ATH9K_INT_SWBA)); | ||
1077 | tasklet_schedule(&sc->intr_tq); | ||
1078 | } | ||
1079 | |||
1080 | return IRQ_HANDLED; | ||
1081 | } | ||
1082 | |||
1083 | /* Deferred interrupt processing */ | ||
1084 | |||
1085 | static void ath9k_tasklet(unsigned long data) | ||
1086 | { | ||
1087 | struct ath_softc *sc = (struct ath_softc *)data; | ||
1088 | u32 status = sc->sc_intrstatus; | ||
1089 | |||
1090 | if (status & ATH9K_INT_FATAL) { | ||
1091 | /* need a chip reset */ | ||
1092 | ath_internal_reset(sc); | ||
1093 | return; | ||
1094 | } else { | ||
1095 | |||
1096 | if (status & | ||
1097 | (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { | ||
1098 | /* XXX: fill me in */ | ||
1099 | /* | ||
1100 | if (status & ATH9K_INT_RXORN) { | ||
1101 | } | ||
1102 | if (status & ATH9K_INT_RXEOL) { | ||
1103 | } | ||
1104 | */ | ||
1105 | spin_lock_bh(&sc->sc_rxflushlock); | ||
1106 | ath_rx_tasklet(sc, 0); | ||
1107 | spin_unlock_bh(&sc->sc_rxflushlock); | ||
1108 | } | ||
1109 | /* XXX: optimize this */ | ||
1110 | if (status & ATH9K_INT_TX) | ||
1111 | ath_tx_tasklet(sc); | ||
1112 | /* XXX: fill me in */ | ||
1113 | /* | ||
1114 | if (status & ATH9K_INT_BMISS) { | ||
1115 | } | ||
1116 | if (status & (ATH9K_INT_TIM | ATH9K_INT_DTIMSYNC)) { | ||
1117 | if (status & ATH9K_INT_TIM) { | ||
1118 | } | ||
1119 | if (status & ATH9K_INT_DTIMSYNC) { | ||
1120 | } | ||
1121 | } | ||
1122 | */ | ||
1123 | } | ||
1124 | |||
1125 | /* re-enable hardware interrupt */ | ||
1126 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask); | ||
1127 | } | ||
1128 | |||
1129 | int ath_init(u16 devid, struct ath_softc *sc) | ||
1130 | { | ||
1131 | struct ath_hal *ah = NULL; | ||
1132 | int status; | ||
1133 | int error = 0, i; | ||
1134 | int csz = 0; | ||
1135 | u32 rd; | ||
1136 | |||
1137 | /* XXX: hardware will not be ready until ath_open() being called */ | ||
1138 | sc->sc_invalid = 1; | ||
1139 | |||
1140 | sc->sc_debug = DBG_DEFAULT; | ||
1141 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid); | ||
1142 | |||
1143 | /* Initialize tasklet */ | ||
1144 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | ||
1145 | tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, | ||
1146 | (unsigned long)sc); | ||
1147 | |||
1148 | /* | ||
1149 | * Cache line size is used to size and align various | ||
1150 | * structures used to communicate with the hardware. | ||
1151 | */ | ||
1152 | bus_read_cachesize(sc, &csz); | ||
1153 | /* XXX assert csz is non-zero */ | ||
1154 | sc->sc_cachelsz = csz << 2; /* convert to bytes */ | ||
1155 | |||
1156 | spin_lock_init(&sc->sc_resetlock); | ||
1157 | |||
1158 | ah = ath9k_hw_attach(devid, sc, sc->mem, &status); | ||
1159 | if (ah == NULL) { | ||
1160 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1161 | "%s: unable to attach hardware; HAL status %u\n", | ||
1162 | __func__, status); | ||
1163 | error = -ENXIO; | ||
1164 | goto bad; | ||
1165 | } | ||
1166 | sc->sc_ah = ah; | ||
1167 | |||
1168 | /* Get the chipset-specific aggr limit. */ | ||
1169 | sc->sc_rtsaggrlimit = ah->ah_caps.halRtsAggrLimit; | ||
1170 | |||
1171 | /* Get the hardware key cache size. */ | ||
1172 | sc->sc_keymax = ah->ah_caps.halKeyCacheSize; | ||
1173 | if (sc->sc_keymax > ATH_KEYMAX) { | ||
1174 | DPRINTF(sc, ATH_DBG_KEYCACHE, | ||
1175 | "%s: Warning, using only %u entries in %u key cache\n", | ||
1176 | __func__, ATH_KEYMAX, sc->sc_keymax); | ||
1177 | sc->sc_keymax = ATH_KEYMAX; | ||
1178 | } | ||
1179 | |||
1180 | /* | ||
1181 | * Reset the key cache since some parts do not | ||
1182 | * reset the contents on initial power up. | ||
1183 | */ | ||
1184 | for (i = 0; i < sc->sc_keymax; i++) | ||
1185 | ath9k_hw_keyreset(ah, (u16) i); | ||
1186 | /* | ||
1187 | * Mark key cache slots associated with global keys | ||
1188 | * as in use. If we knew TKIP was not to be used we | ||
1189 | * could leave the +32, +64, and +32+64 slots free. | ||
1190 | * XXX only for splitmic. | ||
1191 | */ | ||
1192 | for (i = 0; i < IEEE80211_WEP_NKID; i++) { | ||
1193 | set_bit(i, sc->sc_keymap); | ||
1194 | set_bit(i + 32, sc->sc_keymap); | ||
1195 | set_bit(i + 64, sc->sc_keymap); | ||
1196 | set_bit(i + 32 + 64, sc->sc_keymap); | ||
1197 | } | ||
1198 | /* | ||
1199 | * Collect the channel list using the default country | ||
1200 | * code and including outdoor channels. The 802.11 layer | ||
1201 | * is resposible for filtering this list based on settings | ||
1202 | * like the phy mode. | ||
1203 | */ | ||
1204 | rd = ah->ah_currentRD; | ||
1205 | |||
1206 | error = ath_setup_channels(sc); | ||
1207 | if (error) | ||
1208 | goto bad; | ||
1209 | |||
1210 | /* default to STA mode */ | ||
1211 | sc->sc_opmode = ATH9K_M_MONITOR; | ||
1212 | |||
1213 | /* Setup rate tables for all potential media types. */ | ||
1214 | /* 11g encompasses b,g */ | ||
1215 | |||
1216 | ath_rate_setup(sc, WIRELESS_MODE_11a); | ||
1217 | ath_rate_setup(sc, WIRELESS_MODE_11g); | ||
1218 | |||
1219 | /* NB: setup here so ath_rate_update is happy */ | ||
1220 | ath_setcurmode(sc, WIRELESS_MODE_11a); | ||
1221 | |||
1222 | /* | ||
1223 | * Allocate hardware transmit queues: one queue for | ||
1224 | * beacon frames and one data queue for each QoS | ||
1225 | * priority. Note that the hal handles reseting | ||
1226 | * these queues at the needed time. | ||
1227 | */ | ||
1228 | sc->sc_bhalq = ath_beaconq_setup(ah); | ||
1229 | if (sc->sc_bhalq == -1) { | ||
1230 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1231 | "%s: unable to setup a beacon xmit queue\n", __func__); | ||
1232 | error = -EIO; | ||
1233 | goto bad2; | ||
1234 | } | ||
1235 | sc->sc_cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | ||
1236 | if (sc->sc_cabq == NULL) { | ||
1237 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1238 | "%s: unable to setup CAB xmit queue\n", __func__); | ||
1239 | error = -EIO; | ||
1240 | goto bad2; | ||
1241 | } | ||
1242 | |||
1243 | sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME; | ||
1244 | ath_cabq_update(sc); | ||
1245 | |||
1246 | for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++) | ||
1247 | sc->sc_haltype2q[i] = -1; | ||
1248 | |||
1249 | /* Setup data queues */ | ||
1250 | /* NB: ensure BK queue is the lowest priority h/w queue */ | ||
1251 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | ||
1252 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1253 | "%s: unable to setup xmit queue for BK traffic\n", | ||
1254 | __func__); | ||
1255 | error = -EIO; | ||
1256 | goto bad2; | ||
1257 | } | ||
1258 | |||
1259 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | ||
1260 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1261 | "%s: unable to setup xmit queue for BE traffic\n", | ||
1262 | __func__); | ||
1263 | error = -EIO; | ||
1264 | goto bad2; | ||
1265 | } | ||
1266 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | ||
1267 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1268 | "%s: unable to setup xmit queue for VI traffic\n", | ||
1269 | __func__); | ||
1270 | error = -EIO; | ||
1271 | goto bad2; | ||
1272 | } | ||
1273 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | ||
1274 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1275 | "%s: unable to setup xmit queue for VO traffic\n", | ||
1276 | __func__); | ||
1277 | error = -EIO; | ||
1278 | goto bad2; | ||
1279 | } | ||
1280 | |||
1281 | sc->sc_rc = ath_rate_attach(ah); | ||
1282 | if (sc->sc_rc == NULL) { | ||
1283 | error = EIO; | ||
1284 | goto bad2; | ||
1285 | } | ||
1286 | |||
1287 | if (ath9k_hw_getcapability(ah, HAL_CAP_CIPHER, | ||
1288 | ATH9K_CIPHER_TKIP, NULL)) { | ||
1289 | /* | ||
1290 | * Whether we should enable h/w TKIP MIC. | ||
1291 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
1292 | * report WMM capable, so it's always safe to turn on | ||
1293 | * TKIP MIC in this case. | ||
1294 | */ | ||
1295 | ath9k_hw_setcapability(sc->sc_ah, HAL_CAP_TKIP_MIC, 0, 1, NULL); | ||
1296 | } | ||
1297 | |||
1298 | /* | ||
1299 | * Check whether the separate key cache entries | ||
1300 | * are required to handle both tx+rx MIC keys. | ||
1301 | * With split mic keys the number of stations is limited | ||
1302 | * to 27 otherwise 59. | ||
1303 | */ | ||
1304 | if (ath9k_hw_getcapability(ah, HAL_CAP_CIPHER, | ||
1305 | ATH9K_CIPHER_TKIP, NULL) | ||
1306 | && ath9k_hw_getcapability(ah, HAL_CAP_CIPHER, | ||
1307 | ATH9K_CIPHER_MIC, NULL) | ||
1308 | && ath9k_hw_getcapability(ah, HAL_CAP_TKIP_SPLIT, | ||
1309 | 0, NULL)) | ||
1310 | sc->sc_splitmic = 1; | ||
1311 | |||
1312 | /* turn on mcast key search if possible */ | ||
1313 | if (!ath9k_hw_getcapability(ah, HAL_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
1314 | (void)ath9k_hw_setcapability(ah, HAL_CAP_MCAST_KEYSRCH, 1, | ||
1315 | 1, NULL); | ||
1316 | |||
1317 | sc->sc_config.txpowlimit = ATH_TXPOWER_MAX; | ||
1318 | sc->sc_config.txpowlimit_override = 0; | ||
1319 | |||
1320 | /* 11n Capabilities */ | ||
1321 | if (ah->ah_caps.halHTSupport) { | ||
1322 | sc->sc_txaggr = 1; | ||
1323 | sc->sc_rxaggr = 1; | ||
1324 | } | ||
1325 | |||
1326 | sc->sc_tx_chainmask = ah->ah_caps.halTxChainMask; | ||
1327 | sc->sc_rx_chainmask = ah->ah_caps.halRxChainMask; | ||
1328 | |||
1329 | /* Configuration for rx chain detection */ | ||
1330 | sc->sc_rxchaindetect_ref = 0; | ||
1331 | sc->sc_rxchaindetect_thresh5GHz = 35; | ||
1332 | sc->sc_rxchaindetect_thresh2GHz = 35; | ||
1333 | sc->sc_rxchaindetect_delta5GHz = 30; | ||
1334 | sc->sc_rxchaindetect_delta2GHz = 30; | ||
1335 | |||
1336 | ath9k_hw_setcapability(ah, HAL_CAP_DIVERSITY, 1, true, NULL); | ||
1337 | sc->sc_defant = ath9k_hw_getdefantenna(ah); | ||
1338 | |||
1339 | ath9k_hw_getmac(ah, sc->sc_myaddr); | ||
1340 | if (ah->ah_caps.halBssIdMaskSupport) { | ||
1341 | ath9k_hw_getbssidmask(ah, sc->sc_bssidmask); | ||
1342 | ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask); | ||
1343 | ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); | ||
1344 | } | ||
1345 | sc->sc_slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ | ||
1346 | |||
1347 | /* initialize beacon slots */ | ||
1348 | for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++) | ||
1349 | sc->sc_bslot[i] = ATH_IF_ID_ANY; | ||
1350 | |||
1351 | /* save MISC configurations */ | ||
1352 | sc->sc_config.swBeaconProcess = 1; | ||
1353 | |||
1354 | #ifdef CONFIG_SLOW_ANT_DIV | ||
1355 | /* range is 40 - 255, we use something in the middle */ | ||
1356 | ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127); | ||
1357 | #endif | ||
1358 | |||
1359 | return 0; | ||
1360 | bad2: | ||
1361 | /* cleanup tx queues */ | ||
1362 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1363 | if (ATH_TXQ_SETUP(sc, i)) | ||
1364 | ath_tx_cleanupq(sc, &sc->sc_txq[i]); | ||
1365 | bad: | ||
1366 | if (ah) | ||
1367 | ath9k_hw_detach(ah); | ||
1368 | return error; | ||
1369 | } | ||
1370 | |||
1371 | void ath_deinit(struct ath_softc *sc) | ||
1372 | { | ||
1373 | struct ath_hal *ah = sc->sc_ah; | ||
1374 | int i; | ||
1375 | |||
1376 | DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__); | ||
1377 | |||
1378 | ath_stop(sc); | ||
1379 | if (!sc->sc_invalid) | ||
1380 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | ||
1381 | ath_rate_detach(sc->sc_rc); | ||
1382 | /* cleanup tx queues */ | ||
1383 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1384 | if (ATH_TXQ_SETUP(sc, i)) | ||
1385 | ath_tx_cleanupq(sc, &sc->sc_txq[i]); | ||
1386 | ath9k_hw_detach(ah); | ||
1387 | } | ||
1388 | |||
1389 | /*******************/ | ||
1390 | /* Node Management */ | ||
1391 | /*******************/ | ||
1392 | |||
1393 | struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id) | ||
1394 | { | ||
1395 | struct ath_vap *avp; | ||
1396 | struct ath_node *an; | ||
1397 | DECLARE_MAC_BUF(mac); | ||
1398 | |||
1399 | avp = sc->sc_vaps[if_id]; | ||
1400 | ASSERT(avp != NULL); | ||
1401 | |||
1402 | /* mac80211 sta_notify callback is from an IRQ context, so no sleep */ | ||
1403 | an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC); | ||
1404 | if (an == NULL) | ||
1405 | return NULL; | ||
1406 | memzero(an, sizeof(*an)); | ||
1407 | |||
1408 | an->an_sc = sc; | ||
1409 | memcpy(an->an_addr, addr, ETH_ALEN); | ||
1410 | atomic_set(&an->an_refcnt, 1); | ||
1411 | |||
1412 | /* set up per-node tx/rx state */ | ||
1413 | ath_tx_node_init(sc, an); | ||
1414 | ath_rx_node_init(sc, an); | ||
1415 | |||
1416 | ath_chainmask_sel_init(sc, an); | ||
1417 | ath_chainmask_sel_timerstart(&an->an_chainmask_sel); | ||
1418 | list_add(&an->list, &sc->node_list); | ||
1419 | |||
1420 | return an; | ||
1421 | } | ||
1422 | |||
1423 | void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag) | ||
1424 | { | ||
1425 | unsigned long flags; | ||
1426 | |||
1427 | DECLARE_MAC_BUF(mac); | ||
1428 | |||
1429 | ath_chainmask_sel_timerstop(&an->an_chainmask_sel); | ||
1430 | an->an_flags |= ATH_NODE_CLEAN; | ||
1431 | ath_tx_node_cleanup(sc, an, bh_flag); | ||
1432 | ath_rx_node_cleanup(sc, an); | ||
1433 | |||
1434 | ath_tx_node_free(sc, an); | ||
1435 | ath_rx_node_free(sc, an); | ||
1436 | |||
1437 | spin_lock_irqsave(&sc->node_lock, flags); | ||
1438 | |||
1439 | list_del(&an->list); | ||
1440 | |||
1441 | spin_unlock_irqrestore(&sc->node_lock, flags); | ||
1442 | |||
1443 | kfree(an); | ||
1444 | } | ||
1445 | |||
1446 | /* Finds a node and increases the refcnt if found */ | ||
1447 | |||
1448 | struct ath_node *ath_node_get(struct ath_softc *sc, u8 *addr) | ||
1449 | { | ||
1450 | struct ath_node *an = NULL, *an_found = NULL; | ||
1451 | |||
1452 | if (list_empty(&sc->node_list)) /* FIXME */ | ||
1453 | goto out; | ||
1454 | list_for_each_entry(an, &sc->node_list, list) { | ||
1455 | if (!compare_ether_addr(an->an_addr, addr)) { | ||
1456 | atomic_inc(&an->an_refcnt); | ||
1457 | an_found = an; | ||
1458 | break; | ||
1459 | } | ||
1460 | } | ||
1461 | out: | ||
1462 | return an_found; | ||
1463 | } | ||
1464 | |||
1465 | /* Decrements the refcnt and if it drops to zero, detach the node */ | ||
1466 | |||
1467 | void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag) | ||
1468 | { | ||
1469 | if (atomic_dec_and_test(&an->an_refcnt)) | ||
1470 | ath_node_detach(sc, an, bh_flag); | ||
1471 | } | ||
1472 | |||
1473 | /* Finds a node, doesn't increment refcnt. Caller must hold sc->node_lock */ | ||
1474 | struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr) | ||
1475 | { | ||
1476 | struct ath_node *an = NULL, *an_found = NULL; | ||
1477 | |||
1478 | if (list_empty(&sc->node_list)) | ||
1479 | return NULL; | ||
1480 | |||
1481 | list_for_each_entry(an, &sc->node_list, list) | ||
1482 | if (!compare_ether_addr(an->an_addr, addr)) { | ||
1483 | an_found = an; | ||
1484 | break; | ||
1485 | } | ||
1486 | |||
1487 | return an_found; | ||
1488 | } | ||
1489 | |||
1490 | /* | ||
1491 | * Set up New Node | ||
1492 | * | ||
1493 | * Setup driver-specific state for a newly associated node. This routine | ||
1494 | * really only applies if compression or XR are enabled, there is no code | ||
1495 | * covering any other cases. | ||
1496 | */ | ||
1497 | |||
1498 | void ath_newassoc(struct ath_softc *sc, | ||
1499 | struct ath_node *an, int isnew, int isuapsd) | ||
1500 | { | ||
1501 | int tidno; | ||
1502 | |||
1503 | /* if station reassociates, tear down the aggregation state. */ | ||
1504 | if (!isnew) { | ||
1505 | for (tidno = 0; tidno < WME_NUM_TID; tidno++) { | ||
1506 | if (sc->sc_txaggr) | ||
1507 | ath_tx_aggr_teardown(sc, an, tidno); | ||
1508 | if (sc->sc_rxaggr) | ||
1509 | ath_rx_aggr_teardown(sc, an, tidno); | ||
1510 | } | ||
1511 | } | ||
1512 | an->an_flags = 0; | ||
1513 | } | ||
1514 | |||
1515 | /**************/ | ||
1516 | /* Encryption */ | ||
1517 | /**************/ | ||
1518 | |||
1519 | void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot) | ||
1520 | { | ||
1521 | ath9k_hw_keyreset(sc->sc_ah, keyix); | ||
1522 | if (freeslot) | ||
1523 | clear_bit(keyix, sc->sc_keymap); | ||
1524 | } | ||
1525 | |||
1526 | int ath_keyset(struct ath_softc *sc, | ||
1527 | u16 keyix, | ||
1528 | struct ath9k_keyval *hk, | ||
1529 | const u8 mac[ETH_ALEN]) | ||
1530 | { | ||
1531 | bool status; | ||
1532 | |||
1533 | status = ath9k_hw_set_keycache_entry(sc->sc_ah, | ||
1534 | keyix, hk, mac, false); | ||
1535 | |||
1536 | return status != false; | ||
1537 | } | ||
1538 | |||
1539 | /***********************/ | ||
1540 | /* TX Power/Regulatory */ | ||
1541 | /***********************/ | ||
1542 | |||
1543 | /* | ||
1544 | * Set Transmit power in HAL | ||
1545 | * | ||
1546 | * This routine makes the actual HAL calls to set the new transmit power | ||
1547 | * limit. | ||
1548 | */ | ||
1549 | |||
1550 | void ath_update_txpow(struct ath_softc *sc) | ||
1551 | { | ||
1552 | struct ath_hal *ah = sc->sc_ah; | ||
1553 | u32 txpow; | ||
1554 | |||
1555 | if (sc->sc_curtxpow != sc->sc_config.txpowlimit) { | ||
1556 | ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit); | ||
1557 | /* read back in case value is clamped */ | ||
1558 | ath9k_hw_getcapability(ah, HAL_CAP_TXPOW, 1, &txpow); | ||
1559 | sc->sc_curtxpow = txpow; | ||
1560 | } | ||
1561 | } | ||
1562 | |||
1563 | /* Return the current country and domain information */ | ||
1564 | void ath_get_currentCountry(struct ath_softc *sc, | ||
1565 | struct ath9k_country_entry *ctry) | ||
1566 | { | ||
1567 | ath9k_regd_get_current_country(sc->sc_ah, ctry); | ||
1568 | |||
1569 | /* If HAL not specific yet, since it is band dependent, | ||
1570 | * use the one we passed in. */ | ||
1571 | if (ctry->countryCode == CTRY_DEFAULT) { | ||
1572 | ctry->iso[0] = 0; | ||
1573 | ctry->iso[1] = 0; | ||
1574 | } else if (ctry->iso[0] && ctry->iso[1]) { | ||
1575 | if (!ctry->iso[2]) { | ||
1576 | if (ath_outdoor) | ||
1577 | ctry->iso[2] = 'O'; | ||
1578 | else | ||
1579 | ctry->iso[2] = 'I'; | ||
1580 | } | ||
1581 | } | ||
1582 | } | ||
1583 | |||
1584 | /**************************/ | ||
1585 | /* Slow Antenna Diversity */ | ||
1586 | /**************************/ | ||
1587 | |||
1588 | void ath_slow_ant_div_init(struct ath_antdiv *antdiv, | ||
1589 | struct ath_softc *sc, | ||
1590 | int32_t rssitrig) | ||
1591 | { | ||
1592 | int trig; | ||
1593 | |||
1594 | /* antdivf_rssitrig can range from 40 - 0xff */ | ||
1595 | trig = (rssitrig > 0xff) ? 0xff : rssitrig; | ||
1596 | trig = (rssitrig < 40) ? 40 : rssitrig; | ||
1597 | |||
1598 | antdiv->antdiv_sc = sc; | ||
1599 | antdiv->antdivf_rssitrig = trig; | ||
1600 | } | ||
1601 | |||
1602 | void ath_slow_ant_div_start(struct ath_antdiv *antdiv, | ||
1603 | u8 num_antcfg, | ||
1604 | const u8 *bssid) | ||
1605 | { | ||
1606 | antdiv->antdiv_num_antcfg = | ||
1607 | num_antcfg < ATH_ANT_DIV_MAX_CFG ? | ||
1608 | num_antcfg : ATH_ANT_DIV_MAX_CFG; | ||
1609 | antdiv->antdiv_state = ATH_ANT_DIV_IDLE; | ||
1610 | antdiv->antdiv_curcfg = 0; | ||
1611 | antdiv->antdiv_bestcfg = 0; | ||
1612 | antdiv->antdiv_laststatetsf = 0; | ||
1613 | |||
1614 | memcpy(antdiv->antdiv_bssid, bssid, sizeof(antdiv->antdiv_bssid)); | ||
1615 | |||
1616 | antdiv->antdiv_start = 1; | ||
1617 | } | ||
1618 | |||
1619 | void ath_slow_ant_div_stop(struct ath_antdiv *antdiv) | ||
1620 | { | ||
1621 | antdiv->antdiv_start = 0; | ||
1622 | } | ||
1623 | |||
1624 | static int32_t ath_find_max_val(int32_t *val, | ||
1625 | u8 num_val, u8 *max_index) | ||
1626 | { | ||
1627 | u32 MaxVal = *val++; | ||
1628 | u32 cur_index = 0; | ||
1629 | |||
1630 | *max_index = 0; | ||
1631 | while (++cur_index < num_val) { | ||
1632 | if (*val > MaxVal) { | ||
1633 | MaxVal = *val; | ||
1634 | *max_index = cur_index; | ||
1635 | } | ||
1636 | |||
1637 | val++; | ||
1638 | } | ||
1639 | |||
1640 | return MaxVal; | ||
1641 | } | ||
1642 | |||
1643 | void ath_slow_ant_div(struct ath_antdiv *antdiv, | ||
1644 | struct ieee80211_hdr *hdr, | ||
1645 | struct ath_rx_status *rx_stats) | ||
1646 | { | ||
1647 | struct ath_softc *sc = antdiv->antdiv_sc; | ||
1648 | struct ath_hal *ah = sc->sc_ah; | ||
1649 | u64 curtsf = 0; | ||
1650 | u8 bestcfg, curcfg = antdiv->antdiv_curcfg; | ||
1651 | __le16 fc = hdr->frame_control; | ||
1652 | |||
1653 | if (antdiv->antdiv_start && ieee80211_is_beacon(fc) | ||
1654 | && !compare_ether_addr(hdr->addr3, antdiv->antdiv_bssid)) { | ||
1655 | antdiv->antdiv_lastbrssi[curcfg] = rx_stats->rs_rssi; | ||
1656 | antdiv->antdiv_lastbtsf[curcfg] = ath9k_hw_gettsf64(sc->sc_ah); | ||
1657 | curtsf = antdiv->antdiv_lastbtsf[curcfg]; | ||
1658 | } else { | ||
1659 | return; | ||
1660 | } | ||
1661 | |||
1662 | switch (antdiv->antdiv_state) { | ||
1663 | case ATH_ANT_DIV_IDLE: | ||
1664 | if ((antdiv->antdiv_lastbrssi[curcfg] < | ||
1665 | antdiv->antdivf_rssitrig) | ||
1666 | && ((curtsf - antdiv->antdiv_laststatetsf) > | ||
1667 | ATH_ANT_DIV_MIN_IDLE_US)) { | ||
1668 | |||
1669 | curcfg++; | ||
1670 | if (curcfg == antdiv->antdiv_num_antcfg) | ||
1671 | curcfg = 0; | ||
1672 | |||
1673 | if (!ath9k_hw_select_antconfig(ah, curcfg)) { | ||
1674 | antdiv->antdiv_bestcfg = antdiv->antdiv_curcfg; | ||
1675 | antdiv->antdiv_curcfg = curcfg; | ||
1676 | antdiv->antdiv_laststatetsf = curtsf; | ||
1677 | antdiv->antdiv_state = ATH_ANT_DIV_SCAN; | ||
1678 | } | ||
1679 | } | ||
1680 | break; | ||
1681 | |||
1682 | case ATH_ANT_DIV_SCAN: | ||
1683 | if ((curtsf - antdiv->antdiv_laststatetsf) < | ||
1684 | ATH_ANT_DIV_MIN_SCAN_US) | ||
1685 | break; | ||
1686 | |||
1687 | curcfg++; | ||
1688 | if (curcfg == antdiv->antdiv_num_antcfg) | ||
1689 | curcfg = 0; | ||
1690 | |||
1691 | if (curcfg == antdiv->antdiv_bestcfg) { | ||
1692 | ath_find_max_val(antdiv->antdiv_lastbrssi, | ||
1693 | antdiv->antdiv_num_antcfg, &bestcfg); | ||
1694 | if (!ath9k_hw_select_antconfig(ah, bestcfg)) { | ||
1695 | antdiv->antdiv_bestcfg = bestcfg; | ||
1696 | antdiv->antdiv_curcfg = bestcfg; | ||
1697 | antdiv->antdiv_laststatetsf = curtsf; | ||
1698 | antdiv->antdiv_state = ATH_ANT_DIV_IDLE; | ||
1699 | } | ||
1700 | } else { | ||
1701 | if (!ath9k_hw_select_antconfig(ah, curcfg)) { | ||
1702 | antdiv->antdiv_curcfg = curcfg; | ||
1703 | antdiv->antdiv_laststatetsf = curtsf; | ||
1704 | antdiv->antdiv_state = ATH_ANT_DIV_SCAN; | ||
1705 | } | ||
1706 | } | ||
1707 | |||
1708 | break; | ||
1709 | } | ||
1710 | } | ||
1711 | |||
1712 | /***********************/ | ||
1713 | /* Descriptor Handling */ | ||
1714 | /***********************/ | ||
1715 | |||
1716 | /* | ||
1717 | * Set up DMA descriptors | ||
1718 | * | ||
1719 | * This function will allocate both the DMA descriptor structure, and the | ||
1720 | * buffers it contains. These are used to contain the descriptors used | ||
1721 | * by the system. | ||
1722 | */ | ||
1723 | |||
1724 | int ath_descdma_setup(struct ath_softc *sc, | ||
1725 | struct ath_descdma *dd, | ||
1726 | struct list_head *head, | ||
1727 | const char *name, | ||
1728 | int nbuf, | ||
1729 | int ndesc) | ||
1730 | { | ||
1731 | #define DS2PHYS(_dd, _ds) \ | ||
1732 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) | ||
1733 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) | ||
1734 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) | ||
1735 | |||
1736 | struct ath_desc *ds; | ||
1737 | struct ath_buf *bf; | ||
1738 | int i, bsize, error; | ||
1739 | |||
1740 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA: %u buffers %u desc/buf\n", | ||
1741 | __func__, name, nbuf, ndesc); | ||
1742 | |||
1743 | /* ath_desc must be a multiple of DWORDs */ | ||
1744 | if ((sizeof(struct ath_desc) % 4) != 0) { | ||
1745 | DPRINTF(sc, ATH_DBG_FATAL, "%s: ath_desc not DWORD aligned\n", | ||
1746 | __func__); | ||
1747 | ASSERT((sizeof(struct ath_desc) % 4) == 0); | ||
1748 | error = -ENOMEM; | ||
1749 | goto fail; | ||
1750 | } | ||
1751 | |||
1752 | dd->dd_name = name; | ||
1753 | dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; | ||
1754 | |||
1755 | /* | ||
1756 | * Need additional DMA memory because we can't use | ||
1757 | * descriptors that cross the 4K page boundary. Assume | ||
1758 | * one skipped descriptor per 4K page. | ||
1759 | */ | ||
1760 | if (!(sc->sc_ah->ah_caps.hal4kbSplitTransSupport)) { | ||
1761 | u32 ndesc_skipped = | ||
1762 | ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); | ||
1763 | u32 dma_len; | ||
1764 | |||
1765 | while (ndesc_skipped) { | ||
1766 | dma_len = ndesc_skipped * sizeof(struct ath_desc); | ||
1767 | dd->dd_desc_len += dma_len; | ||
1768 | |||
1769 | ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); | ||
1770 | }; | ||
1771 | } | ||
1772 | |||
1773 | /* allocate descriptors */ | ||
1774 | dd->dd_desc = pci_alloc_consistent(sc->pdev, | ||
1775 | dd->dd_desc_len, | ||
1776 | &dd->dd_desc_paddr); | ||
1777 | if (dd->dd_desc == NULL) { | ||
1778 | error = -ENOMEM; | ||
1779 | goto fail; | ||
1780 | } | ||
1781 | ds = dd->dd_desc; | ||
1782 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA map: %p (%u) -> %llx (%u)\n", | ||
1783 | __func__, dd->dd_name, ds, (u32) dd->dd_desc_len, | ||
1784 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | ||
1785 | |||
1786 | /* allocate buffers */ | ||
1787 | bsize = sizeof(struct ath_buf) * nbuf; | ||
1788 | bf = kmalloc(bsize, GFP_KERNEL); | ||
1789 | if (bf == NULL) { | ||
1790 | error = -ENOMEM; | ||
1791 | goto fail2; | ||
1792 | } | ||
1793 | memzero(bf, bsize); | ||
1794 | dd->dd_bufptr = bf; | ||
1795 | |||
1796 | INIT_LIST_HEAD(head); | ||
1797 | for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { | ||
1798 | bf->bf_desc = ds; | ||
1799 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
1800 | |||
1801 | if (!(sc->sc_ah->ah_caps.hal4kbSplitTransSupport)) { | ||
1802 | /* | ||
1803 | * Skip descriptor addresses which can cause 4KB | ||
1804 | * boundary crossing (addr + length) with a 32 dword | ||
1805 | * descriptor fetch. | ||
1806 | */ | ||
1807 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | ||
1808 | ASSERT((caddr_t) bf->bf_desc < | ||
1809 | ((caddr_t) dd->dd_desc + | ||
1810 | dd->dd_desc_len)); | ||
1811 | |||
1812 | ds += ndesc; | ||
1813 | bf->bf_desc = ds; | ||
1814 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
1815 | } | ||
1816 | } | ||
1817 | list_add_tail(&bf->list, head); | ||
1818 | } | ||
1819 | return 0; | ||
1820 | fail2: | ||
1821 | pci_free_consistent(sc->pdev, | ||
1822 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); | ||
1823 | fail: | ||
1824 | memzero(dd, sizeof(*dd)); | ||
1825 | return error; | ||
1826 | #undef ATH_DESC_4KB_BOUND_CHECK | ||
1827 | #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED | ||
1828 | #undef DS2PHYS | ||
1829 | } | ||
1830 | |||
1831 | /* | ||
1832 | * Cleanup DMA descriptors | ||
1833 | * | ||
1834 | * This function will free the DMA block that was allocated for the descriptor | ||
1835 | * pool. Since this was allocated as one "chunk", it is freed in the same | ||
1836 | * manner. | ||
1837 | */ | ||
1838 | |||
1839 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
1840 | struct ath_descdma *dd, | ||
1841 | struct list_head *head) | ||
1842 | { | ||
1843 | /* Free memory associated with descriptors */ | ||
1844 | pci_free_consistent(sc->pdev, | ||
1845 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); | ||
1846 | |||
1847 | INIT_LIST_HEAD(head); | ||
1848 | kfree(dd->dd_bufptr); | ||
1849 | memzero(dd, sizeof(*dd)); | ||
1850 | } | ||
1851 | |||
1852 | /*************/ | ||
1853 | /* Utilities */ | ||
1854 | /*************/ | ||
1855 | |||
1856 | void ath_internal_reset(struct ath_softc *sc) | ||
1857 | { | ||
1858 | ath_reset_start(sc, 0); | ||
1859 | ath_reset(sc); | ||
1860 | ath_reset_end(sc, 0); | ||
1861 | } | ||
1862 | |||
1863 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) | ||
1864 | { | ||
1865 | int qnum; | ||
1866 | |||
1867 | switch (queue) { | ||
1868 | case 0: | ||
1869 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO]; | ||
1870 | break; | ||
1871 | case 1: | ||
1872 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI]; | ||
1873 | break; | ||
1874 | case 2: | ||
1875 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; | ||
1876 | break; | ||
1877 | case 3: | ||
1878 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK]; | ||
1879 | break; | ||
1880 | default: | ||
1881 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; | ||
1882 | break; | ||
1883 | } | ||
1884 | |||
1885 | return qnum; | ||
1886 | } | ||
1887 | |||
1888 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) | ||
1889 | { | ||
1890 | int qnum; | ||
1891 | |||
1892 | switch (queue) { | ||
1893 | case ATH9K_WME_AC_VO: | ||
1894 | qnum = 0; | ||
1895 | break; | ||
1896 | case ATH9K_WME_AC_VI: | ||
1897 | qnum = 1; | ||
1898 | break; | ||
1899 | case ATH9K_WME_AC_BE: | ||
1900 | qnum = 2; | ||
1901 | break; | ||
1902 | case ATH9K_WME_AC_BK: | ||
1903 | qnum = 3; | ||
1904 | break; | ||
1905 | default: | ||
1906 | qnum = -1; | ||
1907 | break; | ||
1908 | } | ||
1909 | |||
1910 | return qnum; | ||
1911 | } | ||
1912 | |||
1913 | |||
1914 | /* | ||
1915 | * Expand time stamp to TSF | ||
1916 | * | ||
1917 | * Extend 15-bit time stamp from rx descriptor to | ||
1918 | * a full 64-bit TSF using the current h/w TSF. | ||
1919 | */ | ||
1920 | |||
1921 | u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) | ||
1922 | { | ||
1923 | u64 tsf; | ||
1924 | |||
1925 | tsf = ath9k_hw_gettsf64(sc->sc_ah); | ||
1926 | if ((tsf & 0x7fff) < rstamp) | ||
1927 | tsf -= 0x8000; | ||
1928 | return (tsf & ~0x7fff) | rstamp; | ||
1929 | } | ||
1930 | |||
1931 | /* | ||
1932 | * Set Default Antenna | ||
1933 | * | ||
1934 | * Call into the HAL to set the default antenna to use. Not really valid for | ||
1935 | * MIMO technology. | ||
1936 | */ | ||
1937 | |||
1938 | void ath_setdefantenna(void *context, u32 antenna) | ||
1939 | { | ||
1940 | struct ath_softc *sc = (struct ath_softc *)context; | ||
1941 | struct ath_hal *ah = sc->sc_ah; | ||
1942 | |||
1943 | /* XXX block beacon interrupts */ | ||
1944 | ath9k_hw_setantenna(ah, antenna); | ||
1945 | sc->sc_defant = antenna; | ||
1946 | sc->sc_rxotherant = 0; | ||
1947 | } | ||
1948 | |||
1949 | /* | ||
1950 | * Set Slot Time | ||
1951 | * | ||
1952 | * This will wake up the chip if required, and set the slot time for the | ||
1953 | * frame (maximum transmit time). Slot time is assumed to be already set | ||
1954 | * in the ATH object member sc_slottime | ||
1955 | */ | ||
1956 | |||
1957 | void ath_setslottime(struct ath_softc *sc) | ||
1958 | { | ||
1959 | ath9k_hw_setslottime(sc->sc_ah, sc->sc_slottime); | ||
1960 | sc->sc_updateslot = OK; | ||
1961 | } | ||
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h new file mode 100644 index 00000000000..cf76b36d175 --- /dev/null +++ b/drivers/net/wireless/ath9k/core.h | |||
@@ -0,0 +1,1097 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef CORE_H | ||
18 | #define CORE_H | ||
19 | |||
20 | #include <linux/version.h> | ||
21 | #include <linux/autoconf.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/skbuff.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/etherdevice.h> | ||
29 | #include <linux/ip.h> | ||
30 | #include <linux/tcp.h> | ||
31 | #include <linux/in.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/sched.h> | ||
37 | #include <linux/list.h> | ||
38 | #include <asm/byteorder.h> | ||
39 | #include <linux/scatterlist.h> | ||
40 | #include <asm/page.h> | ||
41 | #include <net/mac80211.h> | ||
42 | |||
43 | #include "ath9k.h" | ||
44 | #include "rc.h" | ||
45 | |||
46 | struct ath_node; | ||
47 | |||
48 | /******************/ | ||
49 | /* Utility macros */ | ||
50 | /******************/ | ||
51 | |||
52 | /* Macro to expand scalars to 64-bit objects */ | ||
53 | |||
54 | #define ito64(x) (sizeof(x) == 8) ? \ | ||
55 | (((unsigned long long int)(x)) & (0xff)) : \ | ||
56 | (sizeof(x) == 16) ? \ | ||
57 | (((unsigned long long int)(x)) & 0xffff) : \ | ||
58 | ((sizeof(x) == 32) ? \ | ||
59 | (((unsigned long long int)(x)) & 0xffffffff) : \ | ||
60 | (unsigned long long int)(x)) | ||
61 | |||
62 | /* increment with wrap-around */ | ||
63 | #define INCR(_l, _sz) do { \ | ||
64 | (_l)++; \ | ||
65 | (_l) &= ((_sz) - 1); \ | ||
66 | } while (0) | ||
67 | |||
68 | /* decrement with wrap-around */ | ||
69 | #define DECR(_l, _sz) do { \ | ||
70 | (_l)--; \ | ||
71 | (_l) &= ((_sz) - 1); \ | ||
72 | } while (0) | ||
73 | |||
74 | #define A_MAX(a, b) ((a) > (b) ? (a) : (b)) | ||
75 | |||
76 | #define ASSERT(exp) do { \ | ||
77 | if (unlikely(!(exp))) { \ | ||
78 | BUG(); \ | ||
79 | } \ | ||
80 | } while (0) | ||
81 | |||
82 | /* XXX: remove */ | ||
83 | #define memzero(_buf, _len) memset(_buf, 0, _len) | ||
84 | |||
85 | #define get_dma_mem_context(var, field) (&((var)->field)) | ||
86 | #define copy_dma_mem_context(dst, src) (*dst = *src) | ||
87 | |||
88 | #define ATH9K_BH_STATUS_INTACT 0 | ||
89 | #define ATH9K_BH_STATUS_CHANGE 1 | ||
90 | |||
91 | #define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i)) | ||
92 | |||
93 | static inline unsigned long get_timestamp(void) | ||
94 | { | ||
95 | return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ); | ||
96 | } | ||
97 | |||
98 | /*************/ | ||
99 | /* Debugging */ | ||
100 | /*************/ | ||
101 | |||
102 | enum ATH_DEBUG { | ||
103 | ATH_DBG_RESET = 0x00000001, | ||
104 | ATH_DBG_PHY_IO = 0x00000002, | ||
105 | ATH_DBG_REG_IO = 0x00000004, | ||
106 | ATH_DBG_QUEUE = 0x00000008, | ||
107 | ATH_DBG_EEPROM = 0x00000010, | ||
108 | ATH_DBG_NF_CAL = 0x00000020, | ||
109 | ATH_DBG_CALIBRATE = 0x00000040, | ||
110 | ATH_DBG_CHANNEL = 0x00000080, | ||
111 | ATH_DBG_INTERRUPT = 0x00000100, | ||
112 | ATH_DBG_REGULATORY = 0x00000200, | ||
113 | ATH_DBG_ANI = 0x00000400, | ||
114 | ATH_DBG_POWER_MGMT = 0x00000800, | ||
115 | ATH_DBG_XMIT = 0x00001000, | ||
116 | ATH_DBG_BEACON = 0x00002000, | ||
117 | ATH_DBG_RATE = 0x00004000, | ||
118 | ATH_DBG_CONFIG = 0x00008000, | ||
119 | ATH_DBG_KEYCACHE = 0x00010000, | ||
120 | ATH_DBG_AGGR = 0x00020000, | ||
121 | ATH_DBG_FATAL = 0x00040000, | ||
122 | ATH_DBG_ANY = 0xffffffff | ||
123 | }; | ||
124 | |||
125 | #define DBG_DEFAULT (ATH_DBG_FATAL) | ||
126 | |||
127 | #define DPRINTF(sc, _m, _fmt, ...) do { \ | ||
128 | if (sc->sc_debug & (_m)) \ | ||
129 | printk(_fmt , ##__VA_ARGS__); \ | ||
130 | } while (0) | ||
131 | |||
132 | /***************************/ | ||
133 | /* Load-time Configuration */ | ||
134 | /***************************/ | ||
135 | |||
136 | /* Per-instance load-time (note: NOT run-time) configurations | ||
137 | * for Atheros Device */ | ||
138 | struct ath_config { | ||
139 | u32 ath_aggr_prot; | ||
140 | u16 txpowlimit; | ||
141 | u16 txpowlimit_override; | ||
142 | u8 cabqReadytime; /* Cabq Readytime % */ | ||
143 | u8 swBeaconProcess; /* Process received beacons | ||
144 | in SW (vs HW) */ | ||
145 | }; | ||
146 | |||
147 | /***********************/ | ||
148 | /* Chainmask Selection */ | ||
149 | /***********************/ | ||
150 | |||
151 | #define ATH_CHAINMASK_SEL_TIMEOUT 6000 | ||
152 | /* Default - Number of last RSSI values that is used for | ||
153 | * chainmask selection */ | ||
154 | #define ATH_CHAINMASK_SEL_RSSI_CNT 10 | ||
155 | /* Means use 3x3 chainmask instead of configured chainmask */ | ||
156 | #define ATH_CHAINMASK_SEL_3X3 7 | ||
157 | /* Default - Rssi threshold below which we have to switch to 3x3 */ | ||
158 | #define ATH_CHAINMASK_SEL_UP_RSSI_THRES 20 | ||
159 | /* Default - Rssi threshold above which we have to switch to | ||
160 | * user configured values */ | ||
161 | #define ATH_CHAINMASK_SEL_DOWN_RSSI_THRES 35 | ||
162 | /* Struct to store the chainmask select related info */ | ||
163 | struct ath_chainmask_sel { | ||
164 | struct timer_list timer; | ||
165 | int cur_tx_mask; /* user configured or 3x3 */ | ||
166 | int cur_rx_mask; /* user configured or 3x3 */ | ||
167 | int tx_avgrssi; | ||
168 | u8 switch_allowed:1, /* timer will set this */ | ||
169 | cm_sel_enabled:1; | ||
170 | }; | ||
171 | |||
172 | int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an); | ||
173 | void ath_update_chainmask(struct ath_softc *sc, int is_ht); | ||
174 | |||
175 | /*************************/ | ||
176 | /* Descriptor Management */ | ||
177 | /*************************/ | ||
178 | |||
179 | /* Number of descriptors per buffer. The only case where we see skbuff | ||
180 | chains is due to FF aggregation in the driver. */ | ||
181 | #define ATH_TXDESC 1 | ||
182 | /* if there's more fragment for this MSDU */ | ||
183 | #define ATH_BF_MORE_MPDU 1 | ||
184 | #define ATH_TXBUF_RESET(_bf) do { \ | ||
185 | (_bf)->bf_status = 0; \ | ||
186 | (_bf)->bf_lastbf = NULL; \ | ||
187 | (_bf)->bf_lastfrm = NULL; \ | ||
188 | (_bf)->bf_next = NULL; \ | ||
189 | memzero(&((_bf)->bf_state), \ | ||
190 | sizeof(struct ath_buf_state)); \ | ||
191 | } while (0) | ||
192 | |||
193 | struct ath_buf_state { | ||
194 | int bfs_nframes; /* # frames in aggregate */ | ||
195 | u16 bfs_al; /* length of aggregate */ | ||
196 | u16 bfs_frmlen; /* length of frame */ | ||
197 | int bfs_seqno; /* sequence number */ | ||
198 | int bfs_tidno; /* tid of this frame */ | ||
199 | int bfs_retries; /* current retries */ | ||
200 | struct ath_rc_series bfs_rcs[4]; /* rate series */ | ||
201 | u8 bfs_isdata:1; /* is a data frame/aggregate */ | ||
202 | u8 bfs_isaggr:1; /* is an aggregate */ | ||
203 | u8 bfs_isampdu:1; /* is an a-mpdu, aggregate or not */ | ||
204 | u8 bfs_ht:1; /* is an HT frame */ | ||
205 | u8 bfs_isretried:1; /* is retried */ | ||
206 | u8 bfs_isxretried:1; /* is excessive retried */ | ||
207 | u8 bfs_shpreamble:1; /* is short preamble */ | ||
208 | u8 bfs_isbar:1; /* is a BAR */ | ||
209 | u8 bfs_ispspoll:1; /* is a PS-Poll */ | ||
210 | u8 bfs_aggrburst:1; /* is a aggr burst */ | ||
211 | u8 bfs_calcairtime:1; /* requests airtime be calculated | ||
212 | when set for tx frame */ | ||
213 | int bfs_rifsburst_elem; /* RIFS burst/bar */ | ||
214 | int bfs_nrifsubframes; /* # of elements in burst */ | ||
215 | /* key type use to encrypt this frame */ | ||
216 | enum ath9k_key_type bfs_keytype; | ||
217 | }; | ||
218 | |||
219 | #define bf_nframes bf_state.bfs_nframes | ||
220 | #define bf_al bf_state.bfs_al | ||
221 | #define bf_frmlen bf_state.bfs_frmlen | ||
222 | #define bf_retries bf_state.bfs_retries | ||
223 | #define bf_seqno bf_state.bfs_seqno | ||
224 | #define bf_tidno bf_state.bfs_tidno | ||
225 | #define bf_rcs bf_state.bfs_rcs | ||
226 | #define bf_isdata bf_state.bfs_isdata | ||
227 | #define bf_isaggr bf_state.bfs_isaggr | ||
228 | #define bf_isampdu bf_state.bfs_isampdu | ||
229 | #define bf_ht bf_state.bfs_ht | ||
230 | #define bf_isretried bf_state.bfs_isretried | ||
231 | #define bf_isxretried bf_state.bfs_isxretried | ||
232 | #define bf_shpreamble bf_state.bfs_shpreamble | ||
233 | #define bf_rifsburst_elem bf_state.bfs_rifsburst_elem | ||
234 | #define bf_nrifsubframes bf_state.bfs_nrifsubframes | ||
235 | #define bf_keytype bf_state.bfs_keytype | ||
236 | #define bf_isbar bf_state.bfs_isbar | ||
237 | #define bf_ispspoll bf_state.bfs_ispspoll | ||
238 | #define bf_aggrburst bf_state.bfs_aggrburst | ||
239 | #define bf_calcairtime bf_state.bfs_calcairtime | ||
240 | |||
241 | /* | ||
242 | * Abstraction of a contiguous buffer to transmit/receive. There is only | ||
243 | * a single hw descriptor encapsulated here. | ||
244 | */ | ||
245 | |||
246 | struct ath_buf { | ||
247 | struct list_head list; | ||
248 | struct list_head *last; | ||
249 | struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or | ||
250 | an aggregate) */ | ||
251 | struct ath_buf *bf_lastfrm; /* last buf of this frame */ | ||
252 | struct ath_buf *bf_next; /* next subframe in the aggregate */ | ||
253 | struct ath_buf *bf_rifslast; /* last buf for RIFS burst */ | ||
254 | void *bf_mpdu; /* enclosing frame structure */ | ||
255 | void *bf_node; /* pointer to the node */ | ||
256 | struct ath_desc *bf_desc; /* virtual addr of desc */ | ||
257 | dma_addr_t bf_daddr; /* physical addr of desc */ | ||
258 | dma_addr_t bf_buf_addr; /* physical addr of data buffer */ | ||
259 | u32 bf_status; | ||
260 | u16 bf_flags; /* tx descriptor flags */ | ||
261 | struct ath_buf_state bf_state; /* buffer state */ | ||
262 | dma_addr_t bf_dmacontext; | ||
263 | }; | ||
264 | |||
265 | /* | ||
266 | * reset the rx buffer. | ||
267 | * any new fields added to the athbuf and require | ||
268 | * reset need to be added to this macro. | ||
269 | * currently bf_status is the only one requires that | ||
270 | * requires reset. | ||
271 | */ | ||
272 | #define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0) | ||
273 | |||
274 | /* hw processing complete, desc processed by hal */ | ||
275 | #define ATH_BUFSTATUS_DONE 0x00000001 | ||
276 | /* hw processing complete, desc hold for hw */ | ||
277 | #define ATH_BUFSTATUS_STALE 0x00000002 | ||
278 | /* Rx-only: OS is done with this packet and it's ok to queued it to hw */ | ||
279 | #define ATH_BUFSTATUS_FREE 0x00000004 | ||
280 | |||
281 | /* DMA state for tx/rx descriptors */ | ||
282 | |||
283 | struct ath_descdma { | ||
284 | const char *dd_name; | ||
285 | struct ath_desc *dd_desc; /* descriptors */ | ||
286 | dma_addr_t dd_desc_paddr; /* physical addr of dd_desc */ | ||
287 | u32 dd_desc_len; /* size of dd_desc */ | ||
288 | struct ath_buf *dd_bufptr; /* associated buffers */ | ||
289 | dma_addr_t dd_dmacontext; | ||
290 | }; | ||
291 | |||
292 | /* Abstraction of a received RX MPDU/MMPDU, or a RX fragment */ | ||
293 | |||
294 | struct ath_rx_context { | ||
295 | struct ath_buf *ctx_rxbuf; /* associated ath_buf for rx */ | ||
296 | }; | ||
297 | #define ATH_RX_CONTEXT(skb) ((struct ath_rx_context *)skb->cb) | ||
298 | |||
299 | int ath_descdma_setup(struct ath_softc *sc, | ||
300 | struct ath_descdma *dd, | ||
301 | struct list_head *head, | ||
302 | const char *name, | ||
303 | int nbuf, | ||
304 | int ndesc); | ||
305 | int ath_desc_alloc(struct ath_softc *sc); | ||
306 | void ath_desc_free(struct ath_softc *sc); | ||
307 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
308 | struct ath_descdma *dd, | ||
309 | struct list_head *head); | ||
310 | |||
311 | /******/ | ||
312 | /* RX */ | ||
313 | /******/ | ||
314 | |||
315 | #define ATH_MAX_ANTENNA 3 | ||
316 | #define ATH_RXBUF 512 | ||
317 | #define ATH_RX_TIMEOUT 40 /* 40 milliseconds */ | ||
318 | #define WME_NUM_TID 16 | ||
319 | #define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */ | ||
320 | #define IEEE80211_BAR_CTL_TID_S 2 /* tid shift */ | ||
321 | |||
322 | enum ATH_RX_TYPE { | ||
323 | ATH_RX_NON_CONSUMED = 0, | ||
324 | ATH_RX_CONSUMED | ||
325 | }; | ||
326 | |||
327 | /* per frame rx status block */ | ||
328 | struct ath_recv_status { | ||
329 | u64 tsf; /* mac tsf */ | ||
330 | int8_t rssi; /* RSSI (noise floor ajusted) */ | ||
331 | int8_t rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
332 | int8_t rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
333 | int8_t abs_rssi; /* absolute RSSI */ | ||
334 | u8 rateieee; /* data rate received (IEEE rate code) */ | ||
335 | u8 ratecode; /* phy rate code */ | ||
336 | int rateKbps; /* data rate received (Kbps) */ | ||
337 | int antenna; /* rx antenna */ | ||
338 | int flags; /* status of associated skb */ | ||
339 | #define ATH_RX_FCS_ERROR 0x01 | ||
340 | #define ATH_RX_MIC_ERROR 0x02 | ||
341 | #define ATH_RX_DECRYPT_ERROR 0x04 | ||
342 | #define ATH_RX_RSSI_VALID 0x08 | ||
343 | /* if any of ctl,extn chainrssis are valid */ | ||
344 | #define ATH_RX_CHAIN_RSSI_VALID 0x10 | ||
345 | /* if extn chain rssis are valid */ | ||
346 | #define ATH_RX_RSSI_EXTN_VALID 0x20 | ||
347 | /* set if 40Mhz, clear if 20Mhz */ | ||
348 | #define ATH_RX_40MHZ 0x40 | ||
349 | /* set if short GI, clear if full GI */ | ||
350 | #define ATH_RX_SHORT_GI 0x80 | ||
351 | }; | ||
352 | |||
353 | struct ath_rxbuf { | ||
354 | struct sk_buff *rx_wbuf; /* buffer */ | ||
355 | unsigned long rx_time; /* system time when received */ | ||
356 | struct ath_recv_status rx_status; /* cached rx status */ | ||
357 | }; | ||
358 | |||
359 | /* Per-TID aggregate receiver state for a node */ | ||
360 | struct ath_arx_tid { | ||
361 | struct ath_node *an; /* parent ath node */ | ||
362 | struct ath_rxbuf *rxbuf; /* re-ordering buffer */ | ||
363 | struct timer_list timer; | ||
364 | spinlock_t tidlock; /* lock to protect this TID structure */ | ||
365 | int baw_head; /* seq_next at head */ | ||
366 | int baw_tail; /* tail of block-ack window */ | ||
367 | int seq_reset; /* need to reset start sequence */ | ||
368 | int addba_exchangecomplete; | ||
369 | u16 seq_next; /* next expected sequence */ | ||
370 | u16 baw_size; /* block-ack window size */ | ||
371 | }; | ||
372 | |||
373 | /* Per-node receiver aggregate state */ | ||
374 | struct ath_arx { | ||
375 | struct ath_arx_tid tid[WME_NUM_TID]; | ||
376 | }; | ||
377 | |||
378 | int ath_startrecv(struct ath_softc *sc); | ||
379 | bool ath_stoprecv(struct ath_softc *sc); | ||
380 | void ath_flushrecv(struct ath_softc *sc); | ||
381 | u32 ath_calcrxfilter(struct ath_softc *sc); | ||
382 | void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an); | ||
383 | void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an); | ||
384 | void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an); | ||
385 | void ath_handle_rx_intr(struct ath_softc *sc); | ||
386 | int ath_rx_init(struct ath_softc *sc, int nbufs); | ||
387 | void ath_rx_cleanup(struct ath_softc *sc); | ||
388 | int ath_rx_tasklet(struct ath_softc *sc, int flush); | ||
389 | int ath_rx_input(struct ath_softc *sc, | ||
390 | struct ath_node *node, | ||
391 | int is_ampdu, | ||
392 | struct sk_buff *skb, | ||
393 | struct ath_recv_status *rx_status, | ||
394 | enum ATH_RX_TYPE *status); | ||
395 | int ath__rx_indicate(struct ath_softc *sc, | ||
396 | struct sk_buff *skb, | ||
397 | struct ath_recv_status *status, | ||
398 | u16 keyix); | ||
399 | int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb, | ||
400 | struct ath_recv_status *status); | ||
401 | |||
402 | /******/ | ||
403 | /* TX */ | ||
404 | /******/ | ||
405 | |||
406 | #define ATH_FRAG_PER_MSDU 1 | ||
407 | #define ATH_TXBUF (512/ATH_FRAG_PER_MSDU) | ||
408 | /* max number of transmit attempts (tries) */ | ||
409 | #define ATH_TXMAXTRY 13 | ||
410 | /* max number of 11n transmit attempts (tries) */ | ||
411 | #define ATH_11N_TXMAXTRY 10 | ||
412 | /* max number of tries for management and control frames */ | ||
413 | #define ATH_MGT_TXMAXTRY 4 | ||
414 | #define WME_BA_BMP_SIZE 64 | ||
415 | #define WME_MAX_BA WME_BA_BMP_SIZE | ||
416 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) | ||
417 | #define TID_TO_WME_AC(_tid) \ | ||
418 | ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ | ||
419 | (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ | ||
420 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ | ||
421 | WME_AC_VO) | ||
422 | |||
423 | |||
424 | /* Wireless Multimedia Extension Defines */ | ||
425 | #define WME_AC_BE 0 /* best effort */ | ||
426 | #define WME_AC_BK 1 /* background */ | ||
427 | #define WME_AC_VI 2 /* video */ | ||
428 | #define WME_AC_VO 3 /* voice */ | ||
429 | #define WME_NUM_AC 4 | ||
430 | |||
431 | enum ATH_SM_PWRSAV{ | ||
432 | ATH_SM_ENABLE, | ||
433 | ATH_SM_PWRSAV_STATIC, | ||
434 | ATH_SM_PWRSAV_DYNAMIC, | ||
435 | }; | ||
436 | |||
437 | /* | ||
438 | * Data transmit queue state. One of these exists for each | ||
439 | * hardware transmit queue. Packets sent to us from above | ||
440 | * are assigned to queues based on their priority. Not all | ||
441 | * devices support a complete set of hardware transmit queues. | ||
442 | * For those devices the array sc_ac2q will map multiple | ||
443 | * priorities to fewer hardware queues (typically all to one | ||
444 | * hardware queue). | ||
445 | */ | ||
446 | struct ath_txq { | ||
447 | u32 axq_qnum; /* hardware q number */ | ||
448 | u32 *axq_link; /* link ptr in last TX desc */ | ||
449 | struct list_head axq_q; /* transmit queue */ | ||
450 | spinlock_t axq_lock; /* lock on q and link */ | ||
451 | unsigned long axq_lockflags; /* intr state when must cli */ | ||
452 | u32 axq_depth; /* queue depth */ | ||
453 | u8 axq_aggr_depth; /* aggregates queued */ | ||
454 | u32 axq_totalqueued;/* total ever queued */ | ||
455 | u32 axq_intrcnt; /* count to determine | ||
456 | if descriptor should generate | ||
457 | int on this txq. */ | ||
458 | bool stopped; /* Is mac80211 queue | ||
459 | stopped ? */ | ||
460 | /* State for patching up CTS when bursting */ | ||
461 | struct ath_buf *axq_linkbuf; /* virtual addr of last buffer*/ | ||
462 | struct ath_desc *axq_lastdsWithCTS; /* first desc of the | ||
463 | last descriptor that contains CTS */ | ||
464 | struct ath_desc *axq_gatingds; /* final desc of the gating desc | ||
465 | * that determines whether lastdsWithCTS has | ||
466 | * been DMA'ed or not */ | ||
467 | struct list_head axq_acq; | ||
468 | }; | ||
469 | |||
470 | /* per TID aggregate tx state for a destination */ | ||
471 | struct ath_atx_tid { | ||
472 | struct list_head list; /* round-robin tid entry */ | ||
473 | struct list_head buf_q; /* pending buffers */ | ||
474 | struct ath_node *an; /* parent node structure */ | ||
475 | struct ath_atx_ac *ac; /* parent access category */ | ||
476 | struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];/* active tx frames */ | ||
477 | u16 seq_start; /* starting seq of BA window */ | ||
478 | u16 seq_next; /* next seq to be used */ | ||
479 | u16 baw_size; /* BA window size */ | ||
480 | int tidno; /* TID number */ | ||
481 | int baw_head; /* first un-acked tx buffer */ | ||
482 | int baw_tail; /* next unused tx buffer slot */ | ||
483 | int sched; /* TID is scheduled */ | ||
484 | int paused; /* TID is paused */ | ||
485 | int cleanup_inprogress; /* aggr of this TID is | ||
486 | being teared down */ | ||
487 | u32 addba_exchangecomplete:1; /* ADDBA state */ | ||
488 | int32_t addba_exchangeinprogress; | ||
489 | int addba_exchangeattempts; | ||
490 | }; | ||
491 | |||
492 | /* per access-category aggregate tx state for a destination */ | ||
493 | struct ath_atx_ac { | ||
494 | int sched; /* dest-ac is scheduled */ | ||
495 | int qnum; /* H/W queue number associated | ||
496 | with this AC */ | ||
497 | struct list_head list; /* round-robin txq entry */ | ||
498 | struct list_head tid_q; /* queue of TIDs with buffers */ | ||
499 | }; | ||
500 | |||
501 | /* per dest tx state */ | ||
502 | struct ath_atx { | ||
503 | struct ath_atx_tid tid[WME_NUM_TID]; | ||
504 | struct ath_atx_ac ac[WME_NUM_AC]; | ||
505 | }; | ||
506 | |||
507 | /* per-frame tx control block */ | ||
508 | struct ath_tx_control { | ||
509 | struct ath_node *an; /* destination to sent to */ | ||
510 | int if_id; /* only valid for cab traffic */ | ||
511 | int qnum; /* h/w queue number */ | ||
512 | u32 ht:1; /* if it can be transmitted using HT */ | ||
513 | u32 ps:1; /* if one or more stations are in PS mode */ | ||
514 | u32 use_minrate:1; /* if this frame should transmitted using | ||
515 | minimum rate */ | ||
516 | enum ath9k_pkt_type atype; /* Atheros packet type */ | ||
517 | enum ath9k_key_type keytype; /* key type */ | ||
518 | u32 flags; /* HAL flags */ | ||
519 | u16 seqno; /* sequence number */ | ||
520 | u16 tidno; /* tid number */ | ||
521 | u16 txpower; /* transmit power */ | ||
522 | u16 frmlen; /* frame length */ | ||
523 | u32 keyix; /* key index */ | ||
524 | int min_rate; /* minimum rate */ | ||
525 | int mcast_rate; /* multicast rate */ | ||
526 | u16 nextfraglen; /* next fragment length */ | ||
527 | /* below is set only by ath_dev */ | ||
528 | struct ath_softc *dev; /* device handle */ | ||
529 | dma_addr_t dmacontext; | ||
530 | }; | ||
531 | |||
532 | /* per frame tx status block */ | ||
533 | struct ath_xmit_status { | ||
534 | int retries; /* number of retries to successufully | ||
535 | transmit this frame */ | ||
536 | int flags; /* status of transmit */ | ||
537 | #define ATH_TX_ERROR 0x01 | ||
538 | #define ATH_TX_XRETRY 0x02 | ||
539 | #define ATH_TX_BAR 0x04 | ||
540 | }; | ||
541 | |||
542 | struct ath_tx_stat { | ||
543 | int rssi; /* RSSI (noise floor ajusted) */ | ||
544 | int rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
545 | int rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
546 | int rateieee; /* data rate xmitted (IEEE rate code) */ | ||
547 | int rateKbps; /* data rate xmitted (Kbps) */ | ||
548 | int ratecode; /* phy rate code */ | ||
549 | int flags; /* validity flags */ | ||
550 | /* if any of ctl,extn chain rssis are valid */ | ||
551 | #define ATH_TX_CHAIN_RSSI_VALID 0x01 | ||
552 | /* if extn chain rssis are valid */ | ||
553 | #define ATH_TX_RSSI_EXTN_VALID 0x02 | ||
554 | u32 airtime; /* time on air per final tx rate */ | ||
555 | }; | ||
556 | |||
557 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); | ||
558 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); | ||
559 | int ath_tx_setup(struct ath_softc *sc, int haltype); | ||
560 | void ath_draintxq(struct ath_softc *sc, bool retry_tx); | ||
561 | void ath_tx_draintxq(struct ath_softc *sc, | ||
562 | struct ath_txq *txq, bool retry_tx); | ||
563 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); | ||
564 | void ath_tx_node_cleanup(struct ath_softc *sc, | ||
565 | struct ath_node *an, bool bh_flag); | ||
566 | void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an); | ||
567 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); | ||
568 | int ath_tx_init(struct ath_softc *sc, int nbufs); | ||
569 | int ath_tx_cleanup(struct ath_softc *sc); | ||
570 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); | ||
571 | int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_txq_info *q); | ||
572 | int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb); | ||
573 | void ath_tx_tasklet(struct ath_softc *sc); | ||
574 | u32 ath_txq_depth(struct ath_softc *sc, int qnum); | ||
575 | u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum); | ||
576 | void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth); | ||
577 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | ||
578 | struct ath_xmit_status *tx_status, struct ath_node *an); | ||
579 | |||
580 | /**********************/ | ||
581 | /* Node / Aggregation */ | ||
582 | /**********************/ | ||
583 | |||
584 | /* indicates the node is clened up */ | ||
585 | #define ATH_NODE_CLEAN 0x1 | ||
586 | /* indicates the node is 80211 power save */ | ||
587 | #define ATH_NODE_PWRSAVE 0x2 | ||
588 | |||
589 | #define ADDBA_TIMEOUT 200 /* 200 milliseconds */ | ||
590 | #define ADDBA_EXCHANGE_ATTEMPTS 10 | ||
591 | #define ATH_AGGR_DELIM_SZ 4 /* delimiter size */ | ||
592 | #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ | ||
593 | /* number of delimiters for encryption padding */ | ||
594 | #define ATH_AGGR_ENCRYPTDELIM 10 | ||
595 | /* minimum h/w qdepth to be sustained to maximize aggregation */ | ||
596 | #define ATH_AGGR_MIN_QDEPTH 2 | ||
597 | #define ATH_AMPDU_SUBFRAME_DEFAULT 32 | ||
598 | #define IEEE80211_SEQ_SEQ_SHIFT 4 | ||
599 | #define IEEE80211_SEQ_MAX 4096 | ||
600 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | ||
601 | |||
602 | /* return whether a bit at index _n in bitmap _bm is set | ||
603 | * _sz is the size of the bitmap */ | ||
604 | #define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \ | ||
605 | ((_bm)[(_n) >> 5] & (1 << ((_n) & 31)))) | ||
606 | |||
607 | /* return block-ack bitmap index given sequence and starting sequence */ | ||
608 | #define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) | ||
609 | |||
610 | /* returns delimiter padding required given the packet length */ | ||
611 | #define ATH_AGGR_GET_NDELIM(_len) \ | ||
612 | (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ | ||
613 | (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) | ||
614 | |||
615 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ | ||
616 | ((((_seqno) - (_start)) & 4095) < (_bawsz)) | ||
617 | |||
618 | #define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum) | ||
619 | #define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low) | ||
620 | #define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) | ||
621 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->an_aggr.tx.tid[(_tidno)]) | ||
622 | |||
623 | enum ATH_AGGR_STATUS { | ||
624 | ATH_AGGR_DONE, | ||
625 | ATH_AGGR_BAW_CLOSED, | ||
626 | ATH_AGGR_LIMITED, | ||
627 | ATH_AGGR_SHORTPKT, | ||
628 | ATH_AGGR_8K_LIMITED, | ||
629 | }; | ||
630 | |||
631 | enum ATH_AGGR_CHECK { | ||
632 | AGGR_NOT_REQUIRED, | ||
633 | AGGR_REQUIRED, | ||
634 | AGGR_CLEANUP_PROGRESS, | ||
635 | AGGR_EXCHANGE_PROGRESS, | ||
636 | AGGR_EXCHANGE_DONE | ||
637 | }; | ||
638 | |||
639 | struct aggr_rifs_param { | ||
640 | int param_max_frames; | ||
641 | int param_max_len; | ||
642 | int param_rl; | ||
643 | int param_al; | ||
644 | struct ath_rc_series *param_rcs; | ||
645 | }; | ||
646 | |||
647 | /* Per-node aggregation state */ | ||
648 | struct ath_node_aggr { | ||
649 | struct ath_atx tx; /* node transmit state */ | ||
650 | struct ath_arx rx; /* node receive state */ | ||
651 | }; | ||
652 | |||
653 | /* driver-specific node state */ | ||
654 | struct ath_node { | ||
655 | struct list_head list; | ||
656 | struct ath_softc *an_sc; /* back pointer */ | ||
657 | atomic_t an_refcnt; | ||
658 | struct ath_chainmask_sel an_chainmask_sel; | ||
659 | struct ath_node_aggr an_aggr; /* A-MPDU aggregation state */ | ||
660 | u8 an_smmode; /* SM Power save mode */ | ||
661 | u8 an_flags; | ||
662 | u8 an_addr[ETH_ALEN]; | ||
663 | }; | ||
664 | |||
665 | void ath_tx_resume_tid(struct ath_softc *sc, | ||
666 | struct ath_atx_tid *tid); | ||
667 | enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc, | ||
668 | struct ath_node *an, u8 tidno); | ||
669 | void ath_tx_aggr_teardown(struct ath_softc *sc, | ||
670 | struct ath_node *an, u8 tidno); | ||
671 | void ath_rx_aggr_teardown(struct ath_softc *sc, | ||
672 | struct ath_node *an, u8 tidno); | ||
673 | int ath_rx_aggr_start(struct ath_softc *sc, | ||
674 | const u8 *addr, | ||
675 | u16 tid, | ||
676 | u16 *ssn); | ||
677 | int ath_rx_aggr_stop(struct ath_softc *sc, | ||
678 | const u8 *addr, | ||
679 | u16 tid); | ||
680 | int ath_tx_aggr_start(struct ath_softc *sc, | ||
681 | const u8 *addr, | ||
682 | u16 tid, | ||
683 | u16 *ssn); | ||
684 | int ath_tx_aggr_stop(struct ath_softc *sc, | ||
685 | const u8 *addr, | ||
686 | u16 tid); | ||
687 | void ath_newassoc(struct ath_softc *sc, | ||
688 | struct ath_node *node, int isnew, int isuapsd); | ||
689 | struct ath_node *ath_node_attach(struct ath_softc *sc, | ||
690 | u8 addr[ETH_ALEN], int if_id); | ||
691 | void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag); | ||
692 | struct ath_node *ath_node_get(struct ath_softc *sc, u8 addr[ETH_ALEN]); | ||
693 | void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag); | ||
694 | struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr); | ||
695 | |||
696 | /*******************/ | ||
697 | /* Beacon Handling */ | ||
698 | /*******************/ | ||
699 | |||
700 | /* | ||
701 | * Regardless of the number of beacons we stagger, (i.e. regardless of the | ||
702 | * number of BSSIDs) if a given beacon does not go out even after waiting this | ||
703 | * number of beacon intervals, the game's up. | ||
704 | */ | ||
705 | #define BSTUCK_THRESH (9 * ATH_BCBUF) | ||
706 | #define ATH_BCBUF 4 /* number of beacon buffers */ | ||
707 | #define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */ | ||
708 | #define ATH_DEFAULT_BMISS_LIMIT 10 | ||
709 | #define ATH_BEACON_AIFS_DEFAULT 0 /* Default aifs for ap beacon q */ | ||
710 | #define ATH_BEACON_CWMIN_DEFAULT 0 /* Default cwmin for ap beacon q */ | ||
711 | #define ATH_BEACON_CWMAX_DEFAULT 0 /* Default cwmax for ap beacon q */ | ||
712 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | ||
713 | |||
714 | /* beacon configuration */ | ||
715 | struct ath_beacon_config { | ||
716 | u16 beacon_interval; | ||
717 | u16 listen_interval; | ||
718 | u16 dtim_period; | ||
719 | u16 bmiss_timeout; | ||
720 | u8 dtim_count; | ||
721 | u8 tim_offset; | ||
722 | union { | ||
723 | u64 last_tsf; | ||
724 | u8 last_tstamp[8]; | ||
725 | } u; /* last received beacon/probe response timestamp of this BSS. */ | ||
726 | }; | ||
727 | |||
728 | /* offsets in a beacon frame for | ||
729 | * quick acess of beacon content by low-level driver */ | ||
730 | struct ath_beacon_offset { | ||
731 | u8 *bo_tim; /* start of atim/dtim */ | ||
732 | }; | ||
733 | |||
734 | void ath9k_beacon_tasklet(unsigned long data); | ||
735 | void ath_beacon_config(struct ath_softc *sc, int if_id); | ||
736 | int ath_beaconq_setup(struct ath_hal *ah); | ||
737 | int ath_beacon_alloc(struct ath_softc *sc, int if_id); | ||
738 | void ath_bstuck_process(struct ath_softc *sc); | ||
739 | void ath_beacon_tasklet(struct ath_softc *sc, int *needmark); | ||
740 | void ath_beacon_free(struct ath_softc *sc); | ||
741 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp); | ||
742 | void ath_beacon_sync(struct ath_softc *sc, int if_id); | ||
743 | void ath_update_beacon_info(struct ath_softc *sc, int avgbrssi); | ||
744 | void ath_get_beaconconfig(struct ath_softc *sc, | ||
745 | int if_id, | ||
746 | struct ath_beacon_config *conf); | ||
747 | int ath_update_beacon(struct ath_softc *sc, | ||
748 | int if_id, | ||
749 | struct ath_beacon_offset *bo, | ||
750 | struct sk_buff *skb, | ||
751 | int mcast); | ||
752 | /********/ | ||
753 | /* VAPs */ | ||
754 | /********/ | ||
755 | |||
756 | #define ATH_IF_HW_OFF 0x0001 /* hardware state needs to turn off */ | ||
757 | #define ATH_IF_HW_ON 0x0002 /* hardware state needs to turn on */ | ||
758 | /* STA only: the associated AP is HT capable */ | ||
759 | #define ATH_IF_HT 0x0004 | ||
760 | /* AP/IBSS only: current BSS has privacy on */ | ||
761 | #define ATH_IF_PRIVACY 0x0008 | ||
762 | #define ATH_IF_BEACON_ENABLE 0x0010 /* AP/IBSS only: enable beacon */ | ||
763 | #define ATH_IF_BEACON_SYNC 0x0020 /* IBSS only: need to sync beacon */ | ||
764 | |||
765 | /* | ||
766 | * Define the scheme that we select MAC address for multiple | ||
767 | * BSS on the same radio. The very first VAP will just use the MAC | ||
768 | * address from the EEPROM. For the next 3 VAPs, we set the | ||
769 | * U/L bit (bit 1) in MAC address, and use the next two bits as the | ||
770 | * index of the VAP. | ||
771 | */ | ||
772 | |||
773 | #define ATH_SET_VAP_BSSID_MASK(bssid_mask) \ | ||
774 | ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02)) | ||
775 | |||
776 | /* VAP configuration (from protocol layer) */ | ||
777 | struct ath_vap_config { | ||
778 | u32 av_fixed_rateset; | ||
779 | u32 av_fixed_retryset; | ||
780 | }; | ||
781 | |||
782 | /* driver-specific vap state */ | ||
783 | struct ath_vap { | ||
784 | struct ieee80211_vif *av_if_data; /* interface(vap) | ||
785 | instance from 802.11 protocal layer */ | ||
786 | enum ath9k_opmode av_opmode; /* VAP operational mode */ | ||
787 | struct ath_buf *av_bcbuf; /* beacon buffer */ | ||
788 | struct ath_beacon_offset av_boff; /* dynamic update state */ | ||
789 | struct ath_tx_control av_btxctl; /* tx control information | ||
790 | for beacon */ | ||
791 | int av_bslot; /* beacon slot index */ | ||
792 | struct ath_txq av_mcastq; /* multicast | ||
793 | transmit queue */ | ||
794 | struct ath_vap_config av_config; /* vap configuration | ||
795 | parameters from 802.11 protocol layer*/ | ||
796 | struct ath_rate_node *rc_node; | ||
797 | }; | ||
798 | |||
799 | int ath_vap_attach(struct ath_softc *sc, | ||
800 | int if_id, | ||
801 | struct ieee80211_vif *if_data, | ||
802 | enum ath9k_opmode opmode); | ||
803 | int ath_vap_detach(struct ath_softc *sc, int if_id); | ||
804 | int ath_vap_config(struct ath_softc *sc, | ||
805 | int if_id, struct ath_vap_config *if_config); | ||
806 | int ath_vap_listen(struct ath_softc *sc, int if_id); | ||
807 | |||
808 | /*********************/ | ||
809 | /* Antenna diversity */ | ||
810 | /*********************/ | ||
811 | |||
812 | #define ATH_ANT_DIV_MAX_CFG 2 | ||
813 | #define ATH_ANT_DIV_MIN_IDLE_US 1000000 /* us */ | ||
814 | #define ATH_ANT_DIV_MIN_SCAN_US 50000 /* us */ | ||
815 | |||
816 | enum ATH_ANT_DIV_STATE{ | ||
817 | ATH_ANT_DIV_IDLE, | ||
818 | ATH_ANT_DIV_SCAN, /* evaluating antenna */ | ||
819 | }; | ||
820 | |||
821 | struct ath_antdiv { | ||
822 | struct ath_softc *antdiv_sc; | ||
823 | u8 antdiv_start; | ||
824 | enum ATH_ANT_DIV_STATE antdiv_state; | ||
825 | u8 antdiv_num_antcfg; | ||
826 | u8 antdiv_curcfg; | ||
827 | u8 antdiv_bestcfg; | ||
828 | int32_t antdivf_rssitrig; | ||
829 | int32_t antdiv_lastbrssi[ATH_ANT_DIV_MAX_CFG]; | ||
830 | u64 antdiv_lastbtsf[ATH_ANT_DIV_MAX_CFG]; | ||
831 | u64 antdiv_laststatetsf; | ||
832 | u8 antdiv_bssid[ETH_ALEN]; | ||
833 | }; | ||
834 | |||
835 | void ath_slow_ant_div_init(struct ath_antdiv *antdiv, | ||
836 | struct ath_softc *sc, int32_t rssitrig); | ||
837 | void ath_slow_ant_div_start(struct ath_antdiv *antdiv, | ||
838 | u8 num_antcfg, | ||
839 | const u8 *bssid); | ||
840 | void ath_slow_ant_div_stop(struct ath_antdiv *antdiv); | ||
841 | void ath_slow_ant_div(struct ath_antdiv *antdiv, | ||
842 | struct ieee80211_hdr *wh, | ||
843 | struct ath_rx_status *rx_stats); | ||
844 | void ath_setdefantenna(void *sc, u32 antenna); | ||
845 | |||
846 | /********************/ | ||
847 | /* Main driver core */ | ||
848 | /********************/ | ||
849 | |||
850 | /* | ||
851 | * Default cache line size, in bytes. | ||
852 | * Used when PCI device not fully initialized by bootrom/BIOS | ||
853 | */ | ||
854 | #define DEFAULT_CACHELINE 32 | ||
855 | #define ATH_DEFAULT_NOISE_FLOOR -95 | ||
856 | #define ATH_REGCLASSIDS_MAX 10 | ||
857 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | ||
858 | #define ATH_PREAMBLE_SHORT (1<<0) | ||
859 | #define ATH_PROTECT_ENABLE (1<<1) | ||
860 | #define ATH_MAX_SW_RETRIES 10 | ||
861 | /* Num farmes difference in tx to flip default recv */ | ||
862 | #define ATH_ANTENNA_DIFF 2 | ||
863 | #define ATH_CHAN_MAX 255 | ||
864 | #define IEEE80211_WEP_NKID 4 /* number of key ids */ | ||
865 | #define IEEE80211_RATE_VAL 0x7f | ||
866 | /* | ||
867 | * The key cache is used for h/w cipher state and also for | ||
868 | * tracking station state such as the current tx antenna. | ||
869 | * We also setup a mapping table between key cache slot indices | ||
870 | * and station state to short-circuit node lookups on rx. | ||
871 | * Different parts have different size key caches. We handle | ||
872 | * up to ATH_KEYMAX entries (could dynamically allocate state). | ||
873 | */ | ||
874 | #define ATH_KEYMAX 128 /* max key cache size we handle */ | ||
875 | |||
876 | #define RESET_RETRY_TXQ 0x00000001 | ||
877 | #define ATH_IF_ID_ANY 0xff | ||
878 | |||
879 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | ||
880 | |||
881 | #define RSSI_LPF_THRESHOLD -20 | ||
882 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ | ||
883 | #define ATH_RATE_DUMMY_MARKER 0 | ||
884 | #define ATH_RSSI_LPF_LEN 10 | ||
885 | #define ATH_RSSI_DUMMY_MARKER 0x127 | ||
886 | |||
887 | #define ATH_EP_MUL(x, mul) ((x) * (mul)) | ||
888 | #define ATH_EP_RND(x, mul) \ | ||
889 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | ||
890 | #define ATH_RSSI_OUT(x) \ | ||
891 | (((x) != ATH_RSSI_DUMMY_MARKER) ? \ | ||
892 | (ATH_EP_RND((x), ATH_RSSI_EP_MULTIPLIER)) : ATH_RSSI_DUMMY_MARKER) | ||
893 | #define ATH_RSSI_IN(x) \ | ||
894 | (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) | ||
895 | #define ATH_LPF_RSSI(x, y, len) \ | ||
896 | ((x != ATH_RSSI_DUMMY_MARKER) ? \ | ||
897 | (((x) * ((len) - 1) + (y)) / (len)) : (y)) | ||
898 | #define ATH_RSSI_LPF(x, y) do { \ | ||
899 | if ((y) >= RSSI_LPF_THRESHOLD) \ | ||
900 | x = ATH_LPF_RSSI((x), \ | ||
901 | ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ | ||
902 | } while (0) | ||
903 | |||
904 | |||
905 | enum PROT_MODE { | ||
906 | PROT_M_NONE = 0, | ||
907 | PROT_M_RTSCTS, | ||
908 | PROT_M_CTSONLY | ||
909 | }; | ||
910 | |||
911 | enum RATE_TYPE { | ||
912 | NORMAL_RATE = 0, | ||
913 | HALF_RATE, | ||
914 | QUARTER_RATE | ||
915 | }; | ||
916 | |||
917 | struct ath_ht_info { | ||
918 | enum ath9k_ht_macmode tx_chan_width; | ||
919 | u16 maxampdu; | ||
920 | u8 mpdudensity; | ||
921 | u8 ext_chan_offset; | ||
922 | }; | ||
923 | |||
924 | struct ath_softc { | ||
925 | struct ieee80211_hw *hw; /* mac80211 instance */ | ||
926 | struct pci_dev *pdev; /* Bus handle */ | ||
927 | void __iomem *mem; /* address of the device */ | ||
928 | struct tasklet_struct intr_tq; /* General tasklet */ | ||
929 | struct tasklet_struct bcon_tasklet; /* Beacon tasklet */ | ||
930 | struct ath_config sc_config; /* per-instance load-time | ||
931 | parameters */ | ||
932 | int sc_debug; /* Debug masks */ | ||
933 | struct ath_hal *sc_ah; /* HAL Instance */ | ||
934 | struct ath_rate_softc *sc_rc; /* tx rate control support */ | ||
935 | u32 sc_intrstatus; /* HAL_STATUS */ | ||
936 | enum ath9k_opmode sc_opmode; /* current operating mode */ | ||
937 | |||
938 | /* Properties, Config */ | ||
939 | u8 sc_invalid; /* being detached */ | ||
940 | u8 sc_beacons; /* beacons running */ | ||
941 | u8 sc_scanning; /* scanning active */ | ||
942 | u8 sc_txaggr; /* enable 11n tx aggregation */ | ||
943 | u8 sc_rxaggr; /* enable 11n rx aggregation */ | ||
944 | u8 sc_update_chainmask; /* change chain mask */ | ||
945 | u8 sc_full_reset; /* force full reset */ | ||
946 | enum wireless_mode sc_curmode; /* current phy mode */ | ||
947 | u16 sc_curtxpow; /* current tx power limit */ | ||
948 | u16 sc_curaid; /* current association id */ | ||
949 | u8 sc_curbssid[ETH_ALEN]; | ||
950 | u8 sc_myaddr[ETH_ALEN]; | ||
951 | enum PROT_MODE sc_protmode; /* protection mode */ | ||
952 | u8 sc_mcastantenna;/* Multicast antenna number */ | ||
953 | u8 sc_txantenna; /* data tx antenna | ||
954 | (fixed or auto) */ | ||
955 | u8 sc_nbcnvaps; /* # of vaps sending beacons */ | ||
956 | u16 sc_nvaps; /* # of active virtual ap's */ | ||
957 | struct ath_vap *sc_vaps[ATH_BCBUF]; /* interface id | ||
958 | to avp map */ | ||
959 | enum ath9k_int sc_imask; /* interrupt mask copy */ | ||
960 | u8 sc_bssidmask[ETH_ALEN]; | ||
961 | u8 sc_defant; /* current default antenna */ | ||
962 | u8 sc_rxotherant; /* rx's on non-default antenna*/ | ||
963 | u16 sc_cachelsz; /* cache line size */ | ||
964 | int sc_slotupdate; /* slot to next advance fsm */ | ||
965 | int sc_slottime; /* slot time */ | ||
966 | u8 sc_noreset; | ||
967 | int sc_bslot[ATH_BCBUF];/* beacon xmit slots */ | ||
968 | struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ | ||
969 | struct list_head node_list; | ||
970 | struct ath_ht_info sc_ht_info; | ||
971 | int16_t sc_noise_floor; /* signal noise floor in dBm */ | ||
972 | enum ath9k_ht_extprotspacing sc_ht_extprotspacing; | ||
973 | u8 sc_tx_chainmask; | ||
974 | u8 sc_rx_chainmask; | ||
975 | u8 sc_rxchaindetect_ref; | ||
976 | u8 sc_rxchaindetect_thresh5GHz; | ||
977 | u8 sc_rxchaindetect_thresh2GHz; | ||
978 | u8 sc_rxchaindetect_delta5GHz; | ||
979 | u8 sc_rxchaindetect_delta2GHz; | ||
980 | u32 sc_rtsaggrlimit; /* Chipset specific | ||
981 | aggr limit */ | ||
982 | u32 sc_flags; | ||
983 | #ifdef CONFIG_SLOW_ANT_DIV | ||
984 | /* Slow antenna diversity */ | ||
985 | struct ath_antdiv sc_antdiv; | ||
986 | #endif | ||
987 | enum { | ||
988 | OK, /* no change needed */ | ||
989 | UPDATE, /* update pending */ | ||
990 | COMMIT /* beacon sent, commit change */ | ||
991 | } sc_updateslot; /* slot time update fsm */ | ||
992 | |||
993 | /* Crypto */ | ||
994 | u32 sc_keymax; /* size of key cache */ | ||
995 | DECLARE_BITMAP(sc_keymap, ATH_KEYMAX); /* key use bit map */ | ||
996 | u8 sc_splitmic; /* split TKIP MIC keys */ | ||
997 | int sc_keytype; /* type of the key being used */ | ||
998 | |||
999 | /* RX */ | ||
1000 | struct list_head sc_rxbuf; /* receive buffer */ | ||
1001 | struct ath_descdma sc_rxdma; /* RX descriptors */ | ||
1002 | int sc_rxbufsize; /* rx size based on mtu */ | ||
1003 | u32 *sc_rxlink; /* link ptr in last RX desc */ | ||
1004 | u32 sc_rxflush; /* rx flush in progress */ | ||
1005 | u64 sc_lastrx; /* tsf of last rx'd frame */ | ||
1006 | |||
1007 | /* TX */ | ||
1008 | struct list_head sc_txbuf; /* transmit buffer */ | ||
1009 | struct ath_txq sc_txq[ATH9K_NUM_TX_QUEUES]; | ||
1010 | struct ath_descdma sc_txdma; /* TX descriptors */ | ||
1011 | u32 sc_txqsetup; /* h/w queues setup */ | ||
1012 | u32 sc_txintrperiod;/* tx interrupt batching */ | ||
1013 | int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME | ||
1014 | AC -> h/w qnum */ | ||
1015 | u32 sc_ant_tx[8]; /* recent tx frames/antenna */ | ||
1016 | |||
1017 | /* Beacon */ | ||
1018 | struct ath9k_txq_info sc_beacon_qi; /* adhoc only: beacon | ||
1019 | queue parameters */ | ||
1020 | struct ath_descdma sc_bdma; /* beacon descriptors */ | ||
1021 | struct ath_txq *sc_cabq; /* tx q for cab frames */ | ||
1022 | struct list_head sc_bbuf; /* beacon buffers */ | ||
1023 | u32 sc_bhalq; /* HAL q for outgoing beacons */ | ||
1024 | u32 sc_bmisscount; /* missed beacon transmits */ | ||
1025 | u32 ast_be_xmit; /* beacons transmitted */ | ||
1026 | |||
1027 | /* Rate */ | ||
1028 | struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; | ||
1029 | const struct ath9k_rate_table *sc_rates[WIRELESS_MODE_MAX]; | ||
1030 | const struct ath9k_rate_table *sc_currates; /* current rate table */ | ||
1031 | u8 sc_rixmap[256]; /* IEEE to h/w | ||
1032 | rate table ix */ | ||
1033 | u8 sc_minrateix; /* min h/w rate index */ | ||
1034 | u8 sc_protrix; /* protection rate index */ | ||
1035 | struct { | ||
1036 | u32 rateKbps; /* transfer rate in kbs */ | ||
1037 | u8 ieeerate; /* IEEE rate */ | ||
1038 | } sc_hwmap[256]; /* h/w rate ix mappings */ | ||
1039 | |||
1040 | /* Channel, Band */ | ||
1041 | struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX]; | ||
1042 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | ||
1043 | struct ath9k_channel sc_curchan; /* current h/w channel */ | ||
1044 | |||
1045 | /* Locks */ | ||
1046 | spinlock_t sc_rxflushlock; /* lock of RX flush */ | ||
1047 | spinlock_t sc_rxbuflock; /* rxbuf lock */ | ||
1048 | spinlock_t sc_txbuflock; /* txbuf lock */ | ||
1049 | spinlock_t sc_resetlock; | ||
1050 | spinlock_t node_lock; | ||
1051 | }; | ||
1052 | |||
1053 | int ath_init(u16 devid, struct ath_softc *sc); | ||
1054 | void ath_deinit(struct ath_softc *sc); | ||
1055 | int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan); | ||
1056 | int ath_suspend(struct ath_softc *sc); | ||
1057 | irqreturn_t ath_isr(int irq, void *dev); | ||
1058 | int ath_reset(struct ath_softc *sc); | ||
1059 | void ath_scan_start(struct ath_softc *sc); | ||
1060 | void ath_scan_end(struct ath_softc *sc); | ||
1061 | int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan); | ||
1062 | void ath_setup_rate(struct ath_softc *sc, | ||
1063 | enum wireless_mode wMode, | ||
1064 | enum RATE_TYPE type, | ||
1065 | const struct ath9k_rate_table *rt); | ||
1066 | |||
1067 | /*********************/ | ||
1068 | /* Utility Functions */ | ||
1069 | /*********************/ | ||
1070 | |||
1071 | void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot); | ||
1072 | int ath_keyset(struct ath_softc *sc, | ||
1073 | u16 keyix, | ||
1074 | struct ath9k_keyval *hk, | ||
1075 | const u8 mac[ETH_ALEN]); | ||
1076 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); | ||
1077 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); | ||
1078 | void ath_setslottime(struct ath_softc *sc); | ||
1079 | void ath_update_txpow(struct ath_softc *sc); | ||
1080 | int ath_cabq_update(struct ath_softc *); | ||
1081 | void ath_get_currentCountry(struct ath_softc *sc, | ||
1082 | struct ath9k_country_entry *ctry); | ||
1083 | u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp); | ||
1084 | void ath_internal_reset(struct ath_softc *sc); | ||
1085 | u32 ath_chan2flags(struct ieee80211_channel *chan, struct ath_softc *sc); | ||
1086 | dma_addr_t ath_skb_map_single(struct ath_softc *sc, | ||
1087 | struct sk_buff *skb, | ||
1088 | int direction, | ||
1089 | dma_addr_t *pa); | ||
1090 | void ath_skb_unmap_single(struct ath_softc *sc, | ||
1091 | struct sk_buff *skb, | ||
1092 | int direction, | ||
1093 | dma_addr_t *pa); | ||
1094 | void ath_mcast_merge(struct ath_softc *sc, u32 mfilt[2]); | ||
1095 | enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc); | ||
1096 | |||
1097 | #endif /* CORE_H */ | ||
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c new file mode 100644 index 00000000000..1f6f3934d37 --- /dev/null +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -0,0 +1,8563 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/io.h> | ||
18 | #include <asm/unaligned.h> | ||
19 | |||
20 | #include "core.h" | ||
21 | #include "hw.h" | ||
22 | #include "reg.h" | ||
23 | #include "phy.h" | ||
24 | #include "initvals.h" | ||
25 | |||
26 | static void ath9k_hw_iqcal_collect(struct ath_hal *ah); | ||
27 | static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains); | ||
28 | static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah); | ||
29 | static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, | ||
30 | u8 numChains); | ||
31 | static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah); | ||
32 | static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, | ||
33 | u8 numChains); | ||
34 | |||
35 | static const u8 CLOCK_RATE[] = { 40, 80, 22, 44, 88, 40 }; | ||
36 | static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 }; | ||
37 | |||
38 | static const struct hal_percal_data iq_cal_multi_sample = { | ||
39 | IQ_MISMATCH_CAL, | ||
40 | MAX_CAL_SAMPLES, | ||
41 | PER_MIN_LOG_COUNT, | ||
42 | ath9k_hw_iqcal_collect, | ||
43 | ath9k_hw_iqcalibrate | ||
44 | }; | ||
45 | static const struct hal_percal_data iq_cal_single_sample = { | ||
46 | IQ_MISMATCH_CAL, | ||
47 | MIN_CAL_SAMPLES, | ||
48 | PER_MAX_LOG_COUNT, | ||
49 | ath9k_hw_iqcal_collect, | ||
50 | ath9k_hw_iqcalibrate | ||
51 | }; | ||
52 | static const struct hal_percal_data adc_gain_cal_multi_sample = { | ||
53 | ADC_GAIN_CAL, | ||
54 | MAX_CAL_SAMPLES, | ||
55 | PER_MIN_LOG_COUNT, | ||
56 | ath9k_hw_adc_gaincal_collect, | ||
57 | ath9k_hw_adc_gaincal_calibrate | ||
58 | }; | ||
59 | static const struct hal_percal_data adc_gain_cal_single_sample = { | ||
60 | ADC_GAIN_CAL, | ||
61 | MIN_CAL_SAMPLES, | ||
62 | PER_MAX_LOG_COUNT, | ||
63 | ath9k_hw_adc_gaincal_collect, | ||
64 | ath9k_hw_adc_gaincal_calibrate | ||
65 | }; | ||
66 | static const struct hal_percal_data adc_dc_cal_multi_sample = { | ||
67 | ADC_DC_CAL, | ||
68 | MAX_CAL_SAMPLES, | ||
69 | PER_MIN_LOG_COUNT, | ||
70 | ath9k_hw_adc_dccal_collect, | ||
71 | ath9k_hw_adc_dccal_calibrate | ||
72 | }; | ||
73 | static const struct hal_percal_data adc_dc_cal_single_sample = { | ||
74 | ADC_DC_CAL, | ||
75 | MIN_CAL_SAMPLES, | ||
76 | PER_MAX_LOG_COUNT, | ||
77 | ath9k_hw_adc_dccal_collect, | ||
78 | ath9k_hw_adc_dccal_calibrate | ||
79 | }; | ||
80 | static const struct hal_percal_data adc_init_dc_cal = { | ||
81 | ADC_DC_INIT_CAL, | ||
82 | MIN_CAL_SAMPLES, | ||
83 | INIT_LOG_COUNT, | ||
84 | ath9k_hw_adc_dccal_collect, | ||
85 | ath9k_hw_adc_dccal_calibrate | ||
86 | }; | ||
87 | |||
88 | static const struct ath_hal ar5416hal = { | ||
89 | AR5416_MAGIC, | ||
90 | 0, | ||
91 | 0, | ||
92 | NULL, | ||
93 | NULL, | ||
94 | CTRY_DEFAULT, | ||
95 | 0, | ||
96 | 0, | ||
97 | 0, | ||
98 | 0, | ||
99 | 0, | ||
100 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
101 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
102 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
103 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
104 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
105 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
106 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
107 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
108 | }, | ||
109 | }; | ||
110 | |||
111 | static struct ath9k_rate_table ar5416_11a_table = { | ||
112 | 8, | ||
113 | {0}, | ||
114 | { | ||
115 | {true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0}, | ||
116 | {true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0}, | ||
117 | {true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2}, | ||
118 | {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2}, | ||
119 | {true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4}, | ||
120 | {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4}, | ||
121 | {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4}, | ||
122 | {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4} | ||
123 | }, | ||
124 | }; | ||
125 | |||
126 | static struct ath9k_rate_table ar5416_11b_table = { | ||
127 | 4, | ||
128 | {0}, | ||
129 | { | ||
130 | {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0}, | ||
131 | {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1}, | ||
132 | {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 1}, | ||
133 | {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 1} | ||
134 | }, | ||
135 | }; | ||
136 | |||
137 | static struct ath9k_rate_table ar5416_11g_table = { | ||
138 | 12, | ||
139 | {0}, | ||
140 | { | ||
141 | {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0}, | ||
142 | {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1}, | ||
143 | {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2}, | ||
144 | {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3}, | ||
145 | |||
146 | {false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4}, | ||
147 | {false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4}, | ||
148 | {true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6}, | ||
149 | {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6}, | ||
150 | {true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8}, | ||
151 | {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8}, | ||
152 | {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8}, | ||
153 | {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8} | ||
154 | }, | ||
155 | }; | ||
156 | |||
157 | static struct ath9k_rate_table ar5416_11ng_table = { | ||
158 | 28, | ||
159 | {0}, | ||
160 | { | ||
161 | {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0}, | ||
162 | {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1}, | ||
163 | {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2}, | ||
164 | {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3}, | ||
165 | |||
166 | {false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4}, | ||
167 | {false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4}, | ||
168 | {true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6}, | ||
169 | {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6}, | ||
170 | {true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8}, | ||
171 | {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8}, | ||
172 | {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8}, | ||
173 | {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8}, | ||
174 | {true, PHY_HT, 6500, 0x80, 0x00, 0, 4}, | ||
175 | {true, PHY_HT, 13000, 0x81, 0x00, 1, 6}, | ||
176 | {true, PHY_HT, 19500, 0x82, 0x00, 2, 6}, | ||
177 | {true, PHY_HT, 26000, 0x83, 0x00, 3, 8}, | ||
178 | {true, PHY_HT, 39000, 0x84, 0x00, 4, 8}, | ||
179 | {true, PHY_HT, 52000, 0x85, 0x00, 5, 8}, | ||
180 | {true, PHY_HT, 58500, 0x86, 0x00, 6, 8}, | ||
181 | {true, PHY_HT, 65000, 0x87, 0x00, 7, 8}, | ||
182 | {true, PHY_HT, 13000, 0x88, 0x00, 8, 4}, | ||
183 | {true, PHY_HT, 26000, 0x89, 0x00, 9, 6}, | ||
184 | {true, PHY_HT, 39000, 0x8a, 0x00, 10, 6}, | ||
185 | {true, PHY_HT, 52000, 0x8b, 0x00, 11, 8}, | ||
186 | {true, PHY_HT, 78000, 0x8c, 0x00, 12, 8}, | ||
187 | {true, PHY_HT, 104000, 0x8d, 0x00, 13, 8}, | ||
188 | {true, PHY_HT, 117000, 0x8e, 0x00, 14, 8}, | ||
189 | {true, PHY_HT, 130000, 0x8f, 0x00, 15, 8}, | ||
190 | }, | ||
191 | }; | ||
192 | |||
193 | static struct ath9k_rate_table ar5416_11na_table = { | ||
194 | 24, | ||
195 | {0}, | ||
196 | { | ||
197 | {true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0}, | ||
198 | {true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0}, | ||
199 | {true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2}, | ||
200 | {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2}, | ||
201 | {true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4}, | ||
202 | {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4}, | ||
203 | {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4}, | ||
204 | {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4}, | ||
205 | {true, PHY_HT, 6500, 0x80, 0x00, 0, 0}, | ||
206 | {true, PHY_HT, 13000, 0x81, 0x00, 1, 2}, | ||
207 | {true, PHY_HT, 19500, 0x82, 0x00, 2, 2}, | ||
208 | {true, PHY_HT, 26000, 0x83, 0x00, 3, 4}, | ||
209 | {true, PHY_HT, 39000, 0x84, 0x00, 4, 4}, | ||
210 | {true, PHY_HT, 52000, 0x85, 0x00, 5, 4}, | ||
211 | {true, PHY_HT, 58500, 0x86, 0x00, 6, 4}, | ||
212 | {true, PHY_HT, 65000, 0x87, 0x00, 7, 4}, | ||
213 | {true, PHY_HT, 13000, 0x88, 0x00, 8, 0}, | ||
214 | {true, PHY_HT, 26000, 0x89, 0x00, 9, 2}, | ||
215 | {true, PHY_HT, 39000, 0x8a, 0x00, 10, 2}, | ||
216 | {true, PHY_HT, 52000, 0x8b, 0x00, 11, 4}, | ||
217 | {true, PHY_HT, 78000, 0x8c, 0x00, 12, 4}, | ||
218 | {true, PHY_HT, 104000, 0x8d, 0x00, 13, 4}, | ||
219 | {true, PHY_HT, 117000, 0x8e, 0x00, 14, 4}, | ||
220 | {true, PHY_HT, 130000, 0x8f, 0x00, 15, 4}, | ||
221 | }, | ||
222 | }; | ||
223 | |||
224 | static enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah, | ||
225 | const struct ath9k_channel *chan) | ||
226 | { | ||
227 | if (IS_CHAN_CCK(chan)) | ||
228 | return WIRELESS_MODE_11b; | ||
229 | if (IS_CHAN_G(chan)) | ||
230 | return WIRELESS_MODE_11g; | ||
231 | return WIRELESS_MODE_11a; | ||
232 | } | ||
233 | |||
234 | static bool ath9k_hw_wait(struct ath_hal *ah, | ||
235 | u32 reg, | ||
236 | u32 mask, | ||
237 | u32 val) | ||
238 | { | ||
239 | int i; | ||
240 | |||
241 | for (i = 0; i < (AH_TIMEOUT / AH_TIME_QUANTUM); i++) { | ||
242 | if ((REG_READ(ah, reg) & mask) == val) | ||
243 | return true; | ||
244 | |||
245 | udelay(AH_TIME_QUANTUM); | ||
246 | } | ||
247 | DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO, | ||
248 | "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", | ||
249 | __func__, reg, REG_READ(ah, reg), mask, val); | ||
250 | return false; | ||
251 | } | ||
252 | |||
253 | static bool ath9k_hw_eeprom_read(struct ath_hal *ah, u32 off, | ||
254 | u16 *data) | ||
255 | { | ||
256 | (void) REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); | ||
257 | |||
258 | if (!ath9k_hw_wait(ah, | ||
259 | AR_EEPROM_STATUS_DATA, | ||
260 | AR_EEPROM_STATUS_DATA_BUSY | | ||
261 | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) { | ||
262 | return false; | ||
263 | } | ||
264 | |||
265 | *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), | ||
266 | AR_EEPROM_STATUS_DATA_VAL); | ||
267 | |||
268 | return true; | ||
269 | } | ||
270 | |||
271 | static int ath9k_hw_flash_map(struct ath_hal *ah) | ||
272 | { | ||
273 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
274 | |||
275 | ahp->ah_cal_mem = ioremap(AR5416_EEPROM_START_ADDR, AR5416_EEPROM_MAX); | ||
276 | |||
277 | if (!ahp->ah_cal_mem) { | ||
278 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
279 | "%s: cannot remap eeprom region \n", __func__); | ||
280 | return -EIO; | ||
281 | } | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static bool ath9k_hw_flash_read(struct ath_hal *ah, u32 off, | ||
287 | u16 *data) | ||
288 | { | ||
289 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
290 | |||
291 | *data = ioread16(ahp->ah_cal_mem + off); | ||
292 | return true; | ||
293 | } | ||
294 | |||
295 | static void ath9k_hw_read_revisions(struct ath_hal *ah) | ||
296 | { | ||
297 | u32 val; | ||
298 | |||
299 | val = REG_READ(ah, AR_SREV) & AR_SREV_ID; | ||
300 | |||
301 | if (val == 0xFF) { | ||
302 | val = REG_READ(ah, AR_SREV); | ||
303 | |||
304 | ah->ah_macVersion = | ||
305 | (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; | ||
306 | |||
307 | ah->ah_macRev = MS(val, AR_SREV_REVISION2); | ||
308 | ah->ah_isPciExpress = | ||
309 | (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; | ||
310 | |||
311 | } else { | ||
312 | if (!AR_SREV_9100(ah)) | ||
313 | ah->ah_macVersion = MS(val, AR_SREV_VERSION); | ||
314 | |||
315 | ah->ah_macRev = val & AR_SREV_REVISION; | ||
316 | |||
317 | if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) | ||
318 | ah->ah_isPciExpress = true; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | u32 ath9k_hw_reverse_bits(u32 val, u32 n) | ||
323 | { | ||
324 | u32 retval; | ||
325 | int i; | ||
326 | |||
327 | for (i = 0, retval = 0; i < n; i++) { | ||
328 | retval = (retval << 1) | (val & 1); | ||
329 | val >>= 1; | ||
330 | } | ||
331 | return retval; | ||
332 | } | ||
333 | |||
334 | static void ath9k_hw_set_defaults(struct ath_hal *ah) | ||
335 | { | ||
336 | int i; | ||
337 | |||
338 | ah->ah_config.ath_hal_dma_beacon_response_time = 2; | ||
339 | ah->ah_config.ath_hal_sw_beacon_response_time = 10; | ||
340 | ah->ah_config.ath_hal_additional_swba_backoff = 0; | ||
341 | ah->ah_config.ath_hal_6mb_ack = 0x0; | ||
342 | ah->ah_config.ath_hal_cwmIgnoreExtCCA = 0; | ||
343 | ah->ah_config.ath_hal_pciePowerSaveEnable = 0; | ||
344 | ah->ah_config.ath_hal_pcieL1SKPEnable = 0; | ||
345 | ah->ah_config.ath_hal_pcieClockReq = 0; | ||
346 | ah->ah_config.ath_hal_pciePowerReset = 0x100; | ||
347 | ah->ah_config.ath_hal_pcieRestore = 0; | ||
348 | ah->ah_config.ath_hal_pcieWaen = 0; | ||
349 | ah->ah_config.ath_hal_analogShiftReg = 1; | ||
350 | ah->ah_config.ath_hal_htEnable = 1; | ||
351 | ah->ah_config.ath_hal_ofdmTrigLow = 200; | ||
352 | ah->ah_config.ath_hal_ofdmTrigHigh = 500; | ||
353 | ah->ah_config.ath_hal_cckTrigHigh = 200; | ||
354 | ah->ah_config.ath_hal_cckTrigLow = 100; | ||
355 | ah->ah_config.ath_hal_enableANI = 0; | ||
356 | ah->ah_config.ath_hal_noiseImmunityLvl = 4; | ||
357 | ah->ah_config.ath_hal_ofdmWeakSigDet = 1; | ||
358 | ah->ah_config.ath_hal_cckWeakSigThr = 0; | ||
359 | ah->ah_config.ath_hal_spurImmunityLvl = 2; | ||
360 | ah->ah_config.ath_hal_firStepLvl = 0; | ||
361 | ah->ah_config.ath_hal_rssiThrHigh = 40; | ||
362 | ah->ah_config.ath_hal_rssiThrLow = 7; | ||
363 | ah->ah_config.ath_hal_diversityControl = 0; | ||
364 | ah->ah_config.ath_hal_antennaSwitchSwap = 0; | ||
365 | |||
366 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | ||
367 | ah->ah_config.ath_hal_spurChans[i][0] = AR_NO_SPUR; | ||
368 | ah->ah_config.ath_hal_spurChans[i][1] = AR_NO_SPUR; | ||
369 | } | ||
370 | |||
371 | ah->ah_config.ath_hal_intrMitigation = 0; | ||
372 | } | ||
373 | |||
374 | static inline void ath9k_hw_override_ini(struct ath_hal *ah, | ||
375 | struct ath9k_channel *chan) | ||
376 | { | ||
377 | if (!AR_SREV_5416_V20_OR_LATER(ah) | ||
378 | || AR_SREV_9280_10_OR_LATER(ah)) | ||
379 | return; | ||
380 | |||
381 | REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); | ||
382 | } | ||
383 | |||
384 | static inline void ath9k_hw_init_bb(struct ath_hal *ah, | ||
385 | struct ath9k_channel *chan) | ||
386 | { | ||
387 | u32 synthDelay; | ||
388 | |||
389 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; | ||
390 | if (IS_CHAN_CCK(chan)) | ||
391 | synthDelay = (4 * synthDelay) / 22; | ||
392 | else | ||
393 | synthDelay /= 10; | ||
394 | |||
395 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
396 | |||
397 | udelay(synthDelay + BASE_ACTIVATE_DELAY); | ||
398 | } | ||
399 | |||
400 | static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah, | ||
401 | enum ath9k_opmode opmode) | ||
402 | { | ||
403 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
404 | |||
405 | ahp->ah_maskReg = AR_IMR_TXERR | | ||
406 | AR_IMR_TXURN | | ||
407 | AR_IMR_RXERR | | ||
408 | AR_IMR_RXORN | | ||
409 | AR_IMR_BCNMISC; | ||
410 | |||
411 | if (ahp->ah_intrMitigation) | ||
412 | ahp->ah_maskReg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; | ||
413 | else | ||
414 | ahp->ah_maskReg |= AR_IMR_RXOK; | ||
415 | |||
416 | ahp->ah_maskReg |= AR_IMR_TXOK; | ||
417 | |||
418 | if (opmode == ATH9K_M_HOSTAP) | ||
419 | ahp->ah_maskReg |= AR_IMR_MIB; | ||
420 | |||
421 | REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); | ||
422 | REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT); | ||
423 | |||
424 | if (!AR_SREV_9100(ah)) { | ||
425 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); | ||
426 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); | ||
427 | REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); | ||
428 | } | ||
429 | } | ||
430 | |||
431 | static inline void ath9k_hw_init_qos(struct ath_hal *ah) | ||
432 | { | ||
433 | REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); | ||
434 | REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); | ||
435 | |||
436 | REG_WRITE(ah, AR_QOS_NO_ACK, | ||
437 | SM(2, AR_QOS_NO_ACK_TWO_BIT) | | ||
438 | SM(5, AR_QOS_NO_ACK_BIT_OFF) | | ||
439 | SM(0, AR_QOS_NO_ACK_BYTE_OFF)); | ||
440 | |||
441 | REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL); | ||
442 | REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF); | ||
443 | REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF); | ||
444 | REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF); | ||
445 | REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); | ||
446 | } | ||
447 | |||
448 | static void ath9k_hw_analog_shift_rmw(struct ath_hal *ah, | ||
449 | u32 reg, | ||
450 | u32 mask, | ||
451 | u32 shift, | ||
452 | u32 val) | ||
453 | { | ||
454 | u32 regVal; | ||
455 | |||
456 | regVal = REG_READ(ah, reg) & ~mask; | ||
457 | regVal |= (val << shift) & mask; | ||
458 | |||
459 | REG_WRITE(ah, reg, regVal); | ||
460 | |||
461 | if (ah->ah_config.ath_hal_analogShiftReg) | ||
462 | udelay(100); | ||
463 | |||
464 | return; | ||
465 | } | ||
466 | |||
467 | static u8 ath9k_hw_get_num_ant_config(struct ath_hal_5416 *ahp, | ||
468 | enum hal_freq_band freq_band) | ||
469 | { | ||
470 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; | ||
471 | struct modal_eep_header *pModal = | ||
472 | &(eep->modalHeader[HAL_FREQ_BAND_2GHZ == freq_band]); | ||
473 | struct base_eep_header *pBase = &eep->baseEepHeader; | ||
474 | u8 num_ant_config; | ||
475 | |||
476 | num_ant_config = 1; | ||
477 | |||
478 | if (pBase->version >= 0x0E0D) | ||
479 | if (pModal->useAnt1) | ||
480 | num_ant_config += 1; | ||
481 | |||
482 | return num_ant_config; | ||
483 | } | ||
484 | |||
485 | static int | ||
486 | ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal_5416 *ahp, | ||
487 | struct ath9k_channel *chan, | ||
488 | u8 index, | ||
489 | u16 *config) | ||
490 | { | ||
491 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; | ||
492 | struct modal_eep_header *pModal = | ||
493 | &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
494 | struct base_eep_header *pBase = &eep->baseEepHeader; | ||
495 | |||
496 | switch (index) { | ||
497 | case 0: | ||
498 | *config = pModal->antCtrlCommon & 0xFFFF; | ||
499 | return 0; | ||
500 | case 1: | ||
501 | if (pBase->version >= 0x0E0D) { | ||
502 | if (pModal->useAnt1) { | ||
503 | *config = | ||
504 | ((pModal->antCtrlCommon & 0xFFFF0000) >> 16); | ||
505 | return 0; | ||
506 | } | ||
507 | } | ||
508 | break; | ||
509 | default: | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | return -EINVAL; | ||
514 | } | ||
515 | |||
516 | static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, | ||
517 | u32 off, | ||
518 | u16 *data) | ||
519 | { | ||
520 | if (ath9k_hw_use_flash(ah)) | ||
521 | return ath9k_hw_flash_read(ah, off, data); | ||
522 | else | ||
523 | return ath9k_hw_eeprom_read(ah, off, data); | ||
524 | } | ||
525 | |||
526 | static inline bool ath9k_hw_fill_eeprom(struct ath_hal *ah) | ||
527 | { | ||
528 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
529 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; | ||
530 | u16 *eep_data; | ||
531 | int addr, ar5416_eep_start_loc = 0; | ||
532 | |||
533 | if (!ath9k_hw_use_flash(ah)) { | ||
534 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
535 | "%s: Reading from EEPROM, not flash\n", __func__); | ||
536 | ar5416_eep_start_loc = 256; | ||
537 | } | ||
538 | if (AR_SREV_9100(ah)) | ||
539 | ar5416_eep_start_loc = 256; | ||
540 | |||
541 | eep_data = (u16 *) eep; | ||
542 | for (addr = 0; | ||
543 | addr < sizeof(struct ar5416_eeprom) / sizeof(u16); | ||
544 | addr++) { | ||
545 | if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, | ||
546 | eep_data)) { | ||
547 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
548 | "%s: Unable to read eeprom region \n", | ||
549 | __func__); | ||
550 | return false; | ||
551 | } | ||
552 | eep_data++; | ||
553 | } | ||
554 | return true; | ||
555 | } | ||
556 | |||
557 | /* XXX: Clean me up, make me more legible */ | ||
558 | static bool | ||
559 | ath9k_hw_eeprom_set_board_values(struct ath_hal *ah, | ||
560 | struct ath9k_channel *chan) | ||
561 | { | ||
562 | struct modal_eep_header *pModal; | ||
563 | int i, regChainOffset; | ||
564 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
565 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; | ||
566 | u8 txRxAttenLocal; | ||
567 | u16 ant_config; | ||
568 | |||
569 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
570 | |||
571 | txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; | ||
572 | |||
573 | ath9k_hw_get_eeprom_antenna_cfg(ahp, chan, 1, &ant_config); | ||
574 | REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config); | ||
575 | |||
576 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
577 | if (AR_SREV_9280(ah)) { | ||
578 | if (i >= 2) | ||
579 | break; | ||
580 | } | ||
581 | |||
582 | if (AR_SREV_5416_V20_OR_LATER(ah) && | ||
583 | (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) | ||
584 | && (i != 0)) | ||
585 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
586 | else | ||
587 | regChainOffset = i * 0x1000; | ||
588 | |||
589 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, | ||
590 | pModal->antCtrlChain[i]); | ||
591 | |||
592 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | ||
593 | (REG_READ(ah, | ||
594 | AR_PHY_TIMING_CTRL4(0) + | ||
595 | regChainOffset) & | ||
596 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | ||
597 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | ||
598 | SM(pModal->iqCalICh[i], | ||
599 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
600 | SM(pModal->iqCalQCh[i], | ||
601 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
602 | |||
603 | if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { | ||
604 | if ((eep->baseEepHeader.version & | ||
605 | AR5416_EEP_VER_MINOR_MASK) >= | ||
606 | AR5416_EEP_MINOR_VER_3) { | ||
607 | txRxAttenLocal = pModal->txRxAttenCh[i]; | ||
608 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
609 | REG_RMW_FIELD(ah, | ||
610 | AR_PHY_GAIN_2GHZ + | ||
611 | regChainOffset, | ||
612 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
613 | pModal-> | ||
614 | bswMargin[i]); | ||
615 | REG_RMW_FIELD(ah, | ||
616 | AR_PHY_GAIN_2GHZ + | ||
617 | regChainOffset, | ||
618 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, | ||
619 | pModal-> | ||
620 | bswAtten[i]); | ||
621 | REG_RMW_FIELD(ah, | ||
622 | AR_PHY_GAIN_2GHZ + | ||
623 | regChainOffset, | ||
624 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
625 | pModal-> | ||
626 | xatten2Margin[i]); | ||
627 | REG_RMW_FIELD(ah, | ||
628 | AR_PHY_GAIN_2GHZ + | ||
629 | regChainOffset, | ||
630 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | ||
631 | pModal-> | ||
632 | xatten2Db[i]); | ||
633 | } else { | ||
634 | REG_WRITE(ah, | ||
635 | AR_PHY_GAIN_2GHZ + | ||
636 | regChainOffset, | ||
637 | (REG_READ(ah, | ||
638 | AR_PHY_GAIN_2GHZ + | ||
639 | regChainOffset) & | ||
640 | ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | ||
641 | | SM(pModal-> | ||
642 | bswMargin[i], | ||
643 | AR_PHY_GAIN_2GHZ_BSW_MARGIN)); | ||
644 | REG_WRITE(ah, | ||
645 | AR_PHY_GAIN_2GHZ + | ||
646 | regChainOffset, | ||
647 | (REG_READ(ah, | ||
648 | AR_PHY_GAIN_2GHZ + | ||
649 | regChainOffset) & | ||
650 | ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | ||
651 | | SM(pModal->bswAtten[i], | ||
652 | AR_PHY_GAIN_2GHZ_BSW_ATTEN)); | ||
653 | } | ||
654 | } | ||
655 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
656 | REG_RMW_FIELD(ah, | ||
657 | AR_PHY_RXGAIN + | ||
658 | regChainOffset, | ||
659 | AR9280_PHY_RXGAIN_TXRX_ATTEN, | ||
660 | txRxAttenLocal); | ||
661 | REG_RMW_FIELD(ah, | ||
662 | AR_PHY_RXGAIN + | ||
663 | regChainOffset, | ||
664 | AR9280_PHY_RXGAIN_TXRX_MARGIN, | ||
665 | pModal->rxTxMarginCh[i]); | ||
666 | } else { | ||
667 | REG_WRITE(ah, | ||
668 | AR_PHY_RXGAIN + regChainOffset, | ||
669 | (REG_READ(ah, | ||
670 | AR_PHY_RXGAIN + | ||
671 | regChainOffset) & | ||
672 | ~AR_PHY_RXGAIN_TXRX_ATTEN) | | ||
673 | SM(txRxAttenLocal, | ||
674 | AR_PHY_RXGAIN_TXRX_ATTEN)); | ||
675 | REG_WRITE(ah, | ||
676 | AR_PHY_GAIN_2GHZ + | ||
677 | regChainOffset, | ||
678 | (REG_READ(ah, | ||
679 | AR_PHY_GAIN_2GHZ + | ||
680 | regChainOffset) & | ||
681 | ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | | ||
682 | SM(pModal->rxTxMarginCh[i], | ||
683 | AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); | ||
684 | } | ||
685 | } | ||
686 | } | ||
687 | |||
688 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
689 | if (IS_CHAN_2GHZ(chan)) { | ||
690 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, | ||
691 | AR_AN_RF2G1_CH0_OB, | ||
692 | AR_AN_RF2G1_CH0_OB_S, | ||
693 | pModal->ob); | ||
694 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, | ||
695 | AR_AN_RF2G1_CH0_DB, | ||
696 | AR_AN_RF2G1_CH0_DB_S, | ||
697 | pModal->db); | ||
698 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, | ||
699 | AR_AN_RF2G1_CH1_OB, | ||
700 | AR_AN_RF2G1_CH1_OB_S, | ||
701 | pModal->ob_ch1); | ||
702 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, | ||
703 | AR_AN_RF2G1_CH1_DB, | ||
704 | AR_AN_RF2G1_CH1_DB_S, | ||
705 | pModal->db_ch1); | ||
706 | } else { | ||
707 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, | ||
708 | AR_AN_RF5G1_CH0_OB5, | ||
709 | AR_AN_RF5G1_CH0_OB5_S, | ||
710 | pModal->ob); | ||
711 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, | ||
712 | AR_AN_RF5G1_CH0_DB5, | ||
713 | AR_AN_RF5G1_CH0_DB5_S, | ||
714 | pModal->db); | ||
715 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, | ||
716 | AR_AN_RF5G1_CH1_OB5, | ||
717 | AR_AN_RF5G1_CH1_OB5_S, | ||
718 | pModal->ob_ch1); | ||
719 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, | ||
720 | AR_AN_RF5G1_CH1_DB5, | ||
721 | AR_AN_RF5G1_CH1_DB5_S, | ||
722 | pModal->db_ch1); | ||
723 | } | ||
724 | ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, | ||
725 | AR_AN_TOP2_XPABIAS_LVL, | ||
726 | AR_AN_TOP2_XPABIAS_LVL_S, | ||
727 | pModal->xpaBiasLvl); | ||
728 | ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, | ||
729 | AR_AN_TOP2_LOCALBIAS, | ||
730 | AR_AN_TOP2_LOCALBIAS_S, | ||
731 | pModal->local_bias); | ||
732 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, "ForceXPAon: %d\n", | ||
733 | pModal->force_xpaon); | ||
734 | REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, | ||
735 | pModal->force_xpaon); | ||
736 | } | ||
737 | |||
738 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, | ||
739 | pModal->switchSettling); | ||
740 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, | ||
741 | pModal->adcDesiredSize); | ||
742 | |||
743 | if (!AR_SREV_9280_10_OR_LATER(ah)) | ||
744 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
745 | AR_PHY_DESIRED_SZ_PGA, | ||
746 | pModal->pgaDesiredSize); | ||
747 | |||
748 | REG_WRITE(ah, AR_PHY_RF_CTL4, | ||
749 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | ||
750 | | SM(pModal->txEndToXpaOff, | ||
751 | AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | ||
752 | | SM(pModal->txFrameToXpaOn, | ||
753 | AR_PHY_RF_CTL4_FRAME_XPAA_ON) | ||
754 | | SM(pModal->txFrameToXpaOn, | ||
755 | AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | ||
756 | |||
757 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, | ||
758 | pModal->txEndToRxOn); | ||
759 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
760 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, | ||
761 | pModal->thresh62); | ||
762 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, | ||
763 | AR_PHY_EXT_CCA0_THRESH62, | ||
764 | pModal->thresh62); | ||
765 | } else { | ||
766 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, | ||
767 | pModal->thresh62); | ||
768 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, | ||
769 | AR_PHY_EXT_CCA_THRESH62, | ||
770 | pModal->thresh62); | ||
771 | } | ||
772 | |||
773 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
774 | AR5416_EEP_MINOR_VER_2) { | ||
775 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | ||
776 | AR_PHY_TX_END_DATA_START, | ||
777 | pModal->txFrameToDataStart); | ||
778 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, | ||
779 | pModal->txFrameToPaOn); | ||
780 | } | ||
781 | |||
782 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
783 | AR5416_EEP_MINOR_VER_3) { | ||
784 | if (IS_CHAN_HT40(chan)) | ||
785 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
786 | AR_PHY_SETTLING_SWITCH, | ||
787 | pModal->swSettleHt40); | ||
788 | } | ||
789 | |||
790 | return true; | ||
791 | } | ||
792 | |||
793 | static inline int ath9k_hw_check_eeprom(struct ath_hal *ah) | ||
794 | { | ||
795 | u32 sum = 0, el; | ||
796 | u16 *eepdata; | ||
797 | int i; | ||
798 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
799 | bool need_swap = false; | ||
800 | struct ar5416_eeprom *eep = | ||
801 | (struct ar5416_eeprom *) &ahp->ah_eeprom; | ||
802 | |||
803 | if (!ath9k_hw_use_flash(ah)) { | ||
804 | u16 magic, magic2; | ||
805 | int addr; | ||
806 | |||
807 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, | ||
808 | &magic)) { | ||
809 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
810 | "%s: Reading Magic # failed\n", __func__); | ||
811 | return false; | ||
812 | } | ||
813 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "%s: Read Magic = 0x%04X\n", | ||
814 | __func__, magic); | ||
815 | |||
816 | if (magic != AR5416_EEPROM_MAGIC) { | ||
817 | magic2 = swab16(magic); | ||
818 | |||
819 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
820 | need_swap = true; | ||
821 | eepdata = (u16 *) (&ahp->ah_eeprom); | ||
822 | |||
823 | for (addr = 0; | ||
824 | addr < | ||
825 | sizeof(struct ar5416_eeprom) / | ||
826 | sizeof(u16); addr++) { | ||
827 | u16 temp; | ||
828 | |||
829 | temp = swab16(*eepdata); | ||
830 | *eepdata = temp; | ||
831 | eepdata++; | ||
832 | |||
833 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
834 | "0x%04X ", *eepdata); | ||
835 | if (((addr + 1) % 6) == 0) | ||
836 | DPRINTF(ah->ah_sc, | ||
837 | ATH_DBG_EEPROM, | ||
838 | "\n"); | ||
839 | } | ||
840 | } else { | ||
841 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
842 | "Invalid EEPROM Magic. " | ||
843 | "endianness missmatch.\n"); | ||
844 | return -EINVAL; | ||
845 | } | ||
846 | } | ||
847 | } | ||
848 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", | ||
849 | need_swap ? "True" : "False"); | ||
850 | |||
851 | if (need_swap) | ||
852 | el = swab16(ahp->ah_eeprom.baseEepHeader.length); | ||
853 | else | ||
854 | el = ahp->ah_eeprom.baseEepHeader.length; | ||
855 | |||
856 | if (el > sizeof(struct ar5416_eeprom)) | ||
857 | el = sizeof(struct ar5416_eeprom) / sizeof(u16); | ||
858 | else | ||
859 | el = el / sizeof(u16); | ||
860 | |||
861 | eepdata = (u16 *) (&ahp->ah_eeprom); | ||
862 | |||
863 | for (i = 0; i < el; i++) | ||
864 | sum ^= *eepdata++; | ||
865 | |||
866 | if (need_swap) { | ||
867 | u32 integer, j; | ||
868 | u16 word; | ||
869 | |||
870 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
871 | "EEPROM Endianness is not native.. Changing \n"); | ||
872 | |||
873 | word = swab16(eep->baseEepHeader.length); | ||
874 | eep->baseEepHeader.length = word; | ||
875 | |||
876 | word = swab16(eep->baseEepHeader.checksum); | ||
877 | eep->baseEepHeader.checksum = word; | ||
878 | |||
879 | word = swab16(eep->baseEepHeader.version); | ||
880 | eep->baseEepHeader.version = word; | ||
881 | |||
882 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
883 | eep->baseEepHeader.regDmn[0] = word; | ||
884 | |||
885 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
886 | eep->baseEepHeader.regDmn[1] = word; | ||
887 | |||
888 | word = swab16(eep->baseEepHeader.rfSilent); | ||
889 | eep->baseEepHeader.rfSilent = word; | ||
890 | |||
891 | word = swab16(eep->baseEepHeader.blueToothOptions); | ||
892 | eep->baseEepHeader.blueToothOptions = word; | ||
893 | |||
894 | word = swab16(eep->baseEepHeader.deviceCap); | ||
895 | eep->baseEepHeader.deviceCap = word; | ||
896 | |||
897 | for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { | ||
898 | struct modal_eep_header *pModal = | ||
899 | &eep->modalHeader[j]; | ||
900 | integer = swab32(pModal->antCtrlCommon); | ||
901 | pModal->antCtrlCommon = integer; | ||
902 | |||
903 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
904 | integer = swab32(pModal->antCtrlChain[i]); | ||
905 | pModal->antCtrlChain[i] = integer; | ||
906 | } | ||
907 | |||
908 | for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { | ||
909 | word = swab16(pModal->spurChans[i].spurChan); | ||
910 | pModal->spurChans[i].spurChan = word; | ||
911 | } | ||
912 | } | ||
913 | } | ||
914 | |||
915 | if (sum != 0xffff || ar5416_get_eep_ver(ahp) != AR5416_EEP_VER || | ||
916 | ar5416_get_eep_rev(ahp) < AR5416_EEP_NO_BACK_VER) { | ||
917 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
918 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
919 | sum, ar5416_get_eep_ver(ahp)); | ||
920 | return -EINVAL; | ||
921 | } | ||
922 | |||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | static bool ath9k_hw_chip_test(struct ath_hal *ah) | ||
927 | { | ||
928 | u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) }; | ||
929 | u32 regHold[2]; | ||
930 | u32 patternData[4] = { 0x55555555, | ||
931 | 0xaaaaaaaa, | ||
932 | 0x66666666, | ||
933 | 0x99999999 }; | ||
934 | int i, j; | ||
935 | |||
936 | for (i = 0; i < 2; i++) { | ||
937 | u32 addr = regAddr[i]; | ||
938 | u32 wrData, rdData; | ||
939 | |||
940 | regHold[i] = REG_READ(ah, addr); | ||
941 | for (j = 0; j < 0x100; j++) { | ||
942 | wrData = (j << 16) | j; | ||
943 | REG_WRITE(ah, addr, wrData); | ||
944 | rdData = REG_READ(ah, addr); | ||
945 | if (rdData != wrData) { | ||
946 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
947 | "%s: address test failed " | ||
948 | "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", | ||
949 | __func__, addr, wrData, rdData); | ||
950 | return false; | ||
951 | } | ||
952 | } | ||
953 | for (j = 0; j < 4; j++) { | ||
954 | wrData = patternData[j]; | ||
955 | REG_WRITE(ah, addr, wrData); | ||
956 | rdData = REG_READ(ah, addr); | ||
957 | if (wrData != rdData) { | ||
958 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
959 | "%s: address test failed " | ||
960 | "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", | ||
961 | __func__, addr, wrData, rdData); | ||
962 | return false; | ||
963 | } | ||
964 | } | ||
965 | REG_WRITE(ah, regAddr[i], regHold[i]); | ||
966 | } | ||
967 | udelay(100); | ||
968 | return true; | ||
969 | } | ||
970 | |||
971 | u32 ath9k_hw_getrxfilter(struct ath_hal *ah) | ||
972 | { | ||
973 | u32 bits = REG_READ(ah, AR_RX_FILTER); | ||
974 | u32 phybits = REG_READ(ah, AR_PHY_ERR); | ||
975 | |||
976 | if (phybits & AR_PHY_ERR_RADAR) | ||
977 | bits |= ATH9K_RX_FILTER_PHYRADAR; | ||
978 | if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) | ||
979 | bits |= ATH9K_RX_FILTER_PHYERR; | ||
980 | return bits; | ||
981 | } | ||
982 | |||
983 | void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits) | ||
984 | { | ||
985 | u32 phybits; | ||
986 | |||
987 | REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR); | ||
988 | phybits = 0; | ||
989 | if (bits & ATH9K_RX_FILTER_PHYRADAR) | ||
990 | phybits |= AR_PHY_ERR_RADAR; | ||
991 | if (bits & ATH9K_RX_FILTER_PHYERR) | ||
992 | phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; | ||
993 | REG_WRITE(ah, AR_PHY_ERR, phybits); | ||
994 | |||
995 | if (phybits) | ||
996 | REG_WRITE(ah, AR_RXCFG, | ||
997 | REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); | ||
998 | else | ||
999 | REG_WRITE(ah, AR_RXCFG, | ||
1000 | REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); | ||
1001 | } | ||
1002 | |||
1003 | bool ath9k_hw_setcapability(struct ath_hal *ah, | ||
1004 | enum hal_capability_type type, | ||
1005 | u32 capability, | ||
1006 | u32 setting, | ||
1007 | int *status) | ||
1008 | { | ||
1009 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
1010 | u32 v; | ||
1011 | |||
1012 | switch (type) { | ||
1013 | case HAL_CAP_TKIP_MIC: | ||
1014 | if (setting) | ||
1015 | ahp->ah_staId1Defaults |= | ||
1016 | AR_STA_ID1_CRPT_MIC_ENABLE; | ||
1017 | else | ||
1018 | ahp->ah_staId1Defaults &= | ||
1019 | ~AR_STA_ID1_CRPT_MIC_ENABLE; | ||
1020 | return true; | ||
1021 | case HAL_CAP_DIVERSITY: | ||
1022 | v = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
1023 | if (setting) | ||
1024 | v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; | ||
1025 | else | ||
1026 | v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; | ||
1027 | REG_WRITE(ah, AR_PHY_CCK_DETECT, v); | ||
1028 | return true; | ||
1029 | case HAL_CAP_MCAST_KEYSRCH: | ||
1030 | if (setting) | ||
1031 | ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH; | ||
1032 | else | ||
1033 | ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH; | ||
1034 | return true; | ||
1035 | case HAL_CAP_TSF_ADJUST: | ||
1036 | if (setting) | ||
1037 | ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF; | ||
1038 | else | ||
1039 | ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF; | ||
1040 | return true; | ||
1041 | default: | ||
1042 | return false; | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1046 | void ath9k_hw_dmaRegDump(struct ath_hal *ah) | ||
1047 | { | ||
1048 | u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; | ||
1049 | int qcuOffset = 0, dcuOffset = 0; | ||
1050 | u32 *qcuBase = &val[0], *dcuBase = &val[4]; | ||
1051 | int i; | ||
1052 | |||
1053 | REG_WRITE(ah, AR_MACMISC, | ||
1054 | ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | | ||
1055 | (AR_MACMISC_MISC_OBS_BUS_1 << | ||
1056 | AR_MACMISC_MISC_OBS_BUS_MSB_S))); | ||
1057 | |||
1058 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "Raw DMA Debug values:\n"); | ||
1059 | for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { | ||
1060 | if (i % 4 == 0) | ||
1061 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n"); | ||
1062 | |||
1063 | val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32))); | ||
1064 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "%d: %08x ", i, val[i]); | ||
1065 | } | ||
1066 | |||
1067 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n\n"); | ||
1068 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
1069 | "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); | ||
1070 | |||
1071 | for (i = 0; i < ATH9K_NUM_QUEUES; | ||
1072 | i++, qcuOffset += 4, dcuOffset += 5) { | ||
1073 | if (i == 8) { | ||
1074 | qcuOffset = 0; | ||
1075 | qcuBase++; | ||
1076 | } | ||
1077 | |||
1078 | if (i == 6) { | ||
1079 | dcuOffset = 0; | ||
1080 | dcuBase++; | ||
1081 | } | ||
1082 | |||
1083 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
1084 | "%2d %2x %1x %2x %2x\n", | ||
1085 | i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, | ||
1086 | (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + | ||
1087 | 3), | ||
1088 | val[2] & (0x7 << (i * 3)) >> (i * 3), | ||
1089 | (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); | ||
1090 | } | ||
1091 | |||
1092 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n"); | ||
1093 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
1094 | "qcu_stitch state: %2x qcu_fetch state: %2x\n", | ||
1095 | (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); | ||
1096 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
1097 | "qcu_complete state: %2x dcu_complete state: %2x\n", | ||
1098 | (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); | ||
1099 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
1100 | "dcu_arb state: %2x dcu_fp state: %2x\n", | ||
1101 | (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); | ||
1102 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
1103 | "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", | ||
1104 | (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); | ||
1105 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
1106 | "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", | ||
1107 | (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); | ||
1108 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
1109 | "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", | ||
1110 | (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); | ||
1111 | |||
1112 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "pcu observe 0x%x \n", | ||
1113 | REG_READ(ah, AR_OBS_BUS_1)); | ||
1114 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
1115 | "AR_CR 0x%x \n", REG_READ(ah, AR_CR)); | ||
1116 | } | ||
1117 | |||
1118 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah, | ||
1119 | u32 *rxc_pcnt, | ||
1120 | u32 *rxf_pcnt, | ||
1121 | u32 *txf_pcnt) | ||
1122 | { | ||
1123 | static u32 cycles, rx_clear, rx_frame, tx_frame; | ||
1124 | u32 good = 1; | ||
1125 | |||
1126 | u32 rc = REG_READ(ah, AR_RCCNT); | ||
1127 | u32 rf = REG_READ(ah, AR_RFCNT); | ||
1128 | u32 tf = REG_READ(ah, AR_TFCNT); | ||
1129 | u32 cc = REG_READ(ah, AR_CCCNT); | ||
1130 | |||
1131 | if (cycles == 0 || cycles > cc) { | ||
1132 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
1133 | "%s: cycle counter wrap. ExtBusy = 0\n", | ||
1134 | __func__); | ||
1135 | good = 0; | ||
1136 | } else { | ||
1137 | u32 cc_d = cc - cycles; | ||
1138 | u32 rc_d = rc - rx_clear; | ||
1139 | u32 rf_d = rf - rx_frame; | ||
1140 | u32 tf_d = tf - tx_frame; | ||
1141 | |||
1142 | if (cc_d != 0) { | ||
1143 | *rxc_pcnt = rc_d * 100 / cc_d; | ||
1144 | *rxf_pcnt = rf_d * 100 / cc_d; | ||
1145 | *txf_pcnt = tf_d * 100 / cc_d; | ||
1146 | } else { | ||
1147 | good = 0; | ||
1148 | } | ||
1149 | } | ||
1150 | |||
1151 | cycles = cc; | ||
1152 | rx_frame = rf; | ||
1153 | rx_clear = rc; | ||
1154 | tx_frame = tf; | ||
1155 | |||
1156 | return good; | ||
1157 | } | ||
1158 | |||
1159 | void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode) | ||
1160 | { | ||
1161 | u32 macmode; | ||
1162 | |||
1163 | if (mode == ATH9K_HT_MACMODE_2040 && | ||
1164 | !ah->ah_config.ath_hal_cwmIgnoreExtCCA) | ||
1165 | macmode = AR_2040_JOINED_RX_CLEAR; | ||
1166 | else | ||
1167 | macmode = 0; | ||
1168 | |||
1169 | REG_WRITE(ah, AR_2040_MODE, macmode); | ||
1170 | } | ||
1171 | |||
1172 | static void ath9k_hw_mark_phy_inactive(struct ath_hal *ah) | ||
1173 | { | ||
1174 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | ||
1175 | } | ||
1176 | |||
1177 | |||
1178 | static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, | ||
1179 | struct ath_softc *sc, | ||
1180 | void __iomem *mem, | ||
1181 | int *status) | ||
1182 | { | ||
1183 | static const u8 defbssidmask[ETH_ALEN] = | ||
1184 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
1185 | struct ath_hal_5416 *ahp; | ||
1186 | struct ath_hal *ah; | ||
1187 | |||
1188 | ahp = kzalloc(sizeof(struct ath_hal_5416), GFP_KERNEL); | ||
1189 | if (ahp == NULL) { | ||
1190 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1191 | "%s: cannot allocate memory for state block\n", | ||
1192 | __func__); | ||
1193 | *status = -ENOMEM; | ||
1194 | return NULL; | ||
1195 | } | ||
1196 | |||
1197 | ah = &ahp->ah; | ||
1198 | |||
1199 | memcpy(&ahp->ah, &ar5416hal, sizeof(struct ath_hal)); | ||
1200 | |||
1201 | ah->ah_sc = sc; | ||
1202 | ah->ah_sh = mem; | ||
1203 | |||
1204 | ah->ah_devid = devid; | ||
1205 | ah->ah_subvendorid = 0; | ||
1206 | |||
1207 | ah->ah_flags = 0; | ||
1208 | if ((devid == AR5416_AR9100_DEVID)) | ||
1209 | ah->ah_macVersion = AR_SREV_VERSION_9100; | ||
1210 | if (!AR_SREV_9100(ah)) | ||
1211 | ah->ah_flags = AH_USE_EEPROM; | ||
1212 | |||
1213 | ah->ah_powerLimit = MAX_RATE_POWER; | ||
1214 | ah->ah_tpScale = ATH9K_TP_SCALE_MAX; | ||
1215 | |||
1216 | ahp->ah_atimWindow = 0; | ||
1217 | ahp->ah_diversityControl = ah->ah_config.ath_hal_diversityControl; | ||
1218 | ahp->ah_antennaSwitchSwap = | ||
1219 | ah->ah_config.ath_hal_antennaSwitchSwap; | ||
1220 | |||
1221 | ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE; | ||
1222 | ahp->ah_beaconInterval = 100; | ||
1223 | ahp->ah_enable32kHzClock = DONT_USE_32KHZ; | ||
1224 | ahp->ah_slottime = (u32) -1; | ||
1225 | ahp->ah_acktimeout = (u32) -1; | ||
1226 | ahp->ah_ctstimeout = (u32) -1; | ||
1227 | ahp->ah_globaltxtimeout = (u32) -1; | ||
1228 | memcpy(&ahp->ah_bssidmask, defbssidmask, ETH_ALEN); | ||
1229 | |||
1230 | ahp->ah_gBeaconRate = 0; | ||
1231 | |||
1232 | return ahp; | ||
1233 | } | ||
1234 | |||
1235 | static int ath9k_hw_eeprom_attach(struct ath_hal *ah) | ||
1236 | { | ||
1237 | int status; | ||
1238 | |||
1239 | if (ath9k_hw_use_flash(ah)) | ||
1240 | ath9k_hw_flash_map(ah); | ||
1241 | |||
1242 | if (!ath9k_hw_fill_eeprom(ah)) | ||
1243 | return -EIO; | ||
1244 | |||
1245 | status = ath9k_hw_check_eeprom(ah); | ||
1246 | |||
1247 | return status; | ||
1248 | } | ||
1249 | |||
1250 | u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp, | ||
1251 | enum eeprom_param param) | ||
1252 | { | ||
1253 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; | ||
1254 | struct modal_eep_header *pModal = eep->modalHeader; | ||
1255 | struct base_eep_header *pBase = &eep->baseEepHeader; | ||
1256 | |||
1257 | switch (param) { | ||
1258 | case EEP_NFTHRESH_5: | ||
1259 | return -pModal[0].noiseFloorThreshCh[0]; | ||
1260 | case EEP_NFTHRESH_2: | ||
1261 | return -pModal[1].noiseFloorThreshCh[0]; | ||
1262 | case AR_EEPROM_MAC(0): | ||
1263 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | ||
1264 | case AR_EEPROM_MAC(1): | ||
1265 | return pBase->macAddr[2] << 8 | pBase->macAddr[3]; | ||
1266 | case AR_EEPROM_MAC(2): | ||
1267 | return pBase->macAddr[4] << 8 | pBase->macAddr[5]; | ||
1268 | case EEP_REG_0: | ||
1269 | return pBase->regDmn[0]; | ||
1270 | case EEP_REG_1: | ||
1271 | return pBase->regDmn[1]; | ||
1272 | case EEP_OP_CAP: | ||
1273 | return pBase->deviceCap; | ||
1274 | case EEP_OP_MODE: | ||
1275 | return pBase->opCapFlags; | ||
1276 | case EEP_RF_SILENT: | ||
1277 | return pBase->rfSilent; | ||
1278 | case EEP_OB_5: | ||
1279 | return pModal[0].ob; | ||
1280 | case EEP_DB_5: | ||
1281 | return pModal[0].db; | ||
1282 | case EEP_OB_2: | ||
1283 | return pModal[1].ob; | ||
1284 | case EEP_DB_2: | ||
1285 | return pModal[1].db; | ||
1286 | case EEP_MINOR_REV: | ||
1287 | return pBase->version & AR5416_EEP_VER_MINOR_MASK; | ||
1288 | case EEP_TX_MASK: | ||
1289 | return pBase->txMask; | ||
1290 | case EEP_RX_MASK: | ||
1291 | return pBase->rxMask; | ||
1292 | default: | ||
1293 | return 0; | ||
1294 | } | ||
1295 | } | ||
1296 | |||
1297 | static inline int ath9k_hw_get_radiorev(struct ath_hal *ah) | ||
1298 | { | ||
1299 | u32 val; | ||
1300 | int i; | ||
1301 | |||
1302 | REG_WRITE(ah, AR_PHY(0x36), 0x00007058); | ||
1303 | for (i = 0; i < 8; i++) | ||
1304 | REG_WRITE(ah, AR_PHY(0x20), 0x00010000); | ||
1305 | val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; | ||
1306 | val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); | ||
1307 | return ath9k_hw_reverse_bits(val, 8); | ||
1308 | } | ||
1309 | |||
1310 | static inline int ath9k_hw_init_macaddr(struct ath_hal *ah) | ||
1311 | { | ||
1312 | u32 sum; | ||
1313 | int i; | ||
1314 | u16 eeval; | ||
1315 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
1316 | DECLARE_MAC_BUF(mac); | ||
1317 | |||
1318 | sum = 0; | ||
1319 | for (i = 0; i < 3; i++) { | ||
1320 | eeval = ath9k_hw_get_eeprom(ahp, AR_EEPROM_MAC(i)); | ||
1321 | sum += eeval; | ||
1322 | ahp->ah_macaddr[2 * i] = eeval >> 8; | ||
1323 | ahp->ah_macaddr[2 * i + 1] = eeval & 0xff; | ||
1324 | } | ||
1325 | if (sum == 0 || sum == 0xffff * 3) { | ||
1326 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1327 | "%s: mac address read failed: %s\n", __func__, | ||
1328 | print_mac(mac, ahp->ah_macaddr)); | ||
1329 | return -EADDRNOTAVAIL; | ||
1330 | } | ||
1331 | |||
1332 | return 0; | ||
1333 | } | ||
1334 | |||
1335 | static inline int16_t ath9k_hw_interpolate(u16 target, | ||
1336 | u16 srcLeft, | ||
1337 | u16 srcRight, | ||
1338 | int16_t targetLeft, | ||
1339 | int16_t targetRight) | ||
1340 | { | ||
1341 | int16_t rv; | ||
1342 | |||
1343 | if (srcRight == srcLeft) { | ||
1344 | rv = targetLeft; | ||
1345 | } else { | ||
1346 | rv = (int16_t) (((target - srcLeft) * targetRight + | ||
1347 | (srcRight - target) * targetLeft) / | ||
1348 | (srcRight - srcLeft)); | ||
1349 | } | ||
1350 | return rv; | ||
1351 | } | ||
1352 | |||
1353 | static inline u16 ath9k_hw_fbin2freq(u8 fbin, | ||
1354 | bool is2GHz) | ||
1355 | { | ||
1356 | |||
1357 | if (fbin == AR5416_BCHAN_UNUSED) | ||
1358 | return fbin; | ||
1359 | |||
1360 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | ||
1361 | } | ||
1362 | |||
1363 | static u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, | ||
1364 | u16 i, | ||
1365 | bool is2GHz) | ||
1366 | { | ||
1367 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
1368 | struct ar5416_eeprom *eep = | ||
1369 | (struct ar5416_eeprom *) &ahp->ah_eeprom; | ||
1370 | u16 spur_val = AR_NO_SPUR; | ||
1371 | |||
1372 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1373 | "Getting spur idx %d is2Ghz. %d val %x\n", | ||
1374 | i, is2GHz, ah->ah_config.ath_hal_spurChans[i][is2GHz]); | ||
1375 | |||
1376 | switch (ah->ah_config.ath_hal_spurMode) { | ||
1377 | case SPUR_DISABLE: | ||
1378 | break; | ||
1379 | case SPUR_ENABLE_IOCTL: | ||
1380 | spur_val = ah->ah_config.ath_hal_spurChans[i][is2GHz]; | ||
1381 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1382 | "Getting spur val from new loc. %d\n", spur_val); | ||
1383 | break; | ||
1384 | case SPUR_ENABLE_EEPROM: | ||
1385 | spur_val = eep->modalHeader[is2GHz].spurChans[i].spurChan; | ||
1386 | break; | ||
1387 | |||
1388 | } | ||
1389 | return spur_val; | ||
1390 | } | ||
1391 | |||
1392 | static inline int ath9k_hw_rfattach(struct ath_hal *ah) | ||
1393 | { | ||
1394 | bool rfStatus = false; | ||
1395 | int ecode = 0; | ||
1396 | |||
1397 | rfStatus = ath9k_hw_init_rf(ah, &ecode); | ||
1398 | if (!rfStatus) { | ||
1399 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
1400 | "%s: RF setup failed, status %u\n", __func__, | ||
1401 | ecode); | ||
1402 | return ecode; | ||
1403 | } | ||
1404 | |||
1405 | return 0; | ||
1406 | } | ||
1407 | |||
1408 | static int ath9k_hw_rf_claim(struct ath_hal *ah) | ||
1409 | { | ||
1410 | u32 val; | ||
1411 | |||
1412 | REG_WRITE(ah, AR_PHY(0), 0x00000007); | ||
1413 | |||
1414 | val = ath9k_hw_get_radiorev(ah); | ||
1415 | switch (val & AR_RADIO_SREV_MAJOR) { | ||
1416 | case 0: | ||
1417 | val = AR_RAD5133_SREV_MAJOR; | ||
1418 | break; | ||
1419 | case AR_RAD5133_SREV_MAJOR: | ||
1420 | case AR_RAD5122_SREV_MAJOR: | ||
1421 | case AR_RAD2133_SREV_MAJOR: | ||
1422 | case AR_RAD2122_SREV_MAJOR: | ||
1423 | break; | ||
1424 | default: | ||
1425 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
1426 | "%s: 5G Radio Chip Rev 0x%02X is not " | ||
1427 | "supported by this driver\n", | ||
1428 | __func__, ah->ah_analog5GhzRev); | ||
1429 | return -EOPNOTSUPP; | ||
1430 | } | ||
1431 | |||
1432 | ah->ah_analog5GhzRev = val; | ||
1433 | |||
1434 | return 0; | ||
1435 | } | ||
1436 | |||
1437 | static inline void ath9k_hw_init_pll(struct ath_hal *ah, | ||
1438 | struct ath9k_channel *chan) | ||
1439 | { | ||
1440 | u32 pll; | ||
1441 | |||
1442 | if (AR_SREV_9100(ah)) { | ||
1443 | if (chan && IS_CHAN_5GHZ(chan)) | ||
1444 | pll = 0x1450; | ||
1445 | else | ||
1446 | pll = 0x1458; | ||
1447 | } else { | ||
1448 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1449 | pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); | ||
1450 | |||
1451 | if (chan && IS_CHAN_HALF_RATE(chan)) | ||
1452 | pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); | ||
1453 | else if (chan && IS_CHAN_QUARTER_RATE(chan)) | ||
1454 | pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); | ||
1455 | |||
1456 | if (chan && IS_CHAN_5GHZ(chan)) { | ||
1457 | pll |= SM(0x28, AR_RTC_9160_PLL_DIV); | ||
1458 | |||
1459 | |||
1460 | if (AR_SREV_9280_20(ah)) { | ||
1461 | if (((chan->channel % 20) == 0) | ||
1462 | || ((chan->channel % 10) == 0)) | ||
1463 | pll = 0x2850; | ||
1464 | else | ||
1465 | pll = 0x142c; | ||
1466 | } | ||
1467 | } else { | ||
1468 | pll |= SM(0x2c, AR_RTC_9160_PLL_DIV); | ||
1469 | } | ||
1470 | |||
1471 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
1472 | |||
1473 | pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); | ||
1474 | |||
1475 | if (chan && IS_CHAN_HALF_RATE(chan)) | ||
1476 | pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); | ||
1477 | else if (chan && IS_CHAN_QUARTER_RATE(chan)) | ||
1478 | pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); | ||
1479 | |||
1480 | if (chan && IS_CHAN_5GHZ(chan)) | ||
1481 | pll |= SM(0x50, AR_RTC_9160_PLL_DIV); | ||
1482 | else | ||
1483 | pll |= SM(0x58, AR_RTC_9160_PLL_DIV); | ||
1484 | } else { | ||
1485 | pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; | ||
1486 | |||
1487 | if (chan && IS_CHAN_HALF_RATE(chan)) | ||
1488 | pll |= SM(0x1, AR_RTC_PLL_CLKSEL); | ||
1489 | else if (chan && IS_CHAN_QUARTER_RATE(chan)) | ||
1490 | pll |= SM(0x2, AR_RTC_PLL_CLKSEL); | ||
1491 | |||
1492 | if (chan && IS_CHAN_5GHZ(chan)) | ||
1493 | pll |= SM(0xa, AR_RTC_PLL_DIV); | ||
1494 | else | ||
1495 | pll |= SM(0xb, AR_RTC_PLL_DIV); | ||
1496 | } | ||
1497 | } | ||
1498 | REG_WRITE(ah, (u16) (AR_RTC_PLL_CONTROL), pll); | ||
1499 | |||
1500 | udelay(RTC_PLL_SETTLE_DELAY); | ||
1501 | |||
1502 | REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); | ||
1503 | } | ||
1504 | |||
1505 | static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan, | ||
1506 | enum ath9k_ht_macmode macmode) | ||
1507 | { | ||
1508 | u32 phymode; | ||
1509 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
1510 | |||
1511 | phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 | ||
1512 | | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH; | ||
1513 | |||
1514 | if (IS_CHAN_HT40(chan)) { | ||
1515 | phymode |= AR_PHY_FC_DYN2040_EN; | ||
1516 | |||
1517 | if ((chan->chanmode == CHANNEL_A_HT40PLUS) || | ||
1518 | (chan->chanmode == CHANNEL_G_HT40PLUS)) | ||
1519 | phymode |= AR_PHY_FC_DYN2040_PRI_CH; | ||
1520 | |||
1521 | if (ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_25) | ||
1522 | phymode |= AR_PHY_FC_DYN2040_EXT_CH; | ||
1523 | } | ||
1524 | REG_WRITE(ah, AR_PHY_TURBO, phymode); | ||
1525 | |||
1526 | ath9k_hw_set11nmac2040(ah, macmode); | ||
1527 | |||
1528 | REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); | ||
1529 | REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); | ||
1530 | } | ||
1531 | |||
1532 | static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode) | ||
1533 | { | ||
1534 | u32 val; | ||
1535 | |||
1536 | val = REG_READ(ah, AR_STA_ID1); | ||
1537 | val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); | ||
1538 | switch (opmode) { | ||
1539 | case ATH9K_M_HOSTAP: | ||
1540 | REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP | ||
1541 | | AR_STA_ID1_KSRCH_MODE); | ||
1542 | REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); | ||
1543 | break; | ||
1544 | case ATH9K_M_IBSS: | ||
1545 | REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC | ||
1546 | | AR_STA_ID1_KSRCH_MODE); | ||
1547 | REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); | ||
1548 | break; | ||
1549 | case ATH9K_M_STA: | ||
1550 | case ATH9K_M_MONITOR: | ||
1551 | REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); | ||
1552 | break; | ||
1553 | } | ||
1554 | } | ||
1555 | |||
1556 | static inline void | ||
1557 | ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan) | ||
1558 | { | ||
1559 | u32 rfMode = 0; | ||
1560 | |||
1561 | if (chan == NULL) | ||
1562 | return; | ||
1563 | |||
1564 | rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) | ||
1565 | ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; | ||
1566 | |||
1567 | if (!AR_SREV_9280_10_OR_LATER(ah)) | ||
1568 | rfMode |= (IS_CHAN_5GHZ(chan)) ? AR_PHY_MODE_RF5GHZ : | ||
1569 | AR_PHY_MODE_RF2GHZ; | ||
1570 | |||
1571 | if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) | ||
1572 | rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); | ||
1573 | |||
1574 | REG_WRITE(ah, AR_PHY_MODE, rfMode); | ||
1575 | } | ||
1576 | |||
1577 | static bool ath9k_hw_set_reset(struct ath_hal *ah, int type) | ||
1578 | { | ||
1579 | u32 rst_flags; | ||
1580 | u32 tmpReg; | ||
1581 | |||
1582 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | | ||
1583 | AR_RTC_FORCE_WAKE_ON_INT); | ||
1584 | |||
1585 | if (AR_SREV_9100(ah)) { | ||
1586 | rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD | | ||
1587 | AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET; | ||
1588 | } else { | ||
1589 | tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE); | ||
1590 | if (tmpReg & | ||
1591 | (AR_INTR_SYNC_LOCAL_TIMEOUT | | ||
1592 | AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { | ||
1593 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); | ||
1594 | REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); | ||
1595 | } else { | ||
1596 | REG_WRITE(ah, AR_RC, AR_RC_AHB); | ||
1597 | } | ||
1598 | |||
1599 | rst_flags = AR_RTC_RC_MAC_WARM; | ||
1600 | if (type == ATH9K_RESET_COLD) | ||
1601 | rst_flags |= AR_RTC_RC_MAC_COLD; | ||
1602 | } | ||
1603 | |||
1604 | REG_WRITE(ah, (u16) (AR_RTC_RC), rst_flags); | ||
1605 | udelay(50); | ||
1606 | |||
1607 | REG_WRITE(ah, (u16) (AR_RTC_RC), 0); | ||
1608 | if (!ath9k_hw_wait(ah, (u16) (AR_RTC_RC), AR_RTC_RC_M, 0)) { | ||
1609 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
1610 | "%s: RTC stuck in MAC reset\n", | ||
1611 | __func__); | ||
1612 | return false; | ||
1613 | } | ||
1614 | |||
1615 | if (!AR_SREV_9100(ah)) | ||
1616 | REG_WRITE(ah, AR_RC, 0); | ||
1617 | |||
1618 | ath9k_hw_init_pll(ah, NULL); | ||
1619 | |||
1620 | if (AR_SREV_9100(ah)) | ||
1621 | udelay(50); | ||
1622 | |||
1623 | return true; | ||
1624 | } | ||
1625 | |||
1626 | static inline bool ath9k_hw_set_reset_power_on(struct ath_hal *ah) | ||
1627 | { | ||
1628 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | | ||
1629 | AR_RTC_FORCE_WAKE_ON_INT); | ||
1630 | |||
1631 | REG_WRITE(ah, (u16) (AR_RTC_RESET), 0); | ||
1632 | REG_WRITE(ah, (u16) (AR_RTC_RESET), 1); | ||
1633 | |||
1634 | if (!ath9k_hw_wait(ah, | ||
1635 | AR_RTC_STATUS, | ||
1636 | AR_RTC_STATUS_M, | ||
1637 | AR_RTC_STATUS_ON)) { | ||
1638 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: RTC not waking up\n", | ||
1639 | __func__); | ||
1640 | return false; | ||
1641 | } | ||
1642 | |||
1643 | ath9k_hw_read_revisions(ah); | ||
1644 | |||
1645 | return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); | ||
1646 | } | ||
1647 | |||
1648 | static bool ath9k_hw_set_reset_reg(struct ath_hal *ah, | ||
1649 | u32 type) | ||
1650 | { | ||
1651 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, | ||
1652 | AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); | ||
1653 | |||
1654 | switch (type) { | ||
1655 | case ATH9K_RESET_POWER_ON: | ||
1656 | return ath9k_hw_set_reset_power_on(ah); | ||
1657 | break; | ||
1658 | case ATH9K_RESET_WARM: | ||
1659 | case ATH9K_RESET_COLD: | ||
1660 | return ath9k_hw_set_reset(ah, type); | ||
1661 | break; | ||
1662 | default: | ||
1663 | return false; | ||
1664 | } | ||
1665 | } | ||
1666 | |||
1667 | static inline | ||
1668 | struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah, | ||
1669 | struct ath9k_channel *chan) | ||
1670 | { | ||
1671 | if (!(IS_CHAN_2GHZ(chan) ^ IS_CHAN_5GHZ(chan))) { | ||
1672 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
1673 | "%s: invalid channel %u/0x%x; not marked as " | ||
1674 | "2GHz or 5GHz\n", __func__, chan->channel, | ||
1675 | chan->channelFlags); | ||
1676 | return NULL; | ||
1677 | } | ||
1678 | |||
1679 | if (!IS_CHAN_OFDM(chan) && | ||
1680 | !IS_CHAN_CCK(chan) && | ||
1681 | !IS_CHAN_HT20(chan) && | ||
1682 | !IS_CHAN_HT40(chan)) { | ||
1683 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
1684 | "%s: invalid channel %u/0x%x; not marked as " | ||
1685 | "OFDM or CCK or HT20 or HT40PLUS or HT40MINUS\n", | ||
1686 | __func__, chan->channel, chan->channelFlags); | ||
1687 | return NULL; | ||
1688 | } | ||
1689 | |||
1690 | return ath9k_regd_check_channel(ah, chan); | ||
1691 | } | ||
1692 | |||
1693 | static inline bool | ||
1694 | ath9k_hw_get_lower_upper_index(u8 target, | ||
1695 | u8 *pList, | ||
1696 | u16 listSize, | ||
1697 | u16 *indexL, | ||
1698 | u16 *indexR) | ||
1699 | { | ||
1700 | u16 i; | ||
1701 | |||
1702 | if (target <= pList[0]) { | ||
1703 | *indexL = *indexR = 0; | ||
1704 | return true; | ||
1705 | } | ||
1706 | if (target >= pList[listSize - 1]) { | ||
1707 | *indexL = *indexR = (u16) (listSize - 1); | ||
1708 | return true; | ||
1709 | } | ||
1710 | |||
1711 | for (i = 0; i < listSize - 1; i++) { | ||
1712 | if (pList[i] == target) { | ||
1713 | *indexL = *indexR = i; | ||
1714 | return true; | ||
1715 | } | ||
1716 | if (target < pList[i + 1]) { | ||
1717 | *indexL = i; | ||
1718 | *indexR = (u16) (i + 1); | ||
1719 | return false; | ||
1720 | } | ||
1721 | } | ||
1722 | return false; | ||
1723 | } | ||
1724 | |||
1725 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | ||
1726 | { | ||
1727 | int16_t nfval; | ||
1728 | int16_t sort[ATH9K_NF_CAL_HIST_MAX]; | ||
1729 | int i, j; | ||
1730 | |||
1731 | for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++) | ||
1732 | sort[i] = nfCalBuffer[i]; | ||
1733 | |||
1734 | for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) { | ||
1735 | for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) { | ||
1736 | if (sort[j] > sort[j - 1]) { | ||
1737 | nfval = sort[j]; | ||
1738 | sort[j] = sort[j - 1]; | ||
1739 | sort[j - 1] = nfval; | ||
1740 | } | ||
1741 | } | ||
1742 | } | ||
1743 | nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1]; | ||
1744 | |||
1745 | return nfval; | ||
1746 | } | ||
1747 | |||
1748 | static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | ||
1749 | int16_t *nfarray) | ||
1750 | { | ||
1751 | int i; | ||
1752 | |||
1753 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
1754 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; | ||
1755 | |||
1756 | if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) | ||
1757 | h[i].currIndex = 0; | ||
1758 | |||
1759 | if (h[i].invalidNFcount > 0) { | ||
1760 | if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE | ||
1761 | || nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) { | ||
1762 | h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX; | ||
1763 | } else { | ||
1764 | h[i].invalidNFcount--; | ||
1765 | h[i].privNF = nfarray[i]; | ||
1766 | } | ||
1767 | } else { | ||
1768 | h[i].privNF = | ||
1769 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); | ||
1770 | } | ||
1771 | } | ||
1772 | return; | ||
1773 | } | ||
1774 | |||
1775 | static void ar5416GetNoiseFloor(struct ath_hal *ah, | ||
1776 | int16_t nfarray[NUM_NF_READINGS]) | ||
1777 | { | ||
1778 | int16_t nf; | ||
1779 | |||
1780 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
1781 | nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); | ||
1782 | else | ||
1783 | nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); | ||
1784 | |||
1785 | if (nf & 0x100) | ||
1786 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1787 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
1788 | "NF calibrated [ctl] [chain 0] is %d\n", nf); | ||
1789 | nfarray[0] = nf; | ||
1790 | |||
1791 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
1792 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), | ||
1793 | AR9280_PHY_CH1_MINCCA_PWR); | ||
1794 | else | ||
1795 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), | ||
1796 | AR_PHY_CH1_MINCCA_PWR); | ||
1797 | |||
1798 | if (nf & 0x100) | ||
1799 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1800 | DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, | ||
1801 | "NF calibrated [ctl] [chain 1] is %d\n", nf); | ||
1802 | nfarray[1] = nf; | ||
1803 | |||
1804 | if (!AR_SREV_9280(ah)) { | ||
1805 | nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), | ||
1806 | AR_PHY_CH2_MINCCA_PWR); | ||
1807 | if (nf & 0x100) | ||
1808 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1809 | DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, | ||
1810 | "NF calibrated [ctl] [chain 2] is %d\n", nf); | ||
1811 | nfarray[2] = nf; | ||
1812 | } | ||
1813 | |||
1814 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
1815 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), | ||
1816 | AR9280_PHY_EXT_MINCCA_PWR); | ||
1817 | else | ||
1818 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), | ||
1819 | AR_PHY_EXT_MINCCA_PWR); | ||
1820 | |||
1821 | if (nf & 0x100) | ||
1822 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1823 | DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, | ||
1824 | "NF calibrated [ext] [chain 0] is %d\n", nf); | ||
1825 | nfarray[3] = nf; | ||
1826 | |||
1827 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
1828 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), | ||
1829 | AR9280_PHY_CH1_EXT_MINCCA_PWR); | ||
1830 | else | ||
1831 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), | ||
1832 | AR_PHY_CH1_EXT_MINCCA_PWR); | ||
1833 | |||
1834 | if (nf & 0x100) | ||
1835 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1836 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
1837 | "NF calibrated [ext] [chain 1] is %d\n", nf); | ||
1838 | nfarray[4] = nf; | ||
1839 | |||
1840 | if (!AR_SREV_9280(ah)) { | ||
1841 | nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), | ||
1842 | AR_PHY_CH2_EXT_MINCCA_PWR); | ||
1843 | if (nf & 0x100) | ||
1844 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1845 | DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, | ||
1846 | "NF calibrated [ext] [chain 2] is %d\n", nf); | ||
1847 | nfarray[5] = nf; | ||
1848 | } | ||
1849 | } | ||
1850 | |||
1851 | static bool | ||
1852 | getNoiseFloorThresh(struct ath_hal *ah, | ||
1853 | const struct ath9k_channel *chan, | ||
1854 | int16_t *nft) | ||
1855 | { | ||
1856 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
1857 | |||
1858 | switch (chan->chanmode) { | ||
1859 | case CHANNEL_A: | ||
1860 | case CHANNEL_A_HT20: | ||
1861 | case CHANNEL_A_HT40PLUS: | ||
1862 | case CHANNEL_A_HT40MINUS: | ||
1863 | *nft = (int16_t) ath9k_hw_get_eeprom(ahp, EEP_NFTHRESH_5); | ||
1864 | break; | ||
1865 | case CHANNEL_B: | ||
1866 | case CHANNEL_G: | ||
1867 | case CHANNEL_G_HT20: | ||
1868 | case CHANNEL_G_HT40PLUS: | ||
1869 | case CHANNEL_G_HT40MINUS: | ||
1870 | *nft = (int16_t) ath9k_hw_get_eeprom(ahp, EEP_NFTHRESH_2); | ||
1871 | break; | ||
1872 | default: | ||
1873 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
1874 | "%s: invalid channel flags 0x%x\n", __func__, | ||
1875 | chan->channelFlags); | ||
1876 | return false; | ||
1877 | } | ||
1878 | return true; | ||
1879 | } | ||
1880 | |||
1881 | static void ath9k_hw_start_nfcal(struct ath_hal *ah) | ||
1882 | { | ||
1883 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | ||
1884 | AR_PHY_AGC_CONTROL_ENABLE_NF); | ||
1885 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | ||
1886 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | ||
1887 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | ||
1888 | } | ||
1889 | |||
1890 | static void | ||
1891 | ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan) | ||
1892 | { | ||
1893 | struct ath9k_nfcal_hist *h; | ||
1894 | int i, j; | ||
1895 | int32_t val; | ||
1896 | const u32 ar5416_cca_regs[6] = { | ||
1897 | AR_PHY_CCA, | ||
1898 | AR_PHY_CH1_CCA, | ||
1899 | AR_PHY_CH2_CCA, | ||
1900 | AR_PHY_EXT_CCA, | ||
1901 | AR_PHY_CH1_EXT_CCA, | ||
1902 | AR_PHY_CH2_EXT_CCA | ||
1903 | }; | ||
1904 | u8 chainmask; | ||
1905 | |||
1906 | if (AR_SREV_9280(ah)) | ||
1907 | chainmask = 0x1B; | ||
1908 | else | ||
1909 | chainmask = 0x3F; | ||
1910 | |||
1911 | #ifdef ATH_NF_PER_CHAN | ||
1912 | h = chan->nfCalHist; | ||
1913 | #else | ||
1914 | h = ah->nfCalHist; | ||
1915 | #endif | ||
1916 | |||
1917 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
1918 | if (chainmask & (1 << i)) { | ||
1919 | val = REG_READ(ah, ar5416_cca_regs[i]); | ||
1920 | val &= 0xFFFFFE00; | ||
1921 | val |= (((u32) (h[i].privNF) << 1) & 0x1ff); | ||
1922 | REG_WRITE(ah, ar5416_cca_regs[i], val); | ||
1923 | } | ||
1924 | } | ||
1925 | |||
1926 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
1927 | AR_PHY_AGC_CONTROL_ENABLE_NF); | ||
1928 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
1929 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | ||
1930 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | ||
1931 | |||
1932 | for (j = 0; j < 1000; j++) { | ||
1933 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & | ||
1934 | AR_PHY_AGC_CONTROL_NF) == 0) | ||
1935 | break; | ||
1936 | udelay(10); | ||
1937 | } | ||
1938 | |||
1939 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
1940 | if (chainmask & (1 << i)) { | ||
1941 | val = REG_READ(ah, ar5416_cca_regs[i]); | ||
1942 | val &= 0xFFFFFE00; | ||
1943 | val |= (((u32) (-50) << 1) & 0x1ff); | ||
1944 | REG_WRITE(ah, ar5416_cca_regs[i], val); | ||
1945 | } | ||
1946 | } | ||
1947 | } | ||
1948 | |||
1949 | static int16_t ath9k_hw_getnf(struct ath_hal *ah, | ||
1950 | struct ath9k_channel *chan) | ||
1951 | { | ||
1952 | int16_t nf, nfThresh; | ||
1953 | int16_t nfarray[NUM_NF_READINGS] = { 0 }; | ||
1954 | struct ath9k_nfcal_hist *h; | ||
1955 | u8 chainmask; | ||
1956 | |||
1957 | if (AR_SREV_9280(ah)) | ||
1958 | chainmask = 0x1B; | ||
1959 | else | ||
1960 | chainmask = 0x3F; | ||
1961 | |||
1962 | chan->channelFlags &= (~CHANNEL_CW_INT); | ||
1963 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { | ||
1964 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
1965 | "%s: NF did not complete in calibration window\n", | ||
1966 | __func__); | ||
1967 | nf = 0; | ||
1968 | chan->rawNoiseFloor = nf; | ||
1969 | return chan->rawNoiseFloor; | ||
1970 | } else { | ||
1971 | ar5416GetNoiseFloor(ah, nfarray); | ||
1972 | nf = nfarray[0]; | ||
1973 | if (getNoiseFloorThresh(ah, chan, &nfThresh) | ||
1974 | && nf > nfThresh) { | ||
1975 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
1976 | "%s: noise floor failed detected; " | ||
1977 | "detected %d, threshold %d\n", __func__, | ||
1978 | nf, nfThresh); | ||
1979 | chan->channelFlags |= CHANNEL_CW_INT; | ||
1980 | } | ||
1981 | } | ||
1982 | |||
1983 | #ifdef ATH_NF_PER_CHAN | ||
1984 | h = chan->nfCalHist; | ||
1985 | #else | ||
1986 | h = ah->nfCalHist; | ||
1987 | #endif | ||
1988 | |||
1989 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); | ||
1990 | chan->rawNoiseFloor = h[0].privNF; | ||
1991 | |||
1992 | return chan->rawNoiseFloor; | ||
1993 | } | ||
1994 | |||
1995 | static void ath9k_hw_update_mibstats(struct ath_hal *ah, | ||
1996 | struct ath9k_mib_stats *stats) | ||
1997 | { | ||
1998 | stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL); | ||
1999 | stats->rts_bad += REG_READ(ah, AR_RTS_FAIL); | ||
2000 | stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL); | ||
2001 | stats->rts_good += REG_READ(ah, AR_RTS_OK); | ||
2002 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); | ||
2003 | } | ||
2004 | |||
2005 | static void ath9k_enable_mib_counters(struct ath_hal *ah) | ||
2006 | { | ||
2007 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2008 | |||
2009 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable mib counters\n"); | ||
2010 | |||
2011 | ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats); | ||
2012 | |||
2013 | REG_WRITE(ah, AR_FILT_OFDM, 0); | ||
2014 | REG_WRITE(ah, AR_FILT_CCK, 0); | ||
2015 | REG_WRITE(ah, AR_MIBC, | ||
2016 | ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) | ||
2017 | & 0x0f); | ||
2018 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
2019 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
2020 | } | ||
2021 | |||
2022 | static void ath9k_hw_disable_mib_counters(struct ath_hal *ah) | ||
2023 | { | ||
2024 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2025 | |||
2026 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling MIB counters\n"); | ||
2027 | |||
2028 | REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC); | ||
2029 | |||
2030 | ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats); | ||
2031 | |||
2032 | REG_WRITE(ah, AR_FILT_OFDM, 0); | ||
2033 | REG_WRITE(ah, AR_FILT_CCK, 0); | ||
2034 | } | ||
2035 | |||
2036 | static int ath9k_hw_get_ani_channel_idx(struct ath_hal *ah, | ||
2037 | struct ath9k_channel *chan) | ||
2038 | { | ||
2039 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2040 | int i; | ||
2041 | |||
2042 | for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) { | ||
2043 | if (ahp->ah_ani[i].c.channel == chan->channel) | ||
2044 | return i; | ||
2045 | if (ahp->ah_ani[i].c.channel == 0) { | ||
2046 | ahp->ah_ani[i].c.channel = chan->channel; | ||
2047 | ahp->ah_ani[i].c.channelFlags = chan->channelFlags; | ||
2048 | return i; | ||
2049 | } | ||
2050 | } | ||
2051 | |||
2052 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2053 | "No more channel states left. Using channel 0\n"); | ||
2054 | return 0; | ||
2055 | } | ||
2056 | |||
2057 | static void ath9k_hw_ani_attach(struct ath_hal *ah) | ||
2058 | { | ||
2059 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2060 | int i; | ||
2061 | |||
2062 | ahp->ah_hasHwPhyCounters = 1; | ||
2063 | |||
2064 | memset(ahp->ah_ani, 0, sizeof(ahp->ah_ani)); | ||
2065 | for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) { | ||
2066 | ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH; | ||
2067 | ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW; | ||
2068 | ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH; | ||
2069 | ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW; | ||
2070 | ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; | ||
2071 | ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; | ||
2072 | ahp->ah_ani[i].ofdmWeakSigDetectOff = | ||
2073 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; | ||
2074 | ahp->ah_ani[i].cckWeakSigThreshold = | ||
2075 | ATH9K_ANI_CCK_WEAK_SIG_THR; | ||
2076 | ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; | ||
2077 | ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; | ||
2078 | if (ahp->ah_hasHwPhyCounters) { | ||
2079 | ahp->ah_ani[i].ofdmPhyErrBase = | ||
2080 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; | ||
2081 | ahp->ah_ani[i].cckPhyErrBase = | ||
2082 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; | ||
2083 | } | ||
2084 | } | ||
2085 | if (ahp->ah_hasHwPhyCounters) { | ||
2086 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2087 | "Setting OfdmErrBase = 0x%08x\n", | ||
2088 | ahp->ah_ani[0].ofdmPhyErrBase); | ||
2089 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", | ||
2090 | ahp->ah_ani[0].cckPhyErrBase); | ||
2091 | |||
2092 | REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase); | ||
2093 | REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase); | ||
2094 | ath9k_enable_mib_counters(ah); | ||
2095 | } | ||
2096 | ahp->ah_aniPeriod = ATH9K_ANI_PERIOD; | ||
2097 | if (ah->ah_config.ath_hal_enableANI) | ||
2098 | ahp->ah_procPhyErr |= HAL_PROCESS_ANI; | ||
2099 | } | ||
2100 | |||
2101 | static inline void ath9k_hw_ani_setup(struct ath_hal *ah) | ||
2102 | { | ||
2103 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2104 | int i; | ||
2105 | |||
2106 | const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; | ||
2107 | const int coarseHigh[] = { -14, -14, -14, -14, -12 }; | ||
2108 | const int coarseLow[] = { -64, -64, -64, -64, -70 }; | ||
2109 | const int firpwr[] = { -78, -78, -78, -78, -80 }; | ||
2110 | |||
2111 | for (i = 0; i < 5; i++) { | ||
2112 | ahp->ah_totalSizeDesired[i] = totalSizeDesired[i]; | ||
2113 | ahp->ah_coarseHigh[i] = coarseHigh[i]; | ||
2114 | ahp->ah_coarseLow[i] = coarseLow[i]; | ||
2115 | ahp->ah_firpwr[i] = firpwr[i]; | ||
2116 | } | ||
2117 | } | ||
2118 | |||
2119 | static void ath9k_hw_ani_detach(struct ath_hal *ah) | ||
2120 | { | ||
2121 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2122 | |||
2123 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detaching Ani\n"); | ||
2124 | if (ahp->ah_hasHwPhyCounters) { | ||
2125 | ath9k_hw_disable_mib_counters(ah); | ||
2126 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | ||
2127 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | ||
2128 | } | ||
2129 | } | ||
2130 | |||
2131 | |||
2132 | static bool ath9k_hw_ani_control(struct ath_hal *ah, | ||
2133 | enum ath9k_ani_cmd cmd, int param) | ||
2134 | { | ||
2135 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2136 | struct ar5416AniState *aniState = ahp->ah_curani; | ||
2137 | |||
2138 | switch (cmd & ahp->ah_ani_function) { | ||
2139 | case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ | ||
2140 | u32 level = param; | ||
2141 | |||
2142 | if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) { | ||
2143 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2144 | "%s: level out of range (%u > %u)\n", | ||
2145 | __func__, level, | ||
2146 | (unsigned) ARRAY_SIZE(ahp-> | ||
2147 | ah_totalSizeDesired)); | ||
2148 | return false; | ||
2149 | } | ||
2150 | |||
2151 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
2152 | AR_PHY_DESIRED_SZ_TOT_DES, | ||
2153 | ahp->ah_totalSizeDesired[level]); | ||
2154 | REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, | ||
2155 | AR_PHY_AGC_CTL1_COARSE_LOW, | ||
2156 | ahp->ah_coarseLow[level]); | ||
2157 | REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, | ||
2158 | AR_PHY_AGC_CTL1_COARSE_HIGH, | ||
2159 | ahp->ah_coarseHigh[level]); | ||
2160 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
2161 | AR_PHY_FIND_SIG_FIRPWR, | ||
2162 | ahp->ah_firpwr[level]); | ||
2163 | |||
2164 | if (level > aniState->noiseImmunityLevel) | ||
2165 | ahp->ah_stats.ast_ani_niup++; | ||
2166 | else if (level < aniState->noiseImmunityLevel) | ||
2167 | ahp->ah_stats.ast_ani_nidown++; | ||
2168 | aniState->noiseImmunityLevel = level; | ||
2169 | break; | ||
2170 | } | ||
2171 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | ||
2172 | const int m1ThreshLow[] = { 127, 50 }; | ||
2173 | const int m2ThreshLow[] = { 127, 40 }; | ||
2174 | const int m1Thresh[] = { 127, 0x4d }; | ||
2175 | const int m2Thresh[] = { 127, 0x40 }; | ||
2176 | const int m2CountThr[] = { 31, 16 }; | ||
2177 | const int m2CountThrLow[] = { 63, 48 }; | ||
2178 | u32 on = param ? 1 : 0; | ||
2179 | |||
2180 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
2181 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, | ||
2182 | m1ThreshLow[on]); | ||
2183 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
2184 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, | ||
2185 | m2ThreshLow[on]); | ||
2186 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
2187 | AR_PHY_SFCORR_M1_THRESH, | ||
2188 | m1Thresh[on]); | ||
2189 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
2190 | AR_PHY_SFCORR_M2_THRESH, | ||
2191 | m2Thresh[on]); | ||
2192 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
2193 | AR_PHY_SFCORR_M2COUNT_THR, | ||
2194 | m2CountThr[on]); | ||
2195 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
2196 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, | ||
2197 | m2CountThrLow[on]); | ||
2198 | |||
2199 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
2200 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, | ||
2201 | m1ThreshLow[on]); | ||
2202 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
2203 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, | ||
2204 | m2ThreshLow[on]); | ||
2205 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
2206 | AR_PHY_SFCORR_EXT_M1_THRESH, | ||
2207 | m1Thresh[on]); | ||
2208 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
2209 | AR_PHY_SFCORR_EXT_M2_THRESH, | ||
2210 | m2Thresh[on]); | ||
2211 | |||
2212 | if (on) | ||
2213 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, | ||
2214 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
2215 | else | ||
2216 | REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, | ||
2217 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
2218 | |||
2219 | if (!on != aniState->ofdmWeakSigDetectOff) { | ||
2220 | if (on) | ||
2221 | ahp->ah_stats.ast_ani_ofdmon++; | ||
2222 | else | ||
2223 | ahp->ah_stats.ast_ani_ofdmoff++; | ||
2224 | aniState->ofdmWeakSigDetectOff = !on; | ||
2225 | } | ||
2226 | break; | ||
2227 | } | ||
2228 | case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ | ||
2229 | const int weakSigThrCck[] = { 8, 6 }; | ||
2230 | u32 high = param ? 1 : 0; | ||
2231 | |||
2232 | REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, | ||
2233 | AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, | ||
2234 | weakSigThrCck[high]); | ||
2235 | if (high != aniState->cckWeakSigThreshold) { | ||
2236 | if (high) | ||
2237 | ahp->ah_stats.ast_ani_cckhigh++; | ||
2238 | else | ||
2239 | ahp->ah_stats.ast_ani_ccklow++; | ||
2240 | aniState->cckWeakSigThreshold = high; | ||
2241 | } | ||
2242 | break; | ||
2243 | } | ||
2244 | case ATH9K_ANI_FIRSTEP_LEVEL:{ | ||
2245 | const int firstep[] = { 0, 4, 8 }; | ||
2246 | u32 level = param; | ||
2247 | |||
2248 | if (level >= ARRAY_SIZE(firstep)) { | ||
2249 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2250 | "%s: level out of range (%u > %u)\n", | ||
2251 | __func__, level, | ||
2252 | (unsigned) ARRAY_SIZE(firstep)); | ||
2253 | return false; | ||
2254 | } | ||
2255 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
2256 | AR_PHY_FIND_SIG_FIRSTEP, | ||
2257 | firstep[level]); | ||
2258 | if (level > aniState->firstepLevel) | ||
2259 | ahp->ah_stats.ast_ani_stepup++; | ||
2260 | else if (level < aniState->firstepLevel) | ||
2261 | ahp->ah_stats.ast_ani_stepdown++; | ||
2262 | aniState->firstepLevel = level; | ||
2263 | break; | ||
2264 | } | ||
2265 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ | ||
2266 | const int cycpwrThr1[] = | ||
2267 | { 2, 4, 6, 8, 10, 12, 14, 16 }; | ||
2268 | u32 level = param; | ||
2269 | |||
2270 | if (level >= ARRAY_SIZE(cycpwrThr1)) { | ||
2271 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2272 | "%s: level out of range (%u > %u)\n", | ||
2273 | __func__, level, | ||
2274 | (unsigned) | ||
2275 | ARRAY_SIZE(cycpwrThr1)); | ||
2276 | return false; | ||
2277 | } | ||
2278 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | ||
2279 | AR_PHY_TIMING5_CYCPWR_THR1, | ||
2280 | cycpwrThr1[level]); | ||
2281 | if (level > aniState->spurImmunityLevel) | ||
2282 | ahp->ah_stats.ast_ani_spurup++; | ||
2283 | else if (level < aniState->spurImmunityLevel) | ||
2284 | ahp->ah_stats.ast_ani_spurdown++; | ||
2285 | aniState->spurImmunityLevel = level; | ||
2286 | break; | ||
2287 | } | ||
2288 | case ATH9K_ANI_PRESENT: | ||
2289 | break; | ||
2290 | default: | ||
2291 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2292 | "%s: invalid cmd %u\n", __func__, cmd); | ||
2293 | return false; | ||
2294 | } | ||
2295 | |||
2296 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "%s: ANI parameters:\n", __func__); | ||
2297 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2298 | "noiseImmunityLevel=%d, spurImmunityLevel=%d, " | ||
2299 | "ofdmWeakSigDetectOff=%d\n", | ||
2300 | aniState->noiseImmunityLevel, aniState->spurImmunityLevel, | ||
2301 | !aniState->ofdmWeakSigDetectOff); | ||
2302 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2303 | "cckWeakSigThreshold=%d, " | ||
2304 | "firstepLevel=%d, listenTime=%d\n", | ||
2305 | aniState->cckWeakSigThreshold, aniState->firstepLevel, | ||
2306 | aniState->listenTime); | ||
2307 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2308 | "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", | ||
2309 | aniState->cycleCount, aniState->ofdmPhyErrCount, | ||
2310 | aniState->cckPhyErrCount); | ||
2311 | return true; | ||
2312 | } | ||
2313 | |||
2314 | static void ath9k_ani_restart(struct ath_hal *ah) | ||
2315 | { | ||
2316 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2317 | struct ar5416AniState *aniState; | ||
2318 | |||
2319 | if (!DO_ANI(ah)) | ||
2320 | return; | ||
2321 | |||
2322 | aniState = ahp->ah_curani; | ||
2323 | |||
2324 | aniState->listenTime = 0; | ||
2325 | if (ahp->ah_hasHwPhyCounters) { | ||
2326 | if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { | ||
2327 | aniState->ofdmPhyErrBase = 0; | ||
2328 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2329 | "OFDM Trigger is too high for hw counters\n"); | ||
2330 | } else { | ||
2331 | aniState->ofdmPhyErrBase = | ||
2332 | AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; | ||
2333 | } | ||
2334 | if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { | ||
2335 | aniState->cckPhyErrBase = 0; | ||
2336 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2337 | "CCK Trigger is too high for hw counters\n"); | ||
2338 | } else { | ||
2339 | aniState->cckPhyErrBase = | ||
2340 | AR_PHY_COUNTMAX - aniState->cckTrigHigh; | ||
2341 | } | ||
2342 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2343 | "%s: Writing ofdmbase=%u cckbase=%u\n", | ||
2344 | __func__, aniState->ofdmPhyErrBase, | ||
2345 | aniState->cckPhyErrBase); | ||
2346 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | ||
2347 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | ||
2348 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
2349 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
2350 | |||
2351 | ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats); | ||
2352 | } | ||
2353 | aniState->ofdmPhyErrCount = 0; | ||
2354 | aniState->cckPhyErrCount = 0; | ||
2355 | } | ||
2356 | |||
2357 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah) | ||
2358 | { | ||
2359 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2360 | struct ath9k_channel *chan = ah->ah_curchan; | ||
2361 | struct ar5416AniState *aniState; | ||
2362 | enum wireless_mode mode; | ||
2363 | int32_t rssi; | ||
2364 | |||
2365 | if (!DO_ANI(ah)) | ||
2366 | return; | ||
2367 | |||
2368 | aniState = ahp->ah_curani; | ||
2369 | |||
2370 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | ||
2371 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | ||
2372 | aniState->noiseImmunityLevel + 1)) { | ||
2373 | return; | ||
2374 | } | ||
2375 | } | ||
2376 | |||
2377 | if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) { | ||
2378 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, | ||
2379 | aniState->spurImmunityLevel + 1)) { | ||
2380 | return; | ||
2381 | } | ||
2382 | } | ||
2383 | |||
2384 | if (ah->ah_opmode == ATH9K_M_HOSTAP) { | ||
2385 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { | ||
2386 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
2387 | aniState->firstepLevel + 1); | ||
2388 | } | ||
2389 | return; | ||
2390 | } | ||
2391 | rssi = BEACON_RSSI(ahp); | ||
2392 | if (rssi > aniState->rssiThrHigh) { | ||
2393 | if (!aniState->ofdmWeakSigDetectOff) { | ||
2394 | if (ath9k_hw_ani_control(ah, | ||
2395 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
2396 | false)) { | ||
2397 | ath9k_hw_ani_control(ah, | ||
2398 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL, | ||
2399 | 0); | ||
2400 | return; | ||
2401 | } | ||
2402 | } | ||
2403 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { | ||
2404 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
2405 | aniState->firstepLevel + 1); | ||
2406 | return; | ||
2407 | } | ||
2408 | } else if (rssi > aniState->rssiThrLow) { | ||
2409 | if (aniState->ofdmWeakSigDetectOff) | ||
2410 | ath9k_hw_ani_control(ah, | ||
2411 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
2412 | true); | ||
2413 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) | ||
2414 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
2415 | aniState->firstepLevel + 1); | ||
2416 | return; | ||
2417 | } else { | ||
2418 | mode = ath9k_hw_chan2wmode(ah, chan); | ||
2419 | if (mode == WIRELESS_MODE_11g || mode == WIRELESS_MODE_11b) { | ||
2420 | if (!aniState->ofdmWeakSigDetectOff) | ||
2421 | ath9k_hw_ani_control(ah, | ||
2422 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
2423 | false); | ||
2424 | if (aniState->firstepLevel > 0) | ||
2425 | ath9k_hw_ani_control(ah, | ||
2426 | ATH9K_ANI_FIRSTEP_LEVEL, | ||
2427 | 0); | ||
2428 | return; | ||
2429 | } | ||
2430 | } | ||
2431 | } | ||
2432 | |||
2433 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah) | ||
2434 | { | ||
2435 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2436 | struct ath9k_channel *chan = ah->ah_curchan; | ||
2437 | struct ar5416AniState *aniState; | ||
2438 | enum wireless_mode mode; | ||
2439 | int32_t rssi; | ||
2440 | |||
2441 | if (!DO_ANI(ah)) | ||
2442 | return; | ||
2443 | |||
2444 | aniState = ahp->ah_curani; | ||
2445 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | ||
2446 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | ||
2447 | aniState->noiseImmunityLevel + 1)) { | ||
2448 | return; | ||
2449 | } | ||
2450 | } | ||
2451 | if (ah->ah_opmode == ATH9K_M_HOSTAP) { | ||
2452 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { | ||
2453 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
2454 | aniState->firstepLevel + 1); | ||
2455 | } | ||
2456 | return; | ||
2457 | } | ||
2458 | rssi = BEACON_RSSI(ahp); | ||
2459 | if (rssi > aniState->rssiThrLow) { | ||
2460 | if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) | ||
2461 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
2462 | aniState->firstepLevel + 1); | ||
2463 | } else { | ||
2464 | mode = ath9k_hw_chan2wmode(ah, chan); | ||
2465 | if (mode == WIRELESS_MODE_11g || mode == WIRELESS_MODE_11b) { | ||
2466 | if (aniState->firstepLevel > 0) | ||
2467 | ath9k_hw_ani_control(ah, | ||
2468 | ATH9K_ANI_FIRSTEP_LEVEL, | ||
2469 | 0); | ||
2470 | } | ||
2471 | } | ||
2472 | } | ||
2473 | |||
2474 | static void ath9k_ani_reset(struct ath_hal *ah) | ||
2475 | { | ||
2476 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2477 | struct ar5416AniState *aniState; | ||
2478 | struct ath9k_channel *chan = ah->ah_curchan; | ||
2479 | int index; | ||
2480 | |||
2481 | if (!DO_ANI(ah)) | ||
2482 | return; | ||
2483 | |||
2484 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | ||
2485 | aniState = &ahp->ah_ani[index]; | ||
2486 | ahp->ah_curani = aniState; | ||
2487 | |||
2488 | if (DO_ANI(ah) && ah->ah_opmode != ATH9K_M_STA | ||
2489 | && ah->ah_opmode != ATH9K_M_IBSS) { | ||
2490 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2491 | "%s: Reset ANI state opmode %u\n", __func__, | ||
2492 | ah->ah_opmode); | ||
2493 | ahp->ah_stats.ast_ani_reset++; | ||
2494 | ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0); | ||
2495 | ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); | ||
2496 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0); | ||
2497 | ath9k_hw_ani_control(ah, | ||
2498 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
2499 | !ATH9K_ANI_USE_OFDM_WEAK_SIG); | ||
2500 | ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, | ||
2501 | ATH9K_ANI_CCK_WEAK_SIG_THR); | ||
2502 | ath9k_hw_setrxfilter(ah, | ||
2503 | ath9k_hw_getrxfilter(ah) | | ||
2504 | ATH9K_RX_FILTER_PHYERR); | ||
2505 | if (ah->ah_opmode == ATH9K_M_HOSTAP) { | ||
2506 | ahp->ah_curani->ofdmTrigHigh = | ||
2507 | ah->ah_config.ath_hal_ofdmTrigHigh; | ||
2508 | ahp->ah_curani->ofdmTrigLow = | ||
2509 | ah->ah_config.ath_hal_ofdmTrigLow; | ||
2510 | ahp->ah_curani->cckTrigHigh = | ||
2511 | ah->ah_config.ath_hal_cckTrigHigh; | ||
2512 | ahp->ah_curani->cckTrigLow = | ||
2513 | ah->ah_config.ath_hal_cckTrigLow; | ||
2514 | } | ||
2515 | ath9k_ani_restart(ah); | ||
2516 | return; | ||
2517 | } | ||
2518 | |||
2519 | if (aniState->noiseImmunityLevel != 0) | ||
2520 | ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | ||
2521 | aniState->noiseImmunityLevel); | ||
2522 | if (aniState->spurImmunityLevel != 0) | ||
2523 | ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, | ||
2524 | aniState->spurImmunityLevel); | ||
2525 | if (aniState->ofdmWeakSigDetectOff) | ||
2526 | ath9k_hw_ani_control(ah, | ||
2527 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
2528 | !aniState->ofdmWeakSigDetectOff); | ||
2529 | if (aniState->cckWeakSigThreshold) | ||
2530 | ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, | ||
2531 | aniState->cckWeakSigThreshold); | ||
2532 | if (aniState->firstepLevel != 0) | ||
2533 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
2534 | aniState->firstepLevel); | ||
2535 | if (ahp->ah_hasHwPhyCounters) { | ||
2536 | ath9k_hw_setrxfilter(ah, | ||
2537 | ath9k_hw_getrxfilter(ah) & | ||
2538 | ~ATH9K_RX_FILTER_PHYERR); | ||
2539 | ath9k_ani_restart(ah); | ||
2540 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
2541 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
2542 | |||
2543 | } else { | ||
2544 | ath9k_ani_restart(ah); | ||
2545 | ath9k_hw_setrxfilter(ah, | ||
2546 | ath9k_hw_getrxfilter(ah) | | ||
2547 | ATH9K_RX_FILTER_PHYERR); | ||
2548 | } | ||
2549 | } | ||
2550 | |||
2551 | void ath9k_hw_procmibevent(struct ath_hal *ah, | ||
2552 | const struct ath9k_node_stats *stats) | ||
2553 | { | ||
2554 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2555 | u32 phyCnt1, phyCnt2; | ||
2556 | |||
2557 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n"); | ||
2558 | |||
2559 | REG_WRITE(ah, AR_FILT_OFDM, 0); | ||
2560 | REG_WRITE(ah, AR_FILT_CCK, 0); | ||
2561 | if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) | ||
2562 | REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); | ||
2563 | |||
2564 | ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats); | ||
2565 | ahp->ah_stats.ast_nodestats = *stats; | ||
2566 | |||
2567 | if (!DO_ANI(ah)) | ||
2568 | return; | ||
2569 | |||
2570 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
2571 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
2572 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | ||
2573 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { | ||
2574 | struct ar5416AniState *aniState = ahp->ah_curani; | ||
2575 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
2576 | |||
2577 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | ||
2578 | ahp->ah_stats.ast_ani_ofdmerrs += | ||
2579 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
2580 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
2581 | |||
2582 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
2583 | ahp->ah_stats.ast_ani_cckerrs += | ||
2584 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
2585 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
2586 | |||
2587 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) | ||
2588 | ath9k_hw_ani_ofdm_err_trigger(ah); | ||
2589 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) | ||
2590 | ath9k_hw_ani_cck_err_trigger(ah); | ||
2591 | |||
2592 | ath9k_ani_restart(ah); | ||
2593 | } | ||
2594 | } | ||
2595 | |||
2596 | static void ath9k_hw_ani_lower_immunity(struct ath_hal *ah) | ||
2597 | { | ||
2598 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2599 | struct ar5416AniState *aniState; | ||
2600 | int32_t rssi; | ||
2601 | |||
2602 | aniState = ahp->ah_curani; | ||
2603 | |||
2604 | if (ah->ah_opmode == ATH9K_M_HOSTAP) { | ||
2605 | if (aniState->firstepLevel > 0) { | ||
2606 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
2607 | aniState->firstepLevel - 1)) { | ||
2608 | return; | ||
2609 | } | ||
2610 | } | ||
2611 | } else { | ||
2612 | rssi = BEACON_RSSI(ahp); | ||
2613 | if (rssi > aniState->rssiThrHigh) { | ||
2614 | /* XXX: Handle me */ | ||
2615 | } else if (rssi > aniState->rssiThrLow) { | ||
2616 | if (aniState->ofdmWeakSigDetectOff) { | ||
2617 | if (ath9k_hw_ani_control(ah, | ||
2618 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
2619 | true) == | ||
2620 | true) { | ||
2621 | return; | ||
2622 | } | ||
2623 | } | ||
2624 | if (aniState->firstepLevel > 0) { | ||
2625 | if (ath9k_hw_ani_control | ||
2626 | (ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
2627 | aniState->firstepLevel - 1) == | ||
2628 | true) { | ||
2629 | return; | ||
2630 | } | ||
2631 | } | ||
2632 | } else { | ||
2633 | if (aniState->firstepLevel > 0) { | ||
2634 | if (ath9k_hw_ani_control | ||
2635 | (ah, ATH9K_ANI_FIRSTEP_LEVEL, | ||
2636 | aniState->firstepLevel - 1) == | ||
2637 | true) { | ||
2638 | return; | ||
2639 | } | ||
2640 | } | ||
2641 | } | ||
2642 | } | ||
2643 | |||
2644 | if (aniState->spurImmunityLevel > 0) { | ||
2645 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, | ||
2646 | aniState->spurImmunityLevel - 1)) { | ||
2647 | return; | ||
2648 | } | ||
2649 | } | ||
2650 | |||
2651 | if (aniState->noiseImmunityLevel > 0) { | ||
2652 | ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | ||
2653 | aniState->noiseImmunityLevel - 1); | ||
2654 | return; | ||
2655 | } | ||
2656 | } | ||
2657 | |||
2658 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hal *ah) | ||
2659 | { | ||
2660 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2661 | struct ar5416AniState *aniState; | ||
2662 | u32 txFrameCount, rxFrameCount, cycleCount; | ||
2663 | int32_t listenTime; | ||
2664 | |||
2665 | txFrameCount = REG_READ(ah, AR_TFCNT); | ||
2666 | rxFrameCount = REG_READ(ah, AR_RFCNT); | ||
2667 | cycleCount = REG_READ(ah, AR_CCCNT); | ||
2668 | |||
2669 | aniState = ahp->ah_curani; | ||
2670 | if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { | ||
2671 | |||
2672 | listenTime = 0; | ||
2673 | ahp->ah_stats.ast_ani_lzero++; | ||
2674 | } else { | ||
2675 | int32_t ccdelta = cycleCount - aniState->cycleCount; | ||
2676 | int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; | ||
2677 | int32_t tfdelta = txFrameCount - aniState->txFrameCount; | ||
2678 | listenTime = (ccdelta - rfdelta - tfdelta) / 44000; | ||
2679 | } | ||
2680 | aniState->cycleCount = cycleCount; | ||
2681 | aniState->txFrameCount = txFrameCount; | ||
2682 | aniState->rxFrameCount = rxFrameCount; | ||
2683 | |||
2684 | return listenTime; | ||
2685 | } | ||
2686 | |||
2687 | void ath9k_hw_ani_monitor(struct ath_hal *ah, | ||
2688 | const struct ath9k_node_stats *stats, | ||
2689 | struct ath9k_channel *chan) | ||
2690 | { | ||
2691 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2692 | struct ar5416AniState *aniState; | ||
2693 | int32_t listenTime; | ||
2694 | |||
2695 | aniState = ahp->ah_curani; | ||
2696 | ahp->ah_stats.ast_nodestats = *stats; | ||
2697 | |||
2698 | listenTime = ath9k_hw_ani_get_listen_time(ah); | ||
2699 | if (listenTime < 0) { | ||
2700 | ahp->ah_stats.ast_ani_lneg++; | ||
2701 | ath9k_ani_restart(ah); | ||
2702 | return; | ||
2703 | } | ||
2704 | |||
2705 | aniState->listenTime += listenTime; | ||
2706 | |||
2707 | if (ahp->ah_hasHwPhyCounters) { | ||
2708 | u32 phyCnt1, phyCnt2; | ||
2709 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
2710 | |||
2711 | ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats); | ||
2712 | |||
2713 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
2714 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
2715 | |||
2716 | if (phyCnt1 < aniState->ofdmPhyErrBase || | ||
2717 | phyCnt2 < aniState->cckPhyErrBase) { | ||
2718 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | ||
2719 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2720 | "%s: phyCnt1 0x%x, resetting " | ||
2721 | "counter value to 0x%x\n", | ||
2722 | __func__, phyCnt1, | ||
2723 | aniState->ofdmPhyErrBase); | ||
2724 | REG_WRITE(ah, AR_PHY_ERR_1, | ||
2725 | aniState->ofdmPhyErrBase); | ||
2726 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | ||
2727 | AR_PHY_ERR_OFDM_TIMING); | ||
2728 | } | ||
2729 | if (phyCnt2 < aniState->cckPhyErrBase) { | ||
2730 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2731 | "%s: phyCnt2 0x%x, resetting " | ||
2732 | "counter value to 0x%x\n", | ||
2733 | __func__, phyCnt2, | ||
2734 | aniState->cckPhyErrBase); | ||
2735 | REG_WRITE(ah, AR_PHY_ERR_2, | ||
2736 | aniState->cckPhyErrBase); | ||
2737 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | ||
2738 | AR_PHY_ERR_CCK_TIMING); | ||
2739 | } | ||
2740 | return; | ||
2741 | } | ||
2742 | |||
2743 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | ||
2744 | ahp->ah_stats.ast_ani_ofdmerrs += | ||
2745 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
2746 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
2747 | |||
2748 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
2749 | ahp->ah_stats.ast_ani_cckerrs += | ||
2750 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
2751 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
2752 | } | ||
2753 | |||
2754 | if (!DO_ANI(ah)) | ||
2755 | return; | ||
2756 | |||
2757 | if (aniState->listenTime > 5 * ahp->ah_aniPeriod) { | ||
2758 | if (aniState->ofdmPhyErrCount <= aniState->listenTime * | ||
2759 | aniState->ofdmTrigLow / 1000 && | ||
2760 | aniState->cckPhyErrCount <= aniState->listenTime * | ||
2761 | aniState->cckTrigLow / 1000) | ||
2762 | ath9k_hw_ani_lower_immunity(ah); | ||
2763 | ath9k_ani_restart(ah); | ||
2764 | } else if (aniState->listenTime > ahp->ah_aniPeriod) { | ||
2765 | if (aniState->ofdmPhyErrCount > aniState->listenTime * | ||
2766 | aniState->ofdmTrigHigh / 1000) { | ||
2767 | ath9k_hw_ani_ofdm_err_trigger(ah); | ||
2768 | ath9k_ani_restart(ah); | ||
2769 | } else if (aniState->cckPhyErrCount > | ||
2770 | aniState->listenTime * aniState->cckTrigHigh / | ||
2771 | 1000) { | ||
2772 | ath9k_hw_ani_cck_err_trigger(ah); | ||
2773 | ath9k_ani_restart(ah); | ||
2774 | } | ||
2775 | } | ||
2776 | } | ||
2777 | |||
2778 | #ifndef ATH_NF_PER_CHAN | ||
2779 | static void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah) | ||
2780 | { | ||
2781 | int i, j; | ||
2782 | |||
2783 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
2784 | ah->nfCalHist[i].currIndex = 0; | ||
2785 | ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE; | ||
2786 | ah->nfCalHist[i].invalidNFcount = | ||
2787 | AR_PHY_CCA_FILTERWINDOW_LENGTH; | ||
2788 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { | ||
2789 | ah->nfCalHist[i].nfCalBuffer[j] = | ||
2790 | AR_PHY_CCA_MAX_GOOD_VALUE; | ||
2791 | } | ||
2792 | } | ||
2793 | return; | ||
2794 | } | ||
2795 | #endif | ||
2796 | |||
2797 | static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah, | ||
2798 | u32 gpio, u32 type) | ||
2799 | { | ||
2800 | int addr; | ||
2801 | u32 gpio_shift, tmp; | ||
2802 | |||
2803 | if (gpio > 11) | ||
2804 | addr = AR_GPIO_OUTPUT_MUX3; | ||
2805 | else if (gpio > 5) | ||
2806 | addr = AR_GPIO_OUTPUT_MUX2; | ||
2807 | else | ||
2808 | addr = AR_GPIO_OUTPUT_MUX1; | ||
2809 | |||
2810 | gpio_shift = (gpio % 6) * 5; | ||
2811 | |||
2812 | if (AR_SREV_9280_20_OR_LATER(ah) | ||
2813 | || (addr != AR_GPIO_OUTPUT_MUX1)) { | ||
2814 | REG_RMW(ah, addr, (type << gpio_shift), | ||
2815 | (0x1f << gpio_shift)); | ||
2816 | } else { | ||
2817 | tmp = REG_READ(ah, addr); | ||
2818 | tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0); | ||
2819 | tmp &= ~(0x1f << gpio_shift); | ||
2820 | tmp |= (type << gpio_shift); | ||
2821 | REG_WRITE(ah, addr, tmp); | ||
2822 | } | ||
2823 | } | ||
2824 | |||
2825 | static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, | ||
2826 | enum ath9k_gpio_output_mux_type | ||
2827 | halSignalType) | ||
2828 | { | ||
2829 | u32 ah_signal_type; | ||
2830 | u32 gpio_shift; | ||
2831 | |||
2832 | static u32 MuxSignalConversionTable[] = { | ||
2833 | |||
2834 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT, | ||
2835 | |||
2836 | AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, | ||
2837 | |||
2838 | AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, | ||
2839 | |||
2840 | AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, | ||
2841 | |||
2842 | AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, | ||
2843 | }; | ||
2844 | |||
2845 | if ((halSignalType >= 0) | ||
2846 | && (halSignalType < ARRAY_SIZE(MuxSignalConversionTable))) | ||
2847 | ah_signal_type = MuxSignalConversionTable[halSignalType]; | ||
2848 | else | ||
2849 | return false; | ||
2850 | |||
2851 | ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); | ||
2852 | |||
2853 | gpio_shift = 2 * gpio; | ||
2854 | |||
2855 | REG_RMW(ah, | ||
2856 | AR_GPIO_OE_OUT, | ||
2857 | (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), | ||
2858 | (AR_GPIO_OE_OUT_DRV << gpio_shift)); | ||
2859 | |||
2860 | return true; | ||
2861 | } | ||
2862 | |||
2863 | static bool ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, | ||
2864 | u32 val) | ||
2865 | { | ||
2866 | REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), | ||
2867 | AR_GPIO_BIT(gpio)); | ||
2868 | return true; | ||
2869 | } | ||
2870 | |||
2871 | static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio) | ||
2872 | { | ||
2873 | if (gpio >= ah->ah_caps.halNumGpioPins) | ||
2874 | return 0xffffffff; | ||
2875 | |||
2876 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
2877 | return (MS | ||
2878 | (REG_READ(ah, AR_GPIO_IN_OUT), | ||
2879 | AR928X_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0; | ||
2880 | } else { | ||
2881 | return (MS(REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL) & | ||
2882 | AR_GPIO_BIT(gpio)) != 0; | ||
2883 | } | ||
2884 | } | ||
2885 | |||
2886 | static inline int ath9k_hw_post_attach(struct ath_hal *ah) | ||
2887 | { | ||
2888 | int ecode; | ||
2889 | |||
2890 | if (!ath9k_hw_chip_test(ah)) { | ||
2891 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
2892 | "%s: hardware self-test failed\n", __func__); | ||
2893 | return -ENODEV; | ||
2894 | } | ||
2895 | |||
2896 | ecode = ath9k_hw_rf_claim(ah); | ||
2897 | if (ecode != 0) | ||
2898 | return ecode; | ||
2899 | |||
2900 | ecode = ath9k_hw_eeprom_attach(ah); | ||
2901 | if (ecode != 0) | ||
2902 | return ecode; | ||
2903 | ecode = ath9k_hw_rfattach(ah); | ||
2904 | if (ecode != 0) | ||
2905 | return ecode; | ||
2906 | |||
2907 | if (!AR_SREV_9100(ah)) { | ||
2908 | ath9k_hw_ani_setup(ah); | ||
2909 | ath9k_hw_ani_attach(ah); | ||
2910 | } | ||
2911 | return 0; | ||
2912 | } | ||
2913 | |||
2914 | static u32 ath9k_hw_ini_fixup(struct ath_hal *ah, | ||
2915 | struct ar5416_eeprom *pEepData, | ||
2916 | u32 reg, u32 value) | ||
2917 | { | ||
2918 | struct base_eep_header *pBase = &(pEepData->baseEepHeader); | ||
2919 | |||
2920 | switch (ah->ah_devid) { | ||
2921 | case AR9280_DEVID_PCI: | ||
2922 | if (reg == 0x7894) { | ||
2923 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
2924 | "ini VAL: %x EEPROM: %x\n", value, | ||
2925 | (pBase->version & 0xff)); | ||
2926 | |||
2927 | if ((pBase->version & 0xff) > 0x0a) { | ||
2928 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
2929 | "PWDCLKIND: %d\n", | ||
2930 | pBase->pwdclkind); | ||
2931 | value &= ~AR_AN_TOP2_PWDCLKIND; | ||
2932 | value |= AR_AN_TOP2_PWDCLKIND & (pBase-> | ||
2933 | pwdclkind << AR_AN_TOP2_PWDCLKIND_S); | ||
2934 | } else { | ||
2935 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
2936 | "PWDCLKIND Earlier Rev\n"); | ||
2937 | } | ||
2938 | |||
2939 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
2940 | "final ini VAL: %x\n", value); | ||
2941 | } | ||
2942 | break; | ||
2943 | } | ||
2944 | return value; | ||
2945 | } | ||
2946 | |||
2947 | static bool ath9k_hw_fill_cap_info(struct ath_hal *ah) | ||
2948 | { | ||
2949 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
2950 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
2951 | u16 capField = 0, eeval; | ||
2952 | |||
2953 | eeval = ath9k_hw_get_eeprom(ahp, EEP_REG_0); | ||
2954 | |||
2955 | ah->ah_currentRD = eeval; | ||
2956 | |||
2957 | eeval = ath9k_hw_get_eeprom(ahp, EEP_REG_1); | ||
2958 | ah->ah_currentRDExt = eeval; | ||
2959 | |||
2960 | capField = ath9k_hw_get_eeprom(ahp, EEP_OP_CAP); | ||
2961 | |||
2962 | if (ah->ah_opmode != ATH9K_M_HOSTAP && | ||
2963 | ah->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) { | ||
2964 | if (ah->ah_currentRD == 0x64 || ah->ah_currentRD == 0x65) | ||
2965 | ah->ah_currentRD += 5; | ||
2966 | else if (ah->ah_currentRD == 0x41) | ||
2967 | ah->ah_currentRD = 0x43; | ||
2968 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
2969 | "%s: regdomain mapped to 0x%x\n", __func__, | ||
2970 | ah->ah_currentRD); | ||
2971 | } | ||
2972 | |||
2973 | pCap->halWirelessModes = 0; | ||
2974 | eeval = ath9k_hw_get_eeprom(ahp, EEP_OP_MODE); | ||
2975 | |||
2976 | if (eeval & AR5416_OPFLAGS_11A) { | ||
2977 | pCap->halWirelessModes |= ATH9K_MODE_SEL_11A | | ||
2978 | ((!ah->ah_config.ath_hal_htEnable | ||
2979 | || (eeval & AR5416_OPFLAGS_N_5G_HT20)) ? 0 | ||
2980 | : (ATH9K_MODE_SEL_11NA_HT20 | | ||
2981 | ((eeval & AR5416_OPFLAGS_N_5G_HT40) ? 0 | ||
2982 | : (ATH9K_MODE_SEL_11NA_HT40PLUS | | ||
2983 | ATH9K_MODE_SEL_11NA_HT40MINUS)))); | ||
2984 | } | ||
2985 | if (eeval & AR5416_OPFLAGS_11G) { | ||
2986 | pCap->halWirelessModes |= | ||
2987 | ATH9K_MODE_SEL_11B | ATH9K_MODE_SEL_11G | | ||
2988 | ((!ah->ah_config.ath_hal_htEnable | ||
2989 | || (eeval & AR5416_OPFLAGS_N_2G_HT20)) ? 0 | ||
2990 | : (ATH9K_MODE_SEL_11NG_HT20 | | ||
2991 | ((eeval & AR5416_OPFLAGS_N_2G_HT40) ? 0 | ||
2992 | : (ATH9K_MODE_SEL_11NG_HT40PLUS | | ||
2993 | ATH9K_MODE_SEL_11NG_HT40MINUS)))); | ||
2994 | |||
2995 | } | ||
2996 | pCap->halTxChainMask = ath9k_hw_get_eeprom(ahp, EEP_TX_MASK); | ||
2997 | if ((ah->ah_isPciExpress) | ||
2998 | || (eeval & AR5416_OPFLAGS_11A)) { | ||
2999 | pCap->halRxChainMask = | ||
3000 | ath9k_hw_get_eeprom(ahp, EEP_RX_MASK); | ||
3001 | } else { | ||
3002 | pCap->halRxChainMask = | ||
3003 | (ath9k_hw_gpio_get(ah, 0)) ? 0x5 : 0x7; | ||
3004 | } | ||
3005 | |||
3006 | if (!(AR_SREV_9280(ah) && (ah->ah_macRev == 0))) | ||
3007 | ahp->ah_miscMode |= AR_PCU_MIC_NEW_LOC_ENA; | ||
3008 | |||
3009 | pCap->halLow2GhzChan = 2312; | ||
3010 | pCap->halHigh2GhzChan = 2732; | ||
3011 | |||
3012 | pCap->halLow5GhzChan = 4920; | ||
3013 | pCap->halHigh5GhzChan = 6100; | ||
3014 | |||
3015 | pCap->halCipherCkipSupport = false; | ||
3016 | pCap->halCipherTkipSupport = true; | ||
3017 | pCap->halCipherAesCcmSupport = true; | ||
3018 | |||
3019 | pCap->halMicCkipSupport = false; | ||
3020 | pCap->halMicTkipSupport = true; | ||
3021 | pCap->halMicAesCcmSupport = true; | ||
3022 | |||
3023 | pCap->halChanSpreadSupport = true; | ||
3024 | |||
3025 | pCap->halHTSupport = | ||
3026 | ah->ah_config.ath_hal_htEnable ? true : false; | ||
3027 | pCap->halGTTSupport = true; | ||
3028 | pCap->halVEOLSupport = true; | ||
3029 | pCap->halBssIdMaskSupport = true; | ||
3030 | pCap->halMcastKeySrchSupport = false; | ||
3031 | |||
3032 | if (capField & AR_EEPROM_EEPCAP_MAXQCU) | ||
3033 | pCap->halTotalQueues = | ||
3034 | MS(capField, AR_EEPROM_EEPCAP_MAXQCU); | ||
3035 | else | ||
3036 | pCap->halTotalQueues = ATH9K_NUM_TX_QUEUES; | ||
3037 | |||
3038 | if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) | ||
3039 | pCap->halKeyCacheSize = | ||
3040 | 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); | ||
3041 | else | ||
3042 | pCap->halKeyCacheSize = AR_KEYTABLE_SIZE; | ||
3043 | |||
3044 | pCap->halFastCCSupport = true; | ||
3045 | pCap->halNumMRRetries = 4; | ||
3046 | pCap->halTxTrigLevelMax = MAX_TX_FIFO_THRESHOLD; | ||
3047 | |||
3048 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
3049 | pCap->halNumGpioPins = AR928X_NUM_GPIO; | ||
3050 | else | ||
3051 | pCap->halNumGpioPins = AR_NUM_GPIO; | ||
3052 | |||
3053 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3054 | pCap->halWowSupport = true; | ||
3055 | pCap->halWowMatchPatternExact = true; | ||
3056 | } else { | ||
3057 | pCap->halWowSupport = false; | ||
3058 | pCap->halWowMatchPatternExact = false; | ||
3059 | } | ||
3060 | |||
3061 | if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { | ||
3062 | pCap->halCSTSupport = true; | ||
3063 | pCap->halRtsAggrLimit = ATH_AMPDU_LIMIT_MAX; | ||
3064 | } else { | ||
3065 | pCap->halRtsAggrLimit = (8 * 1024); | ||
3066 | } | ||
3067 | |||
3068 | pCap->halEnhancedPmSupport = true; | ||
3069 | |||
3070 | ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT); | ||
3071 | if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) { | ||
3072 | ahp->ah_gpioSelect = | ||
3073 | MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL); | ||
3074 | ahp->ah_polarity = | ||
3075 | MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY); | ||
3076 | |||
3077 | ath9k_hw_setcapability(ah, HAL_CAP_RFSILENT, 1, true, | ||
3078 | NULL); | ||
3079 | pCap->halRfSilentSupport = true; | ||
3080 | } | ||
3081 | |||
3082 | if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) || | ||
3083 | (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) || | ||
3084 | (ah->ah_macVersion == AR_SREV_VERSION_9160) || | ||
3085 | (ah->ah_macVersion == AR_SREV_VERSION_9100) || | ||
3086 | (ah->ah_macVersion == AR_SREV_VERSION_9280)) | ||
3087 | pCap->halAutoSleepSupport = false; | ||
3088 | else | ||
3089 | pCap->halAutoSleepSupport = true; | ||
3090 | |||
3091 | if (AR_SREV_9280(ah)) | ||
3092 | pCap->hal4kbSplitTransSupport = false; | ||
3093 | else | ||
3094 | pCap->hal4kbSplitTransSupport = true; | ||
3095 | |||
3096 | if (ah->ah_currentRDExt & (1 << REG_EXT_JAPAN_MIDBAND)) { | ||
3097 | pCap->halRegCap = | ||
3098 | AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | | ||
3099 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | | ||
3100 | AR_EEPROM_EEREGCAP_EN_KK_U2 | | ||
3101 | AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; | ||
3102 | } else { | ||
3103 | pCap->halRegCap = | ||
3104 | AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | | ||
3105 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; | ||
3106 | } | ||
3107 | |||
3108 | pCap->halRegCap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; | ||
3109 | |||
3110 | pCap->halNumAntCfg5GHz = | ||
3111 | ath9k_hw_get_num_ant_config(ahp, HAL_FREQ_BAND_5GHZ); | ||
3112 | pCap->halNumAntCfg2GHz = | ||
3113 | ath9k_hw_get_num_ant_config(ahp, HAL_FREQ_BAND_2GHZ); | ||
3114 | |||
3115 | return true; | ||
3116 | } | ||
3117 | |||
3118 | static void ar5416DisablePciePhy(struct ath_hal *ah) | ||
3119 | { | ||
3120 | if (!AR_SREV_9100(ah)) | ||
3121 | return; | ||
3122 | |||
3123 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); | ||
3124 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
3125 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); | ||
3126 | REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824); | ||
3127 | REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579); | ||
3128 | REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000); | ||
3129 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | ||
3130 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
3131 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); | ||
3132 | |||
3133 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | ||
3134 | } | ||
3135 | |||
3136 | static void ath9k_set_power_sleep(struct ath_hal *ah, int setChip) | ||
3137 | { | ||
3138 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | ||
3139 | if (setChip) { | ||
3140 | REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, | ||
3141 | AR_RTC_FORCE_WAKE_EN); | ||
3142 | if (!AR_SREV_9100(ah)) | ||
3143 | REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); | ||
3144 | |||
3145 | REG_CLR_BIT(ah, (u16) (AR_RTC_RESET), | ||
3146 | AR_RTC_RESET_EN); | ||
3147 | } | ||
3148 | } | ||
3149 | |||
3150 | static void ath9k_set_power_network_sleep(struct ath_hal *ah, int setChip) | ||
3151 | { | ||
3152 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | ||
3153 | if (setChip) { | ||
3154 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
3155 | |||
3156 | if (!pCap->halAutoSleepSupport) { | ||
3157 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, | ||
3158 | AR_RTC_FORCE_WAKE_ON_INT); | ||
3159 | } else { | ||
3160 | REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, | ||
3161 | AR_RTC_FORCE_WAKE_EN); | ||
3162 | } | ||
3163 | } | ||
3164 | } | ||
3165 | |||
3166 | static bool ath9k_hw_set_power_awake(struct ath_hal *ah, | ||
3167 | int setChip) | ||
3168 | { | ||
3169 | u32 val; | ||
3170 | int i; | ||
3171 | |||
3172 | if (setChip) { | ||
3173 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == | ||
3174 | AR_RTC_STATUS_SHUTDOWN) { | ||
3175 | if (ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON) | ||
3176 | != true) { | ||
3177 | return false; | ||
3178 | } | ||
3179 | } | ||
3180 | if (AR_SREV_9100(ah)) | ||
3181 | REG_SET_BIT(ah, AR_RTC_RESET, | ||
3182 | AR_RTC_RESET_EN); | ||
3183 | |||
3184 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, | ||
3185 | AR_RTC_FORCE_WAKE_EN); | ||
3186 | udelay(50); | ||
3187 | |||
3188 | for (i = POWER_UP_TIME / 50; i > 0; i--) { | ||
3189 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; | ||
3190 | if (val == AR_RTC_STATUS_ON) | ||
3191 | break; | ||
3192 | udelay(50); | ||
3193 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, | ||
3194 | AR_RTC_FORCE_WAKE_EN); | ||
3195 | } | ||
3196 | if (i == 0) { | ||
3197 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
3198 | "%s: Failed to wakeup in %uus\n", | ||
3199 | __func__, POWER_UP_TIME / 20); | ||
3200 | return false; | ||
3201 | } | ||
3202 | } | ||
3203 | |||
3204 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | ||
3205 | return true; | ||
3206 | } | ||
3207 | |||
3208 | bool ath9k_hw_setpower(struct ath_hal *ah, | ||
3209 | enum ath9k_power_mode mode) | ||
3210 | { | ||
3211 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
3212 | static const char *modes[] = { | ||
3213 | "AWAKE", | ||
3214 | "FULL-SLEEP", | ||
3215 | "NETWORK SLEEP", | ||
3216 | "UNDEFINED" | ||
3217 | }; | ||
3218 | int status = true, setChip = true; | ||
3219 | |||
3220 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s: %s -> %s (%s)\n", __func__, | ||
3221 | modes[ahp->ah_powerMode], modes[mode], | ||
3222 | setChip ? "set chip " : ""); | ||
3223 | |||
3224 | switch (mode) { | ||
3225 | case ATH9K_PM_AWAKE: | ||
3226 | status = ath9k_hw_set_power_awake(ah, setChip); | ||
3227 | break; | ||
3228 | case ATH9K_PM_FULL_SLEEP: | ||
3229 | ath9k_set_power_sleep(ah, setChip); | ||
3230 | ahp->ah_chipFullSleep = true; | ||
3231 | break; | ||
3232 | case ATH9K_PM_NETWORK_SLEEP: | ||
3233 | ath9k_set_power_network_sleep(ah, setChip); | ||
3234 | break; | ||
3235 | default: | ||
3236 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
3237 | "%s: unknown power mode %u\n", __func__, mode); | ||
3238 | return false; | ||
3239 | } | ||
3240 | ahp->ah_powerMode = mode; | ||
3241 | return status; | ||
3242 | } | ||
3243 | |||
3244 | static struct ath_hal *ath9k_hw_do_attach(u16 devid, | ||
3245 | struct ath_softc *sc, | ||
3246 | void __iomem *mem, | ||
3247 | int *status) | ||
3248 | { | ||
3249 | struct ath_hal_5416 *ahp; | ||
3250 | struct ath_hal *ah; | ||
3251 | int ecode; | ||
3252 | #ifndef CONFIG_SLOW_ANT_DIV | ||
3253 | u32 i; | ||
3254 | u32 j; | ||
3255 | #endif | ||
3256 | |||
3257 | ahp = ath9k_hw_newstate(devid, sc, mem, status); | ||
3258 | if (ahp == NULL) | ||
3259 | return NULL; | ||
3260 | |||
3261 | ah = &ahp->ah; | ||
3262 | |||
3263 | ath9k_hw_set_defaults(ah); | ||
3264 | |||
3265 | if (ah->ah_config.ath_hal_intrMitigation != 0) | ||
3266 | ahp->ah_intrMitigation = true; | ||
3267 | |||
3268 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { | ||
3269 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: couldn't reset chip\n", | ||
3270 | __func__); | ||
3271 | ecode = -EIO; | ||
3272 | goto bad; | ||
3273 | } | ||
3274 | |||
3275 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { | ||
3276 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: couldn't wakeup chip\n", | ||
3277 | __func__); | ||
3278 | ecode = -EIO; | ||
3279 | goto bad; | ||
3280 | } | ||
3281 | |||
3282 | if (ah->ah_config.ath_hal_serializeRegMode == SER_REG_MODE_AUTO) { | ||
3283 | if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) { | ||
3284 | ah->ah_config.ath_hal_serializeRegMode = | ||
3285 | SER_REG_MODE_ON; | ||
3286 | } else { | ||
3287 | ah->ah_config.ath_hal_serializeRegMode = | ||
3288 | SER_REG_MODE_OFF; | ||
3289 | } | ||
3290 | } | ||
3291 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3292 | "%s: ath_hal_serializeRegMode is %d\n", | ||
3293 | __func__, ah->ah_config.ath_hal_serializeRegMode); | ||
3294 | |||
3295 | if ((ah->ah_macVersion != AR_SREV_VERSION_5416_PCI) && | ||
3296 | (ah->ah_macVersion != AR_SREV_VERSION_5416_PCIE) && | ||
3297 | (ah->ah_macVersion != AR_SREV_VERSION_9160) && | ||
3298 | (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah))) { | ||
3299 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3300 | "%s: Mac Chip Rev 0x%02x.%x is not supported by " | ||
3301 | "this driver\n", __func__, | ||
3302 | ah->ah_macVersion, ah->ah_macRev); | ||
3303 | ecode = -EOPNOTSUPP; | ||
3304 | goto bad; | ||
3305 | } | ||
3306 | |||
3307 | if (AR_SREV_9100(ah)) { | ||
3308 | ahp->ah_iqCalData.calData = &iq_cal_multi_sample; | ||
3309 | ahp->ah_suppCals = IQ_MISMATCH_CAL; | ||
3310 | ah->ah_isPciExpress = false; | ||
3311 | } | ||
3312 | ah->ah_phyRev = REG_READ(ah, AR_PHY_CHIP_ID); | ||
3313 | |||
3314 | if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
3315 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3316 | ahp->ah_iqCalData.calData = &iq_cal_single_sample; | ||
3317 | ahp->ah_adcGainCalData.calData = | ||
3318 | &adc_gain_cal_single_sample; | ||
3319 | ahp->ah_adcDcCalData.calData = | ||
3320 | &adc_dc_cal_single_sample; | ||
3321 | ahp->ah_adcDcCalInitData.calData = | ||
3322 | &adc_init_dc_cal; | ||
3323 | } else { | ||
3324 | ahp->ah_iqCalData.calData = &iq_cal_multi_sample; | ||
3325 | ahp->ah_adcGainCalData.calData = | ||
3326 | &adc_gain_cal_multi_sample; | ||
3327 | ahp->ah_adcDcCalData.calData = | ||
3328 | &adc_dc_cal_multi_sample; | ||
3329 | ahp->ah_adcDcCalInitData.calData = | ||
3330 | &adc_init_dc_cal; | ||
3331 | } | ||
3332 | ahp->ah_suppCals = | ||
3333 | ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; | ||
3334 | } | ||
3335 | |||
3336 | if (AR_SREV_9160(ah)) { | ||
3337 | ah->ah_config.ath_hal_enableANI = 1; | ||
3338 | ahp->ah_ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | | ||
3339 | ATH9K_ANI_FIRSTEP_LEVEL); | ||
3340 | } else { | ||
3341 | ahp->ah_ani_function = ATH9K_ANI_ALL; | ||
3342 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3343 | ahp->ah_ani_function &= | ||
3344 | ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | ||
3345 | } | ||
3346 | } | ||
3347 | |||
3348 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3349 | "%s: This Mac Chip Rev 0x%02x.%x is \n", __func__, | ||
3350 | ah->ah_macVersion, ah->ah_macRev); | ||
3351 | |||
3352 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
3353 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280_2, | ||
3354 | ARRAY_SIZE(ar9280Modes_9280_2), 6); | ||
3355 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280_2, | ||
3356 | ARRAY_SIZE(ar9280Common_9280_2), 2); | ||
3357 | |||
3358 | if (ah->ah_config.ath_hal_pcieClockReq) { | ||
3359 | INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes, | ||
3360 | ar9280PciePhy_clkreq_off_L1_9280, | ||
3361 | ARRAY_SIZE | ||
3362 | (ar9280PciePhy_clkreq_off_L1_9280), | ||
3363 | 2); | ||
3364 | } else { | ||
3365 | INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes, | ||
3366 | ar9280PciePhy_clkreq_always_on_L1_9280, | ||
3367 | ARRAY_SIZE | ||
3368 | (ar9280PciePhy_clkreq_always_on_L1_9280), | ||
3369 | 2); | ||
3370 | } | ||
3371 | INIT_INI_ARRAY(&ahp->ah_iniModesAdditional, | ||
3372 | ar9280Modes_fast_clock_9280_2, | ||
3373 | ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), | ||
3374 | 3); | ||
3375 | } else if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3376 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280, | ||
3377 | ARRAY_SIZE(ar9280Modes_9280), 6); | ||
3378 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280, | ||
3379 | ARRAY_SIZE(ar9280Common_9280), 2); | ||
3380 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
3381 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes_9160, | ||
3382 | ARRAY_SIZE(ar5416Modes_9160), 6); | ||
3383 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common_9160, | ||
3384 | ARRAY_SIZE(ar5416Common_9160), 2); | ||
3385 | INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0_9160, | ||
3386 | ARRAY_SIZE(ar5416Bank0_9160), 2); | ||
3387 | INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain_9160, | ||
3388 | ARRAY_SIZE(ar5416BB_RfGain_9160), 3); | ||
3389 | INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1_9160, | ||
3390 | ARRAY_SIZE(ar5416Bank1_9160), 2); | ||
3391 | INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2_9160, | ||
3392 | ARRAY_SIZE(ar5416Bank2_9160), 2); | ||
3393 | INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3_9160, | ||
3394 | ARRAY_SIZE(ar5416Bank3_9160), 3); | ||
3395 | INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6_9160, | ||
3396 | ARRAY_SIZE(ar5416Bank6_9160), 3); | ||
3397 | INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC_9160, | ||
3398 | ARRAY_SIZE(ar5416Bank6TPC_9160), 3); | ||
3399 | INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7_9160, | ||
3400 | ARRAY_SIZE(ar5416Bank7_9160), 2); | ||
3401 | if (AR_SREV_9160_11(ah)) { | ||
3402 | INIT_INI_ARRAY(&ahp->ah_iniAddac, | ||
3403 | ar5416Addac_91601_1, | ||
3404 | ARRAY_SIZE(ar5416Addac_91601_1), 2); | ||
3405 | } else { | ||
3406 | INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac_9160, | ||
3407 | ARRAY_SIZE(ar5416Addac_9160), 2); | ||
3408 | } | ||
3409 | } else if (AR_SREV_9100_OR_LATER(ah)) { | ||
3410 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes_9100, | ||
3411 | ARRAY_SIZE(ar5416Modes_9100), 6); | ||
3412 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common_9100, | ||
3413 | ARRAY_SIZE(ar5416Common_9100), 2); | ||
3414 | INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0_9100, | ||
3415 | ARRAY_SIZE(ar5416Bank0_9100), 2); | ||
3416 | INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain_9100, | ||
3417 | ARRAY_SIZE(ar5416BB_RfGain_9100), 3); | ||
3418 | INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1_9100, | ||
3419 | ARRAY_SIZE(ar5416Bank1_9100), 2); | ||
3420 | INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2_9100, | ||
3421 | ARRAY_SIZE(ar5416Bank2_9100), 2); | ||
3422 | INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3_9100, | ||
3423 | ARRAY_SIZE(ar5416Bank3_9100), 3); | ||
3424 | INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6_9100, | ||
3425 | ARRAY_SIZE(ar5416Bank6_9100), 3); | ||
3426 | INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC_9100, | ||
3427 | ARRAY_SIZE(ar5416Bank6TPC_9100), 3); | ||
3428 | INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7_9100, | ||
3429 | ARRAY_SIZE(ar5416Bank7_9100), 2); | ||
3430 | INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac_9100, | ||
3431 | ARRAY_SIZE(ar5416Addac_9100), 2); | ||
3432 | } else { | ||
3433 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes, | ||
3434 | ARRAY_SIZE(ar5416Modes), 6); | ||
3435 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common, | ||
3436 | ARRAY_SIZE(ar5416Common), 2); | ||
3437 | INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0, | ||
3438 | ARRAY_SIZE(ar5416Bank0), 2); | ||
3439 | INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain, | ||
3440 | ARRAY_SIZE(ar5416BB_RfGain), 3); | ||
3441 | INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1, | ||
3442 | ARRAY_SIZE(ar5416Bank1), 2); | ||
3443 | INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2, | ||
3444 | ARRAY_SIZE(ar5416Bank2), 2); | ||
3445 | INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3, | ||
3446 | ARRAY_SIZE(ar5416Bank3), 3); | ||
3447 | INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6, | ||
3448 | ARRAY_SIZE(ar5416Bank6), 3); | ||
3449 | INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC, | ||
3450 | ARRAY_SIZE(ar5416Bank6TPC), 3); | ||
3451 | INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7, | ||
3452 | ARRAY_SIZE(ar5416Bank7), 2); | ||
3453 | INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac, | ||
3454 | ARRAY_SIZE(ar5416Addac), 2); | ||
3455 | } | ||
3456 | |||
3457 | if (ah->ah_isPciExpress) | ||
3458 | ath9k_hw_configpcipowersave(ah, 0); | ||
3459 | else | ||
3460 | ar5416DisablePciePhy(ah); | ||
3461 | |||
3462 | ecode = ath9k_hw_post_attach(ah); | ||
3463 | if (ecode != 0) | ||
3464 | goto bad; | ||
3465 | |||
3466 | #ifndef CONFIG_SLOW_ANT_DIV | ||
3467 | if (ah->ah_devid == AR9280_DEVID_PCI) { | ||
3468 | for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) { | ||
3469 | u32 reg = INI_RA(&ahp->ah_iniModes, i, 0); | ||
3470 | |||
3471 | for (j = 1; j < ahp->ah_iniModes.ia_columns; j++) { | ||
3472 | u32 val = INI_RA(&ahp->ah_iniModes, i, j); | ||
3473 | |||
3474 | INI_RA(&ahp->ah_iniModes, i, j) = | ||
3475 | ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom, | ||
3476 | reg, val); | ||
3477 | } | ||
3478 | } | ||
3479 | } | ||
3480 | #endif | ||
3481 | |||
3482 | if (!ath9k_hw_fill_cap_info(ah)) { | ||
3483 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3484 | "%s:failed ath9k_hw_fill_cap_info\n", __func__); | ||
3485 | ecode = -EINVAL; | ||
3486 | goto bad; | ||
3487 | } | ||
3488 | |||
3489 | ecode = ath9k_hw_init_macaddr(ah); | ||
3490 | if (ecode != 0) { | ||
3491 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3492 | "%s: failed initializing mac address\n", | ||
3493 | __func__); | ||
3494 | goto bad; | ||
3495 | } | ||
3496 | |||
3497 | if (AR_SREV_9285(ah)) | ||
3498 | ah->ah_txTrigLevel = (AR_FTRIG_256B >> AR_FTRIG_S); | ||
3499 | else | ||
3500 | ah->ah_txTrigLevel = (AR_FTRIG_512B >> AR_FTRIG_S); | ||
3501 | |||
3502 | #ifndef ATH_NF_PER_CHAN | ||
3503 | |||
3504 | ath9k_init_nfcal_hist_buffer(ah); | ||
3505 | #endif | ||
3506 | |||
3507 | return ah; | ||
3508 | |||
3509 | bad: | ||
3510 | if (ahp) | ||
3511 | ath9k_hw_detach((struct ath_hal *) ahp); | ||
3512 | if (status) | ||
3513 | *status = ecode; | ||
3514 | return NULL; | ||
3515 | } | ||
3516 | |||
3517 | void ath9k_hw_detach(struct ath_hal *ah) | ||
3518 | { | ||
3519 | if (!AR_SREV_9100(ah)) | ||
3520 | ath9k_hw_ani_detach(ah); | ||
3521 | ath9k_hw_rfdetach(ah); | ||
3522 | |||
3523 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | ||
3524 | kfree(ah); | ||
3525 | } | ||
3526 | |||
3527 | bool ath9k_get_channel_edges(struct ath_hal *ah, | ||
3528 | u16 flags, u16 *low, | ||
3529 | u16 *high) | ||
3530 | { | ||
3531 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
3532 | |||
3533 | if (flags & CHANNEL_5GHZ) { | ||
3534 | *low = pCap->halLow5GhzChan; | ||
3535 | *high = pCap->halHigh5GhzChan; | ||
3536 | return true; | ||
3537 | } | ||
3538 | if ((flags & CHANNEL_2GHZ)) { | ||
3539 | *low = pCap->halLow2GhzChan; | ||
3540 | *high = pCap->halHigh2GhzChan; | ||
3541 | |||
3542 | return true; | ||
3543 | } | ||
3544 | return false; | ||
3545 | } | ||
3546 | |||
3547 | static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, | ||
3548 | u8 pwrMax, | ||
3549 | u8 *pPwrList, | ||
3550 | u8 *pVpdList, | ||
3551 | u16 | ||
3552 | numIntercepts, | ||
3553 | u8 *pRetVpdList) | ||
3554 | { | ||
3555 | u16 i, k; | ||
3556 | u8 currPwr = pwrMin; | ||
3557 | u16 idxL = 0, idxR = 0; | ||
3558 | |||
3559 | for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { | ||
3560 | ath9k_hw_get_lower_upper_index(currPwr, pPwrList, | ||
3561 | numIntercepts, &(idxL), | ||
3562 | &(idxR)); | ||
3563 | if (idxR < 1) | ||
3564 | idxR = 1; | ||
3565 | if (idxL == numIntercepts - 1) | ||
3566 | idxL = (u16) (numIntercepts - 2); | ||
3567 | if (pPwrList[idxL] == pPwrList[idxR]) | ||
3568 | k = pVpdList[idxL]; | ||
3569 | else | ||
3570 | k = (u16) (((currPwr - | ||
3571 | pPwrList[idxL]) * | ||
3572 | pVpdList[idxR] + | ||
3573 | (pPwrList[idxR] - | ||
3574 | currPwr) * pVpdList[idxL]) / | ||
3575 | (pPwrList[idxR] - | ||
3576 | pPwrList[idxL])); | ||
3577 | pRetVpdList[i] = (u8) k; | ||
3578 | currPwr += 2; | ||
3579 | } | ||
3580 | |||
3581 | return true; | ||
3582 | } | ||
3583 | |||
3584 | static inline void | ||
3585 | ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah, | ||
3586 | struct ath9k_channel *chan, | ||
3587 | struct cal_data_per_freq *pRawDataSet, | ||
3588 | u8 *bChans, | ||
3589 | u16 availPiers, | ||
3590 | u16 tPdGainOverlap, | ||
3591 | int16_t *pMinCalPower, | ||
3592 | u16 *pPdGainBoundaries, | ||
3593 | u8 *pPDADCValues, | ||
3594 | u16 numXpdGains) | ||
3595 | { | ||
3596 | int i, j, k; | ||
3597 | int16_t ss; | ||
3598 | u16 idxL = 0, idxR = 0, numPiers; | ||
3599 | static u8 vpdTableL[AR5416_NUM_PD_GAINS] | ||
3600 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3601 | static u8 vpdTableR[AR5416_NUM_PD_GAINS] | ||
3602 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3603 | static u8 vpdTableI[AR5416_NUM_PD_GAINS] | ||
3604 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3605 | |||
3606 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
3607 | u8 minPwrT4[AR5416_NUM_PD_GAINS]; | ||
3608 | u8 maxPwrT4[AR5416_NUM_PD_GAINS]; | ||
3609 | int16_t vpdStep; | ||
3610 | int16_t tmpVal; | ||
3611 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
3612 | bool match; | ||
3613 | int16_t minDelta = 0; | ||
3614 | struct chan_centers centers; | ||
3615 | |||
3616 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3617 | |||
3618 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
3619 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
3620 | break; | ||
3621 | } | ||
3622 | |||
3623 | match = ath9k_hw_get_lower_upper_index((u8) | ||
3624 | FREQ2FBIN(centers. | ||
3625 | synth_center, | ||
3626 | IS_CHAN_2GHZ | ||
3627 | (chan)), bChans, | ||
3628 | numPiers, &idxL, &idxR); | ||
3629 | |||
3630 | if (match) { | ||
3631 | for (i = 0; i < numXpdGains; i++) { | ||
3632 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
3633 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
3634 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3635 | pRawDataSet[idxL]. | ||
3636 | pwrPdg[i], | ||
3637 | pRawDataSet[idxL]. | ||
3638 | vpdPdg[i], | ||
3639 | AR5416_PD_GAIN_ICEPTS, | ||
3640 | vpdTableI[i]); | ||
3641 | } | ||
3642 | } else { | ||
3643 | for (i = 0; i < numXpdGains; i++) { | ||
3644 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
3645 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
3646 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
3647 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
3648 | |||
3649 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
3650 | |||
3651 | maxPwrT4[i] = | ||
3652 | min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], | ||
3653 | pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); | ||
3654 | |||
3655 | |||
3656 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3657 | pPwrL, pVpdL, | ||
3658 | AR5416_PD_GAIN_ICEPTS, | ||
3659 | vpdTableL[i]); | ||
3660 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3661 | pPwrR, pVpdR, | ||
3662 | AR5416_PD_GAIN_ICEPTS, | ||
3663 | vpdTableR[i]); | ||
3664 | |||
3665 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
3666 | vpdTableI[i][j] = | ||
3667 | (u8) (ath9k_hw_interpolate | ||
3668 | ((u16) | ||
3669 | FREQ2FBIN(centers. | ||
3670 | synth_center, | ||
3671 | IS_CHAN_2GHZ | ||
3672 | (chan)), | ||
3673 | bChans[idxL], | ||
3674 | bChans[idxR], vpdTableL[i] | ||
3675 | [j], vpdTableR[i] | ||
3676 | [j])); | ||
3677 | } | ||
3678 | } | ||
3679 | } | ||
3680 | |||
3681 | *pMinCalPower = (int16_t) (minPwrT4[0] / 2); | ||
3682 | |||
3683 | k = 0; | ||
3684 | for (i = 0; i < numXpdGains; i++) { | ||
3685 | if (i == (numXpdGains - 1)) | ||
3686 | pPdGainBoundaries[i] = | ||
3687 | (u16) (maxPwrT4[i] / 2); | ||
3688 | else | ||
3689 | pPdGainBoundaries[i] = | ||
3690 | (u16) ((maxPwrT4[i] + | ||
3691 | minPwrT4[i + 1]) / 4); | ||
3692 | |||
3693 | pPdGainBoundaries[i] = | ||
3694 | min((u16) AR5416_MAX_RATE_POWER, | ||
3695 | pPdGainBoundaries[i]); | ||
3696 | |||
3697 | if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) { | ||
3698 | minDelta = pPdGainBoundaries[0] - 23; | ||
3699 | pPdGainBoundaries[0] = 23; | ||
3700 | } else { | ||
3701 | minDelta = 0; | ||
3702 | } | ||
3703 | |||
3704 | if (i == 0) { | ||
3705 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
3706 | ss = (int16_t) (0 - (minPwrT4[i] / 2)); | ||
3707 | else | ||
3708 | ss = 0; | ||
3709 | } else { | ||
3710 | ss = (int16_t) ((pPdGainBoundaries[i - 1] - | ||
3711 | (minPwrT4[i] / 2)) - | ||
3712 | tPdGainOverlap + 1 + minDelta); | ||
3713 | } | ||
3714 | vpdStep = (int16_t) (vpdTableI[i][1] - vpdTableI[i][0]); | ||
3715 | vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep); | ||
3716 | |||
3717 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
3718 | tmpVal = (int16_t) (vpdTableI[i][0] + ss * vpdStep); | ||
3719 | pPDADCValues[k++] = | ||
3720 | (u8) ((tmpVal < 0) ? 0 : tmpVal); | ||
3721 | ss++; | ||
3722 | } | ||
3723 | |||
3724 | sizeCurrVpdTable = | ||
3725 | (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
3726 | tgtIndex = (u8) (pPdGainBoundaries[i] + tPdGainOverlap - | ||
3727 | (minPwrT4[i] / 2)); | ||
3728 | maxIndex = (tgtIndex < | ||
3729 | sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; | ||
3730 | |||
3731 | while ((ss < maxIndex) | ||
3732 | && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
3733 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
3734 | } | ||
3735 | |||
3736 | vpdStep = (int16_t) (vpdTableI[i][sizeCurrVpdTable - 1] - | ||
3737 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
3738 | vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep); | ||
3739 | |||
3740 | if (tgtIndex > maxIndex) { | ||
3741 | while ((ss <= tgtIndex) | ||
3742 | && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
3743 | tmpVal = (int16_t) ((vpdTableI[i] | ||
3744 | [sizeCurrVpdTable - | ||
3745 | 1] + (ss - maxIndex + | ||
3746 | 1) * vpdStep)); | ||
3747 | pPDADCValues[k++] = (u8) ((tmpVal > | ||
3748 | 255) ? 255 : tmpVal); | ||
3749 | ss++; | ||
3750 | } | ||
3751 | } | ||
3752 | } | ||
3753 | |||
3754 | while (i < AR5416_PD_GAINS_IN_MASK) { | ||
3755 | pPdGainBoundaries[i] = pPdGainBoundaries[i - 1]; | ||
3756 | i++; | ||
3757 | } | ||
3758 | |||
3759 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
3760 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
3761 | k++; | ||
3762 | } | ||
3763 | return; | ||
3764 | } | ||
3765 | |||
3766 | static inline bool | ||
3767 | ath9k_hw_set_power_cal_table(struct ath_hal *ah, | ||
3768 | struct ar5416_eeprom *pEepData, | ||
3769 | struct ath9k_channel *chan, | ||
3770 | int16_t *pTxPowerIndexOffset) | ||
3771 | { | ||
3772 | struct cal_data_per_freq *pRawDataset; | ||
3773 | u8 *pCalBChans = NULL; | ||
3774 | u16 pdGainOverlap_t2; | ||
3775 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | ||
3776 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; | ||
3777 | u16 numPiers, i, j; | ||
3778 | int16_t tMinCalPower; | ||
3779 | u16 numXpdGain, xpdMask; | ||
3780 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; | ||
3781 | u32 reg32, regOffset, regChainOffset; | ||
3782 | int16_t modalIdx; | ||
3783 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
3784 | |||
3785 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | ||
3786 | xpdMask = pEepData->modalHeader[modalIdx].xpdGain; | ||
3787 | |||
3788 | if ((pEepData->baseEepHeader. | ||
3789 | version & AR5416_EEP_VER_MINOR_MASK) >= | ||
3790 | AR5416_EEP_MINOR_VER_2) { | ||
3791 | pdGainOverlap_t2 = | ||
3792 | pEepData->modalHeader[modalIdx].pdGainOverlap; | ||
3793 | } else { | ||
3794 | pdGainOverlap_t2 = | ||
3795 | (u16) (MS | ||
3796 | (REG_READ(ah, AR_PHY_TPCRG5), | ||
3797 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
3798 | } | ||
3799 | |||
3800 | if (IS_CHAN_2GHZ(chan)) { | ||
3801 | pCalBChans = pEepData->calFreqPier2G; | ||
3802 | numPiers = AR5416_NUM_2G_CAL_PIERS; | ||
3803 | } else { | ||
3804 | pCalBChans = pEepData->calFreqPier5G; | ||
3805 | numPiers = AR5416_NUM_5G_CAL_PIERS; | ||
3806 | } | ||
3807 | |||
3808 | numXpdGain = 0; | ||
3809 | |||
3810 | for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { | ||
3811 | if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { | ||
3812 | if (numXpdGain >= AR5416_NUM_PD_GAINS) | ||
3813 | break; | ||
3814 | xpdGainValues[numXpdGain] = | ||
3815 | (u16) (AR5416_PD_GAINS_IN_MASK - i); | ||
3816 | numXpdGain++; | ||
3817 | } | ||
3818 | } | ||
3819 | |||
3820 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
3821 | (numXpdGain - 1) & 0x3); | ||
3822 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
3823 | xpdGainValues[0]); | ||
3824 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
3825 | xpdGainValues[1]); | ||
3826 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, | ||
3827 | xpdGainValues[2]); | ||
3828 | |||
3829 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
3830 | if (AR_SREV_5416_V20_OR_LATER(ah) && | ||
3831 | (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) | ||
3832 | && (i != 0)) { | ||
3833 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
3834 | } else | ||
3835 | regChainOffset = i * 0x1000; | ||
3836 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
3837 | if (IS_CHAN_2GHZ(chan)) | ||
3838 | pRawDataset = pEepData->calPierData2G[i]; | ||
3839 | else | ||
3840 | pRawDataset = pEepData->calPierData5G[i]; | ||
3841 | |||
3842 | ath9k_hw_get_gain_boundaries_pdadcs(ah, chan, | ||
3843 | pRawDataset, | ||
3844 | pCalBChans, | ||
3845 | numPiers, | ||
3846 | pdGainOverlap_t2, | ||
3847 | &tMinCalPower, | ||
3848 | gainBoundaries, | ||
3849 | pdadcValues, | ||
3850 | numXpdGain); | ||
3851 | |||
3852 | if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { | ||
3853 | |||
3854 | REG_WRITE(ah, | ||
3855 | AR_PHY_TPCRG5 + regChainOffset, | ||
3856 | SM(pdGainOverlap_t2, | ||
3857 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | ||
3858 | | SM(gainBoundaries[0], | ||
3859 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | ||
3860 | | SM(gainBoundaries[1], | ||
3861 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | ||
3862 | | SM(gainBoundaries[2], | ||
3863 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | ||
3864 | | SM(gainBoundaries[3], | ||
3865 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | ||
3866 | } | ||
3867 | |||
3868 | regOffset = | ||
3869 | AR_PHY_BASE + (672 << 2) + regChainOffset; | ||
3870 | for (j = 0; j < 32; j++) { | ||
3871 | reg32 = | ||
3872 | ((pdadcValues[4 * j + 0] & 0xFF) << 0) | ||
3873 | | ((pdadcValues[4 * j + 1] & 0xFF) << | ||
3874 | 8) | ((pdadcValues[4 * j + 2] & | ||
3875 | 0xFF) << 16) | | ||
3876 | ((pdadcValues[4 * j + 3] & 0xFF) << | ||
3877 | 24); | ||
3878 | REG_WRITE(ah, regOffset, reg32); | ||
3879 | |||
3880 | DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO, | ||
3881 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
3882 | i, regChainOffset, regOffset, | ||
3883 | reg32); | ||
3884 | DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO, | ||
3885 | "PDADC: Chain %d | PDADC %3d Value %3d | " | ||
3886 | "PDADC %3d Value %3d | PDADC %3d Value %3d | " | ||
3887 | "PDADC %3d Value %3d |\n", | ||
3888 | i, 4 * j, pdadcValues[4 * j], | ||
3889 | 4 * j + 1, pdadcValues[4 * j + 1], | ||
3890 | 4 * j + 2, pdadcValues[4 * j + 2], | ||
3891 | 4 * j + 3, | ||
3892 | pdadcValues[4 * j + 3]); | ||
3893 | |||
3894 | regOffset += 4; | ||
3895 | } | ||
3896 | } | ||
3897 | } | ||
3898 | *pTxPowerIndexOffset = 0; | ||
3899 | |||
3900 | return true; | ||
3901 | } | ||
3902 | |||
3903 | void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore) | ||
3904 | { | ||
3905 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
3906 | u8 i; | ||
3907 | |||
3908 | if (ah->ah_isPciExpress != true) | ||
3909 | return; | ||
3910 | |||
3911 | if (ah->ah_config.ath_hal_pciePowerSaveEnable == 2) | ||
3912 | return; | ||
3913 | |||
3914 | if (restore) | ||
3915 | return; | ||
3916 | |||
3917 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
3918 | for (i = 0; i < ahp->ah_iniPcieSerdes.ia_rows; i++) { | ||
3919 | REG_WRITE(ah, INI_RA(&ahp->ah_iniPcieSerdes, i, 0), | ||
3920 | INI_RA(&ahp->ah_iniPcieSerdes, i, 1)); | ||
3921 | } | ||
3922 | udelay(1000); | ||
3923 | } else if (AR_SREV_9280(ah) | ||
3924 | && (ah->ah_macRev == AR_SREV_REVISION_9280_10)) { | ||
3925 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); | ||
3926 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
3927 | |||
3928 | REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); | ||
3929 | REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); | ||
3930 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); | ||
3931 | |||
3932 | if (ah->ah_config.ath_hal_pcieClockReq) | ||
3933 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); | ||
3934 | else | ||
3935 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); | ||
3936 | |||
3937 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | ||
3938 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
3939 | REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); | ||
3940 | |||
3941 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | ||
3942 | |||
3943 | udelay(1000); | ||
3944 | } else { | ||
3945 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); | ||
3946 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
3947 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); | ||
3948 | REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); | ||
3949 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); | ||
3950 | REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); | ||
3951 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | ||
3952 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
3953 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); | ||
3954 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | ||
3955 | } | ||
3956 | |||
3957 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | ||
3958 | |||
3959 | if (ah->ah_config.ath_hal_pcieWaen) { | ||
3960 | REG_WRITE(ah, AR_WA, ah->ah_config.ath_hal_pcieWaen); | ||
3961 | } else { | ||
3962 | if (AR_SREV_9280(ah)) | ||
3963 | REG_WRITE(ah, AR_WA, 0x0040073f); | ||
3964 | else | ||
3965 | REG_WRITE(ah, AR_WA, 0x0000073f); | ||
3966 | } | ||
3967 | } | ||
3968 | |||
3969 | static inline void | ||
3970 | ath9k_hw_get_legacy_target_powers(struct ath_hal *ah, | ||
3971 | struct ath9k_channel *chan, | ||
3972 | struct cal_target_power_leg *powInfo, | ||
3973 | u16 numChannels, | ||
3974 | struct cal_target_power_leg *pNewPower, | ||
3975 | u16 numRates, | ||
3976 | bool isExtTarget) | ||
3977 | { | ||
3978 | u16 clo, chi; | ||
3979 | int i; | ||
3980 | int matchIndex = -1, lowIndex = -1; | ||
3981 | u16 freq; | ||
3982 | struct chan_centers centers; | ||
3983 | |||
3984 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3985 | freq = (isExtTarget) ? centers.ext_center : centers.ctl_center; | ||
3986 | |||
3987 | if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, | ||
3988 | IS_CHAN_2GHZ(chan))) { | ||
3989 | matchIndex = 0; | ||
3990 | } else { | ||
3991 | for (i = 0; (i < numChannels) | ||
3992 | && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { | ||
3993 | if (freq == | ||
3994 | ath9k_hw_fbin2freq(powInfo[i].bChannel, | ||
3995 | IS_CHAN_2GHZ(chan))) { | ||
3996 | matchIndex = i; | ||
3997 | break; | ||
3998 | } else if ((freq < | ||
3999 | ath9k_hw_fbin2freq(powInfo[i].bChannel, | ||
4000 | IS_CHAN_2GHZ(chan))) | ||
4001 | && (freq > | ||
4002 | ath9k_hw_fbin2freq(powInfo[i - 1]. | ||
4003 | bChannel, | ||
4004 | IS_CHAN_2GHZ | ||
4005 | (chan)))) { | ||
4006 | lowIndex = i - 1; | ||
4007 | break; | ||
4008 | } | ||
4009 | } | ||
4010 | if ((matchIndex == -1) && (lowIndex == -1)) | ||
4011 | matchIndex = i - 1; | ||
4012 | } | ||
4013 | |||
4014 | if (matchIndex != -1) { | ||
4015 | *pNewPower = powInfo[matchIndex]; | ||
4016 | } else { | ||
4017 | clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, | ||
4018 | IS_CHAN_2GHZ(chan)); | ||
4019 | chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, | ||
4020 | IS_CHAN_2GHZ(chan)); | ||
4021 | |||
4022 | for (i = 0; i < numRates; i++) { | ||
4023 | pNewPower->tPow2x[i] = | ||
4024 | (u8) ath9k_hw_interpolate(freq, clo, chi, | ||
4025 | powInfo | ||
4026 | [lowIndex]. | ||
4027 | tPow2x[i], | ||
4028 | powInfo | ||
4029 | [lowIndex + | ||
4030 | 1].tPow2x[i]); | ||
4031 | } | ||
4032 | } | ||
4033 | } | ||
4034 | |||
4035 | static inline void | ||
4036 | ath9k_hw_get_target_powers(struct ath_hal *ah, | ||
4037 | struct ath9k_channel *chan, | ||
4038 | struct cal_target_power_ht *powInfo, | ||
4039 | u16 numChannels, | ||
4040 | struct cal_target_power_ht *pNewPower, | ||
4041 | u16 numRates, | ||
4042 | bool isHt40Target) | ||
4043 | { | ||
4044 | u16 clo, chi; | ||
4045 | int i; | ||
4046 | int matchIndex = -1, lowIndex = -1; | ||
4047 | u16 freq; | ||
4048 | struct chan_centers centers; | ||
4049 | |||
4050 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
4051 | freq = isHt40Target ? centers.synth_center : centers.ctl_center; | ||
4052 | |||
4053 | if (freq <= | ||
4054 | ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) { | ||
4055 | matchIndex = 0; | ||
4056 | } else { | ||
4057 | for (i = 0; (i < numChannels) | ||
4058 | && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { | ||
4059 | if (freq == | ||
4060 | ath9k_hw_fbin2freq(powInfo[i].bChannel, | ||
4061 | IS_CHAN_2GHZ(chan))) { | ||
4062 | matchIndex = i; | ||
4063 | break; | ||
4064 | } else | ||
4065 | if ((freq < | ||
4066 | ath9k_hw_fbin2freq(powInfo[i].bChannel, | ||
4067 | IS_CHAN_2GHZ(chan))) | ||
4068 | && (freq > | ||
4069 | ath9k_hw_fbin2freq(powInfo[i - 1]. | ||
4070 | bChannel, | ||
4071 | IS_CHAN_2GHZ | ||
4072 | (chan)))) { | ||
4073 | lowIndex = i - 1; | ||
4074 | break; | ||
4075 | } | ||
4076 | } | ||
4077 | if ((matchIndex == -1) && (lowIndex == -1)) | ||
4078 | matchIndex = i - 1; | ||
4079 | } | ||
4080 | |||
4081 | if (matchIndex != -1) { | ||
4082 | *pNewPower = powInfo[matchIndex]; | ||
4083 | } else { | ||
4084 | clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, | ||
4085 | IS_CHAN_2GHZ(chan)); | ||
4086 | chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, | ||
4087 | IS_CHAN_2GHZ(chan)); | ||
4088 | |||
4089 | for (i = 0; i < numRates; i++) { | ||
4090 | pNewPower->tPow2x[i] = | ||
4091 | (u8) ath9k_hw_interpolate(freq, clo, chi, | ||
4092 | powInfo | ||
4093 | [lowIndex]. | ||
4094 | tPow2x[i], | ||
4095 | powInfo | ||
4096 | [lowIndex + | ||
4097 | 1].tPow2x[i]); | ||
4098 | } | ||
4099 | } | ||
4100 | } | ||
4101 | |||
4102 | static inline u16 | ||
4103 | ath9k_hw_get_max_edge_power(u16 freq, | ||
4104 | struct cal_ctl_edges *pRdEdgesPower, | ||
4105 | bool is2GHz) | ||
4106 | { | ||
4107 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
4108 | int i; | ||
4109 | |||
4110 | for (i = 0; (i < AR5416_NUM_BAND_EDGES) | ||
4111 | && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) { | ||
4112 | if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, | ||
4113 | is2GHz)) { | ||
4114 | twiceMaxEdgePower = pRdEdgesPower[i].tPower; | ||
4115 | break; | ||
4116 | } else if ((i > 0) | ||
4117 | && (freq < | ||
4118 | ath9k_hw_fbin2freq(pRdEdgesPower[i]. | ||
4119 | bChannel, is2GHz))) { | ||
4120 | if (ath9k_hw_fbin2freq | ||
4121 | (pRdEdgesPower[i - 1].bChannel, is2GHz) < freq | ||
4122 | && pRdEdgesPower[i - 1].flag) { | ||
4123 | twiceMaxEdgePower = | ||
4124 | pRdEdgesPower[i - 1].tPower; | ||
4125 | } | ||
4126 | break; | ||
4127 | } | ||
4128 | } | ||
4129 | return twiceMaxEdgePower; | ||
4130 | } | ||
4131 | |||
4132 | static inline bool | ||
4133 | ath9k_hw_set_power_per_rate_table(struct ath_hal *ah, | ||
4134 | struct ar5416_eeprom *pEepData, | ||
4135 | struct ath9k_channel *chan, | ||
4136 | int16_t *ratesArray, | ||
4137 | u16 cfgCtl, | ||
4138 | u8 AntennaReduction, | ||
4139 | u8 twiceMaxRegulatoryPower, | ||
4140 | u8 powerLimit) | ||
4141 | { | ||
4142 | u8 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
4143 | static const u16 tpScaleReductionTable[5] = | ||
4144 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | ||
4145 | |||
4146 | int i; | ||
4147 | int8_t twiceLargestAntenna; | ||
4148 | struct cal_ctl_data *rep; | ||
4149 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { | ||
4150 | 0, { 0, 0, 0, 0} | ||
4151 | }; | ||
4152 | struct cal_target_power_leg targetPowerOfdmExt = { | ||
4153 | 0, { 0, 0, 0, 0} }, targetPowerCckExt = { | ||
4154 | 0, { 0, 0, 0, 0 } | ||
4155 | }; | ||
4156 | struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { | ||
4157 | 0, {0, 0, 0, 0} | ||
4158 | }; | ||
4159 | u8 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
4160 | u16 ctlModesFor11a[] = | ||
4161 | { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; | ||
4162 | u16 ctlModesFor11g[] = | ||
4163 | { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, | ||
4164 | CTL_2GHT40 | ||
4165 | }; | ||
4166 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | ||
4167 | struct chan_centers centers; | ||
4168 | int tx_chainmask; | ||
4169 | u8 twiceMinEdgePower; | ||
4170 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
4171 | |||
4172 | tx_chainmask = ahp->ah_txchainmask; | ||
4173 | |||
4174 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
4175 | |||
4176 | twiceLargestAntenna = max( | ||
4177 | pEepData->modalHeader | ||
4178 | [IS_CHAN_2GHZ(chan)].antennaGainCh[0], | ||
4179 | pEepData->modalHeader | ||
4180 | [IS_CHAN_2GHZ(chan)].antennaGainCh[1]); | ||
4181 | |||
4182 | twiceLargestAntenna = max((u8) twiceLargestAntenna, | ||
4183 | pEepData->modalHeader | ||
4184 | [IS_CHAN_2GHZ(chan)].antennaGainCh[2]); | ||
4185 | |||
4186 | twiceLargestAntenna = | ||
4187 | (int8_t) min(AntennaReduction - twiceLargestAntenna, 0); | ||
4188 | |||
4189 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
4190 | |||
4191 | if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) { | ||
4192 | maxRegAllowedPower -= | ||
4193 | (tpScaleReductionTable[(ah->ah_tpScale)] * 2); | ||
4194 | } | ||
4195 | |||
4196 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
4197 | |||
4198 | switch (ar5416_get_ntxchains(tx_chainmask)) { | ||
4199 | case 1: | ||
4200 | break; | ||
4201 | case 2: | ||
4202 | scaledPower -= | ||
4203 | pEepData->modalHeader[IS_CHAN_2GHZ(chan)]. | ||
4204 | pwrDecreaseFor2Chain; | ||
4205 | break; | ||
4206 | case 3: | ||
4207 | scaledPower -= | ||
4208 | pEepData->modalHeader[IS_CHAN_2GHZ(chan)]. | ||
4209 | pwrDecreaseFor3Chain; | ||
4210 | break; | ||
4211 | } | ||
4212 | |||
4213 | scaledPower = max(0, (int32_t) scaledPower); | ||
4214 | |||
4215 | if (IS_CHAN_2GHZ(chan)) { | ||
4216 | numCtlModes = | ||
4217 | ARRAY_SIZE(ctlModesFor11g) - | ||
4218 | SUB_NUM_CTL_MODES_AT_2G_40; | ||
4219 | pCtlMode = ctlModesFor11g; | ||
4220 | |||
4221 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4222 | pEepData-> | ||
4223 | calTargetPowerCck, | ||
4224 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
4225 | &targetPowerCck, 4, | ||
4226 | false); | ||
4227 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4228 | pEepData-> | ||
4229 | calTargetPower2G, | ||
4230 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
4231 | &targetPowerOfdm, 4, | ||
4232 | false); | ||
4233 | ath9k_hw_get_target_powers(ah, chan, | ||
4234 | pEepData->calTargetPower2GHT20, | ||
4235 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
4236 | &targetPowerHt20, 8, false); | ||
4237 | |||
4238 | if (IS_CHAN_HT40(chan)) { | ||
4239 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
4240 | ath9k_hw_get_target_powers(ah, chan, | ||
4241 | pEepData-> | ||
4242 | calTargetPower2GHT40, | ||
4243 | AR5416_NUM_2G_40_TARGET_POWERS, | ||
4244 | &targetPowerHt40, 8, | ||
4245 | true); | ||
4246 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4247 | pEepData-> | ||
4248 | calTargetPowerCck, | ||
4249 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
4250 | &targetPowerCckExt, | ||
4251 | 4, true); | ||
4252 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4253 | pEepData-> | ||
4254 | calTargetPower2G, | ||
4255 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
4256 | &targetPowerOfdmExt, | ||
4257 | 4, true); | ||
4258 | } | ||
4259 | } else { | ||
4260 | |||
4261 | numCtlModes = | ||
4262 | ARRAY_SIZE(ctlModesFor11a) - | ||
4263 | SUB_NUM_CTL_MODES_AT_5G_40; | ||
4264 | pCtlMode = ctlModesFor11a; | ||
4265 | |||
4266 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4267 | pEepData-> | ||
4268 | calTargetPower5G, | ||
4269 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
4270 | &targetPowerOfdm, 4, | ||
4271 | false); | ||
4272 | ath9k_hw_get_target_powers(ah, chan, | ||
4273 | pEepData->calTargetPower5GHT20, | ||
4274 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
4275 | &targetPowerHt20, 8, false); | ||
4276 | |||
4277 | if (IS_CHAN_HT40(chan)) { | ||
4278 | numCtlModes = ARRAY_SIZE(ctlModesFor11a); | ||
4279 | ath9k_hw_get_target_powers(ah, chan, | ||
4280 | pEepData-> | ||
4281 | calTargetPower5GHT40, | ||
4282 | AR5416_NUM_5G_40_TARGET_POWERS, | ||
4283 | &targetPowerHt40, 8, | ||
4284 | true); | ||
4285 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4286 | pEepData-> | ||
4287 | calTargetPower5G, | ||
4288 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
4289 | &targetPowerOfdmExt, | ||
4290 | 4, true); | ||
4291 | } | ||
4292 | } | ||
4293 | |||
4294 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
4295 | bool isHt40CtlMode = | ||
4296 | (pCtlMode[ctlMode] == CTL_5GHT40) | ||
4297 | || (pCtlMode[ctlMode] == CTL_2GHT40); | ||
4298 | if (isHt40CtlMode) | ||
4299 | freq = centers.synth_center; | ||
4300 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
4301 | freq = centers.ext_center; | ||
4302 | else | ||
4303 | freq = centers.ctl_center; | ||
4304 | |||
4305 | if (ar5416_get_eep_ver(ahp) == 14 | ||
4306 | && ar5416_get_eep_rev(ahp) <= 2) | ||
4307 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
4308 | |||
4309 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
4310 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " | ||
4311 | "EXT_ADDITIVE %d\n", | ||
4312 | ctlMode, numCtlModes, isHt40CtlMode, | ||
4313 | (pCtlMode[ctlMode] & EXT_ADDITIVE)); | ||
4314 | |||
4315 | for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; | ||
4316 | i++) { | ||
4317 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
4318 | " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " | ||
4319 | "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " | ||
4320 | "chan %d\n", | ||
4321 | i, cfgCtl, pCtlMode[ctlMode], | ||
4322 | pEepData->ctlIndex[i], chan->channel); | ||
4323 | |||
4324 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
4325 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
4326 | pEepData->ctlIndex[i]) | ||
4327 | || | ||
4328 | (((cfgCtl & ~CTL_MODE_M) | | ||
4329 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
4330 | ((pEepData-> | ||
4331 | ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { | ||
4332 | rep = &(pEepData->ctlData[i]); | ||
4333 | |||
4334 | twiceMinEdgePower = | ||
4335 | ath9k_hw_get_max_edge_power(freq, | ||
4336 | rep-> | ||
4337 | ctlEdges | ||
4338 | [ar5416_get_ntxchains | ||
4339 | (tx_chainmask) | ||
4340 | - 1], | ||
4341 | IS_CHAN_2GHZ | ||
4342 | (chan)); | ||
4343 | |||
4344 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
4345 | " MATCH-EE_IDX %d: ch %d is2 %d " | ||
4346 | "2xMinEdge %d chainmask %d chains %d\n", | ||
4347 | i, freq, IS_CHAN_2GHZ(chan), | ||
4348 | twiceMinEdgePower, tx_chainmask, | ||
4349 | ar5416_get_ntxchains | ||
4350 | (tx_chainmask)); | ||
4351 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { | ||
4352 | twiceMaxEdgePower = | ||
4353 | min(twiceMaxEdgePower, | ||
4354 | twiceMinEdgePower); | ||
4355 | } else { | ||
4356 | twiceMaxEdgePower = | ||
4357 | twiceMinEdgePower; | ||
4358 | break; | ||
4359 | } | ||
4360 | } | ||
4361 | } | ||
4362 | |||
4363 | minCtlPower = min(twiceMaxEdgePower, scaledPower); | ||
4364 | |||
4365 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
4366 | " SEL-Min ctlMode %d pCtlMode %d " | ||
4367 | "2xMaxEdge %d sP %d minCtlPwr %d\n", | ||
4368 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, | ||
4369 | scaledPower, minCtlPower); | ||
4370 | |||
4371 | switch (pCtlMode[ctlMode]) { | ||
4372 | case CTL_11B: | ||
4373 | for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); | ||
4374 | i++) { | ||
4375 | targetPowerCck.tPow2x[i] = | ||
4376 | min(targetPowerCck.tPow2x[i], | ||
4377 | minCtlPower); | ||
4378 | } | ||
4379 | break; | ||
4380 | case CTL_11A: | ||
4381 | case CTL_11G: | ||
4382 | for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); | ||
4383 | i++) { | ||
4384 | targetPowerOfdm.tPow2x[i] = | ||
4385 | min(targetPowerOfdm.tPow2x[i], | ||
4386 | minCtlPower); | ||
4387 | } | ||
4388 | break; | ||
4389 | case CTL_5GHT20: | ||
4390 | case CTL_2GHT20: | ||
4391 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); | ||
4392 | i++) { | ||
4393 | targetPowerHt20.tPow2x[i] = | ||
4394 | min(targetPowerHt20.tPow2x[i], | ||
4395 | minCtlPower); | ||
4396 | } | ||
4397 | break; | ||
4398 | case CTL_11B_EXT: | ||
4399 | targetPowerCckExt.tPow2x[0] = | ||
4400 | min(targetPowerCckExt.tPow2x[0], minCtlPower); | ||
4401 | break; | ||
4402 | case CTL_11A_EXT: | ||
4403 | case CTL_11G_EXT: | ||
4404 | targetPowerOfdmExt.tPow2x[0] = | ||
4405 | min(targetPowerOfdmExt.tPow2x[0], minCtlPower); | ||
4406 | break; | ||
4407 | case CTL_5GHT40: | ||
4408 | case CTL_2GHT40: | ||
4409 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); | ||
4410 | i++) { | ||
4411 | targetPowerHt40.tPow2x[i] = | ||
4412 | min(targetPowerHt40.tPow2x[i], | ||
4413 | minCtlPower); | ||
4414 | } | ||
4415 | break; | ||
4416 | default: | ||
4417 | break; | ||
4418 | } | ||
4419 | } | ||
4420 | |||
4421 | ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = | ||
4422 | ratesArray[rate18mb] = ratesArray[rate24mb] = | ||
4423 | targetPowerOfdm.tPow2x[0]; | ||
4424 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
4425 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
4426 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
4427 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
4428 | |||
4429 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
4430 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
4431 | |||
4432 | if (IS_CHAN_2GHZ(chan)) { | ||
4433 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
4434 | ratesArray[rate2s] = ratesArray[rate2l] = | ||
4435 | targetPowerCck.tPow2x[1]; | ||
4436 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = | ||
4437 | targetPowerCck.tPow2x[2]; | ||
4438 | ; | ||
4439 | ratesArray[rate11s] = ratesArray[rate11l] = | ||
4440 | targetPowerCck.tPow2x[3]; | ||
4441 | ; | ||
4442 | } | ||
4443 | if (IS_CHAN_HT40(chan)) { | ||
4444 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
4445 | ratesArray[rateHt40_0 + i] = | ||
4446 | targetPowerHt40.tPow2x[i]; | ||
4447 | } | ||
4448 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
4449 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
4450 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
4451 | if (IS_CHAN_2GHZ(chan)) { | ||
4452 | ratesArray[rateExtCck] = | ||
4453 | targetPowerCckExt.tPow2x[0]; | ||
4454 | } | ||
4455 | } | ||
4456 | return true; | ||
4457 | } | ||
4458 | |||
4459 | static int | ||
4460 | ath9k_hw_set_txpower(struct ath_hal *ah, | ||
4461 | struct ar5416_eeprom *pEepData, | ||
4462 | struct ath9k_channel *chan, | ||
4463 | u16 cfgCtl, | ||
4464 | u8 twiceAntennaReduction, | ||
4465 | u8 twiceMaxRegulatoryPower, | ||
4466 | u8 powerLimit) | ||
4467 | { | ||
4468 | struct modal_eep_header *pModal = | ||
4469 | &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
4470 | int16_t ratesArray[Ar5416RateSize]; | ||
4471 | int16_t txPowerIndexOffset = 0; | ||
4472 | u8 ht40PowerIncForPdadc = 2; | ||
4473 | int i; | ||
4474 | |||
4475 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
4476 | |||
4477 | if ((pEepData->baseEepHeader. | ||
4478 | version & AR5416_EEP_VER_MINOR_MASK) >= | ||
4479 | AR5416_EEP_MINOR_VER_2) { | ||
4480 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
4481 | } | ||
4482 | |||
4483 | if (!ath9k_hw_set_power_per_rate_table(ah, pEepData, chan, | ||
4484 | &ratesArray[0], cfgCtl, | ||
4485 | twiceAntennaReduction, | ||
4486 | twiceMaxRegulatoryPower, | ||
4487 | powerLimit)) { | ||
4488 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
4489 | "ath9k_hw_set_txpower: unable to set " | ||
4490 | "tx power per rate table\n"); | ||
4491 | return -EIO; | ||
4492 | } | ||
4493 | |||
4494 | if (!ath9k_hw_set_power_cal_table | ||
4495 | (ah, pEepData, chan, &txPowerIndexOffset)) { | ||
4496 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
4497 | "ath9k_hw_set_txpower: unable to set power table\n"); | ||
4498 | return -EIO; | ||
4499 | } | ||
4500 | |||
4501 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
4502 | ratesArray[i] = | ||
4503 | (int16_t) (txPowerIndexOffset + ratesArray[i]); | ||
4504 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) | ||
4505 | ratesArray[i] = AR5416_MAX_RATE_POWER; | ||
4506 | } | ||
4507 | |||
4508 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
4509 | for (i = 0; i < Ar5416RateSize; i++) | ||
4510 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | ||
4511 | } | ||
4512 | |||
4513 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
4514 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
4515 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
4516 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
4517 | | ATH9K_POW_SM(ratesArray[rate6mb], 0) | ||
4518 | ); | ||
4519 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
4520 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
4521 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
4522 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
4523 | | ATH9K_POW_SM(ratesArray[rate24mb], 0) | ||
4524 | ); | ||
4525 | |||
4526 | if (IS_CHAN_2GHZ(chan)) { | ||
4527 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
4528 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
4529 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
4530 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
4531 | | ATH9K_POW_SM(ratesArray[rate1l], 0) | ||
4532 | ); | ||
4533 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
4534 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
4535 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
4536 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
4537 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0) | ||
4538 | ); | ||
4539 | } | ||
4540 | |||
4541 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
4542 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
4543 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
4544 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
4545 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0) | ||
4546 | ); | ||
4547 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
4548 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
4549 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
4550 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
4551 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0) | ||
4552 | ); | ||
4553 | |||
4554 | if (IS_CHAN_HT40(chan)) { | ||
4555 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
4556 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
4557 | ht40PowerIncForPdadc, 24) | ||
4558 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
4559 | ht40PowerIncForPdadc, 16) | ||
4560 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
4561 | ht40PowerIncForPdadc, 8) | ||
4562 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
4563 | ht40PowerIncForPdadc, 0) | ||
4564 | ); | ||
4565 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
4566 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
4567 | ht40PowerIncForPdadc, 24) | ||
4568 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
4569 | ht40PowerIncForPdadc, 16) | ||
4570 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
4571 | ht40PowerIncForPdadc, 8) | ||
4572 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
4573 | ht40PowerIncForPdadc, 0) | ||
4574 | ); | ||
4575 | |||
4576 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
4577 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
4578 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
4579 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
4580 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0) | ||
4581 | ); | ||
4582 | } | ||
4583 | |||
4584 | REG_WRITE(ah, AR_PHY_POWER_TX_SUB, | ||
4585 | ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | ||
4586 | | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0) | ||
4587 | ); | ||
4588 | |||
4589 | i = rate6mb; | ||
4590 | if (IS_CHAN_HT40(chan)) | ||
4591 | i = rateHt40_0; | ||
4592 | else if (IS_CHAN_HT20(chan)) | ||
4593 | i = rateHt20_0; | ||
4594 | |||
4595 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
4596 | ah->ah_maxPowerLevel = | ||
4597 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; | ||
4598 | else | ||
4599 | ah->ah_maxPowerLevel = ratesArray[i]; | ||
4600 | |||
4601 | return 0; | ||
4602 | } | ||
4603 | |||
4604 | static inline void ath9k_hw_get_delta_slope_vals(struct ath_hal *ah, | ||
4605 | u32 coef_scaled, | ||
4606 | u32 *coef_mantissa, | ||
4607 | u32 *coef_exponent) | ||
4608 | { | ||
4609 | u32 coef_exp, coef_man; | ||
4610 | |||
4611 | for (coef_exp = 31; coef_exp > 0; coef_exp--) | ||
4612 | if ((coef_scaled >> coef_exp) & 0x1) | ||
4613 | break; | ||
4614 | |||
4615 | coef_exp = 14 - (coef_exp - COEF_SCALE_S); | ||
4616 | |||
4617 | coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); | ||
4618 | |||
4619 | *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp); | ||
4620 | *coef_exponent = coef_exp - 16; | ||
4621 | } | ||
4622 | |||
4623 | static void | ||
4624 | ath9k_hw_set_delta_slope(struct ath_hal *ah, | ||
4625 | struct ath9k_channel *chan) | ||
4626 | { | ||
4627 | u32 coef_scaled, ds_coef_exp, ds_coef_man; | ||
4628 | u32 clockMhzScaled = 0x64000000; | ||
4629 | struct chan_centers centers; | ||
4630 | |||
4631 | if (IS_CHAN_HALF_RATE(chan)) | ||
4632 | clockMhzScaled = clockMhzScaled >> 1; | ||
4633 | else if (IS_CHAN_QUARTER_RATE(chan)) | ||
4634 | clockMhzScaled = clockMhzScaled >> 2; | ||
4635 | |||
4636 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
4637 | coef_scaled = clockMhzScaled / centers.synth_center; | ||
4638 | |||
4639 | ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, | ||
4640 | &ds_coef_exp); | ||
4641 | |||
4642 | REG_RMW_FIELD(ah, AR_PHY_TIMING3, | ||
4643 | AR_PHY_TIMING3_DSC_MAN, ds_coef_man); | ||
4644 | REG_RMW_FIELD(ah, AR_PHY_TIMING3, | ||
4645 | AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); | ||
4646 | |||
4647 | coef_scaled = (9 * coef_scaled) / 10; | ||
4648 | |||
4649 | ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, | ||
4650 | &ds_coef_exp); | ||
4651 | |||
4652 | REG_RMW_FIELD(ah, AR_PHY_HALFGI, | ||
4653 | AR_PHY_HALFGI_DSC_MAN, ds_coef_man); | ||
4654 | REG_RMW_FIELD(ah, AR_PHY_HALFGI, | ||
4655 | AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); | ||
4656 | } | ||
4657 | |||
4658 | static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, | ||
4659 | struct ath9k_channel *chan) | ||
4660 | { | ||
4661 | int bb_spur = AR_NO_SPUR; | ||
4662 | int freq; | ||
4663 | int bin, cur_bin; | ||
4664 | int bb_spur_off, spur_subchannel_sd; | ||
4665 | int spur_freq_sd; | ||
4666 | int spur_delta_phase; | ||
4667 | int denominator; | ||
4668 | int upper, lower, cur_vit_mask; | ||
4669 | int tmp, newVal; | ||
4670 | int i; | ||
4671 | int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, | ||
4672 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | ||
4673 | }; | ||
4674 | int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, | ||
4675 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | ||
4676 | }; | ||
4677 | int inc[4] = { 0, 100, 0, 0 }; | ||
4678 | struct chan_centers centers; | ||
4679 | |||
4680 | int8_t mask_m[123]; | ||
4681 | int8_t mask_p[123]; | ||
4682 | int8_t mask_amt; | ||
4683 | int tmp_mask; | ||
4684 | int cur_bb_spur; | ||
4685 | bool is2GHz = IS_CHAN_2GHZ(chan); | ||
4686 | |||
4687 | memset(&mask_m, 0, sizeof(int8_t) * 123); | ||
4688 | memset(&mask_p, 0, sizeof(int8_t) * 123); | ||
4689 | |||
4690 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
4691 | freq = centers.synth_center; | ||
4692 | |||
4693 | ah->ah_config.ath_hal_spurMode = SPUR_ENABLE_EEPROM; | ||
4694 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | ||
4695 | cur_bb_spur = ath9k_hw_eeprom_get_spur_chan(ah, i, is2GHz); | ||
4696 | |||
4697 | if (is2GHz) | ||
4698 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; | ||
4699 | else | ||
4700 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; | ||
4701 | |||
4702 | if (AR_NO_SPUR == cur_bb_spur) | ||
4703 | break; | ||
4704 | cur_bb_spur = cur_bb_spur - freq; | ||
4705 | |||
4706 | if (IS_CHAN_HT40(chan)) { | ||
4707 | if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && | ||
4708 | (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { | ||
4709 | bb_spur = cur_bb_spur; | ||
4710 | break; | ||
4711 | } | ||
4712 | } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && | ||
4713 | (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { | ||
4714 | bb_spur = cur_bb_spur; | ||
4715 | break; | ||
4716 | } | ||
4717 | } | ||
4718 | |||
4719 | if (AR_NO_SPUR == bb_spur) { | ||
4720 | REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, | ||
4721 | AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); | ||
4722 | return; | ||
4723 | } else { | ||
4724 | REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, | ||
4725 | AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); | ||
4726 | } | ||
4727 | |||
4728 | bin = bb_spur * 320; | ||
4729 | |||
4730 | tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); | ||
4731 | |||
4732 | newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | | ||
4733 | AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | | ||
4734 | AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | | ||
4735 | AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); | ||
4736 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); | ||
4737 | |||
4738 | newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | | ||
4739 | AR_PHY_SPUR_REG_ENABLE_MASK_PPM | | ||
4740 | AR_PHY_SPUR_REG_MASK_RATE_SELECT | | ||
4741 | AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | | ||
4742 | SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); | ||
4743 | REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); | ||
4744 | |||
4745 | if (IS_CHAN_HT40(chan)) { | ||
4746 | if (bb_spur < 0) { | ||
4747 | spur_subchannel_sd = 1; | ||
4748 | bb_spur_off = bb_spur + 10; | ||
4749 | } else { | ||
4750 | spur_subchannel_sd = 0; | ||
4751 | bb_spur_off = bb_spur - 10; | ||
4752 | } | ||
4753 | } else { | ||
4754 | spur_subchannel_sd = 0; | ||
4755 | bb_spur_off = bb_spur; | ||
4756 | } | ||
4757 | |||
4758 | if (IS_CHAN_HT40(chan)) | ||
4759 | spur_delta_phase = | ||
4760 | ((bb_spur * 262144) / | ||
4761 | 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; | ||
4762 | else | ||
4763 | spur_delta_phase = | ||
4764 | ((bb_spur * 524288) / | ||
4765 | 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; | ||
4766 | |||
4767 | denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; | ||
4768 | spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; | ||
4769 | |||
4770 | newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | | ||
4771 | SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | | ||
4772 | SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); | ||
4773 | REG_WRITE(ah, AR_PHY_TIMING11, newVal); | ||
4774 | |||
4775 | newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; | ||
4776 | REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); | ||
4777 | |||
4778 | cur_bin = -6000; | ||
4779 | upper = bin + 100; | ||
4780 | lower = bin - 100; | ||
4781 | |||
4782 | for (i = 0; i < 4; i++) { | ||
4783 | int pilot_mask = 0; | ||
4784 | int chan_mask = 0; | ||
4785 | int bp = 0; | ||
4786 | for (bp = 0; bp < 30; bp++) { | ||
4787 | if ((cur_bin > lower) && (cur_bin < upper)) { | ||
4788 | pilot_mask = pilot_mask | 0x1 << bp; | ||
4789 | chan_mask = chan_mask | 0x1 << bp; | ||
4790 | } | ||
4791 | cur_bin += 100; | ||
4792 | } | ||
4793 | cur_bin += inc[i]; | ||
4794 | REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); | ||
4795 | REG_WRITE(ah, chan_mask_reg[i], chan_mask); | ||
4796 | } | ||
4797 | |||
4798 | cur_vit_mask = 6100; | ||
4799 | upper = bin + 120; | ||
4800 | lower = bin - 120; | ||
4801 | |||
4802 | for (i = 0; i < 123; i++) { | ||
4803 | if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { | ||
4804 | if ((abs(cur_vit_mask - bin)) < 75) | ||
4805 | mask_amt = 1; | ||
4806 | else | ||
4807 | mask_amt = 0; | ||
4808 | if (cur_vit_mask < 0) | ||
4809 | mask_m[abs(cur_vit_mask / 100)] = mask_amt; | ||
4810 | else | ||
4811 | mask_p[cur_vit_mask / 100] = mask_amt; | ||
4812 | } | ||
4813 | cur_vit_mask -= 100; | ||
4814 | } | ||
4815 | |||
4816 | tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) | ||
4817 | | (mask_m[48] << 26) | (mask_m[49] << 24) | ||
4818 | | (mask_m[50] << 22) | (mask_m[51] << 20) | ||
4819 | | (mask_m[52] << 18) | (mask_m[53] << 16) | ||
4820 | | (mask_m[54] << 14) | (mask_m[55] << 12) | ||
4821 | | (mask_m[56] << 10) | (mask_m[57] << 8) | ||
4822 | | (mask_m[58] << 6) | (mask_m[59] << 4) | ||
4823 | | (mask_m[60] << 2) | (mask_m[61] << 0); | ||
4824 | REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); | ||
4825 | REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); | ||
4826 | |||
4827 | tmp_mask = (mask_m[31] << 28) | ||
4828 | | (mask_m[32] << 26) | (mask_m[33] << 24) | ||
4829 | | (mask_m[34] << 22) | (mask_m[35] << 20) | ||
4830 | | (mask_m[36] << 18) | (mask_m[37] << 16) | ||
4831 | | (mask_m[48] << 14) | (mask_m[39] << 12) | ||
4832 | | (mask_m[40] << 10) | (mask_m[41] << 8) | ||
4833 | | (mask_m[42] << 6) | (mask_m[43] << 4) | ||
4834 | | (mask_m[44] << 2) | (mask_m[45] << 0); | ||
4835 | REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); | ||
4836 | REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); | ||
4837 | |||
4838 | tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) | ||
4839 | | (mask_m[18] << 26) | (mask_m[18] << 24) | ||
4840 | | (mask_m[20] << 22) | (mask_m[20] << 20) | ||
4841 | | (mask_m[22] << 18) | (mask_m[22] << 16) | ||
4842 | | (mask_m[24] << 14) | (mask_m[24] << 12) | ||
4843 | | (mask_m[25] << 10) | (mask_m[26] << 8) | ||
4844 | | (mask_m[27] << 6) | (mask_m[28] << 4) | ||
4845 | | (mask_m[29] << 2) | (mask_m[30] << 0); | ||
4846 | REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); | ||
4847 | REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); | ||
4848 | |||
4849 | tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) | ||
4850 | | (mask_m[2] << 26) | (mask_m[3] << 24) | ||
4851 | | (mask_m[4] << 22) | (mask_m[5] << 20) | ||
4852 | | (mask_m[6] << 18) | (mask_m[7] << 16) | ||
4853 | | (mask_m[8] << 14) | (mask_m[9] << 12) | ||
4854 | | (mask_m[10] << 10) | (mask_m[11] << 8) | ||
4855 | | (mask_m[12] << 6) | (mask_m[13] << 4) | ||
4856 | | (mask_m[14] << 2) | (mask_m[15] << 0); | ||
4857 | REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); | ||
4858 | REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); | ||
4859 | |||
4860 | tmp_mask = (mask_p[15] << 28) | ||
4861 | | (mask_p[14] << 26) | (mask_p[13] << 24) | ||
4862 | | (mask_p[12] << 22) | (mask_p[11] << 20) | ||
4863 | | (mask_p[10] << 18) | (mask_p[9] << 16) | ||
4864 | | (mask_p[8] << 14) | (mask_p[7] << 12) | ||
4865 | | (mask_p[6] << 10) | (mask_p[5] << 8) | ||
4866 | | (mask_p[4] << 6) | (mask_p[3] << 4) | ||
4867 | | (mask_p[2] << 2) | (mask_p[1] << 0); | ||
4868 | REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); | ||
4869 | REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); | ||
4870 | |||
4871 | tmp_mask = (mask_p[30] << 28) | ||
4872 | | (mask_p[29] << 26) | (mask_p[28] << 24) | ||
4873 | | (mask_p[27] << 22) | (mask_p[26] << 20) | ||
4874 | | (mask_p[25] << 18) | (mask_p[24] << 16) | ||
4875 | | (mask_p[23] << 14) | (mask_p[22] << 12) | ||
4876 | | (mask_p[21] << 10) | (mask_p[20] << 8) | ||
4877 | | (mask_p[19] << 6) | (mask_p[18] << 4) | ||
4878 | | (mask_p[17] << 2) | (mask_p[16] << 0); | ||
4879 | REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); | ||
4880 | REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); | ||
4881 | |||
4882 | tmp_mask = (mask_p[45] << 28) | ||
4883 | | (mask_p[44] << 26) | (mask_p[43] << 24) | ||
4884 | | (mask_p[42] << 22) | (mask_p[41] << 20) | ||
4885 | | (mask_p[40] << 18) | (mask_p[39] << 16) | ||
4886 | | (mask_p[38] << 14) | (mask_p[37] << 12) | ||
4887 | | (mask_p[36] << 10) | (mask_p[35] << 8) | ||
4888 | | (mask_p[34] << 6) | (mask_p[33] << 4) | ||
4889 | | (mask_p[32] << 2) | (mask_p[31] << 0); | ||
4890 | REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); | ||
4891 | REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); | ||
4892 | |||
4893 | tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) | ||
4894 | | (mask_p[59] << 26) | (mask_p[58] << 24) | ||
4895 | | (mask_p[57] << 22) | (mask_p[56] << 20) | ||
4896 | | (mask_p[55] << 18) | (mask_p[54] << 16) | ||
4897 | | (mask_p[53] << 14) | (mask_p[52] << 12) | ||
4898 | | (mask_p[51] << 10) | (mask_p[50] << 8) | ||
4899 | | (mask_p[49] << 6) | (mask_p[48] << 4) | ||
4900 | | (mask_p[47] << 2) | (mask_p[46] << 0); | ||
4901 | REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); | ||
4902 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); | ||
4903 | } | ||
4904 | |||
4905 | static void ath9k_hw_spur_mitigate(struct ath_hal *ah, | ||
4906 | struct ath9k_channel *chan) | ||
4907 | { | ||
4908 | int bb_spur = AR_NO_SPUR; | ||
4909 | int bin, cur_bin; | ||
4910 | int spur_freq_sd; | ||
4911 | int spur_delta_phase; | ||
4912 | int denominator; | ||
4913 | int upper, lower, cur_vit_mask; | ||
4914 | int tmp, new; | ||
4915 | int i; | ||
4916 | int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, | ||
4917 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | ||
4918 | }; | ||
4919 | int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, | ||
4920 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | ||
4921 | }; | ||
4922 | int inc[4] = { 0, 100, 0, 0 }; | ||
4923 | |||
4924 | int8_t mask_m[123]; | ||
4925 | int8_t mask_p[123]; | ||
4926 | int8_t mask_amt; | ||
4927 | int tmp_mask; | ||
4928 | int cur_bb_spur; | ||
4929 | bool is2GHz = IS_CHAN_2GHZ(chan); | ||
4930 | |||
4931 | memset(&mask_m, 0, sizeof(int8_t) * 123); | ||
4932 | memset(&mask_p, 0, sizeof(int8_t) * 123); | ||
4933 | |||
4934 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | ||
4935 | cur_bb_spur = ath9k_hw_eeprom_get_spur_chan(ah, i, is2GHz); | ||
4936 | if (AR_NO_SPUR == cur_bb_spur) | ||
4937 | break; | ||
4938 | cur_bb_spur = cur_bb_spur - (chan->channel * 10); | ||
4939 | if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { | ||
4940 | bb_spur = cur_bb_spur; | ||
4941 | break; | ||
4942 | } | ||
4943 | } | ||
4944 | |||
4945 | if (AR_NO_SPUR == bb_spur) | ||
4946 | return; | ||
4947 | |||
4948 | bin = bb_spur * 32; | ||
4949 | |||
4950 | tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); | ||
4951 | new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | | ||
4952 | AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | | ||
4953 | AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | | ||
4954 | AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); | ||
4955 | |||
4956 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); | ||
4957 | |||
4958 | new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | | ||
4959 | AR_PHY_SPUR_REG_ENABLE_MASK_PPM | | ||
4960 | AR_PHY_SPUR_REG_MASK_RATE_SELECT | | ||
4961 | AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | | ||
4962 | SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); | ||
4963 | REG_WRITE(ah, AR_PHY_SPUR_REG, new); | ||
4964 | |||
4965 | spur_delta_phase = ((bb_spur * 524288) / 100) & | ||
4966 | AR_PHY_TIMING11_SPUR_DELTA_PHASE; | ||
4967 | |||
4968 | denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; | ||
4969 | spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; | ||
4970 | |||
4971 | new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | | ||
4972 | SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | | ||
4973 | SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); | ||
4974 | REG_WRITE(ah, AR_PHY_TIMING11, new); | ||
4975 | |||
4976 | cur_bin = -6000; | ||
4977 | upper = bin + 100; | ||
4978 | lower = bin - 100; | ||
4979 | |||
4980 | for (i = 0; i < 4; i++) { | ||
4981 | int pilot_mask = 0; | ||
4982 | int chan_mask = 0; | ||
4983 | int bp = 0; | ||
4984 | for (bp = 0; bp < 30; bp++) { | ||
4985 | if ((cur_bin > lower) && (cur_bin < upper)) { | ||
4986 | pilot_mask = pilot_mask | 0x1 << bp; | ||
4987 | chan_mask = chan_mask | 0x1 << bp; | ||
4988 | } | ||
4989 | cur_bin += 100; | ||
4990 | } | ||
4991 | cur_bin += inc[i]; | ||
4992 | REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); | ||
4993 | REG_WRITE(ah, chan_mask_reg[i], chan_mask); | ||
4994 | } | ||
4995 | |||
4996 | cur_vit_mask = 6100; | ||
4997 | upper = bin + 120; | ||
4998 | lower = bin - 120; | ||
4999 | |||
5000 | for (i = 0; i < 123; i++) { | ||
5001 | if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { | ||
5002 | if ((abs(cur_vit_mask - bin)) < 75) | ||
5003 | mask_amt = 1; | ||
5004 | else | ||
5005 | mask_amt = 0; | ||
5006 | if (cur_vit_mask < 0) | ||
5007 | mask_m[abs(cur_vit_mask / 100)] = mask_amt; | ||
5008 | else | ||
5009 | mask_p[cur_vit_mask / 100] = mask_amt; | ||
5010 | } | ||
5011 | cur_vit_mask -= 100; | ||
5012 | } | ||
5013 | |||
5014 | tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) | ||
5015 | | (mask_m[48] << 26) | (mask_m[49] << 24) | ||
5016 | | (mask_m[50] << 22) | (mask_m[51] << 20) | ||
5017 | | (mask_m[52] << 18) | (mask_m[53] << 16) | ||
5018 | | (mask_m[54] << 14) | (mask_m[55] << 12) | ||
5019 | | (mask_m[56] << 10) | (mask_m[57] << 8) | ||
5020 | | (mask_m[58] << 6) | (mask_m[59] << 4) | ||
5021 | | (mask_m[60] << 2) | (mask_m[61] << 0); | ||
5022 | REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); | ||
5023 | REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); | ||
5024 | |||
5025 | tmp_mask = (mask_m[31] << 28) | ||
5026 | | (mask_m[32] << 26) | (mask_m[33] << 24) | ||
5027 | | (mask_m[34] << 22) | (mask_m[35] << 20) | ||
5028 | | (mask_m[36] << 18) | (mask_m[37] << 16) | ||
5029 | | (mask_m[48] << 14) | (mask_m[39] << 12) | ||
5030 | | (mask_m[40] << 10) | (mask_m[41] << 8) | ||
5031 | | (mask_m[42] << 6) | (mask_m[43] << 4) | ||
5032 | | (mask_m[44] << 2) | (mask_m[45] << 0); | ||
5033 | REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); | ||
5034 | REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); | ||
5035 | |||
5036 | tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) | ||
5037 | | (mask_m[18] << 26) | (mask_m[18] << 24) | ||
5038 | | (mask_m[20] << 22) | (mask_m[20] << 20) | ||
5039 | | (mask_m[22] << 18) | (mask_m[22] << 16) | ||
5040 | | (mask_m[24] << 14) | (mask_m[24] << 12) | ||
5041 | | (mask_m[25] << 10) | (mask_m[26] << 8) | ||
5042 | | (mask_m[27] << 6) | (mask_m[28] << 4) | ||
5043 | | (mask_m[29] << 2) | (mask_m[30] << 0); | ||
5044 | REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); | ||
5045 | REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); | ||
5046 | |||
5047 | tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) | ||
5048 | | (mask_m[2] << 26) | (mask_m[3] << 24) | ||
5049 | | (mask_m[4] << 22) | (mask_m[5] << 20) | ||
5050 | | (mask_m[6] << 18) | (mask_m[7] << 16) | ||
5051 | | (mask_m[8] << 14) | (mask_m[9] << 12) | ||
5052 | | (mask_m[10] << 10) | (mask_m[11] << 8) | ||
5053 | | (mask_m[12] << 6) | (mask_m[13] << 4) | ||
5054 | | (mask_m[14] << 2) | (mask_m[15] << 0); | ||
5055 | REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); | ||
5056 | REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); | ||
5057 | |||
5058 | tmp_mask = (mask_p[15] << 28) | ||
5059 | | (mask_p[14] << 26) | (mask_p[13] << 24) | ||
5060 | | (mask_p[12] << 22) | (mask_p[11] << 20) | ||
5061 | | (mask_p[10] << 18) | (mask_p[9] << 16) | ||
5062 | | (mask_p[8] << 14) | (mask_p[7] << 12) | ||
5063 | | (mask_p[6] << 10) | (mask_p[5] << 8) | ||
5064 | | (mask_p[4] << 6) | (mask_p[3] << 4) | ||
5065 | | (mask_p[2] << 2) | (mask_p[1] << 0); | ||
5066 | REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); | ||
5067 | REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); | ||
5068 | |||
5069 | tmp_mask = (mask_p[30] << 28) | ||
5070 | | (mask_p[29] << 26) | (mask_p[28] << 24) | ||
5071 | | (mask_p[27] << 22) | (mask_p[26] << 20) | ||
5072 | | (mask_p[25] << 18) | (mask_p[24] << 16) | ||
5073 | | (mask_p[23] << 14) | (mask_p[22] << 12) | ||
5074 | | (mask_p[21] << 10) | (mask_p[20] << 8) | ||
5075 | | (mask_p[19] << 6) | (mask_p[18] << 4) | ||
5076 | | (mask_p[17] << 2) | (mask_p[16] << 0); | ||
5077 | REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); | ||
5078 | REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); | ||
5079 | |||
5080 | tmp_mask = (mask_p[45] << 28) | ||
5081 | | (mask_p[44] << 26) | (mask_p[43] << 24) | ||
5082 | | (mask_p[42] << 22) | (mask_p[41] << 20) | ||
5083 | | (mask_p[40] << 18) | (mask_p[39] << 16) | ||
5084 | | (mask_p[38] << 14) | (mask_p[37] << 12) | ||
5085 | | (mask_p[36] << 10) | (mask_p[35] << 8) | ||
5086 | | (mask_p[34] << 6) | (mask_p[33] << 4) | ||
5087 | | (mask_p[32] << 2) | (mask_p[31] << 0); | ||
5088 | REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); | ||
5089 | REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); | ||
5090 | |||
5091 | tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) | ||
5092 | | (mask_p[59] << 26) | (mask_p[58] << 24) | ||
5093 | | (mask_p[57] << 22) | (mask_p[56] << 20) | ||
5094 | | (mask_p[55] << 18) | (mask_p[54] << 16) | ||
5095 | | (mask_p[53] << 14) | (mask_p[52] << 12) | ||
5096 | | (mask_p[51] << 10) | (mask_p[50] << 8) | ||
5097 | | (mask_p[49] << 6) | (mask_p[48] << 4) | ||
5098 | | (mask_p[47] << 2) | (mask_p[46] << 0); | ||
5099 | REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); | ||
5100 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); | ||
5101 | } | ||
5102 | |||
5103 | static inline void ath9k_hw_init_chain_masks(struct ath_hal *ah) | ||
5104 | { | ||
5105 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5106 | int rx_chainmask, tx_chainmask; | ||
5107 | |||
5108 | rx_chainmask = ahp->ah_rxchainmask; | ||
5109 | tx_chainmask = ahp->ah_txchainmask; | ||
5110 | |||
5111 | switch (rx_chainmask) { | ||
5112 | case 0x5: | ||
5113 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | ||
5114 | AR_PHY_SWAP_ALT_CHAIN); | ||
5115 | case 0x3: | ||
5116 | if (((ah)->ah_macVersion <= AR_SREV_VERSION_9160)) { | ||
5117 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); | ||
5118 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); | ||
5119 | break; | ||
5120 | } | ||
5121 | case 0x1: | ||
5122 | case 0x2: | ||
5123 | if (!AR_SREV_9280(ah)) | ||
5124 | break; | ||
5125 | case 0x7: | ||
5126 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); | ||
5127 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); | ||
5128 | break; | ||
5129 | default: | ||
5130 | break; | ||
5131 | } | ||
5132 | |||
5133 | REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); | ||
5134 | if (tx_chainmask == 0x5) { | ||
5135 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | ||
5136 | AR_PHY_SWAP_ALT_CHAIN); | ||
5137 | } | ||
5138 | if (AR_SREV_9100(ah)) | ||
5139 | REG_WRITE(ah, AR_PHY_ANALOG_SWAP, | ||
5140 | REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); | ||
5141 | } | ||
5142 | |||
5143 | static void ath9k_hw_set_addac(struct ath_hal *ah, | ||
5144 | struct ath9k_channel *chan) | ||
5145 | { | ||
5146 | struct modal_eep_header *pModal; | ||
5147 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5148 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; | ||
5149 | u8 biaslevel; | ||
5150 | |||
5151 | if (ah->ah_macVersion != AR_SREV_VERSION_9160) | ||
5152 | return; | ||
5153 | |||
5154 | if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7) | ||
5155 | return; | ||
5156 | |||
5157 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
5158 | |||
5159 | if (pModal->xpaBiasLvl != 0xff) { | ||
5160 | biaslevel = pModal->xpaBiasLvl; | ||
5161 | } else { | ||
5162 | |||
5163 | u16 resetFreqBin, freqBin, freqCount = 0; | ||
5164 | struct chan_centers centers; | ||
5165 | |||
5166 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
5167 | |||
5168 | resetFreqBin = | ||
5169 | FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)); | ||
5170 | freqBin = pModal->xpaBiasLvlFreq[0] & 0xff; | ||
5171 | biaslevel = (u8) (pModal->xpaBiasLvlFreq[0] >> 14); | ||
5172 | |||
5173 | freqCount++; | ||
5174 | |||
5175 | while (freqCount < 3) { | ||
5176 | if (pModal->xpaBiasLvlFreq[freqCount] == 0x0) | ||
5177 | break; | ||
5178 | |||
5179 | freqBin = pModal->xpaBiasLvlFreq[freqCount] & 0xff; | ||
5180 | if (resetFreqBin >= freqBin) { | ||
5181 | biaslevel = | ||
5182 | (u8) (pModal-> | ||
5183 | xpaBiasLvlFreq[freqCount] | ||
5184 | >> 14); | ||
5185 | } else { | ||
5186 | break; | ||
5187 | } | ||
5188 | freqCount++; | ||
5189 | } | ||
5190 | } | ||
5191 | |||
5192 | if (IS_CHAN_2GHZ(chan)) { | ||
5193 | INI_RA(&ahp->ah_iniAddac, 7, 1) = | ||
5194 | (INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) | biaslevel | ||
5195 | << 3; | ||
5196 | } else { | ||
5197 | INI_RA(&ahp->ah_iniAddac, 6, 1) = | ||
5198 | (INI_RA(&ahp->ah_iniAddac, 6, 1) & (~0xc0)) | biaslevel | ||
5199 | << 6; | ||
5200 | } | ||
5201 | } | ||
5202 | |||
5203 | static u32 ath9k_hw_mac_usec(struct ath_hal *ah, u32 clks) | ||
5204 | { | ||
5205 | if (ah->ah_curchan != NULL) | ||
5206 | return clks / | ||
5207 | CLOCK_RATE[ath9k_hw_chan2wmode(ah, ah->ah_curchan)]; | ||
5208 | else | ||
5209 | return clks / CLOCK_RATE[WIRELESS_MODE_11b]; | ||
5210 | } | ||
5211 | |||
5212 | static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks) | ||
5213 | { | ||
5214 | struct ath9k_channel *chan = ah->ah_curchan; | ||
5215 | |||
5216 | if (chan && IS_CHAN_HT40(chan)) | ||
5217 | return ath9k_hw_mac_usec(ah, clks) / 2; | ||
5218 | else | ||
5219 | return ath9k_hw_mac_usec(ah, clks); | ||
5220 | } | ||
5221 | |||
5222 | static u32 ath9k_hw_mac_clks(struct ath_hal *ah, u32 usecs) | ||
5223 | { | ||
5224 | if (ah->ah_curchan != NULL) | ||
5225 | return usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah, | ||
5226 | ah->ah_curchan)]; | ||
5227 | else | ||
5228 | return usecs * CLOCK_RATE[WIRELESS_MODE_11b]; | ||
5229 | } | ||
5230 | |||
5231 | static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs) | ||
5232 | { | ||
5233 | struct ath9k_channel *chan = ah->ah_curchan; | ||
5234 | |||
5235 | if (chan && IS_CHAN_HT40(chan)) | ||
5236 | return ath9k_hw_mac_clks(ah, usecs) * 2; | ||
5237 | else | ||
5238 | return ath9k_hw_mac_clks(ah, usecs); | ||
5239 | } | ||
5240 | |||
5241 | static bool ath9k_hw_set_ack_timeout(struct ath_hal *ah, u32 us) | ||
5242 | { | ||
5243 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5244 | |||
5245 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { | ||
5246 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad ack timeout %u\n", | ||
5247 | __func__, us); | ||
5248 | ahp->ah_acktimeout = (u32) -1; | ||
5249 | return false; | ||
5250 | } else { | ||
5251 | REG_RMW_FIELD(ah, AR_TIME_OUT, | ||
5252 | AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us)); | ||
5253 | ahp->ah_acktimeout = us; | ||
5254 | return true; | ||
5255 | } | ||
5256 | } | ||
5257 | |||
5258 | static bool ath9k_hw_set_cts_timeout(struct ath_hal *ah, u32 us) | ||
5259 | { | ||
5260 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5261 | |||
5262 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { | ||
5263 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad cts timeout %u\n", | ||
5264 | __func__, us); | ||
5265 | ahp->ah_ctstimeout = (u32) -1; | ||
5266 | return false; | ||
5267 | } else { | ||
5268 | REG_RMW_FIELD(ah, AR_TIME_OUT, | ||
5269 | AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); | ||
5270 | ahp->ah_ctstimeout = us; | ||
5271 | return true; | ||
5272 | } | ||
5273 | } | ||
5274 | static bool ath9k_hw_set_global_txtimeout(struct ath_hal *ah, | ||
5275 | u32 tu) | ||
5276 | { | ||
5277 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5278 | |||
5279 | if (tu > 0xFFFF) { | ||
5280 | DPRINTF(ah->ah_sc, ATH_DBG_XMIT, | ||
5281 | "%s: bad global tx timeout %u\n", __func__, tu); | ||
5282 | ahp->ah_globaltxtimeout = (u32) -1; | ||
5283 | return false; | ||
5284 | } else { | ||
5285 | REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu); | ||
5286 | ahp->ah_globaltxtimeout = tu; | ||
5287 | return true; | ||
5288 | } | ||
5289 | } | ||
5290 | |||
5291 | bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us) | ||
5292 | { | ||
5293 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5294 | |||
5295 | if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { | ||
5296 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad slot time %u\n", | ||
5297 | __func__, us); | ||
5298 | ahp->ah_slottime = (u32) -1; | ||
5299 | return false; | ||
5300 | } else { | ||
5301 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us)); | ||
5302 | ahp->ah_slottime = us; | ||
5303 | return true; | ||
5304 | } | ||
5305 | } | ||
5306 | |||
5307 | static inline void ath9k_hw_init_user_settings(struct ath_hal *ah) | ||
5308 | { | ||
5309 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5310 | |||
5311 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "--AP %s ahp->ah_miscMode 0x%x\n", | ||
5312 | __func__, ahp->ah_miscMode); | ||
5313 | if (ahp->ah_miscMode != 0) | ||
5314 | REG_WRITE(ah, AR_PCU_MISC, | ||
5315 | REG_READ(ah, AR_PCU_MISC) | ahp->ah_miscMode); | ||
5316 | if (ahp->ah_slottime != (u32) -1) | ||
5317 | ath9k_hw_setslottime(ah, ahp->ah_slottime); | ||
5318 | if (ahp->ah_acktimeout != (u32) -1) | ||
5319 | ath9k_hw_set_ack_timeout(ah, ahp->ah_acktimeout); | ||
5320 | if (ahp->ah_ctstimeout != (u32) -1) | ||
5321 | ath9k_hw_set_cts_timeout(ah, ahp->ah_ctstimeout); | ||
5322 | if (ahp->ah_globaltxtimeout != (u32) -1) | ||
5323 | ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout); | ||
5324 | } | ||
5325 | |||
5326 | static inline int | ||
5327 | ath9k_hw_process_ini(struct ath_hal *ah, | ||
5328 | struct ath9k_channel *chan, | ||
5329 | enum ath9k_ht_macmode macmode) | ||
5330 | { | ||
5331 | int i, regWrites = 0; | ||
5332 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5333 | u32 modesIndex, freqIndex; | ||
5334 | int status; | ||
5335 | |||
5336 | switch (chan->chanmode) { | ||
5337 | case CHANNEL_A: | ||
5338 | case CHANNEL_A_HT20: | ||
5339 | modesIndex = 1; | ||
5340 | freqIndex = 1; | ||
5341 | break; | ||
5342 | case CHANNEL_A_HT40PLUS: | ||
5343 | case CHANNEL_A_HT40MINUS: | ||
5344 | modesIndex = 2; | ||
5345 | freqIndex = 1; | ||
5346 | break; | ||
5347 | case CHANNEL_G: | ||
5348 | case CHANNEL_G_HT20: | ||
5349 | case CHANNEL_B: | ||
5350 | modesIndex = 4; | ||
5351 | freqIndex = 2; | ||
5352 | break; | ||
5353 | case CHANNEL_G_HT40PLUS: | ||
5354 | case CHANNEL_G_HT40MINUS: | ||
5355 | modesIndex = 3; | ||
5356 | freqIndex = 2; | ||
5357 | break; | ||
5358 | |||
5359 | default: | ||
5360 | return -EINVAL; | ||
5361 | } | ||
5362 | |||
5363 | REG_WRITE(ah, AR_PHY(0), 0x00000007); | ||
5364 | |||
5365 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); | ||
5366 | |||
5367 | ath9k_hw_set_addac(ah, chan); | ||
5368 | |||
5369 | if (AR_SREV_5416_V22_OR_LATER(ah)) { | ||
5370 | REG_WRITE_ARRAY(&ahp->ah_iniAddac, 1, regWrites); | ||
5371 | } else { | ||
5372 | struct ar5416IniArray temp; | ||
5373 | u32 addacSize = | ||
5374 | sizeof(u32) * ahp->ah_iniAddac.ia_rows * | ||
5375 | ahp->ah_iniAddac.ia_columns; | ||
5376 | |||
5377 | memcpy(ahp->ah_addac5416_21, | ||
5378 | ahp->ah_iniAddac.ia_array, addacSize); | ||
5379 | |||
5380 | (ahp->ah_addac5416_21)[31 * | ||
5381 | ahp->ah_iniAddac.ia_columns + 1] = 0; | ||
5382 | |||
5383 | temp.ia_array = ahp->ah_addac5416_21; | ||
5384 | temp.ia_columns = ahp->ah_iniAddac.ia_columns; | ||
5385 | temp.ia_rows = ahp->ah_iniAddac.ia_rows; | ||
5386 | REG_WRITE_ARRAY(&temp, 1, regWrites); | ||
5387 | } | ||
5388 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); | ||
5389 | |||
5390 | for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) { | ||
5391 | u32 reg = INI_RA(&ahp->ah_iniModes, i, 0); | ||
5392 | u32 val = INI_RA(&ahp->ah_iniModes, i, modesIndex); | ||
5393 | |||
5394 | #ifdef CONFIG_SLOW_ANT_DIV | ||
5395 | if (ah->ah_devid == AR9280_DEVID_PCI) | ||
5396 | val = ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom, reg, | ||
5397 | val); | ||
5398 | #endif | ||
5399 | |||
5400 | REG_WRITE(ah, reg, val); | ||
5401 | |||
5402 | if (reg >= 0x7800 && reg < 0x78a0 | ||
5403 | && ah->ah_config.ath_hal_analogShiftReg) { | ||
5404 | udelay(100); | ||
5405 | } | ||
5406 | |||
5407 | DO_DELAY(regWrites); | ||
5408 | } | ||
5409 | |||
5410 | for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) { | ||
5411 | u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0); | ||
5412 | u32 val = INI_RA(&ahp->ah_iniCommon, i, 1); | ||
5413 | |||
5414 | REG_WRITE(ah, reg, val); | ||
5415 | |||
5416 | if (reg >= 0x7800 && reg < 0x78a0 | ||
5417 | && ah->ah_config.ath_hal_analogShiftReg) { | ||
5418 | udelay(100); | ||
5419 | } | ||
5420 | |||
5421 | DO_DELAY(regWrites); | ||
5422 | } | ||
5423 | |||
5424 | ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites); | ||
5425 | |||
5426 | if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { | ||
5427 | REG_WRITE_ARRAY(&ahp->ah_iniModesAdditional, modesIndex, | ||
5428 | regWrites); | ||
5429 | } | ||
5430 | |||
5431 | ath9k_hw_override_ini(ah, chan); | ||
5432 | ath9k_hw_set_regs(ah, chan, macmode); | ||
5433 | ath9k_hw_init_chain_masks(ah); | ||
5434 | |||
5435 | status = ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan, | ||
5436 | ath9k_regd_get_ctl(ah, chan), | ||
5437 | ath9k_regd_get_antenna_allowed(ah, | ||
5438 | chan), | ||
5439 | chan->maxRegTxPower * 2, | ||
5440 | min((u32) MAX_RATE_POWER, | ||
5441 | (u32) ah->ah_powerLimit)); | ||
5442 | if (status != 0) { | ||
5443 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
5444 | "%s: error init'ing transmit power\n", __func__); | ||
5445 | return -EIO; | ||
5446 | } | ||
5447 | |||
5448 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { | ||
5449 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
5450 | "%s: ar5416SetRfRegs failed\n", __func__); | ||
5451 | return -EIO; | ||
5452 | } | ||
5453 | |||
5454 | return 0; | ||
5455 | } | ||
5456 | |||
5457 | static inline void ath9k_hw_setup_calibration(struct ath_hal *ah, | ||
5458 | struct hal_cal_list *currCal) | ||
5459 | { | ||
5460 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), | ||
5461 | AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, | ||
5462 | currCal->calData->calCountMax); | ||
5463 | |||
5464 | switch (currCal->calData->calType) { | ||
5465 | case IQ_MISMATCH_CAL: | ||
5466 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); | ||
5467 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5468 | "%s: starting IQ Mismatch Calibration\n", | ||
5469 | __func__); | ||
5470 | break; | ||
5471 | case ADC_GAIN_CAL: | ||
5472 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); | ||
5473 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5474 | "%s: starting ADC Gain Calibration\n", __func__); | ||
5475 | break; | ||
5476 | case ADC_DC_CAL: | ||
5477 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); | ||
5478 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5479 | "%s: starting ADC DC Calibration\n", __func__); | ||
5480 | break; | ||
5481 | case ADC_DC_INIT_CAL: | ||
5482 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); | ||
5483 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5484 | "%s: starting Init ADC DC Calibration\n", | ||
5485 | __func__); | ||
5486 | break; | ||
5487 | } | ||
5488 | |||
5489 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | ||
5490 | AR_PHY_TIMING_CTRL4_DO_CAL); | ||
5491 | } | ||
5492 | |||
5493 | static inline void ath9k_hw_reset_calibration(struct ath_hal *ah, | ||
5494 | struct hal_cal_list *currCal) | ||
5495 | { | ||
5496 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5497 | int i; | ||
5498 | |||
5499 | ath9k_hw_setup_calibration(ah, currCal); | ||
5500 | |||
5501 | currCal->calState = CAL_RUNNING; | ||
5502 | |||
5503 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
5504 | ahp->ah_Meas0.sign[i] = 0; | ||
5505 | ahp->ah_Meas1.sign[i] = 0; | ||
5506 | ahp->ah_Meas2.sign[i] = 0; | ||
5507 | ahp->ah_Meas3.sign[i] = 0; | ||
5508 | } | ||
5509 | |||
5510 | ahp->ah_CalSamples = 0; | ||
5511 | } | ||
5512 | |||
5513 | static inline void | ||
5514 | ath9k_hw_per_calibration(struct ath_hal *ah, | ||
5515 | struct ath9k_channel *ichan, | ||
5516 | u8 rxchainmask, | ||
5517 | struct hal_cal_list *currCal, | ||
5518 | bool *isCalDone) | ||
5519 | { | ||
5520 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5521 | |||
5522 | *isCalDone = false; | ||
5523 | |||
5524 | if (currCal->calState == CAL_RUNNING) { | ||
5525 | if (!(REG_READ(ah, | ||
5526 | AR_PHY_TIMING_CTRL4(0)) & | ||
5527 | AR_PHY_TIMING_CTRL4_DO_CAL)) { | ||
5528 | |||
5529 | currCal->calData->calCollect(ah); | ||
5530 | |||
5531 | ahp->ah_CalSamples++; | ||
5532 | |||
5533 | if (ahp->ah_CalSamples >= | ||
5534 | currCal->calData->calNumSamples) { | ||
5535 | int i, numChains = 0; | ||
5536 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
5537 | if (rxchainmask & (1 << i)) | ||
5538 | numChains++; | ||
5539 | } | ||
5540 | |||
5541 | currCal->calData->calPostProc(ah, | ||
5542 | numChains); | ||
5543 | |||
5544 | ichan->CalValid |= | ||
5545 | currCal->calData->calType; | ||
5546 | currCal->calState = CAL_DONE; | ||
5547 | *isCalDone = true; | ||
5548 | } else { | ||
5549 | ath9k_hw_setup_calibration(ah, currCal); | ||
5550 | } | ||
5551 | } | ||
5552 | } else if (!(ichan->CalValid & currCal->calData->calType)) { | ||
5553 | ath9k_hw_reset_calibration(ah, currCal); | ||
5554 | } | ||
5555 | } | ||
5556 | |||
5557 | static inline bool ath9k_hw_run_init_cals(struct ath_hal *ah, | ||
5558 | int init_cal_count) | ||
5559 | { | ||
5560 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5561 | struct ath9k_channel ichan; | ||
5562 | bool isCalDone; | ||
5563 | struct hal_cal_list *currCal = ahp->ah_cal_list_curr; | ||
5564 | const struct hal_percal_data *calData = currCal->calData; | ||
5565 | int i; | ||
5566 | |||
5567 | if (currCal == NULL) | ||
5568 | return false; | ||
5569 | |||
5570 | ichan.CalValid = 0; | ||
5571 | |||
5572 | for (i = 0; i < init_cal_count; i++) { | ||
5573 | ath9k_hw_reset_calibration(ah, currCal); | ||
5574 | |||
5575 | if (!ath9k_hw_wait(ah, AR_PHY_TIMING_CTRL4(0), | ||
5576 | AR_PHY_TIMING_CTRL4_DO_CAL, 0)) { | ||
5577 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5578 | "%s: Cal %d failed to complete in 100ms.\n", | ||
5579 | __func__, calData->calType); | ||
5580 | |||
5581 | ahp->ah_cal_list = ahp->ah_cal_list_last = | ||
5582 | ahp->ah_cal_list_curr = NULL; | ||
5583 | return false; | ||
5584 | } | ||
5585 | |||
5586 | ath9k_hw_per_calibration(ah, &ichan, ahp->ah_rxchainmask, | ||
5587 | currCal, &isCalDone); | ||
5588 | if (!isCalDone) { | ||
5589 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5590 | "%s: Not able to run Init Cal %d.\n", | ||
5591 | __func__, calData->calType); | ||
5592 | } | ||
5593 | if (currCal->calNext) { | ||
5594 | currCal = currCal->calNext; | ||
5595 | calData = currCal->calData; | ||
5596 | } | ||
5597 | } | ||
5598 | |||
5599 | ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL; | ||
5600 | return true; | ||
5601 | } | ||
5602 | |||
5603 | static inline bool | ||
5604 | ath9k_hw_channel_change(struct ath_hal *ah, | ||
5605 | struct ath9k_channel *chan, | ||
5606 | enum ath9k_ht_macmode macmode) | ||
5607 | { | ||
5608 | u32 synthDelay, qnum; | ||
5609 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5610 | |||
5611 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { | ||
5612 | if (ath9k_hw_numtxpending(ah, qnum)) { | ||
5613 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
5614 | "%s: Transmit frames pending on queue %d\n", | ||
5615 | __func__, qnum); | ||
5616 | return false; | ||
5617 | } | ||
5618 | } | ||
5619 | |||
5620 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); | ||
5621 | if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, | ||
5622 | AR_PHY_RFBUS_GRANT_EN)) { | ||
5623 | DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO, | ||
5624 | "%s: Could not kill baseband RX\n", __func__); | ||
5625 | return false; | ||
5626 | } | ||
5627 | |||
5628 | ath9k_hw_set_regs(ah, chan, macmode); | ||
5629 | |||
5630 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
5631 | if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { | ||
5632 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
5633 | "%s: failed to set channel\n", __func__); | ||
5634 | return false; | ||
5635 | } | ||
5636 | } else { | ||
5637 | if (!(ath9k_hw_set_channel(ah, chan))) { | ||
5638 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
5639 | "%s: failed to set channel\n", __func__); | ||
5640 | return false; | ||
5641 | } | ||
5642 | } | ||
5643 | |||
5644 | if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan, | ||
5645 | ath9k_regd_get_ctl(ah, chan), | ||
5646 | ath9k_regd_get_antenna_allowed(ah, chan), | ||
5647 | chan->maxRegTxPower * 2, | ||
5648 | min((u32) MAX_RATE_POWER, | ||
5649 | (u32) ah->ah_powerLimit)) != 0) { | ||
5650 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
5651 | "%s: error init'ing transmit power\n", __func__); | ||
5652 | return false; | ||
5653 | } | ||
5654 | |||
5655 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; | ||
5656 | if (IS_CHAN_CCK(chan)) | ||
5657 | synthDelay = (4 * synthDelay) / 22; | ||
5658 | else | ||
5659 | synthDelay /= 10; | ||
5660 | |||
5661 | udelay(synthDelay + BASE_ACTIVATE_DELAY); | ||
5662 | |||
5663 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); | ||
5664 | |||
5665 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | ||
5666 | ath9k_hw_set_delta_slope(ah, chan); | ||
5667 | |||
5668 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
5669 | ath9k_hw_9280_spur_mitigate(ah, chan); | ||
5670 | else | ||
5671 | ath9k_hw_spur_mitigate(ah, chan); | ||
5672 | |||
5673 | if (!chan->oneTimeCalsDone) | ||
5674 | chan->oneTimeCalsDone = true; | ||
5675 | |||
5676 | return true; | ||
5677 | } | ||
5678 | |||
5679 | static bool ath9k_hw_chip_reset(struct ath_hal *ah, | ||
5680 | struct ath9k_channel *chan) | ||
5681 | { | ||
5682 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5683 | |||
5684 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) | ||
5685 | return false; | ||
5686 | |||
5687 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | ||
5688 | return false; | ||
5689 | |||
5690 | ahp->ah_chipFullSleep = false; | ||
5691 | |||
5692 | ath9k_hw_init_pll(ah, chan); | ||
5693 | |||
5694 | ath9k_hw_set_rfmode(ah, chan); | ||
5695 | |||
5696 | return true; | ||
5697 | } | ||
5698 | |||
5699 | static inline void ath9k_hw_set_dma(struct ath_hal *ah) | ||
5700 | { | ||
5701 | u32 regval; | ||
5702 | |||
5703 | regval = REG_READ(ah, AR_AHB_MODE); | ||
5704 | REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); | ||
5705 | |||
5706 | regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; | ||
5707 | REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); | ||
5708 | |||
5709 | REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->ah_txTrigLevel); | ||
5710 | |||
5711 | regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; | ||
5712 | REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); | ||
5713 | |||
5714 | REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); | ||
5715 | |||
5716 | if (AR_SREV_9285(ah)) { | ||
5717 | REG_WRITE(ah, AR_PCU_TXBUF_CTRL, | ||
5718 | AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); | ||
5719 | } else { | ||
5720 | REG_WRITE(ah, AR_PCU_TXBUF_CTRL, | ||
5721 | AR_PCU_TXBUF_CTRL_USABLE_SIZE); | ||
5722 | } | ||
5723 | } | ||
5724 | |||
5725 | bool ath9k_hw_stopdmarecv(struct ath_hal *ah) | ||
5726 | { | ||
5727 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | ||
5728 | if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) { | ||
5729 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
5730 | "%s: dma failed to stop in 10ms\n" | ||
5731 | "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", | ||
5732 | __func__, | ||
5733 | REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); | ||
5734 | return false; | ||
5735 | } else { | ||
5736 | return true; | ||
5737 | } | ||
5738 | } | ||
5739 | |||
5740 | void ath9k_hw_startpcureceive(struct ath_hal *ah) | ||
5741 | { | ||
5742 | REG_CLR_BIT(ah, AR_DIAG_SW, | ||
5743 | (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | ||
5744 | |||
5745 | ath9k_enable_mib_counters(ah); | ||
5746 | |||
5747 | ath9k_ani_reset(ah); | ||
5748 | } | ||
5749 | |||
5750 | void ath9k_hw_stoppcurecv(struct ath_hal *ah) | ||
5751 | { | ||
5752 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
5753 | |||
5754 | ath9k_hw_disable_mib_counters(ah); | ||
5755 | } | ||
5756 | |||
5757 | static bool ath9k_hw_iscal_supported(struct ath_hal *ah, | ||
5758 | struct ath9k_channel *chan, | ||
5759 | enum hal_cal_types calType) | ||
5760 | { | ||
5761 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5762 | bool retval = false; | ||
5763 | |||
5764 | switch (calType & ahp->ah_suppCals) { | ||
5765 | case IQ_MISMATCH_CAL: | ||
5766 | if (!IS_CHAN_B(chan)) | ||
5767 | retval = true; | ||
5768 | break; | ||
5769 | case ADC_GAIN_CAL: | ||
5770 | case ADC_DC_CAL: | ||
5771 | if (!IS_CHAN_B(chan) | ||
5772 | && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) | ||
5773 | retval = true; | ||
5774 | break; | ||
5775 | } | ||
5776 | |||
5777 | return retval; | ||
5778 | } | ||
5779 | |||
5780 | static inline bool ath9k_hw_init_cal(struct ath_hal *ah, | ||
5781 | struct ath9k_channel *chan) | ||
5782 | { | ||
5783 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5784 | struct ath9k_channel *ichan = | ||
5785 | ath9k_regd_check_channel(ah, chan); | ||
5786 | |||
5787 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | ||
5788 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | ||
5789 | AR_PHY_AGC_CONTROL_CAL); | ||
5790 | |||
5791 | if (!ath9k_hw_wait | ||
5792 | (ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { | ||
5793 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5794 | "%s: offset calibration failed to complete in 1ms; " | ||
5795 | "noisy environment?\n", __func__); | ||
5796 | return false; | ||
5797 | } | ||
5798 | |||
5799 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | ||
5800 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | ||
5801 | AR_PHY_AGC_CONTROL_NF); | ||
5802 | |||
5803 | ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = | ||
5804 | NULL; | ||
5805 | |||
5806 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { | ||
5807 | if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) { | ||
5808 | INIT_CAL(&ahp->ah_adcGainCalData); | ||
5809 | INSERT_CAL(ahp, &ahp->ah_adcGainCalData); | ||
5810 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5811 | "%s: enabling ADC Gain Calibration.\n", | ||
5812 | __func__); | ||
5813 | } | ||
5814 | if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) { | ||
5815 | INIT_CAL(&ahp->ah_adcDcCalData); | ||
5816 | INSERT_CAL(ahp, &ahp->ah_adcDcCalData); | ||
5817 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5818 | "%s: enabling ADC DC Calibration.\n", | ||
5819 | __func__); | ||
5820 | } | ||
5821 | if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) { | ||
5822 | INIT_CAL(&ahp->ah_iqCalData); | ||
5823 | INSERT_CAL(ahp, &ahp->ah_iqCalData); | ||
5824 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5825 | "%s: enabling IQ Calibration.\n", | ||
5826 | __func__); | ||
5827 | } | ||
5828 | |||
5829 | ahp->ah_cal_list_curr = ahp->ah_cal_list; | ||
5830 | |||
5831 | if (ahp->ah_cal_list_curr) | ||
5832 | ath9k_hw_reset_calibration(ah, | ||
5833 | ahp->ah_cal_list_curr); | ||
5834 | } | ||
5835 | |||
5836 | ichan->CalValid = 0; | ||
5837 | |||
5838 | return true; | ||
5839 | } | ||
5840 | |||
5841 | |||
5842 | bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | ||
5843 | struct ath9k_channel *chan, | ||
5844 | enum ath9k_ht_macmode macmode, | ||
5845 | u8 txchainmask, u8 rxchainmask, | ||
5846 | enum ath9k_ht_extprotspacing extprotspacing, | ||
5847 | bool bChannelChange, | ||
5848 | int *status) | ||
5849 | { | ||
5850 | #define FAIL(_code) do { ecode = _code; goto bad; } while (0) | ||
5851 | u32 saveLedState; | ||
5852 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5853 | struct ath9k_channel *curchan = ah->ah_curchan; | ||
5854 | u32 saveDefAntenna; | ||
5855 | u32 macStaId1; | ||
5856 | int ecode; | ||
5857 | int i, rx_chainmask; | ||
5858 | |||
5859 | ahp->ah_extprotspacing = extprotspacing; | ||
5860 | ahp->ah_txchainmask = txchainmask; | ||
5861 | ahp->ah_rxchainmask = rxchainmask; | ||
5862 | |||
5863 | if (AR_SREV_9280(ah)) { | ||
5864 | ahp->ah_txchainmask &= 0x3; | ||
5865 | ahp->ah_rxchainmask &= 0x3; | ||
5866 | } | ||
5867 | |||
5868 | if (ath9k_hw_check_chan(ah, chan) == NULL) { | ||
5869 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
5870 | "%s: invalid channel %u/0x%x; no mapping\n", | ||
5871 | __func__, chan->channel, chan->channelFlags); | ||
5872 | FAIL(-EINVAL); | ||
5873 | } | ||
5874 | |||
5875 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | ||
5876 | return false; | ||
5877 | |||
5878 | if (curchan) | ||
5879 | ath9k_hw_getnf(ah, curchan); | ||
5880 | |||
5881 | if (bChannelChange && | ||
5882 | (ahp->ah_chipFullSleep != true) && | ||
5883 | (ah->ah_curchan != NULL) && | ||
5884 | (chan->channel != ah->ah_curchan->channel) && | ||
5885 | ((chan->channelFlags & CHANNEL_ALL) == | ||
5886 | (ah->ah_curchan->channelFlags & CHANNEL_ALL)) && | ||
5887 | (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && | ||
5888 | !IS_CHAN_A_5MHZ_SPACED(ah-> | ||
5889 | ah_curchan)))) { | ||
5890 | |||
5891 | if (ath9k_hw_channel_change(ah, chan, macmode)) { | ||
5892 | ath9k_hw_loadnf(ah, ah->ah_curchan); | ||
5893 | ath9k_hw_start_nfcal(ah); | ||
5894 | return true; | ||
5895 | } | ||
5896 | } | ||
5897 | |||
5898 | saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); | ||
5899 | if (saveDefAntenna == 0) | ||
5900 | saveDefAntenna = 1; | ||
5901 | |||
5902 | macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; | ||
5903 | |||
5904 | saveLedState = REG_READ(ah, AR_CFG_LED) & | ||
5905 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | | ||
5906 | AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); | ||
5907 | |||
5908 | ath9k_hw_mark_phy_inactive(ah); | ||
5909 | |||
5910 | if (!ath9k_hw_chip_reset(ah, chan)) { | ||
5911 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: chip reset failed\n", | ||
5912 | __func__); | ||
5913 | FAIL(-EIO); | ||
5914 | } | ||
5915 | |||
5916 | if (AR_SREV_9280(ah)) { | ||
5917 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
5918 | AR_GPIO_JTAG_DISABLE); | ||
5919 | |||
5920 | if (ah->ah_caps.halWirelessModes & ATH9K_MODE_SEL_11A) { | ||
5921 | if (IS_CHAN_5GHZ(chan)) | ||
5922 | ath9k_hw_set_gpio(ah, 9, 0); | ||
5923 | else | ||
5924 | ath9k_hw_set_gpio(ah, 9, 1); | ||
5925 | } | ||
5926 | ath9k_hw_cfg_output(ah, 9, ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
5927 | } | ||
5928 | |||
5929 | ecode = ath9k_hw_process_ini(ah, chan, macmode); | ||
5930 | if (ecode != 0) | ||
5931 | goto bad; | ||
5932 | |||
5933 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | ||
5934 | ath9k_hw_set_delta_slope(ah, chan); | ||
5935 | |||
5936 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
5937 | ath9k_hw_9280_spur_mitigate(ah, chan); | ||
5938 | else | ||
5939 | ath9k_hw_spur_mitigate(ah, chan); | ||
5940 | |||
5941 | if (!ath9k_hw_eeprom_set_board_values(ah, chan)) { | ||
5942 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
5943 | "%s: error setting board options\n", __func__); | ||
5944 | FAIL(-EIO); | ||
5945 | } | ||
5946 | |||
5947 | ath9k_hw_decrease_chain_power(ah, chan); | ||
5948 | |||
5949 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ahp->ah_macaddr)); | ||
5950 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ahp->ah_macaddr + 4) | ||
5951 | | macStaId1 | ||
5952 | | AR_STA_ID1_RTS_USE_DEF | ||
5953 | | (ah->ah_config. | ||
5954 | ath_hal_6mb_ack ? AR_STA_ID1_ACKCTS_6MB : 0) | ||
5955 | | ahp->ah_staId1Defaults); | ||
5956 | ath9k_hw_set_operating_mode(ah, opmode); | ||
5957 | |||
5958 | REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask)); | ||
5959 | REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4)); | ||
5960 | |||
5961 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); | ||
5962 | |||
5963 | REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid)); | ||
5964 | REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) | | ||
5965 | ((ahp->ah_assocId & 0x3fff) << AR_BSS_ID1_AID_S)); | ||
5966 | |||
5967 | REG_WRITE(ah, AR_ISR, ~0); | ||
5968 | |||
5969 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | ||
5970 | |||
5971 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
5972 | if (!(ath9k_hw_ar9280_set_channel(ah, chan))) | ||
5973 | FAIL(-EIO); | ||
5974 | } else { | ||
5975 | if (!(ath9k_hw_set_channel(ah, chan))) | ||
5976 | FAIL(-EIO); | ||
5977 | } | ||
5978 | |||
5979 | for (i = 0; i < AR_NUM_DCU; i++) | ||
5980 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | ||
5981 | |||
5982 | ahp->ah_intrTxqs = 0; | ||
5983 | for (i = 0; i < ah->ah_caps.halTotalQueues; i++) | ||
5984 | ath9k_hw_resettxqueue(ah, i); | ||
5985 | |||
5986 | ath9k_hw_init_interrupt_masks(ah, opmode); | ||
5987 | ath9k_hw_init_qos(ah); | ||
5988 | |||
5989 | ath9k_hw_init_user_settings(ah); | ||
5990 | |||
5991 | ah->ah_opmode = opmode; | ||
5992 | |||
5993 | REG_WRITE(ah, AR_STA_ID1, | ||
5994 | REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); | ||
5995 | |||
5996 | ath9k_hw_set_dma(ah); | ||
5997 | |||
5998 | REG_WRITE(ah, AR_OBS, 8); | ||
5999 | |||
6000 | if (ahp->ah_intrMitigation) { | ||
6001 | |||
6002 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); | ||
6003 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); | ||
6004 | } | ||
6005 | |||
6006 | ath9k_hw_init_bb(ah, chan); | ||
6007 | |||
6008 | if (!ath9k_hw_init_cal(ah, chan)) | ||
6009 | FAIL(-ENODEV); | ||
6010 | |||
6011 | rx_chainmask = ahp->ah_rxchainmask; | ||
6012 | if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { | ||
6013 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); | ||
6014 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); | ||
6015 | } | ||
6016 | |||
6017 | REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); | ||
6018 | |||
6019 | if (AR_SREV_9100(ah)) { | ||
6020 | u32 mask; | ||
6021 | mask = REG_READ(ah, AR_CFG); | ||
6022 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | ||
6023 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
6024 | "%s CFG Byte Swap Set 0x%x\n", __func__, | ||
6025 | mask); | ||
6026 | } else { | ||
6027 | mask = | ||
6028 | INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | ||
6029 | REG_WRITE(ah, AR_CFG, mask); | ||
6030 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
6031 | "%s Setting CFG 0x%x\n", __func__, | ||
6032 | REG_READ(ah, AR_CFG)); | ||
6033 | } | ||
6034 | } else { | ||
6035 | #ifdef __BIG_ENDIAN | ||
6036 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
6037 | #endif | ||
6038 | } | ||
6039 | |||
6040 | return true; | ||
6041 | bad: | ||
6042 | if (status) | ||
6043 | *status = ecode; | ||
6044 | return false; | ||
6045 | #undef FAIL | ||
6046 | } | ||
6047 | |||
6048 | bool ath9k_hw_phy_disable(struct ath_hal *ah) | ||
6049 | { | ||
6050 | return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM); | ||
6051 | } | ||
6052 | |||
6053 | bool ath9k_hw_disable(struct ath_hal *ah) | ||
6054 | { | ||
6055 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | ||
6056 | return false; | ||
6057 | |||
6058 | return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); | ||
6059 | } | ||
6060 | |||
6061 | bool | ||
6062 | ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan, | ||
6063 | u8 rxchainmask, bool longcal, | ||
6064 | bool *isCalDone) | ||
6065 | { | ||
6066 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6067 | struct hal_cal_list *currCal = ahp->ah_cal_list_curr; | ||
6068 | struct ath9k_channel *ichan = | ||
6069 | ath9k_regd_check_channel(ah, chan); | ||
6070 | |||
6071 | *isCalDone = true; | ||
6072 | |||
6073 | if (ichan == NULL) { | ||
6074 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
6075 | "%s: invalid channel %u/0x%x; no mapping\n", | ||
6076 | __func__, chan->channel, chan->channelFlags); | ||
6077 | return false; | ||
6078 | } | ||
6079 | |||
6080 | if (currCal && | ||
6081 | (currCal->calState == CAL_RUNNING || | ||
6082 | currCal->calState == CAL_WAITING)) { | ||
6083 | ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal, | ||
6084 | isCalDone); | ||
6085 | if (*isCalDone) { | ||
6086 | ahp->ah_cal_list_curr = currCal = currCal->calNext; | ||
6087 | |||
6088 | if (currCal->calState == CAL_WAITING) { | ||
6089 | *isCalDone = false; | ||
6090 | ath9k_hw_reset_calibration(ah, currCal); | ||
6091 | } | ||
6092 | } | ||
6093 | } | ||
6094 | |||
6095 | if (longcal) { | ||
6096 | ath9k_hw_getnf(ah, ichan); | ||
6097 | ath9k_hw_loadnf(ah, ah->ah_curchan); | ||
6098 | ath9k_hw_start_nfcal(ah); | ||
6099 | |||
6100 | if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { | ||
6101 | |||
6102 | chan->channelFlags |= CHANNEL_CW_INT; | ||
6103 | ichan->channelFlags &= ~CHANNEL_CW_INT; | ||
6104 | } | ||
6105 | } | ||
6106 | |||
6107 | return true; | ||
6108 | } | ||
6109 | |||
6110 | static void ath9k_hw_iqcal_collect(struct ath_hal *ah) | ||
6111 | { | ||
6112 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6113 | int i; | ||
6114 | |||
6115 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
6116 | ahp->ah_totalPowerMeasI[i] += | ||
6117 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | ||
6118 | ahp->ah_totalPowerMeasQ[i] += | ||
6119 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | ||
6120 | ahp->ah_totalIqCorrMeas[i] += | ||
6121 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | ||
6122 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6123 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", | ||
6124 | ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i], | ||
6125 | ahp->ah_totalPowerMeasQ[i], | ||
6126 | ahp->ah_totalIqCorrMeas[i]); | ||
6127 | } | ||
6128 | } | ||
6129 | |||
6130 | static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah) | ||
6131 | { | ||
6132 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6133 | int i; | ||
6134 | |||
6135 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
6136 | ahp->ah_totalAdcIOddPhase[i] += | ||
6137 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | ||
6138 | ahp->ah_totalAdcIEvenPhase[i] += | ||
6139 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | ||
6140 | ahp->ah_totalAdcQOddPhase[i] += | ||
6141 | REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | ||
6142 | ahp->ah_totalAdcQEvenPhase[i] += | ||
6143 | REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | ||
6144 | |||
6145 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6146 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | ||
6147 | "oddq=0x%08x; evenq=0x%08x;\n", | ||
6148 | ahp->ah_CalSamples, i, | ||
6149 | ahp->ah_totalAdcIOddPhase[i], | ||
6150 | ahp->ah_totalAdcIEvenPhase[i], | ||
6151 | ahp->ah_totalAdcQOddPhase[i], | ||
6152 | ahp->ah_totalAdcQEvenPhase[i]); | ||
6153 | } | ||
6154 | } | ||
6155 | |||
6156 | static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah) | ||
6157 | { | ||
6158 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6159 | int i; | ||
6160 | |||
6161 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
6162 | ahp->ah_totalAdcDcOffsetIOddPhase[i] += | ||
6163 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | ||
6164 | ahp->ah_totalAdcDcOffsetIEvenPhase[i] += | ||
6165 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | ||
6166 | ahp->ah_totalAdcDcOffsetQOddPhase[i] += | ||
6167 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | ||
6168 | ahp->ah_totalAdcDcOffsetQEvenPhase[i] += | ||
6169 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | ||
6170 | |||
6171 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6172 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | ||
6173 | "oddq=0x%08x; evenq=0x%08x;\n", | ||
6174 | ahp->ah_CalSamples, i, | ||
6175 | ahp->ah_totalAdcDcOffsetIOddPhase[i], | ||
6176 | ahp->ah_totalAdcDcOffsetIEvenPhase[i], | ||
6177 | ahp->ah_totalAdcDcOffsetQOddPhase[i], | ||
6178 | ahp->ah_totalAdcDcOffsetQEvenPhase[i]); | ||
6179 | } | ||
6180 | } | ||
6181 | |||
6182 | static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains) | ||
6183 | { | ||
6184 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6185 | u32 powerMeasQ, powerMeasI, iqCorrMeas; | ||
6186 | u32 qCoffDenom, iCoffDenom; | ||
6187 | int32_t qCoff, iCoff; | ||
6188 | int iqCorrNeg, i; | ||
6189 | |||
6190 | for (i = 0; i < numChains; i++) { | ||
6191 | powerMeasI = ahp->ah_totalPowerMeasI[i]; | ||
6192 | powerMeasQ = ahp->ah_totalPowerMeasQ[i]; | ||
6193 | iqCorrMeas = ahp->ah_totalIqCorrMeas[i]; | ||
6194 | |||
6195 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6196 | "Starting IQ Cal and Correction for Chain %d\n", | ||
6197 | i); | ||
6198 | |||
6199 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6200 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", | ||
6201 | i, ahp->ah_totalIqCorrMeas[i]); | ||
6202 | |||
6203 | iqCorrNeg = 0; | ||
6204 | |||
6205 | |||
6206 | if (iqCorrMeas > 0x80000000) { | ||
6207 | iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; | ||
6208 | iqCorrNeg = 1; | ||
6209 | } | ||
6210 | |||
6211 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6212 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); | ||
6213 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6214 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); | ||
6215 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", | ||
6216 | iqCorrNeg); | ||
6217 | |||
6218 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; | ||
6219 | qCoffDenom = powerMeasQ / 64; | ||
6220 | |||
6221 | if (powerMeasQ != 0) { | ||
6222 | |||
6223 | iCoff = iqCorrMeas / iCoffDenom; | ||
6224 | qCoff = powerMeasI / qCoffDenom - 64; | ||
6225 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6226 | "Chn %d iCoff = 0x%08x\n", i, iCoff); | ||
6227 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6228 | "Chn %d qCoff = 0x%08x\n", i, qCoff); | ||
6229 | |||
6230 | |||
6231 | iCoff = iCoff & 0x3f; | ||
6232 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6233 | "New: Chn %d iCoff = 0x%08x\n", i, iCoff); | ||
6234 | if (iqCorrNeg == 0x0) | ||
6235 | iCoff = 0x40 - iCoff; | ||
6236 | |||
6237 | if (qCoff > 15) | ||
6238 | qCoff = 15; | ||
6239 | else if (qCoff <= -16) | ||
6240 | qCoff = 16; | ||
6241 | |||
6242 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6243 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", | ||
6244 | i, iCoff, qCoff); | ||
6245 | |||
6246 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | ||
6247 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, | ||
6248 | iCoff); | ||
6249 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | ||
6250 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, | ||
6251 | qCoff); | ||
6252 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6253 | "IQ Cal and Correction done for Chain %d\n", | ||
6254 | i); | ||
6255 | } | ||
6256 | } | ||
6257 | |||
6258 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | ||
6259 | AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); | ||
6260 | } | ||
6261 | |||
6262 | static void | ||
6263 | ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains) | ||
6264 | { | ||
6265 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6266 | u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, | ||
6267 | qEvenMeasOffset; | ||
6268 | u32 qGainMismatch, iGainMismatch, val, i; | ||
6269 | |||
6270 | for (i = 0; i < numChains; i++) { | ||
6271 | iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i]; | ||
6272 | iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i]; | ||
6273 | qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i]; | ||
6274 | qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i]; | ||
6275 | |||
6276 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6277 | "Starting ADC Gain Cal for Chain %d\n", i); | ||
6278 | |||
6279 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6280 | "Chn %d pwr_meas_odd_i = 0x%08x\n", i, | ||
6281 | iOddMeasOffset); | ||
6282 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6283 | "Chn %d pwr_meas_even_i = 0x%08x\n", i, | ||
6284 | iEvenMeasOffset); | ||
6285 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6286 | "Chn %d pwr_meas_odd_q = 0x%08x\n", i, | ||
6287 | qOddMeasOffset); | ||
6288 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6289 | "Chn %d pwr_meas_even_q = 0x%08x\n", i, | ||
6290 | qEvenMeasOffset); | ||
6291 | |||
6292 | if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { | ||
6293 | iGainMismatch = | ||
6294 | ((iEvenMeasOffset * 32) / | ||
6295 | iOddMeasOffset) & 0x3f; | ||
6296 | qGainMismatch = | ||
6297 | ((qOddMeasOffset * 32) / | ||
6298 | qEvenMeasOffset) & 0x3f; | ||
6299 | |||
6300 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6301 | "Chn %d gain_mismatch_i = 0x%08x\n", i, | ||
6302 | iGainMismatch); | ||
6303 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6304 | "Chn %d gain_mismatch_q = 0x%08x\n", i, | ||
6305 | qGainMismatch); | ||
6306 | |||
6307 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | ||
6308 | val &= 0xfffff000; | ||
6309 | val |= (qGainMismatch) | (iGainMismatch << 6); | ||
6310 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | ||
6311 | |||
6312 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6313 | "ADC Gain Cal done for Chain %d\n", i); | ||
6314 | } | ||
6315 | } | ||
6316 | |||
6317 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | ||
6318 | REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | | ||
6319 | AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); | ||
6320 | } | ||
6321 | |||
6322 | static void | ||
6323 | ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains) | ||
6324 | { | ||
6325 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6326 | u32 iOddMeasOffset, iEvenMeasOffset, val, i; | ||
6327 | int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; | ||
6328 | const struct hal_percal_data *calData = | ||
6329 | ahp->ah_cal_list_curr->calData; | ||
6330 | u32 numSamples = | ||
6331 | (1 << (calData->calCountMax + 5)) * calData->calNumSamples; | ||
6332 | |||
6333 | for (i = 0; i < numChains; i++) { | ||
6334 | iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i]; | ||
6335 | iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i]; | ||
6336 | qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i]; | ||
6337 | qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i]; | ||
6338 | |||
6339 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6340 | "Starting ADC DC Offset Cal for Chain %d\n", i); | ||
6341 | |||
6342 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6343 | "Chn %d pwr_meas_odd_i = %d\n", i, | ||
6344 | iOddMeasOffset); | ||
6345 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6346 | "Chn %d pwr_meas_even_i = %d\n", i, | ||
6347 | iEvenMeasOffset); | ||
6348 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6349 | "Chn %d pwr_meas_odd_q = %d\n", i, | ||
6350 | qOddMeasOffset); | ||
6351 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6352 | "Chn %d pwr_meas_even_q = %d\n", i, | ||
6353 | qEvenMeasOffset); | ||
6354 | |||
6355 | iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / | ||
6356 | numSamples) & 0x1ff; | ||
6357 | qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / | ||
6358 | numSamples) & 0x1ff; | ||
6359 | |||
6360 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6361 | "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, | ||
6362 | iDcMismatch); | ||
6363 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6364 | "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, | ||
6365 | qDcMismatch); | ||
6366 | |||
6367 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | ||
6368 | val &= 0xc0000fff; | ||
6369 | val |= (qDcMismatch << 12) | (iDcMismatch << 21); | ||
6370 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | ||
6371 | |||
6372 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6373 | "ADC DC Offset Cal done for Chain %d\n", i); | ||
6374 | } | ||
6375 | |||
6376 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | ||
6377 | REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | | ||
6378 | AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); | ||
6379 | } | ||
6380 | |||
6381 | bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit) | ||
6382 | { | ||
6383 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6384 | struct ath9k_channel *chan = ah->ah_curchan; | ||
6385 | |||
6386 | ah->ah_powerLimit = min(limit, (u32) MAX_RATE_POWER); | ||
6387 | |||
6388 | if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan, | ||
6389 | ath9k_regd_get_ctl(ah, chan), | ||
6390 | ath9k_regd_get_antenna_allowed(ah, | ||
6391 | chan), | ||
6392 | chan->maxRegTxPower * 2, | ||
6393 | min((u32) MAX_RATE_POWER, | ||
6394 | (u32) ah->ah_powerLimit)) != 0) | ||
6395 | return false; | ||
6396 | |||
6397 | return true; | ||
6398 | } | ||
6399 | |||
6400 | void | ||
6401 | ath9k_hw_get_channel_centers(struct ath_hal *ah, | ||
6402 | struct ath9k_channel *chan, | ||
6403 | struct chan_centers *centers) | ||
6404 | { | ||
6405 | int8_t extoff; | ||
6406 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6407 | |||
6408 | if (!IS_CHAN_HT40(chan)) { | ||
6409 | centers->ctl_center = centers->ext_center = | ||
6410 | centers->synth_center = chan->channel; | ||
6411 | return; | ||
6412 | } | ||
6413 | |||
6414 | if ((chan->chanmode == CHANNEL_A_HT40PLUS) || | ||
6415 | (chan->chanmode == CHANNEL_G_HT40PLUS)) { | ||
6416 | centers->synth_center = | ||
6417 | chan->channel + HT40_CHANNEL_CENTER_SHIFT; | ||
6418 | extoff = 1; | ||
6419 | } else { | ||
6420 | centers->synth_center = | ||
6421 | chan->channel - HT40_CHANNEL_CENTER_SHIFT; | ||
6422 | extoff = -1; | ||
6423 | } | ||
6424 | |||
6425 | centers->ctl_center = centers->synth_center - (extoff * | ||
6426 | HT40_CHANNEL_CENTER_SHIFT); | ||
6427 | centers->ext_center = centers->synth_center + (extoff * | ||
6428 | ((ahp-> | ||
6429 | ah_extprotspacing | ||
6430 | == | ||
6431 | ATH9K_HT_EXTPROTSPACING_20) | ||
6432 | ? | ||
6433 | HT40_CHANNEL_CENTER_SHIFT | ||
6434 | : 15)); | ||
6435 | |||
6436 | } | ||
6437 | |||
6438 | void | ||
6439 | ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan, | ||
6440 | bool *isCalDone) | ||
6441 | { | ||
6442 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6443 | struct ath9k_channel *ichan = | ||
6444 | ath9k_regd_check_channel(ah, chan); | ||
6445 | struct hal_cal_list *currCal = ahp->ah_cal_list_curr; | ||
6446 | |||
6447 | *isCalDone = true; | ||
6448 | |||
6449 | if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) | ||
6450 | return; | ||
6451 | |||
6452 | if (currCal == NULL) | ||
6453 | return; | ||
6454 | |||
6455 | if (ichan == NULL) { | ||
6456 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6457 | "%s: invalid channel %u/0x%x; no mapping\n", | ||
6458 | __func__, chan->channel, chan->channelFlags); | ||
6459 | return; | ||
6460 | } | ||
6461 | |||
6462 | |||
6463 | if (currCal->calState != CAL_DONE) { | ||
6464 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6465 | "%s: Calibration state incorrect, %d\n", | ||
6466 | __func__, currCal->calState); | ||
6467 | return; | ||
6468 | } | ||
6469 | |||
6470 | |||
6471 | if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType)) | ||
6472 | return; | ||
6473 | |||
6474 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6475 | "%s: Resetting Cal %d state for channel %u/0x%x\n", | ||
6476 | __func__, currCal->calData->calType, chan->channel, | ||
6477 | chan->channelFlags); | ||
6478 | |||
6479 | ichan->CalValid &= ~currCal->calData->calType; | ||
6480 | currCal->calState = CAL_WAITING; | ||
6481 | |||
6482 | *isCalDone = false; | ||
6483 | } | ||
6484 | |||
6485 | void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac) | ||
6486 | { | ||
6487 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6488 | |||
6489 | memcpy(mac, ahp->ah_macaddr, ETH_ALEN); | ||
6490 | } | ||
6491 | |||
6492 | bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac) | ||
6493 | { | ||
6494 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6495 | |||
6496 | memcpy(ahp->ah_macaddr, mac, ETH_ALEN); | ||
6497 | return true; | ||
6498 | } | ||
6499 | |||
6500 | void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask) | ||
6501 | { | ||
6502 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6503 | |||
6504 | memcpy(mask, ahp->ah_bssidmask, ETH_ALEN); | ||
6505 | } | ||
6506 | |||
6507 | bool | ||
6508 | ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask) | ||
6509 | { | ||
6510 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6511 | |||
6512 | memcpy(ahp->ah_bssidmask, mask, ETH_ALEN); | ||
6513 | |||
6514 | REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask)); | ||
6515 | REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4)); | ||
6516 | |||
6517 | return true; | ||
6518 | } | ||
6519 | |||
6520 | #ifdef CONFIG_ATH9K_RFKILL | ||
6521 | static void ath9k_enable_rfkill(struct ath_hal *ah) | ||
6522 | { | ||
6523 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6524 | |||
6525 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
6526 | AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); | ||
6527 | |||
6528 | REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, | ||
6529 | AR_GPIO_INPUT_MUX2_RFSILENT); | ||
6530 | |||
6531 | ath9k_hw_cfg_gpio_input(ah, ahp->ah_gpioSelect); | ||
6532 | REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); | ||
6533 | |||
6534 | if (ahp->ah_gpioBit == ath9k_hw_gpio_get(ah, ahp->ah_gpioSelect)) { | ||
6535 | |||
6536 | ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect, | ||
6537 | !ahp->ah_gpioBit); | ||
6538 | } else { | ||
6539 | ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect, | ||
6540 | ahp->ah_gpioBit); | ||
6541 | } | ||
6542 | } | ||
6543 | #endif | ||
6544 | |||
6545 | void | ||
6546 | ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, | ||
6547 | u16 assocId) | ||
6548 | { | ||
6549 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6550 | |||
6551 | memcpy(ahp->ah_bssid, bssid, ETH_ALEN); | ||
6552 | ahp->ah_assocId = assocId; | ||
6553 | |||
6554 | REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid)); | ||
6555 | REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) | | ||
6556 | ((assocId & 0x3fff) << AR_BSS_ID1_AID_S)); | ||
6557 | } | ||
6558 | |||
6559 | u64 ath9k_hw_gettsf64(struct ath_hal *ah) | ||
6560 | { | ||
6561 | u64 tsf; | ||
6562 | |||
6563 | tsf = REG_READ(ah, AR_TSF_U32); | ||
6564 | tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32); | ||
6565 | return tsf; | ||
6566 | } | ||
6567 | |||
6568 | void ath9k_hw_reset_tsf(struct ath_hal *ah) | ||
6569 | { | ||
6570 | int count; | ||
6571 | |||
6572 | count = 0; | ||
6573 | while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) { | ||
6574 | count++; | ||
6575 | if (count > 10) { | ||
6576 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
6577 | "%s: AR_SLP32_TSF_WRITE_STATUS limit exceeded\n", | ||
6578 | __func__); | ||
6579 | break; | ||
6580 | } | ||
6581 | udelay(10); | ||
6582 | } | ||
6583 | REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); | ||
6584 | } | ||
6585 | |||
6586 | u32 ath9k_hw_getdefantenna(struct ath_hal *ah) | ||
6587 | { | ||
6588 | return REG_READ(ah, AR_DEF_ANTENNA) & 0x7; | ||
6589 | } | ||
6590 | |||
6591 | void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna) | ||
6592 | { | ||
6593 | REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); | ||
6594 | } | ||
6595 | |||
6596 | bool | ||
6597 | ath9k_hw_setantennaswitch(struct ath_hal *ah, | ||
6598 | enum ath9k_ant_setting settings, | ||
6599 | struct ath9k_channel *chan, | ||
6600 | u8 *tx_chainmask, | ||
6601 | u8 *rx_chainmask, | ||
6602 | u8 *antenna_cfgd) | ||
6603 | { | ||
6604 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6605 | static u8 tx_chainmask_cfg, rx_chainmask_cfg; | ||
6606 | |||
6607 | if (AR_SREV_9280(ah)) { | ||
6608 | if (!tx_chainmask_cfg) { | ||
6609 | |||
6610 | tx_chainmask_cfg = *tx_chainmask; | ||
6611 | rx_chainmask_cfg = *rx_chainmask; | ||
6612 | } | ||
6613 | |||
6614 | switch (settings) { | ||
6615 | case ATH9K_ANT_FIXED_A: | ||
6616 | *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK; | ||
6617 | *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK; | ||
6618 | *antenna_cfgd = true; | ||
6619 | break; | ||
6620 | case ATH9K_ANT_FIXED_B: | ||
6621 | if (ah->ah_caps.halTxChainMask > | ||
6622 | ATH9K_ANTENNA1_CHAINMASK) { | ||
6623 | *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK; | ||
6624 | } | ||
6625 | *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK; | ||
6626 | *antenna_cfgd = true; | ||
6627 | break; | ||
6628 | case ATH9K_ANT_VARIABLE: | ||
6629 | *tx_chainmask = tx_chainmask_cfg; | ||
6630 | *rx_chainmask = rx_chainmask_cfg; | ||
6631 | *antenna_cfgd = true; | ||
6632 | break; | ||
6633 | default: | ||
6634 | break; | ||
6635 | } | ||
6636 | } else { | ||
6637 | ahp->ah_diversityControl = settings; | ||
6638 | } | ||
6639 | |||
6640 | return true; | ||
6641 | } | ||
6642 | |||
6643 | void ath9k_hw_setopmode(struct ath_hal *ah) | ||
6644 | { | ||
6645 | ath9k_hw_set_operating_mode(ah, ah->ah_opmode); | ||
6646 | } | ||
6647 | |||
6648 | bool | ||
6649 | ath9k_hw_getcapability(struct ath_hal *ah, enum hal_capability_type type, | ||
6650 | u32 capability, u32 *result) | ||
6651 | { | ||
6652 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6653 | const struct hal_capabilities *pCap = &ah->ah_caps; | ||
6654 | |||
6655 | switch (type) { | ||
6656 | case HAL_CAP_CIPHER: | ||
6657 | switch (capability) { | ||
6658 | case ATH9K_CIPHER_AES_CCM: | ||
6659 | case ATH9K_CIPHER_AES_OCB: | ||
6660 | case ATH9K_CIPHER_TKIP: | ||
6661 | case ATH9K_CIPHER_WEP: | ||
6662 | case ATH9K_CIPHER_MIC: | ||
6663 | case ATH9K_CIPHER_CLR: | ||
6664 | return true; | ||
6665 | default: | ||
6666 | return false; | ||
6667 | } | ||
6668 | case HAL_CAP_TKIP_MIC: | ||
6669 | switch (capability) { | ||
6670 | case 0: | ||
6671 | return true; | ||
6672 | case 1: | ||
6673 | return (ahp->ah_staId1Defaults & | ||
6674 | AR_STA_ID1_CRPT_MIC_ENABLE) ? true : | ||
6675 | false; | ||
6676 | } | ||
6677 | case HAL_CAP_TKIP_SPLIT: | ||
6678 | return (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) ? | ||
6679 | false : true; | ||
6680 | case HAL_CAP_WME_TKIPMIC: | ||
6681 | return 0; | ||
6682 | case HAL_CAP_PHYCOUNTERS: | ||
6683 | return ahp->ah_hasHwPhyCounters ? 0 : -ENXIO; | ||
6684 | case HAL_CAP_DIVERSITY: | ||
6685 | return (REG_READ(ah, AR_PHY_CCK_DETECT) & | ||
6686 | AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ? | ||
6687 | true : false; | ||
6688 | case HAL_CAP_PHYDIAG: | ||
6689 | return true; | ||
6690 | case HAL_CAP_MCAST_KEYSRCH: | ||
6691 | switch (capability) { | ||
6692 | case 0: | ||
6693 | return true; | ||
6694 | case 1: | ||
6695 | if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) { | ||
6696 | return false; | ||
6697 | } else { | ||
6698 | return (ahp->ah_staId1Defaults & | ||
6699 | AR_STA_ID1_MCAST_KSRCH) ? true : | ||
6700 | false; | ||
6701 | } | ||
6702 | } | ||
6703 | return false; | ||
6704 | case HAL_CAP_TSF_ADJUST: | ||
6705 | return (ahp->ah_miscMode & AR_PCU_TX_ADD_TSF) ? | ||
6706 | true : false; | ||
6707 | case HAL_CAP_RFSILENT: | ||
6708 | if (capability == 3) | ||
6709 | return false; | ||
6710 | case HAL_CAP_ANT_CFG_2GHZ: | ||
6711 | *result = pCap->halNumAntCfg2GHz; | ||
6712 | return true; | ||
6713 | case HAL_CAP_ANT_CFG_5GHZ: | ||
6714 | *result = pCap->halNumAntCfg5GHz; | ||
6715 | return true; | ||
6716 | case HAL_CAP_TXPOW: | ||
6717 | switch (capability) { | ||
6718 | case 0: | ||
6719 | return 0; | ||
6720 | case 1: | ||
6721 | *result = ah->ah_powerLimit; | ||
6722 | return 0; | ||
6723 | case 2: | ||
6724 | *result = ah->ah_maxPowerLevel; | ||
6725 | return 0; | ||
6726 | case 3: | ||
6727 | *result = ah->ah_tpScale; | ||
6728 | return 0; | ||
6729 | } | ||
6730 | return false; | ||
6731 | default: | ||
6732 | return false; | ||
6733 | } | ||
6734 | } | ||
6735 | |||
6736 | int | ||
6737 | ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg) | ||
6738 | { | ||
6739 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6740 | struct ath9k_channel *chan = ah->ah_curchan; | ||
6741 | const struct hal_capabilities *pCap = &ah->ah_caps; | ||
6742 | u16 ant_config; | ||
6743 | u32 halNumAntConfig; | ||
6744 | |||
6745 | halNumAntConfig = | ||
6746 | IS_CHAN_2GHZ(chan) ? pCap->halNumAntCfg2GHz : pCap-> | ||
6747 | halNumAntCfg5GHz; | ||
6748 | |||
6749 | if (cfg < halNumAntConfig) { | ||
6750 | if (!ath9k_hw_get_eeprom_antenna_cfg(ahp, chan, | ||
6751 | cfg, &ant_config)) { | ||
6752 | REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config); | ||
6753 | return 0; | ||
6754 | } | ||
6755 | } | ||
6756 | |||
6757 | return -EINVAL; | ||
6758 | } | ||
6759 | |||
6760 | bool ath9k_hw_intrpend(struct ath_hal *ah) | ||
6761 | { | ||
6762 | u32 host_isr; | ||
6763 | |||
6764 | if (AR_SREV_9100(ah)) | ||
6765 | return true; | ||
6766 | |||
6767 | host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); | ||
6768 | if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) | ||
6769 | return true; | ||
6770 | |||
6771 | host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); | ||
6772 | if ((host_isr & AR_INTR_SYNC_DEFAULT) | ||
6773 | && (host_isr != AR_INTR_SPURIOUS)) | ||
6774 | return true; | ||
6775 | |||
6776 | return false; | ||
6777 | } | ||
6778 | |||
6779 | bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked) | ||
6780 | { | ||
6781 | u32 isr = 0; | ||
6782 | u32 mask2 = 0; | ||
6783 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
6784 | u32 sync_cause = 0; | ||
6785 | bool fatal_int = false; | ||
6786 | |||
6787 | if (!AR_SREV_9100(ah)) { | ||
6788 | if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { | ||
6789 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) | ||
6790 | == AR_RTC_STATUS_ON) { | ||
6791 | isr = REG_READ(ah, AR_ISR); | ||
6792 | } | ||
6793 | } | ||
6794 | |||
6795 | sync_cause = | ||
6796 | REG_READ(ah, | ||
6797 | AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; | ||
6798 | |||
6799 | *masked = 0; | ||
6800 | |||
6801 | if (!isr && !sync_cause) | ||
6802 | return false; | ||
6803 | } else { | ||
6804 | *masked = 0; | ||
6805 | isr = REG_READ(ah, AR_ISR); | ||
6806 | } | ||
6807 | |||
6808 | if (isr) { | ||
6809 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6810 | |||
6811 | if (isr & AR_ISR_BCNMISC) { | ||
6812 | u32 isr2; | ||
6813 | isr2 = REG_READ(ah, AR_ISR_S2); | ||
6814 | if (isr2 & AR_ISR_S2_TIM) | ||
6815 | mask2 |= ATH9K_INT_TIM; | ||
6816 | if (isr2 & AR_ISR_S2_DTIM) | ||
6817 | mask2 |= ATH9K_INT_DTIM; | ||
6818 | if (isr2 & AR_ISR_S2_DTIMSYNC) | ||
6819 | mask2 |= ATH9K_INT_DTIMSYNC; | ||
6820 | if (isr2 & (AR_ISR_S2_CABEND)) | ||
6821 | mask2 |= ATH9K_INT_CABEND; | ||
6822 | if (isr2 & AR_ISR_S2_GTT) | ||
6823 | mask2 |= ATH9K_INT_GTT; | ||
6824 | if (isr2 & AR_ISR_S2_CST) | ||
6825 | mask2 |= ATH9K_INT_CST; | ||
6826 | } | ||
6827 | |||
6828 | isr = REG_READ(ah, AR_ISR_RAC); | ||
6829 | if (isr == 0xffffffff) { | ||
6830 | *masked = 0; | ||
6831 | return false; | ||
6832 | } | ||
6833 | |||
6834 | *masked = isr & ATH9K_INT_COMMON; | ||
6835 | |||
6836 | if (ahp->ah_intrMitigation) { | ||
6837 | |||
6838 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) | ||
6839 | *masked |= ATH9K_INT_RX; | ||
6840 | } | ||
6841 | |||
6842 | if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) | ||
6843 | *masked |= ATH9K_INT_RX; | ||
6844 | if (isr & | ||
6845 | (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | | ||
6846 | AR_ISR_TXEOL)) { | ||
6847 | u32 s0_s, s1_s; | ||
6848 | |||
6849 | *masked |= ATH9K_INT_TX; | ||
6850 | |||
6851 | s0_s = REG_READ(ah, AR_ISR_S0_S); | ||
6852 | ahp->ah_intrTxqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); | ||
6853 | ahp->ah_intrTxqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); | ||
6854 | |||
6855 | s1_s = REG_READ(ah, AR_ISR_S1_S); | ||
6856 | ahp->ah_intrTxqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); | ||
6857 | ahp->ah_intrTxqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); | ||
6858 | } | ||
6859 | |||
6860 | if (isr & AR_ISR_RXORN) { | ||
6861 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | ||
6862 | "%s: receive FIFO overrun interrupt\n", | ||
6863 | __func__); | ||
6864 | } | ||
6865 | |||
6866 | if (!AR_SREV_9100(ah)) { | ||
6867 | if (!pCap->halAutoSleepSupport) { | ||
6868 | u32 isr5 = REG_READ(ah, AR_ISR_S5_S); | ||
6869 | if (isr5 & AR_ISR_S5_TIM_TIMER) | ||
6870 | *masked |= ATH9K_INT_TIM_TIMER; | ||
6871 | } | ||
6872 | } | ||
6873 | |||
6874 | *masked |= mask2; | ||
6875 | } | ||
6876 | if (AR_SREV_9100(ah)) | ||
6877 | return true; | ||
6878 | if (sync_cause) { | ||
6879 | fatal_int = | ||
6880 | (sync_cause & | ||
6881 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) | ||
6882 | ? true : false; | ||
6883 | |||
6884 | if (fatal_int) { | ||
6885 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { | ||
6886 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
6887 | "%s: received PCI FATAL interrupt\n", | ||
6888 | __func__); | ||
6889 | } | ||
6890 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { | ||
6891 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
6892 | "%s: received PCI PERR interrupt\n", | ||
6893 | __func__); | ||
6894 | } | ||
6895 | } | ||
6896 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { | ||
6897 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | ||
6898 | "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n", | ||
6899 | __func__); | ||
6900 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); | ||
6901 | REG_WRITE(ah, AR_RC, 0); | ||
6902 | *masked |= ATH9K_INT_FATAL; | ||
6903 | } | ||
6904 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { | ||
6905 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | ||
6906 | "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n", | ||
6907 | __func__); | ||
6908 | } | ||
6909 | |||
6910 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); | ||
6911 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); | ||
6912 | } | ||
6913 | return true; | ||
6914 | } | ||
6915 | |||
6916 | enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah) | ||
6917 | { | ||
6918 | return AH5416(ah)->ah_maskReg; | ||
6919 | } | ||
6920 | |||
6921 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints) | ||
6922 | { | ||
6923 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6924 | u32 omask = ahp->ah_maskReg; | ||
6925 | u32 mask, mask2; | ||
6926 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
6927 | |||
6928 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: 0x%x => 0x%x\n", __func__, | ||
6929 | omask, ints); | ||
6930 | |||
6931 | if (omask & ATH9K_INT_GLOBAL) { | ||
6932 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: disable IER\n", | ||
6933 | __func__); | ||
6934 | REG_WRITE(ah, AR_IER, AR_IER_DISABLE); | ||
6935 | (void) REG_READ(ah, AR_IER); | ||
6936 | if (!AR_SREV_9100(ah)) { | ||
6937 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); | ||
6938 | (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); | ||
6939 | |||
6940 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); | ||
6941 | (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); | ||
6942 | } | ||
6943 | } | ||
6944 | |||
6945 | mask = ints & ATH9K_INT_COMMON; | ||
6946 | mask2 = 0; | ||
6947 | |||
6948 | if (ints & ATH9K_INT_TX) { | ||
6949 | if (ahp->ah_txOkInterruptMask) | ||
6950 | mask |= AR_IMR_TXOK; | ||
6951 | if (ahp->ah_txDescInterruptMask) | ||
6952 | mask |= AR_IMR_TXDESC; | ||
6953 | if (ahp->ah_txErrInterruptMask) | ||
6954 | mask |= AR_IMR_TXERR; | ||
6955 | if (ahp->ah_txEolInterruptMask) | ||
6956 | mask |= AR_IMR_TXEOL; | ||
6957 | } | ||
6958 | if (ints & ATH9K_INT_RX) { | ||
6959 | mask |= AR_IMR_RXERR; | ||
6960 | if (ahp->ah_intrMitigation) | ||
6961 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; | ||
6962 | else | ||
6963 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; | ||
6964 | if (!pCap->halAutoSleepSupport) | ||
6965 | mask |= AR_IMR_GENTMR; | ||
6966 | } | ||
6967 | |||
6968 | if (ints & (ATH9K_INT_BMISC)) { | ||
6969 | mask |= AR_IMR_BCNMISC; | ||
6970 | if (ints & ATH9K_INT_TIM) | ||
6971 | mask2 |= AR_IMR_S2_TIM; | ||
6972 | if (ints & ATH9K_INT_DTIM) | ||
6973 | mask2 |= AR_IMR_S2_DTIM; | ||
6974 | if (ints & ATH9K_INT_DTIMSYNC) | ||
6975 | mask2 |= AR_IMR_S2_DTIMSYNC; | ||
6976 | if (ints & ATH9K_INT_CABEND) | ||
6977 | mask2 |= (AR_IMR_S2_CABEND); | ||
6978 | } | ||
6979 | |||
6980 | if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { | ||
6981 | mask |= AR_IMR_BCNMISC; | ||
6982 | if (ints & ATH9K_INT_GTT) | ||
6983 | mask2 |= AR_IMR_S2_GTT; | ||
6984 | if (ints & ATH9K_INT_CST) | ||
6985 | mask2 |= AR_IMR_S2_CST; | ||
6986 | } | ||
6987 | |||
6988 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, | ||
6989 | mask); | ||
6990 | REG_WRITE(ah, AR_IMR, mask); | ||
6991 | mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | | ||
6992 | AR_IMR_S2_DTIM | | ||
6993 | AR_IMR_S2_DTIMSYNC | | ||
6994 | AR_IMR_S2_CABEND | | ||
6995 | AR_IMR_S2_CABTO | | ||
6996 | AR_IMR_S2_TSFOOR | | ||
6997 | AR_IMR_S2_GTT | AR_IMR_S2_CST); | ||
6998 | REG_WRITE(ah, AR_IMR_S2, mask | mask2); | ||
6999 | ahp->ah_maskReg = ints; | ||
7000 | |||
7001 | if (!pCap->halAutoSleepSupport) { | ||
7002 | if (ints & ATH9K_INT_TIM_TIMER) | ||
7003 | REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); | ||
7004 | else | ||
7005 | REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); | ||
7006 | } | ||
7007 | |||
7008 | if (ints & ATH9K_INT_GLOBAL) { | ||
7009 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: enable IER\n", | ||
7010 | __func__); | ||
7011 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); | ||
7012 | if (!AR_SREV_9100(ah)) { | ||
7013 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, | ||
7014 | AR_INTR_MAC_IRQ); | ||
7015 | REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); | ||
7016 | |||
7017 | |||
7018 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, | ||
7019 | AR_INTR_SYNC_DEFAULT); | ||
7020 | REG_WRITE(ah, AR_INTR_SYNC_MASK, | ||
7021 | AR_INTR_SYNC_DEFAULT); | ||
7022 | } | ||
7023 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", | ||
7024 | REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); | ||
7025 | } | ||
7026 | |||
7027 | return omask; | ||
7028 | } | ||
7029 | |||
7030 | void | ||
7031 | ath9k_hw_beaconinit(struct ath_hal *ah, | ||
7032 | u32 next_beacon, u32 beacon_period) | ||
7033 | { | ||
7034 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7035 | int flags = 0; | ||
7036 | |||
7037 | ahp->ah_beaconInterval = beacon_period; | ||
7038 | |||
7039 | switch (ah->ah_opmode) { | ||
7040 | case ATH9K_M_STA: | ||
7041 | case ATH9K_M_MONITOR: | ||
7042 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); | ||
7043 | REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff); | ||
7044 | REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff); | ||
7045 | flags |= AR_TBTT_TIMER_EN; | ||
7046 | break; | ||
7047 | case ATH9K_M_IBSS: | ||
7048 | REG_SET_BIT(ah, AR_TXCFG, | ||
7049 | AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); | ||
7050 | REG_WRITE(ah, AR_NEXT_NDP_TIMER, | ||
7051 | TU_TO_USEC(next_beacon + | ||
7052 | (ahp->ah_atimWindow ? ahp-> | ||
7053 | ah_atimWindow : 1))); | ||
7054 | flags |= AR_NDP_TIMER_EN; | ||
7055 | case ATH9K_M_HOSTAP: | ||
7056 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); | ||
7057 | REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, | ||
7058 | TU_TO_USEC(next_beacon - | ||
7059 | ah->ah_config. | ||
7060 | ath_hal_dma_beacon_response_time)); | ||
7061 | REG_WRITE(ah, AR_NEXT_SWBA, | ||
7062 | TU_TO_USEC(next_beacon - | ||
7063 | ah->ah_config. | ||
7064 | ath_hal_sw_beacon_response_time)); | ||
7065 | flags |= | ||
7066 | AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; | ||
7067 | break; | ||
7068 | } | ||
7069 | |||
7070 | REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); | ||
7071 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); | ||
7072 | REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); | ||
7073 | REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); | ||
7074 | |||
7075 | beacon_period &= ~ATH9K_BEACON_ENA; | ||
7076 | if (beacon_period & ATH9K_BEACON_RESET_TSF) { | ||
7077 | beacon_period &= ~ATH9K_BEACON_RESET_TSF; | ||
7078 | ath9k_hw_reset_tsf(ah); | ||
7079 | } | ||
7080 | |||
7081 | REG_SET_BIT(ah, AR_TIMER_MODE, flags); | ||
7082 | } | ||
7083 | |||
7084 | void | ||
7085 | ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah, | ||
7086 | const struct ath9k_beacon_state *bs) | ||
7087 | { | ||
7088 | u32 nextTbtt, beaconintval, dtimperiod, beacontimeout; | ||
7089 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
7090 | |||
7091 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); | ||
7092 | |||
7093 | REG_WRITE(ah, AR_BEACON_PERIOD, | ||
7094 | TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); | ||
7095 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, | ||
7096 | TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); | ||
7097 | |||
7098 | REG_RMW_FIELD(ah, AR_RSSI_THR, | ||
7099 | AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); | ||
7100 | |||
7101 | beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD; | ||
7102 | |||
7103 | if (bs->bs_sleepduration > beaconintval) | ||
7104 | beaconintval = bs->bs_sleepduration; | ||
7105 | |||
7106 | dtimperiod = bs->bs_dtimperiod; | ||
7107 | if (bs->bs_sleepduration > dtimperiod) | ||
7108 | dtimperiod = bs->bs_sleepduration; | ||
7109 | |||
7110 | if (beaconintval == dtimperiod) | ||
7111 | nextTbtt = bs->bs_nextdtim; | ||
7112 | else | ||
7113 | nextTbtt = bs->bs_nexttbtt; | ||
7114 | |||
7115 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: next DTIM %d\n", __func__, | ||
7116 | bs->bs_nextdtim); | ||
7117 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: next beacon %d\n", __func__, | ||
7118 | nextTbtt); | ||
7119 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: beacon period %d\n", __func__, | ||
7120 | beaconintval); | ||
7121 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: DTIM period %d\n", __func__, | ||
7122 | dtimperiod); | ||
7123 | |||
7124 | REG_WRITE(ah, AR_NEXT_DTIM, | ||
7125 | TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); | ||
7126 | REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); | ||
7127 | |||
7128 | REG_WRITE(ah, AR_SLEEP1, | ||
7129 | SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) | ||
7130 | | AR_SLEEP1_ASSUME_DTIM); | ||
7131 | |||
7132 | if (pCap->halAutoSleepSupport) | ||
7133 | beacontimeout = (BEACON_TIMEOUT_VAL << 3); | ||
7134 | else | ||
7135 | beacontimeout = MIN_BEACON_TIMEOUT_VAL; | ||
7136 | |||
7137 | REG_WRITE(ah, AR_SLEEP2, | ||
7138 | SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); | ||
7139 | |||
7140 | REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); | ||
7141 | REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); | ||
7142 | |||
7143 | REG_SET_BIT(ah, AR_TIMER_MODE, | ||
7144 | AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | | ||
7145 | AR_DTIM_TIMER_EN); | ||
7146 | |||
7147 | } | ||
7148 | |||
7149 | bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry) | ||
7150 | { | ||
7151 | if (entry < ah->ah_caps.halKeyCacheSize) { | ||
7152 | u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry)); | ||
7153 | if (val & AR_KEYTABLE_VALID) | ||
7154 | return true; | ||
7155 | } | ||
7156 | return false; | ||
7157 | } | ||
7158 | |||
7159 | bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry) | ||
7160 | { | ||
7161 | u32 keyType; | ||
7162 | |||
7163 | if (entry >= ah->ah_caps.halKeyCacheSize) { | ||
7164 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7165 | "%s: entry %u out of range\n", __func__, entry); | ||
7166 | return false; | ||
7167 | } | ||
7168 | keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); | ||
7169 | |||
7170 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); | ||
7171 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); | ||
7172 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); | ||
7173 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); | ||
7174 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); | ||
7175 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); | ||
7176 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); | ||
7177 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); | ||
7178 | |||
7179 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
7180 | u16 micentry = entry + 64; | ||
7181 | |||
7182 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); | ||
7183 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
7184 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); | ||
7185 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
7186 | |||
7187 | } | ||
7188 | |||
7189 | if (ah->ah_curchan == NULL) | ||
7190 | return true; | ||
7191 | |||
7192 | return true; | ||
7193 | } | ||
7194 | |||
7195 | bool | ||
7196 | ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, | ||
7197 | const u8 *mac) | ||
7198 | { | ||
7199 | u32 macHi, macLo; | ||
7200 | |||
7201 | if (entry >= ah->ah_caps.halKeyCacheSize) { | ||
7202 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7203 | "%s: entry %u out of range\n", __func__, entry); | ||
7204 | return false; | ||
7205 | } | ||
7206 | |||
7207 | if (mac != NULL) { | ||
7208 | macHi = (mac[5] << 8) | mac[4]; | ||
7209 | macLo = (mac[3] << 24) | (mac[2] << 16) | ||
7210 | | (mac[1] << 8) | mac[0]; | ||
7211 | macLo >>= 1; | ||
7212 | macLo |= (macHi & 1) << 31; | ||
7213 | macHi >>= 1; | ||
7214 | } else { | ||
7215 | macLo = macHi = 0; | ||
7216 | } | ||
7217 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); | ||
7218 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); | ||
7219 | |||
7220 | return true; | ||
7221 | } | ||
7222 | |||
7223 | bool | ||
7224 | ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry, | ||
7225 | const struct ath9k_keyval *k, | ||
7226 | const u8 *mac, int xorKey) | ||
7227 | { | ||
7228 | const struct hal_capabilities *pCap = &ah->ah_caps; | ||
7229 | u32 key0, key1, key2, key3, key4; | ||
7230 | u32 keyType; | ||
7231 | u32 xorMask = xorKey ? | ||
7232 | (ATH9K_KEY_XOR << 24 | ATH9K_KEY_XOR << 16 | ATH9K_KEY_XOR << 8 | ||
7233 | | ATH9K_KEY_XOR) : 0; | ||
7234 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7235 | |||
7236 | if (entry >= pCap->halKeyCacheSize) { | ||
7237 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7238 | "%s: entry %u out of range\n", __func__, entry); | ||
7239 | return false; | ||
7240 | } | ||
7241 | switch (k->kv_type) { | ||
7242 | case ATH9K_CIPHER_AES_OCB: | ||
7243 | keyType = AR_KEYTABLE_TYPE_AES; | ||
7244 | break; | ||
7245 | case ATH9K_CIPHER_AES_CCM: | ||
7246 | if (!pCap->halCipherAesCcmSupport) { | ||
7247 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7248 | "%s: AES-CCM not supported by " | ||
7249 | "mac rev 0x%x\n", __func__, | ||
7250 | ah->ah_macRev); | ||
7251 | return false; | ||
7252 | } | ||
7253 | keyType = AR_KEYTABLE_TYPE_CCM; | ||
7254 | break; | ||
7255 | case ATH9K_CIPHER_TKIP: | ||
7256 | keyType = AR_KEYTABLE_TYPE_TKIP; | ||
7257 | if (ATH9K_IS_MIC_ENABLED(ah) | ||
7258 | && entry + 64 >= pCap->halKeyCacheSize) { | ||
7259 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7260 | "%s: entry %u inappropriate for TKIP\n", | ||
7261 | __func__, entry); | ||
7262 | return false; | ||
7263 | } | ||
7264 | break; | ||
7265 | case ATH9K_CIPHER_WEP: | ||
7266 | if (k->kv_len < 40 / NBBY) { | ||
7267 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7268 | "%s: WEP key length %u too small\n", | ||
7269 | __func__, k->kv_len); | ||
7270 | return false; | ||
7271 | } | ||
7272 | if (k->kv_len <= 40 / NBBY) | ||
7273 | keyType = AR_KEYTABLE_TYPE_40; | ||
7274 | else if (k->kv_len <= 104 / NBBY) | ||
7275 | keyType = AR_KEYTABLE_TYPE_104; | ||
7276 | else | ||
7277 | keyType = AR_KEYTABLE_TYPE_128; | ||
7278 | break; | ||
7279 | case ATH9K_CIPHER_CLR: | ||
7280 | keyType = AR_KEYTABLE_TYPE_CLR; | ||
7281 | break; | ||
7282 | default: | ||
7283 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7284 | "%s: cipher %u not supported\n", __func__, | ||
7285 | k->kv_type); | ||
7286 | return false; | ||
7287 | } | ||
7288 | |||
7289 | key0 = get_unaligned_le32(k->kv_val + 0) ^ xorMask; | ||
7290 | key1 = (get_unaligned_le16(k->kv_val + 4) ^ xorMask) & 0xffff; | ||
7291 | key2 = get_unaligned_le32(k->kv_val + 6) ^ xorMask; | ||
7292 | key3 = (get_unaligned_le16(k->kv_val + 10) ^ xorMask) & 0xffff; | ||
7293 | key4 = get_unaligned_le32(k->kv_val + 12) ^ xorMask; | ||
7294 | if (k->kv_len <= 104 / NBBY) | ||
7295 | key4 &= 0xff; | ||
7296 | |||
7297 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
7298 | u16 micentry = entry + 64; | ||
7299 | |||
7300 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); | ||
7301 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); | ||
7302 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
7303 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
7304 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
7305 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
7306 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
7307 | |||
7308 | if (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) { | ||
7309 | u32 mic0, mic1, mic2, mic3, mic4; | ||
7310 | |||
7311 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
7312 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
7313 | mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; | ||
7314 | mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; | ||
7315 | mic4 = get_unaligned_le32(k->kv_txmic + 4); | ||
7316 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
7317 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); | ||
7318 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
7319 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); | ||
7320 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); | ||
7321 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
7322 | AR_KEYTABLE_TYPE_CLR); | ||
7323 | |||
7324 | } else { | ||
7325 | u32 mic0, mic2; | ||
7326 | |||
7327 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
7328 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
7329 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
7330 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
7331 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
7332 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
7333 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); | ||
7334 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
7335 | AR_KEYTABLE_TYPE_CLR); | ||
7336 | } | ||
7337 | REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); | ||
7338 | REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); | ||
7339 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
7340 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
7341 | } else { | ||
7342 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
7343 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
7344 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
7345 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
7346 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
7347 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
7348 | |||
7349 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
7350 | } | ||
7351 | |||
7352 | if (ah->ah_curchan == NULL) | ||
7353 | return true; | ||
7354 | |||
7355 | return true; | ||
7356 | } | ||
7357 | |||
7358 | bool | ||
7359 | ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel) | ||
7360 | { | ||
7361 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7362 | u32 txcfg, curLevel, newLevel; | ||
7363 | enum ath9k_int omask; | ||
7364 | |||
7365 | if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD) | ||
7366 | return false; | ||
7367 | |||
7368 | omask = ath9k_hw_set_interrupts(ah, | ||
7369 | ahp->ah_maskReg & ~ATH9K_INT_GLOBAL); | ||
7370 | |||
7371 | txcfg = REG_READ(ah, AR_TXCFG); | ||
7372 | curLevel = MS(txcfg, AR_FTRIG); | ||
7373 | newLevel = curLevel; | ||
7374 | if (bIncTrigLevel) { | ||
7375 | if (curLevel < MAX_TX_FIFO_THRESHOLD) | ||
7376 | newLevel++; | ||
7377 | } else if (curLevel > MIN_TX_FIFO_THRESHOLD) | ||
7378 | newLevel--; | ||
7379 | if (newLevel != curLevel) | ||
7380 | REG_WRITE(ah, AR_TXCFG, | ||
7381 | (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); | ||
7382 | |||
7383 | ath9k_hw_set_interrupts(ah, omask); | ||
7384 | |||
7385 | ah->ah_txTrigLevel = newLevel; | ||
7386 | |||
7387 | return newLevel != curLevel; | ||
7388 | } | ||
7389 | |||
7390 | static bool ath9k_hw_set_txq_props(struct ath_hal *ah, | ||
7391 | struct ath9k_tx_queue_info *qi, | ||
7392 | const struct ath9k_txq_info *qInfo) | ||
7393 | { | ||
7394 | u32 cw; | ||
7395 | |||
7396 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
7397 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n", | ||
7398 | __func__); | ||
7399 | return false; | ||
7400 | } | ||
7401 | |||
7402 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %p\n", __func__, qi); | ||
7403 | |||
7404 | qi->tqi_ver = qInfo->tqi_ver; | ||
7405 | qi->tqi_subtype = qInfo->tqi_subtype; | ||
7406 | qi->tqi_qflags = qInfo->tqi_qflags; | ||
7407 | qi->tqi_priority = qInfo->tqi_priority; | ||
7408 | if (qInfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT) | ||
7409 | qi->tqi_aifs = min(qInfo->tqi_aifs, 255U); | ||
7410 | else | ||
7411 | qi->tqi_aifs = INIT_AIFS; | ||
7412 | if (qInfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) { | ||
7413 | cw = min(qInfo->tqi_cwmin, 1024U); | ||
7414 | qi->tqi_cwmin = 1; | ||
7415 | while (qi->tqi_cwmin < cw) | ||
7416 | qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; | ||
7417 | } else | ||
7418 | qi->tqi_cwmin = qInfo->tqi_cwmin; | ||
7419 | if (qInfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) { | ||
7420 | cw = min(qInfo->tqi_cwmax, 1024U); | ||
7421 | qi->tqi_cwmax = 1; | ||
7422 | while (qi->tqi_cwmax < cw) | ||
7423 | qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; | ||
7424 | } else | ||
7425 | qi->tqi_cwmax = INIT_CWMAX; | ||
7426 | |||
7427 | if (qInfo->tqi_shretry != 0) | ||
7428 | qi->tqi_shretry = min((u32) qInfo->tqi_shretry, 15U); | ||
7429 | else | ||
7430 | qi->tqi_shretry = INIT_SH_RETRY; | ||
7431 | if (qInfo->tqi_lgretry != 0) | ||
7432 | qi->tqi_lgretry = min((u32) qInfo->tqi_lgretry, 15U); | ||
7433 | else | ||
7434 | qi->tqi_lgretry = INIT_LG_RETRY; | ||
7435 | qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod; | ||
7436 | qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit; | ||
7437 | qi->tqi_burstTime = qInfo->tqi_burstTime; | ||
7438 | qi->tqi_readyTime = qInfo->tqi_readyTime; | ||
7439 | |||
7440 | switch (qInfo->tqi_subtype) { | ||
7441 | case ATH9K_WME_UPSD: | ||
7442 | if (qi->tqi_type == ATH9K_TX_QUEUE_DATA) | ||
7443 | qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS; | ||
7444 | break; | ||
7445 | default: | ||
7446 | break; | ||
7447 | } | ||
7448 | return true; | ||
7449 | } | ||
7450 | |||
7451 | bool ath9k_hw_settxqueueprops(struct ath_hal *ah, int q, | ||
7452 | const struct ath9k_txq_info *qInfo) | ||
7453 | { | ||
7454 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7455 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
7456 | |||
7457 | if (q >= pCap->halTotalQueues) { | ||
7458 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n", | ||
7459 | __func__, q); | ||
7460 | return false; | ||
7461 | } | ||
7462 | return ath9k_hw_set_txq_props(ah, &ahp->ah_txq[q], qInfo); | ||
7463 | } | ||
7464 | |||
7465 | static bool ath9k_hw_get_txq_props(struct ath_hal *ah, | ||
7466 | struct ath9k_txq_info *qInfo, | ||
7467 | const struct ath9k_tx_queue_info *qi) | ||
7468 | { | ||
7469 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
7470 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n", | ||
7471 | __func__); | ||
7472 | return false; | ||
7473 | } | ||
7474 | |||
7475 | qInfo->tqi_qflags = qi->tqi_qflags; | ||
7476 | qInfo->tqi_ver = qi->tqi_ver; | ||
7477 | qInfo->tqi_subtype = qi->tqi_subtype; | ||
7478 | qInfo->tqi_qflags = qi->tqi_qflags; | ||
7479 | qInfo->tqi_priority = qi->tqi_priority; | ||
7480 | qInfo->tqi_aifs = qi->tqi_aifs; | ||
7481 | qInfo->tqi_cwmin = qi->tqi_cwmin; | ||
7482 | qInfo->tqi_cwmax = qi->tqi_cwmax; | ||
7483 | qInfo->tqi_shretry = qi->tqi_shretry; | ||
7484 | qInfo->tqi_lgretry = qi->tqi_lgretry; | ||
7485 | qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; | ||
7486 | qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; | ||
7487 | qInfo->tqi_burstTime = qi->tqi_burstTime; | ||
7488 | qInfo->tqi_readyTime = qi->tqi_readyTime; | ||
7489 | |||
7490 | return true; | ||
7491 | } | ||
7492 | |||
7493 | bool | ||
7494 | ath9k_hw_gettxqueueprops(struct ath_hal *ah, int q, | ||
7495 | struct ath9k_txq_info *qInfo) | ||
7496 | { | ||
7497 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7498 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
7499 | |||
7500 | if (q >= pCap->halTotalQueues) { | ||
7501 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n", | ||
7502 | __func__, q); | ||
7503 | return false; | ||
7504 | } | ||
7505 | return ath9k_hw_get_txq_props(ah, qInfo, &ahp->ah_txq[q]); | ||
7506 | } | ||
7507 | |||
7508 | int | ||
7509 | ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type, | ||
7510 | const struct ath9k_txq_info *qInfo) | ||
7511 | { | ||
7512 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7513 | struct ath9k_tx_queue_info *qi; | ||
7514 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
7515 | int q; | ||
7516 | |||
7517 | switch (type) { | ||
7518 | case ATH9K_TX_QUEUE_BEACON: | ||
7519 | q = pCap->halTotalQueues - 1; | ||
7520 | break; | ||
7521 | case ATH9K_TX_QUEUE_CAB: | ||
7522 | q = pCap->halTotalQueues - 2; | ||
7523 | break; | ||
7524 | case ATH9K_TX_QUEUE_PSPOLL: | ||
7525 | q = 1; | ||
7526 | break; | ||
7527 | case ATH9K_TX_QUEUE_UAPSD: | ||
7528 | q = pCap->halTotalQueues - 3; | ||
7529 | break; | ||
7530 | case ATH9K_TX_QUEUE_DATA: | ||
7531 | for (q = 0; q < pCap->halTotalQueues; q++) | ||
7532 | if (ahp->ah_txq[q].tqi_type == | ||
7533 | ATH9K_TX_QUEUE_INACTIVE) | ||
7534 | break; | ||
7535 | if (q == pCap->halTotalQueues) { | ||
7536 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
7537 | "%s: no available tx queue\n", __func__); | ||
7538 | return -1; | ||
7539 | } | ||
7540 | break; | ||
7541 | default: | ||
7542 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: bad tx queue type %u\n", | ||
7543 | __func__, type); | ||
7544 | return -1; | ||
7545 | } | ||
7546 | |||
7547 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q); | ||
7548 | |||
7549 | qi = &ahp->ah_txq[q]; | ||
7550 | if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { | ||
7551 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
7552 | "%s: tx queue %u already active\n", __func__, q); | ||
7553 | return -1; | ||
7554 | } | ||
7555 | memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); | ||
7556 | qi->tqi_type = type; | ||
7557 | if (qInfo == NULL) { | ||
7558 | qi->tqi_qflags = | ||
7559 | TXQ_FLAG_TXOKINT_ENABLE | ||
7560 | | TXQ_FLAG_TXERRINT_ENABLE | ||
7561 | | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE; | ||
7562 | qi->tqi_aifs = INIT_AIFS; | ||
7563 | qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT; | ||
7564 | qi->tqi_cwmax = INIT_CWMAX; | ||
7565 | qi->tqi_shretry = INIT_SH_RETRY; | ||
7566 | qi->tqi_lgretry = INIT_LG_RETRY; | ||
7567 | qi->tqi_physCompBuf = 0; | ||
7568 | } else { | ||
7569 | qi->tqi_physCompBuf = qInfo->tqi_compBuf; | ||
7570 | (void) ath9k_hw_settxqueueprops(ah, q, qInfo); | ||
7571 | } | ||
7572 | |||
7573 | return q; | ||
7574 | } | ||
7575 | |||
7576 | static void | ||
7577 | ath9k_hw_set_txq_interrupts(struct ath_hal *ah, | ||
7578 | struct ath9k_tx_queue_info *qi) | ||
7579 | { | ||
7580 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7581 | |||
7582 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | ||
7583 | "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", | ||
7584 | __func__, ahp->ah_txOkInterruptMask, | ||
7585 | ahp->ah_txErrInterruptMask, ahp->ah_txDescInterruptMask, | ||
7586 | ahp->ah_txEolInterruptMask, ahp->ah_txUrnInterruptMask); | ||
7587 | |||
7588 | REG_WRITE(ah, AR_IMR_S0, | ||
7589 | SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) | ||
7590 | | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC)); | ||
7591 | REG_WRITE(ah, AR_IMR_S1, | ||
7592 | SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR) | ||
7593 | | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL)); | ||
7594 | REG_RMW_FIELD(ah, AR_IMR_S2, | ||
7595 | AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask); | ||
7596 | } | ||
7597 | |||
7598 | bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q) | ||
7599 | { | ||
7600 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7601 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
7602 | struct ath9k_tx_queue_info *qi; | ||
7603 | |||
7604 | if (q >= pCap->halTotalQueues) { | ||
7605 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n", | ||
7606 | __func__, q); | ||
7607 | return false; | ||
7608 | } | ||
7609 | qi = &ahp->ah_txq[q]; | ||
7610 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
7611 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n", | ||
7612 | __func__, q); | ||
7613 | return false; | ||
7614 | } | ||
7615 | |||
7616 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: release queue %u\n", | ||
7617 | __func__, q); | ||
7618 | |||
7619 | qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; | ||
7620 | ahp->ah_txOkInterruptMask &= ~(1 << q); | ||
7621 | ahp->ah_txErrInterruptMask &= ~(1 << q); | ||
7622 | ahp->ah_txDescInterruptMask &= ~(1 << q); | ||
7623 | ahp->ah_txEolInterruptMask &= ~(1 << q); | ||
7624 | ahp->ah_txUrnInterruptMask &= ~(1 << q); | ||
7625 | ath9k_hw_set_txq_interrupts(ah, qi); | ||
7626 | |||
7627 | return true; | ||
7628 | } | ||
7629 | |||
7630 | bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q) | ||
7631 | { | ||
7632 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7633 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
7634 | struct ath9k_channel *chan = ah->ah_curchan; | ||
7635 | struct ath9k_tx_queue_info *qi; | ||
7636 | u32 cwMin, chanCwMin, value; | ||
7637 | |||
7638 | if (q >= pCap->halTotalQueues) { | ||
7639 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n", | ||
7640 | __func__, q); | ||
7641 | return false; | ||
7642 | } | ||
7643 | qi = &ahp->ah_txq[q]; | ||
7644 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
7645 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n", | ||
7646 | __func__, q); | ||
7647 | return true; | ||
7648 | } | ||
7649 | |||
7650 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: reset queue %u\n", __func__, q); | ||
7651 | |||
7652 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { | ||
7653 | if (chan && IS_CHAN_B(chan)) | ||
7654 | chanCwMin = INIT_CWMIN_11B; | ||
7655 | else | ||
7656 | chanCwMin = INIT_CWMIN; | ||
7657 | |||
7658 | for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); | ||
7659 | } else | ||
7660 | cwMin = qi->tqi_cwmin; | ||
7661 | |||
7662 | REG_WRITE(ah, AR_DLCL_IFS(q), SM(cwMin, AR_D_LCL_IFS_CWMIN) | ||
7663 | | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | ||
7664 | | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); | ||
7665 | |||
7666 | REG_WRITE(ah, AR_DRETRY_LIMIT(q), | ||
7667 | SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) | ||
7668 | | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) | ||
7669 | | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) | ||
7670 | ); | ||
7671 | |||
7672 | REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); | ||
7673 | REG_WRITE(ah, AR_DMISC(q), | ||
7674 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); | ||
7675 | |||
7676 | if (qi->tqi_cbrPeriod) { | ||
7677 | REG_WRITE(ah, AR_QCBRCFG(q), | ||
7678 | SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | ||
7679 | | SM(qi->tqi_cbrOverflowLimit, | ||
7680 | AR_Q_CBRCFG_OVF_THRESH)); | ||
7681 | REG_WRITE(ah, AR_QMISC(q), | ||
7682 | REG_READ(ah, | ||
7683 | AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | (qi-> | ||
7684 | tqi_cbrOverflowLimit | ||
7685 | ? | ||
7686 | AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN | ||
7687 | : | ||
7688 | 0)); | ||
7689 | } | ||
7690 | if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { | ||
7691 | REG_WRITE(ah, AR_QRDYTIMECFG(q), | ||
7692 | SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) | | ||
7693 | AR_Q_RDYTIMECFG_EN); | ||
7694 | } | ||
7695 | |||
7696 | REG_WRITE(ah, AR_DCHNTIME(q), | ||
7697 | SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | | ||
7698 | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); | ||
7699 | |||
7700 | if (qi->tqi_burstTime | ||
7701 | && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) { | ||
7702 | REG_WRITE(ah, AR_QMISC(q), | ||
7703 | REG_READ(ah, | ||
7704 | AR_QMISC(q)) | | ||
7705 | AR_Q_MISC_RDYTIME_EXP_POLICY); | ||
7706 | |||
7707 | } | ||
7708 | |||
7709 | if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) { | ||
7710 | REG_WRITE(ah, AR_DMISC(q), | ||
7711 | REG_READ(ah, AR_DMISC(q)) | | ||
7712 | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
7713 | } | ||
7714 | if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { | ||
7715 | REG_WRITE(ah, AR_DMISC(q), | ||
7716 | REG_READ(ah, AR_DMISC(q)) | | ||
7717 | AR_D_MISC_FRAG_BKOFF_EN); | ||
7718 | } | ||
7719 | switch (qi->tqi_type) { | ||
7720 | case ATH9K_TX_QUEUE_BEACON: | ||
7721 | REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) | ||
7722 | | AR_Q_MISC_FSP_DBA_GATED | ||
7723 | | AR_Q_MISC_BEACON_USE | ||
7724 | | AR_Q_MISC_CBR_INCR_DIS1); | ||
7725 | |||
7726 | REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | ||
7727 | | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << | ||
7728 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S) | ||
7729 | | AR_D_MISC_BEACON_USE | ||
7730 | | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
7731 | break; | ||
7732 | case ATH9K_TX_QUEUE_CAB: | ||
7733 | REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) | ||
7734 | | AR_Q_MISC_FSP_DBA_GATED | ||
7735 | | AR_Q_MISC_CBR_INCR_DIS1 | ||
7736 | | AR_Q_MISC_CBR_INCR_DIS0); | ||
7737 | value = (qi->tqi_readyTime | ||
7738 | - (ah->ah_config.ath_hal_sw_beacon_response_time - | ||
7739 | ah->ah_config.ath_hal_dma_beacon_response_time) | ||
7740 | - | ||
7741 | ah->ah_config.ath_hal_additional_swba_backoff) * | ||
7742 | 1024; | ||
7743 | REG_WRITE(ah, AR_QRDYTIMECFG(q), | ||
7744 | value | AR_Q_RDYTIMECFG_EN); | ||
7745 | REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | ||
7746 | | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << | ||
7747 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); | ||
7748 | break; | ||
7749 | case ATH9K_TX_QUEUE_PSPOLL: | ||
7750 | REG_WRITE(ah, AR_QMISC(q), | ||
7751 | REG_READ(ah, | ||
7752 | AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); | ||
7753 | break; | ||
7754 | case ATH9K_TX_QUEUE_UAPSD: | ||
7755 | REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | ||
7756 | | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
7757 | break; | ||
7758 | default: | ||
7759 | break; | ||
7760 | } | ||
7761 | |||
7762 | if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { | ||
7763 | REG_WRITE(ah, AR_DMISC(q), | ||
7764 | REG_READ(ah, AR_DMISC(q)) | | ||
7765 | SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, | ||
7766 | AR_D_MISC_ARB_LOCKOUT_CNTRL) | | ||
7767 | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
7768 | } | ||
7769 | |||
7770 | if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE) | ||
7771 | ahp->ah_txOkInterruptMask |= 1 << q; | ||
7772 | else | ||
7773 | ahp->ah_txOkInterruptMask &= ~(1 << q); | ||
7774 | if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE) | ||
7775 | ahp->ah_txErrInterruptMask |= 1 << q; | ||
7776 | else | ||
7777 | ahp->ah_txErrInterruptMask &= ~(1 << q); | ||
7778 | if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE) | ||
7779 | ahp->ah_txDescInterruptMask |= 1 << q; | ||
7780 | else | ||
7781 | ahp->ah_txDescInterruptMask &= ~(1 << q); | ||
7782 | if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE) | ||
7783 | ahp->ah_txEolInterruptMask |= 1 << q; | ||
7784 | else | ||
7785 | ahp->ah_txEolInterruptMask &= ~(1 << q); | ||
7786 | if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE) | ||
7787 | ahp->ah_txUrnInterruptMask |= 1 << q; | ||
7788 | else | ||
7789 | ahp->ah_txUrnInterruptMask &= ~(1 << q); | ||
7790 | ath9k_hw_set_txq_interrupts(ah, qi); | ||
7791 | |||
7792 | return true; | ||
7793 | } | ||
7794 | |||
7795 | void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs) | ||
7796 | { | ||
7797 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7798 | *txqs &= ahp->ah_intrTxqs; | ||
7799 | ahp->ah_intrTxqs &= ~(*txqs); | ||
7800 | } | ||
7801 | |||
7802 | bool | ||
7803 | ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
7804 | u32 segLen, bool firstSeg, | ||
7805 | bool lastSeg, const struct ath_desc *ds0) | ||
7806 | { | ||
7807 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7808 | |||
7809 | if (firstSeg) { | ||
7810 | ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); | ||
7811 | } else if (lastSeg) { | ||
7812 | ads->ds_ctl0 = 0; | ||
7813 | ads->ds_ctl1 = segLen; | ||
7814 | ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; | ||
7815 | ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; | ||
7816 | } else { | ||
7817 | ads->ds_ctl0 = 0; | ||
7818 | ads->ds_ctl1 = segLen | AR_TxMore; | ||
7819 | ads->ds_ctl2 = 0; | ||
7820 | ads->ds_ctl3 = 0; | ||
7821 | } | ||
7822 | ads->ds_txstatus0 = ads->ds_txstatus1 = 0; | ||
7823 | ads->ds_txstatus2 = ads->ds_txstatus3 = 0; | ||
7824 | ads->ds_txstatus4 = ads->ds_txstatus5 = 0; | ||
7825 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | ||
7826 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | ||
7827 | return true; | ||
7828 | } | ||
7829 | |||
7830 | void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds) | ||
7831 | { | ||
7832 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7833 | |||
7834 | ads->ds_txstatus0 = ads->ds_txstatus1 = 0; | ||
7835 | ads->ds_txstatus2 = ads->ds_txstatus3 = 0; | ||
7836 | ads->ds_txstatus4 = ads->ds_txstatus5 = 0; | ||
7837 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | ||
7838 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | ||
7839 | } | ||
7840 | |||
7841 | int | ||
7842 | ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds) | ||
7843 | { | ||
7844 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7845 | |||
7846 | if ((ads->ds_txstatus9 & AR_TxDone) == 0) | ||
7847 | return -EINPROGRESS; | ||
7848 | |||
7849 | ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); | ||
7850 | ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp; | ||
7851 | ds->ds_txstat.ts_status = 0; | ||
7852 | ds->ds_txstat.ts_flags = 0; | ||
7853 | |||
7854 | if (ads->ds_txstatus1 & AR_ExcessiveRetries) | ||
7855 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; | ||
7856 | if (ads->ds_txstatus1 & AR_Filtered) | ||
7857 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; | ||
7858 | if (ads->ds_txstatus1 & AR_FIFOUnderrun) | ||
7859 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; | ||
7860 | if (ads->ds_txstatus9 & AR_TxOpExceeded) | ||
7861 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; | ||
7862 | if (ads->ds_txstatus1 & AR_TxTimerExpired) | ||
7863 | ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED; | ||
7864 | |||
7865 | if (ads->ds_txstatus1 & AR_DescCfgErr) | ||
7866 | ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR; | ||
7867 | if (ads->ds_txstatus1 & AR_TxDataUnderrun) { | ||
7868 | ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN; | ||
7869 | ath9k_hw_updatetxtriglevel(ah, true); | ||
7870 | } | ||
7871 | if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { | ||
7872 | ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN; | ||
7873 | ath9k_hw_updatetxtriglevel(ah, true); | ||
7874 | } | ||
7875 | if (ads->ds_txstatus0 & AR_TxBaStatus) { | ||
7876 | ds->ds_txstat.ts_flags |= ATH9K_TX_BA; | ||
7877 | ds->ds_txstat.ba_low = ads->AR_BaBitmapLow; | ||
7878 | ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh; | ||
7879 | } | ||
7880 | |||
7881 | ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); | ||
7882 | switch (ds->ds_txstat.ts_rateindex) { | ||
7883 | case 0: | ||
7884 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); | ||
7885 | break; | ||
7886 | case 1: | ||
7887 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); | ||
7888 | break; | ||
7889 | case 2: | ||
7890 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); | ||
7891 | break; | ||
7892 | case 3: | ||
7893 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); | ||
7894 | break; | ||
7895 | } | ||
7896 | |||
7897 | ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); | ||
7898 | ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); | ||
7899 | ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); | ||
7900 | ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); | ||
7901 | ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); | ||
7902 | ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); | ||
7903 | ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); | ||
7904 | ds->ds_txstat.evm0 = ads->AR_TxEVM0; | ||
7905 | ds->ds_txstat.evm1 = ads->AR_TxEVM1; | ||
7906 | ds->ds_txstat.evm2 = ads->AR_TxEVM2; | ||
7907 | ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); | ||
7908 | ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); | ||
7909 | ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); | ||
7910 | ds->ds_txstat.ts_antenna = 1; | ||
7911 | |||
7912 | return 0; | ||
7913 | } | ||
7914 | |||
7915 | void | ||
7916 | ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
7917 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, | ||
7918 | u32 keyIx, enum ath9k_key_type keyType, u32 flags) | ||
7919 | { | ||
7920 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7921 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7922 | |||
7923 | txPower += ahp->ah_txPowerIndexOffset; | ||
7924 | if (txPower > 63) | ||
7925 | txPower = 63; | ||
7926 | |||
7927 | ads->ds_ctl0 = (pktLen & AR_FrameLen) | ||
7928 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | ||
7929 | | SM(txPower, AR_XmitPower) | ||
7930 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | ||
7931 | | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | ||
7932 | | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) | ||
7933 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); | ||
7934 | |||
7935 | ads->ds_ctl1 = | ||
7936 | (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) | ||
7937 | | SM(type, AR_FrameType) | ||
7938 | | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) | ||
7939 | | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) | ||
7940 | | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); | ||
7941 | |||
7942 | ads->ds_ctl6 = SM(keyType, AR_EncrType); | ||
7943 | |||
7944 | if (AR_SREV_9285(ah)) { | ||
7945 | |||
7946 | ads->ds_ctl8 = 0; | ||
7947 | ads->ds_ctl9 = 0; | ||
7948 | ads->ds_ctl10 = 0; | ||
7949 | ads->ds_ctl11 = 0; | ||
7950 | } | ||
7951 | } | ||
7952 | |||
7953 | void | ||
7954 | ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds, | ||
7955 | struct ath_desc *lastds, | ||
7956 | u32 durUpdateEn, u32 rtsctsRate, | ||
7957 | u32 rtsctsDuration, | ||
7958 | struct ath9k_11n_rate_series series[], | ||
7959 | u32 nseries, u32 flags) | ||
7960 | { | ||
7961 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7962 | struct ar5416_desc *last_ads = AR5416DESC(lastds); | ||
7963 | u32 ds_ctl0; | ||
7964 | |||
7965 | (void) nseries; | ||
7966 | (void) rtsctsDuration; | ||
7967 | |||
7968 | if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { | ||
7969 | ds_ctl0 = ads->ds_ctl0; | ||
7970 | |||
7971 | if (flags & ATH9K_TXDESC_RTSENA) { | ||
7972 | ds_ctl0 &= ~AR_CTSEnable; | ||
7973 | ds_ctl0 |= AR_RTSEnable; | ||
7974 | } else { | ||
7975 | ds_ctl0 &= ~AR_RTSEnable; | ||
7976 | ds_ctl0 |= AR_CTSEnable; | ||
7977 | } | ||
7978 | |||
7979 | ads->ds_ctl0 = ds_ctl0; | ||
7980 | } else { | ||
7981 | ads->ds_ctl0 = | ||
7982 | (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); | ||
7983 | } | ||
7984 | |||
7985 | ads->ds_ctl2 = set11nTries(series, 0) | ||
7986 | | set11nTries(series, 1) | ||
7987 | | set11nTries(series, 2) | ||
7988 | | set11nTries(series, 3) | ||
7989 | | (durUpdateEn ? AR_DurUpdateEna : 0) | ||
7990 | | SM(0, AR_BurstDur); | ||
7991 | |||
7992 | ads->ds_ctl3 = set11nRate(series, 0) | ||
7993 | | set11nRate(series, 1) | ||
7994 | | set11nRate(series, 2) | ||
7995 | | set11nRate(series, 3); | ||
7996 | |||
7997 | ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) | ||
7998 | | set11nPktDurRTSCTS(series, 1); | ||
7999 | |||
8000 | ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) | ||
8001 | | set11nPktDurRTSCTS(series, 3); | ||
8002 | |||
8003 | ads->ds_ctl7 = set11nRateFlags(series, 0) | ||
8004 | | set11nRateFlags(series, 1) | ||
8005 | | set11nRateFlags(series, 2) | ||
8006 | | set11nRateFlags(series, 3) | ||
8007 | | SM(rtsctsRate, AR_RTSCTSRate); | ||
8008 | last_ads->ds_ctl2 = ads->ds_ctl2; | ||
8009 | last_ads->ds_ctl3 = ads->ds_ctl3; | ||
8010 | } | ||
8011 | |||
8012 | void | ||
8013 | ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds, | ||
8014 | u32 aggrLen) | ||
8015 | { | ||
8016 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8017 | |||
8018 | ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); | ||
8019 | |||
8020 | ads->ds_ctl6 &= ~AR_AggrLen; | ||
8021 | ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); | ||
8022 | } | ||
8023 | |||
8024 | void | ||
8025 | ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds, | ||
8026 | u32 numDelims) | ||
8027 | { | ||
8028 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8029 | unsigned int ctl6; | ||
8030 | |||
8031 | ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); | ||
8032 | |||
8033 | ctl6 = ads->ds_ctl6; | ||
8034 | ctl6 &= ~AR_PadDelim; | ||
8035 | ctl6 |= SM(numDelims, AR_PadDelim); | ||
8036 | ads->ds_ctl6 = ctl6; | ||
8037 | } | ||
8038 | |||
8039 | void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds) | ||
8040 | { | ||
8041 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8042 | |||
8043 | ads->ds_ctl1 |= AR_IsAggr; | ||
8044 | ads->ds_ctl1 &= ~AR_MoreAggr; | ||
8045 | ads->ds_ctl6 &= ~AR_PadDelim; | ||
8046 | } | ||
8047 | |||
8048 | void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds) | ||
8049 | { | ||
8050 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8051 | |||
8052 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); | ||
8053 | } | ||
8054 | |||
8055 | void | ||
8056 | ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds, | ||
8057 | u32 burstDuration) | ||
8058 | { | ||
8059 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8060 | |||
8061 | ads->ds_ctl2 &= ~AR_BurstDur; | ||
8062 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); | ||
8063 | } | ||
8064 | |||
8065 | void | ||
8066 | ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds, | ||
8067 | u32 vmf) | ||
8068 | { | ||
8069 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8070 | |||
8071 | if (vmf) | ||
8072 | ads->ds_ctl0 |= AR_VirtMoreFrag; | ||
8073 | else | ||
8074 | ads->ds_ctl0 &= ~AR_VirtMoreFrag; | ||
8075 | } | ||
8076 | |||
8077 | void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp) | ||
8078 | { | ||
8079 | REG_WRITE(ah, AR_RXDP, rxdp); | ||
8080 | } | ||
8081 | |||
8082 | void ath9k_hw_rxena(struct ath_hal *ah) | ||
8083 | { | ||
8084 | REG_WRITE(ah, AR_CR, AR_CR_RXE); | ||
8085 | } | ||
8086 | |||
8087 | bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set) | ||
8088 | { | ||
8089 | if (set) { | ||
8090 | |||
8091 | REG_SET_BIT(ah, AR_DIAG_SW, | ||
8092 | (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | ||
8093 | |||
8094 | if (!ath9k_hw_wait | ||
8095 | (ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0)) { | ||
8096 | u32 reg; | ||
8097 | |||
8098 | REG_CLR_BIT(ah, AR_DIAG_SW, | ||
8099 | (AR_DIAG_RX_DIS | | ||
8100 | AR_DIAG_RX_ABORT)); | ||
8101 | |||
8102 | reg = REG_READ(ah, AR_OBS_BUS_1); | ||
8103 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
8104 | "%s: rx failed to go idle in 10 ms RXSM=0x%x\n", | ||
8105 | __func__, reg); | ||
8106 | |||
8107 | return false; | ||
8108 | } | ||
8109 | } else { | ||
8110 | REG_CLR_BIT(ah, AR_DIAG_SW, | ||
8111 | (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | ||
8112 | } | ||
8113 | |||
8114 | return true; | ||
8115 | } | ||
8116 | |||
8117 | void | ||
8118 | ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, | ||
8119 | u32 filter1) | ||
8120 | { | ||
8121 | REG_WRITE(ah, AR_MCAST_FIL0, filter0); | ||
8122 | REG_WRITE(ah, AR_MCAST_FIL1, filter1); | ||
8123 | } | ||
8124 | |||
8125 | bool | ||
8126 | ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
8127 | u32 size, u32 flags) | ||
8128 | { | ||
8129 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8130 | struct hal_capabilities *pCap = &ah->ah_caps; | ||
8131 | |||
8132 | ads->ds_ctl1 = size & AR_BufLen; | ||
8133 | if (flags & ATH9K_RXDESC_INTREQ) | ||
8134 | ads->ds_ctl1 |= AR_RxIntrReq; | ||
8135 | |||
8136 | ads->ds_rxstatus8 &= ~AR_RxDone; | ||
8137 | if (!pCap->halAutoSleepSupport) | ||
8138 | memset(&(ads->u), 0, sizeof(ads->u)); | ||
8139 | return true; | ||
8140 | } | ||
8141 | |||
8142 | int | ||
8143 | ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
8144 | u32 pa, struct ath_desc *nds, u64 tsf) | ||
8145 | { | ||
8146 | struct ar5416_desc ads; | ||
8147 | struct ar5416_desc *adsp = AR5416DESC(ds); | ||
8148 | |||
8149 | if ((adsp->ds_rxstatus8 & AR_RxDone) == 0) | ||
8150 | return -EINPROGRESS; | ||
8151 | |||
8152 | ads.u.rx = adsp->u.rx; | ||
8153 | |||
8154 | ds->ds_rxstat.rs_status = 0; | ||
8155 | ds->ds_rxstat.rs_flags = 0; | ||
8156 | |||
8157 | ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; | ||
8158 | ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; | ||
8159 | |||
8160 | ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); | ||
8161 | ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00); | ||
8162 | ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01); | ||
8163 | ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02); | ||
8164 | ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10); | ||
8165 | ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11); | ||
8166 | ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12); | ||
8167 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) | ||
8168 | ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); | ||
8169 | else | ||
8170 | ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID; | ||
8171 | |||
8172 | ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads)); | ||
8173 | ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; | ||
8174 | |||
8175 | ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; | ||
8176 | ds->ds_rxstat.rs_moreaggr = | ||
8177 | (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; | ||
8178 | ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); | ||
8179 | ds->ds_rxstat.rs_flags = | ||
8180 | (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; | ||
8181 | ds->ds_rxstat.rs_flags |= | ||
8182 | (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; | ||
8183 | |||
8184 | if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) | ||
8185 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE; | ||
8186 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) | ||
8187 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST; | ||
8188 | if (ads.ds_rxstatus8 & AR_DecryptBusyErr) | ||
8189 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY; | ||
8190 | |||
8191 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { | ||
8192 | |||
8193 | if (ads.ds_rxstatus8 & AR_CRCErr) | ||
8194 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC; | ||
8195 | else if (ads.ds_rxstatus8 & AR_PHYErr) { | ||
8196 | u32 phyerr; | ||
8197 | |||
8198 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY; | ||
8199 | phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); | ||
8200 | ds->ds_rxstat.rs_phyerr = phyerr; | ||
8201 | } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) | ||
8202 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT; | ||
8203 | else if (ads.ds_rxstatus8 & AR_MichaelErr) | ||
8204 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC; | ||
8205 | } | ||
8206 | |||
8207 | return 0; | ||
8208 | } | ||
8209 | |||
8210 | static void ath9k_hw_setup_rate_table(struct ath_hal *ah, | ||
8211 | struct ath9k_rate_table *rt) | ||
8212 | { | ||
8213 | int i; | ||
8214 | |||
8215 | if (rt->rateCodeToIndex[0] != 0) | ||
8216 | return; | ||
8217 | for (i = 0; i < 256; i++) | ||
8218 | rt->rateCodeToIndex[i] = (u8) -1; | ||
8219 | for (i = 0; i < rt->rateCount; i++) { | ||
8220 | u8 code = rt->info[i].rateCode; | ||
8221 | u8 cix = rt->info[i].controlRate; | ||
8222 | |||
8223 | rt->rateCodeToIndex[code] = i; | ||
8224 | rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i; | ||
8225 | |||
8226 | rt->info[i].lpAckDuration = | ||
8227 | ath9k_hw_computetxtime(ah, rt, | ||
8228 | WLAN_CTRL_FRAME_SIZE, | ||
8229 | cix, | ||
8230 | false); | ||
8231 | rt->info[i].spAckDuration = | ||
8232 | ath9k_hw_computetxtime(ah, rt, | ||
8233 | WLAN_CTRL_FRAME_SIZE, | ||
8234 | cix, | ||
8235 | true); | ||
8236 | } | ||
8237 | } | ||
8238 | |||
8239 | const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah, | ||
8240 | u32 mode) | ||
8241 | { | ||
8242 | struct ath9k_rate_table *rt; | ||
8243 | switch (mode) { | ||
8244 | case ATH9K_MODE_SEL_11A: | ||
8245 | rt = &ar5416_11a_table; | ||
8246 | break; | ||
8247 | case ATH9K_MODE_SEL_11B: | ||
8248 | rt = &ar5416_11b_table; | ||
8249 | break; | ||
8250 | case ATH9K_MODE_SEL_11G: | ||
8251 | rt = &ar5416_11g_table; | ||
8252 | break; | ||
8253 | case ATH9K_MODE_SEL_11NG_HT20: | ||
8254 | case ATH9K_MODE_SEL_11NG_HT40PLUS: | ||
8255 | case ATH9K_MODE_SEL_11NG_HT40MINUS: | ||
8256 | rt = &ar5416_11ng_table; | ||
8257 | break; | ||
8258 | case ATH9K_MODE_SEL_11NA_HT20: | ||
8259 | case ATH9K_MODE_SEL_11NA_HT40PLUS: | ||
8260 | case ATH9K_MODE_SEL_11NA_HT40MINUS: | ||
8261 | rt = &ar5416_11na_table; | ||
8262 | break; | ||
8263 | default: | ||
8264 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "%s: invalid mode 0x%x\n", | ||
8265 | __func__, mode); | ||
8266 | return NULL; | ||
8267 | } | ||
8268 | ath9k_hw_setup_rate_table(ah, rt); | ||
8269 | return rt; | ||
8270 | } | ||
8271 | |||
8272 | static const char *ath9k_hw_devname(u16 devid) | ||
8273 | { | ||
8274 | switch (devid) { | ||
8275 | case AR5416_DEVID_PCI: | ||
8276 | case AR5416_DEVID_PCIE: | ||
8277 | return "Atheros 5416"; | ||
8278 | case AR9160_DEVID_PCI: | ||
8279 | return "Atheros 9160"; | ||
8280 | case AR9280_DEVID_PCI: | ||
8281 | case AR9280_DEVID_PCIE: | ||
8282 | return "Atheros 9280"; | ||
8283 | } | ||
8284 | return NULL; | ||
8285 | } | ||
8286 | |||
8287 | const char *ath9k_hw_probe(u16 vendorid, u16 devid) | ||
8288 | { | ||
8289 | return vendorid == ATHEROS_VENDOR_ID ? | ||
8290 | ath9k_hw_devname(devid) : NULL; | ||
8291 | } | ||
8292 | |||
8293 | struct ath_hal *ath9k_hw_attach(u16 devid, | ||
8294 | struct ath_softc *sc, | ||
8295 | void __iomem *mem, | ||
8296 | int *error) | ||
8297 | { | ||
8298 | struct ath_hal *ah = NULL; | ||
8299 | |||
8300 | switch (devid) { | ||
8301 | case AR5416_DEVID_PCI: | ||
8302 | case AR5416_DEVID_PCIE: | ||
8303 | case AR9160_DEVID_PCI: | ||
8304 | case AR9280_DEVID_PCI: | ||
8305 | case AR9280_DEVID_PCIE: | ||
8306 | ah = ath9k_hw_do_attach(devid, sc, mem, error); | ||
8307 | break; | ||
8308 | default: | ||
8309 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
8310 | "devid=0x%x not supported.\n", devid); | ||
8311 | ah = NULL; | ||
8312 | *error = -ENXIO; | ||
8313 | break; | ||
8314 | } | ||
8315 | if (ah != NULL) { | ||
8316 | ah->ah_devid = ah->ah_devid; | ||
8317 | ah->ah_subvendorid = ah->ah_subvendorid; | ||
8318 | ah->ah_macVersion = ah->ah_macVersion; | ||
8319 | ah->ah_macRev = ah->ah_macRev; | ||
8320 | ah->ah_phyRev = ah->ah_phyRev; | ||
8321 | ah->ah_analog5GhzRev = ah->ah_analog5GhzRev; | ||
8322 | ah->ah_analog2GhzRev = ah->ah_analog2GhzRev; | ||
8323 | } | ||
8324 | return ah; | ||
8325 | } | ||
8326 | |||
8327 | u16 | ||
8328 | ath9k_hw_computetxtime(struct ath_hal *ah, | ||
8329 | const struct ath9k_rate_table *rates, | ||
8330 | u32 frameLen, u16 rateix, | ||
8331 | bool shortPreamble) | ||
8332 | { | ||
8333 | u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; | ||
8334 | u32 kbps; | ||
8335 | |||
8336 | kbps = rates->info[rateix].rateKbps; | ||
8337 | |||
8338 | if (kbps == 0) | ||
8339 | return 0; | ||
8340 | switch (rates->info[rateix].phy) { | ||
8341 | |||
8342 | case PHY_CCK: | ||
8343 | phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; | ||
8344 | if (shortPreamble && rates->info[rateix].shortPreamble) | ||
8345 | phyTime >>= 1; | ||
8346 | numBits = frameLen << 3; | ||
8347 | txTime = CCK_SIFS_TIME + phyTime | ||
8348 | + ((numBits * 1000) / kbps); | ||
8349 | break; | ||
8350 | case PHY_OFDM: | ||
8351 | if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) { | ||
8352 | bitsPerSymbol = | ||
8353 | (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; | ||
8354 | |||
8355 | numBits = OFDM_PLCP_BITS + (frameLen << 3); | ||
8356 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); | ||
8357 | txTime = OFDM_SIFS_TIME_QUARTER | ||
8358 | + OFDM_PREAMBLE_TIME_QUARTER | ||
8359 | + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); | ||
8360 | } else if (ah->ah_curchan && | ||
8361 | IS_CHAN_HALF_RATE(ah->ah_curchan)) { | ||
8362 | bitsPerSymbol = | ||
8363 | (kbps * OFDM_SYMBOL_TIME_HALF) / 1000; | ||
8364 | |||
8365 | numBits = OFDM_PLCP_BITS + (frameLen << 3); | ||
8366 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); | ||
8367 | txTime = OFDM_SIFS_TIME_HALF + | ||
8368 | OFDM_PREAMBLE_TIME_HALF | ||
8369 | + (numSymbols * OFDM_SYMBOL_TIME_HALF); | ||
8370 | } else { | ||
8371 | bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; | ||
8372 | |||
8373 | numBits = OFDM_PLCP_BITS + (frameLen << 3); | ||
8374 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); | ||
8375 | txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME | ||
8376 | + (numSymbols * OFDM_SYMBOL_TIME); | ||
8377 | } | ||
8378 | break; | ||
8379 | |||
8380 | default: | ||
8381 | DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO, | ||
8382 | "%s: unknown phy %u (rate ix %u)\n", __func__, | ||
8383 | rates->info[rateix].phy, rateix); | ||
8384 | txTime = 0; | ||
8385 | break; | ||
8386 | } | ||
8387 | return txTime; | ||
8388 | } | ||
8389 | |||
8390 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags) | ||
8391 | { | ||
8392 | if (flags & CHANNEL_2GHZ) { | ||
8393 | if (freq == 2484) | ||
8394 | return 14; | ||
8395 | if (freq < 2484) | ||
8396 | return (freq - 2407) / 5; | ||
8397 | else | ||
8398 | return 15 + ((freq - 2512) / 20); | ||
8399 | } else if (flags & CHANNEL_5GHZ) { | ||
8400 | if (ath9k_regd_is_public_safety_sku(ah) && | ||
8401 | IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { | ||
8402 | return ((freq * 10) + | ||
8403 | (((freq % 5) == 2) ? 5 : 0) - 49400) / 5; | ||
8404 | } else if ((flags & CHANNEL_A) && (freq <= 5000)) { | ||
8405 | return (freq - 4000) / 5; | ||
8406 | } else { | ||
8407 | return (freq - 5000) / 5; | ||
8408 | } | ||
8409 | } else { | ||
8410 | if (freq == 2484) | ||
8411 | return 14; | ||
8412 | if (freq < 2484) | ||
8413 | return (freq - 2407) / 5; | ||
8414 | if (freq < 5000) { | ||
8415 | if (ath9k_regd_is_public_safety_sku(ah) | ||
8416 | && IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { | ||
8417 | return ((freq * 10) + | ||
8418 | (((freq % 5) == | ||
8419 | 2) ? 5 : 0) - 49400) / 5; | ||
8420 | } else if (freq > 4900) { | ||
8421 | return (freq - 4000) / 5; | ||
8422 | } else { | ||
8423 | return 15 + ((freq - 2512) / 20); | ||
8424 | } | ||
8425 | } | ||
8426 | return (freq - 5000) / 5; | ||
8427 | } | ||
8428 | } | ||
8429 | |||
8430 | int16_t | ||
8431 | ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) | ||
8432 | { | ||
8433 | struct ath9k_channel *ichan; | ||
8434 | |||
8435 | ichan = ath9k_regd_check_channel(ah, chan); | ||
8436 | if (ichan == NULL) { | ||
8437 | DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, | ||
8438 | "%s: invalid channel %u/0x%x; no mapping\n", | ||
8439 | __func__, chan->channel, chan->channelFlags); | ||
8440 | return 0; | ||
8441 | } | ||
8442 | if (ichan->rawNoiseFloor == 0) { | ||
8443 | enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan); | ||
8444 | return NOISE_FLOOR[mode]; | ||
8445 | } else | ||
8446 | return ichan->rawNoiseFloor; | ||
8447 | } | ||
8448 | |||
8449 | bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting) | ||
8450 | { | ||
8451 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
8452 | |||
8453 | if (setting) | ||
8454 | ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF; | ||
8455 | else | ||
8456 | ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF; | ||
8457 | return true; | ||
8458 | } | ||
8459 | |||
8460 | bool ath9k_hw_phycounters(struct ath_hal *ah) | ||
8461 | { | ||
8462 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
8463 | |||
8464 | return ahp->ah_hasHwPhyCounters ? true : false; | ||
8465 | } | ||
8466 | |||
8467 | u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q) | ||
8468 | { | ||
8469 | return REG_READ(ah, AR_QTXDP(q)); | ||
8470 | } | ||
8471 | |||
8472 | bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, | ||
8473 | u32 txdp) | ||
8474 | { | ||
8475 | REG_WRITE(ah, AR_QTXDP(q), txdp); | ||
8476 | |||
8477 | return true; | ||
8478 | } | ||
8479 | |||
8480 | bool ath9k_hw_txstart(struct ath_hal *ah, u32 q) | ||
8481 | { | ||
8482 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q); | ||
8483 | |||
8484 | REG_WRITE(ah, AR_Q_TXE, 1 << q); | ||
8485 | |||
8486 | return true; | ||
8487 | } | ||
8488 | |||
8489 | u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q) | ||
8490 | { | ||
8491 | u32 npend; | ||
8492 | |||
8493 | npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; | ||
8494 | if (npend == 0) { | ||
8495 | |||
8496 | if (REG_READ(ah, AR_Q_TXE) & (1 << q)) | ||
8497 | npend = 1; | ||
8498 | } | ||
8499 | return npend; | ||
8500 | } | ||
8501 | |||
8502 | bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) | ||
8503 | { | ||
8504 | u32 wait; | ||
8505 | |||
8506 | REG_WRITE(ah, AR_Q_TXD, 1 << q); | ||
8507 | |||
8508 | for (wait = 1000; wait != 0; wait--) { | ||
8509 | if (ath9k_hw_numtxpending(ah, q) == 0) | ||
8510 | break; | ||
8511 | udelay(100); | ||
8512 | } | ||
8513 | |||
8514 | if (ath9k_hw_numtxpending(ah, q)) { | ||
8515 | u32 tsfLow, j; | ||
8516 | |||
8517 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
8518 | "%s: Num of pending TX Frames %d on Q %d\n", | ||
8519 | __func__, ath9k_hw_numtxpending(ah, q), q); | ||
8520 | |||
8521 | for (j = 0; j < 2; j++) { | ||
8522 | tsfLow = REG_READ(ah, AR_TSF_L32); | ||
8523 | REG_WRITE(ah, AR_QUIET2, | ||
8524 | SM(10, AR_QUIET2_QUIET_DUR)); | ||
8525 | REG_WRITE(ah, AR_QUIET_PERIOD, 100); | ||
8526 | REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); | ||
8527 | REG_SET_BIT(ah, AR_TIMER_MODE, | ||
8528 | AR_QUIET_TIMER_EN); | ||
8529 | |||
8530 | if ((REG_READ(ah, AR_TSF_L32) >> 10) == | ||
8531 | (tsfLow >> 10)) { | ||
8532 | break; | ||
8533 | } | ||
8534 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
8535 | "%s: TSF have moved while trying to set " | ||
8536 | "quiet time TSF: 0x%08x\n", | ||
8537 | __func__, tsfLow); | ||
8538 | } | ||
8539 | |||
8540 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | ||
8541 | |||
8542 | udelay(200); | ||
8543 | REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); | ||
8544 | |||
8545 | wait = 1000; | ||
8546 | |||
8547 | while (ath9k_hw_numtxpending(ah, q)) { | ||
8548 | if ((--wait) == 0) { | ||
8549 | DPRINTF(ah->ah_sc, ATH_DBG_XMIT, | ||
8550 | "%s: Failed to stop Tx DMA in 100 " | ||
8551 | "msec after killing last frame\n", | ||
8552 | __func__); | ||
8553 | break; | ||
8554 | } | ||
8555 | udelay(100); | ||
8556 | } | ||
8557 | |||
8558 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | ||
8559 | } | ||
8560 | |||
8561 | REG_WRITE(ah, AR_Q_TXD, 0); | ||
8562 | return wait != 0; | ||
8563 | } | ||
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h new file mode 100644 index 00000000000..ae680f21ba7 --- /dev/null +++ b/drivers/net/wireless/ath9k/hw.h | |||
@@ -0,0 +1,969 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef HW_H | ||
18 | #define HW_H | ||
19 | |||
20 | #include <linux/if_ether.h> | ||
21 | #include <linux/delay.h> | ||
22 | |||
23 | struct ar5416_desc { | ||
24 | u32 ds_link; | ||
25 | u32 ds_data; | ||
26 | u32 ds_ctl0; | ||
27 | u32 ds_ctl1; | ||
28 | union { | ||
29 | struct { | ||
30 | u32 ctl2; | ||
31 | u32 ctl3; | ||
32 | u32 ctl4; | ||
33 | u32 ctl5; | ||
34 | u32 ctl6; | ||
35 | u32 ctl7; | ||
36 | u32 ctl8; | ||
37 | u32 ctl9; | ||
38 | u32 ctl10; | ||
39 | u32 ctl11; | ||
40 | u32 status0; | ||
41 | u32 status1; | ||
42 | u32 status2; | ||
43 | u32 status3; | ||
44 | u32 status4; | ||
45 | u32 status5; | ||
46 | u32 status6; | ||
47 | u32 status7; | ||
48 | u32 status8; | ||
49 | u32 status9; | ||
50 | } tx; | ||
51 | struct { | ||
52 | u32 status0; | ||
53 | u32 status1; | ||
54 | u32 status2; | ||
55 | u32 status3; | ||
56 | u32 status4; | ||
57 | u32 status5; | ||
58 | u32 status6; | ||
59 | u32 status7; | ||
60 | u32 status8; | ||
61 | } rx; | ||
62 | } u; | ||
63 | } __packed; | ||
64 | |||
65 | #define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) | ||
66 | #define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) | ||
67 | |||
68 | #define ds_ctl2 u.tx.ctl2 | ||
69 | #define ds_ctl3 u.tx.ctl3 | ||
70 | #define ds_ctl4 u.tx.ctl4 | ||
71 | #define ds_ctl5 u.tx.ctl5 | ||
72 | #define ds_ctl6 u.tx.ctl6 | ||
73 | #define ds_ctl7 u.tx.ctl7 | ||
74 | #define ds_ctl8 u.tx.ctl8 | ||
75 | #define ds_ctl9 u.tx.ctl9 | ||
76 | #define ds_ctl10 u.tx.ctl10 | ||
77 | #define ds_ctl11 u.tx.ctl11 | ||
78 | |||
79 | #define ds_txstatus0 u.tx.status0 | ||
80 | #define ds_txstatus1 u.tx.status1 | ||
81 | #define ds_txstatus2 u.tx.status2 | ||
82 | #define ds_txstatus3 u.tx.status3 | ||
83 | #define ds_txstatus4 u.tx.status4 | ||
84 | #define ds_txstatus5 u.tx.status5 | ||
85 | #define ds_txstatus6 u.tx.status6 | ||
86 | #define ds_txstatus7 u.tx.status7 | ||
87 | #define ds_txstatus8 u.tx.status8 | ||
88 | #define ds_txstatus9 u.tx.status9 | ||
89 | |||
90 | #define ds_rxstatus0 u.rx.status0 | ||
91 | #define ds_rxstatus1 u.rx.status1 | ||
92 | #define ds_rxstatus2 u.rx.status2 | ||
93 | #define ds_rxstatus3 u.rx.status3 | ||
94 | #define ds_rxstatus4 u.rx.status4 | ||
95 | #define ds_rxstatus5 u.rx.status5 | ||
96 | #define ds_rxstatus6 u.rx.status6 | ||
97 | #define ds_rxstatus7 u.rx.status7 | ||
98 | #define ds_rxstatus8 u.rx.status8 | ||
99 | |||
100 | #define AR_FrameLen 0x00000fff | ||
101 | #define AR_VirtMoreFrag 0x00001000 | ||
102 | #define AR_TxCtlRsvd00 0x0000e000 | ||
103 | #define AR_XmitPower 0x003f0000 | ||
104 | #define AR_XmitPower_S 16 | ||
105 | #define AR_RTSEnable 0x00400000 | ||
106 | #define AR_VEOL 0x00800000 | ||
107 | #define AR_ClrDestMask 0x01000000 | ||
108 | #define AR_TxCtlRsvd01 0x1e000000 | ||
109 | #define AR_TxIntrReq 0x20000000 | ||
110 | #define AR_DestIdxValid 0x40000000 | ||
111 | #define AR_CTSEnable 0x80000000 | ||
112 | |||
113 | #define AR_BufLen 0x00000fff | ||
114 | #define AR_TxMore 0x00001000 | ||
115 | #define AR_DestIdx 0x000fe000 | ||
116 | #define AR_DestIdx_S 13 | ||
117 | #define AR_FrameType 0x00f00000 | ||
118 | #define AR_FrameType_S 20 | ||
119 | #define AR_NoAck 0x01000000 | ||
120 | #define AR_InsertTS 0x02000000 | ||
121 | #define AR_CorruptFCS 0x04000000 | ||
122 | #define AR_ExtOnly 0x08000000 | ||
123 | #define AR_ExtAndCtl 0x10000000 | ||
124 | #define AR_MoreAggr 0x20000000 | ||
125 | #define AR_IsAggr 0x40000000 | ||
126 | |||
127 | #define AR_BurstDur 0x00007fff | ||
128 | #define AR_BurstDur_S 0 | ||
129 | #define AR_DurUpdateEna 0x00008000 | ||
130 | #define AR_XmitDataTries0 0x000f0000 | ||
131 | #define AR_XmitDataTries0_S 16 | ||
132 | #define AR_XmitDataTries1 0x00f00000 | ||
133 | #define AR_XmitDataTries1_S 20 | ||
134 | #define AR_XmitDataTries2 0x0f000000 | ||
135 | #define AR_XmitDataTries2_S 24 | ||
136 | #define AR_XmitDataTries3 0xf0000000 | ||
137 | #define AR_XmitDataTries3_S 28 | ||
138 | |||
139 | #define AR_XmitRate0 0x000000ff | ||
140 | #define AR_XmitRate0_S 0 | ||
141 | #define AR_XmitRate1 0x0000ff00 | ||
142 | #define AR_XmitRate1_S 8 | ||
143 | #define AR_XmitRate2 0x00ff0000 | ||
144 | #define AR_XmitRate2_S 16 | ||
145 | #define AR_XmitRate3 0xff000000 | ||
146 | #define AR_XmitRate3_S 24 | ||
147 | |||
148 | #define AR_PacketDur0 0x00007fff | ||
149 | #define AR_PacketDur0_S 0 | ||
150 | #define AR_RTSCTSQual0 0x00008000 | ||
151 | #define AR_PacketDur1 0x7fff0000 | ||
152 | #define AR_PacketDur1_S 16 | ||
153 | #define AR_RTSCTSQual1 0x80000000 | ||
154 | |||
155 | #define AR_PacketDur2 0x00007fff | ||
156 | #define AR_PacketDur2_S 0 | ||
157 | #define AR_RTSCTSQual2 0x00008000 | ||
158 | #define AR_PacketDur3 0x7fff0000 | ||
159 | #define AR_PacketDur3_S 16 | ||
160 | #define AR_RTSCTSQual3 0x80000000 | ||
161 | |||
162 | #define AR_AggrLen 0x0000ffff | ||
163 | #define AR_AggrLen_S 0 | ||
164 | #define AR_TxCtlRsvd60 0x00030000 | ||
165 | #define AR_PadDelim 0x03fc0000 | ||
166 | #define AR_PadDelim_S 18 | ||
167 | #define AR_EncrType 0x0c000000 | ||
168 | #define AR_EncrType_S 26 | ||
169 | #define AR_TxCtlRsvd61 0xf0000000 | ||
170 | |||
171 | #define AR_2040_0 0x00000001 | ||
172 | #define AR_GI0 0x00000002 | ||
173 | #define AR_ChainSel0 0x0000001c | ||
174 | #define AR_ChainSel0_S 2 | ||
175 | #define AR_2040_1 0x00000020 | ||
176 | #define AR_GI1 0x00000040 | ||
177 | #define AR_ChainSel1 0x00000380 | ||
178 | #define AR_ChainSel1_S 7 | ||
179 | #define AR_2040_2 0x00000400 | ||
180 | #define AR_GI2 0x00000800 | ||
181 | #define AR_ChainSel2 0x00007000 | ||
182 | #define AR_ChainSel2_S 12 | ||
183 | #define AR_2040_3 0x00008000 | ||
184 | #define AR_GI3 0x00010000 | ||
185 | #define AR_ChainSel3 0x000e0000 | ||
186 | #define AR_ChainSel3_S 17 | ||
187 | #define AR_RTSCTSRate 0x0ff00000 | ||
188 | #define AR_RTSCTSRate_S 20 | ||
189 | #define AR_TxCtlRsvd70 0xf0000000 | ||
190 | |||
191 | #define AR_TxRSSIAnt00 0x000000ff | ||
192 | #define AR_TxRSSIAnt00_S 0 | ||
193 | #define AR_TxRSSIAnt01 0x0000ff00 | ||
194 | #define AR_TxRSSIAnt01_S 8 | ||
195 | #define AR_TxRSSIAnt02 0x00ff0000 | ||
196 | #define AR_TxRSSIAnt02_S 16 | ||
197 | #define AR_TxStatusRsvd00 0x3f000000 | ||
198 | #define AR_TxBaStatus 0x40000000 | ||
199 | #define AR_TxStatusRsvd01 0x80000000 | ||
200 | |||
201 | #define AR_FrmXmitOK 0x00000001 | ||
202 | #define AR_ExcessiveRetries 0x00000002 | ||
203 | #define AR_FIFOUnderrun 0x00000004 | ||
204 | #define AR_Filtered 0x00000008 | ||
205 | #define AR_RTSFailCnt 0x000000f0 | ||
206 | #define AR_RTSFailCnt_S 4 | ||
207 | #define AR_DataFailCnt 0x00000f00 | ||
208 | #define AR_DataFailCnt_S 8 | ||
209 | #define AR_VirtRetryCnt 0x0000f000 | ||
210 | #define AR_VirtRetryCnt_S 12 | ||
211 | #define AR_TxDelimUnderrun 0x00010000 | ||
212 | #define AR_TxDataUnderrun 0x00020000 | ||
213 | #define AR_DescCfgErr 0x00040000 | ||
214 | #define AR_TxTimerExpired 0x00080000 | ||
215 | #define AR_TxStatusRsvd10 0xfff00000 | ||
216 | |||
217 | #define AR_SendTimestamp ds_txstatus2 | ||
218 | #define AR_BaBitmapLow ds_txstatus3 | ||
219 | #define AR_BaBitmapHigh ds_txstatus4 | ||
220 | |||
221 | #define AR_TxRSSIAnt10 0x000000ff | ||
222 | #define AR_TxRSSIAnt10_S 0 | ||
223 | #define AR_TxRSSIAnt11 0x0000ff00 | ||
224 | #define AR_TxRSSIAnt11_S 8 | ||
225 | #define AR_TxRSSIAnt12 0x00ff0000 | ||
226 | #define AR_TxRSSIAnt12_S 16 | ||
227 | #define AR_TxRSSICombined 0xff000000 | ||
228 | #define AR_TxRSSICombined_S 24 | ||
229 | |||
230 | #define AR_TxEVM0 ds_txstatus5 | ||
231 | #define AR_TxEVM1 ds_txstatus6 | ||
232 | #define AR_TxEVM2 ds_txstatus7 | ||
233 | |||
234 | #define AR_TxDone 0x00000001 | ||
235 | #define AR_SeqNum 0x00001ffe | ||
236 | #define AR_SeqNum_S 1 | ||
237 | #define AR_TxStatusRsvd80 0x0001e000 | ||
238 | #define AR_TxOpExceeded 0x00020000 | ||
239 | #define AR_TxStatusRsvd81 0x001c0000 | ||
240 | #define AR_FinalTxIdx 0x00600000 | ||
241 | #define AR_FinalTxIdx_S 21 | ||
242 | #define AR_TxStatusRsvd82 0x01800000 | ||
243 | #define AR_PowerMgmt 0x02000000 | ||
244 | #define AR_TxStatusRsvd83 0xfc000000 | ||
245 | |||
246 | #define AR_RxCTLRsvd00 0xffffffff | ||
247 | |||
248 | #define AR_BufLen 0x00000fff | ||
249 | #define AR_RxCtlRsvd00 0x00001000 | ||
250 | #define AR_RxIntrReq 0x00002000 | ||
251 | #define AR_RxCtlRsvd01 0xffffc000 | ||
252 | |||
253 | #define AR_RxRSSIAnt00 0x000000ff | ||
254 | #define AR_RxRSSIAnt00_S 0 | ||
255 | #define AR_RxRSSIAnt01 0x0000ff00 | ||
256 | #define AR_RxRSSIAnt01_S 8 | ||
257 | #define AR_RxRSSIAnt02 0x00ff0000 | ||
258 | #define AR_RxRSSIAnt02_S 16 | ||
259 | #define AR_RxRate 0xff000000 | ||
260 | #define AR_RxRate_S 24 | ||
261 | #define AR_RxStatusRsvd00 0xff000000 | ||
262 | |||
263 | #define AR_DataLen 0x00000fff | ||
264 | #define AR_RxMore 0x00001000 | ||
265 | #define AR_NumDelim 0x003fc000 | ||
266 | #define AR_NumDelim_S 14 | ||
267 | #define AR_RxStatusRsvd10 0xff800000 | ||
268 | |||
269 | #define AR_RcvTimestamp ds_rxstatus2 | ||
270 | |||
271 | #define AR_GI 0x00000001 | ||
272 | #define AR_2040 0x00000002 | ||
273 | #define AR_Parallel40 0x00000004 | ||
274 | #define AR_Parallel40_S 2 | ||
275 | #define AR_RxStatusRsvd30 0x000000f8 | ||
276 | #define AR_RxAntenna 0xffffff00 | ||
277 | #define AR_RxAntenna_S 8 | ||
278 | |||
279 | #define AR_RxRSSIAnt10 0x000000ff | ||
280 | #define AR_RxRSSIAnt10_S 0 | ||
281 | #define AR_RxRSSIAnt11 0x0000ff00 | ||
282 | #define AR_RxRSSIAnt11_S 8 | ||
283 | #define AR_RxRSSIAnt12 0x00ff0000 | ||
284 | #define AR_RxRSSIAnt12_S 16 | ||
285 | #define AR_RxRSSICombined 0xff000000 | ||
286 | #define AR_RxRSSICombined_S 24 | ||
287 | |||
288 | #define AR_RxEVM0 ds_rxstatus4 | ||
289 | #define AR_RxEVM1 ds_rxstatus5 | ||
290 | #define AR_RxEVM2 ds_rxstatus6 | ||
291 | |||
292 | #define AR_RxDone 0x00000001 | ||
293 | #define AR_RxFrameOK 0x00000002 | ||
294 | #define AR_CRCErr 0x00000004 | ||
295 | #define AR_DecryptCRCErr 0x00000008 | ||
296 | #define AR_PHYErr 0x00000010 | ||
297 | #define AR_MichaelErr 0x00000020 | ||
298 | #define AR_PreDelimCRCErr 0x00000040 | ||
299 | #define AR_RxStatusRsvd70 0x00000080 | ||
300 | #define AR_RxKeyIdxValid 0x00000100 | ||
301 | #define AR_KeyIdx 0x0000fe00 | ||
302 | #define AR_KeyIdx_S 9 | ||
303 | #define AR_PHYErrCode 0x0000ff00 | ||
304 | #define AR_PHYErrCode_S 8 | ||
305 | #define AR_RxMoreAggr 0x00010000 | ||
306 | #define AR_RxAggr 0x00020000 | ||
307 | #define AR_PostDelimCRCErr 0x00040000 | ||
308 | #define AR_RxStatusRsvd71 0x3ff80000 | ||
309 | #define AR_DecryptBusyErr 0x40000000 | ||
310 | #define AR_KeyMiss 0x80000000 | ||
311 | |||
312 | #define AR5416_MAGIC 0x19641014 | ||
313 | |||
314 | #define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \ | ||
315 | MS(ads->ds_rxstatus0, AR_RxRate) : \ | ||
316 | (ads->ds_rxstatus3 >> 2) & 0xFF) | ||
317 | #define RXSTATUS_DUPLICATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \ | ||
318 | MS(ads->ds_rxstatus3, AR_Parallel40) : \ | ||
319 | (ads->ds_rxstatus3 >> 10) & 0x1) | ||
320 | |||
321 | #define set11nTries(_series, _index) \ | ||
322 | (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) | ||
323 | |||
324 | #define set11nRate(_series, _index) \ | ||
325 | (SM((_series)[_index].Rate, AR_XmitRate##_index)) | ||
326 | |||
327 | #define set11nPktDurRTSCTS(_series, _index) \ | ||
328 | (SM((_series)[_index].PktDuration, AR_PacketDur##_index) | \ | ||
329 | ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS ? \ | ||
330 | AR_RTSCTSQual##_index : 0)) | ||
331 | |||
332 | #define set11nRateFlags(_series, _index) \ | ||
333 | (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \ | ||
334 | AR_2040_##_index : 0) \ | ||
335 | |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ | ||
336 | AR_GI##_index : 0) \ | ||
337 | |SM((_series)[_index].ChSel, AR_ChainSel##_index)) | ||
338 | |||
339 | #define AR_SREV_9100(ah) ((ah->ah_macVersion) == AR_SREV_VERSION_9100) | ||
340 | |||
341 | #define INIT_CONFIG_STATUS 0x00000000 | ||
342 | #define INIT_RSSI_THR 0x00000700 | ||
343 | #define INIT_BCON_CNTRL_REG 0x00000000 | ||
344 | |||
345 | #define MIN_TX_FIFO_THRESHOLD 0x1 | ||
346 | #define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1) | ||
347 | #define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD | ||
348 | |||
349 | #define NUM_CORNER_FIX_BITS_2133 7 | ||
350 | #define CCK_OFDM_GAIN_DELTA 15 | ||
351 | |||
352 | struct ar5416AniState { | ||
353 | struct ath9k_channel c; | ||
354 | u8 noiseImmunityLevel; | ||
355 | u8 spurImmunityLevel; | ||
356 | u8 firstepLevel; | ||
357 | u8 ofdmWeakSigDetectOff; | ||
358 | u8 cckWeakSigThreshold; | ||
359 | u32 listenTime; | ||
360 | u32 ofdmTrigHigh; | ||
361 | u32 ofdmTrigLow; | ||
362 | int32_t cckTrigHigh; | ||
363 | int32_t cckTrigLow; | ||
364 | int32_t rssiThrLow; | ||
365 | int32_t rssiThrHigh; | ||
366 | u32 noiseFloor; | ||
367 | u32 txFrameCount; | ||
368 | u32 rxFrameCount; | ||
369 | u32 cycleCount; | ||
370 | u32 ofdmPhyErrCount; | ||
371 | u32 cckPhyErrCount; | ||
372 | u32 ofdmPhyErrBase; | ||
373 | u32 cckPhyErrBase; | ||
374 | int16_t pktRssi[2]; | ||
375 | int16_t ofdmErrRssi[2]; | ||
376 | int16_t cckErrRssi[2]; | ||
377 | }; | ||
378 | |||
379 | #define HAL_PROCESS_ANI 0x00000001 | ||
380 | #define HAL_RADAR_EN 0x80000000 | ||
381 | #define HAL_AR_EN 0x40000000 | ||
382 | |||
383 | #define DO_ANI(ah) \ | ||
384 | ((AH5416(ah)->ah_procPhyErr & HAL_PROCESS_ANI)) | ||
385 | |||
386 | struct ar5416Stats { | ||
387 | u32 ast_ani_niup; | ||
388 | u32 ast_ani_nidown; | ||
389 | u32 ast_ani_spurup; | ||
390 | u32 ast_ani_spurdown; | ||
391 | u32 ast_ani_ofdmon; | ||
392 | u32 ast_ani_ofdmoff; | ||
393 | u32 ast_ani_cckhigh; | ||
394 | u32 ast_ani_ccklow; | ||
395 | u32 ast_ani_stepup; | ||
396 | u32 ast_ani_stepdown; | ||
397 | u32 ast_ani_ofdmerrs; | ||
398 | u32 ast_ani_cckerrs; | ||
399 | u32 ast_ani_reset; | ||
400 | u32 ast_ani_lzero; | ||
401 | u32 ast_ani_lneg; | ||
402 | struct ath9k_mib_stats ast_mibstats; | ||
403 | struct ath9k_node_stats ast_nodestats; | ||
404 | }; | ||
405 | |||
406 | #define AR5416_OPFLAGS_11A 0x01 | ||
407 | #define AR5416_OPFLAGS_11G 0x02 | ||
408 | #define AR5416_OPFLAGS_N_5G_HT40 0x04 | ||
409 | #define AR5416_OPFLAGS_N_2G_HT40 0x08 | ||
410 | #define AR5416_OPFLAGS_N_5G_HT20 0x10 | ||
411 | #define AR5416_OPFLAGS_N_2G_HT20 0x20 | ||
412 | |||
413 | #define EEP_RFSILENT_ENABLED 0x0001 | ||
414 | #define EEP_RFSILENT_ENABLED_S 0 | ||
415 | #define EEP_RFSILENT_POLARITY 0x0002 | ||
416 | #define EEP_RFSILENT_POLARITY_S 1 | ||
417 | #define EEP_RFSILENT_GPIO_SEL 0x001c | ||
418 | #define EEP_RFSILENT_GPIO_SEL_S 2 | ||
419 | |||
420 | #define AR5416_EEP_NO_BACK_VER 0x1 | ||
421 | #define AR5416_EEP_VER 0xE | ||
422 | #define AR5416_EEP_VER_MINOR_MASK 0x0FFF | ||
423 | #define AR5416_EEP_MINOR_VER_2 0x2 | ||
424 | #define AR5416_EEP_MINOR_VER_3 0x3 | ||
425 | #define AR5416_EEP_MINOR_VER_7 0x7 | ||
426 | #define AR5416_EEP_MINOR_VER_9 0x9 | ||
427 | |||
428 | #define AR5416_EEP_START_LOC 256 | ||
429 | #define AR5416_NUM_5G_CAL_PIERS 8 | ||
430 | #define AR5416_NUM_2G_CAL_PIERS 4 | ||
431 | #define AR5416_NUM_5G_20_TARGET_POWERS 8 | ||
432 | #define AR5416_NUM_5G_40_TARGET_POWERS 8 | ||
433 | #define AR5416_NUM_2G_CCK_TARGET_POWERS 3 | ||
434 | #define AR5416_NUM_2G_20_TARGET_POWERS 4 | ||
435 | #define AR5416_NUM_2G_40_TARGET_POWERS 4 | ||
436 | #define AR5416_NUM_CTLS 24 | ||
437 | #define AR5416_NUM_BAND_EDGES 8 | ||
438 | #define AR5416_NUM_PD_GAINS 4 | ||
439 | #define AR5416_PD_GAINS_IN_MASK 4 | ||
440 | #define AR5416_PD_GAIN_ICEPTS 5 | ||
441 | #define AR5416_EEPROM_MODAL_SPURS 5 | ||
442 | #define AR5416_MAX_RATE_POWER 63 | ||
443 | #define AR5416_NUM_PDADC_VALUES 128 | ||
444 | #define AR5416_NUM_RATES 16 | ||
445 | #define AR5416_BCHAN_UNUSED 0xFF | ||
446 | #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 | ||
447 | #define AR5416_EEPMISC_BIG_ENDIAN 0x01 | ||
448 | #define AR5416_MAX_CHAINS 3 | ||
449 | #define AR5416_ANT_16S 25 | ||
450 | |||
451 | #define AR5416_NUM_ANT_CHAIN_FIELDS 7 | ||
452 | #define AR5416_NUM_ANT_COMMON_FIELDS 4 | ||
453 | #define AR5416_SIZE_ANT_CHAIN_FIELD 3 | ||
454 | #define AR5416_SIZE_ANT_COMMON_FIELD 4 | ||
455 | #define AR5416_ANT_CHAIN_MASK 0x7 | ||
456 | #define AR5416_ANT_COMMON_MASK 0xf | ||
457 | #define AR5416_CHAIN_0_IDX 0 | ||
458 | #define AR5416_CHAIN_1_IDX 1 | ||
459 | #define AR5416_CHAIN_2_IDX 2 | ||
460 | |||
461 | #define AR5416_PWR_TABLE_OFFSET -5 | ||
462 | #define AR5416_LEGACY_CHAINMASK 1 | ||
463 | |||
464 | enum eeprom_param { | ||
465 | EEP_NFTHRESH_5, | ||
466 | EEP_NFTHRESH_2, | ||
467 | EEP_MAC_MSW, | ||
468 | EEP_MAC_MID, | ||
469 | EEP_MAC_LSW, | ||
470 | EEP_REG_0, | ||
471 | EEP_REG_1, | ||
472 | EEP_OP_CAP, | ||
473 | EEP_OP_MODE, | ||
474 | EEP_RF_SILENT, | ||
475 | EEP_OB_5, | ||
476 | EEP_DB_5, | ||
477 | EEP_OB_2, | ||
478 | EEP_DB_2, | ||
479 | EEP_MINOR_REV, | ||
480 | EEP_TX_MASK, | ||
481 | EEP_RX_MASK, | ||
482 | }; | ||
483 | |||
484 | enum ar5416_rates { | ||
485 | rate6mb, rate9mb, rate12mb, rate18mb, | ||
486 | rate24mb, rate36mb, rate48mb, rate54mb, | ||
487 | rate1l, rate2l, rate2s, rate5_5l, | ||
488 | rate5_5s, rate11l, rate11s, rateXr, | ||
489 | rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3, | ||
490 | rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7, | ||
491 | rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3, | ||
492 | rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7, | ||
493 | rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm, | ||
494 | Ar5416RateSize | ||
495 | }; | ||
496 | |||
497 | struct base_eep_header { | ||
498 | u16 length; | ||
499 | u16 checksum; | ||
500 | u16 version; | ||
501 | u8 opCapFlags; | ||
502 | u8 eepMisc; | ||
503 | u16 regDmn[2]; | ||
504 | u8 macAddr[6]; | ||
505 | u8 rxMask; | ||
506 | u8 txMask; | ||
507 | u16 rfSilent; | ||
508 | u16 blueToothOptions; | ||
509 | u16 deviceCap; | ||
510 | u32 binBuildNumber; | ||
511 | u8 deviceType; | ||
512 | u8 pwdclkind; | ||
513 | u8 futureBase[32]; | ||
514 | } __packed; | ||
515 | |||
516 | struct spur_chan { | ||
517 | u16 spurChan; | ||
518 | u8 spurRangeLow; | ||
519 | u8 spurRangeHigh; | ||
520 | } __packed; | ||
521 | |||
522 | struct modal_eep_header { | ||
523 | u32 antCtrlChain[AR5416_MAX_CHAINS]; | ||
524 | u32 antCtrlCommon; | ||
525 | u8 antennaGainCh[AR5416_MAX_CHAINS]; | ||
526 | u8 switchSettling; | ||
527 | u8 txRxAttenCh[AR5416_MAX_CHAINS]; | ||
528 | u8 rxTxMarginCh[AR5416_MAX_CHAINS]; | ||
529 | u8 adcDesiredSize; | ||
530 | u8 pgaDesiredSize; | ||
531 | u8 xlnaGainCh[AR5416_MAX_CHAINS]; | ||
532 | u8 txEndToXpaOff; | ||
533 | u8 txEndToRxOn; | ||
534 | u8 txFrameToXpaOn; | ||
535 | u8 thresh62; | ||
536 | u8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; | ||
537 | u8 xpdGain; | ||
538 | u8 xpd; | ||
539 | u8 iqCalICh[AR5416_MAX_CHAINS]; | ||
540 | u8 iqCalQCh[AR5416_MAX_CHAINS]; | ||
541 | u8 pdGainOverlap; | ||
542 | u8 ob; | ||
543 | u8 db; | ||
544 | u8 xpaBiasLvl; | ||
545 | u8 pwrDecreaseFor2Chain; | ||
546 | u8 pwrDecreaseFor3Chain; | ||
547 | u8 txFrameToDataStart; | ||
548 | u8 txFrameToPaOn; | ||
549 | u8 ht40PowerIncForPdadc; | ||
550 | u8 bswAtten[AR5416_MAX_CHAINS]; | ||
551 | u8 bswMargin[AR5416_MAX_CHAINS]; | ||
552 | u8 swSettleHt40; | ||
553 | u8 xatten2Db[AR5416_MAX_CHAINS]; | ||
554 | u8 xatten2Margin[AR5416_MAX_CHAINS]; | ||
555 | u8 ob_ch1; | ||
556 | u8 db_ch1; | ||
557 | u8 useAnt1:1, | ||
558 | force_xpaon:1, | ||
559 | local_bias:1, | ||
560 | femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1; | ||
561 | u8 futureModalar9280; | ||
562 | u16 xpaBiasLvlFreq[3]; | ||
563 | u8 futureModal[6]; | ||
564 | |||
565 | struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; | ||
566 | } __packed; | ||
567 | |||
568 | struct cal_data_per_freq { | ||
569 | u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | ||
570 | u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | ||
571 | } __packed; | ||
572 | |||
573 | struct cal_target_power_leg { | ||
574 | u8 bChannel; | ||
575 | u8 tPow2x[4]; | ||
576 | } __packed; | ||
577 | |||
578 | struct cal_target_power_ht { | ||
579 | u8 bChannel; | ||
580 | u8 tPow2x[8]; | ||
581 | } __packed; | ||
582 | |||
583 | #ifdef __BIG_ENDIAN_BITFIELD | ||
584 | struct cal_ctl_edges { | ||
585 | u8 bChannel; | ||
586 | u8 flag:2, tPower:6; | ||
587 | } __packed; | ||
588 | #else | ||
589 | struct cal_ctl_edges { | ||
590 | u8 bChannel; | ||
591 | u8 tPower:6, flag:2; | ||
592 | } __packed; | ||
593 | #endif | ||
594 | |||
595 | struct cal_ctl_data { | ||
596 | struct cal_ctl_edges | ||
597 | ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; | ||
598 | } __packed; | ||
599 | |||
600 | struct ar5416_eeprom { | ||
601 | struct base_eep_header baseEepHeader; | ||
602 | u8 custData[64]; | ||
603 | struct modal_eep_header modalHeader[2]; | ||
604 | u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS]; | ||
605 | u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS]; | ||
606 | struct cal_data_per_freq | ||
607 | calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS]; | ||
608 | struct cal_data_per_freq | ||
609 | calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; | ||
610 | struct cal_target_power_leg | ||
611 | calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS]; | ||
612 | struct cal_target_power_ht | ||
613 | calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS]; | ||
614 | struct cal_target_power_ht | ||
615 | calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS]; | ||
616 | struct cal_target_power_leg | ||
617 | calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS]; | ||
618 | struct cal_target_power_leg | ||
619 | calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS]; | ||
620 | struct cal_target_power_ht | ||
621 | calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS]; | ||
622 | struct cal_target_power_ht | ||
623 | calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS]; | ||
624 | u8 ctlIndex[AR5416_NUM_CTLS]; | ||
625 | struct cal_ctl_data ctlData[AR5416_NUM_CTLS]; | ||
626 | u8 padding; | ||
627 | } __packed; | ||
628 | |||
629 | struct ar5416IniArray { | ||
630 | u32 *ia_array; | ||
631 | u32 ia_rows; | ||
632 | u32 ia_columns; | ||
633 | }; | ||
634 | |||
635 | #define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \ | ||
636 | (iniarray)->ia_array = (u32 *)(array); \ | ||
637 | (iniarray)->ia_rows = (rows); \ | ||
638 | (iniarray)->ia_columns = (columns); \ | ||
639 | } while (0) | ||
640 | |||
641 | #define INI_RA(iniarray, row, column) \ | ||
642 | (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)]) | ||
643 | |||
644 | #define INIT_CAL(_perCal) do { \ | ||
645 | (_perCal)->calState = CAL_WAITING; \ | ||
646 | (_perCal)->calNext = NULL; \ | ||
647 | } while (0) | ||
648 | |||
649 | #define INSERT_CAL(_ahp, _perCal) \ | ||
650 | do { \ | ||
651 | if ((_ahp)->ah_cal_list_last == NULL) { \ | ||
652 | (_ahp)->ah_cal_list = \ | ||
653 | (_ahp)->ah_cal_list_last = (_perCal); \ | ||
654 | ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \ | ||
655 | } else { \ | ||
656 | ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \ | ||
657 | (_ahp)->ah_cal_list_last = (_perCal); \ | ||
658 | (_perCal)->calNext = (_ahp)->ah_cal_list; \ | ||
659 | } \ | ||
660 | } while (0) | ||
661 | |||
662 | enum hal_cal_types { | ||
663 | ADC_DC_INIT_CAL = 0x1, | ||
664 | ADC_GAIN_CAL = 0x2, | ||
665 | ADC_DC_CAL = 0x4, | ||
666 | IQ_MISMATCH_CAL = 0x8 | ||
667 | }; | ||
668 | |||
669 | enum hal_cal_state { | ||
670 | CAL_INACTIVE, | ||
671 | CAL_WAITING, | ||
672 | CAL_RUNNING, | ||
673 | CAL_DONE | ||
674 | }; | ||
675 | |||
676 | #define MIN_CAL_SAMPLES 1 | ||
677 | #define MAX_CAL_SAMPLES 64 | ||
678 | #define INIT_LOG_COUNT 5 | ||
679 | #define PER_MIN_LOG_COUNT 2 | ||
680 | #define PER_MAX_LOG_COUNT 10 | ||
681 | |||
682 | struct hal_percal_data { | ||
683 | enum hal_cal_types calType; | ||
684 | u32 calNumSamples; | ||
685 | u32 calCountMax; | ||
686 | void (*calCollect) (struct ath_hal *); | ||
687 | void (*calPostProc) (struct ath_hal *, u8); | ||
688 | }; | ||
689 | |||
690 | struct hal_cal_list { | ||
691 | const struct hal_percal_data *calData; | ||
692 | enum hal_cal_state calState; | ||
693 | struct hal_cal_list *calNext; | ||
694 | }; | ||
695 | |||
696 | struct ath_hal_5416 { | ||
697 | struct ath_hal ah; | ||
698 | struct ar5416_eeprom ah_eeprom; | ||
699 | u8 ah_macaddr[ETH_ALEN]; | ||
700 | u8 ah_bssid[ETH_ALEN]; | ||
701 | u8 ah_bssidmask[ETH_ALEN]; | ||
702 | u16 ah_assocId; | ||
703 | int16_t ah_curchanRadIndex; | ||
704 | u32 ah_maskReg; | ||
705 | struct ar5416Stats ah_stats; | ||
706 | u32 ah_txDescMask; | ||
707 | u32 ah_txOkInterruptMask; | ||
708 | u32 ah_txErrInterruptMask; | ||
709 | u32 ah_txDescInterruptMask; | ||
710 | u32 ah_txEolInterruptMask; | ||
711 | u32 ah_txUrnInterruptMask; | ||
712 | struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES]; | ||
713 | enum ath9k_power_mode ah_powerMode; | ||
714 | bool ah_chipFullSleep; | ||
715 | u32 ah_atimWindow; | ||
716 | enum ath9k_ant_setting ah_diversityControl; | ||
717 | u16 ah_antennaSwitchSwap; | ||
718 | enum hal_cal_types ah_suppCals; | ||
719 | struct hal_cal_list ah_iqCalData; | ||
720 | struct hal_cal_list ah_adcGainCalData; | ||
721 | struct hal_cal_list ah_adcDcCalInitData; | ||
722 | struct hal_cal_list ah_adcDcCalData; | ||
723 | struct hal_cal_list *ah_cal_list; | ||
724 | struct hal_cal_list *ah_cal_list_last; | ||
725 | struct hal_cal_list *ah_cal_list_curr; | ||
726 | #define ah_totalPowerMeasI ah_Meas0.unsign | ||
727 | #define ah_totalPowerMeasQ ah_Meas1.unsign | ||
728 | #define ah_totalIqCorrMeas ah_Meas2.sign | ||
729 | #define ah_totalAdcIOddPhase ah_Meas0.unsign | ||
730 | #define ah_totalAdcIEvenPhase ah_Meas1.unsign | ||
731 | #define ah_totalAdcQOddPhase ah_Meas2.unsign | ||
732 | #define ah_totalAdcQEvenPhase ah_Meas3.unsign | ||
733 | #define ah_totalAdcDcOffsetIOddPhase ah_Meas0.sign | ||
734 | #define ah_totalAdcDcOffsetIEvenPhase ah_Meas1.sign | ||
735 | #define ah_totalAdcDcOffsetQOddPhase ah_Meas2.sign | ||
736 | #define ah_totalAdcDcOffsetQEvenPhase ah_Meas3.sign | ||
737 | union { | ||
738 | u32 unsign[AR5416_MAX_CHAINS]; | ||
739 | int32_t sign[AR5416_MAX_CHAINS]; | ||
740 | } ah_Meas0; | ||
741 | union { | ||
742 | u32 unsign[AR5416_MAX_CHAINS]; | ||
743 | int32_t sign[AR5416_MAX_CHAINS]; | ||
744 | } ah_Meas1; | ||
745 | union { | ||
746 | u32 unsign[AR5416_MAX_CHAINS]; | ||
747 | int32_t sign[AR5416_MAX_CHAINS]; | ||
748 | } ah_Meas2; | ||
749 | union { | ||
750 | u32 unsign[AR5416_MAX_CHAINS]; | ||
751 | int32_t sign[AR5416_MAX_CHAINS]; | ||
752 | } ah_Meas3; | ||
753 | u16 ah_CalSamples; | ||
754 | u32 ah_tx6PowerInHalfDbm; | ||
755 | u32 ah_staId1Defaults; | ||
756 | u32 ah_miscMode; | ||
757 | bool ah_tpcEnabled; | ||
758 | u32 ah_beaconInterval; | ||
759 | enum { | ||
760 | AUTO_32KHZ, | ||
761 | USE_32KHZ, | ||
762 | DONT_USE_32KHZ, | ||
763 | } ah_enable32kHzClock; | ||
764 | u32 *ah_analogBank0Data; | ||
765 | u32 *ah_analogBank1Data; | ||
766 | u32 *ah_analogBank2Data; | ||
767 | u32 *ah_analogBank3Data; | ||
768 | u32 *ah_analogBank6Data; | ||
769 | u32 *ah_analogBank6TPCData; | ||
770 | u32 *ah_analogBank7Data; | ||
771 | u32 *ah_addac5416_21; | ||
772 | u32 *ah_bank6Temp; | ||
773 | u32 ah_ofdmTxPower; | ||
774 | int16_t ah_txPowerIndexOffset; | ||
775 | u32 ah_slottime; | ||
776 | u32 ah_acktimeout; | ||
777 | u32 ah_ctstimeout; | ||
778 | u32 ah_globaltxtimeout; | ||
779 | u8 ah_gBeaconRate; | ||
780 | u32 ah_gpioSelect; | ||
781 | u32 ah_polarity; | ||
782 | u32 ah_gpioBit; | ||
783 | bool ah_eepEnabled; | ||
784 | u32 ah_procPhyErr; | ||
785 | bool ah_hasHwPhyCounters; | ||
786 | u32 ah_aniPeriod; | ||
787 | struct ar5416AniState *ah_curani; | ||
788 | struct ar5416AniState ah_ani[255]; | ||
789 | int ah_totalSizeDesired[5]; | ||
790 | int ah_coarseHigh[5]; | ||
791 | int ah_coarseLow[5]; | ||
792 | int ah_firpwr[5]; | ||
793 | u16 ah_ratesArray[16]; | ||
794 | u32 ah_intrTxqs; | ||
795 | bool ah_intrMitigation; | ||
796 | u32 ah_cycleCount; | ||
797 | u32 ah_ctlBusy; | ||
798 | u32 ah_extBusy; | ||
799 | enum ath9k_ht_extprotspacing ah_extprotspacing; | ||
800 | u8 ah_txchainmask; | ||
801 | u8 ah_rxchainmask; | ||
802 | int ah_hwp; | ||
803 | void __iomem *ah_cal_mem; | ||
804 | enum ath9k_ani_cmd ah_ani_function; | ||
805 | struct ar5416IniArray ah_iniModes; | ||
806 | struct ar5416IniArray ah_iniCommon; | ||
807 | struct ar5416IniArray ah_iniBank0; | ||
808 | struct ar5416IniArray ah_iniBB_RfGain; | ||
809 | struct ar5416IniArray ah_iniBank1; | ||
810 | struct ar5416IniArray ah_iniBank2; | ||
811 | struct ar5416IniArray ah_iniBank3; | ||
812 | struct ar5416IniArray ah_iniBank6; | ||
813 | struct ar5416IniArray ah_iniBank6TPC; | ||
814 | struct ar5416IniArray ah_iniBank7; | ||
815 | struct ar5416IniArray ah_iniAddac; | ||
816 | struct ar5416IniArray ah_iniPcieSerdes; | ||
817 | struct ar5416IniArray ah_iniModesAdditional; | ||
818 | }; | ||
819 | #define AH5416(_ah) ((struct ath_hal_5416 *)(_ah)) | ||
820 | |||
821 | #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) | ||
822 | |||
823 | #define IS_5416_EMU(ah) \ | ||
824 | ((ah->ah_devid == AR5416_DEVID_EMU) || \ | ||
825 | (ah->ah_devid == AR5416_DEVID_EMU_PCIE)) | ||
826 | |||
827 | #define ar5416RfDetach(ah) do { \ | ||
828 | if (AH5416(ah)->ah_rfHal.rfDetach != NULL) \ | ||
829 | AH5416(ah)->ah_rfHal.rfDetach(ah); \ | ||
830 | } while (0) | ||
831 | |||
832 | #define ath9k_hw_use_flash(_ah) \ | ||
833 | (!(_ah->ah_flags & AH_USE_EEPROM)) | ||
834 | |||
835 | |||
836 | #define DO_DELAY(x) do { \ | ||
837 | if ((++(x) % 64) == 0) \ | ||
838 | udelay(1); \ | ||
839 | } while (0) | ||
840 | |||
841 | #define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ | ||
842 | int r; \ | ||
843 | for (r = 0; r < ((iniarray)->ia_rows); r++) { \ | ||
844 | REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ | ||
845 | INI_RA((iniarray), r, (column))); \ | ||
846 | DO_DELAY(regWr); \ | ||
847 | } \ | ||
848 | } while (0) | ||
849 | |||
850 | #define BASE_ACTIVATE_DELAY 100 | ||
851 | #define RTC_PLL_SETTLE_DELAY 1000 | ||
852 | #define COEF_SCALE_S 24 | ||
853 | #define HT40_CHANNEL_CENTER_SHIFT 10 | ||
854 | |||
855 | #define ar5416CheckOpMode(_opmode) \ | ||
856 | ((_opmode == ATH9K_M_STA) || (_opmode == ATH9K_M_IBSS) || \ | ||
857 | (_opmode == ATH9K_M_HOSTAP) || (_opmode == ATH9K_M_MONITOR)) | ||
858 | |||
859 | #define AR5416_EEPROM_MAGIC_OFFSET 0x0 | ||
860 | |||
861 | #define AR5416_EEPROM_S 2 | ||
862 | #define AR5416_EEPROM_OFFSET 0x2000 | ||
863 | #define AR5416_EEPROM_START_ADDR \ | ||
864 | (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200 | ||
865 | #define AR5416_EEPROM_MAX 0xae0 | ||
866 | #define ar5416_get_eep_ver(_ahp) \ | ||
867 | (((_ahp)->ah_eeprom.baseEepHeader.version >> 12) & 0xF) | ||
868 | #define ar5416_get_eep_rev(_ahp) \ | ||
869 | (((_ahp)->ah_eeprom.baseEepHeader.version) & 0xFFF) | ||
870 | #define ar5416_get_ntxchains(_txchainmask) \ | ||
871 | (((_txchainmask >> 2) & 1) + \ | ||
872 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) | ||
873 | |||
874 | #define IS_EEP_MINOR_V3(_ahp) \ | ||
875 | (ath9k_hw_get_eeprom((_ahp), EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_3) | ||
876 | |||
877 | #define FIXED_CCA_THRESHOLD 15 | ||
878 | |||
879 | #ifdef __BIG_ENDIAN | ||
880 | #define AR5416_EEPROM_MAGIC 0x5aa5 | ||
881 | #else | ||
882 | #define AR5416_EEPROM_MAGIC 0xa55a | ||
883 | #endif | ||
884 | |||
885 | #define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) | ||
886 | |||
887 | #define ATH9K_ANTENNA0_CHAINMASK 0x1 | ||
888 | #define ATH9K_ANTENNA1_CHAINMASK 0x2 | ||
889 | |||
890 | #define ATH9K_NUM_DMA_DEBUG_REGS 8 | ||
891 | #define ATH9K_NUM_QUEUES 10 | ||
892 | |||
893 | #define HAL_NOISE_IMMUNE_MAX 4 | ||
894 | #define HAL_SPUR_IMMUNE_MAX 7 | ||
895 | #define HAL_FIRST_STEP_MAX 2 | ||
896 | |||
897 | #define ATH9K_ANI_OFDM_TRIG_HIGH 500 | ||
898 | #define ATH9K_ANI_OFDM_TRIG_LOW 200 | ||
899 | #define ATH9K_ANI_CCK_TRIG_HIGH 200 | ||
900 | #define ATH9K_ANI_CCK_TRIG_LOW 100 | ||
901 | #define ATH9K_ANI_NOISE_IMMUNE_LVL 4 | ||
902 | #define ATH9K_ANI_USE_OFDM_WEAK_SIG true | ||
903 | #define ATH9K_ANI_CCK_WEAK_SIG_THR false | ||
904 | #define ATH9K_ANI_SPUR_IMMUNE_LVL 7 | ||
905 | #define ATH9K_ANI_FIRSTEP_LVL 0 | ||
906 | #define ATH9K_ANI_RSSI_THR_HIGH 40 | ||
907 | #define ATH9K_ANI_RSSI_THR_LOW 7 | ||
908 | #define ATH9K_ANI_PERIOD 100 | ||
909 | |||
910 | #define AR_GPIOD_MASK 0x00001FFF | ||
911 | #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) | ||
912 | |||
913 | #define MAX_ANALOG_START 319 | ||
914 | |||
915 | #define HAL_EP_RND(x, mul) \ | ||
916 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | ||
917 | #define BEACON_RSSI(ahp) \ | ||
918 | HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \ | ||
919 | ATH9K_RSSI_EP_MULTIPLIER) | ||
920 | |||
921 | #define ah_mibStats ah_stats.ast_mibstats | ||
922 | |||
923 | #define AH_TIMEOUT 100000 | ||
924 | #define AH_TIME_QUANTUM 10 | ||
925 | |||
926 | #define IS(_c, _f) (((_c)->channelFlags & _f) || 0) | ||
927 | |||
928 | #define AR_KEYTABLE_SIZE 128 | ||
929 | #define POWER_UP_TIME 200000 | ||
930 | |||
931 | #define EXT_ADDITIVE (0x8000) | ||
932 | #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) | ||
933 | #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) | ||
934 | #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) | ||
935 | |||
936 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 | ||
937 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 | ||
938 | #define SPUR_RSSI_THRESH 40 | ||
939 | |||
940 | #define TU_TO_USEC(_tu) ((_tu) << 10) | ||
941 | |||
942 | #define CAB_TIMEOUT_VAL 10 | ||
943 | #define BEACON_TIMEOUT_VAL 10 | ||
944 | #define MIN_BEACON_TIMEOUT_VAL 1 | ||
945 | #define SLEEP_SLOP 3 | ||
946 | |||
947 | #define CCK_SIFS_TIME 10 | ||
948 | #define CCK_PREAMBLE_BITS 144 | ||
949 | #define CCK_PLCP_BITS 48 | ||
950 | |||
951 | #define OFDM_SIFS_TIME 16 | ||
952 | #define OFDM_PREAMBLE_TIME 20 | ||
953 | #define OFDM_PLCP_BITS 22 | ||
954 | #define OFDM_SYMBOL_TIME 4 | ||
955 | |||
956 | #define OFDM_SIFS_TIME_HALF 32 | ||
957 | #define OFDM_PREAMBLE_TIME_HALF 40 | ||
958 | #define OFDM_PLCP_BITS_HALF 22 | ||
959 | #define OFDM_SYMBOL_TIME_HALF 8 | ||
960 | |||
961 | #define OFDM_SIFS_TIME_QUARTER 64 | ||
962 | #define OFDM_PREAMBLE_TIME_QUARTER 80 | ||
963 | #define OFDM_PLCP_BITS_QUARTER 22 | ||
964 | #define OFDM_SYMBOL_TIME_QUARTER 16 | ||
965 | |||
966 | u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp, | ||
967 | enum eeprom_param param); | ||
968 | |||
969 | #endif | ||
diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h new file mode 100644 index 00000000000..3dd3815940a --- /dev/null +++ b/drivers/net/wireless/ath9k/initvals.h | |||
@@ -0,0 +1,3146 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | static const u32 ar5416Modes_9100[][6] = { | ||
18 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | ||
19 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | ||
20 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, | ||
21 | { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, | ||
22 | { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, | ||
23 | { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, | ||
24 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, | ||
25 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, | ||
26 | { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
27 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, | ||
28 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
29 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, | ||
30 | { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, | ||
31 | { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | ||
32 | { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | ||
33 | { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | ||
34 | { 0x00009850, 0x6de8b4e0, 0x6de8b4e0, 0x6de8b0de, 0x6de8b0de, 0x6de8b0de }, | ||
35 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, | ||
36 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, | ||
37 | { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, | ||
38 | { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | ||
39 | { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, | ||
40 | { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, | ||
41 | { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, | ||
42 | { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, | ||
43 | { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, | ||
44 | { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, | ||
45 | { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, | ||
46 | { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, | ||
47 | { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, | ||
48 | { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, | ||
49 | { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, | ||
50 | { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, | ||
51 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | ||
52 | { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, | ||
53 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, | ||
54 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, | ||
55 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
56 | { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
57 | { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, | ||
58 | { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, | ||
59 | { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, | ||
60 | { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, | ||
61 | { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, | ||
62 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, | ||
63 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | ||
64 | { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, | ||
65 | { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, | ||
66 | { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, | ||
67 | { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, | ||
68 | { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, | ||
69 | { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, | ||
70 | { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, | ||
71 | { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, | ||
72 | { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, | ||
73 | { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, | ||
74 | { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, | ||
75 | { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, | ||
76 | { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
77 | { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
78 | { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
79 | }; | ||
80 | |||
81 | static const u32 ar5416Common_9100[][2] = { | ||
82 | { 0x0000000c, 0x00000000 }, | ||
83 | { 0x00000030, 0x00020015 }, | ||
84 | { 0x00000034, 0x00000005 }, | ||
85 | { 0x00000040, 0x00000000 }, | ||
86 | { 0x00000044, 0x00000008 }, | ||
87 | { 0x00000048, 0x00000008 }, | ||
88 | { 0x0000004c, 0x00000010 }, | ||
89 | { 0x00000050, 0x00000000 }, | ||
90 | { 0x00000054, 0x0000001f }, | ||
91 | { 0x00000800, 0x00000000 }, | ||
92 | { 0x00000804, 0x00000000 }, | ||
93 | { 0x00000808, 0x00000000 }, | ||
94 | { 0x0000080c, 0x00000000 }, | ||
95 | { 0x00000810, 0x00000000 }, | ||
96 | { 0x00000814, 0x00000000 }, | ||
97 | { 0x00000818, 0x00000000 }, | ||
98 | { 0x0000081c, 0x00000000 }, | ||
99 | { 0x00000820, 0x00000000 }, | ||
100 | { 0x00000824, 0x00000000 }, | ||
101 | { 0x00001040, 0x002ffc0f }, | ||
102 | { 0x00001044, 0x002ffc0f }, | ||
103 | { 0x00001048, 0x002ffc0f }, | ||
104 | { 0x0000104c, 0x002ffc0f }, | ||
105 | { 0x00001050, 0x002ffc0f }, | ||
106 | { 0x00001054, 0x002ffc0f }, | ||
107 | { 0x00001058, 0x002ffc0f }, | ||
108 | { 0x0000105c, 0x002ffc0f }, | ||
109 | { 0x00001060, 0x002ffc0f }, | ||
110 | { 0x00001064, 0x002ffc0f }, | ||
111 | { 0x00001230, 0x00000000 }, | ||
112 | { 0x00001270, 0x00000000 }, | ||
113 | { 0x00001038, 0x00000000 }, | ||
114 | { 0x00001078, 0x00000000 }, | ||
115 | { 0x000010b8, 0x00000000 }, | ||
116 | { 0x000010f8, 0x00000000 }, | ||
117 | { 0x00001138, 0x00000000 }, | ||
118 | { 0x00001178, 0x00000000 }, | ||
119 | { 0x000011b8, 0x00000000 }, | ||
120 | { 0x000011f8, 0x00000000 }, | ||
121 | { 0x00001238, 0x00000000 }, | ||
122 | { 0x00001278, 0x00000000 }, | ||
123 | { 0x000012b8, 0x00000000 }, | ||
124 | { 0x000012f8, 0x00000000 }, | ||
125 | { 0x00001338, 0x00000000 }, | ||
126 | { 0x00001378, 0x00000000 }, | ||
127 | { 0x000013b8, 0x00000000 }, | ||
128 | { 0x000013f8, 0x00000000 }, | ||
129 | { 0x00001438, 0x00000000 }, | ||
130 | { 0x00001478, 0x00000000 }, | ||
131 | { 0x000014b8, 0x00000000 }, | ||
132 | { 0x000014f8, 0x00000000 }, | ||
133 | { 0x00001538, 0x00000000 }, | ||
134 | { 0x00001578, 0x00000000 }, | ||
135 | { 0x000015b8, 0x00000000 }, | ||
136 | { 0x000015f8, 0x00000000 }, | ||
137 | { 0x00001638, 0x00000000 }, | ||
138 | { 0x00001678, 0x00000000 }, | ||
139 | { 0x000016b8, 0x00000000 }, | ||
140 | { 0x000016f8, 0x00000000 }, | ||
141 | { 0x00001738, 0x00000000 }, | ||
142 | { 0x00001778, 0x00000000 }, | ||
143 | { 0x000017b8, 0x00000000 }, | ||
144 | { 0x000017f8, 0x00000000 }, | ||
145 | { 0x0000103c, 0x00000000 }, | ||
146 | { 0x0000107c, 0x00000000 }, | ||
147 | { 0x000010bc, 0x00000000 }, | ||
148 | { 0x000010fc, 0x00000000 }, | ||
149 | { 0x0000113c, 0x00000000 }, | ||
150 | { 0x0000117c, 0x00000000 }, | ||
151 | { 0x000011bc, 0x00000000 }, | ||
152 | { 0x000011fc, 0x00000000 }, | ||
153 | { 0x0000123c, 0x00000000 }, | ||
154 | { 0x0000127c, 0x00000000 }, | ||
155 | { 0x000012bc, 0x00000000 }, | ||
156 | { 0x000012fc, 0x00000000 }, | ||
157 | { 0x0000133c, 0x00000000 }, | ||
158 | { 0x0000137c, 0x00000000 }, | ||
159 | { 0x000013bc, 0x00000000 }, | ||
160 | { 0x000013fc, 0x00000000 }, | ||
161 | { 0x0000143c, 0x00000000 }, | ||
162 | { 0x0000147c, 0x00000000 }, | ||
163 | { 0x00004030, 0x00000002 }, | ||
164 | { 0x0000403c, 0x00000002 }, | ||
165 | { 0x00007010, 0x00000000 }, | ||
166 | { 0x00007038, 0x000004c2 }, | ||
167 | { 0x00008004, 0x00000000 }, | ||
168 | { 0x00008008, 0x00000000 }, | ||
169 | { 0x0000800c, 0x00000000 }, | ||
170 | { 0x00008018, 0x00000700 }, | ||
171 | { 0x00008020, 0x00000000 }, | ||
172 | { 0x00008038, 0x00000000 }, | ||
173 | { 0x0000803c, 0x00000000 }, | ||
174 | { 0x00008048, 0x40000000 }, | ||
175 | { 0x00008054, 0x00000000 }, | ||
176 | { 0x00008058, 0x00000000 }, | ||
177 | { 0x0000805c, 0x000fc78f }, | ||
178 | { 0x00008060, 0x0000000f }, | ||
179 | { 0x00008064, 0x00000000 }, | ||
180 | { 0x000080c0, 0x2a82301a }, | ||
181 | { 0x000080c4, 0x05dc01e0 }, | ||
182 | { 0x000080c8, 0x1f402710 }, | ||
183 | { 0x000080cc, 0x01f40000 }, | ||
184 | { 0x000080d0, 0x00001e00 }, | ||
185 | { 0x000080d4, 0x00000000 }, | ||
186 | { 0x000080d8, 0x00400000 }, | ||
187 | { 0x000080e0, 0xffffffff }, | ||
188 | { 0x000080e4, 0x0000ffff }, | ||
189 | { 0x000080e8, 0x003f3f3f }, | ||
190 | { 0x000080ec, 0x00000000 }, | ||
191 | { 0x000080f0, 0x00000000 }, | ||
192 | { 0x000080f4, 0x00000000 }, | ||
193 | { 0x000080f8, 0x00000000 }, | ||
194 | { 0x000080fc, 0x00020000 }, | ||
195 | { 0x00008100, 0x00020000 }, | ||
196 | { 0x00008104, 0x00000001 }, | ||
197 | { 0x00008108, 0x00000052 }, | ||
198 | { 0x0000810c, 0x00000000 }, | ||
199 | { 0x00008110, 0x00000168 }, | ||
200 | { 0x00008118, 0x000100aa }, | ||
201 | { 0x0000811c, 0x00003210 }, | ||
202 | { 0x00008120, 0x08f04800 }, | ||
203 | { 0x00008124, 0x00000000 }, | ||
204 | { 0x00008128, 0x00000000 }, | ||
205 | { 0x0000812c, 0x00000000 }, | ||
206 | { 0x00008130, 0x00000000 }, | ||
207 | { 0x00008134, 0x00000000 }, | ||
208 | { 0x00008138, 0x00000000 }, | ||
209 | { 0x0000813c, 0x00000000 }, | ||
210 | { 0x00008144, 0x00000000 }, | ||
211 | { 0x00008168, 0x00000000 }, | ||
212 | { 0x0000816c, 0x00000000 }, | ||
213 | { 0x00008170, 0x32143320 }, | ||
214 | { 0x00008174, 0xfaa4fa50 }, | ||
215 | { 0x00008178, 0x00000100 }, | ||
216 | { 0x0000817c, 0x00000000 }, | ||
217 | { 0x000081c4, 0x00000000 }, | ||
218 | { 0x000081d0, 0x00003210 }, | ||
219 | { 0x000081ec, 0x00000000 }, | ||
220 | { 0x000081f0, 0x00000000 }, | ||
221 | { 0x000081f4, 0x00000000 }, | ||
222 | { 0x000081f8, 0x00000000 }, | ||
223 | { 0x000081fc, 0x00000000 }, | ||
224 | { 0x00008200, 0x00000000 }, | ||
225 | { 0x00008204, 0x00000000 }, | ||
226 | { 0x00008208, 0x00000000 }, | ||
227 | { 0x0000820c, 0x00000000 }, | ||
228 | { 0x00008210, 0x00000000 }, | ||
229 | { 0x00008214, 0x00000000 }, | ||
230 | { 0x00008218, 0x00000000 }, | ||
231 | { 0x0000821c, 0x00000000 }, | ||
232 | { 0x00008220, 0x00000000 }, | ||
233 | { 0x00008224, 0x00000000 }, | ||
234 | { 0x00008228, 0x00000000 }, | ||
235 | { 0x0000822c, 0x00000000 }, | ||
236 | { 0x00008230, 0x00000000 }, | ||
237 | { 0x00008234, 0x00000000 }, | ||
238 | { 0x00008238, 0x00000000 }, | ||
239 | { 0x0000823c, 0x00000000 }, | ||
240 | { 0x00008240, 0x00100000 }, | ||
241 | { 0x00008244, 0x0010f400 }, | ||
242 | { 0x00008248, 0x00000100 }, | ||
243 | { 0x0000824c, 0x0001e800 }, | ||
244 | { 0x00008250, 0x00000000 }, | ||
245 | { 0x00008254, 0x00000000 }, | ||
246 | { 0x00008258, 0x00000000 }, | ||
247 | { 0x0000825c, 0x400000ff }, | ||
248 | { 0x00008260, 0x00080922 }, | ||
249 | { 0x00008270, 0x00000000 }, | ||
250 | { 0x00008274, 0x40000000 }, | ||
251 | { 0x00008278, 0x003e4180 }, | ||
252 | { 0x0000827c, 0x00000000 }, | ||
253 | { 0x00008284, 0x0000002c }, | ||
254 | { 0x00008288, 0x0000002c }, | ||
255 | { 0x0000828c, 0x00000000 }, | ||
256 | { 0x00008294, 0x00000000 }, | ||
257 | { 0x00008298, 0x00000000 }, | ||
258 | { 0x00008300, 0x00000000 }, | ||
259 | { 0x00008304, 0x00000000 }, | ||
260 | { 0x00008308, 0x00000000 }, | ||
261 | { 0x0000830c, 0x00000000 }, | ||
262 | { 0x00008310, 0x00000000 }, | ||
263 | { 0x00008314, 0x00000000 }, | ||
264 | { 0x00008318, 0x00000000 }, | ||
265 | { 0x00008328, 0x00000000 }, | ||
266 | { 0x0000832c, 0x00000007 }, | ||
267 | { 0x00008330, 0x00000302 }, | ||
268 | { 0x00008334, 0x00000e00 }, | ||
269 | { 0x00008338, 0x00000000 }, | ||
270 | { 0x0000833c, 0x00000000 }, | ||
271 | { 0x00008340, 0x000107ff }, | ||
272 | { 0x00009808, 0x00000000 }, | ||
273 | { 0x0000980c, 0xad848e19 }, | ||
274 | { 0x00009810, 0x7d14e000 }, | ||
275 | { 0x00009814, 0x9c0a9f6b }, | ||
276 | { 0x0000981c, 0x00000000 }, | ||
277 | { 0x0000982c, 0x0000a000 }, | ||
278 | { 0x00009830, 0x00000000 }, | ||
279 | { 0x0000983c, 0x00200400 }, | ||
280 | { 0x00009840, 0x206a002e }, | ||
281 | { 0x0000984c, 0x1284233c }, | ||
282 | { 0x00009854, 0x00000859 }, | ||
283 | { 0x00009900, 0x00000000 }, | ||
284 | { 0x00009904, 0x00000000 }, | ||
285 | { 0x00009908, 0x00000000 }, | ||
286 | { 0x0000990c, 0x00000000 }, | ||
287 | { 0x0000991c, 0x10000fff }, | ||
288 | { 0x00009920, 0x05100000 }, | ||
289 | { 0x0000a920, 0x05100000 }, | ||
290 | { 0x0000b920, 0x05100000 }, | ||
291 | { 0x00009928, 0x00000001 }, | ||
292 | { 0x0000992c, 0x00000004 }, | ||
293 | { 0x00009934, 0x1e1f2022 }, | ||
294 | { 0x00009938, 0x0a0b0c0d }, | ||
295 | { 0x0000993c, 0x00000000 }, | ||
296 | { 0x00009948, 0x9280b212 }, | ||
297 | { 0x0000994c, 0x00020028 }, | ||
298 | { 0x00009954, 0x5d50e188 }, | ||
299 | { 0x00009958, 0x00081fff }, | ||
300 | { 0x0000c95c, 0x004b6a8e }, | ||
301 | { 0x0000c968, 0x000003ce }, | ||
302 | { 0x00009970, 0x190fb515 }, | ||
303 | { 0x00009974, 0x00000000 }, | ||
304 | { 0x00009978, 0x00000001 }, | ||
305 | { 0x0000997c, 0x00000000 }, | ||
306 | { 0x00009980, 0x00000000 }, | ||
307 | { 0x00009984, 0x00000000 }, | ||
308 | { 0x00009988, 0x00000000 }, | ||
309 | { 0x0000998c, 0x00000000 }, | ||
310 | { 0x00009990, 0x00000000 }, | ||
311 | { 0x00009994, 0x00000000 }, | ||
312 | { 0x00009998, 0x00000000 }, | ||
313 | { 0x0000999c, 0x00000000 }, | ||
314 | { 0x000099a0, 0x00000000 }, | ||
315 | { 0x000099a4, 0x00000001 }, | ||
316 | { 0x000099a8, 0x001fff00 }, | ||
317 | { 0x000099ac, 0x00000000 }, | ||
318 | { 0x000099b0, 0x03051000 }, | ||
319 | { 0x000099dc, 0x00000000 }, | ||
320 | { 0x000099e0, 0x00000200 }, | ||
321 | { 0x000099e4, 0xaaaaaaaa }, | ||
322 | { 0x000099e8, 0x3c466478 }, | ||
323 | { 0x000099ec, 0x000000aa }, | ||
324 | { 0x000099fc, 0x00001042 }, | ||
325 | { 0x00009b00, 0x00000000 }, | ||
326 | { 0x00009b04, 0x00000001 }, | ||
327 | { 0x00009b08, 0x00000002 }, | ||
328 | { 0x00009b0c, 0x00000003 }, | ||
329 | { 0x00009b10, 0x00000004 }, | ||
330 | { 0x00009b14, 0x00000005 }, | ||
331 | { 0x00009b18, 0x00000008 }, | ||
332 | { 0x00009b1c, 0x00000009 }, | ||
333 | { 0x00009b20, 0x0000000a }, | ||
334 | { 0x00009b24, 0x0000000b }, | ||
335 | { 0x00009b28, 0x0000000c }, | ||
336 | { 0x00009b2c, 0x0000000d }, | ||
337 | { 0x00009b30, 0x00000010 }, | ||
338 | { 0x00009b34, 0x00000011 }, | ||
339 | { 0x00009b38, 0x00000012 }, | ||
340 | { 0x00009b3c, 0x00000013 }, | ||
341 | { 0x00009b40, 0x00000014 }, | ||
342 | { 0x00009b44, 0x00000015 }, | ||
343 | { 0x00009b48, 0x00000018 }, | ||
344 | { 0x00009b4c, 0x00000019 }, | ||
345 | { 0x00009b50, 0x0000001a }, | ||
346 | { 0x00009b54, 0x0000001b }, | ||
347 | { 0x00009b58, 0x0000001c }, | ||
348 | { 0x00009b5c, 0x0000001d }, | ||
349 | { 0x00009b60, 0x00000020 }, | ||
350 | { 0x00009b64, 0x00000021 }, | ||
351 | { 0x00009b68, 0x00000022 }, | ||
352 | { 0x00009b6c, 0x00000023 }, | ||
353 | { 0x00009b70, 0x00000024 }, | ||
354 | { 0x00009b74, 0x00000025 }, | ||
355 | { 0x00009b78, 0x00000028 }, | ||
356 | { 0x00009b7c, 0x00000029 }, | ||
357 | { 0x00009b80, 0x0000002a }, | ||
358 | { 0x00009b84, 0x0000002b }, | ||
359 | { 0x00009b88, 0x0000002c }, | ||
360 | { 0x00009b8c, 0x0000002d }, | ||
361 | { 0x00009b90, 0x00000030 }, | ||
362 | { 0x00009b94, 0x00000031 }, | ||
363 | { 0x00009b98, 0x00000032 }, | ||
364 | { 0x00009b9c, 0x00000033 }, | ||
365 | { 0x00009ba0, 0x00000034 }, | ||
366 | { 0x00009ba4, 0x00000035 }, | ||
367 | { 0x00009ba8, 0x00000035 }, | ||
368 | { 0x00009bac, 0x00000035 }, | ||
369 | { 0x00009bb0, 0x00000035 }, | ||
370 | { 0x00009bb4, 0x00000035 }, | ||
371 | { 0x00009bb8, 0x00000035 }, | ||
372 | { 0x00009bbc, 0x00000035 }, | ||
373 | { 0x00009bc0, 0x00000035 }, | ||
374 | { 0x00009bc4, 0x00000035 }, | ||
375 | { 0x00009bc8, 0x00000035 }, | ||
376 | { 0x00009bcc, 0x00000035 }, | ||
377 | { 0x00009bd0, 0x00000035 }, | ||
378 | { 0x00009bd4, 0x00000035 }, | ||
379 | { 0x00009bd8, 0x00000035 }, | ||
380 | { 0x00009bdc, 0x00000035 }, | ||
381 | { 0x00009be0, 0x00000035 }, | ||
382 | { 0x00009be4, 0x00000035 }, | ||
383 | { 0x00009be8, 0x00000035 }, | ||
384 | { 0x00009bec, 0x00000035 }, | ||
385 | { 0x00009bf0, 0x00000035 }, | ||
386 | { 0x00009bf4, 0x00000035 }, | ||
387 | { 0x00009bf8, 0x00000010 }, | ||
388 | { 0x00009bfc, 0x0000001a }, | ||
389 | { 0x0000a210, 0x40806333 }, | ||
390 | { 0x0000a214, 0x00106c10 }, | ||
391 | { 0x0000a218, 0x009c4060 }, | ||
392 | { 0x0000a220, 0x018830c6 }, | ||
393 | { 0x0000a224, 0x00000400 }, | ||
394 | { 0x0000a228, 0x00000bb5 }, | ||
395 | { 0x0000a22c, 0x00000011 }, | ||
396 | { 0x0000a234, 0x20202020 }, | ||
397 | { 0x0000a238, 0x20202020 }, | ||
398 | { 0x0000a23c, 0x13c889af }, | ||
399 | { 0x0000a240, 0x38490a20 }, | ||
400 | { 0x0000a244, 0x00007bb6 }, | ||
401 | { 0x0000a248, 0x0fff3ffc }, | ||
402 | { 0x0000a24c, 0x00000001 }, | ||
403 | { 0x0000a250, 0x0000a000 }, | ||
404 | { 0x0000a254, 0x00000000 }, | ||
405 | { 0x0000a258, 0x0cc75380 }, | ||
406 | { 0x0000a25c, 0x0f0f0f01 }, | ||
407 | { 0x0000a260, 0xdfa91f01 }, | ||
408 | { 0x0000a268, 0x00000000 }, | ||
409 | { 0x0000a26c, 0x0ebae9c6 }, | ||
410 | { 0x0000b26c, 0x0ebae9c6 }, | ||
411 | { 0x0000c26c, 0x0ebae9c6 }, | ||
412 | { 0x0000d270, 0x00820820 }, | ||
413 | { 0x0000a278, 0x1ce739ce }, | ||
414 | { 0x0000a27c, 0x051701ce }, | ||
415 | { 0x0000a338, 0x00000000 }, | ||
416 | { 0x0000a33c, 0x00000000 }, | ||
417 | { 0x0000a340, 0x00000000 }, | ||
418 | { 0x0000a344, 0x00000000 }, | ||
419 | { 0x0000a348, 0x3fffffff }, | ||
420 | { 0x0000a34c, 0x3fffffff }, | ||
421 | { 0x0000a350, 0x3fffffff }, | ||
422 | { 0x0000a354, 0x0003ffff }, | ||
423 | { 0x0000a358, 0x79a8aa1f }, | ||
424 | { 0x0000d35c, 0x07ffffef }, | ||
425 | { 0x0000d360, 0x0fffffe7 }, | ||
426 | { 0x0000d364, 0x17ffffe5 }, | ||
427 | { 0x0000d368, 0x1fffffe4 }, | ||
428 | { 0x0000d36c, 0x37ffffe3 }, | ||
429 | { 0x0000d370, 0x3fffffe3 }, | ||
430 | { 0x0000d374, 0x57ffffe3 }, | ||
431 | { 0x0000d378, 0x5fffffe2 }, | ||
432 | { 0x0000d37c, 0x7fffffe2 }, | ||
433 | { 0x0000d380, 0x7f3c7bba }, | ||
434 | { 0x0000d384, 0xf3307ff0 }, | ||
435 | { 0x0000a388, 0x08000000 }, | ||
436 | { 0x0000a38c, 0x20202020 }, | ||
437 | { 0x0000a390, 0x20202020 }, | ||
438 | { 0x0000a394, 0x1ce739ce }, | ||
439 | { 0x0000a398, 0x000001ce }, | ||
440 | { 0x0000a39c, 0x00000001 }, | ||
441 | { 0x0000a3a0, 0x00000000 }, | ||
442 | { 0x0000a3a4, 0x00000000 }, | ||
443 | { 0x0000a3a8, 0x00000000 }, | ||
444 | { 0x0000a3ac, 0x00000000 }, | ||
445 | { 0x0000a3b0, 0x00000000 }, | ||
446 | { 0x0000a3b4, 0x00000000 }, | ||
447 | { 0x0000a3b8, 0x00000000 }, | ||
448 | { 0x0000a3bc, 0x00000000 }, | ||
449 | { 0x0000a3c0, 0x00000000 }, | ||
450 | { 0x0000a3c4, 0x00000000 }, | ||
451 | { 0x0000a3c8, 0x00000246 }, | ||
452 | { 0x0000a3cc, 0x20202020 }, | ||
453 | { 0x0000a3d0, 0x20202020 }, | ||
454 | { 0x0000a3d4, 0x20202020 }, | ||
455 | { 0x0000a3dc, 0x1ce739ce }, | ||
456 | { 0x0000a3e0, 0x000001ce }, | ||
457 | }; | ||
458 | |||
459 | static const u32 ar5416Bank0_9100[][2] = { | ||
460 | { 0x000098b0, 0x1e5795e5 }, | ||
461 | { 0x000098e0, 0x02008020 }, | ||
462 | }; | ||
463 | |||
464 | static const u32 ar5416BB_RfGain_9100[][3] = { | ||
465 | { 0x00009a00, 0x00000000, 0x00000000 }, | ||
466 | { 0x00009a04, 0x00000040, 0x00000040 }, | ||
467 | { 0x00009a08, 0x00000080, 0x00000080 }, | ||
468 | { 0x00009a0c, 0x000001a1, 0x00000141 }, | ||
469 | { 0x00009a10, 0x000001e1, 0x00000181 }, | ||
470 | { 0x00009a14, 0x00000021, 0x000001c1 }, | ||
471 | { 0x00009a18, 0x00000061, 0x00000001 }, | ||
472 | { 0x00009a1c, 0x00000168, 0x00000041 }, | ||
473 | { 0x00009a20, 0x000001a8, 0x000001a8 }, | ||
474 | { 0x00009a24, 0x000001e8, 0x000001e8 }, | ||
475 | { 0x00009a28, 0x00000028, 0x00000028 }, | ||
476 | { 0x00009a2c, 0x00000068, 0x00000068 }, | ||
477 | { 0x00009a30, 0x00000189, 0x000000a8 }, | ||
478 | { 0x00009a34, 0x000001c9, 0x00000169 }, | ||
479 | { 0x00009a38, 0x00000009, 0x000001a9 }, | ||
480 | { 0x00009a3c, 0x00000049, 0x000001e9 }, | ||
481 | { 0x00009a40, 0x00000089, 0x00000029 }, | ||
482 | { 0x00009a44, 0x00000170, 0x00000069 }, | ||
483 | { 0x00009a48, 0x000001b0, 0x00000190 }, | ||
484 | { 0x00009a4c, 0x000001f0, 0x000001d0 }, | ||
485 | { 0x00009a50, 0x00000030, 0x00000010 }, | ||
486 | { 0x00009a54, 0x00000070, 0x00000050 }, | ||
487 | { 0x00009a58, 0x00000191, 0x00000090 }, | ||
488 | { 0x00009a5c, 0x000001d1, 0x00000151 }, | ||
489 | { 0x00009a60, 0x00000011, 0x00000191 }, | ||
490 | { 0x00009a64, 0x00000051, 0x000001d1 }, | ||
491 | { 0x00009a68, 0x00000091, 0x00000011 }, | ||
492 | { 0x00009a6c, 0x000001b8, 0x00000051 }, | ||
493 | { 0x00009a70, 0x000001f8, 0x00000198 }, | ||
494 | { 0x00009a74, 0x00000038, 0x000001d8 }, | ||
495 | { 0x00009a78, 0x00000078, 0x00000018 }, | ||
496 | { 0x00009a7c, 0x00000199, 0x00000058 }, | ||
497 | { 0x00009a80, 0x000001d9, 0x00000098 }, | ||
498 | { 0x00009a84, 0x00000019, 0x00000159 }, | ||
499 | { 0x00009a88, 0x00000059, 0x00000199 }, | ||
500 | { 0x00009a8c, 0x00000099, 0x000001d9 }, | ||
501 | { 0x00009a90, 0x000000d9, 0x00000019 }, | ||
502 | { 0x00009a94, 0x000000f9, 0x00000059 }, | ||
503 | { 0x00009a98, 0x000000f9, 0x00000099 }, | ||
504 | { 0x00009a9c, 0x000000f9, 0x000000d9 }, | ||
505 | { 0x00009aa0, 0x000000f9, 0x000000f9 }, | ||
506 | { 0x00009aa4, 0x000000f9, 0x000000f9 }, | ||
507 | { 0x00009aa8, 0x000000f9, 0x000000f9 }, | ||
508 | { 0x00009aac, 0x000000f9, 0x000000f9 }, | ||
509 | { 0x00009ab0, 0x000000f9, 0x000000f9 }, | ||
510 | { 0x00009ab4, 0x000000f9, 0x000000f9 }, | ||
511 | { 0x00009ab8, 0x000000f9, 0x000000f9 }, | ||
512 | { 0x00009abc, 0x000000f9, 0x000000f9 }, | ||
513 | { 0x00009ac0, 0x000000f9, 0x000000f9 }, | ||
514 | { 0x00009ac4, 0x000000f9, 0x000000f9 }, | ||
515 | { 0x00009ac8, 0x000000f9, 0x000000f9 }, | ||
516 | { 0x00009acc, 0x000000f9, 0x000000f9 }, | ||
517 | { 0x00009ad0, 0x000000f9, 0x000000f9 }, | ||
518 | { 0x00009ad4, 0x000000f9, 0x000000f9 }, | ||
519 | { 0x00009ad8, 0x000000f9, 0x000000f9 }, | ||
520 | { 0x00009adc, 0x000000f9, 0x000000f9 }, | ||
521 | { 0x00009ae0, 0x000000f9, 0x000000f9 }, | ||
522 | { 0x00009ae4, 0x000000f9, 0x000000f9 }, | ||
523 | { 0x00009ae8, 0x000000f9, 0x000000f9 }, | ||
524 | { 0x00009aec, 0x000000f9, 0x000000f9 }, | ||
525 | { 0x00009af0, 0x000000f9, 0x000000f9 }, | ||
526 | { 0x00009af4, 0x000000f9, 0x000000f9 }, | ||
527 | { 0x00009af8, 0x000000f9, 0x000000f9 }, | ||
528 | { 0x00009afc, 0x000000f9, 0x000000f9 }, | ||
529 | }; | ||
530 | |||
531 | static const u32 ar5416Bank1_9100[][2] = { | ||
532 | { 0x000098b0, 0x02108421 }, | ||
533 | { 0x000098ec, 0x00000008 }, | ||
534 | }; | ||
535 | |||
536 | static const u32 ar5416Bank2_9100[][2] = { | ||
537 | { 0x000098b0, 0x0e73ff17 }, | ||
538 | { 0x000098e0, 0x00000420 }, | ||
539 | }; | ||
540 | |||
541 | static const u32 ar5416Bank3_9100[][3] = { | ||
542 | { 0x000098f0, 0x01400018, 0x01c00018 }, | ||
543 | }; | ||
544 | |||
545 | static const u32 ar5416Bank6_9100[][3] = { | ||
546 | |||
547 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
548 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
549 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
550 | { 0x0000989c, 0x00e00000, 0x00e00000 }, | ||
551 | { 0x0000989c, 0x005e0000, 0x005e0000 }, | ||
552 | { 0x0000989c, 0x00120000, 0x00120000 }, | ||
553 | { 0x0000989c, 0x00620000, 0x00620000 }, | ||
554 | { 0x0000989c, 0x00020000, 0x00020000 }, | ||
555 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
556 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
557 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
558 | { 0x0000989c, 0x40ff0000, 0x40ff0000 }, | ||
559 | { 0x0000989c, 0x005f0000, 0x005f0000 }, | ||
560 | { 0x0000989c, 0x00870000, 0x00870000 }, | ||
561 | { 0x0000989c, 0x00f90000, 0x00f90000 }, | ||
562 | { 0x0000989c, 0x007b0000, 0x007b0000 }, | ||
563 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
564 | { 0x0000989c, 0x00f50000, 0x00f50000 }, | ||
565 | { 0x0000989c, 0x00dc0000, 0x00dc0000 }, | ||
566 | { 0x0000989c, 0x00110000, 0x00110000 }, | ||
567 | { 0x0000989c, 0x006100a8, 0x006100a8 }, | ||
568 | { 0x0000989c, 0x004210a2, 0x004210a2 }, | ||
569 | { 0x0000989c, 0x0014008f, 0x0014008f }, | ||
570 | { 0x0000989c, 0x00c40003, 0x00c40003 }, | ||
571 | { 0x0000989c, 0x003000f2, 0x003000f2 }, | ||
572 | { 0x0000989c, 0x00440016, 0x00440016 }, | ||
573 | { 0x0000989c, 0x00410040, 0x00410040 }, | ||
574 | { 0x0000989c, 0x0001805e, 0x0001805e }, | ||
575 | { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, | ||
576 | { 0x0000989c, 0x000000f1, 0x000000f1 }, | ||
577 | { 0x0000989c, 0x00002081, 0x00002081 }, | ||
578 | { 0x0000989c, 0x000000d4, 0x000000d4 }, | ||
579 | { 0x000098d0, 0x0000000f, 0x0010000f }, | ||
580 | }; | ||
581 | |||
582 | static const u32 ar5416Bank6TPC_9100[][3] = { | ||
583 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
584 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
585 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
586 | { 0x0000989c, 0x00e00000, 0x00e00000 }, | ||
587 | { 0x0000989c, 0x005e0000, 0x005e0000 }, | ||
588 | { 0x0000989c, 0x00120000, 0x00120000 }, | ||
589 | { 0x0000989c, 0x00620000, 0x00620000 }, | ||
590 | { 0x0000989c, 0x00020000, 0x00020000 }, | ||
591 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
592 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
593 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
594 | { 0x0000989c, 0x40ff0000, 0x40ff0000 }, | ||
595 | { 0x0000989c, 0x005f0000, 0x005f0000 }, | ||
596 | { 0x0000989c, 0x00870000, 0x00870000 }, | ||
597 | { 0x0000989c, 0x00f90000, 0x00f90000 }, | ||
598 | { 0x0000989c, 0x007b0000, 0x007b0000 }, | ||
599 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
600 | { 0x0000989c, 0x00f50000, 0x00f50000 }, | ||
601 | { 0x0000989c, 0x00dc0000, 0x00dc0000 }, | ||
602 | { 0x0000989c, 0x00110000, 0x00110000 }, | ||
603 | { 0x0000989c, 0x006100a8, 0x006100a8 }, | ||
604 | { 0x0000989c, 0x00423022, 0x00423022 }, | ||
605 | { 0x0000989c, 0x201400df, 0x201400df }, | ||
606 | { 0x0000989c, 0x00c40002, 0x00c40002 }, | ||
607 | { 0x0000989c, 0x003000f2, 0x003000f2 }, | ||
608 | { 0x0000989c, 0x00440016, 0x00440016 }, | ||
609 | { 0x0000989c, 0x00410040, 0x00410040 }, | ||
610 | { 0x0000989c, 0x0001805e, 0x0001805e }, | ||
611 | { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, | ||
612 | { 0x0000989c, 0x000000e1, 0x000000e1 }, | ||
613 | { 0x0000989c, 0x00007081, 0x00007081 }, | ||
614 | { 0x0000989c, 0x000000d4, 0x000000d4 }, | ||
615 | { 0x000098d0, 0x0000000f, 0x0010000f }, | ||
616 | }; | ||
617 | |||
618 | static const u32 ar5416Bank7_9100[][2] = { | ||
619 | { 0x0000989c, 0x00000500 }, | ||
620 | { 0x0000989c, 0x00000800 }, | ||
621 | { 0x000098cc, 0x0000000e }, | ||
622 | }; | ||
623 | |||
624 | static const u32 ar5416Addac_9100[][2] = { | ||
625 | {0x0000989c, 0x00000000 }, | ||
626 | {0x0000989c, 0x00000003 }, | ||
627 | {0x0000989c, 0x00000000 }, | ||
628 | {0x0000989c, 0x0000000c }, | ||
629 | {0x0000989c, 0x00000000 }, | ||
630 | {0x0000989c, 0x00000030 }, | ||
631 | {0x0000989c, 0x00000000 }, | ||
632 | {0x0000989c, 0x00000000 }, | ||
633 | {0x0000989c, 0x00000000 }, | ||
634 | {0x0000989c, 0x00000000 }, | ||
635 | {0x0000989c, 0x00000000 }, | ||
636 | {0x0000989c, 0x00000000 }, | ||
637 | {0x0000989c, 0x00000000 }, | ||
638 | {0x0000989c, 0x00000000 }, | ||
639 | {0x0000989c, 0x00000000 }, | ||
640 | {0x0000989c, 0x00000000 }, | ||
641 | {0x0000989c, 0x00000000 }, | ||
642 | {0x0000989c, 0x00000000 }, | ||
643 | {0x0000989c, 0x00000060 }, | ||
644 | {0x0000989c, 0x00000000 }, | ||
645 | {0x0000989c, 0x00000000 }, | ||
646 | {0x0000989c, 0x00000000 }, | ||
647 | {0x0000989c, 0x00000000 }, | ||
648 | {0x0000989c, 0x00000000 }, | ||
649 | {0x0000989c, 0x00000000 }, | ||
650 | {0x0000989c, 0x00000000 }, | ||
651 | {0x0000989c, 0x00000000 }, | ||
652 | {0x0000989c, 0x00000000 }, | ||
653 | {0x0000989c, 0x00000000 }, | ||
654 | {0x0000989c, 0x00000000 }, | ||
655 | {0x0000989c, 0x00000000 }, | ||
656 | {0x0000989c, 0x00000058 }, | ||
657 | {0x0000989c, 0x00000000 }, | ||
658 | {0x0000989c, 0x00000000 }, | ||
659 | {0x0000989c, 0x00000000 }, | ||
660 | {0x0000989c, 0x00000000 }, | ||
661 | {0x000098c4, 0x00000000 }, | ||
662 | }; | ||
663 | |||
664 | static const u32 ar5416Modes[][6] = { | ||
665 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | ||
666 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | ||
667 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, | ||
668 | { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, | ||
669 | { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, | ||
670 | { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, | ||
671 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, | ||
672 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, | ||
673 | { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
674 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, | ||
675 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
676 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, | ||
677 | { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, | ||
678 | { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | ||
679 | { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | ||
680 | { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | ||
681 | { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, | ||
682 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e }, | ||
683 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, | ||
684 | { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, | ||
685 | { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | ||
686 | { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, | ||
687 | { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, | ||
688 | { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, | ||
689 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, | ||
690 | { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d }, | ||
691 | { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, | ||
692 | { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, | ||
693 | { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, | ||
694 | { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, | ||
695 | #ifdef TB243 | ||
696 | { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, | ||
697 | { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, | ||
698 | { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, | ||
699 | { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, | ||
700 | #else | ||
701 | { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, | ||
702 | { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, | ||
703 | { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, | ||
704 | { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, | ||
705 | #endif | ||
706 | { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, | ||
707 | { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, | ||
708 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | ||
709 | { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, | ||
710 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, | ||
711 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, | ||
712 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
713 | { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
714 | { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, | ||
715 | { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, | ||
716 | { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, | ||
717 | { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, | ||
718 | { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, | ||
719 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, | ||
720 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | ||
721 | { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, | ||
722 | { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, | ||
723 | { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, | ||
724 | { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, | ||
725 | { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, | ||
726 | { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, | ||
727 | { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, | ||
728 | { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, | ||
729 | { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, | ||
730 | { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, | ||
731 | { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, | ||
732 | { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, | ||
733 | { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
734 | { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
735 | { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
736 | }; | ||
737 | |||
738 | static const u32 ar5416Common[][2] = { | ||
739 | { 0x0000000c, 0x00000000 }, | ||
740 | { 0x00000030, 0x00020015 }, | ||
741 | { 0x00000034, 0x00000005 }, | ||
742 | { 0x00000040, 0x00000000 }, | ||
743 | { 0x00000044, 0x00000008 }, | ||
744 | { 0x00000048, 0x00000008 }, | ||
745 | { 0x0000004c, 0x00000010 }, | ||
746 | { 0x00000050, 0x00000000 }, | ||
747 | { 0x00000054, 0x0000001f }, | ||
748 | { 0x00000800, 0x00000000 }, | ||
749 | { 0x00000804, 0x00000000 }, | ||
750 | { 0x00000808, 0x00000000 }, | ||
751 | { 0x0000080c, 0x00000000 }, | ||
752 | { 0x00000810, 0x00000000 }, | ||
753 | { 0x00000814, 0x00000000 }, | ||
754 | { 0x00000818, 0x00000000 }, | ||
755 | { 0x0000081c, 0x00000000 }, | ||
756 | { 0x00000820, 0x00000000 }, | ||
757 | { 0x00000824, 0x00000000 }, | ||
758 | { 0x00001040, 0x002ffc0f }, | ||
759 | { 0x00001044, 0x002ffc0f }, | ||
760 | { 0x00001048, 0x002ffc0f }, | ||
761 | { 0x0000104c, 0x002ffc0f }, | ||
762 | { 0x00001050, 0x002ffc0f }, | ||
763 | { 0x00001054, 0x002ffc0f }, | ||
764 | { 0x00001058, 0x002ffc0f }, | ||
765 | { 0x0000105c, 0x002ffc0f }, | ||
766 | { 0x00001060, 0x002ffc0f }, | ||
767 | { 0x00001064, 0x002ffc0f }, | ||
768 | { 0x00001230, 0x00000000 }, | ||
769 | { 0x00001270, 0x00000000 }, | ||
770 | { 0x00001038, 0x00000000 }, | ||
771 | { 0x00001078, 0x00000000 }, | ||
772 | { 0x000010b8, 0x00000000 }, | ||
773 | { 0x000010f8, 0x00000000 }, | ||
774 | { 0x00001138, 0x00000000 }, | ||
775 | { 0x00001178, 0x00000000 }, | ||
776 | { 0x000011b8, 0x00000000 }, | ||
777 | { 0x000011f8, 0x00000000 }, | ||
778 | { 0x00001238, 0x00000000 }, | ||
779 | { 0x00001278, 0x00000000 }, | ||
780 | { 0x000012b8, 0x00000000 }, | ||
781 | { 0x000012f8, 0x00000000 }, | ||
782 | { 0x00001338, 0x00000000 }, | ||
783 | { 0x00001378, 0x00000000 }, | ||
784 | { 0x000013b8, 0x00000000 }, | ||
785 | { 0x000013f8, 0x00000000 }, | ||
786 | { 0x00001438, 0x00000000 }, | ||
787 | { 0x00001478, 0x00000000 }, | ||
788 | { 0x000014b8, 0x00000000 }, | ||
789 | { 0x000014f8, 0x00000000 }, | ||
790 | { 0x00001538, 0x00000000 }, | ||
791 | { 0x00001578, 0x00000000 }, | ||
792 | { 0x000015b8, 0x00000000 }, | ||
793 | { 0x000015f8, 0x00000000 }, | ||
794 | { 0x00001638, 0x00000000 }, | ||
795 | { 0x00001678, 0x00000000 }, | ||
796 | { 0x000016b8, 0x00000000 }, | ||
797 | { 0x000016f8, 0x00000000 }, | ||
798 | { 0x00001738, 0x00000000 }, | ||
799 | { 0x00001778, 0x00000000 }, | ||
800 | { 0x000017b8, 0x00000000 }, | ||
801 | { 0x000017f8, 0x00000000 }, | ||
802 | { 0x0000103c, 0x00000000 }, | ||
803 | { 0x0000107c, 0x00000000 }, | ||
804 | { 0x000010bc, 0x00000000 }, | ||
805 | { 0x000010fc, 0x00000000 }, | ||
806 | { 0x0000113c, 0x00000000 }, | ||
807 | { 0x0000117c, 0x00000000 }, | ||
808 | { 0x000011bc, 0x00000000 }, | ||
809 | { 0x000011fc, 0x00000000 }, | ||
810 | { 0x0000123c, 0x00000000 }, | ||
811 | { 0x0000127c, 0x00000000 }, | ||
812 | { 0x000012bc, 0x00000000 }, | ||
813 | { 0x000012fc, 0x00000000 }, | ||
814 | { 0x0000133c, 0x00000000 }, | ||
815 | { 0x0000137c, 0x00000000 }, | ||
816 | { 0x000013bc, 0x00000000 }, | ||
817 | { 0x000013fc, 0x00000000 }, | ||
818 | { 0x0000143c, 0x00000000 }, | ||
819 | { 0x0000147c, 0x00000000 }, | ||
820 | { 0x00020010, 0x00000003 }, | ||
821 | { 0x00020038, 0x000004c2 }, | ||
822 | { 0x00008004, 0x00000000 }, | ||
823 | { 0x00008008, 0x00000000 }, | ||
824 | { 0x0000800c, 0x00000000 }, | ||
825 | { 0x00008018, 0x00000700 }, | ||
826 | { 0x00008020, 0x00000000 }, | ||
827 | { 0x00008038, 0x00000000 }, | ||
828 | { 0x0000803c, 0x00000000 }, | ||
829 | { 0x00008048, 0x40000000 }, | ||
830 | { 0x00008054, 0x00004000 }, | ||
831 | { 0x00008058, 0x00000000 }, | ||
832 | { 0x0000805c, 0x000fc78f }, | ||
833 | { 0x00008060, 0x0000000f }, | ||
834 | { 0x00008064, 0x00000000 }, | ||
835 | { 0x000080c0, 0x2a82301a }, | ||
836 | { 0x000080c4, 0x05dc01e0 }, | ||
837 | { 0x000080c8, 0x1f402710 }, | ||
838 | { 0x000080cc, 0x01f40000 }, | ||
839 | { 0x000080d0, 0x00001e00 }, | ||
840 | { 0x000080d4, 0x00000000 }, | ||
841 | { 0x000080d8, 0x00400000 }, | ||
842 | { 0x000080e0, 0xffffffff }, | ||
843 | { 0x000080e4, 0x0000ffff }, | ||
844 | { 0x000080e8, 0x003f3f3f }, | ||
845 | { 0x000080ec, 0x00000000 }, | ||
846 | { 0x000080f0, 0x00000000 }, | ||
847 | { 0x000080f4, 0x00000000 }, | ||
848 | { 0x000080f8, 0x00000000 }, | ||
849 | { 0x000080fc, 0x00020000 }, | ||
850 | { 0x00008100, 0x00020000 }, | ||
851 | { 0x00008104, 0x00000001 }, | ||
852 | { 0x00008108, 0x00000052 }, | ||
853 | { 0x0000810c, 0x00000000 }, | ||
854 | { 0x00008110, 0x00000168 }, | ||
855 | { 0x00008118, 0x000100aa }, | ||
856 | { 0x0000811c, 0x00003210 }, | ||
857 | { 0x00008120, 0x08f04800 }, | ||
858 | { 0x00008124, 0x00000000 }, | ||
859 | { 0x00008128, 0x00000000 }, | ||
860 | { 0x0000812c, 0x00000000 }, | ||
861 | { 0x00008130, 0x00000000 }, | ||
862 | { 0x00008134, 0x00000000 }, | ||
863 | { 0x00008138, 0x00000000 }, | ||
864 | { 0x0000813c, 0x00000000 }, | ||
865 | { 0x00008144, 0x00000000 }, | ||
866 | { 0x00008168, 0x00000000 }, | ||
867 | { 0x0000816c, 0x00000000 }, | ||
868 | { 0x00008170, 0x32143320 }, | ||
869 | { 0x00008174, 0xfaa4fa50 }, | ||
870 | { 0x00008178, 0x00000100 }, | ||
871 | { 0x0000817c, 0x00000000 }, | ||
872 | { 0x000081c4, 0x00000000 }, | ||
873 | { 0x000081d0, 0x00003210 }, | ||
874 | { 0x000081ec, 0x00000000 }, | ||
875 | { 0x000081f0, 0x00000000 }, | ||
876 | { 0x000081f4, 0x00000000 }, | ||
877 | { 0x000081f8, 0x00000000 }, | ||
878 | { 0x000081fc, 0x00000000 }, | ||
879 | { 0x00008200, 0x00000000 }, | ||
880 | { 0x00008204, 0x00000000 }, | ||
881 | { 0x00008208, 0x00000000 }, | ||
882 | { 0x0000820c, 0x00000000 }, | ||
883 | { 0x00008210, 0x00000000 }, | ||
884 | { 0x00008214, 0x00000000 }, | ||
885 | { 0x00008218, 0x00000000 }, | ||
886 | { 0x0000821c, 0x00000000 }, | ||
887 | { 0x00008220, 0x00000000 }, | ||
888 | { 0x00008224, 0x00000000 }, | ||
889 | { 0x00008228, 0x00000000 }, | ||
890 | { 0x0000822c, 0x00000000 }, | ||
891 | { 0x00008230, 0x00000000 }, | ||
892 | { 0x00008234, 0x00000000 }, | ||
893 | { 0x00008238, 0x00000000 }, | ||
894 | { 0x0000823c, 0x00000000 }, | ||
895 | { 0x00008240, 0x00100000 }, | ||
896 | { 0x00008244, 0x0010f400 }, | ||
897 | { 0x00008248, 0x00000100 }, | ||
898 | { 0x0000824c, 0x0001e800 }, | ||
899 | { 0x00008250, 0x00000000 }, | ||
900 | { 0x00008254, 0x00000000 }, | ||
901 | { 0x00008258, 0x00000000 }, | ||
902 | { 0x0000825c, 0x400000ff }, | ||
903 | { 0x00008260, 0x00080922 }, | ||
904 | { 0x00008270, 0x00000000 }, | ||
905 | { 0x00008274, 0x40000000 }, | ||
906 | { 0x00008278, 0x003e4180 }, | ||
907 | { 0x0000827c, 0x00000000 }, | ||
908 | { 0x00008284, 0x0000002c }, | ||
909 | { 0x00008288, 0x0000002c }, | ||
910 | { 0x0000828c, 0x00000000 }, | ||
911 | { 0x00008294, 0x00000000 }, | ||
912 | { 0x00008298, 0x00000000 }, | ||
913 | { 0x00008300, 0x00000000 }, | ||
914 | { 0x00008304, 0x00000000 }, | ||
915 | { 0x00008308, 0x00000000 }, | ||
916 | { 0x0000830c, 0x00000000 }, | ||
917 | { 0x00008310, 0x00000000 }, | ||
918 | { 0x00008314, 0x00000000 }, | ||
919 | { 0x00008318, 0x00000000 }, | ||
920 | { 0x00008328, 0x00000000 }, | ||
921 | { 0x0000832c, 0x00000007 }, | ||
922 | { 0x00008330, 0x00000302 }, | ||
923 | { 0x00008334, 0x00000e00 }, | ||
924 | { 0x00008338, 0x00000000 }, | ||
925 | { 0x0000833c, 0x00000000 }, | ||
926 | { 0x00008340, 0x000107ff }, | ||
927 | { 0x00009808, 0x00000000 }, | ||
928 | { 0x0000980c, 0xad848e19 }, | ||
929 | { 0x00009810, 0x7d14e000 }, | ||
930 | { 0x00009814, 0x9c0a9f6b }, | ||
931 | { 0x0000981c, 0x00000000 }, | ||
932 | { 0x0000982c, 0x0000a000 }, | ||
933 | { 0x00009830, 0x00000000 }, | ||
934 | { 0x0000983c, 0x00200400 }, | ||
935 | { 0x00009840, 0x206a01ae }, | ||
936 | { 0x0000984c, 0x1284233c }, | ||
937 | { 0x00009854, 0x00000859 }, | ||
938 | { 0x00009900, 0x00000000 }, | ||
939 | { 0x00009904, 0x00000000 }, | ||
940 | { 0x00009908, 0x00000000 }, | ||
941 | { 0x0000990c, 0x00000000 }, | ||
942 | { 0x0000991c, 0x10000fff }, | ||
943 | { 0x00009920, 0x05100000 }, | ||
944 | { 0x0000a920, 0x05100000 }, | ||
945 | { 0x0000b920, 0x05100000 }, | ||
946 | { 0x00009928, 0x00000001 }, | ||
947 | { 0x0000992c, 0x00000004 }, | ||
948 | { 0x00009934, 0x1e1f2022 }, | ||
949 | { 0x00009938, 0x0a0b0c0d }, | ||
950 | { 0x0000993c, 0x00000000 }, | ||
951 | { 0x00009948, 0x9280b212 }, | ||
952 | { 0x0000994c, 0x00020028 }, | ||
953 | { 0x0000c95c, 0x004b6a8e }, | ||
954 | { 0x0000c968, 0x000003ce }, | ||
955 | { 0x00009970, 0x190fb514 }, | ||
956 | { 0x00009974, 0x00000000 }, | ||
957 | { 0x00009978, 0x00000001 }, | ||
958 | { 0x0000997c, 0x00000000 }, | ||
959 | { 0x00009980, 0x00000000 }, | ||
960 | { 0x00009984, 0x00000000 }, | ||
961 | { 0x00009988, 0x00000000 }, | ||
962 | { 0x0000998c, 0x00000000 }, | ||
963 | { 0x00009990, 0x00000000 }, | ||
964 | { 0x00009994, 0x00000000 }, | ||
965 | { 0x00009998, 0x00000000 }, | ||
966 | { 0x0000999c, 0x00000000 }, | ||
967 | { 0x000099a0, 0x00000000 }, | ||
968 | { 0x000099a4, 0x00000001 }, | ||
969 | { 0x000099a8, 0x201fff00 }, | ||
970 | { 0x000099ac, 0x006f0000 }, | ||
971 | { 0x000099b0, 0x03051000 }, | ||
972 | { 0x000099dc, 0x00000000 }, | ||
973 | { 0x000099e0, 0x00000200 }, | ||
974 | { 0x000099e4, 0xaaaaaaaa }, | ||
975 | { 0x000099e8, 0x3c466478 }, | ||
976 | { 0x000099ec, 0x0cc80caa }, | ||
977 | { 0x000099fc, 0x00001042 }, | ||
978 | { 0x00009b00, 0x00000000 }, | ||
979 | { 0x00009b04, 0x00000001 }, | ||
980 | { 0x00009b08, 0x00000002 }, | ||
981 | { 0x00009b0c, 0x00000003 }, | ||
982 | { 0x00009b10, 0x00000004 }, | ||
983 | { 0x00009b14, 0x00000005 }, | ||
984 | { 0x00009b18, 0x00000008 }, | ||
985 | { 0x00009b1c, 0x00000009 }, | ||
986 | { 0x00009b20, 0x0000000a }, | ||
987 | { 0x00009b24, 0x0000000b }, | ||
988 | { 0x00009b28, 0x0000000c }, | ||
989 | { 0x00009b2c, 0x0000000d }, | ||
990 | { 0x00009b30, 0x00000010 }, | ||
991 | { 0x00009b34, 0x00000011 }, | ||
992 | { 0x00009b38, 0x00000012 }, | ||
993 | { 0x00009b3c, 0x00000013 }, | ||
994 | { 0x00009b40, 0x00000014 }, | ||
995 | { 0x00009b44, 0x00000015 }, | ||
996 | { 0x00009b48, 0x00000018 }, | ||
997 | { 0x00009b4c, 0x00000019 }, | ||
998 | { 0x00009b50, 0x0000001a }, | ||
999 | { 0x00009b54, 0x0000001b }, | ||
1000 | { 0x00009b58, 0x0000001c }, | ||
1001 | { 0x00009b5c, 0x0000001d }, | ||
1002 | { 0x00009b60, 0x00000020 }, | ||
1003 | { 0x00009b64, 0x00000021 }, | ||
1004 | { 0x00009b68, 0x00000022 }, | ||
1005 | { 0x00009b6c, 0x00000023 }, | ||
1006 | { 0x00009b70, 0x00000024 }, | ||
1007 | { 0x00009b74, 0x00000025 }, | ||
1008 | { 0x00009b78, 0x00000028 }, | ||
1009 | { 0x00009b7c, 0x00000029 }, | ||
1010 | { 0x00009b80, 0x0000002a }, | ||
1011 | { 0x00009b84, 0x0000002b }, | ||
1012 | { 0x00009b88, 0x0000002c }, | ||
1013 | { 0x00009b8c, 0x0000002d }, | ||
1014 | { 0x00009b90, 0x00000030 }, | ||
1015 | { 0x00009b94, 0x00000031 }, | ||
1016 | { 0x00009b98, 0x00000032 }, | ||
1017 | { 0x00009b9c, 0x00000033 }, | ||
1018 | { 0x00009ba0, 0x00000034 }, | ||
1019 | { 0x00009ba4, 0x00000035 }, | ||
1020 | { 0x00009ba8, 0x00000035 }, | ||
1021 | { 0x00009bac, 0x00000035 }, | ||
1022 | { 0x00009bb0, 0x00000035 }, | ||
1023 | { 0x00009bb4, 0x00000035 }, | ||
1024 | { 0x00009bb8, 0x00000035 }, | ||
1025 | { 0x00009bbc, 0x00000035 }, | ||
1026 | { 0x00009bc0, 0x00000035 }, | ||
1027 | { 0x00009bc4, 0x00000035 }, | ||
1028 | { 0x00009bc8, 0x00000035 }, | ||
1029 | { 0x00009bcc, 0x00000035 }, | ||
1030 | { 0x00009bd0, 0x00000035 }, | ||
1031 | { 0x00009bd4, 0x00000035 }, | ||
1032 | { 0x00009bd8, 0x00000035 }, | ||
1033 | { 0x00009bdc, 0x00000035 }, | ||
1034 | { 0x00009be0, 0x00000035 }, | ||
1035 | { 0x00009be4, 0x00000035 }, | ||
1036 | { 0x00009be8, 0x00000035 }, | ||
1037 | { 0x00009bec, 0x00000035 }, | ||
1038 | { 0x00009bf0, 0x00000035 }, | ||
1039 | { 0x00009bf4, 0x00000035 }, | ||
1040 | { 0x00009bf8, 0x00000010 }, | ||
1041 | { 0x00009bfc, 0x0000001a }, | ||
1042 | { 0x0000a210, 0x40806333 }, | ||
1043 | { 0x0000a214, 0x00106c10 }, | ||
1044 | { 0x0000a218, 0x009c4060 }, | ||
1045 | { 0x0000a220, 0x018830c6 }, | ||
1046 | { 0x0000a224, 0x00000400 }, | ||
1047 | { 0x0000a228, 0x001a0bb5 }, | ||
1048 | { 0x0000a22c, 0x00000000 }, | ||
1049 | { 0x0000a234, 0x20202020 }, | ||
1050 | { 0x0000a238, 0x20202020 }, | ||
1051 | { 0x0000a23c, 0x13c889ae }, | ||
1052 | { 0x0000a240, 0x38490a20 }, | ||
1053 | { 0x0000a244, 0x00007bb6 }, | ||
1054 | { 0x0000a248, 0x0fff3ffc }, | ||
1055 | { 0x0000a24c, 0x00000001 }, | ||
1056 | { 0x0000a250, 0x0000a000 }, | ||
1057 | { 0x0000a254, 0x00000000 }, | ||
1058 | { 0x0000a258, 0x0cc75380 }, | ||
1059 | { 0x0000a25c, 0x0f0f0f01 }, | ||
1060 | { 0x0000a260, 0xdfa91f01 }, | ||
1061 | { 0x0000a268, 0x00000001 }, | ||
1062 | { 0x0000a26c, 0x0ebae9c6 }, | ||
1063 | { 0x0000b26c, 0x0ebae9c6 }, | ||
1064 | { 0x0000c26c, 0x0ebae9c6 }, | ||
1065 | { 0x0000d270, 0x00820820 }, | ||
1066 | { 0x0000a278, 0x1ce739ce }, | ||
1067 | { 0x0000a27c, 0x050701ce }, | ||
1068 | { 0x0000a338, 0x00000000 }, | ||
1069 | { 0x0000a33c, 0x00000000 }, | ||
1070 | { 0x0000a340, 0x00000000 }, | ||
1071 | { 0x0000a344, 0x00000000 }, | ||
1072 | { 0x0000a348, 0x3fffffff }, | ||
1073 | { 0x0000a34c, 0x3fffffff }, | ||
1074 | { 0x0000a350, 0x3fffffff }, | ||
1075 | { 0x0000a354, 0x0003ffff }, | ||
1076 | { 0x0000a358, 0x79a8aa33 }, | ||
1077 | { 0x0000d35c, 0x07ffffef }, | ||
1078 | { 0x0000d360, 0x0fffffe7 }, | ||
1079 | { 0x0000d364, 0x17ffffe5 }, | ||
1080 | { 0x0000d368, 0x1fffffe4 }, | ||
1081 | { 0x0000d36c, 0x37ffffe3 }, | ||
1082 | { 0x0000d370, 0x3fffffe3 }, | ||
1083 | { 0x0000d374, 0x57ffffe3 }, | ||
1084 | { 0x0000d378, 0x5fffffe2 }, | ||
1085 | { 0x0000d37c, 0x7fffffe2 }, | ||
1086 | { 0x0000d380, 0x7f3c7bba }, | ||
1087 | { 0x0000d384, 0xf3307ff0 }, | ||
1088 | { 0x0000a388, 0x0c000000 }, | ||
1089 | { 0x0000a38c, 0x20202020 }, | ||
1090 | { 0x0000a390, 0x20202020 }, | ||
1091 | { 0x0000a394, 0x1ce739ce }, | ||
1092 | { 0x0000a398, 0x000001ce }, | ||
1093 | { 0x0000a39c, 0x00000001 }, | ||
1094 | { 0x0000a3a0, 0x00000000 }, | ||
1095 | { 0x0000a3a4, 0x00000000 }, | ||
1096 | { 0x0000a3a8, 0x00000000 }, | ||
1097 | { 0x0000a3ac, 0x00000000 }, | ||
1098 | { 0x0000a3b0, 0x00000000 }, | ||
1099 | { 0x0000a3b4, 0x00000000 }, | ||
1100 | { 0x0000a3b8, 0x00000000 }, | ||
1101 | { 0x0000a3bc, 0x00000000 }, | ||
1102 | { 0x0000a3c0, 0x00000000 }, | ||
1103 | { 0x0000a3c4, 0x00000000 }, | ||
1104 | { 0x0000a3c8, 0x00000246 }, | ||
1105 | { 0x0000a3cc, 0x20202020 }, | ||
1106 | { 0x0000a3d0, 0x20202020 }, | ||
1107 | { 0x0000a3d4, 0x20202020 }, | ||
1108 | { 0x0000a3dc, 0x1ce739ce }, | ||
1109 | { 0x0000a3e0, 0x000001ce }, | ||
1110 | }; | ||
1111 | |||
1112 | static const u32 ar5416Bank0[][2] = { | ||
1113 | { 0x000098b0, 0x1e5795e5 }, | ||
1114 | { 0x000098e0, 0x02008020 }, | ||
1115 | }; | ||
1116 | |||
1117 | static const u32 ar5416BB_RfGain[][3] = { | ||
1118 | { 0x00009a00, 0x00000000, 0x00000000 }, | ||
1119 | { 0x00009a04, 0x00000040, 0x00000040 }, | ||
1120 | { 0x00009a08, 0x00000080, 0x00000080 }, | ||
1121 | { 0x00009a0c, 0x000001a1, 0x00000141 }, | ||
1122 | { 0x00009a10, 0x000001e1, 0x00000181 }, | ||
1123 | { 0x00009a14, 0x00000021, 0x000001c1 }, | ||
1124 | { 0x00009a18, 0x00000061, 0x00000001 }, | ||
1125 | { 0x00009a1c, 0x00000168, 0x00000041 }, | ||
1126 | { 0x00009a20, 0x000001a8, 0x000001a8 }, | ||
1127 | { 0x00009a24, 0x000001e8, 0x000001e8 }, | ||
1128 | { 0x00009a28, 0x00000028, 0x00000028 }, | ||
1129 | { 0x00009a2c, 0x00000068, 0x00000068 }, | ||
1130 | { 0x00009a30, 0x00000189, 0x000000a8 }, | ||
1131 | { 0x00009a34, 0x000001c9, 0x00000169 }, | ||
1132 | { 0x00009a38, 0x00000009, 0x000001a9 }, | ||
1133 | { 0x00009a3c, 0x00000049, 0x000001e9 }, | ||
1134 | { 0x00009a40, 0x00000089, 0x00000029 }, | ||
1135 | { 0x00009a44, 0x00000170, 0x00000069 }, | ||
1136 | { 0x00009a48, 0x000001b0, 0x00000190 }, | ||
1137 | { 0x00009a4c, 0x000001f0, 0x000001d0 }, | ||
1138 | { 0x00009a50, 0x00000030, 0x00000010 }, | ||
1139 | { 0x00009a54, 0x00000070, 0x00000050 }, | ||
1140 | { 0x00009a58, 0x00000191, 0x00000090 }, | ||
1141 | { 0x00009a5c, 0x000001d1, 0x00000151 }, | ||
1142 | { 0x00009a60, 0x00000011, 0x00000191 }, | ||
1143 | { 0x00009a64, 0x00000051, 0x000001d1 }, | ||
1144 | { 0x00009a68, 0x00000091, 0x00000011 }, | ||
1145 | { 0x00009a6c, 0x000001b8, 0x00000051 }, | ||
1146 | { 0x00009a70, 0x000001f8, 0x00000198 }, | ||
1147 | { 0x00009a74, 0x00000038, 0x000001d8 }, | ||
1148 | { 0x00009a78, 0x00000078, 0x00000018 }, | ||
1149 | { 0x00009a7c, 0x00000199, 0x00000058 }, | ||
1150 | { 0x00009a80, 0x000001d9, 0x00000098 }, | ||
1151 | { 0x00009a84, 0x00000019, 0x00000159 }, | ||
1152 | { 0x00009a88, 0x00000059, 0x00000199 }, | ||
1153 | { 0x00009a8c, 0x00000099, 0x000001d9 }, | ||
1154 | { 0x00009a90, 0x000000d9, 0x00000019 }, | ||
1155 | { 0x00009a94, 0x000000f9, 0x00000059 }, | ||
1156 | { 0x00009a98, 0x000000f9, 0x00000099 }, | ||
1157 | { 0x00009a9c, 0x000000f9, 0x000000d9 }, | ||
1158 | { 0x00009aa0, 0x000000f9, 0x000000f9 }, | ||
1159 | { 0x00009aa4, 0x000000f9, 0x000000f9 }, | ||
1160 | { 0x00009aa8, 0x000000f9, 0x000000f9 }, | ||
1161 | { 0x00009aac, 0x000000f9, 0x000000f9 }, | ||
1162 | { 0x00009ab0, 0x000000f9, 0x000000f9 }, | ||
1163 | { 0x00009ab4, 0x000000f9, 0x000000f9 }, | ||
1164 | { 0x00009ab8, 0x000000f9, 0x000000f9 }, | ||
1165 | { 0x00009abc, 0x000000f9, 0x000000f9 }, | ||
1166 | { 0x00009ac0, 0x000000f9, 0x000000f9 }, | ||
1167 | { 0x00009ac4, 0x000000f9, 0x000000f9 }, | ||
1168 | { 0x00009ac8, 0x000000f9, 0x000000f9 }, | ||
1169 | { 0x00009acc, 0x000000f9, 0x000000f9 }, | ||
1170 | { 0x00009ad0, 0x000000f9, 0x000000f9 }, | ||
1171 | { 0x00009ad4, 0x000000f9, 0x000000f9 }, | ||
1172 | { 0x00009ad8, 0x000000f9, 0x000000f9 }, | ||
1173 | { 0x00009adc, 0x000000f9, 0x000000f9 }, | ||
1174 | { 0x00009ae0, 0x000000f9, 0x000000f9 }, | ||
1175 | { 0x00009ae4, 0x000000f9, 0x000000f9 }, | ||
1176 | { 0x00009ae8, 0x000000f9, 0x000000f9 }, | ||
1177 | { 0x00009aec, 0x000000f9, 0x000000f9 }, | ||
1178 | { 0x00009af0, 0x000000f9, 0x000000f9 }, | ||
1179 | { 0x00009af4, 0x000000f9, 0x000000f9 }, | ||
1180 | { 0x00009af8, 0x000000f9, 0x000000f9 }, | ||
1181 | { 0x00009afc, 0x000000f9, 0x000000f9 }, | ||
1182 | }; | ||
1183 | |||
1184 | static const u32 ar5416Bank1[][2] = { | ||
1185 | { 0x000098b0, 0x02108421}, | ||
1186 | { 0x000098ec, 0x00000008}, | ||
1187 | }; | ||
1188 | |||
1189 | static const u32 ar5416Bank2[][2] = { | ||
1190 | { 0x000098b0, 0x0e73ff17}, | ||
1191 | { 0x000098e0, 0x00000420}, | ||
1192 | }; | ||
1193 | |||
1194 | static const u32 ar5416Bank3[][3] = { | ||
1195 | { 0x000098f0, 0x01400018, 0x01c00018 }, | ||
1196 | }; | ||
1197 | |||
1198 | static const u32 ar5416Bank6[][3] = { | ||
1199 | |||
1200 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1201 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1202 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1203 | { 0x0000989c, 0x00e00000, 0x00e00000 }, | ||
1204 | { 0x0000989c, 0x005e0000, 0x005e0000 }, | ||
1205 | { 0x0000989c, 0x00120000, 0x00120000 }, | ||
1206 | { 0x0000989c, 0x00620000, 0x00620000 }, | ||
1207 | { 0x0000989c, 0x00020000, 0x00020000 }, | ||
1208 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1209 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1210 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1211 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1212 | { 0x0000989c, 0x005f0000, 0x005f0000 }, | ||
1213 | { 0x0000989c, 0x00870000, 0x00870000 }, | ||
1214 | { 0x0000989c, 0x00f90000, 0x00f90000 }, | ||
1215 | { 0x0000989c, 0x007b0000, 0x007b0000 }, | ||
1216 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1217 | { 0x0000989c, 0x00f50000, 0x00f50000 }, | ||
1218 | { 0x0000989c, 0x00dc0000, 0x00dc0000 }, | ||
1219 | { 0x0000989c, 0x00110000, 0x00110000 }, | ||
1220 | { 0x0000989c, 0x006100a8, 0x006100a8 }, | ||
1221 | { 0x0000989c, 0x004210a2, 0x004210a2 }, | ||
1222 | { 0x0000989c, 0x0014000f, 0x0014000f }, | ||
1223 | { 0x0000989c, 0x00c40002, 0x00c40002 }, | ||
1224 | { 0x0000989c, 0x003000f2, 0x003000f2 }, | ||
1225 | { 0x0000989c, 0x00440016, 0x00440016 }, | ||
1226 | { 0x0000989c, 0x00410040, 0x00410040 }, | ||
1227 | { 0x0000989c, 0x000180d6, 0x000180d6 }, | ||
1228 | { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, | ||
1229 | { 0x0000989c, 0x000000b1, 0x000000b1 }, | ||
1230 | { 0x0000989c, 0x00002000, 0x00002000 }, | ||
1231 | { 0x0000989c, 0x000000d4, 0x000000d4 }, | ||
1232 | { 0x000098d0, 0x0000000f, 0x0010000f }, | ||
1233 | }; | ||
1234 | |||
1235 | |||
1236 | static const u32 ar5416Bank6TPC[][3] = { | ||
1237 | |||
1238 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1239 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1240 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1241 | { 0x0000989c, 0x00e00000, 0x00e00000 }, | ||
1242 | { 0x0000989c, 0x005e0000, 0x005e0000 }, | ||
1243 | { 0x0000989c, 0x00120000, 0x00120000 }, | ||
1244 | { 0x0000989c, 0x00620000, 0x00620000 }, | ||
1245 | { 0x0000989c, 0x00020000, 0x00020000 }, | ||
1246 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1247 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1248 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1249 | { 0x0000989c, 0x40ff0000, 0x40ff0000 }, | ||
1250 | { 0x0000989c, 0x005f0000, 0x005f0000 }, | ||
1251 | { 0x0000989c, 0x00870000, 0x00870000 }, | ||
1252 | { 0x0000989c, 0x00f90000, 0x00f90000 }, | ||
1253 | { 0x0000989c, 0x007b0000, 0x007b0000 }, | ||
1254 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1255 | { 0x0000989c, 0x00f50000, 0x00f50000 }, | ||
1256 | { 0x0000989c, 0x00dc0000, 0x00dc0000 }, | ||
1257 | { 0x0000989c, 0x00110000, 0x00110000 }, | ||
1258 | { 0x0000989c, 0x006100a8, 0x006100a8 }, | ||
1259 | { 0x0000989c, 0x00423022, 0x00423022 }, | ||
1260 | { 0x0000989c, 0x2014008f, 0x2014008f }, | ||
1261 | { 0x0000989c, 0x00c40002, 0x00c40002 }, | ||
1262 | { 0x0000989c, 0x003000f2, 0x003000f2 }, | ||
1263 | { 0x0000989c, 0x00440016, 0x00440016 }, | ||
1264 | { 0x0000989c, 0x00410040, 0x00410040 }, | ||
1265 | { 0x0000989c, 0x0001805e, 0x0001805e }, | ||
1266 | { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, | ||
1267 | { 0x0000989c, 0x000000e1, 0x000000e1 }, | ||
1268 | { 0x0000989c, 0x00007080, 0x00007080 }, | ||
1269 | { 0x0000989c, 0x000000d4, 0x000000d4 }, | ||
1270 | { 0x000098d0, 0x0000000f, 0x0010000f }, | ||
1271 | }; | ||
1272 | |||
1273 | static const u32 ar5416Bank7[][2] = { | ||
1274 | { 0x0000989c, 0x00000500 }, | ||
1275 | { 0x0000989c, 0x00000800 }, | ||
1276 | { 0x000098cc, 0x0000000e }, | ||
1277 | }; | ||
1278 | |||
1279 | static const u32 ar5416Addac[][2] = { | ||
1280 | {0x0000989c, 0x00000000 }, | ||
1281 | {0x0000989c, 0x00000000 }, | ||
1282 | {0x0000989c, 0x00000000 }, | ||
1283 | {0x0000989c, 0x00000000 }, | ||
1284 | {0x0000989c, 0x00000000 }, | ||
1285 | {0x0000989c, 0x00000000 }, | ||
1286 | {0x0000989c, 0x00000000 }, | ||
1287 | {0x0000989c, 0x00000010 }, | ||
1288 | {0x0000989c, 0x00000000 }, | ||
1289 | {0x0000989c, 0x00000000 }, | ||
1290 | {0x0000989c, 0x00000000 }, | ||
1291 | {0x0000989c, 0x00000000 }, | ||
1292 | {0x0000989c, 0x00000000 }, | ||
1293 | {0x0000989c, 0x00000000 }, | ||
1294 | {0x0000989c, 0x00000000 }, | ||
1295 | {0x0000989c, 0x00000000 }, | ||
1296 | {0x0000989c, 0x00000000 }, | ||
1297 | {0x0000989c, 0x00000000 }, | ||
1298 | {0x0000989c, 0x00000000 }, | ||
1299 | {0x0000989c, 0x00000000 }, | ||
1300 | {0x0000989c, 0x00000000 }, | ||
1301 | {0x0000989c, 0x000000c0 }, | ||
1302 | {0x0000989c, 0x00000015 }, | ||
1303 | {0x0000989c, 0x00000000 }, | ||
1304 | {0x0000989c, 0x00000000 }, | ||
1305 | {0x0000989c, 0x00000000 }, | ||
1306 | {0x0000989c, 0x00000000 }, | ||
1307 | {0x0000989c, 0x00000000 }, | ||
1308 | {0x0000989c, 0x00000000 }, | ||
1309 | {0x0000989c, 0x00000000 }, | ||
1310 | {0x0000989c, 0x00000000 }, | ||
1311 | {0x000098cc, 0x00000000 }, | ||
1312 | }; | ||
1313 | |||
1314 | |||
1315 | static const u32 ar5416Modes_9160[][6] = { | ||
1316 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | ||
1317 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | ||
1318 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, | ||
1319 | { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, | ||
1320 | { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, | ||
1321 | { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, | ||
1322 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, | ||
1323 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, | ||
1324 | { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
1325 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, | ||
1326 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
1327 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, | ||
1328 | { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, | ||
1329 | { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | ||
1330 | { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | ||
1331 | { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | ||
1332 | { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, | ||
1333 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, | ||
1334 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, | ||
1335 | { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, | ||
1336 | { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | ||
1337 | { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, | ||
1338 | { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, | ||
1339 | { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, | ||
1340 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, | ||
1341 | { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, | ||
1342 | { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, | ||
1343 | { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, | ||
1344 | { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, | ||
1345 | { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, | ||
1346 | { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, | ||
1347 | { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, | ||
1348 | { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, | ||
1349 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | ||
1350 | { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, | ||
1351 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, | ||
1352 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, | ||
1353 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
1354 | { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
1355 | { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, | ||
1356 | { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, | ||
1357 | { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, | ||
1358 | { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, | ||
1359 | { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, | ||
1360 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, | ||
1361 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | ||
1362 | { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, | ||
1363 | { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, | ||
1364 | { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, | ||
1365 | { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, | ||
1366 | { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, | ||
1367 | { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, | ||
1368 | { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, | ||
1369 | { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, | ||
1370 | { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, | ||
1371 | { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, | ||
1372 | { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, | ||
1373 | { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, | ||
1374 | { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
1375 | { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
1376 | { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
1377 | }; | ||
1378 | |||
1379 | static const u32 ar5416Common_9160[][2] = { | ||
1380 | { 0x0000000c, 0x00000000 }, | ||
1381 | { 0x00000030, 0x00020015 }, | ||
1382 | { 0x00000034, 0x00000005 }, | ||
1383 | { 0x00000040, 0x00000000 }, | ||
1384 | { 0x00000044, 0x00000008 }, | ||
1385 | { 0x00000048, 0x00000008 }, | ||
1386 | { 0x0000004c, 0x00000010 }, | ||
1387 | { 0x00000050, 0x00000000 }, | ||
1388 | { 0x00000054, 0x0000001f }, | ||
1389 | { 0x00000800, 0x00000000 }, | ||
1390 | { 0x00000804, 0x00000000 }, | ||
1391 | { 0x00000808, 0x00000000 }, | ||
1392 | { 0x0000080c, 0x00000000 }, | ||
1393 | { 0x00000810, 0x00000000 }, | ||
1394 | { 0x00000814, 0x00000000 }, | ||
1395 | { 0x00000818, 0x00000000 }, | ||
1396 | { 0x0000081c, 0x00000000 }, | ||
1397 | { 0x00000820, 0x00000000 }, | ||
1398 | { 0x00000824, 0x00000000 }, | ||
1399 | { 0x00001040, 0x002ffc0f }, | ||
1400 | { 0x00001044, 0x002ffc0f }, | ||
1401 | { 0x00001048, 0x002ffc0f }, | ||
1402 | { 0x0000104c, 0x002ffc0f }, | ||
1403 | { 0x00001050, 0x002ffc0f }, | ||
1404 | { 0x00001054, 0x002ffc0f }, | ||
1405 | { 0x00001058, 0x002ffc0f }, | ||
1406 | { 0x0000105c, 0x002ffc0f }, | ||
1407 | { 0x00001060, 0x002ffc0f }, | ||
1408 | { 0x00001064, 0x002ffc0f }, | ||
1409 | { 0x00001230, 0x00000000 }, | ||
1410 | { 0x00001270, 0x00000000 }, | ||
1411 | { 0x00001038, 0x00000000 }, | ||
1412 | { 0x00001078, 0x00000000 }, | ||
1413 | { 0x000010b8, 0x00000000 }, | ||
1414 | { 0x000010f8, 0x00000000 }, | ||
1415 | { 0x00001138, 0x00000000 }, | ||
1416 | { 0x00001178, 0x00000000 }, | ||
1417 | { 0x000011b8, 0x00000000 }, | ||
1418 | { 0x000011f8, 0x00000000 }, | ||
1419 | { 0x00001238, 0x00000000 }, | ||
1420 | { 0x00001278, 0x00000000 }, | ||
1421 | { 0x000012b8, 0x00000000 }, | ||
1422 | { 0x000012f8, 0x00000000 }, | ||
1423 | { 0x00001338, 0x00000000 }, | ||
1424 | { 0x00001378, 0x00000000 }, | ||
1425 | { 0x000013b8, 0x00000000 }, | ||
1426 | { 0x000013f8, 0x00000000 }, | ||
1427 | { 0x00001438, 0x00000000 }, | ||
1428 | { 0x00001478, 0x00000000 }, | ||
1429 | { 0x000014b8, 0x00000000 }, | ||
1430 | { 0x000014f8, 0x00000000 }, | ||
1431 | { 0x00001538, 0x00000000 }, | ||
1432 | { 0x00001578, 0x00000000 }, | ||
1433 | { 0x000015b8, 0x00000000 }, | ||
1434 | { 0x000015f8, 0x00000000 }, | ||
1435 | { 0x00001638, 0x00000000 }, | ||
1436 | { 0x00001678, 0x00000000 }, | ||
1437 | { 0x000016b8, 0x00000000 }, | ||
1438 | { 0x000016f8, 0x00000000 }, | ||
1439 | { 0x00001738, 0x00000000 }, | ||
1440 | { 0x00001778, 0x00000000 }, | ||
1441 | { 0x000017b8, 0x00000000 }, | ||
1442 | { 0x000017f8, 0x00000000 }, | ||
1443 | { 0x0000103c, 0x00000000 }, | ||
1444 | { 0x0000107c, 0x00000000 }, | ||
1445 | { 0x000010bc, 0x00000000 }, | ||
1446 | { 0x000010fc, 0x00000000 }, | ||
1447 | { 0x0000113c, 0x00000000 }, | ||
1448 | { 0x0000117c, 0x00000000 }, | ||
1449 | { 0x000011bc, 0x00000000 }, | ||
1450 | { 0x000011fc, 0x00000000 }, | ||
1451 | { 0x0000123c, 0x00000000 }, | ||
1452 | { 0x0000127c, 0x00000000 }, | ||
1453 | { 0x000012bc, 0x00000000 }, | ||
1454 | { 0x000012fc, 0x00000000 }, | ||
1455 | { 0x0000133c, 0x00000000 }, | ||
1456 | { 0x0000137c, 0x00000000 }, | ||
1457 | { 0x000013bc, 0x00000000 }, | ||
1458 | { 0x000013fc, 0x00000000 }, | ||
1459 | { 0x0000143c, 0x00000000 }, | ||
1460 | { 0x0000147c, 0x00000000 }, | ||
1461 | { 0x00004030, 0x00000002 }, | ||
1462 | { 0x0000403c, 0x00000002 }, | ||
1463 | { 0x00007010, 0x00000020 }, | ||
1464 | { 0x00007038, 0x000004c2 }, | ||
1465 | { 0x00008004, 0x00000000 }, | ||
1466 | { 0x00008008, 0x00000000 }, | ||
1467 | { 0x0000800c, 0x00000000 }, | ||
1468 | { 0x00008018, 0x00000700 }, | ||
1469 | { 0x00008020, 0x00000000 }, | ||
1470 | { 0x00008038, 0x00000000 }, | ||
1471 | { 0x0000803c, 0x00000000 }, | ||
1472 | { 0x00008048, 0x40000000 }, | ||
1473 | { 0x00008054, 0x00000000 }, | ||
1474 | { 0x00008058, 0x00000000 }, | ||
1475 | { 0x0000805c, 0x000fc78f }, | ||
1476 | { 0x00008060, 0x0000000f }, | ||
1477 | { 0x00008064, 0x00000000 }, | ||
1478 | { 0x000080c0, 0x2a82301a }, | ||
1479 | { 0x000080c4, 0x05dc01e0 }, | ||
1480 | { 0x000080c8, 0x1f402710 }, | ||
1481 | { 0x000080cc, 0x01f40000 }, | ||
1482 | { 0x000080d0, 0x00001e00 }, | ||
1483 | { 0x000080d4, 0x00000000 }, | ||
1484 | { 0x000080d8, 0x00400000 }, | ||
1485 | { 0x000080e0, 0xffffffff }, | ||
1486 | { 0x000080e4, 0x0000ffff }, | ||
1487 | { 0x000080e8, 0x003f3f3f }, | ||
1488 | { 0x000080ec, 0x00000000 }, | ||
1489 | { 0x000080f0, 0x00000000 }, | ||
1490 | { 0x000080f4, 0x00000000 }, | ||
1491 | { 0x000080f8, 0x00000000 }, | ||
1492 | { 0x000080fc, 0x00020000 }, | ||
1493 | { 0x00008100, 0x00020000 }, | ||
1494 | { 0x00008104, 0x00000001 }, | ||
1495 | { 0x00008108, 0x00000052 }, | ||
1496 | { 0x0000810c, 0x00000000 }, | ||
1497 | { 0x00008110, 0x00000168 }, | ||
1498 | { 0x00008118, 0x000100aa }, | ||
1499 | { 0x0000811c, 0x00003210 }, | ||
1500 | { 0x00008120, 0x08f04800 }, | ||
1501 | { 0x00008124, 0x00000000 }, | ||
1502 | { 0x00008128, 0x00000000 }, | ||
1503 | { 0x0000812c, 0x00000000 }, | ||
1504 | { 0x00008130, 0x00000000 }, | ||
1505 | { 0x00008134, 0x00000000 }, | ||
1506 | { 0x00008138, 0x00000000 }, | ||
1507 | { 0x0000813c, 0x00000000 }, | ||
1508 | { 0x00008144, 0x00000000 }, | ||
1509 | { 0x00008168, 0x00000000 }, | ||
1510 | { 0x0000816c, 0x00000000 }, | ||
1511 | { 0x00008170, 0x32143320 }, | ||
1512 | { 0x00008174, 0xfaa4fa50 }, | ||
1513 | { 0x00008178, 0x00000100 }, | ||
1514 | { 0x0000817c, 0x00000000 }, | ||
1515 | { 0x000081c4, 0x00000000 }, | ||
1516 | { 0x000081d0, 0x00003210 }, | ||
1517 | { 0x000081ec, 0x00000000 }, | ||
1518 | { 0x000081f0, 0x00000000 }, | ||
1519 | { 0x000081f4, 0x00000000 }, | ||
1520 | { 0x000081f8, 0x00000000 }, | ||
1521 | { 0x000081fc, 0x00000000 }, | ||
1522 | { 0x00008200, 0x00000000 }, | ||
1523 | { 0x00008204, 0x00000000 }, | ||
1524 | { 0x00008208, 0x00000000 }, | ||
1525 | { 0x0000820c, 0x00000000 }, | ||
1526 | { 0x00008210, 0x00000000 }, | ||
1527 | { 0x00008214, 0x00000000 }, | ||
1528 | { 0x00008218, 0x00000000 }, | ||
1529 | { 0x0000821c, 0x00000000 }, | ||
1530 | { 0x00008220, 0x00000000 }, | ||
1531 | { 0x00008224, 0x00000000 }, | ||
1532 | { 0x00008228, 0x00000000 }, | ||
1533 | { 0x0000822c, 0x00000000 }, | ||
1534 | { 0x00008230, 0x00000000 }, | ||
1535 | { 0x00008234, 0x00000000 }, | ||
1536 | { 0x00008238, 0x00000000 }, | ||
1537 | { 0x0000823c, 0x00000000 }, | ||
1538 | { 0x00008240, 0x00100000 }, | ||
1539 | { 0x00008244, 0x0010f400 }, | ||
1540 | { 0x00008248, 0x00000100 }, | ||
1541 | { 0x0000824c, 0x0001e800 }, | ||
1542 | { 0x00008250, 0x00000000 }, | ||
1543 | { 0x00008254, 0x00000000 }, | ||
1544 | { 0x00008258, 0x00000000 }, | ||
1545 | { 0x0000825c, 0x400000ff }, | ||
1546 | { 0x00008260, 0x00080922 }, | ||
1547 | { 0x00008270, 0x00000000 }, | ||
1548 | { 0x00008274, 0x40000000 }, | ||
1549 | { 0x00008278, 0x003e4180 }, | ||
1550 | { 0x0000827c, 0x00000000 }, | ||
1551 | { 0x00008284, 0x0000002c }, | ||
1552 | { 0x00008288, 0x0000002c }, | ||
1553 | { 0x0000828c, 0x00000000 }, | ||
1554 | { 0x00008294, 0x00000000 }, | ||
1555 | { 0x00008298, 0x00000000 }, | ||
1556 | { 0x00008300, 0x00000000 }, | ||
1557 | { 0x00008304, 0x00000000 }, | ||
1558 | { 0x00008308, 0x00000000 }, | ||
1559 | { 0x0000830c, 0x00000000 }, | ||
1560 | { 0x00008310, 0x00000000 }, | ||
1561 | { 0x00008314, 0x00000000 }, | ||
1562 | { 0x00008318, 0x00000000 }, | ||
1563 | { 0x00008328, 0x00000000 }, | ||
1564 | { 0x0000832c, 0x00000007 }, | ||
1565 | { 0x00008330, 0x00000302 }, | ||
1566 | { 0x00008334, 0x00000e00 }, | ||
1567 | { 0x00008338, 0x00000000 }, | ||
1568 | { 0x0000833c, 0x00000000 }, | ||
1569 | { 0x00008340, 0x000107ff }, | ||
1570 | { 0x00009808, 0x00000000 }, | ||
1571 | { 0x0000980c, 0xad848e19 }, | ||
1572 | { 0x00009810, 0x7d14e000 }, | ||
1573 | { 0x00009814, 0x9c0a9f6b }, | ||
1574 | { 0x0000981c, 0x00000000 }, | ||
1575 | { 0x0000982c, 0x0000a000 }, | ||
1576 | { 0x00009830, 0x00000000 }, | ||
1577 | { 0x0000983c, 0x00200400 }, | ||
1578 | { 0x00009840, 0x206a01ae }, | ||
1579 | { 0x0000984c, 0x1284233c }, | ||
1580 | { 0x00009854, 0x00000859 }, | ||
1581 | { 0x00009900, 0x00000000 }, | ||
1582 | { 0x00009904, 0x00000000 }, | ||
1583 | { 0x00009908, 0x00000000 }, | ||
1584 | { 0x0000990c, 0x00000000 }, | ||
1585 | { 0x0000991c, 0x10000fff }, | ||
1586 | { 0x00009920, 0x05100000 }, | ||
1587 | { 0x0000a920, 0x05100000 }, | ||
1588 | { 0x0000b920, 0x05100000 }, | ||
1589 | { 0x00009928, 0x00000001 }, | ||
1590 | { 0x0000992c, 0x00000004 }, | ||
1591 | { 0x00009934, 0x1e1f2022 }, | ||
1592 | { 0x00009938, 0x0a0b0c0d }, | ||
1593 | { 0x0000993c, 0x00000000 }, | ||
1594 | { 0x00009948, 0x9280b212 }, | ||
1595 | { 0x0000994c, 0x00020028 }, | ||
1596 | { 0x00009954, 0x5f3ca3de }, | ||
1597 | { 0x00009958, 0x2108ecff }, | ||
1598 | { 0x00009940, 0x00750604 }, | ||
1599 | { 0x0000c95c, 0x004b6a8e }, | ||
1600 | { 0x0000c968, 0x000003ce }, | ||
1601 | { 0x00009970, 0x190fb515 }, | ||
1602 | { 0x00009974, 0x00000000 }, | ||
1603 | { 0x00009978, 0x00000001 }, | ||
1604 | { 0x0000997c, 0x00000000 }, | ||
1605 | { 0x00009980, 0x00000000 }, | ||
1606 | { 0x00009984, 0x00000000 }, | ||
1607 | { 0x00009988, 0x00000000 }, | ||
1608 | { 0x0000998c, 0x00000000 }, | ||
1609 | { 0x00009990, 0x00000000 }, | ||
1610 | { 0x00009994, 0x00000000 }, | ||
1611 | { 0x00009998, 0x00000000 }, | ||
1612 | { 0x0000999c, 0x00000000 }, | ||
1613 | { 0x000099a0, 0x00000000 }, | ||
1614 | { 0x000099a4, 0x00000001 }, | ||
1615 | { 0x000099a8, 0x201fff00 }, | ||
1616 | { 0x000099ac, 0x006f0000 }, | ||
1617 | { 0x000099b0, 0x03051000 }, | ||
1618 | { 0x000099dc, 0x00000000 }, | ||
1619 | { 0x000099e0, 0x00000200 }, | ||
1620 | { 0x000099e4, 0xaaaaaaaa }, | ||
1621 | { 0x000099e8, 0x3c466478 }, | ||
1622 | { 0x000099ec, 0x0cc80caa }, | ||
1623 | { 0x000099fc, 0x00001042 }, | ||
1624 | { 0x00009b00, 0x00000000 }, | ||
1625 | { 0x00009b04, 0x00000001 }, | ||
1626 | { 0x00009b08, 0x00000002 }, | ||
1627 | { 0x00009b0c, 0x00000003 }, | ||
1628 | { 0x00009b10, 0x00000004 }, | ||
1629 | { 0x00009b14, 0x00000005 }, | ||
1630 | { 0x00009b18, 0x00000008 }, | ||
1631 | { 0x00009b1c, 0x00000009 }, | ||
1632 | { 0x00009b20, 0x0000000a }, | ||
1633 | { 0x00009b24, 0x0000000b }, | ||
1634 | { 0x00009b28, 0x0000000c }, | ||
1635 | { 0x00009b2c, 0x0000000d }, | ||
1636 | { 0x00009b30, 0x00000010 }, | ||
1637 | { 0x00009b34, 0x00000011 }, | ||
1638 | { 0x00009b38, 0x00000012 }, | ||
1639 | { 0x00009b3c, 0x00000013 }, | ||
1640 | { 0x00009b40, 0x00000014 }, | ||
1641 | { 0x00009b44, 0x00000015 }, | ||
1642 | { 0x00009b48, 0x00000018 }, | ||
1643 | { 0x00009b4c, 0x00000019 }, | ||
1644 | { 0x00009b50, 0x0000001a }, | ||
1645 | { 0x00009b54, 0x0000001b }, | ||
1646 | { 0x00009b58, 0x0000001c }, | ||
1647 | { 0x00009b5c, 0x0000001d }, | ||
1648 | { 0x00009b60, 0x00000020 }, | ||
1649 | { 0x00009b64, 0x00000021 }, | ||
1650 | { 0x00009b68, 0x00000022 }, | ||
1651 | { 0x00009b6c, 0x00000023 }, | ||
1652 | { 0x00009b70, 0x00000024 }, | ||
1653 | { 0x00009b74, 0x00000025 }, | ||
1654 | { 0x00009b78, 0x00000028 }, | ||
1655 | { 0x00009b7c, 0x00000029 }, | ||
1656 | { 0x00009b80, 0x0000002a }, | ||
1657 | { 0x00009b84, 0x0000002b }, | ||
1658 | { 0x00009b88, 0x0000002c }, | ||
1659 | { 0x00009b8c, 0x0000002d }, | ||
1660 | { 0x00009b90, 0x00000030 }, | ||
1661 | { 0x00009b94, 0x00000031 }, | ||
1662 | { 0x00009b98, 0x00000032 }, | ||
1663 | { 0x00009b9c, 0x00000033 }, | ||
1664 | { 0x00009ba0, 0x00000034 }, | ||
1665 | { 0x00009ba4, 0x00000035 }, | ||
1666 | { 0x00009ba8, 0x00000035 }, | ||
1667 | { 0x00009bac, 0x00000035 }, | ||
1668 | { 0x00009bb0, 0x00000035 }, | ||
1669 | { 0x00009bb4, 0x00000035 }, | ||
1670 | { 0x00009bb8, 0x00000035 }, | ||
1671 | { 0x00009bbc, 0x00000035 }, | ||
1672 | { 0x00009bc0, 0x00000035 }, | ||
1673 | { 0x00009bc4, 0x00000035 }, | ||
1674 | { 0x00009bc8, 0x00000035 }, | ||
1675 | { 0x00009bcc, 0x00000035 }, | ||
1676 | { 0x00009bd0, 0x00000035 }, | ||
1677 | { 0x00009bd4, 0x00000035 }, | ||
1678 | { 0x00009bd8, 0x00000035 }, | ||
1679 | { 0x00009bdc, 0x00000035 }, | ||
1680 | { 0x00009be0, 0x00000035 }, | ||
1681 | { 0x00009be4, 0x00000035 }, | ||
1682 | { 0x00009be8, 0x00000035 }, | ||
1683 | { 0x00009bec, 0x00000035 }, | ||
1684 | { 0x00009bf0, 0x00000035 }, | ||
1685 | { 0x00009bf4, 0x00000035 }, | ||
1686 | { 0x00009bf8, 0x00000010 }, | ||
1687 | { 0x00009bfc, 0x0000001a }, | ||
1688 | { 0x0000a210, 0x40806333 }, | ||
1689 | { 0x0000a214, 0x00106c10 }, | ||
1690 | { 0x0000a218, 0x009c4060 }, | ||
1691 | { 0x0000a220, 0x018830c6 }, | ||
1692 | { 0x0000a224, 0x00000400 }, | ||
1693 | { 0x0000a228, 0x001a0bb5 }, | ||
1694 | { 0x0000a22c, 0x00000000 }, | ||
1695 | { 0x0000a234, 0x20202020 }, | ||
1696 | { 0x0000a238, 0x20202020 }, | ||
1697 | { 0x0000a23c, 0x13c889af }, | ||
1698 | { 0x0000a240, 0x38490a20 }, | ||
1699 | { 0x0000a244, 0x00007bb6 }, | ||
1700 | { 0x0000a248, 0x0fff3ffc }, | ||
1701 | { 0x0000a24c, 0x00000001 }, | ||
1702 | { 0x0000a250, 0x0000a000 }, | ||
1703 | { 0x0000a254, 0x00000000 }, | ||
1704 | { 0x0000a258, 0x0cc75380 }, | ||
1705 | { 0x0000a25c, 0x0f0f0f01 }, | ||
1706 | { 0x0000a260, 0xdfa91f01 }, | ||
1707 | { 0x0000a268, 0x00000001 }, | ||
1708 | { 0x0000a26c, 0x0ebae9c6 }, | ||
1709 | { 0x0000b26c, 0x0ebae9c6 }, | ||
1710 | { 0x0000c26c, 0x0ebae9c6 }, | ||
1711 | { 0x0000d270, 0x00820820 }, | ||
1712 | { 0x0000a278, 0x1ce739ce }, | ||
1713 | { 0x0000a27c, 0x050701ce }, | ||
1714 | { 0x0000a338, 0x00000000 }, | ||
1715 | { 0x0000a33c, 0x00000000 }, | ||
1716 | { 0x0000a340, 0x00000000 }, | ||
1717 | { 0x0000a344, 0x00000000 }, | ||
1718 | { 0x0000a348, 0x3fffffff }, | ||
1719 | { 0x0000a34c, 0x3fffffff }, | ||
1720 | { 0x0000a350, 0x3fffffff }, | ||
1721 | { 0x0000a354, 0x0003ffff }, | ||
1722 | { 0x0000a358, 0x79a8aa33 }, | ||
1723 | { 0x0000d35c, 0x07ffffef }, | ||
1724 | { 0x0000d360, 0x0fffffe7 }, | ||
1725 | { 0x0000d364, 0x17ffffe5 }, | ||
1726 | { 0x0000d368, 0x1fffffe4 }, | ||
1727 | { 0x0000d36c, 0x37ffffe3 }, | ||
1728 | { 0x0000d370, 0x3fffffe3 }, | ||
1729 | { 0x0000d374, 0x57ffffe3 }, | ||
1730 | { 0x0000d378, 0x5fffffe2 }, | ||
1731 | { 0x0000d37c, 0x7fffffe2 }, | ||
1732 | { 0x0000d380, 0x7f3c7bba }, | ||
1733 | { 0x0000d384, 0xf3307ff0 }, | ||
1734 | { 0x0000a388, 0x0c000000 }, | ||
1735 | { 0x0000a38c, 0x20202020 }, | ||
1736 | { 0x0000a390, 0x20202020 }, | ||
1737 | { 0x0000a394, 0x1ce739ce }, | ||
1738 | { 0x0000a398, 0x000001ce }, | ||
1739 | { 0x0000a39c, 0x00000001 }, | ||
1740 | { 0x0000a3a0, 0x00000000 }, | ||
1741 | { 0x0000a3a4, 0x00000000 }, | ||
1742 | { 0x0000a3a8, 0x00000000 }, | ||
1743 | { 0x0000a3ac, 0x00000000 }, | ||
1744 | { 0x0000a3b0, 0x00000000 }, | ||
1745 | { 0x0000a3b4, 0x00000000 }, | ||
1746 | { 0x0000a3b8, 0x00000000 }, | ||
1747 | { 0x0000a3bc, 0x00000000 }, | ||
1748 | { 0x0000a3c0, 0x00000000 }, | ||
1749 | { 0x0000a3c4, 0x00000000 }, | ||
1750 | { 0x0000a3c8, 0x00000246 }, | ||
1751 | { 0x0000a3cc, 0x20202020 }, | ||
1752 | { 0x0000a3d0, 0x20202020 }, | ||
1753 | { 0x0000a3d4, 0x20202020 }, | ||
1754 | { 0x0000a3dc, 0x1ce739ce }, | ||
1755 | { 0x0000a3e0, 0x000001ce }, | ||
1756 | }; | ||
1757 | |||
1758 | static const u32 ar5416Bank0_9160[][2] = { | ||
1759 | { 0x000098b0, 0x1e5795e5 }, | ||
1760 | { 0x000098e0, 0x02008020 }, | ||
1761 | }; | ||
1762 | |||
1763 | static const u32 ar5416BB_RfGain_9160[][3] = { | ||
1764 | { 0x00009a00, 0x00000000, 0x00000000 }, | ||
1765 | { 0x00009a04, 0x00000040, 0x00000040 }, | ||
1766 | { 0x00009a08, 0x00000080, 0x00000080 }, | ||
1767 | { 0x00009a0c, 0x000001a1, 0x00000141 }, | ||
1768 | { 0x00009a10, 0x000001e1, 0x00000181 }, | ||
1769 | { 0x00009a14, 0x00000021, 0x000001c1 }, | ||
1770 | { 0x00009a18, 0x00000061, 0x00000001 }, | ||
1771 | { 0x00009a1c, 0x00000168, 0x00000041 }, | ||
1772 | { 0x00009a20, 0x000001a8, 0x000001a8 }, | ||
1773 | { 0x00009a24, 0x000001e8, 0x000001e8 }, | ||
1774 | { 0x00009a28, 0x00000028, 0x00000028 }, | ||
1775 | { 0x00009a2c, 0x00000068, 0x00000068 }, | ||
1776 | { 0x00009a30, 0x00000189, 0x000000a8 }, | ||
1777 | { 0x00009a34, 0x000001c9, 0x00000169 }, | ||
1778 | { 0x00009a38, 0x00000009, 0x000001a9 }, | ||
1779 | { 0x00009a3c, 0x00000049, 0x000001e9 }, | ||
1780 | { 0x00009a40, 0x00000089, 0x00000029 }, | ||
1781 | { 0x00009a44, 0x00000170, 0x00000069 }, | ||
1782 | { 0x00009a48, 0x000001b0, 0x00000190 }, | ||
1783 | { 0x00009a4c, 0x000001f0, 0x000001d0 }, | ||
1784 | { 0x00009a50, 0x00000030, 0x00000010 }, | ||
1785 | { 0x00009a54, 0x00000070, 0x00000050 }, | ||
1786 | { 0x00009a58, 0x00000191, 0x00000090 }, | ||
1787 | { 0x00009a5c, 0x000001d1, 0x00000151 }, | ||
1788 | { 0x00009a60, 0x00000011, 0x00000191 }, | ||
1789 | { 0x00009a64, 0x00000051, 0x000001d1 }, | ||
1790 | { 0x00009a68, 0x00000091, 0x00000011 }, | ||
1791 | { 0x00009a6c, 0x000001b8, 0x00000051 }, | ||
1792 | { 0x00009a70, 0x000001f8, 0x00000198 }, | ||
1793 | { 0x00009a74, 0x00000038, 0x000001d8 }, | ||
1794 | { 0x00009a78, 0x00000078, 0x00000018 }, | ||
1795 | { 0x00009a7c, 0x00000199, 0x00000058 }, | ||
1796 | { 0x00009a80, 0x000001d9, 0x00000098 }, | ||
1797 | { 0x00009a84, 0x00000019, 0x00000159 }, | ||
1798 | { 0x00009a88, 0x00000059, 0x00000199 }, | ||
1799 | { 0x00009a8c, 0x00000099, 0x000001d9 }, | ||
1800 | { 0x00009a90, 0x000000d9, 0x00000019 }, | ||
1801 | { 0x00009a94, 0x000000f9, 0x00000059 }, | ||
1802 | { 0x00009a98, 0x000000f9, 0x00000099 }, | ||
1803 | { 0x00009a9c, 0x000000f9, 0x000000d9 }, | ||
1804 | { 0x00009aa0, 0x000000f9, 0x000000f9 }, | ||
1805 | { 0x00009aa4, 0x000000f9, 0x000000f9 }, | ||
1806 | { 0x00009aa8, 0x000000f9, 0x000000f9 }, | ||
1807 | { 0x00009aac, 0x000000f9, 0x000000f9 }, | ||
1808 | { 0x00009ab0, 0x000000f9, 0x000000f9 }, | ||
1809 | { 0x00009ab4, 0x000000f9, 0x000000f9 }, | ||
1810 | { 0x00009ab8, 0x000000f9, 0x000000f9 }, | ||
1811 | { 0x00009abc, 0x000000f9, 0x000000f9 }, | ||
1812 | { 0x00009ac0, 0x000000f9, 0x000000f9 }, | ||
1813 | { 0x00009ac4, 0x000000f9, 0x000000f9 }, | ||
1814 | { 0x00009ac8, 0x000000f9, 0x000000f9 }, | ||
1815 | { 0x00009acc, 0x000000f9, 0x000000f9 }, | ||
1816 | { 0x00009ad0, 0x000000f9, 0x000000f9 }, | ||
1817 | { 0x00009ad4, 0x000000f9, 0x000000f9 }, | ||
1818 | { 0x00009ad8, 0x000000f9, 0x000000f9 }, | ||
1819 | { 0x00009adc, 0x000000f9, 0x000000f9 }, | ||
1820 | { 0x00009ae0, 0x000000f9, 0x000000f9 }, | ||
1821 | { 0x00009ae4, 0x000000f9, 0x000000f9 }, | ||
1822 | { 0x00009ae8, 0x000000f9, 0x000000f9 }, | ||
1823 | { 0x00009aec, 0x000000f9, 0x000000f9 }, | ||
1824 | { 0x00009af0, 0x000000f9, 0x000000f9 }, | ||
1825 | { 0x00009af4, 0x000000f9, 0x000000f9 }, | ||
1826 | { 0x00009af8, 0x000000f9, 0x000000f9 }, | ||
1827 | { 0x00009afc, 0x000000f9, 0x000000f9 }, | ||
1828 | }; | ||
1829 | |||
1830 | static const u32 ar5416Bank1_9160[][2] = { | ||
1831 | { 0x000098b0, 0x02108421 }, | ||
1832 | { 0x000098ec, 0x00000008 }, | ||
1833 | }; | ||
1834 | |||
1835 | static const u32 ar5416Bank2_9160[][2] = { | ||
1836 | { 0x000098b0, 0x0e73ff17 }, | ||
1837 | { 0x000098e0, 0x00000420 }, | ||
1838 | }; | ||
1839 | |||
1840 | static const u32 ar5416Bank3_9160[][3] = { | ||
1841 | { 0x000098f0, 0x01400018, 0x01c00018 }, | ||
1842 | }; | ||
1843 | |||
1844 | static const u32 ar5416Bank6_9160[][3] = { | ||
1845 | |||
1846 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1847 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1848 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1849 | { 0x0000989c, 0x00e00000, 0x00e00000 }, | ||
1850 | { 0x0000989c, 0x005e0000, 0x005e0000 }, | ||
1851 | { 0x0000989c, 0x00120000, 0x00120000 }, | ||
1852 | { 0x0000989c, 0x00620000, 0x00620000 }, | ||
1853 | { 0x0000989c, 0x00020000, 0x00020000 }, | ||
1854 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1855 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1856 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1857 | { 0x0000989c, 0x40ff0000, 0x40ff0000 }, | ||
1858 | { 0x0000989c, 0x005f0000, 0x005f0000 }, | ||
1859 | { 0x0000989c, 0x00870000, 0x00870000 }, | ||
1860 | { 0x0000989c, 0x00f90000, 0x00f90000 }, | ||
1861 | { 0x0000989c, 0x007b0000, 0x007b0000 }, | ||
1862 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1863 | { 0x0000989c, 0x00f50000, 0x00f50000 }, | ||
1864 | { 0x0000989c, 0x00dc0000, 0x00dc0000 }, | ||
1865 | { 0x0000989c, 0x00110000, 0x00110000 }, | ||
1866 | { 0x0000989c, 0x006100a8, 0x006100a8 }, | ||
1867 | { 0x0000989c, 0x004210a2, 0x004210a2 }, | ||
1868 | { 0x0000989c, 0x0014008f, 0x0014008f }, | ||
1869 | { 0x0000989c, 0x00c40003, 0x00c40003 }, | ||
1870 | { 0x0000989c, 0x003000f2, 0x003000f2 }, | ||
1871 | { 0x0000989c, 0x00440016, 0x00440016 }, | ||
1872 | { 0x0000989c, 0x00410040, 0x00410040 }, | ||
1873 | { 0x0000989c, 0x0001805e, 0x0001805e }, | ||
1874 | { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, | ||
1875 | { 0x0000989c, 0x000000f1, 0x000000f1 }, | ||
1876 | { 0x0000989c, 0x00002081, 0x00002081 }, | ||
1877 | { 0x0000989c, 0x000000d4, 0x000000d4 }, | ||
1878 | { 0x000098d0, 0x0000000f, 0x0010000f }, | ||
1879 | }; | ||
1880 | |||
1881 | static const u32 ar5416Bank6TPC_9160[][3] = { | ||
1882 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1883 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1884 | { 0x0000989c, 0x00000000, 0x00000000 }, | ||
1885 | { 0x0000989c, 0x00e00000, 0x00e00000 }, | ||
1886 | { 0x0000989c, 0x005e0000, 0x005e0000 }, | ||
1887 | { 0x0000989c, 0x00120000, 0x00120000 }, | ||
1888 | { 0x0000989c, 0x00620000, 0x00620000 }, | ||
1889 | { 0x0000989c, 0x00020000, 0x00020000 }, | ||
1890 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1891 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1892 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1893 | { 0x0000989c, 0x40ff0000, 0x40ff0000 }, | ||
1894 | { 0x0000989c, 0x005f0000, 0x005f0000 }, | ||
1895 | { 0x0000989c, 0x00870000, 0x00870000 }, | ||
1896 | { 0x0000989c, 0x00f90000, 0x00f90000 }, | ||
1897 | { 0x0000989c, 0x007b0000, 0x007b0000 }, | ||
1898 | { 0x0000989c, 0x00ff0000, 0x00ff0000 }, | ||
1899 | { 0x0000989c, 0x00f50000, 0x00f50000 }, | ||
1900 | { 0x0000989c, 0x00dc0000, 0x00dc0000 }, | ||
1901 | { 0x0000989c, 0x00110000, 0x00110000 }, | ||
1902 | { 0x0000989c, 0x006100a8, 0x006100a8 }, | ||
1903 | { 0x0000989c, 0x00423022, 0x00423022 }, | ||
1904 | { 0x0000989c, 0x2014008f, 0x2014008f }, | ||
1905 | { 0x0000989c, 0x00c40002, 0x00c40002 }, | ||
1906 | { 0x0000989c, 0x003000f2, 0x003000f2 }, | ||
1907 | { 0x0000989c, 0x00440016, 0x00440016 }, | ||
1908 | { 0x0000989c, 0x00410040, 0x00410040 }, | ||
1909 | { 0x0000989c, 0x0001805e, 0x0001805e }, | ||
1910 | { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, | ||
1911 | { 0x0000989c, 0x000000e1, 0x000000e1 }, | ||
1912 | { 0x0000989c, 0x00007080, 0x00007080 }, | ||
1913 | { 0x0000989c, 0x000000d4, 0x000000d4 }, | ||
1914 | { 0x000098d0, 0x0000000f, 0x0010000f }, | ||
1915 | }; | ||
1916 | |||
1917 | static const u32 ar5416Bank7_9160[][2] = { | ||
1918 | { 0x0000989c, 0x00000500 }, | ||
1919 | { 0x0000989c, 0x00000800 }, | ||
1920 | { 0x000098cc, 0x0000000e }, | ||
1921 | }; | ||
1922 | |||
1923 | |||
1924 | static u32 ar5416Addac_9160[][2] = { | ||
1925 | {0x0000989c, 0x00000000 }, | ||
1926 | {0x0000989c, 0x00000000 }, | ||
1927 | {0x0000989c, 0x00000000 }, | ||
1928 | {0x0000989c, 0x00000000 }, | ||
1929 | {0x0000989c, 0x00000000 }, | ||
1930 | {0x0000989c, 0x00000000 }, | ||
1931 | {0x0000989c, 0x000000c0 }, | ||
1932 | {0x0000989c, 0x00000018 }, | ||
1933 | {0x0000989c, 0x00000004 }, | ||
1934 | {0x0000989c, 0x00000000 }, | ||
1935 | {0x0000989c, 0x00000000 }, | ||
1936 | {0x0000989c, 0x00000000 }, | ||
1937 | {0x0000989c, 0x00000000 }, | ||
1938 | {0x0000989c, 0x00000000 }, | ||
1939 | {0x0000989c, 0x00000000 }, | ||
1940 | {0x0000989c, 0x00000000 }, | ||
1941 | {0x0000989c, 0x00000000 }, | ||
1942 | {0x0000989c, 0x00000000 }, | ||
1943 | {0x0000989c, 0x00000000 }, | ||
1944 | {0x0000989c, 0x00000000 }, | ||
1945 | {0x0000989c, 0x00000000 }, | ||
1946 | {0x0000989c, 0x000000c0 }, | ||
1947 | {0x0000989c, 0x00000019 }, | ||
1948 | {0x0000989c, 0x00000004 }, | ||
1949 | {0x0000989c, 0x00000000 }, | ||
1950 | {0x0000989c, 0x00000000 }, | ||
1951 | {0x0000989c, 0x00000000 }, | ||
1952 | {0x0000989c, 0x00000004 }, | ||
1953 | {0x0000989c, 0x00000003 }, | ||
1954 | {0x0000989c, 0x00000008 }, | ||
1955 | {0x0000989c, 0x00000000 }, | ||
1956 | {0x000098cc, 0x00000000 }, | ||
1957 | }; | ||
1958 | |||
1959 | |||
1960 | static u32 ar5416Addac_91601_1[][2] = { | ||
1961 | {0x0000989c, 0x00000000 }, | ||
1962 | {0x0000989c, 0x00000000 }, | ||
1963 | {0x0000989c, 0x00000000 }, | ||
1964 | {0x0000989c, 0x00000000 }, | ||
1965 | {0x0000989c, 0x00000000 }, | ||
1966 | {0x0000989c, 0x00000000 }, | ||
1967 | {0x0000989c, 0x000000c0 }, | ||
1968 | {0x0000989c, 0x00000018 }, | ||
1969 | {0x0000989c, 0x00000004 }, | ||
1970 | {0x0000989c, 0x00000000 }, | ||
1971 | {0x0000989c, 0x00000000 }, | ||
1972 | {0x0000989c, 0x00000000 }, | ||
1973 | {0x0000989c, 0x00000000 }, | ||
1974 | {0x0000989c, 0x00000000 }, | ||
1975 | {0x0000989c, 0x00000000 }, | ||
1976 | {0x0000989c, 0x00000000 }, | ||
1977 | {0x0000989c, 0x00000000 }, | ||
1978 | {0x0000989c, 0x00000000 }, | ||
1979 | {0x0000989c, 0x00000000 }, | ||
1980 | {0x0000989c, 0x00000000 }, | ||
1981 | {0x0000989c, 0x00000000 }, | ||
1982 | {0x0000989c, 0x000000c0 }, | ||
1983 | {0x0000989c, 0x00000019 }, | ||
1984 | {0x0000989c, 0x00000004 }, | ||
1985 | {0x0000989c, 0x00000000 }, | ||
1986 | {0x0000989c, 0x00000000 }, | ||
1987 | {0x0000989c, 0x00000000 }, | ||
1988 | {0x0000989c, 0x00000000 }, | ||
1989 | {0x0000989c, 0x00000000 }, | ||
1990 | {0x0000989c, 0x00000000 }, | ||
1991 | {0x0000989c, 0x00000000 }, | ||
1992 | {0x000098cc, 0x00000000 }, | ||
1993 | }; | ||
1994 | |||
1995 | |||
1996 | |||
1997 | static const u32 ar9280Modes_9280[][6] = { | ||
1998 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | ||
1999 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | ||
2000 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, | ||
2001 | { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, | ||
2002 | { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 }, | ||
2003 | { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, | ||
2004 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, | ||
2005 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, | ||
2006 | { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
2007 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, | ||
2008 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
2009 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, | ||
2010 | { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, | ||
2011 | { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, | ||
2012 | { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, | ||
2013 | { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, | ||
2014 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, | ||
2015 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, | ||
2016 | { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 }, | ||
2017 | { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | ||
2018 | { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 }, | ||
2019 | { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, | ||
2020 | { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, | ||
2021 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, | ||
2022 | { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, | ||
2023 | { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 }, | ||
2024 | { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, | ||
2025 | { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, | ||
2026 | { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, | ||
2027 | { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a }, | ||
2028 | { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, | ||
2029 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, | ||
2030 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | ||
2031 | { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, | ||
2032 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, | ||
2033 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, | ||
2034 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
2035 | { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
2036 | { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 }, | ||
2037 | { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 }, | ||
2038 | { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 }, | ||
2039 | { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 }, | ||
2040 | { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c }, | ||
2041 | { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 }, | ||
2042 | { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 }, | ||
2043 | { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 }, | ||
2044 | { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac }, | ||
2045 | { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 }, | ||
2046 | { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 }, | ||
2047 | { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 }, | ||
2048 | { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 }, | ||
2049 | { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 }, | ||
2050 | { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 }, | ||
2051 | { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 }, | ||
2052 | { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 }, | ||
2053 | { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac }, | ||
2054 | { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 }, | ||
2055 | { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 }, | ||
2056 | { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 }, | ||
2057 | { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 }, | ||
2058 | { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 }, | ||
2059 | { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad }, | ||
2060 | { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, | ||
2061 | { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, | ||
2062 | { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, | ||
2063 | { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, | ||
2064 | { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, | ||
2065 | { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, | ||
2066 | { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, | ||
2067 | { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, | ||
2068 | { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, | ||
2069 | { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, | ||
2070 | { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, | ||
2071 | { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, | ||
2072 | { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, | ||
2073 | { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, | ||
2074 | { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, | ||
2075 | { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, | ||
2076 | { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, | ||
2077 | { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, | ||
2078 | { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, | ||
2079 | { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, | ||
2080 | { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, | ||
2081 | { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, | ||
2082 | { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, | ||
2083 | { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, | ||
2084 | { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, | ||
2085 | { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, | ||
2086 | { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, | ||
2087 | { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, | ||
2088 | { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, | ||
2089 | { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, | ||
2090 | { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, | ||
2091 | { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, | ||
2092 | { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, | ||
2093 | { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, | ||
2094 | { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, | ||
2095 | { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, | ||
2096 | { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, | ||
2097 | { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, | ||
2098 | { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, | ||
2099 | { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, | ||
2100 | { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, | ||
2101 | { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, | ||
2102 | { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, | ||
2103 | { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, | ||
2104 | { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, | ||
2105 | { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, | ||
2106 | { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, | ||
2107 | { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, | ||
2108 | { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, | ||
2109 | { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, | ||
2110 | { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, | ||
2111 | { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, | ||
2112 | { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, | ||
2113 | { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, | ||
2114 | { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, | ||
2115 | { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, | ||
2116 | { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, | ||
2117 | { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, | ||
2118 | { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, | ||
2119 | { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, | ||
2120 | { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, | ||
2121 | { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, | ||
2122 | { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, | ||
2123 | { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, | ||
2124 | { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, | ||
2125 | { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, | ||
2126 | { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, | ||
2127 | { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, | ||
2128 | { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, | ||
2129 | { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, | ||
2130 | { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, | ||
2131 | { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, | ||
2132 | { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, | ||
2133 | { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, | ||
2134 | { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, | ||
2135 | { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, | ||
2136 | { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, | ||
2137 | { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, | ||
2138 | { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2139 | { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2140 | { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2141 | { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2142 | { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2143 | { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2144 | { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2145 | { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2146 | { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2147 | { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2148 | { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2149 | { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2150 | { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2151 | { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2152 | { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2153 | { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2154 | { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2155 | { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2156 | { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2157 | { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2158 | { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2159 | { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2160 | { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2161 | { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2162 | { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2163 | { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2164 | { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, | ||
2165 | { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 }, | ||
2166 | { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, | ||
2167 | { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, | ||
2168 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, | ||
2169 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | ||
2170 | { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, | ||
2171 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
2172 | { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, | ||
2173 | { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, | ||
2174 | { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, | ||
2175 | { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, | ||
2176 | { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, | ||
2177 | { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, | ||
2178 | { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, | ||
2179 | { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, | ||
2180 | { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, | ||
2181 | { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, | ||
2182 | { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, | ||
2183 | { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, | ||
2184 | { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, | ||
2185 | { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, | ||
2186 | { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, | ||
2187 | { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, | ||
2188 | { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, | ||
2189 | { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, | ||
2190 | { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, | ||
2191 | { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, | ||
2192 | { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, | ||
2193 | { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c }, | ||
2194 | { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 }, | ||
2195 | { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 }, | ||
2196 | { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 }, | ||
2197 | }; | ||
2198 | |||
2199 | static const u32 ar9280Common_9280[][2] = { | ||
2200 | { 0x0000000c, 0x00000000 }, | ||
2201 | { 0x00000030, 0x00020015 }, | ||
2202 | { 0x00000034, 0x00000005 }, | ||
2203 | { 0x00000040, 0x00000000 }, | ||
2204 | { 0x00000044, 0x00000008 }, | ||
2205 | { 0x00000048, 0x00000008 }, | ||
2206 | { 0x0000004c, 0x00000010 }, | ||
2207 | { 0x00000050, 0x00000000 }, | ||
2208 | { 0x00000054, 0x0000001f }, | ||
2209 | { 0x00000800, 0x00000000 }, | ||
2210 | { 0x00000804, 0x00000000 }, | ||
2211 | { 0x00000808, 0x00000000 }, | ||
2212 | { 0x0000080c, 0x00000000 }, | ||
2213 | { 0x00000810, 0x00000000 }, | ||
2214 | { 0x00000814, 0x00000000 }, | ||
2215 | { 0x00000818, 0x00000000 }, | ||
2216 | { 0x0000081c, 0x00000000 }, | ||
2217 | { 0x00000820, 0x00000000 }, | ||
2218 | { 0x00000824, 0x00000000 }, | ||
2219 | { 0x00001040, 0x002ffc0f }, | ||
2220 | { 0x00001044, 0x002ffc0f }, | ||
2221 | { 0x00001048, 0x002ffc0f }, | ||
2222 | { 0x0000104c, 0x002ffc0f }, | ||
2223 | { 0x00001050, 0x002ffc0f }, | ||
2224 | { 0x00001054, 0x002ffc0f }, | ||
2225 | { 0x00001058, 0x002ffc0f }, | ||
2226 | { 0x0000105c, 0x002ffc0f }, | ||
2227 | { 0x00001060, 0x002ffc0f }, | ||
2228 | { 0x00001064, 0x002ffc0f }, | ||
2229 | { 0x00001230, 0x00000000 }, | ||
2230 | { 0x00001270, 0x00000000 }, | ||
2231 | { 0x00001038, 0x00000000 }, | ||
2232 | { 0x00001078, 0x00000000 }, | ||
2233 | { 0x000010b8, 0x00000000 }, | ||
2234 | { 0x000010f8, 0x00000000 }, | ||
2235 | { 0x00001138, 0x00000000 }, | ||
2236 | { 0x00001178, 0x00000000 }, | ||
2237 | { 0x000011b8, 0x00000000 }, | ||
2238 | { 0x000011f8, 0x00000000 }, | ||
2239 | { 0x00001238, 0x00000000 }, | ||
2240 | { 0x00001278, 0x00000000 }, | ||
2241 | { 0x000012b8, 0x00000000 }, | ||
2242 | { 0x000012f8, 0x00000000 }, | ||
2243 | { 0x00001338, 0x00000000 }, | ||
2244 | { 0x00001378, 0x00000000 }, | ||
2245 | { 0x000013b8, 0x00000000 }, | ||
2246 | { 0x000013f8, 0x00000000 }, | ||
2247 | { 0x00001438, 0x00000000 }, | ||
2248 | { 0x00001478, 0x00000000 }, | ||
2249 | { 0x000014b8, 0x00000000 }, | ||
2250 | { 0x000014f8, 0x00000000 }, | ||
2251 | { 0x00001538, 0x00000000 }, | ||
2252 | { 0x00001578, 0x00000000 }, | ||
2253 | { 0x000015b8, 0x00000000 }, | ||
2254 | { 0x000015f8, 0x00000000 }, | ||
2255 | { 0x00001638, 0x00000000 }, | ||
2256 | { 0x00001678, 0x00000000 }, | ||
2257 | { 0x000016b8, 0x00000000 }, | ||
2258 | { 0x000016f8, 0x00000000 }, | ||
2259 | { 0x00001738, 0x00000000 }, | ||
2260 | { 0x00001778, 0x00000000 }, | ||
2261 | { 0x000017b8, 0x00000000 }, | ||
2262 | { 0x000017f8, 0x00000000 }, | ||
2263 | { 0x0000103c, 0x00000000 }, | ||
2264 | { 0x0000107c, 0x00000000 }, | ||
2265 | { 0x000010bc, 0x00000000 }, | ||
2266 | { 0x000010fc, 0x00000000 }, | ||
2267 | { 0x0000113c, 0x00000000 }, | ||
2268 | { 0x0000117c, 0x00000000 }, | ||
2269 | { 0x000011bc, 0x00000000 }, | ||
2270 | { 0x000011fc, 0x00000000 }, | ||
2271 | { 0x0000123c, 0x00000000 }, | ||
2272 | { 0x0000127c, 0x00000000 }, | ||
2273 | { 0x000012bc, 0x00000000 }, | ||
2274 | { 0x000012fc, 0x00000000 }, | ||
2275 | { 0x0000133c, 0x00000000 }, | ||
2276 | { 0x0000137c, 0x00000000 }, | ||
2277 | { 0x000013bc, 0x00000000 }, | ||
2278 | { 0x000013fc, 0x00000000 }, | ||
2279 | { 0x0000143c, 0x00000000 }, | ||
2280 | { 0x0000147c, 0x00000000 }, | ||
2281 | { 0x00004030, 0x00000002 }, | ||
2282 | { 0x0000403c, 0x00000002 }, | ||
2283 | { 0x00004024, 0x0000001f }, | ||
2284 | { 0x00007010, 0x00000033 }, | ||
2285 | { 0x00007038, 0x000004c2 }, | ||
2286 | { 0x00008004, 0x00000000 }, | ||
2287 | { 0x00008008, 0x00000000 }, | ||
2288 | { 0x0000800c, 0x00000000 }, | ||
2289 | { 0x00008018, 0x00000700 }, | ||
2290 | { 0x00008020, 0x00000000 }, | ||
2291 | { 0x00008038, 0x00000000 }, | ||
2292 | { 0x0000803c, 0x00000000 }, | ||
2293 | { 0x00008048, 0x40000000 }, | ||
2294 | { 0x00008054, 0x00000000 }, | ||
2295 | { 0x00008058, 0x00000000 }, | ||
2296 | { 0x0000805c, 0x000fc78f }, | ||
2297 | { 0x00008060, 0x0000000f }, | ||
2298 | { 0x00008064, 0x00000000 }, | ||
2299 | { 0x00008070, 0x00000000 }, | ||
2300 | { 0x000080c0, 0x2a82301a }, | ||
2301 | { 0x000080c4, 0x05dc01e0 }, | ||
2302 | { 0x000080c8, 0x1f402710 }, | ||
2303 | { 0x000080cc, 0x01f40000 }, | ||
2304 | { 0x000080d0, 0x00001e00 }, | ||
2305 | { 0x000080d4, 0x00000000 }, | ||
2306 | { 0x000080d8, 0x00400000 }, | ||
2307 | { 0x000080e0, 0xffffffff }, | ||
2308 | { 0x000080e4, 0x0000ffff }, | ||
2309 | { 0x000080e8, 0x003f3f3f }, | ||
2310 | { 0x000080ec, 0x00000000 }, | ||
2311 | { 0x000080f0, 0x00000000 }, | ||
2312 | { 0x000080f4, 0x00000000 }, | ||
2313 | { 0x000080f8, 0x00000000 }, | ||
2314 | { 0x000080fc, 0x00020000 }, | ||
2315 | { 0x00008100, 0x00020000 }, | ||
2316 | { 0x00008104, 0x00000001 }, | ||
2317 | { 0x00008108, 0x00000052 }, | ||
2318 | { 0x0000810c, 0x00000000 }, | ||
2319 | { 0x00008110, 0x00000168 }, | ||
2320 | { 0x00008118, 0x000100aa }, | ||
2321 | { 0x0000811c, 0x00003210 }, | ||
2322 | { 0x00008120, 0x08f04800 }, | ||
2323 | { 0x00008124, 0x00000000 }, | ||
2324 | { 0x00008128, 0x00000000 }, | ||
2325 | { 0x0000812c, 0x00000000 }, | ||
2326 | { 0x00008130, 0x00000000 }, | ||
2327 | { 0x00008134, 0x00000000 }, | ||
2328 | { 0x00008138, 0x00000000 }, | ||
2329 | { 0x0000813c, 0x00000000 }, | ||
2330 | { 0x00008144, 0x00000000 }, | ||
2331 | { 0x00008168, 0x00000000 }, | ||
2332 | { 0x0000816c, 0x00000000 }, | ||
2333 | { 0x00008170, 0x32143320 }, | ||
2334 | { 0x00008174, 0xfaa4fa50 }, | ||
2335 | { 0x00008178, 0x00000100 }, | ||
2336 | { 0x0000817c, 0x00000000 }, | ||
2337 | { 0x000081c4, 0x00000000 }, | ||
2338 | { 0x000081d0, 0x00003210 }, | ||
2339 | { 0x000081ec, 0x00000000 }, | ||
2340 | { 0x000081f0, 0x00000000 }, | ||
2341 | { 0x000081f4, 0x00000000 }, | ||
2342 | { 0x000081f8, 0x00000000 }, | ||
2343 | { 0x000081fc, 0x00000000 }, | ||
2344 | { 0x00008200, 0x00000000 }, | ||
2345 | { 0x00008204, 0x00000000 }, | ||
2346 | { 0x00008208, 0x00000000 }, | ||
2347 | { 0x0000820c, 0x00000000 }, | ||
2348 | { 0x00008210, 0x00000000 }, | ||
2349 | { 0x00008214, 0x00000000 }, | ||
2350 | { 0x00008218, 0x00000000 }, | ||
2351 | { 0x0000821c, 0x00000000 }, | ||
2352 | { 0x00008220, 0x00000000 }, | ||
2353 | { 0x00008224, 0x00000000 }, | ||
2354 | { 0x00008228, 0x00000000 }, | ||
2355 | { 0x0000822c, 0x00000000 }, | ||
2356 | { 0x00008230, 0x00000000 }, | ||
2357 | { 0x00008234, 0x00000000 }, | ||
2358 | { 0x00008238, 0x00000000 }, | ||
2359 | { 0x0000823c, 0x00000000 }, | ||
2360 | { 0x00008240, 0x00100000 }, | ||
2361 | { 0x00008244, 0x0010f400 }, | ||
2362 | { 0x00008248, 0x00000100 }, | ||
2363 | { 0x0000824c, 0x0001e800 }, | ||
2364 | { 0x00008250, 0x00000000 }, | ||
2365 | { 0x00008254, 0x00000000 }, | ||
2366 | { 0x00008258, 0x00000000 }, | ||
2367 | { 0x0000825c, 0x400000ff }, | ||
2368 | { 0x00008260, 0x00080922 }, | ||
2369 | { 0x00008270, 0x00000000 }, | ||
2370 | { 0x00008274, 0x40000000 }, | ||
2371 | { 0x00008278, 0x003e4180 }, | ||
2372 | { 0x0000827c, 0x00000000 }, | ||
2373 | { 0x00008284, 0x0000002c }, | ||
2374 | { 0x00008288, 0x0000002c }, | ||
2375 | { 0x0000828c, 0x00000000 }, | ||
2376 | { 0x00008294, 0x00000000 }, | ||
2377 | { 0x00008298, 0x00000000 }, | ||
2378 | { 0x00008300, 0x00000000 }, | ||
2379 | { 0x00008304, 0x00000000 }, | ||
2380 | { 0x00008308, 0x00000000 }, | ||
2381 | { 0x0000830c, 0x00000000 }, | ||
2382 | { 0x00008310, 0x00000000 }, | ||
2383 | { 0x00008314, 0x00000000 }, | ||
2384 | { 0x00008318, 0x00000000 }, | ||
2385 | { 0x00008328, 0x00000000 }, | ||
2386 | { 0x0000832c, 0x00000007 }, | ||
2387 | { 0x00008330, 0x00000302 }, | ||
2388 | { 0x00008334, 0x00000e00 }, | ||
2389 | { 0x00008338, 0x00000000 }, | ||
2390 | { 0x0000833c, 0x00000000 }, | ||
2391 | { 0x00008340, 0x000107ff }, | ||
2392 | { 0x00008344, 0x00000000 }, | ||
2393 | { 0x00009808, 0x00000000 }, | ||
2394 | { 0x0000980c, 0xaf268e30 }, | ||
2395 | { 0x00009810, 0xfd14e000 }, | ||
2396 | { 0x00009814, 0x9c0a9f6b }, | ||
2397 | { 0x0000981c, 0x00000000 }, | ||
2398 | { 0x0000982c, 0x0000a000 }, | ||
2399 | { 0x00009830, 0x00000000 }, | ||
2400 | { 0x0000983c, 0x00200400 }, | ||
2401 | { 0x00009840, 0x206a01ae }, | ||
2402 | { 0x0000984c, 0x0040233c }, | ||
2403 | { 0x0000a84c, 0x0040233c }, | ||
2404 | { 0x00009854, 0x00000044 }, | ||
2405 | { 0x00009900, 0x00000000 }, | ||
2406 | { 0x00009904, 0x00000000 }, | ||
2407 | { 0x00009908, 0x00000000 }, | ||
2408 | { 0x0000990c, 0x00000000 }, | ||
2409 | { 0x0000991c, 0x10000fff }, | ||
2410 | { 0x00009920, 0x04900000 }, | ||
2411 | { 0x0000a920, 0x04900000 }, | ||
2412 | { 0x00009928, 0x00000001 }, | ||
2413 | { 0x0000992c, 0x00000004 }, | ||
2414 | { 0x00009934, 0x1e1f2022 }, | ||
2415 | { 0x00009938, 0x0a0b0c0d }, | ||
2416 | { 0x0000993c, 0x00000000 }, | ||
2417 | { 0x00009948, 0x9280c00a }, | ||
2418 | { 0x0000994c, 0x00020028 }, | ||
2419 | { 0x00009954, 0xe250a51e }, | ||
2420 | { 0x00009958, 0x3388ffff }, | ||
2421 | { 0x00009940, 0x00781204 }, | ||
2422 | { 0x0000c95c, 0x004b6a8e }, | ||
2423 | { 0x0000c968, 0x000003ce }, | ||
2424 | { 0x00009970, 0x190fb514 }, | ||
2425 | { 0x00009974, 0x00000000 }, | ||
2426 | { 0x00009978, 0x00000001 }, | ||
2427 | { 0x0000997c, 0x00000000 }, | ||
2428 | { 0x00009980, 0x00000000 }, | ||
2429 | { 0x00009984, 0x00000000 }, | ||
2430 | { 0x00009988, 0x00000000 }, | ||
2431 | { 0x0000998c, 0x00000000 }, | ||
2432 | { 0x00009990, 0x00000000 }, | ||
2433 | { 0x00009994, 0x00000000 }, | ||
2434 | { 0x00009998, 0x00000000 }, | ||
2435 | { 0x0000999c, 0x00000000 }, | ||
2436 | { 0x000099a0, 0x00000000 }, | ||
2437 | { 0x000099a4, 0x00000001 }, | ||
2438 | { 0x000099a8, 0x201fff00 }, | ||
2439 | { 0x000099ac, 0x006f00c4 }, | ||
2440 | { 0x000099b0, 0x03051000 }, | ||
2441 | { 0x000099b4, 0x00000820 }, | ||
2442 | { 0x000099dc, 0x00000000 }, | ||
2443 | { 0x000099e0, 0x00000000 }, | ||
2444 | { 0x000099e4, 0xaaaaaaaa }, | ||
2445 | { 0x000099e8, 0x3c466478 }, | ||
2446 | { 0x000099ec, 0x0cc80caa }, | ||
2447 | { 0x000099fc, 0x00001042 }, | ||
2448 | { 0x0000a210, 0x4080a333 }, | ||
2449 | { 0x0000a214, 0x40206c10 }, | ||
2450 | { 0x0000a218, 0x009c4060 }, | ||
2451 | { 0x0000a220, 0x01834061 }, | ||
2452 | { 0x0000a224, 0x00000400 }, | ||
2453 | { 0x0000a228, 0x000003b5 }, | ||
2454 | { 0x0000a22c, 0x23277200 }, | ||
2455 | { 0x0000a234, 0x20202020 }, | ||
2456 | { 0x0000a238, 0x20202020 }, | ||
2457 | { 0x0000a23c, 0x13c889af }, | ||
2458 | { 0x0000a240, 0x38490a20 }, | ||
2459 | { 0x0000a244, 0x00007bb6 }, | ||
2460 | { 0x0000a248, 0x0fff3ffc }, | ||
2461 | { 0x0000a24c, 0x00000001 }, | ||
2462 | { 0x0000a250, 0x001da000 }, | ||
2463 | { 0x0000a254, 0x00000000 }, | ||
2464 | { 0x0000a258, 0x0cdbd380 }, | ||
2465 | { 0x0000a25c, 0x0f0f0f01 }, | ||
2466 | { 0x0000a260, 0xdfa91f01 }, | ||
2467 | { 0x0000a268, 0x00000000 }, | ||
2468 | { 0x0000a26c, 0x0ebae9c6 }, | ||
2469 | { 0x0000b26c, 0x0ebae9c6 }, | ||
2470 | { 0x0000d270, 0x00820820 }, | ||
2471 | { 0x0000a278, 0x1ce739ce }, | ||
2472 | { 0x0000a27c, 0x050701ce }, | ||
2473 | { 0x0000a358, 0x7999aa0f }, | ||
2474 | { 0x0000d35c, 0x07ffffef }, | ||
2475 | { 0x0000d360, 0x0fffffe7 }, | ||
2476 | { 0x0000d364, 0x17ffffe5 }, | ||
2477 | { 0x0000d368, 0x1fffffe4 }, | ||
2478 | { 0x0000d36c, 0x37ffffe3 }, | ||
2479 | { 0x0000d370, 0x3fffffe3 }, | ||
2480 | { 0x0000d374, 0x57ffffe3 }, | ||
2481 | { 0x0000d378, 0x5fffffe2 }, | ||
2482 | { 0x0000d37c, 0x7fffffe2 }, | ||
2483 | { 0x0000d380, 0x7f3c7bba }, | ||
2484 | { 0x0000d384, 0xf3307ff0 }, | ||
2485 | { 0x0000a388, 0x0c000000 }, | ||
2486 | { 0x0000a38c, 0x20202020 }, | ||
2487 | { 0x0000a390, 0x20202020 }, | ||
2488 | { 0x0000a394, 0x1ce739ce }, | ||
2489 | { 0x0000a398, 0x000001ce }, | ||
2490 | { 0x0000a39c, 0x00000001 }, | ||
2491 | { 0x0000a3a0, 0x00000000 }, | ||
2492 | { 0x0000a3a4, 0x00000000 }, | ||
2493 | { 0x0000a3a8, 0x00000000 }, | ||
2494 | { 0x0000a3ac, 0x00000000 }, | ||
2495 | { 0x0000a3b0, 0x00000000 }, | ||
2496 | { 0x0000a3b4, 0x00000000 }, | ||
2497 | { 0x0000a3b8, 0x00000000 }, | ||
2498 | { 0x0000a3bc, 0x00000000 }, | ||
2499 | { 0x0000a3c0, 0x00000000 }, | ||
2500 | { 0x0000a3c4, 0x00000000 }, | ||
2501 | { 0x0000a3c8, 0x00000246 }, | ||
2502 | { 0x0000a3cc, 0x20202020 }, | ||
2503 | { 0x0000a3d0, 0x20202020 }, | ||
2504 | { 0x0000a3d4, 0x20202020 }, | ||
2505 | { 0x0000a3dc, 0x1ce739ce }, | ||
2506 | { 0x0000a3e0, 0x000001ce }, | ||
2507 | { 0x0000a3e4, 0x00000000 }, | ||
2508 | { 0x0000a3e8, 0x18c43433 }, | ||
2509 | { 0x0000a3ec, 0x00f38081 }, | ||
2510 | { 0x00007800, 0x00040000 }, | ||
2511 | { 0x00007804, 0xdb005012 }, | ||
2512 | { 0x00007808, 0x04924914 }, | ||
2513 | { 0x0000780c, 0x21084210 }, | ||
2514 | { 0x00007810, 0x6d801300 }, | ||
2515 | { 0x00007814, 0x0019beff }, | ||
2516 | { 0x00007818, 0x07e40000 }, | ||
2517 | { 0x0000781c, 0x00492000 }, | ||
2518 | { 0x00007820, 0x92492480 }, | ||
2519 | { 0x00007824, 0x00040000 }, | ||
2520 | { 0x00007828, 0xdb005012 }, | ||
2521 | { 0x0000782c, 0x04924914 }, | ||
2522 | { 0x00007830, 0x21084210 }, | ||
2523 | { 0x00007834, 0x6d801300 }, | ||
2524 | { 0x00007838, 0x0019beff }, | ||
2525 | { 0x0000783c, 0x07e40000 }, | ||
2526 | { 0x00007840, 0x00492000 }, | ||
2527 | { 0x00007844, 0x92492480 }, | ||
2528 | { 0x00007848, 0x00120000 }, | ||
2529 | { 0x00007850, 0x54214514 }, | ||
2530 | { 0x00007858, 0x92592692 }, | ||
2531 | { 0x00007860, 0x52802000 }, | ||
2532 | { 0x00007864, 0x0a8e370e }, | ||
2533 | { 0x00007868, 0xc0102850 }, | ||
2534 | { 0x0000786c, 0x812d4000 }, | ||
2535 | { 0x00007874, 0x001b6db0 }, | ||
2536 | { 0x00007878, 0x00376b63 }, | ||
2537 | { 0x0000787c, 0x06db6db6 }, | ||
2538 | { 0x00007880, 0x006d8000 }, | ||
2539 | { 0x00007884, 0xffeffffe }, | ||
2540 | { 0x00007888, 0xffeffffe }, | ||
2541 | { 0x00007890, 0x00060aeb }, | ||
2542 | { 0x00007894, 0x5a108000 }, | ||
2543 | { 0x00007898, 0x2a850160 }, | ||
2544 | }; | ||
2545 | |||
2546 | |||
2547 | |||
2548 | |||
2549 | static const u32 ar9280Modes_9280_2[][6] = { | ||
2550 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | ||
2551 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | ||
2552 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, | ||
2553 | { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, | ||
2554 | { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, | ||
2555 | { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, | ||
2556 | { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, | ||
2557 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, | ||
2558 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, | ||
2559 | { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
2560 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, | ||
2561 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | ||
2562 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, | ||
2563 | { 0x00009840, 0x206a012e, 0x206a012e, 0x206a022e, 0x206a022e, 0x206a022e }, | ||
2564 | { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, | ||
2565 | { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, | ||
2566 | { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, | ||
2567 | { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, | ||
2568 | { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e }, | ||
2569 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, | ||
2570 | { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, | ||
2571 | { 0x0000c864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | ||
2572 | { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, | ||
2573 | { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, | ||
2574 | { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, | ||
2575 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, | ||
2576 | { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, | ||
2577 | { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 }, | ||
2578 | { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, | ||
2579 | { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, | ||
2580 | { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, | ||
2581 | { 0x0000c9b8, 0x0000000f, 0x0000000f, 0x0000001c, 0x0000001c, 0x0000001c }, | ||
2582 | { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, | ||
2583 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, | ||
2584 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | ||
2585 | { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, | ||
2586 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, | ||
2587 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, | ||
2588 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
2589 | { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
2590 | { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, | ||
2591 | { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, | ||
2592 | { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, | ||
2593 | { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, | ||
2594 | { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, | ||
2595 | { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, | ||
2596 | { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, | ||
2597 | { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, | ||
2598 | { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, | ||
2599 | { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, | ||
2600 | { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, | ||
2601 | { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, | ||
2602 | { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, | ||
2603 | { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, | ||
2604 | { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, | ||
2605 | { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, | ||
2606 | { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, | ||
2607 | { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, | ||
2608 | { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, | ||
2609 | { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, | ||
2610 | { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, | ||
2611 | { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, | ||
2612 | { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, | ||
2613 | { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, | ||
2614 | { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, | ||
2615 | { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, | ||
2616 | { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, | ||
2617 | { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, | ||
2618 | { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, | ||
2619 | { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, | ||
2620 | { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, | ||
2621 | { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, | ||
2622 | { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, | ||
2623 | { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, | ||
2624 | { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, | ||
2625 | { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, | ||
2626 | { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, | ||
2627 | { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, | ||
2628 | { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, | ||
2629 | { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, | ||
2630 | { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, | ||
2631 | { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, | ||
2632 | { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, | ||
2633 | { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, | ||
2634 | { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, | ||
2635 | { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, | ||
2636 | { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, | ||
2637 | { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, | ||
2638 | { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, | ||
2639 | { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, | ||
2640 | { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, | ||
2641 | { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, | ||
2642 | { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, | ||
2643 | { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, | ||
2644 | { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, | ||
2645 | { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, | ||
2646 | { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, | ||
2647 | { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, | ||
2648 | { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, | ||
2649 | { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, | ||
2650 | { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, | ||
2651 | { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, | ||
2652 | { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, | ||
2653 | { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, | ||
2654 | { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, | ||
2655 | { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, | ||
2656 | { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, | ||
2657 | { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, | ||
2658 | { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, | ||
2659 | { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, | ||
2660 | { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, | ||
2661 | { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, | ||
2662 | { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, | ||
2663 | { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, | ||
2664 | { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, | ||
2665 | { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, | ||
2666 | { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, | ||
2667 | { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, | ||
2668 | { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, | ||
2669 | { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, | ||
2670 | { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, | ||
2671 | { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, | ||
2672 | { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, | ||
2673 | { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, | ||
2674 | { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, | ||
2675 | { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, | ||
2676 | { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, | ||
2677 | { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, | ||
2678 | { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, | ||
2679 | { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, | ||
2680 | { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, | ||
2681 | { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, | ||
2682 | { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, | ||
2683 | { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, | ||
2684 | { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, | ||
2685 | { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, | ||
2686 | { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, | ||
2687 | { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, | ||
2688 | { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, | ||
2689 | { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, | ||
2690 | { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, | ||
2691 | { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, | ||
2692 | { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2693 | { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2694 | { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2695 | { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2696 | { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2697 | { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2698 | { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2699 | { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2700 | { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2701 | { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2702 | { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2703 | { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2704 | { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2705 | { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2706 | { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2707 | { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2708 | { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2709 | { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2710 | { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2711 | { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2712 | { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2713 | { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2714 | { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2715 | { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2716 | { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2717 | { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2718 | { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, | ||
2719 | { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 }, | ||
2720 | { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, | ||
2721 | { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, | ||
2722 | { 0x0000a21c, 0x1463800a, 0x1463800a, 0x1463800a, 0x1463800a, 0x1463800a }, | ||
2723 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | ||
2724 | { 0x0000a250, 0x001ff000, 0x001ff000, 0x001da000, 0x001da000, 0x001da000 }, | ||
2725 | { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, | ||
2726 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
2727 | { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, | ||
2728 | { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, | ||
2729 | { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, | ||
2730 | { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, | ||
2731 | { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, | ||
2732 | { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, | ||
2733 | { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, | ||
2734 | { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, | ||
2735 | { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, | ||
2736 | { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, | ||
2737 | { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, | ||
2738 | { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, | ||
2739 | { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, | ||
2740 | { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, | ||
2741 | { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, | ||
2742 | { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, | ||
2743 | { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, | ||
2744 | { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, | ||
2745 | { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, | ||
2746 | { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, | ||
2747 | { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, | ||
2748 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, | ||
2749 | { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
2750 | { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, | ||
2751 | }; | ||
2752 | |||
2753 | static const u32 ar9280Common_9280_2[][2] = { | ||
2754 | { 0x0000000c, 0x00000000 }, | ||
2755 | { 0x00000030, 0x00020015 }, | ||
2756 | { 0x00000034, 0x00000005 }, | ||
2757 | { 0x00000040, 0x00000000 }, | ||
2758 | { 0x00000044, 0x00000008 }, | ||
2759 | { 0x00000048, 0x00000008 }, | ||
2760 | { 0x0000004c, 0x00000010 }, | ||
2761 | { 0x00000050, 0x00000000 }, | ||
2762 | { 0x00000054, 0x0000001f }, | ||
2763 | { 0x00000800, 0x00000000 }, | ||
2764 | { 0x00000804, 0x00000000 }, | ||
2765 | { 0x00000808, 0x00000000 }, | ||
2766 | { 0x0000080c, 0x00000000 }, | ||
2767 | { 0x00000810, 0x00000000 }, | ||
2768 | { 0x00000814, 0x00000000 }, | ||
2769 | { 0x00000818, 0x00000000 }, | ||
2770 | { 0x0000081c, 0x00000000 }, | ||
2771 | { 0x00000820, 0x00000000 }, | ||
2772 | { 0x00000824, 0x00000000 }, | ||
2773 | { 0x00001040, 0x002ffc0f }, | ||
2774 | { 0x00001044, 0x002ffc0f }, | ||
2775 | { 0x00001048, 0x002ffc0f }, | ||
2776 | { 0x0000104c, 0x002ffc0f }, | ||
2777 | { 0x00001050, 0x002ffc0f }, | ||
2778 | { 0x00001054, 0x002ffc0f }, | ||
2779 | { 0x00001058, 0x002ffc0f }, | ||
2780 | { 0x0000105c, 0x002ffc0f }, | ||
2781 | { 0x00001060, 0x002ffc0f }, | ||
2782 | { 0x00001064, 0x002ffc0f }, | ||
2783 | { 0x00001230, 0x00000000 }, | ||
2784 | { 0x00001270, 0x00000000 }, | ||
2785 | { 0x00001038, 0x00000000 }, | ||
2786 | { 0x00001078, 0x00000000 }, | ||
2787 | { 0x000010b8, 0x00000000 }, | ||
2788 | { 0x000010f8, 0x00000000 }, | ||
2789 | { 0x00001138, 0x00000000 }, | ||
2790 | { 0x00001178, 0x00000000 }, | ||
2791 | { 0x000011b8, 0x00000000 }, | ||
2792 | { 0x000011f8, 0x00000000 }, | ||
2793 | { 0x00001238, 0x00000000 }, | ||
2794 | { 0x00001278, 0x00000000 }, | ||
2795 | { 0x000012b8, 0x00000000 }, | ||
2796 | { 0x000012f8, 0x00000000 }, | ||
2797 | { 0x00001338, 0x00000000 }, | ||
2798 | { 0x00001378, 0x00000000 }, | ||
2799 | { 0x000013b8, 0x00000000 }, | ||
2800 | { 0x000013f8, 0x00000000 }, | ||
2801 | { 0x00001438, 0x00000000 }, | ||
2802 | { 0x00001478, 0x00000000 }, | ||
2803 | { 0x000014b8, 0x00000000 }, | ||
2804 | { 0x000014f8, 0x00000000 }, | ||
2805 | { 0x00001538, 0x00000000 }, | ||
2806 | { 0x00001578, 0x00000000 }, | ||
2807 | { 0x000015b8, 0x00000000 }, | ||
2808 | { 0x000015f8, 0x00000000 }, | ||
2809 | { 0x00001638, 0x00000000 }, | ||
2810 | { 0x00001678, 0x00000000 }, | ||
2811 | { 0x000016b8, 0x00000000 }, | ||
2812 | { 0x000016f8, 0x00000000 }, | ||
2813 | { 0x00001738, 0x00000000 }, | ||
2814 | { 0x00001778, 0x00000000 }, | ||
2815 | { 0x000017b8, 0x00000000 }, | ||
2816 | { 0x000017f8, 0x00000000 }, | ||
2817 | { 0x0000103c, 0x00000000 }, | ||
2818 | { 0x0000107c, 0x00000000 }, | ||
2819 | { 0x000010bc, 0x00000000 }, | ||
2820 | { 0x000010fc, 0x00000000 }, | ||
2821 | { 0x0000113c, 0x00000000 }, | ||
2822 | { 0x0000117c, 0x00000000 }, | ||
2823 | { 0x000011bc, 0x00000000 }, | ||
2824 | { 0x000011fc, 0x00000000 }, | ||
2825 | { 0x0000123c, 0x00000000 }, | ||
2826 | { 0x0000127c, 0x00000000 }, | ||
2827 | { 0x000012bc, 0x00000000 }, | ||
2828 | { 0x000012fc, 0x00000000 }, | ||
2829 | { 0x0000133c, 0x00000000 }, | ||
2830 | { 0x0000137c, 0x00000000 }, | ||
2831 | { 0x000013bc, 0x00000000 }, | ||
2832 | { 0x000013fc, 0x00000000 }, | ||
2833 | { 0x0000143c, 0x00000000 }, | ||
2834 | { 0x0000147c, 0x00000000 }, | ||
2835 | { 0x00004030, 0x00000002 }, | ||
2836 | { 0x0000403c, 0x00000002 }, | ||
2837 | { 0x00004024, 0x0000001f }, | ||
2838 | { 0x00004060, 0x00000000 }, | ||
2839 | { 0x00004064, 0x00000000 }, | ||
2840 | { 0x00007010, 0x00000033 }, | ||
2841 | { 0x00007034, 0x00000002 }, | ||
2842 | { 0x00007038, 0x000004c2 }, | ||
2843 | { 0x00008004, 0x00000000 }, | ||
2844 | { 0x00008008, 0x00000000 }, | ||
2845 | { 0x0000800c, 0x00000000 }, | ||
2846 | { 0x00008018, 0x00000700 }, | ||
2847 | { 0x00008020, 0x00000000 }, | ||
2848 | { 0x00008038, 0x00000000 }, | ||
2849 | { 0x0000803c, 0x00000000 }, | ||
2850 | { 0x00008048, 0x40000000 }, | ||
2851 | { 0x00008054, 0x00000000 }, | ||
2852 | { 0x00008058, 0x00000000 }, | ||
2853 | { 0x0000805c, 0x000fc78f }, | ||
2854 | { 0x00008060, 0x0000000f }, | ||
2855 | { 0x00008064, 0x00000000 }, | ||
2856 | { 0x00008070, 0x00000000 }, | ||
2857 | { 0x000080c0, 0x2a80001a }, | ||
2858 | { 0x000080c4, 0x05dc01e0 }, | ||
2859 | { 0x000080c8, 0x1f402710 }, | ||
2860 | { 0x000080cc, 0x01f40000 }, | ||
2861 | { 0x000080d0, 0x00001e00 }, | ||
2862 | { 0x000080d4, 0x00000000 }, | ||
2863 | { 0x000080d8, 0x00400000 }, | ||
2864 | { 0x000080e0, 0xffffffff }, | ||
2865 | { 0x000080e4, 0x0000ffff }, | ||
2866 | { 0x000080e8, 0x003f3f3f }, | ||
2867 | { 0x000080ec, 0x00000000 }, | ||
2868 | { 0x000080f0, 0x00000000 }, | ||
2869 | { 0x000080f4, 0x00000000 }, | ||
2870 | { 0x000080f8, 0x00000000 }, | ||
2871 | { 0x000080fc, 0x00020000 }, | ||
2872 | { 0x00008100, 0x00020000 }, | ||
2873 | { 0x00008104, 0x00000001 }, | ||
2874 | { 0x00008108, 0x00000052 }, | ||
2875 | { 0x0000810c, 0x00000000 }, | ||
2876 | { 0x00008110, 0x00000168 }, | ||
2877 | { 0x00008118, 0x000100aa }, | ||
2878 | { 0x0000811c, 0x00003210 }, | ||
2879 | { 0x00008120, 0x08f04800 }, | ||
2880 | { 0x00008124, 0x00000000 }, | ||
2881 | { 0x00008128, 0x00000000 }, | ||
2882 | { 0x0000812c, 0x00000000 }, | ||
2883 | { 0x00008130, 0x00000000 }, | ||
2884 | { 0x00008134, 0x00000000 }, | ||
2885 | { 0x00008138, 0x00000000 }, | ||
2886 | { 0x0000813c, 0x00000000 }, | ||
2887 | { 0x00008144, 0x00000000 }, | ||
2888 | { 0x00008168, 0x00000000 }, | ||
2889 | { 0x0000816c, 0x00000000 }, | ||
2890 | { 0x00008170, 0x32143320 }, | ||
2891 | { 0x00008174, 0xfaa4fa50 }, | ||
2892 | { 0x00008178, 0x00000100 }, | ||
2893 | { 0x0000817c, 0x00000000 }, | ||
2894 | { 0x000081c0, 0x00000000 }, | ||
2895 | { 0x000081d0, 0x00003210 }, | ||
2896 | { 0x000081ec, 0x00000000 }, | ||
2897 | { 0x000081f0, 0x00000000 }, | ||
2898 | { 0x000081f4, 0x00000000 }, | ||
2899 | { 0x000081f8, 0x00000000 }, | ||
2900 | { 0x000081fc, 0x00000000 }, | ||
2901 | { 0x00008200, 0x00000000 }, | ||
2902 | { 0x00008204, 0x00000000 }, | ||
2903 | { 0x00008208, 0x00000000 }, | ||
2904 | { 0x0000820c, 0x00000000 }, | ||
2905 | { 0x00008210, 0x00000000 }, | ||
2906 | { 0x00008214, 0x00000000 }, | ||
2907 | { 0x00008218, 0x00000000 }, | ||
2908 | { 0x0000821c, 0x00000000 }, | ||
2909 | { 0x00008220, 0x00000000 }, | ||
2910 | { 0x00008224, 0x00000000 }, | ||
2911 | { 0x00008228, 0x00000000 }, | ||
2912 | { 0x0000822c, 0x00000000 }, | ||
2913 | { 0x00008230, 0x00000000 }, | ||
2914 | { 0x00008234, 0x00000000 }, | ||
2915 | { 0x00008238, 0x00000000 }, | ||
2916 | { 0x0000823c, 0x00000000 }, | ||
2917 | { 0x00008240, 0x00100000 }, | ||
2918 | { 0x00008244, 0x0010f400 }, | ||
2919 | { 0x00008248, 0x00000100 }, | ||
2920 | { 0x0000824c, 0x0001e800 }, | ||
2921 | { 0x00008250, 0x00000000 }, | ||
2922 | { 0x00008254, 0x00000000 }, | ||
2923 | { 0x00008258, 0x00000000 }, | ||
2924 | { 0x0000825c, 0x400000ff }, | ||
2925 | { 0x00008260, 0x00080922 }, | ||
2926 | { 0x00008270, 0x00000000 }, | ||
2927 | { 0x00008274, 0x40000000 }, | ||
2928 | { 0x00008278, 0x003e4180 }, | ||
2929 | { 0x0000827c, 0x00000000 }, | ||
2930 | { 0x00008284, 0x0000002c }, | ||
2931 | { 0x00008288, 0x0000002c }, | ||
2932 | { 0x0000828c, 0x00000000 }, | ||
2933 | { 0x00008294, 0x00000000 }, | ||
2934 | { 0x00008298, 0x00000000 }, | ||
2935 | { 0x0000829c, 0x00000000 }, | ||
2936 | { 0x00008300, 0x00000040 }, | ||
2937 | { 0x00008314, 0x00000000 }, | ||
2938 | { 0x00008328, 0x00000000 }, | ||
2939 | { 0x0000832c, 0x00000007 }, | ||
2940 | { 0x00008330, 0x00000302 }, | ||
2941 | { 0x00008334, 0x00000e00 }, | ||
2942 | { 0x00008338, 0x00000000 }, | ||
2943 | { 0x0000833c, 0x00000000 }, | ||
2944 | { 0x00008340, 0x000107ff }, | ||
2945 | { 0x00008344, 0x00581043 }, | ||
2946 | { 0x00009808, 0x00000000 }, | ||
2947 | { 0x0000980c, 0xafa68e30 }, | ||
2948 | { 0x00009810, 0xfd14e000 }, | ||
2949 | { 0x00009814, 0x9c0a9f6b }, | ||
2950 | { 0x0000981c, 0x00000000 }, | ||
2951 | { 0x0000982c, 0x0000a000 }, | ||
2952 | { 0x00009830, 0x00000000 }, | ||
2953 | { 0x0000983c, 0x00200400 }, | ||
2954 | { 0x0000984c, 0x0040233c }, | ||
2955 | { 0x0000a84c, 0x0040233c }, | ||
2956 | { 0x00009854, 0x00000044 }, | ||
2957 | { 0x00009900, 0x00000000 }, | ||
2958 | { 0x00009904, 0x00000000 }, | ||
2959 | { 0x00009908, 0x00000000 }, | ||
2960 | { 0x0000990c, 0x00000000 }, | ||
2961 | { 0x00009910, 0x01002310 }, | ||
2962 | { 0x0000991c, 0x10000fff }, | ||
2963 | { 0x00009920, 0x04900000 }, | ||
2964 | { 0x0000a920, 0x04900000 }, | ||
2965 | { 0x00009928, 0x00000001 }, | ||
2966 | { 0x0000992c, 0x00000004 }, | ||
2967 | { 0x00009934, 0x1e1f2022 }, | ||
2968 | { 0x00009938, 0x0a0b0c0d }, | ||
2969 | { 0x0000993c, 0x00000000 }, | ||
2970 | { 0x00009948, 0x9280c00a }, | ||
2971 | { 0x0000994c, 0x00020028 }, | ||
2972 | { 0x00009954, 0x5f3ca3de }, | ||
2973 | { 0x00009958, 0x2108ecff }, | ||
2974 | { 0x00009940, 0x14750604 }, | ||
2975 | { 0x0000c95c, 0x004b6a8e }, | ||
2976 | { 0x0000c968, 0x000003ce }, | ||
2977 | { 0x00009970, 0x190fb515 }, | ||
2978 | { 0x00009974, 0x00000000 }, | ||
2979 | { 0x00009978, 0x00000001 }, | ||
2980 | { 0x0000997c, 0x00000000 }, | ||
2981 | { 0x00009980, 0x00000000 }, | ||
2982 | { 0x00009984, 0x00000000 }, | ||
2983 | { 0x00009988, 0x00000000 }, | ||
2984 | { 0x0000998c, 0x00000000 }, | ||
2985 | { 0x00009990, 0x00000000 }, | ||
2986 | { 0x00009994, 0x00000000 }, | ||
2987 | { 0x00009998, 0x00000000 }, | ||
2988 | { 0x0000999c, 0x00000000 }, | ||
2989 | { 0x000099a0, 0x00000000 }, | ||
2990 | { 0x000099a4, 0x00000001 }, | ||
2991 | { 0x000099a8, 0x201fff00 }, | ||
2992 | { 0x000099ac, 0x006f0000 }, | ||
2993 | { 0x000099b0, 0x03051000 }, | ||
2994 | { 0x000099b4, 0x00000820 }, | ||
2995 | { 0x000099dc, 0x00000000 }, | ||
2996 | { 0x000099e0, 0x00000000 }, | ||
2997 | { 0x000099e4, 0xaaaaaaaa }, | ||
2998 | { 0x000099e8, 0x3c466478 }, | ||
2999 | { 0x000099ec, 0x0cc80caa }, | ||
3000 | { 0x000099f0, 0x00000000 }, | ||
3001 | { 0x000099fc, 0x00001042 }, | ||
3002 | { 0x0000a210, 0x4080a333 }, | ||
3003 | { 0x0000a214, 0x40206c10 }, | ||
3004 | { 0x0000a218, 0x009c4060 }, | ||
3005 | { 0x0000a220, 0x01834061 }, | ||
3006 | { 0x0000a224, 0x00000400 }, | ||
3007 | { 0x0000a228, 0x000003b5 }, | ||
3008 | { 0x0000a22c, 0x233f71c0 }, | ||
3009 | { 0x0000a234, 0x20202020 }, | ||
3010 | { 0x0000a238, 0x20202020 }, | ||
3011 | { 0x0000a23c, 0x13c88000 }, | ||
3012 | { 0x0000a240, 0x38490a20 }, | ||
3013 | { 0x0000a244, 0x00007bb6 }, | ||
3014 | { 0x0000a248, 0x0fff3ffc }, | ||
3015 | { 0x0000a24c, 0x00000000 }, | ||
3016 | { 0x0000a254, 0x00000000 }, | ||
3017 | { 0x0000a258, 0x0cdbd380 }, | ||
3018 | { 0x0000a25c, 0x0f0f0f01 }, | ||
3019 | { 0x0000a260, 0xdfa91f01 }, | ||
3020 | { 0x0000a268, 0x00000000 }, | ||
3021 | { 0x0000a26c, 0x0ebae9c6 }, | ||
3022 | { 0x0000b26c, 0x0ebae9c6 }, | ||
3023 | { 0x0000d270, 0x00820820 }, | ||
3024 | { 0x0000a278, 0x1ce739ce }, | ||
3025 | { 0x0000a27c, 0x050701ce }, | ||
3026 | { 0x0000d35c, 0x07ffffef }, | ||
3027 | { 0x0000d360, 0x0fffffe7 }, | ||
3028 | { 0x0000d364, 0x17ffffe5 }, | ||
3029 | { 0x0000d368, 0x1fffffe4 }, | ||
3030 | { 0x0000d36c, 0x37ffffe3 }, | ||
3031 | { 0x0000d370, 0x3fffffe3 }, | ||
3032 | { 0x0000d374, 0x57ffffe3 }, | ||
3033 | { 0x0000d378, 0x5fffffe2 }, | ||
3034 | { 0x0000d37c, 0x7fffffe2 }, | ||
3035 | { 0x0000d380, 0x7f3c7bba }, | ||
3036 | { 0x0000d384, 0xf3307ff0 }, | ||
3037 | { 0x0000a388, 0x0c000000 }, | ||
3038 | { 0x0000a38c, 0x20202020 }, | ||
3039 | { 0x0000a390, 0x20202020 }, | ||
3040 | { 0x0000a394, 0x1ce739ce }, | ||
3041 | { 0x0000a398, 0x000001ce }, | ||
3042 | { 0x0000a39c, 0x00000001 }, | ||
3043 | { 0x0000a3a0, 0x00000000 }, | ||
3044 | { 0x0000a3a4, 0x00000000 }, | ||
3045 | { 0x0000a3a8, 0x00000000 }, | ||
3046 | { 0x0000a3ac, 0x00000000 }, | ||
3047 | { 0x0000a3b0, 0x00000000 }, | ||
3048 | { 0x0000a3b4, 0x00000000 }, | ||
3049 | { 0x0000a3b8, 0x00000000 }, | ||
3050 | { 0x0000a3bc, 0x00000000 }, | ||
3051 | { 0x0000a3c0, 0x00000000 }, | ||
3052 | { 0x0000a3c4, 0x00000000 }, | ||
3053 | { 0x0000a3c8, 0x00000246 }, | ||
3054 | { 0x0000a3cc, 0x20202020 }, | ||
3055 | { 0x0000a3d0, 0x20202020 }, | ||
3056 | { 0x0000a3d4, 0x20202020 }, | ||
3057 | { 0x0000a3dc, 0x1ce739ce }, | ||
3058 | { 0x0000a3e0, 0x000001ce }, | ||
3059 | { 0x0000a3e4, 0x00000000 }, | ||
3060 | { 0x0000a3e8, 0x18c43433 }, | ||
3061 | { 0x0000a3ec, 0x00f70081 }, | ||
3062 | { 0x00007800, 0x00040000 }, | ||
3063 | { 0x00007804, 0xdb005012 }, | ||
3064 | { 0x00007808, 0x04924914 }, | ||
3065 | { 0x0000780c, 0x21084210 }, | ||
3066 | { 0x00007810, 0x6d801300 }, | ||
3067 | { 0x00007814, 0x0019beff }, | ||
3068 | { 0x00007818, 0x07e41000 }, | ||
3069 | { 0x0000781c, 0x00392000 }, | ||
3070 | { 0x00007820, 0x92592480 }, | ||
3071 | { 0x00007824, 0x00040000 }, | ||
3072 | { 0x00007828, 0xdb005012 }, | ||
3073 | { 0x0000782c, 0x04924914 }, | ||
3074 | { 0x00007830, 0x21084210 }, | ||
3075 | { 0x00007834, 0x6d801300 }, | ||
3076 | { 0x00007838, 0x0019beff }, | ||
3077 | { 0x0000783c, 0x07e40000 }, | ||
3078 | { 0x00007840, 0x00392000 }, | ||
3079 | { 0x00007844, 0x92592480 }, | ||
3080 | { 0x00007848, 0x00100000 }, | ||
3081 | { 0x0000784c, 0x773f0567 }, | ||
3082 | { 0x00007850, 0x54214514 }, | ||
3083 | { 0x00007854, 0x12035828 }, | ||
3084 | { 0x00007858, 0x9259269a }, | ||
3085 | { 0x00007860, 0x52802000 }, | ||
3086 | { 0x00007864, 0x0a8e370e }, | ||
3087 | { 0x00007868, 0xc0102850 }, | ||
3088 | { 0x0000786c, 0x812d4000 }, | ||
3089 | { 0x00007870, 0x807ec400 }, | ||
3090 | { 0x00007874, 0x001b6db0 }, | ||
3091 | { 0x00007878, 0x00376b63 }, | ||
3092 | { 0x0000787c, 0x06db6db6 }, | ||
3093 | { 0x00007880, 0x006d8000 }, | ||
3094 | { 0x00007884, 0xffeffffe }, | ||
3095 | { 0x00007888, 0xffeffffe }, | ||
3096 | { 0x0000788c, 0x00010000 }, | ||
3097 | { 0x00007890, 0x02060aeb }, | ||
3098 | { 0x00007898, 0x2a850160 }, | ||
3099 | }; | ||
3100 | |||
3101 | static const u32 ar9280Modes_fast_clock_9280_2[][3] = { | ||
3102 | { 0x00001030, 0x00000268, 0x000004d0 }, | ||
3103 | { 0x00001070, 0x0000018c, 0x00000318 }, | ||
3104 | { 0x000010b0, 0x00000fd0, 0x00001fa0 }, | ||
3105 | { 0x00008014, 0x044c044c, 0x08980898 }, | ||
3106 | { 0x0000801c, 0x148ec02b, 0x148ec057 }, | ||
3107 | { 0x00008318, 0x000044c0, 0x00008980 }, | ||
3108 | { 0x00009820, 0x02020200, 0x02020200 }, | ||
3109 | { 0x00009824, 0x00000f0f, 0x00000f0f }, | ||
3110 | { 0x00009828, 0x0b020001, 0x0b020001 }, | ||
3111 | { 0x00009834, 0x00000f0f, 0x00000f0f }, | ||
3112 | { 0x00009844, 0x03721821, 0x03721821 }, | ||
3113 | { 0x00009914, 0x00000898, 0x00000898 }, | ||
3114 | { 0x00009918, 0x0000000b, 0x00000016 }, | ||
3115 | { 0x00009944, 0xdfbc1210, 0xdfbc1210 }, | ||
3116 | }; | ||
3117 | |||
3118 | |||
3119 | |||
3120 | static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { | ||
3121 | {0x00004040, 0x9248fd00 }, | ||
3122 | {0x00004040, 0x24924924 }, | ||
3123 | {0x00004040, 0xa8000019 }, | ||
3124 | {0x00004040, 0x13160820 }, | ||
3125 | {0x00004040, 0xe5980560 }, | ||
3126 | {0x00004040, 0x401dcffc }, | ||
3127 | {0x00004040, 0x1aaabe40 }, | ||
3128 | {0x00004040, 0xbe105554 }, | ||
3129 | {0x00004040, 0x00043007 }, | ||
3130 | {0x00004044, 0x00000000 }, | ||
3131 | }; | ||
3132 | |||
3133 | |||
3134 | |||
3135 | static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { | ||
3136 | {0x00004040, 0x9248fd00 }, | ||
3137 | {0x00004040, 0x24924924 }, | ||
3138 | {0x00004040, 0xa8000019 }, | ||
3139 | {0x00004040, 0x13160820 }, | ||
3140 | {0x00004040, 0xe5980560 }, | ||
3141 | {0x00004040, 0x401dcffd }, | ||
3142 | {0x00004040, 0x1aaabe40 }, | ||
3143 | {0x00004040, 0xbe105554 }, | ||
3144 | {0x00004040, 0x00043007 }, | ||
3145 | {0x00004044, 0x00000000 }, | ||
3146 | }; | ||
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c new file mode 100644 index 00000000000..9549524630f --- /dev/null +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -0,0 +1,1533 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* mac80211 and PCI callbacks */ | ||
18 | |||
19 | #include <linux/nl80211.h> | ||
20 | #include "core.h" | ||
21 | |||
22 | #define ATH_PCI_VERSION "0.1" | ||
23 | |||
24 | #define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13 | ||
25 | #define IEEE80211_ACTION_CAT_HT 7 | ||
26 | #define IEEE80211_ACTION_HT_TXCHWIDTH 0 | ||
27 | |||
28 | static char *dev_info = "ath9k"; | ||
29 | |||
30 | MODULE_AUTHOR("Atheros Communications"); | ||
31 | MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); | ||
32 | MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); | ||
33 | MODULE_LICENSE("Dual BSD/GPL"); | ||
34 | |||
35 | static struct pci_device_id ath_pci_id_table[] __devinitdata = { | ||
36 | { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ | ||
37 | { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ | ||
38 | { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ | ||
39 | { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ | ||
40 | { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ | ||
41 | { 0 } | ||
42 | }; | ||
43 | |||
44 | static int ath_get_channel(struct ath_softc *sc, | ||
45 | struct ieee80211_channel *chan) | ||
46 | { | ||
47 | int i; | ||
48 | |||
49 | for (i = 0; i < sc->sc_ah->ah_nchan; i++) { | ||
50 | if (sc->sc_ah->ah_channels[i].channel == chan->center_freq) | ||
51 | return i; | ||
52 | } | ||
53 | |||
54 | return -1; | ||
55 | } | ||
56 | |||
57 | static u32 ath_get_extchanmode(struct ath_softc *sc, | ||
58 | struct ieee80211_channel *chan) | ||
59 | { | ||
60 | u32 chanmode = 0; | ||
61 | u8 ext_chan_offset = sc->sc_ht_info.ext_chan_offset; | ||
62 | enum ath9k_ht_macmode tx_chan_width = sc->sc_ht_info.tx_chan_width; | ||
63 | |||
64 | switch (chan->band) { | ||
65 | case IEEE80211_BAND_2GHZ: | ||
66 | if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) && | ||
67 | (tx_chan_width == ATH9K_HT_MACMODE_20)) | ||
68 | chanmode = CHANNEL_G_HT20; | ||
69 | if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) && | ||
70 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | ||
71 | chanmode = CHANNEL_G_HT40PLUS; | ||
72 | if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) && | ||
73 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | ||
74 | chanmode = CHANNEL_G_HT40MINUS; | ||
75 | break; | ||
76 | case IEEE80211_BAND_5GHZ: | ||
77 | if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) && | ||
78 | (tx_chan_width == ATH9K_HT_MACMODE_20)) | ||
79 | chanmode = CHANNEL_A_HT20; | ||
80 | if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) && | ||
81 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | ||
82 | chanmode = CHANNEL_A_HT40PLUS; | ||
83 | if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) && | ||
84 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | ||
85 | chanmode = CHANNEL_A_HT40MINUS; | ||
86 | break; | ||
87 | default: | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | return chanmode; | ||
92 | } | ||
93 | |||
94 | |||
95 | static int ath_setkey_tkip(struct ath_softc *sc, | ||
96 | struct ieee80211_key_conf *key, | ||
97 | struct ath9k_keyval *hk, | ||
98 | const u8 *addr) | ||
99 | { | ||
100 | u8 *key_rxmic = NULL; | ||
101 | u8 *key_txmic = NULL; | ||
102 | |||
103 | key_txmic = key->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
104 | key_rxmic = key->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
105 | |||
106 | if (addr == NULL) { | ||
107 | /* Group key installation */ | ||
108 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
109 | return ath_keyset(sc, key->keyidx, hk, addr); | ||
110 | } | ||
111 | if (!sc->sc_splitmic) { | ||
112 | /* | ||
113 | * data key goes at first index, | ||
114 | * the hal handles the MIC keys at index+64. | ||
115 | */ | ||
116 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
117 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); | ||
118 | return ath_keyset(sc, key->keyidx, hk, addr); | ||
119 | } | ||
120 | /* | ||
121 | * TX key goes at first index, RX key at +32. | ||
122 | * The hal handles the MIC keys at index+64. | ||
123 | */ | ||
124 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
125 | if (!ath_keyset(sc, key->keyidx, hk, NULL)) { | ||
126 | /* Txmic entry failed. No need to proceed further */ | ||
127 | DPRINTF(sc, ATH_DBG_KEYCACHE, | ||
128 | "%s Setting TX MIC Key Failed\n", __func__); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
133 | /* XXX delete tx key on failure? */ | ||
134 | return ath_keyset(sc, key->keyidx+32, hk, addr); | ||
135 | } | ||
136 | |||
137 | static int ath_key_config(struct ath_softc *sc, | ||
138 | const u8 *addr, | ||
139 | struct ieee80211_key_conf *key) | ||
140 | { | ||
141 | struct ieee80211_vif *vif; | ||
142 | struct ath9k_keyval hk; | ||
143 | const u8 *mac = NULL; | ||
144 | int ret = 0; | ||
145 | enum ieee80211_if_types opmode; | ||
146 | |||
147 | memset(&hk, 0, sizeof(hk)); | ||
148 | |||
149 | switch (key->alg) { | ||
150 | case ALG_WEP: | ||
151 | hk.kv_type = ATH9K_CIPHER_WEP; | ||
152 | break; | ||
153 | case ALG_TKIP: | ||
154 | hk.kv_type = ATH9K_CIPHER_TKIP; | ||
155 | break; | ||
156 | case ALG_CCMP: | ||
157 | hk.kv_type = ATH9K_CIPHER_AES_CCM; | ||
158 | break; | ||
159 | default: | ||
160 | return -EINVAL; | ||
161 | } | ||
162 | |||
163 | hk.kv_len = key->keylen; | ||
164 | memcpy(hk.kv_val, key->key, key->keylen); | ||
165 | |||
166 | if (!sc->sc_vaps[0]) | ||
167 | return -EIO; | ||
168 | |||
169 | vif = sc->sc_vaps[0]->av_if_data; | ||
170 | opmode = vif->type; | ||
171 | |||
172 | /* | ||
173 | * Strategy: | ||
174 | * For _M_STA mc tx, we will not setup a key at all since we never | ||
175 | * tx mc. | ||
176 | * _M_STA mc rx, we will use the keyID. | ||
177 | * for _M_IBSS mc tx, we will use the keyID, and no macaddr. | ||
178 | * for _M_IBSS mc rx, we will alloc a slot and plumb the mac of the | ||
179 | * peer node. BUT we will plumb a cleartext key so that we can do | ||
180 | * perSta default key table lookup in software. | ||
181 | */ | ||
182 | if (is_broadcast_ether_addr(addr)) { | ||
183 | switch (opmode) { | ||
184 | case IEEE80211_IF_TYPE_STA: | ||
185 | /* default key: could be group WPA key | ||
186 | * or could be static WEP key */ | ||
187 | mac = NULL; | ||
188 | break; | ||
189 | case IEEE80211_IF_TYPE_IBSS: | ||
190 | break; | ||
191 | case IEEE80211_IF_TYPE_AP: | ||
192 | break; | ||
193 | default: | ||
194 | ASSERT(0); | ||
195 | break; | ||
196 | } | ||
197 | } else { | ||
198 | mac = addr; | ||
199 | } | ||
200 | |||
201 | if (key->alg == ALG_TKIP) | ||
202 | ret = ath_setkey_tkip(sc, key, &hk, mac); | ||
203 | else | ||
204 | ret = ath_keyset(sc, key->keyidx, &hk, mac); | ||
205 | |||
206 | if (!ret) | ||
207 | return -EIO; | ||
208 | |||
209 | sc->sc_keytype = hk.kv_type; | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) | ||
214 | { | ||
215 | #define ATH_MAX_NUM_KEYS 4 | ||
216 | int freeslot; | ||
217 | |||
218 | freeslot = (key->keyidx >= ATH_MAX_NUM_KEYS) ? 1 : 0; | ||
219 | ath_key_reset(sc, key->keyidx, freeslot); | ||
220 | #undef ATH_MAX_NUM_KEYS | ||
221 | } | ||
222 | |||
223 | static void setup_ht_cap(struct ieee80211_ht_info *ht_info) | ||
224 | { | ||
225 | /* Until mac80211 includes these fields */ | ||
226 | |||
227 | #define IEEE80211_HT_CAP_DSSSCCK40 0x1000 | ||
228 | #define IEEE80211_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ | ||
229 | #define IEEE80211_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ | ||
230 | |||
231 | ht_info->ht_supported = 1; | ||
232 | ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH | ||
233 | |(u16)IEEE80211_HT_CAP_MIMO_PS | ||
234 | |(u16)IEEE80211_HT_CAP_SGI_40 | ||
235 | |(u16)IEEE80211_HT_CAP_DSSSCCK40; | ||
236 | |||
237 | ht_info->ampdu_factor = IEEE80211_HT_CAP_MAXRXAMPDU_65536; | ||
238 | ht_info->ampdu_density = IEEE80211_HT_CAP_MPDUDENSITY_8; | ||
239 | /* setup supported mcs set */ | ||
240 | memset(ht_info->supp_mcs_set, 0, 16); | ||
241 | ht_info->supp_mcs_set[0] = 0xff; | ||
242 | ht_info->supp_mcs_set[1] = 0xff; | ||
243 | ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED; | ||
244 | } | ||
245 | |||
246 | static int ath_rate2idx(struct ath_softc *sc, int rate) | ||
247 | { | ||
248 | int i = 0, cur_band, n_rates; | ||
249 | struct ieee80211_hw *hw = sc->hw; | ||
250 | |||
251 | cur_band = hw->conf.channel->band; | ||
252 | n_rates = sc->sbands[cur_band].n_bitrates; | ||
253 | |||
254 | for (i = 0; i < n_rates; i++) { | ||
255 | if (sc->sbands[cur_band].bitrates[i].bitrate == rate) | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * NB:mac80211 validates rx rate index against the supported legacy rate | ||
261 | * index only (should be done against ht rates also), return the highest | ||
262 | * legacy rate index for rx rate which does not match any one of the | ||
263 | * supported basic and extended rates to make mac80211 happy. | ||
264 | * The following hack will be cleaned up once the issue with | ||
265 | * the rx rate index validation in mac80211 is fixed. | ||
266 | */ | ||
267 | if (i == n_rates) | ||
268 | return n_rates - 1; | ||
269 | return i; | ||
270 | } | ||
271 | |||
272 | static void ath9k_rx_prepare(struct ath_softc *sc, | ||
273 | struct sk_buff *skb, | ||
274 | struct ath_recv_status *status, | ||
275 | struct ieee80211_rx_status *rx_status) | ||
276 | { | ||
277 | struct ieee80211_hw *hw = sc->hw; | ||
278 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
279 | |||
280 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); | ||
281 | |||
282 | rx_status->mactime = status->tsf; | ||
283 | rx_status->band = curchan->band; | ||
284 | rx_status->freq = curchan->center_freq; | ||
285 | rx_status->noise = ATH_DEFAULT_NOISE_FLOOR; | ||
286 | rx_status->signal = rx_status->noise + status->rssi; | ||
287 | rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100)); | ||
288 | rx_status->antenna = status->antenna; | ||
289 | rx_status->qual = status->rssi * 100 / 64; | ||
290 | |||
291 | if (status->flags & ATH_RX_MIC_ERROR) | ||
292 | rx_status->flag |= RX_FLAG_MMIC_ERROR; | ||
293 | if (status->flags & ATH_RX_FCS_ERROR) | ||
294 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
295 | |||
296 | rx_status->flag |= RX_FLAG_TSFT; | ||
297 | } | ||
298 | |||
299 | static u8 parse_mpdudensity(u8 mpdudensity) | ||
300 | { | ||
301 | /* | ||
302 | * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": | ||
303 | * 0 for no restriction | ||
304 | * 1 for 1/4 us | ||
305 | * 2 for 1/2 us | ||
306 | * 3 for 1 us | ||
307 | * 4 for 2 us | ||
308 | * 5 for 4 us | ||
309 | * 6 for 8 us | ||
310 | * 7 for 16 us | ||
311 | */ | ||
312 | switch (mpdudensity) { | ||
313 | case 0: | ||
314 | return 0; | ||
315 | case 1: | ||
316 | case 2: | ||
317 | case 3: | ||
318 | /* Our lower layer calculations limit our precision to | ||
319 | 1 microsecond */ | ||
320 | return 1; | ||
321 | case 4: | ||
322 | return 2; | ||
323 | case 5: | ||
324 | return 4; | ||
325 | case 6: | ||
326 | return 8; | ||
327 | case 7: | ||
328 | return 16; | ||
329 | default: | ||
330 | return 0; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | static int ath9k_start(struct ieee80211_hw *hw) | ||
335 | { | ||
336 | struct ath_softc *sc = hw->priv; | ||
337 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
338 | int error = 0, pos; | ||
339 | |||
340 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with " | ||
341 | "initial channel: %d MHz\n", __func__, curchan->center_freq); | ||
342 | |||
343 | /* setup initial channel */ | ||
344 | |||
345 | pos = ath_get_channel(sc, curchan); | ||
346 | if (pos == -1) { | ||
347 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | |||
351 | sc->sc_ah->ah_channels[pos].chanmode = | ||
352 | (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; | ||
353 | |||
354 | /* open ath_dev */ | ||
355 | error = ath_open(sc, &sc->sc_ah->ah_channels[pos]); | ||
356 | if (error) { | ||
357 | DPRINTF(sc, ATH_DBG_FATAL, | ||
358 | "%s: Unable to complete ath_open\n", __func__); | ||
359 | return error; | ||
360 | } | ||
361 | |||
362 | ieee80211_wake_queues(hw); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static int ath9k_tx(struct ieee80211_hw *hw, | ||
367 | struct sk_buff *skb) | ||
368 | { | ||
369 | struct ath_softc *sc = hw->priv; | ||
370 | int hdrlen, padsize; | ||
371 | |||
372 | /* Add the padding after the header if this is not already done */ | ||
373 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
374 | if (hdrlen & 3) { | ||
375 | padsize = hdrlen % 4; | ||
376 | if (skb_headroom(skb) < padsize) | ||
377 | return -1; | ||
378 | skb_push(skb, padsize); | ||
379 | memmove(skb->data, skb->data + padsize, hdrlen); | ||
380 | } | ||
381 | |||
382 | DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting packet, skb: %p\n", | ||
383 | __func__, | ||
384 | skb); | ||
385 | |||
386 | if (ath_tx_start(sc, skb) != 0) { | ||
387 | DPRINTF(sc, ATH_DBG_XMIT, "%s: TX failed\n", __func__); | ||
388 | dev_kfree_skb_any(skb); | ||
389 | /* FIXME: Check for proper return value from ATH_DEV */ | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static void ath9k_stop(struct ieee80211_hw *hw) | ||
397 | { | ||
398 | struct ath_softc *sc = hw->priv; | ||
399 | int error; | ||
400 | |||
401 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); | ||
402 | |||
403 | error = ath_suspend(sc); | ||
404 | if (error) | ||
405 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
406 | "%s: Device is no longer present\n", __func__); | ||
407 | |||
408 | ieee80211_stop_queues(hw); | ||
409 | } | ||
410 | |||
411 | static int ath9k_add_interface(struct ieee80211_hw *hw, | ||
412 | struct ieee80211_if_init_conf *conf) | ||
413 | { | ||
414 | struct ath_softc *sc = hw->priv; | ||
415 | int error, ic_opmode = 0; | ||
416 | |||
417 | /* Support only vap for now */ | ||
418 | |||
419 | if (sc->sc_nvaps) | ||
420 | return -ENOBUFS; | ||
421 | |||
422 | switch (conf->type) { | ||
423 | case IEEE80211_IF_TYPE_STA: | ||
424 | ic_opmode = ATH9K_M_STA; | ||
425 | break; | ||
426 | case IEEE80211_IF_TYPE_IBSS: | ||
427 | ic_opmode = ATH9K_M_IBSS; | ||
428 | break; | ||
429 | default: | ||
430 | DPRINTF(sc, ATH_DBG_FATAL, | ||
431 | "%s: Only STA and IBSS are supported currently\n", | ||
432 | __func__); | ||
433 | return -EOPNOTSUPP; | ||
434 | } | ||
435 | |||
436 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a VAP of type: %d\n", | ||
437 | __func__, | ||
438 | ic_opmode); | ||
439 | |||
440 | error = ath_vap_attach(sc, 0, conf->vif, ic_opmode); | ||
441 | if (error) { | ||
442 | DPRINTF(sc, ATH_DBG_FATAL, | ||
443 | "%s: Unable to attach vap, error: %d\n", | ||
444 | __func__, error); | ||
445 | return error; | ||
446 | } | ||
447 | |||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static void ath9k_remove_interface(struct ieee80211_hw *hw, | ||
452 | struct ieee80211_if_init_conf *conf) | ||
453 | { | ||
454 | struct ath_softc *sc = hw->priv; | ||
455 | struct ath_vap *avp; | ||
456 | int error; | ||
457 | |||
458 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__); | ||
459 | |||
460 | avp = sc->sc_vaps[0]; | ||
461 | if (avp == NULL) { | ||
462 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", | ||
463 | __func__); | ||
464 | return; | ||
465 | } | ||
466 | |||
467 | #ifdef CONFIG_SLOW_ANT_DIV | ||
468 | ath_slow_ant_div_stop(&sc->sc_antdiv); | ||
469 | #endif | ||
470 | |||
471 | /* Update ratectrl */ | ||
472 | ath_rate_newstate(sc, avp); | ||
473 | |||
474 | /* Reclaim beacon resources */ | ||
475 | if (sc->sc_opmode == ATH9K_M_HOSTAP || sc->sc_opmode == ATH9K_M_IBSS) { | ||
476 | ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); | ||
477 | ath_beacon_return(sc, avp); | ||
478 | } | ||
479 | |||
480 | /* Set interrupt mask */ | ||
481 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | ||
482 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL); | ||
483 | sc->sc_beacons = 0; | ||
484 | |||
485 | error = ath_vap_detach(sc, 0); | ||
486 | if (error) | ||
487 | DPRINTF(sc, ATH_DBG_FATAL, | ||
488 | "%s: Unable to detach vap, error: %d\n", | ||
489 | __func__, error); | ||
490 | } | ||
491 | |||
492 | static int ath9k_config(struct ieee80211_hw *hw, | ||
493 | struct ieee80211_conf *conf) | ||
494 | { | ||
495 | struct ath_softc *sc = hw->priv; | ||
496 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
497 | int pos; | ||
498 | |||
499 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", | ||
500 | __func__, | ||
501 | curchan->center_freq); | ||
502 | |||
503 | pos = ath_get_channel(sc, curchan); | ||
504 | if (pos == -1) { | ||
505 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); | ||
506 | return -EINVAL; | ||
507 | } | ||
508 | |||
509 | sc->sc_ah->ah_channels[pos].chanmode = | ||
510 | (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; | ||
511 | sc->sc_config.txpowlimit = 2 * conf->power_level; | ||
512 | |||
513 | /* set h/w channel */ | ||
514 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | ||
515 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n", | ||
516 | __func__); | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static int ath9k_config_interface(struct ieee80211_hw *hw, | ||
522 | struct ieee80211_vif *vif, | ||
523 | struct ieee80211_if_conf *conf) | ||
524 | { | ||
525 | struct ath_softc *sc = hw->priv; | ||
526 | struct ath_vap *avp; | ||
527 | u32 rfilt = 0; | ||
528 | int error, i; | ||
529 | DECLARE_MAC_BUF(mac); | ||
530 | |||
531 | avp = sc->sc_vaps[0]; | ||
532 | if (avp == NULL) { | ||
533 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", | ||
534 | __func__); | ||
535 | return -EINVAL; | ||
536 | } | ||
537 | |||
538 | if ((conf->changed & IEEE80211_IFCC_BSSID) && | ||
539 | !is_zero_ether_addr(conf->bssid)) { | ||
540 | switch (vif->type) { | ||
541 | case IEEE80211_IF_TYPE_STA: | ||
542 | case IEEE80211_IF_TYPE_IBSS: | ||
543 | /* Update ratectrl about the new state */ | ||
544 | ath_rate_newstate(sc, avp); | ||
545 | |||
546 | /* Set rx filter */ | ||
547 | rfilt = ath_calcrxfilter(sc); | ||
548 | ath9k_hw_setrxfilter(sc->sc_ah, rfilt); | ||
549 | |||
550 | /* Set BSSID */ | ||
551 | memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN); | ||
552 | sc->sc_curaid = 0; | ||
553 | ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid, | ||
554 | sc->sc_curaid); | ||
555 | |||
556 | /* Set aggregation protection mode parameters */ | ||
557 | sc->sc_config.ath_aggr_prot = 0; | ||
558 | |||
559 | /* | ||
560 | * Reset our TSF so that its value is lower than the | ||
561 | * beacon that we are trying to catch. | ||
562 | * Only then hw will update its TSF register with the | ||
563 | * new beacon. Reset the TSF before setting the BSSID | ||
564 | * to avoid allowing in any frames that would update | ||
565 | * our TSF only to have us clear it | ||
566 | * immediately thereafter. | ||
567 | */ | ||
568 | ath9k_hw_reset_tsf(sc->sc_ah); | ||
569 | |||
570 | /* Disable BMISS interrupt when we're not associated */ | ||
571 | ath9k_hw_set_interrupts(sc->sc_ah, | ||
572 | sc->sc_imask & | ||
573 | ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS)); | ||
574 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | ||
575 | |||
576 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
577 | "%s: RX filter 0x%x bssid %s aid 0x%x\n", | ||
578 | __func__, rfilt, | ||
579 | print_mac(mac, sc->sc_curbssid), sc->sc_curaid); | ||
580 | |||
581 | /* need to reconfigure the beacon */ | ||
582 | sc->sc_beacons = 0; | ||
583 | |||
584 | break; | ||
585 | default: | ||
586 | break; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | if ((conf->changed & IEEE80211_IFCC_BEACON) && | ||
591 | (vif->type == IEEE80211_IF_TYPE_IBSS)) { | ||
592 | /* | ||
593 | * Allocate and setup the beacon frame. | ||
594 | * | ||
595 | * Stop any previous beacon DMA. This may be | ||
596 | * necessary, for example, when an ibss merge | ||
597 | * causes reconfiguration; we may be called | ||
598 | * with beacon transmission active. | ||
599 | */ | ||
600 | ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); | ||
601 | |||
602 | error = ath_beacon_alloc(sc, 0); | ||
603 | if (error != 0) | ||
604 | return error; | ||
605 | |||
606 | ath_beacon_sync(sc, 0); | ||
607 | } | ||
608 | |||
609 | /* Check for WLAN_CAPABILITY_PRIVACY ? */ | ||
610 | if ((avp->av_opmode != IEEE80211_IF_TYPE_STA)) { | ||
611 | for (i = 0; i < IEEE80211_WEP_NKID; i++) | ||
612 | if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) | ||
613 | ath9k_hw_keysetmac(sc->sc_ah, | ||
614 | (u16)i, | ||
615 | sc->sc_curbssid); | ||
616 | } | ||
617 | |||
618 | /* Only legacy IBSS for now */ | ||
619 | if (vif->type == IEEE80211_IF_TYPE_IBSS) | ||
620 | ath_update_chainmask(sc, 0); | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | #define SUPPORTED_FILTERS \ | ||
626 | (FIF_PROMISC_IN_BSS | \ | ||
627 | FIF_ALLMULTI | \ | ||
628 | FIF_CONTROL | \ | ||
629 | FIF_OTHER_BSS | \ | ||
630 | FIF_BCN_PRBRESP_PROMISC | \ | ||
631 | FIF_FCSFAIL) | ||
632 | |||
633 | /* Accept unicast, bcast and mcast frames */ | ||
634 | |||
635 | static void ath9k_configure_filter(struct ieee80211_hw *hw, | ||
636 | unsigned int changed_flags, | ||
637 | unsigned int *total_flags, | ||
638 | int mc_count, | ||
639 | struct dev_mc_list *mclist) | ||
640 | { | ||
641 | struct ath_softc *sc = hw->priv; | ||
642 | |||
643 | changed_flags &= SUPPORTED_FILTERS; | ||
644 | *total_flags &= SUPPORTED_FILTERS; | ||
645 | |||
646 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | ||
647 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | ||
648 | ath_scan_start(sc); | ||
649 | else | ||
650 | ath_scan_end(sc); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | static void ath9k_sta_notify(struct ieee80211_hw *hw, | ||
655 | struct ieee80211_vif *vif, | ||
656 | enum sta_notify_cmd cmd, | ||
657 | const u8 *addr) | ||
658 | { | ||
659 | struct ath_softc *sc = hw->priv; | ||
660 | struct ath_node *an; | ||
661 | unsigned long flags; | ||
662 | DECLARE_MAC_BUF(mac); | ||
663 | |||
664 | spin_lock_irqsave(&sc->node_lock, flags); | ||
665 | an = ath_node_find(sc, (u8 *) addr); | ||
666 | spin_unlock_irqrestore(&sc->node_lock, flags); | ||
667 | |||
668 | switch (cmd) { | ||
669 | case STA_NOTIFY_ADD: | ||
670 | spin_lock_irqsave(&sc->node_lock, flags); | ||
671 | if (!an) { | ||
672 | ath_node_attach(sc, (u8 *)addr, 0); | ||
673 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n", | ||
674 | __func__, | ||
675 | print_mac(mac, addr)); | ||
676 | } else { | ||
677 | ath_node_get(sc, (u8 *)addr); | ||
678 | } | ||
679 | spin_unlock_irqrestore(&sc->node_lock, flags); | ||
680 | break; | ||
681 | case STA_NOTIFY_REMOVE: | ||
682 | if (!an) | ||
683 | DPRINTF(sc, ATH_DBG_FATAL, | ||
684 | "%s: Removal of a non-existent node\n", | ||
685 | __func__); | ||
686 | else { | ||
687 | ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT); | ||
688 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n", | ||
689 | __func__, | ||
690 | print_mac(mac, addr)); | ||
691 | } | ||
692 | break; | ||
693 | default: | ||
694 | break; | ||
695 | } | ||
696 | } | ||
697 | |||
698 | static int ath9k_conf_tx(struct ieee80211_hw *hw, | ||
699 | u16 queue, | ||
700 | const struct ieee80211_tx_queue_params *params) | ||
701 | { | ||
702 | struct ath_softc *sc = hw->priv; | ||
703 | struct ath9k_txq_info qi; | ||
704 | int ret = 0, qnum; | ||
705 | |||
706 | if (queue >= WME_NUM_AC) | ||
707 | return 0; | ||
708 | |||
709 | qi.tqi_aifs = params->aifs; | ||
710 | qi.tqi_cwmin = params->cw_min; | ||
711 | qi.tqi_cwmax = params->cw_max; | ||
712 | qi.tqi_burstTime = params->txop; | ||
713 | qnum = ath_get_hal_qnum(queue, sc); | ||
714 | |||
715 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
716 | "%s: Configure tx [queue/halq] [%d/%d], " | ||
717 | "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", | ||
718 | __func__, | ||
719 | queue, | ||
720 | qnum, | ||
721 | params->aifs, | ||
722 | params->cw_min, | ||
723 | params->cw_max, | ||
724 | params->txop); | ||
725 | |||
726 | ret = ath_txq_update(sc, qnum, &qi); | ||
727 | if (ret) | ||
728 | DPRINTF(sc, ATH_DBG_FATAL, | ||
729 | "%s: TXQ Update failed\n", __func__); | ||
730 | |||
731 | return ret; | ||
732 | } | ||
733 | |||
734 | static int ath9k_set_key(struct ieee80211_hw *hw, | ||
735 | enum set_key_cmd cmd, | ||
736 | const u8 *local_addr, | ||
737 | const u8 *addr, | ||
738 | struct ieee80211_key_conf *key) | ||
739 | { | ||
740 | struct ath_softc *sc = hw->priv; | ||
741 | int ret = 0; | ||
742 | |||
743 | DPRINTF(sc, ATH_DBG_KEYCACHE, " %s: Set HW Key\n", __func__); | ||
744 | |||
745 | switch (cmd) { | ||
746 | case SET_KEY: | ||
747 | ret = ath_key_config(sc, addr, key); | ||
748 | if (!ret) { | ||
749 | set_bit(key->keyidx, sc->sc_keymap); | ||
750 | key->hw_key_idx = key->keyidx; | ||
751 | /* push IV and Michael MIC generation to stack */ | ||
752 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
753 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
754 | } | ||
755 | break; | ||
756 | case DISABLE_KEY: | ||
757 | ath_key_delete(sc, key); | ||
758 | clear_bit(key->keyidx, sc->sc_keymap); | ||
759 | sc->sc_keytype = ATH9K_CIPHER_CLR; | ||
760 | break; | ||
761 | default: | ||
762 | ret = -EINVAL; | ||
763 | } | ||
764 | |||
765 | return ret; | ||
766 | } | ||
767 | |||
768 | static void ath9k_ht_conf(struct ath_softc *sc, | ||
769 | struct ieee80211_bss_conf *bss_conf) | ||
770 | { | ||
771 | #define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14) | ||
772 | struct ath_ht_info *ht_info = &sc->sc_ht_info; | ||
773 | |||
774 | if (bss_conf->assoc_ht) { | ||
775 | ht_info->ext_chan_offset = | ||
776 | bss_conf->ht_bss_conf->bss_cap & | ||
777 | IEEE80211_HT_IE_CHA_SEC_OFFSET; | ||
778 | |||
779 | if (!(bss_conf->ht_conf->cap & | ||
780 | IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | ||
781 | (bss_conf->ht_bss_conf->bss_cap & | ||
782 | IEEE80211_HT_IE_CHA_WIDTH)) | ||
783 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; | ||
784 | else | ||
785 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; | ||
786 | |||
787 | ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); | ||
788 | ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + | ||
789 | bss_conf->ht_conf->ampdu_factor); | ||
790 | ht_info->mpdudensity = | ||
791 | parse_mpdudensity(bss_conf->ht_conf->ampdu_density); | ||
792 | |||
793 | } | ||
794 | |||
795 | #undef IEEE80211_HT_CAP_40MHZ_INTOLERANT | ||
796 | } | ||
797 | |||
798 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | ||
799 | struct ieee80211_bss_conf *bss_conf) | ||
800 | { | ||
801 | struct ieee80211_hw *hw = sc->hw; | ||
802 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
803 | struct ath_vap *avp; | ||
804 | int pos; | ||
805 | DECLARE_MAC_BUF(mac); | ||
806 | |||
807 | if (bss_conf->assoc) { | ||
808 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n", | ||
809 | __func__, | ||
810 | bss_conf->aid); | ||
811 | |||
812 | avp = sc->sc_vaps[0]; | ||
813 | if (avp == NULL) { | ||
814 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", | ||
815 | __func__); | ||
816 | return; | ||
817 | } | ||
818 | |||
819 | /* New association, store aid */ | ||
820 | if (avp->av_opmode == ATH9K_M_STA) { | ||
821 | sc->sc_curaid = bss_conf->aid; | ||
822 | ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid, | ||
823 | sc->sc_curaid); | ||
824 | } | ||
825 | |||
826 | /* Configure the beacon */ | ||
827 | ath_beacon_config(sc, 0); | ||
828 | sc->sc_beacons = 1; | ||
829 | |||
830 | /* Reset rssi stats */ | ||
831 | sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; | ||
832 | sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; | ||
833 | sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; | ||
834 | sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; | ||
835 | |||
836 | /* Update chainmask */ | ||
837 | ath_update_chainmask(sc, bss_conf->assoc_ht); | ||
838 | |||
839 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
840 | "%s: bssid %s aid 0x%x\n", | ||
841 | __func__, | ||
842 | print_mac(mac, sc->sc_curbssid), sc->sc_curaid); | ||
843 | |||
844 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", | ||
845 | __func__, | ||
846 | curchan->center_freq); | ||
847 | |||
848 | pos = ath_get_channel(sc, curchan); | ||
849 | if (pos == -1) { | ||
850 | DPRINTF(sc, ATH_DBG_FATAL, | ||
851 | "%s: Invalid channel\n", __func__); | ||
852 | return; | ||
853 | } | ||
854 | |||
855 | if (hw->conf.ht_conf.ht_supported) | ||
856 | sc->sc_ah->ah_channels[pos].chanmode = | ||
857 | ath_get_extchanmode(sc, curchan); | ||
858 | else | ||
859 | sc->sc_ah->ah_channels[pos].chanmode = | ||
860 | (curchan->band == IEEE80211_BAND_2GHZ) ? | ||
861 | CHANNEL_G : CHANNEL_A; | ||
862 | |||
863 | /* set h/w channel */ | ||
864 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | ||
865 | DPRINTF(sc, ATH_DBG_FATAL, | ||
866 | "%s: Unable to set channel\n", | ||
867 | __func__); | ||
868 | |||
869 | ath_rate_newstate(sc, avp); | ||
870 | /* Update ratectrl about the new state */ | ||
871 | ath_rc_node_update(hw, avp->rc_node); | ||
872 | } else { | ||
873 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
874 | "%s: Bss Info DISSOC\n", __func__); | ||
875 | sc->sc_curaid = 0; | ||
876 | } | ||
877 | } | ||
878 | |||
879 | static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | ||
880 | struct ieee80211_vif *vif, | ||
881 | struct ieee80211_bss_conf *bss_conf, | ||
882 | u32 changed) | ||
883 | { | ||
884 | struct ath_softc *sc = hw->priv; | ||
885 | |||
886 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | ||
887 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed PREAMBLE %d\n", | ||
888 | __func__, | ||
889 | bss_conf->use_short_preamble); | ||
890 | if (bss_conf->use_short_preamble) | ||
891 | sc->sc_flags |= ATH_PREAMBLE_SHORT; | ||
892 | else | ||
893 | sc->sc_flags &= ~ATH_PREAMBLE_SHORT; | ||
894 | } | ||
895 | |||
896 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | ||
897 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed CTS PROT %d\n", | ||
898 | __func__, | ||
899 | bss_conf->use_cts_prot); | ||
900 | if (bss_conf->use_cts_prot && | ||
901 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) | ||
902 | sc->sc_flags |= ATH_PROTECT_ENABLE; | ||
903 | else | ||
904 | sc->sc_flags &= ~ATH_PROTECT_ENABLE; | ||
905 | } | ||
906 | |||
907 | if (changed & BSS_CHANGED_HT) { | ||
908 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n", | ||
909 | __func__, | ||
910 | bss_conf->assoc_ht); | ||
911 | ath9k_ht_conf(sc, bss_conf); | ||
912 | } | ||
913 | |||
914 | if (changed & BSS_CHANGED_ASSOC) { | ||
915 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n", | ||
916 | __func__, | ||
917 | bss_conf->assoc); | ||
918 | ath9k_bss_assoc_info(sc, bss_conf); | ||
919 | } | ||
920 | } | ||
921 | |||
922 | static u64 ath9k_get_tsf(struct ieee80211_hw *hw) | ||
923 | { | ||
924 | u64 tsf; | ||
925 | struct ath_softc *sc = hw->priv; | ||
926 | struct ath_hal *ah = sc->sc_ah; | ||
927 | |||
928 | tsf = ath9k_hw_gettsf64(ah); | ||
929 | |||
930 | return tsf; | ||
931 | } | ||
932 | |||
933 | static void ath9k_reset_tsf(struct ieee80211_hw *hw) | ||
934 | { | ||
935 | struct ath_softc *sc = hw->priv; | ||
936 | struct ath_hal *ah = sc->sc_ah; | ||
937 | |||
938 | ath9k_hw_reset_tsf(ah); | ||
939 | } | ||
940 | |||
941 | static int ath9k_ampdu_action(struct ieee80211_hw *hw, | ||
942 | enum ieee80211_ampdu_mlme_action action, | ||
943 | const u8 *addr, | ||
944 | u16 tid, | ||
945 | u16 *ssn) | ||
946 | { | ||
947 | struct ath_softc *sc = hw->priv; | ||
948 | int ret = 0; | ||
949 | |||
950 | switch (action) { | ||
951 | case IEEE80211_AMPDU_RX_START: | ||
952 | ret = ath_rx_aggr_start(sc, addr, tid, ssn); | ||
953 | if (ret < 0) | ||
954 | DPRINTF(sc, ATH_DBG_FATAL, | ||
955 | "%s: Unable to start RX aggregation\n", | ||
956 | __func__); | ||
957 | break; | ||
958 | case IEEE80211_AMPDU_RX_STOP: | ||
959 | ret = ath_rx_aggr_stop(sc, addr, tid); | ||
960 | if (ret < 0) | ||
961 | DPRINTF(sc, ATH_DBG_FATAL, | ||
962 | "%s: Unable to stop RX aggregation\n", | ||
963 | __func__); | ||
964 | break; | ||
965 | case IEEE80211_AMPDU_TX_START: | ||
966 | ret = ath_tx_aggr_start(sc, addr, tid, ssn); | ||
967 | if (ret < 0) | ||
968 | DPRINTF(sc, ATH_DBG_FATAL, | ||
969 | "%s: Unable to start TX aggregation\n", | ||
970 | __func__); | ||
971 | else | ||
972 | ieee80211_start_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid); | ||
973 | break; | ||
974 | case IEEE80211_AMPDU_TX_STOP: | ||
975 | ret = ath_tx_aggr_stop(sc, addr, tid); | ||
976 | if (ret < 0) | ||
977 | DPRINTF(sc, ATH_DBG_FATAL, | ||
978 | "%s: Unable to stop TX aggregation\n", | ||
979 | __func__); | ||
980 | |||
981 | ieee80211_stop_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid); | ||
982 | break; | ||
983 | default: | ||
984 | DPRINTF(sc, ATH_DBG_FATAL, | ||
985 | "%s: Unknown AMPDU action\n", __func__); | ||
986 | } | ||
987 | |||
988 | return ret; | ||
989 | } | ||
990 | |||
991 | static struct ieee80211_ops ath9k_ops = { | ||
992 | .tx = ath9k_tx, | ||
993 | .start = ath9k_start, | ||
994 | .stop = ath9k_stop, | ||
995 | .add_interface = ath9k_add_interface, | ||
996 | .remove_interface = ath9k_remove_interface, | ||
997 | .config = ath9k_config, | ||
998 | .config_interface = ath9k_config_interface, | ||
999 | .configure_filter = ath9k_configure_filter, | ||
1000 | .get_stats = NULL, | ||
1001 | .sta_notify = ath9k_sta_notify, | ||
1002 | .conf_tx = ath9k_conf_tx, | ||
1003 | .get_tx_stats = NULL, | ||
1004 | .bss_info_changed = ath9k_bss_info_changed, | ||
1005 | .set_tim = NULL, | ||
1006 | .set_key = ath9k_set_key, | ||
1007 | .hw_scan = NULL, | ||
1008 | .get_tkip_seq = NULL, | ||
1009 | .set_rts_threshold = NULL, | ||
1010 | .set_frag_threshold = NULL, | ||
1011 | .set_retry_limit = NULL, | ||
1012 | .get_tsf = ath9k_get_tsf, | ||
1013 | .reset_tsf = ath9k_reset_tsf, | ||
1014 | .tx_last_beacon = NULL, | ||
1015 | .ampdu_action = ath9k_ampdu_action | ||
1016 | }; | ||
1017 | |||
1018 | void ath_get_beaconconfig(struct ath_softc *sc, | ||
1019 | int if_id, | ||
1020 | struct ath_beacon_config *conf) | ||
1021 | { | ||
1022 | struct ieee80211_hw *hw = sc->hw; | ||
1023 | |||
1024 | /* fill in beacon config data */ | ||
1025 | |||
1026 | conf->beacon_interval = hw->conf.beacon_int; | ||
1027 | conf->listen_interval = 100; | ||
1028 | conf->dtim_count = 1; | ||
1029 | conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; | ||
1030 | } | ||
1031 | |||
1032 | int ath_update_beacon(struct ath_softc *sc, | ||
1033 | int if_id, | ||
1034 | struct ath_beacon_offset *bo, | ||
1035 | struct sk_buff *skb, | ||
1036 | int mcast) | ||
1037 | { | ||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
1041 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | ||
1042 | struct ath_xmit_status *tx_status, struct ath_node *an) | ||
1043 | { | ||
1044 | struct ieee80211_hw *hw = sc->hw; | ||
1045 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1046 | |||
1047 | DPRINTF(sc, ATH_DBG_XMIT, | ||
1048 | "%s: TX complete: skb: %p\n", __func__, skb); | ||
1049 | |||
1050 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || | ||
1051 | tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | ||
1052 | /* free driver's private data area of tx_info */ | ||
1053 | if (tx_info->driver_data[0] != NULL) | ||
1054 | kfree(tx_info->driver_data[0]); | ||
1055 | tx_info->driver_data[0] = NULL; | ||
1056 | } | ||
1057 | |||
1058 | if (tx_status->flags & ATH_TX_BAR) { | ||
1059 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
1060 | tx_status->flags &= ~ATH_TX_BAR; | ||
1061 | } | ||
1062 | if (tx_status->flags) | ||
1063 | tx_info->status.excessive_retries = 1; | ||
1064 | |||
1065 | tx_info->status.retry_count = tx_status->retries; | ||
1066 | |||
1067 | ieee80211_tx_status(hw, skb); | ||
1068 | if (an) | ||
1069 | ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE); | ||
1070 | } | ||
1071 | |||
1072 | int ath__rx_indicate(struct ath_softc *sc, | ||
1073 | struct sk_buff *skb, | ||
1074 | struct ath_recv_status *status, | ||
1075 | u16 keyix) | ||
1076 | { | ||
1077 | struct ieee80211_hw *hw = sc->hw; | ||
1078 | struct ath_node *an = NULL; | ||
1079 | struct ieee80211_rx_status rx_status; | ||
1080 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1081 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
1082 | int padsize; | ||
1083 | enum ATH_RX_TYPE st; | ||
1084 | |||
1085 | /* see if any padding is done by the hw and remove it */ | ||
1086 | if (hdrlen & 3) { | ||
1087 | padsize = hdrlen % 4; | ||
1088 | memmove(skb->data + padsize, skb->data, hdrlen); | ||
1089 | skb_pull(skb, padsize); | ||
1090 | } | ||
1091 | |||
1092 | /* remove FCS before passing up to protocol stack */ | ||
1093 | skb_trim(skb, (skb->len - FCS_LEN)); | ||
1094 | |||
1095 | /* Prepare rx status */ | ||
1096 | ath9k_rx_prepare(sc, skb, status, &rx_status); | ||
1097 | |||
1098 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && | ||
1099 | !(status->flags & ATH_RX_DECRYPT_ERROR)) { | ||
1100 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
1101 | } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) | ||
1102 | && !(status->flags & ATH_RX_DECRYPT_ERROR) | ||
1103 | && skb->len >= hdrlen + 4) { | ||
1104 | keyix = skb->data[hdrlen + 3] >> 6; | ||
1105 | |||
1106 | if (test_bit(keyix, sc->sc_keymap)) | ||
1107 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
1108 | } | ||
1109 | |||
1110 | spin_lock_bh(&sc->node_lock); | ||
1111 | an = ath_node_find(sc, hdr->addr2); | ||
1112 | spin_unlock_bh(&sc->node_lock); | ||
1113 | |||
1114 | if (an) { | ||
1115 | ath_rx_input(sc, an, | ||
1116 | hw->conf.ht_conf.ht_supported, | ||
1117 | skb, status, &st); | ||
1118 | } | ||
1119 | if (!an || (st != ATH_RX_CONSUMED)) | ||
1120 | __ieee80211_rx(hw, skb, &rx_status); | ||
1121 | |||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | int ath_rx_subframe(struct ath_node *an, | ||
1126 | struct sk_buff *skb, | ||
1127 | struct ath_recv_status *status) | ||
1128 | { | ||
1129 | struct ath_softc *sc = an->an_sc; | ||
1130 | struct ieee80211_hw *hw = sc->hw; | ||
1131 | struct ieee80211_rx_status rx_status; | ||
1132 | |||
1133 | /* Prepare rx status */ | ||
1134 | ath9k_rx_prepare(sc, skb, status, &rx_status); | ||
1135 | if (!(status->flags & ATH_RX_DECRYPT_ERROR)) | ||
1136 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
1137 | |||
1138 | __ieee80211_rx(hw, skb, &rx_status); | ||
1139 | |||
1140 | return 0; | ||
1141 | } | ||
1142 | |||
1143 | enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc) | ||
1144 | { | ||
1145 | return sc->sc_ht_info.tx_chan_width; | ||
1146 | } | ||
1147 | |||
1148 | void ath_setup_rate(struct ath_softc *sc, | ||
1149 | enum wireless_mode wMode, | ||
1150 | enum RATE_TYPE type, | ||
1151 | const struct ath9k_rate_table *rt) | ||
1152 | { | ||
1153 | int i, maxrates, a = 0, b = 0; | ||
1154 | struct ieee80211_supported_band *band_2ghz; | ||
1155 | struct ieee80211_supported_band *band_5ghz; | ||
1156 | struct ieee80211_rate *rates_2ghz; | ||
1157 | struct ieee80211_rate *rates_5ghz; | ||
1158 | |||
1159 | if ((wMode >= WIRELESS_MODE_MAX) || (type != NORMAL_RATE)) | ||
1160 | return; | ||
1161 | |||
1162 | band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
1163 | band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
1164 | rates_2ghz = sc->rates[IEEE80211_BAND_2GHZ]; | ||
1165 | rates_5ghz = sc->rates[IEEE80211_BAND_5GHZ]; | ||
1166 | |||
1167 | if (rt->rateCount > ATH_RATE_MAX) | ||
1168 | maxrates = ATH_RATE_MAX; | ||
1169 | else | ||
1170 | maxrates = rt->rateCount; | ||
1171 | |||
1172 | if ((band_2ghz->n_bitrates != 0) && (band_5ghz->n_bitrates != 0)) { | ||
1173 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
1174 | "%s: Rates already setup\n", __func__); | ||
1175 | return; | ||
1176 | } | ||
1177 | |||
1178 | for (i = 0; i < maxrates; i++) { | ||
1179 | switch (wMode) { | ||
1180 | case WIRELESS_MODE_11b: | ||
1181 | case WIRELESS_MODE_11g: | ||
1182 | rates_2ghz[a].bitrate = rt->info[i].rateKbps / 100; | ||
1183 | rates_2ghz[a].hw_value = rt->info[i].rateCode; | ||
1184 | a++; | ||
1185 | band_2ghz->n_bitrates = a; | ||
1186 | break; | ||
1187 | case WIRELESS_MODE_11a: | ||
1188 | rates_5ghz[b].bitrate = rt->info[i].rateKbps / 100; | ||
1189 | rates_5ghz[b].hw_value = rt->info[i].rateCode; | ||
1190 | b++; | ||
1191 | band_5ghz->n_bitrates = b; | ||
1192 | break; | ||
1193 | default: | ||
1194 | break; | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | if (band_2ghz->n_bitrates) { | ||
1199 | for (i = 0; i < band_2ghz->n_bitrates; i++) { | ||
1200 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
1201 | "%s: 2GHz Rate: %2dMbps, ratecode: %2d\n", | ||
1202 | __func__, | ||
1203 | rates_2ghz[i].bitrate / 10, | ||
1204 | rates_2ghz[i].hw_value); | ||
1205 | } | ||
1206 | } else if (band_5ghz->n_bitrates) { | ||
1207 | for (i = 0; i < band_5ghz->n_bitrates; i++) { | ||
1208 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
1209 | "%s: 5Ghz Rate: %2dMbps, ratecode: %2d\n", | ||
1210 | __func__, | ||
1211 | rates_5ghz[i].bitrate / 10, | ||
1212 | rates_5ghz[i].hw_value); | ||
1213 | } | ||
1214 | } | ||
1215 | } | ||
1216 | |||
1217 | static int ath_detach(struct ath_softc *sc) | ||
1218 | { | ||
1219 | struct ieee80211_hw *hw = sc->hw; | ||
1220 | |||
1221 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); | ||
1222 | |||
1223 | /* Unregister hw */ | ||
1224 | |||
1225 | ieee80211_unregister_hw(hw); | ||
1226 | |||
1227 | /* unregister Rate control */ | ||
1228 | ath_rate_control_unregister(); | ||
1229 | |||
1230 | /* tx/rx cleanup */ | ||
1231 | |||
1232 | ath_rx_cleanup(sc); | ||
1233 | ath_tx_cleanup(sc); | ||
1234 | |||
1235 | /* Deinit */ | ||
1236 | |||
1237 | ath_deinit(sc); | ||
1238 | |||
1239 | return 0; | ||
1240 | } | ||
1241 | |||
1242 | static int ath_attach(u16 devid, | ||
1243 | struct ath_softc *sc) | ||
1244 | { | ||
1245 | struct ieee80211_hw *hw = sc->hw; | ||
1246 | int error = 0; | ||
1247 | |||
1248 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__); | ||
1249 | |||
1250 | error = ath_init(devid, sc); | ||
1251 | if (error != 0) | ||
1252 | return error; | ||
1253 | |||
1254 | /* Init nodes */ | ||
1255 | |||
1256 | INIT_LIST_HEAD(&sc->node_list); | ||
1257 | spin_lock_init(&sc->node_lock); | ||
1258 | |||
1259 | /* get mac address from hardware and set in mac80211 */ | ||
1260 | |||
1261 | SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); | ||
1262 | |||
1263 | /* setup channels and rates */ | ||
1264 | |||
1265 | sc->sbands[IEEE80211_BAND_2GHZ].channels = | ||
1266 | sc->channels[IEEE80211_BAND_2GHZ]; | ||
1267 | sc->sbands[IEEE80211_BAND_2GHZ].bitrates = | ||
1268 | sc->rates[IEEE80211_BAND_2GHZ]; | ||
1269 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | ||
1270 | |||
1271 | if (sc->sc_ah->ah_caps.halHTSupport) | ||
1272 | /* Setup HT capabilities for 2.4Ghz*/ | ||
1273 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info); | ||
1274 | |||
1275 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
1276 | &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
1277 | |||
1278 | if (sc->sc_ah->ah_caps.halWirelessModes & ATH9K_MODE_SEL_11A) { | ||
1279 | sc->sbands[IEEE80211_BAND_5GHZ].channels = | ||
1280 | sc->channels[IEEE80211_BAND_5GHZ]; | ||
1281 | sc->sbands[IEEE80211_BAND_5GHZ].bitrates = | ||
1282 | sc->rates[IEEE80211_BAND_5GHZ]; | ||
1283 | sc->sbands[IEEE80211_BAND_5GHZ].band = | ||
1284 | IEEE80211_BAND_5GHZ; | ||
1285 | |||
1286 | if (sc->sc_ah->ah_caps.halHTSupport) | ||
1287 | /* Setup HT capabilities for 5Ghz*/ | ||
1288 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info); | ||
1289 | |||
1290 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
1291 | &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
1292 | } | ||
1293 | |||
1294 | /* FIXME: Have to figure out proper hw init values later */ | ||
1295 | |||
1296 | hw->queues = 4; | ||
1297 | hw->ampdu_queues = 1; | ||
1298 | |||
1299 | /* Register rate control */ | ||
1300 | hw->rate_control_algorithm = "ath9k_rate_control"; | ||
1301 | error = ath_rate_control_register(); | ||
1302 | if (error != 0) { | ||
1303 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1304 | "%s: Unable to register rate control " | ||
1305 | "algorithm:%d\n", __func__, error); | ||
1306 | ath_rate_control_unregister(); | ||
1307 | goto bad; | ||
1308 | } | ||
1309 | |||
1310 | error = ieee80211_register_hw(hw); | ||
1311 | if (error != 0) { | ||
1312 | ath_rate_control_unregister(); | ||
1313 | goto bad; | ||
1314 | } | ||
1315 | |||
1316 | /* initialize tx/rx engine */ | ||
1317 | |||
1318 | error = ath_tx_init(sc, ATH_TXBUF); | ||
1319 | if (error != 0) | ||
1320 | goto bad1; | ||
1321 | |||
1322 | error = ath_rx_init(sc, ATH_RXBUF); | ||
1323 | if (error != 0) | ||
1324 | goto bad1; | ||
1325 | |||
1326 | return 0; | ||
1327 | bad1: | ||
1328 | ath_detach(sc); | ||
1329 | bad: | ||
1330 | return error; | ||
1331 | } | ||
1332 | |||
1333 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
1334 | { | ||
1335 | void __iomem *mem; | ||
1336 | struct ath_softc *sc; | ||
1337 | struct ieee80211_hw *hw; | ||
1338 | const char *athname; | ||
1339 | u8 csz; | ||
1340 | u32 val; | ||
1341 | int ret = 0; | ||
1342 | |||
1343 | if (pci_enable_device(pdev)) | ||
1344 | return -EIO; | ||
1345 | |||
1346 | /* XXX 32-bit addressing only */ | ||
1347 | if (pci_set_dma_mask(pdev, 0xffffffff)) { | ||
1348 | printk(KERN_ERR "ath_pci: 32-bit DMA not available\n"); | ||
1349 | ret = -ENODEV; | ||
1350 | goto bad; | ||
1351 | } | ||
1352 | |||
1353 | /* | ||
1354 | * Cache line size is used to size and align various | ||
1355 | * structures used to communicate with the hardware. | ||
1356 | */ | ||
1357 | pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); | ||
1358 | if (csz == 0) { | ||
1359 | /* | ||
1360 | * Linux 2.4.18 (at least) writes the cache line size | ||
1361 | * register as a 16-bit wide register which is wrong. | ||
1362 | * We must have this setup properly for rx buffer | ||
1363 | * DMA to work so force a reasonable value here if it | ||
1364 | * comes up zero. | ||
1365 | */ | ||
1366 | csz = L1_CACHE_BYTES / sizeof(u32); | ||
1367 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | ||
1368 | } | ||
1369 | /* | ||
1370 | * The default setting of latency timer yields poor results, | ||
1371 | * set it to the value used by other systems. It may be worth | ||
1372 | * tweaking this setting more. | ||
1373 | */ | ||
1374 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); | ||
1375 | |||
1376 | pci_set_master(pdev); | ||
1377 | |||
1378 | /* | ||
1379 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
1380 | * PCI Tx retries from interfering with C3 CPU state. | ||
1381 | */ | ||
1382 | pci_read_config_dword(pdev, 0x40, &val); | ||
1383 | if ((val & 0x0000ff00) != 0) | ||
1384 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | ||
1385 | |||
1386 | ret = pci_request_region(pdev, 0, "ath9k"); | ||
1387 | if (ret) { | ||
1388 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); | ||
1389 | ret = -ENODEV; | ||
1390 | goto bad; | ||
1391 | } | ||
1392 | |||
1393 | mem = pci_iomap(pdev, 0, 0); | ||
1394 | if (!mem) { | ||
1395 | printk(KERN_ERR "PCI memory map error\n") ; | ||
1396 | ret = -EIO; | ||
1397 | goto bad1; | ||
1398 | } | ||
1399 | |||
1400 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); | ||
1401 | if (hw == NULL) { | ||
1402 | printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n"); | ||
1403 | goto bad2; | ||
1404 | } | ||
1405 | |||
1406 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
1407 | IEEE80211_HW_NOISE_DBM; | ||
1408 | |||
1409 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
1410 | pci_set_drvdata(pdev, hw); | ||
1411 | |||
1412 | sc = hw->priv; | ||
1413 | sc->hw = hw; | ||
1414 | sc->pdev = pdev; | ||
1415 | sc->mem = mem; | ||
1416 | |||
1417 | if (ath_attach(id->device, sc) != 0) { | ||
1418 | ret = -ENODEV; | ||
1419 | goto bad3; | ||
1420 | } | ||
1421 | |||
1422 | /* setup interrupt service routine */ | ||
1423 | |||
1424 | if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) { | ||
1425 | printk(KERN_ERR "%s: request_irq failed\n", | ||
1426 | wiphy_name(hw->wiphy)); | ||
1427 | ret = -EIO; | ||
1428 | goto bad4; | ||
1429 | } | ||
1430 | |||
1431 | athname = ath9k_hw_probe(id->vendor, id->device); | ||
1432 | |||
1433 | printk(KERN_INFO "%s: %s: mem=0x%lx, irq=%d\n", | ||
1434 | wiphy_name(hw->wiphy), | ||
1435 | athname ? athname : "Atheros ???", | ||
1436 | (unsigned long)mem, pdev->irq); | ||
1437 | |||
1438 | return 0; | ||
1439 | bad4: | ||
1440 | ath_detach(sc); | ||
1441 | bad3: | ||
1442 | ieee80211_free_hw(hw); | ||
1443 | bad2: | ||
1444 | pci_iounmap(pdev, mem); | ||
1445 | bad1: | ||
1446 | pci_release_region(pdev, 0); | ||
1447 | bad: | ||
1448 | pci_disable_device(pdev); | ||
1449 | return ret; | ||
1450 | } | ||
1451 | |||
1452 | static void ath_pci_remove(struct pci_dev *pdev) | ||
1453 | { | ||
1454 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
1455 | struct ath_softc *sc = hw->priv; | ||
1456 | |||
1457 | if (pdev->irq) | ||
1458 | free_irq(pdev->irq, sc); | ||
1459 | ath_detach(sc); | ||
1460 | pci_iounmap(pdev, sc->mem); | ||
1461 | pci_release_region(pdev, 0); | ||
1462 | pci_disable_device(pdev); | ||
1463 | ieee80211_free_hw(hw); | ||
1464 | } | ||
1465 | |||
1466 | #ifdef CONFIG_PM | ||
1467 | |||
1468 | static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1469 | { | ||
1470 | pci_save_state(pdev); | ||
1471 | pci_disable_device(pdev); | ||
1472 | pci_set_power_state(pdev, 3); | ||
1473 | |||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1477 | static int ath_pci_resume(struct pci_dev *pdev) | ||
1478 | { | ||
1479 | u32 val; | ||
1480 | int err; | ||
1481 | |||
1482 | err = pci_enable_device(pdev); | ||
1483 | if (err) | ||
1484 | return err; | ||
1485 | pci_restore_state(pdev); | ||
1486 | /* | ||
1487 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
1488 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
1489 | * PCI Tx retries from interfering with C3 CPU state | ||
1490 | */ | ||
1491 | pci_read_config_dword(pdev, 0x40, &val); | ||
1492 | if ((val & 0x0000ff00) != 0) | ||
1493 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | ||
1494 | |||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | #endif /* CONFIG_PM */ | ||
1499 | |||
1500 | MODULE_DEVICE_TABLE(pci, ath_pci_id_table); | ||
1501 | |||
1502 | static struct pci_driver ath_pci_driver = { | ||
1503 | .name = "ath9k", | ||
1504 | .id_table = ath_pci_id_table, | ||
1505 | .probe = ath_pci_probe, | ||
1506 | .remove = ath_pci_remove, | ||
1507 | #ifdef CONFIG_PM | ||
1508 | .suspend = ath_pci_suspend, | ||
1509 | .resume = ath_pci_resume, | ||
1510 | #endif /* CONFIG_PM */ | ||
1511 | }; | ||
1512 | |||
1513 | static int __init init_ath_pci(void) | ||
1514 | { | ||
1515 | printk(KERN_INFO "%s: %s\n", dev_info, ATH_PCI_VERSION); | ||
1516 | |||
1517 | if (pci_register_driver(&ath_pci_driver) < 0) { | ||
1518 | printk(KERN_ERR | ||
1519 | "ath_pci: No devices found, driver not installed.\n"); | ||
1520 | pci_unregister_driver(&ath_pci_driver); | ||
1521 | return -ENODEV; | ||
1522 | } | ||
1523 | |||
1524 | return 0; | ||
1525 | } | ||
1526 | module_init(init_ath_pci); | ||
1527 | |||
1528 | static void __exit exit_ath_pci(void) | ||
1529 | { | ||
1530 | pci_unregister_driver(&ath_pci_driver); | ||
1531 | printk(KERN_INFO "%s: driver unloaded\n", dev_info); | ||
1532 | } | ||
1533 | module_exit(exit_ath_pci); | ||
diff --git a/drivers/net/wireless/ath9k/phy.c b/drivers/net/wireless/ath9k/phy.c new file mode 100644 index 00000000000..eb9121fdfd3 --- /dev/null +++ b/drivers/net/wireless/ath9k/phy.c | |||
@@ -0,0 +1,436 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "core.h" | ||
18 | #include "hw.h" | ||
19 | #include "reg.h" | ||
20 | #include "phy.h" | ||
21 | |||
22 | void | ||
23 | ath9k_hw_write_regs(struct ath_hal *ah, u32 modesIndex, u32 freqIndex, | ||
24 | int regWrites) | ||
25 | { | ||
26 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
27 | |||
28 | REG_WRITE_ARRAY(&ahp->ah_iniBB_RfGain, freqIndex, regWrites); | ||
29 | } | ||
30 | |||
31 | bool | ||
32 | ath9k_hw_set_channel(struct ath_hal *ah, struct ath9k_channel *chan) | ||
33 | { | ||
34 | u32 channelSel = 0; | ||
35 | u32 bModeSynth = 0; | ||
36 | u32 aModeRefSel = 0; | ||
37 | u32 reg32 = 0; | ||
38 | u16 freq; | ||
39 | struct chan_centers centers; | ||
40 | |||
41 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
42 | freq = centers.synth_center; | ||
43 | |||
44 | if (freq < 4800) { | ||
45 | u32 txctl; | ||
46 | |||
47 | if (((freq - 2192) % 5) == 0) { | ||
48 | channelSel = ((freq - 672) * 2 - 3040) / 10; | ||
49 | bModeSynth = 0; | ||
50 | } else if (((freq - 2224) % 5) == 0) { | ||
51 | channelSel = ((freq - 704) * 2 - 3040) / 10; | ||
52 | bModeSynth = 1; | ||
53 | } else { | ||
54 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
55 | "%s: invalid channel %u MHz\n", __func__, | ||
56 | freq); | ||
57 | return false; | ||
58 | } | ||
59 | |||
60 | channelSel = (channelSel << 2) & 0xff; | ||
61 | channelSel = ath9k_hw_reverse_bits(channelSel, 8); | ||
62 | |||
63 | txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); | ||
64 | if (freq == 2484) { | ||
65 | |||
66 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | ||
67 | txctl | AR_PHY_CCK_TX_CTRL_JAPAN); | ||
68 | } else { | ||
69 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | ||
70 | txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); | ||
71 | } | ||
72 | |||
73 | } else if ((freq % 20) == 0 && freq >= 5120) { | ||
74 | channelSel = | ||
75 | ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); | ||
76 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); | ||
77 | } else if ((freq % 10) == 0) { | ||
78 | channelSel = | ||
79 | ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); | ||
80 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) | ||
81 | aModeRefSel = ath9k_hw_reverse_bits(2, 2); | ||
82 | else | ||
83 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); | ||
84 | } else if ((freq % 5) == 0) { | ||
85 | channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); | ||
86 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); | ||
87 | } else { | ||
88 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
89 | "%s: invalid channel %u MHz\n", __func__, freq); | ||
90 | return false; | ||
91 | } | ||
92 | |||
93 | reg32 = | ||
94 | (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | | ||
95 | (1 << 5) | 0x1; | ||
96 | |||
97 | REG_WRITE(ah, AR_PHY(0x37), reg32); | ||
98 | |||
99 | ah->ah_curchan = chan; | ||
100 | |||
101 | AH5416(ah)->ah_curchanRadIndex = -1; | ||
102 | |||
103 | return true; | ||
104 | } | ||
105 | |||
106 | bool | ||
107 | ath9k_hw_ar9280_set_channel(struct ath_hal *ah, | ||
108 | struct ath9k_channel *chan) | ||
109 | { | ||
110 | u16 bMode, fracMode, aModeRefSel = 0; | ||
111 | u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; | ||
112 | struct chan_centers centers; | ||
113 | u32 refDivA = 24; | ||
114 | |||
115 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
116 | freq = centers.synth_center; | ||
117 | |||
118 | reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); | ||
119 | reg32 &= 0xc0000000; | ||
120 | |||
121 | if (freq < 4800) { | ||
122 | u32 txctl; | ||
123 | |||
124 | bMode = 1; | ||
125 | fracMode = 1; | ||
126 | aModeRefSel = 0; | ||
127 | channelSel = (freq * 0x10000) / 15; | ||
128 | |||
129 | txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); | ||
130 | if (freq == 2484) { | ||
131 | |||
132 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | ||
133 | txctl | AR_PHY_CCK_TX_CTRL_JAPAN); | ||
134 | } else { | ||
135 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | ||
136 | txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); | ||
137 | } | ||
138 | } else { | ||
139 | bMode = 0; | ||
140 | fracMode = 0; | ||
141 | |||
142 | if ((freq % 20) == 0) { | ||
143 | aModeRefSel = 3; | ||
144 | } else if ((freq % 10) == 0) { | ||
145 | aModeRefSel = 2; | ||
146 | } else { | ||
147 | aModeRefSel = 0; | ||
148 | |||
149 | fracMode = 1; | ||
150 | refDivA = 1; | ||
151 | channelSel = (freq * 0x8000) / 15; | ||
152 | |||
153 | REG_RMW_FIELD(ah, AR_AN_SYNTH9, | ||
154 | AR_AN_SYNTH9_REFDIVA, refDivA); | ||
155 | } | ||
156 | if (!fracMode) { | ||
157 | ndiv = (freq * (refDivA >> aModeRefSel)) / 60; | ||
158 | channelSel = ndiv & 0x1ff; | ||
159 | channelFrac = (ndiv & 0xfffffe00) * 2; | ||
160 | channelSel = (channelSel << 17) | channelFrac; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | reg32 = reg32 | | ||
165 | (bMode << 29) | | ||
166 | (fracMode << 28) | (aModeRefSel << 26) | (channelSel); | ||
167 | |||
168 | REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); | ||
169 | |||
170 | ah->ah_curchan = chan; | ||
171 | |||
172 | AH5416(ah)->ah_curchanRadIndex = -1; | ||
173 | |||
174 | return true; | ||
175 | } | ||
176 | |||
177 | static void | ||
178 | ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, | ||
179 | u32 numBits, u32 firstBit, | ||
180 | u32 column) | ||
181 | { | ||
182 | u32 tmp32, mask, arrayEntry, lastBit; | ||
183 | int32_t bitPosition, bitsLeft; | ||
184 | |||
185 | tmp32 = ath9k_hw_reverse_bits(reg32, numBits); | ||
186 | arrayEntry = (firstBit - 1) / 8; | ||
187 | bitPosition = (firstBit - 1) % 8; | ||
188 | bitsLeft = numBits; | ||
189 | while (bitsLeft > 0) { | ||
190 | lastBit = (bitPosition + bitsLeft > 8) ? | ||
191 | 8 : bitPosition + bitsLeft; | ||
192 | mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << | ||
193 | (column * 8); | ||
194 | rfBuf[arrayEntry] &= ~mask; | ||
195 | rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << | ||
196 | (column * 8)) & mask; | ||
197 | bitsLeft -= 8 - bitPosition; | ||
198 | tmp32 = tmp32 >> (8 - bitPosition); | ||
199 | bitPosition = 0; | ||
200 | arrayEntry++; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | bool | ||
205 | ath9k_hw_set_rf_regs(struct ath_hal *ah, struct ath9k_channel *chan, | ||
206 | u16 modesIndex) | ||
207 | { | ||
208 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
209 | |||
210 | u32 eepMinorRev; | ||
211 | u32 ob5GHz = 0, db5GHz = 0; | ||
212 | u32 ob2GHz = 0, db2GHz = 0; | ||
213 | int regWrites = 0; | ||
214 | |||
215 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
216 | return true; | ||
217 | |||
218 | eepMinorRev = ath9k_hw_get_eeprom(ahp, EEP_MINOR_REV); | ||
219 | |||
220 | RF_BANK_SETUP(ahp->ah_analogBank0Data, &ahp->ah_iniBank0, 1); | ||
221 | |||
222 | RF_BANK_SETUP(ahp->ah_analogBank1Data, &ahp->ah_iniBank1, 1); | ||
223 | |||
224 | RF_BANK_SETUP(ahp->ah_analogBank2Data, &ahp->ah_iniBank2, 1); | ||
225 | |||
226 | RF_BANK_SETUP(ahp->ah_analogBank3Data, &ahp->ah_iniBank3, | ||
227 | modesIndex); | ||
228 | { | ||
229 | int i; | ||
230 | for (i = 0; i < ahp->ah_iniBank6TPC.ia_rows; i++) { | ||
231 | ahp->ah_analogBank6Data[i] = | ||
232 | INI_RA(&ahp->ah_iniBank6TPC, i, modesIndex); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | if (eepMinorRev >= 2) { | ||
237 | if (IS_CHAN_2GHZ(chan)) { | ||
238 | ob2GHz = ath9k_hw_get_eeprom(ahp, EEP_OB_2); | ||
239 | db2GHz = ath9k_hw_get_eeprom(ahp, EEP_DB_2); | ||
240 | ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data, | ||
241 | ob2GHz, 3, 197, 0); | ||
242 | ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data, | ||
243 | db2GHz, 3, 194, 0); | ||
244 | } else { | ||
245 | ob5GHz = ath9k_hw_get_eeprom(ahp, EEP_OB_5); | ||
246 | db5GHz = ath9k_hw_get_eeprom(ahp, EEP_DB_5); | ||
247 | ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data, | ||
248 | ob5GHz, 3, 203, 0); | ||
249 | ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data, | ||
250 | db5GHz, 3, 200, 0); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | RF_BANK_SETUP(ahp->ah_analogBank7Data, &ahp->ah_iniBank7, 1); | ||
255 | |||
256 | REG_WRITE_RF_ARRAY(&ahp->ah_iniBank0, ahp->ah_analogBank0Data, | ||
257 | regWrites); | ||
258 | REG_WRITE_RF_ARRAY(&ahp->ah_iniBank1, ahp->ah_analogBank1Data, | ||
259 | regWrites); | ||
260 | REG_WRITE_RF_ARRAY(&ahp->ah_iniBank2, ahp->ah_analogBank2Data, | ||
261 | regWrites); | ||
262 | REG_WRITE_RF_ARRAY(&ahp->ah_iniBank3, ahp->ah_analogBank3Data, | ||
263 | regWrites); | ||
264 | REG_WRITE_RF_ARRAY(&ahp->ah_iniBank6TPC, ahp->ah_analogBank6Data, | ||
265 | regWrites); | ||
266 | REG_WRITE_RF_ARRAY(&ahp->ah_iniBank7, ahp->ah_analogBank7Data, | ||
267 | regWrites); | ||
268 | |||
269 | return true; | ||
270 | } | ||
271 | |||
272 | void | ||
273 | ath9k_hw_rfdetach(struct ath_hal *ah) | ||
274 | { | ||
275 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
276 | |||
277 | if (ahp->ah_analogBank0Data != NULL) { | ||
278 | kfree(ahp->ah_analogBank0Data); | ||
279 | ahp->ah_analogBank0Data = NULL; | ||
280 | } | ||
281 | if (ahp->ah_analogBank1Data != NULL) { | ||
282 | kfree(ahp->ah_analogBank1Data); | ||
283 | ahp->ah_analogBank1Data = NULL; | ||
284 | } | ||
285 | if (ahp->ah_analogBank2Data != NULL) { | ||
286 | kfree(ahp->ah_analogBank2Data); | ||
287 | ahp->ah_analogBank2Data = NULL; | ||
288 | } | ||
289 | if (ahp->ah_analogBank3Data != NULL) { | ||
290 | kfree(ahp->ah_analogBank3Data); | ||
291 | ahp->ah_analogBank3Data = NULL; | ||
292 | } | ||
293 | if (ahp->ah_analogBank6Data != NULL) { | ||
294 | kfree(ahp->ah_analogBank6Data); | ||
295 | ahp->ah_analogBank6Data = NULL; | ||
296 | } | ||
297 | if (ahp->ah_analogBank6TPCData != NULL) { | ||
298 | kfree(ahp->ah_analogBank6TPCData); | ||
299 | ahp->ah_analogBank6TPCData = NULL; | ||
300 | } | ||
301 | if (ahp->ah_analogBank7Data != NULL) { | ||
302 | kfree(ahp->ah_analogBank7Data); | ||
303 | ahp->ah_analogBank7Data = NULL; | ||
304 | } | ||
305 | if (ahp->ah_addac5416_21 != NULL) { | ||
306 | kfree(ahp->ah_addac5416_21); | ||
307 | ahp->ah_addac5416_21 = NULL; | ||
308 | } | ||
309 | if (ahp->ah_bank6Temp != NULL) { | ||
310 | kfree(ahp->ah_bank6Temp); | ||
311 | ahp->ah_bank6Temp = NULL; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | bool ath9k_hw_init_rf(struct ath_hal *ah, int *status) | ||
316 | { | ||
317 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
318 | |||
319 | if (!AR_SREV_9280_10_OR_LATER(ah)) { | ||
320 | |||
321 | ahp->ah_analogBank0Data = | ||
322 | kzalloc((sizeof(u32) * | ||
323 | ahp->ah_iniBank0.ia_rows), GFP_KERNEL); | ||
324 | ahp->ah_analogBank1Data = | ||
325 | kzalloc((sizeof(u32) * | ||
326 | ahp->ah_iniBank1.ia_rows), GFP_KERNEL); | ||
327 | ahp->ah_analogBank2Data = | ||
328 | kzalloc((sizeof(u32) * | ||
329 | ahp->ah_iniBank2.ia_rows), GFP_KERNEL); | ||
330 | ahp->ah_analogBank3Data = | ||
331 | kzalloc((sizeof(u32) * | ||
332 | ahp->ah_iniBank3.ia_rows), GFP_KERNEL); | ||
333 | ahp->ah_analogBank6Data = | ||
334 | kzalloc((sizeof(u32) * | ||
335 | ahp->ah_iniBank6.ia_rows), GFP_KERNEL); | ||
336 | ahp->ah_analogBank6TPCData = | ||
337 | kzalloc((sizeof(u32) * | ||
338 | ahp->ah_iniBank6TPC.ia_rows), GFP_KERNEL); | ||
339 | ahp->ah_analogBank7Data = | ||
340 | kzalloc((sizeof(u32) * | ||
341 | ahp->ah_iniBank7.ia_rows), GFP_KERNEL); | ||
342 | |||
343 | if (ahp->ah_analogBank0Data == NULL | ||
344 | || ahp->ah_analogBank1Data == NULL | ||
345 | || ahp->ah_analogBank2Data == NULL | ||
346 | || ahp->ah_analogBank3Data == NULL | ||
347 | || ahp->ah_analogBank6Data == NULL | ||
348 | || ahp->ah_analogBank6TPCData == NULL | ||
349 | || ahp->ah_analogBank7Data == NULL) { | ||
350 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
351 | "%s: cannot allocate RF banks\n", | ||
352 | __func__); | ||
353 | *status = -ENOMEM; | ||
354 | return false; | ||
355 | } | ||
356 | |||
357 | ahp->ah_addac5416_21 = | ||
358 | kzalloc((sizeof(u32) * | ||
359 | ahp->ah_iniAddac.ia_rows * | ||
360 | ahp->ah_iniAddac.ia_columns), GFP_KERNEL); | ||
361 | if (ahp->ah_addac5416_21 == NULL) { | ||
362 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
363 | "%s: cannot allocate ah_addac5416_21\n", | ||
364 | __func__); | ||
365 | *status = -ENOMEM; | ||
366 | return false; | ||
367 | } | ||
368 | |||
369 | ahp->ah_bank6Temp = | ||
370 | kzalloc((sizeof(u32) * | ||
371 | ahp->ah_iniBank6.ia_rows), GFP_KERNEL); | ||
372 | if (ahp->ah_bank6Temp == NULL) { | ||
373 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
374 | "%s: cannot allocate ah_bank6Temp\n", | ||
375 | __func__); | ||
376 | *status = -ENOMEM; | ||
377 | return false; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | return true; | ||
382 | } | ||
383 | |||
384 | void | ||
385 | ath9k_hw_decrease_chain_power(struct ath_hal *ah, struct ath9k_channel *chan) | ||
386 | { | ||
387 | int i, regWrites = 0; | ||
388 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
389 | u32 bank6SelMask; | ||
390 | u32 *bank6Temp = ahp->ah_bank6Temp; | ||
391 | |||
392 | switch (ahp->ah_diversityControl) { | ||
393 | case ATH9K_ANT_FIXED_A: | ||
394 | bank6SelMask = | ||
395 | (ahp-> | ||
396 | ah_antennaSwitchSwap & ANTSWAP_AB) ? REDUCE_CHAIN_0 : | ||
397 | REDUCE_CHAIN_1; | ||
398 | break; | ||
399 | case ATH9K_ANT_FIXED_B: | ||
400 | bank6SelMask = | ||
401 | (ahp-> | ||
402 | ah_antennaSwitchSwap & ANTSWAP_AB) ? REDUCE_CHAIN_1 : | ||
403 | REDUCE_CHAIN_0; | ||
404 | break; | ||
405 | case ATH9K_ANT_VARIABLE: | ||
406 | return; | ||
407 | break; | ||
408 | default: | ||
409 | return; | ||
410 | break; | ||
411 | } | ||
412 | |||
413 | for (i = 0; i < ahp->ah_iniBank6.ia_rows; i++) | ||
414 | bank6Temp[i] = ahp->ah_analogBank6Data[i]; | ||
415 | |||
416 | REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); | ||
417 | |||
418 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); | ||
419 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); | ||
420 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); | ||
421 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); | ||
422 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); | ||
423 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); | ||
424 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); | ||
425 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); | ||
426 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); | ||
427 | |||
428 | REG_WRITE_RF_ARRAY(&ahp->ah_iniBank6, bank6Temp, regWrites); | ||
429 | |||
430 | REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); | ||
431 | #ifdef ALTER_SWITCH | ||
432 | REG_WRITE(ah, PHY_SWITCH_CHAIN_0, | ||
433 | (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) | ||
434 | | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); | ||
435 | #endif | ||
436 | } | ||
diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h new file mode 100644 index 00000000000..0cd399a5344 --- /dev/null +++ b/drivers/net/wireless/ath9k/phy.h | |||
@@ -0,0 +1,543 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef PHY_H | ||
18 | #define PHY_H | ||
19 | |||
20 | bool ath9k_hw_ar9280_set_channel(struct ath_hal *ah, | ||
21 | struct ath9k_channel | ||
22 | *chan); | ||
23 | bool ath9k_hw_set_channel(struct ath_hal *ah, | ||
24 | struct ath9k_channel *chan); | ||
25 | void ath9k_hw_write_regs(struct ath_hal *ah, u32 modesIndex, | ||
26 | u32 freqIndex, int regWrites); | ||
27 | bool ath9k_hw_set_rf_regs(struct ath_hal *ah, | ||
28 | struct ath9k_channel *chan, | ||
29 | u16 modesIndex); | ||
30 | void ath9k_hw_decrease_chain_power(struct ath_hal *ah, | ||
31 | struct ath9k_channel *chan); | ||
32 | bool ath9k_hw_init_rf(struct ath_hal *ah, | ||
33 | int *status); | ||
34 | |||
35 | #define AR_PHY_BASE 0x9800 | ||
36 | #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) | ||
37 | |||
38 | #define AR_PHY_TEST 0x9800 | ||
39 | #define PHY_AGC_CLR 0x10000000 | ||
40 | #define RFSILENT_BB 0x00002000 | ||
41 | |||
42 | #define AR_PHY_TURBO 0x9804 | ||
43 | #define AR_PHY_FC_TURBO_MODE 0x00000001 | ||
44 | #define AR_PHY_FC_TURBO_SHORT 0x00000002 | ||
45 | #define AR_PHY_FC_DYN2040_EN 0x00000004 | ||
46 | #define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 | ||
47 | #define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 | ||
48 | #define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 | ||
49 | #define AR_PHY_FC_HT_EN 0x00000040 | ||
50 | #define AR_PHY_FC_SHORT_GI_40 0x00000080 | ||
51 | #define AR_PHY_FC_WALSH 0x00000100 | ||
52 | #define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200 | ||
53 | |||
54 | #define AR_PHY_TIMING2 0x9810 | ||
55 | #define AR_PHY_TIMING3 0x9814 | ||
56 | #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 | ||
57 | #define AR_PHY_TIMING3_DSC_MAN_S 17 | ||
58 | #define AR_PHY_TIMING3_DSC_EXP 0x0001E000 | ||
59 | #define AR_PHY_TIMING3_DSC_EXP_S 13 | ||
60 | |||
61 | #define AR_PHY_CHIP_ID 0x9818 | ||
62 | #define AR_PHY_CHIP_ID_REV_0 0x80 | ||
63 | #define AR_PHY_CHIP_ID_REV_1 0x81 | ||
64 | #define AR_PHY_CHIP_ID_9160_REV_0 0xb0 | ||
65 | |||
66 | #define AR_PHY_ACTIVE 0x981C | ||
67 | #define AR_PHY_ACTIVE_EN 0x00000001 | ||
68 | #define AR_PHY_ACTIVE_DIS 0x00000000 | ||
69 | |||
70 | #define AR_PHY_RF_CTL2 0x9824 | ||
71 | #define AR_PHY_TX_END_DATA_START 0x000000FF | ||
72 | #define AR_PHY_TX_END_DATA_START_S 0 | ||
73 | #define AR_PHY_TX_END_PA_ON 0x0000FF00 | ||
74 | #define AR_PHY_TX_END_PA_ON_S 8 | ||
75 | |||
76 | #define AR_PHY_RF_CTL3 0x9828 | ||
77 | #define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 | ||
78 | #define AR_PHY_TX_END_TO_A2_RX_ON_S 16 | ||
79 | |||
80 | #define AR_PHY_ADC_CTL 0x982C | ||
81 | #define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 | ||
82 | #define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 | ||
83 | #define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 | ||
84 | #define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 | ||
85 | #define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000 | ||
86 | #define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 | ||
87 | #define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16 | ||
88 | |||
89 | #define AR_PHY_ADC_SERIAL_CTL 0x9830 | ||
90 | #define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000 | ||
91 | #define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001 | ||
92 | |||
93 | #define AR_PHY_RF_CTL4 0x9834 | ||
94 | #define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000 | ||
95 | #define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 | ||
96 | #define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000 | ||
97 | #define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 | ||
98 | #define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00 | ||
99 | #define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 | ||
100 | #define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF | ||
101 | #define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 | ||
102 | |||
103 | #define AR_PHY_SETTLING 0x9844 | ||
104 | #define AR_PHY_SETTLING_SWITCH 0x00003F80 | ||
105 | #define AR_PHY_SETTLING_SWITCH_S 7 | ||
106 | |||
107 | #define AR_PHY_RXGAIN 0x9848 | ||
108 | #define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000 | ||
109 | #define AR_PHY_RXGAIN_TXRX_ATTEN_S 12 | ||
110 | #define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000 | ||
111 | #define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 | ||
112 | #define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80 | ||
113 | #define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7 | ||
114 | #define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000 | ||
115 | #define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 | ||
116 | |||
117 | #define AR_PHY_DESIRED_SZ 0x9850 | ||
118 | #define AR_PHY_DESIRED_SZ_ADC 0x000000FF | ||
119 | #define AR_PHY_DESIRED_SZ_ADC_S 0 | ||
120 | #define AR_PHY_DESIRED_SZ_PGA 0x0000FF00 | ||
121 | #define AR_PHY_DESIRED_SZ_PGA_S 8 | ||
122 | #define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000 | ||
123 | #define AR_PHY_DESIRED_SZ_TOT_DES_S 20 | ||
124 | |||
125 | #define AR_PHY_FIND_SIG 0x9858 | ||
126 | #define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000 | ||
127 | #define AR_PHY_FIND_SIG_FIRSTEP_S 12 | ||
128 | #define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 | ||
129 | #define AR_PHY_FIND_SIG_FIRPWR_S 18 | ||
130 | |||
131 | #define AR_PHY_AGC_CTL1 0x985C | ||
132 | #define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 | ||
133 | #define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 | ||
134 | #define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000 | ||
135 | #define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15 | ||
136 | |||
137 | #define AR_PHY_AGC_CONTROL 0x9860 | ||
138 | #define AR_PHY_AGC_CONTROL_CAL 0x00000001 | ||
139 | #define AR_PHY_AGC_CONTROL_NF 0x00000002 | ||
140 | #define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 | ||
141 | #define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 | ||
142 | #define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 | ||
143 | |||
144 | #define AR_PHY_CCA 0x9864 | ||
145 | #define AR_PHY_MINCCA_PWR 0x0FF80000 | ||
146 | #define AR_PHY_MINCCA_PWR_S 19 | ||
147 | #define AR_PHY_CCA_THRESH62 0x0007F000 | ||
148 | #define AR_PHY_CCA_THRESH62_S 12 | ||
149 | #define AR9280_PHY_MINCCA_PWR 0x1FF00000 | ||
150 | #define AR9280_PHY_MINCCA_PWR_S 20 | ||
151 | #define AR9280_PHY_CCA_THRESH62 0x000FF000 | ||
152 | #define AR9280_PHY_CCA_THRESH62_S 12 | ||
153 | |||
154 | #define AR_PHY_SFCORR_LOW 0x986C | ||
155 | #define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 | ||
156 | #define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00 | ||
157 | #define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 | ||
158 | #define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000 | ||
159 | #define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 | ||
160 | #define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000 | ||
161 | #define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 | ||
162 | |||
163 | #define AR_PHY_SFCORR 0x9868 | ||
164 | #define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F | ||
165 | #define AR_PHY_SFCORR_M2COUNT_THR_S 0 | ||
166 | #define AR_PHY_SFCORR_M1_THRESH 0x00FE0000 | ||
167 | #define AR_PHY_SFCORR_M1_THRESH_S 17 | ||
168 | #define AR_PHY_SFCORR_M2_THRESH 0x7F000000 | ||
169 | #define AR_PHY_SFCORR_M2_THRESH_S 24 | ||
170 | |||
171 | #define AR_PHY_SLEEP_CTR_CONTROL 0x9870 | ||
172 | #define AR_PHY_SLEEP_CTR_LIMIT 0x9874 | ||
173 | #define AR_PHY_SYNTH_CONTROL 0x9874 | ||
174 | #define AR_PHY_SLEEP_SCAL 0x9878 | ||
175 | |||
176 | #define AR_PHY_PLL_CTL 0x987c | ||
177 | #define AR_PHY_PLL_CTL_40 0xaa | ||
178 | #define AR_PHY_PLL_CTL_40_5413 0x04 | ||
179 | #define AR_PHY_PLL_CTL_44 0xab | ||
180 | #define AR_PHY_PLL_CTL_44_2133 0xeb | ||
181 | #define AR_PHY_PLL_CTL_40_2133 0xea | ||
182 | |||
183 | #define AR_PHY_RX_DELAY 0x9914 | ||
184 | #define AR_PHY_SEARCH_START_DELAY 0x9918 | ||
185 | #define AR_PHY_RX_DELAY_DELAY 0x00003FFF | ||
186 | |||
187 | #define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12)) | ||
188 | #define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F | ||
189 | #define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 | ||
190 | #define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 | ||
191 | #define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 | ||
192 | #define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 | ||
193 | #define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 | ||
194 | #define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 | ||
195 | #define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000 | ||
196 | |||
197 | #define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 | ||
198 | #define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 | ||
199 | #define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 | ||
200 | #define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 | ||
201 | |||
202 | #define AR_PHY_TIMING5 0x9924 | ||
203 | #define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE | ||
204 | #define AR_PHY_TIMING5_CYCPWR_THR1_S 1 | ||
205 | |||
206 | #define AR_PHY_POWER_TX_RATE1 0x9934 | ||
207 | #define AR_PHY_POWER_TX_RATE2 0x9938 | ||
208 | #define AR_PHY_POWER_TX_RATE_MAX 0x993c | ||
209 | #define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 | ||
210 | |||
211 | #define AR_PHY_FRAME_CTL 0x9944 | ||
212 | #define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 | ||
213 | #define AR_PHY_FRAME_CTL_TX_CLIP_S 3 | ||
214 | |||
215 | #define AR_PHY_TXPWRADJ 0x994C | ||
216 | #define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0 | ||
217 | #define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6 | ||
218 | #define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000 | ||
219 | #define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 | ||
220 | |||
221 | #define AR_PHY_RADAR_EXT 0x9940 | ||
222 | #define AR_PHY_RADAR_EXT_ENA 0x00004000 | ||
223 | |||
224 | #define AR_PHY_RADAR_0 0x9954 | ||
225 | #define AR_PHY_RADAR_0_ENA 0x00000001 | ||
226 | #define AR_PHY_RADAR_0_FFT_ENA 0x80000000 | ||
227 | #define AR_PHY_RADAR_0_INBAND 0x0000003e | ||
228 | #define AR_PHY_RADAR_0_INBAND_S 1 | ||
229 | #define AR_PHY_RADAR_0_PRSSI 0x00000FC0 | ||
230 | #define AR_PHY_RADAR_0_PRSSI_S 6 | ||
231 | #define AR_PHY_RADAR_0_HEIGHT 0x0003F000 | ||
232 | #define AR_PHY_RADAR_0_HEIGHT_S 12 | ||
233 | #define AR_PHY_RADAR_0_RRSSI 0x00FC0000 | ||
234 | #define AR_PHY_RADAR_0_RRSSI_S 18 | ||
235 | #define AR_PHY_RADAR_0_FIRPWR 0x7F000000 | ||
236 | #define AR_PHY_RADAR_0_FIRPWR_S 24 | ||
237 | |||
238 | #define AR_PHY_RADAR_1 0x9958 | ||
239 | #define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000 | ||
240 | #define AR_PHY_RADAR_1_USE_FIR128 0x00400000 | ||
241 | #define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000 | ||
242 | #define AR_PHY_RADAR_1_RELPWR_THRESH_S 16 | ||
243 | #define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000 | ||
244 | #define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000 | ||
245 | #define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 | ||
246 | #define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00 | ||
247 | #define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 | ||
248 | #define AR_PHY_RADAR_1_MAXLEN 0x000000FF | ||
249 | #define AR_PHY_RADAR_1_MAXLEN_S 0 | ||
250 | |||
251 | #define AR_PHY_SWITCH_CHAIN_0 0x9960 | ||
252 | #define AR_PHY_SWITCH_COM 0x9964 | ||
253 | |||
254 | #define AR_PHY_SIGMA_DELTA 0x996C | ||
255 | #define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 | ||
256 | #define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0 | ||
257 | #define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8 | ||
258 | #define AR_PHY_SIGMA_DELTA_FILT2_S 3 | ||
259 | #define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00 | ||
260 | #define AR_PHY_SIGMA_DELTA_FILT1_S 8 | ||
261 | #define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000 | ||
262 | #define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 | ||
263 | |||
264 | #define AR_PHY_RESTART 0x9970 | ||
265 | #define AR_PHY_RESTART_DIV_GC 0x001C0000 | ||
266 | #define AR_PHY_RESTART_DIV_GC_S 18 | ||
267 | |||
268 | #define AR_PHY_RFBUS_REQ 0x997C | ||
269 | #define AR_PHY_RFBUS_REQ_EN 0x00000001 | ||
270 | |||
271 | #define AR_PHY_TIMING7 0x9980 | ||
272 | #define AR_PHY_TIMING8 0x9984 | ||
273 | #define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF | ||
274 | #define AR_PHY_TIMING8_PILOT_MASK_2_S 0 | ||
275 | |||
276 | #define AR_PHY_BIN_MASK2_1 0x9988 | ||
277 | #define AR_PHY_BIN_MASK2_2 0x998c | ||
278 | #define AR_PHY_BIN_MASK2_3 0x9990 | ||
279 | #define AR_PHY_BIN_MASK2_4 0x9994 | ||
280 | |||
281 | #define AR_PHY_BIN_MASK_1 0x9900 | ||
282 | #define AR_PHY_BIN_MASK_2 0x9904 | ||
283 | #define AR_PHY_BIN_MASK_3 0x9908 | ||
284 | |||
285 | #define AR_PHY_MASK_CTL 0x990c | ||
286 | |||
287 | #define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF | ||
288 | #define AR_PHY_BIN_MASK2_4_MASK_4_S 0 | ||
289 | |||
290 | #define AR_PHY_TIMING9 0x9998 | ||
291 | #define AR_PHY_TIMING10 0x999c | ||
292 | #define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF | ||
293 | #define AR_PHY_TIMING10_PILOT_MASK_2_S 0 | ||
294 | |||
295 | #define AR_PHY_TIMING11 0x99a0 | ||
296 | #define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF | ||
297 | #define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 | ||
298 | #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 | ||
299 | #define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 | ||
300 | #define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 | ||
301 | #define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 | ||
302 | |||
303 | #define AR_PHY_RX_CHAINMASK 0x99a4 | ||
304 | #define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) | ||
305 | #define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 | ||
306 | #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 | ||
307 | #define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac | ||
308 | |||
309 | #define AR_PHY_EXT_CCA0 0x99b8 | ||
310 | #define AR_PHY_EXT_CCA0_THRESH62 0x000000FF | ||
311 | #define AR_PHY_EXT_CCA0_THRESH62_S 0 | ||
312 | |||
313 | #define AR_PHY_EXT_CCA 0x99bc | ||
314 | #define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00 | ||
315 | #define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 | ||
316 | #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 | ||
317 | #define AR_PHY_EXT_CCA_THRESH62_S 16 | ||
318 | #define AR_PHY_EXT_MINCCA_PWR 0xFF800000 | ||
319 | #define AR_PHY_EXT_MINCCA_PWR_S 23 | ||
320 | #define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 | ||
321 | #define AR9280_PHY_EXT_MINCCA_PWR_S 16 | ||
322 | |||
323 | #define AR_PHY_SFCORR_EXT 0x99c0 | ||
324 | #define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F | ||
325 | #define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 | ||
326 | #define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 | ||
327 | #define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 | ||
328 | #define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 | ||
329 | #define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 | ||
330 | #define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 | ||
331 | #define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 | ||
332 | #define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 | ||
333 | |||
334 | #define AR_PHY_HALFGI 0x99D0 | ||
335 | #define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0 | ||
336 | #define AR_PHY_HALFGI_DSC_MAN_S 4 | ||
337 | #define AR_PHY_HALFGI_DSC_EXP 0x0000000F | ||
338 | #define AR_PHY_HALFGI_DSC_EXP_S 0 | ||
339 | |||
340 | #define AR_PHY_CHAN_INFO_MEMORY 0x99DC | ||
341 | #define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 | ||
342 | |||
343 | #define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 | ||
344 | |||
345 | #define AR_PHY_M_SLEEP 0x99f0 | ||
346 | #define AR_PHY_REFCLKDLY 0x99f4 | ||
347 | #define AR_PHY_REFCLKPD 0x99f8 | ||
348 | |||
349 | #define AR_PHY_CALMODE 0x99f0 | ||
350 | |||
351 | #define AR_PHY_CALMODE_IQ 0x00000000 | ||
352 | #define AR_PHY_CALMODE_ADC_GAIN 0x00000001 | ||
353 | #define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 | ||
354 | #define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003 | ||
355 | |||
356 | #define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12)) | ||
357 | #define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12)) | ||
358 | #define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12)) | ||
359 | #define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12)) | ||
360 | |||
361 | #define AR_PHY_CURRENT_RSSI 0x9c1c | ||
362 | #define AR9280_PHY_CURRENT_RSSI 0x9c3c | ||
363 | |||
364 | #define AR_PHY_RFBUS_GRANT 0x9C20 | ||
365 | #define AR_PHY_RFBUS_GRANT_EN 0x00000001 | ||
366 | |||
367 | #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 | ||
368 | #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 | ||
369 | |||
370 | #define AR_PHY_CHAN_INFO_GAIN 0x9CFC | ||
371 | |||
372 | #define AR_PHY_MODE 0xA200 | ||
373 | #define AR_PHY_MODE_AR2133 0x08 | ||
374 | #define AR_PHY_MODE_AR5111 0x00 | ||
375 | #define AR_PHY_MODE_AR5112 0x08 | ||
376 | #define AR_PHY_MODE_DYNAMIC 0x04 | ||
377 | #define AR_PHY_MODE_RF2GHZ 0x02 | ||
378 | #define AR_PHY_MODE_RF5GHZ 0x00 | ||
379 | #define AR_PHY_MODE_CCK 0x01 | ||
380 | #define AR_PHY_MODE_OFDM 0x00 | ||
381 | #define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 | ||
382 | |||
383 | #define AR_PHY_CCK_TX_CTRL 0xA204 | ||
384 | #define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 | ||
385 | |||
386 | #define AR_PHY_CCK_DETECT 0xA208 | ||
387 | #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F | ||
388 | #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 | ||
389 | /* [12:6] settling time for antenna switch */ | ||
390 | #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 | ||
391 | #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 | ||
392 | #define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 | ||
393 | |||
394 | #define AR_PHY_GAIN_2GHZ 0xA20C | ||
395 | #define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 | ||
396 | #define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 | ||
397 | #define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00 | ||
398 | #define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 | ||
399 | #define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F | ||
400 | #define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 | ||
401 | |||
402 | #define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000 | ||
403 | #define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17 | ||
404 | #define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000 | ||
405 | #define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12 | ||
406 | #define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0 | ||
407 | #define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6 | ||
408 | #define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F | ||
409 | #define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0 | ||
410 | |||
411 | #define AR_PHY_CCK_RXCTRL4 0xA21C | ||
412 | #define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000 | ||
413 | #define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 | ||
414 | |||
415 | #define AR_PHY_DAG_CTRLCCK 0xA228 | ||
416 | #define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 | ||
417 | #define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 | ||
418 | #define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 | ||
419 | |||
420 | #define AR_PHY_FORCE_CLKEN_CCK 0xA22C | ||
421 | #define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 | ||
422 | |||
423 | #define AR_PHY_POWER_TX_RATE3 0xA234 | ||
424 | #define AR_PHY_POWER_TX_RATE4 0xA238 | ||
425 | |||
426 | #define AR_PHY_SCRM_SEQ_XR 0xA23C | ||
427 | #define AR_PHY_HEADER_DETECT_XR 0xA240 | ||
428 | #define AR_PHY_CHIRP_DETECTED_XR 0xA244 | ||
429 | #define AR_PHY_BLUETOOTH 0xA254 | ||
430 | |||
431 | #define AR_PHY_TPCRG1 0xA258 | ||
432 | #define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 | ||
433 | #define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 | ||
434 | |||
435 | #define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000 | ||
436 | #define AR_PHY_TPCRG1_PD_GAIN_1_S 16 | ||
437 | #define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000 | ||
438 | #define AR_PHY_TPCRG1_PD_GAIN_2_S 18 | ||
439 | #define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 | ||
440 | #define AR_PHY_TPCRG1_PD_GAIN_3_S 20 | ||
441 | |||
442 | #define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 | ||
443 | #define AR_PHY_MASK2_M_31_45 0xa3a4 | ||
444 | #define AR_PHY_MASK2_M_16_30 0xa3a8 | ||
445 | #define AR_PHY_MASK2_M_00_15 0xa3ac | ||
446 | #define AR_PHY_MASK2_P_15_01 0xa3b8 | ||
447 | #define AR_PHY_MASK2_P_30_16 0xa3bc | ||
448 | #define AR_PHY_MASK2_P_45_31 0xa3c0 | ||
449 | #define AR_PHY_MASK2_P_61_45 0xa3c4 | ||
450 | #define AR_PHY_SPUR_REG 0x994c | ||
451 | |||
452 | #define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18) | ||
453 | #define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 | ||
454 | |||
455 | #define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 | ||
456 | #define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9) | ||
457 | #define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 | ||
458 | #define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 | ||
459 | #define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F | ||
460 | #define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 | ||
461 | |||
462 | #define AR_PHY_PILOT_MASK_01_30 0xa3b0 | ||
463 | #define AR_PHY_PILOT_MASK_31_60 0xa3b4 | ||
464 | |||
465 | #define AR_PHY_CHANNEL_MASK_01_30 0x99d4 | ||
466 | #define AR_PHY_CHANNEL_MASK_31_60 0x99d8 | ||
467 | |||
468 | #define AR_PHY_ANALOG_SWAP 0xa268 | ||
469 | #define AR_PHY_SWAP_ALT_CHAIN 0x00000040 | ||
470 | |||
471 | #define AR_PHY_TPCRG5 0xA26C | ||
472 | #define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F | ||
473 | #define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 | ||
474 | #define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0 | ||
475 | #define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 | ||
476 | #define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00 | ||
477 | #define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 | ||
478 | #define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000 | ||
479 | #define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 | ||
480 | #define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000 | ||
481 | #define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 | ||
482 | |||
483 | #define AR_PHY_POWER_TX_RATE5 0xA38C | ||
484 | #define AR_PHY_POWER_TX_RATE6 0xA390 | ||
485 | |||
486 | #define AR_PHY_CAL_CHAINMASK 0xA39C | ||
487 | |||
488 | #define AR_PHY_POWER_TX_SUB 0xA3C8 | ||
489 | #define AR_PHY_POWER_TX_RATE7 0xA3CC | ||
490 | #define AR_PHY_POWER_TX_RATE8 0xA3D0 | ||
491 | #define AR_PHY_POWER_TX_RATE9 0xA3D4 | ||
492 | |||
493 | #define AR_PHY_XPA_CFG 0xA3D8 | ||
494 | #define AR_PHY_FORCE_XPA_CFG 0x000000001 | ||
495 | #define AR_PHY_FORCE_XPA_CFG_S 0 | ||
496 | |||
497 | #define AR_PHY_CH1_CCA 0xa864 | ||
498 | #define AR_PHY_CH1_MINCCA_PWR 0x0FF80000 | ||
499 | #define AR_PHY_CH1_MINCCA_PWR_S 19 | ||
500 | #define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000 | ||
501 | #define AR9280_PHY_CH1_MINCCA_PWR_S 20 | ||
502 | |||
503 | #define AR_PHY_CH2_CCA 0xb864 | ||
504 | #define AR_PHY_CH2_MINCCA_PWR 0x0FF80000 | ||
505 | #define AR_PHY_CH2_MINCCA_PWR_S 19 | ||
506 | |||
507 | #define AR_PHY_CH1_EXT_CCA 0xa9bc | ||
508 | #define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 | ||
509 | #define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 | ||
510 | #define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000 | ||
511 | #define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 | ||
512 | |||
513 | #define AR_PHY_CH2_EXT_CCA 0xb9bc | ||
514 | #define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 | ||
515 | #define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 | ||
516 | |||
517 | #define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ | ||
518 | int r; \ | ||
519 | for (r = 0; r < ((iniarray)->ia_rows); r++) { \ | ||
520 | REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ | ||
521 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, \ | ||
522 | "RF 0x%x V 0x%x\n", \ | ||
523 | INI_RA((iniarray), r, 0), (regData)[r]); \ | ||
524 | DO_DELAY(regWr); \ | ||
525 | } \ | ||
526 | } while (0) | ||
527 | |||
528 | #define ATH9K_KEY_XOR 0xaa | ||
529 | |||
530 | #define ATH9K_IS_MIC_ENABLED(ah) \ | ||
531 | (AH5416(ah)->ah_staId1Defaults & AR_STA_ID1_CRPT_MIC_ENABLE) | ||
532 | |||
533 | #define ANTSWAP_AB 0x0001 | ||
534 | #define REDUCE_CHAIN_0 0x00000050 | ||
535 | #define REDUCE_CHAIN_1 0x00000051 | ||
536 | |||
537 | #define RF_BANK_SETUP(_bank, _iniarray, _col) do { \ | ||
538 | int i; \ | ||
539 | for (i = 0; i < (_iniarray)->ia_rows; i++) \ | ||
540 | (_bank)[i] = INI_RA((_iniarray), i, _col);; \ | ||
541 | } while (0) | ||
542 | |||
543 | #endif | ||
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c new file mode 100644 index 00000000000..e0797afee52 --- /dev/null +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -0,0 +1,2126 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004 Video54 Technologies, Inc. | ||
3 | * Copyright (c) 2004-2008 Atheros Communications, Inc. | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | /* | ||
19 | * Atheros rate control algorithm | ||
20 | */ | ||
21 | |||
22 | #include "core.h" | ||
23 | #include "../net/mac80211/rate.h" | ||
24 | |||
25 | static u32 tx_triglevel_max; | ||
26 | |||
27 | static struct ath_rate_table ar5416_11na_ratetable = { | ||
28 | 42, | ||
29 | { | ||
30 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | ||
31 | 5400, 0x0b, 0x00, 12, | ||
32 | 0, 2, 1, 0, 0, 0, 0, 0 }, | ||
33 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | ||
34 | 7800, 0x0f, 0x00, 18, | ||
35 | 0, 3, 1, 1, 1, 1, 1, 0 }, | ||
36 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | ||
37 | 10000, 0x0a, 0x00, 24, | ||
38 | 2, 4, 2, 2, 2, 2, 2, 0 }, | ||
39 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | ||
40 | 13900, 0x0e, 0x00, 36, | ||
41 | 2, 6, 2, 3, 3, 3, 3, 0 }, | ||
42 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | ||
43 | 17300, 0x09, 0x00, 48, | ||
44 | 4, 10, 3, 4, 4, 4, 4, 0 }, | ||
45 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | ||
46 | 23000, 0x0d, 0x00, 72, | ||
47 | 4, 14, 3, 5, 5, 5, 5, 0 }, | ||
48 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | ||
49 | 27400, 0x08, 0x00, 96, | ||
50 | 4, 20, 3, 6, 6, 6, 6, 0 }, | ||
51 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | ||
52 | 29300, 0x0c, 0x00, 108, | ||
53 | 4, 23, 3, 7, 7, 7, 7, 0 }, | ||
54 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | ||
55 | 6400, 0x80, 0x00, 0, | ||
56 | 0, 2, 3, 8, 24, 8, 24, 3216 }, | ||
57 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */ | ||
58 | 12700, 0x81, 0x00, 1, | ||
59 | 2, 4, 3, 9, 25, 9, 25, 6434 }, | ||
60 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | ||
61 | 18800, 0x82, 0x00, 2, | ||
62 | 2, 6, 3, 10, 26, 10, 26, 9650 }, | ||
63 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */ | ||
64 | 25000, 0x83, 0x00, 3, | ||
65 | 4, 10, 3, 11, 27, 11, 27, 12868 }, | ||
66 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */ | ||
67 | 36700, 0x84, 0x00, 4, | ||
68 | 4, 14, 3, 12, 28, 12, 28, 19304 }, | ||
69 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */ | ||
70 | 48100, 0x85, 0x00, 5, | ||
71 | 4, 20, 3, 13, 29, 13, 29, 25740 }, | ||
72 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | ||
73 | 53500, 0x86, 0x00, 6, | ||
74 | 4, 23, 3, 14, 30, 14, 30, 28956 }, | ||
75 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */ | ||
76 | 59000, 0x87, 0x00, 7, | ||
77 | 4, 25, 3, 15, 31, 15, 32, 32180 }, | ||
78 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */ | ||
79 | 12700, 0x88, 0x00, | ||
80 | 8, 0, 2, 3, 16, 33, 16, 33, 6430 }, | ||
81 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */ | ||
82 | 24800, 0x89, 0x00, 9, | ||
83 | 2, 4, 3, 17, 34, 17, 34, 12860 }, | ||
84 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */ | ||
85 | 36600, 0x8a, 0x00, 10, | ||
86 | 2, 6, 3, 18, 35, 18, 35, 19300 }, | ||
87 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */ | ||
88 | 48100, 0x8b, 0x00, 11, | ||
89 | 4, 10, 3, 19, 36, 19, 36, 25736 }, | ||
90 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */ | ||
91 | 69500, 0x8c, 0x00, 12, | ||
92 | 4, 14, 3, 20, 37, 20, 37, 38600 }, | ||
93 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */ | ||
94 | 89500, 0x8d, 0x00, 13, | ||
95 | 4, 20, 3, 21, 38, 21, 38, 51472 }, | ||
96 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */ | ||
97 | 98900, 0x8e, 0x00, 14, | ||
98 | 4, 23, 3, 22, 39, 22, 39, 57890 }, | ||
99 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */ | ||
100 | 108300, 0x8f, 0x00, 15, | ||
101 | 4, 25, 3, 23, 40, 23, 41, 64320 }, | ||
102 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | ||
103 | 13200, 0x80, 0x00, 0, | ||
104 | 0, 2, 3, 8, 24, 24, 24, 6684 }, | ||
105 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | ||
106 | 25900, 0x81, 0x00, 1, | ||
107 | 2, 4, 3, 9, 25, 25, 25, 13368 }, | ||
108 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | ||
109 | 38600, 0x82, 0x00, 2, | ||
110 | 2, 6, 3, 10, 26, 26, 26, 20052 }, | ||
111 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */ | ||
112 | 49800, 0x83, 0x00, 3, | ||
113 | 4, 10, 3, 11, 27, 27, 27, 26738 }, | ||
114 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */ | ||
115 | 72200, 0x84, 0x00, 4, | ||
116 | 4, 14, 3, 12, 28, 28, 28, 40104 }, | ||
117 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */ | ||
118 | 92900, 0x85, 0x00, 5, | ||
119 | 4, 20, 3, 13, 29, 29, 29, 53476 }, | ||
120 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | ||
121 | 102700, 0x86, 0x00, 6, | ||
122 | 4, 23, 3, 14, 30, 30, 30, 60156 }, | ||
123 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */ | ||
124 | 112000, 0x87, 0x00, 7, | ||
125 | 4, 25, 3, 15, 31, 32, 32, 66840 }, | ||
126 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | ||
127 | 122000, 0x87, 0x00, 7, | ||
128 | 4, 25, 3, 15, 31, 32, 32, 74200 }, | ||
129 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */ | ||
130 | 25800, 0x88, 0x00, 8, | ||
131 | 0, 2, 3, 16, 33, 33, 33, 13360 }, | ||
132 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */ | ||
133 | 49800, 0x89, 0x00, 9, | ||
134 | 2, 4, 3, 17, 34, 34, 34, 26720 }, | ||
135 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */ | ||
136 | 71900, 0x8a, 0x00, 10, | ||
137 | 2, 6, 3, 18, 35, 35, 35, 40080 }, | ||
138 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */ | ||
139 | 92500, 0x8b, 0x00, 11, | ||
140 | 4, 10, 3, 19, 36, 36, 36, 53440 }, | ||
141 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */ | ||
142 | 130300, 0x8c, 0x00, 12, | ||
143 | 4, 14, 3, 20, 37, 37, 37, 80160 }, | ||
144 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */ | ||
145 | 162800, 0x8d, 0x00, 13, | ||
146 | 4, 20, 3, 21, 38, 38, 38, 106880 }, | ||
147 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */ | ||
148 | 178200, 0x8e, 0x00, 14, | ||
149 | 4, 23, 3, 22, 39, 39, 39, 120240 }, | ||
150 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */ | ||
151 | 192100, 0x8f, 0x00, 15, | ||
152 | 4, 25, 3, 23, 40, 41, 41, 133600 }, | ||
153 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | ||
154 | 207000, 0x8f, 0x00, 15, | ||
155 | 4, 25, 3, 23, 40, 41, 41, 148400 }, | ||
156 | }, | ||
157 | 50, /* probe interval */ | ||
158 | 50, /* rssi reduce interval */ | ||
159 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | ||
160 | }; | ||
161 | |||
162 | /* TRUE_ALL - valid for 20/40/Legacy, | ||
163 | * TRUE - Legacy only, | ||
164 | * TRUE_20 - HT 20 only, | ||
165 | * TRUE_40 - HT 40 only */ | ||
166 | |||
167 | /* 4ms frame limit not used for NG mode. The values filled | ||
168 | * for HT are the 64K max aggregate limit */ | ||
169 | |||
170 | static struct ath_rate_table ar5416_11ng_ratetable = { | ||
171 | 46, | ||
172 | { | ||
173 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 1000, /* 1 Mb */ | ||
174 | 900, 0x1b, 0x00, 2, | ||
175 | 0, 0, 1, 0, 0, 0, 0, 0 }, | ||
176 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 2000, /* 2 Mb */ | ||
177 | 1900, 0x1a, 0x04, 4, | ||
178 | 1, 1, 1, 1, 1, 1, 1, 0 }, | ||
179 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ | ||
180 | 4900, 0x19, 0x04, 11, | ||
181 | 2, 2, 2, 2, 2, 2, 2, 0 }, | ||
182 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 11000, /* 11 Mb */ | ||
183 | 8100, 0x18, 0x04, 22, | ||
184 | 3, 3, 2, 3, 3, 3, 3, 0 }, | ||
185 | { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | ||
186 | 5400, 0x0b, 0x00, 12, | ||
187 | 4, 2, 1, 4, 4, 4, 4, 0 }, | ||
188 | { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | ||
189 | 7800, 0x0f, 0x00, 18, | ||
190 | 4, 3, 1, 5, 5, 5, 5, 0 }, | ||
191 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | ||
192 | 10100, 0x0a, 0x00, 24, | ||
193 | 6, 4, 1, 6, 6, 6, 6, 0 }, | ||
194 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | ||
195 | 14100, 0x0e, 0x00, 36, | ||
196 | 6, 6, 2, 7, 7, 7, 7, 0 }, | ||
197 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | ||
198 | 17700, 0x09, 0x00, 48, | ||
199 | 8, 10, 3, 8, 8, 8, 8, 0 }, | ||
200 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | ||
201 | 23700, 0x0d, 0x00, 72, | ||
202 | 8, 14, 3, 9, 9, 9, 9, 0 }, | ||
203 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | ||
204 | 27400, 0x08, 0x00, 96, | ||
205 | 8, 20, 3, 10, 10, 10, 10, 0 }, | ||
206 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | ||
207 | 30900, 0x0c, 0x00, 108, | ||
208 | 8, 23, 3, 11, 11, 11, 11, 0 }, | ||
209 | { FALSE, FALSE, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | ||
210 | 6400, 0x80, 0x00, 0, | ||
211 | 4, 2, 3, 12, 28, 12, 28, 3216 }, | ||
212 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */ | ||
213 | 12700, 0x81, 0x00, 1, | ||
214 | 6, 4, 3, 13, 29, 13, 29, 6434 }, | ||
215 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | ||
216 | 18800, 0x82, 0x00, 2, | ||
217 | 6, 6, 3, 14, 30, 14, 30, 9650 }, | ||
218 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */ | ||
219 | 25000, 0x83, 0x00, 3, | ||
220 | 8, 10, 3, 15, 31, 15, 31, 12868 }, | ||
221 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */ | ||
222 | 36700, 0x84, 0x00, 4, | ||
223 | 8, 14, 3, 16, 32, 16, 32, 19304 }, | ||
224 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */ | ||
225 | 48100, 0x85, 0x00, 5, | ||
226 | 8, 20, 3, 17, 33, 17, 33, 25740 }, | ||
227 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | ||
228 | 53500, 0x86, 0x00, 6, | ||
229 | 8, 23, 3, 18, 34, 18, 34, 28956 }, | ||
230 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */ | ||
231 | 59000, 0x87, 0x00, 7, | ||
232 | 8, 25, 3, 19, 35, 19, 36, 32180 }, | ||
233 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */ | ||
234 | 12700, 0x88, 0x00, 8, | ||
235 | 4, 2, 3, 20, 37, 20, 37, 6430 }, | ||
236 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */ | ||
237 | 24800, 0x89, 0x00, 9, | ||
238 | 6, 4, 3, 21, 38, 21, 38, 12860 }, | ||
239 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */ | ||
240 | 36600, 0x8a, 0x00, 10, | ||
241 | 6, 6, 3, 22, 39, 22, 39, 19300 }, | ||
242 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */ | ||
243 | 48100, 0x8b, 0x00, 11, | ||
244 | 8, 10, 3, 23, 40, 23, 40, 25736 }, | ||
245 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */ | ||
246 | 69500, 0x8c, 0x00, 12, | ||
247 | 8, 14, 3, 24, 41, 24, 41, 38600 }, | ||
248 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */ | ||
249 | 89500, 0x8d, 0x00, 13, | ||
250 | 8, 20, 3, 25, 42, 25, 42, 51472 }, | ||
251 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */ | ||
252 | 98900, 0x8e, 0x00, 14, | ||
253 | 8, 23, 3, 26, 43, 26, 44, 57890 }, | ||
254 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */ | ||
255 | 108300, 0x8f, 0x00, 15, | ||
256 | 8, 25, 3, 27, 44, 27, 45, 64320 }, | ||
257 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | ||
258 | 13200, 0x80, 0x00, 0, | ||
259 | 8, 2, 3, 12, 28, 28, 28, 6684 }, | ||
260 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | ||
261 | 25900, 0x81, 0x00, 1, | ||
262 | 8, 4, 3, 13, 29, 29, 29, 13368 }, | ||
263 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | ||
264 | 38600, 0x82, 0x00, 2, | ||
265 | 8, 6, 3, 14, 30, 30, 30, 20052 }, | ||
266 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */ | ||
267 | 49800, 0x83, 0x00, 3, | ||
268 | 8, 10, 3, 15, 31, 31, 31, 26738 }, | ||
269 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */ | ||
270 | 72200, 0x84, 0x00, 4, | ||
271 | 8, 14, 3, 16, 32, 32, 32, 40104 }, | ||
272 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */ | ||
273 | 92900, 0x85, 0x00, 5, | ||
274 | 8, 20, 3, 17, 33, 33, 33, 53476 }, | ||
275 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | ||
276 | 102700, 0x86, 0x00, 6, | ||
277 | 8, 23, 3, 18, 34, 34, 34, 60156 }, | ||
278 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */ | ||
279 | 112000, 0x87, 0x00, 7, | ||
280 | 8, 23, 3, 19, 35, 36, 36, 66840 }, | ||
281 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | ||
282 | 122000, 0x87, 0x00, 7, | ||
283 | 8, 25, 3, 19, 35, 36, 36, 74200 }, | ||
284 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */ | ||
285 | 25800, 0x88, 0x00, 8, | ||
286 | 8, 2, 3, 20, 37, 37, 37, 13360 }, | ||
287 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */ | ||
288 | 49800, 0x89, 0x00, 9, | ||
289 | 8, 4, 3, 21, 38, 38, 38, 26720 }, | ||
290 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */ | ||
291 | 71900, 0x8a, 0x00, 10, | ||
292 | 8, 6, 3, 22, 39, 39, 39, 40080 }, | ||
293 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */ | ||
294 | 92500, 0x8b, 0x00, 11, | ||
295 | 8, 10, 3, 23, 40, 40, 40, 53440 }, | ||
296 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */ | ||
297 | 130300, 0x8c, 0x00, 12, | ||
298 | 8, 14, 3, 24, 41, 41, 41, 80160 }, | ||
299 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */ | ||
300 | 162800, 0x8d, 0x00, 13, | ||
301 | 8, 20, 3, 25, 42, 42, 42, 106880 }, | ||
302 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */ | ||
303 | 178200, 0x8e, 0x00, 14, | ||
304 | 8, 23, 3, 26, 43, 43, 43, 120240 }, | ||
305 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */ | ||
306 | 192100, 0x8f, 0x00, 15, | ||
307 | 8, 23, 3, 27, 44, 45, 45, 133600 }, | ||
308 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | ||
309 | 207000, 0x8f, 0x00, 15, | ||
310 | 8, 25, 3, 27, 44, 45, 45, 148400 }, | ||
311 | }, | ||
312 | 50, /* probe interval */ | ||
313 | 50, /* rssi reduce interval */ | ||
314 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | ||
315 | }; | ||
316 | |||
317 | static struct ath_rate_table ar5416_11a_ratetable = { | ||
318 | 8, | ||
319 | { | ||
320 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | ||
321 | 5400, 0x0b, 0x00, (0x80|12), | ||
322 | 0, 2, 1, 0, 0 }, | ||
323 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | ||
324 | 7800, 0x0f, 0x00, 18, | ||
325 | 0, 3, 1, 1, 0 }, | ||
326 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | ||
327 | 10000, 0x0a, 0x00, (0x80|24), | ||
328 | 2, 4, 2, 2, 0 }, | ||
329 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | ||
330 | 13900, 0x0e, 0x00, 36, | ||
331 | 2, 6, 2, 3, 0 }, | ||
332 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | ||
333 | 17300, 0x09, 0x00, (0x80|48), | ||
334 | 4, 10, 3, 4, 0 }, | ||
335 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | ||
336 | 23000, 0x0d, 0x00, 72, | ||
337 | 4, 14, 3, 5, 0 }, | ||
338 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | ||
339 | 27400, 0x08, 0x00, 96, | ||
340 | 4, 19, 3, 6, 0 }, | ||
341 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | ||
342 | 29300, 0x0c, 0x00, 108, | ||
343 | 4, 23, 3, 7, 0 }, | ||
344 | }, | ||
345 | 50, /* probe interval */ | ||
346 | 50, /* rssi reduce interval */ | ||
347 | 0, /* Phy rates allowed initially */ | ||
348 | }; | ||
349 | |||
350 | static struct ath_rate_table ar5416_11a_ratetable_Half = { | ||
351 | 8, | ||
352 | { | ||
353 | { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 6 Mb */ | ||
354 | 2700, 0x0b, 0x00, (0x80|6), | ||
355 | 0, 2, 1, 0, 0}, | ||
356 | { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 9 Mb */ | ||
357 | 3900, 0x0f, 0x00, 9, | ||
358 | 0, 3, 1, 1, 0 }, | ||
359 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 12 Mb */ | ||
360 | 5000, 0x0a, 0x00, (0x80|12), | ||
361 | 2, 4, 2, 2, 0 }, | ||
362 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 18 Mb */ | ||
363 | 6950, 0x0e, 0x00, 18, | ||
364 | 2, 6, 2, 3, 0 }, | ||
365 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 24 Mb */ | ||
366 | 8650, 0x09, 0x00, (0x80|24), | ||
367 | 4, 10, 3, 4, 0 }, | ||
368 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 36 Mb */ | ||
369 | 11500, 0x0d, 0x00, 36, | ||
370 | 4, 14, 3, 5, 0 }, | ||
371 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 48 Mb */ | ||
372 | 13700, 0x08, 0x00, 48, | ||
373 | 4, 19, 3, 6, 0 }, | ||
374 | { TRUE, TRUE, WLAN_PHY_OFDM, 27000, /* 54 Mb */ | ||
375 | 14650, 0x0c, 0x00, 54, | ||
376 | 4, 23, 3, 7, 0 }, | ||
377 | }, | ||
378 | 50, /* probe interval */ | ||
379 | 50, /* rssi reduce interval */ | ||
380 | 0, /* Phy rates allowed initially */ | ||
381 | }; | ||
382 | |||
383 | static struct ath_rate_table ar5416_11a_ratetable_Quarter = { | ||
384 | 8, | ||
385 | { | ||
386 | { TRUE, TRUE, WLAN_PHY_OFDM, 1500, /* 6 Mb */ | ||
387 | 1350, 0x0b, 0x00, (0x80|3), | ||
388 | 0, 2, 1, 0, 0 }, | ||
389 | { TRUE, TRUE, WLAN_PHY_OFDM, 2250, /* 9 Mb */ | ||
390 | 1950, 0x0f, 0x00, 4, | ||
391 | 0, 3, 1, 1, 0 }, | ||
392 | { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 12 Mb */ | ||
393 | 2500, 0x0a, 0x00, (0x80|6), | ||
394 | 2, 4, 2, 2, 0 }, | ||
395 | { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 18 Mb */ | ||
396 | 3475, 0x0e, 0x00, 9, | ||
397 | 2, 6, 2, 3, 0 }, | ||
398 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 25 Mb */ | ||
399 | 4325, 0x09, 0x00, (0x80|12), | ||
400 | 4, 10, 3, 4, 0 }, | ||
401 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 36 Mb */ | ||
402 | 5750, 0x0d, 0x00, 18, | ||
403 | 4, 14, 3, 5, 0 }, | ||
404 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 48 Mb */ | ||
405 | 6850, 0x08, 0x00, 24, | ||
406 | 4, 19, 3, 6, 0 }, | ||
407 | { TRUE, TRUE, WLAN_PHY_OFDM, 13500, /* 54 Mb */ | ||
408 | 7325, 0x0c, 0x00, 27, | ||
409 | 4, 23, 3, 7, 0 }, | ||
410 | }, | ||
411 | 50, /* probe interval */ | ||
412 | 50, /* rssi reduce interval */ | ||
413 | 0, /* Phy rates allowed initially */ | ||
414 | }; | ||
415 | |||
416 | static struct ath_rate_table ar5416_11g_ratetable = { | ||
417 | 12, | ||
418 | { | ||
419 | { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */ | ||
420 | 900, 0x1b, 0x00, 2, | ||
421 | 0, 0, 1, 0, 0 }, | ||
422 | { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */ | ||
423 | 1900, 0x1a, 0x04, 4, | ||
424 | 1, 1, 1, 1, 0 }, | ||
425 | { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ | ||
426 | 4900, 0x19, 0x04, 11, | ||
427 | 2, 2, 2, 2, 0 }, | ||
428 | { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */ | ||
429 | 8100, 0x18, 0x04, 22, | ||
430 | 3, 3, 2, 3, 0 }, | ||
431 | { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | ||
432 | 5400, 0x0b, 0x00, 12, | ||
433 | 4, 2, 1, 4, 0 }, | ||
434 | { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | ||
435 | 7800, 0x0f, 0x00, 18, | ||
436 | 4, 3, 1, 5, 0 }, | ||
437 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | ||
438 | 10000, 0x0a, 0x00, 24, | ||
439 | 6, 4, 1, 6, 0 }, | ||
440 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | ||
441 | 13900, 0x0e, 0x00, 36, | ||
442 | 6, 6, 2, 7, 0 }, | ||
443 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | ||
444 | 17300, 0x09, 0x00, 48, | ||
445 | 8, 10, 3, 8, 0 }, | ||
446 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | ||
447 | 23000, 0x0d, 0x00, 72, | ||
448 | 8, 14, 3, 9, 0 }, | ||
449 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | ||
450 | 27400, 0x08, 0x00, 96, | ||
451 | 8, 19, 3, 10, 0 }, | ||
452 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | ||
453 | 29300, 0x0c, 0x00, 108, | ||
454 | 8, 23, 3, 11, 0 }, | ||
455 | }, | ||
456 | 50, /* probe interval */ | ||
457 | 50, /* rssi reduce interval */ | ||
458 | 0, /* Phy rates allowed initially */ | ||
459 | }; | ||
460 | |||
461 | static struct ath_rate_table ar5416_11b_ratetable = { | ||
462 | 4, | ||
463 | { | ||
464 | { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */ | ||
465 | 900, 0x1b, 0x00, (0x80|2), | ||
466 | 0, 0, 1, 0, 0 }, | ||
467 | { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */ | ||
468 | 1800, 0x1a, 0x04, (0x80|4), | ||
469 | 1, 1, 1, 1, 0 }, | ||
470 | { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ | ||
471 | 4300, 0x19, 0x04, (0x80|11), | ||
472 | 1, 2, 2, 2, 0 }, | ||
473 | { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */ | ||
474 | 7100, 0x18, 0x04, (0x80|22), | ||
475 | 1, 4, 100, 3, 0 }, | ||
476 | }, | ||
477 | 100, /* probe interval */ | ||
478 | 100, /* rssi reduce interval */ | ||
479 | 0, /* Phy rates allowed initially */ | ||
480 | }; | ||
481 | |||
482 | static void ar5416_attach_ratetables(struct ath_rate_softc *sc) | ||
483 | { | ||
484 | /* | ||
485 | * Attach rate tables. | ||
486 | */ | ||
487 | sc->hw_rate_table[WIRELESS_MODE_11b] = &ar5416_11b_ratetable; | ||
488 | sc->hw_rate_table[WIRELESS_MODE_11a] = &ar5416_11a_ratetable; | ||
489 | sc->hw_rate_table[WIRELESS_MODE_11g] = &ar5416_11g_ratetable; | ||
490 | |||
491 | sc->hw_rate_table[WIRELESS_MODE_11NA_HT20] = &ar5416_11na_ratetable; | ||
492 | sc->hw_rate_table[WIRELESS_MODE_11NG_HT20] = &ar5416_11ng_ratetable; | ||
493 | sc->hw_rate_table[WIRELESS_MODE_11NA_HT40PLUS] = | ||
494 | &ar5416_11na_ratetable; | ||
495 | sc->hw_rate_table[WIRELESS_MODE_11NA_HT40MINUS] = | ||
496 | &ar5416_11na_ratetable; | ||
497 | sc->hw_rate_table[WIRELESS_MODE_11NG_HT40PLUS] = | ||
498 | &ar5416_11ng_ratetable; | ||
499 | sc->hw_rate_table[WIRELESS_MODE_11NG_HT40MINUS] = | ||
500 | &ar5416_11ng_ratetable; | ||
501 | } | ||
502 | |||
503 | static void ar5416_setquarter_ratetable(struct ath_rate_softc *sc) | ||
504 | { | ||
505 | sc->hw_rate_table[WIRELESS_MODE_11a] = &ar5416_11a_ratetable_Quarter; | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | static void ar5416_sethalf_ratetable(struct ath_rate_softc *sc) | ||
510 | { | ||
511 | sc->hw_rate_table[WIRELESS_MODE_11a] = &ar5416_11a_ratetable_Half; | ||
512 | return; | ||
513 | } | ||
514 | |||
515 | static void ar5416_setfull_ratetable(struct ath_rate_softc *sc) | ||
516 | { | ||
517 | sc->hw_rate_table[WIRELESS_MODE_11a] = &ar5416_11a_ratetable; | ||
518 | return; | ||
519 | } | ||
520 | |||
521 | /* | ||
522 | * Return the median of three numbers | ||
523 | */ | ||
524 | static inline int8_t median(int8_t a, int8_t b, int8_t c) | ||
525 | { | ||
526 | if (a >= b) { | ||
527 | if (b >= c) | ||
528 | return b; | ||
529 | else if (a > c) | ||
530 | return c; | ||
531 | else | ||
532 | return a; | ||
533 | } else { | ||
534 | if (a >= c) | ||
535 | return a; | ||
536 | else if (b >= c) | ||
537 | return c; | ||
538 | else | ||
539 | return b; | ||
540 | } | ||
541 | } | ||
542 | |||
543 | static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, | ||
544 | struct ath_tx_ratectrl *rate_ctrl) | ||
545 | { | ||
546 | u8 i, j, idx, idx_next; | ||
547 | |||
548 | for (i = rate_ctrl->max_valid_rate - 1; i > 0; i--) { | ||
549 | for (j = 0; j <= i-1; j++) { | ||
550 | idx = rate_ctrl->valid_rate_index[j]; | ||
551 | idx_next = rate_ctrl->valid_rate_index[j+1]; | ||
552 | |||
553 | if (rate_table->info[idx].ratekbps > | ||
554 | rate_table->info[idx_next].ratekbps) { | ||
555 | rate_ctrl->valid_rate_index[j] = idx_next; | ||
556 | rate_ctrl->valid_rate_index[j+1] = idx; | ||
557 | } | ||
558 | } | ||
559 | } | ||
560 | } | ||
561 | |||
562 | /* Access functions for valid_txrate_mask */ | ||
563 | |||
564 | static void ath_rc_init_valid_txmask(struct ath_tx_ratectrl *rate_ctrl) | ||
565 | { | ||
566 | u8 i; | ||
567 | |||
568 | for (i = 0; i < rate_ctrl->rate_table_size; i++) | ||
569 | rate_ctrl->valid_rate_index[i] = FALSE; | ||
570 | } | ||
571 | |||
572 | static inline void ath_rc_set_valid_txmask(struct ath_tx_ratectrl *rate_ctrl, | ||
573 | u8 index, int valid_tx_rate) | ||
574 | { | ||
575 | ASSERT(index <= rate_ctrl->rate_table_size); | ||
576 | rate_ctrl->valid_rate_index[index] = valid_tx_rate ? TRUE : FALSE; | ||
577 | } | ||
578 | |||
579 | static inline int ath_rc_isvalid_txmask(struct ath_tx_ratectrl *rate_ctrl, | ||
580 | u8 index) | ||
581 | { | ||
582 | ASSERT(index <= rate_ctrl->rate_table_size); | ||
583 | return rate_ctrl->valid_rate_index[index]; | ||
584 | } | ||
585 | |||
586 | /* Iterators for valid_txrate_mask */ | ||
587 | static inline int | ||
588 | ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, | ||
589 | struct ath_tx_ratectrl *rate_ctrl, | ||
590 | u8 cur_valid_txrate, | ||
591 | u8 *next_idx) | ||
592 | { | ||
593 | u8 i; | ||
594 | |||
595 | for (i = 0; i < rate_ctrl->max_valid_rate - 1; i++) { | ||
596 | if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) { | ||
597 | *next_idx = rate_ctrl->valid_rate_index[i+1]; | ||
598 | return TRUE; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | /* No more valid rates */ | ||
603 | *next_idx = 0; | ||
604 | return FALSE; | ||
605 | } | ||
606 | |||
607 | /* Return true only for single stream */ | ||
608 | |||
609 | static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) | ||
610 | { | ||
611 | if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG)) | ||
612 | return FALSE; | ||
613 | if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) | ||
614 | return FALSE; | ||
615 | if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) | ||
616 | return FALSE; | ||
617 | if (!ignore_cw && WLAN_RC_PHY_HT(phy)) | ||
618 | if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) | ||
619 | return FALSE; | ||
620 | if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG)) | ||
621 | return FALSE; | ||
622 | return TRUE; | ||
623 | } | ||
624 | |||
625 | static inline int | ||
626 | ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table, | ||
627 | struct ath_tx_ratectrl *rate_ctrl, | ||
628 | u8 cur_valid_txrate, u8 *next_idx) | ||
629 | { | ||
630 | int8_t i; | ||
631 | |||
632 | for (i = 1; i < rate_ctrl->max_valid_rate ; i++) { | ||
633 | if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) { | ||
634 | *next_idx = rate_ctrl->valid_rate_index[i-1]; | ||
635 | return TRUE; | ||
636 | } | ||
637 | } | ||
638 | return FALSE; | ||
639 | } | ||
640 | |||
641 | /* | ||
642 | * Initialize the Valid Rate Index from valid entries in Rate Table | ||
643 | */ | ||
644 | static u8 | ||
645 | ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv, | ||
646 | const struct ath_rate_table *rate_table, | ||
647 | u32 capflag) | ||
648 | { | ||
649 | struct ath_tx_ratectrl *rate_ctrl; | ||
650 | u8 i, hi = 0; | ||
651 | u32 valid; | ||
652 | |||
653 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
654 | for (i = 0; i < rate_table->rate_cnt; i++) { | ||
655 | valid = (ath_rc_priv->single_stream ? | ||
656 | rate_table->info[i].valid_single_stream : | ||
657 | rate_table->info[i].valid); | ||
658 | if (valid == TRUE) { | ||
659 | u32 phy = rate_table->info[i].phy; | ||
660 | u8 valid_rate_count = 0; | ||
661 | |||
662 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | ||
663 | continue; | ||
664 | |||
665 | valid_rate_count = rate_ctrl->valid_phy_ratecnt[phy]; | ||
666 | |||
667 | rate_ctrl->valid_phy_rateidx[phy][valid_rate_count] = i; | ||
668 | rate_ctrl->valid_phy_ratecnt[phy] += 1; | ||
669 | ath_rc_set_valid_txmask(rate_ctrl, i, TRUE); | ||
670 | hi = A_MAX(hi, i); | ||
671 | } | ||
672 | } | ||
673 | return hi; | ||
674 | } | ||
675 | |||
676 | /* | ||
677 | * Initialize the Valid Rate Index from Rate Set | ||
678 | */ | ||
679 | static u8 | ||
680 | ath_rc_sib_setvalid_rates(struct ath_rate_node *ath_rc_priv, | ||
681 | const struct ath_rate_table *rate_table, | ||
682 | struct ath_rateset *rateset, | ||
683 | u32 capflag) | ||
684 | { | ||
685 | /* XXX: Clean me up and make identation friendly */ | ||
686 | u8 i, j, hi = 0; | ||
687 | struct ath_tx_ratectrl *rate_ctrl = | ||
688 | (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
689 | |||
690 | /* Use intersection of working rates and valid rates */ | ||
691 | for (i = 0; i < rateset->rs_nrates; i++) { | ||
692 | for (j = 0; j < rate_table->rate_cnt; j++) { | ||
693 | u32 phy = rate_table->info[j].phy; | ||
694 | u32 valid = (ath_rc_priv->single_stream ? | ||
695 | rate_table->info[j].valid_single_stream : | ||
696 | rate_table->info[j].valid); | ||
697 | |||
698 | /* We allow a rate only if its valid and the | ||
699 | * capflag matches one of the validity | ||
700 | * (TRUE/TRUE_20/TRUE_40) flags */ | ||
701 | |||
702 | /* XXX: catch the negative of this branch | ||
703 | * first and then continue */ | ||
704 | if (((rateset->rs_rates[i] & 0x7F) == | ||
705 | (rate_table->info[j].dot11rate & 0x7F)) && | ||
706 | ((valid & WLAN_RC_CAP_MODE(capflag)) == | ||
707 | WLAN_RC_CAP_MODE(capflag)) && | ||
708 | !WLAN_RC_PHY_HT(phy)) { | ||
709 | |||
710 | u8 valid_rate_count = 0; | ||
711 | |||
712 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | ||
713 | continue; | ||
714 | |||
715 | valid_rate_count = | ||
716 | rate_ctrl->valid_phy_ratecnt[phy]; | ||
717 | |||
718 | rate_ctrl->valid_phy_rateidx[phy] | ||
719 | [valid_rate_count] = j; | ||
720 | rate_ctrl->valid_phy_ratecnt[phy] += 1; | ||
721 | ath_rc_set_valid_txmask(rate_ctrl, j, TRUE); | ||
722 | hi = A_MAX(hi, j); | ||
723 | } | ||
724 | } | ||
725 | } | ||
726 | return hi; | ||
727 | } | ||
728 | |||
729 | static u8 | ||
730 | ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv, | ||
731 | const struct ath_rate_table *rate_table, | ||
732 | u8 *mcs_set, u32 capflag) | ||
733 | { | ||
734 | u8 i, j, hi = 0; | ||
735 | struct ath_tx_ratectrl *rate_ctrl = | ||
736 | (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
737 | |||
738 | /* Use intersection of working rates and valid rates */ | ||
739 | for (i = 0; i < ((struct ath_rateset *)mcs_set)->rs_nrates; i++) { | ||
740 | for (j = 0; j < rate_table->rate_cnt; j++) { | ||
741 | u32 phy = rate_table->info[j].phy; | ||
742 | u32 valid = (ath_rc_priv->single_stream ? | ||
743 | rate_table->info[j].valid_single_stream : | ||
744 | rate_table->info[j].valid); | ||
745 | |||
746 | if (((((struct ath_rateset *) | ||
747 | mcs_set)->rs_rates[i] & 0x7F) != | ||
748 | (rate_table->info[j].dot11rate & 0x7F)) || | ||
749 | !WLAN_RC_PHY_HT(phy) || | ||
750 | !WLAN_RC_PHY_HT_VALID(valid, capflag)) | ||
751 | continue; | ||
752 | |||
753 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | ||
754 | continue; | ||
755 | |||
756 | rate_ctrl->valid_phy_rateidx[phy] | ||
757 | [rate_ctrl->valid_phy_ratecnt[phy]] = j; | ||
758 | rate_ctrl->valid_phy_ratecnt[phy] += 1; | ||
759 | ath_rc_set_valid_txmask(rate_ctrl, j, TRUE); | ||
760 | hi = A_MAX(hi, j); | ||
761 | } | ||
762 | } | ||
763 | return hi; | ||
764 | } | ||
765 | |||
766 | /* | ||
767 | * Attach to a device instance. Setup the public definition | ||
768 | * of how much per-node space we need and setup the private | ||
769 | * phy tables that have rate control parameters. | ||
770 | */ | ||
771 | struct ath_rate_softc *ath_rate_attach(struct ath_hal *ah) | ||
772 | { | ||
773 | struct ath_rate_softc *asc; | ||
774 | |||
775 | /* we are only in user context so we can sleep for memory */ | ||
776 | asc = kzalloc(sizeof(struct ath_rate_softc), GFP_KERNEL); | ||
777 | if (asc == NULL) | ||
778 | return NULL; | ||
779 | |||
780 | ar5416_attach_ratetables(asc); | ||
781 | |||
782 | /* Save Maximum TX Trigger Level (used for 11n) */ | ||
783 | tx_triglevel_max = ah->ah_caps.halTxTrigLevelMax; | ||
784 | /* return alias for ath_rate_softc * */ | ||
785 | return asc; | ||
786 | } | ||
787 | |||
788 | static struct ath_rate_node *ath_rate_node_alloc(struct ath_vap *avp, | ||
789 | struct ath_rate_softc *rsc, | ||
790 | gfp_t gfp) | ||
791 | { | ||
792 | struct ath_rate_node *anode; | ||
793 | |||
794 | anode = kzalloc(sizeof(struct ath_rate_node), gfp); | ||
795 | if (anode == NULL) | ||
796 | return NULL; | ||
797 | |||
798 | anode->avp = avp; | ||
799 | anode->asc = rsc; | ||
800 | avp->rc_node = anode; | ||
801 | |||
802 | return anode; | ||
803 | } | ||
804 | |||
805 | static void ath_rate_node_free(struct ath_rate_node *anode) | ||
806 | { | ||
807 | if (anode != NULL) | ||
808 | kfree(anode); | ||
809 | } | ||
810 | |||
811 | void ath_rate_detach(struct ath_rate_softc *asc) | ||
812 | { | ||
813 | if (asc != NULL) | ||
814 | kfree(asc); | ||
815 | } | ||
816 | |||
817 | u8 ath_rate_findrateix(struct ath_softc *sc, | ||
818 | u8 dot11rate) | ||
819 | { | ||
820 | const struct ath_rate_table *ratetable; | ||
821 | struct ath_rate_softc *rsc = sc->sc_rc; | ||
822 | int i; | ||
823 | |||
824 | ratetable = rsc->hw_rate_table[sc->sc_curmode]; | ||
825 | |||
826 | if (WARN_ON(!ratetable)) | ||
827 | return 0; | ||
828 | |||
829 | for (i = 0; i < ratetable->rate_cnt; i++) { | ||
830 | if ((ratetable->info[i].dot11rate & 0x7f) == (dot11rate & 0x7f)) | ||
831 | return i; | ||
832 | } | ||
833 | |||
834 | return 0; | ||
835 | } | ||
836 | |||
837 | /* | ||
838 | * Update rate-control state on a device state change. When | ||
839 | * operating as a station this includes associate/reassociate | ||
840 | * with an AP. Otherwise this gets called, for example, when | ||
841 | * the we transition to run state when operating as an AP. | ||
842 | */ | ||
843 | void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp) | ||
844 | { | ||
845 | struct ath_rate_softc *asc = sc->sc_rc; | ||
846 | |||
847 | /* For half and quarter rate channles use different | ||
848 | * rate tables | ||
849 | */ | ||
850 | if (sc->sc_curchan.channelFlags & CHANNEL_HALF) | ||
851 | ar5416_sethalf_ratetable(asc); | ||
852 | else if (sc->sc_curchan.channelFlags & CHANNEL_QUARTER) | ||
853 | ar5416_setquarter_ratetable(asc); | ||
854 | else /* full rate */ | ||
855 | ar5416_setfull_ratetable(asc); | ||
856 | |||
857 | if (avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) { | ||
858 | asc->fixedrix = | ||
859 | sc->sc_rixmap[avp->av_config.av_fixed_rateset & 0xff]; | ||
860 | /* NB: check the fixed rate exists */ | ||
861 | if (asc->fixedrix == 0xff) | ||
862 | asc->fixedrix = IEEE80211_FIXED_RATE_NONE; | ||
863 | } else { | ||
864 | asc->fixedrix = IEEE80211_FIXED_RATE_NONE; | ||
865 | } | ||
866 | } | ||
867 | |||
868 | static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | ||
869 | struct ath_rate_node *ath_rc_priv, | ||
870 | const struct ath_rate_table *rate_table, | ||
871 | int probe_allowed, int *is_probing, | ||
872 | int is_retry) | ||
873 | { | ||
874 | u32 dt, best_thruput, this_thruput, now_msec; | ||
875 | u8 rate, next_rate, best_rate, maxindex, minindex; | ||
876 | int8_t rssi_last, rssi_reduce = 0, index = 0; | ||
877 | struct ath_tx_ratectrl *rate_ctrl = NULL; | ||
878 | |||
879 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv ? | ||
880 | (ath_rc_priv) : NULL); | ||
881 | |||
882 | *is_probing = FALSE; | ||
883 | |||
884 | rssi_last = median(rate_ctrl->rssi_last, | ||
885 | rate_ctrl->rssi_last_prev, | ||
886 | rate_ctrl->rssi_last_prev2); | ||
887 | |||
888 | /* | ||
889 | * Age (reduce) last ack rssi based on how old it is. | ||
890 | * The bizarre numbers are so the delta is 160msec, | ||
891 | * meaning we divide by 16. | ||
892 | * 0msec <= dt <= 25msec: don't derate | ||
893 | * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB | ||
894 | * 185msec <= dt: derate by 10dB | ||
895 | */ | ||
896 | |||
897 | now_msec = jiffies_to_msecs(jiffies); | ||
898 | dt = now_msec - rate_ctrl->rssi_time; | ||
899 | |||
900 | if (dt >= 185) | ||
901 | rssi_reduce = 10; | ||
902 | else if (dt >= 25) | ||
903 | rssi_reduce = (u8)((dt - 25) >> 4); | ||
904 | |||
905 | /* Now reduce rssi_last by rssi_reduce */ | ||
906 | if (rssi_last < rssi_reduce) | ||
907 | rssi_last = 0; | ||
908 | else | ||
909 | rssi_last -= rssi_reduce; | ||
910 | |||
911 | /* | ||
912 | * Now look up the rate in the rssi table and return it. | ||
913 | * If no rates match then we return 0 (lowest rate) | ||
914 | */ | ||
915 | |||
916 | best_thruput = 0; | ||
917 | maxindex = rate_ctrl->max_valid_rate-1; | ||
918 | |||
919 | minindex = 0; | ||
920 | best_rate = minindex; | ||
921 | |||
922 | /* | ||
923 | * Try the higher rate first. It will reduce memory moving time | ||
924 | * if we have very good channel characteristics. | ||
925 | */ | ||
926 | for (index = maxindex; index >= minindex ; index--) { | ||
927 | u8 per_thres; | ||
928 | |||
929 | rate = rate_ctrl->valid_rate_index[index]; | ||
930 | if (rate > rate_ctrl->rate_max_phy) | ||
931 | continue; | ||
932 | |||
933 | /* | ||
934 | * For TCP the average collision rate is around 11%, | ||
935 | * so we ignore PERs less than this. This is to | ||
936 | * prevent the rate we are currently using (whose | ||
937 | * PER might be in the 10-15 range because of TCP | ||
938 | * collisions) looking worse than the next lower | ||
939 | * rate whose PER has decayed close to 0. If we | ||
940 | * used to next lower rate, its PER would grow to | ||
941 | * 10-15 and we would be worse off then staying | ||
942 | * at the current rate. | ||
943 | */ | ||
944 | per_thres = rate_ctrl->state[rate].per; | ||
945 | if (per_thres < 12) | ||
946 | per_thres = 12; | ||
947 | |||
948 | this_thruput = rate_table->info[rate].user_ratekbps * | ||
949 | (100 - per_thres); | ||
950 | |||
951 | if (best_thruput <= this_thruput) { | ||
952 | best_thruput = this_thruput; | ||
953 | best_rate = rate; | ||
954 | } | ||
955 | } | ||
956 | |||
957 | rate = best_rate; | ||
958 | |||
959 | /* if we are retrying for more than half the number | ||
960 | * of max retries, use the min rate for the next retry | ||
961 | */ | ||
962 | if (is_retry) | ||
963 | rate = rate_ctrl->valid_rate_index[minindex]; | ||
964 | |||
965 | rate_ctrl->rssi_last_lookup = rssi_last; | ||
966 | |||
967 | /* | ||
968 | * Must check the actual rate (ratekbps) to account for | ||
969 | * non-monoticity of 11g's rate table | ||
970 | */ | ||
971 | |||
972 | if (rate >= rate_ctrl->rate_max_phy && probe_allowed) { | ||
973 | rate = rate_ctrl->rate_max_phy; | ||
974 | |||
975 | /* Probe the next allowed phy state */ | ||
976 | /* FIXME:XXXX Check to make sure ratMax is checked properly */ | ||
977 | if (ath_rc_get_nextvalid_txrate(rate_table, | ||
978 | rate_ctrl, rate, &next_rate) && | ||
979 | (now_msec - rate_ctrl->probe_time > | ||
980 | rate_table->probe_interval) && | ||
981 | (rate_ctrl->hw_maxretry_pktcnt >= 1)) { | ||
982 | rate = next_rate; | ||
983 | rate_ctrl->probe_rate = rate; | ||
984 | rate_ctrl->probe_time = now_msec; | ||
985 | rate_ctrl->hw_maxretry_pktcnt = 0; | ||
986 | *is_probing = TRUE; | ||
987 | } | ||
988 | } | ||
989 | |||
990 | /* | ||
991 | * Make sure rate is not higher than the allowed maximum. | ||
992 | * We should also enforce the min, but I suspect the min is | ||
993 | * normally 1 rather than 0 because of the rate 9 vs 6 issue | ||
994 | * in the old code. | ||
995 | */ | ||
996 | if (rate > (rate_ctrl->rate_table_size - 1)) | ||
997 | rate = rate_ctrl->rate_table_size - 1; | ||
998 | |||
999 | ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || | ||
1000 | (rate_table->info[rate].valid_single_stream && | ||
1001 | ath_rc_priv->single_stream)); | ||
1002 | |||
1003 | return rate; | ||
1004 | } | ||
1005 | |||
1006 | static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table , | ||
1007 | struct ath_rc_series *series, | ||
1008 | u8 tries, | ||
1009 | u8 rix, | ||
1010 | int rtsctsenable) | ||
1011 | { | ||
1012 | series->tries = tries; | ||
1013 | series->flags = (rtsctsenable ? ATH_RC_RTSCTS_FLAG : 0) | | ||
1014 | (WLAN_RC_PHY_DS(rate_table->info[rix].phy) ? | ||
1015 | ATH_RC_DS_FLAG : 0) | | ||
1016 | (WLAN_RC_PHY_40(rate_table->info[rix].phy) ? | ||
1017 | ATH_RC_CW40_FLAG : 0) | | ||
1018 | (WLAN_RC_PHY_SGI(rate_table->info[rix].phy) ? | ||
1019 | ATH_RC_SGI_FLAG : 0); | ||
1020 | |||
1021 | series->rix = rate_table->info[rix].base_index; | ||
1022 | series->max_4ms_framelen = rate_table->info[rix].max_4ms_framelen; | ||
1023 | } | ||
1024 | |||
1025 | static u8 ath_rc_rate_getidx(struct ath_softc *sc, | ||
1026 | struct ath_rate_node *ath_rc_priv, | ||
1027 | const struct ath_rate_table *rate_table, | ||
1028 | u8 rix, u16 stepdown, | ||
1029 | u16 min_rate) | ||
1030 | { | ||
1031 | u32 j; | ||
1032 | u8 nextindex; | ||
1033 | struct ath_tx_ratectrl *rate_ctrl = | ||
1034 | (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
1035 | |||
1036 | if (min_rate) { | ||
1037 | for (j = RATE_TABLE_SIZE; j > 0; j--) { | ||
1038 | if (ath_rc_get_nextlowervalid_txrate(rate_table, | ||
1039 | rate_ctrl, rix, &nextindex)) | ||
1040 | rix = nextindex; | ||
1041 | else | ||
1042 | break; | ||
1043 | } | ||
1044 | } else { | ||
1045 | for (j = stepdown; j > 0; j--) { | ||
1046 | if (ath_rc_get_nextlowervalid_txrate(rate_table, | ||
1047 | rate_ctrl, rix, &nextindex)) | ||
1048 | rix = nextindex; | ||
1049 | else | ||
1050 | break; | ||
1051 | } | ||
1052 | } | ||
1053 | return rix; | ||
1054 | } | ||
1055 | |||
1056 | static void ath_rc_ratefind(struct ath_softc *sc, | ||
1057 | struct ath_rate_node *ath_rc_priv, | ||
1058 | int num_tries, int num_rates, unsigned int rcflag, | ||
1059 | struct ath_rc_series series[], int *is_probe, | ||
1060 | int is_retry) | ||
1061 | { | ||
1062 | u8 try_per_rate = 0, i = 0, rix, nrix; | ||
1063 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | ||
1064 | struct ath_rate_table *rate_table; | ||
1065 | |||
1066 | rate_table = | ||
1067 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; | ||
1068 | rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, | ||
1069 | (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0, | ||
1070 | is_probe, is_retry); | ||
1071 | nrix = rix; | ||
1072 | |||
1073 | if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) { | ||
1074 | /* set one try for probe rates. For the | ||
1075 | * probes don't enable rts */ | ||
1076 | ath_rc_rate_set_series(rate_table, | ||
1077 | &series[i++], 1, nrix, FALSE); | ||
1078 | |||
1079 | try_per_rate = (num_tries/num_rates); | ||
1080 | /* Get the next tried/allowed rate. No RTS for the next series | ||
1081 | * after the probe rate | ||
1082 | */ | ||
1083 | nrix = ath_rc_rate_getidx(sc, | ||
1084 | ath_rc_priv, rate_table, nrix, 1, FALSE); | ||
1085 | ath_rc_rate_set_series(rate_table, | ||
1086 | &series[i++], try_per_rate, nrix, 0); | ||
1087 | } else { | ||
1088 | try_per_rate = (num_tries/num_rates); | ||
1089 | /* Set the choosen rate. No RTS for first series entry. */ | ||
1090 | ath_rc_rate_set_series(rate_table, | ||
1091 | &series[i++], try_per_rate, nrix, FALSE); | ||
1092 | } | ||
1093 | |||
1094 | /* Fill in the other rates for multirate retry */ | ||
1095 | for ( ; i < num_rates; i++) { | ||
1096 | u8 try_num; | ||
1097 | u8 min_rate; | ||
1098 | |||
1099 | try_num = ((i + 1) == num_rates) ? | ||
1100 | num_tries - (try_per_rate * i) : try_per_rate ; | ||
1101 | min_rate = (((i + 1) == num_rates) && | ||
1102 | (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0; | ||
1103 | |||
1104 | nrix = ath_rc_rate_getidx(sc, ath_rc_priv, | ||
1105 | rate_table, nrix, 1, min_rate); | ||
1106 | /* All other rates in the series have RTS enabled */ | ||
1107 | ath_rc_rate_set_series(rate_table, | ||
1108 | &series[i], try_num, nrix, TRUE); | ||
1109 | } | ||
1110 | |||
1111 | /* | ||
1112 | * NB:Change rate series to enable aggregation when operating | ||
1113 | * at lower MCS rates. When first rate in series is MCS2 | ||
1114 | * in HT40 @ 2.4GHz, series should look like: | ||
1115 | * | ||
1116 | * {MCS2, MCS1, MCS0, MCS0}. | ||
1117 | * | ||
1118 | * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should | ||
1119 | * look like: | ||
1120 | * | ||
1121 | * {MCS3, MCS2, MCS1, MCS1} | ||
1122 | * | ||
1123 | * So, set fourth rate in series to be same as third one for | ||
1124 | * above conditions. | ||
1125 | */ | ||
1126 | if ((sc->sc_curmode == WIRELESS_MODE_11NG_HT20) || | ||
1127 | (sc->sc_curmode == WIRELESS_MODE_11NG_HT40PLUS) || | ||
1128 | (sc->sc_curmode == WIRELESS_MODE_11NG_HT40MINUS)) { | ||
1129 | u8 dot11rate = rate_table->info[rix].dot11rate; | ||
1130 | u8 phy = rate_table->info[rix].phy; | ||
1131 | if (i == 4 && | ||
1132 | ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || | ||
1133 | (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { | ||
1134 | series[3].rix = series[2].rix; | ||
1135 | series[3].flags = series[2].flags; | ||
1136 | series[3].max_4ms_framelen = series[2].max_4ms_framelen; | ||
1137 | } | ||
1138 | } | ||
1139 | } | ||
1140 | |||
1141 | /* | ||
1142 | * Return the Tx rate series. | ||
1143 | */ | ||
1144 | void ath_rate_findrate(struct ath_softc *sc, | ||
1145 | struct ath_rate_node *ath_rc_priv, | ||
1146 | int num_tries, | ||
1147 | int num_rates, | ||
1148 | unsigned int rcflag, | ||
1149 | struct ath_rc_series series[], | ||
1150 | int *is_probe, | ||
1151 | int is_retry) | ||
1152 | { | ||
1153 | struct ath_vap *avp = ath_rc_priv->avp; | ||
1154 | |||
1155 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | ||
1156 | if (!num_rates || !num_tries) | ||
1157 | return; | ||
1158 | |||
1159 | if (avp->av_config.av_fixed_rateset == IEEE80211_FIXED_RATE_NONE) { | ||
1160 | ath_rc_ratefind(sc, ath_rc_priv, num_tries, num_rates, | ||
1161 | rcflag, series, is_probe, is_retry); | ||
1162 | } else { | ||
1163 | /* Fixed rate */ | ||
1164 | int idx; | ||
1165 | u8 flags; | ||
1166 | u32 rix; | ||
1167 | struct ath_rate_softc *asc = ath_rc_priv->asc; | ||
1168 | struct ath_rate_table *rate_table; | ||
1169 | |||
1170 | rate_table = (struct ath_rate_table *) | ||
1171 | asc->hw_rate_table[sc->sc_curmode]; | ||
1172 | |||
1173 | for (idx = 0; idx < 4; idx++) { | ||
1174 | unsigned int mcs; | ||
1175 | u8 series_rix = 0; | ||
1176 | |||
1177 | series[idx].tries = | ||
1178 | IEEE80211_RATE_IDX_ENTRY( | ||
1179 | avp->av_config.av_fixed_retryset, idx); | ||
1180 | |||
1181 | mcs = IEEE80211_RATE_IDX_ENTRY( | ||
1182 | avp->av_config.av_fixed_rateset, idx); | ||
1183 | |||
1184 | if (idx == 3 && (mcs & 0xf0) == 0x70) | ||
1185 | mcs = (mcs & ~0xf0)|0x80; | ||
1186 | |||
1187 | if (!(mcs & 0x80)) | ||
1188 | flags = 0; | ||
1189 | else | ||
1190 | flags = ((ath_rc_priv->ht_cap & | ||
1191 | WLAN_RC_DS_FLAG) ? | ||
1192 | ATH_RC_DS_FLAG : 0) | | ||
1193 | ((ath_rc_priv->ht_cap & | ||
1194 | WLAN_RC_40_FLAG) ? | ||
1195 | ATH_RC_CW40_FLAG : 0) | | ||
1196 | ((ath_rc_priv->ht_cap & | ||
1197 | WLAN_RC_SGI_FLAG) ? | ||
1198 | ((ath_rc_priv->ht_cap & | ||
1199 | WLAN_RC_40_FLAG) ? | ||
1200 | ATH_RC_SGI_FLAG : 0) : 0); | ||
1201 | |||
1202 | series[idx].rix = sc->sc_rixmap[mcs]; | ||
1203 | series_rix = series[idx].rix; | ||
1204 | |||
1205 | /* XXX: Give me some cleanup love */ | ||
1206 | if ((flags & ATH_RC_CW40_FLAG) && | ||
1207 | (flags & ATH_RC_SGI_FLAG)) | ||
1208 | rix = rate_table->info[series_rix].ht_index; | ||
1209 | else if (flags & ATH_RC_SGI_FLAG) | ||
1210 | rix = rate_table->info[series_rix].sgi_index; | ||
1211 | else if (flags & ATH_RC_CW40_FLAG) | ||
1212 | rix = rate_table->info[series_rix].cw40index; | ||
1213 | else | ||
1214 | rix = rate_table->info[series_rix].base_index; | ||
1215 | series[idx].max_4ms_framelen = | ||
1216 | rate_table->info[rix].max_4ms_framelen; | ||
1217 | series[idx].flags = flags; | ||
1218 | } | ||
1219 | } | ||
1220 | } | ||
1221 | |||
1222 | static void ath_rc_update_ht(struct ath_softc *sc, | ||
1223 | struct ath_rate_node *ath_rc_priv, | ||
1224 | struct ath_tx_info_priv *info_priv, | ||
1225 | int tx_rate, int xretries, int retries) | ||
1226 | { | ||
1227 | struct ath_tx_ratectrl *rate_ctrl; | ||
1228 | u32 now_msec = jiffies_to_msecs(jiffies); | ||
1229 | int state_change = FALSE, rate, count; | ||
1230 | u8 last_per; | ||
1231 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | ||
1232 | struct ath_rate_table *rate_table = | ||
1233 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; | ||
1234 | |||
1235 | static u32 nretry_to_per_lookup[10] = { | ||
1236 | 100 * 0 / 1, | ||
1237 | 100 * 1 / 4, | ||
1238 | 100 * 1 / 2, | ||
1239 | 100 * 3 / 4, | ||
1240 | 100 * 4 / 5, | ||
1241 | 100 * 5 / 6, | ||
1242 | 100 * 6 / 7, | ||
1243 | 100 * 7 / 8, | ||
1244 | 100 * 8 / 9, | ||
1245 | 100 * 9 / 10 | ||
1246 | }; | ||
1247 | |||
1248 | if (!ath_rc_priv) | ||
1249 | return; | ||
1250 | |||
1251 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
1252 | |||
1253 | ASSERT(tx_rate >= 0); | ||
1254 | if (tx_rate < 0) | ||
1255 | return; | ||
1256 | |||
1257 | /* To compensate for some imbalance between ctrl and ext. channel */ | ||
1258 | |||
1259 | if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy)) | ||
1260 | info_priv->tx.ts_rssi = | ||
1261 | info_priv->tx.ts_rssi < 3 ? 0 : | ||
1262 | info_priv->tx.ts_rssi - 3; | ||
1263 | |||
1264 | last_per = rate_ctrl->state[tx_rate].per; | ||
1265 | |||
1266 | if (xretries) { | ||
1267 | /* Update the PER. */ | ||
1268 | if (xretries == 1) { | ||
1269 | rate_ctrl->state[tx_rate].per += 30; | ||
1270 | if (rate_ctrl->state[tx_rate].per > 100) | ||
1271 | rate_ctrl->state[tx_rate].per = 100; | ||
1272 | } else { | ||
1273 | /* xretries == 2 */ | ||
1274 | count = sizeof(nretry_to_per_lookup) / | ||
1275 | sizeof(nretry_to_per_lookup[0]); | ||
1276 | if (retries >= count) | ||
1277 | retries = count - 1; | ||
1278 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | ||
1279 | rate_ctrl->state[tx_rate].per = | ||
1280 | (u8)(rate_ctrl->state[tx_rate].per - | ||
1281 | (rate_ctrl->state[tx_rate].per >> 3) + | ||
1282 | ((100) >> 3)); | ||
1283 | } | ||
1284 | |||
1285 | /* xretries == 1 or 2 */ | ||
1286 | |||
1287 | if (rate_ctrl->probe_rate == tx_rate) | ||
1288 | rate_ctrl->probe_rate = 0; | ||
1289 | |||
1290 | } else { /* xretries == 0 */ | ||
1291 | /* Update the PER. */ | ||
1292 | /* Make sure it doesn't index out of array's bounds. */ | ||
1293 | count = sizeof(nretry_to_per_lookup) / | ||
1294 | sizeof(nretry_to_per_lookup[0]); | ||
1295 | if (retries >= count) | ||
1296 | retries = count - 1; | ||
1297 | if (info_priv->n_bad_frames) { | ||
1298 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | ||
1299 | /* | ||
1300 | * Assuming that n_frames is not 0. The current PER | ||
1301 | * from the retries is 100 * retries / (retries+1), | ||
1302 | * since the first retries attempts failed, and the | ||
1303 | * next one worked. For the one that worked, | ||
1304 | * n_bad_frames subframes out of n_frames wored, | ||
1305 | * so the PER for that part is | ||
1306 | * 100 * n_bad_frames / n_frames, and it contributes | ||
1307 | * 100 * n_bad_frames / (n_frames * (retries+1)) to | ||
1308 | * the above PER. The expression below is a | ||
1309 | * simplified version of the sum of these two terms. | ||
1310 | */ | ||
1311 | if (info_priv->n_frames > 0) | ||
1312 | rate_ctrl->state[tx_rate].per | ||
1313 | = (u8) | ||
1314 | (rate_ctrl->state[tx_rate].per - | ||
1315 | (rate_ctrl->state[tx_rate].per >> 3) + | ||
1316 | ((100*(retries*info_priv->n_frames + | ||
1317 | info_priv->n_bad_frames) / | ||
1318 | (info_priv->n_frames * | ||
1319 | (retries+1))) >> 3)); | ||
1320 | } else { | ||
1321 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | ||
1322 | |||
1323 | rate_ctrl->state[tx_rate].per = (u8) | ||
1324 | (rate_ctrl->state[tx_rate].per - | ||
1325 | (rate_ctrl->state[tx_rate].per >> 3) + | ||
1326 | (nretry_to_per_lookup[retries] >> 3)); | ||
1327 | } | ||
1328 | |||
1329 | rate_ctrl->rssi_last_prev2 = rate_ctrl->rssi_last_prev; | ||
1330 | rate_ctrl->rssi_last_prev = rate_ctrl->rssi_last; | ||
1331 | rate_ctrl->rssi_last = info_priv->tx.ts_rssi; | ||
1332 | rate_ctrl->rssi_time = now_msec; | ||
1333 | |||
1334 | /* | ||
1335 | * If we got at most one retry then increase the max rate if | ||
1336 | * this was a probe. Otherwise, ignore the probe. | ||
1337 | */ | ||
1338 | |||
1339 | if (rate_ctrl->probe_rate && rate_ctrl->probe_rate == tx_rate) { | ||
1340 | if (retries > 0 || 2 * info_priv->n_bad_frames > | ||
1341 | info_priv->n_frames) { | ||
1342 | /* | ||
1343 | * Since we probed with just a single attempt, | ||
1344 | * any retries means the probe failed. Also, | ||
1345 | * if the attempt worked, but more than half | ||
1346 | * the subframes were bad then also consider | ||
1347 | * the probe a failure. | ||
1348 | */ | ||
1349 | rate_ctrl->probe_rate = 0; | ||
1350 | } else { | ||
1351 | u8 probe_rate = 0; | ||
1352 | |||
1353 | rate_ctrl->rate_max_phy = rate_ctrl->probe_rate; | ||
1354 | probe_rate = rate_ctrl->probe_rate; | ||
1355 | |||
1356 | if (rate_ctrl->state[probe_rate].per > 30) | ||
1357 | rate_ctrl->state[probe_rate].per = 20; | ||
1358 | |||
1359 | rate_ctrl->probe_rate = 0; | ||
1360 | |||
1361 | /* | ||
1362 | * Since this probe succeeded, we allow the next | ||
1363 | * probe twice as soon. This allows the maxRate | ||
1364 | * to move up faster if the probes are | ||
1365 | * succesful. | ||
1366 | */ | ||
1367 | rate_ctrl->probe_time = now_msec - | ||
1368 | rate_table->probe_interval / 2; | ||
1369 | } | ||
1370 | } | ||
1371 | |||
1372 | if (retries > 0) { | ||
1373 | /* | ||
1374 | * Don't update anything. We don't know if | ||
1375 | * this was because of collisions or poor signal. | ||
1376 | * | ||
1377 | * Later: if rssi_ack is close to | ||
1378 | * rate_ctrl->state[txRate].rssi_thres and we see lots | ||
1379 | * of retries, then we could increase | ||
1380 | * rate_ctrl->state[txRate].rssi_thres. | ||
1381 | */ | ||
1382 | rate_ctrl->hw_maxretry_pktcnt = 0; | ||
1383 | } else { | ||
1384 | /* | ||
1385 | * It worked with no retries. First ignore bogus (small) | ||
1386 | * rssi_ack values. | ||
1387 | */ | ||
1388 | if (tx_rate == rate_ctrl->rate_max_phy && | ||
1389 | rate_ctrl->hw_maxretry_pktcnt < 255) { | ||
1390 | rate_ctrl->hw_maxretry_pktcnt++; | ||
1391 | } | ||
1392 | |||
1393 | if (info_priv->tx.ts_rssi >= | ||
1394 | rate_table->info[tx_rate].rssi_ack_validmin) { | ||
1395 | /* Average the rssi */ | ||
1396 | if (tx_rate != rate_ctrl->rssi_sum_rate) { | ||
1397 | rate_ctrl->rssi_sum_rate = tx_rate; | ||
1398 | rate_ctrl->rssi_sum = | ||
1399 | rate_ctrl->rssi_sum_cnt = 0; | ||
1400 | } | ||
1401 | |||
1402 | rate_ctrl->rssi_sum += info_priv->tx.ts_rssi; | ||
1403 | rate_ctrl->rssi_sum_cnt++; | ||
1404 | |||
1405 | if (rate_ctrl->rssi_sum_cnt > 4) { | ||
1406 | int32_t rssi_ackAvg = | ||
1407 | (rate_ctrl->rssi_sum + 2) / 4; | ||
1408 | int8_t rssi_thres = | ||
1409 | rate_ctrl->state[tx_rate]. | ||
1410 | rssi_thres; | ||
1411 | int8_t rssi_ack_vmin = | ||
1412 | rate_table->info[tx_rate]. | ||
1413 | rssi_ack_validmin; | ||
1414 | |||
1415 | rate_ctrl->rssi_sum = | ||
1416 | rate_ctrl->rssi_sum_cnt = 0; | ||
1417 | |||
1418 | /* Now reduce the current | ||
1419 | * rssi threshold. */ | ||
1420 | if ((rssi_ackAvg < rssi_thres + 2) && | ||
1421 | (rssi_thres > rssi_ack_vmin)) { | ||
1422 | rate_ctrl->state[tx_rate]. | ||
1423 | rssi_thres--; | ||
1424 | } | ||
1425 | |||
1426 | state_change = TRUE; | ||
1427 | } | ||
1428 | } | ||
1429 | } | ||
1430 | } | ||
1431 | |||
1432 | /* For all cases */ | ||
1433 | |||
1434 | /* | ||
1435 | * If this rate looks bad (high PER) then stop using it for | ||
1436 | * a while (except if we are probing). | ||
1437 | */ | ||
1438 | if (rate_ctrl->state[tx_rate].per >= 55 && tx_rate > 0 && | ||
1439 | rate_table->info[tx_rate].ratekbps <= | ||
1440 | rate_table->info[rate_ctrl->rate_max_phy].ratekbps) { | ||
1441 | ath_rc_get_nextlowervalid_txrate(rate_table, rate_ctrl, | ||
1442 | (u8) tx_rate, &rate_ctrl->rate_max_phy); | ||
1443 | |||
1444 | /* Don't probe for a little while. */ | ||
1445 | rate_ctrl->probe_time = now_msec; | ||
1446 | } | ||
1447 | |||
1448 | if (state_change) { | ||
1449 | /* | ||
1450 | * Make sure the rates above this have higher rssi thresholds. | ||
1451 | * (Note: Monotonicity is kept within the OFDM rates and | ||
1452 | * within the CCK rates. However, no adjustment is | ||
1453 | * made to keep the rssi thresholds monotonically | ||
1454 | * increasing between the CCK and OFDM rates.) | ||
1455 | */ | ||
1456 | for (rate = tx_rate; rate < | ||
1457 | rate_ctrl->rate_table_size - 1; rate++) { | ||
1458 | if (rate_table->info[rate+1].phy != | ||
1459 | rate_table->info[tx_rate].phy) | ||
1460 | break; | ||
1461 | |||
1462 | if (rate_ctrl->state[rate].rssi_thres + | ||
1463 | rate_table->info[rate].rssi_ack_deltamin > | ||
1464 | rate_ctrl->state[rate+1].rssi_thres) { | ||
1465 | rate_ctrl->state[rate+1].rssi_thres = | ||
1466 | rate_ctrl->state[rate]. | ||
1467 | rssi_thres + | ||
1468 | rate_table->info[rate]. | ||
1469 | rssi_ack_deltamin; | ||
1470 | } | ||
1471 | } | ||
1472 | |||
1473 | /* Make sure the rates below this have lower rssi thresholds. */ | ||
1474 | for (rate = tx_rate - 1; rate >= 0; rate--) { | ||
1475 | if (rate_table->info[rate].phy != | ||
1476 | rate_table->info[tx_rate].phy) | ||
1477 | break; | ||
1478 | |||
1479 | if (rate_ctrl->state[rate].rssi_thres + | ||
1480 | rate_table->info[rate].rssi_ack_deltamin > | ||
1481 | rate_ctrl->state[rate+1].rssi_thres) { | ||
1482 | if (rate_ctrl->state[rate+1].rssi_thres < | ||
1483 | rate_table->info[rate]. | ||
1484 | rssi_ack_deltamin) | ||
1485 | rate_ctrl->state[rate].rssi_thres = 0; | ||
1486 | else { | ||
1487 | rate_ctrl->state[rate].rssi_thres = | ||
1488 | rate_ctrl->state[rate+1]. | ||
1489 | rssi_thres - | ||
1490 | rate_table->info[rate]. | ||
1491 | rssi_ack_deltamin; | ||
1492 | } | ||
1493 | |||
1494 | if (rate_ctrl->state[rate].rssi_thres < | ||
1495 | rate_table->info[rate]. | ||
1496 | rssi_ack_validmin) { | ||
1497 | rate_ctrl->state[rate].rssi_thres = | ||
1498 | rate_table->info[rate]. | ||
1499 | rssi_ack_validmin; | ||
1500 | } | ||
1501 | } | ||
1502 | } | ||
1503 | } | ||
1504 | |||
1505 | /* Make sure the rates below this have lower PER */ | ||
1506 | /* Monotonicity is kept only for rates below the current rate. */ | ||
1507 | if (rate_ctrl->state[tx_rate].per < last_per) { | ||
1508 | for (rate = tx_rate - 1; rate >= 0; rate--) { | ||
1509 | if (rate_table->info[rate].phy != | ||
1510 | rate_table->info[tx_rate].phy) | ||
1511 | break; | ||
1512 | |||
1513 | if (rate_ctrl->state[rate].per > | ||
1514 | rate_ctrl->state[rate+1].per) { | ||
1515 | rate_ctrl->state[rate].per = | ||
1516 | rate_ctrl->state[rate+1].per; | ||
1517 | } | ||
1518 | } | ||
1519 | } | ||
1520 | |||
1521 | /* Maintain monotonicity for rates above the current rate */ | ||
1522 | for (rate = tx_rate; rate < rate_ctrl->rate_table_size - 1; rate++) { | ||
1523 | if (rate_ctrl->state[rate+1].per < rate_ctrl->state[rate].per) | ||
1524 | rate_ctrl->state[rate+1].per = | ||
1525 | rate_ctrl->state[rate].per; | ||
1526 | } | ||
1527 | |||
1528 | /* Every so often, we reduce the thresholds and | ||
1529 | * PER (different for CCK and OFDM). */ | ||
1530 | if (now_msec - rate_ctrl->rssi_down_time >= | ||
1531 | rate_table->rssi_reduce_interval) { | ||
1532 | |||
1533 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { | ||
1534 | if (rate_ctrl->state[rate].rssi_thres > | ||
1535 | rate_table->info[rate].rssi_ack_validmin) | ||
1536 | rate_ctrl->state[rate].rssi_thres -= 1; | ||
1537 | } | ||
1538 | rate_ctrl->rssi_down_time = now_msec; | ||
1539 | } | ||
1540 | |||
1541 | /* Every so often, we reduce the thresholds | ||
1542 | * and PER (different for CCK and OFDM). */ | ||
1543 | if (now_msec - rate_ctrl->per_down_time >= | ||
1544 | rate_table->rssi_reduce_interval) { | ||
1545 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { | ||
1546 | rate_ctrl->state[rate].per = | ||
1547 | 7 * rate_ctrl->state[rate].per / 8; | ||
1548 | } | ||
1549 | |||
1550 | rate_ctrl->per_down_time = now_msec; | ||
1551 | } | ||
1552 | } | ||
1553 | |||
1554 | /* | ||
1555 | * This routine is called in rate control callback tx_status() to give | ||
1556 | * the status of previous frames. | ||
1557 | */ | ||
1558 | static void ath_rc_update(struct ath_softc *sc, | ||
1559 | struct ath_rate_node *ath_rc_priv, | ||
1560 | struct ath_tx_info_priv *info_priv, int final_ts_idx, | ||
1561 | int xretries, int long_retry) | ||
1562 | { | ||
1563 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | ||
1564 | struct ath_rate_table *rate_table; | ||
1565 | struct ath_tx_ratectrl *rate_ctrl; | ||
1566 | struct ath_rc_series rcs[4]; | ||
1567 | u8 flags; | ||
1568 | u32 series = 0, rix; | ||
1569 | |||
1570 | memcpy(rcs, info_priv->rcs, 4 * sizeof(rcs[0])); | ||
1571 | rate_table = (struct ath_rate_table *) | ||
1572 | asc->hw_rate_table[sc->sc_curmode]; | ||
1573 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
1574 | ASSERT(rcs[0].tries != 0); | ||
1575 | |||
1576 | /* | ||
1577 | * If the first rate is not the final index, there | ||
1578 | * are intermediate rate failures to be processed. | ||
1579 | */ | ||
1580 | if (final_ts_idx != 0) { | ||
1581 | /* Process intermediate rates that failed.*/ | ||
1582 | for (series = 0; series < final_ts_idx ; series++) { | ||
1583 | if (rcs[series].tries != 0) { | ||
1584 | flags = rcs[series].flags; | ||
1585 | /* If HT40 and we have switched mode from | ||
1586 | * 40 to 20 => don't update */ | ||
1587 | if ((flags & ATH_RC_CW40_FLAG) && | ||
1588 | (rate_ctrl->rc_phy_mode != | ||
1589 | (flags & ATH_RC_CW40_FLAG))) | ||
1590 | return; | ||
1591 | if ((flags & ATH_RC_CW40_FLAG) && | ||
1592 | (flags & ATH_RC_SGI_FLAG)) | ||
1593 | rix = rate_table->info[ | ||
1594 | rcs[series].rix].ht_index; | ||
1595 | else if (flags & ATH_RC_SGI_FLAG) | ||
1596 | rix = rate_table->info[ | ||
1597 | rcs[series].rix].sgi_index; | ||
1598 | else if (flags & ATH_RC_CW40_FLAG) | ||
1599 | rix = rate_table->info[ | ||
1600 | rcs[series].rix].cw40index; | ||
1601 | else | ||
1602 | rix = rate_table->info[ | ||
1603 | rcs[series].rix].base_index; | ||
1604 | ath_rc_update_ht(sc, ath_rc_priv, | ||
1605 | info_priv, rix, | ||
1606 | xretries ? 1 : 2, | ||
1607 | rcs[series].tries); | ||
1608 | } | ||
1609 | } | ||
1610 | } else { | ||
1611 | /* | ||
1612 | * Handle the special case of MIMO PS burst, where the second | ||
1613 | * aggregate is sent out with only one rate and one try. | ||
1614 | * Treating it as an excessive retry penalizes the rate | ||
1615 | * inordinately. | ||
1616 | */ | ||
1617 | if (rcs[0].tries == 1 && xretries == 1) | ||
1618 | xretries = 2; | ||
1619 | } | ||
1620 | |||
1621 | flags = rcs[series].flags; | ||
1622 | /* If HT40 and we have switched mode from 40 to 20 => don't update */ | ||
1623 | if ((flags & ATH_RC_CW40_FLAG) && | ||
1624 | (rate_ctrl->rc_phy_mode != (flags & ATH_RC_CW40_FLAG))) | ||
1625 | return; | ||
1626 | |||
1627 | if ((flags & ATH_RC_CW40_FLAG) && (flags & ATH_RC_SGI_FLAG)) | ||
1628 | rix = rate_table->info[rcs[series].rix].ht_index; | ||
1629 | else if (flags & ATH_RC_SGI_FLAG) | ||
1630 | rix = rate_table->info[rcs[series].rix].sgi_index; | ||
1631 | else if (flags & ATH_RC_CW40_FLAG) | ||
1632 | rix = rate_table->info[rcs[series].rix].cw40index; | ||
1633 | else | ||
1634 | rix = rate_table->info[rcs[series].rix].base_index; | ||
1635 | |||
1636 | ath_rc_update_ht(sc, ath_rc_priv, info_priv, rix, | ||
1637 | xretries, long_retry); | ||
1638 | } | ||
1639 | |||
1640 | |||
1641 | /* | ||
1642 | * Process a tx descriptor for a completed transmit (success or failure). | ||
1643 | */ | ||
1644 | static void ath_rate_tx_complete(struct ath_softc *sc, | ||
1645 | struct ath_node *an, | ||
1646 | struct ath_rate_node *rc_priv, | ||
1647 | struct ath_tx_info_priv *info_priv) | ||
1648 | { | ||
1649 | int final_ts_idx = info_priv->tx.ts_rateindex; | ||
1650 | int tx_status = 0, is_underrun = 0; | ||
1651 | struct ath_vap *avp; | ||
1652 | |||
1653 | avp = rc_priv->avp; | ||
1654 | if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) | ||
1655 | || info_priv->tx.ts_status & ATH9K_TXERR_FILT) | ||
1656 | return; | ||
1657 | |||
1658 | if (info_priv->tx.ts_rssi > 0) { | ||
1659 | ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi, | ||
1660 | info_priv->tx.ts_rssi); | ||
1661 | } | ||
1662 | |||
1663 | /* | ||
1664 | * If underrun error is seen assume it as an excessive retry only | ||
1665 | * if prefetch trigger level have reached the max (0x3f for 5416) | ||
1666 | * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY | ||
1667 | * times. This affects how ratectrl updates PER for the failed rate. | ||
1668 | */ | ||
1669 | if (info_priv->tx.ts_flags & | ||
1670 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) && | ||
1671 | ((sc->sc_ah->ah_txTrigLevel) >= tx_triglevel_max)) { | ||
1672 | tx_status = 1; | ||
1673 | is_underrun = 1; | ||
1674 | } | ||
1675 | |||
1676 | if ((info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) || | ||
1677 | (info_priv->tx.ts_status & ATH9K_TXERR_FIFO)) | ||
1678 | tx_status = 1; | ||
1679 | |||
1680 | ath_rc_update(sc, rc_priv, info_priv, final_ts_idx, tx_status, | ||
1681 | (is_underrun) ? ATH_11N_TXMAXTRY : | ||
1682 | info_priv->tx.ts_longretry); | ||
1683 | } | ||
1684 | |||
1685 | |||
1686 | /* | ||
1687 | * Update the SIB's rate control information | ||
1688 | * | ||
1689 | * This should be called when the supported rates change | ||
1690 | * (e.g. SME operation, wireless mode change) | ||
1691 | * | ||
1692 | * It will determine which rates are valid for use. | ||
1693 | */ | ||
1694 | static void ath_rc_sib_update(struct ath_softc *sc, | ||
1695 | struct ath_rate_node *ath_rc_priv, | ||
1696 | u32 capflag, int keep_state, | ||
1697 | struct ath_rateset *negotiated_rates, | ||
1698 | struct ath_rateset *negotiated_htrates) | ||
1699 | { | ||
1700 | struct ath_rate_table *rate_table = NULL; | ||
1701 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | ||
1702 | struct ath_rateset *rateset = negotiated_rates; | ||
1703 | u8 *ht_mcs = (u8 *)negotiated_htrates; | ||
1704 | struct ath_tx_ratectrl *rate_ctrl = (struct ath_tx_ratectrl *) | ||
1705 | (ath_rc_priv); | ||
1706 | u8 i, j, k, hi = 0, hthi = 0; | ||
1707 | |||
1708 | rate_table = (struct ath_rate_table *) | ||
1709 | asc->hw_rate_table[sc->sc_curmode]; | ||
1710 | |||
1711 | /* Initial rate table size. Will change depending | ||
1712 | * on the working rate set */ | ||
1713 | rate_ctrl->rate_table_size = MAX_TX_RATE_TBL; | ||
1714 | |||
1715 | /* Initialize thresholds according to the global rate table */ | ||
1716 | for (i = 0 ; (i < rate_ctrl->rate_table_size) && (!keep_state); i++) { | ||
1717 | rate_ctrl->state[i].rssi_thres = | ||
1718 | rate_table->info[i].rssi_ack_validmin; | ||
1719 | rate_ctrl->state[i].per = 0; | ||
1720 | } | ||
1721 | |||
1722 | /* Determine the valid rates */ | ||
1723 | ath_rc_init_valid_txmask(rate_ctrl); | ||
1724 | |||
1725 | for (i = 0; i < WLAN_RC_PHY_MAX; i++) { | ||
1726 | for (j = 0; j < MAX_TX_RATE_PHY; j++) | ||
1727 | rate_ctrl->valid_phy_rateidx[i][j] = 0; | ||
1728 | rate_ctrl->valid_phy_ratecnt[i] = 0; | ||
1729 | } | ||
1730 | rate_ctrl->rc_phy_mode = (capflag & WLAN_RC_40_FLAG); | ||
1731 | |||
1732 | /* Set stream capability */ | ||
1733 | ath_rc_priv->single_stream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1; | ||
1734 | |||
1735 | if (!rateset->rs_nrates) { | ||
1736 | /* No working rate, just initialize valid rates */ | ||
1737 | hi = ath_rc_sib_init_validrates(ath_rc_priv, rate_table, | ||
1738 | capflag); | ||
1739 | } else { | ||
1740 | /* Use intersection of working rates and valid rates */ | ||
1741 | hi = ath_rc_sib_setvalid_rates(ath_rc_priv, rate_table, | ||
1742 | rateset, capflag); | ||
1743 | if (capflag & WLAN_RC_HT_FLAG) { | ||
1744 | hthi = ath_rc_sib_setvalid_htrates(ath_rc_priv, | ||
1745 | rate_table, | ||
1746 | ht_mcs, | ||
1747 | capflag); | ||
1748 | } | ||
1749 | hi = A_MAX(hi, hthi); | ||
1750 | } | ||
1751 | |||
1752 | rate_ctrl->rate_table_size = hi + 1; | ||
1753 | rate_ctrl->rate_max_phy = 0; | ||
1754 | ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL); | ||
1755 | |||
1756 | for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { | ||
1757 | for (j = 0; j < rate_ctrl->valid_phy_ratecnt[i]; j++) { | ||
1758 | rate_ctrl->valid_rate_index[k++] = | ||
1759 | rate_ctrl->valid_phy_rateidx[i][j]; | ||
1760 | } | ||
1761 | |||
1762 | if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, TRUE) | ||
1763 | || !rate_ctrl->valid_phy_ratecnt[i]) | ||
1764 | continue; | ||
1765 | |||
1766 | rate_ctrl->rate_max_phy = rate_ctrl->valid_phy_rateidx[i][j-1]; | ||
1767 | } | ||
1768 | ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL); | ||
1769 | ASSERT(k <= MAX_TX_RATE_TBL); | ||
1770 | |||
1771 | rate_ctrl->max_valid_rate = k; | ||
1772 | /* | ||
1773 | * Some third party vendors don't send the supported rate series in | ||
1774 | * order. So sorting to make sure its in order, otherwise our RateFind | ||
1775 | * Algo will select wrong rates | ||
1776 | */ | ||
1777 | ath_rc_sort_validrates(rate_table, rate_ctrl); | ||
1778 | rate_ctrl->rate_max_phy = rate_ctrl->valid_rate_index[k-4]; | ||
1779 | } | ||
1780 | |||
1781 | /* | ||
1782 | * Update rate-control state on station associate/reassociate. | ||
1783 | */ | ||
1784 | static int ath_rate_newassoc(struct ath_softc *sc, | ||
1785 | struct ath_rate_node *ath_rc_priv, | ||
1786 | unsigned int capflag, | ||
1787 | struct ath_rateset *negotiated_rates, | ||
1788 | struct ath_rateset *negotiated_htrates) | ||
1789 | { | ||
1790 | |||
1791 | |||
1792 | ath_rc_priv->ht_cap = | ||
1793 | ((capflag & ATH_RC_DS_FLAG) ? WLAN_RC_DS_FLAG : 0) | | ||
1794 | ((capflag & ATH_RC_SGI_FLAG) ? WLAN_RC_SGI_FLAG : 0) | | ||
1795 | ((capflag & ATH_RC_HT_FLAG) ? WLAN_RC_HT_FLAG : 0) | | ||
1796 | ((capflag & ATH_RC_CW40_FLAG) ? WLAN_RC_40_FLAG : 0); | ||
1797 | |||
1798 | ath_rc_sib_update(sc, ath_rc_priv, ath_rc_priv->ht_cap, 0, | ||
1799 | negotiated_rates, negotiated_htrates); | ||
1800 | |||
1801 | return 0; | ||
1802 | } | ||
1803 | |||
1804 | /* | ||
1805 | * This routine is called to initialize the rate control parameters | ||
1806 | * in the SIB. It is called initially during system initialization | ||
1807 | * or when a station is associated with the AP. | ||
1808 | */ | ||
1809 | static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv) | ||
1810 | { | ||
1811 | struct ath_tx_ratectrl *rate_ctrl; | ||
1812 | |||
1813 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
1814 | rate_ctrl->rssi_down_time = jiffies_to_msecs(jiffies); | ||
1815 | } | ||
1816 | |||
1817 | |||
1818 | static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta) | ||
1819 | |||
1820 | { | ||
1821 | struct ieee80211_supported_band *sband; | ||
1822 | struct ieee80211_hw *hw = local_to_hw(local); | ||
1823 | struct ath_softc *sc = hw->priv; | ||
1824 | struct ath_rate_node *rc_priv = sta->rate_ctrl_priv; | ||
1825 | int i, j = 0; | ||
1826 | |||
1827 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | ||
1828 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1829 | for (i = 0; i < sband->n_bitrates; i++) { | ||
1830 | if (sta->supp_rates[local->hw.conf.channel->band] & BIT(i)) { | ||
1831 | rc_priv->neg_rates.rs_rates[j] | ||
1832 | = (sband->bitrates[i].bitrate * 2) / 10; | ||
1833 | j++; | ||
1834 | } | ||
1835 | } | ||
1836 | rc_priv->neg_rates.rs_nrates = j; | ||
1837 | } | ||
1838 | |||
1839 | void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv) | ||
1840 | { | ||
1841 | struct ath_softc *sc = hw->priv; | ||
1842 | u32 capflag = 0; | ||
1843 | |||
1844 | if (hw->conf.ht_conf.ht_supported) { | ||
1845 | capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG; | ||
1846 | if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040) | ||
1847 | capflag |= ATH_RC_CW40_FLAG; | ||
1848 | } | ||
1849 | |||
1850 | ath_rate_newassoc(sc, rc_priv, capflag, | ||
1851 | &rc_priv->neg_rates, | ||
1852 | &rc_priv->neg_ht_rates); | ||
1853 | |||
1854 | } | ||
1855 | |||
1856 | /* Rate Control callbacks */ | ||
1857 | static void ath_tx_status(void *priv, struct net_device *dev, | ||
1858 | struct sk_buff *skb) | ||
1859 | { | ||
1860 | struct ath_softc *sc = priv; | ||
1861 | struct ath_tx_info_priv *tx_info_priv; | ||
1862 | struct ath_node *an; | ||
1863 | struct sta_info *sta; | ||
1864 | struct ieee80211_local *local; | ||
1865 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1866 | struct ieee80211_hdr *hdr; | ||
1867 | __le16 fc; | ||
1868 | |||
1869 | local = hw_to_local(sc->hw); | ||
1870 | hdr = (struct ieee80211_hdr *)skb->data; | ||
1871 | fc = hdr->frame_control; | ||
1872 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | ||
1873 | |||
1874 | spin_lock_bh(&sc->node_lock); | ||
1875 | an = ath_node_find(sc, hdr->addr1); | ||
1876 | spin_unlock_bh(&sc->node_lock); | ||
1877 | |||
1878 | sta = sta_info_get(local, hdr->addr1); | ||
1879 | if (!an || !sta || !ieee80211_is_data(fc)) { | ||
1880 | if (tx_info->driver_data[0] != NULL) { | ||
1881 | kfree(tx_info->driver_data[0]); | ||
1882 | tx_info->driver_data[0] = NULL; | ||
1883 | } | ||
1884 | return; | ||
1885 | } | ||
1886 | if (tx_info->driver_data[0] != NULL) { | ||
1887 | ath_rate_tx_complete(sc, an, sta->rate_ctrl_priv, tx_info_priv); | ||
1888 | kfree(tx_info->driver_data[0]); | ||
1889 | tx_info->driver_data[0] = NULL; | ||
1890 | } | ||
1891 | } | ||
1892 | |||
1893 | static void ath_tx_aggr_resp(struct ath_softc *sc, | ||
1894 | struct sta_info *sta, | ||
1895 | struct ath_node *an, | ||
1896 | u8 tidno) | ||
1897 | { | ||
1898 | struct ieee80211_hw *hw = sc->hw; | ||
1899 | struct ieee80211_local *local; | ||
1900 | struct ath_atx_tid *txtid; | ||
1901 | struct ieee80211_supported_band *sband; | ||
1902 | u16 buffersize = 0; | ||
1903 | int state; | ||
1904 | DECLARE_MAC_BUF(mac); | ||
1905 | |||
1906 | if (!sc->sc_txaggr) | ||
1907 | return; | ||
1908 | |||
1909 | txtid = ATH_AN_2_TID(an, tidno); | ||
1910 | if (!txtid->paused) | ||
1911 | return; | ||
1912 | |||
1913 | local = hw_to_local(sc->hw); | ||
1914 | sband = hw->wiphy->bands[hw->conf.channel->band]; | ||
1915 | buffersize = IEEE80211_MIN_AMPDU_BUF << | ||
1916 | sband->ht_info.ampdu_factor; /* FIXME */ | ||
1917 | state = sta->ampdu_mlme.tid_state_tx[tidno]; | ||
1918 | |||
1919 | if (state & HT_ADDBA_RECEIVED_MSK) { | ||
1920 | txtid->addba_exchangecomplete = 1; | ||
1921 | txtid->addba_exchangeinprogress = 0; | ||
1922 | txtid->baw_size = buffersize; | ||
1923 | |||
1924 | DPRINTF(sc, ATH_DBG_AGGR, | ||
1925 | "%s: Resuming tid, buffersize: %d\n", | ||
1926 | __func__, | ||
1927 | buffersize); | ||
1928 | |||
1929 | ath_tx_resume_tid(sc, txtid); | ||
1930 | } | ||
1931 | } | ||
1932 | |||
1933 | static void ath_get_rate(void *priv, struct net_device *dev, | ||
1934 | struct ieee80211_supported_band *sband, | ||
1935 | struct sk_buff *skb, | ||
1936 | struct rate_selection *sel) | ||
1937 | { | ||
1938 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1939 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1940 | struct sta_info *sta; | ||
1941 | struct ath_softc *sc = (struct ath_softc *)priv; | ||
1942 | struct ieee80211_hw *hw = sc->hw; | ||
1943 | struct ath_tx_info_priv *tx_info_priv; | ||
1944 | struct ath_rate_node *ath_rc_priv; | ||
1945 | struct ath_node *an; | ||
1946 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1947 | int is_probe, chk, ret; | ||
1948 | s8 lowest_idx; | ||
1949 | __le16 fc = hdr->frame_control; | ||
1950 | u8 *qc, tid; | ||
1951 | DECLARE_MAC_BUF(mac); | ||
1952 | |||
1953 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | ||
1954 | |||
1955 | /* allocate driver private area of tx_info */ | ||
1956 | tx_info->driver_data[0] = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); | ||
1957 | ASSERT(tx_info->driver_data[0] != NULL); | ||
1958 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | ||
1959 | |||
1960 | sta = sta_info_get(local, hdr->addr1); | ||
1961 | lowest_idx = rate_lowest_index(local, sband, sta); | ||
1962 | tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; | ||
1963 | /* lowest rate for management and multicast/broadcast frames */ | ||
1964 | if (!ieee80211_is_data(fc) || | ||
1965 | is_multicast_ether_addr(hdr->addr1) || !sta) { | ||
1966 | sel->rate_idx = lowest_idx; | ||
1967 | return; | ||
1968 | } | ||
1969 | |||
1970 | ath_rc_priv = sta->rate_ctrl_priv; | ||
1971 | |||
1972 | /* Find tx rate for unicast frames */ | ||
1973 | ath_rate_findrate(sc, ath_rc_priv, | ||
1974 | ATH_11N_TXMAXTRY, 4, | ||
1975 | ATH_RC_PROBE_ALLOWED, | ||
1976 | tx_info_priv->rcs, | ||
1977 | &is_probe, | ||
1978 | false); | ||
1979 | if (is_probe) | ||
1980 | sel->probe_idx = ((struct ath_tx_ratectrl *) | ||
1981 | sta->rate_ctrl_priv)->probe_rate; | ||
1982 | |||
1983 | /* Ratecontrol sometimes returns invalid rate index */ | ||
1984 | if (tx_info_priv->rcs[0].rix != 0xff) | ||
1985 | ath_rc_priv->prev_data_rix = tx_info_priv->rcs[0].rix; | ||
1986 | else | ||
1987 | tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix; | ||
1988 | |||
1989 | sel->rate_idx = tx_info_priv->rcs[0].rix; | ||
1990 | |||
1991 | /* Check if aggregation has to be enabled for this tid */ | ||
1992 | |||
1993 | if (hw->conf.ht_conf.ht_supported) { | ||
1994 | if (ieee80211_is_data_qos(fc)) { | ||
1995 | qc = ieee80211_get_qos_ctl(hdr); | ||
1996 | tid = qc[0] & 0xf; | ||
1997 | |||
1998 | spin_lock_bh(&sc->node_lock); | ||
1999 | an = ath_node_find(sc, hdr->addr1); | ||
2000 | spin_unlock_bh(&sc->node_lock); | ||
2001 | |||
2002 | if (!an) { | ||
2003 | DPRINTF(sc, ATH_DBG_AGGR, | ||
2004 | "%s: Node not found to " | ||
2005 | "init/chk TX aggr\n", __func__); | ||
2006 | return; | ||
2007 | } | ||
2008 | |||
2009 | chk = ath_tx_aggr_check(sc, an, tid); | ||
2010 | if (chk == AGGR_REQUIRED) { | ||
2011 | ret = ieee80211_start_tx_ba_session(hw, | ||
2012 | hdr->addr1, tid); | ||
2013 | if (ret) | ||
2014 | DPRINTF(sc, ATH_DBG_AGGR, | ||
2015 | "%s: Unable to start tx " | ||
2016 | "aggr for: %s\n", | ||
2017 | __func__, | ||
2018 | print_mac(mac, hdr->addr1)); | ||
2019 | else | ||
2020 | DPRINTF(sc, ATH_DBG_AGGR, | ||
2021 | "%s: Started tx aggr for: %s\n", | ||
2022 | __func__, | ||
2023 | print_mac(mac, hdr->addr1)); | ||
2024 | } else if (chk == AGGR_EXCHANGE_PROGRESS) | ||
2025 | ath_tx_aggr_resp(sc, sta, an, tid); | ||
2026 | } | ||
2027 | } | ||
2028 | } | ||
2029 | |||
2030 | static void ath_rate_init(void *priv, void *priv_sta, | ||
2031 | struct ieee80211_local *local, | ||
2032 | struct sta_info *sta) | ||
2033 | { | ||
2034 | struct ieee80211_supported_band *sband; | ||
2035 | struct ieee80211_hw *hw = local_to_hw(local); | ||
2036 | struct ieee80211_conf *conf = &local->hw.conf; | ||
2037 | struct ath_softc *sc = hw->priv; | ||
2038 | int i, j = 0; | ||
2039 | |||
2040 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | ||
2041 | |||
2042 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
2043 | sta->txrate_idx = rate_lowest_index(local, sband, sta); | ||
2044 | |||
2045 | ath_setup_rates(local, sta); | ||
2046 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | ||
2047 | for (i = 0; i < MCS_SET_SIZE; i++) { | ||
2048 | if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) | ||
2049 | ((struct ath_rate_node *) | ||
2050 | priv_sta)->neg_ht_rates.rs_rates[j++] = i; | ||
2051 | if (j == ATH_RATE_MAX) | ||
2052 | break; | ||
2053 | } | ||
2054 | ((struct ath_rate_node *)priv_sta)->neg_ht_rates.rs_nrates = j; | ||
2055 | } | ||
2056 | ath_rc_node_update(hw, priv_sta); | ||
2057 | } | ||
2058 | |||
2059 | static void ath_rate_clear(void *priv) | ||
2060 | { | ||
2061 | return; | ||
2062 | } | ||
2063 | |||
2064 | static void *ath_rate_alloc(struct ieee80211_local *local) | ||
2065 | { | ||
2066 | struct ieee80211_hw *hw = local_to_hw(local); | ||
2067 | struct ath_softc *sc = hw->priv; | ||
2068 | |||
2069 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | ||
2070 | return local->hw.priv; | ||
2071 | } | ||
2072 | |||
2073 | static void ath_rate_free(void *priv) | ||
2074 | { | ||
2075 | return; | ||
2076 | } | ||
2077 | |||
2078 | static void *ath_rate_alloc_sta(void *priv, gfp_t gfp) | ||
2079 | { | ||
2080 | struct ath_softc *sc = priv; | ||
2081 | struct ath_vap *avp = sc->sc_vaps[0]; | ||
2082 | struct ath_rate_node *rate_priv; | ||
2083 | |||
2084 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | ||
2085 | rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp); | ||
2086 | if (!rate_priv) { | ||
2087 | DPRINTF(sc, ATH_DBG_FATAL, "%s:Unable to allocate" | ||
2088 | "private rate control structure", __func__); | ||
2089 | return NULL; | ||
2090 | } | ||
2091 | ath_rc_sib_init(rate_priv); | ||
2092 | return rate_priv; | ||
2093 | } | ||
2094 | |||
2095 | static void ath_rate_free_sta(void *priv, void *priv_sta) | ||
2096 | { | ||
2097 | struct ath_rate_node *rate_priv = priv_sta; | ||
2098 | struct ath_softc *sc = priv; | ||
2099 | |||
2100 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | ||
2101 | ath_rate_node_free(rate_priv); | ||
2102 | } | ||
2103 | |||
2104 | static struct rate_control_ops ath_rate_ops = { | ||
2105 | .module = NULL, | ||
2106 | .name = "ath9k_rate_control", | ||
2107 | .tx_status = ath_tx_status, | ||
2108 | .get_rate = ath_get_rate, | ||
2109 | .rate_init = ath_rate_init, | ||
2110 | .clear = ath_rate_clear, | ||
2111 | .alloc = ath_rate_alloc, | ||
2112 | .free = ath_rate_free, | ||
2113 | .alloc_sta = ath_rate_alloc_sta, | ||
2114 | .free_sta = ath_rate_free_sta | ||
2115 | }; | ||
2116 | |||
2117 | int ath_rate_control_register(void) | ||
2118 | { | ||
2119 | return ieee80211_rate_control_register(&ath_rate_ops); | ||
2120 | } | ||
2121 | |||
2122 | void ath_rate_control_unregister(void) | ||
2123 | { | ||
2124 | ieee80211_rate_control_unregister(&ath_rate_ops); | ||
2125 | } | ||
2126 | |||
diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h new file mode 100644 index 00000000000..8f6c28e6519 --- /dev/null +++ b/drivers/net/wireless/ath9k/rc.h | |||
@@ -0,0 +1,316 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004 Sam Leffler, Errno Consulting | ||
3 | * Copyright (c) 2004 Video54 Technologies, Inc. | ||
4 | * Copyright (c) 2008 Atheros Communications Inc. | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | #ifndef RC_H | ||
20 | #define RC_H | ||
21 | |||
22 | #include "ath9k.h" | ||
23 | /* | ||
24 | * Interface definitions for transmit rate control modules for the | ||
25 | * Atheros driver. | ||
26 | * | ||
27 | * A rate control module is responsible for choosing the transmit rate | ||
28 | * for each data frame. Management+control frames are always sent at | ||
29 | * a fixed rate. | ||
30 | * | ||
31 | * Only one module may be present at a time; the driver references | ||
32 | * rate control interfaces by symbol name. If multiple modules are | ||
33 | * to be supported we'll need to switch to a registration-based scheme | ||
34 | * as is currently done, for example, for authentication modules. | ||
35 | * | ||
36 | * An instance of the rate control module is attached to each device | ||
37 | * at attach time and detached when the device is destroyed. The module | ||
38 | * may associate data with each device and each node (station). Both | ||
39 | * sets of storage are opaque except for the size of the per-node storage | ||
40 | * which must be provided when the module is attached. | ||
41 | * | ||
42 | * The rate control module is notified for each state transition and | ||
43 | * station association/reassociation. Otherwise it is queried for a | ||
44 | * rate for each outgoing frame and provided status from each transmitted | ||
45 | * frame. Any ancillary processing is the responsibility of the module | ||
46 | * (e.g. if periodic processing is required then the module should setup | ||
47 | * it's own timer). | ||
48 | * | ||
49 | * In addition to the transmit rate for each frame the module must also | ||
50 | * indicate the number of attempts to make at the specified rate. If this | ||
51 | * number is != ATH_TXMAXTRY then an additional callback is made to setup | ||
52 | * additional transmit state. The rate control code is assumed to write | ||
53 | * this additional data directly to the transmit descriptor. | ||
54 | */ | ||
55 | |||
56 | struct ath_softc; | ||
57 | |||
58 | #define TRUE 1 | ||
59 | #define FALSE 0 | ||
60 | |||
61 | #define ATH_RATE_MAX 30 | ||
62 | #define MCS_SET_SIZE 128 | ||
63 | |||
64 | enum ieee80211_fixed_rate_mode { | ||
65 | IEEE80211_FIXED_RATE_NONE = 0, | ||
66 | IEEE80211_FIXED_RATE_MCS = 1 /* HT rates */ | ||
67 | }; | ||
68 | |||
69 | /* | ||
70 | * Use the hal os glue code to get ms time | ||
71 | */ | ||
72 | #define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8))) | ||
73 | |||
74 | #define SHORT_PRE 1 | ||
75 | #define LONG_PRE 0 | ||
76 | |||
77 | #define WLAN_PHY_HT_20_SS WLAN_RC_PHY_HT_20_SS | ||
78 | #define WLAN_PHY_HT_20_DS WLAN_RC_PHY_HT_20_DS | ||
79 | #define WLAN_PHY_HT_20_DS_HGI WLAN_RC_PHY_HT_20_DS_HGI | ||
80 | #define WLAN_PHY_HT_40_SS WLAN_RC_PHY_HT_40_SS | ||
81 | #define WLAN_PHY_HT_40_SS_HGI WLAN_RC_PHY_HT_40_SS_HGI | ||
82 | #define WLAN_PHY_HT_40_DS WLAN_RC_PHY_HT_40_DS | ||
83 | #define WLAN_PHY_HT_40_DS_HGI WLAN_RC_PHY_HT_40_DS_HGI | ||
84 | |||
85 | #define WLAN_PHY_OFDM PHY_OFDM | ||
86 | #define WLAN_PHY_CCK PHY_CCK | ||
87 | |||
88 | #define TRUE_20 0x2 | ||
89 | #define TRUE_40 0x4 | ||
90 | #define TRUE_2040 (TRUE_20|TRUE_40) | ||
91 | #define TRUE_ALL (TRUE_2040|TRUE) | ||
92 | |||
93 | enum { | ||
94 | WLAN_RC_PHY_HT_20_SS = 4, | ||
95 | WLAN_RC_PHY_HT_20_DS, | ||
96 | WLAN_RC_PHY_HT_40_SS, | ||
97 | WLAN_RC_PHY_HT_40_DS, | ||
98 | WLAN_RC_PHY_HT_20_SS_HGI, | ||
99 | WLAN_RC_PHY_HT_20_DS_HGI, | ||
100 | WLAN_RC_PHY_HT_40_SS_HGI, | ||
101 | WLAN_RC_PHY_HT_40_DS_HGI, | ||
102 | WLAN_RC_PHY_MAX | ||
103 | }; | ||
104 | |||
105 | #define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ | ||
106 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ | ||
107 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ | ||
108 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) | ||
109 | #define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ | ||
110 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ | ||
111 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ | ||
112 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) | ||
113 | #define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ | ||
114 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ | ||
115 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ | ||
116 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) | ||
117 | |||
118 | #define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) | ||
119 | |||
120 | /* Returns the capflag mode */ | ||
121 | #define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \ | ||
122 | (capflag & WLAN_RC_40_FLAG) ? TRUE_40 : TRUE_20 : TRUE)) | ||
123 | |||
124 | /* Return TRUE if flag supports HT20 && client supports HT20 or | ||
125 | * return TRUE if flag supports HT40 && client supports HT40. | ||
126 | * This is used becos some rates overlap between HT20/HT40. | ||
127 | */ | ||
128 | |||
129 | #define WLAN_RC_PHY_HT_VALID(flag, capflag) (((flag & TRUE_20) && !(capflag \ | ||
130 | & WLAN_RC_40_FLAG)) || ((flag & TRUE_40) && \ | ||
131 | (capflag & WLAN_RC_40_FLAG))) | ||
132 | |||
133 | #define WLAN_RC_DS_FLAG (0x01) | ||
134 | #define WLAN_RC_40_FLAG (0x02) | ||
135 | #define WLAN_RC_SGI_FLAG (0x04) | ||
136 | #define WLAN_RC_HT_FLAG (0x08) | ||
137 | |||
138 | /* Index into the rate table */ | ||
139 | #define INIT_RATE_MAX_20 23 | ||
140 | #define INIT_RATE_MAX_40 40 | ||
141 | |||
142 | #define RATE_TABLE_SIZE 64 | ||
143 | |||
144 | /* XXX: Convert to kdoc */ | ||
145 | struct ath_rate_table { | ||
146 | int rate_cnt; | ||
147 | struct { | ||
148 | int valid; /* Valid for use in rate control */ | ||
149 | int valid_single_stream;/* Valid for use in rate control | ||
150 | for single stream operation */ | ||
151 | u8 phy; /* CCK/OFDM/TURBO/XR */ | ||
152 | u32 ratekbps; /* Rate in Kbits per second */ | ||
153 | u32 user_ratekbps; /* User rate in KBits per second */ | ||
154 | u8 ratecode; /* rate that goes into | ||
155 | hw descriptors */ | ||
156 | u8 short_preamble; /* Mask for enabling short preamble | ||
157 | in rate code for CCK */ | ||
158 | u8 dot11rate; /* Value that goes into supported | ||
159 | rates info element of MLME */ | ||
160 | u8 ctrl_rate; /* Index of next lower basic rate, | ||
161 | used for duration computation */ | ||
162 | int8_t rssi_ack_validmin; /* Rate control related */ | ||
163 | int8_t rssi_ack_deltamin; /* Rate control related */ | ||
164 | u8 base_index; /* base rate index */ | ||
165 | u8 cw40index; /* 40cap rate index */ | ||
166 | u8 sgi_index; /* shortgi rate index */ | ||
167 | u8 ht_index; /* shortgi rate index */ | ||
168 | u32 max_4ms_framelen; /* Maximum frame length(bytes) | ||
169 | for 4ms tx duration */ | ||
170 | } info[RATE_TABLE_SIZE]; | ||
171 | u32 probe_interval; /* interval for ratectrl to | ||
172 | probe for other rates */ | ||
173 | u32 rssi_reduce_interval; /* interval for ratectrl | ||
174 | to reduce RSSI */ | ||
175 | u8 initial_ratemax; /* the initial ratemax value used | ||
176 | in ath_rc_sib_update() */ | ||
177 | }; | ||
178 | |||
179 | #define ATH_RC_PROBE_ALLOWED 0x00000001 | ||
180 | #define ATH_RC_MINRATE_LASTRATE 0x00000002 | ||
181 | #define ATH_RC_SHORT_PREAMBLE 0x00000004 | ||
182 | |||
183 | struct ath_rc_series { | ||
184 | u8 rix; | ||
185 | u8 tries; | ||
186 | u8 flags; | ||
187 | u32 max_4ms_framelen; | ||
188 | }; | ||
189 | |||
190 | /* rcs_flags definition */ | ||
191 | #define ATH_RC_DS_FLAG 0x01 | ||
192 | #define ATH_RC_CW40_FLAG 0x02 /* CW 40 */ | ||
193 | #define ATH_RC_SGI_FLAG 0x04 /* Short Guard Interval */ | ||
194 | #define ATH_RC_HT_FLAG 0x08 /* HT */ | ||
195 | #define ATH_RC_RTSCTS_FLAG 0x10 /* RTS-CTS */ | ||
196 | |||
197 | /* | ||
198 | * State structures for new rate adaptation code | ||
199 | */ | ||
200 | #define MAX_TX_RATE_TBL 64 | ||
201 | #define MAX_TX_RATE_PHY 48 | ||
202 | |||
203 | struct ath_tx_ratectrl_state { | ||
204 | int8_t rssi_thres; /* required rssi for this rate (dB) */ | ||
205 | u8 per; /* recent estimate of packet error rate (%) */ | ||
206 | }; | ||
207 | |||
208 | struct ath_tx_ratectrl { | ||
209 | struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL]; /* state */ | ||
210 | int8_t rssi_last; /* last ack rssi */ | ||
211 | int8_t rssi_last_lookup; /* last ack rssi used for lookup */ | ||
212 | int8_t rssi_last_prev; /* previous last ack rssi */ | ||
213 | int8_t rssi_last_prev2; /* 2nd previous last ack rssi */ | ||
214 | int32_t rssi_sum_cnt; /* count of rssi_sum for averaging */ | ||
215 | int32_t rssi_sum_rate; /* rate that we are averaging */ | ||
216 | int32_t rssi_sum; /* running sum of rssi for averaging */ | ||
217 | u32 valid_txrate_mask; /* mask of valid rates */ | ||
218 | u8 rate_table_size; /* rate table size */ | ||
219 | u8 rate_max; /* max rate that has recently worked */ | ||
220 | u8 probe_rate; /* rate we are probing at */ | ||
221 | u32 rssi_time; /* msec timestamp for last ack rssi */ | ||
222 | u32 rssi_down_time; /* msec timestamp for last down step */ | ||
223 | u32 probe_time; /* msec timestamp for last probe */ | ||
224 | u8 hw_maxretry_pktcnt; /* num packets since we got | ||
225 | HW max retry error */ | ||
226 | u8 max_valid_rate; /* maximum number of valid rate */ | ||
227 | u8 valid_rate_index[MAX_TX_RATE_TBL]; /* valid rate index */ | ||
228 | u32 per_down_time; /* msec timstamp for last | ||
229 | PER down step */ | ||
230 | |||
231 | /* 11n state */ | ||
232 | u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; /* valid rate count */ | ||
233 | u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL]; | ||
234 | u8 rc_phy_mode; | ||
235 | u8 rate_max_phy; /* Phy index for the max rate */ | ||
236 | u32 rate_max_lastused; /* msec timstamp of when we | ||
237 | last used rateMaxPhy */ | ||
238 | u32 probe_interval; /* interval for ratectrl to probe | ||
239 | for other rates */ | ||
240 | }; | ||
241 | |||
242 | struct ath_rateset { | ||
243 | u8 rs_nrates; | ||
244 | u8 rs_rates[ATH_RATE_MAX]; | ||
245 | }; | ||
246 | |||
247 | /* per-device state */ | ||
248 | struct ath_rate_softc { | ||
249 | /* phy tables that contain rate control data */ | ||
250 | const void *hw_rate_table[WIRELESS_MODE_MAX]; | ||
251 | int fixedrix; /* -1 or index of fixed rate */ | ||
252 | }; | ||
253 | |||
254 | /* per-node state */ | ||
255 | struct ath_rate_node { | ||
256 | struct ath_tx_ratectrl tx_ratectrl; /* rate control state proper */ | ||
257 | u32 prev_data_rix; /* rate idx of last data frame */ | ||
258 | |||
259 | /* map of rate ix -> negotiated rate set ix */ | ||
260 | u8 rixmap[MAX_TX_RATE_TBL]; | ||
261 | |||
262 | /* map of ht rate ix -> negotiated rate set ix */ | ||
263 | u8 ht_rixmap[MAX_TX_RATE_TBL]; | ||
264 | |||
265 | u8 ht_cap; /* ht capabilities */ | ||
266 | u8 ant_tx; /* current transmit antenna */ | ||
267 | |||
268 | u8 single_stream; /* When TRUE, only single | ||
269 | stream Tx possible */ | ||
270 | struct ath_rateset neg_rates; /* Negotiated rates */ | ||
271 | struct ath_rateset neg_ht_rates; /* Negotiated HT rates */ | ||
272 | struct ath_rate_softc *asc; /* back pointer to atheros softc */ | ||
273 | struct ath_vap *avp; /* back pointer to vap */ | ||
274 | }; | ||
275 | |||
276 | /* Driver data of ieee80211_tx_info */ | ||
277 | struct ath_tx_info_priv { | ||
278 | struct ath_rc_series rcs[4]; | ||
279 | struct ath_tx_status tx; | ||
280 | int n_frames; | ||
281 | int n_bad_frames; | ||
282 | u8 min_rate; | ||
283 | }; | ||
284 | |||
285 | /* | ||
286 | * Attach/detach a rate control module. | ||
287 | */ | ||
288 | struct ath_rate_softc *ath_rate_attach(struct ath_hal *ah); | ||
289 | void ath_rate_detach(struct ath_rate_softc *asc); | ||
290 | |||
291 | /* | ||
292 | * Update/reset rate control state for 802.11 state transitions. | ||
293 | * Important mostly as the analog to ath_rate_newassoc when operating | ||
294 | * in station mode. | ||
295 | */ | ||
296 | void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv); | ||
297 | void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp); | ||
298 | |||
299 | /* | ||
300 | * Return the tx rate series. | ||
301 | */ | ||
302 | void ath_rate_findrate(struct ath_softc *sc, struct ath_rate_node *ath_rc_priv, | ||
303 | int num_tries, int num_rates, | ||
304 | unsigned int rcflag, struct ath_rc_series[], | ||
305 | int *is_probe, int isretry); | ||
306 | /* | ||
307 | * Return rate index for given Dot11 Rate. | ||
308 | */ | ||
309 | u8 ath_rate_findrateix(struct ath_softc *sc, | ||
310 | u8 dot11_rate); | ||
311 | |||
312 | /* Routines to register/unregister rate control algorithm */ | ||
313 | int ath_rate_control_register(void); | ||
314 | void ath_rate_control_unregister(void); | ||
315 | |||
316 | #endif /* RC_H */ | ||
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c new file mode 100644 index 00000000000..8e14e643e99 --- /dev/null +++ b/drivers/net/wireless/ath9k/recv.c | |||
@@ -0,0 +1,1318 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* | ||
18 | * Implementation of receive path. | ||
19 | */ | ||
20 | |||
21 | #include "core.h" | ||
22 | |||
23 | /* | ||
24 | * Setup and link descriptors. | ||
25 | * | ||
26 | * 11N: we can no longer afford to self link the last descriptor. | ||
27 | * MAC acknowledges BA status as long as it copies frames to host | ||
28 | * buffer (or rx fifo). This can incorrectly acknowledge packets | ||
29 | * to a sender if last desc is self-linked. | ||
30 | * | ||
31 | * NOTE: Caller should hold the rxbuf lock. | ||
32 | */ | ||
33 | |||
34 | static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | ||
35 | { | ||
36 | struct ath_hal *ah = sc->sc_ah; | ||
37 | struct ath_desc *ds; | ||
38 | struct sk_buff *skb; | ||
39 | |||
40 | ATH_RXBUF_RESET(bf); | ||
41 | |||
42 | ds = bf->bf_desc; | ||
43 | ds->ds_link = 0; /* link to null */ | ||
44 | ds->ds_data = bf->bf_buf_addr; | ||
45 | |||
46 | /* XXX For RADAR? | ||
47 | * virtual addr of the beginning of the buffer. */ | ||
48 | skb = bf->bf_mpdu; | ||
49 | ASSERT(skb != NULL); | ||
50 | ds->ds_vdata = skb->data; | ||
51 | |||
52 | /* setup rx descriptors */ | ||
53 | ath9k_hw_setuprxdesc(ah, | ||
54 | ds, | ||
55 | skb_tailroom(skb), /* buffer size */ | ||
56 | 0); | ||
57 | |||
58 | if (sc->sc_rxlink == NULL) | ||
59 | ath9k_hw_putrxbuf(ah, bf->bf_daddr); | ||
60 | else | ||
61 | *sc->sc_rxlink = bf->bf_daddr; | ||
62 | |||
63 | sc->sc_rxlink = &ds->ds_link; | ||
64 | ath9k_hw_rxena(ah); | ||
65 | } | ||
66 | |||
67 | /* Process received BAR frame */ | ||
68 | |||
69 | static int ath_bar_rx(struct ath_softc *sc, | ||
70 | struct ath_node *an, | ||
71 | struct sk_buff *skb) | ||
72 | { | ||
73 | struct ieee80211_bar *bar; | ||
74 | struct ath_arx_tid *rxtid; | ||
75 | struct sk_buff *tskb; | ||
76 | struct ath_recv_status *rx_status; | ||
77 | int tidno, index, cindex; | ||
78 | u16 seqno; | ||
79 | |||
80 | /* look at BAR contents */ | ||
81 | |||
82 | bar = (struct ieee80211_bar *)skb->data; | ||
83 | tidno = (le16_to_cpu(bar->control) & IEEE80211_BAR_CTL_TID_M) | ||
84 | >> IEEE80211_BAR_CTL_TID_S; | ||
85 | seqno = le16_to_cpu(bar->start_seq_num) >> IEEE80211_SEQ_SEQ_SHIFT; | ||
86 | |||
87 | /* process BAR - indicate all pending RX frames till the BAR seqno */ | ||
88 | |||
89 | rxtid = &an->an_aggr.rx.tid[tidno]; | ||
90 | |||
91 | spin_lock_bh(&rxtid->tidlock); | ||
92 | |||
93 | /* get relative index */ | ||
94 | |||
95 | index = ATH_BA_INDEX(rxtid->seq_next, seqno); | ||
96 | |||
97 | /* drop BAR if old sequence (index is too large) */ | ||
98 | |||
99 | if ((index > rxtid->baw_size) && | ||
100 | (index > (IEEE80211_SEQ_MAX - (rxtid->baw_size << 2)))) | ||
101 | /* discard frame, ieee layer may not treat frame as a dup */ | ||
102 | goto unlock_and_free; | ||
103 | |||
104 | /* complete receive processing for all pending frames upto BAR seqno */ | ||
105 | |||
106 | cindex = (rxtid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | ||
107 | while ((rxtid->baw_head != rxtid->baw_tail) && | ||
108 | (rxtid->baw_head != cindex)) { | ||
109 | tskb = rxtid->rxbuf[rxtid->baw_head].rx_wbuf; | ||
110 | rx_status = &rxtid->rxbuf[rxtid->baw_head].rx_status; | ||
111 | rxtid->rxbuf[rxtid->baw_head].rx_wbuf = NULL; | ||
112 | |||
113 | if (tskb != NULL) | ||
114 | ath_rx_subframe(an, tskb, rx_status); | ||
115 | |||
116 | INCR(rxtid->baw_head, ATH_TID_MAX_BUFS); | ||
117 | INCR(rxtid->seq_next, IEEE80211_SEQ_MAX); | ||
118 | } | ||
119 | |||
120 | /* ... and indicate rest of the frames in-order */ | ||
121 | |||
122 | while (rxtid->baw_head != rxtid->baw_tail && | ||
123 | rxtid->rxbuf[rxtid->baw_head].rx_wbuf != NULL) { | ||
124 | tskb = rxtid->rxbuf[rxtid->baw_head].rx_wbuf; | ||
125 | rx_status = &rxtid->rxbuf[rxtid->baw_head].rx_status; | ||
126 | rxtid->rxbuf[rxtid->baw_head].rx_wbuf = NULL; | ||
127 | |||
128 | ath_rx_subframe(an, tskb, rx_status); | ||
129 | |||
130 | INCR(rxtid->baw_head, ATH_TID_MAX_BUFS); | ||
131 | INCR(rxtid->seq_next, IEEE80211_SEQ_MAX); | ||
132 | } | ||
133 | |||
134 | unlock_and_free: | ||
135 | spin_unlock_bh(&rxtid->tidlock); | ||
136 | /* free bar itself */ | ||
137 | dev_kfree_skb(skb); | ||
138 | return IEEE80211_FTYPE_CTL; | ||
139 | } | ||
140 | |||
141 | /* Function to handle a subframe of aggregation when HT is enabled */ | ||
142 | |||
143 | static int ath_ampdu_input(struct ath_softc *sc, | ||
144 | struct ath_node *an, | ||
145 | struct sk_buff *skb, | ||
146 | struct ath_recv_status *rx_status) | ||
147 | { | ||
148 | struct ieee80211_hdr *hdr; | ||
149 | struct ath_arx_tid *rxtid; | ||
150 | struct ath_rxbuf *rxbuf; | ||
151 | u8 type, subtype; | ||
152 | u16 rxseq; | ||
153 | int tid = 0, index, cindex, rxdiff; | ||
154 | __le16 fc; | ||
155 | u8 *qc; | ||
156 | |||
157 | hdr = (struct ieee80211_hdr *)skb->data; | ||
158 | fc = hdr->frame_control; | ||
159 | |||
160 | /* collect stats of frames with non-zero version */ | ||
161 | |||
162 | if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_VERS) != 0) { | ||
163 | dev_kfree_skb(skb); | ||
164 | return -1; | ||
165 | } | ||
166 | |||
167 | type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; | ||
168 | subtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE; | ||
169 | |||
170 | if (ieee80211_is_back_req(fc)) | ||
171 | return ath_bar_rx(sc, an, skb); | ||
172 | |||
173 | /* special aggregate processing only for qos unicast data frames */ | ||
174 | |||
175 | if (!ieee80211_is_data(fc) || | ||
176 | !ieee80211_is_data_qos(fc) || | ||
177 | is_multicast_ether_addr(hdr->addr1)) | ||
178 | return ath_rx_subframe(an, skb, rx_status); | ||
179 | |||
180 | /* lookup rx tid state */ | ||
181 | |||
182 | if (ieee80211_is_data_qos(fc)) { | ||
183 | qc = ieee80211_get_qos_ctl(hdr); | ||
184 | tid = qc[0] & 0xf; | ||
185 | } | ||
186 | |||
187 | if (sc->sc_opmode == ATH9K_M_STA) { | ||
188 | /* Drop the frame not belonging to me. */ | ||
189 | if (memcmp(hdr->addr1, sc->sc_myaddr, ETH_ALEN)) { | ||
190 | dev_kfree_skb(skb); | ||
191 | return -1; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | rxtid = &an->an_aggr.rx.tid[tid]; | ||
196 | |||
197 | spin_lock(&rxtid->tidlock); | ||
198 | |||
199 | rxdiff = (rxtid->baw_tail - rxtid->baw_head) & | ||
200 | (ATH_TID_MAX_BUFS - 1); | ||
201 | |||
202 | /* | ||
203 | * If the ADDBA exchange has not been completed by the source, | ||
204 | * process via legacy path (i.e. no reordering buffer is needed) | ||
205 | */ | ||
206 | if (!rxtid->addba_exchangecomplete) { | ||
207 | spin_unlock(&rxtid->tidlock); | ||
208 | return ath_rx_subframe(an, skb, rx_status); | ||
209 | } | ||
210 | |||
211 | /* extract sequence number from recvd frame */ | ||
212 | |||
213 | rxseq = le16_to_cpu(hdr->seq_ctrl) >> IEEE80211_SEQ_SEQ_SHIFT; | ||
214 | |||
215 | if (rxtid->seq_reset) { | ||
216 | rxtid->seq_reset = 0; | ||
217 | rxtid->seq_next = rxseq; | ||
218 | } | ||
219 | |||
220 | index = ATH_BA_INDEX(rxtid->seq_next, rxseq); | ||
221 | |||
222 | /* drop frame if old sequence (index is too large) */ | ||
223 | |||
224 | if (index > (IEEE80211_SEQ_MAX - (rxtid->baw_size << 2))) { | ||
225 | /* discard frame, ieee layer may not treat frame as a dup */ | ||
226 | spin_unlock(&rxtid->tidlock); | ||
227 | dev_kfree_skb(skb); | ||
228 | return IEEE80211_FTYPE_DATA; | ||
229 | } | ||
230 | |||
231 | /* sequence number is beyond block-ack window */ | ||
232 | |||
233 | if (index >= rxtid->baw_size) { | ||
234 | |||
235 | /* complete receive processing for all pending frames */ | ||
236 | |||
237 | while (index >= rxtid->baw_size) { | ||
238 | |||
239 | rxbuf = rxtid->rxbuf + rxtid->baw_head; | ||
240 | |||
241 | if (rxbuf->rx_wbuf != NULL) { | ||
242 | ath_rx_subframe(an, rxbuf->rx_wbuf, | ||
243 | &rxbuf->rx_status); | ||
244 | rxbuf->rx_wbuf = NULL; | ||
245 | } | ||
246 | |||
247 | INCR(rxtid->baw_head, ATH_TID_MAX_BUFS); | ||
248 | INCR(rxtid->seq_next, IEEE80211_SEQ_MAX); | ||
249 | |||
250 | index--; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | /* add buffer to the recv ba window */ | ||
255 | |||
256 | cindex = (rxtid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | ||
257 | rxbuf = rxtid->rxbuf + cindex; | ||
258 | |||
259 | if (rxbuf->rx_wbuf != NULL) { | ||
260 | spin_unlock(&rxtid->tidlock); | ||
261 | /* duplicate frame */ | ||
262 | dev_kfree_skb(skb); | ||
263 | return IEEE80211_FTYPE_DATA; | ||
264 | } | ||
265 | |||
266 | rxbuf->rx_wbuf = skb; | ||
267 | rxbuf->rx_time = get_timestamp(); | ||
268 | rxbuf->rx_status = *rx_status; | ||
269 | |||
270 | /* advance tail if sequence received is newer | ||
271 | * than any received so far */ | ||
272 | |||
273 | if (index >= rxdiff) { | ||
274 | rxtid->baw_tail = cindex; | ||
275 | INCR(rxtid->baw_tail, ATH_TID_MAX_BUFS); | ||
276 | } | ||
277 | |||
278 | /* indicate all in-order received frames */ | ||
279 | |||
280 | while (rxtid->baw_head != rxtid->baw_tail) { | ||
281 | rxbuf = rxtid->rxbuf + rxtid->baw_head; | ||
282 | if (!rxbuf->rx_wbuf) | ||
283 | break; | ||
284 | |||
285 | ath_rx_subframe(an, rxbuf->rx_wbuf, &rxbuf->rx_status); | ||
286 | rxbuf->rx_wbuf = NULL; | ||
287 | |||
288 | INCR(rxtid->baw_head, ATH_TID_MAX_BUFS); | ||
289 | INCR(rxtid->seq_next, IEEE80211_SEQ_MAX); | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * start a timer to flush all received frames if there are pending | ||
294 | * receive frames | ||
295 | */ | ||
296 | if (rxtid->baw_head != rxtid->baw_tail) | ||
297 | mod_timer(&rxtid->timer, ATH_RX_TIMEOUT); | ||
298 | else | ||
299 | del_timer_sync(&rxtid->timer); | ||
300 | |||
301 | spin_unlock(&rxtid->tidlock); | ||
302 | return IEEE80211_FTYPE_DATA; | ||
303 | } | ||
304 | |||
305 | /* Timer to flush all received sub-frames */ | ||
306 | |||
307 | static void ath_rx_timer(unsigned long data) | ||
308 | { | ||
309 | struct ath_arx_tid *rxtid = (struct ath_arx_tid *)data; | ||
310 | struct ath_node *an = rxtid->an; | ||
311 | struct ath_rxbuf *rxbuf; | ||
312 | int nosched; | ||
313 | |||
314 | spin_lock_bh(&rxtid->tidlock); | ||
315 | while (rxtid->baw_head != rxtid->baw_tail) { | ||
316 | rxbuf = rxtid->rxbuf + rxtid->baw_head; | ||
317 | if (!rxbuf->rx_wbuf) { | ||
318 | INCR(rxtid->baw_head, ATH_TID_MAX_BUFS); | ||
319 | INCR(rxtid->seq_next, IEEE80211_SEQ_MAX); | ||
320 | continue; | ||
321 | } | ||
322 | |||
323 | /* | ||
324 | * Stop if the next one is a very recent frame. | ||
325 | * | ||
326 | * Call get_timestamp in every iteration to protect against the | ||
327 | * case in which a new frame is received while we are executing | ||
328 | * this function. Using a timestamp obtained before entering | ||
329 | * the loop could lead to a very large time interval | ||
330 | * (a negative value typecast to unsigned), breaking the | ||
331 | * function's logic. | ||
332 | */ | ||
333 | if ((get_timestamp() - rxbuf->rx_time) < | ||
334 | (ATH_RX_TIMEOUT * HZ / 1000)) | ||
335 | break; | ||
336 | |||
337 | ath_rx_subframe(an, rxbuf->rx_wbuf, | ||
338 | &rxbuf->rx_status); | ||
339 | rxbuf->rx_wbuf = NULL; | ||
340 | |||
341 | INCR(rxtid->baw_head, ATH_TID_MAX_BUFS); | ||
342 | INCR(rxtid->seq_next, IEEE80211_SEQ_MAX); | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * start a timer to flush all received frames if there are pending | ||
347 | * receive frames | ||
348 | */ | ||
349 | if (rxtid->baw_head != rxtid->baw_tail) | ||
350 | nosched = 0; | ||
351 | else | ||
352 | nosched = 1; /* no need to re-arm the timer again */ | ||
353 | |||
354 | spin_unlock_bh(&rxtid->tidlock); | ||
355 | } | ||
356 | |||
357 | /* Free all pending sub-frames in the re-ordering buffer */ | ||
358 | |||
359 | static void ath_rx_flush_tid(struct ath_softc *sc, | ||
360 | struct ath_arx_tid *rxtid, int drop) | ||
361 | { | ||
362 | struct ath_rxbuf *rxbuf; | ||
363 | |||
364 | spin_lock_bh(&rxtid->tidlock); | ||
365 | while (rxtid->baw_head != rxtid->baw_tail) { | ||
366 | rxbuf = rxtid->rxbuf + rxtid->baw_head; | ||
367 | if (!rxbuf->rx_wbuf) { | ||
368 | INCR(rxtid->baw_head, ATH_TID_MAX_BUFS); | ||
369 | INCR(rxtid->seq_next, IEEE80211_SEQ_MAX); | ||
370 | continue; | ||
371 | } | ||
372 | |||
373 | if (drop) | ||
374 | dev_kfree_skb(rxbuf->rx_wbuf); | ||
375 | else | ||
376 | ath_rx_subframe(rxtid->an, | ||
377 | rxbuf->rx_wbuf, | ||
378 | &rxbuf->rx_status); | ||
379 | |||
380 | rxbuf->rx_wbuf = NULL; | ||
381 | |||
382 | INCR(rxtid->baw_head, ATH_TID_MAX_BUFS); | ||
383 | INCR(rxtid->seq_next, IEEE80211_SEQ_MAX); | ||
384 | } | ||
385 | spin_unlock_bh(&rxtid->tidlock); | ||
386 | } | ||
387 | |||
388 | static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, | ||
389 | u32 len) | ||
390 | { | ||
391 | struct sk_buff *skb; | ||
392 | u32 off; | ||
393 | |||
394 | /* | ||
395 | * Cache-line-align. This is important (for the | ||
396 | * 5210 at least) as not doing so causes bogus data | ||
397 | * in rx'd frames. | ||
398 | */ | ||
399 | |||
400 | skb = dev_alloc_skb(len + sc->sc_cachelsz - 1); | ||
401 | if (skb != NULL) { | ||
402 | off = ((unsigned long) skb->data) % sc->sc_cachelsz; | ||
403 | if (off != 0) | ||
404 | skb_reserve(skb, sc->sc_cachelsz - off); | ||
405 | } else { | ||
406 | DPRINTF(sc, ATH_DBG_FATAL, | ||
407 | "%s: skbuff alloc of size %u failed\n", | ||
408 | __func__, len); | ||
409 | return NULL; | ||
410 | } | ||
411 | |||
412 | return skb; | ||
413 | } | ||
414 | |||
415 | static void ath_rx_requeue(struct ath_softc *sc, struct sk_buff *skb) | ||
416 | { | ||
417 | struct ath_buf *bf = ATH_RX_CONTEXT(skb)->ctx_rxbuf; | ||
418 | |||
419 | ASSERT(bf != NULL); | ||
420 | |||
421 | spin_lock_bh(&sc->sc_rxbuflock); | ||
422 | if (bf->bf_status & ATH_BUFSTATUS_STALE) { | ||
423 | /* | ||
424 | * This buffer is still held for hw acess. | ||
425 | * Mark it as free to be re-queued it later. | ||
426 | */ | ||
427 | bf->bf_status |= ATH_BUFSTATUS_FREE; | ||
428 | } else { | ||
429 | /* XXX: we probably never enter here, remove after | ||
430 | * verification */ | ||
431 | list_add_tail(&bf->list, &sc->sc_rxbuf); | ||
432 | ath_rx_buf_link(sc, bf); | ||
433 | } | ||
434 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
435 | } | ||
436 | |||
437 | /* | ||
438 | * The skb indicated to upper stack won't be returned to us. | ||
439 | * So we have to allocate a new one and queue it by ourselves. | ||
440 | */ | ||
441 | static int ath_rx_indicate(struct ath_softc *sc, | ||
442 | struct sk_buff *skb, | ||
443 | struct ath_recv_status *status, | ||
444 | u16 keyix) | ||
445 | { | ||
446 | struct ath_buf *bf = ATH_RX_CONTEXT(skb)->ctx_rxbuf; | ||
447 | struct sk_buff *nskb; | ||
448 | int type; | ||
449 | |||
450 | /* indicate frame to the stack, which will free the old skb. */ | ||
451 | type = ath__rx_indicate(sc, skb, status, keyix); | ||
452 | |||
453 | /* allocate a new skb and queue it to for H/W processing */ | ||
454 | nskb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize); | ||
455 | if (nskb != NULL) { | ||
456 | bf->bf_mpdu = nskb; | ||
457 | bf->bf_buf_addr = ath_skb_map_single(sc, | ||
458 | nskb, | ||
459 | PCI_DMA_FROMDEVICE, | ||
460 | /* XXX: Remove get_dma_mem_context() */ | ||
461 | get_dma_mem_context(bf, bf_dmacontext)); | ||
462 | ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf; | ||
463 | |||
464 | /* queue the new wbuf to H/W */ | ||
465 | ath_rx_requeue(sc, nskb); | ||
466 | } | ||
467 | |||
468 | return type; | ||
469 | } | ||
470 | |||
471 | static void ath_opmode_init(struct ath_softc *sc) | ||
472 | { | ||
473 | struct ath_hal *ah = sc->sc_ah; | ||
474 | u32 rfilt, mfilt[2]; | ||
475 | |||
476 | /* configure rx filter */ | ||
477 | rfilt = ath_calcrxfilter(sc); | ||
478 | ath9k_hw_setrxfilter(ah, rfilt); | ||
479 | |||
480 | /* configure bssid mask */ | ||
481 | if (ah->ah_caps.halBssIdMaskSupport) | ||
482 | ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); | ||
483 | |||
484 | /* configure operational mode */ | ||
485 | ath9k_hw_setopmode(ah); | ||
486 | |||
487 | /* Handle any link-level address change. */ | ||
488 | ath9k_hw_setmac(ah, sc->sc_myaddr); | ||
489 | |||
490 | /* calculate and install multicast filter */ | ||
491 | mfilt[0] = mfilt[1] = ~0; | ||
492 | |||
493 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | ||
494 | DPRINTF(sc, ATH_DBG_CONFIG , | ||
495 | "%s: RX filter 0x%x, MC filter %08x:%08x\n", | ||
496 | __func__, rfilt, mfilt[0], mfilt[1]); | ||
497 | } | ||
498 | |||
499 | int ath_rx_init(struct ath_softc *sc, int nbufs) | ||
500 | { | ||
501 | struct sk_buff *skb; | ||
502 | struct ath_buf *bf; | ||
503 | int error = 0; | ||
504 | |||
505 | do { | ||
506 | spin_lock_init(&sc->sc_rxflushlock); | ||
507 | sc->sc_rxflush = 0; | ||
508 | spin_lock_init(&sc->sc_rxbuflock); | ||
509 | |||
510 | /* | ||
511 | * Cisco's VPN software requires that drivers be able to | ||
512 | * receive encapsulated frames that are larger than the MTU. | ||
513 | * Since we can't be sure how large a frame we'll get, setup | ||
514 | * to handle the larges on possible. | ||
515 | */ | ||
516 | sc->sc_rxbufsize = roundup(IEEE80211_MAX_MPDU_LEN, | ||
517 | min(sc->sc_cachelsz, | ||
518 | (u16)64)); | ||
519 | |||
520 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: cachelsz %u rxbufsize %u\n", | ||
521 | __func__, sc->sc_cachelsz, sc->sc_rxbufsize); | ||
522 | |||
523 | /* Initialize rx descriptors */ | ||
524 | |||
525 | error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf, | ||
526 | "rx", nbufs, 1); | ||
527 | if (error != 0) { | ||
528 | DPRINTF(sc, ATH_DBG_FATAL, | ||
529 | "%s: failed to allocate rx descriptors: %d\n", | ||
530 | __func__, error); | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | /* Pre-allocate a wbuf for each rx buffer */ | ||
535 | |||
536 | list_for_each_entry(bf, &sc->sc_rxbuf, list) { | ||
537 | skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize); | ||
538 | if (skb == NULL) { | ||
539 | error = -ENOMEM; | ||
540 | break; | ||
541 | } | ||
542 | |||
543 | bf->bf_mpdu = skb; | ||
544 | bf->bf_buf_addr = | ||
545 | ath_skb_map_single(sc, skb, PCI_DMA_FROMDEVICE, | ||
546 | get_dma_mem_context(bf, bf_dmacontext)); | ||
547 | ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf; | ||
548 | } | ||
549 | sc->sc_rxlink = NULL; | ||
550 | |||
551 | } while (0); | ||
552 | |||
553 | if (error) | ||
554 | ath_rx_cleanup(sc); | ||
555 | |||
556 | return error; | ||
557 | } | ||
558 | |||
559 | /* Reclaim all rx queue resources */ | ||
560 | |||
561 | void ath_rx_cleanup(struct ath_softc *sc) | ||
562 | { | ||
563 | struct sk_buff *skb; | ||
564 | struct ath_buf *bf; | ||
565 | |||
566 | list_for_each_entry(bf, &sc->sc_rxbuf, list) { | ||
567 | skb = bf->bf_mpdu; | ||
568 | if (skb) | ||
569 | dev_kfree_skb(skb); | ||
570 | } | ||
571 | |||
572 | /* cleanup rx descriptors */ | ||
573 | |||
574 | if (sc->sc_rxdma.dd_desc_len != 0) | ||
575 | ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); | ||
576 | } | ||
577 | |||
578 | /* | ||
579 | * Calculate the receive filter according to the | ||
580 | * operating mode and state: | ||
581 | * | ||
582 | * o always accept unicast, broadcast, and multicast traffic | ||
583 | * o maintain current state of phy error reception (the hal | ||
584 | * may enable phy error frames for noise immunity work) | ||
585 | * o probe request frames are accepted only when operating in | ||
586 | * hostap, adhoc, or monitor modes | ||
587 | * o enable promiscuous mode according to the interface state | ||
588 | * o accept beacons: | ||
589 | * - when operating in adhoc mode so the 802.11 layer creates | ||
590 | * node table entries for peers, | ||
591 | * - when operating in station mode for collecting rssi data when | ||
592 | * the station is otherwise quiet, or | ||
593 | * - when operating as a repeater so we see repeater-sta beacons | ||
594 | * - when scanning | ||
595 | */ | ||
596 | |||
597 | u32 ath_calcrxfilter(struct ath_softc *sc) | ||
598 | { | ||
599 | #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) | ||
600 | u32 rfilt; | ||
601 | |||
602 | rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) | ||
603 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | ||
604 | | ATH9K_RX_FILTER_MCAST; | ||
605 | |||
606 | /* If not a STA, enable processing of Probe Requests */ | ||
607 | if (sc->sc_opmode != ATH9K_M_STA) | ||
608 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | ||
609 | |||
610 | /* Can't set HOSTAP into promiscous mode */ | ||
611 | if (sc->sc_opmode == ATH9K_M_MONITOR) { | ||
612 | rfilt |= ATH9K_RX_FILTER_PROM; | ||
613 | /* ??? To prevent from sending ACK */ | ||
614 | rfilt &= ~ATH9K_RX_FILTER_UCAST; | ||
615 | } | ||
616 | |||
617 | if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS || | ||
618 | sc->sc_scanning) | ||
619 | rfilt |= ATH9K_RX_FILTER_BEACON; | ||
620 | |||
621 | /* If in HOSTAP mode, want to enable reception of PSPOLL frames | ||
622 | & beacon frames */ | ||
623 | if (sc->sc_opmode == ATH9K_M_HOSTAP) | ||
624 | rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL); | ||
625 | return rfilt; | ||
626 | #undef RX_FILTER_PRESERVE | ||
627 | } | ||
628 | |||
629 | /* Enable the receive h/w following a reset. */ | ||
630 | |||
631 | int ath_startrecv(struct ath_softc *sc) | ||
632 | { | ||
633 | struct ath_hal *ah = sc->sc_ah; | ||
634 | struct ath_buf *bf, *tbf; | ||
635 | |||
636 | spin_lock_bh(&sc->sc_rxbuflock); | ||
637 | if (list_empty(&sc->sc_rxbuf)) | ||
638 | goto start_recv; | ||
639 | |||
640 | sc->sc_rxlink = NULL; | ||
641 | list_for_each_entry_safe(bf, tbf, &sc->sc_rxbuf, list) { | ||
642 | if (bf->bf_status & ATH_BUFSTATUS_STALE) { | ||
643 | /* restarting h/w, no need for holding descriptors */ | ||
644 | bf->bf_status &= ~ATH_BUFSTATUS_STALE; | ||
645 | /* | ||
646 | * Upper layer may not be done with the frame yet so | ||
647 | * we can't just re-queue it to hardware. Remove it | ||
648 | * from h/w queue. It'll be re-queued when upper layer | ||
649 | * returns the frame and ath_rx_requeue_mpdu is called. | ||
650 | */ | ||
651 | if (!(bf->bf_status & ATH_BUFSTATUS_FREE)) { | ||
652 | list_del(&bf->list); | ||
653 | continue; | ||
654 | } | ||
655 | } | ||
656 | /* chain descriptors */ | ||
657 | ath_rx_buf_link(sc, bf); | ||
658 | } | ||
659 | |||
660 | /* We could have deleted elements so the list may be empty now */ | ||
661 | if (list_empty(&sc->sc_rxbuf)) | ||
662 | goto start_recv; | ||
663 | |||
664 | bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list); | ||
665 | ath9k_hw_putrxbuf(ah, bf->bf_daddr); | ||
666 | ath9k_hw_rxena(ah); /* enable recv descriptors */ | ||
667 | |||
668 | start_recv: | ||
669 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
670 | ath_opmode_init(sc); /* set filters, etc. */ | ||
671 | ath9k_hw_startpcureceive(ah); /* re-enable PCU/DMA engine */ | ||
672 | return 0; | ||
673 | } | ||
674 | |||
675 | /* Disable the receive h/w in preparation for a reset. */ | ||
676 | |||
677 | bool ath_stoprecv(struct ath_softc *sc) | ||
678 | { | ||
679 | struct ath_hal *ah = sc->sc_ah; | ||
680 | u64 tsf; | ||
681 | bool stopped; | ||
682 | |||
683 | ath9k_hw_stoppcurecv(ah); /* disable PCU */ | ||
684 | ath9k_hw_setrxfilter(ah, 0); /* clear recv filter */ | ||
685 | stopped = ath9k_hw_stopdmarecv(ah); /* disable DMA engine */ | ||
686 | mdelay(3); /* 3ms is long enough for 1 frame */ | ||
687 | tsf = ath9k_hw_gettsf64(ah); | ||
688 | sc->sc_rxlink = NULL; /* just in case */ | ||
689 | return stopped; | ||
690 | } | ||
691 | |||
692 | /* Flush receive queue */ | ||
693 | |||
694 | void ath_flushrecv(struct ath_softc *sc) | ||
695 | { | ||
696 | /* | ||
697 | * ath_rx_tasklet may be used to handle rx interrupt and flush receive | ||
698 | * queue at the same time. Use a lock to serialize the access of rx | ||
699 | * queue. | ||
700 | * ath_rx_tasklet cannot hold the spinlock while indicating packets. | ||
701 | * Instead, do not claim the spinlock but check for a flush in | ||
702 | * progress (see references to sc_rxflush) | ||
703 | */ | ||
704 | spin_lock_bh(&sc->sc_rxflushlock); | ||
705 | sc->sc_rxflush = 1; | ||
706 | |||
707 | ath_rx_tasklet(sc, 1); | ||
708 | |||
709 | sc->sc_rxflush = 0; | ||
710 | spin_unlock_bh(&sc->sc_rxflushlock); | ||
711 | } | ||
712 | |||
713 | /* Process an individual frame */ | ||
714 | |||
715 | int ath_rx_input(struct ath_softc *sc, | ||
716 | struct ath_node *an, | ||
717 | int is_ampdu, | ||
718 | struct sk_buff *skb, | ||
719 | struct ath_recv_status *rx_status, | ||
720 | enum ATH_RX_TYPE *status) | ||
721 | { | ||
722 | if (is_ampdu && sc->sc_rxaggr) { | ||
723 | *status = ATH_RX_CONSUMED; | ||
724 | return ath_ampdu_input(sc, an, skb, rx_status); | ||
725 | } else { | ||
726 | *status = ATH_RX_NON_CONSUMED; | ||
727 | return -1; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | /* Process receive queue, as well as LED, etc. */ | ||
732 | |||
733 | int ath_rx_tasklet(struct ath_softc *sc, int flush) | ||
734 | { | ||
735 | #define PA2DESC(_sc, _pa) \ | ||
736 | ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \ | ||
737 | ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr))) | ||
738 | |||
739 | struct ath_buf *bf, *bf_held = NULL; | ||
740 | struct ath_desc *ds; | ||
741 | struct ieee80211_hdr *hdr; | ||
742 | struct sk_buff *skb = NULL; | ||
743 | struct ath_recv_status rx_status; | ||
744 | struct ath_hal *ah = sc->sc_ah; | ||
745 | int type, rx_processed = 0; | ||
746 | u32 phyerr; | ||
747 | u8 chainreset = 0; | ||
748 | int retval; | ||
749 | __le16 fc; | ||
750 | |||
751 | do { | ||
752 | /* If handling rx interrupt and flush is in progress => exit */ | ||
753 | if (sc->sc_rxflush && (flush == 0)) | ||
754 | break; | ||
755 | |||
756 | spin_lock_bh(&sc->sc_rxbuflock); | ||
757 | if (list_empty(&sc->sc_rxbuf)) { | ||
758 | sc->sc_rxlink = NULL; | ||
759 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
760 | break; | ||
761 | } | ||
762 | |||
763 | bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list); | ||
764 | |||
765 | /* | ||
766 | * There is a race condition that BH gets scheduled after sw | ||
767 | * writes RxE and before hw re-load the last descriptor to get | ||
768 | * the newly chained one. Software must keep the last DONE | ||
769 | * descriptor as a holding descriptor - software does so by | ||
770 | * marking it with the STALE flag. | ||
771 | */ | ||
772 | if (bf->bf_status & ATH_BUFSTATUS_STALE) { | ||
773 | bf_held = bf; | ||
774 | if (list_is_last(&bf_held->list, &sc->sc_rxbuf)) { | ||
775 | /* | ||
776 | * The holding descriptor is the last | ||
777 | * descriptor in queue. It's safe to | ||
778 | * remove the last holding descriptor | ||
779 | * in BH context. | ||
780 | */ | ||
781 | list_del(&bf_held->list); | ||
782 | bf_held->bf_status &= ~ATH_BUFSTATUS_STALE; | ||
783 | sc->sc_rxlink = NULL; | ||
784 | |||
785 | if (bf_held->bf_status & ATH_BUFSTATUS_FREE) { | ||
786 | list_add_tail(&bf_held->list, | ||
787 | &sc->sc_rxbuf); | ||
788 | ath_rx_buf_link(sc, bf_held); | ||
789 | } | ||
790 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
791 | break; | ||
792 | } | ||
793 | bf = list_entry(bf->list.next, struct ath_buf, list); | ||
794 | } | ||
795 | |||
796 | ds = bf->bf_desc; | ||
797 | ++rx_processed; | ||
798 | |||
799 | /* | ||
800 | * Must provide the virtual address of the current | ||
801 | * descriptor, the physical address, and the virtual | ||
802 | * address of the next descriptor in the h/w chain. | ||
803 | * This allows the HAL to look ahead to see if the | ||
804 | * hardware is done with a descriptor by checking the | ||
805 | * done bit in the following descriptor and the address | ||
806 | * of the current descriptor the DMA engine is working | ||
807 | * on. All this is necessary because of our use of | ||
808 | * a self-linked list to avoid rx overruns. | ||
809 | */ | ||
810 | retval = ath9k_hw_rxprocdesc(ah, | ||
811 | ds, | ||
812 | bf->bf_daddr, | ||
813 | PA2DESC(sc, ds->ds_link), | ||
814 | 0); | ||
815 | if (retval == -EINPROGRESS) { | ||
816 | struct ath_buf *tbf; | ||
817 | struct ath_desc *tds; | ||
818 | |||
819 | if (list_is_last(&bf->list, &sc->sc_rxbuf)) { | ||
820 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
821 | break; | ||
822 | } | ||
823 | |||
824 | tbf = list_entry(bf->list.next, struct ath_buf, list); | ||
825 | |||
826 | /* | ||
827 | * On some hardware the descriptor status words could | ||
828 | * get corrupted, including the done bit. Because of | ||
829 | * this, check if the next descriptor's done bit is | ||
830 | * set or not. | ||
831 | * | ||
832 | * If the next descriptor's done bit is set, the current | ||
833 | * descriptor has been corrupted. Force s/w to discard | ||
834 | * this descriptor and continue... | ||
835 | */ | ||
836 | |||
837 | tds = tbf->bf_desc; | ||
838 | retval = ath9k_hw_rxprocdesc(ah, | ||
839 | tds, tbf->bf_daddr, | ||
840 | PA2DESC(sc, tds->ds_link), 0); | ||
841 | if (retval == -EINPROGRESS) { | ||
842 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
843 | break; | ||
844 | } | ||
845 | } | ||
846 | |||
847 | /* XXX: we do not support frames spanning | ||
848 | * multiple descriptors */ | ||
849 | bf->bf_status |= ATH_BUFSTATUS_DONE; | ||
850 | |||
851 | skb = bf->bf_mpdu; | ||
852 | if (skb == NULL) { /* XXX ??? can this happen */ | ||
853 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
854 | continue; | ||
855 | } | ||
856 | /* | ||
857 | * Now we know it's a completed frame, we can indicate the | ||
858 | * frame. Remove the previous holding descriptor and leave | ||
859 | * this one in the queue as the new holding descriptor. | ||
860 | */ | ||
861 | if (bf_held) { | ||
862 | list_del(&bf_held->list); | ||
863 | bf_held->bf_status &= ~ATH_BUFSTATUS_STALE; | ||
864 | if (bf_held->bf_status & ATH_BUFSTATUS_FREE) { | ||
865 | list_add_tail(&bf_held->list, &sc->sc_rxbuf); | ||
866 | /* try to requeue this descriptor */ | ||
867 | ath_rx_buf_link(sc, bf_held); | ||
868 | } | ||
869 | } | ||
870 | |||
871 | bf->bf_status |= ATH_BUFSTATUS_STALE; | ||
872 | bf_held = bf; | ||
873 | /* | ||
874 | * Release the lock here in case ieee80211_input() return | ||
875 | * the frame immediately by calling ath_rx_mpdu_requeue(). | ||
876 | */ | ||
877 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
878 | |||
879 | if (flush) { | ||
880 | /* | ||
881 | * If we're asked to flush receive queue, directly | ||
882 | * chain it back at the queue without processing it. | ||
883 | */ | ||
884 | goto rx_next; | ||
885 | } | ||
886 | |||
887 | hdr = (struct ieee80211_hdr *)skb->data; | ||
888 | fc = hdr->frame_control; | ||
889 | memzero(&rx_status, sizeof(struct ath_recv_status)); | ||
890 | |||
891 | if (ds->ds_rxstat.rs_more) { | ||
892 | /* | ||
893 | * Frame spans multiple descriptors; this | ||
894 | * cannot happen yet as we don't support | ||
895 | * jumbograms. If not in monitor mode, | ||
896 | * discard the frame. | ||
897 | */ | ||
898 | #ifndef ERROR_FRAMES | ||
899 | /* | ||
900 | * Enable this if you want to see | ||
901 | * error frames in Monitor mode. | ||
902 | */ | ||
903 | if (sc->sc_opmode != ATH9K_M_MONITOR) | ||
904 | goto rx_next; | ||
905 | #endif | ||
906 | /* fall thru for monitor mode handling... */ | ||
907 | } else if (ds->ds_rxstat.rs_status != 0) { | ||
908 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) | ||
909 | rx_status.flags |= ATH_RX_FCS_ERROR; | ||
910 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) { | ||
911 | phyerr = ds->ds_rxstat.rs_phyerr & 0x1f; | ||
912 | goto rx_next; | ||
913 | } | ||
914 | |||
915 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) { | ||
916 | /* | ||
917 | * Decrypt error. We only mark packet status | ||
918 | * here and always push up the frame up to let | ||
919 | * mac80211 handle the actual error case, be | ||
920 | * it no decryption key or real decryption | ||
921 | * error. This let us keep statistics there. | ||
922 | */ | ||
923 | rx_status.flags |= ATH_RX_DECRYPT_ERROR; | ||
924 | } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) { | ||
925 | /* | ||
926 | * Demic error. We only mark frame status here | ||
927 | * and always push up the frame up to let | ||
928 | * mac80211 handle the actual error case. This | ||
929 | * let us keep statistics there. Hardware may | ||
930 | * post a false-positive MIC error. | ||
931 | */ | ||
932 | if (ieee80211_is_ctl(fc)) | ||
933 | /* | ||
934 | * Sometimes, we get invalid | ||
935 | * MIC failures on valid control frames. | ||
936 | * Remove these mic errors. | ||
937 | */ | ||
938 | ds->ds_rxstat.rs_status &= | ||
939 | ~ATH9K_RXERR_MIC; | ||
940 | else | ||
941 | rx_status.flags |= ATH_RX_MIC_ERROR; | ||
942 | } | ||
943 | /* | ||
944 | * Reject error frames with the exception of | ||
945 | * decryption and MIC failures. For monitor mode, | ||
946 | * we also ignore the CRC error. | ||
947 | */ | ||
948 | if (sc->sc_opmode == ATH9K_M_MONITOR) { | ||
949 | if (ds->ds_rxstat.rs_status & | ||
950 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | ||
951 | ATH9K_RXERR_CRC)) | ||
952 | goto rx_next; | ||
953 | } else { | ||
954 | if (ds->ds_rxstat.rs_status & | ||
955 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { | ||
956 | goto rx_next; | ||
957 | } | ||
958 | } | ||
959 | } | ||
960 | /* | ||
961 | * The status portion of the descriptor could get corrupted. | ||
962 | */ | ||
963 | if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen) | ||
964 | goto rx_next; | ||
965 | /* | ||
966 | * Sync and unmap the frame. At this point we're | ||
967 | * committed to passing the sk_buff somewhere so | ||
968 | * clear buf_skb; this means a new sk_buff must be | ||
969 | * allocated when the rx descriptor is setup again | ||
970 | * to receive another frame. | ||
971 | */ | ||
972 | skb_put(skb, ds->ds_rxstat.rs_datalen); | ||
973 | skb->protocol = cpu_to_be16(ETH_P_CONTROL); | ||
974 | rx_status.tsf = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); | ||
975 | rx_status.rateieee = | ||
976 | sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate; | ||
977 | rx_status.rateKbps = | ||
978 | sc->sc_hwmap[ds->ds_rxstat.rs_rate].rateKbps; | ||
979 | rx_status.ratecode = ds->ds_rxstat.rs_rate; | ||
980 | |||
981 | /* HT rate */ | ||
982 | if (rx_status.ratecode & 0x80) { | ||
983 | /* TODO - add table to avoid division */ | ||
984 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) { | ||
985 | rx_status.flags |= ATH_RX_40MHZ; | ||
986 | rx_status.rateKbps = | ||
987 | (rx_status.rateKbps * 27) / 13; | ||
988 | } | ||
989 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI) | ||
990 | rx_status.rateKbps = | ||
991 | (rx_status.rateKbps * 10) / 9; | ||
992 | else | ||
993 | rx_status.flags |= ATH_RX_SHORT_GI; | ||
994 | } | ||
995 | |||
996 | /* sc->sc_noise_floor is only available when the station | ||
997 | attaches to an AP, so we use a default value | ||
998 | if we are not yet attached. */ | ||
999 | |||
1000 | /* XXX we should use either sc->sc_noise_floor or | ||
1001 | * ath_hal_getChanNoise(ah, &sc->sc_curchan) | ||
1002 | * to calculate the noise floor. | ||
1003 | * However, the value returned by ath_hal_getChanNoise | ||
1004 | * seems to be incorrect (-31dBm on the last test), | ||
1005 | * so we will use a hard-coded value until we | ||
1006 | * figure out what is going on. | ||
1007 | */ | ||
1008 | rx_status.abs_rssi = | ||
1009 | ds->ds_rxstat.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; | ||
1010 | |||
1011 | pci_dma_sync_single_for_cpu(sc->pdev, | ||
1012 | bf->bf_buf_addr, | ||
1013 | skb_tailroom(skb), | ||
1014 | PCI_DMA_FROMDEVICE); | ||
1015 | pci_unmap_single(sc->pdev, | ||
1016 | bf->bf_buf_addr, | ||
1017 | sc->sc_rxbufsize, | ||
1018 | PCI_DMA_FROMDEVICE); | ||
1019 | |||
1020 | /* XXX: Ah! make me more readable, use a helper */ | ||
1021 | if (ah->ah_caps.halHTSupport) { | ||
1022 | if (ds->ds_rxstat.rs_moreaggr == 0) { | ||
1023 | rx_status.rssictl[0] = | ||
1024 | ds->ds_rxstat.rs_rssi_ctl0; | ||
1025 | rx_status.rssictl[1] = | ||
1026 | ds->ds_rxstat.rs_rssi_ctl1; | ||
1027 | rx_status.rssictl[2] = | ||
1028 | ds->ds_rxstat.rs_rssi_ctl2; | ||
1029 | rx_status.rssi = ds->ds_rxstat.rs_rssi; | ||
1030 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) { | ||
1031 | rx_status.rssiextn[0] = | ||
1032 | ds->ds_rxstat.rs_rssi_ext0; | ||
1033 | rx_status.rssiextn[1] = | ||
1034 | ds->ds_rxstat.rs_rssi_ext1; | ||
1035 | rx_status.rssiextn[2] = | ||
1036 | ds->ds_rxstat.rs_rssi_ext2; | ||
1037 | rx_status.flags |= | ||
1038 | ATH_RX_RSSI_EXTN_VALID; | ||
1039 | } | ||
1040 | rx_status.flags |= ATH_RX_RSSI_VALID | | ||
1041 | ATH_RX_CHAIN_RSSI_VALID; | ||
1042 | } | ||
1043 | } else { | ||
1044 | /* | ||
1045 | * Need to insert the "combined" rssi into the | ||
1046 | * status structure for upper layer processing | ||
1047 | */ | ||
1048 | rx_status.rssi = ds->ds_rxstat.rs_rssi; | ||
1049 | rx_status.flags |= ATH_RX_RSSI_VALID; | ||
1050 | } | ||
1051 | |||
1052 | /* Pass frames up to the stack. */ | ||
1053 | |||
1054 | type = ath_rx_indicate(sc, skb, | ||
1055 | &rx_status, ds->ds_rxstat.rs_keyix); | ||
1056 | |||
1057 | /* | ||
1058 | * change the default rx antenna if rx diversity chooses the | ||
1059 | * other antenna 3 times in a row. | ||
1060 | */ | ||
1061 | if (sc->sc_defant != ds->ds_rxstat.rs_antenna) { | ||
1062 | if (++sc->sc_rxotherant >= 3) | ||
1063 | ath_setdefantenna(sc, | ||
1064 | ds->ds_rxstat.rs_antenna); | ||
1065 | } else { | ||
1066 | sc->sc_rxotherant = 0; | ||
1067 | } | ||
1068 | |||
1069 | #ifdef CONFIG_SLOW_ANT_DIV | ||
1070 | if ((rx_status.flags & ATH_RX_RSSI_VALID) && | ||
1071 | ieee80211_is_beacon(fc)) { | ||
1072 | ath_slow_ant_div(&sc->sc_antdiv, hdr, &ds->ds_rxstat); | ||
1073 | } | ||
1074 | #endif | ||
1075 | /* | ||
1076 | * For frames successfully indicated, the buffer will be | ||
1077 | * returned to us by upper layers by calling | ||
1078 | * ath_rx_mpdu_requeue, either synchronusly or asynchronously. | ||
1079 | * So we don't want to do it here in this loop. | ||
1080 | */ | ||
1081 | continue; | ||
1082 | |||
1083 | rx_next: | ||
1084 | bf->bf_status |= ATH_BUFSTATUS_FREE; | ||
1085 | } while (TRUE); | ||
1086 | |||
1087 | if (chainreset) { | ||
1088 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
1089 | "%s: Reset rx chain mask. " | ||
1090 | "Do internal reset\n", __func__); | ||
1091 | ASSERT(flush == 0); | ||
1092 | ath_internal_reset(sc); | ||
1093 | } | ||
1094 | |||
1095 | return 0; | ||
1096 | #undef PA2DESC | ||
1097 | } | ||
1098 | |||
1099 | /* Process ADDBA request in per-TID data structure */ | ||
1100 | |||
1101 | int ath_rx_aggr_start(struct ath_softc *sc, | ||
1102 | const u8 *addr, | ||
1103 | u16 tid, | ||
1104 | u16 *ssn) | ||
1105 | { | ||
1106 | struct ath_arx_tid *rxtid; | ||
1107 | struct ath_node *an; | ||
1108 | struct ieee80211_hw *hw = sc->hw; | ||
1109 | struct ieee80211_supported_band *sband; | ||
1110 | u16 buffersize = 0; | ||
1111 | |||
1112 | spin_lock_bh(&sc->node_lock); | ||
1113 | an = ath_node_find(sc, (u8 *) addr); | ||
1114 | spin_unlock_bh(&sc->node_lock); | ||
1115 | |||
1116 | if (!an) { | ||
1117 | DPRINTF(sc, ATH_DBG_AGGR, | ||
1118 | "%s: Node not found to initialize RX aggregation\n", | ||
1119 | __func__); | ||
1120 | return -1; | ||
1121 | } | ||
1122 | |||
1123 | sband = hw->wiphy->bands[hw->conf.channel->band]; | ||
1124 | buffersize = IEEE80211_MIN_AMPDU_BUF << | ||
1125 | sband->ht_info.ampdu_factor; /* FIXME */ | ||
1126 | |||
1127 | rxtid = &an->an_aggr.rx.tid[tid]; | ||
1128 | |||
1129 | spin_lock_bh(&rxtid->tidlock); | ||
1130 | if (sc->sc_rxaggr) { | ||
1131 | /* Allow aggregation reception | ||
1132 | * Adjust rx BA window size. Peer might indicate a | ||
1133 | * zero buffer size for a _dont_care_ condition. | ||
1134 | */ | ||
1135 | if (buffersize) | ||
1136 | rxtid->baw_size = min(buffersize, rxtid->baw_size); | ||
1137 | |||
1138 | /* set rx sequence number */ | ||
1139 | rxtid->seq_next = *ssn; | ||
1140 | |||
1141 | /* Allocate the receive buffers for this TID */ | ||
1142 | DPRINTF(sc, ATH_DBG_AGGR, | ||
1143 | "%s: Allcating rxbuffer for TID %d\n", __func__, tid); | ||
1144 | |||
1145 | if (rxtid->rxbuf == NULL) { | ||
1146 | /* | ||
1147 | * If the rxbuff is not NULL at this point, we *probably* | ||
1148 | * already allocated the buffer on a previous ADDBA, | ||
1149 | * and this is a subsequent ADDBA that got through. | ||
1150 | * Don't allocate, but use the value in the pointer, | ||
1151 | * we zero it out when we de-allocate. | ||
1152 | */ | ||
1153 | rxtid->rxbuf = kmalloc(ATH_TID_MAX_BUFS * | ||
1154 | sizeof(struct ath_rxbuf), GFP_ATOMIC); | ||
1155 | } | ||
1156 | if (rxtid->rxbuf == NULL) { | ||
1157 | DPRINTF(sc, ATH_DBG_AGGR, | ||
1158 | "%s: Unable to allocate RX buffer, " | ||
1159 | "refusing ADDBA\n", __func__); | ||
1160 | } else { | ||
1161 | /* Ensure the memory is zeroed out (all internal | ||
1162 | * pointers are null) */ | ||
1163 | memzero(rxtid->rxbuf, ATH_TID_MAX_BUFS * | ||
1164 | sizeof(struct ath_rxbuf)); | ||
1165 | DPRINTF(sc, ATH_DBG_AGGR, | ||
1166 | "%s: Allocated @%p\n", __func__, rxtid->rxbuf); | ||
1167 | |||
1168 | /* Allow aggregation reception */ | ||
1169 | rxtid->addba_exchangecomplete = 1; | ||
1170 | } | ||
1171 | } | ||
1172 | spin_unlock_bh(&rxtid->tidlock); | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | /* Process DELBA */ | ||
1178 | |||
1179 | int ath_rx_aggr_stop(struct ath_softc *sc, | ||
1180 | const u8 *addr, | ||
1181 | u16 tid) | ||
1182 | { | ||
1183 | struct ath_node *an; | ||
1184 | |||
1185 | spin_lock_bh(&sc->node_lock); | ||
1186 | an = ath_node_find(sc, (u8 *) addr); | ||
1187 | spin_unlock_bh(&sc->node_lock); | ||
1188 | |||
1189 | if (!an) { | ||
1190 | DPRINTF(sc, ATH_DBG_AGGR, | ||
1191 | "%s: RX aggr stop for non-existent node\n", __func__); | ||
1192 | return -1; | ||
1193 | } | ||
1194 | |||
1195 | ath_rx_aggr_teardown(sc, an, tid); | ||
1196 | return 0; | ||
1197 | } | ||
1198 | |||
1199 | /* Rx aggregation tear down */ | ||
1200 | |||
1201 | void ath_rx_aggr_teardown(struct ath_softc *sc, | ||
1202 | struct ath_node *an, u8 tid) | ||
1203 | { | ||
1204 | struct ath_arx_tid *rxtid = &an->an_aggr.rx.tid[tid]; | ||
1205 | |||
1206 | if (!rxtid->addba_exchangecomplete) | ||
1207 | return; | ||
1208 | |||
1209 | del_timer_sync(&rxtid->timer); | ||
1210 | ath_rx_flush_tid(sc, rxtid, 0); | ||
1211 | rxtid->addba_exchangecomplete = 0; | ||
1212 | |||
1213 | /* De-allocate the receive buffer array allocated when addba started */ | ||
1214 | |||
1215 | if (rxtid->rxbuf) { | ||
1216 | DPRINTF(sc, ATH_DBG_AGGR, | ||
1217 | "%s: Deallocating TID %d rxbuff @%p\n", | ||
1218 | __func__, tid, rxtid->rxbuf); | ||
1219 | kfree(rxtid->rxbuf); | ||
1220 | |||
1221 | /* Set pointer to null to avoid reuse*/ | ||
1222 | rxtid->rxbuf = NULL; | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | /* Initialize per-node receive state */ | ||
1227 | |||
1228 | void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an) | ||
1229 | { | ||
1230 | if (sc->sc_rxaggr) { | ||
1231 | struct ath_arx_tid *rxtid; | ||
1232 | int tidno; | ||
1233 | |||
1234 | /* Init per tid rx state */ | ||
1235 | for (tidno = 0, rxtid = &an->an_aggr.rx.tid[tidno]; | ||
1236 | tidno < WME_NUM_TID; | ||
1237 | tidno++, rxtid++) { | ||
1238 | rxtid->an = an; | ||
1239 | rxtid->seq_reset = 1; | ||
1240 | rxtid->seq_next = 0; | ||
1241 | rxtid->baw_size = WME_MAX_BA; | ||
1242 | rxtid->baw_head = rxtid->baw_tail = 0; | ||
1243 | |||
1244 | /* | ||
1245 | * Ensure the buffer pointer is null at this point | ||
1246 | * (needs to be allocated when addba is received) | ||
1247 | */ | ||
1248 | |||
1249 | rxtid->rxbuf = NULL; | ||
1250 | setup_timer(&rxtid->timer, ath_rx_timer, | ||
1251 | (unsigned long)rxtid); | ||
1252 | spin_lock_init(&rxtid->tidlock); | ||
1253 | |||
1254 | /* ADDBA state */ | ||
1255 | rxtid->addba_exchangecomplete = 0; | ||
1256 | } | ||
1257 | } | ||
1258 | } | ||
1259 | |||
1260 | void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | ||
1261 | { | ||
1262 | if (sc->sc_rxaggr) { | ||
1263 | struct ath_arx_tid *rxtid; | ||
1264 | int tidno, i; | ||
1265 | |||
1266 | /* Init per tid rx state */ | ||
1267 | for (tidno = 0, rxtid = &an->an_aggr.rx.tid[tidno]; | ||
1268 | tidno < WME_NUM_TID; | ||
1269 | tidno++, rxtid++) { | ||
1270 | |||
1271 | if (!rxtid->addba_exchangecomplete) | ||
1272 | continue; | ||
1273 | |||
1274 | /* must cancel timer first */ | ||
1275 | del_timer_sync(&rxtid->timer); | ||
1276 | |||
1277 | /* drop any pending sub-frames */ | ||
1278 | ath_rx_flush_tid(sc, rxtid, 1); | ||
1279 | |||
1280 | for (i = 0; i < ATH_TID_MAX_BUFS; i++) | ||
1281 | ASSERT(rxtid->rxbuf[i].rx_wbuf == NULL); | ||
1282 | |||
1283 | rxtid->addba_exchangecomplete = 0; | ||
1284 | } | ||
1285 | } | ||
1286 | |||
1287 | } | ||
1288 | |||
1289 | /* Cleanup per-node receive state */ | ||
1290 | |||
1291 | void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an) | ||
1292 | { | ||
1293 | ath_rx_node_cleanup(sc, an); | ||
1294 | } | ||
1295 | |||
1296 | dma_addr_t ath_skb_map_single(struct ath_softc *sc, | ||
1297 | struct sk_buff *skb, | ||
1298 | int direction, | ||
1299 | dma_addr_t *pa) | ||
1300 | { | ||
1301 | /* | ||
1302 | * NB: do NOT use skb->len, which is 0 on initialization. | ||
1303 | * Use skb's entire data area instead. | ||
1304 | */ | ||
1305 | *pa = pci_map_single(sc->pdev, skb->data, | ||
1306 | skb_end_pointer(skb) - skb->head, direction); | ||
1307 | return *pa; | ||
1308 | } | ||
1309 | |||
1310 | void ath_skb_unmap_single(struct ath_softc *sc, | ||
1311 | struct sk_buff *skb, | ||
1312 | int direction, | ||
1313 | dma_addr_t *pa) | ||
1314 | { | ||
1315 | /* Unmap skb's entire data area */ | ||
1316 | pci_unmap_single(sc->pdev, *pa, | ||
1317 | skb_end_pointer(skb) - skb->head, direction); | ||
1318 | } | ||
diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h new file mode 100644 index 00000000000..42b0890a468 --- /dev/null +++ b/drivers/net/wireless/ath9k/reg.h | |||
@@ -0,0 +1,1385 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef REG_H | ||
18 | #define REG_H | ||
19 | |||
20 | #define AR_CR 0x0008 | ||
21 | #define AR_CR_RXE 0x00000004 | ||
22 | #define AR_CR_RXD 0x00000020 | ||
23 | #define AR_CR_SWI 0x00000040 | ||
24 | |||
25 | #define AR_RXDP 0x000C | ||
26 | |||
27 | #define AR_CFG 0x0014 | ||
28 | #define AR_CFG_SWTD 0x00000001 | ||
29 | #define AR_CFG_SWTB 0x00000002 | ||
30 | #define AR_CFG_SWRD 0x00000004 | ||
31 | #define AR_CFG_SWRB 0x00000008 | ||
32 | #define AR_CFG_SWRG 0x00000010 | ||
33 | #define AR_CFG_AP_ADHOC_INDICATION 0x00000020 | ||
34 | #define AR_CFG_PHOK 0x00000100 | ||
35 | #define AR_CFG_CLK_GATE_DIS 0x00000400 | ||
36 | #define AR_CFG_EEBS 0x00000200 | ||
37 | #define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 | ||
38 | #define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 | ||
39 | |||
40 | #define AR_MIRT 0x0020 | ||
41 | #define AR_MIRT_VAL 0x0000ffff | ||
42 | #define AR_MIRT_VAL_S 16 | ||
43 | |||
44 | #define AR_IER 0x0024 | ||
45 | #define AR_IER_ENABLE 0x00000001 | ||
46 | #define AR_IER_DISABLE 0x00000000 | ||
47 | |||
48 | #define AR_TIMT 0x0028 | ||
49 | #define AR_TIMT_LAST 0x0000ffff | ||
50 | #define AR_TIMT_LAST_S 0 | ||
51 | #define AR_TIMT_FIRST 0xffff0000 | ||
52 | #define AR_TIMT_FIRST_S 16 | ||
53 | |||
54 | #define AR_RIMT 0x002C | ||
55 | #define AR_RIMT_LAST 0x0000ffff | ||
56 | #define AR_RIMT_LAST_S 0 | ||
57 | #define AR_RIMT_FIRST 0xffff0000 | ||
58 | #define AR_RIMT_FIRST_S 16 | ||
59 | |||
60 | #define AR_DMASIZE_4B 0x00000000 | ||
61 | #define AR_DMASIZE_8B 0x00000001 | ||
62 | #define AR_DMASIZE_16B 0x00000002 | ||
63 | #define AR_DMASIZE_32B 0x00000003 | ||
64 | #define AR_DMASIZE_64B 0x00000004 | ||
65 | #define AR_DMASIZE_128B 0x00000005 | ||
66 | #define AR_DMASIZE_256B 0x00000006 | ||
67 | #define AR_DMASIZE_512B 0x00000007 | ||
68 | |||
69 | #define AR_TXCFG 0x0030 | ||
70 | #define AR_TXCFG_DMASZ_MASK 0x00000003 | ||
71 | #define AR_TXCFG_DMASZ_4B 0 | ||
72 | #define AR_TXCFG_DMASZ_8B 1 | ||
73 | #define AR_TXCFG_DMASZ_16B 2 | ||
74 | #define AR_TXCFG_DMASZ_32B 3 | ||
75 | #define AR_TXCFG_DMASZ_64B 4 | ||
76 | #define AR_TXCFG_DMASZ_128B 5 | ||
77 | #define AR_TXCFG_DMASZ_256B 6 | ||
78 | #define AR_TXCFG_DMASZ_512B 7 | ||
79 | #define AR_FTRIG 0x000003F0 | ||
80 | #define AR_FTRIG_S 4 | ||
81 | #define AR_FTRIG_IMMED 0x00000000 | ||
82 | #define AR_FTRIG_64B 0x00000010 | ||
83 | #define AR_FTRIG_128B 0x00000020 | ||
84 | #define AR_FTRIG_192B 0x00000030 | ||
85 | #define AR_FTRIG_256B 0x00000040 | ||
86 | #define AR_FTRIG_512B 0x00000080 | ||
87 | #define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800 | ||
88 | |||
89 | #define AR_RXCFG 0x0034 | ||
90 | #define AR_RXCFG_CHIRP 0x00000008 | ||
91 | #define AR_RXCFG_ZLFDMA 0x00000010 | ||
92 | #define AR_RXCFG_DMASZ_MASK 0x00000007 | ||
93 | #define AR_RXCFG_DMASZ_4B 0 | ||
94 | #define AR_RXCFG_DMASZ_8B 1 | ||
95 | #define AR_RXCFG_DMASZ_16B 2 | ||
96 | #define AR_RXCFG_DMASZ_32B 3 | ||
97 | #define AR_RXCFG_DMASZ_64B 4 | ||
98 | #define AR_RXCFG_DMASZ_128B 5 | ||
99 | #define AR_RXCFG_DMASZ_256B 6 | ||
100 | #define AR_RXCFG_DMASZ_512B 7 | ||
101 | |||
102 | #define AR_MIBC 0x0040 | ||
103 | #define AR_MIBC_COW 0x00000001 | ||
104 | #define AR_MIBC_FMC 0x00000002 | ||
105 | #define AR_MIBC_CMC 0x00000004 | ||
106 | #define AR_MIBC_MCS 0x00000008 | ||
107 | |||
108 | #define AR_TOPS 0x0044 | ||
109 | #define AR_TOPS_MASK 0x0000FFFF | ||
110 | |||
111 | #define AR_RXNPTO 0x0048 | ||
112 | #define AR_RXNPTO_MASK 0x000003FF | ||
113 | |||
114 | #define AR_TXNPTO 0x004C | ||
115 | #define AR_TXNPTO_MASK 0x000003FF | ||
116 | #define AR_TXNPTO_QCU_MASK 0x000FFC00 | ||
117 | |||
118 | #define AR_RPGTO 0x0050 | ||
119 | #define AR_RPGTO_MASK 0x000003FF | ||
120 | |||
121 | #define AR_RPCNT 0x0054 | ||
122 | #define AR_RPCNT_MASK 0x0000001F | ||
123 | |||
124 | #define AR_MACMISC 0x0058 | ||
125 | #define AR_MACMISC_PCI_EXT_FORCE 0x00000010 | ||
126 | #define AR_MACMISC_DMA_OBS 0x000001E0 | ||
127 | #define AR_MACMISC_DMA_OBS_S 5 | ||
128 | #define AR_MACMISC_DMA_OBS_LINE_0 0 | ||
129 | #define AR_MACMISC_DMA_OBS_LINE_1 1 | ||
130 | #define AR_MACMISC_DMA_OBS_LINE_2 2 | ||
131 | #define AR_MACMISC_DMA_OBS_LINE_3 3 | ||
132 | #define AR_MACMISC_DMA_OBS_LINE_4 4 | ||
133 | #define AR_MACMISC_DMA_OBS_LINE_5 5 | ||
134 | #define AR_MACMISC_DMA_OBS_LINE_6 6 | ||
135 | #define AR_MACMISC_DMA_OBS_LINE_7 7 | ||
136 | #define AR_MACMISC_DMA_OBS_LINE_8 8 | ||
137 | #define AR_MACMISC_MISC_OBS 0x00000E00 | ||
138 | #define AR_MACMISC_MISC_OBS_S 9 | ||
139 | #define AR_MACMISC_MISC_OBS_BUS_LSB 0x00007000 | ||
140 | #define AR_MACMISC_MISC_OBS_BUS_LSB_S 12 | ||
141 | #define AR_MACMISC_MISC_OBS_BUS_MSB 0x00038000 | ||
142 | #define AR_MACMISC_MISC_OBS_BUS_MSB_S 15 | ||
143 | #define AR_MACMISC_MISC_OBS_BUS_1 1 | ||
144 | |||
145 | #define AR_GTXTO 0x0064 | ||
146 | #define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF | ||
147 | #define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000 | ||
148 | #define AR_GTXTO_TIMEOUT_LIMIT_S 16 | ||
149 | |||
150 | #define AR_GTTM 0x0068 | ||
151 | #define AR_GTTM_USEC 0x00000001 | ||
152 | #define AR_GTTM_IGNORE_IDLE 0x00000002 | ||
153 | #define AR_GTTM_RESET_IDLE 0x00000004 | ||
154 | #define AR_GTTM_CST_USEC 0x00000008 | ||
155 | |||
156 | #define AR_CST 0x006C | ||
157 | #define AR_CST_TIMEOUT_COUNTER 0x0000FFFF | ||
158 | #define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 | ||
159 | #define AR_CST_TIMEOUT_LIMIT_S 16 | ||
160 | |||
161 | #define AR_SREV_VERSION_9100 0x014 | ||
162 | |||
163 | #define AR_SREV_5416_V20_OR_LATER(_ah) \ | ||
164 | (AR_SREV_9100((_ah)) || AR_SREV_5416_20_OR_LATER(_ah)) | ||
165 | #define AR_SREV_5416_V22_OR_LATER(_ah) \ | ||
166 | (AR_SREV_9100((_ah)) || AR_SREV_5416_22_OR_LATER(_ah)) | ||
167 | |||
168 | #define AR_ISR 0x0080 | ||
169 | #define AR_ISR_RXOK 0x00000001 | ||
170 | #define AR_ISR_RXDESC 0x00000002 | ||
171 | #define AR_ISR_RXERR 0x00000004 | ||
172 | #define AR_ISR_RXNOPKT 0x00000008 | ||
173 | #define AR_ISR_RXEOL 0x00000010 | ||
174 | #define AR_ISR_RXORN 0x00000020 | ||
175 | #define AR_ISR_TXOK 0x00000040 | ||
176 | #define AR_ISR_TXDESC 0x00000080 | ||
177 | #define AR_ISR_TXERR 0x00000100 | ||
178 | #define AR_ISR_TXNOPKT 0x00000200 | ||
179 | #define AR_ISR_TXEOL 0x00000400 | ||
180 | #define AR_ISR_TXURN 0x00000800 | ||
181 | #define AR_ISR_MIB 0x00001000 | ||
182 | #define AR_ISR_SWI 0x00002000 | ||
183 | #define AR_ISR_RXPHY 0x00004000 | ||
184 | #define AR_ISR_RXKCM 0x00008000 | ||
185 | #define AR_ISR_SWBA 0x00010000 | ||
186 | #define AR_ISR_BRSSI 0x00020000 | ||
187 | #define AR_ISR_BMISS 0x00040000 | ||
188 | #define AR_ISR_BNR 0x00100000 | ||
189 | #define AR_ISR_RXCHIRP 0x00200000 | ||
190 | #define AR_ISR_BCNMISC 0x00800000 | ||
191 | #define AR_ISR_TIM 0x00800000 | ||
192 | #define AR_ISR_QCBROVF 0x02000000 | ||
193 | #define AR_ISR_QCBRURN 0x04000000 | ||
194 | #define AR_ISR_QTRIG 0x08000000 | ||
195 | #define AR_ISR_GENTMR 0x10000000 | ||
196 | |||
197 | #define AR_ISR_TXMINTR 0x00080000 | ||
198 | #define AR_ISR_RXMINTR 0x01000000 | ||
199 | #define AR_ISR_TXINTM 0x40000000 | ||
200 | #define AR_ISR_RXINTM 0x80000000 | ||
201 | |||
202 | #define AR_ISR_S0 0x0084 | ||
203 | #define AR_ISR_S0_QCU_TXOK 0x000003FF | ||
204 | #define AR_ISR_S0_QCU_TXOK_S 0 | ||
205 | #define AR_ISR_S0_QCU_TXDESC 0x03FF0000 | ||
206 | #define AR_ISR_S0_QCU_TXDESC_S 16 | ||
207 | |||
208 | #define AR_ISR_S1 0x0088 | ||
209 | #define AR_ISR_S1_QCU_TXERR 0x000003FF | ||
210 | #define AR_ISR_S1_QCU_TXERR_S 0 | ||
211 | #define AR_ISR_S1_QCU_TXEOL 0x03FF0000 | ||
212 | #define AR_ISR_S1_QCU_TXEOL_S 16 | ||
213 | |||
214 | #define AR_ISR_S2 0x008c | ||
215 | #define AR_ISR_S2_QCU_TXURN 0x000003FF | ||
216 | #define AR_ISR_S2_CST 0x00400000 | ||
217 | #define AR_ISR_S2_GTT 0x00800000 | ||
218 | #define AR_ISR_S2_TIM 0x01000000 | ||
219 | #define AR_ISR_S2_CABEND 0x02000000 | ||
220 | #define AR_ISR_S2_DTIMSYNC 0x04000000 | ||
221 | #define AR_ISR_S2_BCNTO 0x08000000 | ||
222 | #define AR_ISR_S2_CABTO 0x10000000 | ||
223 | #define AR_ISR_S2_DTIM 0x20000000 | ||
224 | #define AR_ISR_S2_TSFOOR 0x40000000 | ||
225 | #define AR_ISR_S2_TBTT_TIME 0x80000000 | ||
226 | |||
227 | #define AR_ISR_S3 0x0090 | ||
228 | #define AR_ISR_S3_QCU_QCBROVF 0x000003FF | ||
229 | #define AR_ISR_S3_QCU_QCBRURN 0x03FF0000 | ||
230 | |||
231 | #define AR_ISR_S4 0x0094 | ||
232 | #define AR_ISR_S4_QCU_QTRIG 0x000003FF | ||
233 | #define AR_ISR_S4_RESV0 0xFFFFFC00 | ||
234 | |||
235 | #define AR_ISR_S5 0x0098 | ||
236 | #define AR_ISR_S5_TIMER_TRIG 0x000000FF | ||
237 | #define AR_ISR_S5_TIMER_THRESH 0x0007FE00 | ||
238 | #define AR_ISR_S5_TIM_TIMER 0x00000010 | ||
239 | #define AR_ISR_S5_DTIM_TIMER 0x00000020 | ||
240 | #define AR_ISR_S5_S 0x00d8 | ||
241 | #define AR_IMR_S5 0x00b8 | ||
242 | #define AR_IMR_S5_TIM_TIMER 0x00000010 | ||
243 | #define AR_IMR_S5_DTIM_TIMER 0x00000020 | ||
244 | |||
245 | |||
246 | #define AR_IMR 0x00a0 | ||
247 | #define AR_IMR_RXOK 0x00000001 | ||
248 | #define AR_IMR_RXDESC 0x00000002 | ||
249 | #define AR_IMR_RXERR 0x00000004 | ||
250 | #define AR_IMR_RXNOPKT 0x00000008 | ||
251 | #define AR_IMR_RXEOL 0x00000010 | ||
252 | #define AR_IMR_RXORN 0x00000020 | ||
253 | #define AR_IMR_TXOK 0x00000040 | ||
254 | #define AR_IMR_TXDESC 0x00000080 | ||
255 | #define AR_IMR_TXERR 0x00000100 | ||
256 | #define AR_IMR_TXNOPKT 0x00000200 | ||
257 | #define AR_IMR_TXEOL 0x00000400 | ||
258 | #define AR_IMR_TXURN 0x00000800 | ||
259 | #define AR_IMR_MIB 0x00001000 | ||
260 | #define AR_IMR_SWI 0x00002000 | ||
261 | #define AR_IMR_RXPHY 0x00004000 | ||
262 | #define AR_IMR_RXKCM 0x00008000 | ||
263 | #define AR_IMR_SWBA 0x00010000 | ||
264 | #define AR_IMR_BRSSI 0x00020000 | ||
265 | #define AR_IMR_BMISS 0x00040000 | ||
266 | #define AR_IMR_BNR 0x00100000 | ||
267 | #define AR_IMR_RXCHIRP 0x00200000 | ||
268 | #define AR_IMR_BCNMISC 0x00800000 | ||
269 | #define AR_IMR_TIM 0x00800000 | ||
270 | #define AR_IMR_QCBROVF 0x02000000 | ||
271 | #define AR_IMR_QCBRURN 0x04000000 | ||
272 | #define AR_IMR_QTRIG 0x08000000 | ||
273 | #define AR_IMR_GENTMR 0x10000000 | ||
274 | |||
275 | #define AR_IMR_TXMINTR 0x00080000 | ||
276 | #define AR_IMR_RXMINTR 0x01000000 | ||
277 | #define AR_IMR_TXINTM 0x40000000 | ||
278 | #define AR_IMR_RXINTM 0x80000000 | ||
279 | |||
280 | #define AR_IMR_S0 0x00a4 | ||
281 | #define AR_IMR_S0_QCU_TXOK 0x000003FF | ||
282 | #define AR_IMR_S0_QCU_TXOK_S 0 | ||
283 | #define AR_IMR_S0_QCU_TXDESC 0x03FF0000 | ||
284 | #define AR_IMR_S0_QCU_TXDESC_S 16 | ||
285 | |||
286 | #define AR_IMR_S1 0x00a8 | ||
287 | #define AR_IMR_S1_QCU_TXERR 0x000003FF | ||
288 | #define AR_IMR_S1_QCU_TXERR_S 0 | ||
289 | #define AR_IMR_S1_QCU_TXEOL 0x03FF0000 | ||
290 | #define AR_IMR_S1_QCU_TXEOL_S 16 | ||
291 | |||
292 | #define AR_IMR_S2 0x00ac | ||
293 | #define AR_IMR_S2_QCU_TXURN 0x000003FF | ||
294 | #define AR_IMR_S2_QCU_TXURN_S 0 | ||
295 | #define AR_IMR_S2_CST 0x00400000 | ||
296 | #define AR_IMR_S2_GTT 0x00800000 | ||
297 | #define AR_IMR_S2_TIM 0x01000000 | ||
298 | #define AR_IMR_S2_CABEND 0x02000000 | ||
299 | #define AR_IMR_S2_DTIMSYNC 0x04000000 | ||
300 | #define AR_IMR_S2_BCNTO 0x08000000 | ||
301 | #define AR_IMR_S2_CABTO 0x10000000 | ||
302 | #define AR_IMR_S2_DTIM 0x20000000 | ||
303 | #define AR_IMR_S2_TSFOOR 0x40000000 | ||
304 | |||
305 | #define AR_IMR_S3 0x00b0 | ||
306 | #define AR_IMR_S3_QCU_QCBROVF 0x000003FF | ||
307 | #define AR_IMR_S3_QCU_QCBRURN 0x03FF0000 | ||
308 | #define AR_IMR_S3_QCU_QCBRURN_S 16 | ||
309 | |||
310 | #define AR_IMR_S4 0x00b4 | ||
311 | #define AR_IMR_S4_QCU_QTRIG 0x000003FF | ||
312 | #define AR_IMR_S4_RESV0 0xFFFFFC00 | ||
313 | |||
314 | #define AR_IMR_S5 0x00b8 | ||
315 | #define AR_IMR_S5_TIMER_TRIG 0x000000FF | ||
316 | #define AR_IMR_S5_TIMER_THRESH 0x0000FF00 | ||
317 | |||
318 | |||
319 | #define AR_ISR_RAC 0x00c0 | ||
320 | #define AR_ISR_S0_S 0x00c4 | ||
321 | #define AR_ISR_S0_QCU_TXOK 0x000003FF | ||
322 | #define AR_ISR_S0_QCU_TXOK_S 0 | ||
323 | #define AR_ISR_S0_QCU_TXDESC 0x03FF0000 | ||
324 | #define AR_ISR_S0_QCU_TXDESC_S 16 | ||
325 | |||
326 | #define AR_ISR_S1_S 0x00c8 | ||
327 | #define AR_ISR_S1_QCU_TXERR 0x000003FF | ||
328 | #define AR_ISR_S1_QCU_TXERR_S 0 | ||
329 | #define AR_ISR_S1_QCU_TXEOL 0x03FF0000 | ||
330 | #define AR_ISR_S1_QCU_TXEOL_S 16 | ||
331 | |||
332 | #define AR_ISR_S2_S 0x00cc | ||
333 | #define AR_ISR_S3_S 0x00d0 | ||
334 | #define AR_ISR_S4_S 0x00d4 | ||
335 | #define AR_ISR_S5_S 0x00d8 | ||
336 | #define AR_DMADBG_0 0x00e0 | ||
337 | #define AR_DMADBG_1 0x00e4 | ||
338 | #define AR_DMADBG_2 0x00e8 | ||
339 | #define AR_DMADBG_3 0x00ec | ||
340 | #define AR_DMADBG_4 0x00f0 | ||
341 | #define AR_DMADBG_5 0x00f4 | ||
342 | #define AR_DMADBG_6 0x00f8 | ||
343 | #define AR_DMADBG_7 0x00fc | ||
344 | |||
345 | #define AR_NUM_QCU 10 | ||
346 | #define AR_QCU_0 0x0001 | ||
347 | #define AR_QCU_1 0x0002 | ||
348 | #define AR_QCU_2 0x0004 | ||
349 | #define AR_QCU_3 0x0008 | ||
350 | #define AR_QCU_4 0x0010 | ||
351 | #define AR_QCU_5 0x0020 | ||
352 | #define AR_QCU_6 0x0040 | ||
353 | #define AR_QCU_7 0x0080 | ||
354 | #define AR_QCU_8 0x0100 | ||
355 | #define AR_QCU_9 0x0200 | ||
356 | |||
357 | #define AR_Q0_TXDP 0x0800 | ||
358 | #define AR_Q1_TXDP 0x0804 | ||
359 | #define AR_Q2_TXDP 0x0808 | ||
360 | #define AR_Q3_TXDP 0x080c | ||
361 | #define AR_Q4_TXDP 0x0810 | ||
362 | #define AR_Q5_TXDP 0x0814 | ||
363 | #define AR_Q6_TXDP 0x0818 | ||
364 | #define AR_Q7_TXDP 0x081c | ||
365 | #define AR_Q8_TXDP 0x0820 | ||
366 | #define AR_Q9_TXDP 0x0824 | ||
367 | #define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2)) | ||
368 | |||
369 | #define AR_Q_TXE 0x0840 | ||
370 | #define AR_Q_TXE_M 0x000003FF | ||
371 | |||
372 | #define AR_Q_TXD 0x0880 | ||
373 | #define AR_Q_TXD_M 0x000003FF | ||
374 | |||
375 | #define AR_Q0_CBRCFG 0x08c0 | ||
376 | #define AR_Q1_CBRCFG 0x08c4 | ||
377 | #define AR_Q2_CBRCFG 0x08c8 | ||
378 | #define AR_Q3_CBRCFG 0x08cc | ||
379 | #define AR_Q4_CBRCFG 0x08d0 | ||
380 | #define AR_Q5_CBRCFG 0x08d4 | ||
381 | #define AR_Q6_CBRCFG 0x08d8 | ||
382 | #define AR_Q7_CBRCFG 0x08dc | ||
383 | #define AR_Q8_CBRCFG 0x08e0 | ||
384 | #define AR_Q9_CBRCFG 0x08e4 | ||
385 | #define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2)) | ||
386 | #define AR_Q_CBRCFG_INTERVAL 0x00FFFFFF | ||
387 | #define AR_Q_CBRCFG_INTERVAL_S 0 | ||
388 | #define AR_Q_CBRCFG_OVF_THRESH 0xFF000000 | ||
389 | #define AR_Q_CBRCFG_OVF_THRESH_S 24 | ||
390 | |||
391 | #define AR_Q0_RDYTIMECFG 0x0900 | ||
392 | #define AR_Q1_RDYTIMECFG 0x0904 | ||
393 | #define AR_Q2_RDYTIMECFG 0x0908 | ||
394 | #define AR_Q3_RDYTIMECFG 0x090c | ||
395 | #define AR_Q4_RDYTIMECFG 0x0910 | ||
396 | #define AR_Q5_RDYTIMECFG 0x0914 | ||
397 | #define AR_Q6_RDYTIMECFG 0x0918 | ||
398 | #define AR_Q7_RDYTIMECFG 0x091c | ||
399 | #define AR_Q8_RDYTIMECFG 0x0920 | ||
400 | #define AR_Q9_RDYTIMECFG 0x0924 | ||
401 | #define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2)) | ||
402 | #define AR_Q_RDYTIMECFG_DURATION 0x00FFFFFF | ||
403 | #define AR_Q_RDYTIMECFG_DURATION_S 0 | ||
404 | #define AR_Q_RDYTIMECFG_EN 0x01000000 | ||
405 | |||
406 | #define AR_Q_ONESHOTARM_SC 0x0940 | ||
407 | #define AR_Q_ONESHOTARM_SC_M 0x000003FF | ||
408 | #define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00 | ||
409 | |||
410 | #define AR_Q_ONESHOTARM_CC 0x0980 | ||
411 | #define AR_Q_ONESHOTARM_CC_M 0x000003FF | ||
412 | #define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00 | ||
413 | |||
414 | #define AR_Q0_MISC 0x09c0 | ||
415 | #define AR_Q1_MISC 0x09c4 | ||
416 | #define AR_Q2_MISC 0x09c8 | ||
417 | #define AR_Q3_MISC 0x09cc | ||
418 | #define AR_Q4_MISC 0x09d0 | ||
419 | #define AR_Q5_MISC 0x09d4 | ||
420 | #define AR_Q6_MISC 0x09d8 | ||
421 | #define AR_Q7_MISC 0x09dc | ||
422 | #define AR_Q8_MISC 0x09e0 | ||
423 | #define AR_Q9_MISC 0x09e4 | ||
424 | #define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2)) | ||
425 | #define AR_Q_MISC_FSP 0x0000000F | ||
426 | #define AR_Q_MISC_FSP_ASAP 0 | ||
427 | #define AR_Q_MISC_FSP_CBR 1 | ||
428 | #define AR_Q_MISC_FSP_DBA_GATED 2 | ||
429 | #define AR_Q_MISC_FSP_TIM_GATED 3 | ||
430 | #define AR_Q_MISC_FSP_BEACON_SENT_GATED 4 | ||
431 | #define AR_Q_MISC_FSP_BEACON_RCVD_GATED 5 | ||
432 | #define AR_Q_MISC_ONE_SHOT_EN 0x00000010 | ||
433 | #define AR_Q_MISC_CBR_INCR_DIS1 0x00000020 | ||
434 | #define AR_Q_MISC_CBR_INCR_DIS0 0x00000040 | ||
435 | #define AR_Q_MISC_BEACON_USE 0x00000080 | ||
436 | #define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN 0x00000100 | ||
437 | #define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200 | ||
438 | #define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400 | ||
439 | #define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800 | ||
440 | #define AR_Q_MISC_RESV0 0xFFFFF000 | ||
441 | |||
442 | #define AR_Q0_STS 0x0a00 | ||
443 | #define AR_Q1_STS 0x0a04 | ||
444 | #define AR_Q2_STS 0x0a08 | ||
445 | #define AR_Q3_STS 0x0a0c | ||
446 | #define AR_Q4_STS 0x0a10 | ||
447 | #define AR_Q5_STS 0x0a14 | ||
448 | #define AR_Q6_STS 0x0a18 | ||
449 | #define AR_Q7_STS 0x0a1c | ||
450 | #define AR_Q8_STS 0x0a20 | ||
451 | #define AR_Q9_STS 0x0a24 | ||
452 | #define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2)) | ||
453 | #define AR_Q_STS_PEND_FR_CNT 0x00000003 | ||
454 | #define AR_Q_STS_RESV0 0x000000FC | ||
455 | #define AR_Q_STS_CBR_EXP_CNT 0x0000FF00 | ||
456 | #define AR_Q_STS_RESV1 0xFFFF0000 | ||
457 | |||
458 | #define AR_Q_RDYTIMESHDN 0x0a40 | ||
459 | #define AR_Q_RDYTIMESHDN_M 0x000003FF | ||
460 | |||
461 | |||
462 | #define AR_NUM_DCU 10 | ||
463 | #define AR_DCU_0 0x0001 | ||
464 | #define AR_DCU_1 0x0002 | ||
465 | #define AR_DCU_2 0x0004 | ||
466 | #define AR_DCU_3 0x0008 | ||
467 | #define AR_DCU_4 0x0010 | ||
468 | #define AR_DCU_5 0x0020 | ||
469 | #define AR_DCU_6 0x0040 | ||
470 | #define AR_DCU_7 0x0080 | ||
471 | #define AR_DCU_8 0x0100 | ||
472 | #define AR_DCU_9 0x0200 | ||
473 | |||
474 | #define AR_D0_QCUMASK 0x1000 | ||
475 | #define AR_D1_QCUMASK 0x1004 | ||
476 | #define AR_D2_QCUMASK 0x1008 | ||
477 | #define AR_D3_QCUMASK 0x100c | ||
478 | #define AR_D4_QCUMASK 0x1010 | ||
479 | #define AR_D5_QCUMASK 0x1014 | ||
480 | #define AR_D6_QCUMASK 0x1018 | ||
481 | #define AR_D7_QCUMASK 0x101c | ||
482 | #define AR_D8_QCUMASK 0x1020 | ||
483 | #define AR_D9_QCUMASK 0x1024 | ||
484 | #define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2)) | ||
485 | #define AR_D_QCUMASK 0x000003FF | ||
486 | #define AR_D_QCUMASK_RESV0 0xFFFFFC00 | ||
487 | |||
488 | #define AR_D_TXBLK_CMD 0x1038 | ||
489 | #define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) | ||
490 | |||
491 | #define AR_D0_LCL_IFS 0x1040 | ||
492 | #define AR_D1_LCL_IFS 0x1044 | ||
493 | #define AR_D2_LCL_IFS 0x1048 | ||
494 | #define AR_D3_LCL_IFS 0x104c | ||
495 | #define AR_D4_LCL_IFS 0x1050 | ||
496 | #define AR_D5_LCL_IFS 0x1054 | ||
497 | #define AR_D6_LCL_IFS 0x1058 | ||
498 | #define AR_D7_LCL_IFS 0x105c | ||
499 | #define AR_D8_LCL_IFS 0x1060 | ||
500 | #define AR_D9_LCL_IFS 0x1064 | ||
501 | #define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2)) | ||
502 | #define AR_D_LCL_IFS_CWMIN 0x000003FF | ||
503 | #define AR_D_LCL_IFS_CWMIN_S 0 | ||
504 | #define AR_D_LCL_IFS_CWMAX 0x000FFC00 | ||
505 | #define AR_D_LCL_IFS_CWMAX_S 10 | ||
506 | #define AR_D_LCL_IFS_AIFS 0x0FF00000 | ||
507 | #define AR_D_LCL_IFS_AIFS_S 20 | ||
508 | |||
509 | #define AR_D_LCL_IFS_RESV0 0xF0000000 | ||
510 | |||
511 | #define AR_D0_RETRY_LIMIT 0x1080 | ||
512 | #define AR_D1_RETRY_LIMIT 0x1084 | ||
513 | #define AR_D2_RETRY_LIMIT 0x1088 | ||
514 | #define AR_D3_RETRY_LIMIT 0x108c | ||
515 | #define AR_D4_RETRY_LIMIT 0x1090 | ||
516 | #define AR_D5_RETRY_LIMIT 0x1094 | ||
517 | #define AR_D6_RETRY_LIMIT 0x1098 | ||
518 | #define AR_D7_RETRY_LIMIT 0x109c | ||
519 | #define AR_D8_RETRY_LIMIT 0x10a0 | ||
520 | #define AR_D9_RETRY_LIMIT 0x10a4 | ||
521 | #define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2)) | ||
522 | #define AR_D_RETRY_LIMIT_FR_SH 0x0000000F | ||
523 | #define AR_D_RETRY_LIMIT_FR_SH_S 0 | ||
524 | #define AR_D_RETRY_LIMIT_STA_SH 0x00003F00 | ||
525 | #define AR_D_RETRY_LIMIT_STA_SH_S 8 | ||
526 | #define AR_D_RETRY_LIMIT_STA_LG 0x000FC000 | ||
527 | #define AR_D_RETRY_LIMIT_STA_LG_S 14 | ||
528 | #define AR_D_RETRY_LIMIT_RESV0 0xFFF00000 | ||
529 | |||
530 | #define AR_D0_CHNTIME 0x10c0 | ||
531 | #define AR_D1_CHNTIME 0x10c4 | ||
532 | #define AR_D2_CHNTIME 0x10c8 | ||
533 | #define AR_D3_CHNTIME 0x10cc | ||
534 | #define AR_D4_CHNTIME 0x10d0 | ||
535 | #define AR_D5_CHNTIME 0x10d4 | ||
536 | #define AR_D6_CHNTIME 0x10d8 | ||
537 | #define AR_D7_CHNTIME 0x10dc | ||
538 | #define AR_D8_CHNTIME 0x10e0 | ||
539 | #define AR_D9_CHNTIME 0x10e4 | ||
540 | #define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2)) | ||
541 | #define AR_D_CHNTIME_DUR 0x000FFFFF | ||
542 | #define AR_D_CHNTIME_DUR_S 0 | ||
543 | #define AR_D_CHNTIME_EN 0x00100000 | ||
544 | #define AR_D_CHNTIME_RESV0 0xFFE00000 | ||
545 | |||
546 | #define AR_D0_MISC 0x1100 | ||
547 | #define AR_D1_MISC 0x1104 | ||
548 | #define AR_D2_MISC 0x1108 | ||
549 | #define AR_D3_MISC 0x110c | ||
550 | #define AR_D4_MISC 0x1110 | ||
551 | #define AR_D5_MISC 0x1114 | ||
552 | #define AR_D6_MISC 0x1118 | ||
553 | #define AR_D7_MISC 0x111c | ||
554 | #define AR_D8_MISC 0x1120 | ||
555 | #define AR_D9_MISC 0x1124 | ||
556 | #define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2)) | ||
557 | #define AR_D_MISC_BKOFF_THRESH 0x0000003F | ||
558 | #define AR_D_MISC_RETRY_CNT_RESET_EN 0x00000040 | ||
559 | #define AR_D_MISC_CW_RESET_EN 0x00000080 | ||
560 | #define AR_D_MISC_FRAG_WAIT_EN 0x00000100 | ||
561 | #define AR_D_MISC_FRAG_BKOFF_EN 0x00000200 | ||
562 | #define AR_D_MISC_CW_BKOFF_EN 0x00001000 | ||
563 | #define AR_D_MISC_VIR_COL_HANDLING 0x0000C000 | ||
564 | #define AR_D_MISC_VIR_COL_HANDLING_S 14 | ||
565 | #define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0 | ||
566 | #define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1 | ||
567 | #define AR_D_MISC_BEACON_USE 0x00010000 | ||
568 | #define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000 | ||
569 | #define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17 | ||
570 | #define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0 | ||
571 | #define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1 | ||
572 | #define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2 | ||
573 | #define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000 | ||
574 | #define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000 | ||
575 | #define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000 | ||
576 | #define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000 | ||
577 | #define AR_D_MISC_BLOWN_IFS_RETRY_EN 0x00800000 | ||
578 | #define AR_D_MISC_RESV0 0xFF000000 | ||
579 | |||
580 | #define AR_D_SEQNUM 0x1140 | ||
581 | |||
582 | #define AR_D_GBL_IFS_SIFS 0x1030 | ||
583 | #define AR_D_GBL_IFS_SIFS_M 0x0000FFFF | ||
584 | #define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF | ||
585 | |||
586 | #define AR_D_TXBLK_BASE 0x1038 | ||
587 | #define AR_D_TXBLK_WRITE_BITMASK 0x0000FFFF | ||
588 | #define AR_D_TXBLK_WRITE_BITMASK_S 0 | ||
589 | #define AR_D_TXBLK_WRITE_SLICE 0x000F0000 | ||
590 | #define AR_D_TXBLK_WRITE_SLICE_S 16 | ||
591 | #define AR_D_TXBLK_WRITE_DCU 0x00F00000 | ||
592 | #define AR_D_TXBLK_WRITE_DCU_S 20 | ||
593 | #define AR_D_TXBLK_WRITE_COMMAND 0x0F000000 | ||
594 | #define AR_D_TXBLK_WRITE_COMMAND_S 24 | ||
595 | |||
596 | #define AR_D_GBL_IFS_SLOT 0x1070 | ||
597 | #define AR_D_GBL_IFS_SLOT_M 0x0000FFFF | ||
598 | #define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000 | ||
599 | |||
600 | #define AR_D_GBL_IFS_EIFS 0x10b0 | ||
601 | #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF | ||
602 | #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 | ||
603 | |||
604 | #define AR_D_GBL_IFS_MISC 0x10f0 | ||
605 | #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 | ||
606 | #define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008 | ||
607 | #define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00 | ||
608 | #define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000 | ||
609 | #define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000 | ||
610 | #define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN 0x06000000 | ||
611 | #define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000 | ||
612 | #define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF 0x10000000 | ||
613 | |||
614 | #define AR_D_FPCTL 0x1230 | ||
615 | #define AR_D_FPCTL_DCU 0x0000000F | ||
616 | #define AR_D_FPCTL_DCU_S 0 | ||
617 | #define AR_D_FPCTL_PREFETCH_EN 0x00000010 | ||
618 | #define AR_D_FPCTL_BURST_PREFETCH 0x00007FE0 | ||
619 | #define AR_D_FPCTL_BURST_PREFETCH_S 5 | ||
620 | |||
621 | #define AR_D_TXPSE 0x1270 | ||
622 | #define AR_D_TXPSE_CTRL 0x000003FF | ||
623 | #define AR_D_TXPSE_RESV0 0x0000FC00 | ||
624 | #define AR_D_TXPSE_STATUS 0x00010000 | ||
625 | #define AR_D_TXPSE_RESV1 0xFFFE0000 | ||
626 | |||
627 | #define AR_D_TXSLOTMASK 0x12f0 | ||
628 | #define AR_D_TXSLOTMASK_NUM 0x0000000F | ||
629 | |||
630 | #define AR_CFG_LED 0x1f04 | ||
631 | #define AR_CFG_SCLK_RATE_IND 0x00000003 | ||
632 | #define AR_CFG_SCLK_RATE_IND_S 0 | ||
633 | #define AR_CFG_SCLK_32MHZ 0x00000000 | ||
634 | #define AR_CFG_SCLK_4MHZ 0x00000001 | ||
635 | #define AR_CFG_SCLK_1MHZ 0x00000002 | ||
636 | #define AR_CFG_SCLK_32KHZ 0x00000003 | ||
637 | #define AR_CFG_LED_BLINK_SLOW 0x00000008 | ||
638 | #define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 | ||
639 | #define AR_CFG_LED_MODE_SEL 0x00000380 | ||
640 | #define AR_CFG_LED_MODE_SEL_S 7 | ||
641 | #define AR_CFG_LED_POWER 0x00000280 | ||
642 | #define AR_CFG_LED_POWER_S 7 | ||
643 | #define AR_CFG_LED_NETWORK 0x00000300 | ||
644 | #define AR_CFG_LED_NETWORK_S 7 | ||
645 | #define AR_CFG_LED_MODE_PROP 0x0 | ||
646 | #define AR_CFG_LED_MODE_RPROP 0x1 | ||
647 | #define AR_CFG_LED_MODE_SPLIT 0x2 | ||
648 | #define AR_CFG_LED_MODE_RAND 0x3 | ||
649 | #define AR_CFG_LED_MODE_POWER_OFF 0x4 | ||
650 | #define AR_CFG_LED_MODE_POWER_ON 0x5 | ||
651 | #define AR_CFG_LED_MODE_NETWORK_OFF 0x4 | ||
652 | #define AR_CFG_LED_MODE_NETWORK_ON 0x6 | ||
653 | #define AR_CFG_LED_ASSOC_CTL 0x00000c00 | ||
654 | #define AR_CFG_LED_ASSOC_CTL_S 10 | ||
655 | #define AR_CFG_LED_ASSOC_NONE 0x0 | ||
656 | #define AR_CFG_LED_ASSOC_ACTIVE 0x1 | ||
657 | #define AR_CFG_LED_ASSOC_PENDING 0x2 | ||
658 | |||
659 | #define AR_CFG_LED_BLINK_SLOW 0x00000008 | ||
660 | #define AR_CFG_LED_BLINK_SLOW_S 3 | ||
661 | |||
662 | #define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 | ||
663 | #define AR_CFG_LED_BLINK_THRESH_SEL_S 4 | ||
664 | |||
665 | #define AR_MAC_SLEEP 0x1f00 | ||
666 | #define AR_MAC_SLEEP_MAC_AWAKE 0x00000000 | ||
667 | #define AR_MAC_SLEEP_MAC_ASLEEP 0x00000001 | ||
668 | |||
669 | #define AR_RC 0x4000 | ||
670 | #define AR_RC_AHB 0x00000001 | ||
671 | #define AR_RC_APB 0x00000002 | ||
672 | #define AR_RC_HOSTIF 0x00000100 | ||
673 | |||
674 | #define AR_WA 0x4004 | ||
675 | |||
676 | #define AR_PM_STATE 0x4008 | ||
677 | #define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 | ||
678 | |||
679 | #define AR_HOST_TIMEOUT 0x4018 | ||
680 | #define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF | ||
681 | #define AR_HOST_TIMEOUT_APB_CNTR_S 0 | ||
682 | #define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 | ||
683 | #define AR_HOST_TIMEOUT_LCL_CNTR_S 16 | ||
684 | |||
685 | #define AR_EEPROM 0x401c | ||
686 | #define AR_EEPROM_ABSENT 0x00000100 | ||
687 | #define AR_EEPROM_CORRUPT 0x00000200 | ||
688 | #define AR_EEPROM_PROT_MASK 0x03FFFC00 | ||
689 | #define AR_EEPROM_PROT_MASK_S 10 | ||
690 | |||
691 | #define EEPROM_PROTECT_RP_0_31 0x0001 | ||
692 | #define EEPROM_PROTECT_WP_0_31 0x0002 | ||
693 | #define EEPROM_PROTECT_RP_32_63 0x0004 | ||
694 | #define EEPROM_PROTECT_WP_32_63 0x0008 | ||
695 | #define EEPROM_PROTECT_RP_64_127 0x0010 | ||
696 | #define EEPROM_PROTECT_WP_64_127 0x0020 | ||
697 | #define EEPROM_PROTECT_RP_128_191 0x0040 | ||
698 | #define EEPROM_PROTECT_WP_128_191 0x0080 | ||
699 | #define EEPROM_PROTECT_RP_192_255 0x0100 | ||
700 | #define EEPROM_PROTECT_WP_192_255 0x0200 | ||
701 | #define EEPROM_PROTECT_RP_256_511 0x0400 | ||
702 | #define EEPROM_PROTECT_WP_256_511 0x0800 | ||
703 | #define EEPROM_PROTECT_RP_512_1023 0x1000 | ||
704 | #define EEPROM_PROTECT_WP_512_1023 0x2000 | ||
705 | #define EEPROM_PROTECT_RP_1024_2047 0x4000 | ||
706 | #define EEPROM_PROTECT_WP_1024_2047 0x8000 | ||
707 | |||
708 | #define AR_SREV \ | ||
709 | ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020) | ||
710 | |||
711 | #define AR_SREV_ID \ | ||
712 | ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF) | ||
713 | #define AR_SREV_VERSION 0x000000F0 | ||
714 | #define AR_SREV_VERSION_S 4 | ||
715 | #define AR_SREV_REVISION 0x00000007 | ||
716 | |||
717 | #define AR_SREV_ID2 0xFFFFFFFF | ||
718 | #define AR_SREV_VERSION2 0xFFFC0000 | ||
719 | #define AR_SREV_VERSION2_S 18 | ||
720 | #define AR_SREV_TYPE2 0x0003F000 | ||
721 | #define AR_SREV_TYPE2_S 12 | ||
722 | #define AR_SREV_TYPE2_CHAIN 0x00001000 | ||
723 | #define AR_SREV_TYPE2_HOST_MODE 0x00002000 | ||
724 | #define AR_SREV_REVISION2 0x00000F00 | ||
725 | #define AR_SREV_REVISION2_S 8 | ||
726 | |||
727 | #define AR_SREV_VERSION_5416_PCI 0xD | ||
728 | #define AR_SREV_VERSION_5416_PCIE 0xC | ||
729 | #define AR_SREV_REVISION_5416_10 0 | ||
730 | #define AR_SREV_REVISION_5416_20 1 | ||
731 | #define AR_SREV_REVISION_5416_22 2 | ||
732 | #define AR_SREV_VERSION_9160 0x40 | ||
733 | #define AR_SREV_REVISION_9160_10 0 | ||
734 | #define AR_SREV_REVISION_9160_11 1 | ||
735 | #define AR_SREV_VERSION_9280 0x80 | ||
736 | #define AR_SREV_REVISION_9280_10 0 | ||
737 | #define AR_SREV_REVISION_9280_20 1 | ||
738 | #define AR_SREV_REVISION_9280_21 2 | ||
739 | #define AR_SREV_VERSION_9285 0xC0 | ||
740 | #define AR_SREV_REVISION_9285_10 0 | ||
741 | |||
742 | #define AR_SREV_9100_OR_LATER(_ah) \ | ||
743 | (((_ah)->ah_macVersion >= AR_SREV_VERSION_5416_PCIE)) | ||
744 | #define AR_SREV_5416_20_OR_LATER(_ah) \ | ||
745 | (((_ah)->ah_macVersion >= AR_SREV_VERSION_9160) || \ | ||
746 | ((_ah)->ah_macRev >= AR_SREV_REVISION_5416_20)) | ||
747 | #define AR_SREV_5416_22_OR_LATER(_ah) \ | ||
748 | (((_ah)->ah_macVersion >= AR_SREV_VERSION_9160) || \ | ||
749 | ((_ah)->ah_macRev >= AR_SREV_REVISION_5416_22)) | ||
750 | #define AR_SREV_9160(_ah) \ | ||
751 | (((_ah)->ah_macVersion == AR_SREV_VERSION_9160)) | ||
752 | #define AR_SREV_9160_10_OR_LATER(_ah) \ | ||
753 | (((_ah)->ah_macVersion >= AR_SREV_VERSION_9160)) | ||
754 | #define AR_SREV_9160_11(_ah) \ | ||
755 | (AR_SREV_9160(_ah) && ((_ah)->ah_macRev == AR_SREV_REVISION_9160_11)) | ||
756 | #define AR_SREV_9280(_ah) \ | ||
757 | (((_ah)->ah_macVersion == AR_SREV_VERSION_9280)) | ||
758 | #define AR_SREV_9280_10_OR_LATER(_ah) \ | ||
759 | (((_ah)->ah_macVersion >= AR_SREV_VERSION_9280)) | ||
760 | #define AR_SREV_9280_20(_ah) \ | ||
761 | (((_ah)->ah_macVersion == AR_SREV_VERSION_9280) && \ | ||
762 | ((_ah)->ah_macRev >= AR_SREV_REVISION_9280_20)) | ||
763 | #define AR_SREV_9280_20_OR_LATER(_ah) \ | ||
764 | (((_ah)->ah_macVersion > AR_SREV_VERSION_9280) || \ | ||
765 | (((_ah)->ah_macVersion == AR_SREV_VERSION_9280) && \ | ||
766 | ((_ah)->ah_macRev >= AR_SREV_REVISION_9280_20))) | ||
767 | |||
768 | #define AR_SREV_9285(_ah) (((_ah)->ah_macVersion == AR_SREV_VERSION_9285)) | ||
769 | #define AR_SREV_9285_10_OR_LATER(_ah) \ | ||
770 | (((_ah)->ah_macVersion >= AR_SREV_VERSION_9285)) | ||
771 | |||
772 | #define AR_RADIO_SREV_MAJOR 0xf0 | ||
773 | #define AR_RAD5133_SREV_MAJOR 0xc0 | ||
774 | #define AR_RAD2133_SREV_MAJOR 0xd0 | ||
775 | #define AR_RAD5122_SREV_MAJOR 0xe0 | ||
776 | #define AR_RAD2122_SREV_MAJOR 0xf0 | ||
777 | |||
778 | #define AR_AHB_MODE 0x4024 | ||
779 | #define AR_AHB_EXACT_WR_EN 0x00000000 | ||
780 | #define AR_AHB_BUF_WR_EN 0x00000001 | ||
781 | #define AR_AHB_EXACT_RD_EN 0x00000000 | ||
782 | #define AR_AHB_CACHELINE_RD_EN 0x00000002 | ||
783 | #define AR_AHB_PREFETCH_RD_EN 0x00000004 | ||
784 | #define AR_AHB_PAGE_SIZE_1K 0x00000000 | ||
785 | #define AR_AHB_PAGE_SIZE_2K 0x00000008 | ||
786 | #define AR_AHB_PAGE_SIZE_4K 0x00000010 | ||
787 | |||
788 | #define AR_INTR_RTC_IRQ 0x00000001 | ||
789 | #define AR_INTR_MAC_IRQ 0x00000002 | ||
790 | #define AR_INTR_EEP_PROT_ACCESS 0x00000004 | ||
791 | #define AR_INTR_MAC_AWAKE 0x00020000 | ||
792 | #define AR_INTR_MAC_ASLEEP 0x00040000 | ||
793 | #define AR_INTR_SPURIOUS 0xFFFFFFFF | ||
794 | |||
795 | |||
796 | #define AR_INTR_SYNC_CAUSE_CLR 0x4028 | ||
797 | |||
798 | #define AR_INTR_SYNC_CAUSE 0x4028 | ||
799 | |||
800 | #define AR_INTR_SYNC_ENABLE 0x402c | ||
801 | #define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 | ||
802 | #define AR_INTR_SYNC_ENABLE_GPIO_S 18 | ||
803 | |||
804 | enum { | ||
805 | AR_INTR_SYNC_RTC_IRQ = 0x00000001, | ||
806 | AR_INTR_SYNC_MAC_IRQ = 0x00000002, | ||
807 | AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004, | ||
808 | AR_INTR_SYNC_APB_TIMEOUT = 0x00000008, | ||
809 | AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010, | ||
810 | AR_INTR_SYNC_HOST1_FATAL = 0x00000020, | ||
811 | AR_INTR_SYNC_HOST1_PERR = 0x00000040, | ||
812 | AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080, | ||
813 | AR_INTR_SYNC_RADM_CPL_EP = 0x00000100, | ||
814 | AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200, | ||
815 | AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400, | ||
816 | AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800, | ||
817 | AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000, | ||
818 | AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000, | ||
819 | AR_INTR_SYNC_PM_ACCESS = 0x00004000, | ||
820 | AR_INTR_SYNC_MAC_AWAKE = 0x00008000, | ||
821 | AR_INTR_SYNC_MAC_ASLEEP = 0x00010000, | ||
822 | AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000, | ||
823 | AR_INTR_SYNC_ALL = 0x0003FFFF, | ||
824 | |||
825 | |||
826 | AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL | | ||
827 | AR_INTR_SYNC_HOST1_PERR | | ||
828 | AR_INTR_SYNC_RADM_CPL_EP | | ||
829 | AR_INTR_SYNC_RADM_CPL_DLLP_ABORT | | ||
830 | AR_INTR_SYNC_RADM_CPL_TLP_ABORT | | ||
831 | AR_INTR_SYNC_RADM_CPL_ECRC_ERR | | ||
832 | AR_INTR_SYNC_RADM_CPL_TIMEOUT | | ||
833 | AR_INTR_SYNC_LOCAL_TIMEOUT | | ||
834 | AR_INTR_SYNC_MAC_SLEEP_ACCESS), | ||
835 | |||
836 | AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF, | ||
837 | |||
838 | }; | ||
839 | |||
840 | #define AR_INTR_ASYNC_MASK 0x4030 | ||
841 | #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 | ||
842 | #define AR_INTR_ASYNC_MASK_GPIO_S 18 | ||
843 | |||
844 | #define AR_INTR_SYNC_MASK 0x4034 | ||
845 | #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 | ||
846 | #define AR_INTR_SYNC_MASK_GPIO_S 18 | ||
847 | |||
848 | #define AR_INTR_ASYNC_CAUSE_CLR 0x4038 | ||
849 | #define AR_INTR_ASYNC_CAUSE 0x4038 | ||
850 | |||
851 | #define AR_INTR_ASYNC_ENABLE 0x403c | ||
852 | #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 | ||
853 | #define AR_INTR_ASYNC_ENABLE_GPIO_S 18 | ||
854 | |||
855 | #define AR_PCIE_SERDES 0x4040 | ||
856 | #define AR_PCIE_SERDES2 0x4044 | ||
857 | #define AR_PCIE_PM_CTRL 0x4014 | ||
858 | #define AR_PCIE_PM_CTRL_ENA 0x00080000 | ||
859 | |||
860 | #define AR_NUM_GPIO 14 | ||
861 | #define AR928X_NUM_GPIO 10 | ||
862 | |||
863 | #define AR_GPIO_IN_OUT 0x4048 | ||
864 | #define AR_GPIO_IN_VAL 0x0FFFC000 | ||
865 | #define AR_GPIO_IN_VAL_S 14 | ||
866 | #define AR928X_GPIO_IN_VAL 0x000FFC00 | ||
867 | #define AR928X_GPIO_IN_VAL_S 10 | ||
868 | |||
869 | #define AR_GPIO_OE_OUT 0x404c | ||
870 | #define AR_GPIO_OE_OUT_DRV 0x3 | ||
871 | #define AR_GPIO_OE_OUT_DRV_NO 0x0 | ||
872 | #define AR_GPIO_OE_OUT_DRV_LOW 0x1 | ||
873 | #define AR_GPIO_OE_OUT_DRV_HI 0x2 | ||
874 | #define AR_GPIO_OE_OUT_DRV_ALL 0x3 | ||
875 | |||
876 | #define AR_GPIO_INTR_POL 0x4050 | ||
877 | #define AR_GPIO_INTR_POL_VAL 0x00001FFF | ||
878 | #define AR_GPIO_INTR_POL_VAL_S 0 | ||
879 | |||
880 | #define AR_GPIO_INPUT_EN_VAL 0x4054 | ||
881 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080 | ||
882 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 | ||
883 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 | ||
884 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 | ||
885 | #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 | ||
886 | #define AR_GPIO_JTAG_DISABLE 0x00020000 | ||
887 | |||
888 | #define AR_GPIO_INPUT_MUX1 0x4058 | ||
889 | |||
890 | #define AR_GPIO_INPUT_MUX2 0x405c | ||
891 | #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f | ||
892 | #define AR_GPIO_INPUT_MUX2_CLK25_S 0 | ||
893 | #define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 | ||
894 | #define AR_GPIO_INPUT_MUX2_RFSILENT_S 4 | ||
895 | #define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 | ||
896 | #define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 | ||
897 | |||
898 | #define AR_GPIO_OUTPUT_MUX1 0x4060 | ||
899 | #define AR_GPIO_OUTPUT_MUX2 0x4064 | ||
900 | #define AR_GPIO_OUTPUT_MUX3 0x4068 | ||
901 | |||
902 | #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 | ||
903 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 | ||
904 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 | ||
905 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 | ||
906 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 | ||
907 | |||
908 | #define AR_INPUT_STATE 0x406c | ||
909 | |||
910 | #define AR_EEPROM_STATUS_DATA 0x407c | ||
911 | #define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff | ||
912 | #define AR_EEPROM_STATUS_DATA_VAL_S 0 | ||
913 | #define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 | ||
914 | #define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000 | ||
915 | #define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 | ||
916 | #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 | ||
917 | |||
918 | #define AR_OBS 0x4080 | ||
919 | |||
920 | #define AR_PCIE_MSI 0x4094 | ||
921 | #define AR_PCIE_MSI_ENABLE 0x00000001 | ||
922 | |||
923 | |||
924 | #define AR_RTC_9160_PLL_DIV 0x000003ff | ||
925 | #define AR_RTC_9160_PLL_DIV_S 0 | ||
926 | #define AR_RTC_9160_PLL_REFDIV 0x00003C00 | ||
927 | #define AR_RTC_9160_PLL_REFDIV_S 10 | ||
928 | #define AR_RTC_9160_PLL_CLKSEL 0x0000C000 | ||
929 | #define AR_RTC_9160_PLL_CLKSEL_S 14 | ||
930 | |||
931 | #define AR_RTC_BASE 0x00020000 | ||
932 | #define AR_RTC_RC \ | ||
933 | (AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000 | ||
934 | #define AR_RTC_RC_M 0x00000003 | ||
935 | #define AR_RTC_RC_MAC_WARM 0x00000001 | ||
936 | #define AR_RTC_RC_MAC_COLD 0x00000002 | ||
937 | #define AR_RTC_RC_COLD_RESET 0x00000004 | ||
938 | #define AR_RTC_RC_WARM_RESET 0x00000008 | ||
939 | |||
940 | #define AR_RTC_PLL_CONTROL \ | ||
941 | (AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014 | ||
942 | |||
943 | #define AR_RTC_PLL_DIV 0x0000001f | ||
944 | #define AR_RTC_PLL_DIV_S 0 | ||
945 | #define AR_RTC_PLL_DIV2 0x00000020 | ||
946 | #define AR_RTC_PLL_REFDIV_5 0x000000c0 | ||
947 | #define AR_RTC_PLL_CLKSEL 0x00000300 | ||
948 | #define AR_RTC_PLL_CLKSEL_S 8 | ||
949 | |||
950 | |||
951 | |||
952 | #define AR_RTC_RESET \ | ||
953 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040) | ||
954 | #define AR_RTC_RESET_EN (0x00000001) | ||
955 | |||
956 | #define AR_RTC_STATUS \ | ||
957 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044) | ||
958 | |||
959 | #define AR_RTC_STATUS_M \ | ||
960 | ((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f) | ||
961 | |||
962 | #define AR_RTC_PM_STATUS_M 0x0000000f | ||
963 | |||
964 | #define AR_RTC_STATUS_SHUTDOWN 0x00000001 | ||
965 | #define AR_RTC_STATUS_ON 0x00000002 | ||
966 | #define AR_RTC_STATUS_SLEEP 0x00000004 | ||
967 | #define AR_RTC_STATUS_WAKEUP 0x00000008 | ||
968 | |||
969 | #define AR_RTC_SLEEP_CLK \ | ||
970 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048) | ||
971 | #define AR_RTC_FORCE_DERIVED_CLK 0x2 | ||
972 | |||
973 | #define AR_RTC_FORCE_WAKE \ | ||
974 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c) | ||
975 | #define AR_RTC_FORCE_WAKE_EN 0x00000001 | ||
976 | #define AR_RTC_FORCE_WAKE_ON_INT 0x00000002 | ||
977 | |||
978 | |||
979 | #define AR_RTC_INTR_CAUSE \ | ||
980 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050) | ||
981 | |||
982 | #define AR_RTC_INTR_ENABLE \ | ||
983 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054) | ||
984 | |||
985 | #define AR_RTC_INTR_MASK \ | ||
986 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058) | ||
987 | |||
988 | #define AR_SEQ_MASK 0x8060 | ||
989 | |||
990 | #define AR_AN_RF2G1_CH0 0x7810 | ||
991 | #define AR_AN_RF2G1_CH0_OB 0x03800000 | ||
992 | #define AR_AN_RF2G1_CH0_OB_S 23 | ||
993 | #define AR_AN_RF2G1_CH0_DB 0x1C000000 | ||
994 | #define AR_AN_RF2G1_CH0_DB_S 26 | ||
995 | |||
996 | #define AR_AN_RF5G1_CH0 0x7818 | ||
997 | #define AR_AN_RF5G1_CH0_OB5 0x00070000 | ||
998 | #define AR_AN_RF5G1_CH0_OB5_S 16 | ||
999 | #define AR_AN_RF5G1_CH0_DB5 0x00380000 | ||
1000 | #define AR_AN_RF5G1_CH0_DB5_S 19 | ||
1001 | |||
1002 | #define AR_AN_RF2G1_CH1 0x7834 | ||
1003 | #define AR_AN_RF2G1_CH1_OB 0x03800000 | ||
1004 | #define AR_AN_RF2G1_CH1_OB_S 23 | ||
1005 | #define AR_AN_RF2G1_CH1_DB 0x1C000000 | ||
1006 | #define AR_AN_RF2G1_CH1_DB_S 26 | ||
1007 | |||
1008 | #define AR_AN_RF5G1_CH1 0x783C | ||
1009 | #define AR_AN_RF5G1_CH1_OB5 0x00070000 | ||
1010 | #define AR_AN_RF5G1_CH1_OB5_S 16 | ||
1011 | #define AR_AN_RF5G1_CH1_DB5 0x00380000 | ||
1012 | #define AR_AN_RF5G1_CH1_DB5_S 19 | ||
1013 | |||
1014 | #define AR_AN_TOP2 0x7894 | ||
1015 | #define AR_AN_TOP2_XPABIAS_LVL 0xC0000000 | ||
1016 | #define AR_AN_TOP2_XPABIAS_LVL_S 30 | ||
1017 | #define AR_AN_TOP2_LOCALBIAS 0x00200000 | ||
1018 | #define AR_AN_TOP2_LOCALBIAS_S 21 | ||
1019 | #define AR_AN_TOP2_PWDCLKIND 0x00400000 | ||
1020 | #define AR_AN_TOP2_PWDCLKIND_S 22 | ||
1021 | |||
1022 | #define AR_AN_SYNTH9 0x7868 | ||
1023 | #define AR_AN_SYNTH9_REFDIVA 0xf8000000 | ||
1024 | #define AR_AN_SYNTH9_REFDIVA_S 27 | ||
1025 | |||
1026 | #define AR_STA_ID0 0x8000 | ||
1027 | #define AR_STA_ID1 0x8004 | ||
1028 | #define AR_STA_ID1_SADH_MASK 0x0000FFFF | ||
1029 | #define AR_STA_ID1_STA_AP 0x00010000 | ||
1030 | #define AR_STA_ID1_ADHOC 0x00020000 | ||
1031 | #define AR_STA_ID1_PWR_SAV 0x00040000 | ||
1032 | #define AR_STA_ID1_KSRCHDIS 0x00080000 | ||
1033 | #define AR_STA_ID1_PCF 0x00100000 | ||
1034 | #define AR_STA_ID1_USE_DEFANT 0x00200000 | ||
1035 | #define AR_STA_ID1_DEFANT_UPDATE 0x00400000 | ||
1036 | #define AR_STA_ID1_RTS_USE_DEF 0x00800000 | ||
1037 | #define AR_STA_ID1_ACKCTS_6MB 0x01000000 | ||
1038 | #define AR_STA_ID1_BASE_RATE_11B 0x02000000 | ||
1039 | #define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000 | ||
1040 | #define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000 | ||
1041 | #define AR_STA_ID1_KSRCH_MODE 0x10000000 | ||
1042 | #define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000 | ||
1043 | #define AR_STA_ID1_CBCIV_ENDIAN 0x40000000 | ||
1044 | #define AR_STA_ID1_MCAST_KSRCH 0x80000000 | ||
1045 | |||
1046 | #define AR_BSS_ID0 0x8008 | ||
1047 | #define AR_BSS_ID1 0x800C | ||
1048 | #define AR_BSS_ID1_U16 0x0000FFFF | ||
1049 | #define AR_BSS_ID1_AID 0x07FF0000 | ||
1050 | #define AR_BSS_ID1_AID_S 16 | ||
1051 | |||
1052 | #define AR_BCN_RSSI_AVE 0x8010 | ||
1053 | #define AR_BCN_RSSI_AVE_MASK 0x00000FFF | ||
1054 | |||
1055 | #define AR_TIME_OUT 0x8014 | ||
1056 | #define AR_TIME_OUT_ACK 0x00003FFF | ||
1057 | #define AR_TIME_OUT_ACK_S 0 | ||
1058 | #define AR_TIME_OUT_CTS 0x3FFF0000 | ||
1059 | #define AR_TIME_OUT_CTS_S 16 | ||
1060 | |||
1061 | #define AR_RSSI_THR 0x8018 | ||
1062 | #define AR_RSSI_THR_MASK 0x000000FF | ||
1063 | #define AR_RSSI_THR_BM_THR 0x0000FF00 | ||
1064 | #define AR_RSSI_THR_BM_THR_S 8 | ||
1065 | #define AR_RSSI_BCN_WEIGHT 0x1F000000 | ||
1066 | #define AR_RSSI_BCN_WEIGHT_S 24 | ||
1067 | #define AR_RSSI_BCN_RSSI_RST 0x20000000 | ||
1068 | |||
1069 | #define AR_USEC 0x801c | ||
1070 | #define AR_USEC_USEC 0x0000007F | ||
1071 | #define AR_USEC_TX_LAT 0x007FC000 | ||
1072 | #define AR_USEC_TX_LAT_S 14 | ||
1073 | #define AR_USEC_RX_LAT 0x1F800000 | ||
1074 | #define AR_USEC_RX_LAT_S 23 | ||
1075 | |||
1076 | #define AR_RESET_TSF 0x8020 | ||
1077 | #define AR_RESET_TSF_ONCE 0x01000000 | ||
1078 | |||
1079 | #define AR_MAX_CFP_DUR 0x8038 | ||
1080 | #define AR_CFP_VAL 0x0000FFFF | ||
1081 | |||
1082 | #define AR_RX_FILTER 0x803C | ||
1083 | #define AR_RX_FILTER_ALL 0x00000000 | ||
1084 | #define AR_RX_UCAST 0x00000001 | ||
1085 | #define AR_RX_MCAST 0x00000002 | ||
1086 | #define AR_RX_BCAST 0x00000004 | ||
1087 | #define AR_RX_CONTROL 0x00000008 | ||
1088 | #define AR_RX_BEACON 0x00000010 | ||
1089 | #define AR_RX_PROM 0x00000020 | ||
1090 | #define AR_RX_PROBE_REQ 0x00000080 | ||
1091 | #define AR_RX_MY_BEACON 0x00000200 | ||
1092 | #define AR_RX_COMPR_BAR 0x00000400 | ||
1093 | #define AR_RX_COMPR_BA 0x00000800 | ||
1094 | #define AR_RX_UNCOM_BA_BAR 0x00001000 | ||
1095 | |||
1096 | #define AR_MCAST_FIL0 0x8040 | ||
1097 | #define AR_MCAST_FIL1 0x8044 | ||
1098 | |||
1099 | #define AR_DIAG_SW 0x8048 | ||
1100 | #define AR_DIAG_CACHE_ACK 0x00000001 | ||
1101 | #define AR_DIAG_ACK_DIS 0x00000002 | ||
1102 | #define AR_DIAG_CTS_DIS 0x00000004 | ||
1103 | #define AR_DIAG_ENCRYPT_DIS 0x00000008 | ||
1104 | #define AR_DIAG_DECRYPT_DIS 0x00000010 | ||
1105 | #define AR_DIAG_RX_DIS 0x00000020 | ||
1106 | #define AR_DIAG_LOOP_BACK 0x00000040 | ||
1107 | #define AR_DIAG_CORR_FCS 0x00000080 | ||
1108 | #define AR_DIAG_CHAN_INFO 0x00000100 | ||
1109 | #define AR_DIAG_SCRAM_SEED 0x0001FE00 | ||
1110 | #define AR_DIAG_SCRAM_SEED_S 8 | ||
1111 | #define AR_DIAG_FRAME_NV0 0x00020000 | ||
1112 | #define AR_DIAG_OBS_PT_SEL1 0x000C0000 | ||
1113 | #define AR_DIAG_OBS_PT_SEL1_S 18 | ||
1114 | #define AR_DIAG_FORCE_RX_CLEAR 0x00100000 | ||
1115 | #define AR_DIAG_IGNORE_VIRT_CS 0x00200000 | ||
1116 | #define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000 | ||
1117 | #define AR_DIAG_EIFS_CTRL_ENA 0x00800000 | ||
1118 | #define AR_DIAG_DUAL_CHAIN_INFO 0x01000000 | ||
1119 | #define AR_DIAG_RX_ABORT 0x02000000 | ||
1120 | #define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000 | ||
1121 | #define AR_DIAG_OBS_PT_SEL2 0x08000000 | ||
1122 | #define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000 | ||
1123 | #define AR_DIAG_RX_CLEAR_EXT_LOW 0x20000000 | ||
1124 | |||
1125 | #define AR_TSF_L32 0x804c | ||
1126 | #define AR_TSF_U32 0x8050 | ||
1127 | |||
1128 | #define AR_TST_ADDAC 0x8054 | ||
1129 | #define AR_DEF_ANTENNA 0x8058 | ||
1130 | |||
1131 | #define AR_AES_MUTE_MASK0 0x805c | ||
1132 | #define AR_AES_MUTE_MASK0_FC 0x0000FFFF | ||
1133 | #define AR_AES_MUTE_MASK0_QOS 0xFFFF0000 | ||
1134 | #define AR_AES_MUTE_MASK0_QOS_S 16 | ||
1135 | |||
1136 | #define AR_AES_MUTE_MASK1 0x8060 | ||
1137 | #define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF | ||
1138 | |||
1139 | #define AR_GATED_CLKS 0x8064 | ||
1140 | #define AR_GATED_CLKS_TX 0x00000002 | ||
1141 | #define AR_GATED_CLKS_RX 0x00000004 | ||
1142 | #define AR_GATED_CLKS_REG 0x00000008 | ||
1143 | |||
1144 | #define AR_OBS_BUS_CTRL 0x8068 | ||
1145 | #define AR_OBS_BUS_SEL_1 0x00040000 | ||
1146 | #define AR_OBS_BUS_SEL_2 0x00080000 | ||
1147 | #define AR_OBS_BUS_SEL_3 0x000C0000 | ||
1148 | #define AR_OBS_BUS_SEL_4 0x08040000 | ||
1149 | #define AR_OBS_BUS_SEL_5 0x08080000 | ||
1150 | |||
1151 | #define AR_OBS_BUS_1 0x806c | ||
1152 | #define AR_OBS_BUS_1_PCU 0x00000001 | ||
1153 | #define AR_OBS_BUS_1_RX_END 0x00000002 | ||
1154 | #define AR_OBS_BUS_1_RX_WEP 0x00000004 | ||
1155 | #define AR_OBS_BUS_1_RX_BEACON 0x00000008 | ||
1156 | #define AR_OBS_BUS_1_RX_FILTER 0x00000010 | ||
1157 | #define AR_OBS_BUS_1_TX_HCF 0x00000020 | ||
1158 | #define AR_OBS_BUS_1_QUIET_TIME 0x00000040 | ||
1159 | #define AR_OBS_BUS_1_CHAN_IDLE 0x00000080 | ||
1160 | #define AR_OBS_BUS_1_TX_HOLD 0x00000100 | ||
1161 | #define AR_OBS_BUS_1_TX_FRAME 0x00000200 | ||
1162 | #define AR_OBS_BUS_1_RX_FRAME 0x00000400 | ||
1163 | #define AR_OBS_BUS_1_RX_CLEAR 0x00000800 | ||
1164 | #define AR_OBS_BUS_1_WEP_STATE 0x0003F000 | ||
1165 | #define AR_OBS_BUS_1_WEP_STATE_S 12 | ||
1166 | #define AR_OBS_BUS_1_RX_STATE 0x01F00000 | ||
1167 | #define AR_OBS_BUS_1_RX_STATE_S 20 | ||
1168 | #define AR_OBS_BUS_1_TX_STATE 0x7E000000 | ||
1169 | #define AR_OBS_BUS_1_TX_STATE_S 25 | ||
1170 | |||
1171 | #define AR_LAST_TSTP 0x8080 | ||
1172 | #define AR_NAV 0x8084 | ||
1173 | #define AR_RTS_OK 0x8088 | ||
1174 | #define AR_RTS_FAIL 0x808c | ||
1175 | #define AR_ACK_FAIL 0x8090 | ||
1176 | #define AR_FCS_FAIL 0x8094 | ||
1177 | #define AR_BEACON_CNT 0x8098 | ||
1178 | |||
1179 | #define AR_SLEEP1 0x80d4 | ||
1180 | #define AR_SLEEP1_ASSUME_DTIM 0x00080000 | ||
1181 | #define AR_SLEEP1_CAB_TIMEOUT 0xFFE00000 | ||
1182 | #define AR_SLEEP1_CAB_TIMEOUT_S 21 | ||
1183 | |||
1184 | #define AR_SLEEP2 0x80d8 | ||
1185 | #define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000 | ||
1186 | #define AR_SLEEP2_BEACON_TIMEOUT_S 21 | ||
1187 | |||
1188 | #define AR_BSSMSKL 0x80e0 | ||
1189 | #define AR_BSSMSKU 0x80e4 | ||
1190 | |||
1191 | #define AR_TPC 0x80e8 | ||
1192 | #define AR_TPC_ACK 0x0000003f | ||
1193 | #define AR_TPC_ACK_S 0x00 | ||
1194 | #define AR_TPC_CTS 0x00003f00 | ||
1195 | #define AR_TPC_CTS_S 0x08 | ||
1196 | #define AR_TPC_CHIRP 0x003f0000 | ||
1197 | #define AR_TPC_CHIRP_S 0x16 | ||
1198 | |||
1199 | #define AR_TFCNT 0x80ec | ||
1200 | #define AR_RFCNT 0x80f0 | ||
1201 | #define AR_RCCNT 0x80f4 | ||
1202 | #define AR_CCCNT 0x80f8 | ||
1203 | |||
1204 | #define AR_QUIET1 0x80fc | ||
1205 | #define AR_QUIET1_NEXT_QUIET_S 0 | ||
1206 | #define AR_QUIET1_NEXT_QUIET_M 0x0000ffff | ||
1207 | #define AR_QUIET1_QUIET_ENABLE 0x00010000 | ||
1208 | #define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000 | ||
1209 | #define AR_QUIET2 0x8100 | ||
1210 | #define AR_QUIET2_QUIET_PERIOD_S 0 | ||
1211 | #define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff | ||
1212 | #define AR_QUIET2_QUIET_DUR_S 16 | ||
1213 | #define AR_QUIET2_QUIET_DUR 0xffff0000 | ||
1214 | |||
1215 | #define AR_TSF_PARM 0x8104 | ||
1216 | #define AR_TSF_INCREMENT_M 0x000000ff | ||
1217 | #define AR_TSF_INCREMENT_S 0x00 | ||
1218 | |||
1219 | #define AR_QOS_NO_ACK 0x8108 | ||
1220 | #define AR_QOS_NO_ACK_TWO_BIT 0x0000000f | ||
1221 | #define AR_QOS_NO_ACK_TWO_BIT_S 0 | ||
1222 | #define AR_QOS_NO_ACK_BIT_OFF 0x00000070 | ||
1223 | #define AR_QOS_NO_ACK_BIT_OFF_S 4 | ||
1224 | #define AR_QOS_NO_ACK_BYTE_OFF 0x00000180 | ||
1225 | #define AR_QOS_NO_ACK_BYTE_OFF_S 7 | ||
1226 | |||
1227 | #define AR_PHY_ERR 0x810c | ||
1228 | |||
1229 | #define AR_PHY_ERR_DCHIRP 0x00000008 | ||
1230 | #define AR_PHY_ERR_RADAR 0x00000020 | ||
1231 | #define AR_PHY_ERR_OFDM_TIMING 0x00020000 | ||
1232 | #define AR_PHY_ERR_CCK_TIMING 0x02000000 | ||
1233 | |||
1234 | #define AR_RXFIFO_CFG 0x8114 | ||
1235 | |||
1236 | |||
1237 | #define AR_MIC_QOS_CONTROL 0x8118 | ||
1238 | #define AR_MIC_QOS_SELECT 0x811c | ||
1239 | |||
1240 | #define AR_PCU_MISC 0x8120 | ||
1241 | #define AR_PCU_FORCE_BSSID_MATCH 0x00000001 | ||
1242 | #define AR_PCU_MIC_NEW_LOC_ENA 0x00000004 | ||
1243 | #define AR_PCU_TX_ADD_TSF 0x00000008 | ||
1244 | #define AR_PCU_CCK_SIFS_MODE 0x00000010 | ||
1245 | #define AR_PCU_RX_ANT_UPDT 0x00000800 | ||
1246 | #define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000 | ||
1247 | #define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000 | ||
1248 | #define AR_PCU_BUG_12306_FIX_ENA 0x00020000 | ||
1249 | #define AR_PCU_FORCE_QUIET_COLL 0x00040000 | ||
1250 | #define AR_PCU_TBTT_PROTECT 0x00200000 | ||
1251 | #define AR_PCU_CLEAR_VMF 0x01000000 | ||
1252 | #define AR_PCU_CLEAR_BA_VALID 0x04000000 | ||
1253 | |||
1254 | |||
1255 | #define AR_FILT_OFDM 0x8124 | ||
1256 | #define AR_FILT_OFDM_COUNT 0x00FFFFFF | ||
1257 | |||
1258 | #define AR_FILT_CCK 0x8128 | ||
1259 | #define AR_FILT_CCK_COUNT 0x00FFFFFF | ||
1260 | |||
1261 | #define AR_PHY_ERR_1 0x812c | ||
1262 | #define AR_PHY_ERR_1_COUNT 0x00FFFFFF | ||
1263 | #define AR_PHY_ERR_MASK_1 0x8130 | ||
1264 | |||
1265 | #define AR_PHY_ERR_2 0x8134 | ||
1266 | #define AR_PHY_ERR_2_COUNT 0x00FFFFFF | ||
1267 | #define AR_PHY_ERR_MASK_2 0x8138 | ||
1268 | |||
1269 | #define AR_PHY_COUNTMAX (3 << 22) | ||
1270 | #define AR_MIBCNT_INTRMASK (3 << 22) | ||
1271 | |||
1272 | #define AR_TSF_THRESHOLD 0x813c | ||
1273 | #define AR_TSF_THRESHOLD_VAL 0x0000FFFF | ||
1274 | |||
1275 | #define AR_PHY_ERR_EIFS_MASK 8144 | ||
1276 | |||
1277 | #define AR_PHY_ERR_3 0x8168 | ||
1278 | #define AR_PHY_ERR_3_COUNT 0x00FFFFFF | ||
1279 | #define AR_PHY_ERR_MASK_3 0x816c | ||
1280 | |||
1281 | #define AR_TXSIFS 0x81d0 | ||
1282 | #define AR_TXSIFS_TIME 0x000000FF | ||
1283 | #define AR_TXSIFS_TX_LATENCY 0x00000F00 | ||
1284 | #define AR_TXSIFS_TX_LATENCY_S 8 | ||
1285 | #define AR_TXSIFS_ACK_SHIFT 0x00007000 | ||
1286 | #define AR_TXSIFS_ACK_SHIFT_S 12 | ||
1287 | |||
1288 | #define AR_TXOP_X 0x81ec | ||
1289 | #define AR_TXOP_X_VAL 0x000000FF | ||
1290 | |||
1291 | |||
1292 | #define AR_TXOP_0_3 0x81f0 | ||
1293 | #define AR_TXOP_4_7 0x81f4 | ||
1294 | #define AR_TXOP_8_11 0x81f8 | ||
1295 | #define AR_TXOP_12_15 0x81fc | ||
1296 | |||
1297 | |||
1298 | #define AR_NEXT_TBTT_TIMER 0x8200 | ||
1299 | #define AR_NEXT_DMA_BEACON_ALERT 0x8204 | ||
1300 | #define AR_NEXT_SWBA 0x8208 | ||
1301 | #define AR_NEXT_CFP 0x8208 | ||
1302 | #define AR_NEXT_HCF 0x820C | ||
1303 | #define AR_NEXT_TIM 0x8210 | ||
1304 | #define AR_NEXT_DTIM 0x8214 | ||
1305 | #define AR_NEXT_QUIET_TIMER 0x8218 | ||
1306 | #define AR_NEXT_NDP_TIMER 0x821C | ||
1307 | |||
1308 | #define AR_BEACON_PERIOD 0x8220 | ||
1309 | #define AR_DMA_BEACON_PERIOD 0x8224 | ||
1310 | #define AR_SWBA_PERIOD 0x8228 | ||
1311 | #define AR_HCF_PERIOD 0x822C | ||
1312 | #define AR_TIM_PERIOD 0x8230 | ||
1313 | #define AR_DTIM_PERIOD 0x8234 | ||
1314 | #define AR_QUIET_PERIOD 0x8238 | ||
1315 | #define AR_NDP_PERIOD 0x823C | ||
1316 | |||
1317 | #define AR_TIMER_MODE 0x8240 | ||
1318 | #define AR_TBTT_TIMER_EN 0x00000001 | ||
1319 | #define AR_DBA_TIMER_EN 0x00000002 | ||
1320 | #define AR_SWBA_TIMER_EN 0x00000004 | ||
1321 | #define AR_HCF_TIMER_EN 0x00000008 | ||
1322 | #define AR_TIM_TIMER_EN 0x00000010 | ||
1323 | #define AR_DTIM_TIMER_EN 0x00000020 | ||
1324 | #define AR_QUIET_TIMER_EN 0x00000040 | ||
1325 | #define AR_NDP_TIMER_EN 0x00000080 | ||
1326 | #define AR_TIMER_OVERFLOW_INDEX 0x00000700 | ||
1327 | #define AR_TIMER_OVERFLOW_INDEX_S 8 | ||
1328 | #define AR_TIMER_THRESH 0xFFFFF000 | ||
1329 | #define AR_TIMER_THRESH_S 12 | ||
1330 | |||
1331 | #define AR_SLP32_MODE 0x8244 | ||
1332 | #define AR_SLP32_HALF_CLK_LATENCY 0x000FFFFF | ||
1333 | #define AR_SLP32_ENA 0x00100000 | ||
1334 | #define AR_SLP32_TSF_WRITE_STATUS 0x00200000 | ||
1335 | |||
1336 | #define AR_SLP32_WAKE 0x8248 | ||
1337 | #define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF | ||
1338 | |||
1339 | #define AR_SLP32_INC 0x824c | ||
1340 | #define AR_SLP32_TST_INC 0x000FFFFF | ||
1341 | |||
1342 | #define AR_SLP_CNT 0x8250 | ||
1343 | #define AR_SLP_CYCLE_CNT 0x8254 | ||
1344 | |||
1345 | #define AR_SLP_MIB_CTRL 0x8258 | ||
1346 | #define AR_SLP_MIB_CLEAR 0x00000001 | ||
1347 | #define AR_SLP_MIB_PENDING 0x00000002 | ||
1348 | |||
1349 | #define AR_2040_MODE 0x8318 | ||
1350 | #define AR_2040_JOINED_RX_CLEAR 0x00000001 | ||
1351 | |||
1352 | |||
1353 | #define AR_EXTRCCNT 0x8328 | ||
1354 | |||
1355 | #define AR_SELFGEN_MASK 0x832c | ||
1356 | |||
1357 | #define AR_PCU_TXBUF_CTRL 0x8340 | ||
1358 | #define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF | ||
1359 | #define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 | ||
1360 | #define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380 | ||
1361 | |||
1362 | #define AR_KEYTABLE_0 0x8800 | ||
1363 | #define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) | ||
1364 | #define AR_KEY_CACHE_SIZE 128 | ||
1365 | #define AR_RSVD_KEYTABLE_ENTRIES 4 | ||
1366 | #define AR_KEY_TYPE 0x00000007 | ||
1367 | #define AR_KEYTABLE_TYPE_40 0x00000000 | ||
1368 | #define AR_KEYTABLE_TYPE_104 0x00000001 | ||
1369 | #define AR_KEYTABLE_TYPE_128 0x00000003 | ||
1370 | #define AR_KEYTABLE_TYPE_TKIP 0x00000004 | ||
1371 | #define AR_KEYTABLE_TYPE_AES 0x00000005 | ||
1372 | #define AR_KEYTABLE_TYPE_CCM 0x00000006 | ||
1373 | #define AR_KEYTABLE_TYPE_CLR 0x00000007 | ||
1374 | #define AR_KEYTABLE_ANT 0x00000008 | ||
1375 | #define AR_KEYTABLE_VALID 0x00008000 | ||
1376 | #define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0) | ||
1377 | #define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4) | ||
1378 | #define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8) | ||
1379 | #define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12) | ||
1380 | #define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16) | ||
1381 | #define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20) | ||
1382 | #define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) | ||
1383 | #define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) | ||
1384 | |||
1385 | #endif | ||
diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c new file mode 100644 index 00000000000..7b0176e3eb4 --- /dev/null +++ b/drivers/net/wireless/ath9k/regd.c | |||
@@ -0,0 +1,1031 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include "core.h" | ||
20 | #include "hw.h" | ||
21 | #include "regd.h" | ||
22 | #include "regd_common.h" | ||
23 | |||
24 | static int ath9k_regd_chansort(const void *a, const void *b) | ||
25 | { | ||
26 | const struct ath9k_channel *ca = a; | ||
27 | const struct ath9k_channel *cb = b; | ||
28 | |||
29 | return (ca->channel == cb->channel) ? | ||
30 | (ca->channelFlags & CHAN_FLAGS) - | ||
31 | (cb->channelFlags & CHAN_FLAGS) : ca->channel - cb->channel; | ||
32 | } | ||
33 | |||
34 | static void | ||
35 | ath9k_regd_sort(void *a, u32 n, u32 size, ath_hal_cmp_t *cmp) | ||
36 | { | ||
37 | u8 *aa = a; | ||
38 | u8 *ai, *t; | ||
39 | |||
40 | for (ai = aa + size; --n >= 1; ai += size) | ||
41 | for (t = ai; t > aa; t -= size) { | ||
42 | u8 *u = t - size; | ||
43 | if (cmp(u, t) <= 0) | ||
44 | break; | ||
45 | swap(u, t, size); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | static u16 ath9k_regd_get_eepromRD(struct ath_hal *ah) | ||
50 | { | ||
51 | return ah->ah_currentRD & ~WORLDWIDE_ROAMING_FLAG; | ||
52 | } | ||
53 | |||
54 | static bool ath9k_regd_is_chan_bm_zero(u64 *bitmask) | ||
55 | { | ||
56 | int i; | ||
57 | |||
58 | for (i = 0; i < BMLEN; i++) { | ||
59 | if (bitmask[i] != 0) | ||
60 | return false; | ||
61 | } | ||
62 | return true; | ||
63 | } | ||
64 | |||
65 | static bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah) | ||
66 | { | ||
67 | u16 rd = ath9k_regd_get_eepromRD(ah); | ||
68 | int i; | ||
69 | |||
70 | if (rd & COUNTRY_ERD_FLAG) { | ||
71 | u16 cc = rd & ~COUNTRY_ERD_FLAG; | ||
72 | for (i = 0; i < ARRAY_SIZE(allCountries); i++) | ||
73 | if (allCountries[i].countryCode == cc) | ||
74 | return true; | ||
75 | } else { | ||
76 | for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) | ||
77 | if (regDomainPairs[i].regDmnEnum == rd) | ||
78 | return true; | ||
79 | } | ||
80 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
81 | "%s: invalid regulatory domain/country code 0x%x\n", | ||
82 | __func__, rd); | ||
83 | return false; | ||
84 | } | ||
85 | |||
86 | static bool ath9k_regd_is_fcc_midband_supported(struct ath_hal *ah) | ||
87 | { | ||
88 | u32 regcap; | ||
89 | |||
90 | regcap = ah->ah_caps.halRegCap; | ||
91 | |||
92 | if (regcap & AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND) | ||
93 | return true; | ||
94 | else | ||
95 | return false; | ||
96 | } | ||
97 | |||
98 | static bool ath9k_regd_is_ccode_valid(struct ath_hal *ah, | ||
99 | u16 cc) | ||
100 | { | ||
101 | u16 rd; | ||
102 | int i; | ||
103 | |||
104 | if (cc == CTRY_DEFAULT) | ||
105 | return true; | ||
106 | if (cc == CTRY_DEBUG) | ||
107 | return true; | ||
108 | |||
109 | rd = ath9k_regd_get_eepromRD(ah); | ||
110 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: EEPROM regdomain 0x%x\n", | ||
111 | __func__, rd); | ||
112 | |||
113 | if (rd & COUNTRY_ERD_FLAG) { | ||
114 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
115 | "%s: EEPROM setting is country code %u\n", | ||
116 | __func__, rd & ~COUNTRY_ERD_FLAG); | ||
117 | return cc == (rd & ~COUNTRY_ERD_FLAG); | ||
118 | } | ||
119 | |||
120 | for (i = 0; i < ARRAY_SIZE(allCountries); i++) { | ||
121 | if (cc == allCountries[i].countryCode) { | ||
122 | #ifdef AH_SUPPORT_11D | ||
123 | if ((rd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) | ||
124 | return true; | ||
125 | #endif | ||
126 | if (allCountries[i].regDmnEnum == rd || | ||
127 | rd == DEBUG_REG_DMN || rd == NO_ENUMRD) | ||
128 | return true; | ||
129 | } | ||
130 | } | ||
131 | return false; | ||
132 | } | ||
133 | |||
134 | static u32 | ||
135 | ath9k_regd_get_wmodes_nreg(struct ath_hal *ah, | ||
136 | struct country_code_to_enum_rd *country, | ||
137 | struct regDomain *rd5GHz) | ||
138 | { | ||
139 | u32 modesAvail; | ||
140 | |||
141 | modesAvail = ah->ah_caps.halWirelessModes; | ||
142 | |||
143 | if ((modesAvail & ATH9K_MODE_SEL_11G) && (!country->allow11g)) | ||
144 | modesAvail &= ~ATH9K_MODE_SEL_11G; | ||
145 | if ((modesAvail & ATH9K_MODE_SEL_11A) && | ||
146 | (ath9k_regd_is_chan_bm_zero(rd5GHz->chan11a))) | ||
147 | modesAvail &= ~ATH9K_MODE_SEL_11A; | ||
148 | |||
149 | if ((modesAvail & ATH9K_MODE_SEL_11NG_HT20) | ||
150 | && (!country->allow11ng20)) | ||
151 | modesAvail &= ~ATH9K_MODE_SEL_11NG_HT20; | ||
152 | |||
153 | if ((modesAvail & ATH9K_MODE_SEL_11NA_HT20) | ||
154 | && (!country->allow11na20)) | ||
155 | modesAvail &= ~ATH9K_MODE_SEL_11NA_HT20; | ||
156 | |||
157 | if ((modesAvail & ATH9K_MODE_SEL_11NG_HT40PLUS) && | ||
158 | (!country->allow11ng40)) | ||
159 | modesAvail &= ~ATH9K_MODE_SEL_11NG_HT40PLUS; | ||
160 | |||
161 | if ((modesAvail & ATH9K_MODE_SEL_11NG_HT40MINUS) && | ||
162 | (!country->allow11ng40)) | ||
163 | modesAvail &= ~ATH9K_MODE_SEL_11NG_HT40MINUS; | ||
164 | |||
165 | if ((modesAvail & ATH9K_MODE_SEL_11NA_HT40PLUS) && | ||
166 | (!country->allow11na40)) | ||
167 | modesAvail &= ~ATH9K_MODE_SEL_11NA_HT40PLUS; | ||
168 | |||
169 | if ((modesAvail & ATH9K_MODE_SEL_11NA_HT40MINUS) && | ||
170 | (!country->allow11na40)) | ||
171 | modesAvail &= ~ATH9K_MODE_SEL_11NA_HT40MINUS; | ||
172 | |||
173 | return modesAvail; | ||
174 | } | ||
175 | |||
176 | bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah) | ||
177 | { | ||
178 | u16 rd; | ||
179 | |||
180 | rd = ath9k_regd_get_eepromRD(ah); | ||
181 | |||
182 | switch (rd) { | ||
183 | case FCC4_FCCA: | ||
184 | case (CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG): | ||
185 | return true; | ||
186 | case DEBUG_REG_DMN: | ||
187 | case NO_ENUMRD: | ||
188 | if (ah->ah_countryCode == CTRY_UNITED_STATES_FCC49) | ||
189 | return true; | ||
190 | break; | ||
191 | } | ||
192 | return false; | ||
193 | } | ||
194 | |||
195 | static struct country_code_to_enum_rd* | ||
196 | ath9k_regd_find_country(u16 countryCode) | ||
197 | { | ||
198 | int i; | ||
199 | |||
200 | for (i = 0; i < ARRAY_SIZE(allCountries); i++) { | ||
201 | if (allCountries[i].countryCode == countryCode) | ||
202 | return &allCountries[i]; | ||
203 | } | ||
204 | return NULL; | ||
205 | } | ||
206 | |||
207 | static u16 ath9k_regd_get_default_country(struct ath_hal *ah) | ||
208 | { | ||
209 | u16 rd; | ||
210 | int i; | ||
211 | |||
212 | rd = ath9k_regd_get_eepromRD(ah); | ||
213 | if (rd & COUNTRY_ERD_FLAG) { | ||
214 | struct country_code_to_enum_rd *country = NULL; | ||
215 | u16 cc = rd & ~COUNTRY_ERD_FLAG; | ||
216 | |||
217 | country = ath9k_regd_find_country(cc); | ||
218 | if (country != NULL) | ||
219 | return cc; | ||
220 | } | ||
221 | |||
222 | for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) | ||
223 | if (regDomainPairs[i].regDmnEnum == rd) { | ||
224 | if (regDomainPairs[i].singleCC != 0) | ||
225 | return regDomainPairs[i].singleCC; | ||
226 | else | ||
227 | i = ARRAY_SIZE(regDomainPairs); | ||
228 | } | ||
229 | return CTRY_DEFAULT; | ||
230 | } | ||
231 | |||
232 | static bool ath9k_regd_is_valid_reg_domain(int regDmn, | ||
233 | struct regDomain *rd) | ||
234 | { | ||
235 | int i; | ||
236 | |||
237 | for (i = 0; i < ARRAY_SIZE(regDomains); i++) { | ||
238 | if (regDomains[i].regDmnEnum == regDmn) { | ||
239 | if (rd != NULL) { | ||
240 | memcpy(rd, ®Domains[i], | ||
241 | sizeof(struct regDomain)); | ||
242 | } | ||
243 | return true; | ||
244 | } | ||
245 | } | ||
246 | return false; | ||
247 | } | ||
248 | |||
249 | static bool ath9k_regd_is_valid_reg_domainPair(int regDmnPair) | ||
250 | { | ||
251 | int i; | ||
252 | |||
253 | if (regDmnPair == NO_ENUMRD) | ||
254 | return false; | ||
255 | for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { | ||
256 | if (regDomainPairs[i].regDmnEnum == regDmnPair) | ||
257 | return true; | ||
258 | } | ||
259 | return false; | ||
260 | } | ||
261 | |||
262 | static bool | ||
263 | ath9k_regd_get_wmode_regdomain(struct ath_hal *ah, int regDmn, | ||
264 | u16 channelFlag, struct regDomain *rd) | ||
265 | { | ||
266 | int i, found; | ||
267 | u64 flags = NO_REQ; | ||
268 | struct reg_dmn_pair_mapping *regPair = NULL; | ||
269 | int regOrg; | ||
270 | |||
271 | regOrg = regDmn; | ||
272 | if (regDmn == CTRY_DEFAULT) { | ||
273 | u16 rdnum; | ||
274 | rdnum = ath9k_regd_get_eepromRD(ah); | ||
275 | |||
276 | if (!(rdnum & COUNTRY_ERD_FLAG)) { | ||
277 | if (ath9k_regd_is_valid_reg_domain(rdnum, NULL) || | ||
278 | ath9k_regd_is_valid_reg_domainPair(rdnum)) { | ||
279 | regDmn = rdnum; | ||
280 | } | ||
281 | } | ||
282 | } | ||
283 | |||
284 | if ((regDmn & MULTI_DOMAIN_MASK) == 0) { | ||
285 | for (i = 0, found = 0; | ||
286 | (i < ARRAY_SIZE(regDomainPairs)) && (!found); i++) { | ||
287 | if (regDomainPairs[i].regDmnEnum == regDmn) { | ||
288 | regPair = ®DomainPairs[i]; | ||
289 | found = 1; | ||
290 | } | ||
291 | } | ||
292 | if (!found) { | ||
293 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
294 | "%s: Failed to find reg domain pair %u\n", | ||
295 | __func__, regDmn); | ||
296 | return false; | ||
297 | } | ||
298 | if (!(channelFlag & CHANNEL_2GHZ)) { | ||
299 | regDmn = regPair->regDmn5GHz; | ||
300 | flags = regPair->flags5GHz; | ||
301 | } | ||
302 | if (channelFlag & CHANNEL_2GHZ) { | ||
303 | regDmn = regPair->regDmn2GHz; | ||
304 | flags = regPair->flags2GHz; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | found = ath9k_regd_is_valid_reg_domain(regDmn, rd); | ||
309 | if (!found) { | ||
310 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
311 | "%s: Failed to find unitary reg domain %u\n", | ||
312 | __func__, regDmn); | ||
313 | return false; | ||
314 | } else { | ||
315 | rd->pscan &= regPair->pscanMask; | ||
316 | if (((regOrg & MULTI_DOMAIN_MASK) == 0) && | ||
317 | (flags != NO_REQ)) { | ||
318 | rd->flags = flags; | ||
319 | } | ||
320 | |||
321 | rd->flags &= (channelFlag & CHANNEL_2GHZ) ? | ||
322 | REG_DOMAIN_2GHZ_MASK : REG_DOMAIN_5GHZ_MASK; | ||
323 | return true; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | static bool ath9k_regd_is_bit_set(int bit, u64 *bitmask) | ||
328 | { | ||
329 | int byteOffset, bitnum; | ||
330 | u64 val; | ||
331 | |||
332 | byteOffset = bit / 64; | ||
333 | bitnum = bit - byteOffset * 64; | ||
334 | val = ((u64) 1) << bitnum; | ||
335 | if (bitmask[byteOffset] & val) | ||
336 | return true; | ||
337 | else | ||
338 | return false; | ||
339 | } | ||
340 | |||
341 | static void | ||
342 | ath9k_regd_add_reg_classid(u8 *regclassids, u32 maxregids, | ||
343 | u32 *nregids, u8 regclassid) | ||
344 | { | ||
345 | int i; | ||
346 | |||
347 | if (regclassid == 0) | ||
348 | return; | ||
349 | |||
350 | for (i = 0; i < maxregids; i++) { | ||
351 | if (regclassids[i] == regclassid) | ||
352 | return; | ||
353 | if (regclassids[i] == 0) | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | if (i == maxregids) | ||
358 | return; | ||
359 | else { | ||
360 | regclassids[i] = regclassid; | ||
361 | *nregids += 1; | ||
362 | } | ||
363 | |||
364 | return; | ||
365 | } | ||
366 | |||
367 | static bool | ||
368 | ath9k_regd_get_eeprom_reg_ext_bits(struct ath_hal *ah, | ||
369 | enum reg_ext_bitmap bit) | ||
370 | { | ||
371 | return (ah->ah_currentRDExt & (1 << bit)) ? true : false; | ||
372 | } | ||
373 | |||
374 | #ifdef ATH_NF_PER_CHAN | ||
375 | |||
376 | static void ath9k_regd_init_rf_buffer(struct ath9k_channel *ichans, | ||
377 | int nchans) | ||
378 | { | ||
379 | int i, j, next; | ||
380 | |||
381 | for (next = 0; next < nchans; next++) { | ||
382 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
383 | ichans[next].nfCalHist[i].currIndex = 0; | ||
384 | ichans[next].nfCalHist[i].privNF = | ||
385 | AR_PHY_CCA_MAX_GOOD_VALUE; | ||
386 | ichans[next].nfCalHist[i].invalidNFcount = | ||
387 | AR_PHY_CCA_FILTERWINDOW_LENGTH; | ||
388 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { | ||
389 | ichans[next].nfCalHist[i].nfCalBuffer[j] = | ||
390 | AR_PHY_CCA_MAX_GOOD_VALUE; | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | #endif | ||
396 | |||
397 | static int ath9k_regd_is_chan_present(struct ath_hal *ah, | ||
398 | u16 c) | ||
399 | { | ||
400 | int i; | ||
401 | |||
402 | for (i = 0; i < 150; i++) { | ||
403 | if (!ah->ah_channels[i].channel) | ||
404 | return -1; | ||
405 | else if (ah->ah_channels[i].channel == c) | ||
406 | return i; | ||
407 | } | ||
408 | |||
409 | return -1; | ||
410 | } | ||
411 | |||
412 | static bool | ||
413 | ath9k_regd_add_channel(struct ath_hal *ah, | ||
414 | u16 c, | ||
415 | u16 c_lo, | ||
416 | u16 c_hi, | ||
417 | u16 maxChan, | ||
418 | u8 ctl, | ||
419 | int pos, | ||
420 | struct regDomain rd5GHz, | ||
421 | struct RegDmnFreqBand *fband, | ||
422 | struct regDomain *rd, | ||
423 | const struct cmode *cm, | ||
424 | struct ath9k_channel *ichans, | ||
425 | bool enableExtendedChannels) | ||
426 | { | ||
427 | struct ath9k_channel *chan; | ||
428 | int ret; | ||
429 | u32 channelFlags = 0; | ||
430 | u8 privFlags = 0; | ||
431 | |||
432 | if (!(c_lo <= c && c <= c_hi)) { | ||
433 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
434 | "%s: c %u out of range [%u..%u]\n", | ||
435 | __func__, c, c_lo, c_hi); | ||
436 | return false; | ||
437 | } | ||
438 | if ((fband->channelBW == CHANNEL_HALF_BW) && | ||
439 | !ah->ah_caps.halChanHalfRate) { | ||
440 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
441 | "%s: Skipping %u half rate channel\n", | ||
442 | __func__, c); | ||
443 | return false; | ||
444 | } | ||
445 | |||
446 | if ((fband->channelBW == CHANNEL_QUARTER_BW) && | ||
447 | !ah->ah_caps.halChanQuarterRate) { | ||
448 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
449 | "%s: Skipping %u quarter rate channel\n", | ||
450 | __func__, c); | ||
451 | return false; | ||
452 | } | ||
453 | |||
454 | if (((c + fband->channelSep) / 2) > (maxChan + HALF_MAXCHANBW)) { | ||
455 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
456 | "%s: c %u > maxChan %u\n", | ||
457 | __func__, c, maxChan); | ||
458 | return false; | ||
459 | } | ||
460 | |||
461 | if ((fband->usePassScan & IS_ECM_CHAN) && !enableExtendedChannels) { | ||
462 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
463 | "Skipping ecm channel\n"); | ||
464 | return false; | ||
465 | } | ||
466 | |||
467 | if ((rd->flags & NO_HOSTAP) && (ah->ah_opmode == ATH9K_M_HOSTAP)) { | ||
468 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
469 | "Skipping HOSTAP channel\n"); | ||
470 | return false; | ||
471 | } | ||
472 | |||
473 | if (IS_HT40_MODE(cm->mode) && | ||
474 | !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_FCC_DFS_HT40)) && | ||
475 | (fband->useDfs) && | ||
476 | (rd->conformanceTestLimit != MKK)) { | ||
477 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
478 | "Skipping HT40 channel (en_fcc_dfs_ht40 = 0)\n"); | ||
479 | return false; | ||
480 | } | ||
481 | |||
482 | if (IS_HT40_MODE(cm->mode) && | ||
483 | !(ath9k_regd_get_eeprom_reg_ext_bits(ah, | ||
484 | REG_EXT_JAPAN_NONDFS_HT40)) && | ||
485 | !(fband->useDfs) && (rd->conformanceTestLimit == MKK)) { | ||
486 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
487 | "Skipping HT40 channel (en_jap_ht40 = 0)\n"); | ||
488 | return false; | ||
489 | } | ||
490 | |||
491 | if (IS_HT40_MODE(cm->mode) && | ||
492 | !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_JAPAN_DFS_HT40)) && | ||
493 | (fband->useDfs) && | ||
494 | (rd->conformanceTestLimit == MKK)) { | ||
495 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
496 | "Skipping HT40 channel (en_jap_dfs_ht40 = 0)\n"); | ||
497 | return false; | ||
498 | } | ||
499 | |||
500 | /* Calculate channel flags */ | ||
501 | |||
502 | channelFlags = cm->flags; | ||
503 | |||
504 | switch (fband->channelBW) { | ||
505 | case CHANNEL_HALF_BW: | ||
506 | channelFlags |= CHANNEL_HALF; | ||
507 | break; | ||
508 | case CHANNEL_QUARTER_BW: | ||
509 | channelFlags |= CHANNEL_QUARTER; | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | if (fband->usePassScan & rd->pscan) | ||
514 | channelFlags |= CHANNEL_PASSIVE; | ||
515 | else | ||
516 | channelFlags &= ~CHANNEL_PASSIVE; | ||
517 | if (fband->useDfs & rd->dfsMask) | ||
518 | privFlags = CHANNEL_DFS; | ||
519 | else | ||
520 | privFlags = 0; | ||
521 | if (rd->flags & LIMIT_FRAME_4MS) | ||
522 | privFlags |= CHANNEL_4MS_LIMIT; | ||
523 | if (privFlags & CHANNEL_DFS) | ||
524 | privFlags |= CHANNEL_DISALLOW_ADHOC; | ||
525 | if (rd->flags & ADHOC_PER_11D) | ||
526 | privFlags |= CHANNEL_PER_11D_ADHOC; | ||
527 | |||
528 | if (channelFlags & CHANNEL_PASSIVE) { | ||
529 | if ((c < 2412) || (c > 2462)) { | ||
530 | if (rd5GHz.regDmnEnum == MKK1 || | ||
531 | rd5GHz.regDmnEnum == MKK2) { | ||
532 | u32 regcap = ah->ah_caps.halRegCap; | ||
533 | if (!(regcap & | ||
534 | (AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | | ||
535 | AR_EEPROM_EEREGCAP_EN_KK_U2 | | ||
536 | AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) && | ||
537 | isUNII1OddChan(c)) { | ||
538 | channelFlags &= ~CHANNEL_PASSIVE; | ||
539 | } else { | ||
540 | privFlags |= CHANNEL_DISALLOW_ADHOC; | ||
541 | } | ||
542 | } else { | ||
543 | privFlags |= CHANNEL_DISALLOW_ADHOC; | ||
544 | } | ||
545 | } | ||
546 | } | ||
547 | |||
548 | if (cm->mode & (ATH9K_MODE_SEL_11A | | ||
549 | ATH9K_MODE_SEL_11NA_HT20 | | ||
550 | ATH9K_MODE_SEL_11NA_HT40PLUS | | ||
551 | ATH9K_MODE_SEL_11NA_HT40MINUS)) { | ||
552 | if (rd->flags & (ADHOC_NO_11A | DISALLOW_ADHOC_11A)) | ||
553 | privFlags |= CHANNEL_DISALLOW_ADHOC; | ||
554 | } | ||
555 | |||
556 | /* Fill in channel details */ | ||
557 | |||
558 | ret = ath9k_regd_is_chan_present(ah, c); | ||
559 | if (ret == -1) { | ||
560 | chan = &ah->ah_channels[pos]; | ||
561 | chan->channel = c; | ||
562 | chan->maxRegTxPower = fband->powerDfs; | ||
563 | chan->antennaMax = fband->antennaMax; | ||
564 | chan->regDmnFlags = rd->flags; | ||
565 | chan->maxTxPower = AR5416_MAX_RATE_POWER; | ||
566 | chan->minTxPower = AR5416_MAX_RATE_POWER; | ||
567 | chan->channelFlags = channelFlags; | ||
568 | chan->privFlags = privFlags; | ||
569 | } else { | ||
570 | chan = &ah->ah_channels[ret]; | ||
571 | chan->channelFlags |= channelFlags; | ||
572 | chan->privFlags |= privFlags; | ||
573 | } | ||
574 | |||
575 | /* Set CTLs */ | ||
576 | |||
577 | if ((cm->flags & CHANNEL_ALL) == CHANNEL_A) | ||
578 | chan->conformanceTestLimit[0] = ctl; | ||
579 | else if ((cm->flags & CHANNEL_ALL) == CHANNEL_B) | ||
580 | chan->conformanceTestLimit[1] = ctl; | ||
581 | else if ((cm->flags & CHANNEL_ALL) == CHANNEL_G) | ||
582 | chan->conformanceTestLimit[2] = ctl; | ||
583 | |||
584 | return (ret == -1) ? true : false; | ||
585 | } | ||
586 | |||
587 | static bool ath9k_regd_japan_check(struct ath_hal *ah, | ||
588 | int b, | ||
589 | struct regDomain *rd5GHz) | ||
590 | { | ||
591 | bool skipband = false; | ||
592 | int i; | ||
593 | u32 regcap; | ||
594 | |||
595 | for (i = 0; i < ARRAY_SIZE(j_bandcheck); i++) { | ||
596 | if (j_bandcheck[i].freqbandbit == b) { | ||
597 | regcap = ah->ah_caps.halRegCap; | ||
598 | if ((j_bandcheck[i].eepromflagtocheck & regcap) == 0) { | ||
599 | skipband = true; | ||
600 | } else if ((regcap & AR_EEPROM_EEREGCAP_EN_KK_U2) || | ||
601 | (regcap & AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) { | ||
602 | rd5GHz->dfsMask |= DFS_MKK4; | ||
603 | rd5GHz->pscan |= PSCAN_MKK3; | ||
604 | } | ||
605 | break; | ||
606 | } | ||
607 | } | ||
608 | |||
609 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
610 | "%s: Skipping %d freq band\n", | ||
611 | __func__, j_bandcheck[i].freqbandbit); | ||
612 | |||
613 | return skipband; | ||
614 | } | ||
615 | |||
616 | bool | ||
617 | ath9k_regd_init_channels(struct ath_hal *ah, | ||
618 | u32 maxchans, | ||
619 | u32 *nchans, u8 *regclassids, | ||
620 | u32 maxregids, u32 *nregids, u16 cc, | ||
621 | u32 modeSelect, bool enableOutdoor, | ||
622 | bool enableExtendedChannels) | ||
623 | { | ||
624 | u32 modesAvail; | ||
625 | u16 maxChan = 7000; | ||
626 | struct country_code_to_enum_rd *country = NULL; | ||
627 | struct regDomain rd5GHz, rd2GHz; | ||
628 | const struct cmode *cm; | ||
629 | struct ath9k_channel *ichans = &ah->ah_channels[0]; | ||
630 | int next = 0, b; | ||
631 | u8 ctl; | ||
632 | int regdmn; | ||
633 | u16 chanSep; | ||
634 | |||
635 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: cc %u mode 0x%x%s%s\n", | ||
636 | __func__, cc, modeSelect, | ||
637 | enableOutdoor ? " Enable outdoor" : " ", | ||
638 | enableExtendedChannels ? " Enable ecm" : ""); | ||
639 | |||
640 | if (!ath9k_regd_is_ccode_valid(ah, cc)) { | ||
641 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
642 | "%s: invalid country code %d\n", __func__, cc); | ||
643 | return false; | ||
644 | } | ||
645 | |||
646 | if (!ath9k_regd_is_eeprom_valid(ah)) { | ||
647 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
648 | "%s: invalid EEPROM contents\n", __func__); | ||
649 | return false; | ||
650 | } | ||
651 | |||
652 | ah->ah_countryCode = ath9k_regd_get_default_country(ah); | ||
653 | |||
654 | if (ah->ah_countryCode == CTRY_DEFAULT) { | ||
655 | ah->ah_countryCode = cc & COUNTRY_CODE_MASK; | ||
656 | if ((ah->ah_countryCode == CTRY_DEFAULT) && | ||
657 | (ath9k_regd_get_eepromRD(ah) == CTRY_DEFAULT)) { | ||
658 | ah->ah_countryCode = CTRY_UNITED_STATES; | ||
659 | } | ||
660 | } | ||
661 | |||
662 | #ifdef AH_SUPPORT_11D | ||
663 | if (ah->ah_countryCode == CTRY_DEFAULT) { | ||
664 | regdmn = ath9k_regd_get_eepromRD(ah); | ||
665 | country = NULL; | ||
666 | } else { | ||
667 | #endif | ||
668 | country = ath9k_regd_find_country(ah->ah_countryCode); | ||
669 | if (country == NULL) { | ||
670 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
671 | "Country is NULL!!!!, cc= %d\n", | ||
672 | ah->ah_countryCode); | ||
673 | return false; | ||
674 | } else { | ||
675 | regdmn = country->regDmnEnum; | ||
676 | #ifdef AH_SUPPORT_11D | ||
677 | if (((ath9k_regd_get_eepromRD(ah) & | ||
678 | WORLD_SKU_MASK) == WORLD_SKU_PREFIX) && | ||
679 | (cc == CTRY_UNITED_STATES)) { | ||
680 | if (!isWwrSKU_NoMidband(ah) | ||
681 | && ath9k_regd_is_fcc_midband_supported(ah)) | ||
682 | regdmn = FCC3_FCCA; | ||
683 | else | ||
684 | regdmn = FCC1_FCCA; | ||
685 | } | ||
686 | #endif | ||
687 | } | ||
688 | #ifdef AH_SUPPORT_11D | ||
689 | } | ||
690 | #endif | ||
691 | if (!ath9k_regd_get_wmode_regdomain(ah, | ||
692 | regdmn, | ||
693 | ~CHANNEL_2GHZ, | ||
694 | &rd5GHz)) { | ||
695 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
696 | "%s: couldn't find unitary " | ||
697 | "5GHz reg domain for country %u\n", | ||
698 | __func__, ah->ah_countryCode); | ||
699 | return false; | ||
700 | } | ||
701 | if (!ath9k_regd_get_wmode_regdomain(ah, | ||
702 | regdmn, | ||
703 | CHANNEL_2GHZ, | ||
704 | &rd2GHz)) { | ||
705 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
706 | "%s: couldn't find unitary 2GHz " | ||
707 | "reg domain for country %u\n", | ||
708 | __func__, ah->ah_countryCode); | ||
709 | return false; | ||
710 | } | ||
711 | |||
712 | if (!isWwrSKU(ah) && ((rd5GHz.regDmnEnum == FCC1) || | ||
713 | (rd5GHz.regDmnEnum == FCC2))) { | ||
714 | if (ath9k_regd_is_fcc_midband_supported(ah)) { | ||
715 | if (!ath9k_regd_get_wmode_regdomain(ah, | ||
716 | FCC3_FCCA, | ||
717 | ~CHANNEL_2GHZ, | ||
718 | &rd5GHz)) { | ||
719 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
720 | "%s: couldn't find unitary 5GHz " | ||
721 | "reg domain for country %u\n", | ||
722 | __func__, ah->ah_countryCode); | ||
723 | return false; | ||
724 | } | ||
725 | } | ||
726 | } | ||
727 | |||
728 | if (country == NULL) { | ||
729 | modesAvail = ah->ah_caps.halWirelessModes; | ||
730 | } else { | ||
731 | modesAvail = ath9k_regd_get_wmodes_nreg(ah, country, &rd5GHz); | ||
732 | if (!enableOutdoor) | ||
733 | maxChan = country->outdoorChanStart; | ||
734 | } | ||
735 | |||
736 | next = 0; | ||
737 | |||
738 | if (maxchans > ARRAY_SIZE(ah->ah_channels)) | ||
739 | maxchans = ARRAY_SIZE(ah->ah_channels); | ||
740 | |||
741 | for (cm = modes; cm < &modes[ARRAY_SIZE(modes)]; cm++) { | ||
742 | u16 c, c_hi, c_lo; | ||
743 | u64 *channelBM = NULL; | ||
744 | struct regDomain *rd = NULL; | ||
745 | struct RegDmnFreqBand *fband = NULL, *freqs; | ||
746 | int8_t low_adj = 0, hi_adj = 0; | ||
747 | |||
748 | if ((cm->mode & modeSelect) == 0) { | ||
749 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
750 | "%s: skip mode 0x%x flags 0x%x\n", | ||
751 | __func__, cm->mode, cm->flags); | ||
752 | continue; | ||
753 | } | ||
754 | if ((cm->mode & modesAvail) == 0) { | ||
755 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
756 | "%s: !avail mode 0x%x (0x%x) flags 0x%x\n", | ||
757 | __func__, modesAvail, cm->mode, | ||
758 | cm->flags); | ||
759 | continue; | ||
760 | } | ||
761 | if (!ath9k_get_channel_edges(ah, cm->flags, &c_lo, &c_hi)) { | ||
762 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
763 | "%s: channels 0x%x not supported " | ||
764 | "by hardware\n", | ||
765 | __func__, cm->flags); | ||
766 | continue; | ||
767 | } | ||
768 | |||
769 | switch (cm->mode) { | ||
770 | case ATH9K_MODE_SEL_11A: | ||
771 | case ATH9K_MODE_SEL_11NA_HT20: | ||
772 | case ATH9K_MODE_SEL_11NA_HT40PLUS: | ||
773 | case ATH9K_MODE_SEL_11NA_HT40MINUS: | ||
774 | rd = &rd5GHz; | ||
775 | channelBM = rd->chan11a; | ||
776 | freqs = ®Dmn5GhzFreq[0]; | ||
777 | ctl = rd->conformanceTestLimit; | ||
778 | break; | ||
779 | case ATH9K_MODE_SEL_11B: | ||
780 | rd = &rd2GHz; | ||
781 | channelBM = rd->chan11b; | ||
782 | freqs = ®Dmn2GhzFreq[0]; | ||
783 | ctl = rd->conformanceTestLimit | CTL_11B; | ||
784 | break; | ||
785 | case ATH9K_MODE_SEL_11G: | ||
786 | case ATH9K_MODE_SEL_11NG_HT20: | ||
787 | case ATH9K_MODE_SEL_11NG_HT40PLUS: | ||
788 | case ATH9K_MODE_SEL_11NG_HT40MINUS: | ||
789 | rd = &rd2GHz; | ||
790 | channelBM = rd->chan11g; | ||
791 | freqs = ®Dmn2Ghz11gFreq[0]; | ||
792 | ctl = rd->conformanceTestLimit | CTL_11G; | ||
793 | break; | ||
794 | default: | ||
795 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
796 | "%s: Unknown HAL mode 0x%x\n", __func__, | ||
797 | cm->mode); | ||
798 | continue; | ||
799 | } | ||
800 | |||
801 | if (ath9k_regd_is_chan_bm_zero(channelBM)) | ||
802 | continue; | ||
803 | |||
804 | if ((cm->mode == ATH9K_MODE_SEL_11NA_HT40PLUS) || | ||
805 | (cm->mode == ATH9K_MODE_SEL_11NG_HT40PLUS)) { | ||
806 | hi_adj = -20; | ||
807 | } | ||
808 | |||
809 | if ((cm->mode == ATH9K_MODE_SEL_11NA_HT40MINUS) || | ||
810 | (cm->mode == ATH9K_MODE_SEL_11NG_HT40MINUS)) { | ||
811 | low_adj = 20; | ||
812 | } | ||
813 | |||
814 | /* XXX: Add a helper here instead */ | ||
815 | for (b = 0; b < 64 * BMLEN; b++) { | ||
816 | if (ath9k_regd_is_bit_set(b, channelBM)) { | ||
817 | fband = &freqs[b]; | ||
818 | if (rd5GHz.regDmnEnum == MKK1 | ||
819 | || rd5GHz.regDmnEnum == MKK2) { | ||
820 | if (ath9k_regd_japan_check(ah, | ||
821 | b, | ||
822 | &rd5GHz)) | ||
823 | continue; | ||
824 | } | ||
825 | |||
826 | ath9k_regd_add_reg_classid(regclassids, | ||
827 | maxregids, | ||
828 | nregids, | ||
829 | fband-> | ||
830 | regClassId); | ||
831 | |||
832 | if (IS_HT40_MODE(cm->mode) && (rd == &rd5GHz)) { | ||
833 | chanSep = 40; | ||
834 | if (fband->lowChannel == 5280) | ||
835 | low_adj += 20; | ||
836 | |||
837 | if (fband->lowChannel == 5170) | ||
838 | continue; | ||
839 | } else | ||
840 | chanSep = fband->channelSep; | ||
841 | |||
842 | for (c = fband->lowChannel + low_adj; | ||
843 | ((c <= (fband->highChannel + hi_adj)) && | ||
844 | (c >= (fband->lowChannel + low_adj))); | ||
845 | c += chanSep) { | ||
846 | if (next >= maxchans) { | ||
847 | DPRINTF(ah->ah_sc, | ||
848 | ATH_DBG_REGULATORY, | ||
849 | "%s: too many channels " | ||
850 | "for channel table\n", | ||
851 | __func__); | ||
852 | goto done; | ||
853 | } | ||
854 | if (ath9k_regd_add_channel(ah, | ||
855 | c, c_lo, c_hi, | ||
856 | maxChan, ctl, | ||
857 | next, | ||
858 | rd5GHz, | ||
859 | fband, rd, cm, | ||
860 | ichans, | ||
861 | enableExtendedChannels)) | ||
862 | next++; | ||
863 | } | ||
864 | if (IS_HT40_MODE(cm->mode) && | ||
865 | (fband->lowChannel == 5280)) { | ||
866 | low_adj -= 20; | ||
867 | } | ||
868 | } | ||
869 | } | ||
870 | } | ||
871 | done: | ||
872 | if (next != 0) { | ||
873 | int i; | ||
874 | |||
875 | if (next > ARRAY_SIZE(ah->ah_channels)) { | ||
876 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
877 | "%s: too many channels %u; truncating to %u\n", | ||
878 | __func__, next, | ||
879 | (int) ARRAY_SIZE(ah->ah_channels)); | ||
880 | next = ARRAY_SIZE(ah->ah_channels); | ||
881 | } | ||
882 | #ifdef ATH_NF_PER_CHAN | ||
883 | ath9k_regd_init_rf_buffer(ichans, next); | ||
884 | #endif | ||
885 | ath9k_regd_sort(ichans, next, | ||
886 | sizeof(struct ath9k_channel), | ||
887 | ath9k_regd_chansort); | ||
888 | |||
889 | ah->ah_nchan = next; | ||
890 | |||
891 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "Channel list:\n"); | ||
892 | for (i = 0; i < next; i++) { | ||
893 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
894 | "chan: %d flags: 0x%x\n", | ||
895 | ah->ah_channels[i].channel, | ||
896 | ah->ah_channels[i].channelFlags); | ||
897 | } | ||
898 | } | ||
899 | *nchans = next; | ||
900 | |||
901 | ah->ah_countryCode = ah->ah_countryCode; | ||
902 | |||
903 | ah->ah_currentRDInUse = regdmn; | ||
904 | ah->ah_currentRD5G = rd5GHz.regDmnEnum; | ||
905 | ah->ah_currentRD2G = rd2GHz.regDmnEnum; | ||
906 | if (country == NULL) { | ||
907 | ah->ah_iso[0] = 0; | ||
908 | ah->ah_iso[1] = 0; | ||
909 | } else { | ||
910 | ah->ah_iso[0] = country->isoName[0]; | ||
911 | ah->ah_iso[1] = country->isoName[1]; | ||
912 | } | ||
913 | |||
914 | return next != 0; | ||
915 | } | ||
916 | |||
917 | struct ath9k_channel* | ||
918 | ath9k_regd_check_channel(struct ath_hal *ah, | ||
919 | const struct ath9k_channel *c) | ||
920 | { | ||
921 | struct ath9k_channel *base, *cc; | ||
922 | |||
923 | int flags = c->channelFlags & CHAN_FLAGS; | ||
924 | int n, lim; | ||
925 | |||
926 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
927 | "%s: channel %u/0x%x (0x%x) requested\n", __func__, | ||
928 | c->channel, c->channelFlags, flags); | ||
929 | |||
930 | cc = ah->ah_curchan; | ||
931 | if (cc != NULL && cc->channel == c->channel && | ||
932 | (cc->channelFlags & CHAN_FLAGS) == flags) { | ||
933 | if ((cc->privFlags & CHANNEL_INTERFERENCE) && | ||
934 | (cc->privFlags & CHANNEL_DFS)) | ||
935 | return NULL; | ||
936 | else | ||
937 | return cc; | ||
938 | } | ||
939 | |||
940 | base = ah->ah_channels; | ||
941 | n = ah->ah_nchan; | ||
942 | |||
943 | for (lim = n; lim != 0; lim >>= 1) { | ||
944 | int d; | ||
945 | cc = &base[lim >> 1]; | ||
946 | d = c->channel - cc->channel; | ||
947 | if (d == 0) { | ||
948 | if ((cc->channelFlags & CHAN_FLAGS) == flags) { | ||
949 | if ((cc->privFlags & CHANNEL_INTERFERENCE) && | ||
950 | (cc->privFlags & CHANNEL_DFS)) | ||
951 | return NULL; | ||
952 | else | ||
953 | return cc; | ||
954 | } | ||
955 | d = flags - (cc->channelFlags & CHAN_FLAGS); | ||
956 | } | ||
957 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
958 | "%s: channel %u/0x%x d %d\n", __func__, | ||
959 | cc->channel, cc->channelFlags, d); | ||
960 | if (d > 0) { | ||
961 | base = cc + 1; | ||
962 | lim--; | ||
963 | } | ||
964 | } | ||
965 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: no match for %u/0x%x\n", | ||
966 | __func__, c->channel, c->channelFlags); | ||
967 | return NULL; | ||
968 | } | ||
969 | |||
970 | u32 | ||
971 | ath9k_regd_get_antenna_allowed(struct ath_hal *ah, | ||
972 | struct ath9k_channel *chan) | ||
973 | { | ||
974 | struct ath9k_channel *ichan = NULL; | ||
975 | |||
976 | ichan = ath9k_regd_check_channel(ah, chan); | ||
977 | if (!ichan) | ||
978 | return 0; | ||
979 | |||
980 | return ichan->antennaMax; | ||
981 | } | ||
982 | |||
983 | u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan) | ||
984 | { | ||
985 | u32 ctl = NO_CTL; | ||
986 | struct ath9k_channel *ichan; | ||
987 | |||
988 | if (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)) { | ||
989 | if (IS_CHAN_B(chan)) | ||
990 | ctl = SD_NO_CTL | CTL_11B; | ||
991 | else if (IS_CHAN_G(chan)) | ||
992 | ctl = SD_NO_CTL | CTL_11G; | ||
993 | else | ||
994 | ctl = SD_NO_CTL | CTL_11A; | ||
995 | } else { | ||
996 | ichan = ath9k_regd_check_channel(ah, chan); | ||
997 | if (ichan != NULL) { | ||
998 | /* FIXME */ | ||
999 | if (IS_CHAN_A(ichan)) | ||
1000 | ctl = ichan->conformanceTestLimit[0]; | ||
1001 | else if (IS_CHAN_B(ichan)) | ||
1002 | ctl = ichan->conformanceTestLimit[1]; | ||
1003 | else if (IS_CHAN_G(ichan)) | ||
1004 | ctl = ichan->conformanceTestLimit[2]; | ||
1005 | |||
1006 | if (IS_CHAN_G(chan) && (ctl & 0xf) == CTL_11B) | ||
1007 | ctl = (ctl & ~0xf) | CTL_11G; | ||
1008 | } | ||
1009 | } | ||
1010 | return ctl; | ||
1011 | } | ||
1012 | |||
1013 | void ath9k_regd_get_current_country(struct ath_hal *ah, | ||
1014 | struct ath9k_country_entry *ctry) | ||
1015 | { | ||
1016 | u16 rd = ath9k_regd_get_eepromRD(ah); | ||
1017 | |||
1018 | ctry->isMultidomain = false; | ||
1019 | if (rd == CTRY_DEFAULT) | ||
1020 | ctry->isMultidomain = true; | ||
1021 | else if (!(rd & COUNTRY_ERD_FLAG)) | ||
1022 | ctry->isMultidomain = isWwrSKU(ah); | ||
1023 | |||
1024 | ctry->countryCode = ah->ah_countryCode; | ||
1025 | ctry->regDmnEnum = ah->ah_currentRD; | ||
1026 | ctry->regDmn5G = ah->ah_currentRD5G; | ||
1027 | ctry->regDmn2G = ah->ah_currentRD2G; | ||
1028 | ctry->iso[0] = ah->ah_iso[0]; | ||
1029 | ctry->iso[1] = ah->ah_iso[1]; | ||
1030 | ctry->iso[2] = ah->ah_iso[2]; | ||
1031 | } | ||
diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h new file mode 100644 index 00000000000..ae77496bfde --- /dev/null +++ b/drivers/net/wireless/ath9k/regd.h | |||
@@ -0,0 +1,412 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef REGD_H | ||
18 | #define REGD_H | ||
19 | |||
20 | #include "ath9k.h" | ||
21 | |||
22 | #define BMLEN 2 | ||
23 | #define BMZERO {(u64) 0, (u64) 0} | ||
24 | |||
25 | #define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi, _fj, _fk, _fl) \ | ||
26 | {((((_fa >= 0) && (_fa < 64)) ? \ | ||
27 | (((u64) 1) << _fa) : (u64) 0) | \ | ||
28 | (((_fb >= 0) && (_fb < 64)) ? \ | ||
29 | (((u64) 1) << _fb) : (u64) 0) | \ | ||
30 | (((_fc >= 0) && (_fc < 64)) ? \ | ||
31 | (((u64) 1) << _fc) : (u64) 0) | \ | ||
32 | (((_fd >= 0) && (_fd < 64)) ? \ | ||
33 | (((u64) 1) << _fd) : (u64) 0) | \ | ||
34 | (((_fe >= 0) && (_fe < 64)) ? \ | ||
35 | (((u64) 1) << _fe) : (u64) 0) | \ | ||
36 | (((_ff >= 0) && (_ff < 64)) ? \ | ||
37 | (((u64) 1) << _ff) : (u64) 0) | \ | ||
38 | (((_fg >= 0) && (_fg < 64)) ? \ | ||
39 | (((u64) 1) << _fg) : (u64) 0) | \ | ||
40 | (((_fh >= 0) && (_fh < 64)) ? \ | ||
41 | (((u64) 1) << _fh) : (u64) 0) | \ | ||
42 | (((_fi >= 0) && (_fi < 64)) ? \ | ||
43 | (((u64) 1) << _fi) : (u64) 0) | \ | ||
44 | (((_fj >= 0) && (_fj < 64)) ? \ | ||
45 | (((u64) 1) << _fj) : (u64) 0) | \ | ||
46 | (((_fk >= 0) && (_fk < 64)) ? \ | ||
47 | (((u64) 1) << _fk) : (u64) 0) | \ | ||
48 | (((_fl >= 0) && (_fl < 64)) ? \ | ||
49 | (((u64) 1) << _fl) : (u64) 0) | \ | ||
50 | ((((_fa > 63) && (_fa < 128)) ? \ | ||
51 | (((u64) 1) << (_fa - 64)) : (u64) 0) | \ | ||
52 | (((_fb > 63) && (_fb < 128)) ? \ | ||
53 | (((u64) 1) << (_fb - 64)) : (u64) 0) | \ | ||
54 | (((_fc > 63) && (_fc < 128)) ? \ | ||
55 | (((u64) 1) << (_fc - 64)) : (u64) 0) | \ | ||
56 | (((_fd > 63) && (_fd < 128)) ? \ | ||
57 | (((u64) 1) << (_fd - 64)) : (u64) 0) | \ | ||
58 | (((_fe > 63) && (_fe < 128)) ? \ | ||
59 | (((u64) 1) << (_fe - 64)) : (u64) 0) | \ | ||
60 | (((_ff > 63) && (_ff < 128)) ? \ | ||
61 | (((u64) 1) << (_ff - 64)) : (u64) 0) | \ | ||
62 | (((_fg > 63) && (_fg < 128)) ? \ | ||
63 | (((u64) 1) << (_fg - 64)) : (u64) 0) | \ | ||
64 | (((_fh > 63) && (_fh < 128)) ? \ | ||
65 | (((u64) 1) << (_fh - 64)) : (u64) 0) | \ | ||
66 | (((_fi > 63) && (_fi < 128)) ? \ | ||
67 | (((u64) 1) << (_fi - 64)) : (u64) 0) | \ | ||
68 | (((_fj > 63) && (_fj < 128)) ? \ | ||
69 | (((u64) 1) << (_fj - 64)) : (u64) 0) | \ | ||
70 | (((_fk > 63) && (_fk < 128)) ? \ | ||
71 | (((u64) 1) << (_fk - 64)) : (u64) 0) | \ | ||
72 | (((_fl > 63) && (_fl < 128)) ? \ | ||
73 | (((u64) 1) << (_fl - 64)) : (u64) 0)))} | ||
74 | |||
75 | #define DEF_REGDMN FCC1_FCCA | ||
76 | #define DEF_DMN_5 FCC1 | ||
77 | #define DEF_DMN_2 FCCA | ||
78 | #define COUNTRY_ERD_FLAG 0x8000 | ||
79 | #define WORLDWIDE_ROAMING_FLAG 0x4000 | ||
80 | #define SUPER_DOMAIN_MASK 0x0fff | ||
81 | #define COUNTRY_CODE_MASK 0x3fff | ||
82 | #define CF_INTERFERENCE (CHANNEL_CW_INT | CHANNEL_RADAR_INT) | ||
83 | #define CHANNEL_14 (2484) | ||
84 | #define IS_11G_CH14(_ch,_cf) \ | ||
85 | (((_ch) == CHANNEL_14) && ((_cf) == CHANNEL_G)) | ||
86 | |||
87 | #define NO_PSCAN 0x0ULL | ||
88 | #define PSCAN_FCC 0x0000000000000001ULL | ||
89 | #define PSCAN_FCC_T 0x0000000000000002ULL | ||
90 | #define PSCAN_ETSI 0x0000000000000004ULL | ||
91 | #define PSCAN_MKK1 0x0000000000000008ULL | ||
92 | #define PSCAN_MKK2 0x0000000000000010ULL | ||
93 | #define PSCAN_MKKA 0x0000000000000020ULL | ||
94 | #define PSCAN_MKKA_G 0x0000000000000040ULL | ||
95 | #define PSCAN_ETSIA 0x0000000000000080ULL | ||
96 | #define PSCAN_ETSIB 0x0000000000000100ULL | ||
97 | #define PSCAN_ETSIC 0x0000000000000200ULL | ||
98 | #define PSCAN_WWR 0x0000000000000400ULL | ||
99 | #define PSCAN_MKKA1 0x0000000000000800ULL | ||
100 | #define PSCAN_MKKA1_G 0x0000000000001000ULL | ||
101 | #define PSCAN_MKKA2 0x0000000000002000ULL | ||
102 | #define PSCAN_MKKA2_G 0x0000000000004000ULL | ||
103 | #define PSCAN_MKK3 0x0000000000008000ULL | ||
104 | #define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL | ||
105 | #define IS_ECM_CHAN 0x8000000000000000ULL | ||
106 | |||
107 | #define isWwrSKU(_ah) \ | ||
108 | (((ath9k_regd_get_eepromRD((_ah)) & WORLD_SKU_MASK) == \ | ||
109 | WORLD_SKU_PREFIX) || \ | ||
110 | (ath9k_regd_get_eepromRD(_ah) == WORLD)) | ||
111 | |||
112 | #define isWwrSKU_NoMidband(_ah) \ | ||
113 | ((ath9k_regd_get_eepromRD((_ah)) == WOR3_WORLD) || \ | ||
114 | (ath9k_regd_get_eepromRD(_ah) == WOR4_WORLD) || \ | ||
115 | (ath9k_regd_get_eepromRD(_ah) == WOR5_ETSIC)) | ||
116 | |||
117 | #define isUNII1OddChan(ch) \ | ||
118 | ((ch == 5170) || (ch == 5190) || (ch == 5210) || (ch == 5230)) | ||
119 | |||
120 | #define IS_HT40_MODE(_mode) \ | ||
121 | (((_mode == ATH9K_MODE_SEL_11NA_HT40PLUS || \ | ||
122 | _mode == ATH9K_MODE_SEL_11NG_HT40PLUS || \ | ||
123 | _mode == ATH9K_MODE_SEL_11NA_HT40MINUS || \ | ||
124 | _mode == ATH9K_MODE_SEL_11NG_HT40MINUS) ? true : false)) | ||
125 | |||
126 | #define CHAN_FLAGS (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER) | ||
127 | |||
128 | #define swap(_a, _b, _size) { \ | ||
129 | u8 *s = _b; \ | ||
130 | int i = _size; \ | ||
131 | do { \ | ||
132 | u8 tmp = *_a; \ | ||
133 | *_a++ = *s; \ | ||
134 | *s++ = tmp; \ | ||
135 | } while (--i); \ | ||
136 | _a -= _size; \ | ||
137 | } | ||
138 | |||
139 | |||
140 | #define HALF_MAXCHANBW 10 | ||
141 | |||
142 | #define MULTI_DOMAIN_MASK 0xFF00 | ||
143 | |||
144 | #define WORLD_SKU_MASK 0x00F0 | ||
145 | #define WORLD_SKU_PREFIX 0x0060 | ||
146 | |||
147 | #define CHANNEL_HALF_BW 10 | ||
148 | #define CHANNEL_QUARTER_BW 5 | ||
149 | |||
150 | typedef int ath_hal_cmp_t(const void *, const void *); | ||
151 | |||
152 | struct reg_dmn_pair_mapping { | ||
153 | u16 regDmnEnum; | ||
154 | u16 regDmn5GHz; | ||
155 | u16 regDmn2GHz; | ||
156 | u32 flags5GHz; | ||
157 | u32 flags2GHz; | ||
158 | u64 pscanMask; | ||
159 | u16 singleCC; | ||
160 | }; | ||
161 | |||
162 | struct ccmap { | ||
163 | char isoName[3]; | ||
164 | u16 countryCode; | ||
165 | }; | ||
166 | |||
167 | struct country_code_to_enum_rd { | ||
168 | u16 countryCode; | ||
169 | u16 regDmnEnum; | ||
170 | const char *isoName; | ||
171 | const char *name; | ||
172 | bool allow11g; | ||
173 | bool allow11aTurbo; | ||
174 | bool allow11gTurbo; | ||
175 | bool allow11ng20; | ||
176 | bool allow11ng40; | ||
177 | bool allow11na20; | ||
178 | bool allow11na40; | ||
179 | u16 outdoorChanStart; | ||
180 | }; | ||
181 | |||
182 | struct RegDmnFreqBand { | ||
183 | u16 lowChannel; | ||
184 | u16 highChannel; | ||
185 | u8 powerDfs; | ||
186 | u8 antennaMax; | ||
187 | u8 channelBW; | ||
188 | u8 channelSep; | ||
189 | u64 useDfs; | ||
190 | u64 usePassScan; | ||
191 | u8 regClassId; | ||
192 | }; | ||
193 | |||
194 | struct regDomain { | ||
195 | u16 regDmnEnum; | ||
196 | u8 conformanceTestLimit; | ||
197 | u64 dfsMask; | ||
198 | u64 pscan; | ||
199 | u32 flags; | ||
200 | u64 chan11a[BMLEN]; | ||
201 | u64 chan11a_turbo[BMLEN]; | ||
202 | u64 chan11a_dyn_turbo[BMLEN]; | ||
203 | u64 chan11b[BMLEN]; | ||
204 | u64 chan11g[BMLEN]; | ||
205 | u64 chan11g_turbo[BMLEN]; | ||
206 | }; | ||
207 | |||
208 | struct cmode { | ||
209 | u32 mode; | ||
210 | u32 flags; | ||
211 | }; | ||
212 | |||
213 | #define YES true | ||
214 | #define NO false | ||
215 | |||
216 | struct japan_bandcheck { | ||
217 | u16 freqbandbit; | ||
218 | u32 eepromflagtocheck; | ||
219 | }; | ||
220 | |||
221 | struct common_mode_power { | ||
222 | u16 lchan; | ||
223 | u16 hchan; | ||
224 | u8 pwrlvl; | ||
225 | }; | ||
226 | |||
227 | enum CountryCode { | ||
228 | CTRY_ALBANIA = 8, | ||
229 | CTRY_ALGERIA = 12, | ||
230 | CTRY_ARGENTINA = 32, | ||
231 | CTRY_ARMENIA = 51, | ||
232 | CTRY_AUSTRALIA = 36, | ||
233 | CTRY_AUSTRIA = 40, | ||
234 | CTRY_AZERBAIJAN = 31, | ||
235 | CTRY_BAHRAIN = 48, | ||
236 | CTRY_BELARUS = 112, | ||
237 | CTRY_BELGIUM = 56, | ||
238 | CTRY_BELIZE = 84, | ||
239 | CTRY_BOLIVIA = 68, | ||
240 | CTRY_BOSNIA_HERZ = 70, | ||
241 | CTRY_BRAZIL = 76, | ||
242 | CTRY_BRUNEI_DARUSSALAM = 96, | ||
243 | CTRY_BULGARIA = 100, | ||
244 | CTRY_CANADA = 124, | ||
245 | CTRY_CHILE = 152, | ||
246 | CTRY_CHINA = 156, | ||
247 | CTRY_COLOMBIA = 170, | ||
248 | CTRY_COSTA_RICA = 188, | ||
249 | CTRY_CROATIA = 191, | ||
250 | CTRY_CYPRUS = 196, | ||
251 | CTRY_CZECH = 203, | ||
252 | CTRY_DENMARK = 208, | ||
253 | CTRY_DOMINICAN_REPUBLIC = 214, | ||
254 | CTRY_ECUADOR = 218, | ||
255 | CTRY_EGYPT = 818, | ||
256 | CTRY_EL_SALVADOR = 222, | ||
257 | CTRY_ESTONIA = 233, | ||
258 | CTRY_FAEROE_ISLANDS = 234, | ||
259 | CTRY_FINLAND = 246, | ||
260 | CTRY_FRANCE = 250, | ||
261 | CTRY_GEORGIA = 268, | ||
262 | CTRY_GERMANY = 276, | ||
263 | CTRY_GREECE = 300, | ||
264 | CTRY_GUATEMALA = 320, | ||
265 | CTRY_HONDURAS = 340, | ||
266 | CTRY_HONG_KONG = 344, | ||
267 | CTRY_HUNGARY = 348, | ||
268 | CTRY_ICELAND = 352, | ||
269 | CTRY_INDIA = 356, | ||
270 | CTRY_INDONESIA = 360, | ||
271 | CTRY_IRAN = 364, | ||
272 | CTRY_IRAQ = 368, | ||
273 | CTRY_IRELAND = 372, | ||
274 | CTRY_ISRAEL = 376, | ||
275 | CTRY_ITALY = 380, | ||
276 | CTRY_JAMAICA = 388, | ||
277 | CTRY_JAPAN = 392, | ||
278 | CTRY_JORDAN = 400, | ||
279 | CTRY_KAZAKHSTAN = 398, | ||
280 | CTRY_KENYA = 404, | ||
281 | CTRY_KOREA_NORTH = 408, | ||
282 | CTRY_KOREA_ROC = 410, | ||
283 | CTRY_KOREA_ROC2 = 411, | ||
284 | CTRY_KOREA_ROC3 = 412, | ||
285 | CTRY_KUWAIT = 414, | ||
286 | CTRY_LATVIA = 428, | ||
287 | CTRY_LEBANON = 422, | ||
288 | CTRY_LIBYA = 434, | ||
289 | CTRY_LIECHTENSTEIN = 438, | ||
290 | CTRY_LITHUANIA = 440, | ||
291 | CTRY_LUXEMBOURG = 442, | ||
292 | CTRY_MACAU = 446, | ||
293 | CTRY_MACEDONIA = 807, | ||
294 | CTRY_MALAYSIA = 458, | ||
295 | CTRY_MALTA = 470, | ||
296 | CTRY_MEXICO = 484, | ||
297 | CTRY_MONACO = 492, | ||
298 | CTRY_MOROCCO = 504, | ||
299 | CTRY_NEPAL = 524, | ||
300 | CTRY_NETHERLANDS = 528, | ||
301 | CTRY_NETHERLANDS_ANTILLES = 530, | ||
302 | CTRY_NEW_ZEALAND = 554, | ||
303 | CTRY_NICARAGUA = 558, | ||
304 | CTRY_NORWAY = 578, | ||
305 | CTRY_OMAN = 512, | ||
306 | CTRY_PAKISTAN = 586, | ||
307 | CTRY_PANAMA = 591, | ||
308 | CTRY_PAPUA_NEW_GUINEA = 598, | ||
309 | CTRY_PARAGUAY = 600, | ||
310 | CTRY_PERU = 604, | ||
311 | CTRY_PHILIPPINES = 608, | ||
312 | CTRY_POLAND = 616, | ||
313 | CTRY_PORTUGAL = 620, | ||
314 | CTRY_PUERTO_RICO = 630, | ||
315 | CTRY_QATAR = 634, | ||
316 | CTRY_ROMANIA = 642, | ||
317 | CTRY_RUSSIA = 643, | ||
318 | CTRY_SAUDI_ARABIA = 682, | ||
319 | CTRY_SERBIA_MONTENEGRO = 891, | ||
320 | CTRY_SINGAPORE = 702, | ||
321 | CTRY_SLOVAKIA = 703, | ||
322 | CTRY_SLOVENIA = 705, | ||
323 | CTRY_SOUTH_AFRICA = 710, | ||
324 | CTRY_SPAIN = 724, | ||
325 | CTRY_SRI_LANKA = 144, | ||
326 | CTRY_SWEDEN = 752, | ||
327 | CTRY_SWITZERLAND = 756, | ||
328 | CTRY_SYRIA = 760, | ||
329 | CTRY_TAIWAN = 158, | ||
330 | CTRY_THAILAND = 764, | ||
331 | CTRY_TRINIDAD_Y_TOBAGO = 780, | ||
332 | CTRY_TUNISIA = 788, | ||
333 | CTRY_TURKEY = 792, | ||
334 | CTRY_UAE = 784, | ||
335 | CTRY_UKRAINE = 804, | ||
336 | CTRY_UNITED_KINGDOM = 826, | ||
337 | CTRY_UNITED_STATES = 840, | ||
338 | CTRY_UNITED_STATES_FCC49 = 842, | ||
339 | CTRY_URUGUAY = 858, | ||
340 | CTRY_UZBEKISTAN = 860, | ||
341 | CTRY_VENEZUELA = 862, | ||
342 | CTRY_VIET_NAM = 704, | ||
343 | CTRY_YEMEN = 887, | ||
344 | CTRY_ZIMBABWE = 716, | ||
345 | CTRY_JAPAN1 = 393, | ||
346 | CTRY_JAPAN2 = 394, | ||
347 | CTRY_JAPAN3 = 395, | ||
348 | CTRY_JAPAN4 = 396, | ||
349 | CTRY_JAPAN5 = 397, | ||
350 | CTRY_JAPAN6 = 4006, | ||
351 | CTRY_JAPAN7 = 4007, | ||
352 | CTRY_JAPAN8 = 4008, | ||
353 | CTRY_JAPAN9 = 4009, | ||
354 | CTRY_JAPAN10 = 4010, | ||
355 | CTRY_JAPAN11 = 4011, | ||
356 | CTRY_JAPAN12 = 4012, | ||
357 | CTRY_JAPAN13 = 4013, | ||
358 | CTRY_JAPAN14 = 4014, | ||
359 | CTRY_JAPAN15 = 4015, | ||
360 | CTRY_JAPAN16 = 4016, | ||
361 | CTRY_JAPAN17 = 4017, | ||
362 | CTRY_JAPAN18 = 4018, | ||
363 | CTRY_JAPAN19 = 4019, | ||
364 | CTRY_JAPAN20 = 4020, | ||
365 | CTRY_JAPAN21 = 4021, | ||
366 | CTRY_JAPAN22 = 4022, | ||
367 | CTRY_JAPAN23 = 4023, | ||
368 | CTRY_JAPAN24 = 4024, | ||
369 | CTRY_JAPAN25 = 4025, | ||
370 | CTRY_JAPAN26 = 4026, | ||
371 | CTRY_JAPAN27 = 4027, | ||
372 | CTRY_JAPAN28 = 4028, | ||
373 | CTRY_JAPAN29 = 4029, | ||
374 | CTRY_JAPAN30 = 4030, | ||
375 | CTRY_JAPAN31 = 4031, | ||
376 | CTRY_JAPAN32 = 4032, | ||
377 | CTRY_JAPAN33 = 4033, | ||
378 | CTRY_JAPAN34 = 4034, | ||
379 | CTRY_JAPAN35 = 4035, | ||
380 | CTRY_JAPAN36 = 4036, | ||
381 | CTRY_JAPAN37 = 4037, | ||
382 | CTRY_JAPAN38 = 4038, | ||
383 | CTRY_JAPAN39 = 4039, | ||
384 | CTRY_JAPAN40 = 4040, | ||
385 | CTRY_JAPAN41 = 4041, | ||
386 | CTRY_JAPAN42 = 4042, | ||
387 | CTRY_JAPAN43 = 4043, | ||
388 | CTRY_JAPAN44 = 4044, | ||
389 | CTRY_JAPAN45 = 4045, | ||
390 | CTRY_JAPAN46 = 4046, | ||
391 | CTRY_JAPAN47 = 4047, | ||
392 | CTRY_JAPAN48 = 4048, | ||
393 | CTRY_JAPAN49 = 4049, | ||
394 | CTRY_JAPAN50 = 4050, | ||
395 | CTRY_JAPAN51 = 4051, | ||
396 | CTRY_JAPAN52 = 4052, | ||
397 | CTRY_JAPAN53 = 4053, | ||
398 | CTRY_JAPAN54 = 4054, | ||
399 | CTRY_JAPAN55 = 4055, | ||
400 | CTRY_JAPAN56 = 4056, | ||
401 | CTRY_JAPAN57 = 4057, | ||
402 | CTRY_JAPAN58 = 4058, | ||
403 | CTRY_JAPAN59 = 4059, | ||
404 | CTRY_AUSTRALIA2 = 5000, | ||
405 | CTRY_CANADA2 = 5001, | ||
406 | CTRY_BELGIUM2 = 5002 | ||
407 | }; | ||
408 | |||
409 | void ath9k_regd_get_current_country(struct ath_hal *ah, | ||
410 | struct ath9k_country_entry *ctry); | ||
411 | |||
412 | #endif | ||
diff --git a/drivers/net/wireless/ath9k/regd_common.h b/drivers/net/wireless/ath9k/regd_common.h new file mode 100644 index 00000000000..b3bfae4fc99 --- /dev/null +++ b/drivers/net/wireless/ath9k/regd_common.h | |||
@@ -0,0 +1,1915 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef REGD_COMMON_H | ||
18 | #define REGD_COMMON_H | ||
19 | |||
20 | enum EnumRd { | ||
21 | NO_ENUMRD = 0x00, | ||
22 | NULL1_WORLD = 0x03, | ||
23 | NULL1_ETSIB = 0x07, | ||
24 | NULL1_ETSIC = 0x08, | ||
25 | FCC1_FCCA = 0x10, | ||
26 | FCC1_WORLD = 0x11, | ||
27 | FCC4_FCCA = 0x12, | ||
28 | FCC5_FCCA = 0x13, | ||
29 | FCC6_FCCA = 0x14, | ||
30 | |||
31 | FCC2_FCCA = 0x20, | ||
32 | FCC2_WORLD = 0x21, | ||
33 | FCC2_ETSIC = 0x22, | ||
34 | FCC6_WORLD = 0x23, | ||
35 | FRANCE_RES = 0x31, | ||
36 | FCC3_FCCA = 0x3A, | ||
37 | FCC3_WORLD = 0x3B, | ||
38 | |||
39 | ETSI1_WORLD = 0x37, | ||
40 | ETSI3_ETSIA = 0x32, | ||
41 | ETSI2_WORLD = 0x35, | ||
42 | ETSI3_WORLD = 0x36, | ||
43 | ETSI4_WORLD = 0x30, | ||
44 | ETSI4_ETSIC = 0x38, | ||
45 | ETSI5_WORLD = 0x39, | ||
46 | ETSI6_WORLD = 0x34, | ||
47 | ETSI_RESERVED = 0x33, | ||
48 | |||
49 | MKK1_MKKA = 0x40, | ||
50 | MKK1_MKKB = 0x41, | ||
51 | APL4_WORLD = 0x42, | ||
52 | MKK2_MKKA = 0x43, | ||
53 | APL_RESERVED = 0x44, | ||
54 | APL2_WORLD = 0x45, | ||
55 | APL2_APLC = 0x46, | ||
56 | APL3_WORLD = 0x47, | ||
57 | MKK1_FCCA = 0x48, | ||
58 | APL2_APLD = 0x49, | ||
59 | MKK1_MKKA1 = 0x4A, | ||
60 | MKK1_MKKA2 = 0x4B, | ||
61 | MKK1_MKKC = 0x4C, | ||
62 | |||
63 | APL3_FCCA = 0x50, | ||
64 | APL1_WORLD = 0x52, | ||
65 | APL1_FCCA = 0x53, | ||
66 | APL1_APLA = 0x54, | ||
67 | APL1_ETSIC = 0x55, | ||
68 | APL2_ETSIC = 0x56, | ||
69 | APL5_WORLD = 0x58, | ||
70 | APL6_WORLD = 0x5B, | ||
71 | APL7_FCCA = 0x5C, | ||
72 | APL8_WORLD = 0x5D, | ||
73 | APL9_WORLD = 0x5E, | ||
74 | |||
75 | WOR0_WORLD = 0x60, | ||
76 | WOR1_WORLD = 0x61, | ||
77 | WOR2_WORLD = 0x62, | ||
78 | WOR3_WORLD = 0x63, | ||
79 | WOR4_WORLD = 0x64, | ||
80 | WOR5_ETSIC = 0x65, | ||
81 | |||
82 | WOR01_WORLD = 0x66, | ||
83 | WOR02_WORLD = 0x67, | ||
84 | EU1_WORLD = 0x68, | ||
85 | |||
86 | WOR9_WORLD = 0x69, | ||
87 | WORA_WORLD = 0x6A, | ||
88 | WORB_WORLD = 0x6B, | ||
89 | |||
90 | MKK3_MKKB = 0x80, | ||
91 | MKK3_MKKA2 = 0x81, | ||
92 | MKK3_MKKC = 0x82, | ||
93 | |||
94 | MKK4_MKKB = 0x83, | ||
95 | MKK4_MKKA2 = 0x84, | ||
96 | MKK4_MKKC = 0x85, | ||
97 | |||
98 | MKK5_MKKB = 0x86, | ||
99 | MKK5_MKKA2 = 0x87, | ||
100 | MKK5_MKKC = 0x88, | ||
101 | |||
102 | MKK6_MKKB = 0x89, | ||
103 | MKK6_MKKA2 = 0x8A, | ||
104 | MKK6_MKKC = 0x8B, | ||
105 | |||
106 | MKK7_MKKB = 0x8C, | ||
107 | MKK7_MKKA2 = 0x8D, | ||
108 | MKK7_MKKC = 0x8E, | ||
109 | |||
110 | MKK8_MKKB = 0x8F, | ||
111 | MKK8_MKKA2 = 0x90, | ||
112 | MKK8_MKKC = 0x91, | ||
113 | |||
114 | MKK14_MKKA1 = 0x92, | ||
115 | MKK15_MKKA1 = 0x93, | ||
116 | |||
117 | MKK10_FCCA = 0xD0, | ||
118 | MKK10_MKKA1 = 0xD1, | ||
119 | MKK10_MKKC = 0xD2, | ||
120 | MKK10_MKKA2 = 0xD3, | ||
121 | |||
122 | MKK11_MKKA = 0xD4, | ||
123 | MKK11_FCCA = 0xD5, | ||
124 | MKK11_MKKA1 = 0xD6, | ||
125 | MKK11_MKKC = 0xD7, | ||
126 | MKK11_MKKA2 = 0xD8, | ||
127 | |||
128 | MKK12_MKKA = 0xD9, | ||
129 | MKK12_FCCA = 0xDA, | ||
130 | MKK12_MKKA1 = 0xDB, | ||
131 | MKK12_MKKC = 0xDC, | ||
132 | MKK12_MKKA2 = 0xDD, | ||
133 | |||
134 | MKK13_MKKB = 0xDE, | ||
135 | |||
136 | MKK3_MKKA = 0xF0, | ||
137 | MKK3_MKKA1 = 0xF1, | ||
138 | MKK3_FCCA = 0xF2, | ||
139 | MKK4_MKKA = 0xF3, | ||
140 | MKK4_MKKA1 = 0xF4, | ||
141 | MKK4_FCCA = 0xF5, | ||
142 | MKK9_MKKA = 0xF6, | ||
143 | MKK10_MKKA = 0xF7, | ||
144 | MKK6_MKKA1 = 0xF8, | ||
145 | MKK6_FCCA = 0xF9, | ||
146 | MKK7_MKKA1 = 0xFA, | ||
147 | MKK7_FCCA = 0xFB, | ||
148 | MKK9_FCCA = 0xFC, | ||
149 | MKK9_MKKA1 = 0xFD, | ||
150 | MKK9_MKKC = 0xFE, | ||
151 | MKK9_MKKA2 = 0xFF, | ||
152 | |||
153 | APL1 = 0x0150, | ||
154 | APL2 = 0x0250, | ||
155 | APL3 = 0x0350, | ||
156 | APL4 = 0x0450, | ||
157 | APL5 = 0x0550, | ||
158 | APL6 = 0x0650, | ||
159 | APL7 = 0x0750, | ||
160 | APL8 = 0x0850, | ||
161 | APL9 = 0x0950, | ||
162 | APL10 = 0x1050, | ||
163 | |||
164 | ETSI1 = 0x0130, | ||
165 | ETSI2 = 0x0230, | ||
166 | ETSI3 = 0x0330, | ||
167 | ETSI4 = 0x0430, | ||
168 | ETSI5 = 0x0530, | ||
169 | ETSI6 = 0x0630, | ||
170 | ETSIA = 0x0A30, | ||
171 | ETSIB = 0x0B30, | ||
172 | ETSIC = 0x0C30, | ||
173 | |||
174 | FCC1 = 0x0110, | ||
175 | FCC2 = 0x0120, | ||
176 | FCC3 = 0x0160, | ||
177 | FCC4 = 0x0165, | ||
178 | FCC5 = 0x0510, | ||
179 | FCC6 = 0x0610, | ||
180 | FCCA = 0x0A10, | ||
181 | |||
182 | APLD = 0x0D50, | ||
183 | |||
184 | MKK1 = 0x0140, | ||
185 | MKK2 = 0x0240, | ||
186 | MKK3 = 0x0340, | ||
187 | MKK4 = 0x0440, | ||
188 | MKK5 = 0x0540, | ||
189 | MKK6 = 0x0640, | ||
190 | MKK7 = 0x0740, | ||
191 | MKK8 = 0x0840, | ||
192 | MKK9 = 0x0940, | ||
193 | MKK10 = 0x0B40, | ||
194 | MKK11 = 0x1140, | ||
195 | MKK12 = 0x1240, | ||
196 | MKK13 = 0x0C40, | ||
197 | MKK14 = 0x1440, | ||
198 | MKK15 = 0x1540, | ||
199 | MKKA = 0x0A40, | ||
200 | MKKC = 0x0A50, | ||
201 | |||
202 | NULL1 = 0x0198, | ||
203 | WORLD = 0x0199, | ||
204 | DEBUG_REG_DMN = 0x01ff, | ||
205 | }; | ||
206 | |||
207 | enum { | ||
208 | FCC = 0x10, | ||
209 | MKK = 0x40, | ||
210 | ETSI = 0x30, | ||
211 | }; | ||
212 | |||
213 | enum { | ||
214 | NO_REQ = 0x00000000, | ||
215 | DISALLOW_ADHOC_11A = 0x00000001, | ||
216 | DISALLOW_ADHOC_11A_TURB = 0x00000002, | ||
217 | NEED_NFC = 0x00000004, | ||
218 | |||
219 | ADHOC_PER_11D = 0x00000008, | ||
220 | ADHOC_NO_11A = 0x00000010, | ||
221 | |||
222 | PUBLIC_SAFETY_DOMAIN = 0x00000020, | ||
223 | LIMIT_FRAME_4MS = 0x00000040, | ||
224 | |||
225 | NO_HOSTAP = 0x00000080, | ||
226 | |||
227 | REQ_MASK = 0x000000FF, | ||
228 | }; | ||
229 | |||
230 | #define REG_DOMAIN_2GHZ_MASK (REQ_MASK & \ | ||
231 | (!(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB))) | ||
232 | #define REG_DOMAIN_5GHZ_MASK REQ_MASK | ||
233 | |||
234 | static struct reg_dmn_pair_mapping regDomainPairs[] = { | ||
235 | {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN, NO_REQ, NO_REQ, | ||
236 | PSCAN_DEFER, 0}, | ||
237 | {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
238 | {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
239 | {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
240 | |||
241 | {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
242 | {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
243 | {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
244 | {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
245 | {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
246 | {FCC4_FCCA, FCC4, FCCA, | ||
247 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
248 | 0}, | ||
249 | {FCC5_FCCA, FCC5, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
250 | {FCC6_FCCA, FCC6, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
251 | {FCC6_WORLD, FCC6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
252 | |||
253 | {ETSI1_WORLD, ETSI1, WORLD, | ||
254 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
255 | 0}, | ||
256 | {ETSI2_WORLD, ETSI2, WORLD, | ||
257 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
258 | 0}, | ||
259 | {ETSI3_WORLD, ETSI3, WORLD, | ||
260 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
261 | 0}, | ||
262 | {ETSI4_WORLD, ETSI4, WORLD, | ||
263 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
264 | 0}, | ||
265 | {ETSI5_WORLD, ETSI5, WORLD, | ||
266 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
267 | 0}, | ||
268 | {ETSI6_WORLD, ETSI6, WORLD, | ||
269 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
270 | 0}, | ||
271 | |||
272 | {ETSI3_ETSIA, ETSI3, WORLD, | ||
273 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
274 | 0}, | ||
275 | {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
276 | |||
277 | {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
278 | {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
279 | {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
280 | {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
281 | {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
282 | {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
283 | {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
284 | {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
285 | {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
286 | {APL9_WORLD, APL9, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
287 | |||
288 | {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
289 | {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
290 | {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
291 | {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER,}, | ||
292 | |||
293 | {MKK1_MKKA, MKK1, MKKA, | ||
294 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
295 | PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN}, | ||
296 | {MKK1_MKKB, MKK1, MKKA, | ||
297 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | | ||
298 | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, | ||
299 | CTRY_JAPAN1}, | ||
300 | {MKK1_FCCA, MKK1, FCCA, | ||
301 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
302 | PSCAN_MKK1, CTRY_JAPAN2}, | ||
303 | {MKK1_MKKA1, MKK1, MKKA, | ||
304 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
305 | PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4}, | ||
306 | {MKK1_MKKA2, MKK1, MKKA, | ||
307 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
308 | PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5}, | ||
309 | {MKK1_MKKC, MKK1, MKKC, | ||
310 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
311 | PSCAN_MKK1, CTRY_JAPAN6}, | ||
312 | |||
313 | {MKK2_MKKA, MKK2, MKKA, | ||
314 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | | ||
315 | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, | ||
316 | CTRY_JAPAN3}, | ||
317 | |||
318 | {MKK3_MKKA, MKK3, MKKA, | ||
319 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
320 | PSCAN_MKKA, CTRY_JAPAN25}, | ||
321 | {MKK3_MKKB, MKK3, MKKA, | ||
322 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | | ||
323 | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, | ||
324 | CTRY_JAPAN7}, | ||
325 | {MKK3_MKKA1, MKK3, MKKA, | ||
326 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
327 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN26}, | ||
328 | {MKK3_MKKA2, MKK3, MKKA, | ||
329 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
330 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8}, | ||
331 | {MKK3_MKKC, MKK3, MKKC, | ||
332 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
333 | NO_PSCAN, CTRY_JAPAN9}, | ||
334 | {MKK3_FCCA, MKK3, FCCA, | ||
335 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
336 | NO_PSCAN, CTRY_JAPAN27}, | ||
337 | |||
338 | {MKK4_MKKA, MKK4, MKKA, | ||
339 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
340 | PSCAN_MKK3, CTRY_JAPAN36}, | ||
341 | {MKK4_MKKB, MKK4, MKKA, | ||
342 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | | ||
343 | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, | ||
344 | CTRY_JAPAN10}, | ||
345 | {MKK4_MKKA1, MKK4, MKKA, | ||
346 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
347 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN28}, | ||
348 | {MKK4_MKKA2, MKK4, MKKA, | ||
349 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
350 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11}, | ||
351 | {MKK4_MKKC, MKK4, MKKC, | ||
352 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
353 | PSCAN_MKK3, CTRY_JAPAN12}, | ||
354 | {MKK4_FCCA, MKK4, FCCA, | ||
355 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
356 | PSCAN_MKK3, CTRY_JAPAN29}, | ||
357 | |||
358 | {MKK5_MKKB, MKK5, MKKA, | ||
359 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | | ||
360 | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, | ||
361 | CTRY_JAPAN13}, | ||
362 | {MKK5_MKKA2, MKK5, MKKA, | ||
363 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
364 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14}, | ||
365 | {MKK5_MKKC, MKK5, MKKC, | ||
366 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
367 | PSCAN_MKK3, CTRY_JAPAN15}, | ||
368 | |||
369 | {MKK6_MKKB, MKK6, MKKA, | ||
370 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
371 | PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16}, | ||
372 | {MKK6_MKKA1, MKK6, MKKA, | ||
373 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
374 | PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN30}, | ||
375 | {MKK6_MKKA2, MKK6, MKKA, | ||
376 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
377 | PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17}, | ||
378 | {MKK6_MKKC, MKK6, MKKC, | ||
379 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
380 | PSCAN_MKK1, CTRY_JAPAN18}, | ||
381 | {MKK6_FCCA, MKK6, FCCA, | ||
382 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
383 | NO_PSCAN, CTRY_JAPAN31}, | ||
384 | |||
385 | {MKK7_MKKB, MKK7, MKKA, | ||
386 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
387 | PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, | ||
388 | CTRY_JAPAN19}, | ||
389 | {MKK7_MKKA1, MKK7, MKKA, | ||
390 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
391 | PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN32}, | ||
392 | {MKK7_MKKA2, MKK7, MKKA, | ||
393 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
394 | PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, | ||
395 | CTRY_JAPAN20}, | ||
396 | {MKK7_MKKC, MKK7, MKKC, | ||
397 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
398 | PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21}, | ||
399 | {MKK7_FCCA, MKK7, FCCA, | ||
400 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
401 | PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN33}, | ||
402 | |||
403 | {MKK8_MKKB, MKK8, MKKA, | ||
404 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
405 | PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, | ||
406 | CTRY_JAPAN22}, | ||
407 | {MKK8_MKKA2, MKK8, MKKA, | ||
408 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
409 | PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, | ||
410 | CTRY_JAPAN23}, | ||
411 | {MKK8_MKKC, MKK8, MKKC, | ||
412 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
413 | PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN24}, | ||
414 | |||
415 | {MKK9_MKKA, MKK9, MKKA, | ||
416 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | | ||
417 | LIMIT_FRAME_4MS, NEED_NFC, | ||
418 | PSCAN_MKK2 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, | ||
419 | CTRY_JAPAN34}, | ||
420 | {MKK9_FCCA, MKK9, FCCA, | ||
421 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
422 | NO_PSCAN, CTRY_JAPAN37}, | ||
423 | {MKK9_MKKA1, MKK9, MKKA, | ||
424 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
425 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN38}, | ||
426 | {MKK9_MKKA2, MKK9, MKKA, | ||
427 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
428 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN40}, | ||
429 | {MKK9_MKKC, MKK9, MKKC, | ||
430 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
431 | NO_PSCAN, CTRY_JAPAN39}, | ||
432 | |||
433 | {MKK10_MKKA, MKK10, MKKA, | ||
434 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | | ||
435 | LIMIT_FRAME_4MS, NEED_NFC, PSCAN_MKK2 | PSCAN_MKK3, CTRY_JAPAN35}, | ||
436 | {MKK10_FCCA, MKK10, FCCA, | ||
437 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
438 | NO_PSCAN, CTRY_JAPAN41}, | ||
439 | {MKK10_MKKA1, MKK10, MKKA, | ||
440 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
441 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN42}, | ||
442 | {MKK10_MKKA2, MKK10, MKKA, | ||
443 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
444 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN44}, | ||
445 | {MKK10_MKKC, MKK10, MKKC, | ||
446 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
447 | NO_PSCAN, CTRY_JAPAN43}, | ||
448 | |||
449 | {MKK11_MKKA, MKK11, MKKA, | ||
450 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
451 | PSCAN_MKK3, CTRY_JAPAN45}, | ||
452 | {MKK11_FCCA, MKK11, FCCA, | ||
453 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
454 | PSCAN_MKK3, CTRY_JAPAN46}, | ||
455 | {MKK11_MKKA1, MKK11, MKKA, | ||
456 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
457 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN47}, | ||
458 | {MKK11_MKKA2, MKK11, MKKA, | ||
459 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
460 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN49}, | ||
461 | {MKK11_MKKC, MKK11, MKKC, | ||
462 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
463 | PSCAN_MKK3, CTRY_JAPAN48}, | ||
464 | |||
465 | {MKK12_MKKA, MKK12, MKKA, | ||
466 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
467 | PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN50}, | ||
468 | {MKK12_FCCA, MKK12, FCCA, | ||
469 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
470 | PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN51}, | ||
471 | {MKK12_MKKA1, MKK12, MKKA, | ||
472 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
473 | PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, | ||
474 | CTRY_JAPAN52}, | ||
475 | {MKK12_MKKA2, MKK12, MKKA, | ||
476 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
477 | PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, | ||
478 | CTRY_JAPAN54}, | ||
479 | {MKK12_MKKC, MKK12, MKKC, | ||
480 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
481 | PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN53}, | ||
482 | |||
483 | {MKK13_MKKB, MKK13, MKKA, | ||
484 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC | | ||
485 | LIMIT_FRAME_4MS, NEED_NFC, | ||
486 | PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, | ||
487 | CTRY_JAPAN57}, | ||
488 | |||
489 | {MKK14_MKKA1, MKK14, MKKA, | ||
490 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
491 | PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN58}, | ||
492 | {MKK15_MKKA1, MKK15, MKKA, | ||
493 | DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS, NEED_NFC, | ||
494 | PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN59}, | ||
495 | |||
496 | {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, | ||
497 | 0}, | ||
498 | {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD, | ||
499 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
500 | 0}, | ||
501 | {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB, | ||
502 | NO_REQ, PSCAN_DEFER, 0}, | ||
503 | {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, | ||
504 | 0}, | ||
505 | {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD, | ||
506 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
507 | 0}, | ||
508 | {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC, | ||
509 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
510 | 0}, | ||
511 | {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ, | ||
512 | PSCAN_DEFER, 0}, | ||
513 | {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ, | ||
514 | PSCAN_DEFER, 0}, | ||
515 | {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0}, | ||
516 | {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, | ||
517 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
518 | 0}, | ||
519 | {WORA_WORLD, WORA_WORLD, WORA_WORLD, | ||
520 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
521 | 0}, | ||
522 | {WORB_WORLD, WORB_WORLD, WORB_WORLD, | ||
523 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, | ||
524 | 0}, | ||
525 | }; | ||
526 | |||
527 | #define NO_INTERSECT_REQ 0xFFFFFFFF | ||
528 | #define NO_UNION_REQ 0 | ||
529 | |||
530 | static struct country_code_to_enum_rd allCountries[] = { | ||
531 | {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG", YES, YES, YES, YES, YES, | ||
532 | YES, YES, 7000}, | ||
533 | {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET", YES, YES, YES, | ||
534 | YES, YES, YES, YES, 7000}, | ||
535 | {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA", YES, NO, YES, YES, NO, | ||
536 | NO, NO, 7000}, | ||
537 | {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA", YES, NO, YES, YES, NO, | ||
538 | NO, NO, 7000}, | ||
539 | {CTRY_ARGENTINA, APL3_WORLD, "AR", "ARGENTINA", YES, NO, NO, YES, | ||
540 | NO, YES, NO, 7000}, | ||
541 | {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA", YES, NO, YES, YES, | ||
542 | YES, NO, NO, 7000}, | ||
543 | {CTRY_AUSTRALIA, FCC2_WORLD, "AU", "AUSTRALIA", YES, YES, YES, YES, | ||
544 | YES, YES, YES, 7000}, | ||
545 | {CTRY_AUSTRALIA2, FCC6_WORLD, "AU", "AUSTRALIA2", YES, YES, YES, | ||
546 | YES, YES, YES, YES, 7000}, | ||
547 | {CTRY_AUSTRIA, ETSI1_WORLD, "AT", "AUSTRIA", YES, NO, YES, YES, | ||
548 | YES, YES, YES, 7000}, | ||
549 | {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN", YES, YES, YES, | ||
550 | YES, YES, YES, YES, 7000}, | ||
551 | {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN", YES, NO, YES, YES, YES, | ||
552 | YES, NO, 7000}, | ||
553 | {CTRY_BELARUS, ETSI1_WORLD, "BY", "BELARUS", YES, NO, YES, YES, | ||
554 | YES, YES, YES, 7000}, | ||
555 | {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM", YES, NO, YES, YES, | ||
556 | YES, YES, YES, 7000}, | ||
557 | {CTRY_BELGIUM2, ETSI4_WORLD, "BL", "BELGIUM", YES, NO, YES, YES, | ||
558 | YES, YES, YES, 7000}, | ||
559 | {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE", YES, YES, YES, YES, YES, | ||
560 | YES, YES, 7000}, | ||
561 | {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLVIA", YES, YES, YES, YES, YES, | ||
562 | YES, YES, 7000}, | ||
563 | {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA", "BOSNIA_HERZGOWINA", YES, NO, | ||
564 | YES, YES, YES, YES, NO, 7000}, | ||
565 | {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL", YES, NO, NO, YES, NO, | ||
566 | YES, NO, 7000}, | ||
567 | {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN", "BRUNEI DARUSSALAM", | ||
568 | YES, YES, YES, YES, YES, YES, YES, 7000}, | ||
569 | {CTRY_BULGARIA, ETSI6_WORLD, "BG", "BULGARIA", YES, NO, YES, YES, | ||
570 | YES, YES, YES, 7000}, | ||
571 | {CTRY_CANADA, FCC2_FCCA, "CA", "CANADA", YES, YES, YES, YES, YES, | ||
572 | YES, YES, 7000}, | ||
573 | {CTRY_CANADA2, FCC6_FCCA, "CA", "CANADA2", YES, YES, YES, YES, YES, | ||
574 | YES, YES, 7000}, | ||
575 | {CTRY_CHILE, APL6_WORLD, "CL", "CHILE", YES, YES, YES, YES, YES, | ||
576 | YES, YES, 7000}, | ||
577 | {CTRY_CHINA, APL1_WORLD, "CN", "CHINA", YES, YES, YES, YES, YES, | ||
578 | YES, YES, 7000}, | ||
579 | {CTRY_COLOMBIA, FCC1_FCCA, "CO", "COLOMBIA", YES, NO, YES, YES, | ||
580 | YES, YES, NO, 7000}, | ||
581 | {CTRY_COSTA_RICA, FCC1_WORLD, "CR", "COSTA RICA", YES, NO, YES, | ||
582 | YES, YES, YES, NO, 7000}, | ||
583 | {CTRY_CROATIA, ETSI3_WORLD, "HR", "CROATIA", YES, NO, YES, YES, | ||
584 | YES, YES, NO, 7000}, | ||
585 | {CTRY_CYPRUS, ETSI1_WORLD, "CY", "CYPRUS", YES, YES, YES, YES, YES, | ||
586 | YES, YES, 7000}, | ||
587 | {CTRY_CZECH, ETSI3_WORLD, "CZ", "CZECH REPUBLIC", YES, NO, YES, | ||
588 | YES, YES, YES, YES, 7000}, | ||
589 | {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK", YES, NO, YES, YES, | ||
590 | YES, YES, YES, 7000}, | ||
591 | {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO", "DOMINICAN REPUBLIC", | ||
592 | YES, YES, YES, YES, YES, YES, YES, 7000}, | ||
593 | {CTRY_ECUADOR, FCC1_WORLD, "EC", "ECUADOR", YES, NO, NO, YES, YES, | ||
594 | YES, NO, 7000}, | ||
595 | {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT", YES, NO, YES, YES, YES, | ||
596 | YES, NO, 7000}, | ||
597 | {CTRY_EL_SALVADOR, FCC1_WORLD, "SV", "EL SALVADOR", YES, NO, YES, | ||
598 | YES, YES, YES, NO, 7000}, | ||
599 | {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA", YES, NO, YES, YES, | ||
600 | YES, YES, YES, 7000}, | ||
601 | {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND", YES, NO, YES, YES, | ||
602 | YES, YES, YES, 7000}, | ||
603 | {CTRY_FRANCE, ETSI1_WORLD, "FR", "FRANCE", YES, NO, YES, YES, YES, | ||
604 | YES, YES, 7000}, | ||
605 | {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA", YES, YES, YES, YES, | ||
606 | YES, YES, YES, 7000}, | ||
607 | {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY", YES, NO, YES, YES, | ||
608 | YES, YES, YES, 7000}, | ||
609 | {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE", YES, NO, YES, YES, YES, | ||
610 | YES, YES, 7000}, | ||
611 | {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA", YES, YES, YES, YES, | ||
612 | YES, YES, YES, 7000}, | ||
613 | {CTRY_HONDURAS, NULL1_WORLD, "HN", "HONDURAS", YES, NO, YES, YES, | ||
614 | YES, NO, NO, 7000}, | ||
615 | {CTRY_HONG_KONG, FCC2_WORLD, "HK", "HONG KONG", YES, YES, YES, YES, | ||
616 | YES, YES, YES, 7000}, | ||
617 | {CTRY_HUNGARY, ETSI1_WORLD, "HU", "HUNGARY", YES, NO, YES, YES, | ||
618 | YES, YES, YES, 7000}, | ||
619 | {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND", YES, NO, YES, YES, | ||
620 | YES, YES, YES, 7000}, | ||
621 | {CTRY_INDIA, APL6_WORLD, "IN", "INDIA", YES, NO, YES, YES, YES, | ||
622 | YES, NO, 7000}, | ||
623 | {CTRY_INDONESIA, APL1_WORLD, "ID", "INDONESIA", YES, NO, YES, YES, | ||
624 | YES, YES, NO, 7000}, | ||
625 | {CTRY_IRAN, APL1_WORLD, "IR", "IRAN", YES, YES, YES, YES, YES, YES, | ||
626 | YES, 7000}, | ||
627 | {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND", YES, NO, YES, YES, | ||
628 | YES, YES, YES, 7000}, | ||
629 | {CTRY_ISRAEL, NULL1_WORLD, "IL", "ISRAEL", YES, NO, YES, YES, YES, | ||
630 | NO, NO, 7000}, | ||
631 | {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY", YES, NO, YES, YES, YES, | ||
632 | YES, YES, 7000}, | ||
633 | {CTRY_JAMAICA, ETSI1_WORLD, "JM", "JAMAICA", YES, NO, YES, YES, | ||
634 | YES, YES, YES, 7000}, | ||
635 | |||
636 | {CTRY_JAPAN, MKK1_MKKA, "JP", "JAPAN", YES, NO, NO, YES, YES, YES, | ||
637 | YES, 7000}, | ||
638 | {CTRY_JAPAN1, MKK1_MKKB, "JP", "JAPAN1", YES, NO, NO, YES, YES, | ||
639 | YES, YES, 7000}, | ||
640 | {CTRY_JAPAN2, MKK1_FCCA, "JP", "JAPAN2", YES, NO, NO, YES, YES, | ||
641 | YES, YES, 7000}, | ||
642 | {CTRY_JAPAN3, MKK2_MKKA, "JP", "JAPAN3", YES, NO, NO, YES, YES, | ||
643 | YES, YES, 7000}, | ||
644 | {CTRY_JAPAN4, MKK1_MKKA1, "JP", "JAPAN4", YES, NO, NO, YES, YES, | ||
645 | YES, YES, 7000}, | ||
646 | {CTRY_JAPAN5, MKK1_MKKA2, "JP", "JAPAN5", YES, NO, NO, YES, YES, | ||
647 | YES, YES, 7000}, | ||
648 | {CTRY_JAPAN6, MKK1_MKKC, "JP", "JAPAN6", YES, NO, NO, YES, YES, | ||
649 | YES, YES, 7000}, | ||
650 | |||
651 | {CTRY_JAPAN7, MKK3_MKKB, "JP", "JAPAN7", YES, NO, NO, YES, YES, | ||
652 | YES, YES, 7000}, | ||
653 | {CTRY_JAPAN8, MKK3_MKKA2, "JP", "JAPAN8", YES, NO, NO, YES, YES, | ||
654 | YES, YES, 7000}, | ||
655 | {CTRY_JAPAN9, MKK3_MKKC, "JP", "JAPAN9", YES, NO, NO, YES, YES, | ||
656 | YES, YES, 7000}, | ||
657 | |||
658 | {CTRY_JAPAN10, MKK4_MKKB, "JP", "JAPAN10", YES, NO, NO, YES, YES, | ||
659 | YES, YES, 7000}, | ||
660 | {CTRY_JAPAN11, MKK4_MKKA2, "JP", "JAPAN11", YES, NO, NO, YES, YES, | ||
661 | YES, YES, 7000}, | ||
662 | {CTRY_JAPAN12, MKK4_MKKC, "JP", "JAPAN12", YES, NO, NO, YES, YES, | ||
663 | YES, YES, 7000}, | ||
664 | |||
665 | {CTRY_JAPAN13, MKK5_MKKB, "JP", "JAPAN13", YES, NO, NO, YES, YES, | ||
666 | YES, YES, 7000}, | ||
667 | {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN14", YES, NO, NO, YES, YES, | ||
668 | YES, YES, 7000}, | ||
669 | {CTRY_JAPAN15, MKK5_MKKC, "JP", "JAPAN15", YES, NO, NO, YES, YES, | ||
670 | YES, YES, 7000}, | ||
671 | |||
672 | {CTRY_JAPAN16, MKK6_MKKB, "JP", "JAPAN16", YES, NO, NO, YES, YES, | ||
673 | YES, YES, 7000}, | ||
674 | {CTRY_JAPAN17, MKK6_MKKA2, "JP", "JAPAN17", YES, NO, NO, YES, YES, | ||
675 | YES, YES, 7000}, | ||
676 | {CTRY_JAPAN18, MKK6_MKKC, "JP", "JAPAN18", YES, NO, NO, YES, YES, | ||
677 | YES, YES, 7000}, | ||
678 | |||
679 | {CTRY_JAPAN19, MKK7_MKKB, "JP", "JAPAN19", YES, NO, NO, YES, YES, | ||
680 | YES, YES, 7000}, | ||
681 | {CTRY_JAPAN20, MKK7_MKKA2, "JP", "JAPAN20", YES, NO, NO, YES, YES, | ||
682 | YES, YES, 7000}, | ||
683 | {CTRY_JAPAN21, MKK7_MKKC, "JP", "JAPAN21", YES, NO, NO, YES, YES, | ||
684 | YES, YES, 7000}, | ||
685 | |||
686 | {CTRY_JAPAN22, MKK8_MKKB, "JP", "JAPAN22", YES, NO, NO, YES, YES, | ||
687 | YES, YES, 7000}, | ||
688 | {CTRY_JAPAN23, MKK8_MKKA2, "JP", "JAPAN23", YES, NO, NO, YES, YES, | ||
689 | YES, YES, 7000}, | ||
690 | {CTRY_JAPAN24, MKK8_MKKC, "JP", "JAPAN24", YES, NO, NO, YES, YES, | ||
691 | YES, YES, 7000}, | ||
692 | |||
693 | {CTRY_JAPAN25, MKK3_MKKA, "JP", "JAPAN25", YES, NO, NO, YES, YES, | ||
694 | YES, YES, 7000}, | ||
695 | {CTRY_JAPAN26, MKK3_MKKA1, "JP", "JAPAN26", YES, NO, NO, YES, YES, | ||
696 | YES, YES, 7000}, | ||
697 | {CTRY_JAPAN27, MKK3_FCCA, "JP", "JAPAN27", YES, NO, NO, YES, YES, | ||
698 | YES, YES, 7000}, | ||
699 | {CTRY_JAPAN28, MKK4_MKKA1, "JP", "JAPAN28", YES, NO, NO, YES, YES, | ||
700 | YES, YES, 7000}, | ||
701 | {CTRY_JAPAN29, MKK4_FCCA, "JP", "JAPAN29", YES, NO, NO, YES, YES, | ||
702 | YES, YES, 7000}, | ||
703 | {CTRY_JAPAN30, MKK6_MKKA1, "JP", "JAPAN30", YES, NO, NO, YES, YES, | ||
704 | YES, YES, 7000}, | ||
705 | {CTRY_JAPAN31, MKK6_FCCA, "JP", "JAPAN31", YES, NO, NO, YES, YES, | ||
706 | YES, YES, 7000}, | ||
707 | {CTRY_JAPAN32, MKK7_MKKA1, "JP", "JAPAN32", YES, NO, NO, YES, YES, | ||
708 | YES, YES, 7000}, | ||
709 | {CTRY_JAPAN33, MKK7_FCCA, "JP", "JAPAN33", YES, NO, NO, YES, YES, | ||
710 | YES, YES, 7000}, | ||
711 | {CTRY_JAPAN34, MKK9_MKKA, "JP", "JAPAN34", YES, NO, NO, YES, YES, | ||
712 | YES, YES, 7000}, | ||
713 | {CTRY_JAPAN35, MKK10_MKKA, "JP", "JAPAN35", YES, NO, NO, YES, YES, | ||
714 | YES, YES, 7000}, | ||
715 | {CTRY_JAPAN36, MKK4_MKKA, "JP", "JAPAN36", YES, NO, NO, YES, YES, | ||
716 | YES, YES, 7000}, | ||
717 | {CTRY_JAPAN37, MKK9_FCCA, "JP", "JAPAN37", YES, NO, NO, YES, YES, | ||
718 | YES, YES, 7000}, | ||
719 | {CTRY_JAPAN38, MKK9_MKKA1, "JP", "JAPAN38", YES, NO, NO, YES, YES, | ||
720 | YES, YES, 7000}, | ||
721 | {CTRY_JAPAN39, MKK9_MKKC, "JP", "JAPAN39", YES, NO, NO, YES, YES, | ||
722 | YES, YES, 7000}, | ||
723 | {CTRY_JAPAN40, MKK9_MKKA2, "JP", "JAPAN40", YES, NO, NO, YES, YES, | ||
724 | YES, YES, 7000}, | ||
725 | {CTRY_JAPAN41, MKK10_FCCA, "JP", "JAPAN41", YES, NO, NO, YES, YES, | ||
726 | YES, YES, 7000}, | ||
727 | {CTRY_JAPAN42, MKK10_MKKA1, "JP", "JAPAN42", YES, NO, NO, YES, YES, | ||
728 | YES, YES, 7000}, | ||
729 | {CTRY_JAPAN43, MKK10_MKKC, "JP", "JAPAN43", YES, NO, NO, YES, YES, | ||
730 | YES, YES, 7000}, | ||
731 | {CTRY_JAPAN44, MKK10_MKKA2, "JP", "JAPAN44", YES, NO, NO, YES, YES, | ||
732 | YES, YES, 7000}, | ||
733 | {CTRY_JAPAN45, MKK11_MKKA, "JP", "JAPAN45", YES, NO, NO, YES, YES, | ||
734 | YES, YES, 7000}, | ||
735 | {CTRY_JAPAN46, MKK11_FCCA, "JP", "JAPAN46", YES, NO, NO, YES, YES, | ||
736 | YES, YES, 7000}, | ||
737 | {CTRY_JAPAN47, MKK11_MKKA1, "JP", "JAPAN47", YES, NO, NO, YES, YES, | ||
738 | YES, YES, 7000}, | ||
739 | {CTRY_JAPAN48, MKK11_MKKC, "JP", "JAPAN48", YES, NO, NO, YES, YES, | ||
740 | YES, YES, 7000}, | ||
741 | {CTRY_JAPAN49, MKK11_MKKA2, "JP", "JAPAN49", YES, NO, NO, YES, YES, | ||
742 | YES, YES, 7000}, | ||
743 | {CTRY_JAPAN50, MKK12_MKKA, "JP", "JAPAN50", YES, NO, NO, YES, YES, | ||
744 | YES, YES, 7000}, | ||
745 | {CTRY_JAPAN51, MKK12_FCCA, "JP", "JAPAN51", YES, NO, NO, YES, YES, | ||
746 | YES, YES, 7000}, | ||
747 | {CTRY_JAPAN52, MKK12_MKKA1, "JP", "JAPAN52", YES, NO, NO, YES, YES, | ||
748 | YES, YES, 7000}, | ||
749 | {CTRY_JAPAN53, MKK12_MKKC, "JP", "JAPAN53", YES, NO, NO, YES, YES, | ||
750 | YES, YES, 7000}, | ||
751 | {CTRY_JAPAN54, MKK12_MKKA2, "JP", "JAPAN54", YES, NO, NO, YES, YES, | ||
752 | YES, YES, 7000}, | ||
753 | |||
754 | {CTRY_JAPAN57, MKK13_MKKB, "JP", "JAPAN57", YES, NO, NO, YES, YES, | ||
755 | YES, YES, 7000}, | ||
756 | {CTRY_JAPAN58, MKK14_MKKA1, "JP", "JAPAN58", YES, NO, NO, YES, YES, | ||
757 | YES, YES, 7000}, | ||
758 | {CTRY_JAPAN59, MKK15_MKKA1, "JP", "JAPAN59", YES, NO, NO, YES, YES, | ||
759 | YES, YES, 7000}, | ||
760 | |||
761 | {CTRY_JORDAN, ETSI2_WORLD, "JO", "JORDAN", YES, NO, YES, YES, YES, | ||
762 | YES, NO, 7000}, | ||
763 | {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN", YES, NO, YES, | ||
764 | YES, YES, NO, NO, 7000}, | ||
765 | {CTRY_KOREA_NORTH, APL9_WORLD, "KP", "NORTH KOREA", YES, NO, NO, | ||
766 | YES, YES, YES, YES, 7000}, | ||
767 | {CTRY_KOREA_ROC, APL9_WORLD, "KR", "KOREA REPUBLIC", YES, NO, NO, | ||
768 | YES, NO, YES, NO, 7000}, | ||
769 | {CTRY_KOREA_ROC2, APL2_WORLD, "K2", "KOREA REPUBLIC2", YES, NO, NO, | ||
770 | YES, NO, YES, NO, 7000}, | ||
771 | {CTRY_KOREA_ROC3, APL9_WORLD, "K3", "KOREA REPUBLIC3", YES, NO, NO, | ||
772 | YES, NO, YES, NO, 7000}, | ||
773 | {CTRY_KUWAIT, NULL1_WORLD, "KW", "KUWAIT", YES, NO, YES, YES, YES, | ||
774 | NO, NO, 7000}, | ||
775 | {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA", YES, NO, YES, YES, YES, | ||
776 | YES, YES, 7000}, | ||
777 | {CTRY_LEBANON, NULL1_WORLD, "LB", "LEBANON", YES, NO, YES, YES, | ||
778 | YES, NO, NO, 7000}, | ||
779 | {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI", "LIECHTENSTEIN", YES, NO, | ||
780 | YES, YES, YES, YES, YES, 7000}, | ||
781 | {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA", YES, NO, YES, YES, | ||
782 | YES, YES, YES, 7000}, | ||
783 | {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG", YES, NO, YES, | ||
784 | YES, YES, YES, YES, 7000}, | ||
785 | {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU", YES, YES, YES, YES, YES, | ||
786 | YES, YES, 7000}, | ||
787 | {CTRY_MACEDONIA, NULL1_WORLD, "MK", "MACEDONIA", YES, NO, YES, YES, | ||
788 | YES, NO, NO, 7000}, | ||
789 | {CTRY_MALAYSIA, APL8_WORLD, "MY", "MALAYSIA", YES, NO, NO, YES, NO, | ||
790 | YES, NO, 7000}, | ||
791 | {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA", YES, NO, YES, YES, YES, | ||
792 | YES, YES, 7000}, | ||
793 | {CTRY_MEXICO, FCC1_FCCA, "MX", "MEXICO", YES, YES, YES, YES, YES, | ||
794 | YES, YES, 7000}, | ||
795 | {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO", YES, YES, YES, YES, YES, | ||
796 | YES, YES, 7000}, | ||
797 | {CTRY_MOROCCO, NULL1_WORLD, "MA", "MOROCCO", YES, NO, YES, YES, | ||
798 | YES, NO, NO, 7000}, | ||
799 | {CTRY_NEPAL, APL1_WORLD, "NP", "NEPAL", YES, NO, YES, YES, YES, | ||
800 | YES, YES, 7000}, | ||
801 | {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS", YES, NO, YES, | ||
802 | YES, YES, YES, YES, 7000}, | ||
803 | {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN", | ||
804 | "NETHERLANDS-ANTILLES", YES, NO, YES, YES, YES, YES, YES, 7000}, | ||
805 | {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ", "NEW ZEALAND", YES, NO, YES, | ||
806 | YES, YES, YES, NO, 7000}, | ||
807 | {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY", YES, NO, YES, YES, YES, | ||
808 | YES, YES, 7000}, | ||
809 | {CTRY_OMAN, APL6_WORLD, "OM", "OMAN", YES, NO, YES, YES, YES, YES, | ||
810 | NO, 7000}, | ||
811 | {CTRY_PAKISTAN, NULL1_WORLD, "PK", "PAKISTAN", YES, NO, YES, YES, | ||
812 | YES, NO, NO, 7000}, | ||
813 | {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA", YES, YES, YES, YES, YES, | ||
814 | YES, YES, 7000}, | ||
815 | {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG", "PAPUA NEW GUINEA", YES, | ||
816 | YES, YES, YES, YES, YES, YES, 7000}, | ||
817 | {CTRY_PERU, APL1_WORLD, "PE", "PERU", YES, NO, YES, YES, YES, YES, | ||
818 | NO, 7000}, | ||
819 | {CTRY_PHILIPPINES, APL1_WORLD, "PH", "PHILIPPINES", YES, YES, YES, | ||
820 | YES, YES, YES, YES, 7000}, | ||
821 | {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND", YES, NO, YES, YES, YES, | ||
822 | YES, YES, 7000}, | ||
823 | {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL", YES, NO, YES, YES, | ||
824 | YES, YES, YES, 7000}, | ||
825 | {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO", YES, YES, YES, | ||
826 | YES, YES, YES, YES, 7000}, | ||
827 | {CTRY_QATAR, NULL1_WORLD, "QA", "QATAR", YES, NO, YES, YES, YES, | ||
828 | NO, NO, 7000}, | ||
829 | {CTRY_ROMANIA, NULL1_WORLD, "RO", "ROMANIA", YES, NO, YES, YES, | ||
830 | YES, NO, NO, 7000}, | ||
831 | {CTRY_RUSSIA, NULL1_WORLD, "RU", "RUSSIA", YES, NO, YES, YES, YES, | ||
832 | NO, NO, 7000}, | ||
833 | {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA", "SAUDI ARABIA", YES, NO, | ||
834 | YES, YES, YES, NO, NO, 7000}, | ||
835 | {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS", "SERBIA & MONTENEGRO", | ||
836 | YES, NO, YES, YES, YES, YES, YES, 7000}, | ||
837 | {CTRY_SINGAPORE, APL6_WORLD, "SG", "SINGAPORE", YES, YES, YES, YES, | ||
838 | YES, YES, YES, 7000}, | ||
839 | {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAK REPUBLIC", YES, NO, YES, | ||
840 | YES, YES, YES, YES, 7000}, | ||
841 | {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA", YES, NO, YES, YES, | ||
842 | YES, YES, YES, 7000}, | ||
843 | {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA", "SOUTH AFRICA", YES, NO, YES, | ||
844 | YES, YES, YES, NO, 7000}, | ||
845 | {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN", YES, NO, YES, YES, YES, | ||
846 | YES, YES, 7000}, | ||
847 | {CTRY_SRI_LANKA, FCC3_WORLD, "LK", "SRI LANKA", YES, NO, YES, YES, | ||
848 | YES, YES, NO, 7000}, | ||
849 | {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN", YES, NO, YES, YES, YES, | ||
850 | YES, YES, 7000}, | ||
851 | {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND", YES, NO, YES, | ||
852 | YES, YES, YES, YES, 7000}, | ||
853 | {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIA", YES, NO, YES, YES, YES, | ||
854 | NO, NO, 7000}, | ||
855 | {CTRY_TAIWAN, APL3_FCCA, "TW", "TAIWAN", YES, YES, YES, YES, YES, | ||
856 | YES, YES, 7000}, | ||
857 | {CTRY_THAILAND, NULL1_WORLD, "TH", "THAILAND", YES, NO, YES, YES, | ||
858 | YES, NO, NO, 7000}, | ||
859 | {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT", "TRINIDAD & TOBAGO", | ||
860 | YES, NO, YES, YES, YES, YES, NO, 7000}, | ||
861 | {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA", YES, NO, YES, YES, | ||
862 | YES, YES, NO, 7000}, | ||
863 | {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY", YES, NO, YES, YES, YES, | ||
864 | YES, NO, 7000}, | ||
865 | {CTRY_UKRAINE, NULL1_WORLD, "UA", "UKRAINE", YES, NO, YES, YES, | ||
866 | YES, NO, NO, 7000}, | ||
867 | {CTRY_UAE, NULL1_WORLD, "AE", "UNITED ARAB EMIRATES", YES, NO, YES, | ||
868 | YES, YES, NO, NO, 7000}, | ||
869 | {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB", "UNITED KINGDOM", YES, NO, | ||
870 | YES, YES, YES, YES, YES, 7000}, | ||
871 | {CTRY_UNITED_STATES, FCC3_FCCA, "US", "UNITED STATES", YES, YES, | ||
872 | YES, YES, YES, YES, YES, 5825}, | ||
873 | {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS", | ||
874 | "UNITED STATES (PUBLIC SAFETY)", YES, YES, YES, YES, YES, YES, | ||
875 | YES, 7000}, | ||
876 | {CTRY_URUGUAY, APL2_WORLD, "UY", "URUGUAY", YES, NO, YES, YES, YES, | ||
877 | YES, NO, 7000}, | ||
878 | {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN", YES, YES, YES, | ||
879 | YES, YES, YES, YES, 7000}, | ||
880 | {CTRY_VENEZUELA, APL2_ETSIC, "VE", "VENEZUELA", YES, NO, YES, YES, | ||
881 | YES, YES, NO, 7000}, | ||
882 | {CTRY_VIET_NAM, NULL1_WORLD, "VN", "VIET NAM", YES, NO, YES, YES, | ||
883 | YES, NO, NO, 7000}, | ||
884 | {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN", YES, NO, YES, YES, YES, | ||
885 | NO, NO, 7000}, | ||
886 | {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, YES, | ||
887 | YES, NO, NO, 7000} | ||
888 | }; | ||
889 | |||
890 | enum { | ||
891 | NO_DFS = 0x0000000000000000ULL, | ||
892 | DFS_FCC3 = 0x0000000000000001ULL, | ||
893 | DFS_ETSI = 0x0000000000000002ULL, | ||
894 | DFS_MKK4 = 0x0000000000000004ULL, | ||
895 | }; | ||
896 | |||
897 | enum { | ||
898 | F1_4915_4925, | ||
899 | F1_4935_4945, | ||
900 | F1_4920_4980, | ||
901 | F1_4942_4987, | ||
902 | F1_4945_4985, | ||
903 | F1_4950_4980, | ||
904 | F1_5035_5040, | ||
905 | F1_5040_5080, | ||
906 | F1_5055_5055, | ||
907 | |||
908 | F1_5120_5240, | ||
909 | |||
910 | F1_5170_5230, | ||
911 | F2_5170_5230, | ||
912 | |||
913 | F1_5180_5240, | ||
914 | F2_5180_5240, | ||
915 | F3_5180_5240, | ||
916 | F4_5180_5240, | ||
917 | F5_5180_5240, | ||
918 | F6_5180_5240, | ||
919 | F7_5180_5240, | ||
920 | F8_5180_5240, | ||
921 | |||
922 | F1_5180_5320, | ||
923 | |||
924 | F1_5240_5280, | ||
925 | |||
926 | F1_5260_5280, | ||
927 | |||
928 | F1_5260_5320, | ||
929 | F2_5260_5320, | ||
930 | F3_5260_5320, | ||
931 | F4_5260_5320, | ||
932 | F5_5260_5320, | ||
933 | F6_5260_5320, | ||
934 | |||
935 | F1_5260_5700, | ||
936 | |||
937 | F1_5280_5320, | ||
938 | |||
939 | F1_5500_5580, | ||
940 | |||
941 | F1_5500_5620, | ||
942 | |||
943 | F1_5500_5700, | ||
944 | F2_5500_5700, | ||
945 | F3_5500_5700, | ||
946 | F4_5500_5700, | ||
947 | F5_5500_5700, | ||
948 | |||
949 | F1_5660_5700, | ||
950 | |||
951 | F1_5745_5805, | ||
952 | F2_5745_5805, | ||
953 | F3_5745_5805, | ||
954 | |||
955 | F1_5745_5825, | ||
956 | F2_5745_5825, | ||
957 | F3_5745_5825, | ||
958 | F4_5745_5825, | ||
959 | F5_5745_5825, | ||
960 | F6_5745_5825, | ||
961 | |||
962 | W1_4920_4980, | ||
963 | W1_5040_5080, | ||
964 | W1_5170_5230, | ||
965 | W1_5180_5240, | ||
966 | W1_5260_5320, | ||
967 | W1_5745_5825, | ||
968 | W1_5500_5700, | ||
969 | A_DEMO_ALL_CHANNELS | ||
970 | }; | ||
971 | |||
972 | static struct RegDmnFreqBand regDmn5GhzFreq[] = { | ||
973 | {4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16}, | ||
974 | {4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16}, | ||
975 | {4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7}, | ||
976 | {4942, 4987, 27, 6, 5, 5, NO_DFS, PSCAN_FCC, 0}, | ||
977 | {4945, 4985, 30, 6, 10, 5, NO_DFS, PSCAN_FCC, 0}, | ||
978 | {4950, 4980, 33, 6, 20, 5, NO_DFS, PSCAN_FCC, 0}, | ||
979 | {5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12}, | ||
980 | {5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2}, | ||
981 | {5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12}, | ||
982 | |||
983 | {5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
984 | |||
985 | {5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1}, | ||
986 | {5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1}, | ||
987 | |||
988 | {5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0}, | ||
989 | {5180, 5240, 17, 6, 20, 20, NO_DFS, NO_PSCAN, 1}, | ||
990 | {5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0}, | ||
991 | {5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0}, | ||
992 | {5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0}, | ||
993 | {5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0}, | ||
994 | {5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK3, 0}, | ||
995 | {5180, 5240, 23, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
996 | |||
997 | {5180, 5320, 20, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0}, | ||
998 | |||
999 | {5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0}, | ||
1000 | |||
1001 | {5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, | ||
1002 | PSCAN_FCC | PSCAN_ETSI, 0}, | ||
1003 | |||
1004 | {5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, | ||
1005 | PSCAN_FCC | PSCAN_ETSI, 0}, | ||
1006 | |||
1007 | {5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, | ||
1008 | PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3, 0}, | ||
1009 | |||
1010 | |||
1011 | {5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, | ||
1012 | PSCAN_FCC | PSCAN_ETSI, 2}, | ||
1013 | {5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2}, | ||
1014 | {5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0}, | ||
1015 | {5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
1016 | |||
1017 | {5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0}, | ||
1018 | |||
1019 | {5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0}, | ||
1020 | |||
1021 | {5500, 5580, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0}, | ||
1022 | |||
1023 | {5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0}, | ||
1024 | |||
1025 | {5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4}, | ||
1026 | {5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, | ||
1027 | PSCAN_FCC | PSCAN_ETSI, 0}, | ||
1028 | {5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, | ||
1029 | PSCAN_FCC | PSCAN_ETSI, 0}, | ||
1030 | {5500, 5700, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, | ||
1031 | PSCAN_MKK3 | PSCAN_FCC, 0}, | ||
1032 | {5500, 5700, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0}, | ||
1033 | |||
1034 | {5660, 5700, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0}, | ||
1035 | |||
1036 | {5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
1037 | {5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
1038 | {5745, 5805, 30, 6, 20, 20, NO_DFS, PSCAN_ETSI, 0}, | ||
1039 | {5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
1040 | {5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
1041 | {5745, 5825, 20, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
1042 | {5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
1043 | {5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3}, | ||
1044 | {5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
1045 | |||
1046 | |||
1047 | {4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, | ||
1048 | {5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, | ||
1049 | {5170, 5230, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, | ||
1050 | {5180, 5240, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, | ||
1051 | {5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, | ||
1052 | {5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0}, | ||
1053 | {5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0}, | ||
1054 | {4920, 6100, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0}, | ||
1055 | }; | ||
1056 | |||
1057 | enum { | ||
1058 | T1_5130_5650, | ||
1059 | T1_5150_5670, | ||
1060 | |||
1061 | T1_5200_5200, | ||
1062 | T2_5200_5200, | ||
1063 | T3_5200_5200, | ||
1064 | T4_5200_5200, | ||
1065 | T5_5200_5200, | ||
1066 | T6_5200_5200, | ||
1067 | T7_5200_5200, | ||
1068 | T8_5200_5200, | ||
1069 | |||
1070 | T1_5200_5280, | ||
1071 | T2_5200_5280, | ||
1072 | T3_5200_5280, | ||
1073 | T4_5200_5280, | ||
1074 | T5_5200_5280, | ||
1075 | T6_5200_5280, | ||
1076 | |||
1077 | T1_5200_5240, | ||
1078 | T1_5210_5210, | ||
1079 | T2_5210_5210, | ||
1080 | T3_5210_5210, | ||
1081 | T4_5210_5210, | ||
1082 | T5_5210_5210, | ||
1083 | T6_5210_5210, | ||
1084 | T7_5210_5210, | ||
1085 | T8_5210_5210, | ||
1086 | T9_5210_5210, | ||
1087 | T10_5210_5210, | ||
1088 | T1_5240_5240, | ||
1089 | |||
1090 | T1_5210_5250, | ||
1091 | T1_5210_5290, | ||
1092 | T2_5210_5290, | ||
1093 | T3_5210_5290, | ||
1094 | |||
1095 | T1_5280_5280, | ||
1096 | T2_5280_5280, | ||
1097 | T1_5290_5290, | ||
1098 | T2_5290_5290, | ||
1099 | T3_5290_5290, | ||
1100 | T1_5250_5290, | ||
1101 | T2_5250_5290, | ||
1102 | T3_5250_5290, | ||
1103 | T4_5250_5290, | ||
1104 | |||
1105 | T1_5540_5660, | ||
1106 | T2_5540_5660, | ||
1107 | T3_5540_5660, | ||
1108 | T1_5760_5800, | ||
1109 | T2_5760_5800, | ||
1110 | T3_5760_5800, | ||
1111 | T4_5760_5800, | ||
1112 | T5_5760_5800, | ||
1113 | T6_5760_5800, | ||
1114 | T7_5760_5800, | ||
1115 | |||
1116 | T1_5765_5805, | ||
1117 | T2_5765_5805, | ||
1118 | T3_5765_5805, | ||
1119 | T4_5765_5805, | ||
1120 | T5_5765_5805, | ||
1121 | T6_5765_5805, | ||
1122 | T7_5765_5805, | ||
1123 | T8_5765_5805, | ||
1124 | T9_5765_5805, | ||
1125 | |||
1126 | WT1_5210_5250, | ||
1127 | WT1_5290_5290, | ||
1128 | WT1_5540_5660, | ||
1129 | WT1_5760_5800, | ||
1130 | }; | ||
1131 | |||
1132 | enum { | ||
1133 | F1_2312_2372, | ||
1134 | F2_2312_2372, | ||
1135 | |||
1136 | F1_2412_2472, | ||
1137 | F2_2412_2472, | ||
1138 | F3_2412_2472, | ||
1139 | |||
1140 | F1_2412_2462, | ||
1141 | F2_2412_2462, | ||
1142 | |||
1143 | F1_2432_2442, | ||
1144 | |||
1145 | F1_2457_2472, | ||
1146 | |||
1147 | F1_2467_2472, | ||
1148 | |||
1149 | F1_2484_2484, | ||
1150 | F2_2484_2484, | ||
1151 | |||
1152 | F1_2512_2732, | ||
1153 | |||
1154 | W1_2312_2372, | ||
1155 | W1_2412_2412, | ||
1156 | W1_2417_2432, | ||
1157 | W1_2437_2442, | ||
1158 | W1_2447_2457, | ||
1159 | W1_2462_2462, | ||
1160 | W1_2467_2467, | ||
1161 | W2_2467_2467, | ||
1162 | W1_2472_2472, | ||
1163 | W2_2472_2472, | ||
1164 | W1_2484_2484, | ||
1165 | W2_2484_2484, | ||
1166 | }; | ||
1167 | |||
1168 | static struct RegDmnFreqBand regDmn2GhzFreq[] = { | ||
1169 | {2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1170 | {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1171 | |||
1172 | {2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1173 | {2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, | ||
1174 | {2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1175 | |||
1176 | {2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1177 | {2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0}, | ||
1178 | |||
1179 | {2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1180 | |||
1181 | {2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1182 | |||
1183 | {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0}, | ||
1184 | |||
1185 | {2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1186 | {2484, 2484, 20, 0, 20, 5, NO_DFS, | ||
1187 | PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0}, | ||
1188 | |||
1189 | {2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1190 | |||
1191 | {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1192 | {2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1193 | {2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1194 | {2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1195 | {2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1196 | {2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1197 | {2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, | ||
1198 | {2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, | ||
1199 | {2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, | ||
1200 | {2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, | ||
1201 | {2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, | ||
1202 | {2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, | ||
1203 | }; | ||
1204 | |||
1205 | enum { | ||
1206 | G1_2312_2372, | ||
1207 | G2_2312_2372, | ||
1208 | |||
1209 | G1_2412_2472, | ||
1210 | G2_2412_2472, | ||
1211 | G3_2412_2472, | ||
1212 | |||
1213 | G1_2412_2462, | ||
1214 | G2_2412_2462, | ||
1215 | |||
1216 | G1_2432_2442, | ||
1217 | |||
1218 | G1_2457_2472, | ||
1219 | |||
1220 | G1_2512_2732, | ||
1221 | |||
1222 | G1_2467_2472, | ||
1223 | |||
1224 | WG1_2312_2372, | ||
1225 | WG1_2412_2462, | ||
1226 | WG1_2467_2472, | ||
1227 | WG2_2467_2472, | ||
1228 | G_DEMO_ALL_CHANNELS | ||
1229 | }; | ||
1230 | |||
1231 | static struct RegDmnFreqBand regDmn2Ghz11gFreq[] = { | ||
1232 | {2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1233 | {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1234 | |||
1235 | {2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1236 | {2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, | ||
1237 | {2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1238 | |||
1239 | {2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1240 | {2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0}, | ||
1241 | |||
1242 | {2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1243 | |||
1244 | {2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1245 | |||
1246 | {2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1247 | |||
1248 | {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0}, | ||
1249 | |||
1250 | {2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1251 | {2412, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1252 | {2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0}, | ||
1253 | {2467, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0}, | ||
1254 | {2312, 2732, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0}, | ||
1255 | }; | ||
1256 | |||
1257 | enum { | ||
1258 | T1_2312_2372, | ||
1259 | T1_2437_2437, | ||
1260 | T2_2437_2437, | ||
1261 | T3_2437_2437, | ||
1262 | T1_2512_2732 | ||
1263 | }; | ||
1264 | |||
1265 | static struct regDomain regDomains[] = { | ||
1266 | |||
1267 | {DEBUG_REG_DMN, FCC, DFS_FCC3, NO_PSCAN, NO_REQ, | ||
1268 | BM(A_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1269 | -1), | ||
1270 | BM(T1_5130_5650, T1_5150_5670, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1271 | -1), | ||
1272 | BM(T1_5200_5240, T1_5280_5280, T1_5540_5660, T1_5765_5805, -1, -1, | ||
1273 | -1, -1, -1, -1, -1, -1), | ||
1274 | BM(F1_2312_2372, F1_2412_2472, F1_2484_2484, F1_2512_2732, -1, -1, | ||
1275 | -1, -1, -1, -1, -1, -1), | ||
1276 | BM(G_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1277 | -1), | ||
1278 | BM(T1_2312_2372, T1_2437_2437, T1_2512_2732, -1, -1, -1, -1, -1, | ||
1279 | -1, -1, -1, -1)}, | ||
1280 | |||
1281 | {APL1, FCC, NO_DFS, NO_PSCAN, NO_REQ, | ||
1282 | BM(F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1283 | BM(T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1284 | BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1285 | BMZERO, | ||
1286 | BMZERO, | ||
1287 | BMZERO}, | ||
1288 | |||
1289 | {APL2, FCC, NO_DFS, NO_PSCAN, NO_REQ, | ||
1290 | BM(F1_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1291 | BM(T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1292 | BM(T2_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1293 | BMZERO, | ||
1294 | BMZERO, | ||
1295 | BMZERO}, | ||
1296 | |||
1297 | {APL3, FCC, NO_DFS, NO_PSCAN, NO_REQ, | ||
1298 | BM(F1_5280_5320, F2_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1299 | -1), | ||
1300 | BM(T1_5290_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1301 | -1), | ||
1302 | BM(T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1303 | BMZERO, | ||
1304 | BMZERO, | ||
1305 | BMZERO}, | ||
1306 | |||
1307 | {APL4, FCC, NO_DFS, NO_PSCAN, NO_REQ, | ||
1308 | BM(F4_5180_5240, F3_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1309 | -1), | ||
1310 | BM(T1_5210_5210, T3_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1311 | -1), | ||
1312 | BM(T1_5200_5200, T3_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1313 | -1), | ||
1314 | BMZERO, | ||
1315 | BMZERO, | ||
1316 | BMZERO}, | ||
1317 | |||
1318 | {APL5, FCC, NO_DFS, NO_PSCAN, NO_REQ, | ||
1319 | BM(F2_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1320 | BM(T4_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1321 | BM(T4_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1322 | BMZERO, | ||
1323 | BMZERO, | ||
1324 | BMZERO}, | ||
1325 | |||
1326 | {APL6, ETSI, DFS_ETSI, PSCAN_FCC_T | PSCAN_FCC, NO_REQ, | ||
1327 | BM(F4_5180_5240, F2_5260_5320, F3_5745_5825, -1, -1, -1, -1, -1, | ||
1328 | -1, -1, -1, -1), | ||
1329 | BM(T2_5210_5210, T1_5250_5290, T1_5760_5800, -1, -1, -1, -1, -1, | ||
1330 | -1, -1, -1, -1), | ||
1331 | BM(T1_5200_5280, T5_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1332 | -1), | ||
1333 | BMZERO, | ||
1334 | BMZERO, | ||
1335 | BMZERO}, | ||
1336 | |||
1337 | {APL7, ETSI, DFS_ETSI, PSCAN_ETSI, NO_REQ, | ||
1338 | BM(F1_5280_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1, | ||
1339 | -1, -1, -1, -1), | ||
1340 | BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1341 | -1), | ||
1342 | BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1343 | -1), | ||
1344 | BMZERO, | ||
1345 | BMZERO, | ||
1346 | BMZERO}, | ||
1347 | |||
1348 | {APL8, ETSI, NO_DFS, NO_PSCAN, | ||
1349 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1350 | BM(F6_5260_5320, F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1351 | -1), | ||
1352 | BM(T2_5290_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1353 | -1), | ||
1354 | BM(T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1355 | -1), | ||
1356 | BMZERO, | ||
1357 | BMZERO, | ||
1358 | BMZERO}, | ||
1359 | |||
1360 | {APL9, ETSI, DFS_ETSI, PSCAN_ETSI, | ||
1361 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1362 | BM(F1_5180_5320, F1_5500_5620, F3_5745_5805, -1, -1, -1, -1, -1, | ||
1363 | -1, -1, -1, -1), | ||
1364 | BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1365 | -1), | ||
1366 | BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1367 | -1), | ||
1368 | BMZERO, | ||
1369 | BMZERO, | ||
1370 | BMZERO}, | ||
1371 | |||
1372 | {APL10, ETSI, DFS_ETSI, PSCAN_ETSI, | ||
1373 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1374 | BM(F1_5180_5320, F5_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1, | ||
1375 | -1, -1, -1, -1), | ||
1376 | BM(T3_5290_5290, T5_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1377 | -1), | ||
1378 | BM(T1_5540_5660, T6_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1379 | -1), | ||
1380 | BMZERO, | ||
1381 | BMZERO, | ||
1382 | BMZERO}, | ||
1383 | |||
1384 | {ETSI1, ETSI, DFS_ETSI, PSCAN_ETSI, | ||
1385 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1386 | BM(F4_5180_5240, F2_5260_5320, F2_5500_5700, -1, -1, -1, -1, -1, | ||
1387 | -1, -1, -1, -1), | ||
1388 | BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1389 | BM(T2_5200_5280, T2_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1390 | -1), | ||
1391 | BMZERO, | ||
1392 | BMZERO, | ||
1393 | BMZERO}, | ||
1394 | |||
1395 | {ETSI2, ETSI, DFS_ETSI, PSCAN_ETSI, | ||
1396 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1397 | BM(F3_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1398 | BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1399 | BM(T2_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1400 | BMZERO, | ||
1401 | BMZERO, | ||
1402 | BMZERO}, | ||
1403 | |||
1404 | {ETSI3, ETSI, DFS_ETSI, PSCAN_ETSI, | ||
1405 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1406 | BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1407 | -1), | ||
1408 | BM(T1_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1409 | BM(T2_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1410 | BMZERO, | ||
1411 | BMZERO, | ||
1412 | BMZERO}, | ||
1413 | |||
1414 | {ETSI4, ETSI, DFS_ETSI, PSCAN_ETSI, | ||
1415 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1416 | BM(F3_5180_5240, F1_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1417 | -1), | ||
1418 | BM(T2_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1419 | BM(T3_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1420 | BMZERO, | ||
1421 | BMZERO, | ||
1422 | BMZERO}, | ||
1423 | |||
1424 | {ETSI5, ETSI, DFS_ETSI, PSCAN_ETSI, | ||
1425 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1426 | BM(F1_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1427 | BM(T4_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1428 | BM(T3_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1429 | BMZERO, | ||
1430 | BMZERO, | ||
1431 | BMZERO}, | ||
1432 | |||
1433 | {ETSI6, ETSI, DFS_ETSI, PSCAN_ETSI, | ||
1434 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1435 | BM(F5_5180_5240, F1_5260_5280, F3_5500_5700, -1, -1, -1, -1, -1, | ||
1436 | -1, -1, -1, -1), | ||
1437 | BM(T1_5210_5250, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1438 | BM(T4_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1439 | BMZERO, | ||
1440 | BMZERO, | ||
1441 | BMZERO}, | ||
1442 | |||
1443 | {FCC1, FCC, NO_DFS, NO_PSCAN, NO_REQ, | ||
1444 | BM(F2_5180_5240, F4_5260_5320, F5_5745_5825, -1, -1, -1, -1, -1, | ||
1445 | -1, -1, -1, -1), | ||
1446 | BM(T6_5210_5210, T2_5250_5290, T6_5760_5800, -1, -1, -1, -1, -1, | ||
1447 | -1, -1, -1, -1), | ||
1448 | BM(T1_5200_5240, T2_5280_5280, T7_5765_5805, -1, -1, -1, -1, -1, | ||
1449 | -1, -1, -1, -1), | ||
1450 | BMZERO, | ||
1451 | BMZERO, | ||
1452 | BMZERO}, | ||
1453 | |||
1454 | {FCC2, FCC, NO_DFS, NO_PSCAN, NO_REQ, | ||
1455 | BM(F6_5180_5240, F5_5260_5320, F6_5745_5825, -1, -1, -1, -1, -1, | ||
1456 | -1, -1, -1, -1), | ||
1457 | BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, | ||
1458 | -1, -1, -1, -1), | ||
1459 | BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1, | ||
1460 | -1, -1, -1, -1, -1, -1), | ||
1461 | BMZERO, | ||
1462 | BMZERO, | ||
1463 | BMZERO}, | ||
1464 | |||
1465 | {FCC3, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, | ||
1466 | BM(F2_5180_5240, F3_5260_5320, F1_5500_5700, F5_5745_5825, -1, -1, | ||
1467 | -1, -1, -1, -1, -1, -1), | ||
1468 | BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1469 | -1), | ||
1470 | BM(T4_5200_5200, T8_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1471 | -1), | ||
1472 | BMZERO, | ||
1473 | BMZERO, | ||
1474 | BMZERO}, | ||
1475 | |||
1476 | {FCC4, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ, | ||
1477 | BM(F1_4942_4987, F1_4945_4985, F1_4950_4980, -1, -1, -1, -1, -1, | ||
1478 | -1, -1, -1, -1), | ||
1479 | BM(T8_5210_5210, T4_5250_5290, T7_5760_5800, -1, -1, -1, -1, -1, | ||
1480 | -1, -1, -1, -1), | ||
1481 | BM(T1_5200_5240, T1_5280_5280, T9_5765_5805, -1, -1, -1, -1, -1, | ||
1482 | -1, -1, -1, -1), | ||
1483 | BMZERO, | ||
1484 | BMZERO, | ||
1485 | BMZERO}, | ||
1486 | |||
1487 | {FCC5, FCC, NO_DFS, NO_PSCAN, NO_REQ, | ||
1488 | BM(F2_5180_5240, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1489 | -1), | ||
1490 | BM(T6_5210_5210, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1491 | -1), | ||
1492 | BM(T8_5200_5200, T7_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1493 | -1), | ||
1494 | BMZERO, | ||
1495 | BMZERO, | ||
1496 | BMZERO}, | ||
1497 | |||
1498 | {FCC6, FCC, DFS_FCC3, PSCAN_FCC, NO_REQ, | ||
1499 | BM(F8_5180_5240, F5_5260_5320, F1_5500_5580, F1_5660_5700, | ||
1500 | F6_5745_5825, -1, -1, -1, -1, -1, -1, -1), | ||
1501 | BM(T7_5210_5210, T3_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, | ||
1502 | -1, -1, -1, -1), | ||
1503 | BM(T7_5200_5200, T1_5240_5240, T2_5280_5280, T1_5765_5805, -1, -1, | ||
1504 | -1, -1, -1, -1, -1, -1), | ||
1505 | BMZERO, | ||
1506 | BMZERO, | ||
1507 | BMZERO}, | ||
1508 | |||
1509 | {MKK1, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, | ||
1510 | BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, | ||
1511 | -1, -1, -1, -1, -1, -1), | ||
1512 | BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1513 | BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1514 | BMZERO, | ||
1515 | BMZERO, | ||
1516 | BMZERO}, | ||
1517 | |||
1518 | {MKK2, MKK, NO_DFS, PSCAN_MKK2, DISALLOW_ADHOC_11A_TURB, | ||
1519 | BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, | ||
1520 | F1_5055_5055, F1_5040_5080, F1_5170_5230, F4_5180_5240, | ||
1521 | F2_5260_5320, F4_5500_5700, -1, -1), | ||
1522 | BM(T7_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1523 | BM(T5_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1524 | BMZERO, | ||
1525 | BMZERO, | ||
1526 | BMZERO}, | ||
1527 | |||
1528 | |||
1529 | {MKK3, MKK, NO_DFS, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, | ||
1530 | BM(F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1531 | BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1532 | BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1533 | BMZERO, | ||
1534 | BMZERO, | ||
1535 | BMZERO}, | ||
1536 | |||
1537 | |||
1538 | {MKK4, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, | ||
1539 | BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1540 | -1), | ||
1541 | BM(T10_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1542 | BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1543 | BMZERO, | ||
1544 | BMZERO, | ||
1545 | BMZERO}, | ||
1546 | |||
1547 | |||
1548 | {MKK5, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, | ||
1549 | BM(F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, -1, -1, -1, | ||
1550 | -1, -1, -1, -1), | ||
1551 | BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1552 | BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1553 | -1), | ||
1554 | BMZERO, | ||
1555 | BMZERO, | ||
1556 | BMZERO}, | ||
1557 | |||
1558 | |||
1559 | {MKK6, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, | ||
1560 | BM(F2_5170_5230, F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1561 | -1), | ||
1562 | BM(T3_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1563 | BM(T6_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1564 | BMZERO, | ||
1565 | BMZERO, | ||
1566 | BMZERO}, | ||
1567 | |||
1568 | |||
1569 | {MKK7, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, | ||
1570 | DISALLOW_ADHOC_11A_TURB, | ||
1571 | BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, | ||
1572 | -1, -1, -1, -1), | ||
1573 | BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1574 | BM(T5_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1575 | BMZERO, | ||
1576 | BMZERO, | ||
1577 | BMZERO}, | ||
1578 | |||
1579 | |||
1580 | {MKK8, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, | ||
1581 | DISALLOW_ADHOC_11A_TURB, | ||
1582 | BM(F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, | ||
1583 | -1, -1, -1, -1, -1, -1), | ||
1584 | BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1585 | BM(T5_5200_5280, T3_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1586 | -1), | ||
1587 | BMZERO, | ||
1588 | BMZERO, | ||
1589 | BMZERO}, | ||
1590 | |||
1591 | |||
1592 | {MKK9, MKK, NO_DFS, PSCAN_MKK2 | PSCAN_MKK3, | ||
1593 | DISALLOW_ADHOC_11A_TURB, | ||
1594 | BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, | ||
1595 | F1_5055_5055, F1_5040_5080, F4_5180_5240, -1, -1, -1, -1, -1), | ||
1596 | BM(T9_5210_5210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1597 | BM(T1_5200_5200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1598 | BMZERO, | ||
1599 | BMZERO, | ||
1600 | BMZERO}, | ||
1601 | |||
1602 | |||
1603 | {MKK10, MKK, DFS_MKK4, PSCAN_MKK2 | PSCAN_MKK3, | ||
1604 | DISALLOW_ADHOC_11A_TURB, | ||
1605 | BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, | ||
1606 | F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320, -1, -1, | ||
1607 | -1, -1), | ||
1608 | BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1609 | BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1610 | BMZERO, | ||
1611 | BMZERO, | ||
1612 | BMZERO}, | ||
1613 | |||
1614 | |||
1615 | {MKK11, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB, | ||
1616 | BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, | ||
1617 | F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320, | ||
1618 | F4_5500_5700, -1, -1, -1), | ||
1619 | BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1620 | BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1621 | BMZERO, | ||
1622 | BMZERO, | ||
1623 | BMZERO}, | ||
1624 | |||
1625 | |||
1626 | {MKK12, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, | ||
1627 | DISALLOW_ADHOC_11A_TURB, | ||
1628 | BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, | ||
1629 | F1_5055_5055, F1_5040_5080, F1_5170_5230, F4_5180_5240, | ||
1630 | F2_5260_5320, F4_5500_5700, -1, -1), | ||
1631 | BM(T3_5210_5290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1632 | BM(T1_5200_5280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1633 | BMZERO, | ||
1634 | BMZERO, | ||
1635 | BMZERO}, | ||
1636 | |||
1637 | |||
1638 | {MKK13, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3, | ||
1639 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1640 | BM(F1_5170_5230, F7_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, | ||
1641 | -1, -1, -1, -1, -1, -1), | ||
1642 | BMZERO, | ||
1643 | BMZERO, | ||
1644 | BMZERO, | ||
1645 | BMZERO, | ||
1646 | BMZERO}, | ||
1647 | |||
1648 | |||
1649 | {MKK14, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, | ||
1650 | BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, | ||
1651 | F1_5040_5080, F1_5055_5055, F1_5170_5230, F4_5180_5240, -1, -1, | ||
1652 | -1, -1), | ||
1653 | BMZERO, | ||
1654 | BMZERO, | ||
1655 | BMZERO, | ||
1656 | BMZERO, | ||
1657 | BMZERO}, | ||
1658 | |||
1659 | |||
1660 | {MKK15, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB, | ||
1661 | BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, | ||
1662 | F1_5040_5080, F1_5055_5055, F1_5170_5230, F4_5180_5240, | ||
1663 | F2_5260_5320, -1, -1, -1), | ||
1664 | BMZERO, | ||
1665 | BMZERO, | ||
1666 | BMZERO, | ||
1667 | BMZERO, | ||
1668 | BMZERO}, | ||
1669 | |||
1670 | |||
1671 | {APLD, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, | ||
1672 | BMZERO, | ||
1673 | BMZERO, | ||
1674 | BMZERO, | ||
1675 | BM(F2_2312_2372, F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1676 | -1), | ||
1677 | BM(G2_2312_2372, G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1678 | -1), | ||
1679 | BMZERO}, | ||
1680 | |||
1681 | {ETSIA, NO_CTL, NO_DFS, PSCAN_ETSIA, | ||
1682 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1683 | BMZERO, | ||
1684 | BMZERO, | ||
1685 | BMZERO, | ||
1686 | BM(F1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1687 | BM(G1_2457_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1688 | BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1689 | |||
1690 | {ETSIB, ETSI, NO_DFS, PSCAN_ETSIB, | ||
1691 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1692 | BMZERO, | ||
1693 | BMZERO, | ||
1694 | BMZERO, | ||
1695 | BM(F1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1696 | BM(G1_2432_2442, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1697 | BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1698 | |||
1699 | {ETSIC, ETSI, NO_DFS, PSCAN_ETSIC, | ||
1700 | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, | ||
1701 | BMZERO, | ||
1702 | BMZERO, | ||
1703 | BMZERO, | ||
1704 | BM(F3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1705 | BM(G3_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1706 | BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1707 | |||
1708 | {FCCA, FCC, NO_DFS, NO_PSCAN, NO_REQ, | ||
1709 | BMZERO, | ||
1710 | BMZERO, | ||
1711 | BMZERO, | ||
1712 | BM(F1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1713 | BM(G1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1714 | BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1715 | |||
1716 | {MKKA, MKK, NO_DFS, | ||
1717 | PSCAN_MKKA | PSCAN_MKKA_G | PSCAN_MKKA1 | PSCAN_MKKA1_G | | ||
1718 | PSCAN_MKKA2 | PSCAN_MKKA2_G, DISALLOW_ADHOC_11A_TURB, | ||
1719 | BMZERO, | ||
1720 | BMZERO, | ||
1721 | BMZERO, | ||
1722 | BM(F2_2412_2462, F1_2467_2472, F2_2484_2484, -1, -1, -1, -1, -1, | ||
1723 | -1, -1, -1, -1), | ||
1724 | BM(G2_2412_2462, G1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1725 | -1), | ||
1726 | BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1727 | |||
1728 | {MKKC, MKK, NO_DFS, NO_PSCAN, NO_REQ, | ||
1729 | BMZERO, | ||
1730 | BMZERO, | ||
1731 | BMZERO, | ||
1732 | BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1733 | BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1734 | BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1735 | |||
1736 | {WORLD, ETSI, NO_DFS, NO_PSCAN, NO_REQ, | ||
1737 | BMZERO, | ||
1738 | BMZERO, | ||
1739 | BMZERO, | ||
1740 | BM(F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1741 | BM(G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1742 | BM(T2_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1743 | |||
1744 | {WOR0_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, | ||
1745 | BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, | ||
1746 | W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), | ||
1747 | BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, | ||
1748 | -1, -1, -1, -1, -1), | ||
1749 | BMZERO, | ||
1750 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, | ||
1751 | W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, | ||
1752 | -1, -1), | ||
1753 | BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1754 | -1, -1), | ||
1755 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1756 | |||
1757 | {WOR01_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, | ||
1758 | ADHOC_PER_11D, | ||
1759 | BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, | ||
1760 | W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), | ||
1761 | BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, | ||
1762 | -1, -1, -1, -1, -1), | ||
1763 | BMZERO, | ||
1764 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, | ||
1765 | W1_2447_2457, -1, -1, -1, -1, -1, -1, -1), | ||
1766 | BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1767 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1768 | |||
1769 | {WOR02_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, | ||
1770 | ADHOC_PER_11D, | ||
1771 | BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, | ||
1772 | W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), | ||
1773 | BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, | ||
1774 | -1, -1, -1, -1, -1), | ||
1775 | BMZERO, | ||
1776 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, | ||
1777 | W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), | ||
1778 | BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1779 | -1, -1), | ||
1780 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1781 | |||
1782 | {EU1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, | ||
1783 | BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, | ||
1784 | W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), | ||
1785 | BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, | ||
1786 | -1, -1, -1, -1, -1), | ||
1787 | BMZERO, | ||
1788 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W2_2472_2472, | ||
1789 | W1_2417_2432, W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1), | ||
1790 | BM(WG1_2412_2462, WG2_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1791 | -1, -1), | ||
1792 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1793 | |||
1794 | {WOR1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, | ||
1795 | BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, | ||
1796 | W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), | ||
1797 | BMZERO, | ||
1798 | BMZERO, | ||
1799 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, | ||
1800 | W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, | ||
1801 | -1, -1), | ||
1802 | BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1803 | -1, -1), | ||
1804 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1805 | |||
1806 | {WOR2_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, | ||
1807 | BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, | ||
1808 | W1_5500_5700, -1, -1, -1, -1, -1, -1, -1), | ||
1809 | BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, | ||
1810 | -1, -1, -1, -1, -1), | ||
1811 | BMZERO, | ||
1812 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, | ||
1813 | W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, | ||
1814 | -1, -1), | ||
1815 | BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1816 | -1, -1), | ||
1817 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1818 | |||
1819 | {WOR3_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D, | ||
1820 | BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, -1, -1, | ||
1821 | -1, -1, -1, -1, -1, -1), | ||
1822 | BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, | ||
1823 | -1, -1, -1, -1, -1), | ||
1824 | BMZERO, | ||
1825 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, | ||
1826 | W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), | ||
1827 | BM(WG1_2412_2462, WG2_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1828 | -1, -1), | ||
1829 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1830 | |||
1831 | {WOR4_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, | ||
1832 | BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, -1, -1, -1, -1, -1, | ||
1833 | -1, -1, -1, -1), | ||
1834 | BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, | ||
1835 | -1, -1, -1, -1, -1), | ||
1836 | BMZERO, | ||
1837 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, | ||
1838 | W1_2447_2457, -1, -1, -1, -1, -1, -1, -1), | ||
1839 | BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1840 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1841 | |||
1842 | {WOR5_ETSIC, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, | ||
1843 | BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, -1, -1, -1, -1, -1, | ||
1844 | -1, -1, -1, -1), | ||
1845 | BMZERO, | ||
1846 | BMZERO, | ||
1847 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, | ||
1848 | W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), | ||
1849 | BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1850 | -1, -1), | ||
1851 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1852 | |||
1853 | {WOR9_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, | ||
1854 | BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1, | ||
1855 | -1, -1, -1, -1, -1, -1), | ||
1856 | BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, | ||
1857 | -1, -1, -1, -1, -1), | ||
1858 | BMZERO, | ||
1859 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, | ||
1860 | W1_2447_2457, -1, -1, -1, -1, -1, -1, -1), | ||
1861 | BM(WG1_2412_2462, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), | ||
1862 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1863 | |||
1864 | {WORA_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, | ||
1865 | BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1, | ||
1866 | -1, -1, -1, -1, -1, -1), | ||
1867 | BMZERO, | ||
1868 | BMZERO, | ||
1869 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, | ||
1870 | W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), | ||
1871 | BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1872 | -1, -1), | ||
1873 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1874 | |||
1875 | {WORB_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A, | ||
1876 | BM(W1_5260_5320, W1_5180_5240, W1_5500_5700, -1, -1, -1, -1, -1, | ||
1877 | -1, -1, -1, -1), | ||
1878 | BMZERO, | ||
1879 | BMZERO, | ||
1880 | BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, | ||
1881 | W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1), | ||
1882 | BM(WG1_2412_2462, WG1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, | ||
1883 | -1, -1), | ||
1884 | BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)}, | ||
1885 | |||
1886 | {NULL1, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ, | ||
1887 | BMZERO, | ||
1888 | BMZERO, | ||
1889 | BMZERO, | ||
1890 | BMZERO, | ||
1891 | BMZERO, | ||
1892 | BMZERO} | ||
1893 | }; | ||
1894 | |||
1895 | static const struct cmode modes[] = { | ||
1896 | {ATH9K_MODE_SEL_11A, CHANNEL_A}, | ||
1897 | {ATH9K_MODE_SEL_11B, CHANNEL_B}, | ||
1898 | {ATH9K_MODE_SEL_11G, CHANNEL_G}, | ||
1899 | {ATH9K_MODE_SEL_11NG_HT20, CHANNEL_G_HT20}, | ||
1900 | {ATH9K_MODE_SEL_11NG_HT40PLUS, CHANNEL_G_HT40PLUS}, | ||
1901 | {ATH9K_MODE_SEL_11NG_HT40MINUS, CHANNEL_G_HT40MINUS}, | ||
1902 | {ATH9K_MODE_SEL_11NA_HT20, CHANNEL_A_HT20}, | ||
1903 | {ATH9K_MODE_SEL_11NA_HT40PLUS, CHANNEL_A_HT40PLUS}, | ||
1904 | {ATH9K_MODE_SEL_11NA_HT40MINUS, CHANNEL_A_HT40MINUS}, | ||
1905 | }; | ||
1906 | |||
1907 | static struct japan_bandcheck j_bandcheck[] = { | ||
1908 | {F1_5170_5230, AR_EEPROM_EEREGCAP_EN_KK_U1_ODD}, | ||
1909 | {F4_5180_5240, AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN}, | ||
1910 | {F2_5260_5320, AR_EEPROM_EEREGCAP_EN_KK_U2}, | ||
1911 | {F4_5500_5700, AR_EEPROM_EEREGCAP_EN_KK_MIDBAND} | ||
1912 | }; | ||
1913 | |||
1914 | |||
1915 | #endif | ||
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c new file mode 100644 index 00000000000..f0297ee5d05 --- /dev/null +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -0,0 +1,2870 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* | ||
18 | * Implementation of transmit path. | ||
19 | */ | ||
20 | |||
21 | #include "core.h" | ||
22 | |||
23 | #define BITS_PER_BYTE 8 | ||
24 | #define OFDM_PLCP_BITS 22 | ||
25 | #define HT_RC_2_MCS(_rc) ((_rc) & 0x0f) | ||
26 | #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) | ||
27 | #define L_STF 8 | ||
28 | #define L_LTF 8 | ||
29 | #define L_SIG 4 | ||
30 | #define HT_SIG 8 | ||
31 | #define HT_STF 4 | ||
32 | #define HT_LTF(_ns) (4 * (_ns)) | ||
33 | #define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */ | ||
34 | #define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */ | ||
35 | #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) | ||
36 | #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) | ||
37 | |||
38 | #define OFDM_SIFS_TIME 16 | ||
39 | |||
40 | static u32 bits_per_symbol[][2] = { | ||
41 | /* 20MHz 40MHz */ | ||
42 | { 26, 54 }, /* 0: BPSK */ | ||
43 | { 52, 108 }, /* 1: QPSK 1/2 */ | ||
44 | { 78, 162 }, /* 2: QPSK 3/4 */ | ||
45 | { 104, 216 }, /* 3: 16-QAM 1/2 */ | ||
46 | { 156, 324 }, /* 4: 16-QAM 3/4 */ | ||
47 | { 208, 432 }, /* 5: 64-QAM 2/3 */ | ||
48 | { 234, 486 }, /* 6: 64-QAM 3/4 */ | ||
49 | { 260, 540 }, /* 7: 64-QAM 5/6 */ | ||
50 | { 52, 108 }, /* 8: BPSK */ | ||
51 | { 104, 216 }, /* 9: QPSK 1/2 */ | ||
52 | { 156, 324 }, /* 10: QPSK 3/4 */ | ||
53 | { 208, 432 }, /* 11: 16-QAM 1/2 */ | ||
54 | { 312, 648 }, /* 12: 16-QAM 3/4 */ | ||
55 | { 416, 864 }, /* 13: 64-QAM 2/3 */ | ||
56 | { 468, 972 }, /* 14: 64-QAM 3/4 */ | ||
57 | { 520, 1080 }, /* 15: 64-QAM 5/6 */ | ||
58 | }; | ||
59 | |||
60 | #define IS_HT_RATE(_rate) ((_rate) & 0x80) | ||
61 | |||
62 | /* | ||
63 | * Insert a chain of ath_buf (descriptors) on a multicast txq | ||
64 | * but do NOT start tx DMA on this queue. | ||
65 | * NB: must be called with txq lock held | ||
66 | */ | ||
67 | |||
68 | static void ath_tx_mcastqaddbuf(struct ath_softc *sc, | ||
69 | struct ath_txq *txq, | ||
70 | struct list_head *head) | ||
71 | { | ||
72 | struct ath_hal *ah = sc->sc_ah; | ||
73 | struct ath_buf *bf; | ||
74 | |||
75 | if (list_empty(head)) | ||
76 | return; | ||
77 | |||
78 | /* | ||
79 | * Insert the frame on the outbound list and | ||
80 | * pass it on to the hardware. | ||
81 | */ | ||
82 | bf = list_first_entry(head, struct ath_buf, list); | ||
83 | |||
84 | /* | ||
85 | * The CAB queue is started from the SWBA handler since | ||
86 | * frames only go out on DTIM and to avoid possible races. | ||
87 | */ | ||
88 | ath9k_hw_set_interrupts(ah, 0); | ||
89 | |||
90 | /* | ||
91 | * If there is anything in the mcastq, we want to set | ||
92 | * the "more data" bit in the last item in the queue to | ||
93 | * indicate that there is "more data". It makes sense to add | ||
94 | * it here since you are *always* going to have | ||
95 | * more data when adding to this queue, no matter where | ||
96 | * you call from. | ||
97 | */ | ||
98 | |||
99 | if (txq->axq_depth) { | ||
100 | struct ath_buf *lbf; | ||
101 | struct ieee80211_hdr *hdr; | ||
102 | |||
103 | /* | ||
104 | * Add the "more data flag" to the last frame | ||
105 | */ | ||
106 | |||
107 | lbf = list_entry(txq->axq_q.prev, struct ath_buf, list); | ||
108 | hdr = (struct ieee80211_hdr *) | ||
109 | ((struct sk_buff *)(lbf->bf_mpdu))->data; | ||
110 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Now, concat the frame onto the queue | ||
115 | */ | ||
116 | list_splice_tail_init(head, &txq->axq_q); | ||
117 | txq->axq_depth++; | ||
118 | txq->axq_totalqueued++; | ||
119 | txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); | ||
120 | |||
121 | DPRINTF(sc, ATH_DBG_QUEUE, | ||
122 | "%s: txq depth = %d\n", __func__, txq->axq_depth); | ||
123 | if (txq->axq_link != NULL) { | ||
124 | *txq->axq_link = bf->bf_daddr; | ||
125 | DPRINTF(sc, ATH_DBG_XMIT, | ||
126 | "%s: link[%u](%p)=%llx (%p)\n", | ||
127 | __func__, | ||
128 | txq->axq_qnum, txq->axq_link, | ||
129 | ito64(bf->bf_daddr), bf->bf_desc); | ||
130 | } | ||
131 | txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); | ||
132 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * Insert a chain of ath_buf (descriptors) on a txq and | ||
137 | * assume the descriptors are already chained together by caller. | ||
138 | * NB: must be called with txq lock held | ||
139 | */ | ||
140 | |||
141 | static void ath_tx_txqaddbuf(struct ath_softc *sc, | ||
142 | struct ath_txq *txq, struct list_head *head) | ||
143 | { | ||
144 | struct ath_hal *ah = sc->sc_ah; | ||
145 | struct ath_buf *bf; | ||
146 | /* | ||
147 | * Insert the frame on the outbound list and | ||
148 | * pass it on to the hardware. | ||
149 | */ | ||
150 | |||
151 | if (list_empty(head)) | ||
152 | return; | ||
153 | |||
154 | bf = list_first_entry(head, struct ath_buf, list); | ||
155 | |||
156 | list_splice_tail_init(head, &txq->axq_q); | ||
157 | txq->axq_depth++; | ||
158 | txq->axq_totalqueued++; | ||
159 | txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); | ||
160 | |||
161 | DPRINTF(sc, ATH_DBG_QUEUE, | ||
162 | "%s: txq depth = %d\n", __func__, txq->axq_depth); | ||
163 | |||
164 | if (txq->axq_link == NULL) { | ||
165 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); | ||
166 | DPRINTF(sc, ATH_DBG_XMIT, | ||
167 | "%s: TXDP[%u] = %llx (%p)\n", | ||
168 | __func__, txq->axq_qnum, | ||
169 | ito64(bf->bf_daddr), bf->bf_desc); | ||
170 | } else { | ||
171 | *txq->axq_link = bf->bf_daddr; | ||
172 | DPRINTF(sc, ATH_DBG_XMIT, "%s: link[%u] (%p)=%llx (%p)\n", | ||
173 | __func__, | ||
174 | txq->axq_qnum, txq->axq_link, | ||
175 | ito64(bf->bf_daddr), bf->bf_desc); | ||
176 | } | ||
177 | txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); | ||
178 | ath9k_hw_txstart(ah, txq->axq_qnum); | ||
179 | } | ||
180 | |||
181 | /* Get transmit rate index using rate in Kbps */ | ||
182 | |||
183 | static int ath_tx_findindex(const struct ath9k_rate_table *rt, int rate) | ||
184 | { | ||
185 | int i; | ||
186 | int ndx = 0; | ||
187 | |||
188 | for (i = 0; i < rt->rateCount; i++) { | ||
189 | if (rt->info[i].rateKbps == rate) { | ||
190 | ndx = i; | ||
191 | break; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | return ndx; | ||
196 | } | ||
197 | |||
198 | /* Check if it's okay to send out aggregates */ | ||
199 | |||
200 | static int ath_aggr_query(struct ath_softc *sc, | ||
201 | struct ath_node *an, u8 tidno) | ||
202 | { | ||
203 | struct ath_atx_tid *tid; | ||
204 | tid = ATH_AN_2_TID(an, tidno); | ||
205 | |||
206 | if (tid->addba_exchangecomplete || tid->addba_exchangeinprogress) | ||
207 | return 1; | ||
208 | else | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static enum ath9k_pkt_type get_hal_packet_type(struct ieee80211_hdr *hdr) | ||
213 | { | ||
214 | enum ath9k_pkt_type htype; | ||
215 | __le16 fc; | ||
216 | |||
217 | fc = hdr->frame_control; | ||
218 | |||
219 | /* Calculate Atheros packet type from IEEE80211 packet header */ | ||
220 | |||
221 | if (ieee80211_is_beacon(fc)) | ||
222 | htype = ATH9K_PKT_TYPE_BEACON; | ||
223 | else if (ieee80211_is_probe_resp(fc)) | ||
224 | htype = ATH9K_PKT_TYPE_PROBE_RESP; | ||
225 | else if (ieee80211_is_atim(fc)) | ||
226 | htype = ATH9K_PKT_TYPE_ATIM; | ||
227 | else if (ieee80211_is_pspoll(fc)) | ||
228 | htype = ATH9K_PKT_TYPE_PSPOLL; | ||
229 | else | ||
230 | htype = ATH9K_PKT_TYPE_NORMAL; | ||
231 | |||
232 | return htype; | ||
233 | } | ||
234 | |||
235 | static void fill_min_rates(struct sk_buff *skb, struct ath_tx_control *txctl) | ||
236 | { | ||
237 | struct ieee80211_hdr *hdr; | ||
238 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
239 | struct ath_tx_info_priv *tx_info_priv; | ||
240 | __le16 fc; | ||
241 | |||
242 | hdr = (struct ieee80211_hdr *)skb->data; | ||
243 | fc = hdr->frame_control; | ||
244 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | ||
245 | |||
246 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) { | ||
247 | txctl->use_minrate = 1; | ||
248 | txctl->min_rate = tx_info_priv->min_rate; | ||
249 | } else if (ieee80211_is_data(fc)) { | ||
250 | if (ieee80211_is_nullfunc(fc) || | ||
251 | /* Port Access Entity (IEEE 802.1X) */ | ||
252 | (skb->protocol == cpu_to_be16(0x888E))) { | ||
253 | txctl->use_minrate = 1; | ||
254 | txctl->min_rate = tx_info_priv->min_rate; | ||
255 | } | ||
256 | if (is_multicast_ether_addr(hdr->addr1)) | ||
257 | txctl->mcast_rate = tx_info_priv->min_rate; | ||
258 | } | ||
259 | |||
260 | } | ||
261 | |||
262 | /* This function will setup additional txctl information, mostly rate stuff */ | ||
263 | /* FIXME: seqno, ps */ | ||
264 | static int ath_tx_prepare(struct ath_softc *sc, | ||
265 | struct sk_buff *skb, | ||
266 | struct ath_tx_control *txctl) | ||
267 | { | ||
268 | struct ieee80211_hw *hw = sc->hw; | ||
269 | struct ieee80211_hdr *hdr; | ||
270 | struct ath_rc_series *rcs; | ||
271 | struct ath_txq *txq = NULL; | ||
272 | const struct ath9k_rate_table *rt; | ||
273 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
274 | struct ath_tx_info_priv *tx_info_priv; | ||
275 | int hdrlen; | ||
276 | u8 rix, antenna; | ||
277 | __le16 fc; | ||
278 | u8 *qc; | ||
279 | |||
280 | memset(txctl, 0, sizeof(struct ath_tx_control)); | ||
281 | |||
282 | txctl->dev = sc; | ||
283 | hdr = (struct ieee80211_hdr *)skb->data; | ||
284 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
285 | fc = hdr->frame_control; | ||
286 | |||
287 | rt = sc->sc_currates; | ||
288 | BUG_ON(!rt); | ||
289 | |||
290 | /* Fill misc fields */ | ||
291 | |||
292 | spin_lock_bh(&sc->node_lock); | ||
293 | txctl->an = ath_node_get(sc, hdr->addr1); | ||
294 | /* create a temp node, if the node is not there already */ | ||
295 | if (!txctl->an) | ||
296 | txctl->an = ath_node_attach(sc, hdr->addr1, 0); | ||
297 | spin_unlock_bh(&sc->node_lock); | ||
298 | |||
299 | if (ieee80211_is_data_qos(fc)) { | ||
300 | qc = ieee80211_get_qos_ctl(hdr); | ||
301 | txctl->tidno = qc[0] & 0xf; | ||
302 | } | ||
303 | |||
304 | txctl->if_id = 0; | ||
305 | txctl->nextfraglen = 0; | ||
306 | txctl->frmlen = skb->len + FCS_LEN - (hdrlen & 3); | ||
307 | txctl->txpower = MAX_RATE_POWER; /* FIXME */ | ||
308 | |||
309 | /* Fill Key related fields */ | ||
310 | |||
311 | txctl->keytype = ATH9K_KEY_TYPE_CLEAR; | ||
312 | txctl->keyix = ATH9K_TXKEYIX_INVALID; | ||
313 | |||
314 | if (tx_info->control.hw_key) { | ||
315 | txctl->keyix = tx_info->control.hw_key->hw_key_idx; | ||
316 | txctl->frmlen += tx_info->control.icv_len; | ||
317 | |||
318 | if (sc->sc_keytype == ATH9K_CIPHER_WEP) | ||
319 | txctl->keytype = ATH9K_KEY_TYPE_WEP; | ||
320 | else if (sc->sc_keytype == ATH9K_CIPHER_TKIP) | ||
321 | txctl->keytype = ATH9K_KEY_TYPE_TKIP; | ||
322 | else if (sc->sc_keytype == ATH9K_CIPHER_AES_CCM) | ||
323 | txctl->keytype = ATH9K_KEY_TYPE_AES; | ||
324 | } | ||
325 | |||
326 | /* Fill packet type */ | ||
327 | |||
328 | txctl->atype = get_hal_packet_type(hdr); | ||
329 | |||
330 | /* Fill qnum */ | ||
331 | |||
332 | txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); | ||
333 | txq = &sc->sc_txq[txctl->qnum]; | ||
334 | spin_lock_bh(&txq->axq_lock); | ||
335 | |||
336 | /* Try to avoid running out of descriptors */ | ||
337 | if (txq->axq_depth >= (ATH_TXBUF - 20)) { | ||
338 | DPRINTF(sc, ATH_DBG_FATAL, | ||
339 | "%s: TX queue: %d is full, depth: %d\n", | ||
340 | __func__, | ||
341 | txctl->qnum, | ||
342 | txq->axq_depth); | ||
343 | ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); | ||
344 | txq->stopped = 1; | ||
345 | spin_unlock_bh(&txq->axq_lock); | ||
346 | return -1; | ||
347 | } | ||
348 | |||
349 | spin_unlock_bh(&txq->axq_lock); | ||
350 | |||
351 | /* Fill rate */ | ||
352 | |||
353 | fill_min_rates(skb, txctl); | ||
354 | |||
355 | /* Fill flags */ | ||
356 | |||
357 | txctl->flags = ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ | ||
358 | |||
359 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
360 | tx_info->flags |= ATH9K_TXDESC_NOACK; | ||
361 | if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) | ||
362 | tx_info->flags |= ATH9K_TXDESC_RTSENA; | ||
363 | |||
364 | /* | ||
365 | * Setup for rate calculations. | ||
366 | */ | ||
367 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | ||
368 | rcs = tx_info_priv->rcs; | ||
369 | |||
370 | if (ieee80211_is_data(fc) && !txctl->use_minrate) { | ||
371 | |||
372 | /* Enable HT only for DATA frames and not for EAPOL */ | ||
373 | txctl->ht = (hw->conf.ht_conf.ht_supported && | ||
374 | (tx_info->flags & IEEE80211_TX_CTL_AMPDU)); | ||
375 | |||
376 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
377 | rcs[0].rix = (u8) | ||
378 | ath_tx_findindex(rt, txctl->mcast_rate); | ||
379 | |||
380 | /* | ||
381 | * mcast packets are not re-tried. | ||
382 | */ | ||
383 | rcs[0].tries = 1; | ||
384 | } | ||
385 | /* For HT capable stations, we save tidno for later use. | ||
386 | * We also override seqno set by upper layer with the one | ||
387 | * in tx aggregation state. | ||
388 | * | ||
389 | * First, the fragmentation stat is determined. | ||
390 | * If fragmentation is on, the sequence number is | ||
391 | * not overridden, since it has been | ||
392 | * incremented by the fragmentation routine. | ||
393 | */ | ||
394 | if (likely(!(txctl->flags & ATH9K_TXDESC_FRAG_IS_ON)) && | ||
395 | txctl->ht && sc->sc_txaggr) { | ||
396 | struct ath_atx_tid *tid; | ||
397 | |||
398 | tid = ATH_AN_2_TID(txctl->an, txctl->tidno); | ||
399 | |||
400 | hdr->seq_ctrl = cpu_to_le16(tid->seq_next << | ||
401 | IEEE80211_SEQ_SEQ_SHIFT); | ||
402 | txctl->seqno = tid->seq_next; | ||
403 | INCR(tid->seq_next, IEEE80211_SEQ_MAX); | ||
404 | } | ||
405 | } else { | ||
406 | /* for management and control frames, | ||
407 | * or for NULL and EAPOL frames */ | ||
408 | if (txctl->min_rate) | ||
409 | rcs[0].rix = ath_rate_findrateix(sc, txctl->min_rate); | ||
410 | else | ||
411 | rcs[0].rix = sc->sc_minrateix; | ||
412 | rcs[0].tries = ATH_MGT_TXMAXTRY; | ||
413 | } | ||
414 | rix = rcs[0].rix; | ||
415 | |||
416 | /* | ||
417 | * Calculate duration. This logically belongs in the 802.11 | ||
418 | * layer but it lacks sufficient information to calculate it. | ||
419 | */ | ||
420 | if ((txctl->flags & ATH9K_TXDESC_NOACK) == 0 && !ieee80211_is_ctl(fc)) { | ||
421 | u16 dur; | ||
422 | /* | ||
423 | * XXX not right with fragmentation. | ||
424 | */ | ||
425 | if (sc->sc_flags & ATH_PREAMBLE_SHORT) | ||
426 | dur = rt->info[rix].spAckDuration; | ||
427 | else | ||
428 | dur = rt->info[rix].lpAckDuration; | ||
429 | |||
430 | if (le16_to_cpu(hdr->frame_control) & | ||
431 | IEEE80211_FCTL_MOREFRAGS) { | ||
432 | dur += dur; /* Add additional 'SIFS + ACK' */ | ||
433 | |||
434 | /* | ||
435 | ** Compute size of next fragment in order to compute | ||
436 | ** durations needed to update NAV. | ||
437 | ** The last fragment uses the ACK duration only. | ||
438 | ** Add time for next fragment. | ||
439 | */ | ||
440 | dur += ath9k_hw_computetxtime(sc->sc_ah, rt, | ||
441 | txctl->nextfraglen, | ||
442 | rix, sc->sc_flags & ATH_PREAMBLE_SHORT); | ||
443 | } | ||
444 | |||
445 | if (ieee80211_has_morefrags(fc) || | ||
446 | (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { | ||
447 | /* | ||
448 | ** Force hardware to use computed duration for next | ||
449 | ** fragment by disabling multi-rate retry, which | ||
450 | ** updates duration based on the multi-rate | ||
451 | ** duration table. | ||
452 | */ | ||
453 | rcs[1].tries = rcs[2].tries = rcs[3].tries = 0; | ||
454 | rcs[1].rix = rcs[2].rix = rcs[3].rix = 0; | ||
455 | /* reset tries but keep rate index */ | ||
456 | rcs[0].tries = ATH_TXMAXTRY; | ||
457 | } | ||
458 | |||
459 | hdr->duration_id = cpu_to_le16(dur); | ||
460 | } | ||
461 | |||
462 | /* | ||
463 | * Determine if a tx interrupt should be generated for | ||
464 | * this descriptor. We take a tx interrupt to reap | ||
465 | * descriptors when the h/w hits an EOL condition or | ||
466 | * when the descriptor is specifically marked to generate | ||
467 | * an interrupt. We periodically mark descriptors in this | ||
468 | * way to insure timely replenishing of the supply needed | ||
469 | * for sending frames. Defering interrupts reduces system | ||
470 | * load and potentially allows more concurrent work to be | ||
471 | * done but if done to aggressively can cause senders to | ||
472 | * backup. | ||
473 | * | ||
474 | * NB: use >= to deal with sc_txintrperiod changing | ||
475 | * dynamically through sysctl. | ||
476 | */ | ||
477 | spin_lock_bh(&txq->axq_lock); | ||
478 | if ((++txq->axq_intrcnt >= sc->sc_txintrperiod)) { | ||
479 | txctl->flags |= ATH9K_TXDESC_INTREQ; | ||
480 | txq->axq_intrcnt = 0; | ||
481 | } | ||
482 | spin_unlock_bh(&txq->axq_lock); | ||
483 | |||
484 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
485 | antenna = sc->sc_mcastantenna + 1; | ||
486 | sc->sc_mcastantenna = (sc->sc_mcastantenna + 1) & 0x1; | ||
487 | } else | ||
488 | antenna = sc->sc_txantenna; | ||
489 | |||
490 | #ifdef USE_LEGACY_HAL | ||
491 | txctl->antenna = antenna; | ||
492 | #endif | ||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | /* To complete a chain of buffers associated a frame */ | ||
497 | |||
498 | static void ath_tx_complete_buf(struct ath_softc *sc, | ||
499 | struct ath_buf *bf, | ||
500 | struct list_head *bf_q, | ||
501 | int txok, int sendbar) | ||
502 | { | ||
503 | struct sk_buff *skb = bf->bf_mpdu; | ||
504 | struct ath_xmit_status tx_status; | ||
505 | dma_addr_t *pa; | ||
506 | |||
507 | /* | ||
508 | * Set retry information. | ||
509 | * NB: Don't use the information in the descriptor, because the frame | ||
510 | * could be software retried. | ||
511 | */ | ||
512 | tx_status.retries = bf->bf_retries; | ||
513 | tx_status.flags = 0; | ||
514 | |||
515 | if (sendbar) | ||
516 | tx_status.flags = ATH_TX_BAR; | ||
517 | |||
518 | if (!txok) { | ||
519 | tx_status.flags |= ATH_TX_ERROR; | ||
520 | |||
521 | if (bf->bf_isxretried) | ||
522 | tx_status.flags |= ATH_TX_XRETRY; | ||
523 | } | ||
524 | /* Unmap this frame */ | ||
525 | pa = get_dma_mem_context(bf, bf_dmacontext); | ||
526 | pci_unmap_single(sc->pdev, | ||
527 | *pa, | ||
528 | skb->len, | ||
529 | PCI_DMA_TODEVICE); | ||
530 | /* complete this frame */ | ||
531 | ath_tx_complete(sc, skb, &tx_status, bf->bf_node); | ||
532 | |||
533 | /* | ||
534 | * Return the list of ath_buf of this mpdu to free queue | ||
535 | */ | ||
536 | spin_lock_bh(&sc->sc_txbuflock); | ||
537 | list_splice_tail_init(bf_q, &sc->sc_txbuf); | ||
538 | spin_unlock_bh(&sc->sc_txbuflock); | ||
539 | } | ||
540 | |||
541 | /* | ||
542 | * queue up a dest/ac pair for tx scheduling | ||
543 | * NB: must be called with txq lock held | ||
544 | */ | ||
545 | |||
546 | static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) | ||
547 | { | ||
548 | struct ath_atx_ac *ac = tid->ac; | ||
549 | |||
550 | /* | ||
551 | * if tid is paused, hold off | ||
552 | */ | ||
553 | if (tid->paused) | ||
554 | return; | ||
555 | |||
556 | /* | ||
557 | * add tid to ac atmost once | ||
558 | */ | ||
559 | if (tid->sched) | ||
560 | return; | ||
561 | |||
562 | tid->sched = true; | ||
563 | list_add_tail(&tid->list, &ac->tid_q); | ||
564 | |||
565 | /* | ||
566 | * add node ac to txq atmost once | ||
567 | */ | ||
568 | if (ac->sched) | ||
569 | return; | ||
570 | |||
571 | ac->sched = true; | ||
572 | list_add_tail(&ac->list, &txq->axq_acq); | ||
573 | } | ||
574 | |||
575 | /* pause a tid */ | ||
576 | |||
577 | static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | ||
578 | { | ||
579 | struct ath_txq *txq = &sc->sc_txq[tid->ac->qnum]; | ||
580 | |||
581 | spin_lock_bh(&txq->axq_lock); | ||
582 | |||
583 | tid->paused++; | ||
584 | |||
585 | spin_unlock_bh(&txq->axq_lock); | ||
586 | } | ||
587 | |||
588 | /* resume a tid and schedule aggregate */ | ||
589 | |||
590 | void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | ||
591 | { | ||
592 | struct ath_txq *txq = &sc->sc_txq[tid->ac->qnum]; | ||
593 | |||
594 | ASSERT(tid->paused > 0); | ||
595 | spin_lock_bh(&txq->axq_lock); | ||
596 | |||
597 | tid->paused--; | ||
598 | |||
599 | if (tid->paused > 0) | ||
600 | goto unlock; | ||
601 | |||
602 | if (list_empty(&tid->buf_q)) | ||
603 | goto unlock; | ||
604 | |||
605 | /* | ||
606 | * Add this TID to scheduler and try to send out aggregates | ||
607 | */ | ||
608 | ath_tx_queue_tid(txq, tid); | ||
609 | ath_txq_schedule(sc, txq); | ||
610 | unlock: | ||
611 | spin_unlock_bh(&txq->axq_lock); | ||
612 | } | ||
613 | |||
614 | /* Compute the number of bad frames */ | ||
615 | |||
616 | static int ath_tx_num_badfrms(struct ath_softc *sc, | ||
617 | struct ath_buf *bf, int txok) | ||
618 | { | ||
619 | struct ath_node *an = bf->bf_node; | ||
620 | int isnodegone = (an->an_flags & ATH_NODE_CLEAN); | ||
621 | struct ath_buf *bf_last = bf->bf_lastbf; | ||
622 | struct ath_desc *ds = bf_last->bf_desc; | ||
623 | u16 seq_st = 0; | ||
624 | u32 ba[WME_BA_BMP_SIZE >> 5]; | ||
625 | int ba_index; | ||
626 | int nbad = 0; | ||
627 | int isaggr = 0; | ||
628 | |||
629 | if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) | ||
630 | return 0; | ||
631 | |||
632 | isaggr = bf->bf_isaggr; | ||
633 | if (isaggr) { | ||
634 | seq_st = ATH_DS_BA_SEQ(ds); | ||
635 | memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); | ||
636 | } | ||
637 | |||
638 | while (bf) { | ||
639 | ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); | ||
640 | if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) | ||
641 | nbad++; | ||
642 | |||
643 | bf = bf->bf_next; | ||
644 | } | ||
645 | |||
646 | return nbad; | ||
647 | } | ||
648 | |||
649 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf) | ||
650 | { | ||
651 | struct sk_buff *skb; | ||
652 | struct ieee80211_hdr *hdr; | ||
653 | |||
654 | bf->bf_isretried = 1; | ||
655 | bf->bf_retries++; | ||
656 | |||
657 | skb = bf->bf_mpdu; | ||
658 | hdr = (struct ieee80211_hdr *)skb->data; | ||
659 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); | ||
660 | } | ||
661 | |||
662 | /* Update block ack window */ | ||
663 | |||
664 | static void ath_tx_update_baw(struct ath_softc *sc, | ||
665 | struct ath_atx_tid *tid, int seqno) | ||
666 | { | ||
667 | int index, cindex; | ||
668 | |||
669 | index = ATH_BA_INDEX(tid->seq_start, seqno); | ||
670 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | ||
671 | |||
672 | tid->tx_buf[cindex] = NULL; | ||
673 | |||
674 | while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) { | ||
675 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | ||
676 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | * ath_pkt_dur - compute packet duration (NB: not NAV) | ||
682 | * | ||
683 | * rix - rate index | ||
684 | * pktlen - total bytes (delims + data + fcs + pads + pad delims) | ||
685 | * width - 0 for 20 MHz, 1 for 40 MHz | ||
686 | * half_gi - to use 4us v/s 3.6 us for symbol time | ||
687 | */ | ||
688 | |||
689 | static u32 ath_pkt_duration(struct ath_softc *sc, | ||
690 | u8 rix, | ||
691 | struct ath_buf *bf, | ||
692 | int width, | ||
693 | int half_gi, | ||
694 | bool shortPreamble) | ||
695 | { | ||
696 | const struct ath9k_rate_table *rt = sc->sc_currates; | ||
697 | u32 nbits, nsymbits, duration, nsymbols; | ||
698 | u8 rc; | ||
699 | int streams, pktlen; | ||
700 | |||
701 | pktlen = bf->bf_isaggr ? bf->bf_al : bf->bf_frmlen; | ||
702 | rc = rt->info[rix].rateCode; | ||
703 | |||
704 | /* | ||
705 | * for legacy rates, use old function to compute packet duration | ||
706 | */ | ||
707 | if (!IS_HT_RATE(rc)) | ||
708 | return ath9k_hw_computetxtime(sc->sc_ah, | ||
709 | rt, | ||
710 | pktlen, | ||
711 | rix, | ||
712 | shortPreamble); | ||
713 | /* | ||
714 | * find number of symbols: PLCP + data | ||
715 | */ | ||
716 | nbits = (pktlen << 3) + OFDM_PLCP_BITS; | ||
717 | nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; | ||
718 | nsymbols = (nbits + nsymbits - 1) / nsymbits; | ||
719 | |||
720 | if (!half_gi) | ||
721 | duration = SYMBOL_TIME(nsymbols); | ||
722 | else | ||
723 | duration = SYMBOL_TIME_HALFGI(nsymbols); | ||
724 | |||
725 | /* | ||
726 | * addup duration for legacy/ht training and signal fields | ||
727 | */ | ||
728 | streams = HT_RC_2_STREAMS(rc); | ||
729 | duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); | ||
730 | return duration; | ||
731 | } | ||
732 | |||
733 | /* Rate module function to set rate related fields in tx descriptor */ | ||
734 | |||
735 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | ||
736 | { | ||
737 | struct ath_hal *ah = sc->sc_ah; | ||
738 | const struct ath9k_rate_table *rt; | ||
739 | struct ath_desc *ds = bf->bf_desc; | ||
740 | struct ath_desc *lastds = bf->bf_lastbf->bf_desc; | ||
741 | struct ath9k_11n_rate_series series[4]; | ||
742 | int i, flags, rtsctsena = 0, dynamic_mimops = 0; | ||
743 | u32 ctsduration = 0; | ||
744 | u8 rix = 0, cix, ctsrate = 0; | ||
745 | u32 aggr_limit_with_rts = sc->sc_rtsaggrlimit; | ||
746 | struct ath_node *an = (struct ath_node *) bf->bf_node; | ||
747 | |||
748 | /* | ||
749 | * get the cix for the lowest valid rix. | ||
750 | */ | ||
751 | rt = sc->sc_currates; | ||
752 | for (i = 4; i--;) { | ||
753 | if (bf->bf_rcs[i].tries) { | ||
754 | rix = bf->bf_rcs[i].rix; | ||
755 | break; | ||
756 | } | ||
757 | } | ||
758 | flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)); | ||
759 | cix = rt->info[rix].controlRate; | ||
760 | |||
761 | /* | ||
762 | * If 802.11g protection is enabled, determine whether | ||
763 | * to use RTS/CTS or just CTS. Note that this is only | ||
764 | * done for OFDM/HT unicast frames. | ||
765 | */ | ||
766 | if (sc->sc_protmode != PROT_M_NONE && | ||
767 | (rt->info[rix].phy == PHY_OFDM || | ||
768 | rt->info[rix].phy == PHY_HT) && | ||
769 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | ||
770 | if (sc->sc_protmode == PROT_M_RTSCTS) | ||
771 | flags = ATH9K_TXDESC_RTSENA; | ||
772 | else if (sc->sc_protmode == PROT_M_CTSONLY) | ||
773 | flags = ATH9K_TXDESC_CTSENA; | ||
774 | |||
775 | cix = rt->info[sc->sc_protrix].controlRate; | ||
776 | rtsctsena = 1; | ||
777 | } | ||
778 | |||
779 | /* For 11n, the default behavior is to enable RTS for | ||
780 | * hw retried frames. We enable the global flag here and | ||
781 | * let rate series flags determine which rates will actually | ||
782 | * use RTS. | ||
783 | */ | ||
784 | if (ah->ah_caps.halHTSupport && bf->bf_isdata) { | ||
785 | BUG_ON(!an); | ||
786 | /* | ||
787 | * 802.11g protection not needed, use our default behavior | ||
788 | */ | ||
789 | if (!rtsctsena) | ||
790 | flags = ATH9K_TXDESC_RTSENA; | ||
791 | /* | ||
792 | * For dynamic MIMO PS, RTS needs to precede the first aggregate | ||
793 | * and the second aggregate should have any protection at all. | ||
794 | */ | ||
795 | if (an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) { | ||
796 | if (!bf->bf_aggrburst) { | ||
797 | flags = ATH9K_TXDESC_RTSENA; | ||
798 | dynamic_mimops = 1; | ||
799 | } else { | ||
800 | flags = 0; | ||
801 | } | ||
802 | } | ||
803 | } | ||
804 | |||
805 | /* | ||
806 | * Set protection if aggregate protection on | ||
807 | */ | ||
808 | if (sc->sc_config.ath_aggr_prot && | ||
809 | (!bf->bf_isaggr || (bf->bf_isaggr && bf->bf_al < 8192))) { | ||
810 | flags = ATH9K_TXDESC_RTSENA; | ||
811 | cix = rt->info[sc->sc_protrix].controlRate; | ||
812 | rtsctsena = 1; | ||
813 | } | ||
814 | |||
815 | /* | ||
816 | * For AR5416 - RTS cannot be followed by a frame larger than 8K. | ||
817 | */ | ||
818 | if (bf->bf_isaggr && (bf->bf_al > aggr_limit_with_rts)) { | ||
819 | /* | ||
820 | * Ensure that in the case of SM Dynamic power save | ||
821 | * while we are bursting the second aggregate the | ||
822 | * RTS is cleared. | ||
823 | */ | ||
824 | flags &= ~(ATH9K_TXDESC_RTSENA); | ||
825 | } | ||
826 | |||
827 | /* | ||
828 | * CTS transmit rate is derived from the transmit rate | ||
829 | * by looking in the h/w rate table. We must also factor | ||
830 | * in whether or not a short preamble is to be used. | ||
831 | */ | ||
832 | /* NB: cix is set above where RTS/CTS is enabled */ | ||
833 | BUG_ON(cix == 0xff); | ||
834 | ctsrate = rt->info[cix].rateCode | | ||
835 | (bf->bf_shpreamble ? rt->info[cix].shortPreamble : 0); | ||
836 | |||
837 | /* | ||
838 | * Setup HAL rate series | ||
839 | */ | ||
840 | memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); | ||
841 | |||
842 | for (i = 0; i < 4; i++) { | ||
843 | if (!bf->bf_rcs[i].tries) | ||
844 | continue; | ||
845 | |||
846 | rix = bf->bf_rcs[i].rix; | ||
847 | |||
848 | series[i].Rate = rt->info[rix].rateCode | | ||
849 | (bf->bf_shpreamble ? rt->info[rix].shortPreamble : 0); | ||
850 | |||
851 | series[i].Tries = bf->bf_rcs[i].tries; | ||
852 | |||
853 | series[i].RateFlags = ( | ||
854 | (bf->bf_rcs[i].flags & ATH_RC_RTSCTS_FLAG) ? | ||
855 | ATH9K_RATESERIES_RTS_CTS : 0) | | ||
856 | ((bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) ? | ||
857 | ATH9K_RATESERIES_2040 : 0) | | ||
858 | ((bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG) ? | ||
859 | ATH9K_RATESERIES_HALFGI : 0); | ||
860 | |||
861 | series[i].PktDuration = ath_pkt_duration( | ||
862 | sc, rix, bf, | ||
863 | (bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0, | ||
864 | (bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG), | ||
865 | bf->bf_shpreamble); | ||
866 | |||
867 | if ((an->an_smmode == ATH_SM_PWRSAV_STATIC) && | ||
868 | (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG) == 0) { | ||
869 | /* | ||
870 | * When sending to an HT node that has enabled static | ||
871 | * SM/MIMO power save, send at single stream rates but | ||
872 | * use maximum allowed transmit chains per user, | ||
873 | * hardware, regulatory, or country limits for | ||
874 | * better range. | ||
875 | */ | ||
876 | series[i].ChSel = sc->sc_tx_chainmask; | ||
877 | } else { | ||
878 | if (bf->bf_ht) | ||
879 | series[i].ChSel = | ||
880 | ath_chainmask_sel_logic(sc, an); | ||
881 | else | ||
882 | series[i].ChSel = sc->sc_tx_chainmask; | ||
883 | } | ||
884 | |||
885 | if (rtsctsena) | ||
886 | series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; | ||
887 | |||
888 | /* | ||
889 | * Set RTS for all rates if node is in dynamic powersave | ||
890 | * mode and we are using dual stream rates. | ||
891 | */ | ||
892 | if (dynamic_mimops && (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG)) | ||
893 | series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; | ||
894 | } | ||
895 | |||
896 | /* | ||
897 | * For non-HT devices, calculate RTS/CTS duration in software | ||
898 | * and disable multi-rate retry. | ||
899 | */ | ||
900 | if (flags && !ah->ah_caps.halHTSupport) { | ||
901 | /* | ||
902 | * Compute the transmit duration based on the frame | ||
903 | * size and the size of an ACK frame. We call into the | ||
904 | * HAL to do the computation since it depends on the | ||
905 | * characteristics of the actual PHY being used. | ||
906 | * | ||
907 | * NB: CTS is assumed the same size as an ACK so we can | ||
908 | * use the precalculated ACK durations. | ||
909 | */ | ||
910 | if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */ | ||
911 | ctsduration += bf->bf_shpreamble ? | ||
912 | rt->info[cix].spAckDuration : | ||
913 | rt->info[cix].lpAckDuration; | ||
914 | } | ||
915 | |||
916 | ctsduration += series[0].PktDuration; | ||
917 | |||
918 | if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */ | ||
919 | ctsduration += bf->bf_shpreamble ? | ||
920 | rt->info[rix].spAckDuration : | ||
921 | rt->info[rix].lpAckDuration; | ||
922 | } | ||
923 | |||
924 | /* | ||
925 | * Disable multi-rate retry when using RTS/CTS by clearing | ||
926 | * series 1, 2 and 3. | ||
927 | */ | ||
928 | memzero(&series[1], sizeof(struct ath9k_11n_rate_series) * 3); | ||
929 | } | ||
930 | |||
931 | /* | ||
932 | * set dur_update_en for l-sig computation except for PS-Poll frames | ||
933 | */ | ||
934 | ath9k_hw_set11n_ratescenario(ah, ds, lastds, | ||
935 | !bf->bf_ispspoll, | ||
936 | ctsrate, | ||
937 | ctsduration, | ||
938 | series, 4, flags); | ||
939 | if (sc->sc_config.ath_aggr_prot && flags) | ||
940 | ath9k_hw_set11n_burstduration(ah, ds, 8192); | ||
941 | } | ||
942 | |||
943 | /* | ||
944 | * Function to send a normal HT (non-AMPDU) frame | ||
945 | * NB: must be called with txq lock held | ||
946 | */ | ||
947 | |||
948 | static int ath_tx_send_normal(struct ath_softc *sc, | ||
949 | struct ath_txq *txq, | ||
950 | struct ath_atx_tid *tid, | ||
951 | struct list_head *bf_head) | ||
952 | { | ||
953 | struct ath_buf *bf; | ||
954 | struct sk_buff *skb; | ||
955 | struct ieee80211_tx_info *tx_info; | ||
956 | struct ath_tx_info_priv *tx_info_priv; | ||
957 | |||
958 | BUG_ON(list_empty(bf_head)); | ||
959 | |||
960 | bf = list_first_entry(bf_head, struct ath_buf, list); | ||
961 | bf->bf_isampdu = 0; /* regular HT frame */ | ||
962 | |||
963 | skb = (struct sk_buff *)bf->bf_mpdu; | ||
964 | tx_info = IEEE80211_SKB_CB(skb); | ||
965 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | ||
966 | memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); | ||
967 | |||
968 | /* update starting sequence number for subsequent ADDBA request */ | ||
969 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | ||
970 | |||
971 | /* Queue to h/w without aggregation */ | ||
972 | bf->bf_nframes = 1; | ||
973 | bf->bf_lastbf = bf->bf_lastfrm; /* one single frame */ | ||
974 | ath_buf_set_rate(sc, bf); | ||
975 | ath_tx_txqaddbuf(sc, txq, bf_head); | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | /* flush tid's software queue and send frames as non-ampdu's */ | ||
981 | |||
982 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | ||
983 | { | ||
984 | struct ath_txq *txq = &sc->sc_txq[tid->ac->qnum]; | ||
985 | struct ath_buf *bf; | ||
986 | struct list_head bf_head; | ||
987 | INIT_LIST_HEAD(&bf_head); | ||
988 | |||
989 | ASSERT(tid->paused > 0); | ||
990 | spin_lock_bh(&txq->axq_lock); | ||
991 | |||
992 | tid->paused--; | ||
993 | |||
994 | if (tid->paused > 0) { | ||
995 | spin_unlock_bh(&txq->axq_lock); | ||
996 | return; | ||
997 | } | ||
998 | |||
999 | while (!list_empty(&tid->buf_q)) { | ||
1000 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | ||
1001 | ASSERT(!bf->bf_isretried); | ||
1002 | list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); | ||
1003 | ath_tx_send_normal(sc, txq, tid, &bf_head); | ||
1004 | } | ||
1005 | |||
1006 | spin_unlock_bh(&txq->axq_lock); | ||
1007 | } | ||
1008 | |||
1009 | /* Completion routine of an aggregate */ | ||
1010 | |||
1011 | static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | ||
1012 | struct ath_txq *txq, | ||
1013 | struct ath_buf *bf, | ||
1014 | struct list_head *bf_q, | ||
1015 | int txok) | ||
1016 | { | ||
1017 | struct ath_node *an = bf->bf_node; | ||
1018 | struct ath_atx_tid *tid = ATH_AN_2_TID(an, bf->bf_tidno); | ||
1019 | struct ath_buf *bf_last = bf->bf_lastbf; | ||
1020 | struct ath_desc *ds = bf_last->bf_desc; | ||
1021 | struct ath_buf *bf_next, *bf_lastq = NULL; | ||
1022 | struct list_head bf_head, bf_pending; | ||
1023 | u16 seq_st = 0; | ||
1024 | u32 ba[WME_BA_BMP_SIZE >> 5]; | ||
1025 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0; | ||
1026 | int isnodegone = (an->an_flags & ATH_NODE_CLEAN); | ||
1027 | |||
1028 | isaggr = bf->bf_isaggr; | ||
1029 | if (isaggr) { | ||
1030 | if (txok) { | ||
1031 | if (ATH_DS_TX_BA(ds)) { | ||
1032 | /* | ||
1033 | * extract starting sequence and | ||
1034 | * block-ack bitmap | ||
1035 | */ | ||
1036 | seq_st = ATH_DS_BA_SEQ(ds); | ||
1037 | memcpy(ba, | ||
1038 | ATH_DS_BA_BITMAP(ds), | ||
1039 | WME_BA_BMP_SIZE >> 3); | ||
1040 | } else { | ||
1041 | memzero(ba, WME_BA_BMP_SIZE >> 3); | ||
1042 | |||
1043 | /* | ||
1044 | * AR5416 can become deaf/mute when BA | ||
1045 | * issue happens. Chip needs to be reset. | ||
1046 | * But AP code may have sychronization issues | ||
1047 | * when perform internal reset in this routine. | ||
1048 | * Only enable reset in STA mode for now. | ||
1049 | */ | ||
1050 | if (sc->sc_opmode == ATH9K_M_STA) | ||
1051 | needreset = 1; | ||
1052 | } | ||
1053 | } else { | ||
1054 | memzero(ba, WME_BA_BMP_SIZE >> 3); | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | INIT_LIST_HEAD(&bf_pending); | ||
1059 | INIT_LIST_HEAD(&bf_head); | ||
1060 | |||
1061 | while (bf) { | ||
1062 | txfail = txpending = 0; | ||
1063 | bf_next = bf->bf_next; | ||
1064 | |||
1065 | if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { | ||
1066 | /* transmit completion, subframe is | ||
1067 | * acked by block ack */ | ||
1068 | } else if (!isaggr && txok) { | ||
1069 | /* transmit completion */ | ||
1070 | } else { | ||
1071 | |||
1072 | if (!tid->cleanup_inprogress && !isnodegone && | ||
1073 | ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { | ||
1074 | if (bf->bf_retries < ATH_MAX_SW_RETRIES) { | ||
1075 | ath_tx_set_retry(sc, bf); | ||
1076 | txpending = 1; | ||
1077 | } else { | ||
1078 | bf->bf_isxretried = 1; | ||
1079 | txfail = 1; | ||
1080 | sendbar = 1; | ||
1081 | } | ||
1082 | } else { | ||
1083 | /* | ||
1084 | * cleanup in progress, just fail | ||
1085 | * the un-acked sub-frames | ||
1086 | */ | ||
1087 | txfail = 1; | ||
1088 | } | ||
1089 | } | ||
1090 | /* | ||
1091 | * Remove ath_buf's of this sub-frame from aggregate queue. | ||
1092 | */ | ||
1093 | if (bf_next == NULL) { /* last subframe in the aggregate */ | ||
1094 | ASSERT(bf->bf_lastfrm == bf_last); | ||
1095 | |||
1096 | /* | ||
1097 | * The last descriptor of the last sub frame could be | ||
1098 | * a holding descriptor for h/w. If that's the case, | ||
1099 | * bf->bf_lastfrm won't be in the bf_q. | ||
1100 | * Make sure we handle bf_q properly here. | ||
1101 | */ | ||
1102 | |||
1103 | if (!list_empty(bf_q)) { | ||
1104 | bf_lastq = list_entry(bf_q->prev, | ||
1105 | struct ath_buf, list); | ||
1106 | list_cut_position(&bf_head, | ||
1107 | bf_q, &bf_lastq->list); | ||
1108 | } else { | ||
1109 | /* | ||
1110 | * XXX: if the last subframe only has one | ||
1111 | * descriptor which is also being used as | ||
1112 | * a holding descriptor. Then the ath_buf | ||
1113 | * is not in the bf_q at all. | ||
1114 | */ | ||
1115 | INIT_LIST_HEAD(&bf_head); | ||
1116 | } | ||
1117 | } else { | ||
1118 | ASSERT(!list_empty(bf_q)); | ||
1119 | list_cut_position(&bf_head, | ||
1120 | bf_q, &bf->bf_lastfrm->list); | ||
1121 | } | ||
1122 | |||
1123 | if (!txpending) { | ||
1124 | /* | ||
1125 | * complete the acked-ones/xretried ones; update | ||
1126 | * block-ack window | ||
1127 | */ | ||
1128 | spin_lock_bh(&txq->axq_lock); | ||
1129 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | ||
1130 | spin_unlock_bh(&txq->axq_lock); | ||
1131 | |||
1132 | /* complete this sub-frame */ | ||
1133 | ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); | ||
1134 | } else { | ||
1135 | /* | ||
1136 | * retry the un-acked ones | ||
1137 | */ | ||
1138 | /* | ||
1139 | * XXX: if the last descriptor is holding descriptor, | ||
1140 | * in order to requeue the frame to software queue, we | ||
1141 | * need to allocate a new descriptor and | ||
1142 | * copy the content of holding descriptor to it. | ||
1143 | */ | ||
1144 | if (bf->bf_next == NULL && | ||
1145 | bf_last->bf_status & ATH_BUFSTATUS_STALE) { | ||
1146 | struct ath_buf *tbf; | ||
1147 | |||
1148 | /* allocate new descriptor */ | ||
1149 | spin_lock_bh(&sc->sc_txbuflock); | ||
1150 | ASSERT(!list_empty((&sc->sc_txbuf))); | ||
1151 | tbf = list_first_entry(&sc->sc_txbuf, | ||
1152 | struct ath_buf, list); | ||
1153 | list_del(&tbf->list); | ||
1154 | spin_unlock_bh(&sc->sc_txbuflock); | ||
1155 | |||
1156 | ATH_TXBUF_RESET(tbf); | ||
1157 | |||
1158 | /* copy descriptor content */ | ||
1159 | tbf->bf_mpdu = bf_last->bf_mpdu; | ||
1160 | tbf->bf_node = bf_last->bf_node; | ||
1161 | tbf->bf_buf_addr = bf_last->bf_buf_addr; | ||
1162 | *(tbf->bf_desc) = *(bf_last->bf_desc); | ||
1163 | |||
1164 | /* link it to the frame */ | ||
1165 | if (bf_lastq) { | ||
1166 | bf_lastq->bf_desc->ds_link = | ||
1167 | tbf->bf_daddr; | ||
1168 | bf->bf_lastfrm = tbf; | ||
1169 | ath9k_hw_cleartxdesc(sc->sc_ah, | ||
1170 | bf->bf_lastfrm->bf_desc); | ||
1171 | } else { | ||
1172 | tbf->bf_state = bf_last->bf_state; | ||
1173 | tbf->bf_lastfrm = tbf; | ||
1174 | ath9k_hw_cleartxdesc(sc->sc_ah, | ||
1175 | tbf->bf_lastfrm->bf_desc); | ||
1176 | |||
1177 | /* copy the DMA context */ | ||
1178 | copy_dma_mem_context( | ||
1179 | get_dma_mem_context(tbf, | ||
1180 | bf_dmacontext), | ||
1181 | get_dma_mem_context(bf_last, | ||
1182 | bf_dmacontext)); | ||
1183 | } | ||
1184 | list_add_tail(&tbf->list, &bf_head); | ||
1185 | } else { | ||
1186 | /* | ||
1187 | * Clear descriptor status words for | ||
1188 | * software retry | ||
1189 | */ | ||
1190 | ath9k_hw_cleartxdesc(sc->sc_ah, | ||
1191 | bf->bf_lastfrm->bf_desc); | ||
1192 | } | ||
1193 | |||
1194 | /* | ||
1195 | * Put this buffer to the temporary pending | ||
1196 | * queue to retain ordering | ||
1197 | */ | ||
1198 | list_splice_tail_init(&bf_head, &bf_pending); | ||
1199 | } | ||
1200 | |||
1201 | bf = bf_next; | ||
1202 | } | ||
1203 | |||
1204 | /* | ||
1205 | * node is already gone. no more assocication | ||
1206 | * with the node. the node might have been freed | ||
1207 | * any node acces can result in panic.note tid | ||
1208 | * is part of the node. | ||
1209 | */ | ||
1210 | if (isnodegone) | ||
1211 | return; | ||
1212 | |||
1213 | if (tid->cleanup_inprogress) { | ||
1214 | /* check to see if we're done with cleaning the h/w queue */ | ||
1215 | spin_lock_bh(&txq->axq_lock); | ||
1216 | |||
1217 | if (tid->baw_head == tid->baw_tail) { | ||
1218 | tid->addba_exchangecomplete = 0; | ||
1219 | tid->addba_exchangeattempts = 0; | ||
1220 | spin_unlock_bh(&txq->axq_lock); | ||
1221 | |||
1222 | tid->cleanup_inprogress = false; | ||
1223 | |||
1224 | /* send buffered frames as singles */ | ||
1225 | ath_tx_flush_tid(sc, tid); | ||
1226 | } else | ||
1227 | spin_unlock_bh(&txq->axq_lock); | ||
1228 | |||
1229 | return; | ||
1230 | } | ||
1231 | |||
1232 | /* | ||
1233 | * prepend un-acked frames to the beginning of the pending frame queue | ||
1234 | */ | ||
1235 | if (!list_empty(&bf_pending)) { | ||
1236 | spin_lock_bh(&txq->axq_lock); | ||
1237 | /* Note: we _prepend_, we _do_not_ at to | ||
1238 | * the end of the queue ! */ | ||
1239 | list_splice(&bf_pending, &tid->buf_q); | ||
1240 | ath_tx_queue_tid(txq, tid); | ||
1241 | spin_unlock_bh(&txq->axq_lock); | ||
1242 | } | ||
1243 | |||
1244 | if (needreset) | ||
1245 | ath_internal_reset(sc); | ||
1246 | |||
1247 | return; | ||
1248 | } | ||
1249 | |||
1250 | /* Process completed xmit descriptors from the specified queue */ | ||
1251 | |||
1252 | static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | ||
1253 | { | ||
1254 | struct ath_hal *ah = sc->sc_ah; | ||
1255 | struct ath_buf *bf, *lastbf, *bf_held = NULL; | ||
1256 | struct list_head bf_head; | ||
1257 | struct ath_desc *ds, *tmp_ds; | ||
1258 | struct sk_buff *skb; | ||
1259 | struct ieee80211_tx_info *tx_info; | ||
1260 | struct ath_tx_info_priv *tx_info_priv; | ||
1261 | int nacked, txok, nbad = 0, isrifs = 0; | ||
1262 | int status; | ||
1263 | |||
1264 | DPRINTF(sc, ATH_DBG_QUEUE, | ||
1265 | "%s: tx queue %d (%x), link %p\n", __func__, | ||
1266 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), | ||
1267 | txq->axq_link); | ||
1268 | |||
1269 | nacked = 0; | ||
1270 | for (;;) { | ||
1271 | spin_lock_bh(&txq->axq_lock); | ||
1272 | txq->axq_intrcnt = 0; /* reset periodic desc intr count */ | ||
1273 | if (list_empty(&txq->axq_q)) { | ||
1274 | txq->axq_link = NULL; | ||
1275 | txq->axq_linkbuf = NULL; | ||
1276 | spin_unlock_bh(&txq->axq_lock); | ||
1277 | break; | ||
1278 | } | ||
1279 | bf = list_first_entry(&txq->axq_q, struct ath_buf, list); | ||
1280 | |||
1281 | /* | ||
1282 | * There is a race condition that a BH gets scheduled | ||
1283 | * after sw writes TxE and before hw re-load the last | ||
1284 | * descriptor to get the newly chained one. | ||
1285 | * Software must keep the last DONE descriptor as a | ||
1286 | * holding descriptor - software does so by marking | ||
1287 | * it with the STALE flag. | ||
1288 | */ | ||
1289 | bf_held = NULL; | ||
1290 | if (bf->bf_status & ATH_BUFSTATUS_STALE) { | ||
1291 | bf_held = bf; | ||
1292 | if (list_is_last(&bf_held->list, &txq->axq_q)) { | ||
1293 | /* FIXME: | ||
1294 | * The holding descriptor is the last | ||
1295 | * descriptor in queue. It's safe to remove | ||
1296 | * the last holding descriptor in BH context. | ||
1297 | */ | ||
1298 | spin_unlock_bh(&txq->axq_lock); | ||
1299 | break; | ||
1300 | } else { | ||
1301 | /* Lets work with the next buffer now */ | ||
1302 | bf = list_entry(bf_held->list.next, | ||
1303 | struct ath_buf, list); | ||
1304 | } | ||
1305 | } | ||
1306 | |||
1307 | lastbf = bf->bf_lastbf; | ||
1308 | ds = lastbf->bf_desc; /* NB: last decriptor */ | ||
1309 | |||
1310 | status = ath9k_hw_txprocdesc(ah, ds); | ||
1311 | if (status == -EINPROGRESS) { | ||
1312 | spin_unlock_bh(&txq->axq_lock); | ||
1313 | break; | ||
1314 | } | ||
1315 | if (bf->bf_desc == txq->axq_lastdsWithCTS) | ||
1316 | txq->axq_lastdsWithCTS = NULL; | ||
1317 | if (ds == txq->axq_gatingds) | ||
1318 | txq->axq_gatingds = NULL; | ||
1319 | |||
1320 | /* | ||
1321 | * Remove ath_buf's of the same transmit unit from txq, | ||
1322 | * however leave the last descriptor back as the holding | ||
1323 | * descriptor for hw. | ||
1324 | */ | ||
1325 | lastbf->bf_status |= ATH_BUFSTATUS_STALE; | ||
1326 | INIT_LIST_HEAD(&bf_head); | ||
1327 | |||
1328 | if (!list_is_singular(&lastbf->list)) | ||
1329 | list_cut_position(&bf_head, | ||
1330 | &txq->axq_q, lastbf->list.prev); | ||
1331 | |||
1332 | txq->axq_depth--; | ||
1333 | |||
1334 | if (bf->bf_isaggr) | ||
1335 | txq->axq_aggr_depth--; | ||
1336 | |||
1337 | txok = (ds->ds_txstat.ts_status == 0); | ||
1338 | |||
1339 | spin_unlock_bh(&txq->axq_lock); | ||
1340 | |||
1341 | if (bf_held) { | ||
1342 | list_del(&bf_held->list); | ||
1343 | spin_lock_bh(&sc->sc_txbuflock); | ||
1344 | list_add_tail(&bf_held->list, &sc->sc_txbuf); | ||
1345 | spin_unlock_bh(&sc->sc_txbuflock); | ||
1346 | } | ||
1347 | |||
1348 | if (!bf->bf_isampdu) { | ||
1349 | /* | ||
1350 | * This frame is sent out as a single frame. | ||
1351 | * Use hardware retry status for this frame. | ||
1352 | */ | ||
1353 | bf->bf_retries = ds->ds_txstat.ts_longretry; | ||
1354 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) | ||
1355 | bf->bf_isxretried = 1; | ||
1356 | nbad = 0; | ||
1357 | } else { | ||
1358 | nbad = ath_tx_num_badfrms(sc, bf, txok); | ||
1359 | } | ||
1360 | skb = bf->bf_mpdu; | ||
1361 | tx_info = IEEE80211_SKB_CB(skb); | ||
1362 | tx_info_priv = (struct ath_tx_info_priv *) | ||
1363 | tx_info->driver_data[0]; | ||
1364 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | ||
1365 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
1366 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | ||
1367 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | ||
1368 | if (ds->ds_txstat.ts_status == 0) | ||
1369 | nacked++; | ||
1370 | |||
1371 | if (bf->bf_isdata) { | ||
1372 | if (isrifs) | ||
1373 | tmp_ds = bf->bf_rifslast->bf_desc; | ||
1374 | else | ||
1375 | tmp_ds = ds; | ||
1376 | memcpy(&tx_info_priv->tx, | ||
1377 | &tmp_ds->ds_txstat, | ||
1378 | sizeof(tx_info_priv->tx)); | ||
1379 | tx_info_priv->n_frames = bf->bf_nframes; | ||
1380 | tx_info_priv->n_bad_frames = nbad; | ||
1381 | } | ||
1382 | } | ||
1383 | |||
1384 | /* | ||
1385 | * Complete this transmit unit | ||
1386 | */ | ||
1387 | if (bf->bf_isampdu) | ||
1388 | ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok); | ||
1389 | else | ||
1390 | ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); | ||
1391 | |||
1392 | /* Wake up mac80211 queue */ | ||
1393 | |||
1394 | spin_lock_bh(&txq->axq_lock); | ||
1395 | if (txq->stopped && ath_txq_depth(sc, txq->axq_qnum) <= | ||
1396 | (ATH_TXBUF - 20)) { | ||
1397 | int qnum; | ||
1398 | qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); | ||
1399 | if (qnum != -1) { | ||
1400 | ieee80211_wake_queue(sc->hw, qnum); | ||
1401 | txq->stopped = 0; | ||
1402 | } | ||
1403 | |||
1404 | } | ||
1405 | |||
1406 | /* | ||
1407 | * schedule any pending packets if aggregation is enabled | ||
1408 | */ | ||
1409 | if (sc->sc_txaggr) | ||
1410 | ath_txq_schedule(sc, txq); | ||
1411 | spin_unlock_bh(&txq->axq_lock); | ||
1412 | } | ||
1413 | return nacked; | ||
1414 | } | ||
1415 | |||
1416 | static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq) | ||
1417 | { | ||
1418 | struct ath_hal *ah = sc->sc_ah; | ||
1419 | |||
1420 | (void) ath9k_hw_stoptxdma(ah, txq->axq_qnum); | ||
1421 | DPRINTF(sc, ATH_DBG_XMIT, "%s: tx queue [%u] %x, link %p\n", | ||
1422 | __func__, txq->axq_qnum, | ||
1423 | ath9k_hw_gettxbuf(ah, txq->axq_qnum), txq->axq_link); | ||
1424 | } | ||
1425 | |||
1426 | /* Drain only the data queues */ | ||
1427 | |||
1428 | static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) | ||
1429 | { | ||
1430 | struct ath_hal *ah = sc->sc_ah; | ||
1431 | int i; | ||
1432 | int npend = 0; | ||
1433 | enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); | ||
1434 | |||
1435 | /* XXX return value */ | ||
1436 | if (!sc->sc_invalid) { | ||
1437 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
1438 | if (ATH_TXQ_SETUP(sc, i)) { | ||
1439 | ath_tx_stopdma(sc, &sc->sc_txq[i]); | ||
1440 | |||
1441 | /* The TxDMA may not really be stopped. | ||
1442 | * Double check the hal tx pending count */ | ||
1443 | npend += ath9k_hw_numtxpending(ah, | ||
1444 | sc->sc_txq[i].axq_qnum); | ||
1445 | } | ||
1446 | } | ||
1447 | } | ||
1448 | |||
1449 | if (npend) { | ||
1450 | int status; | ||
1451 | |||
1452 | /* TxDMA not stopped, reset the hal */ | ||
1453 | DPRINTF(sc, ATH_DBG_XMIT, | ||
1454 | "%s: Unable to stop TxDMA. Reset HAL!\n", __func__); | ||
1455 | |||
1456 | spin_lock_bh(&sc->sc_resetlock); | ||
1457 | if (!ath9k_hw_reset(ah, sc->sc_opmode, | ||
1458 | &sc->sc_curchan, ht_macmode, | ||
1459 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
1460 | sc->sc_ht_extprotspacing, true, &status)) { | ||
1461 | |||
1462 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1463 | "%s: unable to reset hardware; hal status %u\n", | ||
1464 | __func__, | ||
1465 | status); | ||
1466 | } | ||
1467 | spin_unlock_bh(&sc->sc_resetlock); | ||
1468 | } | ||
1469 | |||
1470 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
1471 | if (ATH_TXQ_SETUP(sc, i)) | ||
1472 | ath_tx_draintxq(sc, &sc->sc_txq[i], retry_tx); | ||
1473 | } | ||
1474 | } | ||
1475 | |||
1476 | /* Add a sub-frame to block ack window */ | ||
1477 | |||
1478 | static void ath_tx_addto_baw(struct ath_softc *sc, | ||
1479 | struct ath_atx_tid *tid, | ||
1480 | struct ath_buf *bf) | ||
1481 | { | ||
1482 | int index, cindex; | ||
1483 | |||
1484 | if (bf->bf_isretried) | ||
1485 | return; | ||
1486 | |||
1487 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); | ||
1488 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | ||
1489 | |||
1490 | ASSERT(tid->tx_buf[cindex] == NULL); | ||
1491 | tid->tx_buf[cindex] = bf; | ||
1492 | |||
1493 | if (index >= ((tid->baw_tail - tid->baw_head) & | ||
1494 | (ATH_TID_MAX_BUFS - 1))) { | ||
1495 | tid->baw_tail = cindex; | ||
1496 | INCR(tid->baw_tail, ATH_TID_MAX_BUFS); | ||
1497 | } | ||
1498 | } | ||
1499 | |||
1500 | /* | ||
1501 | * Function to send an A-MPDU | ||
1502 | * NB: must be called with txq lock held | ||
1503 | */ | ||
1504 | |||
1505 | static int ath_tx_send_ampdu(struct ath_softc *sc, | ||
1506 | struct ath_txq *txq, | ||
1507 | struct ath_atx_tid *tid, | ||
1508 | struct list_head *bf_head, | ||
1509 | struct ath_tx_control *txctl) | ||
1510 | { | ||
1511 | struct ath_buf *bf; | ||
1512 | struct sk_buff *skb; | ||
1513 | struct ieee80211_tx_info *tx_info; | ||
1514 | struct ath_tx_info_priv *tx_info_priv; | ||
1515 | |||
1516 | BUG_ON(list_empty(bf_head)); | ||
1517 | |||
1518 | bf = list_first_entry(bf_head, struct ath_buf, list); | ||
1519 | bf->bf_isampdu = 1; | ||
1520 | bf->bf_seqno = txctl->seqno; /* save seqno and tidno in buffer */ | ||
1521 | bf->bf_tidno = txctl->tidno; | ||
1522 | |||
1523 | /* | ||
1524 | * Do not queue to h/w when any of the following conditions is true: | ||
1525 | * - there are pending frames in software queue | ||
1526 | * - the TID is currently paused for ADDBA/BAR request | ||
1527 | * - seqno is not within block-ack window | ||
1528 | * - h/w queue depth exceeds low water mark | ||
1529 | */ | ||
1530 | if (!list_empty(&tid->buf_q) || tid->paused || | ||
1531 | !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || | ||
1532 | txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { | ||
1533 | /* | ||
1534 | * Add this frame to software queue for scheduling later | ||
1535 | * for aggregation. | ||
1536 | */ | ||
1537 | list_splice_tail_init(bf_head, &tid->buf_q); | ||
1538 | ath_tx_queue_tid(txq, tid); | ||
1539 | return 0; | ||
1540 | } | ||
1541 | |||
1542 | skb = (struct sk_buff *)bf->bf_mpdu; | ||
1543 | tx_info = IEEE80211_SKB_CB(skb); | ||
1544 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | ||
1545 | memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); | ||
1546 | |||
1547 | /* Add sub-frame to BAW */ | ||
1548 | ath_tx_addto_baw(sc, tid, bf); | ||
1549 | |||
1550 | /* Queue to h/w without aggregation */ | ||
1551 | bf->bf_nframes = 1; | ||
1552 | bf->bf_lastbf = bf->bf_lastfrm; /* one single frame */ | ||
1553 | ath_buf_set_rate(sc, bf); | ||
1554 | ath_tx_txqaddbuf(sc, txq, bf_head); | ||
1555 | return 0; | ||
1556 | } | ||
1557 | |||
1558 | /* | ||
1559 | * looks up the rate | ||
1560 | * returns aggr limit based on lowest of the rates | ||
1561 | */ | ||
1562 | |||
1563 | static u32 ath_lookup_rate(struct ath_softc *sc, | ||
1564 | struct ath_buf *bf) | ||
1565 | { | ||
1566 | const struct ath9k_rate_table *rt = sc->sc_currates; | ||
1567 | struct sk_buff *skb; | ||
1568 | struct ieee80211_tx_info *tx_info; | ||
1569 | struct ath_tx_info_priv *tx_info_priv; | ||
1570 | u32 max_4ms_framelen, frame_length; | ||
1571 | u16 aggr_limit, legacy = 0, maxampdu; | ||
1572 | int i; | ||
1573 | |||
1574 | |||
1575 | skb = (struct sk_buff *)bf->bf_mpdu; | ||
1576 | tx_info = IEEE80211_SKB_CB(skb); | ||
1577 | tx_info_priv = (struct ath_tx_info_priv *) | ||
1578 | tx_info->driver_data[0]; | ||
1579 | memcpy(bf->bf_rcs, | ||
1580 | tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); | ||
1581 | |||
1582 | /* | ||
1583 | * Find the lowest frame length among the rate series that will have a | ||
1584 | * 4ms transmit duration. | ||
1585 | * TODO - TXOP limit needs to be considered. | ||
1586 | */ | ||
1587 | max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; | ||
1588 | |||
1589 | for (i = 0; i < 4; i++) { | ||
1590 | if (bf->bf_rcs[i].tries) { | ||
1591 | frame_length = bf->bf_rcs[i].max_4ms_framelen; | ||
1592 | |||
1593 | if (rt->info[bf->bf_rcs[i].rix].phy != PHY_HT) { | ||
1594 | legacy = 1; | ||
1595 | break; | ||
1596 | } | ||
1597 | |||
1598 | max_4ms_framelen = min(max_4ms_framelen, frame_length); | ||
1599 | } | ||
1600 | } | ||
1601 | |||
1602 | /* | ||
1603 | * limit aggregate size by the minimum rate if rate selected is | ||
1604 | * not a probe rate, if rate selected is a probe rate then | ||
1605 | * avoid aggregation of this packet. | ||
1606 | */ | ||
1607 | if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) | ||
1608 | return 0; | ||
1609 | |||
1610 | aggr_limit = min(max_4ms_framelen, | ||
1611 | (u32)ATH_AMPDU_LIMIT_DEFAULT); | ||
1612 | |||
1613 | /* | ||
1614 | * h/w can accept aggregates upto 16 bit lengths (65535). | ||
1615 | * The IE, however can hold upto 65536, which shows up here | ||
1616 | * as zero. Ignore 65536 since we are constrained by hw. | ||
1617 | */ | ||
1618 | maxampdu = sc->sc_ht_info.maxampdu; | ||
1619 | if (maxampdu) | ||
1620 | aggr_limit = min(aggr_limit, maxampdu); | ||
1621 | |||
1622 | return aggr_limit; | ||
1623 | } | ||
1624 | |||
1625 | /* | ||
1626 | * returns the number of delimiters to be added to | ||
1627 | * meet the minimum required mpdudensity. | ||
1628 | * caller should make sure that the rate is HT rate . | ||
1629 | */ | ||
1630 | |||
1631 | static int ath_compute_num_delims(struct ath_softc *sc, | ||
1632 | struct ath_buf *bf, | ||
1633 | u16 frmlen) | ||
1634 | { | ||
1635 | const struct ath9k_rate_table *rt = sc->sc_currates; | ||
1636 | u32 nsymbits, nsymbols, mpdudensity; | ||
1637 | u16 minlen; | ||
1638 | u8 rc, flags, rix; | ||
1639 | int width, half_gi, ndelim, mindelim; | ||
1640 | |||
1641 | /* Select standard number of delimiters based on frame length alone */ | ||
1642 | ndelim = ATH_AGGR_GET_NDELIM(frmlen); | ||
1643 | |||
1644 | /* | ||
1645 | * If encryption enabled, hardware requires some more padding between | ||
1646 | * subframes. | ||
1647 | * TODO - this could be improved to be dependent on the rate. | ||
1648 | * The hardware can keep up at lower rates, but not higher rates | ||
1649 | */ | ||
1650 | if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) | ||
1651 | ndelim += ATH_AGGR_ENCRYPTDELIM; | ||
1652 | |||
1653 | /* | ||
1654 | * Convert desired mpdu density from microeconds to bytes based | ||
1655 | * on highest rate in rate series (i.e. first rate) to determine | ||
1656 | * required minimum length for subframe. Take into account | ||
1657 | * whether high rate is 20 or 40Mhz and half or full GI. | ||
1658 | */ | ||
1659 | mpdudensity = sc->sc_ht_info.mpdudensity; | ||
1660 | |||
1661 | /* | ||
1662 | * If there is no mpdu density restriction, no further calculation | ||
1663 | * is needed. | ||
1664 | */ | ||
1665 | if (mpdudensity == 0) | ||
1666 | return ndelim; | ||
1667 | |||
1668 | rix = bf->bf_rcs[0].rix; | ||
1669 | flags = bf->bf_rcs[0].flags; | ||
1670 | rc = rt->info[rix].rateCode; | ||
1671 | width = (flags & ATH_RC_CW40_FLAG) ? 1 : 0; | ||
1672 | half_gi = (flags & ATH_RC_SGI_FLAG) ? 1 : 0; | ||
1673 | |||
1674 | if (half_gi) | ||
1675 | nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); | ||
1676 | else | ||
1677 | nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity); | ||
1678 | |||
1679 | if (nsymbols == 0) | ||
1680 | nsymbols = 1; | ||
1681 | |||
1682 | nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; | ||
1683 | minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; | ||
1684 | |||
1685 | /* Is frame shorter than required minimum length? */ | ||
1686 | if (frmlen < minlen) { | ||
1687 | /* Get the minimum number of delimiters required. */ | ||
1688 | mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ; | ||
1689 | ndelim = max(mindelim, ndelim); | ||
1690 | } | ||
1691 | |||
1692 | return ndelim; | ||
1693 | } | ||
1694 | |||
1695 | /* | ||
1696 | * For aggregation from software buffer queue. | ||
1697 | * NB: must be called with txq lock held | ||
1698 | */ | ||
1699 | |||
1700 | static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | ||
1701 | struct ath_atx_tid *tid, | ||
1702 | struct list_head *bf_q, | ||
1703 | struct ath_buf **bf_last, | ||
1704 | struct aggr_rifs_param *param, | ||
1705 | int *prev_frames) | ||
1706 | { | ||
1707 | #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) | ||
1708 | struct ath_buf *bf, *tbf, *bf_first, *bf_prev = NULL; | ||
1709 | struct list_head bf_head; | ||
1710 | int rl = 0, nframes = 0, ndelim; | ||
1711 | u16 aggr_limit = 0, al = 0, bpad = 0, | ||
1712 | al_delta, h_baw = tid->baw_size / 2; | ||
1713 | enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; | ||
1714 | int prev_al = 0, is_ds_rate = 0; | ||
1715 | INIT_LIST_HEAD(&bf_head); | ||
1716 | |||
1717 | BUG_ON(list_empty(&tid->buf_q)); | ||
1718 | |||
1719 | bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); | ||
1720 | |||
1721 | do { | ||
1722 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | ||
1723 | |||
1724 | /* | ||
1725 | * do not step over block-ack window | ||
1726 | */ | ||
1727 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { | ||
1728 | status = ATH_AGGR_BAW_CLOSED; | ||
1729 | break; | ||
1730 | } | ||
1731 | |||
1732 | if (!rl) { | ||
1733 | aggr_limit = ath_lookup_rate(sc, bf); | ||
1734 | rl = 1; | ||
1735 | /* | ||
1736 | * Is rate dual stream | ||
1737 | */ | ||
1738 | is_ds_rate = | ||
1739 | (bf->bf_rcs[0].flags & ATH_RC_DS_FLAG) ? 1 : 0; | ||
1740 | } | ||
1741 | |||
1742 | /* | ||
1743 | * do not exceed aggregation limit | ||
1744 | */ | ||
1745 | al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; | ||
1746 | |||
1747 | if (nframes && (aggr_limit < | ||
1748 | (al + bpad + al_delta + prev_al))) { | ||
1749 | status = ATH_AGGR_LIMITED; | ||
1750 | break; | ||
1751 | } | ||
1752 | |||
1753 | /* | ||
1754 | * do not exceed subframe limit | ||
1755 | */ | ||
1756 | if ((nframes + *prev_frames) >= | ||
1757 | min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { | ||
1758 | status = ATH_AGGR_LIMITED; | ||
1759 | break; | ||
1760 | } | ||
1761 | |||
1762 | /* | ||
1763 | * add padding for previous frame to aggregation length | ||
1764 | */ | ||
1765 | al += bpad + al_delta; | ||
1766 | |||
1767 | /* | ||
1768 | * Get the delimiters needed to meet the MPDU | ||
1769 | * density for this node. | ||
1770 | */ | ||
1771 | ndelim = ath_compute_num_delims(sc, bf_first, bf->bf_frmlen); | ||
1772 | |||
1773 | bpad = PADBYTES(al_delta) + (ndelim << 2); | ||
1774 | |||
1775 | bf->bf_next = NULL; | ||
1776 | bf->bf_lastfrm->bf_desc->ds_link = 0; | ||
1777 | |||
1778 | /* | ||
1779 | * this packet is part of an aggregate | ||
1780 | * - remove all descriptors belonging to this frame from | ||
1781 | * software queue | ||
1782 | * - add it to block ack window | ||
1783 | * - set up descriptors for aggregation | ||
1784 | */ | ||
1785 | list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); | ||
1786 | ath_tx_addto_baw(sc, tid, bf); | ||
1787 | |||
1788 | list_for_each_entry(tbf, &bf_head, list) { | ||
1789 | ath9k_hw_set11n_aggr_middle(sc->sc_ah, | ||
1790 | tbf->bf_desc, ndelim); | ||
1791 | } | ||
1792 | |||
1793 | /* | ||
1794 | * link buffers of this frame to the aggregate | ||
1795 | */ | ||
1796 | list_splice_tail_init(&bf_head, bf_q); | ||
1797 | nframes++; | ||
1798 | |||
1799 | if (bf_prev) { | ||
1800 | bf_prev->bf_next = bf; | ||
1801 | bf_prev->bf_lastfrm->bf_desc->ds_link = bf->bf_daddr; | ||
1802 | } | ||
1803 | bf_prev = bf; | ||
1804 | |||
1805 | #ifdef AGGR_NOSHORT | ||
1806 | /* | ||
1807 | * terminate aggregation on a small packet boundary | ||
1808 | */ | ||
1809 | if (bf->bf_frmlen < ATH_AGGR_MINPLEN) { | ||
1810 | status = ATH_AGGR_SHORTPKT; | ||
1811 | break; | ||
1812 | } | ||
1813 | #endif | ||
1814 | } while (!list_empty(&tid->buf_q)); | ||
1815 | |||
1816 | bf_first->bf_al = al; | ||
1817 | bf_first->bf_nframes = nframes; | ||
1818 | *bf_last = bf_prev; | ||
1819 | return status; | ||
1820 | #undef PADBYTES | ||
1821 | } | ||
1822 | |||
1823 | /* | ||
1824 | * process pending frames possibly doing a-mpdu aggregation | ||
1825 | * NB: must be called with txq lock held | ||
1826 | */ | ||
1827 | |||
1828 | static void ath_tx_sched_aggr(struct ath_softc *sc, | ||
1829 | struct ath_txq *txq, struct ath_atx_tid *tid) | ||
1830 | { | ||
1831 | struct ath_buf *bf, *tbf, *bf_last, *bf_lastaggr = NULL; | ||
1832 | enum ATH_AGGR_STATUS status; | ||
1833 | struct list_head bf_q; | ||
1834 | struct aggr_rifs_param param = {0, 0, 0, 0, NULL}; | ||
1835 | int prev_frames = 0; | ||
1836 | |||
1837 | do { | ||
1838 | if (list_empty(&tid->buf_q)) | ||
1839 | return; | ||
1840 | |||
1841 | INIT_LIST_HEAD(&bf_q); | ||
1842 | |||
1843 | status = ath_tx_form_aggr(sc, tid, &bf_q, &bf_lastaggr, ¶m, | ||
1844 | &prev_frames); | ||
1845 | |||
1846 | /* | ||
1847 | * no frames picked up to be aggregated; block-ack | ||
1848 | * window is not open | ||
1849 | */ | ||
1850 | if (list_empty(&bf_q)) | ||
1851 | break; | ||
1852 | |||
1853 | bf = list_first_entry(&bf_q, struct ath_buf, list); | ||
1854 | bf_last = list_entry(bf_q.prev, struct ath_buf, list); | ||
1855 | bf->bf_lastbf = bf_last; | ||
1856 | |||
1857 | /* | ||
1858 | * if only one frame, send as non-aggregate | ||
1859 | */ | ||
1860 | if (bf->bf_nframes == 1) { | ||
1861 | ASSERT(bf->bf_lastfrm == bf_last); | ||
1862 | |||
1863 | bf->bf_isaggr = 0; | ||
1864 | /* | ||
1865 | * clear aggr bits for every descriptor | ||
1866 | * XXX TODO: is there a way to optimize it? | ||
1867 | */ | ||
1868 | list_for_each_entry(tbf, &bf_q, list) { | ||
1869 | ath9k_hw_clr11n_aggr(sc->sc_ah, tbf->bf_desc); | ||
1870 | } | ||
1871 | |||
1872 | ath_buf_set_rate(sc, bf); | ||
1873 | ath_tx_txqaddbuf(sc, txq, &bf_q); | ||
1874 | continue; | ||
1875 | } | ||
1876 | |||
1877 | /* | ||
1878 | * setup first desc with rate and aggr info | ||
1879 | */ | ||
1880 | bf->bf_isaggr = 1; | ||
1881 | ath_buf_set_rate(sc, bf); | ||
1882 | ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); | ||
1883 | |||
1884 | /* | ||
1885 | * anchor last frame of aggregate correctly | ||
1886 | */ | ||
1887 | ASSERT(bf_lastaggr); | ||
1888 | ASSERT(bf_lastaggr->bf_lastfrm == bf_last); | ||
1889 | tbf = bf_lastaggr; | ||
1890 | ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc); | ||
1891 | |||
1892 | /* XXX: We don't enter into this loop, consider removing this */ | ||
1893 | while (!list_empty(&bf_q) && !list_is_last(&tbf->list, &bf_q)) { | ||
1894 | tbf = list_entry(tbf->list.next, struct ath_buf, list); | ||
1895 | ath9k_hw_set11n_aggr_last(sc->sc_ah, tbf->bf_desc); | ||
1896 | } | ||
1897 | |||
1898 | txq->axq_aggr_depth++; | ||
1899 | |||
1900 | /* | ||
1901 | * Normal aggregate, queue to hardware | ||
1902 | */ | ||
1903 | ath_tx_txqaddbuf(sc, txq, &bf_q); | ||
1904 | |||
1905 | } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && | ||
1906 | status != ATH_AGGR_BAW_CLOSED); | ||
1907 | } | ||
1908 | |||
1909 | /* Called with txq lock held */ | ||
1910 | |||
1911 | static void ath_tid_drain(struct ath_softc *sc, | ||
1912 | struct ath_txq *txq, | ||
1913 | struct ath_atx_tid *tid, | ||
1914 | bool bh_flag) | ||
1915 | { | ||
1916 | struct ath_buf *bf; | ||
1917 | struct list_head bf_head; | ||
1918 | INIT_LIST_HEAD(&bf_head); | ||
1919 | |||
1920 | for (;;) { | ||
1921 | if (list_empty(&tid->buf_q)) | ||
1922 | break; | ||
1923 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | ||
1924 | |||
1925 | list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); | ||
1926 | |||
1927 | /* update baw for software retried frame */ | ||
1928 | if (bf->bf_isretried) | ||
1929 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | ||
1930 | |||
1931 | /* | ||
1932 | * do not indicate packets while holding txq spinlock. | ||
1933 | * unlock is intentional here | ||
1934 | */ | ||
1935 | if (likely(bh_flag)) | ||
1936 | spin_unlock_bh(&txq->axq_lock); | ||
1937 | else | ||
1938 | spin_unlock(&txq->axq_lock); | ||
1939 | |||
1940 | /* complete this sub-frame */ | ||
1941 | ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); | ||
1942 | |||
1943 | if (likely(bh_flag)) | ||
1944 | spin_lock_bh(&txq->axq_lock); | ||
1945 | else | ||
1946 | spin_lock(&txq->axq_lock); | ||
1947 | } | ||
1948 | |||
1949 | /* | ||
1950 | * TODO: For frame(s) that are in the retry state, we will reuse the | ||
1951 | * sequence number(s) without setting the retry bit. The | ||
1952 | * alternative is to give up on these and BAR the receiver's window | ||
1953 | * forward. | ||
1954 | */ | ||
1955 | tid->seq_next = tid->seq_start; | ||
1956 | tid->baw_tail = tid->baw_head; | ||
1957 | } | ||
1958 | |||
1959 | /* | ||
1960 | * Drain all pending buffers | ||
1961 | * NB: must be called with txq lock held | ||
1962 | */ | ||
1963 | |||
1964 | static void ath_txq_drain_pending_buffers(struct ath_softc *sc, | ||
1965 | struct ath_txq *txq, | ||
1966 | bool bh_flag) | ||
1967 | { | ||
1968 | struct ath_atx_ac *ac, *ac_tmp; | ||
1969 | struct ath_atx_tid *tid, *tid_tmp; | ||
1970 | |||
1971 | list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { | ||
1972 | list_del(&ac->list); | ||
1973 | ac->sched = false; | ||
1974 | list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) { | ||
1975 | list_del(&tid->list); | ||
1976 | tid->sched = false; | ||
1977 | ath_tid_drain(sc, txq, tid, bh_flag); | ||
1978 | } | ||
1979 | } | ||
1980 | } | ||
1981 | |||
1982 | static int ath_tx_start_dma(struct ath_softc *sc, | ||
1983 | struct sk_buff *skb, | ||
1984 | struct scatterlist *sg, | ||
1985 | u32 n_sg, | ||
1986 | struct ath_tx_control *txctl) | ||
1987 | { | ||
1988 | struct ath_node *an = txctl->an; | ||
1989 | struct ath_buf *bf = NULL; | ||
1990 | struct list_head bf_head; | ||
1991 | struct ath_desc *ds; | ||
1992 | struct ath_hal *ah = sc->sc_ah; | ||
1993 | struct ath_txq *txq = &sc->sc_txq[txctl->qnum]; | ||
1994 | struct ath_tx_info_priv *tx_info_priv; | ||
1995 | struct ath_rc_series *rcs; | ||
1996 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1997 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1998 | __le16 fc = hdr->frame_control; | ||
1999 | |||
2000 | /* For each sglist entry, allocate an ath_buf for DMA */ | ||
2001 | INIT_LIST_HEAD(&bf_head); | ||
2002 | spin_lock_bh(&sc->sc_txbuflock); | ||
2003 | if (unlikely(list_empty(&sc->sc_txbuf))) { | ||
2004 | spin_unlock_bh(&sc->sc_txbuflock); | ||
2005 | return -ENOMEM; | ||
2006 | } | ||
2007 | |||
2008 | bf = list_first_entry(&sc->sc_txbuf, struct ath_buf, list); | ||
2009 | list_del(&bf->list); | ||
2010 | spin_unlock_bh(&sc->sc_txbuflock); | ||
2011 | |||
2012 | list_add_tail(&bf->list, &bf_head); | ||
2013 | |||
2014 | /* set up this buffer */ | ||
2015 | ATH_TXBUF_RESET(bf); | ||
2016 | bf->bf_frmlen = txctl->frmlen; | ||
2017 | bf->bf_isdata = ieee80211_is_data(fc); | ||
2018 | bf->bf_isbar = ieee80211_is_back_req(fc); | ||
2019 | bf->bf_ispspoll = ieee80211_is_pspoll(fc); | ||
2020 | bf->bf_flags = txctl->flags; | ||
2021 | bf->bf_shpreamble = sc->sc_flags & ATH_PREAMBLE_SHORT; | ||
2022 | bf->bf_keytype = txctl->keytype; | ||
2023 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | ||
2024 | rcs = tx_info_priv->rcs; | ||
2025 | bf->bf_rcs[0] = rcs[0]; | ||
2026 | bf->bf_rcs[1] = rcs[1]; | ||
2027 | bf->bf_rcs[2] = rcs[2]; | ||
2028 | bf->bf_rcs[3] = rcs[3]; | ||
2029 | bf->bf_node = an; | ||
2030 | bf->bf_mpdu = skb; | ||
2031 | bf->bf_buf_addr = sg_dma_address(sg); | ||
2032 | |||
2033 | /* setup descriptor */ | ||
2034 | ds = bf->bf_desc; | ||
2035 | ds->ds_link = 0; | ||
2036 | ds->ds_data = bf->bf_buf_addr; | ||
2037 | |||
2038 | /* | ||
2039 | * Save the DMA context in the first ath_buf | ||
2040 | */ | ||
2041 | copy_dma_mem_context(get_dma_mem_context(bf, bf_dmacontext), | ||
2042 | get_dma_mem_context(txctl, dmacontext)); | ||
2043 | |||
2044 | /* | ||
2045 | * Formulate first tx descriptor with tx controls. | ||
2046 | */ | ||
2047 | ath9k_hw_set11n_txdesc(ah, | ||
2048 | ds, | ||
2049 | bf->bf_frmlen, /* frame length */ | ||
2050 | txctl->atype, /* Atheros packet type */ | ||
2051 | min(txctl->txpower, (u16)60), /* txpower */ | ||
2052 | txctl->keyix, /* key cache index */ | ||
2053 | txctl->keytype, /* key type */ | ||
2054 | txctl->flags); /* flags */ | ||
2055 | ath9k_hw_filltxdesc(ah, | ||
2056 | ds, | ||
2057 | sg_dma_len(sg), /* segment length */ | ||
2058 | true, /* first segment */ | ||
2059 | (n_sg == 1) ? true : false, /* last segment */ | ||
2060 | ds); /* first descriptor */ | ||
2061 | |||
2062 | bf->bf_lastfrm = bf; | ||
2063 | bf->bf_ht = txctl->ht; | ||
2064 | |||
2065 | spin_lock_bh(&txq->axq_lock); | ||
2066 | |||
2067 | if (txctl->ht && sc->sc_txaggr) { | ||
2068 | struct ath_atx_tid *tid = ATH_AN_2_TID(an, txctl->tidno); | ||
2069 | if (ath_aggr_query(sc, an, txctl->tidno)) { | ||
2070 | /* | ||
2071 | * Try aggregation if it's a unicast data frame | ||
2072 | * and the destination is HT capable. | ||
2073 | */ | ||
2074 | ath_tx_send_ampdu(sc, txq, tid, &bf_head, txctl); | ||
2075 | } else { | ||
2076 | /* | ||
2077 | * Send this frame as regular when ADDBA exchange | ||
2078 | * is neither complete nor pending. | ||
2079 | */ | ||
2080 | ath_tx_send_normal(sc, txq, tid, &bf_head); | ||
2081 | } | ||
2082 | } else { | ||
2083 | bf->bf_lastbf = bf; | ||
2084 | bf->bf_nframes = 1; | ||
2085 | ath_buf_set_rate(sc, bf); | ||
2086 | |||
2087 | if (ieee80211_is_back_req(fc)) { | ||
2088 | /* This is required for resuming tid | ||
2089 | * during BAR completion */ | ||
2090 | bf->bf_tidno = txctl->tidno; | ||
2091 | } | ||
2092 | |||
2093 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
2094 | struct ath_vap *avp = sc->sc_vaps[txctl->if_id]; | ||
2095 | |||
2096 | /* | ||
2097 | * When servicing one or more stations in power-save | ||
2098 | * mode (or) if there is some mcast data waiting on | ||
2099 | * mcast queue (to prevent out of order delivery of | ||
2100 | * mcast,bcast packets) multicast frames must be | ||
2101 | * buffered until after the beacon. We use the private | ||
2102 | * mcast queue for that. | ||
2103 | */ | ||
2104 | /* XXX? more bit in 802.11 frame header */ | ||
2105 | spin_lock_bh(&avp->av_mcastq.axq_lock); | ||
2106 | if (txctl->ps || avp->av_mcastq.axq_depth) | ||
2107 | ath_tx_mcastqaddbuf(sc, | ||
2108 | &avp->av_mcastq, &bf_head); | ||
2109 | else | ||
2110 | ath_tx_txqaddbuf(sc, txq, &bf_head); | ||
2111 | spin_unlock_bh(&avp->av_mcastq.axq_lock); | ||
2112 | } else | ||
2113 | ath_tx_txqaddbuf(sc, txq, &bf_head); | ||
2114 | } | ||
2115 | spin_unlock_bh(&txq->axq_lock); | ||
2116 | return 0; | ||
2117 | } | ||
2118 | |||
2119 | static void xmit_map_sg(struct ath_softc *sc, | ||
2120 | struct sk_buff *skb, | ||
2121 | dma_addr_t *pa, | ||
2122 | struct ath_tx_control *txctl) | ||
2123 | { | ||
2124 | struct ath_xmit_status tx_status; | ||
2125 | struct ath_atx_tid *tid; | ||
2126 | struct scatterlist sg; | ||
2127 | |||
2128 | *pa = pci_map_single(sc->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); | ||
2129 | |||
2130 | /* setup S/G list */ | ||
2131 | memset(&sg, 0, sizeof(struct scatterlist)); | ||
2132 | sg_dma_address(&sg) = *pa; | ||
2133 | sg_dma_len(&sg) = skb->len; | ||
2134 | |||
2135 | if (ath_tx_start_dma(sc, skb, &sg, 1, txctl) != 0) { | ||
2136 | /* | ||
2137 | * We have to do drop frame here. | ||
2138 | */ | ||
2139 | pci_unmap_single(sc->pdev, *pa, skb->len, PCI_DMA_TODEVICE); | ||
2140 | |||
2141 | tx_status.retries = 0; | ||
2142 | tx_status.flags = ATH_TX_ERROR; | ||
2143 | |||
2144 | if (txctl->ht && sc->sc_txaggr) { | ||
2145 | /* Reclaim the seqno. */ | ||
2146 | tid = ATH_AN_2_TID((struct ath_node *) | ||
2147 | txctl->an, txctl->tidno); | ||
2148 | DECR(tid->seq_next, IEEE80211_SEQ_MAX); | ||
2149 | } | ||
2150 | ath_tx_complete(sc, skb, &tx_status, txctl->an); | ||
2151 | } | ||
2152 | } | ||
2153 | |||
2154 | /* Initialize TX queue and h/w */ | ||
2155 | |||
2156 | int ath_tx_init(struct ath_softc *sc, int nbufs) | ||
2157 | { | ||
2158 | int error = 0; | ||
2159 | |||
2160 | do { | ||
2161 | spin_lock_init(&sc->sc_txbuflock); | ||
2162 | |||
2163 | /* Setup tx descriptors */ | ||
2164 | error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf, | ||
2165 | "tx", nbufs * ATH_FRAG_PER_MSDU, ATH_TXDESC); | ||
2166 | if (error != 0) { | ||
2167 | DPRINTF(sc, ATH_DBG_FATAL, | ||
2168 | "%s: failed to allocate tx descriptors: %d\n", | ||
2169 | __func__, error); | ||
2170 | break; | ||
2171 | } | ||
2172 | |||
2173 | /* XXX allocate beacon state together with vap */ | ||
2174 | error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf, | ||
2175 | "beacon", ATH_BCBUF, 1); | ||
2176 | if (error != 0) { | ||
2177 | DPRINTF(sc, ATH_DBG_FATAL, | ||
2178 | "%s: failed to allocate " | ||
2179 | "beacon descripotrs: %d\n", | ||
2180 | __func__, error); | ||
2181 | break; | ||
2182 | } | ||
2183 | |||
2184 | } while (0); | ||
2185 | |||
2186 | if (error != 0) | ||
2187 | ath_tx_cleanup(sc); | ||
2188 | |||
2189 | return error; | ||
2190 | } | ||
2191 | |||
2192 | /* Reclaim all tx queue resources */ | ||
2193 | |||
2194 | int ath_tx_cleanup(struct ath_softc *sc) | ||
2195 | { | ||
2196 | /* cleanup beacon descriptors */ | ||
2197 | if (sc->sc_bdma.dd_desc_len != 0) | ||
2198 | ath_descdma_cleanup(sc, &sc->sc_bdma, &sc->sc_bbuf); | ||
2199 | |||
2200 | /* cleanup tx descriptors */ | ||
2201 | if (sc->sc_txdma.dd_desc_len != 0) | ||
2202 | ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf); | ||
2203 | |||
2204 | return 0; | ||
2205 | } | ||
2206 | |||
2207 | /* Setup a h/w transmit queue */ | ||
2208 | |||
2209 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | ||
2210 | { | ||
2211 | struct ath_hal *ah = sc->sc_ah; | ||
2212 | struct ath9k_txq_info qi; | ||
2213 | int qnum; | ||
2214 | |||
2215 | memzero(&qi, sizeof(qi)); | ||
2216 | qi.tqi_subtype = subtype; | ||
2217 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; | ||
2218 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; | ||
2219 | qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; | ||
2220 | qi.tqi_compBuf = 0; | ||
2221 | |||
2222 | /* | ||
2223 | * Enable interrupts only for EOL and DESC conditions. | ||
2224 | * We mark tx descriptors to receive a DESC interrupt | ||
2225 | * when a tx queue gets deep; otherwise waiting for the | ||
2226 | * EOL to reap descriptors. Note that this is done to | ||
2227 | * reduce interrupt load and this only defers reaping | ||
2228 | * descriptors, never transmitting frames. Aside from | ||
2229 | * reducing interrupts this also permits more concurrency. | ||
2230 | * The only potential downside is if the tx queue backs | ||
2231 | * up in which case the top half of the kernel may backup | ||
2232 | * due to a lack of tx descriptors. | ||
2233 | * | ||
2234 | * The UAPSD queue is an exception, since we take a desc- | ||
2235 | * based intr on the EOSP frames. | ||
2236 | */ | ||
2237 | if (qtype == ATH9K_TX_QUEUE_UAPSD) | ||
2238 | qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; | ||
2239 | else | ||
2240 | qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | | ||
2241 | TXQ_FLAG_TXDESCINT_ENABLE; | ||
2242 | qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); | ||
2243 | if (qnum == -1) { | ||
2244 | /* | ||
2245 | * NB: don't print a message, this happens | ||
2246 | * normally on parts with too few tx queues | ||
2247 | */ | ||
2248 | return NULL; | ||
2249 | } | ||
2250 | if (qnum >= ARRAY_SIZE(sc->sc_txq)) { | ||
2251 | DPRINTF(sc, ATH_DBG_FATAL, | ||
2252 | "%s: hal qnum %u out of range, max %u!\n", | ||
2253 | __func__, qnum, (unsigned int)ARRAY_SIZE(sc->sc_txq)); | ||
2254 | ath9k_hw_releasetxqueue(ah, qnum); | ||
2255 | return NULL; | ||
2256 | } | ||
2257 | if (!ATH_TXQ_SETUP(sc, qnum)) { | ||
2258 | struct ath_txq *txq = &sc->sc_txq[qnum]; | ||
2259 | |||
2260 | txq->axq_qnum = qnum; | ||
2261 | txq->axq_link = NULL; | ||
2262 | INIT_LIST_HEAD(&txq->axq_q); | ||
2263 | INIT_LIST_HEAD(&txq->axq_acq); | ||
2264 | spin_lock_init(&txq->axq_lock); | ||
2265 | txq->axq_depth = 0; | ||
2266 | txq->axq_aggr_depth = 0; | ||
2267 | txq->axq_totalqueued = 0; | ||
2268 | txq->axq_intrcnt = 0; | ||
2269 | txq->axq_linkbuf = NULL; | ||
2270 | sc->sc_txqsetup |= 1<<qnum; | ||
2271 | } | ||
2272 | return &sc->sc_txq[qnum]; | ||
2273 | } | ||
2274 | |||
2275 | /* Reclaim resources for a setup queue */ | ||
2276 | |||
2277 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) | ||
2278 | { | ||
2279 | ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum); | ||
2280 | sc->sc_txqsetup &= ~(1<<txq->axq_qnum); | ||
2281 | } | ||
2282 | |||
2283 | /* | ||
2284 | * Setup a hardware data transmit queue for the specified | ||
2285 | * access control. The hal may not support all requested | ||
2286 | * queues in which case it will return a reference to a | ||
2287 | * previously setup queue. We record the mapping from ac's | ||
2288 | * to h/w queues for use by ath_tx_start and also track | ||
2289 | * the set of h/w queues being used to optimize work in the | ||
2290 | * transmit interrupt handler and related routines. | ||
2291 | */ | ||
2292 | |||
2293 | int ath_tx_setup(struct ath_softc *sc, int haltype) | ||
2294 | { | ||
2295 | struct ath_txq *txq; | ||
2296 | |||
2297 | if (haltype >= ARRAY_SIZE(sc->sc_haltype2q)) { | ||
2298 | DPRINTF(sc, ATH_DBG_FATAL, | ||
2299 | "%s: HAL AC %u out of range, max %zu!\n", | ||
2300 | __func__, haltype, ARRAY_SIZE(sc->sc_haltype2q)); | ||
2301 | return 0; | ||
2302 | } | ||
2303 | txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); | ||
2304 | if (txq != NULL) { | ||
2305 | sc->sc_haltype2q[haltype] = txq->axq_qnum; | ||
2306 | return 1; | ||
2307 | } else | ||
2308 | return 0; | ||
2309 | } | ||
2310 | |||
2311 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) | ||
2312 | { | ||
2313 | int qnum; | ||
2314 | |||
2315 | switch (qtype) { | ||
2316 | case ATH9K_TX_QUEUE_DATA: | ||
2317 | if (haltype >= ARRAY_SIZE(sc->sc_haltype2q)) { | ||
2318 | DPRINTF(sc, ATH_DBG_FATAL, | ||
2319 | "%s: HAL AC %u out of range, max %zu!\n", | ||
2320 | __func__, | ||
2321 | haltype, ARRAY_SIZE(sc->sc_haltype2q)); | ||
2322 | return -1; | ||
2323 | } | ||
2324 | qnum = sc->sc_haltype2q[haltype]; | ||
2325 | break; | ||
2326 | case ATH9K_TX_QUEUE_BEACON: | ||
2327 | qnum = sc->sc_bhalq; | ||
2328 | break; | ||
2329 | case ATH9K_TX_QUEUE_CAB: | ||
2330 | qnum = sc->sc_cabq->axq_qnum; | ||
2331 | break; | ||
2332 | default: | ||
2333 | qnum = -1; | ||
2334 | } | ||
2335 | return qnum; | ||
2336 | } | ||
2337 | |||
2338 | /* Update parameters for a transmit queue */ | ||
2339 | |||
2340 | int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_txq_info *qi0) | ||
2341 | { | ||
2342 | struct ath_hal *ah = sc->sc_ah; | ||
2343 | int error = 0; | ||
2344 | struct ath9k_txq_info qi; | ||
2345 | |||
2346 | if (qnum == sc->sc_bhalq) { | ||
2347 | /* | ||
2348 | * XXX: for beacon queue, we just save the parameter. | ||
2349 | * It will be picked up by ath_beaconq_config when | ||
2350 | * it's necessary. | ||
2351 | */ | ||
2352 | sc->sc_beacon_qi = *qi0; | ||
2353 | return 0; | ||
2354 | } | ||
2355 | |||
2356 | ASSERT(sc->sc_txq[qnum].axq_qnum == qnum); | ||
2357 | |||
2358 | ath9k_hw_gettxqueueprops(ah, qnum, &qi); | ||
2359 | qi.tqi_aifs = qi0->tqi_aifs; | ||
2360 | qi.tqi_cwmin = qi0->tqi_cwmin; | ||
2361 | qi.tqi_cwmax = qi0->tqi_cwmax; | ||
2362 | qi.tqi_burstTime = qi0->tqi_burstTime; | ||
2363 | qi.tqi_readyTime = qi0->tqi_readyTime; | ||
2364 | |||
2365 | if (!ath9k_hw_settxqueueprops(ah, qnum, &qi)) { | ||
2366 | DPRINTF(sc, ATH_DBG_FATAL, | ||
2367 | "%s: unable to update hardware queue %u!\n", | ||
2368 | __func__, qnum); | ||
2369 | error = -EIO; | ||
2370 | } else { | ||
2371 | ath9k_hw_resettxqueue(ah, qnum); /* push to h/w */ | ||
2372 | } | ||
2373 | |||
2374 | return error; | ||
2375 | } | ||
2376 | |||
2377 | int ath_cabq_update(struct ath_softc *sc) | ||
2378 | { | ||
2379 | struct ath9k_txq_info qi; | ||
2380 | int qnum = sc->sc_cabq->axq_qnum; | ||
2381 | struct ath_beacon_config conf; | ||
2382 | |||
2383 | ath9k_hw_gettxqueueprops(sc->sc_ah, qnum, &qi); | ||
2384 | /* | ||
2385 | * Ensure the readytime % is within the bounds. | ||
2386 | */ | ||
2387 | if (sc->sc_config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) | ||
2388 | sc->sc_config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; | ||
2389 | else if (sc->sc_config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) | ||
2390 | sc->sc_config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; | ||
2391 | |||
2392 | ath_get_beaconconfig(sc, ATH_IF_ID_ANY, &conf); | ||
2393 | qi.tqi_readyTime = | ||
2394 | (conf.beacon_interval * sc->sc_config.cabqReadytime) / 100; | ||
2395 | ath_txq_update(sc, qnum, &qi); | ||
2396 | |||
2397 | return 0; | ||
2398 | } | ||
2399 | |||
2400 | int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb) | ||
2401 | { | ||
2402 | struct ath_tx_control txctl; | ||
2403 | int error = 0; | ||
2404 | |||
2405 | error = ath_tx_prepare(sc, skb, &txctl); | ||
2406 | if (error == 0) | ||
2407 | /* | ||
2408 | * Start DMA mapping. | ||
2409 | * ath_tx_start_dma() will be called either synchronously | ||
2410 | * or asynchrounsly once DMA is complete. | ||
2411 | */ | ||
2412 | xmit_map_sg(sc, skb, | ||
2413 | get_dma_mem_context(&txctl, dmacontext), | ||
2414 | &txctl); | ||
2415 | else | ||
2416 | ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE); | ||
2417 | |||
2418 | /* failed packets will be dropped by the caller */ | ||
2419 | return error; | ||
2420 | } | ||
2421 | |||
2422 | /* Deferred processing of transmit interrupt */ | ||
2423 | |||
2424 | void ath_tx_tasklet(struct ath_softc *sc) | ||
2425 | { | ||
2426 | u64 tsf = ath9k_hw_gettsf64(sc->sc_ah); | ||
2427 | int i, nacked = 0; | ||
2428 | u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); | ||
2429 | |||
2430 | ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); | ||
2431 | |||
2432 | /* | ||
2433 | * Process each active queue. | ||
2434 | */ | ||
2435 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
2436 | if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) | ||
2437 | nacked += ath_tx_processq(sc, &sc->sc_txq[i]); | ||
2438 | } | ||
2439 | if (nacked) | ||
2440 | sc->sc_lastrx = tsf; | ||
2441 | } | ||
2442 | |||
2443 | void ath_tx_draintxq(struct ath_softc *sc, | ||
2444 | struct ath_txq *txq, bool retry_tx) | ||
2445 | { | ||
2446 | struct ath_buf *bf, *lastbf; | ||
2447 | struct list_head bf_head; | ||
2448 | |||
2449 | INIT_LIST_HEAD(&bf_head); | ||
2450 | |||
2451 | /* | ||
2452 | * NB: this assumes output has been stopped and | ||
2453 | * we do not need to block ath_tx_tasklet | ||
2454 | */ | ||
2455 | for (;;) { | ||
2456 | spin_lock_bh(&txq->axq_lock); | ||
2457 | |||
2458 | if (list_empty(&txq->axq_q)) { | ||
2459 | txq->axq_link = NULL; | ||
2460 | txq->axq_linkbuf = NULL; | ||
2461 | spin_unlock_bh(&txq->axq_lock); | ||
2462 | break; | ||
2463 | } | ||
2464 | |||
2465 | bf = list_first_entry(&txq->axq_q, struct ath_buf, list); | ||
2466 | |||
2467 | if (bf->bf_status & ATH_BUFSTATUS_STALE) { | ||
2468 | list_del(&bf->list); | ||
2469 | spin_unlock_bh(&txq->axq_lock); | ||
2470 | |||
2471 | spin_lock_bh(&sc->sc_txbuflock); | ||
2472 | list_add_tail(&bf->list, &sc->sc_txbuf); | ||
2473 | spin_unlock_bh(&sc->sc_txbuflock); | ||
2474 | continue; | ||
2475 | } | ||
2476 | |||
2477 | lastbf = bf->bf_lastbf; | ||
2478 | if (!retry_tx) | ||
2479 | lastbf->bf_desc->ds_txstat.ts_flags = | ||
2480 | ATH9K_TX_SW_ABORTED; | ||
2481 | |||
2482 | /* remove ath_buf's of the same mpdu from txq */ | ||
2483 | list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); | ||
2484 | txq->axq_depth--; | ||
2485 | |||
2486 | spin_unlock_bh(&txq->axq_lock); | ||
2487 | |||
2488 | if (bf->bf_isampdu) | ||
2489 | ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0); | ||
2490 | else | ||
2491 | ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); | ||
2492 | } | ||
2493 | |||
2494 | /* flush any pending frames if aggregation is enabled */ | ||
2495 | if (sc->sc_txaggr) { | ||
2496 | if (!retry_tx) { | ||
2497 | spin_lock_bh(&txq->axq_lock); | ||
2498 | ath_txq_drain_pending_buffers(sc, txq, | ||
2499 | ATH9K_BH_STATUS_CHANGE); | ||
2500 | spin_unlock_bh(&txq->axq_lock); | ||
2501 | } | ||
2502 | } | ||
2503 | } | ||
2504 | |||
2505 | /* Drain the transmit queues and reclaim resources */ | ||
2506 | |||
2507 | void ath_draintxq(struct ath_softc *sc, bool retry_tx) | ||
2508 | { | ||
2509 | /* stop beacon queue. The beacon will be freed when | ||
2510 | * we go to INIT state */ | ||
2511 | if (!sc->sc_invalid) { | ||
2512 | (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); | ||
2513 | DPRINTF(sc, ATH_DBG_XMIT, "%s: beacon queue %x\n", __func__, | ||
2514 | ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq)); | ||
2515 | } | ||
2516 | |||
2517 | ath_drain_txdataq(sc, retry_tx); | ||
2518 | } | ||
2519 | |||
2520 | u32 ath_txq_depth(struct ath_softc *sc, int qnum) | ||
2521 | { | ||
2522 | return sc->sc_txq[qnum].axq_depth; | ||
2523 | } | ||
2524 | |||
2525 | u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum) | ||
2526 | { | ||
2527 | return sc->sc_txq[qnum].axq_aggr_depth; | ||
2528 | } | ||
2529 | |||
2530 | /* Check if an ADDBA is required. A valid node must be passed. */ | ||
2531 | enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc, | ||
2532 | struct ath_node *an, | ||
2533 | u8 tidno) | ||
2534 | { | ||
2535 | struct ath_atx_tid *txtid; | ||
2536 | DECLARE_MAC_BUF(mac); | ||
2537 | |||
2538 | if (!sc->sc_txaggr) | ||
2539 | return AGGR_NOT_REQUIRED; | ||
2540 | |||
2541 | /* ADDBA exchange must be completed before sending aggregates */ | ||
2542 | txtid = ATH_AN_2_TID(an, tidno); | ||
2543 | |||
2544 | if (txtid->addba_exchangecomplete) | ||
2545 | return AGGR_EXCHANGE_DONE; | ||
2546 | |||
2547 | if (txtid->cleanup_inprogress) | ||
2548 | return AGGR_CLEANUP_PROGRESS; | ||
2549 | |||
2550 | if (txtid->addba_exchangeinprogress) | ||
2551 | return AGGR_EXCHANGE_PROGRESS; | ||
2552 | |||
2553 | if (!txtid->addba_exchangecomplete) { | ||
2554 | if (!txtid->addba_exchangeinprogress && | ||
2555 | (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) { | ||
2556 | txtid->addba_exchangeattempts++; | ||
2557 | return AGGR_REQUIRED; | ||
2558 | } | ||
2559 | } | ||
2560 | |||
2561 | return AGGR_NOT_REQUIRED; | ||
2562 | } | ||
2563 | |||
2564 | /* Start TX aggregation */ | ||
2565 | |||
2566 | int ath_tx_aggr_start(struct ath_softc *sc, | ||
2567 | const u8 *addr, | ||
2568 | u16 tid, | ||
2569 | u16 *ssn) | ||
2570 | { | ||
2571 | struct ath_atx_tid *txtid; | ||
2572 | struct ath_node *an; | ||
2573 | |||
2574 | spin_lock_bh(&sc->node_lock); | ||
2575 | an = ath_node_find(sc, (u8 *) addr); | ||
2576 | spin_unlock_bh(&sc->node_lock); | ||
2577 | |||
2578 | if (!an) { | ||
2579 | DPRINTF(sc, ATH_DBG_AGGR, | ||
2580 | "%s: Node not found to initialize " | ||
2581 | "TX aggregation\n", __func__); | ||
2582 | return -1; | ||
2583 | } | ||
2584 | |||
2585 | if (sc->sc_txaggr) { | ||
2586 | txtid = ATH_AN_2_TID(an, tid); | ||
2587 | txtid->addba_exchangeinprogress = 1; | ||
2588 | ath_tx_pause_tid(sc, txtid); | ||
2589 | } | ||
2590 | |||
2591 | return 0; | ||
2592 | } | ||
2593 | |||
2594 | /* Stop tx aggregation */ | ||
2595 | |||
2596 | int ath_tx_aggr_stop(struct ath_softc *sc, | ||
2597 | const u8 *addr, | ||
2598 | u16 tid) | ||
2599 | { | ||
2600 | struct ath_node *an; | ||
2601 | |||
2602 | spin_lock_bh(&sc->node_lock); | ||
2603 | an = ath_node_find(sc, (u8 *) addr); | ||
2604 | spin_unlock_bh(&sc->node_lock); | ||
2605 | |||
2606 | if (!an) { | ||
2607 | DPRINTF(sc, ATH_DBG_AGGR, | ||
2608 | "%s: TX aggr stop for non-existent node\n", __func__); | ||
2609 | return -1; | ||
2610 | } | ||
2611 | |||
2612 | ath_tx_aggr_teardown(sc, an, tid); | ||
2613 | return 0; | ||
2614 | } | ||
2615 | |||
2616 | /* | ||
2617 | * Performs transmit side cleanup when TID changes from aggregated to | ||
2618 | * unaggregated. | ||
2619 | * - Pause the TID and mark cleanup in progress | ||
2620 | * - Discard all retry frames from the s/w queue. | ||
2621 | */ | ||
2622 | |||
2623 | void ath_tx_aggr_teardown(struct ath_softc *sc, | ||
2624 | struct ath_node *an, u8 tid) | ||
2625 | { | ||
2626 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); | ||
2627 | struct ath_txq *txq = &sc->sc_txq[txtid->ac->qnum]; | ||
2628 | struct ath_buf *bf; | ||
2629 | struct list_head bf_head; | ||
2630 | INIT_LIST_HEAD(&bf_head); | ||
2631 | |||
2632 | DPRINTF(sc, ATH_DBG_AGGR, "%s: teardown TX aggregation\n", __func__); | ||
2633 | |||
2634 | if (txtid->cleanup_inprogress) /* cleanup is in progress */ | ||
2635 | return; | ||
2636 | |||
2637 | if (!txtid->addba_exchangecomplete) { | ||
2638 | txtid->addba_exchangeattempts = 0; | ||
2639 | return; | ||
2640 | } | ||
2641 | |||
2642 | /* TID must be paused first */ | ||
2643 | ath_tx_pause_tid(sc, txtid); | ||
2644 | |||
2645 | /* drop all software retried frames and mark this TID */ | ||
2646 | spin_lock_bh(&txq->axq_lock); | ||
2647 | while (!list_empty(&txtid->buf_q)) { | ||
2648 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); | ||
2649 | if (!bf->bf_isretried) { | ||
2650 | /* | ||
2651 | * NB: it's based on the assumption that | ||
2652 | * software retried frame will always stay | ||
2653 | * at the head of software queue. | ||
2654 | */ | ||
2655 | break; | ||
2656 | } | ||
2657 | list_cut_position(&bf_head, | ||
2658 | &txtid->buf_q, &bf->bf_lastfrm->list); | ||
2659 | ath_tx_update_baw(sc, txtid, bf->bf_seqno); | ||
2660 | |||
2661 | /* complete this sub-frame */ | ||
2662 | ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); | ||
2663 | } | ||
2664 | |||
2665 | if (txtid->baw_head != txtid->baw_tail) { | ||
2666 | spin_unlock_bh(&txq->axq_lock); | ||
2667 | txtid->cleanup_inprogress = true; | ||
2668 | } else { | ||
2669 | txtid->addba_exchangecomplete = 0; | ||
2670 | txtid->addba_exchangeattempts = 0; | ||
2671 | spin_unlock_bh(&txq->axq_lock); | ||
2672 | ath_tx_flush_tid(sc, txtid); | ||
2673 | } | ||
2674 | } | ||
2675 | |||
2676 | /* | ||
2677 | * Tx scheduling logic | ||
2678 | * NB: must be called with txq lock held | ||
2679 | */ | ||
2680 | |||
2681 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | ||
2682 | { | ||
2683 | struct ath_atx_ac *ac; | ||
2684 | struct ath_atx_tid *tid; | ||
2685 | |||
2686 | /* nothing to schedule */ | ||
2687 | if (list_empty(&txq->axq_acq)) | ||
2688 | return; | ||
2689 | /* | ||
2690 | * get the first node/ac pair on the queue | ||
2691 | */ | ||
2692 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); | ||
2693 | list_del(&ac->list); | ||
2694 | ac->sched = false; | ||
2695 | |||
2696 | /* | ||
2697 | * process a single tid per destination | ||
2698 | */ | ||
2699 | do { | ||
2700 | /* nothing to schedule */ | ||
2701 | if (list_empty(&ac->tid_q)) | ||
2702 | return; | ||
2703 | |||
2704 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list); | ||
2705 | list_del(&tid->list); | ||
2706 | tid->sched = false; | ||
2707 | |||
2708 | if (tid->paused) /* check next tid to keep h/w busy */ | ||
2709 | continue; | ||
2710 | |||
2711 | if (!(tid->an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) || | ||
2712 | ((txq->axq_depth % 2) == 0)) { | ||
2713 | ath_tx_sched_aggr(sc, txq, tid); | ||
2714 | } | ||
2715 | |||
2716 | /* | ||
2717 | * add tid to round-robin queue if more frames | ||
2718 | * are pending for the tid | ||
2719 | */ | ||
2720 | if (!list_empty(&tid->buf_q)) | ||
2721 | ath_tx_queue_tid(txq, tid); | ||
2722 | |||
2723 | /* only schedule one TID at a time */ | ||
2724 | break; | ||
2725 | } while (!list_empty(&ac->tid_q)); | ||
2726 | |||
2727 | /* | ||
2728 | * schedule AC if more TIDs need processing | ||
2729 | */ | ||
2730 | if (!list_empty(&ac->tid_q)) { | ||
2731 | /* | ||
2732 | * add dest ac to txq if not already added | ||
2733 | */ | ||
2734 | if (!ac->sched) { | ||
2735 | ac->sched = true; | ||
2736 | list_add_tail(&ac->list, &txq->axq_acq); | ||
2737 | } | ||
2738 | } | ||
2739 | } | ||
2740 | |||
2741 | /* Initialize per-node transmit state */ | ||
2742 | |||
2743 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | ||
2744 | { | ||
2745 | if (sc->sc_txaggr) { | ||
2746 | struct ath_atx_tid *tid; | ||
2747 | struct ath_atx_ac *ac; | ||
2748 | int tidno, acno; | ||
2749 | |||
2750 | sc->sc_ht_info.maxampdu = ATH_AMPDU_LIMIT_DEFAULT; | ||
2751 | |||
2752 | /* | ||
2753 | * Init per tid tx state | ||
2754 | */ | ||
2755 | for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno]; | ||
2756 | tidno < WME_NUM_TID; | ||
2757 | tidno++, tid++) { | ||
2758 | tid->an = an; | ||
2759 | tid->tidno = tidno; | ||
2760 | tid->seq_start = tid->seq_next = 0; | ||
2761 | tid->baw_size = WME_MAX_BA; | ||
2762 | tid->baw_head = tid->baw_tail = 0; | ||
2763 | tid->sched = false; | ||
2764 | tid->paused = false; | ||
2765 | tid->cleanup_inprogress = false; | ||
2766 | INIT_LIST_HEAD(&tid->buf_q); | ||
2767 | |||
2768 | acno = TID_TO_WME_AC(tidno); | ||
2769 | tid->ac = &an->an_aggr.tx.ac[acno]; | ||
2770 | |||
2771 | /* ADDBA state */ | ||
2772 | tid->addba_exchangecomplete = 0; | ||
2773 | tid->addba_exchangeinprogress = 0; | ||
2774 | tid->addba_exchangeattempts = 0; | ||
2775 | } | ||
2776 | |||
2777 | /* | ||
2778 | * Init per ac tx state | ||
2779 | */ | ||
2780 | for (acno = 0, ac = &an->an_aggr.tx.ac[acno]; | ||
2781 | acno < WME_NUM_AC; acno++, ac++) { | ||
2782 | ac->sched = false; | ||
2783 | INIT_LIST_HEAD(&ac->tid_q); | ||
2784 | |||
2785 | switch (acno) { | ||
2786 | case WME_AC_BE: | ||
2787 | ac->qnum = ath_tx_get_qnum(sc, | ||
2788 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
2789 | break; | ||
2790 | case WME_AC_BK: | ||
2791 | ac->qnum = ath_tx_get_qnum(sc, | ||
2792 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK); | ||
2793 | break; | ||
2794 | case WME_AC_VI: | ||
2795 | ac->qnum = ath_tx_get_qnum(sc, | ||
2796 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI); | ||
2797 | break; | ||
2798 | case WME_AC_VO: | ||
2799 | ac->qnum = ath_tx_get_qnum(sc, | ||
2800 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO); | ||
2801 | break; | ||
2802 | } | ||
2803 | } | ||
2804 | } | ||
2805 | } | ||
2806 | |||
2807 | /* Cleanupthe pending buffers for the node. */ | ||
2808 | |||
2809 | void ath_tx_node_cleanup(struct ath_softc *sc, | ||
2810 | struct ath_node *an, bool bh_flag) | ||
2811 | { | ||
2812 | int i; | ||
2813 | struct ath_atx_ac *ac, *ac_tmp; | ||
2814 | struct ath_atx_tid *tid, *tid_tmp; | ||
2815 | struct ath_txq *txq; | ||
2816 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
2817 | if (ATH_TXQ_SETUP(sc, i)) { | ||
2818 | txq = &sc->sc_txq[i]; | ||
2819 | |||
2820 | if (likely(bh_flag)) | ||
2821 | spin_lock_bh(&txq->axq_lock); | ||
2822 | else | ||
2823 | spin_lock(&txq->axq_lock); | ||
2824 | |||
2825 | list_for_each_entry_safe(ac, | ||
2826 | ac_tmp, &txq->axq_acq, list) { | ||
2827 | tid = list_first_entry(&ac->tid_q, | ||
2828 | struct ath_atx_tid, list); | ||
2829 | if (tid && tid->an != an) | ||
2830 | continue; | ||
2831 | list_del(&ac->list); | ||
2832 | ac->sched = false; | ||
2833 | |||
2834 | list_for_each_entry_safe(tid, | ||
2835 | tid_tmp, &ac->tid_q, list) { | ||
2836 | list_del(&tid->list); | ||
2837 | tid->sched = false; | ||
2838 | ath_tid_drain(sc, txq, tid, bh_flag); | ||
2839 | tid->addba_exchangecomplete = 0; | ||
2840 | tid->addba_exchangeattempts = 0; | ||
2841 | tid->cleanup_inprogress = false; | ||
2842 | } | ||
2843 | } | ||
2844 | |||
2845 | if (likely(bh_flag)) | ||
2846 | spin_unlock_bh(&txq->axq_lock); | ||
2847 | else | ||
2848 | spin_unlock(&txq->axq_lock); | ||
2849 | } | ||
2850 | } | ||
2851 | } | ||
2852 | |||
2853 | /* Cleanup per node transmit state */ | ||
2854 | |||
2855 | void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an) | ||
2856 | { | ||
2857 | if (sc->sc_txaggr) { | ||
2858 | struct ath_atx_tid *tid; | ||
2859 | int tidno, i; | ||
2860 | |||
2861 | /* Init per tid rx state */ | ||
2862 | for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno]; | ||
2863 | tidno < WME_NUM_TID; | ||
2864 | tidno++, tid++) { | ||
2865 | |||
2866 | for (i = 0; i < ATH_TID_MAX_BUFS; i++) | ||
2867 | ASSERT(tid->tx_buf[i] == NULL); | ||
2868 | } | ||
2869 | } | ||
2870 | } | ||