diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-07 21:52:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-07 21:52:57 -0400 |
commit | 22c7fdf4a7acfa24d9d498b1357e6c07d0e6c553 (patch) | |
tree | 040ce9c55cb285c5eff565942f313a07e157fbb2 /drivers/net | |
parent | 5423b2ed25993e13009ce39f55d742c3c6d03edb (diff) | |
parent | 86b89eed9aca2a4a335b9c1bf7380f9183db431f (diff) |
Merge branch 'ath9k' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
Diffstat (limited to 'drivers/net')
23 files changed, 31520 insertions, 2 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 4c7ff61a1a9c..9931b5ab59cd 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 54a4f6f1db67..59aa89ec6e81 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/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index ebf19bc11f5b..2028866f5995 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -95,8 +95,6 @@ static struct pci_device_id ath5k_pci_id_table[] __devinitdata = { | |||
95 | { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */ | 95 | { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */ |
96 | { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */ | 96 | { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */ |
97 | { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* 5424 Condor (PCI-E)*/ | 97 | { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* 5424 Condor (PCI-E)*/ |
98 | { PCI_VDEVICE(ATHEROS, 0x0023), .driver_data = AR5K_AR5212 }, /* 5416 */ | ||
99 | { PCI_VDEVICE(ATHEROS, 0x0024), .driver_data = AR5K_AR5212 }, /* 5418 */ | ||
100 | { 0 } | 98 | { 0 } |
101 | }; | 99 | }; |
102 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); | 100 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); |
diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig new file mode 100644 index 000000000000..9e19dcceb3a2 --- /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 000000000000..a6411517e5f8 --- /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 000000000000..d1b0fbae5a32 --- /dev/null +++ b/drivers/net/wireless/ath9k/ath9k.h | |||
@@ -0,0 +1,1021 @@ | |||
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 wireless_mode { | ||
151 | ATH9K_MODE_11A = 0, | ||
152 | ATH9K_MODE_11B = 2, | ||
153 | ATH9K_MODE_11G = 3, | ||
154 | ATH9K_MODE_11NA_HT20 = 6, | ||
155 | ATH9K_MODE_11NG_HT20 = 7, | ||
156 | ATH9K_MODE_11NA_HT40PLUS = 8, | ||
157 | ATH9K_MODE_11NA_HT40MINUS = 9, | ||
158 | ATH9K_MODE_11NG_HT40PLUS = 10, | ||
159 | ATH9K_MODE_11NG_HT40MINUS = 11, | ||
160 | ATH9K_MODE_MAX | ||
161 | }; | ||
162 | |||
163 | enum ath9k_hw_caps { | ||
164 | ATH9K_HW_CAP_CHAN_SPREAD = BIT(0), | ||
165 | ATH9K_HW_CAP_MIC_AESCCM = BIT(1), | ||
166 | ATH9K_HW_CAP_MIC_CKIP = BIT(2), | ||
167 | ATH9K_HW_CAP_MIC_TKIP = BIT(3), | ||
168 | ATH9K_HW_CAP_CIPHER_AESCCM = BIT(4), | ||
169 | ATH9K_HW_CAP_CIPHER_CKIP = BIT(5), | ||
170 | ATH9K_HW_CAP_CIPHER_TKIP = BIT(6), | ||
171 | ATH9K_HW_CAP_VEOL = BIT(7), | ||
172 | ATH9K_HW_CAP_BSSIDMASK = BIT(8), | ||
173 | ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(9), | ||
174 | ATH9K_HW_CAP_CHAN_HALFRATE = BIT(10), | ||
175 | ATH9K_HW_CAP_CHAN_QUARTERRATE = BIT(11), | ||
176 | ATH9K_HW_CAP_HT = BIT(12), | ||
177 | ATH9K_HW_CAP_GTT = BIT(13), | ||
178 | ATH9K_HW_CAP_FASTCC = BIT(14), | ||
179 | ATH9K_HW_CAP_RFSILENT = BIT(15), | ||
180 | ATH9K_HW_CAP_WOW = BIT(16), | ||
181 | ATH9K_HW_CAP_CST = BIT(17), | ||
182 | ATH9K_HW_CAP_ENHANCEDPM = BIT(18), | ||
183 | ATH9K_HW_CAP_AUTOSLEEP = BIT(19), | ||
184 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(20), | ||
185 | ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT = BIT(21), | ||
186 | }; | ||
187 | |||
188 | enum ath9k_capability_type { | ||
189 | ATH9K_CAP_CIPHER = 0, | ||
190 | ATH9K_CAP_TKIP_MIC, | ||
191 | ATH9K_CAP_TKIP_SPLIT, | ||
192 | ATH9K_CAP_PHYCOUNTERS, | ||
193 | ATH9K_CAP_DIVERSITY, | ||
194 | ATH9K_CAP_TXPOW, | ||
195 | ATH9K_CAP_PHYDIAG, | ||
196 | ATH9K_CAP_MCAST_KEYSRCH, | ||
197 | ATH9K_CAP_TSF_ADJUST, | ||
198 | ATH9K_CAP_WME_TKIPMIC, | ||
199 | ATH9K_CAP_RFSILENT, | ||
200 | ATH9K_CAP_ANT_CFG_2GHZ, | ||
201 | ATH9K_CAP_ANT_CFG_5GHZ | ||
202 | }; | ||
203 | |||
204 | struct ath9k_hw_capabilities { | ||
205 | u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ | ||
206 | DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */ | ||
207 | u16 total_queues; | ||
208 | u16 keycache_size; | ||
209 | u16 low_5ghz_chan, high_5ghz_chan; | ||
210 | u16 low_2ghz_chan, high_2ghz_chan; | ||
211 | u16 num_mr_retries; | ||
212 | u16 rts_aggr_limit; | ||
213 | u8 tx_chainmask; | ||
214 | u8 rx_chainmask; | ||
215 | u16 tx_triglevel_max; | ||
216 | u16 reg_cap; | ||
217 | u8 num_gpio_pins; | ||
218 | u8 num_antcfg_2ghz; | ||
219 | u8 num_antcfg_5ghz; | ||
220 | }; | ||
221 | |||
222 | struct ath9k_ops_config { | ||
223 | int dma_beacon_response_time; | ||
224 | int sw_beacon_response_time; | ||
225 | int additional_swba_backoff; | ||
226 | int ack_6mb; | ||
227 | int cwm_ignore_extcca; | ||
228 | u8 pcie_powersave_enable; | ||
229 | u8 pcie_l1skp_enable; | ||
230 | u8 pcie_clock_req; | ||
231 | u32 pcie_waen; | ||
232 | int pcie_power_reset; | ||
233 | u8 pcie_restore; | ||
234 | u8 analog_shiftreg; | ||
235 | u8 ht_enable; | ||
236 | u32 ofdm_trig_low; | ||
237 | u32 ofdm_trig_high; | ||
238 | u32 cck_trig_high; | ||
239 | u32 cck_trig_low; | ||
240 | u32 enable_ani; | ||
241 | u8 noise_immunity_level; | ||
242 | u32 ofdm_weaksignal_det; | ||
243 | u32 cck_weaksignal_thr; | ||
244 | u8 spur_immunity_level; | ||
245 | u8 firstep_level; | ||
246 | int8_t rssi_thr_high; | ||
247 | int8_t rssi_thr_low; | ||
248 | u16 diversity_control; | ||
249 | u16 antenna_switch_swap; | ||
250 | int serialize_regmode; | ||
251 | int intr_mitigation; | ||
252 | #define SPUR_DISABLE 0 | ||
253 | #define SPUR_ENABLE_IOCTL 1 | ||
254 | #define SPUR_ENABLE_EEPROM 2 | ||
255 | #define AR_EEPROM_MODAL_SPURS 5 | ||
256 | #define AR_SPUR_5413_1 1640 | ||
257 | #define AR_SPUR_5413_2 1200 | ||
258 | #define AR_NO_SPUR 0x8000 | ||
259 | #define AR_BASE_FREQ_2GHZ 2300 | ||
260 | #define AR_BASE_FREQ_5GHZ 4900 | ||
261 | #define AR_SPUR_FEEQ_BOUND_HT40 19 | ||
262 | #define AR_SPUR_FEEQ_BOUND_HT20 10 | ||
263 | int spurmode; | ||
264 | u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; | ||
265 | }; | ||
266 | |||
267 | enum ath9k_tx_queue { | ||
268 | ATH9K_TX_QUEUE_INACTIVE = 0, | ||
269 | ATH9K_TX_QUEUE_DATA, | ||
270 | ATH9K_TX_QUEUE_BEACON, | ||
271 | ATH9K_TX_QUEUE_CAB, | ||
272 | ATH9K_TX_QUEUE_UAPSD, | ||
273 | ATH9K_TX_QUEUE_PSPOLL | ||
274 | }; | ||
275 | |||
276 | #define ATH9K_NUM_TX_QUEUES 10 | ||
277 | |||
278 | enum ath9k_tx_queue_subtype { | ||
279 | ATH9K_WME_AC_BK = 0, | ||
280 | ATH9K_WME_AC_BE, | ||
281 | ATH9K_WME_AC_VI, | ||
282 | ATH9K_WME_AC_VO, | ||
283 | ATH9K_WME_UPSD | ||
284 | }; | ||
285 | |||
286 | enum ath9k_tx_queue_flags { | ||
287 | TXQ_FLAG_TXOKINT_ENABLE = 0x0001, | ||
288 | TXQ_FLAG_TXERRINT_ENABLE = 0x0001, | ||
289 | TXQ_FLAG_TXDESCINT_ENABLE = 0x0002, | ||
290 | TXQ_FLAG_TXEOLINT_ENABLE = 0x0004, | ||
291 | TXQ_FLAG_TXURNINT_ENABLE = 0x0008, | ||
292 | TXQ_FLAG_BACKOFF_DISABLE = 0x0010, | ||
293 | TXQ_FLAG_COMPRESSION_ENABLE = 0x0020, | ||
294 | TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040, | ||
295 | TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080, | ||
296 | }; | ||
297 | |||
298 | #define ATH9K_TXQ_USEDEFAULT ((u32) -1) | ||
299 | |||
300 | #define ATH9K_DECOMP_MASK_SIZE 128 | ||
301 | #define ATH9K_READY_TIME_LO_BOUND 50 | ||
302 | #define ATH9K_READY_TIME_HI_BOUND 96 | ||
303 | |||
304 | enum ath9k_pkt_type { | ||
305 | ATH9K_PKT_TYPE_NORMAL = 0, | ||
306 | ATH9K_PKT_TYPE_ATIM, | ||
307 | ATH9K_PKT_TYPE_PSPOLL, | ||
308 | ATH9K_PKT_TYPE_BEACON, | ||
309 | ATH9K_PKT_TYPE_PROBE_RESP, | ||
310 | ATH9K_PKT_TYPE_CHIRP, | ||
311 | ATH9K_PKT_TYPE_GRP_POLL, | ||
312 | }; | ||
313 | |||
314 | struct ath9k_tx_queue_info { | ||
315 | u32 tqi_ver; | ||
316 | enum ath9k_tx_queue tqi_type; | ||
317 | enum ath9k_tx_queue_subtype tqi_subtype; | ||
318 | enum ath9k_tx_queue_flags tqi_qflags; | ||
319 | u32 tqi_priority; | ||
320 | u32 tqi_aifs; | ||
321 | u32 tqi_cwmin; | ||
322 | u32 tqi_cwmax; | ||
323 | u16 tqi_shretry; | ||
324 | u16 tqi_lgretry; | ||
325 | u32 tqi_cbrPeriod; | ||
326 | u32 tqi_cbrOverflowLimit; | ||
327 | u32 tqi_burstTime; | ||
328 | u32 tqi_readyTime; | ||
329 | u32 tqi_physCompBuf; | ||
330 | u32 tqi_intFlags; | ||
331 | }; | ||
332 | |||
333 | enum ath9k_rx_filter { | ||
334 | ATH9K_RX_FILTER_UCAST = 0x00000001, | ||
335 | ATH9K_RX_FILTER_MCAST = 0x00000002, | ||
336 | ATH9K_RX_FILTER_BCAST = 0x00000004, | ||
337 | ATH9K_RX_FILTER_CONTROL = 0x00000008, | ||
338 | ATH9K_RX_FILTER_BEACON = 0x00000010, | ||
339 | ATH9K_RX_FILTER_PROM = 0x00000020, | ||
340 | ATH9K_RX_FILTER_PROBEREQ = 0x00000080, | ||
341 | ATH9K_RX_FILTER_PSPOLL = 0x00004000, | ||
342 | ATH9K_RX_FILTER_PHYERR = 0x00000100, | ||
343 | ATH9K_RX_FILTER_PHYRADAR = 0x00002000, | ||
344 | }; | ||
345 | |||
346 | enum ath9k_int { | ||
347 | ATH9K_INT_RX = 0x00000001, | ||
348 | ATH9K_INT_RXDESC = 0x00000002, | ||
349 | ATH9K_INT_RXNOFRM = 0x00000008, | ||
350 | ATH9K_INT_RXEOL = 0x00000010, | ||
351 | ATH9K_INT_RXORN = 0x00000020, | ||
352 | ATH9K_INT_TX = 0x00000040, | ||
353 | ATH9K_INT_TXDESC = 0x00000080, | ||
354 | ATH9K_INT_TIM_TIMER = 0x00000100, | ||
355 | ATH9K_INT_TXURN = 0x00000800, | ||
356 | ATH9K_INT_MIB = 0x00001000, | ||
357 | ATH9K_INT_RXPHY = 0x00004000, | ||
358 | ATH9K_INT_RXKCM = 0x00008000, | ||
359 | ATH9K_INT_SWBA = 0x00010000, | ||
360 | ATH9K_INT_BMISS = 0x00040000, | ||
361 | ATH9K_INT_BNR = 0x00100000, | ||
362 | ATH9K_INT_TIM = 0x00200000, | ||
363 | ATH9K_INT_DTIM = 0x00400000, | ||
364 | ATH9K_INT_DTIMSYNC = 0x00800000, | ||
365 | ATH9K_INT_GPIO = 0x01000000, | ||
366 | ATH9K_INT_CABEND = 0x02000000, | ||
367 | ATH9K_INT_CST = 0x10000000, | ||
368 | ATH9K_INT_GTT = 0x20000000, | ||
369 | ATH9K_INT_FATAL = 0x40000000, | ||
370 | ATH9K_INT_GLOBAL = 0x80000000, | ||
371 | ATH9K_INT_BMISC = ATH9K_INT_TIM | | ||
372 | ATH9K_INT_DTIM | | ||
373 | ATH9K_INT_DTIMSYNC | | ||
374 | ATH9K_INT_CABEND, | ||
375 | ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM | | ||
376 | ATH9K_INT_RXDESC | | ||
377 | ATH9K_INT_RXEOL | | ||
378 | ATH9K_INT_RXORN | | ||
379 | ATH9K_INT_TXURN | | ||
380 | ATH9K_INT_TXDESC | | ||
381 | ATH9K_INT_MIB | | ||
382 | ATH9K_INT_RXPHY | | ||
383 | ATH9K_INT_RXKCM | | ||
384 | ATH9K_INT_SWBA | | ||
385 | ATH9K_INT_BMISS | | ||
386 | ATH9K_INT_GPIO, | ||
387 | ATH9K_INT_NOCARD = 0xffffffff | ||
388 | }; | ||
389 | |||
390 | struct ath9k_rate_table { | ||
391 | int rateCount; | ||
392 | u8 rateCodeToIndex[256]; | ||
393 | struct { | ||
394 | u8 valid; | ||
395 | u8 phy; | ||
396 | u32 rateKbps; | ||
397 | u8 rateCode; | ||
398 | u8 shortPreamble; | ||
399 | u8 dot11Rate; | ||
400 | u8 controlRate; | ||
401 | u16 lpAckDuration; | ||
402 | u16 spAckDuration; | ||
403 | } info[32]; | ||
404 | }; | ||
405 | |||
406 | #define ATH9K_RATESERIES_RTS_CTS 0x0001 | ||
407 | #define ATH9K_RATESERIES_2040 0x0002 | ||
408 | #define ATH9K_RATESERIES_HALFGI 0x0004 | ||
409 | |||
410 | struct ath9k_11n_rate_series { | ||
411 | u32 Tries; | ||
412 | u32 Rate; | ||
413 | u32 PktDuration; | ||
414 | u32 ChSel; | ||
415 | u32 RateFlags; | ||
416 | }; | ||
417 | |||
418 | #define CHANNEL_CW_INT 0x00002 | ||
419 | #define CHANNEL_CCK 0x00020 | ||
420 | #define CHANNEL_OFDM 0x00040 | ||
421 | #define CHANNEL_2GHZ 0x00080 | ||
422 | #define CHANNEL_5GHZ 0x00100 | ||
423 | #define CHANNEL_PASSIVE 0x00200 | ||
424 | #define CHANNEL_DYN 0x00400 | ||
425 | #define CHANNEL_HALF 0x04000 | ||
426 | #define CHANNEL_QUARTER 0x08000 | ||
427 | #define CHANNEL_HT20 0x10000 | ||
428 | #define CHANNEL_HT40PLUS 0x20000 | ||
429 | #define CHANNEL_HT40MINUS 0x40000 | ||
430 | |||
431 | #define CHANNEL_INTERFERENCE 0x01 | ||
432 | #define CHANNEL_DFS 0x02 | ||
433 | #define CHANNEL_4MS_LIMIT 0x04 | ||
434 | #define CHANNEL_DFS_CLEAR 0x08 | ||
435 | #define CHANNEL_DISALLOW_ADHOC 0x10 | ||
436 | #define CHANNEL_PER_11D_ADHOC 0x20 | ||
437 | |||
438 | #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) | ||
439 | #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) | ||
440 | #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) | ||
441 | #define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20) | ||
442 | #define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20) | ||
443 | #define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS) | ||
444 | #define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS) | ||
445 | #define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS) | ||
446 | #define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS) | ||
447 | #define CHANNEL_ALL \ | ||
448 | (CHANNEL_OFDM| \ | ||
449 | CHANNEL_CCK| \ | ||
450 | CHANNEL_2GHZ | \ | ||
451 | CHANNEL_5GHZ | \ | ||
452 | CHANNEL_HT20 | \ | ||
453 | CHANNEL_HT40PLUS | \ | ||
454 | CHANNEL_HT40MINUS) | ||
455 | |||
456 | struct ath9k_channel { | ||
457 | u16 channel; | ||
458 | u32 channelFlags; | ||
459 | u8 privFlags; | ||
460 | int8_t maxRegTxPower; | ||
461 | int8_t maxTxPower; | ||
462 | int8_t minTxPower; | ||
463 | u32 chanmode; | ||
464 | int32_t CalValid; | ||
465 | bool oneTimeCalsDone; | ||
466 | int8_t iCoff; | ||
467 | int8_t qCoff; | ||
468 | int16_t rawNoiseFloor; | ||
469 | int8_t antennaMax; | ||
470 | u32 regDmnFlags; | ||
471 | u32 conformanceTestLimit[3]; /* 0:11a, 1: 11b, 2:11g */ | ||
472 | #ifdef ATH_NF_PER_CHAN | ||
473 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | ||
474 | #endif | ||
475 | }; | ||
476 | |||
477 | #define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \ | ||
478 | (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \ | ||
479 | (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \ | ||
480 | (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS)) | ||
481 | #define IS_CHAN_B(_c) (((_c)->channelFlags & CHANNEL_B) == CHANNEL_B) | ||
482 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | ||
483 | (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ | ||
484 | (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ | ||
485 | (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) | ||
486 | #define IS_CHAN_CCK(_c) (((_c)->channelFlags & CHANNEL_CCK) != 0) | ||
487 | #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) | ||
488 | #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) | ||
489 | #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) | ||
490 | #define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0) | ||
491 | #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) | ||
492 | #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) | ||
493 | |||
494 | /* These macros check chanmode and not channelFlags */ | ||
495 | #define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ | ||
496 | ((_c)->chanmode == CHANNEL_G_HT20)) | ||
497 | #define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ | ||
498 | ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \ | ||
499 | ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \ | ||
500 | ((_c)->chanmode == CHANNEL_G_HT40MINUS)) | ||
501 | #define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c))) | ||
502 | |||
503 | #define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990) | ||
504 | #define IS_CHAN_A_5MHZ_SPACED(_c) \ | ||
505 | ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ | ||
506 | (((_c)->channel % 20) != 0) && \ | ||
507 | (((_c)->channel % 10) != 0)) | ||
508 | |||
509 | struct ath9k_keyval { | ||
510 | u8 kv_type; | ||
511 | u8 kv_pad; | ||
512 | u16 kv_len; | ||
513 | u8 kv_val[16]; | ||
514 | u8 kv_mic[8]; | ||
515 | u8 kv_txmic[8]; | ||
516 | }; | ||
517 | |||
518 | enum ath9k_key_type { | ||
519 | ATH9K_KEY_TYPE_CLEAR, | ||
520 | ATH9K_KEY_TYPE_WEP, | ||
521 | ATH9K_KEY_TYPE_AES, | ||
522 | ATH9K_KEY_TYPE_TKIP, | ||
523 | }; | ||
524 | |||
525 | enum ath9k_cipher { | ||
526 | ATH9K_CIPHER_WEP = 0, | ||
527 | ATH9K_CIPHER_AES_OCB = 1, | ||
528 | ATH9K_CIPHER_AES_CCM = 2, | ||
529 | ATH9K_CIPHER_CKIP = 3, | ||
530 | ATH9K_CIPHER_TKIP = 4, | ||
531 | ATH9K_CIPHER_CLR = 5, | ||
532 | ATH9K_CIPHER_MIC = 127 | ||
533 | }; | ||
534 | |||
535 | #define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001 | ||
536 | #define AR_EEPROM_EEPCAP_AES_DIS 0x0002 | ||
537 | #define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004 | ||
538 | #define AR_EEPROM_EEPCAP_BURST_DIS 0x0008 | ||
539 | #define AR_EEPROM_EEPCAP_MAXQCU 0x01F0 | ||
540 | #define AR_EEPROM_EEPCAP_MAXQCU_S 4 | ||
541 | #define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200 | ||
542 | #define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000 | ||
543 | #define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12 | ||
544 | |||
545 | #define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 | ||
546 | #define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 | ||
547 | #define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100 | ||
548 | #define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 | ||
549 | #define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 | ||
550 | #define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 | ||
551 | |||
552 | #define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000 | ||
553 | #define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000 | ||
554 | |||
555 | #define SD_NO_CTL 0xE0 | ||
556 | #define NO_CTL 0xff | ||
557 | #define CTL_MODE_M 7 | ||
558 | #define CTL_11A 0 | ||
559 | #define CTL_11B 1 | ||
560 | #define CTL_11G 2 | ||
561 | #define CTL_2GHT20 5 | ||
562 | #define CTL_5GHT20 6 | ||
563 | #define CTL_2GHT40 7 | ||
564 | #define CTL_5GHT40 8 | ||
565 | |||
566 | #define AR_EEPROM_MAC(i) (0x1d+(i)) | ||
567 | #define EEP_SCALE 100 | ||
568 | #define EEP_DELTA 10 | ||
569 | |||
570 | #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c | ||
571 | #define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 | ||
572 | #define AR_EEPROM_RFSILENT_POLARITY 0x0002 | ||
573 | #define AR_EEPROM_RFSILENT_POLARITY_S 1 | ||
574 | |||
575 | #define CTRY_DEBUG 0x1ff | ||
576 | #define CTRY_DEFAULT 0 | ||
577 | |||
578 | enum reg_ext_bitmap { | ||
579 | REG_EXT_JAPAN_MIDBAND = 1, | ||
580 | REG_EXT_FCC_DFS_HT40 = 2, | ||
581 | REG_EXT_JAPAN_NONDFS_HT40 = 3, | ||
582 | REG_EXT_JAPAN_DFS_HT40 = 4 | ||
583 | }; | ||
584 | |||
585 | struct ath9k_country_entry { | ||
586 | u16 countryCode; | ||
587 | u16 regDmnEnum; | ||
588 | u16 regDmn5G; | ||
589 | u16 regDmn2G; | ||
590 | u8 isMultidomain; | ||
591 | u8 iso[3]; | ||
592 | }; | ||
593 | |||
594 | #define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg) | ||
595 | #define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg) | ||
596 | |||
597 | #define SM(_v, _f) (((_v) << _f##_S) & _f) | ||
598 | #define MS(_v, _f) (((_v) & _f) >> _f##_S) | ||
599 | #define REG_RMW(_a, _r, _set, _clr) \ | ||
600 | REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set)) | ||
601 | #define REG_RMW_FIELD(_a, _r, _f, _v) \ | ||
602 | REG_WRITE(_a, _r, \ | ||
603 | (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) | ||
604 | #define REG_SET_BIT(_a, _r, _f) \ | ||
605 | REG_WRITE(_a, _r, REG_READ(_a, _r) | _f) | ||
606 | #define REG_CLR_BIT(_a, _r, _f) \ | ||
607 | REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) | ||
608 | |||
609 | #define ATH9K_COMP_BUF_MAX_SIZE 9216 | ||
610 | #define ATH9K_COMP_BUF_ALIGN_SIZE 512 | ||
611 | |||
612 | #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 | ||
613 | |||
614 | #define INIT_AIFS 2 | ||
615 | #define INIT_CWMIN 15 | ||
616 | #define INIT_CWMIN_11B 31 | ||
617 | #define INIT_CWMAX 1023 | ||
618 | #define INIT_SH_RETRY 10 | ||
619 | #define INIT_LG_RETRY 10 | ||
620 | #define INIT_SSH_RETRY 32 | ||
621 | #define INIT_SLG_RETRY 32 | ||
622 | |||
623 | #define WLAN_CTRL_FRAME_SIZE (2+2+6+4) | ||
624 | |||
625 | #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) | ||
626 | #define ATH_AMPDU_LIMIT_DEFAULT ATH_AMPDU_LIMIT_MAX | ||
627 | |||
628 | #define IEEE80211_WEP_IVLEN 3 | ||
629 | #define IEEE80211_WEP_KIDLEN 1 | ||
630 | #define IEEE80211_WEP_CRCLEN 4 | ||
631 | #define IEEE80211_MAX_MPDU_LEN (3840 + FCS_LEN + \ | ||
632 | (IEEE80211_WEP_IVLEN + \ | ||
633 | IEEE80211_WEP_KIDLEN + \ | ||
634 | IEEE80211_WEP_CRCLEN)) | ||
635 | #define IEEE80211_MAX_LEN (2300 + FCS_LEN + \ | ||
636 | (IEEE80211_WEP_IVLEN + \ | ||
637 | IEEE80211_WEP_KIDLEN + \ | ||
638 | IEEE80211_WEP_CRCLEN)) | ||
639 | |||
640 | #define MAX_REG_ADD_COUNT 129 | ||
641 | #define MAX_RATE_POWER 63 | ||
642 | |||
643 | enum ath9k_power_mode { | ||
644 | ATH9K_PM_AWAKE = 0, | ||
645 | ATH9K_PM_FULL_SLEEP, | ||
646 | ATH9K_PM_NETWORK_SLEEP, | ||
647 | ATH9K_PM_UNDEFINED | ||
648 | }; | ||
649 | |||
650 | struct ath9k_mib_stats { | ||
651 | u32 ackrcv_bad; | ||
652 | u32 rts_bad; | ||
653 | u32 rts_good; | ||
654 | u32 fcs_bad; | ||
655 | u32 beacons; | ||
656 | }; | ||
657 | |||
658 | enum ath9k_ant_setting { | ||
659 | ATH9K_ANT_VARIABLE = 0, | ||
660 | ATH9K_ANT_FIXED_A, | ||
661 | ATH9K_ANT_FIXED_B | ||
662 | }; | ||
663 | |||
664 | enum ath9k_opmode { | ||
665 | ATH9K_M_STA = 1, | ||
666 | ATH9K_M_IBSS = 0, | ||
667 | ATH9K_M_HOSTAP = 6, | ||
668 | ATH9K_M_MONITOR = 8 | ||
669 | }; | ||
670 | |||
671 | #define ATH9K_SLOT_TIME_6 6 | ||
672 | #define ATH9K_SLOT_TIME_9 9 | ||
673 | #define ATH9K_SLOT_TIME_20 20 | ||
674 | |||
675 | enum ath9k_ht_macmode { | ||
676 | ATH9K_HT_MACMODE_20 = 0, | ||
677 | ATH9K_HT_MACMODE_2040 = 1, | ||
678 | }; | ||
679 | |||
680 | enum ath9k_ht_extprotspacing { | ||
681 | ATH9K_HT_EXTPROTSPACING_20 = 0, | ||
682 | ATH9K_HT_EXTPROTSPACING_25 = 1, | ||
683 | }; | ||
684 | |||
685 | struct ath9k_ht_cwm { | ||
686 | enum ath9k_ht_macmode ht_macmode; | ||
687 | enum ath9k_ht_extprotspacing ht_extprotspacing; | ||
688 | }; | ||
689 | |||
690 | enum ath9k_ani_cmd { | ||
691 | ATH9K_ANI_PRESENT = 0x1, | ||
692 | ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, | ||
693 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4, | ||
694 | ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8, | ||
695 | ATH9K_ANI_FIRSTEP_LEVEL = 0x10, | ||
696 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, | ||
697 | ATH9K_ANI_MODE = 0x40, | ||
698 | ATH9K_ANI_PHYERR_RESET = 0x80, | ||
699 | ATH9K_ANI_ALL = 0xff | ||
700 | }; | ||
701 | |||
702 | enum phytype { | ||
703 | PHY_DS, | ||
704 | PHY_FH, | ||
705 | PHY_OFDM, | ||
706 | PHY_HT, | ||
707 | }; | ||
708 | #define PHY_CCK PHY_DS | ||
709 | |||
710 | enum start_adhoc_option { | ||
711 | START_ADHOC_NO_11A, | ||
712 | START_ADHOC_PER_11D, | ||
713 | START_ADHOC_IN_11A, | ||
714 | START_ADHOC_IN_11B, | ||
715 | }; | ||
716 | |||
717 | enum ath9k_tp_scale { | ||
718 | ATH9K_TP_SCALE_MAX = 0, | ||
719 | ATH9K_TP_SCALE_50, | ||
720 | ATH9K_TP_SCALE_25, | ||
721 | ATH9K_TP_SCALE_12, | ||
722 | ATH9K_TP_SCALE_MIN | ||
723 | }; | ||
724 | |||
725 | enum ser_reg_mode { | ||
726 | SER_REG_MODE_OFF = 0, | ||
727 | SER_REG_MODE_ON = 1, | ||
728 | SER_REG_MODE_AUTO = 2, | ||
729 | }; | ||
730 | |||
731 | #define AR_PHY_CCA_MAX_GOOD_VALUE -85 | ||
732 | #define AR_PHY_CCA_MAX_HIGH_VALUE -62 | ||
733 | #define AR_PHY_CCA_MIN_BAD_VALUE -121 | ||
734 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 | ||
735 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 | ||
736 | |||
737 | #define ATH9K_NF_CAL_HIST_MAX 5 | ||
738 | #define NUM_NF_READINGS 6 | ||
739 | |||
740 | struct ath9k_nfcal_hist { | ||
741 | int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX]; | ||
742 | u8 currIndex; | ||
743 | int16_t privNF; | ||
744 | u8 invalidNFcount; | ||
745 | }; | ||
746 | |||
747 | struct ath9k_beacon_state { | ||
748 | u32 bs_nexttbtt; | ||
749 | u32 bs_nextdtim; | ||
750 | u32 bs_intval; | ||
751 | #define ATH9K_BEACON_PERIOD 0x0000ffff | ||
752 | #define ATH9K_BEACON_ENA 0x00800000 | ||
753 | #define ATH9K_BEACON_RESET_TSF 0x01000000 | ||
754 | u32 bs_dtimperiod; | ||
755 | u16 bs_cfpperiod; | ||
756 | u16 bs_cfpmaxduration; | ||
757 | u32 bs_cfpnext; | ||
758 | u16 bs_timoffset; | ||
759 | u16 bs_bmissthreshold; | ||
760 | u32 bs_sleepduration; | ||
761 | }; | ||
762 | |||
763 | struct ath9k_node_stats { | ||
764 | u32 ns_avgbrssi; | ||
765 | u32 ns_avgrssi; | ||
766 | u32 ns_avgtxrssi; | ||
767 | u32 ns_avgtxrate; | ||
768 | }; | ||
769 | |||
770 | #define ATH9K_RSSI_EP_MULTIPLIER (1<<7) | ||
771 | |||
772 | enum ath9k_gpio_output_mux_type { | ||
773 | ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT, | ||
774 | ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, | ||
775 | ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, | ||
776 | ATH9K_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, | ||
777 | ATH9K_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, | ||
778 | ATH9K_GPIO_OUTPUT_MUX_NUM_ENTRIES | ||
779 | }; | ||
780 | |||
781 | enum { | ||
782 | ATH9K_RESET_POWER_ON, | ||
783 | ATH9K_RESET_WARM, | ||
784 | ATH9K_RESET_COLD, | ||
785 | }; | ||
786 | |||
787 | #define AH_USE_EEPROM 0x1 | ||
788 | |||
789 | struct ath_hal { | ||
790 | u32 ah_magic; | ||
791 | u16 ah_devid; | ||
792 | u16 ah_subvendorid; | ||
793 | struct ath_softc *ah_sc; | ||
794 | void __iomem *ah_sh; | ||
795 | u16 ah_countryCode; | ||
796 | u32 ah_macVersion; | ||
797 | u16 ah_macRev; | ||
798 | u16 ah_phyRev; | ||
799 | u16 ah_analog5GhzRev; | ||
800 | u16 ah_analog2GhzRev; | ||
801 | u8 ah_decompMask[ATH9K_DECOMP_MASK_SIZE]; | ||
802 | u32 ah_flags; | ||
803 | enum ath9k_opmode ah_opmode; | ||
804 | struct ath9k_ops_config ah_config; | ||
805 | struct ath9k_hw_capabilities ah_caps; | ||
806 | int16_t ah_powerLimit; | ||
807 | u16 ah_maxPowerLevel; | ||
808 | u32 ah_tpScale; | ||
809 | u16 ah_currentRD; | ||
810 | u16 ah_currentRDExt; | ||
811 | u16 ah_currentRDInUse; | ||
812 | u16 ah_currentRD5G; | ||
813 | u16 ah_currentRD2G; | ||
814 | char ah_iso[4]; | ||
815 | enum start_adhoc_option ah_adHocMode; | ||
816 | bool ah_commonMode; | ||
817 | struct ath9k_channel ah_channels[150]; | ||
818 | u32 ah_nchan; | ||
819 | struct ath9k_channel *ah_curchan; | ||
820 | u16 ah_rfsilent; | ||
821 | bool ah_rfkillEnabled; | ||
822 | bool ah_isPciExpress; | ||
823 | u16 ah_txTrigLevel; | ||
824 | #ifndef ATH_NF_PER_CHAN | ||
825 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | ||
826 | #endif | ||
827 | }; | ||
828 | |||
829 | struct chan_centers { | ||
830 | u16 synth_center; | ||
831 | u16 ctl_center; | ||
832 | u16 ext_center; | ||
833 | }; | ||
834 | |||
835 | int ath_hal_getcapability(struct ath_hal *ah, | ||
836 | enum ath9k_capability_type type, | ||
837 | u32 capability, | ||
838 | u32 *result); | ||
839 | const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah, | ||
840 | u32 mode); | ||
841 | void ath9k_hw_detach(struct ath_hal *ah); | ||
842 | struct ath_hal *ath9k_hw_attach(u16 devid, | ||
843 | struct ath_softc *sc, | ||
844 | void __iomem *mem, | ||
845 | int *error); | ||
846 | bool ath9k_regd_init_channels(struct ath_hal *ah, | ||
847 | u32 maxchans, u32 *nchans, | ||
848 | u8 *regclassids, | ||
849 | u32 maxregids, u32 *nregids, | ||
850 | u16 cc, | ||
851 | bool enableOutdoor, | ||
852 | bool enableExtendedChannels); | ||
853 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); | ||
854 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, | ||
855 | enum ath9k_int ints); | ||
856 | bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | ||
857 | struct ath9k_channel *chan, | ||
858 | enum ath9k_ht_macmode macmode, | ||
859 | u8 txchainmask, u8 rxchainmask, | ||
860 | enum ath9k_ht_extprotspacing extprotspacing, | ||
861 | bool bChannelChange, | ||
862 | int *status); | ||
863 | bool ath9k_hw_phy_disable(struct ath_hal *ah); | ||
864 | void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan, | ||
865 | bool *isCalDone); | ||
866 | void ath9k_hw_ani_monitor(struct ath_hal *ah, | ||
867 | const struct ath9k_node_stats *stats, | ||
868 | struct ath9k_channel *chan); | ||
869 | bool ath9k_hw_calibrate(struct ath_hal *ah, | ||
870 | struct ath9k_channel *chan, | ||
871 | u8 rxchainmask, | ||
872 | bool longcal, | ||
873 | bool *isCalDone); | ||
874 | int16_t ath9k_hw_getchan_noise(struct ath_hal *ah, | ||
875 | struct ath9k_channel *chan); | ||
876 | void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, | ||
877 | u16 assocId); | ||
878 | void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits); | ||
879 | void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, | ||
880 | u16 assocId); | ||
881 | bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q); | ||
882 | void ath9k_hw_reset_tsf(struct ath_hal *ah); | ||
883 | bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry); | ||
884 | bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, | ||
885 | const u8 *mac); | ||
886 | bool ath9k_hw_set_keycache_entry(struct ath_hal *ah, | ||
887 | u16 entry, | ||
888 | const struct ath9k_keyval *k, | ||
889 | const u8 *mac, | ||
890 | int xorKey); | ||
891 | bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, | ||
892 | u32 setting); | ||
893 | void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore); | ||
894 | bool ath9k_hw_intrpend(struct ath_hal *ah); | ||
895 | bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked); | ||
896 | bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, | ||
897 | bool bIncTrigLevel); | ||
898 | void ath9k_hw_procmibevent(struct ath_hal *ah, | ||
899 | const struct ath9k_node_stats *stats); | ||
900 | bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set); | ||
901 | void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode); | ||
902 | bool ath9k_hw_phycounters(struct ath_hal *ah); | ||
903 | bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry); | ||
904 | bool ath9k_hw_getcapability(struct ath_hal *ah, | ||
905 | enum ath9k_capability_type type, | ||
906 | u32 capability, | ||
907 | u32 *result); | ||
908 | bool ath9k_hw_setcapability(struct ath_hal *ah, | ||
909 | enum ath9k_capability_type type, | ||
910 | u32 capability, | ||
911 | u32 setting, | ||
912 | int *status); | ||
913 | u32 ath9k_hw_getdefantenna(struct ath_hal *ah); | ||
914 | void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac); | ||
915 | void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask); | ||
916 | bool ath9k_hw_setbssidmask(struct ath_hal *ah, | ||
917 | const u8 *mask); | ||
918 | bool ath9k_hw_setpower(struct ath_hal *ah, | ||
919 | enum ath9k_power_mode mode); | ||
920 | enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah); | ||
921 | u64 ath9k_hw_gettsf64(struct ath_hal *ah); | ||
922 | u32 ath9k_hw_getdefantenna(struct ath_hal *ah); | ||
923 | bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us); | ||
924 | bool ath9k_hw_setantennaswitch(struct ath_hal *ah, | ||
925 | enum ath9k_ant_setting settings, | ||
926 | struct ath9k_channel *chan, | ||
927 | u8 *tx_chainmask, | ||
928 | u8 *rx_chainmask, | ||
929 | u8 *antenna_cfgd); | ||
930 | void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna); | ||
931 | int ath9k_hw_select_antconfig(struct ath_hal *ah, | ||
932 | u32 cfg); | ||
933 | bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, | ||
934 | u32 txdp); | ||
935 | bool ath9k_hw_txstart(struct ath_hal *ah, u32 q); | ||
936 | u16 ath9k_hw_computetxtime(struct ath_hal *ah, | ||
937 | const struct ath9k_rate_table *rates, | ||
938 | u32 frameLen, u16 rateix, | ||
939 | bool shortPreamble); | ||
940 | void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds, | ||
941 | struct ath_desc *lastds, | ||
942 | u32 durUpdateEn, u32 rtsctsRate, | ||
943 | u32 rtsctsDuration, | ||
944 | struct ath9k_11n_rate_series series[], | ||
945 | u32 nseries, u32 flags); | ||
946 | void ath9k_hw_set11n_burstduration(struct ath_hal *ah, | ||
947 | struct ath_desc *ds, | ||
948 | u32 burstDuration); | ||
949 | void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds); | ||
950 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); | ||
951 | bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q); | ||
952 | u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan); | ||
953 | u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah, | ||
954 | struct ath9k_channel *chan); | ||
955 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); | ||
956 | bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q, | ||
957 | struct ath9k_tx_queue_info *qinfo); | ||
958 | bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q, | ||
959 | const struct ath9k_tx_queue_info *qinfo); | ||
960 | struct ath9k_channel *ath9k_regd_check_channel(struct ath_hal *ah, | ||
961 | const struct ath9k_channel *c); | ||
962 | void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
963 | u32 pktLen, enum ath9k_pkt_type type, | ||
964 | u32 txPower, u32 keyIx, | ||
965 | enum ath9k_key_type keyType, u32 flags); | ||
966 | bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
967 | u32 segLen, bool firstSeg, | ||
968 | bool lastSeg, | ||
969 | const struct ath_desc *ds0); | ||
970 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah, | ||
971 | u32 *rxc_pcnt, | ||
972 | u32 *rxf_pcnt, | ||
973 | u32 *txf_pcnt); | ||
974 | void ath9k_hw_dmaRegDump(struct ath_hal *ah); | ||
975 | void ath9k_hw_beaconinit(struct ath_hal *ah, | ||
976 | u32 next_beacon, u32 beacon_period); | ||
977 | void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah, | ||
978 | const struct ath9k_beacon_state *bs); | ||
979 | bool ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
980 | u32 size, u32 flags); | ||
981 | void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp); | ||
982 | void ath9k_hw_rxena(struct ath_hal *ah); | ||
983 | void ath9k_hw_setopmode(struct ath_hal *ah); | ||
984 | bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac); | ||
985 | void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, | ||
986 | u32 filter1); | ||
987 | u32 ath9k_hw_getrxfilter(struct ath_hal *ah); | ||
988 | void ath9k_hw_startpcureceive(struct ath_hal *ah); | ||
989 | void ath9k_hw_stoppcurecv(struct ath_hal *ah); | ||
990 | bool ath9k_hw_stopdmarecv(struct ath_hal *ah); | ||
991 | int ath9k_hw_rxprocdesc(struct ath_hal *ah, | ||
992 | struct ath_desc *ds, u32 pa, | ||
993 | struct ath_desc *nds, u64 tsf); | ||
994 | u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q); | ||
995 | int ath9k_hw_txprocdesc(struct ath_hal *ah, | ||
996 | struct ath_desc *ds); | ||
997 | void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds, | ||
998 | u32 numDelims); | ||
999 | void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds, | ||
1000 | u32 aggrLen); | ||
1001 | void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds); | ||
1002 | bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q); | ||
1003 | void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs); | ||
1004 | void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds); | ||
1005 | void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, | ||
1006 | struct ath_desc *ds, u32 vmf); | ||
1007 | bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit); | ||
1008 | bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah); | ||
1009 | int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type, | ||
1010 | const struct ath9k_tx_queue_info *qinfo); | ||
1011 | u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q); | ||
1012 | const char *ath9k_hw_probe(u16 vendorid, u16 devid); | ||
1013 | bool ath9k_hw_disable(struct ath_hal *ah); | ||
1014 | void ath9k_hw_rfdetach(struct ath_hal *ah); | ||
1015 | void ath9k_hw_get_channel_centers(struct ath_hal *ah, | ||
1016 | struct ath9k_channel *chan, | ||
1017 | struct chan_centers *centers); | ||
1018 | bool ath9k_get_channel_edges(struct ath_hal *ah, | ||
1019 | u16 flags, u16 *low, | ||
1020 | u16 *high); | ||
1021 | #endif | ||
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c new file mode 100644 index 000000000000..caf569401a34 --- /dev/null +++ b/drivers/net/wireless/ath9k/beacon.c | |||
@@ -0,0 +1,979 @@ | |||
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_tx_queue_info qi; | ||
34 | |||
35 | ath9k_hw_get_txq_props(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_set_txq_props(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 && | ||
89 | (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) { | ||
90 | ds->ds_link = bf->bf_daddr; /* self-linked */ | ||
91 | flags |= ATH9K_TXDESC_VEOL; | ||
92 | /* Let hardware handle antenna switching. */ | ||
93 | antenna = 0; | ||
94 | } else { | ||
95 | ds->ds_link = 0; | ||
96 | /* | ||
97 | * Switch antenna every beacon. | ||
98 | * Should only switch every beacon period, not for every | ||
99 | * SWBA's | ||
100 | * XXX assumes two antenna | ||
101 | */ | ||
102 | antenna = ((sc->ast_be_xmit / sc->sc_nbcnvaps) & 1 ? 2 : 1); | ||
103 | } | ||
104 | |||
105 | ds->ds_data = bf->bf_buf_addr; | ||
106 | |||
107 | /* | ||
108 | * Calculate rate code. | ||
109 | * XXX everything at min xmit rate | ||
110 | */ | ||
111 | rix = 0; | ||
112 | rt = sc->sc_currates; | ||
113 | rate = rt->info[rix].rateCode; | ||
114 | if (sc->sc_flags & ATH_PREAMBLE_SHORT) | ||
115 | rate |= rt->info[rix].shortPreamble; | ||
116 | |||
117 | ath9k_hw_set11n_txdesc(ah, ds | ||
118 | , skb->len + FCS_LEN /* frame length */ | ||
119 | , ATH9K_PKT_TYPE_BEACON /* Atheros packet type */ | ||
120 | , avp->av_btxctl.txpower /* txpower XXX */ | ||
121 | , ATH9K_TXKEYIX_INVALID /* no encryption */ | ||
122 | , ATH9K_KEY_TYPE_CLEAR /* no encryption */ | ||
123 | , flags /* no ack, veol for beacons */ | ||
124 | ); | ||
125 | |||
126 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | ||
127 | ath9k_hw_filltxdesc(ah, ds | ||
128 | , roundup(skb->len, 4) /* buffer length */ | ||
129 | , true /* first segment */ | ||
130 | , true /* last segment */ | ||
131 | , ds /* first descriptor */ | ||
132 | ); | ||
133 | |||
134 | memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); | ||
135 | series[0].Tries = 1; | ||
136 | series[0].Rate = rate; | ||
137 | series[0].ChSel = sc->sc_tx_chainmask; | ||
138 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; | ||
139 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, | ||
140 | ctsrate, ctsduration, series, 4, 0); | ||
141 | } | ||
142 | |||
143 | /* Move everything from the vap's mcast queue to the hardware cab queue. | ||
144 | * Caller must hold mcasq lock and cabq lock | ||
145 | * XXX MORE_DATA bit? | ||
146 | */ | ||
147 | static void empty_mcastq_into_cabq(struct ath_hal *ah, | ||
148 | struct ath_txq *mcastq, struct ath_txq *cabq) | ||
149 | { | ||
150 | struct ath_buf *bfmcast; | ||
151 | |||
152 | BUG_ON(list_empty(&mcastq->axq_q)); | ||
153 | |||
154 | bfmcast = list_first_entry(&mcastq->axq_q, struct ath_buf, list); | ||
155 | |||
156 | /* link the descriptors */ | ||
157 | if (!cabq->axq_link) | ||
158 | ath9k_hw_puttxbuf(ah, cabq->axq_qnum, bfmcast->bf_daddr); | ||
159 | else | ||
160 | *cabq->axq_link = bfmcast->bf_daddr; | ||
161 | |||
162 | /* append the private vap mcast list to the cabq */ | ||
163 | |||
164 | cabq->axq_depth += mcastq->axq_depth; | ||
165 | cabq->axq_totalqueued += mcastq->axq_totalqueued; | ||
166 | cabq->axq_linkbuf = mcastq->axq_linkbuf; | ||
167 | cabq->axq_link = mcastq->axq_link; | ||
168 | list_splice_tail_init(&mcastq->axq_q, &cabq->axq_q); | ||
169 | mcastq->axq_depth = 0; | ||
170 | mcastq->axq_totalqueued = 0; | ||
171 | mcastq->axq_linkbuf = NULL; | ||
172 | mcastq->axq_link = NULL; | ||
173 | } | ||
174 | |||
175 | /* This is only run at DTIM. We move everything from the vap's mcast queue | ||
176 | * to the hardware cab queue. Caller must hold the mcastq lock. */ | ||
177 | static void trigger_mcastq(struct ath_hal *ah, | ||
178 | struct ath_txq *mcastq, struct ath_txq *cabq) | ||
179 | { | ||
180 | spin_lock_bh(&cabq->axq_lock); | ||
181 | |||
182 | if (!list_empty(&mcastq->axq_q)) | ||
183 | empty_mcastq_into_cabq(ah, mcastq, cabq); | ||
184 | |||
185 | /* cabq is gated by beacon so it is safe to start here */ | ||
186 | if (!list_empty(&cabq->axq_q)) | ||
187 | ath9k_hw_txstart(ah, cabq->axq_qnum); | ||
188 | |||
189 | spin_unlock_bh(&cabq->axq_lock); | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * Generate beacon frame and queue cab data for a vap. | ||
194 | * | ||
195 | * Updates the contents of the beacon frame. It is assumed that the buffer for | ||
196 | * the beacon frame has been allocated in the ATH object, and simply needs to | ||
197 | * be filled for this cycle. Also, any CAB (crap after beacon?) traffic will | ||
198 | * be added to the beacon frame at this point. | ||
199 | */ | ||
200 | static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | ||
201 | { | ||
202 | struct ath_hal *ah = sc->sc_ah; | ||
203 | struct ath_buf *bf; | ||
204 | struct ath_vap *avp; | ||
205 | struct sk_buff *skb; | ||
206 | int cabq_depth; | ||
207 | int mcastq_depth; | ||
208 | int is_beacon_dtim = 0; | ||
209 | unsigned int curlen; | ||
210 | struct ath_txq *cabq; | ||
211 | struct ath_txq *mcastq; | ||
212 | avp = sc->sc_vaps[if_id]; | ||
213 | |||
214 | mcastq = &avp->av_mcastq; | ||
215 | cabq = sc->sc_cabq; | ||
216 | |||
217 | ASSERT(avp); | ||
218 | |||
219 | if (avp->av_bcbuf == NULL) { | ||
220 | DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", | ||
221 | __func__, avp, avp->av_bcbuf); | ||
222 | return NULL; | ||
223 | } | ||
224 | bf = avp->av_bcbuf; | ||
225 | skb = (struct sk_buff *) bf->bf_mpdu; | ||
226 | |||
227 | /* | ||
228 | * Update dynamic beacon contents. If this returns | ||
229 | * non-zero then we need to remap the memory because | ||
230 | * the beacon frame changed size (probably because | ||
231 | * of the TIM bitmap). | ||
232 | */ | ||
233 | curlen = skb->len; | ||
234 | |||
235 | /* XXX: spin_lock_bh should not be used here, but sparse bitches | ||
236 | * otherwise. We should fix sparse :) */ | ||
237 | spin_lock_bh(&mcastq->axq_lock); | ||
238 | mcastq_depth = avp->av_mcastq.axq_depth; | ||
239 | |||
240 | if (ath_update_beacon(sc, if_id, &avp->av_boff, skb, mcastq_depth) == | ||
241 | 1) { | ||
242 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
243 | get_dma_mem_context(bf, bf_dmacontext)); | ||
244 | bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE, | ||
245 | get_dma_mem_context(bf, bf_dmacontext)); | ||
246 | } else { | ||
247 | pci_dma_sync_single_for_cpu(sc->pdev, | ||
248 | bf->bf_buf_addr, | ||
249 | skb_tailroom(skb), | ||
250 | PCI_DMA_TODEVICE); | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * if the CABQ traffic from previous DTIM is pending and the current | ||
255 | * beacon is also a DTIM. | ||
256 | * 1) if there is only one vap let the cab traffic continue. | ||
257 | * 2) if there are more than one vap and we are using staggered | ||
258 | * beacons, then drain the cabq by dropping all the frames in | ||
259 | * the cabq so that the current vaps cab traffic can be scheduled. | ||
260 | */ | ||
261 | spin_lock_bh(&cabq->axq_lock); | ||
262 | cabq_depth = cabq->axq_depth; | ||
263 | spin_unlock_bh(&cabq->axq_lock); | ||
264 | |||
265 | is_beacon_dtim = avp->av_boff.bo_tim[4] & 1; | ||
266 | |||
267 | if (mcastq_depth && is_beacon_dtim && cabq_depth) { | ||
268 | /* | ||
269 | * Unlock the cabq lock as ath_tx_draintxq acquires | ||
270 | * the lock again which is a common function and that | ||
271 | * acquires txq lock inside. | ||
272 | */ | ||
273 | if (sc->sc_nvaps > 1) { | ||
274 | ath_tx_draintxq(sc, cabq, false); | ||
275 | DPRINTF(sc, ATH_DBG_BEACON, | ||
276 | "%s: flush previous cabq traffic\n", __func__); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | /* Construct tx descriptor. */ | ||
281 | ath_beacon_setup(sc, avp, bf); | ||
282 | |||
283 | /* | ||
284 | * Enable the CAB queue before the beacon queue to | ||
285 | * insure cab frames are triggered by this beacon. | ||
286 | */ | ||
287 | if (is_beacon_dtim) | ||
288 | trigger_mcastq(ah, mcastq, cabq); | ||
289 | |||
290 | spin_unlock_bh(&mcastq->axq_lock); | ||
291 | return bf; | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * Startup beacon transmission for adhoc mode when they are sent entirely | ||
296 | * by the hardware using the self-linked descriptor + veol trick. | ||
297 | */ | ||
298 | |||
299 | static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) | ||
300 | { | ||
301 | struct ath_hal *ah = sc->sc_ah; | ||
302 | struct ath_buf *bf; | ||
303 | struct ath_vap *avp; | ||
304 | struct sk_buff *skb; | ||
305 | |||
306 | avp = sc->sc_vaps[if_id]; | ||
307 | ASSERT(avp); | ||
308 | |||
309 | if (avp->av_bcbuf == NULL) { | ||
310 | DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", | ||
311 | __func__, avp, avp != NULL ? avp->av_bcbuf : NULL); | ||
312 | return; | ||
313 | } | ||
314 | bf = avp->av_bcbuf; | ||
315 | skb = (struct sk_buff *) bf->bf_mpdu; | ||
316 | |||
317 | /* Construct tx descriptor. */ | ||
318 | ath_beacon_setup(sc, avp, bf); | ||
319 | |||
320 | /* NB: caller is known to have already stopped tx dma */ | ||
321 | ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr); | ||
322 | ath9k_hw_txstart(ah, sc->sc_bhalq); | ||
323 | DPRINTF(sc, ATH_DBG_BEACON, "%s: TXDP%u = %llx (%p)\n", __func__, | ||
324 | sc->sc_bhalq, ito64(bf->bf_daddr), bf->bf_desc); | ||
325 | } | ||
326 | |||
327 | /* | ||
328 | * Setup a h/w transmit queue for beacons. | ||
329 | * | ||
330 | * This function allocates an information structure (struct ath9k_txq_info) | ||
331 | * on the stack, sets some specific parameters (zero out channel width | ||
332 | * min/max, and enable aifs). The info structure does not need to be | ||
333 | * persistant. | ||
334 | */ | ||
335 | |||
336 | int ath_beaconq_setup(struct ath_hal *ah) | ||
337 | { | ||
338 | struct ath9k_tx_queue_info qi; | ||
339 | |||
340 | memzero(&qi, sizeof(qi)); | ||
341 | qi.tqi_aifs = 1; | ||
342 | qi.tqi_cwmin = 0; | ||
343 | qi.tqi_cwmax = 0; | ||
344 | /* NB: don't enable any interrupts */ | ||
345 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); | ||
346 | } | ||
347 | |||
348 | |||
349 | /* | ||
350 | * Allocate and setup an initial beacon frame. | ||
351 | * | ||
352 | * Allocate a beacon state variable for a specific VAP instance created on | ||
353 | * the ATH interface. This routine also calculates the beacon "slot" for | ||
354 | * staggared beacons in the mBSSID case. | ||
355 | */ | ||
356 | |||
357 | int ath_beacon_alloc(struct ath_softc *sc, int if_id) | ||
358 | { | ||
359 | struct ath_vap *avp; | ||
360 | struct ieee80211_hdr *wh; | ||
361 | struct ath_buf *bf; | ||
362 | struct sk_buff *skb; | ||
363 | |||
364 | avp = sc->sc_vaps[if_id]; | ||
365 | ASSERT(avp); | ||
366 | |||
367 | /* Allocate a beacon descriptor if we haven't done so. */ | ||
368 | if (!avp->av_bcbuf) { | ||
369 | /* | ||
370 | * Allocate beacon state for hostap/ibss. We know | ||
371 | * a buffer is available. | ||
372 | */ | ||
373 | |||
374 | avp->av_bcbuf = list_first_entry(&sc->sc_bbuf, | ||
375 | struct ath_buf, list); | ||
376 | list_del(&avp->av_bcbuf->list); | ||
377 | |||
378 | if (sc->sc_opmode == ATH9K_M_HOSTAP || | ||
379 | !(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) { | ||
380 | int slot; | ||
381 | /* | ||
382 | * Assign the vap to a beacon xmit slot. As | ||
383 | * above, this cannot fail to find one. | ||
384 | */ | ||
385 | avp->av_bslot = 0; | ||
386 | for (slot = 0; slot < ATH_BCBUF; slot++) | ||
387 | if (sc->sc_bslot[slot] == ATH_IF_ID_ANY) { | ||
388 | /* | ||
389 | * XXX hack, space out slots to better | ||
390 | * deal with misses | ||
391 | */ | ||
392 | if (slot+1 < ATH_BCBUF && | ||
393 | sc->sc_bslot[slot+1] == | ||
394 | ATH_IF_ID_ANY) { | ||
395 | avp->av_bslot = slot+1; | ||
396 | break; | ||
397 | } | ||
398 | avp->av_bslot = slot; | ||
399 | /* NB: keep looking for a double slot */ | ||
400 | } | ||
401 | BUG_ON(sc->sc_bslot[avp->av_bslot] != ATH_IF_ID_ANY); | ||
402 | sc->sc_bslot[avp->av_bslot] = if_id; | ||
403 | sc->sc_nbcnvaps++; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | /* release the previous beacon frame , if it already exists. */ | ||
408 | bf = avp->av_bcbuf; | ||
409 | if (bf->bf_mpdu != NULL) { | ||
410 | skb = (struct sk_buff *)bf->bf_mpdu; | ||
411 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
412 | get_dma_mem_context(bf, bf_dmacontext)); | ||
413 | dev_kfree_skb_any(skb); | ||
414 | bf->bf_mpdu = NULL; | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * NB: the beacon data buffer must be 32-bit aligned; | ||
419 | * we assume the wbuf routines will return us something | ||
420 | * with this alignment (perhaps should assert). | ||
421 | * FIXME: Fill avp->av_boff.bo_tim,avp->av_btxctl.txpower and | ||
422 | * avp->av_btxctl.shortPreamble | ||
423 | */ | ||
424 | skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); | ||
425 | if (skb == NULL) { | ||
426 | DPRINTF(sc, ATH_DBG_BEACON, "%s: cannot get skb\n", | ||
427 | __func__); | ||
428 | return -ENOMEM; | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | * Calculate a TSF adjustment factor required for | ||
433 | * staggered beacons. Note that we assume the format | ||
434 | * of the beacon frame leaves the tstamp field immediately | ||
435 | * following the header. | ||
436 | */ | ||
437 | if (avp->av_bslot > 0) { | ||
438 | u64 tsfadjust; | ||
439 | __le64 val; | ||
440 | int intval; | ||
441 | |||
442 | /* FIXME: Use default value for now: Sujith */ | ||
443 | |||
444 | intval = ATH_DEFAULT_BINTVAL; | ||
445 | |||
446 | /* | ||
447 | * The beacon interval is in TU's; the TSF in usecs. | ||
448 | * We figure out how many TU's to add to align the | ||
449 | * timestamp then convert to TSF units and handle | ||
450 | * byte swapping before writing it in the frame. | ||
451 | * The hardware will then add this each time a beacon | ||
452 | * frame is sent. Note that we align vap's 1..N | ||
453 | * and leave vap 0 untouched. This means vap 0 | ||
454 | * has a timestamp in one beacon interval while the | ||
455 | * others get a timestamp aligned to the next interval. | ||
456 | */ | ||
457 | tsfadjust = (intval * (ATH_BCBUF - avp->av_bslot)) / ATH_BCBUF; | ||
458 | val = cpu_to_le64(tsfadjust << 10); /* TU->TSF */ | ||
459 | |||
460 | DPRINTF(sc, ATH_DBG_BEACON, | ||
461 | "%s: %s beacons, bslot %d intval %u tsfadjust %llu\n", | ||
462 | __func__, "stagger", | ||
463 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | ||
464 | |||
465 | wh = (struct ieee80211_hdr *)skb->data; | ||
466 | memcpy(&wh[1], &val, sizeof(val)); | ||
467 | } | ||
468 | |||
469 | bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE, | ||
470 | get_dma_mem_context(bf, bf_dmacontext)); | ||
471 | bf->bf_mpdu = skb; | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | /* | ||
477 | * Reclaim beacon resources and return buffer to the pool. | ||
478 | * | ||
479 | * Checks the VAP to put the beacon frame buffer back to the ATH object | ||
480 | * queue, and de-allocates any wbuf frames that were sent as CAB traffic. | ||
481 | */ | ||
482 | |||
483 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) | ||
484 | { | ||
485 | if (avp->av_bcbuf != NULL) { | ||
486 | struct ath_buf *bf; | ||
487 | |||
488 | if (avp->av_bslot != -1) { | ||
489 | sc->sc_bslot[avp->av_bslot] = ATH_IF_ID_ANY; | ||
490 | sc->sc_nbcnvaps--; | ||
491 | } | ||
492 | |||
493 | bf = avp->av_bcbuf; | ||
494 | if (bf->bf_mpdu != NULL) { | ||
495 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | ||
496 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
497 | get_dma_mem_context(bf, bf_dmacontext)); | ||
498 | dev_kfree_skb_any(skb); | ||
499 | bf->bf_mpdu = NULL; | ||
500 | } | ||
501 | list_add_tail(&bf->list, &sc->sc_bbuf); | ||
502 | |||
503 | avp->av_bcbuf = NULL; | ||
504 | } | ||
505 | } | ||
506 | |||
507 | /* | ||
508 | * Reclaim beacon resources and return buffer to the pool. | ||
509 | * | ||
510 | * This function will free any wbuf frames that are still attached to the | ||
511 | * beacon buffers in the ATH object. Note that this does not de-allocate | ||
512 | * any wbuf objects that are in the transmit queue and have not yet returned | ||
513 | * to the ATH object. | ||
514 | */ | ||
515 | |||
516 | void ath_beacon_free(struct ath_softc *sc) | ||
517 | { | ||
518 | struct ath_buf *bf; | ||
519 | |||
520 | list_for_each_entry(bf, &sc->sc_bbuf, list) { | ||
521 | if (bf->bf_mpdu != NULL) { | ||
522 | struct sk_buff *skb = (struct sk_buff *) bf->bf_mpdu; | ||
523 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
524 | get_dma_mem_context(bf, bf_dmacontext)); | ||
525 | dev_kfree_skb_any(skb); | ||
526 | bf->bf_mpdu = NULL; | ||
527 | } | ||
528 | } | ||
529 | } | ||
530 | |||
531 | /* | ||
532 | * Tasklet for Sending Beacons | ||
533 | * | ||
534 | * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame | ||
535 | * contents are done as needed and the slot time is also adjusted based on | ||
536 | * current state. | ||
537 | * | ||
538 | * This tasklet is not scheduled, it's called in ISR context. | ||
539 | */ | ||
540 | |||
541 | void ath9k_beacon_tasklet(unsigned long data) | ||
542 | { | ||
543 | #define TSF_TO_TU(_h,_l) \ | ||
544 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
545 | |||
546 | struct ath_softc *sc = (struct ath_softc *)data; | ||
547 | struct ath_hal *ah = sc->sc_ah; | ||
548 | struct ath_buf *bf = NULL; | ||
549 | int slot, if_id; | ||
550 | u32 bfaddr; | ||
551 | u32 rx_clear = 0, rx_frame = 0, tx_frame = 0; | ||
552 | u32 show_cycles = 0; | ||
553 | u32 bc = 0; /* beacon count */ | ||
554 | u64 tsf; | ||
555 | u32 tsftu; | ||
556 | u16 intval; | ||
557 | |||
558 | if (sc->sc_noreset) { | ||
559 | show_cycles = ath9k_hw_GetMibCycleCountsPct(ah, | ||
560 | &rx_clear, | ||
561 | &rx_frame, | ||
562 | &tx_frame); | ||
563 | } | ||
564 | |||
565 | /* | ||
566 | * Check if the previous beacon has gone out. If | ||
567 | * not don't try to post another, skip this period | ||
568 | * and wait for the next. Missed beacons indicate | ||
569 | * a problem and should not occur. If we miss too | ||
570 | * many consecutive beacons reset the device. | ||
571 | */ | ||
572 | if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) { | ||
573 | sc->sc_bmisscount++; | ||
574 | /* XXX: doth needs the chanchange IE countdown decremented. | ||
575 | * We should consider adding a mac80211 call to indicate | ||
576 | * a beacon miss so appropriate action could be taken | ||
577 | * (in that layer). | ||
578 | */ | ||
579 | if (sc->sc_bmisscount < BSTUCK_THRESH) { | ||
580 | if (sc->sc_noreset) { | ||
581 | DPRINTF(sc, ATH_DBG_BEACON, | ||
582 | "%s: missed %u consecutive beacons\n", | ||
583 | __func__, sc->sc_bmisscount); | ||
584 | if (show_cycles) { | ||
585 | /* | ||
586 | * Display cycle counter stats | ||
587 | * from HW to aide in debug of | ||
588 | * stickiness. | ||
589 | */ | ||
590 | DPRINTF(sc, | ||
591 | ATH_DBG_BEACON, | ||
592 | "%s: busy times: rx_clear=%d, " | ||
593 | "rx_frame=%d, tx_frame=%d\n", | ||
594 | __func__, rx_clear, rx_frame, | ||
595 | tx_frame); | ||
596 | } else { | ||
597 | DPRINTF(sc, | ||
598 | ATH_DBG_BEACON, | ||
599 | "%s: unable to obtain " | ||
600 | "busy times\n", __func__); | ||
601 | } | ||
602 | } else { | ||
603 | DPRINTF(sc, ATH_DBG_BEACON, | ||
604 | "%s: missed %u consecutive beacons\n", | ||
605 | __func__, sc->sc_bmisscount); | ||
606 | } | ||
607 | } else if (sc->sc_bmisscount >= BSTUCK_THRESH) { | ||
608 | if (sc->sc_noreset) { | ||
609 | if (sc->sc_bmisscount == BSTUCK_THRESH) { | ||
610 | DPRINTF(sc, | ||
611 | ATH_DBG_BEACON, | ||
612 | "%s: beacon is officially " | ||
613 | "stuck\n", __func__); | ||
614 | ath9k_hw_dmaRegDump(ah); | ||
615 | } | ||
616 | } else { | ||
617 | DPRINTF(sc, ATH_DBG_BEACON, | ||
618 | "%s: beacon is officially stuck\n", | ||
619 | __func__); | ||
620 | ath_bstuck_process(sc); | ||
621 | } | ||
622 | } | ||
623 | |||
624 | return; | ||
625 | } | ||
626 | if (sc->sc_bmisscount != 0) { | ||
627 | if (sc->sc_noreset) { | ||
628 | DPRINTF(sc, | ||
629 | ATH_DBG_BEACON, | ||
630 | "%s: resume beacon xmit after %u misses\n", | ||
631 | __func__, sc->sc_bmisscount); | ||
632 | } else { | ||
633 | DPRINTF(sc, ATH_DBG_BEACON, | ||
634 | "%s: resume beacon xmit after %u misses\n", | ||
635 | __func__, sc->sc_bmisscount); | ||
636 | } | ||
637 | sc->sc_bmisscount = 0; | ||
638 | } | ||
639 | |||
640 | /* | ||
641 | * Generate beacon frames. we are sending frames | ||
642 | * staggered so calculate the slot for this frame based | ||
643 | * on the tsf to safeguard against missing an swba. | ||
644 | */ | ||
645 | |||
646 | /* FIXME: Use default value for now - Sujith */ | ||
647 | intval = ATH_DEFAULT_BINTVAL; | ||
648 | |||
649 | tsf = ath9k_hw_gettsf64(ah); | ||
650 | tsftu = TSF_TO_TU(tsf>>32, tsf); | ||
651 | slot = ((tsftu % intval) * ATH_BCBUF) / intval; | ||
652 | if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF]; | ||
653 | DPRINTF(sc, ATH_DBG_BEACON, | ||
654 | "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", | ||
655 | __func__, slot, (unsigned long long) tsf, tsftu, | ||
656 | intval, if_id); | ||
657 | bfaddr = 0; | ||
658 | if (if_id != ATH_IF_ID_ANY) { | ||
659 | bf = ath_beacon_generate(sc, if_id); | ||
660 | if (bf != NULL) { | ||
661 | bfaddr = bf->bf_daddr; | ||
662 | bc = 1; | ||
663 | } | ||
664 | } | ||
665 | /* | ||
666 | * Handle slot time change when a non-ERP station joins/leaves | ||
667 | * an 11g network. The 802.11 layer notifies us via callback, | ||
668 | * we mark updateslot, then wait one beacon before effecting | ||
669 | * the change. This gives associated stations at least one | ||
670 | * beacon interval to note the state change. | ||
671 | * | ||
672 | * NB: The slot time change state machine is clocked according | ||
673 | * to whether we are bursting or staggering beacons. We | ||
674 | * recognize the request to update and record the current | ||
675 | * slot then don't transition until that slot is reached | ||
676 | * again. If we miss a beacon for that slot then we'll be | ||
677 | * slow to transition but we'll be sure at least one beacon | ||
678 | * interval has passed. When bursting slot is always left | ||
679 | * set to ATH_BCBUF so this check is a noop. | ||
680 | */ | ||
681 | /* XXX locking */ | ||
682 | if (sc->sc_updateslot == UPDATE) { | ||
683 | sc->sc_updateslot = COMMIT; /* commit next beacon */ | ||
684 | sc->sc_slotupdate = slot; | ||
685 | } else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot) | ||
686 | ath_setslottime(sc); /* commit change to hardware */ | ||
687 | |||
688 | if (bfaddr != 0) { | ||
689 | /* | ||
690 | * Stop any current dma and put the new frame(s) on the queue. | ||
691 | * This should never fail since we check above that no frames | ||
692 | * are still pending on the queue. | ||
693 | */ | ||
694 | if (!ath9k_hw_stoptxdma(ah, sc->sc_bhalq)) { | ||
695 | DPRINTF(sc, ATH_DBG_FATAL, | ||
696 | "%s: beacon queue %u did not stop?\n", | ||
697 | __func__, sc->sc_bhalq); | ||
698 | /* NB: the HAL still stops DMA, so proceed */ | ||
699 | } | ||
700 | |||
701 | /* NB: cabq traffic should already be queued and primed */ | ||
702 | ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bfaddr); | ||
703 | ath9k_hw_txstart(ah, sc->sc_bhalq); | ||
704 | |||
705 | sc->ast_be_xmit += bc; /* XXX per-vap? */ | ||
706 | } | ||
707 | #undef TSF_TO_TU | ||
708 | } | ||
709 | |||
710 | /* | ||
711 | * Tasklet for Beacon Stuck processing | ||
712 | * | ||
713 | * Processing for Beacon Stuck. | ||
714 | * Basically calls the ath_internal_reset function to reset the chip. | ||
715 | */ | ||
716 | |||
717 | void ath_bstuck_process(struct ath_softc *sc) | ||
718 | { | ||
719 | DPRINTF(sc, ATH_DBG_BEACON, | ||
720 | "%s: stuck beacon; resetting (bmiss count %u)\n", | ||
721 | __func__, sc->sc_bmisscount); | ||
722 | ath_internal_reset(sc); | ||
723 | } | ||
724 | |||
725 | /* | ||
726 | * Configure the beacon and sleep timers. | ||
727 | * | ||
728 | * When operating as an AP this resets the TSF and sets | ||
729 | * up the hardware to notify us when we need to issue beacons. | ||
730 | * | ||
731 | * When operating in station mode this sets up the beacon | ||
732 | * timers according to the timestamp of the last received | ||
733 | * beacon and the current TSF, configures PCF and DTIM | ||
734 | * handling, programs the sleep registers so the hardware | ||
735 | * will wakeup in time to receive beacons, and configures | ||
736 | * the beacon miss handling so we'll receive a BMISS | ||
737 | * interrupt when we stop seeing beacons from the AP | ||
738 | * we've associated with. | ||
739 | */ | ||
740 | |||
741 | void ath_beacon_config(struct ath_softc *sc, int if_id) | ||
742 | { | ||
743 | #define TSF_TO_TU(_h,_l) \ | ||
744 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
745 | struct ath_hal *ah = sc->sc_ah; | ||
746 | u32 nexttbtt, intval; | ||
747 | struct ath_beacon_config conf; | ||
748 | enum ath9k_opmode av_opmode; | ||
749 | |||
750 | if (if_id != ATH_IF_ID_ANY) | ||
751 | av_opmode = sc->sc_vaps[if_id]->av_opmode; | ||
752 | else | ||
753 | av_opmode = sc->sc_opmode; | ||
754 | |||
755 | memzero(&conf, sizeof(struct ath_beacon_config)); | ||
756 | |||
757 | /* FIXME: Use default values for now - Sujith */ | ||
758 | /* Query beacon configuration first */ | ||
759 | /* | ||
760 | * Protocol stack doesn't support dynamic beacon configuration, | ||
761 | * use default configurations. | ||
762 | */ | ||
763 | conf.beacon_interval = ATH_DEFAULT_BINTVAL; | ||
764 | conf.listen_interval = 1; | ||
765 | conf.dtim_period = conf.beacon_interval; | ||
766 | conf.dtim_count = 1; | ||
767 | conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; | ||
768 | |||
769 | /* extract tstamp from last beacon and convert to TU */ | ||
770 | nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4), | ||
771 | get_unaligned_le32(conf.u.last_tstamp)); | ||
772 | /* XXX conditionalize multi-bss support? */ | ||
773 | if (sc->sc_opmode == ATH9K_M_HOSTAP) { | ||
774 | /* | ||
775 | * For multi-bss ap support beacons are either staggered | ||
776 | * evenly over N slots or burst together. For the former | ||
777 | * arrange for the SWBA to be delivered for each slot. | ||
778 | * Slots that are not occupied will generate nothing. | ||
779 | */ | ||
780 | /* NB: the beacon interval is kept internally in TU's */ | ||
781 | intval = conf.beacon_interval & ATH9K_BEACON_PERIOD; | ||
782 | intval /= ATH_BCBUF; /* for staggered beacons */ | ||
783 | } else { | ||
784 | intval = conf.beacon_interval & ATH9K_BEACON_PERIOD; | ||
785 | } | ||
786 | |||
787 | if (nexttbtt == 0) /* e.g. for ap mode */ | ||
788 | nexttbtt = intval; | ||
789 | else if (intval) /* NB: can be 0 for monitor mode */ | ||
790 | nexttbtt = roundup(nexttbtt, intval); | ||
791 | DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", | ||
792 | __func__, nexttbtt, intval, conf.beacon_interval); | ||
793 | /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */ | ||
794 | if (sc->sc_opmode == ATH9K_M_STA) { | ||
795 | struct ath9k_beacon_state bs; | ||
796 | u64 tsf; | ||
797 | u32 tsftu; | ||
798 | int dtimperiod, dtimcount, sleepduration; | ||
799 | int cfpperiod, cfpcount; | ||
800 | |||
801 | /* | ||
802 | * Setup dtim and cfp parameters according to | ||
803 | * last beacon we received (which may be none). | ||
804 | */ | ||
805 | dtimperiod = conf.dtim_period; | ||
806 | if (dtimperiod <= 0) /* NB: 0 if not known */ | ||
807 | dtimperiod = 1; | ||
808 | dtimcount = conf.dtim_count; | ||
809 | if (dtimcount >= dtimperiod) /* NB: sanity check */ | ||
810 | dtimcount = 0; /* XXX? */ | ||
811 | cfpperiod = 1; /* NB: no PCF support yet */ | ||
812 | cfpcount = 0; | ||
813 | |||
814 | sleepduration = conf.listen_interval * intval; | ||
815 | if (sleepduration <= 0) | ||
816 | sleepduration = intval; | ||
817 | |||
818 | #define FUDGE 2 | ||
819 | /* | ||
820 | * Pull nexttbtt forward to reflect the current | ||
821 | * TSF and calculate dtim+cfp state for the result. | ||
822 | */ | ||
823 | tsf = ath9k_hw_gettsf64(ah); | ||
824 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; | ||
825 | do { | ||
826 | nexttbtt += intval; | ||
827 | if (--dtimcount < 0) { | ||
828 | dtimcount = dtimperiod - 1; | ||
829 | if (--cfpcount < 0) | ||
830 | cfpcount = cfpperiod - 1; | ||
831 | } | ||
832 | } while (nexttbtt < tsftu); | ||
833 | #undef FUDGE | ||
834 | memzero(&bs, sizeof(bs)); | ||
835 | bs.bs_intval = intval; | ||
836 | bs.bs_nexttbtt = nexttbtt; | ||
837 | bs.bs_dtimperiod = dtimperiod*intval; | ||
838 | bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; | ||
839 | bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; | ||
840 | bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; | ||
841 | bs.bs_cfpmaxduration = 0; | ||
842 | /* | ||
843 | * Calculate the number of consecutive beacons to miss | ||
844 | * before taking a BMISS interrupt. The configuration | ||
845 | * is specified in TU so we only need calculate based | ||
846 | * on the beacon interval. Note that we clamp the | ||
847 | * result to at most 15 beacons. | ||
848 | */ | ||
849 | if (sleepduration > intval) { | ||
850 | bs.bs_bmissthreshold = | ||
851 | conf.listen_interval * | ||
852 | ATH_DEFAULT_BMISS_LIMIT / 2; | ||
853 | } else { | ||
854 | bs.bs_bmissthreshold = | ||
855 | DIV_ROUND_UP(conf.bmiss_timeout, intval); | ||
856 | if (bs.bs_bmissthreshold > 15) | ||
857 | bs.bs_bmissthreshold = 15; | ||
858 | else if (bs.bs_bmissthreshold <= 0) | ||
859 | bs.bs_bmissthreshold = 1; | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * Calculate sleep duration. The configuration is | ||
864 | * given in ms. We insure a multiple of the beacon | ||
865 | * period is used. Also, if the sleep duration is | ||
866 | * greater than the DTIM period then it makes senses | ||
867 | * to make it a multiple of that. | ||
868 | * | ||
869 | * XXX fixed at 100ms | ||
870 | */ | ||
871 | |||
872 | bs.bs_sleepduration = | ||
873 | roundup(IEEE80211_MS_TO_TU(100), sleepduration); | ||
874 | if (bs.bs_sleepduration > bs.bs_dtimperiod) | ||
875 | bs.bs_sleepduration = bs.bs_dtimperiod; | ||
876 | |||
877 | DPRINTF(sc, ATH_DBG_BEACON, | ||
878 | "%s: tsf %llu " | ||
879 | "tsf:tu %u " | ||
880 | "intval %u " | ||
881 | "nexttbtt %u " | ||
882 | "dtim %u " | ||
883 | "nextdtim %u " | ||
884 | "bmiss %u " | ||
885 | "sleep %u " | ||
886 | "cfp:period %u " | ||
887 | "maxdur %u " | ||
888 | "next %u " | ||
889 | "timoffset %u\n" | ||
890 | , __func__ | ||
891 | , (unsigned long long)tsf, tsftu | ||
892 | , bs.bs_intval | ||
893 | , bs.bs_nexttbtt | ||
894 | , bs.bs_dtimperiod | ||
895 | , bs.bs_nextdtim | ||
896 | , bs.bs_bmissthreshold | ||
897 | , bs.bs_sleepduration | ||
898 | , bs.bs_cfpperiod | ||
899 | , bs.bs_cfpmaxduration | ||
900 | , bs.bs_cfpnext | ||
901 | , bs.bs_timoffset | ||
902 | ); | ||
903 | |||
904 | ath9k_hw_set_interrupts(ah, 0); | ||
905 | ath9k_hw_set_sta_beacon_timers(ah, &bs); | ||
906 | sc->sc_imask |= ATH9K_INT_BMISS; | ||
907 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
908 | } else { | ||
909 | u64 tsf; | ||
910 | u32 tsftu; | ||
911 | ath9k_hw_set_interrupts(ah, 0); | ||
912 | if (nexttbtt == intval) | ||
913 | intval |= ATH9K_BEACON_RESET_TSF; | ||
914 | if (sc->sc_opmode == ATH9K_M_IBSS) { | ||
915 | /* | ||
916 | * Pull nexttbtt forward to reflect the current | ||
917 | * TSF . | ||
918 | */ | ||
919 | #define FUDGE 2 | ||
920 | if (!(intval & ATH9K_BEACON_RESET_TSF)) { | ||
921 | tsf = ath9k_hw_gettsf64(ah); | ||
922 | tsftu = TSF_TO_TU((u32)(tsf>>32), | ||
923 | (u32)tsf) + FUDGE; | ||
924 | do { | ||
925 | nexttbtt += intval; | ||
926 | } while (nexttbtt < tsftu); | ||
927 | } | ||
928 | #undef FUDGE | ||
929 | DPRINTF(sc, ATH_DBG_BEACON, | ||
930 | "%s: IBSS nexttbtt %u intval %u (%u)\n", | ||
931 | __func__, nexttbtt, | ||
932 | intval & ~ATH9K_BEACON_RESET_TSF, | ||
933 | conf.beacon_interval); | ||
934 | |||
935 | /* | ||
936 | * In IBSS mode enable the beacon timers but only | ||
937 | * enable SWBA interrupts if we need to manually | ||
938 | * prepare beacon frames. Otherwise we use a | ||
939 | * self-linked tx descriptor and let the hardware | ||
940 | * deal with things. | ||
941 | */ | ||
942 | intval |= ATH9K_BEACON_ENA; | ||
943 | if (!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) | ||
944 | sc->sc_imask |= ATH9K_INT_SWBA; | ||
945 | ath_beaconq_config(sc); | ||
946 | } else if (sc->sc_opmode == ATH9K_M_HOSTAP) { | ||
947 | /* | ||
948 | * In AP mode we enable the beacon timers and | ||
949 | * SWBA interrupts to prepare beacon frames. | ||
950 | */ | ||
951 | intval |= ATH9K_BEACON_ENA; | ||
952 | sc->sc_imask |= ATH9K_INT_SWBA; /* beacon prepare */ | ||
953 | ath_beaconq_config(sc); | ||
954 | } | ||
955 | ath9k_hw_beaconinit(ah, nexttbtt, intval); | ||
956 | sc->sc_bmisscount = 0; | ||
957 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
958 | /* | ||
959 | * When using a self-linked beacon descriptor in | ||
960 | * ibss mode load it once here. | ||
961 | */ | ||
962 | if (sc->sc_opmode == ATH9K_M_IBSS && | ||
963 | (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) | ||
964 | ath_beacon_start_adhoc(sc, 0); | ||
965 | } | ||
966 | #undef TSF_TO_TU | ||
967 | } | ||
968 | |||
969 | /* Function to collect beacon rssi data and resync beacon if necessary */ | ||
970 | |||
971 | void ath_beacon_sync(struct ath_softc *sc, int if_id) | ||
972 | { | ||
973 | /* | ||
974 | * Resync beacon timers using the tsf of the | ||
975 | * beacon frame we just received. | ||
976 | */ | ||
977 | ath_beacon_config(sc, if_id); | ||
978 | sc->sc_beacons = 1; | ||
979 | } | ||
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c new file mode 100644 index 000000000000..f6c45288d0e7 --- /dev/null +++ b/drivers/net/wireless/ath9k/core.c | |||
@@ -0,0 +1,1923 @@ | |||
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 = ath9k_hw_getratetable(sc->sc_ah, 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 == ATH9K_MODE_11G ? 1 : 0); | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * Set up rate table (legacy rates) | ||
104 | */ | ||
105 | static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) | ||
106 | { | ||
107 | struct ath_hal *ah = sc->sc_ah; | ||
108 | const struct ath9k_rate_table *rt = NULL; | ||
109 | struct ieee80211_supported_band *sband; | ||
110 | struct ieee80211_rate *rate; | ||
111 | int i, maxrates; | ||
112 | |||
113 | switch (band) { | ||
114 | case IEEE80211_BAND_2GHZ: | ||
115 | rt = ath9k_hw_getratetable(ah, ATH9K_MODE_11G); | ||
116 | break; | ||
117 | case IEEE80211_BAND_5GHZ: | ||
118 | rt = ath9k_hw_getratetable(ah, ATH9K_MODE_11A); | ||
119 | break; | ||
120 | default: | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | if (rt == NULL) | ||
125 | return; | ||
126 | |||
127 | sband = &sc->sbands[band]; | ||
128 | rate = sc->rates[band]; | ||
129 | |||
130 | if (rt->rateCount > ATH_RATE_MAX) | ||
131 | maxrates = ATH_RATE_MAX; | ||
132 | else | ||
133 | maxrates = rt->rateCount; | ||
134 | |||
135 | for (i = 0; i < maxrates; i++) { | ||
136 | rate[i].bitrate = rt->info[i].rateKbps / 100; | ||
137 | rate[i].hw_value = rt->info[i].rateCode; | ||
138 | sband->n_bitrates++; | ||
139 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
140 | "%s: Rate: %2dMbps, ratecode: %2d\n", | ||
141 | __func__, | ||
142 | rate[i].bitrate / 10, | ||
143 | rate[i].hw_value); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * Set up channel list | ||
149 | */ | ||
150 | static int ath_setup_channels(struct ath_softc *sc) | ||
151 | { | ||
152 | struct ath_hal *ah = sc->sc_ah; | ||
153 | int nchan, i, a = 0, b = 0; | ||
154 | u8 regclassids[ATH_REGCLASSIDS_MAX]; | ||
155 | u32 nregclass = 0; | ||
156 | struct ieee80211_supported_band *band_2ghz; | ||
157 | struct ieee80211_supported_band *band_5ghz; | ||
158 | struct ieee80211_channel *chan_2ghz; | ||
159 | struct ieee80211_channel *chan_5ghz; | ||
160 | struct ath9k_channel *c; | ||
161 | |||
162 | /* Fill in ah->ah_channels */ | ||
163 | if (!ath9k_regd_init_channels(ah, | ||
164 | ATH_CHAN_MAX, | ||
165 | (u32 *)&nchan, | ||
166 | regclassids, | ||
167 | ATH_REGCLASSIDS_MAX, | ||
168 | &nregclass, | ||
169 | CTRY_DEFAULT, | ||
170 | false, | ||
171 | 1)) { | ||
172 | u32 rd = ah->ah_currentRD; | ||
173 | |||
174 | DPRINTF(sc, ATH_DBG_FATAL, | ||
175 | "%s: unable to collect channel list; " | ||
176 | "regdomain likely %u country code %u\n", | ||
177 | __func__, rd, CTRY_DEFAULT); | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
182 | band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
183 | chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ]; | ||
184 | chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ]; | ||
185 | |||
186 | for (i = 0; i < nchan; i++) { | ||
187 | c = &ah->ah_channels[i]; | ||
188 | if (IS_CHAN_2GHZ(c)) { | ||
189 | chan_2ghz[a].band = IEEE80211_BAND_2GHZ; | ||
190 | chan_2ghz[a].center_freq = c->channel; | ||
191 | chan_2ghz[a].max_power = c->maxTxPower; | ||
192 | |||
193 | if (c->privFlags & CHANNEL_DISALLOW_ADHOC) | ||
194 | chan_2ghz[a].flags |= | ||
195 | IEEE80211_CHAN_NO_IBSS; | ||
196 | if (c->channelFlags & CHANNEL_PASSIVE) | ||
197 | chan_2ghz[a].flags |= | ||
198 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
199 | |||
200 | band_2ghz->n_channels = ++a; | ||
201 | |||
202 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
203 | "%s: 2MHz channel: %d, " | ||
204 | "channelFlags: 0x%x\n", | ||
205 | __func__, | ||
206 | c->channel, | ||
207 | c->channelFlags); | ||
208 | } else if (IS_CHAN_5GHZ(c)) { | ||
209 | chan_5ghz[b].band = IEEE80211_BAND_5GHZ; | ||
210 | chan_5ghz[b].center_freq = c->channel; | ||
211 | chan_5ghz[b].max_power = c->maxTxPower; | ||
212 | |||
213 | if (c->privFlags & CHANNEL_DISALLOW_ADHOC) | ||
214 | chan_5ghz[b].flags |= | ||
215 | IEEE80211_CHAN_NO_IBSS; | ||
216 | if (c->channelFlags & CHANNEL_PASSIVE) | ||
217 | chan_5ghz[b].flags |= | ||
218 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
219 | |||
220 | band_5ghz->n_channels = ++b; | ||
221 | |||
222 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
223 | "%s: 5MHz channel: %d, " | ||
224 | "channelFlags: 0x%x\n", | ||
225 | __func__, | ||
226 | c->channel, | ||
227 | c->channelFlags); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * Determine mode from channel flags | ||
236 | * | ||
237 | * This routine will provide the enumerated WIRELESSS_MODE value based | ||
238 | * on the settings of the channel flags. If ho valid set of flags | ||
239 | * exist, the lowest mode (11b) is selected. | ||
240 | */ | ||
241 | |||
242 | static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan) | ||
243 | { | ||
244 | if (chan->chanmode == CHANNEL_A) | ||
245 | return ATH9K_MODE_11A; | ||
246 | else if (chan->chanmode == CHANNEL_G) | ||
247 | return ATH9K_MODE_11G; | ||
248 | else if (chan->chanmode == CHANNEL_B) | ||
249 | return ATH9K_MODE_11B; | ||
250 | else if (chan->chanmode == CHANNEL_A_HT20) | ||
251 | return ATH9K_MODE_11NA_HT20; | ||
252 | else if (chan->chanmode == CHANNEL_G_HT20) | ||
253 | return ATH9K_MODE_11NG_HT20; | ||
254 | else if (chan->chanmode == CHANNEL_A_HT40PLUS) | ||
255 | return ATH9K_MODE_11NA_HT40PLUS; | ||
256 | else if (chan->chanmode == CHANNEL_A_HT40MINUS) | ||
257 | return ATH9K_MODE_11NA_HT40MINUS; | ||
258 | else if (chan->chanmode == CHANNEL_G_HT40PLUS) | ||
259 | return ATH9K_MODE_11NG_HT40PLUS; | ||
260 | else if (chan->chanmode == CHANNEL_G_HT40MINUS) | ||
261 | return ATH9K_MODE_11NG_HT40MINUS; | ||
262 | |||
263 | /* NB: should not get here */ | ||
264 | return ATH9K_MODE_11B; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * Stop the device, grabbing the top-level lock to protect | ||
269 | * against concurrent entry through ath_init (which can happen | ||
270 | * if another thread does a system call and the thread doing the | ||
271 | * stop is preempted). | ||
272 | */ | ||
273 | |||
274 | static int ath_stop(struct ath_softc *sc) | ||
275 | { | ||
276 | struct ath_hal *ah = sc->sc_ah; | ||
277 | |||
278 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %u\n", | ||
279 | __func__, sc->sc_invalid); | ||
280 | |||
281 | /* | ||
282 | * Shutdown the hardware and driver: | ||
283 | * stop output from above | ||
284 | * reset 802.11 state machine | ||
285 | * (sends station deassoc/deauth frames) | ||
286 | * turn off timers | ||
287 | * disable interrupts | ||
288 | * clear transmit machinery | ||
289 | * clear receive machinery | ||
290 | * turn off the radio | ||
291 | * reclaim beacon resources | ||
292 | * | ||
293 | * Note that some of this work is not possible if the | ||
294 | * hardware is gone (invalid). | ||
295 | */ | ||
296 | |||
297 | if (!sc->sc_invalid) | ||
298 | ath9k_hw_set_interrupts(ah, 0); | ||
299 | ath_draintxq(sc, false); | ||
300 | if (!sc->sc_invalid) { | ||
301 | ath_stoprecv(sc); | ||
302 | ath9k_hw_phy_disable(ah); | ||
303 | } else | ||
304 | sc->sc_rxlink = NULL; | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * Start Scan | ||
311 | * | ||
312 | * This function is called when starting a channel scan. It will perform | ||
313 | * power save wakeup processing, set the filter for the scan, and get the | ||
314 | * chip ready to send broadcast packets out during the scan. | ||
315 | */ | ||
316 | |||
317 | void ath_scan_start(struct ath_softc *sc) | ||
318 | { | ||
319 | struct ath_hal *ah = sc->sc_ah; | ||
320 | u32 rfilt; | ||
321 | u32 now = (u32) jiffies_to_msecs(get_timestamp()); | ||
322 | |||
323 | sc->sc_scanning = 1; | ||
324 | rfilt = ath_calcrxfilter(sc); | ||
325 | ath9k_hw_setrxfilter(ah, rfilt); | ||
326 | ath9k_hw_write_associd(ah, ath_bcast_mac, 0); | ||
327 | |||
328 | /* Restore previous power management state. */ | ||
329 | |||
330 | DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0\n", | ||
331 | now / 1000, now % 1000, __func__, rfilt); | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * Scan End | ||
336 | * | ||
337 | * This routine is called by the upper layer when the scan is completed. This | ||
338 | * will set the filters back to normal operating mode, set the BSSID to the | ||
339 | * correct value, and restore the power save state. | ||
340 | */ | ||
341 | |||
342 | void ath_scan_end(struct ath_softc *sc) | ||
343 | { | ||
344 | struct ath_hal *ah = sc->sc_ah; | ||
345 | u32 rfilt; | ||
346 | u32 now = (u32) jiffies_to_msecs(get_timestamp()); | ||
347 | |||
348 | sc->sc_scanning = 0; | ||
349 | /* Request for a full reset due to rx packet filter changes */ | ||
350 | sc->sc_full_reset = 1; | ||
351 | rfilt = ath_calcrxfilter(sc); | ||
352 | ath9k_hw_setrxfilter(ah, rfilt); | ||
353 | ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid); | ||
354 | |||
355 | DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0x%x\n", | ||
356 | now / 1000, now % 1000, __func__, rfilt, sc->sc_curaid); | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * Set the current channel | ||
361 | * | ||
362 | * Set/change channels. If the channel is really being changed, it's done | ||
363 | * by reseting the chip. To accomplish this we must first cleanup any pending | ||
364 | * DMA, then restart stuff after a la ath_init. | ||
365 | */ | ||
366 | int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) | ||
367 | { | ||
368 | struct ath_hal *ah = sc->sc_ah; | ||
369 | bool fastcc = true, stopped; | ||
370 | enum ath9k_ht_macmode ht_macmode; | ||
371 | |||
372 | if (sc->sc_invalid) /* if the device is invalid or removed */ | ||
373 | return -EIO; | ||
374 | |||
375 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
376 | "%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n", | ||
377 | __func__, | ||
378 | ath9k_hw_mhz2ieee(ah, sc->sc_curchan.channel, | ||
379 | sc->sc_curchan.channelFlags), | ||
380 | sc->sc_curchan.channel, | ||
381 | ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags), | ||
382 | hchan->channel, hchan->channelFlags); | ||
383 | |||
384 | ht_macmode = ath_cwm_macmode(sc); | ||
385 | |||
386 | if (hchan->channel != sc->sc_curchan.channel || | ||
387 | hchan->channelFlags != sc->sc_curchan.channelFlags || | ||
388 | sc->sc_update_chainmask || sc->sc_full_reset) { | ||
389 | int status; | ||
390 | /* | ||
391 | * This is only performed if the channel settings have | ||
392 | * actually changed. | ||
393 | * | ||
394 | * To switch channels clear any pending DMA operations; | ||
395 | * wait long enough for the RX fifo to drain, reset the | ||
396 | * hardware at the new frequency, and then re-enable | ||
397 | * the relevant bits of the h/w. | ||
398 | */ | ||
399 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ | ||
400 | ath_draintxq(sc, false); /* clear pending tx frames */ | ||
401 | stopped = ath_stoprecv(sc); /* turn off frame recv */ | ||
402 | |||
403 | /* XXX: do not flush receive queue here. We don't want | ||
404 | * to flush data frames already in queue because of | ||
405 | * changing channel. */ | ||
406 | |||
407 | if (!stopped || sc->sc_full_reset) | ||
408 | fastcc = false; | ||
409 | |||
410 | spin_lock_bh(&sc->sc_resetlock); | ||
411 | if (!ath9k_hw_reset(ah, sc->sc_opmode, hchan, | ||
412 | ht_macmode, sc->sc_tx_chainmask, | ||
413 | sc->sc_rx_chainmask, | ||
414 | sc->sc_ht_extprotspacing, | ||
415 | fastcc, &status)) { | ||
416 | DPRINTF(sc, ATH_DBG_FATAL, | ||
417 | "%s: unable to reset channel %u (%uMhz) " | ||
418 | "flags 0x%x hal status %u\n", __func__, | ||
419 | ath9k_hw_mhz2ieee(ah, hchan->channel, | ||
420 | hchan->channelFlags), | ||
421 | hchan->channel, hchan->channelFlags, status); | ||
422 | spin_unlock_bh(&sc->sc_resetlock); | ||
423 | return -EIO; | ||
424 | } | ||
425 | spin_unlock_bh(&sc->sc_resetlock); | ||
426 | |||
427 | sc->sc_curchan = *hchan; | ||
428 | sc->sc_update_chainmask = 0; | ||
429 | sc->sc_full_reset = 0; | ||
430 | |||
431 | /* Re-enable rx framework */ | ||
432 | if (ath_startrecv(sc) != 0) { | ||
433 | DPRINTF(sc, ATH_DBG_FATAL, | ||
434 | "%s: unable to restart recv logic\n", __func__); | ||
435 | return -EIO; | ||
436 | } | ||
437 | /* | ||
438 | * Change channels and update the h/w rate map | ||
439 | * if we're switching; e.g. 11a to 11b/g. | ||
440 | */ | ||
441 | ath_setcurmode(sc, ath_chan2mode(hchan)); | ||
442 | |||
443 | ath_update_txpow(sc); /* update tx power state */ | ||
444 | /* | ||
445 | * Re-enable interrupts. | ||
446 | */ | ||
447 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
448 | } | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | /**********************/ | ||
453 | /* Chainmask Handling */ | ||
454 | /**********************/ | ||
455 | |||
456 | static void ath_chainmask_sel_timertimeout(unsigned long data) | ||
457 | { | ||
458 | struct ath_chainmask_sel *cm = (struct ath_chainmask_sel *)data; | ||
459 | cm->switch_allowed = 1; | ||
460 | } | ||
461 | |||
462 | /* Start chainmask select timer */ | ||
463 | static void ath_chainmask_sel_timerstart(struct ath_chainmask_sel *cm) | ||
464 | { | ||
465 | cm->switch_allowed = 0; | ||
466 | mod_timer(&cm->timer, ath_chainmask_sel_period); | ||
467 | } | ||
468 | |||
469 | /* Stop chainmask select timer */ | ||
470 | static void ath_chainmask_sel_timerstop(struct ath_chainmask_sel *cm) | ||
471 | { | ||
472 | cm->switch_allowed = 0; | ||
473 | del_timer_sync(&cm->timer); | ||
474 | } | ||
475 | |||
476 | static void ath_chainmask_sel_init(struct ath_softc *sc, struct ath_node *an) | ||
477 | { | ||
478 | struct ath_chainmask_sel *cm = &an->an_chainmask_sel; | ||
479 | |||
480 | memzero(cm, sizeof(struct ath_chainmask_sel)); | ||
481 | |||
482 | cm->cur_tx_mask = sc->sc_tx_chainmask; | ||
483 | cm->cur_rx_mask = sc->sc_rx_chainmask; | ||
484 | cm->tx_avgrssi = ATH_RSSI_DUMMY_MARKER; | ||
485 | setup_timer(&cm->timer, | ||
486 | ath_chainmask_sel_timertimeout, (unsigned long) cm); | ||
487 | } | ||
488 | |||
489 | int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an) | ||
490 | { | ||
491 | struct ath_chainmask_sel *cm = &an->an_chainmask_sel; | ||
492 | |||
493 | /* | ||
494 | * Disable auto-swtiching in one of the following if conditions. | ||
495 | * sc_chainmask_auto_sel is used for internal global auto-switching | ||
496 | * enabled/disabled setting | ||
497 | */ | ||
498 | if (sc->sc_ah->ah_caps.tx_chainmask != ATH_CHAINMASK_SEL_3X3) { | ||
499 | cm->cur_tx_mask = sc->sc_tx_chainmask; | ||
500 | return cm->cur_tx_mask; | ||
501 | } | ||
502 | |||
503 | if (cm->tx_avgrssi == ATH_RSSI_DUMMY_MARKER) | ||
504 | return cm->cur_tx_mask; | ||
505 | |||
506 | if (cm->switch_allowed) { | ||
507 | /* Switch down from tx 3 to tx 2. */ | ||
508 | if (cm->cur_tx_mask == ATH_CHAINMASK_SEL_3X3 && | ||
509 | ATH_RSSI_OUT(cm->tx_avgrssi) >= | ||
510 | ath_chainmask_sel_down_rssi_thres) { | ||
511 | cm->cur_tx_mask = sc->sc_tx_chainmask; | ||
512 | |||
513 | /* Don't let another switch happen until | ||
514 | * this timer expires */ | ||
515 | ath_chainmask_sel_timerstart(cm); | ||
516 | } | ||
517 | /* Switch up from tx 2 to 3. */ | ||
518 | else if (cm->cur_tx_mask == sc->sc_tx_chainmask && | ||
519 | ATH_RSSI_OUT(cm->tx_avgrssi) <= | ||
520 | ath_chainmask_sel_up_rssi_thres) { | ||
521 | cm->cur_tx_mask = ATH_CHAINMASK_SEL_3X3; | ||
522 | |||
523 | /* Don't let another switch happen | ||
524 | * until this timer expires */ | ||
525 | ath_chainmask_sel_timerstart(cm); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | return cm->cur_tx_mask; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Update tx/rx chainmask. For legacy association, | ||
534 | * hard code chainmask to 1x1, for 11n association, use | ||
535 | * the chainmask configuration. | ||
536 | */ | ||
537 | |||
538 | void ath_update_chainmask(struct ath_softc *sc, int is_ht) | ||
539 | { | ||
540 | sc->sc_update_chainmask = 1; | ||
541 | if (is_ht) { | ||
542 | sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask; | ||
543 | sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask; | ||
544 | } else { | ||
545 | sc->sc_tx_chainmask = 1; | ||
546 | sc->sc_rx_chainmask = 1; | ||
547 | } | ||
548 | |||
549 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: tx chmask: %d, rx chmask: %d\n", | ||
550 | __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask); | ||
551 | } | ||
552 | |||
553 | /******************/ | ||
554 | /* VAP management */ | ||
555 | /******************/ | ||
556 | |||
557 | /* | ||
558 | * VAP in Listen mode | ||
559 | * | ||
560 | * This routine brings the VAP out of the down state into a "listen" state | ||
561 | * where it waits for association requests. This is used in AP and AdHoc | ||
562 | * modes. | ||
563 | */ | ||
564 | |||
565 | int ath_vap_listen(struct ath_softc *sc, int if_id) | ||
566 | { | ||
567 | struct ath_hal *ah = sc->sc_ah; | ||
568 | struct ath_vap *avp; | ||
569 | u32 rfilt = 0; | ||
570 | DECLARE_MAC_BUF(mac); | ||
571 | |||
572 | avp = sc->sc_vaps[if_id]; | ||
573 | if (avp == NULL) { | ||
574 | DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n", | ||
575 | __func__, if_id); | ||
576 | return -EINVAL; | ||
577 | } | ||
578 | |||
579 | #ifdef CONFIG_SLOW_ANT_DIV | ||
580 | ath_slow_ant_div_stop(&sc->sc_antdiv); | ||
581 | #endif | ||
582 | |||
583 | /* update ratectrl about the new state */ | ||
584 | ath_rate_newstate(sc, avp); | ||
585 | |||
586 | rfilt = ath_calcrxfilter(sc); | ||
587 | ath9k_hw_setrxfilter(ah, rfilt); | ||
588 | |||
589 | if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS) { | ||
590 | memcpy(sc->sc_curbssid, ath_bcast_mac, ETH_ALEN); | ||
591 | ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid); | ||
592 | } else | ||
593 | sc->sc_curaid = 0; | ||
594 | |||
595 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
596 | "%s: RX filter 0x%x bssid %s aid 0x%x\n", | ||
597 | __func__, rfilt, print_mac(mac, | ||
598 | sc->sc_curbssid), sc->sc_curaid); | ||
599 | |||
600 | /* | ||
601 | * XXXX | ||
602 | * Disable BMISS interrupt when we're not associated | ||
603 | */ | ||
604 | ath9k_hw_set_interrupts(ah, | ||
605 | sc->sc_imask & ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS)); | ||
606 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | ||
607 | /* need to reconfigure the beacons when it moves to RUN */ | ||
608 | sc->sc_beacons = 0; | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | int ath_vap_attach(struct ath_softc *sc, | ||
614 | int if_id, | ||
615 | struct ieee80211_vif *if_data, | ||
616 | enum ath9k_opmode opmode) | ||
617 | { | ||
618 | struct ath_vap *avp; | ||
619 | |||
620 | if (if_id >= ATH_BCBUF || sc->sc_vaps[if_id] != NULL) { | ||
621 | DPRINTF(sc, ATH_DBG_FATAL, | ||
622 | "%s: Invalid interface id = %u\n", __func__, if_id); | ||
623 | return -EINVAL; | ||
624 | } | ||
625 | |||
626 | switch (opmode) { | ||
627 | case ATH9K_M_STA: | ||
628 | case ATH9K_M_IBSS: | ||
629 | case ATH9K_M_MONITOR: | ||
630 | break; | ||
631 | case ATH9K_M_HOSTAP: | ||
632 | /* XXX not right, beacon buffer is allocated on RUN trans */ | ||
633 | if (list_empty(&sc->sc_bbuf)) | ||
634 | return -ENOMEM; | ||
635 | break; | ||
636 | default: | ||
637 | return -EINVAL; | ||
638 | } | ||
639 | |||
640 | /* create ath_vap */ | ||
641 | avp = kmalloc(sizeof(struct ath_vap), GFP_KERNEL); | ||
642 | if (avp == NULL) | ||
643 | return -ENOMEM; | ||
644 | |||
645 | memzero(avp, sizeof(struct ath_vap)); | ||
646 | avp->av_if_data = if_data; | ||
647 | /* Set the VAP opmode */ | ||
648 | avp->av_opmode = opmode; | ||
649 | avp->av_bslot = -1; | ||
650 | INIT_LIST_HEAD(&avp->av_mcastq.axq_q); | ||
651 | INIT_LIST_HEAD(&avp->av_mcastq.axq_acq); | ||
652 | spin_lock_init(&avp->av_mcastq.axq_lock); | ||
653 | |||
654 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); | ||
655 | |||
656 | sc->sc_vaps[if_id] = avp; | ||
657 | sc->sc_nvaps++; | ||
658 | /* Set the device opmode */ | ||
659 | sc->sc_opmode = opmode; | ||
660 | |||
661 | /* default VAP configuration */ | ||
662 | avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE; | ||
663 | avp->av_config.av_fixed_retryset = 0x03030303; | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | int ath_vap_detach(struct ath_softc *sc, int if_id) | ||
669 | { | ||
670 | struct ath_hal *ah = sc->sc_ah; | ||
671 | struct ath_vap *avp; | ||
672 | |||
673 | avp = sc->sc_vaps[if_id]; | ||
674 | if (avp == NULL) { | ||
675 | DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n", | ||
676 | __func__, if_id); | ||
677 | return -EINVAL; | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | * Quiesce the hardware while we remove the vap. In | ||
682 | * particular we need to reclaim all references to the | ||
683 | * vap state by any frames pending on the tx queues. | ||
684 | * | ||
685 | * XXX can we do this w/o affecting other vap's? | ||
686 | */ | ||
687 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ | ||
688 | ath_draintxq(sc, false); /* stop xmit side */ | ||
689 | ath_stoprecv(sc); /* stop recv side */ | ||
690 | ath_flushrecv(sc); /* flush recv queue */ | ||
691 | |||
692 | /* Reclaim any pending mcast bufs on the vap. */ | ||
693 | ath_tx_draintxq(sc, &avp->av_mcastq, false); | ||
694 | |||
695 | kfree(avp); | ||
696 | sc->sc_vaps[if_id] = NULL; | ||
697 | sc->sc_nvaps--; | ||
698 | |||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | int ath_vap_config(struct ath_softc *sc, | ||
703 | int if_id, struct ath_vap_config *if_config) | ||
704 | { | ||
705 | struct ath_vap *avp; | ||
706 | |||
707 | if (if_id >= ATH_BCBUF) { | ||
708 | DPRINTF(sc, ATH_DBG_FATAL, | ||
709 | "%s: Invalid interface id = %u\n", __func__, if_id); | ||
710 | return -EINVAL; | ||
711 | } | ||
712 | |||
713 | avp = sc->sc_vaps[if_id]; | ||
714 | ASSERT(avp != NULL); | ||
715 | |||
716 | if (avp) | ||
717 | memcpy(&avp->av_config, if_config, sizeof(avp->av_config)); | ||
718 | |||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | /********/ | ||
723 | /* Core */ | ||
724 | /********/ | ||
725 | |||
726 | int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | ||
727 | { | ||
728 | struct ath_hal *ah = sc->sc_ah; | ||
729 | int status; | ||
730 | int error = 0; | ||
731 | enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); | ||
732 | |||
733 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", __func__, sc->sc_opmode); | ||
734 | |||
735 | /* | ||
736 | * Stop anything previously setup. This is safe | ||
737 | * whether this is the first time through or not. | ||
738 | */ | ||
739 | ath_stop(sc); | ||
740 | |||
741 | /* Initialize chanmask selection */ | ||
742 | sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask; | ||
743 | sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask; | ||
744 | |||
745 | /* Reset SERDES registers */ | ||
746 | ath9k_hw_configpcipowersave(ah, 0); | ||
747 | |||
748 | /* | ||
749 | * The basic interface to setting the hardware in a good | ||
750 | * state is ``reset''. On return the hardware is known to | ||
751 | * be powered up and with interrupts disabled. This must | ||
752 | * be followed by initialization of the appropriate bits | ||
753 | * and then setup of the interrupt mask. | ||
754 | */ | ||
755 | sc->sc_curchan = *initial_chan; | ||
756 | |||
757 | spin_lock_bh(&sc->sc_resetlock); | ||
758 | if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, ht_macmode, | ||
759 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
760 | sc->sc_ht_extprotspacing, false, &status)) { | ||
761 | DPRINTF(sc, ATH_DBG_FATAL, | ||
762 | "%s: unable to reset hardware; hal status %u " | ||
763 | "(freq %u flags 0x%x)\n", __func__, status, | ||
764 | sc->sc_curchan.channel, sc->sc_curchan.channelFlags); | ||
765 | error = -EIO; | ||
766 | spin_unlock_bh(&sc->sc_resetlock); | ||
767 | goto done; | ||
768 | } | ||
769 | spin_unlock_bh(&sc->sc_resetlock); | ||
770 | /* | ||
771 | * This is needed only to setup initial state | ||
772 | * but it's best done after a reset. | ||
773 | */ | ||
774 | ath_update_txpow(sc); | ||
775 | |||
776 | /* | ||
777 | * Setup the hardware after reset: | ||
778 | * The receive engine is set going. | ||
779 | * Frame transmit is handled entirely | ||
780 | * in the frame output path; there's nothing to do | ||
781 | * here except setup the interrupt mask. | ||
782 | */ | ||
783 | if (ath_startrecv(sc) != 0) { | ||
784 | DPRINTF(sc, ATH_DBG_FATAL, | ||
785 | "%s: unable to start recv logic\n", __func__); | ||
786 | error = -EIO; | ||
787 | goto done; | ||
788 | } | ||
789 | /* Setup our intr mask. */ | ||
790 | sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX | ||
791 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | ||
792 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; | ||
793 | |||
794 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_GTT) | ||
795 | sc->sc_imask |= ATH9K_INT_GTT; | ||
796 | |||
797 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) | ||
798 | sc->sc_imask |= ATH9K_INT_CST; | ||
799 | |||
800 | /* | ||
801 | * Enable MIB interrupts when there are hardware phy counters. | ||
802 | * Note we only do this (at the moment) for station mode. | ||
803 | */ | ||
804 | if (ath9k_hw_phycounters(ah) && | ||
805 | ((sc->sc_opmode == ATH9K_M_STA) || (sc->sc_opmode == ATH9K_M_IBSS))) | ||
806 | sc->sc_imask |= ATH9K_INT_MIB; | ||
807 | /* | ||
808 | * Some hardware processes the TIM IE and fires an | ||
809 | * interrupt when the TIM bit is set. For hardware | ||
810 | * that does, if not overridden by configuration, | ||
811 | * enable the TIM interrupt when operating as station. | ||
812 | */ | ||
813 | if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && | ||
814 | (sc->sc_opmode == ATH9K_M_STA) && | ||
815 | !sc->sc_config.swBeaconProcess) | ||
816 | sc->sc_imask |= ATH9K_INT_TIM; | ||
817 | /* | ||
818 | * Don't enable interrupts here as we've not yet built our | ||
819 | * vap and node data structures, which will be needed as soon | ||
820 | * as we start receiving. | ||
821 | */ | ||
822 | ath_setcurmode(sc, ath_chan2mode(initial_chan)); | ||
823 | |||
824 | /* XXX: we must make sure h/w is ready and clear invalid flag | ||
825 | * before turning on interrupt. */ | ||
826 | sc->sc_invalid = 0; | ||
827 | done: | ||
828 | return error; | ||
829 | } | ||
830 | |||
831 | /* | ||
832 | * Reset the hardware w/o losing operational state. This is | ||
833 | * basically a more efficient way of doing ath_stop, ath_init, | ||
834 | * followed by state transitions to the current 802.11 | ||
835 | * operational state. Used to recover from errors rx overrun | ||
836 | * and to reset the hardware when rf gain settings must be reset. | ||
837 | */ | ||
838 | |||
839 | static int ath_reset_start(struct ath_softc *sc, u32 flag) | ||
840 | { | ||
841 | struct ath_hal *ah = sc->sc_ah; | ||
842 | |||
843 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ | ||
844 | ath_draintxq(sc, flag & RESET_RETRY_TXQ); /* stop xmit side */ | ||
845 | ath_stoprecv(sc); /* stop recv side */ | ||
846 | ath_flushrecv(sc); /* flush recv queue */ | ||
847 | |||
848 | return 0; | ||
849 | } | ||
850 | |||
851 | static int ath_reset_end(struct ath_softc *sc, u32 flag) | ||
852 | { | ||
853 | struct ath_hal *ah = sc->sc_ah; | ||
854 | |||
855 | if (ath_startrecv(sc) != 0) /* restart recv */ | ||
856 | DPRINTF(sc, ATH_DBG_FATAL, | ||
857 | "%s: unable to start recv logic\n", __func__); | ||
858 | |||
859 | /* | ||
860 | * We may be doing a reset in response to a request | ||
861 | * that changes the channel so update any state that | ||
862 | * might change as a result. | ||
863 | */ | ||
864 | ath_setcurmode(sc, ath_chan2mode(&sc->sc_curchan)); | ||
865 | |||
866 | ath_update_txpow(sc); /* update tx power state */ | ||
867 | |||
868 | if (sc->sc_beacons) | ||
869 | ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ | ||
870 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
871 | |||
872 | /* Restart the txq */ | ||
873 | if (flag & RESET_RETRY_TXQ) { | ||
874 | int i; | ||
875 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
876 | if (ATH_TXQ_SETUP(sc, i)) { | ||
877 | spin_lock_bh(&sc->sc_txq[i].axq_lock); | ||
878 | ath_txq_schedule(sc, &sc->sc_txq[i]); | ||
879 | spin_unlock_bh(&sc->sc_txq[i].axq_lock); | ||
880 | } | ||
881 | } | ||
882 | } | ||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | int ath_reset(struct ath_softc *sc) | ||
887 | { | ||
888 | struct ath_hal *ah = sc->sc_ah; | ||
889 | int status; | ||
890 | int error = 0; | ||
891 | enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); | ||
892 | |||
893 | /* NB: indicate channel change so we do a full reset */ | ||
894 | spin_lock_bh(&sc->sc_resetlock); | ||
895 | if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, | ||
896 | ht_macmode, | ||
897 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
898 | sc->sc_ht_extprotspacing, false, &status)) { | ||
899 | DPRINTF(sc, ATH_DBG_FATAL, | ||
900 | "%s: unable to reset hardware; hal status %u\n", | ||
901 | __func__, status); | ||
902 | error = -EIO; | ||
903 | } | ||
904 | spin_unlock_bh(&sc->sc_resetlock); | ||
905 | |||
906 | return error; | ||
907 | } | ||
908 | |||
909 | int ath_suspend(struct ath_softc *sc) | ||
910 | { | ||
911 | struct ath_hal *ah = sc->sc_ah; | ||
912 | |||
913 | /* No I/O if device has been surprise removed */ | ||
914 | if (sc->sc_invalid) | ||
915 | return -EIO; | ||
916 | |||
917 | /* Shut off the interrupt before setting sc->sc_invalid to '1' */ | ||
918 | ath9k_hw_set_interrupts(ah, 0); | ||
919 | |||
920 | /* XXX: we must make sure h/w will not generate any interrupt | ||
921 | * before setting the invalid flag. */ | ||
922 | sc->sc_invalid = 1; | ||
923 | |||
924 | /* disable HAL and put h/w to sleep */ | ||
925 | ath9k_hw_disable(sc->sc_ah); | ||
926 | |||
927 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); | ||
928 | |||
929 | return 0; | ||
930 | } | ||
931 | |||
932 | /* Interrupt handler. Most of the actual processing is deferred. | ||
933 | * It's the caller's responsibility to ensure the chip is awake. */ | ||
934 | |||
935 | irqreturn_t ath_isr(int irq, void *dev) | ||
936 | { | ||
937 | struct ath_softc *sc = dev; | ||
938 | struct ath_hal *ah = sc->sc_ah; | ||
939 | enum ath9k_int status; | ||
940 | bool sched = false; | ||
941 | |||
942 | do { | ||
943 | if (sc->sc_invalid) { | ||
944 | /* | ||
945 | * The hardware is not ready/present, don't | ||
946 | * touch anything. Note this can happen early | ||
947 | * on if the IRQ is shared. | ||
948 | */ | ||
949 | return IRQ_NONE; | ||
950 | } | ||
951 | if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */ | ||
952 | return IRQ_NONE; | ||
953 | } | ||
954 | |||
955 | /* | ||
956 | * Figure out the reason(s) for the interrupt. Note | ||
957 | * that the hal returns a pseudo-ISR that may include | ||
958 | * bits we haven't explicitly enabled so we mask the | ||
959 | * value to insure we only process bits we requested. | ||
960 | */ | ||
961 | ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ | ||
962 | |||
963 | status &= sc->sc_imask; /* discard unasked-for bits */ | ||
964 | |||
965 | /* | ||
966 | * If there are no status bits set, then this interrupt was not | ||
967 | * for me (should have been caught above). | ||
968 | */ | ||
969 | |||
970 | if (!status) | ||
971 | return IRQ_NONE; | ||
972 | |||
973 | sc->sc_intrstatus = status; | ||
974 | |||
975 | if (status & ATH9K_INT_FATAL) { | ||
976 | /* need a chip reset */ | ||
977 | sched = true; | ||
978 | } else if (status & ATH9K_INT_RXORN) { | ||
979 | /* need a chip reset */ | ||
980 | sched = true; | ||
981 | } else { | ||
982 | if (status & ATH9K_INT_SWBA) { | ||
983 | /* schedule a tasklet for beacon handling */ | ||
984 | tasklet_schedule(&sc->bcon_tasklet); | ||
985 | } | ||
986 | if (status & ATH9K_INT_RXEOL) { | ||
987 | /* | ||
988 | * NB: the hardware should re-read the link when | ||
989 | * RXE bit is written, but it doesn't work | ||
990 | * at least on older hardware revs. | ||
991 | */ | ||
992 | sched = true; | ||
993 | } | ||
994 | |||
995 | if (status & ATH9K_INT_TXURN) | ||
996 | /* bump tx trigger level */ | ||
997 | ath9k_hw_updatetxtriglevel(ah, true); | ||
998 | /* XXX: optimize this */ | ||
999 | if (status & ATH9K_INT_RX) | ||
1000 | sched = true; | ||
1001 | if (status & ATH9K_INT_TX) | ||
1002 | sched = true; | ||
1003 | if (status & ATH9K_INT_BMISS) | ||
1004 | sched = true; | ||
1005 | /* carrier sense timeout */ | ||
1006 | if (status & ATH9K_INT_CST) | ||
1007 | sched = true; | ||
1008 | if (status & ATH9K_INT_MIB) { | ||
1009 | /* | ||
1010 | * Disable interrupts until we service the MIB | ||
1011 | * interrupt; otherwise it will continue to | ||
1012 | * fire. | ||
1013 | */ | ||
1014 | ath9k_hw_set_interrupts(ah, 0); | ||
1015 | /* | ||
1016 | * Let the hal handle the event. We assume | ||
1017 | * it will clear whatever condition caused | ||
1018 | * the interrupt. | ||
1019 | */ | ||
1020 | ath9k_hw_procmibevent(ah, &sc->sc_halstats); | ||
1021 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
1022 | } | ||
1023 | if (status & ATH9K_INT_TIM_TIMER) { | ||
1024 | if (!(ah->ah_caps.hw_caps & | ||
1025 | ATH9K_HW_CAP_AUTOSLEEP)) { | ||
1026 | /* Clear RxAbort bit so that we can | ||
1027 | * receive frames */ | ||
1028 | ath9k_hw_setrxabort(ah, 0); | ||
1029 | sched = true; | ||
1030 | } | ||
1031 | } | ||
1032 | } | ||
1033 | } while (0); | ||
1034 | |||
1035 | if (sched) { | ||
1036 | /* turn off every interrupt except SWBA */ | ||
1037 | ath9k_hw_set_interrupts(ah, (sc->sc_imask & ATH9K_INT_SWBA)); | ||
1038 | tasklet_schedule(&sc->intr_tq); | ||
1039 | } | ||
1040 | |||
1041 | return IRQ_HANDLED; | ||
1042 | } | ||
1043 | |||
1044 | /* Deferred interrupt processing */ | ||
1045 | |||
1046 | static void ath9k_tasklet(unsigned long data) | ||
1047 | { | ||
1048 | struct ath_softc *sc = (struct ath_softc *)data; | ||
1049 | u32 status = sc->sc_intrstatus; | ||
1050 | |||
1051 | if (status & ATH9K_INT_FATAL) { | ||
1052 | /* need a chip reset */ | ||
1053 | ath_internal_reset(sc); | ||
1054 | return; | ||
1055 | } else { | ||
1056 | |||
1057 | if (status & | ||
1058 | (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { | ||
1059 | /* XXX: fill me in */ | ||
1060 | /* | ||
1061 | if (status & ATH9K_INT_RXORN) { | ||
1062 | } | ||
1063 | if (status & ATH9K_INT_RXEOL) { | ||
1064 | } | ||
1065 | */ | ||
1066 | spin_lock_bh(&sc->sc_rxflushlock); | ||
1067 | ath_rx_tasklet(sc, 0); | ||
1068 | spin_unlock_bh(&sc->sc_rxflushlock); | ||
1069 | } | ||
1070 | /* XXX: optimize this */ | ||
1071 | if (status & ATH9K_INT_TX) | ||
1072 | ath_tx_tasklet(sc); | ||
1073 | /* XXX: fill me in */ | ||
1074 | /* | ||
1075 | if (status & ATH9K_INT_BMISS) { | ||
1076 | } | ||
1077 | if (status & (ATH9K_INT_TIM | ATH9K_INT_DTIMSYNC)) { | ||
1078 | if (status & ATH9K_INT_TIM) { | ||
1079 | } | ||
1080 | if (status & ATH9K_INT_DTIMSYNC) { | ||
1081 | } | ||
1082 | } | ||
1083 | */ | ||
1084 | } | ||
1085 | |||
1086 | /* re-enable hardware interrupt */ | ||
1087 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask); | ||
1088 | } | ||
1089 | |||
1090 | int ath_init(u16 devid, struct ath_softc *sc) | ||
1091 | { | ||
1092 | struct ath_hal *ah = NULL; | ||
1093 | int status; | ||
1094 | int error = 0, i; | ||
1095 | int csz = 0; | ||
1096 | u32 rd; | ||
1097 | |||
1098 | /* XXX: hardware will not be ready until ath_open() being called */ | ||
1099 | sc->sc_invalid = 1; | ||
1100 | |||
1101 | sc->sc_debug = DBG_DEFAULT; | ||
1102 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid); | ||
1103 | |||
1104 | /* Initialize tasklet */ | ||
1105 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | ||
1106 | tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, | ||
1107 | (unsigned long)sc); | ||
1108 | |||
1109 | /* | ||
1110 | * Cache line size is used to size and align various | ||
1111 | * structures used to communicate with the hardware. | ||
1112 | */ | ||
1113 | bus_read_cachesize(sc, &csz); | ||
1114 | /* XXX assert csz is non-zero */ | ||
1115 | sc->sc_cachelsz = csz << 2; /* convert to bytes */ | ||
1116 | |||
1117 | spin_lock_init(&sc->sc_resetlock); | ||
1118 | |||
1119 | ah = ath9k_hw_attach(devid, sc, sc->mem, &status); | ||
1120 | if (ah == NULL) { | ||
1121 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1122 | "%s: unable to attach hardware; HAL status %u\n", | ||
1123 | __func__, status); | ||
1124 | error = -ENXIO; | ||
1125 | goto bad; | ||
1126 | } | ||
1127 | sc->sc_ah = ah; | ||
1128 | |||
1129 | /* Get the chipset-specific aggr limit. */ | ||
1130 | sc->sc_rtsaggrlimit = ah->ah_caps.rts_aggr_limit; | ||
1131 | |||
1132 | /* Get the hardware key cache size. */ | ||
1133 | sc->sc_keymax = ah->ah_caps.keycache_size; | ||
1134 | if (sc->sc_keymax > ATH_KEYMAX) { | ||
1135 | DPRINTF(sc, ATH_DBG_KEYCACHE, | ||
1136 | "%s: Warning, using only %u entries in %u key cache\n", | ||
1137 | __func__, ATH_KEYMAX, sc->sc_keymax); | ||
1138 | sc->sc_keymax = ATH_KEYMAX; | ||
1139 | } | ||
1140 | |||
1141 | /* | ||
1142 | * Reset the key cache since some parts do not | ||
1143 | * reset the contents on initial power up. | ||
1144 | */ | ||
1145 | for (i = 0; i < sc->sc_keymax; i++) | ||
1146 | ath9k_hw_keyreset(ah, (u16) i); | ||
1147 | /* | ||
1148 | * Mark key cache slots associated with global keys | ||
1149 | * as in use. If we knew TKIP was not to be used we | ||
1150 | * could leave the +32, +64, and +32+64 slots free. | ||
1151 | * XXX only for splitmic. | ||
1152 | */ | ||
1153 | for (i = 0; i < IEEE80211_WEP_NKID; i++) { | ||
1154 | set_bit(i, sc->sc_keymap); | ||
1155 | set_bit(i + 32, sc->sc_keymap); | ||
1156 | set_bit(i + 64, sc->sc_keymap); | ||
1157 | set_bit(i + 32 + 64, sc->sc_keymap); | ||
1158 | } | ||
1159 | /* | ||
1160 | * Collect the channel list using the default country | ||
1161 | * code and including outdoor channels. The 802.11 layer | ||
1162 | * is resposible for filtering this list based on settings | ||
1163 | * like the phy mode. | ||
1164 | */ | ||
1165 | rd = ah->ah_currentRD; | ||
1166 | |||
1167 | error = ath_setup_channels(sc); | ||
1168 | if (error) | ||
1169 | goto bad; | ||
1170 | |||
1171 | /* default to STA mode */ | ||
1172 | sc->sc_opmode = ATH9K_M_MONITOR; | ||
1173 | |||
1174 | /* Setup rate tables */ | ||
1175 | |||
1176 | ath_setup_rates(sc, IEEE80211_BAND_2GHZ); | ||
1177 | ath_setup_rates(sc, IEEE80211_BAND_5GHZ); | ||
1178 | |||
1179 | /* NB: setup here so ath_rate_update is happy */ | ||
1180 | ath_setcurmode(sc, ATH9K_MODE_11A); | ||
1181 | |||
1182 | /* | ||
1183 | * Allocate hardware transmit queues: one queue for | ||
1184 | * beacon frames and one data queue for each QoS | ||
1185 | * priority. Note that the hal handles reseting | ||
1186 | * these queues at the needed time. | ||
1187 | */ | ||
1188 | sc->sc_bhalq = ath_beaconq_setup(ah); | ||
1189 | if (sc->sc_bhalq == -1) { | ||
1190 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1191 | "%s: unable to setup a beacon xmit queue\n", __func__); | ||
1192 | error = -EIO; | ||
1193 | goto bad2; | ||
1194 | } | ||
1195 | sc->sc_cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | ||
1196 | if (sc->sc_cabq == NULL) { | ||
1197 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1198 | "%s: unable to setup CAB xmit queue\n", __func__); | ||
1199 | error = -EIO; | ||
1200 | goto bad2; | ||
1201 | } | ||
1202 | |||
1203 | sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME; | ||
1204 | ath_cabq_update(sc); | ||
1205 | |||
1206 | for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++) | ||
1207 | sc->sc_haltype2q[i] = -1; | ||
1208 | |||
1209 | /* Setup data queues */ | ||
1210 | /* NB: ensure BK queue is the lowest priority h/w queue */ | ||
1211 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | ||
1212 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1213 | "%s: unable to setup xmit queue for BK traffic\n", | ||
1214 | __func__); | ||
1215 | error = -EIO; | ||
1216 | goto bad2; | ||
1217 | } | ||
1218 | |||
1219 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | ||
1220 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1221 | "%s: unable to setup xmit queue for BE traffic\n", | ||
1222 | __func__); | ||
1223 | error = -EIO; | ||
1224 | goto bad2; | ||
1225 | } | ||
1226 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | ||
1227 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1228 | "%s: unable to setup xmit queue for VI traffic\n", | ||
1229 | __func__); | ||
1230 | error = -EIO; | ||
1231 | goto bad2; | ||
1232 | } | ||
1233 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | ||
1234 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1235 | "%s: unable to setup xmit queue for VO traffic\n", | ||
1236 | __func__); | ||
1237 | error = -EIO; | ||
1238 | goto bad2; | ||
1239 | } | ||
1240 | |||
1241 | sc->sc_rc = ath_rate_attach(ah); | ||
1242 | if (sc->sc_rc == NULL) { | ||
1243 | error = EIO; | ||
1244 | goto bad2; | ||
1245 | } | ||
1246 | |||
1247 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1248 | ATH9K_CIPHER_TKIP, NULL)) { | ||
1249 | /* | ||
1250 | * Whether we should enable h/w TKIP MIC. | ||
1251 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
1252 | * report WMM capable, so it's always safe to turn on | ||
1253 | * TKIP MIC in this case. | ||
1254 | */ | ||
1255 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, | ||
1256 | 0, 1, NULL); | ||
1257 | } | ||
1258 | |||
1259 | /* | ||
1260 | * Check whether the separate key cache entries | ||
1261 | * are required to handle both tx+rx MIC keys. | ||
1262 | * With split mic keys the number of stations is limited | ||
1263 | * to 27 otherwise 59. | ||
1264 | */ | ||
1265 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1266 | ATH9K_CIPHER_TKIP, NULL) | ||
1267 | && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1268 | ATH9K_CIPHER_MIC, NULL) | ||
1269 | && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, | ||
1270 | 0, NULL)) | ||
1271 | sc->sc_splitmic = 1; | ||
1272 | |||
1273 | /* turn on mcast key search if possible */ | ||
1274 | if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
1275 | (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, | ||
1276 | 1, NULL); | ||
1277 | |||
1278 | sc->sc_config.txpowlimit = ATH_TXPOWER_MAX; | ||
1279 | sc->sc_config.txpowlimit_override = 0; | ||
1280 | |||
1281 | /* 11n Capabilities */ | ||
1282 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
1283 | sc->sc_txaggr = 1; | ||
1284 | sc->sc_rxaggr = 1; | ||
1285 | } | ||
1286 | |||
1287 | sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask; | ||
1288 | sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask; | ||
1289 | |||
1290 | /* Configuration for rx chain detection */ | ||
1291 | sc->sc_rxchaindetect_ref = 0; | ||
1292 | sc->sc_rxchaindetect_thresh5GHz = 35; | ||
1293 | sc->sc_rxchaindetect_thresh2GHz = 35; | ||
1294 | sc->sc_rxchaindetect_delta5GHz = 30; | ||
1295 | sc->sc_rxchaindetect_delta2GHz = 30; | ||
1296 | |||
1297 | ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); | ||
1298 | sc->sc_defant = ath9k_hw_getdefantenna(ah); | ||
1299 | |||
1300 | ath9k_hw_getmac(ah, sc->sc_myaddr); | ||
1301 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) { | ||
1302 | ath9k_hw_getbssidmask(ah, sc->sc_bssidmask); | ||
1303 | ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask); | ||
1304 | ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); | ||
1305 | } | ||
1306 | sc->sc_slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ | ||
1307 | |||
1308 | /* initialize beacon slots */ | ||
1309 | for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++) | ||
1310 | sc->sc_bslot[i] = ATH_IF_ID_ANY; | ||
1311 | |||
1312 | /* save MISC configurations */ | ||
1313 | sc->sc_config.swBeaconProcess = 1; | ||
1314 | |||
1315 | #ifdef CONFIG_SLOW_ANT_DIV | ||
1316 | /* range is 40 - 255, we use something in the middle */ | ||
1317 | ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127); | ||
1318 | #endif | ||
1319 | |||
1320 | return 0; | ||
1321 | bad2: | ||
1322 | /* cleanup tx queues */ | ||
1323 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1324 | if (ATH_TXQ_SETUP(sc, i)) | ||
1325 | ath_tx_cleanupq(sc, &sc->sc_txq[i]); | ||
1326 | bad: | ||
1327 | if (ah) | ||
1328 | ath9k_hw_detach(ah); | ||
1329 | return error; | ||
1330 | } | ||
1331 | |||
1332 | void ath_deinit(struct ath_softc *sc) | ||
1333 | { | ||
1334 | struct ath_hal *ah = sc->sc_ah; | ||
1335 | int i; | ||
1336 | |||
1337 | DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__); | ||
1338 | |||
1339 | ath_stop(sc); | ||
1340 | if (!sc->sc_invalid) | ||
1341 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | ||
1342 | ath_rate_detach(sc->sc_rc); | ||
1343 | /* cleanup tx queues */ | ||
1344 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1345 | if (ATH_TXQ_SETUP(sc, i)) | ||
1346 | ath_tx_cleanupq(sc, &sc->sc_txq[i]); | ||
1347 | ath9k_hw_detach(ah); | ||
1348 | } | ||
1349 | |||
1350 | /*******************/ | ||
1351 | /* Node Management */ | ||
1352 | /*******************/ | ||
1353 | |||
1354 | struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id) | ||
1355 | { | ||
1356 | struct ath_vap *avp; | ||
1357 | struct ath_node *an; | ||
1358 | DECLARE_MAC_BUF(mac); | ||
1359 | |||
1360 | avp = sc->sc_vaps[if_id]; | ||
1361 | ASSERT(avp != NULL); | ||
1362 | |||
1363 | /* mac80211 sta_notify callback is from an IRQ context, so no sleep */ | ||
1364 | an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC); | ||
1365 | if (an == NULL) | ||
1366 | return NULL; | ||
1367 | memzero(an, sizeof(*an)); | ||
1368 | |||
1369 | an->an_sc = sc; | ||
1370 | memcpy(an->an_addr, addr, ETH_ALEN); | ||
1371 | atomic_set(&an->an_refcnt, 1); | ||
1372 | |||
1373 | /* set up per-node tx/rx state */ | ||
1374 | ath_tx_node_init(sc, an); | ||
1375 | ath_rx_node_init(sc, an); | ||
1376 | |||
1377 | ath_chainmask_sel_init(sc, an); | ||
1378 | ath_chainmask_sel_timerstart(&an->an_chainmask_sel); | ||
1379 | list_add(&an->list, &sc->node_list); | ||
1380 | |||
1381 | return an; | ||
1382 | } | ||
1383 | |||
1384 | void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag) | ||
1385 | { | ||
1386 | unsigned long flags; | ||
1387 | |||
1388 | DECLARE_MAC_BUF(mac); | ||
1389 | |||
1390 | ath_chainmask_sel_timerstop(&an->an_chainmask_sel); | ||
1391 | an->an_flags |= ATH_NODE_CLEAN; | ||
1392 | ath_tx_node_cleanup(sc, an, bh_flag); | ||
1393 | ath_rx_node_cleanup(sc, an); | ||
1394 | |||
1395 | ath_tx_node_free(sc, an); | ||
1396 | ath_rx_node_free(sc, an); | ||
1397 | |||
1398 | spin_lock_irqsave(&sc->node_lock, flags); | ||
1399 | |||
1400 | list_del(&an->list); | ||
1401 | |||
1402 | spin_unlock_irqrestore(&sc->node_lock, flags); | ||
1403 | |||
1404 | kfree(an); | ||
1405 | } | ||
1406 | |||
1407 | /* Finds a node and increases the refcnt if found */ | ||
1408 | |||
1409 | struct ath_node *ath_node_get(struct ath_softc *sc, u8 *addr) | ||
1410 | { | ||
1411 | struct ath_node *an = NULL, *an_found = NULL; | ||
1412 | |||
1413 | if (list_empty(&sc->node_list)) /* FIXME */ | ||
1414 | goto out; | ||
1415 | list_for_each_entry(an, &sc->node_list, list) { | ||
1416 | if (!compare_ether_addr(an->an_addr, addr)) { | ||
1417 | atomic_inc(&an->an_refcnt); | ||
1418 | an_found = an; | ||
1419 | break; | ||
1420 | } | ||
1421 | } | ||
1422 | out: | ||
1423 | return an_found; | ||
1424 | } | ||
1425 | |||
1426 | /* Decrements the refcnt and if it drops to zero, detach the node */ | ||
1427 | |||
1428 | void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag) | ||
1429 | { | ||
1430 | if (atomic_dec_and_test(&an->an_refcnt)) | ||
1431 | ath_node_detach(sc, an, bh_flag); | ||
1432 | } | ||
1433 | |||
1434 | /* Finds a node, doesn't increment refcnt. Caller must hold sc->node_lock */ | ||
1435 | struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr) | ||
1436 | { | ||
1437 | struct ath_node *an = NULL, *an_found = NULL; | ||
1438 | |||
1439 | if (list_empty(&sc->node_list)) | ||
1440 | return NULL; | ||
1441 | |||
1442 | list_for_each_entry(an, &sc->node_list, list) | ||
1443 | if (!compare_ether_addr(an->an_addr, addr)) { | ||
1444 | an_found = an; | ||
1445 | break; | ||
1446 | } | ||
1447 | |||
1448 | return an_found; | ||
1449 | } | ||
1450 | |||
1451 | /* | ||
1452 | * Set up New Node | ||
1453 | * | ||
1454 | * Setup driver-specific state for a newly associated node. This routine | ||
1455 | * really only applies if compression or XR are enabled, there is no code | ||
1456 | * covering any other cases. | ||
1457 | */ | ||
1458 | |||
1459 | void ath_newassoc(struct ath_softc *sc, | ||
1460 | struct ath_node *an, int isnew, int isuapsd) | ||
1461 | { | ||
1462 | int tidno; | ||
1463 | |||
1464 | /* if station reassociates, tear down the aggregation state. */ | ||
1465 | if (!isnew) { | ||
1466 | for (tidno = 0; tidno < WME_NUM_TID; tidno++) { | ||
1467 | if (sc->sc_txaggr) | ||
1468 | ath_tx_aggr_teardown(sc, an, tidno); | ||
1469 | if (sc->sc_rxaggr) | ||
1470 | ath_rx_aggr_teardown(sc, an, tidno); | ||
1471 | } | ||
1472 | } | ||
1473 | an->an_flags = 0; | ||
1474 | } | ||
1475 | |||
1476 | /**************/ | ||
1477 | /* Encryption */ | ||
1478 | /**************/ | ||
1479 | |||
1480 | void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot) | ||
1481 | { | ||
1482 | ath9k_hw_keyreset(sc->sc_ah, keyix); | ||
1483 | if (freeslot) | ||
1484 | clear_bit(keyix, sc->sc_keymap); | ||
1485 | } | ||
1486 | |||
1487 | int ath_keyset(struct ath_softc *sc, | ||
1488 | u16 keyix, | ||
1489 | struct ath9k_keyval *hk, | ||
1490 | const u8 mac[ETH_ALEN]) | ||
1491 | { | ||
1492 | bool status; | ||
1493 | |||
1494 | status = ath9k_hw_set_keycache_entry(sc->sc_ah, | ||
1495 | keyix, hk, mac, false); | ||
1496 | |||
1497 | return status != false; | ||
1498 | } | ||
1499 | |||
1500 | /***********************/ | ||
1501 | /* TX Power/Regulatory */ | ||
1502 | /***********************/ | ||
1503 | |||
1504 | /* | ||
1505 | * Set Transmit power in HAL | ||
1506 | * | ||
1507 | * This routine makes the actual HAL calls to set the new transmit power | ||
1508 | * limit. | ||
1509 | */ | ||
1510 | |||
1511 | void ath_update_txpow(struct ath_softc *sc) | ||
1512 | { | ||
1513 | struct ath_hal *ah = sc->sc_ah; | ||
1514 | u32 txpow; | ||
1515 | |||
1516 | if (sc->sc_curtxpow != sc->sc_config.txpowlimit) { | ||
1517 | ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit); | ||
1518 | /* read back in case value is clamped */ | ||
1519 | ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); | ||
1520 | sc->sc_curtxpow = txpow; | ||
1521 | } | ||
1522 | } | ||
1523 | |||
1524 | /* Return the current country and domain information */ | ||
1525 | void ath_get_currentCountry(struct ath_softc *sc, | ||
1526 | struct ath9k_country_entry *ctry) | ||
1527 | { | ||
1528 | ath9k_regd_get_current_country(sc->sc_ah, ctry); | ||
1529 | |||
1530 | /* If HAL not specific yet, since it is band dependent, | ||
1531 | * use the one we passed in. */ | ||
1532 | if (ctry->countryCode == CTRY_DEFAULT) { | ||
1533 | ctry->iso[0] = 0; | ||
1534 | ctry->iso[1] = 0; | ||
1535 | } else if (ctry->iso[0] && ctry->iso[1]) { | ||
1536 | if (!ctry->iso[2]) { | ||
1537 | if (ath_outdoor) | ||
1538 | ctry->iso[2] = 'O'; | ||
1539 | else | ||
1540 | ctry->iso[2] = 'I'; | ||
1541 | } | ||
1542 | } | ||
1543 | } | ||
1544 | |||
1545 | /**************************/ | ||
1546 | /* Slow Antenna Diversity */ | ||
1547 | /**************************/ | ||
1548 | |||
1549 | void ath_slow_ant_div_init(struct ath_antdiv *antdiv, | ||
1550 | struct ath_softc *sc, | ||
1551 | int32_t rssitrig) | ||
1552 | { | ||
1553 | int trig; | ||
1554 | |||
1555 | /* antdivf_rssitrig can range from 40 - 0xff */ | ||
1556 | trig = (rssitrig > 0xff) ? 0xff : rssitrig; | ||
1557 | trig = (rssitrig < 40) ? 40 : rssitrig; | ||
1558 | |||
1559 | antdiv->antdiv_sc = sc; | ||
1560 | antdiv->antdivf_rssitrig = trig; | ||
1561 | } | ||
1562 | |||
1563 | void ath_slow_ant_div_start(struct ath_antdiv *antdiv, | ||
1564 | u8 num_antcfg, | ||
1565 | const u8 *bssid) | ||
1566 | { | ||
1567 | antdiv->antdiv_num_antcfg = | ||
1568 | num_antcfg < ATH_ANT_DIV_MAX_CFG ? | ||
1569 | num_antcfg : ATH_ANT_DIV_MAX_CFG; | ||
1570 | antdiv->antdiv_state = ATH_ANT_DIV_IDLE; | ||
1571 | antdiv->antdiv_curcfg = 0; | ||
1572 | antdiv->antdiv_bestcfg = 0; | ||
1573 | antdiv->antdiv_laststatetsf = 0; | ||
1574 | |||
1575 | memcpy(antdiv->antdiv_bssid, bssid, sizeof(antdiv->antdiv_bssid)); | ||
1576 | |||
1577 | antdiv->antdiv_start = 1; | ||
1578 | } | ||
1579 | |||
1580 | void ath_slow_ant_div_stop(struct ath_antdiv *antdiv) | ||
1581 | { | ||
1582 | antdiv->antdiv_start = 0; | ||
1583 | } | ||
1584 | |||
1585 | static int32_t ath_find_max_val(int32_t *val, | ||
1586 | u8 num_val, u8 *max_index) | ||
1587 | { | ||
1588 | u32 MaxVal = *val++; | ||
1589 | u32 cur_index = 0; | ||
1590 | |||
1591 | *max_index = 0; | ||
1592 | while (++cur_index < num_val) { | ||
1593 | if (*val > MaxVal) { | ||
1594 | MaxVal = *val; | ||
1595 | *max_index = cur_index; | ||
1596 | } | ||
1597 | |||
1598 | val++; | ||
1599 | } | ||
1600 | |||
1601 | return MaxVal; | ||
1602 | } | ||
1603 | |||
1604 | void ath_slow_ant_div(struct ath_antdiv *antdiv, | ||
1605 | struct ieee80211_hdr *hdr, | ||
1606 | struct ath_rx_status *rx_stats) | ||
1607 | { | ||
1608 | struct ath_softc *sc = antdiv->antdiv_sc; | ||
1609 | struct ath_hal *ah = sc->sc_ah; | ||
1610 | u64 curtsf = 0; | ||
1611 | u8 bestcfg, curcfg = antdiv->antdiv_curcfg; | ||
1612 | __le16 fc = hdr->frame_control; | ||
1613 | |||
1614 | if (antdiv->antdiv_start && ieee80211_is_beacon(fc) | ||
1615 | && !compare_ether_addr(hdr->addr3, antdiv->antdiv_bssid)) { | ||
1616 | antdiv->antdiv_lastbrssi[curcfg] = rx_stats->rs_rssi; | ||
1617 | antdiv->antdiv_lastbtsf[curcfg] = ath9k_hw_gettsf64(sc->sc_ah); | ||
1618 | curtsf = antdiv->antdiv_lastbtsf[curcfg]; | ||
1619 | } else { | ||
1620 | return; | ||
1621 | } | ||
1622 | |||
1623 | switch (antdiv->antdiv_state) { | ||
1624 | case ATH_ANT_DIV_IDLE: | ||
1625 | if ((antdiv->antdiv_lastbrssi[curcfg] < | ||
1626 | antdiv->antdivf_rssitrig) | ||
1627 | && ((curtsf - antdiv->antdiv_laststatetsf) > | ||
1628 | ATH_ANT_DIV_MIN_IDLE_US)) { | ||
1629 | |||
1630 | curcfg++; | ||
1631 | if (curcfg == antdiv->antdiv_num_antcfg) | ||
1632 | curcfg = 0; | ||
1633 | |||
1634 | if (!ath9k_hw_select_antconfig(ah, curcfg)) { | ||
1635 | antdiv->antdiv_bestcfg = antdiv->antdiv_curcfg; | ||
1636 | antdiv->antdiv_curcfg = curcfg; | ||
1637 | antdiv->antdiv_laststatetsf = curtsf; | ||
1638 | antdiv->antdiv_state = ATH_ANT_DIV_SCAN; | ||
1639 | } | ||
1640 | } | ||
1641 | break; | ||
1642 | |||
1643 | case ATH_ANT_DIV_SCAN: | ||
1644 | if ((curtsf - antdiv->antdiv_laststatetsf) < | ||
1645 | ATH_ANT_DIV_MIN_SCAN_US) | ||
1646 | break; | ||
1647 | |||
1648 | curcfg++; | ||
1649 | if (curcfg == antdiv->antdiv_num_antcfg) | ||
1650 | curcfg = 0; | ||
1651 | |||
1652 | if (curcfg == antdiv->antdiv_bestcfg) { | ||
1653 | ath_find_max_val(antdiv->antdiv_lastbrssi, | ||
1654 | antdiv->antdiv_num_antcfg, &bestcfg); | ||
1655 | if (!ath9k_hw_select_antconfig(ah, bestcfg)) { | ||
1656 | antdiv->antdiv_bestcfg = bestcfg; | ||
1657 | antdiv->antdiv_curcfg = bestcfg; | ||
1658 | antdiv->antdiv_laststatetsf = curtsf; | ||
1659 | antdiv->antdiv_state = ATH_ANT_DIV_IDLE; | ||
1660 | } | ||
1661 | } else { | ||
1662 | if (!ath9k_hw_select_antconfig(ah, curcfg)) { | ||
1663 | antdiv->antdiv_curcfg = curcfg; | ||
1664 | antdiv->antdiv_laststatetsf = curtsf; | ||
1665 | antdiv->antdiv_state = ATH_ANT_DIV_SCAN; | ||
1666 | } | ||
1667 | } | ||
1668 | |||
1669 | break; | ||
1670 | } | ||
1671 | } | ||
1672 | |||
1673 | /***********************/ | ||
1674 | /* Descriptor Handling */ | ||
1675 | /***********************/ | ||
1676 | |||
1677 | /* | ||
1678 | * Set up DMA descriptors | ||
1679 | * | ||
1680 | * This function will allocate both the DMA descriptor structure, and the | ||
1681 | * buffers it contains. These are used to contain the descriptors used | ||
1682 | * by the system. | ||
1683 | */ | ||
1684 | |||
1685 | int ath_descdma_setup(struct ath_softc *sc, | ||
1686 | struct ath_descdma *dd, | ||
1687 | struct list_head *head, | ||
1688 | const char *name, | ||
1689 | int nbuf, | ||
1690 | int ndesc) | ||
1691 | { | ||
1692 | #define DS2PHYS(_dd, _ds) \ | ||
1693 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) | ||
1694 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) | ||
1695 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) | ||
1696 | |||
1697 | struct ath_desc *ds; | ||
1698 | struct ath_buf *bf; | ||
1699 | int i, bsize, error; | ||
1700 | |||
1701 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA: %u buffers %u desc/buf\n", | ||
1702 | __func__, name, nbuf, ndesc); | ||
1703 | |||
1704 | /* ath_desc must be a multiple of DWORDs */ | ||
1705 | if ((sizeof(struct ath_desc) % 4) != 0) { | ||
1706 | DPRINTF(sc, ATH_DBG_FATAL, "%s: ath_desc not DWORD aligned\n", | ||
1707 | __func__); | ||
1708 | ASSERT((sizeof(struct ath_desc) % 4) == 0); | ||
1709 | error = -ENOMEM; | ||
1710 | goto fail; | ||
1711 | } | ||
1712 | |||
1713 | dd->dd_name = name; | ||
1714 | dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; | ||
1715 | |||
1716 | /* | ||
1717 | * Need additional DMA memory because we can't use | ||
1718 | * descriptors that cross the 4K page boundary. Assume | ||
1719 | * one skipped descriptor per 4K page. | ||
1720 | */ | ||
1721 | if (!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
1722 | u32 ndesc_skipped = | ||
1723 | ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); | ||
1724 | u32 dma_len; | ||
1725 | |||
1726 | while (ndesc_skipped) { | ||
1727 | dma_len = ndesc_skipped * sizeof(struct ath_desc); | ||
1728 | dd->dd_desc_len += dma_len; | ||
1729 | |||
1730 | ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); | ||
1731 | }; | ||
1732 | } | ||
1733 | |||
1734 | /* allocate descriptors */ | ||
1735 | dd->dd_desc = pci_alloc_consistent(sc->pdev, | ||
1736 | dd->dd_desc_len, | ||
1737 | &dd->dd_desc_paddr); | ||
1738 | if (dd->dd_desc == NULL) { | ||
1739 | error = -ENOMEM; | ||
1740 | goto fail; | ||
1741 | } | ||
1742 | ds = dd->dd_desc; | ||
1743 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA map: %p (%u) -> %llx (%u)\n", | ||
1744 | __func__, dd->dd_name, ds, (u32) dd->dd_desc_len, | ||
1745 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | ||
1746 | |||
1747 | /* allocate buffers */ | ||
1748 | bsize = sizeof(struct ath_buf) * nbuf; | ||
1749 | bf = kmalloc(bsize, GFP_KERNEL); | ||
1750 | if (bf == NULL) { | ||
1751 | error = -ENOMEM; | ||
1752 | goto fail2; | ||
1753 | } | ||
1754 | memzero(bf, bsize); | ||
1755 | dd->dd_bufptr = bf; | ||
1756 | |||
1757 | INIT_LIST_HEAD(head); | ||
1758 | for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { | ||
1759 | bf->bf_desc = ds; | ||
1760 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
1761 | |||
1762 | if (!(sc->sc_ah->ah_caps.hw_caps & | ||
1763 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
1764 | /* | ||
1765 | * Skip descriptor addresses which can cause 4KB | ||
1766 | * boundary crossing (addr + length) with a 32 dword | ||
1767 | * descriptor fetch. | ||
1768 | */ | ||
1769 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | ||
1770 | ASSERT((caddr_t) bf->bf_desc < | ||
1771 | ((caddr_t) dd->dd_desc + | ||
1772 | dd->dd_desc_len)); | ||
1773 | |||
1774 | ds += ndesc; | ||
1775 | bf->bf_desc = ds; | ||
1776 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
1777 | } | ||
1778 | } | ||
1779 | list_add_tail(&bf->list, head); | ||
1780 | } | ||
1781 | return 0; | ||
1782 | fail2: | ||
1783 | pci_free_consistent(sc->pdev, | ||
1784 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); | ||
1785 | fail: | ||
1786 | memzero(dd, sizeof(*dd)); | ||
1787 | return error; | ||
1788 | #undef ATH_DESC_4KB_BOUND_CHECK | ||
1789 | #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED | ||
1790 | #undef DS2PHYS | ||
1791 | } | ||
1792 | |||
1793 | /* | ||
1794 | * Cleanup DMA descriptors | ||
1795 | * | ||
1796 | * This function will free the DMA block that was allocated for the descriptor | ||
1797 | * pool. Since this was allocated as one "chunk", it is freed in the same | ||
1798 | * manner. | ||
1799 | */ | ||
1800 | |||
1801 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
1802 | struct ath_descdma *dd, | ||
1803 | struct list_head *head) | ||
1804 | { | ||
1805 | /* Free memory associated with descriptors */ | ||
1806 | pci_free_consistent(sc->pdev, | ||
1807 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); | ||
1808 | |||
1809 | INIT_LIST_HEAD(head); | ||
1810 | kfree(dd->dd_bufptr); | ||
1811 | memzero(dd, sizeof(*dd)); | ||
1812 | } | ||
1813 | |||
1814 | /*************/ | ||
1815 | /* Utilities */ | ||
1816 | /*************/ | ||
1817 | |||
1818 | void ath_internal_reset(struct ath_softc *sc) | ||
1819 | { | ||
1820 | ath_reset_start(sc, 0); | ||
1821 | ath_reset(sc); | ||
1822 | ath_reset_end(sc, 0); | ||
1823 | } | ||
1824 | |||
1825 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) | ||
1826 | { | ||
1827 | int qnum; | ||
1828 | |||
1829 | switch (queue) { | ||
1830 | case 0: | ||
1831 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO]; | ||
1832 | break; | ||
1833 | case 1: | ||
1834 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI]; | ||
1835 | break; | ||
1836 | case 2: | ||
1837 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; | ||
1838 | break; | ||
1839 | case 3: | ||
1840 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK]; | ||
1841 | break; | ||
1842 | default: | ||
1843 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; | ||
1844 | break; | ||
1845 | } | ||
1846 | |||
1847 | return qnum; | ||
1848 | } | ||
1849 | |||
1850 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) | ||
1851 | { | ||
1852 | int qnum; | ||
1853 | |||
1854 | switch (queue) { | ||
1855 | case ATH9K_WME_AC_VO: | ||
1856 | qnum = 0; | ||
1857 | break; | ||
1858 | case ATH9K_WME_AC_VI: | ||
1859 | qnum = 1; | ||
1860 | break; | ||
1861 | case ATH9K_WME_AC_BE: | ||
1862 | qnum = 2; | ||
1863 | break; | ||
1864 | case ATH9K_WME_AC_BK: | ||
1865 | qnum = 3; | ||
1866 | break; | ||
1867 | default: | ||
1868 | qnum = -1; | ||
1869 | break; | ||
1870 | } | ||
1871 | |||
1872 | return qnum; | ||
1873 | } | ||
1874 | |||
1875 | |||
1876 | /* | ||
1877 | * Expand time stamp to TSF | ||
1878 | * | ||
1879 | * Extend 15-bit time stamp from rx descriptor to | ||
1880 | * a full 64-bit TSF using the current h/w TSF. | ||
1881 | */ | ||
1882 | |||
1883 | u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) | ||
1884 | { | ||
1885 | u64 tsf; | ||
1886 | |||
1887 | tsf = ath9k_hw_gettsf64(sc->sc_ah); | ||
1888 | if ((tsf & 0x7fff) < rstamp) | ||
1889 | tsf -= 0x8000; | ||
1890 | return (tsf & ~0x7fff) | rstamp; | ||
1891 | } | ||
1892 | |||
1893 | /* | ||
1894 | * Set Default Antenna | ||
1895 | * | ||
1896 | * Call into the HAL to set the default antenna to use. Not really valid for | ||
1897 | * MIMO technology. | ||
1898 | */ | ||
1899 | |||
1900 | void ath_setdefantenna(void *context, u32 antenna) | ||
1901 | { | ||
1902 | struct ath_softc *sc = (struct ath_softc *)context; | ||
1903 | struct ath_hal *ah = sc->sc_ah; | ||
1904 | |||
1905 | /* XXX block beacon interrupts */ | ||
1906 | ath9k_hw_setantenna(ah, antenna); | ||
1907 | sc->sc_defant = antenna; | ||
1908 | sc->sc_rxotherant = 0; | ||
1909 | } | ||
1910 | |||
1911 | /* | ||
1912 | * Set Slot Time | ||
1913 | * | ||
1914 | * This will wake up the chip if required, and set the slot time for the | ||
1915 | * frame (maximum transmit time). Slot time is assumed to be already set | ||
1916 | * in the ATH object member sc_slottime | ||
1917 | */ | ||
1918 | |||
1919 | void ath_setslottime(struct ath_softc *sc) | ||
1920 | { | ||
1921 | ath9k_hw_setslottime(sc->sc_ah, sc->sc_slottime); | ||
1922 | sc->sc_updateslot = OK; | ||
1923 | } | ||
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h new file mode 100644 index 000000000000..673b3d81133a --- /dev/null +++ b/drivers/net/wireless/ath9k/core.h | |||
@@ -0,0 +1,1072 @@ | |||
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 in SW (vs HW) */ | ||
144 | }; | ||
145 | |||
146 | /***********************/ | ||
147 | /* Chainmask Selection */ | ||
148 | /***********************/ | ||
149 | |||
150 | #define ATH_CHAINMASK_SEL_TIMEOUT 6000 | ||
151 | /* Default - Number of last RSSI values that is used for | ||
152 | * chainmask selection */ | ||
153 | #define ATH_CHAINMASK_SEL_RSSI_CNT 10 | ||
154 | /* Means use 3x3 chainmask instead of configured chainmask */ | ||
155 | #define ATH_CHAINMASK_SEL_3X3 7 | ||
156 | /* Default - Rssi threshold below which we have to switch to 3x3 */ | ||
157 | #define ATH_CHAINMASK_SEL_UP_RSSI_THRES 20 | ||
158 | /* Default - Rssi threshold above which we have to switch to | ||
159 | * user configured values */ | ||
160 | #define ATH_CHAINMASK_SEL_DOWN_RSSI_THRES 35 | ||
161 | /* Struct to store the chainmask select related info */ | ||
162 | struct ath_chainmask_sel { | ||
163 | struct timer_list timer; | ||
164 | int cur_tx_mask; /* user configured or 3x3 */ | ||
165 | int cur_rx_mask; /* user configured or 3x3 */ | ||
166 | int tx_avgrssi; | ||
167 | u8 switch_allowed:1, /* timer will set this */ | ||
168 | cm_sel_enabled : 1; | ||
169 | }; | ||
170 | |||
171 | int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an); | ||
172 | void ath_update_chainmask(struct ath_softc *sc, int is_ht); | ||
173 | |||
174 | /*************************/ | ||
175 | /* Descriptor Management */ | ||
176 | /*************************/ | ||
177 | |||
178 | /* Number of descriptors per buffer. The only case where we see skbuff | ||
179 | chains is due to FF aggregation in the driver. */ | ||
180 | #define ATH_TXDESC 1 | ||
181 | /* if there's more fragment for this MSDU */ | ||
182 | #define ATH_BF_MORE_MPDU 1 | ||
183 | #define ATH_TXBUF_RESET(_bf) do { \ | ||
184 | (_bf)->bf_status = 0; \ | ||
185 | (_bf)->bf_lastbf = NULL; \ | ||
186 | (_bf)->bf_lastfrm = NULL; \ | ||
187 | (_bf)->bf_next = NULL; \ | ||
188 | memzero(&((_bf)->bf_state), \ | ||
189 | sizeof(struct ath_buf_state)); \ | ||
190 | } while (0) | ||
191 | |||
192 | struct ath_buf_state { | ||
193 | int bfs_nframes; /* # frames in aggregate */ | ||
194 | u16 bfs_al; /* length of aggregate */ | ||
195 | u16 bfs_frmlen; /* length of frame */ | ||
196 | int bfs_seqno; /* sequence number */ | ||
197 | int bfs_tidno; /* tid of this frame */ | ||
198 | int bfs_retries; /* current retries */ | ||
199 | struct ath_rc_series bfs_rcs[4]; /* rate series */ | ||
200 | u8 bfs_isdata:1; /* is a data frame/aggregate */ | ||
201 | u8 bfs_isaggr:1; /* is an aggregate */ | ||
202 | u8 bfs_isampdu:1; /* is an a-mpdu, aggregate or not */ | ||
203 | u8 bfs_ht:1; /* is an HT frame */ | ||
204 | u8 bfs_isretried:1; /* is retried */ | ||
205 | u8 bfs_isxretried:1; /* is excessive retried */ | ||
206 | u8 bfs_shpreamble:1; /* is short preamble */ | ||
207 | u8 bfs_isbar:1; /* is a BAR */ | ||
208 | u8 bfs_ispspoll:1; /* is a PS-Poll */ | ||
209 | u8 bfs_aggrburst:1; /* is a aggr burst */ | ||
210 | u8 bfs_calcairtime:1; /* requests airtime be calculated | ||
211 | when set for tx frame */ | ||
212 | int bfs_rifsburst_elem; /* RIFS burst/bar */ | ||
213 | int bfs_nrifsubframes; /* # of elements in burst */ | ||
214 | /* key type use to encrypt this frame */ | ||
215 | enum ath9k_key_type bfs_keytype; | ||
216 | }; | ||
217 | |||
218 | #define bf_nframes bf_state.bfs_nframes | ||
219 | #define bf_al bf_state.bfs_al | ||
220 | #define bf_frmlen bf_state.bfs_frmlen | ||
221 | #define bf_retries bf_state.bfs_retries | ||
222 | #define bf_seqno bf_state.bfs_seqno | ||
223 | #define bf_tidno bf_state.bfs_tidno | ||
224 | #define bf_rcs bf_state.bfs_rcs | ||
225 | #define bf_isdata bf_state.bfs_isdata | ||
226 | #define bf_isaggr bf_state.bfs_isaggr | ||
227 | #define bf_isampdu bf_state.bfs_isampdu | ||
228 | #define bf_ht bf_state.bfs_ht | ||
229 | #define bf_isretried bf_state.bfs_isretried | ||
230 | #define bf_isxretried bf_state.bfs_isxretried | ||
231 | #define bf_shpreamble bf_state.bfs_shpreamble | ||
232 | #define bf_rifsburst_elem bf_state.bfs_rifsburst_elem | ||
233 | #define bf_nrifsubframes bf_state.bfs_nrifsubframes | ||
234 | #define bf_keytype bf_state.bfs_keytype | ||
235 | #define bf_isbar bf_state.bfs_isbar | ||
236 | #define bf_ispspoll bf_state.bfs_ispspoll | ||
237 | #define bf_aggrburst bf_state.bfs_aggrburst | ||
238 | #define bf_calcairtime bf_state.bfs_calcairtime | ||
239 | |||
240 | /* | ||
241 | * Abstraction of a contiguous buffer to transmit/receive. There is only | ||
242 | * a single hw descriptor encapsulated here. | ||
243 | */ | ||
244 | |||
245 | struct ath_buf { | ||
246 | struct list_head list; | ||
247 | struct list_head *last; | ||
248 | struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or | ||
249 | an aggregate) */ | ||
250 | struct ath_buf *bf_lastfrm; /* last buf of this frame */ | ||
251 | struct ath_buf *bf_next; /* next subframe in the aggregate */ | ||
252 | struct ath_buf *bf_rifslast; /* last buf for RIFS burst */ | ||
253 | void *bf_mpdu; /* enclosing frame structure */ | ||
254 | void *bf_node; /* pointer to the node */ | ||
255 | struct ath_desc *bf_desc; /* virtual addr of desc */ | ||
256 | dma_addr_t bf_daddr; /* physical addr of desc */ | ||
257 | dma_addr_t bf_buf_addr; /* physical addr of data buffer */ | ||
258 | u32 bf_status; | ||
259 | u16 bf_flags; /* tx descriptor flags */ | ||
260 | struct ath_buf_state bf_state; /* buffer state */ | ||
261 | dma_addr_t bf_dmacontext; | ||
262 | }; | ||
263 | |||
264 | /* | ||
265 | * reset the rx buffer. | ||
266 | * any new fields added to the athbuf and require | ||
267 | * reset need to be added to this macro. | ||
268 | * currently bf_status is the only one requires that | ||
269 | * requires reset. | ||
270 | */ | ||
271 | #define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0) | ||
272 | |||
273 | /* hw processing complete, desc processed by hal */ | ||
274 | #define ATH_BUFSTATUS_DONE 0x00000001 | ||
275 | /* hw processing complete, desc hold for hw */ | ||
276 | #define ATH_BUFSTATUS_STALE 0x00000002 | ||
277 | /* Rx-only: OS is done with this packet and it's ok to queued it to hw */ | ||
278 | #define ATH_BUFSTATUS_FREE 0x00000004 | ||
279 | |||
280 | /* DMA state for tx/rx descriptors */ | ||
281 | |||
282 | struct ath_descdma { | ||
283 | const char *dd_name; | ||
284 | struct ath_desc *dd_desc; /* descriptors */ | ||
285 | dma_addr_t dd_desc_paddr; /* physical addr of dd_desc */ | ||
286 | u32 dd_desc_len; /* size of dd_desc */ | ||
287 | struct ath_buf *dd_bufptr; /* associated buffers */ | ||
288 | dma_addr_t dd_dmacontext; | ||
289 | }; | ||
290 | |||
291 | /* Abstraction of a received RX MPDU/MMPDU, or a RX fragment */ | ||
292 | |||
293 | struct ath_rx_context { | ||
294 | struct ath_buf *ctx_rxbuf; /* associated ath_buf for rx */ | ||
295 | }; | ||
296 | #define ATH_RX_CONTEXT(skb) ((struct ath_rx_context *)skb->cb) | ||
297 | |||
298 | int ath_descdma_setup(struct ath_softc *sc, | ||
299 | struct ath_descdma *dd, | ||
300 | struct list_head *head, | ||
301 | const char *name, | ||
302 | int nbuf, | ||
303 | int ndesc); | ||
304 | int ath_desc_alloc(struct ath_softc *sc); | ||
305 | void ath_desc_free(struct ath_softc *sc); | ||
306 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
307 | struct ath_descdma *dd, | ||
308 | struct list_head *head); | ||
309 | |||
310 | /******/ | ||
311 | /* RX */ | ||
312 | /******/ | ||
313 | |||
314 | #define ATH_MAX_ANTENNA 3 | ||
315 | #define ATH_RXBUF 512 | ||
316 | #define ATH_RX_TIMEOUT 40 /* 40 milliseconds */ | ||
317 | #define WME_NUM_TID 16 | ||
318 | #define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */ | ||
319 | #define IEEE80211_BAR_CTL_TID_S 2 /* tid shift */ | ||
320 | |||
321 | enum ATH_RX_TYPE { | ||
322 | ATH_RX_NON_CONSUMED = 0, | ||
323 | ATH_RX_CONSUMED | ||
324 | }; | ||
325 | |||
326 | /* per frame rx status block */ | ||
327 | struct ath_recv_status { | ||
328 | u64 tsf; /* mac tsf */ | ||
329 | int8_t rssi; /* RSSI (noise floor ajusted) */ | ||
330 | int8_t rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
331 | int8_t rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
332 | int8_t abs_rssi; /* absolute RSSI */ | ||
333 | u8 rateieee; /* data rate received (IEEE rate code) */ | ||
334 | u8 ratecode; /* phy rate code */ | ||
335 | int rateKbps; /* data rate received (Kbps) */ | ||
336 | int antenna; /* rx antenna */ | ||
337 | int flags; /* status of associated skb */ | ||
338 | #define ATH_RX_FCS_ERROR 0x01 | ||
339 | #define ATH_RX_MIC_ERROR 0x02 | ||
340 | #define ATH_RX_DECRYPT_ERROR 0x04 | ||
341 | #define ATH_RX_RSSI_VALID 0x08 | ||
342 | /* if any of ctl,extn chainrssis are valid */ | ||
343 | #define ATH_RX_CHAIN_RSSI_VALID 0x10 | ||
344 | /* if extn chain rssis are valid */ | ||
345 | #define ATH_RX_RSSI_EXTN_VALID 0x20 | ||
346 | /* set if 40Mhz, clear if 20Mhz */ | ||
347 | #define ATH_RX_40MHZ 0x40 | ||
348 | /* set if short GI, clear if full GI */ | ||
349 | #define ATH_RX_SHORT_GI 0x80 | ||
350 | }; | ||
351 | |||
352 | struct ath_rxbuf { | ||
353 | struct sk_buff *rx_wbuf; | ||
354 | unsigned long rx_time; /* system time when received */ | ||
355 | struct ath_recv_status rx_status; /* cached rx status */ | ||
356 | }; | ||
357 | |||
358 | /* Per-TID aggregate receiver state for a node */ | ||
359 | struct ath_arx_tid { | ||
360 | struct ath_node *an; | ||
361 | struct ath_rxbuf *rxbuf; /* re-ordering buffer */ | ||
362 | struct timer_list timer; | ||
363 | spinlock_t tidlock; | ||
364 | int baw_head; /* seq_next at head */ | ||
365 | int baw_tail; /* tail of block-ack window */ | ||
366 | int seq_reset; /* need to reset start sequence */ | ||
367 | int addba_exchangecomplete; | ||
368 | u16 seq_next; /* next expected sequence */ | ||
369 | u16 baw_size; /* block-ack window size */ | ||
370 | }; | ||
371 | |||
372 | /* Per-node receiver aggregate state */ | ||
373 | struct ath_arx { | ||
374 | struct ath_arx_tid tid[WME_NUM_TID]; | ||
375 | }; | ||
376 | |||
377 | int ath_startrecv(struct ath_softc *sc); | ||
378 | bool ath_stoprecv(struct ath_softc *sc); | ||
379 | void ath_flushrecv(struct ath_softc *sc); | ||
380 | u32 ath_calcrxfilter(struct ath_softc *sc); | ||
381 | void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an); | ||
382 | void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an); | ||
383 | void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an); | ||
384 | void ath_handle_rx_intr(struct ath_softc *sc); | ||
385 | int ath_rx_init(struct ath_softc *sc, int nbufs); | ||
386 | void ath_rx_cleanup(struct ath_softc *sc); | ||
387 | int ath_rx_tasklet(struct ath_softc *sc, int flush); | ||
388 | int ath_rx_input(struct ath_softc *sc, | ||
389 | struct ath_node *node, | ||
390 | int is_ampdu, | ||
391 | struct sk_buff *skb, | ||
392 | struct ath_recv_status *rx_status, | ||
393 | enum ATH_RX_TYPE *status); | ||
394 | int ath__rx_indicate(struct ath_softc *sc, | ||
395 | struct sk_buff *skb, | ||
396 | struct ath_recv_status *status, | ||
397 | u16 keyix); | ||
398 | int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb, | ||
399 | struct ath_recv_status *status); | ||
400 | |||
401 | /******/ | ||
402 | /* TX */ | ||
403 | /******/ | ||
404 | |||
405 | #define ATH_FRAG_PER_MSDU 1 | ||
406 | #define ATH_TXBUF (512/ATH_FRAG_PER_MSDU) | ||
407 | /* max number of transmit attempts (tries) */ | ||
408 | #define ATH_TXMAXTRY 13 | ||
409 | /* max number of 11n transmit attempts (tries) */ | ||
410 | #define ATH_11N_TXMAXTRY 10 | ||
411 | /* max number of tries for management and control frames */ | ||
412 | #define ATH_MGT_TXMAXTRY 4 | ||
413 | #define WME_BA_BMP_SIZE 64 | ||
414 | #define WME_MAX_BA WME_BA_BMP_SIZE | ||
415 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) | ||
416 | #define TID_TO_WME_AC(_tid) \ | ||
417 | ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ | ||
418 | (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ | ||
419 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ | ||
420 | WME_AC_VO) | ||
421 | |||
422 | |||
423 | /* Wireless Multimedia Extension Defines */ | ||
424 | #define WME_AC_BE 0 /* best effort */ | ||
425 | #define WME_AC_BK 1 /* background */ | ||
426 | #define WME_AC_VI 2 /* video */ | ||
427 | #define WME_AC_VO 3 /* voice */ | ||
428 | #define WME_NUM_AC 4 | ||
429 | |||
430 | enum ATH_SM_PWRSAV{ | ||
431 | ATH_SM_ENABLE, | ||
432 | ATH_SM_PWRSAV_STATIC, | ||
433 | ATH_SM_PWRSAV_DYNAMIC, | ||
434 | }; | ||
435 | |||
436 | /* | ||
437 | * Data transmit queue state. One of these exists for each | ||
438 | * hardware transmit queue. Packets sent to us from above | ||
439 | * are assigned to queues based on their priority. Not all | ||
440 | * devices support a complete set of hardware transmit queues. | ||
441 | * For those devices the array sc_ac2q will map multiple | ||
442 | * priorities to fewer hardware queues (typically all to one | ||
443 | * hardware queue). | ||
444 | */ | ||
445 | struct ath_txq { | ||
446 | u32 axq_qnum; /* hardware q number */ | ||
447 | u32 *axq_link; /* link ptr in last TX desc */ | ||
448 | struct list_head axq_q; /* transmit queue */ | ||
449 | spinlock_t axq_lock; | ||
450 | unsigned long axq_lockflags; /* intr state when must cli */ | ||
451 | u32 axq_depth; /* queue depth */ | ||
452 | u8 axq_aggr_depth; /* aggregates queued */ | ||
453 | u32 axq_totalqueued; /* total ever queued */ | ||
454 | |||
455 | /* count to determine if descriptor should generate int on this txq. */ | ||
456 | u32 axq_intrcnt; | ||
457 | |||
458 | bool stopped; /* Is mac80211 queue stopped ? */ | ||
459 | struct ath_buf *axq_linkbuf; /* virtual addr of last buffer*/ | ||
460 | |||
461 | /* first desc of the last descriptor that contains CTS */ | ||
462 | struct ath_desc *axq_lastdsWithCTS; | ||
463 | |||
464 | /* final desc of the gating desc that determines whether | ||
465 | lastdsWithCTS has been DMA'ed or not */ | ||
466 | struct ath_desc *axq_gatingds; | ||
467 | |||
468 | struct list_head axq_acq; | ||
469 | }; | ||
470 | |||
471 | /* per TID aggregate tx state for a destination */ | ||
472 | struct ath_atx_tid { | ||
473 | struct list_head list; /* round-robin tid entry */ | ||
474 | struct list_head buf_q; /* pending buffers */ | ||
475 | struct ath_node *an; | ||
476 | struct ath_atx_ac *ac; | ||
477 | struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; /* active tx frames */ | ||
478 | u16 seq_start; | ||
479 | u16 seq_next; | ||
480 | u16 baw_size; | ||
481 | int tidno; | ||
482 | int baw_head; /* first un-acked tx buffer */ | ||
483 | int baw_tail; /* next unused tx buffer slot */ | ||
484 | int sched; | ||
485 | int paused; | ||
486 | int cleanup_inprogress; | ||
487 | u32 addba_exchangecomplete:1; | ||
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; | ||
510 | int if_id; | ||
511 | int qnum; | ||
512 | u32 ht:1; | ||
513 | u32 ps:1; | ||
514 | u32 use_minrate:1; | ||
515 | enum ath9k_pkt_type atype; | ||
516 | enum ath9k_key_type keytype; | ||
517 | u32 flags; | ||
518 | u16 seqno; | ||
519 | u16 tidno; | ||
520 | u16 txpower; | ||
521 | u16 frmlen; | ||
522 | u32 keyix; | ||
523 | int min_rate; | ||
524 | int mcast_rate; | ||
525 | u16 nextfraglen; | ||
526 | struct ath_softc *dev; | ||
527 | dma_addr_t dmacontext; | ||
528 | }; | ||
529 | |||
530 | /* per frame tx status block */ | ||
531 | struct ath_xmit_status { | ||
532 | int retries; /* number of retries to successufully | ||
533 | transmit this frame */ | ||
534 | int flags; /* status of transmit */ | ||
535 | #define ATH_TX_ERROR 0x01 | ||
536 | #define ATH_TX_XRETRY 0x02 | ||
537 | #define ATH_TX_BAR 0x04 | ||
538 | }; | ||
539 | |||
540 | struct ath_tx_stat { | ||
541 | int rssi; /* RSSI (noise floor ajusted) */ | ||
542 | int rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
543 | int rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
544 | int rateieee; /* data rate xmitted (IEEE rate code) */ | ||
545 | int rateKbps; /* data rate xmitted (Kbps) */ | ||
546 | int ratecode; /* phy rate code */ | ||
547 | int flags; /* validity flags */ | ||
548 | /* if any of ctl,extn chain rssis are valid */ | ||
549 | #define ATH_TX_CHAIN_RSSI_VALID 0x01 | ||
550 | /* if extn chain rssis are valid */ | ||
551 | #define ATH_TX_RSSI_EXTN_VALID 0x02 | ||
552 | u32 airtime; /* time on air per final tx rate */ | ||
553 | }; | ||
554 | |||
555 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); | ||
556 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); | ||
557 | int ath_tx_setup(struct ath_softc *sc, int haltype); | ||
558 | void ath_draintxq(struct ath_softc *sc, bool retry_tx); | ||
559 | void ath_tx_draintxq(struct ath_softc *sc, | ||
560 | struct ath_txq *txq, bool retry_tx); | ||
561 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); | ||
562 | void ath_tx_node_cleanup(struct ath_softc *sc, | ||
563 | struct ath_node *an, bool bh_flag); | ||
564 | void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an); | ||
565 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); | ||
566 | int ath_tx_init(struct ath_softc *sc, int nbufs); | ||
567 | int ath_tx_cleanup(struct ath_softc *sc); | ||
568 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); | ||
569 | int ath_txq_update(struct ath_softc *sc, int qnum, | ||
570 | struct ath9k_tx_queue_info *q); | ||
571 | int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb); | ||
572 | void ath_tx_tasklet(struct ath_softc *sc); | ||
573 | u32 ath_txq_depth(struct ath_softc *sc, int qnum); | ||
574 | u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum); | ||
575 | void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth); | ||
576 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | ||
577 | struct ath_xmit_status *tx_status, struct ath_node *an); | ||
578 | |||
579 | /**********************/ | ||
580 | /* Node / Aggregation */ | ||
581 | /**********************/ | ||
582 | |||
583 | /* indicates the node is clened up */ | ||
584 | #define ATH_NODE_CLEAN 0x1 | ||
585 | /* indicates the node is 80211 power save */ | ||
586 | #define ATH_NODE_PWRSAVE 0x2 | ||
587 | |||
588 | #define ADDBA_TIMEOUT 200 /* 200 milliseconds */ | ||
589 | #define ADDBA_EXCHANGE_ATTEMPTS 10 | ||
590 | #define ATH_AGGR_DELIM_SZ 4 /* delimiter size */ | ||
591 | #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ | ||
592 | /* number of delimiters for encryption padding */ | ||
593 | #define ATH_AGGR_ENCRYPTDELIM 10 | ||
594 | /* minimum h/w qdepth to be sustained to maximize aggregation */ | ||
595 | #define ATH_AGGR_MIN_QDEPTH 2 | ||
596 | #define ATH_AMPDU_SUBFRAME_DEFAULT 32 | ||
597 | #define IEEE80211_SEQ_SEQ_SHIFT 4 | ||
598 | #define IEEE80211_SEQ_MAX 4096 | ||
599 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | ||
600 | |||
601 | /* return whether a bit at index _n in bitmap _bm is set | ||
602 | * _sz is the size of the bitmap */ | ||
603 | #define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \ | ||
604 | ((_bm)[(_n) >> 5] & (1 << ((_n) & 31)))) | ||
605 | |||
606 | /* return block-ack bitmap index given sequence and starting sequence */ | ||
607 | #define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) | ||
608 | |||
609 | /* returns delimiter padding required given the packet length */ | ||
610 | #define ATH_AGGR_GET_NDELIM(_len) \ | ||
611 | (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ | ||
612 | (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) | ||
613 | |||
614 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ | ||
615 | ((((_seqno) - (_start)) & 4095) < (_bawsz)) | ||
616 | |||
617 | #define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum) | ||
618 | #define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low) | ||
619 | #define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) | ||
620 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->an_aggr.tx.tid[(_tidno)]) | ||
621 | |||
622 | enum ATH_AGGR_STATUS { | ||
623 | ATH_AGGR_DONE, | ||
624 | ATH_AGGR_BAW_CLOSED, | ||
625 | ATH_AGGR_LIMITED, | ||
626 | ATH_AGGR_SHORTPKT, | ||
627 | ATH_AGGR_8K_LIMITED, | ||
628 | }; | ||
629 | |||
630 | enum ATH_AGGR_CHECK { | ||
631 | AGGR_NOT_REQUIRED, | ||
632 | AGGR_REQUIRED, | ||
633 | AGGR_CLEANUP_PROGRESS, | ||
634 | AGGR_EXCHANGE_PROGRESS, | ||
635 | AGGR_EXCHANGE_DONE | ||
636 | }; | ||
637 | |||
638 | struct aggr_rifs_param { | ||
639 | int param_max_frames; | ||
640 | int param_max_len; | ||
641 | int param_rl; | ||
642 | int param_al; | ||
643 | struct ath_rc_series *param_rcs; | ||
644 | }; | ||
645 | |||
646 | /* Per-node aggregation state */ | ||
647 | struct ath_node_aggr { | ||
648 | struct ath_atx tx; /* node transmit state */ | ||
649 | struct ath_arx rx; /* node receive state */ | ||
650 | }; | ||
651 | |||
652 | /* driver-specific node state */ | ||
653 | struct ath_node { | ||
654 | struct list_head list; | ||
655 | struct ath_softc *an_sc; | ||
656 | atomic_t an_refcnt; | ||
657 | struct ath_chainmask_sel an_chainmask_sel; | ||
658 | struct ath_node_aggr an_aggr; | ||
659 | u8 an_smmode; /* SM Power save mode */ | ||
660 | u8 an_flags; | ||
661 | u8 an_addr[ETH_ALEN]; | ||
662 | }; | ||
663 | |||
664 | void ath_tx_resume_tid(struct ath_softc *sc, | ||
665 | struct ath_atx_tid *tid); | ||
666 | enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc, | ||
667 | struct ath_node *an, u8 tidno); | ||
668 | void ath_tx_aggr_teardown(struct ath_softc *sc, | ||
669 | struct ath_node *an, u8 tidno); | ||
670 | void ath_rx_aggr_teardown(struct ath_softc *sc, | ||
671 | struct ath_node *an, u8 tidno); | ||
672 | int ath_rx_aggr_start(struct ath_softc *sc, | ||
673 | const u8 *addr, | ||
674 | u16 tid, | ||
675 | u16 *ssn); | ||
676 | int ath_rx_aggr_stop(struct ath_softc *sc, | ||
677 | const u8 *addr, | ||
678 | u16 tid); | ||
679 | int ath_tx_aggr_start(struct ath_softc *sc, | ||
680 | const u8 *addr, | ||
681 | u16 tid, | ||
682 | u16 *ssn); | ||
683 | int ath_tx_aggr_stop(struct ath_softc *sc, | ||
684 | const u8 *addr, | ||
685 | u16 tid); | ||
686 | void ath_newassoc(struct ath_softc *sc, | ||
687 | struct ath_node *node, int isnew, int isuapsd); | ||
688 | struct ath_node *ath_node_attach(struct ath_softc *sc, | ||
689 | u8 addr[ETH_ALEN], int if_id); | ||
690 | void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag); | ||
691 | struct ath_node *ath_node_get(struct ath_softc *sc, u8 addr[ETH_ALEN]); | ||
692 | void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag); | ||
693 | struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr); | ||
694 | |||
695 | /*******************/ | ||
696 | /* Beacon Handling */ | ||
697 | /*******************/ | ||
698 | |||
699 | /* | ||
700 | * Regardless of the number of beacons we stagger, (i.e. regardless of the | ||
701 | * number of BSSIDs) if a given beacon does not go out even after waiting this | ||
702 | * number of beacon intervals, the game's up. | ||
703 | */ | ||
704 | #define BSTUCK_THRESH (9 * ATH_BCBUF) | ||
705 | #define ATH_BCBUF 4 /* number of beacon buffers */ | ||
706 | #define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */ | ||
707 | #define ATH_DEFAULT_BMISS_LIMIT 10 | ||
708 | #define ATH_BEACON_AIFS_DEFAULT 0 /* Default aifs for ap beacon q */ | ||
709 | #define ATH_BEACON_CWMIN_DEFAULT 0 /* Default cwmin for ap beacon q */ | ||
710 | #define ATH_BEACON_CWMAX_DEFAULT 0 /* Default cwmax for ap beacon q */ | ||
711 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | ||
712 | |||
713 | /* beacon configuration */ | ||
714 | struct ath_beacon_config { | ||
715 | u16 beacon_interval; | ||
716 | u16 listen_interval; | ||
717 | u16 dtim_period; | ||
718 | u16 bmiss_timeout; | ||
719 | u8 dtim_count; | ||
720 | u8 tim_offset; | ||
721 | union { | ||
722 | u64 last_tsf; | ||
723 | u8 last_tstamp[8]; | ||
724 | } u; /* last received beacon/probe response timestamp of this BSS. */ | ||
725 | }; | ||
726 | |||
727 | /* offsets in a beacon frame for | ||
728 | * quick acess of beacon content by low-level driver */ | ||
729 | struct ath_beacon_offset { | ||
730 | u8 *bo_tim; /* start of atim/dtim */ | ||
731 | }; | ||
732 | |||
733 | void ath9k_beacon_tasklet(unsigned long data); | ||
734 | void ath_beacon_config(struct ath_softc *sc, int if_id); | ||
735 | int ath_beaconq_setup(struct ath_hal *ah); | ||
736 | int ath_beacon_alloc(struct ath_softc *sc, int if_id); | ||
737 | void ath_bstuck_process(struct ath_softc *sc); | ||
738 | void ath_beacon_tasklet(struct ath_softc *sc, int *needmark); | ||
739 | void ath_beacon_free(struct ath_softc *sc); | ||
740 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp); | ||
741 | void ath_beacon_sync(struct ath_softc *sc, int if_id); | ||
742 | void ath_update_beacon_info(struct ath_softc *sc, int avgbrssi); | ||
743 | void ath_get_beaconconfig(struct ath_softc *sc, | ||
744 | int if_id, | ||
745 | struct ath_beacon_config *conf); | ||
746 | int ath_update_beacon(struct ath_softc *sc, | ||
747 | int if_id, | ||
748 | struct ath_beacon_offset *bo, | ||
749 | struct sk_buff *skb, | ||
750 | int mcast); | ||
751 | /********/ | ||
752 | /* VAPs */ | ||
753 | /********/ | ||
754 | |||
755 | /* | ||
756 | * Define the scheme that we select MAC address for multiple | ||
757 | * BSS on the same radio. The very first VAP will just use the MAC | ||
758 | * address from the EEPROM. For the next 3 VAPs, we set the | ||
759 | * U/L bit (bit 1) in MAC address, and use the next two bits as the | ||
760 | * index of the VAP. | ||
761 | */ | ||
762 | |||
763 | #define ATH_SET_VAP_BSSID_MASK(bssid_mask) \ | ||
764 | ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02)) | ||
765 | |||
766 | /* VAP configuration (from protocol layer) */ | ||
767 | struct ath_vap_config { | ||
768 | u32 av_fixed_rateset; | ||
769 | u32 av_fixed_retryset; | ||
770 | }; | ||
771 | |||
772 | /* driver-specific vap state */ | ||
773 | struct ath_vap { | ||
774 | struct ieee80211_vif *av_if_data; | ||
775 | enum ath9k_opmode av_opmode; /* VAP operational mode */ | ||
776 | struct ath_buf *av_bcbuf; /* beacon buffer */ | ||
777 | struct ath_beacon_offset av_boff; /* dynamic update state */ | ||
778 | struct ath_tx_control av_btxctl; /* txctl information for beacon */ | ||
779 | int av_bslot; /* beacon slot index */ | ||
780 | struct ath_txq av_mcastq; /* multicast transmit queue */ | ||
781 | struct ath_vap_config av_config;/* vap configuration parameters*/ | ||
782 | struct ath_rate_node *rc_node; | ||
783 | }; | ||
784 | |||
785 | int ath_vap_attach(struct ath_softc *sc, | ||
786 | int if_id, | ||
787 | struct ieee80211_vif *if_data, | ||
788 | enum ath9k_opmode opmode); | ||
789 | int ath_vap_detach(struct ath_softc *sc, int if_id); | ||
790 | int ath_vap_config(struct ath_softc *sc, | ||
791 | int if_id, struct ath_vap_config *if_config); | ||
792 | int ath_vap_listen(struct ath_softc *sc, int if_id); | ||
793 | |||
794 | /*********************/ | ||
795 | /* Antenna diversity */ | ||
796 | /*********************/ | ||
797 | |||
798 | #define ATH_ANT_DIV_MAX_CFG 2 | ||
799 | #define ATH_ANT_DIV_MIN_IDLE_US 1000000 /* us */ | ||
800 | #define ATH_ANT_DIV_MIN_SCAN_US 50000 /* us */ | ||
801 | |||
802 | enum ATH_ANT_DIV_STATE{ | ||
803 | ATH_ANT_DIV_IDLE, | ||
804 | ATH_ANT_DIV_SCAN, /* evaluating antenna */ | ||
805 | }; | ||
806 | |||
807 | struct ath_antdiv { | ||
808 | struct ath_softc *antdiv_sc; | ||
809 | u8 antdiv_start; | ||
810 | enum ATH_ANT_DIV_STATE antdiv_state; | ||
811 | u8 antdiv_num_antcfg; | ||
812 | u8 antdiv_curcfg; | ||
813 | u8 antdiv_bestcfg; | ||
814 | int32_t antdivf_rssitrig; | ||
815 | int32_t antdiv_lastbrssi[ATH_ANT_DIV_MAX_CFG]; | ||
816 | u64 antdiv_lastbtsf[ATH_ANT_DIV_MAX_CFG]; | ||
817 | u64 antdiv_laststatetsf; | ||
818 | u8 antdiv_bssid[ETH_ALEN]; | ||
819 | }; | ||
820 | |||
821 | void ath_slow_ant_div_init(struct ath_antdiv *antdiv, | ||
822 | struct ath_softc *sc, int32_t rssitrig); | ||
823 | void ath_slow_ant_div_start(struct ath_antdiv *antdiv, | ||
824 | u8 num_antcfg, | ||
825 | const u8 *bssid); | ||
826 | void ath_slow_ant_div_stop(struct ath_antdiv *antdiv); | ||
827 | void ath_slow_ant_div(struct ath_antdiv *antdiv, | ||
828 | struct ieee80211_hdr *wh, | ||
829 | struct ath_rx_status *rx_stats); | ||
830 | void ath_setdefantenna(void *sc, u32 antenna); | ||
831 | |||
832 | /********************/ | ||
833 | /* Main driver core */ | ||
834 | /********************/ | ||
835 | |||
836 | /* | ||
837 | * Default cache line size, in bytes. | ||
838 | * Used when PCI device not fully initialized by bootrom/BIOS | ||
839 | */ | ||
840 | #define DEFAULT_CACHELINE 32 | ||
841 | #define ATH_DEFAULT_NOISE_FLOOR -95 | ||
842 | #define ATH_REGCLASSIDS_MAX 10 | ||
843 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | ||
844 | #define ATH_PREAMBLE_SHORT (1<<0) | ||
845 | #define ATH_PROTECT_ENABLE (1<<1) | ||
846 | #define ATH_MAX_SW_RETRIES 10 | ||
847 | /* Num farmes difference in tx to flip default recv */ | ||
848 | #define ATH_ANTENNA_DIFF 2 | ||
849 | #define ATH_CHAN_MAX 255 | ||
850 | #define IEEE80211_WEP_NKID 4 /* number of key ids */ | ||
851 | #define IEEE80211_RATE_VAL 0x7f | ||
852 | /* | ||
853 | * The key cache is used for h/w cipher state and also for | ||
854 | * tracking station state such as the current tx antenna. | ||
855 | * We also setup a mapping table between key cache slot indices | ||
856 | * and station state to short-circuit node lookups on rx. | ||
857 | * Different parts have different size key caches. We handle | ||
858 | * up to ATH_KEYMAX entries (could dynamically allocate state). | ||
859 | */ | ||
860 | #define ATH_KEYMAX 128 /* max key cache size we handle */ | ||
861 | |||
862 | #define RESET_RETRY_TXQ 0x00000001 | ||
863 | #define ATH_IF_ID_ANY 0xff | ||
864 | |||
865 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | ||
866 | |||
867 | #define RSSI_LPF_THRESHOLD -20 | ||
868 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ | ||
869 | #define ATH_RATE_DUMMY_MARKER 0 | ||
870 | #define ATH_RSSI_LPF_LEN 10 | ||
871 | #define ATH_RSSI_DUMMY_MARKER 0x127 | ||
872 | |||
873 | #define ATH_EP_MUL(x, mul) ((x) * (mul)) | ||
874 | #define ATH_EP_RND(x, mul) \ | ||
875 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | ||
876 | #define ATH_RSSI_OUT(x) \ | ||
877 | (((x) != ATH_RSSI_DUMMY_MARKER) ? \ | ||
878 | (ATH_EP_RND((x), ATH_RSSI_EP_MULTIPLIER)) : ATH_RSSI_DUMMY_MARKER) | ||
879 | #define ATH_RSSI_IN(x) \ | ||
880 | (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) | ||
881 | #define ATH_LPF_RSSI(x, y, len) \ | ||
882 | ((x != ATH_RSSI_DUMMY_MARKER) ? \ | ||
883 | (((x) * ((len) - 1) + (y)) / (len)) : (y)) | ||
884 | #define ATH_RSSI_LPF(x, y) do { \ | ||
885 | if ((y) >= RSSI_LPF_THRESHOLD) \ | ||
886 | x = ATH_LPF_RSSI((x), \ | ||
887 | ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ | ||
888 | } while (0) | ||
889 | |||
890 | |||
891 | enum PROT_MODE { | ||
892 | PROT_M_NONE = 0, | ||
893 | PROT_M_RTSCTS, | ||
894 | PROT_M_CTSONLY | ||
895 | }; | ||
896 | |||
897 | enum RATE_TYPE { | ||
898 | NORMAL_RATE = 0, | ||
899 | HALF_RATE, | ||
900 | QUARTER_RATE | ||
901 | }; | ||
902 | |||
903 | struct ath_ht_info { | ||
904 | enum ath9k_ht_macmode tx_chan_width; | ||
905 | u16 maxampdu; | ||
906 | u8 mpdudensity; | ||
907 | u8 ext_chan_offset; | ||
908 | }; | ||
909 | |||
910 | struct ath_softc { | ||
911 | struct ieee80211_hw *hw; | ||
912 | struct pci_dev *pdev; | ||
913 | void __iomem *mem; | ||
914 | struct tasklet_struct intr_tq; | ||
915 | struct tasklet_struct bcon_tasklet; | ||
916 | struct ath_config sc_config; /* load-time parameters */ | ||
917 | int sc_debug; | ||
918 | struct ath_hal *sc_ah; | ||
919 | struct ath_rate_softc *sc_rc; /* tx rate control support */ | ||
920 | u32 sc_intrstatus; | ||
921 | enum ath9k_opmode sc_opmode; /* current operating mode */ | ||
922 | |||
923 | u8 sc_invalid; /* being detached */ | ||
924 | u8 sc_beacons; /* beacons running */ | ||
925 | u8 sc_scanning; /* scanning active */ | ||
926 | u8 sc_txaggr; /* enable 11n tx aggregation */ | ||
927 | u8 sc_rxaggr; /* enable 11n rx aggregation */ | ||
928 | u8 sc_update_chainmask; /* change chain mask */ | ||
929 | u8 sc_full_reset; /* force full reset */ | ||
930 | enum wireless_mode sc_curmode; /* current phy mode */ | ||
931 | u16 sc_curtxpow; | ||
932 | u16 sc_curaid; | ||
933 | u8 sc_curbssid[ETH_ALEN]; | ||
934 | u8 sc_myaddr[ETH_ALEN]; | ||
935 | enum PROT_MODE sc_protmode; | ||
936 | u8 sc_mcastantenna; | ||
937 | u8 sc_txantenna; /* data tx antenna (fixed or auto) */ | ||
938 | u8 sc_nbcnvaps; /* # of vaps sending beacons */ | ||
939 | u16 sc_nvaps; /* # of active virtual ap's */ | ||
940 | struct ath_vap *sc_vaps[ATH_BCBUF]; | ||
941 | enum ath9k_int sc_imask; | ||
942 | u8 sc_bssidmask[ETH_ALEN]; | ||
943 | u8 sc_defant; /* current default antenna */ | ||
944 | u8 sc_rxotherant; /* rx's on non-default antenna */ | ||
945 | u16 sc_cachelsz; | ||
946 | int sc_slotupdate; /* slot to next advance fsm */ | ||
947 | int sc_slottime; | ||
948 | u8 sc_noreset; | ||
949 | int sc_bslot[ATH_BCBUF]; | ||
950 | struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ | ||
951 | struct list_head node_list; | ||
952 | struct ath_ht_info sc_ht_info; | ||
953 | int16_t sc_noise_floor; /* signal noise floor in dBm */ | ||
954 | enum ath9k_ht_extprotspacing sc_ht_extprotspacing; | ||
955 | u8 sc_tx_chainmask; | ||
956 | u8 sc_rx_chainmask; | ||
957 | u8 sc_rxchaindetect_ref; | ||
958 | u8 sc_rxchaindetect_thresh5GHz; | ||
959 | u8 sc_rxchaindetect_thresh2GHz; | ||
960 | u8 sc_rxchaindetect_delta5GHz; | ||
961 | u8 sc_rxchaindetect_delta2GHz; | ||
962 | u32 sc_rtsaggrlimit; /* Chipset specific aggr limit */ | ||
963 | u32 sc_flags; | ||
964 | #ifdef CONFIG_SLOW_ANT_DIV | ||
965 | struct ath_antdiv sc_antdiv; | ||
966 | #endif | ||
967 | enum { | ||
968 | OK, /* no change needed */ | ||
969 | UPDATE, /* update pending */ | ||
970 | COMMIT /* beacon sent, commit change */ | ||
971 | } sc_updateslot; /* slot time update fsm */ | ||
972 | |||
973 | /* Crypto */ | ||
974 | u32 sc_keymax; /* size of key cache */ | ||
975 | DECLARE_BITMAP(sc_keymap, ATH_KEYMAX); /* key use bit map */ | ||
976 | u8 sc_splitmic; /* split TKIP MIC keys */ | ||
977 | int sc_keytype; | ||
978 | |||
979 | /* RX */ | ||
980 | struct list_head sc_rxbuf; | ||
981 | struct ath_descdma sc_rxdma; | ||
982 | int sc_rxbufsize; /* rx size based on mtu */ | ||
983 | u32 *sc_rxlink; /* link ptr in last RX desc */ | ||
984 | u32 sc_rxflush; /* rx flush in progress */ | ||
985 | u64 sc_lastrx; /* tsf of last rx'd frame */ | ||
986 | |||
987 | /* TX */ | ||
988 | struct list_head sc_txbuf; | ||
989 | struct ath_txq sc_txq[ATH9K_NUM_TX_QUEUES]; | ||
990 | struct ath_descdma sc_txdma; | ||
991 | u32 sc_txqsetup; | ||
992 | u32 sc_txintrperiod; /* tx interrupt batching */ | ||
993 | int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */ | ||
994 | u32 sc_ant_tx[8]; /* recent tx frames/antenna */ | ||
995 | |||
996 | /* Beacon */ | ||
997 | struct ath9k_tx_queue_info sc_beacon_qi; | ||
998 | struct ath_descdma sc_bdma; | ||
999 | struct ath_txq *sc_cabq; | ||
1000 | struct list_head sc_bbuf; | ||
1001 | u32 sc_bhalq; | ||
1002 | u32 sc_bmisscount; | ||
1003 | u32 ast_be_xmit; /* beacons transmitted */ | ||
1004 | |||
1005 | /* Rate */ | ||
1006 | struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; | ||
1007 | const struct ath9k_rate_table *sc_currates; | ||
1008 | u8 sc_rixmap[256]; /* IEEE to h/w rate table ix */ | ||
1009 | u8 sc_protrix; /* protection rate index */ | ||
1010 | struct { | ||
1011 | u32 rateKbps; /* transfer rate in kbs */ | ||
1012 | u8 ieeerate; /* IEEE rate */ | ||
1013 | } sc_hwmap[256]; /* h/w rate ix mappings */ | ||
1014 | |||
1015 | /* Channel, Band */ | ||
1016 | struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX]; | ||
1017 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | ||
1018 | struct ath9k_channel sc_curchan; | ||
1019 | |||
1020 | /* Locks */ | ||
1021 | spinlock_t sc_rxflushlock; | ||
1022 | spinlock_t sc_rxbuflock; | ||
1023 | spinlock_t sc_txbuflock; | ||
1024 | spinlock_t sc_resetlock; | ||
1025 | spinlock_t node_lock; | ||
1026 | }; | ||
1027 | |||
1028 | int ath_init(u16 devid, struct ath_softc *sc); | ||
1029 | void ath_deinit(struct ath_softc *sc); | ||
1030 | int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan); | ||
1031 | int ath_suspend(struct ath_softc *sc); | ||
1032 | irqreturn_t ath_isr(int irq, void *dev); | ||
1033 | int ath_reset(struct ath_softc *sc); | ||
1034 | void ath_scan_start(struct ath_softc *sc); | ||
1035 | void ath_scan_end(struct ath_softc *sc); | ||
1036 | int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan); | ||
1037 | void ath_setup_rate(struct ath_softc *sc, | ||
1038 | enum wireless_mode wMode, | ||
1039 | enum RATE_TYPE type, | ||
1040 | const struct ath9k_rate_table *rt); | ||
1041 | |||
1042 | /*********************/ | ||
1043 | /* Utility Functions */ | ||
1044 | /*********************/ | ||
1045 | |||
1046 | void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot); | ||
1047 | int ath_keyset(struct ath_softc *sc, | ||
1048 | u16 keyix, | ||
1049 | struct ath9k_keyval *hk, | ||
1050 | const u8 mac[ETH_ALEN]); | ||
1051 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); | ||
1052 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); | ||
1053 | void ath_setslottime(struct ath_softc *sc); | ||
1054 | void ath_update_txpow(struct ath_softc *sc); | ||
1055 | int ath_cabq_update(struct ath_softc *); | ||
1056 | void ath_get_currentCountry(struct ath_softc *sc, | ||
1057 | struct ath9k_country_entry *ctry); | ||
1058 | u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp); | ||
1059 | void ath_internal_reset(struct ath_softc *sc); | ||
1060 | u32 ath_chan2flags(struct ieee80211_channel *chan, struct ath_softc *sc); | ||
1061 | dma_addr_t ath_skb_map_single(struct ath_softc *sc, | ||
1062 | struct sk_buff *skb, | ||
1063 | int direction, | ||
1064 | dma_addr_t *pa); | ||
1065 | void ath_skb_unmap_single(struct ath_softc *sc, | ||
1066 | struct sk_buff *skb, | ||
1067 | int direction, | ||
1068 | dma_addr_t *pa); | ||
1069 | void ath_mcast_merge(struct ath_softc *sc, u32 mfilt[2]); | ||
1070 | enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc); | ||
1071 | |||
1072 | #endif /* CORE_H */ | ||
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c new file mode 100644 index 000000000000..bde162f128ab --- /dev/null +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -0,0 +1,8571 @@ | |||
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 ATH9K_MODE_11A; | ||
229 | if (IS_CHAN_G(chan)) | ||
230 | return ATH9K_MODE_11G; | ||
231 | return ATH9K_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.dma_beacon_response_time = 2; | ||
339 | ah->ah_config.sw_beacon_response_time = 10; | ||
340 | ah->ah_config.additional_swba_backoff = 0; | ||
341 | ah->ah_config.ack_6mb = 0x0; | ||
342 | ah->ah_config.cwm_ignore_extcca = 0; | ||
343 | ah->ah_config.pcie_powersave_enable = 0; | ||
344 | ah->ah_config.pcie_l1skp_enable = 0; | ||
345 | ah->ah_config.pcie_clock_req = 0; | ||
346 | ah->ah_config.pcie_power_reset = 0x100; | ||
347 | ah->ah_config.pcie_restore = 0; | ||
348 | ah->ah_config.pcie_waen = 0; | ||
349 | ah->ah_config.analog_shiftreg = 1; | ||
350 | ah->ah_config.ht_enable = 1; | ||
351 | ah->ah_config.ofdm_trig_low = 200; | ||
352 | ah->ah_config.ofdm_trig_high = 500; | ||
353 | ah->ah_config.cck_trig_high = 200; | ||
354 | ah->ah_config.cck_trig_low = 100; | ||
355 | ah->ah_config.enable_ani = 0; | ||
356 | ah->ah_config.noise_immunity_level = 4; | ||
357 | ah->ah_config.ofdm_weaksignal_det = 1; | ||
358 | ah->ah_config.cck_weaksignal_thr = 0; | ||
359 | ah->ah_config.spur_immunity_level = 2; | ||
360 | ah->ah_config.firstep_level = 0; | ||
361 | ah->ah_config.rssi_thr_high = 40; | ||
362 | ah->ah_config.rssi_thr_low = 7; | ||
363 | ah->ah_config.diversity_control = 0; | ||
364 | ah->ah_config.antenna_switch_swap = 0; | ||
365 | |||
366 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | ||
367 | ah->ah_config.spurchans[i][0] = AR_NO_SPUR; | ||
368 | ah->ah_config.spurchans[i][1] = AR_NO_SPUR; | ||
369 | } | ||
370 | |||
371 | ah->ah_config.intr_mitigation = 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.analog_shiftreg) | ||
462 | udelay(100); | ||
463 | |||
464 | return; | ||
465 | } | ||
466 | |||
467 | static u8 ath9k_hw_get_num_ant_config(struct ath_hal_5416 *ahp, | ||
468 | enum ieee80211_band freq_band) | ||
469 | { | ||
470 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; | ||
471 | struct modal_eep_header *pModal = | ||
472 | &(eep->modalHeader[IEEE80211_BAND_5GHZ == 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 ath9k_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 ATH9K_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 ATH9K_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 ATH9K_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 ATH9K_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.cwm_ignore_extcca) | ||
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.diversity_control; | ||
1218 | ahp->ah_antennaSwitchSwap = | ||
1219 | ah->ah_config.antenna_switch_swap; | ||
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.spurchans[i][is2GHz]); | ||
1375 | |||
1376 | switch (ah->ah_config.spurmode) { | ||
1377 | case SPUR_DISABLE: | ||
1378 | break; | ||
1379 | case SPUR_ENABLE_IOCTL: | ||
1380 | spur_val = ah->ah_config.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.enable_ani) | ||
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 == ATH9K_MODE_11G || mode == ATH9K_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 == ATH9K_MODE_11G || mode == ATH9K_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.ofdm_trig_high; | ||
2508 | ahp->ah_curani->ofdmTrigLow = | ||
2509 | ah->ah_config.ofdm_trig_low; | ||
2510 | ahp->ah_curani->cckTrigHigh = | ||
2511 | ah->ah_config.cck_trig_high; | ||
2512 | ahp->ah_curani->cckTrigLow = | ||
2513 | ah->ah_config.cck_trig_low; | ||
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.num_gpio_pins) | ||
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 ath9k_hw_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 | eeval = ath9k_hw_get_eeprom(ahp, EEP_OP_MODE); | ||
2974 | bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX); | ||
2975 | |||
2976 | if (eeval & AR5416_OPFLAGS_11A) { | ||
2977 | set_bit(ATH9K_MODE_11A, pCap->wireless_modes); | ||
2978 | if (ah->ah_config.ht_enable) { | ||
2979 | if (!(eeval & AR5416_OPFLAGS_N_5G_HT20)) | ||
2980 | set_bit(ATH9K_MODE_11NA_HT20, | ||
2981 | pCap->wireless_modes); | ||
2982 | if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) { | ||
2983 | set_bit(ATH9K_MODE_11NA_HT40PLUS, | ||
2984 | pCap->wireless_modes); | ||
2985 | set_bit(ATH9K_MODE_11NA_HT40MINUS, | ||
2986 | pCap->wireless_modes); | ||
2987 | } | ||
2988 | } | ||
2989 | } | ||
2990 | |||
2991 | if (eeval & AR5416_OPFLAGS_11G) { | ||
2992 | set_bit(ATH9K_MODE_11B, pCap->wireless_modes); | ||
2993 | set_bit(ATH9K_MODE_11G, pCap->wireless_modes); | ||
2994 | if (ah->ah_config.ht_enable) { | ||
2995 | if (!(eeval & AR5416_OPFLAGS_N_2G_HT20)) | ||
2996 | set_bit(ATH9K_MODE_11NG_HT20, | ||
2997 | pCap->wireless_modes); | ||
2998 | if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) { | ||
2999 | set_bit(ATH9K_MODE_11NG_HT40PLUS, | ||
3000 | pCap->wireless_modes); | ||
3001 | set_bit(ATH9K_MODE_11NG_HT40MINUS, | ||
3002 | pCap->wireless_modes); | ||
3003 | } | ||
3004 | } | ||
3005 | } | ||
3006 | |||
3007 | pCap->tx_chainmask = ath9k_hw_get_eeprom(ahp, EEP_TX_MASK); | ||
3008 | if ((ah->ah_isPciExpress) | ||
3009 | || (eeval & AR5416_OPFLAGS_11A)) { | ||
3010 | pCap->rx_chainmask = | ||
3011 | ath9k_hw_get_eeprom(ahp, EEP_RX_MASK); | ||
3012 | } else { | ||
3013 | pCap->rx_chainmask = | ||
3014 | (ath9k_hw_gpio_get(ah, 0)) ? 0x5 : 0x7; | ||
3015 | } | ||
3016 | |||
3017 | if (!(AR_SREV_9280(ah) && (ah->ah_macRev == 0))) | ||
3018 | ahp->ah_miscMode |= AR_PCU_MIC_NEW_LOC_ENA; | ||
3019 | |||
3020 | pCap->low_2ghz_chan = 2312; | ||
3021 | pCap->high_2ghz_chan = 2732; | ||
3022 | |||
3023 | pCap->low_5ghz_chan = 4920; | ||
3024 | pCap->high_5ghz_chan = 6100; | ||
3025 | |||
3026 | pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP; | ||
3027 | pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP; | ||
3028 | pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM; | ||
3029 | |||
3030 | pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP; | ||
3031 | pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; | ||
3032 | pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; | ||
3033 | |||
3034 | pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD; | ||
3035 | |||
3036 | if (ah->ah_config.ht_enable) | ||
3037 | pCap->hw_caps |= ATH9K_HW_CAP_HT; | ||
3038 | else | ||
3039 | pCap->hw_caps &= ~ATH9K_HW_CAP_HT; | ||
3040 | |||
3041 | pCap->hw_caps |= ATH9K_HW_CAP_GTT; | ||
3042 | pCap->hw_caps |= ATH9K_HW_CAP_VEOL; | ||
3043 | pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK; | ||
3044 | pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH; | ||
3045 | |||
3046 | if (capField & AR_EEPROM_EEPCAP_MAXQCU) | ||
3047 | pCap->total_queues = | ||
3048 | MS(capField, AR_EEPROM_EEPCAP_MAXQCU); | ||
3049 | else | ||
3050 | pCap->total_queues = ATH9K_NUM_TX_QUEUES; | ||
3051 | |||
3052 | if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) | ||
3053 | pCap->keycache_size = | ||
3054 | 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); | ||
3055 | else | ||
3056 | pCap->keycache_size = AR_KEYTABLE_SIZE; | ||
3057 | |||
3058 | pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; | ||
3059 | pCap->num_mr_retries = 4; | ||
3060 | pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; | ||
3061 | |||
3062 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
3063 | pCap->num_gpio_pins = AR928X_NUM_GPIO; | ||
3064 | else | ||
3065 | pCap->num_gpio_pins = AR_NUM_GPIO; | ||
3066 | |||
3067 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3068 | pCap->hw_caps |= ATH9K_HW_CAP_WOW; | ||
3069 | pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT; | ||
3070 | } else { | ||
3071 | pCap->hw_caps &= ~ATH9K_HW_CAP_WOW; | ||
3072 | pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT; | ||
3073 | } | ||
3074 | |||
3075 | if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { | ||
3076 | pCap->hw_caps |= ATH9K_HW_CAP_CST; | ||
3077 | pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; | ||
3078 | } else { | ||
3079 | pCap->rts_aggr_limit = (8 * 1024); | ||
3080 | } | ||
3081 | |||
3082 | pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; | ||
3083 | |||
3084 | ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT); | ||
3085 | if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) { | ||
3086 | ahp->ah_gpioSelect = | ||
3087 | MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL); | ||
3088 | ahp->ah_polarity = | ||
3089 | MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY); | ||
3090 | |||
3091 | ath9k_hw_setcapability(ah, ATH9K_CAP_RFSILENT, 1, true, | ||
3092 | NULL); | ||
3093 | pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; | ||
3094 | } | ||
3095 | |||
3096 | if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) || | ||
3097 | (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) || | ||
3098 | (ah->ah_macVersion == AR_SREV_VERSION_9160) || | ||
3099 | (ah->ah_macVersion == AR_SREV_VERSION_9100) || | ||
3100 | (ah->ah_macVersion == AR_SREV_VERSION_9280)) | ||
3101 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; | ||
3102 | else | ||
3103 | pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; | ||
3104 | |||
3105 | if (AR_SREV_9280(ah)) | ||
3106 | pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; | ||
3107 | else | ||
3108 | pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; | ||
3109 | |||
3110 | if (ah->ah_currentRDExt & (1 << REG_EXT_JAPAN_MIDBAND)) { | ||
3111 | pCap->reg_cap = | ||
3112 | AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | | ||
3113 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | | ||
3114 | AR_EEPROM_EEREGCAP_EN_KK_U2 | | ||
3115 | AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; | ||
3116 | } else { | ||
3117 | pCap->reg_cap = | ||
3118 | AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | | ||
3119 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; | ||
3120 | } | ||
3121 | |||
3122 | pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; | ||
3123 | |||
3124 | pCap->num_antcfg_5ghz = | ||
3125 | ath9k_hw_get_num_ant_config(ahp, IEEE80211_BAND_5GHZ); | ||
3126 | pCap->num_antcfg_2ghz = | ||
3127 | ath9k_hw_get_num_ant_config(ahp, IEEE80211_BAND_2GHZ); | ||
3128 | |||
3129 | return true; | ||
3130 | } | ||
3131 | |||
3132 | static void ar5416DisablePciePhy(struct ath_hal *ah) | ||
3133 | { | ||
3134 | if (!AR_SREV_9100(ah)) | ||
3135 | return; | ||
3136 | |||
3137 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); | ||
3138 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
3139 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); | ||
3140 | REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824); | ||
3141 | REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579); | ||
3142 | REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000); | ||
3143 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | ||
3144 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
3145 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); | ||
3146 | |||
3147 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | ||
3148 | } | ||
3149 | |||
3150 | static void ath9k_set_power_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 | REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, | ||
3155 | AR_RTC_FORCE_WAKE_EN); | ||
3156 | if (!AR_SREV_9100(ah)) | ||
3157 | REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); | ||
3158 | |||
3159 | REG_CLR_BIT(ah, (u16) (AR_RTC_RESET), | ||
3160 | AR_RTC_RESET_EN); | ||
3161 | } | ||
3162 | } | ||
3163 | |||
3164 | static void ath9k_set_power_network_sleep(struct ath_hal *ah, int setChip) | ||
3165 | { | ||
3166 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | ||
3167 | if (setChip) { | ||
3168 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
3169 | |||
3170 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
3171 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, | ||
3172 | AR_RTC_FORCE_WAKE_ON_INT); | ||
3173 | } else { | ||
3174 | REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, | ||
3175 | AR_RTC_FORCE_WAKE_EN); | ||
3176 | } | ||
3177 | } | ||
3178 | } | ||
3179 | |||
3180 | static bool ath9k_hw_set_power_awake(struct ath_hal *ah, | ||
3181 | int setChip) | ||
3182 | { | ||
3183 | u32 val; | ||
3184 | int i; | ||
3185 | |||
3186 | if (setChip) { | ||
3187 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == | ||
3188 | AR_RTC_STATUS_SHUTDOWN) { | ||
3189 | if (ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON) | ||
3190 | != true) { | ||
3191 | return false; | ||
3192 | } | ||
3193 | } | ||
3194 | if (AR_SREV_9100(ah)) | ||
3195 | REG_SET_BIT(ah, AR_RTC_RESET, | ||
3196 | AR_RTC_RESET_EN); | ||
3197 | |||
3198 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, | ||
3199 | AR_RTC_FORCE_WAKE_EN); | ||
3200 | udelay(50); | ||
3201 | |||
3202 | for (i = POWER_UP_TIME / 50; i > 0; i--) { | ||
3203 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; | ||
3204 | if (val == AR_RTC_STATUS_ON) | ||
3205 | break; | ||
3206 | udelay(50); | ||
3207 | REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, | ||
3208 | AR_RTC_FORCE_WAKE_EN); | ||
3209 | } | ||
3210 | if (i == 0) { | ||
3211 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
3212 | "%s: Failed to wakeup in %uus\n", | ||
3213 | __func__, POWER_UP_TIME / 20); | ||
3214 | return false; | ||
3215 | } | ||
3216 | } | ||
3217 | |||
3218 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | ||
3219 | return true; | ||
3220 | } | ||
3221 | |||
3222 | bool ath9k_hw_setpower(struct ath_hal *ah, | ||
3223 | enum ath9k_power_mode mode) | ||
3224 | { | ||
3225 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
3226 | static const char *modes[] = { | ||
3227 | "AWAKE", | ||
3228 | "FULL-SLEEP", | ||
3229 | "NETWORK SLEEP", | ||
3230 | "UNDEFINED" | ||
3231 | }; | ||
3232 | int status = true, setChip = true; | ||
3233 | |||
3234 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s: %s -> %s (%s)\n", __func__, | ||
3235 | modes[ahp->ah_powerMode], modes[mode], | ||
3236 | setChip ? "set chip " : ""); | ||
3237 | |||
3238 | switch (mode) { | ||
3239 | case ATH9K_PM_AWAKE: | ||
3240 | status = ath9k_hw_set_power_awake(ah, setChip); | ||
3241 | break; | ||
3242 | case ATH9K_PM_FULL_SLEEP: | ||
3243 | ath9k_set_power_sleep(ah, setChip); | ||
3244 | ahp->ah_chipFullSleep = true; | ||
3245 | break; | ||
3246 | case ATH9K_PM_NETWORK_SLEEP: | ||
3247 | ath9k_set_power_network_sleep(ah, setChip); | ||
3248 | break; | ||
3249 | default: | ||
3250 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
3251 | "%s: unknown power mode %u\n", __func__, mode); | ||
3252 | return false; | ||
3253 | } | ||
3254 | ahp->ah_powerMode = mode; | ||
3255 | return status; | ||
3256 | } | ||
3257 | |||
3258 | static struct ath_hal *ath9k_hw_do_attach(u16 devid, | ||
3259 | struct ath_softc *sc, | ||
3260 | void __iomem *mem, | ||
3261 | int *status) | ||
3262 | { | ||
3263 | struct ath_hal_5416 *ahp; | ||
3264 | struct ath_hal *ah; | ||
3265 | int ecode; | ||
3266 | #ifndef CONFIG_SLOW_ANT_DIV | ||
3267 | u32 i; | ||
3268 | u32 j; | ||
3269 | #endif | ||
3270 | |||
3271 | ahp = ath9k_hw_newstate(devid, sc, mem, status); | ||
3272 | if (ahp == NULL) | ||
3273 | return NULL; | ||
3274 | |||
3275 | ah = &ahp->ah; | ||
3276 | |||
3277 | ath9k_hw_set_defaults(ah); | ||
3278 | |||
3279 | if (ah->ah_config.intr_mitigation != 0) | ||
3280 | ahp->ah_intrMitigation = true; | ||
3281 | |||
3282 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { | ||
3283 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: couldn't reset chip\n", | ||
3284 | __func__); | ||
3285 | ecode = -EIO; | ||
3286 | goto bad; | ||
3287 | } | ||
3288 | |||
3289 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { | ||
3290 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: couldn't wakeup chip\n", | ||
3291 | __func__); | ||
3292 | ecode = -EIO; | ||
3293 | goto bad; | ||
3294 | } | ||
3295 | |||
3296 | if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) { | ||
3297 | if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) { | ||
3298 | ah->ah_config.serialize_regmode = | ||
3299 | SER_REG_MODE_ON; | ||
3300 | } else { | ||
3301 | ah->ah_config.serialize_regmode = | ||
3302 | SER_REG_MODE_OFF; | ||
3303 | } | ||
3304 | } | ||
3305 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3306 | "%s: serialize_regmode is %d\n", | ||
3307 | __func__, ah->ah_config.serialize_regmode); | ||
3308 | |||
3309 | if ((ah->ah_macVersion != AR_SREV_VERSION_5416_PCI) && | ||
3310 | (ah->ah_macVersion != AR_SREV_VERSION_5416_PCIE) && | ||
3311 | (ah->ah_macVersion != AR_SREV_VERSION_9160) && | ||
3312 | (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah))) { | ||
3313 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3314 | "%s: Mac Chip Rev 0x%02x.%x is not supported by " | ||
3315 | "this driver\n", __func__, | ||
3316 | ah->ah_macVersion, ah->ah_macRev); | ||
3317 | ecode = -EOPNOTSUPP; | ||
3318 | goto bad; | ||
3319 | } | ||
3320 | |||
3321 | if (AR_SREV_9100(ah)) { | ||
3322 | ahp->ah_iqCalData.calData = &iq_cal_multi_sample; | ||
3323 | ahp->ah_suppCals = IQ_MISMATCH_CAL; | ||
3324 | ah->ah_isPciExpress = false; | ||
3325 | } | ||
3326 | ah->ah_phyRev = REG_READ(ah, AR_PHY_CHIP_ID); | ||
3327 | |||
3328 | if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
3329 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3330 | ahp->ah_iqCalData.calData = &iq_cal_single_sample; | ||
3331 | ahp->ah_adcGainCalData.calData = | ||
3332 | &adc_gain_cal_single_sample; | ||
3333 | ahp->ah_adcDcCalData.calData = | ||
3334 | &adc_dc_cal_single_sample; | ||
3335 | ahp->ah_adcDcCalInitData.calData = | ||
3336 | &adc_init_dc_cal; | ||
3337 | } else { | ||
3338 | ahp->ah_iqCalData.calData = &iq_cal_multi_sample; | ||
3339 | ahp->ah_adcGainCalData.calData = | ||
3340 | &adc_gain_cal_multi_sample; | ||
3341 | ahp->ah_adcDcCalData.calData = | ||
3342 | &adc_dc_cal_multi_sample; | ||
3343 | ahp->ah_adcDcCalInitData.calData = | ||
3344 | &adc_init_dc_cal; | ||
3345 | } | ||
3346 | ahp->ah_suppCals = | ||
3347 | ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; | ||
3348 | } | ||
3349 | |||
3350 | if (AR_SREV_9160(ah)) { | ||
3351 | ah->ah_config.enable_ani = 1; | ||
3352 | ahp->ah_ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | | ||
3353 | ATH9K_ANI_FIRSTEP_LEVEL); | ||
3354 | } else { | ||
3355 | ahp->ah_ani_function = ATH9K_ANI_ALL; | ||
3356 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3357 | ahp->ah_ani_function &= | ||
3358 | ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | ||
3359 | } | ||
3360 | } | ||
3361 | |||
3362 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3363 | "%s: This Mac Chip Rev 0x%02x.%x is \n", __func__, | ||
3364 | ah->ah_macVersion, ah->ah_macRev); | ||
3365 | |||
3366 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
3367 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280_2, | ||
3368 | ARRAY_SIZE(ar9280Modes_9280_2), 6); | ||
3369 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280_2, | ||
3370 | ARRAY_SIZE(ar9280Common_9280_2), 2); | ||
3371 | |||
3372 | if (ah->ah_config.pcie_clock_req) { | ||
3373 | INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes, | ||
3374 | ar9280PciePhy_clkreq_off_L1_9280, | ||
3375 | ARRAY_SIZE | ||
3376 | (ar9280PciePhy_clkreq_off_L1_9280), | ||
3377 | 2); | ||
3378 | } else { | ||
3379 | INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes, | ||
3380 | ar9280PciePhy_clkreq_always_on_L1_9280, | ||
3381 | ARRAY_SIZE | ||
3382 | (ar9280PciePhy_clkreq_always_on_L1_9280), | ||
3383 | 2); | ||
3384 | } | ||
3385 | INIT_INI_ARRAY(&ahp->ah_iniModesAdditional, | ||
3386 | ar9280Modes_fast_clock_9280_2, | ||
3387 | ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), | ||
3388 | 3); | ||
3389 | } else if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3390 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280, | ||
3391 | ARRAY_SIZE(ar9280Modes_9280), 6); | ||
3392 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280, | ||
3393 | ARRAY_SIZE(ar9280Common_9280), 2); | ||
3394 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | ||
3395 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes_9160, | ||
3396 | ARRAY_SIZE(ar5416Modes_9160), 6); | ||
3397 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common_9160, | ||
3398 | ARRAY_SIZE(ar5416Common_9160), 2); | ||
3399 | INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0_9160, | ||
3400 | ARRAY_SIZE(ar5416Bank0_9160), 2); | ||
3401 | INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain_9160, | ||
3402 | ARRAY_SIZE(ar5416BB_RfGain_9160), 3); | ||
3403 | INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1_9160, | ||
3404 | ARRAY_SIZE(ar5416Bank1_9160), 2); | ||
3405 | INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2_9160, | ||
3406 | ARRAY_SIZE(ar5416Bank2_9160), 2); | ||
3407 | INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3_9160, | ||
3408 | ARRAY_SIZE(ar5416Bank3_9160), 3); | ||
3409 | INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6_9160, | ||
3410 | ARRAY_SIZE(ar5416Bank6_9160), 3); | ||
3411 | INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC_9160, | ||
3412 | ARRAY_SIZE(ar5416Bank6TPC_9160), 3); | ||
3413 | INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7_9160, | ||
3414 | ARRAY_SIZE(ar5416Bank7_9160), 2); | ||
3415 | if (AR_SREV_9160_11(ah)) { | ||
3416 | INIT_INI_ARRAY(&ahp->ah_iniAddac, | ||
3417 | ar5416Addac_91601_1, | ||
3418 | ARRAY_SIZE(ar5416Addac_91601_1), 2); | ||
3419 | } else { | ||
3420 | INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac_9160, | ||
3421 | ARRAY_SIZE(ar5416Addac_9160), 2); | ||
3422 | } | ||
3423 | } else if (AR_SREV_9100_OR_LATER(ah)) { | ||
3424 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes_9100, | ||
3425 | ARRAY_SIZE(ar5416Modes_9100), 6); | ||
3426 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common_9100, | ||
3427 | ARRAY_SIZE(ar5416Common_9100), 2); | ||
3428 | INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0_9100, | ||
3429 | ARRAY_SIZE(ar5416Bank0_9100), 2); | ||
3430 | INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain_9100, | ||
3431 | ARRAY_SIZE(ar5416BB_RfGain_9100), 3); | ||
3432 | INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1_9100, | ||
3433 | ARRAY_SIZE(ar5416Bank1_9100), 2); | ||
3434 | INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2_9100, | ||
3435 | ARRAY_SIZE(ar5416Bank2_9100), 2); | ||
3436 | INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3_9100, | ||
3437 | ARRAY_SIZE(ar5416Bank3_9100), 3); | ||
3438 | INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6_9100, | ||
3439 | ARRAY_SIZE(ar5416Bank6_9100), 3); | ||
3440 | INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC_9100, | ||
3441 | ARRAY_SIZE(ar5416Bank6TPC_9100), 3); | ||
3442 | INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7_9100, | ||
3443 | ARRAY_SIZE(ar5416Bank7_9100), 2); | ||
3444 | INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac_9100, | ||
3445 | ARRAY_SIZE(ar5416Addac_9100), 2); | ||
3446 | } else { | ||
3447 | INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes, | ||
3448 | ARRAY_SIZE(ar5416Modes), 6); | ||
3449 | INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common, | ||
3450 | ARRAY_SIZE(ar5416Common), 2); | ||
3451 | INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0, | ||
3452 | ARRAY_SIZE(ar5416Bank0), 2); | ||
3453 | INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain, | ||
3454 | ARRAY_SIZE(ar5416BB_RfGain), 3); | ||
3455 | INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1, | ||
3456 | ARRAY_SIZE(ar5416Bank1), 2); | ||
3457 | INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2, | ||
3458 | ARRAY_SIZE(ar5416Bank2), 2); | ||
3459 | INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3, | ||
3460 | ARRAY_SIZE(ar5416Bank3), 3); | ||
3461 | INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6, | ||
3462 | ARRAY_SIZE(ar5416Bank6), 3); | ||
3463 | INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC, | ||
3464 | ARRAY_SIZE(ar5416Bank6TPC), 3); | ||
3465 | INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7, | ||
3466 | ARRAY_SIZE(ar5416Bank7), 2); | ||
3467 | INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac, | ||
3468 | ARRAY_SIZE(ar5416Addac), 2); | ||
3469 | } | ||
3470 | |||
3471 | if (ah->ah_isPciExpress) | ||
3472 | ath9k_hw_configpcipowersave(ah, 0); | ||
3473 | else | ||
3474 | ar5416DisablePciePhy(ah); | ||
3475 | |||
3476 | ecode = ath9k_hw_post_attach(ah); | ||
3477 | if (ecode != 0) | ||
3478 | goto bad; | ||
3479 | |||
3480 | #ifndef CONFIG_SLOW_ANT_DIV | ||
3481 | if (ah->ah_devid == AR9280_DEVID_PCI) { | ||
3482 | for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) { | ||
3483 | u32 reg = INI_RA(&ahp->ah_iniModes, i, 0); | ||
3484 | |||
3485 | for (j = 1; j < ahp->ah_iniModes.ia_columns; j++) { | ||
3486 | u32 val = INI_RA(&ahp->ah_iniModes, i, j); | ||
3487 | |||
3488 | INI_RA(&ahp->ah_iniModes, i, j) = | ||
3489 | ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom, | ||
3490 | reg, val); | ||
3491 | } | ||
3492 | } | ||
3493 | } | ||
3494 | #endif | ||
3495 | |||
3496 | if (!ath9k_hw_fill_cap_info(ah)) { | ||
3497 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3498 | "%s:failed ath9k_hw_fill_cap_info\n", __func__); | ||
3499 | ecode = -EINVAL; | ||
3500 | goto bad; | ||
3501 | } | ||
3502 | |||
3503 | ecode = ath9k_hw_init_macaddr(ah); | ||
3504 | if (ecode != 0) { | ||
3505 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3506 | "%s: failed initializing mac address\n", | ||
3507 | __func__); | ||
3508 | goto bad; | ||
3509 | } | ||
3510 | |||
3511 | if (AR_SREV_9285(ah)) | ||
3512 | ah->ah_txTrigLevel = (AR_FTRIG_256B >> AR_FTRIG_S); | ||
3513 | else | ||
3514 | ah->ah_txTrigLevel = (AR_FTRIG_512B >> AR_FTRIG_S); | ||
3515 | |||
3516 | #ifndef ATH_NF_PER_CHAN | ||
3517 | |||
3518 | ath9k_init_nfcal_hist_buffer(ah); | ||
3519 | #endif | ||
3520 | |||
3521 | return ah; | ||
3522 | |||
3523 | bad: | ||
3524 | if (ahp) | ||
3525 | ath9k_hw_detach((struct ath_hal *) ahp); | ||
3526 | if (status) | ||
3527 | *status = ecode; | ||
3528 | return NULL; | ||
3529 | } | ||
3530 | |||
3531 | void ath9k_hw_detach(struct ath_hal *ah) | ||
3532 | { | ||
3533 | if (!AR_SREV_9100(ah)) | ||
3534 | ath9k_hw_ani_detach(ah); | ||
3535 | ath9k_hw_rfdetach(ah); | ||
3536 | |||
3537 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | ||
3538 | kfree(ah); | ||
3539 | } | ||
3540 | |||
3541 | bool ath9k_get_channel_edges(struct ath_hal *ah, | ||
3542 | u16 flags, u16 *low, | ||
3543 | u16 *high) | ||
3544 | { | ||
3545 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
3546 | |||
3547 | if (flags & CHANNEL_5GHZ) { | ||
3548 | *low = pCap->low_5ghz_chan; | ||
3549 | *high = pCap->high_5ghz_chan; | ||
3550 | return true; | ||
3551 | } | ||
3552 | if ((flags & CHANNEL_2GHZ)) { | ||
3553 | *low = pCap->low_2ghz_chan; | ||
3554 | *high = pCap->high_2ghz_chan; | ||
3555 | |||
3556 | return true; | ||
3557 | } | ||
3558 | return false; | ||
3559 | } | ||
3560 | |||
3561 | static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, | ||
3562 | u8 pwrMax, | ||
3563 | u8 *pPwrList, | ||
3564 | u8 *pVpdList, | ||
3565 | u16 | ||
3566 | numIntercepts, | ||
3567 | u8 *pRetVpdList) | ||
3568 | { | ||
3569 | u16 i, k; | ||
3570 | u8 currPwr = pwrMin; | ||
3571 | u16 idxL = 0, idxR = 0; | ||
3572 | |||
3573 | for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { | ||
3574 | ath9k_hw_get_lower_upper_index(currPwr, pPwrList, | ||
3575 | numIntercepts, &(idxL), | ||
3576 | &(idxR)); | ||
3577 | if (idxR < 1) | ||
3578 | idxR = 1; | ||
3579 | if (idxL == numIntercepts - 1) | ||
3580 | idxL = (u16) (numIntercepts - 2); | ||
3581 | if (pPwrList[idxL] == pPwrList[idxR]) | ||
3582 | k = pVpdList[idxL]; | ||
3583 | else | ||
3584 | k = (u16) (((currPwr - | ||
3585 | pPwrList[idxL]) * | ||
3586 | pVpdList[idxR] + | ||
3587 | (pPwrList[idxR] - | ||
3588 | currPwr) * pVpdList[idxL]) / | ||
3589 | (pPwrList[idxR] - | ||
3590 | pPwrList[idxL])); | ||
3591 | pRetVpdList[i] = (u8) k; | ||
3592 | currPwr += 2; | ||
3593 | } | ||
3594 | |||
3595 | return true; | ||
3596 | } | ||
3597 | |||
3598 | static inline void | ||
3599 | ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah, | ||
3600 | struct ath9k_channel *chan, | ||
3601 | struct cal_data_per_freq *pRawDataSet, | ||
3602 | u8 *bChans, | ||
3603 | u16 availPiers, | ||
3604 | u16 tPdGainOverlap, | ||
3605 | int16_t *pMinCalPower, | ||
3606 | u16 *pPdGainBoundaries, | ||
3607 | u8 *pPDADCValues, | ||
3608 | u16 numXpdGains) | ||
3609 | { | ||
3610 | int i, j, k; | ||
3611 | int16_t ss; | ||
3612 | u16 idxL = 0, idxR = 0, numPiers; | ||
3613 | static u8 vpdTableL[AR5416_NUM_PD_GAINS] | ||
3614 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3615 | static u8 vpdTableR[AR5416_NUM_PD_GAINS] | ||
3616 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3617 | static u8 vpdTableI[AR5416_NUM_PD_GAINS] | ||
3618 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3619 | |||
3620 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
3621 | u8 minPwrT4[AR5416_NUM_PD_GAINS]; | ||
3622 | u8 maxPwrT4[AR5416_NUM_PD_GAINS]; | ||
3623 | int16_t vpdStep; | ||
3624 | int16_t tmpVal; | ||
3625 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
3626 | bool match; | ||
3627 | int16_t minDelta = 0; | ||
3628 | struct chan_centers centers; | ||
3629 | |||
3630 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3631 | |||
3632 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
3633 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
3634 | break; | ||
3635 | } | ||
3636 | |||
3637 | match = ath9k_hw_get_lower_upper_index((u8) | ||
3638 | FREQ2FBIN(centers. | ||
3639 | synth_center, | ||
3640 | IS_CHAN_2GHZ | ||
3641 | (chan)), bChans, | ||
3642 | numPiers, &idxL, &idxR); | ||
3643 | |||
3644 | if (match) { | ||
3645 | for (i = 0; i < numXpdGains; i++) { | ||
3646 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
3647 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
3648 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3649 | pRawDataSet[idxL]. | ||
3650 | pwrPdg[i], | ||
3651 | pRawDataSet[idxL]. | ||
3652 | vpdPdg[i], | ||
3653 | AR5416_PD_GAIN_ICEPTS, | ||
3654 | vpdTableI[i]); | ||
3655 | } | ||
3656 | } else { | ||
3657 | for (i = 0; i < numXpdGains; i++) { | ||
3658 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
3659 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
3660 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
3661 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
3662 | |||
3663 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
3664 | |||
3665 | maxPwrT4[i] = | ||
3666 | min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], | ||
3667 | pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); | ||
3668 | |||
3669 | |||
3670 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3671 | pPwrL, pVpdL, | ||
3672 | AR5416_PD_GAIN_ICEPTS, | ||
3673 | vpdTableL[i]); | ||
3674 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3675 | pPwrR, pVpdR, | ||
3676 | AR5416_PD_GAIN_ICEPTS, | ||
3677 | vpdTableR[i]); | ||
3678 | |||
3679 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
3680 | vpdTableI[i][j] = | ||
3681 | (u8) (ath9k_hw_interpolate | ||
3682 | ((u16) | ||
3683 | FREQ2FBIN(centers. | ||
3684 | synth_center, | ||
3685 | IS_CHAN_2GHZ | ||
3686 | (chan)), | ||
3687 | bChans[idxL], | ||
3688 | bChans[idxR], vpdTableL[i] | ||
3689 | [j], vpdTableR[i] | ||
3690 | [j])); | ||
3691 | } | ||
3692 | } | ||
3693 | } | ||
3694 | |||
3695 | *pMinCalPower = (int16_t) (minPwrT4[0] / 2); | ||
3696 | |||
3697 | k = 0; | ||
3698 | for (i = 0; i < numXpdGains; i++) { | ||
3699 | if (i == (numXpdGains - 1)) | ||
3700 | pPdGainBoundaries[i] = | ||
3701 | (u16) (maxPwrT4[i] / 2); | ||
3702 | else | ||
3703 | pPdGainBoundaries[i] = | ||
3704 | (u16) ((maxPwrT4[i] + | ||
3705 | minPwrT4[i + 1]) / 4); | ||
3706 | |||
3707 | pPdGainBoundaries[i] = | ||
3708 | min((u16) AR5416_MAX_RATE_POWER, | ||
3709 | pPdGainBoundaries[i]); | ||
3710 | |||
3711 | if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) { | ||
3712 | minDelta = pPdGainBoundaries[0] - 23; | ||
3713 | pPdGainBoundaries[0] = 23; | ||
3714 | } else { | ||
3715 | minDelta = 0; | ||
3716 | } | ||
3717 | |||
3718 | if (i == 0) { | ||
3719 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
3720 | ss = (int16_t) (0 - (minPwrT4[i] / 2)); | ||
3721 | else | ||
3722 | ss = 0; | ||
3723 | } else { | ||
3724 | ss = (int16_t) ((pPdGainBoundaries[i - 1] - | ||
3725 | (minPwrT4[i] / 2)) - | ||
3726 | tPdGainOverlap + 1 + minDelta); | ||
3727 | } | ||
3728 | vpdStep = (int16_t) (vpdTableI[i][1] - vpdTableI[i][0]); | ||
3729 | vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep); | ||
3730 | |||
3731 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
3732 | tmpVal = (int16_t) (vpdTableI[i][0] + ss * vpdStep); | ||
3733 | pPDADCValues[k++] = | ||
3734 | (u8) ((tmpVal < 0) ? 0 : tmpVal); | ||
3735 | ss++; | ||
3736 | } | ||
3737 | |||
3738 | sizeCurrVpdTable = | ||
3739 | (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
3740 | tgtIndex = (u8) (pPdGainBoundaries[i] + tPdGainOverlap - | ||
3741 | (minPwrT4[i] / 2)); | ||
3742 | maxIndex = (tgtIndex < | ||
3743 | sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; | ||
3744 | |||
3745 | while ((ss < maxIndex) | ||
3746 | && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
3747 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
3748 | } | ||
3749 | |||
3750 | vpdStep = (int16_t) (vpdTableI[i][sizeCurrVpdTable - 1] - | ||
3751 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
3752 | vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep); | ||
3753 | |||
3754 | if (tgtIndex > maxIndex) { | ||
3755 | while ((ss <= tgtIndex) | ||
3756 | && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
3757 | tmpVal = (int16_t) ((vpdTableI[i] | ||
3758 | [sizeCurrVpdTable - | ||
3759 | 1] + (ss - maxIndex + | ||
3760 | 1) * vpdStep)); | ||
3761 | pPDADCValues[k++] = (u8) ((tmpVal > | ||
3762 | 255) ? 255 : tmpVal); | ||
3763 | ss++; | ||
3764 | } | ||
3765 | } | ||
3766 | } | ||
3767 | |||
3768 | while (i < AR5416_PD_GAINS_IN_MASK) { | ||
3769 | pPdGainBoundaries[i] = pPdGainBoundaries[i - 1]; | ||
3770 | i++; | ||
3771 | } | ||
3772 | |||
3773 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
3774 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
3775 | k++; | ||
3776 | } | ||
3777 | return; | ||
3778 | } | ||
3779 | |||
3780 | static inline bool | ||
3781 | ath9k_hw_set_power_cal_table(struct ath_hal *ah, | ||
3782 | struct ar5416_eeprom *pEepData, | ||
3783 | struct ath9k_channel *chan, | ||
3784 | int16_t *pTxPowerIndexOffset) | ||
3785 | { | ||
3786 | struct cal_data_per_freq *pRawDataset; | ||
3787 | u8 *pCalBChans = NULL; | ||
3788 | u16 pdGainOverlap_t2; | ||
3789 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | ||
3790 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; | ||
3791 | u16 numPiers, i, j; | ||
3792 | int16_t tMinCalPower; | ||
3793 | u16 numXpdGain, xpdMask; | ||
3794 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; | ||
3795 | u32 reg32, regOffset, regChainOffset; | ||
3796 | int16_t modalIdx; | ||
3797 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
3798 | |||
3799 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | ||
3800 | xpdMask = pEepData->modalHeader[modalIdx].xpdGain; | ||
3801 | |||
3802 | if ((pEepData->baseEepHeader. | ||
3803 | version & AR5416_EEP_VER_MINOR_MASK) >= | ||
3804 | AR5416_EEP_MINOR_VER_2) { | ||
3805 | pdGainOverlap_t2 = | ||
3806 | pEepData->modalHeader[modalIdx].pdGainOverlap; | ||
3807 | } else { | ||
3808 | pdGainOverlap_t2 = | ||
3809 | (u16) (MS | ||
3810 | (REG_READ(ah, AR_PHY_TPCRG5), | ||
3811 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
3812 | } | ||
3813 | |||
3814 | if (IS_CHAN_2GHZ(chan)) { | ||
3815 | pCalBChans = pEepData->calFreqPier2G; | ||
3816 | numPiers = AR5416_NUM_2G_CAL_PIERS; | ||
3817 | } else { | ||
3818 | pCalBChans = pEepData->calFreqPier5G; | ||
3819 | numPiers = AR5416_NUM_5G_CAL_PIERS; | ||
3820 | } | ||
3821 | |||
3822 | numXpdGain = 0; | ||
3823 | |||
3824 | for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { | ||
3825 | if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { | ||
3826 | if (numXpdGain >= AR5416_NUM_PD_GAINS) | ||
3827 | break; | ||
3828 | xpdGainValues[numXpdGain] = | ||
3829 | (u16) (AR5416_PD_GAINS_IN_MASK - i); | ||
3830 | numXpdGain++; | ||
3831 | } | ||
3832 | } | ||
3833 | |||
3834 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
3835 | (numXpdGain - 1) & 0x3); | ||
3836 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
3837 | xpdGainValues[0]); | ||
3838 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
3839 | xpdGainValues[1]); | ||
3840 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, | ||
3841 | xpdGainValues[2]); | ||
3842 | |||
3843 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
3844 | if (AR_SREV_5416_V20_OR_LATER(ah) && | ||
3845 | (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) | ||
3846 | && (i != 0)) { | ||
3847 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
3848 | } else | ||
3849 | regChainOffset = i * 0x1000; | ||
3850 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
3851 | if (IS_CHAN_2GHZ(chan)) | ||
3852 | pRawDataset = pEepData->calPierData2G[i]; | ||
3853 | else | ||
3854 | pRawDataset = pEepData->calPierData5G[i]; | ||
3855 | |||
3856 | ath9k_hw_get_gain_boundaries_pdadcs(ah, chan, | ||
3857 | pRawDataset, | ||
3858 | pCalBChans, | ||
3859 | numPiers, | ||
3860 | pdGainOverlap_t2, | ||
3861 | &tMinCalPower, | ||
3862 | gainBoundaries, | ||
3863 | pdadcValues, | ||
3864 | numXpdGain); | ||
3865 | |||
3866 | if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { | ||
3867 | |||
3868 | REG_WRITE(ah, | ||
3869 | AR_PHY_TPCRG5 + regChainOffset, | ||
3870 | SM(pdGainOverlap_t2, | ||
3871 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | ||
3872 | | SM(gainBoundaries[0], | ||
3873 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | ||
3874 | | SM(gainBoundaries[1], | ||
3875 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | ||
3876 | | SM(gainBoundaries[2], | ||
3877 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | ||
3878 | | SM(gainBoundaries[3], | ||
3879 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | ||
3880 | } | ||
3881 | |||
3882 | regOffset = | ||
3883 | AR_PHY_BASE + (672 << 2) + regChainOffset; | ||
3884 | for (j = 0; j < 32; j++) { | ||
3885 | reg32 = | ||
3886 | ((pdadcValues[4 * j + 0] & 0xFF) << 0) | ||
3887 | | ((pdadcValues[4 * j + 1] & 0xFF) << | ||
3888 | 8) | ((pdadcValues[4 * j + 2] & | ||
3889 | 0xFF) << 16) | | ||
3890 | ((pdadcValues[4 * j + 3] & 0xFF) << | ||
3891 | 24); | ||
3892 | REG_WRITE(ah, regOffset, reg32); | ||
3893 | |||
3894 | DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO, | ||
3895 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
3896 | i, regChainOffset, regOffset, | ||
3897 | reg32); | ||
3898 | DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO, | ||
3899 | "PDADC: Chain %d | PDADC %3d Value %3d | " | ||
3900 | "PDADC %3d Value %3d | PDADC %3d Value %3d | " | ||
3901 | "PDADC %3d Value %3d |\n", | ||
3902 | i, 4 * j, pdadcValues[4 * j], | ||
3903 | 4 * j + 1, pdadcValues[4 * j + 1], | ||
3904 | 4 * j + 2, pdadcValues[4 * j + 2], | ||
3905 | 4 * j + 3, | ||
3906 | pdadcValues[4 * j + 3]); | ||
3907 | |||
3908 | regOffset += 4; | ||
3909 | } | ||
3910 | } | ||
3911 | } | ||
3912 | *pTxPowerIndexOffset = 0; | ||
3913 | |||
3914 | return true; | ||
3915 | } | ||
3916 | |||
3917 | void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore) | ||
3918 | { | ||
3919 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
3920 | u8 i; | ||
3921 | |||
3922 | if (ah->ah_isPciExpress != true) | ||
3923 | return; | ||
3924 | |||
3925 | if (ah->ah_config.pcie_powersave_enable == 2) | ||
3926 | return; | ||
3927 | |||
3928 | if (restore) | ||
3929 | return; | ||
3930 | |||
3931 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
3932 | for (i = 0; i < ahp->ah_iniPcieSerdes.ia_rows; i++) { | ||
3933 | REG_WRITE(ah, INI_RA(&ahp->ah_iniPcieSerdes, i, 0), | ||
3934 | INI_RA(&ahp->ah_iniPcieSerdes, i, 1)); | ||
3935 | } | ||
3936 | udelay(1000); | ||
3937 | } else if (AR_SREV_9280(ah) | ||
3938 | && (ah->ah_macRev == AR_SREV_REVISION_9280_10)) { | ||
3939 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); | ||
3940 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
3941 | |||
3942 | REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); | ||
3943 | REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); | ||
3944 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); | ||
3945 | |||
3946 | if (ah->ah_config.pcie_clock_req) | ||
3947 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); | ||
3948 | else | ||
3949 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); | ||
3950 | |||
3951 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | ||
3952 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
3953 | REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); | ||
3954 | |||
3955 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | ||
3956 | |||
3957 | udelay(1000); | ||
3958 | } else { | ||
3959 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); | ||
3960 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
3961 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); | ||
3962 | REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); | ||
3963 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); | ||
3964 | REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); | ||
3965 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | ||
3966 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
3967 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); | ||
3968 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | ||
3969 | } | ||
3970 | |||
3971 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | ||
3972 | |||
3973 | if (ah->ah_config.pcie_waen) { | ||
3974 | REG_WRITE(ah, AR_WA, ah->ah_config.pcie_waen); | ||
3975 | } else { | ||
3976 | if (AR_SREV_9280(ah)) | ||
3977 | REG_WRITE(ah, AR_WA, 0x0040073f); | ||
3978 | else | ||
3979 | REG_WRITE(ah, AR_WA, 0x0000073f); | ||
3980 | } | ||
3981 | } | ||
3982 | |||
3983 | static inline void | ||
3984 | ath9k_hw_get_legacy_target_powers(struct ath_hal *ah, | ||
3985 | struct ath9k_channel *chan, | ||
3986 | struct cal_target_power_leg *powInfo, | ||
3987 | u16 numChannels, | ||
3988 | struct cal_target_power_leg *pNewPower, | ||
3989 | u16 numRates, | ||
3990 | bool isExtTarget) | ||
3991 | { | ||
3992 | u16 clo, chi; | ||
3993 | int i; | ||
3994 | int matchIndex = -1, lowIndex = -1; | ||
3995 | u16 freq; | ||
3996 | struct chan_centers centers; | ||
3997 | |||
3998 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3999 | freq = (isExtTarget) ? centers.ext_center : centers.ctl_center; | ||
4000 | |||
4001 | if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, | ||
4002 | IS_CHAN_2GHZ(chan))) { | ||
4003 | matchIndex = 0; | ||
4004 | } else { | ||
4005 | for (i = 0; (i < numChannels) | ||
4006 | && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { | ||
4007 | if (freq == | ||
4008 | ath9k_hw_fbin2freq(powInfo[i].bChannel, | ||
4009 | IS_CHAN_2GHZ(chan))) { | ||
4010 | matchIndex = i; | ||
4011 | break; | ||
4012 | } else if ((freq < | ||
4013 | ath9k_hw_fbin2freq(powInfo[i].bChannel, | ||
4014 | IS_CHAN_2GHZ(chan))) | ||
4015 | && (freq > | ||
4016 | ath9k_hw_fbin2freq(powInfo[i - 1]. | ||
4017 | bChannel, | ||
4018 | IS_CHAN_2GHZ | ||
4019 | (chan)))) { | ||
4020 | lowIndex = i - 1; | ||
4021 | break; | ||
4022 | } | ||
4023 | } | ||
4024 | if ((matchIndex == -1) && (lowIndex == -1)) | ||
4025 | matchIndex = i - 1; | ||
4026 | } | ||
4027 | |||
4028 | if (matchIndex != -1) { | ||
4029 | *pNewPower = powInfo[matchIndex]; | ||
4030 | } else { | ||
4031 | clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, | ||
4032 | IS_CHAN_2GHZ(chan)); | ||
4033 | chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, | ||
4034 | IS_CHAN_2GHZ(chan)); | ||
4035 | |||
4036 | for (i = 0; i < numRates; i++) { | ||
4037 | pNewPower->tPow2x[i] = | ||
4038 | (u8) ath9k_hw_interpolate(freq, clo, chi, | ||
4039 | powInfo | ||
4040 | [lowIndex]. | ||
4041 | tPow2x[i], | ||
4042 | powInfo | ||
4043 | [lowIndex + | ||
4044 | 1].tPow2x[i]); | ||
4045 | } | ||
4046 | } | ||
4047 | } | ||
4048 | |||
4049 | static inline void | ||
4050 | ath9k_hw_get_target_powers(struct ath_hal *ah, | ||
4051 | struct ath9k_channel *chan, | ||
4052 | struct cal_target_power_ht *powInfo, | ||
4053 | u16 numChannels, | ||
4054 | struct cal_target_power_ht *pNewPower, | ||
4055 | u16 numRates, | ||
4056 | bool isHt40Target) | ||
4057 | { | ||
4058 | u16 clo, chi; | ||
4059 | int i; | ||
4060 | int matchIndex = -1, lowIndex = -1; | ||
4061 | u16 freq; | ||
4062 | struct chan_centers centers; | ||
4063 | |||
4064 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
4065 | freq = isHt40Target ? centers.synth_center : centers.ctl_center; | ||
4066 | |||
4067 | if (freq <= | ||
4068 | ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) { | ||
4069 | matchIndex = 0; | ||
4070 | } else { | ||
4071 | for (i = 0; (i < numChannels) | ||
4072 | && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { | ||
4073 | if (freq == | ||
4074 | ath9k_hw_fbin2freq(powInfo[i].bChannel, | ||
4075 | IS_CHAN_2GHZ(chan))) { | ||
4076 | matchIndex = i; | ||
4077 | break; | ||
4078 | } else | ||
4079 | if ((freq < | ||
4080 | ath9k_hw_fbin2freq(powInfo[i].bChannel, | ||
4081 | IS_CHAN_2GHZ(chan))) | ||
4082 | && (freq > | ||
4083 | ath9k_hw_fbin2freq(powInfo[i - 1]. | ||
4084 | bChannel, | ||
4085 | IS_CHAN_2GHZ | ||
4086 | (chan)))) { | ||
4087 | lowIndex = i - 1; | ||
4088 | break; | ||
4089 | } | ||
4090 | } | ||
4091 | if ((matchIndex == -1) && (lowIndex == -1)) | ||
4092 | matchIndex = i - 1; | ||
4093 | } | ||
4094 | |||
4095 | if (matchIndex != -1) { | ||
4096 | *pNewPower = powInfo[matchIndex]; | ||
4097 | } else { | ||
4098 | clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, | ||
4099 | IS_CHAN_2GHZ(chan)); | ||
4100 | chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, | ||
4101 | IS_CHAN_2GHZ(chan)); | ||
4102 | |||
4103 | for (i = 0; i < numRates; i++) { | ||
4104 | pNewPower->tPow2x[i] = | ||
4105 | (u8) ath9k_hw_interpolate(freq, clo, chi, | ||
4106 | powInfo | ||
4107 | [lowIndex]. | ||
4108 | tPow2x[i], | ||
4109 | powInfo | ||
4110 | [lowIndex + | ||
4111 | 1].tPow2x[i]); | ||
4112 | } | ||
4113 | } | ||
4114 | } | ||
4115 | |||
4116 | static inline u16 | ||
4117 | ath9k_hw_get_max_edge_power(u16 freq, | ||
4118 | struct cal_ctl_edges *pRdEdgesPower, | ||
4119 | bool is2GHz) | ||
4120 | { | ||
4121 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
4122 | int i; | ||
4123 | |||
4124 | for (i = 0; (i < AR5416_NUM_BAND_EDGES) | ||
4125 | && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) { | ||
4126 | if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, | ||
4127 | is2GHz)) { | ||
4128 | twiceMaxEdgePower = pRdEdgesPower[i].tPower; | ||
4129 | break; | ||
4130 | } else if ((i > 0) | ||
4131 | && (freq < | ||
4132 | ath9k_hw_fbin2freq(pRdEdgesPower[i]. | ||
4133 | bChannel, is2GHz))) { | ||
4134 | if (ath9k_hw_fbin2freq | ||
4135 | (pRdEdgesPower[i - 1].bChannel, is2GHz) < freq | ||
4136 | && pRdEdgesPower[i - 1].flag) { | ||
4137 | twiceMaxEdgePower = | ||
4138 | pRdEdgesPower[i - 1].tPower; | ||
4139 | } | ||
4140 | break; | ||
4141 | } | ||
4142 | } | ||
4143 | return twiceMaxEdgePower; | ||
4144 | } | ||
4145 | |||
4146 | static inline bool | ||
4147 | ath9k_hw_set_power_per_rate_table(struct ath_hal *ah, | ||
4148 | struct ar5416_eeprom *pEepData, | ||
4149 | struct ath9k_channel *chan, | ||
4150 | int16_t *ratesArray, | ||
4151 | u16 cfgCtl, | ||
4152 | u8 AntennaReduction, | ||
4153 | u8 twiceMaxRegulatoryPower, | ||
4154 | u8 powerLimit) | ||
4155 | { | ||
4156 | u8 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
4157 | static const u16 tpScaleReductionTable[5] = | ||
4158 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | ||
4159 | |||
4160 | int i; | ||
4161 | int8_t twiceLargestAntenna; | ||
4162 | struct cal_ctl_data *rep; | ||
4163 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { | ||
4164 | 0, { 0, 0, 0, 0} | ||
4165 | }; | ||
4166 | struct cal_target_power_leg targetPowerOfdmExt = { | ||
4167 | 0, { 0, 0, 0, 0} }, targetPowerCckExt = { | ||
4168 | 0, { 0, 0, 0, 0 } | ||
4169 | }; | ||
4170 | struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { | ||
4171 | 0, {0, 0, 0, 0} | ||
4172 | }; | ||
4173 | u8 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
4174 | u16 ctlModesFor11a[] = | ||
4175 | { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; | ||
4176 | u16 ctlModesFor11g[] = | ||
4177 | { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, | ||
4178 | CTL_2GHT40 | ||
4179 | }; | ||
4180 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | ||
4181 | struct chan_centers centers; | ||
4182 | int tx_chainmask; | ||
4183 | u8 twiceMinEdgePower; | ||
4184 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
4185 | |||
4186 | tx_chainmask = ahp->ah_txchainmask; | ||
4187 | |||
4188 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
4189 | |||
4190 | twiceLargestAntenna = max( | ||
4191 | pEepData->modalHeader | ||
4192 | [IS_CHAN_2GHZ(chan)].antennaGainCh[0], | ||
4193 | pEepData->modalHeader | ||
4194 | [IS_CHAN_2GHZ(chan)].antennaGainCh[1]); | ||
4195 | |||
4196 | twiceLargestAntenna = max((u8) twiceLargestAntenna, | ||
4197 | pEepData->modalHeader | ||
4198 | [IS_CHAN_2GHZ(chan)].antennaGainCh[2]); | ||
4199 | |||
4200 | twiceLargestAntenna = | ||
4201 | (int8_t) min(AntennaReduction - twiceLargestAntenna, 0); | ||
4202 | |||
4203 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
4204 | |||
4205 | if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) { | ||
4206 | maxRegAllowedPower -= | ||
4207 | (tpScaleReductionTable[(ah->ah_tpScale)] * 2); | ||
4208 | } | ||
4209 | |||
4210 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
4211 | |||
4212 | switch (ar5416_get_ntxchains(tx_chainmask)) { | ||
4213 | case 1: | ||
4214 | break; | ||
4215 | case 2: | ||
4216 | scaledPower -= | ||
4217 | pEepData->modalHeader[IS_CHAN_2GHZ(chan)]. | ||
4218 | pwrDecreaseFor2Chain; | ||
4219 | break; | ||
4220 | case 3: | ||
4221 | scaledPower -= | ||
4222 | pEepData->modalHeader[IS_CHAN_2GHZ(chan)]. | ||
4223 | pwrDecreaseFor3Chain; | ||
4224 | break; | ||
4225 | } | ||
4226 | |||
4227 | scaledPower = max(0, (int32_t) scaledPower); | ||
4228 | |||
4229 | if (IS_CHAN_2GHZ(chan)) { | ||
4230 | numCtlModes = | ||
4231 | ARRAY_SIZE(ctlModesFor11g) - | ||
4232 | SUB_NUM_CTL_MODES_AT_2G_40; | ||
4233 | pCtlMode = ctlModesFor11g; | ||
4234 | |||
4235 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4236 | pEepData-> | ||
4237 | calTargetPowerCck, | ||
4238 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
4239 | &targetPowerCck, 4, | ||
4240 | false); | ||
4241 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4242 | pEepData-> | ||
4243 | calTargetPower2G, | ||
4244 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
4245 | &targetPowerOfdm, 4, | ||
4246 | false); | ||
4247 | ath9k_hw_get_target_powers(ah, chan, | ||
4248 | pEepData->calTargetPower2GHT20, | ||
4249 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
4250 | &targetPowerHt20, 8, false); | ||
4251 | |||
4252 | if (IS_CHAN_HT40(chan)) { | ||
4253 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
4254 | ath9k_hw_get_target_powers(ah, chan, | ||
4255 | pEepData-> | ||
4256 | calTargetPower2GHT40, | ||
4257 | AR5416_NUM_2G_40_TARGET_POWERS, | ||
4258 | &targetPowerHt40, 8, | ||
4259 | true); | ||
4260 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4261 | pEepData-> | ||
4262 | calTargetPowerCck, | ||
4263 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
4264 | &targetPowerCckExt, | ||
4265 | 4, true); | ||
4266 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4267 | pEepData-> | ||
4268 | calTargetPower2G, | ||
4269 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
4270 | &targetPowerOfdmExt, | ||
4271 | 4, true); | ||
4272 | } | ||
4273 | } else { | ||
4274 | |||
4275 | numCtlModes = | ||
4276 | ARRAY_SIZE(ctlModesFor11a) - | ||
4277 | SUB_NUM_CTL_MODES_AT_5G_40; | ||
4278 | pCtlMode = ctlModesFor11a; | ||
4279 | |||
4280 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4281 | pEepData-> | ||
4282 | calTargetPower5G, | ||
4283 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
4284 | &targetPowerOfdm, 4, | ||
4285 | false); | ||
4286 | ath9k_hw_get_target_powers(ah, chan, | ||
4287 | pEepData->calTargetPower5GHT20, | ||
4288 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
4289 | &targetPowerHt20, 8, false); | ||
4290 | |||
4291 | if (IS_CHAN_HT40(chan)) { | ||
4292 | numCtlModes = ARRAY_SIZE(ctlModesFor11a); | ||
4293 | ath9k_hw_get_target_powers(ah, chan, | ||
4294 | pEepData-> | ||
4295 | calTargetPower5GHT40, | ||
4296 | AR5416_NUM_5G_40_TARGET_POWERS, | ||
4297 | &targetPowerHt40, 8, | ||
4298 | true); | ||
4299 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
4300 | pEepData-> | ||
4301 | calTargetPower5G, | ||
4302 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
4303 | &targetPowerOfdmExt, | ||
4304 | 4, true); | ||
4305 | } | ||
4306 | } | ||
4307 | |||
4308 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
4309 | bool isHt40CtlMode = | ||
4310 | (pCtlMode[ctlMode] == CTL_5GHT40) | ||
4311 | || (pCtlMode[ctlMode] == CTL_2GHT40); | ||
4312 | if (isHt40CtlMode) | ||
4313 | freq = centers.synth_center; | ||
4314 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
4315 | freq = centers.ext_center; | ||
4316 | else | ||
4317 | freq = centers.ctl_center; | ||
4318 | |||
4319 | if (ar5416_get_eep_ver(ahp) == 14 | ||
4320 | && ar5416_get_eep_rev(ahp) <= 2) | ||
4321 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
4322 | |||
4323 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
4324 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " | ||
4325 | "EXT_ADDITIVE %d\n", | ||
4326 | ctlMode, numCtlModes, isHt40CtlMode, | ||
4327 | (pCtlMode[ctlMode] & EXT_ADDITIVE)); | ||
4328 | |||
4329 | for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; | ||
4330 | i++) { | ||
4331 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
4332 | " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " | ||
4333 | "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " | ||
4334 | "chan %d\n", | ||
4335 | i, cfgCtl, pCtlMode[ctlMode], | ||
4336 | pEepData->ctlIndex[i], chan->channel); | ||
4337 | |||
4338 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
4339 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
4340 | pEepData->ctlIndex[i]) | ||
4341 | || | ||
4342 | (((cfgCtl & ~CTL_MODE_M) | | ||
4343 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
4344 | ((pEepData-> | ||
4345 | ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { | ||
4346 | rep = &(pEepData->ctlData[i]); | ||
4347 | |||
4348 | twiceMinEdgePower = | ||
4349 | ath9k_hw_get_max_edge_power(freq, | ||
4350 | rep-> | ||
4351 | ctlEdges | ||
4352 | [ar5416_get_ntxchains | ||
4353 | (tx_chainmask) | ||
4354 | - 1], | ||
4355 | IS_CHAN_2GHZ | ||
4356 | (chan)); | ||
4357 | |||
4358 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
4359 | " MATCH-EE_IDX %d: ch %d is2 %d " | ||
4360 | "2xMinEdge %d chainmask %d chains %d\n", | ||
4361 | i, freq, IS_CHAN_2GHZ(chan), | ||
4362 | twiceMinEdgePower, tx_chainmask, | ||
4363 | ar5416_get_ntxchains | ||
4364 | (tx_chainmask)); | ||
4365 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { | ||
4366 | twiceMaxEdgePower = | ||
4367 | min(twiceMaxEdgePower, | ||
4368 | twiceMinEdgePower); | ||
4369 | } else { | ||
4370 | twiceMaxEdgePower = | ||
4371 | twiceMinEdgePower; | ||
4372 | break; | ||
4373 | } | ||
4374 | } | ||
4375 | } | ||
4376 | |||
4377 | minCtlPower = min(twiceMaxEdgePower, scaledPower); | ||
4378 | |||
4379 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
4380 | " SEL-Min ctlMode %d pCtlMode %d " | ||
4381 | "2xMaxEdge %d sP %d minCtlPwr %d\n", | ||
4382 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, | ||
4383 | scaledPower, minCtlPower); | ||
4384 | |||
4385 | switch (pCtlMode[ctlMode]) { | ||
4386 | case CTL_11B: | ||
4387 | for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); | ||
4388 | i++) { | ||
4389 | targetPowerCck.tPow2x[i] = | ||
4390 | min(targetPowerCck.tPow2x[i], | ||
4391 | minCtlPower); | ||
4392 | } | ||
4393 | break; | ||
4394 | case CTL_11A: | ||
4395 | case CTL_11G: | ||
4396 | for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); | ||
4397 | i++) { | ||
4398 | targetPowerOfdm.tPow2x[i] = | ||
4399 | min(targetPowerOfdm.tPow2x[i], | ||
4400 | minCtlPower); | ||
4401 | } | ||
4402 | break; | ||
4403 | case CTL_5GHT20: | ||
4404 | case CTL_2GHT20: | ||
4405 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); | ||
4406 | i++) { | ||
4407 | targetPowerHt20.tPow2x[i] = | ||
4408 | min(targetPowerHt20.tPow2x[i], | ||
4409 | minCtlPower); | ||
4410 | } | ||
4411 | break; | ||
4412 | case CTL_11B_EXT: | ||
4413 | targetPowerCckExt.tPow2x[0] = | ||
4414 | min(targetPowerCckExt.tPow2x[0], minCtlPower); | ||
4415 | break; | ||
4416 | case CTL_11A_EXT: | ||
4417 | case CTL_11G_EXT: | ||
4418 | targetPowerOfdmExt.tPow2x[0] = | ||
4419 | min(targetPowerOfdmExt.tPow2x[0], minCtlPower); | ||
4420 | break; | ||
4421 | case CTL_5GHT40: | ||
4422 | case CTL_2GHT40: | ||
4423 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); | ||
4424 | i++) { | ||
4425 | targetPowerHt40.tPow2x[i] = | ||
4426 | min(targetPowerHt40.tPow2x[i], | ||
4427 | minCtlPower); | ||
4428 | } | ||
4429 | break; | ||
4430 | default: | ||
4431 | break; | ||
4432 | } | ||
4433 | } | ||
4434 | |||
4435 | ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = | ||
4436 | ratesArray[rate18mb] = ratesArray[rate24mb] = | ||
4437 | targetPowerOfdm.tPow2x[0]; | ||
4438 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
4439 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
4440 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
4441 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
4442 | |||
4443 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
4444 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
4445 | |||
4446 | if (IS_CHAN_2GHZ(chan)) { | ||
4447 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
4448 | ratesArray[rate2s] = ratesArray[rate2l] = | ||
4449 | targetPowerCck.tPow2x[1]; | ||
4450 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = | ||
4451 | targetPowerCck.tPow2x[2]; | ||
4452 | ; | ||
4453 | ratesArray[rate11s] = ratesArray[rate11l] = | ||
4454 | targetPowerCck.tPow2x[3]; | ||
4455 | ; | ||
4456 | } | ||
4457 | if (IS_CHAN_HT40(chan)) { | ||
4458 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
4459 | ratesArray[rateHt40_0 + i] = | ||
4460 | targetPowerHt40.tPow2x[i]; | ||
4461 | } | ||
4462 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
4463 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
4464 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
4465 | if (IS_CHAN_2GHZ(chan)) { | ||
4466 | ratesArray[rateExtCck] = | ||
4467 | targetPowerCckExt.tPow2x[0]; | ||
4468 | } | ||
4469 | } | ||
4470 | return true; | ||
4471 | } | ||
4472 | |||
4473 | static int | ||
4474 | ath9k_hw_set_txpower(struct ath_hal *ah, | ||
4475 | struct ar5416_eeprom *pEepData, | ||
4476 | struct ath9k_channel *chan, | ||
4477 | u16 cfgCtl, | ||
4478 | u8 twiceAntennaReduction, | ||
4479 | u8 twiceMaxRegulatoryPower, | ||
4480 | u8 powerLimit) | ||
4481 | { | ||
4482 | struct modal_eep_header *pModal = | ||
4483 | &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
4484 | int16_t ratesArray[Ar5416RateSize]; | ||
4485 | int16_t txPowerIndexOffset = 0; | ||
4486 | u8 ht40PowerIncForPdadc = 2; | ||
4487 | int i; | ||
4488 | |||
4489 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
4490 | |||
4491 | if ((pEepData->baseEepHeader. | ||
4492 | version & AR5416_EEP_VER_MINOR_MASK) >= | ||
4493 | AR5416_EEP_MINOR_VER_2) { | ||
4494 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
4495 | } | ||
4496 | |||
4497 | if (!ath9k_hw_set_power_per_rate_table(ah, pEepData, chan, | ||
4498 | &ratesArray[0], cfgCtl, | ||
4499 | twiceAntennaReduction, | ||
4500 | twiceMaxRegulatoryPower, | ||
4501 | powerLimit)) { | ||
4502 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
4503 | "ath9k_hw_set_txpower: unable to set " | ||
4504 | "tx power per rate table\n"); | ||
4505 | return -EIO; | ||
4506 | } | ||
4507 | |||
4508 | if (!ath9k_hw_set_power_cal_table | ||
4509 | (ah, pEepData, chan, &txPowerIndexOffset)) { | ||
4510 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
4511 | "ath9k_hw_set_txpower: unable to set power table\n"); | ||
4512 | return -EIO; | ||
4513 | } | ||
4514 | |||
4515 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
4516 | ratesArray[i] = | ||
4517 | (int16_t) (txPowerIndexOffset + ratesArray[i]); | ||
4518 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) | ||
4519 | ratesArray[i] = AR5416_MAX_RATE_POWER; | ||
4520 | } | ||
4521 | |||
4522 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
4523 | for (i = 0; i < Ar5416RateSize; i++) | ||
4524 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | ||
4525 | } | ||
4526 | |||
4527 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
4528 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
4529 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
4530 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
4531 | | ATH9K_POW_SM(ratesArray[rate6mb], 0) | ||
4532 | ); | ||
4533 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
4534 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
4535 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
4536 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
4537 | | ATH9K_POW_SM(ratesArray[rate24mb], 0) | ||
4538 | ); | ||
4539 | |||
4540 | if (IS_CHAN_2GHZ(chan)) { | ||
4541 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
4542 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
4543 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
4544 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
4545 | | ATH9K_POW_SM(ratesArray[rate1l], 0) | ||
4546 | ); | ||
4547 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
4548 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
4549 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
4550 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
4551 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0) | ||
4552 | ); | ||
4553 | } | ||
4554 | |||
4555 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
4556 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
4557 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
4558 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
4559 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0) | ||
4560 | ); | ||
4561 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
4562 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
4563 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
4564 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
4565 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0) | ||
4566 | ); | ||
4567 | |||
4568 | if (IS_CHAN_HT40(chan)) { | ||
4569 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
4570 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
4571 | ht40PowerIncForPdadc, 24) | ||
4572 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
4573 | ht40PowerIncForPdadc, 16) | ||
4574 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
4575 | ht40PowerIncForPdadc, 8) | ||
4576 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
4577 | ht40PowerIncForPdadc, 0) | ||
4578 | ); | ||
4579 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
4580 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
4581 | ht40PowerIncForPdadc, 24) | ||
4582 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
4583 | ht40PowerIncForPdadc, 16) | ||
4584 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
4585 | ht40PowerIncForPdadc, 8) | ||
4586 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
4587 | ht40PowerIncForPdadc, 0) | ||
4588 | ); | ||
4589 | |||
4590 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
4591 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
4592 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
4593 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
4594 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0) | ||
4595 | ); | ||
4596 | } | ||
4597 | |||
4598 | REG_WRITE(ah, AR_PHY_POWER_TX_SUB, | ||
4599 | ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | ||
4600 | | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0) | ||
4601 | ); | ||
4602 | |||
4603 | i = rate6mb; | ||
4604 | if (IS_CHAN_HT40(chan)) | ||
4605 | i = rateHt40_0; | ||
4606 | else if (IS_CHAN_HT20(chan)) | ||
4607 | i = rateHt20_0; | ||
4608 | |||
4609 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
4610 | ah->ah_maxPowerLevel = | ||
4611 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; | ||
4612 | else | ||
4613 | ah->ah_maxPowerLevel = ratesArray[i]; | ||
4614 | |||
4615 | return 0; | ||
4616 | } | ||
4617 | |||
4618 | static inline void ath9k_hw_get_delta_slope_vals(struct ath_hal *ah, | ||
4619 | u32 coef_scaled, | ||
4620 | u32 *coef_mantissa, | ||
4621 | u32 *coef_exponent) | ||
4622 | { | ||
4623 | u32 coef_exp, coef_man; | ||
4624 | |||
4625 | for (coef_exp = 31; coef_exp > 0; coef_exp--) | ||
4626 | if ((coef_scaled >> coef_exp) & 0x1) | ||
4627 | break; | ||
4628 | |||
4629 | coef_exp = 14 - (coef_exp - COEF_SCALE_S); | ||
4630 | |||
4631 | coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); | ||
4632 | |||
4633 | *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp); | ||
4634 | *coef_exponent = coef_exp - 16; | ||
4635 | } | ||
4636 | |||
4637 | static void | ||
4638 | ath9k_hw_set_delta_slope(struct ath_hal *ah, | ||
4639 | struct ath9k_channel *chan) | ||
4640 | { | ||
4641 | u32 coef_scaled, ds_coef_exp, ds_coef_man; | ||
4642 | u32 clockMhzScaled = 0x64000000; | ||
4643 | struct chan_centers centers; | ||
4644 | |||
4645 | if (IS_CHAN_HALF_RATE(chan)) | ||
4646 | clockMhzScaled = clockMhzScaled >> 1; | ||
4647 | else if (IS_CHAN_QUARTER_RATE(chan)) | ||
4648 | clockMhzScaled = clockMhzScaled >> 2; | ||
4649 | |||
4650 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
4651 | coef_scaled = clockMhzScaled / centers.synth_center; | ||
4652 | |||
4653 | ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, | ||
4654 | &ds_coef_exp); | ||
4655 | |||
4656 | REG_RMW_FIELD(ah, AR_PHY_TIMING3, | ||
4657 | AR_PHY_TIMING3_DSC_MAN, ds_coef_man); | ||
4658 | REG_RMW_FIELD(ah, AR_PHY_TIMING3, | ||
4659 | AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); | ||
4660 | |||
4661 | coef_scaled = (9 * coef_scaled) / 10; | ||
4662 | |||
4663 | ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, | ||
4664 | &ds_coef_exp); | ||
4665 | |||
4666 | REG_RMW_FIELD(ah, AR_PHY_HALFGI, | ||
4667 | AR_PHY_HALFGI_DSC_MAN, ds_coef_man); | ||
4668 | REG_RMW_FIELD(ah, AR_PHY_HALFGI, | ||
4669 | AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); | ||
4670 | } | ||
4671 | |||
4672 | static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, | ||
4673 | struct ath9k_channel *chan) | ||
4674 | { | ||
4675 | int bb_spur = AR_NO_SPUR; | ||
4676 | int freq; | ||
4677 | int bin, cur_bin; | ||
4678 | int bb_spur_off, spur_subchannel_sd; | ||
4679 | int spur_freq_sd; | ||
4680 | int spur_delta_phase; | ||
4681 | int denominator; | ||
4682 | int upper, lower, cur_vit_mask; | ||
4683 | int tmp, newVal; | ||
4684 | int i; | ||
4685 | int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, | ||
4686 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | ||
4687 | }; | ||
4688 | int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, | ||
4689 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | ||
4690 | }; | ||
4691 | int inc[4] = { 0, 100, 0, 0 }; | ||
4692 | struct chan_centers centers; | ||
4693 | |||
4694 | int8_t mask_m[123]; | ||
4695 | int8_t mask_p[123]; | ||
4696 | int8_t mask_amt; | ||
4697 | int tmp_mask; | ||
4698 | int cur_bb_spur; | ||
4699 | bool is2GHz = IS_CHAN_2GHZ(chan); | ||
4700 | |||
4701 | memset(&mask_m, 0, sizeof(int8_t) * 123); | ||
4702 | memset(&mask_p, 0, sizeof(int8_t) * 123); | ||
4703 | |||
4704 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
4705 | freq = centers.synth_center; | ||
4706 | |||
4707 | ah->ah_config.spurmode = SPUR_ENABLE_EEPROM; | ||
4708 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | ||
4709 | cur_bb_spur = ath9k_hw_eeprom_get_spur_chan(ah, i, is2GHz); | ||
4710 | |||
4711 | if (is2GHz) | ||
4712 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; | ||
4713 | else | ||
4714 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; | ||
4715 | |||
4716 | if (AR_NO_SPUR == cur_bb_spur) | ||
4717 | break; | ||
4718 | cur_bb_spur = cur_bb_spur - freq; | ||
4719 | |||
4720 | if (IS_CHAN_HT40(chan)) { | ||
4721 | if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && | ||
4722 | (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { | ||
4723 | bb_spur = cur_bb_spur; | ||
4724 | break; | ||
4725 | } | ||
4726 | } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && | ||
4727 | (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { | ||
4728 | bb_spur = cur_bb_spur; | ||
4729 | break; | ||
4730 | } | ||
4731 | } | ||
4732 | |||
4733 | if (AR_NO_SPUR == bb_spur) { | ||
4734 | REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, | ||
4735 | AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); | ||
4736 | return; | ||
4737 | } else { | ||
4738 | REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, | ||
4739 | AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); | ||
4740 | } | ||
4741 | |||
4742 | bin = bb_spur * 320; | ||
4743 | |||
4744 | tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); | ||
4745 | |||
4746 | newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | | ||
4747 | AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | | ||
4748 | AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | | ||
4749 | AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); | ||
4750 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); | ||
4751 | |||
4752 | newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | | ||
4753 | AR_PHY_SPUR_REG_ENABLE_MASK_PPM | | ||
4754 | AR_PHY_SPUR_REG_MASK_RATE_SELECT | | ||
4755 | AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | | ||
4756 | SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); | ||
4757 | REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); | ||
4758 | |||
4759 | if (IS_CHAN_HT40(chan)) { | ||
4760 | if (bb_spur < 0) { | ||
4761 | spur_subchannel_sd = 1; | ||
4762 | bb_spur_off = bb_spur + 10; | ||
4763 | } else { | ||
4764 | spur_subchannel_sd = 0; | ||
4765 | bb_spur_off = bb_spur - 10; | ||
4766 | } | ||
4767 | } else { | ||
4768 | spur_subchannel_sd = 0; | ||
4769 | bb_spur_off = bb_spur; | ||
4770 | } | ||
4771 | |||
4772 | if (IS_CHAN_HT40(chan)) | ||
4773 | spur_delta_phase = | ||
4774 | ((bb_spur * 262144) / | ||
4775 | 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; | ||
4776 | else | ||
4777 | spur_delta_phase = | ||
4778 | ((bb_spur * 524288) / | ||
4779 | 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; | ||
4780 | |||
4781 | denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; | ||
4782 | spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; | ||
4783 | |||
4784 | newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | | ||
4785 | SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | | ||
4786 | SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); | ||
4787 | REG_WRITE(ah, AR_PHY_TIMING11, newVal); | ||
4788 | |||
4789 | newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; | ||
4790 | REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); | ||
4791 | |||
4792 | cur_bin = -6000; | ||
4793 | upper = bin + 100; | ||
4794 | lower = bin - 100; | ||
4795 | |||
4796 | for (i = 0; i < 4; i++) { | ||
4797 | int pilot_mask = 0; | ||
4798 | int chan_mask = 0; | ||
4799 | int bp = 0; | ||
4800 | for (bp = 0; bp < 30; bp++) { | ||
4801 | if ((cur_bin > lower) && (cur_bin < upper)) { | ||
4802 | pilot_mask = pilot_mask | 0x1 << bp; | ||
4803 | chan_mask = chan_mask | 0x1 << bp; | ||
4804 | } | ||
4805 | cur_bin += 100; | ||
4806 | } | ||
4807 | cur_bin += inc[i]; | ||
4808 | REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); | ||
4809 | REG_WRITE(ah, chan_mask_reg[i], chan_mask); | ||
4810 | } | ||
4811 | |||
4812 | cur_vit_mask = 6100; | ||
4813 | upper = bin + 120; | ||
4814 | lower = bin - 120; | ||
4815 | |||
4816 | for (i = 0; i < 123; i++) { | ||
4817 | if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { | ||
4818 | |||
4819 | /* workaround for gcc bug #37014 */ | ||
4820 | volatile int tmp = abs(cur_vit_mask - bin); | ||
4821 | |||
4822 | if (tmp < 75) | ||
4823 | mask_amt = 1; | ||
4824 | else | ||
4825 | mask_amt = 0; | ||
4826 | if (cur_vit_mask < 0) | ||
4827 | mask_m[abs(cur_vit_mask / 100)] = mask_amt; | ||
4828 | else | ||
4829 | mask_p[cur_vit_mask / 100] = mask_amt; | ||
4830 | } | ||
4831 | cur_vit_mask -= 100; | ||
4832 | } | ||
4833 | |||
4834 | tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) | ||
4835 | | (mask_m[48] << 26) | (mask_m[49] << 24) | ||
4836 | | (mask_m[50] << 22) | (mask_m[51] << 20) | ||
4837 | | (mask_m[52] << 18) | (mask_m[53] << 16) | ||
4838 | | (mask_m[54] << 14) | (mask_m[55] << 12) | ||
4839 | | (mask_m[56] << 10) | (mask_m[57] << 8) | ||
4840 | | (mask_m[58] << 6) | (mask_m[59] << 4) | ||
4841 | | (mask_m[60] << 2) | (mask_m[61] << 0); | ||
4842 | REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); | ||
4843 | REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); | ||
4844 | |||
4845 | tmp_mask = (mask_m[31] << 28) | ||
4846 | | (mask_m[32] << 26) | (mask_m[33] << 24) | ||
4847 | | (mask_m[34] << 22) | (mask_m[35] << 20) | ||
4848 | | (mask_m[36] << 18) | (mask_m[37] << 16) | ||
4849 | | (mask_m[48] << 14) | (mask_m[39] << 12) | ||
4850 | | (mask_m[40] << 10) | (mask_m[41] << 8) | ||
4851 | | (mask_m[42] << 6) | (mask_m[43] << 4) | ||
4852 | | (mask_m[44] << 2) | (mask_m[45] << 0); | ||
4853 | REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); | ||
4854 | REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); | ||
4855 | |||
4856 | tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) | ||
4857 | | (mask_m[18] << 26) | (mask_m[18] << 24) | ||
4858 | | (mask_m[20] << 22) | (mask_m[20] << 20) | ||
4859 | | (mask_m[22] << 18) | (mask_m[22] << 16) | ||
4860 | | (mask_m[24] << 14) | (mask_m[24] << 12) | ||
4861 | | (mask_m[25] << 10) | (mask_m[26] << 8) | ||
4862 | | (mask_m[27] << 6) | (mask_m[28] << 4) | ||
4863 | | (mask_m[29] << 2) | (mask_m[30] << 0); | ||
4864 | REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); | ||
4865 | REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); | ||
4866 | |||
4867 | tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) | ||
4868 | | (mask_m[2] << 26) | (mask_m[3] << 24) | ||
4869 | | (mask_m[4] << 22) | (mask_m[5] << 20) | ||
4870 | | (mask_m[6] << 18) | (mask_m[7] << 16) | ||
4871 | | (mask_m[8] << 14) | (mask_m[9] << 12) | ||
4872 | | (mask_m[10] << 10) | (mask_m[11] << 8) | ||
4873 | | (mask_m[12] << 6) | (mask_m[13] << 4) | ||
4874 | | (mask_m[14] << 2) | (mask_m[15] << 0); | ||
4875 | REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); | ||
4876 | REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); | ||
4877 | |||
4878 | tmp_mask = (mask_p[15] << 28) | ||
4879 | | (mask_p[14] << 26) | (mask_p[13] << 24) | ||
4880 | | (mask_p[12] << 22) | (mask_p[11] << 20) | ||
4881 | | (mask_p[10] << 18) | (mask_p[9] << 16) | ||
4882 | | (mask_p[8] << 14) | (mask_p[7] << 12) | ||
4883 | | (mask_p[6] << 10) | (mask_p[5] << 8) | ||
4884 | | (mask_p[4] << 6) | (mask_p[3] << 4) | ||
4885 | | (mask_p[2] << 2) | (mask_p[1] << 0); | ||
4886 | REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); | ||
4887 | REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); | ||
4888 | |||
4889 | tmp_mask = (mask_p[30] << 28) | ||
4890 | | (mask_p[29] << 26) | (mask_p[28] << 24) | ||
4891 | | (mask_p[27] << 22) | (mask_p[26] << 20) | ||
4892 | | (mask_p[25] << 18) | (mask_p[24] << 16) | ||
4893 | | (mask_p[23] << 14) | (mask_p[22] << 12) | ||
4894 | | (mask_p[21] << 10) | (mask_p[20] << 8) | ||
4895 | | (mask_p[19] << 6) | (mask_p[18] << 4) | ||
4896 | | (mask_p[17] << 2) | (mask_p[16] << 0); | ||
4897 | REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); | ||
4898 | REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); | ||
4899 | |||
4900 | tmp_mask = (mask_p[45] << 28) | ||
4901 | | (mask_p[44] << 26) | (mask_p[43] << 24) | ||
4902 | | (mask_p[42] << 22) | (mask_p[41] << 20) | ||
4903 | | (mask_p[40] << 18) | (mask_p[39] << 16) | ||
4904 | | (mask_p[38] << 14) | (mask_p[37] << 12) | ||
4905 | | (mask_p[36] << 10) | (mask_p[35] << 8) | ||
4906 | | (mask_p[34] << 6) | (mask_p[33] << 4) | ||
4907 | | (mask_p[32] << 2) | (mask_p[31] << 0); | ||
4908 | REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); | ||
4909 | REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); | ||
4910 | |||
4911 | tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) | ||
4912 | | (mask_p[59] << 26) | (mask_p[58] << 24) | ||
4913 | | (mask_p[57] << 22) | (mask_p[56] << 20) | ||
4914 | | (mask_p[55] << 18) | (mask_p[54] << 16) | ||
4915 | | (mask_p[53] << 14) | (mask_p[52] << 12) | ||
4916 | | (mask_p[51] << 10) | (mask_p[50] << 8) | ||
4917 | | (mask_p[49] << 6) | (mask_p[48] << 4) | ||
4918 | | (mask_p[47] << 2) | (mask_p[46] << 0); | ||
4919 | REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); | ||
4920 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); | ||
4921 | } | ||
4922 | |||
4923 | static void ath9k_hw_spur_mitigate(struct ath_hal *ah, | ||
4924 | struct ath9k_channel *chan) | ||
4925 | { | ||
4926 | int bb_spur = AR_NO_SPUR; | ||
4927 | int bin, cur_bin; | ||
4928 | int spur_freq_sd; | ||
4929 | int spur_delta_phase; | ||
4930 | int denominator; | ||
4931 | int upper, lower, cur_vit_mask; | ||
4932 | int tmp, new; | ||
4933 | int i; | ||
4934 | int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, | ||
4935 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | ||
4936 | }; | ||
4937 | int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, | ||
4938 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | ||
4939 | }; | ||
4940 | int inc[4] = { 0, 100, 0, 0 }; | ||
4941 | |||
4942 | int8_t mask_m[123]; | ||
4943 | int8_t mask_p[123]; | ||
4944 | int8_t mask_amt; | ||
4945 | int tmp_mask; | ||
4946 | int cur_bb_spur; | ||
4947 | bool is2GHz = IS_CHAN_2GHZ(chan); | ||
4948 | |||
4949 | memset(&mask_m, 0, sizeof(int8_t) * 123); | ||
4950 | memset(&mask_p, 0, sizeof(int8_t) * 123); | ||
4951 | |||
4952 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | ||
4953 | cur_bb_spur = ath9k_hw_eeprom_get_spur_chan(ah, i, is2GHz); | ||
4954 | if (AR_NO_SPUR == cur_bb_spur) | ||
4955 | break; | ||
4956 | cur_bb_spur = cur_bb_spur - (chan->channel * 10); | ||
4957 | if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { | ||
4958 | bb_spur = cur_bb_spur; | ||
4959 | break; | ||
4960 | } | ||
4961 | } | ||
4962 | |||
4963 | if (AR_NO_SPUR == bb_spur) | ||
4964 | return; | ||
4965 | |||
4966 | bin = bb_spur * 32; | ||
4967 | |||
4968 | tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); | ||
4969 | new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | | ||
4970 | AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | | ||
4971 | AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | | ||
4972 | AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); | ||
4973 | |||
4974 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); | ||
4975 | |||
4976 | new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | | ||
4977 | AR_PHY_SPUR_REG_ENABLE_MASK_PPM | | ||
4978 | AR_PHY_SPUR_REG_MASK_RATE_SELECT | | ||
4979 | AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | | ||
4980 | SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); | ||
4981 | REG_WRITE(ah, AR_PHY_SPUR_REG, new); | ||
4982 | |||
4983 | spur_delta_phase = ((bb_spur * 524288) / 100) & | ||
4984 | AR_PHY_TIMING11_SPUR_DELTA_PHASE; | ||
4985 | |||
4986 | denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; | ||
4987 | spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; | ||
4988 | |||
4989 | new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | | ||
4990 | SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | | ||
4991 | SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); | ||
4992 | REG_WRITE(ah, AR_PHY_TIMING11, new); | ||
4993 | |||
4994 | cur_bin = -6000; | ||
4995 | upper = bin + 100; | ||
4996 | lower = bin - 100; | ||
4997 | |||
4998 | for (i = 0; i < 4; i++) { | ||
4999 | int pilot_mask = 0; | ||
5000 | int chan_mask = 0; | ||
5001 | int bp = 0; | ||
5002 | for (bp = 0; bp < 30; bp++) { | ||
5003 | if ((cur_bin > lower) && (cur_bin < upper)) { | ||
5004 | pilot_mask = pilot_mask | 0x1 << bp; | ||
5005 | chan_mask = chan_mask | 0x1 << bp; | ||
5006 | } | ||
5007 | cur_bin += 100; | ||
5008 | } | ||
5009 | cur_bin += inc[i]; | ||
5010 | REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); | ||
5011 | REG_WRITE(ah, chan_mask_reg[i], chan_mask); | ||
5012 | } | ||
5013 | |||
5014 | cur_vit_mask = 6100; | ||
5015 | upper = bin + 120; | ||
5016 | lower = bin - 120; | ||
5017 | |||
5018 | for (i = 0; i < 123; i++) { | ||
5019 | if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { | ||
5020 | if ((abs(cur_vit_mask - bin)) < 75) | ||
5021 | mask_amt = 1; | ||
5022 | else | ||
5023 | mask_amt = 0; | ||
5024 | if (cur_vit_mask < 0) | ||
5025 | mask_m[abs(cur_vit_mask / 100)] = mask_amt; | ||
5026 | else | ||
5027 | mask_p[cur_vit_mask / 100] = mask_amt; | ||
5028 | } | ||
5029 | cur_vit_mask -= 100; | ||
5030 | } | ||
5031 | |||
5032 | tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) | ||
5033 | | (mask_m[48] << 26) | (mask_m[49] << 24) | ||
5034 | | (mask_m[50] << 22) | (mask_m[51] << 20) | ||
5035 | | (mask_m[52] << 18) | (mask_m[53] << 16) | ||
5036 | | (mask_m[54] << 14) | (mask_m[55] << 12) | ||
5037 | | (mask_m[56] << 10) | (mask_m[57] << 8) | ||
5038 | | (mask_m[58] << 6) | (mask_m[59] << 4) | ||
5039 | | (mask_m[60] << 2) | (mask_m[61] << 0); | ||
5040 | REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); | ||
5041 | REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); | ||
5042 | |||
5043 | tmp_mask = (mask_m[31] << 28) | ||
5044 | | (mask_m[32] << 26) | (mask_m[33] << 24) | ||
5045 | | (mask_m[34] << 22) | (mask_m[35] << 20) | ||
5046 | | (mask_m[36] << 18) | (mask_m[37] << 16) | ||
5047 | | (mask_m[48] << 14) | (mask_m[39] << 12) | ||
5048 | | (mask_m[40] << 10) | (mask_m[41] << 8) | ||
5049 | | (mask_m[42] << 6) | (mask_m[43] << 4) | ||
5050 | | (mask_m[44] << 2) | (mask_m[45] << 0); | ||
5051 | REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); | ||
5052 | REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); | ||
5053 | |||
5054 | tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) | ||
5055 | | (mask_m[18] << 26) | (mask_m[18] << 24) | ||
5056 | | (mask_m[20] << 22) | (mask_m[20] << 20) | ||
5057 | | (mask_m[22] << 18) | (mask_m[22] << 16) | ||
5058 | | (mask_m[24] << 14) | (mask_m[24] << 12) | ||
5059 | | (mask_m[25] << 10) | (mask_m[26] << 8) | ||
5060 | | (mask_m[27] << 6) | (mask_m[28] << 4) | ||
5061 | | (mask_m[29] << 2) | (mask_m[30] << 0); | ||
5062 | REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); | ||
5063 | REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); | ||
5064 | |||
5065 | tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) | ||
5066 | | (mask_m[2] << 26) | (mask_m[3] << 24) | ||
5067 | | (mask_m[4] << 22) | (mask_m[5] << 20) | ||
5068 | | (mask_m[6] << 18) | (mask_m[7] << 16) | ||
5069 | | (mask_m[8] << 14) | (mask_m[9] << 12) | ||
5070 | | (mask_m[10] << 10) | (mask_m[11] << 8) | ||
5071 | | (mask_m[12] << 6) | (mask_m[13] << 4) | ||
5072 | | (mask_m[14] << 2) | (mask_m[15] << 0); | ||
5073 | REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); | ||
5074 | REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); | ||
5075 | |||
5076 | tmp_mask = (mask_p[15] << 28) | ||
5077 | | (mask_p[14] << 26) | (mask_p[13] << 24) | ||
5078 | | (mask_p[12] << 22) | (mask_p[11] << 20) | ||
5079 | | (mask_p[10] << 18) | (mask_p[9] << 16) | ||
5080 | | (mask_p[8] << 14) | (mask_p[7] << 12) | ||
5081 | | (mask_p[6] << 10) | (mask_p[5] << 8) | ||
5082 | | (mask_p[4] << 6) | (mask_p[3] << 4) | ||
5083 | | (mask_p[2] << 2) | (mask_p[1] << 0); | ||
5084 | REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); | ||
5085 | REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); | ||
5086 | |||
5087 | tmp_mask = (mask_p[30] << 28) | ||
5088 | | (mask_p[29] << 26) | (mask_p[28] << 24) | ||
5089 | | (mask_p[27] << 22) | (mask_p[26] << 20) | ||
5090 | | (mask_p[25] << 18) | (mask_p[24] << 16) | ||
5091 | | (mask_p[23] << 14) | (mask_p[22] << 12) | ||
5092 | | (mask_p[21] << 10) | (mask_p[20] << 8) | ||
5093 | | (mask_p[19] << 6) | (mask_p[18] << 4) | ||
5094 | | (mask_p[17] << 2) | (mask_p[16] << 0); | ||
5095 | REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); | ||
5096 | REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); | ||
5097 | |||
5098 | tmp_mask = (mask_p[45] << 28) | ||
5099 | | (mask_p[44] << 26) | (mask_p[43] << 24) | ||
5100 | | (mask_p[42] << 22) | (mask_p[41] << 20) | ||
5101 | | (mask_p[40] << 18) | (mask_p[39] << 16) | ||
5102 | | (mask_p[38] << 14) | (mask_p[37] << 12) | ||
5103 | | (mask_p[36] << 10) | (mask_p[35] << 8) | ||
5104 | | (mask_p[34] << 6) | (mask_p[33] << 4) | ||
5105 | | (mask_p[32] << 2) | (mask_p[31] << 0); | ||
5106 | REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); | ||
5107 | REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); | ||
5108 | |||
5109 | tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) | ||
5110 | | (mask_p[59] << 26) | (mask_p[58] << 24) | ||
5111 | | (mask_p[57] << 22) | (mask_p[56] << 20) | ||
5112 | | (mask_p[55] << 18) | (mask_p[54] << 16) | ||
5113 | | (mask_p[53] << 14) | (mask_p[52] << 12) | ||
5114 | | (mask_p[51] << 10) | (mask_p[50] << 8) | ||
5115 | | (mask_p[49] << 6) | (mask_p[48] << 4) | ||
5116 | | (mask_p[47] << 2) | (mask_p[46] << 0); | ||
5117 | REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); | ||
5118 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); | ||
5119 | } | ||
5120 | |||
5121 | static inline void ath9k_hw_init_chain_masks(struct ath_hal *ah) | ||
5122 | { | ||
5123 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5124 | int rx_chainmask, tx_chainmask; | ||
5125 | |||
5126 | rx_chainmask = ahp->ah_rxchainmask; | ||
5127 | tx_chainmask = ahp->ah_txchainmask; | ||
5128 | |||
5129 | switch (rx_chainmask) { | ||
5130 | case 0x5: | ||
5131 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | ||
5132 | AR_PHY_SWAP_ALT_CHAIN); | ||
5133 | case 0x3: | ||
5134 | if (((ah)->ah_macVersion <= AR_SREV_VERSION_9160)) { | ||
5135 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); | ||
5136 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); | ||
5137 | break; | ||
5138 | } | ||
5139 | case 0x1: | ||
5140 | case 0x2: | ||
5141 | if (!AR_SREV_9280(ah)) | ||
5142 | break; | ||
5143 | case 0x7: | ||
5144 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); | ||
5145 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); | ||
5146 | break; | ||
5147 | default: | ||
5148 | break; | ||
5149 | } | ||
5150 | |||
5151 | REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); | ||
5152 | if (tx_chainmask == 0x5) { | ||
5153 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | ||
5154 | AR_PHY_SWAP_ALT_CHAIN); | ||
5155 | } | ||
5156 | if (AR_SREV_9100(ah)) | ||
5157 | REG_WRITE(ah, AR_PHY_ANALOG_SWAP, | ||
5158 | REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); | ||
5159 | } | ||
5160 | |||
5161 | static void ath9k_hw_set_addac(struct ath_hal *ah, | ||
5162 | struct ath9k_channel *chan) | ||
5163 | { | ||
5164 | struct modal_eep_header *pModal; | ||
5165 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5166 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; | ||
5167 | u8 biaslevel; | ||
5168 | |||
5169 | if (ah->ah_macVersion != AR_SREV_VERSION_9160) | ||
5170 | return; | ||
5171 | |||
5172 | if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7) | ||
5173 | return; | ||
5174 | |||
5175 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
5176 | |||
5177 | if (pModal->xpaBiasLvl != 0xff) { | ||
5178 | biaslevel = pModal->xpaBiasLvl; | ||
5179 | } else { | ||
5180 | |||
5181 | u16 resetFreqBin, freqBin, freqCount = 0; | ||
5182 | struct chan_centers centers; | ||
5183 | |||
5184 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
5185 | |||
5186 | resetFreqBin = | ||
5187 | FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)); | ||
5188 | freqBin = pModal->xpaBiasLvlFreq[0] & 0xff; | ||
5189 | biaslevel = (u8) (pModal->xpaBiasLvlFreq[0] >> 14); | ||
5190 | |||
5191 | freqCount++; | ||
5192 | |||
5193 | while (freqCount < 3) { | ||
5194 | if (pModal->xpaBiasLvlFreq[freqCount] == 0x0) | ||
5195 | break; | ||
5196 | |||
5197 | freqBin = pModal->xpaBiasLvlFreq[freqCount] & 0xff; | ||
5198 | if (resetFreqBin >= freqBin) { | ||
5199 | biaslevel = | ||
5200 | (u8) (pModal-> | ||
5201 | xpaBiasLvlFreq[freqCount] | ||
5202 | >> 14); | ||
5203 | } else { | ||
5204 | break; | ||
5205 | } | ||
5206 | freqCount++; | ||
5207 | } | ||
5208 | } | ||
5209 | |||
5210 | if (IS_CHAN_2GHZ(chan)) { | ||
5211 | INI_RA(&ahp->ah_iniAddac, 7, 1) = | ||
5212 | (INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) | biaslevel | ||
5213 | << 3; | ||
5214 | } else { | ||
5215 | INI_RA(&ahp->ah_iniAddac, 6, 1) = | ||
5216 | (INI_RA(&ahp->ah_iniAddac, 6, 1) & (~0xc0)) | biaslevel | ||
5217 | << 6; | ||
5218 | } | ||
5219 | } | ||
5220 | |||
5221 | static u32 ath9k_hw_mac_usec(struct ath_hal *ah, u32 clks) | ||
5222 | { | ||
5223 | if (ah->ah_curchan != NULL) | ||
5224 | return clks / | ||
5225 | CLOCK_RATE[ath9k_hw_chan2wmode(ah, ah->ah_curchan)]; | ||
5226 | else | ||
5227 | return clks / CLOCK_RATE[ATH9K_MODE_11B]; | ||
5228 | } | ||
5229 | |||
5230 | static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks) | ||
5231 | { | ||
5232 | struct ath9k_channel *chan = ah->ah_curchan; | ||
5233 | |||
5234 | if (chan && IS_CHAN_HT40(chan)) | ||
5235 | return ath9k_hw_mac_usec(ah, clks) / 2; | ||
5236 | else | ||
5237 | return ath9k_hw_mac_usec(ah, clks); | ||
5238 | } | ||
5239 | |||
5240 | static u32 ath9k_hw_mac_clks(struct ath_hal *ah, u32 usecs) | ||
5241 | { | ||
5242 | if (ah->ah_curchan != NULL) | ||
5243 | return usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah, | ||
5244 | ah->ah_curchan)]; | ||
5245 | else | ||
5246 | return usecs * CLOCK_RATE[ATH9K_MODE_11B]; | ||
5247 | } | ||
5248 | |||
5249 | static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs) | ||
5250 | { | ||
5251 | struct ath9k_channel *chan = ah->ah_curchan; | ||
5252 | |||
5253 | if (chan && IS_CHAN_HT40(chan)) | ||
5254 | return ath9k_hw_mac_clks(ah, usecs) * 2; | ||
5255 | else | ||
5256 | return ath9k_hw_mac_clks(ah, usecs); | ||
5257 | } | ||
5258 | |||
5259 | static bool ath9k_hw_set_ack_timeout(struct ath_hal *ah, u32 us) | ||
5260 | { | ||
5261 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5262 | |||
5263 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { | ||
5264 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad ack timeout %u\n", | ||
5265 | __func__, us); | ||
5266 | ahp->ah_acktimeout = (u32) -1; | ||
5267 | return false; | ||
5268 | } else { | ||
5269 | REG_RMW_FIELD(ah, AR_TIME_OUT, | ||
5270 | AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us)); | ||
5271 | ahp->ah_acktimeout = us; | ||
5272 | return true; | ||
5273 | } | ||
5274 | } | ||
5275 | |||
5276 | static bool ath9k_hw_set_cts_timeout(struct ath_hal *ah, u32 us) | ||
5277 | { | ||
5278 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5279 | |||
5280 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { | ||
5281 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad cts timeout %u\n", | ||
5282 | __func__, us); | ||
5283 | ahp->ah_ctstimeout = (u32) -1; | ||
5284 | return false; | ||
5285 | } else { | ||
5286 | REG_RMW_FIELD(ah, AR_TIME_OUT, | ||
5287 | AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); | ||
5288 | ahp->ah_ctstimeout = us; | ||
5289 | return true; | ||
5290 | } | ||
5291 | } | ||
5292 | static bool ath9k_hw_set_global_txtimeout(struct ath_hal *ah, | ||
5293 | u32 tu) | ||
5294 | { | ||
5295 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5296 | |||
5297 | if (tu > 0xFFFF) { | ||
5298 | DPRINTF(ah->ah_sc, ATH_DBG_XMIT, | ||
5299 | "%s: bad global tx timeout %u\n", __func__, tu); | ||
5300 | ahp->ah_globaltxtimeout = (u32) -1; | ||
5301 | return false; | ||
5302 | } else { | ||
5303 | REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu); | ||
5304 | ahp->ah_globaltxtimeout = tu; | ||
5305 | return true; | ||
5306 | } | ||
5307 | } | ||
5308 | |||
5309 | bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us) | ||
5310 | { | ||
5311 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5312 | |||
5313 | if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { | ||
5314 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad slot time %u\n", | ||
5315 | __func__, us); | ||
5316 | ahp->ah_slottime = (u32) -1; | ||
5317 | return false; | ||
5318 | } else { | ||
5319 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us)); | ||
5320 | ahp->ah_slottime = us; | ||
5321 | return true; | ||
5322 | } | ||
5323 | } | ||
5324 | |||
5325 | static inline void ath9k_hw_init_user_settings(struct ath_hal *ah) | ||
5326 | { | ||
5327 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5328 | |||
5329 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "--AP %s ahp->ah_miscMode 0x%x\n", | ||
5330 | __func__, ahp->ah_miscMode); | ||
5331 | if (ahp->ah_miscMode != 0) | ||
5332 | REG_WRITE(ah, AR_PCU_MISC, | ||
5333 | REG_READ(ah, AR_PCU_MISC) | ahp->ah_miscMode); | ||
5334 | if (ahp->ah_slottime != (u32) -1) | ||
5335 | ath9k_hw_setslottime(ah, ahp->ah_slottime); | ||
5336 | if (ahp->ah_acktimeout != (u32) -1) | ||
5337 | ath9k_hw_set_ack_timeout(ah, ahp->ah_acktimeout); | ||
5338 | if (ahp->ah_ctstimeout != (u32) -1) | ||
5339 | ath9k_hw_set_cts_timeout(ah, ahp->ah_ctstimeout); | ||
5340 | if (ahp->ah_globaltxtimeout != (u32) -1) | ||
5341 | ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout); | ||
5342 | } | ||
5343 | |||
5344 | static inline int | ||
5345 | ath9k_hw_process_ini(struct ath_hal *ah, | ||
5346 | struct ath9k_channel *chan, | ||
5347 | enum ath9k_ht_macmode macmode) | ||
5348 | { | ||
5349 | int i, regWrites = 0; | ||
5350 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5351 | u32 modesIndex, freqIndex; | ||
5352 | int status; | ||
5353 | |||
5354 | switch (chan->chanmode) { | ||
5355 | case CHANNEL_A: | ||
5356 | case CHANNEL_A_HT20: | ||
5357 | modesIndex = 1; | ||
5358 | freqIndex = 1; | ||
5359 | break; | ||
5360 | case CHANNEL_A_HT40PLUS: | ||
5361 | case CHANNEL_A_HT40MINUS: | ||
5362 | modesIndex = 2; | ||
5363 | freqIndex = 1; | ||
5364 | break; | ||
5365 | case CHANNEL_G: | ||
5366 | case CHANNEL_G_HT20: | ||
5367 | case CHANNEL_B: | ||
5368 | modesIndex = 4; | ||
5369 | freqIndex = 2; | ||
5370 | break; | ||
5371 | case CHANNEL_G_HT40PLUS: | ||
5372 | case CHANNEL_G_HT40MINUS: | ||
5373 | modesIndex = 3; | ||
5374 | freqIndex = 2; | ||
5375 | break; | ||
5376 | |||
5377 | default: | ||
5378 | return -EINVAL; | ||
5379 | } | ||
5380 | |||
5381 | REG_WRITE(ah, AR_PHY(0), 0x00000007); | ||
5382 | |||
5383 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); | ||
5384 | |||
5385 | ath9k_hw_set_addac(ah, chan); | ||
5386 | |||
5387 | if (AR_SREV_5416_V22_OR_LATER(ah)) { | ||
5388 | REG_WRITE_ARRAY(&ahp->ah_iniAddac, 1, regWrites); | ||
5389 | } else { | ||
5390 | struct ar5416IniArray temp; | ||
5391 | u32 addacSize = | ||
5392 | sizeof(u32) * ahp->ah_iniAddac.ia_rows * | ||
5393 | ahp->ah_iniAddac.ia_columns; | ||
5394 | |||
5395 | memcpy(ahp->ah_addac5416_21, | ||
5396 | ahp->ah_iniAddac.ia_array, addacSize); | ||
5397 | |||
5398 | (ahp->ah_addac5416_21)[31 * | ||
5399 | ahp->ah_iniAddac.ia_columns + 1] = 0; | ||
5400 | |||
5401 | temp.ia_array = ahp->ah_addac5416_21; | ||
5402 | temp.ia_columns = ahp->ah_iniAddac.ia_columns; | ||
5403 | temp.ia_rows = ahp->ah_iniAddac.ia_rows; | ||
5404 | REG_WRITE_ARRAY(&temp, 1, regWrites); | ||
5405 | } | ||
5406 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); | ||
5407 | |||
5408 | for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) { | ||
5409 | u32 reg = INI_RA(&ahp->ah_iniModes, i, 0); | ||
5410 | u32 val = INI_RA(&ahp->ah_iniModes, i, modesIndex); | ||
5411 | |||
5412 | #ifdef CONFIG_SLOW_ANT_DIV | ||
5413 | if (ah->ah_devid == AR9280_DEVID_PCI) | ||
5414 | val = ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom, reg, | ||
5415 | val); | ||
5416 | #endif | ||
5417 | |||
5418 | REG_WRITE(ah, reg, val); | ||
5419 | |||
5420 | if (reg >= 0x7800 && reg < 0x78a0 | ||
5421 | && ah->ah_config.analog_shiftreg) { | ||
5422 | udelay(100); | ||
5423 | } | ||
5424 | |||
5425 | DO_DELAY(regWrites); | ||
5426 | } | ||
5427 | |||
5428 | for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) { | ||
5429 | u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0); | ||
5430 | u32 val = INI_RA(&ahp->ah_iniCommon, i, 1); | ||
5431 | |||
5432 | REG_WRITE(ah, reg, val); | ||
5433 | |||
5434 | if (reg >= 0x7800 && reg < 0x78a0 | ||
5435 | && ah->ah_config.analog_shiftreg) { | ||
5436 | udelay(100); | ||
5437 | } | ||
5438 | |||
5439 | DO_DELAY(regWrites); | ||
5440 | } | ||
5441 | |||
5442 | ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites); | ||
5443 | |||
5444 | if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { | ||
5445 | REG_WRITE_ARRAY(&ahp->ah_iniModesAdditional, modesIndex, | ||
5446 | regWrites); | ||
5447 | } | ||
5448 | |||
5449 | ath9k_hw_override_ini(ah, chan); | ||
5450 | ath9k_hw_set_regs(ah, chan, macmode); | ||
5451 | ath9k_hw_init_chain_masks(ah); | ||
5452 | |||
5453 | status = ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan, | ||
5454 | ath9k_regd_get_ctl(ah, chan), | ||
5455 | ath9k_regd_get_antenna_allowed(ah, | ||
5456 | chan), | ||
5457 | chan->maxRegTxPower * 2, | ||
5458 | min((u32) MAX_RATE_POWER, | ||
5459 | (u32) ah->ah_powerLimit)); | ||
5460 | if (status != 0) { | ||
5461 | DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, | ||
5462 | "%s: error init'ing transmit power\n", __func__); | ||
5463 | return -EIO; | ||
5464 | } | ||
5465 | |||
5466 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { | ||
5467 | DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, | ||
5468 | "%s: ar5416SetRfRegs failed\n", __func__); | ||
5469 | return -EIO; | ||
5470 | } | ||
5471 | |||
5472 | return 0; | ||
5473 | } | ||
5474 | |||
5475 | static inline void ath9k_hw_setup_calibration(struct ath_hal *ah, | ||
5476 | struct hal_cal_list *currCal) | ||
5477 | { | ||
5478 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), | ||
5479 | AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, | ||
5480 | currCal->calData->calCountMax); | ||
5481 | |||
5482 | switch (currCal->calData->calType) { | ||
5483 | case IQ_MISMATCH_CAL: | ||
5484 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); | ||
5485 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5486 | "%s: starting IQ Mismatch Calibration\n", | ||
5487 | __func__); | ||
5488 | break; | ||
5489 | case ADC_GAIN_CAL: | ||
5490 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); | ||
5491 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5492 | "%s: starting ADC Gain Calibration\n", __func__); | ||
5493 | break; | ||
5494 | case ADC_DC_CAL: | ||
5495 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); | ||
5496 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5497 | "%s: starting ADC DC Calibration\n", __func__); | ||
5498 | break; | ||
5499 | case ADC_DC_INIT_CAL: | ||
5500 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); | ||
5501 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5502 | "%s: starting Init ADC DC Calibration\n", | ||
5503 | __func__); | ||
5504 | break; | ||
5505 | } | ||
5506 | |||
5507 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | ||
5508 | AR_PHY_TIMING_CTRL4_DO_CAL); | ||
5509 | } | ||
5510 | |||
5511 | static inline void ath9k_hw_reset_calibration(struct ath_hal *ah, | ||
5512 | struct hal_cal_list *currCal) | ||
5513 | { | ||
5514 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5515 | int i; | ||
5516 | |||
5517 | ath9k_hw_setup_calibration(ah, currCal); | ||
5518 | |||
5519 | currCal->calState = CAL_RUNNING; | ||
5520 | |||
5521 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
5522 | ahp->ah_Meas0.sign[i] = 0; | ||
5523 | ahp->ah_Meas1.sign[i] = 0; | ||
5524 | ahp->ah_Meas2.sign[i] = 0; | ||
5525 | ahp->ah_Meas3.sign[i] = 0; | ||
5526 | } | ||
5527 | |||
5528 | ahp->ah_CalSamples = 0; | ||
5529 | } | ||
5530 | |||
5531 | static inline void | ||
5532 | ath9k_hw_per_calibration(struct ath_hal *ah, | ||
5533 | struct ath9k_channel *ichan, | ||
5534 | u8 rxchainmask, | ||
5535 | struct hal_cal_list *currCal, | ||
5536 | bool *isCalDone) | ||
5537 | { | ||
5538 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5539 | |||
5540 | *isCalDone = false; | ||
5541 | |||
5542 | if (currCal->calState == CAL_RUNNING) { | ||
5543 | if (!(REG_READ(ah, | ||
5544 | AR_PHY_TIMING_CTRL4(0)) & | ||
5545 | AR_PHY_TIMING_CTRL4_DO_CAL)) { | ||
5546 | |||
5547 | currCal->calData->calCollect(ah); | ||
5548 | |||
5549 | ahp->ah_CalSamples++; | ||
5550 | |||
5551 | if (ahp->ah_CalSamples >= | ||
5552 | currCal->calData->calNumSamples) { | ||
5553 | int i, numChains = 0; | ||
5554 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
5555 | if (rxchainmask & (1 << i)) | ||
5556 | numChains++; | ||
5557 | } | ||
5558 | |||
5559 | currCal->calData->calPostProc(ah, | ||
5560 | numChains); | ||
5561 | |||
5562 | ichan->CalValid |= | ||
5563 | currCal->calData->calType; | ||
5564 | currCal->calState = CAL_DONE; | ||
5565 | *isCalDone = true; | ||
5566 | } else { | ||
5567 | ath9k_hw_setup_calibration(ah, currCal); | ||
5568 | } | ||
5569 | } | ||
5570 | } else if (!(ichan->CalValid & currCal->calData->calType)) { | ||
5571 | ath9k_hw_reset_calibration(ah, currCal); | ||
5572 | } | ||
5573 | } | ||
5574 | |||
5575 | static inline bool ath9k_hw_run_init_cals(struct ath_hal *ah, | ||
5576 | int init_cal_count) | ||
5577 | { | ||
5578 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5579 | struct ath9k_channel ichan; | ||
5580 | bool isCalDone; | ||
5581 | struct hal_cal_list *currCal = ahp->ah_cal_list_curr; | ||
5582 | const struct hal_percal_data *calData = currCal->calData; | ||
5583 | int i; | ||
5584 | |||
5585 | if (currCal == NULL) | ||
5586 | return false; | ||
5587 | |||
5588 | ichan.CalValid = 0; | ||
5589 | |||
5590 | for (i = 0; i < init_cal_count; i++) { | ||
5591 | ath9k_hw_reset_calibration(ah, currCal); | ||
5592 | |||
5593 | if (!ath9k_hw_wait(ah, AR_PHY_TIMING_CTRL4(0), | ||
5594 | AR_PHY_TIMING_CTRL4_DO_CAL, 0)) { | ||
5595 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5596 | "%s: Cal %d failed to complete in 100ms.\n", | ||
5597 | __func__, calData->calType); | ||
5598 | |||
5599 | ahp->ah_cal_list = ahp->ah_cal_list_last = | ||
5600 | ahp->ah_cal_list_curr = NULL; | ||
5601 | return false; | ||
5602 | } | ||
5603 | |||
5604 | ath9k_hw_per_calibration(ah, &ichan, ahp->ah_rxchainmask, | ||
5605 | currCal, &isCalDone); | ||
5606 | if (!isCalDone) { | ||
5607 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5608 | "%s: Not able to run Init Cal %d.\n", | ||
5609 | __func__, calData->calType); | ||
5610 | } | ||
5611 | if (currCal->calNext) { | ||
5612 | currCal = currCal->calNext; | ||
5613 | calData = currCal->calData; | ||
5614 | } | ||
5615 | } | ||
5616 | |||
5617 | ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL; | ||
5618 | return true; | ||
5619 | } | ||
5620 | |||
5621 | static inline bool | ||
5622 | ath9k_hw_channel_change(struct ath_hal *ah, | ||
5623 | struct ath9k_channel *chan, | ||
5624 | enum ath9k_ht_macmode macmode) | ||
5625 | { | ||
5626 | u32 synthDelay, qnum; | ||
5627 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5628 | |||
5629 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { | ||
5630 | if (ath9k_hw_numtxpending(ah, qnum)) { | ||
5631 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
5632 | "%s: Transmit frames pending on queue %d\n", | ||
5633 | __func__, qnum); | ||
5634 | return false; | ||
5635 | } | ||
5636 | } | ||
5637 | |||
5638 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); | ||
5639 | if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, | ||
5640 | AR_PHY_RFBUS_GRANT_EN)) { | ||
5641 | DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO, | ||
5642 | "%s: Could not kill baseband RX\n", __func__); | ||
5643 | return false; | ||
5644 | } | ||
5645 | |||
5646 | ath9k_hw_set_regs(ah, chan, macmode); | ||
5647 | |||
5648 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
5649 | if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { | ||
5650 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
5651 | "%s: failed to set channel\n", __func__); | ||
5652 | return false; | ||
5653 | } | ||
5654 | } else { | ||
5655 | if (!(ath9k_hw_set_channel(ah, chan))) { | ||
5656 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
5657 | "%s: failed to set channel\n", __func__); | ||
5658 | return false; | ||
5659 | } | ||
5660 | } | ||
5661 | |||
5662 | if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan, | ||
5663 | ath9k_regd_get_ctl(ah, chan), | ||
5664 | ath9k_regd_get_antenna_allowed(ah, chan), | ||
5665 | chan->maxRegTxPower * 2, | ||
5666 | min((u32) MAX_RATE_POWER, | ||
5667 | (u32) ah->ah_powerLimit)) != 0) { | ||
5668 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
5669 | "%s: error init'ing transmit power\n", __func__); | ||
5670 | return false; | ||
5671 | } | ||
5672 | |||
5673 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; | ||
5674 | if (IS_CHAN_CCK(chan)) | ||
5675 | synthDelay = (4 * synthDelay) / 22; | ||
5676 | else | ||
5677 | synthDelay /= 10; | ||
5678 | |||
5679 | udelay(synthDelay + BASE_ACTIVATE_DELAY); | ||
5680 | |||
5681 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); | ||
5682 | |||
5683 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | ||
5684 | ath9k_hw_set_delta_slope(ah, chan); | ||
5685 | |||
5686 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
5687 | ath9k_hw_9280_spur_mitigate(ah, chan); | ||
5688 | else | ||
5689 | ath9k_hw_spur_mitigate(ah, chan); | ||
5690 | |||
5691 | if (!chan->oneTimeCalsDone) | ||
5692 | chan->oneTimeCalsDone = true; | ||
5693 | |||
5694 | return true; | ||
5695 | } | ||
5696 | |||
5697 | static bool ath9k_hw_chip_reset(struct ath_hal *ah, | ||
5698 | struct ath9k_channel *chan) | ||
5699 | { | ||
5700 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5701 | |||
5702 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) | ||
5703 | return false; | ||
5704 | |||
5705 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | ||
5706 | return false; | ||
5707 | |||
5708 | ahp->ah_chipFullSleep = false; | ||
5709 | |||
5710 | ath9k_hw_init_pll(ah, chan); | ||
5711 | |||
5712 | ath9k_hw_set_rfmode(ah, chan); | ||
5713 | |||
5714 | return true; | ||
5715 | } | ||
5716 | |||
5717 | static inline void ath9k_hw_set_dma(struct ath_hal *ah) | ||
5718 | { | ||
5719 | u32 regval; | ||
5720 | |||
5721 | regval = REG_READ(ah, AR_AHB_MODE); | ||
5722 | REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); | ||
5723 | |||
5724 | regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; | ||
5725 | REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); | ||
5726 | |||
5727 | REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->ah_txTrigLevel); | ||
5728 | |||
5729 | regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; | ||
5730 | REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); | ||
5731 | |||
5732 | REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); | ||
5733 | |||
5734 | if (AR_SREV_9285(ah)) { | ||
5735 | REG_WRITE(ah, AR_PCU_TXBUF_CTRL, | ||
5736 | AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); | ||
5737 | } else { | ||
5738 | REG_WRITE(ah, AR_PCU_TXBUF_CTRL, | ||
5739 | AR_PCU_TXBUF_CTRL_USABLE_SIZE); | ||
5740 | } | ||
5741 | } | ||
5742 | |||
5743 | bool ath9k_hw_stopdmarecv(struct ath_hal *ah) | ||
5744 | { | ||
5745 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | ||
5746 | if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) { | ||
5747 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
5748 | "%s: dma failed to stop in 10ms\n" | ||
5749 | "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", | ||
5750 | __func__, | ||
5751 | REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); | ||
5752 | return false; | ||
5753 | } else { | ||
5754 | return true; | ||
5755 | } | ||
5756 | } | ||
5757 | |||
5758 | void ath9k_hw_startpcureceive(struct ath_hal *ah) | ||
5759 | { | ||
5760 | REG_CLR_BIT(ah, AR_DIAG_SW, | ||
5761 | (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | ||
5762 | |||
5763 | ath9k_enable_mib_counters(ah); | ||
5764 | |||
5765 | ath9k_ani_reset(ah); | ||
5766 | } | ||
5767 | |||
5768 | void ath9k_hw_stoppcurecv(struct ath_hal *ah) | ||
5769 | { | ||
5770 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
5771 | |||
5772 | ath9k_hw_disable_mib_counters(ah); | ||
5773 | } | ||
5774 | |||
5775 | static bool ath9k_hw_iscal_supported(struct ath_hal *ah, | ||
5776 | struct ath9k_channel *chan, | ||
5777 | enum hal_cal_types calType) | ||
5778 | { | ||
5779 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5780 | bool retval = false; | ||
5781 | |||
5782 | switch (calType & ahp->ah_suppCals) { | ||
5783 | case IQ_MISMATCH_CAL: | ||
5784 | if (!IS_CHAN_B(chan)) | ||
5785 | retval = true; | ||
5786 | break; | ||
5787 | case ADC_GAIN_CAL: | ||
5788 | case ADC_DC_CAL: | ||
5789 | if (!IS_CHAN_B(chan) | ||
5790 | && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) | ||
5791 | retval = true; | ||
5792 | break; | ||
5793 | } | ||
5794 | |||
5795 | return retval; | ||
5796 | } | ||
5797 | |||
5798 | static inline bool ath9k_hw_init_cal(struct ath_hal *ah, | ||
5799 | struct ath9k_channel *chan) | ||
5800 | { | ||
5801 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5802 | struct ath9k_channel *ichan = | ||
5803 | ath9k_regd_check_channel(ah, chan); | ||
5804 | |||
5805 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | ||
5806 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | ||
5807 | AR_PHY_AGC_CONTROL_CAL); | ||
5808 | |||
5809 | if (!ath9k_hw_wait | ||
5810 | (ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { | ||
5811 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5812 | "%s: offset calibration failed to complete in 1ms; " | ||
5813 | "noisy environment?\n", __func__); | ||
5814 | return false; | ||
5815 | } | ||
5816 | |||
5817 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | ||
5818 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | ||
5819 | AR_PHY_AGC_CONTROL_NF); | ||
5820 | |||
5821 | ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = | ||
5822 | NULL; | ||
5823 | |||
5824 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { | ||
5825 | if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) { | ||
5826 | INIT_CAL(&ahp->ah_adcGainCalData); | ||
5827 | INSERT_CAL(ahp, &ahp->ah_adcGainCalData); | ||
5828 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5829 | "%s: enabling ADC Gain Calibration.\n", | ||
5830 | __func__); | ||
5831 | } | ||
5832 | if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) { | ||
5833 | INIT_CAL(&ahp->ah_adcDcCalData); | ||
5834 | INSERT_CAL(ahp, &ahp->ah_adcDcCalData); | ||
5835 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5836 | "%s: enabling ADC DC Calibration.\n", | ||
5837 | __func__); | ||
5838 | } | ||
5839 | if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) { | ||
5840 | INIT_CAL(&ahp->ah_iqCalData); | ||
5841 | INSERT_CAL(ahp, &ahp->ah_iqCalData); | ||
5842 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
5843 | "%s: enabling IQ Calibration.\n", | ||
5844 | __func__); | ||
5845 | } | ||
5846 | |||
5847 | ahp->ah_cal_list_curr = ahp->ah_cal_list; | ||
5848 | |||
5849 | if (ahp->ah_cal_list_curr) | ||
5850 | ath9k_hw_reset_calibration(ah, | ||
5851 | ahp->ah_cal_list_curr); | ||
5852 | } | ||
5853 | |||
5854 | ichan->CalValid = 0; | ||
5855 | |||
5856 | return true; | ||
5857 | } | ||
5858 | |||
5859 | |||
5860 | bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | ||
5861 | struct ath9k_channel *chan, | ||
5862 | enum ath9k_ht_macmode macmode, | ||
5863 | u8 txchainmask, u8 rxchainmask, | ||
5864 | enum ath9k_ht_extprotspacing extprotspacing, | ||
5865 | bool bChannelChange, | ||
5866 | int *status) | ||
5867 | { | ||
5868 | #define FAIL(_code) do { ecode = _code; goto bad; } while (0) | ||
5869 | u32 saveLedState; | ||
5870 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
5871 | struct ath9k_channel *curchan = ah->ah_curchan; | ||
5872 | u32 saveDefAntenna; | ||
5873 | u32 macStaId1; | ||
5874 | int ecode; | ||
5875 | int i, rx_chainmask; | ||
5876 | |||
5877 | ahp->ah_extprotspacing = extprotspacing; | ||
5878 | ahp->ah_txchainmask = txchainmask; | ||
5879 | ahp->ah_rxchainmask = rxchainmask; | ||
5880 | |||
5881 | if (AR_SREV_9280(ah)) { | ||
5882 | ahp->ah_txchainmask &= 0x3; | ||
5883 | ahp->ah_rxchainmask &= 0x3; | ||
5884 | } | ||
5885 | |||
5886 | if (ath9k_hw_check_chan(ah, chan) == NULL) { | ||
5887 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
5888 | "%s: invalid channel %u/0x%x; no mapping\n", | ||
5889 | __func__, chan->channel, chan->channelFlags); | ||
5890 | FAIL(-EINVAL); | ||
5891 | } | ||
5892 | |||
5893 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | ||
5894 | return false; | ||
5895 | |||
5896 | if (curchan) | ||
5897 | ath9k_hw_getnf(ah, curchan); | ||
5898 | |||
5899 | if (bChannelChange && | ||
5900 | (ahp->ah_chipFullSleep != true) && | ||
5901 | (ah->ah_curchan != NULL) && | ||
5902 | (chan->channel != ah->ah_curchan->channel) && | ||
5903 | ((chan->channelFlags & CHANNEL_ALL) == | ||
5904 | (ah->ah_curchan->channelFlags & CHANNEL_ALL)) && | ||
5905 | (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && | ||
5906 | !IS_CHAN_A_5MHZ_SPACED(ah-> | ||
5907 | ah_curchan)))) { | ||
5908 | |||
5909 | if (ath9k_hw_channel_change(ah, chan, macmode)) { | ||
5910 | ath9k_hw_loadnf(ah, ah->ah_curchan); | ||
5911 | ath9k_hw_start_nfcal(ah); | ||
5912 | return true; | ||
5913 | } | ||
5914 | } | ||
5915 | |||
5916 | saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); | ||
5917 | if (saveDefAntenna == 0) | ||
5918 | saveDefAntenna = 1; | ||
5919 | |||
5920 | macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; | ||
5921 | |||
5922 | saveLedState = REG_READ(ah, AR_CFG_LED) & | ||
5923 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | | ||
5924 | AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); | ||
5925 | |||
5926 | ath9k_hw_mark_phy_inactive(ah); | ||
5927 | |||
5928 | if (!ath9k_hw_chip_reset(ah, chan)) { | ||
5929 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: chip reset failed\n", | ||
5930 | __func__); | ||
5931 | FAIL(-EIO); | ||
5932 | } | ||
5933 | |||
5934 | if (AR_SREV_9280(ah)) { | ||
5935 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
5936 | AR_GPIO_JTAG_DISABLE); | ||
5937 | |||
5938 | if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes)) { | ||
5939 | if (IS_CHAN_5GHZ(chan)) | ||
5940 | ath9k_hw_set_gpio(ah, 9, 0); | ||
5941 | else | ||
5942 | ath9k_hw_set_gpio(ah, 9, 1); | ||
5943 | } | ||
5944 | ath9k_hw_cfg_output(ah, 9, ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
5945 | } | ||
5946 | |||
5947 | ecode = ath9k_hw_process_ini(ah, chan, macmode); | ||
5948 | if (ecode != 0) | ||
5949 | goto bad; | ||
5950 | |||
5951 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | ||
5952 | ath9k_hw_set_delta_slope(ah, chan); | ||
5953 | |||
5954 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
5955 | ath9k_hw_9280_spur_mitigate(ah, chan); | ||
5956 | else | ||
5957 | ath9k_hw_spur_mitigate(ah, chan); | ||
5958 | |||
5959 | if (!ath9k_hw_eeprom_set_board_values(ah, chan)) { | ||
5960 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
5961 | "%s: error setting board options\n", __func__); | ||
5962 | FAIL(-EIO); | ||
5963 | } | ||
5964 | |||
5965 | ath9k_hw_decrease_chain_power(ah, chan); | ||
5966 | |||
5967 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ahp->ah_macaddr)); | ||
5968 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ahp->ah_macaddr + 4) | ||
5969 | | macStaId1 | ||
5970 | | AR_STA_ID1_RTS_USE_DEF | ||
5971 | | (ah->ah_config. | ||
5972 | ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ||
5973 | | ahp->ah_staId1Defaults); | ||
5974 | ath9k_hw_set_operating_mode(ah, opmode); | ||
5975 | |||
5976 | REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask)); | ||
5977 | REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4)); | ||
5978 | |||
5979 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); | ||
5980 | |||
5981 | REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid)); | ||
5982 | REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) | | ||
5983 | ((ahp->ah_assocId & 0x3fff) << AR_BSS_ID1_AID_S)); | ||
5984 | |||
5985 | REG_WRITE(ah, AR_ISR, ~0); | ||
5986 | |||
5987 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | ||
5988 | |||
5989 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
5990 | if (!(ath9k_hw_ar9280_set_channel(ah, chan))) | ||
5991 | FAIL(-EIO); | ||
5992 | } else { | ||
5993 | if (!(ath9k_hw_set_channel(ah, chan))) | ||
5994 | FAIL(-EIO); | ||
5995 | } | ||
5996 | |||
5997 | for (i = 0; i < AR_NUM_DCU; i++) | ||
5998 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | ||
5999 | |||
6000 | ahp->ah_intrTxqs = 0; | ||
6001 | for (i = 0; i < ah->ah_caps.total_queues; i++) | ||
6002 | ath9k_hw_resettxqueue(ah, i); | ||
6003 | |||
6004 | ath9k_hw_init_interrupt_masks(ah, opmode); | ||
6005 | ath9k_hw_init_qos(ah); | ||
6006 | |||
6007 | ath9k_hw_init_user_settings(ah); | ||
6008 | |||
6009 | ah->ah_opmode = opmode; | ||
6010 | |||
6011 | REG_WRITE(ah, AR_STA_ID1, | ||
6012 | REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); | ||
6013 | |||
6014 | ath9k_hw_set_dma(ah); | ||
6015 | |||
6016 | REG_WRITE(ah, AR_OBS, 8); | ||
6017 | |||
6018 | if (ahp->ah_intrMitigation) { | ||
6019 | |||
6020 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); | ||
6021 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); | ||
6022 | } | ||
6023 | |||
6024 | ath9k_hw_init_bb(ah, chan); | ||
6025 | |||
6026 | if (!ath9k_hw_init_cal(ah, chan)) | ||
6027 | FAIL(-ENODEV); | ||
6028 | |||
6029 | rx_chainmask = ahp->ah_rxchainmask; | ||
6030 | if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { | ||
6031 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); | ||
6032 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); | ||
6033 | } | ||
6034 | |||
6035 | REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); | ||
6036 | |||
6037 | if (AR_SREV_9100(ah)) { | ||
6038 | u32 mask; | ||
6039 | mask = REG_READ(ah, AR_CFG); | ||
6040 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | ||
6041 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
6042 | "%s CFG Byte Swap Set 0x%x\n", __func__, | ||
6043 | mask); | ||
6044 | } else { | ||
6045 | mask = | ||
6046 | INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | ||
6047 | REG_WRITE(ah, AR_CFG, mask); | ||
6048 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
6049 | "%s Setting CFG 0x%x\n", __func__, | ||
6050 | REG_READ(ah, AR_CFG)); | ||
6051 | } | ||
6052 | } else { | ||
6053 | #ifdef __BIG_ENDIAN | ||
6054 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | ||
6055 | #endif | ||
6056 | } | ||
6057 | |||
6058 | return true; | ||
6059 | bad: | ||
6060 | if (status) | ||
6061 | *status = ecode; | ||
6062 | return false; | ||
6063 | #undef FAIL | ||
6064 | } | ||
6065 | |||
6066 | bool ath9k_hw_phy_disable(struct ath_hal *ah) | ||
6067 | { | ||
6068 | return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM); | ||
6069 | } | ||
6070 | |||
6071 | bool ath9k_hw_disable(struct ath_hal *ah) | ||
6072 | { | ||
6073 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | ||
6074 | return false; | ||
6075 | |||
6076 | return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); | ||
6077 | } | ||
6078 | |||
6079 | bool | ||
6080 | ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan, | ||
6081 | u8 rxchainmask, bool longcal, | ||
6082 | bool *isCalDone) | ||
6083 | { | ||
6084 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6085 | struct hal_cal_list *currCal = ahp->ah_cal_list_curr; | ||
6086 | struct ath9k_channel *ichan = | ||
6087 | ath9k_regd_check_channel(ah, chan); | ||
6088 | |||
6089 | *isCalDone = true; | ||
6090 | |||
6091 | if (ichan == NULL) { | ||
6092 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | ||
6093 | "%s: invalid channel %u/0x%x; no mapping\n", | ||
6094 | __func__, chan->channel, chan->channelFlags); | ||
6095 | return false; | ||
6096 | } | ||
6097 | |||
6098 | if (currCal && | ||
6099 | (currCal->calState == CAL_RUNNING || | ||
6100 | currCal->calState == CAL_WAITING)) { | ||
6101 | ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal, | ||
6102 | isCalDone); | ||
6103 | if (*isCalDone) { | ||
6104 | ahp->ah_cal_list_curr = currCal = currCal->calNext; | ||
6105 | |||
6106 | if (currCal->calState == CAL_WAITING) { | ||
6107 | *isCalDone = false; | ||
6108 | ath9k_hw_reset_calibration(ah, currCal); | ||
6109 | } | ||
6110 | } | ||
6111 | } | ||
6112 | |||
6113 | if (longcal) { | ||
6114 | ath9k_hw_getnf(ah, ichan); | ||
6115 | ath9k_hw_loadnf(ah, ah->ah_curchan); | ||
6116 | ath9k_hw_start_nfcal(ah); | ||
6117 | |||
6118 | if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { | ||
6119 | |||
6120 | chan->channelFlags |= CHANNEL_CW_INT; | ||
6121 | ichan->channelFlags &= ~CHANNEL_CW_INT; | ||
6122 | } | ||
6123 | } | ||
6124 | |||
6125 | return true; | ||
6126 | } | ||
6127 | |||
6128 | static void ath9k_hw_iqcal_collect(struct ath_hal *ah) | ||
6129 | { | ||
6130 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6131 | int i; | ||
6132 | |||
6133 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
6134 | ahp->ah_totalPowerMeasI[i] += | ||
6135 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | ||
6136 | ahp->ah_totalPowerMeasQ[i] += | ||
6137 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | ||
6138 | ahp->ah_totalIqCorrMeas[i] += | ||
6139 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | ||
6140 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6141 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", | ||
6142 | ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i], | ||
6143 | ahp->ah_totalPowerMeasQ[i], | ||
6144 | ahp->ah_totalIqCorrMeas[i]); | ||
6145 | } | ||
6146 | } | ||
6147 | |||
6148 | static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah) | ||
6149 | { | ||
6150 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6151 | int i; | ||
6152 | |||
6153 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
6154 | ahp->ah_totalAdcIOddPhase[i] += | ||
6155 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | ||
6156 | ahp->ah_totalAdcIEvenPhase[i] += | ||
6157 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | ||
6158 | ahp->ah_totalAdcQOddPhase[i] += | ||
6159 | REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | ||
6160 | ahp->ah_totalAdcQEvenPhase[i] += | ||
6161 | REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | ||
6162 | |||
6163 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6164 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | ||
6165 | "oddq=0x%08x; evenq=0x%08x;\n", | ||
6166 | ahp->ah_CalSamples, i, | ||
6167 | ahp->ah_totalAdcIOddPhase[i], | ||
6168 | ahp->ah_totalAdcIEvenPhase[i], | ||
6169 | ahp->ah_totalAdcQOddPhase[i], | ||
6170 | ahp->ah_totalAdcQEvenPhase[i]); | ||
6171 | } | ||
6172 | } | ||
6173 | |||
6174 | static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah) | ||
6175 | { | ||
6176 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6177 | int i; | ||
6178 | |||
6179 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
6180 | ahp->ah_totalAdcDcOffsetIOddPhase[i] += | ||
6181 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | ||
6182 | ahp->ah_totalAdcDcOffsetIEvenPhase[i] += | ||
6183 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | ||
6184 | ahp->ah_totalAdcDcOffsetQOddPhase[i] += | ||
6185 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | ||
6186 | ahp->ah_totalAdcDcOffsetQEvenPhase[i] += | ||
6187 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | ||
6188 | |||
6189 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6190 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | ||
6191 | "oddq=0x%08x; evenq=0x%08x;\n", | ||
6192 | ahp->ah_CalSamples, i, | ||
6193 | ahp->ah_totalAdcDcOffsetIOddPhase[i], | ||
6194 | ahp->ah_totalAdcDcOffsetIEvenPhase[i], | ||
6195 | ahp->ah_totalAdcDcOffsetQOddPhase[i], | ||
6196 | ahp->ah_totalAdcDcOffsetQEvenPhase[i]); | ||
6197 | } | ||
6198 | } | ||
6199 | |||
6200 | static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains) | ||
6201 | { | ||
6202 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6203 | u32 powerMeasQ, powerMeasI, iqCorrMeas; | ||
6204 | u32 qCoffDenom, iCoffDenom; | ||
6205 | int32_t qCoff, iCoff; | ||
6206 | int iqCorrNeg, i; | ||
6207 | |||
6208 | for (i = 0; i < numChains; i++) { | ||
6209 | powerMeasI = ahp->ah_totalPowerMeasI[i]; | ||
6210 | powerMeasQ = ahp->ah_totalPowerMeasQ[i]; | ||
6211 | iqCorrMeas = ahp->ah_totalIqCorrMeas[i]; | ||
6212 | |||
6213 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6214 | "Starting IQ Cal and Correction for Chain %d\n", | ||
6215 | i); | ||
6216 | |||
6217 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6218 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", | ||
6219 | i, ahp->ah_totalIqCorrMeas[i]); | ||
6220 | |||
6221 | iqCorrNeg = 0; | ||
6222 | |||
6223 | |||
6224 | if (iqCorrMeas > 0x80000000) { | ||
6225 | iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; | ||
6226 | iqCorrNeg = 1; | ||
6227 | } | ||
6228 | |||
6229 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6230 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); | ||
6231 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6232 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); | ||
6233 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", | ||
6234 | iqCorrNeg); | ||
6235 | |||
6236 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; | ||
6237 | qCoffDenom = powerMeasQ / 64; | ||
6238 | |||
6239 | if (powerMeasQ != 0) { | ||
6240 | |||
6241 | iCoff = iqCorrMeas / iCoffDenom; | ||
6242 | qCoff = powerMeasI / qCoffDenom - 64; | ||
6243 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6244 | "Chn %d iCoff = 0x%08x\n", i, iCoff); | ||
6245 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6246 | "Chn %d qCoff = 0x%08x\n", i, qCoff); | ||
6247 | |||
6248 | |||
6249 | iCoff = iCoff & 0x3f; | ||
6250 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6251 | "New: Chn %d iCoff = 0x%08x\n", i, iCoff); | ||
6252 | if (iqCorrNeg == 0x0) | ||
6253 | iCoff = 0x40 - iCoff; | ||
6254 | |||
6255 | if (qCoff > 15) | ||
6256 | qCoff = 15; | ||
6257 | else if (qCoff <= -16) | ||
6258 | qCoff = 16; | ||
6259 | |||
6260 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6261 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", | ||
6262 | i, iCoff, qCoff); | ||
6263 | |||
6264 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | ||
6265 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, | ||
6266 | iCoff); | ||
6267 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | ||
6268 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, | ||
6269 | qCoff); | ||
6270 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6271 | "IQ Cal and Correction done for Chain %d\n", | ||
6272 | i); | ||
6273 | } | ||
6274 | } | ||
6275 | |||
6276 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | ||
6277 | AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); | ||
6278 | } | ||
6279 | |||
6280 | static void | ||
6281 | ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains) | ||
6282 | { | ||
6283 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6284 | u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, | ||
6285 | qEvenMeasOffset; | ||
6286 | u32 qGainMismatch, iGainMismatch, val, i; | ||
6287 | |||
6288 | for (i = 0; i < numChains; i++) { | ||
6289 | iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i]; | ||
6290 | iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i]; | ||
6291 | qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i]; | ||
6292 | qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i]; | ||
6293 | |||
6294 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6295 | "Starting ADC Gain Cal for Chain %d\n", i); | ||
6296 | |||
6297 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6298 | "Chn %d pwr_meas_odd_i = 0x%08x\n", i, | ||
6299 | iOddMeasOffset); | ||
6300 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6301 | "Chn %d pwr_meas_even_i = 0x%08x\n", i, | ||
6302 | iEvenMeasOffset); | ||
6303 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6304 | "Chn %d pwr_meas_odd_q = 0x%08x\n", i, | ||
6305 | qOddMeasOffset); | ||
6306 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6307 | "Chn %d pwr_meas_even_q = 0x%08x\n", i, | ||
6308 | qEvenMeasOffset); | ||
6309 | |||
6310 | if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { | ||
6311 | iGainMismatch = | ||
6312 | ((iEvenMeasOffset * 32) / | ||
6313 | iOddMeasOffset) & 0x3f; | ||
6314 | qGainMismatch = | ||
6315 | ((qOddMeasOffset * 32) / | ||
6316 | qEvenMeasOffset) & 0x3f; | ||
6317 | |||
6318 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6319 | "Chn %d gain_mismatch_i = 0x%08x\n", i, | ||
6320 | iGainMismatch); | ||
6321 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6322 | "Chn %d gain_mismatch_q = 0x%08x\n", i, | ||
6323 | qGainMismatch); | ||
6324 | |||
6325 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | ||
6326 | val &= 0xfffff000; | ||
6327 | val |= (qGainMismatch) | (iGainMismatch << 6); | ||
6328 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | ||
6329 | |||
6330 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6331 | "ADC Gain Cal done for Chain %d\n", i); | ||
6332 | } | ||
6333 | } | ||
6334 | |||
6335 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | ||
6336 | REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | | ||
6337 | AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); | ||
6338 | } | ||
6339 | |||
6340 | static void | ||
6341 | ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains) | ||
6342 | { | ||
6343 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6344 | u32 iOddMeasOffset, iEvenMeasOffset, val, i; | ||
6345 | int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; | ||
6346 | const struct hal_percal_data *calData = | ||
6347 | ahp->ah_cal_list_curr->calData; | ||
6348 | u32 numSamples = | ||
6349 | (1 << (calData->calCountMax + 5)) * calData->calNumSamples; | ||
6350 | |||
6351 | for (i = 0; i < numChains; i++) { | ||
6352 | iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i]; | ||
6353 | iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i]; | ||
6354 | qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i]; | ||
6355 | qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i]; | ||
6356 | |||
6357 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6358 | "Starting ADC DC Offset Cal for Chain %d\n", i); | ||
6359 | |||
6360 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6361 | "Chn %d pwr_meas_odd_i = %d\n", i, | ||
6362 | iOddMeasOffset); | ||
6363 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6364 | "Chn %d pwr_meas_even_i = %d\n", i, | ||
6365 | iEvenMeasOffset); | ||
6366 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6367 | "Chn %d pwr_meas_odd_q = %d\n", i, | ||
6368 | qOddMeasOffset); | ||
6369 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6370 | "Chn %d pwr_meas_even_q = %d\n", i, | ||
6371 | qEvenMeasOffset); | ||
6372 | |||
6373 | iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / | ||
6374 | numSamples) & 0x1ff; | ||
6375 | qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / | ||
6376 | numSamples) & 0x1ff; | ||
6377 | |||
6378 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6379 | "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, | ||
6380 | iDcMismatch); | ||
6381 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6382 | "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, | ||
6383 | qDcMismatch); | ||
6384 | |||
6385 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | ||
6386 | val &= 0xc0000fff; | ||
6387 | val |= (qDcMismatch << 12) | (iDcMismatch << 21); | ||
6388 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | ||
6389 | |||
6390 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6391 | "ADC DC Offset Cal done for Chain %d\n", i); | ||
6392 | } | ||
6393 | |||
6394 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | ||
6395 | REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | | ||
6396 | AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); | ||
6397 | } | ||
6398 | |||
6399 | bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit) | ||
6400 | { | ||
6401 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6402 | struct ath9k_channel *chan = ah->ah_curchan; | ||
6403 | |||
6404 | ah->ah_powerLimit = min(limit, (u32) MAX_RATE_POWER); | ||
6405 | |||
6406 | if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan, | ||
6407 | ath9k_regd_get_ctl(ah, chan), | ||
6408 | ath9k_regd_get_antenna_allowed(ah, | ||
6409 | chan), | ||
6410 | chan->maxRegTxPower * 2, | ||
6411 | min((u32) MAX_RATE_POWER, | ||
6412 | (u32) ah->ah_powerLimit)) != 0) | ||
6413 | return false; | ||
6414 | |||
6415 | return true; | ||
6416 | } | ||
6417 | |||
6418 | void | ||
6419 | ath9k_hw_get_channel_centers(struct ath_hal *ah, | ||
6420 | struct ath9k_channel *chan, | ||
6421 | struct chan_centers *centers) | ||
6422 | { | ||
6423 | int8_t extoff; | ||
6424 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6425 | |||
6426 | if (!IS_CHAN_HT40(chan)) { | ||
6427 | centers->ctl_center = centers->ext_center = | ||
6428 | centers->synth_center = chan->channel; | ||
6429 | return; | ||
6430 | } | ||
6431 | |||
6432 | if ((chan->chanmode == CHANNEL_A_HT40PLUS) || | ||
6433 | (chan->chanmode == CHANNEL_G_HT40PLUS)) { | ||
6434 | centers->synth_center = | ||
6435 | chan->channel + HT40_CHANNEL_CENTER_SHIFT; | ||
6436 | extoff = 1; | ||
6437 | } else { | ||
6438 | centers->synth_center = | ||
6439 | chan->channel - HT40_CHANNEL_CENTER_SHIFT; | ||
6440 | extoff = -1; | ||
6441 | } | ||
6442 | |||
6443 | centers->ctl_center = centers->synth_center - (extoff * | ||
6444 | HT40_CHANNEL_CENTER_SHIFT); | ||
6445 | centers->ext_center = centers->synth_center + (extoff * | ||
6446 | ((ahp-> | ||
6447 | ah_extprotspacing | ||
6448 | == | ||
6449 | ATH9K_HT_EXTPROTSPACING_20) | ||
6450 | ? | ||
6451 | HT40_CHANNEL_CENTER_SHIFT | ||
6452 | : 15)); | ||
6453 | |||
6454 | } | ||
6455 | |||
6456 | void | ||
6457 | ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan, | ||
6458 | bool *isCalDone) | ||
6459 | { | ||
6460 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6461 | struct ath9k_channel *ichan = | ||
6462 | ath9k_regd_check_channel(ah, chan); | ||
6463 | struct hal_cal_list *currCal = ahp->ah_cal_list_curr; | ||
6464 | |||
6465 | *isCalDone = true; | ||
6466 | |||
6467 | if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) | ||
6468 | return; | ||
6469 | |||
6470 | if (currCal == NULL) | ||
6471 | return; | ||
6472 | |||
6473 | if (ichan == NULL) { | ||
6474 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6475 | "%s: invalid channel %u/0x%x; no mapping\n", | ||
6476 | __func__, chan->channel, chan->channelFlags); | ||
6477 | return; | ||
6478 | } | ||
6479 | |||
6480 | |||
6481 | if (currCal->calState != CAL_DONE) { | ||
6482 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6483 | "%s: Calibration state incorrect, %d\n", | ||
6484 | __func__, currCal->calState); | ||
6485 | return; | ||
6486 | } | ||
6487 | |||
6488 | |||
6489 | if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType)) | ||
6490 | return; | ||
6491 | |||
6492 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | ||
6493 | "%s: Resetting Cal %d state for channel %u/0x%x\n", | ||
6494 | __func__, currCal->calData->calType, chan->channel, | ||
6495 | chan->channelFlags); | ||
6496 | |||
6497 | ichan->CalValid &= ~currCal->calData->calType; | ||
6498 | currCal->calState = CAL_WAITING; | ||
6499 | |||
6500 | *isCalDone = false; | ||
6501 | } | ||
6502 | |||
6503 | void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac) | ||
6504 | { | ||
6505 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6506 | |||
6507 | memcpy(mac, ahp->ah_macaddr, ETH_ALEN); | ||
6508 | } | ||
6509 | |||
6510 | bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac) | ||
6511 | { | ||
6512 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6513 | |||
6514 | memcpy(ahp->ah_macaddr, mac, ETH_ALEN); | ||
6515 | return true; | ||
6516 | } | ||
6517 | |||
6518 | void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask) | ||
6519 | { | ||
6520 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6521 | |||
6522 | memcpy(mask, ahp->ah_bssidmask, ETH_ALEN); | ||
6523 | } | ||
6524 | |||
6525 | bool | ||
6526 | ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask) | ||
6527 | { | ||
6528 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6529 | |||
6530 | memcpy(ahp->ah_bssidmask, mask, ETH_ALEN); | ||
6531 | |||
6532 | REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask)); | ||
6533 | REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4)); | ||
6534 | |||
6535 | return true; | ||
6536 | } | ||
6537 | |||
6538 | #ifdef CONFIG_ATH9K_RFKILL | ||
6539 | static void ath9k_enable_rfkill(struct ath_hal *ah) | ||
6540 | { | ||
6541 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6542 | |||
6543 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
6544 | AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); | ||
6545 | |||
6546 | REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, | ||
6547 | AR_GPIO_INPUT_MUX2_RFSILENT); | ||
6548 | |||
6549 | ath9k_hw_cfg_gpio_input(ah, ahp->ah_gpioSelect); | ||
6550 | REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); | ||
6551 | |||
6552 | if (ahp->ah_gpioBit == ath9k_hw_gpio_get(ah, ahp->ah_gpioSelect)) { | ||
6553 | |||
6554 | ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect, | ||
6555 | !ahp->ah_gpioBit); | ||
6556 | } else { | ||
6557 | ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect, | ||
6558 | ahp->ah_gpioBit); | ||
6559 | } | ||
6560 | } | ||
6561 | #endif | ||
6562 | |||
6563 | void | ||
6564 | ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, | ||
6565 | u16 assocId) | ||
6566 | { | ||
6567 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6568 | |||
6569 | memcpy(ahp->ah_bssid, bssid, ETH_ALEN); | ||
6570 | ahp->ah_assocId = assocId; | ||
6571 | |||
6572 | REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid)); | ||
6573 | REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) | | ||
6574 | ((assocId & 0x3fff) << AR_BSS_ID1_AID_S)); | ||
6575 | } | ||
6576 | |||
6577 | u64 ath9k_hw_gettsf64(struct ath_hal *ah) | ||
6578 | { | ||
6579 | u64 tsf; | ||
6580 | |||
6581 | tsf = REG_READ(ah, AR_TSF_U32); | ||
6582 | tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32); | ||
6583 | return tsf; | ||
6584 | } | ||
6585 | |||
6586 | void ath9k_hw_reset_tsf(struct ath_hal *ah) | ||
6587 | { | ||
6588 | int count; | ||
6589 | |||
6590 | count = 0; | ||
6591 | while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) { | ||
6592 | count++; | ||
6593 | if (count > 10) { | ||
6594 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
6595 | "%s: AR_SLP32_TSF_WRITE_STATUS limit exceeded\n", | ||
6596 | __func__); | ||
6597 | break; | ||
6598 | } | ||
6599 | udelay(10); | ||
6600 | } | ||
6601 | REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); | ||
6602 | } | ||
6603 | |||
6604 | u32 ath9k_hw_getdefantenna(struct ath_hal *ah) | ||
6605 | { | ||
6606 | return REG_READ(ah, AR_DEF_ANTENNA) & 0x7; | ||
6607 | } | ||
6608 | |||
6609 | void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna) | ||
6610 | { | ||
6611 | REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); | ||
6612 | } | ||
6613 | |||
6614 | bool | ||
6615 | ath9k_hw_setantennaswitch(struct ath_hal *ah, | ||
6616 | enum ath9k_ant_setting settings, | ||
6617 | struct ath9k_channel *chan, | ||
6618 | u8 *tx_chainmask, | ||
6619 | u8 *rx_chainmask, | ||
6620 | u8 *antenna_cfgd) | ||
6621 | { | ||
6622 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6623 | static u8 tx_chainmask_cfg, rx_chainmask_cfg; | ||
6624 | |||
6625 | if (AR_SREV_9280(ah)) { | ||
6626 | if (!tx_chainmask_cfg) { | ||
6627 | |||
6628 | tx_chainmask_cfg = *tx_chainmask; | ||
6629 | rx_chainmask_cfg = *rx_chainmask; | ||
6630 | } | ||
6631 | |||
6632 | switch (settings) { | ||
6633 | case ATH9K_ANT_FIXED_A: | ||
6634 | *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK; | ||
6635 | *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK; | ||
6636 | *antenna_cfgd = true; | ||
6637 | break; | ||
6638 | case ATH9K_ANT_FIXED_B: | ||
6639 | if (ah->ah_caps.tx_chainmask > | ||
6640 | ATH9K_ANTENNA1_CHAINMASK) { | ||
6641 | *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK; | ||
6642 | } | ||
6643 | *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK; | ||
6644 | *antenna_cfgd = true; | ||
6645 | break; | ||
6646 | case ATH9K_ANT_VARIABLE: | ||
6647 | *tx_chainmask = tx_chainmask_cfg; | ||
6648 | *rx_chainmask = rx_chainmask_cfg; | ||
6649 | *antenna_cfgd = true; | ||
6650 | break; | ||
6651 | default: | ||
6652 | break; | ||
6653 | } | ||
6654 | } else { | ||
6655 | ahp->ah_diversityControl = settings; | ||
6656 | } | ||
6657 | |||
6658 | return true; | ||
6659 | } | ||
6660 | |||
6661 | void ath9k_hw_setopmode(struct ath_hal *ah) | ||
6662 | { | ||
6663 | ath9k_hw_set_operating_mode(ah, ah->ah_opmode); | ||
6664 | } | ||
6665 | |||
6666 | bool | ||
6667 | ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type, | ||
6668 | u32 capability, u32 *result) | ||
6669 | { | ||
6670 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6671 | const struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
6672 | |||
6673 | switch (type) { | ||
6674 | case ATH9K_CAP_CIPHER: | ||
6675 | switch (capability) { | ||
6676 | case ATH9K_CIPHER_AES_CCM: | ||
6677 | case ATH9K_CIPHER_AES_OCB: | ||
6678 | case ATH9K_CIPHER_TKIP: | ||
6679 | case ATH9K_CIPHER_WEP: | ||
6680 | case ATH9K_CIPHER_MIC: | ||
6681 | case ATH9K_CIPHER_CLR: | ||
6682 | return true; | ||
6683 | default: | ||
6684 | return false; | ||
6685 | } | ||
6686 | case ATH9K_CAP_TKIP_MIC: | ||
6687 | switch (capability) { | ||
6688 | case 0: | ||
6689 | return true; | ||
6690 | case 1: | ||
6691 | return (ahp->ah_staId1Defaults & | ||
6692 | AR_STA_ID1_CRPT_MIC_ENABLE) ? true : | ||
6693 | false; | ||
6694 | } | ||
6695 | case ATH9K_CAP_TKIP_SPLIT: | ||
6696 | return (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) ? | ||
6697 | false : true; | ||
6698 | case ATH9K_CAP_WME_TKIPMIC: | ||
6699 | return 0; | ||
6700 | case ATH9K_CAP_PHYCOUNTERS: | ||
6701 | return ahp->ah_hasHwPhyCounters ? 0 : -ENXIO; | ||
6702 | case ATH9K_CAP_DIVERSITY: | ||
6703 | return (REG_READ(ah, AR_PHY_CCK_DETECT) & | ||
6704 | AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ? | ||
6705 | true : false; | ||
6706 | case ATH9K_CAP_PHYDIAG: | ||
6707 | return true; | ||
6708 | case ATH9K_CAP_MCAST_KEYSRCH: | ||
6709 | switch (capability) { | ||
6710 | case 0: | ||
6711 | return true; | ||
6712 | case 1: | ||
6713 | if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) { | ||
6714 | return false; | ||
6715 | } else { | ||
6716 | return (ahp->ah_staId1Defaults & | ||
6717 | AR_STA_ID1_MCAST_KSRCH) ? true : | ||
6718 | false; | ||
6719 | } | ||
6720 | } | ||
6721 | return false; | ||
6722 | case ATH9K_CAP_TSF_ADJUST: | ||
6723 | return (ahp->ah_miscMode & AR_PCU_TX_ADD_TSF) ? | ||
6724 | true : false; | ||
6725 | case ATH9K_CAP_RFSILENT: | ||
6726 | if (capability == 3) | ||
6727 | return false; | ||
6728 | case ATH9K_CAP_ANT_CFG_2GHZ: | ||
6729 | *result = pCap->num_antcfg_2ghz; | ||
6730 | return true; | ||
6731 | case ATH9K_CAP_ANT_CFG_5GHZ: | ||
6732 | *result = pCap->num_antcfg_5ghz; | ||
6733 | return true; | ||
6734 | case ATH9K_CAP_TXPOW: | ||
6735 | switch (capability) { | ||
6736 | case 0: | ||
6737 | return 0; | ||
6738 | case 1: | ||
6739 | *result = ah->ah_powerLimit; | ||
6740 | return 0; | ||
6741 | case 2: | ||
6742 | *result = ah->ah_maxPowerLevel; | ||
6743 | return 0; | ||
6744 | case 3: | ||
6745 | *result = ah->ah_tpScale; | ||
6746 | return 0; | ||
6747 | } | ||
6748 | return false; | ||
6749 | default: | ||
6750 | return false; | ||
6751 | } | ||
6752 | } | ||
6753 | |||
6754 | int | ||
6755 | ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg) | ||
6756 | { | ||
6757 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6758 | struct ath9k_channel *chan = ah->ah_curchan; | ||
6759 | const struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
6760 | u16 ant_config; | ||
6761 | u32 halNumAntConfig; | ||
6762 | |||
6763 | halNumAntConfig = | ||
6764 | IS_CHAN_2GHZ(chan) ? pCap->num_antcfg_2ghz : pCap-> | ||
6765 | num_antcfg_5ghz; | ||
6766 | |||
6767 | if (cfg < halNumAntConfig) { | ||
6768 | if (!ath9k_hw_get_eeprom_antenna_cfg(ahp, chan, | ||
6769 | cfg, &ant_config)) { | ||
6770 | REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config); | ||
6771 | return 0; | ||
6772 | } | ||
6773 | } | ||
6774 | |||
6775 | return -EINVAL; | ||
6776 | } | ||
6777 | |||
6778 | bool ath9k_hw_intrpend(struct ath_hal *ah) | ||
6779 | { | ||
6780 | u32 host_isr; | ||
6781 | |||
6782 | if (AR_SREV_9100(ah)) | ||
6783 | return true; | ||
6784 | |||
6785 | host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); | ||
6786 | if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) | ||
6787 | return true; | ||
6788 | |||
6789 | host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); | ||
6790 | if ((host_isr & AR_INTR_SYNC_DEFAULT) | ||
6791 | && (host_isr != AR_INTR_SPURIOUS)) | ||
6792 | return true; | ||
6793 | |||
6794 | return false; | ||
6795 | } | ||
6796 | |||
6797 | bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked) | ||
6798 | { | ||
6799 | u32 isr = 0; | ||
6800 | u32 mask2 = 0; | ||
6801 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
6802 | u32 sync_cause = 0; | ||
6803 | bool fatal_int = false; | ||
6804 | |||
6805 | if (!AR_SREV_9100(ah)) { | ||
6806 | if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { | ||
6807 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) | ||
6808 | == AR_RTC_STATUS_ON) { | ||
6809 | isr = REG_READ(ah, AR_ISR); | ||
6810 | } | ||
6811 | } | ||
6812 | |||
6813 | sync_cause = | ||
6814 | REG_READ(ah, | ||
6815 | AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; | ||
6816 | |||
6817 | *masked = 0; | ||
6818 | |||
6819 | if (!isr && !sync_cause) | ||
6820 | return false; | ||
6821 | } else { | ||
6822 | *masked = 0; | ||
6823 | isr = REG_READ(ah, AR_ISR); | ||
6824 | } | ||
6825 | |||
6826 | if (isr) { | ||
6827 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6828 | |||
6829 | if (isr & AR_ISR_BCNMISC) { | ||
6830 | u32 isr2; | ||
6831 | isr2 = REG_READ(ah, AR_ISR_S2); | ||
6832 | if (isr2 & AR_ISR_S2_TIM) | ||
6833 | mask2 |= ATH9K_INT_TIM; | ||
6834 | if (isr2 & AR_ISR_S2_DTIM) | ||
6835 | mask2 |= ATH9K_INT_DTIM; | ||
6836 | if (isr2 & AR_ISR_S2_DTIMSYNC) | ||
6837 | mask2 |= ATH9K_INT_DTIMSYNC; | ||
6838 | if (isr2 & (AR_ISR_S2_CABEND)) | ||
6839 | mask2 |= ATH9K_INT_CABEND; | ||
6840 | if (isr2 & AR_ISR_S2_GTT) | ||
6841 | mask2 |= ATH9K_INT_GTT; | ||
6842 | if (isr2 & AR_ISR_S2_CST) | ||
6843 | mask2 |= ATH9K_INT_CST; | ||
6844 | } | ||
6845 | |||
6846 | isr = REG_READ(ah, AR_ISR_RAC); | ||
6847 | if (isr == 0xffffffff) { | ||
6848 | *masked = 0; | ||
6849 | return false; | ||
6850 | } | ||
6851 | |||
6852 | *masked = isr & ATH9K_INT_COMMON; | ||
6853 | |||
6854 | if (ahp->ah_intrMitigation) { | ||
6855 | |||
6856 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) | ||
6857 | *masked |= ATH9K_INT_RX; | ||
6858 | } | ||
6859 | |||
6860 | if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) | ||
6861 | *masked |= ATH9K_INT_RX; | ||
6862 | if (isr & | ||
6863 | (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | | ||
6864 | AR_ISR_TXEOL)) { | ||
6865 | u32 s0_s, s1_s; | ||
6866 | |||
6867 | *masked |= ATH9K_INT_TX; | ||
6868 | |||
6869 | s0_s = REG_READ(ah, AR_ISR_S0_S); | ||
6870 | ahp->ah_intrTxqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); | ||
6871 | ahp->ah_intrTxqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); | ||
6872 | |||
6873 | s1_s = REG_READ(ah, AR_ISR_S1_S); | ||
6874 | ahp->ah_intrTxqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); | ||
6875 | ahp->ah_intrTxqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); | ||
6876 | } | ||
6877 | |||
6878 | if (isr & AR_ISR_RXORN) { | ||
6879 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | ||
6880 | "%s: receive FIFO overrun interrupt\n", | ||
6881 | __func__); | ||
6882 | } | ||
6883 | |||
6884 | if (!AR_SREV_9100(ah)) { | ||
6885 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
6886 | u32 isr5 = REG_READ(ah, AR_ISR_S5_S); | ||
6887 | if (isr5 & AR_ISR_S5_TIM_TIMER) | ||
6888 | *masked |= ATH9K_INT_TIM_TIMER; | ||
6889 | } | ||
6890 | } | ||
6891 | |||
6892 | *masked |= mask2; | ||
6893 | } | ||
6894 | if (AR_SREV_9100(ah)) | ||
6895 | return true; | ||
6896 | if (sync_cause) { | ||
6897 | fatal_int = | ||
6898 | (sync_cause & | ||
6899 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) | ||
6900 | ? true : false; | ||
6901 | |||
6902 | if (fatal_int) { | ||
6903 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { | ||
6904 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
6905 | "%s: received PCI FATAL interrupt\n", | ||
6906 | __func__); | ||
6907 | } | ||
6908 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { | ||
6909 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
6910 | "%s: received PCI PERR interrupt\n", | ||
6911 | __func__); | ||
6912 | } | ||
6913 | } | ||
6914 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { | ||
6915 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | ||
6916 | "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n", | ||
6917 | __func__); | ||
6918 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); | ||
6919 | REG_WRITE(ah, AR_RC, 0); | ||
6920 | *masked |= ATH9K_INT_FATAL; | ||
6921 | } | ||
6922 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { | ||
6923 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | ||
6924 | "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n", | ||
6925 | __func__); | ||
6926 | } | ||
6927 | |||
6928 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); | ||
6929 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); | ||
6930 | } | ||
6931 | return true; | ||
6932 | } | ||
6933 | |||
6934 | enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah) | ||
6935 | { | ||
6936 | return AH5416(ah)->ah_maskReg; | ||
6937 | } | ||
6938 | |||
6939 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints) | ||
6940 | { | ||
6941 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
6942 | u32 omask = ahp->ah_maskReg; | ||
6943 | u32 mask, mask2; | ||
6944 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
6945 | |||
6946 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: 0x%x => 0x%x\n", __func__, | ||
6947 | omask, ints); | ||
6948 | |||
6949 | if (omask & ATH9K_INT_GLOBAL) { | ||
6950 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: disable IER\n", | ||
6951 | __func__); | ||
6952 | REG_WRITE(ah, AR_IER, AR_IER_DISABLE); | ||
6953 | (void) REG_READ(ah, AR_IER); | ||
6954 | if (!AR_SREV_9100(ah)) { | ||
6955 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); | ||
6956 | (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); | ||
6957 | |||
6958 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); | ||
6959 | (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); | ||
6960 | } | ||
6961 | } | ||
6962 | |||
6963 | mask = ints & ATH9K_INT_COMMON; | ||
6964 | mask2 = 0; | ||
6965 | |||
6966 | if (ints & ATH9K_INT_TX) { | ||
6967 | if (ahp->ah_txOkInterruptMask) | ||
6968 | mask |= AR_IMR_TXOK; | ||
6969 | if (ahp->ah_txDescInterruptMask) | ||
6970 | mask |= AR_IMR_TXDESC; | ||
6971 | if (ahp->ah_txErrInterruptMask) | ||
6972 | mask |= AR_IMR_TXERR; | ||
6973 | if (ahp->ah_txEolInterruptMask) | ||
6974 | mask |= AR_IMR_TXEOL; | ||
6975 | } | ||
6976 | if (ints & ATH9K_INT_RX) { | ||
6977 | mask |= AR_IMR_RXERR; | ||
6978 | if (ahp->ah_intrMitigation) | ||
6979 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; | ||
6980 | else | ||
6981 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; | ||
6982 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | ||
6983 | mask |= AR_IMR_GENTMR; | ||
6984 | } | ||
6985 | |||
6986 | if (ints & (ATH9K_INT_BMISC)) { | ||
6987 | mask |= AR_IMR_BCNMISC; | ||
6988 | if (ints & ATH9K_INT_TIM) | ||
6989 | mask2 |= AR_IMR_S2_TIM; | ||
6990 | if (ints & ATH9K_INT_DTIM) | ||
6991 | mask2 |= AR_IMR_S2_DTIM; | ||
6992 | if (ints & ATH9K_INT_DTIMSYNC) | ||
6993 | mask2 |= AR_IMR_S2_DTIMSYNC; | ||
6994 | if (ints & ATH9K_INT_CABEND) | ||
6995 | mask2 |= (AR_IMR_S2_CABEND); | ||
6996 | } | ||
6997 | |||
6998 | if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { | ||
6999 | mask |= AR_IMR_BCNMISC; | ||
7000 | if (ints & ATH9K_INT_GTT) | ||
7001 | mask2 |= AR_IMR_S2_GTT; | ||
7002 | if (ints & ATH9K_INT_CST) | ||
7003 | mask2 |= AR_IMR_S2_CST; | ||
7004 | } | ||
7005 | |||
7006 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, | ||
7007 | mask); | ||
7008 | REG_WRITE(ah, AR_IMR, mask); | ||
7009 | mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | | ||
7010 | AR_IMR_S2_DTIM | | ||
7011 | AR_IMR_S2_DTIMSYNC | | ||
7012 | AR_IMR_S2_CABEND | | ||
7013 | AR_IMR_S2_CABTO | | ||
7014 | AR_IMR_S2_TSFOOR | | ||
7015 | AR_IMR_S2_GTT | AR_IMR_S2_CST); | ||
7016 | REG_WRITE(ah, AR_IMR_S2, mask | mask2); | ||
7017 | ahp->ah_maskReg = ints; | ||
7018 | |||
7019 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
7020 | if (ints & ATH9K_INT_TIM_TIMER) | ||
7021 | REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); | ||
7022 | else | ||
7023 | REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); | ||
7024 | } | ||
7025 | |||
7026 | if (ints & ATH9K_INT_GLOBAL) { | ||
7027 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: enable IER\n", | ||
7028 | __func__); | ||
7029 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); | ||
7030 | if (!AR_SREV_9100(ah)) { | ||
7031 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, | ||
7032 | AR_INTR_MAC_IRQ); | ||
7033 | REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); | ||
7034 | |||
7035 | |||
7036 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, | ||
7037 | AR_INTR_SYNC_DEFAULT); | ||
7038 | REG_WRITE(ah, AR_INTR_SYNC_MASK, | ||
7039 | AR_INTR_SYNC_DEFAULT); | ||
7040 | } | ||
7041 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", | ||
7042 | REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); | ||
7043 | } | ||
7044 | |||
7045 | return omask; | ||
7046 | } | ||
7047 | |||
7048 | void | ||
7049 | ath9k_hw_beaconinit(struct ath_hal *ah, | ||
7050 | u32 next_beacon, u32 beacon_period) | ||
7051 | { | ||
7052 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7053 | int flags = 0; | ||
7054 | |||
7055 | ahp->ah_beaconInterval = beacon_period; | ||
7056 | |||
7057 | switch (ah->ah_opmode) { | ||
7058 | case ATH9K_M_STA: | ||
7059 | case ATH9K_M_MONITOR: | ||
7060 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); | ||
7061 | REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff); | ||
7062 | REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff); | ||
7063 | flags |= AR_TBTT_TIMER_EN; | ||
7064 | break; | ||
7065 | case ATH9K_M_IBSS: | ||
7066 | REG_SET_BIT(ah, AR_TXCFG, | ||
7067 | AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); | ||
7068 | REG_WRITE(ah, AR_NEXT_NDP_TIMER, | ||
7069 | TU_TO_USEC(next_beacon + | ||
7070 | (ahp->ah_atimWindow ? ahp-> | ||
7071 | ah_atimWindow : 1))); | ||
7072 | flags |= AR_NDP_TIMER_EN; | ||
7073 | case ATH9K_M_HOSTAP: | ||
7074 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); | ||
7075 | REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, | ||
7076 | TU_TO_USEC(next_beacon - | ||
7077 | ah->ah_config. | ||
7078 | dma_beacon_response_time)); | ||
7079 | REG_WRITE(ah, AR_NEXT_SWBA, | ||
7080 | TU_TO_USEC(next_beacon - | ||
7081 | ah->ah_config. | ||
7082 | sw_beacon_response_time)); | ||
7083 | flags |= | ||
7084 | AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; | ||
7085 | break; | ||
7086 | } | ||
7087 | |||
7088 | REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); | ||
7089 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); | ||
7090 | REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); | ||
7091 | REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); | ||
7092 | |||
7093 | beacon_period &= ~ATH9K_BEACON_ENA; | ||
7094 | if (beacon_period & ATH9K_BEACON_RESET_TSF) { | ||
7095 | beacon_period &= ~ATH9K_BEACON_RESET_TSF; | ||
7096 | ath9k_hw_reset_tsf(ah); | ||
7097 | } | ||
7098 | |||
7099 | REG_SET_BIT(ah, AR_TIMER_MODE, flags); | ||
7100 | } | ||
7101 | |||
7102 | void | ||
7103 | ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah, | ||
7104 | const struct ath9k_beacon_state *bs) | ||
7105 | { | ||
7106 | u32 nextTbtt, beaconintval, dtimperiod, beacontimeout; | ||
7107 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
7108 | |||
7109 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); | ||
7110 | |||
7111 | REG_WRITE(ah, AR_BEACON_PERIOD, | ||
7112 | TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); | ||
7113 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, | ||
7114 | TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); | ||
7115 | |||
7116 | REG_RMW_FIELD(ah, AR_RSSI_THR, | ||
7117 | AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); | ||
7118 | |||
7119 | beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD; | ||
7120 | |||
7121 | if (bs->bs_sleepduration > beaconintval) | ||
7122 | beaconintval = bs->bs_sleepduration; | ||
7123 | |||
7124 | dtimperiod = bs->bs_dtimperiod; | ||
7125 | if (bs->bs_sleepduration > dtimperiod) | ||
7126 | dtimperiod = bs->bs_sleepduration; | ||
7127 | |||
7128 | if (beaconintval == dtimperiod) | ||
7129 | nextTbtt = bs->bs_nextdtim; | ||
7130 | else | ||
7131 | nextTbtt = bs->bs_nexttbtt; | ||
7132 | |||
7133 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: next DTIM %d\n", __func__, | ||
7134 | bs->bs_nextdtim); | ||
7135 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: next beacon %d\n", __func__, | ||
7136 | nextTbtt); | ||
7137 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: beacon period %d\n", __func__, | ||
7138 | beaconintval); | ||
7139 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: DTIM period %d\n", __func__, | ||
7140 | dtimperiod); | ||
7141 | |||
7142 | REG_WRITE(ah, AR_NEXT_DTIM, | ||
7143 | TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); | ||
7144 | REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); | ||
7145 | |||
7146 | REG_WRITE(ah, AR_SLEEP1, | ||
7147 | SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) | ||
7148 | | AR_SLEEP1_ASSUME_DTIM); | ||
7149 | |||
7150 | if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP) | ||
7151 | beacontimeout = (BEACON_TIMEOUT_VAL << 3); | ||
7152 | else | ||
7153 | beacontimeout = MIN_BEACON_TIMEOUT_VAL; | ||
7154 | |||
7155 | REG_WRITE(ah, AR_SLEEP2, | ||
7156 | SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); | ||
7157 | |||
7158 | REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); | ||
7159 | REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); | ||
7160 | |||
7161 | REG_SET_BIT(ah, AR_TIMER_MODE, | ||
7162 | AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | | ||
7163 | AR_DTIM_TIMER_EN); | ||
7164 | |||
7165 | } | ||
7166 | |||
7167 | bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry) | ||
7168 | { | ||
7169 | if (entry < ah->ah_caps.keycache_size) { | ||
7170 | u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry)); | ||
7171 | if (val & AR_KEYTABLE_VALID) | ||
7172 | return true; | ||
7173 | } | ||
7174 | return false; | ||
7175 | } | ||
7176 | |||
7177 | bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry) | ||
7178 | { | ||
7179 | u32 keyType; | ||
7180 | |||
7181 | if (entry >= ah->ah_caps.keycache_size) { | ||
7182 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7183 | "%s: entry %u out of range\n", __func__, entry); | ||
7184 | return false; | ||
7185 | } | ||
7186 | keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); | ||
7187 | |||
7188 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); | ||
7189 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); | ||
7190 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); | ||
7191 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); | ||
7192 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); | ||
7193 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); | ||
7194 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); | ||
7195 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); | ||
7196 | |||
7197 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
7198 | u16 micentry = entry + 64; | ||
7199 | |||
7200 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); | ||
7201 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
7202 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); | ||
7203 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
7204 | |||
7205 | } | ||
7206 | |||
7207 | if (ah->ah_curchan == NULL) | ||
7208 | return true; | ||
7209 | |||
7210 | return true; | ||
7211 | } | ||
7212 | |||
7213 | bool | ||
7214 | ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, | ||
7215 | const u8 *mac) | ||
7216 | { | ||
7217 | u32 macHi, macLo; | ||
7218 | |||
7219 | if (entry >= ah->ah_caps.keycache_size) { | ||
7220 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7221 | "%s: entry %u out of range\n", __func__, entry); | ||
7222 | return false; | ||
7223 | } | ||
7224 | |||
7225 | if (mac != NULL) { | ||
7226 | macHi = (mac[5] << 8) | mac[4]; | ||
7227 | macLo = (mac[3] << 24) | (mac[2] << 16) | ||
7228 | | (mac[1] << 8) | mac[0]; | ||
7229 | macLo >>= 1; | ||
7230 | macLo |= (macHi & 1) << 31; | ||
7231 | macHi >>= 1; | ||
7232 | } else { | ||
7233 | macLo = macHi = 0; | ||
7234 | } | ||
7235 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); | ||
7236 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); | ||
7237 | |||
7238 | return true; | ||
7239 | } | ||
7240 | |||
7241 | bool | ||
7242 | ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry, | ||
7243 | const struct ath9k_keyval *k, | ||
7244 | const u8 *mac, int xorKey) | ||
7245 | { | ||
7246 | const struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
7247 | u32 key0, key1, key2, key3, key4; | ||
7248 | u32 keyType; | ||
7249 | u32 xorMask = xorKey ? | ||
7250 | (ATH9K_KEY_XOR << 24 | ATH9K_KEY_XOR << 16 | ATH9K_KEY_XOR << 8 | ||
7251 | | ATH9K_KEY_XOR) : 0; | ||
7252 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7253 | |||
7254 | if (entry >= pCap->keycache_size) { | ||
7255 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7256 | "%s: entry %u out of range\n", __func__, entry); | ||
7257 | return false; | ||
7258 | } | ||
7259 | switch (k->kv_type) { | ||
7260 | case ATH9K_CIPHER_AES_OCB: | ||
7261 | keyType = AR_KEYTABLE_TYPE_AES; | ||
7262 | break; | ||
7263 | case ATH9K_CIPHER_AES_CCM: | ||
7264 | if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { | ||
7265 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7266 | "%s: AES-CCM not supported by " | ||
7267 | "mac rev 0x%x\n", __func__, | ||
7268 | ah->ah_macRev); | ||
7269 | return false; | ||
7270 | } | ||
7271 | keyType = AR_KEYTABLE_TYPE_CCM; | ||
7272 | break; | ||
7273 | case ATH9K_CIPHER_TKIP: | ||
7274 | keyType = AR_KEYTABLE_TYPE_TKIP; | ||
7275 | if (ATH9K_IS_MIC_ENABLED(ah) | ||
7276 | && entry + 64 >= pCap->keycache_size) { | ||
7277 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7278 | "%s: entry %u inappropriate for TKIP\n", | ||
7279 | __func__, entry); | ||
7280 | return false; | ||
7281 | } | ||
7282 | break; | ||
7283 | case ATH9K_CIPHER_WEP: | ||
7284 | if (k->kv_len < 40 / NBBY) { | ||
7285 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7286 | "%s: WEP key length %u too small\n", | ||
7287 | __func__, k->kv_len); | ||
7288 | return false; | ||
7289 | } | ||
7290 | if (k->kv_len <= 40 / NBBY) | ||
7291 | keyType = AR_KEYTABLE_TYPE_40; | ||
7292 | else if (k->kv_len <= 104 / NBBY) | ||
7293 | keyType = AR_KEYTABLE_TYPE_104; | ||
7294 | else | ||
7295 | keyType = AR_KEYTABLE_TYPE_128; | ||
7296 | break; | ||
7297 | case ATH9K_CIPHER_CLR: | ||
7298 | keyType = AR_KEYTABLE_TYPE_CLR; | ||
7299 | break; | ||
7300 | default: | ||
7301 | DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE, | ||
7302 | "%s: cipher %u not supported\n", __func__, | ||
7303 | k->kv_type); | ||
7304 | return false; | ||
7305 | } | ||
7306 | |||
7307 | key0 = get_unaligned_le32(k->kv_val + 0) ^ xorMask; | ||
7308 | key1 = (get_unaligned_le16(k->kv_val + 4) ^ xorMask) & 0xffff; | ||
7309 | key2 = get_unaligned_le32(k->kv_val + 6) ^ xorMask; | ||
7310 | key3 = (get_unaligned_le16(k->kv_val + 10) ^ xorMask) & 0xffff; | ||
7311 | key4 = get_unaligned_le32(k->kv_val + 12) ^ xorMask; | ||
7312 | if (k->kv_len <= 104 / NBBY) | ||
7313 | key4 &= 0xff; | ||
7314 | |||
7315 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
7316 | u16 micentry = entry + 64; | ||
7317 | |||
7318 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); | ||
7319 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); | ||
7320 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
7321 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
7322 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
7323 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
7324 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
7325 | |||
7326 | if (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) { | ||
7327 | u32 mic0, mic1, mic2, mic3, mic4; | ||
7328 | |||
7329 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
7330 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
7331 | mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; | ||
7332 | mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; | ||
7333 | mic4 = get_unaligned_le32(k->kv_txmic + 4); | ||
7334 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
7335 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); | ||
7336 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
7337 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); | ||
7338 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); | ||
7339 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
7340 | AR_KEYTABLE_TYPE_CLR); | ||
7341 | |||
7342 | } else { | ||
7343 | u32 mic0, mic2; | ||
7344 | |||
7345 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
7346 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
7347 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
7348 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
7349 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
7350 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
7351 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); | ||
7352 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
7353 | AR_KEYTABLE_TYPE_CLR); | ||
7354 | } | ||
7355 | REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); | ||
7356 | REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); | ||
7357 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
7358 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
7359 | } else { | ||
7360 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
7361 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
7362 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
7363 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
7364 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
7365 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
7366 | |||
7367 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
7368 | } | ||
7369 | |||
7370 | if (ah->ah_curchan == NULL) | ||
7371 | return true; | ||
7372 | |||
7373 | return true; | ||
7374 | } | ||
7375 | |||
7376 | bool | ||
7377 | ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel) | ||
7378 | { | ||
7379 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7380 | u32 txcfg, curLevel, newLevel; | ||
7381 | enum ath9k_int omask; | ||
7382 | |||
7383 | if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD) | ||
7384 | return false; | ||
7385 | |||
7386 | omask = ath9k_hw_set_interrupts(ah, | ||
7387 | ahp->ah_maskReg & ~ATH9K_INT_GLOBAL); | ||
7388 | |||
7389 | txcfg = REG_READ(ah, AR_TXCFG); | ||
7390 | curLevel = MS(txcfg, AR_FTRIG); | ||
7391 | newLevel = curLevel; | ||
7392 | if (bIncTrigLevel) { | ||
7393 | if (curLevel < MAX_TX_FIFO_THRESHOLD) | ||
7394 | newLevel++; | ||
7395 | } else if (curLevel > MIN_TX_FIFO_THRESHOLD) | ||
7396 | newLevel--; | ||
7397 | if (newLevel != curLevel) | ||
7398 | REG_WRITE(ah, AR_TXCFG, | ||
7399 | (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); | ||
7400 | |||
7401 | ath9k_hw_set_interrupts(ah, omask); | ||
7402 | |||
7403 | ah->ah_txTrigLevel = newLevel; | ||
7404 | |||
7405 | return newLevel != curLevel; | ||
7406 | } | ||
7407 | |||
7408 | bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q, | ||
7409 | const struct ath9k_tx_queue_info *qinfo) | ||
7410 | { | ||
7411 | u32 cw; | ||
7412 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7413 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
7414 | struct ath9k_tx_queue_info *qi; | ||
7415 | |||
7416 | if (q >= pCap->total_queues) { | ||
7417 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n", | ||
7418 | __func__, q); | ||
7419 | return false; | ||
7420 | } | ||
7421 | |||
7422 | qi = &ahp->ah_txq[q]; | ||
7423 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
7424 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n", | ||
7425 | __func__); | ||
7426 | return false; | ||
7427 | } | ||
7428 | |||
7429 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %p\n", __func__, qi); | ||
7430 | |||
7431 | qi->tqi_ver = qinfo->tqi_ver; | ||
7432 | qi->tqi_subtype = qinfo->tqi_subtype; | ||
7433 | qi->tqi_qflags = qinfo->tqi_qflags; | ||
7434 | qi->tqi_priority = qinfo->tqi_priority; | ||
7435 | if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT) | ||
7436 | qi->tqi_aifs = min(qinfo->tqi_aifs, 255U); | ||
7437 | else | ||
7438 | qi->tqi_aifs = INIT_AIFS; | ||
7439 | if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) { | ||
7440 | cw = min(qinfo->tqi_cwmin, 1024U); | ||
7441 | qi->tqi_cwmin = 1; | ||
7442 | while (qi->tqi_cwmin < cw) | ||
7443 | qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; | ||
7444 | } else | ||
7445 | qi->tqi_cwmin = qinfo->tqi_cwmin; | ||
7446 | if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) { | ||
7447 | cw = min(qinfo->tqi_cwmax, 1024U); | ||
7448 | qi->tqi_cwmax = 1; | ||
7449 | while (qi->tqi_cwmax < cw) | ||
7450 | qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; | ||
7451 | } else | ||
7452 | qi->tqi_cwmax = INIT_CWMAX; | ||
7453 | |||
7454 | if (qinfo->tqi_shretry != 0) | ||
7455 | qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U); | ||
7456 | else | ||
7457 | qi->tqi_shretry = INIT_SH_RETRY; | ||
7458 | if (qinfo->tqi_lgretry != 0) | ||
7459 | qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U); | ||
7460 | else | ||
7461 | qi->tqi_lgretry = INIT_LG_RETRY; | ||
7462 | qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod; | ||
7463 | qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit; | ||
7464 | qi->tqi_burstTime = qinfo->tqi_burstTime; | ||
7465 | qi->tqi_readyTime = qinfo->tqi_readyTime; | ||
7466 | |||
7467 | switch (qinfo->tqi_subtype) { | ||
7468 | case ATH9K_WME_UPSD: | ||
7469 | if (qi->tqi_type == ATH9K_TX_QUEUE_DATA) | ||
7470 | qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS; | ||
7471 | break; | ||
7472 | default: | ||
7473 | break; | ||
7474 | } | ||
7475 | return true; | ||
7476 | } | ||
7477 | |||
7478 | bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q, | ||
7479 | struct ath9k_tx_queue_info *qinfo) | ||
7480 | { | ||
7481 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7482 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
7483 | struct ath9k_tx_queue_info *qi; | ||
7484 | |||
7485 | if (q >= pCap->total_queues) { | ||
7486 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n", | ||
7487 | __func__, q); | ||
7488 | return false; | ||
7489 | } | ||
7490 | |||
7491 | qi = &ahp->ah_txq[q]; | ||
7492 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
7493 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n", | ||
7494 | __func__); | ||
7495 | return false; | ||
7496 | } | ||
7497 | |||
7498 | qinfo->tqi_qflags = qi->tqi_qflags; | ||
7499 | qinfo->tqi_ver = qi->tqi_ver; | ||
7500 | qinfo->tqi_subtype = qi->tqi_subtype; | ||
7501 | qinfo->tqi_qflags = qi->tqi_qflags; | ||
7502 | qinfo->tqi_priority = qi->tqi_priority; | ||
7503 | qinfo->tqi_aifs = qi->tqi_aifs; | ||
7504 | qinfo->tqi_cwmin = qi->tqi_cwmin; | ||
7505 | qinfo->tqi_cwmax = qi->tqi_cwmax; | ||
7506 | qinfo->tqi_shretry = qi->tqi_shretry; | ||
7507 | qinfo->tqi_lgretry = qi->tqi_lgretry; | ||
7508 | qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; | ||
7509 | qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; | ||
7510 | qinfo->tqi_burstTime = qi->tqi_burstTime; | ||
7511 | qinfo->tqi_readyTime = qi->tqi_readyTime; | ||
7512 | |||
7513 | return true; | ||
7514 | } | ||
7515 | |||
7516 | int | ||
7517 | ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type, | ||
7518 | const struct ath9k_tx_queue_info *qinfo) | ||
7519 | { | ||
7520 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7521 | struct ath9k_tx_queue_info *qi; | ||
7522 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
7523 | int q; | ||
7524 | |||
7525 | switch (type) { | ||
7526 | case ATH9K_TX_QUEUE_BEACON: | ||
7527 | q = pCap->total_queues - 1; | ||
7528 | break; | ||
7529 | case ATH9K_TX_QUEUE_CAB: | ||
7530 | q = pCap->total_queues - 2; | ||
7531 | break; | ||
7532 | case ATH9K_TX_QUEUE_PSPOLL: | ||
7533 | q = 1; | ||
7534 | break; | ||
7535 | case ATH9K_TX_QUEUE_UAPSD: | ||
7536 | q = pCap->total_queues - 3; | ||
7537 | break; | ||
7538 | case ATH9K_TX_QUEUE_DATA: | ||
7539 | for (q = 0; q < pCap->total_queues; q++) | ||
7540 | if (ahp->ah_txq[q].tqi_type == | ||
7541 | ATH9K_TX_QUEUE_INACTIVE) | ||
7542 | break; | ||
7543 | if (q == pCap->total_queues) { | ||
7544 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
7545 | "%s: no available tx queue\n", __func__); | ||
7546 | return -1; | ||
7547 | } | ||
7548 | break; | ||
7549 | default: | ||
7550 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: bad tx queue type %u\n", | ||
7551 | __func__, type); | ||
7552 | return -1; | ||
7553 | } | ||
7554 | |||
7555 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q); | ||
7556 | |||
7557 | qi = &ahp->ah_txq[q]; | ||
7558 | if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { | ||
7559 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
7560 | "%s: tx queue %u already active\n", __func__, q); | ||
7561 | return -1; | ||
7562 | } | ||
7563 | memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); | ||
7564 | qi->tqi_type = type; | ||
7565 | if (qinfo == NULL) { | ||
7566 | qi->tqi_qflags = | ||
7567 | TXQ_FLAG_TXOKINT_ENABLE | ||
7568 | | TXQ_FLAG_TXERRINT_ENABLE | ||
7569 | | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE; | ||
7570 | qi->tqi_aifs = INIT_AIFS; | ||
7571 | qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT; | ||
7572 | qi->tqi_cwmax = INIT_CWMAX; | ||
7573 | qi->tqi_shretry = INIT_SH_RETRY; | ||
7574 | qi->tqi_lgretry = INIT_LG_RETRY; | ||
7575 | qi->tqi_physCompBuf = 0; | ||
7576 | } else { | ||
7577 | qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; | ||
7578 | (void) ath9k_hw_set_txq_props(ah, q, qinfo); | ||
7579 | } | ||
7580 | |||
7581 | return q; | ||
7582 | } | ||
7583 | |||
7584 | static void | ||
7585 | ath9k_hw_set_txq_interrupts(struct ath_hal *ah, | ||
7586 | struct ath9k_tx_queue_info *qi) | ||
7587 | { | ||
7588 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7589 | |||
7590 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | ||
7591 | "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", | ||
7592 | __func__, ahp->ah_txOkInterruptMask, | ||
7593 | ahp->ah_txErrInterruptMask, ahp->ah_txDescInterruptMask, | ||
7594 | ahp->ah_txEolInterruptMask, ahp->ah_txUrnInterruptMask); | ||
7595 | |||
7596 | REG_WRITE(ah, AR_IMR_S0, | ||
7597 | SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK) | ||
7598 | | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC)); | ||
7599 | REG_WRITE(ah, AR_IMR_S1, | ||
7600 | SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR) | ||
7601 | | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL)); | ||
7602 | REG_RMW_FIELD(ah, AR_IMR_S2, | ||
7603 | AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask); | ||
7604 | } | ||
7605 | |||
7606 | bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q) | ||
7607 | { | ||
7608 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7609 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
7610 | struct ath9k_tx_queue_info *qi; | ||
7611 | |||
7612 | if (q >= pCap->total_queues) { | ||
7613 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n", | ||
7614 | __func__, q); | ||
7615 | return false; | ||
7616 | } | ||
7617 | qi = &ahp->ah_txq[q]; | ||
7618 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
7619 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n", | ||
7620 | __func__, q); | ||
7621 | return false; | ||
7622 | } | ||
7623 | |||
7624 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: release queue %u\n", | ||
7625 | __func__, q); | ||
7626 | |||
7627 | qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; | ||
7628 | ahp->ah_txOkInterruptMask &= ~(1 << q); | ||
7629 | ahp->ah_txErrInterruptMask &= ~(1 << q); | ||
7630 | ahp->ah_txDescInterruptMask &= ~(1 << q); | ||
7631 | ahp->ah_txEolInterruptMask &= ~(1 << q); | ||
7632 | ahp->ah_txUrnInterruptMask &= ~(1 << q); | ||
7633 | ath9k_hw_set_txq_interrupts(ah, qi); | ||
7634 | |||
7635 | return true; | ||
7636 | } | ||
7637 | |||
7638 | bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q) | ||
7639 | { | ||
7640 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7641 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
7642 | struct ath9k_channel *chan = ah->ah_curchan; | ||
7643 | struct ath9k_tx_queue_info *qi; | ||
7644 | u32 cwMin, chanCwMin, value; | ||
7645 | |||
7646 | if (q >= pCap->total_queues) { | ||
7647 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n", | ||
7648 | __func__, q); | ||
7649 | return false; | ||
7650 | } | ||
7651 | qi = &ahp->ah_txq[q]; | ||
7652 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
7653 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n", | ||
7654 | __func__, q); | ||
7655 | return true; | ||
7656 | } | ||
7657 | |||
7658 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: reset queue %u\n", __func__, q); | ||
7659 | |||
7660 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { | ||
7661 | if (chan && IS_CHAN_B(chan)) | ||
7662 | chanCwMin = INIT_CWMIN_11B; | ||
7663 | else | ||
7664 | chanCwMin = INIT_CWMIN; | ||
7665 | |||
7666 | for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); | ||
7667 | } else | ||
7668 | cwMin = qi->tqi_cwmin; | ||
7669 | |||
7670 | REG_WRITE(ah, AR_DLCL_IFS(q), SM(cwMin, AR_D_LCL_IFS_CWMIN) | ||
7671 | | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | ||
7672 | | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); | ||
7673 | |||
7674 | REG_WRITE(ah, AR_DRETRY_LIMIT(q), | ||
7675 | SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) | ||
7676 | | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) | ||
7677 | | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) | ||
7678 | ); | ||
7679 | |||
7680 | REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); | ||
7681 | REG_WRITE(ah, AR_DMISC(q), | ||
7682 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); | ||
7683 | |||
7684 | if (qi->tqi_cbrPeriod) { | ||
7685 | REG_WRITE(ah, AR_QCBRCFG(q), | ||
7686 | SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | ||
7687 | | SM(qi->tqi_cbrOverflowLimit, | ||
7688 | AR_Q_CBRCFG_OVF_THRESH)); | ||
7689 | REG_WRITE(ah, AR_QMISC(q), | ||
7690 | REG_READ(ah, | ||
7691 | AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | (qi-> | ||
7692 | tqi_cbrOverflowLimit | ||
7693 | ? | ||
7694 | AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN | ||
7695 | : | ||
7696 | 0)); | ||
7697 | } | ||
7698 | if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { | ||
7699 | REG_WRITE(ah, AR_QRDYTIMECFG(q), | ||
7700 | SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) | | ||
7701 | AR_Q_RDYTIMECFG_EN); | ||
7702 | } | ||
7703 | |||
7704 | REG_WRITE(ah, AR_DCHNTIME(q), | ||
7705 | SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | | ||
7706 | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); | ||
7707 | |||
7708 | if (qi->tqi_burstTime | ||
7709 | && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) { | ||
7710 | REG_WRITE(ah, AR_QMISC(q), | ||
7711 | REG_READ(ah, | ||
7712 | AR_QMISC(q)) | | ||
7713 | AR_Q_MISC_RDYTIME_EXP_POLICY); | ||
7714 | |||
7715 | } | ||
7716 | |||
7717 | if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) { | ||
7718 | REG_WRITE(ah, AR_DMISC(q), | ||
7719 | REG_READ(ah, AR_DMISC(q)) | | ||
7720 | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
7721 | } | ||
7722 | if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { | ||
7723 | REG_WRITE(ah, AR_DMISC(q), | ||
7724 | REG_READ(ah, AR_DMISC(q)) | | ||
7725 | AR_D_MISC_FRAG_BKOFF_EN); | ||
7726 | } | ||
7727 | switch (qi->tqi_type) { | ||
7728 | case ATH9K_TX_QUEUE_BEACON: | ||
7729 | REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) | ||
7730 | | AR_Q_MISC_FSP_DBA_GATED | ||
7731 | | AR_Q_MISC_BEACON_USE | ||
7732 | | AR_Q_MISC_CBR_INCR_DIS1); | ||
7733 | |||
7734 | REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | ||
7735 | | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << | ||
7736 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S) | ||
7737 | | AR_D_MISC_BEACON_USE | ||
7738 | | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
7739 | break; | ||
7740 | case ATH9K_TX_QUEUE_CAB: | ||
7741 | REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) | ||
7742 | | AR_Q_MISC_FSP_DBA_GATED | ||
7743 | | AR_Q_MISC_CBR_INCR_DIS1 | ||
7744 | | AR_Q_MISC_CBR_INCR_DIS0); | ||
7745 | value = (qi->tqi_readyTime | ||
7746 | - (ah->ah_config.sw_beacon_response_time - | ||
7747 | ah->ah_config.dma_beacon_response_time) | ||
7748 | - | ||
7749 | ah->ah_config.additional_swba_backoff) * | ||
7750 | 1024; | ||
7751 | REG_WRITE(ah, AR_QRDYTIMECFG(q), | ||
7752 | value | AR_Q_RDYTIMECFG_EN); | ||
7753 | REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | ||
7754 | | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << | ||
7755 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); | ||
7756 | break; | ||
7757 | case ATH9K_TX_QUEUE_PSPOLL: | ||
7758 | REG_WRITE(ah, AR_QMISC(q), | ||
7759 | REG_READ(ah, | ||
7760 | AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); | ||
7761 | break; | ||
7762 | case ATH9K_TX_QUEUE_UAPSD: | ||
7763 | REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | ||
7764 | | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
7765 | break; | ||
7766 | default: | ||
7767 | break; | ||
7768 | } | ||
7769 | |||
7770 | if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { | ||
7771 | REG_WRITE(ah, AR_DMISC(q), | ||
7772 | REG_READ(ah, AR_DMISC(q)) | | ||
7773 | SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, | ||
7774 | AR_D_MISC_ARB_LOCKOUT_CNTRL) | | ||
7775 | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
7776 | } | ||
7777 | |||
7778 | if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE) | ||
7779 | ahp->ah_txOkInterruptMask |= 1 << q; | ||
7780 | else | ||
7781 | ahp->ah_txOkInterruptMask &= ~(1 << q); | ||
7782 | if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE) | ||
7783 | ahp->ah_txErrInterruptMask |= 1 << q; | ||
7784 | else | ||
7785 | ahp->ah_txErrInterruptMask &= ~(1 << q); | ||
7786 | if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE) | ||
7787 | ahp->ah_txDescInterruptMask |= 1 << q; | ||
7788 | else | ||
7789 | ahp->ah_txDescInterruptMask &= ~(1 << q); | ||
7790 | if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE) | ||
7791 | ahp->ah_txEolInterruptMask |= 1 << q; | ||
7792 | else | ||
7793 | ahp->ah_txEolInterruptMask &= ~(1 << q); | ||
7794 | if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE) | ||
7795 | ahp->ah_txUrnInterruptMask |= 1 << q; | ||
7796 | else | ||
7797 | ahp->ah_txUrnInterruptMask &= ~(1 << q); | ||
7798 | ath9k_hw_set_txq_interrupts(ah, qi); | ||
7799 | |||
7800 | return true; | ||
7801 | } | ||
7802 | |||
7803 | void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs) | ||
7804 | { | ||
7805 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7806 | *txqs &= ahp->ah_intrTxqs; | ||
7807 | ahp->ah_intrTxqs &= ~(*txqs); | ||
7808 | } | ||
7809 | |||
7810 | bool | ||
7811 | ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
7812 | u32 segLen, bool firstSeg, | ||
7813 | bool lastSeg, const struct ath_desc *ds0) | ||
7814 | { | ||
7815 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7816 | |||
7817 | if (firstSeg) { | ||
7818 | ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); | ||
7819 | } else if (lastSeg) { | ||
7820 | ads->ds_ctl0 = 0; | ||
7821 | ads->ds_ctl1 = segLen; | ||
7822 | ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; | ||
7823 | ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; | ||
7824 | } else { | ||
7825 | ads->ds_ctl0 = 0; | ||
7826 | ads->ds_ctl1 = segLen | AR_TxMore; | ||
7827 | ads->ds_ctl2 = 0; | ||
7828 | ads->ds_ctl3 = 0; | ||
7829 | } | ||
7830 | ads->ds_txstatus0 = ads->ds_txstatus1 = 0; | ||
7831 | ads->ds_txstatus2 = ads->ds_txstatus3 = 0; | ||
7832 | ads->ds_txstatus4 = ads->ds_txstatus5 = 0; | ||
7833 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | ||
7834 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | ||
7835 | return true; | ||
7836 | } | ||
7837 | |||
7838 | void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds) | ||
7839 | { | ||
7840 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7841 | |||
7842 | ads->ds_txstatus0 = ads->ds_txstatus1 = 0; | ||
7843 | ads->ds_txstatus2 = ads->ds_txstatus3 = 0; | ||
7844 | ads->ds_txstatus4 = ads->ds_txstatus5 = 0; | ||
7845 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | ||
7846 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | ||
7847 | } | ||
7848 | |||
7849 | int | ||
7850 | ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds) | ||
7851 | { | ||
7852 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7853 | |||
7854 | if ((ads->ds_txstatus9 & AR_TxDone) == 0) | ||
7855 | return -EINPROGRESS; | ||
7856 | |||
7857 | ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); | ||
7858 | ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp; | ||
7859 | ds->ds_txstat.ts_status = 0; | ||
7860 | ds->ds_txstat.ts_flags = 0; | ||
7861 | |||
7862 | if (ads->ds_txstatus1 & AR_ExcessiveRetries) | ||
7863 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; | ||
7864 | if (ads->ds_txstatus1 & AR_Filtered) | ||
7865 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; | ||
7866 | if (ads->ds_txstatus1 & AR_FIFOUnderrun) | ||
7867 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; | ||
7868 | if (ads->ds_txstatus9 & AR_TxOpExceeded) | ||
7869 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; | ||
7870 | if (ads->ds_txstatus1 & AR_TxTimerExpired) | ||
7871 | ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED; | ||
7872 | |||
7873 | if (ads->ds_txstatus1 & AR_DescCfgErr) | ||
7874 | ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR; | ||
7875 | if (ads->ds_txstatus1 & AR_TxDataUnderrun) { | ||
7876 | ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN; | ||
7877 | ath9k_hw_updatetxtriglevel(ah, true); | ||
7878 | } | ||
7879 | if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { | ||
7880 | ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN; | ||
7881 | ath9k_hw_updatetxtriglevel(ah, true); | ||
7882 | } | ||
7883 | if (ads->ds_txstatus0 & AR_TxBaStatus) { | ||
7884 | ds->ds_txstat.ts_flags |= ATH9K_TX_BA; | ||
7885 | ds->ds_txstat.ba_low = ads->AR_BaBitmapLow; | ||
7886 | ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh; | ||
7887 | } | ||
7888 | |||
7889 | ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); | ||
7890 | switch (ds->ds_txstat.ts_rateindex) { | ||
7891 | case 0: | ||
7892 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); | ||
7893 | break; | ||
7894 | case 1: | ||
7895 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); | ||
7896 | break; | ||
7897 | case 2: | ||
7898 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); | ||
7899 | break; | ||
7900 | case 3: | ||
7901 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); | ||
7902 | break; | ||
7903 | } | ||
7904 | |||
7905 | ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); | ||
7906 | ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); | ||
7907 | ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); | ||
7908 | ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); | ||
7909 | ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); | ||
7910 | ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); | ||
7911 | ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); | ||
7912 | ds->ds_txstat.evm0 = ads->AR_TxEVM0; | ||
7913 | ds->ds_txstat.evm1 = ads->AR_TxEVM1; | ||
7914 | ds->ds_txstat.evm2 = ads->AR_TxEVM2; | ||
7915 | ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); | ||
7916 | ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); | ||
7917 | ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); | ||
7918 | ds->ds_txstat.ts_antenna = 1; | ||
7919 | |||
7920 | return 0; | ||
7921 | } | ||
7922 | |||
7923 | void | ||
7924 | ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
7925 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, | ||
7926 | u32 keyIx, enum ath9k_key_type keyType, u32 flags) | ||
7927 | { | ||
7928 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7929 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
7930 | |||
7931 | txPower += ahp->ah_txPowerIndexOffset; | ||
7932 | if (txPower > 63) | ||
7933 | txPower = 63; | ||
7934 | |||
7935 | ads->ds_ctl0 = (pktLen & AR_FrameLen) | ||
7936 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | ||
7937 | | SM(txPower, AR_XmitPower) | ||
7938 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | ||
7939 | | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | ||
7940 | | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) | ||
7941 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); | ||
7942 | |||
7943 | ads->ds_ctl1 = | ||
7944 | (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) | ||
7945 | | SM(type, AR_FrameType) | ||
7946 | | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) | ||
7947 | | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) | ||
7948 | | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); | ||
7949 | |||
7950 | ads->ds_ctl6 = SM(keyType, AR_EncrType); | ||
7951 | |||
7952 | if (AR_SREV_9285(ah)) { | ||
7953 | |||
7954 | ads->ds_ctl8 = 0; | ||
7955 | ads->ds_ctl9 = 0; | ||
7956 | ads->ds_ctl10 = 0; | ||
7957 | ads->ds_ctl11 = 0; | ||
7958 | } | ||
7959 | } | ||
7960 | |||
7961 | void | ||
7962 | ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds, | ||
7963 | struct ath_desc *lastds, | ||
7964 | u32 durUpdateEn, u32 rtsctsRate, | ||
7965 | u32 rtsctsDuration, | ||
7966 | struct ath9k_11n_rate_series series[], | ||
7967 | u32 nseries, u32 flags) | ||
7968 | { | ||
7969 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
7970 | struct ar5416_desc *last_ads = AR5416DESC(lastds); | ||
7971 | u32 ds_ctl0; | ||
7972 | |||
7973 | (void) nseries; | ||
7974 | (void) rtsctsDuration; | ||
7975 | |||
7976 | if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { | ||
7977 | ds_ctl0 = ads->ds_ctl0; | ||
7978 | |||
7979 | if (flags & ATH9K_TXDESC_RTSENA) { | ||
7980 | ds_ctl0 &= ~AR_CTSEnable; | ||
7981 | ds_ctl0 |= AR_RTSEnable; | ||
7982 | } else { | ||
7983 | ds_ctl0 &= ~AR_RTSEnable; | ||
7984 | ds_ctl0 |= AR_CTSEnable; | ||
7985 | } | ||
7986 | |||
7987 | ads->ds_ctl0 = ds_ctl0; | ||
7988 | } else { | ||
7989 | ads->ds_ctl0 = | ||
7990 | (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); | ||
7991 | } | ||
7992 | |||
7993 | ads->ds_ctl2 = set11nTries(series, 0) | ||
7994 | | set11nTries(series, 1) | ||
7995 | | set11nTries(series, 2) | ||
7996 | | set11nTries(series, 3) | ||
7997 | | (durUpdateEn ? AR_DurUpdateEna : 0) | ||
7998 | | SM(0, AR_BurstDur); | ||
7999 | |||
8000 | ads->ds_ctl3 = set11nRate(series, 0) | ||
8001 | | set11nRate(series, 1) | ||
8002 | | set11nRate(series, 2) | ||
8003 | | set11nRate(series, 3); | ||
8004 | |||
8005 | ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) | ||
8006 | | set11nPktDurRTSCTS(series, 1); | ||
8007 | |||
8008 | ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) | ||
8009 | | set11nPktDurRTSCTS(series, 3); | ||
8010 | |||
8011 | ads->ds_ctl7 = set11nRateFlags(series, 0) | ||
8012 | | set11nRateFlags(series, 1) | ||
8013 | | set11nRateFlags(series, 2) | ||
8014 | | set11nRateFlags(series, 3) | ||
8015 | | SM(rtsctsRate, AR_RTSCTSRate); | ||
8016 | last_ads->ds_ctl2 = ads->ds_ctl2; | ||
8017 | last_ads->ds_ctl3 = ads->ds_ctl3; | ||
8018 | } | ||
8019 | |||
8020 | void | ||
8021 | ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds, | ||
8022 | u32 aggrLen) | ||
8023 | { | ||
8024 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8025 | |||
8026 | ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); | ||
8027 | |||
8028 | ads->ds_ctl6 &= ~AR_AggrLen; | ||
8029 | ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); | ||
8030 | } | ||
8031 | |||
8032 | void | ||
8033 | ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds, | ||
8034 | u32 numDelims) | ||
8035 | { | ||
8036 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8037 | unsigned int ctl6; | ||
8038 | |||
8039 | ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); | ||
8040 | |||
8041 | ctl6 = ads->ds_ctl6; | ||
8042 | ctl6 &= ~AR_PadDelim; | ||
8043 | ctl6 |= SM(numDelims, AR_PadDelim); | ||
8044 | ads->ds_ctl6 = ctl6; | ||
8045 | } | ||
8046 | |||
8047 | void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds) | ||
8048 | { | ||
8049 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8050 | |||
8051 | ads->ds_ctl1 |= AR_IsAggr; | ||
8052 | ads->ds_ctl1 &= ~AR_MoreAggr; | ||
8053 | ads->ds_ctl6 &= ~AR_PadDelim; | ||
8054 | } | ||
8055 | |||
8056 | void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds) | ||
8057 | { | ||
8058 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8059 | |||
8060 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); | ||
8061 | } | ||
8062 | |||
8063 | void | ||
8064 | ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds, | ||
8065 | u32 burstDuration) | ||
8066 | { | ||
8067 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8068 | |||
8069 | ads->ds_ctl2 &= ~AR_BurstDur; | ||
8070 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); | ||
8071 | } | ||
8072 | |||
8073 | void | ||
8074 | ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds, | ||
8075 | u32 vmf) | ||
8076 | { | ||
8077 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8078 | |||
8079 | if (vmf) | ||
8080 | ads->ds_ctl0 |= AR_VirtMoreFrag; | ||
8081 | else | ||
8082 | ads->ds_ctl0 &= ~AR_VirtMoreFrag; | ||
8083 | } | ||
8084 | |||
8085 | void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp) | ||
8086 | { | ||
8087 | REG_WRITE(ah, AR_RXDP, rxdp); | ||
8088 | } | ||
8089 | |||
8090 | void ath9k_hw_rxena(struct ath_hal *ah) | ||
8091 | { | ||
8092 | REG_WRITE(ah, AR_CR, AR_CR_RXE); | ||
8093 | } | ||
8094 | |||
8095 | bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set) | ||
8096 | { | ||
8097 | if (set) { | ||
8098 | |||
8099 | REG_SET_BIT(ah, AR_DIAG_SW, | ||
8100 | (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | ||
8101 | |||
8102 | if (!ath9k_hw_wait | ||
8103 | (ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0)) { | ||
8104 | u32 reg; | ||
8105 | |||
8106 | REG_CLR_BIT(ah, AR_DIAG_SW, | ||
8107 | (AR_DIAG_RX_DIS | | ||
8108 | AR_DIAG_RX_ABORT)); | ||
8109 | |||
8110 | reg = REG_READ(ah, AR_OBS_BUS_1); | ||
8111 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
8112 | "%s: rx failed to go idle in 10 ms RXSM=0x%x\n", | ||
8113 | __func__, reg); | ||
8114 | |||
8115 | return false; | ||
8116 | } | ||
8117 | } else { | ||
8118 | REG_CLR_BIT(ah, AR_DIAG_SW, | ||
8119 | (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | ||
8120 | } | ||
8121 | |||
8122 | return true; | ||
8123 | } | ||
8124 | |||
8125 | void | ||
8126 | ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, | ||
8127 | u32 filter1) | ||
8128 | { | ||
8129 | REG_WRITE(ah, AR_MCAST_FIL0, filter0); | ||
8130 | REG_WRITE(ah, AR_MCAST_FIL1, filter1); | ||
8131 | } | ||
8132 | |||
8133 | bool | ||
8134 | ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
8135 | u32 size, u32 flags) | ||
8136 | { | ||
8137 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
8138 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
8139 | |||
8140 | ads->ds_ctl1 = size & AR_BufLen; | ||
8141 | if (flags & ATH9K_RXDESC_INTREQ) | ||
8142 | ads->ds_ctl1 |= AR_RxIntrReq; | ||
8143 | |||
8144 | ads->ds_rxstatus8 &= ~AR_RxDone; | ||
8145 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | ||
8146 | memset(&(ads->u), 0, sizeof(ads->u)); | ||
8147 | return true; | ||
8148 | } | ||
8149 | |||
8150 | int | ||
8151 | ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds, | ||
8152 | u32 pa, struct ath_desc *nds, u64 tsf) | ||
8153 | { | ||
8154 | struct ar5416_desc ads; | ||
8155 | struct ar5416_desc *adsp = AR5416DESC(ds); | ||
8156 | |||
8157 | if ((adsp->ds_rxstatus8 & AR_RxDone) == 0) | ||
8158 | return -EINPROGRESS; | ||
8159 | |||
8160 | ads.u.rx = adsp->u.rx; | ||
8161 | |||
8162 | ds->ds_rxstat.rs_status = 0; | ||
8163 | ds->ds_rxstat.rs_flags = 0; | ||
8164 | |||
8165 | ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; | ||
8166 | ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; | ||
8167 | |||
8168 | ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); | ||
8169 | ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00); | ||
8170 | ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01); | ||
8171 | ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02); | ||
8172 | ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10); | ||
8173 | ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11); | ||
8174 | ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12); | ||
8175 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) | ||
8176 | ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); | ||
8177 | else | ||
8178 | ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID; | ||
8179 | |||
8180 | ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads)); | ||
8181 | ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; | ||
8182 | |||
8183 | ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; | ||
8184 | ds->ds_rxstat.rs_moreaggr = | ||
8185 | (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; | ||
8186 | ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); | ||
8187 | ds->ds_rxstat.rs_flags = | ||
8188 | (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; | ||
8189 | ds->ds_rxstat.rs_flags |= | ||
8190 | (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; | ||
8191 | |||
8192 | if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) | ||
8193 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE; | ||
8194 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) | ||
8195 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST; | ||
8196 | if (ads.ds_rxstatus8 & AR_DecryptBusyErr) | ||
8197 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY; | ||
8198 | |||
8199 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { | ||
8200 | |||
8201 | if (ads.ds_rxstatus8 & AR_CRCErr) | ||
8202 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC; | ||
8203 | else if (ads.ds_rxstatus8 & AR_PHYErr) { | ||
8204 | u32 phyerr; | ||
8205 | |||
8206 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY; | ||
8207 | phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); | ||
8208 | ds->ds_rxstat.rs_phyerr = phyerr; | ||
8209 | } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) | ||
8210 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT; | ||
8211 | else if (ads.ds_rxstatus8 & AR_MichaelErr) | ||
8212 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC; | ||
8213 | } | ||
8214 | |||
8215 | return 0; | ||
8216 | } | ||
8217 | |||
8218 | static void ath9k_hw_setup_rate_table(struct ath_hal *ah, | ||
8219 | struct ath9k_rate_table *rt) | ||
8220 | { | ||
8221 | int i; | ||
8222 | |||
8223 | if (rt->rateCodeToIndex[0] != 0) | ||
8224 | return; | ||
8225 | for (i = 0; i < 256; i++) | ||
8226 | rt->rateCodeToIndex[i] = (u8) -1; | ||
8227 | for (i = 0; i < rt->rateCount; i++) { | ||
8228 | u8 code = rt->info[i].rateCode; | ||
8229 | u8 cix = rt->info[i].controlRate; | ||
8230 | |||
8231 | rt->rateCodeToIndex[code] = i; | ||
8232 | rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i; | ||
8233 | |||
8234 | rt->info[i].lpAckDuration = | ||
8235 | ath9k_hw_computetxtime(ah, rt, | ||
8236 | WLAN_CTRL_FRAME_SIZE, | ||
8237 | cix, | ||
8238 | false); | ||
8239 | rt->info[i].spAckDuration = | ||
8240 | ath9k_hw_computetxtime(ah, rt, | ||
8241 | WLAN_CTRL_FRAME_SIZE, | ||
8242 | cix, | ||
8243 | true); | ||
8244 | } | ||
8245 | } | ||
8246 | |||
8247 | const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah, | ||
8248 | u32 mode) | ||
8249 | { | ||
8250 | struct ath9k_rate_table *rt; | ||
8251 | switch (mode) { | ||
8252 | case ATH9K_MODE_11A: | ||
8253 | rt = &ar5416_11a_table; | ||
8254 | break; | ||
8255 | case ATH9K_MODE_11B: | ||
8256 | rt = &ar5416_11b_table; | ||
8257 | break; | ||
8258 | case ATH9K_MODE_11G: | ||
8259 | rt = &ar5416_11g_table; | ||
8260 | break; | ||
8261 | case ATH9K_MODE_11NG_HT20: | ||
8262 | case ATH9K_MODE_11NG_HT40PLUS: | ||
8263 | case ATH9K_MODE_11NG_HT40MINUS: | ||
8264 | rt = &ar5416_11ng_table; | ||
8265 | break; | ||
8266 | case ATH9K_MODE_11NA_HT20: | ||
8267 | case ATH9K_MODE_11NA_HT40PLUS: | ||
8268 | case ATH9K_MODE_11NA_HT40MINUS: | ||
8269 | rt = &ar5416_11na_table; | ||
8270 | break; | ||
8271 | default: | ||
8272 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "%s: invalid mode 0x%x\n", | ||
8273 | __func__, mode); | ||
8274 | return NULL; | ||
8275 | } | ||
8276 | ath9k_hw_setup_rate_table(ah, rt); | ||
8277 | return rt; | ||
8278 | } | ||
8279 | |||
8280 | static const char *ath9k_hw_devname(u16 devid) | ||
8281 | { | ||
8282 | switch (devid) { | ||
8283 | case AR5416_DEVID_PCI: | ||
8284 | case AR5416_DEVID_PCIE: | ||
8285 | return "Atheros 5416"; | ||
8286 | case AR9160_DEVID_PCI: | ||
8287 | return "Atheros 9160"; | ||
8288 | case AR9280_DEVID_PCI: | ||
8289 | case AR9280_DEVID_PCIE: | ||
8290 | return "Atheros 9280"; | ||
8291 | } | ||
8292 | return NULL; | ||
8293 | } | ||
8294 | |||
8295 | const char *ath9k_hw_probe(u16 vendorid, u16 devid) | ||
8296 | { | ||
8297 | return vendorid == ATHEROS_VENDOR_ID ? | ||
8298 | ath9k_hw_devname(devid) : NULL; | ||
8299 | } | ||
8300 | |||
8301 | struct ath_hal *ath9k_hw_attach(u16 devid, | ||
8302 | struct ath_softc *sc, | ||
8303 | void __iomem *mem, | ||
8304 | int *error) | ||
8305 | { | ||
8306 | struct ath_hal *ah = NULL; | ||
8307 | |||
8308 | switch (devid) { | ||
8309 | case AR5416_DEVID_PCI: | ||
8310 | case AR5416_DEVID_PCIE: | ||
8311 | case AR9160_DEVID_PCI: | ||
8312 | case AR9280_DEVID_PCI: | ||
8313 | case AR9280_DEVID_PCIE: | ||
8314 | ah = ath9k_hw_do_attach(devid, sc, mem, error); | ||
8315 | break; | ||
8316 | default: | ||
8317 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | ||
8318 | "devid=0x%x not supported.\n", devid); | ||
8319 | ah = NULL; | ||
8320 | *error = -ENXIO; | ||
8321 | break; | ||
8322 | } | ||
8323 | if (ah != NULL) { | ||
8324 | ah->ah_devid = ah->ah_devid; | ||
8325 | ah->ah_subvendorid = ah->ah_subvendorid; | ||
8326 | ah->ah_macVersion = ah->ah_macVersion; | ||
8327 | ah->ah_macRev = ah->ah_macRev; | ||
8328 | ah->ah_phyRev = ah->ah_phyRev; | ||
8329 | ah->ah_analog5GhzRev = ah->ah_analog5GhzRev; | ||
8330 | ah->ah_analog2GhzRev = ah->ah_analog2GhzRev; | ||
8331 | } | ||
8332 | return ah; | ||
8333 | } | ||
8334 | |||
8335 | u16 | ||
8336 | ath9k_hw_computetxtime(struct ath_hal *ah, | ||
8337 | const struct ath9k_rate_table *rates, | ||
8338 | u32 frameLen, u16 rateix, | ||
8339 | bool shortPreamble) | ||
8340 | { | ||
8341 | u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; | ||
8342 | u32 kbps; | ||
8343 | |||
8344 | kbps = rates->info[rateix].rateKbps; | ||
8345 | |||
8346 | if (kbps == 0) | ||
8347 | return 0; | ||
8348 | switch (rates->info[rateix].phy) { | ||
8349 | |||
8350 | case PHY_CCK: | ||
8351 | phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; | ||
8352 | if (shortPreamble && rates->info[rateix].shortPreamble) | ||
8353 | phyTime >>= 1; | ||
8354 | numBits = frameLen << 3; | ||
8355 | txTime = CCK_SIFS_TIME + phyTime | ||
8356 | + ((numBits * 1000) / kbps); | ||
8357 | break; | ||
8358 | case PHY_OFDM: | ||
8359 | if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) { | ||
8360 | bitsPerSymbol = | ||
8361 | (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; | ||
8362 | |||
8363 | numBits = OFDM_PLCP_BITS + (frameLen << 3); | ||
8364 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); | ||
8365 | txTime = OFDM_SIFS_TIME_QUARTER | ||
8366 | + OFDM_PREAMBLE_TIME_QUARTER | ||
8367 | + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); | ||
8368 | } else if (ah->ah_curchan && | ||
8369 | IS_CHAN_HALF_RATE(ah->ah_curchan)) { | ||
8370 | bitsPerSymbol = | ||
8371 | (kbps * OFDM_SYMBOL_TIME_HALF) / 1000; | ||
8372 | |||
8373 | numBits = OFDM_PLCP_BITS + (frameLen << 3); | ||
8374 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); | ||
8375 | txTime = OFDM_SIFS_TIME_HALF + | ||
8376 | OFDM_PREAMBLE_TIME_HALF | ||
8377 | + (numSymbols * OFDM_SYMBOL_TIME_HALF); | ||
8378 | } else { | ||
8379 | bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; | ||
8380 | |||
8381 | numBits = OFDM_PLCP_BITS + (frameLen << 3); | ||
8382 | numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); | ||
8383 | txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME | ||
8384 | + (numSymbols * OFDM_SYMBOL_TIME); | ||
8385 | } | ||
8386 | break; | ||
8387 | |||
8388 | default: | ||
8389 | DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO, | ||
8390 | "%s: unknown phy %u (rate ix %u)\n", __func__, | ||
8391 | rates->info[rateix].phy, rateix); | ||
8392 | txTime = 0; | ||
8393 | break; | ||
8394 | } | ||
8395 | return txTime; | ||
8396 | } | ||
8397 | |||
8398 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags) | ||
8399 | { | ||
8400 | if (flags & CHANNEL_2GHZ) { | ||
8401 | if (freq == 2484) | ||
8402 | return 14; | ||
8403 | if (freq < 2484) | ||
8404 | return (freq - 2407) / 5; | ||
8405 | else | ||
8406 | return 15 + ((freq - 2512) / 20); | ||
8407 | } else if (flags & CHANNEL_5GHZ) { | ||
8408 | if (ath9k_regd_is_public_safety_sku(ah) && | ||
8409 | IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { | ||
8410 | return ((freq * 10) + | ||
8411 | (((freq % 5) == 2) ? 5 : 0) - 49400) / 5; | ||
8412 | } else if ((flags & CHANNEL_A) && (freq <= 5000)) { | ||
8413 | return (freq - 4000) / 5; | ||
8414 | } else { | ||
8415 | return (freq - 5000) / 5; | ||
8416 | } | ||
8417 | } else { | ||
8418 | if (freq == 2484) | ||
8419 | return 14; | ||
8420 | if (freq < 2484) | ||
8421 | return (freq - 2407) / 5; | ||
8422 | if (freq < 5000) { | ||
8423 | if (ath9k_regd_is_public_safety_sku(ah) | ||
8424 | && IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) { | ||
8425 | return ((freq * 10) + | ||
8426 | (((freq % 5) == | ||
8427 | 2) ? 5 : 0) - 49400) / 5; | ||
8428 | } else if (freq > 4900) { | ||
8429 | return (freq - 4000) / 5; | ||
8430 | } else { | ||
8431 | return 15 + ((freq - 2512) / 20); | ||
8432 | } | ||
8433 | } | ||
8434 | return (freq - 5000) / 5; | ||
8435 | } | ||
8436 | } | ||
8437 | |||
8438 | int16_t | ||
8439 | ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) | ||
8440 | { | ||
8441 | struct ath9k_channel *ichan; | ||
8442 | |||
8443 | ichan = ath9k_regd_check_channel(ah, chan); | ||
8444 | if (ichan == NULL) { | ||
8445 | DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, | ||
8446 | "%s: invalid channel %u/0x%x; no mapping\n", | ||
8447 | __func__, chan->channel, chan->channelFlags); | ||
8448 | return 0; | ||
8449 | } | ||
8450 | if (ichan->rawNoiseFloor == 0) { | ||
8451 | enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan); | ||
8452 | return NOISE_FLOOR[mode]; | ||
8453 | } else | ||
8454 | return ichan->rawNoiseFloor; | ||
8455 | } | ||
8456 | |||
8457 | bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting) | ||
8458 | { | ||
8459 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
8460 | |||
8461 | if (setting) | ||
8462 | ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF; | ||
8463 | else | ||
8464 | ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF; | ||
8465 | return true; | ||
8466 | } | ||
8467 | |||
8468 | bool ath9k_hw_phycounters(struct ath_hal *ah) | ||
8469 | { | ||
8470 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
8471 | |||
8472 | return ahp->ah_hasHwPhyCounters ? true : false; | ||
8473 | } | ||
8474 | |||
8475 | u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q) | ||
8476 | { | ||
8477 | return REG_READ(ah, AR_QTXDP(q)); | ||
8478 | } | ||
8479 | |||
8480 | bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, | ||
8481 | u32 txdp) | ||
8482 | { | ||
8483 | REG_WRITE(ah, AR_QTXDP(q), txdp); | ||
8484 | |||
8485 | return true; | ||
8486 | } | ||
8487 | |||
8488 | bool ath9k_hw_txstart(struct ath_hal *ah, u32 q) | ||
8489 | { | ||
8490 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q); | ||
8491 | |||
8492 | REG_WRITE(ah, AR_Q_TXE, 1 << q); | ||
8493 | |||
8494 | return true; | ||
8495 | } | ||
8496 | |||
8497 | u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q) | ||
8498 | { | ||
8499 | u32 npend; | ||
8500 | |||
8501 | npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; | ||
8502 | if (npend == 0) { | ||
8503 | |||
8504 | if (REG_READ(ah, AR_Q_TXE) & (1 << q)) | ||
8505 | npend = 1; | ||
8506 | } | ||
8507 | return npend; | ||
8508 | } | ||
8509 | |||
8510 | bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) | ||
8511 | { | ||
8512 | u32 wait; | ||
8513 | |||
8514 | REG_WRITE(ah, AR_Q_TXD, 1 << q); | ||
8515 | |||
8516 | for (wait = 1000; wait != 0; wait--) { | ||
8517 | if (ath9k_hw_numtxpending(ah, q) == 0) | ||
8518 | break; | ||
8519 | udelay(100); | ||
8520 | } | ||
8521 | |||
8522 | if (ath9k_hw_numtxpending(ah, q)) { | ||
8523 | u32 tsfLow, j; | ||
8524 | |||
8525 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
8526 | "%s: Num of pending TX Frames %d on Q %d\n", | ||
8527 | __func__, ath9k_hw_numtxpending(ah, q), q); | ||
8528 | |||
8529 | for (j = 0; j < 2; j++) { | ||
8530 | tsfLow = REG_READ(ah, AR_TSF_L32); | ||
8531 | REG_WRITE(ah, AR_QUIET2, | ||
8532 | SM(10, AR_QUIET2_QUIET_DUR)); | ||
8533 | REG_WRITE(ah, AR_QUIET_PERIOD, 100); | ||
8534 | REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); | ||
8535 | REG_SET_BIT(ah, AR_TIMER_MODE, | ||
8536 | AR_QUIET_TIMER_EN); | ||
8537 | |||
8538 | if ((REG_READ(ah, AR_TSF_L32) >> 10) == | ||
8539 | (tsfLow >> 10)) { | ||
8540 | break; | ||
8541 | } | ||
8542 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | ||
8543 | "%s: TSF have moved while trying to set " | ||
8544 | "quiet time TSF: 0x%08x\n", | ||
8545 | __func__, tsfLow); | ||
8546 | } | ||
8547 | |||
8548 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | ||
8549 | |||
8550 | udelay(200); | ||
8551 | REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); | ||
8552 | |||
8553 | wait = 1000; | ||
8554 | |||
8555 | while (ath9k_hw_numtxpending(ah, q)) { | ||
8556 | if ((--wait) == 0) { | ||
8557 | DPRINTF(ah->ah_sc, ATH_DBG_XMIT, | ||
8558 | "%s: Failed to stop Tx DMA in 100 " | ||
8559 | "msec after killing last frame\n", | ||
8560 | __func__); | ||
8561 | break; | ||
8562 | } | ||
8563 | udelay(100); | ||
8564 | } | ||
8565 | |||
8566 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | ||
8567 | } | ||
8568 | |||
8569 | REG_WRITE(ah, AR_Q_TXD, 0); | ||
8570 | return wait != 0; | ||
8571 | } | ||
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h new file mode 100644 index 000000000000..ae680f21ba7e --- /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 000000000000..3dd3815940a4 --- /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 000000000000..2888778040e4 --- /dev/null +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -0,0 +1,1470 @@ | |||
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) ? | ||
511 | CHANNEL_G : CHANNEL_A; | ||
512 | |||
513 | if (sc->sc_curaid && hw->conf.ht_conf.ht_supported) | ||
514 | sc->sc_ah->ah_channels[pos].chanmode = | ||
515 | ath_get_extchanmode(sc, curchan); | ||
516 | |||
517 | sc->sc_config.txpowlimit = 2 * conf->power_level; | ||
518 | |||
519 | /* set h/w channel */ | ||
520 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | ||
521 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n", | ||
522 | __func__); | ||
523 | |||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int ath9k_config_interface(struct ieee80211_hw *hw, | ||
528 | struct ieee80211_vif *vif, | ||
529 | struct ieee80211_if_conf *conf) | ||
530 | { | ||
531 | struct ath_softc *sc = hw->priv; | ||
532 | struct ath_vap *avp; | ||
533 | u32 rfilt = 0; | ||
534 | int error, i; | ||
535 | DECLARE_MAC_BUF(mac); | ||
536 | |||
537 | avp = sc->sc_vaps[0]; | ||
538 | if (avp == NULL) { | ||
539 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", | ||
540 | __func__); | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | |||
544 | if ((conf->changed & IEEE80211_IFCC_BSSID) && | ||
545 | !is_zero_ether_addr(conf->bssid)) { | ||
546 | switch (vif->type) { | ||
547 | case IEEE80211_IF_TYPE_STA: | ||
548 | case IEEE80211_IF_TYPE_IBSS: | ||
549 | /* Update ratectrl about the new state */ | ||
550 | ath_rate_newstate(sc, avp); | ||
551 | |||
552 | /* Set rx filter */ | ||
553 | rfilt = ath_calcrxfilter(sc); | ||
554 | ath9k_hw_setrxfilter(sc->sc_ah, rfilt); | ||
555 | |||
556 | /* Set BSSID */ | ||
557 | memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN); | ||
558 | sc->sc_curaid = 0; | ||
559 | ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid, | ||
560 | sc->sc_curaid); | ||
561 | |||
562 | /* Set aggregation protection mode parameters */ | ||
563 | sc->sc_config.ath_aggr_prot = 0; | ||
564 | |||
565 | /* | ||
566 | * Reset our TSF so that its value is lower than the | ||
567 | * beacon that we are trying to catch. | ||
568 | * Only then hw will update its TSF register with the | ||
569 | * new beacon. Reset the TSF before setting the BSSID | ||
570 | * to avoid allowing in any frames that would update | ||
571 | * our TSF only to have us clear it | ||
572 | * immediately thereafter. | ||
573 | */ | ||
574 | ath9k_hw_reset_tsf(sc->sc_ah); | ||
575 | |||
576 | /* Disable BMISS interrupt when we're not associated */ | ||
577 | ath9k_hw_set_interrupts(sc->sc_ah, | ||
578 | sc->sc_imask & | ||
579 | ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS)); | ||
580 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | ||
581 | |||
582 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
583 | "%s: RX filter 0x%x bssid %s aid 0x%x\n", | ||
584 | __func__, rfilt, | ||
585 | print_mac(mac, sc->sc_curbssid), sc->sc_curaid); | ||
586 | |||
587 | /* need to reconfigure the beacon */ | ||
588 | sc->sc_beacons = 0; | ||
589 | |||
590 | break; | ||
591 | default: | ||
592 | break; | ||
593 | } | ||
594 | } | ||
595 | |||
596 | if ((conf->changed & IEEE80211_IFCC_BEACON) && | ||
597 | (vif->type == IEEE80211_IF_TYPE_IBSS)) { | ||
598 | /* | ||
599 | * Allocate and setup the beacon frame. | ||
600 | * | ||
601 | * Stop any previous beacon DMA. This may be | ||
602 | * necessary, for example, when an ibss merge | ||
603 | * causes reconfiguration; we may be called | ||
604 | * with beacon transmission active. | ||
605 | */ | ||
606 | ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); | ||
607 | |||
608 | error = ath_beacon_alloc(sc, 0); | ||
609 | if (error != 0) | ||
610 | return error; | ||
611 | |||
612 | ath_beacon_sync(sc, 0); | ||
613 | } | ||
614 | |||
615 | /* Check for WLAN_CAPABILITY_PRIVACY ? */ | ||
616 | if ((avp->av_opmode != IEEE80211_IF_TYPE_STA)) { | ||
617 | for (i = 0; i < IEEE80211_WEP_NKID; i++) | ||
618 | if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) | ||
619 | ath9k_hw_keysetmac(sc->sc_ah, | ||
620 | (u16)i, | ||
621 | sc->sc_curbssid); | ||
622 | } | ||
623 | |||
624 | /* Only legacy IBSS for now */ | ||
625 | if (vif->type == IEEE80211_IF_TYPE_IBSS) | ||
626 | ath_update_chainmask(sc, 0); | ||
627 | |||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | #define SUPPORTED_FILTERS \ | ||
632 | (FIF_PROMISC_IN_BSS | \ | ||
633 | FIF_ALLMULTI | \ | ||
634 | FIF_CONTROL | \ | ||
635 | FIF_OTHER_BSS | \ | ||
636 | FIF_BCN_PRBRESP_PROMISC | \ | ||
637 | FIF_FCSFAIL) | ||
638 | |||
639 | /* Accept unicast, bcast and mcast frames */ | ||
640 | |||
641 | static void ath9k_configure_filter(struct ieee80211_hw *hw, | ||
642 | unsigned int changed_flags, | ||
643 | unsigned int *total_flags, | ||
644 | int mc_count, | ||
645 | struct dev_mc_list *mclist) | ||
646 | { | ||
647 | struct ath_softc *sc = hw->priv; | ||
648 | |||
649 | changed_flags &= SUPPORTED_FILTERS; | ||
650 | *total_flags &= SUPPORTED_FILTERS; | ||
651 | |||
652 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | ||
653 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | ||
654 | ath_scan_start(sc); | ||
655 | else | ||
656 | ath_scan_end(sc); | ||
657 | } | ||
658 | } | ||
659 | |||
660 | static void ath9k_sta_notify(struct ieee80211_hw *hw, | ||
661 | struct ieee80211_vif *vif, | ||
662 | enum sta_notify_cmd cmd, | ||
663 | const u8 *addr) | ||
664 | { | ||
665 | struct ath_softc *sc = hw->priv; | ||
666 | struct ath_node *an; | ||
667 | unsigned long flags; | ||
668 | DECLARE_MAC_BUF(mac); | ||
669 | |||
670 | spin_lock_irqsave(&sc->node_lock, flags); | ||
671 | an = ath_node_find(sc, (u8 *) addr); | ||
672 | spin_unlock_irqrestore(&sc->node_lock, flags); | ||
673 | |||
674 | switch (cmd) { | ||
675 | case STA_NOTIFY_ADD: | ||
676 | spin_lock_irqsave(&sc->node_lock, flags); | ||
677 | if (!an) { | ||
678 | ath_node_attach(sc, (u8 *)addr, 0); | ||
679 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n", | ||
680 | __func__, | ||
681 | print_mac(mac, addr)); | ||
682 | } else { | ||
683 | ath_node_get(sc, (u8 *)addr); | ||
684 | } | ||
685 | spin_unlock_irqrestore(&sc->node_lock, flags); | ||
686 | break; | ||
687 | case STA_NOTIFY_REMOVE: | ||
688 | if (!an) | ||
689 | DPRINTF(sc, ATH_DBG_FATAL, | ||
690 | "%s: Removal of a non-existent node\n", | ||
691 | __func__); | ||
692 | else { | ||
693 | ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT); | ||
694 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n", | ||
695 | __func__, | ||
696 | print_mac(mac, addr)); | ||
697 | } | ||
698 | break; | ||
699 | default: | ||
700 | break; | ||
701 | } | ||
702 | } | ||
703 | |||
704 | static int ath9k_conf_tx(struct ieee80211_hw *hw, | ||
705 | u16 queue, | ||
706 | const struct ieee80211_tx_queue_params *params) | ||
707 | { | ||
708 | struct ath_softc *sc = hw->priv; | ||
709 | struct ath9k_tx_queue_info qi; | ||
710 | int ret = 0, qnum; | ||
711 | |||
712 | if (queue >= WME_NUM_AC) | ||
713 | return 0; | ||
714 | |||
715 | qi.tqi_aifs = params->aifs; | ||
716 | qi.tqi_cwmin = params->cw_min; | ||
717 | qi.tqi_cwmax = params->cw_max; | ||
718 | qi.tqi_burstTime = params->txop; | ||
719 | qnum = ath_get_hal_qnum(queue, sc); | ||
720 | |||
721 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
722 | "%s: Configure tx [queue/halq] [%d/%d], " | ||
723 | "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", | ||
724 | __func__, | ||
725 | queue, | ||
726 | qnum, | ||
727 | params->aifs, | ||
728 | params->cw_min, | ||
729 | params->cw_max, | ||
730 | params->txop); | ||
731 | |||
732 | ret = ath_txq_update(sc, qnum, &qi); | ||
733 | if (ret) | ||
734 | DPRINTF(sc, ATH_DBG_FATAL, | ||
735 | "%s: TXQ Update failed\n", __func__); | ||
736 | |||
737 | return ret; | ||
738 | } | ||
739 | |||
740 | static int ath9k_set_key(struct ieee80211_hw *hw, | ||
741 | enum set_key_cmd cmd, | ||
742 | const u8 *local_addr, | ||
743 | const u8 *addr, | ||
744 | struct ieee80211_key_conf *key) | ||
745 | { | ||
746 | struct ath_softc *sc = hw->priv; | ||
747 | int ret = 0; | ||
748 | |||
749 | DPRINTF(sc, ATH_DBG_KEYCACHE, " %s: Set HW Key\n", __func__); | ||
750 | |||
751 | switch (cmd) { | ||
752 | case SET_KEY: | ||
753 | ret = ath_key_config(sc, addr, key); | ||
754 | if (!ret) { | ||
755 | set_bit(key->keyidx, sc->sc_keymap); | ||
756 | key->hw_key_idx = key->keyidx; | ||
757 | /* push IV and Michael MIC generation to stack */ | ||
758 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
759 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
760 | } | ||
761 | break; | ||
762 | case DISABLE_KEY: | ||
763 | ath_key_delete(sc, key); | ||
764 | clear_bit(key->keyidx, sc->sc_keymap); | ||
765 | sc->sc_keytype = ATH9K_CIPHER_CLR; | ||
766 | break; | ||
767 | default: | ||
768 | ret = -EINVAL; | ||
769 | } | ||
770 | |||
771 | return ret; | ||
772 | } | ||
773 | |||
774 | static void ath9k_ht_conf(struct ath_softc *sc, | ||
775 | struct ieee80211_bss_conf *bss_conf) | ||
776 | { | ||
777 | #define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14) | ||
778 | struct ath_ht_info *ht_info = &sc->sc_ht_info; | ||
779 | |||
780 | if (bss_conf->assoc_ht) { | ||
781 | ht_info->ext_chan_offset = | ||
782 | bss_conf->ht_bss_conf->bss_cap & | ||
783 | IEEE80211_HT_IE_CHA_SEC_OFFSET; | ||
784 | |||
785 | if (!(bss_conf->ht_conf->cap & | ||
786 | IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | ||
787 | (bss_conf->ht_bss_conf->bss_cap & | ||
788 | IEEE80211_HT_IE_CHA_WIDTH)) | ||
789 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; | ||
790 | else | ||
791 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; | ||
792 | |||
793 | ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); | ||
794 | ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + | ||
795 | bss_conf->ht_conf->ampdu_factor); | ||
796 | ht_info->mpdudensity = | ||
797 | parse_mpdudensity(bss_conf->ht_conf->ampdu_density); | ||
798 | |||
799 | } | ||
800 | |||
801 | #undef IEEE80211_HT_CAP_40MHZ_INTOLERANT | ||
802 | } | ||
803 | |||
804 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | ||
805 | struct ieee80211_bss_conf *bss_conf) | ||
806 | { | ||
807 | struct ieee80211_hw *hw = sc->hw; | ||
808 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
809 | struct ath_vap *avp; | ||
810 | int pos; | ||
811 | DECLARE_MAC_BUF(mac); | ||
812 | |||
813 | if (bss_conf->assoc) { | ||
814 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n", | ||
815 | __func__, | ||
816 | bss_conf->aid); | ||
817 | |||
818 | avp = sc->sc_vaps[0]; | ||
819 | if (avp == NULL) { | ||
820 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", | ||
821 | __func__); | ||
822 | return; | ||
823 | } | ||
824 | |||
825 | /* New association, store aid */ | ||
826 | if (avp->av_opmode == ATH9K_M_STA) { | ||
827 | sc->sc_curaid = bss_conf->aid; | ||
828 | ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid, | ||
829 | sc->sc_curaid); | ||
830 | } | ||
831 | |||
832 | /* Configure the beacon */ | ||
833 | ath_beacon_config(sc, 0); | ||
834 | sc->sc_beacons = 1; | ||
835 | |||
836 | /* Reset rssi stats */ | ||
837 | sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; | ||
838 | sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; | ||
839 | sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; | ||
840 | sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; | ||
841 | |||
842 | /* Update chainmask */ | ||
843 | ath_update_chainmask(sc, bss_conf->assoc_ht); | ||
844 | |||
845 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
846 | "%s: bssid %s aid 0x%x\n", | ||
847 | __func__, | ||
848 | print_mac(mac, sc->sc_curbssid), sc->sc_curaid); | ||
849 | |||
850 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", | ||
851 | __func__, | ||
852 | curchan->center_freq); | ||
853 | |||
854 | pos = ath_get_channel(sc, curchan); | ||
855 | if (pos == -1) { | ||
856 | DPRINTF(sc, ATH_DBG_FATAL, | ||
857 | "%s: Invalid channel\n", __func__); | ||
858 | return; | ||
859 | } | ||
860 | |||
861 | if (hw->conf.ht_conf.ht_supported) | ||
862 | sc->sc_ah->ah_channels[pos].chanmode = | ||
863 | ath_get_extchanmode(sc, curchan); | ||
864 | else | ||
865 | sc->sc_ah->ah_channels[pos].chanmode = | ||
866 | (curchan->band == IEEE80211_BAND_2GHZ) ? | ||
867 | CHANNEL_G : CHANNEL_A; | ||
868 | |||
869 | /* set h/w channel */ | ||
870 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | ||
871 | DPRINTF(sc, ATH_DBG_FATAL, | ||
872 | "%s: Unable to set channel\n", | ||
873 | __func__); | ||
874 | |||
875 | ath_rate_newstate(sc, avp); | ||
876 | /* Update ratectrl about the new state */ | ||
877 | ath_rc_node_update(hw, avp->rc_node); | ||
878 | } else { | ||
879 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
880 | "%s: Bss Info DISSOC\n", __func__); | ||
881 | sc->sc_curaid = 0; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | ||
886 | struct ieee80211_vif *vif, | ||
887 | struct ieee80211_bss_conf *bss_conf, | ||
888 | u32 changed) | ||
889 | { | ||
890 | struct ath_softc *sc = hw->priv; | ||
891 | |||
892 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | ||
893 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed PREAMBLE %d\n", | ||
894 | __func__, | ||
895 | bss_conf->use_short_preamble); | ||
896 | if (bss_conf->use_short_preamble) | ||
897 | sc->sc_flags |= ATH_PREAMBLE_SHORT; | ||
898 | else | ||
899 | sc->sc_flags &= ~ATH_PREAMBLE_SHORT; | ||
900 | } | ||
901 | |||
902 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | ||
903 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed CTS PROT %d\n", | ||
904 | __func__, | ||
905 | bss_conf->use_cts_prot); | ||
906 | if (bss_conf->use_cts_prot && | ||
907 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) | ||
908 | sc->sc_flags |= ATH_PROTECT_ENABLE; | ||
909 | else | ||
910 | sc->sc_flags &= ~ATH_PROTECT_ENABLE; | ||
911 | } | ||
912 | |||
913 | if (changed & BSS_CHANGED_HT) { | ||
914 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n", | ||
915 | __func__, | ||
916 | bss_conf->assoc_ht); | ||
917 | ath9k_ht_conf(sc, bss_conf); | ||
918 | } | ||
919 | |||
920 | if (changed & BSS_CHANGED_ASSOC) { | ||
921 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n", | ||
922 | __func__, | ||
923 | bss_conf->assoc); | ||
924 | ath9k_bss_assoc_info(sc, bss_conf); | ||
925 | } | ||
926 | } | ||
927 | |||
928 | static u64 ath9k_get_tsf(struct ieee80211_hw *hw) | ||
929 | { | ||
930 | u64 tsf; | ||
931 | struct ath_softc *sc = hw->priv; | ||
932 | struct ath_hal *ah = sc->sc_ah; | ||
933 | |||
934 | tsf = ath9k_hw_gettsf64(ah); | ||
935 | |||
936 | return tsf; | ||
937 | } | ||
938 | |||
939 | static void ath9k_reset_tsf(struct ieee80211_hw *hw) | ||
940 | { | ||
941 | struct ath_softc *sc = hw->priv; | ||
942 | struct ath_hal *ah = sc->sc_ah; | ||
943 | |||
944 | ath9k_hw_reset_tsf(ah); | ||
945 | } | ||
946 | |||
947 | static int ath9k_ampdu_action(struct ieee80211_hw *hw, | ||
948 | enum ieee80211_ampdu_mlme_action action, | ||
949 | const u8 *addr, | ||
950 | u16 tid, | ||
951 | u16 *ssn) | ||
952 | { | ||
953 | struct ath_softc *sc = hw->priv; | ||
954 | int ret = 0; | ||
955 | |||
956 | switch (action) { | ||
957 | case IEEE80211_AMPDU_RX_START: | ||
958 | ret = ath_rx_aggr_start(sc, addr, tid, ssn); | ||
959 | if (ret < 0) | ||
960 | DPRINTF(sc, ATH_DBG_FATAL, | ||
961 | "%s: Unable to start RX aggregation\n", | ||
962 | __func__); | ||
963 | break; | ||
964 | case IEEE80211_AMPDU_RX_STOP: | ||
965 | ret = ath_rx_aggr_stop(sc, addr, tid); | ||
966 | if (ret < 0) | ||
967 | DPRINTF(sc, ATH_DBG_FATAL, | ||
968 | "%s: Unable to stop RX aggregation\n", | ||
969 | __func__); | ||
970 | break; | ||
971 | case IEEE80211_AMPDU_TX_START: | ||
972 | ret = ath_tx_aggr_start(sc, addr, tid, ssn); | ||
973 | if (ret < 0) | ||
974 | DPRINTF(sc, ATH_DBG_FATAL, | ||
975 | "%s: Unable to start TX aggregation\n", | ||
976 | __func__); | ||
977 | else | ||
978 | ieee80211_start_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid); | ||
979 | break; | ||
980 | case IEEE80211_AMPDU_TX_STOP: | ||
981 | ret = ath_tx_aggr_stop(sc, addr, tid); | ||
982 | if (ret < 0) | ||
983 | DPRINTF(sc, ATH_DBG_FATAL, | ||
984 | "%s: Unable to stop TX aggregation\n", | ||
985 | __func__); | ||
986 | |||
987 | ieee80211_stop_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid); | ||
988 | break; | ||
989 | default: | ||
990 | DPRINTF(sc, ATH_DBG_FATAL, | ||
991 | "%s: Unknown AMPDU action\n", __func__); | ||
992 | } | ||
993 | |||
994 | return ret; | ||
995 | } | ||
996 | |||
997 | static struct ieee80211_ops ath9k_ops = { | ||
998 | .tx = ath9k_tx, | ||
999 | .start = ath9k_start, | ||
1000 | .stop = ath9k_stop, | ||
1001 | .add_interface = ath9k_add_interface, | ||
1002 | .remove_interface = ath9k_remove_interface, | ||
1003 | .config = ath9k_config, | ||
1004 | .config_interface = ath9k_config_interface, | ||
1005 | .configure_filter = ath9k_configure_filter, | ||
1006 | .get_stats = NULL, | ||
1007 | .sta_notify = ath9k_sta_notify, | ||
1008 | .conf_tx = ath9k_conf_tx, | ||
1009 | .get_tx_stats = NULL, | ||
1010 | .bss_info_changed = ath9k_bss_info_changed, | ||
1011 | .set_tim = NULL, | ||
1012 | .set_key = ath9k_set_key, | ||
1013 | .hw_scan = NULL, | ||
1014 | .get_tkip_seq = NULL, | ||
1015 | .set_rts_threshold = NULL, | ||
1016 | .set_frag_threshold = NULL, | ||
1017 | .set_retry_limit = NULL, | ||
1018 | .get_tsf = ath9k_get_tsf, | ||
1019 | .reset_tsf = ath9k_reset_tsf, | ||
1020 | .tx_last_beacon = NULL, | ||
1021 | .ampdu_action = ath9k_ampdu_action | ||
1022 | }; | ||
1023 | |||
1024 | void ath_get_beaconconfig(struct ath_softc *sc, | ||
1025 | int if_id, | ||
1026 | struct ath_beacon_config *conf) | ||
1027 | { | ||
1028 | struct ieee80211_hw *hw = sc->hw; | ||
1029 | |||
1030 | /* fill in beacon config data */ | ||
1031 | |||
1032 | conf->beacon_interval = hw->conf.beacon_int; | ||
1033 | conf->listen_interval = 100; | ||
1034 | conf->dtim_count = 1; | ||
1035 | conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; | ||
1036 | } | ||
1037 | |||
1038 | int ath_update_beacon(struct ath_softc *sc, | ||
1039 | int if_id, | ||
1040 | struct ath_beacon_offset *bo, | ||
1041 | struct sk_buff *skb, | ||
1042 | int mcast) | ||
1043 | { | ||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | ||
1048 | struct ath_xmit_status *tx_status, struct ath_node *an) | ||
1049 | { | ||
1050 | struct ieee80211_hw *hw = sc->hw; | ||
1051 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1052 | |||
1053 | DPRINTF(sc, ATH_DBG_XMIT, | ||
1054 | "%s: TX complete: skb: %p\n", __func__, skb); | ||
1055 | |||
1056 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || | ||
1057 | tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | ||
1058 | /* free driver's private data area of tx_info */ | ||
1059 | if (tx_info->driver_data[0] != NULL) | ||
1060 | kfree(tx_info->driver_data[0]); | ||
1061 | tx_info->driver_data[0] = NULL; | ||
1062 | } | ||
1063 | |||
1064 | if (tx_status->flags & ATH_TX_BAR) { | ||
1065 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
1066 | tx_status->flags &= ~ATH_TX_BAR; | ||
1067 | } | ||
1068 | if (tx_status->flags) | ||
1069 | tx_info->status.excessive_retries = 1; | ||
1070 | |||
1071 | tx_info->status.retry_count = tx_status->retries; | ||
1072 | |||
1073 | ieee80211_tx_status(hw, skb); | ||
1074 | if (an) | ||
1075 | ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE); | ||
1076 | } | ||
1077 | |||
1078 | int ath__rx_indicate(struct ath_softc *sc, | ||
1079 | struct sk_buff *skb, | ||
1080 | struct ath_recv_status *status, | ||
1081 | u16 keyix) | ||
1082 | { | ||
1083 | struct ieee80211_hw *hw = sc->hw; | ||
1084 | struct ath_node *an = NULL; | ||
1085 | struct ieee80211_rx_status rx_status; | ||
1086 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1087 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
1088 | int padsize; | ||
1089 | enum ATH_RX_TYPE st; | ||
1090 | |||
1091 | /* see if any padding is done by the hw and remove it */ | ||
1092 | if (hdrlen & 3) { | ||
1093 | padsize = hdrlen % 4; | ||
1094 | memmove(skb->data + padsize, skb->data, hdrlen); | ||
1095 | skb_pull(skb, padsize); | ||
1096 | } | ||
1097 | |||
1098 | /* remove FCS before passing up to protocol stack */ | ||
1099 | skb_trim(skb, (skb->len - FCS_LEN)); | ||
1100 | |||
1101 | /* Prepare rx status */ | ||
1102 | ath9k_rx_prepare(sc, skb, status, &rx_status); | ||
1103 | |||
1104 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && | ||
1105 | !(status->flags & ATH_RX_DECRYPT_ERROR)) { | ||
1106 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
1107 | } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) | ||
1108 | && !(status->flags & ATH_RX_DECRYPT_ERROR) | ||
1109 | && skb->len >= hdrlen + 4) { | ||
1110 | keyix = skb->data[hdrlen + 3] >> 6; | ||
1111 | |||
1112 | if (test_bit(keyix, sc->sc_keymap)) | ||
1113 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
1114 | } | ||
1115 | |||
1116 | spin_lock_bh(&sc->node_lock); | ||
1117 | an = ath_node_find(sc, hdr->addr2); | ||
1118 | spin_unlock_bh(&sc->node_lock); | ||
1119 | |||
1120 | if (an) { | ||
1121 | ath_rx_input(sc, an, | ||
1122 | hw->conf.ht_conf.ht_supported, | ||
1123 | skb, status, &st); | ||
1124 | } | ||
1125 | if (!an || (st != ATH_RX_CONSUMED)) | ||
1126 | __ieee80211_rx(hw, skb, &rx_status); | ||
1127 | |||
1128 | return 0; | ||
1129 | } | ||
1130 | |||
1131 | int ath_rx_subframe(struct ath_node *an, | ||
1132 | struct sk_buff *skb, | ||
1133 | struct ath_recv_status *status) | ||
1134 | { | ||
1135 | struct ath_softc *sc = an->an_sc; | ||
1136 | struct ieee80211_hw *hw = sc->hw; | ||
1137 | struct ieee80211_rx_status rx_status; | ||
1138 | |||
1139 | /* Prepare rx status */ | ||
1140 | ath9k_rx_prepare(sc, skb, status, &rx_status); | ||
1141 | if (!(status->flags & ATH_RX_DECRYPT_ERROR)) | ||
1142 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
1143 | |||
1144 | __ieee80211_rx(hw, skb, &rx_status); | ||
1145 | |||
1146 | return 0; | ||
1147 | } | ||
1148 | |||
1149 | enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc) | ||
1150 | { | ||
1151 | return sc->sc_ht_info.tx_chan_width; | ||
1152 | } | ||
1153 | |||
1154 | static int ath_detach(struct ath_softc *sc) | ||
1155 | { | ||
1156 | struct ieee80211_hw *hw = sc->hw; | ||
1157 | |||
1158 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); | ||
1159 | |||
1160 | /* Unregister hw */ | ||
1161 | |||
1162 | ieee80211_unregister_hw(hw); | ||
1163 | |||
1164 | /* unregister Rate control */ | ||
1165 | ath_rate_control_unregister(); | ||
1166 | |||
1167 | /* tx/rx cleanup */ | ||
1168 | |||
1169 | ath_rx_cleanup(sc); | ||
1170 | ath_tx_cleanup(sc); | ||
1171 | |||
1172 | /* Deinit */ | ||
1173 | |||
1174 | ath_deinit(sc); | ||
1175 | |||
1176 | return 0; | ||
1177 | } | ||
1178 | |||
1179 | static int ath_attach(u16 devid, | ||
1180 | struct ath_softc *sc) | ||
1181 | { | ||
1182 | struct ieee80211_hw *hw = sc->hw; | ||
1183 | int error = 0; | ||
1184 | |||
1185 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__); | ||
1186 | |||
1187 | error = ath_init(devid, sc); | ||
1188 | if (error != 0) | ||
1189 | return error; | ||
1190 | |||
1191 | /* Init nodes */ | ||
1192 | |||
1193 | INIT_LIST_HEAD(&sc->node_list); | ||
1194 | spin_lock_init(&sc->node_lock); | ||
1195 | |||
1196 | /* get mac address from hardware and set in mac80211 */ | ||
1197 | |||
1198 | SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); | ||
1199 | |||
1200 | /* setup channels and rates */ | ||
1201 | |||
1202 | sc->sbands[IEEE80211_BAND_2GHZ].channels = | ||
1203 | sc->channels[IEEE80211_BAND_2GHZ]; | ||
1204 | sc->sbands[IEEE80211_BAND_2GHZ].bitrates = | ||
1205 | sc->rates[IEEE80211_BAND_2GHZ]; | ||
1206 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | ||
1207 | |||
1208 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) | ||
1209 | /* Setup HT capabilities for 2.4Ghz*/ | ||
1210 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info); | ||
1211 | |||
1212 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
1213 | &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
1214 | |||
1215 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { | ||
1216 | sc->sbands[IEEE80211_BAND_5GHZ].channels = | ||
1217 | sc->channels[IEEE80211_BAND_5GHZ]; | ||
1218 | sc->sbands[IEEE80211_BAND_5GHZ].bitrates = | ||
1219 | sc->rates[IEEE80211_BAND_5GHZ]; | ||
1220 | sc->sbands[IEEE80211_BAND_5GHZ].band = | ||
1221 | IEEE80211_BAND_5GHZ; | ||
1222 | |||
1223 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) | ||
1224 | /* Setup HT capabilities for 5Ghz*/ | ||
1225 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info); | ||
1226 | |||
1227 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
1228 | &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
1229 | } | ||
1230 | |||
1231 | /* FIXME: Have to figure out proper hw init values later */ | ||
1232 | |||
1233 | hw->queues = 4; | ||
1234 | hw->ampdu_queues = 1; | ||
1235 | |||
1236 | /* Register rate control */ | ||
1237 | hw->rate_control_algorithm = "ath9k_rate_control"; | ||
1238 | error = ath_rate_control_register(); | ||
1239 | if (error != 0) { | ||
1240 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1241 | "%s: Unable to register rate control " | ||
1242 | "algorithm:%d\n", __func__, error); | ||
1243 | ath_rate_control_unregister(); | ||
1244 | goto bad; | ||
1245 | } | ||
1246 | |||
1247 | error = ieee80211_register_hw(hw); | ||
1248 | if (error != 0) { | ||
1249 | ath_rate_control_unregister(); | ||
1250 | goto bad; | ||
1251 | } | ||
1252 | |||
1253 | /* initialize tx/rx engine */ | ||
1254 | |||
1255 | error = ath_tx_init(sc, ATH_TXBUF); | ||
1256 | if (error != 0) | ||
1257 | goto bad1; | ||
1258 | |||
1259 | error = ath_rx_init(sc, ATH_RXBUF); | ||
1260 | if (error != 0) | ||
1261 | goto bad1; | ||
1262 | |||
1263 | return 0; | ||
1264 | bad1: | ||
1265 | ath_detach(sc); | ||
1266 | bad: | ||
1267 | return error; | ||
1268 | } | ||
1269 | |||
1270 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
1271 | { | ||
1272 | void __iomem *mem; | ||
1273 | struct ath_softc *sc; | ||
1274 | struct ieee80211_hw *hw; | ||
1275 | const char *athname; | ||
1276 | u8 csz; | ||
1277 | u32 val; | ||
1278 | int ret = 0; | ||
1279 | |||
1280 | if (pci_enable_device(pdev)) | ||
1281 | return -EIO; | ||
1282 | |||
1283 | /* XXX 32-bit addressing only */ | ||
1284 | if (pci_set_dma_mask(pdev, 0xffffffff)) { | ||
1285 | printk(KERN_ERR "ath_pci: 32-bit DMA not available\n"); | ||
1286 | ret = -ENODEV; | ||
1287 | goto bad; | ||
1288 | } | ||
1289 | |||
1290 | /* | ||
1291 | * Cache line size is used to size and align various | ||
1292 | * structures used to communicate with the hardware. | ||
1293 | */ | ||
1294 | pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); | ||
1295 | if (csz == 0) { | ||
1296 | /* | ||
1297 | * Linux 2.4.18 (at least) writes the cache line size | ||
1298 | * register as a 16-bit wide register which is wrong. | ||
1299 | * We must have this setup properly for rx buffer | ||
1300 | * DMA to work so force a reasonable value here if it | ||
1301 | * comes up zero. | ||
1302 | */ | ||
1303 | csz = L1_CACHE_BYTES / sizeof(u32); | ||
1304 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | ||
1305 | } | ||
1306 | /* | ||
1307 | * The default setting of latency timer yields poor results, | ||
1308 | * set it to the value used by other systems. It may be worth | ||
1309 | * tweaking this setting more. | ||
1310 | */ | ||
1311 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); | ||
1312 | |||
1313 | pci_set_master(pdev); | ||
1314 | |||
1315 | /* | ||
1316 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
1317 | * PCI Tx retries from interfering with C3 CPU state. | ||
1318 | */ | ||
1319 | pci_read_config_dword(pdev, 0x40, &val); | ||
1320 | if ((val & 0x0000ff00) != 0) | ||
1321 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | ||
1322 | |||
1323 | ret = pci_request_region(pdev, 0, "ath9k"); | ||
1324 | if (ret) { | ||
1325 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); | ||
1326 | ret = -ENODEV; | ||
1327 | goto bad; | ||
1328 | } | ||
1329 | |||
1330 | mem = pci_iomap(pdev, 0, 0); | ||
1331 | if (!mem) { | ||
1332 | printk(KERN_ERR "PCI memory map error\n") ; | ||
1333 | ret = -EIO; | ||
1334 | goto bad1; | ||
1335 | } | ||
1336 | |||
1337 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); | ||
1338 | if (hw == NULL) { | ||
1339 | printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n"); | ||
1340 | goto bad2; | ||
1341 | } | ||
1342 | |||
1343 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
1344 | IEEE80211_HW_NOISE_DBM; | ||
1345 | |||
1346 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
1347 | pci_set_drvdata(pdev, hw); | ||
1348 | |||
1349 | sc = hw->priv; | ||
1350 | sc->hw = hw; | ||
1351 | sc->pdev = pdev; | ||
1352 | sc->mem = mem; | ||
1353 | |||
1354 | if (ath_attach(id->device, sc) != 0) { | ||
1355 | ret = -ENODEV; | ||
1356 | goto bad3; | ||
1357 | } | ||
1358 | |||
1359 | /* setup interrupt service routine */ | ||
1360 | |||
1361 | if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) { | ||
1362 | printk(KERN_ERR "%s: request_irq failed\n", | ||
1363 | wiphy_name(hw->wiphy)); | ||
1364 | ret = -EIO; | ||
1365 | goto bad4; | ||
1366 | } | ||
1367 | |||
1368 | athname = ath9k_hw_probe(id->vendor, id->device); | ||
1369 | |||
1370 | printk(KERN_INFO "%s: %s: mem=0x%lx, irq=%d\n", | ||
1371 | wiphy_name(hw->wiphy), | ||
1372 | athname ? athname : "Atheros ???", | ||
1373 | (unsigned long)mem, pdev->irq); | ||
1374 | |||
1375 | return 0; | ||
1376 | bad4: | ||
1377 | ath_detach(sc); | ||
1378 | bad3: | ||
1379 | ieee80211_free_hw(hw); | ||
1380 | bad2: | ||
1381 | pci_iounmap(pdev, mem); | ||
1382 | bad1: | ||
1383 | pci_release_region(pdev, 0); | ||
1384 | bad: | ||
1385 | pci_disable_device(pdev); | ||
1386 | return ret; | ||
1387 | } | ||
1388 | |||
1389 | static void ath_pci_remove(struct pci_dev *pdev) | ||
1390 | { | ||
1391 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
1392 | struct ath_softc *sc = hw->priv; | ||
1393 | |||
1394 | if (pdev->irq) | ||
1395 | free_irq(pdev->irq, sc); | ||
1396 | ath_detach(sc); | ||
1397 | pci_iounmap(pdev, sc->mem); | ||
1398 | pci_release_region(pdev, 0); | ||
1399 | pci_disable_device(pdev); | ||
1400 | ieee80211_free_hw(hw); | ||
1401 | } | ||
1402 | |||
1403 | #ifdef CONFIG_PM | ||
1404 | |||
1405 | static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1406 | { | ||
1407 | pci_save_state(pdev); | ||
1408 | pci_disable_device(pdev); | ||
1409 | pci_set_power_state(pdev, 3); | ||
1410 | |||
1411 | return 0; | ||
1412 | } | ||
1413 | |||
1414 | static int ath_pci_resume(struct pci_dev *pdev) | ||
1415 | { | ||
1416 | u32 val; | ||
1417 | int err; | ||
1418 | |||
1419 | err = pci_enable_device(pdev); | ||
1420 | if (err) | ||
1421 | return err; | ||
1422 | pci_restore_state(pdev); | ||
1423 | /* | ||
1424 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
1425 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
1426 | * PCI Tx retries from interfering with C3 CPU state | ||
1427 | */ | ||
1428 | pci_read_config_dword(pdev, 0x40, &val); | ||
1429 | if ((val & 0x0000ff00) != 0) | ||
1430 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | ||
1431 | |||
1432 | return 0; | ||
1433 | } | ||
1434 | |||
1435 | #endif /* CONFIG_PM */ | ||
1436 | |||
1437 | MODULE_DEVICE_TABLE(pci, ath_pci_id_table); | ||
1438 | |||
1439 | static struct pci_driver ath_pci_driver = { | ||
1440 | .name = "ath9k", | ||
1441 | .id_table = ath_pci_id_table, | ||
1442 | .probe = ath_pci_probe, | ||
1443 | .remove = ath_pci_remove, | ||
1444 | #ifdef CONFIG_PM | ||
1445 | .suspend = ath_pci_suspend, | ||
1446 | .resume = ath_pci_resume, | ||
1447 | #endif /* CONFIG_PM */ | ||
1448 | }; | ||
1449 | |||
1450 | static int __init init_ath_pci(void) | ||
1451 | { | ||
1452 | printk(KERN_INFO "%s: %s\n", dev_info, ATH_PCI_VERSION); | ||
1453 | |||
1454 | if (pci_register_driver(&ath_pci_driver) < 0) { | ||
1455 | printk(KERN_ERR | ||
1456 | "ath_pci: No devices found, driver not installed.\n"); | ||
1457 | pci_unregister_driver(&ath_pci_driver); | ||
1458 | return -ENODEV; | ||
1459 | } | ||
1460 | |||
1461 | return 0; | ||
1462 | } | ||
1463 | module_init(init_ath_pci); | ||
1464 | |||
1465 | static void __exit exit_ath_pci(void) | ||
1466 | { | ||
1467 | pci_unregister_driver(&ath_pci_driver); | ||
1468 | printk(KERN_INFO "%s: driver unloaded\n", dev_info); | ||
1469 | } | ||
1470 | 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 000000000000..eb9121fdfd38 --- /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 000000000000..0cd399a5344a --- /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 000000000000..73c460ad355f --- /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[ATH9K_MODE_11B] = &ar5416_11b_ratetable; | ||
488 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable; | ||
489 | sc->hw_rate_table[ATH9K_MODE_11G] = &ar5416_11g_ratetable; | ||
490 | |||
491 | sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable; | ||
492 | sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable; | ||
493 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] = | ||
494 | &ar5416_11na_ratetable; | ||
495 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] = | ||
496 | &ar5416_11na_ratetable; | ||
497 | sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] = | ||
498 | &ar5416_11ng_ratetable; | ||
499 | sc->hw_rate_table[ATH9K_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[ATH9K_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[ATH9K_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[ATH9K_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.tx_triglevel_max; | ||
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 == ATH9K_MODE_11NG_HT20) || | ||
1127 | (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) || | ||
1128 | (sc->sc_curmode == ATH9K_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 000000000000..71aef9c75232 --- /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[ATH9K_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 000000000000..2fe806175c01 --- /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.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | ||
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.hw_caps & ATH9K_HW_CAP_HT) { | ||
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 000000000000..42b0890a4685 --- /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 000000000000..62e28887ccd3 --- /dev/null +++ b/drivers/net/wireless/ath9k/regd.c | |||
@@ -0,0 +1,1026 @@ | |||
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.reg_cap; | ||
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 void | ||
135 | ath9k_regd_get_wmodes_nreg(struct ath_hal *ah, | ||
136 | struct country_code_to_enum_rd *country, | ||
137 | struct regDomain *rd5GHz, | ||
138 | unsigned long *modes_allowed) | ||
139 | { | ||
140 | bitmap_copy(modes_allowed, ah->ah_caps.wireless_modes, ATH9K_MODE_MAX); | ||
141 | |||
142 | if (test_bit(ATH9K_MODE_11G, ah->ah_caps.wireless_modes) && | ||
143 | (!country->allow11g)) | ||
144 | clear_bit(ATH9K_MODE_11G, modes_allowed); | ||
145 | |||
146 | if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes) && | ||
147 | (ath9k_regd_is_chan_bm_zero(rd5GHz->chan11a))) | ||
148 | clear_bit(ATH9K_MODE_11A, modes_allowed); | ||
149 | |||
150 | if (test_bit(ATH9K_MODE_11NG_HT20, ah->ah_caps.wireless_modes) | ||
151 | && (!country->allow11ng20)) | ||
152 | clear_bit(ATH9K_MODE_11NG_HT20, modes_allowed); | ||
153 | |||
154 | if (test_bit(ATH9K_MODE_11NA_HT20, ah->ah_caps.wireless_modes) | ||
155 | && (!country->allow11na20)) | ||
156 | clear_bit(ATH9K_MODE_11NA_HT20, modes_allowed); | ||
157 | |||
158 | if (test_bit(ATH9K_MODE_11NG_HT40PLUS, ah->ah_caps.wireless_modes) && | ||
159 | (!country->allow11ng40)) | ||
160 | clear_bit(ATH9K_MODE_11NG_HT40PLUS, modes_allowed); | ||
161 | |||
162 | if (test_bit(ATH9K_MODE_11NG_HT40MINUS, ah->ah_caps.wireless_modes) && | ||
163 | (!country->allow11ng40)) | ||
164 | clear_bit(ATH9K_MODE_11NG_HT40MINUS, modes_allowed); | ||
165 | |||
166 | if (test_bit(ATH9K_MODE_11NA_HT40PLUS, ah->ah_caps.wireless_modes) && | ||
167 | (!country->allow11na40)) | ||
168 | clear_bit(ATH9K_MODE_11NA_HT40PLUS, modes_allowed); | ||
169 | |||
170 | if (test_bit(ATH9K_MODE_11NA_HT40MINUS, ah->ah_caps.wireless_modes) && | ||
171 | (!country->allow11na40)) | ||
172 | clear_bit(ATH9K_MODE_11NA_HT40MINUS, modes_allowed); | ||
173 | } | ||
174 | |||
175 | bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah) | ||
176 | { | ||
177 | u16 rd; | ||
178 | |||
179 | rd = ath9k_regd_get_eepromRD(ah); | ||
180 | |||
181 | switch (rd) { | ||
182 | case FCC4_FCCA: | ||
183 | case (CTRY_UNITED_STATES_FCC49 | COUNTRY_ERD_FLAG): | ||
184 | return true; | ||
185 | case DEBUG_REG_DMN: | ||
186 | case NO_ENUMRD: | ||
187 | if (ah->ah_countryCode == CTRY_UNITED_STATES_FCC49) | ||
188 | return true; | ||
189 | break; | ||
190 | } | ||
191 | return false; | ||
192 | } | ||
193 | |||
194 | static struct country_code_to_enum_rd* | ||
195 | ath9k_regd_find_country(u16 countryCode) | ||
196 | { | ||
197 | int i; | ||
198 | |||
199 | for (i = 0; i < ARRAY_SIZE(allCountries); i++) { | ||
200 | if (allCountries[i].countryCode == countryCode) | ||
201 | return &allCountries[i]; | ||
202 | } | ||
203 | return NULL; | ||
204 | } | ||
205 | |||
206 | static u16 ath9k_regd_get_default_country(struct ath_hal *ah) | ||
207 | { | ||
208 | u16 rd; | ||
209 | int i; | ||
210 | |||
211 | rd = ath9k_regd_get_eepromRD(ah); | ||
212 | if (rd & COUNTRY_ERD_FLAG) { | ||
213 | struct country_code_to_enum_rd *country = NULL; | ||
214 | u16 cc = rd & ~COUNTRY_ERD_FLAG; | ||
215 | |||
216 | country = ath9k_regd_find_country(cc); | ||
217 | if (country != NULL) | ||
218 | return cc; | ||
219 | } | ||
220 | |||
221 | for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) | ||
222 | if (regDomainPairs[i].regDmnEnum == rd) { | ||
223 | if (regDomainPairs[i].singleCC != 0) | ||
224 | return regDomainPairs[i].singleCC; | ||
225 | else | ||
226 | i = ARRAY_SIZE(regDomainPairs); | ||
227 | } | ||
228 | return CTRY_DEFAULT; | ||
229 | } | ||
230 | |||
231 | static bool ath9k_regd_is_valid_reg_domain(int regDmn, | ||
232 | struct regDomain *rd) | ||
233 | { | ||
234 | int i; | ||
235 | |||
236 | for (i = 0; i < ARRAY_SIZE(regDomains); i++) { | ||
237 | if (regDomains[i].regDmnEnum == regDmn) { | ||
238 | if (rd != NULL) { | ||
239 | memcpy(rd, ®Domains[i], | ||
240 | sizeof(struct regDomain)); | ||
241 | } | ||
242 | return true; | ||
243 | } | ||
244 | } | ||
245 | return false; | ||
246 | } | ||
247 | |||
248 | static bool ath9k_regd_is_valid_reg_domainPair(int regDmnPair) | ||
249 | { | ||
250 | int i; | ||
251 | |||
252 | if (regDmnPair == NO_ENUMRD) | ||
253 | return false; | ||
254 | for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { | ||
255 | if (regDomainPairs[i].regDmnEnum == regDmnPair) | ||
256 | return true; | ||
257 | } | ||
258 | return false; | ||
259 | } | ||
260 | |||
261 | static bool | ||
262 | ath9k_regd_get_wmode_regdomain(struct ath_hal *ah, int regDmn, | ||
263 | u16 channelFlag, struct regDomain *rd) | ||
264 | { | ||
265 | int i, found; | ||
266 | u64 flags = NO_REQ; | ||
267 | struct reg_dmn_pair_mapping *regPair = NULL; | ||
268 | int regOrg; | ||
269 | |||
270 | regOrg = regDmn; | ||
271 | if (regDmn == CTRY_DEFAULT) { | ||
272 | u16 rdnum; | ||
273 | rdnum = ath9k_regd_get_eepromRD(ah); | ||
274 | |||
275 | if (!(rdnum & COUNTRY_ERD_FLAG)) { | ||
276 | if (ath9k_regd_is_valid_reg_domain(rdnum, NULL) || | ||
277 | ath9k_regd_is_valid_reg_domainPair(rdnum)) { | ||
278 | regDmn = rdnum; | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | if ((regDmn & MULTI_DOMAIN_MASK) == 0) { | ||
284 | for (i = 0, found = 0; | ||
285 | (i < ARRAY_SIZE(regDomainPairs)) && (!found); i++) { | ||
286 | if (regDomainPairs[i].regDmnEnum == regDmn) { | ||
287 | regPair = ®DomainPairs[i]; | ||
288 | found = 1; | ||
289 | } | ||
290 | } | ||
291 | if (!found) { | ||
292 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
293 | "%s: Failed to find reg domain pair %u\n", | ||
294 | __func__, regDmn); | ||
295 | return false; | ||
296 | } | ||
297 | if (!(channelFlag & CHANNEL_2GHZ)) { | ||
298 | regDmn = regPair->regDmn5GHz; | ||
299 | flags = regPair->flags5GHz; | ||
300 | } | ||
301 | if (channelFlag & CHANNEL_2GHZ) { | ||
302 | regDmn = regPair->regDmn2GHz; | ||
303 | flags = regPair->flags2GHz; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | found = ath9k_regd_is_valid_reg_domain(regDmn, rd); | ||
308 | if (!found) { | ||
309 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
310 | "%s: Failed to find unitary reg domain %u\n", | ||
311 | __func__, regDmn); | ||
312 | return false; | ||
313 | } else { | ||
314 | rd->pscan &= regPair->pscanMask; | ||
315 | if (((regOrg & MULTI_DOMAIN_MASK) == 0) && | ||
316 | (flags != NO_REQ)) { | ||
317 | rd->flags = flags; | ||
318 | } | ||
319 | |||
320 | rd->flags &= (channelFlag & CHANNEL_2GHZ) ? | ||
321 | REG_DOMAIN_2GHZ_MASK : REG_DOMAIN_5GHZ_MASK; | ||
322 | return true; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | static bool ath9k_regd_is_bit_set(int bit, u64 *bitmask) | ||
327 | { | ||
328 | int byteOffset, bitnum; | ||
329 | u64 val; | ||
330 | |||
331 | byteOffset = bit / 64; | ||
332 | bitnum = bit - byteOffset * 64; | ||
333 | val = ((u64) 1) << bitnum; | ||
334 | if (bitmask[byteOffset] & val) | ||
335 | return true; | ||
336 | else | ||
337 | return false; | ||
338 | } | ||
339 | |||
340 | static void | ||
341 | ath9k_regd_add_reg_classid(u8 *regclassids, u32 maxregids, | ||
342 | u32 *nregids, u8 regclassid) | ||
343 | { | ||
344 | int i; | ||
345 | |||
346 | if (regclassid == 0) | ||
347 | return; | ||
348 | |||
349 | for (i = 0; i < maxregids; i++) { | ||
350 | if (regclassids[i] == regclassid) | ||
351 | return; | ||
352 | if (regclassids[i] == 0) | ||
353 | break; | ||
354 | } | ||
355 | |||
356 | if (i == maxregids) | ||
357 | return; | ||
358 | else { | ||
359 | regclassids[i] = regclassid; | ||
360 | *nregids += 1; | ||
361 | } | ||
362 | |||
363 | return; | ||
364 | } | ||
365 | |||
366 | static bool | ||
367 | ath9k_regd_get_eeprom_reg_ext_bits(struct ath_hal *ah, | ||
368 | enum reg_ext_bitmap bit) | ||
369 | { | ||
370 | return (ah->ah_currentRDExt & (1 << bit)) ? true : false; | ||
371 | } | ||
372 | |||
373 | #ifdef ATH_NF_PER_CHAN | ||
374 | |||
375 | static void ath9k_regd_init_rf_buffer(struct ath9k_channel *ichans, | ||
376 | int nchans) | ||
377 | { | ||
378 | int i, j, next; | ||
379 | |||
380 | for (next = 0; next < nchans; next++) { | ||
381 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
382 | ichans[next].nfCalHist[i].currIndex = 0; | ||
383 | ichans[next].nfCalHist[i].privNF = | ||
384 | AR_PHY_CCA_MAX_GOOD_VALUE; | ||
385 | ichans[next].nfCalHist[i].invalidNFcount = | ||
386 | AR_PHY_CCA_FILTERWINDOW_LENGTH; | ||
387 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { | ||
388 | ichans[next].nfCalHist[i].nfCalBuffer[j] = | ||
389 | AR_PHY_CCA_MAX_GOOD_VALUE; | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | #endif | ||
395 | |||
396 | static int ath9k_regd_is_chan_present(struct ath_hal *ah, | ||
397 | u16 c) | ||
398 | { | ||
399 | int i; | ||
400 | |||
401 | for (i = 0; i < 150; i++) { | ||
402 | if (!ah->ah_channels[i].channel) | ||
403 | return -1; | ||
404 | else if (ah->ah_channels[i].channel == c) | ||
405 | return i; | ||
406 | } | ||
407 | |||
408 | return -1; | ||
409 | } | ||
410 | |||
411 | static bool | ||
412 | ath9k_regd_add_channel(struct ath_hal *ah, | ||
413 | u16 c, | ||
414 | u16 c_lo, | ||
415 | u16 c_hi, | ||
416 | u16 maxChan, | ||
417 | u8 ctl, | ||
418 | int pos, | ||
419 | struct regDomain rd5GHz, | ||
420 | struct RegDmnFreqBand *fband, | ||
421 | struct regDomain *rd, | ||
422 | const struct cmode *cm, | ||
423 | struct ath9k_channel *ichans, | ||
424 | bool enableExtendedChannels) | ||
425 | { | ||
426 | struct ath9k_channel *chan; | ||
427 | int ret; | ||
428 | u32 channelFlags = 0; | ||
429 | u8 privFlags = 0; | ||
430 | |||
431 | if (!(c_lo <= c && c <= c_hi)) { | ||
432 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
433 | "%s: c %u out of range [%u..%u]\n", | ||
434 | __func__, c, c_lo, c_hi); | ||
435 | return false; | ||
436 | } | ||
437 | if ((fband->channelBW == CHANNEL_HALF_BW) && | ||
438 | !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_HALFRATE)) { | ||
439 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
440 | "%s: Skipping %u half rate channel\n", | ||
441 | __func__, c); | ||
442 | return false; | ||
443 | } | ||
444 | |||
445 | if ((fband->channelBW == CHANNEL_QUARTER_BW) && | ||
446 | !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_QUARTERRATE)) { | ||
447 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
448 | "%s: Skipping %u quarter rate channel\n", | ||
449 | __func__, c); | ||
450 | return false; | ||
451 | } | ||
452 | |||
453 | if (((c + fband->channelSep) / 2) > (maxChan + HALF_MAXCHANBW)) { | ||
454 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
455 | "%s: c %u > maxChan %u\n", | ||
456 | __func__, c, maxChan); | ||
457 | return false; | ||
458 | } | ||
459 | |||
460 | if ((fband->usePassScan & IS_ECM_CHAN) && !enableExtendedChannels) { | ||
461 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
462 | "Skipping ecm channel\n"); | ||
463 | return false; | ||
464 | } | ||
465 | |||
466 | if ((rd->flags & NO_HOSTAP) && (ah->ah_opmode == ATH9K_M_HOSTAP)) { | ||
467 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
468 | "Skipping HOSTAP channel\n"); | ||
469 | return false; | ||
470 | } | ||
471 | |||
472 | if (IS_HT40_MODE(cm->mode) && | ||
473 | !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_FCC_DFS_HT40)) && | ||
474 | (fband->useDfs) && | ||
475 | (rd->conformanceTestLimit != MKK)) { | ||
476 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
477 | "Skipping HT40 channel (en_fcc_dfs_ht40 = 0)\n"); | ||
478 | return false; | ||
479 | } | ||
480 | |||
481 | if (IS_HT40_MODE(cm->mode) && | ||
482 | !(ath9k_regd_get_eeprom_reg_ext_bits(ah, | ||
483 | REG_EXT_JAPAN_NONDFS_HT40)) && | ||
484 | !(fband->useDfs) && (rd->conformanceTestLimit == MKK)) { | ||
485 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
486 | "Skipping HT40 channel (en_jap_ht40 = 0)\n"); | ||
487 | return false; | ||
488 | } | ||
489 | |||
490 | if (IS_HT40_MODE(cm->mode) && | ||
491 | !(ath9k_regd_get_eeprom_reg_ext_bits(ah, REG_EXT_JAPAN_DFS_HT40)) && | ||
492 | (fband->useDfs) && | ||
493 | (rd->conformanceTestLimit == MKK)) { | ||
494 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
495 | "Skipping HT40 channel (en_jap_dfs_ht40 = 0)\n"); | ||
496 | return false; | ||
497 | } | ||
498 | |||
499 | /* Calculate channel flags */ | ||
500 | |||
501 | channelFlags = cm->flags; | ||
502 | |||
503 | switch (fband->channelBW) { | ||
504 | case CHANNEL_HALF_BW: | ||
505 | channelFlags |= CHANNEL_HALF; | ||
506 | break; | ||
507 | case CHANNEL_QUARTER_BW: | ||
508 | channelFlags |= CHANNEL_QUARTER; | ||
509 | break; | ||
510 | } | ||
511 | |||
512 | if (fband->usePassScan & rd->pscan) | ||
513 | channelFlags |= CHANNEL_PASSIVE; | ||
514 | else | ||
515 | channelFlags &= ~CHANNEL_PASSIVE; | ||
516 | if (fband->useDfs & rd->dfsMask) | ||
517 | privFlags = CHANNEL_DFS; | ||
518 | else | ||
519 | privFlags = 0; | ||
520 | if (rd->flags & LIMIT_FRAME_4MS) | ||
521 | privFlags |= CHANNEL_4MS_LIMIT; | ||
522 | if (privFlags & CHANNEL_DFS) | ||
523 | privFlags |= CHANNEL_DISALLOW_ADHOC; | ||
524 | if (rd->flags & ADHOC_PER_11D) | ||
525 | privFlags |= CHANNEL_PER_11D_ADHOC; | ||
526 | |||
527 | if (channelFlags & CHANNEL_PASSIVE) { | ||
528 | if ((c < 2412) || (c > 2462)) { | ||
529 | if (rd5GHz.regDmnEnum == MKK1 || | ||
530 | rd5GHz.regDmnEnum == MKK2) { | ||
531 | u32 regcap = ah->ah_caps.reg_cap; | ||
532 | if (!(regcap & | ||
533 | (AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | | ||
534 | AR_EEPROM_EEREGCAP_EN_KK_U2 | | ||
535 | AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) && | ||
536 | isUNII1OddChan(c)) { | ||
537 | channelFlags &= ~CHANNEL_PASSIVE; | ||
538 | } else { | ||
539 | privFlags |= CHANNEL_DISALLOW_ADHOC; | ||
540 | } | ||
541 | } else { | ||
542 | privFlags |= CHANNEL_DISALLOW_ADHOC; | ||
543 | } | ||
544 | } | ||
545 | } | ||
546 | |||
547 | if ((cm->mode == ATH9K_MODE_11A) || | ||
548 | (cm->mode == ATH9K_MODE_11NA_HT20) || | ||
549 | (cm->mode == ATH9K_MODE_11NA_HT40PLUS) || | ||
550 | (cm->mode == ATH9K_MODE_11NA_HT40MINUS)) { | ||
551 | if (rd->flags & (ADHOC_NO_11A | DISALLOW_ADHOC_11A)) | ||
552 | privFlags |= CHANNEL_DISALLOW_ADHOC; | ||
553 | } | ||
554 | |||
555 | /* Fill in channel details */ | ||
556 | |||
557 | ret = ath9k_regd_is_chan_present(ah, c); | ||
558 | if (ret == -1) { | ||
559 | chan = &ah->ah_channels[pos]; | ||
560 | chan->channel = c; | ||
561 | chan->maxRegTxPower = fband->powerDfs; | ||
562 | chan->antennaMax = fband->antennaMax; | ||
563 | chan->regDmnFlags = rd->flags; | ||
564 | chan->maxTxPower = AR5416_MAX_RATE_POWER; | ||
565 | chan->minTxPower = AR5416_MAX_RATE_POWER; | ||
566 | chan->channelFlags = channelFlags; | ||
567 | chan->privFlags = privFlags; | ||
568 | } else { | ||
569 | chan = &ah->ah_channels[ret]; | ||
570 | chan->channelFlags |= channelFlags; | ||
571 | chan->privFlags |= privFlags; | ||
572 | } | ||
573 | |||
574 | /* Set CTLs */ | ||
575 | |||
576 | if ((cm->flags & CHANNEL_ALL) == CHANNEL_A) | ||
577 | chan->conformanceTestLimit[0] = ctl; | ||
578 | else if ((cm->flags & CHANNEL_ALL) == CHANNEL_B) | ||
579 | chan->conformanceTestLimit[1] = ctl; | ||
580 | else if ((cm->flags & CHANNEL_ALL) == CHANNEL_G) | ||
581 | chan->conformanceTestLimit[2] = ctl; | ||
582 | |||
583 | return (ret == -1) ? true : false; | ||
584 | } | ||
585 | |||
586 | static bool ath9k_regd_japan_check(struct ath_hal *ah, | ||
587 | int b, | ||
588 | struct regDomain *rd5GHz) | ||
589 | { | ||
590 | bool skipband = false; | ||
591 | int i; | ||
592 | u32 regcap; | ||
593 | |||
594 | for (i = 0; i < ARRAY_SIZE(j_bandcheck); i++) { | ||
595 | if (j_bandcheck[i].freqbandbit == b) { | ||
596 | regcap = ah->ah_caps.reg_cap; | ||
597 | if ((j_bandcheck[i].eepromflagtocheck & regcap) == 0) { | ||
598 | skipband = true; | ||
599 | } else if ((regcap & AR_EEPROM_EEREGCAP_EN_KK_U2) || | ||
600 | (regcap & AR_EEPROM_EEREGCAP_EN_KK_MIDBAND)) { | ||
601 | rd5GHz->dfsMask |= DFS_MKK4; | ||
602 | rd5GHz->pscan |= PSCAN_MKK3; | ||
603 | } | ||
604 | break; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
609 | "%s: Skipping %d freq band\n", | ||
610 | __func__, j_bandcheck[i].freqbandbit); | ||
611 | |||
612 | return skipband; | ||
613 | } | ||
614 | |||
615 | bool | ||
616 | ath9k_regd_init_channels(struct ath_hal *ah, | ||
617 | u32 maxchans, | ||
618 | u32 *nchans, u8 *regclassids, | ||
619 | u32 maxregids, u32 *nregids, u16 cc, | ||
620 | bool enableOutdoor, | ||
621 | bool enableExtendedChannels) | ||
622 | { | ||
623 | u16 maxChan = 7000; | ||
624 | struct country_code_to_enum_rd *country = NULL; | ||
625 | struct regDomain rd5GHz, rd2GHz; | ||
626 | const struct cmode *cm; | ||
627 | struct ath9k_channel *ichans = &ah->ah_channels[0]; | ||
628 | int next = 0, b; | ||
629 | u8 ctl; | ||
630 | int regdmn; | ||
631 | u16 chanSep; | ||
632 | unsigned long *modes_avail; | ||
633 | DECLARE_BITMAP(modes_allowed, ATH9K_MODE_MAX); | ||
634 | |||
635 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: cc %u %s %s\n", | ||
636 | __func__, cc, | ||
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 | modes_avail = ah->ah_caps.wireless_modes; | ||
730 | } else { | ||
731 | ath9k_regd_get_wmodes_nreg(ah, country, &rd5GHz, modes_allowed); | ||
732 | modes_avail = modes_allowed; | ||
733 | |||
734 | if (!enableOutdoor) | ||
735 | maxChan = country->outdoorChanStart; | ||
736 | } | ||
737 | |||
738 | next = 0; | ||
739 | |||
740 | if (maxchans > ARRAY_SIZE(ah->ah_channels)) | ||
741 | maxchans = ARRAY_SIZE(ah->ah_channels); | ||
742 | |||
743 | for (cm = modes; cm < &modes[ARRAY_SIZE(modes)]; cm++) { | ||
744 | u16 c, c_hi, c_lo; | ||
745 | u64 *channelBM = NULL; | ||
746 | struct regDomain *rd = NULL; | ||
747 | struct RegDmnFreqBand *fband = NULL, *freqs; | ||
748 | int8_t low_adj = 0, hi_adj = 0; | ||
749 | |||
750 | if (!test_bit(cm->mode, modes_avail)) { | ||
751 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
752 | "%s: !avail mode %d flags 0x%x\n", | ||
753 | __func__, cm->mode, cm->flags); | ||
754 | continue; | ||
755 | } | ||
756 | if (!ath9k_get_channel_edges(ah, cm->flags, &c_lo, &c_hi)) { | ||
757 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
758 | "%s: channels 0x%x not supported " | ||
759 | "by hardware\n", | ||
760 | __func__, cm->flags); | ||
761 | continue; | ||
762 | } | ||
763 | |||
764 | switch (cm->mode) { | ||
765 | case ATH9K_MODE_11A: | ||
766 | case ATH9K_MODE_11NA_HT20: | ||
767 | case ATH9K_MODE_11NA_HT40PLUS: | ||
768 | case ATH9K_MODE_11NA_HT40MINUS: | ||
769 | rd = &rd5GHz; | ||
770 | channelBM = rd->chan11a; | ||
771 | freqs = ®Dmn5GhzFreq[0]; | ||
772 | ctl = rd->conformanceTestLimit; | ||
773 | break; | ||
774 | case ATH9K_MODE_11B: | ||
775 | rd = &rd2GHz; | ||
776 | channelBM = rd->chan11b; | ||
777 | freqs = ®Dmn2GhzFreq[0]; | ||
778 | ctl = rd->conformanceTestLimit | CTL_11B; | ||
779 | break; | ||
780 | case ATH9K_MODE_11G: | ||
781 | case ATH9K_MODE_11NG_HT20: | ||
782 | case ATH9K_MODE_11NG_HT40PLUS: | ||
783 | case ATH9K_MODE_11NG_HT40MINUS: | ||
784 | rd = &rd2GHz; | ||
785 | channelBM = rd->chan11g; | ||
786 | freqs = ®Dmn2Ghz11gFreq[0]; | ||
787 | ctl = rd->conformanceTestLimit | CTL_11G; | ||
788 | break; | ||
789 | default: | ||
790 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
791 | "%s: Unknown HAL mode 0x%x\n", __func__, | ||
792 | cm->mode); | ||
793 | continue; | ||
794 | } | ||
795 | |||
796 | if (ath9k_regd_is_chan_bm_zero(channelBM)) | ||
797 | continue; | ||
798 | |||
799 | if ((cm->mode == ATH9K_MODE_11NA_HT40PLUS) || | ||
800 | (cm->mode == ATH9K_MODE_11NG_HT40PLUS)) { | ||
801 | hi_adj = -20; | ||
802 | } | ||
803 | |||
804 | if ((cm->mode == ATH9K_MODE_11NA_HT40MINUS) || | ||
805 | (cm->mode == ATH9K_MODE_11NG_HT40MINUS)) { | ||
806 | low_adj = 20; | ||
807 | } | ||
808 | |||
809 | /* XXX: Add a helper here instead */ | ||
810 | for (b = 0; b < 64 * BMLEN; b++) { | ||
811 | if (ath9k_regd_is_bit_set(b, channelBM)) { | ||
812 | fband = &freqs[b]; | ||
813 | if (rd5GHz.regDmnEnum == MKK1 | ||
814 | || rd5GHz.regDmnEnum == MKK2) { | ||
815 | if (ath9k_regd_japan_check(ah, | ||
816 | b, | ||
817 | &rd5GHz)) | ||
818 | continue; | ||
819 | } | ||
820 | |||
821 | ath9k_regd_add_reg_classid(regclassids, | ||
822 | maxregids, | ||
823 | nregids, | ||
824 | fband-> | ||
825 | regClassId); | ||
826 | |||
827 | if (IS_HT40_MODE(cm->mode) && (rd == &rd5GHz)) { | ||
828 | chanSep = 40; | ||
829 | if (fband->lowChannel == 5280) | ||
830 | low_adj += 20; | ||
831 | |||
832 | if (fband->lowChannel == 5170) | ||
833 | continue; | ||
834 | } else | ||
835 | chanSep = fband->channelSep; | ||
836 | |||
837 | for (c = fband->lowChannel + low_adj; | ||
838 | ((c <= (fband->highChannel + hi_adj)) && | ||
839 | (c >= (fband->lowChannel + low_adj))); | ||
840 | c += chanSep) { | ||
841 | if (next >= maxchans) { | ||
842 | DPRINTF(ah->ah_sc, | ||
843 | ATH_DBG_REGULATORY, | ||
844 | "%s: too many channels " | ||
845 | "for channel table\n", | ||
846 | __func__); | ||
847 | goto done; | ||
848 | } | ||
849 | if (ath9k_regd_add_channel(ah, | ||
850 | c, c_lo, c_hi, | ||
851 | maxChan, ctl, | ||
852 | next, | ||
853 | rd5GHz, | ||
854 | fband, rd, cm, | ||
855 | ichans, | ||
856 | enableExtendedChannels)) | ||
857 | next++; | ||
858 | } | ||
859 | if (IS_HT40_MODE(cm->mode) && | ||
860 | (fband->lowChannel == 5280)) { | ||
861 | low_adj -= 20; | ||
862 | } | ||
863 | } | ||
864 | } | ||
865 | } | ||
866 | done: | ||
867 | if (next != 0) { | ||
868 | int i; | ||
869 | |||
870 | if (next > ARRAY_SIZE(ah->ah_channels)) { | ||
871 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
872 | "%s: too many channels %u; truncating to %u\n", | ||
873 | __func__, next, | ||
874 | (int) ARRAY_SIZE(ah->ah_channels)); | ||
875 | next = ARRAY_SIZE(ah->ah_channels); | ||
876 | } | ||
877 | #ifdef ATH_NF_PER_CHAN | ||
878 | ath9k_regd_init_rf_buffer(ichans, next); | ||
879 | #endif | ||
880 | ath9k_regd_sort(ichans, next, | ||
881 | sizeof(struct ath9k_channel), | ||
882 | ath9k_regd_chansort); | ||
883 | |||
884 | ah->ah_nchan = next; | ||
885 | |||
886 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "Channel list:\n"); | ||
887 | for (i = 0; i < next; i++) { | ||
888 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
889 | "chan: %d flags: 0x%x\n", | ||
890 | ah->ah_channels[i].channel, | ||
891 | ah->ah_channels[i].channelFlags); | ||
892 | } | ||
893 | } | ||
894 | *nchans = next; | ||
895 | |||
896 | ah->ah_countryCode = ah->ah_countryCode; | ||
897 | |||
898 | ah->ah_currentRDInUse = regdmn; | ||
899 | ah->ah_currentRD5G = rd5GHz.regDmnEnum; | ||
900 | ah->ah_currentRD2G = rd2GHz.regDmnEnum; | ||
901 | if (country == NULL) { | ||
902 | ah->ah_iso[0] = 0; | ||
903 | ah->ah_iso[1] = 0; | ||
904 | } else { | ||
905 | ah->ah_iso[0] = country->isoName[0]; | ||
906 | ah->ah_iso[1] = country->isoName[1]; | ||
907 | } | ||
908 | |||
909 | return next != 0; | ||
910 | } | ||
911 | |||
912 | struct ath9k_channel* | ||
913 | ath9k_regd_check_channel(struct ath_hal *ah, | ||
914 | const struct ath9k_channel *c) | ||
915 | { | ||
916 | struct ath9k_channel *base, *cc; | ||
917 | |||
918 | int flags = c->channelFlags & CHAN_FLAGS; | ||
919 | int n, lim; | ||
920 | |||
921 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
922 | "%s: channel %u/0x%x (0x%x) requested\n", __func__, | ||
923 | c->channel, c->channelFlags, flags); | ||
924 | |||
925 | cc = ah->ah_curchan; | ||
926 | if (cc != NULL && cc->channel == c->channel && | ||
927 | (cc->channelFlags & CHAN_FLAGS) == flags) { | ||
928 | if ((cc->privFlags & CHANNEL_INTERFERENCE) && | ||
929 | (cc->privFlags & CHANNEL_DFS)) | ||
930 | return NULL; | ||
931 | else | ||
932 | return cc; | ||
933 | } | ||
934 | |||
935 | base = ah->ah_channels; | ||
936 | n = ah->ah_nchan; | ||
937 | |||
938 | for (lim = n; lim != 0; lim >>= 1) { | ||
939 | int d; | ||
940 | cc = &base[lim >> 1]; | ||
941 | d = c->channel - cc->channel; | ||
942 | if (d == 0) { | ||
943 | if ((cc->channelFlags & CHAN_FLAGS) == flags) { | ||
944 | if ((cc->privFlags & CHANNEL_INTERFERENCE) && | ||
945 | (cc->privFlags & CHANNEL_DFS)) | ||
946 | return NULL; | ||
947 | else | ||
948 | return cc; | ||
949 | } | ||
950 | d = flags - (cc->channelFlags & CHAN_FLAGS); | ||
951 | } | ||
952 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | ||
953 | "%s: channel %u/0x%x d %d\n", __func__, | ||
954 | cc->channel, cc->channelFlags, d); | ||
955 | if (d > 0) { | ||
956 | base = cc + 1; | ||
957 | lim--; | ||
958 | } | ||
959 | } | ||
960 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: no match for %u/0x%x\n", | ||
961 | __func__, c->channel, c->channelFlags); | ||
962 | return NULL; | ||
963 | } | ||
964 | |||
965 | u32 | ||
966 | ath9k_regd_get_antenna_allowed(struct ath_hal *ah, | ||
967 | struct ath9k_channel *chan) | ||
968 | { | ||
969 | struct ath9k_channel *ichan = NULL; | ||
970 | |||
971 | ichan = ath9k_regd_check_channel(ah, chan); | ||
972 | if (!ichan) | ||
973 | return 0; | ||
974 | |||
975 | return ichan->antennaMax; | ||
976 | } | ||
977 | |||
978 | u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan) | ||
979 | { | ||
980 | u32 ctl = NO_CTL; | ||
981 | struct ath9k_channel *ichan; | ||
982 | |||
983 | if (ah->ah_countryCode == CTRY_DEFAULT && isWwrSKU(ah)) { | ||
984 | if (IS_CHAN_B(chan)) | ||
985 | ctl = SD_NO_CTL | CTL_11B; | ||
986 | else if (IS_CHAN_G(chan)) | ||
987 | ctl = SD_NO_CTL | CTL_11G; | ||
988 | else | ||
989 | ctl = SD_NO_CTL | CTL_11A; | ||
990 | } else { | ||
991 | ichan = ath9k_regd_check_channel(ah, chan); | ||
992 | if (ichan != NULL) { | ||
993 | /* FIXME */ | ||
994 | if (IS_CHAN_A(ichan)) | ||
995 | ctl = ichan->conformanceTestLimit[0]; | ||
996 | else if (IS_CHAN_B(ichan)) | ||
997 | ctl = ichan->conformanceTestLimit[1]; | ||
998 | else if (IS_CHAN_G(ichan)) | ||
999 | ctl = ichan->conformanceTestLimit[2]; | ||
1000 | |||
1001 | if (IS_CHAN_G(chan) && (ctl & 0xf) == CTL_11B) | ||
1002 | ctl = (ctl & ~0xf) | CTL_11G; | ||
1003 | } | ||
1004 | } | ||
1005 | return ctl; | ||
1006 | } | ||
1007 | |||
1008 | void ath9k_regd_get_current_country(struct ath_hal *ah, | ||
1009 | struct ath9k_country_entry *ctry) | ||
1010 | { | ||
1011 | u16 rd = ath9k_regd_get_eepromRD(ah); | ||
1012 | |||
1013 | ctry->isMultidomain = false; | ||
1014 | if (rd == CTRY_DEFAULT) | ||
1015 | ctry->isMultidomain = true; | ||
1016 | else if (!(rd & COUNTRY_ERD_FLAG)) | ||
1017 | ctry->isMultidomain = isWwrSKU(ah); | ||
1018 | |||
1019 | ctry->countryCode = ah->ah_countryCode; | ||
1020 | ctry->regDmnEnum = ah->ah_currentRD; | ||
1021 | ctry->regDmn5G = ah->ah_currentRD5G; | ||
1022 | ctry->regDmn2G = ah->ah_currentRD2G; | ||
1023 | ctry->iso[0] = ah->ah_iso[0]; | ||
1024 | ctry->iso[1] = ah->ah_iso[1]; | ||
1025 | ctry->iso[2] = ah->ah_iso[2]; | ||
1026 | } | ||
diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h new file mode 100644 index 000000000000..0ecd344fbd98 --- /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_11NA_HT40PLUS || \ | ||
122 | _mode == ATH9K_MODE_11NG_HT40PLUS || \ | ||
123 | _mode == ATH9K_MODE_11NA_HT40MINUS || \ | ||
124 | _mode == ATH9K_MODE_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 000000000000..9112c030b1e8 --- /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_11A, CHANNEL_A}, | ||
1897 | {ATH9K_MODE_11B, CHANNEL_B}, | ||
1898 | {ATH9K_MODE_11G, CHANNEL_G}, | ||
1899 | {ATH9K_MODE_11NG_HT20, CHANNEL_G_HT20}, | ||
1900 | {ATH9K_MODE_11NG_HT40PLUS, CHANNEL_G_HT40PLUS}, | ||
1901 | {ATH9K_MODE_11NG_HT40MINUS, CHANNEL_G_HT40MINUS}, | ||
1902 | {ATH9K_MODE_11NA_HT20, CHANNEL_A_HT20}, | ||
1903 | {ATH9K_MODE_11NA_HT40PLUS, CHANNEL_A_HT40PLUS}, | ||
1904 | {ATH9K_MODE_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 000000000000..157f830ee6b8 --- /dev/null +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -0,0 +1,2871 @@ | |||
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 = 0; | ||
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.hw_caps & ATH9K_HW_CAP_HT) && 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.hw_caps & ATH9K_HW_CAP_HT)) { | ||
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_tx_queue_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_physCompBuf = 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, | ||
2341 | struct ath9k_tx_queue_info *qinfo) | ||
2342 | { | ||
2343 | struct ath_hal *ah = sc->sc_ah; | ||
2344 | int error = 0; | ||
2345 | struct ath9k_tx_queue_info qi; | ||
2346 | |||
2347 | if (qnum == sc->sc_bhalq) { | ||
2348 | /* | ||
2349 | * XXX: for beacon queue, we just save the parameter. | ||
2350 | * It will be picked up by ath_beaconq_config when | ||
2351 | * it's necessary. | ||
2352 | */ | ||
2353 | sc->sc_beacon_qi = *qinfo; | ||
2354 | return 0; | ||
2355 | } | ||
2356 | |||
2357 | ASSERT(sc->sc_txq[qnum].axq_qnum == qnum); | ||
2358 | |||
2359 | ath9k_hw_get_txq_props(ah, qnum, &qi); | ||
2360 | qi.tqi_aifs = qinfo->tqi_aifs; | ||
2361 | qi.tqi_cwmin = qinfo->tqi_cwmin; | ||
2362 | qi.tqi_cwmax = qinfo->tqi_cwmax; | ||
2363 | qi.tqi_burstTime = qinfo->tqi_burstTime; | ||
2364 | qi.tqi_readyTime = qinfo->tqi_readyTime; | ||
2365 | |||
2366 | if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { | ||
2367 | DPRINTF(sc, ATH_DBG_FATAL, | ||
2368 | "%s: unable to update hardware queue %u!\n", | ||
2369 | __func__, qnum); | ||
2370 | error = -EIO; | ||
2371 | } else { | ||
2372 | ath9k_hw_resettxqueue(ah, qnum); /* push to h/w */ | ||
2373 | } | ||
2374 | |||
2375 | return error; | ||
2376 | } | ||
2377 | |||
2378 | int ath_cabq_update(struct ath_softc *sc) | ||
2379 | { | ||
2380 | struct ath9k_tx_queue_info qi; | ||
2381 | int qnum = sc->sc_cabq->axq_qnum; | ||
2382 | struct ath_beacon_config conf; | ||
2383 | |||
2384 | ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); | ||
2385 | /* | ||
2386 | * Ensure the readytime % is within the bounds. | ||
2387 | */ | ||
2388 | if (sc->sc_config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) | ||
2389 | sc->sc_config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; | ||
2390 | else if (sc->sc_config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) | ||
2391 | sc->sc_config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; | ||
2392 | |||
2393 | ath_get_beaconconfig(sc, ATH_IF_ID_ANY, &conf); | ||
2394 | qi.tqi_readyTime = | ||
2395 | (conf.beacon_interval * sc->sc_config.cabqReadytime) / 100; | ||
2396 | ath_txq_update(sc, qnum, &qi); | ||
2397 | |||
2398 | return 0; | ||
2399 | } | ||
2400 | |||
2401 | int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb) | ||
2402 | { | ||
2403 | struct ath_tx_control txctl; | ||
2404 | int error = 0; | ||
2405 | |||
2406 | error = ath_tx_prepare(sc, skb, &txctl); | ||
2407 | if (error == 0) | ||
2408 | /* | ||
2409 | * Start DMA mapping. | ||
2410 | * ath_tx_start_dma() will be called either synchronously | ||
2411 | * or asynchrounsly once DMA is complete. | ||
2412 | */ | ||
2413 | xmit_map_sg(sc, skb, | ||
2414 | get_dma_mem_context(&txctl, dmacontext), | ||
2415 | &txctl); | ||
2416 | else | ||
2417 | ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE); | ||
2418 | |||
2419 | /* failed packets will be dropped by the caller */ | ||
2420 | return error; | ||
2421 | } | ||
2422 | |||
2423 | /* Deferred processing of transmit interrupt */ | ||
2424 | |||
2425 | void ath_tx_tasklet(struct ath_softc *sc) | ||
2426 | { | ||
2427 | u64 tsf = ath9k_hw_gettsf64(sc->sc_ah); | ||
2428 | int i, nacked = 0; | ||
2429 | u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); | ||
2430 | |||
2431 | ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); | ||
2432 | |||
2433 | /* | ||
2434 | * Process each active queue. | ||
2435 | */ | ||
2436 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
2437 | if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) | ||
2438 | nacked += ath_tx_processq(sc, &sc->sc_txq[i]); | ||
2439 | } | ||
2440 | if (nacked) | ||
2441 | sc->sc_lastrx = tsf; | ||
2442 | } | ||
2443 | |||
2444 | void ath_tx_draintxq(struct ath_softc *sc, | ||
2445 | struct ath_txq *txq, bool retry_tx) | ||
2446 | { | ||
2447 | struct ath_buf *bf, *lastbf; | ||
2448 | struct list_head bf_head; | ||
2449 | |||
2450 | INIT_LIST_HEAD(&bf_head); | ||
2451 | |||
2452 | /* | ||
2453 | * NB: this assumes output has been stopped and | ||
2454 | * we do not need to block ath_tx_tasklet | ||
2455 | */ | ||
2456 | for (;;) { | ||
2457 | spin_lock_bh(&txq->axq_lock); | ||
2458 | |||
2459 | if (list_empty(&txq->axq_q)) { | ||
2460 | txq->axq_link = NULL; | ||
2461 | txq->axq_linkbuf = NULL; | ||
2462 | spin_unlock_bh(&txq->axq_lock); | ||
2463 | break; | ||
2464 | } | ||
2465 | |||
2466 | bf = list_first_entry(&txq->axq_q, struct ath_buf, list); | ||
2467 | |||
2468 | if (bf->bf_status & ATH_BUFSTATUS_STALE) { | ||
2469 | list_del(&bf->list); | ||
2470 | spin_unlock_bh(&txq->axq_lock); | ||
2471 | |||
2472 | spin_lock_bh(&sc->sc_txbuflock); | ||
2473 | list_add_tail(&bf->list, &sc->sc_txbuf); | ||
2474 | spin_unlock_bh(&sc->sc_txbuflock); | ||
2475 | continue; | ||
2476 | } | ||
2477 | |||
2478 | lastbf = bf->bf_lastbf; | ||
2479 | if (!retry_tx) | ||
2480 | lastbf->bf_desc->ds_txstat.ts_flags = | ||
2481 | ATH9K_TX_SW_ABORTED; | ||
2482 | |||
2483 | /* remove ath_buf's of the same mpdu from txq */ | ||
2484 | list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); | ||
2485 | txq->axq_depth--; | ||
2486 | |||
2487 | spin_unlock_bh(&txq->axq_lock); | ||
2488 | |||
2489 | if (bf->bf_isampdu) | ||
2490 | ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0); | ||
2491 | else | ||
2492 | ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); | ||
2493 | } | ||
2494 | |||
2495 | /* flush any pending frames if aggregation is enabled */ | ||
2496 | if (sc->sc_txaggr) { | ||
2497 | if (!retry_tx) { | ||
2498 | spin_lock_bh(&txq->axq_lock); | ||
2499 | ath_txq_drain_pending_buffers(sc, txq, | ||
2500 | ATH9K_BH_STATUS_CHANGE); | ||
2501 | spin_unlock_bh(&txq->axq_lock); | ||
2502 | } | ||
2503 | } | ||
2504 | } | ||
2505 | |||
2506 | /* Drain the transmit queues and reclaim resources */ | ||
2507 | |||
2508 | void ath_draintxq(struct ath_softc *sc, bool retry_tx) | ||
2509 | { | ||
2510 | /* stop beacon queue. The beacon will be freed when | ||
2511 | * we go to INIT state */ | ||
2512 | if (!sc->sc_invalid) { | ||
2513 | (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); | ||
2514 | DPRINTF(sc, ATH_DBG_XMIT, "%s: beacon queue %x\n", __func__, | ||
2515 | ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq)); | ||
2516 | } | ||
2517 | |||
2518 | ath_drain_txdataq(sc, retry_tx); | ||
2519 | } | ||
2520 | |||
2521 | u32 ath_txq_depth(struct ath_softc *sc, int qnum) | ||
2522 | { | ||
2523 | return sc->sc_txq[qnum].axq_depth; | ||
2524 | } | ||
2525 | |||
2526 | u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum) | ||
2527 | { | ||
2528 | return sc->sc_txq[qnum].axq_aggr_depth; | ||
2529 | } | ||
2530 | |||
2531 | /* Check if an ADDBA is required. A valid node must be passed. */ | ||
2532 | enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc, | ||
2533 | struct ath_node *an, | ||
2534 | u8 tidno) | ||
2535 | { | ||
2536 | struct ath_atx_tid *txtid; | ||
2537 | DECLARE_MAC_BUF(mac); | ||
2538 | |||
2539 | if (!sc->sc_txaggr) | ||
2540 | return AGGR_NOT_REQUIRED; | ||
2541 | |||
2542 | /* ADDBA exchange must be completed before sending aggregates */ | ||
2543 | txtid = ATH_AN_2_TID(an, tidno); | ||
2544 | |||
2545 | if (txtid->addba_exchangecomplete) | ||
2546 | return AGGR_EXCHANGE_DONE; | ||
2547 | |||
2548 | if (txtid->cleanup_inprogress) | ||
2549 | return AGGR_CLEANUP_PROGRESS; | ||
2550 | |||
2551 | if (txtid->addba_exchangeinprogress) | ||
2552 | return AGGR_EXCHANGE_PROGRESS; | ||
2553 | |||
2554 | if (!txtid->addba_exchangecomplete) { | ||
2555 | if (!txtid->addba_exchangeinprogress && | ||
2556 | (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) { | ||
2557 | txtid->addba_exchangeattempts++; | ||
2558 | return AGGR_REQUIRED; | ||
2559 | } | ||
2560 | } | ||
2561 | |||
2562 | return AGGR_NOT_REQUIRED; | ||
2563 | } | ||
2564 | |||
2565 | /* Start TX aggregation */ | ||
2566 | |||
2567 | int ath_tx_aggr_start(struct ath_softc *sc, | ||
2568 | const u8 *addr, | ||
2569 | u16 tid, | ||
2570 | u16 *ssn) | ||
2571 | { | ||
2572 | struct ath_atx_tid *txtid; | ||
2573 | struct ath_node *an; | ||
2574 | |||
2575 | spin_lock_bh(&sc->node_lock); | ||
2576 | an = ath_node_find(sc, (u8 *) addr); | ||
2577 | spin_unlock_bh(&sc->node_lock); | ||
2578 | |||
2579 | if (!an) { | ||
2580 | DPRINTF(sc, ATH_DBG_AGGR, | ||
2581 | "%s: Node not found to initialize " | ||
2582 | "TX aggregation\n", __func__); | ||
2583 | return -1; | ||
2584 | } | ||
2585 | |||
2586 | if (sc->sc_txaggr) { | ||
2587 | txtid = ATH_AN_2_TID(an, tid); | ||
2588 | txtid->addba_exchangeinprogress = 1; | ||
2589 | ath_tx_pause_tid(sc, txtid); | ||
2590 | } | ||
2591 | |||
2592 | return 0; | ||
2593 | } | ||
2594 | |||
2595 | /* Stop tx aggregation */ | ||
2596 | |||
2597 | int ath_tx_aggr_stop(struct ath_softc *sc, | ||
2598 | const u8 *addr, | ||
2599 | u16 tid) | ||
2600 | { | ||
2601 | struct ath_node *an; | ||
2602 | |||
2603 | spin_lock_bh(&sc->node_lock); | ||
2604 | an = ath_node_find(sc, (u8 *) addr); | ||
2605 | spin_unlock_bh(&sc->node_lock); | ||
2606 | |||
2607 | if (!an) { | ||
2608 | DPRINTF(sc, ATH_DBG_AGGR, | ||
2609 | "%s: TX aggr stop for non-existent node\n", __func__); | ||
2610 | return -1; | ||
2611 | } | ||
2612 | |||
2613 | ath_tx_aggr_teardown(sc, an, tid); | ||
2614 | return 0; | ||
2615 | } | ||
2616 | |||
2617 | /* | ||
2618 | * Performs transmit side cleanup when TID changes from aggregated to | ||
2619 | * unaggregated. | ||
2620 | * - Pause the TID and mark cleanup in progress | ||
2621 | * - Discard all retry frames from the s/w queue. | ||
2622 | */ | ||
2623 | |||
2624 | void ath_tx_aggr_teardown(struct ath_softc *sc, | ||
2625 | struct ath_node *an, u8 tid) | ||
2626 | { | ||
2627 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); | ||
2628 | struct ath_txq *txq = &sc->sc_txq[txtid->ac->qnum]; | ||
2629 | struct ath_buf *bf; | ||
2630 | struct list_head bf_head; | ||
2631 | INIT_LIST_HEAD(&bf_head); | ||
2632 | |||
2633 | DPRINTF(sc, ATH_DBG_AGGR, "%s: teardown TX aggregation\n", __func__); | ||
2634 | |||
2635 | if (txtid->cleanup_inprogress) /* cleanup is in progress */ | ||
2636 | return; | ||
2637 | |||
2638 | if (!txtid->addba_exchangecomplete) { | ||
2639 | txtid->addba_exchangeattempts = 0; | ||
2640 | return; | ||
2641 | } | ||
2642 | |||
2643 | /* TID must be paused first */ | ||
2644 | ath_tx_pause_tid(sc, txtid); | ||
2645 | |||
2646 | /* drop all software retried frames and mark this TID */ | ||
2647 | spin_lock_bh(&txq->axq_lock); | ||
2648 | while (!list_empty(&txtid->buf_q)) { | ||
2649 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); | ||
2650 | if (!bf->bf_isretried) { | ||
2651 | /* | ||
2652 | * NB: it's based on the assumption that | ||
2653 | * software retried frame will always stay | ||
2654 | * at the head of software queue. | ||
2655 | */ | ||
2656 | break; | ||
2657 | } | ||
2658 | list_cut_position(&bf_head, | ||
2659 | &txtid->buf_q, &bf->bf_lastfrm->list); | ||
2660 | ath_tx_update_baw(sc, txtid, bf->bf_seqno); | ||
2661 | |||
2662 | /* complete this sub-frame */ | ||
2663 | ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); | ||
2664 | } | ||
2665 | |||
2666 | if (txtid->baw_head != txtid->baw_tail) { | ||
2667 | spin_unlock_bh(&txq->axq_lock); | ||
2668 | txtid->cleanup_inprogress = true; | ||
2669 | } else { | ||
2670 | txtid->addba_exchangecomplete = 0; | ||
2671 | txtid->addba_exchangeattempts = 0; | ||
2672 | spin_unlock_bh(&txq->axq_lock); | ||
2673 | ath_tx_flush_tid(sc, txtid); | ||
2674 | } | ||
2675 | } | ||
2676 | |||
2677 | /* | ||
2678 | * Tx scheduling logic | ||
2679 | * NB: must be called with txq lock held | ||
2680 | */ | ||
2681 | |||
2682 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | ||
2683 | { | ||
2684 | struct ath_atx_ac *ac; | ||
2685 | struct ath_atx_tid *tid; | ||
2686 | |||
2687 | /* nothing to schedule */ | ||
2688 | if (list_empty(&txq->axq_acq)) | ||
2689 | return; | ||
2690 | /* | ||
2691 | * get the first node/ac pair on the queue | ||
2692 | */ | ||
2693 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); | ||
2694 | list_del(&ac->list); | ||
2695 | ac->sched = false; | ||
2696 | |||
2697 | /* | ||
2698 | * process a single tid per destination | ||
2699 | */ | ||
2700 | do { | ||
2701 | /* nothing to schedule */ | ||
2702 | if (list_empty(&ac->tid_q)) | ||
2703 | return; | ||
2704 | |||
2705 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list); | ||
2706 | list_del(&tid->list); | ||
2707 | tid->sched = false; | ||
2708 | |||
2709 | if (tid->paused) /* check next tid to keep h/w busy */ | ||
2710 | continue; | ||
2711 | |||
2712 | if (!(tid->an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) || | ||
2713 | ((txq->axq_depth % 2) == 0)) { | ||
2714 | ath_tx_sched_aggr(sc, txq, tid); | ||
2715 | } | ||
2716 | |||
2717 | /* | ||
2718 | * add tid to round-robin queue if more frames | ||
2719 | * are pending for the tid | ||
2720 | */ | ||
2721 | if (!list_empty(&tid->buf_q)) | ||
2722 | ath_tx_queue_tid(txq, tid); | ||
2723 | |||
2724 | /* only schedule one TID at a time */ | ||
2725 | break; | ||
2726 | } while (!list_empty(&ac->tid_q)); | ||
2727 | |||
2728 | /* | ||
2729 | * schedule AC if more TIDs need processing | ||
2730 | */ | ||
2731 | if (!list_empty(&ac->tid_q)) { | ||
2732 | /* | ||
2733 | * add dest ac to txq if not already added | ||
2734 | */ | ||
2735 | if (!ac->sched) { | ||
2736 | ac->sched = true; | ||
2737 | list_add_tail(&ac->list, &txq->axq_acq); | ||
2738 | } | ||
2739 | } | ||
2740 | } | ||
2741 | |||
2742 | /* Initialize per-node transmit state */ | ||
2743 | |||
2744 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | ||
2745 | { | ||
2746 | if (sc->sc_txaggr) { | ||
2747 | struct ath_atx_tid *tid; | ||
2748 | struct ath_atx_ac *ac; | ||
2749 | int tidno, acno; | ||
2750 | |||
2751 | sc->sc_ht_info.maxampdu = ATH_AMPDU_LIMIT_DEFAULT; | ||
2752 | |||
2753 | /* | ||
2754 | * Init per tid tx state | ||
2755 | */ | ||
2756 | for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno]; | ||
2757 | tidno < WME_NUM_TID; | ||
2758 | tidno++, tid++) { | ||
2759 | tid->an = an; | ||
2760 | tid->tidno = tidno; | ||
2761 | tid->seq_start = tid->seq_next = 0; | ||
2762 | tid->baw_size = WME_MAX_BA; | ||
2763 | tid->baw_head = tid->baw_tail = 0; | ||
2764 | tid->sched = false; | ||
2765 | tid->paused = false; | ||
2766 | tid->cleanup_inprogress = false; | ||
2767 | INIT_LIST_HEAD(&tid->buf_q); | ||
2768 | |||
2769 | acno = TID_TO_WME_AC(tidno); | ||
2770 | tid->ac = &an->an_aggr.tx.ac[acno]; | ||
2771 | |||
2772 | /* ADDBA state */ | ||
2773 | tid->addba_exchangecomplete = 0; | ||
2774 | tid->addba_exchangeinprogress = 0; | ||
2775 | tid->addba_exchangeattempts = 0; | ||
2776 | } | ||
2777 | |||
2778 | /* | ||
2779 | * Init per ac tx state | ||
2780 | */ | ||
2781 | for (acno = 0, ac = &an->an_aggr.tx.ac[acno]; | ||
2782 | acno < WME_NUM_AC; acno++, ac++) { | ||
2783 | ac->sched = false; | ||
2784 | INIT_LIST_HEAD(&ac->tid_q); | ||
2785 | |||
2786 | switch (acno) { | ||
2787 | case WME_AC_BE: | ||
2788 | ac->qnum = ath_tx_get_qnum(sc, | ||
2789 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
2790 | break; | ||
2791 | case WME_AC_BK: | ||
2792 | ac->qnum = ath_tx_get_qnum(sc, | ||
2793 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK); | ||
2794 | break; | ||
2795 | case WME_AC_VI: | ||
2796 | ac->qnum = ath_tx_get_qnum(sc, | ||
2797 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI); | ||
2798 | break; | ||
2799 | case WME_AC_VO: | ||
2800 | ac->qnum = ath_tx_get_qnum(sc, | ||
2801 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO); | ||
2802 | break; | ||
2803 | } | ||
2804 | } | ||
2805 | } | ||
2806 | } | ||
2807 | |||
2808 | /* Cleanupthe pending buffers for the node. */ | ||
2809 | |||
2810 | void ath_tx_node_cleanup(struct ath_softc *sc, | ||
2811 | struct ath_node *an, bool bh_flag) | ||
2812 | { | ||
2813 | int i; | ||
2814 | struct ath_atx_ac *ac, *ac_tmp; | ||
2815 | struct ath_atx_tid *tid, *tid_tmp; | ||
2816 | struct ath_txq *txq; | ||
2817 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
2818 | if (ATH_TXQ_SETUP(sc, i)) { | ||
2819 | txq = &sc->sc_txq[i]; | ||
2820 | |||
2821 | if (likely(bh_flag)) | ||
2822 | spin_lock_bh(&txq->axq_lock); | ||
2823 | else | ||
2824 | spin_lock(&txq->axq_lock); | ||
2825 | |||
2826 | list_for_each_entry_safe(ac, | ||
2827 | ac_tmp, &txq->axq_acq, list) { | ||
2828 | tid = list_first_entry(&ac->tid_q, | ||
2829 | struct ath_atx_tid, list); | ||
2830 | if (tid && tid->an != an) | ||
2831 | continue; | ||
2832 | list_del(&ac->list); | ||
2833 | ac->sched = false; | ||
2834 | |||
2835 | list_for_each_entry_safe(tid, | ||
2836 | tid_tmp, &ac->tid_q, list) { | ||
2837 | list_del(&tid->list); | ||
2838 | tid->sched = false; | ||
2839 | ath_tid_drain(sc, txq, tid, bh_flag); | ||
2840 | tid->addba_exchangecomplete = 0; | ||
2841 | tid->addba_exchangeattempts = 0; | ||
2842 | tid->cleanup_inprogress = false; | ||
2843 | } | ||
2844 | } | ||
2845 | |||
2846 | if (likely(bh_flag)) | ||
2847 | spin_unlock_bh(&txq->axq_lock); | ||
2848 | else | ||
2849 | spin_unlock(&txq->axq_lock); | ||
2850 | } | ||
2851 | } | ||
2852 | } | ||
2853 | |||
2854 | /* Cleanup per node transmit state */ | ||
2855 | |||
2856 | void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an) | ||
2857 | { | ||
2858 | if (sc->sc_txaggr) { | ||
2859 | struct ath_atx_tid *tid; | ||
2860 | int tidno, i; | ||
2861 | |||
2862 | /* Init per tid rx state */ | ||
2863 | for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno]; | ||
2864 | tidno < WME_NUM_TID; | ||
2865 | tidno++, tid++) { | ||
2866 | |||
2867 | for (i = 0; i < ATH_TID_MAX_BUFS; i++) | ||
2868 | ASSERT(tid->tx_buf[i] == NULL); | ||
2869 | } | ||
2870 | } | ||
2871 | } | ||